Tetris

So I’ve made a port of tetris using gscript. Ever since I saw a screenshot of a tetris game running on Graal 2001 it became my main goal.
It made me realize also that programming wasn’t that hard and that if kids could put tetris in graal, why couldn’t I?

So here it is… it’s not fully complete… it doesn’t speed up with the score but I have other plans for it.

[CODE]//NPC made by 2ndwolf
if (created) {
playerx =10;
playery = 10;
//Global Vars
//Init

alltetrominos =
//Z
{1,1,0,0,
0,1,1,0,
0,0,0,0,
0,0,0,0,

0,1,0,0,
1,1,0,0,
1,0,0,0,
0,0,0,0,

1,1,0,0,
0,1,1,0,
0,0,0,0,
0,0,0,0,

0,1,0,0,
1,1,0,0,
1,0,0,0,
0,0,0,0,
  //S
0,1,1,0,
1,1,0,0,
0,0,0,0,
0,0,0,0,

1,0,0,0,
1,1,0,0,
0,1,0,0,
0,0,0,0,

0,1,1,0,
1,1,0,0,
0,0,0,0,
0,0,0,0,

1,0,0,0,
1,1,0,0,
0,1,0,0,
0,0,0,0,
  //L
1,0,0,0,
1,0,0,0,
1,1,0,0,
0,0,0,0,

1,1,1,0,
1,0,0,0,
0,0,0,0,
0,0,0,0,

1,1,0,0,
0,1,0,0,
0,1,0,0,
0,0,0,0,

0,0,1,0,
1,1,1,0,
0,0,0,0,
0,0,0,0,

//J
0,1,0,0,
0,1,0,0,
1,1,0,0,
0,0,0,0,

1,0,0,0,
1,1,1,0,
0,0,0,0,
0,0,0,0,

1,1,0,0,
1,0,0,0,
1,0,0,0,
0,0,0,0,

1,1,1,0,
0,0,1,0,
0,0,0,0,
0,0,0,0,

//O
1,1,0,0,
1,1,0,0,
0,0,0,0,
0,0,0,0,

1,1,0,0,
1,1,0,0,
0,0,0,0,
0,0,0,0,

1,1,0,0,
1,1,0,0,
0,0,0,0,
0,0,0,0,

1,1,0,0,
1,1,0,0,
0,0,0,0,
0,0,0,0,

//I
1,1,1,1,
0,0,0,0,
0,0,0,0,
0,0,0,0,

1,0,0,0,
1,0,0,0,
1,0,0,0,
1,0,0,0,

1,1,1,1,
0,0,0,0,
0,0,0,0,
0,0,0,0,

1,0,0,0,
1,0,0,0,
1,0,0,0,
1,0,0,0,

//T
1,1,1,0,
0,1,0,0,
0,0,0,0,
0,0,0,0,

0,1,0,0,
1,1,0,0,
0,1,0,0,
0,0,0,0,

0,1,0,0,
1,1,1,0,
0,0,0,0,
0,0,0,0,

1,0,0,0,
1,1,0,0,
1,0,0,0,
0,0,0,0};

tetromino.colors =
{ 1,0,0,
1,1,0,
0,0,1,
.8,.33,0,
0,.6,1,
.4,1,0,
1,0,1};

tetromino.type = 0;

tetromino.type.wait = 0;

imgindexs = 100;

tetromino.allflips = 64;
tetromino.oneflip = 16;
tetromino.width = 4;
playing.board.width = 10;
playing.board.height = 20;
playing.limits.width = 12;
playing.board.start = 4;
playing.prevision.width = 8;
tetromino.falling = 0;
tetromino.falling.dropstate = -1;
tetromino.destroying = -1;

game.speed = 20;

game.origin = {10,10};

atomsize = {1,1};

setarray this.key,10;

playing.board =
{0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0};

playing.board.previous =
{0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0};

setarray this.coords,arraylen(playing.board)*2;
setarray tetromino.atoms.pos,tetromino.oneflip;
setarray tetromino.atoms.oldpos,tetromino.oneflip;
setarray atom.type,arraylen(playing.board);
setarray freseen.indexs,4;

for(this.i=0;this.i<arraylen(this.coords)/2;this.i++){
this.coords[this.i*2] = game.origin[0]+this.i-int(this.i/playing.board.width)playing.board.width;
this.coords[this.i
2+1] = game.origin[1]+int(this.i/playing.board.width);
if(this.i<arraylen(freseen.indexs)){
freseen.indexs[this.i] = imgindexs;
imgindexs++;
}
}

foreseetetromino();
detach();

this.timeout.time = 0.05;

timeout = this.timeout.time;
}

if(timeout){
tetromino.pushed.down = 0;

//tetromino.falling.dropstate -1 = just dropped
//tetromino.falling.dropstate 0 = new tetromino required
//tetromino.falling.dropstate 1 = tetromino falling
//tetromino.destroying = 1 destroy lines
//tetromino.destroying = 0 drop lines
//tetromino.destroying =-1 done

if (tetromino.falling.dropstate==-1){
detach();
}
if(tetromino.falling.dropstate == 0){
if(tetromino.destroying==-1){
addtetromino();
foreseetetromino();
tetromino.falling.dropstate = 1;
} else if (tetromino.destroying==1){
destroylines();
} else if (tetromino.destroying==0) {
droplines();
}
}

get_Keys();

if (this.key[1]>0) {
if(this.movloop%4==0){
moveleft();
} else if (this.key[1]==1) {
this.movloop = 1;
moveleft();
}
}

if (this.key[3]>0) {
if(this.movloop%4==0){
moveright();
} else if (this.key[1]==1) {
this.movloop = 1;
moveright();
}
}

if(this.key[0]==1){
rotatetetromino();
}

if (this.key[2]>0) {
testdropstate();
if(tetromino.falling.dropstate==1){
tetromino.pushed.down = 1;
movedown();
}
}

if(tetromino.pushed.down!=1&&this.loop%20==0){
testdropstate();
if(tetromino.falling.dropstate>0) naturalfall();
}

draw();

freezeplayer this.timeout.time;
hideplayer this.timeout.time;

this.loop++;
this.movloop++;

timeout = this.timeout.time;
}

function testdropstate(){
for(this.i=0;this.i<arraylen(tetromino.atoms.pos);this.i++){
if(tetromino.atoms.pos[this.i]!=-1) atom.type[tetromino.atoms.pos[this.i]] = tetromino.falling;
if(tetromino.atoms.pos[this.i]!=-1 && (
tetromino.atoms.pos[this.i]+11>arraylen(playing.board)||
(playing.board[tetromino.atoms.pos[this.i]+10]>0 &&
!(tetromino.atoms.pos[this.i]+10 in tetromino.atoms.pos)))){
tetromino.falling.dropstate = -1;
}
}
}

function foreseetetromino(){
tetromino.foreseen = int(random(0,7));
freseen.startindex = tetromino.allflips*tetromino.foreseen;

this.o = 0;

for(this.i=0;this.i<tetromino.oneflip;this.i++){
if(alltetrominos[freseen.startindex+this.i]==1){
showimg freseen.indexs[this.o],tetromino_atom.gif,25+this.i%tetromino.width,25+int(this.i/tetromino.width);
changeimgcolors freseen.indexs[this.o],tetromino.colors[tetromino.foreseen3],tetromino.colors[tetromino.foreseen3+1],
tetromino.colors[tetromino.foreseen*3+2],1;
this.o++;
}
}

}

function detach(){
tetromino.falling.dropstate = 0;
//Check for lines to destroy
for(this.i=0;this.i<arraylen(playing.board)/playing.board.width;this.i++){
line.filling = 0;
for(this.j=0;this.j<playing.board.width;this.j++){
if(playing.board[this.i*playing.board.width+this.j]>0)line.filling++;
}
if(line.filling==playing.board.width){
addstring lines.filled,#v(this.i);
}
}
if(sarraylen(lines.filled)>0)tetromino.destroying = 1;
}

function addtetromino(){
// saved.loop = this.loop;
tetromino.rotate = 0;
tetromino.falling = tetromino.foreseen;
tetromino.startindex = tetromino.allflipstetromino.falling;
this.o = 0;
for(this.i=0;this.i<tetromino.oneflip;this.i++){
if(alltetrominos[tetromino.startindex+this.i]==1){
//Array of Positions on board for hit detection
tetromino.atoms.pos[this.i] = playing.board.start+this.i+(int(this.i/tetromino.width)
(playing.board.width-tetromino.width));
//Placed img indexes on board for drawing
playing.board[tetromino.atoms.pos[this.i]] = imgindexs;
imgindexs++;
} else tetromino.atoms.pos[this.i] = -1;
}
}

function destroylines(){
for(this.i=0;this.i<sarraylen(lines.filled);this.i++){
for(this.j=0;this.j<playing.board.width;this.j++){
hideimg playing.board[strtofloat(#I(lines.filled,this.i))*playing.board.width+this.j];
playing.board[strtofloat(#I(lines.filled,this.i))*playing.board.width+this.j] = 0;
}
}
tetromino.destroying = 0;
}

function droplines(){
lines.falling = 0;
for(this.i=sarraylen(lines.filled)-1;this.i>=0;this.i–){
lines.falling++;
for(this.j=strtofloat(#I(lines.filled,this.i))playing.board.width+(playing.board.widthlines.falling)-1;this.j>0;this.j–){
if(this.j<arraylen(playing.board)&&this.j-playing.board.widthlines.falling>=0){
playing.board[this.j] = playing.board[this.j-playing.board.width];
atom.type[this.j] = atom.type[this.j-playing.board.width];
} else if (this.j-playing.board.width
lines.falling<0){
playing.board[this.j] = 0;
}
}
}
tetromino.destroying = -1;
unset lines.filled;
}

function draw(){

for(this.i=0;this.i<arraylen(playing.board);this.i++){
if(playing.board.previous[this.i]>0&&playing.board[this.i]==0){
hideimg playing.board.previous[this.i];
}
if(playing.board[this.i]!=0){
showimg playing.board[this.i],tetromino_atom.gif,this.coords[this.i2],this.coords[this.i2+1];
changeimgcolors playing.board[this.i],tetromino.colors[atom.type[this.i]*3],tetromino.colors[atom.type[this.i]*3+1],
tetromino.colors[atom.type[this.i]*3+2],1;

}
playing.board.previous[this.i] = playing.board[this.i];

}
for(this.i=imgindexs-1;this.i>imgindexs-5;this.i–){
changeimgcolors this.i,tetromino.colors[tetromino.falling3],tetromino.colors[tetromino.falling3+1],
tetromino.colors[tetromino.falling*3+2],1;
}
}

function rotatetetromino(){
tetromino.rotate = (tetromino.rotate+1)%4;
tetromino.startindex = (tetromino.allflipstetromino.falling)+(tetromino.rotatetetromino.oneflip);

if(tetromino.atoms.pos[0]==-1&&tetromino.atoms.pos[1]==-1)tetromino.board.pos = tetromino.atoms.pos[2]-2;
else if (tetromino.atoms.pos[0]==-1) tetromino.board.pos = tetromino.atoms.pos[1]-1;
else tetromino.board.pos = tetromino.atoms.pos[0];

this.o = 0;
this.undo = 0;

for(this.i=0;this.i<arraylen(tetromino.atoms.pos);this.i++){
tetromino.atoms.oldpos[this.i] = tetromino.atoms.pos[this.i];
}

for(this.i=0;this.i<tetromino.oneflip;this.i++){
if(alltetrominos[tetromino.startindex+this.i]==1){
//Array of Positions on board for hit detection
tetromino.atoms.pos[this.i] = tetromino.board.pos+this.i+(int(this.i/tetromino.width)*(playing.board.width-tetromino.width));
if(playing.board[tetromino.atoms.pos[this.i]]!=0 &&
!(tetromino.atoms.pos[this.i] in tetromino.atoms.oldpos)||
(this.i>0 &&
int(tetromino.atoms.pos[this.i]%playing.board.width)==0 &&
int(tetromino.atoms.pos[this.i-1]%playing.board.width)==9)||
tetromino.atoms.pos[this.i]>arraylen(playing.board)) {
for(this.j=0;this.j<arraylen(tetromino.atoms.pos);this.j++){
this.undo = 1;
break;
}
}
} else tetromino.atoms.pos[this.i] = -1;
}
if(this.undo==1){
tetromino.rotate = (tetromino.rotate-1)%4;
for(this.i=0;this.i<arraylen(tetromino.atoms.pos);this.i++){
tetromino.atoms.pos[this.i] = tetromino.atoms.oldpos[this.i];
}
} else {
for(this.i=0;this.i<arraylen(tetromino.atoms.pos);this.i++){
if(tetromino.atoms.oldpos[this.i]!=-1){
hideimg playing.board[tetromino.atoms.oldpos[this.i]];
playing.board[tetromino.atoms.oldpos[this.i]] = 0;
}
if(tetromino.atoms.pos[this.i]!=-1){
playing.board[tetromino.atoms.pos[this.i]] = imgindexs;
imgindexs++;
}
}
}
}

function moveright(){
none.zero = 1;
for(this.i=0;this.i<arraylen(tetromino.atoms.pos);this.i++){
if((tetromino.atoms.pos[this.i]+1)%playing.board.width==0 ||
(playing.board[tetromino.atoms.pos[this.i]+1] != 0 &&
!(tetromino.atoms.pos[this.i]+1 in tetromino.atoms.pos))){
if(tetromino.atoms.pos[this.i]!=-1){
none.zero=0;
break;
}
}
}
if(none.zero==1){
for(this.i=arraylen(tetromino.atoms.pos)-1;this.i>=0;this.i–){
if(tetromino.atoms.pos[this.i]!=-1){
playing.board[tetromino.atoms.pos[this.i]+1] = playing.board[tetromino.atoms.pos[this.i]];
playing.board[tetromino.atoms.pos[this.i]] = 0;
tetromino.atoms.pos[this.i] += 1;
}
}
}
}

function moveleft(){
none.zero = 1;
for(this.i=0;this.i<arraylen(tetromino.atoms.pos);this.i++){
if(tetromino.atoms.pos[this.i]!=-1 && (
(tetromino.atoms.pos[this.i]-1)%playing.board.width==9 ||
(playing.board[tetromino.atoms.pos[this.i]-1] != 0 &&
!(tetromino.atoms.pos[this.i]-1 in tetromino.atoms.pos)))){
none.zero=0;
break;
}
}
if(none.zero==1){
for(this.i=0;this.i<arraylen(tetromino.atoms.pos);this.i++){
if(tetromino.atoms.pos[this.i]!=-1){
playing.board[tetromino.atoms.pos[this.i]-1] = playing.board[tetromino.atoms.pos[this.i]];
playing.board[tetromino.atoms.pos[this.i]] = 0;
tetromino.atoms.pos[this.i] -= 1;
}
}
}
}

function movedown(){
for(this.i=arraylen(tetromino.atoms.pos)-1;this.i>=0;this.i–){
if(tetromino.atoms.pos[this.i]!=-1){
playing.board[tetromino.atoms.pos[this.i]+playing.board.width] = playing.board[tetromino.atoms.pos[this.i]];
playing.board[tetromino.atoms.pos[this.i]] = 0;
tetromino.atoms.pos[this.i] += playing.board.width;
}
}
}

function naturalfall(){
for(this.i=arraylen(tetromino.atoms.pos)-1;this.i>=0;this.i–){
if(tetromino.atoms.pos[this.i]!=-1){
playing.board[tetromino.atoms.pos[this.i]+playing.board.width] = playing.board[tetromino.atoms.pos[this.i]];
playing.board[tetromino.atoms.pos[this.i]] = 0;
tetromino.atoms.pos[this.i] += playing.board.width;
}
}
}

function get_Keys(){
for (this.keyCheck = 0;this.keyCheck < 10; this.keyCheck++){
if (keydown(this.keyCheck))
this.key[this.keyCheck] = (this.key[this.keyCheck] == 0)?1:2;//1 = pressed,2 = held
else
this.key[this.keyCheck] = (this.key[this.keyCheck]>0)?-1:0;//-1 = released, 0 = not held
}
}[/CODE]

i dont think you are using enough variables

28
Most of them were planned… I added some to patch the destroying of lines and the tetromino colors.

Edit
I think some are not used, I didn’t care cleaning up my code.

That’s pretty cool. The button to move the tetrimino to the right feels a bit stiff, and the blue feels really sharp on my eyes compared to the other colors. All this needs is a few tweaks and a scoring system and this could probably be a pretty solid piece for the NPC showcase.

Dangerless and I tried to get Beholder to make Tetris but the fucker wouldn’t do it.

You should put all these minigames on a server and have highscore tables or whatever.

I’m writing these for fun more than anything… as I don’t have access to Internet where I live right now I won’t put efforts into putting this online. If you want to, you can make them server minigames, I won’t mind.

However these will be imbeded in Ch2 of Armonston. Which will be a long enough linear quest where you’ll mostly have to complete minigames to get further. If it ever gets online.

Does that mean you’ll be putting back up Ch1 as well?

No, I did code a compass to ease finding the objectives and remade the town but the amount of efforts making Ch1 tighter (to address the main complaint) were too big. I might finish Ch1 someday but for now I’ve just arranged things so the players start in the jail (where Ch1 ended) and have a quick explanation of the storyline… I’m currently working on the first… and only dungeon of Ch2.

What the fuck is Armonston?

The playerworld 2ndWolf hosted what must be 2-3 years ago? which had quite a few bugs but consisted of a series of quests that made up Chapter(ch) 1, and was actually quite fun. It’s a shame more people didn’t persist with playing it.

well put it up, 2ndwolf. wtf

I suspect people will complain of bugs if he does and give up on it as per usual.

stop trying to ruin the good things

Well I doubt anyone will want to go through the first quest and, admittedly, things were far from obvious.

I don’t want to maintain Ch1… anyone who wants the files can have them… but I won’t be online much for faqs.

put it online

alright, next time I come here I’ll bring the files and put the server online