Index: apps/plugins/rocklife.c =================================================================== --- apps/plugins/rocklife.c (revision 28308) +++ apps/plugins/rocklife.c (working copy) @@ -20,7 +20,7 @@ ****************************************************************************/ /* - * This is an implementatino of Conway's Game of Life + * This is an implementation of Conway's Game of Life * * from http://en.wikipedia.org/wiki/Conway's_Game_of_Life: * @@ -90,8 +90,9 @@ int generation = 0; int population = 0; int status_line = 0; +unsigned int s_vect[9] = {0, 0, 1, 1, 0, 0, 0, 0, 0}; +unsigned int b_vect[9] = {0, 0, 0, 1, 0, 0, 0, 0, 0}; - static inline bool is_valid_cell(int x, int y) { return (x >= 0 && x < GRID_W && y >= 0 && y < GRID_H); @@ -123,54 +124,366 @@ void init_grid(char *pgrid){ memset(pgrid, 0, GRID_W * GRID_H); } +static int getline(int fd, char *buf, int size) +{ + char c; + int n = 0; + while (rb->read(fd, &c, 1) > 0 && c != '\n') { + if (n < size-1) + buf[n] = c; + n++; + } + buf[MIN(size-1, n)] = '\0'; + return n; +} +static char *skip_spaces(char *str) +{ + while(*str == ' ' || *str == '\r' || *str == '\n') + str++; + return str; +} /*fill grid with pattern from file (viewer mode)*/ static bool load_cellfile(const char *file, char *pgrid){ int fd; + char buf[128], *marker, *ptr; + char c, ext_c, lastchar; + int cnt, xmid, ymid, xmax, ymax; + int x, y, px, py; + bool comment; + + init_grid(pgrid); + + ext_c = '-'; + ptr = rb->strrchr(file, '.'); /* Get the file extension */ + if (rb->strcasecmp(ptr, ".cells") == 0) + ext_c = 'a'; + if (rb->strcasecmp(ptr, ".l") == 0) + ext_c = 'b'; + if (rb->strcasecmp(ptr, ".rle") == 0) + ext_c = 'b'; + if (rb->strcasecmp(ptr, ".lif") == 0 + || rb->strcasecmp(ptr, ".life") == 0) + ext_c = 'c'; + + if (ext_c == '-') { + rb->splash(HZ, "Unrecognized format"); + return false; + } + fd = rb->open(file, O_RDONLY); - if (fd<0) + if (fd<0) { + rb->splash(HZ, "File Open Error"); return false; + } - init_grid(pgrid); - - char c; - int nc, x, y, xmid, ymid; - bool comment; + lastchar = ' '; x=0; y=0; - xmid = (GRID_W>>1) - 2; - ymid = (GRID_H>>1) - 2; + xmid = (GRID_W>>1); + ymid = (GRID_H>>1); + xmax = 0; + ymax = 0; comment = false; - while (true) { - nc = rb->read(fd, &c, 1); - if (nc <= 0) + switch(ext_c) { /* handle different file types */ + case 'a': + while (true) { + if (rb->read(fd, &c, 1) <= 0) + break; + + switch(c) { + case '!': + comment = true; + break; + case '.': + if (!comment) + x++; + break; + case 'O': + if (!comment) { + if (is_valid_cell(x, y)) + set_cell(x, y, pgrid); + x++; + } + break; + case '\n': + y++; + x=0; + comment = false; + break; + default: + break; + } + if (x > xmax) + xmax = x; + if (y > ymax) + ymax = y; + } + break; + case 'b': + while (true) { + getline(fd, buf, sizeof(buf)); + c = *skip_spaces(buf); + if (c == '#') /* comment line */ + continue; + else if (c == '!') { /* Test for Life 1.05 type */ + ext_c = 'l'; + break; + } + else if (c == 'x') { /* Test for RLE type */ + ext_c = 'r'; + break; + } + } + switch(ext_c) { + case 'r': + /* parse header: x = m, y = n[, rule = Babc../Sdef..] */ + ptr = rb->strtok_r(buf, " ,=x", &marker); + xmid -= ptr != NULL? rb->atoi(ptr) / 2: 0; + ptr = rb->strtok_r(NULL, " ,=y", &marker); + ymid -= ptr != NULL? rb->atoi(ptr) / 2: 0; + /* Read new rules if any */ + ptr = rb->strtok_r(NULL, " ,", &marker); + if (ptr != NULL && rb->strcmp(ptr, "rule") == 0 + && (ptr = rb->strtok_r(NULL, " =", &marker)) != NULL) { + for (cnt = 0; cnt < 9; cnt++) { + b_vect[cnt] = 0; + s_vect[cnt] = 0; + } + ptr = rb->strtok_r(ptr, "B/\r\n", &marker); + for (; ptr != NULL && *ptr != '\0'; ptr++) { + if (*ptr >= '0' && *ptr < '9') + b_vect[*ptr - '0'] = 1; + } + ptr = rb->strtok_r(NULL, "S/\r\n", &marker); + for (; ptr != NULL && *ptr != '\0'; ptr++) { + if (*ptr >= '0' && *ptr < '9') + s_vect[*ptr - '0'] = 1; + } + } + cnt = 0; + while(true) { + if (rb->read(fd, &c, 1) <= 0) + break; + if (c == '!') + break; + else if (c == 'x' || c =='y' || c == 'z') + c = 'o'; + else if (!comment && c >= '0' && c <= '9') + cnt = cnt * 10 + (int) c - '0'; + switch(c) { /* parse body chars */ + case 'b': + if (!comment) { + if (cnt < 1) cnt = 1; + while (cnt > 0) { + cnt--; + x++; + } + } + break; + case 'o': + if (!comment) { + if (cnt < 1) cnt = 1; + while (cnt > 0) { + if (is_valid_cell(xmid + x, ymid + y)) + set_cell(xmid + x, ymid + y, pgrid); + cnt--; + x++; + } + } + break; + case '$': + if (!comment) { + y++; + x = 0; + } + if (lastchar >= '0' && lastchar <= '9') + cnt = 0; /* Ignore numbers that precede $ */ + break; + case '#': + comment = true; + break; + case '\n': + comment = false; + break; + default: + break; + } + lastchar = c; + rb->yield(); + } break; - switch(c) { - case '!': - comment = true; - case '.': - if (!comment) - x++; - break; - case 'O': - if (!comment) { - if (is_valid_cell(xmid + x, ymid + y)) - set_cell(xmid + x, ymid + y, pgrid); - x++; + case 'l': + cnt = 0; + while (true) { + if (rb->read(fd, &c, 1) <= 0) + break; + if (!comment && c >= '0' && c <= '9') + cnt = cnt * 10 + (int) c - '0'; + else { + switch(c) { + case '!': + comment = true; + break; + case '.': + if (!comment) { + if (cnt < 1) cnt = 1; + while (cnt > 0) { + cnt--; + x++; + } + } + break; + case '*': + case 'O': + if (!comment) { + if (cnt < 1) cnt = 1; + while (cnt > 0) { + if (is_valid_cell(x, y)) + set_cell(x, y, pgrid); + cnt--; + x++; + } + } + break; + case '\n': + if (!comment) { + y++; + x = 0; + } + cnt = 0; + comment = false; + break; + + default: + break; + } + if (x > xmax) + xmax = x; + if (y > ymax) + ymax = y; + } } break; - case '\n': - y++; - x=0; - comment = false; - break; default: break; } + break; + case 'c': /* Life files */ + if (getline(fd, buf, sizeof(buf)) == 0) + break; + /* check version */ + if (rb->strncasecmp(buf, "#Life", 5)) + break; + if ((ptr = rb->strtok_r(buf + 5, " \r\n", &marker)) == NULL) + break; + if (!rb->strncmp(ptr, "1.05", 4)) { /* 1.05 */ + while (true) { + if (rb->read(fd, &c, 1) <= 0) + break; + if (c == 'x' || c == 'y' || c == 'z') + c = '*'; /* Treat all living states the same */ + switch(c) { + case '#': + comment = true; + break; + case 'P': + if (lastchar == '#') { + getline(fd, buf, sizeof(buf)); + ptr = rb->strtok_r(buf, " ", &marker); + px = ptr != NULL? rb->atoi(ptr): 0; + ptr = rb->strtok_r(NULL, " ", &marker); + py = ptr != NULL? rb->atoi(ptr): 0; + comment = false; + x = 0; + y = 0; + } + break; + /* Read rule information */ + case 'R': + if (lastchar == '#') { + /* clear birth/survival vectors */ + getline(fd, buf, sizeof(buf)); + for (cnt = 0; cnt < 9; cnt++) { + b_vect[cnt] = 0; + s_vect[cnt] = 0; + } + ptr = rb->strtok_r(buf, " /\r\n", &marker); + for (; ptr != NULL && *ptr != '\0'; ptr++) { + if (*ptr >= '0' && *ptr < '9') + b_vect[*ptr - '0'] = 1; + } + ptr = rb->strtok_r(NULL, " \r\n", &marker); + for (; ptr != NULL && *ptr != '\0'; ptr++) { + if (*ptr >= '0' && *ptr < '9') + s_vect[*ptr - '0'] = 1; + } + } + break; + case '.': + if (!comment) + x++; + break; + case '*': + if (!comment) { + if (is_valid_cell(xmid + px + x, ymid + py + y)) + set_cell(xmid + px + x, ymid + py + y, pgrid); + x++; + } + break; + case '\n': + if (!comment) { + y++; + x = 0; + } + comment = false; + break; + default: + break; + } + lastchar = c; + } + } + else if (!rb->strncmp(ptr, "1.06", 4)) { /* 1.06 */ + while (true) { + if (getline(fd, buf, sizeof(buf)) == 0) + break; + if ((ptr = rb->strtok_r(buf, " \r\n", &marker)) == NULL) + continue; + x = rb->atoi(ptr); + if ((ptr = rb->strtok_r(NULL, " \r\n", &marker)) == NULL) + continue; + y = rb->atoi(ptr); + if (is_valid_cell(x, y)) + set_cell(x, y, pgrid); + if (x > xmax) + xmax = x; + if (y > ymax) + ymax = y; + } + } + else { + /* Unrecognized format */ + break; + } + break; + } + rb->close(fd); + /* move to center */ + if (xmax > 0 || ymax > 0) { + if (xmax > GRID_W) xmax = GRID_W; + if (ymax > GRID_H) ymax = GRID_H; + px = (GRID_W - xmax) / 2; + py = (GRID_H - ymax) / 2; + cnt = (py > 0)? xmax: px; + for (y = ymax - 1; y >= 0; y--) { + rb->memmove(&pgrid[(x+px) + (y+py)*GRID_W], + &pgrid[x + y*GRID_W], xmax); + rb->memset(&pgrid[x + y*GRID_W], 0, cnt); + } } - rb->close(fd); return true; } @@ -310,7 +623,11 @@ #if LCD_DEPTH > 1 rb->lcd_set_foreground( LCD_BLACK ); #endif - rb->lcd_putsf(0, 0, "g:%d p:%d", generation, population); + rb->lcd_putsf(0, 0, "g:%d p:%d B:%d%d%d%d%d%d%d%d%d S:%d%d%d%d%d%d%d%d%d", + generation, population, b_vect[0], b_vect[1], b_vect[2], + b_vect[3], b_vect[4], b_vect[5], b_vect[6], b_vect[7], + b_vect[8], s_vect[0], s_vect[1], s_vect[2], s_vect[3], + s_vect[4], s_vect[5], s_vect[6], s_vect[7], s_vect[8]); } rb->lcd_update(); } @@ -343,12 +660,12 @@ alive_cells = 8 - empty_cells; if (n[4]) { - /* If the cell is alive, it stays alive iff it has 2 or 3 alive neighbours */ - result = (alive_cells==2 || alive_cells==3); + /* Check result against survival vector */ + result = (bool) s_vect[alive_cells]; } else { - /* If the cell is dead, it gets alive iff it has 3 alive neighbours */ - result = (alive_cells==3); + /* If dead, check result against birth vector */ + result = (bool) b_vect[alive_cells]; } return result; @@ -501,7 +818,6 @@ } else { - rb->splash( 1*HZ, "File Open Error"); setup_grid(pgrid, pattern++); /* fall back to stored patterns */ } } @@ -535,7 +851,8 @@ /* show new generation */ rb->yield(); show_grid(pgrid); - button = pluginlib_getaction(0, plugin_contexts, ARRAYLEN(plugin_contexts)); + button = pluginlib_getaction(0, plugin_contexts, + ARRAYLEN(plugin_contexts)); switch(button) { case ROCKLIFE_PLAY_PAUSE: case ROCKLIFE_QUIT: Index: apps/plugins/viewers.config =================================================================== --- apps/plugins/viewers.config (revision 28308) +++ apps/plugins/viewers.config (working copy) @@ -59,6 +59,10 @@ colours,apps/text_editor,11 ssg,games/superdom,- cells,games/rocklife,- +l,games/rocklife,- +rle,games/rocklife,- +lif,games/rocklife,- +life,games/rocklife,- link,viewers/shortcuts_view,- *,viewers/shortcuts_append,- *,apps/md5sum,-