void SelfPlay() { printf("\n\n--------------The Bot Will Now Play itself to Some Randomized Depth-------------\n\n"); printf("Press Any Key To See The Next Move\n"); BOARD *board=new BOARD; SetStart(board); getchar(); while(1) { MOVE *list=new MOVE; GenMoves(board,list); if(list->Count==0) { printf("%c LOST THE GAME\n\n",PceSideChar[board->Side]); break; } int Depth=5+rand()%4; vector<int>BestMove=SearchPos(board,Depth); PrintBoard(board); MakeMove(board,BestMove); getchar(); getchar(); } StartGame(); }
void TestMoveList (void) /**************************************************************************** * * This routine reads in a *.epd file (EPD notation) and prints the legal * moves for that position. * ****************************************************************************/ { while (ReadEPDFile ("TEST/GMG1.epd", 0)) { ShowBoard (); GenCnt = 0; TreePtr[2] = TreePtr[1]; GenMoves (1); FilterIllegalMoves (1); ShowMoveList (1); printf ("No. of moves generated = %lu\n\n", GenCnt); } }
//this fuction takes in a move in form of files and rank and return the move in integer int ParseMove(char *ptrChar, BOARD *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 f1=(ptrChar[0] - 'a'); int r1=(ptrChar[1] - '1'); int f2=(ptrChar[2] - 'a'); int r2=(ptrChar[3] - '1'); int from = fr2sq(f1, r1); int to = fr2sq(f2, r2); MOVELIST list[1]; GenMoves(pos,list); int MoveNum = 0; int Move = 0; int PromPce = EMPTY; for(MoveNum = 0; MoveNum < list->Count; ++MoveNum) { Move = list->MoveNum[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(IsKnight[PromPce]&& ptrChar[4]=='n') { return Move; } continue; } return Move; } } return NOMOVE; }
void TestMoveGenSpeed (void) /************************************************************************** * * This routine benchmarks the speed of the bitmap move generation. * The test case is BK.epd, the 24 positions from the Brat-Kopec test * suite. * **************************************************************************/ { unsigned long i; struct timeval t1, t2; double et; short side, xside; GenCnt = 0; et = 0; /* while (ReadEPDFile ("../test/wac.epd", 0)) { */ gettimeofday (&t1, NULL); side = board.side; xside = 1^side; for (i = 0; i < 2000000; i++) { TreePtr[2] = TreePtr[1]; GenMoves (1); } gettimeofday (&t2, NULL); et += (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) / 1e6; printf ("Time = %f\n", et); /* } */ printf ("No. of moves generated = %lu\n", GenCnt); printf ("Time taken = %f secs\n", et); if (et > 0) printf ("Rate = %f moves/sec.\n", GenCnt / et); }
void ShowLine (int move __attribute__ ((unused)), int score, char c) /***************************************************************************** * * Print out the latest PV found during the search. * The only move we know is the root move. The rest of the PV is taken * from the hash table. This strategy avoids all the headaches associated * with returning the PV up from the leaf to the root. * *****************************************************************************/ { int i, len; int pvar[MAXPLYDEPTH]; /* SMC */ if (!(flags & POST)) return; if (NodeCnt < 500000 && (flags & SOLVE)) { /* printf("NodeCnt = %d\n",NodeCnt); getchar(); */ return; } if (Idepth == DEPTH && c == '&') return; if ((flags & XBOARD) && c == '&') return; if (rootscore == -INFINITY-1) return; GetElapsed (); /* * What is the reason for these different output formats, in * particular for et? */ if (flags & XBOARD) { if (score > MATE-255) { printf ("%d%c Mat%d %d %lu\t", Idepth/DEPTH, c, (int)(MATE+2-abs(score))/2, (int)(et*100), NodeCnt+QuiesCnt); if (ofp != stdout) fprintf (ofp,"%2d%c%7.2f Mat%02d%10lu\t", Idepth/DEPTH, c, et, (MATE+2-abs(score))/2, NodeCnt+QuiesCnt); } else if (score < -MATE+255) { printf ("%d%c -Mat%2d %d %lu\t", Idepth/DEPTH, c, (int)(MATE+2-abs(score))/2, (int)(et*100), NodeCnt+QuiesCnt); if (ofp != stdout) fprintf (ofp,"%2d%c%7.2f -Mat%02d%10lu\t", Idepth/DEPTH, c, et, (MATE+2-abs(score))/2, NodeCnt+QuiesCnt); } else { printf ("%d%c %d %d %lu\t", Idepth/DEPTH, c, (int)score, (int)(et*100), NodeCnt+QuiesCnt); if (ofp != stdout) fprintf (ofp,"%2d%c%7.2f%7d%10lu\t", Idepth/DEPTH, c, et, score, NodeCnt+QuiesCnt); } } else { if (score > MATE-255) { printf ("\r%2d%c%7.2f Mat%02d%10lu\t", Idepth/DEPTH, c, et, (MATE+2-abs(score))/2, NodeCnt+QuiesCnt); if (ofp != stdout) fprintf (ofp,"\r%2d%c%7.2f Mat%02d%10lu\t", Idepth/DEPTH, c, et, (MATE+2-abs(score))/2, NodeCnt+QuiesCnt); } else if (score < -MATE+255) { printf ("\r%2d%c%7.2f -Mat%02d%10lu\t", Idepth/DEPTH, c, et, (MATE+2-abs(score))/2, NodeCnt+QuiesCnt); if (ofp != stdout) fprintf (ofp,"\r%2d%c%7.2f -Mat%02d%10lu\t", Idepth/DEPTH, c, et, (MATE+2-abs(score))/2, NodeCnt+QuiesCnt); } else { printf ("\r%2d%c%7.2f%7d%10lu\t", Idepth/DEPTH, c, et, score, NodeCnt+QuiesCnt); if (ofp != stdout) fprintf (ofp,"\r%2d%c%7.2f%7d%10lu\t", Idepth/DEPTH, c, et, score, NodeCnt+QuiesCnt); } } if (c == '-') { printf ("\n"); if (ofp != stdout) fprintf(ofp, "\n"); return; } else if (c == '+') { SANMove (RootPV, 1); printf (" %s\n", SANmv); if (ofp != stdout) fprintf (ofp," %s\n", SANmv); return; } SANMove (RootPV, 1); printf (" %s", SANmv); if (ofp != stdout) fprintf (ofp," %s", SANmv); MakeMove (board.side, &RootPV); TreePtr[3] = TreePtr[2]; GenMoves (2); len = strlen (SANmv); i = 2; pvar[1] = RootPV; /* We fill the rest of the PV with moves from the hash table */ if ((flags & USEHASH)) { while (TTGetPV (board.side, i, rootscore, &pvar[i])) { if ((MATESCORE(score) && abs(score) == MATE+2-i) || Repeat ()) break; if (len >= 32) { printf ("\n\t\t\t\t"); if (ofp != stdout) fprintf (ofp,"\n\t\t\t\t"); len = 0; } SANMove (pvar[i], i); printf (" %s", SANmv); if (ofp != stdout) fprintf (ofp," %s", SANmv); MakeMove (board.side, &pvar[i]); TreePtr[i+2] = TreePtr[i+1]; GenMoves (++i); len += strlen (SANmv); } } printf ("\n"); if (ofp != stdout) fprintf(ofp,"\n"); for (--i; i; i--) UnmakeMove (board.side, &pvar[i]); fflush (stdout); if (ofp != stdout) fflush (ofp); }
void MoveList (short int side, register short int ply) /* * Fill the array Tree[] with all available moves for side to play. Array * TrPnt[ply] contains the index into Tree[] of the first move at a ply. */ { register short i, xside, f; xside = side ^ 1; TrP = &TrPnt[ply + 1]; *TrP = TrPnt[ply]; if (!PV) Swag0 = killr0[ply]; else Swag0 = PV; Swag1 = killr1[ply]; Swag2 = killr2[ply]; Swag3 = killr3[ply]; if (ply > 2) Swag4 = killr1[ply - 2]; else Swag4 = 0; #ifdef KILLT sidebit = ((side == white) ? 0 : 0x80); killt[SwagHt | sidebit] += 5000; killt[Swag0 | sidebit] += 2000; killt[Swag1 | sidebit] += 60; killt[Swag2 | sidebit] += 50; killt[Swag3 | sidebit] += 40; killt[Swag4 | sidebit] += 30; #endif #ifdef HISTORY i = (side == black)?0x4000:0; history[SwagHt | i] += 5000; history[Swag0 | i] += 2000; history[Swag1 | i] += 60; history[Swag2 | i] += 50; history[Swag3 | i] += 40; history[Swag4 | i] += 30; #endif for (i = PieceCnt[side]; i >= 0; i--) GenMoves (ply, PieceList[side][i], side, xside); if (!castld[side]) { f = PieceList[side][0]; if (castle (side, f, f + 2, 0)) { LinkMove (ply, f, f + 2, cstlmask, xside); } if (castle (side, f, f - 2, 0)) { LinkMove (ply, f, f - 2, cstlmask, xside); } } if (epsquare > 0) { f = epmove1[epsquare]; if (color[f] == side && board[f] == pawn) LinkMove (ply, f, epsquare, capture | epmask, xside); f = epmove2[epsquare]; if (color[f] == side && board[f] == pawn) LinkMove (ply, f, epsquare, capture | epmask, xside); } #ifdef KILLT killt[SwagHt | sidebit] -= 5000; killt[Swag0 | sidebit] -= 2000; killt[Swag1 | sidebit] -= 60; killt[Swag2 | sidebit] -= 50; killt[Swag3 | sidebit] -= 40; killt[Swag4 | sidebit] -= 30; #endif #ifdef HISTORY i = (side == black)?0x4000:0; history[SwagHt | i] -= 5000; history[Swag0 | i] -= 2000; history[Swag1 | i] -= 60; history[Swag2 | i] -= 50; history[Swag3 | i] -= 40; history[Swag4 | i] -= 30; #endif SwagHt = 0; /* SwagHt is only used once */ GenCnt += (TrPnt[ply+1] - TrPnt[ply]); }
void PlayBot() { printf("\n\nAt Any Time In The Game If You Want To See The Grid Indexing In Which You Have To Make A Move\n\n"); printf("During Enter A Move Command...Just Press 0 And Press Enter \n\n"); BOARD *board=new BOARD; SetStart(board); printf("The Starting Board\n\n"); PrintBoard(board); char Inp[200]; int Side; printf("\nChoose Your Side...\n\n0. For Black\n1. For White\n"); scanf("%d",&Side); if(Side==0) { MOVE *list1=new MOVE; GenMoves(board,list1); vector<int>BestMove1=SearchPos(board,8); MakeMove(board,BestMove1); PrintBoard(board); } while(1) { printf("\n\nEnter Your Move\n"); getchar(); scanf("%[^\n]",&Inp); if(Inp[0]=='0') { PrintIndex(); continue; } else if(Inp[0]=='1') { printf("\nYour Possible MoveList is\n"); MOVE *YourMoveList=new MOVE; GenMoves(board,YourMoveList); PrintMoveList(YourMoveList); } vector<int>Move=ParseMove(Inp); if(MoveExists(board,Move)) MakeMove(board,Move); else { MOVE *User=new MOVE; GenMoves(board,User); if(User->Count==0) { printf("Sorry You Lost\n\n"); break; } else printf("Invalid Move...Enter Again\n\n"); continue; } PrintBoard(board); printf("-----------------------------------Bot's Turn----------------------------------\n"); MOVE *Bot=new MOVE; GenMoves(board,Bot); if(Bot->Count==0) { printf("--------------------------Congratulations You Win--------------------------\n"); break; } vector<int>BestMove=SearchPos(board,8); MakeMove(board,BestMove); PrintBoard(board); } StartGame(); }
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; }
int Search (int alpha, int beta, int depth, MOVE * pBestMove, LINE * pline) { /* Vars deffinition */ int i; int value; /* To store the evaluation */ int havemove; /* Either we have or not a legal move available */ int movecnt; /* The number of available moves */ // int score; MOVE moveBuf[200]; /* List of movements */ MOVE tmpMove; LINE line; nodes++; countSearchCalls++; /* Do some housekeeping every 1024 nodes */ if ((nodes & 1023) == 0) checkup(stop_time); if (must_stop) return 0; havemove = 0; /* is there a move available? */ pBestMove->type_of_move = MOVE_TYPE_NONE; /* If we are in a leaf node we cal quiescence instead of eval */ if (depth == 0) { pline->cmove = 0; return Quiescent(alpha, beta); /* Uncomment nest line if want to make tests avoiding qsearch */ //return Eval(alpha, beta); } /* If we're in check we want to search deeper */ if (IsInCheck(side)) ++depth; /* Static null move prunning */ if (ply && !IsInCheck(side)) { int ev = Eval(-MATE, MATE); int evalua = ev - 150; if (evalua >= beta) return beta; } /* Generate and count all moves for current position */ movecnt = GenMoves (side, moveBuf); /* Once we have all the moves available, we loop through the posible * moves and apply an alpha-beta search */ for (i = 0; i < movecnt; ++i) { /* Here must be called OrderMove, so we have the moves are ordered before picking one up from the list*/ MoveOrder(i, movecnt, moveBuf); /* If the current move isn't legal, we take it back * and take the next move in the list */ if (!MakeMove (moveBuf[i])) { TakeBack (); continue; } /* If we've reached this far, then we have a move available */ havemove = 1; value = -Search(-beta, -alpha, depth - 1, &tmpMove, &line); /* We've evaluated the position, so we return to the previous position in such a way that when we take the next move from moveBuf everything is in order */ TakeBack (); /* Once we have an evaluation, we use it in in an alpha-beta search */ if (value > alpha) { /* Este movimiento causo un cutoff, asi que incrementamos el valor de historia para que sea ordenado antes la proxima vez que se busque */ history[moveBuf[i].from][moveBuf[i].dest] += depth; /* This move is so good and caused a cutoff */ if (value >= beta) { return beta; } alpha = value; /* So far, current move is the best reaction for current position */ *pBestMove = moveBuf[i]; /* Update the principal line */ pline->argmove[0] = moveBuf[i]; memcpy(pline->argmove + 1, line.argmove, line.cmove * sizeof(MOVE)); pline->cmove = line.cmove + 1; } } /* Once we've checked all the moves, if we have no legal moves, * then that's checkmate or stalemate */ if (!havemove) { if (IsInCheck (side)) return -MATE + ply; /* add ply to find the longest path to lose or shortest path to win */ else return 0; } /* 3 vecez la misma posicion */ if (reps() >= 2) return 0; if (fifty >= 100) /* 50 jugadas o mas */ return 0; /* Finally we return alpha, the score value */ return alpha; }