home · contact · privacy
Move hardcoding of world data to init process.
authorChristian Heller <c.heller@plomlompom.de>
Tue, 11 Dec 2018 22:27:21 +0000 (23:27 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 11 Dec 2018 22:27:21 +0000 (23:27 +0100)
client.py
server.py
server_/game.py

index df5d7e360147a074e2f5754ed9e0ece91e514502..c5d6fcde99000d5972cd9d0a4b3c93a5737ed25b 100755 (executable)
--- a/client.py
+++ b/client.py
@@ -9,12 +9,13 @@ from parser import ArgError, Parser
 class Game:
     turn = 0
     log_text = ''
-    map_size = (5, 5)
-    terrain_map = ('?'*5)*5
+    map_size = (0, 0)
+    terrain_map = ''
     things = []
 
     class Thing:
-        def __init__(self, position, symbol):
+        def __init__(self, id_, position, symbol):
+            self.id_ = id_
             self.position = position
             self.symbol = symbol
 
@@ -22,15 +23,33 @@ class Game:
         """Prefix msg plus newline to self.log_text."""
         self.log_text = msg + '\n' + self.log_text
 
-    def cmd_THING(self, type_, yx):
-        """Add to self.things at .position yx with .symbol defined by type_."""
+    def get_thing(self, i):
+        for thing in self.things:
+            if i == thing.id_:
+                return thing
+        t = self.Thing(i, [0,0], '?')
+        self.things += [t]
+        return t
+
+    def cmd_THING_TYPE(self, i, type_):
+        t = self.get_thing(i)
         symbol = '?'
-        if type_ == 'TYPE:human':
+        if type_ == 'human':
             symbol = '@'
-        elif type_ == 'TYPE:monster':
+        elif type_ == 'monster':
             symbol = 'm'
-        self.things += [self.Thing(yx, symbol)]
-    cmd_THING.argtypes = 'string yx_tuple:nonneg'
+        t.symbol = symbol
+    cmd_THING_TYPE.argtypes = 'int:nonneg string'
+
+    def cmd_THING_POS(self, i, yx):
+        t = self.get_thing(i)
+        t.position = list(yx)
+    cmd_THING_POS.argtypes = 'int:nonneg yx_tuple:nonneg'
+
+    def cmd_THING_POS(self, i, yx):
+        t = self.get_thing(i)
+        t.position = list(yx)
+    cmd_THING_POS.argtypes = 'int:nonneg yx_tuple:nonneg'
 
     def cmd_MAP_SIZE(self, yx):
         """Set self.map_size to yx, redraw self.terrain_map as '?' cells."""
@@ -38,8 +57,7 @@ class Game:
         self.map_size = (y, x)
         self.terrain_map = ''
         for y in range(self.map_size[0]):
-            self.terrain_map += '?' * self.map_size[1]# + '\n'
-        self.terrain_map = self.terrain_map[:-1]
+            self.terrain_map += '?' * self.map_size[1]
     cmd_MAP_SIZE.argtypes = 'yx_tuple:nonneg'
 
     def cmd_TURN_FINISHED(self, n):
index e688f2cf41f7d903207d5e2d4d226a4af35b78b3..16915e9e6671d982fb200c6aa18da8805d041205 100755 (executable)
--- a/server.py
+++ b/server.py
@@ -94,9 +94,9 @@ def fib(n):
 
 class CommandHandler:
 
-    def __init__(self, queues_out={}):
+    def __init__(self):
         from multiprocessing import Pool
-        self.queues_out = queues_out
+        self.queues_out = {}
         self.world = World()
         self.parser = Parser(self)
         # self.pool and self.pool_result are currently only needed by the FIB
@@ -157,8 +157,8 @@ class CommandHandler:
             terrain_line = self.world.map_[y * width:(y + 1) * width]
             self.send_all('TERRAIN_LINE %5s %s' % (y, self.quoted(terrain_line)))
         for thing in self.world.things:
-            self.send_all('THING TYPE:' + thing.type_ + ' '
-                          + self.stringify_yx(thing.position))
+            self.send_all('THING_TYPE %s %s' % (thing.id_, thing.type_))
+            self.send_all('THING_POS %s %s' % (thing.id_, self.stringify_yx(thing.position)))
 
     def proceed(self):
         """Send turn finish signal, run game world, send new world data.
@@ -170,20 +170,41 @@ class CommandHandler:
         self.world.proceed_to_next_player_turn()
         self.send_all_gamestate()
 
+    def get_player(self):
+        return self.world.get_thing(self.world.player_id)
+
     def cmd_MOVE(self, direction, connection_id):
         """Set player task to 'move' with direction arg, finish player turn."""
         if direction not in {'UP', 'DOWN', 'RIGHT', 'LEFT'}:
             raise ArgError('Move argument must be one of: '
                            'UP, DOWN, RIGHT, LEFT')
-        self.world.player.set_task('move', direction=direction)
+        self.get_player().set_task('move', direction=direction)
         self.proceed()
     cmd_MOVE.argtypes = 'string'
 
     def cmd_WAIT(self, connection_id):
         """Set player task to 'wait', finish player turn."""
-        self.world.player.set_task('wait')
+        self.get_player().set_task('wait')
         self.proceed()
 
+    def cmd_MAP_SIZE(self, yx, connection_id):
+        self.world.set_map_size(yx)
+    cmd_MAP_SIZE.argtypes = 'yx_tuple:nonneg'
+
+    def cmd_TERRAIN_LINE(self, y, line, connection_id):
+        self.world.set_map_line(y, line)
+    cmd_TERRAIN_LINE.argtypes = 'int:nonneg string'
+
+    def cmd_THING_TYPE(self, i, type_, connection_id):
+        t = self.world.get_thing(i)
+        t.type_ = type_
+    cmd_THING_TYPE.argtypes = 'int:nonneg string'
+
+    def cmd_THING_POS(self, i, yx, connection_id):
+        t = self.world.get_thing(i)
+        t.position = list(yx)
+    cmd_THING_POS.argtypes = 'int:nonneg yx_tuple:nonneg'
+
     def cmd_GET_TURN(self, connection_id):
         """Send world.turn to caller."""
         self.send_to(connection_id, str(self.world.turn))
@@ -279,6 +300,17 @@ if os.path.exists(game_file_name):
             line = lines[i]
             print("FILE INPUT LINE %s: %s" % (i, line), end='')
             commander.handle_input(line, abort_on_error=True)
+else:
+    commander.handle_input('MAP_SIZE Y:5,X:5')
+    commander.handle_input('TERRAIN_LINE 0 "xxxxx"')
+    commander.handle_input('TERRAIN_LINE 1 "x...x"')
+    commander.handle_input('TERRAIN_LINE 2 "x.X.x"')
+    commander.handle_input('TERRAIN_LINE 3 "x...x"')
+    commander.handle_input('TERRAIN_LINE 4 "xxxxx"')
+    commander.handle_input('THING_TYPE 0 human')
+    commander.handle_input('THING_POS 0 Y:3,X:3')
+    commander.handle_input('THING_TYPE 1 monster')
+    commander.handle_input('THING_POS 1 Y:1,X:1')
 q = queue.Queue()
 c = threading.Thread(target=io_loop, daemon=True, args=(q, commander))
 c.start()
index e24b30aad2958df13fecebd9b10cce416289d686..f9492896102895738b6705cec7bded3c9fb87ba9 100644 (file)
@@ -17,18 +17,14 @@ class World:
 
     def __init__(self):
         self.turn = 0
-        self.map_size = (5, 5)
-        self.map_ = 'xxxxx' +\
-                    'x...x' +\
-                    'x.X.x' +\
-                    'x...x' +\
-                    'xxxxx'
-        self.things = [
-            Thing(self, 'human', [3, 3]),
-            Thing(self, 'monster', [1, 1])
-        ]
-        self.player_i = 0
-        self.player = self.things[self.player_i]
+        self.map_size = (0, 0)
+        self.map_ = ''
+        self.things = []
+#            Thing(self, 'human', [3, 3]),
+#            Thing(self, 'monster', [1, 1])
+#        ]
+        self.player_id = 0
+#        self.player = self.things[self.player_i]
 
     def proceed_to_next_player_turn(self):
         """Run game world turns until player can decide their next step.
@@ -43,15 +39,42 @@ class World:
         the player's task is finished, the loop breaks.
         """
         while True:
-            for thing in self.things[self.player_i+1:]:
+            for thing in self.things[self.player_id+1:]:
                 thing.proceed()
             self.turn += 1
-            for thing in self.things[:self.player_i]:
+            for thing in self.things[:self.player_id]:
                 thing.proceed()
-            self.player.proceed(is_AI=False)
-            if self.player.task is None:
+            player = self.get_thing(self.player_id)
+            player.proceed(is_AI=False)
+            if player.task is None:
                 break
 
+    def set_map_size(self, yx):
+        y, x = yx
+        self.map_size = (y, x)
+        self.map_ = ''
+        for y in range(self.map_size[0]):
+            self.map_ += '?' * self.map_size[1]
+
+    def set_map_line(self, y, line):
+        width_map = self.map_size[1]
+        if y >= self.map_size[0]:
+            raise ArgError('too large row number %s' % y)
+        width_line = len(line)
+        if width_line > width_map:
+            raise ArgError('too large map line width %s' % width_line)
+        self.map_ = self.map_[:y * width_map] + line + \
+                    self.map_[(y + 1) * width_map:]
+
+    def get_thing(self, i):
+        for thing in self.things:
+            if i == thing.id_:
+                return thing
+        t = Thing(self, i, '?', [0,0])
+        self.things += [t]
+        return t
+
+
 class Task:
 
     def __init__(self, thing, name, args=(), kwargs={}):
@@ -81,8 +104,9 @@ class Task:
 
 class Thing:
 
-    def __init__(self, world, type_, position):
+    def __init__(self, world, id_, type_, position):
         self.world = world
+        self.id_ = id_
         self.type_ = type_
         self.position = position
         self.task = Task(self, 'wait')
@@ -101,8 +125,8 @@ class Thing:
         else:
             self.set_task('wait')
 
-    def set_task(self, task, *args, **kwargs):
-        self.task = Task(self, task, args, kwargs)
+    def set_task(self, task_name, *args, **kwargs):
+        self.task = Task(self, task_name, args, kwargs)
         self.task.check()
 
     def proceed(self, is_AI=True):