From b229325e090117095eaa871ae6bbbaf63e09fadc Mon Sep 17 00:00:00 2001 From: Vuk Djordjevic Date: Sat, 13 Jul 2024 12:40:30 +0200 Subject: [PATCH] Update regarding generated binaries option Moved asset folder to project directory. Changed the file paths to absolute file paths. Added icon file. Added scripts to generate binaries using pyinstaller. --- .gitignore | 1 + __init__.py | 0 {src/assets => assets}/bonuses/catapult.png | Bin .../assets => assets}/bonuses/hard_repair.png | Bin .../bonuses/light_repair.png | Bin {src/assets => assets}/explosion_images/0.png | Bin {src/assets => assets}/explosion_images/1.png | Bin {src/assets => assets}/explosion_images/2.png | Bin {src/assets => assets}/explosion_images/3.png | Bin {src/assets => assets}/explosion_images/4.png | Bin {src/assets => assets}/explosion_images/5.png | Bin {src/assets => assets}/explosion_images/6.png | Bin .../explosion_images/Empty.png | Bin {src/assets => assets}/flag.png | Bin .../hex_images/desert_empty.png | Bin .../hex_images/desert_obstacle.png | Bin .../hex_images/summer_empty.png | Bin .../hex_images/summer_obstacle.png | Bin .../hex_images/winter_empty.png | Bin .../hex_images/winter_obstacle.png | Bin {src/assets => assets}/icon.png | Bin .../menu/BrunoAceSC-Regular.ttf | Bin {src/assets => assets}/menu/background.jpg | Bin {src/assets => assets}/sounds/explosion.mp3 | Bin {src/assets => assets}/sounds/shot.mp3 | Bin {src/assets => assets}/tank_classes/ht.png | Bin {src/assets => assets}/tank_classes/lt.png | Bin {src/assets => assets}/tank_classes/mt.png | Bin {src/assets => assets}/tank_classes/spg.png | Bin {src/assets => assets}/tank_classes/td.png | Bin {src/assets => assets}/tank_icon.png | Bin {src/assets => assets}/tracks_green.png | Bin {src/assets => assets}/trophy.png | Bin {src/assets => assets}/white_bullet.png | Bin generate_binaries.bat | 17 +++++ generate_binaries.ps1 | 21 ++++++ icon.ico | Bin 0 -> 110475 bytes mab/data/data_io.py | 22 +++--- src/constants.py | 67 ++++++++++-------- 39 files changed, 90 insertions(+), 38 deletions(-) delete mode 100644 __init__.py rename {src/assets => assets}/bonuses/catapult.png (100%) rename {src/assets => assets}/bonuses/hard_repair.png (100%) rename {src/assets => assets}/bonuses/light_repair.png (100%) rename {src/assets => assets}/explosion_images/0.png (100%) rename {src/assets => assets}/explosion_images/1.png (100%) rename {src/assets => assets}/explosion_images/2.png (100%) rename {src/assets => assets}/explosion_images/3.png (100%) rename {src/assets => assets}/explosion_images/4.png (100%) rename {src/assets => assets}/explosion_images/5.png (100%) rename {src/assets => assets}/explosion_images/6.png (100%) rename {src/assets => assets}/explosion_images/Empty.png (100%) rename {src/assets => assets}/flag.png (100%) rename {src/assets => assets}/hex_images/desert_empty.png (100%) rename {src/assets => assets}/hex_images/desert_obstacle.png (100%) rename {src/assets => assets}/hex_images/summer_empty.png (100%) rename {src/assets => assets}/hex_images/summer_obstacle.png (100%) rename {src/assets => assets}/hex_images/winter_empty.png (100%) rename {src/assets => assets}/hex_images/winter_obstacle.png (100%) rename {src/assets => assets}/icon.png (100%) rename {src/assets => assets}/menu/BrunoAceSC-Regular.ttf (100%) rename {src/assets => assets}/menu/background.jpg (100%) rename {src/assets => assets}/sounds/explosion.mp3 (100%) rename {src/assets => assets}/sounds/shot.mp3 (100%) rename {src/assets => assets}/tank_classes/ht.png (100%) rename {src/assets => assets}/tank_classes/lt.png (100%) rename {src/assets => assets}/tank_classes/mt.png (100%) rename {src/assets => assets}/tank_classes/spg.png (100%) rename {src/assets => assets}/tank_classes/td.png (100%) rename {src/assets => assets}/tank_icon.png (100%) rename {src/assets => assets}/tracks_green.png (100%) rename {src/assets => assets}/trophy.png (100%) rename {src/assets => assets}/white_bullet.png (100%) create mode 100644 generate_binaries.bat create mode 100644 generate_binaries.ps1 create mode 100644 icon.ico diff --git a/.gitignore b/.gitignore index 1a1c1e4..31fd21e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ __pycache__/ # Distribution / packaging .Python +output/ build/ develop-eggs/ dist/ diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/assets/bonuses/catapult.png b/assets/bonuses/catapult.png similarity index 100% rename from src/assets/bonuses/catapult.png rename to assets/bonuses/catapult.png diff --git a/src/assets/bonuses/hard_repair.png b/assets/bonuses/hard_repair.png similarity index 100% rename from src/assets/bonuses/hard_repair.png rename to assets/bonuses/hard_repair.png diff --git a/src/assets/bonuses/light_repair.png b/assets/bonuses/light_repair.png similarity index 100% rename from src/assets/bonuses/light_repair.png rename to assets/bonuses/light_repair.png diff --git a/src/assets/explosion_images/0.png b/assets/explosion_images/0.png similarity index 100% rename from src/assets/explosion_images/0.png rename to assets/explosion_images/0.png diff --git a/src/assets/explosion_images/1.png b/assets/explosion_images/1.png similarity index 100% rename from src/assets/explosion_images/1.png rename to assets/explosion_images/1.png diff --git a/src/assets/explosion_images/2.png b/assets/explosion_images/2.png similarity index 100% rename from src/assets/explosion_images/2.png rename to assets/explosion_images/2.png diff --git a/src/assets/explosion_images/3.png b/assets/explosion_images/3.png similarity index 100% rename from src/assets/explosion_images/3.png rename to assets/explosion_images/3.png diff --git a/src/assets/explosion_images/4.png b/assets/explosion_images/4.png similarity index 100% rename from src/assets/explosion_images/4.png rename to assets/explosion_images/4.png diff --git a/src/assets/explosion_images/5.png b/assets/explosion_images/5.png similarity index 100% rename from src/assets/explosion_images/5.png rename to assets/explosion_images/5.png diff --git a/src/assets/explosion_images/6.png b/assets/explosion_images/6.png similarity index 100% rename from src/assets/explosion_images/6.png rename to assets/explosion_images/6.png diff --git a/src/assets/explosion_images/Empty.png b/assets/explosion_images/Empty.png similarity index 100% rename from src/assets/explosion_images/Empty.png rename to assets/explosion_images/Empty.png diff --git a/src/assets/flag.png b/assets/flag.png similarity index 100% rename from src/assets/flag.png rename to assets/flag.png diff --git a/src/assets/hex_images/desert_empty.png b/assets/hex_images/desert_empty.png similarity index 100% rename from src/assets/hex_images/desert_empty.png rename to assets/hex_images/desert_empty.png diff --git a/src/assets/hex_images/desert_obstacle.png b/assets/hex_images/desert_obstacle.png similarity index 100% rename from src/assets/hex_images/desert_obstacle.png rename to assets/hex_images/desert_obstacle.png diff --git a/src/assets/hex_images/summer_empty.png b/assets/hex_images/summer_empty.png similarity index 100% rename from src/assets/hex_images/summer_empty.png rename to assets/hex_images/summer_empty.png diff --git a/src/assets/hex_images/summer_obstacle.png b/assets/hex_images/summer_obstacle.png similarity index 100% rename from src/assets/hex_images/summer_obstacle.png rename to assets/hex_images/summer_obstacle.png diff --git a/src/assets/hex_images/winter_empty.png b/assets/hex_images/winter_empty.png similarity index 100% rename from src/assets/hex_images/winter_empty.png rename to assets/hex_images/winter_empty.png diff --git a/src/assets/hex_images/winter_obstacle.png b/assets/hex_images/winter_obstacle.png similarity index 100% rename from src/assets/hex_images/winter_obstacle.png rename to assets/hex_images/winter_obstacle.png diff --git a/src/assets/icon.png b/assets/icon.png similarity index 100% rename from src/assets/icon.png rename to assets/icon.png diff --git a/src/assets/menu/BrunoAceSC-Regular.ttf b/assets/menu/BrunoAceSC-Regular.ttf similarity index 100% rename from src/assets/menu/BrunoAceSC-Regular.ttf rename to assets/menu/BrunoAceSC-Regular.ttf diff --git a/src/assets/menu/background.jpg b/assets/menu/background.jpg similarity index 100% rename from src/assets/menu/background.jpg rename to assets/menu/background.jpg diff --git a/src/assets/sounds/explosion.mp3 b/assets/sounds/explosion.mp3 similarity index 100% rename from src/assets/sounds/explosion.mp3 rename to assets/sounds/explosion.mp3 diff --git a/src/assets/sounds/shot.mp3 b/assets/sounds/shot.mp3 similarity index 100% rename from src/assets/sounds/shot.mp3 rename to assets/sounds/shot.mp3 diff --git a/src/assets/tank_classes/ht.png b/assets/tank_classes/ht.png similarity index 100% rename from src/assets/tank_classes/ht.png rename to assets/tank_classes/ht.png diff --git a/src/assets/tank_classes/lt.png b/assets/tank_classes/lt.png similarity index 100% rename from src/assets/tank_classes/lt.png rename to assets/tank_classes/lt.png diff --git a/src/assets/tank_classes/mt.png b/assets/tank_classes/mt.png similarity index 100% rename from src/assets/tank_classes/mt.png rename to assets/tank_classes/mt.png diff --git a/src/assets/tank_classes/spg.png b/assets/tank_classes/spg.png similarity index 100% rename from src/assets/tank_classes/spg.png rename to assets/tank_classes/spg.png diff --git a/src/assets/tank_classes/td.png b/assets/tank_classes/td.png similarity index 100% rename from src/assets/tank_classes/td.png rename to assets/tank_classes/td.png diff --git a/src/assets/tank_icon.png b/assets/tank_icon.png similarity index 100% rename from src/assets/tank_icon.png rename to assets/tank_icon.png diff --git a/src/assets/tracks_green.png b/assets/tracks_green.png similarity index 100% rename from src/assets/tracks_green.png rename to assets/tracks_green.png diff --git a/src/assets/trophy.png b/assets/trophy.png similarity index 100% rename from src/assets/trophy.png rename to assets/trophy.png diff --git a/src/assets/white_bullet.png b/assets/white_bullet.png similarity index 100% rename from src/assets/white_bullet.png rename to assets/white_bullet.png diff --git a/generate_binaries.bat b/generate_binaries.bat new file mode 100644 index 0000000..d5a03be --- /dev/null +++ b/generate_binaries.bat @@ -0,0 +1,17 @@ +@echo off +REM Check if PowerShell script exists +if not exist generate_binaries.ps1 ( + echo generate_binaries.ps1 does not exist. + exit /b 1 +) + +REM Run the PowerShell script +powershell.exe -NoProfile -ExecutionPolicy Bypass -File generate_binaries.ps1 + +REM Check if the PowerShell script ran successfully +if %errorlevel% neq 0 ( + echo PowerShell script generate_binaries.ps1 failed. + exit /b 1 +) + +echo PowerShell script generate_binaries.ps1 ran successfully. diff --git a/generate_binaries.ps1 b/generate_binaries.ps1 new file mode 100644 index 0000000..73e09df --- /dev/null +++ b/generate_binaries.ps1 @@ -0,0 +1,21 @@ +# Display menu options +Write-Host "Select an option:" +Write-Host "1. Run command for One Directory" +Write-Host "2. Run command for One File" + +# Read user input +$userChoice = Read-Host "Enter your choice (1 or 2)" + +# Process user choice +switch ($userChoice) +{ + 1 { + pyinstaller --noconfirm --onedir --console --icon "C:\Users\xparh\OneDrive\Desktop\Team-Segfault\icon.ico" --name "team_segfault" --optimize "2" --add-data "C:\Users\xparh\OneDrive\Desktop\Team-Segfault\assets;assets/" --add-data "C:\Users\xparh\OneDrive\Desktop\Team-Segfault\mab\data\server_data;mab/data/server_data/" --add-data "C:\Users\xparh\OneDrive\Desktop\Team-Segfault\mab\data\training_data;mab/data/training_data/" "C:\Users\xparh\OneDrive\Desktop\Team-Segfault\main.py" + } + 2 { + pyinstaller --noconfirm --onefile --console --icon "C:\Users\xparh\OneDrive\Desktop\Team-Segfault\icon.ico" --name "team_segfault" --optimize "2" --add-data "C:\Users\xparh\OneDrive\Desktop\Team-Segfault\assets;assets/" --add-data "C:\Users\xparh\OneDrive\Desktop\Team-Segfault\mab\data\server_data;mab/data/server_data/" --add-data "C:\Users\xparh\OneDrive\Desktop\Team-Segfault\mab\data\training_data;mab/data/training_data/" "C:\Users\xparh\OneDrive\Desktop\Team-Segfault\main.py" + } + default { + Write-Host "Invalid choice. Please enter 1 or 2." + } +} diff --git a/icon.ico b/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..debd7833d0517f0ae447aac4ee4ba05247aaaaba GIT binary patch literal 110475 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 USr9G)z;ry1#j{#mK~VYr58PoEy#N3J literal 0 HcmV?d00001 diff --git a/mab/data/data_io.py b/mab/data/data_io.py index 9d34722..df93cc3 100644 --- a/mab/data/data_io.py +++ b/mab/data/data_io.py @@ -1,12 +1,15 @@ import json +import os from typing import Type class DataIO: - __training_data_path = "mab\\data\\training_data\\" + __script_path = os.path.dirname(__file__) - __client_map_path = "mab\\data\\server_data\\client_map" - __game_state_path = "mab\\data\\server_data\\game_state" + __training_data_path = os.path.join(__script_path, "training_data") + + __client_map_path = os.path.join(__script_path, "server_data/client_map") + __game_state_path = os.path.join(__script_path, "server_data/game_state") ResultsTable = Type[dict[int, dict[str, list[int]]]] @@ -66,25 +69,26 @@ def save_game_state(game_state: dict) -> None: @staticmethod def load_results_table(save_file: str) -> ResultsTable: - return DataIO.__load(DataIO.__training_data_path + save_file + '_results_table') + return DataIO.__load(DataIO.__training_data_path + '\\' + save_file + '_results_table') @staticmethod def load_num_games(save_file: str) -> int: - return DataIO.__load(DataIO.__training_data_path + save_file + '_num_games') + return DataIO.__load(DataIO.__training_data_path + '\\' + save_file + '_num_games') @staticmethod def load_best_actions(save_file: str) -> dict[int, str]: - return DataIO.__load(DataIO.__training_data_path + save_file + '_best_actions') + return DataIO.__load(DataIO.__training_data_path + '\\' + save_file + '_best_actions') @staticmethod - def load_client_map() -> dict: return DataIO.__load(DataIO.__client_map_path) + def load_client_map() -> dict: + return DataIO.__load(DataIO.__client_map_path) @staticmethod - def load_game_state() -> dict: return DataIO.__load(DataIO.__game_state_path) + def load_game_state() -> dict: + return DataIO.__load(DataIO.__game_state_path) @staticmethod def __load(from_where: str): with open(from_where + '.json', 'r') as file: what = json.load(file) return what - diff --git a/src/constants.py b/src/constants.py index 3cb4ee9..3e0296b 100644 --- a/src/constants.py +++ b/src/constants.py @@ -76,41 +76,50 @@ SOUND_VOLUME = [0.0] MAX_PLAYERS = 3 DEFAULT_NUM_TURNS = 45 + +import os + +# get the directory where the current script is located +SCRIPT_DIR = os.path.dirname(__file__) + +# define the base directory for the assets +ASSETS_LOCATION = os.path.join(SCRIPT_DIR, '../assets') + # sound paths -EXPLOSION_SOUND = 'src/assets/sounds/explosion.mp3' -BULLET_SOUND = 'src/assets/sounds/shot.mp3' +EXPLOSION_SOUND = os.path.join(ASSETS_LOCATION, 'sounds', 'explosion.mp3') +BULLET_SOUND = os.path.join(ASSETS_LOCATION, 'sounds', 'shot.mp3') -# font paths -MENU_FONT = 'src/assets/menu/BrunoAceSC-Regular.ttf' +# font path +MENU_FONT = os.path.join(ASSETS_LOCATION, 'menu', 'BrunoAceSC-Regular.ttf') # image paths -TANK_ICON_PATH = 'src/assets/tank_icon.png' -SPG_IMAGE_PATH = 'src/assets/tank_classes/spg.png' -HT_IMAGE_PATH = 'src/assets/tank_classes/ht.png' -LT_IMAGE_PATH = 'src/assets/tank_classes/lt.png' -MT_IMAGE_PATH = 'src/assets/tank_classes/mt.png' -TD_IMAGE_PATH = 'src/assets/tank_classes/td.png' - -CATAPULT_IMAGE_PATH = 'src/assets/bonuses/catapult.png' -LIGHT_REPAIR_IMAGE_PATH = 'src/assets/bonuses/light_repair.png' -HARD_REPAIR_IMAGE_PATH = 'src/assets/bonuses/hard_repair.png' - -FLAG_PATH = 'src/assets/flag.png' -EXPLOSION_IMAGES = [f'src/assets/explosion_images/{i}.png' for i in range(7)] -BULLET_IMAGE_PATH = 'src/assets/white_bullet.png' - -BACKGROUND_IMAGE_PATH = 'src/assets/menu/background.jpg' -GUI_ICON_PATH = 'src/assets/icon.png' -TRACKS_IMAGE_PATH = 'src/assets/tracks_green.png' -TROPHY_IMAGE_PATH = 'src/assets/trophy.png' +TANK_ICON_PATH = os.path.join(ASSETS_LOCATION, 'tank_icon.png') +SPG_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'tank_classes', 'spg.png') +HT_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'tank_classes', 'ht.png') +LT_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'tank_classes', 'lt.png') +MT_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'tank_classes', 'mt.png') +TD_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'tank_classes', 'td.png') + +CATAPULT_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'bonuses', 'catapult.png') +LIGHT_REPAIR_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'bonuses', 'light_repair.png') +HARD_REPAIR_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'bonuses', 'hard_repair.png') + +FLAG_PATH = os.path.join(ASSETS_LOCATION, 'flag.png') +EXPLOSION_IMAGES = [os.path.join(ASSETS_LOCATION, 'explosion_images', f'{i}.png') for i in range(7)] +BULLET_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'white_bullet.png') + +BACKGROUND_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'menu', 'background.jpg') +GUI_ICON_PATH = os.path.join(ASSETS_LOCATION, 'icon.png') +TRACKS_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'tracks_green.png') +TROPHY_IMAGE_PATH = os.path.join(ASSETS_LOCATION, 'trophy.png') # map hexes -SUMMER_GRASS_PATH = 'src/assets/hex_images/summer_empty.png' -SUMMER_OBSTACLE_PATH = 'src/assets/hex_images/summer_obstacle.png' -DESERT_EMPTY_PATH = 'src/assets/hex_images/desert_empty.png' -DESERT_OBSTACLE_PATH = 'src/assets/hex_images/desert_obstacle.png' -WINTER_EMPTY_PATH = 'src/assets/hex_images/winter_empty.png' -WINTER_OBSTACLE_PATH = 'src/assets/hex_images/winter_obstacle.png' +SUMMER_GRASS_PATH = os.path.join(ASSETS_LOCATION, 'hex_images', 'summer_empty.png') +SUMMER_OBSTACLE_PATH = os.path.join(ASSETS_LOCATION, 'hex_images', 'summer_obstacle.png') +DESERT_EMPTY_PATH = os.path.join(ASSETS_LOCATION, 'hex_images', 'desert_empty.png') +DESERT_OBSTACLE_PATH = os.path.join(ASSETS_LOCATION, 'hex_images', 'desert_obstacle.png') +WINTER_EMPTY_PATH = os.path.join(ASSETS_LOCATION, 'hex_images', 'winter_empty.png') +WINTER_OBSTACLE_PATH = os.path.join(ASSETS_LOCATION, 'hex_images', 'winter_obstacle.png') # other BULLET_VECTOR = (1, 0)