int play(int me, int opponent, int row, int col, bool first_player, move_t **moves) { bool can_capture_right, can_capture_left; move_t *moves_right, *moves_left; int score_right = 0; int score_left = 0; if (me == BLACK) { D printf("BLACK: "); can_capture_left = can_capture(me,opponent,row,col,row+1,col+1,row+2,col+2); can_capture_right = can_capture(me,opponent,row,col,row+1,col-1,row+2,col-2); D printf(" From (%d,%d): Right? %s Left? %s\n",row,col,(can_capture_right ? "Yes" : "No"), (can_capture_left ? "Yes" : "No")); if (can_capture_left) score_left = 1 + test_capture(me,opponent,row,col,row+1,col+1,row+2,col+2,first_player,&moves_left); if (can_capture_right) score_right = 1 + test_capture(me,opponent,row,col,row+1,col-1,row+2,col-2,first_player,&moves_right); moves_left = move_gen(row+2,col+2,moves_left); moves_right = move_gen(row+2,col-2,moves_right); } else { D printf("WHITE: "); can_capture_left = can_capture(me,opponent,row,col,row-1,col-1,row-2,col-2); can_capture_right = can_capture(me,opponent,row,col,row-1,col+1,row-2,col+2); if (can_capture_left) score_left = 1 + test_capture(me,opponent,row,col,row-1,col-1,row-2,col-2,first_player,&moves_left); if (can_capture_right) score_right = 1 + test_capture(me,opponent,row,col,row-1,col+1,row-2,col+2,first_player,&moves_right); moves_left = move_gen(row-2,col-2,moves_left); moves_right = move_gen(row-2,col+2,moves_right); } if ((!can_capture_right) && (!can_capture_left) && first_player) { move_t *temp_moves; *moves = NULL; D printf(" returning 0 (no captures available)\n"); return - find_best_move(opponent,me,false,&temp_moves); } else { if ((can_capture_left && (!can_capture_right)) || (can_capture_left && can_capture_right && (score_left > score_right))) { *moves = moves_left; D printf(" returning %d (score_left)\n",score_left); return score_left; } else { *moves = moves_right; D printf(" returning %d (score_right)\n",score_right); return score_right; } } }
void test_divide(int depth) { int i,move_count; move_t ms[MOVE_STACK]; uint64 nodes; uint64 total_nodes; int legal_moves; #ifdef EVASIONS char strbuff[256]; move_t ms_test[MOVE_STACK]; #endif if(!depth) return; nodes = 0; total_nodes = 0; legal_moves = 0; pht_init(); depth -= 1; timer_start(); #ifdef EVASIONS if(is_in_check(board->side)) { move_count = move_gen_evasions(&ms[0]); if(move_count != move_gen_legal(&ms_test[0])) { board_to_fen(&strbuff[0]); printf("error: \n %s \n",strbuff); } } else { move_count = move_gen(&ms[0]); } #else move_count = move_gen(&ms[0]); #endif for(i = 0; i < move_count; i++) { if(!move_make(ms[i])) continue; nodes = perft(depth); print_move(ms[i].p); legal_moves++; printf("%I64u",nodes); printf("\n"); move_undo(); total_nodes += nodes; } printf("\nNodes: %I64u",total_nodes); printf("\nMoves: %d",legal_moves); printf("\n\n"); timer_stop(); pht_free(); }
int find_best_move(int me, int opponent, bool first_player, move_t **moves) { int best_score, best_row, best_col; move_t *best_moves; bool first = true; for (int row=0; row<8; row++) for (int col=0; col<8; col++) if (board[row][col] == me) { int score; move_t *move_list; D printf("Looking for the best moves starting from (%d,%d)\n",row,col); score = play(me,opponent,row,col,first_player,&move_list); D printf("The score from (%d,%d) was %d\n",row,col,score); if ((score > best_score) || first) { D printf("This is the new best score.\n"); best_score = score; best_row = row; best_col = col; best_moves = move_list; first = false; } } D printf("Making the final move_gen()\n"); *moves = move_gen(best_row,best_col,best_moves); return best_score; }
void test_pawn_divide(int depth) { int i,move_count; move_t ms[MOVE_STACK]; uint64 nodes = 0; uint64 total_nodes = 0; int legal_moves = 0; if(!depth) return; pawnhits = 0; pawncollisions = 0; pht_init(); depth -= 1; timer_start(); move_count = move_gen(&ms[0]); for(i = 0; i < move_count; i++) { if(!move_make(ms[i])) continue; nodes = perft(depth); print_move(ms[i].p); legal_moves++; printf("%I64u",nodes); printf("\n"); move_undo(); total_nodes += nodes; } printf("\nNodes: %I64u",total_nodes); printf("\nMoves: %d",legal_moves); printf("\nPawnHits: %d",pawnhits); printf("\nPawnCollisions: %d",pawncollisions); printf("\n\n"); timer_stop(); pht_free(); }
// Nega-max演算法(recursive) // board: 盤面資訊(0~59), 表示法如下(X:邊界, 0:棋盤格子): // XXXXXX // X0000X // X0000X // X0000X // X0000X // X0000X // X0000X // X0000X // X0000X // XXXXXX // // piece_num: 記錄各兵種之存活棋子數 // dark_num: 記錄可翻棋子數 // red_num, black_num: 紅黑存活棋子數 // turn: 輪走方 // depth: 目前深度 // max_depth: 最大深度 int search(int board[BOARD_SIZE], int piece_num[PIECE_TYPE], int dark_num, int red_num, int black_num, int turn, int depth, int max_depth, clock_t t) { int s[MAX_MOVE], d[MAX_MOVE], cap_s[MAX_MOVE], cap_d[MAX_MOVE]; int i, m, n; int curr_score, score, value; int src, dest, cap; int factor; // factor: 將分數轉換為相對於自己的分數 factor = (turn == RED) ? 1 : -1; // 終止條件 if(red_num == 0) return -(MAX_SCORE-depth-1) * factor; if(black_num == 0) return (MAX_SCORE-depth-1) * factor; if(depth == max_depth) return factor * eval(piece_num); src = 0; dest = 0; score = -MAX_SCORE; if(clock() > t) return score; // 產生走法 move_gen(board, turn, s, d, &n, cap_s, cap_d, &m); // if(depth == 1) // printf("%d %d\n", n, m); // 對吃子步進行搜尋 for(i = 0; i < m; i++){ cap = move(board, piece_num, &red_num, &black_num, cap_s[i], cap_d[i]); value = -search(board, piece_num, dark_num, red_num, black_num, !turn, depth + 1, max_depth, t); if(value >= score){ score = value; src = cap_s[i]; dest = cap_d[i]; } unmove(board, piece_num, &red_num, &black_num, cap_s[i], cap_d[i], cap); // if(depth == 1) // printf("%d %d %d\n", value, cap_s[i], cap_d[i]); } // 對走子步進行搜尋 for(i = 0; i < n; i++){ cap = move(board, piece_num, &red_num, &black_num, s[i], d[i]); value = -search(board, piece_num, dark_num, red_num, black_num, !turn, depth + 1, max_depth, t); if(value >= score){ score = value; src = s[i]; dest = d[i]; } unmove(board, piece_num, &red_num, &black_num, s[i], d[i], cap); // if(depth == 1) // printf("%d %d %d\n", value, s[i], d[i]); } // 計算當前盤面之審局分數 curr_score = eval(piece_num) * factor; // 判斷是否執行null move if(dark_num > 0 && score <= curr_score){ value = -search(board, piece_num, dark_num, red_num, black_num, !turn, depth + 1, max_depth, t); if(value >= score){ score = value; src = 0; dest = 0; } // if(depth == 1) // printf("%d 0 0\n", value); } if(depth == 1){ best_src = src; best_dest = dest; } return score; }
uint64 perft(int depth) { int i,move_count; move_t ms[MOVE_STACK]; uint64 nodes; uint64 val; #ifdef EVASIONS char strbuff[256]; move_t ms_test[MOVE_STACK]; #endif #ifdef BITS bitboard_t bb; #endif if(depth == 0) return 1; if((val = probe_hash(depth)) != 0) return val; nodes = 0; val = 0; #ifdef BITS bb = 0; for(i = PLS(WP); i <= H8; i = PLN(i)) bitset(&bb, rsz[i]); if(bb != board->bb_pawns[W]) printf("pawn_error\n"); bb = 0; for(i = PLS(BP); i <= H8; i = PLN(i)) bitset(&bb, rsz[i]); if(bb != board->bb_pawns[B]) printf("pawn_error\n"); #endif #ifdef EVASIONS if(is_in_check(board->side)) { move_count = move_gen_evasions(&ms[0]); if(move_count != move_gen_legal(&ms_test[0])) { board_to_fen(&strbuff[0]); printf("error: \n %s \n",strbuff); } } else { move_count = move_gen(&ms[0]); } #else move_count = move_gen(&ms[0]); #endif for(i = 0; i < move_count; i++) { if(!move_make(ms[i])) continue; if(depth == 1) nodes++; else nodes += perft(depth - 1); move_undo(); } record_hash(depth,nodes); return (nodes); }