Files
Grinch-AP/worlds/zillion/logic.py
Doug Hoskisson 265ee7098a New Game: Zillion (#1081)
* Option RangeWithSpecialMax

* amendment to typing in web options

* compare string with number

* lots of work on zillion

* fix zillion fill logic

* fix a few more issues in zillion fill logic

* can make zillion patch and use it

* put multi items in zillion rom

* work on ZillionClient

* logging and auth in client

* work on sending and receiving items

* implement item_handling flag

* fix locations ids to NuktiServer package

* use rewrite of zri

* cache logic rule data for performance

* use new id maps

* fix some problems with the big recent merge

* ZillionClient: use new context manager for Memory class

* fix ItemClassification for Zillion items
and some debug statements for asserts,
documentation on running scripts for manual testing
type correction in CommonContext

* fix some issues in client, start on docs, put rescue and item ram addresses in slot data

* use new location name system
fix item locations getting out of sync in progression balancing

* zillion client can read slot name from game

* zillion: new item names

* remove extra unneeded import

* newer options (room gen and starting cards)

* update comment in zillion patch

* zillion non static regions

* change some logging, update some comments

* allow ZillionClient to exit in certain situations

* todo note to fix options doc strings

* don't force auto forfeit

* rework validation of floppy requirement and item counts
and fix race condition in generate_output

* reorganize Zillion component structure
with System class

* documentation updates for Zillion

* attempt inno_setup.iss

* remove todo comment for something done

* update comment

* rework item count zillion options
and some small cleanups

* fix location check count

* data package version 1

* Zillion can pass unit tests without rom

* fix freeze if closing ZillionClient while it's waiting for server login

* specify commit hash for zilliandomizer package

* some changes to options validation

* Zillion doors saved on multiworld server

* add missing function in inno_setup
and name of vanilla continues in options

* rework zillion sync task and context

* Apply documentation suggestions from SoldierofOrder

Co-authored-by: SoldierofOrder <107806872+SoldierofOrder@users.noreply.github.com>

* update zillion package

* workaround for asyncio udp bug

There is a bug in Python in Windows
https://github.com/python/cpython/issues/91227
that makes it so if I look for RetroArch before it's ready, it breaks the asyncio udp transport system.

As a workaround, we don't look for RetroArch until the user asks for it with /sms

* a few of the smaller suggestions from review

* logic only looks at my locations
instead of all the multiworld locations

* some adjustments from pull request discussion
and some unit tests

* patch webhost changes from pull request discussion

* zillion logic tests

* better vblr test

* test interaction of character rescue items with logic

* move unit tests to new worlds folder

* comment improvements

* fix minor logic issue
and add memory read timeout

* capitalization in option display names
Opa-Opa is a proper noun

* redirect zz stdout to debug

* fix option validation bug making unbeatable seeds

* remove line that does nothing

* attach logic cache to world

Co-authored-by: SoldierofOrder <107806872+SoldierofOrder@users.noreply.github.com>
Co-authored-by: Doug Hoskisson <doughoskisson@novuslabs.com>
2022-10-20 19:41:11 +02:00

78 lines
2.8 KiB
Python

from typing import Dict, FrozenSet, Tuple, cast, List, Counter as _Counter
from BaseClasses import CollectionState
from zilliandomizer.logic_components.locations import Location
from zilliandomizer.randomizer import Randomizer
from zilliandomizer.logic_components.items import Item, items
from .region import ZillionLocation
from .item import ZillionItem
from .id_maps import item_name_to_id
zz_empty = items[4]
# TODO: unit tests for these
def set_randomizer_locs(cs: CollectionState, p: int, zz_r: Randomizer) -> int:
"""
sync up zilliandomizer locations with archipelago locations
returns a hash of the player and of the set locations with their items
"""
z_world = cs.world.worlds[p]
my_locations = cast(List[ZillionLocation], getattr(z_world, "my_locations"))
_hash = p
for z_loc in my_locations:
zz_name = z_loc.zz_loc.name
zz_item = z_loc.item.zz_item \
if isinstance(z_loc.item, ZillionItem) and z_loc.item.player == p \
else zz_empty
zz_r.locations[zz_name].item = zz_item
_hash += hash(zz_name) ^ hash(zz_item)
return _hash
def item_counts(cs: CollectionState, p: int) -> Tuple[Tuple[str, int], ...]:
"""
the zilliandomizer items that player p has collected
((item_name, count), (item_name, count), ...)
"""
return tuple((item_name, cs.item_count(item_name, p)) for item_name in item_name_to_id)
LogicCacheType = Dict[int, Tuple[_Counter[Tuple[str, int]], FrozenSet[Location]]]
def cs_to_zz_locs(cs: CollectionState, p: int, zz_r: Randomizer, id_to_zz_item: Dict[int, Item]) -> FrozenSet[Location]:
"""
given an Archipelago `CollectionState`,
returns frozenset of accessible zilliandomizer locations
"""
# caching this function because it would be slow
logic_cache: LogicCacheType = getattr(cs.world, "zillion_logic_cache", {})
_hash = set_randomizer_locs(cs, p, zz_r)
counts = item_counts(cs, p)
_hash += hash(counts)
if _hash in logic_cache and logic_cache[_hash][0] == cs.prog_items:
# print("cache hit")
return logic_cache[_hash][1]
# print("cache miss")
have_items: List[Item] = []
for name, count in counts:
have_items.extend([id_to_zz_item[item_name_to_id[name]]] * count)
# have_req is the result of converting AP CollectionState to zilliandomizer collection state
have_req = zz_r.make_ability(have_items)
# This `get_locations` is where the core of the logic comes in.
# It takes a zilliandomizer collection state (a set of the abilities that I have)
# and returns list of all the zilliandomizer locations I can access with those abilities.
tr = frozenset(zz_r.get_locations(have_req))
# save result in cache
logic_cache[_hash] = (cs.prog_items.copy(), tr)
return tr