From 6db9b24b654beff83f8ccbfb1797306402623a54 Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Thu, 5 Sep 2019 13:11:11 +0200 Subject: [PATCH 01/14] Create bomberman_state_encoding util For encoding a bomberman game state given a board object --- src/features/bomberman_state_encoding.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/features/bomberman_state_encoding.py diff --git a/src/features/bomberman_state_encoding.py b/src/features/bomberman_state_encoding.py new file mode 100644 index 0000000..8681173 --- /dev/null +++ b/src/features/bomberman_state_encoding.py @@ -0,0 +1,13 @@ +import src.entities + +def image_layers(self, board): + # LAYERS: + # - Fire and danger (e.g 0 when bomb is placed -> progress to -1 as it approaches explosion, 1 for safe) + # - Agent/players (e.g discrete numbers 0-3 for players and 4 for empty squares) + # - Walls and bonuses (-1 for wall, 1 for bonus) + # - Powerup status for all players (Vector of size 3 (bombs, speed, fireradius), 1 for each player) + + #TODO: Create the different image layers given board + #TODO: Send inn a dummy board and check for correctness (Visualize with ascii art) + #TODO: Return flattended array (layers + powerup vectors) for input to NN + pass From d1c96f509bdb437afadc3fca3f546f387e7d38d4 Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Mon, 9 Sep 2019 00:33:17 +0200 Subject: [PATCH 02/14] Create functions for creating images for danger, enemies, and env. Not tested. --- src/features/bomberman_state_encoding.py | 93 +++++++++++++++++++++--- 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/src/features/bomberman_state_encoding.py b/src/features/bomberman_state_encoding.py index 8681173..ba1ec65 100644 --- a/src/features/bomberman_state_encoding.py +++ b/src/features/bomberman_state_encoding.py @@ -1,13 +1,84 @@ import src.entities +import numpy as np -def image_layers(self, board): - # LAYERS: - # - Fire and danger (e.g 0 when bomb is placed -> progress to -1 as it approaches explosion, 1 for safe) - # - Agent/players (e.g discrete numbers 0-3 for players and 4 for empty squares) - # - Walls and bonuses (-1 for wall, 1 for bonus) - # - Powerup status for all players (Vector of size 3 (bombs, speed, fireradius), 1 for each player) - - #TODO: Create the different image layers given board - #TODO: Send inn a dummy board and check for correctness (Visualize with ascii art) - #TODO: Return flattended array (layers + powerup vectors) for input to NN - pass +BOMB_MAX_TIME = 3 +BOARD_HEIGHT = 11 +BOARD_WIDTH = 15 + +#TODO: Load in a config file or something isntead of having hard coded constants inside +#TODO: Make this module compatible with conv nets aswell (dont remove walls, and dont flatten) +#TODO: Send inn a dummy board and check for correctness (Visualize with ascii art, board class) + +# LAYERS: +# - Fire and danger (e.g 0 when bomb is placed -> progress to -1 as it approaches explosion, 1 for safe) +# - Agent, crates, bonus, empty tile (0 for empty, 1 for crate, 2 for bonus, 3 for player) +# - Enemy players (0 for empty tiles, 1 for enemy) +# - Powerups ... + +def construct_images(bombs, fires, walls, player, enemies, crates, bonuses): + danger_image = construct_danger_image(bombs, fires, walls) + player_and_env_image = construct_player_and_env_image(player, bonuses, crates, walls) + enemy_image = construct_enemy_image(enemies, walls) + state_vector = np.concatenate((danger_image, player_and_env_image, enemy_image)) + return state_vector + +def construct_danger_image(bombs, fires, walls): + danger_image = np.ones(BOARD_HEIGHT, BOARD_WIDTH) + for bomb in bombs: + x, y = bomb.position.x, bomb.position.y + timer = bomb.timer + str = bomb.strength + + # Mark danger in horizontal direction + danger_radius_left = max(x - str, 0) + danger_radius_right = min(x + str, BOARD_WIDTH - 1) + for x_disp in range(danger_radius_left, danger_radius_right): + danger_image[x_disp, y] = timer/BOMB_MAX_TIME - 1 + + # Mark danger in vertical direction + danger_radius_up = max(y - str, 0) + danger_radius_down = min(y + str, BOARD_HEIGHT - 1) + for y_disp in range(danger_radius_up, danger_radius_down): + danger_image[y_disp, y] = timer/BOMB_MAX_TIME - 1 + + for fire in fires: + x, y = fire.position.x, fire.position.y + danger_image[x, y] = -1 + #TODO: Add representation for how long the fire will remain on the board + + # Flatten layer and remove wall tiles + danger_image_flatten = danger_image.flatten() + danger_image_flatten = remove_walls_from_image(walls, danger_image_flatten) + + return danger_image_flatten + +def construct_player_and_env_image(player, bonuses, crates, walls): + player_and_env_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) + for crate in crates: + player_and_env_image[crate.player.position.x, crate.position.y] = 1 + for bonus in bonuses: + player_and_env_image[bonus.player.position.x, bonus.position.y] = 2 + player_and_env_image[player.position.x, player.position.y] = 3 + + # Flatten layer and remove wall tiles + player_and_env_image_flatten = player_and_env_image.flatten() + player_and_env_image_flatten = remove_walls_from_image(walls, player_and_env_image_flatten) + + return player_and_env_image_flatten + +def construct_enemy_image(enemies, walls): + enemy_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) + for enemy in enemies: + enemy_image[enemy.position.x, enemy.position.y] = 1 + enemy_image_flatten= enemy_image.flatten() + enemy_image_flatten = remove_walls_from_image(walls, enemy_image_flatten) + + return enemy_image_flatten + +def remove_walls_from_image(walls, image): + new_image = image + for wall in walls: + index = BOARD_WIDTH * wall.position.y + wall.position.x + new_image = np.delete(image, index) + + return new_image From 36a8503a3db6cde73138ccd0030db910f2f6a345 Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Mon, 9 Sep 2019 00:37:48 +0200 Subject: [PATCH 03/14] Add some todos for the next steps in developement --- src/features/bomberman_state_encoding.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/features/bomberman_state_encoding.py b/src/features/bomberman_state_encoding.py index ba1ec65..da1ceb9 100644 --- a/src/features/bomberman_state_encoding.py +++ b/src/features/bomberman_state_encoding.py @@ -5,9 +5,13 @@ BOARD_HEIGHT = 11 BOARD_WIDTH = 15 -#TODO: Load in a config file or something isntead of having hard coded constants inside -#TODO: Make this module compatible with conv nets aswell (dont remove walls, and dont flatten) -#TODO: Send inn a dummy board and check for correctness (Visualize with ascii art, board class) +# TODO: Load in a config file or something instead of having hard coded constants inside +# TODO: Send inn a dummy board and check for correctness (Visualize with ascii art, board class) +# TODO: Add powerup information (number of bombs and players speeds) +# TODO: Figure out a way to encode movement (aka player 2 is moving west even though he is standing in position x right now) + +# Nice to have todos: +# TODO: Make this module compatible with conv nets aswell (dont remove walls, and dont flatten) # LAYERS: # - Fire and danger (e.g 0 when bomb is placed -> progress to -1 as it approaches explosion, 1 for safe) From f45f8ca7d7a8274eeae7e4c31cbfdb47a9f0e7c6 Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Mon, 9 Sep 2019 09:49:45 +0200 Subject: [PATCH 04/14] Fix a mistake causing the program to incorrectly iterating over y-tiles when marking bombs --- src/features/bomberman_state_encoding.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/features/bomberman_state_encoding.py b/src/features/bomberman_state_encoding.py index da1ceb9..cbe72d5 100644 --- a/src/features/bomberman_state_encoding.py +++ b/src/features/bomberman_state_encoding.py @@ -8,9 +8,9 @@ # TODO: Load in a config file or something instead of having hard coded constants inside # TODO: Send inn a dummy board and check for correctness (Visualize with ascii art, board class) # TODO: Add powerup information (number of bombs and players speeds) -# TODO: Figure out a way to encode movement (aka player 2 is moving west even though he is standing in position x right now) # Nice to have todos: +# TODO: Figure out a way to encode movement (aka player 2 is moving west even though he is standing in position x right now) # TODO: Make this module compatible with conv nets aswell (dont remove walls, and dont flatten) # LAYERS: @@ -43,7 +43,7 @@ def construct_danger_image(bombs, fires, walls): danger_radius_up = max(y - str, 0) danger_radius_down = min(y + str, BOARD_HEIGHT - 1) for y_disp in range(danger_radius_up, danger_radius_down): - danger_image[y_disp, y] = timer/BOMB_MAX_TIME - 1 + danger_image[x, y_disp] = timer/BOMB_MAX_TIME - 1 for fire in fires: x, y = fire.position.x, fire.position.y @@ -79,10 +79,10 @@ def construct_enemy_image(enemies, walls): return enemy_image_flatten -def remove_walls_from_image(walls, image): - new_image = image +def remove_walls_from_image(walls, image_flatten): + new_image = image_flatten for wall in walls: index = BOARD_WIDTH * wall.position.y + wall.position.x - new_image = np.delete(image, index) + new_image = np.delete(image_flatten, index) return new_image From 8f7d0704fdfd9b00bba19149d7cfbae74a632539 Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Mon, 9 Sep 2019 10:29:55 +0200 Subject: [PATCH 05/14] Correct spelling mistake in one of the images and refactor for code consistency --- src/features/bomberman_state_encoding.py | 26 +++++++++--------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/features/bomberman_state_encoding.py b/src/features/bomberman_state_encoding.py index cbe72d5..2f1a100 100644 --- a/src/features/bomberman_state_encoding.py +++ b/src/features/bomberman_state_encoding.py @@ -29,25 +29,20 @@ def construct_images(bombs, fires, walls, player, enemies, crates, bonuses): def construct_danger_image(bombs, fires, walls): danger_image = np.ones(BOARD_HEIGHT, BOARD_WIDTH) for bomb in bombs: - x, y = bomb.position.x, bomb.position.y - timer = bomb.timer - str = bomb.strength - # Mark danger in horizontal direction - danger_radius_left = max(x - str, 0) - danger_radius_right = min(x + str, BOARD_WIDTH - 1) + danger_radius_left = max(bomb.position.x - bomb.strength, 0) + danger_radius_right = min(bomb.position.x + bomb.strength, BOARD_WIDTH - 1) for x_disp in range(danger_radius_left, danger_radius_right): - danger_image[x_disp, y] = timer/BOMB_MAX_TIME - 1 + danger_image[x_disp, bomb.postion.y] = bomb.timer/BOMB_MAX_TIME - 1 # Mark danger in vertical direction - danger_radius_up = max(y - str, 0) - danger_radius_down = min(y + str, BOARD_HEIGHT - 1) + danger_radius_up = max(bomb.position.y - bomb.strength, 0) + danger_radius_down = min(bomb.position.y + bomb.strength, BOARD_HEIGHT - 1) for y_disp in range(danger_radius_up, danger_radius_down): - danger_image[x, y_disp] = timer/BOMB_MAX_TIME - 1 + danger_image[bomb.position.x, y_disp] = bomb.timer/BOMB_MAX_TIME - 1 for fire in fires: - x, y = fire.position.x, fire.position.y - danger_image[x, y] = -1 + danger_image[fire.position.x, fire.position.y] = -1 #TODO: Add representation for how long the fire will remain on the board # Flatten layer and remove wall tiles @@ -59,9 +54,9 @@ def construct_danger_image(bombs, fires, walls): def construct_player_and_env_image(player, bonuses, crates, walls): player_and_env_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) for crate in crates: - player_and_env_image[crate.player.position.x, crate.position.y] = 1 + player_and_env_image[crate.position.x, crate.position.y] = 1 for bonus in bonuses: - player_and_env_image[bonus.player.position.x, bonus.position.y] = 2 + player_and_env_image[bonus.position.x, bonus.position.y] = 2 player_and_env_image[player.position.x, player.position.y] = 3 # Flatten layer and remove wall tiles @@ -83,6 +78,5 @@ def remove_walls_from_image(walls, image_flatten): new_image = image_flatten for wall in walls: index = BOARD_WIDTH * wall.position.y + wall.position.x - new_image = np.delete(image_flatten, index) - + new_image = np.delete(new_image, index) return new_image From ce51a6ff06c850e6d836d8d22fbd73b27d08b243 Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Mon, 9 Sep 2019 12:34:07 +0200 Subject: [PATCH 06/14] Move information about the agent position to the adversary image (renamed from enemy image) and scale all values -1 to 1 --- src/features/bomberman_state_encoding.py | 27 +++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/features/bomberman_state_encoding.py b/src/features/bomberman_state_encoding.py index 2f1a100..a0e715e 100644 --- a/src/features/bomberman_state_encoding.py +++ b/src/features/bomberman_state_encoding.py @@ -7,7 +7,7 @@ # TODO: Load in a config file or something instead of having hard coded constants inside # TODO: Send inn a dummy board and check for correctness (Visualize with ascii art, board class) -# TODO: Add powerup information (number of bombs and players speeds) +# TODO: Add powerup information (number of bombs the agent has left and players speeds) # Nice to have todos: # TODO: Figure out a way to encode movement (aka player 2 is moving west even though he is standing in position x right now) @@ -15,15 +15,15 @@ # LAYERS: # - Fire and danger (e.g 0 when bomb is placed -> progress to -1 as it approaches explosion, 1 for safe) -# - Agent, crates, bonus, empty tile (0 for empty, 1 for crate, 2 for bonus, 3 for player) -# - Enemy players (0 for empty tiles, 1 for enemy) +# - Agent, crates, bonus, empty tile (-1 for bonus, 0 for empty, 1 for create) +# - Players and enemy players (-1 for enemy, 0 for empty tiles, 1 for player) # - Powerups ... -def construct_images(bombs, fires, walls, player, enemies, crates, bonuses): +def construct_images(bombs, fires, walls, agent, enemies, crates, bonuses): danger_image = construct_danger_image(bombs, fires, walls) - player_and_env_image = construct_player_and_env_image(player, bonuses, crates, walls) - enemy_image = construct_enemy_image(enemies, walls) - state_vector = np.concatenate((danger_image, player_and_env_image, enemy_image)) + env_image = construct_env_image(bonuses, crates, walls) + adversary_image = construct_adversary_image(agent, enemies, walls) + state_vector = np.concatenate((danger_image, env_image, adversary_image)) return state_vector def construct_danger_image(bombs, fires, walls): @@ -51,13 +51,12 @@ def construct_danger_image(bombs, fires, walls): return danger_image_flatten -def construct_player_and_env_image(player, bonuses, crates, walls): +def construct_env_image(bonuses, crates, walls): player_and_env_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) for crate in crates: player_and_env_image[crate.position.x, crate.position.y] = 1 for bonus in bonuses: - player_and_env_image[bonus.position.x, bonus.position.y] = 2 - player_and_env_image[player.position.x, player.position.y] = 3 + player_and_env_image[bonus.position.x, bonus.position.y] = -1 # Flatten layer and remove wall tiles player_and_env_image_flatten = player_and_env_image.flatten() @@ -65,15 +64,19 @@ def construct_player_and_env_image(player, bonuses, crates, walls): return player_and_env_image_flatten -def construct_enemy_image(enemies, walls): +def construct_adversary_image(agent, enemies, walls): enemy_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) + enemy_image[agent.position.x, agent.position.y] = 1 for enemy in enemies: - enemy_image[enemy.position.x, enemy.position.y] = 1 + enemy_image[enemy.position.x, enemy.position.y] = -1 enemy_image_flatten= enemy_image.flatten() enemy_image_flatten = remove_walls_from_image(walls, enemy_image_flatten) return enemy_image_flatten +def construct_powerup_vector(the_agent, enemies): + raise NotImplemented() + def remove_walls_from_image(walls, image_flatten): new_image = image_flatten for wall in walls: From f678e453bad7d0ababfb7ac441cf34d26c89b27a Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Mon, 9 Sep 2019 14:40:23 +0200 Subject: [PATCH 07/14] =?UTF-8?q?=C2=96Remove=20agent=20position=20from=20?= =?UTF-8?q?adversary=20image=20and=20create=20a=20new=20agent=20image=20sh?= =?UTF-8?q?owing=20the=20agents=20position?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/bomberman_state_encoding.py | 38 ++++++++++++++---------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/features/bomberman_state_encoding.py b/src/features/bomberman_state_encoding.py index a0e715e..cde7b39 100644 --- a/src/features/bomberman_state_encoding.py +++ b/src/features/bomberman_state_encoding.py @@ -15,15 +15,16 @@ # LAYERS: # - Fire and danger (e.g 0 when bomb is placed -> progress to -1 as it approaches explosion, 1 for safe) -# - Agent, crates, bonus, empty tile (-1 for bonus, 0 for empty, 1 for create) -# - Players and enemy players (-1 for enemy, 0 for empty tiles, 1 for player) -# - Powerups ... +# - Crates, bonus, empty tile (-1 for bonus, 0 for empty, 1 for create) +# - The agent and enemy players (-1 for enemy, 0 for empty tiles, 1 for player) +# - Powerups ... (not implemented) -def construct_images(bombs, fires, walls, agent, enemies, crates, bonuses): +def construct_flattened_images_state(bombs, fires, walls, agent, enemies, crates, bonuses): danger_image = construct_danger_image(bombs, fires, walls) env_image = construct_env_image(bonuses, crates, walls) + agent_image = construct_agent_image(agent, walls) adversary_image = construct_adversary_image(agent, enemies, walls) - state_vector = np.concatenate((danger_image, env_image, adversary_image)) + state_vector = np.concatenate((danger_image, env_image, agent_image, adversary_image)) return state_vector def construct_danger_image(bombs, fires, walls): @@ -52,29 +53,36 @@ def construct_danger_image(bombs, fires, walls): return danger_image_flatten def construct_env_image(bonuses, crates, walls): - player_and_env_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) + env_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) for crate in crates: - player_and_env_image[crate.position.x, crate.position.y] = 1 + env_image[crate.position.x, crate.position.y] = 1 for bonus in bonuses: - player_and_env_image[bonus.position.x, bonus.position.y] = -1 + env_image[bonus.position.x, bonus.position.y] = -1 # Flatten layer and remove wall tiles - player_and_env_image_flatten = player_and_env_image.flatten() - player_and_env_image_flatten = remove_walls_from_image(walls, player_and_env_image_flatten) + env_image_flatten = env_image.flatten() + env_image_flatten = remove_walls_from_image(walls, env_image_flatten) - return player_and_env_image_flatten + return env_image_flatten -def construct_adversary_image(agent, enemies, walls): +def construct_adversary_image(enemies, walls): enemy_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) - enemy_image[agent.position.x, agent.position.y] = 1 for enemy in enemies: - enemy_image[enemy.position.x, enemy.position.y] = -1 + enemy_image[enemy.position.x, enemy.position.y] = 1 enemy_image_flatten= enemy_image.flatten() enemy_image_flatten = remove_walls_from_image(walls, enemy_image_flatten) return enemy_image_flatten -def construct_powerup_vector(the_agent, enemies): +def construct_agent_image(agent, walls): + agent_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) + agent_image[agent.position.x, agent.position.y] = 1 + agent_image_flatten= agent_image.flatten() + agent_image_flatten = remove_walls_from_image(walls, agent_image_flatten) + + return agent_image_flatten + +def construct_powerup_vector(agent, enemies): raise NotImplemented() def remove_walls_from_image(walls, image_flatten): From 886169b26d5be251dfe18f1f7148bfc0c283af9a Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Mon, 9 Sep 2019 14:41:44 +0200 Subject: [PATCH 08/14] Correct parameter list for adversary image that was not updated in prev commit --- src/features/bomberman_state_encoding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/bomberman_state_encoding.py b/src/features/bomberman_state_encoding.py index cde7b39..be383ae 100644 --- a/src/features/bomberman_state_encoding.py +++ b/src/features/bomberman_state_encoding.py @@ -23,7 +23,7 @@ def construct_flattened_images_state(bombs, fires, walls, agent, enemies, crates danger_image = construct_danger_image(bombs, fires, walls) env_image = construct_env_image(bonuses, crates, walls) agent_image = construct_agent_image(agent, walls) - adversary_image = construct_adversary_image(agent, enemies, walls) + adversary_image = construct_adversary_image(enemies, walls) state_vector = np.concatenate((danger_image, env_image, agent_image, adversary_image)) return state_vector From 7a0f4f4a3813f4c7e82fc1fe476c3fedc9a6bf85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20S=C3=B8dal=20Dietrichson?= Date: Mon, 9 Sep 2019 14:46:49 +0200 Subject: [PATCH 09/14] Removed irrelevant stuff --- README.md | 43 +------------------------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/README.md b/README.md index 6c1bcdc..2888320 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ You can log the training using a tensorboard object that logs the training resul To start tensorboard: -``` tensorboard --logdir src/agents/agent_storage ``` +``` tensorboard --logdir /RoboSchool/src/agents/agent_storage ``` This will start tensorboard on localhost:6006 from the runs folder @@ -53,47 +53,6 @@ Setting up a docker volume, i.e. a dynamic connection between a folder on the lo https://github.com/Cyb3rWard0g/HELK/issues/79 -### Omniboard and mongoDB - -Omniboard and mongo DB must be run and also be able to talk with each other. This can be obtained by starting them on the same docker network. First, create a new docker network or use an existing network - -``` docker network create omniboard-network ``` - -We now have a network on which to run the docker containers. The mongodb and omniboard container should use the same docker network - -``` docker run --rm --name mongo-container --net omniboard-network -d mongo ``` - -Then run the omniboard network - -``` docker run --rm -d -p 9000:9000 --name omniboard --net=omniboard-network vivekratnavel/omniboard -m MONGODB_CONTAINER:27017:sacred ``` - - -### RL development environment - -To start up the RL environment with a jupyter notebook running, write: - -``` docker run --rm -it -v pwd:/notebooks -p 8888:8888 justheuristic/practical_rl ``` - -Go to localhost:8888 and insert the token from the console to log in. A RL environment image has been made for this projects and can be run by - -``` docker run --rm -it -p 8888:8888 fabiansd/rl-env bash ``` - -You will then start up a linux container with all the necessary libraries installed. Here you can run python scripts and linux commands, and also start jupyter by typing - -``` sh /RoboSchool/src/run_jyputer.sh ``` - - -### Flask application - -The frontend application is implemented with a Flask app and docker image built from /Roboschool with - -``` docker build -f app/Dockerfile -t fabiansd/roboschool-app . ``` - -The application can be started up by running: - -``` docker run --rm -d -p 9999:9999 fabiansd/roboschool-app ``` - -Then go to localhost:9090 to see the frontend application ### Docker-compose From 89bf8e111bfd78d9d94d5bf1346b6362d78ef884 Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Tue, 10 Sep 2019 15:03:39 +0200 Subject: [PATCH 10/14] Add __init__.py file to entities such that it recognized as a module --- src/entities/__init__.py | 0 tests/features/test_bomberman_state_encoding.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/entities/__init__.py create mode 100644 tests/features/test_bomberman_state_encoding.py diff --git a/src/entities/__init__.py b/src/entities/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/features/test_bomberman_state_encoding.py b/tests/features/test_bomberman_state_encoding.py new file mode 100644 index 0000000..e69de29 From 2dd31ce9d19a32fa030f793a1b7fe9787ab39413 Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Tue, 10 Sep 2019 15:08:31 +0200 Subject: [PATCH 11/14] Fix numpy indexing (y before x convention) --- src/features/bomberman_state_encoding.py | 41 +++++++++++++++--------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/features/bomberman_state_encoding.py b/src/features/bomberman_state_encoding.py index be383ae..58859fa 100644 --- a/src/features/bomberman_state_encoding.py +++ b/src/features/bomberman_state_encoding.py @@ -1,12 +1,15 @@ -import src.entities +from src.entities.bomb import Bomb import numpy as np -BOMB_MAX_TIME = 3 -BOARD_HEIGHT = 11 -BOARD_WIDTH = 15 +BOMB_MAX_TIME = 5 +BOARD_HEIGHT = 8 +BOARD_WIDTH = 7 -# TODO: Load in a config file or something instead of having hard coded constants inside +# TODO: When inserting danger level, check if there is already a higher danger level in the square +# TODO: When inserting danger, stop marking danger when you hit a wall/crate # TODO: Send inn a dummy board and check for correctness (Visualize with ascii art, board class) + +# TODO: Load in a config file or something instead of having hard coded constants inside # TODO: Add powerup information (number of bombs the agent has left and players speeds) # Nice to have todos: @@ -28,22 +31,22 @@ def construct_flattened_images_state(bombs, fires, walls, agent, enemies, crates return state_vector def construct_danger_image(bombs, fires, walls): - danger_image = np.ones(BOARD_HEIGHT, BOARD_WIDTH) + danger_image = np.ones((BOARD_HEIGHT, BOARD_WIDTH)) for bomb in bombs: # Mark danger in horizontal direction danger_radius_left = max(bomb.position.x - bomb.strength, 0) danger_radius_right = min(bomb.position.x + bomb.strength, BOARD_WIDTH - 1) for x_disp in range(danger_radius_left, danger_radius_right): - danger_image[x_disp, bomb.postion.y] = bomb.timer/BOMB_MAX_TIME - 1 + danger_image[bomb.position.y, x_disp] = bomb.timer/BOMB_MAX_TIME - 1 # Mark danger in vertical direction danger_radius_up = max(bomb.position.y - bomb.strength, 0) danger_radius_down = min(bomb.position.y + bomb.strength, BOARD_HEIGHT - 1) for y_disp in range(danger_radius_up, danger_radius_down): - danger_image[bomb.position.x, y_disp] = bomb.timer/BOMB_MAX_TIME - 1 + danger_image[y_disp, bomb.position.x] = bomb.timer/BOMB_MAX_TIME - 1 for fire in fires: - danger_image[fire.position.x, fire.position.y] = -1 + danger_image[fire.position.y, fire.position.x] = -1 #TODO: Add representation for how long the fire will remain on the board # Flatten layer and remove wall tiles @@ -53,11 +56,11 @@ def construct_danger_image(bombs, fires, walls): return danger_image_flatten def construct_env_image(bonuses, crates, walls): - env_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) + env_image = np.zeros((BOARD_HEIGHT, BOARD_WIDTH)) for crate in crates: - env_image[crate.position.x, crate.position.y] = 1 + env_image[crate.position.y, crate.position.x] = 1 for bonus in bonuses: - env_image[bonus.position.x, bonus.position.y] = -1 + env_image[bonus.position.y, bonus.position.x] = -1 # Flatten layer and remove wall tiles env_image_flatten = env_image.flatten() @@ -66,22 +69,28 @@ def construct_env_image(bonuses, crates, walls): return env_image_flatten def construct_adversary_image(enemies, walls): - enemy_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) + enemy_image = np.zeros((BOARD_HEIGHT, BOARD_WIDTH)) for enemy in enemies: - enemy_image[enemy.position.x, enemy.position.y] = 1 + enemy_image[enemy.position.y, enemy.position.x] = 1 enemy_image_flatten= enemy_image.flatten() enemy_image_flatten = remove_walls_from_image(walls, enemy_image_flatten) return enemy_image_flatten def construct_agent_image(agent, walls): - agent_image = np.zeros(BOARD_HEIGHT, BOARD_WIDTH) - agent_image[agent.position.x, agent.position.y] = 1 + agent_image = np.zeros((BOARD_HEIGHT, BOARD_WIDTH)) + agent_image[agent.position.y, agent.position.x] = 1 agent_image_flatten= agent_image.flatten() agent_image_flatten = remove_walls_from_image(walls, agent_image_flatten) return agent_image_flatten +def construct_wall_image(walls): + wall_image = np.zeros((BOARD_HEIGHT, BOARD_WIDTH)) + for wall in walls: + wall_image[wall.position.y, wall.position.x] = 1 + return wall_image + def construct_powerup_vector(agent, enemies): raise NotImplemented() From 383483ec50f35527685a20eadecde281b8e9f2bf Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Tue, 10 Sep 2019 15:09:32 +0200 Subject: [PATCH 12/14] Add bomberman_state_encoding test (incomplete) --- .../features/test_bomberman_state_encoding.py | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/tests/features/test_bomberman_state_encoding.py b/tests/features/test_bomberman_state_encoding.py index e69de29..2a747b4 100644 --- a/tests/features/test_bomberman_state_encoding.py +++ b/tests/features/test_bomberman_state_encoding.py @@ -0,0 +1,70 @@ +from src.features import bomberman_state_encoding +from src.entities.bomb import Bomb +from src.entities.crate import Crate +from src.entities.position import Position +from src.entities.fire import Fire +from src.entities.player import Player +from src.entities.wall import Wall +from src.entities.bonus import Bonus +import numpy as np + +danger_image_solution = np.array([ + [0, 0, 0, 0, 1, 1, 1], + [1, 0, 1, 1, 1, 1, 1], + [1, 0, 1, 1, 1, 1, 1], + [1, 1, 3/5-1, 1, 1, 1, 0.1/5-1], + [3/5-1, 3/5-1, 3/5-1, 3/5-1, 3/5-1, 0.1/5-1, 0.1/5-1], + [1, 1, 1, 1, 1, 1, 0.1/5-1], + [1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1] +]) + +# Objects +bombs = [] +bombs.append(Bomb(position = Position(1,0), strength = 2, timer = 5)) +bombs.append(Bomb(position = Position(2,4), strength = 3, timer = 2)) +bombs.append(Bomb(position = Position(6,4), strength = 1, timer = 0.1)) +fires = [] +fires.append(Fire(position = Position(5, 1))) +fires.append(Fire(position = Position(6, 1))) +fires.append(Fire(position = Position(7, 1))) +fires.append(Fire(position = Position(6, 2))) +crates = [] +crates.append(Crate(position = Position(0,0))) +crates.append(Crate(position = Position(3,2))) +crates.append(Crate(position = Position(3,3))) +crates.append(Crate(position = Position(3,4))) +crates.append(Crate(position = Position(3,5))) +crates.append(Crate(position = Position(3,6))) +crates.append(Crate(position = Position(2,3))) +crates.append(Crate(position = Position(3,3))) +crates.append(Crate(position = Position(4,3))) +crates.append(Crate(position = Position(5,3))) +crates.append(Crate(position = Position(6,3))) +walls = [] +walls.append(Wall(position = Position(2, 2))) +walls.append(Wall(position = Position(2, 4))) +walls.append(Wall(position = Position(5, 2))) +walls.append(Wall(position = Position(5, 4))) +player = Player(position = Position(1, 1), username = 'agent') +enemies = [] +enemies.append(Player(position = Position(1, 1), username = 'enemy_1')) +enemies.append(Player(position = Position(0, 4), username = 'enemy_2')) +enemies.append(Player(position = Position(6, 0), username = 'enemy_3')) +enemies.append(Player(position = Position(7, 6), username = 'enemy_4')) +bonuses = [] +bonuses.append(Bonus(position = Position(0, 6), type = 'BLAST_RADIUS')) +bonuses.append(Bonus(position = Position(4, 4), type = 'BLAST_RADIUS')) + +state_vector = bomberman_state_encoding.construct_flattened_images_state( + bombs = bombs, + fires = fires, + walls = walls, + agent = player, + enemies = enemies, + crates = crates, + bonuses = bonuses +) + +print(state_vector) +print(len(state_vector)) \ No newline at end of file From 4a25bc22ce64246ba1409c99da76ded946deae6f Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Mon, 16 Sep 2019 09:41:26 +0200 Subject: [PATCH 13/14] Fix danger image such that danger stops at walls, make flatten optional, split player image into adversary and agent --- src/features/bomberman_state_encoding.py | 136 ++++++++++++++--------- 1 file changed, 82 insertions(+), 54 deletions(-) diff --git a/src/features/bomberman_state_encoding.py b/src/features/bomberman_state_encoding.py index 58859fa..0b25e2b 100644 --- a/src/features/bomberman_state_encoding.py +++ b/src/features/bomberman_state_encoding.py @@ -1,95 +1,111 @@ -from src.entities.bomb import Bomb import numpy as np BOMB_MAX_TIME = 5 BOARD_HEIGHT = 8 BOARD_WIDTH = 7 +NUM_IMAGES = 4 -# TODO: When inserting danger level, check if there is already a higher danger level in the square -# TODO: When inserting danger, stop marking danger when you hit a wall/crate -# TODO: Send inn a dummy board and check for correctness (Visualize with ascii art, board class) - -# TODO: Load in a config file or something instead of having hard coded constants inside -# TODO: Add powerup information (number of bombs the agent has left and players speeds) +# TODO: Load in a config file or something instead of having hard coded constants for board height/width and max bomb time # Nice to have todos: # TODO: Figure out a way to encode movement (aka player 2 is moving west even though he is standing in position x right now) -# TODO: Make this module compatible with conv nets aswell (dont remove walls, and dont flatten) +# TODO: Add representation for how long the fire will remain on the board +# TODO: Add powerup information (number of bombs the agent has left, the agents speed, and other players bombs available) +# TODO: Implement a relative state vector that encodes information locally and relative to the agents position (reduced state vector) # LAYERS: # - Fire and danger (e.g 0 when bomb is placed -> progress to -1 as it approaches explosion, 1 for safe) # - Crates, bonus, empty tile (-1 for bonus, 0 for empty, 1 for create) -# - The agent and enemy players (-1 for enemy, 0 for empty tiles, 1 for player) -# - Powerups ... (not implemented) - -def construct_flattened_images_state(bombs, fires, walls, agent, enemies, crates, bonuses): - danger_image = construct_danger_image(bombs, fires, walls) - env_image = construct_env_image(bonuses, crates, walls) - agent_image = construct_agent_image(agent, walls) - adversary_image = construct_adversary_image(enemies, walls) - state_vector = np.concatenate((danger_image, env_image, agent_image, adversary_image)) +# - Adversaries (1 for enemy, 0 for not) +# - Player position (1 for current position, 0 for not) + +def construct_full_state(bombs, fires, walls, agent, enemies, crates, bonuses, flatten = True): + images = [] + solids_image = construct_solids_image(walls, crates) # for help to construct danger_image only + images.append(construct_danger_image(bombs, fires, solids_image)) + images.append(construct_env_image(bonuses, crates)) + images.append(construct_agent_image(agent)) + images.append(construct_adversary_image(enemies)) + if flatten: + state_vector = np.concatenate([flatten_image(image, walls) for image in images]) + else: + state_vector = np.dstack((image for image in images)) return state_vector -def construct_danger_image(bombs, fires, walls): +def construct_relative_state(): + return NotImplemented() + +def construct_danger_image(bombs, fires, wall_image): danger_image = np.ones((BOARD_HEIGHT, BOARD_WIDTH)) - for bomb in bombs: + bombs_timer_sorted = sorted(bombs, key=lambda bomb: bomb.timer, reverse=True) # sort on ascending timers + for bomb in bombs_timer_sorted: # Mark danger in horizontal direction - danger_radius_left = max(bomb.position.x - bomb.strength, 0) - danger_radius_right = min(bomb.position.x + bomb.strength, BOARD_WIDTH - 1) - for x_disp in range(danger_radius_left, danger_radius_right): - danger_image[bomb.position.y, x_disp] = bomb.timer/BOMB_MAX_TIME - 1 + danger_most_left = max(bomb.position.x - bomb.strength, 0) + danger_most_right = min(bomb.position.x + bomb.strength, BOARD_WIDTH - 1) + for x in range(bomb.position.x, danger_most_left - 1, -1): + if(wall_image[bomb.position.y, x] == 1): + break + else: + danger_image[bomb.position.y, x] = bomb.timer/BOMB_MAX_TIME - 1 + if(wall_image[bomb.position.y, x] != 0): + break + for x in range(bomb.position.x, danger_most_right + 1, 1): + if(wall_image[bomb.position.y, x] == 1): + break + else: + danger_image[bomb.position.y, x] = bomb.timer / BOMB_MAX_TIME - 1 + if (wall_image[bomb.position.y, x] != 0): + break # Mark danger in vertical direction - danger_radius_up = max(bomb.position.y - bomb.strength, 0) - danger_radius_down = min(bomb.position.y + bomb.strength, BOARD_HEIGHT - 1) - for y_disp in range(danger_radius_up, danger_radius_down): - danger_image[y_disp, bomb.position.x] = bomb.timer/BOMB_MAX_TIME - 1 + danger_most_up = max(bomb.position.y - bomb.strength, 0) + danger_most_down = min(bomb.position.y + bomb.strength, BOARD_HEIGHT - 1) + for y in range(bomb.position.y, danger_most_up - 1, -1): + if(wall_image[y, bomb.position.x] == 1): + break + else: + danger_image[y, bomb.position.x] = bomb.timer/BOMB_MAX_TIME - 1 + if(wall_image[y, bomb.position.x] != 0): + break + for y in range(bomb.position.y, danger_most_down + 1, 1): + if(wall_image[y, bomb.position.x] == 1): + break + else: + danger_image[y, bomb.position.x] = bomb.timer/BOMB_MAX_TIME - 1 + if(wall_image[y, bomb.position.x] != 0): + break for fire in fires: danger_image[fire.position.y, fire.position.x] = -1 - #TODO: Add representation for how long the fire will remain on the board - - # Flatten layer and remove wall tiles - danger_image_flatten = danger_image.flatten() - danger_image_flatten = remove_walls_from_image(walls, danger_image_flatten) - return danger_image_flatten + return danger_image -def construct_env_image(bonuses, crates, walls): +def construct_env_image(bonuses, crates): env_image = np.zeros((BOARD_HEIGHT, BOARD_WIDTH)) for crate in crates: env_image[crate.position.y, crate.position.x] = 1 for bonus in bonuses: env_image[bonus.position.y, bonus.position.x] = -1 + return env_image - # Flatten layer and remove wall tiles - env_image_flatten = env_image.flatten() - env_image_flatten = remove_walls_from_image(walls, env_image_flatten) - - return env_image_flatten - -def construct_adversary_image(enemies, walls): +def construct_adversary_image(enemies): enemy_image = np.zeros((BOARD_HEIGHT, BOARD_WIDTH)) for enemy in enemies: enemy_image[enemy.position.y, enemy.position.x] = 1 - enemy_image_flatten= enemy_image.flatten() - enemy_image_flatten = remove_walls_from_image(walls, enemy_image_flatten) + return enemy_image - return enemy_image_flatten - -def construct_agent_image(agent, walls): +def construct_agent_image(agent): agent_image = np.zeros((BOARD_HEIGHT, BOARD_WIDTH)) agent_image[agent.position.y, agent.position.x] = 1 - agent_image_flatten= agent_image.flatten() - agent_image_flatten = remove_walls_from_image(walls, agent_image_flatten) - - return agent_image_flatten + return agent_image -def construct_wall_image(walls): - wall_image = np.zeros((BOARD_HEIGHT, BOARD_WIDTH)) +def construct_solids_image(walls, crates): + solids_image = np.zeros((BOARD_HEIGHT, BOARD_WIDTH)) for wall in walls: - wall_image[wall.position.y, wall.position.x] = 1 - return wall_image + solids_image[wall.position.y, wall.position.x] = 1 + for crate in crates: + solids_image[crate.position.y, crate.position.x] = -1 + return solids_image def construct_powerup_vector(agent, enemies): raise NotImplemented() @@ -100,3 +116,15 @@ def remove_walls_from_image(walls, image_flatten): index = BOARD_WIDTH * wall.position.y + wall.position.x new_image = np.delete(new_image, index) return new_image + +def flatten_image(image, walls): + image_flatten = image.flatten() + image_flatten_no_walls = remove_walls_from_image(walls=walls, image_flatten=image_flatten) + return image_flatten_no_walls + +def visualize_image(image): + ydim, xdim = image.shape + for y in range(0, ydim): + for x in range(0, xdim): + print(image[y, x], end = " ") + print() From e9d6a8c2dbb1001231ac8f58ce48c6741dc9d9bd Mon Sep 17 00:00:00 2001 From: Lasse Henriksen Date: Mon, 16 Sep 2019 09:44:59 +0200 Subject: [PATCH 14/14] Create test for bomber_state_encoding (passes) --- .../features/test_bomberman_state_encoding.py | 168 +++++++++++++----- 1 file changed, 124 insertions(+), 44 deletions(-) diff --git a/tests/features/test_bomberman_state_encoding.py b/tests/features/test_bomberman_state_encoding.py index 2a747b4..5c159f8 100644 --- a/tests/features/test_bomberman_state_encoding.py +++ b/tests/features/test_bomberman_state_encoding.py @@ -8,63 +8,143 @@ from src.entities.bonus import Bonus import numpy as np +board_height = bomberman_state_encoding.BOARD_HEIGHT +board_width = bomberman_state_encoding.BOARD_WIDTH +num_images = bomberman_state_encoding.NUM_IMAGES + danger_image_solution = np.array([ [0, 0, 0, 0, 1, 1, 1], [1, 0, 1, 1, 1, 1, 1], [1, 0, 1, 1, 1, 1, 1], - [1, 1, 3/5-1, 1, 1, 1, 0.1/5-1], - [3/5-1, 3/5-1, 3/5-1, 3/5-1, 3/5-1, 0.1/5-1, 0.1/5-1], - [1, 1, 1, 1, 1, 1, 0.1/5-1], - [1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1] + [1, 1, 2/5-1, 1, 1, 1, 0.1/5-1], + [2/5-1, 2/5-1, 2/5-1, 2/5-1, 1, 0.1/5-1, 0.1/5-1], + [1, -1, 1, 1, 1, 0.2/5-1, 0.1/5-1], + [1, -1, -1, 1, 1, 1, 0.2/5-1], + [1, -1, 1, 1, 1, 1, 1] +]) + +env_image_solution = np.array([ + [1, 0, 0, 0, 0, 0, -1], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + [0, 0, 1, 1, 1, 1, 1], + [0, 0, 0, 1, -1, 1, 0], + [0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0] +]) + +adversary_image_solution = np.array([ + [0, 0, 0, 0, 1, 0, 0], + [0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 1] +]) + +agent_image_solution = np.array([ + [0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0] +]) + +solids_image_solution = np.array([ + [-1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 1, -1, 1, 0, 0], + [0, 0, -1, -1, -1, -1, -1], + [0, 0, 0, -1, 0, -1, 0], + [0, 0, 1, -1, 1, 0, 0], + [0, 0, 0, -1, 0, 0, 0], + [0, 0, 0, -1, 0, 0, 0] ]) # Objects bombs = [] -bombs.append(Bomb(position = Position(1,0), strength = 2, timer = 5)) -bombs.append(Bomb(position = Position(2,4), strength = 3, timer = 2)) -bombs.append(Bomb(position = Position(6,4), strength = 1, timer = 0.1)) +bombs.append(Bomb(position = Position(x=2, y=4), strength = 3, timer = 2)) +bombs.append(Bomb(position = Position(x=1,y=0), strength = 2, timer = 5)) +bombs.append(Bomb(position = Position(x=6,y=4), strength = 1, timer = 0.1)) +bombs.append(Bomb(position = Position(x=6,y=5), strength = 1, timer = 0.2)) fires = [] -fires.append(Fire(position = Position(5, 1))) -fires.append(Fire(position = Position(6, 1))) -fires.append(Fire(position = Position(7, 1))) -fires.append(Fire(position = Position(6, 2))) +fires.append(Fire(position = Position(x=1,y=5))) +fires.append(Fire(position = Position(x=1,y=6))) +fires.append(Fire(position = Position(x=1,y=7))) +fires.append(Fire(position = Position(x=2,y=6))) crates = [] -crates.append(Crate(position = Position(0,0))) -crates.append(Crate(position = Position(3,2))) -crates.append(Crate(position = Position(3,3))) -crates.append(Crate(position = Position(3,4))) -crates.append(Crate(position = Position(3,5))) -crates.append(Crate(position = Position(3,6))) -crates.append(Crate(position = Position(2,3))) -crates.append(Crate(position = Position(3,3))) -crates.append(Crate(position = Position(4,3))) -crates.append(Crate(position = Position(5,3))) -crates.append(Crate(position = Position(6,3))) +crates.append(Crate(position = Position(x=0,y=0))) +crates.append(Crate(position = Position(x=3,y=2))) +crates.append(Crate(position = Position(x=3,y=3))) +crates.append(Crate(position = Position(x=3,y=4))) +crates.append(Crate(position = Position(x=3,y=5))) +crates.append(Crate(position = Position(x=3,y=6))) +crates.append(Crate(position = Position(x=3,y=7))) +crates.append(Crate(position = Position(x=2,y=3))) +crates.append(Crate(position = Position(x=3,y=3))) +crates.append(Crate(position = Position(x=4,y=3))) +crates.append(Crate(position = Position(x=5,y=3))) +crates.append(Crate(position = Position(x=6,y=3))) +crates.append(Crate(position = Position(x=5,y=4))) walls = [] -walls.append(Wall(position = Position(2, 2))) -walls.append(Wall(position = Position(2, 4))) -walls.append(Wall(position = Position(5, 2))) -walls.append(Wall(position = Position(5, 4))) -player = Player(position = Position(1, 1), username = 'agent') +walls.append(Wall(position = Position(x=2, y=2))) +walls.append(Wall(position = Position(x=2, y=5))) +walls.append(Wall(position = Position(x=4, y=2))) +walls.append(Wall(position = Position(x=4, y=5))) +agent = Player(position = Position(1, 1), username = 'agent') enemies = [] -enemies.append(Player(position = Position(1, 1), username = 'enemy_1')) -enemies.append(Player(position = Position(0, 4), username = 'enemy_2')) -enemies.append(Player(position = Position(6, 0), username = 'enemy_3')) -enemies.append(Player(position = Position(7, 6), username = 'enemy_4')) +enemies.append(Player(position = Position(1,1), username = 'enemy_1')) +enemies.append(Player(position = Position(4,0), username = 'enemy_2')) +enemies.append(Player(position = Position(0,6), username = 'enemy_3')) +enemies.append(Player(position = Position(6,7), username = 'enemy_4')) bonuses = [] -bonuses.append(Bonus(position = Position(0, 6), type = 'BLAST_RADIUS')) +bonuses.append(Bonus(position = Position(6, 0), type = 'BLAST_RADIUS')) bonuses.append(Bonus(position = Position(4, 4), type = 'BLAST_RADIUS')) -state_vector = bomberman_state_encoding.construct_flattened_images_state( - bombs = bombs, - fires = fires, - walls = walls, - agent = player, - enemies = enemies, - crates = crates, - bonuses = bonuses -) +def test_construct_full_state(): + state_vector = bomberman_state_encoding.construct_full_state( + bombs = bombs, + fires = fires, + walls = walls, + agent = agent, + enemies = enemies, + crates = crates, + bonuses = bonuses, + flatten = True + ) + assert len(state_vector) == (num_images*board_width*board_height - num_images*len(walls)),\ + "Length of the flattened-full state vector is incorrect!" + +def test_construct_danger_image(): + solids_image = bomberman_state_encoding.construct_solids_image(walls=walls, crates=crates) + danger_image = bomberman_state_encoding.construct_danger_image(bombs=bombs, fires=fires, wall_image=solids_image) + assert np.array_equal(danger_image, danger_image_solution) == True, "Danger image is incorrect!" + +def test_construct_env_image(): + env_image = bomberman_state_encoding.construct_env_image(crates=crates, bonuses=bonuses) + assert np.array_equal(env_image, env_image_solution) == True, "Environment image is incorrect!" + +def test_construct_adversary_image(): + adversary_image = bomberman_state_encoding.construct_adversary_image(enemies=enemies) + assert np.array_equal(adversary_image, adversary_image_solution) == True, "Adversary image is incorrect!" + +def test_construct_agent_image(): + agent_image = bomberman_state_encoding.construct_agent_image(agent=agent) + assert np.array_equal(agent_image, agent_image_solution) == True, "Adversary image is incorrect!" + +def test_construct_solids_image(): + solids_image = bomberman_state_encoding.construct_solids_image(walls=walls, crates=crates) + assert np.array_equal(solids_image, solids_image_solution) == True, "Adversary image is incorrect!" -print(state_vector) -print(len(state_vector)) \ No newline at end of file +# test_construct_full_state() +# test_construct_danger_image() +# test_construct_env_image() +# test_construct_adversary_image() +# test_construct_agent_image() +# test_construct_solids_image()