Improve random, allow playing more than one game

This commit is contained in:
Matthias Schiffer 2013-03-14 22:52:04 +01:00
parent 9054f9a526
commit b0dda6fda2
2 changed files with 30 additions and 12 deletions

1
kbd.h
View file

@ -9,6 +9,7 @@
#define KBD_FLAG_BREAK (_BV(1))
#define KBD_FLAG_EXT (_BV(2))
#define KBD_CODE_SPACE 0x29
#define KBD_CODE_UP 0xe075
#define KBD_CODE_LEFT 0xe06b
#define KBD_CODE_DOWN 0xe072

39
snake.c
View file

@ -4,6 +4,7 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdbool.h>
typedef struct _point_t {
@ -20,6 +21,8 @@ typedef enum _dir_t {
static volatile uint8_t dir;
static volatile bool start = false;
static volatile uint16_t lfsr = 0xace1;
static point_t tail = {7, 4};
@ -32,7 +35,6 @@ static uint8_t history_pos = 0;
static point_t q;
static uint16_t rand(void) {
static uint16_t lfsr = 0xace1;
unsigned bit;
/* taps: 16 14 13 11; feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */
@ -42,6 +44,10 @@ static uint16_t rand(void) {
return lfsr;
}
static void rand_mix(uint16_t mix) {
lfsr ^= mix;
}
static void rand_q(void) {
q.x = rand() % 14;
q.y = rand() % 9;
@ -78,6 +84,8 @@ static uint8_t get_dir(uint8_t i) {
}
static void reset(void) {
LedSignClear(0);
rand_q();
dir = EAST;
@ -95,6 +103,10 @@ void kbd_handle(uint16_t code, bool make) {
return;
switch(code) {
case KBD_CODE_SPACE:
start = true;
break;
case KBD_CODE_UP:
dir = NORTH;
break;
@ -142,9 +154,11 @@ static bool point_used(const point_t *p, bool head) {
return false;
}
static void step(void) {
static bool step(void) {
uint8_t d = dir;
rand_mix(d);
LedSignSet(tail.x, tail.y, 0);
int i;
@ -160,9 +174,8 @@ static void step(void) {
go(&pt, d);
LedSignSet(pt.x, pt.y, 3);
if (point_used(&pt, true)) {
while(true) {}
}
if (point_used(&pt, true))
return false;
if (points_equal(&pt, &q)) {
rand_q();
@ -173,25 +186,29 @@ static void step(void) {
move(d, false);
}
if (point_used(&pt, false)) {
while(true) {}
}
if (point_used(&pt, false))
return false;
LedSignSet(q.x, q.y, 7);
return true;
}
int main() {
LedSignInit(GRAYSCALE);
kbd_init();
reset();
sei();
kbd_send(KBD_CMD_RESET);
while(true) {
step();
while (!start) {}
start = false;
reset();
while (step())
_delay_ms(100);
}