diff options
Diffstat (limited to 'src/tick.c')
-rw-r--r-- | src/tick.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/src/tick.c b/src/tick.c new file mode 100644 index 0000000..338017b --- /dev/null +++ b/src/tick.c @@ -0,0 +1,376 @@ +#ifndef INCLUDE_TICK_C +#define INCLUDE_TICK_C + +#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)); + + if (lastState->spawnerCount > 0) { + game->state.spawnerCount = lastState->spawnerCount - 1; + } + + 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] = BLACK; // used to be RED + } else { + game->state.grid[x + y * GRIDWIDTH] = BLACK; + } + break; + case BLUE: + // Win condition + if (game->state.goalx == x && game->state.goaly == y) { + if (!game->state.need9) { + game->state.levelComplete = 1; + } else { + if (game->state.blues < 9) { + game->state.blues++; + if (game->state.blues == 9) { + game->state.levelComplete = 1; + } + } + } + game->state.grid[x + y * GRIDWIDTH] = EMPTY; + } + 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: + blues = 0; + if ( + x > 0 && + lastState->grid[x - 1 + y * GRIDWIDTH] == BLUE_RIGHT + ) { + blues++; + blue = BLUE_RIGHT; + } + if ( + x < GRIDWIDTH - 1 && + lastState->grid[x + 1 + y * GRIDWIDTH] == BLUE_LEFT + ) { + blues++; + blue = BLUE_LEFT; + } + if ( + y > 0 && + lastState->grid[x + (y - 1) * GRIDWIDTH] == BLUE_DOWN + ) { + blues++; + blue = BLUE_DOWN; + } + if ( + y < GRIDHEIGHT - 1 && + lastState->grid[x + (y + 1) * GRIDWIDTH] == BLUE_UP + ) { + blues++; + blue = BLUE_UP; + } + if (blues == 1) { + game->state.grid[x + y * GRIDWIDTH] = blue; + } else if (blues >= 2) { + game->state.grid[x + y * GRIDWIDTH] = BLUE; + } + + // Spawner + if ( + game->state.spawnerx != 0 && + game->state.spawnery != 0 && + game->state.grid[x + y * GRIDWIDTH] == EMPTY && + x == game->state.spawnerx && + y == game->state.spawnery && + lastState->spawnerCount == 0 + ) { + game->state.grid[x + y * GRIDWIDTH] = BLUE; + game->state.spawnerCount = levels[game->state.currentLevel].spawnRate; + } + break; + } + } + } +} + +#endif // INCLUDE_TICK_C |