143 lines
3.1 KiB
C++
143 lines
3.1 KiB
C++
#include "GameBoard.h"
|
|
#include <algorithm>
|
|
|
|
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<TeamRanking> GameBoard::leaderboard() const {
|
|
std::vector<TeamRanking> res(t);
|
|
std::vector<PlayerRanking> prank(n);
|
|
for (Player i = 1; i <= n; ++i)
|
|
prank[i - 1].player = i;
|
|
|
|
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 (auto &p : prank) {
|
|
// res[teamOf(p.player) - 1]
|
|
// TODO
|
|
}
|
|
|
|
PlayerState::PlayerState() {
|
|
is_defeated = false;
|
|
}
|
|
|