diff options
Diffstat (limited to 'src/tick.c')
-rw-r--r-- | src/tick.c | 335 |
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 + } +} |