Last active
February 16, 2021 03:05
-
-
Save chronologos/f60579288b647c01cff649e0b20c4cb8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from abc import ABC, abstractmethod | |
from enum import Enum | |
from typing import List, Union, Dict, Tuple | |
import Math | |
class Color(Enum): | |
WHITE = 1 | |
BLACK = 2 | |
class Piece(ABC): | |
def __init__(self, color: Color): | |
self._color = color | |
pass | |
@abstractmethod | |
def validMove(self, board, src, dest) -> bool: | |
if src.getPiece() != self: | |
return False | |
return True | |
class Spot: | |
def __str__(self): | |
return "({},{},{})".format( | |
self._x, self._y, (self._piece if self._piece else ".") | |
) | |
def __init__(self, piece: Union[Piece, None], x: int, y: int): | |
self.setPiece(piece) | |
self._x = x | |
self._y = y | |
def setPiece(self, piece: Union[Piece, None]): | |
self._piece = piece | |
def getPiece(self) -> Union[Piece, None]: | |
return self._piece | |
def getRow(self) -> int: | |
return self._x | |
def getCol(self) -> int: | |
return self._y | |
class King(Piece): | |
def __init__(self, color): | |
super().__init__(color) | |
def validMove(self, board, src: Spot, dest: Spot) -> bool: | |
if self._color == dest.getPiece()._color: | |
return False | |
class Knight(Piece): | |
def __str__(self): | |
return "{} N".format(self._color) | |
def __init__(self, color: Color): | |
super().__init__(color) | |
def validMove(self, board: Board, start: Spot, end: Spot): | |
if self._color == end.getPiece()._color: | |
return False | |
deltaI = Math.abs(start.getRow() - end.getRow()) | |
deltaJ = Math.abs(start.getCol() - end.getCol()) | |
return deltaI * deltaJ == 2 # Knight moves in L shape | |
class Pawn(Piece): | |
def __str__(self): | |
return "{} P".format(self._color) | |
def __init__(self, color): | |
super().__init__(color) | |
def validMove(self, board, src: Spot, dest: Spot) -> bool: | |
if not super().validMove(board, src, dest): | |
return False | |
m, n = src.getRow(), src.getCol() | |
mm, nn = dest.getRow(), dest.getCol() | |
if dest.getPiece(): | |
if nn != n - 1 and nn != n + 1: | |
return False | |
if mm != m + 1: | |
return False | |
else: | |
if n != nn: | |
return False | |
return True | |
class Board: | |
def __str__(self): | |
return ",".join([str(spot) for spot in self._spots.values()]) | |
def __init__(self): | |
self._spots: Dict[Tuple[int, int], Spot] = { | |
(m, n): Spot(None, m, n) for m in range(4) for n in range(4) | |
} | |
for (r, c) in self._spots: | |
if r == 1: | |
self._spots[(r, c)].setPiece(Pawn(Color.WHITE)) | |
if r == 2: | |
self._spots[(r, c)].setPiece(Pawn(Color.BLACK)) | |
# TODO(fill in pieces) | |
def getSpot(self, m: int, n: int) -> Spot: | |
return self._spots[(m, n)] | |
class GameStatus(Enum): | |
IN_PROGRESS = 1 | |
ENDED = 2 | |
class Player: | |
def __init__(self, color: Color): | |
self._color = color | |
class Game: | |
def __init__(self, player1, player2): | |
self._board: Board = Board() | |
self._status: GameStatus = GameStatus.IN_PROGRESS | |
self._players: List[Player] = [player1, player2] | |
self._currentTurn: Player = player1 | |
self._movesPlayed: List[str] = [] | |
def move( | |
self, player: Player, srcCoords: Tuple[int, int], destCoords: Tuple[int, int] | |
) -> bool: | |
src = self._board.getSpot(srcCoords[0], srcCoords[1]) | |
dest = self._board.getSpot(destCoords[0], destCoords[1]) | |
if not self._genericMoveValid(self._board, src, dest): | |
return False | |
# special rules for castling, promoting a pawn etc. | |
# if isinstance(src.getPiece(), King) and isValidCastle(): | |
# castle(src, board) | |
# return | |
# if not castling and not promoting a pawn, make a normal move. | |
dest.setPiece(src.getPiece()) | |
src.setPiece(None) | |
# Toggle self._currentTurn | |
# other possible actions | |
def resign(self, player): | |
pass | |
def offerDraw(self, player): | |
pass | |
def acceptDrawOffer(self, player): | |
pass | |
def _genericMoveValid(self, board: Board, src: Spot, dest: Spot) -> bool: | |
if not src.getPiece(): | |
return False | |
if src.getRow() == dest.getRow() and src.getCol() == dest.getCol(): | |
return False | |
if self._color == dest.getPiece()._color: | |
return False | |
print("piece-specific check") | |
if not src.getPiece().validMove(board, src, dest): | |
return False | |
return True | |
if __name__ == "__main__": | |
p1 = Player(Color.WHITE) | |
p2 = Player(Color.BLACK) | |
game = Game(p1, p2) | |
print(game._board) | |
srcSpot = game._board.getSpot(0, 0) | |
destSpot = game._board.getSpot(1, 0) | |
print(game.move(p1, (0, 0), (1, 0))) | |
print(game._board) | |
srcSpot = game._board.getSpot(1, 0) | |
destSpot = game._board.getSpot(2, 1) | |
print(game.move(p1, (1, 0), (2, 1))) | |
print(game._board) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment