📄 xs.c
字号:
#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 10uchar 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -