Files changed (1) hide show
  1. app.py +122 -575
app.py CHANGED
@@ -1,601 +1,148 @@
1
  import random
2
  import time
3
- import json
4
- import os
5
  import gradio as gr
6
 
7
- class DDayGame:
8
  def __init__(self):
9
- # Campaign and mission tracking
 
10
  self.current_mission = 1
11
  self.total_missions = 5
12
- self.mission_names = [
13
- "Omaha Beach Landing",
14
- "Clearing the Bunkers",
15
- "Inland Advance",
16
- "Crossing the Causeway",
17
- "Capturing the Town"
18
- ]
19
-
20
- # Player stats that carry over between missions
21
- self.player_name = ""
22
- self.rank = "Private"
23
- self.experience = 0
24
- self.level = 1
25
- self.skills = {"leadership": 1, "tactics": 1, "survival": 1}
26
-
27
- # Mission-specific stats
28
- self.reset_mission_stats()
29
-
30
- # Inventory system
31
- self.inventory = {
32
- "weapons": ["Rifle"],
33
- "equipment": ["First Aid Kit", "Grenade"],
34
- "ammunition": 100
35
- }
36
-
37
- # Game state
38
- self.game_over = False
39
- self.campaign_complete = False
40
- self.save_file = "dday_save.json"
41
- self.output_text = ""
42
-
43
- def reset_mission_stats(self):
44
- """Reset mission-specific stats for a new mission"""
45
- self.troops = 100
46
- self.morale = 100
47
- self.distance = 0
48
- self.bunkers_destroyed = 0
49
- self.mission_objective = 100
50
- self.mission_type = "assault"
51
- self.enemies_defeated = 0
52
- self.resources_acquired = 0
53
- self.mission_complete = False
54
-
55
- def print_to_output(self, text):
56
- """Add text to the output display"""
57
- self.output_text += text + "\n"
58
-
59
- def print_status(self):
60
- """Display current game status"""
61
- status = f"""
62
- ╔══════════════════════════════════════════════════════════════╗
63
- ║ {self.player_name:<15} │ {self.rank:<15} │ Lvl: {self.level:<3} ║
64
- ║ XP: {self.experience:<12} │ Troops: {self.troops:<7} │ Morale: {self.morale}% ║
65
- ║ Dist: {self.distance:<11}m │ Mission: {self.current_mission}/{self.total_missions:<6} │ {self.mission_names[self.current_mission-1]:<15} ║
66
- ║ OBJECTIVE: {self.get_objective_description():<38} ║
67
- ╚══════════════════════════════════════════════════════════════╝
68
- """
69
- self.print_to_output(status)
70
-
71
- def get_objective_description(self):
72
- """Get a description of the current mission objective"""
73
- if self.mission_type == "assault":
74
- return f"Reach {self.mission_objective}m"
75
- elif self.mission_type == "bunker":
76
- return f"Destroy {self.mission_objective} bunkers"
77
- elif self.mission_type == "defend":
78
- return f"Survive for {self.mission_objective} turns"
79
- else:
80
- return f"Reach {self.mission_objective}m"
81
-
82
- def print_battlefield_map(self):
83
- """Display a visual representation of the battlefield"""
84
- self.print_to_output("BATTLEFIELD MAP:")
85
- progress_bar_length = 50
86
- progress_symbol = "█"
87
- empty_symbol = "░"
88
-
89
- if self.mission_type == "assault":
90
- progress = min(100, (self.distance / self.mission_objective) * 100)
91
- else:
92
- progress = min(100, (self.bunkers_destroyed / self.mission_objective) * 100) if self.mission_objective > 0 else 0
93
-
94
- filled_length = int(progress_bar_length * progress // 100)
95
- bar = progress_symbol * filled_length + empty_symbol * (progress_bar_length - filled_length)
96
-
97
- self.print_to_output(f"Beach to objective: [{bar}] {progress:.1f}%")
98
-
99
- map_desc = [" "] * progress_bar_length
100
- if self.mission_type == "assault":
101
- bunker_positions = [30, 60, 90, 120, 150, 180]
102
- for pos in bunker_positions:
103
- if pos <= self.mission_objective:
104
- map_pos = int((pos / self.mission_objective) * progress_bar_length)
105
- if 0 <= map_pos < progress_bar_length:
106
- map_desc[map_pos] = "B"
107
-
108
- if self.mission_type == "assault" and self.mission_objective > 0:
109
- current_pos = int((self.distance / self.mission_objective) * progress_bar_length)
110
- if 0 <= current_pos < progress_bar_length:
111
- map_desc[current_pos] = "X"
112
-
113
- self.print_to_output(f" {''.join(map_desc)}")
114
- self.print_to_output("")
115
-
116
- def display_inventory(self):
117
- """Display player inventory"""
118
- inv_text = f"""
119
- INVENTORY:
120
- Weapons: {', '.join(self.inventory['weapons'])}
121
- Equipment: {', '.join(self.inventory['equipment'])}
122
- Ammunition: {self.inventory['ammunition']}
123
- """
124
- self.print_to_output(inv_text)
125
-
126
- def setup_mission(self):
127
- """Set up mission-specific parameters"""
128
- if self.current_mission == 1:
129
- self.mission_type = "assault"
130
- self.mission_objective = 100
131
- self.troops = 100
132
- self.morale = 100
133
- elif self.current_mission == 2:
134
- self.mission_type = "bunker"
135
- self.mission_objective = 5
136
- self.troops = max(30, self.troops)
137
- self.morale = min(100, self.morale + 10)
138
- elif self.current_mission == 3:
139
- self.mission_type = "assault"
140
- self.mission_objective = 200
141
- self.troops = max(20, self.troops)
142
- self.morale = min(100, self.morale)
143
- elif self.current_mission == 4:
144
- self.mission_type = "assault"
145
- self.mission_objective = 150
146
- self.troops = max(15, self.troops)
147
- self.morale = min(100, self.morale)
148
- elif self.current_mission == 5:
149
- self.mission_type = "assault"
150
- self.mission_objective = 100
151
- self.troops = max(10, self.troops)
152
- self.morale = min(100, self.morale)
153
-
154
  self.distance = 0
155
- self.bunkers_destroyed = 0
156
-
157
- def landing(self):
158
- """Initial landing sequence"""
159
- if self.current_mission == 1:
160
- self.print_to_output("\n🎖️ OPERATION OVERLORD - OMAHA BEACH 🎖️")
161
- self.print_to_output("June 6, 1944 - 0630 Hours\n")
162
- self.print_to_output("Your landing craft hits the beach...")
163
- self.print_to_output("The ramp drops. Machine gun fire erupts!")
164
-
165
- casualties = random.randint(10, 25)
166
- self.troops -= casualties
167
- self.morale -= random.randint(5, 15)
168
-
169
- self.print_to_output(f"\n⚠️ Casualties in initial landing: {casualties} troops lost!")
170
- self.print_to_output("You need to push forward!\n")
171
- else:
172
- self.print_to_output(f"\n🎯 MISSION {self.current_mission}: {self.mission_names[self.current_mission-1]}")
173
- self.print_to_output(f"Your remaining troops prepare for the next phase...\n")
174
-
175
- def rush_forward(self):
176
- """Rush forward - risky but fast"""
177
- self.print_to_output("⚡ Your troops charge forward through enemy fire!")
178
- advance = random.randint(15, 25)
179
- casualties = random.randint(5, 15)
180
-
181
- self.distance += advance
182
- self.troops -= casualties
183
- self.morale -= random.randint(5, 10)
184
-
185
- self.print_to_output(f"📍 Advanced {advance}m but lost {casualties} troops!")
186
-
187
- def cautious_advance(self):
188
- """Advance with cover - safer but slower"""
189
- self.print_to_output("🛡️ Your troops move carefully from cover to cover...")
190
- advance = random.randint(8, 15)
191
- casualties = random.randint(2, 8)
192
-
193
- self.distance += advance
194
- self.troops -= casualties
195
- self.morale += random.randint(0, 5)
196
-
197
- self.print_to_output(f"📍 Advanced {advance}m with only {casualties} casualties.")
198
-
199
- def artillery_support(self):
200
- """Call in artillery support"""
201
- self.print_to_output("📻 Radioing the artillery units...")
202
- self.print_to_output("💥 Artillery pounds enemy positions!")
203
-
204
- advance = random.randint(10, 20)
205
- casualties = random.randint(0, 5)
206
- morale_boost = random.randint(10, 20)
207
-
208
- self.distance += advance
209
- self.troops -= casualties
210
- self.morale = min(100, self.morale + morale_boost)
211
-
212
- self.print_to_output(f"✅ Enemy suppressed! Advanced {advance}m. Morale boosted!")
213
-
214
- def regroup(self):
215
- """Regroup and recover"""
216
- self.print_to_output("🏥 Taking a moment to reorganize and help the wounded...")
217
- morale_gain = random.randint(15, 25)
218
-
219
- self.morale = min(100, self.morale + morale_gain)
220
-
221
- self.print_to_output(f"💪 Morale restored by {morale_gain} points!")
222
- self.print_to_output("⏸️ But you didn't advance...")
223
 
224
- def bunker_encounter(self):
225
- """Special bunker assault sequence"""
226
- self.print_to_output("\n🏰 ENEMY BUNKER DETECTED!")
227
- self.print_to_output("A concrete bunker is blocking your advance!\n")
 
 
 
 
 
 
 
 
228
 
229
- def random_event(self):
230
- """Random battlefield events"""
231
- events = [
232
- ("🎖️ Reinforcements arrive from another sector!", 15, 0, 10),
233
- ("🎯 Sniper spotted! Taking cover...", -random.randint(3, 7), 0, -5),
234
- ("✈️ Allied air support flies overhead!", 0, 10, 15),
235
- ("💣 Artillery barrage lands nearby!", -random.randint(5, 12), 0, -10),
236
- ("📣 Officer rallies the troops!", 0, 0, 20),
237
- ("📦 Supply drop landed nearby!", 0, 0, 5, "supply"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
239
 
240
- event = random.choice(events)
241
- self.print_to_output(f"\n🎲 RANDOM EVENT: {event[0]}")
242
- self.troops = max(0, self.troops + event[1])
243
- self.distance += event[2]
244
- self.morale = max(0, min(100, self.morale + event[3]))
245
 
246
- if len(event) > 4 and event[4] == "supply":
247
- new_item = random.choice(["Grenade", "First Aid Kit", "Extra Ammunition"])
248
- self.inventory["equipment"].append(new_item)
249
- self.print_to_output(f"🎁 Found: {new_item}!")
250
-
251
- def check_mission_status(self):
252
- """Check if mission is won or lost"""
253
- if self.troops <= 0:
254
- self.print_to_output("\n💀 All troops lost! Mission failed!")
255
- self.print_to_output("The operation has been compromised...")
256
- self.game_over = True
257
- elif self.morale <= 0:
258
- self.print_to_output("\n😰 Troops are demoralized and retreating!")
259
- self.print_to_output("The assault has been broken!")
260
- self.game_over = True
261
- elif self.mission_type == "assault" and self.distance >= self.mission_objective:
262
- self.mission_complete = True
263
- self.print_to_output(f"\n🎉 MISSION {self.current_mission} COMPLETE!")
264
- self.print_to_output(f"✅ Objective reached! {self.troops} troops survived.")
265
- xp_gained = 50 + (self.troops * 2) + (self.morale // 2)
266
- self.experience += xp_gained
267
- self.print_to_output(f"⭐ Experience gained: {xp_gained}")
268
- self.check_level_up()
269
- elif self.mission_type == "bunker" and self.bunkers_destroyed >= self.mission_objective:
270
- self.mission_complete = True
271
- self.print_to_output(f"\n🎉 MISSION {self.current_mission} COMPLETE!")
272
- self.print_to_output(f"💥 All bunkers destroyed! {self.troops} troops survived.")
273
- xp_gained = 75 + (self.troops * 2) + (self.morale // 2)
274
- self.experience += xp_gained
275
- self.print_to_output(f"⭐ Experience gained: {xp_gained}")
276
- self.check_level_up()
277
-
278
- def check_level_up(self):
279
- """Check if player has leveled up"""
280
- new_level = self.experience // 100 + 1
281
- if new_level > self.level:
282
- self.level = new_level
283
- skill_to_improve = random.choice(list(self.skills.keys()))
284
- self.skills[skill_to_improve] += 1
285
-
286
- if self.level >= 10:
287
- self.rank = "Sergeant Major"
288
- elif self.level >= 8:
289
- self.rank = "Master Sergeant"
290
- elif self.level >= 6:
291
- self.rank = "Sergeant"
292
- elif self.level >= 4:
293
- self.rank = "Corporal"
294
- elif self.level >= 2:
295
- self.rank = "Lance Corporal"
296
-
297
- self.print_to_output(f"\n🆙 LEVEL UP! You are now level {self.level} - {self.rank}!")
298
- self.print_to_output(f"📈 {skill_to_improve.title()} +1")
299
 
300
- def display_skills(self):
301
- """Display player skills"""
302
- skills_text = f"""
303
- 👤 {self.player_name} - {self.rank} (Level {self.level})
304
- ⭐ Experience: {self.experience}
305
 
306
- 💪 Skills:
307
- 🎖️ Leadership: Level {self.skills['leadership']}
308
- 🎯 Tactics: Level {self.skills['tactics']}
309
- 🛡️ Survival: Level {self.skills['survival']}
310
- """
311
- self.print_to_output(skills_text)
312
 
313
- def save_game(self):
314
- """Save game state"""
315
- game_state = {
316
- 'current_mission': self.current_mission,
317
- 'player_name': self.player_name,
318
- 'rank': self.rank,
319
- 'experience': self.experience,
320
- 'level': self.level,
321
- 'skills': self.skills,
322
- 'troops': self.troops,
323
- 'morale': self.morale,
324
- 'distance': self.distance,
325
- 'bunkers_destroyed': self.bunkers_destroyed,
326
- 'inventory': self.inventory
327
- }
328
 
329
- try:
330
- with open(self.save_file, 'w') as f:
331
- json.dump(game_state, f, indent=2)
332
- self.print_to_output("💾 Game saved successfully!")
333
- except Exception as e:
334
- self.print_to_output(f"❌ Error saving game: {str(e)}")
335
-
336
- def load_game(self):
337
- """Load game state"""
338
- try:
339
- if os.path.exists(self.save_file):
340
- with open(self.save_file, 'r') as f:
341
- game_state = json.load(f)
342
-
343
- for key, value in game_state.items():
344
- if hasattr(self, key):
345
- setattr(self, key, value)
346
-
347
- self.print_to_output("📂 Game loaded successfully!")
348
- self.print_to_output(f"Welcome back, {self.player_name}!")
349
- return True
350
  else:
351
- self.print_to_output("❌ No saved game found!")
352
- return False
353
- except Exception as e:
354
- self.print_to_output(f"❌ Error loading game: {str(e)}")
355
- return False
356
-
357
- def next_mission(self):
358
- """Prepare for next mission"""
359
- if self.current_mission < self.total_missions:
360
- self.current_mission += 1
361
- self.reset_mission_stats()
362
- self.setup_mission()
363
- self.landing()
364
- else:
365
- self.campaign_complete = True
366
- self.print_to_output("\n🏆 CONGRATULATIONS! CAMPAIGN COMPLETE! 🏆")
367
- self.print_to_output(f"You helped secure the beachhead!")
368
- self.print_to_output(f"Final: {self.troops} troops, {self.experience} XP")
369
- self.game_over = True
370
-
371
- def start_game(self, player_name_input):
372
- """Initialize new game"""
373
- self.output_text = ""
374
- self.player_name = player_name_input if player_name_input else "Private Ryan"
375
- self.setup_mission()
376
- self.landing()
377
- self.print_status()
378
- self.print_battlefield_map()
379
-
380
- return self.output_text, "Choose your action:", gr.update(visible=False)
381
-
382
- def make_move(self, action):
383
- """Handle player action"""
384
- self.output_text = ""
385
-
386
- if self.game_over:
387
- return self.output_text, "Game Over. Start a new game!", gr.update(visible=False)
388
-
389
- if self.mission_complete:
390
- self.next_mission()
391
- if not self.game_over:
392
- self.print_status()
393
- self.print_battlefield_map()
394
- return self.output_text, "Choose your action:", gr.update(visible=False)
395
-
396
- # Process action
397
- if action == "rush_forward":
398
- self.rush_forward()
399
- elif action == "cautious_advance":
400
- self.cautious_advance()
401
- elif action == "artillery_support":
402
- self.artillery_support()
403
- elif action == "regroup":
404
- self.regroup()
405
- elif action == "check_inventory":
406
- self.display_inventory()
407
- elif action == "view_skills":
408
- self.display_skills()
409
- elif action == "save_game":
410
- self.save_game()
411
- elif action == "load_game":
412
- if self.load_game():
413
- self.print_status()
414
- self.print_battlefield_map()
415
- elif action.startswith("bunker_assault"):
416
- if action == "bunker_assault_1":
417
- if random.random() < (0.7 + self.skills["tactics"] * 0.05):
418
- self.print_to_output("💥 BOOM! Bunker destroyed!")
419
- self.bunkers_destroyed += 1
420
- self.troops -= random.randint(3, 8)
421
- self.morale = min(100, self.morale + 15)
422
- self.experience += 25
423
- else:
424
- self.print_to_output("💀 Engineers were cut down!")
425
- self.troops -= random.randint(10, 18)
426
- self.morale = max(0, self.morale - 10)
427
- elif action == "bunker_assault_2":
428
- casualties = random.randint(15, 25)
429
- self.troops -= casualties
430
- if random.random() < (0.5 + self.skills["leadership"] * 0.05):
431
- self.print_to_output(f"✅ Bunker taken! Cost: {casualties} troops")
432
- self.bunkers_destroyed += 1
433
- self.morale = max(0, self.morale - 5)
434
- self.experience += 20
435
- else:
436
- self.print_to_output(f"❌ Assault failed! Lost {casualties} troops")
437
- self.morale = max(0, self.morale - 15)
438
- elif action == "bunker_assault_3":
439
- if random.random() < (0.8 + self.skills["tactics"] * 0.05):
440
- self.print_to_output("🎯 Perfect flanking! Bunker neutralized!")
441
- self.bunkers_destroyed += 1
442
- self.troops -= random.randint(2, 6)
443
- self.morale = min(100, self.morale + 20)
444
- self.experience += 30
445
- else:
446
- self.print_to_output("⚠️ Flank spotted! Taking casualties!")
447
- self.troops -= random.randint(8, 15)
448
- self.morale = max(0, self.morale - 8)
449
- elif action == "bunker_assault_4":
450
- if "Grenade" in self.inventory["equipment"]:
451
- if random.random() < (0.6 + self.skills["survival"] * 0.05):
452
- self.print_to_output("💣 Grenades did the job!")
453
- self.bunkers_destroyed += 1
454
- self.troops -= random.randint(1, 4)
455
- self.morale = min(100, self.morale + 10)
456
- self.experience += 15
457
- self.inventory["equipment"].remove("Grenade")
458
- else:
459
- self.print_to_output("❌ Grenades didn't penetrate!")
460
- self.troops -= random.randint(5, 10)
461
- self.morale = max(0, self.morale - 5)
462
- else:
463
- self.print_to_output("❌ No grenades available!")
464
-
465
- # Check for encounters
466
- if self.mission_type == "assault" and self.distance in [30, 60, 90]:
467
- self.bunker_encounter()
468
-
469
- # Random events
470
- if random.random() < 0.25:
471
- self.random_event()
472
-
473
- # Check status
474
- self.check_mission_status()
475
-
476
- if not self.game_over and not self.mission_complete:
477
- self.print_status()
478
- self.print_battlefield_map()
479
-
480
- # Show bunker buttons if bunker detected
481
- show_bunker = "BUNKER DETECTED" in self.output_text
482
- next_options = "BUNKER ENCOUNTER! Choose method:" if show_bunker else "Choose your action:"
483
-
484
- return self.output_text, next_options, gr.update(visible=show_bunker)
485
-
486
-
487
- # Create Gradio interface
488
- def create_ui():
489
- game = DDayGame()
490
 
491
- with gr.Blocks(title="D-Day Commander", theme=gr.themes.Soft()) as demo:
492
- gr.Markdown("# 🎖️ D-Day Commander")
493
- gr.Markdown("Lead your troops through the historic D-Day invasion of Normandy!")
494
 
495
  with gr.Row():
496
- with gr.Column(scale=1):
497
- player_name = gr.Textbox(label="Enter your name", value="Private Ryan", placeholder="Your soldier name")
498
- start_btn = gr.Button("🚀 Start New Game", variant="primary", size="lg")
499
-
500
- gr.Markdown("### ⚔️ Combat Actions")
501
- with gr.Row():
502
- rush_btn = gr.Button("⚡ Rush Forward", variant="primary")
503
- cautious_btn = gr.Button("🛡️ Cautious Advance", variant="primary")
504
- artillery_btn = gr.Button("💥 Artillery Support", variant="primary")
505
-
506
- gr.Markdown("### 🔧 Support Actions")
507
- with gr.Row():
508
- regroup_btn = gr.Button("🏥 Regroup", variant="secondary")
509
- inventory_btn = gr.Button("🎒 Check Inventory", variant="secondary")
510
- skills_btn = gr.Button("📊 View Skills", variant="secondary")
511
-
512
- gr.Markdown("### 💾 Game Management")
513
- with gr.Row():
514
- save_btn = gr.Button("💾 Save Game")
515
- load_btn = gr.Button("📂 Load Game")
516
-
517
- gr.Markdown("### 🏰 Bunker Assault Options")
518
- with gr.Column(visible=False) as bunker_row:
519
- engineer_btn = gr.Button("🔧 Engineer Assault", variant="primary")
520
- frontal_btn = gr.Button("⚔️ Frontal Assault", variant="primary")
521
- flank_btn = gr.Button("🎯 Flank Attack", variant="primary")
522
- grenade_btn = gr.Button("💣 Grenade Attack", variant="primary")
523
-
524
- with gr.Column(scale=2):
525
- output = gr.TextArea(label="📜 Game Output", lines=20, max_lines=30, interactive=False)
526
- status = gr.Textbox(label="Current Status", value="Enter your name and click Start!", interactive=False)
527
-
528
- # Event handlers
529
- start_btn.click(
530
- game.start_game,
531
- inputs=[player_name],
532
- outputs=[output, status, bunker_row]
533
- )
534
-
535
- rush_btn.click(
536
- lambda: game.make_move("rush_forward"),
537
- outputs=[output, status, bunker_row]
538
- )
539
-
540
- cautious_btn.click(
541
- lambda: game.make_move("cautious_advance"),
542
- outputs=[output, status, bunker_row]
543
- )
544
-
545
- artillery_btn.click(
546
- lambda: game.make_move("artillery_support"),
547
- outputs=[output, status, bunker_row]
548
- )
549
-
550
- regroup_btn.click(
551
- lambda: game.make_move("regroup"),
552
- outputs=[output, status, bunker_row]
553
- )
554
-
555
- inventory_btn.click(
556
- lambda: game.make_move("check_inventory"),
557
- outputs=[output, status, bunker_row]
558
- )
559
-
560
- skills_btn.click(
561
- lambda: game.make_move("view_skills"),
562
- outputs=[output, status, bunker_row]
563
- )
564
-
565
- save_btn.click(
566
- lambda: game.make_move("save_game"),
567
- outputs=[output, status, bunker_row]
568
- )
569
-
570
- load_btn.click(
571
- lambda: game.make_move("load_game"),
572
- outputs=[output, status, bunker_row]
573
- )
574
-
575
- engineer_btn.click(
576
- lambda: game.make_move("bunker_assault_1"),
577
- outputs=[output, status, bunker_row]
578
- )
579
-
580
- frontal_btn.click(
581
- lambda: game.make_move("bunker_assault_2"),
582
- outputs=[output, status, bunker_row]
583
- )
584
-
585
- flank_btn.click(
586
- lambda: game.make_move("bunker_assault_3"),
587
- outputs=[output, status, bunker_row]
588
- )
589
 
590
- grenade_btn.click(
591
- lambda: game.make_move("bunker_assault_4"),
592
- outputs=[output, status, bunker_row]
 
 
 
 
 
593
  )
594
-
595
- return demo
596
 
 
597
 
598
- # Launch
599
  if __name__ == "__main__":
600
- demo = create_ui()
601
- demo.launch()
 
1
  import random
2
  import time
 
 
3
  import gradio as gr
4
 
5
+ class SavingPrivateRyanDefinitive:
6
  def __init__(self):
7
+ # Game State
8
+ self.mode = "Stable"
9
  self.current_mission = 1
10
  self.total_missions = 5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  self.distance = 0
12
+ self.game_over = False
13
+ self.ryan_found = False
14
+ self.miller_wounded = False
15
+
16
+ # Plot-Specific Locations
17
+ self.missions = {
18
+ 1: {"name": "Omaha Beach", "goal": 300, "desc": "Dog One Sector. The Atlantic Wall."},
19
+ 2: {"name": "Neuville Village", "goal": 400, "desc": "Searching for Ryan. Sniper territory."},
20
+ 3: {"name": "Radar Station", "goal": 500, "desc": "The hills of Normandy. German MG nest ahead."},
21
+ 4: {"name": "Battle of Ramelle", "goal": 600, "desc": "Hold the bridge at all costs."},
22
+ 5: {"name": "Normandy Cemetery", "goal": 100, "desc": "Present Day. Colleville-sur-Mer."}
23
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ # The Actual 2nd Ranger Squad
26
+ # Format: status, death_mission, death_distance, final_words
27
+ self.squad = {
28
+ "Capt. Miller": {"status": "Alive", "death": (4, 590), "words": "James... earn this. Earn it."},
29
+ "Sgt. Horvath": {"status": "Alive", "death": (4, 550), "words": "I moved the rock..."},
30
+ "Pvt. Reiben": {"status": "Alive", "death": (9, 999), "words": "I'm going home."},
31
+ "Pvt. Jackson": {"status": "Alive", "death": (4, 450), "words": "Be not far from me, for trouble is near."},
32
+ "Pvt. Mellish": {"status": "Alive", "death": (4, 500), "words": "Give 'em hell!"},
33
+ "Pvt. Caparzo": {"status": "Alive", "death": (2, 200), "words": "It's for the kid's father."},
34
+ "Medic Wade": {"status": "Alive", "death": (3, 250), "words": "I want to go home... Mama..."},
35
+ "Cpl. Upham": {"status": "Alive", "death": (9, 999), "words": "FUBAR."}
36
+ }
37
 
38
+ def get_beta_visuals(self):
39
+ """Generates the Graphical UI elements for Beta Mode"""
40
+ if self.mode == "Stable": return ""
41
+
42
+ progress = int((self.distance / self.missions[self.current_mission]["goal"]) * 15)
43
+ bar = "█" * progress + "░" * (15 - progress)
44
+
45
+ status_icons = "".join([f"[{n[5:8]}:{'💚' if s['status']=='Alive' else '💀'}]" for n, s in self.squad.items()])
46
+
47
+ visual = f"\n{'='*50}\n"
48
+ visual += f"📍 SECTOR: {self.missions[self.current_mission]['name'].upper()}\n"
49
+ visual += f"🗺️ MAP PROGRESS: |{bar}| {self.distance}m\n"
50
+ visual += f"👥 SQUAD VITALS: {status_icons}\n"
51
+ visual += f"{'='*50}\n"
52
+ return visual
53
+
54
+ def get_chatter(self):
55
+ living = [n for n, s in self.squad.items() if s["status"] == "Alive" and n != "Capt. Miller"]
56
+ if not living: return "Miller: 'Keep moving!'"
57
+
58
+ speaker = random.choice(living)
59
+ quotes = [
60
+ "What's the pool up to? I've got 300 on the Captain.",
61
+ "FUBAR. Everything is FUBAR.",
62
+ "You think Ryan's worth all this?",
63
+ "Keep five yards! Don't bunch up!",
64
+ "I haven't had a decent meal since Portsmouth."
65
  ]
66
+ return f"{speaker}: '{random.choice(quotes)}'"
67
+
68
+ def handle_plot(self):
69
+ plot_log = ""
70
+ # Check for scripted deaths
71
+ for name, info in self.squad.items():
72
+ m_death, d_death = info["death"]
73
+ if self.current_mission == m_death and self.distance >= d_death and info["status"] == "Alive":
74
+ info["status"] = "Dead"
75
+ plot_log += f"\n🚨 CINEMATIC EVENT: {name} has been hit! {info['words']}\n"
76
+
77
+ if name == "Capt. Miller":
78
+ self.miller_wounded = True
79
 
80
+ # Plot Beats
81
+ if self.current_mission == 3 and self.distance > 300:
82
+ plot_log += "\n📖 STORY: Miller stops the squad's infighting. 'I'm a schoolteacher from Pennsylvania.' The squad goes silent.\n"
 
 
83
 
84
+ if self.current_mission == 4 and self.distance > 100 and not self.ryan_found:
85
+ self.ryan_found = True
86
+ plot_log += "\n✨ STORY: Private James Francis Ryan found. He won't leave his post. Miller: 'Rally on the bridge!'\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
+ return plot_log
 
 
 
 
89
 
90
+ def play(self, action, mode):
91
+ self.mode = mode
92
+ if self.game_over: return "The mission is over. James Ryan is home.", "End of File"
 
 
 
93
 
94
+ # Movement and Narrative
95
+ advance = random.randint(45, 85)
96
+ self.distance += advance
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
+ # Build Output
99
+ output = self.get_beta_visuals()
100
+ output += f"\n📢 {self.get_chatter()}\n"
101
+ output += self.handle_plot()
102
+
103
+ # Check Mission Completion
104
+ if self.distance >= self.missions[self.current_mission]["goal"]:
105
+ if self.current_mission < self.total_missions:
106
+ self.current_mission += 1
107
+ self.distance = 0
108
+ output += f"\n✅ MISSION COMPLETE. Transitioning to {self.missions[self.current_mission]['name']}...\n"
 
 
 
 
 
 
 
 
 
 
109
  else:
110
+ self.game_over = True
111
+ output += "\n🕊️ FINAL SCENE: 'Tell me I'm a good man.' Ryan salutes the grave. Fade to black.\n"
112
+
113
+ # Special Death Logic for Miller
114
+ if self.miller_wounded:
115
+ output += "\n🎬 [BETA]: P-51 Mustangs scream overhead. The Tiger tank is destroyed. Miller looks at Ryan... 'Earn this.'\n"
116
+ self.current_mission = 5 # Skip to Cemetery
117
+ self.distance = 0
118
+ self.miller_wounded = False
119
+
120
+ status_str = f"Mission {self.current_mission}: {self.missions[self.current_mission]['name']}"
121
+ return output, status_str
122
+
123
+ # UI Assembly
124
+ def run_app():
125
+ game_engine = SavingPrivateRyanDefinitive()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
+ with gr.Blocks(theme=gr.themes.Monochrome(), title="Saving Private Ryan") as demo:
128
+ gr.Markdown("# 🎖️ SAVING PRIVATE RYAN: THE DEFINITIVE CAMPAIGN")
129
+ gr.Markdown("Experience the full journey from Omaha Beach to the final sacrifice.")
130
 
131
  with gr.Row():
132
+ mode_select = gr.Radio(["Stable", "Beta"], label="Interface", value="Beta")
133
+ action_btn = gr.Button("ADVANCE SQUAD", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
+ with gr.Row():
136
+ text_output = gr.TextArea(label="Battlefield Journal", lines=22)
137
+ meta_status = gr.Textbox(label="Current Objective")
138
+
139
+ action_btn.click(
140
+ game_engine.play,
141
+ inputs=[gr.State("move"), mode_select],
142
+ outputs=[text_output, meta_status]
143
  )
 
 
144
 
145
+ demo.launch()
146
 
 
147
  if __name__ == "__main__":
148
+ run_app()