Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix castling and spelling of en passant #9 #11

Merged
merged 7 commits into from
Jan 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.pyc
*.pycache
*.bak

build/
dist/
110 changes: 78 additions & 32 deletions src/Board.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
class Board:

def __init__(self, mateInOne=False, castleBoard=False,
pessant=False, promotion=False):
passant=False, promotion=False):
self.pieces = []
self.history = []
self.points = 0
self.currentSide = WHITE
self.movesMade = 0
self.checkmate = False

if not mateInOne and not castleBoard and not pessant and not promotion:
if not mateInOne and not castleBoard and not passant and not promotion:
self.pieces.extend([Rook(self, BLACK, C(0, 7)),
Knight(self, BLACK, C(1, 7)),
Bishop(self, BLACK, C(2, 7)),
Expand Down Expand Up @@ -53,7 +53,7 @@ def __init__(self, mateInOne=False, castleBoard=False,
kingBlack = King(self, BLACK, C(3, 2))
self.pieces.extend([pawnToPromote, kingWhite, kingBlack])

elif pessant:
elif passant:
pawn = Pawn(self, WHITE, C(1, 4))
pawn2 = Pawn(self, BLACK, C(2, 6))
kingWhite = King(self, WHITE, C(4, 0))
Expand Down Expand Up @@ -85,7 +85,7 @@ def undoLastMove(self):
king.movesMade -= 1
rook.movesMade -= 1

elif lastMove.pessant:
elif lastMove.passant:
pawnMoved = lastMove.piece
pawnTaken = pieceTaken
self.pieces.append(pawnTaken)
Expand All @@ -100,6 +100,12 @@ def undoLastMove(self):
pawnPromoted = lastMove.piece
promotedPiece = self.pieceAtPosition(lastMove.newPos)
self.pieces.remove(promotedPiece)
if pieceTaken:
if pieceTaken.side == WHITE:
self.points += pieceTaken.value
if pieceTaken.side == BLACK:
self.points -= pieceTaken.value
self.pieces.append(pieceTaken)
self.pieces.append(pawnPromoted)
if pawnPromoted.side == WHITE:
self.points -= promotedPiece.value - 1
Expand Down Expand Up @@ -148,7 +154,7 @@ def getLastPieceMoved(self):

def addMoveToHistory(self, move):
pieceTaken = None
if move.pessant:
if move.passant:
pieceTaken = move.specialMovePiece
self.history.append([move, pieceTaken])
return
Expand Down Expand Up @@ -177,18 +183,16 @@ def makeStringRep(self, pieces):
color = 'blue' if side == WHITE else 'red'
pieceRep = colored(piece.stringRep, color)
else:
pieceRep = 'x'
pieceRep = ' '
stringRep += pieceRep + ' '
stringRep += '\n'
stringRep = stringRep.strip()
return stringRep
return stringRep.rstrip()

def wrapStringRep(self, stringRep):
sRep = '\n'.join(
[' a b c d e f g h ', ' '*21] +
['%d %s %d' % (8-r, s.strip(), 8-r)
['%d %s' % (8-r, s.rstrip())
for r, s in enumerate(stringRep.split('\n'))] +
[' '*21, ' a b c d e f g h ']
[' '*21, ' a b c d e f g h']
).rstrip()
return sRep

Expand All @@ -199,22 +203,52 @@ def fileOfPiece(self, piece):
transTable = str.maketrans('01234567', 'abcdefgh')
return str(piece.position[0]).translate(transTable)

def getShortNotationOfMove(self, move):
def getCoordinateNotationOfMove(self, move):
notation = ""
notation += self.positionToHumanCoord(move.oldPos)
notation += self.positionToHumanCoord(move.newPos)

if move.promotion:
notation += str(move.specialMovePiece.stringRep)

return notation

def getCaptureNotation(self, move, short=False):
notation = ""
pieceToMove = move.piece
pieceToTake = move.pieceToCapture

if type(pieceToMove) is Pawn:
notation += self.fileOfPiece(pieceToMove)
else:
notation += pieceToMove.stringRep
notation += 'x'
if short:
notation += pieceToTake.stringRep
else:
notation += self.positionToHumanCoord(move.newPos)

if move.promotion:
notation += str(move.specialMovePiece.stringRep)

return notation

def getAlgebraicNotationOfMove(self, move, short=True):
notation = ""
pieceToMove = move.piece
pieceToTake = move.pieceToCapture

if move.queensideCastle:
return "0-0-0"
return "O-O-O"

if move.kingsideCastle:
return "0-0"
return "O-O"

if pieceToMove.stringRep != 'p':
if not short or type(pieceToMove) is not Pawn:
notation += pieceToMove.stringRep

if pieceToTake is not None:
if pieceToMove.stringRep == 'p':
if short and type(pieceToMove) is Pawn:
notation += self.fileOfPiece(pieceToMove)
notation += 'x'

Expand All @@ -225,55 +259,58 @@ def getShortNotationOfMove(self, move):

return notation

def getShortNotationOfMoveWithFile(self, move):
# TODO: Use self.getShortNotationOfMove instead of repeating code
def getAlgebraicNotationOfMoveWithFile(self, move, short=True):
# TODO: Use self.getAlgebraicNotationOfMove instead of repeating code
notation = ""
pieceToMove = self.pieceAtPosition(move.oldPos)
pieceToTake = self.pieceAtPosition(move.newPos)

if pieceToMove.stringRep != 'p':
if not short or type(pieceToMove) is not Pawn:
notation += pieceToMove.stringRep
notation += self.fileOfPiece(pieceToMove)
notation += self.fileOfPiece(pieceToMove)

if pieceToTake is not None:
notation += 'x'

notation += self.positionToHumanCoord(move.newPos)
return notation

def getShortNotationOfMoveWithRank(self, move):
# TODO: Use self.getShortNotationOfMove instead of repeating code
def getAlgebraicNotationOfMoveWithRank(self, move, short=True):
# TODO: Use self.getAlgebraicNotationOfMove instead of repeating code
notation = ""
pieceToMove = self.pieceAtPosition(move.oldPos)
pieceToTake = self.pieceAtPosition(move.newPos)

if pieceToMove.stringRep != 'p':
if not short or type(pieceToMove) is not Pawn:
notation += pieceToMove.stringRep
notation += self.rankOfPiece(pieceToMove)

notation += self.rankOfPiece(pieceToMove)

if pieceToTake is not None:
if short and type(pieceToMove) is Pawn:
notation += self.fileOfPiece(pieceToMove)
notation += 'x'

notation += self.positionToHumanCoord(move.newPos)
return notation

def getShortNotationOfMoveWithFileAndRank(self, move):
# TODO: Use self.getShortNotationOfMove instead of repeating code
def getAlgebraicNotationOfMoveWithFileAndRank(self, move, short=True):
# TODO: Use self.getAlgebraicNotationOfMove instead of repeating code
notation = ""
pieceToMove = self.pieceAtPosition(move.oldPos)
pieceToTake = self.pieceAtPosition(move.newPos)

if pieceToMove.stringRep != 'p':
if not short or type(pieceToMove) is not Pawn:
notation += pieceToMove.stringRep
notation += self.fileOfPiece(pieceToMove)
notation += self.rankOfPiece(pieceToMove)

notation += self.fileOfPiece(pieceToMove)
notation += self.rankOfPiece(pieceToMove)

if pieceToTake is not None:
notation += 'x'

notation += self.positionToHumanCoord(move.newPos)
return notation
return

def humanCoordToPosition(self, coord):
transTable = str.maketrans('abcdefgh', '12345678')
Expand Down Expand Up @@ -329,24 +366,33 @@ def makeMove(self, move):
kingToMove = move.piece
rookToMove = move.specialMovePiece
self.movePieceToPosition(kingToMove, move.newPos)
self.movePieceToPosition(rookToMove, move.rookMovePos)
self.movePieceToPosition(rookToMove, move.rookMove.newPos)
kingToMove.movesMade += 1
rookToMove.movesMade += 1

elif move.pessant:
elif move.passant:
pawnToMove = move.piece
pawnToTake = move.specialMovePiece
pawnToMove.position = move.newPos
self.pieces.remove(pawnToTake)
pawnToMove.movesMade += 1

elif move.promotion:
pieceToTake = move.pieceToCapture
self.pieces.remove(move.piece)
if pieceToTake:
if pieceToTake.side == WHITE:
self.points -= pieceToTake.value
if pieceToTake.side == BLACK:
self.points += pieceToTake.value
self.pieces.remove(pieceToTake)

self.pieces.append(move.specialMovePiece)
if move.piece.side == WHITE:
self.points += move.specialMovePiece.value - 1
if move.piece.side == BLACK:
self.points -= move.specialMovePiece.value - 1
move.piece.movesMade += 1

else:
pieceToMove = move.piece
Expand Down
66 changes: 53 additions & 13 deletions src/InputParser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
from Pawn import Pawn


class InputParser:
Expand All @@ -8,44 +9,83 @@ def __init__(self, board, side):
self.side = side

def parse(self, humanInput):
humanInput = humanInput.lower()
regexShortNotation = re.compile('[rnbkqp][a-z][1-8]')
if regexShortNotation.match(humanInput):
return self.moveForShortNotation(humanInput)
regexCoordinateNotation = re.compile('(?i)[a-h][1-8][a-h][1-8][QRBN]?')
if regexCoordinateNotation.match(humanInput):
return self.moveForCoordinateNotation(humanInput)
regexAlgebraicNotation = re.compile('(?i)O-O|O-O-O|(?:[KQRBNP]?[a-h]?[1-8]?x?[a-h][1-8]|[Pa-h]x?[a-h])(?:=?[QRBN])?')
if regexAlgebraicNotation.match(humanInput):
return self.moveForShortAlgebraicNotation(humanInput)
raise ValueError("Invalid move: %s" % humanInput)

def moveForShortNotation(self, notation):
moves = self.getLegalMovesWithShortNotation(self.side)
def moveForCoordinateNotation(self, notation):
for move in self.board.getAllMovesLegal(self.side):
if self.board.getCoordinateNotationOfMove(move).lower() == notation.lower():
move.notation = self.notationForMove(move)
return move
raise ValueError("Illegal move: %s" % notation)

# Only handles SAN, not long-algebraic or descriptive
def moveForShortAlgebraicNotation(self, notation):
shortNotation = notation.replace("x","")
moves = self.getLegalMovesWithNotation(self.side, False)
for move in moves:
if move.notation.replace("x","") == shortNotation: # Bxc3 versus bxc3
return move
for move in moves:
if move.notation.replace("x","").lower() == shortNotation.lower():
return move
moves = self.getLegalMovesWithNotation(self.side, True)
for move in moves:
if move.notation.replace("x","") == shortNotation: # Bxc3 versus bxc3
return move
for move in moves:
if move.notation.lower() == notation.lower():
if move.notation.replace("x","").lower() == shortNotation.lower():
return move
shortNotation = notation.lower().replace("p","").replace("=","")
if re.compile('[a-h][1-8]?[qrbn]?').match(shortNotation):
for move in moves:
if type(move.piece) is Pawn and not move.pieceToCapture and self.board.getCoordinateNotationOfMove(move).replace("=","").lower().endswith(shortNotation):
return move
for move in moves:
if type(move.piece) is Pawn and not move.pieceToCapture and re.sub("[1-8]", "", self.board.getCoordinateNotationOfMove(move)).replace("=","").lower().endswith(shortNotation):
return move # ASSUME lazy pawn move (P)c is unambiguous
shortNotation = shortNotation.lower().replace("x","")
if re.compile('[a-h]?[a-h][1-8]?[qrbn]?').match(shortNotation):
for move in moves:
if type(move.piece) is Pawn and move.pieceToCapture and self.board.getCaptureNotation(move).replace("x","").lower().endswith(shortNotation):
return move # ASSUME lazier pawn capture (P)b(x)c3 is unambiguous
for move in moves:
if type(move.piece) is Pawn and move.pieceToCapture and re.sub("[1-8]", "", self.board.getCaptureNotation(move).replace("x","")).lower().endswith(shortNotation):
return move # ASSUME laziest pawn capture (P)b(x)c is unambiguous
raise ValueError("Illegal move: %s" % notation)

def notationForMove(self, move):
side = self.board.getSideOfMove(move)
moves = self.getLegalMovesWithShortNotation(side)
moves = self.getLegalMovesWithNotation(side)
for m in moves:
if m == move:
return m.notation

def getLegalMovesWithShortNotation(self, side):
def getLegalMovesWithNotation(self, side, short=True):
moves = []
for legalMove in self.board.getAllMovesLegal(side):
moves.append(legalMove)
legalMove.notation = self.board.getShortNotationOfMove(legalMove)
legalMove.notation = self.board.getAlgebraicNotationOfMove(legalMove, short)

duplicateNotationMoves = self.duplicateMovesFromMoves(moves)
for duplicateMove in duplicateNotationMoves:
duplicateMove.notation = \
self.board.getShortNotationOfMoveWithFile(duplicateMove)
self.board.getAlgebraicNotationOfMoveWithFile(duplicateMove, short)

duplicateNotationMoves = self.duplicateMovesFromMoves(moves)
for duplicateMove in duplicateNotationMoves:
duplicateMove.notation = \
self.board.getShortNotationOfMoveWithRank(duplicateMove)
self.board.getAlgebraicNotationOfMoveWithRank(duplicateMove, short)

duplicateNotationMoves = self.duplicateMovesFromMoves(moves)
for duplicateMove in duplicateNotationMoves:
duplicateMove.notation = \
self.board.getShortNotationOfMoveWithFileAndRank(duplicateMove)
self.board.getAlgebraicNotationOfMoveWithFileAndRank(duplicateMove, short)

return moves

Expand Down