Archipelago/worlds/raft/__init__.py

163 lines
7.4 KiB
Python

import typing
import random
from .Locations import location_table, lookup_name_to_id as locations_lookup_name_to_id
from .Items import (createResourcePackName, item_table, progressive_table, progressive_item_list,
lookup_name_to_item, resourcepack_items as resourcePackItems, lookup_name_to_id as items_lookup_name_to_id)
from .Regions import create_regions, getConnectionName
from .Rules import set_rules
from .Options import raft_options
from BaseClasses import Region, RegionType, Entrance, Location, MultiWorld, Item
from ..AutoWorld import World
class RaftWorld(World):
"""
Raft is a flooded world exploration game. You're stranded on a small raft in the middle of the
ocean, and you must survive on trash floating by you on the top of the water and around/on any
islands that you come across.
"""
game: str = "Raft"
item_name_to_id = items_lookup_name_to_id.copy()
lastItemId = max(filter(lambda val: val is not None, item_name_to_id.values()))
location_name_to_id = locations_lookup_name_to_id
options = raft_options
data_version = 1
def generate_basic(self):
minRPSpecified = self.world.minimum_resource_pack_amount[self.player].value
maxRPSpecified = self.world.maximum_resource_pack_amount[self.player].value
minimumResourcePackAmount = min(minRPSpecified, maxRPSpecified)
maximumResourcePackAmount = max(minRPSpecified, maxRPSpecified)
# Generate item pool
pool = []
for item in item_table:
raft_item = self.create_item_replaceAsNecessary(item["name"])
pool.append(raft_item)
extraItemNamePool = []
extras = len(location_table) - len(item_table) - 1 # Victory takes up 1 unaccounted-for slot
if extras > 0:
if (self.world.use_resource_packs[self.player].value):
for packItem in resourcePackItems:
for i in range(minimumResourcePackAmount, maximumResourcePackAmount + 1):
extraItemNamePool.append(createResourcePackName(i, packItem))
if self.world.duplicate_items[self.player].value != 0:
dupeItemPool = item_table.copy()
# Remove frequencies if necessary
if self.world.island_frequency_locations[self.player].value != 3: # Not completely random locations
dupeItemPool = (itm for itm in dupeItemPool if "Frequency" not in itm["name"])
# Remove progression or non-progression items if necessary
if (self.world.duplicate_items[self.player].value == 1): # Progression only
dupeItemPool = (itm for itm in dupeItemPool if itm["progression"] == True)
elif (self.world.duplicate_items[self.player].value == 2): # Non-progression only
dupeItemPool = (itm for itm in dupeItemPool if itm["progression"] == False)
dupeItemPool = list(dupeItemPool)
# Finally, add items as necessary
if len(dupeItemPool) > 0:
for item in dupeItemPool:
extraItemNamePool.append(item["name"])
if (len(extraItemNamePool) > 0):
for randomItem in random.choices(extraItemNamePool, k=extras):
raft_item = self.create_item_replaceAsNecessary(randomItem)
pool.append(raft_item)
self.world.itempool += pool
def set_rules(self):
set_rules(self.world, self.player)
def create_regions(self):
create_regions(self.world, self.player)
def fill_slot_data(self):
slot_data = {}
return slot_data
def create_item_replaceAsNecessary(self, name: str) -> Item:
isFrequency = "Frequency" in name
shouldUseProgressive = ((isFrequency and self.world.island_frequency_locations[self.player].value == 2)
or (not isFrequency and self.world.progressive_items[self.player].value))
if shouldUseProgressive and name in progressive_table:
name = progressive_table[name]
return self.create_item(name)
def create_item(self, name: str) -> Item:
item = lookup_name_to_item[name]
return RaftItem(name, item["progression"], self.item_name_to_id[name], player=self.player)
def create_resourcePack(self, rpName: str) -> Item:
return RaftItem(rpName, False, self.item_name_to_id[rpName], player=self.player)
def collect_item(self, state, item, remove=False):
if item.name in progressive_item_list:
prog_table = progressive_item_list[item.name]
if remove:
for item_name in reversed(prog_table):
if state.has(item_name, item.player):
return item_name
else:
for item_name in prog_table:
if not state.has(item_name, item.player):
return item_name
return super(RaftWorld, self).collect_item(state, item, remove)
def get_required_client_version(self) -> typing.Tuple[int, int, int]:
return max((0, 2, 0), super(RaftWorld, self).get_required_client_version())
def pre_fill(self):
if self.world.island_frequency_locations[self.player] == 0:
self.setLocationItem("Radio Tower Frequency to Vasagatan", "Vasagatan Frequency")
self.setLocationItem("Vasagatan Frequency to Balboa", "Balboa Island Frequency")
self.setLocationItem("Relay Station quest", "Caravan Island Frequency")
self.setLocationItem("Caravan Island Frequency to Tangaroa", "Tangaroa Frequency")
elif self.world.island_frequency_locations[self.player] == 1:
self.setLocationItemFromRegion("RadioTower", "Vasagatan Frequency")
self.setLocationItemFromRegion("Vasagatan", "Balboa Island Frequency")
self.setLocationItemFromRegion("BalboaIsland", "Caravan Island Frequency")
self.setLocationItemFromRegion("CaravanIsland", "Tangaroa Frequency")
# Victory item
self.world.get_location("Tangaroa Next Frequency", self.player).place_locked_item(
RaftItem("Victory", True, None, player=self.player))
def setLocationItem(self, location: str, itemName: str):
itemToUse = next(filter(lambda itm: itm.name == itemName, self.world.itempool))
self.world.itempool.remove(itemToUse)
self.world.get_location(location, self.player).place_locked_item(itemToUse)
def setLocationItemFromRegion(self, region: str, itemName: str):
itemToUse = next(filter(lambda itm: itm.name == itemName, self.world.itempool))
self.world.itempool.remove(itemToUse)
location = random.choice(list(loc for loc in location_table if loc["region"] == region))
self.world.get_location(location["name"], self.player).place_locked_item(itemToUse)
def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None):
ret = Region(name, RegionType.Generic, name, player)
ret.world = world
if locations:
for location in locations:
loc_id = locations_lookup_name_to_id.get(location, 0)
locationObj = RaftLocation(player, location, loc_id, ret)
ret.locations.append(locationObj)
if exits:
for exit in exits:
ret.exits.append(Entrance(player, getConnectionName(name, exit), ret))
return ret
class RaftLocation(Location):
game = "Raft"
class RaftItem(Item):
game = "Raft"