9d0fa5fe8a8892334b2402424cf469ce2045d926
[sicpelago] / apworld / sicp / __init__.py
1 import itertools
2 import logging
3 import os
4 import sys
5 import yaml
6
7 from typing import Any
8
9 import BaseClasses
10 from BaseClasses import ItemClassification, Region
11
12 from worlds.AutoWorld import World
13 from worlds.LauncherComponents import Component, SuffixIdentifier, components, Type, launch
14
15 from .locations import all_locations, Location, LocationData, OriginRegionName, set_up_rules
16
17 GAME = "SICPelago"
18
19 class Item(BaseClasses.Item):
20     game = GAME
21
22 class ItemData:
23     def __init__(self, data: dict[str, Any]):
24         self.data = data
25     def __str__(self):
26         return self.data['name']
27     def id(self):
28         return self.data['id']
29     def kind(self) -> ItemClassification:
30         kind = self.data.get('kind')
31         if kind == 'progression':
32             return ItemClassification.progression
33         if kind == 'useful_progression':
34             return ItemClassification.progression | ItemClassification.useful
35         if kind == 'useful':
36             return ItemClassification.useful
37         if kind == 'progression_skip_balancing':
38             return ItemClassification.progression_skip_balancing
39         return ItemClassification.filler
40
41 with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'items.yml'), 'r') as input:
42     all_items = {data['name']: ItemData(data) for data in yaml.safe_load(input)}
43
44
45 class SicpWorld(World):
46     game = GAME
47     topology_present = True
48     item_name_to_id = {k: v.id() for k,v in all_items.items()}
49     location_name_to_id = {**{f"{loc} A": 10 * loc.id() for loc in all_locations},
50                            **{f"{loc} B": 10 * loc.id() + 1 for loc in all_locations}}
51     origin_region_name = OriginRegionName
52
53     def create_item(self, name: str) -> Item:
54         if name == 'junk':
55             return Item(name, ItemClassification.filler, 0, self.player)
56         data = all_items[name]
57         return Item(name, data.kind(), data.id(), self.player)
58
59     def create_regions(self) -> None:
60         repl = Region(self.origin_region_name, self.player, self.multiworld)
61         self.multiworld.regions.append(repl)
62
63         # TODO: logic
64         for loc in all_locations:
65             region = Region(str(loc), self.player, self.multiworld)
66             self.multiworld.regions.append(region)
67             region.locations = [
68                 Location(self.player, f"{loc} A", 10 * loc.id(), region),
69                 Location(self.player, f"{loc} B", 10 * loc.id() + 1, region)
70             ]
71             set_up_rules(loc, repl, region, self.player)
72
73     def create_items(self) -> None:
74         exclude = [item for item in self.multiworld.precollected_items[self.player]]
75
76         for item in map(self.create_item, all_items):
77             if item in exclude:
78                 exclude.remove(item)  # this is destructive. create unique list above
79                 self.multiworld.itempool.append(self.create_item("junk"))
80             else:
81                 self.multiworld.itempool.append(item)
82
83         # FIXME: need six traps later
84         self.multiworld.itempool.append(self.create_item("junk"))
85         self.multiworld.itempool.append(self.create_item("junk"))
86         self.multiworld.itempool.append(self.create_item("junk"))
87         self.multiworld.itempool.append(self.create_item("junk"))
88         self.multiworld.itempool.append(self.create_item("junk"))
89         self.multiworld.itempool.append(self.create_item("junk"))
90
91         all_macguffins = [str(x) for x in all_items.values() if x.id() < 32]
92         self.multiworld.completion_condition[self.player] = lambda state: state.has_all(all_macguffins, self.player)
93
94 def launch_client(*args) -> None:
95     from . import client
96     launch(client.run, name="SICPelago", args=args)
97
98 components.append(Component('SICPelago', 'sicp', func=launch_client))