-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathAgentState.cs
More file actions
204 lines (180 loc) · 6.73 KB
/
AgentState.cs
File metadata and controls
204 lines (180 loc) · 6.73 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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
using System;
using System.Collections.Generic;
namespace mapf;
[Serializable] public class AgentState : IComparable<IBinaryHeapItem>, IBinaryHeapItem
{
/// <summary>
/// Only used when AgentState objects are put in the open list priority queue - mainly in AStarForSingleAgent, I think.
/// </summary>
public int h;
public Agent agent;
/// <summary>
/// At goal
/// </summary>
public int arrivalTime;
/// <summary>
/// The last move's time is the agent's G
/// </summary>
public TimedMove lastMove;
private int binaryHeapIndex;
public int potentialConflicts;
public ushort potentialConflictsID;
/// <summary>
/// Only used by AStarForSingleAgent, which should itself be deleted.
/// </summary>
[NonSerialized] public AgentState prev;
/// <summary>
/// For CBS this must be set to false.
/// </summary>
public static bool EquivalenceOverDifferentTimes = true;
public AgentState(int pos_X, int pos_Y, Agent agent)
{
this.lastMove = new TimedMove(pos_X, pos_Y, Move.Direction.NO_DIRECTION, 0);
this.agent = agent;
}
public AgentState(int startX, int startY, int goalX, int goalY, int agentId)
: this(startX, startY, new Agent(goalX, goalY, agentId))
{}
public AgentState(AgentState copy)
{
this.agent = copy.agent;
this.h = copy.h;
this.arrivalTime = copy.arrivalTime;
this.lastMove = copy.lastMove; //new TimedMove(copy.lastMove); // Can we just do this.lastMove = copy.lastMove? I think we can now, since MoveTo replaces the move
//this.prev = copy;
this.g = copy.g;
}
/// <summary>
/// Only used by EnumeratedPDB - check if can be removed
/// </summary>
public void SwapCurrentWithGoal()
{
int nTemp = lastMove.x;
lastMove.x = agent.Goal.x;
agent.Goal.x = nTemp;
nTemp = lastMove.y;
lastMove.y = agent.Goal.y;
agent.Goal.y = nTemp;
}
/// <summary>
/// Updates the agent's last move with the given move and sets arrivalTime (at goal) if necessary.
/// </summary>
public void MoveTo(TimedMove move)
{
this.lastMove = move;
bool isWait = move.direction == Move.Direction.Wait;
bool atGoal = this.AtGoal();
// If performed a non WAIT move and reached the agent's goal - store the arrival time
if (atGoal && (isWait == false))
this.arrivalTime = move.time;
if (Constants.sumOfCostsVariant == Constants.SumOfCostsVariant.ORIG)
{
if (this.AtGoal())
this.g = this.arrivalTime;
else
this.g = this.lastMove.time;
}
else if (Constants.sumOfCostsVariant == Constants.SumOfCostsVariant.WAITING_AT_GOAL_ALWAYS_FREE)
{
if ((atGoal && isWait) == false)
this.g += 1;
}
}
/// <summary>
/// Checks if the agent is at its goal location
/// </summary>
/// <returns>True if the agent has reached its goal location</returns>
public bool AtGoal()
{
return this.agent.Goal.Equals(this.lastMove); // Comparing Move to TimedMove is allowed, the reverse isn't.
}
public int g;
/// <summary>
/// BH_Item implementation
/// </summary>
public int GetIndexInHeap() { return binaryHeapIndex; }
/// <summary>
/// BH_Item implementation
/// </summary>
public void SetIndexInHeap(int index) { binaryHeapIndex = index; }
/// <summary>
/// When equivalence over different times is necessary,
/// checks this.agent and last position only,
/// ignoring data that would make this state different to other equivalent states:
/// It doesn't matter from which direction the agent got to its current location.
/// It's also necessary to ignore the agents' move time - we want the same positions
/// in any time to be equivalent.
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (obj == null)
return false;
AgentState that = (AgentState)obj;
if (AgentState.EquivalenceOverDifferentTimes)
{
return this.agent.Equals(that.agent) &&
this.lastMove.x == that.lastMove.x &&
this.lastMove.y == that.lastMove.y; // Ignoring the time and the direction
}
else
{
return this.agent.Equals(that.agent) &&
this.lastMove.x == that.lastMove.x &&
this.lastMove.y == that.lastMove.y &&
this.lastMove.time == that.lastMove.time; // Ignoring the direction
}
}
/// <summary>
/// When equivalence over different times is necessary,
/// uses this.agent and last position only, ignoring direction and time.
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
unchecked
{
if (AgentState.EquivalenceOverDifferentTimes)
return 3 * this.agent.GetHashCode() + 5 * this.lastMove.x + 7 * this.lastMove.y;
else
return 3 * this.agent.GetHashCode() + 5 * this.lastMove.GetHashCode();
}
}
public Move GetMove()
{
return this.lastMove;
}
/// <summary>
/// Used when AgentState objects are put in the open list priority queue - mainly in AStarForSingleAgent, I think.
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public int CompareTo(IBinaryHeapItem other)
{
AgentState that = (AgentState)other;
if (this.h + this.lastMove.time < that.h + that.lastMove.time)
return -1;
if (this.h + this.lastMove.time > that.h + that.lastMove.time)
return 1;
if (this.potentialConflictsID < that.potentialConflictsID)
return -1;
if (this.potentialConflictsID > that.potentialConflictsID)
return 1;
if (this.potentialConflicts < that.potentialConflicts) // Doesn't this come before the potentialConflictsID in other places?
return -1;
if (this.potentialConflicts > that.potentialConflicts)
return 1;
// TODO: Prefer goal nodes.
// Prefer larger g:
if (this.lastMove.time < that.lastMove.time)
return 1;
if (this.lastMove.time > that.lastMove.time)
return -1;
return 0;
}
public override string ToString()
{
return $"step-{lastMove.time} position {this.lastMove}";
}
}