Bc-AI commited on
Commit
72833b0
Β·
verified Β·
1 Parent(s): 21ca4e1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +177 -121
app.py CHANGED
@@ -1,148 +1,204 @@
 
 
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()
 
1
+
2
+
3
  import random
4
+ import json
5
+ import os
6
  import gradio as gr
7
 
8
+ class SavingPrivateRyanGame:
9
  def __init__(self):
 
 
10
  self.current_mission = 1
11
+ self.total_missions = 4
12
+ self.mission_names = [
13
+ "Omaha Beach Landing",
14
+ "Neuville Village: The Sniper",
15
+ "The Radar Station: The Field",
16
+ "Ramelle: The Bridge"
17
+ ]
18
 
19
+ self.player_name = "Captain Miller"
20
+ self.inventory = ["Thompson SMG", "Colt 1911", "Sticky Bombs"]
21
+
22
+ # Real Movie Squad
 
 
 
 
 
 
 
23
  self.squad = {
24
+ "Sergeant Horvath": {"status": "Alive", "death_trigger": 550, "mission": 4},
25
+ "Private Reiben": {"status": "Alive", "death_trigger": 999, "mission": 4}, # Survivor
26
+ "Private Jackson": {"status": "Alive", "death_trigger": 450, "mission": 4},
27
+ "Private Mellish": {"status": "Alive", "death_trigger": 500, "mission": 4},
28
+ "Private Caparzo": {"status": "Alive", "death_trigger": 200, "mission": 2},
29
+ "Medic Wade": {"status": "Alive", "death_trigger": 250, "mission": 3},
30
+ "Corporal Upham": {"status": "Alive", "death_trigger": 999, "mission": 4} # Survivor
 
31
  }
 
 
 
 
32
 
33
+ self.miller_alive = True
34
+ self.ryan_found = False
35
+ self.game_over = False
36
+ self.output_text = ""
37
+ self.reset_mission_stats()
 
 
 
 
 
 
38
 
39
  def get_chatter(self):
40
+ living = [n for n, i in self.squad.items() if i["status"] == "Alive"]
41
+ if not living: return "Miller: 'Move up!'"
 
42
  speaker = random.choice(living)
43
  quotes = [
44
+ "'FUBAR, Captain. Absolute FUBAR.'",
45
+ "'Why are we risking eight guys for one?'",
46
+ "'I've got a bad feeling about that corner.'",
47
+ "'Just tell us where we're going, Cap.'",
48
+ "'Keep your head down, Upham!'"
49
  ]
50
+ return f"{speaker}: {random.choice(quotes)}"
51
+
52
+ def reset_mission_stats(self):
53
+ self.distance = 0
54
+ self.bunkers_destroyed = 0
55
+ self.tiger_tank_approaching = False
 
 
 
 
 
 
 
56
 
57
+ configs = {
58
+ 1: {"map": "BEACH", "obj": 300},
59
+ 2: {"map": "VILLAGE", "obj": 400},
60
+ 3: {"map": "FOREST", "obj": 500},
61
+ 4: {"map": "CITY (RAMELLE)", "obj": 600},
62
+ }
63
+ cfg = configs.get(self.current_mission)
64
+ self.map_type = cfg["map"]
65
+ self.mission_objective = cfg["obj"]
66
+
67
+ def process_plot_points(self):
68
+ """Triggers scripted deaths and events exactly as they happen in the movie."""
69
+ event_log = ""
70
 
71
+ # Mission 2: Caparzo
72
+ if self.current_mission == 2 and self.distance >= 200 and self.squad["Private Caparzo"]["status"] == "Alive":
73
+ self.squad["Private Caparzo"]["status"] = "Dead"
74
+ 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."
75
+
76
+ # Mission 3: Wade
77
+ elif self.current_mission == 3 and self.distance >= 250 and self.squad["Medic Wade"]["status"] == "Alive":
78
+ self.squad["Medic Wade"]["status"] = "Dead"
79
+ 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)."
80
 
81
+ # Mission 4: The Final Stand
82
+ elif self.current_mission == 4:
83
+ if not self.ryan_found:
84
+ self.ryan_found = True
85
+ event_log = "✨ PLOT EVENT: You found Private James Ryan. He refuses to leave his post. The squad stays to defend the bridge."
86
+
87
+ # Scripted deaths during the bridge defense
88
+ if self.distance >= 450 and self.squad["Private Jackson"]["status"] == "Alive":
89
+ self.squad["Private Jackson"]["status"] = "Dead"
90
+ event_log = "⚠️ Jackson is in the bell tower... A Tiger tank levels the tower. Jackson has fallen."
91
+
92
+ if self.distance >= 500 and self.squad["Private Mellish"]["status"] == "Alive":
93
+ self.squad["Private Mellish"]["status"] = "Dead"
94
+ event_log = "⚠️ Hand-to-hand combat in the ruins. Mellish is overwhelmed. Upham is frozen in the stairwell..."
95
+
96
+ if self.distance >= 550 and self.squad["Sergeant Horvath"]["status"] == "Alive":
97
+ self.squad["Sergeant Horvath"]["status"] = "Dead"
98
+ event_log = "⚠️ Horvath is hit multiple times. He fires one last round at the tank. 'I moved the rock...'"
99
 
100
+ return event_log
 
 
101
 
102
+ def miller_sacrifice(self):
103
+ """The final scene on the bridge."""
104
+ self.miller_alive = False
105
+ self.game_over = True
106
+ sacrifice_text = """
107
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
108
+ πŸ’₯ THE FINAL SACRIFICE πŸ’₯
109
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
110
+ Miller is wounded on the bridge, leaning against a pillar.
111
+ A Tiger tank rolls toward him. He pulls his Colt 1911 and fires uselessly at the steel.
112
+
113
+ Suddenlyβ€”BOOM! A P-51 Mustang 'Tank Buster' screams overhead and vaporizes the Tiger.
114
+
115
+ Reiben finds you. You pull James Ryan close.
116
+ Miller: 'James... earn this. Earn it.'
117
+
118
+ Captain John H. Miller has died.
119
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
120
+ """
121
+ return sacrifice_text
122
+
123
+ def make_move(self, action):
124
+ self.output_text = ""
125
+ if self.game_over: return self.output_text, "Campaign Finished", gr.update(visible=False)
126
+
127
+ # Movement
128
+ adv = random.randint(40, 80) if action == "rush" else random.randint(20, 40)
129
+ self.distance += adv
130
 
131
+ # Check Plot
132
+ plot_event = self.process_plot_points()
133
+ if plot_event: self.print_to_output(f"\n{plot_event}\n")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
+ self.print_to_output(f"πŸ“’ {self.get_chatter()}")
136
+
137
+ # The End Trigger
138
+ if self.current_mission == 4 and self.distance >= 590:
139
+ self.print_to_output(self.miller_sacrifice())
140
+ return self.output_text, "Earn This.", gr.update(visible=False)
141
+
142
+ # Standard Check
143
+ show_action = False
144
+ if self.distance >= (self.bunkers_destroyed + 1) * (self.mission_objective / 3):
145
+ show_action = True
146
+ self.print_to_output("\n⚠️ CONTACT: Enemy forces blocking progress!")
147
+
148
+ if action == "assault":
149
+ self.bunkers_destroyed += 1
150
+ self.print_to_output("πŸ’₯ Clear! Advancing...")
151
+
152
+ self.check_transition()
153
+ self.print_status()
154
+
155
+ return self.output_text, "Awaiting Command", gr.update(visible=show_action)
156
+
157
+ def print_status(self):
158
+ living = [n for n, i in self.squad.items() if i["status"] == "Alive"]
159
+ self.print_to_output(f"\nπŸ“ LOCATION: {self.map_type} | DISTANCE: {self.distance}/{self.mission_objective}m")
160
+ self.print_to_output(f"πŸ‘₯ SQUAD: Miller, {', '.join(living)}")
161
+
162
+ def check_transition(self):
163
+ if self.distance >= self.mission_objective and self.current_mission < 4:
164
+ self.current_mission += 1
165
+ self.reset_mission_stats()
166
+ self.print_to_output(f"\nβœ… MISSION COMPLETE. Transitioning to {self.mission_names[self.current_mission-1]}...")
167
+
168
+ def print_to_output(self, text):
169
+ self.output_text += text + "\n"
170
+
171
+ def start_game(self, _):
172
+ self.output_text = "June 6, 1944. Dog One Sector. Omaha Beach.\n'CLEAR THE RAMP!'"
173
+ self.current_mission = 1
174
+ self.reset_mission_stats()
175
+ self.print_status()
176
+ return self.output_text, "Rangers Lead The Way", gr.update(visible=False)
177
+
178
+ def create_ui():
179
+ game = SavingPrivateRyanGame()
180
+ with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
181
+ gr.Markdown("# πŸŽ–οΈ SAVING PRIVATE RYAN: THE COMPLETE JOURNEY")
182
 
183
  with gr.Row():
184
+ with gr.Column(scale=1):
185
+ start_btn = gr.Button("πŸš€ Start Campaign", variant="primary")
186
+ rush_btn = gr.Button("⚑ Advance")
187
+
188
+ with gr.Column(visible=False) as action_row:
189
+ gr.Markdown("### ⚠️ ENGAGEMENT")
190
+ assault_btn = gr.Button("πŸ’₯ Tactical Assault", variant="stop")
191
+
192
+ with gr.Column(scale=2):
193
+ output = gr.TextArea(label="Radio Log", lines=25)
194
+ status = gr.Textbox(label="Mission Status")
195
 
196
+ controls = [output, status, action_row]
197
+ start_btn.click(game.start_game, None, controls)
198
+ rush_btn.click(lambda: game.make_move("rush"), None, controls)
199
+ assault_btn.click(lambda: game.make_move("assault"), None, controls)
 
200
 
201
+ return demo
202
 
203
  if __name__ == "__main__":
204
+ create_ui().launch()