ref: 781b19e0fb31b0bb5c6ee7e9a5d1c010812b5349
dir: /piece.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <draw.h>
#include "dat.h"
#include "fns.h"
#include "/sys/src/games/eui.h"
int fours[NF][Nrot] = {
[FI] {
0b0000111100000000,
0b0010001000100010,
0b0000000011110000,
0b0100010001000100,
},
[FJ] {
0b1000111000000000,
0b0110010001000000,
0b0000111000100000,
0b0100010011000000,
},
[FL] {
0b0010111000000000,
0b0100010001100000,
0b0000111010000000,
0b1100010001000000,
},
[FO] {
0b0000011001100000,
0b0000011001100000,
0b0000011001100000,
0b0000011001100000,
},
[FS] {
0b0110110000000000,
0b0100011000100000,
0b0000011011000000,
0b1000110001000000,
},
[FT] {
0b0100111000000000,
0b0100011001000000,
0b0000111001000000,
0b0100110001000000,
},
[FZ] {
0b1100011000000000,
0b0010011001000000,
0b0000110001100000,
0b0100110010000000,
},
};
int rkick[NF][Nrot][Ntest*2] = {
[FI] {
{0,0, -2,0, +1,0, -2,-1, +1,+2}, /* 0->R */
{0,0, -1,0, +2,0, -1,+2, +2,-1}, /* R->2 */
{0,0, +2,0, -1,0, +2,+1, -1,-2}, /* 2->L */
{0,0, +1,0, -2,0, +1,-2, -2,+1}, /* L->0 */
},
[FJ] {
{0,0, -1,0, -1,+1, 0,-2, -1,-2},
{0,0, +1,0, +1,-1, 0,+2, +1,+2},
{0,0, +1,0, +1,+1, 0,-2, +1,-2},
{0,0, -1,0, -1,-1, 0,+2, -1,+2},
},
[FL] {
{0,0, -1,0, -1,+1, 0,-2, -1,-2},
{0,0, +1,0, +1,-1, 0,+2, +1,+2},
{0,0, +1,0, +1,+1, 0,-2, +1,-2},
{0,0, -1,0, -1,-1, 0,+2, -1,+2},
},
[FO] { 0 },
[FS] {
{0,0, -1,0, -1,+1, 0,-2, -1,-2},
{0,0, +1,0, +1,-1, 0,+2, +1,+2},
{0,0, +1,0, +1,+1, 0,-2, +1,-2},
{0,0, -1,0, -1,-1, 0,+2, -1,+2},
},
[FT] {
{0,0, -1,0, -1,+1, 0,-2, -1,-2},
{0,0, +1,0, +1,-1, 0,+2, +1,+2},
{0,0, +1,0, +1,+1, 0,-2, +1,-2},
{0,0, -1,0, -1,-1, 0,+2, -1,+2},
},
[FZ] {
{0,0, -1,0, -1,+1, 0,-2, -1,-2},
{0,0, +1,0, +1,-1, 0,+2, +1,+2},
{0,0, +1,0, +1,+1, 0,-2, +1,-2},
{0,0, -1,0, -1,-1, 0,+2, -1,+2},
},
};
int lkick[NF][Nrot][Ntest*2] = {
[FI] {
{0,0, -1,0, +2,0, -1,+2, +2,-1}, /* 0->L */
{0,0, +2,0, -1,0, +2,+1, -1,-2}, /* R->0 */
{0,0, +1,0, -2,0, +1,-2, -2,+1}, /* 2->R */
{0,0, -2,0, +1,0, -2,-1, +1,+2}, /* L->2 */
},
[FJ] {
{0,0, +1,0, +1,+1, 0,-2, +1,-2},
{0,0, +1,0, +1,-1, 0,+2, +1,+2},
{0,0, -1,0, -1,+1, 0,-2, -1,-2},
{0,0, -1,0, -1,-1, 0,+2, -1,+2},
},
[FL] {
{0,0, +1,0, +1,+1, 0,-2, +1,-2},
{0,0, +1,0, +1,-1, 0,+2, +1,+2},
{0,0, -1,0, -1,+1, 0,-2, -1,-2},
{0,0, -1,0, -1,-1, 0,+2, -1,+2},
},
[FO] { 0 },
[FS] {
{0,0, +1,0, +1,+1, 0,-2, +1,-2},
{0,0, +1,0, +1,-1, 0,+2, +1,+2},
{0,0, -1,0, -1,+1, 0,-2, -1,-2},
{0,0, -1,0, -1,-1, 0,+2, -1,+2},
},
[FT] {
{0,0, +1,0, +1,+1, 0,-2, +1,-2},
{0,0, +1,0, +1,-1, 0,+2, +1,+2},
{0,0, -1,0, -1,+1, 0,-2, -1,-2},
{0,0, -1,0, -1,-1, 0,+2, -1,+2},
},
[FZ] {
{0,0, +1,0, +1,+1, 0,-2, +1,-2},
{0,0, +1,0, +1,-1, 0,+2, +1,+2},
{0,0, -1,0, -1,+1, 0,-2, -1,-2},
{0,0, -1,0, -1,-1, 0,+2, -1,+2},
},
};
enum{
Cline = 0xf5,
};
/* FIXME: draw level, line clears, score */
/* FIXME: freeze screen on game over + print message instead of immediate exit */
static void
drawbackground(void)
{
int n, m, y;
u32int c, *p, *pe;
memset(pic, 0, Vheight * Vwidth * sizeof *p);
c = palette[Cline];
p = (u32int *)pic;
for(y=Nrow-Wheight; y<Nrow; y++){
p += Wside * Block;
for(pe=p+Ncol*Block; p<pe; p++)
*p = c;
p += Wside * Block;
m = y == Nrow - 1 ? Block - 2 : Block - 1;
for(n=0; n<m; n++){
p += Wside * Block;
for(pe=p+Ncol*Block; p<pe; p+=Block)
*p = c;
p[-1] = c;
p += Wside * Block;
}
}
p += Wside * Block;
for(pe=p+Ncol*Block; p<pe; p++)
*p = c;
}
static void
drawplayfield(void)
{
int n, y;
u32int *p, *pe;
char fc, *f, *fs, *fe;
uchar *sp;
p = (u32int *)pic;
fs = playfield + Wwidth * (Nrow - Wheight);
for(y=Nrow-Wheight; y<Nrow; y++){
fe = fs + Ncol;
for(n=0; n<Block; n++){
p += Wside * Block;
for(f=fs; f<fe; f++){
if((fc = *f) == 0){
p += Block;
continue;
}
sp = sprites[fc - 1] + n * Block;
for(pe=p+Block; p<pe; p++)
*p = palette[*sp++];
}
p += Wside * Block;
}
fs += Ncol;
}
}
static void
drawfour(int x, int y, int rot, int type)
{
int f, n, m, k;
uchar *sp;
u32int *l, *s, *p, *pe;
p = (u32int *)pic + (y - Nstartrow + Nextrarows) * Vwidth * Block;
p += (Wside + x) * Block;
l = p;
f = fours[type][rot];
for(k=0, m=1<<(Nside*Nside-1); m>0; m>>=1){
s = p;
if(f & m){
sp = sprites[type];
for(n=0; n<Block; n++){
if(p >= (u32int *)pic)
for(pe=p+Block; p<pe; p++)
*p = palette[*sp++];
else
p += Block;
p += Vwidth - Block;
}
}
p = s + Block;
if(++k == Nside){
k = 0;
l += Vwidth * Block;
p = l;
}
}
}
static void
drawsides(void)
{
int y, *p;
if(held != -1)
drawfour(-4, Nrow / 2, 1, held);
for(y=1, p=next; p<next+nelem(next); p++, y+=5)
drawfour(Wwidth, Nstartrow - Nextrarows + y, 1, *p);
}
static void
drawpiece(void)
{
if(cur == nil)
return;
drawfour(cur->x, cur->y, cur->rot, cur->type);
}
static void
drawui(void)
{
}
void
redraw(void)
{
drawbackground();
drawplayfield();
drawpiece();
drawsides();
drawui();
flushmouse(1);
flushscreen();
}