+from parser import ArgError, Parser
+import game_common
+
+
+class MapSquare(game_common.Map):
+
+ def list_terrain_to_lines(self, terrain_as_list, center, size):
+ terrain = ''.join(terrain_as_list)
+ map_lines = []
+ start_cut = 0
+ while start_cut < len(terrain):
+ limit = start_cut + self.size[1]
+ map_lines += [terrain[start_cut:limit]]
+ start_cut = limit
+ if len(map_lines) > size[0] and center[0] > size[0] / 2:
+ diff = len(map_lines) - size[0]
+ if center[0] > len(map_lines) - size[0] / 2:
+ map_lines = map_lines[diff:]
+ else:
+ start = center[0] - int(size[0] / 2)
+ map_lines = map_lines[start:start + size[0]]
+ if self.size[1] > size[1] and center[1] > size[1] / 2:
+ if center[1] > self.size[1] - size[1] / 2:
+ cut_start = self.size[1] - size[1]
+ cut_end = None
+ else:
+ cut_start = center[1] - int(size[1] / 2)
+ cut_end = cut_start + size[1]
+ map_lines = [line[cut_start:cut_end] for line in map_lines]
+ return map_lines
+
+
+class MapHex(game_common.Map):
+
+ def list_terrain_to_lines(self, terrain_as_list, center, size):
+ new_terrain_list = [' ']
+ x = 0
+ y = 0
+ for c in terrain_as_list:
+ new_terrain_list += [c, ' ']
+ x += 1
+ if x == self.size[1]:
+ new_terrain_list += ['\n']
+ x = 0
+ y += 1
+ if y % 2 == 0:
+ new_terrain_list += [' ']
+ map_lines = ''.join(new_terrain_list).split('\n')
+ if len(map_lines) > size[0] and center[0] > size[0] / 2:
+ diff = len(map_lines) - size[0]
+ if center[0] > len(map_lines) - size[0] / 2:
+ map_lines = map_lines[diff:]
+ else:
+ start = center[0] - int(size[0] / 2)
+ map_lines = map_lines[start:start + size[0]]
+ if self.size[1]*2 > size[1] and center[1]*4 > size[1]:
+ if center[1]*2 > self.size[1]*2 - size[1] / 2:
+ cut_start = self.size[1] * 2 - size[1]
+ cut_end = None
+ else:
+ cut_start = center[1]*2 - int(size[1] / 2)
+ cut_end = cut_start + size[1]
+ map_lines = [line[cut_start:cut_end] for line in map_lines]
+ return map_lines
+
+
+map_manager = game_common.MapManager(globals())
+
+
+class World(game_common.World):
+
+ def __init__(self, game, *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.game = game
+ self.map_ = self.game.map_manager.get_map_class('Hex')()
+ self.player_position = (0, 0)
+
+
+class Game(game_common.CommonCommandsMixin):
+
+ def __init__(self):
+ self.map_manager = map_manager
+ self.parser = Parser(self)
+ self.world = World(self)
+ self.log_text = ''
+ self.to_update = {
+ 'log': False,
+ 'map': False,
+ 'turn': False,
+ }
+ self.do_quit = False
+
+ def handle_input(self, msg):
+ if msg == 'BYE':
+ self.do_quit = True
+ return
+ try:
+ command = self.parser.parse(msg)
+ if command is None:
+ self.log('UNHANDLED INPUT: ' + msg)
+ self.to_update['log'] = True
+ else:
+ command()
+ except ArgError as e:
+ self.log('ARGUMENT ERROR: ' + msg + '\n' + str(e))
+ self.to_update['log'] = True
+
+ def log(self, msg):
+ """Prefix msg plus newline to self.log_text."""
+ self.log_text = msg + '\n' + self.log_text
+
+ def symbol_for_type(self, type_):
+ symbol = '?'
+ if type_ == 'human':
+ symbol = '@'
+ elif type_ == 'monster':
+ symbol = 'm'
+ return symbol
+
+ def cmd_LAST_PLAYER_TASK_RESULT(self, msg):
+ if msg != "success":
+ self.log(msg)
+ self.to_update['log'] = True
+ cmd_LAST_PLAYER_TASK_RESULT.argtypes = 'string'
+
+ def cmd_TURN_FINISHED(self, n):
+ """Do nothing. (This may be extended later.)"""
+ pass
+ cmd_TURN_FINISHED.argtypes = 'int:nonneg'
+
+ def cmd_NEW_TURN(self, n):
+ """Set self.turn to n, empty self.things."""
+ self.world.turn = n
+ self.world.things = []
+ cmd_NEW_TURN.argtypes = 'int:nonneg'
+
+ def cmd_VISIBLE_MAP_LINE(self, y, terrain_line):
+ self.world.map_.set_line(y, terrain_line)
+ cmd_VISIBLE_MAP_LINE.argtypes = 'int:nonneg string'
+
+ def cmd_PLAYER_POS(self, yx):
+ self.world.player_position = yx
+ cmd_PLAYER_POS.argtypes = 'yx_tuple:pos'
+
+ def cmd_GAME_STATE_COMPLETE(self):
+ self.to_update['turn'] = True
+ self.to_update['map'] = True
+