Skip to content

Commit 61509dc

Browse files
committed
errors fixed, spec added
1 parent cab3a7f commit 61509dc

File tree

3 files changed

+91
-74
lines changed

3 files changed

+91
-74
lines changed
Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
package aima.core.search.adversarial
22

33
final case class UtilityValue(value: Double) extends AnyVal {
4-
def <(that: UtilityValue) = if (this.value < that.value) true else false
5-
def >(that: UtilityValue) = if (this.value > that.value) true else false
4+
def <(that: UtilityValue) = if (this.value < that.value) true else false
5+
def >(that: UtilityValue) = if (this.value > that.value) true else false
6+
def ==(that: UtilityValue) = if (this.value == that.value) true else false
67

78
}
89

910
/**
1011
* @author Aditya Lahiri
1112
* @author Shawn Garner
1213
*/
13-
trait Game[Player, State, Action] {
14-
def initialState: State
15-
def getPlayer(state: State): Player
16-
def getActions(state: State): List[Action]
17-
def result(state: State, action: Action): State
18-
def isTerminalState(state: State): Boolean
19-
def getUtility(state: State, player: Player): UtilityValue
14+
trait Game[P <: Player, S <: State, A <: Action] {
15+
def initialState: S
16+
def getPlayer(state: S): P
17+
def getActions(state: S): List[A]
18+
def result(state: S, action: A): S
19+
def isTerminalState(state: S): Boolean
20+
def getUtility(state: S): UtilityValue
2021
}
22+
23+
trait Player {}
24+
25+
trait State {}
26+
27+
trait Action {}

core/src/main/scala/aima/core/search/adversarial/MinimaxSearch.scala

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,44 @@ import scala.annotation.tailrec
77
* @author Shawn Garner
88
*/
99
object MinimaxDecision {
10-
def minMaxDecision[PLAYER, STATE, ACTION](
10+
def minMaxDecision[PLAYER <: Player, STATE <: State, ACTION <: Action](
1111
g: Game[PLAYER, STATE, ACTION],
1212
noAction: ACTION
13-
): (STATE, PLAYER) => ACTION = { (s: STATE, p: PLAYER) =>
14-
@tailrec def maxMinValue(Actions: List[ACTION], p: PLAYER): ACTION = Actions match {
15-
case Nil => noAction
16-
case a :: Nil => a
17-
case a1 :: a2 :: rest =>
18-
maxMinValue((if (minValue(g.result(s, a1), p) > minValue(g.result(s, a2), p)) a1 else a2) :: rest, p)
13+
): (STATE) => ACTION = { (state: STATE) =>
14+
@tailrec def maxMinValue(Actions: List[ACTION]): ACTION = Actions match {
15+
case Nil => noAction
16+
case singularAction :: Nil => singularAction
17+
case action1 :: action2 :: rest =>
18+
maxMinValue(
19+
(if (minValue(g.result(state, action1)) > minValue(g.result(state, action2))) action1
20+
else action2) :: rest
21+
)
1922
}
2023

21-
@tailrec def minMaxValue(Actions: List[ACTION], p: PLAYER): ACTION = Actions match {
22-
case Nil => noAction
23-
case a :: Nil => a
24-
case a1 :: a2 :: rest =>
25-
minMaxValue((if (maxValue(g.result(s, a1), p) < maxValue(g.result(s, a2), p)) a1 else a2) :: rest, p)
24+
@tailrec def minMaxValue(Actions: List[ACTION]): ACTION = Actions match {
25+
case Nil => noAction
26+
case singularAction :: Nil => singularAction
27+
case action1 :: action2 :: rest =>
28+
minMaxValue(
29+
(if (maxValue(g.result(state, action1)) < maxValue(g.result(state, action2))) action1
30+
else action2) :: rest
31+
)
2632
}
2733

28-
def maxValue(s: STATE, p: PLAYER): UtilityValue = {
29-
if (g.isTerminalState(s))
30-
g.getUtility(s, p)
34+
def maxValue(state: STATE): UtilityValue = {
35+
if (g.isTerminalState(state))
36+
g.getUtility(state)
3137
else
32-
minValue(g.result(s, maxMinValue(g.getActions(s), p)), p)
38+
minValue(g.result(state, maxMinValue(g.getActions(state))))
3339
}
3440

35-
def minValue(s: STATE, p: PLAYER): UtilityValue = {
36-
if (g.isTerminalState(s))
37-
g.getUtility(s, p)
41+
def minValue(state: STATE): UtilityValue = {
42+
if (g.isTerminalState(state))
43+
g.getUtility(state)
3844
else
39-
maxValue(g.result(s, minMaxValue(g.getActions(s), p)), p)
45+
maxValue(g.result(state, minMaxValue(g.getActions(state))))
4046
}
4147

42-
maxMinValue(g.getActions(s), p)
48+
maxMinValue(g.getActions(g.initialState))
4349
}
4450
}
Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,70 @@
11
package aima.core.search.problems
22

3-
import aima.core.search.adversarial.{Game, UtilityValue}
3+
import aima.core.search.adversarial._
44

55
/**
66
* @author Aditya Lahiri
77
*/
8-
sealed abstract class Player
9-
object PlayerMax extends Player //PlayerMax aims to obtain maximum value
10-
object PlayerMin extends Player
8+
case class TwoPlyPlayer(name: String) extends Player
119

12-
case class State(stateNumber: Int) extends AnyVal
13-
case class Action(stateNumber: Int) extends AnyVal
10+
case class TwoPlyState(name: String) extends State
11+
case class TwoPlyAction(name: String) extends Action
1412

15-
object TwoPlyGame extends Game[Player, State, Action] {
13+
object TwoPlyGame extends Game[TwoPlyPlayer, TwoPlyState, TwoPlyAction] {
1614
val adjacencyMat = Map(
17-
0 -> List(Action(1), Action(2), Action(3)),
18-
1 -> List(Action(4), Action(5), Action(6)),
19-
2 -> List(Action(7), Action(8), Action(9)),
20-
3 -> List(Action(10), Action(11), Action(12))
15+
"A" -> List(TwoPlyAction("B"), TwoPlyAction("C"), TwoPlyAction("D")),
16+
"B" -> List(TwoPlyAction("E"), TwoPlyAction("F"), TwoPlyAction("G")),
17+
"C" -> List(TwoPlyAction("H"), TwoPlyAction("I"), TwoPlyAction("J")),
18+
"D" -> List(TwoPlyAction("K"), TwoPlyAction("L"), TwoPlyAction("M"))
2119
)
22-
val States = Map(
23-
0 -> State(0),
24-
1 -> State(1),
25-
2 -> State(2),
26-
3 -> State(3),
27-
4 -> State(4),
28-
5 -> State(5),
29-
6 -> State(6),
30-
7 -> State(7),
31-
8 -> State(8),
32-
9 -> State(9),
33-
10 -> State(10),
34-
11 -> State(11),
35-
12 -> State(12)
20+
val TwoPlyStates = Map(
21+
"A" -> TwoPlyState("A"),
22+
"B" -> TwoPlyState("B"),
23+
"C" -> TwoPlyState("C"),
24+
"D" -> TwoPlyState("D"),
25+
"E" -> TwoPlyState("E"),
26+
"F" -> TwoPlyState("F"),
27+
"G" -> TwoPlyState("G"),
28+
"H" -> TwoPlyState("H"),
29+
"I" -> TwoPlyState("I"),
30+
"J" -> TwoPlyState("J"),
31+
"K" -> TwoPlyState("K"),
32+
"L" -> TwoPlyState("L"),
33+
"M" -> TwoPlyState("M")
3634
)
3735

38-
def initialState: State = States(0)
36+
@Override
37+
def initialState: TwoPlyState = TwoPlyStates("A")
3938

40-
def getPlayer(state: State): Player = state.stateNumber match {
41-
case 0 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 => PlayerMax
42-
case 1 | 2 | 3 => PlayerMin
39+
@Override
40+
def getPlayer(state: TwoPlyState): TwoPlyPlayer = state.name match {
41+
case "B" | "C" | "D" => TwoPlyPlayer("MIN")
42+
case _ => TwoPlyPlayer("MAX")
4343
}
4444

45-
def getActions(state: State): List[Action] = adjacencyMat(state.stateNumber)
45+
@Override
46+
def getActions(state: TwoPlyState): List[TwoPlyAction] = adjacencyMat(state.name)
4647

47-
def result(state: State, action: Action): State = States(action.stateNumber)
48+
@Override
49+
def result(state: TwoPlyState, action: TwoPlyAction): TwoPlyState = TwoPlyStates(action.name)
4850

49-
def isTerminalState(state: State): Boolean = state.stateNumber match {
50-
case 0 | 1 | 2 | 3 => false
51-
case 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 => true
51+
@Override
52+
def isTerminalState(state: TwoPlyState): Boolean = state.name match {
53+
case "A" | "B" | "C" | "D" => false
54+
case _ => true
5255

5356
}
5457

55-
def getUtility(state: State, player: Player): UtilityValue = state.stateNumber match {
56-
case 4 => UtilityValue(3)
57-
case 5 => UtilityValue(12)
58-
case 6 => UtilityValue(8)
59-
case 7 => UtilityValue(2)
60-
case 8 => UtilityValue(4)
61-
case 9 => UtilityValue(6)
62-
case 10 => UtilityValue(14)
63-
case 11 => UtilityValue(5)
64-
case 12 => UtilityValue(2)
58+
@Override
59+
def getUtility(state: TwoPlyState): UtilityValue = state.name match {
60+
case "E" => UtilityValue(3)
61+
case "F" => UtilityValue(12)
62+
case "G" => UtilityValue(8)
63+
case "H" => UtilityValue(2)
64+
case "I" => UtilityValue(4)
65+
case "J" => UtilityValue(6)
66+
case "K" => UtilityValue(14)
67+
case "L" => UtilityValue(5)
68+
case "M" => UtilityValue(2)
6569
}
6670
}

0 commit comments

Comments
 (0)