def applyMove(self, move): flag = move >> 12 fcord = (move >> 6) & 63 tcord = move & 63 fpiece = fcord if flag == DROP else self.arBoard[fcord] tpiece = self.arBoard[tcord] color = self.color opcolor = 1 - self.color castling = self.castling self.hist_move.append(move) self.hist_enpassant.append(self.enpassant) self.hist_castling.append(self.castling) self.hist_hash.append(self.hash) self.hist_fifty.append(self.fifty) self.hist_checked.append(self.checked) self.hist_opchecked.append(self.opchecked) if self.variant in DROP_VARIANTS: self.hist_capture_promoting.append(self.capture_promoting) if self.variant == CAMBODIANCHESS: self.hist_is_first_move.append({ KING: self.is_first_move[KING][:], QUEEN: self.is_first_move[QUEEN][:] }) self.opchecked = None self.checked = None if flag == NULL_MOVE: self.setColor(opcolor) self.plyCount += 1 return move if self.variant == CAMBODIANCHESS: if fpiece == KING and self.is_first_move[KING][color]: self.is_first_move[KING][color] = False elif fpiece == QUEEN and self.is_first_move[QUEEN][color]: self.is_first_move[QUEEN][color] = False # Castling moves can be represented strangely, so normalize them. if flag in (KING_CASTLE, QUEEN_CASTLE): side = flag - QUEEN_CASTLE fpiece = KING tpiece = EMPTY # In FRC, there may be a rook there, but the king doesn't capture it. fcord = self.ini_kings[color] if FILE(fcord) == 3 and self.variant in (WILDCASTLECHESS, WILDCASTLESHUFFLECHESS): side = 0 if side == 1 else 1 tcord = self.fin_kings[color][side] rookf = self.ini_rooks[color][side] rookt = self.fin_rooks[color][side] # Capture (sittuyin in place promotion is not capture move!) if tpiece != EMPTY and fcord != tcord: self._removePiece(tcord, tpiece, opcolor) self.pieceCount[opcolor][tpiece] -= 1 if self.variant in DROP_VARIANTS: if self.promoted[tcord]: if self.variant == CRAZYHOUSECHESS: self.holding[color][PAWN] += 1 self.hash ^= holdingHash[color][PAWN][ self.holding[color][PAWN]] self.capture_promoting = True else: if self.variant == CRAZYHOUSECHESS: self.holding[color][tpiece] += 1 self.hash ^= holdingHash[color][tpiece][ self.holding[color][tpiece]] self.capture_promoting = False elif self.variant == ATOMICCHESS: from pychess.Variants.atomic import piecesAround apieces = [ (fcord, fpiece, color), ] for acord, apiece, acolor in piecesAround(self, tcord): if apiece != PAWN and acord != fcord: self._removePiece(acord, apiece, acolor) self.pieceCount[acolor][apiece] -= 1 apieces.append((acord, apiece, acolor)) if apiece == ROOK and acord != fcord: if acord == self.ini_rooks[opcolor][0]: castling &= ~CAS_FLAGS[opcolor][0] elif acord == self.ini_rooks[opcolor][1]: castling &= ~CAS_FLAGS[opcolor][1] self.hist_exploding_around.append(apieces) self.hist_tpiece.append(tpiece) # Remove moving piece(s), then add them at their destination. if flag == DROP: if self.variant in DROP_VARIANTS: assert self.holding[color][fpiece] > 0 self.holding[color][fpiece] -= 1 self.hash ^= holdingHash[color][fpiece][self.holding[color] [fpiece]] self.pieceCount[color][fpiece] += 1 else: self._removePiece(fcord, fpiece, color) if flag in (KING_CASTLE, QUEEN_CASTLE): self._removePiece(rookf, ROOK, color) self._addPiece(rookt, ROOK, color) self.hasCastled[color] = True if flag == ENPASSANT: takenPawnC = tcord + (color == WHITE and -8 or 8) self._removePiece(takenPawnC, PAWN, opcolor) self.pieceCount[opcolor][PAWN] -= 1 if self.variant == CRAZYHOUSECHESS: self.holding[color][PAWN] += 1 self.hash ^= holdingHash[color][PAWN][self.holding[color] [PAWN]] elif self.variant == ATOMICCHESS: from pychess.Variants.atomic import piecesAround apieces = [ (fcord, fpiece, color), ] for acord, apiece, acolor in piecesAround(self, tcord): if apiece != PAWN and acord != fcord: self._removePiece(acord, apiece, acolor) self.pieceCount[acolor][apiece] -= 1 apieces.append((acord, apiece, acolor)) self.hist_exploding_around.append(apieces) elif flag in PROMOTIONS: # Pretend the pawn changes into a piece before reaching its destination. fpiece = flag - 2 self.pieceCount[color][fpiece] += 1 self.pieceCount[color][PAWN] -= 1 if self.variant in DROP_VARIANTS: if tpiece == EMPTY: self.capture_promoting = False if flag in PROMOTIONS: self.promoted[tcord] = 1 elif flag != DROP: if self.promoted[fcord]: self.promoted[fcord] = 0 self.promoted[tcord] = 1 elif tpiece != EMPTY: self.promoted[tcord] = 0 if self.variant == ATOMICCHESS and (tpiece != EMPTY or flag == ENPASSANT): self.pieceCount[color][fpiece] -= 1 else: self._addPiece(tcord, fpiece, color) if fpiece == PAWN and abs(fcord - tcord) == 16: self.setEnpassant((fcord + tcord) // 2) else: self.setEnpassant(None) if tpiece == EMPTY and fpiece != PAWN: self.fifty += 1 else: self.fifty = 0 # Clear castle flags king = self.ini_kings[color] wildcastle = FILE(king) == 3 and self.variant in ( WILDCASTLECHESS, WILDCASTLESHUFFLECHESS) if fpiece == KING: castling &= ~CAS_FLAGS[color][0] castling &= ~CAS_FLAGS[color][1] elif fpiece == ROOK: if fcord == self.ini_rooks[color][0]: side = 1 if wildcastle else 0 castling &= ~CAS_FLAGS[color][side] elif fcord == self.ini_rooks[color][1]: side = 0 if wildcastle else 1 castling &= ~CAS_FLAGS[color][side] if tpiece == ROOK: if tcord == self.ini_rooks[opcolor][0]: side = 1 if wildcastle else 0 castling &= ~CAS_FLAGS[opcolor][side] elif tcord == self.ini_rooks[opcolor][1]: side = 0 if wildcastle else 1 castling &= ~CAS_FLAGS[opcolor][side] self.setCastling(castling) self.setColor(opcolor) self.plyCount += 1
def applyMove (self, move): flag = move >> 12 fcord = (move >> 6) & 63 tcord = move & 63 fpiece = fcord if flag==DROP else self.arBoard[fcord] tpiece = self.arBoard[tcord] color = self.color opcolor = 1-self.color castling = self.castling self.hist_move.append(move) self.hist_enpassant.append(self.enpassant) self.hist_castling.append(self.castling) self.hist_hash.append(self.hash) self.hist_fifty.append(self.fifty) self.hist_checked.append(self.checked) self.hist_opchecked.append(self.opchecked) if self.variant in DROP_VARIANTS: self.hist_capture_promoting.append(self.capture_promoting) if self.variant == CAMBODIANCHESS: self.hist_is_first_move.append({KING: self.is_first_move[KING][:], \ QUEEN: self.is_first_move[QUEEN][:]}) self.opchecked = None self.checked = None if flag == NULL_MOVE: self.setColor(opcolor) self.plyCount += 1 return move if self.variant == CAMBODIANCHESS: if fpiece == KING and self.is_first_move[KING][color]: self.is_first_move[KING][color] = False elif fpiece == QUEEN and self.is_first_move[QUEEN][color]: self.is_first_move[QUEEN][color] = False # Castling moves can be represented strangely, so normalize them. if flag in (KING_CASTLE, QUEEN_CASTLE): side = flag - QUEEN_CASTLE fpiece = KING tpiece = EMPTY # In FRC, there may be a rook there, but the king doesn't capture it. fcord = self.ini_kings[color] if FILE(fcord) == 3 and self.variant in (WILDCASTLECHESS, WILDCASTLESHUFFLECHESS): side = 0 if side == 1 else 1 tcord = self.fin_kings[color][side] rookf = self.ini_rooks[color][side] rookt = self.fin_rooks[color][side] # Capture (sittuyin in place promotion is not capture move!) if tpiece != EMPTY and fcord != tcord: self._removePiece(tcord, tpiece, opcolor) self.pieceCount[opcolor][tpiece] -= 1 if self.variant in DROP_VARIANTS: if self.promoted[tcord]: if self.variant == CRAZYHOUSECHESS: self.holding[color][PAWN] += 1 self.capture_promoting = True else: if self.variant == CRAZYHOUSECHESS: self.holding[color][tpiece] += 1 self.capture_promoting = False elif self.variant == ATOMICCHESS: from pychess.Variants.atomic import piecesAround apieces = [(fcord, fpiece, color),] for acord, apiece, acolor in piecesAround(self, tcord): if apiece != PAWN and acord != fcord: self._removePiece(acord, apiece, acolor) self.pieceCount[acolor][apiece] -= 1 apieces.append((acord, apiece, acolor)) if apiece == ROOK and acord != fcord: if acord == self.ini_rooks[opcolor][0]: castling &= ~CAS_FLAGS[opcolor][0] elif acord == self.ini_rooks[opcolor][1]: castling &= ~CAS_FLAGS[opcolor][1] self.hist_exploding_around.append(apieces) self.hist_tpiece.append(tpiece) # Remove moving piece(s), then add them at their destination. if flag == DROP: if self.variant in DROP_VARIANTS: assert self.holding[color][fpiece] > 0 self.holding[color][fpiece] -= 1 self.pieceCount[color][fpiece] += 1 else: self._removePiece(fcord, fpiece, color) if flag in (KING_CASTLE, QUEEN_CASTLE): self._removePiece (rookf, ROOK, color) self._addPiece (rookt, ROOK, color) self.hasCastled[color] = True if flag == ENPASSANT: takenPawnC = tcord + (color == WHITE and -8 or 8) self._removePiece (takenPawnC, PAWN, opcolor) self.pieceCount[opcolor][PAWN] -= 1 if self.variant == CRAZYHOUSECHESS: self.holding[color][PAWN] += 1 elif self.variant == ATOMICCHESS: from pychess.Variants.atomic import piecesAround apieces = [(fcord, fpiece, color),] for acord, apiece, acolor in piecesAround(self, tcord): if apiece != PAWN and acord != fcord: self._removePiece(acord, apiece, acolor) self.pieceCount[acolor][apiece] -= 1 apieces.append((acord, apiece, acolor)) self.hist_exploding_around.append(apieces) elif flag in PROMOTIONS: # Pretend the pawn changes into a piece before reaching its destination. fpiece = flag - 2 self.pieceCount[color][fpiece] += 1 self.pieceCount[color][PAWN] -=1 if self.variant in DROP_VARIANTS: if tpiece == EMPTY: self.capture_promoting = False if flag in PROMOTIONS: self.promoted[tcord] = 1 elif flag != DROP: if self.promoted[fcord]: self.promoted[fcord] = 0 self.promoted[tcord] = 1 elif tpiece != EMPTY: self.promoted[tcord] = 0 if self.variant == ATOMICCHESS and (tpiece != EMPTY or flag == ENPASSANT): self.pieceCount[color][fpiece] -= 1 else: self._addPiece(tcord, fpiece, color) if fpiece == PAWN and abs(fcord-tcord) == 16: self.setEnpassant ((fcord + tcord) // 2) else: self.setEnpassant (None) if tpiece == EMPTY and fpiece != PAWN: self.fifty += 1 else: self.fifty = 0 # Clear castle flags king = self.ini_kings[color] wildcastle = FILE(king) == 3 and self.variant in (WILDCASTLECHESS, WILDCASTLESHUFFLECHESS) if fpiece == KING: castling &= ~CAS_FLAGS[color][0] castling &= ~CAS_FLAGS[color][1] elif fpiece == ROOK: if fcord == self.ini_rooks[color][0]: side = 1 if wildcastle else 0 castling &= ~CAS_FLAGS[color][side] elif fcord == self.ini_rooks[color][1]: side = 0 if wildcastle else 1 castling &= ~CAS_FLAGS[color][side] if tpiece == ROOK: if tcord == self.ini_rooks[opcolor][0]: side = 1 if wildcastle else 0 castling &= ~CAS_FLAGS[opcolor][side] elif tcord == self.ini_rooks[opcolor][1]: side = 0 if wildcastle else 1 castling &= ~CAS_FLAGS[opcolor][side] self.setCastling(castling) self.setColor(opcolor) self.plyCount += 1