From a96d31ff5ffe0c5b58c52fa9c919935cfd790907 Mon Sep 17 00:00:00 2001 From: NicEastvillage Date: Mon, 3 Feb 2025 14:40:37 +0100 Subject: [PATCH 1/3] Add load_match_config and move config loading to config module --- rlbot/config.py | 218 ++++++++++++++++++++++++++++++++++++++++ rlbot/managers/match.py | 130 +----------------------- rlbot/utils/logging.py | 2 +- tests/read_toml.py | 9 +- tests/rlbot.toml | 24 ++--- tests/run_forever.py | 13 +-- tests/run_match.py | 6 +- tests/run_only.py | 6 +- tests/runner.py | 6 +- tests/testm/rlbot.toml | 61 +++++++++++ 10 files changed, 315 insertions(+), 160 deletions(-) create mode 100644 rlbot/config.py create mode 100644 tests/testm/rlbot.toml diff --git a/rlbot/config.py b/rlbot/config.py new file mode 100644 index 0000000..bd7af5d --- /dev/null +++ b/rlbot/config.py @@ -0,0 +1,218 @@ +import tomllib +from pathlib import Path +from typing import Any + +import rlbot.flat as flat +from rlbot.utils.logging import DEFAULT_LOGGER as logger +from rlbot.utils.os_detector import CURRENT_OS, OS + + +def __parse_enum(table: dict, key: str, enum: Any, default: int = 0) -> Any: + if key not in table: + return enum(0) + try: + for i in range(100000): + if str(enum(i)).split('.')[-1].lower() == table[key].lower(): + return enum(i) + except ValueError: + logger.warning(f"Unknown value '{table[key]}' for key '{key}' using default ({enum(default)})") + return enum(default) + + +def load_match_config(config_path: Path | str) -> flat.MatchConfiguration: + """ + Reads the match toml file at the provided path and creates the corresponding MatchConfiguration. + """ + config_path = Path(config_path) + with open(config_path, "rb") as f: + config = tomllib.load(f) + + rlbot_table = config.get("rlbot", dict()) + match_table = config.get("match", dict()) + mutator_table = config.get("mutators", dict()) + + players = [] + for car_table in config.get("cars", []): + car_config = car_table.get("config") + name = car_table.get("name", "") + team = car_table.get("team", 0) + try: + team = int(team) + except ValueError: + team = {"blue": 0, "orange": 1}.get(team.lower()) + if team is None or team not in [0, 1]: + logger.warning(f"Unknown team '{car_table.get("team")}' for player {len(players)}, using default team 0") + + loadout_file = car_table.get("loadout_file") + variant = car_table.get("type", "rlbot") + skill = __parse_enum(car_table, "skill", flat.PsyonixSkill) + match variant: + case "rlbot": + if car_config is None: + loadout = load_player_loadout(loadout_file, team) if loadout_file else None + players.append(flat.PlayerConfiguration(flat.CustomBot(), name, team, loadout=loadout)) + else: + abs_config_path = (config_path.parent / car_config).resolve() + players.append(load_player_config(abs_config_path, flat.CustomBot(), team, name, loadout_file)) + case "psyonix": + if car_config is None: + loadout = load_player_loadout(loadout_file, team) if loadout_file else None + players.append(flat.PlayerConfiguration(flat.Psyonix(skill), name, team, loadout=loadout)) + else: + abs_config_path = (config_path.parent / car_config).resolve() + players.append(load_player_config(abs_config_path, flat.Psyonix(skill), team, name, loadout_file)) + case "human": + loadout = load_player_loadout(loadout_file, team) if loadout_file else None + players.append(flat.PlayerConfiguration(flat.Human(), name, team, loadout=loadout)) + + scripts = [] + for script_table in config.get("scripts", []): + if script_config := script_table.get("config"): + abs_config_path = (config_path.parent / script_config).resolve() + scripts.append(load_script_config(abs_config_path)) + else: + scripts.append(flat.ScriptConfiguration()) + + mutators = flat.MutatorSettings( + match_length=__parse_enum(mutator_table, "match_length", flat.MatchLengthMutator), + max_score=__parse_enum(mutator_table, "max_score", flat.MaxScoreMutator), + multi_ball=__parse_enum(mutator_table, "multi_ball", flat.MultiBallMutator), + overtime=__parse_enum(mutator_table, "overtime", flat.OvertimeMutator), + series_length=__parse_enum(mutator_table, "series_length", flat.SeriesLengthMutator), + game_speed=__parse_enum(mutator_table, "game_speed", flat.GameSpeedMutator), + ball_max_speed=__parse_enum(mutator_table, "ball_max_speed", flat.BallMaxSpeedMutator), + ball_type=__parse_enum(mutator_table, "ball_type", flat.BallTypeMutator), + ball_weight=__parse_enum(mutator_table, "ball_weight", flat.BallWeightMutator), + ball_size=__parse_enum(mutator_table, "ball_size", flat.BallSizeMutator), + ball_bounciness=__parse_enum(mutator_table, "ball_bounciness", flat.BallBouncinessMutator), + boost=__parse_enum(mutator_table, "boost_amount", flat.BoostMutator), + rumble=__parse_enum(mutator_table, "rumble", flat.RumbleMutator), + boost_strength=__parse_enum(mutator_table, "boost_strength", flat.BoostStrengthMutator), + gravity=__parse_enum(mutator_table, "gravity", flat.GravityMutator), + demolish=__parse_enum(mutator_table, "demolish", flat.DemolishMutator), + respawn_time=__parse_enum(mutator_table, "respawn_time", flat.RespawnTimeMutator), + max_time=__parse_enum(mutator_table, "max_time", flat.MaxTimeMutator), + game_event=__parse_enum(mutator_table, "game_event", flat.GameEventMutator), + audio=__parse_enum(mutator_table, "audio", flat.AudioMutator), + ) + + return flat.MatchConfiguration( + launcher=__parse_enum(rlbot_table, "launcher", flat.Launcher), + launcher_arg=rlbot_table.get("launcher_arg", ""), + auto_start_bots=rlbot_table.get("auto_start_bots", True), + game_map_upk=match_table.get("game_map_upk", ""), + player_configurations=players, + script_configurations=scripts, + game_mode=__parse_enum(match_table, "game_mode", flat.GameMode), + skip_replays=match_table.get("skip_replays", False), + instant_start=match_table.get("instant_start", False), + mutators=mutators, + existing_match_behavior=__parse_enum(match_table, "existing_match_behavior", flat.ExistingMatchBehavior), + enable_rendering=match_table.get("enable_rendering", False), + enable_state_setting=match_table.get("enable_state_setting", False), + freeplay=match_table.get("freeplay", False), + ) + + +def load_player_loadout(path: Path | str, team: int) -> flat.PlayerLoadout: + """ + Reads the loadout toml file at the provided path and extracts the `PlayerLoadout` for the given team. + """ + with open(path, "rb") as f: + config = tomllib.load(f) + + loadout = config["blue_loadout"] if team == 0 else config["orange_loadout"] + paint = None + if paint_table := loadout.get("paint", None): + paint = flat.LoadoutPaint( + car_paint_id=paint_table.get("car_paint_id", 0), + decal_paint_id=paint_table.get("decal_paint_id", 0), + wheels_paint_id=paint_table.get("wheels_paint_id", 0), + boost_paint_id=paint_table.get("boost_paint_id", 0), + antenna_paint_id=paint_table.get("antenna_paint_id", 0), + hat_paint_id=paint_table.get("hat_paint_id", 0), + trails_paint_id=paint_table.get("trails_paint_id", 0), + goal_explosion_paint_id=paint_table.get("goal_explosion_paint_id", 0), + ) + + return flat.PlayerLoadout( + team_color_id=loadout.get("team_color_id", 0), + custom_color_id=loadout.get("custom_color_id", 0), + car_id=loadout.get("car_id", 0), + decal_id=loadout.get("decal_id", 0), + wheels_id=loadout.get("wheels_id", 0), + boost_id=loadout.get("boost_id", 0), + antenna_id=loadout.get("antenna_id", 0), + hat_id=loadout.get("hat_id", 0), + paint_finish_id=loadout.get("paint_finish_id", 0), + custom_finish_id=loadout.get("custom_finish_id", 0), + engine_audio_id=loadout.get("engine_audio_id", 0), + trails_id=loadout.get("trails_id", 0), + goal_explosion_id=loadout.get("goal_explosion_id", 0), + loadout_paint=paint, + ) + + +def load_player_config( + path: Path | str, type: flat.CustomBot | flat.Psyonix, team: int, + name_override: str | None = None, loadout_override: Path | str | None = None, +) -> flat.PlayerConfiguration: + """ + Reads the bot toml file at the provided path and + creates a `PlayerConfiguration` of the given type for the given team. + """ + path = Path(path) + with open(path, "rb") as f: + config = tomllib.load(f) + + settings: dict[str, Any] = config["settings"] + + root_dir = path.parent.absolute() + if "root_dir" in settings: + root_dir /= Path(settings["root_dir"]) + + run_command = settings.get("run_command", "") + if CURRENT_OS == OS.LINUX and "run_command_linux" in settings: + run_command = settings["run_command_linux"] + + loadout_path = path.parent / Path(settings["loadout_file"]) if "loadout_file" in settings else loadout_override + loadout = load_player_loadout(loadout_path, team) if loadout_path is not None else None + + return flat.PlayerConfiguration( + type, + settings.get("name", name_override or "Unnamed"), + team, + str(root_dir), + str(run_command), + loadout, + 0, + settings.get("agent_id", ""), + settings.get("hivemind", False), + ) + + +def load_script_config(path: Path | str) -> flat.ScriptConfiguration: + """ + Reads the script toml file at the provided path and creates a `ScriptConfiguration` from it. + """ + path = Path(path) + with open(path, "rb") as f: + config = tomllib.load(f) + + settings: dict[str, Any] = config["settings"] + + root_dir = path.parent + if "root_dir" in settings: + root_dir /= Path(settings["root_dir"]) + + run_command = settings.get("run_command", "") + if CURRENT_OS == OS.LINUX and "run_command_linux" in settings: + run_command = settings["run_command_linux"] + + return flat.ScriptConfiguration( + settings.get("name", "Unnamed"), + str(root_dir), + run_command, + 0, + settings.get("agent_id", ""), + ) diff --git a/rlbot/managers/match.py b/rlbot/managers/match.py index e0270c7..b6d2d9d 100644 --- a/rlbot/managers/match.py +++ b/rlbot/managers/match.py @@ -1,7 +1,6 @@ -import tomllib from pathlib import Path from time import sleep -from typing import Any, Optional +from typing import Optional import psutil @@ -9,132 +8,7 @@ from rlbot.interface import RLBOT_SERVER_IP, RLBOT_SERVER_PORT, SocketRelay from rlbot.utils import fill_desired_game_state, gateway from rlbot.utils.logging import DEFAULT_LOGGER -from rlbot.utils.os_detector import CURRENT_OS, MAIN_EXECUTABLE_NAME, OS - - -def extract_loadout_paint(config: dict[str, Any]) -> flat.LoadoutPaint: - """ - Extracts a `LoadoutPaint` structure from a dictionary. - """ - return flat.LoadoutPaint( - config.get("car_paint_id", 0), - config.get("decal_paint_id", 0), - config.get("wheels_paint_id", 0), - config.get("boost_paint_id", 0), - config.get("antenna_paint_id", 0), - config.get("hat_paint_id", 0), - config.get("trails_paint_id", 0), - config.get("goal_explosion_paint_id", 0), - ) - - -def get_player_loadout(path: str, team: int) -> flat.PlayerLoadout: - """ - Reads the loadout toml file at the provided path and extracts the `PlayerLoadout` for the given team. - """ - with open(path, "rb") as f: - config = tomllib.load(f) - - loadout = config["blue_loadout"] if team == 0 else config["orange_loadout"] - paint = loadout.get("paint", None) - - return flat.PlayerLoadout( - loadout.get("team_color_id", 0), - loadout.get("custom_color_id", 0), - loadout.get("car_id", 0), - loadout.get("decal_id", 0), - loadout.get("wheels_id", 0), - loadout.get("boost_id", 0), - loadout.get("antenna_id", 0), - loadout.get("hat_id", 0), - loadout.get("paint_finish_id", 0), - loadout.get("custom_finish_id", 0), - loadout.get("engine_audio_id", 0), - loadout.get("trails_id", 0), - loadout.get("goal_explosion_id", 0), - extract_loadout_paint(paint) if paint is not None else None, - ) - - -def get_player_config( - type: flat.CustomBot | flat.Psyonix, team: int, path: Path | str -) -> flat.PlayerConfiguration: - """ - Reads the bot toml file at the provided path and - creates a `PlayerConfiguration` of the given type for the given team. - """ - with open(path, "rb") as f: - config = tomllib.load(f) - - match path: - case Path(): - parent = path.parent - case _: - parent = Path(path).parent - - settings: dict[str, Any] = config["settings"] - - root_dir = parent - if "root_dir" in settings: - root_dir /= settings["root_dir"] - - run_command = settings.get("run_command", "") - if CURRENT_OS == OS.LINUX and "run_command_linux" in settings: - run_command = settings["run_command_linux"] - - loadout_path = settings.get("loadout_file", None) - if loadout_path is not None: - loadout_path = parent / loadout_path - - loadout = ( - get_player_loadout(loadout_path, team) - if loadout_path is not None and loadout_path.exists() - else None - ) - - return flat.PlayerConfiguration( - type, - settings["name"], - team, - str(root_dir), - str(run_command), - loadout, - 0, - settings.get("agent_id", ""), - settings.get("hivemind", False), - ) - - -def get_script_config(path: Path | str) -> flat.ScriptConfiguration: - """ - Reads the script toml file at the provided path and creates a `ScriptConfiguration` from it. - """ - with open(path, "rb") as f: - config = tomllib.load(f) - - match path: - case Path(): - parent = path.parent - case _: - parent = Path(path).parent - - settings: dict[str, Any] = config["settings"] - - root_dir = parent - if "root_dir" in settings: - root_dir /= settings["root_dir"] - - run_command = settings.get("run_command", "") - if CURRENT_OS == OS.LINUX and "run_command_linux" in settings: - run_command = settings["run_command_linux"] - - return flat.ScriptConfiguration( - settings["name"], - str(root_dir), - run_command, - 0, - settings.get("agent_id", ""), - ) +from rlbot.utils.os_detector import MAIN_EXECUTABLE_NAME class MatchManager: diff --git a/rlbot/utils/logging.py b/rlbot/utils/logging.py index df354c3..912afd1 100644 --- a/rlbot/utils/logging.py +++ b/rlbot/utils/logging.py @@ -2,7 +2,7 @@ import sys DEFAULT_LOGGER_NAME = "rlbot" -DEFAULT_LOGGER = None +DEFAULT_LOGGER = None # Set later LOGGING_LEVEL = logging.INFO logging.getLogger().setLevel(logging.NOTSET) diff --git a/tests/read_toml.py b/tests/read_toml.py index 4bd2b84..331d172 100644 --- a/tests/read_toml.py +++ b/tests/read_toml.py @@ -1,9 +1,10 @@ from pathlib import Path -from rlbot import flat -from rlbot.managers.match import get_player_config +from rlbot.config import load_match_config -CURRENT_FILE = Path(__file__).parent +DIR = Path(__file__).parent + +MATCH_CONFIG_PATH = DIR / "testm" / "rlbot.toml" if __name__ == "__main__": - print(get_player_config(flat.CustomBot(), 0, CURRENT_FILE / "necto/bot.toml")) + print(load_match_config(MATCH_CONFIG_PATH)) diff --git a/tests/rlbot.toml b/tests/rlbot.toml index f9ea210..adf021b 100644 --- a/tests/rlbot.toml +++ b/tests/rlbot.toml @@ -12,18 +12,6 @@ enable_rendering = true enable_state_setting = true auto_save_replay = false -[mutators] -match_length = "TwentyMinutes" -ball_max_speed = "Fast" -ball_type = "Puck" -ball_weight = "SuperLight" -ball_size = "Large" -ball_bounciness = "SuperHigh" -boost_amount = "UnlimitedBoost" -rumble = "SpikesOnly" -boost_strength = "OneAndAHalf" -respawn_time = "One_Second" - [[cars]] # The location of the configuration file for your agent here # The path is always relative to the folder that this file is in @@ -59,3 +47,15 @@ skill = "pro" [[cars]] type = "human" team = 1 + +[mutators] +match_length = "TwentyMinutes" +ball_max_speed = "Fast" +ball_type = "Puck" +ball_weight = "SuperLight" +ball_size = "Large" +ball_bounciness = "SuperHigh" +boost_amount = "UnlimitedBoost" +rumble = "SpikesOnly" +boost_strength = "OneAndAHalf" +respawn_time = "OneSecond" \ No newline at end of file diff --git a/tests/run_forever.py b/tests/run_forever.py index 45836bc..87dcbd2 100644 --- a/tests/run_forever.py +++ b/tests/run_forever.py @@ -2,13 +2,14 @@ from time import sleep from rlbot import flat -from rlbot.managers import MatchManager, get_player_config +from rlbot.config import load_player_config +from rlbot.managers import MatchManager from rlbot.utils.maps import GAME_MAP_TO_UPK, STANDARD_MAPS -THIS_DIR = Path(__file__).parent +DIR = Path(__file__).parent -BOT_PATH = THIS_DIR / "atba/atba.bot.toml" -RLBOT_SERVER_FOLDER = THIS_DIR / "../../core/RLBotCS/bin/Release/" +BOT_PATH = DIR / "atba/atba.bot.toml" +RLBOT_SERVER_FOLDER = DIR / "../../core/RLBotCS/bin/Release/" if __name__ == "__main__": match_manager = MatchManager(RLBOT_SERVER_FOLDER) @@ -16,8 +17,8 @@ current_map = -1 - blue_bot = get_player_config(flat.CustomBot(), 0, BOT_PATH) - orange_bot = get_player_config(flat.CustomBot(), 1, BOT_PATH) + blue_bot = load_player_config(BOT_PATH, flat.CustomBot(), 0) + orange_bot = load_player_config(BOT_PATH, flat.CustomBot(), 1) match_settings = flat.MatchConfiguration( launcher=flat.Launcher.Steam, diff --git a/tests/run_match.py b/tests/run_match.py index e1110c7..e353020 100644 --- a/tests/run_match.py +++ b/tests/run_match.py @@ -4,10 +4,10 @@ from rlbot import flat from rlbot.managers import MatchManager -CURRENT_FILE = Path(__file__).parent +DIR = Path(__file__).parent -MATCH_CONFIG_PATH = CURRENT_FILE / "render_test.toml" -RLBOT_SERVER_FOLDER = CURRENT_FILE / "../../core/RLBotCS/bin/Release/" +MATCH_CONFIG_PATH = DIR / "render_test.toml" +RLBOT_SERVER_FOLDER = DIR / "../../core/RLBotCS/bin/Release/" if __name__ == "__main__": match_manager = MatchManager(RLBOT_SERVER_FOLDER) diff --git a/tests/run_only.py b/tests/run_only.py index 3035f70..0bd7eb5 100644 --- a/tests/run_only.py +++ b/tests/run_only.py @@ -2,10 +2,10 @@ from rlbot.managers import MatchManager -CURRENT_FILE = Path(__file__).parent +DIR = Path(__file__).parent -MATCH_CONFIG_PATH = CURRENT_FILE / "human_vs_necto.toml" -RLBOT_SERVER_FOLDER = CURRENT_FILE / "../" +MATCH_CONFIG_PATH = DIR / "human_vs_necto.toml" +RLBOT_SERVER_FOLDER = DIR / "../" if __name__ == "__main__": # start the match diff --git a/tests/runner.py b/tests/runner.py index e974d65..d93d930 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -5,10 +5,10 @@ from rlbot.managers.match import MatchManager from rlbot.utils.logging import get_logger -CURRENT_FILE = Path(__file__).parent +DIR = Path(__file__).parent -MATCH_CONFIG_PATH = CURRENT_FILE / "human_vs_atba.toml" -RLBOT_SERVER_FOLDER = CURRENT_FILE / "../../core/RLBotCS/bin/Release/" +MATCH_CONFIG_PATH = DIR / "human_vs_atba.toml" +RLBOT_SERVER_FOLDER = DIR / "../../core/RLBotCS/bin/Release/" if __name__ == "__main__": logger = get_logger("runner") diff --git a/tests/testm/rlbot.toml b/tests/testm/rlbot.toml new file mode 100644 index 0000000..5a73db8 --- /dev/null +++ b/tests/testm/rlbot.toml @@ -0,0 +1,61 @@ +[rlbot] +launcher = "steam" +auto_start_bots = true + +[match] +game_mode = "Soccer" +game_map_upk = "Stadium_P" +skip_replays = false +start_without_countdown = false +existing_match_behavior = "Restart" +enable_rendering = true +enable_state_setting = true +auto_save_replay = false + +[[cars]] +# The location of the configuration file for your agent here +# The path is always relative to the folder that this file is in +config = "../atba/atba.bot.toml" +# Which team the player should be on: +# team 0 (blue) shoots on positive goal, team 1 (orange) shoots on negative goal +team = 0 +# Accepted values are "human", "rlbot", "psyonix" +# If no player is specified you will be spawned in as spectator! +# human - not controlled by the framework +# rlbot - controlled by the framework +# psyonix - default bots +type = "rlbot" + +[[cars]] +config = "../atba/atba.bot.toml" +team = 1 +# you don't have to specify type/skill for rlbots + +[[cars]] +config = "../necto/bot.toml" +team = 0 + +[[cars]] +# you don't need to specify a config for psyonix bots and humans +team = 0 +type = "psyonix" +# If participant is a bot and not RLBot controlled, this value will be used to set bot skill. +# possible values are "beginner", "rookie", "pro", and "allstar" +# default is "allstar" +skill = "pro" + +[[cars]] +type = "human" +team = 1 + +[mutators] +match_length = "TwentyMinutes" +ball_max_speed = "Fast" +ball_type = "Puck" +ball_weight = "SuperLight" +ball_size = "Large" +ball_bounciness = "SuperHigh" +boost_amount = "UnlimitedBoost" +rumble = "SpikesOnly" +boost_strength = "OneAndAHalf" +respawn_time = "OneSecond" \ No newline at end of file From 7d74aa8bddfe1bf31bc8a286580f65165ac426e8 Mon Sep 17 00:00:00 2001 From: NicEastvillage Date: Mon, 3 Feb 2025 14:58:33 +0100 Subject: [PATCH 2/3] Undo test setup and minor fixes --- tests/default.toml | 2 +- tests/read_toml.py | 2 +- tests/run_match.py | 1 - tests/testm/rlbot.toml | 61 ------------------------------------------ 4 files changed, 2 insertions(+), 64 deletions(-) delete mode 100644 tests/testm/rlbot.toml diff --git a/tests/default.toml b/tests/default.toml index 2536276..356f3f4 100644 --- a/tests/default.toml +++ b/tests/default.toml @@ -22,7 +22,7 @@ existing_match_behavior = "Restart" enable_rendering = false enable_state_setting = true auto_save_replay = false -# Whether or not to use freeplay instead of an exhibition match +# Whether to use freeplay instead of an exhibition match freeplay = false [mutators] diff --git a/tests/read_toml.py b/tests/read_toml.py index 331d172..89e7e73 100644 --- a/tests/read_toml.py +++ b/tests/read_toml.py @@ -4,7 +4,7 @@ DIR = Path(__file__).parent -MATCH_CONFIG_PATH = DIR / "testm" / "rlbot.toml" +MATCH_CONFIG_PATH = DIR / "rlbot.toml" if __name__ == "__main__": print(load_match_config(MATCH_CONFIG_PATH)) diff --git a/tests/run_match.py b/tests/run_match.py index e353020..085d6b6 100644 --- a/tests/run_match.py +++ b/tests/run_match.py @@ -12,7 +12,6 @@ if __name__ == "__main__": match_manager = MatchManager(RLBOT_SERVER_FOLDER) - match_manager.ensure_server_started() match_manager.start_match(MATCH_CONFIG_PATH) assert match_manager.packet is not None diff --git a/tests/testm/rlbot.toml b/tests/testm/rlbot.toml deleted file mode 100644 index 5a73db8..0000000 --- a/tests/testm/rlbot.toml +++ /dev/null @@ -1,61 +0,0 @@ -[rlbot] -launcher = "steam" -auto_start_bots = true - -[match] -game_mode = "Soccer" -game_map_upk = "Stadium_P" -skip_replays = false -start_without_countdown = false -existing_match_behavior = "Restart" -enable_rendering = true -enable_state_setting = true -auto_save_replay = false - -[[cars]] -# The location of the configuration file for your agent here -# The path is always relative to the folder that this file is in -config = "../atba/atba.bot.toml" -# Which team the player should be on: -# team 0 (blue) shoots on positive goal, team 1 (orange) shoots on negative goal -team = 0 -# Accepted values are "human", "rlbot", "psyonix" -# If no player is specified you will be spawned in as spectator! -# human - not controlled by the framework -# rlbot - controlled by the framework -# psyonix - default bots -type = "rlbot" - -[[cars]] -config = "../atba/atba.bot.toml" -team = 1 -# you don't have to specify type/skill for rlbots - -[[cars]] -config = "../necto/bot.toml" -team = 0 - -[[cars]] -# you don't need to specify a config for psyonix bots and humans -team = 0 -type = "psyonix" -# If participant is a bot and not RLBot controlled, this value will be used to set bot skill. -# possible values are "beginner", "rookie", "pro", and "allstar" -# default is "allstar" -skill = "pro" - -[[cars]] -type = "human" -team = 1 - -[mutators] -match_length = "TwentyMinutes" -ball_max_speed = "Fast" -ball_type = "Puck" -ball_weight = "SuperLight" -ball_size = "Large" -ball_bounciness = "SuperHigh" -boost_amount = "UnlimitedBoost" -rumble = "SpikesOnly" -boost_strength = "OneAndAHalf" -respawn_time = "OneSecond" \ No newline at end of file From fe54be93e0eda3b6815dd4d965e1685dbe37d1de Mon Sep 17 00:00:00 2001 From: NicEastvillage Date: Mon, 3 Feb 2025 21:40:34 +0100 Subject: [PATCH 3/3] Fix wrong PsyonixSkill default --- rlbot/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rlbot/config.py b/rlbot/config.py index bd7af5d..b767c8b 100644 --- a/rlbot/config.py +++ b/rlbot/config.py @@ -45,7 +45,7 @@ def load_match_config(config_path: Path | str) -> flat.MatchConfiguration: loadout_file = car_table.get("loadout_file") variant = car_table.get("type", "rlbot") - skill = __parse_enum(car_table, "skill", flat.PsyonixSkill) + skill = __parse_enum(car_table, "skill", flat.PsyonixSkill, int(flat.PsyonixSkill.AllStar)) match variant: case "rlbot": if car_config is None: