Browse Source

converted bitstuffing algorithms to native borg frame buffer format, saving 124 bytes

feature/2015
Christian Kroll 14 years ago
parent
commit
12a8e94db4
  1. 291
      animations/gameoflife.c

291
animations/gameoflife.c

@ -23,34 +23,34 @@
#define XSIZE UNUM_COLS #define XSIZE UNUM_COLS
#define YSIZE UNUM_ROWS #define YSIZE UNUM_ROWS
// optimizing for 8 bit archs while retaining compatibility with dimensions >255 // optimizing for 8 bit archs while retaining compatibility with dimensions >127
#if UNUM_COLS < 128 && UNUM_ROWS < 128 #if UNUM_COLS < 128 && UNUM_ROWS < 128
typedef uint8_t coord_t; typedef uint8_t coord_t;
#else #else
typedef unsigned int coord_t; typedef unsigned int coord_t;
#endif #endif
/* /*
* last line is for debug information * last line is for debug information
*/ */
#ifdef DEBUG #ifdef DEBUG
#undef YSIZE #undef YSIZE
#define YSIZE (UNUM_ROWS-1) #define YSIZE (UNUM_ROWS-1)
#define DEBUG_ROW (UNUM_ROWS-1) #define DEBUG_ROW (UNUM_ROWS-1)
#define DEBUG_BIT(pos, val) \ #define DEBUG_BIT(pos, val) \
setpixel((pixel){(pos)%XSIZE,DEBUG_ROW+(pos)/XSIZE},(val)?3:0) setpixel((pixel){(pos) % XSIZE,DEBUG_ROW + (pos) / XSIZE}, (val) ? 3 : 0)
#define DEBUG_BYTE(s,v) \ #define DEBUG_BYTE(s,v) \
DEBUG_BIT((s)*8+0, (v)&(1<<0)); \ DEBUG_BIT((s)*8+0, (v)&(1<<0)); \
DEBUG_BIT((s)*8+1, (v)&(1<<1)); \ DEBUG_BIT((s)*8+1, (v)&(1<<1)); \
DEBUG_BIT((s)*8+2, (v)&(1<<2)); \ DEBUG_BIT((s)*8+2, (v)&(1<<2)); \
DEBUG_BIT((s)*8+3, (v)&(1<<3)); \ DEBUG_BIT((s)*8+3, (v)&(1<<3)); \
DEBUG_BIT((s)*8+4, (v)&(1<<4)); \ DEBUG_BIT((s)*8+4, (v)&(1<<4)); \
DEBUG_BIT((s)*8+5, (v)&(1<<5)); \ DEBUG_BIT((s)*8+5, (v)&(1<<5)); \
DEBUG_BIT((s)*8+6, (v)&(1<<6)); \ DEBUG_BIT((s)*8+6, (v)&(1<<6)); \
DEBUG_BIT((s)*8+7, (v)&(1<<7)) DEBUG_BIT((s)*8+7, (v)&(1<<7))
#else #else
#define DEBUG_BIT(s,v) #define DEBUG_BIT(s,v)
#define DEBUG_BYTE(s,v) #define DEBUG_BYTE(s,v)
#endif #endif
//#define GLIDER_TEST //#define GLIDER_TEST
@ -59,17 +59,19 @@ typedef unsigned int coord_t;
#define LOOP_DETECT_BUFFER_SIZE 8U #define LOOP_DETECT_BUFFER_SIZE 8U
#ifndef GOL_DELAY #ifndef GOL_DELAY
#define GOL_DELAY 1 /* milliseconds */ #define GOL_DELAY 1 /* milliseconds */
#endif #endif
#ifndef GOL_CYCLES #ifndef GOL_CYCLES
#define GOL_CYCLES (2*60*3) #define GOL_CYCLES (2*60*3)
#endif #endif
/******************************************************************************/ /******************************************************************************/
/******************************************************************************/ /******************************************************************************/
enum cell_e {dead=0, alive=1}; enum cell_e {
dead = 0, alive = 1
};
#ifdef NDEBUG #ifdef NDEBUG
typedef uint8_t cell_t; typedef uint8_t cell_t;
#else #else
@ -81,60 +83,55 @@ enum cell_e {dead=0, alive=1};
#define FIELD_XSIZE XSIZE #define FIELD_XSIZE XSIZE
#define FIELD_YSIZE YSIZE #define FIELD_YSIZE YSIZE
typedef cell_t field_t[FIELD_XSIZE][FIELD_YSIZE]; typedef cell_t field_t[FIELD_YSIZE][FIELD_XSIZE];
/******************************************************************************/ /******************************************************************************/
void setcell(field_t pf, coord_t x, coord_t y, cell_t value){ void setcell(field_t pf, coord_t x, coord_t y, cell_t value) {
pf[(x+FIELD_XSIZE)%FIELD_XSIZE][(y+FIELD_YSIZE)%FIELD_YSIZE] = value; pf[(y+FIELD_YSIZE) % FIELD_YSIZE][(x+FIELD_XSIZE) % FIELD_XSIZE] = value;
} }
/******************************************************************************/ /******************************************************************************/
cell_t getcell(field_t pf, coord_t x, coord_t y){ cell_t getcell(field_t pf, coord_t x, coord_t y) {
return pf[(x+FIELD_XSIZE)%FIELD_XSIZE][(y+FIELD_YSIZE)%FIELD_YSIZE]; return pf[(y+FIELD_YSIZE) % FIELD_YSIZE][(x+FIELD_XSIZE) % FIELD_XSIZE];
} }
#else /* BITSTUFFED */ #else /* BITSTUFFED */
#define FIELD_XSIZE ((XSIZE+7)/8) #define FIELD_XSIZE LINEBYTES
#define FIELD_YSIZE YSIZE #define FIELD_YSIZE YSIZE
typedef uint8_t field_t[FIELD_XSIZE][FIELD_YSIZE]; typedef uint8_t field_t[FIELD_YSIZE][FIELD_XSIZE];
/******************************************************************************/ /******************************************************************************/
void setcell(field_t pf, coord_t x, coord_t y, cell_t value){ void setcell(field_t pf, coord_t x, coord_t y, cell_t value) {
uint8_t t; if (value != dead) {
pf[y][x / 8] |= shl_table[x & 7];
t = pf[x/8][y];
if(value==alive){
t |= 1<<(x&7);
} else { } else {
t &= ~(1<<(x&7)); pf[y][x / 8] &= ~shl_table[x & 7];
} }
pf[x/8][y] = t;
} }
/******************************************************************************/ /******************************************************************************/
static cell_t getcell(field_t pf, coord_t x, coord_t y){ static cell_t getcell(field_t pf, coord_t x, coord_t y) {
return ((pf[x/8][y])&(1<<(x&7)))?alive:dead; return ((pf[y][x / 8]) & (shl_table[x & 7])) ? alive : dead;
} }
#endif #endif
/******************************************************************************/ /******************************************************************************/
uint8_t countsurroundingalive(field_t pf, coord_t x, coord_t y){ uint8_t countsurroundingalive(field_t pf, coord_t x, coord_t y) {
static int8_t const offset[] = {-1, -1, 0, +1, +1, +1, 0, -1, -1, -1}; static int8_t const offset[] = {-1, -1, 0, +1, +1, +1, 0, -1, -1, -1};
x += XSIZE; x += XSIZE;
y += YSIZE; y += YSIZE;
uint8_t i, ret=0; uint8_t i, ret = 0;
for (i = 8; i--;) for (i = 8; i--;) {
{
// getcell(...) returns either 0 or 1 // getcell(...) returns either 0 or 1
ret += getcell(pf,(x+offset[i+2])%XSIZE, (y+offset[i])%YSIZE); ret += getcell(pf, (x + offset[i+2]) % XSIZE, (y + offset[i]) % YSIZE);
} }
return ret; return ret;
@ -142,29 +139,29 @@ uint8_t countsurroundingalive(field_t pf, coord_t x, coord_t y){
/******************************************************************************/ /******************************************************************************/
void nextiteration(field_t dest, field_t src){ void nextiteration(field_t dest, field_t src) {
coord_t x,y; coord_t x, y;
uint8_t tc; uint8_t tc;
for(y=0; y<YSIZE; ++y){ for (y = YSIZE; y--;) {
for(x=0; x<XSIZE; ++x){ for (x = XSIZE; x--;) {
tc=countsurroundingalive(src,x,y); tc = countsurroundingalive(src, x, y);
switch(tc){ switch (tc) {
// case 0: // case 0:
// case 1: // case 1:
// /* dead */ // /* dead */
// setcell(dest, x,y, dead); // setcell(dest, x,y, dead);
case 2: case 2:
/* keep */ /* keep */
setcell(dest, x,y, getcell(src,x,y)); setcell(dest, x, y, getcell(src, x, y));
break; break;
case 3: case 3:
/* alive */ /* alive */
setcell(dest, x,y, alive); setcell(dest, x, y, alive);
break; break;
default: default:
/* dead */ /* dead */
setcell(dest, x,y, dead); setcell(dest, x, y, dead);
break; break;
} }
} }
} }
@ -172,151 +169,145 @@ void nextiteration(field_t dest, field_t src){
/******************************************************************************/ /******************************************************************************/
void printpf(field_t pf){ #ifdef BITSTUFFED
static void pfprint(field_t pf) {
memcpy(pixmap[NUMPLANE - 1], pf, sizeof(field_t));
}
#else
void pfprint(field_t pf) {
coord_t x,y; coord_t x,y;
for(y=YSIZE; y--;){ for(y=YSIZE; y--;) {
for(x=XSIZE; x--;){ for(x=XSIZE; x--;) {
setpixel((pixel){x,y},getcell(pf,x,y)*3); setpixel((pixel){x,y},getcell(pf,x,y)*3);
} }
} }
} }
#endif
/******************************************************************************/ /******************************************************************************/
void pfcopy(field_t dest, field_t src){ static void pfcopy(field_t dest, field_t src) {
coord_t x,y; memcpy(dest, src, sizeof(field_t));
for(y=YSIZE; y--;){
for(x=XSIZE; x--;){
setcell(dest,x,y,getcell(src,x,y));
}
}
} }
/******************************************************************************/ /******************************************************************************/
#ifndef BITSTUFFED
uint8_t pfcmp(field_t dest, field_t src){ static int pfcmp(field_t dest, field_t src) {
coord_t x,y; return memcmp(dest, src, sizeof(field_t));
for(y=YSIZE; y--;){
for(x=XSIZE; x--;){
if (getcell(src,x,y) != getcell(dest,x,y))
return 1;
}
}
return 0;
} }
#ifndef BITSTUFFED
/******************************************************************************/ /******************************************************************************/
uint8_t pfempty(field_t src){ uint8_t pfempty(field_t src) {
coord_t x,y; coord_t x,y;
for(y=YSIZE; y--;){ for(y=YSIZE; y--;) {
for(x=XSIZE; x--;){ for(x=XSIZE; x--;) {
if (getcell(src,x,y)==alive) if (getcell(src, x, y)==alive)
return 0; return 0;
} }
} }
return 1; return 1;
} }
#else #else
uint8_t pfcmp(field_t dest, field_t src){
coord_t x,y;
for(y=0; y<FIELD_YSIZE; ++y){
for(x=0; x<FIELD_XSIZE; ++x){
if (src[x][y] != dest[x][y])
return 1;
}
}
return 0;
}
/******************************************************************************/ /******************************************************************************/
uint8_t pfempty(field_t src){ uint8_t pfempty(field_t src) {
coord_t x,y; coord_t x, y;
for(y=0; y<FIELD_YSIZE; ++y){ for (y = 0; y < FIELD_YSIZE; ++y) {
for(x=0; x<FIELD_XSIZE; ++x){ for (x = 0; x < FIELD_XSIZE; ++x) {
if (src[x][y]!=0) if (src[y][x] != 0)
return 0; return 0;
} }
} }
return 1; return 1;
} }
#endif #endif
/******************************************************************************/ /******************************************************************************/
void insertglider(field_t pf){ void insertglider(field_t pf) {
/* /*
* # * #
* # * #
* ### * ###
*/ */
setcell(pf, 1, 0, alive); setcell(pf, 1, 0, alive);
setcell(pf, 2, 1, alive); setcell(pf, 2, 1, alive);
setcell(pf, 0, 2, alive); setcell(pf, 1, 2, alive); setcell(pf, 2, 2, alive); setcell(pf, 0, 2, alive);setcell(pf, 1, 2, alive);setcell(pf, 2, 2, alive);
}
/******************************************************************************/
static void pfinit(field_t pf)
{
coord_t x, y;
#ifndef BITSTUFFED
for (y = YSIZE; y--;) {
for (x = XSIZE; x--;) {
setcell(pf, x, y, (random8() & 1) ? alive : dead);
}
}
#else
for (y = 0; y < FIELD_YSIZE; ++y) {
for (x = 0; x < FIELD_XSIZE; ++x) {
pf[y][x] = random8();
}
}
#endif
} }
/******************************************************************************/ /******************************************************************************/
int gameoflife(){ void gameoflife() {
DEBUG_BYTE(0,0); // set debug bytes to zero DEBUG_BYTE(0,0); // set debug bytes to zero
DEBUG_BYTE(1,0); DEBUG_BYTE(1,0);
field_t pf1,pf2; field_t pf1, pf2;
field_t ldbuf[LOOP_DETECT_BUFFER_SIZE]={{{0}}}; // loop detect buffer field_t ldbuf[LOOP_DETECT_BUFFER_SIZE] = {{{0}}}; // loop detect buffer
uint8_t ldbuf_idx=0; uint8_t ldbuf_idx = 0;
coord_t x,y;
uint16_t cycle; uint16_t cycle;
//start: /* initialize the field with random */
/* initalise the field with random */ pfinit(pf1);
for(y=YSIZE; y--;){
for(x=XSIZE; x--;){
setcell(pf1,x,y,(random8()&1)?alive:dead);
}
}
#ifdef GLIDER_TEST #ifdef GLIDER_TEST
/* initialise with glider */ /* initialize with glider */
for(y=YSIZE; y--;){ for(y=YSIZE; y--;) {
for(x=XSIZE; x--;){ for(x=XSIZE; x--;) {
setcell(pf1,x,y,dead); setcell(pf1, x, y, dead);
} }
} }
insertglider(pf1); insertglider(pf1);
#endif #endif
/* the main part */ /* the main part */
printpf(pf1); pfprint(pf1);
for(cycle=1; cycle<GOL_CYCLES; ++cycle){ for (cycle = 1; cycle < GOL_CYCLES; ++cycle) {
DEBUG_BYTE(0,(uint8_t)(GOL_CYCLES-cycle)&0xff); DEBUG_BYTE(0, (uint8_t)(GOL_CYCLES-cycle) & 0xff); DEBUG_BYTE(1, SREG);
DEBUG_BYTE(1, SREG);
wait(GOL_DELAY); wait(GOL_DELAY);
pfcopy(pf2,pf1); pfcopy(pf2, pf1);
nextiteration(pf1,pf2); nextiteration(pf1, pf2);
printpf(pf1); pfprint(pf1);
/* loop detection */ /* loop detection */
if(!pfcmp(pf1, pf2)){ if (!pfcmp(pf1, pf2)) {
insertglider(pf1); insertglider(pf1);
cycle=1; cycle = 1;
} }
if(pfempty(pf1)){ if (pfempty(pf1)) {
/* kill game */ /* kill game */
return 0; return;
} }
/* */ /* */
uint8_t i; uint8_t i;
for(i=0; i<LOOP_DETECT_BUFFER_SIZE; ++i){ for (i = 0; i < LOOP_DETECT_BUFFER_SIZE; ++i) {
if(!pfcmp(pf1, ldbuf[i])){ if (!pfcmp(pf1, ldbuf[i])) {
insertglider(pf1); insertglider(pf1);
cycle=1; cycle = 1;
} }
} }
pfcopy(ldbuf[ldbuf_idx], pf1); pfcopy(ldbuf[ldbuf_idx], pf1);
ldbuf_idx = (ldbuf_idx+1)%LOOP_DETECT_BUFFER_SIZE; ldbuf_idx = (ldbuf_idx + 1) % LOOP_DETECT_BUFFER_SIZE;
} }
return 0;
} }

Loading…
Cancel
Save