完全にスクリプトが壊れてしまった
(
    delete objects

    global g_dist = 20.0
    global g_z = 10.0
    global g_size = 8.0
    global g_busy = false

    /* ---------- ヘルパー生成（5x5グリッド） ---------- */
    fn randomColor =
    (
        color (random 0 255) (random 0 255) (random 0 255)
    )

/* ---------- ヘルパー生成（5x5グリッド）---------- */
-- 第1列（固定）
global g_A1 = point name:"A1" pos:[0, g_dist*4, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_B1 = point name:"B1" pos:[0, g_dist*3, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_C1 = point name:"C1" pos:[0, g_dist*2, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_D1 = point name:"D1" pos:[0, g_dist, g_z] size:g_size wirecolor:(randomColor()) cross:true

-- 第2列
global g_A2 = point name:"A2" pos:[g_dist, g_dist*4, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_B2 = point name:"B2" pos:[g_dist, g_dist*3, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_C2 = point name:"C2" pos:[g_dist, g_dist*2, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_D2 = point name:"D2" pos:[g_dist, g_dist, g_z] size:g_size wirecolor:(randomColor()) cross:true

-- 第3列
global g_A3 = point name:"A3" pos:[g_dist*2, g_dist*4, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_B3 = point name:"B3" pos:[g_dist*2, g_dist*3, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_C3 = point name:"C3" pos:[g_dist*2, g_dist*2, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_D3 = point name:"D3" pos:[g_dist*2, g_dist, g_z] size:g_size wirecolor:(randomColor()) cross:true

-- 第4列
global g_A4 = point name:"A4" pos:[g_dist*3, g_dist*4, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_B4 = point name:"B4" pos:[g_dist*3, g_dist*3, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_C4 = point name:"C4" pos:[g_dist*3, g_dist*2, g_z] size:g_size wirecolor:(randomColor()) cross:true
global g_D4 = point name:"D4" pos:[g_dist*3, g_dist, g_z] size:g_size wirecolor:(randomColor()) cross:true


/* ---------- 親行固定 ---------- */
for p in #(g_A1, g_B1, g_C1, g_D1) do p.isFrozen = true

/* ---------- ヘルパーのグリッド配列化 ---------- */
global g_grid = #(
    #(g_A1, g_A2, g_A3, g_A4),
    #(g_B1, g_B2, g_B3, g_B4),
    #(g_C1, g_C2, g_C3, g_C4),
    #(g_D1, g_D2, g_D3, g_D4)
)

/* ---------- ベクトル正規化関数 ---------- */
fn safeNormalize v =
(
    local L = length v
    if L < 1e-4 then [1,0,0] else v / L
)
/* ---------- 平行四辺形維持（Z軸固定） ---------- */
fn maintainParallelogram mover =
(
    if g_busy then return()
    g_busy = true

    try
    (
        local baseVec, parent, dirVec
        case mover of
        (
            g_A2: (parent = g_A1; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
            g_B2: (parent = g_B1; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
            g_C2: (parent = g_C1; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
            g_D2: (parent = g_D1; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
            g_A3: (parent = g_A2; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
            g_B3: (parent = g_B2; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
            g_C3: (parent = g_C2; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
            g_D3: (parent = g_D2; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
g_A4: (parent = g_A3; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
g_B4: (parent = g_B3; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
g_C4: (parent = g_C3; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
g_D4: (parent = g_D3; baseVec = [mover.pos.x - parent.pos.x, mover.pos.y - parent.pos.y, 0])
        )

        if parent != undefined do
        (
            dirVec = safeNormalize(baseVec) * g_dist

            -- 各ポイントに応じた処理
            case mover of
            (
                g_A2:
                (
                    g_A2.pos = [g_A1.pos.x + dirVec.x, g_A1.pos.y + dirVec.y, g_A2.pos.z]
                    g_B2.pos = [g_B1.pos.x + dirVec.x, g_B1.pos.y + dirVec.y, g_B2.pos.z]
                    g_C2.pos = [g_C1.pos.x + dirVec.x, g_C1.pos.y + dirVec.y, g_C2.pos.z]
                    g_D2.pos = [g_D1.pos.x + dirVec.x, g_D1.pos.y + dirVec.y, g_D2.pos.z]

                    g_A3.pos = [g_A2.pos.x + (g_A3.pos.x - g_A2.pos.x), g_A2.pos.y + (g_A3.pos.y - g_A2.pos.y), g_A3.pos.z]
                    g_B3.pos = [g_B2.pos.x + (g_B3.pos.x - g_B2.pos.x), g_B2.pos.y + (g_B3.pos.y - g_B2.pos.y), g_B3.pos.z]
                    g_C3.pos = [g_C2.pos.x + (g_C3.pos.x - g_C2.pos.x), g_C2.pos.y + (g_C3.pos.y - g_C2.pos.y), g_C3.pos.z]
                    g_D3.pos = [g_D2.pos.x + (g_D3.pos.x - g_D2.pos.x), g_D2.pos.y + (g_D3.pos.y - g_D2.pos.y), g_D3.pos.z]
                )

                g_B2:
                (
                    g_A2.pos = [g_A1.pos.x + dirVec.x, g_A1.pos.y + dirVec.y, g_A2.pos.z]
                    g_B2.pos = [g_B1.pos.x + dirVec.x, g_B1.pos.y + dirVec.y, g_B2.pos.z]
                    g_C2.pos = [g_C1.pos.x + dirVec.x, g_C1.pos.y + dirVec.y, g_C2.pos.z]
                    g_D2.pos = [g_D1.pos.x + dirVec.x, g_D1.pos.y + dirVec.y, g_D2.pos.z]

                    g_A3.pos = [g_A2.pos.x + (g_A3.pos.x - g_A2.pos.x), g_A2.pos.y + (g_A3.pos.y - g_A2.pos.y), g_A3.pos.z]
                    g_B3.pos = [g_B2.pos.x + (g_B3.pos.x - g_B2.pos.x), g_B2.pos.y + (g_B3.pos.y - g_B2.pos.y), g_B3.pos.z]
                    g_C3.pos = [g_C2.pos.x + (g_C3.pos.x - g_C2.pos.x), g_C2.pos.y + (g_C3.pos.y - g_C2.pos.y), g_C3.pos.z]
                    g_D3.pos = [g_D2.pos.x + (g_D3.pos.x - g_D2.pos.x), g_D2.pos.y + (g_D3.pos.y - g_D2.pos.y), g_D3.pos.z]
                )

                g_C2:
                (
                    g_A2.pos = [g_A1.pos.x + dirVec.x, g_A1.pos.y + dirVec.y, g_A2.pos.z]
                    g_B2.pos = [g_B1.pos.x + dirVec.x, g_B1.pos.y + dirVec.y, g_B2.pos.z]
                    g_C2.pos = [g_C1.pos.x + dirVec.x, g_C1.pos.y + dirVec.y, g_C2.pos.z]
                    g_D2.pos = [g_D1.pos.x + dirVec.x, g_D1.pos.y + dirVec.y, g_D2.pos.z]

                    g_A3.pos = [g_A2.pos.x + (g_A3.pos.x - g_A2.pos.x), g_A2.pos.y + (g_A3.pos.y - g_A2.pos.y), g_A3.pos.z]
                    g_B3.pos = [g_B2.pos.x + (g_B3.pos.x - g_B2.pos.x), g_B2.pos.y + (g_B3.pos.y - g_B2.pos.y), g_B3.pos.z]
                    g_C3.pos = [g_C2.pos.x + (g_C3.pos.x - g_C2.pos.x), g_C2.pos.y + (g_C3.pos.y - g_C2.pos.y), g_C3.pos.z]
                    g_D3.pos = [g_D2.pos.x + (g_D3.pos.x - g_D2.pos.x), g_D2.pos.y + (g_D3.pos.y - g_D2.pos.y), g_D3.pos.z]
                )

                g_D2:
                (
                    g_A2.pos = [g_A1.pos.x + dirVec.x, g_A1.pos.y + dirVec.y, g_A2.pos.z]
                    g_B2.pos = [g_B1.pos.x + dirVec.x, g_B1.pos.y + dirVec.y, g_B2.pos.z]
                    g_C2.pos = [g_C1.pos.x + dirVec.x, g_C1.pos.y + dirVec.y, g_C2.pos.z]
                    g_D2.pos = [g_D1.pos.x + dirVec.x, g_D1.pos.y + dirVec.y, g_D2.pos.z]

                    g_A3.pos = [g_A2.pos.x + (g_A3.pos.x - g_A2.pos.x), g_A2.pos.y + (g_A3.pos.y - g_A2.pos.y), g_A3.pos.z]
                    g_B3.pos = [g_B2.pos.x + (g_B3.pos.x - g_B2.pos.x), g_B2.pos.y + (g_B3.pos.y - g_B2.pos.y), g_B3.pos.z]
                    g_C3.pos = [g_C2.pos.x + (g_C3.pos.x - g_C2.pos.x), g_C2.pos.y + (g_C3.pos.y - g_C2.pos.y), g_C3.pos.z]
                    g_D3.pos = [g_D2.pos.x + (g_D3.pos.x - g_D2.pos.x), g_D2.pos.y + (g_D3.pos.y - g_D2.pos.y), g_D3.pos.z]
                )

                g_A3:
                (
                    g_A3.pos = [g_A2.pos.x + dirVec.x, g_A2.pos.y + dirVec.y, g_A3.pos.z]
                    g_B3.pos = [g_B2.pos.x + dirVec.x, g_B2.pos.y + dirVec.y, g_B3.pos.z]
                    g_C3.pos = [g_C2.pos.x + dirVec.x, g_C2.pos.y + dirVec.y, g_C3.pos.z]
                    g_D3.pos = [g_D2.pos.x + dirVec.x, g_D2.pos.y + dirVec.y, g_D3.pos.z]
                )

                g_B3:
                (
                    g_A3.pos = [g_A2.pos.x + dirVec.x, g_A2.pos.y + dirVec.y, g_A3.pos.z]
                    g_B3.pos = [g_B2.pos.x + dirVec.x, g_B2.pos.y + dirVec.y, g_B3.pos.z]
                    g_C3.pos = [g_C2.pos.x + dirVec.x, g_C2.pos.y + dirVec.y, g_C3.pos.z]
                    g_D3.pos = [g_D2.pos.x + dirVec.x, g_D2.pos.y + dirVec.y, g_D3.pos.z]
                )

                g_C3:
                (
                    g_A3.pos = [g_A2.pos.x + dirVec.x, g_A2.pos.y + dirVec.y, g_A3.pos.z]
                    g_B3.pos = [g_B2.pos.x + dirVec.x, g_B2.pos.y + dirVec.y, g_B3.pos.z]
                    g_C3.pos = [g_C2.pos.x + dirVec.x, g_C2.pos.y + dirVec.y, g_C3.pos.z]
                    g_D3.pos = [g_D2.pos.x + dirVec.x, g_D2.pos.y + dirVec.y, g_D3.pos.z]
                )

                g_D3:
                (
                    g_A3.pos = [g_A2.pos.x + dirVec.x, g_A2.pos.y + dirVec.y, g_A3.pos.z]
                    g_B3.pos = [g_B2.pos.x + dirVec.x, g_B2.pos.y + dirVec.y, g_B3.pos.z]
                    g_C3.pos = [g_C2.pos.x + dirVec.x, g_C2.pos.y + dirVec.y, g_C3.pos.z]
                    g_D3.pos = [g_D2.pos.x + dirVec.x, g_D2.pos.y + dirVec.y, g_D3.pos.z]
                )
            )
        )
    )
    catch
    (
        format "Error in maintainParallelogram: %\n" (getCurrentException())
    )
    finally
    (
        g_busy = false
    )
)
fn adjustNeighbors mover =
(
    if not g_busy then
    (
        g_busy = true
        try
        (
            -- 連鎖調整用キューと処理済みリスト
            local queue = #()
            local processed = #()

            -- 移動したヘルパーをキューに追加
            append queue mover
            append processed mover

            while queue.count > 0 do
            (
                local current = queue[1]
                queue = deleteItem queue 1

                -- 現在のヘルパーがグリッド内の位置を検索
                local row = undefined
                local col = undefined
                for i = 1 to 4 do
                (
                    for j = 1 to 4 do
                    (
                        if g_grid[i][j] == current do
                        (
                            row = i
                            col = j
                            exit
                        )
                    )
                )

                if row != undefined and col != undefined then
                (
                    -- 上下左右の隣接ヘルパーを取得
                    local neighbors = #()
                    if row > 1 then append neighbors g_grid[row-1][col] -- 上
                    if row < 4 then append neighbors g_grid[row+1][col] -- 下
                    if col > 1 then append neighbors g_grid[row][col-1] -- 左
                    if col < 4 then append neighbors g_grid[row][col+1] -- 右

                    -- 隣接ヘルパーを調整
                    for neighbor in neighbors where not neighbor.isFrozen and findItem processed neighbor == 0 do
                    (
                        -- 位置調整
                        local dir = safeNormalize(current.pos - neighbor.pos)
                        neighbor.pos = current.pos - dir * g_dist

                        -- 連鎖処理用にキューに追加
                        append queue neighbor
                        append processed neighbor
                    )
                )
            )

            -- 全ての列の距離を再調整
            for i = 1 to 4 do
            (
                local col1 = g_grid[i][1]
                local col2 = g_grid[i][2]
                local col3 = g_grid[i][3]
                local col4 = g_grid[i][4]

                -- 列間距離の維持（既存ロジック）
                if not col2.isFrozen do
                (
                    local dir = safeNormalize(col2.pos - col1.pos)
                    col2.pos = col1.pos + dir * g_dist
                )
                if not col3.isFrozen do
                (
                    local dir = safeNormalize(col3.pos - col2.pos)
                    col3.pos = col2.pos + dir * g_dist
                )
                if not col4.isFrozen do
                (
                    local dir = safeNormalize(col4.pos - col3.pos)
                    col4.pos = col3.pos + dir * g_dist
                )
            )
        )
        catch (format "Error in adjustNeighbors: %\n" (getCurrentException()))
        finally 
(g_busy = false)
    )
)

/* ---------- 統合制御 ---------- */
fn maintainAllConstraints mover =
(
    maintainParallelogram mover
  --  adjustNeighbors mover
)

/* ---------- ハンドラ登録 ---------- */
deleteAllChangeHandlers id:#NeighborConstraintHandler

local rows = #("A", "B", "C", "D")
local cols = #("2", "3", "4")  -- 第1列は固定なので除外

-- 動的にハンドラーを登録
for row in rows do
(
    for col in cols do
    (
        local varName = "g_" + row + col
        execute ("when transform " + varName + " changes id:#NeighborConstraintHandler do maintainAllConstraints " + varName)
    )
)


format "Setup complete: 全ての列の距離を常時維持する制約システムが有効です。\n"
)
ここまでロールバックして、どのヘルパーを移動しても常に平行四辺形を維持して、隣のヘルパーとの距離が一定になるようにして