Open-source project
ArchipelagoMW/Archipelago avatar
ArchipelagoMW/Archipelago

Archipelago is a multiworld framework where each game speaks its own client protocol

Archipelago Multi-Game Randomizer and Server

1,729 stars2,253 forksPythonNOASSERTION

At a glance

What is it?
Archipelago is a Python randomizer and multiplayer server that shuffles items across dozens of games at once; the interesting engineering is in the per-game client files and the WebHost container, not in the generation logic.
Who is it for?
Adopt Archipelago if you are running a multiworld session and want one server that can host every game in the group, since the alternative is one randomizer and one sync process per title. Do not adopt it for single-player play or for a headless production deployment without reading the build internals: setup.py installs a pinned cx-Freeze from inside the build script and prompts for input when it is missing, which is not what you want in CI.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A generic framework that is also a working randomizer

Archipelago describes itself as a generic framework for adding multiworld capability to game randomizers, then immediately notes that in practice it is also the randomizer itself. Both halves are in the same repository. Generation lives in Generate.py and Fill.py, the server loop in MultiServer.py, networking helpers in NetUtils.py, and the per-game logic in worlds/.

That layout explains why the project supports around eighty games without eighty separate programs. The multiworld layer knows nothing about any specific game. What it knows is that each player has an inventory, receives items addressed to them, and sends back location checks when something is collected. A game contributes a world module that describes its items, its locations and how to translate between them.

The repository root shows how wide that surface is. Client modules are flat files named after games: AHITClient.py for A Short Hike, AdventureClient.py, BizHawkClient.py, ChecksFinderClient.py, MMBN3Client.py, OoTClient.py, SNIClient.py, UndertaleClient.py, ZillionClient.py. CommonClient.py is the base for clients that only need a plain websocket connection, and BaseClasses.py plus Options.py hold the shared schema.

Coverage is broad enough to be a checklist rather than a feature list, from Super Metroid and Dark Souls 3 to Stardew Valley, Terraria, Minecraft-adjacent community titles and a combined Super Metroid plus Link to the Past mode called SMZ3.

Clients are per-game integrations, and they are the maintenance surface

Each game that Archipelago supports needs a client, because a multiplayer randomizer has to notice that a player picked something up. That client is either a Lua script running inside an emulator such as BizHawk, a mod or script inside the game itself, or a separate Python process. The names of those files are the clearest evidence of how many integration styles exist.

Because the clients depend on the games and their modding tools, an Archipelago upgrade can break a session for one game while others keep working. The requirements file pins the emulator-facing side: it pins websockets==13.1, PyYAML==6.0.3, orjson==3.11.7, cython==3.2.4 and a specific certifi release, and it pulls KivyMD from a Git commit rather than PyPI.

Legacy worlds get their own section in that file. Pymem==1.14.0 is listed as a dependency for legacy worlds that rely on reading process memory, which is a fair signal of the kind of integration some older worlds depend on.

The WebHost container runs gunicorn against WebHost.py

Multiworld sessions are coordinated by a host process, and the repository ships a Dockerfile that turns it into a service. The build runs in two stages. The first compiles the Cython speedups module.

dockerfile
FROM python:3.12 AS cython-builder

WORKDIR /build

COPY _speedups.pyx .
COPY intset.h .

RUN cythonize -b -i _speedups.pyx

The second stage installs the web dependencies, runs the module updater, purges the build toolchain and defines a health check.

dockerfile
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
    CMD curl -f http://localhost:${PORT:-80} || exit 1

ENV SKIP_REQUIREMENTS_UPDATE=true

ENTRYPOINT [ "python", "WebHost.py" ]

Three details carry real information. The server listens on the PORT environment variable and falls back to port 80, so a deployment must set PORT explicitly behind a reverse proxy. SKIP_REQUIREMENTS_UPDATE is set in the image precisely because the build already ran ModuleUpdate and the container must not do it again on every start. And gunicorn is pinned to gunicorn==23.0.0 in the image, so WebHostLib has a WSGI application behind it rather than being served by its own HTTP server.

Installing means picking an installer or an AppImage

For most people the README's answer is one line: go to the releases page and run the appropriate installer, or the AppImage on Linux-based systems. Compiled Windows binaries are published there too.

The source path is documented separately, in docs/running from source.md, which is where anyone on a platform with no compiled release should start. There is no package name to look up and no documented pip install of the project itself. The dependency list lives in requirements.txt and the web side in WebHostLib/requirements.txt, and setup.py drives the packaging rather than describing a clean library install.

Setup and per-game instructions are not in the repository README at all; they live on the tutorials page at archipelago.gg/tutorial, and the FAQ is a web page rather than a file in the tree. That split matters for anyone running an offline or archived session: the operational knowledge is on the site, not in the checkout.

setup.py installs a build dependency before it builds anything

Reading setup.py explains why building from source can feel unusual. The script requires cx-Freeze==8.6.4 and checks for it through pkg_resources.

python
requirement = "cx-Freeze==8.6.4"
try:
    import pkg_resources
    try:
        pkg_resources.require(requirement)
        install_cx_freeze = False
    except pkg_resources.ResolutionError:
        install_cx_freeze = True
except (AttributeError, ImportError):
    install_cx_freeze = True

If the version does not match, the script installs it itself, and if neither --yes nor -y is on the command line it stops at an input() prompt asking whether to install. So a clean build machine will block for a keystroke unless you pass -y, and a machine with a different cx-Freeze version will be modified without asking. The comment above the requirement calls this jank, and it is an accurate description.

One more pin is worth reading before you wire clients up: SNI_VERSION is set to v0.0.100 rather than latest, with a note that it should return to latest once tray icon issues are fixed. That is a deliberate downgrade, so a client expecting a newer emulator build may not behave as it would elsewhere.

What Archipelago does not solve

The obvious wrong tool is single-player play. If one person is randomizing one game, the multiworld server, the client processes and the location-check bookkeeping add moving parts without adding anything.

The second boundary is game support. A game that has no world module and no client is not playable in a multiworld session, and the README's list is the authoritative statement of what exists. Adding a game means writing the world module, the client and the tests, which is why contributing guidelines are separate documentation.

Third, the Docker image is a WebHost image, not a headless generator. It runs the web host with gunicorn; it does not by itself generate or fill a multiworld. There is no documentation in the repository about authentication, TLS termination or persistent state for the host, which means anyone running it beyond a LAN is making those decisions outside the project.

One server against per-game randomizers

The alternative arrangement, and the one Archipelago grew out of, is running each game's randomizer separately and syncing inventories yourself.

Archipelago's difference is structural: a single MultiServer, one WebHost process and a shared item-and-location schema, with games participating as modules rather than as separate programs. Related repositories confirm the lineage, with z3randomizer, Enemizer and the Ocarina of Time Randomizer handled as separate projects rather than folded in.

The cost of that unification is coupling. A bug in the shared layer affects every game at once, and a game whose integration depends on process memory or an emulator script drags that dependency into requirements.txt. That is the trade you are making when you choose one host over three.

Frequent releases, custom licence

The project is not archived and the last push was on 2026-10-14. Release 0.6.8 came out on 2026-10-04, preceded by a 0.6.8-rc1 candidate on 2026-09-29 and 0.6.7 on 2026-04-01. The gap between 0.6.7 and the 0.6.8 line is the kind of cadence that suits groups running long sessions, since you can pin a release instead of tracking main.

The licence is not a standard one. GitHub classifies it as Other with a custom licence in the LICENSE file, which means you cannot assume MIT or Apache terms. Nothing in the README summarises the permissions, and the practical step is to read LICENSE directly before you redistribute a modified WebHost or fold its code into anything you ship.

Documentation is split across the repository, docs/ and the website, which also means a fork has to carry all three to stay usable offline.

Editorial conclusion

Adopt Archipelago if you are running a multiworld session and want one server that can host every game in the group, since the alternative is one randomizer and one sync process per title. Do not adopt it for single-player play or for a headless production deployment without reading the build internals: setup.py installs a pinned cx-Freeze from inside the build script and prompts for input when it is missing, which is not what you want in CI. Verify first that a pinned release matches your group's client versions, that the game client you need actually exists in worlds/, and that ModuleUpdate.py -y does not rewrite requirements.txt on your machine before the first launch. The last push was on 2026-10-14 with release 0.6.8 dated 2026-10-04, and the LICENSE file is custom rather than a standard OSI licence, so read it before redistributing a modified WebHost.

Frequently asked questions

How do I install Archipelago?

Download the appropriate installer from the releases page, or the AppImage on Linux-based systems, and run it. Compiled Windows binaries are published there too, and developers on other platforms are pointed to docs/running from source.md.

Which games does Archipelago support?

The README lists around eighty titles, including The Legend of Zelda: A Link to the Past, Factorio, Subnautica, Risk of Rain 2, Super Metroid, Hollow Knight, Dark Souls 3, Stardew Valley, Terraria and TUNIC. The list also includes a combined Super Metroid and Link to the Past mode called SMZ3.

Does Archipelago have a Docker image?

Yes. The Dockerfile builds the Cython speedups in a first stage and then runs WebHost.py under gunicorn in a second stage, listening on the PORT environment variable and defaulting to port 80.

What licence does Archipelago use?

It is a custom licence in the LICENSE file, which GitHub classifies as Other rather than one of the standard OSI licences. Read that file before redistributing a modified version.

Official sources

  1. ArchipelagoMW/Archipelago on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/archipelagomw-archipelago.svg)](https://hysenlabs.com/projects/archipelagomw-archipelago)

Was this useful?