home · contact · privacy
Flatten game->world hierarchy.
authorChristian Heller <c.heller@plomlompom.de>
Tue, 30 Apr 2019 17:34:35 +0000 (19:34 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 30 Apr 2019 17:34:35 +0000 (19:34 +0200)
new/example_client.py
new/plomrogue/commands.py
new/plomrogue/game.py
new/plomrogue/tasks.py
new/plomrogue/things.py

index a88c85b3c2d642f2a7a9cce5dc3be95f46b6e010..2a4b80cc6e03fe722033790a310f84e90c830f64 100755 (executable)
@@ -4,7 +4,7 @@ import socket
 import threading
 from plomrogue.parser import ArgError, Parser
 from plomrogue.commands import cmd_PLAYER_ID, cmd_THING_HEALTH
 import threading
 from plomrogue.parser import ArgError, Parser
 from plomrogue.commands import cmd_PLAYER_ID, cmd_THING_HEALTH
-from plomrogue.game import Game, WorldBase
+from plomrogue.game import GameBase
 from plomrogue.mapping import Map, MapGeometryHex, YX
 from plomrogue.io import PlomSocket
 from plomrogue.things import ThingBase
 from plomrogue.mapping import Map, MapGeometryHex, YX
 from plomrogue.io import PlomSocket
 from plomrogue.things import ThingBase
@@ -65,30 +65,6 @@ class ClientMap(Map):
         return map_lines
 
 
         return map_lines
 
 
-class World(WorldBase):
-
-    def __init__(self, *args, **kwargs):
-        """Extend original with local classes and empty default map.
-
-        We need the empty default map because we draw the map widget
-        on any update, even before we actually receive map data.
-        """
-        super().__init__(*args, **kwargs)
-        self.map_ = ClientMap()
-        self.offset = YX(0,0)
-        self.player_inventory = []
-        self.player_id = 0
-        self.pickable_items = []
-
-    def new_map(self, offset, size):
-        self.map_ = ClientMap(size)
-        self.offset = offset
-
-    @property
-    def player(self):
-        return self.get_thing(self.player_id)
-
-
 def cmd_LAST_PLAYER_TASK_RESULT(game, msg):
     if msg != "success":
         game.log(msg)
 def cmd_LAST_PLAYER_TASK_RESULT(game, msg):
     if msg != "success":
         game.log(msg)
@@ -103,19 +79,19 @@ cmd_TURN_FINISHED.argtypes = 'int:nonneg'
 
 def cmd_TURN(game, n):
     """Set game.turn to n, empty game.things."""
 
 def cmd_TURN(game, n):
     """Set game.turn to n, empty game.things."""
-    game.world.turn = n
-    game.world.things = []
-    game.world.pickable_items[:] = []
+    game.turn = n
+    game.things = []
+    game.pickable_items[:] = []
 cmd_TURN.argtypes = 'int:nonneg'
 
 
 def cmd_VISIBLE_MAP(game, offset, size):
 cmd_TURN.argtypes = 'int:nonneg'
 
 
 def cmd_VISIBLE_MAP(game, offset, size):
-    game.world.new_map(offset, size)
+    game.new_map(offset, size)
 cmd_VISIBLE_MAP.argtypes = 'yx_tuple yx_tuple:pos'
 
 
 def cmd_VISIBLE_MAP_LINE(game, y, terrain_line):
 cmd_VISIBLE_MAP.argtypes = 'yx_tuple yx_tuple:pos'
 
 
 def cmd_VISIBLE_MAP_LINE(game, y, terrain_line):
-    game.world.map_.set_line(y, terrain_line)
+    game.map_.set_line(y, terrain_line)
 cmd_VISIBLE_MAP_LINE.argtypes = 'int:nonneg string'
 
 
 cmd_VISIBLE_MAP_LINE.argtypes = 'int:nonneg string'
 
 
@@ -126,34 +102,39 @@ def cmd_GAME_STATE_COMPLETE(game):
 
 
 def cmd_THING_TYPE(game, i, type_):
 
 
 def cmd_THING_TYPE(game, i, type_):
-    t = game.world.get_thing(i)
+    t = game.get_thing(i)
     t.type_ = type_
 cmd_THING_TYPE.argtypes = 'int:nonneg string'
 
 
 def cmd_THING_POS(game, i, yx):
     t.type_ = type_
 cmd_THING_TYPE.argtypes = 'int:nonneg string'
 
 
 def cmd_THING_POS(game, i, yx):
-    t = game.world.get_thing(i)
+    t = game.get_thing(i)
     t.position = YX(0,0), yx
 cmd_THING_POS.argtypes = 'int:nonneg yx_tuple:nonneg'
 
 
 def cmd_PLAYER_INVENTORY(game, ids):
     t.position = YX(0,0), yx
 cmd_THING_POS.argtypes = 'int:nonneg yx_tuple:nonneg'
 
 
 def cmd_PLAYER_INVENTORY(game, ids):
-    game.world.player_inventory[:] = ids  # TODO: test whether valid IDs
+    game.player_inventory[:] = ids  # TODO: test whether valid IDs
     game.tui.to_update['inventory'] = True
 cmd_PLAYER_INVENTORY.argtypes = 'seq:int:nonneg'
 
 
 def cmd_PICKABLE_ITEMS(game, ids):
     game.tui.to_update['inventory'] = True
 cmd_PLAYER_INVENTORY.argtypes = 'seq:int:nonneg'
 
 
 def cmd_PICKABLE_ITEMS(game, ids):
-    game.world.pickable_items[:] = ids
+    game.pickable_items[:] = ids
     game.tui.to_update['pickable_items'] = True
 cmd_PICKABLE_ITEMS.argtypes = 'seq:int:nonneg'
 
 
     game.tui.to_update['pickable_items'] = True
 cmd_PICKABLE_ITEMS.argtypes = 'seq:int:nonneg'
 
 
-class Game:
+class Game(GameBase):
 
 
-    def __init__(self):
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.map_ = ClientMap()  # we need an empty default map cause we draw
+        self.offset = YX(0,0)    # the map widget even before we get a real one
+        self.player_inventory = []
+        self.player_id = 0
+        self.pickable_items = []
         self.parser = Parser(self)
         self.parser = Parser(self)
-        self.world = World(self)
         self.map_geometry = MapGeometryHex()
         self.thing_type = ThingBase
         self.commands = {'LAST_PLAYER_TASK_RESULT': cmd_LAST_PLAYER_TASK_RESULT,
         self.map_geometry = MapGeometryHex()
         self.thing_type = ThingBase
         self.commands = {'LAST_PLAYER_TASK_RESULT': cmd_LAST_PLAYER_TASK_RESULT,
@@ -172,6 +153,14 @@ class Game:
         self.do_quit = False
         self.tui = None
 
         self.do_quit = False
         self.tui = None
 
+    def new_map(self, offset, size):
+        self.map_ = ClientMap(size)
+        self.offset = offset
+
+    @property
+    def player(self):
+        return self.get_thing(self.player_id)
+
     def get_command(self, command_name):
         from functools import partial
         if command_name in self.commands:
     def get_command(self, command_name):
         from functools import partial
         if command_name in self.commands:
@@ -333,11 +322,11 @@ class DescriptorWidget(TextLinesWidget):
 
     def get_text_lines(self):
         lines = []
 
     def get_text_lines(self):
         lines = []
-        pos_i = self.tui.game.world.map_.\
+        pos_i = self.tui.game.map_.\
                 get_position_index(self.tui.examiner_position[1])
                 get_position_index(self.tui.examiner_position[1])
-        terrain = self.tui.game.world.map_.terrain[pos_i]
+        terrain = self.tui.game.map_.terrain[pos_i]
         lines = [terrain]
         lines = [terrain]
-        for t in self.tui.game.world.things_at_pos(self.tui.examiner_position):
+        for t in self.tui.game.things_at_pos(self.tui.examiner_position):
             lines += [t.type_]
         return lines
 
             lines += [t.type_]
         return lines
 
@@ -381,7 +370,7 @@ class ItemsSelectorWidget(Widget):
         counter = 0
         for id_ in self.selection:
             pointer = '*' if counter == self.tui.item_pointer else ' '
         counter = 0
         for id_ in self.selection:
             pointer = '*' if counter == self.tui.item_pointer else ' '
-            t = self.tui.game.world.get_thing(id_)
+            t = self.tui.game.get_thing(id_)
             lines += ['%s %s' % (pointer, t.type_)]
             counter += 1
         line_width = self.size.x
             lines += ['%s %s' % (pointer, t.type_)]
             counter += 1
         line_width = self.size.x
@@ -399,12 +388,11 @@ class MapWidget(Widget):
     def draw(self):
 
         def annotated_terrain():
     def draw(self):
 
         def annotated_terrain():
-            terrain_as_list = list(self.tui.game.world.map_.terrain[:])
-            for t in self.tui.game.world.things:
-                if t.id_ in self.tui.game.world.player_inventory:
+            terrain_as_list = list(self.tui.game.map_.terrain[:])
+            for t in self.tui.game.things:
+                if t.id_ in self.tui.game.player_inventory:
                     continue
                     continue
-                pos_i = self.tui.game.world.map_.\
-                        get_position_index(t.position[1])
+                pos_i = self.tui.game.map_.get_position_index(t.position[1])
                 symbol = self.tui.game.symbol_for_type(t.type_)
                 if terrain_as_list[pos_i][0] in {'f', '@', 'm'}:
                     old_symbol = terrain_as_list[pos_i][0]
                 symbol = self.tui.game.symbol_for_type(t.type_)
                 if terrain_as_list[pos_i][0] in {'f', '@', 'm'}:
                     old_symbol = terrain_as_list[pos_i][0]
@@ -414,7 +402,7 @@ class MapWidget(Widget):
                 else:
                     terrain_as_list[pos_i] = symbol
             if self.tui.examiner_mode:
                 else:
                     terrain_as_list[pos_i] = symbol
             if self.tui.examiner_mode:
-                pos_i = self.tui.game.world.map_.\
+                pos_i = self.tui.game.map_.\
                         get_position_index(self.tui.examiner_position[1])
                 terrain_as_list[pos_i] = (terrain_as_list[pos_i][0], '?')
             return terrain_as_list
                         get_position_index(self.tui.examiner_position[1])
                 terrain_as_list[pos_i] = (terrain_as_list[pos_i][0], '?')
             return terrain_as_list
@@ -451,18 +439,18 @@ class MapWidget(Widget):
                     chars_with_attrs += [c]
             return chars_with_attrs
 
                     chars_with_attrs += [c]
             return chars_with_attrs
 
-        if self.tui.game.world.map_.terrain == '':
+        if self.tui.game.map_.terrain == '':
             lines = []
             pad_y(lines)
             self.safe_write(''.join(lines))
             return
 
         annotated_terrain = annotated_terrain()
             lines = []
             pad_y(lines)
             self.safe_write(''.join(lines))
             return
 
         annotated_terrain = annotated_terrain()
-        center = self.tui.game.world.player.position
+        center = self.tui.game.player.position
         if self.tui.examiner_mode:
             center = self.tui.examiner_position
         if self.tui.examiner_mode:
             center = self.tui.examiner_position
-        indent_first_line = not bool(self.tui.game.world.offset.y % 2)
-        lines = self.tui.game.world.map_.\
+        indent_first_line = not bool(self.tui.game.offset.y % 2)
+        lines = self.tui.game.map_.\
                 format_to_view(annotated_terrain, center, self.size,
                                indent_first_line)
         pad_or_cut_x(lines)
                 format_to_view(annotated_terrain, center, self.size,
                                indent_first_line)
         pad_or_cut_x(lines)
@@ -473,14 +461,14 @@ class MapWidget(Widget):
 class TurnWidget(Widget):
 
     def draw(self):
 class TurnWidget(Widget):
 
     def draw(self):
-        self.safe_write((str(self.tui.game.world.turn), curses.color_pair(2)))
+        self.safe_write((str(self.tui.game.turn), curses.color_pair(2)))
 
 
 class HealthWidget(Widget):
 
     def draw(self):
 
 
 class HealthWidget(Widget):
 
     def draw(self):
-        if hasattr(self.tui.game.world.player, 'health'):
-            self.safe_write((str(self.tui.game.world.player.health),
+        if hasattr(self.tui.game.player, 'health'):
+            self.safe_write((str(self.tui.game.player.health),
                              curses.color_pair(2)))
 
 
                              curses.color_pair(2)))
 
 
@@ -548,7 +536,7 @@ class TUI:
                 return True
 
             selectables_menu(key, pickable_items_widget,
                 return True
 
             selectables_menu(key, pickable_items_widget,
-                             self.game.world.pickable_items, f)
+                             self.game.pickable_items, f)
 
         def inventory_menu(key):
 
 
         def inventory_menu(key):
 
@@ -564,12 +552,12 @@ class TUI:
                 return True
 
             selectables_menu(key, inventory_widget,
                 return True
 
             selectables_menu(key, inventory_widget,
-                             self.game.world.player_inventory, f)
+                             self.game.player_inventory, f)
 
         def move_examiner(direction):
             start_pos = self.examiner_position
             new_examine_pos = self.game.map_geometry.move(start_pos, direction,
 
         def move_examiner(direction):
             start_pos = self.examiner_position
             new_examine_pos = self.game.map_geometry.move(start_pos, direction,
-                                                          self.game.world.map_.size)
+                                                          self.game.map_.size)
             if new_examine_pos[0] == (0,0):
                 self.examiner_position = new_examine_pos
             self.to_update['map'] = True
             if new_examine_pos[0] == (0,0):
                 self.examiner_position = new_examine_pos
             self.to_update['map'] = True
@@ -587,7 +575,7 @@ class TUI:
                 switch_widgets(descriptor_widget, log_widget)
             else:
                 self.examiner_mode = True
                 switch_widgets(descriptor_widget, log_widget)
             else:
                 self.examiner_mode = True
-                self.examiner_position = self.game.world.player.position
+                self.examiner_position = self.game.player.position
                 switch_widgets(log_widget, descriptor_widget)
             self.to_update['map'] = True
 
                 switch_widgets(log_widget, descriptor_widget)
             self.to_update['map'] = True
 
@@ -668,11 +656,11 @@ class TUI:
                                              ['map'], False)
         map_widget = MapWidget(self, YX(0, 21), YX(None, None), ['map'])
         inventory_widget = ItemsSelectorWidget('INVENTORY:',
                                              ['map'], False)
         map_widget = MapWidget(self, YX(0, 21), YX(None, None), ['map'])
         inventory_widget = ItemsSelectorWidget('INVENTORY:',
-                                               self.game.world.player_inventory,
+                                               self.game.player_inventory,
                                                self, YX(0, 21), YX(None, None),
                                                ['inventory'], False)
         pickable_items_widget = ItemsSelectorWidget('PICKABLE:',
                                                self, YX(0, 21), YX(None, None),
                                                ['inventory'], False)
         pickable_items_widget = ItemsSelectorWidget('PICKABLE:',
-                                                    self.game.world.pickable_items,
+                                                    self.game.pickable_items,
                                                     self, YX(0, 21),
                                                     YX(None, None),
                                                     ['pickable_items'],
                                                     self, YX(0, 21),
                                                     YX(None, None),
                                                     ['pickable_items'],
index bcab2d10702c13bda99a2fee684e210b5e7fa979..744d471fac100bc5e326813899d93466a353566e 100644 (file)
@@ -3,7 +3,7 @@ from plomrogue.misc import quote
 
 
 def cmd_GEN_WORLD(game, yx, seed):
 
 
 def cmd_GEN_WORLD(game, yx, seed):
-    game.world.make_new(yx, seed)
+    game.make_new_world(yx, seed)
 cmd_GEN_WORLD.argtypes = 'yx_tuple:pos int:nonneg'
 
 def cmd_GET_GAMESTATE(game, connection_id):
 cmd_GEN_WORLD.argtypes = 'yx_tuple:pos int:nonneg'
 
 def cmd_GET_GAMESTATE(game, connection_id):
@@ -11,7 +11,7 @@ def cmd_GET_GAMESTATE(game, connection_id):
     game.send_gamestate(connection_id)
 
 def cmd_SEED(game, seed):
     game.send_gamestate(connection_id)
 
 def cmd_SEED(game, seed):
-    game.world.rand.prngod_seed = seed
+    game.rand.prngod_seed = seed
 cmd_SEED.argtypes = 'int:nonneg'
 
 def cmd_MAP_SIZE(game, size):
 cmd_SEED.argtypes = 'int:nonneg'
 
 def cmd_MAP_SIZE(game, size):
@@ -20,12 +20,12 @@ cmd_MAP_SIZE.argtypes = 'yx_tuple:pos'
 
 def cmd_MAP(game, map_pos):
     """Ensure (possibly empty/'?'-filled) map at position map_pos."""
 
 def cmd_MAP(game, map_pos):
     """Ensure (possibly empty/'?'-filled) map at position map_pos."""
-    game.world.get_map(map_pos)
+    game.get_map(map_pos)
 cmd_MAP.argtypes = 'yx_tuple'
 
 def cmd_THING_TYPE(game, i, type_):
 cmd_MAP.argtypes = 'yx_tuple'
 
 def cmd_THING_TYPE(game, i, type_):
-    t_old = game.world.get_thing(i)
-    t_new = game.thing_types[type_](game.world, i)
+    t_old = game.get_thing(i)
+    t_new = game.thing_types[type_](game, i)
     #attr_names_of_old = [name for name in dir(t_old) where name[:2] != '__']
     #attr_names_of_new = [name for name in dir(t_new) where name[:2] != '__']
     #class_new = type(t_new)
     #attr_names_of_old = [name for name in dir(t_old) where name[:2] != '__']
     #attr_names_of_new = [name for name in dir(t_new) where name[:2] != '__']
     #class_new = type(t_new)
@@ -41,31 +41,31 @@ def cmd_THING_TYPE(game, i, type_):
     #    setattr(t_new, attr_name, attr_old)
     t_new.position = t_old.position
     t_new.in_inventory = t_old.in_inventory
     #    setattr(t_new, attr_name, attr_old)
     t_new.position = t_old.position
     t_new.in_inventory = t_old.in_inventory
-    t_old_index = game.world.things.index(t_old)
-    game.world.things[t_old_index] = t_new
+    t_old_index = game.things.index(t_old)
+    game.things[t_old_index] = t_new
 cmd_THING_TYPE.argtypes = 'int:nonneg string:thingtype'
 
 def cmd_THING_POS(game, i, big_yx, small_yx):
 cmd_THING_TYPE.argtypes = 'int:nonneg string:thingtype'
 
 def cmd_THING_POS(game, i, big_yx, small_yx):
-    t = game.world.get_thing(i)
+    t = game.get_thing(i)
     t.position = (big_yx, small_yx)
 cmd_THING_POS.argtypes = 'int:nonneg yx_tuple yx_tuple:nonneg'
 
 def cmd_THING_INVENTORY(game, id_, ids):
     t.position = (big_yx, small_yx)
 cmd_THING_POS.argtypes = 'int:nonneg yx_tuple yx_tuple:nonneg'
 
 def cmd_THING_INVENTORY(game, id_, ids):
-    carrier = game.world.get_thing(id_)
+    carrier = game.get_thing(id_)
     carrier.inventory = ids
     for id_ in ids:
     carrier.inventory = ids
     for id_ in ids:
-        t = game.world.get_thing(id_)
+        t = game.get_thing(id_)
         t.in_inventory = True
         t.position = carrier.position
 cmd_THING_INVENTORY.argtypes = 'int:nonneg seq:int:nonneg'
 
 def cmd_THING_HEALTH(game, id_, health):
         t.in_inventory = True
         t.position = carrier.position
 cmd_THING_INVENTORY.argtypes = 'int:nonneg seq:int:nonneg'
 
 def cmd_THING_HEALTH(game, id_, health):
-    t = game.world.get_thing(id_)
+    t = game.get_thing(id_)
     t.health = health
 cmd_THING_HEALTH.argtypes = 'int:nonneg int:nonneg'
 
 def cmd_GET_PICKABLE_ITEMS(game, connection_id):
     t.health = health
 cmd_THING_HEALTH.argtypes = 'int:nonneg int:nonneg'
 
 def cmd_GET_PICKABLE_ITEMS(game, connection_id):
-    pickable_ids = game.world.player.get_pickable_items()
+    pickable_ids = game.player.get_pickable_items()
     if len(pickable_ids) > 0:
         game.io.send('PICKABLE_ITEMS %s' %
                      ','.join([str(id_) for id_ in pickable_ids]))
     if len(pickable_ids) > 0:
         game.io.send('PICKABLE_ITEMS %s' %
                      ','.join([str(id_) for id_ in pickable_ids]))
@@ -73,26 +73,26 @@ def cmd_GET_PICKABLE_ITEMS(game, connection_id):
         game.io.send('PICKABLE_ITEMS ,')
 
 def cmd_TERRAIN_LINE(game, big_yx, y, terrain_line):
         game.io.send('PICKABLE_ITEMS ,')
 
 def cmd_TERRAIN_LINE(game, big_yx, y, terrain_line):
-    game.world.maps[big_yx].set_line(y, terrain_line)
+    game.maps[big_yx].set_line(y, terrain_line)
 cmd_TERRAIN_LINE.argtypes = 'yx_tuple int:nonneg string'
 
 def cmd_PLAYER_ID(game, id_):
     # TODO: test whether valid thing ID
 cmd_TERRAIN_LINE.argtypes = 'yx_tuple int:nonneg string'
 
 def cmd_PLAYER_ID(game, id_):
     # TODO: test whether valid thing ID
-    game.world.player_id = id_
+    game.player_id = id_
 cmd_PLAYER_ID.argtypes = 'int:nonneg'
 
 def cmd_TURN(game, n):
 cmd_PLAYER_ID.argtypes = 'int:nonneg'
 
 def cmd_TURN(game, n):
-    game.world.turn = n
+    game.turn = n
 cmd_TURN.argtypes = 'int:nonneg'
 
 def cmd_SWITCH_PLAYER(game):
 cmd_TURN.argtypes = 'int:nonneg'
 
 def cmd_SWITCH_PLAYER(game):
-    game.world.player.set_task('WAIT')
-    thing_ids = [t.id_ for t in game.world.things]
-    player_index = thing_ids.index(game.world.player.id_)
+    game.player.set_task('WAIT')
+    thing_ids = [t.id_ for t in game.things]
+    player_index = thing_ids.index(game.player.id_)
     if player_index == len(thing_ids) - 1:
     if player_index == len(thing_ids) - 1:
-        game.world.player_id = thing_ids[0]
+        game.player_id = thing_ids[0]
     else:
     else:
-        game.world.player_id = thing_ids[player_index + 1]
+        game.player_id = thing_ids[player_index + 1]
     game.proceed()
 
 def cmd_SAVE(game):
     game.proceed()
 
 def cmd_SAVE(game):
@@ -102,15 +102,15 @@ def cmd_SAVE(game):
 
     save_file_name = game.io.game_file_name + '.save'
     with open(save_file_name, 'w') as f:
 
     save_file_name = game.io.game_file_name + '.save'
     with open(save_file_name, 'w') as f:
-        write(f, 'TURN %s' % game.world.turn)
-        write(f, 'SEED %s' % game.world.rand.prngod_seed)
+        write(f, 'TURN %s' % game.turn)
+        write(f, 'SEED %s' % game.rand.prngod_seed)
         write(f, 'MAP_SIZE %s' % (game.map_size,))
         write(f, 'MAP_SIZE %s' % (game.map_size,))
-        for map_pos in game.world.maps:
+        for map_pos in game.maps:
             write(f, 'MAP %s' % (map_pos,))
             write(f, 'MAP %s' % (map_pos,))
-        for map_pos in game.world.maps:
-            for y, line in game.world.maps[map_pos].lines():
+        for map_pos in game.maps:
+            for y, line in game.maps[map_pos].lines():
                  write(f, 'TERRAIN_LINE %s %5s %s' % (map_pos, y, quote(line)))
                  write(f, 'TERRAIN_LINE %s %5s %s' % (map_pos, y, quote(line)))
-        for thing in game.world.things:
+        for thing in game.things:
             write(f, 'THING_TYPE %s %s' % (thing.id_, thing.type_))
             write(f, 'THING_POS %s %s %s' % (thing.id_, thing.position[0],
                                              thing.position[1]))
             write(f, 'THING_TYPE %s %s' % (thing.id_, thing.type_))
             write(f, 'THING_POS %s %s %s' % (thing.id_, thing.position[0],
                                              thing.position[1]))
@@ -129,5 +129,5 @@ def cmd_SAVE(game):
                                  if game.tasks[k] == task.__class__][0]
                     write(f, 'SET_TASK:%s %s %s %s' % (task_name, thing.id_,
                                                        task.todo, task_args))
                                  if game.tasks[k] == task.__class__][0]
                     write(f, 'SET_TASK:%s %s %s %s' % (task_name, thing.id_,
                                                        task.todo, task_args))
-        write(f, 'PLAYER_ID %s' % game.world.player_id)
+        write(f, 'PLAYER_ID %s' % game.player_id)
 cmd_SAVE.dont_save = True
 cmd_SAVE.dont_save = True
index db71f21e21df5adf7412f7e2279f3a48177a1c5d..6b2c74b62f7427e9ae4daa9e705e0f740f16745e 100755 (executable)
@@ -34,19 +34,18 @@ class PRNGod(random.Random):
 
 
 
 
 
 
-class WorldBase:
+class GameBase:
 
 
-    def __init__(self, game):
+    def __init__(self):
         self.turn = 0
         self.things = []
         self.turn = 0
         self.things = []
-        self.game = game
 
     def get_thing(self, id_, create_unfound=True):
         for thing in self.things:
             if id_ == thing.id_:
                 return thing
         if create_unfound:
 
     def get_thing(self, id_, create_unfound=True):
         for thing in self.things:
             if id_ == thing.id_:
                 return thing
         if create_unfound:
-            t = self.game.thing_type(self, id_)
+            t = self.thing_type(self, id_)
             self.things += [t]
             return t
         return None
             self.things += [t]
             return t
         return None
@@ -60,107 +59,10 @@ class WorldBase:
 
 
 
 
 
 
-class World(WorldBase):
+class Game(GameBase):
 
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, game_file_name, *args, **kwargs):
         super().__init__(*args, **kwargs)
         super().__init__(*args, **kwargs)
-        self.player_id = 0
-        self.player_is_alive = True
-        self.maps = {}
-        self.rand = PRNGod(0)
-
-    @property
-    def player(self):
-        return self.get_thing(self.player_id)
-
-    def new_thing_id(self):
-        if len(self.things) == 0:
-            return 0
-        return self.things[-1].id_ + 1
-
-    def get_map(self, map_pos, create_unfound=True):
-        if not (map_pos in self.maps and
-                self.maps[map_pos].size == self.game.map_size):
-            if create_unfound:
-                self.maps[map_pos] = Map(self.game.map_size)
-                for pos in self.maps[map_pos]:
-                    self.maps[map_pos][pos] = '.'
-            else:
-                return None
-        return self.maps[map_pos]
-
-    def proceed_to_next_player_turn(self):
-        """Run game world turns until player can decide their next step.
-
-        Iterates through all non-player things, on each step
-        furthering them in their tasks (and letting them decide new
-        ones if they finish). The iteration order is: first all things
-        that come after the player in the world things list, then
-        (after incrementing the world turn) all that come before the
-        player; then the player's .proceed() is run, and if it does
-        not finish his task, the loop starts at the beginning. Once
-        the player's task is finished, or the player is dead, the loop
-        breaks.
-
-        """
-        while True:
-            player_i = self.things.index(self.player)
-            for thing in self.things[player_i+1:]:
-                thing.proceed()
-            self.turn += 1
-            for pos in self.maps[YX(0,0)]:
-                if self.maps[YX(0,0)][pos] == '.' and \
-                   len(self.things_at_pos((YX(0,0), pos))) == 0 and \
-                   self.rand.random() > 0.999:
-                    self.add_thing_at('food', (YX(0,0), pos))
-            for thing in self.things[:player_i]:
-                thing.proceed()
-            self.player.proceed(is_AI=False)
-            if self.player.task is None or not self.player_is_alive:
-                break
-
-    def add_thing_at(self, type_, pos):
-        t = self.game.thing_types[type_](self)
-        t.position = pos
-        self.things += [t]
-        return t
-
-    def make_new(self, yx, seed):
-
-        def add_thing_at_random(type_):
-            while True:
-                new_pos = (YX(0,0),
-                           YX(self.rand.randint(0, yx.y - 1),
-                              self.rand.randint(0, yx.x - 1)))
-                if self.maps[new_pos[0]][new_pos[1]] != '.':
-                    continue
-                if len(self.things_at_pos(new_pos)) > 0:
-                    continue
-                return self.add_thing_at(type_, new_pos)
-
-        self.things = []
-        self.rand.seed(seed)
-        self.turn = 0
-        self.maps = {}
-        self.game.map_size = yx
-        map_ = self.get_map(YX(0,0))
-        for pos in map_:
-            map_[pos] = self.rand.choice(('.', '.', '.', '~', 'x'))
-        player = add_thing_at_random('human')
-        self.player_id = player.id_
-        add_thing_at_random('monster')
-        add_thing_at_random('monster')
-        add_thing_at_random('food')
-        add_thing_at_random('food')
-        add_thing_at_random('food')
-        add_thing_at_random('food')
-        return 'success'
-
-
-
-class Game:
-
-    def __init__(self, game_file_name):
         self.io = GameIO(game_file_name, self)
         self.map_size = None
         self.map_geometry = MapGeometryHex()
         self.io = GameIO(game_file_name, self)
         self.map_size = None
         self.map_geometry = MapGeometryHex()
@@ -184,12 +86,14 @@ class Game:
                          'TURN': cmd_TURN,
                          'SWITCH_PLAYER': cmd_SWITCH_PLAYER,
                          'SAVE': cmd_SAVE}
                          'TURN': cmd_TURN,
                          'SWITCH_PLAYER': cmd_SWITCH_PLAYER,
                          'SAVE': cmd_SAVE}
-        self.world_type = World
-        self.world = self.world_type(self)
         self.thing_type = Thing
         self.thing_types = {'human': ThingHuman,
                             'monster': ThingMonster,
                             'food': ThingFood}
         self.thing_type = Thing
         self.thing_types = {'human': ThingHuman,
                             'monster': ThingMonster,
                             'food': ThingFood}
+        self.player_id = 0
+        self.player_is_alive = True
+        self.maps = {}
+        self.rand = PRNGod(0)
 
     def get_string_options(self, string_option_type):
         if string_option_type == 'direction':
 
     def get_string_options(self, string_option_type):
         if string_option_type == 'direction':
@@ -208,25 +112,25 @@ class Game:
             self.io.send('THING_TYPE %s %s' % (thing.id_, thing.type_))
             self.io.send('THING_POS %s %s' % (thing.id_, offset_pos))
 
             self.io.send('THING_TYPE %s %s' % (thing.id_, thing.type_))
             self.io.send('THING_POS %s %s' % (thing.id_, offset_pos))
 
-        self.io.send('TURN ' + str(self.world.turn))
-        visible_map = self.world.player.get_visible_map()
-        offset = self.world.player.get_surroundings_offset()
+        self.io.send('TURN ' + str(self.turn))
+        visible_map = self.player.get_visible_map()
+        offset = self.player.get_surroundings_offset()
         self.io.send('VISIBLE_MAP %s %s' % (offset, visible_map.size))
         for y, line in visible_map.lines():
             self.io.send('VISIBLE_MAP_LINE %5s %s' % (y, quote(line)))
         self.io.send('VISIBLE_MAP %s %s' % (offset, visible_map.size))
         for y, line in visible_map.lines():
             self.io.send('VISIBLE_MAP_LINE %5s %s' % (y, quote(line)))
-        visible_things = self.world.player.get_visible_things()
+        visible_things = self.player.get_visible_things()
         for thing in visible_things:
             send_thing(offset, thing)
             if hasattr(thing, 'health'):
                 self.io.send('THING_HEALTH %s %s' % (thing.id_,
                                                      thing.health))
         for thing in visible_things:
             send_thing(offset, thing)
             if hasattr(thing, 'health'):
                 self.io.send('THING_HEALTH %s %s' % (thing.id_,
                                                      thing.health))
-        if len(self.world.player.inventory) > 0:
+        if len(self.player.inventory) > 0:
             self.io.send('PLAYER_INVENTORY %s' %
             self.io.send('PLAYER_INVENTORY %s' %
-                         ','.join([str(i) for i in self.world.player.inventory]))
+                         ','.join([str(i) for i in self.player.inventory]))
         else:
             self.io.send('PLAYER_INVENTORY ,')
         else:
             self.io.send('PLAYER_INVENTORY ,')
-        for id_ in self.world.player.inventory:
-            thing = self.world.get_thing(id_)
+        for id_ in self.player.inventory:
+            thing = self.get_thing(id_)
             send_thing(offset, thing)
         self.io.send('GAME_STATE_COMPLETE')
 
             send_thing(offset, thing)
         self.io.send('GAME_STATE_COMPLETE')
 
@@ -236,9 +140,9 @@ class Game:
         First sends 'TURN_FINISHED' message, then runs game world
         until new player input is needed, then sends game state.
         """
         First sends 'TURN_FINISHED' message, then runs game world
         until new player input is needed, then sends game state.
         """
-        self.io.send('TURN_FINISHED ' + str(self.world.turn))
-        self.world.proceed_to_next_player_turn()
-        msg = str(self.world.player._last_task_result)
+        self.io.send('TURN_FINISHED ' + str(self.turn))
+        self.proceed_to_next_player_turn()
+        msg = str(self.player._last_task_result)
         self.io.send('LAST_PLAYER_TASK_RESULT ' + quote(msg))
         self.send_gamestate()
 
         self.io.send('LAST_PLAYER_TASK_RESULT ' + quote(msg))
         self.send_gamestate()
 
@@ -251,13 +155,13 @@ class Game:
             return p
 
         def cmd_TASK_colon(task_name, game, *args):
             return p
 
         def cmd_TASK_colon(task_name, game, *args):
-            if not game.world.player_is_alive:
+            if not game.player_is_alive:
                 raise GameError('You are dead.')
                 raise GameError('You are dead.')
-            game.world.player.set_task(task_name, args)
+            game.player.set_task(task_name, args)
             game.proceed()
 
         def cmd_SET_TASK_colon(task_name, game, thing_id, todo, *args):
             game.proceed()
 
         def cmd_SET_TASK_colon(task_name, game, thing_id, todo, *args):
-            t = game.world.get_thing(thing_id, False)
+            t = game.get_thing(thing_id, False)
             if t is None:
                 raise ArgError('No such Thing.')
             task_class = game.tasks[task_name]
             if t is None:
                 raise ArgError('No such Thing.')
             task_class = game.tasks[task_name]
@@ -289,3 +193,91 @@ class Game:
             f = partial_with_attrs(self.commands[command_name], self)
             return f
         return None
             f = partial_with_attrs(self.commands[command_name], self)
             return f
         return None
+
+    @property
+    def player(self):
+        return self.get_thing(self.player_id)
+
+    def new_thing_id(self):
+        if len(self.things) == 0:
+            return 0
+        return self.things[-1].id_ + 1
+
+    def get_map(self, map_pos, create_unfound=True):
+        if not (map_pos in self.maps and
+                self.maps[map_pos].size == self.map_size):
+            if create_unfound:
+                self.maps[map_pos] = Map(self.map_size)
+                for pos in self.maps[map_pos]:
+                    self.maps[map_pos][pos] = '.'
+            else:
+                return None
+        return self.maps[map_pos]
+
+    def proceed_to_next_player_turn(self):
+        """Run game world turns until player can decide their next step.
+
+        Iterates through all non-player things, on each step
+        furthering them in their tasks (and letting them decide new
+        ones if they finish). The iteration order is: first all things
+        that come after the player in the world things list, then
+        (after incrementing the world turn) all that come before the
+        player; then the player's .proceed() is run, and if it does
+        not finish his task, the loop starts at the beginning. Once
+        the player's task is finished, or the player is dead, the loop
+        breaks.
+
+        """
+        while True:
+            player_i = self.things.index(self.player)
+            for thing in self.things[player_i+1:]:
+                thing.proceed()
+            self.turn += 1
+            for pos in self.maps[YX(0,0)]:
+                if self.maps[YX(0,0)][pos] == '.' and \
+                   len(self.things_at_pos((YX(0,0), pos))) == 0 and \
+                   self.rand.random() > 0.999:
+                    self.add_thing_at('food', (YX(0,0), pos))
+            for thing in self.things[:player_i]:
+                thing.proceed()
+            self.player.proceed(is_AI=False)
+            if self.player.task is None or not self.player_is_alive:
+                break
+
+    def add_thing_at(self, type_, pos):
+        t = self.thing_types[type_](self)
+        t.position = pos
+        self.things += [t]
+        return t
+
+    def make_new_world(self, yx, seed):
+
+        def add_thing_at_random(type_):
+            while True:
+                new_pos = (YX(0,0),
+                           YX(self.rand.randint(0, yx.y - 1),
+                              self.rand.randint(0, yx.x - 1)))
+                if self.maps[new_pos[0]][new_pos[1]] != '.':
+                    continue
+                if len(self.things_at_pos(new_pos)) > 0:
+                    continue
+                return self.add_thing_at(type_, new_pos)
+
+        self.things = []
+        self.rand.seed(seed)
+        self.turn = 0
+        self.maps = {}
+        self.map_size = yx
+        map_ = self.get_map(YX(0,0))
+        for pos in map_:
+            map_[pos] = self.rand.choice(('.', '.', '.', '~', 'x'))
+        player = add_thing_at_random('human')
+        self.player_id = player.id_
+        add_thing_at_random('monster')
+        add_thing_at_random('monster')
+        add_thing_at_random('food')
+        add_thing_at_random('food')
+        add_thing_at_random('food')
+        add_thing_at_random('food')
+        return 'success'
+
index 6d67c35b1b088b0bf5b617525530668d8c1acbac..11d4ba33ca69b125366f4262f4a65bfc8816617f 100644 (file)
@@ -39,15 +39,15 @@ class Task_MOVE(Task):
     argtypes = 'string:direction'
 
     def get_move_target(self):
     argtypes = 'string:direction'
 
     def get_move_target(self):
-        return self.thing.world.game.map_geometry.move(self.thing.position,
-                                                       self.args[0],
-                                                       self.thing.world.game.map_size)
+        return self.thing.game.map_geometry.move(self.thing.position,
+                                                 self.args[0],
+                                                 self.thing.game.map_size)
 
     def check(self):
         test_pos = self.get_move_target()
 
     def check(self):
         test_pos = self.get_move_target()
-        if self.thing.world.maps[test_pos[0]][test_pos[1]] != '.':
+        if self.thing.game.maps[test_pos[0]][test_pos[1]] != '.':
             raise GameError('%s would move into illegal terrain' % self.thing.id_)
             raise GameError('%s would move into illegal terrain' % self.thing.id_)
-        for t in self.thing.world.things_at_pos(test_pos):
+        for t in self.thing.game.things_at_pos(test_pos):
             if t.blocking:
                 raise GameError('%s would move into other thing' % self.thing.id_)
 
             if t.blocking:
                 raise GameError('%s would move into other thing' % self.thing.id_)
 
@@ -60,15 +60,15 @@ class Task_PICKUP(Task):
     argtypes = 'int:nonneg'
 
     def check(self):
     argtypes = 'int:nonneg'
 
     def check(self):
-        to_pick_up = self.thing.world.get_thing(self.args[0],
-                                                create_unfound=False)
+        to_pick_up = self.thing.game.get_thing(self.args[0],
+                                               create_unfound=False)
         if to_pick_up is None or \
            to_pick_up.id_ not in self.thing.get_pickable_items():
             raise GameError('thing of ID %s not in reach to pick up'
                             % self.args[0])
 
     def do(self):
         if to_pick_up is None or \
            to_pick_up.id_ not in self.thing.get_pickable_items():
             raise GameError('thing of ID %s not in reach to pick up'
                             % self.args[0])
 
     def do(self):
-        to_pick_up = self.thing.world.get_thing(self.args[0])
+        to_pick_up = self.thing.game.get_thing(self.args[0])
         self.thing.inventory += [self.args[0]]
         to_pick_up.in_inventory = True
         to_pick_up.position = self.thing.position
         self.thing.inventory += [self.args[0]]
         to_pick_up.in_inventory = True
         to_pick_up.position = self.thing.position
@@ -79,7 +79,7 @@ class TaskOnInventoryItem(Task):
     argtypes = 'int:nonneg'
 
     def _basic_inventory_item_check(self):
     argtypes = 'int:nonneg'
 
     def _basic_inventory_item_check(self):
-        item = self.thing.world.get_thing(self.args[0], create_unfound=False)
+        item = self.thing.game.get_thing(self.args[0], create_unfound=False)
         if item is None:
             raise GameError('no thing of ID %s' % self.args[0])
         if item.id_ not in self.thing.inventory:
         if item is None:
             raise GameError('no thing of ID %s' % self.args[0])
         if item.id_ not in self.thing.inventory:
@@ -87,7 +87,7 @@ class TaskOnInventoryItem(Task):
         return item
 
     def _eliminate_from_inventory(self):
         return item
 
     def _eliminate_from_inventory(self):
-        item = self.thing.world.get_thing(self.args[0])
+        item = self.thing.game.get_thing(self.args[0])
         del self.thing.inventory[self.thing.inventory.index(item.id_)]
         item.in_inventory = False
         return item
         del self.thing.inventory[self.thing.inventory.index(item.id_)]
         item.in_inventory = False
         return item
@@ -115,5 +115,5 @@ class Task_EAT(TaskOnInventoryItem):
 
     def do(self):
         to_eat = self._eliminate_from_inventory()
 
     def do(self):
         to_eat = self._eliminate_from_inventory()
-        del self.thing.world.things[self.thing.world.things.index(to_eat)]
+        del self.thing.game.things[self.thing.game.things.index(to_eat)]
         self.thing.health += 50
         self.thing.health += 50
index 4f35880b7689644a1e3f1c941f02a93898130077..2e97541a8cb2416eaa3ead7bad023c4b9d75ce3d 100644 (file)
@@ -6,10 +6,10 @@ from plomrogue.mapping import YX, Map, FovMapHex
 class ThingBase:
     type_ = '?'
 
 class ThingBase:
     type_ = '?'
 
-    def __init__(self, world, id_=None, position=(YX(0,0), YX(0,0))):
-        self.world = world
+    def __init__(self, game, id_=None, position=(YX(0,0), YX(0,0))):
+        self.game = game
         if id_ is None:
         if id_ is None:
-            self.id_ = self.world.new_thing_id()
+            self.id_ = self.game.new_thing_id()
         else:
             self.id_ = id_
         self.position = position
         else:
             self.id_ = id_
         self.position = position
@@ -51,30 +51,44 @@ class Thing(ThingBase):
     def _position_set(self, pos):
         super()._position_set(pos)
         for t_id in self.inventory:
     def _position_set(self, pos):
         super()._position_set(pos)
         for t_id in self.inventory:
-            t = self.world.get_thing(t_id)
+            t = self.game.get_thing(t_id)
             t.position = self.position
             t.position = self.position
-        if not self.id_ == self.world.player_id:
+        if not self.id_ == self.game.player_id:
             return
         edge_left = self.position[1].x - self._radius
         edge_right = self.position[1].x + self._radius
         edge_up = self.position[1].y - self._radius
         edge_down = self.position[1].y + self._radius
         if edge_left < 0:
             return
         edge_left = self.position[1].x - self._radius
         edge_right = self.position[1].x + self._radius
         edge_up = self.position[1].y - self._radius
         edge_down = self.position[1].y + self._radius
         if edge_left < 0:
-            self.world.get_map(self.position[0] + YX(1,-1))
-            self.world.get_map(self.position[0] + YX(0,-1))
-            self.world.get_map(self.position[0] + YX(-1,-1))
-        if edge_right >= self.world.game.map_size.x:
-            self.world.get_map(self.position[0] + YX(1,1))
-            self.world.get_map(self.position[0] + YX(0,1))
-            self.world.get_map(self.position[0] + YX(-1,1))
+            self.game.get_map(self.position[0] + YX(1,-1))
+            self.game.get_map(self.position[0] + YX(0,-1))
+            self.game.get_map(self.position[0] + YX(-1,-1))
+        if edge_right >= self.game.map_size.x:
+            self.game.get_map(self.position[0] + YX(1,1))
+            self.game.get_map(self.position[0] + YX(0,1))
+            self.game.get_map(self.position[0] + YX(-1,1))
         if edge_up < 0:
         if edge_up < 0:
-            self.world.get_map(self.position[0] + YX(-1,1))
-            self.world.get_map(self.position[0] + YX(-1,0))
-            self.world.get_map(self.position[0] + YX(-1,-1))
-        if edge_down >= self.world.game.map_size.y:
-            self.world.get_map(self.position[0] + YX(1,1))
-            self.world.get_map(self.position[0] + YX(1,0))
-            self.world.get_map(self.position[0] + YX(1,-1))
+            self.game.get_map(self.position[0] + YX(-1,1))
+            self.game.get_map(self.position[0] + YX(-1,0))
+            self.game.get_map(self.position[0] + YX(-1,-1))
+        if edge_down >= self.game.map_size.y:
+            self.game.get_map(self.position[0] + YX(1,1))
+            self.game.get_map(self.position[0] + YX(1,0))
+            self.game.get_map(self.position[0] + YX(1,-1))
+        #alternative
+        #if self.position[1].x < self._radius:
+        #    self.game.get_map(self.position[0] - YX(0,1))
+        #if self.position[1].y < self._radius:
+        #    self.game.get_map(self.position[0] - YX(1,0))
+        #if self.position[1].x > self.game.map_size.x - self._radius:
+        #    self.game.get_map(self.position[0] + YX(0,1))
+        #if self.position[1].y > self.game.map_size.y - self._radius:
+        #    self.game.get_map(self.position[0] + YX(1,0))
+        #if self.position[1].y < self._radius and \
+        #   self.position[1].x <= [pos for pos in
+        #                          diagonal_distance_edge
+        #                          if pos.y == self.position[1].y][0].x:
+        #    self.game.get_map(self.position[0] - YX(1,1))
 
 
 
 
 
 
@@ -110,16 +124,16 @@ class ThingAnimate(Thing):
             for pos in dijkstra_map:
                 if visible_map[pos] != '.':
                     continue
             for pos in dijkstra_map:
                 if visible_map[pos] != '.':
                     continue
-                neighbors = self.world.game.map_geometry.get_neighbors((YX(0,0), pos),
-                                                                       dijkstra_map.size)
+                neighbors = self.game.map_geometry.get_neighbors((YX(0,0), pos),
+                                                                 dijkstra_map.size)
                 for direction in neighbors:
                     big_yx, small_yx = neighbors[direction]
                     if big_yx == YX(0,0) and \
                        dijkstra_map[small_yx] < dijkstra_map[pos] - 1:
                         dijkstra_map[pos] = dijkstra_map[small_yx] + 1
                         shrunk = True
                 for direction in neighbors:
                     big_yx, small_yx = neighbors[direction]
                     if big_yx == YX(0,0) and \
                        dijkstra_map[small_yx] < dijkstra_map[pos] - 1:
                         dijkstra_map[pos] = dijkstra_map[small_yx] + 1
                         shrunk = True
-        neighbors = self.world.game.map_geometry.get_neighbors((YX(0,0), own_pos),
-                                                               dijkstra_map.size)
+        neighbors = self.game.map_geometry.get_neighbors((YX(0,0), own_pos),
+                                                         dijkstra_map.size)
         n = n_max
         target_direction = None
         for direction in sorted(neighbors.keys()):
         n = n_max
         target_direction = None
         for direction in sorted(neighbors.keys()):
@@ -153,12 +167,12 @@ class ThingAnimate(Thing):
 
     def hunt_food_satisfaction(self):
         for id_ in self.inventory:
 
     def hunt_food_satisfaction(self):
         for id_ in self.inventory:
-            t = self.world.get_thing(id_)
+            t = self.game.get_thing(id_)
             if t.type_ == 'food':
                 self.set_task('EAT', (id_,))
                 return True
         for id_ in self.get_pickable_items():
             if t.type_ == 'food':
                 self.set_task('EAT', (id_,))
                 return True
         for id_ in self.get_pickable_items():
-            t = self.world.get_thing(id_)
+            t = self.game.get_thing(id_)
             if t.type_ == 'food':
                 self.set_task('PICKUP', (id_,))
                 return True
             if t.type_ == 'food':
                 self.set_task('PICKUP', (id_,))
                 return True
@@ -185,7 +199,7 @@ class ThingAnimate(Thing):
             self.set_task('WAIT')
 
     def set_task(self, task_name, args=()):
             self.set_task('WAIT')
 
     def set_task(self, task_name, args=()):
-        task_class = self.world.game.tasks[task_name]
+        task_class = self.game.tasks[task_name]
         self.task = task_class(self, args)
         self.task.check()  # will throw GameError if necessary
 
         self.task = task_class(self, args)
         self.task.check()  # will throw GameError if necessary
 
@@ -193,8 +207,8 @@ class ThingAnimate(Thing):
         """Further the thing in its tasks, decrease its health.
 
         First, ensures an empty map, decrements .health and kills
         """Further the thing in its tasks, decrease its health.
 
         First, ensures an empty map, decrements .health and kills
-        thing if crossing zero (removes from self.world.things for AI
-        thing, or unsets self.world.player_is_alive for player thing);
+        thing if crossing zero (removes from self.game.things for AI
+        thing, or unsets self.game.player_is_alive for player thing);
         then checks that self.task is still possible and aborts if
         otherwise (for AI things, decides a new task).
 
         then checks that self.task is still possible and aborts if
         otherwise (for AI things, decides a new task).
 
@@ -206,10 +220,10 @@ class ThingAnimate(Thing):
         self.unset_surroundings()
         self.health -= 1
         if self.health <= 0:
         self.unset_surroundings()
         self.health -= 1
         if self.health <= 0:
-            if self is self.world.player:
-                self.world.player_is_alive = False
+            if self is self.game.player:
+                self.game.player_is_alive = False
             else:
             else:
-                del self.world.things[self.world.things.index(self)]
+                del self.game.things[self.game.things.index(self)]
             return
         try:
             self.task.check()
             return
         try:
             self.task.check()
@@ -240,9 +254,9 @@ class ThingAnimate(Thing):
     def get_surroundings_offset(self):
         if self._surroundings_offset is not None:
             return self._surroundings_offset
     def get_surroundings_offset(self):
         if self._surroundings_offset is not None:
             return self._surroundings_offset
-        offset = YX(self.position[0].y * self.world.game.map_size.y +
+        offset = YX(self.position[0].y * self.game.map_size.y +
                     self.position[1].y - self._radius,
                     self.position[1].y - self._radius,
-                    self.position[0].x * self.world.game.map_size.x +
+                    self.position[0].x * self.game.map_size.x +
                     self.position[1].x - self._radius)
         self._surroundings_offset = offset
         return self._surroundings_offset
                     self.position[1].x - self._radius)
         self._surroundings_offset = offset
         return self._surroundings_offset
@@ -254,10 +268,11 @@ class ThingAnimate(Thing):
         offset = self.get_surroundings_offset()
         for pos in self._surrounding_map:
             offset_pos = pos + offset
         offset = self.get_surroundings_offset()
         for pos in self._surrounding_map:
             offset_pos = pos + offset
-            big_yx, small_yx = self.world.game.map_geometry.absolutize_coordinate(self.world.game.map_size, (0,0), offset_pos)
-            map_ = self.world.get_map(big_yx, False)
+            absolutize = self.game.map_geometry.absolutize_coordinate
+            big_yx, small_yx = absolutize(self.game.map_size, (0,0), offset_pos)
+            map_ = self.game.get_map(big_yx, False)
             if map_ is None:
             if map_ is None:
-                map_ = Map(size=self.world.game.map_size)
+                map_ = Map(size=self.game.map_size)
             self._surrounding_map[pos] = map_[small_yx]
         return self._surrounding_map
 
             self._surrounding_map[pos] = map_[small_yx]
         return self._surrounding_map
 
@@ -285,10 +300,10 @@ class ThingAnimate(Thing):
         stencil = self.get_stencil()
         offset = self.get_surroundings_offset()
         visible_things = []
         stencil = self.get_stencil()
         offset = self.get_surroundings_offset()
         visible_things = []
-        for thing in self.world.things:
-            pos = self.world.game.map_geometry.pos_in_projection(thing.position,
-                                                                 offset,
-                                                                 self.world.game.map_size)
+        for thing in self.game.things:
+            pos = self.game.map_geometry.pos_in_projection(thing.position,
+                                                           offset,
+                                                           self.game.map_size)
             if pos.y < 0 or pos.x < 0 or\
                pos.y >= stencil.size.y or pos.x >= stencil.size.x:
                 continue
             if pos.y < 0 or pos.x < 0 or\
                pos.y >= stencil.size.y or pos.x >= stencil.size.x:
                 continue
@@ -299,8 +314,8 @@ class ThingAnimate(Thing):
     def get_pickable_items(self):
         pickable_ids = []
         visible_things = self.get_visible_things()
     def get_pickable_items(self):
         pickable_ids = []
         visible_things = self.get_visible_things()
-        neighbor_fields = self.world.game.map_geometry.get_neighbors(self.position,
-                                                                     self.world.game.map_size)
+        neighbor_fields = self.game.map_geometry.get_neighbors(self.position,
+                                                               self.game.map_size)
         for t in [t for t in visible_things
                   if isinstance(t, ThingItem) and
                   (t.position == self.position or
         for t in [t for t in visible_things
                   if isinstance(t, ThingItem) and
                   (t.position == self.position or