Chris Dick
/
Gameduino_chessboard_demo
Chessboard demo for the Gameduino
Diff: main.cpp
- Revision:
- 0:abda8c4b7cfd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Dec 20 21:06:10 2012 +0000 @@ -0,0 +1,264 @@ +#include "mbed.h" +#include "GD.h" +#include "shield.h" + +#include "Wood32.h" +#include "staunton.h" // Chess pieces from eboard's Staunton set: http://www.bergo.eng.br + +#define digits (sizeof(staunton_img) / 256) +#include "digits.h" + +GDClass GD(ARD_MOSI, ARD_MISO, ARD_SCK, ARD_D9, USBTX, USBRX) ; +int atxy(int x, int y) +{ + return (y << 6) + x; +} + +static void square(byte x, byte y, byte light) +{ + PROGMEM prog_uchar *src = Wood32_pic + (16 * light); + int addr = atxy(x, y); + GD.copy(addr + 0 * 64, src, 4); + GD.copy(addr + 1 * 64, src + 4, 4); + GD.copy(addr + 2 * 64, src + 8, 4); + GD.copy(addr + 3 * 64, src + 12, 4); +} + +#define QROOK 0 +#define QKNIGHT 1 +#define QBISHOP 2 +#define QUEEN 3 +#define KING 4 +#define KBISHOP 5 +#define KKNIGHT 6 +#define KROOK 7 +#define PAWN 8 +#define WHITE 0x00 +#define BLACK 0x10 + +static signed char board[32]; + +static void startboard() +{ + byte i; + + for (i = 0; i < 8; i++) { + board[i] = 56 + i; + board[8+i] = 48 + i; + board[16+i] = i; + board[24+i] = 8 + i; + } +} + +// Return the piece at pos, or -1 if pos is empty +static signed char find(byte pos) +{ + byte slot; + for (slot = 0; slot < 32; slot++) + if (board[slot] == pos) + return slot; + return -1; +} + +byte images[16] = { 0, 1, 2, 3, 4, 2, 1, 0, 5, 5, 5, 5, 5, 5, 5, 5 }; + +static void piece(byte slot, int x, int y) +{ + byte i = (4 * slot); + byte j = images[slot & 0xf] * 2; + byte bw = (slot >> 4) & 1; + GD.sprite(i, x, y, j, bw, 0); + GD.sprite(i + 1, x + 16, y, j + 1, bw, 0); + GD.sprite(i + 2, x, y + 16, j + 12, bw, 0); + GD.sprite(i + 3, x + 16, y + 16, j + 13, bw, 0); +} + +#define BOARDX(pos) (8 + (((pos) & 7) << 5)) +#define BOARDY(pos) (24 + ((((pos) >> 3) & 7) << 5)) + +static void drawboard() +{ + byte slot; + + for (slot = 0; slot < 32; slot++) { + signed char pos = board[slot]; + if (pos < 0) + piece(slot, 400, 400); + else { + piece(slot, BOARDX(pos), BOARDY(pos)); + } + } +} + +static float smoothstep(float x) +{ + return x*x*(3-2*x); +} + + +// move piece 'slot' to position 'pos'. +// return true if a piece was taken. +static byte movepiece(byte slot, byte pos) +{ + long double x0 = BOARDX(board[slot]); + long double y0 = BOARDY(board[slot]); + long double x1 = BOARDX(pos); + long double y1 = BOARDY(pos); + // move at 1.5 pix/frame + int d = int(sqrt(((x0 - x1)*(x0 - x1)) + ((y0 - y1)*(y0 - y1))) / 2); + int it; + for (it = 0; it < d; it++) { + float t = smoothstep(float(it) / d); + GD.waitvblank(); + GD.waitvblank(); + piece(slot, int(x0 + t * (x1 - x0)), int(y0 + t * (y1 - y0))); + } + byte taken = find(pos) != -1; + if (taken) + board[find(pos)] = -1; + board[slot] = pos; + drawboard(); + return taken; +} + +void setup() +{ + int i, j; + + GD.begin(); + GD.ascii(); + GD.putstr(0, 0, "Chess board"); + + GD.copy(RAM_CHR, Wood32_chr, sizeof(Wood32_chr)); + GD.copy(RAM_PAL, Wood32_pal, sizeof(Wood32_pal)); + GD.copy(RAM_SPRIMG, staunton_img, sizeof(staunton_img)); + GD.copy(RAM_SPRPAL, staunton_white, sizeof(staunton_white)); + GD.copy(RAM_SPRPAL + 512, staunton_black, sizeof(staunton_black)); + + GD.copy(RAM_SPRIMG + (digits << 8), digits_img, sizeof(digits_img)); + GD.copy(RAM_SPRPAL + 2 * 512, digits_pal, sizeof(digits_pal)); + for (i = 0; i < 256; i++) { + unsigned int b = GD.rd16(RAM_SPRPAL + 2 * 512 + 2 * i); + GD.wr16(RAM_SPRPAL + 3 * 512 + 2 * i, b ^ 0x7fff); + } + + // Draw the 64 squares of the board + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + square(1 + (i << 2), 3 + (j << 2), (i ^ j) & 1); + + // Draw the rank and file markers 1-8 a-h + for (i = 0; i < 8; i++) { + GD.wr(atxy(3 + (i << 2), 2), 'a' + i); + GD.wr(atxy(3 + (i << 2), 35), 'a' + i); + GD.wr(atxy(0, 5 + (i << 2)), '8' - i); + GD.wr(atxy(33, 5 + (i << 2)), '8' - i); + } + + startboard(); + drawboard(); +} + +static int clocktimer[2]; + +// draw digit d in sprite slots spr,spr+1 at (x,y) +static void digit(byte spr, byte d, byte bw, int x, int y) +{ + GD.sprite(spr, x, y, digits + d, 2 + bw, 0); + GD.sprite(spr + 1, x, y + 16, digits + d + 11, 2 + bw, 0); +} + +static void showclock(byte bw) +{ + int t = clocktimer[bw]; + byte spr = 128 + (bw * 16); + byte s = t % 60; + int y = (bw ? 31 : 3) * 8; + byte d0 = s % 10; s /= 10; + digit(spr, d0, bw, 400 - 1 * 16, y); + digit(spr + 2, s, bw, 400 - 2 * 16, y); + + digit(spr + 4, 10, bw, 400 - 3 * 16, y); // colon + spr += 6; + int x = 400 - 4 * 16; + + byte m = t / 60; + do { + d0 = m % 10; m /= 10; + digit(spr, d0, bw, x, y); + spr += 2; + x -= 16; + } while (m); +} + +static int turn; + +#define ALG(r,f) ((r - 'a') + ((8 - f) * 8)) +#define CASTLE 255,255 + +static byte game[] = { + ALG('e', 2),ALG('e', 4), ALG('e', 7),ALG('e', 5), + ALG('g', 1),ALG('f', 3), ALG('b', 8),ALG('c', 6), + ALG('f', 1),ALG('b', 5), ALG('a', 7),ALG('a', 6), + ALG('b', 5),ALG('a', 4), ALG('g', 8),ALG('f', 6), + ALG('d', 1),ALG('e', 2), ALG('b', 7),ALG('b', 5), + ALG('a', 4),ALG('b', 3), ALG('f', 8),ALG('e', 7), + ALG('c', 2),ALG('c', 3), CASTLE, + CASTLE, ALG('d', 7),ALG('d', 5), + ALG('e', 4),ALG('d', 5), ALG('f', 6),ALG('d', 5), + ALG('f', 3),ALG('e', 5), ALG('d', 5),ALG('f', 4), + ALG('e', 2),ALG('e', 4), ALG('c', 6),ALG('e', 5), + ALG('e', 4),ALG('a', 8), ALG('d', 8),ALG('d', 3), + ALG('b', 3),ALG('d', 1), ALG('c', 8),ALG('h', 3), + ALG('a', 8),ALG('a', 6), ALG('h', 3),ALG('g', 2), + ALG('f', 1),ALG('e', 1), ALG('d', 3),ALG('f', 3), +}; + +static void putalg(byte x, byte y, byte a) +{ + GD.wr(atxy(x, y), 'a' + (a & 7)); + GD.wr(atxy(x+1, y), '8' - ((a >> 3) & 7)); +} + +int main() +{ + setup(); + while(1){ + byte i; + for (i = rand()%25; i; i--) { + clocktimer[(1 & turn) ^ 1]++; + GD.waitvblank(); + showclock(0); + showclock(1); + wait_ms(20); + } + if (turn < (sizeof(game) / 2)) { + byte yy = 8 + (turn >> 1); + byte xx = (turn & 1) ? 44 : 38; + byte i = 1 + (turn >> 1); + if (i >= 10) + GD.wr(atxy(35, yy), '0' + i / 10); + GD.wr(atxy(36, yy), '0' + i % 10); + GD.wr(atxy(37, yy), '.'); + + byte from = game[2 * turn]; + byte to = game[2 * turn + 1]; + if (from != 255) { + putalg(xx, yy, from); + GD.wr(atxy(xx + 2, yy), movepiece(find(from), to) ? 'x' : '-'); + putalg(xx + 3, yy, to); + } else { + byte rank = (turn & 1) ? 8 : 1; + movepiece(find(ALG('e', rank)), ALG('g', rank)); + movepiece(find(ALG('h', rank)), ALG('f', rank)); + GD.putstr(xx, yy, "O-O"); + } + turn++; + } else { + wait_ms(4000); + setup(); + turn = 0; + clocktimer[0] = 0; + clocktimer[1] = 0; + } +}} \ No newline at end of file