Skip to content

Commit

Permalink
LADX: Improve icon guesses for foreign items (ArchipelagoMW#2201)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* Update worlds/ladx/ItemIconGuessing.py

Co-authored-by: Scipio Wright <[email protected]>

* 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 <[email protected]>

* 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 (ArchipelagoMW#40)

* Adding FNAFW suggestions from @LOLZ1190

* missing comma

---------

Co-authored-by: threeandthreee <[email protected]>

---------

Co-authored-by: Scipio Wright <[email protected]>
Co-authored-by: NewSoupVi <[email protected]>
Co-authored-by: palex00 <[email protected]>
  • Loading branch information
4 people authored Dec 13, 2024
1 parent 8d9454e commit ccea6bc
Show file tree
Hide file tree
Showing 9 changed files with 603 additions and 62 deletions.
531 changes: 531 additions & 0 deletions worlds/ladx/ItemIconGuessing.py

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion worlds/ladx/Items.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class ItemName:
HEART_CONTAINER = "Heart Container"
BAD_HEART_CONTAINER = "Bad Heart Container"
TOADSTOOL = "Toadstool"
GUARDIAN_ACORN = "Guardian Acorn"
KEY = "Key"
KEY1 = "Small Key (Tail Cave)"
KEY2 = "Small Key (Bottle Grotto)"
Expand Down Expand Up @@ -173,6 +174,7 @@ class ItemName:
TRADING_ITEM_NECKLACE = "Necklace"
TRADING_ITEM_SCALE = "Scale"
TRADING_ITEM_MAGNIFYING_GLASS = "Magnifying Glass"
PIECE_OF_POWER = "Piece Of Power"

trade_item_prog = ItemClassification.progression

Expand Down Expand Up @@ -219,6 +221,7 @@ class ItemName:
ItemData(ItemName.HEART_CONTAINER, "HEART_CONTAINER", ItemClassification.useful),
#ItemData(ItemName.BAD_HEART_CONTAINER, "BAD_HEART_CONTAINER", ItemClassification.trap),
ItemData(ItemName.TOADSTOOL, "TOADSTOOL", ItemClassification.progression),
ItemData(ItemName.GUARDIAN_ACORN, "GUARDIAN_ACORN", ItemClassification.filler),
DungeonItemData(ItemName.KEY, "KEY", ItemClassification.progression),
DungeonItemData(ItemName.KEY1, "KEY1", ItemClassification.progression),
DungeonItemData(ItemName.KEY2, "KEY2", ItemClassification.progression),
Expand Down Expand Up @@ -293,7 +296,8 @@ class ItemName:
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_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 = {
Expand Down
4 changes: 4 additions & 0 deletions worlds/ladx/LADXR/locations/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@

TOADSTOOL: 0x50,

GUARDIAN_ACORN: 0x51,

HEART_PIECE: 0x80,
BOWWOW: 0x81,
ARROWS_10: 0x82,
Expand Down Expand Up @@ -128,4 +130,6 @@
TRADING_ITEM_NECKLACE: 0xA2,
TRADING_ITEM_SCALE: 0xA3,
TRADING_ITEM_MAGNIFYING_GLASS: 0xA4,

PIECE_OF_POWER: 0xA5,
}
4 changes: 4 additions & 0 deletions worlds/ladx/LADXR/locations/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

TOADSTOOL = "TOADSTOOL"

GUARDIAN_ACORN = "GUARDIAN_ACORN"

KEY = "KEY"
KEY1 = "KEY1"
KEY2 = "KEY2"
Expand Down Expand Up @@ -124,3 +126,5 @@
TRADING_ITEM_NECKLACE = "TRADING_ITEM_NECKLACE"
TRADING_ITEM_SCALE = "TRADING_ITEM_SCALE"
TRADING_ITEM_MAGNIFYING_GLASS = "TRADING_ITEM_MAGNIFYING_GLASS"

PIECE_OF_POWER = "PIECE_OF_POWER"
4 changes: 3 additions & 1 deletion worlds/ladx/LADXR/patches/bank3e.asm/chest.asm
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,7 @@ ItemSpriteTable:
db $46, $1C ; NIGHTMARE_KEY8
db $46, $1C ; NIGHTMARE_KEY9
db $4C, $1C ; Toadstool
db $AE, $14 ; Guardian Acorn

LargeItemSpriteTable:
db $AC, $02, $AC, $22 ; heart piece
Expand Down Expand Up @@ -874,6 +875,7 @@ LargeItemSpriteTable:
db $D8, $0D, $DA, $0D ; TradeItem12
db $DC, $0D, $DE, $0D ; TradeItem13
db $E0, $0D, $E2, $0D ; TradeItem14
db $14, $42, $14, $62 ; Piece Of Power

ItemMessageTable:
db $90, $3D, $89, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $D9, $A2
Expand All @@ -888,7 +890,7 @@ ItemMessageTable:
; $80
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, $9D
db $C9, $C9, $C9, $C9, $9D, $C9

RenderDroppedKey:
;TODO: See EntityInitKeyDropPoint for a few special cases to unload.
Expand Down
8 changes: 7 additions & 1 deletion worlds/ladx/LADXR/patches/bank3e.asm/itemnames.asm
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ ItemNamePointers:
dw ItemNameNightmareKey8
dw ItemNameNightmareKey9
dw ItemNameToadstool
dw ItemNameNone ; 0x51
dw ItemNameGuardianAcorn
dw ItemNameNone ; 0x52
dw ItemNameNone ; 0x53
dw ItemNameNone ; 0x54
Expand Down Expand Up @@ -254,6 +254,7 @@ ItemNamePointers:
dw ItemTradeQuest12
dw ItemTradeQuest13
dw ItemTradeQuest14
dw ItemPieceOfPower

ItemNameNone:
db m"NONE", $ff
Expand Down Expand Up @@ -418,6 +419,8 @@ ItemNameNightmareKey9:
db m"Got the {NIGHTMARE_KEY9}", $ff
ItemNameToadstool:
db m"Got the {TOADSTOOL}", $ff
ItemNameGuardianAcorn:
db m"Got a Guardian Acorn", $ff

ItemNameHeartPiece:
db m"Got the {HEART_PIECE}", $ff
Expand Down Expand Up @@ -496,5 +499,8 @@ ItemTradeQuest13:
db m"You've got the Scale", $ff
ItemTradeQuest14:
db m"You've got the Magnifying Lens", $ff
ItemPieceOfPower:
db m"You've got a Piece of Power", $ff

MultiNamePointers:
8 changes: 2 additions & 6 deletions worlds/ladx/LADXR/patches/droppedKey.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,10 @@ def fixDroppedKey(rom):
ld a, $06 ; giveItemMultiworld
rst 8
ldh a, [$F1] ; Load active sprite variant to see if this is just a normal small key
cp $1A
jr z, isAKey
;Show message (if not a key)
;Show message
ld a, $0A ; showMessageMultiworld
rst 8
isAKey:
ret
"""))
rom.patch(0x03, 0x24B7, "3E", "3E") # sanity check
Expand Down
15 changes: 15 additions & 0 deletions worlds/ladx/Options.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,19 @@ class InGameHints(DefaultOnToggle):
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 = [
OptionGroup("Goal Options", [
Goal,
Expand Down Expand Up @@ -537,6 +550,7 @@ class InGameHints(DefaultOnToggle):
LinkPalette,
Palette,
TextShuffle,
ForeignItemIcons,
APTitleScreen,
GfxMod,
Music,
Expand Down Expand Up @@ -571,6 +585,7 @@ class LinksAwakeningOptions(PerGameCommonOptions):
gfxmod: GfxMod
palette: Palette
text_shuffle: TextShuffle
foreign_item_icons: ForeignItemIcons
shuffle_nightmare_keys: ShuffleNightmareKeys
shuffle_small_keys: ShuffleSmallKeys
shuffle_maps: ShuffleMaps
Expand Down
85 changes: 32 additions & 53 deletions worlds/ladx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pkgutil
import tempfile
import typing
import re

import bsdiff4

Expand All @@ -12,6 +13,7 @@
from Fill import fill_restrictive
from worlds.AutoWorld import WebWorld, World
from .Common import *
from . import ItemIconGuessing
from .Items import (DungeonItemData, DungeonItemType, ItemName, LinksAwakeningItem, TradeItemData,
ladxr_item_to_la_item_name, links_awakening_items, links_awakening_items_by_name,
links_awakening_item_name_groups)
Expand Down Expand Up @@ -380,66 +382,36 @@ def priority(item):

name_cache = {}
# 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:
forbidden = [
"TRADING",
"ITEM",
"BAD",
"SINGLE",
"UPGRADE",
"BLUE",
"RED",
"NOTHING",
"MESSAGE",
]
for item in ladxr_item_to_la_item_name.keys():
self.name_cache[item] = item
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("_"):
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
others = {
'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():
for name in ItemIconGuessing.SYNONYMS.values():
assert name in self.name_cache, name
assert name in CHEST_ITEMS, name
self.name_cache.update(others)


uppered = other.upper()
if "BIG KEY" in uppered:
return 'NIGHTMARE_KEY'
possibles = other.upper().split(" ")
rejoined = "".join(possibles)
if rejoined in self.name_cache:
return self.name_cache[rejoined]
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])

for phrase, icon in phrases.items():
if phrase in uppered:
return icon
# pattern for breaking down camelCase, also separates out digits
pattern = re.compile(r"(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[a-zA-Z])(?=\d)")
possibles = pattern.sub(' ', foreign_item.name).upper()
for ch in "[]()_":
possibles = possibles.replace(ch, " ")
possibles = possibles.split()
for name in possibles:
if name in self.name_cache:
return self.name_cache[name]
Expand All @@ -465,8 +437,15 @@ def generate_output(self, output_directory: str):

# If the item name contains "sword", use a sword icon, etc
# 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:
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

if loc.item:
Expand Down

0 comments on commit ccea6bc

Please sign in to comment.