What it does
You describe each kind of creature as a record: hit points, size, speed, sight, altitude for flyers, how many come
together, what it targets, how it attacks and which of six ways it moves. A zoo takes those kinds, a host object your
game supplies, and your game's own array of creatures. Each step it chooses every creature's target, moves it, trails
its segments, lets it eat and grow, lays eggs, and calls your attack when an attack is due.
The split of work is what makes it fit many games. The zoo owns movement and choice. Your game says what the targets are
and where, through the host's targets and locate, and decides what an attack does: a melee bite becomes a call to
your damage code, a ranged attack named fireball becomes your projectile. Damage rules, effects and scoring never move
into the zoo, and the creatures stay a plain array you save with the rest of your game's state.
Behaviour comes from a few rules that combine well. A creature never goes for its own team. A passive kind waits until
something hurts its herd. Melee attackers close in and ranged ones stand off. Your game can keep a creature chasing one
target, a grudge, through the host's keep. Kinds that eat reach food, grow 40% a stage, gain the attacks each stage
brings and lay young, so a population can rise over a level.
Features
- Six ways to move —
flock(loose flocks that wander and swoop),flyer(alone, circling and diving),worm(swims through the land and rears to strike),serpent(a flying worm with segments),walker(never crosses water) andsea(rises from below). - Melee and ranged attacks — melee kinds close in; any other attack name stands off at its range and fires every so often, carried out by your game.
- Teams, herds and anger — no attacks on their own team, passive kinds that wait to be provoked, and grudges the host can hold a creature to.
- Eat, grow and lay — eaters reach food, grow through stages with their own attacks, and lay young on a timer.
- Herds where they can live —
spawnGroupplaces a herd on land, sea or in the air as the kind lives, well away from a point such as the player. - Plain data — kinds are records and creatures are plain objects, so both save and load with your game.
- Host flags —
humanOnly,stealsMana,teleportsAt,converts,seesInvisibleandignoresReboundare carried on a kind for your own rules to read. - Headless and deterministic — the host supplies the random source, so a seeded game replays the same.
Good for
- God games and flying-carpet battles in the style of Magic Carpet, with vultures, worms, dragons and krakens over a landscape.
- Open-world hunting games, an island of monsters to track down, some passive until provoked.
- Safari and wildlife scenes, with grazing herds that keep to the land and birds that scatter.
- Flight and helicopter games that need airborne threats which circle, dive and stand off.
- Games with growing populations, where eaters grow, gain attacks and lay eggs over a level.
Make it yours
Each CreatureKind sets its hit points, the mana it holds and drops, size, speed, altitude, sight, group size and
regeneration; its motion and, for worms and serpents, its segment count; its attack with damage, range and how
often; whether it is aggressive; which classes of target it wants; whether it eats mana; and how it grows, per stage,
with each stage's attacks and how often it lays. The host decides the rest: which targets each creature may see, what
food exists and what happens when it is eaten.
Two quite different uses: a hostile sky for a flying game, with flocks of vultures that swoop in melee and lone dragons that stand off and breathe fire through your projectile code; and a calm wildlife reserve, with herds of passive walkers that graze on food, grow and lay young, and only turn on the player when one of the herd is hurt.
A quick look
A zoo with a host that supplies targets and carries out attacks, a herd spawned away from the player, and a step:
const { Zoo } = game.creatureZoo;
const zoo = new Zoo(kinds, {
ground: land, rand: () => rng.next(), id: () => ++nextId,
targets: (k, kind) => heroes.filter((h) => kind.targets.includes('hero')),
locate: (ref) => heroes.find((h) => h.ref === ref) ?? null,
attack: (k, kind, atk, at, to) => atk.kind === 'melee' ? hurt(k.target, atk.damage) : fire(atk.kind, at, to),
}, creatures);
zoo.spawnGroup(kinds.vulture, player);
zoo.step(dt);
Works with
torus-land— a land from it serves as the zoo's ground.mana-conquest— a flying-carpet conquest game whose thirteen creature kinds are zoo records.steering— seek, flock and avoid for anything that moves, without creature records.projectile-patterns— for what the creatures fire.wave-plan— for when creatures arrive.flight-formation— for scripted attack runs rather than roaming creatures.
Good to know
- It steers rather than finds paths: a walker that meets the shore stops there until its goal moves, and in a maze it would stick.
- There is no line-of-sight test: a creature can go for any target the host offers within its sight range.
- Creatures do not collide with each other or with scenery; only the ground and the sea constrain them.
- The zoo carries out no attacks itself: your game decides what every attack does.






