def main(stdscr: curses.window): curses.echo() curses.nocbreak() width = config['size']['width'] ol = config['size']['output_lines'] il = config['size']['input_lines'] real_id = str(get_real_id(room_id)) output_win = curses.newwin(ol, width, 1, 1) output_win.scrollok(True) input_win = curses.newwin(il, width, ol + 3, 1) rectangle(stdscr, 0, 0, ol + 1, width + 1) rectangle(stdscr, ol + 2, 0, ol + 2 + il + 1, width + 1) if width > 'Message'.__len__(): stdscr.addstr(ol + 1, 1, 'Message') if width > 'Press Enter'.__len__(): stdscr.addstr(ol + 2 + il + 1, 1, 'Press Enter') stdscr.refresh() output_win.refresh() input_win.refresh() t = Thread(None, input_thread, args=(input_win, real_id)) t.setDaemon(True) t.start() asyncio.run( start('wss://broadcastlv.chat.bilibili.com:2245/sub', real_id, output_win)) t.join()
def process_shooting(screen: curses.window, cur_player: Player, game: Game, is_human: bool): """ function for processing current player's shot """ # shoot succ, hit = game.player_shoot() # if player chose an inappropriate cell, do nothing if not succ: game.turn -= 1 else: screen.clear() message = "You missed" if is_human else "AI missed" if hit: message = "You hit enemy ship" if is_human else "AI hit enemy ship" game.check_victory() game.turn -= 1 # printing the result of the shot to the screen if is_human: print_to_center(screen, [message]) else: y_shot = cur_player.enemy_field.y_cur x_shot = cur_player.enemy_field.x_cur print_to_center(screen, [f"AI has shot to {y_shot} {x_shot}", message]) screen.refresh() screen.getch() screen.refresh()
def display_field(screen: curses.window, coords, player: Player, my: bool, game: Game) -> None: """ function for printing fields on the console """ # obtaining field field = player.my_field if my else player.enemy_field # obtaining sliding window borders start_left = field.border_left start_top = field.border_top iter_row = start_top iter_col = start_left for y, x, symb in coords: # replacing current active element with the cursor if iter_row == field.y_cur and iter_col == field.x_cur: screen.addstr(y, x, Field.CURSOR) else: screen.addstr(y, x, symb) # printing numbers on the top of the sliding window if iter_row == start_top: num_zeros = len(str(game.map_width)) - len(str(iter_col)) power_of_ten = 10**len(str(game.map_width)) screen.addstr( y - 1, x, "0" * num_zeros + str(iter_col) + " " if iter_col < power_of_ten else str(iter_col) + ' ') # printing numbers on the left of the sliding window if iter_col == start_left: screen.addstr(y, x - len(str(iter_row)), str(iter_row)) iter_col += 1 if iter_col == start_left + Field.WINDOW_WIDTH: iter_col = start_left iter_row += 1 screen.refresh()
def input_str(y, x, scr: c.window, max_len=0, prompt=''): res = '' len_count = 0 if prompt: scr.addstr(y, x, prompt) if max_len > 0: scr.addstr(y + int(bool(prompt)), x, '_' * max_len) while True: char = scr.get_wch() if char == '\n': break elif char in ('\b', '\x7f'): if len_count > 0: res = res[:-1] scr.addch(y + int(bool(prompt)), x + len_count - 1, '_') scr.refresh() len_count -= 1 elif len(char) == 1: res += char scr.addch(y + int(bool(prompt)), x + len_count, char) scr.refresh() len_count += 1 if 0 < max_len <= len_count: break return res
def display_menu(screen: curses.window, menu_items, cur_index: int): """ prints the menu to the console """ # obtaining size of the screen sheight, swidth = screen.getmaxyx() welcome = "Welcome to Battleships" screen.addstr(1, swidth // 2 - len(welcome) // 2, '#' * len(welcome)) screen.addstr(2, swidth // 2 - len(welcome) // 2, welcome) screen.addstr(3, swidth // 2 - len(welcome) // 2, '#' * len(welcome)) # printing the menu in center of the screen for index, item in enumerate(menu_items): x = swidth // 2 - len(item) // 2 y = sheight // 2 - len(menu_items) // 2 + index if index == cur_index: screen.attron(curses.color_pair(1)) screen.addstr(y, x, item) screen.attroff(curses.color_pair(1)) else: screen.addstr(y, x, item) screen.refresh()
def start_game(screen: curses.window, mheight: int, mwidth: int) -> None: """ function for starting a new game mheight: map height mwidth: map width """ # reading player's name screen.clear() print_to_center(screen, ['Enter your name: ']) screen.refresh() curses.curs_set(1) curses.echo() name = screen.getstr().decode("utf-8") curses.curs_set(0) curses.noecho() screen.clear() print_to_center(screen, ['Preparing the game...']) screen.refresh() # initializing a new game game = Game(mheight, mwidth) # making necessary preparations game.prepare_game(player_name=name) # playing the game play_game(screen=screen, game=game)
def draw(canvas: curses.window): canvas.border() canvas.nodelay(True) # https://docs.python.org/3/library/curses.html#curses.window.getmaxyx window_height, window_width = canvas.getmaxyx() # rows and columns greater by one then real window size max_y, max_x = window_height - 1, window_width - 1 curses.curs_set(False) # Reducing max dimensions by 2 allows to avoid "curses.error" stars_max_y = window_height - 2 stars_max_x = window_width - 2 coroutines = [ blink( canvas, random.randint(1, stars_max_y), # stars mustn't appear on border random.randint(0, stars_max_x), delay=random.randint(1, 20), ) for _ in range(random.randint(100, 200)) ] coroutines.append(animate_rocket_flight(canvas, max_y, max_x)) while coroutines: for coro in coroutines.copy(): try: coro.send(None) except StopIteration: coroutines.remove(coro) canvas.refresh() time.sleep(TIC_TIMEOUT)
def render_welcome_screen(window: curses.window) -> None: window.clear() window.addstr(0, 10, "jocus 0.0.1") window.addstr(1, 10, "collect coins and you win") window.addstr(3, 10, "press any key to start...") window.refresh()
def declare_winner(screen: curses.window, game: Game): """ function for printing the winner to the screen """ screen.clear() message = f'Congrats! Player {game.winner} has won!' print_to_center(screen, [message]) screen.refresh() screen.getch()
def sprite_init(scr: c.window, text: c.window, sprite: dict, erase=True): show_sprite(scr, sprite['image'], erase) for group in sprite['lines']: for i, line in enumerate(group): text.addstr(i, 0, line) text.getch() text.erase() scr.erase() scr.refresh()
def show_sprite(scr: c.window, sprite: list, erase=True): if erase: scr.erase() scr_y, scr_x = scr.getmaxyx() begin_y = scr_y // 2 - len(sprite) // 2 begin_x = scr_x // 2 - len(sprite[0]) // 2 for i, s in enumerate(sprite): scr.addstr(begin_y + i, begin_x, s) scr.refresh()
def curses_get_input(stdscr: curses.window, inputwin: curses.window, msgqueue: Queue, status): to_send = "" next_char_x = 2 next_char_y = 0 inputwin.addstr(0, 0, ">>") inputwin.refresh() while status.run: curr_in = inputwin.getkey() with open("keys.log", "a") as f: f.write(f"got {curr_in}") if curr_in == "\n": msgqueue.put(to_send) to_send = "" inputwin.erase() next_char_x = next_char_y = 0 inputwin.addstr(next_char_y, next_char_x, ">>") next_char_x += 2 elif curr_in == 'KEY_BACKSPACE' or curr_in == curses.KEY_BACKSPACE or curr_in == "^?" or curr_in == "\b" or curr_in == '\x7f': with open("clientdebug.log", "a") as f: f.write(f"got key {curr_in} went into backspace case\n") if next_char_x == 2 and next_char_y == 0: continue #nothing to delete if next_char_x == 0 and next_char_y > 0: # at the start of a new line next_char_y -= 1 next_char_x = INPUT_WIDTH - 1 elif (next_char_x > 0 and next_char_y > 0) or next_char_x > 2: next_char_x -= 1 inputwin.addstr(next_char_y, next_char_x, " ") inputwin.move(next_char_y, next_char_x) to_send = to_send[:-1] else: to_send += curr_in inputwin.addstr(next_char_y, next_char_x, curr_in) next_char_x += 1 if next_char_x == INPUT_WIDTH: next_char_x = 0 next_char_y += 1 inputwin.refresh()
def play_game(screen: curses.window, game: Game) -> None: """ function for simulating the game """ while not game.is_finished: # obtaining the current player cur_player = game.players[game.turn % 2] # if human if cur_player.is_human: process_human_move(screen, cur_player, game) screen.refresh() # if current player is AI else: process_ai_move(screen, cur_player, game) screen.refresh() game.turn += 1 declare_winner(screen, game)
def run_mainmenu(scr: curses.window): curses.curs_set(0) title: str = "Snake" menu_items: list = ["Start", "Exit"] game_state = "" cursor: int = 0 while True: scr.erase() scr.addstr(1, 1, title, curses.A_BOLD) scr.addstr(2, 1, '-'*(len(title)*2)) for i, item in enumerate(menu_items): if i == cursor: scr.addstr(3+i, 2, item, curses.A_REVERSE) else: scr.addstr(3+i, 2, item) # ++ Tick ++ key = scr.getch() cursor, game_state = process_key(key, cursor, menu_items) if game_state != "": return game_state, 0 # -- Tick -- scr.refresh()
def run_end(scr: curses.window, score: int): curses.curs_set(0) message: str = f"Game over! Score: {score}" menu_items: list = ["Play again", "Exit"] game_state = "" cursor: int = 0 while True: scr.erase() scr.addstr(1, 1, message, curses.A_BOLD) scr.addstr(2, 1, '-' * (len(message) + 5)) for i, item in enumerate(menu_items): if i == cursor: scr.addstr(3 + i, 2, item, curses.A_REVERSE) else: scr.addstr(3 + i, 2, item) # ++ Tick ++ key = scr.getch() cursor, game_state = process_key(key, cursor, menu_items) if game_state != "": return game_state, 0 # -- Tick -- scr.refresh()
def run_game(scr: curses.window): curses.curs_set(0) scr.nodelay(True) game_state = "" status_w: int = 25 maxy = scr.getmaxyx()[0] - 1 maxx = scr.getmaxyx()[1] midy = int(maxy / 2) midx = int(maxx / 2) snake: list = [] for i in range(SNAKE_LEN): snake.append((midy, status_w + midx + i)) direction = WEST apples: list = [] score = 0 while True: scr.erase() draw_statusbar(scr, (maxy - 1, maxx), status_w, score) draw_snek(scr, snake, direction) draw_apples(scr, apples) # ++ Tick ++ key = scr.getch() direction, game_state = process_key(key, direction) snake = move_snake(snake, direction) snake = portals(snake, direction, status_w + 2, (maxy - 1, maxx)) snake, apples, nscore = eat_apples(snake, apples) apples = create_apples(snake, apples, MAX_APPLES - len(apples), status_w, (maxy, maxx)) score += nscore if game_state != "": return game_state, 0 # -- Tick -- scr.refresh() if check_loss(snake): curses.napms(1000) return "end", score curses.napms(100)
def start(screen: curses.window): while 1: key = screen.getch() screen.erase() h_h, h_w = center(screen) head_text = "Potato Messenger" head = (h_h // 2, h_w - len(head_text) // 2, head_text) click_text = "Click Here To Continue or press Enter." button = (h_h, h_w - len(click_text) // 2, click_text) box1 = screen.subwin(3, len(button[2]) + 4, button[0] - 1, button[1] - 2) box1.box() screen.addstr(head[0], head[1], head[2]) screen.addstr(button[0], button[1], button[2]) if key == curses.KEY_ENTER or key in (10, 13): break if key == curses.KEY_MOUSE: _, mx, my, *_ = curses.getmouse() if button[1] <= mx <= button[1] + len( button[2]) and my == button[0]: break screen.refresh()
def _main(stdscr: curses.window): maxy, maxx = 0, 0 examples = [] count = 1 while 1: # Prompt maxy, maxx = stdscr.getmaxyx() stdscr.clear() stdscr.addstr( 0, 0, "Enter example: (hit Ctrl-G to execute, Ctrl-C to exit)", curses.A_BOLD) editwin = curses.newwin(5, maxx - 4, 2, 2) rectangle(stdscr, 1, 1, 1 + 5 + 1, maxx - 2) # Printing is part of the prompt cur = 8 def putstr(str, x=0, attr=0): nonlocal cur # This is how we handle going off the bottom of the scren lol if cur < maxy: stdscr.addstr(cur, x, str, attr) cur += (len(str.split("\n")) or 1) for ex, buff, vals, err in reversed(examples): putstr(f"Example {ex}:", attr=curses.A_BOLD) for l in buff.split("\n"): putstr(f" | {l}") putstr("") if err: err = str(err) err = err.split("\n") putstr(" Error:") for l in err: putstr(f" {l}", attr=curses.COLOR_YELLOW) elif vals: putstr(" Value:") for x, t in zip(range(1, 1 << 64), vals): putstr(f" {x:>3}) " + repr(t)) putstr("") stdscr.refresh() # Readf rom the user box = Textbox(editwin) try: box.edit() except KeyboardInterrupt: break buff = box.gather().strip() if not buff: continue vals, err = handle(buff, count) examples.append((count, buff, vals, err)) count += 1 stdscr.refresh()
def main(scr: curses.window): # Remove blinking cursor curses.curs_set(0) # Get screen's height and width & check if the screen is big enough sh, sw = scr.getmaxyx() if sh < SCR_H + 2 or sw < SCR_W + 2: show_msg(scr, sh, sw, MSG_SCR_SMALL) # Get args mode, ip, port, plname = get_args(scr, sh, sw) # Start socket for host/join mode skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM) skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) if mode == 'host': try: skt.bind((ip, port)) skt.listen(1) except: show_msg(scr, sh, sw, MSG_CANT_HOST) else: try: skt.connect((ip, port)) except: show_msg(scr, sh, sw, MSG_CANT_JOIN) # Setup keys up_key = set((curses.KEY_UP, ord('k'), ord('K'), ord('w'), ord('W'))) down_key = set((curses.KEY_DOWN, ord('j'), ord('J'), ord('s'), ord('S'))) quit_key = set((ord('q'), ord('Q'))) keys = {'up_key': up_key, 'down_key': down_key, 'quit_key': quit_key} # Activate nodelay (so getch won't interrupt the execution) scr.nodelay(1) scr.timeout(33) # Create arena arena = Arena(0, 1, SCR_W, SCR_H) # Create players player1 = Player('left', arena) player2 = Player('right', arena) # Create the ball ball = Ball(arena.bound_x // 2, arena.bound_y // 2, choice((-1, 1)), choice((-1, 0, 1))) # Connection accepted accepted = False # Waiting connection message scr.addstr(sh // 2, sw // 2 - len(MSG_WAITING) // 2, MSG_WAITING) scr.refresh() scr.addstr(sh // 2, 0, " " * sw) # Draw the arena arena.draw(scr) # Game loop while True: # Start networking if mode == 'host': if not accepted: # Accept client try: clskt, claddr = skt.accept() except: sys.exit() # Write host name on the screen and send it scr.addstr(0, 0, plname) clskt.send(plname.encode().ljust(16)) # Receive client name and add to screen try: clname = clskt.recv(16).strip().decode()[:16] except: show_msg(scr, 0, SCR_W, MSG_DISCONN) scr.addstr(0, SCR_W + 1 - len(clname), clname) # Mark client as accpeted accepted = True else: if not accepted: # Receive host name and add to screen try: scr.addstr(0, 0, skt.recv(16).strip().decode()[:16]) except: show_msg(scr, 0, SCR_W, MSG_DISCONN) # Write client name on the screen and send it scr.addstr(0, SCR_W + 1 - len(plname), plname) skt.send(plname.encode().ljust(16)) accepted = True # Draw the game score scr.addstr(0, SCR_W // 2 - 6, str(player1.score)) scr.addstr(0, SCR_W // 2 + 6, str(player2.score)) # Draw players player1.draw(scr, arena) player2.draw(scr, arena) # Draw ball (host) and check goals if mode == 'host': ball.move(player1, player2, arena) ball.draw(scr) # Get button press, perform action and send over the network if mode == 'host': action = get_action(scr, arena, player1, keys, plname == 'AI', { 'p1': player1.y, 'p2': player2.y, 'ball': ball.upload() }) if action == 'up' and player1.y > arena.y + 3: player1.move('up') elif action == 'down' and player1.y < arena.bound_y - 3: player1.move('down') elif action == 'quit': clskt.close() sys.exit(0) else: action = None # Send ball and host's action try: clskt.send(pickle.dumps((str(action), ball.upload()))) player2_action = clskt.recv(16).strip().decode() if player2_action == 'up' and player2.y > arena.y + 3: player2.move('up') elif player2_action == 'down' and player2.y < arena.bound_y - 3: player2.move('down') except: show_msg(scr, 0, SCR_W, MSG_DISCONN) else: action = get_action(scr, arena, player2, keys, plname == 'AI', { 'p1': player1.y, 'p2': player2.y, 'ball': ball.upload() }) if action == 'up' and player2.y > arena.y + 3: player2.move('up') elif action == 'down' and player2.y < arena.bound_y - 3: player2.move('down') elif action == 'quit': skt.close() sys.exit(0) else: action = None # Send client's action, then get ball and host's position try: skt.send(str(action).encode().ljust(16)) player1_action, ball_info = pickle.loads( skt.recv(sys.getsizeof(('down', ball.upload())) * 3)) if player1_action == 'up' and player1.y > arena.y + 3: player1.move('up') elif player1_action == 'down' and player1.y < arena.bound_y - 3: player1.move('down') ball.download(ball_info) except: show_msg(scr, 0, SCR_W, MSG_DISCONN) # Draw ball (join) and check goals ball.move(player1, player2, arena) ball.draw(scr) scr.refresh()
def render_game_frame(window: curses.window, state: State) -> None: state.update(window) state.render(window) window.refresh()
def wprint(w: curses.window, msg: str): w.addstr(msg + '\n') w.refresh()
def chat_page(screen: curses.window): global running user_typing = False read_str = "" rendered_display_chats = 0 display_chats: List[str] = [] while running: key = screen.getch() if key == curses.KEY_MOUSE: _, mx, my, *_ = curses.getmouse() if my == center(screen)[0] * 2 - 2: user_typing = True else: user_typing = False elif key == 27 or key == curses.KEY_BREAK: running = False screen.erase() start_index = -1 end_index = -(center(screen)[0] * 2 - 3) - 1 box2 = screen.subwin(3, center(screen)[1] * 2, center(screen)[0] * 2 - 3, 0) box2.box() start_render_from = rendered_display_chats rendered_display_chats = len(chats) width_limit = center(screen)[1] * 2 - 2 for chat in chats[start_render_from:]: parts = textwrap.fill(chat, width_limit).split("\n") display_chats.extend(parts) for index, msg in enumerate(display_chats[start_index:end_index:-1]): y = center(screen)[0] * 2 - 4 - index x = 0 screen.addstr(y, x, msg) if user_typing: curses.curs_set(1) screen.move( center(screen)[0] * 2 - 2, len(read_str[-(center(screen)[1] - 2) * 2:])) if key: if key == curses.KEY_ENTER or key in (10, 13): if read_str: send_this.append(read_str) read_str = "" elif key == curses.KEY_BACKSPACE or key == 8: if read_str: read_str = read_str[:-1] else: if curses.ascii.isascii(key): letter = chr(key) read_str += letter screen.move( center(screen)[0] * 2 - 2, len(read_str[-(center(screen)[1] - 2) * 2:])) else: screen.move(0, center(screen)[1] * 2 - 1) if key == ord("q"): running = False elif key == ord("w") or key == curses.KEY_ENTER or key in (10, 18): user_typing = True screen.addstr( center(screen)[0] * 2 - 2, 1, read_str[-(center(screen)[1] - 2) * 2 - 1:]) screen.refresh()
def main(s: curses.window, a: list[str], c: int, o: list[bool]): """Lists system specs""" s.clear() s.refresh() io.printw("System Specs:\n " + platform.uname().system + ", {}, {}, {}".format(platform.uname().processor, platform.uname().machine, platform.uname().version) )