-
-
Notifications
You must be signed in to change notification settings - Fork 113
/
Copy pathposition_matching.cpp
87 lines (76 loc) · 2.42 KB
/
position_matching.cpp
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
#include "position_matching.h"
#include "movement_type.h"
optional<Position> PositionMatching::getMatch(Position pos) const {
return matches.getValueMaybe(pos);
}
void PositionMatching::releaseTarget(Position pos) {
targets.erase(pos);
if (auto match = matches.getValueMaybe(pos)) {
removeMatch(pos);
findPath(*match);
}
}
void PositionMatching::addTarget(Position pos) {
targets.insert(pos);
findPath(pos);
}
static bool isOpen(Position pos) {
return pos.canEnterEmpty({MovementTrait::WALK});
}
void PositionMatching::updateMovement(Position pos) {
if (targets.count(pos))
releaseTarget(pos);
if (isOpen(pos))
findPath(pos);
else {
if (auto match = reverseMatches.getValueMaybe(pos)) {
removeMatch(pos);
findPath(*match);
}
}
}
void PositionMatching::removeMatch(Position pos) {
if (auto match = matches.getValueMaybe(pos)) {
reverseMatches.erase(*match);
matches.erase(pos);
//std::cout << "Removed match " << pos.getCoord() << " " << match->getCoord() << std::endl;
}
if (auto match = reverseMatches.getValueMaybe(pos)) {
matches.erase(*match);
reverseMatches.erase(pos);
//std::cout << "Removed match " << pos.getCoord() << " " << match->getCoord() << std::endl;
}
}
void PositionMatching::setMatch(Position pos1, Position pos2) {
if (!targets.count(pos1)) {
swap(pos1, pos2);
CHECK(targets.count(pos1));
}
removeMatch(pos1);
removeMatch(pos2);
matches.set(pos1, pos2);
reverseMatches.set(pos2, pos1);
//std::cout << "Added match " << pos1.getCoord() << " " << pos2.getCoord() << std::endl;
}
void PositionMatching::findPath(Position pos) {
PositionSet visited;
findPath(pos, visited, true);
}
bool PositionMatching::findPath(Position pos, PositionSet& visited, bool matchedWithFather) {
if (visited.count(pos))
return false;
visited.insert(pos);
bool isTarget = targets.count(pos);
auto match = isTarget ? matches.getValueMaybe(pos) : reverseMatches.getValueMaybe(pos);
if (matchedWithFather) {
for (auto candidate : pos.neighbors8())
if (((isTarget && isOpen(candidate)) || (!isTarget && targets.count(candidate))) &&
findPath(candidate, visited, false)) {
setMatch(pos, candidate);
return true;
}
return false;
} else
return (!match || findPath(*match, visited, true));
}
SERIALIZE_DEF(PositionMatching, SUBCLASS(OwnedObject<PositionMatching>), matches, reverseMatches, targets)