+ def get_info(self):
+ if self.info_cached:
+ return self.info_cached
+ pos_i = self.explorer.y * self.game.map_geometry.size.x + self.explorer.x
+ info_to_cache = ''
+ if len(self.game.fov) > pos_i and self.game.fov[pos_i] != '.':
+ info_to_cache += 'outside field of view'
+ else:
+ for t in self.game.things:
+ if t.position == self.explorer:
+ info_to_cache += '%s' % self.get_thing_info(t, True)
+ terrain_char = self.game.map_content[pos_i]
+ terrain_desc = '?'
+ if terrain_char in self.game.terrains:
+ terrain_desc = self.game.terrains[terrain_char]
+ info_to_cache += 'TERRAIN: %s (%s' % (terrain_char,
+ terrain_desc)
+ protection = self.game.map_control_content[pos_i]
+ if protection != '.':
+ info_to_cache += '/protection:%s' % protection
+ info_to_cache += ')\n'
+ if self.explorer in self.game.portals:
+ info_to_cache += 'PORTAL: ' +\
+ self.game.portals[self.explorer] + '\n'
+ if self.explorer in self.game.annotations:
+ info_to_cache += 'ANNOTATION: ' +\
+ self.game.annotations[self.explorer]
+ self.info_cached = info_to_cache
+ return self.info_cached
+
+ def get_thing_info(self, t, detailed=False):
+ info = ''
+ if detailed:
+ info += '- '
+ info += self.game.thing_types[t.type_]
+ if hasattr(t, 'thing_char'):
+ info += t.thing_char
+ if hasattr(t, 'name'):
+ info += ': %s' % t.name
+ info += ' (%s' % t.type_
+ if hasattr(t, 'installed'):
+ info += '/installed'
+ if t.type_ == 'Bottle':
+ if t.thing_char == '_':
+ info += '/empty'
+ elif t.thing_char == '~':
+ info += '/full'
+ if detailed:
+ protection = t.protection
+ if protection != '.':
+ info += '/protection:%s' % protection
+ info += ')\n'
+ if hasattr(t, 'hat') or hasattr(t, 'face'):
+ info += '----------\n'
+ if hasattr(t, 'hat'):
+ info += '| %s |\n' % t.hat[0:6]
+ info += '| %s |\n' % t.hat[6:12]
+ info += '| %s |\n' % t.hat[12:18]
+ if hasattr(t, 'face'):
+ info += '| %s |\n' % t.face[0:6]
+ info += '| %s |\n' % t.face[6:12]
+ info += '| %s |\n' % t.face[12:18]
+ info += '----------\n'
+ if hasattr(t, 'design'):
+ line_length = t.design[0].x
+ lines = []
+ for i in range(t.design[0].y):
+ start = i * line_length
+ end = (i + 1) * line_length
+ lines += [t.design[1][start:end]]
+ info += '-' * (line_length + 4) + '\n'
+ for line in lines:
+ info += '| %s |\n' % line
+ info += '-' * (line_length + 4) + '\n'
+ else:
+ info += ')'
+ return info
+
+ def reset_size(self):
+ super().reset_size()
+ self.left_window_width = min(52, int(self.size.x / 2))
+ self.right_window_width = self.size.x - self.left_window_width
+
+ def addstr(self, y, x, line, ignore=None):
+ super().addstr(y, x, line, curses.color_pair(1))
+
+ def init_loop(self):
+ self.switch_mode('waiting_for_server')
+ curses.start_color()
+ self.set_default_colors()
+ curses.init_pair(1, 7, 0)
+ if not curses.can_change_color():
+ self.log('@ unfortunately, your terminal does not seem to '
+ 'support re-definition of colors; you might miss out '
+ 'on some color effects')
+ super().init_loop()
+
+ def recalc_input_lines(self):
+ if not self.mode.has_input_prompt:
+ self.input_lines = []
+ else:
+ self.input_lines = msg_into_lines_of_width(self.input_prompt
+ + self.input_ + '█',
+ self.right_window_width)
+ def draw_history(self):
+ lines = []
+ for line in self._log:
+ lines += msg_into_lines_of_width(line, self.right_window_width)
+ lines.reverse()
+ height_header = 2
+ max_y = self.size.y - len(self.input_lines)
+ for i in range(len(lines)):
+ if (i >= max_y - height_header):
+ break
+ self.addstr(max_y - i - 1, self.left_window_width, lines[i])
+
+ def draw_info(self):
+ info = 'MAP VIEW: %s\n%s' % (self.map_mode, self.get_info())
+ lines = msg_into_lines_of_width(info, self.right_window_width)
+ height_header = 2
+ for i in range(len(lines)):
+ y = height_header + i
+ if y >= self.size.y - len(self.input_lines):
+ break
+ self.addstr(y, self.left_window_width, lines[i])
+
+ def draw_input(self):
+ y = self.size.y - len(self.input_lines)
+ for i in range(len(self.input_lines)):
+ self.addstr(y, self.left_window_width, self.input_lines[i])
+ y += 1
+
+ def draw_stats(self):
+ stats = 'ENERGY: %s BLADDER: %s' % (self.game.energy,
+ self.game.bladder_pressure)
+ self.addstr(0, self.left_window_width, stats)
+
+ def draw_mode(self):
+ help = "hit [%s] for help" % self.keys['help']
+ if self.mode.has_input_prompt:
+ help = "enter /help for help"
+ self.addstr(1, self.left_window_width,
+ 'MODE: %s – %s' % (self.mode.short_desc, help))
+
+ def draw_map(self):
+ if (not self.game.turn_complete) and len(self.map_lines) == 0:
+ return
+ if self.game.turn_complete:
+ map_lines_split = []
+ for y in range(self.game.map_geometry.size.y):
+ start = self.game.map_geometry.size.x * y
+ end = start + self.game.map_geometry.size.x
+ if self.map_mode == 'protections':
+ map_lines_split += [[c + ' ' for c
+ in self.game.map_control_content[start:end]]]
+ else:
+ map_lines_split += [[c + ' ' for c
+ in self.game.map_content[start:end]]]
+ if self.map_mode == 'terrain + annotations':
+ for p in self.game.annotations:
+ map_lines_split[p.y][p.x] = 'A '
+ elif self.map_mode == 'terrain + things':
+ for p in self.game.portals.keys():
+ original = map_lines_split[p.y][p.x]
+ map_lines_split[p.y][p.x] = original[0] + 'P'
+ used_positions = []
+
+ def draw_thing(t, used_positions):
+ symbol = self.game.thing_types[t.type_]
+ meta_char = ' '
+ if hasattr(t, 'thing_char'):
+ meta_char = t.thing_char
+ if t.position in used_positions:
+ meta_char = '+'
+ if hasattr(t, 'carrying') and t.carrying:
+ meta_char = '$'
+ map_lines_split[t.position.y][t.position.x] = symbol + meta_char
+ used_positions += [t.position]
+
+ for t in [t for t in self.game.things if t.type_ != 'Player']:
+ draw_thing(t, used_positions)
+ for t in [t for t in self.game.things if t.type_ == 'Player']:
+ draw_thing(t, used_positions)
+ if self.mode.shows_info or self.mode.name == 'control_tile_draw':
+ map_lines_split[self.explorer.y][self.explorer.x] = '??'
+ elif self.map_mode != 'terrain + things':
+ map_lines_split[self.game.player.position.y]\
+ [self.game.player.position.x] = '??'
+ self.map_lines = []
+ if type(self.game.map_geometry) == MapGeometryHex:
+ indent = 0
+ for line in map_lines_split:
+ self.map_lines += [indent * ' ' + ''.join(line)]
+ indent = 0 if indent else 1
+ else:
+ for line in map_lines_split:
+ self.map_lines += [''.join(line)]
+ window_center = YX(int(self.size.y / 2),
+ int(self.left_window_width / 2))
+ center = self.game.player.position
+ if self.mode.shows_info or self.mode.name == 'control_tile_draw':
+ center = self.explorer
+ center = YX(center.y, center.x * 2)
+ self.offset = center - window_center
+ if type(self.game.map_geometry) == MapGeometryHex and self.offset.y % 2:
+ self.offset += YX(0, 1)
+ term_y = max(0, -self.offset.y)
+ term_x = max(0, -self.offset.x)
+ map_y = max(0, self.offset.y)
+ map_x = max(0, self.offset.x)
+ while term_y < self.size.y and map_y < len(self.map_lines):
+ to_draw = self.map_lines[map_y][map_x:self.left_window_width + self.offset.x]
+ self.addstr(term_y, term_x, to_draw)
+ term_y += 1
+ map_y += 1
+
+ def draw_names(self):
+ players = [t for t in self.game.things if t.type_ == 'Player']
+ players.sort(key=lambda t: len(t.name))
+ players.reverse()
+ shrink_offset = max(0, (self.size.y - self.left_window_width // 2) // 2)
+ y = 0
+ for t in players:
+ offset_y = y - shrink_offset
+ max_len = max(5, (self.left_window_width // 2) - (offset_y * 2) - 8)
+ name = t.name[:]
+ if len(name) > max_len:
+ name = name[:max_len - 1] + '…'
+ self.addstr(y, 0, '@%s:%s' % (t.thing_char, name))
+ y += 1
+ if y >= self.size.y:
+ break