def dict_to_game_state(state_dict): gs = GameState() if 'ball' in state_dict: gs.ball = BallState() if 'physics' in state_dict['ball']: gs.ball.physics = dict_to_physics(state_dict['ball']['physics']) if 'cars' in state_dict: gs.cars = {} for index, car in state_dict['cars'].items(): car_state = CarState() if 'physics' in car: car_state.physics = dict_to_physics(car['physics']) if 'boost_amount' in car: car_state.boost_amount = car['boost_amount'] gs.cars[int(index)] = car_state if 'game_info' in state_dict: gs.game_info = GameInfoState() if 'paused' in state_dict['game_info']: gs.game_info.paused = state_dict['game_info']['paused'] if 'world_gravity_z' in state_dict['game_info']: gs.game_info.world_gravity_z = state_dict['game_info']['world_gravity_z'] if 'game_speed' in state_dict['game_info']: gs.game_info.game_speed = state_dict['game_info']['game_speed'] if 'console_commands' in state_dict: gs.console_commands = state_dict['console_commands'] return gs
def manage_game_state(challenge: dict, upgrades: dict, setup_manager: SetupManager) -> Tuple[bool, dict]: """ Continuously track the game and adjust state to respect challenge rules and upgrades. At the end of the game, calculate results and the challenge completion and return that """ early_failure = False, {} expected_player_count = challenge["humanTeamSize"] + len( challenge["opponentBots"]) # Wait for everything to be initialized packet = wait_till_cars_spawned(setup_manager, expected_player_count) if packet.num_cars == 0: print("The game was initialized with no cars") return early_failure tick_rate = 120 results = None max_boost = 0 if "boost-100" in upgrades: max_boost = 100 elif "boost-33" in upgrades: max_boost = 33 half_field = challenge.get("limitations", []).count("half-field") > 0 stats_tracker = ManualStatsTracker(challenge) last_boost_bump_time = time.monotonic() while True: try: eel.sleep(0) # yield to allow other gui threads to operate. packet = GameTickPacket() setup_manager.game_interface.fresh_live_data_packet( packet, 1000, WITNESS_ID) if packet.num_cars == 0: # User seems to have ended the match print("User ended the match") return early_failure stats_tracker.updateStats(packet) results = packet_to_game_results(packet) if has_user_perma_failed(challenge, stats_tracker.stats): time.sleep(1) setup_failure_freeplay(setup_manager, "You failed the challenge!") return early_failure if end_by_mercy(challenge, stats_tracker.stats, results): time.sleep(3) setup_failure_freeplay(setup_manager, "Challenge completed by mercy rule!", "green") return True, results human_info = packet.game_cars[0] game_state = GameState() human_desired_state = CarState() game_state.cars = {0: human_desired_state} changed = False # adjust boost if human_info.boost > max_boost and not half_field: # Adjust boost, unless in heatseeker mode human_desired_state.boost_amount = max_boost changed = True if "boost-recharge" in upgrades: # increase boost at 10% per second now = time.monotonic() if human_info.boost < max_boost and (now - last_boost_bump_time > 0.1): changed = True last_boost_bump_time = now human_desired_state.boost_amount = min( human_info.boost + 1, max_boost) if changed: setup_manager.game_interface.set_game_state(game_state) if packet.game_info.is_match_ended: break except KeyError: traceback.print_exc() # it means that the game was interrupted by the user print("Looks like the game is in a bad state") setup_failure_freeplay(setup_manager, "The game was interrupted.") return early_failure return calculate_completion(challenge, stats_tracker.stats, results), results