Skip to content

Instantly share code, notes, and snippets.

@chronologos
Last active February 16, 2021 03:05
Show Gist options
  • Save chronologos/f60579288b647c01cff649e0b20c4cb8 to your computer and use it in GitHub Desktop.
Save chronologos/f60579288b647c01cff649e0b20c4cb8 to your computer and use it in GitHub Desktop.
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