chainreaction/game.cpp

84 lines
2.1 KiB
C++

#include <cassert>
#include <iostream>
#include "game.hpp"
using namespace game;
using namespace game::data;
Boards game::logic::play(Board& b, const Coordinate& c, const Player p)
{
auto& square = Board::square(b, c);
Boards state_transitions;
if (square.owner != Player::NONE && p != square.owner)
throw error::invalid_move();
square.owner = p;
square.value++;
if (square.value > logic::square_capacity(b, c))
state_transitions = spread(b, c);
return state_transitions;
}
Boards game::logic::spread(data::Board& b, const data::Coordinate& c)
{
Boards state_transitions;
data::Player owner = Board::square(b, c).owner;
if (logic::winner(b) == data::Player::NONE)
{
state_transitions.push_back(b);
data::Square::reset(Board::square(b, c));
state_transitions.push_back(b);
for (data::Coordinate neighboors[4] {
{c.x, c.y + 1},
{c.x + 1, c.y},
{c.x, c.y - 1},
{c.x - 1, c.y}
}; const data::Coordinate& c : neighboors)
{
if (c.x >= 0 && c.y >= 0 && c.x < b.width && c.y < b.height)
{
Board::square(b, c).value++;
Board::square(b, c).owner = owner;
state_transitions.push_back(b);
if (Board::square(b, c).value > square_capacity(b, c))
{
auto transitions = spread(b, c);
state_transitions.insert(std::end(state_transitions),
std::cbegin(transitions),
std::cend(transitions));
}
}
}
}
return state_transitions;
}
Player game::logic::winner(const Board& b) noexcept
{
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;
}