Ever since I saw someone do this in graal, I’ve wanted to do the same… from what I remember of that guy’s code it semt very hard to make… ahhh young coders.
In fact, it was pretty easy… I even added a labyrinth mode for fun.
Content of the level’s npc:
// NPC made by 2ndwolf
if (created) {
putnpc ,snakelabyrinth.txt,0,0;
freezeplayer 0.05;
hideplayer 0.05;
startagain();
}
//The initializing function
function startagain(){
this.mode = 0; //0 = Regular snake, 1 = Labyrinth mode, 2 = Menu mode, to be coded
this.origin = {23,23};
this.playboardsize = {18,18};
playerx = this.origin[0]+this.playboardsize[0]/2;
playery = this.origin[1]+this.playboardsize[1]/2;
this.scrollinglimits = {6,6,12,12};
this.hurttile = 0x71F;
this.playtile = 0x937;
this.foodtile = 0x71E;
this.snaketile = 0x936;
this.goaltile = 0x7FF;
this.headpos = {8,8};
this.labyrinthxoffset = 0; //Resets the offsets
this.labyrinthyoffset = 0;
this.snakelength = 3;
setstring this.snaketail,#v(this.headpos[0]),#v(this.headpos[1]),#v(this.headpos[0]),#v(this.headpos[1]);
this.snakespeed = 10; //The bigger the slower
//Empty the board for regular snake mode
for(i=0;i<this.playboardsize[0]*this.playboardsize[1];i++){
if(int(i/this.playboardsize[0])==0 || int(i/this.playboardsize[0])==this.playboardsize[1]-1 || i%this.playboardsize[0]== 0 || i%this.playboardsize[0] == this.playboardsize[0]-1){
tiles[this.origin[0]+i%this.playboardsize[0],this.origin[1]+int(i/this.playboardsize[0])] = this.hurttile;
}
else{
tiles[this.origin[0]+i%this.playboardsize[0],this.origin[1]+int(i/this.playboardsize[0])] = this.playtile;
}
}
placefood();
updateboard this.origin[0],this.origin[1],this.playboardsize[0],this.playboardsize[1];
timeout = 0.05;
}
if(timeout){
freezeplayer 0.05;
hideplayer 0.05;
checkiterations();
//Read the latest pressed key
if(keydown(0)&&this.lastdir!=2)this.dir = 0;
else if(keydown(1)&&this.lastdir!=3)this.dir = 1;
else if(keydown(2)&&this.lastdir!=0)this.dir = 2;
else if(keydown(3)&&this.lastdir!=1)this.dir = 3;
if(this.iterated%this.snakespeed == 0){
//If in labyrinth mode
if(this.mode==1){
//Scroll if snake is near the borders
if(this.headpos[0]<this.scrollinglimits[0]){
this.labyrinthxoffset -= 1;
this.headpos = {this.headpos[0]+1,this.headpos[1]};
for(i=0;i<sarraylen(this.snaketail)/2;i++){
replacestring this.snaketail,i*2,#v(strtofloat(#I(this.snaketail,i*2))+1);
}
}
if(this.headpos[1]<this.scrollinglimits[1]){
this.labyrinthyoffset -= 1;
this.headpos = {this.headpos[0],this.headpos[1]+1};
for(i=0;i<sarraylen(this.snaketail)/2;i++){
replacestring this.snaketail,i*2+1,#v(strtofloat(#I(this.snaketail,i*2+1))+1);
}
}
if(this.headpos[0]>this.scrollinglimits[2]){
this.labyrinthxoffset += 1;
this.headpos = {this.headpos[0]-1,this.headpos[1]};
for(i=0;i<sarraylen(this.snaketail)/2;i++){
replacestring this.snaketail,i*2,#v(strtofloat(#I(this.snaketail,i*2))-1);
}
}
if(this.headpos[1]>this.scrollinglimits[3]){
this.labyrinthyoffset += 1;
this.headpos = {this.headpos[0],this.headpos[1]-1};
for(i=0;i<sarraylen(this.snaketail)/2;i++){
replacestring this.snaketail,i*2+1,#v(strtofloat(#I(this.snaketail,i*2+1))-1);
}
}
//Generate the board's tiles according to what's inside local.snakelabyrinth
for(k=0;k<this.playboardsize[1];k++){
for(j=0;j<this.playboardsize[0];j++){
if(strequals(#I(local.snakelabyrinth,this.labyrinthxoffset+this.labyrinthyoffset*strtofloat(#I(local.snakelabyrinth,0))+j+k*strtofloat(#I(local.snakelabyrinth,0))),X)){
tiles[this.origin[0]+j,this.origin[1]+k] = this.hurttile;
}
else if (strequals(#I(local.snakelabyrinth,this.labyrinthxoffset+this.labyrinthyoffset*strtofloat(#I(local.snakelabyrinth,0))+j+k*strtofloat(#I(local.snakelabyrinth,0))),o)){
tiles[this.origin[0]+j,this.origin[1]+k] = this.foodtile;
}
else if (strequals(#I(local.snakelabyrinth,this.labyrinthxoffset+this.labyrinthyoffset*strtofloat(#I(local.snakelabyrinth,0))+j+k*strtofloat(#I(local.snakelabyrinth,0))),.)){
tiles[this.origin[0]+j,this.origin[1]+k] = this.playtile;
}
else if (strequals(#I(local.snakelabyrinth,this.labyrinthxoffset+this.labyrinthyoffset*strtofloat(#I(local.snakelabyrinth,0))+j+k*strtofloat(#I(local.snakelabyrinth,0))),G)){
tiles[this.origin[0]+j,this.origin[1]+k] = this.goaltile;
}
}
}
}
//If he didn't just eat, let's make the tail follow the head, otherwise let it go longer
if(this.justate==0){
tiles[this.origin[0]+strtofloat(#I(this.snaketail,0)),this.origin[1]+strtofloat(#I(this.snaketail,1))] = this.playtile;
for(i=0;i<sarraylen(this.snaketail)/2;i++){
replacestring this.snaketail,i*2,#I(this.snaketail,i*2+2);
replacestring this.snaketail,i*2+1,#I(this.snaketail,i*2+3);
}
}
this.justate = 0;
//Make the front of the tail equal head's position then make the head get further
replacestring this.snaketail,sarraylen(this.snaketail)-1,#v(this.headpos[1]);
replacestring this.snaketail,sarraylen(this.snaketail)-2,#v(this.headpos[0]);
this.headpos = {this.headpos[0]+vecx(this.dir),this.headpos[1]+vecy(this.dir)}
//Redraw the tail because it might have got overwritten by the labyrinth
for(i=0;i<sarraylen(this.snaketail)/2;i++){
tiles[this.origin[0]+strtofloat(#I(this.snaketail,i*2)),this.origin[1]+strtofloat(#I(this.snaketail,i*2+1))] = this.snaketile;
}
//If you eat yourself or touch a border tile, you lose
if(tiles[this.origin[0]+this.headpos[0],this.origin[1]+this.headpos[1]] == this.hurttile || tiles[this.origin[0]+this.headpos[0],this.origin[1]+this.headpos[1]] == this.snaketile){
say2 Game over;
startagain();
}
//If you eat food
if(tiles[this.origin[0]+this.headpos[0],this.origin[1]+this.headpos[1]] == this.foodtile){
this.snakelength += 1;
addstring this.snaketail,#v(this.headpos[0]);
addstring this.snaketail,#v(this.headpos[1]);
this.justate = 1;
if(this.mode==0){placefood();}
//In labyrinth mode, erase the food from the string
if(this.mode==1){
replacestring local.snakelabyrinth,this.headpos[0]+this.labyrinthxoffset+(this.headpos[1]+this.labyrinthyoffset)*strtofloat(#I(local.snakelabyrinth,0)),.;
}
}
//If you touch the goal
if(tiles[this.origin[0]+this.headpos[0],this.origin[1]+this.headpos[1]] == this.goaltile){
say2 You won!;
}
//Save last dir to keep the snake from turning around directly and eating himself
this.lastdir = this.dir;
tiles[this.origin[0]+this.headpos[0],this.origin[1]+this.headpos[1]] = this.snaketile;
//Finally, update the board
updateboard this.origin[0],this.origin[1],this.playboardsize[0],this.playboardsize[1];
}
timeout = 0.05;
}
//Just a function to check iterations, obvious isn't it!?
function checkiterations(){
this.iterated+=1;
}
//This function places food on the board while in normal mode and activates labyrinth mode once the snake gets long enough
function placefood(){
if(this.snakelength<5){
this.foodpos = {random(this.origin[0],this.origin[0]+this.playboardsize[0]),random(this.origin[1],this.origin[1]+this.playboardsize[1])};
while(tiles[this.foodpos[0],this.foodpos[1]]!=this.playtile){
this.foodpos = {random(this.origin[0],this.origin[0]+this.playboardsize[0]),random(this.origin[1],this.origin[1]+this.playboardsize[1])};
}
tiles[this.foodpos[0],this.foodpos[1]] = this.foodtile;
}
else{
this.mode = 1;
}
}
//Have fun
Content of snakelabyrinth.txt:
if(created){setstring local.snakelabyrinth,58,33,
X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,.,.,.,.,.,.,.,.,.,X,.,.,.,.,.,.,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,.,.,.,.,.,.,.,.,.,X,.,.,.,.,.,.,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,X,X,X,X,X,X,.,.,X,.,.,X,X,X,X,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,.,.,X,.,.,X,.,.,.,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,.,.,X,.,.,X,.,.,.,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,.,.,X,X,.,.,X,X,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,o,o,X,X,X,X,X,X,X,X,X,X,X,X,.,.,.,.,.,X,X,.,.,X,X,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,.,.,.,.,.,X,X,.,.,X,X,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,o,o,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,X,X,X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,X,X,X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,
X,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,.,.,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,g,.,.,.,.,X,
X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,g,.,.,.,.,X,
X,X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
X,X,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
X,X,X,X,X,X,X,X,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
X,X,X,X,X,X,X,X,.,.,.,.,.,.,.,.,.,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X;
}
Behaviour:
Has two modes, labyrinth mode and regular snake mode.
Known bugs:
When you get food on the left side and enter labyrinth mode the snake appears in the wall.
Sometimes a playtile appears on the top left corner while it should be a hurttile.
You reach the bottom of the screen then when you move off to the side it’ll decide to start shifting focus down.
To do:
Needs a labyrinth generator which I’m going to code in python sometime between now and the release of Mistral.
Menu mode.