In Ceasefire, every third round is quiet: nobody fires, but abilities keep charging, so the round after a ceasefire is when the big ships come out. The fleet is the Kayak, Medium Galleon, Sailboat and Raft.
The player's request:
Make a BattleTabs mod called Ceasefire: every third round, both sides hold fire, but ability cooldowns keep counting down.
It took 25 calls to the mod tool, three versions and one typecheck error. We've kept in both places it went wrong, including a bug that only showed up in the full game log.
All in one go: Paste this into your agent with the battletabs-mod tool connected, and it runs the whole loop by itself: build, test, tune.
Make a BattleTabs mod called Ceasefire: every third round, both sides hold fire, but ability cooldowns keep counting down.
Read the battletabs-mod ship-mods docs first, and only use ships that are allowed in the Arcade.
Typecheck it, then play a few test games on different seeds and check the rule works.
Run 500 bot games and compare the win split and game length with normal rules. If one side wins much more often, or games run much longer, change it and test again.
Save it as case-ceasefire, then tell me what you changed along the way and why.Or step by step, as we did it: Going one prompt at a time lets you look at each result and steer, the way the decisions on this page were made. Some prompts react to what came back, so read the result before you send the next one.
Make a BattleTabs mod called Ceasefire: every third round, both sides hold fire, but ability cooldowns keep counting down.Use four ships that have real cooldowns and are allowed in the Arcade. Typecheck it.Play a game with bots and show me the log.On a ceasefire turn, try to use the Kayak. Does it still fire? Show me the whole log.Combos like the Galleon's double shot are throwing the count off. Count each player's turns instead, so both sides always hold fire in the same round.Prove the cooldowns really keep counting down during a ceasefire. Use a ship with a long cooldown and check when it's ready.Run 200 bot games and tell me the win split and how long games are compared with normal rules.Players shouldn't have to click during a ceasefire. Just skip both turns automatically, but keep the cooldowns counting.Play a couple of seeds again, including one where the other side moves first.Run 500 bot games on the final version and give me the win split, game length and any errors.Save a picture of the board just after a ceasefire, and save the mod as case-ceasefire.Prompt 1
Make a BattleTabs mod called Ceasefire: every third round, both sides hold fire, but ability cooldowns keep counting down.get_docs (ship-mods, then examples/second-wind)onAttack hook that returns "cancel": the player takes their turn, but the shot does nothing ("A cancelled attack is not a skip"). Or ctx.skipNextTurn(seat): the turn is skipped, and "the skipped seat's cooldowns still tick"."cancel", the most literal reading of "hold fire".Prompt 2
Use four ships that have real cooldowns and are allowed in the Arcade. Typecheck it.floor(ctx.turn / 2) + 1, and cancelled shots in rounds 3, 6, 9 and so on.list_ships (arcade_only), save_mod, typecheckPrompt 3
Play a game with bots and show me the log.play_once (seed 1)ctx.turn counts actions, not player turns, so the round sum will drift.Prompt 4
On a ceasefire turn, try to use the Kayak. Does it still fire? Show me the whole log.play_once (seed 2, with a scripted Kayak shot, run twice)onTurnStart, which runs once per player turn, not once per shot.Prompt 5
Combos like the Galleon's double shot are throwing the count off. Count each player's turns instead, so both sides always hold fire in the same round.holdFire: false flag in the mod's data.save_mod, typecheck (twice), play_once (seed 2)holdFire: false as boolean fixed the type. Both sides now always hold fire in the same round.Prompt 6
Prove the cooldowns really keep counting down during a ceasefire. Use a ship with a long cooldown and check when it's ready.render_state plays scripted moves and refuses an illegal one, listing what is legal.render_state (three scripted runs, then a png)Prompts 7 to 11
Run 200 bot games and tell me the win split and how long games are compared with normal rules.Players shouldn't have to click during a ceasefire. Just skip both turns automatically, but keep the cooldowns counting.Play a couple of seeds again, including one where the other side moves first.Run 500 bot games on the final version and give me the win split, game length and any errors.Save a picture of the board just after a ceasefire, and save the mod as case-ceasefire.ctx.skipNextTurn: when a player starts their 2nd, 5th or 8th turn, their next one is skipped, and a "ceasefire next round" message goes up once both sides are set.simulate_n (200 games), save_mod, typecheck, play_once (seeds 2 and 7), render_state, simulate_n (500 games), render_stateCombo ships take extra turn numbers: the Medium Galleon's double shot uses two. Working rounds out from ctx.turn let a ceasefire land in the middle of a combo, so one player held fire alone.
Fix: Count each player's own turns in onTurnStart, which runs once per player turn.
The mod's data started as holdFire: false, and TypeScript decided the flag's type was "always false", so setting it to true failed typecheck.
Fix: Write holdFire: false as boolean. A data object's starting values become its types.
The first scripted test printed only 12 log lines and cut off the part that showed the bug.
Fix: Run it again with 60 lines. The bug was in the full log.
Version 2 was balanced, but games were 36% longer, and on a ceasefire turn a player had to pick a target and press fire, then watch the shot quietly disappear.
Fix: Skip the turn with ctx.skipNextTurn instead of cancelling the shot. Same rule, same winners on the same seeds, no dead clicks.
500 bot games on the final version, seeds 1 to 500, against normal rules on the same fleets and seeds.
| Ceasefire | Normal rules | |
|---|---|---|
| Wins, seat 0 / seat 1 | 254 / 246 (51% / 49%) | 250 / 250 (50% / 50%) |
| First mover won | 284 (57%) | 314 (63%) |
| Turns played per game | 28.7 | 29.2 |
| Ceasefire turns (skipped instantly) | 11.2 | 0 |
| Raft ability uses per game | 1.1 | 0.8 |
| Sailboat ability uses per game | 1.5 | 1.3 |
| Draws / errors | 0 / 0 | 0 / 0 |
Every version along the way:
| Version | Change | Result | Kept? |
|---|---|---|---|
| v1 | Cancel shots, rounds worked out from ctx.turn | Combos broke the count | No |
| v2 | Cancel shots, each player's turns counted | 107 / 93, 40.2 turns (normal 29.6), 200 games | No, dead turns |
| v3 | Skip the turn instead of cancelling the shot | 254 / 246, 28.7 turns played (normal 29.2), 500 games | Final |
TODO: in-game screenshot of this game in the BattleTabs Arcade.
The mod tool's render_state draws the boards as 2D pictures. Dark red cells are a sunk ship.


The whole mod, as saved by save_mod. Copy it into your own mods folder to start from it.
import { defineShipMod } from "@battletabs/mod-api";
// Ceasefire: every third round, both sides hold fire, but ability cooldowns keep counting down.
// A round is one turn for each seat. Each seat counts its own turns. When a seat starts its 2nd,
// 5th, 8th ... turn, its NEXT turn (the 3rd, 6th, 9th ...) is skipped. A skipped turn still ticks
// the seat's cooldowns, so abilities keep charging while nobody fires, and nobody has to click
// through a dead turn.
export default defineShipMod({
id: "case-ceasefire",
apiVersion: 1,
classicVersion: "classic-2",
rules: {
pitch: "Every third round the guns fall silent, but your abilities keep charging.",
bullets: [
"Sink every enemy ship to win",
"Every third round is a ceasefire: both sides skip their turn",
"Ability cooldowns keep counting down during a ceasefire",
],
},
maxTurns: 200,
fleet: ["kayak", "galleonmedium", "sailboat", "raft"],
data: { turnsTaken: [0, 0], ceasefires: 0 },
hooks: {
onTurnStart(start, ctx) {
const seat = start.seat;
ctx.data.turnsTaken[seat] += 1;
if ((ctx.data.turnsTaken[seat] + 1) % 3 === 0) {
ctx.skipNextTurn(seat);
ctx.data.turnsTaken[seat] += 1; // the skipped turn will not start, so count it now
if (ctx.data.turnsTaken[0] === ctx.data.turnsTaken[1]) {
ctx.data.ceasefires += 1;
ctx.emit({ type: "show-message", audience: "all", template: "ceasefire-next-round" });
}
}
},
},
});
Install the mod tools and connect your agent with the Arcade guide. Then paste the prompts above into your agent, all in one go or one at a time. To play against the bot yourself, ask your agent to open the play page.