void print_result() { int i; /* is there a legal move? */ for (i = 0; i < first_move[1]; ++i) if (makemove(gen_dat[i].m.b)) { takeback(); break; } if (i == first_move[1]) { if (in_check(side)) { if (side == LIGHT) printf("0-1 {Black mates}\n"); else printf("1-0 {White mates}\n"); } else printf("1/2-1/2 {Stalemate}\n"); } else if (reps() == 3) printf("1/2-1/2 {Draw by repetition}\n"); else if (fifty >= 100) printf("1/2-1/2 {Draw by fifty move rule}\n"); }
void perf_t(char dep) { unsigned int i; /*char dummy; gen_all_captures();*/ gen_all(); check_condition(); dep--; for (i = tree.first_move[Ply];i < tree.first_move[Ply + 1];i++) { if (verify_move(tree.move_list[i].move)==0) continue; if (makemove(tree.move_list[i].move,0)) { /*print_board(); printf("Press any key to continue:"); while (!kbhit()); dummy=getch();*/ Nodes++; if (dep) perf_t(dep); unmakemove(); } } }
int main (void) { initialize_curses(); initialize_field_window(); bdinit (_board); // Randomly choose who goes first enum { USER, // get input from standard input PROGRAM // get input from program }; unsigned input[2]; _humanPlayer = nrand(2); input[_humanPlayer] = USER; input[!_humanPlayer] = PROGRAM; _plyr[_humanPlayer] = "you"; _plyr[!_humanPlayer] = "me"; for (unsigned color = BLACK;; color = !color) { bdisp(); unsigned curmove; if (input[color] == USER) curmove = _lastHumanMove = usermove(); else curmove = _lastComputerMove = pickmove (color); int mv = makemove(color, curmove); if (mv != MOVEOK) { // Game finished. Display result and quit. if (mv != RESIGN) display_game_result_message (mv, input[color] == USER); break; } } return EXIT_SUCCESS; }
/* Check the validity of the move */ BOOL check_validity(void) { char s[256]; int i; BOOL found; if (to != 999) { /* loop through the moves to see if it's legal */ found = FALSE; for (i = 0; i < first_move[1]; ++i) { if (gen_dat[i].m.b.from == from && gen_dat[i].m.b.to == to) { found = TRUE; /* get the promotion piece right */ if (gen_dat[i].m.b.bits & 32) { switch (s[4]) { case 'N': break; case 'B': i += 1; break; case 'R': i += 2; break; default: i += 3; break; } } break; } } if (!found || !makemove(gen_dat[i].m.b)) { printf("Illegal move.\n"); if (is_mini) { draw_message(" ","Nope"); } else { pz_draw_header("Illegal move !"); } return FALSE; } else { ply = 0; gen_moves(); print_board(); print_result(); to = 999; return TRUE; } } /* if to != 999 */ else { return FALSE; } }
/* print_result() checks to see if the game is over */ void print_result() { int i; /* is there a legal move? */ for (i = 0; i < first_move[1]; ++i) if (makemove(gen_dat[i].m.b)) { takeback(); break; } if (i == first_move[1]) { if (in_check(side)) { if (side == LIGHT) gprintf("Black mates"); else gprintf("White mates"); } else gprintf("Stalemate"); } else if (reps() == 3) gprintf("Draw by repetition"); else if (fifty >= 100) gprintf("Draw by fifty move rule"); }
int quiesce(int alpha,int beta) { int i, j, x; ++nodes; /* do some housekeeping every 1024 nodes */ if ((nodes & 1023) == 0) checkup(); pv_length[ply] = ply; /* are we too deep? */ if (ply >= MAX_PLY - 1) return eval(); if (hply >= HIST_STACK - 1) return eval(); /* check with the evaluation function */ x = eval(); if (x >= beta) return beta; if (x > alpha) alpha = x; gen_caps(); if (follow_pv) /* are we following the PV? */ sort_pv(); /* loop through the moves */ for (i = first_move[ply]; i < first_move[ply + 1]; ++i) { sort(i); if (!makemove(gen_dat[i].m.b)) continue; x = -quiesce(-beta, -alpha); takeback(); if (x > alpha) { if (x >= beta) return beta; alpha = x; /* update the PV */ pv[ply][ply] = gen_dat[i].m; for (j = ply + 1; j < pv_length[ply + 1]; ++j) pv[ply][j] = pv[ply + 1][j]; pv_length[ply] = pv_length[ply + 1]; } } return alpha; }
short parse_input_string (char *str, struct board *board) { short cnt = 0, move; char *p; p = str; board->cpu = 3; switch (*p) { case 'a': board->white_lev = 1; board->black_lev = 1; break; case 'b': board->white_lev = 2; board->black_lev = 2; break; case 'c': board->white_lev = 3; board->black_lev = 3; break; default: return -1; } p++; while (p[cnt] != '0') { move = (short) (p[cnt] - '1'); if (move < 0 || move > 6) return -1; if (board->stack[move] < BOARDY) makemove (board, move); else return -2; if (cnt >= 42 || endgame (board) != 0) return -2; cnt++; } return 1; }
int ab(int alpha, int beta) { int besti,i,j,h,k,l,val,score; int x,v,work; int nav, av[8]; int64 poscnt; int side, otherside; nodes++; if (plycnt == 41) return DRAW; side = (otherside = plycnt & 1) ^ 1; for (i = nav = 0; ++i <= 7; ) { if ((h = height[i]) <= 6) { if (wins(i,h,3) || colthr[columns[i]] != 0) { if (h+1 <= 6 && wins(i,h+1,1<<otherside)) return LOSE; av[0] = i; /* forget other moves */ while (++i <= 7) if ((h = height[i]) <= 6 && (wins(i,h,3) || colthr[columns[i]] != 0)) return LOSE; nav = 1; break; } if (!(h+1 <= 6 && wins(i,h+1,1<<otherside))) av[nav++] = i; } } if (nav == 0) return LOSE; if (nav == 1) { makemove(av[0]); score = -ab(-beta,-alpha); backmove(); return score; } if ((x = transpose()) != ABSENT) { score = x >> 5; if (score == DRAWLOSE) { if ((beta = DRAW) <= alpha) return score; } else if (score == DRAWWIN) { if ((alpha = DRAW) >= beta) return score; } else return score; /* exact score */ }
int moveexists(S_BOARD *pos,const int move) { S_MOVELIST list[1]; generateallmoves(pos,list); int movenum = 0; for(movenum = 0; movenum < list->count; movenum++) { if(!makemove(pos,list->moves[movenum].move)) continue; takemove(pos); if(list->moves[movenum].move == move) return TRUE; } return FALSE; }
int main (void) { initialize_curses(); initialize_windows(); shuffle_deck_and_deal(); instructions(); enum EPlayer player = nrand(NPLAYERS); printplayer (player); waddstr (_wmsg, "get to start.\n"); for (;;) { unsigned m = makemove (player); if (_hand[OTHER(player)][m]) goodmove (player, m); else if (!gofish (player, m)) player = OTHER(player); } return EXIT_SUCCESS; }
/* Let's make the iPod think about ;-) */ void computer_play(void) { if (!is_mini) { pz_draw_header("computer play"); } /* think about the move and make it */ //sleep(1); printf("think\n"); think(2); //sleep(1); if (!pv[0][0].u) { printf("No legal moves\n"); if (!is_mini) { pz_draw_header ("No legal moves"); } } sprintf(cpu_move,"%s", move_str(pv[0][0].b)); makemove(pv[0][0].b); ply = 0; gen_moves(); if (in_check(LIGHT)) { if (is_mini) { draw_message(" ", "Check"); } else { pz_draw_header("Check"); } } else { if (is_mini) { draw_message(" ", "Play"); } else { pz_draw_header("Your Turn"); } } }
int Search::printDtm() { int side = getSide(); u64 friends = side == WHITE ? getBitmap<WHITE>() : getBitmap<BLACK>(); u64 enemies = side == BLACK ? getBitmap<WHITE>() : getBitmap<BLACK>(); display(); int res = side ? getGtb().getDtm<WHITE, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100) : getGtb().getDtm<BLACK, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100); cout << " res: " << res; incListId(); generateCaptures(side, enemies, friends); generateMoves(side, friends | enemies); _Tmove *move; u64 oldKey = 0; cout << "\n succ. \n"; int best = -_INFINITE; for (int i = 0; i < getListSize(); i++) { move = &gen_list[listId].moveList[i]; makemove(move, false, false); cout << "\n" << decodeBoardinv(move->type, move->from, getSide()) << decodeBoardinv(move->type, move->to, getSide()) << " "; res = side ? -getGtb().getDtm<BLACK, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100) : getGtb().getDtm<WHITE, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100); if (res != -INT_MAX) { cout << " res: " << res; } cout << "\n"; takeback(move, oldKey, false); if (res > best) { best = res; } } if (best > 0) { best = _INFINITE - best; } else if (best < 0) { best = -(_INFINITE - best); } cout << endl; decListId(); return best; }
/*Genera le mosse della Root e le ordina*/ void root(){ int d,next; RMOVEL m; unsigned int c; /*siamo sotto scacco?*/ check_condition(); /*generiamo le mosse della root*/ gen_all(); /*validiamo, inseriamo nella lista e attribuiamo un valore*/ tree.last_root_move=0; for (c=0;c<tree.first_move[1];c++) { if(!makemove(tree.move_list[c].move,0))continue; tree.root_move_list[tree.last_root_move].move=tree.move_list[c].move; tree.root_move_list[c].scorec=-quiesce(-INF,+INF,0); tree.root_move_list[c].scoren=0; tree.last_root_move++; unmakemove(); } /*ordiniamo*/ d=1; do { next=0; for (c=0;c<((tree.last_root_move)-d);c++) { if (tree.root_move_list[c].scorec<tree.root_move_list[c+1].scorec) { m=tree.root_move_list[c]; tree.root_move_list[c]=tree.root_move_list[c+1]; tree.root_move_list[c+1]=m; next=1; } } d++; } while (next); }
void spantree(board *init) { int i,j,mi,ni=-1; for(j=0;j<valor;j++) { if(init->s[j]==0) { mi=j; break; } } level++; if(level==5) { level--; return; } else init->children=moves[mi][4]; for(i=0;i<init->children;i++) { board *temp=getboard(); for(j=0;j<valor;j++) { if(init->s[j]==0) { mi=j; break; } } for(j=0;j<4;j++) { if(moves[mi][j]!=-1 && j>ni) { ni=j; break; } } switch((i+1)) { case 1: init->c1=temp; copyarray(init->path,temp->path,init->pi); temp->pi=init->pi; temp->path[(temp->pi)++]=1; makemove(init,init->c1,mi,ni); spantree(init->c1); break; case 2: init->c2=temp; copyarray(init->path,temp->path,init->pi); temp->pi=init->pi; temp->path[(temp->pi)++]=2; makemove(init,init->c2,mi,ni); spantree(init->c2); break; case 3: init->c3=temp; copyarray(init->path,temp->path,init->pi); temp->pi=init->pi; temp->path[(temp->pi)++]=3; makemove(init,init->c3,mi,ni); spantree(init->c3); break; case 4: init->c4=temp; copyarray(init->path,temp->path,init->pi); temp->pi=init->pi; temp->path[(temp->pi)++]=4; makemove(init,init->c4,mi,ni); spantree(init->c4); break; default: printf("\nNO TIENE HIJOS"); } } level--; return; }
/* print_result() checks to see if the game is over */ void print_result() { int i; /* is there a legal move? */ for (i = 0; i < first_move[1]; ++i) { if (makemove(gen_dat[i].m.b)) { takeback(); break; } } if (i == first_move[1]) { if (in_check(side)) { if (side == LIGHT) { printf("GR_RGB(0,0,0) mates"); if (is_mini) { draw_message("GR_RGB(0,0,0)","Mates"); } else { pz_draw_header("GR_RGB(0,0,0) mates"); } draw_end('b'); } else { printf("GR_RGB(255,255,255) mates"); if (is_mini) { draw_message("GR_RGB(255,255,255)","Mates"); } else { pz_draw_header("GR_RGB(255,255,255) mates"); } draw_end('w'); } } else { printf("Stalemate"); if (is_mini) { draw_message("Stale","Mate"); } else { pz_draw_header("Stalemate"); } draw_end('d'); } } /* else if (reps() == 3) { printf("Draw by repetition"); if (is_mini == 0) pz_draw_header("Draw by repetition"); draw_end('d'); } */ else if (fifty >= 100) { printf("Draw by fifty move rule"); if (is_mini == 0) { pz_draw_header("Draw : fifty moves"); } draw_end('d'); } }
/*Equivalente alla search() ma alcune cose non vengono effettuate*/ int search_root(int alpha,int beta,int depth){ int i,c,score,legal,old_depth; unsigned int start_nodes,nws; MOVE m; start_nodes=Nodes; /*questo e' un nuovo nodo da cercare*/ Nodes++; /*controlla se è tempo di abortire la ricerca*/ if(stop_search()) { tree.abort_search=1; return 0; } /*aggiorna la lunghezza della pv corrente*/ tree.pv_lenght[Ply]=Ply; /*estensioni*/ old_depth=depth; /*1-se sotto scacco: estendi la ricerca!*/ if(tree.check[Side][Ply]) depth++; legal=0; nws=0; /*negascout fail-soft alpha beta*/ for (i=0;i<tree.last_root_move;i++) { m=tree.root_move_list[i].move; if(!makemove(m,0)) continue; legal = 1; if (nws) { score = -search( -alpha-1, -alpha, (depth - 1)); if (tree.abort_search) { unmakemove(); return 0; } if (score > alpha && score < beta ) { score = -search( -beta, -alpha, (depth - 1)); } } else score = -search( -beta, -alpha, (depth - 1)); unmakemove(); tree.root_move_list[i].scoren=Nodes-start_nodes; start_nodes=Nodes; if(tree.abort_search) return 0; if(score>alpha) { if(score>=beta) { heuristic(m,old_depth); return (score); } alpha=score; nws=1; /*aggiorna la pv*/ tree.pv[Ply][Ply]=m; heuristic(tree.pv[Ply][Ply],old_depth); for(c=Ply+1;c<tree.pv_lenght[Ply+1];c++) tree.pv[Ply][c]=tree.pv[Ply+1][c]; tree.pv_lenght[Ply]=tree.pv_lenght[Ply+1]; } }/*ciclo mosse*/ /*Se non ci sono mosse legali*/ if(legal==0) { if(tree.check[Side][Ply]) return -INF+Ply; else return DRAW; } return alpha; }
char *move2san(struct board_t *brd,DWORD move,char buf[128]) { short c,idx,from,to,pcs,cnt,i,row,mcheck,mlm; short mlegal[MAXMOVES]; char pcschar[]={'X','N','B','R','Q','K'}; DWORD mvs[MAXMOVES]; from=move&0x3F; to=(move>>6)&0x3F; pcs=(move>>12)&0x7; buf[0]='\0'; cnt=idx=i=0; generate_moves(brd,mvs,&idx); for(c=0;c<idx;c++) { makemove(brd,mvs[c]); mlegal[c]=FALSE; if(is_in_check(brd,brd->color^1)==FALSE) { mlegal[c]=TRUE; if(mvs[c]==move) cnt++; } unmakemove(brd); } if(cnt!=1) return buf; makemove(brd,move); mcheck=is_in_check(brd,brd->color); mlm=legal_moves(brd,NULL); unmakemove(brd); /* primo passaggio: ci occupiamo subito del "caso particolare" dell'arrocco */ if((move>>18)&CASTLING) { if((to==G1)||(to==G8)) snprintf(buf+i,128-i,"O-O"); else if((to==C1)||(to==C8)) snprintf(buf+i,128-i,"O-O-O"); if(mcheck==TRUE) i+=snprintf(buf+i,128-i,"%c",((mlm==0)?('#'):('+'))); return buf; } /* secondo passaggio: proviamo a generare una mossa del tipo Nc3 o Bxf6+ controllando che non ci siano ambiguita' */ for(c=cnt=0;c<idx;c++) { if(((mvs[c]>>12)&0x7)!=pcs) mlegal[c]=FALSE; if(((mvs[c]>>6)&0x3F)!=to) mlegal[c]=FALSE; if((move>>18)&PROMOTION) if(((mvs[c]>>18)&0xFF)!=((move>>18)&0xFF)) mlegal[c]=FALSE; if(mlegal[c]==TRUE) cnt++; } if(cnt==1) { if(pcs!=PAWN) i+=snprintf(buf+i,128-i,"%c",pcschar[pcs]); if((brd->board[to]!=EMPTY)||(brd->ep==to)) { if(pcs==PAWN) i+=snprintf(buf+i,128-i,"%cx",'a'+(from&0x7)); else i+=snprintf(buf+i,128-i,"x"); } i+=snprintf(buf+i,128-i,"%s",coords[to]); if((move>>18)&PROMOTION) i+=snprintf(buf+i,128-i,"=%c",promchar(move)); if(mcheck==TRUE) i+=snprintf(buf+i,128-i,"%c",((mlm==0)?('#'):('+'))); return buf; } /* terzo passaggio: proviamo anche ad indicare la colonna o la riga, come ad esempio in Rad1 o N2xc3+ */ for(c=cnt=row=0;c<idx;c++) { if((mlegal[c]==FALSE)||(mvs[c]==move)) continue; if((mvs[c]&0x7)==(from&0x7)) cnt++; if(((mvs[c]&0x3F)>>3)==(from>>3)) row++; } if((cnt==0)||(row==0)) { if(pcs!=PAWN) i+=snprintf(buf+i,128-i,"%c",pcschar[pcs]); if(cnt==0) i+=snprintf(buf+i,128-i,"%c",'a'+(from&0x7)); else if(row==0) i+=snprintf(buf+i,128-i,"%c",'1'+7-(from>>3)); if((brd->board[to]!=EMPTY)||(brd->ep==to)) i+=snprintf(buf+i,128-i,"x"); i+=snprintf(buf+i,128-i,"%s",coords[to]); if((move>>18)&PROMOTION) i+=snprintf(buf+i,128-i,"=%c",promchar(move)); if(mcheck==TRUE) i+=snprintf(buf+i,128-i,"%c",((mlm==0)?('#'):('+'))); return buf; } /* quarto passaggio: se la mossa resta ancora ambigua dobbiamo scrivere sia la casa di partenza che quella di destinazione */ i+=snprintf(buf+i,128-i,"%c%s",pcschar[pcs],coords[from]); if(brd->board[to]!=EMPTY) i+=snprintf(buf+i,128-i,"x"); i+=snprintf(buf+i,128-i,"%s",coords[to]); if(mcheck==TRUE) i+=snprintf(buf+i,128-i,"%c",((mlm==0)?('#'):('+'))); return buf; }
void xboard() { int computer_side; char line[256], command[256]; int m; int post = 0; signal(SIGINT, SIG_IGN); printf("\n"); init_board(); gen(); computer_side = EMPTY; for (;;) { fflush(stdout); if (side == computer_side) { think(post); if (!pv[0][0].u) { computer_side = EMPTY; continue; } printf("move %s\n", move_str(pv[0][0].b)); makemove(pv[0][0].b); ply = 0; gen(); print_result(); continue; } if (!fgets(line, 256, stdin)) return; if (line[0] == '\n') continue; sscanf(line, "%s", command); if (!strcmp(command, "xboard")) continue; if (!strcmp(command, "new")) { init_board(); gen(); computer_side = DARK; continue; } if (!strcmp(command, "quit")) return; if (!strcmp(command, "force")) { computer_side = EMPTY; continue; } if (!strcmp(command, "white")) { side = LIGHT; xside = DARK; gen(); computer_side = DARK; continue; } if (!strcmp(command, "black")) { side = DARK; xside = LIGHT; gen(); computer_side = LIGHT; continue; } if (!strcmp(command, "st")) { sscanf(line, "st %d", &max_time); max_time *= 1000; max_depth = 32; continue; } if (!strcmp(command, "sd")) { sscanf(line, "sd %d", &max_depth); max_time = 1 << 25; continue; } if (!strcmp(command, "time")) { sscanf(line, "time %d", &max_time); max_time *= 10; max_time /= 30; max_depth = 32; continue; } if (!strcmp(command, "otim")) { continue; } if (!strcmp(command, "go")) { computer_side = side; continue; } if (!strcmp(command, "hint")) { think(0); if (!pv[0][0].u) continue; printf("Hint: %s\n", move_str(pv[0][0].b)); continue; } if (!strcmp(command, "undo")) { if (!hply) continue; takeback(); ply = 0; gen(); continue; } if (!strcmp(command, "remove")) { if (hply < 2) continue; takeback(); takeback(); ply = 0; gen(); continue; } if (!strcmp(command, "post")) { post = 2; continue; } if (!strcmp(command, "nopost")) { post = 0; continue; } m = parse_move(line); if (m == -1 || !makemove(gen_dat[m].m.b)) printf("Error (unknown command): %s\n", command); else { ply = 0; gen(); print_result(); } } }
DWORD san2move(struct board_t *brd,char san[128]) { short c,d,idx,to,from,pcs,file,row,found,cap; short mvalid[MAXMOVES]; char buf[128]; char *str; DWORD promotion,mvs[MAXMOVES]; to=from=file=row=-1; cap=FALSE; pcs=PAWN; promotion=0; for(c=0;c<=127;c++) buf[c]=san[c]; buf[127]='\0'; str=buf; /* primo passaggio: cerchiamo di individuare subito gli arrocchi */ if(strncmp(buf,"O-O",strlen("O-O"))==0) { pcs=KING; from=((brd->color==WHITE)?(E1):(E8)); to=((brd->color==WHITE)?(G1):(G8)); goto third; } if(strncmp(buf,"O-O-O",strlen("O-O-O"))==0) { pcs=KING; from=((brd->color==WHITE)?(E1):(E8)); to=((brd->color==WHITE)?(C1):(C8)); goto third; } /* secondo passaggio: togliamo i caratteri inutili "x+#" e leggiamo la posizione SAN "normale" */ for(c=0;c<strlen(buf);c++) { if((buf[c]=='+')||(buf[c]=='#')||(buf[c]=='x')) { if(buf[c]=='x') cap=TRUE; for(d=c;d<strlen(buf);d++) buf[d]=buf[d+1]; } if((buf[c]=='=')&&(strlen(buf)==(c+2))) { promotion=promflags(buf[c+1]); buf[c]='\0'; } } if(strspn(buf,"123456789NBRQKabcdefgh")!=strlen(buf)) return 0; if((c=inarray(*san,"PNBRQK"))!=-1) { if(c==PAWN) return 0; pcs=c; *str++; } if((strlen(str)>=5)||(strlen(str)<=1)) return 0; if(strlen(str)==4) { if((from=findcoord(str))==-1) return 0; if((to=findcoord(str+2))==-1) return 0; } if(strlen(str)==3) { row=inarray(*str,"12345678"); file=inarray(*str,"abcdefgh"); if((to=findcoord(str+1))==-1) return 0; } if(strlen(str)==2) { if((to=findcoord(str))==-1) return 0; } third: /* terzo passaggio: generiamo tutte le mosse possibili ed escludiamo tutte quelle che non combaciano con i dati in nostro possesso */ idx=0; if(cap==TRUE) generate_captures(brd,mvs,&idx); else generate_moves(brd,mvs,&idx); for(c=0;c<idx;c++) { makemove(brd,mvs[c]); mvalid[c]=FALSE; if(is_in_check(brd,brd->color^1)==FALSE) { mvalid[c]=TRUE; if(((mvs[c]>>6)&0x3F)!=to) mvalid[c]=FALSE; else if(((mvs[c]>>12)&0x7)!=pcs) mvalid[c]=FALSE; else if((from!=-1)&&((mvs[c]&0x3F)!=from))
int Search::search(int depth, int alpha, int beta, _TpvLine *pline, int N_PIECE, int *mateIn) { ASSERT_RANGE(depth, 0, MAX_PLY); INC(cumulativeMovesCount); *mateIn = INT_MAX; ASSERT_RANGE(side, 0, 1); if (!getRunning()) { return 0; } int score = -_INFINITE; /* gtb */ if (gtb && pline->cmove && maxTimeMillsec > 1000 && gtb->isInstalledPieces(N_PIECE) && depth >= gtb->getProbeDepth()) { int v = gtb->getDtm<side, false>(chessboard, (uchar) chessboard[RIGHT_CASTLE_IDX], depth); if (abs(v) != INT_MAX) { *mateIn = v; int res = 0; if (v == 0) { res = 0; } else { res = _INFINITE - (abs(v)); if (v < 0) { res = -res; } } ASSERT_RANGE(res, -_INFINITE, _INFINITE); ASSERT(mainDepth >= depth); return res; } } u64 oldKey = chessboard[ZOBRISTKEY_IDX]; #ifdef DEBUG_MODE double betaEfficiencyCount = 0.0; #endif ASSERT(chessboard[KING_BLACK]); ASSERT(chessboard[KING_WHITE]); ASSERT(chessboard[KING_BLACK + side]); int extension = 0; int is_incheck_side = inCheck<side>(); if (!is_incheck_side && depth != mainDepth) { if (checkInsufficientMaterial(N_PIECE)) { if (inCheck<side ^ 1>()) { return _INFINITE - (mainDepth - depth + 1); } return -lazyEval<side>() * 2; } if (checkDraw(chessboard[ZOBRISTKEY_IDX])) { return -lazyEval<side>() * 2; } } if (is_incheck_side) { extension++; } depth += extension; if (depth == 0) { return quiescence<side, smp>(alpha, beta, -1, N_PIECE, 0); } //************* hash **************** u64 zobristKeyR = chessboard[ZOBRISTKEY_IDX] ^_random::RANDSIDE[side]; _TcheckHash checkHashStruct; if (checkHash<Hash::HASH_GREATER, smp>(false, alpha, beta, depth, zobristKeyR, checkHashStruct)) { return checkHashStruct.res; }; if (checkHash<Hash::HASH_ALWAYS, smp>(false, alpha, beta, depth, zobristKeyR, checkHashStruct)) { return checkHashStruct.res; }; ///********** end hash *************** if (!(numMoves & 1023)) { setRunning(checkTime()); } ++numMoves; ///********* null move *********** int n_pieces_side; _TpvLine line; line.cmove = 0; if (!is_incheck_side && !nullSearch && depth >= NULLMOVE_DEPTH && (n_pieces_side = getNpiecesNoPawnNoKing<side>()) >= NULLMOVES_MIN_PIECE) { nullSearch = true; int nullScore = -search<side ^ 1, smp>(depth - (NULLMOVES_R1 + (depth > (NULLMOVES_R2 + (n_pieces_side < NULLMOVES_R3 ? NULLMOVES_R4 : 0)))) - 1, -beta, -beta + 1, &line, N_PIECE, mateIn); nullSearch = false; if (nullScore >= beta) { INC(nNullMoveCut); return nullScore; } } ///******* null move end ******** /**************Futility Pruning****************/ /**************Futility Pruning razor at pre-pre-frontier*****/ bool futilPrune = false; int futilScore = 0; if (depth <= 3 && !is_incheck_side) { int matBalance = lazyEval<side>(); if ((futilScore = matBalance + FUTIL_MARGIN) <= alpha) { if (depth == 3 && (matBalance + RAZOR_MARGIN) <= alpha && getNpiecesNoPawnNoKing<side ^ 1>() > 3) { INC(nCutRazor); depth--; } else ///**************Futility Pruning at pre-frontier***** if (depth == 2 && (futilScore = matBalance + EXT_FUTILY_MARGIN) <= alpha) { futilPrune = true; score = futilScore; } else ///**************Futility Pruning at frontier***** if (depth == 1) { futilPrune = true; score = futilScore; } } } /************ end Futility Pruning*************/ incListId(); ASSERT_RANGE(KING_BLACK + side, 0, 11); ASSERT_RANGE(KING_BLACK + (side ^ 1), 0, 11); u64 friends = getBitmap<side>(); u64 enemies = getBitmap<side ^ 1>(); if (generateCaptures<side>(enemies, friends)) { decListId(); score = _INFINITE - (mainDepth - depth + 1); return score; } generateMoves<side>(friends | enemies); int listcount = getListSize(); if (!listcount) { --listId; if (is_incheck_side) { return -_INFINITE + (mainDepth - depth + 1); } else { return -lazyEval<side>() * 2; } } _Tmove *best = nullptr; if (checkHashStruct.hashFlag[Hash::HASH_GREATER]) { sortHashMoves(listId, checkHashStruct.phasheType[Hash::HASH_GREATER]); } else if (checkHashStruct.hashFlag[Hash::HASH_ALWAYS]) { sortHashMoves(listId, checkHashStruct.phasheType[Hash::HASH_ALWAYS]); } INC(totGen); _Tmove *move; bool checkInCheck = false; int countMove = 0; char hashf = Hash::hashfALPHA; while ((move = getNextMove(&gen_list[listId]))) { countMove++; INC(betaEfficiencyCount); if (!makemove(move, true, checkInCheck)) { takeback(move, oldKey, true); continue; } checkInCheck = true; if (futilPrune && ((move->type & 0x3) != PROMOTION_MOVE_MASK) && futilScore + PIECES_VALUE[move->capturedPiece] <= alpha && !inCheck<side>()) { INC(nCutFp); takeback(move, oldKey, true); continue; } //Late Move Reduction int val = INT_MAX; if (countMove > 4 && !is_incheck_side && depth >= 3 && move->capturedPiece == SQUARE_FREE && move->promotionPiece == NO_PROMOTION) { currentPly++; val = -search<side ^ 1, smp>(depth - 2, -(alpha + 1), -alpha, &line, N_PIECE, mateIn); ASSERT(val != INT_MAX); currentPly--; } if (val > alpha) { int doMws = (score > -_INFINITE + MAX_PLY); int lwb = max(alpha, score); int upb = (doMws ? (lwb + 1) : beta); currentPly++; val = -search<side ^ 1, smp>(depth - 1, -upb, -lwb, &line, move->capturedPiece == SQUARE_FREE ? N_PIECE : N_PIECE - 1, mateIn); ASSERT(val != INT_MAX); currentPly--; if (doMws && (lwb < val) && (val < beta)) { currentPly++; val = -search<side ^ 1, smp>(depth - 1, -beta, -val + 1, &line, move->capturedPiece == SQUARE_FREE ? N_PIECE : N_PIECE - 1, mateIn); currentPly--; } } score = max(score, val); takeback(move, oldKey, true); move->score = score; if (score > alpha) { if (score >= beta) { decListId(); ASSERT(move->score == score); INC(nCutAB); ADD(betaEfficiency, betaEfficiencyCount / (double) listcount * 100.0); ASSERT(checkHashStruct.rootHash[Hash::HASH_GREATER]); ASSERT(checkHashStruct.rootHash[Hash::HASH_ALWAYS]); recordHash<smp>(getRunning(), checkHashStruct.rootHash, depth - extension, Hash::hashfBETA, zobristKeyR, score, move); setKillerHeuristic(move->from, move->to, 0x400); return score; } alpha = score; hashf = Hash::hashfEXACT; best = move; move->score = score; //used in it updatePv(pline, &line, move); } } ASSERT(checkHashStruct.rootHash[Hash::HASH_GREATER]); ASSERT(checkHashStruct.rootHash[Hash::HASH_ALWAYS]); recordHash<smp>(getRunning(), checkHashStruct.rootHash, depth - extension, hashf, zobristKeyR, score, best); decListId(); return score; }
/* ***********************************************************/ int main(int argc, char* argv[]) { GR_EVENT event; GR_WM_PROPERTIES props; int computer_side; char s[256]; int i; BOOL found; char temp[50]; if (GrOpen() < 0) { fprintf(stderr, "tuxchess: cannot open graphics\n"); exit(1); } load_images(); master = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0, BM_WIDTH, BM_HEIGHT, 0, WHITE, WHITE); board = GrNewWindow((GR_WINDOW_ID) master, 0, 0, 394, 394, 0, WHITE, WHITE); text = GrNewWindow((GR_WINDOW_ID) master, 0, 393, 394, 20, 0, BLACK, BLACK); GrSelectEvents(master, GR_EVENT_MASK_CLOSE_REQ | GR_EVENT_MASK_EXPOSURE | GR_EVENT_MASK_BUTTON_DOWN); props.flags = GR_WM_FLAGS_PROPS | GR_WM_FLAGS_TITLE; props.props = GR_WM_PROPS_BORDER | GR_WM_PROPS_CAPTION | GR_WM_PROPS_CLOSEBOX; props.title = TITLE; GrSetWMProperties(master, &props); /* eliminate white background*/ props.flags = GR_WM_FLAGS_PROPS; props.props = GR_WM_PROPS_NOBACKGROUND; GrSetWMProperties(board, &props); GrMapWindow(master); GrMapWindow(board); GrMapWindow(text); gc = GrNewGC(); text_gc = GrNewGC(); init(); gen(); max_time = 1 << 25; max_depth = 4; if (argc > 1) computer_side = side; /* computer plays white */ else { computer_side = EMPTY; /* human plays white */ gprintf("Make a move..."); } for (;;) { if (side == computer_side) { /* think about the move and make it */ think(0); if (!pv[0][0].u) { gprintf("No legal moves"); computer_side = EMPTY; continue; } sprintf(temp,"Computer's move: %s\n", move_str(pv[0][0].b)); gprintf(temp); makemove(pv[0][0].b); ply = 0; gen(); print_board(); print_result(); continue; } GrGetNextEvent(&event); switch(event.type) { case GR_EVENT_TYPE_CLOSE_REQ: GrClose(); exit(0); /* no return*/ case GR_EVENT_TYPE_EXPOSURE: print_board(); gprintf(NULL); break; case GR_EVENT_TYPE_BUTTON_DOWN: mouse_hit(event.button.x, event.button.y); break; } if (to != 999) { /* loop through the moves to see if it's legal */ found = FALSE; for (i = 0; i < first_move[1]; ++i) if (gen_dat[i].m.b.from == from && gen_dat[i].m.b.to == to) { found = TRUE; /* get the promotion piece right */ if (gen_dat[i].m.b.bits & 32) switch (s[4]) { case 'N': break; case 'B': i += 1; break; case 'R': i += 2; break; default: i += 3; break; } break; } /* if */ if (!found || !makemove(gen_dat[i].m.b)) gprintf("Illegal move.\n"); else { ply = 0; gen(); print_board(); print_result(); computer_side = side; to = 999; } } /* if to != 999 */ } /* for (;;) */ return(0); /* never reached */ }
int main() { int computer_side; char s[256]; int m; printf("\n"); printf("Tom Kerrigan's Simple Chess Program (TSCP)\n"); printf("version 1.81, 2/5/03\n"); printf("Copyright 1997 Tom Kerrigan\n"); printf("\n"); printf("\"help\" displays a list of commands.\n"); printf("\n"); init_hash(); init_board(); open_book(); gen(); computer_side = EMPTY; max_time = 1 << 25; max_depth = 4; for (;;) { if (side == computer_side) { /* computer's turn */ /* think about the move and make it */ think(1); if (!pv[0][0].u) { printf("(no legal moves)\n"); computer_side = EMPTY; continue; } printf("Computer's move: %s\n", move_str(pv[0][0].b)); makemove(pv[0][0].b); ply = 0; gen(); print_result(); continue; } /* get user input */ printf("tscp> "); if (scanf("%s", s) == EOF) return 0; if (!strcmp(s, "on")) { computer_side = side; continue; } if (!strcmp(s, "off")) { computer_side = EMPTY; continue; } if (!strcmp(s, "st")) { scanf("%d", &max_time); max_time *= 1000; max_depth = 32; continue; } if (!strcmp(s, "sd")) { scanf("%d", &max_depth); max_time = 1 << 25; continue; } if (!strcmp(s, "undo")) { if (!hply) continue; computer_side = EMPTY; takeback(); ply = 0; gen(); continue; } if (!strcmp(s, "new")) { computer_side = EMPTY; init_board(); gen(); continue; } if (!strcmp(s, "d")) { print_board(); continue; } if (!strcmp(s, "bench")) { computer_side = EMPTY; bench(); continue; } if (!strcmp(s, "bye")) { printf("Share and enjoy!\n"); break; } if (!strcmp(s, "xboard")) { xboard(); break; } if (!strcmp(s, "help")) { printf("on - computer plays for the side to move\n"); printf("off - computer stops playing\n"); printf("st n - search for n seconds per move\n"); printf("sd n - search n ply per move\n"); printf("undo - takes back a move\n"); printf("new - starts a new game\n"); printf("d - display the board\n"); printf("bench - run the built-in benchmark\n"); printf("bye - exit the program\n"); printf("xboard - switch to XBoard mode\n"); printf("Enter moves in coordinate notation, e.g., e2e4, e7e8Q\n"); continue; } /* maybe the user entered a move? */ m = parse_move(s); if (m == -1 || !makemove(gen_dat[m].m.b)) printf("Illegal move.\n"); else { ply = 0; gen(); print_result(); } } close_book(); return 0; }
int strategize () { dwait (D_CONTROL, "Strategizing..."); /* If replaying, instead of making an action, return the old one */ if (replaying) return (replaycommand ()); /* Clear any messages we printed last turn */ if (msgonscreen) { at (0,0); clrtoeol (); msgonscreen = 0; at (row,col); } /* ----------------------- Production Rules --------------------------- */ if (fightmonster ()) /* We are under attack! */ return (1); if (fightinvisible ()) /* Claude Raines! */ return (1); if (tomonster ()) /* Go play with the pretty monster */ return (1); if (shootindark ()) /* Shoot arrows in dark rooms */ return (1); if (handleweapon ()) /* Play with the nice sword */ { dwait (D_BATTLE, "Switching to sword [1]"); return (1); } if (light ()) /* Fiat lux! Especially if we lost */ return (1); /* a monster from view. */ if (dinnertime ()) /* Soups on! */ return (1); /* * These variables are short term memory. Slowed and * cancelled are fuses which are disabled after a small * number of turns. */ lyinginwait = 0; /* No more monsters to wait for */ if (foughtmonster) foughtmonster--; /* Turns since fought monster */ if (slowed) slowed--; /* Turns since we slowed a monster */ if (cancelled) cancelled--; /* Turns since we zapped 'cancel' */ if (beingheld) beingheld--; /* Turns since held by a fungus */ /* ---- End of short term memory modification ---- */ if (dropjunk ()) /* Send it back */ return (1); if (readscroll ()) /* Get out the reading glasses */ return (1); /* Must come before handlearmor() */ if (handlearmor ()) /* Play dressup */ return (1); if (quaffpotion ()) /* Glug glug glug ... */ return (1); /* Must come before handlering() */ if (handlering ()) /* We are engaged! */ return (1); if (blinded && grope (50)) /* Who turned out the lights */ { display ("Blinded, groping..."); return (1); } if (aftermelee ()) /* Wait for lingering monsters */ return (1); if (tostuff ()) /* Pick up the play pretty */ return (1); if (restup ()) /* Yawn! */ return (1); if (goupstairs (NOTRUNNING)) /* Up we go! Make sure that we get */ return (1); /* a better rank on the board. */ if (trywand ()) /* Try to use a wand */ return (1); if (gotowardsgoal ()) /* Keep on trucking */ return (1); if (exploreroom ()) /* Search the room */ return (1); if (archery ()) /* Try to position for fight */ return (1); if (pickupafter ()) /* Look for stuff dropped by arched mon */ return (1); if (plunge ()) /* Plunge mode */ return (1); if (findarrow ()) /* Do we have an unitialized arrow? */ return (1); if (findroom ()) /* Look for another room */ return (1); /* * 'attempt' records the number of times we have completely searched * this level for secret doors. If attempt is greater than 0, then we * have failed once to find the stairs and go down. If this happens * three times, there could be amonster sleeping on the stairs. We set * the SLEEPER bit for each square with a sleeping monster. Go find * such a monster and kill it to see whether (s)he was on the stairs). */ if (attempt > 4 && makemove (ATTACKSLEEP, genericinit, sleepvalue, REUSE)) { display ("No stairs, attacking sleeping monster..."); return (1); } if (Level>1 && larder>0 && doorexplore ()) /* Grub around */ return (1); if (godownstairs (NOTRUNNING)) /* Down we go! */ return (1); if ((Level<2 || larder<1) && doorexplore()) /* Grub around anyway */ return (1); /* * If we think we are on the stairs, but arent, maybe they were moved * (ie we were hallucinating when we saw them last time). */ if (on (STAIRS) && (atrow != stairrow || atcol != staircol)) { dwait (D_ERROR, "Stairs moved!"); findstairs (NONE, NONE); return (1); } /* * If we failed to find the stairs, explore each possible secret door * another ten times. */ while (attempt++ < MAXATTEMPTS) { timestosearch += max (3, k_door / 5); foundnew (); if (doorexplore ()) return (1); } /* * Don't give up, start all over! */ newlevel (); display ("I would give up, but I am too stubborn, starting over..."); return (grope (10)); }
int main(int argc, char *argv[]) { /* Seed randomness. */ srand(time(NULL) ^ getpid()); bake_args(argc, argv); initgame(); do { if(thegame.players == 1) whatside(); else player = X; thegame.restart = false; cleargame(); while(thegame.running) { if(thegame.players == 0) { printboard(false); compmove(player); if(checkwinner()) break; compmove(-player); } else if(thegame.players == 1) { if(player == X){ printboard(true); makemove(player); if(checkwinner()) break; compmove(-player); } else { compmove(-player); if(checkwinner()) break; printboard(true); makemove(player); } } else { printboard(true); makemove(player); player = -player; } checkwinner(); } printwinner(); restart(); } while(thegame.restart); /* we so funny */ if(thegame.players == 0) wargames(); return 0; }
int mainConsoleChess(int pick_side) { int computer_side; char s[256]; int m; printf("\n"); printf("Phung Nhat Huy and Pham Duy Hung's Console Chess\n"); printf("\n"); printf("Type \"help\" to displays a list of commands.\n"); printf("\n"); init_hash(); init_board(); gen(); computer_side = EMPTY; max_time = 1 << 25; max_depth = 4; for (;;) { if (side == computer_side) { /* computer's turn */ /* think about the move and make it */ //think(1); if (!pv[0][0].u) { printf("(no legal moves)\n"); computer_side = EMPTY; continue; } printf("Your enermy's move: %s\n", move_str(pv[0][0].b)); makemove(pv[0][0].b); ply = 0; gen(); print_result(); continue; } /* get user input */ printf("ConsoleChess > "); if (scanf("%s", s) == EOF) return 0; if (!strcmp(s, "on")) { computer_side = side; continue; } if (!strcmp(s, "off")) { computer_side = EMPTY; continue; } if (!strcmp(s, "undo")) { if (!hply) continue; computer_side = EMPTY; takeback(); ply = 0; gen(); continue; } if (!strcmp(s, "new")) { computer_side = EMPTY; init_board(); gen(); continue; } if (!strcmp(s, "d")) { print_board(); continue; } /*if (!strcmp(s, "bench")) { computer_side = EMPTY; bench(); continue; }*/ if (!strcmp(s, "bye")) { printf("Thanks for playing. Enjoy!\n"); break; } if (!strcmp(s, "help")) { printf("on - computer plays for the side to move\n"); printf("off - computer stops playing\n"); printf("undo - takes back a move\n"); printf("new - starts a new game\n"); printf("d - display the board\n"); printf("bye - exit the program\n"); printf("Enter moves in coordinate notation, e.g., e2e4, e7e8Q (for promote moving)\n"); continue; } /* maybe the user entered a move? */ m = parse_move(s); if (m == -1 || !makemove(gen_dat[m].m.b)) printf("Illegal move.\n"); else { ply = 0; gen(); print_result(); } } //close_book(); return 0; }
score_t search_ab(boost::shared_ptr<search_info> proc_info) { if(proc_info->get_abort()) return bad_min_score; // Unmarshall the info struct node_t board = proc_info->board; const int depth = proc_info->depth; if(depth != board.depth) { std::cout << "depth=" << depth << "board.depth=" << board.depth << std::endl; } assert(depth == board.depth); score_t alpha = proc_info->alpha; score_t beta = proc_info->beta; assert(depth >= 0); std::ostringstream strB; print_board(board, strB, true); std::string strBoard = strB.str(); // if we are a leaf node, return the value from the eval() function if (depth == 0) { evaluator ev; DECL_SCORE(s,ev.eval(board, chosen_evaluator),board.hash); return s; } /* if this isn't the root of the search tree (where we have to pick a chess_move and can't simply return 0) then check to see if the position is a repeat. if so, we can assume that this line is a draw and return 0. */ if (board.ply && reps(board)==3) { DECL_SCORE(z,0,board.hash); proc_info->draw = true; return z; } // fifty chess_move draw rule if (board.fifty >= 100) { DECL_SCORE(z,0,board.hash); proc_info->draw = true; return z; } score_t max_val = bad_min_score; score_t p_board = board.p_board; score_t zlo = bad_min_score,zhi = bad_max_score; bool white =board.side == LIGHT; bool entry_found = false; int excess =0; bool exact = false; if (white && board.root_side == LIGHT && db_on && board.ply > 0 && !proc_info->quiescent){ entry_found = dbase.get_transposition_value (board, zlo, zhi, white,p_board,excess,exact,board.depth); int pe = proc_info->excess; if (excess > proc_info->excess){ proc_info->excess = excess; //if (!board.follow_capt && search_method == MTDF) board.follow_capt = true; } else{ //board.follow_depth = 0; } if(entry_found && excess > 0) { assert(depth == board.depth); std::cout << "excess = " << (excess+depth) << std::endl; zhi = bad_max_score; verify(strBoard,board.side,depth+excess,board.castle,board.ep,zlo,bad_max_score); } } if (entry_found){ return zlo; } if(!entry_found) { entry_found = get_transposition_value (board, zlo, zhi); if(!entry_found && db_on && board.side == LIGHT){ entry_found = dbase.get_transposition_value(board,zlo,zhi,white,p_board,excess,true,depth); verify(strBoard,board.side,depth,board.castle,board.ep,zlo,zhi); } } if (entry_found) { if(zlo >= beta) { return zlo; } if(alpha >= zhi) { return zhi; } alpha = max(zlo,alpha); beta = min(zhi,beta); } if(alpha >= beta) { //proc_info->stop=false; //deeper= false; return alpha; } const score_t alpha0 = alpha; std::vector<chess_move> workq; std::vector<chess_move> max_move; gen(workq, board); // Generate the moves #ifdef PV_ON if(!proc_info->use_srand) proc_info->incr = rand(); proc_info->use_srand = false; srand(proc_info->incr); sort_pv(workq, board.depth); // Part of iterative deepening #endif const int worksq = workq.size(); std::vector<boost::shared_ptr<task> > tasks; int j=0; score_t val; bool aborted = false; bool children_aborted = false; // loop through the moves //for (; j < worksq; j++) while(j < worksq) { while(j < worksq) { chess_move g = workq[j++]; boost::shared_ptr<search_info> child_info{new search_info(board)}; bool parallel; if (!aborted && !proc_info->get_abort() && makemove(child_info->board, g)) { parallel = j > 0 && !capture(board,g); boost::shared_ptr<task> t = parallel_task(depth, ¶llel); t->info = child_info; int d = depth - 1; if(!test_alphabeta && d == 0 && capture(board,g)) { d = 1; /* if(!proc_info->quiescent) { t->info->alpha = bad_min_score; t->info->beta = bad_max_score; } */ t->info->quiescent = true; } else if(proc_info->quiescent) { t->info->quiescent = true; } t->info->board.depth = child_info->depth = d; assert(depth >= 0); t->info->alpha = -beta; t->info->beta = -alpha; t->info->mv = g; t->pfunc = search_ab_f; t->start(); tasks.push_back(t); // Control branching if (!parallel) break; /* else if (beta >= max_score*.9) continue; */ else if (tasks.size() < 5) continue; else break; } } When when(tasks); size_t const count = tasks.size(); for(size_t n_=0;n_<count;n_++) { int n = when.any(); boost::shared_ptr<task> child_task = tasks[n]; //assert(child_task.valid()); child_task->join(); boost::shared_ptr<search_info> child_info = child_task->info; tasks.erase(tasks.begin()+n); if(!children_aborted && (aborted || child_info->get_abort())) { for(unsigned int m = 0;m < tasks.size();m++) { tasks[m]->info->set_abort(true); } children_aborted = true; } //child_task->join(); if(child_info->get_abort()) continue; if(child_info->draw) proc_info->draw = true; val = -child_info->result; proc_info->log << " " << child_info->mv << "=" << val; bool found = false; if (child_info->excess > proc_info->excess){ proc_info->excess = child_info->excess; found = true; if (!board.follow_capt){ board.follow_capt = true; } } if (val > max_val || found ) { max_move.clear(); max_move.push_back(child_info->mv); if (val > max_val) max_val = val; if (val > alpha) { alpha = val; #ifdef PV_ON if(!child_info->get_abort()) ;//pv[board.search_depth - 1].set(child_info->mv); #endif if(alpha >= beta) { //aborted = true; j += worksq; continue; } } } else if(val == max_val && proc_info->excess == 0) { max_move.push_back(child_info->mv); } } if(alpha >= beta) { j += worksq; break; } } // no legal moves? then we're in checkmate or stalemate if (max_move.size()==0) { if (in_check(board, board.side)) { DECL_SCORE(s,max_score,board.hash); return s; } else { DECL_SCORE(z,0,board.hash); return z; } } if(db_on) { if (board.ply == 0 || board.depth>0) { assert(max_move.size() != 0); ScopedLock s(cmutex); move_to_make = max_move.at(rand() % max_move.size()); } } bool store = true; if(proc_info->draw) { store = false; } if(proc_info->quiescent) store = false; score_t lo, hi; if(proc_info->excess) { lo = max_val; hi = max_score; //std::cout<<"Max depth: "<<proc_info->excess+depth<<std::endl; store = false; } else if(alpha0 < max_val && max_val < beta) { lo = max_val-1; hi = max_val; } else if(max_val <= alpha0) { hi = max_val; lo = zlo; if(lo == zlo) store = false; } else if (max_val >= beta){ lo = max_val; hi = zhi; if(hi == zhi) store = false; } else { store = false; lo = hi = 0; } if(store && lo > hi) { std::cout << "lo=" << lo << " hi=" << hi << std::endl; abort(); } if(store && db_on) { verify(strBoard,board.side,depth,board.castle,board.ep,lo,hi); } if(store) { //if(board.depth > 1) dbase.add_data(board,lo,hi,white,proc_info->excess); set_transposition_value(board,lo,hi); } return max_val; }
int search(int alpha, int beta, int depth) { int i, j, x; BOOL c, f; /* we're as deep as we want to be; call quiesce() to get a reasonable score and return it. */ if (!depth) return quiesce(alpha,beta); ++nodes; /* do some housekeeping every 1024 nodes */ if ((nodes & 1023) == 0) checkup(); pv_length[ply] = ply; /* if this isn't the root of the search tree (where we have to pick a move and can't simply return 0) then check to see if the position is a repeat. if so, we can assume that this line is a draw and return 0. */ if (ply && reps()) return 0; /* are we too deep? */ if (ply >= MAX_PLY - 1) return eval(); if (hply >= HIST_STACK - 1) return eval(); /* are we in check? if so, we want to search deeper */ c = in_check(side); if (c) ++depth; gen(); if (follow_pv) /* are we following the PV? */ sort_pv(); f = FALSE; /* loop through the moves */ for (i = first_move[ply]; i < first_move[ply + 1]; ++i) { sort(i); if (!makemove(gen_dat[i].m.b)) continue; f = TRUE; x = -search(-beta, -alpha, depth - 1); takeback(); if (x > alpha) { /* this move caused a cutoff, so increase the history value so it gets ordered high next time we can search it */ history[(int)gen_dat[i].m.b.from][(int)gen_dat[i].m.b.to] += depth; if (x >= beta) return beta; alpha = x; /* update the PV */ pv[ply][ply] = gen_dat[i].m; for (j = ply + 1; j < pv_length[ply + 1]; ++j) pv[ply][j] = pv[ply + 1][j]; pv_length[ply] = pv_length[ply + 1]; } } /* no legal moves? then we're in checkmate or stalemate */ if (!f) { if (c) return -10000 + ply; else return 0; } /* fifty move draw rule */ if (fifty >= 100) return 0; return alpha; }
int Search::quiescence(int alpha, int beta, const char promotionPiece, int N_PIECE, int depth) { if (!getRunning()) { return 0; } ASSERT(chessboard[KING_BLACK + side]); if (!(numMovesq++ & 1023)) { setRunning(checkTime()); } int score = getScore(side, N_PIECE, alpha, beta, false); if (score >= beta) { return beta; } ///************* hash **************** char hashf = Hash::hashfALPHA; u64 zobristKeyR = chessboard[ZOBRISTKEY_IDX] ^_random::RANDSIDE[side]; _TcheckHash checkHashStruct; if (checkHash<Hash::HASH_GREATER, smp>(true, alpha, beta, depth, zobristKeyR, checkHashStruct)) { return checkHashStruct.res; }; if (checkHash<Hash::HASH_ALWAYS, smp>(true, alpha, beta, depth, zobristKeyR, checkHashStruct)) { return checkHashStruct.res; }; ///********** end hash *************** /**************Delta Pruning ****************/ char fprune = 0; int fscore; if ((fscore = score + (promotionPiece == NO_PROMOTION ? VALUEQUEEN : 2 * VALUEQUEEN)) < alpha) { fprune = 1; } /************ end Delta Pruning *************/ if (score > alpha) { alpha = score; } incListId(); u64 friends = getBitmap<side>(); u64 enemies = getBitmap<side ^ 1>(); if (generateCaptures<side>(enemies, friends)) { decListId(); return _INFINITE - (mainDepth + depth); } if (!getListSize()) { --listId; return score; } _Tmove *move; _Tmove *best = nullptr; u64 oldKey = chessboard[ZOBRISTKEY_IDX]; if (checkHashStruct.hashFlag[Hash::HASH_GREATER]) { sortHashMoves(listId, checkHashStruct.phasheType[Hash::HASH_GREATER]); } else if (checkHashStruct.hashFlag[Hash::HASH_ALWAYS]) { sortHashMoves(listId, checkHashStruct.phasheType[Hash::HASH_ALWAYS]); } while ((move = getNextMove(&gen_list[listId]))) { if (!makemove(move, false, true)) { takeback(move, oldKey, false); continue; } /**************Delta Pruning ****************/ if (fprune && ((move->type & 0x3) != PROMOTION_MOVE_MASK) && fscore + PIECES_VALUE[move->capturedPiece] <= alpha) { INC(nCutFp); takeback(move, oldKey, false); continue; } /************ end Delta Pruning *************/ int val = -quiescence<side ^ 1, smp>(-beta, -alpha, move->promotionPiece, N_PIECE - 1, depth - 1); score = max(score, val); takeback(move, oldKey, false); if (score > alpha) { if (score >= beta) { decListId(); ASSERT(checkHashStruct.rootHash[Hash::HASH_GREATER]); ASSERT(checkHashStruct.rootHash[Hash::HASH_ALWAYS]); recordHash<smp>(getRunning(), checkHashStruct.rootHash, depth, Hash::hashfBETA, zobristKeyR, score, move); return beta; } best = move; alpha = score; hashf = Hash::hashfEXACT; } } ASSERT(checkHashStruct.rootHash[Hash::HASH_GREATER]); ASSERT(checkHashStruct.rootHash[Hash::HASH_ALWAYS]); recordHash<smp>(getRunning(), checkHashStruct.rootHash, depth, hashf, zobristKeyR, score, best); decListId(); return score; }