Skip to content

Commit a7019fc

Browse files
committed
Add JUnit tests for adversarial search
1 parent bd95797 commit a7019fc

File tree

6 files changed

+229
-2
lines changed

6 files changed

+229
-2
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package aima.core.environment.twoply;
2+
3+
import aima.core.environment.map.MoveToAction;
4+
import aima.core.search.adversarial.Game;
5+
6+
import java.util.List;
7+
8+
public class TwoPlyGame implements Game<TwoPlyGameState, MoveToAction, String> {
9+
10+
@Override
11+
public TwoPlyGameState getInitialState() {
12+
return new TwoPlyGameState("A");
13+
}
14+
15+
@Override
16+
public String[] getPlayers() {
17+
return new String[]{"MAX", "MIN"};
18+
}
19+
20+
@Override
21+
public String getPlayer(TwoPlyGameState state) {
22+
switch (state.getLocation()) {
23+
case "B":
24+
case "C":
25+
case "D":
26+
return "MIN";
27+
default:
28+
return "MAX";
29+
}
30+
}
31+
32+
33+
@Override
34+
public List<MoveToAction> getActions(TwoPlyGameState state) {
35+
return new TwoPlyGameTree().getActions(state);
36+
}
37+
38+
@Override
39+
public TwoPlyGameState getResult(TwoPlyGameState state, MoveToAction action) {
40+
return new TwoPlyGameState(action.getToLocation());
41+
}
42+
43+
@Override
44+
public boolean isTerminal(TwoPlyGameState state) {
45+
return (state.getLocation().charAt(0) > 'D');
46+
}
47+
48+
@Override
49+
public double getUtility(TwoPlyGameState state, String player) {
50+
switch (state.getLocation()) {
51+
// B
52+
case "E":
53+
return 3;
54+
case "F":
55+
return 12;
56+
case "G":
57+
return 8;
58+
// C
59+
case "H":
60+
return 2;
61+
case "I":
62+
return 4;
63+
case "J":
64+
return 6;
65+
// D
66+
case "K":
67+
return 14;
68+
case "L":
69+
return 5;
70+
case "M":
71+
return 2;
72+
default:
73+
throw new IllegalArgumentException("State " + state.getLocation() + " unexpected.");
74+
}
75+
}
76+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package aima.core.environment.twoply;
2+
3+
public class TwoPlyGameState {
4+
private String location;
5+
6+
public TwoPlyGameState(String location) {
7+
this.location = location;
8+
}
9+
10+
public String getLocation() {
11+
return location;
12+
}
13+
14+
@Override
15+
public boolean equals(Object obj) {
16+
if (obj instanceof TwoPlyGameState) {
17+
return this.getLocation().equals(((TwoPlyGameState) obj).getLocation());
18+
}
19+
return super.equals(obj);
20+
}
21+
22+
@Override
23+
public int hashCode() {
24+
return getLocation().hashCode();
25+
}
26+
27+
@Override
28+
public String toString() {
29+
return location;
30+
}
31+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package aima.core.environment.twoply;
2+
3+
import aima.core.environment.map.ExtendableMap;
4+
import aima.core.environment.map.Map;
5+
import aima.core.environment.map.MoveToAction;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
10+
public class TwoPlyGameTree {
11+
Map aima3eFig5_2;
12+
13+
public TwoPlyGameTree() {
14+
aima3eFig5_2 = new ExtendableMap() {
15+
{
16+
addUnidirectionalLink("A", "B", 1.0);
17+
addUnidirectionalLink("A", "C", 1.0);
18+
addUnidirectionalLink("A", "D", 1.0);
19+
addUnidirectionalLink("B", "E", 1.0);
20+
addUnidirectionalLink("B", "F", 1.0);
21+
addUnidirectionalLink("B", "G", 1.0);
22+
addUnidirectionalLink("C", "H", 1.0);
23+
addUnidirectionalLink("C", "I", 1.0);
24+
addUnidirectionalLink("C", "J", 1.0);
25+
addUnidirectionalLink("D", "K", 1.0);
26+
addUnidirectionalLink("D", "L", 1.0);
27+
addUnidirectionalLink("D", "M", 1.0);
28+
}
29+
};
30+
}
31+
32+
public List<MoveToAction> getActions(TwoPlyGameState state) {
33+
List<MoveToAction> possibleActions = new ArrayList<>();
34+
List<String> nextPossibleLocations = aima3eFig5_2.getPossibleNextLocations(state.getLocation());
35+
for (String nextLocation : nextPossibleLocations) {
36+
MoveToAction action = new MoveToAction(nextLocation);
37+
possibleActions.add(action);
38+
}
39+
return possibleActions;
40+
}
41+
42+
}

aima-core/src/test/java/aima/test/core/unit/search/SearchTestSuite.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package aima.test.core.unit.search;
22

3+
import aima.test.core.unit.search.adversarial.AlphaBetaSearchTest;
4+
import aima.test.core.unit.search.adversarial.MinimaxSearchTest;
35
import aima.test.core.unit.search.csp.AssignmentTest;
46
import aima.test.core.unit.search.csp.CSPTest;
57
import aima.test.core.unit.search.csp.MapCSPTest;
@@ -19,8 +21,8 @@
1921
import org.junit.runners.Suite;
2022

2123
@RunWith(Suite.class)
22-
@Suite.SuiteClasses({ AssignmentTest.class, CSPTest.class, MapCSPTest.class, MetricsTest.class, TreeCspSolverTest.class,
23-
AStarSearchTest.class, GreedyBestFirstSearchTest.class, RecursiveBestFirstSearchTest.class,
24+
@Suite.SuiteClasses({AlphaBetaSearchTest.class, MinimaxSearchTest.class, AssignmentTest.class, CSPTest.class, MapCSPTest.class,
25+
MetricsTest.class, TreeCspSolverTest.class, AStarSearchTest.class, GreedyBestFirstSearchTest.class, RecursiveBestFirstSearchTest.class,
2426
SimulatedAnnealingSearchTest.class, AndOrSearchTest.class, LRTAStarAgentTest.class, OnlineDFSAgentTest.class,
2527
BidirectionalSearchTest.class, BreadthFirstSearchTest.class, DepthFirstSearchTest.class,
2628
DepthLimitedSearchTest.class, IterativeDeepeningSearchTest.class, UniformCostSearchTest.class, NodeTest.class,
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package aima.test.core.unit.search.adversarial;
2+
3+
import aima.core.environment.twoply.TwoPlyGame;
4+
import aima.core.environment.twoply.TwoPlyGameState;
5+
import aima.core.search.adversarial.AlphaBetaSearch;
6+
import aima.core.search.adversarial.Game;
7+
import org.junit.Assert;
8+
import org.junit.Before;
9+
import org.junit.Test;
10+
11+
public class AlphaBetaSearchTest {
12+
Game game;
13+
AlphaBetaSearch alphaBetaSearch;
14+
15+
@Before
16+
public void setup() {
17+
this.game = new TwoPlyGame();
18+
this.alphaBetaSearch = new AlphaBetaSearch(game);
19+
}
20+
21+
@Test
22+
public void testUtilities() {
23+
TwoPlyGameState state = new TwoPlyGameState("E");
24+
Assert.assertEquals(3, game.getUtility(state, game.getPlayer(state)), 0);
25+
state = new TwoPlyGameState("I");
26+
Assert.assertEquals(4, game.getUtility(state, game.getPlayer(state)), 0);
27+
state = new TwoPlyGameState("K");
28+
Assert.assertEquals(14, game.getUtility(state, game.getPlayer(state)), 0);
29+
30+
}
31+
32+
@Test
33+
public void testMinimaxDecision() {
34+
Assert.assertEquals("A", game.getInitialState().toString());
35+
Assert.assertEquals("MAX", game.getPlayer(game.getInitialState()));
36+
Assert.assertEquals("Action[name=moveTo, location=B]", alphaBetaSearch.makeDecision(game.getInitialState()).toString());
37+
}
38+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package aima.test.core.unit.search.adversarial;
2+
3+
import aima.core.environment.twoply.TwoPlyGame;
4+
import aima.core.environment.twoply.TwoPlyGameState;
5+
import aima.core.search.adversarial.Game;
6+
import aima.core.search.adversarial.MinimaxSearch;
7+
import org.junit.Assert;
8+
import org.junit.Before;
9+
import org.junit.Test;
10+
11+
public class MinimaxSearchTest {
12+
Game game;
13+
MinimaxSearch minimaxSearch;
14+
15+
@Before
16+
public void setup() {
17+
this.game = new TwoPlyGame();
18+
this.minimaxSearch = new MinimaxSearch(game);
19+
}
20+
21+
@Test
22+
public void testUtilities() {
23+
TwoPlyGameState state = new TwoPlyGameState("E");
24+
Assert.assertEquals(3, game.getUtility(state, game.getPlayer(state)), 0);
25+
state = new TwoPlyGameState("I");
26+
Assert.assertEquals(4, game.getUtility(state, game.getPlayer(state)), 0);
27+
state = new TwoPlyGameState("K");
28+
Assert.assertEquals(14, game.getUtility(state, game.getPlayer(state)), 0);
29+
30+
}
31+
32+
@Test
33+
public void testMinimaxDecision() {
34+
Assert.assertEquals("A", game.getInitialState().toString());
35+
Assert.assertEquals("MAX", game.getPlayer(game.getInitialState()));
36+
Assert.assertEquals("Action[name=moveTo, location=B]", minimaxSearch.makeDecision(game.getInitialState()).toString());
37+
}
38+
}

0 commit comments

Comments
 (0)