def executeCommand(cb: ChessBoard, cmd: GameCommands) -> Either[List[str], ChessBoard]: return when( cmd, { # This is a hack! Python doesn't have switch statements or any elegant form of case matching is_(Pick): lambda: Right(showPossibleMoves(Just(cmd.position), cb)), is_(Move): lambda: validateAndMakeMove(cmd, cb), is_(Promotion): Left("Unimplemented"), _: Right(cb) })
def parseMoveCommand(fromPosStr: str, toPosStr: str): msg = ["invalid position. If you are trying to move a piece, give two positions separated by space e.g a1 a2"] # return fromString(fromPosStr).map(lambda x: fromString(toPosStr).map(lambda y: Right(Move(x, y))) # .orElse(Left(msg)) # ).orElse(Left(msg)) from_ = maybeToLeft(fromString(fromPosStr), ["Invalid source position!"]) to_ = maybeToLeft(fromString(toPosStr), ["Invalid target position!"]) res = from_ |bind| (lambda x: to_ |bind| (lambda y: Right(Move(x, y)))) return res
def parseInput(inputStr: Maybe[str]) -> Either[List[str], GameCommands]: def handleCmd(args): if args[0] == "promote": return parsePromoteCommand(args[1:]) if len(args) == 1: return parsePickCommand(args[0]) if len(args) == 2: return parseMoveCommand(args[0], args[1]) return Left(["Unrecognised command"]) return inputStr.map(trim).filter(lambda x: x) \ .map(lambda x: x.split(" ")) \ .map(mapl(trim)) \ .map(handleCmd) \ .orElse(Right(ShowBoard()))
def parsePromoteCommand(args) -> Either[List[str], GameCommands]: if len(args) != 2: return Left(["If you are trying to promote a pawn, type promote <position> <piece name>"]) pos = fromString(args[0]) def piece(): return { "rook": Just(PieceType.Rook), "queen": Just(PieceType.Queen), "bishop": Just(PieceType.Bishop), "knight": Just(PieceType.Knight) }.get(args[1], Nothing) return pos.map(lambda p: piece().map(lambda x: Right(Promotion(p, x))) .orElse(Left(["Invalid piece. You can promote to queen, rook, bishop, or knight"])) ).orElse(Left(["Invalid position. First argument to promote must be a position e.g. a1"]))
def parsePickCommand(pos: str): return fromString(pos).map(lambda x: Right(Pick(x))) \ .orElse(Left(["invalid position. If you want to highlight the moves from a position, " "give just a position e.g. a1"]))
def pieceAt(x: Position): return at(cb, x).map(lambda x: Right(x)).orElse( Left(["No piece at source position!"]))
def validateTurn(piece: Piece): (col, typ) = piece if not (col == cb.nextPlayer()): return Left(["Not your turn!"]) return Right(piece)
def validateMove(): px: Position = move.fromPos py: Position = move.toPos ys = mapl(lambda p: toIndex(p), possiblePositionsToMove(cb, px)) return Right(movePiece(px, py, cb)) if toIndex(py) in ys else Left( ["This move not allowed!"])