Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,39 +1,37 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import numpy as np
|
| 3 |
import os
|
| 4 |
-
import time
|
| 5 |
|
| 6 |
# Bibliothèques d'IA et de RL
|
| 7 |
-
# **IMPORTANT:** Assurez-vous que gymnasium est importé ici
|
| 8 |
import gymnasium as gym
|
| 9 |
from gymnasium import register, spaces
|
| 10 |
from stable_baselines3 import PPO
|
| 11 |
from huggingface_hub import hf_hub_download
|
| 12 |
|
| 13 |
# --- PARAMÈTRES DU DÉPÔT HUGGING FACE ---
|
| 14 |
-
|
|
|
|
| 15 |
MODEL_FILE = "mirobot_final_model.zip"
|
| 16 |
ENV_SCRIPT_FILE = "MiRobotEnv.py"
|
| 17 |
ENV_ID = 'MiRobot-v0'
|
| 18 |
|
| 19 |
# --- CONSTANTES DE JEU ---
|
| 20 |
GRID_SIZE = 10
|
| 21 |
-
|
| 22 |
-
MAX_FAIM = 1.0
|
| 23 |
-
FAIM_PENALTY_THRESHOLD = 0.9 # 90% de faim = Défaite
|
| 24 |
INITIAL_LEVEL = 1
|
| 25 |
|
| 26 |
-
# ---
|
|
|
|
| 27 |
CMD_AVANCER = 0
|
| 28 |
CMD_TOURNER = 1
|
| 29 |
ETAT_FAIM = 2
|
| 30 |
ETAT_SOMMEIL = 3
|
| 31 |
ETAT_HUMEUR = 4
|
| 32 |
|
| 33 |
-
# Map des actions du modèle
|
| 34 |
ACTION_MAP_MODEL = {0: "S'Arrêter", 1: "Avancer", 2: "Tourner G", 3: "Tourner D"}
|
| 35 |
|
| 36 |
-
# Map des commandes utilisateur aux ID d'action du modèle
|
| 37 |
ACTION_MAP_USER = {
|
| 38 |
"AVANCER": 1,
|
| 39 |
"TOURNER À GAUCHE": 2,
|
|
@@ -41,7 +39,7 @@ ACTION_MAP_USER = {
|
|
| 41 |
}
|
| 42 |
|
| 43 |
# ----------------------------------------------------------------------
|
| 44 |
-
# 1. PRÉPARATION DU MODÈLE ET DE L'ENVIRONNEMENT (CORRECTION
|
| 45 |
# ----------------------------------------------------------------------
|
| 46 |
|
| 47 |
model = None
|
|
@@ -60,22 +58,16 @@ try:
|
|
| 60 |
env_path = hf_hub_download(repo_id=REPO_ID, filename=ENV_SCRIPT_FILE, local_dir=TEMP_DIR)
|
| 61 |
|
| 62 |
# INJECTION DE DÉPENDANCES pour que MiRobotEnv.py fonctionne
|
| 63 |
-
env_globals = {
|
| 64 |
-
'gym': gym,
|
| 65 |
-
'np': np,
|
| 66 |
-
'spaces': spaces
|
| 67 |
-
}
|
| 68 |
|
| 69 |
with open(env_path, 'r') as f:
|
| 70 |
exec(f.read(), env_globals)
|
| 71 |
|
| 72 |
-
# Récupérer la classe MiRobotEnv
|
| 73 |
MiRobotEnv = env_globals['MiRobotEnv']
|
| 74 |
print("Classe MiRobotEnv définie avec succès.")
|
| 75 |
|
| 76 |
|
| 77 |
# --- 2. Enregistrement de l'environnement Custom ---
|
| 78 |
-
# On passe la classe elle-même à entry_point
|
| 79 |
register(
|
| 80 |
id=ENV_ID,
|
| 81 |
entry_point=MiRobotEnv,
|
|
@@ -88,7 +80,7 @@ try:
|
|
| 88 |
model = PPO.load(model_path)
|
| 89 |
|
| 90 |
env = gym.make(ENV_ID)
|
| 91 |
-
env.reset() # Initialise l'état interne
|
| 92 |
|
| 93 |
# Lecture des états initiaux pour l'interface Gradio (Utilisation sûre)
|
| 94 |
initial_faim = env.state[ETAT_FAIM] * 100
|
|
@@ -98,19 +90,17 @@ try:
|
|
| 98 |
|
| 99 |
except Exception as e:
|
| 100 |
print(f"❌ ERREUR CRITIQUE lors du chargement de MiRobot: {e}")
|
| 101 |
-
#
|
| 102 |
|
| 103 |
# ----------------------------------------------------------------------
|
| 104 |
# 2. LOGIQUE DU JEU
|
| 105 |
# ----------------------------------------------------------------------
|
| 106 |
|
| 107 |
-
# L'état initial du jeu
|
| 108 |
game_state_initial = {
|
| 109 |
'level': INITIAL_LEVEL,
|
| 110 |
'puppy_pos': [GRID_SIZE // 2, GRID_SIZE // 2],
|
| 111 |
'reward_pos': [0, 0],
|
| 112 |
-
'last_command': 'S_ARRETER',
|
| 113 |
-
'last_action_id': 0,
|
| 114 |
'message': 'Bienvenue ! Téléchargez une récompense et commencez !',
|
| 115 |
'reward_asset_path': None
|
| 116 |
}
|
|
@@ -121,9 +111,7 @@ def _reset_game(reward_path):
|
|
| 121 |
new_state = game_state_initial.copy()
|
| 122 |
|
| 123 |
if env is not None:
|
| 124 |
-
obs, info = env.reset() #
|
| 125 |
-
|
| 126 |
-
# Mettre à jour les valeurs de sortie après reset
|
| 127 |
faim_display = env.state[ETAT_FAIM] * 100
|
| 128 |
humeur_display = env.state[ETAT_HUMEUR]
|
| 129 |
else:
|
|
@@ -137,40 +125,32 @@ def _reset_game(reward_path):
|
|
| 137 |
|
| 138 |
return new_state, new_state['puppy_pos'][0], new_state['puppy_pos'][1], new_state['reward_pos'][0], new_state['reward_pos'][1], faim_display, humeur_display, new_state['message']
|
| 139 |
|
| 140 |
-
def _get_faim_humeur():
|
| 141 |
-
"""Récupère le niveau de faim et d'humeur actuel du chiot."""
|
| 142 |
-
if env is None or env.state is None:
|
| 143 |
-
return 0.0, 0.0
|
| 144 |
-
return env.state[ETAT_FAIM], env.state[ETAT_HUMEUR]
|
| 145 |
-
|
| 146 |
def handle_user_command(current_state, command_text, reward_path):
|
| 147 |
-
"""
|
| 148 |
-
Fonction principale appelée par Gradio pour gérer une commande utilisateur.
|
| 149 |
-
"""
|
| 150 |
game_state = current_state
|
| 151 |
|
| 152 |
if model is None or env is None:
|
|
|
|
| 153 |
return game_state, command_text, 5, 5, 0, 0, '❌ Erreur: Le modèle MiRobot n\'a pas pu être chargé !'
|
| 154 |
|
| 155 |
game_state['reward_asset_path'] = reward_path
|
| 156 |
|
| 157 |
# 2. Vérification de la faim (condition de défaite)
|
| 158 |
-
faim_actuelle
|
| 159 |
if faim_actuelle >= FAIM_PENALTY_THRESHOLD:
|
| 160 |
game_state['message'] = f'💔 Défaite ! MiRobot a trop faim ({faim_actuelle:.0%}) et ne peut plus obéir. Jeu réinitialisé au Niveau 1.'
|
| 161 |
return _reset_game(reward_path)
|
| 162 |
|
| 163 |
-
|
| 164 |
# 3. Traitement de la commande utilisateur
|
| 165 |
command_upper = command_text.upper()
|
| 166 |
|
| 167 |
if command_upper not in ACTION_MAP_USER:
|
| 168 |
-
game_state['message'] = f"🤔 MiRobot n'a pas compris l'ordre '{command_text}'.
|
| 169 |
|
|
|
|
| 170 |
env.state[CMD_AVANCER] = 0.0
|
| 171 |
env.state[CMD_TOURNER] = 0.0
|
| 172 |
new_obs, mirobot_action, reward, terminated, truncated, info = env.step(0)
|
| 173 |
-
game_state['last_action_id'] = mirobot_action
|
| 174 |
|
| 175 |
faim_display = env.state[ETAT_FAIM] * 100
|
| 176 |
humeur_display = env.state[ETAT_HUMEUR]
|
|
@@ -179,16 +159,20 @@ def handle_user_command(current_state, command_text, reward_path):
|
|
| 179 |
|
| 180 |
# 4. Exécution de la décision du Modèle
|
| 181 |
command_action_name = command_upper
|
|
|
|
|
|
|
| 182 |
env.state[CMD_AVANCER] = 1.0 if command_action_name == "AVANCER" else 0.0
|
| 183 |
env.state[CMD_TOURNER] = 1.0 if command_action_name.startswith("TOURNER") else 0.0
|
| 184 |
|
|
|
|
| 185 |
obs = env.state
|
| 186 |
mirobot_action_id, _ = model.predict(obs, deterministic=True)
|
| 187 |
|
|
|
|
| 188 |
new_obs, reward, terminated, truncated, info = env.step(mirobot_action_id)
|
| 189 |
|
| 190 |
|
| 191 |
-
# 4.
|
| 192 |
dx, dy = 0, 0
|
| 193 |
|
| 194 |
if mirobot_action_id == ACTION_MAP_USER[command_action_name]:
|
|
@@ -198,7 +182,7 @@ def handle_user_command(current_state, command_text, reward_path):
|
|
| 198 |
rx, ry = game_state['reward_pos']
|
| 199 |
px, py = game_state['puppy_pos']
|
| 200 |
|
| 201 |
-
# Déplacement
|
| 202 |
if abs(rx - px) > abs(ry - py):
|
| 203 |
dx = 1 if rx > px else -1
|
| 204 |
elif abs(ry - py) > 0:
|
|
@@ -208,11 +192,10 @@ def handle_user_command(current_state, command_text, reward_path):
|
|
| 208 |
real_action_name = ACTION_MAP_MODEL[mirobot_action_id]
|
| 209 |
game_state['message'] = f"😥 MiRobot a désobéi ! Il a fait '{real_action_name}' au lieu de '{command_action_name}'. Faim ou Humeur faible ? Récompense RL: {reward:.2f}"
|
| 210 |
|
| 211 |
-
# 4.
|
| 212 |
new_x = np.clip(game_state['puppy_pos'][0] + dx, 0, GRID_SIZE - 1)
|
| 213 |
new_y = np.clip(game_state['puppy_pos'][1] + dy, 0, GRID_SIZE - 1)
|
| 214 |
game_state['puppy_pos'] = [new_x, new_y]
|
| 215 |
-
game_state['last_action_id'] = mirobot_action_id
|
| 216 |
|
| 217 |
faim_display = env.state[ETAT_FAIM] * 100
|
| 218 |
humeur_display = env.state[ETAT_HUMEUR]
|
|
@@ -220,11 +203,10 @@ def handle_user_command(current_state, command_text, reward_path):
|
|
| 220 |
|
| 221 |
|
| 222 |
def handle_bravo(current_state):
|
| 223 |
-
"""Gère l'événement de récompense
|
| 224 |
game_state = current_state
|
| 225 |
|
| 226 |
if env is None:
|
| 227 |
-
# Sortie sûre en cas d'échec de chargement
|
| 228 |
return game_state, game_state['puppy_pos'][0], game_state['puppy_pos'][1], 0, 0, '❌ Erreur: Modèle non chargé.'
|
| 229 |
|
| 230 |
px, py = game_state['puppy_pos']
|
|
@@ -233,6 +215,7 @@ def handle_bravo(current_state):
|
|
| 233 |
if px == rx and py == ry:
|
| 234 |
game_state['level'] += 1
|
| 235 |
|
|
|
|
| 236 |
env.state[ETAT_FAIM] = np.clip(env.state[ETAT_FAIM] - 0.5, 0.0, 1.0)
|
| 237 |
env.state[ETAT_HUMEUR] = np.clip(env.state[ETAT_HUMEUR] + 0.5, -1.0, 1.0)
|
| 238 |
|
|
@@ -246,7 +229,7 @@ def handle_bravo(current_state):
|
|
| 246 |
|
| 247 |
|
| 248 |
def _draw_grid(puppy_pos, reward_pos, reward_path):
|
| 249 |
-
"""Dessine la grille de jeu avec le chiot et la récompense."""
|
| 250 |
if reward_path is None:
|
| 251 |
return "<p style='text-align: center; color: red;'>Veuillez télécharger une image de récompense pour afficher la grille.</p>"
|
| 252 |
|
|
@@ -305,6 +288,8 @@ else:
|
|
| 305 |
gr.Markdown(
|
| 306 |
f"""
|
| 307 |
# MiRobot - Le Jeu d'Obéissance 🐾
|
|
|
|
|
|
|
| 308 |
Bienvenue dans la simulation interactive de votre modèle RL **{REPO_ID}** !
|
| 309 |
**Objectif :** Guider MiRobot vers la récompense en donnant des ordres. Attention, sa **Faim** augmente à chaque pas !
|
| 310 |
"""
|
|
@@ -324,7 +309,7 @@ else:
|
|
| 324 |
with gr.Column(scale=1):
|
| 325 |
level_display = gr.Markdown(f"### Niveau Actuel : {INITIAL_LEVEL}")
|
| 326 |
|
| 327 |
-
#
|
| 328 |
faim_bar = gr.Slider(minimum=0, maximum=100, value=initial_faim, label="Faim de MiRobot (%)", interactive=False)
|
| 329 |
humeur_bar = gr.Slider(minimum=-1.0, maximum=1.0, value=initial_humeur, label="Humeur de MiRobot", interactive=False)
|
| 330 |
|
|
@@ -340,13 +325,13 @@ else:
|
|
| 340 |
|
| 341 |
message_output = gr.Markdown(f"**Message :** {game_state_initial['message']}")
|
| 342 |
|
| 343 |
-
# États cachés
|
| 344 |
puppy_pos_x = gr.State(game_state_initial['puppy_pos'][0])
|
| 345 |
puppy_pos_y = gr.State(game_state_initial['puppy_pos'][1])
|
| 346 |
faim_state = gr.State(initial_faim)
|
| 347 |
humeur_state = gr.State(initial_humeur)
|
| 348 |
|
| 349 |
-
# --- ÉVÉNEMENTS
|
| 350 |
|
| 351 |
reward_x.change(
|
| 352 |
fn=update_reward_pos,
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import numpy as np
|
| 3 |
import os
|
|
|
|
| 4 |
|
| 5 |
# Bibliothèques d'IA et de RL
|
|
|
|
| 6 |
import gymnasium as gym
|
| 7 |
from gymnasium import register, spaces
|
| 8 |
from stable_baselines3 import PPO
|
| 9 |
from huggingface_hub import hf_hub_download
|
| 10 |
|
| 11 |
# --- PARAMÈTRES DU DÉPÔT HUGGING FACE ---
|
| 12 |
+
# Basé sur vos fichiers.
|
| 13 |
+
REPO_ID = "Clemylia/MiRobot"
|
| 14 |
MODEL_FILE = "mirobot_final_model.zip"
|
| 15 |
ENV_SCRIPT_FILE = "MiRobotEnv.py"
|
| 16 |
ENV_ID = 'MiRobot-v0'
|
| 17 |
|
| 18 |
# --- CONSTANTES DE JEU ---
|
| 19 |
GRID_SIZE = 10
|
| 20 |
+
FAIM_PENALTY_THRESHOLD = 0.9
|
|
|
|
|
|
|
| 21 |
INITIAL_LEVEL = 1
|
| 22 |
|
| 23 |
+
# --- INDICES D'ÉTAT ---
|
| 24 |
+
# Basé sur votre MiRobotEnv.py
|
| 25 |
CMD_AVANCER = 0
|
| 26 |
CMD_TOURNER = 1
|
| 27 |
ETAT_FAIM = 2
|
| 28 |
ETAT_SOMMEIL = 3
|
| 29 |
ETAT_HUMEUR = 4
|
| 30 |
|
| 31 |
+
# Map des actions du modèle pour l'affichage
|
| 32 |
ACTION_MAP_MODEL = {0: "S'Arrêter", 1: "Avancer", 2: "Tourner G", 3: "Tourner D"}
|
| 33 |
|
| 34 |
+
# Map des commandes utilisateur aux ID d'action du modèle
|
| 35 |
ACTION_MAP_USER = {
|
| 36 |
"AVANCER": 1,
|
| 37 |
"TOURNER À GAUCHE": 2,
|
|
|
|
| 39 |
}
|
| 40 |
|
| 41 |
# ----------------------------------------------------------------------
|
| 42 |
+
# 1. PRÉPARATION DU MODÈLE ET DE L'ENVIRONNEMENT (CORRECTION DE L'INITIALISATION)
|
| 43 |
# ----------------------------------------------------------------------
|
| 44 |
|
| 45 |
model = None
|
|
|
|
| 58 |
env_path = hf_hub_download(repo_id=REPO_ID, filename=ENV_SCRIPT_FILE, local_dir=TEMP_DIR)
|
| 59 |
|
| 60 |
# INJECTION DE DÉPENDANCES pour que MiRobotEnv.py fonctionne
|
| 61 |
+
env_globals = {'gym': gym, 'np': np, 'spaces': spaces}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
|
| 63 |
with open(env_path, 'r') as f:
|
| 64 |
exec(f.read(), env_globals)
|
| 65 |
|
|
|
|
| 66 |
MiRobotEnv = env_globals['MiRobotEnv']
|
| 67 |
print("Classe MiRobotEnv définie avec succès.")
|
| 68 |
|
| 69 |
|
| 70 |
# --- 2. Enregistrement de l'environnement Custom ---
|
|
|
|
| 71 |
register(
|
| 72 |
id=ENV_ID,
|
| 73 |
entry_point=MiRobotEnv,
|
|
|
|
| 80 |
model = PPO.load(model_path)
|
| 81 |
|
| 82 |
env = gym.make(ENV_ID)
|
| 83 |
+
env.reset() # Initialise l'état interne (self.state est créé ici)
|
| 84 |
|
| 85 |
# Lecture des états initiaux pour l'interface Gradio (Utilisation sûre)
|
| 86 |
initial_faim = env.state[ETAT_FAIM] * 100
|
|
|
|
| 90 |
|
| 91 |
except Exception as e:
|
| 92 |
print(f"❌ ERREUR CRITIQUE lors du chargement de MiRobot: {e}")
|
| 93 |
+
# Si échec, model et env restent None, et les valeurs initiales restent 0.0
|
| 94 |
|
| 95 |
# ----------------------------------------------------------------------
|
| 96 |
# 2. LOGIQUE DU JEU
|
| 97 |
# ----------------------------------------------------------------------
|
| 98 |
|
| 99 |
+
# L'état initial du jeu
|
| 100 |
game_state_initial = {
|
| 101 |
'level': INITIAL_LEVEL,
|
| 102 |
'puppy_pos': [GRID_SIZE // 2, GRID_SIZE // 2],
|
| 103 |
'reward_pos': [0, 0],
|
|
|
|
|
|
|
| 104 |
'message': 'Bienvenue ! Téléchargez une récompense et commencez !',
|
| 105 |
'reward_asset_path': None
|
| 106 |
}
|
|
|
|
| 111 |
new_state = game_state_initial.copy()
|
| 112 |
|
| 113 |
if env is not None:
|
| 114 |
+
obs, info = env.reset() # IMPORTANT : Assure la création de self.state
|
|
|
|
|
|
|
| 115 |
faim_display = env.state[ETAT_FAIM] * 100
|
| 116 |
humeur_display = env.state[ETAT_HUMEUR]
|
| 117 |
else:
|
|
|
|
| 125 |
|
| 126 |
return new_state, new_state['puppy_pos'][0], new_state['puppy_pos'][1], new_state['reward_pos'][0], new_state['reward_pos'][1], faim_display, humeur_display, new_state['message']
|
| 127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
def handle_user_command(current_state, command_text, reward_path):
|
| 129 |
+
"""Fonction principale appelée par Gradio pour gérer une commande utilisateur."""
|
|
|
|
|
|
|
| 130 |
game_state = current_state
|
| 131 |
|
| 132 |
if model is None or env is None:
|
| 133 |
+
# Sortie sécurisée en cas d'échec de chargement
|
| 134 |
return game_state, command_text, 5, 5, 0, 0, '❌ Erreur: Le modèle MiRobot n\'a pas pu être chargé !'
|
| 135 |
|
| 136 |
game_state['reward_asset_path'] = reward_path
|
| 137 |
|
| 138 |
# 2. Vérification de la faim (condition de défaite)
|
| 139 |
+
faim_actuelle = env.state[ETAT_FAIM]
|
| 140 |
if faim_actuelle >= FAIM_PENALTY_THRESHOLD:
|
| 141 |
game_state['message'] = f'💔 Défaite ! MiRobot a trop faim ({faim_actuelle:.0%}) et ne peut plus obéir. Jeu réinitialisé au Niveau 1.'
|
| 142 |
return _reset_game(reward_path)
|
| 143 |
|
|
|
|
| 144 |
# 3. Traitement de la commande utilisateur
|
| 145 |
command_upper = command_text.upper()
|
| 146 |
|
| 147 |
if command_upper not in ACTION_MAP_USER:
|
| 148 |
+
game_state['message'] = f"🤔 MiRobot n'a pas compris l'ordre '{command_text}'. Sa faim augmente..."
|
| 149 |
|
| 150 |
+
# Simuler un pas de temps (Action 0: S'arrêter) sans commande active pour laisser la faim monter
|
| 151 |
env.state[CMD_AVANCER] = 0.0
|
| 152 |
env.state[CMD_TOURNER] = 0.0
|
| 153 |
new_obs, mirobot_action, reward, terminated, truncated, info = env.step(0)
|
|
|
|
| 154 |
|
| 155 |
faim_display = env.state[ETAT_FAIM] * 100
|
| 156 |
humeur_display = env.state[ETAT_HUMEUR]
|
|
|
|
| 159 |
|
| 160 |
# 4. Exécution de la décision du Modèle
|
| 161 |
command_action_name = command_upper
|
| 162 |
+
|
| 163 |
+
# 4.1. Injecter la commande dans l'état de l'environnement (Observation)
|
| 164 |
env.state[CMD_AVANCER] = 1.0 if command_action_name == "AVANCER" else 0.0
|
| 165 |
env.state[CMD_TOURNER] = 1.0 if command_action_name.startswith("TOURNER") else 0.0
|
| 166 |
|
| 167 |
+
# 4.2. Le modèle prédit l'action réelle (Obéissance ou gestion de besoin)
|
| 168 |
obs = env.state
|
| 169 |
mirobot_action_id, _ = model.predict(obs, deterministic=True)
|
| 170 |
|
| 171 |
+
# 4.3. Exécuter l'action PRÉDITE par le modèle (mise à jour de la faim, humeur)
|
| 172 |
new_obs, reward, terminated, truncated, info = env.step(mirobot_action_id)
|
| 173 |
|
| 174 |
|
| 175 |
+
# 4.4. Traduire l'action réelle du modèle en mouvement sur la grille
|
| 176 |
dx, dy = 0, 0
|
| 177 |
|
| 178 |
if mirobot_action_id == ACTION_MAP_USER[command_action_name]:
|
|
|
|
| 182 |
rx, ry = game_state['reward_pos']
|
| 183 |
px, py = game_state['puppy_pos']
|
| 184 |
|
| 185 |
+
# Déplacement d'une unité vers la récompense
|
| 186 |
if abs(rx - px) > abs(ry - py):
|
| 187 |
dx = 1 if rx > px else -1
|
| 188 |
elif abs(ry - py) > 0:
|
|
|
|
| 192 |
real_action_name = ACTION_MAP_MODEL[mirobot_action_id]
|
| 193 |
game_state['message'] = f"😥 MiRobot a désobéi ! Il a fait '{real_action_name}' au lieu de '{command_action_name}'. Faim ou Humeur faible ? Récompense RL: {reward:.2f}"
|
| 194 |
|
| 195 |
+
# 4.5. Mise à jour de la position et de l'état du chiot
|
| 196 |
new_x = np.clip(game_state['puppy_pos'][0] + dx, 0, GRID_SIZE - 1)
|
| 197 |
new_y = np.clip(game_state['puppy_pos'][1] + dy, 0, GRID_SIZE - 1)
|
| 198 |
game_state['puppy_pos'] = [new_x, new_y]
|
|
|
|
| 199 |
|
| 200 |
faim_display = env.state[ETAT_FAIM] * 100
|
| 201 |
humeur_display = env.state[ETAT_HUMEUR]
|
|
|
|
| 203 |
|
| 204 |
|
| 205 |
def handle_bravo(current_state):
|
| 206 |
+
"""Gère l'événement de récompense."""
|
| 207 |
game_state = current_state
|
| 208 |
|
| 209 |
if env is None:
|
|
|
|
| 210 |
return game_state, game_state['puppy_pos'][0], game_state['puppy_pos'][1], 0, 0, '❌ Erreur: Modèle non chargé.'
|
| 211 |
|
| 212 |
px, py = game_state['puppy_pos']
|
|
|
|
| 215 |
if px == rx and py == ry:
|
| 216 |
game_state['level'] += 1
|
| 217 |
|
| 218 |
+
# Réduction de la faim et augmentation de l'humeur
|
| 219 |
env.state[ETAT_FAIM] = np.clip(env.state[ETAT_FAIM] - 0.5, 0.0, 1.0)
|
| 220 |
env.state[ETAT_HUMEUR] = np.clip(env.state[ETAT_HUMEUR] + 0.5, -1.0, 1.0)
|
| 221 |
|
|
|
|
| 229 |
|
| 230 |
|
| 231 |
def _draw_grid(puppy_pos, reward_pos, reward_path):
|
| 232 |
+
"""Dessine la grille de jeu avec le chiot et la récompense (via HTML/CSS)."""
|
| 233 |
if reward_path is None:
|
| 234 |
return "<p style='text-align: center; color: red;'>Veuillez télécharger une image de récompense pour afficher la grille.</p>"
|
| 235 |
|
|
|
|
| 288 |
gr.Markdown(
|
| 289 |
f"""
|
| 290 |
# MiRobot - Le Jeu d'Obéissance 🐾
|
| 291 |
+
**ATTENTION :** Votre Space a atteint sa limite de stockage (50G). Pour que l'application fonctionne, vous devez supprimer des fichiers ou augmenter la capacité de votre Space.
|
| 292 |
+
|
| 293 |
Bienvenue dans la simulation interactive de votre modèle RL **{REPO_ID}** !
|
| 294 |
**Objectif :** Guider MiRobot vers la récompense en donnant des ordres. Attention, sa **Faim** augmente à chaque pas !
|
| 295 |
"""
|
|
|
|
| 309 |
with gr.Column(scale=1):
|
| 310 |
level_display = gr.Markdown(f"### Niveau Actuel : {INITIAL_LEVEL}")
|
| 311 |
|
| 312 |
+
# Utilisation des valeurs initiales sûres
|
| 313 |
faim_bar = gr.Slider(minimum=0, maximum=100, value=initial_faim, label="Faim de MiRobot (%)", interactive=False)
|
| 314 |
humeur_bar = gr.Slider(minimum=-1.0, maximum=1.0, value=initial_humeur, label="Humeur de MiRobot", interactive=False)
|
| 315 |
|
|
|
|
| 325 |
|
| 326 |
message_output = gr.Markdown(f"**Message :** {game_state_initial['message']}")
|
| 327 |
|
| 328 |
+
# États cachés
|
| 329 |
puppy_pos_x = gr.State(game_state_initial['puppy_pos'][0])
|
| 330 |
puppy_pos_y = gr.State(game_state_initial['puppy_pos'][1])
|
| 331 |
faim_state = gr.State(initial_faim)
|
| 332 |
humeur_state = gr.State(initial_humeur)
|
| 333 |
|
| 334 |
+
# --- ÉVÉNEMENTS ---
|
| 335 |
|
| 336 |
reward_x.change(
|
| 337 |
fn=update_reward_pos,
|