static void AddEnPassantMove(const CHESS_BOARD *pos, int move, MOVELIST *list) { ASSERT(SqOnBoard(FROMSQ(move))); ASSERT(SqOnBoard(TOSQ(move))); ASSERT(CheckBoard(pos)); ASSERT((RanksBrd[TOSQ(move)] == RANK_6 && pos->side == WHITE) || (RanksBrd[TOSQ(move)] == RANK_3 && pos->side == BLACK)); list->moves[list->count].move = move; list->moves[list->count].score = 105 + 1000000; list->count++; }
static void AddCaptureMove(const CHESS_BOARD *pos, int move, MOVELIST *list) { ASSERT(SqOnBoard(FROMSQ(move))); ASSERT(SqOnBoard(TOSQ(move))); ASSERT(PieceValid(CAPTURED(move))); ASSERT(CheckBoard(pos)); list->moves[list->count].move = move; list->moves[list->count].score = MvvLvaScores[CAPTURED(move)][pos->pieces[FROMSQ(move)]] + 1000000; list->count++; }
static void AddBlackPawnMove(const S_BOARD *pos, const int from, const int to, S_MOVELIST *list) { ASSERT(SqOnBoard(from)); ASSERT(SqOnBoard(to)); if(RanksBrd[from] == RANK_2) { AddQuietMove(pos, MOVE(from, to, EMPTY, bQ, 0), list); AddQuietMove(pos, MOVE(from, to, EMPTY, bR, 0), list); AddQuietMove(pos, MOVE(from, to, EMPTY, bB, 0), list); AddQuietMove(pos, MOVE(from, to, EMPTY, bN, 0), list); } else { AddQuietMove(pos, MOVE(from, to, EMPTY, EMPTY, 0), list); } }
static void AddWhitePawnCapMove(const S_BOARD *pos, const int from, const int to, const int cap, S_MOVELIST *list) { ASSERT(PieceValidEmpty(cap)); ASSERT(SqOnBoard(from)); ASSERT(SqOnBoard(to)); if(RanksBrd[from] == RANK_7) { AddCaptureMove(pos, MOVE(from, to, cap, wQ, 0), list); AddCaptureMove(pos, MOVE(from, to, cap, wR, 0), list); AddCaptureMove(pos, MOVE(from, to, cap, wB, 0), list); AddCaptureMove(pos, MOVE(from, to, cap, wN, 0), list); } else { AddCaptureMove(pos, MOVE(from, to, cap, EMPTY, 0), list); } }
static void AddWhitePawnMove(const CHESS_BOARD *pos, const int from, const int to, MOVELIST *list) { ASSERT(SqOnBoard(from)); ASSERT(SqOnBoard(to)); ASSERT(CheckBoard(pos)); if (RanksBrd[from] == RANK_7) { AddQuietMove(pos, MOVE(from, to, EMPTY, wQ, 0), list); AddQuietMove(pos, MOVE(from, to, EMPTY, wR, 0), list); AddQuietMove(pos, MOVE(from, to, EMPTY, wB, 0), list); AddQuietMove(pos, MOVE(from, to, EMPTY, wN, 0), list); } else { AddQuietMove(pos, MOVE(from, to, EMPTY, EMPTY, 0), list); } }
static void AddBlackPawnCapMove(const CHESS_BOARD *pos, const int from, const int to, const int cap, MOVELIST *list) { ASSERT(PieceValidEmpty(cap)); ASSERT(SqOnBoard(from)); ASSERT(SqOnBoard(to)); ASSERT(CheckBoard(pos)); if (RanksBrd[from] == RANK_2) { AddCaptureMove(pos, MOVE(from, to, cap, bQ, 0), list); AddCaptureMove(pos, MOVE(from, to, cap, bR, 0), list); AddCaptureMove(pos, MOVE(from, to, cap, bB, 0), list); AddCaptureMove(pos, MOVE(from, to, cap, bN, 0), list); } else { AddCaptureMove(pos, MOVE(from, to, cap, EMPTY, 0), list); } }
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; }
static void AddQuietMove(const CHESS_BOARD *pos, int move, MOVELIST *list) { ASSERT(SqOnBoard(FROMSQ(move))); ASSERT(SqOnBoard(TOSQ(move))); ASSERT(CheckBoard(pos)); ASSERT(pos->ply >= 0 && pos->ply < MAXDEPTH); list->moves[list->count].move = move; if (pos->searchKillers[0][pos->ply] == move) { list->moves[list->count].score = 900000; } else if (pos->searchKillers[1][pos->ply] == move) { list->moves[list->count].score = 800000; } else { list->moves[list->count].score = pos->searchHistory[pos->pieces[FROMSQ(move)]][TOSQ(move)]; } list->count++; }
int MoveListOk(const S_MOVELIST *list, const S_BOARD *pos) { if(list->count < 0 || list->count >= MAXPOSITIONMOVES) { return FALSE; } int MoveNum; int from = 0; int to = 0; for(MoveNum = 0; MoveNum < list->count; ++MoveNum) { to = TOSQ(list->moves[MoveNum].move); from = FROMSQ(list->moves[MoveNum].move); if(!SqOnBoard(to) || !SqOnBoard(from)) { return FALSE; } if(!PieceValid(pos->pieces[from])) { PrintBoard(pos); return FALSE; } } return TRUE; }
int PceListOk(const S_BOARD *pos) { int pce = wP; int sq; int num; for(pce = wP; pce <= bK; ++pce) { if(pos->pceNum[pce]<0 || pos->pceNum[pce]>=10) return FALSE; } if(pos->pceNum[wK]!=1 || pos->pceNum[bK]!=1) return FALSE; for(pce = wP; pce <= bK; ++pce) { for(num = 0; num < pos->pceNum[pce]; ++num) { sq = pos->pList[pce][num]; if(!SqOnBoard(sq)) return FALSE; } } return TRUE; }
void GenerateAllCaps(const CHESS_BOARD *pos, MOVELIST *list) { ASSERT(CheckBoard(pos)); list->count = 0; int pce = EMPTY; int side = pos->side; int sq = 0; int t_sq = 0; int pceNum = 0; int dir = 0; int index = 0; int pceIndex = 0; if (side == WHITE) { for (pceNum = 0; pceNum < pos->pieceNum[wP]; ++pceNum) { sq = pos->pList[wP][pceNum]; ASSERT(SqOnBoard(sq)); if (!SQOFFBOARD(sq + 9) && PieceCol[pos->pieces[sq + 9]] == BLACK) { AddWhitePawnCapMove(pos, sq, sq + 9, pos->pieces[sq + 9], list); } if (!SQOFFBOARD(sq + 11) && PieceCol[pos->pieces[sq + 11]] == BLACK) { AddWhitePawnCapMove(pos, sq, sq + 11, pos->pieces[sq + 11], list); } if (pos->enPas != NO_SQ) { if (sq + 9 == pos->enPas) { AddEnPassantMove(pos, MOVE(sq, sq + 9, EMPTY, EMPTY, MFLAGEP), list); } if (sq + 11 == pos->enPas) { AddEnPassantMove(pos, MOVE(sq, sq + 11, EMPTY, EMPTY, MFLAGEP), list); } } } } else { for (pceNum = 0; pceNum < pos->pieceNum[bP]; ++pceNum) { sq = pos->pList[bP][pceNum]; ASSERT(SqOnBoard(sq)); if (!SQOFFBOARD(sq - 9) && PieceCol[pos->pieces[sq - 9]] == WHITE) { AddBlackPawnCapMove(pos, sq, sq - 9, pos->pieces[sq - 9], list); } if (!SQOFFBOARD(sq - 11) && PieceCol[pos->pieces[sq - 11]] == WHITE) { AddBlackPawnCapMove(pos, sq, sq - 11, pos->pieces[sq - 11], list); } if (pos->enPas != NO_SQ) { if (sq - 9 == pos->enPas) { AddEnPassantMove(pos, MOVE(sq, sq - 9, EMPTY, EMPTY, MFLAGEP), list); } if (sq - 11 == pos->enPas) { AddEnPassantMove(pos, MOVE(sq, sq - 11, EMPTY, EMPTY, MFLAGEP), list); } } } } /* Loop for slide pieces */ pceIndex = LoopSlideIndex[side]; pce = LoopSlidePce[pceIndex++]; while (pce != 0) { ASSERT(PieceValid(pce)); for (pceNum = 0; pceNum < pos->pieceNum[pce]; ++pceNum) { sq = pos->pList[pce][pceNum]; ASSERT(SqOnBoard(sq)); for (index = 0; index < NumDir[pce]; ++index) { dir = PceDir[pce][index]; t_sq = sq + dir; while (!SQOFFBOARD(t_sq)) { // BLACK ^ 1 == WHITE WHITE ^ 1 == BLACK if (pos->pieces[t_sq] != EMPTY) { if (PieceCol[pos->pieces[t_sq]] == (side ^ 1)) { AddCaptureMove(pos, MOVE(sq, t_sq, pos->pieces[t_sq], EMPTY, 0), list); } break; } t_sq += dir; } } } pce = LoopSlidePce[pceIndex++]; } /* Loop for non slide */ pceIndex = LoopNonSlideIndex[side]; pce = LoopNonSlidePce[pceIndex++]; while (pce != 0) { ASSERT(PieceValid(pce)); for (pceNum = 0; pceNum < pos->pieceNum[pce]; ++pceNum) { sq = pos->pList[pce][pceNum]; ASSERT(SqOnBoard(sq)); for (index = 0; index < NumDir[pce]; ++index) { dir = PceDir[pce][index]; t_sq = sq + dir; if (SQOFFBOARD(t_sq)) { continue; } // BLACK ^ 1 == WHITE WHITE ^ 1 == BLACK if (pos->pieces[t_sq] != EMPTY) { if (PieceCol[pos->pieces[t_sq]] == (side ^ 1)) { AddCaptureMove(pos, MOVE(sq, t_sq, pos->pieces[t_sq], EMPTY, 0), list); } continue; } } } pce = LoopNonSlidePce[pceIndex++]; } ASSERT(MoveListOk(list, pos)); }
void GenerateAllMoves(const CHESS_BOARD *pos, MOVELIST *list) { ASSERT(CheckBoard(pos)); list->count = 0; int pce = EMPTY; int side = pos->side; int sq = 0; int t_sq = 0; int pceNum = 0; int dir = 0; int index = 0; int pceIndex = 0; if (side == WHITE) { for (pceNum = 0; pceNum < pos->pieceNum[wP]; ++pceNum) { sq = pos->pList[wP][pceNum]; ASSERT(SqOnBoard(sq)); if (pos->pieces[sq + 10] == EMPTY) { AddWhitePawnMove(pos, sq, sq + 10, list); if (RanksBrd[sq] == RANK_2 && pos->pieces[sq + 20] == EMPTY) { AddQuietMove(pos, MOVE(sq, (sq + 20), EMPTY, EMPTY, MFLAGPS), list); } } if (!SQOFFBOARD(sq + 9) && PieceCol[pos->pieces[sq + 9]] == BLACK) { AddWhitePawnCapMove(pos, sq, sq + 9, pos->pieces[sq + 9], list); } if (!SQOFFBOARD(sq + 11) && PieceCol[pos->pieces[sq + 11]] == BLACK) { AddWhitePawnCapMove(pos, sq, sq + 11, pos->pieces[sq + 11], list); } if (pos->enPas != NO_SQ) { if (sq + 9 == pos->enPas) { AddEnPassantMove(pos, MOVE(sq, sq + 9, EMPTY, EMPTY, MFLAGEP), list); } if (sq + 11 == pos->enPas) { AddEnPassantMove(pos, MOVE(sq, sq + 11, EMPTY, EMPTY, MFLAGEP), list); } } } if (pos->castlePerm & WKCA) { if (pos->pieces[F1] == EMPTY && pos->pieces[G1] == EMPTY) { if (!SqAttacked(E1, BLACK, pos) && !SqAttacked(F1, BLACK, pos)) { AddQuietMove(pos, MOVE(E1, G1, EMPTY, EMPTY, MFLAGCA), list); } } } if (pos->castlePerm & WQCA) { if (pos->pieces[D1] == EMPTY && pos->pieces[C1] == EMPTY && pos->pieces[B1] == EMPTY) { if (!SqAttacked(E1, BLACK, pos) && !SqAttacked(D1, BLACK, pos)) { AddQuietMove(pos, MOVE(E1, C1, EMPTY, EMPTY, MFLAGCA), list); } } } } else { for (pceNum = 0; pceNum < pos->pieceNum[bP]; ++pceNum) { sq = pos->pList[bP][pceNum]; ASSERT(SqOnBoard(sq)); if (pos->pieces[sq - 10] == EMPTY) { AddBlackPawnMove(pos, sq, sq - 10, list); if (RanksBrd[sq] == RANK_7 && pos->pieces[sq - 20] == EMPTY) { AddQuietMove(pos, MOVE(sq, (sq - 20), EMPTY, EMPTY, MFLAGPS), list); } } if (!SQOFFBOARD(sq - 9) && PieceCol[pos->pieces[sq - 9]] == WHITE) { AddBlackPawnCapMove(pos, sq, sq - 9, pos->pieces[sq - 9], list); } if (!SQOFFBOARD(sq - 11) && PieceCol[pos->pieces[sq - 11]] == WHITE) { AddBlackPawnCapMove(pos, sq, sq - 11, pos->pieces[sq - 11], list); } if (pos->enPas != NO_SQ) { if (sq - 9 == pos->enPas) { AddEnPassantMove(pos, MOVE(sq, sq - 9, EMPTY, EMPTY, MFLAGEP), list); } if (sq - 11 == pos->enPas) { AddEnPassantMove(pos, MOVE(sq, sq - 11, EMPTY, EMPTY, MFLAGEP), list); } } } // castling if (pos->castlePerm & BKCA) { if (pos->pieces[F8] == EMPTY && pos->pieces[G8] == EMPTY) { if (!SqAttacked(E8, WHITE, pos) && !SqAttacked(F8, WHITE, pos)) { AddQuietMove(pos, MOVE(E8, G8, EMPTY, EMPTY, MFLAGCA), list); } } } if (pos->castlePerm & BQCA) { if (pos->pieces[D8] == EMPTY && pos->pieces[C8] == EMPTY && pos->pieces[B8] == EMPTY) { if (!SqAttacked(E8, WHITE, pos) && !SqAttacked(D8, WHITE, pos)) { AddQuietMove(pos, MOVE(E8, C8, EMPTY, EMPTY, MFLAGCA), list); } } } } /* Loop for slide pieces */ pceIndex = LoopSlideIndex[side]; pce = LoopSlidePce[pceIndex++]; while (pce != 0) { ASSERT(PieceValid(pce)); for (pceNum = 0; pceNum < pos->pieceNum[pce]; ++pceNum) { sq = pos->pList[pce][pceNum]; ASSERT(SqOnBoard(sq)); for (index = 0; index < NumDir[pce]; ++index) { dir = PceDir[pce][index]; t_sq = sq + dir; while (!SQOFFBOARD(t_sq)) { // BLACK ^ 1 == WHITE WHITE ^ 1 == BLACK if (pos->pieces[t_sq] != EMPTY) { if (PieceCol[pos->pieces[t_sq]] == (side ^ 1)) { AddCaptureMove(pos, MOVE(sq, t_sq, pos->pieces[t_sq], EMPTY, 0), list); } break; } AddQuietMove(pos, MOVE(sq, t_sq, EMPTY, EMPTY, 0), list); t_sq += dir; } } } pce = LoopSlidePce[pceIndex++]; } /* Loop for non slide */ pceIndex = LoopNonSlideIndex[side]; pce = LoopNonSlidePce[pceIndex++]; while (pce != 0) { ASSERT(PieceValid(pce)); for (pceNum = 0; pceNum < pos->pieceNum[pce]; ++pceNum) { sq = pos->pList[pce][pceNum]; ASSERT(SqOnBoard(sq)); for (index = 0; index < NumDir[pce]; ++index) { dir = PceDir[pce][index]; t_sq = sq + dir; if (SQOFFBOARD(t_sq)) { continue; } // BLACK ^ 1 == WHITE WHITE ^ 1 == BLACK if (pos->pieces[t_sq] != EMPTY) { if (PieceCol[pos->pieces[t_sq]] == (side ^ 1)) { AddCaptureMove(pos, MOVE(sq, t_sq, pos->pieces[t_sq], EMPTY, 0), list); } continue; } AddQuietMove(pos, MOVE(sq, t_sq, EMPTY, EMPTY, 0), list); } } pce = LoopNonSlidePce[pceIndex++]; } //ASSERT(MoveListOk(list, pos)); }
int SqAttacked(const int sq, const int side, const S_BOARD *pos) { int piece; int tmpSQ; int dir; int i; ASSERT(SqOnBoard(sq)); ASSERT(SideValid(side)); ASSERT(checkBoard(pos)); //pawn attacks if(side == WHITE) { if(pos->pieces[sq-11] == wP || pos->pieces[sq-9] == wP) return TRUE; } else { //BLACK if(pos->pieces[sq+11] == bP || pos->pieces[sq+9] == bP) return TRUE; } //knight attacks for(i = 0; i < 8; i++) { piece = pos->pieces[ sq + KnDir[i] ]; if(piece != OFFBOARD && IsKn(piece) && PieceColor[piece]==side) return TRUE; } //king attacks for(i = 0; i < 8; i++) { piece = pos->pieces[ sq + KiDir[i] ]; if(piece != OFFBOARD && IsKi(piece) && PieceColor[piece]==side) { return TRUE; } } //rook and Queen attacks for(i = 0; i < 4; i++) { dir = RkDir[i]; tmpSQ = sq + dir; piece = pos->pieces[tmpSQ]; while(piece != OFFBOARD) { if(piece != EMPTY) { if(piece != OFFBOARD && IsRQ(piece) && PieceColor[piece] == side) return TRUE; break; } tmpSQ += dir; piece = pos->pieces[tmpSQ]; } } //bishop and queen attacks for(i = 0; i < 4; i++) { dir = BiDir[i]; tmpSQ = sq + dir; piece = pos->pieces[tmpSQ]; while(piece != OFFBOARD) { if(piece != EMPTY) { if(piece != OFFBOARD && IsBQ(piece) && PieceColor[piece] == side) return TRUE; break; } tmpSQ += dir; piece = pos->pieces[tmpSQ]; } } return FALSE; }