Merge branch 'autonomic_stroll'

This commit is contained in:
s452645 2021-05-23 08:48:29 +02:00
commit 439e27625c
5 changed files with 82 additions and 8 deletions

17
game.py
View File

@ -1,4 +1,4 @@
from random import randint from random import choice, randint
import project_constants as const import project_constants as const
@ -112,8 +112,20 @@ class Game:
def get_turn_number(self): def get_turn_number(self):
return self.turn return self.turn
# draws a random mine to disarm (in auto mode)
def set_random_mine_as_target(self):
self.goal = choice(self.minefield.get_active_mines()).position
# display new destination
self.input_box_row.set_texts(user_input=str(self.goal[0]))
self.input_box_column.set_texts(user_input=str(self.goal[1]))
# prevents highlighting input_box_row,
# couldn't find any better solution w/o major Game class changes
self.input_box_row.set_is_selected(False)
# gets action sequence for agent # gets action sequence for agent
def get_action_sequence(self): def get_action_sequence(self, target_type: str = "tile"):
return a_star.graphsearch( return a_star.graphsearch(
initial_state=a_star.State( initial_state=a_star.State(
row=self.agent.row, row=self.agent.row,
@ -121,6 +133,7 @@ class Game:
direction=self.agent.direction direction=self.agent.direction
), ),
minefield=self.minefield, minefield=self.minefield,
target_type=target_type,
tox=self.goal[0], tox=self.goal[0],
toy=self.goal[1] toy=self.goal[1]
) )

22
main.py
View File

@ -1,7 +1,8 @@
# libraries # libraries
import time
import pygame import pygame
from pyglet.gl import * # for blocky textures from pyglet.gl import * # for blocky textures
import random
# other files of this project # other files of this project
from game import Game from game import Game
import project_constants as const import project_constants as const
@ -25,6 +26,7 @@ def main():
# setting flags for program # setting flags for program
running = True running = True
in_menu = True in_menu = True
auto = False
is_game_over = False is_game_over = False
# create and initialize_gui_components game instance # create and initialize_gui_components game instance
@ -37,7 +39,7 @@ def main():
# ==== MENU ==== # # ==== MENU ==== #
# ============== # # ============== #
while running and in_menu: while running and in_menu and not auto:
events = pygame.event.get() events = pygame.event.get()
# checking if game should stop running # checking if game should stop running
@ -58,12 +60,21 @@ def main():
# if ok button is clicked then leave menu section # if ok button is clicked then leave menu section
in_menu = not game.button_ok.is_clicked(pygame.mouse.get_pos(), events) in_menu = not game.button_ok.is_clicked(pygame.mouse.get_pos(), events)
# if auto button is clicked then leave menu and start auto-mode
auto = game.button_auto.is_clicked(pygame.mouse.get_pos(), events)
# ========================== # # ========================== #
# ==== BEFORE GAME LOOP ==== # # ==== BEFORE GAME LOOP ==== #
# ========================== # # ========================== #
# getting action sequence for agent # getting action sequence for agent
action_sequence = game.get_action_sequence() if auto:
in_menu = False
game.set_random_mine_as_target()
action_sequence = game.get_action_sequence("mine")
else:
action_sequence = game.get_action_sequence("tile")
# initializing game attributes before the game loop # initializing game attributes before the game loop
game.initialize_before_game_loop() game.initialize_before_game_loop()
@ -87,6 +98,11 @@ def main():
# drawing minefield and agent instances # drawing minefield and agent instances
game.draw_minefield() game.draw_minefield()
# handling auto button (clicking quits auto-mode)
if auto:
game.button_auto.set_flags(is_active=True)
auto = not game.button_auto.is_clicked(pygame.mouse.get_pos(), events)
# drawing inactive gui components so they don't "disappear" # drawing inactive gui components so they don't "disappear"
game.run_in_game_menu_overlay(pygame.mouse.get_pos(), events) game.run_in_game_menu_overlay(pygame.mouse.get_pos(), events)
game.set_is_active_flag_for_all_in_game_gui_components(False) game.set_is_active_flag_for_all_in_game_gui_components(False)

View File

@ -45,6 +45,22 @@ class Minefield:
if mine is not None and isinstance(mine, TimeMine): if mine is not None and isinstance(mine, TimeMine):
mine.timer = max(0, mine.starting_time - int(self.turn / 4)) mine.timer = max(0, mine.starting_time - int(self.turn / 4))
def get_active_mines(self):
mines = list()
for row in range(const.V_GRID_VER_TILES):
for column in range(const.V_GRID_VER_TILES):
mine = self.matrix[row][column].mine
if mine is not None and mine.active:
# do not add mines with predecessors
if mine.type == 'chained' and mine.predecessor is not None:
continue
mines.append(mine)
return mines
def disarm_mine(self, x, y): def disarm_mine(self, x, y):
tile = self.matrix[x][y] tile = self.matrix[x][y]
mine = tile.mine mine = tile.mine
@ -55,7 +71,6 @@ class Minefield:
# ================ # # ================ #
# check if sapper's destination is accessible # check if sapper's destination is accessible
# If Agent comes upon a tile with a mine his starting position shall be reestablished
@staticmethod @staticmethod
def is_valid_move(target_row: int, target_column: int): def is_valid_move(target_row: int, target_column: int):
if 0 <= target_row < const.V_GRID_VER_TILES \ if 0 <= target_row < const.V_GRID_VER_TILES \

View File

@ -3,7 +3,7 @@ from .mine import Mine
class StandardMine(Mine): class StandardMine(Mine):
def __init__(self, position, active=True): def __init__(self, position, active=True):
self.mine_type = "standard" self.type = "standard"
super().__init__(position, active) super().__init__(position, active)
def disarm(self): def disarm(self):

View File

@ -45,12 +45,32 @@ def get_estimated_cost(node: Node):
return abs(node.state.row - GOAL[0]) + abs(node.state.column - GOAL[1]) return abs(node.state.row - GOAL[0]) + abs(node.state.column - GOAL[1])
def goal_test(state: State): def tile_goal_test(state: State):
if (state.row, state.column) == GOAL: if (state.row, state.column) == GOAL:
return True return True
return False return False
def mine_goal_test(state: State):
if state.row == GOAL[0] and state.column == GOAL[1] - 1:
if state.direction == Direction.RIGHT:
return True
elif state.row == GOAL[0] and state.column == GOAL[1] + 1:
if state.direction == Direction.LEFT:
return True
elif state.row == GOAL[0] - 1 and state.column == GOAL[1]:
if state.direction == Direction.DOWN:
return True
elif state.row == GOAL[0] + 1 and state.column == GOAL[1]:
if state.direction == Direction.UP:
return True
return False
def get_successors(state: State, minefield: Minefield): def get_successors(state: State, minefield: Minefield):
successors = list() successors = list()
@ -73,6 +93,7 @@ def graphsearch(initial_state: State,
minefield: Minefield, minefield: Minefield,
fringe: List[Node] = None, fringe: List[Node] = None,
explored: List[Node] = None, explored: List[Node] = None,
target_type: str = "tile",
tox: int = None, tox: int = None,
toy: int = None): toy: int = None):
@ -86,6 +107,15 @@ def graphsearch(initial_state: State,
if tox is not None and toy is not None: if tox is not None and toy is not None:
GOAL = (tox, toy) GOAL = (tox, toy)
if target_type == "mine":
goal_test = mine_goal_test
else:
goal_test = tile_goal_test
if minefield.matrix[GOAL[0]][GOAL[1]].mine is not None and minefield.matrix[GOAL[0]][GOAL[1]].mine.active:
# TODO: cross-platform popup, move to separate function
ctypes.windll.user32.MessageBoxW(0, "Brak rozwiązania", "GAME OVER", 1)
return []
# fringe and explored initialization # fringe and explored initialization
if fringe is None: if fringe is None:
fringe = list() fringe = list()