Compare commits

35 Commits

Author SHA1 Message Date
toucan_dev 8ce78103d0 🎨 code format 2026-07-26 15:38:04 +02:00
toucan_dev 5cffcba502 🐛 fix UI not propagated 2026-07-26 15:33:12 +02:00
toucan_dev 3d7a03fb2b list log levels in CLI 2026-07-26 15:26:45 +02:00
toucan_dev 7e26db26c7 ♻️ use entrypoint to load UI 2026-07-26 15:24:44 +02:00
toucan_dev 732afb65c5 test entrypoint class 2026-07-26 15:15:32 +02:00
toucan_dev 2c2e3b0597 entrypoint class 2026-07-26 15:15:23 +02:00
toucan_dev 181b928c25 🔧 define UI entrypoint 2026-07-26 14:46:22 +02: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
toucan_dev 464adfa338 🚚 mv builder tests 2026-07-17 21:52:31 +02:00
toucan_dev f571603866 🙈 ignore build folder 2026-07-17 21:46:49 +02:00
toucan_dev abb1631414 🎨 unused import 2026-07-17 21:44:19 +02:00
toucan_dev 9e7968b6b3 fix builder tests 2026-07-17 21:43:07 +02:00
toucan_dev 3d43f3ee66 ♻️ wip refactoring builder 2026-07-17 21:42:52 +02:00
toucan_dev 4583fcdea6 ♻️ refactoring mob utils 2026-07-17 21:14:32 +02:00
toucan_dev 73b918f2f1 🚧 wip refactoring mob 2026-07-17 21:13:12 +02:00
toucan_dev 1c26070798 🚧 wip refactoring mob 2026-07-17 20:58:29 +02:00
toucan_dev 35ec79e7e5 🚚 mv menu 2026-07-17 20:42:51 +02:00
toucan_dev 4cfa6b72ff 🔨 update formatter util 2026-07-17 20:37:37 +02:00
toucan_dev 0d41da6544 🎉 pyproject file 2026-07-17 20:37:37 +02:00
toucan_dev e8e6c02756 🎨 code format 2026-07-17 20:37:37 +02:00
toucan_dev f36c8f6b17 ♻️ update tests 2026-07-17 20:02:56 +02:00
toucan_dev 3bed4f9903 ♻️ update imports 2026-07-17 20:02:56 +02:00
toucan_dev 1f1b928fd7 🚚 mv scripts into src folder 2026-07-17 19:32:20 +02:00
toucan_dev 4a06728381 🙈 ignore egg-info files 2026-07-17 19:29:55 +02:00
toucan_dev bd55060b97 ♻️ refactor entrypoint 2026-07-17 19:29:03 +02:00
toucan_dev 32306f041a 📝 add changelog 2026-07-17 19:28:42 +02:00
27 changed files with 487 additions and 331 deletions
+2 -2
View File
@@ -52,5 +52,5 @@ __pycache__/
.spyproject/
.pydevproject
*.egg-info
build
+1
View File
@@ -0,0 +1 @@
# Changelog
-105
View File
@@ -1,105 +0,0 @@
import os
import sys
from enum import Enum
from base_mob import BaseMob
from character_builder import CharacterBuilder
from level import Level
class Action(Enum):
PIECE_SUIVANTE = (1, "Pièce suivante")
COMBAT = (2, "Combat")
FUIR = (3, "Fuir")
QUITTER = (4, "Quitter")
@property
def code(self):
return self.value[0]
@property
def libelle(self):
return self.value[1]
def clear_console() -> None:
os.system('cls' if os.name == 'nt' else 'clear')
def action_menu(actions_autorisees: list[Action] = None) -> Action:
"""Affiche le menu et retourne une action valide."""
actions_autorisees = list(Action) if actions_autorisees is None else actions_autorisees
while True:
print("\n------ Menu Action ------\n")
for action in actions_autorisees:
print(f"{action.libelle:<20} : {action.code}")
try:
choix = int(input("\nChoix : "))
clear_console()
for action in actions_autorisees:
if action.code == choix:
return action
print("Mauvais choix")
except ValueError:
clear_console()
print("Veuillez saisir un nombre.")
def play_room(room: list[BaseMob], level: Level) -> int:
if room is None:
print("\n ------ Pièce vide ------ \n")
return 1
for mob in room:
print(f"Un {mob.name} est devant toi !")
match action_menu([Action.COMBAT, Action.FUIR]):
case Action.COMBAT:
level.combat(mob, level.player)
if level.player.current_pv <= 0:
print("!!!!!!!!! Joueur mort !!!!!!!!!!")
sys.exit(0)
if mob.current_pv == 0:
print(f"Le {mob.name} est mort !!")
case Action.FUIR:
print("Tu fuis la pièce")
return 0
return 1
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]):
case Action.PIECE_SUIVANTE:
if level.current_room_index >= len(level.rooms):
print("fin du donjon !")
break
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} !")
def app(character_name: str) -> None:
loaded_character = CharacterBuilder.load_character(character_name)
if not loaded_character:
sys.exit(-1)
print(loaded_character)
level = Level(2, loaded_character)
print(f"Nombre de pièce dans le donjon : {len(level.rooms)}")
play_donjon(level)
# Exemple d'utilisation
if __name__ == "__main__":
app(character_name=sys.argv[1] if len(sys.argv) > 1 else "Jamin")
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

-105
View File
@@ -1,105 +0,0 @@
import importlib.util
import json
import os
import sys
from typing import Callable
from base_mob import BaseMob
class CharacterBuilder:
save_character_impl: Callable[[BaseMob], str]
load_character_impl: Callable[[str], None]
@classmethod
def build_character(cls):
"""Demande à l'utilisateur de saisir les attributs du personnage."""
print("Création d'un nouveau personnage :")
name = input("Nom du personnage : ")
max_pv = int(input("Points de vie maximum : "))
strength = int(input("Force : "))
protection = int(input("Protection : "))
speed = int(input("Vitesse : "))
mob_type = 0
return BaseMob(name, max_pv, strength, protection, speed, mob_type)
@classmethod
def save_character(cls, character: BaseMob) -> None:
"""Enregistre un personnage dans un fichier JSON."""
filename = cls.save_character_impl(character)
print(f"Personnage enregistré dans {filename}.")
@classmethod
def load_character(cls, name: str) -> BaseMob | None:
"""Charge un personnage à partir d'un fichier JSON."""
try:
return cls.load_character_impl(name)
except Exception as e:
return None
def save_character(character: BaseMob) -> str:
"""Enregistre un personnage dans un fichier JSON."""
character_data = {
"name": character.name,
"max_pv": character.max_pv,
"current_pv": character.current_pv,
"strength": character.strength,
"protection": character.protection,
"speed": character.speed,
"mob_type": character.mob_type
}
filename = character.name + ".json"
with open(filename, "w", encoding='UTF-8') as file:
json.dump(character_data, file, indent=4)
return filename
def load_character(name: str) -> BaseMob | None:
"""Charge un personnage à partir d'un fichier JSON."""
filename = name + ".json"
if not os.path.exists(filename):
print(f"Erreur : Le fichier {filename} n'existe pas.")
return None
try:
with open(filename, "r", encoding='UTF-8') as file:
character_data = json.load(file)
# Vérification des clés essentielles dans le JSON pour éviter les erreurs
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.")
return None
# Construction du personnage
return BaseMob(
name=character_data["name"],
max_pv=character_data["max_pv"],
strength=character_data["strength"],
protection=character_data["protection"],
speed=character_data["speed"],
mob_type=character_data["mob_type"]
)
except json.JSONDecodeError:
print(f"Erreur : Le fichier {filename} n'est pas un JSON valide.")
return None
pydantic = None
name = 'pydantic'
if name in sys.modules:
pydantic = sys.modules[name]
elif (spec := importlib.util.find_spec(name)) is not None:
pydantic = importlib.util.module_from_spec(spec)
sys.modules[name] = pydantic
spec.loader.exec_module(pydantic)
if pydantic and os.environ.get('ELIRON_BUILDER') == 'pydantic':
pydantic_character_builder = importlib.import_module('pydantic_character_builder')
CharacterBuilder.save_character_impl = pydantic_character_builder.save_character
CharacterBuilder.load_character_impl = pydantic_character_builder.load_character
else:
CharacterBuilder.save_character_impl = save_character
CharacterBuilder.load_character_impl = load_character
+2 -2
View File
@@ -1,2 +1,2 @@
isort $1
autopep8 -i --max-line-length=120 $1
isort src tests
autopep8 src tests
-30
View File
@@ -1,30 +0,0 @@
""" Class Level """
import random
import mobs_utils
class Level:
""" Class Level """
def __init__(self, difficulty, player):
""" Chargement du niveau """
print("Loading Level")
self.mobs_in_level = mobs_utils.generate_random_mob_list(random.randint(2, difficulty))
self.exit_level = True
self.player = player
self.rooms = mobs_utils.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")
def combat(self, mob, player):
while mob.current_pv > 0 and player.current_pv > 0:
if mob.speed > player.speed:
mob.perform_attack(player)
player.perform_attack(mob)
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")
-26
View File
@@ -1,26 +0,0 @@
# def main_loop(breaker:bool):
# pass
# def menu ():
# print("Nouvelle partie :\t1")
# print("Charger :\t\t2")
# print("Option :\t\t3")
# print("Quitter :\t\t4")
# return int(input("Choix : "))
# choix = menu()
# match choix:
# case 1:
# print("Nouvelle partie")
# case 2:
# print("Charger")
# case 3:
# print("Option")
# case 4:
# print("Quitter")
# case _:
# print("Mauvais choix")
-49
View File
@@ -1,49 +0,0 @@
import random
from base_mob import BaseMob
# Créer des instances de BaseMob
yanaar = BaseMob("Yanaar", 15, 2, 1, 3, 2)
ulnarain = BaseMob("Ulnarain", 20, 3, 3, 2, 2)
skroll = BaseMob("Skroll", 25, 5, 3, 1, 2)
# Liste d'instances de BaseMob (au lieu d'un ensemble pour autoriser des doublons)
mobs_list = [yanaar, skroll, ulnarain]
def generate_random_mob_list(max_mobs):
"""
Génère une liste aléatoire de mobs à partir de la liste des instances disponibles.
:param max_mobs: Le nombre maximum de mobs dans la liste générée.
:return: Une liste de mobs sélectionnés aléatoirement.
"""
if max_mobs <= 0:
return []
num_mobs = random.randint(2, max_mobs)
selected_mobs = [random.choice(mobs_list) for _ in range(num_mobs)]
return selected_mobs
def generate_random_rooms(mobs_in_level, num_rooms):
"""
Génère un nombre spécifié de pièces et y distribue les mobs disponibles.
:param mobs_in_level: Liste des mobs disponibles pour le niveau.
:param num_rooms: Nombre total de pièces à générer.
:return: Une liste de pièces, chaque pièce contenant un ou plusieurs mobs, ou étant vide si aucun mob n'est disponible.
"""
rooms = []
for _ in range(num_rooms):
if len(mobs_in_level) > 0:
# Si des mobs sont disponibles, ajouter le premier mob à la pièce
new_room = []
for x in range(random.randint(1, len(mobs_in_level))):
new_room.append(mobs_in_level.pop(0))
rooms.append(new_room)
else:
# Ajouter une pièce vide si aucun mob n'est disponible
rooms.append(None)
return rooms
+44
View File
@@ -0,0 +1,44 @@
[project]
name = "elironwars-python"
version = "0.0.0"
description = "Lovely Spam! Wonderful Spam!"
readme = "README.md"
keywords = []
requires-python = ">= 3.14"
dependencies = [
"pydantic >= 2.13.4",
]
authors = [
{ name = "Raggaroth", email = "b.baudouin@pm.me" },
{ name = "Toucan", email = "anthony.melin@laposte.net" },
]
maintainers = [
{ name = "Raggaroth", email = "b.baudouin@pm.me" }
]
[project.urls]
Homepage = "https://gitea.raggaroth-factory.fr/public/elironwars-python"
Documentation = "https://gitea.raggaroth-factory.fr/public/elironwars-python/wiki"
Repository = "https://gitea.raggaroth-factory.fr/public/elironwars-python.git"
Issues = "https://gitea.raggaroth-factory.fr/public/elironwars-python/issues"
Changelog = "https://github.com/me/spam/blob/master/CHANGELOG.md"
[build-system]
requires = ["setuptools >= 77.0.3"]
build-backend = "setuptools.build_meta"
[project.scripts]
elironwars = "elironwars.app:app"
[project.entry-points."elironwars.ui"]
console = "elironwars.console:ConsoleUi"
[tool.isort]
profile = "black"
src_paths = ["src", "tests"]
known_first_party = ["elironwars"]
[tool.autopep8]
max_line_length = 120
in-place = true
recursive = true
View File
+101
View File
@@ -0,0 +1,101 @@
import argparse
import logging
import os
import sys
from typing import Any
from .entrypoints import Entrypoints
from .level import Level
from .menu import Action
from .mob import BaseMob, load_character
logger = logging.getLogger(__name__)
# FIXME replace this global declaration
UI: Any = None
def play_room(room: list[BaseMob], level: Level) -> int:
if room is None:
logger.info('Empty room')
UI.empty_room()
return 1
for mob in room:
logger.info('Meet mob %s', mob.name)
UI.meet_mob(mob)
match UI.action_menu([Action.COMBAT, Action.FUIR]):
case Action.COMBAT:
pvs = level.combat(mob, level.player)
UI.fight_pvs(level.player, mob, pvs)
if level.player.current_pv <= 0:
UI.player_dead()
sys.exit(0)
if mob.current_pv == 0:
UI.mob_dead(mob)
case Action.FUIR:
UI.run_away()
return 0
return 1
def play_donjon(level: Level) -> None:
while level.exit_level:
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):
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
logger.info('Leaving game')
UI.leave(level.player)
def app() -> None:
entrypoints = Entrypoints()
parser = argparse.ArgumentParser(
prog='elironwars',
description='elironwars CLI',
)
parser.add_argument('--player', default='Jamin')
parser.add_argument('--ui', default='console', choices=entrypoints.ui.names)
parser.add_argument('--log-level', default='ERROR', choices=logging.getLevelNamesMapping().keys())
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)
global UI
UI = entrypoints.load_ui(args.ui)
UI.select_player(loaded_character)
# Créer des instances de BaseMob
yanaar = BaseMob("Yanaar", 15, 2, 1, 3, 2)
ulnarain = BaseMob("Ulnarain", 20, 3, 3, 2, 2)
skroll = BaseMob("Skroll", 25, 5, 3, 1, 2)
# Liste d'instances de BaseMob (au lieu d'un ensemble pour autoriser des doublons)
mobs_list = [yanaar, skroll, ulnarain]
level = Level(2, loaded_character, mobs_list)
UI.entering_donjon(level)
play_donjon(level)
# Exemple d'utilisation
if __name__ == "__main__":
app()
+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()
+18
View File
@@ -0,0 +1,18 @@
import logging
from importlib.metadata import entry_points
logger = logging.getLogger(__name__)
class Entrypoints:
def __init__(self):
self.ui = entry_points(group='elironwars.ui')
def load_ui(self, ui):
logger.info('Loading ui %s', ui)
try:
ui_class = self.ui[ui].load()
return ui_class()
except KeyError:
logger.critical('Unable to load ui %s', ui)
+35
View File
@@ -0,0 +1,35 @@
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 """
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
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)
player.perform_attack(mob)
else:
player.perform_attack(mob)
mob.perform_attack(player)
pvs.append({
'player': player.current_pv,
'mob': mob.current_pv
})
return pvs
+55
View File
@@ -0,0 +1,55 @@
import logging
import os
from enum import Enum
logger = logging.getLogger(__name__)
class Action(Enum):
PIECE_SUIVANTE = (1, "Pièce suivante")
COMBAT = (2, "Combat")
FUIR = (3, "Fuir")
QUITTER = (4, "Quitter")
@property
def code(self):
return self.value[0]
@property
def libelle(self):
return self.value[1]
def clear_console() -> None:
os.system('cls' if os.name == 'nt' else 'clear')
def action_menu(actions_autorisees: list[Action] = None) -> Action:
"""Affiche le menu et retourne une action valide."""
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")
for action in actions_autorisees:
print(f"{action.libelle:<20} : {action.code}")
try:
choix = int(input("\nChoix : "))
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')
+19
View File
@@ -0,0 +1,19 @@
import importlib.util
import os
import sys
from .base_mob import BaseMob
pydantic = None
name = 'pydantic'
if name in sys.modules:
pydantic = sys.modules[name]
elif (spec := importlib.util.find_spec(name)) is not None:
pydantic = importlib.util.module_from_spec(spec)
sys.modules[name] = pydantic
spec.loader.exec_module(pydantic)
if pydantic and os.environ.get('ELIRON_BUILDER') == 'pydantic':
from .pydantic_builder import load_character, save_character
else:
from .default_builder import load_character, save_character
@@ -62,4 +62,4 @@ class BaseMob:
"""Retourne une représentation sous forme de chaîne du mob."""
return (f"{self.name} - PV: {self.current_pv}/{self.max_pv}, "
f"Force: {self.strength}, Protection: {self.protection}, "
f"Vitesse: {self.speed}")
f"Vitesse: {self.speed}")
+69
View File
@@ -0,0 +1,69 @@
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."""
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 : "))
protection = int(input("Protection : "))
speed = int(input("Vitesse : "))
mob_type = 0
return BaseMob(name, max_pv, strength, protection, speed, mob_type)
def save_character(character: BaseMob) -> str:
"""Enregistre un personnage dans un fichier JSON."""
character_data = {
"name": character.name,
"max_pv": character.max_pv,
"current_pv": character.current_pv,
"strength": character.strength,
"protection": character.protection,
"speed": character.speed,
"mob_type": character.mob_type
}
filename = character.name + ".json"
with open(filename, "w", encoding='UTF-8') as file:
json.dump(character_data, file, indent=4)
return filename
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):
logger.error(f"Erreur : Le fichier {filename} n'existe pas.")
return None
try:
with open(filename, "r", encoding='UTF-8') as file:
character_data = json.load(file)
# Vérification des clés essentielles dans le JSON pour éviter les erreurs
required_keys = ["name", "max_pv", "current_pv",
"strength", "protection", "speed", "mob_type"]
if not all(key in character_data for key in required_keys):
logger.error(f"Erreur : Le fichier {filename} ne contient pas toutes les clés nécessaires.")
return None
# Construction du personnage
return BaseMob(
name=character_data["name"],
max_pv=character_data["max_pv"],
strength=character_data["strength"],
protection=character_data["protection"],
speed=character_data["speed"],
mob_type=character_data["mob_type"]
)
except json.JSONDecodeError:
logger.error(f"Erreur : Le fichier {filename} n'est pas un JSON valide.")
return None
@@ -2,7 +2,7 @@ import pathlib
from pydantic import BaseModel
from base_mob import BaseMob
from .base_mob import BaseMob
class CharacterModel(BaseModel):
+41
View File
@@ -0,0 +1,41 @@
import random
def generate_random_mob_list(mob_list, max_mobs):
"""
Génère une liste aléatoire de mobs à partir de la liste fournie.
:param mob_list: Liste de mob a choisir aleatoirement.
:param max_mobs: Le nombre maximum de mobs dans la liste générée.
:return: Une liste de mobs sélectionnés aléatoirement.
"""
if max_mobs <= 0:
return []
num_mobs = random.randint(2, max_mobs)
selected_mobs = [random.choice(mob_list) for _ in range(num_mobs)]
return selected_mobs
def generate_random_rooms(mobs_in_level, num_rooms):
"""
Génère un nombre spécifié de pièces et y distribue les mobs disponibles.
:param mobs_in_level: Liste des mobs disponibles pour le niveau.
:param num_rooms: Nombre total de pièces à générer.
:return: Une liste de pièces, chaque pièce contenant un ou plusieurs mobs, ou étant vide si aucun mob n'est disponible.
"""
rooms = []
for _ in range(num_rooms):
if len(mobs_in_level) > 0:
# Si des mobs sont disponibles, ajouter le premier mob à la pièce
new_room = []
for x in range(random.randint(1, len(mobs_in_level))):
new_room.append(mobs_in_level.pop(0))
rooms.append(new_room)
else:
# Ajouter une pièce vide si aucun mob n'est disponible
rooms.append(None)
return rooms
+3
View File
@@ -0,0 +1,3 @@
import logging
logging.basicConfig(level=logging.DEBUG)
@@ -1,10 +1,10 @@
import unittest
from unittest.mock import patch
import json
import pathlib
import unittest
from unittest.mock import patch
from base_mob import BaseMob
from character_builder import CharacterBuilder
from elironwars.mob import BaseMob, load_character, save_character
from elironwars.mob.default_builder import build_character
ARTHUR_JSON = """{
"name": "Arthur",
@@ -37,7 +37,7 @@ class TestCharacterBuilder(unittest.TestCase):
]
# Act
character = CharacterBuilder.build_character()
character = build_character()
# Assert
self.assertIsInstance(character, BaseMob)
@@ -60,7 +60,7 @@ class TestCharacterBuilder(unittest.TestCase):
)
# Act
CharacterBuilder.save_character(character)
save_character(character)
# Assert
self.assertTrue(ARTHUR_FILE.exists())
@@ -68,7 +68,7 @@ class TestCharacterBuilder(unittest.TestCase):
def test_load_character_file_not_found(self):
# Act
result = CharacterBuilder.load_character("Lancelot")
result = load_character("Lancelot")
# Assert
self.assertIsNone(result)
@@ -78,7 +78,7 @@ class TestCharacterBuilder(unittest.TestCase):
ARTHUR_FILE.write_text(ARTHUR_JSON, encoding='utf-8')
# Act
character = CharacterBuilder.load_character("Arthur")
character = load_character("Arthur")
# Assert
self.assertIsNotNone(character)
@@ -101,7 +101,7 @@ class TestCharacterBuilder(unittest.TestCase):
invalid_dict), encoding='utf-8')
# Act
result = CharacterBuilder.load_character("Arthur")
result = load_character("Arthur")
# Assert
self.assertIsNone(result)
@@ -111,7 +111,7 @@ class TestCharacterBuilder(unittest.TestCase):
ARTHUR_FILE.write_text(ARTHUR_JSON[1:], encoding='utf-8')
# Act
result = CharacterBuilder.load_character("Arthur")
result = load_character("Arthur")
# Assert
self.assertIsNone(result)
+25
View File
@@ -0,0 +1,25 @@
import unittest
from elironwars.console import ConsoleUi
from elironwars.entrypoints import Entrypoints
class TestEntrypoints(unittest.TestCase):
def test_load_console_ui(self):
console_ep = 'console'
ep = Entrypoints()
self.assertIn(console_ep, ep.ui.names)
self.assertIsInstance(ep.load_ui(console_ep), ConsoleUi)
def test_load_unknown_ui(self):
unknown_ep = 'unknown'
ep = Entrypoints()
self.assertNotIn(unknown_ep, ep.ui.names)
self.assertIsNone(ep.load_ui(unknown_ep), ConsoleUi)
if __name__ == "__main__":
unittest.main()