diff options
| author | Väinö Kauppila <vaino@vke.fi> | 2026-04-20 14:57:39 +0300 |
|---|---|---|
| committer | Väinö Kauppila <vaino@vke.fi> | 2026-04-20 14:57:39 +0300 |
| commit | 922c620bf0921a60e15e8abe627b3199e7e1e12a (patch) | |
| tree | eb42145ade148978e2d5c34e7f5881a1d7fcc152 /fw | |
| parent | d36d2c8a9f4c8e602bd8d72295bb6285c0f7f67c (diff) | |
| download | vhdl_pic-922c620bf0921a60e15e8abe627b3199e7e1e12a.tar.gz vhdl_pic-922c620bf0921a60e15e8abe627b3199e7e1e12a.zip | |
snake
Diffstat (limited to 'fw')
| -rw-r--r-- | fw/snake.c | 164 |
1 files changed, 118 insertions, 46 deletions
@@ -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(); } } |
