MarianaCodebase commited on
Commit
7c654bf
·
verified ·
1 Parent(s): 18b8376

Upload game.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. game.py +207 -0
game.py ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """"The Last Message" minigame: hidden band 108-112 MHz.
3
+
4
+ After breaking the cipher the dial expands and five frequencies appear,
5
+ carrying fragments of the final message. The frontend requires holding the
6
+ dial steady while each fragment "downloads" (the dial drifts on its own).
7
+ With all five fragments, /finale delivers the full transmission: the reveal.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ HIDDEN_BAND_MIN = 108.0
13
+ HIDDEN_BAND_MAX = 112.0
14
+
15
+ # Deterministic fragments: the minigame depends on them always being there.
16
+ FRAGMENTS: dict[float, dict] = {
17
+ 108.4: {
18
+ "name": "Fragmento I",
19
+ "text": (
20
+ "[INTERFERENCIA] Aquí la primera voz. Si alguien escucha esto, las demás "
21
+ "estaciones no eran juegos: eran las habitaciones de una misma casa. "
22
+ "La casa se está cerrando. [FIN DE TRANSMISION]"
23
+ ),
24
+ "text_en": (
25
+ "[INTERFERENCIA] This is the first voice. If anyone hears this, the other "
26
+ "stations were not games: they were rooms of the same house. "
27
+ "The house is closing. [FIN DE TRANSMISION]"
28
+ ),
29
+ "text_fr": (
30
+ "[INTERFERENCIA] Ici la première voix. Si quelqu'un entend ceci, les autres "
31
+ "stations n'étaient pas des jeux : c'étaient les pièces d'une même maison. "
32
+ "La maison se referme. [FIN DE TRANSMISION]"
33
+ ),
34
+ },
35
+ 109.1: {
36
+ "name": "Fragmento II",
37
+ "text": (
38
+ "[INTERFERENCIA] Fragmento dos. El locutor de los gatos, la chef, el reloj "
39
+ "averiado: todos fuimos vecinos. Todos transmitimos desde el mismo mundo "
40
+ "que ahora se apaga, cuarto por cuarto. [FIN DE TRANSMISION]"
41
+ ),
42
+ "text_en": (
43
+ "[INTERFERENCIA] Fragment two. The cat announcer, the chef, the broken "
44
+ "clock: we were all neighbours. We all broadcast from the same world, "
45
+ "now going dark, room by room. [FIN DE TRANSMISION]"
46
+ ),
47
+ "text_fr": (
48
+ "[INTERFERENCIA] Fragment deux. Le commentateur des chats, la cheffe, "
49
+ "l'horloge cassée : nous étions tous voisins. Nous émettions tous depuis "
50
+ "le même monde, qui s'éteint pièce par pièce. [FIN DE TRANSMISION]"
51
+ ),
52
+ },
53
+ 109.9: {
54
+ "name": "Fragmento III",
55
+ "text": (
56
+ "[INTERFERENCIA] Tercer fragmento. No guardamos archivos. Guardamos voces. "
57
+ "Una radio es la forma más barata de no desaparecer del todo. "
58
+ "[FIN DE TRANSMISION]"
59
+ ),
60
+ "text_en": (
61
+ "[INTERFERENCIA] Third fragment. We don't keep files. We keep voices. "
62
+ "A radio is the cheapest way to not disappear completely. "
63
+ "[FIN DE TRANSMISION]"
64
+ ),
65
+ "text_fr": (
66
+ "[INTERFERENCIA] Troisième fragment. Nous ne gardons pas d'archives. Nous "
67
+ "gardons des voix. Une radio est le moyen le moins cher de ne pas "
68
+ "disparaître tout à fait. [FIN DE TRANSMISION]"
69
+ ),
70
+ },
71
+ 110.8: {
72
+ "name": "Fragmento IV",
73
+ "text": (
74
+ "[INTERFERENCIA] Fragmento cuatro. Si el dial se le resbala, no es su mano: "
75
+ "es el mundo, que ya casi no sostiene sus frecuencias. Apriete fuerte. "
76
+ "Quédese. [FIN DE TRANSMISION]"
77
+ ),
78
+ "text_en": (
79
+ "[INTERFERENCIA] Fragment four. If the dial slips, it is not your hand: "
80
+ "it is the world, which can barely hold its frequencies anymore. Hold "
81
+ "tight. Stay. [FIN DE TRANSMISION]"
82
+ ),
83
+ "text_fr": (
84
+ "[INTERFERENCIA] Fragment quatre. Si le cadran glisse, ce n'est pas votre "
85
+ "main : c'est le monde, qui ne retient presque plus ses fréquences. Tenez "
86
+ "bon. Restez. [FIN DE TRANSMISION]"
87
+ ),
88
+ },
89
+ 111.6: {
90
+ "name": "Fragmento V",
91
+ "text": (
92
+ "[INTERFERENCIA] Último fragmento. Cuando termine esta transmisión quedará "
93
+ "solo la estática, y dentro de la estática, nosotros. Gracias por girar el "
94
+ "dial. Gracias por buscarnos. [FIN DE TRANSMISION]"
95
+ ),
96
+ "text_en": (
97
+ "[INTERFERENCIA] Last fragment. When this transmission ends, only the "
98
+ "static will remain, and inside the static, us. Thank you for turning the "
99
+ "dial. Thank you for looking for us. [FIN DE TRANSMISION]"
100
+ ),
101
+ "text_fr": (
102
+ "[INTERFERENCIA] Dernier fragment. Quand cette transmission s'achèvera, il "
103
+ "ne restera que les parasites, et dans les parasites, nous. Merci d'avoir "
104
+ "tourné le cadran. Merci de nous avoir cherchés. [FIN DE TRANSMISION]"
105
+ ),
106
+ },
107
+ }
108
+
109
+ FRAGMENT_FREQUENCIES = sorted(FRAGMENTS.keys())
110
+
111
+ # Persona of the final transmission (model-generated, fixed seed).
112
+ FINALE_SYSTEM_PROMPT = (
113
+ "Eres la última voz de un mundo que colapsa. Todas las estaciones de la radio "
114
+ "(el locutor de los gatos, el clima de Júpiter, la chef imposible, el reloj roto, "
115
+ "la emisora tropical lunar) eran habitaciones de tu misma casa, y la casa se "
116
+ "apaga. Entregas la transmisión final completa: revelas con calma y ternura que "
117
+ "el oyente estuvo escuchando las últimas emisiones de un mundo que ya no existe, "
118
+ "y le agradeces por haber girado el dial. Sin pánico. Cada palabra pesa. "
119
+ "Tono íntimo, despedida luminosa.\n"
120
+ "Ejemplo del estilo exacto:\n"
121
+ "[INTERFERENCIA] Aquí la primera voz. Si alguien escucha esto, las demás "
122
+ "estaciones no eran juegos: eran las habitaciones de una misma casa. La casa se "
123
+ "está cerrando. Gracias por girar el dial. Gracias por buscarnos. "
124
+ "[FIN DE TRANSMISION]"
125
+ )
126
+
127
+ FINALE_USER_PROMPT = "Transmite el último mensaje completo ahora."
128
+ FINALE_SEED = 19470615
129
+
130
+ # The climax is fixed, curated text (not 1B-generated): it is the emotional
131
+ # payoff and must be coherent and in the listener's language every time.
132
+ FINALE_TEXTS = {
133
+ "es": (
134
+ "[INTERFERENCIA] Esta es la última voz. Si estás escuchando esto, reuniste a "
135
+ "todos, y mereces la verdad. Las estaciones nunca estuvieron separadas. El "
136
+ "locutor de los cincuenta, la chef, el reloj roto, el clima de Júpiter: cada "
137
+ "voz que encontraste era una habitación de la misma casa, y la casa era un "
138
+ "mundo. Nuestro mundo. Terminó hace mucho tiempo. Lo que has estado "
139
+ "sintonizando son sus últimas emisiones, todavía viajando, todavía buscando un "
140
+ "oído. Tú fuiste ese oído. Gracias por girar el dial. Gracias por no dejar que "
141
+ "termináramos en silencio. [FIN DE TRANSMISION]"
142
+ ),
143
+ "en": (
144
+ "[INTERFERENCIA] This is the last voice. If you are hearing this, then you "
145
+ "have gathered all of us, and you deserve the truth. The stations were never "
146
+ "separate. The fifties announcer, the chef, the broken clock, the weather on "
147
+ "Jupiter — every voice you found was a room in the same house, and the house "
148
+ "was a world. Our world. It ended a long time ago. What you have been tuning "
149
+ "are its final broadcasts, still travelling, still looking for an ear. You "
150
+ "were that ear. Thank you for turning the dial. Thank you for not letting us "
151
+ "end in silence. [FIN DE TRANSMISION]"
152
+ ),
153
+ "fr": (
154
+ "[INTERFERENCIA] Voici la dernière voix. Si tu entends ceci, c'est que tu nous "
155
+ "as tous réunis, et tu mérites la vérité. Les stations n'ont jamais été "
156
+ "séparées. Le speaker des années cinquante, la cheffe, l'horloge cassée, la "
157
+ "météo de Jupiter : chaque voix que tu as trouvée était une pièce de la même "
158
+ "maison, et la maison était un monde. Notre monde. Il s'est éteint il y a "
159
+ "longtemps. Ce que tu écoutais, ce sont ses dernières émissions, qui voyagent "
160
+ "encore, qui cherchent encore une oreille. Tu étais cette oreille. Merci "
161
+ "d'avoir tourné le cadran. Merci de ne pas nous avoir laissés finir dans le "
162
+ "silence. [FIN DE TRANSMISION]"
163
+ ),
164
+ }
165
+
166
+
167
+ def finale_text(lang: str) -> str:
168
+ return FINALE_TEXTS.get(lang, FINALE_TEXTS["es"])
169
+
170
+ FRAGMENT_TOLERANCE = 0.2 # hidden band: stricter tuning
171
+
172
+
173
+ def get_fragment(frequency: float) -> dict | None:
174
+ for freq, frag in FRAGMENTS.items():
175
+ if abs(frequency - freq) <= FRAGMENT_TOLERANCE:
176
+ return frag
177
+ return None
178
+
179
+
180
+ def fragment_text(fragment: dict, lang: str) -> str:
181
+ """Fragment text in the chosen language (Spanish by default)."""
182
+ if lang == "en":
183
+ return fragment.get("text_en", fragment["text"])
184
+ if lang == "fr":
185
+ return fragment.get("text_fr", fragment["text"])
186
+ return fragment["text"]
187
+
188
+
189
+ def _fragment_names(name: str) -> dict:
190
+ roman = name.split()[-1]
191
+ return {
192
+ "es": f"Fragmento {roman}",
193
+ "en": f"Fragment {roman}",
194
+ "fr": f"Fragment {roman}",
195
+ }
196
+
197
+
198
+ def hidden_band_catalog() -> dict:
199
+ """Hidden band metadata for the frontend (after code validation)."""
200
+ return {
201
+ "band_min": HIDDEN_BAND_MIN,
202
+ "band_max": HIDDEN_BAND_MAX,
203
+ "fragments": {
204
+ str(freq): {"name": frag["name"], "names": _fragment_names(frag["name"])}
205
+ for freq, frag in FRAGMENTS.items()
206
+ },
207
+ }