opengenerals/processor/logic/GameBoard.cpp
szdytom 4046abd656
add player info methods of GameBoard
Signed-off-by: szdytom <szdytom@qq.com>
2024-02-04 21:53:16 +08:00

118 lines
2.5 KiB
C++

#include "GameBoard.h"
#include <algorithm>
GameBoard::GameBoard(std::uint8_t n, std::uint8_t t, pos_t w, pos_t h
, const std::vector<Team> &player_team)
: n(n), t(t), w(w), h(h), players(n + 1)
{
for (std::uint8_t i = 1; i <= n; ++i) {
players[i].id = i;
players[i].team = player_team[i];
}
}
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);
}
}
}
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;
}
PlayerState::PlayerState() {
is_defeated = false;
}