@name Snake Game
@inputs EGP:wirelink Button
@outputs Target:entity Use Active Test:string Gamespeed
@persist [Pos Move Direction Food GridLoc]:vector2 [W A S D Sections Score Active]
@persist [Death Obst]:array HighScore CurrentMove
interval(Active ? 15 : 500)
runOnChat(1)
runOnKeys(Target,1)

GameSpeed = 300
Resolution = 2
###########################
BlockS = 64/Resolution
GridS = 8*Resolution

if (first()) {
    timer("curpos",500)
    EGP:egpClear()
} elseif (keyClk(Target)) {
    local Presser = keyClk() #gets the person who caused this key event to trigger
    local Pressed = keyClk(Presser) #returns 1 if the key was pressed, -1 if it was released
    local Key = keyClkPressed() #get the key that was pressed (or released)
    Test = Key
    timer("curpos2",500)
}

if(clk("curpos2")){
    Test=""}

if(clk("curpos")){
    findByClass("player")
    Target = findClosest(entity():pos())
    timer("curpos",500)}

if(Button ==1){
    Active=1
}
else{
    Active=0
}



if(Test =="left"){
    A=1
}
else{
    A=0
}

if(Test =="up"){
    W=1
}
else{
    W=0
}

if(Test =="down"){
    S=1
}
else{
    S=0
}

if(Test =="right"){
    D=1
}
else{
    D=0
}

function vector2 gridLoc(Position:vector2){
    X1 = (BlockS/2) + ((Position:x()-1)*BlockS)
    Y1 = (BlockS/2) + (BlockS * (Position:y()-1)) 

    return (vec2(X1, Y1))
}

function void newFood(){
    while (Food == Pos){
        Food = vec2(randint(1, GridS), randint(1, GridS))
    }     
    EGP:egpPos(184, gridLoc(Food))
}

function void init(){
    EGP:egpClear()
    Pos = vec2(GridS/2,GridS/2)
    Sections = 1
    Score = 0
    Move = vec2()
    Direction = vec2()
    CurrentMove = 1
    Obst:clear()
    
    EGP:egpBox(1, gridLoc(Pos), vec2(BlockS, BlockS))
    EGP:egpCircle(184, gridLoc(Food), vec2(BlockS/2, BlockS/2))
    EGP:egpColor(184, vec(0, 0, 255))
    EGP:egpText(185, "Score: "+Score, vec2(100, 0))
    EGP:egpText(186, "High Score: "+HighScore, vec2(300, 0))
    EGP:egpFont(185, "Arial")
    EGP:egpFont(186, "Arial")
}

function void lose(){
    newFood()
    if (Active){
        init()
        timer("tick", GameSpeed)
    }
    else{
        EGP:egpClear()
    }
}

function void deathCheck(){
    for (I = 1, Sections){
        if (CurrentMove != I){
            if (EGP:egpPos(CurrentMove) == Death[I, vector2]){
                lose()
            }
        }
    }
    
    for (I = 1, Obst:count()){
        if (EGP:egpPos(CurrentMove) == Obst[I, vector2]){
            lose()   
        }   
    }   
}

if (first()|dupefinished()){
    lose()
}

if (clk("tick")){
    if (Active){
        timer("tick", GameSpeed)
    }

    if (Sections >= 1){    
        CurrentMove++
        if (CurrentMove > Sections){
            CurrentMove = 1   
        }
    }
    
    if (changed(Score) && (Score/10 - Score%10)%1 == 0 && Score != 0){
        ObstVec = Pos
        
        while (ObstVec == Pos){
            ObstVec = vec2(randint(1, GridS), randint(1, GridS))
        }
        
        EGP:egpBox(187 + int(Score/10), gridLoc(ObstVec), vec2(BlockS, BlockS))
        Obst:pushVector2(EGP:egpPos(260 + int(Score/10)))
        EGP:egpColor(187 + int(Score/10), vec(255,0,0))
    }
    
    Pos += Move
    Direction = Move
    EGP:egpPos(CurrentMove, gridLoc(Pos))
    
    if (Pos:x() < 1 | Pos:x() > GridS | Pos:y() < 1 | Pos:y() > GridS){
        lose()
    }
    
    if (Pos == Food){
        Score++
        HighScore = HighScore < Score ? Score : HighScore
        EGP:egpText(185, "Score: "+Score, vec2(100, 0))
        EGP:egpText(186, "High Score: "+HighScore, vec2(300, 0))
        newFood()
        Sections += 1 
        EGP:egpBox(Sections, gridLoc(vec2()), vec2(BlockS, BlockS)) 
    }
    
    Death:clear()  
    
    for (I = 2, Sections){
        Death:insertVector2(I, EGP:egpPos(I))   
    }
    
    deathCheck()
}

if (D & $D & Direction != vec2(-1,0)){
    Move = vec2(1, 0)
}
elseif (A & $A & Direction != vec2(1,0)){
    Move = vec2(-1, 0)
}
elseif (W & $W & Direction != vec2(0,1)){
    Move = vec2(0, -1)
}
elseif (S & $S & Direction != vec2(0,-1)){
    Move = vec2(0, 1)
}

if ($Active){
    if (!Active){
        lose()
    }
    if (Active){
        init()
        timer("tick", GameSpeed)
    }
}
