Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Dictionary Referencing
#1
Hi all,

I'm writing a pretty rudimentary code that essentially plays chess with itself. Dictionaries are the data types used to contain all of the data about each individual piece. I have only programmed the movement of pawns this far. I've been using functions for most of the content but I'm having an issue with one of the functions referencing a dictionary. I'm trying to reference an input from the function using an if statement, but the function simply skips over it and executes the else statement. Attached below is the chess code and subsequent UDF code. The code below is the function causing issues.

P.S. I am interested in hearing any good advice on optimizing the code as it is.

Thanks.

def pawn(board,color,which):
    if color == white:
        nr = -1
        spot = 'W_pawn'
    else:
        nr = 1
        spot = 'B_pawn'
        
    # empty current pos
    board[color['Pawns']['Pawn %s' %(which)]['Row'],color['Pawns']['Pawn %s' %(which)]['Column']] = ''
    
    # edit row value in dictionary
    color['Pawns']['Pawn %s' %(which)]['Row'] += nr
    
    # update new pos in board
    board[color['Pawns']['Pawn %s' %(which)]['Row'],color['Pawns']['Pawn %s' %(which)]['Column']] = spot

    return board,color

Attached Files

.txt   ChessBoard.txt (Size: 566 bytes / Downloads: 181)
.py   ChessUDF.py (Size: 7.75 KB / Downloads: 172)
.py   Robots Play Chess 1.2.py (Size: 2.07 KB / Downloads: 165)
Reply
#2
Obviously color is never white. What is white? The only place I see white defined is here:
# White Dictionary ------------------------------------------------------------
def white():
if color == some function seems odd. Did you mean to do this?
if color == "white":
You are trying to make dictionaries do what classes do much better. This does somewhat the same thing you were doing using classes instead of dictionaries. To show how subclassing works I gave each chess piece a method that will return a list of available moves for the piece. The way the list is constructed is different for pawns than rooks or bishops or knights, so subclassing lets me use a different algorithm for each piece.
from numpy import genfromtxt

BLACK = 0
WHITE = 1

class Piece:
    '''Base class for chess pieces'''
    all_pieces = []   # List of all chess pieces
    black_pieces = [] # List of all black chess pieces
    white_pieces = [] # List of all white chess pieces

    @classmethod
    def find(cls, row, column):
        '''Return piece at row, column or None if no piece found'''
        for piece in cls.all_pieces:
            if piece.row == row and piece.column == column:
                return piece
        return None

    @classmethod
    def isempty(cls, row, column):
        '''Return True if square[row, board] is empty, else False'''
        return cls.find(row, column) is None

    @classmethod
    def iscolor(cls, row, column, color):
        '''Return True if square[row, column] contains a piece of color'''
        piece = cls.find(row, column)
        if piece and piece.color == color:
            return True
        return False

    @classmethod
    def isopen(cls, row, column, color):
        '''Return True if square[row, column] is empty or contains a piece of color'''
        piece = cls.find(row, column)
        return piece is None or piece.color == color

    def __init__(self, color, row, column):
        self.color = color
        self.moves = []
        self.move(row, column)
        self.taken = False
        self.all_pieces.append(self)
        if color == BLACK:
            self.black_pieces.append(self)
        else:
            self.white_pieces.append(self)

    def __str__(self):
        '''Return string representation of piece'''
        color = ("Black", "White")[self.color]
        return f"{color} {self.__class__.__name__} ({self.row}, {self.column})"
    
    def move(self, row, column):
        '''Move piece to square[row, column]'''
        self.row = row
        self.column = column
        self.moves.append((row, column))

class Pawn(Piece):
    def open_moves(self):
        '''Return list of available moves'''
        moves = []
        if self.color == BLACK:
            if self.row == 7:
                return moves
            if self.isempty(self.row+1, self.column):
                moves.append((self.row+1, self.column))
            if self.row == 1 and self.isempty(2, self.column) and self.isempty(3, self.column):
                moves.append((3, self.column))
            if self.column > 0 and self.iscolor(self.row+1, self.column-1, WHITE):
                moves.append((self.row+1, self.column-1))
            if self.column < 7 and self.iscolor(self.row+1, self.column+1, WHITE):
                moves.append((self.row+1, self.column+1))
        else: # color == White
            if self.row == 0:
                return moves
            if self.isempty(self.row-1, self.column):
                moves.append((self.row-1, self.column))
            if self.row == 6 and self.isempty(5, self.column) and self.isempty(4, self.column):
                moves.append((4, self.column))
            if self.column > 0 and self.iscolor(self.row-1, self.column-1, BLACK):
                moves.append((self.row-1, self.column-1))
            if self.column < 7 and self.iscolor(self.row-1, self.column+1, BLACK):
                moves.append((self.row-1, self.column+1))
        return moves

class Rook(Piece):
   def open_moves(self):
        '''Return list of available moves.  Castling not supported at this time'''
        moves = []
        color = WHITE if self.color is BLACK else BLACK
        for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
            for x in range(1, 9):
                row = self.row + dr * x
                col = self.column + dc * x
                if row < 0 or row > 7 or col < 0 or col > 7:
                    break
                if self.isempty(row, col):
                    moves.append((row, col))
                elif self.iscolor(row, col, color):
                    moves.append((row, col))
                    break
                else:
                    break
        return moves

class Knight(Piece):
    def open_moves(self):
        '''Return list of available moves'''
        moves = []
        color = WHITE if self.color is BLACK else BLACK
        for dr, dc in ((1, 2), (1, -2), (-1, 2), (-1, -2), (2, 1), (2, -1), (-2, 1), (-2, -1)):
            row = self.row + dr
            col = self.column + dc
            if 0 <= row <= 7 and 0 <= col <= 7 and self.isopen(row, col, color):
                moves.append((row, col))
        return moves

class Bishop(Piece):
   def open_moves(self):
        '''Return list of available moves'''
        moves = []
        color = WHITE if self.color is BLACK else BLACK
        for dr, dc in ((1, 1), (1, -1), (-1, 1), (-1, -1)):
            for x in range(1, 9):
                row = self.row + dr * x
                col = self.column + dc * x
                if row < 0 or row > 7 or col < 0 or col > 7:
                    break
                if self.isempty(row, col):
                    moves.append((row, col))
                elif self.iscolor(row, col, color):
                    moves.append((row, col))
                    break
                else:
                    break
        return moves

class Queen(Piece):
   def open_moves(self):
        '''Return list of available moves'''
        return Bishop.open_moves(self) + Rook.open_moves(self)

class King(Piece):
    def open_moves(self):
        '''Return list of available moves'''
        moves = []
        color = WHITE if self.color is BLACK else BLACK
        for dr, dc in ((1, 1), (1, -1), (-1, 1), (-1, -1)):
            row = self.row + dr
            col = self.column + dc
            if row < 0 or row > 7 or col < 0 or col > 7:
                break
            if self.isempty(row, col):
                moves.append((row, col))
            elif self.iscolor(row, col, color):
                moves.append((row, col))
                break
            else:
                break
        return moves

class Player:
    '''Create chess pieces for a player'''
    def __init__(self, color=BLACK):
        row = 1 if color == BLACK else 6
        self.pawns = [Pawn(color, row, column) for column in range(8)]

        row = 0 if color == BLACK else 7
        self.rooks = [Rook(color, row, column) for column in (0, 7)]
        self.knights = [Knight(color, row, column) for column in (1, 6)]
        self.bishops = [Bishop(color, row, column) for column in (2, 5)]
        self.queen = Queen(color, row, 3)
        self.king = King(color, row, 4)

black = Player(BLACK)
white = Player(WHITE)

for piece in Piece.all_pieces:
    print(piece, piece.open_moves())
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  name 'lblstatus' is not defined when referencing a label KatManDEW 4 1,470 Apr-21-2022, 12:33 PM
Last Post: KatManDEW
  Referencing string names in df to outside variables illmattic 1 1,328 Nov-16-2021, 12:47 PM
Last Post: jefsummers
  Referencing a fixed cell Mark17 2 2,020 Dec-17-2020, 07:14 PM
Last Post: Mark17
Sad need help in referencing a list n00bdev 2 1,810 Nov-01-2020, 12:06 PM
Last Post: buran
  Issue referencing new instance from other class nanok66 3 2,180 Jul-31-2020, 02:07 AM
Last Post: nanok66
  referencing another method in a class Skaperen 6 2,591 Jul-02-2020, 04:30 AM
Last Post: Skaperen
  Theory behind referencing a dictionary rather than copying it to a list sShadowSerpent 2 2,040 Mar-24-2020, 07:18 PM
Last Post: sShadowSerpent
  "not defined" error in function referencing a class Exsul 2 3,641 Mar-27-2019, 11:59 PM
Last Post: Exsul
  Prevent Variable Referencing Th3Eye 4 2,828 Oct-03-2018, 07:01 PM
Last Post: buran
  Tree insertion and variable referencing hshivaraj 3 3,284 Dec-10-2017, 04:29 PM
Last Post: Windspar

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020