move_t ChessBoard_unmakeMove(ChessBoard* self){ GameInfo* info = (GameInfo*)self->extra; assert(info->movesCount!=0); move_t move = info->moves[info->movesCount-1]; BoardBackup* backup = &(info->backups[--(info->movesCount)]); int meta = GET_META(move); location_t from = GET_FROM(move); location_t to = GET_TO(move); //unmove the key piece __movePieceByLoc(self, to, from); //unpromote pawn if(meta&PROMOTION_MOVE_FLAG){ ChessPiece* piece = self->squares[from]; __removePiece(self, piece); piece->type=PAWN; __addPiece(self, piece); } //uncapture piece if(meta&CAPTURE_MOVE_FLAG) __uncapturePiece(self); //uncastle else if(meta==KING_CASTLE_MOVE){ int rank = GET_RANK(from); __movePieceByLoc(self, RANK_FILE(rank, 5), RANK_FILE(rank, 7)); } else if(meta==QUEEN_CASTLE_MOVE){ int rank = GET_RANK(from); __movePieceByLoc(self, RANK_FILE(rank, 3), RANK_FILE(rank, 0)); } //restore flags and hash self->flags = backup->flags; self->hash = backup->hash; self->fiftyMoveCount = backup->fiftyMoveCount; return move; }
PyObject* PyCOMPSPack_strget_(PyCOMPS_Package *self, void *closure) { char *tmp = GET_FROM(self->package, (size_t)closure); return PyUnicode_FromString(tmp); }
void ChessBoard_makeMove(ChessBoard* self, move_t move){ //push the move onto the move stack GameInfo* info = (GameInfo*)self->extra; BoardBackup* backup = &(info->backups[info->movesCount]); backup->hash = self->hash; backup->flags = self->flags; backup->fiftyMoveCount = self->fiftyMoveCount; info->moves[info->movesCount++] = move; if(self->flags&TO_PLAY_FLAG) //black self->fiftyMoveCount++; __toggleToPlay(self); __clearEnPassantFlags(self); int meta = GET_META(move); location_t from = GET_FROM(move); location_t to = GET_TO(move); if((self->squares[from]->type==PAWN) || (meta&CAPTURE_MOVE_FLAG)) self->fiftyMoveCount=0; int rank, file; //do special moves switch(meta){ case DOUBLE_PAWN_PUSH_MOVE: __setEnPassantFlags(self, GET_FILE(to)); break; case KING_CASTLE_MOVE: case QUEEN_CASTLE_MOVE: rank = GET_RANK(from); if(meta==KING_CASTLE_MOVE) __movePieceByLoc(self, RANK_FILE(rank, 7), RANK_FILE(rank, 5)); else __movePieceByLoc(self, RANK_FILE(rank, 0), RANK_FILE(rank, 3)); if(rank==0){//white __unsetCastleFlag(self, WHITE_KING_CASTLE_FLAG); __unsetCastleFlag(self, WHITE_QUEEN_CASTLE_FLAG); } else{//black __unsetCastleFlag(self, BLACK_KING_CASTLE_FLAG); __unsetCastleFlag(self, BLACK_QUEEN_CASTLE_FLAG); } break; case EN_PASSANT_MOVE: rank = GET_RANK(from); file = GET_FILE(to); __capturePiece(self, self->squares[RANK_FILE(rank,file)]); break; default: if(meta&CAPTURE_MOVE_FLAG){ ChessPiece* captured = self->squares[to]; __capturePiece(self, captured); if(captured->type==ROOK){ switch(to){ case WHITE_QUEEN_ROOK_START: __unsetCastleFlag(self, WHITE_QUEEN_CASTLE_FLAG); break; case WHITE_KING_ROOK_START: __unsetCastleFlag(self, WHITE_KING_CASTLE_FLAG); break; case BLACK_QUEEN_ROOK_START: __unsetCastleFlag(self, BLACK_QUEEN_CASTLE_FLAG); break; case BLACK_KING_ROOK_START: __unsetCastleFlag(self, BLACK_KING_CASTLE_FLAG); break; } } } if(meta&PROMOTION_MOVE_FLAG){ ChessPiece* piece = self->squares[from]; __removePiece(self, piece); switch(meta&PROMOTION_MASK){ case QUEEN_PROMOTION: piece->type=QUEEN; break; case ROOK_PROMOTION: piece->type=ROOK; break; case KNIGHT_PROMOTION: piece->type=KNIGHT; break; case BISHOP_PROMOTION: piece->type=BISHOP; break; default: assert(0); } __addPiece(self, piece); } } if(meta==0 || meta==CAPTURE_MOVE_FLAG){ switch(from){ case WHITE_QUEEN_ROOK_START: __unsetCastleFlag(self, WHITE_QUEEN_CASTLE_FLAG); break; case WHITE_KING_ROOK_START: __unsetCastleFlag(self, WHITE_KING_CASTLE_FLAG); break; case WHITE_KING_START: __unsetCastleFlag(self, WHITE_QUEEN_CASTLE_FLAG); __unsetCastleFlag(self, WHITE_KING_CASTLE_FLAG); break; case BLACK_QUEEN_ROOK_START: __unsetCastleFlag(self, BLACK_QUEEN_CASTLE_FLAG); break; case BLACK_KING_ROOK_START: __unsetCastleFlag(self, BLACK_KING_CASTLE_FLAG); break; case BLACK_KING_START: __unsetCastleFlag(self, BLACK_QUEEN_CASTLE_FLAG); __unsetCastleFlag(self, BLACK_KING_CASTLE_FLAG); break; } } __movePieceByLoc(self, from, to); }
void toAlgebraicNotation(move_t move, ChessBoard* board, char* out, int* outSize){ location_t from = GET_FROM(move); location_t to = GET_TO(move); int meta = GET_META(move); int i = 0; ChessBoard_makeMove(board, move); int isInCheck = ChessBoard_testForCheck(board); ChessMoveGenerator* gen = ChessMoveGenerator_new(board); ChessMoveGenerator_generateMoves(gen, isInCheck, NULL); int isInCheckmate = isInCheck&&(gen->nextCount==0); ChessBoard_unmakeMove(board); ChessMoveGenerator_generateMoves(gen, ChessBoard_testForCheck(board), NULL); if(meta==KING_CASTLE_MOVE){ char* notation = "O-O"; for(i = 0; i < 3; i++) out[i] = notation[i]; } else if(meta==QUEEN_CASTLE_MOVE){ char* notation = "O-O-O"; for(i = 0; i < 5; i++) out[i] = notation[i]; } else{ //write piece indicator ChessPiece* piece = board->squares[from]; if(piece->type==KING) out[i++] = 'K'; else{ //for each other move, //check to see if there are multiple pieces //of this piece's type that can move to the 'to' square. int j; move_t otherMoves[20]; int otherMovesCount = 0; move_t otherMove; for(j = 0; j < gen->nextCount; j++){ otherMove = gen->next[j]; if((GET_TO(otherMove)==to) && (GET_FROM(otherMove)!=from) && (board->squares[GET_FROM(otherMove)]->type== piece->type)){ if(piece->type==PAWN && (move&CAPTURE_MOVE_FLAG)!= (otherMove&CAPTURE_MOVE_FLAG)) continue; if(otherMove==move) continue; otherMoves[otherMovesCount++] = otherMove; } } //note if there are multiple moves //from the same rank or file int sameRank = 0, sameFile = 0; for(j = 0; j < otherMovesCount; j++){ otherMove = otherMoves[j]; if(GET_RANK(from)==GET_RANK(GET_FROM(otherMove))) sameRank = 1; if(GET_FILE(from)==GET_FILE(GET_FROM(otherMove))) sameFile = 1; } if(piece->type!=PAWN) out[i++] = __pieceTypeToChar(piece->type); else if(meta&CAPTURE_MOVE_FLAG) out[i++] = __fileToChar(GET_FILE(from)); if(piece->type!=PAWN && otherMovesCount){ if(!sameFile) out[i++] = __fileToChar(GET_FILE(from)); else if(!sameRank) out[i++] = __rankToChar(GET_RANK(from)); else{ out[i++] = __fileToChar(GET_FILE(from)); out[i++] = __rankToChar(GET_RANK(from)); } } } //if capture if(meta&CAPTURE_MOVE_FLAG) out[i++] = 'x'; //write destination out[i++] = __fileToChar(GET_FILE(to)); out[i++] = __rankToChar(GET_RANK(to)); if(meta&PROMOTION_MOVE_FLAG){ out[i++] = '='; switch(meta&PROMOTION_MASK){ case KNIGHT_PROMOTION: out[i++] = 'N'; break; case BISHOP_PROMOTION: out[i++] = 'B'; break; case ROOK_PROMOTION: out[i++] = 'R'; break; case QUEEN_PROMOTION: out[i++] = 'Q'; break; default: assert(0); } } } if(isInCheckmate) out[i++] = '#'; else if(isInCheck) out[i++] = '+'; out[i] = '\0'; (*outSize) = i; ChessMoveGenerator_delete(gen); }