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 show_msg(screen: curses.window, screen_height: int, screen_width: int, message: str): """Generic routine to generate an error message""" screen.addstr(screen_height // 2, screen_width // 2 - len(message) // 2, message) screen.nodelay(0) screen.getch() sys.exit(0)
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 read_controls(canvas: curses.window) -> typing.Tuple[int, int, bool]: """Read keys pressed and returns tuple witl controls state.""" rows_direction = columns_direction = 0 space_pressed = False while True: pressed_key_code = canvas.getch() if pressed_key_code == -1: # https://docs.python.org/3/library/curses.html#curses.window.getch break if pressed_key_code == UP_KEY_CODE: rows_direction = -1 if pressed_key_code == DOWN_KEY_CODE: rows_direction = 1 if pressed_key_code == RIGHT_KEY_CODE: columns_direction = 1 if pressed_key_code == LEFT_KEY_CODE: columns_direction = -1 if pressed_key_code == SPACE_KEY_CODE: space_pressed = True return rows_direction, columns_direction, space_pressed
def process_human_move(screen: curses.window, cur_player: Player, game: Game): """ function for listening to player's input and taking appropriate actions """ buttons_move_cursor = [ curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT, ord('w'), ord('s'), ord('a'), ord('d') ] buttons_shoot = [curses.KEY_ENTER, 10, 12, 13, 14] while True: # get fields my_field = cur_player.my_field enemy_field = cur_player.enemy_field display_game(screen, cur_player, game) # listen to the input key = screen.getch() # move corresponding cursors if key in buttons_move_cursor: move_cursor(key, my_field=my_field, enemy_field=enemy_field, game=game) # shoot at the current location of the cursor elif key in buttons_shoot: process_shooting(screen, cur_player, game, is_human=True) break # save the game elif key == ord('o'): screen.clear() save_game(game) print_to_center(screen, ['The game was saved']) screen.getch() game.turn -= 1 break
def main(screen: curses.window, height, width): game: Optional[Game] = None curses.curs_set(0) while True: display_string_builder: list[str, ...] = list() display_string_builder.append('###########################') display_string_builder.append('# WELCOME TO BATTLESHIP #') display_string_builder.append('###########################') display_string_builder.append('') if game and game.winner: display_string_builder.append( f'The winner of the last game is {game.winner}!') display_string_builder.append('') display_string_builder.append('Press n to start new game.') display_string_builder.append('Press l to load the game (if exists).') display_string_builder.append('Press q to quit the game.') screen.clear() check_text_size(display_string_builder, *screen.getmaxyx()) display_string = '\n'.join(display_string_builder) screen.addstr(0, 0, display_string) input_character = screen.getch() if input_character == ord('q'): return if input_character in (ord('n'), ord('l')): if input_character == ord('l'): try: with open(SAVE_FILE_NAME, 'rb') as file: game = pickle.load(file) except OSError: continue else: first_player = HumanPlayer('You') second_player = RandomPlayer('Robot') game = Game(first_player=first_player, second_player=second_player, board_size=(height, width)) try: game.play(screen) except QuitSignal as qs: if qs.signal_type == QuitSignal.BACK_TO_MAIN_MENU: continue if qs.signal_type == QuitSignal.QUIT: return if qs.signal_type == QuitSignal.QUIT_AND_SAVE: with open(SAVE_FILE_NAME, 'wb') as file: pickle.dump(game, file, pickle.HIGHEST_PROTOCOL) return
def main(screen: curses.window, mheight: int, mwidth: int): # removing cursor curses.curs_set(0) # setting color for menu curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE) # things to be printed prev_game = load_game() str_start_game = "Start New Game" str_load_game = "Load Game" str_exit = "Exit" menu_items = [str_load_game, str_start_game, str_exit ] if prev_game else [str_start_game, str_exit] cur_index = 0 # selected menu item display_menu(screen, menu_items, cur_index) while True: # listen to input key = screen.getch() # handling navigation if key == curses.KEY_UP and cur_index > 0: cur_index -= 1 elif key == curses.KEY_DOWN and cur_index < len(menu_items) - 1: cur_index += 1 # handling Enter button elif key == curses.KEY_ENTER or key in [10, 13]: cur_item = menu_items[cur_index] if cur_item == str_start_game: # adjust length of the symbols Field.recal_sybms(len(str(mwidth))) # start new game start_game(screen, mheight, mwidth) elif cur_item == str_load_game: # adjust length of the symbols Field.recal_sybms(len(str(prev_game.map_width))) # continue last saved game play_game(screen, game=prev_game) elif cur_item == str_exit: return screen.clear() display_menu(screen, menu_items, cur_index)
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_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_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 main(scr: curses.window): mode = "movement" for n, pair in enumerate(colors): curses.init_pair(n + 1, *pair) y, x = 0, 0 while True: # maxy/x maxy, maxx = [n - 1 for n in scr.getmaxyx()] maxy -= 1 # output mode scr.move(maxy + 1, 1) scr.clrtobot() scr.addstr(maxy + 1, 1, mode) # move cursor to proper position scr.move(y, x) # get user input key = scr.getch() # try: y, x, scr, mode = modes[mode](key, mode, y, x, maxy, maxx, scr)
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 get_action(screen: curses.window, arena: Arena, player: Player, keys: dict, is_AI: bool, game_status: dict) -> str or None: """Get player's action. The purpuse of this function is to be a wrapper, for convenience if one day another kind of control is to be implemented Parameters ---------- screen : curses.window arena : Arena player : Player keys : dict dictionary containing all the configured key to play the game is_AI : bool if True, the AI will control the character (if an AI is available) game_status : dict dictionary containing players y position and ball position & velocity. Useful to create an AI, for exemple. Returns ------- action : str string containing what the player wants to do action : None if no action (or invalid action) is taken """ if is_AI and AI_AVAILABLE: return AI(screen, arena, player, keys, is_AI, game_status) else: key = screen.getch() if key in keys['up_key']: return 'up' elif key in keys['down_key']: return 'down' elif key in keys['quit_key']: return 'quit' return None
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()