Skip to content

Commit ccea6bc

Browse files
threeandthreeeScipioWrightNewSoupVipalex00
authored
LADX: Improve icon guesses for foreign items (ArchipelagoMW#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>
1 parent 8d9454e commit ccea6bc

File tree

9 files changed

+603
-62
lines changed

9 files changed

+603
-62
lines changed

worlds/ladx/ItemIconGuessing.py

+531
Large diffs are not rendered by default.

worlds/ladx/Items.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class ItemName:
9898
HEART_CONTAINER = "Heart Container"
9999
BAD_HEART_CONTAINER = "Bad Heart Container"
100100
TOADSTOOL = "Toadstool"
101+
GUARDIAN_ACORN = "Guardian Acorn"
101102
KEY = "Key"
102103
KEY1 = "Small Key (Tail Cave)"
103104
KEY2 = "Small Key (Bottle Grotto)"
@@ -173,6 +174,7 @@ class ItemName:
173174
TRADING_ITEM_NECKLACE = "Necklace"
174175
TRADING_ITEM_SCALE = "Scale"
175176
TRADING_ITEM_MAGNIFYING_GLASS = "Magnifying Glass"
177+
PIECE_OF_POWER = "Piece Of Power"
176178

177179
trade_item_prog = ItemClassification.progression
178180

@@ -219,6 +221,7 @@ class ItemName:
219221
ItemData(ItemName.HEART_CONTAINER, "HEART_CONTAINER", ItemClassification.useful),
220222
#ItemData(ItemName.BAD_HEART_CONTAINER, "BAD_HEART_CONTAINER", ItemClassification.trap),
221223
ItemData(ItemName.TOADSTOOL, "TOADSTOOL", ItemClassification.progression),
224+
ItemData(ItemName.GUARDIAN_ACORN, "GUARDIAN_ACORN", ItemClassification.filler),
222225
DungeonItemData(ItemName.KEY, "KEY", ItemClassification.progression),
223226
DungeonItemData(ItemName.KEY1, "KEY1", ItemClassification.progression),
224227
DungeonItemData(ItemName.KEY2, "KEY2", ItemClassification.progression),
@@ -293,7 +296,8 @@ class ItemName:
293296
TradeItemData(ItemName.TRADING_ITEM_FISHING_HOOK, "TRADING_ITEM_FISHING_HOOK", trade_item_prog, "Grandma (Animal Village)"),
294297
TradeItemData(ItemName.TRADING_ITEM_NECKLACE, "TRADING_ITEM_NECKLACE", trade_item_prog, "Fisher (Martha's Bay)"),
295298
TradeItemData(ItemName.TRADING_ITEM_SCALE, "TRADING_ITEM_SCALE", trade_item_prog, "Mermaid (Martha's Bay)"),
296-
TradeItemData(ItemName.TRADING_ITEM_MAGNIFYING_GLASS, "TRADING_ITEM_MAGNIFYING_GLASS", trade_item_prog, "Mermaid Statue (Martha's Bay)")
299+
TradeItemData(ItemName.TRADING_ITEM_MAGNIFYING_GLASS, "TRADING_ITEM_MAGNIFYING_GLASS", trade_item_prog, "Mermaid Statue (Martha's Bay)"),
300+
ItemData(ItemName.PIECE_OF_POWER, "PIECE_OF_POWER", ItemClassification.filler),
297301
]
298302

299303
ladxr_item_to_la_item_name = {

worlds/ladx/LADXR/locations/constants.py

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@
8787

8888
TOADSTOOL: 0x50,
8989

90+
GUARDIAN_ACORN: 0x51,
91+
9092
HEART_PIECE: 0x80,
9193
BOWWOW: 0x81,
9294
ARROWS_10: 0x82,
@@ -128,4 +130,6 @@
128130
TRADING_ITEM_NECKLACE: 0xA2,
129131
TRADING_ITEM_SCALE: 0xA3,
130132
TRADING_ITEM_MAGNIFYING_GLASS: 0xA4,
133+
134+
PIECE_OF_POWER: 0xA5,
131135
}

worlds/ladx/LADXR/locations/items.py

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444

4545
TOADSTOOL = "TOADSTOOL"
4646

47+
GUARDIAN_ACORN = "GUARDIAN_ACORN"
48+
4749
KEY = "KEY"
4850
KEY1 = "KEY1"
4951
KEY2 = "KEY2"
@@ -124,3 +126,5 @@
124126
TRADING_ITEM_NECKLACE = "TRADING_ITEM_NECKLACE"
125127
TRADING_ITEM_SCALE = "TRADING_ITEM_SCALE"
126128
TRADING_ITEM_MAGNIFYING_GLASS = "TRADING_ITEM_MAGNIFYING_GLASS"
129+
130+
PIECE_OF_POWER = "PIECE_OF_POWER"

worlds/ladx/LADXR/patches/bank3e.asm/chest.asm

+3-1
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ ItemSpriteTable:
835835
db $46, $1C ; NIGHTMARE_KEY8
836836
db $46, $1C ; NIGHTMARE_KEY9
837837
db $4C, $1C ; Toadstool
838+
db $AE, $14 ; Guardian Acorn
838839

839840
LargeItemSpriteTable:
840841
db $AC, $02, $AC, $22 ; heart piece
@@ -874,6 +875,7 @@ LargeItemSpriteTable:
874875
db $D8, $0D, $DA, $0D ; TradeItem12
875876
db $DC, $0D, $DE, $0D ; TradeItem13
876877
db $E0, $0D, $E2, $0D ; TradeItem14
878+
db $14, $42, $14, $62 ; Piece Of Power
877879

878880
ItemMessageTable:
879881
db $90, $3D, $89, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $D9, $A2
@@ -888,7 +890,7 @@ ItemMessageTable:
888890
; $80
889891
db $4F, $C8, $CA, $CB, $E2, $E3, $E4, $CC, $CD, $2A, $2B, $C9, $C9, $C9, $C9, $C9
890892
db $C9, $C9, $C9, $C9, $C9, $C9, $B8, $44, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9
891-
db $C9, $C9, $C9, $C9, $9D
893+
db $C9, $C9, $C9, $C9, $9D, $C9
892894

893895
RenderDroppedKey:
894896
;TODO: See EntityInitKeyDropPoint for a few special cases to unload.

worlds/ladx/LADXR/patches/bank3e.asm/itemnames.asm

+7-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ ItemNamePointers:
170170
dw ItemNameNightmareKey8
171171
dw ItemNameNightmareKey9
172172
dw ItemNameToadstool
173-
dw ItemNameNone ; 0x51
173+
dw ItemNameGuardianAcorn
174174
dw ItemNameNone ; 0x52
175175
dw ItemNameNone ; 0x53
176176
dw ItemNameNone ; 0x54
@@ -254,6 +254,7 @@ ItemNamePointers:
254254
dw ItemTradeQuest12
255255
dw ItemTradeQuest13
256256
dw ItemTradeQuest14
257+
dw ItemPieceOfPower
257258

258259
ItemNameNone:
259260
db m"NONE", $ff
@@ -418,6 +419,8 @@ ItemNameNightmareKey9:
418419
db m"Got the {NIGHTMARE_KEY9}", $ff
419420
ItemNameToadstool:
420421
db m"Got the {TOADSTOOL}", $ff
422+
ItemNameGuardianAcorn:
423+
db m"Got a Guardian Acorn", $ff
421424

422425
ItemNameHeartPiece:
423426
db m"Got the {HEART_PIECE}", $ff
@@ -496,5 +499,8 @@ ItemTradeQuest13:
496499
db m"You've got the Scale", $ff
497500
ItemTradeQuest14:
498501
db m"You've got the Magnifying Lens", $ff
502+
503+
ItemPieceOfPower:
504+
db m"You've got a Piece of Power", $ff
499505

500506
MultiNamePointers:

worlds/ladx/LADXR/patches/droppedKey.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,10 @@ def fixDroppedKey(rom):
2424
ld a, $06 ; giveItemMultiworld
2525
rst 8
2626
27-
ldh a, [$F1] ; Load active sprite variant to see if this is just a normal small key
28-
cp $1A
29-
jr z, isAKey
30-
31-
;Show message (if not a key)
27+
;Show message
3228
ld a, $0A ; showMessageMultiworld
3329
rst 8
34-
isAKey:
30+
3531
ret
3632
"""))
3733
rom.patch(0x03, 0x24B7, "3E", "3E") # sanity check

worlds/ladx/Options.py

+15
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,19 @@ class InGameHints(DefaultOnToggle):
505505
display_name = "In-game Hints"
506506

507507

508+
509+
class ForeignItemIcons(Choice):
510+
"""
511+
Choose how to display foreign items.
512+
[Guess By Name] Foreign items can look like any Link's Awakening item.
513+
[Indicate Progression] Foreign items are either a Piece of Power (progression) or Guardian Acorn (non-progression).
514+
"""
515+
display_name = "Foreign Item Icons"
516+
option_guess_by_name = 0
517+
option_indicate_progression = 1
518+
default = option_guess_by_name
519+
520+
508521
ladx_option_groups = [
509522
OptionGroup("Goal Options", [
510523
Goal,
@@ -537,6 +550,7 @@ class InGameHints(DefaultOnToggle):
537550
LinkPalette,
538551
Palette,
539552
TextShuffle,
553+
ForeignItemIcons,
540554
APTitleScreen,
541555
GfxMod,
542556
Music,
@@ -571,6 +585,7 @@ class LinksAwakeningOptions(PerGameCommonOptions):
571585
gfxmod: GfxMod
572586
palette: Palette
573587
text_shuffle: TextShuffle
588+
foreign_item_icons: ForeignItemIcons
574589
shuffle_nightmare_keys: ShuffleNightmareKeys
575590
shuffle_small_keys: ShuffleSmallKeys
576591
shuffle_maps: ShuffleMaps

worlds/ladx/__init__.py

+32-53
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pkgutil
55
import tempfile
66
import typing
7+
import re
78

89
import bsdiff4
910

@@ -12,6 +13,7 @@
1213
from Fill import fill_restrictive
1314
from worlds.AutoWorld import WebWorld, World
1415
from .Common import *
16+
from . import ItemIconGuessing
1517
from .Items import (DungeonItemData, DungeonItemType, ItemName, LinksAwakeningItem, TradeItemData,
1618
ladxr_item_to_la_item_name, links_awakening_items, links_awakening_items_by_name,
1719
links_awakening_item_name_groups)
@@ -380,66 +382,36 @@ def priority(item):
380382

381383
name_cache = {}
382384
# Tries to associate an icon from another game with an icon we have
383-
def guess_icon_for_other_world(self, other):
385+
def guess_icon_for_other_world(self, foreign_item):
384386
if not self.name_cache:
385-
forbidden = [
386-
"TRADING",
387-
"ITEM",
388-
"BAD",
389-
"SINGLE",
390-
"UPGRADE",
391-
"BLUE",
392-
"RED",
393-
"NOTHING",
394-
"MESSAGE",
395-
]
396387
for item in ladxr_item_to_la_item_name.keys():
397388
self.name_cache[item] = item
398389
splits = item.split("_")
399-
self.name_cache["".join(splits)] = item
400-
if 'RUPEES' in splits:
401-
self.name_cache["".join(reversed(splits))] = item
402-
403390
for word in item.split("_"):
404-
if word not in forbidden and not word.isnumeric():
391+
if word not in ItemIconGuessing.BLOCKED_ASSOCIATIONS and not word.isnumeric():
405392
self.name_cache[word] = item
406-
others = {
407-
'KEY': 'KEY',
408-
'COMPASS': 'COMPASS',
409-
'BIGKEY': 'NIGHTMARE_KEY',
410-
'MAP': 'MAP',
411-
'FLUTE': 'OCARINA',
412-
'SONG': 'OCARINA',
413-
'MUSHROOM': 'TOADSTOOL',
414-
'GLOVE': 'POWER_BRACELET',
415-
'BOOT': 'PEGASUS_BOOTS',
416-
'SHOE': 'PEGASUS_BOOTS',
417-
'SHOES': 'PEGASUS_BOOTS',
418-
'SANCTUARYHEARTCONTAINER': 'HEART_CONTAINER',
419-
'BOSSHEARTCONTAINER': 'HEART_CONTAINER',
420-
'HEARTCONTAINER': 'HEART_CONTAINER',
421-
'ENERGYTANK': 'HEART_CONTAINER',
422-
'MISSILE': 'SINGLE_ARROW',
423-
'BOMBS': 'BOMB',
424-
'BLUEBOOMERANG': 'BOOMERANG',
425-
'MAGICMIRROR': 'TRADING_ITEM_MAGNIFYING_GLASS',
426-
'MIRROR': 'TRADING_ITEM_MAGNIFYING_GLASS',
427-
'MESSAGE': 'TRADING_ITEM_LETTER',
428-
# TODO: Also use AP item name
429-
}
430-
for name in others.values():
393+
for name in ItemIconGuessing.SYNONYMS.values():
431394
assert name in self.name_cache, name
432395
assert name in CHEST_ITEMS, name
433-
self.name_cache.update(others)
434-
435-
436-
uppered = other.upper()
437-
if "BIG KEY" in uppered:
438-
return 'NIGHTMARE_KEY'
439-
possibles = other.upper().split(" ")
440-
rejoined = "".join(possibles)
441-
if rejoined in self.name_cache:
442-
return self.name_cache[rejoined]
396+
self.name_cache.update(ItemIconGuessing.SYNONYMS)
397+
pluralizations = {k + "S": v for k, v in self.name_cache.items()}
398+
self.name_cache = pluralizations | self.name_cache
399+
400+
uppered = foreign_item.name.upper()
401+
foreign_game = self.multiworld.game[foreign_item.player]
402+
phrases = ItemIconGuessing.PHRASES.copy()
403+
if foreign_game in ItemIconGuessing.GAME_SPECIFIC_PHRASES:
404+
phrases.update(ItemIconGuessing.GAME_SPECIFIC_PHRASES[foreign_game])
405+
406+
for phrase, icon in phrases.items():
407+
if phrase in uppered:
408+
return icon
409+
# pattern for breaking down camelCase, also separates out digits
410+
pattern = re.compile(r"(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[a-zA-Z])(?=\d)")
411+
possibles = pattern.sub(' ', foreign_item.name).upper()
412+
for ch in "[]()_":
413+
possibles = possibles.replace(ch, " ")
414+
possibles = possibles.split()
443415
for name in possibles:
444416
if name in self.name_cache:
445417
return self.name_cache[name]
@@ -465,8 +437,15 @@ def generate_output(self, output_directory: str):
465437

466438
# If the item name contains "sword", use a sword icon, etc
467439
# Otherwise, use a cute letter as the icon
440+
elif self.options.foreign_item_icons == 'guess_by_name':
441+
loc.ladxr_item.item = self.guess_icon_for_other_world(loc.item)
442+
loc.ladxr_item.custom_item_name = loc.item.name
443+
468444
else:
469-
loc.ladxr_item.item = self.guess_icon_for_other_world(loc.item.name)
445+
if loc.item.advancement:
446+
loc.ladxr_item.item = 'PIECE_OF_POWER'
447+
else:
448+
loc.ladxr_item.item = 'GUARDIAN_ACORN'
470449
loc.ladxr_item.custom_item_name = loc.item.name
471450

472451
if loc.item:

0 commit comments

Comments
 (0)