import random import json import os import gradio as gr class SavingPrivateRyanGame: def __init__(self): self.current_mission = 1 self.total_missions = 4 self.mission_names = [ "Omaha Beach Landing", "Neuville Village: The Sniper", "The Radar Station: The Field", "Ramelle: The Bridge" ] self.player_name = "Captain Miller" self.inventory = ["Thompson SMG", "Colt 1911", "Sticky Bombs"] # Real Movie Squad self.squad = { "Sergeant Horvath": {"status": "Alive", "death_trigger": 550, "mission": 4}, "Private Reiben": {"status": "Alive", "death_trigger": 999, "mission": 4}, # Survivor "Private Jackson": {"status": "Alive", "death_trigger": 450, "mission": 4}, "Private Mellish": {"status": "Alive", "death_trigger": 500, "mission": 4}, "Private Caparzo": {"status": "Alive", "death_trigger": 200, "mission": 2}, "Medic Wade": {"status": "Alive", "death_trigger": 250, "mission": 3}, "Corporal Upham": {"status": "Alive", "death_trigger": 999, "mission": 4} # Survivor } self.miller_alive = True self.ryan_found = False self.game_over = False self.output_text = "" self.reset_mission_stats() def get_chatter(self): living = [n for n, i in self.squad.items() if i["status"] == "Alive"] if not living: return "Miller: 'Move up!'" speaker = random.choice(living) quotes = [ "'FUBAR, Captain. Absolute FUBAR.'", "'Why are we risking eight guys for one?'", "'I've got a bad feeling about that corner.'", "'Just tell us where we're going, Cap.'", "'Keep your head down, Upham!'" ] return f"{speaker}: {random.choice(quotes)}" def reset_mission_stats(self): self.distance = 0 self.bunkers_destroyed = 0 self.tiger_tank_approaching = False configs = { 1: {"map": "BEACH", "obj": 300}, 2: {"map": "VILLAGE", "obj": 400}, 3: {"map": "FOREST", "obj": 500}, 4: {"map": "CITY (RAMELLE)", "obj": 600}, } cfg = configs.get(self.current_mission) self.map_type = cfg["map"] self.mission_objective = cfg["obj"] def process_plot_points(self): """Triggers scripted deaths and events exactly as they happen in the movie.""" event_log = "" # Mission 2: Caparzo if self.current_mission == 2 and self.distance >= 200 and self.squad["Private Caparzo"]["status"] == "Alive": self.squad["Private Caparzo"]["status"] = "Dead" event_log = "⚠️ PLOT EVENT: Rain starts falling. Caparzo tries to help a child—A SNIPER SHOT! Caparzo is down. Jackson counter-snipes the German in the tower." # Mission 3: Wade elif self.current_mission == 3 and self.distance >= 250 and self.squad["Medic Wade"]["status"] == "Alive": self.squad["Medic Wade"]["status"] = "Dead" event_log = "⚠️ PLOT EVENT: Assaulting the MG42 nest. 'MEDIC!' Wade is hit in the liver. The squad tries to save him, but he's gone. Miller releases the German prisoner (Steamship Willie)." # Mission 4: The Final Stand elif self.current_mission == 4: if not self.ryan_found: self.ryan_found = True event_log = "✨ PLOT EVENT: You found Private James Ryan. He refuses to leave his post. The squad stays to defend the bridge." # Scripted deaths during the bridge defense if self.distance >= 450 and self.squad["Private Jackson"]["status"] == "Alive": self.squad["Private Jackson"]["status"] = "Dead" event_log = "⚠️ Jackson is in the bell tower... A Tiger tank levels the tower. Jackson has fallen." if self.distance >= 500 and self.squad["Private Mellish"]["status"] == "Alive": self.squad["Private Mellish"]["status"] = "Dead" event_log = "⚠️ Hand-to-hand combat in the ruins. Mellish is overwhelmed. Upham is frozen in the stairwell..." if self.distance >= 550 and self.squad["Sergeant Horvath"]["status"] == "Alive": self.squad["Sergeant Horvath"]["status"] = "Dead" event_log = "⚠️ Horvath is hit multiple times. He fires one last round at the tank. 'I moved the rock...'" return event_log def miller_sacrifice(self): """The final scene on the bridge.""" self.miller_alive = False self.game_over = True sacrifice_text = """ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 💥 THE FINAL SACRIFICE 💥 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Miller is wounded on the bridge, leaning against a pillar. A Tiger tank rolls toward him. He pulls his Colt 1911 and fires uselessly at the steel. Suddenly—BOOM! A P-51 Mustang 'Tank Buster' screams overhead and vaporizes the Tiger. Reiben finds you. You pull James Ryan close. Miller: 'James... earn this. Earn it.' Captain John H. Miller has died. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ """ return sacrifice_text def make_move(self, action): self.output_text = "" if self.game_over: return self.output_text, "Campaign Finished", gr.update(visible=False) # Movement adv = random.randint(40, 80) if action == "rush" else random.randint(20, 40) self.distance += adv # Check Plot plot_event = self.process_plot_points() if plot_event: self.print_to_output(f"\n{plot_event}\n") self.print_to_output(f"📢 {self.get_chatter()}") # The End Trigger if self.current_mission == 4 and self.distance >= 590: self.print_to_output(self.miller_sacrifice()) return self.output_text, "Earn This.", gr.update(visible=False) # Standard Check show_action = False if self.distance >= (self.bunkers_destroyed + 1) * (self.mission_objective / 3): show_action = True self.print_to_output("\n⚠️ CONTACT: Enemy forces blocking progress!") if action == "assault": self.bunkers_destroyed += 1 self.print_to_output("💥 Clear! Advancing...") self.check_transition() self.print_status() return self.output_text, "Awaiting Command", gr.update(visible=show_action) def print_status(self): living = [n for n, i in self.squad.items() if i["status"] == "Alive"] self.print_to_output(f"\n📍 LOCATION: {self.map_type} | DISTANCE: {self.distance}/{self.mission_objective}m") self.print_to_output(f"👥 SQUAD: Miller, {', '.join(living)}") def check_transition(self): if self.distance >= self.mission_objective and self.current_mission < 4: self.current_mission += 1 self.reset_mission_stats() self.print_to_output(f"\n✅ MISSION COMPLETE. Transitioning to {self.mission_names[self.current_mission-1]}...") def print_to_output(self, text): self.output_text += text + "\n" def start_game(self, _): self.output_text = "June 6, 1944. Dog One Sector. Omaha Beach.\n'CLEAR THE RAMP!'" self.current_mission = 1 self.reset_mission_stats() self.print_status() return self.output_text, "Rangers Lead The Way", gr.update(visible=False) def create_ui(): game = SavingPrivateRyanGame() with gr.Blocks(theme=gr.themes.Monochrome()) as demo: gr.Markdown("# 🎖️ SAVING PRIVATE RYAN: THE COMPLETE JOURNEY") with gr.Row(): with gr.Column(scale=1): start_btn = gr.Button("🚀 Start Campaign", variant="primary") rush_btn = gr.Button("⚡ Advance") with gr.Column(visible=False) as action_row: gr.Markdown("### ⚠️ ENGAGEMENT") assault_btn = gr.Button("💥 Tactical Assault", variant="stop") with gr.Column(scale=2): output = gr.TextArea(label="Radio Log", lines=25) status = gr.Textbox(label="Mission Status") controls = [output, status, action_row] start_btn.click(game.start_game, None, controls) rush_btn.click(lambda: game.make_move("rush"), None, controls) assault_btn.click(lambda: game.make_move("assault"), None, controls) return demo if __name__ == "__main__": create_ui().launch()