beginning of transition
This commit is contained in:
+104
-4
@@ -1,11 +1,13 @@
|
||||
from enum import Enum, auto
|
||||
from dataclasses import dataclass
|
||||
from typing import Iterator, Optional, List, Tuple
|
||||
import random
|
||||
|
||||
import copy
|
||||
FILES = "abcdefgh"
|
||||
RANKS = "12345678"
|
||||
|
||||
|
||||
|
||||
|
||||
class PieceType(Enum):
|
||||
PAWN = auto()
|
||||
KNIGHT = auto()
|
||||
@@ -26,6 +28,19 @@ class Color(Enum):
|
||||
else:
|
||||
return Color.WHITE
|
||||
|
||||
class Outcome(Enum):
|
||||
DRAW = auto()
|
||||
WHITE_WIN = auto()
|
||||
BLACK_WIN = auto()
|
||||
NOT_FINISHED = auto()
|
||||
|
||||
@classmethod
|
||||
def from_color(cls, color: Color) -> "Outcome":
|
||||
if color == Color.WHITE:
|
||||
return Outcome.WHITE_WIN
|
||||
else:
|
||||
return Outcome.BLACK_WIN
|
||||
|
||||
|
||||
@dataclass
|
||||
class BoardPos:
|
||||
@@ -99,6 +114,87 @@ class ChessBoard:
|
||||
fields: List[List[BoardField]]
|
||||
num_moves: int
|
||||
move_history: List[Tuple['BoardMove', Optional[Piece]]]
|
||||
initial_board: List[List[BoardField]]
|
||||
|
||||
@property
|
||||
def turn(self) -> "Color":
|
||||
len_mv_history = len(self.move_history)
|
||||
if len_mv_history > 0:
|
||||
|
||||
first_moved_piece_color = self.initial_move_color
|
||||
if len_mv_history % 2 == 0:
|
||||
return first_moved_piece_color
|
||||
else:
|
||||
return first_moved_piece_color.opposite
|
||||
else:
|
||||
return Color.WHITE
|
||||
|
||||
@property
|
||||
def initial_move_color(self) -> Color:
|
||||
first_move = self.move_history[0]
|
||||
from_pos = first_move[0].m_from
|
||||
# look up what color the piece had that moved first
|
||||
# (odd solution but i think its quite fine)
|
||||
first_moved_field = self.initial_board[from_pos.x][from_pos.y]
|
||||
first_moved_piece_color = Color.WHITE
|
||||
if first_moved_field.piece is not None:
|
||||
first_moved_piece_color = first_moved_field.piece.color
|
||||
return first_moved_piece_color
|
||||
|
||||
def is_checkmate(self) -> bool:
|
||||
cur_turn_color = self.turn
|
||||
return len(self.generate_moves(cur_turn_color)) == 0 and self.is_field_attacked(self.pos_of_king(cur_turn_color), cur_turn_color.opposite)
|
||||
|
||||
def is_stalemate(self) -> bool:
|
||||
cur_turn_color = self.turn
|
||||
return len(self.generate_moves(cur_turn_color)) == 0
|
||||
|
||||
def is_seventyfive_moves(self) -> bool:
|
||||
return len(self.move_history) >= 75
|
||||
|
||||
def is_fivefold_repetition(self) -> bool:
|
||||
return self.highest_repetiton_amount() >= 5
|
||||
|
||||
def outcome(self) -> Outcome:
|
||||
if self.is_checkmate():
|
||||
return Outcome.from_color(self.turn)
|
||||
if self.is_stalemate() or self.is_seventyfive_moves or self.is_fivefold_repetition:
|
||||
return Outcome.DRAW
|
||||
return Outcome.NOT_FINISHED
|
||||
|
||||
def highest_repetiton_amount(self) -> int:
|
||||
if self.move_history:
|
||||
starting_color = self.initial_move_color
|
||||
else:
|
||||
starting_color = Color.WHITE
|
||||
|
||||
dummy = ChessBoard(
|
||||
copy.deepcopy(self.initial_board),
|
||||
0,
|
||||
[],
|
||||
copy.deepcopy(self.initial_board),
|
||||
)
|
||||
|
||||
color = starting_color
|
||||
states: list[str] = []
|
||||
|
||||
states.append(str(dummy))
|
||||
|
||||
for mv, _ in self.move_history:
|
||||
dummy.make_move(mv, color)
|
||||
color = color.opposite
|
||||
states.append(str(dummy))
|
||||
|
||||
counts: dict[str, int] = {}
|
||||
max_count = 0
|
||||
|
||||
for state in states:
|
||||
counts[state] = counts.get(state, 0) + 1
|
||||
if counts[state] > max_count:
|
||||
max_count = counts[state]
|
||||
|
||||
return max_count
|
||||
|
||||
|
||||
def place(self, row: int, col: int, piece_type: PieceType, color: Color):
|
||||
self.fields[row][col].piece = Piece(piece_type, color)
|
||||
@@ -106,8 +202,9 @@ class ChessBoard:
|
||||
# initialize default starting position
|
||||
@classmethod
|
||||
def init_default(cls) -> "ChessBoard":
|
||||
empty_board = [[BoardField() for _ in range(8)] for _ in range(8)]
|
||||
brd = cls(
|
||||
[[BoardField() for _ in range(8)] for _ in range(8)], 0, []
|
||||
empty_board, 0, [], empty_board
|
||||
)
|
||||
|
||||
# place pawns
|
||||
@@ -135,6 +232,9 @@ class ChessBoard:
|
||||
for col, piece_type in enumerate(back_rank):
|
||||
brd.place(7, col, piece_type, Color.WHITE)
|
||||
|
||||
#set the inital board for later ref
|
||||
brd.initial_board = brd.fields
|
||||
|
||||
return brd
|
||||
|
||||
# attempt to make move for color
|
||||
@@ -317,7 +417,7 @@ class ChessBoard:
|
||||
color.opposite,
|
||||
):
|
||||
# check if the last move moved the pawn there from the starting square
|
||||
last_move = self.move_history[move_history_len][0]
|
||||
last_move = self.move_history[-1][0] # final move, not past-the-end
|
||||
|
||||
if last_move.m_from == BoardPos((tr, tc + en_passant_dir)) and last_move.m_to == BoardPos((tr, tc - en_passant_dir)):
|
||||
moves.append(BoardMove(pos, BoardPos((tr, tc))))
|
||||
|
||||
Reference in New Issue
Block a user