Place nodes, wire them up, copy the output into core.js. Recognised parts are drawn with real symbol artwork; anything else (or a custom body+actuator build) shows a warning in the right-hand panel once placed, explaining what's missing.
A view is a box over part of the circuit. Present has a button for each one that zooms onto it, outlines it and can grey out the rest; the Level 4 cards use them the same way. Order here is button order.
Or drag on empty sheet to draw one.
On: click two ports and a clear route is found for you, and routes are re-checked when you move components. Off: wires are drawn as a plain elbow and nothing is ever re-routed for you — click extra points while drawing to shape them by hand.
The app always scales your whole grid to fill the screen — there's no fixed pixel boundary to match. Set cols/rows/cell directly below.
0 selected
Shift-click nodes to add or remove them, or drag on empty canvas to rubber-band select. Drag any selected node to move the whole group together.
3+ selected — spread the outer two apart evenly, keeping them fixed, and distribute the rest between them (matches "Distribute" in design tools).
Keyboard: Ctrl/Cmd+Z to undo, Ctrl/Cmd+Y (or Ctrl/Cmd+Shift+Z) to redo, Enter to finish a wire in progress, Delete/Backspace to remove whatever's currently selected, Escape to cancel a wire in progress or clear selection, arrow keys to nudge a selected node one grid step (Shift+arrow for a bigger step). All of these are ignored while typing in a text field.
Paste a previously exported block (or one you're editing by hand) to pick up right where you left off instead of rebuilding from scratch.
Adds this layout to core.js's own CIRCUITS list at load, so it renders through the real engine — real geometry, real wire bending, real hit areas — rather than this tool's approximation. Requires the small draft-circuit hook added to core.js.
Open index.html, open its browser console (F12), paste this in, press Enter. The circuit appears in Level 4 → Circuits as "Draft (from layout editor)". To remove it again: localStorage.removeItem('draftCircuit'); location.reload();
One-time repair for wires drawn before this fix, when the clean port-approach routing shown in the preview was never actually being saved — so what you saw here and what the real app rendered could genuinely disagree. Re-bakes routing into every wire's current via points, based on where things are right now — including routing a plain (no-via) wire around its own component's box automatically if it's currently cutting straight through it, the same check new wires get as they're drawn. Safe to run on a whole circuit even if some wires are already correctly baked — it strips any existing approach stub first, so it won't stack a second one on top and produce a zigzag.
Everything in one place now — grid, nodes, wires, dots, views and states together, ready to paste as the body of one CIRCUITS.push({ ... }) call.
Wraps the same data as a ready-to-use file — the download itself gets a date/time stamp added to its name so repeated exports never collide or overwrite each other, but the id inside stays exactly what you type, since that's what other code refers to it by. Add one more <script src="circuits/your-file.js"></script> line to trainer.html, after core.js, and it pushes itself onto the real CIRCUITS list at load. No build step, works the same way core.js itself loads.
One state per named condition — "held", "raising", "left solenoid energised", etc. Add a state, make it active, then set each wire's role for that condition on the right. Drag by ☰ to reorder (display order only).
Click a wire on the canvas, or find it in the list on the right, to set its role and arrow for this state. Pressure values are separate tags, below.
Click a wire to start tracing.
A pressure value is a tag you place anywhere on the sheet. It stays in the same spot in every state; only what it reads changes. Drag a tag to move it.
Click the sheet to drop a tag and type its value. Enter confirms, ready for the next one.
Clicking a start port and then an end port finds a route between them: straight out of each port for a fixed distance, then around any components in the way, crossing other wires square-on and never running along one. Routes are re-checked whenever you place or move a component, so a wire drawn before something existed still avoids it afterwards.
If no clean route exists the wire is still created, but drawn dashed red with the reason in the status line — it is never quietly replaced with a worse route that hasn't been checked against anything. Move something and it will try again, or turn this off and shape it by hand.
A wire becomes a plain elbow between its two ports, and nothing on the sheet is ever re-routed for you. Worth switching to on a large, busy schematic: the number of possible routes grows with the circuit, so the chance of the automatic one picking a route you wouldn't have grows with it. Click extra points while drawing to place the corners yourself.
Clicking extra points while drawing always routes by hand, whichever way this is set — a wire with corners you placed is yours, and is never silently re-routed. The same goes for "Insert clearance points" on a selected wire. "Re-bake all wire routing" below still re-runs the automatic router on everything when you explicitly ask it to.
When dragging one node, its ports/center pull into line with anything else on the sheet within a few pixels — a pink guide line shows what it snapped to. Grid snap still applies if nothing else is nearby. Off by default for multi-select drags, to keep group moves predictable.
While placing a dot, the preview rides along whichever wire is closest to the cursor, snapped exactly onto it. Turn this off to drop a dot in open space near a wire without it pulling onto the line — useful in a crowded area. Port alignment above still shows its pink guide either way, whether the dot is riding a wire or free.
The same way a directional valve's flashcard steps through its positions, each state here is one condition of the whole circuit — the canvas recolours live to match whichever one's active, so you can check it as you go.
Click wires in order from where flow starts to where it ends — each has to share an end (or a component) with the one before it. Direction is worked out automatically as you go. At a junction, whichever wire you click next is the choice.
Click empty sheet, then a wire, to start a fresh trace. The result selects exactly like a normal multi-select.
Shift-click, Esc, or changing state stops tracing. Shift-click keeps its usual job of adding a wire to the selection, so you can trace a run and then shift-click more wires onto it.
Steps back through every change made this session — placing or deleting a node, drawing a wire, editing a field, adding a dot. Ctrl/Cmd+Z does the same thing. Greyed out with nothing to undo.
Click a start point: a green port marker snaps exactly to that port, empty grid gives a raw coordinate, and clicking on an existing wire or dot snaps exactly onto it. Keep clicking to add via points — corners bend to right angles automatically, and the live preview always shows the actual routed path rather than a straight line to the cursor. Click a port marker, a dot, or an existing wire to finish there — that always ends the draft, it's never added as another via point — or use "Finish wire here" (or Enter) to end on the last point instead, and Escape to cancel. Hold Shift while placing a free-standing point to lock it to a right angle (0/90/180/270) off the last point, the same alignment idea as dragging a node, just axis-locked instead of nearest-neighbour — a pink guide line shows the lock. A wire can't connect two ports on the same component — that's not a real external connection, and trying it (a pilot port to its own valve's other ports is the case this comes up for) turns the draft red with an explanation instead. If you draw a plain wire (no via points) straight between two ports on the SAME component and the direct route would cut through that component's own box, it's routed around it automatically; add your own via point and it'll trust your routing instead. Wires crossing some OTHER, unrelated component still need "Insert clearance points" on the selected wire.
Re-applies whatever Undo just took back. Ctrl/Cmd+Y (or Ctrl/Cmd+Shift+Z) does the same thing. Any new change clears the redo stack, same as any other undo system.
Click empty space to place a new component — a box opens on the right with a search field and a categorised list to pick what goes in. Type to filter, or press Enter to place whichever result is currently on top without reaching for the mouse; arrow keys move that highlight up and down through the results first, so Enter places whichever one you've actually navigated to. Once you've picked one, it follows the mouse showing its real size and shape, snapping to line up with other components exactly like dragging an existing one does — click on the canvas to drop it there, or Escape to cancel and remove it. The same box also switches to rotate/flip controls (R, F, V, or the buttons), Delete, and Advanced node options, usable before or after you've dropped it — click Done (or Enter) when you're finished. Clicking empty space again starts a fresh placement — whatever you just placed is left exactly as you set it. Clicking an EXISTING component instead selects it and switches to Move mode, same as clicking it there would — this never adds a duplicate on top of something already on the sheet.
Drag a node to move it, or a wire's own via points to reshape it. Click a node or wire to select it and edit it on the right — rotate/flip, delete, pilot line, or route around another component. Shift-click to add several nodes to a selection, or drag on empty canvas to rubber-band select a group; a selected group can be dragged, deleted, or distributed evenly together.
Click to add or remove a junction dot. The preview rides along whichever wire is closest to the cursor and snaps exactly onto it, splitting that wire when you click; a pink guide line still shows if that spot also lines up with a port, purely as a heads-up — it won't pull the dot off the wire to chase it. Turn off "Snap to nearby wire" in Snapping behaviours to place a dot in open space near a wire instead — alignment to ports still applies, then falls back to the raw grid point. Click an existing dot to remove it.
| A | Insert a component: click the sheet, then search |
| W | Draw a wire: click a port, then another |
| S | Move and select |
| D | Add or remove a junction dot |
| Ctrl+Z / Ctrl+Y | Undo / redo |
| Ctrl+C / Ctrl+V | Copy / paste the selection |
| Del | Delete what is selected |
| R F V | Rotate, flip across, flip up and down |
| Arrows | Nudge one grid step (Shift for a bigger step) |
| Enter / Esc | Finish / cancel a wire |
| Shift-click, or drag on empty sheet | Select several |
| Ctrl+scroll | Zoom |
| Alt+drag | Pan |
| ? | This list |
Three steps to a circuit
Or paste a saved circuit under Export / Import. ? lists every shortcut.
Add a component to remove this message.
Not drawing. Switch to "Draw wire" and click a start point.
Matches wire.pilot in core.js — the real renderer draws this dashed the same way.
For the rare case a wire needs to clear a THIRD component neither of its own ends belongs to — routing around either end's own component already happens automatically as you draw. Replaces this wire's via points with a route hugging just outside that node's box the whole way. Nudge the points afterward if needed.
—
Anchor is where inside the box the pinned port sits — 0.5/0.5 is dead centre, 0.5/1 is bottom-middle, etc. Only used when the ref/port isn't in the known-parts library.
Outer/inner is read the way the signal travels: outer is outermost on the drawing, inner is nearest the spool — e.g. a two-stage valve is outer "solenoid", inner "pilot". Leave inner blank for a single-stage chain.
This has to be a real port on the combination above for sizing to use the true aspect ratio — it's kept in sync automatically as you change body/actuators.
One line per valve node — free text, since position names differ by valve type.
Click a wire to select it — its role/colour/etc. show above.