Back to shtanton's homepage
summaryrefslogtreecommitdiff
path: root/src/tick.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tick.c')
-rw-r--r--src/tick.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/src/tick.c b/src/tick.c
new file mode 100644
index 0000000..8b8f731
--- /dev/null
+++ b/src/tick.c
@@ -0,0 +1,335 @@
+#include "all.c"
+
+static int isRed(int cell) {
+ return (
+ cell == RED ||
+ cell == RED_LEFT ||
+ cell == RED_RIGHT ||
+ cell == RED_UP ||
+ cell == RED_DOWN
+ );
+}
+
+static int isBlue(int cell) {
+ return (
+ cell == BLUE ||
+ cell == BLUE_LEFT ||
+ cell == BLUE_RIGHT ||
+ cell == BLUE_UP ||
+ cell == BLUE_DOWN
+ );
+}
+
+static void tick(Game *game, Arena a) {
+ State *lastState = new(&a, 1, State);
+ xmemcpy(lastState, game, sizeof(State));
+
+ for (int x = 0; x < GRIDWIDTH; x++) {
+ for (int y = 0; y < GRIDHEIGHT; y++) {
+ switch (lastState->grid[x + y * GRIDWIDTH]) {
+ int reds, red;
+ int blues, blue;
+ case BLACK:
+ reds = 0;
+ if (
+ x < GRIDWIDTH - 1 && (
+ lastState->grid[x + 1 + y * GRIDWIDTH] == RED_LEFT ||
+ lastState->grid[x + 1 + y * GRIDWIDTH] == RED
+ )
+ ) {
+ reds++;
+ if (
+ x < GRIDWIDTH - 2 &&
+ y > 0 &&
+ y < GRIDHEIGHT - 1 &&
+ lastState->grid[x + 2 + y * GRIDWIDTH] == YELLOW &&
+ lastState->grid[x + 1 + (y - 1) * GRIDWIDTH] == YELLOW &&
+ lastState->grid[x + 1 + (y + 1) * GRIDWIDTH] == YELLOW
+ ) {
+ red = RED_LEFT;
+ } else {
+ red = lastState->grid[x + 1 + y * GRIDWIDTH];
+ }
+ }
+
+ if (
+ x > 0 && (
+ lastState->grid[x - 1 + y * GRIDWIDTH] == RED_RIGHT ||
+ lastState->grid[x - 1 + y * GRIDWIDTH] == RED
+ )
+ ) {
+ reds++;
+ if (
+ x > 1 &&
+ y > 0 &&
+ y < GRIDHEIGHT - 1 &&
+ lastState->grid[x - 2 + y * GRIDWIDTH] == YELLOW &&
+ lastState->grid[x - 1 + (y - 1) * GRIDWIDTH] == YELLOW &&
+ lastState->grid[x - 1 + (y + 1) * GRIDWIDTH] == YELLOW
+ ) {
+ red = RED_RIGHT;
+ } else {
+ red = lastState->grid[x - 1 + y * GRIDWIDTH];
+ }
+ }
+
+ if (
+ y > 0 && (
+ lastState->grid[x + (y - 1) * GRIDWIDTH] == RED_DOWN ||
+ lastState->grid[x + (y - 1) * GRIDWIDTH] == RED
+ )
+ ) {
+ reds++;
+ if (
+ x > 0 &&
+ x < GRIDWIDTH - 1 &&
+ y > 1 &&
+ lastState->grid[x + (y - 2) * GRIDWIDTH] == YELLOW &&
+ lastState->grid[x - 1 + (y - 1) * GRIDWIDTH] == YELLOW &&
+ lastState->grid[x + 1 + (y - 1) * GRIDWIDTH] == YELLOW
+ ) {
+ red = RED_DOWN;
+ } else {
+ red = lastState->grid[x + (y - 1) * GRIDWIDTH];
+ }
+ }
+
+ if (
+ y < GRIDHEIGHT - 1 && (
+ lastState->grid[x + (y + 1) * GRIDWIDTH] == RED_UP ||
+ lastState->grid[x + (y + 1) * GRIDWIDTH] == RED
+ )
+ ) {
+ reds++;
+ if (
+ x > 0 &&
+ x < GRIDWIDTH - 1 &&
+ y < GRIDHEIGHT - 2 &&
+ lastState->grid[x + (y + 2) * GRIDWIDTH] == YELLOW &&
+ lastState->grid[x - 1 + (y + 1) * GRIDWIDTH] == YELLOW &&
+ lastState->grid[x + 1 + (y + 1) * GRIDWIDTH] == YELLOW
+ ) {
+ red = RED_UP;
+ } else {
+ red = lastState->grid[x + (y + 1) * GRIDWIDTH];
+ }
+ }
+
+ if (reds == 1) {
+ game->state.grid[x + y * GRIDWIDTH] = red;
+ } else if (reds >= 2) {
+ game->state.grid[x + y * GRIDWIDTH] = RED;
+ }
+ break;
+ case RED:
+ game->state.grid[x + y * GRIDWIDTH] = YELLOW;
+ break;
+ case RED_LEFT:
+ if (
+ x > 0 &&
+ lastState->grid[x - 1 + y * GRIDWIDTH] == BLACK
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = YELLOW;
+ } else {
+ game->state.grid[x + y * GRIDWIDTH] = RED_UP;
+ }
+ break;
+ case RED_RIGHT:
+ if (
+ x < GRIDWIDTH - 1 &&
+ lastState->grid[x + 1 + y * GRIDWIDTH] == BLACK
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = YELLOW;
+ } else {
+ game->state.grid[x + y * GRIDWIDTH] = RED_DOWN;
+ }
+ break;
+ case RED_UP:
+ if (
+ y > 0 &&
+ lastState->grid[x + (y - 1) * GRIDWIDTH] == BLACK
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = YELLOW;
+ } else {
+ game->state.grid[x + y * GRIDWIDTH] = RED_RIGHT;
+ }
+ break;
+ case RED_DOWN:
+ if (
+ y < GRIDHEIGHT - 1 &&
+ lastState->grid[x + (y + 1) * GRIDWIDTH] == BLACK
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = YELLOW;
+ } else {
+ game->state.grid[x + y * GRIDWIDTH] = RED_LEFT;
+ }
+ break;
+ case YELLOW:
+ if (
+ (x > 0 && lastState->grid[x - 1 + y * GRIDWIDTH] == BLUE_RIGHT) ||
+ (x < GRIDWIDTH - 1 && lastState->grid[x + 1 + y * GRIDWIDTH] == BLUE_LEFT) ||
+ (y > 0 && lastState->grid[x + (y - 1) * GRIDWIDTH] == BLUE_DOWN) ||
+ (y < GRIDHEIGHT - 1 && lastState->grid[x + (y + 1) * GRIDWIDTH] == BLUE_UP)
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = RED;
+ } else {
+ game->state.grid[x + y * GRIDWIDTH] = BLACK;
+ }
+ break;
+ case BLUE:
+ blues = 0;
+ if (
+ x > 0 && (
+ lastState->grid[x - 1 + y * GRIDWIDTH] == RED ||
+ lastState->grid[x - 1 + y * GRIDWIDTH] == RED_LEFT ||
+ lastState->grid[x - 1 + y * GRIDWIDTH] == RED_RIGHT ||
+ lastState->grid[x - 1 + y * GRIDWIDTH] == RED_DOWN ||
+ lastState->grid[x - 1 + y * GRIDWIDTH] == RED_UP
+ )
+ ) {
+ blues++;
+ blue = BLUE_RIGHT;
+ }
+ if (
+ x < GRIDWIDTH - 1 && (
+ lastState->grid[x + 1 + y * GRIDWIDTH] == RED ||
+ lastState->grid[x + 1 + y * GRIDWIDTH] == RED_LEFT ||
+ lastState->grid[x + 1 + y * GRIDWIDTH] == RED_RIGHT ||
+ lastState->grid[x + 1 + y * GRIDWIDTH] == RED_DOWN ||
+ lastState->grid[x + 1 + y * GRIDWIDTH] == RED_UP
+ )
+ ) {
+ blues++;
+ blue = BLUE_LEFT;
+ }
+ if (
+ y > 0 && (
+ lastState->grid[x + (y - 1) * GRIDWIDTH] == RED ||
+ lastState->grid[x + (y - 1) * GRIDWIDTH] == RED_LEFT ||
+ lastState->grid[x + (y - 1) * GRIDWIDTH] == RED_RIGHT ||
+ lastState->grid[x + (y - 1) * GRIDWIDTH] == RED_DOWN ||
+ lastState->grid[x + (y - 1) * GRIDWIDTH] == RED_UP
+ )
+ ) {
+ blues++;
+ blue = BLUE_DOWN;
+ }
+ if (
+ y < GRIDHEIGHT - 1 && (
+ lastState->grid[x + (y + 1) * GRIDWIDTH] == RED ||
+ lastState->grid[x + (y + 1) * GRIDWIDTH] == RED_LEFT ||
+ lastState->grid[x + (y + 1) * GRIDWIDTH] == RED_RIGHT ||
+ lastState->grid[x + (y + 1) * GRIDWIDTH] == RED_DOWN ||
+ lastState->grid[x + (y + 1) * GRIDWIDTH] == RED_UP
+ )
+ ) {
+ blues++;
+ blue = BLUE_UP;
+ }
+ if (blues == 1) {
+ game->state.grid[x + y * GRIDWIDTH] = blue;
+ }
+ break;
+ case BLUE_LEFT:
+ if (
+ (x > 0 && isRed(lastState->grid[x - 1 + y * GRIDWIDTH])) ||
+ (x < GRIDWIDTH - 1 && isRed(lastState->grid[x + 1 + y * GRIDWIDTH])) ||
+ (y > 0 && isRed(lastState->grid[x + (y - 1) * GRIDWIDTH])) ||
+ (y < GRIDHEIGHT - 1 && isRed(lastState->grid[x + (y + 1) * GRIDWIDTH]))
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE;
+ } else if (
+ x > 0 &&
+ lastState->grid[x - 1 + y * GRIDWIDTH] == EMPTY
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = EMPTY;
+ } else {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE;
+ }
+ break;
+ case BLUE_RIGHT:
+ if (
+ (x > 0 && isRed(lastState->grid[x - 1 + y * GRIDWIDTH])) ||
+ (x < GRIDWIDTH - 1 && isRed(lastState->grid[x + 1 + y * GRIDWIDTH])) ||
+ (y > 0 && isRed(lastState->grid[x + (y - 1) * GRIDWIDTH])) ||
+ (y < GRIDHEIGHT - 1 && isRed(lastState->grid[x + (y + 1) * GRIDWIDTH]))
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE;
+ } else if (
+ x < GRIDWIDTH - 1 &&
+ lastState->grid[x + 1 + y * GRIDWIDTH] == EMPTY
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = EMPTY;
+ } else {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE;
+ }
+ break;
+ case BLUE_UP:
+ if (
+ (x > 0 && isRed(lastState->grid[x - 1 + y * GRIDWIDTH])) ||
+ (x < GRIDWIDTH - 1 && isRed(lastState->grid[x + 1 + y * GRIDWIDTH])) ||
+ (y > 0 && isRed(lastState->grid[x + (y - 1) * GRIDWIDTH])) ||
+ (y < GRIDHEIGHT - 1 && isRed(lastState->grid[x + (y + 1) * GRIDWIDTH]))
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE;
+ } else if (
+ y > 0 &&
+ lastState->grid[x + (y - 1) * GRIDWIDTH] == EMPTY
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = EMPTY;
+ } else {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE;
+ }
+ break;
+ case BLUE_DOWN:
+ if (
+ (x > 0 && isRed(lastState->grid[x - 1 + y * GRIDWIDTH])) ||
+ (x < GRIDWIDTH - 1 && isRed(lastState->grid[x + 1 + y * GRIDWIDTH])) ||
+ (y > 0 && isRed(lastState->grid[x + (y - 1) * GRIDWIDTH])) ||
+ (y < GRIDHEIGHT - 1 && isRed(lastState->grid[x + (y + 1) * GRIDWIDTH]))
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE;
+ } else if (
+ y < GRIDHEIGHT - 1 &&
+ lastState->grid[x + (y + 1) * GRIDWIDTH] == EMPTY
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = EMPTY;
+ } else {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE;
+ }
+ break;
+ case EMPTY:
+ // TODO: same as multiple reds
+ if (
+ x > 0 &&
+ lastState->grid[x - 1 + y * GRIDWIDTH] == BLUE_RIGHT
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE_RIGHT;
+ }
+ if (
+ x < GRIDWIDTH - 1 &&
+ lastState->grid[x + 1 + y * GRIDWIDTH] == BLUE_LEFT
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE_LEFT;
+ }
+ if (
+ y > 0 &&
+ lastState->grid[x + (y - 1) * GRIDWIDTH] == BLUE_DOWN
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE_DOWN;
+ }
+ if (
+ y < GRIDHEIGHT - 1 &&
+ lastState->grid[x + (y + 1) * GRIDWIDTH] == BLUE_UP
+ ) {
+ game->state.grid[x + y * GRIDWIDTH] = BLUE_UP;
+ }
+ break;
+ }
+ }
+ }
+
+ if (isBlue(game->state.grid[game->state.goalx + game->state.goaly * GRIDWIDTH])) {
+ // TODO: Win conditions
+ }
+}