Mercurial > pyntnclick
comparison gamelib/scenes/engine.py @ 854:3577c51029f1 default tip
Remove Suspended Sentence. pyntnclick is the library we extracted from it
author | Stefano Rivera <stefano@rivera.za.net> |
---|---|
date | Sat, 21 Jun 2014 22:15:54 +0200 |
parents | f95830b58336 |
children |
comparison
equal
deleted
inserted
replaced
853:f95830b58336 | 854:3577c51029f1 |
---|---|
1 """Engine room where things need to be repaired.""" | |
2 | |
3 from pyntnclick.i18n import _ | |
4 from pyntnclick.cursor import CursorSprite | |
5 from pyntnclick.utils import render_text | |
6 from pyntnclick.state import Scene, Item, Thing, Result | |
7 from pyntnclick.scenewidgets import ( | |
8 InteractNoImage, InteractRectUnion, InteractImage, InteractAnimated, | |
9 GenericDescThing, TakeableThing) | |
10 | |
11 from gamelib.scenes.game_constants import PLAYER_ID | |
12 from gamelib.scenes.game_widgets import Door, make_jim_dialog | |
13 | |
14 | |
15 class Engine(Scene): | |
16 | |
17 FOLDER = "engine" | |
18 BACKGROUND = "engine_room.png" | |
19 | |
20 INITIAL_DATA = { | |
21 'engine online': False, | |
22 'greet': True, | |
23 } | |
24 | |
25 def setup(self): | |
26 self.add_item_factory(CanOpener) | |
27 self.add_thing(CanOpenerThing()) | |
28 self.add_thing(SuperconductorSocket()) | |
29 self.add_thing(PowerLines()) | |
30 self.add_thing(CryoContainers()) | |
31 self.add_thing(CryoContainerReceptacle()) | |
32 self.add_thing(CoolingPipes()) | |
33 self.add_thing(ArrowsTopLeft()) | |
34 self.add_thing(ArrowsBottomLeft()) | |
35 self.add_thing(ArrowsRight()) | |
36 self.add_thing(DangerSign()) | |
37 self.add_thing(Stars()) | |
38 self.add_thing(CrackedPipe()) | |
39 self.add_thing(ComputerConsole()) | |
40 self.add_thing(ToMap()) | |
41 self.add_thing(GenericDescThing('engine.body', 1, | |
42 _("Dead. Those cans must have been past their sell-by date."), | |
43 ( | |
44 (594, 387, 45, 109), | |
45 (549, 479, 60, 55), | |
46 ) | |
47 )) | |
48 self.add_thing(GenericDescThing('engine.superconductors', 4, | |
49 _("Superconductors. The engines must be power hogs."), | |
50 ( | |
51 (679, 246, 50, 56), | |
52 (473, 280, 28, 23), | |
53 (381, 224, 25, 22), | |
54 ) | |
55 )) | |
56 self.add_thing(GenericDescThing('engine.floor_hole', 5, | |
57 _("A gaping hole in the floor of the room. " | |
58 "It is clearly irreparable."), | |
59 ( | |
60 (257, 493, 141, 55), | |
61 (301, 450, 95, 45), | |
62 (377, 422, 19, 29), | |
63 (239, 547, 123, 39), | |
64 ) | |
65 )) | |
66 self.add_thing(GenericDescThing('engine.empty_cans', 7, | |
67 _("Empty chocolate-covered bacon cans? Poor guy, he must have" | |
68 " found them irresistible."), | |
69 ( | |
70 (562, 422, 30, 31), | |
71 ) | |
72 )) | |
73 if not self.get_data('engine online'): | |
74 self.add_thing(GenericDescThing('engine.engines', 8, | |
75 _("The engines. They don't look like they are working."), | |
76 ( | |
77 (342, 261, 109, 81), | |
78 ) | |
79 )) | |
80 self.add_thing(GenericDescThing('engine.laser_cutter', 9, | |
81 _("A burned-out laser cutter. It may be responsible for the" | |
82 " hole in the floor."), | |
83 ( | |
84 (120, 466, 115, 67), | |
85 ) | |
86 )) | |
87 self.add_thing(GenericDescThing('engine.fuel_lines', 10, | |
88 _("The main fuel line for the engines."), | |
89 ( | |
90 (220, 49, 59, 75), | |
91 (239, 84, 51, 66), | |
92 (271, 113, 28, 53), | |
93 (285, 132, 26, 50), | |
94 (299, 153, 22, 46), | |
95 (321, 172, 167, 25), | |
96 (308, 186, 36, 22), | |
97 (326, 217, 30, 13), | |
98 (336, 229, 28, 13), | |
99 (343, 239, 21, 14), | |
100 (446, 197, 33, 11), | |
101 (424, 240, 21, 20), | |
102 (418, 249, 19, 11), | |
103 (438, 217, 30, 11), | |
104 (435, 225, 18, 15), | |
105 ) | |
106 )) | |
107 self.add_thing(GenericDescThing('engine.spare_fuel_line', 11, | |
108 _("The spare fuel line. If something went wrong with the main" | |
109 " one, you would hook that one up."), | |
110 ( | |
111 (512, 49, 68, 44), | |
112 ) | |
113 )) | |
114 self.add_thing(GenericDescThing('engine.danger_area', 12, | |
115 _("The sign says DANGER. You would be wise to listen to it."), | |
116 ( | |
117 (293, 343, 211, 46), | |
118 ) | |
119 )) | |
120 self.add_thing(GenericDescThing('engine.exit_sign', 13, | |
121 _("It's one of those glow-in-the-dark signs needed to satisfy the " | |
122 "health and safety inspectors."), | |
123 ( | |
124 (681, 322, 80, 33), | |
125 ) | |
126 )) | |
127 | |
128 def engine_online_check(self): | |
129 if (self.things['engine.cryo_containers'].get_data('filled') | |
130 and self.things['engine.superconductor'].get_data('working')): | |
131 self.set_data('engine online', True) | |
132 self.remove_thing(self.things['engine.engines.8']) | |
133 self.add_thing(Engines()) | |
134 return make_jim_dialog(_("The engines are now operational. You" | |
135 " have done a satisfactory job, Prisoner" | |
136 " %s.") % PLAYER_ID, self.game) | |
137 | |
138 def enter(self): | |
139 if self.get_data('greet'): | |
140 self.set_data('greet', False) | |
141 return Result( | |
142 _("With your improvised helmet, the automatic airlock" | |
143 " allows you into the engine room. Even if there wasn't" | |
144 " a vacuum it would be eerily quiet.")) | |
145 | |
146 | |
147 class Engines(Thing): | |
148 NAME = 'engine.engines' | |
149 | |
150 INTERACTS = { | |
151 'on': InteractImage(334, 253, 'engine_on.png'), | |
152 } | |
153 | |
154 INITIAL = 'on' | |
155 | |
156 def is_interactive(self, tool=None): | |
157 return False | |
158 | |
159 def get_description(self): | |
160 return _("All systems are go! Or at least the engines are.") | |
161 | |
162 | |
163 class CanOpener(Item): | |
164 NAME = 'canopener' | |
165 INVENTORY_IMAGE = 'can_opener.png' | |
166 CURSOR = CursorSprite('can_opener_cursor.png') | |
167 | |
168 | |
169 class CanOpenerThing(TakeableThing): | |
170 NAME = 'engine.canopener' | |
171 | |
172 INTERACTS = { | |
173 'canopener': InteractImage(565, 456, 'can_opener.png'), | |
174 } | |
175 | |
176 INITIAL = 'canopener' | |
177 ITEM = 'canopener' | |
178 | |
179 def get_description(self): | |
180 return _("A can opener. Looks like you won't be starving") | |
181 | |
182 def interact_without(self): | |
183 self.take() | |
184 return Result(_("You pick up the can opener. It looks brand new; " | |
185 "the vacuum has kept it in perfect condition.")) | |
186 | |
187 | |
188 class SuperconductorSocket(Thing): | |
189 NAME = 'engine.superconductor' | |
190 | |
191 INTERACTS = { | |
192 'broken': InteractImage(553, 260, 'superconductor_broken.png'), | |
193 'removed': InteractImage(553, 260, 'superconductor_socket.png'), | |
194 'fixed': InteractImage(553, 260, 'superconductor_fixed.png'), | |
195 } | |
196 | |
197 INITIAL = 'broken' | |
198 | |
199 INITIAL_DATA = { | |
200 'present': True, | |
201 'working': False, | |
202 } | |
203 | |
204 def get_description(self): | |
205 if self.get_data('present') and not self.get_data('working'): | |
206 return _("That superconductor looks burned out. It's wedged" | |
207 " in there pretty firmly.") | |
208 elif not self.get_data('present'): | |
209 return _("An empty superconductor socket") | |
210 else: | |
211 return _("A working superconductor.") | |
212 | |
213 def select_interact(self): | |
214 if not self.get_data('present'): | |
215 return 'removed' | |
216 if self.get_data('working'): | |
217 return 'fixed' | |
218 return self.INITIAL | |
219 | |
220 def interact_without(self): | |
221 if self.get_data('present') and not self.get_data('working'): | |
222 return Result(_("It's wedged in there pretty firmly, it won't" | |
223 " come out.")) | |
224 elif self.get_data('working'): | |
225 return Result(_("You decide that working engines are more" | |
226 " important than having a shiny superconductor.")) | |
227 | |
228 def interact_with_machete(self, item): | |
229 if self.get_data('present') and not self.get_data('working'): | |
230 self.set_data('present', False) | |
231 self.set_interact() | |
232 return Result(_("With leverage, the burned-out superconductor" | |
233 " snaps out. You discard it.")) | |
234 | |
235 def interact_with_superconductor(self, item): | |
236 if self.get_data('present'): | |
237 return Result(_("It might help to remove the broken" | |
238 " superconductor first")) | |
239 else: | |
240 return Result(_("You plug in the superconductor, and feel a hum " | |
241 "as things kick into life. Unfortunately, it's " | |
242 "the wrong size for the socket and just falls " | |
243 "out again when you let go.")) | |
244 | |
245 def interact_with_taped_superconductor(self, item): | |
246 if not self.get_data('present'): | |
247 self.set_data('present', True) | |
248 self.set_data('working', True) | |
249 self.set_interact() | |
250 self.game.remove_inventory_item(item.name) | |
251 results = [Result(_("The chair's superconductor looks over-specced" | |
252 " for this job, but it should work."))] | |
253 results.append(self.scene.engine_online_check()) | |
254 return results | |
255 else: | |
256 return Result(_("It might help to remove the broken superconductor" | |
257 " first.")) | |
258 | |
259 | |
260 class CryoContainers(Thing): | |
261 NAME = 'engine.cryo_containers' | |
262 | |
263 INTERACTS = { | |
264 'empty': InteractImage(118, 211, 'cryo_empty.png'), | |
265 'full': InteractImage(118, 211, 'cryo_full.png'), | |
266 } | |
267 | |
268 INITIAL = 'empty' | |
269 | |
270 INITIAL_DATA = { | |
271 'filled': False, | |
272 } | |
273 | |
274 def select_interact(self): | |
275 if self.get_data('filled'): | |
276 return 'full' | |
277 return self.INITIAL | |
278 | |
279 def get_description(self): | |
280 if not self.get_data('filled'): | |
281 return _("Those are coolant reservoirs. They look empty.") | |
282 return _("The coolant reservoirs are full.") | |
283 | |
284 def is_interactive(self, tool=None): | |
285 return False | |
286 | |
287 | |
288 class CryoContainerReceptacle(Thing): | |
289 NAME = 'engine.cryo_container_receptacle' | |
290 | |
291 INTERACTS = { | |
292 'containers': InteractRectUnion(( | |
293 (132, 250, 56, 28), | |
294 (184, 258, 42, 30), | |
295 (219, 267, 42, 24), | |
296 )), | |
297 } | |
298 | |
299 INITIAL = 'containers' | |
300 | |
301 def get_description(self): | |
302 return _("The receptacles for the coolant reservoirs.") | |
303 | |
304 def interact_without(self): | |
305 return Result(_("You stick your finger in the receptacle. " | |
306 "It almost gets stuck.")) | |
307 | |
308 def interact_with_full_detergent_bottle(self, item): | |
309 if not self.scene.things['engine.cracked_pipe'].get_data('fixed'): | |
310 return Result(_("Pouring the precious cryo fluid into a" | |
311 " container connected to a cracked pipe would be a" | |
312 " waste.")) | |
313 self.game.remove_inventory_item(item.name) | |
314 self.scene.things['engine.cryo_containers'].set_data('filled', True) | |
315 self.scene.things['engine.cryo_containers'].set_interact() | |
316 results = [Result(_("You fill the reservoirs. " | |
317 "The detergent bottle was just big enough, which " | |
318 "is handy, because it's sprung a leak."))] | |
319 results.append(self.scene.engine_online_check()) | |
320 return results | |
321 | |
322 | |
323 class CoolingPipes(Thing): | |
324 NAME = 'engine.coolingpipes' | |
325 | |
326 INTERACTS = { | |
327 'pipes': InteractRectUnion(( | |
328 (262, 209, 315, 7), | |
329 (693, 155, 14, 90), | |
330 (673, 138, 32, 27), | |
331 (649, 155, 25, 21), | |
332 (608, 177, 23, 18), | |
333 (587, 186, 25, 18), | |
334 (570, 195, 27, 20), | |
335 (625, 167, 28, 18), | |
336 (57, 86, 16, 238), | |
337 (227, 188, 31, 49), | |
338 (71, 91, 39, 36), | |
339 (108, 117, 32, 69), | |
340 (140, 135, 31, 64), | |
341 (168, 156, 33, 57), | |
342 (200, 172, 27, 55), | |
343 (105, 159, 15, 289), | |
344 (0, 309, 128, 16), | |
345 (79, 390, 28, 22), | |
346 (257, 209, 27, 10), | |
347 (249, 225, 26, 20), | |
348 (272, 237, 25, 17), | |
349 (294, 247, 41, 24), | |
350 (333, 254, 35, 6), | |
351 (364, 235, 7, 25), | |
352 (365, 231, 15, 13), | |
353 (121, 403, 70, 38), | |
354 (180, 392, 33, 19), | |
355 (199, 383, 30, 18), | |
356 (219, 378, 20, 10), | |
357 (232, 370, 18, 11), | |
358 )), | |
359 } | |
360 INITIAL = 'pipes' | |
361 | |
362 def get_description(self): | |
363 if not self.scene.things['engine.cryo_containers'].get_data('filled'): | |
364 return _("These pipes carry coolant to the superconductors. " | |
365 "They feel warm.") | |
366 return _("These pipes carry coolant to the superconductors. " | |
367 "They are very cold.") | |
368 | |
369 def is_interactive(self, tool=None): | |
370 return False | |
371 | |
372 | |
373 class PowerLines(Thing): | |
374 NAME = 'engine.powerlines' | |
375 | |
376 INTERACTS = { | |
377 'lines': InteractRectUnion(( | |
378 (592, 270, 87, 21), | |
379 (605, 259, 74, 14), | |
380 (502, 280, 63, 13), | |
381 (527, 272, 38, 11), | |
382 (454, 229, 38, 11), | |
383 (480, 232, 13, 45), | |
384 (407, 229, 27, 10), | |
385 )), | |
386 } | |
387 | |
388 INITIAL = 'lines' | |
389 | |
390 def get_description(self): | |
391 if self.scene.things['engine.superconductor'].get_data('working'): | |
392 return _("Power lines. They are delivering power to the engines.") | |
393 return _("Power lines. It looks like they aren't working correctly.") | |
394 | |
395 def is_interactive(self, tool=None): | |
396 return False | |
397 | |
398 | |
399 class ArrowsTopLeft(Thing): | |
400 NAME = 'engine.arrows_top_left' | |
401 | |
402 INTERACTS = { | |
403 'arrows': InteractAnimated(25, 324, ( | |
404 'arrow_top_left_1.png', 'arrow_top_left_2.png', | |
405 'arrow_top_left_3.png', 'arrow_top_left_4.png', | |
406 ), 15, | |
407 ), | |
408 } | |
409 | |
410 INITIAL = 'arrows' | |
411 | |
412 def is_interactive(self, tool=None): | |
413 return False | |
414 | |
415 | |
416 class ArrowsBottomLeft(Thing): | |
417 NAME = 'engine.arrows_bottom_left' | |
418 | |
419 INTERACTS = { | |
420 'arrows': InteractAnimated(32, 425, ( | |
421 'arrow_bottom_left_1.png', 'arrow_bottom_left_2.png', | |
422 'arrow_bottom_left_3.png', 'arrow_bottom_left_4.png', | |
423 ), 16, | |
424 ), | |
425 } | |
426 | |
427 INITIAL = 'arrows' | |
428 | |
429 def is_interactive(self, tool=None): | |
430 return False | |
431 | |
432 | |
433 class ArrowsRight(Thing): | |
434 NAME = 'engine.arrows_right' | |
435 | |
436 INTERACTS = { | |
437 'arrows': InteractAnimated(708, 172, ( | |
438 'arrow_right_1.png', 'arrow_right_2.png', | |
439 'arrow_right_3.png', 'arrow_right_4.png', | |
440 ), 17, | |
441 ), | |
442 } | |
443 | |
444 INITIAL = 'arrows' | |
445 | |
446 def is_interactive(self, tool=None): | |
447 return False | |
448 | |
449 | |
450 class DangerSign(Thing): | |
451 NAME = 'engine.danger_sign' | |
452 | |
453 INTERACTS = { | |
454 'sign': InteractAnimated(299, 341, ( | |
455 'danger_dim.png', 'danger_bright.png', | |
456 ), 10, | |
457 ), | |
458 } | |
459 | |
460 INITIAL = 'sign' | |
461 | |
462 def is_interactive(self, tool=None): | |
463 return False | |
464 | |
465 | |
466 class Stars(Thing): | |
467 NAME = 'engine.stars' | |
468 | |
469 INTERACTS = { | |
470 'stars': InteractAnimated(287, 455, | |
471 ['stars_%d.png' % (i + 1) for i | |
472 in range(5) + range(3, 0, -1)], | |
473 30, | |
474 ), | |
475 } | |
476 | |
477 INITIAL = 'stars' | |
478 | |
479 def is_interactive(self, tool=None): | |
480 return False | |
481 | |
482 def get_description(self): | |
483 return _("A gaping hole in the floor of the room. You're guessing" | |
484 " that's why there's a vacuum in here.") | |
485 | |
486 | |
487 class CrackedPipe(Thing): | |
488 NAME = "engine.cracked_pipe" | |
489 | |
490 INTERACTS = { | |
491 'cracked': InteractImage(13, 402, 'cracked_pipe.png'), | |
492 'taped': InteractImage(13, 402, 'duct_taped_pipe.png'), | |
493 } | |
494 | |
495 INITIAL = 'cracked' | |
496 | |
497 INITIAL_DATA = { | |
498 'fixed': False, | |
499 } | |
500 | |
501 def get_description(self): | |
502 if self.get_data('fixed'): | |
503 return _("The duct tape appears to be holding.") | |
504 else: | |
505 return _("The pipe looks cracked and won't hold" | |
506 " fluid until it's fixed.") | |
507 | |
508 def select_interact(self): | |
509 if self.get_data('fixed'): | |
510 return 'taped' | |
511 return self.INITIAL | |
512 | |
513 def interact_with_duct_tape(self, item): | |
514 if self.get_data('fixed'): | |
515 return Result(_("The duct tape already there appears to be " | |
516 "sufficient.")) | |
517 else: | |
518 self.set_data('fixed', True) | |
519 self.set_interact() | |
520 return Result(_("You apply your trusty duct tape to the " | |
521 "creak, sealing it.")) | |
522 | |
523 | |
524 class ComputerConsole(Thing): | |
525 NAME = "engine.computer_console" | |
526 | |
527 INTERACTS = { | |
528 'console': InteractRectUnion(( | |
529 (293, 287, 39, 36), | |
530 (513, 330, 58, 50), | |
531 )), | |
532 } | |
533 | |
534 INITIAL = 'console' | |
535 | |
536 def interact_without(self): | |
537 return Result(detail_view='engine_comp_detail') | |
538 | |
539 def get_description(self): | |
540 return _("A computer console. It's alarmingly close to the engine.") | |
541 | |
542 | |
543 class EngineCompDetail(Scene): | |
544 | |
545 FOLDER = "engine" | |
546 BACKGROUND = "engine_comp_detail.png" | |
547 NAME = "engine_comp_detail" | |
548 | |
549 ALERTS = { | |
550 'cryo leaking': _("Cryo system leaking!"), | |
551 'cryo empty': _("Cryo reservoir empty!"), | |
552 'super malfunction': _("Superconductor malfunction!"), | |
553 } | |
554 | |
555 # Point to start drawing changeable alerts | |
556 ALERT_OFFSET = (16, 100) | |
557 ALERT_SPACING = 4 | |
558 | |
559 def setup(self): | |
560 self._alert_messages = {} | |
561 self._alert_header = render_text(_("Alerts"), 'DejaVuSans.ttf', | |
562 27, 'darkred', (0, 0, 0, 0), self.resource, (120, 33), False) | |
563 for key, msg in self.ALERTS.iteritems(): | |
564 self._alert_messages[key] = render_text(msg, 'DejaVuSans-Bold.ttf', | |
565 30, 'darkred', (0, 0, 0, 0), self.resource, (480, 33), | |
566 False) | |
567 | |
568 def _draw_alerts(self, surface): | |
569 xpos, ypos = self.ALERT_OFFSET | |
570 engine = self.game.scenes['engine'] | |
571 surface.blit(self._alert_header, (15, 55)) | |
572 if not engine.things['engine.cracked_pipe'].get_data('fixed'): | |
573 image = self._alert_messages['cryo leaking'] | |
574 surface.blit(image, (xpos, ypos)) | |
575 ypos += image.get_size()[1] + self.ALERT_SPACING | |
576 if not engine.things['engine.cryo_containers'].get_data('filled'): | |
577 image = self._alert_messages['cryo empty'] | |
578 surface.blit(image, (xpos, ypos)) | |
579 ypos += image.get_size()[1] + self.ALERT_SPACING | |
580 if not engine.things['engine.superconductor'].get_data('working'): | |
581 image = self._alert_messages['super malfunction'] | |
582 surface.blit(image, (xpos, ypos)) | |
583 ypos += image.get_size()[1] + self.ALERT_SPACING | |
584 | |
585 def draw_things(self, surface): | |
586 self._draw_alerts(surface) | |
587 super(EngineCompDetail, self).draw_things(surface) | |
588 | |
589 | |
590 class ToMap(Door): | |
591 | |
592 SCENE = "engine" | |
593 | |
594 INTERACTS = { | |
595 "door": InteractNoImage(663, 360, 108, 193), | |
596 } | |
597 | |
598 INITIAL = "door" | |
599 | |
600 def get_description(self): | |
601 return _("The airlock leads back to the rest of the ship.") | |
602 | |
603 | |
604 SCENES = [Engine] | |
605 DETAIL_VIEWS = [EngineCompDetail] |