Skip to content

Commit

Permalink
fix: integrate with abilities
Browse files Browse the repository at this point in the history
  • Loading branch information
shubham-1806 committed Feb 10, 2024
1 parent bd99370 commit c31e3fe
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 55 deletions.
2 changes: 1 addition & 1 deletion src/attacker/attacker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void Attacker::check_ability(size_t turn) {
this->get_num_ability_turns();
}

bool Attacker::is_ability_active() { return this->_is_ability_active; }
bool Attacker::is_ability_active() const { return this->_is_ability_active; }

unsigned Attacker::get_ability_activation_cost() {
return this->attribute_dictionary[this->_type].ability_activation_cost;
Expand Down
2 changes: 1 addition & 1 deletion src/attacker/attacker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Attacker : public Actor {
[[nodiscard]] State get_state() const;

void activate_ability(size_t turn);
bool is_ability_active();
bool is_ability_active() const;
void check_ability(size_t turn);

unsigned get_ability_activation_cost();
Expand Down
2 changes: 1 addition & 1 deletion src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Game Game::simulate(
prev_state_attackers.end());
std::vector<Defender> defenders(prev_state_defenders.begin(),
prev_state_defenders.end());
ranges::for_each(attackers, [&](Attacker &attacker) {
ranges::for_each(attackers, [turn](Attacker &attacker) {
attacker.clear_destination();
attacker.check_ability(turn);
});
Expand Down
2 changes: 1 addition & 1 deletion src/game/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Game {
[[nodiscard]] const std::vector<Defender> &get_defenders() const;

[[nodiscard]] Game simulate(
const Game::turn_t turn,
const turn_t turn,
const std::unordered_map<attacker_id, defender_id> &player_set_targets,
const std::vector<std::pair<Position, AttackerType>> &spawn_positions,
const std::vector<attacker_id> &ability_activations);
Expand Down
59 changes: 54 additions & 5 deletions src/game/pvpgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,18 @@ PvPGame::PvPGame(std::vector<PvPAttacker> player_1_attackers,
}

PvPGame PvPGame::simulate(
const turn_t turn,
const std::unordered_map<player_1_attacker_id, player_2_attacker_id>
&player_1_set_targets,
const std::vector<std::pair<Position, AttackerType>>
&player_1_spawn_positions,
const std::unordered_map<player_2_attacker_id, player_1_attacker_id>
&player_2_set_targets,
const std::vector<std::pair<Position, AttackerType>>
&player_2_spawn_positions) const {
&player_2_spawn_positions,
const std::vector<player_1_attacker_id> &player_1_ability_activations,
const std::vector<player_2_attacker_id> &player_2_ability_activations)
const {

const auto &prev_state_player_1_attackers = this->get_player_1_attackers();
const auto &prev_state_player_2_attackers = this->get_player_2_attackers();
Expand All @@ -46,14 +50,19 @@ PvPGame PvPGame::simulate(
prev_state_player_2_attackers.begin(),
prev_state_player_2_attackers.end());

std::ranges::for_each(player_1_attackers, [](PvPAttacker &attacker) {
std::ranges::for_each(player_1_attackers, [turn](PvPAttacker &attacker) {
attacker.clear_destination();
attacker.check_ability(turn);
});

std::ranges::for_each(player_2_attackers, [](PvPAttacker &attacker) {
std::ranges::for_each(player_2_attackers, [turn](PvPAttacker &attacker) {
attacker.clear_destination();
attacker.check_ability(turn);
});

unsigned player_1_coins = PvPGame::FIXED_COINS_PER_TURN;
unsigned player_2_coins = PvPGame::FIXED_COINS_PER_TURN;

std::ranges::for_each(
player_1_set_targets,
[&](const std::pair<player_1_attacker_id, player_2_attacker_id> &entry) {
Expand Down Expand Up @@ -82,6 +91,48 @@ PvPGame PvPGame::simulate(
}
});

std::ranges::for_each(
player_1_ability_activations, [&](player_1_attacker_id id) {
auto player_1_attacker_index =
this->get_player_1_attacker_index_by_id(id);
unsigned ability_activation_cost =
player_1_attackers[*player_1_attacker_index]
.get_ability_activation_cost();

if (player_1_coins < ability_activation_cost) {
return;
}
player_1_coins -= ability_activation_cost;
// In case the ability is already active,
// the user would have paid the cost but the ability would not be
// activated This is the penalty for trying to activate an already
// active ability.
if (player_1_attacker_index.has_value()) {
player_1_attackers[*player_1_attacker_index].activate_ability(turn);
}
});

std::ranges::for_each(
player_2_ability_activations, [&](player_2_attacker_id id) {
auto player_2_attacker_index =
this->get_player_2_attacker_index_by_id(id);
unsigned ability_activation_cost =
player_2_attackers[*player_2_attacker_index]
.get_ability_activation_cost();

if (player_2_coins < ability_activation_cost) {
return;
}
player_2_coins -= ability_activation_cost;
// In case the ability is already active,
// the user would have paid the cost but the ability would not be
// activated This is the penalty for trying to activate an already
// active ability.
if (player_2_attacker_index.has_value()) {
player_2_attackers[*player_2_attacker_index].activate_ability(turn);
}
});

std::ranges::for_each(player_1_attackers, [&](PvPAttacker &attacker) mutable {
std::optional<index_t> player_2_attacker_index{std::nullopt};
if (attacker.is_target_set_by_player() &&
Expand Down Expand Up @@ -173,8 +224,6 @@ PvPGame PvPGame::simulate(

auto player_1_positions = std::set<Position>{};
auto player_2_positions = std::set<Position>{};
unsigned player_1_coins = PvPGame::FIXED_COINS_PER_TURN;
unsigned player_2_coins = PvPGame::FIXED_COINS_PER_TURN;

std::ranges::for_each(
player_1_spawn_positions, [&](const auto &spawn_details) {
Expand Down
23 changes: 14 additions & 9 deletions src/game/pvpgame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,27 @@ class PvPGame {
using player_1_attacker_id = size_t;
using player_2_attacker_id = size_t;
using index_t = size_t;
using turn_t = size_t;

static inline unsigned int FIXED_COINS_PER_TURN;

[[nodiscard]] const std::vector<PvPAttacker> &get_player_1_attackers() const;

[[nodiscard]] const std::vector<PvPAttacker> &get_player_2_attackers() const;

[[nodiscard]] PvPGame
simulate(const std::unordered_map<player_1_attacker_id, player_2_attacker_id>
&player_1_set_targets,
const std::vector<std::pair<Position, AttackerType>>
&player_1_spawn_positions,
const std::unordered_map<player_2_attacker_id, player_1_attacker_id>
&player_2_set_targets,
const std::vector<std::pair<Position, AttackerType>>
&player_2_spawn_positions) const;
[[nodiscard]] PvPGame simulate(
const turn_t turn,
const std::unordered_map<player_1_attacker_id, player_2_attacker_id>
&player_1_set_targets,
const std::vector<std::pair<Position, AttackerType>>
&player_1_spawn_positions,
const std::unordered_map<player_2_attacker_id, player_1_attacker_id>
&player_2_set_targets,
const std::vector<std::pair<Position, AttackerType>>
&player_2_spawn_positions,
const std::vector<player_1_attacker_id> &player_1_ability_activations,
const std::vector<player_2_attacker_id> &player_2_ability_activations)
const;

private:
std::optional<index_t>
Expand Down
58 changes: 41 additions & 17 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
#include "utils/game_type.hpp"

#include <algorithm>
#include <cassert>
#include <filesystem>
#include <fstream>
#include <cassert>
#include <iostream>
#include <numeric>

Expand All @@ -25,7 +25,8 @@ void NormalGame() {
for (unsigned attacker_type_id = 1; attacker_type_id <= n_attacker_types;
++attacker_type_id) {
// for normal game weight is not required so we just input and ignore it
unsigned hp, range, attack_power, speed, price, weight, num_ability_turns, ability_activation_cost;
unsigned hp, range, attack_power, speed, price, weight, num_ability_turns,
ability_activation_cost;
bool is_aerial;
std::cin >> hp >> range >> attack_power >> speed >> price >> is_aerial >>
weight >> num_ability_turns >> ability_activation_cost;
Expand All @@ -39,15 +40,12 @@ void NormalGame() {
std::cin >> n_defender_types;
for (unsigned defender_type_id = 1; defender_type_id <= n_defender_types;
++defender_type_id) {
unsigned hp, range, attack_power, speed, price, num_ability_turns,
ability_activation_cost;
unsigned hp, range, attack_power, speed, price;
bool is_aerial;
std::cin >> hp >> range >> attack_power >> speed >> price >> is_aerial >>
num_ability_turns >> ability_activation_cost;
std::cin >> hp >> range >> attack_power >> speed >> price >> is_aerial;
Defender::attribute_dictionary.insert(std::make_pair(
DefenderType(defender_type_id),
Attributes(hp, range, attack_power, speed, price, is_aerial,
num_ability_turns, ability_activation_cost)));
Attributes(hp, range, attack_power, speed, price, is_aerial, 0, 0)));
}

auto map = Map::get(std::cin);
Expand Down Expand Up @@ -109,7 +107,8 @@ void NormalGame() {
std::ranges::for_each(active_attackers, [](const Attacker &attacker) {
std::cout << attacker.get_id() << " " << attacker.get_position().get_x()
<< " " << attacker.get_position().get_y() << " "
<< (int)attacker.get_type() << " " << attacker.get_hp() << "\n";
<< (int)attacker.get_type() << " " << attacker.get_hp() << " "
<< (int)attacker.is_ability_active() << "\n";
});

auto active_defenders = game.get_defenders();
Expand Down Expand Up @@ -151,7 +150,8 @@ void PVPGame(std::string p1_in, std::string p1_out, std::string p2_in,
std::cin >> n_attacker_types;
for (unsigned attacker_type_id = 1; attacker_type_id <= n_attacker_types;
++attacker_type_id) {
unsigned hp, range, attack_power, speed, price, weight, num_ability_turns, ability_activation_cost;
unsigned hp, range, attack_power, speed, price, weight, num_ability_turns,
ability_activation_cost;
bool is_aerial;
std::cin >> hp >> range >> attack_power >> speed >> price >> is_aerial >>
weight >> num_ability_turns >> ability_activation_cost;
Expand All @@ -172,7 +172,7 @@ void PVPGame(std::string p1_in, std::string p1_out, std::string p2_in,
std::cin >> hp >> range >> attack_power >> speed >> price >> is_aerial;
Defender::attribute_dictionary.insert(std::make_pair(
DefenderType(defender_type_id),
Attributes(hp, range, attack_power, speed, price, is_aerial,0,0)));
Attributes(hp, range, attack_power, speed, price, is_aerial, 0, 0)));
}

PvPLogger::log_init();
Expand Down Expand Up @@ -231,8 +231,28 @@ void PVPGame(std::string p1_in, std::string p1_out, std::string p2_in,
player_2_set_targets[att_id] = def_id;
}

game = game.simulate(player_1_set_targets, player_1_spawn_positions,
player_2_set_targets, player_2_spawn_positions);
int no_of_player_1_ability_activations = 0;
player1_stream.get() >> no_of_player_1_ability_activations;
std::vector<PvPGame::player_1_attacker_id> player_1_ability_activations;
while ((no_of_player_1_ability_activations--) > 0) {
PvPGame::player_1_attacker_id att_id = 0;
player1_stream.get() >> att_id;
player_1_ability_activations.push_back(att_id);
}

int no_of_player_2_ability_activations = 0;
player2_stream.get() >> no_of_player_2_ability_activations;
std::vector<PvPGame::player_2_attacker_id> player_2_ability_activations;
while ((no_of_player_2_ability_activations--) > 0) {
PvPGame::player_2_attacker_id att_id = 0;
player2_stream.get() >> att_id;
player_2_ability_activations.push_back(att_id);
}

game = game.simulate(turn, player_1_set_targets, player_1_spawn_positions,
player_2_set_targets, player_2_spawn_positions,
player_1_ability_activations,
player_2_ability_activations);

auto player1_active_attackers = game.get_player_1_attackers();
player1_stream.put() << player1_active_attackers.size() << "\n";
Expand All @@ -242,7 +262,8 @@ void PVPGame(std::string p1_in, std::string p1_out, std::string p2_in,
player1_stream.put()
<< attacker.get_id() << " " << attacker.get_position().get_x()
<< " " << attacker.get_position().get_y() << " "
<< (int)attacker.get_type() << " " << attacker.get_hp() << "\n";
<< (int)attacker.get_type() << " " << attacker.get_hp() << " "
<< (int)attacker.is_ability_active() << "\n";
player1_stream.put().flush();
});

Expand All @@ -256,7 +277,8 @@ void PVPGame(std::string p1_in, std::string p1_out, std::string p2_in,
player1_stream.put()
<< attacker.get_id() << " " << attacker.get_position().get_x()
<< " " << attacker.get_position().get_y() << " "
<< (int)attacker.get_type() << " " << attacker.get_hp() << "\n";
<< (int)attacker.get_type() << " " << attacker.get_hp() << " "
<< (int)attacker.is_ability_active() << "\n";
player1_stream.put().flush();
});
player1_stream.put().flush();
Expand All @@ -267,7 +289,8 @@ void PVPGame(std::string p1_in, std::string p1_out, std::string p2_in,
player2_stream.put()
<< attacker.get_id() << " " << attacker.get_position().get_x()
<< " " << attacker.get_position().get_y() << " "
<< (int)attacker.get_type() << " " << attacker.get_hp() << "\n";
<< (int)attacker.get_type() << " " << attacker.get_hp() << " "
<< (int)attacker.is_ability_active() << "\n";
player2_stream.put().flush();
});

Expand All @@ -279,7 +302,8 @@ void PVPGame(std::string p1_in, std::string p1_out, std::string p2_in,
player2_stream.put()
<< attacker.get_id() << " " << attacker.get_position().get_x()
<< " " << attacker.get_position().get_y() << " "
<< (int)attacker.get_type() << " " << attacker.get_hp() << "\n";
<< (int)attacker.get_type() << " " << attacker.get_hp() << " "
<< (int)attacker.is_ability_active() << "\n";
player2_stream.put().flush();
});

Expand Down
12 changes: 6 additions & 6 deletions test/pvpattacker_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
SCENARIO("PvPAttacker::get_nearest_defender_index") {
GIVEN("a list of defenders") {
PvPAttacker::attribute_dictionary.clear();
PvPAttacker::attribute_dictionary.insert(
std::make_pair(AttackerType::A1, Attributes(0, 2, 0, 4, 0, false)));
PvPAttacker::attribute_dictionary.insert(
std::make_pair(AttackerType::A2, Attributes(0, 4, 0, 2, 0, false)));
PvPAttacker::attribute_dictionary.insert(
std::make_pair(AttackerType::A3, Attributes(0, 4, 0, 4, 0, true)));
PvPAttacker::attribute_dictionary.insert(std::make_pair(
AttackerType::A1, Attributes(0, 2, 0, 4, 0, false, 1, 1)));
PvPAttacker::attribute_dictionary.insert(std::make_pair(
AttackerType::A2, Attributes(0, 4, 0, 2, 0, false, 1, 1)));
PvPAttacker::attribute_dictionary.insert(std::make_pair(
AttackerType::A3, Attributes(0, 4, 0, 4, 0, true, 1, 1)));
std::vector<PvPAttacker> attackers{
PvPAttacker::construct(AttackerType::A1, {0, 1}, Owner::PLAYER1),
PvPAttacker::construct(AttackerType::A2, {0, 2}, Owner::PLAYER1),
Expand Down
Loading

0 comments on commit c31e3fe

Please sign in to comment.