def test_simple_game_play(): delay = 0.5 player_1 = 'Alice' player_2 = 'Bob' alice = queue.Queue() bob = queue.Queue() game_server_1 = Battleship(REDIS_HOST) game_server_2 = Battleship(REDIS_HOST) input_stream_1 = game_server_1.Game(stream(alice, player_1), {}) input_stream_2 = game_server_2.Game(stream(bob, player_2), {}) start_thread(input_stream_1, player_1) start_thread(input_stream_2, player_2) # Both players join alice.put(Request(join=Request.Player(id=player_1))) time.sleep(delay) bob.put(Request(join=Request.Player(id=player_2))) time.sleep(delay) # Player 1 gets to start alice.put(attack("a1")) bob.put(report(Status.State.MISS)) time.sleep(delay) # Now it is Player 2's turn bob.put(attack("j10")) alice.put(report(Status.State.HIT)) time.sleep(delay) # Now it is Player 1's turn alice.put(attack("c5")) bob.put(report(Status.State.MISS)) time.sleep(delay) # Now it is Player 2's turn bob.put(attack("e3")) alice.put(report(Status.State.DEFEAT)) time.sleep(delay) alice.put(None) bob.put(None) time.sleep(1)
def join(self): """This method sets up the client for sending and receiving gRPC messages to the server. It then sends a join message to the game server to indicate we are ready to play a new game. """ self.__player_id = str(uuid.uuid4()) logger.info(f'New player: {self.__player_id}') self.__channel = grpc.insecure_channel(f'{self.__host}:{self.__port}') stub = BattleshipsStub(self.__channel) responses = stub.Game(self.__stream()) self.__response_thread = threading.Thread( target=lambda: self.__receive_responses(responses)) self.__response_thread.daemon = True self.__response_thread.start() # Everything's set up, so we can now join a game self.__send(Request(join=Request.Player(id=self.__player_id)))
def attack(self, vector): """This method sends an Attack message with the associated vector to the game server. This method does not do any validation on the provided vector, other than that is must be a string. It is up to the caller to determine what the vector should look like. :param vector: Vector to send to game server, e.g., "G4" :raise ValueError: if vector is None or not a string """ if vector is None or type(vector) is not str: raise ValueError('Parameter vector must be a string!') self.__send(Request(move=Attack(vector=vector)))
def defeat(self): """This method indicates to the game serve that the received attack was a HIT, which sunk the last of the remaining ships. In other words: Game Over. Too bad. """ self.__send(Request(report=Status(state=Status.State.DEFEAT)))
def sunk(self): """This method indicates to the game server that the received attack has SUNK a ship. Phew! """ self.__send(Request(report=Status(state=Status.State.SUNK)))
def miss(self): """This method indicates to the game server that the received attack was a MISS. Phew! """ self.__send(Request(report=Status(state=Status.State.MISS)))
def hit(self): """This method indicates to the game server that the received attack was a HIT. Oh no! """ self.__send(Request(report=Status(state=Status.State.HIT)))
def report(state): return Request(report=Status(state=state))
def attack(vector): return Request(move=Attack(vector=vector))