summaryrefslogtreecommitdiffstats
path: root/src/snake.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/snake.cpp')
-rw-r--r--src/snake.cpp65
1 files changed, 59 insertions, 6 deletions
diff --git a/src/snake.cpp b/src/snake.cpp
index e855250..8d45dd9 100644
--- a/src/snake.cpp
+++ b/src/snake.cpp
@@ -22,11 +22,13 @@
#define CELL_BREAKOUT_BRICK 4
#define CELL_SNAKEBRICK 5
#define CELL_PADDLE 6
+#define CELL_GOL 7
#define AXIS_X 0
#define AXIS_Y 1
#define FIELD(x,y) _field[(x) + ((y) * _width)]
+#define FIELD2(x,y) _field2[(x) + ((y) * _width)]
struct Paddle;
@@ -38,15 +40,17 @@ struct Cell
Cell(int t, QColor c) : type(t), color(QBrush(c)), player(nullptr) {}
bool isFood() const { return type == CELL_FOOD; }
bool willKill() const { return type == CELL_PADDLE_BACKING | type == CELL_PADDLE || type == CELL_SNAKE || type == CELL_SNAKEBRICK; }
- bool isFree() const { return type == CELL_FREE; }
- bool isPaddleFree() const { return type == CELL_FREE || type == CELL_SNAKEBRICK || type == CELL_BREAKOUT_BRICK || type == CELL_FOOD; }
+ bool isFree() const { return type == CELL_FREE || type == CELL_GOL; }
+ bool isPaddleFree() const { return type == CELL_FREE || type == CELL_SNAKEBRICK || type == CELL_BREAKOUT_BRICK || type == CELL_FOOD || type == CELL_GOL; }
bool isBrick() const { return type == CELL_BREAKOUT_BRICK || type == CELL_SNAKEBRICK; }
- bool canSpawnFood() const { return type == CELL_SNAKE || type == CELL_FREE || type == CELL_BREAKOUT_BRICK; }
- bool ballWillDestroy() const { return isFood() || isBrick(); }
+ bool canSpawnFood() const { return type == CELL_SNAKE || type == CELL_FREE || type == CELL_BREAKOUT_BRICK || type == CELL_GOL; }
+ bool ballWillDestroy() const { return isFood() || isBrick() || type == CELL_GOL; }
+ bool isAlive() const { return type == CELL_FOOD || type == CELL_BREAKOUT_BRICK || type == CELL_GOL; }
};
static const Cell empty(CELL_FREE, QColor());
static const Cell snakebrick(CELL_SNAKEBRICK, QColor::fromRgb(200, 200, 200));
+static const Cell golBrick(CELL_GOL, QColor::fromRgb(180, 200, 220));
static Cell breakoutCenterBrick(CELL_BREAKOUT_BRICK, QColor::fromRgb(255, 255, 255));
static const Cell food[] = {
Cell(CELL_FOOD, QColor::fromRgb(0, 255, 0)),
@@ -133,6 +137,8 @@ public:
};
void GameCore::setField(int x, int y, const Cell *val) {
+ if (_field[x + _width * y] == val)
+ return;
_field[x + _width * y] = val;
_widget->update(x * SCALING, y * SCALING, SCALING, SCALING);
}
@@ -151,6 +157,7 @@ GameCore::GameCore(QWidget *widget)
return;
int cellCount = _width * _height;
_field = (const Cell**)calloc(cellCount, sizeof(*_field));
+ _field2 = (const Cell**)calloc(cellCount, sizeof(*_field));
for (int i = 0; i < cellCount; ++i) {
_field[i] = &empty;
}
@@ -462,7 +469,53 @@ GameCore::GameCore(QWidget *widget)
}
} // Done with movement logic
} // End loop over paddles
- }
+ } // End paddles
+ // Game of life
+ if (tick % 13 == 0) {
+ auto **tmp = _field;
+ _field = _field2;
+ _field2 = tmp;
+ memcpy(_field, _field2, _width * _height * sizeof(void*));
+ bool killall = ((tick / 4000) % 2);
+ int killed = 0;
+ for (int y = 0; y < _height; ++y) {
+ for (int x = 0; x < _width; ++x) {
+ if (FIELD2(x,y) != &golBrick && FIELD2(x,y) != &empty) {
+ FIELD(x,y) = FIELD2(x,y);
+ continue;
+ }
+ if (killall) {
+ if (FIELD2(x,y) == &golBrick) {
+ setField(x,y, &empty);
+ if (++killed > 5) {
+ goto endgol;
+ }
+ }
+ continue;
+ }
+ int alive = 0;
+ // Direct
+ if (x > 0 && FIELD2(x-1,y)->isAlive()) alive++;
+ if (y > 0 && FIELD2(x,y-1)->isAlive()) alive++;
+ if (x+1 < _width && FIELD2(x+1,y)->isAlive()) alive++;
+ if (y+1 < _height && FIELD2(x,y+1)->isAlive()) alive++;
+ // Diagonal
+ if (x > 0 && y > 0 && FIELD2(x-1,y-1)->isAlive()) alive++;
+ if (x > 0 && y+1 < _height && FIELD2(x-1,y+1)->isAlive()) alive++;
+ if (y > 0 && x+1 < _width && FIELD2(x+1,y-1)->isAlive()) alive++;
+ if (x+1 < _width && y+1 < _height && FIELD2(x+1,y+1)->isAlive()) alive++;
+ // Check
+ if (alive < 2 || alive > 3) {
+ setField(x,y, &empty);
+ } else if (alive == 3) {
+ setField(x,y, &golBrick);
+ } else {
+ FIELD(x,y) = FIELD2(x,y);
+ }
+ }
+ }
+endgol:;
+ } // End GOL
});
}
@@ -623,7 +676,7 @@ void GameCore::paint(QPaintEvent *event)
if (x < 0)
continue;
const Cell *c = FIELD(x, y);
- if (c->isFree())
+ if (c == &empty)
continue;
p.setBrush(c->color);
p.drawRect(x * SCALING, y * SCALING, SCALING-1, SCALING-1);