Exemple #1
0
    async def end_game_with_reason(self, our_ctrl: GameController,
                                   other_ctrl: GameController,
                                   our_reason: EndGameReason,
                                   other_reason: EndGameReason):
        our_ctrl.cancel_timeout()
        other_ctrl.cancel_timeout()

        del self.games[our_ctrl.game_id]
        del self.user_game_ctrl[our_ctrl.username]
        del self.user_game_ctrl[other_ctrl.username]
        del self.user_gid[our_ctrl.username]
        del self.user_gid[other_ctrl.username]

        # if this was called from logout, the user no longer exists
        if our_ctrl.username in self.users:
            self.users[
                our_ctrl.username].state = ClientConnectionState.GAME_SELECTION

        # if this was called from logout, the user no longer exists
        if other_ctrl.username in self.users:
            self.users[other_ctrl.
                       username].state = ClientConnectionState.GAME_SELECTION

        await self.send(
            other_ctrl.client,
            ProtocolMessage.create_single(ProtocolMessageType.ENDGAME,
                                          {"reason": other_reason}))
        await self.send(
            our_ctrl.client,
            ProtocolMessage.create_single(ProtocolMessageType.ENDGAME,
                                          {"reason": our_reason}))

        self.print_stats()
Exemple #2
0
    async def handle_shoot(self, client: Client, msg: ProtocolMessage):
        our_ctrl: GameController = self.user_game_ctrl[client.username]
        other_ctrl: GameController = self.user_game_ctrl[
            our_ctrl.opponent_name]

        try:
            hit: bool = other_ctrl.run(msg)
        except BattleshipError as e:
            answer = ProtocolMessage.create_error(e.error_code)
            await self.send(client, answer)
            return
        except Exception as e:
            raise e

        our_ctrl.timeout_counter = 0
        our_ctrl.cancel_timeout()

        if hit:
            sunk: bool = other_ctrl.ship_sunk_at_pos(
                msg.parameters["position"].horizontal,
                msg.parameters["position"].vertical)
            msg_hit: ProtocolMessage = ProtocolMessage.create_single(
                ProtocolMessageType.HIT, {
                    "sunk": sunk,
                    "position": msg.parameters["position"]
                })

            await self.send(other_ctrl.client, msg_hit)
            await self.send(our_ctrl.client, msg_hit)
            our_ctrl.run(msg_hit)
            other_ctrl.run(msg_hit)

            our_ctrl.start_timeout(self.handle_timeout_wrapper)

            if other_ctrl.all_ships_sunk():
                await self.end_game_with_reason(our_ctrl, other_ctrl,
                                                EndGameReason.YOU_WON,
                                                EndGameReason.OPPONENT_WON)

        else:
            msg_fail: ProtocolMessage = ProtocolMessage.create_single(
                ProtocolMessageType.FAIL,
                {"position": msg.parameters["position"]})

            await self.send(other_ctrl.client, msg_fail)
            await self.send(our_ctrl.client, msg_fail)
            our_ctrl.run(msg_fail)
            other_ctrl.run(msg_fail)

            other_ctrl.start_timeout(self.handle_timeout_wrapper)
Exemple #3
0
    async def handle_timeout(self, client: Client):
        if not client.username in self.user_game_ctrl:
            # This happened once when a timeout came almost exactly when the game ended
            return

        our_ctrl: GameController = self.user_game_ctrl[client.username]

        if not our_ctrl.opponent_name in self.user_game_ctrl:
            # This happened once when a timeout came almost exactly when the game ended
            return

        other_ctrl: GameController = self.user_game_ctrl[
            our_ctrl.opponent_name]

        our_ctrl.timeout_counter += 1

        if our_ctrl.timeout_counter >= 3:
            # TODO: really send OPPONENT_WON?
            await self.end_game_with_reason(our_ctrl, other_ctrl,
                                            EndGameReason.OPPONENT_WON,
                                            EndGameReason.OPPONENT_TIMEOUT)
            return

        msg_timeout: ProtocolMessage = ProtocolMessage.create_single(
            ProtocolMessageType.TIMEOUT)

        await self.send(our_ctrl.client, msg_timeout)
        await self.send(other_ctrl.client, msg_timeout)
        our_ctrl.run(msg_timeout)
        other_ctrl.run(msg_timeout)

        other_ctrl.start_timeout(self.handle_timeout_wrapper)
Exemple #4
0
    async def handle_move(self, client: Client, msg: ProtocolMessage):
        our_ctrl: GameController = self.user_game_ctrl[client.username]
        other_ctrl: GameController = self.user_game_ctrl[
            our_ctrl.opponent_name]

        try:
            positions: Positions = our_ctrl.run(msg)
        except BattleshipError as e:
            answer: ProtocolMessage = ProtocolMessage.create_error(
                e.error_code)
            await self.send(client, answer)
            return
        except Exception as e:
            raise e

        our_ctrl.timeout_counter = 0
        our_ctrl.cancel_timeout()

        # notify
        params = {}
        if not len(positions.positions) == 0:
            params["positions"] = positions
        msg_moved: ProtocolMessage = ProtocolMessage.create_single(
            ProtocolMessageType.MOVED, params)

        await self.send(other_ctrl.client, msg_moved)
        await self.send(our_ctrl.client, msg_moved)
        our_ctrl.run(msg_moved)
        other_ctrl.run(msg_moved)

        other_ctrl.start_timeout(self.handle_timeout_wrapper)
Exemple #5
0
    async def send_cancel(self):
        msg = ProtocolMessage.create_single(ProtocolMessageType.CANCEL)
        await self.client.send_and_wait_for_answer(msg)

        # TODO: timeouts
        if self.client.last_msg_was_error:
            raise BattleshipError(self.client.last_error)
Exemple #6
0
    async def handle_place(self, client: Client, msg: ProtocolMessage):
        our_ctrl: GameController = self.user_game_ctrl[client.username]
        other_ctrl: GameController = self.user_game_ctrl[
            our_ctrl.opponent_name]

        try:
            our_ctrl.run(msg)
        except BattleshipError as e:
            # TODO: maybe check if it's not an internal error
            answer: ProtocolMessage = ProtocolMessage.create_error(
                e.error_code)
            await self.send(client, answer)
            return
        except Exception as e:
            raise e

        # notify the other
        msg_placed: ProtocolMessage = ProtocolMessage.create_single(
            ProtocolMessageType.PLACED)
        await self.send(other_ctrl.client, msg_placed)

        # if both are on waiting, the game can start
        if our_ctrl.state == GameState.WAITING and other_ctrl.state == GameState.WAITING:
            # who starts?
            starting_ctrl: GameController
            waiting_ctrl: GameController
            (starting_ctrl, waiting_ctrl) = (
                our_ctrl, other_ctrl) if randrange(2) == 1 else (other_ctrl,
                                                                 our_ctrl)

            youstart: ProtocolMessage = ProtocolMessage.create_single(
                ProtocolMessageType.YOUSTART)
            await self.send(starting_ctrl.client, youstart)
            starting_ctrl.run(youstart)
            starting_ctrl.timeout_counter = 0
            starting_ctrl.start_timeout(self.handle_timeout_wrapper)

            youwait: ProtocolMessage = ProtocolMessage.create_single(
                ProtocolMessageType.WAIT)
            await self.send(waiting_ctrl.client, youwait)
            waiting_ctrl.run(youwait)

            # TODO: fix this, should be merged with state, is this even used anymore?
            starting_ctrl._game_started = True
            waiting_ctrl._game_started = True
Exemple #7
0
    async def handle_chat_send(self, client: Client, msg: ProtocolMessage):
        params: Dict[str, Any] = msg.parameters
        answer: Optional[ProtocolMessage] = None
        forward: ProtocolMessage

        text: str = params["text"]
        recipient: str = params["username"]

        if len(text) > ProtocolConfig.CHAT_MAX_TEXT_LENGTH:
            answer = ProtocolMessage.create_error(
                ErrorCode.SYNTAX_MESSAGE_TEXT_TOO_LONG)

        # check if the message is for all users
        elif recipient == "":
            forward = ProtocolMessage.create_single(
                ProtocolMessageType.CHAT_RECV, {
                    "sender": client.username,
                    "recipient": "",
                    "text": text
                })
            await self.msg_to_all_but_one(forward, client.username)
            self.print_client(
                client,
                "Forwarding chat message to all logged in users but {}".format(
                    client.username))

        elif recipient not in self.users:
            answer = ProtocolMessage.create_error(
                ErrorCode.PARAMETER_USERNAME_DOES_NOT_EXIST)

        else:
            forward = ProtocolMessage.create_single(
                ProtocolMessageType.CHAT_RECV, {
                    "sender": client.username,
                    "recipient": recipient,
                    "text": text
                })
            await self.msg_to_user(forward, recipient)
            self.print_client(
                client, "Forwarding chat message to '{}'".format(recipient))

        if answer is not None:
            await self.send(client, answer)
    async def client(client_id: int):

        async def msg_callback(msg: ProtocolMessage):
            print("< [{}] {}".format(client_id, msg))

        def closed_callback():
            print("< [{}] server closed connection".format(client_id))

        async def _send_and_wait(msg: ProtocolMessage, seconds_to_wait: float = 0.0):
            print("> [{}] {}".format(client_id, msg))
            await battleship_client.send(msg)
            if seconds_to_wait > 0:
                await asyncio.sleep(seconds_to_wait)

        battleship_client = BattleshipClient(loop, msg_callback, closed_callback)
        await battleship_client.connect(Constants.SERVER_IP, Constants.SERVER_PORT)

        # the following messages are just to test
        # normally you can just call `await battleship_client.send(msg)`
        # await is necessary because it's asynchronous

        await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.LOGIN,
                                                    {"username": "******".format(client_id)}))

        if client_id % 2 == 0:
            await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.CREATE_GAME,
                                         {"board_size": 10,
                                          "num_ships": NumShips([1, 1, 1, 1, 1]),
                                          "round_time": 25,
                                          "options": GameOptions.PASSWORD,
                                          "password": "******"
                                              }))

        #await do_join.wait()
        await asyncio.sleep(10)

        if client_id % 2 == 1:
            await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.JOIN,
                                                    {"game_id": int((client_id+1)/2), "password": "******"}))

        #await finished.wait()
        await asyncio.sleep(10)
        battleship_client.close()
Exemple #9
0
    async def send_join(self, game_id: int, password: str = ""):
        params: Dict[str, Any] = {"game_id": game_id}
        if not password == "":
            params["password"] = password
        msg: ProtocolMessage = ProtocolMessage.create_single(
            ProtocolMessageType.JOIN, params)
        await self.client.send_and_wait_for_answer(msg)

        # TODO: timeouts
        if self.client.last_msg_was_error:
            raise BattleshipError(self.client.last_error)
Exemple #10
0
 async def send_chat(self, username, text):
     if len(text) > ProtocolConfig.CHAT_MAX_TEXT_LENGTH:
         offset = 0
         while offset < len(text):
             next_text = text[offset:offset +
                              ProtocolConfig.CHAT_MAX_TEXT_LENGTH]
             offset += ProtocolConfig.CHAT_MAX_TEXT_LENGTH
             msg = ProtocolMessage.create_single(
                 ProtocolMessageType.CHAT_SEND, {
                     "username": username,
                     "text": next_text
                 })
             await self.client.send(msg)
     else:
         msg = ProtocolMessage.create_single(ProtocolMessageType.CHAT_SEND,
                                             {
                                                 "username": username,
                                                 "text": text
                                             })
         await self.client.send(msg)
Exemple #11
0
    async def send_get_games(self):
        try:
            msg = ProtocolMessage.create_single(ProtocolMessageType.GET_GAMES)
            self.games = {}
            await self.client.send_and_wait_for_answer(msg)
        except Exception as e:
            logging.debug("send_get_games-->".format(str(e)))

        # TODO: timeouts
        if self.client.last_msg_was_error:
            raise BattleshipError(self.client.last_error)
Exemple #12
0
    async def try_login(self, server, port, username):
        if not self.client.connected:
            await self.client.connect(server, port)

        if username.strip() == "":
            raise BattleshipError(ErrorCode.PARAMETER_INVALID_USERNAME)
        elif len(username) > ProtocolConfig.USERNAME_MAX_LENGTH:
            raise BattleshipError(ErrorCode.SYNTAX_USERNAME_TOO_LONG)

        msg = ProtocolMessage.create_single(ProtocolMessageType.LOGIN,
                                            {"username": username})
        await self.client.send_and_wait_for_answer(msg)

        # TODO: timeouts
        if self.client.last_msg_was_error:
            raise BattleshipError(self.client.last_error)
Exemple #13
0
 async def send_delete_game(self, game_id: int):
     del_msg: ProtocolMessage = ProtocolMessage.create_single(
         ProtocolMessageType.DELETE_GAME, {"game_id": game_id})
     await self.msg_to_all(del_msg)
Exemple #14
0
 async def send_abort(self):
     msg = ProtocolMessage.create_single(ProtocolMessageType.ABORT)
     await self.client.send_and_wait_for_answer(msg)
Exemple #15
0
    async def client(client_id: int):

        async def msg_callback(msg: ProtocolMessage):
            print("< [{}] {}".format(client_id, msg))

        def closed_callback():
            print("< [{}] server closed connection".format(client_id))

        async def _send_and_wait(msg: ProtocolMessage, seconds_to_wait: float = 1.0):
            print("> [{}] {}".format(client_id, msg))
            await battleship_client.send(msg)
            if seconds_to_wait > 0:
                await asyncio.sleep(seconds_to_wait)

        battleship_client = BattleshipClient(loop, msg_callback, closed_callback)
        await battleship_client.connect(Constants.SERVER_IP, Constants.SERVER_PORT)

        # the following messages are just to test
        # normally you can just call `await battleship_client.send(msg)`
        # await is necessary because it's asynchronous

        await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.LOGIN,
                                                    {"username": "******".format(client_id)}))

        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.CREATE_GAME,
        #                                 {"board_size": 5,
        #                                  "num_ships": NumShips([1, 2, 3, 4, 5]),
        #                                  "round_time": 25,
        #                                  "options": GameOptions.PASSWORD,
        #                                  "password": "******"
        #                                      }))
        #
        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.CREATE_GAME,
        #                                 {"board_size": 5,
        #                                  "num_ships": NumShips([1, 2, 3, 4, 5]),
        #                                  "round_time": 25,
        #                                  "options": 0
        #                                      }))

        await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.CHAT_SEND, {"username": "******".format((client_id + 1) % 2), "text": "hurz from client {}".format(client_id)}))
        await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.CHAT_SEND, {"username": "", "text": "z"}))
        #
        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.MOVE, {"turn_counter": 2, "ship_id": 146579, "direction": Orientation.EAST}))
        #
        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.GAME, {
        #     "game_id": 60000, "username": "******", "board_size": 7, "num_ships": NumShips([1, 2, 3, 4, 5]), "round_time": 25, "options": GameOptions.PASSWORD}))
        #
        # await _send_and_wait(ProtocolMessage.create_repeating(ProtocolMessageType.GAMES, [
        #     {"game_id": 60000, "username": "******", "board_size": 7, "num_ships": NumShips([1, 2, 3, 4, 5]),
        #         "round_time": 25, "options": GameOptions.PASSWORD},
        #     {"game_id": 60001, "username": "******", "board_size": 8, "num_ships": NumShips([1, 2, 3, 4, 6]),
        #         "round_time": 30, "options": 0},
        #     {"game_id": 60002, "username": "******", "board_size": 9, "num_ships": NumShips([1, 2, 3, 4, 7]),
        #      "round_time": 35, "options": GameOptions.PASSWORD}]))
        #
        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.JOIN, {"game_id": 60000, "password": "******"}))
        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.JOIN, {"game_id": 60001}))

        await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.LOGOUT))

        battleship_client.close()
Exemple #16
0
    async def client(client_id: int):
        async def msg_callback(msg: ProtocolMessage):
            print("< [{}] {}".format(client_id, msg))

        def closed_callback():
            print("< [{}] server closed connection".format(client_id))

        async def _send_and_wait(msg: ProtocolMessage,
                                 seconds_to_wait: float = 0.5):
            print("> [{}] {}".format(client_id, msg))
            await battleship_client.send(msg)
            if seconds_to_wait > 0:
                await asyncio.sleep(seconds_to_wait)

        # Ding was die Verbindung managed zum Server
        battleship_client = BattleshipClient(loop, msg_callback,
                                             closed_callback)
        await battleship_client.connect(Constants.SERVER_IP,
                                        Constants.SERVER_PORT)
        #await battleship_client.connect("192.168.0.1", "4242")
        # the following messages are just to test
        # normally you can just call `await battleship_client.send(msg)`
        # await is necessary because it's asynchronous

        await _send_and_wait(
            ProtocolMessage.create_single(
                ProtocolMessageType.LOGIN,
                {"username": "******".format(client_id)}))

        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.CREATE_GAME,
        #                                 {"board_size": 5,
        #                                  "num_ships": NumShips([1, 2, 3, 4, 5]),
        #                                  "round_time": 25,
        #                                  "options": GameOptions.PASSWORD,
        #                                  "password": "******"
        #                                      }))
        #
        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.CREATE_GAME,
        #                                 {"board_size": 5,
        #                                  "num_ships": NumShips([1, 2, 3, 4, 5]),
        #                                  "round_time": 25,
        #                                  "options": 0
        #                                      }))
        input("PUSH THE BUTTON for chatting")
        await _send_and_wait(
            ProtocolMessage.create_single(
                ProtocolMessageType.CHAT_SEND, {
                    "username": "******".format((client_id + 1) % 2),
                    "text":
                    "client {} schießt den server ab :P".format(client_id)
                }))
        input("PUSH THE BUTTON to create a game")
        #await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.CHAT_SEND, {"username": "", "text": "z"}))

        await _send_and_wait(
            ProtocolMessage.create_single(
                ProtocolMessageType.CREATE_GAME, {
                    "board_size": 10,
                    "num_ships": NumShips([1, 0, 0, 0, 2]),
                    "round_time": 25,
                    "options": 0
                }))

        input("PUSH THE BUTTON to place a game")
        msg = ProtocolMessage.create_single(
            ProtocolMessageType.PLACE, {
                "ship_positions":
                ShipPositions([
                    ShipPosition(Position(0, 0), Orientation.EAST),
                    ShipPosition(Position(3, 0), Orientation.EAST)
                ])
            })

        await _send_and_wait(msg)
        ####################################################################################################################
        # Start Playing #
        ####################################################################################################################
        end = input("x=exit, m=move, s=shoot:_")
        while end is not "x":
            if end == "s":
                turn_counter = int(input("insert turn_counter to shoot: "))
                x_pos = int(input("shot x_pos: "))
                y_pos = int(input("shoot y_pos: "))
                msg = ProtocolMessage.create_single(
                    ProtocolMessageType.SHOOT, {
                        "position": Position(y_pos, x_pos),
                        "turn_counter": turn_counter
                    })

            if end == "m":
                turn_counter = int(input("insert turn_counter to move: "))
                move_direction = int(input("insert move direction: "))
                msg = ProtocolMessage.create_single(
                    ProtocolMessageType.MOVE, {
                        "ship_id": 0,
                        "direction": move_direction,
                        "turn_counter": turn_counter
                    })

            await _send_and_wait(msg)
            end = input("x=exit, m=move, s=shoot:_")

#ABORT
        input("PUSH THE BOTTEN for abort")
        msg = ProtocolMessage.create_single(ProtocolMessageType.ABORT)
        await _send_and_wait(msg)

        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.MOVE, {"turn_counter": 2, "ship_id": 146579, "direction": Orientation.EAST}))
        #
        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.GAME, {
        #     "game_id": 60000, "username": "******", "board_size": 7, "num_ships": NumShips([1, 2, 3, 4, 5]), "round_time": 25, "options": GameOptions.PASSWORD}))
        #
        # await _send_and_wait(ProtocolMessage.create_repeating(ProtocolMessageType.GAMES, [
        #     {"game_id": 60000, "username": "******", "board_size": 7, "num_ships": NumShips([1, 2, 3, 4, 5]),
        #         "round_time": 25, "options": GameOptions.PASSWORD},
        #     {"game_id": 60001, "username": "******", "board_size": 8, "num_ships": NumShips([1, 2, 3, 4, 6]),
        #         "round_time": 30, "options": 0},
        #     {"game_id": 60002, "username": "******", "board_size": 9, "num_ships": NumShips([1, 2, 3, 4, 7]),
        #      "round_time": 35, "options": GameOptions.PASSWORD}]))
        #
        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.JOIN, {"game_id": 60000, "password": "******"}))
        # await _send_and_wait(ProtocolMessage.create_single(ProtocolMessageType.JOIN, {"game_id": 60001}))

        ####################################################################################################################
        # Logout #
        ####################################################################################################################
        input("PUSH THE BUTTON to logout")
        await _send_and_wait(
            ProtocolMessage.create_single(ProtocolMessageType.LOGOUT))

        battleship_client.close()