catacomms

A dungeon for a few friends, played over radio you own. Your party is whoever you can hear.

A dungeon room: three players in green, blue and pink standing in a corridor, an ogre and a goblin beside them, gold coins on the floor, a lit shrine, and torchlight falling away into the dark.
Turn six. Two of them still standing between the party and the door, coins where the rat fell, and a shrine still burning.

What it is

Two to four people plug a LoRa module into a USB port, go down together, and come back out or do not. There is no server, no account and no internet connection. Everyone runs the same rules on their own machine and the radio carries what you decide.

It runs on top of loraline, which is the messenger the radios were doing before there was a game: same modules, same keys, same link. Whatever you type that is not a command is said out loud to the party, on the same channel, in the same window.

The name is the two halves of it. A catacomb, and comms.

Why a dungeon and not a farm

Under the European duty cycle you get about one action every seventeen seconds. That is the whole design brief, and it rules out most games immediately.

A loot-and-repeat loop is enjoyable because it is dense: many small decisions a minute, the next drop always seconds away. At seventeen seconds a swing that is not a slower version of it, it is a worse one. So this is an expedition rather than a grind. You go in as a party, it is dangerous, and seventeen seconds to choose becomes deliberation instead of lag.

A median room runs about fifteen turns, which is four minutes of real time, and then you stop.

Your party is whoever you can hear

This is the part that cannot be built any other way.

Every online game simulates distance, and every one of them can be lied to, because your machine reports where it is. Here your position is measured by other people's receivers. Whether you can be heard is a physical fact about buildings and hills, and no amount of cleverness makes you somewhere you are not.

So the fog of war is not a rule the engine applies. It is a wall.

How three machines share one world

The engine is a pure deterministic state machine: a room and everyone's inputs go in, the next room comes out. No clock, no floats, no randomness that is not derived from the turn number. Every machine given the same room and the same inputs computes the same bytes.

Which leaves the actual problem, because a radio loses packets:

That is divergence detection, not consensus. With three players on a half-duplex channel there is no quorum worth having. For a party who can see each other it is enough: the game stops and says so, rather than drifting quietly into two different worlds.

Everything is inside that hash: what you are carrying, whether the shrine has been spent, how many of you came down. A client that quietly gave itself a better sword is not cheating anybody, it is simply no longer playing the same game, and everyone finds out on the next turn.

What you find

Sixteen generated items: threads, seeds, feathers, hooks, shells, scales and blades, each in a different colour, two of them ringed with a violet glow.
Every item looks like its name. The noun is the shape, the adjective is the colour, the tier is the glow.

Twenty-nine shapes and fourteen colours cover four hundred distinct named things, so a Cold Fang is a cold-coloured fang rather than a generic sword. Nothing about the picture is ever transmitted: it is derived from the name, which every machine already agreed on when the room was built.

kindwhat it changesplainfinerarenamed
bladedamage, one square681012
bowdamage, four squares3579
rodthree squares, always lands2468
armourchance to be missed20%30%40%50%
charmmaximum health+4+7+10+13
coinpays a shrine, two for one point of health

How far a weapon reaches comes from its noun, so attack east means what it always did and nothing extra crosses the radio. There is nothing to equip and nothing to choose: you strike with whatever reaches, and with the harder one when two do.

Armour is a chance to be missed, so it can turn a blade or an arrow but never a rod. A rod is the answer to something well armoured; a blade is the answer to something in front of you.

The first thing in the line is the thing you hit. A friend standing between you and the ogre is a friend you do not shoot: the shot is held and the turn is spent. That is the whole reason to care where anybody stands, and before there were bows the grid had no such reason.

rare turns up in about one room in seventeen; named in one in twenty-six, which is roughly ninety minutes of play. A named weapon doubles your damage and a named coat means half of everything swung at you misses, so one good drop changes a fight.

Coin is both the prize and the medicine

Sixty percent of rooms hold a shrine. Walk onto it hurt and carrying coin and it mends you, two coins a point, and is spent. No prompt, because a prompt would cost a turn.

Which is the tension worth having: the thing you came down for is the thing that keeps you alive long enough to carry it out.

What it can't do

Knowing the limits is most of knowing whether this is for you.

It is slow, and that is the point

One action every seventeen seconds under the European duty cycle. Elsewhere the cap is collisions rather than law, and it is faster, but it is never a real-time game.

Four people, and only just

Rooms hold one monster per person. Across four hundred rooms at each size, played competently:

partyclearedwithdrewwiped
167%12%20%
265%18%16%
369%21%10%
467%25%7%

Past four, everyone's heartbeats and inputs start colliding on a channel that can only carry one at a time. It is a small-group game by physics rather than by preference.

Nothing carries over yet

A room is a room. There are no levels between delves, no stash, no towns to spend coin in. That is not laziness: a local hoard is unverifiable until a finished delve produces a record signed by everyone who was there, and inventing an enforcement that enforces nothing would be worse than the gap.

You are responsible for the band

It transmits on licensed-free spectrum that differs by country. Read loraline's setup before you switch a radio on.

Playing

You need loraline working first. Its walkthrough takes about half an hour from unpacking the modules to talking, and needs no prior experience.

git clone https://github.com/intervalplace/loraline
git clone https://github.com/intervalplace/catacomms
pip install -r catacomms/requirements.txt
cd catacomms && PYTHONPATH=../loraline python tests.py

The tests run three players through a whole fight over a simulated lossy radio and need no hardware at all.

In a browser

python -m catacomms --port /dev/ttyUSB0 --band eu868 --nick hank --web

Then open localhost:8080, or the machine's address from a phone on the same network, and play from the sofa while the dongle stays on the laptop. Arrows or hjkl to move, HJKL to strike, d to set down, or tap a square next to you.

The rules are not reimplemented in the browser. A second engine in JavaScript would diverge on some integer division nobody thought about, and the divergence detector would fire, correctly, for ever. The page receives snapshots and posts back actions; the Python process remains the only thing that decides anything. One file, no dependencies, nothing fetched.

In a terminal

python -m catacomms --port /dev/ttyUSB0 --band eu868 --nick hank

Letters by default, /tiles for half-block pixels. It runs over SSH on anything with a terminal, which the browser view cannot.

Once you are in

/delve calls one, /begin sets off, /join and /stay answer somebody else's. Anything else you type is said to the party.