# HG changeset patch # User Stefano Rivera # Date 1378243645 -7200 # Node ID 3495a2025bc65f4a96517223742f09e55ceb8418 # Parent dc0cc8228e2ae5ae898e2c07d33c92815fee3096 Break puzzlers out of game_object.py diff -r dc0cc8228e2a -r 3495a2025bc6 nagslang/game_object.py --- a/nagslang/game_object.py Tue Sep 03 23:16:09 2013 +0200 +++ b/nagslang/game_object.py Tue Sep 03 23:27:25 2013 +0200 @@ -4,89 +4,19 @@ import pymunk import pymunk.pygame_util +from nagslang import puzzle from nagslang.constants import ( SWITCH_PUSHERS, COLLISION_TYPE_SWITCH, COLLISION_TYPE_BOX, ZORDER_LOW, - ZORDER_FLOOR, COLLISION_TYPE_DOOR, COLLISION_TYPE_PLAYER) + ZORDER_FLOOR, COLLISION_TYPE_DOOR) from nagslang.options import options from nagslang.resources import resources from nagslang.events import DoorEvent from nagslang.widgets.text import LabelWidget -class PuzzleGlue(object): - """Glue that holds bits of a puzzle together. - """ - def __init__(self): - self._components = {} - - def add_component(self, name, puzzler): - if not isinstance(puzzler, Puzzler): - puzzler = puzzler.puzzler - self._components[name] = puzzler - puzzler.set_glue(self) - - def get_state_of(self, name): - return self._components[name].get_state() - - -class Puzzler(object): - """Behaviour specific to a puzzle component. - """ - def set_glue(self, glue): - self.glue = glue - - def set_game_object(self, game_object): - self.game_object = game_object - - def get_state(self): - raise NotImplementedError() - - -class YesPuzzler(Puzzler): - """Yes sir, I'm always on. - """ - def get_state(self): - return True - - -class NoPuzzler(Puzzler): - """No sir, I'm always off. - """ - def get_state(self): - return False - - -class CollidePuzzler(Puzzler): - def __init__(self, *collision_types): - if not collision_types: - collision_types = (COLLISION_TYPE_PLAYER,) - self._collision_types = collision_types - - def get_state(self): - space = self.game_object.get_space() - for shape in space.shape_query(self.game_object.get_shape()): - if shape.collision_type in self._collision_types: - return True - return False - - -class StateProxyPuzzler(Puzzler): - def __init__(self, state_source): - self._state_source = state_source - - def get_state(self): - return self.glue.get_state_of(self._state_source) - - -class StateLogicalAndPuzzler(Puzzler): - def __init__(self, *state_sources): - self._state_sources = state_sources - - def get_state(self): - for state_source in self._state_sources: - if not self.glue.get_state_of(state_source): - return False - return True +# For levels to import, until we get module names in 'classname' +StateProxyPuzzler = puzzle.StateProxyPuzzler +StateLogicalAndPuzzler = puzzle.StateLogicalAndPuzzler class Physicser(object): @@ -403,7 +333,7 @@ True: resources.get_image('objects', 'sensor_on.png'), False: resources.get_image('objects', 'sensor_off.png'), }), - CollidePuzzler(*SWITCH_PUSHERS), + puzzle.CollidePuzzler(*SWITCH_PUSHERS), ) @@ -417,7 +347,7 @@ super(Note, self).__init__( SingleShapePhysicser(space, self.shape), ImageRenderer(resources.get_image('objects', 'note.png')), - CollidePuzzler(), + puzzle.CollidePuzzler(), TextOverlay(message), ) @@ -436,7 +366,7 @@ True: resources.get_image('objects', 'light_on.png'), False: resources.get_image('objects', 'light_off.png'), }), - StateProxyPuzzler(state_source), + puzzle.StateProxyPuzzler(state_source), ) @@ -464,9 +394,9 @@ self.destination = destination self.dest_pos = tuple(dest_pos) if key_state is None: - puzzler = YesPuzzler() + puzzler = puzzle.YesPuzzler() else: - puzzler = StateProxyPuzzler(key_state) + puzzler = puzzle.StateProxyPuzzler(key_state) super(Door, self).__init__( SingleShapePhysicser(space, self.shape), ImageRenderer(resources.get_image('objects', 'door.png')), diff -r dc0cc8228e2a -r 3495a2025bc6 nagslang/level.py --- a/nagslang/level.py Tue Sep 03 23:16:09 2013 +0200 +++ b/nagslang/level.py Tue Sep 03 23:27:25 2013 +0200 @@ -3,6 +3,7 @@ from nagslang import game_object as go from nagslang import enemies +from nagslang import puzzle from nagslang.resources import resources from nagslang.yamlish import load, dump @@ -32,7 +33,7 @@ self._tile_image = None self._surface = None self._exterior = False - self._glue = go.PuzzleGlue() + self._glue = puzzle.PuzzleGlue() self.drawables = [] self.overlay_drawables = [] self._game_objects = [] @@ -74,7 +75,7 @@ # We should probably build a registry of game objects or something. # At least this is better than just calling `eval`, right? cls = getattr(go, classname) - if issubclass(cls, go.Puzzler): + if issubclass(cls, puzzle.Puzzler): gobj = cls(*args) elif issubclass(cls, go.GameObject): gobj = cls(space, *args) diff -r dc0cc8228e2a -r 3495a2025bc6 nagslang/puzzle.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nagslang/puzzle.py Tue Sep 03 23:27:25 2013 +0200 @@ -0,0 +1,77 @@ +from nagslang.constants import COLLISION_TYPE_PLAYER + + +class PuzzleGlue(object): + """Glue that holds bits of a puzzle together. + """ + def __init__(self): + self._components = {} + + def add_component(self, name, puzzler): + if not isinstance(puzzler, Puzzler): + puzzler = puzzler.puzzler + self._components[name] = puzzler + puzzler.set_glue(self) + + def get_state_of(self, name): + return self._components[name].get_state() + + +class Puzzler(object): + """Behaviour specific to a puzzle component. + """ + def set_glue(self, glue): + self.glue = glue + + def set_game_object(self, game_object): + self.game_object = game_object + + def get_state(self): + raise NotImplementedError() + + +class YesPuzzler(Puzzler): + """Yes sir, I'm always on. + """ + def get_state(self): + return True + + +class NoPuzzler(Puzzler): + """No sir, I'm always off. + """ + def get_state(self): + return False + + +class CollidePuzzler(Puzzler): + def __init__(self, *collision_types): + if not collision_types: + collision_types = (COLLISION_TYPE_PLAYER,) + self._collision_types = collision_types + + def get_state(self): + space = self.game_object.get_space() + for shape in space.shape_query(self.game_object.get_shape()): + if shape.collision_type in self._collision_types: + return True + return False + + +class StateProxyPuzzler(Puzzler): + def __init__(self, state_source): + self._state_source = state_source + + def get_state(self): + return self.glue.get_state_of(self._state_source) + + +class StateLogicalAndPuzzler(Puzzler): + def __init__(self, *state_sources): + self._state_sources = state_sources + + def get_state(self): + for state_source in self._state_sources: + if not self.glue.get_state_of(state_source): + return False + return True diff -r dc0cc8228e2a -r 3495a2025bc6 nagslang/tests/test_game_object.py --- a/nagslang/tests/test_game_object.py Tue Sep 03 23:16:09 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -from unittest import TestCase - -from nagslang.constants import COLLISION_TYPE_OTHER, SWITCH_PUSHERS -from nagslang import game_object - - -class FakeShape(object): - def __init__(self, collision_type=COLLISION_TYPE_OTHER): - self.collision_type = collision_type - - -class FakeSpace(object): - def __init__(self, *shapes): - self._shapes = shapes - - def shape_query(self, shape): - return self._shapes - - -class FakeGameObject(object): - def __init__(self, shape, space): - self._shape = shape - self._space = space - - def get_shape(self): - return self._shape - - def get_space(self): - return self._space - - -class FakePuzzler(game_object.Puzzler): - def __init__(self, fake_state): - self.fake_state = fake_state - - def get_state(self): - return self.fake_state - - -class TestPuzzles(TestCase): - def mkpuzzler(self, gobj, cls, *args, **kw): - puzzler = cls(*args, **kw) - puzzler.set_game_object(gobj) - return puzzler - - def assert_collide_state(self, expected, shapes, collision_types): - gobj = FakeGameObject(None, FakeSpace(*shapes)) - puzzler = self.mkpuzzler( - gobj, game_object.CollidePuzzler, *collision_types) - self.assertEqual(expected, puzzler.get_state()) - - def test_collide_puzzler(self): - self.assert_collide_state(False, [], []) - self.assert_collide_state(False, [FakeShape()], SWITCH_PUSHERS) - - for collision_type in SWITCH_PUSHERS: - self.assert_collide_state( - True, [FakeShape(collision_type)], SWITCH_PUSHERS) - self.assert_collide_state( - True, [FakeShape(), FakeShape(collision_type)], SWITCH_PUSHERS) - - def test_state_proxy_puzzler(self): - glue = game_object.PuzzleGlue() - puzzler = game_object.StateProxyPuzzler('faker') - glue.add_component('puzzler', puzzler) - faker = FakePuzzler('foo') - glue.add_component('faker', faker) - - self.assertEqual('foo', puzzler.get_state()) - faker.fake_state = 'bar' - self.assertEqual('bar', puzzler.get_state()) - - def test_glue_add_component(self): - glue = game_object.PuzzleGlue() - puzzler = FakePuzzler('foo') - gobj = FakeGameObject(None, None) - gobj.puzzler = FakePuzzler('bar') - - self.assertEqual({}, glue._components) - glue.add_component('foo', puzzler) - self.assertEqual({'foo': puzzler}, glue._components) - glue.add_component('bar', gobj) - self.assertEqual( - {'foo': puzzler, 'bar': gobj.puzzler}, glue._components) diff -r dc0cc8228e2a -r 3495a2025bc6 nagslang/tests/test_puzzle.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nagslang/tests/test_puzzle.py Tue Sep 03 23:27:25 2013 +0200 @@ -0,0 +1,84 @@ +from unittest import TestCase + +from nagslang.constants import COLLISION_TYPE_OTHER, SWITCH_PUSHERS +from nagslang import puzzle + + +class FakeShape(object): + def __init__(self, collision_type=COLLISION_TYPE_OTHER): + self.collision_type = collision_type + + +class FakeSpace(object): + def __init__(self, *shapes): + self._shapes = shapes + + def shape_query(self, shape): + return self._shapes + + +class FakeGameObject(object): + def __init__(self, shape, space): + self._shape = shape + self._space = space + + def get_shape(self): + return self._shape + + def get_space(self): + return self._space + + +class FakePuzzler(puzzle.Puzzler): + def __init__(self, fake_state): + self.fake_state = fake_state + + def get_state(self): + return self.fake_state + + +class TestPuzzles(TestCase): + def mkpuzzler(self, gobj, cls, *args, **kw): + puzzler = cls(*args, **kw) + puzzler.set_game_object(gobj) + return puzzler + + def assert_collide_state(self, expected, shapes, collision_types): + gobj = FakeGameObject(None, FakeSpace(*shapes)) + puzzler = self.mkpuzzler( + gobj, puzzle.CollidePuzzler, *collision_types) + self.assertEqual(expected, puzzler.get_state()) + + def test_collide_puzzler(self): + self.assert_collide_state(False, [], []) + self.assert_collide_state(False, [FakeShape()], SWITCH_PUSHERS) + + for collision_type in SWITCH_PUSHERS: + self.assert_collide_state( + True, [FakeShape(collision_type)], SWITCH_PUSHERS) + self.assert_collide_state( + True, [FakeShape(), FakeShape(collision_type)], SWITCH_PUSHERS) + + def test_state_proxy_puzzler(self): + glue = puzzle.PuzzleGlue() + puzzler = puzzle.StateProxyPuzzler('faker') + glue.add_component('puzzler', puzzler) + faker = FakePuzzler('foo') + glue.add_component('faker', faker) + + self.assertEqual('foo', puzzler.get_state()) + faker.fake_state = 'bar' + self.assertEqual('bar', puzzler.get_state()) + + def test_glue_add_component(self): + glue = puzzle.PuzzleGlue() + puzzler = FakePuzzler('foo') + gobj = FakeGameObject(None, None) + gobj.puzzler = FakePuzzler('bar') + + self.assertEqual({}, glue._components) + glue.add_component('foo', puzzler) + self.assertEqual({'foo': puzzler}, glue._components) + glue.add_component('bar', gobj) + self.assertEqual( + {'foo': puzzler, 'bar': gobj.puzzler}, glue._components)