Esempio n. 1
0
 async def manage(self):
     await super().manage()
     address = self.server_address
     print_header(f"Joining game @ {address.host}:{address.port}")
     await self._connect_to_server()
     game = await self._wait_for_game()
     await self.play_game(game)
Esempio n. 2
0
        async def handle(e: rnd.RoundEnd) -> None:
            get_username = lambda p: game.get_player(p).username  # noqa

            await pause()
            print_header("Round end", filler="—")
            draw_game(game, reveal=True)

            print(">>>>> The round has ended! <<<<<")
            if e.reason == rnd.RoundEnd.Reason.EMPTY_DECK:
                print("There are no cards remaining in the deck.")
                if len(e.tie_contenders) == 1:
                    print(
                        f"{get_username(e.winner)} wins with a {e.winner.hand.card}, "
                        f"which is the highest card among those remaining.")
                else:
                    card = mitt.first(p.hand.card for p in e.tie_contenders)
                    contenders = list(map(get_username, e.tie_contenders))
                    contenders_str = (
                        f"Both {contenders[0]} and {contenders[1]}"
                        if len(contenders) == 2 else
                        f"Each of {', '.join(contenders[:-1])} and {contenders[-1]}"
                    )
                    print(f"{contenders_str} have the highest card: a {card}.")
                    print(
                        f"But {get_username(e.winner)} has a higher sum of discarded"
                        f" values, so they win." if len(e.winners) == 1 else
                        f"And they each have the same sum of discarded values,"
                        f" so they {'both' if len(contenders) == 2 else 'all'} win"
                        f" in a tie.")
            elif e.reason == rnd.RoundEnd.Reason.ONE_PLAYER_STANDING:
                print(
                    f"{get_username(e.winner)} is the only player still alive, "
                    f"so they win the round.")
Esempio n. 3
0
    async def manage(self):
        import loveletter_cli.server_script

        await super().manage()
        print_header(
            f"Hosting game on {', '.join(f'{h}:{p}' for h, p in self.server_addresses)}"
        )
        server_process = multiprocessing.Process(
            target=loveletter_cli.server_script.main,
            kwargs=dict(
                logging_level=LOGGER.getEffectiveLevel(),
                host=self.hosts,
                port=self.port,
                party_host_username=self.user.username,
            ),
        )
        LOGGER.debug(f"Starting server process: %s", server_process)
        server_process.start()
        try:
            self.client = HostClient(self.user.username)
            connection = await self._connect_localhost()
            game = await self._ready_to_play()
            await self.play_game(game)
            await self.client.send_shutdown()
            await connection
        finally:
            if (exc_info := sys.exc_info()) == (None, None, None):
                LOGGER.info("Waiting on server process to end")
            else:
Esempio n. 4
0
def main(logging_level: int = logging.INFO):
    setup_logging(logging_level)

    print_header("Welcome to Love Letter (CLI)!", filler="~")

    user = ask_user()
    print(f"Welcome, {user.username}!")

    mode = ask_play_mode()

    runners = {PlayMode.JOIN: join_game, PlayMode.HOST: host_game}
    while True:
        try:
            print()
            return runners[mode](user)
        except Exception as e:
            traceback.print_exc()
            time.sleep(0.2)
            print("Unhandled exception while running the session:")
            print_exception(e)
            time.sleep(0.2)
            choice = ask_valid_input(
                "What would you like to do?",
                choices=ErrorOptions,
                default=ErrorOptions.RETRY,
            )
            if choice == ErrorOptions.RETRY:
                continue
            elif choice == ErrorOptions.QUIT:
                return
            else:
                assert False, f"Unhandled error option: {choice}"
Esempio n. 5
0
        async def handle(e: rnd.Turn) -> None:
            if e.turn_no > 1:
                await pause()
            player = game.get_player(e.current_player)
            is_client = player is game.client_player

            possessive = "Your" if is_client else f"{player.username}'s"
            print_header(f"{possessive} turn", filler="—")
            draw_game(game)
            if is_client:
                print(">>>>> It's your turn! <<<<<\a")
            else:
                print(f"It's {player.username}'s turn.")
Esempio n. 6
0
 async def _show_game_end(game: RemoteGameShadowCopy):
     assert game.ended
     print_header("GAME OVER", filler="#")
     end: loveletter.game.GameEnd = game.state  # noqa
     try:
         winner = end.winner
     except ValueError:
         print("There were multiple winners!")
         print(
             f"{', '.join(p.username for p in end.winners)} all won in a tie."
         )
     else:
         if winner is game.client_player:
             print("You win!")
         else:
             print(f"{winner.username} wins!")
Esempio n. 7
0
        async def handle(e: loveletter.game.PlayingRound) -> None:
            if e.points_update:
                # print updates from last round
                print("Points gained:")
                for player, delta in (+e.points_update).items():
                    print(f"    {player.username}: {delta:+}")
                print()
                print("Leaderboard:")
                width = max(map(len, (p.username for p in game.players))) + 2
                for i, (player, points) in enumerate(game.points.most_common(),
                                                     start=1):
                    print(
                        f"\t{i}. {player.username:{width}}"
                        f"\t{points} {pluralize('token', points)} of affection"
                    )
                print()
                await pause()

            print_header(f"ROUND {e.round_no}", filler="#")
Esempio n. 8
0
def host_game(user: UserInfo):
    print_header("Hosting a game")
    mode = ask_valid_input(
        "Choose the server_addresses's visibility:",
        choices=HostVisibility,
        default=HostVisibility.PUBLIC,
    )
    addresses = {"local": get_local_ip()}
    if mode == HostVisibility.PUBLIC:
        addresses["public"] = get_public_ip()
        hosts = ("",)
    else:
        hosts = (
            "127.0.0.1",
            str(addresses["local"]),
        )  # allow either localhost or local net.
    print(f"Your address: {' | '.join(f'{v} ({k})' for k, v in addresses.items())}")
    port = ask_port_for_hosting()
    session = HostCLISession(user, hosts, port)
    asyncio.run(session.manage())
Esempio n. 9
0
def join_game(user: UserInfo):
    print_header("Joining game")
    address = ask_address_for_joining()
    session = GuestCLISession(user, address)
    asyncio.run(session.manage())