X-Git-Url: https://plomlompom.com/repos/?a=blobdiff_plain;f=client_prototype.py;h=582df073688bd4a9a7f43314a30ae820cc51768a;hb=177f9281c875a37b62793771e5b38564faac0e89;hp=9a67b98d0e0ac54d72de916b5aa0ec6ef21d2dfe;hpb=e64fbb87ec0b4d36f2d47d0b0bcbcd3f5f7d2918;p=plomrogue diff --git a/client_prototype.py b/client_prototype.py index 9a67b98..582df07 100644 --- a/client_prototype.py +++ b/client_prototype.py @@ -1,4 +1,5 @@ import curses +import math import os import signal import time @@ -84,6 +85,16 @@ def set_window_geometries(): def draw_screen(): + def healthy_addch(y, x, char, attr=0): + """Bizarre workaround for .""" + if y == screen_size[0] - 1 and x == screen_size[1] - 1: + char_before = stdscr.inch(y, x - 1) + stdscr.addch(y, x - 1, char, attr) + stdscr.insstr(y, x - 1, " ") + stdscr.addch(y, x - 1, char_before) + else: + stdscr.addch(y, x, char, attr) + def draw_window_border_lines(): for win in windows: for k in range(2): @@ -94,9 +105,9 @@ def draw_screen(): end = win["start"][k] + win["size"][k] end = end if end < screen_size[k] else screen_size[k] if k: - [stdscr.addch(j, i, '-') for i in range(start, end)] + [healthy_addch(j, i, '-') for i in range(start, end)] else: - [stdscr.addch(i, j, '|') for i in range(start, end)] + [healthy_addch(i, j, '|') for i in range(start, end)] def draw_window_border_corners(): for win in windows: @@ -106,29 +117,34 @@ def draw_screen(): right = win["start"][1] + win["size"][1] if (up >= 0 and up < screen_size[0]): if (left >= 0 and left < screen_size[1]): - stdscr.addch(up, left, '+') + healthy_addch(up, left, '+') if (right >= 0 and right < screen_size[1]): - stdscr.addch(up, right, '+') + healthy_addch(up, right, '+') if (down >= 0 and down < screen_size[0]): if (left >= 0 and left < screen_size[1]): - stdscr.addch(down, left, '+') + healthy_addch(down, left, '+') if (right >= 0 and right < screen_size[1]): - stdscr.addch(down, right, '+') + healthy_addch(down, right, '+') def draw_window_contents(): def draw_winmap(): stop = [0, 0] for i in range(2): stop[i] = win["size"][i] + offset[i] - stop[i] = stop[i] if stop[i] < size[i] else size[i] + if stop[i] >= winmap_size[i]: + stop[i] = winmap_size[i] for y in range(offset[0], stop[0]): for x in range(offset[1], stop[1]): - cell = winmap[y * size[1] + x] + cell = winmap[y * winmap_size[1] + x] + attr = 0 + if len(cell) > 1: + attr = cell[1] + cell = cell[0] y_in_screen = win["start"][0] + (y - offset[0]) x_in_screen = win["start"][1] + (x - offset[1]) if (y_in_screen < screen_size[0] and x_in_screen < screen_size[1]): - stdscr.addch(y_in_screen, x_in_screen, cell) + healthy_addch(y_in_screen, x_in_screen, cell, attr) def draw_scroll_hints(): def draw_scroll_string(n_lines_outside): hint = ' ' + str(n_lines_outside + 1) + ' more ' + unit + ' ' @@ -138,12 +154,12 @@ def draw_screen(): for j in range(win["size"][ni] - non_hint_space): pos_2 = win["start"][ni] + hint_offset + j x, y = (pos_2, pos_1) if ni else (pos_1, pos_2) - stdscr.addch(y, x, hint[j], curses.A_REVERSE) + healthy_addch(y, x, hint[j], curses.A_REVERSE) def draw_scroll_arrows(ar1, ar2): for j in range(win["size"][ni]): pos_2 = win["start"][ni] + j x, y = (pos_2, pos_1) if ni else (pos_1, pos_2) - stdscr.addch(y, x, ar1 if ni else ar2, curses.A_REVERSE) + healthy_addch(y, x, ar1 if ni else ar2, curses.A_REVERSE) for i in range(2): ni = int(i == 0) unit = 'rows' if ni else 'columns' @@ -151,12 +167,13 @@ def draw_screen(): pos_1 = win["start"][i] draw_scroll_arrows('^', '<') draw_scroll_string(offset[i]) - if (size[i] > offset[i] + win["size"][i]): + if (winmap_size[i] > offset[i] + win["size"][i]): pos_1 = win["start"][i] + win["size"][i] - 1 draw_scroll_arrows('v', '>') - draw_scroll_string(size[i] - offset[i] - win["size"][i]) + draw_scroll_string(winmap_size[i] - offset[i] + - win["size"][i]) for win in windows: - offset, size, winmap = win["func"]() + offset, winmap_size, winmap = win["func"]() draw_winmap() draw_scroll_hints() @@ -167,25 +184,86 @@ def draw_screen(): stdscr.refresh() -def test_and_poll_server(): - half_wait_time = 5 - new_file_content = io["file_in"].read() - # TODO: do something useful with new_file_content - server_answered = len(new_file_content) > 0 - if server_answered: - test_and_poll_server.ping_sent = False - elif test_and_poll_server.wait_start + half_wait_time < time.time(): - if not test_and_poll_server.ping_sent: - io["file_out"].write("PING\n") - io["file_out"].flush() - test_and_poll_server.ping_sent = True - test_and_poll_server.wait_start = time.time() - elif test_and_poll_server.ping_sent: - raise SystemExit("Server not answering anymore.") -test_and_poll_server.wait_start = 0 +def read_worldstate(): + if not os.access(io["path_worldstate"], os.F_OK): + msg = "No world state file found at " + io["path_worldstate"] + "." + raise SystemExit(msg) + read_anew = False + worldstate_file = open(io["path_worldstate"], "r") + turn_string = worldstate_file.readline() + if int(turn_string) != world_data["turn"]: + read_anew = True + if not read_anew: # In rare cases, world may change, but not turn number. + mtime = os.stat(io["path_worldstate"]) + if mtime != read_worldstate.last_checked_mtime: + read_worldstate.last_checked_mtime = mtime + read_anew = True + if read_anew: + cursed_main.redraw = True + world_data["turn"] = int(turn_string) + world_data["lifepoints"] = int(worldstate_file.readline()) + world_data["satiation"] = int(worldstate_file.readline()) + world_data["inventory"] = [] + while True: + line = worldstate_file.readline().replace("\n", "") + if line == '%': + break + world_data["inventory"] += [line] + world_data["position"][0] = int(worldstate_file.readline()) + world_data["position"][1] = int(worldstate_file.readline()) + world_data["map_size"] = int(worldstate_file.readline()) + world_data["fov_map"] = "" + for i in range(world_data["map_size"]): + line = worldstate_file.readline().replace("\n", "") + world_data["fov_map"] += line + world_data["mem_map"] = "" + for i in range(world_data["map_size"]): + line = worldstate_file.readline().replace("\n", "") + world_data["mem_map"] += line + worldstate_file.close() +read_worldstate.last_checked_mtime = -1 + + +def read_message_queue(): + while (len(message_queue["messages"]) > 1 + or (len(message_queue["messages"]) == 0 + and not message_queue["open_end"])): + message = message_queue["messages"].pop(0) + if message[0:4] == "LOG ": + world_data["log"] += [message[4:]] + cursed_main.redraw = True def cursed_main(stdscr): + + def ping_test(): + half_wait_time = 5 + if len(new_data_from_server) > 0: + ping_test.sent = False + elif ping_test.wait_start + half_wait_time < time.time(): + if not ping_test.sent: + io["file_out"].write("PING\n") + io["file_out"].flush() + ping_test.sent = True + ping_test.wait_start = time.time() + elif ping_test.sent: + raise SystemExit("Server not answering anymore.") + ping_test.wait_start = 0 + + def read_into_message_queue(): + if new_data_from_server == "": + return + new_open_end = False + if new_data_from_server[-1] is not "\n": + new_open_end = True + new_messages = new_data_from_server.splitlines() + if message_queue["open_end"]: + message_queue["messages"][-1] += new_messages[0] + del new_messages[0] + message_queue["messages"] += new_messages + if new_open_end: + message_queue["open_end"] = True + curses.noecho() curses.curs_set(False) # stdscr.keypad(True) @@ -197,21 +275,85 @@ def cursed_main(stdscr): stdscr.timeout(delay) delay = delay * 2 if delay < 1000 else delay if cursed_main.redraw: + delay = 1 draw_screen() cursed_main.redraw = False char = stdscr.getch() - if (char >= 0): - if chr(char) in commands: - commands[chr(char)]() - cursed_main.redraw = True - test_and_poll_server() + if char >= 0 and chr(char) in commands: + commands[chr(char)]() + cursed_main.redraw = True + new_data_from_server = io["file_in"].read() + ping_test() + read_into_message_queue() + read_worldstate() + read_message_queue() + + +def win_foo(): + winmap = [('.', 0), ('o', 0), ('.', 0), ('o', 0), ('O', 0), ('o', 0), + ('.', 0), ('o', 0), ('.', 0), ('x', 0), ('y', 0), ('x', 0)] + winmap_size = [4, 3] + offset = [0, 0] + return offset, winmap_size, winmap + + +def win_map(): + offset = [0, 0] + winmap_size = [world_data["map_size"], world_data["map_size"] * 2 + 1] + winmap = [] + for y in range(world_data["map_size"]): + for x in range(world_data["map_size"]): + char = world_data["fov_map"][y * world_data["map_size"] + x] + if char == " ": + char = world_data["mem_map"][y * world_data["map_size"] + x] + attribute = curses.A_REVERSE + winmap += [(char, attribute), (" ", attribute)] + else: + winmap += char + " " + if y % 2 == 0: + winmap += " " + return offset, winmap_size, winmap + + +def win_inventory(): + winmap = "" + winmap_size = [0, 0] + for line in world_data["inventory"]: + winmap_size[1] = winmap_size[1] if len(line) <= winmap_size[1] \ + else len(line) + for line in world_data["inventory"]: + padding_size = winmap_size[1] - len(line) + winmap += line + (" " * padding_size) + winmap_size[0] = winmap_size[0] + 1 + offset = [0, 0] + return offset, winmap_size, winmap -def foo(): - winmap = ['.', 'o', '.', 'o', 'O', 'o', '.', 'o', '.', 'x', 'y', 'x'] - size = [4, 3] +def win_info(): + winmap = "T: " + str(world_data["turn"]) \ + + " H: " + str(world_data["lifepoints"]) \ + + " S: " + str(world_data["satiation"]) + winmap_size = [1, len(winmap)] offset = [0, 0] - return offset, size, winmap + return offset, winmap_size, winmap + + +def win_log(): + win_size = next(win["size"] for win in windows if win["func"] == win_log) + offset = [0, 0] + winmap = "" + number_of_lines = 0 + for line in world_data["log"]: + number_of_lines += math.ceil(len(line) / win_size[1]) + padding_size = win_size[1] - (len(line) % win_size[1]) + winmap += line + (padding_size * " ") + if number_of_lines < win_size[0]: + winmap = (" " * win_size[1] * (win_size[0] - number_of_lines)) + winmap + number_of_lines = win_size[0] + elif number_of_lines > win_size[0]: + offset[0] = number_of_lines - win_size[0] + winmap_size = [number_of_lines, win_size[1]] + return offset, winmap_size, winmap def command_quit(): @@ -221,19 +363,35 @@ def command_quit(): windows = [ - {"config": [1, 33], "func": foo}, - {"config": [-7, 33], "func": foo}, - {"config": [4, 16], "func": foo}, - {"config": [4, 16], "func": foo}, - {"config": [0, -34], "func": foo} + {"config": [1, 33], "func": win_info}, + {"config": [-7, 33], "func": win_log}, + {"config": [4, 16], "func": win_inventory}, + {"config": [4, 16], "func": win_foo}, + {"config": [0, -34], "func": win_map} ] io = { "path_out": "server/in", - "path_in": "server/out" + "path_in": "server/out", + "path_worldstate": "server/worldstate" } commands = { "Q": command_quit } +message_queue = { + "open_end": False, + "messages": [] +} +world_data = { + "fov_map": "", + "inventory": [], + "lifepoints": -1, + "log": [], + "map_size": 0, + "mem_map": "", + "position": [-1, -1], + "satiation": -1, + "turn": -1 +} sep_size = 1 # Width of inter-window borders and title bars. stdscr = None screen_size = [0,0]