home · contact · privacy
Add ever-decreasing health to animate things, and death.
[plomrogue2-experiments] / new / plomrogue / game.py
index d244582deed90cb227bd5caa5cc7dc5e55f4d036..2e780928cd073d6e23d2248ff30307abfcc2b40e 100755 (executable)
@@ -1,14 +1,17 @@
-from plomrogue.tasks import Task_WAIT, Task_MOVE
-from plomrogue.errors import ArgError
-from plomrogue.commands import (cmd_GEN_WORLD, cmd_GET_GAMESTATE, cmd_MAP,
-                                cmd_MAP, cmd_THING_TYPE, cmd_THING_POS,
-                                cmd_TERRAIN_LINE, cmd_PLAYER_ID, cmd_TURN,
-                                cmd_SWITCH_PLAYER, cmd_SAVE)
+from plomrogue.tasks import Task_WAIT, Task_MOVE, Task_PICKUP, Task_DROP
+from plomrogue.errors import ArgError, GameError
+from plomrogue.commands import (cmd_GEN_WORLD, cmd_GET_GAMESTATE,
+                                cmd_MAP, cmd_MAP, cmd_THING_TYPE,
+                                cmd_THING_POS, cmd_THING_INVENTORY,
+                                cmd_THING_HEALTH,
+                                cmd_GET_PICKABLE_ITEMS,
+                                cmd_TERRAIN_LINE, cmd_PLAYER_ID,
+                                cmd_TURN, cmd_SWITCH_PLAYER, cmd_SAVE)
 from plomrogue.mapping import MapHex
 from plomrogue.parser import Parser
 from plomrogue.io import GameIO
 from plomrogue.misc import quote, stringify_yx
 from plomrogue.mapping import MapHex
 from plomrogue.parser import Parser
 from plomrogue.io import GameIO
 from plomrogue.misc import quote, stringify_yx
-from plomrogue.things import Thing
+from plomrogue.things import Thing, ThingMonster, ThingHuman, ThingItem
 
 
 
 
 
 
@@ -36,6 +39,16 @@ class World(WorldBase):
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.player_id = 0
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.player_id = 0
+        self.player_is_alive = True
+
+    @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 new_map(self, yx):
         self.map_ = self.game.map_type(yx)
 
     def new_map(self, yx):
         self.map_ = self.game.map_type(yx)
@@ -50,25 +63,32 @@ class World(WorldBase):
         (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
         (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, the loop breaks.
+        the player's task is finished, or the player is dead, the loop
+        breaks.
+
         """
         while True:
         """
         while True:
-            player = self.get_player()
-            player_i = self.things.index(player)
+            player_i = self.things.index(self.player)
             for thing in self.things[player_i+1:]:
                 thing.proceed()
             self.turn += 1
             for thing in self.things[:player_i]:
                 thing.proceed()
             for thing in self.things[player_i+1:]:
                 thing.proceed()
             self.turn += 1
             for thing in self.things[:player_i]:
                 thing.proceed()
-            player.proceed(is_AI=False)
-            if player.task is None:
+            self.player.proceed(is_AI=False)
+            if self.player.task is None or not self.player_is_alive:
                 break
 
                 break
 
-    def get_player(self):
-        return self.get_thing(self.player_id)
-
     def make_new(self, yx, seed):
         import random
     def make_new(self, yx, seed):
         import random
+
+        def add_thing(type_):
+            t = self.game.thing_types[type_](self)
+            t.position = (random.randint(0, yx[0] -1),
+                          random.randint(0, yx[1] - 1))
+            self.things += [t]
+            return t
+
+        self.things = []
         random.seed(seed)
         self.turn = 0
         self.new_map(yx)
         random.seed(seed)
         self.turn = 0
         self.new_map(yx)
@@ -77,15 +97,13 @@ class World(WorldBase):
                 self.map_[pos] = '#'
                 continue
             self.map_[pos] = random.choice(('.', '.', '.', '.', 'x'))
                 self.map_[pos] = '#'
                 continue
             self.map_[pos] = random.choice(('.', '.', '.', '.', 'x'))
-        player = self.game.thing_type(self, 0)
-        player.type_ = 'human'
-        player.position = [random.randint(0, yx[0] -1),
-                           random.randint(0, yx[1] - 1)]
-        npc = self.game.thing_type(self, 1)
-        npc.type_ = 'monster'
-        npc.position = [random.randint(0, yx[0] -1),
-                        random.randint(0, yx[1] -1)]
-        self.things = [player, npc]
+
+        player = add_thing('human')
+        self.player_id = player.id_
+        add_thing('monster')
+        add_thing('monster')
+        add_thing('item')
+        add_thing('item')
         return 'success'
 
 
         return 'success'
 
 
@@ -95,13 +113,19 @@ class Game:
     def __init__(self, game_file_name):
         self.io = GameIO(game_file_name, self)
         self.map_type = MapHex
     def __init__(self, game_file_name):
         self.io = GameIO(game_file_name, self)
         self.map_type = MapHex
-        self.tasks = {'WAIT': Task_WAIT, 'MOVE': Task_MOVE}
+        self.tasks = {'WAIT': Task_WAIT,
+                      'MOVE': Task_MOVE,
+                      'PICKUP': Task_PICKUP,
+                      'DROP': Task_DROP}
         self.commands = {'GEN_WORLD': cmd_GEN_WORLD,
                          'GET_GAMESTATE': cmd_GET_GAMESTATE,
                          'MAP': cmd_MAP,
                          'THING_TYPE': cmd_THING_TYPE,
                          'THING_POS': cmd_THING_POS,
         self.commands = {'GEN_WORLD': cmd_GEN_WORLD,
                          'GET_GAMESTATE': cmd_GET_GAMESTATE,
                          'MAP': cmd_MAP,
                          'THING_TYPE': cmd_THING_TYPE,
                          'THING_POS': cmd_THING_POS,
+                         'THING_HEALTH': cmd_THING_HEALTH,
+                         'THING_INVENTORY': cmd_THING_INVENTORY,
                          'TERRAIN_LINE': cmd_TERRAIN_LINE,
                          'TERRAIN_LINE': cmd_TERRAIN_LINE,
+                         'GET_PICKABLE_ITEMS': cmd_GET_PICKABLE_ITEMS,
                          'PLAYER_ID': cmd_PLAYER_ID,
                          'TURN': cmd_TURN,
                          'SWITCH_PLAYER': cmd_SWITCH_PLAYER,
                          'PLAYER_ID': cmd_PLAYER_ID,
                          'TURN': cmd_TURN,
                          'SWITCH_PLAYER': cmd_SWITCH_PLAYER,
@@ -109,10 +133,15 @@ class Game:
         self.world_type = World
         self.world = self.world_type(self)
         self.thing_type = Thing
         self.world_type = World
         self.world = self.world_type(self)
         self.thing_type = Thing
+        self.thing_types = {'human': ThingHuman,
+                            'monster': ThingMonster,
+                            'item': ThingItem}
 
     def get_string_options(self, string_option_type):
         if string_option_type == 'direction':
             return self.world.map_.get_directions()
 
     def get_string_options(self, string_option_type):
         if string_option_type == 'direction':
             return self.world.map_.get_directions()
+        elif string_option_type == 'thingtype':
+            return list(self.thing_types.keys())
         return None
 
     def send_gamestate(self, connection_id=None):
         return None
 
     def send_gamestate(self, connection_id=None):
@@ -120,16 +149,27 @@ class Game:
 
         self.io.send('TURN ' + str(self.world.turn))
         self.io.send('MAP ' + stringify_yx(self.world.map_.size))
 
         self.io.send('TURN ' + str(self.world.turn))
         self.io.send('MAP ' + stringify_yx(self.world.map_.size))
-        visible_map = self.world.get_player().get_visible_map()
+        visible_map = self.world.player.get_visible_map()
         for y, line in visible_map.lines():
             self.io.send('VISIBLE_MAP_LINE %5s %s' % (y, quote(line)))
         for y, line in visible_map.lines():
             self.io.send('VISIBLE_MAP_LINE %5s %s' % (y, quote(line)))
-        visible_things = self.world.get_player().get_visible_things()
+        visible_things = self.world.player.get_visible_things()
         for thing in visible_things:
             self.io.send('THING_TYPE %s %s' % (thing.id_, thing.type_))
             self.io.send('THING_POS %s %s' % (thing.id_,
                                               stringify_yx(thing.position)))
         for thing in visible_things:
             self.io.send('THING_TYPE %s %s' % (thing.id_, thing.type_))
             self.io.send('THING_POS %s %s' % (thing.id_,
                                               stringify_yx(thing.position)))
-        player = self.world.get_player()
-        self.io.send('PLAYER_POS %s' % (stringify_yx(player.position)))
+            if hasattr(thing, 'health'):
+                self.io.send('THING_HEALTH %s %s' % (thing.id_,
+                                                     thing.health))
+        if len(self.world.player.inventory) > 0:
+            self.io.send('PLAYER_INVENTORY %s' %
+                         ','.join([str(i) for i in self.world.player.inventory]))
+        else:
+            self.io.send('PLAYER_INVENTORY ,')
+        for id_ in self.world.player.inventory:
+            thing = self.world.get_thing(id_)
+            self.io.send('THING_TYPE %s %s' % (thing.id_, thing.type_))
+            self.io.send('THING_POS %s %s' % (thing.id_,
+                                              stringify_yx(thing.position)))
         self.io.send('GAME_STATE_COMPLETE')
 
     def proceed(self):
         self.io.send('GAME_STATE_COMPLETE')
 
     def proceed(self):
@@ -140,7 +180,7 @@ class Game:
         """
         self.io.send('TURN_FINISHED ' + str(self.world.turn))
         self.world.proceed_to_next_player_turn()
         """
         self.io.send('TURN_FINISHED ' + str(self.world.turn))
         self.world.proceed_to_next_player_turn()
-        msg = str(self.world.get_player()._last_task_result)
+        msg = str(self.world.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()
 
@@ -153,7 +193,9 @@ class Game:
             return p
 
         def cmd_TASK_colon(task_name, game, *args):
             return p
 
         def cmd_TASK_colon(task_name, game, *args):
-            game.world.get_player().set_task(task_name, args)
+            if not game.world.player_is_alive:
+                raise GameError('You are dead.')
+            game.world.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):