void perft_divide(int depth) { char str[10]; unsigned moves[256], count, i; double timespan; uint64_t total, perft; clock_t start, end; printf("Divide (depth %02i)\n", depth); printf("--------------------\n"); start = clock(); count = gen_moves(moves); total = 0, perft = 0; for(i = 0; i < count; i++) { if(board_add(moves[i])) { perft = perft_perft(depth-1); board_subtract(); total += perft; move_to_string(moves[i], str); printf("%-5s %10llu\n", str, (long long unsigned int)perft); } } end = clock(); timespan = (double)(end - start) / CLOCKS_PER_SEC; printf("\nTotal %10llu\n", (long long unsigned int)total); printf("Time %9.3fs\n", timespan); printf("Moves/s %12.1f\n", total/timespan); }
static void nboard_send_move(Result *result) { char move[4]; move_to_string(result->move, WHITE, move); nboard_send("=== %s %.2f %.1f", move, 1.0 * result->score, 0.001 * result->time); }
void search_update_root() { int move, move_pos, move_nb; double time; sint64 node_nb; char move_string[256]; if (DispRoot) { search_update_current(); if (SearchCurrent->time >= 1.0) { move = SearchRoot->move; move_pos = SearchRoot->move_pos; move_nb = SearchRoot->move_nb; time = SearchCurrent->time; node_nb = SearchCurrent->node_nb; move_to_string(move,move_string,256); send("info currmove %s currmovenumber %d",move_string,move_pos+1); } } }
void describe_moves(unsigned *moves, unsigned move_count) { unsigned i; char str[6]; for(i = 0; i < move_count; i++) { move_to_string(moves[i], str); printf("%u %s\n", i, str); } }
bool pv_to_string(const mv_t pv[], char string[], int size) { int pos; int move; ASSERT(pv_is_ok(pv)); ASSERT(string!=NULL); ASSERT(size>=512); // init if (size < 512) return false; pos = 0; // loop while ((move = *pv++) != MoveNone) { if (pos != 0) string[pos++] = ' '; move_to_string(move,&string[pos],size-pos); pos += strlen(&string[pos]); } string[pos] = '\0'; return true; }
static void send_best_move() { double time, speed, cpu; sint64 node_nb; char move_string[256]; char ponder_string[256]; int move; mv_t * pv; // info // HACK: should be in search.cpp time = SearchCurrent->time; speed = SearchCurrent->speed; cpu = SearchCurrent->cpu; node_nb = SearchCurrent->node_nb; send("info time %.0f nodes " S64_FORMAT " nps %.0f cpuload %.0f",time*1000.0,node_nb,speed,cpu*1000.0); trans_stats(Trans); // pawn_stats(); // material_stats(); // best move move = SearchBest[0].move; pv = SearchBest[0].pv; move_to_string(move,move_string,256); if (pv[0] == move && move_is_ok(pv[1])) { move_to_string(pv[1],ponder_string,256); send("bestmove %s ponder %s",move_string,ponder_string); } else { send("bestmove %s",move_string); } // PRS+ (exit after sending best move) ASSERT(!Searching); ASSERT(!Delay); exit(EXIT_SUCCESS); }
void TEngine::AddMove(mv_t move) { undo_t undo; move_do(&Board,move,&undo); char move_str[6]; strcat(move_history," "); move_to_string(move,move_str,6); strcat(move_history,move_str); move_history_len++; }
/** * @brief ui_ggs_update * * Update a game. * * @param ui User Interface. */ static void ui_ggs_update(UI *ui) { char buffer[256], s_move[4]; Play *play; int edax_turn, turn; Board board[1]; printf("[received GGS_BOARD_UPDATE]\n"); // set correct played game if (strcmp(ui->ggs->board->player[0].name, ui->ggs->me) == 0) { play = ui->play; edax_turn = BLACK; } else if (strcmp(ui->ggs->board->player[1].name, ui->ggs->me) == 0) { play = ui->play + 1; edax_turn = WHITE; } else { return ; } if (!ui->ggs->board->match_type->is_synchro) play = ui->play; // set board as an edax's board sprintf(buffer, "%s %c", ui->ggs->board->board, ui->ggs->board->turn); turn = board_set(board, buffer); // update the board... if possible if (!play_move(play, ui->ggs->board->move)) { info("<Updating with bad move %s>\n", move_to_string(ui->ggs->board->move, play->player, s_move)); } if (!board_equal(board, play->board)) { // may happens when game diverges info("<Resynchronize boards: diverging games>\n"); *play->board = *board; play->player = turn; } if (turn != play->player) { // should never happen: TODO fatal error? printf("[WARNING: updating player's turn]\n"); play->player = turn; } printf("[%s's turn in game %s]\n", ui->ggs->board->player[play->player].name, ui->ggs->board->id); // playing same game... ? ui->is_same_play = (!ui->ggs->board->match_type->is_synchro || board_equal(ui->play[0].board, ui->play[1].board)); if (ui->is_same_play) printf("<Playing same game...>\n"); // set time & start thinking if (play->player == edax_turn) { printf("<My turn>\n"); ui_ggs_play(ui, edax_turn); } else { printf("<Opponent turn>\n"); ui_ggs_ponder(ui, edax_turn); } }
/* Returns a move if it exists. Otherwise results EMPTY */ unsigned find_move(char* move_string) { unsigned i, move_count, moves[256]; char str[6]; move_count = gen_moves(moves); for(i = 0; i < move_count; i++) { move_to_string(moves[i], str); if(strncmp(str, move_string, strlen(str)) == 0) return moves[i]; } return EMPTY; }
bool test_generator(const unsigned long long flipped, const unsigned long long P, const unsigned long long O, const int x0) { if (flipped != flip_slow(P, O, x0)) { Board b[1]; char s[3] = "--"; b->player = P; b->opponent = O; board_print(b, BLACK, stderr); fprintf(stderr, "move wrong : %s\n", move_to_string(x0, BLACK, s)); bitboard_write(flipped, stderr); return true; } return false; }
/** * @brief ui_ggs_join * * Join a new game. * This is a new game from Edax point of view. * This may be a saved game from GGS side. * * @param ui User Interface. */ static void ui_ggs_join(UI *ui) { char buffer[256]; char s_move[4]; Play *play; int edax_turn, i; printf("[received GGS_BOARD_JOIN]\n"); // set correct played game if (strcmp(ui->ggs->board->player[0].name, ui->ggs->me) == 0) { play = ui->play; edax_turn = BLACK; } else if (strcmp(ui->ggs->board->player[1].name, ui->ggs->me) == 0) { play = ui->play + 1; edax_turn = WHITE; } else { warn("Edax is not concerned by this game\n"); return ; } // non synchro games => play a single match if (!ui->ggs->board->match_type->is_synchro) play = ui->play; // set board sprintf(buffer, "%s %c", ui->ggs->board->board_init, ui->ggs->board->turn_init); play_set_board(play, buffer); for (i = 0; i < ui->ggs->board->move_list_n; i++) { if (!play_move(play, ui->ggs->board->move_list[i])) { error("cannot play GGS move %s ?", move_to_string(ui->ggs->board->move_list[i], play->player, s_move)); break; } } printf("[%s's turn in game %s]\n", ui->ggs->board->player[play->player].name, ui->ggs->board->id); board_print(play->board, play->player, stdout); ui->is_same_play = (ui->ggs->board->move_list_n == 0 || board_equal(ui->play[0].board, ui->play[1].board) || !ui->ggs->board->match_type->is_synchro); if (ui->is_same_play) printf("[Playing same game]\n"); // set time & start thinking if (play->player == edax_turn) { printf("<My turn>\n"); ggs_client_send(ui->ggs, "tell .%s =====================================\n", ui->ggs->me); ui_ggs_play(ui, edax_turn); ui_ggs_ponder(ui, edax_turn); } else { printf("[Waiting opponent move]\n"); // ui_ggs_ponder(ui, edax_turn); } }
static void send_best_move() { double time, speed, cpu; sint64 node_nb; char move_string[256]; char ponder_string[256]; int move; mv_t * pv; // info // HACK: should be in search.cpp time = SearchCurrent->time; speed = SearchCurrent->speed; cpu = SearchCurrent->cpu; node_nb = search_update_node_nb(); send("info time %.0f nodes " S64_FORMAT " nps %.0f cpuload %.0f",time*1000.0,node_nb,speed,cpu*1000.0); trans_stats(); // best move move = SearchBest->move; pv = SearchBest->pv; move_to_string(move,move_string,256); if (pv[0] == move && move_is_ok(pv[1])) { move_to_string(pv[1],ponder_string,256); send("bestmove %s ponder %s",move_string,ponder_string); } else { send("bestmove %s",move_string); } }
void search_update_root() { if (DispRoot) { search_update_current(); if (SearchCurrent->time >= 1.0) { const U16 move = SearchRoot->move, move_pos = SearchRoot->move_pos;//, move_nb = SearchRoot->move_nb; //double time = SearchCurrent->time; //S64 node_nb = SearchCurrent->node_nb; char move_string[256]; move_to_string(move, move_string, 256); send("info currmove %s currmovenumber %d", move_string, move_pos + 1); } } }
void TEngine::StartNewThink() { Process->Send("stop"); Sleep(10); AnsiString pos = "position startpos"; if (move_history_len > 0 || LastMove) { pos += " moves"; pos += move_history; if (LastMove) { char move_str[6] = ""; move_to_string(LastMove,move_str,6); pos += " "; pos += move_str; } } Process->Send(pos); for (int i=0; i<100; i++) PV[i].pv_len = 0; Process->Send("go infinite"); }
void search_update_best() { int move, value, flags, depth, max_depth; const mv_t * pv; double time; sint64 node_nb; int mate, i, z; bool found; char move_string[256], pv_string[512]; search_update_current(); if (DispBest) { move = SearchBest[SearchCurrent->multipv].move; value = SearchBest[SearchCurrent->multipv].value; flags = SearchBest[SearchCurrent->multipv].flags; depth = SearchBest[SearchCurrent->multipv].depth; pv = SearchBest[SearchCurrent->multipv].pv; max_depth = SearchCurrent->max_depth; time = SearchCurrent->time; node_nb = SearchCurrent->node_nb; move_to_string(move,move_string,256); pv_to_string(pv,pv_string,512); mate = value_to_mate(value); if (SearchCurrent->multipv == 0){ save_multipv[SearchCurrent->multipv].mate = mate; save_multipv[SearchCurrent->multipv].depth = depth; save_multipv[SearchCurrent->multipv].max_depth = max_depth; save_multipv[SearchCurrent->multipv].value = value; save_multipv[SearchCurrent->multipv].time = time*1000.0; save_multipv[SearchCurrent->multipv].node_nb = node_nb; strcpy(save_multipv[SearchCurrent->multipv].pv_string,pv_string); } else{ found = false; for (i = 0; i < SearchCurrent->multipv; i++){ if (save_multipv[i].value < value){ found = true; break; } } if (found){ for (z = SearchCurrent->multipv; z > i; z--){ save_multipv[z].mate = save_multipv[z-1].mate; save_multipv[z].depth = save_multipv[z-1].depth; save_multipv[z].max_depth = save_multipv[z-1].max_depth; save_multipv[z].value = save_multipv[z-1].value; save_multipv[z].time = save_multipv[z-1].time; save_multipv[z].node_nb = save_multipv[z-1].node_nb; strcpy(save_multipv[z].pv_string,save_multipv[z-1].pv_string); } save_multipv[i].mate = mate; save_multipv[i].depth = depth; save_multipv[i].max_depth = max_depth; save_multipv[i].value = value; save_multipv[i].time = time*1000.0; save_multipv[i].node_nb = node_nb; strcpy(save_multipv[i].pv_string,pv_string); } else{ save_multipv[SearchCurrent->multipv].mate = mate; save_multipv[SearchCurrent->multipv].depth = depth; save_multipv[SearchCurrent->multipv].max_depth = max_depth; save_multipv[SearchCurrent->multipv].value = value; save_multipv[SearchCurrent->multipv].time = time*1000.0; save_multipv[SearchCurrent->multipv].node_nb = node_nb; strcpy(save_multipv[SearchCurrent->multipv].pv_string,pv_string); } } if (depth > 1 || (depth == 1 && SearchCurrent->multipv == SearchInput->multipv)){ for (i = 0; i <= SearchInput->multipv; i++){ if (save_multipv[i].mate == 0) { // normal evaluation if (false) { } else if (flags == SearchExact) { send("info multipv %d depth %d seldepth %d score cp %d time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].value,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } else if (flags == SearchLower) { send("info multipv %d depth %d seldepth %d score cp %d lowerbound time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].value,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } else if (flags == SearchUpper) { send("info multipv %d depth %d seldepth %d score cp %d upperbound time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].value,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } } else { // mate announcement if (false) { } else if (flags == SearchExact) { send("info multipv %d depth %d seldepth %d score mate %d time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].mate,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } else if (flags == SearchLower) { send("info multipv %d depth %d seldepth %d score mate %d lowerbound time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].mate,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } else if (flags == SearchUpper) { send("info multipv %d depth %d seldepth %d score mate %d upperbound time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].mate,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } } } } } // update time-management info if (SearchBest[SearchCurrent->multipv].depth > 1) { if (SearchBest[SearchCurrent->multipv].value <= SearchRoot->last_value - BadThreshold) { SearchRoot->bad_1 = true; SearchRoot->easy = false; SearchRoot->flag = false; } else { SearchRoot->bad_1 = false; } } }
//------------------------------------------------------------------------------ void repl_bench(char *file_name) { char line[256], buffer[512]; int total = 0, solved = 0; char *white, *black, *solution, *best; FILE *file = fopen(file_name, "rt"); if (!file) { printf("Could not open file: [%s]\n", file_name); return; } // Save engine settings. int64 max_depth = engine.options.max_depth; int64 move_time = engine.options.move_time; // Set fixed time of 10s per position. engine.options.max_depth = 0; engine.options.move_time = 10 * 1000 * 1000; // Read benchmarks line by line, turn them into position, and solve. while (fgets(line, sizeof(line), file)) { if (strlen(line) > 0 && line[0] != '#' && line[0] != '\n') { total++; line[strlen(line) - 1] = '\0'; // Strip trailing \n. // Split into white, black, and solution move(s). white = strtok(line, " : "); if (white) { black = strtok(white + strlen(white) + 3, " # "); if (black) { solution = black + strlen(black) + 3; } } if (white && black && solution) { setup(white, black); Position *p = start(); printf(ANSI_TEAL "%d) %s for %s" ANSI_NONE "\n%s\n", total, solution, p->color ? "Black" : "White", position_string(p, buffer)); Move move = think(); // Solution might space-separated list of best moves. best = strtok(solution, " "); while (best) { // Strip extra characters leaving the actual move only. for (char *ch = best + strlen(best) - 1; strchr(" +?!", *ch); ch--) { *ch = '\0'; } if (!strcmp(move_to_string(move, buffer), best)) { solved++; printf(ANSI_GREEN "%d) Solved (%d/%d %2.1f%%)\n\n\n" ANSI_NONE, total, solved, total - solved, (float)solved * 100.0 / (float)total); goto read_next_line; } best = strtok(NULL, " "); } printf(ANSI_RED "%d) Not solved (%d/%d %2.1f%%)\n\n\n" ANSI_NONE, total, solved, total - solved, (float)solved * 100.0 / (float)total); } } read_next_line:; } fclose(file); // Restore engine settings. engine.options.max_depth = max_depth; engine.options.move_time = move_time; }
void TEngine::Output() { board_t backup_board; board_copy(&backup_board,&Board); bool flag = false; char move_str[6] = ""; if (LastMove) move_to_string(&Board,LastMove,move_str,6); MainForm->edLastMove->Text = move_str; char buf[10000]; char *next_line = buf; if (Process->Get(buf)) { while (next_line[0] != 0) { char *cur_line = next_line; char *end; end = strstr(cur_line,"\r\n"); if (end) { end[0] = 0; end[1] = 0; if (end[-1] == '\r') end[-1] = 0; next_line = end + 2; if (flag && Board.square[75] == 66) { int k; k++; } ParseLine(cur_line); if (flag && Board.square[75] == 66) { int k; k++; } } else break; } MainForm->Memo->Lines->Clear(); for (int i=0; i<MainForm->MultiPV; i++) { AnsiString s; s += PV[i].score; s += " "; undo_t last_move_undo; if (LastMove) move_do(&Board,LastMove,&last_move_undo); int cnt = 0; ASSERT(PV[i].pv_len>=0); for (int j=0; j<PV[i].pv_len; j++) { char move_s[6]; //move_to_string(&Board,PV[i].moves[j],move_s,6); move_to_string(PV[i].moves[j],move_s,8); s += move_s; s += " "; /* move_do(&Board,PV[i].moves[j],&PV[i].undo[j]); cnt++; */ } /* for (int j=PV[i].pv_len-1; j>=0; j--) { move_undo(&Board,PV[i].moves[j],&PV[i].undo[j]); cnt--; } if (cnt) { int k; k++; } */ if (LastMove) move_undo(&Board,LastMove,&last_move_undo); MainForm->Memo->Lines->Append(s); } } }
/** * @brief ui_ggs_play * * Search the best move. * * @param ui User Interface. * @param turn Edax's color. */ static void ui_ggs_play(UI *ui, int turn) { long long real_time = -time_clock(); int remaining_time = ui->ggs->board->clock[turn].ini_time; int extra_time = ui->ggs->board->clock[turn].ext_time; Play *play; Result *result; char move[4], line[32]; const char *(search_state_array[6]) = {"running", "interrupted", "stop pondering", "out of time", "stopped on user demand", "completed"}; char search_state[32]; if (ui->is_same_play) { play = ui->play; if (search_count_tasks(ui->play->search) < options.n_task) { printf("<use a single %d tasks search while a single game is played>\n", options.n_task); play_stop_pondering(ui->play); search_set_task_number(ui->play[0].search, options.n_task); play_stop_pondering(ui->play + 1); search_set_task_number(ui->play[1].search, 0); } } else { play = ui->play + turn; if (search_count_tasks(ui->play->search) == options.n_task && options.n_task > 1) { printf("<split single %d tasks search into two %d task searches>\n", options.n_task, options.n_task / 2); play_stop_pondering(ui->play); search_set_task_number(ui->play[0].search, options.n_task / 2); play_stop_pondering(ui->play + 1); search_set_task_number(ui->play[1].search, options.n_task / 2); search_share(ui->play[0].search, ui->play[1].search); ui_ggs_ponder(ui, turn ^ 1); // ponder opponent move } } // game over detection... if (play_is_game_over(play)) { ggs_client_send(ui->ggs, "tell .%s *** GAME OVER ***\n", ui->ggs->me); return ; } result = play->result; if (remaining_time > 60000) remaining_time -= 10000; // keep 10s. for safety. else if (remaining_time > 10000) remaining_time -= 2000; // keep 2s. for safety. if (remaining_time < 1000) remaining_time = 1000; // set time to at list 1ms play_adjust_time(play, remaining_time, extra_time); printf("<ggs: go thinking>\n"); play_go(play, false); real_time += time_clock(); move_to_string(result->move, play->player, move); ggs_client_send(ui->ggs, "tell /os play %s %s/%d/%.2f\n", ui->ggs->board->id, move, result->score, 0.001 * (real_time + 1)); if (result->book_move) { printf("[%s plays %s in game %s ; score = %d from book]\n", ui->ggs->me, move, ui->ggs->board->id, result->score); ggs_client_send(ui->ggs, "tell .%s -----------------------------------------" "\\%s plays %s in game %s" "\\score == %d from book\n", ui->ggs->me, ui->ggs->me, move, ui->ggs->board->id, result->score ); } else if (play->search->n_empties >= 15) { //avoid noisy display const char *bound; char s_nodes[16], s_speed[16]; if (result->bound[result->move].lower < result->score && result->score == result->bound[result->move].upper) bound = "<="; else if (result->bound[result->move].lower == result->score && result->score < result->bound[result->move].upper) bound = ">="; else bound = "=="; info("<%s plays %s in game %s ; score = %d at %d@%d%% ; %lld nodes in %.1fs (%.0f nodes/s.)>\n", ui->ggs->me, move, ui->ggs->board->id, result->score, result->depth, selectivity_table[result->selectivity].percent, result->n_nodes, 0.001 * real_time, (result->n_nodes / (0.001 * real_time + 0.001)) ); if (play->search->stop == STOP_TIMEOUT) { sprintf(search_state, "%s at %d@%d%%", search_state_array[play->search->stop], play->search->depth, selectivity_table[play->search->selectivity].percent); } else { sprintf(search_state, "%s", search_state_array[play->search->stop]); } ggs_client_send(ui->ggs, "tell .%s -----------------------------------------" "\\%s plays %s in game %s using %d thread%s" "\\score %s %+02d at %d@%d%% ; PV: %s ;" "\\nodes: %s ; time: search = %.1fs, move = %.1fs; speed: %s." "\\search %s\n", ui->ggs->me, ui->ggs->me, move, ui->ggs->board->id, search_count_tasks(play->search), search_count_tasks(play->search) > 1 ? "s ;" : " ;", bound, result->score, result->depth, selectivity_table[result->selectivity].percent, line_to_string(result->pv, 8, " ", line), format_scientific(result->n_nodes, "N", s_nodes), 0.001 * result->time, 0.001 * real_time, format_scientific(result->n_nodes / (0.001 * result->time+ 0.001), "N/s", s_speed), search_state ); } }
Move openBookAndGetNextMove(char* file_name, uint64* key){ FILE *f; entry_t entry; int offset; entry_t entries[MAX_MOVES]; int count=0; int ret, i; char move_s[6]; int total_weight; Move lastChosen={0,0}; f=fopen(file_name,"rb"); if(!f){ perror(file_name); return lastChosen; } offset=find_key(f,*key,&entry); if(entry.key!=*key){ // printf("%016llx: No such key\n",key); return lastChosen; } entries[0]=entry; count=1; fseek(f,16*(offset+1),SEEK_SET); while(1){ ret=entry_from_file(f,&entry); if(ret){ break; } if(entry.key!=*key){ break; } if(count==MAX_MOVES){ printf("#Too many moves in this position (max=%d)\n",MAX_MOVES); return lastChosen; } entries[count++]=entry; } total_weight=0; for(i=0;i<count;i++){ total_weight+=entries[i].weight; } double weightForChoosing=0; // srand(clock()); double randomNumber=(double)rand()/RAND_MAX; for(i=0;i<count;i++){ move_to_string(move_s,entries[i].move); if(move_s[0]>='a'&&move_s[0]<='h'){ if(move_s[1]>='1'&&move_s[1]<='8'){ if(move_s[2]>='a'&&move_s[2]<='h'){ if(move_s[3]>='1'&&move_s[3]<='8'){ lastChosen.from=(int)(move_s[0]-'a')+0x10*(7-(int)(move_s[1]-'1')); lastChosen.to=(int)(move_s[2]-'a')+0x10*(7-(int)(move_s[3]-'1')); if(move_s[4]=='q') lastChosen.promote=queen; else if(move_s[4]=='r') lastChosen.promote=knight; else if(move_s[4]=='b') lastChosen.promote=bishop; else if(move_s[4]=='n') lastChosen.promote=knight; } } } } printf("#move=%s weight=%5.2f%%\n", move_s, 100*((double) entries[i].weight/ (double) total_weight)); weightForChoosing+=((double) entries[i].weight/ (double) total_weight); if(weightForChoosing>randomNumber) break; } return lastChosen; }
void print_outcome(int player, int move, int result) { printf(COM2, "Player %d played: %s, Result: %s\n", player, move_to_string(move), result_to_string(result)); }
void Thread::move_good(const Move b_move, const Move h_move[256], const int h_size, const int ply, const int depth){ Piece p; Square from, to; if(!is_tactical(b_move) && b_move != MoveNull){ if(killer[ply][0] != b_move) { killer[ply][1] = killer[ply][0]; killer[ply][0] = b_move; } p = pos.get_piece(move_from(b_move)); to = move_to(b_move); from = move_from(b_move); #ifndef NDEBUG if(p>13 || to > 63 || from > 63){ std::cerr<<"Wrong good move!"<<std::endl; pos.print(); std::cerr<<"move:"<<move_to_string(b_move)<<std::endl; exit(1); } #endif history[p][from][to] += depth*depth; if (history[p][from][to] >= HistoryMax) { for (Piece p = WP; p <= BK; p++) { for(Square sq_f=A1; sq_f<=H8; sq_f++){ for(Square sq_t=A1; sq_t<=H8; sq_t++){ history[p][sq_f][sq_t] /= 2; } } } } his_tot[p][from][to]++; his_hit[p][from][to]++; if (his_tot[p][from][to] >= HistoryMax) { his_tot[p][from][to] = (his_tot[p][from][to] + 1) / 2; his_hit[p][from][to] = (his_hit[p][from][to] + 1) / 2; } } for(int i=0; i<h_size; i++){ if(is_tactical(h_move[i])) continue; p = pos.get_piece(move_from(h_move[i])); to = move_to(h_move[i]); from = move_from(h_move[i]); #ifndef NDEBUG if(p>13 || to > 63 || from > 63){ std::cerr<<"Wrong good move!"<<std::endl; pos.print(); std::cerr<<"move:"<<move_to_string(h_move[i])<<std::endl; exit(1); } #endif his_tot[p][from][to]++; if (his_tot[p][from][to] >= HistoryMax) { his_tot[p][from][to] = (his_tot[p][from][to] + 1) / 2; his_hit[p][from][to] = (his_hit[p][from][to] + 1) / 2; } } }