def test_level_over_but_not_game_over_when_player_beats_level(self): state = create_two_level_game_state(num_players=1) self.assertFalse(RuleChecker.is_game_over(state)) self.assertFalse(RuleChecker.is_level_over(state)) RuleChecker.validate_game_state(state) # move player to key state.update("p0", (7, 12)) # move player to exit state.update("p0", (7, 13)) self.assertFalse(RuleChecker.is_game_over(state))
def test_game_over_when_player_wins(self): state = create_basic_game_state() self.assertFalse(RuleChecker.is_game_over(state)) self.assertFalse(RuleChecker.is_level_over(state)) RuleChecker.validate_game_state(state) # move player to key state.update("p1", (7, 12)) # move player to exit state.update("p1", (7, 13)) self.assertTrue(RuleChecker.is_game_over) self.assertTrue(RuleChecker.is_level_over) self.assertEqual(RuleChecker.get_game_winner(state), constants.PLAYER_STRING)
def launch_game(self): """ 1. Creates a game & notifies players 2. Starts the game loop 3. Sends the game over message """ self.__create_initial_game_state() self.__send_start_message() while not RuleChecker.is_game_over(self.state): current_level = self.state.current_level while current_level == self.state.current_level \ and not RuleChecker.is_level_over(self.state): self.__send_state() self.__play_move() self.__send_level_over() self.__send_game_over()
def run_test(): """ 'Main' method for the test """ # Creates the intermediate game state based on the user input state_json, name, desired_location = read_user_input() state_json["level"] = swap_level(state_json["level"]) state = construct_state(state_json, name) # Validates the given move try: RuleChecker.validate_move(state, name, desired_location[::-1]) except InvalidOccupantIdError: print_json(["Failure", "Player ", name, " is not a part of the game."]) return except NonTraversableTileError: print_json([ "Failure", "The destination position ", desired_location, " is invalid." ]) return except: # Note: # Ignoring other exceptions (particularly InvalidDestinationError) # Because the assignment states: # > We are not checking rules, so the position # > can be arbitrarily removed from the original position pass # Update the state state.update(name, desired_location[::-1]) # Print the output if not state.occupants[name].is_alive: print_json( ["Success", "Player ", name, " was ejected.", state.to_json()]) elif state.occupants[name].has_exited: print_json(["Success", "Player ", name, " exited.", state.to_json()]) else: print_json(["Success", state.to_json()])
def __send_level_over(self): """ Sends the level over message to all connected entitites. """ level_number = self.state.current_level - 1 + RuleChecker.is_game_over( self.state) for actor in self.__all_actors.values(): actor.accept_game_state( StateExporter.create_end_level_state(self.state, level_number)) self.__update_observers()
def test_valid_move(self): state = create_basic_game_state() with self.assertRaises(InvalidOccupantIdError): RuleChecker.validate_move(state, "p0", [6,4]) with self.assertRaises(InvalidDestinationError): RuleChecker.validate_move(state, "p1", [10,2]) with self.assertRaises(NonTraversableTileError): RuleChecker.validate_move(state, "p1", [16,4]) RuleChecker.validate_move(state, "p1", state.occupants["p1"].current_location)
def __evaluate_game_state(self, occupant_id): """ Determines if the game or level is over If so, update the state the reflect that. """ result = constants.OK_RESULT occupant = self.occupants[occupant_id] if not occupant.is_alive: result = constants.EJECTED_RESULT elif occupant.actor_type == constants.PLAYER_ACTOR_TYPE: player_location = occupant.current_location # unlocks exit if the player found the key if player_location in self.current_level_object.items[ constants.KEY_NAME]: self.is_exit_unlocked = True self.current_level_object.remove_item(constants.KEY_NAME, player_location) result = constants.UNLOCKED_RESULT occupant.keys_found.add(self.current_level) # exits the level if they arrived at an unlocked exit elif player_location in self.current_level_object.items[ constants.EXIT_NAME] and self.is_exit_unlocked: occupant.has_exited = True occupant.current_tile.current_occupant = None result = constants.EXITED_RESULT occupant.exits.add(self.current_level) # End Game if RuleChecker.is_game_over(self): self.__end_game() # End level elif RuleChecker.is_level_over(self): self.__end_level() self.__store_player_message(occupant, result) return result
def test_game_not_over_when_one_player_dies(self): state = create_two_level_game_state() self.assertFalse(RuleChecker.is_game_over(state)) self.assertFalse(RuleChecker.is_level_over(state)) RuleChecker.validate_game_state(state) a1_location = state.occupants["a1"].current_location with self.assertRaises(InvalidOccupantTurnOrder): RuleChecker.validate_move(state, "p1", a1_location) state.update("p1", a1_location) self.assertFalse(RuleChecker.is_game_over(state)) self.assertFalse(RuleChecker.is_level_over(state))
def __play_move(self): """ 1. Gets the move from the current actor 2. Applies that move to the GameState 3. Sends the result to the actor. """ current_turn = self.state.current_turn current_actors = self.__current_actors if current_turn in current_actors: while True: move = current_actors[current_turn].provide_move() or \ self.state.occupants[current_turn].current_location try: RuleChecker.validate_move(self.state, current_turn, move) result = self.state.update(current_turn, move) current_actors[current_turn].accept_game_state(result) break except Exception as e: print("Player provided an invalid move.\nIt raised a:", type(e)) current_actors[current_turn].accept_game_state( constants.INVALID_RESULT) continue
def play_game(self): """ Plays the game using the preestablished moves. """ self.manager._send_players_game_state() _, _, num_turns, _, _ = self.user_input interactors = [self.manager] + self.players while self.manager.state.turns_elapsed < num_turns and not self.manager.state.is_game_over: for interactor in interactors: try: interactor.accept_messages_from_server() except PlayerOutofMovesError: return self.generate_output() if RuleChecker.is_game_over(self.manager.state): self.generate_output() self.generate_output()
def test_game_and_level_over_when_players_die(self): state = create_basic_game_state() self.assertFalse(RuleChecker.is_game_over(state)) self.assertFalse(RuleChecker.is_level_over(state)) RuleChecker.validate_game_state(state) a1_location = state.occupants["a1"].current_location p1_location = state.occupants["p1"].current_location with self.assertRaises(InvalidDestinationError): RuleChecker.validate_move(state, "p1", a1_location) for _ in range(5): state.update("a1", p1_location) self.assertTrue(RuleChecker.is_game_over) self.assertTrue(RuleChecker.is_level_over) self.assertEqual(RuleChecker.get_game_winner(state), constants.ADVERSARY_STRING)