X-Git-Url: https://plomlompom.com/repos/condition_titles?a=blobdiff_plain;f=server.py;h=22cd7ec3f8ffa9a338888830a68b764549d811cb;hb=877b51134a2ce2e808e9403194d05b88b1b3b801;hp=8a9d0578b210199c930f84d2484d4c236a697d4d;hpb=0fc41c2a7adfcf282beeea4e7df0fb7bfd6dc5ab;p=plomrogue2-experiments diff --git a/server.py b/server.py index 8a9d057..22cd7ec 100755 --- a/server.py +++ b/server.py @@ -10,6 +10,10 @@ from parser import ArgError, Parser socketserver.TCPServer.allow_reuse_address = True +class GameError(Exception): + pass + + class Server(socketserver.ThreadingTCPServer): """Bind together threaded IO handling server and message queue.""" @@ -81,34 +85,57 @@ class IO_Handler(socketserver.BaseRequestHandler): self.request.close() +def move_pos(direction, pos_yx): + if direction == 'UP': + pos_yx[0] -= 1 + elif direction == 'DOWN': + pos_yx[0] += 1 + elif direction == 'RIGHT': + pos_yx[1] += 1 + elif direction == 'LEFT': + pos_yx[1] -= 1 + + class Task: - def __init__(self, name, args=(), kwargs={}): + def __init__(self, thing, name, args=(), kwargs={}): self.name = name + self.thing = thing self.args = args self.kwargs = kwargs self.todo = 1 + def check(self): + if self.name == 'move': + if len(self.args) > 0: + direction = self.args[0] + else: + direction = self.kwargs['direction'] + test_pos = self.thing.position[:] + move_pos(direction, test_pos) + if test_pos[0] < 0 or test_pos[1] < 0 or \ + test_pos[0] >= self.thing.world.map_size[0] or \ + test_pos[1] >= self.thing.world.map_size[1]: + raise GameError('would move outside map bounds') + pos_i = test_pos[0] * self.thing.world.map_size[1] + test_pos[1] + map_tile = self.thing.world.map_[pos_i] + if map_tile != '.': + raise GameError('would move into illegal terrain') + class Thing: - def __init__(self, type_, position): - self.type = type_ + def __init__(self, world, type_, position): + self.world = world + self.type_ = type_ self.position = position - self.task = Task('wait') + self.task = Task(self, 'wait') def task_wait(self): pass def task_move(self, direction): - if direction == 'UP': - self.position[0] -= 1 - elif direction == 'DOWN': - self.position[0] += 1 - elif direction == 'RIGHT': - self.position[1] += 1 - elif direction == 'LEFT': - self.position[1] -= 1 + move_pos(direction, self.position) def decide_task(self): if self.position[1] > 1: @@ -119,7 +146,8 @@ class Thing: self.set_task('wait') def set_task(self, task, *args, **kwargs): - self.task = Task(task, args, kwargs) + self.task = Task(self, task, args, kwargs) + self.task.check() def proceed(self, is_AI=True): """Further the thing in its tasks. @@ -142,12 +170,15 @@ class World: def __init__(self): self.turn = 0 self.map_size = (5, 5) - self.map_ = 'xxxxx\n' +\ - 'x...x\n' +\ - 'x.X.x\n' +\ - 'x...x\n' +\ + self.map_ = 'xxxxx' +\ + 'x...x' +\ + 'x.X.x' +\ + 'x...x' +\ 'xxxxx' - self.things = [Thing('human', [3, 3]), Thing('monster', [1, 1])] + self.things = [ + Thing(self, 'human', [3, 3]), + Thing(self, 'monster', [1, 1]) + ] self.player_i = 0 self.player = self.things[self.player_i] @@ -182,6 +213,8 @@ class CommandHandler: command(connection_id=connection_id) except ArgError as e: self.send_to(connection_id, 'ARGUMENT ERROR: ' + str(e)) + except GameError as e: + self.send_to(connection_id, 'GAME ERROR: ' + str(e)) def send_to(self, connection_id, msg): """Send msg to client of connection_id.""" @@ -207,13 +240,25 @@ class CommandHandler: quoted += ['"'] return ''.join(quoted) + def quoted_map(self, map_string, map_width): + """Put \n into map_string at map_width intervals, return quoted whole.""" + map_lines = [] + map_size = len(map_string) + start_cut = 0 + while start_cut < map_size: + limit = start_cut + map_width + map_lines += [map_string[start_cut:limit]] + start_cut = limit + return self.quoted("\n".join(map_lines)) + def send_all_gamestate(self): """Send out game state data relevant to clients.""" self.send_all('NEW_TURN ' + str(self.world.turn)) self.send_all('MAP_SIZE ' + self.stringify_yx(self.world.map_size)) - self.send_all('TERRAIN\n' + self.quoted(self.world.map_)) + self.send_all('TERRAIN\n' + self.quoted_map(self.world.map_, + self.world.map_size[1])) for thing in self.world.things: - self.send_all('THING TYPE:' + thing.type + ' ' + self.send_all('THING TYPE:' + thing.type_ + ' ' + self.stringify_yx(thing.position)) def proceed_to_next_player_turn(self, connection_id):