Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 105 additions & 1 deletion worlds/crosscode/codegen/lists.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,8 +15,13 @@

from ..types.items import ItemData, ProgressiveItemChainSingle, SingleItemData, ItemPoolEntry, ProgressiveItemChain
from ..types.locations import AccessInfo, LocationData
from ..types.condition import Condition, NeverCondition, RegionCondition, OrCondition, AndCondition, ShopSlotCondition
from ..types.condition import (
Condition, NeverCondition, RegionCondition,
OrCondition, AndCondition, ShopSlotCondition,
SingleTradeCondition,
)
from ..types.shops import ShopData
from ..types.traders import TraderData, SingleTrade

class LocationCategory(StrEnum):
"""
Expand DownExpand Up@@ -66,6 +71,14 @@ class ListInfo:
shop_unlock_by_shop_and_id: dict[tuple[str, int], ItemPoolEntry]
global_slot_region_conditions_list: dict[str, list[Condition]]

trader_data: dict[str, TraderData]
per_trader_locations: dict[str, dict[int, LocationData]]
global_trader_locations: dict[int, LocationData]
trader_unlock_by_id: dict[int, ItemPoolEntry]
trader_unlock_by_trader: dict[str, ItemPoolEntry]
trader_unlock_by_trader_and_id: dict[tuple[str, int], ItemPoolEntry]
global_trade_region_conditions_list: dict[str, list[Condition]]

region_botanics_amounts: dict[str, dict[str, int]] # { mode => { region => number of plants } }
botanics_internal_names_to_ids: dict[str, int]

Expand DownExpand Up@@ -112,6 +125,13 @@ def __init__(self, ctx: Context):
self.shop_unlock_by_shop_and_id = {}
self.global_slot_region_conditions_list = {}

self.trader_data = {}
self.per_trader_locations = defaultdict(dict)
self.trader_unlock_by_id = {} # unused?
self.trader_unlock_by_trader = {}
self.trader_unlock_by_trader_and_id = {}
self.global_trade_region_conditions_list = {} # ?

self.region_botanics_amounts = defaultdict(lambda: defaultdict(lambda: 0))
self.botanics_internal_names_to_ids = {}

Expand DownExpand Up@@ -462,6 +482,90 @@ def __add_shop_list(self, loc_list: dict[str, dict[str, typing.Any]]):
for name, raw_shop in loc_list.items():
self.__add_shop(name, raw_shop)

def __add_trader(self, internal_name: str, raw_trader: dict[str, typing.Any]):
# is it possible to simplify this code by combining it with the shop code?
trader_name: str = raw_trader["location"]["trader"]
area = raw_trader["location"]["area"]
area_name = self.ctx.area_names[area]

metadata = raw_trader["metadata"]
metadata["trader"] = True

access_info = self.json_parser.parse_location_access_info(raw_trader)

# it's empty, but since it's a defaultdict[list], we get an empty list
# so we can modify it in-place and it'll get reflected
locs = self.per_trader_locations[trader_name]

unlock = f"Trader Unlock: {trader_name}"
# the desired behaviour is identical for shops and traders, so can reuse
unlock_item = self.__add_shop_unlock_item(unlock)
if trader_name not in self.trader_unlock_by_trader:
self.trader_unlock_by_trader[trader_name] = ItemPoolEntry(unlock_item, 1, metadata)
self.descriptions[unlock_item.combo_id] = {
# oh no the french are invading
"en_US": fr"Unlocks \c[3]all trades\c[0] for trader \c[3]{trader_name}\c[0]."
}

trader_unlocks = self.item_groups.setdefault("Trader Unlocks", [])
if unlock_item not in trader_unlocks:
trader_unlocks.append(unlock_item)

global_item_group = self.item_groups.setdefault("Global Trader Unlocks", [])
trader_area_group = self.item_groups.setdefault(f"Trader Unlocks: {area_name}", [])

global_item_group.append(unlock_item)
trader_area_group.append(unlock_item)

trade_unlocks_group = self.item_groups.setdefault("Trade Unlocks", [])
this_trader_unlocks = self.item_groups.setdefault(f"Trade Unlocks: {trader_name}", [])

for trade_name, trade in raw_trader["trades"].items():
t_, name, count = trade["reward"]
item_data = self.ctx.rando_data["items"][name]
if t_ != "item": # all trades should give an item
continue

trade_loc_name = f"Trade: {trade_name} ({trader_name})"
locid = self.__get_or_allocate_location_id(trade_loc_name)

item_id = item_data["id"]

trade_location = LocationData(
name=trade_loc_name,
code=locid,
area=area,
metadata=metadata,
access=AccessInfo(
region={rn: trader_name for rn in access_info.region},
cond=[SingleTradeCondition(trader_name, item_id)]
)
)

self.location_groups[area_name].append(trade_location)
self.location_groups[f"{area_name} Traders"].append(trade_location)

trade_unlocks_group.append(trade_location)
this_trader_unlocks.append(trade_location)

locs[item_id] = trade_location
self.locations_data[trade_location.name] = trade_location

by_trader_and_id_name = f"Trade Unlock: {trade_name} ({trader_name})"
by_trader_and_id_item = self.__add_shop_unlock_item(by_trader_and_id_name)
self.trader_unlock_by_trader_and_id[internal_name, item_id]

self.descriptions[by_trader_and_id_item.combo_id] = {
"en_US": fr"Unlocks the trade \c[3]{trade_name}\c[0] from trader \c[3]{trader_name}\c[0]."
}

self.trader_data[trader_name] = TraderData(
internal_name=internal_name,
name=trader_name,
access=access_info,
metadata=metadata,
)

def __add_item_data_list(self, item_list: dict[str, dict[str, typing.Any]]):
"""
Add a list of items to the list.
Expand Down
9 changes: 9 additions & 0 deletions worlds/crosscode/types/condition.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -167,6 +167,15 @@ def satisfied(self, state: CollectionState, player: int, location: int | None, a
return state.has(args["shop_unlock_by_shop_and_id"][self.shop_name, self.item_id].item.name, player)
return True

@dataclass
class SingleTradeCondition(Condition):
trader_name: str
item_id: int

def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool:
# XXX: need to implement this as tradesanity gets further implemented
return True

@dataclass
class BotanicsCompletionCondition(Condition):
amount: float
Expand Down
21 changes: 21 additions & 0 deletions worlds/crosscode/types/traders.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
import typing
from dataclasses import dataclass

from .locations import AccessInfo
from .metadata import IncludeOptions
from .items import ItemData

@dataclass
class TraderData:
internal_name: str
name: str
access: AccessInfo
metadata: typing.Optional[IncludeOptions] = None

@dataclass
class SingleTrade:
display_name: str
reward: ItemData
cost: list[ItemData]
index: int