chainreaction/game.cpp

78 lines
2.3 KiB
C++

#include "game.hpp"
using namespace game;
using namespace game::data;
auto game::logic::play(const Board& b, const Coordinate& c, const Player p) -> Boards
{
auto new_state(b);
auto& square = Board::square(new_state, c);
Boards states;
if (square.owner != Player::NONE && p != square.owner) throw error::invalid_move();
square.owner = p;
square.value++;
states = spread(new_state);
return states;
}
auto game::logic::spread(const data::Board& b) noexcept -> Boards
{
Boards states;
Board current = b;
int overflows;
do {
overflows = 0;
auto new_state = current;
for (auto y = 0; y < current.height; y++) {
for (auto x = 0; x < current.width; x++) {
auto sqr = Board::square(current, {x, y});
if (sqr.value > square_capacity(current, {x, y})) {
overflows++;
Square::reset(Board::square(new_state, {x, y}));
states.push_back(new_state);
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
for (data::Coordinate neighboors[4] {
{ x, y + 1},
{x + 1, y},
{ x, y - 1},
{x - 1, y}
};
const data::Coordinate& c : neighboors)
{
if (c.x >= 0 && c.y >= 0 && c.x < current.width
&& c.y < current.height) {
auto& adj_sqr = Board::square(new_state, c);
adj_sqr.value++;
adj_sqr.owner = sqr.owner;
}
}
}
}
}
states.push_back(new_state);
current = new_state;
} while (overflows > 0 && winner(current) == Player::NONE);
return states;
}
auto game::logic::winner(const Board& b) noexcept -> Player
{
auto winner {Player::NONE};
for (const auto& s : b.squares) {
if (winner == Player::NONE) {
if (s.owner != Player::NONE) {
winner = s.owner;
}
}
else if (s.owner != Player::NONE && winner != s.owner) {
return Player::NONE;
}
}
return winner;
}