source: nagslang/puzzle.py @ 235:831e4f6b3d18

Last change on this file since 235:831e4f6b3d18 was 235:831e4f6b3d18, checked in by Neil Muller <drnlmuller@…>, 7 years ago

Add hints for the level editor

File size: 2.6 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        self._components[name] = puzzler
22        puzzler.set_glue(self)
23
24    def get_state_of(self, name):
25        return self._components[name].get_state()
26
27
28class Puzzler(object):
29    """Behaviour specific to a puzzle component.
30    """
31    def set_glue(self, glue):
32        self.glue = glue
33
34    def set_game_object(self, game_object):
35        self.game_object = game_object
36
37    def get_state(self):
38        raise NotImplementedError()
39
40    @classmethod
41    def requires(cls):
42        """Tell the level editor the arguments we require
43
44           Format is a list of name: type hint tuples"""
45        return [("name", "string")]
46
47
48class YesPuzzler(Puzzler):
49    """Yes sir, I'm always on.
50    """
51    def get_state(self):
52        return True
53
54
55class NoPuzzler(Puzzler):
56    """No sir, I'm always off.
57    """
58    def get_state(self):
59        return False
60
61
62class CollidePuzzler(Puzzler):
63    def __init__(self, *collision_types):
64        if not collision_types:
65            collision_types = (COLLISION_TYPE_PLAYER,)
66        self._collision_types = collision_types
67
68    def get_state(self):
69        space = self.game_object.get_space()
70        for shape in space.shape_query(self.game_object.get_shape()):
71            if shape.collision_type in self._collision_types:
72                return True
73        return False
74
75    @classmethod
76    def requires(cls):
77        return [("name", "string"), ("collision_types", "list of ints")]
78
79
80class StateProxyPuzzler(Puzzler):
81    def __init__(self, state_source):
82        self._state_source = state_source
83
84    def get_state(self):
85        return self.glue.get_state_of(self._state_source)
86
87    @classmethod
88    def requires(cls):
89        return [("name", "string"), ("sources", "list of names")]
90
91
92class StateLogicalAndPuzzler(Puzzler):
93    def __init__(self, *state_sources):
94        self._state_sources = state_sources
95
96    def get_state(self):
97        for state_source in self._state_sources:
98            if not self.glue.get_state_of(state_source):
99                return False
100        return True
101
102    @classmethod
103    def requires(cls):
104        return [("name", "string"), ("sources", "list of names")]
Note: See TracBrowser for help on using the repository browser.