@name trt2
@inputs 
@outputs Can
@persist Tetrominoes:table Game:table Piece:table D Red
@trigger none

if (first()) {
    
    function table createGame() {
        return table(
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
    }

    function print_game( G:table ) {
        local Colors = array(
            0 = vec(155, 155, 155),
            1 = vec(255,   0,   0),
            2 = vec(255, 255,   0)
        )
        
        printColor(vec(255, 255, 255), "      Tetris")
        for (R = 1, 16) {
            local A = G[R, array]
            printColor(
                Colors[A[1, number], vector],  (A[1, number] > 0)  + " ",
                Colors[A[2, number], vector],  (A[2, number] > 0)  + " ",
                Colors[A[3, number], vector],  (A[3, number] > 0)  + " ",
                Colors[A[4, number], vector],  (A[4, number] > 0)  + " ",
                Colors[A[5, number], vector],  (A[5, number] > 0)  + " ",
                Colors[A[6, number], vector],  (A[6, number] > 0)  + " ",
                Colors[A[7, number], vector],  (A[7, number] > 0)  + " ",
                Colors[A[8, number], vector],  (A[8, number] > 0)  + " ",
                Colors[A[9, number], vector],  (A[9, number] > 0)  + " ",
                Colors[A[10, number], vector], (A[10, number] > 0) + " "
            ) 
        }
    }
    
    function table createTetrominoType(Name:string, Shape:table) {
        Tetrominoes[Name, table] = table(
            "shape" = Shape,
            "row"   = 1,
            "col"   = 1
        )    
    }
    
    function table createTetromino(Name:string, Color, Row, Col) {
        local Data  = Tetrominoes[Name, table]:clone()
        local Shape = Data["shape", table]    
        
        for (ShapeRow = 1, Shape:count()) {
            local Index = Shape[ShapeRow, array]
            for (ShapeCol = 1, Index:count()) {
                Index[ShapeCol, number] = Color    
            }
        }
    
        Data["row", number] = Row
        Data["col", number] = Col  
        
        return Data  
    }
    
    function number table:canMoveTetromino(Game:table, RowDir, ColDir) {
        local NextRow = This["row", number] + RowDir
        local NextCol = This["col", number] + ColDir
        local Shape   = This["shape", table]

        for (ShapeRow = 1, Shape:count()) {
            local Index = Shape[ShapeRow, array]
            for (ShapeCol = 1, Index:count()) {
                if (Game[NextRow + ShapeRow, array][NextCol + ShapeCol, number] != 0) {
                    return 0    
                }
                
                if (!inrange(NextRow + ShapeRow, 1, 16)) { return 0 }
                if (!inrange(NextCol + ShapeCol, 1, 10)) { return 0 }
                #if (NextRow + ShapeRow) >= 16) { return 1 }
                #if (NextCol + ShapeCol <= 16
            }
        }
        
        return 1
    }

    function table:moveTetromino(RowDir, ColDir) {
        This["row", number] = This["row", number] + RowDir
        This["col", number] = This["col", number] + ColDir
    }
    
    function table:pushTetromino(Data:table) {
        local Shape = Data["shape", table]
        local Row   = Data["row", number]
        local Col   = Data["col", number]
        
        for (ShapeRow = 1, Shape:count()) {
            local Index = Shape[ShapeRow, array]
            for (ShapeCol = 1, Index:count()) {
                This[ShapeRow + Row, array][ShapeCol + Col, number] = Index[ShapeCol, number]    
            }
        }
    }
    
    function table:popTetromino(Data:table) {
        local Shape = Data["shape", table]
        local Row   = Data["row", number]
        local Col   = Data["col", number]
        
        for (ShapeRow = 1, Shape:count()) {
            local Index = Shape[ShapeRow, array]
            for (ShapeCol = 1, Index:count()) {
                This[ShapeRow + Row, array][ShapeCol + Col, number] = 0    
            }
        }   
    }
    
    createTetrominoType("Square", 
        table(
            array(0, 0),
            array(0, 0)
        )
    )
    
    Red   = 1
    Piece = createTetromino("Square", Red, 1, 4)
    Game  = createGame()

}

interval(500)


Game:pushTetromino(Piece)
print_game(Game)
Game:popTetromino(Piece)

if (Piece:canMoveTetromino(Game, 1, 0)) {
    Piece:moveTetromino(1, 0)

}
else {
    Game:pushTetromino(Piece)
    Piece = createTetromino("Square", Red, 1, 4)
}

