#include "GameBoard.h" #include GameBoard::GameBoard(pos_t w, pos_t h, const InitInfo& info) : n(info.n), t(0), players(info.n + 1), w(w), h(h), board(w * h) { for (std::uint8_t i = 1; i <= n; ++i) { players[i].id = i; players[i].team = info.player_team[i]; t = std::max(t, players[i].team); } } Tile& GameBoard::at(pos_t x, pos_t y) { return board[x * w + y]; } const Tile& GameBoard::at(pos_t x, pos_t y) const { return board[x * w + y]; } bool GameBoard::attack(const PlayerMove& o) { if (!o.isValid(w, h)) return false; auto& sc_tile = at(o.x, o.y); auto& tt_tile = at(o.tx(), o.ty()); if (sc_tile.owner != o.player) return false; if (sc_tile.unit <= 1) return false; auto moving_unit = o.half ? sc_tile.unit : sc_tile.unit / 2; sc_tile.unit -= moving_unit; auto isfriend = isTeammate(o.player, tt_tile.owner); auto delta = isfriend ? moving_unit + tt_tile.unit : moving_unit - tt_tile.unit; updatedPosition(o.x, o.y); updatedPosition(o.ty(), o.ty()); tt_tile.unit = std::abs(delta); if (delta > 0 && (!isfriend || tt_tile.type != TileType::Capital)) { if (!isfriend && tt_tile.type == TileType::Capital) capitalCaptured(tt_tile.owner, o.player); tt_tile.owner = o.player; } return true; } void GameBoard::capitalCaptured(Player tt, Player sc) { for (pos_t x = 0; x < h; ++x) { for (pos_t y = 0; y < w; ++y) { auto& tile = at(x, y); if (tile.owner != tt || tile.type == TileType::Capital) continue; tile.owner = sc; tile.unit = std::max(tile.unit / 2, 1); updatedPosition(x, y); } } } bool GameBoard::isTeammate(Player x, Player y) const { return teamOf(x) == teamOf(y); } void GameBoard::turnUpdate() { for (pos_t x = 0; x < h; ++x) { for (pos_t y = 0; y < w; ++y) { auto& tile = at(x, y); if (tile.owner == neutral_player) continue; if (tile.type == TileType::Stronghold || tile.type == TileType::Capital) tile.unit += 1; if (tile.type == TileType::Swamp) { tile.unit -= 1; if (tile.unit == 0) tile.owner = neutral_player; } } } } void GameBoard::roundUpdate() { for (pos_t x = 0; x < h; ++x) { for (pos_t y = 0; y < w; ++y) { auto& tile = at(x, y); if (tile.owner == neutral_player) continue; tile.unit += 1; } } } void GameBoard::updatedPosition(pos_t x, pos_t y) { updated_tiles.emplace(x, y); } Team GameBoard::teamOf(Player x) const { return players[x].team; } std::uint8_t GameBoard::numPlayers() const { return n; } std::uint8_t GameBoard::numTeams() const { return t; } std::vector GameBoard::leaderboard() const { std::vector res(t); std::vector prank(n); for (Player i = 1; i <= n; ++i) prank[i - 1].player = i, prank[i - 1].is_defeated = defeated_players.find(i) != defeated_players.end(); for (Team i = 1; i <= t; ++i) res[i - 1].team = i; for (pos_t x = 0; x < h; ++x) { for (pos_t y = 0; y < w; ++y) { auto& tile = at(x, y); if (tile.owner == neutral_player) continue; prank[tile.owner - 1].land += 1; prank[tile.owner - 1].unit += tile.unit; } } for (const auto& p : prank) res[teamOf(p.player) - 1].players.push_back(p); for (auto& team : res) { for (const auto& p : team.players) { team.land += p.land; team.unit += p.unit; } sort(team.players.begin(), team.players.end(), [](const PlayerRanking& a, const PlayerRanking& b) { return a.unit != b.unit ? a.unit > b.unit : a.player < b.player; }); } sort(res.begin(), res.end(), [](const TeamRanking& a, const TeamRanking& b) { return a.unit != b.unit ? a.unit > b.unit : a.team < b.team; }); return res; } PlayerState::PlayerState() { is_defeated = false; }