LADX: Improve icon guesses for foreign items (#2201)

* synonyms to new file, many added

* handle singular rupee

* remove redundant map and compass entries

* automatic pluralization

* add guardian acorn and piece of power

* move phrases to ItemIconGuessing.py

* organize, comment

* fix tab spacing

* fix

* add tunic and noita synonyms

* remove triangle instrument synonym

* reorganize, add some matches

* add tunic lucky up

Co-authored-by: Scipio Wright <scipiowright@gmail.com>

* Update worlds/ladx/ItemIconGuessing.py

Co-authored-by: Scipio Wright <scipiowright@gmail.com>

* handle camelCase and single rupee

* add indicate_progression option
Adds alternative system for foreign item icons that simply indicates whether or not the item is a progression item.

* improve splitting
drops some more characters, and also dont bother with rejoined stuff in name_cache because our splitting is better

* the witness stuff

* forbid more

* remove boost and surge

* Update worlds/ladx/ItemIconGuessing.py

Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com>

* match by game name
look at the name of the foreign game and only use game-specific entries for that game

* show message for all key drops

* updates from async test

* vi suggestions

* Adding FNAFW suggestions from @lolz1190 (#40)

* Adding FNAFW suggestions from @lolz1190

* missing comma

---------

Co-authored-by: threeandthreee <a.l.nordstrom@gmail.com>

---------

Co-authored-by: Scipio Wright <scipiowright@gmail.com>
Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com>
Co-authored-by: palex00 <32203971+palex00@users.noreply.github.com>
This commit is contained in:
threeandthreee 2024-12-13 16:49:30 -05:00 committed by GitHub
parent 8d9454ea3b
commit ccea6bcf51
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 603 additions and 62 deletions

View File

@ -0,0 +1,531 @@
BLOCKED_ASSOCIATIONS = [
# MAX_ARROWS_UPGRADE, MAX_BOMBS_UPGRADE, MAX_POWDER_UPGRADE
# arrows and bombs will be matched to arrow and bomb respectively through pluralization
"ARROWS",
"BOMBS",
"MAX",
"UPGRADE",
"TAIL", # TAIL_KEY
"ANGLER", # ANGLER_KEY
"FACE", # FACE_KEY
"BIRD", # BIRD_KEY
"SLIME", # SLIME_KEY
"NIGHTMARE",# NIGHTMARE_KEY
"BLUE", # BLUE_TUNIC
"RED", # RED_TUNIC
"TRADING", # TRADING_ITEM_*
"ITEM", # TRADING_ITEM_*
"BAD", # BAD_HEART_CONTAINER
"GOLD", # GOLD_LEAF
"MAGIC", # MAGIC_POWDER, MAGIC_ROD
"MESSAGE", # MESSAGE (Master Stalfos' Message)
"PEGASUS", # PEGASUS_BOOTS
"PIECE", # HEART_PIECE, PIECE_OF_POWER
"POWER", # POWER_BRACELET, PIECE_OF_POWER
"SINGLE", # SINGLE_ARROW
"STONE", # STONE_BEAK
"BEAK1",
"BEAK2",
"BEAK3",
"BEAK4",
"BEAK5",
"BEAK6",
"BEAK7",
"BEAK8",
"COMPASS1",
"COMPASS2",
"COMPASS3",
"COMPASS4",
"COMPASS5",
"COMPASS6",
"COMPASS7",
"COMPASS8",
"MAP1",
"MAP2",
"MAP3",
"MAP4",
"MAP5",
"MAP6",
"MAP7",
"MAP8",
]
# Single word synonyms for Link's Awakening items, for generic matching.
SYNONYMS = {
# POWER_BRACELET
'ANKLET': 'POWER_BRACELET',
'ARMLET': 'POWER_BRACELET',
'BAND': 'POWER_BRACELET',
'BANGLE': 'POWER_BRACELET',
'BRACER': 'POWER_BRACELET',
'CARRY': 'POWER_BRACELET',
'CIRCLET': 'POWER_BRACELET',
'CROISSANT': 'POWER_BRACELET',
'GAUNTLET': 'POWER_BRACELET',
'GLOVE': 'POWER_BRACELET',
'RING': 'POWER_BRACELET',
'STRENGTH': 'POWER_BRACELET',
# SHIELD
'AEGIS': 'SHIELD',
'BUCKLER': 'SHIELD',
'SHLD': 'SHIELD',
# BOW
'BALLISTA': 'BOW',
# HOOKSHOT
'GRAPPLE': 'HOOKSHOT',
'GRAPPLING': 'HOOKSHOT',
'ROPE': 'HOOKSHOT',
# MAGIC_ROD
'BEAM': 'MAGIC_ROD',
'CANE': 'MAGIC_ROD',
'STAFF': 'MAGIC_ROD',
'WAND': 'MAGIC_ROD',
# PEGASUS_BOOTS
'BOOT': 'PEGASUS_BOOTS',
'GREAVES': 'PEGASUS_BOOTS',
'RUN': 'PEGASUS_BOOTS',
'SHOE': 'PEGASUS_BOOTS',
'SPEED': 'PEGASUS_BOOTS',
# OCARINA
'FLUTE': 'OCARINA',
'RECORDER': 'OCARINA',
# FEATHER
'JUMP': 'FEATHER',
'PLUME': 'FEATHER',
'WING': 'FEATHER',
# SHOVEL
'DIG': 'SHOVEL',
# MAGIC_POWDER
'BAG': 'MAGIC_POWDER',
'CASE': 'MAGIC_POWDER',
'DUST': 'MAGIC_POWDER',
'POUCH': 'MAGIC_POWDER',
'SACK': 'MAGIC_POWDER',
# BOMB
'BLAST': 'BOMB',
'BOMBCHU': 'BOMB',
'FIRECRACKER': 'BOMB',
'TNT': 'BOMB',
# SWORD
'BLADE': 'SWORD',
'CUT': 'SWORD',
'DAGGER': 'SWORD',
'DIRK': 'SWORD',
'EDGE': 'SWORD',
'EPEE': 'SWORD',
'EXCALIBUR': 'SWORD',
'FALCHION': 'SWORD',
'KATANA': 'SWORD',
'KNIFE': 'SWORD',
'MACHETE': 'SWORD',
'MASAMUNE': 'SWORD',
'MURASAME': 'SWORD',
'SABER': 'SWORD',
'SABRE': 'SWORD',
'SCIMITAR': 'SWORD',
'SLASH': 'SWORD',
# FLIPPERS
'FLIPPER': 'FLIPPERS',
'SWIM': 'FLIPPERS',
# MEDICINE
'BOTTLE': 'MEDICINE',
'FLASK': 'MEDICINE',
'LEMONADE': 'MEDICINE',
'POTION': 'MEDICINE',
'TEA': 'MEDICINE',
# TAIL_KEY
# ANGLER_KEY
# FACE_KEY
# BIRD_KEY
# SLIME_KEY
# GOLD_LEAF
'HERB': 'GOLD_LEAF',
# RUPEES_20
'COIN': 'RUPEES_20',
'MONEY': 'RUPEES_20',
'RUPEE': 'RUPEES_20',
# RUPEES_50
# RUPEES_100
# RUPEES_200
# RUPEES_500
'GEM': 'RUPEES_500',
'JEWEL': 'RUPEES_500',
# SEASHELL
'CARAPACE': 'SEASHELL',
'CONCH': 'SEASHELL',
'SHELL': 'SEASHELL',
# MESSAGE (master stalfos message)
'NOTHING': 'MESSAGE',
'TRAP': 'MESSAGE',
# BOOMERANG
'BOOMER': 'BOOMERANG',
# HEART_PIECE
# BOWWOW
'BEAST': 'BOWWOW',
'PET': 'BOWWOW',
# ARROWS_10
# SINGLE_ARROW
'MISSILE': 'SINGLE_ARROW',
'QUIVER': 'SINGLE_ARROW',
# ROOSTER
'BIRD': 'ROOSTER',
'CHICKEN': 'ROOSTER',
'CUCCO': 'ROOSTER',
'FLY': 'ROOSTER',
'GRIFFIN': 'ROOSTER',
'GRYPHON': 'ROOSTER',
# MAX_POWDER_UPGRADE
# MAX_BOMBS_UPGRADE
# MAX_ARROWS_UPGRADE
# RED_TUNIC
# BLUE_TUNIC
'ARMOR': 'BLUE_TUNIC',
'MAIL': 'BLUE_TUNIC',
'SUIT': 'BLUE_TUNIC',
# HEART_CONTAINER
'TANK': 'HEART_CONTAINER',
# TOADSTOOL
'FUNGAL': 'TOADSTOOL',
'FUNGUS': 'TOADSTOOL',
'MUSHROOM': 'TOADSTOOL',
'SHROOM': 'TOADSTOOL',
# GUARDIAN_ACORN
'NUT': 'GUARDIAN_ACORN',
'SEED': 'GUARDIAN_ACORN',
# KEY
'DOOR': 'KEY',
'GATE': 'KEY',
'KEY': 'KEY', # Without this, foreign keys show up as nightmare keys
'LOCK': 'KEY',
'PANEL': 'KEY',
'UNLOCK': 'KEY',
# NIGHTMARE_KEY
# MAP
# COMPASS
# STONE_BEAK
'FOSSIL': 'STONE_BEAK',
'RELIC': 'STONE_BEAK',
# SONG1
'BOLERO': 'SONG1',
'LULLABY': 'SONG1',
'MELODY': 'SONG1',
'MINUET': 'SONG1',
'NOCTURNE': 'SONG1',
'PRELUDE': 'SONG1',
'REQUIEM': 'SONG1',
'SERENADE': 'SONG1',
'SONG': 'SONG1',
# SONG2
'FISH': 'SONG2',
'SURF': 'SONG2',
# SONG3
'FROG': 'SONG3',
# INSTRUMENT1
'CELLO': 'INSTRUMENT1',
'GUITAR': 'INSTRUMENT1',
'LUTE': 'INSTRUMENT1',
'VIOLIN': 'INSTRUMENT1',
# INSTRUMENT2
'HORN': 'INSTRUMENT2',
# INSTRUMENT3
'BELL': 'INSTRUMENT3',
'CHIME': 'INSTRUMENT3',
# INSTRUMENT4
'HARP': 'INSTRUMENT4',
'KANTELE': 'INSTRUMENT4',
# INSTRUMENT5
'MARIMBA': 'INSTRUMENT5',
'XYLOPHONE': 'INSTRUMENT5',
# INSTRUMENT6 (triangle)
# INSTRUMENT7
'KEYBOARD': 'INSTRUMENT7',
'ORGAN': 'INSTRUMENT7',
'PIANO': 'INSTRUMENT7',
# INSTRUMENT8
'DRUM': 'INSTRUMENT8',
# TRADING_ITEM_YOSHI_DOLL
'DINOSAUR': 'TRADING_ITEM_YOSHI_DOLL',
'DRAGON': 'TRADING_ITEM_YOSHI_DOLL',
'TOY': 'TRADING_ITEM_YOSHI_DOLL',
# TRADING_ITEM_RIBBON
'HAIRBAND': 'TRADING_ITEM_RIBBON',
'HAIRPIN': 'TRADING_ITEM_RIBBON',
# TRADING_ITEM_DOG_FOOD
'CAN': 'TRADING_ITEM_DOG_FOOD',
# TRADING_ITEM_BANANAS
'BANANA': 'TRADING_ITEM_BANANAS',
# TRADING_ITEM_STICK
'BRANCH': 'TRADING_ITEM_STICK',
'TWIG': 'TRADING_ITEM_STICK',
# TRADING_ITEM_HONEYCOMB
'BEEHIVE': 'TRADING_ITEM_HONEYCOMB',
'HIVE': 'TRADING_ITEM_HONEYCOMB',
'HONEY': 'TRADING_ITEM_HONEYCOMB',
# TRADING_ITEM_PINEAPPLE
'FOOD': 'TRADING_ITEM_PINEAPPLE',
'FRUIT': 'TRADING_ITEM_PINEAPPLE',
'GOURD': 'TRADING_ITEM_PINEAPPLE',
# TRADING_ITEM_HIBISCUS
'FLOWER': 'TRADING_ITEM_HIBISCUS',
'PETAL': 'TRADING_ITEM_HIBISCUS',
# TRADING_ITEM_LETTER
'CARD': 'TRADING_ITEM_LETTER',
'MESSAGE': 'TRADING_ITEM_LETTER',
# TRADING_ITEM_BROOM
'SWEEP': 'TRADING_ITEM_BROOM',
# TRADING_ITEM_FISHING_HOOK
'CLAW': 'TRADING_ITEM_FISHING_HOOK',
# TRADING_ITEM_NECKLACE
'AMULET': 'TRADING_ITEM_NECKLACE',
'BEADS': 'TRADING_ITEM_NECKLACE',
'PEARLS': 'TRADING_ITEM_NECKLACE',
'PENDANT': 'TRADING_ITEM_NECKLACE',
'ROSARY': 'TRADING_ITEM_NECKLACE',
# TRADING_ITEM_SCALE
# TRADING_ITEM_MAGNIFYING_GLASS
'FINDER': 'TRADING_ITEM_MAGNIFYING_GLASS',
'LENS': 'TRADING_ITEM_MAGNIFYING_GLASS',
'MIRROR': 'TRADING_ITEM_MAGNIFYING_GLASS',
'SCOPE': 'TRADING_ITEM_MAGNIFYING_GLASS',
'XRAY': 'TRADING_ITEM_MAGNIFYING_GLASS',
# PIECE_OF_POWER
'TRIANGLE': 'PIECE_OF_POWER',
'POWER': 'PIECE_OF_POWER',
'TRIFORCE': 'PIECE_OF_POWER',
}
# For generic multi-word matches.
PHRASES = {
'BIG KEY': 'NIGHTMARE_KEY',
'BOSS KEY': 'NIGHTMARE_KEY',
'HEART PIECE': 'HEART_PIECE',
'PIECE OF HEART': 'HEART_PIECE',
}
# All following will only be used to match items for the specific game.
# Item names will be uppercased when comparing.
# Can be multi-word.
GAME_SPECIFIC_PHRASES = {
'Final Fantasy': {
'OXYALE': 'MEDICINE',
'VORPAL': 'SWORD',
'XCALBER': 'SWORD',
},
'The Legend of Zelda': {
'WATER OF LIFE': 'MEDICINE',
},
'The Legend of Zelda - Oracle of Seasons': {
'RARE PEACH STONE': 'HEART_PIECE',
},
'Noita': {
'ALL-SEEING EYE': 'TRADING_ITEM_MAGNIFYING_GLASS', # lets you find secrets
},
'Ocarina of Time': {
'COJIRO': 'ROOSTER',
},
'SMZ3': {
'BIGKEY': 'NIGHTMARE_KEY',
'BYRNA': 'MAGIC_ROD',
'HEARTPIECE': 'HEART_PIECE',
'POWERBOMB': 'BOMB',
'SOMARIA': 'MAGIC_ROD',
'SUPER': 'SINGLE_ARROW',
},
'Sonic Adventure 2 Battle': {
'CHAOS EMERALD': 'PIECE_OF_POWER',
},
'Super Mario 64': {
'POWER STAR': 'PIECE_OF_POWER',
},
'Super Mario World': {
'P-BALLOON': 'FEATHER',
},
'Super Metroid': {
'POWER BOMB': 'BOMB',
},
'The Witness': {
'BONK': 'BOMB',
'BUNKER LASER': 'INSTRUMENT4',
'DESERT LASER': 'INSTRUMENT5',
'JUNGLE LASER': 'INSTRUMENT4',
'KEEP LASER': 'INSTRUMENT7',
'MONASTERY LASER': 'INSTRUMENT1',
'POWER SURGE': 'BOMB',
'PUZZLE SKIP': 'GOLD_LEAF',
'QUARRY LASER': 'INSTRUMENT8',
'SHADOWS LASER': 'INSTRUMENT1',
'SHORTCUTS': 'KEY',
'SLOWNESS': 'BOMB',
'SWAMP LASER': 'INSTRUMENT2',
'SYMMETRY LASER': 'INSTRUMENT6',
'TOWN LASER': 'INSTRUMENT3',
'TREEHOUSE LASER': 'INSTRUMENT2',
'WATER PUMPS': 'KEY',
},
'TUNIC': {
"AURA'S GEM": 'SHIELD', # card that enhances the shield
'DUSTY': 'TRADING_ITEM_BROOM', # a broom
'HERO RELIC - HP': 'TRADING_ITEM_HIBISCUS',
'HERO RELIC - MP': 'TOADSTOOL',
'HERO RELIC - SP': 'FEATHER',
'HP BERRY': 'GUARDIAN_ACORN',
'HP OFFERING': 'TRADING_ITEM_HIBISCUS', # a flower
'LUCKY CUP': 'HEART_CONTAINER', # card with a heart on it
'INVERTED ASH': 'MEDICINE', # card with a potion on it
'MAGIC ORB': 'HOOKSHOT',
'MP BERRY': 'GUARDIAN_ACORN',
'MP OFFERING': 'TOADSTOOL', # a mushroom
'QUESTAGON': 'PIECE_OF_POWER', # triforce piece equivalent
'SP OFFERING': 'FEATHER', # a feather
'SPRING FALLS': 'TRADING_ITEM_HIBISCUS', # a flower
},
'FNaFW': {
'Freddy': 'TRADING_ITEM_YOSHI_DOLL', # all of these are animatronics, aka dolls.
'Bonnie': 'TRADING_ITEM_YOSHI_DOLL',
'Chica': 'TRADING_ITEM_YOSHI_DOLL',
'Foxy': 'TRADING_ITEM_YOSHI_DOLL',
'Toy Bonnie': 'TRADING_ITEM_YOSHI_DOLL',
'Toy Chica': 'TRADING_ITEM_YOSHI_DOLL',
'Toy Freddy': 'TRADING_ITEM_YOSHI_DOLL',
'Mangle': 'TRADING_ITEM_YOSHI_DOLL',
'Balloon Boy': 'TRADING_ITEM_YOSHI_DOLL',
'JJ': 'TRADING_ITEM_YOSHI_DOLL',
'Phantom Freddy': 'TRADING_ITEM_YOSHI_DOLL',
'Phantom BB': 'TRADING_ITEM_YOSHI_DOLL',
'Phantom Chica': 'TRADING_ITEM_YOSHI_DOLL',
'Phantom Mangle': 'TRADING_ITEM_YOSHI_DOLL',
'Withered Foxy': 'TRADING_ITEM_YOSHI_DOLL',
'Phantom Foxy': 'TRADING_ITEM_YOSHI_DOLL',
'Withered Chica': 'TRADING_ITEM_YOSHI_DOLL',
'Withered Freddy': 'TRADING_ITEM_YOSHI_DOLL',
'Withered Bonnie': 'TRADING_ITEM_YOSHI_DOLL',
'Shadow Freddy': 'TRADING_ITEM_YOSHI_DOLL',
'Marionette': 'TRADING_ITEM_YOSHI_DOLL',
'Phantom Marionette': 'TRADING_ITEM_YOSHI_DOLL',
'Golden Freddy': 'TRADING_ITEM_YOSHI_DOLL',
'Paperpals': 'TRADING_ITEM_YOSHI_DOLL',
'Nightmare Freddy': 'TRADING_ITEM_YOSHI_DOLL',
'Nightmare Bonnie': 'TRADING_ITEM_YOSHI_DOLL',
'Nightmare Chica': 'TRADING_ITEM_YOSHI_DOLL',
'Nightmare Foxy': 'TRADING_ITEM_YOSHI_DOLL',
'Endo 01': 'TRADING_ITEM_YOSHI_DOLL',
'Endo 02': 'TRADING_ITEM_YOSHI_DOLL',
'Plushtrap': 'TRADING_ITEM_YOSHI_DOLL',
'Endoplush': 'TRADING_ITEM_YOSHI_DOLL',
'Springtrap': 'TRADING_ITEM_YOSHI_DOLL',
'RWQFSFASXC': 'TRADING_ITEM_YOSHI_DOLL',
'Crying Child': 'TRADING_ITEM_YOSHI_DOLL',
'Funtime Foxy': 'TRADING_ITEM_YOSHI_DOLL',
'Nightmare Fredbear': 'TRADING_ITEM_YOSHI_DOLL',
'Nightmare': 'TRADING_ITEM_YOSHI_DOLL',
'Fredbear': 'TRADING_ITEM_YOSHI_DOLL',
'Spring Bonnie': 'TRADING_ITEM_YOSHI_DOLL',
'Jack-O-Chica': 'TRADING_ITEM_YOSHI_DOLL',
'Nightmare BB': 'TRADING_ITEM_YOSHI_DOLL',
'Coffee': 'TRADING_ITEM_YOSHI_DOLL',
'Jack-O-Bonnie': 'TRADING_ITEM_YOSHI_DOLL',
'Purpleguy': 'TRADING_ITEM_YOSHI_DOLL',
'Nightmarionne': 'TRADING_ITEM_YOSHI_DOLL',
'Mr. Chipper': 'TRADING_ITEM_YOSHI_DOLL',
'Animdude': 'TRADING_ITEM_YOSHI_DOLL',
'Progressive Endoskeleton': 'BLUE_TUNIC', # basically armor you wear to give you more defense
'25 Tokens': 'RUPEES_20', # money
'50 Tokens': 'RUPEES_50',
'100 Tokens': 'RUPEES_100',
'250 Tokens': 'RUPEES_200',
'500 Tokens': 'RUPEES_500',
'1000 Tokens': 'RUPEES_500',
'2500 Tokens': 'RUPEES_500',
'5000 Tokens': 'RUPEES_500',
},
}

View File

@ -98,6 +98,7 @@ class ItemName:
HEART_CONTAINER = "Heart Container" HEART_CONTAINER = "Heart Container"
BAD_HEART_CONTAINER = "Bad Heart Container" BAD_HEART_CONTAINER = "Bad Heart Container"
TOADSTOOL = "Toadstool" TOADSTOOL = "Toadstool"
GUARDIAN_ACORN = "Guardian Acorn"
KEY = "Key" KEY = "Key"
KEY1 = "Small Key (Tail Cave)" KEY1 = "Small Key (Tail Cave)"
KEY2 = "Small Key (Bottle Grotto)" KEY2 = "Small Key (Bottle Grotto)"
@ -173,6 +174,7 @@ class ItemName:
TRADING_ITEM_NECKLACE = "Necklace" TRADING_ITEM_NECKLACE = "Necklace"
TRADING_ITEM_SCALE = "Scale" TRADING_ITEM_SCALE = "Scale"
TRADING_ITEM_MAGNIFYING_GLASS = "Magnifying Glass" TRADING_ITEM_MAGNIFYING_GLASS = "Magnifying Glass"
PIECE_OF_POWER = "Piece Of Power"
trade_item_prog = ItemClassification.progression trade_item_prog = ItemClassification.progression
@ -219,6 +221,7 @@ links_awakening_items = [
ItemData(ItemName.HEART_CONTAINER, "HEART_CONTAINER", ItemClassification.useful), ItemData(ItemName.HEART_CONTAINER, "HEART_CONTAINER", ItemClassification.useful),
#ItemData(ItemName.BAD_HEART_CONTAINER, "BAD_HEART_CONTAINER", ItemClassification.trap), #ItemData(ItemName.BAD_HEART_CONTAINER, "BAD_HEART_CONTAINER", ItemClassification.trap),
ItemData(ItemName.TOADSTOOL, "TOADSTOOL", ItemClassification.progression), ItemData(ItemName.TOADSTOOL, "TOADSTOOL", ItemClassification.progression),
ItemData(ItemName.GUARDIAN_ACORN, "GUARDIAN_ACORN", ItemClassification.filler),
DungeonItemData(ItemName.KEY, "KEY", ItemClassification.progression), DungeonItemData(ItemName.KEY, "KEY", ItemClassification.progression),
DungeonItemData(ItemName.KEY1, "KEY1", ItemClassification.progression), DungeonItemData(ItemName.KEY1, "KEY1", ItemClassification.progression),
DungeonItemData(ItemName.KEY2, "KEY2", ItemClassification.progression), DungeonItemData(ItemName.KEY2, "KEY2", ItemClassification.progression),
@ -293,7 +296,8 @@ links_awakening_items = [
TradeItemData(ItemName.TRADING_ITEM_FISHING_HOOK, "TRADING_ITEM_FISHING_HOOK", trade_item_prog, "Grandma (Animal Village)"), TradeItemData(ItemName.TRADING_ITEM_FISHING_HOOK, "TRADING_ITEM_FISHING_HOOK", trade_item_prog, "Grandma (Animal Village)"),
TradeItemData(ItemName.TRADING_ITEM_NECKLACE, "TRADING_ITEM_NECKLACE", trade_item_prog, "Fisher (Martha's Bay)"), TradeItemData(ItemName.TRADING_ITEM_NECKLACE, "TRADING_ITEM_NECKLACE", trade_item_prog, "Fisher (Martha's Bay)"),
TradeItemData(ItemName.TRADING_ITEM_SCALE, "TRADING_ITEM_SCALE", trade_item_prog, "Mermaid (Martha's Bay)"), TradeItemData(ItemName.TRADING_ITEM_SCALE, "TRADING_ITEM_SCALE", trade_item_prog, "Mermaid (Martha's Bay)"),
TradeItemData(ItemName.TRADING_ITEM_MAGNIFYING_GLASS, "TRADING_ITEM_MAGNIFYING_GLASS", trade_item_prog, "Mermaid Statue (Martha's Bay)") TradeItemData(ItemName.TRADING_ITEM_MAGNIFYING_GLASS, "TRADING_ITEM_MAGNIFYING_GLASS", trade_item_prog, "Mermaid Statue (Martha's Bay)"),
ItemData(ItemName.PIECE_OF_POWER, "PIECE_OF_POWER", ItemClassification.filler),
] ]
ladxr_item_to_la_item_name = { ladxr_item_to_la_item_name = {

View File

@ -87,6 +87,8 @@ CHEST_ITEMS = {
TOADSTOOL: 0x50, TOADSTOOL: 0x50,
GUARDIAN_ACORN: 0x51,
HEART_PIECE: 0x80, HEART_PIECE: 0x80,
BOWWOW: 0x81, BOWWOW: 0x81,
ARROWS_10: 0x82, ARROWS_10: 0x82,
@ -128,4 +130,6 @@ CHEST_ITEMS = {
TRADING_ITEM_NECKLACE: 0xA2, TRADING_ITEM_NECKLACE: 0xA2,
TRADING_ITEM_SCALE: 0xA3, TRADING_ITEM_SCALE: 0xA3,
TRADING_ITEM_MAGNIFYING_GLASS: 0xA4, TRADING_ITEM_MAGNIFYING_GLASS: 0xA4,
PIECE_OF_POWER: 0xA5,
} }

View File

@ -44,6 +44,8 @@ BAD_HEART_CONTAINER = "BAD_HEART_CONTAINER"
TOADSTOOL = "TOADSTOOL" TOADSTOOL = "TOADSTOOL"
GUARDIAN_ACORN = "GUARDIAN_ACORN"
KEY = "KEY" KEY = "KEY"
KEY1 = "KEY1" KEY1 = "KEY1"
KEY2 = "KEY2" KEY2 = "KEY2"
@ -124,3 +126,5 @@ TRADING_ITEM_FISHING_HOOK = "TRADING_ITEM_FISHING_HOOK"
TRADING_ITEM_NECKLACE = "TRADING_ITEM_NECKLACE" TRADING_ITEM_NECKLACE = "TRADING_ITEM_NECKLACE"
TRADING_ITEM_SCALE = "TRADING_ITEM_SCALE" TRADING_ITEM_SCALE = "TRADING_ITEM_SCALE"
TRADING_ITEM_MAGNIFYING_GLASS = "TRADING_ITEM_MAGNIFYING_GLASS" TRADING_ITEM_MAGNIFYING_GLASS = "TRADING_ITEM_MAGNIFYING_GLASS"
PIECE_OF_POWER = "PIECE_OF_POWER"

View File

@ -835,6 +835,7 @@ ItemSpriteTable:
db $46, $1C ; NIGHTMARE_KEY8 db $46, $1C ; NIGHTMARE_KEY8
db $46, $1C ; NIGHTMARE_KEY9 db $46, $1C ; NIGHTMARE_KEY9
db $4C, $1C ; Toadstool db $4C, $1C ; Toadstool
db $AE, $14 ; Guardian Acorn
LargeItemSpriteTable: LargeItemSpriteTable:
db $AC, $02, $AC, $22 ; heart piece db $AC, $02, $AC, $22 ; heart piece
@ -874,6 +875,7 @@ LargeItemSpriteTable:
db $D8, $0D, $DA, $0D ; TradeItem12 db $D8, $0D, $DA, $0D ; TradeItem12
db $DC, $0D, $DE, $0D ; TradeItem13 db $DC, $0D, $DE, $0D ; TradeItem13
db $E0, $0D, $E2, $0D ; TradeItem14 db $E0, $0D, $E2, $0D ; TradeItem14
db $14, $42, $14, $62 ; Piece Of Power
ItemMessageTable: ItemMessageTable:
db $90, $3D, $89, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $D9, $A2 db $90, $3D, $89, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $D9, $A2
@ -888,7 +890,7 @@ ItemMessageTable:
; $80 ; $80
db $4F, $C8, $CA, $CB, $E2, $E3, $E4, $CC, $CD, $2A, $2B, $C9, $C9, $C9, $C9, $C9 db $4F, $C8, $CA, $CB, $E2, $E3, $E4, $CC, $CD, $2A, $2B, $C9, $C9, $C9, $C9, $C9
db $C9, $C9, $C9, $C9, $C9, $C9, $B8, $44, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9 db $C9, $C9, $C9, $C9, $C9, $C9, $B8, $44, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9
db $C9, $C9, $C9, $C9, $9D db $C9, $C9, $C9, $C9, $9D, $C9
RenderDroppedKey: RenderDroppedKey:
;TODO: See EntityInitKeyDropPoint for a few special cases to unload. ;TODO: See EntityInitKeyDropPoint for a few special cases to unload.

View File

@ -170,7 +170,7 @@ ItemNamePointers:
dw ItemNameNightmareKey8 dw ItemNameNightmareKey8
dw ItemNameNightmareKey9 dw ItemNameNightmareKey9
dw ItemNameToadstool dw ItemNameToadstool
dw ItemNameNone ; 0x51 dw ItemNameGuardianAcorn
dw ItemNameNone ; 0x52 dw ItemNameNone ; 0x52
dw ItemNameNone ; 0x53 dw ItemNameNone ; 0x53
dw ItemNameNone ; 0x54 dw ItemNameNone ; 0x54
@ -254,6 +254,7 @@ ItemNamePointers:
dw ItemTradeQuest12 dw ItemTradeQuest12
dw ItemTradeQuest13 dw ItemTradeQuest13
dw ItemTradeQuest14 dw ItemTradeQuest14
dw ItemPieceOfPower
ItemNameNone: ItemNameNone:
db m"NONE", $ff db m"NONE", $ff
@ -418,6 +419,8 @@ ItemNameNightmareKey9:
db m"Got the {NIGHTMARE_KEY9}", $ff db m"Got the {NIGHTMARE_KEY9}", $ff
ItemNameToadstool: ItemNameToadstool:
db m"Got the {TOADSTOOL}", $ff db m"Got the {TOADSTOOL}", $ff
ItemNameGuardianAcorn:
db m"Got a Guardian Acorn", $ff
ItemNameHeartPiece: ItemNameHeartPiece:
db m"Got the {HEART_PIECE}", $ff db m"Got the {HEART_PIECE}", $ff
@ -497,4 +500,7 @@ ItemTradeQuest13:
ItemTradeQuest14: ItemTradeQuest14:
db m"You've got the Magnifying Lens", $ff db m"You've got the Magnifying Lens", $ff
ItemPieceOfPower:
db m"You've got a Piece of Power", $ff
MultiNamePointers: MultiNamePointers:

View File

@ -24,14 +24,10 @@ notSpecialSideView:
ld a, $06 ; giveItemMultiworld ld a, $06 ; giveItemMultiworld
rst 8 rst 8
ldh a, [$F1] ; Load active sprite variant to see if this is just a normal small key ;Show message
cp $1A
jr z, isAKey
;Show message (if not a key)
ld a, $0A ; showMessageMultiworld ld a, $0A ; showMessageMultiworld
rst 8 rst 8
isAKey:
ret ret
""")) """))
rom.patch(0x03, 0x24B7, "3E", "3E") # sanity check rom.patch(0x03, 0x24B7, "3E", "3E") # sanity check

View File

@ -505,6 +505,19 @@ class InGameHints(DefaultOnToggle):
display_name = "In-game Hints" display_name = "In-game Hints"
class ForeignItemIcons(Choice):
"""
Choose how to display foreign items.
[Guess By Name] Foreign items can look like any Link's Awakening item.
[Indicate Progression] Foreign items are either a Piece of Power (progression) or Guardian Acorn (non-progression).
"""
display_name = "Foreign Item Icons"
option_guess_by_name = 0
option_indicate_progression = 1
default = option_guess_by_name
ladx_option_groups = [ ladx_option_groups = [
OptionGroup("Goal Options", [ OptionGroup("Goal Options", [
Goal, Goal,
@ -537,6 +550,7 @@ ladx_option_groups = [
LinkPalette, LinkPalette,
Palette, Palette,
TextShuffle, TextShuffle,
ForeignItemIcons,
APTitleScreen, APTitleScreen,
GfxMod, GfxMod,
Music, Music,
@ -571,6 +585,7 @@ class LinksAwakeningOptions(PerGameCommonOptions):
gfxmod: GfxMod gfxmod: GfxMod
palette: Palette palette: Palette
text_shuffle: TextShuffle text_shuffle: TextShuffle
foreign_item_icons: ForeignItemIcons
shuffle_nightmare_keys: ShuffleNightmareKeys shuffle_nightmare_keys: ShuffleNightmareKeys
shuffle_small_keys: ShuffleSmallKeys shuffle_small_keys: ShuffleSmallKeys
shuffle_maps: ShuffleMaps shuffle_maps: ShuffleMaps

View File

@ -4,6 +4,7 @@ import os
import pkgutil import pkgutil
import tempfile import tempfile
import typing import typing
import re
import bsdiff4 import bsdiff4
@ -12,6 +13,7 @@ from BaseClasses import Entrance, Item, ItemClassification, Location, Tutorial,
from Fill import fill_restrictive from Fill import fill_restrictive
from worlds.AutoWorld import WebWorld, World from worlds.AutoWorld import WebWorld, World
from .Common import * from .Common import *
from . import ItemIconGuessing
from .Items import (DungeonItemData, DungeonItemType, ItemName, LinksAwakeningItem, TradeItemData, from .Items import (DungeonItemData, DungeonItemType, ItemName, LinksAwakeningItem, TradeItemData,
ladxr_item_to_la_item_name, links_awakening_items, links_awakening_items_by_name, ladxr_item_to_la_item_name, links_awakening_items, links_awakening_items_by_name,
links_awakening_item_name_groups) links_awakening_item_name_groups)
@ -380,66 +382,36 @@ class LinksAwakeningWorld(World):
name_cache = {} name_cache = {}
# Tries to associate an icon from another game with an icon we have # Tries to associate an icon from another game with an icon we have
def guess_icon_for_other_world(self, other): def guess_icon_for_other_world(self, foreign_item):
if not self.name_cache: if not self.name_cache:
forbidden = [
"TRADING",
"ITEM",
"BAD",
"SINGLE",
"UPGRADE",
"BLUE",
"RED",
"NOTHING",
"MESSAGE",
]
for item in ladxr_item_to_la_item_name.keys(): for item in ladxr_item_to_la_item_name.keys():
self.name_cache[item] = item self.name_cache[item] = item
splits = item.split("_") splits = item.split("_")
self.name_cache["".join(splits)] = item
if 'RUPEES' in splits:
self.name_cache["".join(reversed(splits))] = item
for word in item.split("_"): for word in item.split("_"):
if word not in forbidden and not word.isnumeric(): if word not in ItemIconGuessing.BLOCKED_ASSOCIATIONS and not word.isnumeric():
self.name_cache[word] = item self.name_cache[word] = item
others = { for name in ItemIconGuessing.SYNONYMS.values():
'KEY': 'KEY',
'COMPASS': 'COMPASS',
'BIGKEY': 'NIGHTMARE_KEY',
'MAP': 'MAP',
'FLUTE': 'OCARINA',
'SONG': 'OCARINA',
'MUSHROOM': 'TOADSTOOL',
'GLOVE': 'POWER_BRACELET',
'BOOT': 'PEGASUS_BOOTS',
'SHOE': 'PEGASUS_BOOTS',
'SHOES': 'PEGASUS_BOOTS',
'SANCTUARYHEARTCONTAINER': 'HEART_CONTAINER',
'BOSSHEARTCONTAINER': 'HEART_CONTAINER',
'HEARTCONTAINER': 'HEART_CONTAINER',
'ENERGYTANK': 'HEART_CONTAINER',
'MISSILE': 'SINGLE_ARROW',
'BOMBS': 'BOMB',
'BLUEBOOMERANG': 'BOOMERANG',
'MAGICMIRROR': 'TRADING_ITEM_MAGNIFYING_GLASS',
'MIRROR': 'TRADING_ITEM_MAGNIFYING_GLASS',
'MESSAGE': 'TRADING_ITEM_LETTER',
# TODO: Also use AP item name
}
for name in others.values():
assert name in self.name_cache, name assert name in self.name_cache, name
assert name in CHEST_ITEMS, name assert name in CHEST_ITEMS, name
self.name_cache.update(others) self.name_cache.update(ItemIconGuessing.SYNONYMS)
pluralizations = {k + "S": v for k, v in self.name_cache.items()}
self.name_cache = pluralizations | self.name_cache
uppered = foreign_item.name.upper()
foreign_game = self.multiworld.game[foreign_item.player]
phrases = ItemIconGuessing.PHRASES.copy()
if foreign_game in ItemIconGuessing.GAME_SPECIFIC_PHRASES:
phrases.update(ItemIconGuessing.GAME_SPECIFIC_PHRASES[foreign_game])
uppered = other.upper() for phrase, icon in phrases.items():
if "BIG KEY" in uppered: if phrase in uppered:
return 'NIGHTMARE_KEY' return icon
possibles = other.upper().split(" ") # pattern for breaking down camelCase, also separates out digits
rejoined = "".join(possibles) pattern = re.compile(r"(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[a-zA-Z])(?=\d)")
if rejoined in self.name_cache: possibles = pattern.sub(' ', foreign_item.name).upper()
return self.name_cache[rejoined] for ch in "[]()_":
possibles = possibles.replace(ch, " ")
possibles = possibles.split()
for name in possibles: for name in possibles:
if name in self.name_cache: if name in self.name_cache:
return self.name_cache[name] return self.name_cache[name]
@ -465,8 +437,15 @@ class LinksAwakeningWorld(World):
# If the item name contains "sword", use a sword icon, etc # If the item name contains "sword", use a sword icon, etc
# Otherwise, use a cute letter as the icon # Otherwise, use a cute letter as the icon
elif self.options.foreign_item_icons == 'guess_by_name':
loc.ladxr_item.item = self.guess_icon_for_other_world(loc.item)
loc.ladxr_item.custom_item_name = loc.item.name
else: else:
loc.ladxr_item.item = self.guess_icon_for_other_world(loc.item.name) if loc.item.advancement:
loc.ladxr_item.item = 'PIECE_OF_POWER'
else:
loc.ladxr_item.item = 'GUARDIAN_ACORN'
loc.ladxr_item.custom_item_name = loc.item.name loc.ladxr_item.custom_item_name = loc.item.name
if loc.item: if loc.item: