Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of spy action #292

Merged
merged 10 commits into from
Jun 1, 2020
4 changes: 4 additions & 0 deletions src/datatypes/gameplay/State.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,8 @@ namespace spy::gameplay {
Stats &State::getFactionStats() {
return factionStats;
}

void State::addSafeCombination(unsigned int safe) {
mySafeCombinations.insert(safe);
}
}
4 changes: 3 additions & 1 deletion src/datatypes/gameplay/State.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

namespace spy::gameplay {

struct Stats{
struct Stats {
character::FactionEnum collarToCat = character::FactionEnum::INVALID;
std::pair<unsigned int, unsigned int> cocktails;
std::pair<unsigned int, unsigned int> cocktailsPoured;
Expand Down Expand Up @@ -74,6 +74,8 @@ namespace spy::gameplay {
*/
void setJanitorCoordinates(const std::optional<util::Point> &janitorCoordinates);

void addSafeCombination(unsigned int safe);

friend void to_json(nlohmann::json &j, const State &s);

friend void from_json(const nlohmann::json &j, State &s);
Expand Down
105 changes: 100 additions & 5 deletions src/gameLogic/execution/ActionExecutor_Spy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,112 @@
// Created by jonas on 28.04.20.
//
#include "ActionExecutor.hpp"
#include <util/GameLogicUtils.hpp>

namespace spy::gameplay {

static std::shared_ptr<const BaseOperation>
handleSpyOnPerson(State &s, const SpyAction &op, const MatchConfig &config,
ottojo marked this conversation as resolved.
Show resolved Hide resolved
character::CharacterSet::iterator character, character::CharacterSet::const_iterator targetChar) {
auto retOp = std::make_shared<SpyAction>(op);

if (targetChar->getFaction() != character::FactionEnum::NEUTRAL) {
retOp->setSuccessful(false);
return retOp;
}

bool success = util::GameLogicUtils::probabilityTestWithCharacter(*character,
config.getSpySuccessChance());
retOp->setSuccessful(success);
if (!success) {
return retOp;
}

if (util::GameLogicUtils::probabilityTest(0.5)) {
// character gets a secret
unsigned int maxSafeIndex = 1;

s.getMap().forAllFields([&maxSafeIndex](const scenario::Field &f) {
if (f.getFieldState() == scenario::FieldStateEnum::SAFE
&& f.getSafeIndex().value() > maxSafeIndex) {
maxSafeIndex = f.getSafeIndex().value();
}
});

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<unsigned int> randPos(1, maxSafeIndex);

auto secret = randPos(gen);

if (s.getMySafeCombinations().find(secret) != s.getMySafeCombinations().end()) {
s.addSafeCombination(secret);
character->addIntelligencePoints(static_cast<int>(config.getSecretToIpFactor()));
}
}

return retOp;
}

static std::shared_ptr<const BaseOperation>
handleSpyOnSafe(State &s, const SpyAction &op, const MatchConfig &config,
character::CharacterSet::iterator character) {
auto retOp = std::make_shared<SpyAction>(op);

retOp->setSuccessful(true);

// get index of safe
auto safeIndex = s.getMap().getField(op.getTarget()).getSafeIndex().value();

// query safe indexes and the collar location from the current state
unsigned int maxSafeIndex = 1;
bool collarOnMap = false;

s.getMap().forAllFields([&maxSafeIndex, &collarOnMap](const scenario::Field &f) {
if (f.getFieldState() == scenario::FieldStateEnum::SAFE
&& f.getSafeIndex().value() > maxSafeIndex) {
maxSafeIndex = f.getSafeIndex().value();
} else if (f.getGadget().has_value()
&& f.getGadget().value()->getType() == gadget::GadgetEnum::DIAMOND_COLLAR) {
ottojo marked this conversation as resolved.
Show resolved Hide resolved
collarOnMap = true;
}
});

if (!collarOnMap) {
for (const auto &c : s.getCharacters()) {
if (c.hasGadget(gadget::GadgetEnum::DIAMOND_COLLAR)) {
collarOnMap = true;
break;
}
}
}

if (safeIndex == maxSafeIndex && !collarOnMap) {
// first character gets the diamond collar
character->addGadget(std::make_shared<gadget::Gadget>(gadget::GadgetEnum::DIAMOND_COLLAR));
character->addIntelligencePoints(static_cast<int>(config.getSecretToIpFactor()));
} else if (safeIndex < maxSafeIndex) {
if (s.getMySafeCombinations().find(safeIndex) != s.getMySafeCombinations().end()) {
// faction gets the key for the next safe
s.addSafeCombination(safeIndex + 1);
character->addIntelligencePoints(static_cast<int>(config.getSecretToIpFactor()));
}
}

return retOp;
}

std::shared_ptr<const BaseOperation>
ActionExecutor::executeSpy(State &s, const SpyAction &op, const MatchConfig &/*config*/) {
ActionExecutor::executeSpy(State &s, const SpyAction &op, const MatchConfig &config) {
auto character = s.getCharacters().getByUUID(op.getCharacterId());
character->subActionPoint();
// TODO: implement

auto retOp = std::make_shared<SpyAction>(op);
retOp->setSuccessful(false);
auto targetChar = util::GameLogicUtils::findInCharacterSetByCoordinates(s.getCharacters(), op.getTarget());

return retOp;
if (targetChar != s.getCharacters().end()) {
return handleSpyOnPerson(s, op, config, character, targetChar);
} else {
return handleSpyOnSafe(s, op, config, character);
}
}
}