Files
dockipelago/worlds/cluster_truck/__init__.py
Jonathan Tinney 7971961166
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
add schedule I, sonic 1/frontiers/heroes, spirit island
2026-04-02 23:46:36 -07:00

136 lines
6.1 KiB
Python

from typing import Dict, List, Any, Union, Optional, Mapping
from BaseClasses import Location, Item, Tutorial, ItemClassification, Region
from worlds.AutoWorld import World, WebWorld
from .Items import item_list, base_id, ItemType
from .Locations import location_list, CTLocation
from .Helpers import format_level_name, parse_level_name
from .Options import ClusterTruckOptions
from ..generic.Rules import set_rule
class ClusterTruckItem(Item):
game = "ClusterTruck"
def __init__(self, name: str, classification: ItemClassification, code: Optional[int], player: int) -> None:
super().__init__(name, classification, code, player)
class ClusterTruckLocation(Location):
game = "ClusterTruck"
class ClusterTruckWeb(WebWorld):
tutorials = [Tutorial(
"Multiworld Setup Guide",
"a guide to setting up ClusterTruck randomizer and connecting to an Archipelago Multiworld",
"English",
"en_setup.md",
"setup/en",
["Nullctipus"]
)]
class ClusterTruckWorld(World):
"""ClusterTruck is a new kind of platformer on-top of a speeding highway!"""
game = "ClusterTruck"
web = ClusterTruckWeb()
item_name_to_id = {item.name: (base_id + index) for index, item in enumerate(item_list)}
location_name_to_id = {loc.name: (base_id + index) for index, loc in enumerate(location_list)}
item_name_groups = {
"Abilities": {item.name for item in item_list if item.type == ItemType.Ability},
"Levels": {item.name for item in item_list if item.type == ItemType.Level},
"Traps": {item.name for item in item_list if item.type == ItemType.Trap},
"Filler": {item.name for item in item_list if item.type == ItemType.Filler},
}
options_dataclass = ClusterTruckOptions
options = ClusterTruckOptions
item_type_classification: Dict[ItemType, ItemClassification] = {
ItemType.Ability: ItemClassification.useful,
ItemType.Level: ItemClassification.progression_skip_balancing,
ItemType.Trap: ItemClassification.trap,
ItemType.Filler: ItemClassification.filler,
}
skipped_level: List[int]
all_selected_locations: List[CTLocation]
start_level_name: str
goal_level_name: str
def generate_early(self) -> None:
self.goal_level_name = format_level_name(self.options.goal_level.value)
self.start_level_name = format_level_name(self.options.start_level.value)
self.skipped_level = [parse_level_name(skip)
for skip in self.options.skipped_levels.value]
self.all_selected_locations = [location for location in location_list if location
and location.game_id not in self.skipped_level
and location.game_id != self.options.goal_level.value]
def get_filler_item_name(self) -> str:
if self.random.random() <= self.options.trap_percentage.value:
return self.random.choice([item.name for item in item_list if item.type == ItemType.Trap])
return self.random.choice([item.name for item in item_list if item.type == ItemType.Filler])
def create_item(self, name: str) -> "Item":
location = item_list[self.item_name_to_id[name] - base_id]
return ClusterTruckItem(name, self.item_type_classification[location.type],
self.item_name_to_id[name], self.player)
def create_items(self) -> None:
for location in self.all_selected_locations:
if location.game_id > len(location_list):
break
try:
if (location.game_id != self.options.start_level.value
and location.game_id != self.options.goal_level.value):
self.multiworld.itempool.append(self.create_item(location.name))
except Exception as e:
print(location.name)
raise e
victory: Location = self.get_location(self.goal_level_name)
victory.place_locked_item(ClusterTruckItem("Victory", ItemClassification.progression_skip_balancing
, None, self.player))
# there needs to be one more item /shrug
self.multiworld.itempool.append(self.create_item(self.get_filler_item_name()))
def create_regions(self) -> None:
menu_region = Region("Menu", self.player, self.multiworld)
self.multiworld.regions += [menu_region]
all_selected_locations_copy = self.all_selected_locations.copy()
self.random.shuffle(all_selected_locations_copy)
for location in all_selected_locations_copy:
menu_region.locations.append(ClusterTruckLocation(
self.player, location.name, base_id + location.game_id, menu_region))
menu_region.locations.append(ClusterTruckLocation(self.player, self.goal_level_name, None, menu_region))
def set_rules(self) -> None:
for i in range(105):
if i == self.options.start_level.value or i == self.options.goal_level.value or i in self.skipped_level:
continue
name = format_level_name(i)
set_rule(self.get_location(name), lambda state, name=name: state.has(name, self.player))
self.multiworld.completion_condition[self.player] = lambda state: state.has_from_list_unique(
[item.name for item in item_list if
item.type == ItemType.Level and item.name is not self.goal_level_name and
item.name is not self.start_level_name and item.name not in self.options.skipped_levels.value],
self.player, self.options.goal_requirement.value)
def fill_slot_data(self) -> Mapping[str, Any]:
slot_data: Mapping[str, Any] = {
"version": "1.3.0",
"start": self.start_level_name,
"goal": self.goal_level_name,
"goal_requirement": int(self.options.goal_requirement.value),
"point_multiplier": int(self.options.point_multiplier.value),
"deathlink_amnesty": int(self.options.deathlink_amnesty.value),
"base_id": int(base_id),
}
return slot_data