def str_to_card(str_card): ''' Return a Card obj from a string representation. >>> str_to_card('102') 10♡ >>> str_to_card('!102') 10♡ ''' if str_card.startswith('!'): str_card = str_card[1:] return Card(int(str_card[-1]), str_card[:-1])
def decode_card(card_str): """ Parse card for gameflow >>> decode_card('!10♡') (1, [10♡]) >>> decode_card('J♡;R') (0, [J♡], 'Rook') """ burned = 1 if card_str[0] == '!' else 0 if ';' in card_str: assert not burned col = decode_card_color(card_str[-3]) rank = card_str[:-3] if not burned else card_str[1:-3] jack_choice = card_str[-1] return (burned, [Card(col, rank)], nawaleta(jack_choice)) col = decode_card_color(card_str[-1]) rank = card_str[:-1] if not burned else card_str[1:-1] return (burned, [Card(col, rank)])
def get_move(self, ovr=None): """Second stage of a move: get a chess move.""" self.zamiana = False player = self.get_gracz(self.to_move) # after ace or king of spikes there is no move if not self.burned and (self.now_card.ran == 'A' or (self.now_card.ran == 'K' and self.now_card.kol == 1)): return [] w = self.what_happened() all_moves = self.possible_moves(self.to_move, self.capture, self.now_card, self.burned, w) if len(all_moves) == 0: return [] crd = self.now_card if not self.burned else Card(1, '5') move = player.choose_move(all_moves, self.plansza, crd) if ovr is None else ovr return move
from itertools import permutations import pytest from chessao import BLACK_COLOR, WHITE_COLOR from chessao.cards import Card from chessao.chess import Board, EMPTY from chessao.pieces import Pawn, ChessaoPieceException from chessao.helpers import get_mapdict DEFAULT_CARD = Card(1, '5') DEFAULT_BOARD = Board() MAPDICT = get_mapdict() def test_pawns_ineqaulity(): pieces_pairs = permutations([piece for piece in Board().pieces()], 2) for p1, p2 in pieces_pairs: assert p1 != p2 def test_pawn_moves(): black_pawn = Pawn(color=BLACK_COLOR, position=87) assert black_pawn.moves(DEFAULT_CARD, DEFAULT_BOARD) == [77, 67] white_pawn = Pawn(color=WHITE_COLOR, position=31) assert white_pawn.moves(DEFAULT_CARD, DEFAULT_BOARD) == [41, 51] def test_cant_move_on_wrong_tile(): black_pawn = Pawn(color=BLACK_COLOR, position=MAPDICT['D5']) assert DEFAULT_BOARD.get_piece('D5') == EMPTY
def possible_moves(self, color, okzbi=True, kar=Card(1, '5'), burned=False, flag=(0, )): """ Return a dict of possible moves. """ if burned: kar = Card(1, '5') d = {v: k for (k, v) in self.plansza.mapdict.items()} if flag[0] == 1: return {} elif flag[0] == 2: # king of spades a = [self.plansza.mapdict[flag[1][0]]] elif flag[0] == 3: # king of hearts a = [self.plansza.mapdict[flag[1]]] elif flag[0] == 4: # jack a = [ i for i in self.plansza.all_taken() if self.plansza[i].color == color and self.plansza[i].name == flag[1] ] elif kar.ran == 'Q' and len( self.plansza.positions_of_piece('Queen', color)) > 0: assert flag[0] == 0 if self.plansza.piece_types_left(color) != {'King', 'Queen'}: a = self.plansza.positions_of_piece('Queen', color) else: kar = Card(1, '5') a = [ i for i in self.plansza.all_taken() if self.plansza[i].color == color ] else: a = [ i for i in self.plansza.all_taken() if self.plansza[i].color == color ] res = {} for i in a: skad = d[i] if okzbi: gdzie = [ d[c] for c in self.plansza[i].moves(kar, self.plansza) if type(self.plansza[c]) != King ] else: gdzie = [ d[c] for c in self.plansza[i].moves(kar, self.plansza) if type(self.plansza[c]) != King and (self.plansza.is_empty(c) or self.plansza[c].color == color ) ] if flag[0] == 2: try: gdzie.remove(flag[1][1]) except Exception as e: raise ChessaoGameplayError( 'Error in remove! color:{} okzbi:{} karta:{} burned: {} flag {} gdzie: {} skad {} a: {}\n{}' .format(color, okzbi, kar, burned, flag, gdzie, skad, a, self.snapshot()), gameplay=self, errors=e) if len(gdzie) > 0: res[skad] = gdzie res2 = deepcopy(res) for key in res2: for where in res2[key]: try: pln = self.plansza.simulate_move(key, where, kar) except Exception as e: raise ChessaoGameplayError( '\n color: {} from {} to {} karta {}\nSNAPSHOT:{}'. format(color, key, where, kar, self.snapshot()), gameplay=self, errors=e) if pln.color_is_checked(color) == (True, color): res[key].remove(where) del pln final = {k: v for (k, v) in res.items() if v != []} return final
def move(self, pos_from, pos_to=None, card=Card(1, '5'), only_bool=False): """ Move a piece on a board. Args: pos_from (str): e.g. 'A2' pos_to (str): e.g. 'A4' card (Card): a Card that is played alongisde the move only_bool (bool): check if move is valid, don't change state >>> Board(fenrep='R3K2R/8/8/8/8/8/8/8').move('E1','C1') # roszada Board: 2KR3R/8/8/8/8/8/8/8 - - 1 0 >>> Board(fenrep='R3K2R/8/8/pP6/8/NnrRqQbB/8/7k KQ').move('E1','G1') # zła roszada Traceback (most recent call last): ... AssertionError: Move is not possible: E1 -> G1; R3K2R/8/8/pP6/8/NnrRqQbB/8/7k KQ - 0 0 >>> Board(fenrep='R3K2R/8/8/pP6/8/NnrRqQbB/8/7k KQ').move('E1','C1') #doctest: +ELLIPSIS Traceback (most recent call last): ... AssertionError: ... >>> Board(fenrep='K7/8/8/pP6/8/NnrRqQbB/8/r3k2r KQ').move('E8','C8') #doctest: +ELLIPSIS Traceback (most recent call last): ... AssertionError: ... >>> Board(fenrep='R3K2R/8/8/Q7/8/8/8/8').move('A4','A1', Card(1,'Q')) Board: Q3K2R/8/8/R7/8/8/8/8 K - 1 0 >>> Board(fenrep='R3K2R/8/8/P7/8/8/8/8').move('A4','A5', Card(1,'Q')) Board: R3K2R/8/8/8/P7/8/8/8 KQ - 0 0 >>> Board(fenrep='R3K2R/8/8/P7/q7/8/8/8').move('A5','A4', Card(1,'6')) Board: R3K2R/8/8/q7/8/8/8/8 KQ - 0 1 >>> Board(fenrep='R3K2R/8/8/P7/q7/8/1N6/8').move('B7','A5', Card(1,'6')) Board: R3K2R/8/8/P7/N7/8/8/8 KQ - 0 0 >>> b = Board() >>> b.move('D2','D4') Board: RNBQKBNR/PPP1PPPP/8/3P4/8/8/pppppppp/rnbqkbnr KQkq D3 0 0 >>> b.move('A7','A6') Board: RNBQKBNR/PPP1PPPP/8/3P4/8/p7/1ppppppp/rnbqkbnr KQkq - 0 1 >>> b.move('D4', 'D5') Board: RNBQKBNR/PPP1PPPP/8/8/3P4/p7/1ppppppp/rnbqkbnr KQkq - 0 1 >>> b.move('E7','E5') Board: RNBQKBNR/PPP1PPPP/8/8/3Pp3/p7/1ppp1ppp/rnbqkbnr KQkq E6 0 2 >>> b.move('D5','E6') Board: RNBQKBNR/PPP1PPPP/8/8/8/p3P3/1ppp1ppp/rnbqkbnr KQkq - 0 2 >>> b.move('A6','A5') Board: RNBQKBNR/PPP1PPPP/8/8/p7/4P3/1ppp1ppp/rnbqkbnr KQkq - 0 3 >>> b.move('A5', 'A4') Board: RNBQKBNR/PPP1PPPP/8/p7/8/4P3/1ppp1ppp/rnbqkbnr KQkq - 0 4 >>> b.move('B2','B4') Board: RNBQKBNR/P1P1PPPP/8/pP6/8/4P3/1ppp1ppp/rnbqkbnr KQkq B3 0 4 >>> b.move('A4','B3') Board: RNBQKBNR/P1P1PPPP/1p6/8/8/4P3/1ppp1ppp/rnbqkbnr KQkq - 0 5 >>> b.move('H2', 'H5', only_bool=True) Traceback (most recent call last): ... AssertionError: Move is not possible: H2 -> H5; RNBQKBNR/P1P1PPPP/1p6/8/8/4P3/1ppp1ppp/rnbqkbnr KQkq - 0 5 """ self.capture_took_place = False start_position_int = self.mapdict[pos_from] end_position_int = self.mapdict[pos_to] if self.is_empty(start_position_int): raise ValueError('There is no Piece in that field {}'.format(pos_from)) assert end_position_int in self[start_position_int].moves(card, self), \ f"Move is not possible: {pos_from} -> {pos_to}; {self.fen()}" # first check if the move is an enappsant one if self[start_position_int].name == 'Pawn': if self.enpass == end_position_int: return self._enpassant_move(start_position_int, end_position_int, only_bool) elif self[start_position_int].mvs_number == 0 and \ abs(start_position_int - end_position_int) == 20: # then set enpassant self.enpass = (start_position_int + end_position_int) / 2 else: self.enpass = 300 # checking for castle if all([card.ran != 'K' or card.kol not in (3, 4), self[start_position_int].name == 'King', abs(end_position_int - start_position_int) == 2]): return self._castle_move(start_position_int, end_position_int, only_bool) # checking for Queen card and valid Queen move enemy_pieces_left = self.piece_types_left(self[start_position_int].color) if all([card.ran == 'Q', self[start_position_int].name == 'Queen', enemy_pieces_left != {'King', 'Queen'}]): return self._queen_move(start_position_int, end_position_int, only_bool) else: # default move if only_bool: return True if self[start_position_int].name == 'Pawn': clock_value = 0 else: clock_value = 1 if not self.is_empty(end_position_int): self.capture_took_place = True clock_value = 0 self.captured_pieces.append(self[end_position_int]) self._move_piece(pos_from=start_position_int, pos_to=end_position_int) self._turn_clock(piece_color=end_position_int, clock=clock_value) return self raise ValueError( 'BŁĄD w funkcji move! skad {} dokad {} card {} mvs {}, enpas {}'.format( pos_from, pos_to, card, self[start_position_int].mvs_number, self.enpass))
def test_wrong_card(self): assert not self.gameplay.capture assert self.gameplay.to_move == BLACK_COLOR with pytest.raises(helpers.ChessaoGameplayError): self.gameplay.make_an_overriden_move_in_one_func( card=(0, [Card(1, '5')]), move=['A7', 'A6'])