Classify stage authoring difficulty tiers

This commit is contained in:
gamer147
2026-07-23 23:45:46 -04:00
parent 796b0e850e
commit f855c3d01f
12 changed files with 81 additions and 30 deletions

View File

@@ -708,7 +708,7 @@ STAGE_DEFINITION_ARRAYS = {
"map_max_tile_y": (MAP_STAGE_MAX_Y, 1),
"minimap_atlas_origin_y": (0xED47D, 1),
"clear_base_spendable_point_reward": (0xED865, 1),
"unresolved_parameter_0xedc4d": (0xEDC4D, 1),
"authoring_difficulty_tier": (0xEDC4D, 1),
"scjump_decision_ids": (0xEE035, 3),
"extra_dungeon_flag": (0xEEBED, 1),
"clear_coin_quantities": (0xEEFD5, 3),
@@ -6130,11 +6130,11 @@ def extract_stage_definitions(scr):
if coin_quantities[column]
],
}
unresolved = scalar(
"unresolved_parameter_0xedc4d", stage_id
difficulty_tier = scalar(
"authoring_difficulty_tier", stage_id
)
if unresolved:
record["unresolved_parameter_0xedc4d"] = unresolved
if difficulty_tier:
record["authoring_difficulty_tier"] = difficulty_tier
records.append(record)
field_counts = {
@@ -6167,6 +6167,9 @@ def extract_stage_definitions(scr):
"clear_base_spendable_point_reward": (
"stage_clear_base_spendable_point_rewards"
),
"authoring_difficulty_tier": (
"stage_authoring_difficulty_tiers"
),
"scjump_decision_ids": "stage_scjump_decision_ids",
"extra_dungeon_flag": "stage_extra_dungeon_flags",
"clear_coin_quantities": "stage_clear_coin_quantities",
@@ -6265,9 +6268,16 @@ def extract_stage_definitions(scr):
"clear_coin_reward_cell_count": field_counts[
"clear_coin_quantities"
],
"unresolved_parameter_population": field_counts[
"unresolved_parameter_0xedc4d"
"authoring_difficulty_tier_population": field_counts[
"authoring_difficulty_tier"
],
"authoring_difficulty_tier_counts": {
str(tier): sum(
record.get("authoring_difficulty_tier") == tier
for record in records
)
for tier in range(1, 9)
},
"consumer_contract": {
"FORT.BIN": (
"enumerates named rows, applies required/forbidden story "
@@ -6910,7 +6920,8 @@ def write_data_index(data_dir: Path) -> None:
"slots, progression and story gates, numbered/EVENT/EX presentation, map and",
"minimap geometry, point/coin rewards, and all 174 SCINIT-resolved entry, clear,",
"and failure decisions. All rows resolve their shared STINIT loader reference;",
"the unconsumed 0xedc4d column remains explicit rather than receiving a guess.",
"the unconsumed 0xedc4d column is retained as a medium-confidence,",
"authoring-only difficulty tier rather than being assigned runtime behavior.",
"",
"MPINIT's dedicated terrain-atlas schema exposes 1,472 authored rows of a sparse",
"53-column half-tile grid. It joins STINIT2's doubled tile-bound rectangles to 66",

View File

@@ -615,8 +615,11 @@ def profile_stage_definitions(data: dict) -> dict:
"clear_coin_reward_cell_count": data.get(
"clear_coin_reward_cell_count", 0
),
"unresolved_parameter_population": data.get(
"unresolved_parameter_population", 0
"authoring_difficulty_tier_population": data.get(
"authoring_difficulty_tier_population", 0
),
"authoring_difficulty_tier_counts": data.get(
"authoring_difficulty_tier_counts", {}
),
}
@@ -818,8 +821,9 @@ def render_markdown(data: dict, rows: list[dict], limit: int) -> str:
f"{stage_profile['stage_count']}",
f"- clear coin reward cells: "
f"{stage_profile['clear_coin_reward_cell_count']}",
f"- unresolved 0xedc4d cells: "
f"{stage_profile['unresolved_parameter_population']}",
f"- authoring-only difficulty tiers: "
f"{stage_profile['authoring_difficulty_tier_population']} "
f"({stage_profile['authoring_difficulty_tier_counts']})",
])
elif definition_profile := profile_card_definitions(data):
lines.extend([

View File

@@ -2079,9 +2079,20 @@ def test_stage_definitions() -> None:
"STINIT2 resolves the spendable-point and three coin reward columns",
)
check(
meta["unresolved_parameter_population"] == 66
and by_id[167]["unresolved_parameter_0xedc4d"] == 8,
"STINIT2 preserves the one still-unresolved populated stage column",
meta["authoring_difficulty_tier_population"] == 66
and meta["authoring_difficulty_tier_counts"]
== {
"1": 7,
"2": 11,
"3": 17,
"4": 5,
"5": 12,
"6": 9,
"7": 4,
"8": 1,
}
and by_id[167]["authoring_difficulty_tier"] == 8,
"STINIT2 preserves the inferred authoring-only difficulty tiers",
)

View File

@@ -124,8 +124,10 @@ def test_load_and_lint():
and entries[0xec0f5]["name"] == "stage_display_number_minor"
and entries[0xed47d]["name"] == "stage_minimap_atlas_origin_y"
and entries[0xed865]["name"]
== "stage_clear_base_spendable_point_rewards",
"STINIT2 stage numbering, minimap, and point rewards are curated")
== "stage_clear_base_spendable_point_rewards"
and entries[0xedc4d]["name"]
== "stage_authoring_difficulty_tiers",
"STINIT2 numbering, minimap, points, and authoring tiers are curated")
check(entries[0xee035]["columns"]
== {"0": "entry", "1": "clear", "2": "failure"}
and entries[0xeebed]["name"] == "stage_extra_dungeon_flags"

View File

@@ -430,7 +430,12 @@ def main() -> int:
"resolved_scjump_reference_count": 12,
"resolved_loader_script_count": 5,
"clear_coin_reward_cell_count": 4,
"unresolved_parameter_population": 4,
"authoring_difficulty_tier_population": 4,
"authoring_difficulty_tier_counts": {
"1": 1,
"2": 2,
"3": 1,
},
"records": [{}, {}, {}, {}, {}],
}
stage_summary = profile.profile_stage_definitions(stage_fixture)
@@ -442,6 +447,7 @@ def main() -> int:
assert "- stage definitions: 5/1000 rows" in rendered_stages
assert "- mapped/event-only stages: 4/1" in rendered_stages
assert "- SCJUMP joins: 12/12" in rendered_stages
assert "- authoring-only difficulty tiers: 4" in rendered_stages
training_fixture = {
"table": "TRAINING",