NET FORGE DOCS

Monster collector template (MOSSBOUND)

Last updated Checked against @netforge/engine 0.2.0View as Markdown

Net Forge, the open-source multiplayer browser game engine built for AI coding agents, is published on npm under @netforge with source at github.com/netnetdev/net-forge.

MOSSBOUND is a complete multiplayer monster collector: each player picks one of three starters at camp, walks a marsh shared with up to seven others, meets wild creatures in tall grass and battles them turn by turn with a team of three, catching the ones worth keeping. Every player in the marsh wears down the same boss, the warden, which has to fall before dusk.

npm create netforge@latest my-game -- --template collector --yes
cd my-game
npm run play

Walk with WASD, the arrows or the left thumb. Open the link in a second tab and you meet the other keeper in the marsh.

What you get

PartWhat it doesWhere
The mapSize in tiles, camp, water, blocked tiles, grass zones with encounter rates and creature pools, the warden, dusk, snaresmarsh({...})
CreaturesUp to 24 creatures with an element, base stats that grow 12% a level, 1 to 4 moves and a catch ratecreature(...)
MovesUp to 48 moves with element, power and accuracy; effects drain, heal, guardmove(...)
ElementsA four-way cycle (root, tide, spark, stone); strong hits deal 1.5x, weak ones 0.67xthe engine
BattlesTurn order by speed, swaps, snares, flee, XP for the active and benched creaturesthe engine
Shared bossOne health pool for the whole marsh; everyone who hurt it is credited when it fallsmarsh({ warden })
Netcode30 Hz authoritative room; walking is predicted with the room's own tile collision; battles are private to each playerthe template package
Playtest botsFour keepers for four minutes: battles won, catches, levels, team wipes, earnnpm test

Measured on an Apple M2 Pro, Node 22: four bots over four minutes (7,200 ticks at 30 Hz) caught 14 creatures, raised a creature to level 6 and fired the catch rules, at 0.002 ms per server tick on average.

1. Add a creature and a move

src/game.ts
import { creature, move } from "@netforge/engine";

move("thorn_curl", { element: "root", power: 0, effect: "guard" });
move("tide_crash", { element: "tide", power: 70, accuracy: 0.8 });

creature("thistlehog", {
  model: "style.lowpoly.fox",
  element: "root",
  hp: 50,
  atk: 52,
  def: 48,
  spd: 46,
  moves: ["leaf_lash", "thorn_curl"],
  catchRate: 0.7,
});

power: 40 is a plain hit. drain heals half the damage dealt, heal (with power: 0) restores amount of max health, and guard halves the next hit taken. Then put the creature in a grass pool and add its label to src/names.json.

2. Lay out the marsh

src/game.ts
import { marsh } from "@netforge/engine";

marsh({
  size: [30, 20],
  camp: [2, 10],
  starters: ["mossling", "cindertail", "puddlewump"],
  starterLevel: 4,
  water: [[11, 0, 2, 6]],
  blocked: [[19, 0, 1, 8]],
  grass: [
    { at: [4, 2, 6, 5], rate: 0.22, pool: [{ creature: "thistlehog", weight: 3, level: [2, 3] }] },
    { at: [21, 4, 4, 12], rate: 0.18, pool: [{ creature: "bogling", weight: 2, level: [6, 8] }] },
  ],
  warden: { creature: "fenwarden", at: [27, 10], level: 9, hp: 700 },
  dusk: 600,
  snares: 6,
});

Rectangles are [x, y, width, height] in tiles of 2 m. Put weak creatures near camp and stronger ones toward the warden, and leave a walkable way from camp to every grass zone. The build checks that the camp and warden stand on open tiles and that every pool names a declared creature.

3. Add an earn rule

src/game.ts
import { earn } from "@netforge/engine";

earn.rule("ten_wins", { when: "creature.defeated", n: 10, pay: 15, oncePer: "run" });

Events are creature.caught, creature.defeated, creature.levelup, level.five and level.ten (each credits the player), warden.defeated (everyone who hurt it) and run.won (everyone in the marsh).

4. Check it with bots

npm test

How it works

The collector is a board genre: its rules are a deterministic module in @netforge/engine/rules. Every roll (encounters, accuracy, damage spread, snares and the wild creature's move) comes from the room's seeded random number, so a run replays exactly from its inputs. Walking is predicted with the same tile collision the room runs, so it never waits for the server. Battles are private: your team, your opponent and the battle log reach only you, while other players see the creature walking beside you. See Simulation and ECS.

The full guide is Build a monster collecting game with battles and a party.

Alternatives

  • Godot has a tilemap editor, a scripting language and a web export. Pick it for a single-player collector with a hand-built overworld and story.
  • Phaser is a 2D HTML5 framework with tilemaps. Pick it for a top-down 2D collector with pixel art.
  • Net Forge fits when you want a shared world where players catch and battle side by side, with every roll made on the server and a shared boss fight.

FAQ

How do wild encounters work?

Each step into a new tile of tall grass rolls the zone's rate. A hit starts a battle with a creature from that zone's pool, at a level in its range.

How is the catch chance calculated?

A snare succeeds with chance catchRate x (0.25 + 0.75 x the opponent's missing health), so weakening a creature first makes it easier to catch.

Can players battle each other?

Not in this template. Players share the marsh and the warden fight; battles are against wild creatures and the warden.

How big can a team be?

Three creatures travel with you; more catches go into your lantern. The amount upgrade adds extra snares.

What happens if my whole team faints?

You are sent back to camp with half health. Standing at camp heals your team.