int main(int ununsed, char **alsoUnused) { TestHashTable(); return 0; }
int AlphaBeta(board_t *brd, int alpha, int beta, int depth, searchinfo_t *sinfo, int null) { if(depth == 0){ //return Eval(brd); return Quiece(brd, alpha, beta, sinfo); } if(!(sinfo->nodes & 0xfff)) CheckUp(sinfo); sinfo->nodes++; ASSERT(CheckBrd(brd)); // if we are not the root of the tree and we have a repetition // or we exceeded the fifty move rule, then we have a draw and return 0 if((IsRep(brd) || brd->fifty >= 100) && brd->ply) return 0; if(brd->ply >= MAXDEPTH-1) return Eval(brd); // if we are too deep, we return // test if we are in check int check = SqAttacked(brd, LOCATEBIT(brd->bb[brd->side][King]), brd->side^1); if(check) depth++; int score = -INFINITE; int pvMain = NO_MOVE; // check the transposition table if we have searched the current position before // if so, return what we found if(TestHashTable(brd, &pvMain, &score, alpha, beta, depth)) return score; // Before we search, we try how we do if we don't make a move // i.e. make a null move if( null && !check && brd->ply && depth >= 4 && (brd->all[brd->side]^brd->bb[brd->side][Pawn]^brd->bb[brd->side][King]) ) { MakeMoveNull(brd); // We cannot do two null moves in a row so we set the null argument here to false score = -AlphaBeta(brd, -beta, -beta + 1, depth-4, sinfo, false); TakeBackNull(brd); if(sinfo->stop){ return 0; } if(score >= beta){ return beta; } } mlist_t list; int i; int legal = 0; int bestMove = NO_MOVE; int bestScore = -INFINITE; int oldAlpha = alpha; score = -INFINITE; GenMoves(brd, &list); // we tested our transposition table for the best move 'pvMain' // if it exists we will set this move as the first move to be searched if(pvMain != NO_MOVE){ if(MakeMove(brd, pvMain)){ score = -AlphaBeta(brd, -beta, -alpha, depth-1, sinfo, true); TakeBack(brd); bestScore = score; if(score > alpha){ if(score >= beta){ if(!(pvMain & FLAGCAP)){ brd->betaMoves[1][brd->ply] = brd->betaMoves[0][brd->ply]; brd->betaMoves[0][brd->ply] = pvMain; } return beta; } alpha = score; bestMove = pvMain; } } /*/ for(i = 0; i < list.len; i++){ if(list.move[i].move == pvMain){ list.move[i].score = 5000000; break; } }//*/ } for(i = 0; i < list.len; i++) // Loop through all moves { if(sinfo->stop) return 0; SelectNextMove(&list, i); if(!MakeMove(brd, list.move[i].move)) continue; legal++; // we have found a legal move so we need not check for mate afterwards // call AlphaBeta in a negamax fashion score = -AlphaBeta(brd, -beta, -alpha, depth-1, sinfo, true); TakeBack(brd); if(score > bestScore){ bestScore = score; if(score > alpha){ if(score >= beta){ if(legal==1) sinfo->fhf++; // count the number of beta cutoffs searched first sinfo->fh++; // compared to all beta cutoffs (measure of efficiency) if(!(list.move[i].move & FLAGCAP)){ brd->betaMoves[1][brd->ply] = brd->betaMoves[0][brd->ply]; brd->betaMoves[0][brd->ply] = list.move[i].move; } // Store the move in the transposition table as a beta (killer) move StorePvMove(brd, bestMove, depth, beta, HFBETA); return beta; } alpha = score; bestMove = list.move[i].move; } } } if(legal == 0){ // We havn't found a legal move if(check){ // if we are in check it is mate; but we want the shortest path // to it so we'll subtract the path length return -MATE + brd->ply; } return 0; // Stalemate } if(oldAlpha != alpha){ // Store exact (normal) transposition entry StorePvMove(brd, bestMove, depth, bestScore, HFEXACT); } else { // Store alpha cutoff transposition entry StorePvMove(brd, bestMove, depth, alpha, HFALPHA); } return alpha; }