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]