Lukeetah commited on
Commit
97de684
·
verified ·
1 Parent(s): 5b387b8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +514 -429
app.py CHANGED
@@ -1,507 +1,592 @@
1
- # app.py - EL GAUCHO CÓSMICO ÉPICO VERSION 2.0
2
  import gradio as gr
3
  import time
4
  import math
5
  import random
6
- from PIL import Image, ImageDraw, ImageFont
7
- from game_engine import GauchoCharacter, PhysicsEngine, WorldGenerator, Vector2D
8
 
9
- class EpicGameEngine:
10
  def __init__(self):
11
- self.width = 800
12
- self.height = 600
13
- self.player = GauchoCharacter()
14
- self.player.position = Vector2D(100, 400)
15
- self.physics = PhysicsEngine()
16
-
17
- # Sistema de juego épico
18
- self.scroll_x = 0
19
- self.enemies = []
20
- self.projectiles = []
21
- self.crystals = []
22
- self.particles = []
23
- self.combo_meter = 0
24
- self.cultural_power = 100
25
-
26
- # Estados de juego
27
- self.game_state = "playing" # playing, dialogue, victory
28
- self.current_level = 1
29
- self.boss_fight = False
30
-
31
- # Inicializar mundo épico
32
- self._spawn_initial_world()
33
- self._spawn_enemies()
34
- self._spawn_crystals()
35
-
36
- def _spawn_initial_world(self):
37
- """Crea un mundo side-scrolling épico"""
38
- self.terrain = []
39
- for x in range(0, 2000, 50):
40
- height = 450 + 50 * math.sin(x / 100)
41
- self.terrain.append((x, int(height)))
42
-
43
- def _spawn_enemies(self):
44
- """Genera enemigos algorítmicos épicos"""
45
- enemy_types = ['homogenizer', 'cultural_eraser', 'identity_fragmenter']
46
- for i in range(5):
47
- self.enemies.append({
48
- 'type': random.choice(enemy_types),
49
- 'position': Vector2D(300 + i * 200, 350),
50
- 'health': 3,
51
- 'pattern': 'patrol',
52
- 'attack_timer': 0,
53
- 'animation_frame': 0
54
- })
55
-
56
- def _spawn_crystals(self):
57
- """Cristales de valores argentinos distribuidos épicamente"""
58
- values = ['Solidaridad', 'Familia', 'Amistad', 'Respeto', 'Creatividad']
59
- colors = [(255, 100, 100), (100, 255, 100), (100, 100, 255), (255, 255, 100), (255, 100, 255)]
60
-
61
- for i, (value, color) in enumerate(zip(values, colors)):
62
- self.crystals.append({
63
- 'type': value,
64
- 'position': Vector2D(200 + i * 300, 200 + random.randint(-100, 100)),
65
- 'color': color,
66
- 'collected': False,
67
- 'pulse': 0,
68
- 'floating_offset': random.random() * math.pi
69
- })
70
-
71
- def update_game(self, action):
72
- """Motor de juego principal"""
73
- dt = 0.016 # 60 FPS target
74
-
75
- # Actualizar jugador
76
- self._update_player(action, dt)
77
-
78
- # Actualizar mundo
79
- self._update_scroll()
80
- self._update_enemies(dt)
81
- self._update_projectiles(dt)
82
- self._update_particles(dt)
83
- self._check_collisions()
84
-
85
- # Sistemas de juego
86
- self._update_combo_system()
87
- self._check_victory_condition()
88
-
89
- def _update_player(self, action, dt):
90
- """Sistema de movimiento fluido del gaucho"""
91
- acceleration = Vector2D(0, 0.5) # Gravedad
92
-
93
- if action == "left":
94
- acceleration.x = -8
95
- self.player.facing = "left"
96
- elif action == "right":
97
- acceleration.x = 8
98
- self.player.facing = "right"
99
- elif action == "jump":
100
- if self.player.on_ground:
101
- self.player.velocity.y = -12
102
- self.player.on_ground = False
103
- self._create_particles(self.player.position, "jump", 5)
104
- elif action == "attack":
105
- self._throw_boleadoras()
106
- elif action == "special":
107
- self._use_mate_power()
108
-
109
- # Aplicar física fluida
110
- self.player.velocity = self.physics.apply_momentum(
111
- self.player.velocity, acceleration, dt
112
- )
113
 
114
- # Movimiento suave
115
- self.player.position += self.player.velocity * dt * 60
 
 
 
 
 
 
 
116
 
117
- # Colisión con terreno
118
- self._handle_terrain_collision()
119
-
120
- def _update_scroll(self):
121
- """Cámara que sigue al jugador dinámicamente"""
122
- target_scroll = self.player.position.x - 200
123
- self.scroll_x += (target_scroll - self.scroll_x) * 0.1 # Smooth following
124
-
125
- def _throw_boleadoras(self):
126
- """Sistema de combate con boleadoras cuánticas"""
127
- if len(self.projectiles) < 3: # Máximo 3 boleadoras activas
128
- direction = 1 if self.player.facing == "right" else -1
129
- self.projectiles.append({
130
- 'position': Vector2D(self.player.position.x, self.player.position.y - 20),
131
- 'velocity': Vector2D(direction * 15, -2),
132
- 'type': 'boleadoras',
133
- 'lifetime': 2.0,
134
- 'trail': []
135
- })
136
- self._create_particles(self.player.position, "boleadoras", 3)
137
-
138
- def _use_mate_power(self):
139
- """Poder especial del mate tecnológico"""
140
- if self.cultural_power >= 50:
141
- self.cultural_power -= 50
142
- self.combo_meter += 20
143
-
144
- # Efecto de área que afecta enemigos cercanos
145
- for enemy in self.enemies:
146
- distance = ((self.player.position.x - enemy['position'].x) ** 2 +
147
- (self.player.position.y - enemy['position'].y) ** 2) ** 0.5
148
- if distance < 150:
149
- enemy['health'] -= 2
150
- self._create_particles(enemy['position'], "mate_effect", 8)
151
 
152
- def _create_particles(self, position, particle_type, count):
153
- """Sistema de partículas épico"""
154
- for _ in range(count):
155
- self.particles.append({
156
- 'position': Vector2D(position.x + random.randint(-10, 10),
157
- position.y + random.randint(-10, 10)),
158
- 'velocity': Vector2D(random.randint(-3, 3), random.randint(-5, 0)),
159
- 'color': self._get_particle_color(particle_type),
160
- 'lifetime': random.uniform(0.5, 1.5),
161
- 'type': particle_type
162
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
- def _get_particle_color(self, particle_type):
165
- colors = {
166
- 'jump': (100, 200, 255),
167
- 'boleadoras': (255, 200, 100),
168
- 'mate_effect': (0, 255, 100),
169
- 'explosion': (255, 100, 100),
170
- 'crystal': (255, 255, 255)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  }
172
- return colors.get(particle_type, (255, 255, 255))
 
 
 
 
173
 
174
- def render_epic_frame(self) -> Image.Image:
175
- """Renderizado épico con múltiples capas"""
176
- img = Image.new('RGB', (self.width, self.height), (10, 15, 35))
177
  draw = ImageDraw.Draw(img)
178
 
179
- # Capa 1: Fondo estrellado con parallax
180
- self._draw_starfield(draw)
181
 
182
- # Capa 2: Montañas distantes
183
- self._draw_mountains(draw)
184
 
185
- # Capa 3: Terreno principal
186
- self._draw_terrain(draw)
187
 
188
- # Capa 4: Cristales con efectos
189
- self._draw_crystals(draw)
190
 
191
- # Capa 5: Enemigos animados
192
- self._draw_enemies(draw)
193
 
194
- # Capa 6: Proyectiles con trails
195
- self._draw_projectiles(draw)
196
-
197
- # Capa 7: Gaucho protagonista
198
- self._draw_epic_gaucho(draw)
 
199
 
200
- # Capa 8: Partículas
201
- self._draw_particles(draw)
 
 
 
202
 
203
- # Capa 9: UI épica
204
- self._draw_ui(draw)
 
 
 
205
 
206
- return img
207
-
208
- def _draw_starfield(self, draw):
209
- """Fondo estrellado con parallax scrolling"""
210
- for i in range(100):
211
- star_x = (i * 47 + self.scroll_x * 0.2) % self.width
212
- star_y = (i * 31) % self.height
213
- brightness = 100 + (i % 155)
214
- draw.ellipse([star_x-1, star_y-1, star_x+1, star_y+1],
215
- fill=(brightness, brightness, brightness))
216
 
217
- def _draw_mountains(self, draw):
218
- """Montañas de fondo con profundidad"""
219
- for i in range(0, self.width + 100, 100):
220
- mountain_x = i - (self.scroll_x * 0.5) % 100
221
- mountain_height = 200 + 50 * math.sin((mountain_x + self.scroll_x) / 150)
222
- draw.polygon([
223
- (mountain_x, self.height),
224
- (mountain_x + 50, mountain_height),
225
- (mountain_x + 100, self.height)
226
- ], fill=(30, 40, 80), outline=(50, 60, 120))
227
 
228
- def _draw_terrain(self, draw):
229
- """Terreno orgánico y fluido"""
230
- terrain_points = [(0, self.height)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
 
232
- for i in range(0, self.width, 20):
233
- world_x = i + self.scroll_x
234
- height = 450 + 30 * math.sin(world_x / 80) + 20 * math.cos(world_x / 120)
235
- terrain_points.append((i, height))
236
 
237
- terrain_points.append((self.width, self.height))
238
- draw.polygon(terrain_points, fill=(20, 60, 40), outline=(40, 120, 80))
 
239
 
240
- def _draw_epic_gaucho(self, draw):
241
- """Gaucho protagonista con animaciones fluidas"""
242
- screen_x = int(self.player.position.x - self.scroll_x)
243
- screen_y = int(self.player.position.y)
244
-
245
- if 0 <= screen_x <= self.width:
246
- # Sombra dinámica
247
- draw.ellipse([screen_x-15, screen_y+20, screen_x+15, screen_y+25],
248
- fill=(0, 0, 0, 100))
249
-
250
- # Cuerpo principal
251
- body_color = (139, 69, 19)
252
- draw.ellipse([screen_x-20, screen_y-30, screen_x+20, screen_y+10],
253
- fill=body_color, outline=(101, 67, 33), width=2)
254
 
255
- # Poncho tecnológico animado
256
- poncho_wave = math.sin(time.time() * 5) * 3
257
- poncho_points = [
258
- (screen_x-25, screen_y-15 + poncho_wave),
259
- (screen_x-15, screen_y-35),
260
- (screen_x+15, screen_y-35),
261
- (screen_x+25, screen_y-15 - poncho_wave),
262
- (screen_x+20, screen_y+5),
263
- (screen_x-20, screen_y+5)
264
- ]
265
- draw.polygon(poncho_points, fill=(0, 120, 200), outline=(0, 180, 255), width=2)
266
 
267
- # Líneas energéticas del poncho
268
- for i in range(-15, 20, 8):
269
- line_alpha = int(255 * (0.5 + 0.5 * math.sin(time.time() * 3 + i)))
270
- draw.line([(screen_x+i, screen_y-30), (screen_x+i, screen_y+5)],
271
- fill=(255, 255, 100), width=1)
 
 
 
 
272
 
273
- # Sombrero gaucho épico
274
- hat_tilt = 2 if self.player.facing == "right" else -2
275
- draw.ellipse([screen_x-18+hat_tilt, screen_y-45, screen_x+18+hat_tilt, screen_y-35],
276
- fill=(50, 25, 0), outline=(100, 50, 0), width=2)
277
- draw.ellipse([screen_x-30+hat_tilt, screen_y-40, screen_x+30+hat_tilt, screen_y-38],
278
- fill=(40, 20, 0), outline=(80, 40, 0), width=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
 
280
- # Mate tecnológico brillante
281
- mate_x = screen_x + (12 if self.player.facing == "right" else -12)
282
- mate_glow = int(100 + 50 * math.sin(time.time() * 4))
283
- draw.ellipse([mate_x-6, screen_y-10, mate_x+6, screen_y+2],
284
- fill=(150, 75, 0), outline=(255, mate_glow, 0), width=2)
285
 
286
- # Bombilla láser
287
- laser_intensity = int(255 * (0.7 + 0.3 * math.sin(time.time() * 8)))
288
- draw.line([(mate_x, screen_y-10), (mate_x, screen_y-18)],
289
- fill=(0, laser_intensity, 0), width=3)
 
 
290
 
291
- # Ojos expresivos
292
- eye_offset = 2 if self.player.facing == "right" else -2
293
- draw.ellipse([screen_x-8+eye_offset, screen_y-25, screen_x-3+eye_offset, screen_y-20],
294
- fill=(255, 255, 255))
295
- draw.ellipse([screen_x+3+eye_offset, screen_y-25, screen_x+8+eye_offset, screen_y-20],
296
- fill=(255, 255, 255))
297
- draw.ellipse([screen_x-6+eye_offset, screen_y-23, screen_x-5+eye_offset, screen_y-22],
298
- fill=(0, 0, 0))
299
- draw.ellipse([screen_x+5+eye_offset, screen_y-23, screen_x+6+eye_offset, screen_y-22],
300
- fill=(0, 0, 0))
301
-
302
- def _draw_crystals(self, draw):
303
- """Cristales con efectos mágicos"""
304
- for crystal in self.crystals:
305
- if not crystal['collected']:
306
- screen_x = int(crystal['position'].x - self.scroll_x)
307
- screen_y = int(crystal['position'].y + 10 * math.sin(time.time() * 2 + crystal['floating_offset']))
308
-
309
- if -50 <= screen_x <= self.width + 50:
310
- # Aura brillante
311
- aura_size = 25 + 8 * math.sin(time.time() * 3 + crystal['pulse'])
312
- for i in range(3):
313
- alpha = 50 - i * 15
314
- draw.ellipse([screen_x-aura_size+i*5, screen_y-aura_size+i*5,
315
- screen_x+aura_size-i*5, screen_y+aura_size-i*5],
316
- outline=crystal['color'])
317
-
318
- # Cristal central
319
- crystal_size = 15 + 5 * math.sin(time.time() * 4 + crystal['pulse'])
320
- draw.polygon([
321
- (screen_x, screen_y-crystal_size),
322
- (screen_x-crystal_size*0.7, screen_y-crystal_size*0.3),
323
- (screen_x-crystal_size*0.7, screen_y+crystal_size*0.3),
324
- (screen_x, screen_y+crystal_size),
325
- (screen_x+crystal_size*0.7, screen_y+crystal_size*0.3),
326
- (screen_x+crystal_size*0.7, screen_y-crystal_size*0.3)
327
- ], fill=crystal['color'], outline=(255, 255, 255), width=2)
328
-
329
- def _draw_enemies(self, draw):
330
- """Enemigos algorítmicos con IA visual"""
331
- for enemy in self.enemies:
332
- if enemy['health'] > 0:
333
- screen_x = int(enemy['position'].x - self.scroll_x)
334
- screen_y = int(enemy['position'].y)
335
-
336
- if -50 <= screen_x <= self.width + 50:
337
- # Forma algorítmica hostil
338
- if enemy['type'] == 'homogenizer':
339
- # Cubo gris hostil
340
- draw.rectangle([screen_x-15, screen_y-15, screen_x+15, screen_y+15],
341
- fill=(80, 80, 80), outline=(120, 120, 120), width=2)
342
- # Patrón de homogenización
343
- for i in range(-10, 15, 5):
344
- draw.line([(screen_x+i, screen_y-15), (screen_x+i, screen_y+15)],
345
- fill=(150, 150, 150), width=1)
346
-
347
- elif enemy['type'] == 'cultural_eraser':
348
- # Forma que "borra" la cultura
349
- draw.polygon([
350
- (screen_x, screen_y-20),
351
- (screen_x-15, screen_y),
352
- (screen_x, screen_y+20),
353
- (screen_x+15, screen_y)
354
- ], fill=(100, 50, 50), outline=(150, 100, 100), width=2)
355
-
356
- # Barras de vida
357
- health_width = (enemy['health'] / 3) * 30
358
- draw.rectangle([screen_x-15, screen_y-25, screen_x+15, screen_y-22],
359
- fill=(50, 50, 50))
360
- draw.rectangle([screen_x-15, screen_y-25, screen_x-15+health_width, screen_y-22],
361
- fill=(255, 100, 100))
362
-
363
- def _draw_particles(self, draw):
364
- """Sistema de partículas dinámico"""
365
- for particle in self.particles:
366
- if particle['lifetime'] > 0:
367
- screen_x = int(particle['position'].x - self.scroll_x)
368
- screen_y = int(particle['position'].y)
369
-
370
- if 0 <= screen_x <= self.width and 0 <= screen_y <= self.height:
371
- alpha = int(255 * (particle['lifetime'] / 1.5))
372
- size = max(1, int(3 * particle['lifetime']))
373
- draw.ellipse([screen_x-size, screen_y-size, screen_x+size, screen_y+size],
374
- fill=particle['color'])
375
 
376
- def _draw_ui(self, draw):
377
- """Interfaz épica superpuesta"""
378
- # Barra de poder cultural
379
- draw.rectangle([20, 20, 220, 40], fill=(50, 50, 50), outline=(150, 150, 150), width=2)
380
- cultural_width = int((self.cultural_power / 100) * 200)
381
- draw.rectangle([20, 20, 20 + cultural_width, 40], fill=(0, 200, 100))
382
-
383
- # Combo meter
384
- if self.combo_meter > 0:
385
- combo_height = min(100, self.combo_meter * 2)
386
- draw.rectangle([self.width - 50, self.height - 120, self.width - 30, self.height - 20],
387
- fill=(50, 50, 50), outline=(200, 200, 200), width=2)
388
- draw.rectangle([self.width - 50, self.height - 20 - combo_height,
389
- self.width - 30, self.height - 20], fill=(255, 200, 0))
390
 
391
- class GauchoCosmicGame:
392
  def __init__(self):
393
- self.engine = EpicGameEngine()
394
- self.last_action = "none"
395
- self.game_stats = {
396
- 'crystals_collected': 0,
397
- 'enemies_defeated': 0,
398
- 'cultural_combos': 0,
399
- 'epic_level': 'MÁXIMO'
 
 
 
 
 
 
400
  }
 
 
 
 
401
 
402
- def process_input(self, action):
403
- """Procesa input del jugador"""
404
- self.last_action = action
405
- self.engine.update_game(action)
406
- self._update_stats()
407
- return self.engine.render_epic_frame(), self.get_status()
 
 
 
 
 
 
 
 
 
 
408
 
409
- def _update_stats(self):
410
- """Actualiza estadísticas del juego"""
411
- self.game_stats['crystals_collected'] = sum(
412
- 1 for crystal in self.engine.crystals if crystal['collected']
413
- )
414
- self.game_stats['cultural_combos'] = self.engine.combo_meter // 10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
415
 
416
- def get_status(self):
417
- """Estado épico del juego"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
  return {
419
- "🗺️ Posición": f"X: {self.engine.player.position.x:.0f}",
420
- " Velocidad": f"{abs(self.engine.player.velocity.x):.1f} km/h",
421
- "💎 Cristales": f"{self.game_stats['crystals_collected']}/5",
422
- "🔥 Poder Cultural": f"{self.engine.cultural_power:.0f}%",
423
- "🎯 Combos": self.game_stats['cultural_combos'],
424
- "🚀 Épica": self.game_stats['epic_level']
 
 
 
425
  }
426
 
427
- def create_ultimate_interface():
428
- game = GauchoCosmicGame()
429
 
430
  with gr.Blocks(
431
- title="🎮 EL GAUCHO CÓSMICO - ULTIMATE EDITION 🇦🇷",
432
- theme=gr.themes.Glass()
433
  ) as interface:
434
 
435
  gr.HTML("""
436
- <div style="text-align: center; background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
437
- color: white; padding: 20px; border-radius: 10px; margin: 10px;">
438
- <h1 style="font-size: 3em; margin: 0; text-shadow: 2px 2px 4px rgba(0,0,0,0.5);">
439
- 🌟 EL GAUCHO CÓSMICO 🌟
440
  </h1>
441
- <p style="font-size: 1.2em; margin: 10px 0;">
442
- AVENTURA SIDE-SCROLLING DE IDENTIDAD CULTURAL ARGENTINA
 
 
 
443
  </p>
444
  </div>
445
  """)
446
 
447
  with gr.Row():
448
- with gr.Column(scale=3):
449
  game_display = gr.Image(
450
- label="🌌 PAMPA CÓSMICA ÉPICA",
451
- interactive=False,
452
- width=800,
453
  height=600
454
  )
455
 
456
- gr.Markdown("### 🎮 CONTROLES ÉPICOS")
457
  with gr.Row():
458
- left_btn = gr.Button("⬅️ IZQUIERDA", variant="primary")
459
- right_btn = gr.Button("➡️ DERECHA", variant="primary")
460
- jump_btn = gr.Button("⬆️ SALTAR", variant="secondary")
461
-
462
  with gr.Row():
463
- attack_btn = gr.Button("🪃 BOLEADORAS", variant="stop")
464
- special_btn = gr.Button("🧉 MATE POWER", variant="stop")
 
465
 
466
  with gr.Column(scale=1):
467
- gr.Markdown("### 📊 ESTADO ÉPICO")
468
  status_display = gr.JSON(
469
- label="🎯 MÉTRICAS DE MARTÍN 'EL MATE'",
470
- value=game.get_status()
471
  )
472
 
473
- gr.Markdown("### 🎵 SOUNDTRACK")
 
 
 
 
 
 
 
 
474
  gr.HTML("""
475
- <div style="background: #2C3E50; padding: 15px; border-radius: 8px; color: white;">
476
- <p>🎼 <strong>Ahora sonando:</strong></p>
477
- <p style="font-style: italic;">"Pampa Cósmica - Tema Principal"</p>
478
- <p>🎸 Género: Folklectrónica Argentina</p>
 
 
 
 
 
 
479
  </div>
480
  """)
481
-
482
- gr.Markdown("### 💬 DIÁLOGOS ÉPICOS")
483
- dialogue_box = gr.Textbox(
484
- value="¡Che! ¿Viste esos algoritmos tratando de borrar nuestra cultura? ¡Ni en pedo se la llevo!",
485
- label="🗨️ Martín 'El Mate' habla",
486
- interactive=False,
487
- max_lines=3
488
- )
489
 
490
- # Conectar controles
491
- left_btn.click(fn=lambda: game.process_input("left"), outputs=[game_display, status_display])
492
- right_btn.click(fn=lambda: game.process_input("right"), outputs=[game_display, status_display])
493
- jump_btn.click(fn=lambda: game.process_input("jump"), outputs=[game_display, status_display])
494
- attack_btn.click(fn=lambda: game.process_input("attack"), outputs=[game_display, status_display])
495
- special_btn.click(fn=lambda: game.process_input("special"), outputs=[game_display, status_display])
 
 
 
 
 
 
 
 
 
 
 
 
496
 
497
  # Inicialización
498
  interface.load(
499
- fn=lambda: (game.engine.render_epic_frame(), game.get_status()),
500
- outputs=[game_display, status_display]
 
 
501
  )
502
 
503
  return interface
504
 
505
  if __name__ == "__main__":
506
- interface = create_ultimate_interface()
507
  interface.launch(share=True, show_error=True)
 
1
+ # main_game.py - CRISIS Y CORAJE: EL JUEGO ARGENTINO DEFINITIVO
2
  import gradio as gr
3
  import time
4
  import math
5
  import random
6
+ from PIL import Image, ImageDraw
7
+ from typing import Dict, List, Tuple
8
 
9
+ class ArgentinaGameEngine:
10
  def __init__(self):
11
+ # Core del juego
12
+ self.width, self.height = 900, 600
13
+ self.player = ArgentineCharacter()
14
+ self.world = ArgentineWorld()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ # Sistema de supervivencia argentino
17
+ self.resources = {
18
+ 'pesos': 1000,
19
+ 'dolares': 50,
20
+ 'comida': 80,
21
+ 'esperanza': 100,
22
+ 'solidaridad': 90,
23
+ 'trabajo': 70
24
+ }
25
 
26
+ # Mecánicas únicas argentinas
27
+ self.inflation_rate = 1.0
28
+ self.social_network = []
29
+ self.cultural_events = []
30
+ self.crisis_level = 1
31
+
32
+ # Estados del juego dinámicos
33
+ self.day = 1
34
+ self.season = "verano"
35
+ self.current_crisis = "corralito_2001"
36
+ self.neighborhood_mood = "esperanzado"
37
+
38
+ self.initialize_argentina()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
+ def initialize_argentina(self):
41
+ """Inicializa el mundo argentino auténtico"""
42
+ self.create_neighborhoods()
43
+ self.spawn_cultural_events()
44
+ self.setup_crisis_timeline()
45
+
46
+ class ArgentineCharacter:
47
+ def __init__(self):
48
+ self.name = "Carlos"
49
+ self.profession = random.choice(["albañil", "docente", "comerciante", "empleado_publico"])
50
+ self.position = [450, 300] # Centro de CABA
51
+ self.family = {
52
+ 'spouse': True,
53
+ 'children': random.randint(1, 3),
54
+ 'elderly_parents': random.choice([True, False])
55
+ }
56
+
57
+ # Skills argentinos únicos
58
+ self.skills = {
59
+ 'rebusque': 70,
60
+ 'mate_sharing': 90,
61
+ 'asado_expertise': 80,
62
+ 'crisis_survival': 60,
63
+ 'soccer_knowledge': 95,
64
+ 'political_debate': 75
65
+ }
66
+
67
+ self.current_strategy = "supervivencia_diaria"
68
+ self.stress_level = 30
69
+ self.community_reputation = 50
70
+
71
+ class CrisisManager:
72
+ """Sistema que simula las crisis argentinas reales"""
73
+ def __init__(self):
74
+ self.crisis_timeline = {
75
+ 2001: {
76
+ 'name': 'Corralito',
77
+ 'effects': {'peso_devaluation': 300, 'unemployment': 25, 'social_unrest': 80},
78
+ 'opportunities': ['trueque', 'economia_popular', 'solidaridad_vecinal']
79
+ },
80
+ 2008: {
81
+ 'name': 'Crisis Mundial',
82
+ 'effects': {'export_drop': 40, 'inflation': 25},
83
+ 'opportunities': ['mercado_interno', 'cooperativas']
84
+ },
85
+ 2018: {
86
+ 'name': 'Crisis Cambiaria',
87
+ 'effects': {'peso_devaluation': 100, 'inflation': 50},
88
+ 'opportunities': ['dolarizacion_popular', 'emprendedurismo']
89
+ },
90
+ 2020: {
91
+ 'name': 'Pandemia',
92
+ 'effects': {'lockdown': 90, 'unemployment': 15, 'solidarity_boost': 120},
93
+ 'opportunities': ['delivery', 'remote_work', 'community_support']
94
+ }
95
+ }
96
 
97
+ def apply_crisis_effects(self, game_state, current_year):
98
+ """Aplica efectos realistas de las crisis"""
99
+ if current_year in self.crisis_timeline:
100
+ crisis = self.crisis_timeline[current_year]
101
+ return self.modify_game_state(game_state, crisis)
102
+ return game_state
103
+
104
+ class NeighborhoodSystem:
105
+ """Sistema de barrios argentinos dinámicos"""
106
+ def __init__(self):
107
+ self.neighborhoods = {
108
+ 'villa_31': {
109
+ 'solidarity': 95, 'resources': 30, 'creativity': 90,
110
+ 'challenges': ['infraestructura', 'estigma_social'],
111
+ 'strengths': ['union_vecinal', 'cultura_popular']
112
+ },
113
+ 'palermo': {
114
+ 'solidarity': 60, 'resources': 85, 'creativity': 75,
115
+ 'challenges': ['gentrificacion', 'burbuja_social'],
116
+ 'strengths': ['startups', 'vida_nocturna']
117
+ },
118
+ 'san_telmo': {
119
+ 'solidarity': 80, 'resources': 70, 'creativity': 95,
120
+ 'challenges': ['turismo_masivo'],
121
+ 'strengths': ['tango', 'arte', 'historia']
122
+ },
123
+ 'mataderos': {
124
+ 'solidarity': 90, 'resources': 50, 'creativity': 85,
125
+ 'challenges': ['infraestructura'],
126
+ 'strengths': ['folklore', 'tradicion_gaucha']
127
+ }
128
  }
129
+
130
+ class GameRenderer:
131
+ def __init__(self):
132
+ self.current_view = "neighborhood"
133
+ self.animation_frame = 0
134
 
135
+ def render_argentina_frame(self, game_state) -> Image.Image:
136
+ """Renderiza Argentina de manera épica y auténtica"""
137
+ img = Image.new('RGB', (900, 600), (20, 30, 60))
138
  draw = ImageDraw.Draw(img)
139
 
140
+ # Fondo: Skyline de Buenos Aires
141
+ self.draw_buenos_aires_skyline(draw, game_state)
142
 
143
+ # Primer plano: Vecindario actual
144
+ self.draw_neighborhood(draw, game_state)
145
 
146
+ # Personajes: Vecinos interactuando
147
+ self.draw_community_life(draw, game_state)
148
 
149
+ # UI: Información de supervivencia
150
+ self.draw_survival_ui(draw, game_state)
151
 
152
+ # Efectos especiales: Crisis o celebraciones
153
+ self.draw_dynamic_effects(draw, game_state)
154
 
155
+ return img
156
+
157
+ def draw_buenos_aires_skyline(self, draw, game_state):
158
+ """Dibuja el skyline icónico de Buenos Aires"""
159
+ # Río de la Plata
160
+ draw.rectangle([0, 400, 900, 600], fill=(30, 60, 120))
161
 
162
+ # Puerto Madero
163
+ for i in range(5):
164
+ building_height = 250 + random.randint(-50, 50)
165
+ draw.rectangle([700 + i*30, 600-building_height, 720 + i*30, 600],
166
+ fill=(40, 40, 60), outline=(80, 80, 100))
167
 
168
+ # Microcentro
169
+ for i in range(8):
170
+ building_height = 200 + random.randint(-100, 100)
171
+ draw.rectangle([200 + i*40, 600-building_height, 230 + i*40, 600],
172
+ fill=(60, 60, 80), outline=(100, 100, 120))
173
 
174
+ # Obelisco (si estamos en el centro)
175
+ if game_state.get('location') == 'microcentro':
176
+ draw.polygon([(450, 150), (445, 400), (455, 400)],
177
+ fill=(200, 200, 200), outline=(255, 255, 255))
 
 
 
 
 
 
178
 
179
+ def draw_neighborhood(self, draw, game_state):
180
+ """Dibuja el barrio actual con detalles auténticos"""
181
+ neighborhood = game_state.get('current_neighborhood', 'villa_31')
182
+
183
+ if neighborhood == 'villa_31':
184
+ self.draw_villa_scene(draw, game_state)
185
+ elif neighborhood == 'palermo':
186
+ self.draw_palermo_scene(draw, game_state)
187
+ elif neighborhood == 'san_telmo':
188
+ self.draw_san_telmo_scene(draw, game_state)
189
 
190
+ def draw_villa_scene(self, draw, game_state):
191
+ """Villa 31: Casas coloridas, solidaridad, creatividad"""
192
+ # Casas de chapa coloridas
193
+ colors = [(255, 100, 100), (100, 255, 100), (100, 100, 255), (255, 255, 100)]
194
+ for i in range(6):
195
+ x = 50 + i * 120
196
+ y = 350 + random.randint(-30, 30)
197
+ color = random.choice(colors)
198
+
199
+ # Casa principal
200
+ draw.rectangle([x, y, x+80, y+80], fill=color, outline=(0, 0, 0), width=2)
201
+
202
+ # Techo de chapa
203
+ draw.polygon([(x-5, y), (x+40, y-20), (x+85, y)],
204
+ fill=(150, 150, 150), outline=(100, 100, 100))
205
+
206
+ # Antena parabólica
207
+ draw.ellipse([x+60, y-30, x+75, y-15], outline=(200, 200, 200), width=2)
208
 
209
+ # Cancha de fútbol improvisada
210
+ draw.rectangle([300, 450, 600, 550], fill=(100, 150, 50), outline=(255, 255, 255), width=3)
 
 
211
 
212
+ # Arcos de fútbol
213
+ draw.rectangle([300, 480, 310, 520], outline=(255, 255, 255), width=3)
214
+ draw.rectangle([590, 480, 600, 520], outline=(255, 255, 255), width=3)
215
 
216
+ def draw_community_life(self, draw, game_state):
217
+ """Dibuja la vida comunitaria argentina"""
218
+ # Ronda de mate
219
+ mate_circle_x, mate_circle_y = 200, 500
220
+ for i in range(5):
221
+ angle = i * (math.pi * 2 / 5)
222
+ x = mate_circle_x + 40 * math.cos(angle)
223
+ y = mate_circle_y + 40 * math.sin(angle)
 
 
 
 
 
 
224
 
225
+ # Persona
226
+ draw.ellipse([x-8, y-15, x+8, y+10], fill=(150, 120, 90), outline=(100, 80, 60))
 
 
 
 
 
 
 
 
 
227
 
228
+ # Mate (persona central)
229
+ if i == 0:
230
+ draw.ellipse([x-3, y-5, x+3, y+2], fill=(100, 50, 0), outline=(150, 100, 50))
231
+
232
+ # Parrilla/asado
233
+ if game_state.get('day_time') == 'tarde':
234
+ asado_x, asado_y = 700, 500
235
+ draw.rectangle([asado_x, asado_y, asado_x+60, asado_y+30],
236
+ fill=(50, 50, 50), outline=(100, 100, 100))
237
 
238
+ # Humo del asado
239
+ for i in range(5):
240
+ smoke_y = asado_y - 20 - i*15
241
+ smoke_x = asado_x + 30 + random.randint(-10, 10)
242
+ draw.ellipse([smoke_x-5, smoke_y-5, smoke_x+5, smoke_y+5],
243
+ fill=(200, 200, 200, 100))
244
+
245
+ # Chicos jugando
246
+ for i in range(3):
247
+ child_x = 400 + i*50 + random.randint(-20, 20)
248
+ child_y = 470 + random.randint(-10, 10)
249
+ draw.ellipse([child_x-5, child_y-10, child_x+5, child_y+5],
250
+ fill=(180, 140, 100), outline=(120, 100, 80))
251
+
252
+ # Pelota de fútbol
253
+ ball_x = 450 + 20 * math.sin(time.time() * 2)
254
+ draw.ellipse([ball_x-8, 485, ball_x+8, 501],
255
+ fill=(255, 255, 255), outline=(0, 0, 0), width=2)
256
+
257
+ def draw_survival_ui(self, draw, game_state):
258
+ """UI de supervivencia argentina"""
259
+ # Panel principal
260
+ draw.rectangle([10, 10, 300, 150], fill=(0, 0, 0, 180), outline=(150, 150, 150))
261
+
262
+ # Recursos
263
+ resources = game_state.get('resources', {})
264
+ y_offset = 25
265
+
266
+ for resource, value in resources.items():
267
+ color = self.get_resource_color(resource, value)
268
 
269
+ # Barra de recurso
270
+ draw.rectangle([20, y_offset, 200, y_offset+15], fill=(50, 50, 50))
271
+ bar_width = int((value / 100) * 180)
272
+ draw.rectangle([20, y_offset, 20 + bar_width, y_offset+15], fill=color)
 
273
 
274
+ # Texto del recurso
275
+ resource_names = {
276
+ 'pesos': '💰 Pesos', 'dolares': '💵 Dólares', 'comida': '🍖 Comida',
277
+ 'esperanza': '💪 Esperanza', 'solidaridad': '🤝 Solidaridad', 'trabajo': '🔨 Trabajo'
278
+ }
279
+ # draw.text([210, y_offset], f"{resource_names.get(resource, resource)}: {value}", fill=(255, 255, 255))
280
 
281
+ y_offset += 20
282
+
283
+ # Indicador de crisis
284
+ crisis_intensity = game_state.get('crisis_level', 1)
285
+ crisis_color = (255, 255 - crisis_intensity * 50, 255 - crisis_intensity * 50)
286
+ draw.rectangle([320, 10, 500, 40], fill=crisis_color, outline=(255, 255, 255))
287
+
288
+ # Día y situación
289
+ day = game_state.get('day', 1)
290
+ draw.rectangle([320, 50, 500, 80], fill=(20, 20, 20), outline=(100, 100, 100))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
 
292
+ def get_resource_color(self, resource, value):
293
+ """Colores dinámicos según el estado del recurso"""
294
+ if value > 70:
295
+ return (100, 255, 100) # Verde
296
+ elif value > 30:
297
+ return (255, 255, 100) # Amarillo
298
+ else:
299
+ return (255, 100, 100) # Rojo
 
 
 
 
 
 
300
 
301
+ class CrisisYCorajeGame:
302
  def __init__(self):
303
+ self.engine = ArgentinaGameEngine()
304
+ self.renderer = GameRenderer()
305
+ self.crisis_manager = CrisisManager()
306
+ self.neighborhood_system = NeighborhoodSystem()
307
+
308
+ # Estado del juego
309
+ self.game_state = {
310
+ 'resources': self.engine.resources.copy(),
311
+ 'day': 1,
312
+ 'current_neighborhood': 'villa_31',
313
+ 'crisis_level': 1,
314
+ 'location': 'villa_31',
315
+ 'day_time': 'mañana'
316
  }
317
+
318
+ # Eventos dinámicos
319
+ self.active_events = []
320
+ self.decisions_made = []
321
 
322
+ def process_action(self, action):
323
+ """Procesa las acciones del jugador con consecuencias reales"""
324
+ if action == "trabajar":
325
+ return self.work_day()
326
+ elif action == "ayudar_vecinos":
327
+ return self.help_neighbors()
328
+ elif action == "buscar_rebusque":
329
+ return self.find_rebusque()
330
+ elif action == "organizar_comunitario":
331
+ return self.organize_community()
332
+ elif action == "ahorrar_dolares":
333
+ return self.save_dollars()
334
+ elif action == "hacer_asado":
335
+ return self.make_asado()
336
+
337
+ return self.advance_day()
338
 
339
+ def work_day(self):
340
+ """Simula un día de trabajo con variables argentinas"""
341
+ profession = self.engine.player.profession
342
+ base_income = {
343
+ 'albañil': random.randint(2000, 4000),
344
+ 'docente': random.randint(1500, 2500),
345
+ 'comerciante': random.randint(1000, 8000),
346
+ 'empleado_publico': random.randint(1800, 2200)
347
+ }
348
+
349
+ income = base_income.get(profession, 2000)
350
+
351
+ # Efectos de la inflación
352
+ real_income = income / self.engine.inflation_rate
353
+
354
+ self.game_state['resources']['pesos'] += real_income
355
+ self.game_state['resources']['trabajo'] = min(100, self.game_state['resources']['trabajo'] + 10)
356
+
357
+ # Stress por la crisis
358
+ if self.game_state['crisis_level'] > 3:
359
+ self.engine.player.stress_level += 5
360
+ self.game_state['resources']['esperanza'] -= 5
361
+
362
+ return self.advance_day(), f"Trabajaste como {profession}. Ganaste ${real_income:.0f} pesos (inflación: {self.engine.inflation_rate:.1f}x)"
363
+
364
+ def help_neighbors(self):
365
+ """Ayudar a los vecinos - mecánica clave argentina"""
366
+ solidarity_gain = random.randint(10, 20)
367
+ self.game_state['resources']['solidaridad'] += solidarity_gain
368
+ self.game_state['resources']['esperanza'] += 5
369
+
370
+ # Costo en recursos pero ganancia en red social
371
+ self.game_state['resources']['comida'] -= 10
372
+ self.game_state['resources']['pesos'] -= 200
373
+
374
+ # Chance de reciprocidad
375
+ if random.random() < 0.3:
376
+ favor_returned = random.choice([
377
+ "Te devolvieron un favor con trabajo",
378
+ "Te invitaron a un asado",
379
+ "Te prestaron herramientas",
380
+ "Te cuidaron a los chicos"
381
+ ])
382
+ self.game_state['resources']['trabajo'] += 15
383
+ return self.advance_day(), f"Ayudaste a tus vecinos. {favor_returned}."
384
+
385
+ return self.advance_day(), f"Ayudaste a tus vecinos. Ganaste {solidarity_gain} puntos de solidaridad."
386
+
387
+ def find_rebusque(self):
388
+ """Rebusque - supervivencia argentina pura"""
389
+ rebusque_skill = self.engine.player.skills['rebusque']
390
+ success_chance = rebusque_skill / 100
391
+
392
+ if random.random() < success_chance:
393
+ rebusque_options = [
394
+ "Vendiste empanadas caseras",
395
+ "Arreglaste celulares",
396
+ "Hiciste changas de albañilería",
397
+ "Vendiste en la feria",
398
+ "Diste clases particulares"
399
+ ]
400
+
401
+ chosen_rebusque = random.choice(rebusque_options)
402
+ income = random.randint(500, 2000)
403
+ self.game_state['resources']['pesos'] += income
404
+ self.engine.player.skills['rebusque'] += 2
405
+
406
+ return self.advance_day(), f"{chosen_rebusque}. Ganaste ${income} pesos!"
407
+ else:
408
+ self.game_state['resources']['esperanza'] -= 10
409
+ return self.advance_day(), "El rebusque no funcionó hoy. Seguí intentando."
410
+
411
+ def make_asado(self):
412
+ """Hacer asado - tradición argentina que mejora la moral"""
413
+ if self.game_state['resources']['pesos'] >= 1500:
414
+ self.game_state['resources']['pesos'] -= 1500
415
+ self.game_state['resources']['solidaridad'] += 25
416
+ self.game_state['resources']['esperanza'] += 20
417
+
418
+ # Bonus de comunidad
419
+ self.engine.player.community_reputation += 10
420
+
421
+ return self.advance_day(), "Hiciste un asado bárbaro. Todo el barrio vino, mejoró la moral general!"
422
+ else:
423
+ return self.advance_day(), "No tenés suficiente plata para el asado. Seguí juntando."
424
 
425
+ def advance_day(self):
426
+ """Avanza el día con eventos dinámicos"""
427
+ self.game_state['day'] += 1
428
+
429
+ # Inflación diaria
430
+ self.engine.inflation_rate += random.uniform(0.01, 0.05)
431
+
432
+ # Consumo diario
433
+ daily_costs = {
434
+ 'comida': random.randint(5, 15),
435
+ 'pesos': random.randint(100, 500)
436
+ }
437
+
438
+ for resource, cost in daily_costs.items():
439
+ self.game_state['resources'][resource] -= cost
440
+ self.game_state['resources'][resource] = max(0, self.game_state['resources'][resource])
441
+
442
+ # Eventos random
443
+ if random.random() < 0.2:
444
+ self.trigger_random_event()
445
+
446
+ # Cambio de estación
447
+ if self.game_state['day'] % 90 == 0:
448
+ self.change_season()
449
+
450
+ return self.renderer.render_argentina_frame(self.game_state)
451
+
452
+ def trigger_random_event(self):
453
+ """Eventos aleatorios argentinos"""
454
+ events = [
455
+ "Piquete en 9 de Julio - no pudiste trabajar",
456
+ "Encontraste $500 en el subte",
457
+ "El almacenero te fió hasta fin de mes",
458
+ "Ganaste en la quiniela",
459
+ "Se rompió el colectivo - llegaste tarde",
460
+ "Apareció laburo extra en el barrio"
461
+ ]
462
+
463
+ event = random.choice(events)
464
+ self.active_events.append(event)
465
+
466
+ # Aplicar efectos del evento
467
+ if "Piquete" in event:
468
+ self.game_state['resources']['trabajo'] -= 20
469
+ elif "Encontraste $500" in event:
470
+ self.game_state['resources']['pesos'] += 500
471
+ elif "quiniela" in event:
472
+ self.game_state['resources']['pesos'] += random.randint(1000, 5000)
473
+ self.game_state['resources']['esperanza'] += 30
474
+
475
+ def get_game_status(self):
476
+ """Estado completo del juego"""
477
  return {
478
+ "📅 Día": self.game_state['day'],
479
+ "🏠 Barrio": self.game_state['current_neighborhood'].replace('_', ' ').title(),
480
+ "💰 Pesos": f"${self.game_state['resources']['pesos']:.0f}",
481
+ "💵 Dólares": f"US${self.game_state['resources']['dolares']:.0f}",
482
+ "🍖 Comida": f"{self.game_state['resources']['comida']:.0f}%",
483
+ "💪 Esperanza": f"{self.game_state['resources']['esperanza']:.0f}%",
484
+ "🤝 Solidaridad": f"{self.game_state['resources']['solidaridad']:.0f}%",
485
+ "📈 Inflación": f"{self.engine.inflation_rate:.2f}x",
486
+ "🎯 Crisis": f"Nivel {self.game_state['crisis_level']}/5"
487
  }
488
 
489
+ def create_revolutionary_interface():
490
+ game = CrisisYCorajeGame()
491
 
492
  with gr.Blocks(
493
+ title="🇦🇷 CRISIS Y CORAJE - El Juego Argentino Definitivo",
494
+ theme=gr.themes.Soft()
495
  ) as interface:
496
 
497
  gr.HTML("""
498
+ <div style="background: linear-gradient(135deg, #74b9ff, #0984e3, #fdcb6e);
499
+ padding: 25px; text-align: center; border-radius: 15px; margin: 15px;">
500
+ <h1 style="color: white; font-size: 3em; text-shadow: 2px 2px 4px rgba(0,0,0,0.7); margin: 0;">
501
+ 🇦🇷 CRISIS Y CORAJE
502
  </h1>
503
+ <h2 style="color: #ffffff; font-size: 1.3em; margin: 10px 0;">
504
+ Supervivencia, Solidaridad y Cultura en la Argentina Real
505
+ </h2>
506
+ <p style="color: #f1f2f6; font-size: 1.1em; margin: 5px 0;">
507
+ Navegá las crisis económicas mientras preservás lo que nos hace argentinos
508
  </p>
509
  </div>
510
  """)
511
 
512
  with gr.Row():
513
+ with gr.Column(scale=2):
514
  game_display = gr.Image(
515
+ label="🌆 Tu Barrio en Argentina",
516
+ width=900,
 
517
  height=600
518
  )
519
 
520
+ gr.Markdown("### 🎮 ACCIONES ARGENTINAS")
521
  with gr.Row():
522
+ work_btn = gr.Button("💼 TRABAJAR", variant="primary", size="lg")
523
+ help_btn = gr.Button("🤝 AYUDAR VECINOS", variant="secondary", size="lg")
524
+ rebusque_btn = gr.Button("💡 REBUSQUE", variant="stop", size="lg")
525
+
526
  with gr.Row():
527
+ organize_btn = gr.Button("📢 ORGANIZAR", variant="secondary", size="lg")
528
+ save_btn = gr.Button("💵 AHORRAR", variant="primary", size="lg")
529
+ asado_btn = gr.Button("🔥 HACER ASADO", variant="stop", size="lg")
530
 
531
  with gr.Column(scale=1):
532
+ gr.Markdown("### 📊 ESTADO DE SUPERVIVENCIA")
533
  status_display = gr.JSON(
534
+ label="🎯 Tu Situación",
535
+ value=game.get_game_status()
536
  )
537
 
538
+ gr.Markdown("### 📰 ÚLTIMAS NOTICIAS")
539
+ news_display = gr.Textbox(
540
+ value="Bienvenido a tu barrio. La crisis está, pero la solidaridad también. ¿Cómo vas a sobrevivir hoy?",
541
+ label="📺 Canal de Noticias",
542
+ lines=4,
543
+ interactive=False
544
+ )
545
+
546
+ gr.Markdown("### 🎯 TUTORIAL RÁPIDO")
547
  gr.HTML("""
548
+ <div style="background: #2d3436; color: white; padding: 15px; border-radius: 10px;">
549
+ <p><strong>🎮 Cómo Jugar:</strong></p>
550
+ <ul style="margin: 10px 0; padding-left: 20px;">
551
+ <li>💼 <strong>Trabajá</strong> para ganar pesos</li>
552
+ <li>🤝 <strong>Ayudá</strong> para aumentar solidaridad</li>
553
+ <li>💡 <strong>Rebuscátelas</strong> en crisis</li>
554
+ <li>🔥 <strong>Hacé asados</strong> para la moral</li>
555
+ <li>💵 <strong>Ahorrá dólares</strong> contra inflación</li>
556
+ </ul>
557
+ <p><em>¡Sobreviví con creatividad argentina!</em></p>
558
  </div>
559
  """)
 
 
 
 
 
 
 
 
560
 
561
+ # Conectar acciones
562
+ def handle_action(action_name):
563
+ frame, message = game.process_action(action_name)
564
+ status = game.get_game_status()
565
+ return frame, status, message
566
+
567
+ work_btn.click(fn=lambda: handle_action("trabajar"),
568
+ outputs=[game_display, status_display, news_display])
569
+ help_btn.click(fn=lambda: handle_action("ayudar_vecinos"),
570
+ outputs=[game_display, status_display, news_display])
571
+ rebusque_btn.click(fn=lambda: handle_action("buscar_rebusque"),
572
+ outputs=[game_display, status_display, news_display])
573
+ organize_btn.click(fn=lambda: handle_action("organizar_comunitario"),
574
+ outputs=[game_display, status_display, news_display])
575
+ save_btn.click(fn=lambda: handle_action("ahorrar_dolares"),
576
+ outputs=[game_display, status_display, news_display])
577
+ asado_btn.click(fn=lambda: handle_action("hacer_asado"),
578
+ outputs=[game_display, status_display, news_display])
579
 
580
  # Inicialización
581
  interface.load(
582
+ fn=lambda: (game.renderer.render_argentina_frame(game.game_state),
583
+ game.get_game_status(),
584
+ "¡Arrancó el juego! Tomate tu tiempo para pensar cada decisión."),
585
+ outputs=[game_display, status_display, news_display]
586
  )
587
 
588
  return interface
589
 
590
  if __name__ == "__main__":
591
+ interface = create_revolutionary_interface()
592
  interface.launch(share=True, show_error=True)