Super Mario 64: ItemData class and tables (#4321)

* sm64ex: use item data class

* rearrange imports

* Dict to dict

* remove optional typing

* bonus item descriptions since we can also add stuff for webworld easily

* remove item descriptions (rip) and decrease verbosity for classifications

* formatting
This commit is contained in:
josephwhite
2025-03-08 12:07:50 -05:00
committed by GitHub
parent 54094c6331
commit ce34b60712
4 changed files with 61 additions and 53 deletions

View File

@@ -1,47 +1,58 @@
from BaseClasses import Item from typing import NamedTuple
from BaseClasses import Item, ItemClassification
sm64ex_base_id: int = 3626000
class SM64Item(Item): class SM64Item(Item):
game: str = "Super Mario 64" game: str = "Super Mario 64"
class SM64ItemData(NamedTuple):
code: int | None = None
classification: ItemClassification = ItemClassification.progression
generic_item_table = { generic_item_data_table: dict[str, SM64ItemData] = {
"Power Star": 3626000, "Power Star": SM64ItemData(sm64ex_base_id + 0, ItemClassification.progression_skip_balancing),
"Basement Key": 3626178, "Basement Key": SM64ItemData(sm64ex_base_id + 178),
"Second Floor Key": 3626179, "Second Floor Key": SM64ItemData(sm64ex_base_id + 179),
"Progressive Key": 3626180, "Progressive Key": SM64ItemData(sm64ex_base_id + 180),
"Wing Cap": 3626181, "Wing Cap": SM64ItemData(sm64ex_base_id + 181),
"Metal Cap": 3626182, "Metal Cap": SM64ItemData(sm64ex_base_id + 182),
"Vanish Cap": 3626183, "Vanish Cap": SM64ItemData(sm64ex_base_id + 183),
"1Up Mushroom": 3626184 "1Up Mushroom": SM64ItemData(sm64ex_base_id + 184, ItemClassification.filler),
} }
action_item_table = { action_item_data_table: dict[str, SM64ItemData] = {
"Double Jump": 3626185, "Double Jump": SM64ItemData(sm64ex_base_id + 185),
"Triple Jump": 3626186, "Triple Jump": SM64ItemData(sm64ex_base_id + 186),
"Long Jump": 3626187, "Long Jump": SM64ItemData(sm64ex_base_id + 187),
"Backflip": 3626188, "Backflip": SM64ItemData(sm64ex_base_id + 188),
"Side Flip": 3626189, "Side Flip": SM64ItemData(sm64ex_base_id + 189),
"Wall Kick": 3626190, "Wall Kick": SM64ItemData(sm64ex_base_id + 190),
"Dive": 3626191, "Dive": SM64ItemData(sm64ex_base_id + 191),
"Ground Pound": 3626192, "Ground Pound": SM64ItemData(sm64ex_base_id + 192),
"Kick": 3626193, "Kick": SM64ItemData(sm64ex_base_id + 193),
"Climb": 3626194, "Climb": SM64ItemData(sm64ex_base_id + 194),
"Ledge Grab": 3626195 "Ledge Grab": SM64ItemData(sm64ex_base_id + 195),
} }
cannon_item_data_table: dict[str, SM64ItemData] = {
cannon_item_table = { "Cannon Unlock BoB": SM64ItemData(sm64ex_base_id + 200),
"Cannon Unlock BoB": 3626200, "Cannon Unlock WF": SM64ItemData(sm64ex_base_id + 201),
"Cannon Unlock WF": 3626201, "Cannon Unlock JRB": SM64ItemData(sm64ex_base_id + 202),
"Cannon Unlock JRB": 3626202, "Cannon Unlock CCM": SM64ItemData(sm64ex_base_id + 203),
"Cannon Unlock CCM": 3626203, "Cannon Unlock SSL": SM64ItemData(sm64ex_base_id + 207),
"Cannon Unlock SSL": 3626207, "Cannon Unlock SL": SM64ItemData(sm64ex_base_id + 209),
"Cannon Unlock SL": 3626209, "Cannon Unlock WDW": SM64ItemData(sm64ex_base_id + 210),
"Cannon Unlock WDW": 3626210, "Cannon Unlock TTM": SM64ItemData(sm64ex_base_id + 211),
"Cannon Unlock TTM": 3626211, "Cannon Unlock THI": SM64ItemData(sm64ex_base_id + 212),
"Cannon Unlock THI": 3626212, "Cannon Unlock RR": SM64ItemData(sm64ex_base_id + 214),
"Cannon Unlock RR": 3626214
} }
item_table = {**generic_item_table, **action_item_table, **cannon_item_table} item_data_table = {
**generic_item_data_table,
**action_item_data_table,
**cannon_item_data_table
}
item_table = {name: data.code for name, data in item_data_table.items() if data.code is not None}

View File

@@ -1,7 +1,7 @@
import typing import typing
from dataclasses import dataclass from dataclasses import dataclass
from Options import DefaultOnToggle, Range, Toggle, DeathLink, Choice, PerGameCommonOptions, OptionSet, OptionGroup from Options import DefaultOnToggle, Range, Toggle, DeathLink, Choice, PerGameCommonOptions, OptionSet, OptionGroup
from .Items import action_item_table from .Items import action_item_data_table
class EnableCoinStars(Choice): class EnableCoinStars(Choice):
""" """
@@ -135,7 +135,7 @@ class MoveRandomizerActions(OptionSet):
"""Which actions to randomize when Move Randomizer is enabled""" """Which actions to randomize when Move Randomizer is enabled"""
display_name = "Randomized Moves" display_name = "Randomized Moves"
# HACK: Disable randomization for double jump # HACK: Disable randomization for double jump
valid_keys = [action for action in action_item_table if action != 'Double Jump'] valid_keys = [action for action in action_item_data_table if action != 'Double Jump']
default = valid_keys default = valid_keys
sm64_options_groups = [ sm64_options_groups = [

View File

@@ -6,7 +6,7 @@ from .Locations import location_table
from .Options import SM64Options from .Options import SM64Options
from .Regions import connect_regions, SM64Levels, sm64_level_to_paintings, sm64_paintings_to_level,\ from .Regions import connect_regions, SM64Levels, sm64_level_to_paintings, sm64_paintings_to_level,\
sm64_level_to_secrets, sm64_secrets_to_level, sm64_entrances_to_level, sm64_level_to_entrances sm64_level_to_secrets, sm64_secrets_to_level, sm64_entrances_to_level, sm64_level_to_entrances
from .Items import action_item_table from .Items import action_item_data_table
def shuffle_dict_keys(world, dictionary: dict) -> dict: def shuffle_dict_keys(world, dictionary: dict) -> dict:
keys = list(dictionary.keys()) keys = list(dictionary.keys())
@@ -372,8 +372,9 @@ class RuleFactory:
item = self.token_table.get(token, None) item = self.token_table.get(token, None)
if not item: if not item:
raise Exception(f"Invalid token: '{item}'") raise Exception(f"Invalid token: '{item}'")
if item in action_item_table: if item in action_item_data_table:
if self.move_rando_bitvec & (1 << (action_item_table[item] - action_item_table['Double Jump'])) == 0: double_jump_bitvec_offset = action_item_data_table['Double Jump'].code
if self.move_rando_bitvec & (1 << (action_item_data_table[item].code - double_jump_bitvec_offset)) == 0:
# This action item is not randomized. # This action item is not randomized.
return True return True
return item return item

View File

@@ -1,7 +1,7 @@
import typing import typing
import os import os
import json import json
from .Items import item_table, action_item_table, cannon_item_table, SM64Item from .Items import item_data_table, action_item_data_table, cannon_item_data_table, item_table, SM64Item
from .Locations import location_table, SM64Location from .Locations import location_table, SM64Location
from .Options import sm64_options_groups, SM64Options from .Options import sm64_options_groups, SM64Options
from .Rules import set_rules from .Rules import set_rules
@@ -65,9 +65,10 @@ class SM64World(World):
max_stars -= 15 max_stars -= 15
self.move_rando_bitvec = 0 self.move_rando_bitvec = 0
if self.options.enable_move_rando: if self.options.enable_move_rando:
double_jump_bitvec_offset = action_item_data_table['Double Jump'].code
for action in self.options.move_rando_actions.value: for action in self.options.move_rando_actions.value:
max_stars -= 1 max_stars -= 1
self.move_rando_bitvec |= (1 << (action_item_table[action] - action_item_table['Double Jump'])) self.move_rando_bitvec |= (1 << (action_item_data_table[action].code - double_jump_bitvec_offset))
if self.options.exclamation_boxes: if self.options.exclamation_boxes:
max_stars += 29 max_stars += 29
self.number_of_stars = min(self.options.amount_of_stars, max_stars) self.number_of_stars = min(self.options.amount_of_stars, max_stars)
@@ -100,14 +101,8 @@ class SM64World(World):
'entrance', self.player) 'entrance', self.player)
def create_item(self, name: str) -> Item: def create_item(self, name: str) -> Item:
item_id = item_table[name] data = item_data_table[name]
if name == "1Up Mushroom": item = SM64Item(name, data.classification, data.code, self.player)
classification = ItemClassification.filler
elif name == "Power Star":
classification = ItemClassification.progression_skip_balancing
else:
classification = ItemClassification.progression
item = SM64Item(name, classification, item_id, self.player)
return item return item
@@ -131,11 +126,12 @@ class SM64World(World):
self.multiworld.itempool += [self.create_item(cap_name) for cap_name in ["Wing Cap", "Metal Cap", "Vanish Cap"]] self.multiworld.itempool += [self.create_item(cap_name) for cap_name in ["Wing Cap", "Metal Cap", "Vanish Cap"]]
# Cannons # Cannons
if (self.options.buddy_checks): if (self.options.buddy_checks):
self.multiworld.itempool += [self.create_item(name) for name, id in cannon_item_table.items()] self.multiworld.itempool += [self.create_item(cannon_name) for cannon_name in cannon_item_data_table.keys()]
# Moves # Moves
double_jump_bitvec_offset = action_item_data_table['Double Jump'].code
self.multiworld.itempool += [self.create_item(action) self.multiworld.itempool += [self.create_item(action)
for action, itemid in action_item_table.items() for action, itemdata in action_item_data_table.items()
if self.move_rando_bitvec & (1 << itemid - action_item_table['Double Jump'])] if self.move_rando_bitvec & (1 << itemdata.code - double_jump_bitvec_offset)]
def generate_basic(self): def generate_basic(self):
if not (self.options.buddy_checks): if not (self.options.buddy_checks):