#include #include #include #include #include #include enum{GAP = 4}; Point o; Image *bg, *fg, *cards; int w, h, from = -1, to = -1; char locofcard[52], cardatloc[52]; Rectangle rect(int i){ Rectangle r; r.min.x = o.x + (i % 13) * (w + GAP); r.min.y = o.y + (i / 13) * (h + GAP); r.max.x = r.min.x + w; r.max.y = r.min.y + h; return r; } void paint(Image *colour){ border(screen, rect(from), -GAP, colour, ZP); if(to) draw(screen, rect(to), colour, nil, ZP); else{ if(!cardatloc[0]) draw(screen, rect(0), colour, nil, ZP); if(!cardatloc[13]) draw(screen, rect(13), colour, nil, ZP); if(!cardatloc[26]) draw(screen, rect(26), colour, nil, ZP); if(!cardatloc[39]) draw(screen, rect(39), colour, nil, ZP); } } void move(void){ while(cardatloc[to]) to += 13; cardatloc[to] = cardatloc[from]; cardatloc[from] = 0; locofcard[cardatloc[to]] = to; draw(screen, rect(from), bg, nil, ZP); draw(screen, rect(to), cards, nil, Pt(cardatloc[to] % 13 * w, cardatloc[to] / 13 * h)); from = to = -1; flushimage(display, 1); } void threadmain(int, char**){ Mousectl *m; Keyboardctl *kbd; Rune k; int i, j, b; char *s = "shuffles used: 0"; char *cmd[] = {"hint", "shuffle", "quit", nil}; Menu menu = {cmd, nil, 0}; enum{RESIZE, MOUSE, KEYBOARD}; Alt a[] = { [RESIZE]{nil, nil, CHANRCV}, [MOUSE]{nil, nil, CHANRCV}, [KEYBOARD]{nil, &k, CHANRCV}, {nil, nil, CHANEND} }; if(initdraw(nil, nil, "addiction") < 0) sysfatal("initdraw: %r"); bg = allocimage(display, Rect(0,0,1,1), RGBA32, 1, DDarkgreen); fg = allocimage(display, Rect(0,0,1,1), RGBA32, 1, DPaleyellow); if(bg == nil || fg == nil) sysfatal("allocimage: %r"); if((i = open("/sys/games/lib/cards/default.bit", OREAD)) < 0) sysfatal("couldn't find cards: %r"); if((cards = readimage(display, i, 0)) == nil) sysfatal("readimage: /sys/games/lib/cards/default.bit bad format"); close(i); w = Dx(cards->r) / 13; h = Dy(cards->r) / 4; if((m = initmouse(nil, screen)) == nil) sysfatal("initmouse: %r"); a[RESIZE].c = m->resizec; a[MOUSE].c = m->c; a[MOUSE].v = &m->Mouse; if((kbd = initkeyboard(nil)) == nil) sysfatal("initkeyboard: %r"); a[KEYBOARD].c = kbd->c; srand(truerand()); for(j = 0; j < 52; j++) cardatloc[j] = j; cardatloc[13] = cardatloc[26] = cardatloc[39] = 0; while(j > 1){ i = nrand(j--); locofcard[cardatloc[j]] = i; if(i != j){ locofcard[cardatloc[i]] = j; b = cardatloc[i]; cardatloc[i] = cardatloc[j]; cardatloc[j] = b; } } sendul(m->resizec, 1); for(;;) switch(alt(a)){ case RESIZE: from = to = -1; if(getwindow(display, Refnone) < 0) sysfatal("getwindow: %r"); draw(screen, screen->r, bg, nil, ZP); o.x = screen->r.min.x + screen->r.max.x - 13 * w - 12 * GAP >> 1; o.y = screen->r.min.y + screen->r.max.y - 4 * h - 3 * GAP >> 1; for(i = 0; i < 52; i++) if(cardatloc[i]){ draw(screen, rect(i), cards, nil, Pt(cardatloc[i] % 13 * w, cardatloc[i] / 13 * h)); flushimage(display, 1); sleep(20); } string(screen, Pt(o.x, o.y - font->height), fg, ZP, font, s); flushimage(display, 1); break; case MOUSE: if(!m->buttons) break; if(m->buttons & 4){ i = menuhit(3, m, &menu, nil); if(i >= 0 && i < nelem(cmd)) sendul(kbd->c, *cmd[i]); break; } b = m->buttons; do readmouse(m); while(m->buttons); if(from >= 0) paint(bg); i = m->xy.x - o.x; j = m->xy.y - o.y; if(i < 0 || j < 0 || i % (w + GAP) >= w || j % (h + GAP) >= h || (i /= w + GAP) >= 13 || (j /= h + GAP) >= 4){ if(from >= 0){ from = to = -1; flushimage(display, 1); } break; } i += j * 13; if(from < 0){ if(cardatloc[i] % 13 == 1 && !cardatloc[0] | !cardatloc[13] | !cardatloc[26] | !cardatloc[39]){ from = i; to = 0; } else if(cardatloc[i]){ j = locofcard[cardatloc[i] - 1] + 1; if(j % 13 && !cardatloc[j]){ from = i; to = j; } } if(from == i){ if(b & 2) move(); else{ paint(fg); flushimage(display, 1); } } break; } if(cardatloc[i] || i % 13 && i != to || i % 13 == 0 && to){ from = to = -1; flushimage(display, 1); break; } to = i; move(); break; case KEYBOARD: switch(k){ case ' ': if(from >= 0){ paint(bg); move(); break; } case 'h': if(from >= 0) paint(bg); i = j = from < 0 ? 53 : from; do{ i = i == 53 ? 0 : i + 1; if(cardatloc[i] % 13 == 1 && (!cardatloc[0] || !cardatloc[13] || !cardatloc[26] || !cardatloc[39])){ from = i; to = 0; paint(fg); break; } if(cardatloc[i] % 13 > 1 && locofcard[cardatloc[i] - 1] % 13 < 12 && !cardatloc[locofcard[cardatloc[i] - 1] + 1]){ from = i; to = locofcard[cardatloc[i] - 1] + 1; paint(fg); break; } }while(i != j); flushimage(display, 1); break; case 's': s[15] = s[15] == '9' ? 'A' : s[15] + 1; i = j = 0; if(cardatloc[i] % 13 == 1) do i++; while(cardatloc[i] == cardatloc[i - 1] + 1); while(i < 13){ locofcard[j++] = cardatloc[i]; cardatloc[i++] = 52; } if(cardatloc[i] % 13 == 1) do i++; while(cardatloc[i] == cardatloc[i - 1] + 1); while(i < 26){ locofcard[j++] = cardatloc[i]; cardatloc[i++] = 52; } if(cardatloc[i] % 13 == 1) do i++; while(cardatloc[i] == cardatloc[i - 1] + 1); while(i < 39){ locofcard[j++] = cardatloc[i]; cardatloc[i++] = 52; } if(cardatloc[i] % 13 == 1) do i++; while(cardatloc[i] == cardatloc[i - 1] + 1); while(i < 52){ locofcard[j++] = cardatloc[i]; cardatloc[i++] = 52; } while(j > 1){ i = nrand(j--); from = locofcard[i]; locofcard[i] = locofcard[j]; locofcard[j] = from; } for(i = j = 0; i < 52; i++) if(cardatloc[i] == 52) cardatloc[i] = locofcard[j++]; for(i = 0; i < 52; i++) locofcard[cardatloc[i]] = i; from = to = -1; sendul(m->resizec, 1); break; case Kesc: if((i = open("/dev/wctl", OWRITE)) >= 0){ write(i, "hide", 4); close(i); } break; case Kdel: case 'q': threadexitsall(nil); } break; default: sysfatal("Murtis bene felas"); } }