Skip to content

Maniacs Patch - Expand variable array operations - #3656

Open
jetrotal wants to merge 1 commit into
EasyRPG:masterfrom
EasyRPG-NewFeatures:maniacs/array-commands-update
Open

Maniacs Patch - Expand variable array operations#3656
jetrotal wants to merge 1 commit into
EasyRPG:masterfrom
EasyRPG-NewFeatures:maniacs/array-commands-update

Conversation

@jetrotal

@jetrotal jetrotal commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Extends Maniac ControlVarArray with new operations for dereference, sync sort (asc/desc), sync shuffle, range fill, reverse, and copy-from behavior. Game_Variables now implements these operations and updates array write/copy/swap logic to use ID-based access via Get(), improving handling of out-of-range IDs and overlapping ranges while keeping values clamped.

I had some problems with deref and edge cases related to out of bounds assertions.

Expressions_Test_Suite.zip
Test project also included. It depend on the expressions implementations from #3653
Interact with the Character to the right of the screen to init it.

Test TPC script:
/*start of file ./ultimate_var_arrays_suite.txt*/

// ============================================================================
// VARIABLE ARRAYS USECASE TEST SUITE (100% COVERAGE)
// Covers all Maniac Patch Variable Array operations natively processed
// by the RM2k3 engine, plus scalar broadcasting, dynamic/indirect 
// addressing, math safety guards, and memory overlapping edge-cases.
// ============================================================================

// ----------------------------------------------------------------------------
// Renderer Component
// ----------------------------------------------------------------------------
__fn renderPage $title {
    // Background 
    @pic[9].strpic {
        ""
        .pos 160, 120 .center
        .size 320, 240
        .rgbs 0, 0, 0, 0
        .chromakey 1 .skin "" .stretch
        .mapLayer 6 .eraseWhenTransfer
    }

    // Draw Title
    @pic[10].strpic {
        $title
        .pos 16, 4 .topLeft
        .font "TinyUnicode", 12 .spacing 0, 0 .noShadow
        .chromakey 1 .noframe .noPadding .nobg .noGradation
        .mapLayer 7 .eraseWhenTransfer
    }
    
    // Draw Col 1 (Expressions)
    @pic[11].strpic {
        t[11]
        .pos 16, 16 .topLeft
        .font "TinyUnicode", 12 .spacing 0, -1 .noShadow
        .chromakey 1 .noframe .noPadding .nobg .noGradation
        .mapLayer 7 .eraseWhenTransfer
    }
    
    // Get Col 1 Width and push X for Col 2
    @pic.getInfo [11] .currentRect(v[901], v[902], v[903], v[904]) .xywh
    v[905] = v[901] + v[903] + 8
    
    // Draw Col 2 (Results)
    v[999] = 16
    @pic[12].strpic {
        t[12]
        .pos v[905], v[999] .topLeft
        .font "TinyUnicode", 12 .spacing 0, -1 .noShadow
        .chromakey 1 .noframe .noPadding .nobg .noGradation
        .mapLayer 7 .eraseWhenTransfer
    }
    
    // Get Col 2 Width and push X for Col 3
    @pic.getInfo [12] .currentRect(v[901], v[902], v[903], v[904]) .xywh
    v[905] = v[901] + v[903] + 8
    
    // Draw Col 3 (Expected)
    v[999] = 16
    @pic[13].strpic {
        t[13]
        .pos v[905], v[999] .topLeft
        .font "TinyUnicode", 12 .spacing 0, -1 .noShadow
        .chromakey 1 .noframe .noPadding .nobg .noGradation
        .mapLayer 7 .eraseWhenTransfer
    }
    
    // Draw Footer
    @pic[14].strpic {
        "\C[1](Press Action to continue)\C[0]"
        .pos 260, 230 .center
        .font "TinyUnicode", 12 .spacing 0, -1 .noShadow
        .chromakey 1 .noframe .noPadding .nobg .noGradation
        .mapLayer 7 .eraseWhenTransfer
    }
    
    @wait .input
    @pic.erase [9..14]
}

// ----------------------------------------------------------------------------
// Page 1: Initialization & Copying
// ----------------------------------------------------------------------------
// Note: TPC compilation rules map literals to variables for most array 
// operations, but Repeat and Enum natively support literals.
v[21].repeat(10, 3)      

v[24].enum(11, 3)        

v[24].copyTo(v[27], 3)   
v[30].copyFrom(v[21], 2) 

t[11] .asg "v[21].repeat(10, 3)


v[24].enum(11, 3)


v[24].copyTo(v[27], 3)
v[30].copyFrom(v[21], 2)"

t[12] .asg "
=> [\C[8]\v[21], \v[22], \v[23]\C[0]]



=> [\C[8]\v[24], \v[25], \v[26]\C[0]]


=> [\C[8]\v[27], \v[28], \v[29]\C[0]]
=> [\C[8]\v[30], \v[31]\C[0]]"

t[13] .asg "
\C[4][10, 10, 10]\C[0]



\C[4][11, 12, 13]\C[0]


\C[4][11, 12, 13]\C[0]
\C[4][10, 10]\C[0]"

renderPage("\C[6]--- 1. Array Init & Copying ---\C[0]")

// ----------------------------------------------------------------------------
// Page 2: Array Reordering
// ----------------------------------------------------------------------------
v[21]=1
v[22]=5
v[23]=2
v[24]=4
v[25]=3
v[21].reverse(5)

v[26]=1
v[27]=5
v[28]=2
v[29]=4
v[30]=3
v[26].sort(5)

v[31]=1
v[32]=5
v[33]=2
v[34]=4
v[35]=3
v[31].sortDescending(5)

v[36]=1
v[37]=2
v[38]=3
v[36].shuffle(3)

t[11] .asg "v[21..25] = [1,5,2,4,3]
v[21].reverse(5)

v[26..30] = [1,5,2,4,3]
v[26].sort(5)

v[31..35] = [1,5,2,4,3]
v[31].sortDescending(5)

v[36..38] = [1,2,3]
v[36].shuffle(3)"

t[12] .asg "
=> [\C[8]\v[21], \v[22], \v[23], \v[24], \v[25]\C[0]]


=> [\C[8]\v[26], \v[27], \v[28], \v[29], \v[30]\C[0]]


=> [\C[8]\v[31], \v[32], \v[33], \v[34], \v[35]\C[0]]


=> [\C[8]\v[36], \v[37], \v[38]\C[0]]"

t[13] .asg "
\C[4][3, 4, 2, 5, 1]\C[0]


\C[4][1, 2, 3, 4, 5]\C[0]


\C[4][5, 4, 3, 2, 1]\C[0]


\C[4][Randomized]\C[0]"

renderPage("\C[6]--- 2. Array Reordering ---\C[0]")

// ----------------------------------------------------------------------------
// Page 3: Synced Operations
// ----------------------------------------------------------------------------
v[21]=50
v[22]=10
v[23]=40
v[24]=20
v[25]=30
v[31]=1
 v[32]=2
 v[33]=3
 v[34]=4
 v[35]=5
v[21].sort(5) .sync(v[31])       

v[41]=10
v[42]=30
v[43]=20
v[51]=1
 v[52]=2
 v[53]=3
v[41].sortDescending(3) .sync(v[51])

v[61]=100
v[62]=200
v[63]=300
v[71]=1
  v[72]=2
  v[73]=3
v[61].shuffle(3) .sync(v[71])

t[11] .asg "v[21] (HP) = [50,10,40,20,30]
v[31] (ID) = [1, 2, 3, 4, 5]
v[21].sort(5) .sync(v[31])

v[41] (HP) = [10, 30, 20]
v[51] (ID) = [1, 2, 3]
v[41].sortDesc(3) .sync(v[51])

v[61] = [100, 200, 300]
v[71] = [1, 2, 3]
v[61].shuffle(3) .sync(v[71])"

t[12] .asg "=> HP: [\C[8]\v[21], \v[22], \v[23], \v[24], \v[25]\C[0]]
=> ID: [\C[8]\v[31], \v[32], \v[33], \v[34], \v[35]\C[0]]


=> HP: [\C[8]\v[41], \v[42], \v[43]\C[0]]
=> ID: [\C[8]\v[51], \v[52], \v[53]\C[0]]


=> Val: [\C[8]\v[61], \v[62], \v[63]\C[0]]
=> ID:  [\C[8]\v[71], \v[72], \v[73]\C[0]]
"

t[13] .asg "\C[4][10, 20, 30, 40, 50]\C[0]
\C[4][2,  4,  5,  3,  1]\C[0]


\C[4][30, 20, 10]\C[0]
\C[4][2,  3,  1]\C[0]


\C[4][Randomized]\C[0]
\C[4][Synced IDs]\C[0]
"

renderPage("\C[6]--- 3. Synced Array Operations ---\C[0]")

// ----------------------------------------------------------------------------
// Page 4: Array-to-Array Math
// ----------------------------------------------------------------------------
v[21]=10
v[22]=20
v[31]=5
 v[32]=5
v[21].add(v[31], 2)

v[23]=10
v[24]=20
v[33]=5
 v[34]=5
v[23].sub(v[33], 2)

v[25]=10
v[26]=20
v[35]=5
 v[36]=5
v[25].mul(v[35], 2)

v[27]=10
v[28]=20
v[37]=5
 v[38]=5
v[27].div(v[37], 2)

v[29]=14
v[30]=21
v[39]=5
 v[40]=5
v[29].mod(v[39], 2)

t[11] .asg "a=[10, 20], b=[5, 5]
v[21].add(v[31], 2)
v[23].sub(v[33], 2)
v[25].mul(v[35], 2)
v[27].div(v[37], 2)
v[29].mod(v[39], 2)"

t[12] .asg "
=> [\C[8]\v[21], \v[22]\C[0]]
=> [\C[8]\v[23], \v[24]\C[0]]
=> [\C[8]\v[25], \v[26]\C[0]]
=> [\C[8]\v[27], \v[28]\C[0]]
=> [\C[8]\v[29], \v[30]\C[0]]"

t[13] .asg "
\C[4][15, 25]\C[0]
\C[4][5, 15]\C[0]
\C[4][50, 100]\C[0]
\C[4][2, 4]\C[0]
\C[4][4, 1]\C[0]"

renderPage("\C[6]--- 4. Array-to-Array Math ---\C[0]")

// ----------------------------------------------------------------------------
// Page 5: Scalar-to-Array Broadcasting
// ----------------------------------------------------------------------------
// Array operations natively apply pairwise. To safely broadcast a scalar
// across the array without relying on expressions, we fill a temp array.
v[21]=1
v[22]=2
v[23]=3
v[10]=10
v[10].repeat(v[10], 3)
v[21].add(v[10], 3)

v[24]=10
v[25]=20
v[26]=30
v[13]=5
v[13].repeat(v[13], 3)
v[24].sub(v[13], 3)

v[27]=1
v[28]=2
v[29]=3
v[16]=-2
v[16].repeat(v[16], 3)
v[27].mul(v[16], 3)

v[30]=100
v[31]=200
v[32]=300
v[19]=10
v[19].repeat(v[19], 3)
v[30].div(v[19], 3)

v[33]=15
v[34]=20
v[35]=25
v[222]=10 
v[222].repeat(v[222], 3)
v[33].mod(v[222], 3)

t[11] .asg "v[21..23] = [1, 2, 3]
v[10]=10
v[10].repeat(v[10], 3)
v[21].add(v[10], 3)

v[24..26] = [10, 20, 30]
v[13]=5
v[13].repeat(v[13], 3)
v[24].sub(v[13], 3)

v[27..29] = [1, 2, 3]
v[16]=-2
v[16].repeat(v[16], 3)
v[27].mul(v[16], 3)

v[30..32] = [100, 200, 300]
v[19]=10
v[19].repeat(v[19], 3)
v[30].div(v[19], 3)

v[33..35] = [15, 20, 25]
v[222]=10
v[222].repeat(v[222], 3)
v[33].mod(v[222], 3)"

t[12] .asg "

=> [\C[8]\v[21], \v[22], \v[23]\C[0]]



=> [\C[8]\v[24], \v[25], \v[26]\C[0]]



=> [\C[8]\v[27], \v[28], \v[29]\C[0]]



=> [\C[8]\v[30], \v[31], \v[32]\C[0]]



=> [\C[8]\v[33], \v[34], \v[35]\C[0]]"

t[13] .asg "

\C[4][11, 12, 13]\C[0]



\C[4][5, 15, 25]\C[0]



\C[4][-2, -4, -6]\C[0]



\C[4][10, 20, 30]\C[0]



\C[4][5, 0, 5]\C[0]"

renderPage("\C[6]--- 5. Scalar-to-Array Math (Broadcast) ---\C[0]")

// ----------------------------------------------------------------------------
// Page 6: Engine Guards (Div/Mod by Zero) & Edge Cases
// ----------------------------------------------------------------------------
v[21]=50
v[22]=100
v[31]=0
 v[32]=0
v[21].div(v[31], 2)

v[23]=45
v[24]=95
v[33]=0
 v[34]=0
v[23].mod(v[33], 2)

v[25]=1
v[26]=2
v[35]=100
v[36]=100
v[25].add(v[35], 0)

// Div by -1 works, but forcing a negative literal natively fails.
v[27]=7
v[28]=7
v[37]=-1
v[38]=-1
v[27].div(v[37], 2)

t[11] .asg "a=[50, 100], b=[0, 0]
v[21].div(v[31], 2)  (Div by 0)

a=[45, 95], b=[0, 0]
v[23].mod(v[33], 2)  (Mod by 0)

v[25..26] = [1, 2]
v[25].add(v[35], 0)  (Count 0)

a=[7, 7], b=[-1, -1]
v[27].div(v[37], 2)  (Negative Div)"

t[12] .asg "
=> [\C[8]\v[21], \v[22]\C[0]]


=> [\C[8]\v[23], \v[24]\C[0]]


=> [\C[8]\v[25], \v[26]\C[0]]


=> [\C[8]\v[27], \v[28]\C[0]]"

t[13] .asg "
\C[4][50, 100]\C[0]


\C[4][0, 0]\C[0]


\C[4][1, 2]\C[0]


\C[4][-7, -7]\C[0]"

renderPage("\C[6]--- 6. Math Safety Guards (Zero/Edge) ---\C[0]")

// ----------------------------------------------------------------------------
// Page 7: Array Bitwise
// ----------------------------------------------------------------------------
v[21]=5
v[22]=5
v[31]=3
v[32]=2
v[21].and(v[31], 2)

v[23]=5
v[24]=5
v[33]=3
v[34]=2
v[23].or(v[33], 2)

v[25]=5
v[26]=5
v[35]=3
v[36]=2
v[25].xor(v[35], 2)

v[27]=3
v[28]=3
v[37]=1
v[38]=2
v[27].shl(v[37], 2)

v[29]=16
v[30]=16
v[39]=1
v[40]=2
v[29].shr(v[39], 2)

t[11] .asg "a=[5, 5], b=[3, 2]
v[21].and(v[31], 2)
v[23].or(v[33], 2)
v[25].xor(v[35], 2)
v[27].shl(v[37], 2) 
v[29].shr(v[39], 2) "

t[12] .asg "
=> [\C[8]\v[21], \v[22]\C[0]]
=> [\C[8]\v[23], \v[24]\C[0]]
=> [\C[8]\v[25], \v[26]\C[0]]
=> [\C[8]\v[27], \v[28]\C[0]]
=> [\C[8]\v[29], \v[30]\C[0]]"

t[13] .asg "
\C[4][1, 0]\C[0]
\C[4][7, 7]\C[0]
\C[4][6, 7]\C[0]
\C[4][6, 12]\C[0]
\C[4][8, 4]\C[0]"

renderPage("\C[6]--- 7. Array Bitwise Math ---\C[0]")

// ----------------------------------------------------------------------------
// Page 8: Scalar-to-Array Bitwise
// ----------------------------------------------------------------------------
// Same pattern as math, use a temp array for clean native broadcast.
v[21]=2
v[22]=6
v[10]=2
v[10].repeat(v[10], 2)
v[21].and(v[10], 2)

v[23]=4
v[24]=1
v[12]=2
v[12].repeat(v[12], 2)
v[23].or(v[12], 2)

v[25]=7
v[26]=2
v[14]=2
v[14].repeat(v[14], 2)
v[25].xor(v[14], 2)

v[27]=1
v[28]=2
v[16]=3
v[16].repeat(v[16], 2)
v[27].shl(v[16], 2)

v[29]=16
v[30]=32
v[18]=2
v[18].repeat(v[18], 2)
v[29].shr(v[18], 2)

t[11] .asg "v[21..22] = [2, 6]
v[10]=2
v[10].repeat(v[10], 2)
v[21].and(v[10], 2)

v[23..24] = [4, 1]
v[12]=2
v[12].repeat(v[12], 2)
v[23].or(v[12], 2)

v[25..26] = [7, 2]
v[14]=2
v[14].repeat(v[14], 2)
v[25].xor(v[14], 2)

v[27..28] = [1, 2]
v[16]=3
v[16].repeat(v[16], 2)
v[27].shl(v[16], 2)

v[29..30] = [16, 32]
v[18]=2
v[18].repeat(v[18], 2)
v[29].shr(v[18], 2)"

t[12] .asg "

=> [\C[8]\v[21], \v[22]\C[0]]



=> [\C[8]\v[23], \v[24]\C[0]]



=> [\C[8]\v[25], \v[26]\C[0]]



=> [\C[8]\v[27], \v[28]\C[0]]



=> [\C[8]\v[29], \v[30]\C[0]]"

t[13] .asg "

\C[4][2, 2]\C[0]



\C[4][6, 3]\C[0]



\C[4][5, 0]\C[0]



\C[4][8, 16]\C[0]



\C[4][4, 8]\C[0]"

renderPage("\C[6]--- 8. Scalar-to-Array Bitwise ---\C[0]")

// ----------------------------------------------------------------------------
// Page 9: Swap & Pointers (Deref)
// ----------------------------------------------------------------------------
v[21]=1
v[22]=2
v[23]=3
v[31]=9
v[32]=8
v[33]=7
v[21].swap(v[31], 3)

v[41]=31
v[42]=32
v[43]=33  
// Deref assigns v[Target] = v[v[Operand]]. 
// Because of the swap above, v[31..33] evaluates to [1, 2, 3].
v[51].deref(v[41], 3)

t[11] .asg "v[21] = [1,2,3], v[31] = [9,8,7]
v[21].swap(v[31], 3)


v[41] (Pointers) = [31, 32, 33]
(v[31..33] is now [1, 2, 3])
v[51].deref(v[41], 3)"

t[12] .asg "
=> v[21]: [\C[8]\v[21], \v[22], \v[23]\C[0]]
=> v[31]: [\C[8]\v[31], \v[32], \v[33]\C[0]]



=> v[51]: [\C[8]\v[51], \v[52], \v[53]\C[0]]"

t[13] .asg "
\C[4][9, 8, 7]\C[0]
\C[4][1, 2, 3]\C[0]



\C[4][1, 2, 3]\C[0]"

renderPage("\C[6]--- 9. Swap & Pointers (Deref) ---\C[0]")

// ----------------------------------------------------------------------------
// Page 10: Memory Overlapping Safety (copyTo)
// ----------------------------------------------------------------------------
v[21]=1
v[22]=2
v[23]=3
v[24]=4
v[25]=5
v[21].copyTo(v[22], 4)

v[31]=1
v[32]=2
v[33]=3
v[34]=4
v[35]=5
v[32].copyTo(v[31], 4)

t[11] .asg "v[21..25] = [1,2,3,4,5]
v[21].copyTo(v[22], 4) (Forward)


v[31..35] = [1,2,3,4,5]
v[32].copyTo(v[31], 4) (Backward)"

t[12] .asg "
=> [\C[8]\v[21], \v[22], \v[23], \v[24], \v[25]\C[0]]



=> [\C[8]\v[31], \v[32], \v[33], \v[34], \v[35]\C[0]]"

t[13] .asg "
\C[4]If safe:   [1, 1, 2, 3, 4]\C[0]
\C[4]If unsafe: [1, 1, 1, 1, 1]\C[0]


\C[4]If safe:   [2, 3, 4, 5, 5]\C[0]
\C[4]If unsafe: [2, 3, 4, 5, 5]\C[0]"

renderPage("\C[6]--- 10. Memory Overlap (copyTo) ---\C[0]")

// ----------------------------------------------------------------------------
// Page 11: Memory Overlapping Safety (copyFrom & swap)
// ----------------------------------------------------------------------------
v[21]=1
v[22]=2
v[23]=3
v[24]=4
v[25]=5
v[22].copyFrom(v[21], 4)

v[31]=1
v[32]=2
v[33]=3
v[34]=4
v[35]=5
v[31].copyFrom(v[32], 4)

v[41]=1
v[42]=2
v[43]=3
v[44]=4
v[41].swap(v[42], 3)

t[11] .asg "v[21..25] = [1,2,3,4,5]
v[22].copyFrom(v[21], 4) (Forward)


v[31..35] = [1,2,3,4,5]
v[31].copyFrom(v[32], 4) (Backward)


v[41..44] = [1,2,3,4]
v[41].swap(v[42], 3) (Overlap)"

t[12] .asg "
=> [\C[8]\v[21], \v[22], \v[23], \v[24], \v[25]\C[0]]



=> [\C[8]\v[31], \v[32], \v[33], \v[34], \v[35]\C[0]]



=> [\C[8]\v[41], \v[42], \v[43], \v[44]\C[0]]"

t[13] .asg "
\C[4]If safe:   [1, 1, 2, 3, 4]\C[0]
\C[4]If unsafe: [1, 1, 1, 1, 1]\C[0]


\C[4]If safe:   [2, 3, 4, 5, 5]\C[0]
\C[4]If unsafe: [2, 3, 4, 5, 5]\C[0]


\C[4]Engine Det: [2, 3, 4, 1]\C[0]"

renderPage("\C[6]--- 11. Memory Overlap (copyFrom & swap) ---\C[0]")

// ----------------------------------------------------------------------------
// Page 12: Fully Dynamic & Indirect Addressing
// ----------------------------------------------------------------------------
v[1] = 5
v[2] = 3
v[10] = 5
v[21].repeat(v[10], v[2]) // Dynamic Repeat 

v[3] = 100
v[4] = 2
v[11] = 100
v[25].enum(v[11], v[4]) // Dynamic Enum 

v[10] = 30
v[11] = 33
v[12] = 2
v[30]=99
v[31]=88
v[v[10]].copyTo(v[v[11]], v[12]) // Indirect Copy

v[15] = 51
v[16] = 54
v[17] = 2
v[51]=61
v[52]=62
v[61]=77
v[62]=88
v[v[16]].deref(v[v[15]], v[17]) // Indirect Deref

t[11] .asg "v[10]=5, v[2]=3 (Count)
v[21].repeat(v[10], v[2])

v[11]=100, v[4]=2 (Count)
v[25].enum(v[11], v[4])

v[10]=30, v[11]=33, v[12]=2
v[v[10]].copyTo(v[v[11]], v[12])

v[15]=51, v[16]=54, v[17]=2
v[v[16]].deref(v[v[15]], v[17])"

t[12] .asg "
=> [\C[8]\v[21], \v[22], \v[23]\C[0]]


=> [\C[8]\v[25], \v[26]\C[0]]


=> [\C[8]\v[33], \v[34]\C[0]]


=> [\C[8]\v[54], \v[55]\C[0]]"

t[13] .asg "
\C[4][5, 5, 5]\C[0]


\C[4][100, 101]\C[0]


\C[4][99, 88]\C[0]


\C[4][77, 88]\C[0]"

renderPage("\C[6]--- 12. Dynamic Args & Indirect Targeting ---\C[0]")

// ----------------------------------------------------------------------------
// Page 13: Compiler Edge Cases & Extended Logic
// ----------------------------------------------------------------------------
// 1. Array Truncation (Source shorter than Target safely pads with 0)
v[21]=9
v[22]=9
v[23]=9
v[24]=9
v[25]=9 
v[899]=1
v[900]=2
// Variable 901+ is 0
v[21].copyFrom(v[899], 5)

// 2. Reverse ignores Sync (Hardcoded Compiler/Engine Limitation)
v[31]=1
v[32]=2
v[33]=3
v[34]=4
v[35]=5
v[41]=1
v[42]=2
v[43]=3
v[44]=4
v[45]=5
v[31].reverse(5) .sync(v[41]) 

// 3. Double Indirect Math & Lengths
v[1] = 51   // Target ptr
v[2] = 54   // Source ptr
v[3] = 2    // Length ptr
v[51]=100
v[52]=200
v[54]=20
 v[55]=30
v[v[1]].add(v[v[2]], v[3])

t[11] .asg "v[21..25] = [9, 9, 9, 9, 9]
v[899]=1
v[900]=2
v[21].copyFrom(v[899], 5)

v[31] = [1, 2, 3, 4, 5]
v[41] = [1, 2, 3, 4, 5]
v[31].reverse(5) .sync(v[41])

v[1]=51, v[2]=54, v[3]=2
v[v[1]].add(v[v[2]], v[3])"

t[12] .asg "


=> [\C[8]\v[21], \v[22], \v[23], \v[24], \v[25]\C[0]]



=> Val: [\C[8]\v[31], \v[32], \v[33], \v[34], \v[35]\C[0]]
=> ID:  [\C[8]\v[41], \v[42], \v[43], \v[44], \v[45]\C[0]]


=> [\C[8]\v[51], \v[52]\C[0]]"

t[13] .asg "


\C[4][1, 2, 0, 0, 0]\C[0]



\C[4][5, 4, 3, 2, 1]\C[0]
\C[4]NOT SYNCED! [1..5]\C[0]


\C[4][120, 230]\C[0]"

renderPage("\C[6]--- 13. Compiler & Indirect Edge Cases ---\C[0]")

/*end of file ./ultimate_var_arrays_suite.txt*/
Test screenshots (Ignore the yellow test at the end, It did not considered maniacs quirks) image image image image image image image image image image image image image

Extends Maniac ControlVarArray with new operations for dereference, sync sort (asc/desc), sync shuffle, range fill, reverse, and copy-from behavior. Game_Variables now implements these operations and updates array write/copy/swap logic to use ID-based access via Get(), improving handling of out-of-range IDs and overlapping ranges while keeping values clamped.

I had some problems with deref and edge cases related to out of bounds assertions.

Test project also included
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant