-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimulator.cpp
More file actions
101 lines (83 loc) · 2.85 KB
/
Copy pathsimulator.cpp
File metadata and controls
101 lines (83 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "simulator.h"
#include <cassert>
#include <numeric>
Simulator::Simulator(const std::atomic<bool> &runningAllowed, std::vector<Character> chars, std::unique_ptr<DiceRoller>&& roller)
: result(true)
, roundCount(0)
, runningAllowed(runningAllowed)
, dice(std::move(roller))
, characters(std::move(chars))
, alive(characters.begin(), characters.end())
{
guys = std::accumulate(alive.cbegin(), alive.cend(), std::pair<int, int>(0, 0), [](std::pair<int, int> guys, const Character &ch) {
if (ch.isGood()) {
++guys.first;
} else {
++guys.second;
}
return guys;
});
}
bool Simulator::pickTarget(Character &ch)
{
// TODO: Don't walk to close target
if (ch.currentAttackingWeapon() != Character::AttackingWeapon::Ranged && !ch.walk()) {
return false;
}
// randomly pick target
int targetIdx = dice->roll(ch.isGood() ? guys.second : guys.first);
const auto it = std::find_if_not(alive.cbegin(), alive.cend(), [&](const Character &target) {
return ch.isGood() == target.isGood() || --targetIdx;
});
assert(it != alive.cend());
ch.target = std::addressof(it->get());
return true;
}
bool Simulator::simulate()
{
// sort by initative
std::sort(alive.begin(), alive.end(), [](const Character &first, const Character &second) { return first.initative() < second.initative(); });
while (guys.first > 0 && guys.second > 0) {
// runningAllowed will be changed from the other thread so we cannot check it at the end of function
if (!runningAllowed) {
result = guys.first > 0;
return false;
}
++roundCount;
for (Character &ch : alive) {
ch.newTurn();
}
for (Character &ch : alive) {
if ((!ch.target || !ch.target->isAlive()) && !pickTarget(ch)) {
continue;
}
assert(ch.target);
if (!ch.loadWeapon()) {
continue;
}
if (ch.numberOfAttacks() == 1 && ch.remainingActions() > 1) {
ch.focusAttack();
}
// we have a target lets hit it
if (ch.attack(*dice)) {
if (!ch.target->isAlive()) {
if (ch.target->isGood()) {
--guys.first;
} else {
--guys.second;
}
}
if (guys.first <= 0 || guys.second <= 0) {
break;
}
if (!ch.target->isAlive()) {
pickTarget(ch);
}
ch.loadWeapon();
}
}
std::remove_if(alive.begin(), alive.end(), [](const Character &ch) { return !ch.isAlive(); });
}
result = guys.first > 0;
return true;
}