Ramparts
Hold the road, then the next act, then the citadel
palupdated 2026-10-05FunIn pal's registry
In pal's registry: the button shows it in pal, which asks before installing; the command does the same from a terminal. This page can't see what your pal has installed.






What it does
A tower defense roguelike: build towers, soldiers and spells against waves on a lit 3D diorama, inside a run of three acts and a final citadel. Draft a war table of up to six towers with boons and relics along a branching map of battles, elites, shops, events, forges and camps, then come back with renown, new commanders and ascensions.
- Twelve towers with distinct jobs, each going to level three and then one of two specialisations; soldiers that block the road and two commander spells
- Fifteen enemy roles with counters: armour, wards, shields, flyers, stealth, healers, splitters; seven bosses with their own tricks, from a burrowing wyrm to a dragon that takes to the air
- Synergies you find by seeing them: frost then shatter, oil then fire, marks then crits; fire and ice cancel
- A run of three acts and a final citadel on branching maps of battles, elites, shops, events, forges and camps; lives carry over and leaks cost them
- Draft a war table of up to six towers with 91 boons and 52 relics; every reward leans toward your core and keeps one wild card
- Renown after every run opens towers, relics, events and perks; five commanders and ten ascensions each
- A lit low-poly diorama for each act, hitstop and shatter chimes, and synthesised music that swells with the wave
- A codex of every tower, enemy, boss, boon, relic and event you've met; close pal mid-run and the run waits where you left it
- A board for the highest ascension won; signed in, your renown, unlocks, codex and the run in progress follow you to your other machines and play.cagdas.io
Palettes 1
-
Ramparts
rampartsviewA tower defense roguelike run. Escape or closing the panel pauses a battle, and the run waits for you.
- spaceNext wave
- 1Build on the pad (1-6)
- QCommander spells (Q and W)
- FBattle speed
- PPause or carry on
- ⌫Back
- MSound on or off
Actions
- Build and upgradeClick a pad for the build ring, or move between pads with the arrows or Tab and press 1-6; U upgrades, X sells (twice), T changes the target.1or2or3or4or5or6
- Next waveStarts the first wave, then calls the next one early for gold.space
- Commander spellsAim with the mouse or the arrows, Enter casts, Backspace cancels.QorW
- War suppliesEorD
- Show every rangeHold Alt.⌥
- Battle speed1x, 2x or 3x.F
- Pause or carry onP
- BackCloses what is open, cancels an aim, leaves a shop.⌫
- War table and map zoomOutside a battle: V shows your towers, boons and relics; Z zooms the run map.VorZ
- Sound on or offM
Settings
Extension, [extensions.ramparts]
volumeHow loud the game is, music and effects together; M in the game turns it off.
musicThe music that swells with the fight.
effectsArrows, blasts, coins and the rest.
Defaults shown. Change them in pal's settings window or in the config file.
The README
Everything Ramparts does, key by key, from the extension's own README.md
Ramparts
A tower defense roguelike. You build Kingdom Rush-style towers, soldiers and commander spells, and you play them inside a Slay the Spire-style run. A run has three acts and a final citadel. Each act is a branching map of battles, elites, shops, events, forges and camps. Along the way you draft a war table of up to six towers, plus boons and relics. The world is a lit low-poly 3D diorama, and all of its music and sound is synthesised.
Ported into pal from the standalone game (2026-10-05): the rules, look and balance are as they were; what changed is what a pal surface needs (below).
DESIGN.mdis the front page of the design: pillars, the rulings, controls and balance targets. Each chapter indesign/covers one area in full:systems.md(battle),run-meta.md(run and meta),content.md(every number and line of text),art.md(look),balance.md(tuning log and measurements) andarchitecture.md(code layout).NEXT.mdis what's left for the next round.
In pal
- The page is
surface/index.html, served file by file (.tstranspiled one at a time, no bundler): three.js is one vendored module,surface/vendor/three.js(scripts/vendor.shrebuilds it frompackage.json's version), and the two fonts are insurface/font/. - Saving goes through the kit's storage (
surface/storage.ts, read once at start):profile(renown, unlocks, codex, history),run(the run in progress, with a version) andsettings. Signed in, they sync by the rules inpal.json, whichgame/sync.tsbuilds from the content (bun ramparts/scripts/sync-rules.tswrites them after content changes; a test fails when they drift): counts add up, records keep the best, unlocks and history are a union, the run is the latest. - A won run posts its ascension to the
ascensionboard. - Volume, music and effects are pal's settings for the game; M mutes, from anywhere.
- Escape is the panel's: it leaves, and leaving (or hiding the panel) pauses a battle and stops the sound. Backspace does what Esc did: cancel an aim, close the radial, leave a shop, go back.
bun .pal/host/src/surface.ts ramparts 8791serves the page in a browser;?battle=1..4&kind=battle|elite|boss&seed=N&towers=archer,frost,...jumps straight into a battle, andwindow.__gameexposes state for headless checks.
Controls
| Key | Battle | Outside battle |
|---|---|---|
| Mouse | click a pad for the build menu, click a tower for upgrade/sell/target | click cards, nodes, choices |
| 1-6 | build that tower on the focused pad | pick a card or choice |
| Arrows, Tab | move between pads | move on the map or between items |
| Space | start wave 1, or call the next wave early for gold | |
| U / X / T / R | upgrade / sell (press twice) / cycle target mode / move the rally point | |
| 1 / 2 in the open menu on an L3 tower | choose a specialisation | |
| Q / W | commander spells (aim with mouse or arrows, Enter casts, Backspace cancels) | |
| E / D | war supplies | |
| Alt (hold) | show every tower's range | |
| F | speed 1x / 2x / 3x | |
| P | pause (mute, shake, damage numbers) | |
| Backspace | cancel aim, close the menu, pause | back |
| V | war table | |
| Z | zoom the run map | |
| M | mute | mute |
Code
game/: pure, deterministic rules (seeded, 30 Hz fixed step, no DOM).battle/,map.ts,content/battle/: the battle sim, maps and waves.run/,meta.ts,content/run/: the run, renown, unlocks and codex;sync.tsthe merge rules.bot/: a player-like bot with a knowledge level, used by the balance simulator.
surface/: the page.render/: three.js stage, world, models, units and towers.render/fx/: projectiles, particles, status overlays, hitstop and shake.ui/: DOM HUD, radial menu, every screen, SVG glyphs.audio/: WebAudio synth music and effects.main.ts: the app shell, the loop and pal's hooks.storage.ts: the only persistence.
scripts/:sim.tsandbalance/: the balance simulator and its probes.sweep.ts: the full-strength rule sweeps the test suite samples.audio-check.ts: measures every song and effect offline in headless Chromium.
fixture.ts: the store screenshots (make shots EXT=ramparts).- Tests:
test/ramparts-*.test.ts(make test NAMES=ramparts).
Credits and licences
- Code, models, textures, music and sound: made for this project. Everything is procedural or synthesised; no third-party art or audio is used.
- Fonts: Cinzel (Natanael Gama) and
Nunito Sans (Vernon Adams, Jacques Le Bailly,
Manvel Shmavonyan, Alexei Vanyashin), SIL Open Font License 1.1 (
surface/font/OFL-*.txt). - Libraries: three.js (MIT).