Skip to content

Commit 6c07437

Browse files
el-uFlySniper
authored andcommitted
Docs: clean up world api.md a bit (ArchipelagoMW#1958)
1 parent 35aa28d commit 6c07437

File tree

2 files changed

+43
-42
lines changed

2 files changed

+43
-42
lines changed

docs/apworld specification.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# apworld Specification
22

33
Archipelago depends on worlds to provide game-specific details like items, locations and output generation.
4-
Those are located in the `worlds/` folder (source) or `<insall dir>/lib/worlds/` (when installed).
4+
Those are located in the `worlds/` folder (source) or `<install dir>/lib/worlds/` (when installed).
55
See [world api.md](world%20api.md) for details.
66

77
apworld provides a way to package and ship a world that is not part of the main distribution by placing a `*.apworld`

docs/world api.md

+42-41
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ allows using WebSockets.
2222

2323
## Coding style
2424

25-
AP follows all the PEPs. When in doubt use an IDE with coding style
26-
linter, for example PyCharm Community Edition.
25+
AP follows [style.md](https://github.com/ArchipelagoMW/Archipelago/blob/main/docs/style.md).
26+
When in doubt use an IDE with coding style linter, for example PyCharm Community Edition.
2727

2828

2929
## Docstrings
@@ -44,7 +44,7 @@ class MyGameWorld(World):
4444
## Definitions
4545

4646
This section will cover various classes and objects you can use for your world.
47-
While some of the attributes and methods are mentioned here not all of them are,
47+
While some of the attributes and methods are mentioned here, not all of them are,
4848
but you can find them in `BaseClasses.py`.
4949

5050
### World Class
@@ -56,11 +56,12 @@ game.
5656
### WebWorld Class
5757

5858
A `WebWorld` class contains specific attributes and methods that can be modified
59-
for your world specifically on the webhost.
59+
for your world specifically on the webhost:
6060

61-
`settings_page` which can be changed to a link instead of an AP generated settings page.
61+
`settings_page`, which can be changed to a link instead of an AP generated settings page.
6262

6363
`theme` to be used for your game specific AP pages. Available themes:
64+
6465
| dirt | grass (default) | grassFlowers | ice | jungle | ocean | partyTime | stone |
6566
|---|---|---|---|---|---|---|---|
6667
| <img src="img/theme_dirt.JPG" width="100"> | <img src="img/theme_grass.JPG" width="100"> | <img src="img/theme_grassFlowers.JPG" width="100"> | <img src="img/theme_ice.JPG" width="100"> | <img src="img/theme_jungle.JPG" width="100"> | <img src="img/theme_ocean.JPG" width="100"> | <img src="img/theme_partyTime.JPG" width="100"> | <img src="img/theme_stone.JPG" width="100"> |
@@ -75,26 +76,27 @@ prefixed with the same string as defined here. Default already has 'en'.
7576
### MultiWorld Object
7677

7778
The `MultiWorld` object references the whole multiworld (all items and locations
78-
for all players) and is accessible through `self.world` inside a `World` object.
79+
for all players) and is accessible through `self.multiworld` inside a `World` object.
7980

8081
### Player
8182

8283
The player is just an integer in AP and is accessible through `self.player`
83-
inside a World object.
84+
inside a `World` object.
8485

8586
### Player Options
8687

8788
Players provide customized settings for their World in the form of yamls.
88-
Those are accessible through `self.world.<option_name>[self.player]`. A dict
89+
Those are accessible through `self.multiworld.<option_name>[self.player]`. A dict
8990
of valid options has to be provided in `self.option_definitions`. Options are automatically
9091
added to the `World` object for easy access.
9192

92-
### World Options
93+
### World Settings
9394

94-
Any AP installation can provide settings for a world, for example a ROM file, accessible through `self.settings.option`
95-
or `cls.settings.option` (new API) or `Utils.get_options()["<world>_options"]["<option>"]` (deprecated).
95+
Any AP installation can provide settings for a world, for example a ROM file, accessible through
96+
`self.settings.<setting_name>` or `cls.settings.<setting_name>` (new API)
97+
or `Utils.get_options()["<world>_options"]["<setting_name>"]` (deprecated).
9698

97-
Users can set those in their `host.yaml` file. Some options may automatically open a file browser if a file is missing.
99+
Users can set those in their `host.yaml` file. Some settings may automatically open a file browser if a file is missing.
98100

99101
Refer to [settings api.md](https://github.com/ArchipelagoMW/Archipelago/blob/main/docs/settings%20api.md)
100102
for details.
@@ -135,10 +137,10 @@ same ID. Name must not be numeric (has to contain at least 1 letter or symbol).
135137
Special items with ID `None` can mark events (read below).
136138

137139
Other classifications include
138-
* filler: a regular item or trash item
139-
* useful: generally quite useful, but not required for anything logical
140-
* trap: negative impact on the player
141-
* skip_balancing: add to progression to skip balancing; e.g. currency or tokens
140+
* `filler`: a regular item or trash item
141+
* `useful`: generally quite useful, but not required for anything logical
142+
* `trap`: negative impact on the player
143+
* `skip_balancing`: add to `progression` to skip balancing; e.g. currency or tokens
142144

143145
### Events
144146

@@ -162,10 +164,10 @@ or more event locations based on player options.
162164

163165
Regions are logical groups of locations that share some common access rules. If
164166
location logic is written from scratch, using regions greatly simplifies the
165-
definition and allow to somewhat easily implement things like entrance
167+
definition and allows to somewhat easily implement things like entrance
166168
randomizer in logic.
167169

168-
Regions have a list called `exits` which are `Entrance` objects representing
170+
Regions have a list called `exits`, which are `Entrance` objects representing
169171
transitions to other regions.
170172

171173
There has to be one special region "Menu" from which the logic unfolds. AP
@@ -182,7 +184,7 @@ They can be static (regular logic) or be defined/connected during generation
182184
### Access Rules
183185

184186
An access rule is a function that returns `True` or `False` for a `Location` or
185-
`Entrance` based on the the current `state` (items that can be collected).
187+
`Entrance` based on the current `state` (items that can be collected).
186188

187189
### Item Rules
188190

@@ -199,14 +201,14 @@ the `/worlds` directory. The starting point for the package is `__init__.py`.
199201
Conventionally, your world class is placed in that file.
200202

201203
World classes must inherit from the `World` class in `/worlds/AutoWorld.py`,
202-
which can be imported as `worlds.AutoWorld.World` from your package.
204+
which can be imported as `from worlds.AutoWorld import World` from your package.
203205

204206
AP will pick up your world automatically due to the `AutoWorld` implementation.
205207

206208
### Requirements
207209

208210
If your world needs specific python packages, they can be listed in
209-
`world/[world_name]/requirements.txt`. ModuleUpdate.py will automatically
211+
`worlds/<world_name>/requirements.txt`. ModuleUpdate.py will automatically
210212
pick up and install them.
211213

212214
See [pip documentation](https://pip.pypa.io/en/stable/cli/pip_install/#requirements-file-format).
@@ -217,7 +219,7 @@ AP will only import the `__init__.py`. Depending on code size it makes sense to
217219
use multiple files and use relative imports to access them.
218220

219221
e.g. `from .Options import mygame_options` from your `__init__.py` will load
220-
`world/[world_name]/Options.py` and make its `mygame_options` accesible.
222+
`worlds/<world_name>/Options.py` and make its `mygame_options` accessible.
221223

222224
When imported names pile up it may be easier to use `from . import Options`
223225
and access the variable as `Options.mygame_options`.
@@ -228,12 +230,12 @@ function, see [apworld specification.md](apworld%20specification.md).
228230

229231
### Your Item Type
230232

231-
Each world uses its own subclass of `BaseClasses.Item`. The constuctor can be
233+
Each world uses its own subclass of `BaseClasses.Item`. The constructor can be
232234
overridden to attach additional data to it, e.g. "price in shop".
233235
Since the constructor is only ever called from your code, you can add whatever
234236
arguments you like to the constructor.
235237

236-
In its simplest form we only set the game name and use the default constuctor
238+
In its simplest form we only set the game name and use the default constructor
237239
```python
238240
from BaseClasses import Item
239241

@@ -268,7 +270,7 @@ Each option has its own class, inherits from a base option type, has a docstring
268270
to describe it and a `display_name` property for display on the website and in
269271
spoiler logs.
270272

271-
The actual name as used in the yaml is defined in a `dict[str, Option]`, that is
273+
The actual name as used in the yaml is defined in a `Dict[str, AssembleOptions]`, that is
272274
assigned to the world under `self.option_definitions`.
273275

274276
Common option types are `Toggle`, `DefaultOnToggle`, `Choice`, `Range`.
@@ -329,10 +331,10 @@ class FixXYZGlitch(Toggle):
329331
display_name = "Fix XYZ Glitch"
330332

331333
# By convention we call the options dict variable `<world>_options`.
332-
mygame_options: typing.Dict[str, type(Option)] = {
334+
mygame_options: typing.Dict[str, AssembleOptions] = {
333335
"difficulty": Difficulty,
334336
"final_boss_hp": FinalBossHP,
335-
"fix_xyz_glitch": FixXYZGlitch
337+
"fix_xyz_glitch": FixXYZGlitch,
336338
}
337339
```
338340
```python
@@ -359,7 +361,6 @@ from .Items import mygame_items # data used below to add items to the World
359361
from .Locations import mygame_locations # same as above
360362
from worlds.AutoWorld import World
361363
from BaseClasses import Region, Location, Entrance, Item, RegionType, ItemClassification
362-
from Utils import get_options, output_path
363364

364365

365366
class MyGameItem(Item): # or from Items import MyGameItem
@@ -385,7 +386,7 @@ class MyGameWorld(World):
385386
topology_present = True # show path to required location checks in spoiler
386387

387388
# ID of first item and location, could be hard-coded but code may be easier
388-
# to read with this as a propery.
389+
# to read with this as a property.
389390
base_id = 1234
390391
# Instead of dynamic numbering, IDs could be part of data.
391392

@@ -400,7 +401,7 @@ class MyGameWorld(World):
400401
# Items can be grouped using their names to allow easy checking if any item
401402
# from that group has been collected. Group names can also be used for !hint
402403
item_name_groups = {
403-
"weapons": {"sword", "lance"}
404+
"weapons": {"sword", "lance"},
404405
}
405406
```
406407

@@ -414,7 +415,7 @@ The world has to provide the following things for generation
414415
* locations placed inside those regions
415416
* a `def create_item(self, item: str) -> MyGameItem` to create any item on demand
416417
* applying `self.multiworld.push_precollected` for start inventory
417-
* `required_client_version: Tuple(int, int, int)`
418+
* `required_client_version: Tuple[int, int, int]`
418419
Optional client version as tuple of 3 ints to make sure the client is compatible to
419420
this world (e.g. implements all required features) when connecting.
420421

@@ -587,7 +588,7 @@ def set_rules(self) -> None:
587588
# require one item from an item group
588589
add_rule(self.multiworld.get_location("Chest3", self.player),
589590
lambda state: state.has_group("weapons", self.player))
590-
# state also has .item_count() for items, .has_any() and.has_all() for sets
591+
# state also has .item_count() for items, .has_any() and .has_all() for sets
591592
# and .count_group() for groups
592593
# set_rule is likely to be a bit faster than add_rule
593594

@@ -625,7 +626,7 @@ public members with `mygame_`.
625626
More advanced uses could be to add additional variables to the state object,
626627
override `World.collect(self, state, item)` and `remove(self, state, item)`
627628
to update the state object, and check those added variables in added methods.
628-
Please do this with caution and only when neccessary.
629+
Please do this with caution and only when necessary.
629630

630631
#### Sample
631632

@@ -637,7 +638,7 @@ from worlds.AutoWorld import LogicMixin
637638
class MyGameLogic(LogicMixin):
638639
def mygame_has_key(self, player: int):
639640
# Arguments above are free to choose
640-
# MultiWorld can be accessed through self.world, explicitly passing in
641+
# MultiWorld can be accessed through self.multiworld, explicitly passing in
641642
# MyGameWorld instance for easy options access is also a valid approach
642643
return self.has("key", player) # or whatever
643644
```
@@ -650,8 +651,8 @@ import .Logic # apply the mixin by importing its file
650651
class MyGameWorld(World):
651652
# ...
652653
def set_rules(self):
653-
set_rule(self.world.get_location("A Door", self.player),
654-
lamda state: state.mygame_has_key(self.player))
654+
set_rule(self.multiworld.get_location("A Door", self.player),
655+
lambda state: state.mygame_has_key(self.player))
655656
```
656657

657658
### Generate Output
@@ -679,14 +680,14 @@ def generate_output(self, output_directory: str):
679680
# store option name "easy", "normal" or "hard" for difficuly
680681
"difficulty": self.multiworld.difficulty[self.player].current_key,
681682
# store option value True or False for fixing a glitch
682-
"fix_xyz_glitch": self.multiworld.fix_xyz_glitch[self.player].value
683+
"fix_xyz_glitch": self.multiworld.fix_xyz_glitch[self.player].value,
683684
}
684685
# point to a ROM specified by the installation
685686
src = self.settings.rom_file
686687
# or point to worlds/mygame/data/mod_template
687688
src = os.path.join(os.path.dirname(__file__), "data", "mod_template")
688689
# generate output path
689-
mod_name = f"AP-{self.multiworld.seed_name}-P{self.player}-{self.multiworld.player_name[self.player]}"
690+
mod_name = self.multiworld.get_out_file_name_base(self.player)
690691
out_file = os.path.join(output_directory, mod_name + ".zip")
691692
# generate the file
692693
generate_mod(src, out_file, data)
@@ -735,14 +736,14 @@ from . import MyGameTestBase
735736

736737

737738
class TestChestAccess(MyGameTestBase):
738-
def testSwordChests(self):
739+
def test_sword_chests(self):
739740
"""Test locations that require a sword"""
740741
locations = ["Chest1", "Chest2"]
741742
items = [["Sword"]]
742743
# this will test that each location can't be accessed without the "Sword", but can be accessed once obtained.
743744
self.assertAccessDependency(locations, items)
744-
745-
def testAnyWeaponChests(self):
745+
746+
def test_any_weapon_chests(self):
746747
"""Test locations that require any weapon"""
747748
locations = [f"Chest{i}" for i in range(3, 6)]
748749
items = [["Sword"], ["Axe"], ["Spear"]]

0 commit comments

Comments
 (0)