import time from minefield import Minefield import project_constants as const from project_constants import Direction from algorithms.search.a_star import State, graphsearch from objects.mine_models.chained_mine import ChainedMine from objects.mine_models.time_mine import TimeMine def possible_states(row, column): possible_states = [] if Minefield.is_valid_move(row + 1, column): possible_states.append(State(row + 1, column, Direction.UP)) if Minefield.is_valid_move(row - 1, column): possible_states.append(State(row - 1, column, Direction.DOWN)) if Minefield.is_valid_move(row, column + 1): possible_states.append(State(row, column + 1, Direction.LEFT)) if Minefield.is_valid_move(row, column - 1): possible_states.append(State(row, column - 1, Direction.RIGHT)) return possible_states def create_scores_table(minefield): mines = get_mines_coords(minefield) dict_table = { mine1: { mine2: { direction: 0 for direction in Direction} for mine2 in mines} for mine1 in mines} dict_table[(0, 0)] = {mine: {Direction.RIGHT: 0} for mine in mines} for mine in mines: _, end_state, cost = \ graphsearch(State(0, 0, Direction.RIGHT), minefield, target_type="mine", tox=mine[0], toy=mine[1], with_data=True) dict_table[(0, 0)][mine][Direction.RIGHT] = (end_state, cost) for mine1 in mines: for mine2 in mines: for initial_state in possible_states(mine1[0], mine1[1]): _, end_state, cost = \ graphsearch(initial_state, minefield, target_type="mine", tox=mine2[0], toy=mine2[1], with_data=True) dict_table[mine1][mine2][initial_state.direction] = (end_state, cost) return dict_table def get_score(minefield, speciment, table=None): score = 0 initial_state = State(0, 0, Direction.RIGHT) if table is not None: for el_index in range(len(speciment)): end_state, cost = table[(initial_state.row, initial_state.column)] \ [(speciment[el_index][0], speciment[el_index][1])] \ [initial_state.direction] initial_state = State(speciment[el_index][0], speciment[el_index][1], end_state.direction) mine = minefield.matrix[speciment[el_index][0]][speciment[el_index][1]].mine if isinstance(mine, ChainedMine) and mine.predecessor is not None and mine.predecessor.active: score += 200 mine.active = False minefield.next_turn(n_turns=cost) score += cost score += 200 * minefield.explosions return score # IF THERE IS NO TABLE else: for el_index in range(len(speciment) - 1): action_sequence, initial_state, cost = \ graphsearch(initial_state, minefield, target_type="mine", tox=speciment[el_index][0], toy=speciment[el_index][1], with_data=True) mine = minefield.matrix[speciment[el_index][0]][speciment[el_index][1]].mine if isinstance(mine, ChainedMine) and mine.predecessor is not None and mine.predecessor.active: cost += 200 mine.active = False for _ in range(cost): minefield.next_turn() score += cost score += 200 * minefield.explosions return score def get_mines_coords(minefield: Minefield): mines = list() for row in range(const.V_GRID_VER_TILES): for column in range(const.V_GRID_VER_TILES): mine = minefield.matrix[row][column].mine if mine is not None: mines.append((row, column)) return mines