finish tetris.nas
This commit is contained in:
parent
984deed883
commit
9456a903d7
|
@ -108,7 +108,7 @@ __CAUTION__: If want to use the release zip/tar.gz file to build the interpreter
|
||||||
|
|
||||||
Also remember to use g++ or clang++.(`mingw-w64` in __`Windows`__)
|
Also remember to use g++ or clang++.(`mingw-w64` in __`Windows`__)
|
||||||
|
|
||||||
> [cpp compiler] -std=c++11 -O3 main.cpp -o nasal.exe -fno-exceptions
|
> [cpp compiler] -std=c++11 -O3 main.cpp -o nasal.exe -fno-exceptions -static
|
||||||
|
|
||||||
Or use this in __`linux/macOS/Unix`__
|
Or use this in __`linux/macOS/Unix`__
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#else
|
#else
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <termio.h>
|
#include <termios.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
|
@ -9,7 +9,7 @@ libkey.so: keyboard.cpp
|
||||||
clang++ -c -O3 keyboard.cpp -fPIC -o keyboard.o
|
clang++ -c -O3 keyboard.cpp -fPIC -o keyboard.o
|
||||||
clang++ -shared -o libkey.so keyboard.o
|
clang++ -shared -o libkey.so keyboard.o
|
||||||
libkey.dll: keyboard.cpp
|
libkey.dll: keyboard.cpp
|
||||||
g++ -c -O3 keyboard.cpp -fPIC -o keyboard.o
|
g++ -c -O3 keyboard.cpp -fPIC -o keyboard.o -static
|
||||||
g++ -shared -o libkey.dll keyboard.o
|
g++ -shared -o libkey.dll keyboard.o -static
|
||||||
clean:
|
clean:
|
||||||
rm *.o *.so *.dll *.dylib
|
rm *.o *.so *.dll *.dylib
|
138
test/tetris.nas
138
test/tetris.nas
|
@ -1,6 +1,10 @@
|
||||||
import("lib.nas");
|
import("lib.nas");
|
||||||
import("module/libkey.nas");
|
import("./module/libkey.nas");
|
||||||
|
|
||||||
|
var color=[
|
||||||
|
"\e[31m","\e[32m","\e[33m","\e[34m","\e[35m","\e[36m",
|
||||||
|
"\e[91m","\e[92m","\e[93m","\e[94m","\e[95m","\e[96m",
|
||||||
|
];
|
||||||
var blocktype=[
|
var blocktype=[
|
||||||
[0,1,2,3 ],
|
[0,1,2,3 ],
|
||||||
[4,5,6,7 ],
|
[4,5,6,7 ],
|
||||||
|
@ -52,32 +56,45 @@ var blockshape=[
|
||||||
[[0,0],[0,1],[1,1],[1,2]],
|
[[0,0],[0,1],[1,1],[1,2]],
|
||||||
[[0,0],[1,0],[0,1],[-1,1]]
|
[[0,0],[1,0],[0,1],[-1,1]]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var stick_count=0; # make sure one stick in 10 tries
|
||||||
var block={
|
var block={
|
||||||
x:0,
|
x:0,
|
||||||
y:0,
|
y:0,
|
||||||
rotate:0,
|
rotate:0,
|
||||||
type:nil,
|
type:nil,
|
||||||
shape:nil,
|
shape:nil,
|
||||||
|
color:nil,
|
||||||
new:func(x=0,y=0){
|
new:func(x=0,y=0){
|
||||||
(me.x,me.y)=(x,y);
|
(me.x,me.y)=(x,y);
|
||||||
me.rotate=0;
|
me.rotate=0;
|
||||||
me.type=blocktype[rand()*size(blocktype)];
|
var t=int(rand()*size(blocktype));
|
||||||
|
if(t!=3){
|
||||||
|
stick_count+=1;
|
||||||
|
if(stick_count==10)
|
||||||
|
(t,stick_count)=(3,0);
|
||||||
|
}else
|
||||||
|
stick_count=0;
|
||||||
|
me.type=blocktype[t];
|
||||||
me.shape=blockshape[me.type[me.rotate]];
|
me.shape=blockshape[me.type[me.rotate]];
|
||||||
|
me.color=int(rand()*size(color));
|
||||||
return {parents:[block]};
|
return {parents:[block]};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var mapgen=func(mapx,mapy){
|
var mapgen=func(mapx,mapy){
|
||||||
var score=0;
|
var (score,gameover)=(0,0);
|
||||||
var (empty,unset,full)=(0,1,2);
|
var (empty,unset,full)=(0,1,2);
|
||||||
|
|
||||||
if(mapx<1 or mapy<1)
|
if(mapx<1 or mapy<1)
|
||||||
die("map_x or map_y must be greater than 1");
|
die("map_x or map_y must be greater than 1");
|
||||||
|
|
||||||
# use in print
|
# use in print
|
||||||
var table="\e[44m ";
|
var table="\e[32m+";
|
||||||
for(var i=0;i<mapx;i+=1)
|
for(var i=0;i<mapx;i+=1)
|
||||||
table~=" ";
|
table~="--";
|
||||||
table~=" \e[0m\n";
|
table~="+\e[0m\n";
|
||||||
|
|
||||||
# generate new map
|
# generate new map
|
||||||
var map=[];
|
var map=[];
|
||||||
for(var y=0;y<mapy;y+=1){
|
for(var y=0;y<mapy;y+=1){
|
||||||
|
@ -90,29 +107,37 @@ var mapgen=func(mapx,mapy){
|
||||||
var blk=nil;
|
var blk=nil;
|
||||||
var new_block=func(){
|
var new_block=func(){
|
||||||
blk=block.new(int(mapx/2),0);
|
blk=block.new(int(mapx/2),0);
|
||||||
# check game end unfinished
|
|
||||||
|
# check if has enough place to place a new block
|
||||||
|
foreach(var i;blk.shape)
|
||||||
|
if(map[blk.y+i[1]][blk.x+i[0]]>=full){
|
||||||
|
gameover=1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
# update map
|
||||||
foreach(var i;blk.shape)
|
foreach(var i;blk.shape)
|
||||||
map[blk.y+i[1]][blk.x+i[0]]=unset;
|
map[blk.y+i[1]][blk.x+i[0]]=unset;
|
||||||
}
|
}
|
||||||
new_block();
|
new_block(); # initialize the first block
|
||||||
|
|
||||||
# color print
|
# color print
|
||||||
var front=[
|
|
||||||
"31","32","33","34","35","36",
|
|
||||||
"91","92","93","94","95","96",
|
|
||||||
];
|
|
||||||
var map_print=func(){
|
var map_print=func(){
|
||||||
print("\e[1;1Hscore: ",score,"\n");
|
var s="\e[1;1H"~table;
|
||||||
var s=table;
|
|
||||||
for(var y=0;y<mapy;y+=1){
|
for(var y=0;y<mapy;y+=1){
|
||||||
s~="\e[44m \e[0m";
|
s~="\e[32m|\e[0m";
|
||||||
for(var x=0;x<mapx;x+=1){
|
for(var x=0;x<mapx;x+=1){
|
||||||
s~=(map[y][x]!=empty)?"\e["~front[rand()*12]~"m██\e[0m":" ";
|
var c=map[y][x];
|
||||||
|
if(c==empty)
|
||||||
|
s~=" ";
|
||||||
|
elsif(c==unset)
|
||||||
|
s~=color[blk.color]~"██\e[0m";
|
||||||
|
elsif(c>=full)
|
||||||
|
s~=color[c-full]~"██\e[0m";
|
||||||
}
|
}
|
||||||
s~="\e[44m \e[0m\n";
|
s~="\e[32m|\e[0m\n";
|
||||||
}
|
}
|
||||||
s~=table;
|
s~=table;
|
||||||
print(s);
|
print(s," score: ",score,'\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
var moveleft=func(){
|
var moveleft=func(){
|
||||||
|
@ -120,9 +145,10 @@ var mapgen=func(mapx,mapy){
|
||||||
foreach(var i;blk.shape){
|
foreach(var i;blk.shape){
|
||||||
if(x+i[0]<0)
|
if(x+i[0]<0)
|
||||||
return;
|
return;
|
||||||
if(map[y+i[1]][x+i[0]]==full)
|
if(map[y+i[1]][x+i[0]]>=full)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
# update block state and map
|
||||||
foreach(var i;blk.shape)
|
foreach(var i;blk.shape)
|
||||||
map[blk.y+i[1]][blk.x+i[0]]=empty;
|
map[blk.y+i[1]][blk.x+i[0]]=empty;
|
||||||
blk.x=x;
|
blk.x=x;
|
||||||
|
@ -136,9 +162,10 @@ var mapgen=func(mapx,mapy){
|
||||||
foreach(var i;blk.shape){
|
foreach(var i;blk.shape){
|
||||||
if(x+i[0]>=mapx)
|
if(x+i[0]>=mapx)
|
||||||
return;
|
return;
|
||||||
if(map[y+i[1]][x+i[0]]==full)
|
if(map[y+i[1]][x+i[0]]>=full)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
# update block state and map
|
||||||
foreach(var i;blk.shape)
|
foreach(var i;blk.shape)
|
||||||
map[blk.y+i[1]][blk.x+i[0]]=empty;
|
map[blk.y+i[1]][blk.x+i[0]]=empty;
|
||||||
blk.x=x;
|
blk.x=x;
|
||||||
|
@ -154,9 +181,11 @@ var mapgen=func(mapx,mapy){
|
||||||
foreach(var i;shape){
|
foreach(var i;shape){
|
||||||
if(x+i[0]>=mapx or x+i[0]<0 or y+i[1]>=mapy or y+i[1]<0)
|
if(x+i[0]>=mapx or x+i[0]<0 or y+i[1]>=mapy or y+i[1]<0)
|
||||||
return;
|
return;
|
||||||
if(map[y+i[1]][x+i[0]]==full)
|
if(map[y+i[1]][x+i[0]]>=full)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# update block state and map
|
||||||
foreach(var i;blk.shape)
|
foreach(var i;blk.shape)
|
||||||
map[blk.y+i[1]][blk.x+i[0]]=empty;
|
map[blk.y+i[1]][blk.x+i[0]]=empty;
|
||||||
blk.rotate=r;
|
blk.rotate=r;
|
||||||
|
@ -168,21 +197,23 @@ var mapgen=func(mapx,mapy){
|
||||||
|
|
||||||
var fall=func(){
|
var fall=func(){
|
||||||
var (x,y)=(blk.x,blk.y+1);
|
var (x,y)=(blk.x,blk.y+1);
|
||||||
|
# check if falls to the edge of other blocks or map
|
||||||
var sethere=0;
|
var sethere=0;
|
||||||
foreach(var i;blk.shape){
|
foreach(var i;blk.shape)
|
||||||
if(y+i[1]>=mapy or map[y+i[1]][x+i[0]]==full){
|
if(y+i[1]>=mapy or map[y+i[1]][x+i[0]]>=full){
|
||||||
sethere=1;
|
sethere=1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
# set block here and generate a new block
|
||||||
if(sethere){
|
if(sethere){
|
||||||
foreach(var i;blk.shape)
|
foreach(var i;blk.shape)
|
||||||
map[blk.y+i[1]][blk.x+i[0]]=full;
|
map[blk.y+i[1]][blk.x+i[0]]=blk.color+full;
|
||||||
checkmap();
|
checkmap();
|
||||||
new_block();
|
new_block();
|
||||||
map_print();
|
map_print();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
# update block state and map
|
||||||
foreach(var i;blk.shape)
|
foreach(var i;blk.shape)
|
||||||
map[blk.y+i[1]][blk.x+i[0]]=empty;
|
map[blk.y+i[1]][blk.x+i[0]]=empty;
|
||||||
blk.y=y;
|
blk.y=y;
|
||||||
|
@ -193,11 +224,17 @@ var mapgen=func(mapx,mapy){
|
||||||
|
|
||||||
var checkmap=func(){
|
var checkmap=func(){
|
||||||
for(var y=mapy-1;y>=0;y-=1){
|
for(var y=mapy-1;y>=0;y-=1){
|
||||||
for(var x=0;x<mapx;x+=1)
|
# check if this line is full of blocks
|
||||||
if(map[y][x]!=full)
|
var tmp=0;
|
||||||
|
for(var x=0;x<mapx;x+=1){
|
||||||
|
if(map[y][x]<full)
|
||||||
break;
|
break;
|
||||||
|
tmp+=map[y][x];
|
||||||
|
}
|
||||||
|
# if is full, clear this line and
|
||||||
|
# all the lines above fall one block
|
||||||
if(x==mapx){
|
if(x==mapx){
|
||||||
score+=mapx;
|
score+=tmp;
|
||||||
for(var t=y;t>=1;t-=1)
|
for(var t=y;t>=1;t-=1)
|
||||||
for(var x=0;x<mapx;x+=1)
|
for(var x=0;x<mapx;x+=1)
|
||||||
map[t][x]=map[t-1][x];
|
map[t][x]=map[t-1][x];
|
||||||
|
@ -214,47 +251,74 @@ var mapgen=func(mapx,mapy){
|
||||||
moveright:moveright,
|
moveright:moveright,
|
||||||
rotate:rotate,
|
rotate:rotate,
|
||||||
fall:fall,
|
fall:fall,
|
||||||
checkmap:checkmap
|
checkmap:checkmap,
|
||||||
|
gameover:func(){return gameover;}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var main=func(){
|
var main=func(){
|
||||||
print("\ec");
|
# windows use chcp 65001 to output unicode
|
||||||
|
if(os.platform()=="windows")
|
||||||
|
system("chcp 65001");
|
||||||
|
print(
|
||||||
|
"\ec\e[1:1H",
|
||||||
|
"+-------------------------+\n",
|
||||||
|
"| TETRIS |\n",
|
||||||
|
"| w:rotate, a:move left |\n",
|
||||||
|
"| s:fall, d:move right |\n",
|
||||||
|
"| p:pause, q:quit |\n",
|
||||||
|
"+-------------------------+\n",
|
||||||
|
"|press any key to start...|\n",
|
||||||
|
"+-------------------------+\n"
|
||||||
|
);
|
||||||
|
|
||||||
rand(time(0));
|
rand(time(0));
|
||||||
var map=mapgen(mapx:15,mapy:15);
|
var map=mapgen(mapx:12,mapy:15);
|
||||||
|
|
||||||
libkey.init();
|
libkey.init();
|
||||||
|
libkey.getch();
|
||||||
|
print("\ec");
|
||||||
|
|
||||||
while(1){
|
while(1){
|
||||||
|
# nonblock input one character
|
||||||
var ch=libkey.nonblock();
|
var ch=libkey.nonblock();
|
||||||
if(ch){
|
if(ch){
|
||||||
if(ch=='a'[0]) # move left
|
if(ch=='a'[0]) # move left
|
||||||
map.moveleft();
|
map.moveleft();
|
||||||
elsif(ch=='d'[0]) # move right
|
elsif(ch=='d'[0]) # move right
|
||||||
map.moveright();
|
map.moveright();
|
||||||
elsif(ch=='s'[0]) # rotate
|
elsif(ch=='w'[0]) # rotate
|
||||||
map.rotate();
|
map.rotate();
|
||||||
elsif(ch==' '[0]) # move down
|
elsif(ch=='s'[0]) # move down
|
||||||
map.fall();
|
map.fall();
|
||||||
elsif(ch=='q'[0])
|
elsif(ch=='q'[0]) # quit the game
|
||||||
break;
|
break;
|
||||||
if(ch=='p'[0]){
|
if(ch=='p'[0]){ # pause the game
|
||||||
print("\rpress any key to continue...");
|
print("\rpress any key to continue...");
|
||||||
libkey.getch();
|
libkey.getch();
|
||||||
print("\r ");
|
print("\r ");
|
||||||
}
|
}
|
||||||
map.checkmap();
|
map.checkmap();
|
||||||
|
if(map.gameover())
|
||||||
|
break;
|
||||||
unix.sleep(0.01);
|
unix.sleep(0.01);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
# automatically fall one block and check
|
||||||
map.fall();
|
map.fall();
|
||||||
map.checkmap();
|
map.checkmap();
|
||||||
unix.sleep(0.65);
|
if(map.gameover())
|
||||||
|
break;
|
||||||
|
unix.sleep(0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
libkey.close();
|
libkey.close();
|
||||||
|
|
||||||
print("\ec\e[31ms\e[32me\e[33me \e[34my\e[35mo\e[36mu \e[94m~\e[0m\n");
|
print(
|
||||||
|
map.gameover()?
|
||||||
|
"\e[31mg\e[32ma\e[33mm\e[34me \e[35mo\e[36mv\e[94me\e[31mr \e[32m~\e[0m\n":
|
||||||
|
"\e[31ms\e[32me\e[33me \e[34my\e[35mo\e[36mu \e[94m~\e[0m\n"
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|
Loading…
Reference in New Issue