Skip to content

Commit fd113fd

Browse files
committed
New WumpusAgentApp added.
- KB: Now Wumpus and pit can be at same location, visited locations are regarded as safe - Unit Tests: New Wumpus agent simulation test added.
1 parent 39e8ee2 commit fd113fd

File tree

14 files changed

+202
-31
lines changed

14 files changed

+202
-31
lines changed

aima-core/src/main/java/aima/core/environment/wumpusworld/WumpusCave.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,19 @@ public WumpusCave setAllowed(Set<Room> allowedRooms) {
8787
return this;
8888
}
8989

90-
public WumpusCave setGold(Room room) {
90+
public void setWumpus(Room room) {
91+
wumpus = room;
92+
}
93+
94+
public void setGold(Room room) {
9195
gold = room;
92-
return this;
96+
}
97+
98+
public void setPit(Room room, boolean b) {
99+
if (!b)
100+
pits.remove(room);
101+
else if (!room.equals(start.getRoom()) && !room.equals(gold))
102+
pits.add(room);
93103
}
94104

95105
public int getCaveXDimension() {

aima-core/src/main/java/aima/core/environment/wumpusworld/WumpusEnvironment.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
public class WumpusEnvironment extends AbstractEnvironment {
1818

1919
private WumpusCave cave;
20-
private boolean wumpusAlive = true;
20+
private boolean isWumpusAlive = true;
21+
private boolean isGoldGrabbed;
2122
private boolean scream;
2223
/** We assume that only one agent is added to the environment! */
2324
private boolean hasArrow =true;
@@ -28,6 +29,22 @@ public WumpusEnvironment(WumpusCave cave) {
2829
this.cave = cave;
2930
}
3031

32+
public WumpusCave getCave() {
33+
return cave;
34+
}
35+
36+
public boolean isWumpusAlive() {
37+
return isWumpusAlive;
38+
}
39+
40+
public boolean isGoalGrabbed() {
41+
return isGoldGrabbed;
42+
}
43+
44+
public AgentPosition getAgentPosition(Agent agent) {
45+
return agentPositions.get(agent);
46+
}
47+
3148
@Override
3249
public void addAgent(Agent agent) {
3350
super.addAgent(agent);
@@ -42,18 +59,18 @@ public void executeAction(Agent agent, Action action) {
4259
agentPositions.put(agent, newPos);
4360
if (newPos.equals(pos))
4461
bump = true;
45-
else if (cave.isPit(newPos.getRoom()) || newPos.getRoom().equals(cave.getWumpus()) && wumpusAlive)
62+
else if (cave.isPit(newPos.getRoom()) || newPos.getRoom().equals(cave.getWumpus()) && isWumpusAlive)
4663
agent.setAlive(false);
4764
} else if (action == WumpusAction.TURN_LEFT) {
4865
agentPositions.put(agent, cave.turnLeft(pos));
4966
} else if (action == WumpusAction.TURN_RIGHT) {
5067
agentPositions.put(agent, cave.turnRight(pos));
5168
} else if (action == WumpusAction.GRAB) {
52-
if (pos.getRoom().equals(cave.getGold()))
53-
cave.setGold(null);
69+
if (!isGoldGrabbed && pos.getRoom().equals(cave.getGold()))
70+
isGoldGrabbed = true;
5471
} else if (action == WumpusAction.SHOOT) {
5572
if (hasArrow && isAgentFacingWumpus(pos)) {
56-
wumpusAlive = false;
73+
isWumpusAlive = false;
5774
scream = true;
5875
hasArrow = false;
5976
}

aima-core/src/main/java/aima/core/environment/wumpusworld/WumpusKnowledgeBase.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,6 @@ public WumpusKnowledgeBase(DPLL dpll, int caveDimensions, AgentPosition start) {
114114
}
115115
}
116116

117-
// The Wumpus will never be located in a pit.
118-
for (int y = 1; y <= caveYDimension; y++)
119-
for (int x = 1; x <= caveXDimension; x++)
120-
tell(new ComplexSentence(newSymbol(WUMPUS, x, y), Connective.IMPLICATION,
121-
new ComplexSentence(Connective.NOT, newSymbol(PIT, x, y))));
122-
123117
// The agent also knows there is exactly one wumpus. This is represented
124118
// in two parts. First, we have to say that there is at least one wumpus
125119
List<PropositionSymbol> wumpsAtLeast = new ArrayList<>();
@@ -215,7 +209,10 @@ public Set<Room> askSafeRooms(int t) {
215209
Set<Room> safe = new LinkedHashSet<>();
216210
for (int x = 1; x <= getCaveXDimension(); x++) {
217211
for (int y = 1; y <= getCaveYDimension(); y++) {
218-
if (ask(newSymbol(OK_TO_MOVE_INTO, t, x, y))) {
212+
// Already visited rooms are safe! This is important because not all pits can be located by percept.
213+
// Not-unsafe planing adds knowledge by surviving dangerous moves but this is not used in OK_TO_MOVE_INTO.
214+
if (ask(new ComplexSentence(newSymbol(LOCATION_VISITED, x, y),
215+
Connective.OR, newSymbol(OK_TO_MOVE_INTO, t, x, y)))) {
219216
safe.add(new Room(x, y));
220217
}
221218
}

aima-core/src/test/java/aima/test/core/unit/environment/wumpusworld/HybridWumpusAgentTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package aima.test.core.unit.environment.wumpusworld;
22

33
import aima.core.agent.Action;
4+
import aima.core.agent.EnvironmentView;
5+
import aima.core.agent.impl.SimpleActionTracker;
6+
import aima.core.agent.impl.SimpleEnvironmentView;
47
import aima.core.environment.wumpusworld.*;
58
import org.junit.Assert;
69
import org.junit.Test;
@@ -102,6 +105,21 @@ public void testGrabAndClimb() {
102105
Assert.assertEquals(a, WumpusAction.CLIMB);
103106
}
104107

108+
@Test
109+
public void testSimulation2x2Cave() {
110+
WumpusCave cave = new WumpusCave(2, 2, ""
111+
+ "W."
112+
+ "SG");
113+
WumpusEnvironment env = new WumpusEnvironment(cave);
114+
SimpleActionTracker view = new SimpleActionTracker();
115+
env.addEnvironmentView(view);
116+
HybridWumpusAgent a = new HybridWumpusAgent(cave.getCaveXDimension(), cave.getStart(), env);
117+
env.addAgent(a);
118+
env.stepUntilDone();
119+
Assert.assertEquals(view.getActions(),
120+
"SHOOT, FORWARD, TURN_RIGHT, FORWARD, TURN_RIGHT, FORWARD, GRAB, TURN_RIGHT, FORWARD, CLIMB");
121+
}
122+
105123
private static Set<Room> allRooms(int caveDimensions) {
106124
Set<Room> allRooms = new LinkedHashSet<>();
107125
for (int x = 1; x <= caveDimensions; x++) {

aima-gui/src/main/java/aima/gui/fx/applications/IntegratedAimaFxApp.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import aima.gui.demo.search.TicTacToeDemo;
1616
import aima.gui.fx.applications.agent.RouteFindingAgentApp;
1717
import aima.gui.fx.applications.agent.VacuumAgentApp;
18+
import aima.gui.fx.applications.agent.WumpusAgentApp;
1819
import aima.gui.fx.applications.search.MapColoringCspApp;
1920
import aima.gui.fx.applications.search.NQueensCspApp;
2021
import aima.gui.fx.applications.search.NQueensCspDemo;
@@ -57,6 +58,7 @@ public void start(Stage primaryStage) throws Exception {
5758
public static void defineContent(IntegratedAppBuilder builder) {
5859
builder.registerApp(VacuumAgentApp.class);
5960
builder.registerApp(RouteFindingAgentApp.class);
61+
builder.registerApp(WumpusAgentApp.class);
6062

6163
builder.registerApp(MapColoringCspApp.class);
6264
builder.registerApp(NQueensCspApp.class);

aima-gui/src/main/java/aima/gui/fx/applications/agent/RouteFindingAgentApp.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ public static void main(String[] args) {
5757
/** Heuristic function to be used when performing informed search. */
5858
protected ToDoubleFunction<Node<String, MoveToAction>> heuristic;
5959

60-
public RouteFindingAgentApp() {
61-
}
62-
6360
@Override
6461
public String getTitle() {
6562
return "Route Finding Agent App";

aima-gui/src/main/java/aima/gui/fx/applications/agent/VacuumAgentApp.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ public static void main(String[] args) {
3939
protected VacuumEnvironment env = null;
4040
protected AbstractAgent agent = null;
4141

42-
public VacuumAgentApp() {
43-
44-
}
45-
4642
@Override
4743
public String getTitle() {
4844
return "Vacuum Agent App";
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package aima.gui.fx.applications.agent;
2+
3+
import aima.core.environment.wumpusworld.*;
4+
import aima.core.util.Tasks;
5+
import aima.gui.fx.framework.IntegrableApplication;
6+
import aima.gui.fx.framework.Parameter;
7+
import aima.gui.fx.framework.TaskExecutionPaneBuilder;
8+
import aima.gui.fx.framework.TaskExecutionPaneCtrl;
9+
import aima.gui.fx.views.WumpusEnvironmentViewCtrl;
10+
import javafx.scene.layout.BorderPane;
11+
import javafx.scene.layout.Pane;
12+
import javafx.scene.layout.StackPane;
13+
14+
import java.util.Arrays;
15+
import java.util.List;
16+
17+
/**
18+
* Integrable application which demonstrates how the Hybrid Wumpus Agent
19+
* solves the problem of finding gold in a Wumpus cave.
20+
*
21+
* @author Ruediger Lunde
22+
*
23+
*/
24+
public class WumpusAgentApp extends IntegrableApplication {
25+
26+
public static void main(String[] args) {
27+
launch(args);
28+
}
29+
30+
protected static String PARAM_CAVE = "cave";
31+
protected static String PARAM_AGENT = "agent";
32+
33+
private TaskExecutionPaneCtrl taskPaneCtrl;
34+
private WumpusEnvironmentViewCtrl envViewCtrl;
35+
36+
protected WumpusEnvironment env = null;
37+
protected HybridWumpusAgent agent = null;
38+
/** The selected Wumpus cave */
39+
protected WumpusCave cave;
40+
41+
@Override
42+
public String getTitle() {
43+
return "Wumpus Agent App";
44+
}
45+
46+
/**
47+
* Defines state view, parameters, and call-back functions and calls the
48+
* simulation pane builder to create layout and controller objects.
49+
*/
50+
@Override
51+
public Pane createRootPane() {
52+
BorderPane root = new BorderPane();
53+
54+
StackPane envView = new StackPane();
55+
envViewCtrl = new WumpusEnvironmentViewCtrl(envView);
56+
57+
List<Parameter> params = createParameters();
58+
59+
TaskExecutionPaneBuilder builder = new TaskExecutionPaneBuilder();
60+
builder.defineParameters(params);
61+
builder.defineStateView(envView);
62+
builder.defineInitMethod(this::initialize);
63+
builder.defineTaskMethod(this::startExperiment);
64+
taskPaneCtrl = builder.getResultFor(root);
65+
66+
return root;
67+
}
68+
69+
protected List<Parameter> createParameters() {
70+
Parameter p1 = new Parameter(PARAM_CAVE, "2x2", "3x3", "Typical");
71+
p1.setDefaultValueIndex(2);
72+
Parameter p2 = new Parameter(PARAM_AGENT, "Hybrid Wumpus Agent", "Efficient Wumpus Agent");
73+
p2.setDefaultValueIndex(1);
74+
return Arrays.asList(p1, p2);
75+
}
76+
77+
/** Is called after each parameter selection change. */
78+
@Override
79+
public void initialize() {
80+
switch (taskPaneCtrl.getParamValueIndex(PARAM_CAVE)) {
81+
case 0:
82+
cave = new WumpusCave(2, 2, ""
83+
+ "W."
84+
+ "SG");
85+
break;
86+
case 1:
87+
cave = new WumpusCave(3, 3, ""
88+
+ "P.G"
89+
+ ".W."
90+
+ "S.P");
91+
break;
92+
case 2:
93+
// from Figure 7.2 A typical wumpus world.
94+
cave = new WumpusCave(4, 4, ""
95+
+ "...P"
96+
+ "WGP."
97+
+ "...."
98+
+ "S.P.");
99+
break;
100+
}
101+
env = new WumpusEnvironment(cave);
102+
switch (taskPaneCtrl.getParamValueIndex(PARAM_AGENT)) {
103+
case 0:
104+
agent = new HybridWumpusAgent(cave.getCaveXDimension(), cave.getStart(), env);
105+
break;
106+
case 1:
107+
agent = new EfficientHybridWumpusAgent(cave.getCaveXDimension(), cave.getStart(), env);
108+
break;
109+
}
110+
env.addEnvironmentView(envViewCtrl);
111+
envViewCtrl.initialize(env);
112+
}
113+
114+
/** Starts the experiment. */
115+
public void startExperiment() {
116+
env.addAgent(agent);
117+
while (!env.isDone() && !Tasks.currIsCancelled()) {
118+
env.step();
119+
updateStatus();
120+
taskPaneCtrl.waitAfterStep();
121+
}
122+
}
123+
124+
@Override
125+
public void cleanup() {
126+
taskPaneCtrl.cancelExecution();
127+
}
128+
129+
private void updateStatus() {
130+
WumpusKnowledgeBase kb = agent.getKB();
131+
taskPaneCtrl.setStatus("{KB.size=" + kb.size() +
132+
", KB.sym.size=" + kb.getSymbols().size() + ", KB.cnf.size=" + kb.asCNF().size() + "}");
133+
}
134+
}

aima-gui/src/main/java/aima/gui/fx/views/CspViewCtrl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import java.util.List;
1818

1919
/**
20-
* Controller class which provides functionality to visualize a binary CSP state in a pane.
20+
* Controller class which provides functionality to visualize a binary CSP state in a markerPane.
2121
*
2222
* @author Ruediger Lunde
2323
*/
@@ -126,7 +126,7 @@ protected void visualize(Constraint<VAR, VAL> constraint) {
126126

127127
/**
128128
* Computes transforms (translations and scaling) and applies them to the environment state view. Those transforms
129-
* map logical positions to screen positions in the viewer pane. The purpose is to show the graphical state
129+
* map logical positions to screen positions in the viewer markerPane. The purpose is to show the graphical state
130130
* representation as large as possible.
131131
*
132132
* @return The scale value.

aima-gui/src/main/java/aima/gui/fx/views/EightPuzzleViewCtrl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import javafx.scene.text.Font;
1414

1515
/**
16-
* Controller class which provides functionality for using a stack pane as a
16+
* Controller class which provides functionality for using a stack markerPane as a
1717
* state view for the Eight Puzzle problem.
1818
*
1919
* @author Ruediger Lunde
@@ -24,7 +24,7 @@ public class EightPuzzleViewCtrl {
2424
private EightPuzzleBoard board;
2525

2626
/**
27-
* Adds a grid pane to the provided pane and creates a controller class
27+
* Adds a grid markerPane to the provided markerPane and creates a controller class
2828
* instance which is responsible for Eight Puzzle tile positioning on the grid.
2929
*/
3030
public EightPuzzleViewCtrl(StackPane viewRoot) {

0 commit comments

Comments
 (0)