#!/usr/bin/python EMPTY = None BLACK = True WHITE = False BOARDWIDTH = BOARDHEIGHT = 8 def onBoard((col, row)): return col in range(BOARDWIDTH) and row in range(BOARDHEIGHT) import piece def otherColor(color): return (not color) # DIRECTIONS = ((-1, -1), (0, -1), (1, -1), # (-1, 0), (1, 0), # (-1, 1), (0, 1), (1, 1)) def positionName((column, rank)): return "abcdefgh"[column] + "12345678"[rank] def position(name): assert len(name) == 2 return ("abcdefgh".index(name[0]), "12345678".index(name[1])) def positions(): # the board references are column, row # to simplify x, y translation for column in range(BOARDWIDTH): for row in range(BOARDHEIGHT): yield (column, row) def dumpBoard(board): """Debugging support""" for row in range(BOARDHEIGHT)[::-1]: for column in range(BOARDWIDTH): if (board.pieceAt((column,row))) == EMPTY: if ((row+column)%2 == 0): print " ", else: print "#", else: # piece prints itself print board.pieceAt((column,row)).code(), print if board.nextMove == WHITE: print "White to move" else: print "Black to move" class GameState: def __init__(self): self.initializeState() self.lastMove = (None, None) def initializeState(self): self.board = {}.fromkeys(positions()) # white always goes first self.nextMove = WHITE self.gameOver = False def setup(self): self.setFen("rnbqkbnr/pppppppp/////PPPPPPPP/RNBQKBNR") return self # to allow b = Board().setup() def pieceAt(self, pos): return self.board.get(pos) def putPieceAt(self, piece, pos): self.board[pos] = piece def movePiece(self, src, dest): p = self.pieceAt(src) assert(p != EMPTY) self.putPieceAt(p, dest) self.putPieceAt(EMPTY, src) self.nextMove = otherColor(self.nextMove) self.lastMove = (src, dest) def whereIs(self, piece): """returns tuple (col,row) or None""" for key,value in self.board.iteritems(): if (piece == value): return key return None def findKingAndPos(self, color): for curPos, curPiece in self.board.iteritems(): if isinstance(curPiece, piece.King) \ and curPiece.color == color: return curPiece, curPos raise Exception("no king! is this a democracy?") def isInCheck(self, color): king, kingPos = self.findKingAndPos(color) other = otherColor(color) for pc in filter(lambda pc: pc.color == other, filter(None, self.board.values())): if kingPos in pc.attacks(): return True return False def setFen(self, s): """Allow board setup via FEN board encoding standard""" map = {'B':piece.Bishop,'K':piece.King,'N':piece.Knight, 'P':piece.Pawn,'Q':piece.Queen,'R':piece.Rook} for p in positions(): self.board[p] = EMPTY col,row = 0,7 for c in s: if c == '/': col,row = 0,row-1 elif c in "BKNPQR": self.board[(col,row)] = map[c](self,WHITE) col += 1 elif c in "bknpqr": self.board[(col,row)] = map[c.upper()](self,BLACK) col += 1 elif c in "12345678": col += int(c) def storeOn(self, stream): print >>stream, "[", for pos in positions(): p = self.pieceAt(pos) if p: print >>stream, "@".join([p.code(), positionName(pos)]), print >>stream, "]"