Пример #1
0
    def test_on_briefing_tweak(self):
        logger = get_logger('steering optimization')
        # We want to assert that this constant is better than other constants.

        # Hold the setup_manager here such that we don't need to shutdown/relaunch everything all the time.
        with setup_manager_context() as setup_manager:

            def time_to_goal(steering_coefficient: float) -> float:
                ex = TurnAndDriveToBall(
                    name=
                    f'Turn to ball (steering_coefficient={steering_coefficient:.2f})',
                    steering_coefficient=steering_coefficient)
                result = list(run_playlist([ex],
                                           setup_manager=setup_manager))[0]
                grade = result.grade
                assert isinstance(
                    grade,
                    GameTickPacketWrapperGrader.WrappedPass) or isinstance(
                        grade, GameTickPacketWrapperGrader.WrappedFail
                    ), f'Unexpected grade: {grade}'
                duration_seconds = grade.last_tick.game_info.seconds_elapsed - grade.first_tick.game_info.seconds_elapsed
                logger.debug(f'intermediate result: {duration_seconds}')
                return duration_seconds

            result = naive_function_minimization(time_to_goal, .4, 9)

        logger.debug('Best steering_coefficient: ', result.best_input)
        logger.debug('all_samples:')
        for k, v in sorted(result.all_samples.items()):
            logger.debug(f'{k},{v}')
        self.assertLess(0.4, result.best_input)
        self.assertLess(1.0, result.best_output)
        self.assertLess(result.best_output, 4.0)
Пример #2
0
    def test_render_call(self):
        test_self = self
        class RenderTestExercise(Exercise):
            def get_name(self):
                return 'RenderTestExercise'
            def get_match_config(self) -> MatchConfig:
                return read_match_config_from_file(Path(__file__).parent / 'training_test.cfg')
            def setup(self, rng: random.Random) -> GameState:
                self.num_render_calls = 0
                self.num_on_tick_calls = 0
                return GameState()
            def on_tick(self, game_tick_packet: GameTickPacket) -> Optional[Result]:
                self.num_on_tick_calls += 1
                if self.num_on_tick_calls >= 100:
                    nonlocal test_self
                    test_self.assertEqual(self.num_on_tick_calls-1, self.num_render_calls)
                    return Pass()
            def render(self, renderer: RenderingManager):
                self.num_render_calls += 1

        with setup_manager_context() as setup_manager:
            results = list(run_exercises(setup_manager, [RenderTestExercise()], 4))
        self.assertEqual(len(results), 1)
        result = results[0]
        self.assertIsInstance(result.grade, Pass)
Пример #3
0
def run_module(python_file_with_playlist: Path, history_dir: Optional[Path] = None,
    reload_policy=ReloadPolicy.EACH_EXERCISE, render_policy=RenderPolicy.DEFAULT):
    """
    This function repeatedly runs exercises in the module and reloads the module to pick up
    any new changes to the Exercise. e.g. make_game_state() can be updated or
    you could implement a new Grader without needing to terminate the training.
    """

    # load the playlist initially, keep trying if we fail
    playlist_factory = None
    playlist: Playlist = None
    while playlist is None:
        try:
            playlist_factory = load_default_playlist(python_file_with_playlist)
            playlist = playlist_factory()
        except Exception:
            traceback.print_exc()
            time.sleep(1.0)

    log = get_logger(LOGGER_ID)
    with setup_manager_context() as setup_manager:
        apply_render_policy(render_policy, setup_manager)
        for seed in infinite_seed_generator():
            playlist = playlist_factory()
            wrapped_exercises = [TrainingExerciseAdapter(ex) for ex in playlist]
            result_iter = rlbot_run_exercises(setup_manager, wrapped_exercises, seed)

            for i, rlbot_result in enumerate(result_iter):
                result = ExerciseResult(
                    grade=rlbot_result.grade,
                    exercise=rlbot_result.exercise.exercise,  # unwrap the TrainingExerciseAdapter.
                    reproduction_info=ReproductionInfo(
                        seed=seed,
                        python_file_with_playlist=str(python_file_with_playlist.absolute()),
                        playlist_index=i,
                    )
                )

                log_result(result, log)
                if history_dir:
                    store_result(result, history_dir)

                # Reload the module and apply the new exercises
                if reload_policy == ReloadPolicy.EACH_EXERCISE:
                    try:
                        new_playlist_factory = load_default_playlist(python_file_with_playlist)
                        new_playlist = new_playlist_factory()
                    except Exception:
                        traceback.print_exc()
                        continue  # keep running previous exercises until new ones are fixed.
                    playlist_factory = new_playlist_factory
                    if len(new_playlist) != len(playlist) or any(e1.name != e2.name for e1,e2 in zip(new_playlist, playlist)):
                        log.warning(f'Need to restart to pick up new exercises.')
                        playlist = new_playlist
                        break  # different set of exercises. Can't monkeypatch.
                    for new_exercise, old_exercise in zip(new_playlist, playlist):
                        _monkeypatch_copy(new_exercise, old_exercise)
Пример #4
0
def run_match(
    ld: LeagueDir, match_details: MatchDetails,
    bots: Mapping[BotID, BotConfigBundle], replay_preference: ReplayPreference
) -> Tuple[MatchResult, Optional[ReplayData]]:
    """
    Run a match, wait for it to finish, and return the result.
    """

    with setup_manager_context() as setup_manager:

        # Expose data to overlay
        make_overlay(ld, match_details, bots)

        # Prepare the match exercise
        print(
            f"Starting match: {match_details.blue} vs {match_details.orange}. Waiting for match to finish..."
        )
        match = MatchExercise(name=match_details.name,
                              match_config=match_details.to_config(bots),
                              grader=MatchGrader(replay_monitor=ReplayMonitor(
                                  replay_preference=replay_preference), ))

        # If any bots have signed up for early start, give them 10 seconds.
        # This is typically enough for Scratch.
        setup_manager.early_start_seconds = 10

        # For loop, but should only run exactly once
        for exercise_result in run_playlist(
            [match],
                setup_manager=setup_manager,
                render_policy=RenderPolicy.DEFAULT):

            replay_data = None

            # Warn if no replay was found
            replay_data = exercise_result.exercise.grader.replay_monitor.replay_data(
            )
            if isinstance(exercise_result.grade,
                          Fail) and replay_data.replay_id is None:
                print(
                    f"WARNING: No replay was found for the match '{match_details.name}'."
                )
            else:
                if replay_preference != ReplayPreference.NONE and replay_data.replay_path is not None:
                    try:
                        dst = ld.replays / f"{replay_data.replay_id}.replay"
                        shutil.copy(replay_data.replay_path, dst)
                        print(
                            "Replay successfully copied to replays directory")
                    except:
                        pass

            match_result = confirm_match_result(
                exercise_result.exercise.grader.match_result)
            return match_result, replay_data
Пример #5
0
def match_running(start_event: Event, stop_event: Event, exit_event: Event):
    with setup_manager_context() as manager:
        while True:
            if start_event.is_set():
                start_match(manager)
                start_event.clear()
            elif stop_event.is_set():
                stop_match(manager)
                stop_event.clear()
            elif exit_event.is_set():
                exit_event.clear()
                break
Пример #6
0
def run_playlist(playlist: Playlist, seed: int = 4) -> Iterator[ExerciseResult]:
    with setup_manager_context() as setup_manager:
        wrapped_exercises = [TrainingExerciseAdapter(ex) for ex in playlist]
        for i, rlbot_result in enumerate(rlbot_run_exercises(setup_manager, wrapped_exercises, seed)):
            yield ExerciseResult(
                grade=rlbot_result.grade,
                exercise=rlbot_result.exercise.exercise,  # unwrap the TrainingExerciseAdapter.
                reproduction_info=ReproductionInfo(
                    seed=seed,
                    playlist_index=i,
                )
            )
Пример #7
0
def run_test_match(participant_1: str, participant_2: str,
                   match_config) -> Optional[Grade]:

    # Play the match
    print(f'Starting test match: {participant_1} vs {participant_2}...')
    match = MatchExercise(name=f'{participant_1} vs {participant_2}',
                          match_config=match_config,
                          grader=AliveGrader())

    with setup_manager_context() as setup_manager:

        # If any bots have signed up for early start, give them 10 seconds.
        # This is typically enough for Scratch.
        setup_manager.early_start_seconds = 10

        # For loop, but should only run exactly once
        for exercise_result in run_playlist([match],
                                            setup_manager=setup_manager):
            return exercise_result.grade
Пример #8
0
    def test_run_exercises(self):
        ownGoalExercise = BallInFrontOfCar('BallInFrontOfCar(facing own goal)', Vector3(0, -4000, 0), ball_location=Vector3(0,-4500,100))
        seed = 4
        with setup_manager_context() as setup_manager:
            result_iter = run_exercises(
                setup_manager,
                [
                    BallInFrontOfCar('BallInFrontOfCar(goal 1)', Vector3(0, 3500, 0)),
                    BallInFrontOfCar('BallInFrontOfCar(goal 2)', Vector3(1000, 3500, 0)),
                    ownGoalExercise,
                    BallInFrontOfCar('BallInFrontOfCar(sideways)', Vector3(-1500, 0, 0), ball_location=Vector3(1500, 0, 100)),
                ],
                seed
            )

            result = next(result_iter)
            self.assertEqual(result.exercise.get_name(), 'BallInFrontOfCar(goal 1)')
            self.assertIsInstance(result.grade, Pass)

            result = next(result_iter)
            self.assertEqual(result.exercise.get_name(), 'BallInFrontOfCar(goal 2)')
            self.assertIsInstance(result.grade, Pass)

            result = next(result_iter)
            self.assertEqual(result.exercise.get_name(), 'BallInFrontOfCar(facing own goal)')
            self.assertIsInstance(result.grade, Fail)
            self.assertIsInstance(result.grade, FailWithReason)
            self.assertEqual(result.grade.reason, 'own goal')
            self.assertIs(result.exercise, ownGoalExercise)
            self.assertIsInstance(result.seed, int)

            result = next(result_iter)
            self.assertEqual(result.exercise.get_name(), 'BallInFrontOfCar(sideways)')
            self.assertIsInstance(result.grade, Fail)
            self.assertIsInstance(result.grade, FailDueToExerciseException)
            self.assertIsInstance(result.grade.exception, Exception)
            self.assertIsInstance(result.grade.exception, ArithmeticError) # 1/0

            try:
                next(result_iter)
                self.Fail('expected the result_iter to be finished.')
            except StopIteration:
                pass
Пример #9
0
def run_match(participant_1: str, participant_2: str, match_config,
              replay_preference: ReplayPreference) -> MatchResult:
    with setup_manager_context() as setup_manager:

        # Prepare the match exercise
        print(
            f'Starting match: {participant_1} vs {participant_2}. Waiting for match to finish...'
        )
        match = MatchExercise(
            name=f'{participant_1} vs {participant_2}',
            match_config=match_config,
            grader=MatchGrader(
                mercy_rule=MercyRule(
                    game_interface=setup_manager.game_interface),
                replay_monitor=ReplayMonitor(
                    replay_preference=replay_preference),
            ))

        # If any bots have signed up for early start, give them 10 seconds.
        # This is typically enough for Scratch.
        setup_manager.early_start_seconds = 10

        # For loop, but should only run exactly once
        for exercise_result in run_playlist(
            [match],
                setup_manager=setup_manager,
                render_policy=RenderPolicy.NO_TRAINING_RENDER):

            # Warn users if no replay was found
            if isinstance(
                    exercise_result.grade, Fail
            ) and exercise_result.exercise.grader.replay_monitor.replay_id == None:
                print(
                    f'WARNING: No replay was found for the match \'{participant_1} vs {participant_2}\'. Is Bakkesmod injected and \'Automatically save all replays\' enabled?'
                )

            return exercise_result.exercise.grader.match_result
Пример #10
0
def run_league_play(working_dir: WorkingDir, odd_week: bool,
                    replay_preference: ReplayPreference):
    """
    Run a league play event by running round robins for half the divisions. When done, a new ladder file is created.
    """

    bots = load_all_bots(working_dir)
    ladder = Ladder.read(working_dir.ladder)

    # We need the result of every match to create the next ladder. For each match in each round robin, if a result
    # exist already, it will be parsed, if it doesn't exist, it will be played.
    # When all results have been found, the new ladder can be completed and saved.
    new_ladder = Ladder(ladder.bots)
    event_results = []

    # playing_division_indices contains either even or odd indices.
    # If there is only one division always play that division (division 0, quantum).
    playing_division_indices = range(
        ladder.division_count())[int(odd_week) %
                                 2::2] if ladder.division_count() > 1 else [0]

    # The divisions play in reverse order, so quantum/overclocked division plays last
    for div_index in playing_division_indices[::-1]:
        print(
            f'Starting round robin for the {Ladder.DIVISION_NAMES[div_index]} division'
        )

        rr_bots = ladder.round_robin_participants(div_index)
        rr_matches = generate_round_robin_matches(rr_bots)
        rr_results = []

        for match_participants in rr_matches:

            # Check if match has already been play, i.e. the result file already exist
            result_path = working_dir.get_match_result(div_index,
                                                       match_participants[0],
                                                       match_participants[1])
            if result_path.exists():
                # Found existing result
                try:
                    print(f'Found existing result {result_path.name}')
                    result = MatchResult.read(result_path)

                    rr_results.append(result)

                except Exception as e:
                    print(
                        f'Error loading result {result_path.name}. Fix/delete the result and run script again.'
                    )
                    raise e

            else:
                assert match_participants[
                    0] in bots, f'{match_participants[0]} was not found in \'{working_dir.bots}\''
                assert match_participants[
                    1] in bots, f'{match_participants[1]} was not found in \'{working_dir.bots}\''

                # Play the match
                print(
                    f'Starting match: {match_participants[0]} vs {match_participants[1]}. Waiting for match to finish...'
                )
                match_config = make_match_config(working_dir,
                                                 bots[match_participants[0]],
                                                 bots[match_participants[1]])
                match = MatchExercise(
                    name=f'{match_participants[0]} vs {match_participants[1]}',
                    match_config=match_config,
                    grader=MatchGrader(replay_monitor=ReplayMonitor(
                        replay_preference=replay_preference), ))

                # Let overlay know which match we are about to start
                overlay_data = OverlayData(
                    div_index, bots[match_participants[0]].config_path,
                    bots[match_participants[1]].config_path)
                overlay_data.write(working_dir.overlay_interface)

                with setup_manager_context() as setup_manager:
                    # Disable rendering by replacing renderer with a renderer that does nothing
                    setup_manager.game_interface.renderer = FakeRenderer()

                    # For loop, but should only run exactly once
                    for exercise_result in run_playlist(
                        [match], setup_manager=setup_manager):

                        # Warn users if no replay was found
                        if isinstance(
                                exercise_result.grade, Fail
                        ) and exercise_result.exercise.grader.replay_monitor.replay_id == None:
                            print(
                                f'WARNING: No replay was found for the match \'{match_participants[0]} vs {match_participants[1]}\'. Is Bakkesmod injected and \'Automatically save all replays\' enabled?'
                            )

                        # Save result in file
                        result = exercise_result.exercise.grader.match_result
                        result.write(result_path)
                        print(
                            f'Match finished {result.blue_goals}-{result.orange_goals}. Saved result as {result_path}'
                        )

                        rr_results.append(result)

                        # Let the winner celebrate and the scoreboard show for a few seconds.
                        # This sleep not required.
                        time.sleep(8)

        print(f'{Ladder.DIVISION_NAMES[div_index]} division done')
        event_results.append(rr_results)

        # Find bots' overall score for the round robin
        overall_scores = [
            CombinedScore.calc_score(bot, rr_results) for bot in rr_bots
        ]
        sorted_overall_scores = sorted(overall_scores)[::-1]
        print(
            f'Bots\' overall performance in {Ladder.DIVISION_NAMES[div_index]} division:'
        )
        for score in sorted_overall_scores:
            print(
                f'> {score.bot}: goal_diff={score.goal_diff}, goals={score.goals}, shots={score.shots}, saves={score.saves}, points={score.points}'
            )

        # Rearrange bots in division on the new ladder
        first_bot_index = new_ladder.division_size * div_index
        bots_to_rearrange = len(rr_bots)
        for i in range(bots_to_rearrange):
            new_ladder.bots[first_bot_index + i] = sorted_overall_scores[i].bot

    # Save new ladder
    Ladder.write(new_ladder, working_dir.new_ladder)
    print(f'Done. Saved new ladder as {working_dir.new_ladder.name}')

    # Remove overlay interface file now that we are done
    if working_dir.overlay_interface.exists():
        working_dir.overlay_interface.unlink()

    return new_ladder
Пример #11
0
def run_match(
    ld: LeagueDir, match_details: MatchDetails,
    bots: Mapping[BotID, BotConfigBundle], replay_preference: ReplayPreference
) -> Tuple[MatchResult, Optional[ReplayData]]:
    """
    Run a match, wait for it to finish, and return the result.
    """

    settings = PersistentSettings.load()

    with setup_manager_context(settings.launcher()) as setup_manager:

        # Expose data to overlay
        make_overlay(ld, match_details, bots)

        # Prepare the match exercise
        print(
            f"Starting match: {match_details.blue} vs {match_details.orange}. Waiting for match to finish..."
        )
        match = MatchExercise(name=match_details.name,
                              match_config=match_details.to_config(bots),
                              grader=MatchGrader(replay_monitor=ReplayMonitor(
                                  replay_preference=replay_preference), ))

        # If any bots have signed up for early start, give them 10 seconds.
        # This is typically enough for Scratch.
        setup_manager.early_start_seconds = 10

        # For loop, but should only run exactly once
        with use_or_create(setup_manager,
                           setup_manager_context) as setup_manager:
            wrapped_exercises = [TrainingExerciseAdapter(match)]

            for rlbot_result in run_exercises(setup_manager,
                                              wrapped_exercises,
                                              4,
                                              reload_agent=False):
                exercise_result = ExerciseResult(
                    grade=rlbot_result.grade,
                    exercise=rlbot_result.exercise.
                    exercise,  # unwrap the TrainingExerciseAdapter.
                    reproduction_info=None)

                # Warn if no replay was found
                replay_data = exercise_result.exercise.grader.replay_monitor.replay_data(
                )
                if isinstance(exercise_result.grade,
                              Fail) and replay_data.replay_id is None:
                    print(
                        f"WARNING: No replay was found for the match '{match_details.name}'."
                    )
                else:
                    if replay_preference != ReplayPreference.NONE and replay_data.replay_path is not None:
                        try:
                            dst = ld.replays / f"{replay_data.replay_id}.replay"
                            shutil.copy(replay_data.replay_path, dst)
                            print(
                                "Replay successfully copied to replays directory"
                            )
                        except:
                            pass

                match_result = exercise_result.exercise.grader.match_result
                return match_result, replay_data