From 81bf65f63c839e5b90f85dfcbbf80cc5ecbb520a Mon Sep 17 00:00:00 2001 From: girst Date: Mon, 3 Sep 2018 09:53:04 +0200 Subject: [PATCH] wrap-around-mode (needs cleanup) --- README.md | 6 +++--- schemes.h | 29 +++++++++++++++++++++++------ viiper.c | 39 ++++++++++++++++++++++++++++++++------- viiper.h | 1 + 4 files changed, 59 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 26881a3..0169c82 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,11 @@ game. This is what I'd recommend: - DONE ~~input out of whack when stopping (^Z) and resuming~~ - DONE ~~keybindings for restart, pause, redraw~~ - DONE ~~on dying: show end screen, allow restarting~~ - - DONE ~~score, increasing speed, ~~timer~~~~ + - DONE ~~score, increasing speed, ~~ - DONE ~~bonus/special items: slower snake, shorter snake, etc.~~ + - DONE ~~wall-wrap-around mode?~~ - TODO decaying points? (more points the faster you get the food) - - TODO wall-wrap-around mode? - - TODO fix all `grep -n TODO viiper.c` + - TODO fix all `grep -n 'TODO\|XXX\|\([^:]\|^\)//' *.[ch]` - TODO VT220 charset based on soft downloadable character set (->minesviiper) ## Notes diff --git a/schemes.h b/schemes.h index f4ef47c..94fb3d2 100644 --- a/schemes.h +++ b/schemes.h @@ -9,10 +9,13 @@ #define BORDER_S 3 #define BORDER_L 0 #define BORDER_R 2 -#define BORDER(v,h) op.sch->border[BORDER_ ## v][BORDER_ ## h] +//#define BORDER(v,h) op.sch->border[BORDER_ ## v][BORDER_ ## h] +#define BORDER(v,h) (g.b.a&&g.b.t==BONUS_WRAP?op.sch->permeable:op.sch->border) \ + [BORDER_ ## v][BORDER_ ## h] struct scheme { char* border[4][3]; + char* permeable[4][3]; /* for wrap-around mode */ char* snake[5][5]; /* [predecessor][successor] */ char* color[3]; /* 0=even, 1=odd, 2=head */ @@ -35,8 +38,15 @@ struct scheme unic0de = { {"╚", "══", "╝"}, { "╡","","╞" }, }, + .permeable = {//┅╍ + {"┏", "╍╍", "┓"}, + {"┋", " ", "┋"}, + {"┗", "╍╍", "┛"}, + { "┥","","┝" }, + }, .snake = { /* sorted like in the enum directions */ + /*NOTE: same-to-same direction is for wrap-around*/ {/* NONE -> */ /*NONE */ "", /*NORTH*/ "⢿⡿", @@ -45,28 +55,28 @@ struct scheme unic0de = { /*WEST */ "⣿⡷", },{/* NORTH -> */ /*NONE */ "⢇⡸", - /*NORTH*/ "", + /*NORTH*/ "⢇⠜", /*EAST */ "⢇⣈", /*SOUTH*/ "⡇⢸", /*WEST */ "⣁⡸", },{/* EAST -> */ /*NONE */ "⢎⣉", /*NORTH*/ "⢇⣈", - /*EAST */ "", + /*EAST */ "⠪⣉", /*SOUTH*/ "⡎⢉", /*WEST */ "⣉⣉", },{/* SOUTH -> */ /*NONE */ "⡎⢱", /*NORTH*/ "⡇⢸", /*EAST */ "⡎⢉", - /*SOUTH*/ "", + /*SOUTH*/ "⡔⢱", /*WEST */ "⡉⢱", },{/* WEST -> */ /*NONE */ "⣉⡱", /*NORTH*/ "⣁⡸", /*EAST */ "⣉⣉", /*SOUTH*/ "⡉⢱", - /*WEST */ "", + /*WEST */ "⣉⡢", }, }, .color = {"32", "92", "92;1"}, @@ -81,6 +91,7 @@ struct scheme unic0de = { [BONUS_GROW] = "🐍", [BONUS_SLOW] = "🐌", [BONUS_FAST] = "🐇", + [BONUS_WRAP] = "🧱", }, .cell_width = 2, @@ -94,6 +105,12 @@ struct scheme vt220_charset = { {"\033#6\x6d","\x71","\x6a"}, { "=","","=" }, }, + .permeable = {//TODO: ascii-colons? + {"\033#6\x6c","\x71","\x6b"}, + {"\033#6\x78"," ","\x78"}, + {"\033#6\x6d","\x71","\x6a"}, + { "=","","=" }, + }, .snake = { {"@","A",">","V","<"}, //head @@ -105,7 +122,7 @@ struct scheme vt220_charset = { .color = {"0", "0", "1"}, .food = { "$", "%", "&", }, - .boni = { "\033Nx", "\033N|", "\033Ns", "\033Nf", }, + .boni = { "\033Nx", "\033N|", "\033Ns", "\033Nf", "\033Nw", }, .init_seq = "\033(0\033*B\x0f" /* G0=Graphics, G2=ASCII, invoke G0 */ "\033[?3l", /* disable 132 column mode (DECCOLM) */ diff --git a/viiper.c b/viiper.c index fcfb9c8..5cebdcd 100644 --- a/viiper.c +++ b/viiper.c @@ -49,7 +49,7 @@ #define CW op.sch->cell_width #define SPEEDUP_AFTER 100 /* increment speed every n points */ -#define BONUS_INTERVAL 90 /* how often a bonus item is spawned */ +#define BONUS_INTERVAL .90 /* how often a bonus item is spawned */ #define BONUS_DURATION 15 /* how long one can catch the bonus */ #define BONUS_WARN 5 /* how long before the removal to warn */ @@ -60,9 +60,14 @@ struct game { int p; /* score */ float v; /* velocity in moves per second */ time_t t; /* time of game start */ - time_t b; /* time of next bonus item spawn */ struct snake* s; /* snek */ struct item* i; /* items (food, boni) */ + struct bonus { + int a; /* bonus action active? *///TODO: obsoleted by g.b.t + int t; /* bonus type (enum) *///TODO: bitmask (could be more than 1 active?) + time_t n; /* time of next bonus item spawn */ + time_t u; /* time until end of bonus */ + } b; /* bonus-related values */ struct directions { int h; /* write head */ int n; /* number of elements */ @@ -169,7 +174,8 @@ int viiper(void) { g.t = time(NULL); g.p = 0; g.k.n = 0; - g.b = time(NULL) + BONUS_INTERVAL; + g.b.n = time(NULL) + BONUS_INTERVAL; + g.b.a = 0; spawn_item(FOOD, rand() % NUM_FOODS, NULL); //TODO: shape distribution, so bigger values get selected less @@ -217,8 +223,15 @@ void snake_advance (void) { } } - if (new_row >= g.h || new_col >= g.w || new_row < 0 || new_col < 0) + if (g.b.a && g.b.t == BONUS_WRAP) { + if (new_row >= g.h) new_row = 0; + if (new_col >= g.w) new_col = 0; + if (new_row < 0) new_row = g.h-1; + if (new_col < 0) new_col = g.w-1; + } else { + if (new_row >= g.h || new_col >= g.w || new_row < 0 || new_col < 0) siglongjmp(game_over, GAME_OVER); + } struct snake* new_head; struct snake* new_tail; /* former second-to-last element */ @@ -236,6 +249,12 @@ void snake_advance (void) { g.s = new_head; + // bonus stuff: + if (g.b.a && g.b.u < time(NULL)) { + g.b.a = 0; //disable bonusaction if it expired + show_playfield();//redraw correct border (TODO: allgemeiner) + } + if (respawn) spawn_item(FOOD, rand() % NUM_FOODS, i); draw_sprites (old_tail[0], old_tail[1]); } @@ -307,6 +326,12 @@ void consume_item (struct item* i) { g.v++; timer_setup(1); break; + case BONUS_WRAP: + g.b.u = time(NULL)+30; + g.b.a = 1; + g.b.t = BONUS_WRAP; + show_playfield(); + break; } break; } @@ -327,9 +352,9 @@ void spawn_bonus(void) { } return; } - if (g.b < time(NULL)) { /* time to spawn item: */ + if (g.b.n < time(NULL)) { /* time to spawn item: */ spawn_item(BONUS, rand() % NUM_BONI, NULL); - g.b = time(NULL) + BONUS_INTERVAL; //TODO: only start counting after old bonus was removed/eaten + g.b.n = time(NULL) + BONUS_INTERVAL; //TODO: only start counting after old bonus was removed/eaten } } @@ -414,7 +439,7 @@ void pause_game (void) { /* update all timers, so bonus items don't get out of sync: */ pause_diff = time(NULL) - pause_start; - g.b += pause_diff; + g.b.n += pause_diff; for (struct item* i = g.i; i; i = i->next) i->s += pause_diff; diff --git a/viiper.h b/viiper.h index bbdbfa7..e4bc9f6 100644 --- a/viiper.h +++ b/viiper.h @@ -54,6 +54,7 @@ enum bonus_value { BONUS_GROW, BONUS_SLOW, BONUS_FAST, + BONUS_WRAP, NUM_BONI, }; enum game_state { -- 2.39.3