source: nagslang/puzzle.py@ 328:14339d2d46bc

Last change on this file since 328:14339d2d46bc was 328:14339d2d46bc, checked in by Neil Muller <drnlmuller@…>, 8 years ago

Only add objects with actual puzzlers to the glue

File size: 3.1 KB
Line 
1from nagslang.constants import COLLISION_TYPE_PLAYER
2
3
4def get_editable_puzzlers():
5 classes = []
6 for cls_name, cls in globals().iteritems():
7 if isinstance(cls, type) and hasattr(cls, 'requires'):
8 classes.append((cls_name, cls))
9 return classes
10
11
12class PuzzleGlue(object):
13 """Glue that holds bits of a puzzle together.
14 """
15 def __init__(self):
16 self._components = {}
17
18 def add_component(self, name, puzzler):
19 if not isinstance(puzzler, Puzzler):
20 puzzler = puzzler.puzzler
21 if puzzler is None:
22 # We've got a name, but no puzzler,
23 # so we shouldn't actually be stuck
24 # in here
25 return
26 self._components[name] = puzzler
27 puzzler.set_glue(self)
28
29 def get_state_of(self, name):
30 return self._components[name].get_state()
31
32
33class Puzzler(object):
34 """Behaviour specific to a puzzle component.
35 """
36 def set_glue(self, glue):
37 self.glue = glue
38
39 def set_game_object(self, game_object):
40 self.game_object = game_object
41
42 def get_state(self):
43 raise NotImplementedError()
44
45 @classmethod
46 def requires(cls):
47 """Tell the level editor the arguments we require
48
49 Format is a list of name: type hint tuples"""
50 return [("name", "string")]
51
52
53class YesPuzzler(Puzzler):
54 """Yes sir, I'm always on.
55 """
56 def get_state(self):
57 return True
58
59
60class NoPuzzler(Puzzler):
61 """No sir, I'm always off.
62 """
63 def get_state(self):
64 return False
65
66
67class CollidePuzzler(Puzzler):
68 def __init__(self, *collision_types):
69 if not collision_types:
70 collision_types = (COLLISION_TYPE_PLAYER,)
71 self._collision_types = collision_types
72
73 def get_state(self):
74 space = self.game_object.get_space()
75 for shape in space.shape_query(self.game_object.get_shape()):
76 if shape.collision_type in self._collision_types:
77 return True
78 return False
79
80 @classmethod
81 def requires(cls):
82 return [("name", "string"), ("collision_types", "list of ints")]
83
84
85class ParentAttrPuzzler(Puzzler):
86 def __init__(self, attr_name):
87 self._attr_name = attr_name
88
89 def get_state(self):
90 return getattr(self.game_object, self._attr_name)
91
92 @classmethod
93 def requires(cls):
94 return [("name", "string"), ("attr_name", "string")]
95
96
97class StateProxyPuzzler(Puzzler):
98 def __init__(self, state_source):
99 self._state_source = state_source
100
101 def get_state(self):
102 return self.glue.get_state_of(self._state_source)
103
104 @classmethod
105 def requires(cls):
106 return [("name", "string"), ("sources", "list of names")]
107
108
109class StateLogicalAndPuzzler(Puzzler):
110 def __init__(self, *state_sources):
111 self._state_sources = state_sources
112
113 def get_state(self):
114 for state_source in self._state_sources:
115 if not self.glue.get_state_of(state_source):
116 return False
117 return True
118
119 @classmethod
120 def requires(cls):
121 return [("name", "string"), ("sources", "list of names")]
Note: See TracBrowser for help on using the repository browser.