/** * @brief Move generator performance test function. * * @param board * @param depth * @param global_stats statistics */ static void count_game(const Board *board, const int depth, GameStatistics *global_stats) { GameStatistics stats = GAME_STATISTICS_INIT; unsigned long long moves; int x; Board next[1]; if (depth == 1) { moves = get_moves(board->player, board->opponent); stats.n_moves = stats.max_mobility = stats.min_mobility = bit_count(moves); if (moves == 0) { if (can_move(board->opponent, board->player)) { stats.n_passes = 1; } else { const int n_player = bit_count(board->player); const int n_opponent = bit_count(board->opponent); if (n_player > n_opponent) stats.n_wins = 1; else if (n_player == n_opponent) stats.n_draws = 1; else stats.n_losses = 1; } } } else { moves = get_moves(board->player, board->opponent); if (moves) { foreach_bit (x, moves) { board_next(board, x, next); count_game(next, depth - 1, &stats); } } else {
/** * is_a_winner * input : player_e turn * output : TRUE/FALSE * functionality : returns TRUE if given player is the winner of the game else return FALSE */ bool is_a_winner(player_e turn){ bool winner = FALSE; coordinate_t* temp_king, *temp_man; if (turn == COMPUTER) { temp_king = creat_linkedList_pointer(KING, USER); temp_man = creat_linkedList_pointer(MAN, USER); } else { temp_king = creat_linkedList_pointer(KING, COMPUTER); temp_man = creat_linkedList_pointer(MAN, COMPUTER); } if ((temp_king == NULL) && (temp_man == NULL)) /* enemy don't have any tools.*/ { winner = TRUE; } else { get_moves(turn^1); if (paths_arr[0] == NULL) { winner = TRUE; } } return winner; }
/* * Tries to make a move for r1, if it can't, generate more moves * */ void move(path *r1, path *r2) { int ret = -1; // Try to reserve a move if (r1->moves_x->size() > 0) { //&& !(r1->moves_x->front() == r2->curr_x)) ret = robot->reserveMap(r1->moves_x->front(), r1->moves_y->front()); printf("Ret: %d: %d %d \n", ret, r1->moves_x->front(), r1->moves_y->front()); } if (0 == ret) { // Consume the move we are making from the queue r1->curr_x = r1->moves_x->front(); r1->curr_y = r1->moves_y->front(); r1->moves_x->erase(r1->moves_x->begin()); r1->moves_y->erase(r1->moves_y->begin()); // Move to cell if we are not debugging robotPose->moveToCell(r1->curr_x, r1->curr_y); // Sleep if we are debugging //sleep(1); robot->updateMap(r1->curr_x, r1->curr_y); //if (maze[r1->curr_y][r1->curr_x] > 0) { //r1_score += maze[r1->curr_y][r1->curr_x]; //maze[r1->curr_y][r1->curr_x] = 0; //} } // Give up and try generating new moves else { get_moves(r1, r2); move(r1, r2); } }
/* 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; }
/* * @brief initiates the forest generation, setting the max number of tiles(lifespan) that can be set to road * sets the possible moves and send it to tile_forest_walk to be evaluated * @param int tile index to start the forest walk. */ void tile_forest_gen(int start) { int i = start; int done = false; int lifespan = TOTAL_TILES / 20; //-1 means can't move to that node tile_list[i].mType = TILE_ROAD; dest_tile_list[i].mType = TILE_ROAD; ++call_stack; while( 0 < lifespan--) { int moves[4] = {i-1, i+1, i-TOTAL_TILES_X, i + TOTAL_TILES_X}; // left,right,up,down a tile on map int j; get_moves(moves, 4, i);//4 directions i = tile_forest_walk(moves); //update scores here //road tiles have heur score +10 //adjacent tiles to road have score +3 tile_list_scores[i] += 10; moves[0] = i - 1; moves[1] = i + 1; moves[2] = i - TOTAL_TILES_X; moves[3] = i + TOTAL_TILES_X; get_moves(moves, 4, i);//4 directions for(j = 0; j < 4; j++) { if(moves[j] == -1) { continue; } tile_list_scores[moves[j]] += 3; } tile_list[i].mType = TILE_ROAD; dest_tile_list[i].mType = TILE_ROAD; } }
/* 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; }
int setNewGame(tGame * game) { if (game->gametype != GAMETYPE_CAMPAIGN) { getDim(game); getLevel(game); } else { int campaign_rows = game->campaign[game->campaign_level-1].rows; int campaign_columns = game->campaign[game->campaign_level-1].columns; int campaign_level = game->campaign[game->campaign_level-1].level; if (campaign_rows > MAX_ROWS || campaign_columns > MAX_COLUMNS) { printf("El nivel actual posee un tablero muy grande, se pasara al proximo nivel"); game->campaign_level++; return FALSE; } game->visualboard.rows = game->hiddenboard.rows = campaign_rows; game->visualboard.columns = game->hiddenboard.columns = campaign_columns; game->level = campaign_level; } setGameMinesNumber(game); game->undos = get_undos(game->level); /* Moves */ if (game->gametype == GAMETYPE_INDIVIDUAL_NOLIMIT) game->moves = UNLIMITED_MOVES; else game->moves = get_moves(game->undos, game->mines); game->mines_left = game->mines; game->sweeps_left = (game->visualboard.rows * game->visualboard.columns) - game->mines; game->flags_left = game->mines; game->gamestate = GAMESTATE_DEFAULT; if (!CreateHiddenVisualBoard(game)) return MALLOC_ERR; /* Ready to play */ return TRUE; }
/** returns an int representing the score for the previously * executed move (that caused the a_board configuration), * according to the scoring function and depending on the depth. * this is a recursive function. */ int minmax(char a_board[BOARD_SIZE][BOARD_SIZE], int minim, int next_color, int depth, int alpha, int beta) { int true_color = (minim) ? !next_color : next_color; move *moves = NULL; move *temp = NULL; int mini_score = INF_SCORE; int maxi_score = -INF_SCORE; // recursion ends if ( depth == MINIMAX_DEPTH ) return score_board(a_board, true_color); if ( board_cnt > TOO_MUCH ) return score_board(a_board, true_color); // (just to be safe) moves = get_moves(a_board, next_color); //get the moves of the other player if ( moves == NULL ) { int current_score = score_board(a_board, next_color); if (current_score == TIE_SCORE) return TIE_SCORE; if(minim) return WIN_SCORE; else return LOOSE_SCORE; } temp = moves; //initialize temp while ( temp != NULL ) { int temp_score; char board_copy[BOARD_SIZE][BOARD_SIZE]; memcpy(board_copy, a_board, sizeof(board_copy)); board_cnt++; DO_DEBUG2(if (board_cnt%100000 == 0) printf("%d millions of boards.\n", board_cnt/1000000); fflush(stdout);) do_move(board_copy, temp); // now the board copy is updated temp_score = minmax(board_copy, !minim, !next_color, depth+1, alpha, beta); if ( temp_score > maxi_score ) { maxi_score = temp_score; if ( !minim ) alpha = maxi_score; } if ( temp_score < mini_score ) { mini_score = temp_score; if ( minim ) beta = mini_score; } if ( alpha > beta ) break; temp = temp->next; }
/** * is_legal_move * input : path_t* user_input_path * output : TRUE/FALSE * functionality : returns TRUE if the move is legal else return FALSE */ bool is_legal_move(path_t* user_input_path) { bool comparison; int i; comparison = FALSE; get_moves(Turn); if (paths_number == 0) { return comparison; } else { for(i = 0; i < paths_number; i++) { comparison = compare_two_paths(paths_arr[i], user_input_path); if (comparison) { break; } } } return comparison; }
/** * Process a monster * * In several cases, we directly update the monster lore * * Note that a monster is only allowed to "reproduce" if there * are a limited number of "reproducing" monsters on the current * level. This should prevent the level from being "swamped" by * reproducing monsters. It also allows a large mass of mice to * prevent a louse from multiplying, but this is a small price to * pay for a simple multiplication method. * * XXX Monster fear is slightly odd, in particular, monsters will * fixate on opening a door even if they cannot open it. Actually, * the same thing happens to normal monsters when they hit a door * * In addition, monsters which *cannot* open or bash down a door * will still stand there trying to open it... XXX XXX XXX * * Technically, need to check for monster in the way combined * with that monster being in a wall (or door?) XXX */ static void process_monster(struct chunk *c, struct monster *mon) { struct monster_lore *lore = get_lore(mon->race); bool did_something = false; int i; int dir = 0; bool stagger = false; char m_name[80]; /* Get the monster name */ monster_desc(m_name, sizeof(m_name), mon, MDESC_CAPITAL | MDESC_IND_HID); /* Try to multiply - this can use up a turn */ if (process_monster_multiply(c, mon)) return; /* Attempt to cast a spell */ if (make_attack_spell(mon)) return; /* Work out what kind of movement to use - AI or staggered movement */ if (!process_monster_should_stagger(mon)) { if (!get_moves(c, mon, &dir)) return; } else { stagger = true; } /* Process moves */ for (i = 0; i < 5 && !did_something; i++) { int oy = mon->fy; int ox = mon->fx; /* Get the direction (or stagger) */ int d = (stagger ? ddd[randint0(8)] : side_dirs[dir][i]); /* Get the destination */ int ny = oy + ddy[d]; int nx = ox + ddx[d]; /* Check if we can move */ if (!process_monster_can_move(c, mon, m_name, nx, ny, &did_something)) continue; /* Try to break the glyph if there is one. This can happen multiple * times per turn because failure does not break the loop */ if (square_iswarded(c, ny, nx) && !process_monster_glyph(c, mon, nx, ny)) continue; /* The player is in the way. */ if (square_isplayer(c, ny, nx)) { /* Learn about if the monster attacks */ if (mflag_has(mon->mflag, MFLAG_VISIBLE)) rf_on(lore->flags, RF_NEVER_BLOW); /* Some monsters never attack */ if (rf_has(mon->race->flags, RF_NEVER_BLOW)) continue; /* Otherwise, attack the player */ make_attack_normal(mon, player); did_something = true; break; } else { /* Some monsters never move */ if (rf_has(mon->race->flags, RF_NEVER_MOVE)) { /* Learn about lack of movement */ if (mflag_has(mon->mflag, MFLAG_VISIBLE)) rf_on(lore->flags, RF_NEVER_MOVE); return; } } /* A monster is in the way, try to push past/kill */ if (square_monster(c, ny, nx)) { did_something = process_monster_try_push(c, mon, m_name, nx, ny); } else { /* Otherwise we can just move */ monster_swap(oy, ox, ny, nx); did_something = true; } /* Scan all objects in the grid, if we reached it */ if (mon == square_monster(c, ny, nx)) { monster_desc(m_name, sizeof(m_name), mon, MDESC_CAPITAL | MDESC_IND_HID); process_monster_grab_objects(c, mon, m_name, nx, ny); } } if (did_something) { /* Learn about no lack of movement */ if (mflag_has(mon->mflag, MFLAG_VISIBLE)) rf_on(lore->flags, RF_NEVER_MOVE); /* Possible disturb */ if (mflag_has(mon->mflag, MFLAG_VISIBLE) && mflag_has(mon->mflag, MFLAG_VIEW) && OPT(player, disturb_near)) disturb(player, 0); } /* Hack -- get "bold" if out of options */ if (!did_something && mon->m_timed[MON_TMD_FEAR]) mon_clear_timed(mon, MON_TMD_FEAR, MON_TMD_FLG_NOTIFY, false); /* If we see an unaware monster do something, become aware of it */ if (did_something && mflag_has(mon->mflag, MFLAG_UNAWARE)) become_aware(mon); }