Give the graph a loop, and build Tetris with it

A Tetris example project needs to draw 200 board cells and scan rows
for a full line. Neither is expressible without iteration, so the node
system gets a Repeat node plus the missing text side: Substring, Find
text and To number. The interpreter drops its data cache once per
round -- otherwise every round would recompute with the first round's
values.

Object by name takes its name as an input now, not just as a setting;
addressing "c" + index is impossible otherwise. An unconnected input
reads the stored setting, so saved projects are untouched.

The board itself is a 200-character text, "." for empty. That makes
both operations of Tetris a single expression instead of a loop, and
each frame attempts exactly one move -- rotate beats sideways beats
fall -- so the fit check exists once in the whole graph.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Opus 5 committed 2026-09-09 19:10:41 +02:00
1 parent 9c4148dc1b
commit 4f78c7518c
16 files changed
+1479 -25

No files matched your search

+19
View File
@@ -0,0 +1,19 @@
import type { NodeDef } from '../../NodeRegistry';
import { asNumber } from '../../values';
import { exec, num, withDefault } from '../shared';
export const Repeat: NodeDef = {
type: 'Repeat',
label: 'Repeat',
category: 'flow',
description:
'Runs "body" a number of times, counting "index" up from 0, and continues at "done" afterwards. ' +
'Every round reads its data inputs anew, so an expression built on "index" changes with it.',
inputs: [exec(), withDefault(num('times'), 1)],
outputs: [exec('body', 'body'), num('index'), exec('done', 'done')],
params: [],
run: (_ctx, inputs) => ({
repeat: { port: 'body', index: 'index', times: Math.max(0, Math.floor(asNumber(inputs.times))) },
next: 'done',
}),
};