home · contact · privacy
Fix delay flickering in web client.
[plomrogue2] / rogue_chat_curses.py
index eb708a249a3ddc6c4392e2349fa81d0587de7d43..2783e24087afdc38666504daa59124f0d74c682d 100755 (executable)
@@ -179,7 +179,7 @@ cmd_THING_NAME.argtypes = 'int:nonneg string'
 def cmd_THING_CHAR(game, thing_id, c):
     t = game.get_thing(thing_id)
     if t:
-        t.player_char = c
+        t.thing_char = c
 cmd_THING_CHAR.argtypes = 'int:nonneg char'
 
 def cmd_MAP(game, geometry, size, content):
@@ -268,6 +268,14 @@ def cmd_PONG(game):
     pass
 cmd_PONG.argtypes = ''
 
+def cmd_DEFAULT_COLORS(game):
+    game.tui.set_default_colors()
+cmd_DEFAULT_COLORS.argtypes = ''
+
+def cmd_RANDOM_COLORS(game):
+    game.tui.set_random_colors()
+cmd_RANDOM_COLORS.argtypes = ''
+
 class Game(GameBase):
     turn_complete = False
     tasks = {}
@@ -297,6 +305,8 @@ class Game(GameBase):
         self.register_command(cmd_PLAY_ERROR)
         self.register_command(cmd_TASKS)
         self.register_command(cmd_FOV)
+        self.register_command(cmd_DEFAULT_COLORS)
+        self.register_command(cmd_RANDOM_COLORS)
         self.map_content = ''
         self.player_id = -1
         self.info_db = {}
@@ -383,7 +393,7 @@ class TUI:
         import json
         self.mode_play.available_modes = ["chat", "study", "edit", "admin_enter"]
         self.mode_play.available_actions = ["move", "take_thing", "drop_thing",
-                                            "teleport", "door"]
+                                            "teleport", "door", "consume"]
         self.mode_study.available_modes = ["chat", "play", "admin_enter", "edit"]
         self.mode_study.available_actions = ["toggle_map_mode", "move_explorer"]
         self.mode_admin.available_modes = ["admin_thing_protect", "control_pw_type",
@@ -427,6 +437,7 @@ class TUI:
             'take_thing': 'z',
             'drop_thing': 'u',
             'teleport': 'p',
+            'consume': 'C',
             'door': 'D',
             'help': 'h',
             'toggle_map_mode': 'L',
@@ -453,6 +464,8 @@ class TUI:
         self.input_lines = []
         self.fov = ''
         self.flash = False
+        self.map_lines = []
+        self.offset = YX(0,0)
         curses.wrapper(self.loop)
 
     def connect(self):
@@ -596,19 +609,34 @@ class TUI:
         self.input_ = ""
         self.restore_input_values()
 
+    def set_default_colors(self):
+        curses.init_color(1, 1000, 1000, 1000)
+        curses.init_color(2, 0, 0, 0)
+        self.do_refresh = True
+
+    def set_random_colors(self):
+
+        def rand(offset):
+            import random
+            return int(offset + random.random()*375)
+
+        curses.init_color(1, rand(625), rand(625), rand(625))
+        curses.init_color(2, rand(0), rand(0), rand(0))
+        self.do_refresh = True
+
     def loop(self, stdscr):
         import datetime
 
         def safe_addstr(y, x, line):
             if y < self.size.y - 1 or x + len(line) < self.size.x:
-                stdscr.addstr(y, x, line)
+                stdscr.addstr(y, x, line, curses.color_pair(1))
             else:  # workaround to <https://stackoverflow.com/q/7063128>
                 cut_i = self.size.x - x - 1
                 cut = line[:cut_i]
                 last_char = line[cut_i]
-                stdscr.addstr(y, self.size.x - 2, last_char)
+                stdscr.addstr(y, self.size.x - 2, last_char, curses.color_pair(1))
                 stdscr.insstr(y, self.size.x - 2, ' ')
-                stdscr.addstr(y, x, cut)
+                stdscr.addstr(y, x, cut, curses.color_pair(1))
 
         def handle_input(msg):
             command, args = self.parser.parse(msg)
@@ -694,8 +722,8 @@ class TUI:
                             protection = 'none'
                         info += 'THING: %s / %s' % (t.type_,
                                                     self.game.thing_types[t.type_])
-                        if hasattr(t, 'player_char'):
-                            info += t.player_char
+                        if hasattr(t, 'thing_char'):
+                            info += t.thing_char
                         if hasattr(t, 'name'):
                             info += ' (%s)' % t.name
                         info += ' / protection: %s\n' % protection
@@ -734,64 +762,65 @@ class TUI:
                         'MODE: %s – %s' % (self.mode.short_desc, help))
 
         def draw_map():
-            if not self.game.turn_complete:
+            if not self.game.turn_complete and len(self.map_lines) == 0:
                 return
-            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]]]
+            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.info_hints:
+                        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 = []
+                    for t in self.game.things:
+                        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 = '+'
+                        map_lines_split[t.position.y][t.position.x] = symbol + meta_char
+                        used_positions += [t.position]
+                player = self.game.get_thing(self.game.player_id)
+                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[player.position.y][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:
-                    map_lines_split += [[c + ' ' for c
-                                         in self.game.map_content[start:end]]]
-            if self.map_mode == 'terrain + annotations':
-                for p in self.game.info_hints:
-                    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 = []
-                for t in self.game.things:
-                    symbol = self.game.thing_types[t.type_]
-                    meta_char = ' '
-                    if hasattr(t, 'player_char'):
-                        meta_char = t.player_char
-                    if t.position in used_positions:
-                        meta_char = '+'
-                    map_lines_split[t.position.y][t.position.x] = symbol + meta_char
-                    used_positions += [t.position]
-            player = self.game.get_thing(self.game.player_id)
-            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[player.position.y][player.position.x] = '??'
-            map_lines = []
-            if type(self.game.map_geometry) == MapGeometryHex:
-                indent = 0
-                for line in map_lines_split:
-                    map_lines += [indent * ' ' + ''.join(line)]
-                    indent = 0 if indent else 1
-            else:
-                for line in map_lines_split:
-                    map_lines += [''.join(line)]
-            window_center = YX(int(self.size.y / 2),
-                               int(self.window_width / 2))
-            center = player.position
-            if self.mode.shows_info or self.mode.name == 'control_tile_draw':
-                center = self.explorer
-            center = YX(center.y, center.x * 2)
-            offset = center - window_center
-            if type(self.game.map_geometry) == MapGeometryHex and offset.y % 2:
-                offset += YX(0, 1)
-            term_y = max(0, -offset.y)
-            term_x = max(0, -offset.x)
-            map_y = max(0, offset.y)
-            map_x = max(0, offset.x)
+                    for line in map_lines_split:
+                        self.map_lines += [''.join(line)]
+                window_center = YX(int(self.size.y / 2),
+                                   int(self.window_width / 2))
+                center = 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 < self.game.map_geometry.size.y):
-                to_draw = map_lines[map_y][map_x:self.window_width + offset.x]
+                to_draw = self.map_lines[map_y][map_x:self.window_width + self.offset.x]
                 safe_addstr(term_y, term_x, to_draw)
                 term_y += 1
                 map_y += 1
@@ -836,6 +865,7 @@ class TUI:
 
         def draw_screen():
             stdscr.clear()
+            stdscr.bkgd(' ', curses.color_pair(1))
             recalc_input_lines()
             if self.mode.has_input_prompt:
                 draw_input()
@@ -859,6 +889,7 @@ class TUI:
             'toggle_map_mode': 'toggle map view',
             'toggle_tile_draw': 'toggle protection character drawing',
             'door': 'open/close',
+            'consume': 'consume',
         }
 
         action_tasks = {
@@ -867,10 +898,13 @@ class TUI:
             'drop_thing': 'DROP',
             'door': 'DOOR',
             'move': 'MOVE',
+            'consume': 'INTOXICATE',
         }
 
         curses.curs_set(False)  # hide cursor
-        curses.use_default_colors()
+        curses.start_color()
+        self.set_default_colors()
+        curses.init_pair(1, 1, 2)
         stdscr.timeout(10)
         reset_screen_size()
         self.explorer = YX(0, 0)
@@ -1021,6 +1055,8 @@ class TUI:
                     self.send('TASK:DROP')
                 elif key == self.keys['door'] and task_action_on('door'):
                     self.send('TASK:DOOR')
+                elif key == self.keys['consume'] and task_action_on('consume'):
+                    self.send('TASK:INTOXICATE')
                 elif key == self.keys['teleport']:
                     player = self.game.get_thing(self.game.player_id)
                     if player.position in self.game.portals: