void PrintBoard(const S_BOARD *pos){ int sq,file,rank,piece; printf("\nGame Board:\n\n"); for(rank = RANK_8; rank >= RANK_1; rank--){ printf("%d ",rank+1); for(file = FILE_A; file <= FILE_H; file++){ sq = FR2SQ(file,rank); piece = pos->pieces[sq]; printf("%3c", PceChar[piece]); } printf("\n"); } printf("\n "); for(file = FILE_A; file <= FILE_H; file++){ printf("%3c",'a'+file); } printf("\n"); printf("side:%c\n",SideChar[pos->side]); printf("enPas:%d\n",pos->enPas); printf("castle:%c%c%c%c\n", pos->castlePerm&WKCA?'K':'-', pos->castlePerm&WQCA?'Q':'-', pos->castlePerm&BKCA?'k':'-', pos->castlePerm&BQCA?'q':'-' ); printf("PosKey:%llX\n",pos->posKey); }
// Prints a formatted version of the game board into the console window. inline void printBoard(const S_BOARD *pos) { static const char *temp = " +---+---+---+---+---+---+---+---+"; printf("\n============================ GAME BOARD " "============================\n\n"); printf(" a b c d e f g h\n"); printf("%s\n", temp); for (unsigned rank = RANK_8; rank != (unsigned)(RANK_1 - 1); rank--) { printf(" %c | ", '1' + rank); for (unsigned file = FILE_A; file <= FILE_H; file++) { const unsigned piece = pos->pieces[FR2SQ(file, rank)]; ASSERT(pieceValidEmpty(piece)); printf("%c | ", pieceChar[piece]); } printf("%c", '1' + rank); switch (rank) { case RANK_8: printf(" DROPPABLE PIECES\n%s +---+---+---+---+---+\n", temp); break; case RANK_7: printf(" | P | N | B | R | Q |"); printf("\n%s +---+---+---+---+---+---+\n", temp); break; case RANK_6: printf(" | W | %d | %d | %d | %d | %d |", pos->dropNum[wP], pos->dropNum[wN], pos->dropNum[wB], pos->dropNum[wR], pos->dropNum[wQ]); printf("\n%s +---+---+---+---+---+---+\n", temp); break; case RANK_5: printf(" | B | %d | %d | %d | %d | %d |", pos->dropNum[bP], pos->dropNum[bN], pos->dropNum[bB], pos->dropNum[bR], pos->dropNum[bQ]); printf("\n%s +---+---+---+---+---+---+\n", temp); break; default: printf("\n%s\n", temp); break; } } printf(" a b c d e f g h\n\n"); ASSERT(sideValid(pos->side)); if (pos->hisPly > 0) { printf(" LAST MOVE: %s\n", printMove(pos->history[pos->hisPly - 1]->move)); } else { printf(" LAST MOVE: NONE\n"); } printf(" SIDE TO MOVE: %s\n", pos->side == WHITE ? "WHITE" : "BLACK"); printf(" EN PASSANT SQUARE: %s\n", printSquare(pos->enPas)); printf(" CASTLING PERMISSIONS: %c%c%c%c\n", pos->castlePerm & WKCA ? 'K' : '-', pos->castlePerm & WQCA ? 'Q' : '-', pos->castlePerm & BKCA ? 'k' : '-', pos->castlePerm & BQCA ? 'q' : '-'); printf(" HASHKEY: %llX\n", pos->posKey); printf(" FEN: '%s'\n", printFEN(pos)); printf("\n========================== END GAME BOARD " "==========================\n\n"); }
int ParseMove(char *ptrChar, CHESS_BOARD *pos) { ASSERT(CheckBoard(pos)); if (ptrChar[1] > '8' || ptrChar[1] < '1') return NOMOVE; if (ptrChar[3] > '8' || ptrChar[3] < '1') return NOMOVE; if (ptrChar[0] > 'h' || ptrChar[0] < 'a') return NOMOVE; if (ptrChar[2] > 'h' || ptrChar[2] < 'a') return NOMOVE; int from = FR2SQ(ptrChar[0] - 'a', ptrChar[1] - '1'); int to = FR2SQ(ptrChar[2] - 'a', ptrChar[3] - '1'); ASSERT(SqOnBoard(from) && SqOnBoard(to)); MOVELIST list[1]; GenerateAllMoves(pos, list); int MoveNum = 0; int Move = 0; int PromPce = EMPTY; for (MoveNum = 0; MoveNum < list->count; ++MoveNum) { Move = list->moves[MoveNum].move; if (FROMSQ(Move) == from && TOSQ(Move) == to) { PromPce = PROMOTED(Move); if (PromPce != EMPTY) { if (IsRQ(PromPce) && !IsBQ(PromPce) && ptrChar[4] == 'r') { return Move; } else if (!IsRQ(PromPce) && IsBQ(PromPce) && ptrChar[4] == 'b') { return Move; } else if (IsRQ(PromPce) && IsBQ(PromPce) && ptrChar[4] == 'q') { return Move; } else if (IsKn(PromPce) && ptrChar[4] == 'n') { return Move; } continue; } return Move; } } return NOMOVE; }
inline const char *printFEN(const S_BOARD *pos) { int emptyCount = 0; int strIndex = 0; static char result[256]; for (int rank = RANK_8; rank >= RANK_1; rank--) { for (int file = FILE_A; file <= FILE_H; file++) { int sq120 = FR2SQ(file, rank); int piece = pos->pieces[sq120]; if (piece == EMPTY) { emptyCount++; } else { if (emptyCount != 0) { result[strIndex++] = '0' + emptyCount; emptyCount = 0; } result[strIndex++] = pieceChar[piece]; } } if (emptyCount != 0) { result[strIndex++] = '0' + emptyCount; emptyCount = 0; } if (rank != RANK_1) { result[strIndex++] = '/'; } } strIndex += sprintf(result + strIndex, " %c ", pos->side == WHITE ? 'w' : 'b'); if (pos->castlePerm == 0) { result[strIndex++] = '-'; } else { if (pos->castlePerm & WKCA) result[strIndex++] = 'K'; if (pos->castlePerm & WQCA) result[strIndex++] = 'Q'; if (pos->castlePerm & BKCA) result[strIndex++] = 'k'; if (pos->castlePerm & BQCA) result[strIndex++] = 'q'; } // TODO: Check if pos->hisPly / 2 + 1 is the correct formula strIndex += sprintf(result + strIndex, " %s %d %d", printSquare(pos->enPas), pos->fiftyMove, pos->hisPly / 2 + 1); ASSERT(strIndex < 256); return result; }
inline void init() { // Initialize the index converting arrays. unsigned sq64 = 0, sq; // Initialize the bit masks. U64 mask = 1ULL; for (unsigned i = 0; i < 64; i++) { setMask[i] = mask; clearMask[i] = ~mask; mask <<= 1; } // Initialize the hashkey masks to 64-bit random numbers. for (unsigned i = 0; i < 13; i++) for (unsigned j = 0; j < 120; j++) pieceKeys[i][j] = RAND_64; sideKey = RAND_64; for (unsigned i = 0; i < 16; i++) castleKeys[i] = RAND_64; for (unsigned i = 0; i < 13; i++) for (unsigned j = 0; j < 8; j++) dropKeys[i][j] = RAND_64; // Initializes the file and rank lookup tables. for (unsigned i = 0; i < 120; i++) { fileBoard[i] = OFFBOARD; rankBoard[i] = OFFBOARD; SQ64[i] = 65; } for (unsigned i = 0; i < 64; i++) SQ120[i] = 120; for (unsigned rank = RANK_1; rank <= RANK_8; rank++) { for (unsigned file = FILE_A; file <= FILE_H; file++) { sq = FR2SQ(file, rank); SQ120[sq64] = sq; SQ64[sq] = sq64++; fileBoard[sq] = file; rankBoard[sq] = rank; } } }
int ParseFen(char *fen, S_BOARD *pos){ int rank = RANK_8; int file = FILE_A; int piece = 0; int count = 0; int i = 0; int sq64 = 0; int sq120 = 0; ASSERT(fen!=NULL); ASSERT(pos!=NULL); ResetBoard(pos); while(( rank >= RANK_1) && *fen){ count = 1; switch(*fen){ case 'p': piece = bP; break; case 'r': piece = bR; break; case 'n': piece = bN; break; case 'b': piece = bB; break; case 'k': piece = bK; break; case 'q': piece = bQ; break; case 'P': piece = wP; break; case 'R': piece = wR; break; case 'N': piece = wN; break; case 'B': piece = wB; break; case 'K': piece = wK; break; case 'Q': piece = wQ; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': piece = EMPTY; count = *fen - '0'; break; case '/': case ' ': rank--; file = FILE_A; fen++; continue; default: printf("FEN error \n"); return -1; } for(i = 0; i < count; i++){ sq64 = rank * 8 + file; sq120 = SQ120(sq64); if(piece != EMPTY){ pos->pieces[sq120] = piece; } file++; } fen++; } ASSERT(*fen == 'w' || *fen == 'b'); pos->side = (*fen == 'w') ? WHITE : BLACK; fen += 2; for(i = 0; i < 4; i++){ if(*fen == ' '){ break; } switch(*fen){ case 'K': pos->castlePerm |= WKCA; break; case 'Q': pos->castlePerm |= WQCA; break; case 'k': pos->castlePerm |= BKCA; break; case 'q': pos->castlePerm |= BQCA; break; default: break; } fen++; } fen++; ASSERT(pos->castlePerm>=0 && pos->castlePerm <= 15); if(*fen != '-'){ file = fen[0] - 'a'; rank = fen[1] - '1'; ASSERT(file>=FILE_A && file <= FILE_H); ASSERT(rank>=RANK_1 && rank <= RANK_8); pos->enPas = FR2SQ(file,rank); } pos->posKey = GeneratePosKey(pos); return 0; }