Archipelago/worlds/dlcquest/Items.py

164 lines
5.8 KiB
Python

import csv
import enum
import math
from dataclasses import dataclass, field
from random import Random
from typing import Dict, List, Set
from BaseClasses import Item, ItemClassification
from . import Options, data
class DLCQuestItem(Item):
game: str = "DLCQuest"
coins: int = 0
coin_suffix: str = ""
offset = 120_000
class Group(enum.Enum):
DLC = enum.auto()
DLCQuest = enum.auto()
Freemium = enum.auto()
Item = enum.auto()
Coin = enum.auto()
Trap = enum.auto()
Twice = enum.auto()
Piece = enum.auto()
Deprecated = enum.auto()
@dataclass(frozen=True)
class ItemData:
code_without_offset: offset
name: str
classification: ItemClassification
groups: Set[Group] = field(default_factory=frozenset)
def __post_init__(self):
if not isinstance(self.groups, frozenset):
super().__setattr__("groups", frozenset(self.groups))
@property
def code(self):
return offset + self.code_without_offset if self.code_without_offset is not None else None
def has_any_group(self, *group: Group) -> bool:
groups = set(group)
return bool(groups.intersection(self.groups))
def load_item_csv():
try:
from importlib.resources import files
except ImportError:
from importlib_resources import files # noqa
items = []
with files(data).joinpath("items.csv").open() as file:
item_reader = csv.DictReader(file)
for item in item_reader:
id = int(item["id"]) if item["id"] else None
classification = ItemClassification[item["classification"]]
groups = {Group[group] for group in item["groups"].split(",") if group}
items.append(ItemData(id, item["name"], classification, groups))
return items
all_items: List[ItemData] = load_item_csv()
item_table: Dict[str, ItemData] = {}
items_by_group: Dict[Group, List[ItemData]] = {}
def initialize_item_table():
item_table.update({item.name: item for item in all_items})
def initialize_groups():
for item in all_items:
for group in item.groups:
item_group = items_by_group.get(group, list())
item_group.append(item)
items_by_group[group] = item_group
initialize_item_table()
initialize_groups()
def create_trap_items(world, world_options: Options.DLCQuestOptions, trap_needed: int, random: Random) -> List[Item]:
traps = []
for i in range(trap_needed):
trap = random.choice(items_by_group[Group.Trap])
traps.append(world.create_item(trap, ItemClassification.trap))
return traps
def create_items(world, world_options: Options.DLCQuestOptions, locations_count: int, random: Random):
created_items = []
if world_options.campaign == Options.Campaign.option_basic or world_options.campaign == Options.Campaign.option_both:
create_items_basic(world_options, created_items, world)
if (world_options.campaign == Options.Campaign.option_live_freemium_or_die or
world_options.campaign == Options.Campaign.option_both):
create_items_lfod(world_options, created_items, world)
trap_items = create_trap_items(world, world_options, locations_count - len(created_items), random)
created_items += trap_items
return created_items
def create_items_lfod(world_options, created_items, world):
for item in items_by_group[Group.Freemium]:
if item.has_any_group(Group.DLC):
created_items.append(world.create_item(item))
if item.has_any_group(Group.Item) and world_options.item_shuffle == Options.ItemShuffle.option_shuffled:
created_items.append(world.create_item(item))
if item.has_any_group(Group.Twice):
created_items.append(world.create_item(item))
if world_options.coinsanity == Options.CoinSanity.option_coin:
if world_options.coinbundlequantity == -1:
create_coin_piece(created_items, world, 889, 200, Group.Freemium)
return
create_coin(world_options, created_items, world, 889, 200, Group.Freemium)
def create_items_basic(world_options, created_items, world):
for item in items_by_group[Group.DLCQuest]:
if item.has_any_group(Group.DLC):
created_items.append(world.create_item(item))
if item.has_any_group(Group.Item) and world_options.item_shuffle == Options.ItemShuffle.option_shuffled:
created_items.append(world.create_item(item))
if item.has_any_group(Group.Twice):
created_items.append(world.create_item(item))
if world_options.coinsanity == Options.CoinSanity.option_coin:
if world_options.coinbundlequantity == -1:
create_coin_piece(created_items, world, 825, 250, Group.DLCQuest)
return
create_coin(world_options, created_items, world, 825, 250, Group.DLCQuest)
def create_coin(world_options, created_items, world, total_coins, required_coins, group):
coin_bundle_required = math.ceil(required_coins / world_options.coinbundlequantity)
coin_bundle_useful = math.ceil((total_coins - coin_bundle_required * world_options.coinbundlequantity) / world_options.coinbundlequantity)
for item in items_by_group[group]:
if item.has_any_group(Group.Coin):
for i in range(coin_bundle_required):
created_items.append(world.create_item(item))
for i in range(coin_bundle_useful):
created_items.append(world.create_item(item, ItemClassification.useful))
def create_coin_piece(created_items, world, total_coins, required_coins, group):
for item in items_by_group[group]:
if item.has_any_group(Group.Piece):
for i in range(required_coins*10):
created_items.append(world.create_item(item))
for i in range((total_coins - required_coins) * 10):
created_items.append(world.create_item(item, ItemClassification.useful))