source: nagslang/puzzle.py

Last change on this file was 456:427d4a3c53d7, checked in by Jeremy Thurgood <firxen@…>, 8 years ago

Better CollidePuzzler behaviour.

File size: 4.0 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_interior_colliders(self):
74 space = self.game_object.get_space()
75 my_shape = self.game_object.get_shape()
76 shapes = [shape for shape in space.shapes
77 if shape.collision_type in self._collision_types]
78 return set(shape for shape in shapes
79 if my_shape in space.point_query(shape.body.position))
80
81 def get_colliders(self):
82 space = self.game_object.get_space()
83 my_shape = self.game_object.get_shape()
84 shapes = set(shape for shape in space.shape_query(my_shape)
85 if shape.collision_type in self._collision_types)
86 shapes.update(self.get_interior_colliders())
87 return shapes
88
89 def get_state(self):
90 return bool(self.get_colliders())
91
92 @classmethod
93 def requires(cls):
94 return [("name", "string"), ("collision_types", "list of ints")]
95
96
97class MultiCollidePuzzler(CollidePuzzler):
98 def __init__(self, min_count, *collision_types):
99 self._min_count = min_count
100 super(MultiCollidePuzzler, self).__init__(*collision_types)
101
102 def get_state(self):
103 return len(self.get_colliders()) >= self._min_count
104
105 @classmethod
106 def requires(cls):
107 return [("name", "string"), ("min_count", "int"),
108 ("collision_types", "list of ints")]
109
110
111class ParentAttrPuzzler(Puzzler):
112 def __init__(self, attr_name):
113 self._attr_name = attr_name
114
115 def get_state(self):
116 return getattr(self.game_object, self._attr_name)
117
118 @classmethod
119 def requires(cls):
120 return [("name", "string"), ("attr_name", "string")]
121
122
123class StateProxyPuzzler(Puzzler):
124 def __init__(self, state_source):
125 self._state_source = state_source
126
127 def get_state(self):
128 return self.glue.get_state_of(self._state_source)
129
130 @classmethod
131 def requires(cls):
132 return [("name", "string"), ("sources", "list of names")]
133
134
135class StateLogicalAndPuzzler(Puzzler):
136 def __init__(self, *state_sources):
137 self._state_sources = state_sources
138
139 def get_state(self):
140 for state_source in self._state_sources:
141 if not self.glue.get_state_of(state_source):
142 return False
143 return True
144
145 @classmethod
146 def requires(cls):
147 return [("name", "string"), ("sources", "list of names")]
Note: See TracBrowser for help on using the repository browser.