int test_scout() { Board b, orig; Move *moves, *omoves; int status, i, j, n, m; status = WIN; printf("testing scout\n"); setup(&b); setup(&orig); printb(&b); moves = gen_moves(&b, &n); for(i=0; i<n && i<5; i++) { printf("=============================================\napplying move %d\n", i+1); apply_move(&b, moves[i]); omoves = gen_moves(&b, &m); for(j=0; j<m && j<5; j++) { printf("second move %d\n", j+1); apply_move(&b, omoves[j]); printb(&b); printf("eval = %d\n", eval(&b)); undo_move(&b, omoves[j]); } free(omoves); undo_move(&b, moves[i]); } free(moves); return status; }
void Battle::make_move(Participant& participant) { std::vector<const MoveType *> move_types = combat_model->get_available_move_types(*this, participant); const MoveType *best = NULL; int best_target = -1; float best_value = 0; int num_considered = 0; for (auto iter = participants.begin(); iter != participants.end(); iter++) { const Participant& target = *iter; for (auto iter2 = move_types.begin(); iter2 != move_types.end(); iter2++) { const MoveType *type = *iter2; if (!type->is_viable(*this, participant, target)) continue; num_considered++; float expected_value = type->expected_value(*this, participant, target) * type->repeats(); if (expected_value > best_value) { best = type; best_target = target.id; best_value = expected_value; } } } if (best != NULL && best_target != -1) { BOOST_LOG_TRIVIAL(trace) << boost::format("Considered %d moves and chose: ") % num_considered << *best << boost::format(" (with value %0.1f)") % best_value; Participant& target = participants[best_target]; for (int i = 0; i < best->repeats(); i++) { // It's possible the move is no longer viable if (!best->is_viable(*this, participant, target)) break; // Make the move Move move = best->generate(*this, participant, target); moves.push_back(move); apply_move(move); // Riposte MoveType *riposte_type = combat_model->move_types[Riposte]; if (riposte_type != NULL && riposte_type->is_viable(*this, target, participant)) { Move riposte = riposte_type->generate(*this, target, participant); moves.push_back(riposte); apply_move(riposte); } } } else { BOOST_LOG_TRIVIAL(trace) << "Considered no moves"; } }
/* Naively choose the move that will shrink the most dots. */ mask_t choose_move_greedy(grid_t grid, int allow_shrinkers, int *no_moves) { mask_t move = EMPTY_MASK; int i, num_dots, max_dots = -1; int num_moves; move_list_t moves; get_moves(grid, allow_shrinkers, &num_moves, moves); *no_moves = 0; if (SHOULD_SHRINK_RANDOM(num_moves, allow_shrinkers)) { *no_moves = 1; return random_mask(); } for (i = 0; i < num_moves; i++) { grid_t new_grid; memcpy(new_grid, grid, sizeof(grid_t)); num_dots = apply_move(new_grid, moves[i]); if (num_dots > max_dots) { max_dots = num_dots; move = moves[i]; } } return move; }
/* return 1 if the move is valid and 0 otherwise, printing an appropriate * message if print is non-zero. */ int is_valid_move(Game game, Move m, int print) { Board *board = &(game.board); Game game2 = game; uint64_t beginbit, endbit; char *strmove = xboard_move(m); beginbit = 1ull << m.begin; endbit = 1ull << m.end; /* ensure that the piece belongs to the current player */ if(!(board->b[game.turn][OCCUPIED] & beginbit)) { if(print) printf("Illegal move (%s): that is not your piece.\n", strmove); return 0; } /* ensure that the end tile can be moved to from the begin tile */ if(!(generate_moves(&game, m.begin) & endbit)) { if(print) printf("Illegal move (%s): that piece can't move like that.\n", strmove); return 0; } /* ensure that pawns reaching the eighth rank promote */ if(!m.promote && ((m.end / 8) == 0 || (m.end / 8) == 7) && board->mailbox[m.begin] == PAWN) { if(print) printf("Illegal move (%s): pawns reaching the eighth rank must " "promote.\n", strmove); return 0; } /* ensure that no other pieces promote */ if(m.promote && (board->mailbox[m.begin] != PAWN || ((m.end / 8) != 0 && (m.end / 8) != 7))) { if(print) printf("Illegal move (%s): that piece may not promote at this " "time.\n", strmove); return 0; } /* ensure that the king is not left in check * NOTE: we apply_move() here, so the state of the game is changed; this * check must be done last */ apply_move(&game2, m); if(king_in_check(&(game2.board), game.turn)) { if(print) printf("Illegal move (%s): king is left in check.\n", strmove); return 0; } /* hasn't failed any validation, must be a valid move */ return 1; }
void evaluate_move(GAME *game, MOVE move, int *vector, int to_depth) { GAME *game2 = clone_game(game); int window[MAX_PLAYERS]; memset(window, 0, sizeof(window)); apply_move(game2, move); search_tree(game2, vector, to_depth, window, game2->current_player); stack_pop(&game_stack, game2); }
static void tick(int *len, char *buf, struct per_session_data *data) { int path_length = 0; path_t path; mask_t random_dots = EMPTY_MASK; json_object *result; const char *s; /* If it's a new game, only send the grid and don't compute a move. */ if (data->new_game) { data->new_game = 0; } else { struct timeval tv; long ms; mask_t move; int no_moves; gettimeofday(&tv, NULL); ms = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); if ((ms - data->last_updated) < MIN_UPDATE_INTERVAL) { return; } data->last_updated = ms; move = choose_move(data->grid, 0, 100, &no_moves); apply_move(data->grid, move); fill_grid(data->grid, GET_CYCLE_COLOR(move)); if (no_moves) { random_dots = move; } else { mask_to_path(move, &path_length, path); } } result = json_object_new_object(); json_object_object_add(result, "grid", json_grid(data->grid)); if (path_length == 0 && random_dots == EMPTY_MASK) { json_object_object_add(result, "newGrid", json_object_new_boolean(TRUE)); } if (random_dots) { json_object_object_add(result, "shrinkRandom", json_shrink_random(random_dots)); } if (path_length) { json_object_object_add(result, "path", json_path(path_length, path)); } s = json_object_to_json_string(result); *len = strlen(s); memcpy(buf, s, *len); buf[*len] = 0; json_object_put(result); }
void Group::buildTransitionTable() { transition_table = TransitionTable(state_count); std::vector<int> arr(piece_count); for (int index = 0; index < state_count; index++) { for (int move = 0; move < 6; move++) { index_to_array(index, arr); apply_move(arr, move); transition_table[index][move] = array_to_index(arr); } } }
/* heuristic = score ** uncertainty_of_board * where uncertainty_of_board = (sum of certainty_of_dots) / num_dots * uncertainty_of_dot | 1/4 if shrunk by cycle * | 1/5 if shrunk by a regular move * | 1 otherwise */ void _choose_move(grid_t grid, int allow_shrinkers, int turns_remaining, int certainty, float *value, mask_t *move, int *no_moves) { float best_value = -1; mask_t best_move = EMPTY_MASK; int i, num_moves; move_list_t moves; get_moves(grid, allow_shrinkers, &num_moves, moves); if (certainty == 720 && SHOULD_SHRINK_RANDOM(num_moves, allow_shrinkers)) { *move = random_mask(); *value = num_dots(*move); *no_moves = 1; return; } for (i = 0; i < num_moves; i++) { int score; float value; grid_t new_grid; if (turns_remaining > 1 || HAS_CYCLE(moves[i])) { memcpy(new_grid, grid, sizeof(grid_t)); score = apply_move(new_grid, moves[i]); } else { score = num_dots(moves[i]); } value = pow(score, certainty / 720.0); if (turns_remaining > 1) { int next_certainty = certainty - score * (HAS_CYCLE(moves[i]) ? 15 : 16); float next_value; mask_t next_move; _choose_move(new_grid, allow_shrinkers, turns_remaining - 1, next_certainty, &next_value, &next_move, NULL); value += next_value; } if (value > best_value) { best_value = value; best_move = moves[i]; } } *value = best_value; *move = best_move; }
/* Returns 1 if player c has valid moves left. * c = 1 (white) or -1 (black) * If king is in check and no valid moves left, that implies checkmate */ int has_moves(board * brd, int c) { move * t = malloc(sizeof(move)); init_move(&t); generate_all_moves(c, brd, &t); move * t_ = t; while(t_->next != NULL) { if(apply_move(brd, &t_, c)) { undo_move(brd, &t_); free_moves(&t); return 1; } t_ = t_->next; } free_moves(&t); return 0; }
int test_apply_move() { int status, num_moves, i; Board board; Move *moves; status = WIN; num_moves = 0; setup(&board); printb(&board); moves = gen_moves(&board, &num_moves); printf("found %d moves\n", num_moves); for(i=0; i<35 && i<num_moves; i++) { printf("move %d: %d is moving from %d to %d, capturing %d\n", i, moving_type(moves[i]), moves[i].from, moves[i].to, capturing_type(moves[i])); printf("board after move %d looks like:\n", i+1); apply_move(&board, moves[i]); printb(&board); undo_move(&board, moves[i]); } return status; }
void test(void) { GAME game; MOVE moves[MAX_MOVES]; int vector[MAX_PLAYERS]; int num_moves; int i; MOVE chosen_move; clock_t start_time, end_time; int centiseconds, rate; printf("Rankoids AI test\n"); clear_transposition_table(); init_stack(&game_stack, 100*sizeof(GAME)); initialise_game(&game); game.num_players = 3; game.players[0].hand[0] = 1; game.players[0].hand[1] = 3; game.players[0].hand[3] = 2; game.players[1].hand[4] = 1; game.players[0].hand[6] = 4; game.players[0].hand[7] = 3; game.players[0].hand[10] = 2; game.players[0].hand[JOKER_VALUE] = 1; game.players[1].hand[1] = 1; game.players[1].hand[2] = 3; game.players[1].hand[3] = 1; game.players[1].hand[4] = 1; game.players[1].hand[5] = 1; game.players[1].hand[9] = 3; game.players[1].hand[12] = 1; game.players[1].hand[5] = 2; game.players[2].hand[0] = 3; game.players[2].hand[2] = 1; game.players[2].hand[3] = 1; game.players[1].hand[4] = 2; game.players[2].hand[5] = 2; game.players[2].hand[9] = 1; game.players[2].hand[11] = 4; game.current_player = 0; game.pile_owner = 0; printf("Current game:\n"); print_game(&game); printf("All moves for player 1:\n"); num_moves = generate_all_moves(game.players[0].hand, moves); for (i = 0; i < num_moves; i++) print_move(moves[i]); printf("\n"); evaluate_game_immediate(&game, vector); printf("Game vector is: [%d,%d,%d]\n", vector[0], vector[1], vector[2]); printf("All valid moves for player 1:\n"); num_moves = generate_valid_moves(&game, moves); for (i = 0; i < num_moves; i++) print_move(moves[i]); printf("\n"); chosen_move = MAKE_MOVE(3, 2); printf("Apply move "); print_move(chosen_move); printf(", game is:\n"); apply_move(&game, chosen_move); print_game(&game); evaluate_game_immediate(&game, vector); printf("Game vector is: [%d,%d,%d]\n", vector[0], vector[1], vector[2]); printf("All valid moves for player 2:\n"); num_moves = generate_valid_moves(&game, moves); for (i = 0; i < num_moves; i++) { print_move(moves[i]); clear_transposition_table(); evaluate_move(&game, moves[i], vector, parameters.depth); printf(", with vector [%d,%d,%d]\n", vector[0], vector[1], vector[2]); } node_count = 0; clear_transposition_table(); start_time = clock(); chosen_move = choose_move(&game, vector, parameters.depth+5); end_time = clock(); centiseconds = (end_time - start_time)*100 / CLOCKS_PER_SEC; if (centiseconds != 0) { rate = (int) (100.0*node_count/centiseconds); } else { rate = 0; } printf("%d nodes examined (%d hits), time was: %0.2f seconds, rate is: %d nodes/sec\n", node_count, hit_count, centiseconds/100.0, rate); printf("Chosen move was:"); print_move(chosen_move); printf(", with vector [%d,%d,%d]\n", vector[0], vector[1], vector[2]); free_stack(&game_stack); }
MOVE search_tree(GAME *game, int *best_vector, int to_depth, int *window_vector, int window_player) { MOVE moves[MAX_MOVES]; int num_moves; int i; MOVE best_move = MOVE_INVALID; int player; unsigned int hash; if (to_depth <= 0 || game_is_over(game)) { evaluate_game_immediate(game, best_vector); return best_move; } #ifdef USE_TRANSPOSITION_TABLE_SEARCH hash = hash_game(game) % TRANSPOSITION_TABLE_SIZE; if (transposition_table[hash][0] != TABLE_UNUSED) { memcpy(best_vector, transposition_table[hash], sizeof(int)*MAX_PLAYERS); hit_count++; return best_move; } #endif num_moves = generate_valid_moves(game, moves); player = game->current_player; for (i = 0; i < num_moves; i++) { GAME *game2 = clone_game(game); int vector[MAX_PLAYERS]; MOVE move; apply_move(game2, moves[i]); node_count++; move = search_tree(game2, vector, to_depth - 1, best_vector, player); if (move == MOVE_INVALID) move = moves[i]; if (i == 0 || vector[player] > best_vector[player]) { memcpy(best_vector, vector, sizeof(vector)); best_move = moves[i]; } stack_pop(&game_stack, game2); /* Prune if this move is so good for the current player that the potential value for the window player is less than the window. */ if (vector[player] > parameters.total_score - window_vector[window_player]) { break; } } #ifdef USE_TRANSPOSITION_TABLE_SEARCH memcpy(transposition_table[hash], best_vector, sizeof(int)*MAX_PLAYERS); #endif return best_move; }
void BorderList::removeLine(int i) { class is_equal_to_i { int m_i; public: is_equal_to_i(int i) { m_i = i; } bool operator() (Figure& fig) { if (fig.ypos == m_i && fig.ypos != 640) return true; else return false; } }; class apply_move { int m_i; public: apply_move(int i) { m_i = i; } void operator() (Figure& fig) { if (fig.ypos != m_i && fig.ypos < m_i) fig.ypos += 32; } }; std::vector<Figure>::iterator iter; std::vector<Figure> newfence; if (i != -1) { // std::cout << "10 elements found, ret = " << i << std::endl; // for (iter=fence.begin(); iter!=fence.end(); iter++ ) // { // if ((*iter).ypos != i || (*iter).ypos == 640) // { // newfence.push_back(*iter); // } // } std::vector<Figure>::iterator newend = std::remove_if(fence.begin(), fence.end(), is_equal_to_i(i)); fence.erase(newend, fence.end()); // for (iter=fence.begin(); iter!=fence.end(); iter++ ) // { // if ((*iter).ypos != 640 && (*iter).ypos < i) // { // (*iter).ypos += 32; // } // } std::for_each(fence.begin(), fence.end(), apply_move(i)); // fence = newfence; } }
/* apply the given move to the given game */ void apply_move(Game *game, Move m) { Board *board = &(game->board); int beginpiece, endpiece; int begincolour, endcolour; uint64_t beginbit, endbit; int eptile; uint64_t epbit; Move m2; /* check board consistency */ /*if(!consistent_board(&(game->board))) { printf("!!! Inconsistent board at start of apply_move!\n"); draw_board(&(game->board)); printf("occupied:\n"); draw_bitboard(game->board.occupied); printf("black occupied:\n"); draw_bitboard(game->board.b[BLACK][OCCUPIED]); printf("white occupied:\n"); draw_bitboard(game->board.b[WHITE][OCCUPIED]); exit(1); }*/ /* find the piece from the mailbox */ beginpiece = board->mailbox[m.begin]; endpiece = board->mailbox[m.end]; /* find the bits to use */ beginbit = 1ull << m.begin; endbit = 1ull << m.end; /* find out if this move is quiet */ if(board->occupied & endbit) game->quiet_moves = 0; else game->quiet_moves++; /* find the colour from white's occupied bitboard */ begincolour = !(board->b[WHITE][OCCUPIED] & beginbit); endcolour = !(board->b[WHITE][OCCUPIED] & endbit); /* delete a pawn if taken en passant */ if(beginpiece == PAWN && ((m.end / 8) == (5 - begincolour * 3)) && ((m.end % 8) == game->ep)) { eptile = (4 - begincolour) * 8 + game->ep; game->eval += piece_square_score(PAWN, eptile, !game->turn); epbit = 1ull << eptile; board->mailbox[eptile] = EMPTY; board->occupied ^= epbit; board->b[!begincolour][OCCUPIED] ^= epbit; board->b[!begincolour][PAWN] ^= epbit; } /* update en passant availability */ if(beginpiece == PAWN && abs(m.begin - m.end) == 16) game->ep = m.begin % 8; else game->ep = 9; /* remove the piece from the begin square */ game->eval -= piece_square_score(beginpiece, m.begin, game->turn); board->mailbox[m.begin] = EMPTY; board->occupied ^= beginbit; board->b[begincolour][beginpiece] ^= beginbit; board->b[begincolour][OCCUPIED] ^= beginbit; board->zobrist ^= zobrist[beginpiece][m.begin]; board->zobrist ^= zobrist[EMPTY][m.begin]; /* remove the piece from the end square if necessary */ if(endpiece != EMPTY) { game->eval += piece_square_score(endpiece, m.end, !game->turn); board->b[endcolour][endpiece] ^= endbit; board->b[endcolour][OCCUPIED] ^= endbit; } board->zobrist ^= zobrist[endpiece][m.end]; /* change the piece to it's promotion if appropriate */ if(m.promote) beginpiece = m.promote; /* insert the piece at the end square */ game->eval += piece_square_score(beginpiece, m.end, game->turn); board->mailbox[m.end] = beginpiece; board->occupied |= endbit; board->b[begincolour][beginpiece] |= endbit; board->b[begincolour][OCCUPIED] |= endbit; board->zobrist ^= zobrist[beginpiece][m.end]; /* can't castle on one side if a rook was moved from it's original place */ if(beginpiece == ROOK) { /* queenside */ if((m.begin == 0 && begincolour == WHITE) || (m.begin == 56 && begincolour == BLACK)) game->can_castle[begincolour][QUEENSIDE] = 0; /* kingisde */ if((m.begin == 7 && begincolour == WHITE) || (m.begin == 63 && begincolour == BLACK)) game->can_castle[begincolour][KINGSIDE] = 0; } /* can't castle on one side if that rook is taken */ if(endpiece == ROOK) { /* queenside */ if((m.end == 0 && endcolour == WHITE) || (m.end == 56 && endcolour == BLACK)) game->can_castle[endcolour][QUEENSIDE] = 0; /* kingisde */ if((m.end == 7 && endcolour == WHITE) || (m.end == 63 && endcolour == BLACK)) game->can_castle[endcolour][KINGSIDE] = 0; } if(beginpiece == KING) { /* can no longer castle on either side if the king is moved */ game->can_castle[begincolour][QUEENSIDE] = 0; game->can_castle[begincolour][KINGSIDE] = 0; /* move the rook for castling */ if(abs(m.begin - m.end) == 2) { if(m.begin > m.end) {/* queenside */ m2.begin = m.begin - 4; m2.end = m.end + 1; } else {/* kingside */ m2.begin = m.begin + 3; m2.end = m.end - 1; } /* make sure we don't try to promote */ m2.promote = 0; /* apply the rook move */ apply_move(game, m2); /* undo the turn toggle */ game->turn = !game->turn; game->eval = -game->eval; } } /* toggle current player */ game->turn = !game->turn; game->eval = -game->eval; /* check board consistency */ /*if(!consistent_board(&(game->board))) { printf("!!! Inconsistent board at end of apply_move!\n"); draw_board(&(game->board)); printf("occupied:\n"); draw_bitboard(game->board.occupied); printf("black occupied:\n"); draw_bitboard(game->board.b[BLACK][OCCUPIED]); printf("white occupied:\n"); draw_bitboard(game->board.b[WHITE][OCCUPIED]); exit(1); }*/ }
void Battle::replay_move(const Move& move) { apply_move(move); }
/////////////////////////////////// // MAIN (only for internal test) // /////////////////////////////////// int main () { // Valgrind run init_chess_library (); int i, from, to; for (i = 0; i < 1000; i++) { Game *g = init_game (); Board *board; char *fen; // 1. e4 a6 2. Bc4 a5 3. Qh5 a4 4. Qxf7# board = current_board (g); get_coord (board, 'P', "e", "e4", 0, &from, &to); pseudo_legal_move (board, from, to); apply_move (g, from, to, 0); fen = to_fen (board); free (fen); board = current_board (g); get_coord (board, 'P', "a", "a6", 0, &from, &to); pseudo_legal_move (board, from, to); apply_move (g, from, to, 0); fen = to_fen (current_board (g)); free (fen); board = current_board (g); get_coord (board, 'B', "", "c4", 0, &from, &to); pseudo_legal_move (board, from, to); apply_move (g, from, to, 0); fen = to_fen (current_board (g)); free (fen); board = current_board (g); get_coord (board, 'P', "a", "a5", 0, &from, &to); pseudo_legal_move (board, from, to); apply_move (g, from, to, 0); fen = to_fen (current_board (g)); free (fen); board = current_board (g); get_coord (board, 'Q', "", "h5", 0, &from, &to); pseudo_legal_move (board, from, to); apply_move (g, from, to, 0); fen = to_fen (current_board (g)); free (fen); board = current_board (g); get_coord (board, 'P', "a", "a4", 0, &from, &to); pseudo_legal_move (board, from, to); apply_move (g, from, to, 0); fen = to_fen (current_board (g)); free (fen); board = current_board (g); get_coord (board, 'Q', "", "f7", 0, &from, &to); pseudo_legal_move (board, from, to); apply_move (g, from, to, 0); fen = to_fen (current_board (g)); free (fen); free_game (g); } return 0; }