-
Notifications
You must be signed in to change notification settings - Fork 0
/
Agent.c
315 lines (276 loc) · 9.85 KB
/
Agent.c
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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "Graph.h"
#include "Agent.h"
//This struct stores information about an individual agent(detective or thief)
//You might want to add to this struct to store more information
struct agentRep{
Vertex startLocation;
Vertex currentLocation;
int currentCycle;
int maxCycles;
int initialStamina; //max stamina
int stamina; //current stamina
int strategy;
Graph map;
char *name;
//stuff I added
Vertex endLocation;
int *visits; // array of visits
//dfs
int dfsCount;
int Goal;
Vertex *st;
Vertex *pre;
//least turns
Vertex *leastTurns;
Vertex *ThiefLoc; //thief's location from informant
int nVPath; //number of vertices
int oriStrategy; //if needed to return to original strategy
int pathPos;
};
//static Edge clVisited(Agent agent, Graph g, Edge *move, int numMoves);
static Edge CLFilterEdges(Agent agent, Graph g, Edge *filteredMoves, int numFilteredEdges);
static Edge DFSstrat(Graph g, Agent agent);
static Edge LeastTurns(Graph g, Agent agent);
//This creates one individual thief or detective
//You may need to add more to this
Agent initAgent(Vertex start, int maxCycles,int stamina,
int strategy, Graph g, char * name, Vertex end){
if(start >= numV(g)){
printf("Error starting vertex %d not valid\n",start);
abort();
}
Agent agent = malloc(sizeof(struct agentRep));
agent->startLocation = start;
agent->currentLocation = start;
agent->currentCycle = 0;
agent->maxCycles = maxCycles;
agent->initialStamina = stamina;
agent->stamina = stamina;
agent->strategy = strategy;
agent->map = g;
agent->name = strdup(name);
agent->endLocation = end;
agent->visits = calloc(numV(g),sizeof(int) *numV(g));
agent->st = calloc(numV(g),sizeof(int) *numV(g));
agent->pre = calloc(numV(g),sizeof(int) *numV(g));
agent->leastTurns = malloc(sizeof(int) *2*numV(g));
agent->oriStrategy = strategy;
agent->visits[start]++;
if(agent->strategy == DFS){
dfSearch2(g,agent);
}
return agent;
}
// Takes an array with all the possible edges and puts the ones the agent
// has enough stamina for into the filteredMoves array
// returns the number of filteredMoves
int filterEdges(Agent a,int numEdges,Edge *possibleMoves,Edge * filteredMoves){
int numFiltered = 0;
int i;
for(i=0;i<numEdges;i++){
if(possibleMoves[i].weight <= a->stamina){
filteredMoves[numFiltered++] = possibleMoves[i];
}
}
return numFiltered;
}
// Get a legal move. This should be a move that the agent has enough
// stamina to make and is a valid edge from the graph.
// You need to implement all other strategies.
Edge getNextMove(Agent agent,Graph g){
Edge nextMove;
//Stationary strategy useful for debugging
if(agent->strategy == STATIONARY){
nextMove = mkEdge(agent->currentLocation,agent->currentLocation,0);
}else if(agent->strategy == RANDOM || agent->strategy == C_L_VISITED){
Edge * possibleMoves = malloc(numV(g) * sizeof(Edge));
Edge * filteredMoves = malloc(numV(g) * sizeof(Edge));
//Get all edges to adjacent vertices
int numEdges = incidentEdges(g,agent->currentLocation,possibleMoves);
//Filter out edges that the agent does not have enough stamina for
int numFilteredEdges = filterEdges(agent,numEdges,possibleMoves,filteredMoves);
if(numFilteredEdges!= 0){
//nextMove is randomly chosen from the filteredEdges
if(agent->strategy == RANDOM){
nextMove = filteredMoves[rand()%numFilteredEdges];
} else if (agent->strategy == C_L_VISITED){
//have to implement cheapest least visited strat
//nextMove = clVisited(agent,g,filteredMoves,numFilteredEdges);
nextMove = CLFilterEdges(agent,g,filteredMoves,numFilteredEdges);
}
} else {
//the agent must stay in the same location
nextMove = mkEdge(agent->currentLocation,agent->currentLocation,0);
}
free(filteredMoves);
free(possibleMoves);
}else if(agent->strategy == DFS){
nextMove = DFSstrat(g,agent);
}else if(agent->strategy == Least_Turns){
nextMove = LeastTurns(g,agent);
}else {
printf("Agent strategy not implemented yet\n");
abort();
}
agent->visits[nextMove.w]++;
return nextMove;
}
//Actually perform the move, by changing the agent's state
//This function needs to be updated to adjust the agent's stamina
void makeNextMove(Agent agent,Edge move){
agent->currentCycle++;
//deduct stamina for every move
if(agent->currentLocation != move.w){
agent->currentLocation = move.w;
agent->stamina = agent->stamina - move.weight;
} else {
//stamina reloads because agent hasnt moved
agent->stamina = agent->initialStamina;
}
//used Least turns strat and came to the location mentioned in informant
if(agent->strategy == Least_Turns && agent->currentLocation == agent->endLocation){
//but no thief so switch back to original strategy
agent->strategy = agent->oriStrategy;
//if original strategy was DFS
if(agent->strategy == DFS){
//fill the dfs search again
dfSearch2(agent->map,agent);
}
}
}
Vertex getCurrentLocation(Agent agent){
return agent->currentLocation;
}
Vertex getEndLocation(Agent agent){
return agent->endLocation;
}
char * getName(Agent agent){
return agent->name;
}
//Needs to be updated to print out vertex name information
//and * for cities with informants
void printAgent(Agent agent){
//MODIFY THIS
printf("%s %d %s ",agent->name,agent->stamina,
getVertexLabel(agent->map,agent->currentLocation));
checkInformant(agent,agent->map,FALSE);
if(agent->name[0] == 'T'){
printf(" %s ", getVertexLabel(agent->map,agent->endLocation));
checkInformant(agent,agent->map,TRUE);
}
printf("\n");
}
void checkInformant (Agent agent, Graph graph, Vertex count){
Vertex loc = 0;
if((agent->name[0] == 'T') && count == TRUE){
loc = agent->endLocation;
} else {
loc = agent->currentLocation;
}
if(informant(agent->map,loc) == TRUE) {
printf("(%d*)",loc);
} else {
printf("(%d)",loc);
}
}
void leastTurnsInformant(Agent agent, Agent thief, Graph graph){
if(informant(graph,agent->currentLocation) == TRUE){
agent->strategy = Least_Turns;
agent->pathPos = 0;
agent->endLocation = thief->currentLocation;
shortestPath(graph, agent, thief->currentLocation);
}
}
//You may need to update this to free any extra memory you use
void destroyAgent(Agent agent){
//YOU MAY NEED TO MODIFY THIS
free(agent->name);
free(agent->visits);
free(agent->pre);
free(agent->st);
free(agent->leastTurns);
free(agent);
}
static Edge CLFilterEdges(Agent agent, Graph g, Edge *filteredMoves, int numFilteredEdges){
int i , minIndex = 0;
for(i = 0; i < numFilteredEdges; i++){
if(agent->visits[filteredMoves[minIndex].w] > agent->visits[filteredMoves[i].w]){
minIndex = i;
} else if(agent->visits[filteredMoves[minIndex].w] == agent->visits[filteredMoves[i].w]){
if(filteredMoves[minIndex].weight > filteredMoves[i].weight){
minIndex = i;
} else if(filteredMoves[minIndex].weight == filteredMoves[i].weight){
if(filteredMoves[minIndex].w > filteredMoves[i].w){
minIndex = i;
}
}
}
}
return filteredMoves[minIndex];
}
//DFS
void dfSearch2(Graph g, Agent agent){
int v;
Vertex *visited = calloc(numV(g),sizeof(int) *numV(g));
agent->dfsCount = 0;
for(v = 0; v < numV(g); v++){
visited[v] = -1;
agent->st[v] = -1;
agent->pre[v] = -1;
}
for(v = 0; v < numV(g); v++){
if(agent->pre[v] == -1){
dfsR2(g,mkEdge(agent->currentLocation,agent->currentLocation,0),agent,visited);
}
}
agent->Goal = 1;
free(visited);
}
void dfsR2(Graph g, Edge e, Agent agent, Vertex *visited){
int i,w;
agent->pre[agent->dfsCount++] = e.w;
//Vertex *visited = malloc(sizeof(int) *g->V);
visited[e.w] = 1;
agent->st[e.w] = e.v;
for(i = 0; i < numV(g); i++){
w = edgeWeight(g,e.w,i);
if((w != 0) && (visited[i] == -1)){
dfsR2(g,mkEdge(e.w,i,w),agent,visited);
}
}
// free(visited);
}
Edge DFSstrat(Graph g, Agent agent){
int newGoal = agent->Goal;
Vertex goal = agent->pre[newGoal];
Edge pass;
Vertex curr = agent->currentLocation;
int w = edgeWeight(g,curr,goal);
if(w > 0){
newGoal = (agent->Goal + 1) % numV(g);
pass = mkEdge(curr, goal, w);
} else {
w = edgeWeight(g, curr, agent->st[curr]);
pass = mkEdge(curr, agent->st[curr], w);
}
if(agent->stamina < w){
pass = mkEdge(curr,curr,0);
} else {
agent->Goal = newGoal;
}
return pass;
}
//least turns
void shortestPath(Graph g, Agent agent, Vertex EndLoc){
printf("got to implement\n");
}
Edge LeastTurns(Graph g, Agent agent){
Vertex v = agent->leastTurns[agent->pathPos];
agent->pathPos++;
Vertex w = agent->leastTurns[agent->pathPos];
return mkEdge(v,w,edgeWeight(g,v,w));
}