Compare commits

..

No commits in common. "dev" and "main" have entirely different histories.

6 changed files with 27 additions and 309 deletions

View file

@ -32,10 +32,8 @@ is saved after each edit or result, so you can stop and resume later.
The main menu also has a fully randomized one-off show (choose a game first) and The main menu also has a fully randomized one-off show (choose a game first) and
Season Mode. Seasons save separately under `seasons/` and book Raw → Thursday Season Mode. Seasons save separately under `seasons/` and book Raw → Thursday
Night SmackDown! → WWF PPV repeatedly. New season champions can be selected, Night SmackDown! → WWF PPV repeatedly. New season champions can be selected, randomized, or left
randomized, or left vacant. Built-in seasons ask which wrestlers are eligible vacant. Semi-random cards use division rankings and repeat-match rivalries;
for the Light-Heavyweight division; that selection is saved with the season.
Semi-random cards use division rankings and repeat-match rivalries;
title defenses are possible on any show and are weighted more heavily on PPVs. title defenses are possible on any show and are weighted more heavily on PPVs.
PPV cards may feature up to two title defenses, while weekly shows may feature PPV cards may feature up to two title defenses, while weekly shows may feature
one. Mark each season match with a ranking division, and separately mark title one. Mark each season match with a ranking division, and separately mark title
@ -71,8 +69,8 @@ federation, not just the built-in WWF games:
- **Create a new game and federation** — name the game, pick the federation and - **Create a new game and federation** — name the game, pick the federation and
platform (PlayStation 1, PlayStation 2, or other), name the federation's platform (PlayStation 1, PlayStation 2, or other), name the federation's
three shows, list the roster, edit the suggested match types, and add any three shows, list the roster, edit the suggested match types, and add any
championship/ranking divisions (singles, tag team, women's, or championship/ranking divisions (singles, tag team, or women's). A women's
Light-Heavyweight). Restricted divisions let you choose eligible wrestlers. division asks which roster members are eligible.
- **Copy a built-in WWF game to edit** — clones any built-in game into your own - **Copy a built-in WWF game to edit** — clones any built-in game into your own
editable profile; the built-in games themselves stay unchanged. editable profile; the built-in games themselves stay unchanged.
- **Edit a custom game** — reopen any saved profile. - **Edit a custom game** — reopen any saved profile.

View file

@ -41,10 +41,6 @@ def edit_custom_roster(config: dict[str, Any]) -> None:
removed = config["roster"].pop(index) removed = config["roster"].pop(index)
config["women_roster"] = [name for name in config["women_roster"] config["women_roster"] = [name for name in config["women_roster"]
if name.casefold() != removed.casefold()] if name.casefold() != removed.casefold()]
config["light_heavyweight_roster"] = [
name for name in config.get("light_heavyweight_roster", [])
if name.casefold() != removed.casefold()
]
def edit_custom_match_types(config: dict[str, Any]) -> None: def edit_custom_match_types(config: dict[str, Any]) -> None:
@ -121,24 +117,19 @@ def edit_custom_titles(config: dict[str, Any]) -> None:
if not name or any(item["name"].casefold() == name.casefold() for item in existing): if not name or any(item["name"].casefold() == name.casefold() for item in existing):
print("Enter a non-empty championship name not already listed.") print("Enter a non-empty championship name not already listed.")
continue continue
kind_options = ["singles", "tag", "women", "light_heavyweight"] kind_options = ["singles", "tag", "women"]
kind_labels = ["Singles / open", "Tag team", "Women's division", kind_labels = ["Singles / open", "Tag team", "Women's division"]
"Light-Heavyweight division"]
kind = kind_options[app.ask_choice("Championship type", kind_options, labels=kind_labels)] kind = kind_options[app.ask_choice("Championship type", kind_options, labels=kind_labels)]
existing.append({"name": name, "kind": kind}) existing.append({"name": name, "kind": kind})
def edit_eligible_roster(config: dict[str, Any], field: str, division: str, def edit_women_roster(config: dict[str, Any]) -> None:
require_eligible: bool = False) -> None:
eligible = config.setdefault(field, [])
while True: while True:
choices = ["add", "remove", "done"] choices = ["add", "remove", "done"]
labels = ["Add eligible wrestler", "Remove eligible wrestler", "Done"] labels = ["Add eligible wrestler", "Remove eligible wrestler", "Done"]
action = app.ask_choice(f"{division} eligibility", choices, labels=labels) action = app.ask_choice("Women's division eligibility", choices, labels=labels)
eligible = config["women_roster"]
if action == 2: if action == 2:
if require_eligible and not eligible:
print(f"Choose at least one eligible wrestler for the {division} division.")
continue
return return
if action == 0: if action == 0:
available = [name for name in config["roster"] available = [name for name in config["roster"]
@ -155,16 +146,6 @@ def edit_eligible_roster(config: dict[str, Any], field: str, division: str,
eligible.pop(remove_index) eligible.pop(remove_index)
def edit_women_roster(config: dict[str, Any]) -> None:
edit_eligible_roster(config, "women_roster", "Women's division")
def edit_light_heavyweight_roster(config: dict[str, Any]) -> None:
edit_eligible_roster(
config, "light_heavyweight_roster", "Light-Heavyweight", require_eligible=True
)
def edit_custom_shows(config: dict[str, Any]) -> None: def edit_custom_shows(config: dict[str, Any]) -> None:
while True: while True:
shows = config["shows"] shows = config["shows"]
@ -188,24 +169,13 @@ def edit_custom_shows(config: dict[str, Any]) -> None:
def edit_custom_profile(config: dict[str, Any]) -> dict[str, Any]: def edit_custom_profile(config: dict[str, Any]) -> dict[str, Any]:
while True: while True:
options = ["identity", "shows", "roster", "match_types", "titles", "women"] options = ["identity", "shows", "roster", "match_types", "titles", "women", "save"]
labels = ["Game/federation, platform, screenshot directory", labels = ["Game/federation, platform, screenshot directory",
f"Show names (Raw: {config['shows']['Raw']})", f"Show names (Raw: {config['shows']['Raw']})",
f"Edit roster ({len(config['roster'])} wrestlers)", f"Edit roster ({len(config['roster'])} wrestlers)",
f"Edit match types ({len(config['match_types'])})", f"Edit match types ({len(config['match_types'])})",
f"Edit championships ({len(config['championships'])})", f"Edit championships ({len(config['championships'])})",
f"Edit Women's eligibility ({len(config['women_roster'])})"] f"Edit Women's eligibility ({len(config['women_roster'])})", "Validate and save"]
has_light_heavyweight = any(
title.get("kind") == "light_heavyweight" for title in config["championships"]
)
if has_light_heavyweight:
options.append("light_heavyweight")
labels.append(
f"Edit Light-Heavyweight eligibility "
f"({len(config.get('light_heavyweight_roster', []))})"
)
options.append("save")
labels.append("Validate and save")
action = app.ask_choice("BYOG editor", options, labels=labels) action = app.ask_choice("BYOG editor", options, labels=labels)
if action == 0: if action == 0:
config["game_title"] = app.ask("Game title", config["game_title"]).strip() config["game_title"] = app.ask("Game title", config["game_title"]).strip()
@ -231,12 +201,7 @@ def edit_custom_profile(config: dict[str, Any]) -> dict[str, Any]:
app.edit_custom_titles(config) app.edit_custom_titles(config)
elif action == 5: elif action == 5:
app.edit_women_roster(config) app.edit_women_roster(config)
elif has_light_heavyweight and action == 6:
app.edit_light_heavyweight_roster(config)
else: else:
if has_light_heavyweight and not config.get("light_heavyweight_roster"):
print("Choose eligible Light-Heavyweight wrestlers before saving this profile.")
continue
try: try:
return app.save_custom_game(config) return app.save_custom_game(config)
except ValueError as exc: except ValueError as exc:
@ -260,7 +225,6 @@ def builtin_profile_for_copy(game_id: str, custom_id: str) -> dict[str, Any]:
"match_types": definitions, "match_types": definitions,
"championships": app.title_definitions_for_game(game_id), "championships": app.title_definitions_for_game(game_id),
"women_roster": sorted(app.WOMEN_ROSTERS.get(game_id, set())), "women_roster": sorted(app.WOMEN_ROSTERS.get(game_id, set())),
"light_heavyweight_roster": app.load_roster(game_id),
"shows": {"Raw": "Monday Night Raw", "SmackDown": "Thursday Night SmackDown!", "shows": {"Raw": "Monday Night Raw", "SmackDown": "Thursday Night SmackDown!",
"PPV": "WWF PPV"}, "PPV": "WWF PPV"},
}) })
@ -297,7 +261,6 @@ def create_custom_game() -> dict[str, Any]:
"match_types": [], "match_types": [],
"championships": [], "championships": [],
"women_roster": [], "women_roster": [],
"light_heavyweight_roster": [],
"shows": shows, "shows": shows,
} }
app.edit_custom_roster(config) app.edit_custom_roster(config)
@ -310,8 +273,6 @@ def create_custom_game() -> dict[str, Any]:
app.edit_custom_titles(config) app.edit_custom_titles(config)
if any(title["kind"] == "women" for title in config["championships"]): if any(title["kind"] == "women" for title in config["championships"]):
app.edit_women_roster(config) app.edit_women_roster(config)
if any(title["kind"] == "light_heavyweight" for title in config["championships"]):
app.edit_light_heavyweight_roster(config)
return app.edit_custom_profile(config) return app.edit_custom_profile(config)
@ -329,9 +290,6 @@ def clone_builtin_game() -> dict[str, Any]:
config = app.builtin_profile_for_copy(source_id, app.new_custom_game_id(federation, title)) config = app.builtin_profile_for_copy(source_id, app.new_custom_game_id(federation, title))
config["game_title"] = title or config["game_title"] config["game_title"] = title or config["game_title"]
config["federation_name"] = federation or config["federation_name"] config["federation_name"] = federation or config["federation_name"]
if any(item["kind"] == "light_heavyweight" for item in config["championships"]):
config["light_heavyweight_roster"] = []
app.edit_light_heavyweight_roster(config)
print(f"Copied {app.game_title(source_id)} into the editable BYOG directory.") print(f"Copied {app.game_title(source_id)} into the editable BYOG directory.")
return app.edit_custom_profile(config) return app.edit_custom_profile(config)
@ -368,4 +326,4 @@ def manage_games() -> None:
else: else:
return return
__all__ = ['builtin_profile_for_copy', 'choose_builtin_game', 'clone_builtin_game', 'create_custom_game', 'edit_custom_match_types', 'edit_custom_profile', 'edit_custom_roster', 'edit_custom_shows', 'edit_custom_titles', 'edit_eligible_roster', 'edit_existing_custom_game', 'edit_light_heavyweight_roster', 'edit_women_roster', 'manage_games', 'show_roster'] __all__ = ['builtin_profile_for_copy', 'choose_builtin_game', 'clone_builtin_game', 'create_custom_game', 'edit_custom_match_types', 'edit_custom_profile', 'edit_custom_roster', 'edit_custom_shows', 'edit_custom_titles', 'edit_existing_custom_game', 'edit_women_roster', 'manage_games', 'show_roster']

View file

@ -61,15 +61,7 @@ def title_definitions_for_game(game_id: str,
if game_id in app.CUSTOM_GAME_CONFIGS: if game_id in app.CUSTOM_GAME_CONFIGS:
return [dict(title) for title in app.CUSTOM_GAME_CONFIGS[game_id]["championships"]] return [dict(title) for title in app.CUSTOM_GAME_CONFIGS[game_id]["championships"]]
return [ return [
{ {"name": name, "kind": "tag" if name == "Tag Team" else "women" if name == "Women's" else "singles"}
"name": name,
"kind": (
"tag" if name == "Tag Team"
else "women" if name == "Women's"
else "light_heavyweight" if name == "Light-Heavyweight"
else "singles"
),
}
for name in app.CHAMPIONSHIPS for name in app.CHAMPIONSHIPS
] ]
@ -251,27 +243,16 @@ def validate_custom_game(data: Any) -> dict[str, Any]:
for item in raw_titles: for item in raw_titles:
if not isinstance(item, dict): if not isinstance(item, dict):
raise ValueError("Each championship must be a JSON object with name and kind.") raise ValueError("Each championship must be a JSON object with name and kind.")
name = item.get("name") name, kind = item.get("name"), str(item.get("kind", "singles")).casefold()
if not isinstance(name, str) or not name.strip() or name.casefold() in seen_titles: if not isinstance(name, str) or not name.strip() or name.casefold() in seen_titles:
raise ValueError("Championship names must be non-empty and unique.") raise ValueError("Championship names must be non-empty and unique.")
default_kind = "light_heavyweight" if name.casefold() == "light-heavyweight" else "singles" if kind not in {"singles", "tag", "women"}:
kind = str(item.get("kind", default_kind)).casefold() raise ValueError(f"Championship '{name}' kind must be singles, tag, or women.")
if kind not in {"singles", "tag", "women", "light_heavyweight"}:
raise ValueError(
f"Championship '{name}' kind must be singles, tag, women, or light_heavyweight."
)
championships.append({"name": name.strip(), "kind": kind}) championships.append({"name": name.strip(), "kind": kind})
seen_titles.add(name.casefold()) seen_titles.add(name.casefold())
women = data.get("women_roster", []) women = data.get("women_roster", [])
if not isinstance(women, list) or any(name not in roster for name in women): if not isinstance(women, list) or any(name not in roster for name in women):
raise ValueError("women_roster must be a subset of the roster.") raise ValueError("women_roster must be a subset of the roster.")
light_heavyweight = data.get("light_heavyweight_roster", [])
if (not isinstance(light_heavyweight, list)
or any(name not in roster for name in light_heavyweight)):
raise ValueError("light_heavyweight_roster must be a subset of the roster.")
if (any(title["kind"] == "light_heavyweight" for title in championships)
and not light_heavyweight):
raise ValueError("light_heavyweight_roster must contain eligible wrestlers.")
raw_shows = data.get("shows") raw_shows = data.get("shows")
if raw_shows is not None and not isinstance(raw_shows, dict): if raw_shows is not None and not isinstance(raw_shows, dict):
raise ValueError("shows must be an object with Raw, SmackDown, and PPV names.") raise ValueError("shows must be an object with Raw, SmackDown, and PPV names.")
@ -297,7 +278,6 @@ def validate_custom_game(data: Any) -> dict[str, Any]:
"match_types": match_types, "match_types": match_types,
"championships": championships, "championships": championships,
"women_roster": list(dict.fromkeys(women)), "women_roster": list(dict.fromkeys(women)),
"light_heavyweight_roster": list(dict.fromkeys(light_heavyweight)),
"shows": shows, "shows": shows,
} }
@ -326,7 +306,6 @@ def builtin_game_profile(game_id: str) -> dict[str, Any]:
"match_types": app.match_type_definitions(game_id), "match_types": app.match_type_definitions(game_id),
"championships": app.title_definitions_for_game(game_id), "championships": app.title_definitions_for_game(game_id),
"women_roster": sorted(app.WOMEN_ROSTERS.get(game_id, set())), "women_roster": sorted(app.WOMEN_ROSTERS.get(game_id, set())),
"light_heavyweight_roster": None,
"shows": {"Raw": "Monday Night Raw", "SmackDown": "Thursday Night SmackDown!", "shows": {"Raw": "Monday Night Raw", "SmackDown": "Thursday Night SmackDown!",
"PPV": "WWF PPV"}, "PPV": "WWF PPV"},
} }

View file

@ -141,14 +141,7 @@ def record_match_result(card: dict[str, Any], index: int, auto_simulate: bool =
if not is_player_match and not auto_simulate: if not is_player_match and not auto_simulate:
print(f"Only {wrestler}'s matches can be recorded manually in Wrestler control.") print(f"Only {wrestler}'s matches can be recorded manually in Wrestler control.")
return False return False
if season: if match.get("title_defense") and season and not app.validate_title_defense(season, match):
valid_division = (
app.validate_title_defense(season, match)
if match.get("title_defense")
else app.validate_match_division_eligibility(season, match)
)
if not valid_division:
if match.get("title_defense"):
print("Edit this match's participants or title status before recording its result.") print("Edit this match's participants or title status before recording its result.")
return False return False

View file

@ -13,10 +13,9 @@ def season_path(season_id: str) -> Path:
def new_season_state(name: str, game_id: str, def new_season_state(name: str, game_id: str,
champions: dict[str, list[str] | None] | None = None, champions: dict[str, list[str] | None] | None = None,
season_id: str | None = None, season_id: str | None = None) -> dict[str, Any]:
profile: dict[str, Any] | None = None) -> dict[str, Any]:
champions = champions or {} champions = champions or {}
profile = profile or app.game_profile(game_id) profile = app.game_profile(game_id)
title_definitions = [dict(item) for item in profile["championships"]] title_definitions = [dict(item) for item in profile["championships"]]
title_state: dict[str, Any] = {} title_state: dict[str, Any] = {}
for definition in title_definitions: for definition in title_definitions:
@ -70,14 +69,6 @@ def load_season(path_or_id: Path | str) -> dict[str, Any]:
if not payload.get("season_id") or not payload.get("name"): if not payload.get("season_id") or not payload.get("name"):
raise ValueError(f"Season save is missing its identity: {path}") raise ValueError(f"Season save is missing its identity: {path}")
payload.setdefault("game_config", app.game_profile(payload["game_id"])) payload.setdefault("game_config", app.game_profile(payload["game_id"]))
if payload["game_id"] in app.BUILTIN_GAME_IDS:
for definitions in (payload.get("title_definitions"),
payload["game_config"].get("championships")):
if isinstance(definitions, list):
for definition in definitions:
if (definition.get("name") == "Light-Heavyweight"
and definition.get("kind") == "singles"):
definition["kind"] = "light_heavyweight"
payload.setdefault("game_title", payload["game_config"].get("game_title", app.game_title(payload["game_id"]))) payload.setdefault("game_title", payload["game_config"].get("game_title", app.game_title(payload["game_id"])))
payload.setdefault("federation_name", payload["game_config"].get( payload.setdefault("federation_name", payload["game_config"].get(
"federation_name", app.federation_name(payload["game_id"]) "federation_name", app.federation_name(payload["game_id"])
@ -183,45 +174,13 @@ def eligible_roster_for_division(game_id: str, division: str,
profile: dict[str, Any] | None = None) -> list[str]: profile: dict[str, Any] | None = None) -> list[str]:
profile = profile or app.game_profile(game_id) profile = profile or app.game_profile(game_id)
roster = list(profile.get("roster", [])) if roster is None else roster roster = list(profile.get("roster", [])) if roster is None else roster
eligibility_field = { if app.championship_kind(game_id, division, profile) == "women":
"women": "women_roster", eligible_names = profile.get("women_roster", [])
"light_heavyweight": "light_heavyweight_roster",
}.get(app.championship_kind(game_id, division, profile))
if eligibility_field:
eligible_names = profile.get(eligibility_field)
# Older seasons do not have a Light-Heavyweight eligibility snapshot.
if eligible_names is None:
return list(roster)
eligible = {name.casefold() for name in eligible_names} eligible = {name.casefold() for name in eligible_names}
return [name for name in roster if name.casefold() in eligible] return [name for name in roster if name.casefold() in eligible]
return list(roster) return list(roster)
def validate_match_division_eligibility(season: dict[str, Any],
match: dict[str, Any]) -> bool:
division = match.get("ranking_division")
if division not in app.season_title_names(season):
return True
if app.season_championship_kind(season, division) not in {"women", "light_heavyweight"}:
return True
profile = app.season_game_profile(season)
eligible = {
name.casefold()
for name in app.eligible_roster_for_division(
season["game_id"], division, profile=profile
)
}
excluded = [
name for side in match.get("sides", []) for name in side
if name.casefold() not in eligible
]
if excluded:
names = ", ".join(dict.fromkeys(excluded))
print(f"{names} is not eligible for the {division} division.")
return False
return True
def choose_roster_member(names: list[str], prompt: str) -> str: def choose_roster_member(names: list[str], prompt: str) -> str:
if not names: if not names:
raise ValueError("No eligible wrestlers are available for that championship.") raise ValueError("No eligible wrestlers are available for that championship.")
@ -258,13 +217,6 @@ def create_season() -> dict[str, Any]:
game_id = app.choose_game() game_id = app.choose_game()
profile = app.game_profile(game_id) profile = app.game_profile(game_id)
name = app.ask("Season name", f"{app.game_display_name(game_id)} Season") name = app.ask("Season name", f"{app.game_display_name(game_id)} Season")
has_light_heavyweight = any(
definition.get("kind") == "light_heavyweight"
for definition in profile["championships"]
)
if has_light_heavyweight and game_id in app.BUILTIN_GAME_IDS:
profile["light_heavyweight_roster"] = []
app.edit_light_heavyweight_roster(profile)
champions: dict[str, list[str] | None] = {} champions: dict[str, list[str] | None] = {}
used: set[str] = set() used: set[str] = set()
for definition in profile["championships"]: for definition in profile["championships"]:
@ -273,7 +225,7 @@ def create_season() -> dict[str, Any]:
champions[division] = holder champions[division] = holder
if holder: if holder:
used.update(name.casefold() for name in holder) used.update(name.casefold() for name in holder)
season = app.new_season_state(name, game_id, champions, profile=profile) season = app.new_season_state(name, game_id, champions)
app.save_season(season) app.save_season(season)
print(f"Season saved: {app.season_path(season['season_id'])}") print(f"Season saved: {app.season_path(season['season_id'])}")
return season return season
@ -350,9 +302,7 @@ def season_rivalry_id(sides: list[list[str]]) -> str | None:
def record_season_match(season: dict[str, Any], card: dict[str, Any], def record_season_match(season: dict[str, Any], card: dict[str, Any],
match: dict[str, Any], match_index: int) -> bool: match: dict[str, Any], match_index: int) -> None:
if not app.validate_match_division_eligibility(season, match):
return False
division = match.get("ranking_division") division = match.get("ranking_division")
winner = match.get("winner_side") winner = match.get("winner_side")
if division in app.season_title_names(season) and winner is not None: if division in app.season_title_names(season) and winner is not None:
@ -401,7 +351,6 @@ def record_season_match(season: dict[str, Any], card: dict[str, Any],
if match.get("rivalry_payoff"): if match.get("rivalry_payoff"):
rivalry["resolved"] = True rivalry["resolved"] = True
rivalry["resolved_at"] = card.get("season_show", "") rivalry["resolved_at"] = card.get("season_show", "")
return True
def validate_title_defense(season: dict[str, Any], match: dict[str, Any]) -> bool: def validate_title_defense(season: dict[str, Any], match: dict[str, Any]) -> bool:
@ -411,8 +360,6 @@ def validate_title_defense(season: dict[str, Any], match: dict[str, Any]) -> boo
if division not in app.season_title_names(season): if division not in app.season_title_names(season):
print("A title defense must be assigned to a championship division.") print("A title defense must be assigned to a championship division.")
return False return False
if not app.validate_match_division_eligibility(season, match):
return False
holder = season["champions"][division].get("holder") holder = season["champions"][division].get("holder")
if holder and not any(app.side_identity(side) == app.side_identity(holder) if holder and not any(app.side_identity(side) == app.side_identity(holder)
for side in match.get("sides", [])): for side in match.get("sides", [])):
@ -437,12 +384,9 @@ def sync_season_card_results(card: dict[str, Any]) -> None:
result_id = f"{season_id}:{card.get('season_show_number', 0)}:{index + 1}" result_id = f"{season_id}:{card.get('season_show_number', 0)}:{index + 1}"
if result_id in processed: if result_id in processed:
continue continue
if not app.validate_match_division_eligibility(season, match):
continue
if match.get("title_defense") and not app.validate_title_defense(season, match): if match.get("title_defense") and not app.validate_title_defense(season, match):
continue continue
if not app.record_season_match(season, card, match, index): app.record_season_match(season, card, match, index)
continue
processed.add(result_id) processed.add(result_id)
season["processed_results"] = sorted(processed) season["processed_results"] = sorted(processed)
complete = all(match.get("winner_side") is not None for match in card["matches"]) complete = all(match.get("winner_side") is not None for match in card["matches"])
@ -455,4 +399,4 @@ def sync_season_card_results(card: dict[str, Any]) -> None:
season["show_history"].append(card["path"]) season["show_history"].append(card["path"])
app.save_season(season) app.save_season(season)
__all__ = ['choose_initial_champion', 'choose_roster_member', 'choose_season_control_mode', 'create_season', 'eligible_roster_for_division', 'load_season', 'new_season_state', 'print_power_rankings', 'record_season_match', 'save_season', 'season_control_label', 'season_other_pool', 'season_path', 'season_ranking_entries', 'season_rivalry_id', 'season_show_brand', 'side_display', 'side_identity', 'sync_season_card_results', 'toggle_season_control_mode', 'validate_match_division_eligibility', 'validate_title_defense'] __all__ = ['choose_initial_champion', 'choose_roster_member', 'choose_season_control_mode', 'create_season', 'eligible_roster_for_division', 'load_season', 'new_season_state', 'print_power_rankings', 'record_season_match', 'save_season', 'season_control_label', 'season_other_pool', 'season_path', 'season_ranking_entries', 'season_rivalry_id', 'season_show_brand', 'side_display', 'side_identity', 'sync_season_card_results', 'toggle_season_control_mode', 'validate_title_defense']

View file

@ -916,126 +916,6 @@ class SeasonControlTests(unittest.TestCase):
self.assertEqual(updated["next_show_number"], 2) self.assertEqual(updated["next_show_number"], 2)
class LightHeavyweightTests(unittest.TestCase):
def test_builtin_season_selects_and_snapshots_eligible_wrestlers(self):
def select_eligible(profile):
profile["light_heavyweight_roster"] = ["X-Pac", "Jeff Hardy"]
def initial_champion(division, _game_id, _used, _profile):
return ["X-Pac"] if division == "Light-Heavyweight" else None
with tempfile.TemporaryDirectory() as folder, \
patch.object(app, "SEASON_DIR", Path(folder)), \
patch.object(app, "choose_game", return_value="sd1"), \
patch.object(app, "ask", return_value="Lightweight Season"), \
patch.object(app, "edit_light_heavyweight_roster", side_effect=select_eligible), \
patch.object(app, "choose_initial_champion", side_effect=initial_champion), \
contextlib.redirect_stdout(io.StringIO()):
season = app.create_season()
loaded = app.load_season(season["season_id"])
self.assertEqual(season["game_config"]["light_heavyweight_roster"],
["X-Pac", "Jeff Hardy"])
self.assertEqual(
app.eligible_roster_for_division(
"sd1", "Light-Heavyweight", profile=loaded["game_config"]
),
["X-Pac", "Jeff Hardy"],
)
self.assertEqual(loaded["champions"]["Light-Heavyweight"]["holder"], ["X-Pac"])
defense = {
"ranking_division": "Light-Heavyweight", "title_defense": True,
"sides": [["X-Pac"], ["Jeff Hardy"]], "winner_side": 1,
}
self.assertTrue(app.validate_title_defense(loaded, defense))
app.record_season_match(loaded, {"season_show": "Raw"}, defense, 0)
self.assertEqual(loaded["champions"]["Light-Heavyweight"]["holder"], ["Jeff Hardy"])
def test_initial_champion_random_choice_uses_only_eligible_wrestlers(self):
profile = app.game_profile("sd1")
profile["light_heavyweight_roster"] = ["X-Pac"]
choices_seen = []
def first_choice(options):
choices_seen.append(list(options))
return options[0]
with patch.object(app, "ask_choice", return_value=1), \
patch.object(app.random, "choice", side_effect=first_choice), \
contextlib.redirect_stdout(io.StringIO()):
champion = app.choose_initial_champion(
"Light-Heavyweight", "sd1", set(), profile
)
self.assertEqual(champion, ["X-Pac"])
self.assertEqual(choices_seen, [["X-Pac"]])
def test_ineligible_wrestlers_cannot_record_or_sync_division_results(self):
with tempfile.TemporaryDirectory() as folder, \
patch.object(app, "SEASON_DIR", Path(folder)):
season = app.new_season_state(
"Lightweight Season", "sd1",
champions={"Light-Heavyweight": ["X-Pac"]},
season_id="lightweight-results",
)
season["game_config"]["light_heavyweight_roster"] = ["X-Pac"]
card_path = Path(folder) / "card.md"
season["current_card"] = str(card_path)
app.save_season(season)
match = {
"type": "Singles", "sides": [["X-Pac"], ["The Rock"]],
"winner_side": 1, "ranking_division": "Light-Heavyweight",
"title_defense": True,
}
card = {
"season_id": season["season_id"], "season_show_number": 1,
"season_show": "Raw", "path": str(card_path),
"matches": [match],
}
with contextlib.redirect_stdout(io.StringIO()):
self.assertFalse(app.validate_title_defense(season, match))
self.assertFalse(app.record_match_result(card, 0, auto_simulate=True))
app.sync_season_card_results(card)
updated = app.load_season(season["season_id"])
self.assertEqual(updated["champions"]["Light-Heavyweight"]["holder"], ["X-Pac"])
self.assertEqual(updated["rankings"]["Light-Heavyweight"], {})
self.assertEqual(updated["processed_results"], [])
def test_legacy_season_without_eligibility_snapshot_remains_unrestricted(self):
season = app.new_season_state("Legacy Season", "sd1", season_id="legacy-lightweight")
season["game_config"].pop("light_heavyweight_roster", None)
self.assertEqual(
app.eligible_roster_for_division(
"sd1", "Light-Heavyweight", profile=season["game_config"]
),
season["game_config"]["roster"],
)
def test_legacy_builtin_light_heavyweight_kind_migrates_without_restricting_roster(self):
season = app.new_season_state(
"Legacy Lightweight", "sd1", season_id="legacy-lightweight-kind"
)
for definitions in (season["title_definitions"],
season["game_config"]["championships"]):
next(item for item in definitions if item["name"] == "Light-Heavyweight")["kind"] = "singles"
season["game_config"].pop("light_heavyweight_roster", None)
with tempfile.TemporaryDirectory() as folder, \
patch.object(app, "SEASON_DIR", Path(folder)):
app.save_season(season)
loaded = app.load_season(season["season_id"])
self.assertEqual(
app.season_championship_kind(loaded, "Light-Heavyweight"),
"light_heavyweight",
)
self.assertEqual(
app.eligible_roster_for_division(
"sd1", "Light-Heavyweight", profile=loaded["game_config"]
),
loaded["game_config"]["roster"],
)
class BYOGTests(unittest.TestCase): class BYOGTests(unittest.TestCase):
def setUp(self): def setUp(self):
self._configs = app.CUSTOM_GAME_CONFIGS self._configs = app.CUSTOM_GAME_CONFIGS
@ -1074,7 +954,6 @@ class BYOGTests(unittest.TestCase):
{"name": "Fantasy Women", "kind": "women"}, {"name": "Fantasy Women", "kind": "women"},
], ],
"women_roster": ["Cara Storm"], "women_roster": ["Cara Storm"],
"light_heavyweight_roster": [],
} }
data.update(overrides) data.update(overrides)
return data return data
@ -1128,7 +1007,6 @@ class BYOGTests(unittest.TestCase):
"invalid side sizes"), "invalid side sizes"),
({"match_types": []}, "at least one match type"), ({"match_types": []}, "at least one match type"),
({"championships": [{"name": "Belt", "kind": "hardcore"}]}, "kind"), ({"championships": [{"name": "Belt", "kind": "hardcore"}]}, "kind"),
({"light_heavyweight_roster": ["Not Listed"]}, "subset of the roster"),
({"platform": "dreamcast"}, "platform must be ps1"), ({"platform": "dreamcast"}, "platform must be ps1"),
({"screenshot_directory": 3}, "screenshot_directory must be a path string"), ({"screenshot_directory": 3}, "screenshot_directory must be a path string"),
] ]
@ -1175,38 +1053,6 @@ class BYOGTests(unittest.TestCase):
app.ROOT / "custom-screens") app.ROOT / "custom-screens")
self.assertTrue(app.game_has_screenshots(overridden["game_id"])) self.assertTrue(app.game_has_screenshots(overridden["game_id"]))
def test_custom_light_heavyweight_eligibility_is_validated_and_applied(self):
config = self.config(
championships=[
{"name": "Fantasy Lightweight", "kind": "light_heavyweight"},
],
light_heavyweight_roster=["Ava Crusher", "Cara Storm"],
)
self.register(config)
profile = app.game_profile(config["game_id"])
self.assertEqual(
app.eligible_roster_for_division(
config["game_id"], "Fantasy Lightweight", profile=profile
),
["Ava Crusher", "Cara Storm"],
)
self.assertEqual(
app.championship_kind(config["game_id"], "Fantasy Lightweight", profile),
"light_heavyweight",
)
with self.assertRaisesRegex(ValueError, "must contain eligible wrestlers"):
app.validate_custom_game(self.config(championships=[
{"name": "Fantasy Lightweight", "kind": "light_heavyweight"},
]))
def test_light_heavyweight_eligibility_editor_selects_roster_members(self):
config = {"roster": ["Ava Crusher", "Ben Brawler"],
"light_heavyweight_roster": []}
with patch.object(app, "ask_choice", side_effect=[0, 0, 2]), \
contextlib.redirect_stdout(io.StringIO()):
app.edit_light_heavyweight_roster(config)
self.assertEqual(config["light_heavyweight_roster"], ["Ava Crusher"])
def test_custom_game_screenshot_override_can_be_set_in_editor(self): def test_custom_game_screenshot_override_can_be_set_in_editor(self):
config = app.validate_custom_game(self.config()) config = app.validate_custom_game(self.config())
with patch.object(app, "ask_choice", side_effect=[0, 0, 6]), \ with patch.object(app, "ask_choice", side_effect=[0, 0, 6]), \