'on some color effects')
super().init_loop()
- def loop(self):
+ 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
+
+ def draw_face_popup(self):
+ t = self.game.get_thing(self.draw_face)
+ if not t or not hasattr(t, 'face'):
+ self.draw_face = False
+ return
+
+ start_x = self.left_window_width - 10
+ def draw_body_part(body_part, end_y):
+ self.addstr(end_y - 3, start_x, '----------')
+ self.addstr(end_y - 2, start_x, '| ' + body_part[0:6] + ' |')
+ self.addstr(end_y - 1, start_x, '| ' + body_part[6:12] + ' |')
+ self.addstr(end_y, start_x, '| ' + body_part[12:18] + ' |')
+
+ if hasattr(t, 'face'):
+ draw_body_part(t.face, self.size.y - 3)
+ if hasattr(t, 'hat'):
+ draw_body_part(t.hat, self.size.y - 6)
+ self.addstr(self.size.y - 2, start_x, '----------')
+ name = t.name[:]
+ if len(name) > 7:
+ name = name[:6 - 1] + '…'
+ self.addstr(self.size.y - 1, start_x, '@%s:%s' % (t.thing_char, name))
+
+ def draw_help(self):
+ content = "%s help\n\n%s\n\n" % (self.mode.short_desc,
+ self.mode.help_intro)
+ if len(self.mode.available_actions) > 0:
+ content += "Available actions:\n"
+ for action in self.mode.available_actions:
+ if action in self.action_tasks:
+ if self.action_tasks[action] not in self.game.tasks:
+ continue
+ if action == 'move_explorer':
+ action = 'move'
+ if action == 'move':
+ key = ','.join(self.movement_keys)
+ else:
+ key = self.keys[action]
+ content += '[%s] – %s\n' % (key, self.action_descriptions[action])
+ content += '\n'
+ content += self.mode.list_available_modes(self)
+ for i in range(self.size.y):
+ self.addstr(i,
+ self.left_window_width * (not self.mode.has_input_prompt),
+ ' ' * self.left_window_width)
+ lines = []
+ for line in content.split('\n'):
+ lines += msg_into_lines_of_width(line, self.right_window_width)
+ for i in range(len(lines)):
+ if i >= self.size.y:
+ break
+ self.addstr(i,
+ self.left_window_width * (not self.mode.has_input_prompt),
+ lines[i])
+
+ def draw_screen(self):
+ super().draw_screen()
+ self.stdscr.bkgd(' ', curses.color_pair(1))
+ self.recalc_input_lines()
+ if self.mode.has_input_prompt:
+ self.draw_input()
+ if self.mode.shows_info:
+ self.draw_info()
+ else:
+ self.draw_history()
+ self.draw_mode()
+ if not self.mode.is_intro:
+ self.draw_stats()
+ self.draw_map()
+ if self.show_help:
+ self.draw_help()
+ if self.mode.name in {'chat', 'play'}:
+ self.draw_names()
+ if self.draw_face:
+ self.draw_face_popup()
+
+ def handle_server_message(self, msg):
+ command, args = self.parser.parse(msg)
+ command(*args)
+
+ def on_each_loop_start(self):
+ prev_disconnected = self.socket.disconnected
+ self.socket.keep_connection_alive()
+ if prev_disconnected and not self.socket.disconnected:
+ self.update_on_connect()
+ if self.flash:
+ curses.flash()
+ self.flash = False
- def handle_input(msg):
- command, args = self.parser.parse(msg)
- command(*args)
+ def on_key(self, key, keycode):
def task_action_on(action):
return self.action_tasks[action] in self.game.tasks
- def recalc_input_lines():
- 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 move_explorer(direction):
target = self.game.map_geometry.move_yx(self.explorer, direction)
if target:
self.send_tile_control_command()
else:
self.flash = True
-
- def draw_history():
- 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():
- 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():
- 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():
- stats = 'ENERGY: %s BLADDER: %s' % (self.game.energy,
- self.game.bladder_pressure)
- self.addstr(0, self.left_window_width, stats)
-
- def draw_mode():
- 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():
- 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():
- 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
-
- def draw_face_popup():
- t = self.game.get_thing(self.draw_face)
- if not t or not hasattr(t, 'face'):
- self.draw_face = False
- return
-
- start_x = self.left_window_width - 10
- def draw_body_part(body_part, end_y):
- self.addstr(end_y - 3, start_x, '----------')
- self.addstr(end_y - 2, start_x, '| ' + body_part[0:6] + ' |')
- self.addstr(end_y - 1, start_x, '| ' + body_part[6:12] + ' |')
- self.addstr(end_y, start_x, '| ' + body_part[12:18] + ' |')
-
- if hasattr(t, 'face'):
- draw_body_part(t.face, self.size.y - 3)
- if hasattr(t, 'hat'):
- draw_body_part(t.hat, self.size.y - 6)
- self.addstr(self.size.y - 2, start_x, '----------')
- name = t.name[:]
- if len(name) > 7:
- name = name[:6 - 1] + '…'
- self.addstr(self.size.y - 1, start_x, '@%s:%s' % (t.thing_char, name))
-
- def draw_help():
- content = "%s help\n\n%s\n\n" % (self.mode.short_desc,
- self.mode.help_intro)
- if len(self.mode.available_actions) > 0:
- content += "Available actions:\n"
- for action in self.mode.available_actions:
- if action in self.action_tasks:
- if self.action_tasks[action] not in self.game.tasks:
- continue
- if action == 'move_explorer':
- action = 'move'
- if action == 'move':
- key = ','.join(self.movement_keys)
- else:
- key = self.keys[action]
- content += '[%s] – %s\n' % (key, self.action_descriptions[action])
- content += '\n'
- content += self.mode.list_available_modes(self)
- for i in range(self.size.y):
- self.addstr(i,
- self.left_window_width * (not self.mode.has_input_prompt),
- ' ' * self.left_window_width)
- lines = []
- for line in content.split('\n'):
- lines += msg_into_lines_of_width(line, self.right_window_width)
- for i in range(len(lines)):
- if i >= self.size.y:
- break
- self.addstr(i,
- self.left_window_width * (not self.mode.has_input_prompt),
- lines[i])
-
- def draw_screen():
- self.stdscr.clear()
- self.stdscr.bkgd(' ', curses.color_pair(1))
- recalc_input_lines()
- if self.mode.has_input_prompt:
- draw_input()
- if self.mode.shows_info:
- draw_info()
- else:
- draw_history()
- draw_mode()
- if not self.mode.is_intro:
- draw_stats()
- draw_map()
- if self.show_help:
- draw_help()
- if self.mode.name in {'chat', 'play'}:
- draw_names()
- if self.draw_face:
- draw_face_popup()
-
def pick_selectable(task_name):
try:
i = int(self.input_)
self.input_ = ""
self.switch_mode('edit')
- prev_disconnected = self.socket.disconnected
- self.socket.keep_connection_alive()
- if prev_disconnected and not self.socket.disconnected:
- self.update_on_connect()
- if self.flash:
- curses.flash()
- self.flash = False
- if self.do_refresh:
- draw_screen()
- self.do_refresh = False
- for msg in self.socket.get_message():
- handle_input(msg)
- key, keycode = self.get_key_and_keycode()
self.show_help = False
self.draw_face = False
if key == 'KEY_RESIZE':