summaryrefslogtreecommitdiffstats
path: root/fw/snake.c
diff options
context:
space:
mode:
Diffstat (limited to 'fw/snake.c')
-rw-r--r--fw/snake.c164
1 files changed, 118 insertions, 46 deletions
diff --git a/fw/snake.c b/fw/snake.c
index 968379e..a57d241 100644
--- a/fw/snake.c
+++ b/fw/snake.c
@@ -6,23 +6,27 @@ __sfr __at(0x70) UART_TX;
__sfr __at(0x71) UART_RX;
__sfr __at(0x72) UART_STATUS;
-/*
- * how many OVF per refresh of the screen
- */
-#define OVF_PER_REFRESH 80
+#define GRID_W 20
+#define GRID_H 10
+#define MAX_LEN 20
+#define OVF_PER_FRAME 60
#define DIR_UP 0
#define DIR_DOWN 1
#define DIR_LEFT 2
#define DIR_RIGHT 3
-uint8_t direction;
-uint8_t position[2];
-
-static volatile uint8_t ovf_count = 0;
+static uint8_t snake_x[MAX_LEN];
+static uint8_t snake_y[MAX_LEN];
+static uint8_t snake_len;
+static uint8_t direction;
+static uint8_t food_x;
+static uint8_t food_y;
+static uint8_t score;
+static volatile uint8_t ovf_count;
void isr(void) __interrupt(0) {
- if (INTCON & 0x04) { /* T0IF = bit 2 */
+ if (INTCON & 0x04) {
ovf_count++;
INTCON &= ~(uint8_t)0x04;
}
@@ -39,8 +43,8 @@ static void uart_puts(const char *s) {
static uint8_t uart_recv(void) {
if (UART_STATUS & 0x02)
- return 0; /* rx_empty: nothing to read */
- return UART_RX; /* reading pops the FIFO */
+ return 0;
+ return UART_RX;
}
static uint8_t uart_getc(void) {
@@ -50,25 +54,19 @@ static uint8_t uart_getc(void) {
static void handle_input(void) {
uint8_t c = uart_recv();
- if (c != 0x1B)
- return;
- if (uart_getc() != '[')
- return;
+ if (c != 0x1B) return;
+ if (uart_getc() != '[') return;
switch (uart_getc()) {
- case 'A': direction = DIR_UP; break; /* ESC [ A */
- case 'B': direction = DIR_DOWN; break; /* ESC [ B */
- case 'C': direction = DIR_RIGHT; break; /* ESC [ C */
- case 'D': direction = DIR_LEFT; break; /* ESC [ D */
+ case 'A': if (direction != DIR_DOWN) direction = DIR_UP; break;
+ case 'B': if (direction != DIR_UP) direction = DIR_DOWN; break;
+ case 'C': if (direction != DIR_LEFT) direction = DIR_RIGHT; break;
+ case 'D': if (direction != DIR_RIGHT) direction = DIR_LEFT; break;
}
}
-static void update_position(void) {
- switch (direction) {
- case DIR_UP: position[1]--; break;
- case DIR_DOWN: position[1]++; break;
- case DIR_LEFT: position[0]--; break;
- case DIR_RIGHT: position[0]++; break;
- }
+static void place_food(void) {
+ food_x = (ovf_count * 7 + 3) % GRID_W;
+ food_y = (ovf_count * 5 + 1) % GRID_H;
}
static void print_uint8(uint8_t v) {
@@ -83,40 +81,114 @@ static void print_uint8(uint8_t v) {
uart_send(v + '0');
}
-
static void render(void) {
- uart_puts("\x1B[H"); /* cursor home */
+ uint8_t x, y, i;
+
+ uart_puts("\x1B[H");
- uart_puts("pos: ");
- print_uint8(position[0]);
- uart_puts(", ");
- print_uint8(position[1]);
- uart_puts("\r\n");
+ /* top border */
+ uart_send('+');
+ for (x = 0; x < GRID_W; x++) uart_send('-');
+ uart_puts("+\r\n");
+
+ for (y = 0; y < GRID_H; y++) {
+ uart_send('|');
+ for (x = 0; x < GRID_W; x++) {
+ uint8_t ch = ' ';
+ if (x == food_x && y == food_y) {
+ ch = '*';
+ } else {
+ for (i = 0; i < snake_len; i++) {
+ if (snake_x[i] == x && snake_y[i] == y) {
+ ch = (i == 0) ? 'O' : 'o';
+ break;
+ }
+ }
+ }
+ uart_send(ch);
+ }
+ uart_puts("|\r\n");
+ }
+
+ /* bottom border */
+ uart_send('+');
+ for (x = 0; x < GRID_W; x++) uart_send('-');
+ uart_puts("+\r\n");
+
+ uart_puts("Score: ");
+ print_uint8(score);
+ uart_puts(" \r\n");
}
+/* returns 1 if alive, 0 if dead */
+static uint8_t update(void) {
+ uint8_t nx, ny, i;
+
+ nx = snake_x[0];
+ ny = snake_y[0];
+ switch (direction) {
+ case DIR_UP: if (ny == 0) return 0; ny--; break;
+ case DIR_DOWN: if (ny == GRID_H-1) return 0; ny++; break;
+ case DIR_LEFT: if (nx == 0) return 0; nx--; break;
+ case DIR_RIGHT: if (nx == GRID_W-1) return 0; nx++; break;
+ }
+
+ /* self-collision (exclude tail: it moves away this step) */
+ for (i = 0; i < snake_len - 1; i++) {
+ if (snake_x[i] == nx && snake_y[i] == ny) return 0;
+ }
+
+ if (nx == food_x && ny == food_y) {
+ if (snake_len < MAX_LEN) snake_len++;
+ score++;
+ place_food();
+ }
+
+ /* shift body back, add new head */
+ for (i = snake_len - 1; i > 0; i--) {
+ snake_x[i] = snake_x[i-1];
+ snake_y[i] = snake_y[i-1];
+ }
+ snake_x[0] = nx;
+ snake_y[0] = ny;
+
+ return 1;
+}
void main(void) {
+ uint8_t alive;
OPTION_REG = 0x07;
TMR0 = 0;
INTCON = 0xa0;
- direction = DIR_RIGHT;
- position[0] = 10;
- position[1] = 5;
+ while (1) {
+ /* init */
+ direction = DIR_RIGHT;
+ snake_len = 3;
+ score = 0;
+ snake_x[0] = 5; snake_y[0] = 5;
+ snake_x[1] = 4; snake_y[1] = 5;
+ snake_x[2] = 3; snake_y[2] = 5;
+ place_food();
- uart_puts("\x1B[2J\x1B[H");
- uart_puts("snake\r\n");
- uart_puts("-----------\r\n");
+ uart_puts("\x1B[2J\x1B[H");
- while (1) {
- ovf_count = 0;
- while (ovf_count < OVF_PER_REFRESH);
+ alive = 1;
+ while (alive) {
+ ovf_count = 0;
+ while (ovf_count < OVF_PER_FRAME);
- handle_input();
- update_position();
- render();
+ handle_input();
+ alive = update();
+ render();
+ PORTA ^= 0x01;
+ }
- PORTA ^= 0x01;
+ uart_puts("\x1B[2J\x1B[H");
+ uart_puts("GAME OVER score: ");
+ print_uint8(score);
+ uart_puts("\r\npress any key\r\n");
+ uart_getc();
}
}