rminnichinitial1fcdf7916 years agoHistory
891 lines · 16.7 KB · C
RawDownload
#include "xs.h" /* * engine for 4s, 5s, etc */ Cursor whitearrow = {	{0, 0},	{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 	 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC, 	 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 	 0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, },	{0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C, 	 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C, 	 0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C, 	 0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }}; enum{	CNone	= 0,	CBounds	= 1,	CPiece	= 2,	NX	= 10,	NY	= 20,}; enum{	TIMER,	MOUSE,	RESHAPE,	KBD,	SUSPEND,	NALT}; char		board[NY][NX];Rectangle	rboard;Point		pscore;Point		scoresz;int		pcsz = 32;Point		pos;Image	*bb, *bbmask, *bb2, *bb2mask;Image	*whitemask;Rectangle	br, br2;long		points;int		dt;int		DY;int		DMOUSE;int		lastmx;Mouse	mouse;int		newscreen;Channel	*timerc;Channel	*suspc;Channel	*mousec;Channel	*kbdc;Mousectl	*mousectl;Keyboardctl	*kbdctl;int		suspended; void		redraw(int); int	tsleep; Piece *piece; #define	NCOL	10 uchar txbits[NCOL][32]={	{0xDD,0xDD,0xFF,0xFF,0x77,0x77,0xFF,0xFF,	 0xDD,0xDD,0xFF,0xFF,0x77,0x77,0xFF,0xFF,	 0xDD,0xDD,0xFF,0xFF,0x77,0x77,0xFF,0xFF,	 0xDD,0xDD,0xFF,0xFF,0x77,0x77,0xFF,0xFF},	{0xDD,0xDD,0x77,0x77,0xDD,0xDD,0x77,0x77,	 0xDD,0xDD,0x77,0x77,0xDD,0xDD,0x77,0x77,	 0xDD,0xDD,0x77,0x77,0xDD,0xDD,0x77,0x77,	 0xDD,0xDD,0x77,0x77,0xDD,0xDD,0x77,0x77},	{0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,	 0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,	 0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,	 0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55},	{0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,	 0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,	 0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,	 0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55},	{0x22,0x22,0x88,0x88,0x22,0x22,0x88,0x88,	 0x22,0x22,0x88,0x88,0x22,0x22,0x88,0x88,	 0x22,0x22,0x88,0x88,0x22,0x22,0x88,0x88,	 0x22,0x22,0x88,0x88,0x22,0x22,0x88,0x88},	{0x22,0x22,0x00,0x00,0x88,0x88,0x00,0x00,	 0x22,0x22,0x00,0x00,0x88,0x88,0x00,0x00,	 0x22,0x22,0x00,0x00,0x88,0x88,0x00,0x00,	 0x22,0x22,0x00,0x00,0x88,0x88,0x00,0x00},	{0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,	 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,	 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,	 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},	{0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,	 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,	 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,	 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},	{0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,	 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,	 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,	 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC},	{0xCC,0xCC,0xCC,0xCC,0x33,0x33,0x33,0x33,	 0xCC,0xCC,0xCC,0xCC,0x33,0x33,0x33,0x33,	 0xCC,0xCC,0xCC,0xCC,0x33,0x33,0x33,0x33,	 0xCC,0xCC,0xCC,0xCC,0x33,0x33,0x33,0x33},}; int txpix[NCOL] = {	DYellow,	/* yellow */	DCyan,	/* cyan */	DGreen,	/* lime green */	DGreyblue,	/* slate */	DRed,	/* red */	DGreygreen,	/* olive green */	DBlue,	/* blue */	0xFF55AAFF,	/* pink */	0xFFAAFFFF,	/* lavender */	0xBB005DFF,	/* maroon */}; Image *tx[NCOL]; intmovemouse(void){	mouse.xy = Pt(rboard.min.x + Dx(rboard)/2, rboard.min.y +Dy(rboard)/2);	moveto(mousectl, mouse.xy);	return mouse.xy.x;} intwarp(Point p, int x){	if (!suspended && piece != nil) {		x = pos.x + piece->sz.x*pcsz/2;		if (p.y < rboard.min.y)			p.y = rboard.min.y;		if (p.y >= rboard.max.y)			p.y = rboard.max.y - 1;		moveto(mousectl, Pt(x, p.y));	}	return x;} Piece *rotr(Piece *p){	if(p->rot == 3)		return p-3;	return p+1;} Piece *rotl(Piece *p){	if(p->rot == 0)		return p+3;	return p-1;} intcollide(Point pt, Piece *p){	int i;	int c = CNone; 	pt.x = (pt.x - rboard.min.x) / pcsz;	pt.y = (pt.y - rboard.min.y) / pcsz;	for(i=0; i<N; i++){		pt.x += p->d[i].x;		pt.y += p->d[i].y;		if(pt.x<0 || pt.x>=NX || pt.y<0 || pt.y>=NY)			c |= CBounds;		if(board[pt.y][pt.x])			c |= CPiece;	}	return c;} intcollider(Point pt, Point pmax){	int i, j, pi, pj, n, m; 	pi = (pt.x - rboard.min.x) / pcsz;	pj = (pt.y - rboard.min.y) / pcsz;	n = pmax.x / pcsz;	m = pmax.y / pcsz + 1;	for(i = pi; i < pi+n && i < NX; i++)		for(j = pj; j < pj+m && j < NY; j++)			if(board[j][i])				return 1;	return 0;} voidsetpiece(Piece *p){	int i;	Rectangle r, r2;	Point op, delta; 	draw(bb, bb->r, display->white, nil, ZP);	draw(bbmask, bbmask->r, display->transparent, nil, ZP);	br = Rect(0, 0, 0, 0);	br2 = br;	piece = p;	if(p == 0)		return;	r.min = bb->r.min;	for(i=0; i<N; i++){		r.min.x += p->d[i].x*pcsz;		r.min.y += p->d[i].y*pcsz;		r.max.x = r.min.x + pcsz;		r.max.y = r.min.y + pcsz;		if(i == 0){			draw(bb, r, display->black, nil, ZP);			draw(bb, insetrect(r, 1), tx[piece->tx], nil, ZP);			draw(bbmask, r, display->opaque, nil, ZP);			op = r.min;		}else{			draw(bb, r, bb, nil, op);			draw(bbmask, r, bbmask, nil, op);		}		if(br.max.x < r.max.x)			br.max.x = r.max.x;		if(br.max.y < r.max.y)			br.max.y = r.max.y;	}	br.max = subpt(br.max, bb->r.min);	delta = Pt(0,DY);	br2.max = addpt(br.max, delta);	r = rectaddpt(br, bb2->r.min);	r2 = rectaddpt(br2, bb2->r.min);	draw(bb2, r2, display->white, nil, ZP);	draw(bb2, rectaddpt(r,delta), bb, nil, bb->r.min);	draw(bb2mask, r2, display->transparent, nil, ZP);	draw(bb2mask, r, display->opaque, bbmask, bb->r.min);	draw(bb2mask, rectaddpt(r,delta), display->opaque, bbmask, bb->r.min);} voiddrawpiece(void){	draw(screen, rectaddpt(br, pos), bb, bbmask, bb->r.min);	if (suspended)		draw(screen, rectaddpt(br, pos), display->white, whitemask, ZP);} voidundrawpiece(void){	Image *mask = nil;	if(collider(pos, br.max))		mask = bbmask;	draw(screen, rectaddpt(br, pos), display->white, mask, bb->r.min);} voidrest(void){	int i;	Point pt; 	pt = divpt(subpt(pos, rboard.min), pcsz);	for(i=0; i<N; i++){		pt.x += piece->d[i].x;		pt.y += piece->d[i].y;		board[pt.y][pt.x] = piece->tx+16;	}} intcanfit(Piece *p){	static int dx[]={0, -1, 1, -2, 2, -3, 3, 4, -4};	int i, j;	Point z; 	j = N + 1;	if(j >= 4){		j = p->sz.x;		if(j<p->sz.y)			j = p->sz.y;		j = 2*j-1;	}	for(i=0; i<j; i++){		z.x = pos.x + dx[i]*pcsz;		z.y = pos.y;		if(!collide(z, p)){			z.y = pos.y + pcsz-1;			if(!collide(z, p)){				undrawpiece();				pos.x = z.x;				return 1;			}		}	}	return 0;} voidscore(int p){	char buf[128]; 	points += p;	snprint(buf, sizeof(buf), "%.6ld", points);	draw(screen, Rpt(pscore, addpt(pscore, scoresz)), display->white, nil, ZP);	string(screen, pscore, display->black, ZP, font, buf);} voiddrawsq(Image *b, Point p, int ptx){	Rectangle r; 	r.min = p;	r.max.x = r.min.x+pcsz;	r.max.y = r.min.y+pcsz;	draw(b, r, display->black, nil, ZP);	draw(b, insetrect(r, 1), tx[ptx], nil, ZP);} voiddrawboard(void){	int i, j; 	border(screen, insetrect(rboard, -2), 2, display->black, ZP);	draw(screen, Rect(rboard.min.x, rboard.min.y-2, rboard.max.x, rboard.min.y),		display->white, nil, ZP);	for(i=0; i<NY; i++)		for(j=0; j<NX; j++)			if(board[i][j])				drawsq(screen, Pt(rboard.min.x+j*pcsz, rboard.min.y+i*pcsz), board[i][j]-16);	score(0);	if (suspended)		draw(screen, screen->r, display->white, whitemask, ZP);} voidchoosepiece(void){	int i; 	do{		i = nrand(NP);		setpiece(&pieces[i]);		pos = rboard.min;		pos.x += nrand(NX)*pcsz;	}while(collide(Pt(pos.x, pos.y+pcsz-DY), piece));	drawpiece();	flushimage(display, 1);} intmovepiece(void){	Image *mask = nil; 	if(collide(Pt(pos.x, pos.y+pcsz), piece))		return 0;	if(collider(pos, br2.max))		mask = bb2mask;	draw(screen, rectaddpt(br2, pos), bb2, mask, bb2->r.min);	pos.y += DY;	flushimage(display, 1);	return 1;} voidsuspend(int s){	suspended = s;	if (suspended)		setcursor(mousectl, &whitearrow);	else		setcursor(mousectl, nil);	if (!suspended)		drawpiece();	drawboard();	flushimage(display, 1);} voidpause(int t){	int s;	Alt alts[NALT+1]; 	alts[TIMER].c = timerc;	alts[TIMER].v = nil;	alts[TIMER].op = CHANRCV;	alts[SUSPEND].c = suspc;	alts[SUSPEND].v = &s;	alts[SUSPEND].op = CHANRCV;	alts[RESHAPE].c = mousectl->resizec;	alts[RESHAPE].v = nil;	alts[RESHAPE].op = CHANRCV;	// avoid hanging up those writing ong mousec and kbdc	// so just accept it all and keep mouse up-to-date	alts[MOUSE].c = mousec;	alts[MOUSE].v = &mouse;	alts[MOUSE].op = CHANRCV;	alts[KBD].c = kbdc;	alts[KBD].v = nil;	alts[KBD].op = CHANRCV;	alts[NALT].op = CHANEND; 	flushimage(display, 1);	for(;;)		switch(alt(alts)){		case SUSPEND:			if (!suspended && s) {				suspend(1);			} else if (suspended && !s) {				suspend(0);				lastmx = warp(mouse.xy, lastmx);			}			break;		case TIMER:			if(suspended)				break;			if((t -= tsleep) < 0)				return;			break;		case RESHAPE:			redraw(1);			break;				}} inthoriz(void){	int lev[MAXN];	int i, j, h;	Rectangle r; 	h = 0;	for(i=0; i<NY; i++){		for(j=0; board[i][j]; j++)			if(j == NX-1){				lev[h++] = i;				break;			}	}	if(h == 0)		return 0;	r = rboard;	newscreen = 0;	for(j=0; j<h; j++){		r.min.y = rboard.min.y + lev[j]*pcsz;		r.max.y = r.min.y + pcsz;		draw(screen, r, display->white, whitemask, ZP);		flushimage(display, 1);	}	for(i=0; i<3; i++){		pause(250);		if(newscreen){			drawboard();			break;		}		for(j=0; j<h; j++){			r.min.y = rboard.min.y + lev[j]*pcsz;			r.max.y = r.min.y + pcsz;			draw(screen, r, display->white, whitemask, ZP);		}		flushimage(display, 1);	}	r = rboard;	for(j=0; j<h; j++){		i = NY - lev[j] - 1;		score(250+10*i*i);		r.min.y = rboard.min.y;		r.max.y = rboard.min.y+lev[j]*pcsz;		draw(screen, rectaddpt(r, Pt(0,pcsz)), screen, nil, r.min);		r.max.y = rboard.min.y+pcsz;		draw(screen, r, display->white, nil, ZP);		memcpy(&board[1][0], &board[0][0], NX*lev[j]);		memset(&board[0][0], 0, NX);	}	flushimage(display, 1);	return 1;} voidmright(void){	if(!collide(Pt(pos.x+pcsz, pos.y), piece))	if(!collide(Pt(pos.x+pcsz, pos.y+pcsz-DY), piece)){		undrawpiece();		pos.x += pcsz;		drawpiece();		flushimage(display, 1);	}} 

Lines 1–500 of 891.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t