Compare commits

11 Commits

Author SHA1 Message Date
bbaudouin e682607eac Merge pull request ' cli & console output' (#4) from ux into develop
Reviewed-on: #4
2026-07-22 07:57:32 +01:00
bbaudouin 583a026dc4 ajout d'images pour les ennemise 2026-07-21 21:27:23 +02:00
toucan_dev 9efdc27332 cli with argparse 2026-07-19 18:42:07 +02:00
toucan_dev 33052979f0 ♻️ use console ui 2026-07-19 17:48:09 +02:00
toucan_dev fe5b5890b2 console ui 2026-07-19 17:47:49 +02:00
toucan_dev d02b48b2b0 🔊 add some logs 2026-07-19 00:50:29 +02:00
toucan_dev 3746f32cd0 🔊 log config for app 2026-07-19 00:14:32 +02:00
toucan_dev b7daf32569 🔊 replace print by logger 2026-07-19 00:14:18 +02:00
toucan_dev e5eb96623f 🎨 code format 2026-07-19 00:00:58 +02:00
toucan_dev df93b8a587 🔊 log config for tests 2026-07-18 23:15:58 +02:00
bbaudouin acd443072e Merge pull request '🏗️ ♻️ restructuration du projet et refactoring' (#3) from toucan into develop
Reviewed-on: public/elironwars-python#3
2026-07-18 06:33:34 +01:00
11 changed files with 134 additions and 24 deletions
Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

+40 -15
View File
@@ -1,27 +1,36 @@
import argparse
import logging
import os
import sys
from .console import UI
from .level import Level
from .menu import Action, action_menu
from .menu import Action
from .mob import BaseMob, load_character
logger = logging.getLogger(__name__)
def play_room(room: list[BaseMob], level: Level) -> int:
if room is None:
print("\n ------ Pièce vide ------ \n")
logger.info('Empty room')
UI.empty_room()
return 1
for mob in room:
print(f"Un {mob.name} est devant toi !")
match action_menu([Action.COMBAT, Action.FUIR]):
logger.info('Meet mob %s', mob.name)
UI.meet_mob(mob)
match UI.action_menu([Action.COMBAT, Action.FUIR]):
case Action.COMBAT:
level.combat(mob, level.player)
pvs = level.combat(mob, level.player)
UI.fight_pvs(level.player, mob, pvs)
if level.player.current_pv <= 0:
print("!!!!!!!!! Joueur mort !!!!!!!!!!")
UI.player_dead()
sys.exit(0)
if mob.current_pv == 0:
print(f"Le {mob.name} est mort !!")
UI.mob_dead(mob)
case Action.FUIR:
print("Tu fuis la pièce")
UI.run_away()
return 0
return 1
@@ -29,25 +38,41 @@ def play_room(room: list[BaseMob], level: Level) -> int:
def play_donjon(level: Level) -> None:
while level.exit_level:
print(f"Pièce actuelle : {level.current_room_index}")
match action_menu([Action.PIECE_SUIVANTE, Action.QUITTER]):
UI.entering_room(level.current_room_index)
match UI.action_menu([Action.PIECE_SUIVANTE, Action.QUITTER]):
case Action.PIECE_SUIVANTE:
if level.current_room_index >= len(level.rooms):
print("fin du donjon !")
logger.info('Exiting last room')
UI.last_room()
break
logger.info('Entering next room')
level.current_room_index += play_room(level.rooms[level.current_room_index], level)
level.player.current_pv = level.player.max_pv
case Action.QUITTER:
level.exit_level = False
print(f"Au revoir {level.player.name} !")
logger.info('Leaving game')
UI.leave(level.player)
def app() -> None:
loaded_character = load_character(sys.argv[1] if len(sys.argv) > 1 else "Jamin")
parser = argparse.ArgumentParser(
prog='elironwars',
description='elironwars CLI',
)
parser.add_argument('--player', default='Jamin')
parser.add_argument('--ui', default='cli')
parser.add_argument('--log-level', default='ERROR')
args = parser.parse_args()
os.makedirs('logs', exist_ok=True)
logging.basicConfig(filename='logs/app.log', level=logging.getLevelName(args.log_level))
logging.info('start')
loaded_character = load_character(args.player)
if not loaded_character:
sys.exit(-1)
print(loaded_character)
UI.select_player(loaded_character)
# Créer des instances de BaseMob
yanaar = BaseMob("Yanaar", 15, 2, 1, 3, 2)
@@ -58,7 +83,7 @@ def app() -> None:
mobs_list = [yanaar, skroll, ulnarain]
level = Level(2, loaded_character, mobs_list)
print(f"Nombre de pièce dans le donjon : {len(level.rooms)}")
UI.entering_donjon(level)
play_donjon(level)
+60
View File
@@ -0,0 +1,60 @@
from .menu import Action, action_menu
class ConsoleUi:
def __init__(self):
pass
@staticmethod
def empty_room():
print("\n ------ Pièce vide ------ \n")
@staticmethod
def meet_mob(mob):
print(f"Un {mob.name} est devant toi !")
@staticmethod
def player_dead():
print("!!!!!!!!! Joueur mort !!!!!!!!!!")
@staticmethod
def mob_dead(mob):
print(f"Le {mob.name} est mort !!")
@staticmethod
def run_away():
print("Tu fuis la pièce")
@staticmethod
def leave(player):
print(f"Au revoir {player.name} !")
@staticmethod
def select_player(player):
print(player)
@staticmethod
def entering_room(room_name):
print(f"Pièce actuelle : {room_name}")
@staticmethod
def last_room():
print("fin du donjon !")
@staticmethod
def entering_donjon(level):
print(f"Nombre de pièce dans le donjon : {len(level.rooms)}")
@staticmethod
def action_menu(actions_autorisees: list[Action] = None) -> Action:
return action_menu(actions_autorisees)
@staticmethod
def fight_pvs(player, mob, pvs):
for pv in pvs:
print(f"{player.name} - {pv['player']} PV")
print(f"{mob.name} - {pv['mob']} PV")
UI = ConsoleUi()
+12 -4
View File
@@ -1,21 +1,26 @@
import logging
from .random_utils import generate_random_mob_list, generate_random_rooms
logger = logging.getLogger(__name__)
class Level:
""" Class Level """
def __init__(self, difficulty, player, mob_list):
""" Chargement du niveau """
print("Loading Level")
logger.debug("Loading Level")
self.mobs_in_level = generate_random_mob_list(mob_list, difficulty)
self.exit_level = True
self.player = player
self.rooms = generate_random_rooms(self.mobs_in_level, difficulty) # Liste des pièces du niveau
self.current_room_index = 0 # Index de la pièce actuelle
print("Level Loaded")
logger.debug("Level Loaded")
def combat(self, mob, player):
pvs = []
while mob.current_pv > 0 and player.current_pv > 0:
if mob.speed > player.speed:
mob.perform_attack(player)
@@ -23,5 +28,8 @@ class Level:
else:
player.perform_attack(mob)
mob.perform_attack(player)
print(f"{player.name} - {player.current_pv} PV")
print(f"{mob.name} - {mob.current_pv} PV")
pvs.append({
'player': player.current_pv,
'mob': mob.current_pv
})
return pvs
+10
View File
@@ -1,6 +1,9 @@
import logging
import os
from enum import Enum
logger = logging.getLogger(__name__)
class Action(Enum):
PIECE_SUIVANTE = (1, "Pièce suivante")
@@ -26,6 +29,10 @@ def action_menu(actions_autorisees: list[Action] = None) -> Action:
actions_autorisees = list(Action) if actions_autorisees is None else actions_autorisees
logger.debug('Show action menu')
for action in actions_autorisees:
logger.debug('Action %s - "%s"', action.code, action.libelle)
while True:
print("\n------ Menu Action ------\n")
@@ -37,9 +44,12 @@ def action_menu(actions_autorisees: list[Action] = None) -> Action:
clear_console()
for action in actions_autorisees:
if action.code == choix:
logger.info('User selected action %s - "%s"', action.code, action.libelle)
return action
print("Mauvais choix")
except ValueError:
clear_console()
print("Veuillez saisir un nombre.")
logger.info('Bad input')
+8 -4
View File
@@ -1,12 +1,15 @@
import json
import logging
import os
from .base_mob import BaseMob
logger = logging.getLogger(__name__)
def build_character():
"""Demande à l'utilisateur de saisir les attributs du personnage."""
print("Création d'un nouveau personnage :")
logger.debug("Création d'un nouveau personnage :")
name = input("Nom du personnage : ")
max_pv = int(input("Points de vie maximum : "))
strength = int(input("Force : "))
@@ -35,9 +38,10 @@ def save_character(character: BaseMob) -> str:
def load_character(name: str) -> BaseMob | None:
"""Charge un personnage à partir d'un fichier JSON."""
logger.debug('Loading character %s', name)
filename = name + ".json"
if not os.path.exists(filename):
print(f"Erreur : Le fichier {filename} n'existe pas.")
logger.error(f"Erreur : Le fichier {filename} n'existe pas.")
return None
try:
@@ -48,7 +52,7 @@ def load_character(name: str) -> BaseMob | None:
required_keys = ["name", "max_pv", "current_pv",
"strength", "protection", "speed", "mob_type"]
if not all(key in character_data for key in required_keys):
print(f"Erreur : Le fichier {filename} ne contient pas toutes les clés nécessaires.")
logger.error(f"Erreur : Le fichier {filename} ne contient pas toutes les clés nécessaires.")
return None
# Construction du personnage
@@ -61,5 +65,5 @@ def load_character(name: str) -> BaseMob | None:
mob_type=character_data["mob_type"]
)
except json.JSONDecodeError:
print(f"Erreur : Le fichier {filename} n'est pas un JSON valide.")
logger.error(f"Erreur : Le fichier {filename} n'est pas un JSON valide.")
return None
+3
View File
@@ -0,0 +1,3 @@
import logging
logging.basicConfig(level=logging.DEBUG)
+1 -1
View File
@@ -3,7 +3,7 @@ import pathlib
import unittest
from unittest.mock import patch
from elironwars.mob import BaseMob, save_character, load_character
from elironwars.mob import BaseMob, load_character, save_character
from elironwars.mob.default_builder import build_character
ARTHUR_JSON = """{