@@ -42,39 +42,40 @@ def min_value(state):
42
42
# ______________________________________________________________________________
43
43
44
44
def expectiminimax (state , game ):
45
- """Returns the best move for a player after dice are thrown. The game tree
45
+ """Return the best move for a player after dice are thrown. The game tree
46
46
includes chance nodes along with min and max nodes. [Figure 5.11]"""
47
47
player = game .to_move (state )
48
48
49
- def max_value (state ):
50
- if game .terminal_test (state ):
51
- return game .utility (state , player )
49
+ def max_value (state , dice_roll ):
52
50
v = - infinity
53
51
for a in game .actions (state ):
54
52
v = max (v , chance_node (state , a ))
53
+ game .dice_roll = dice_roll
55
54
return v
56
55
57
- def min_value (state ):
58
- if game .terminal_test (state ):
59
- return game .utility (state , player )
56
+ def min_value (state , dice_roll ):
60
57
v = infinity
61
58
for a in game .actions (state ):
62
59
v = min (v , chance_node (state , a ))
60
+ game .dice_roll = dice_roll
63
61
return v
64
62
65
63
def chance_node (state , action ):
66
64
res_state = game .result (state , action )
65
+ if game .terminal_test (res_state ):
66
+ return game .utility (res_state , player )
67
67
sum_chances = 0
68
68
num_chances = 21
69
69
dice_rolls = list (itertools .combinations_with_replacement ([1 , 2 , 3 , 4 , 5 , 6 ], 2 ))
70
70
if res_state .to_move == 'W' :
71
71
for val in dice_rolls :
72
72
game .dice_roll = (- val [0 ], - val [1 ])
73
- sum_chances += max_value (res_state ) * (1 / 36 if val [0 ] == val [1 ] else 1 / 18 )
73
+ sum_chances += max_value (res_state ,
74
+ (- val [0 ], - val [1 ])) * (1 / 36 if val [0 ] == val [1 ] else 1 / 18 )
74
75
elif res_state .to_move == 'B' :
75
76
for val in dice_rolls :
76
77
game .dice_roll = val
77
- sum_chances += min_value (res_state ) * (1 / 36 if val [0 ] == val [1 ] else 1 / 18 )
78
+ sum_chances += min_value (res_state , val ) * (1 / 36 if val [0 ] == val [1 ] else 1 / 18 )
78
79
return sum_chances / num_chances
79
80
80
81
# Body of expectiminimax:
@@ -403,6 +404,8 @@ def actions(self, state):
403
404
"""Returns a list of legal moves for a state."""
404
405
player = state .to_move
405
406
moves = state .moves
407
+ if len (moves ) == 1 and len (moves [0 ]) == 1 :
408
+ return moves
406
409
legal_moves = []
407
410
for move in moves :
408
411
board = copy .deepcopy (state .board )
@@ -414,10 +417,11 @@ def result(self, state, move):
414
417
board = copy .deepcopy (state .board )
415
418
player = state .to_move
416
419
board .move_checker (move [0 ], self .dice_roll [0 ], player )
417
- board .move_checker (move [1 ], self .dice_roll [1 ], player )
420
+ if len (move ) == 2 :
421
+ board .move_checker (move [1 ], self .dice_roll [1 ], player )
418
422
to_move = ('W' if player == 'B' else 'B' )
419
423
return GameState (to_move = to_move ,
420
- utility = self .compute_utility (board , move , to_move ),
424
+ utility = self .compute_utility (board , move , player ),
421
425
board = board ,
422
426
moves = self .get_all_moves (board , to_move ))
423
427
@@ -437,6 +441,8 @@ def get_all_moves(self, board, player):
437
441
all_points = board .points
438
442
taken_points = [index for index , point in enumerate (all_points )
439
443
if point [player ] > 0 ]
444
+ if board .checkers_at_home (player ) == 1 :
445
+ return [(taken_points [0 ], )]
440
446
moves = list (itertools .permutations (taken_points , 2 ))
441
447
moves = moves + [(index , index ) for index , point in enumerate (all_points )
442
448
if point [player ] >= 2 ]
@@ -446,11 +452,11 @@ def display(self, state):
446
452
"""Display state of the game."""
447
453
board = state .board
448
454
player = state .to_move
455
+ print ("Current State : " )
449
456
for index , point in enumerate (board .points ):
450
457
if point ['W' ] != 0 or point ['B' ] != 0 :
451
- print ("Point : " , index , " W : " , point ['W' ], " B : " , point ['B' ])
452
- print ("player : " , player )
453
-
458
+ print ("Point : " , index , " W : " , point ['W' ], " B : " , point ['B' ])
459
+ print ("To play : " , player )
454
460
455
461
def compute_utility (self , board , move , player ):
456
462
"""If 'W' wins with this move, return 1; if 'B' wins return -1; else return 0."""
@@ -482,7 +488,7 @@ def __init__(self):
482
488
self .allow_bear_off = {'W' : False , 'B' : False }
483
489
484
490
def checkers_at_home (self , player ):
485
- """Returns the no. of checkers at home for a player."""
491
+ """Return the no. of checkers at home for a player."""
486
492
sum_range = range (0 , 7 ) if player == 'W' else range (17 , 24 )
487
493
count = 0
488
494
for idx in sum_range :
@@ -516,7 +522,7 @@ def is_legal_move(self, start, steps, player):
516
522
return move1_legal and move2_legal
517
523
518
524
def move_checker (self , start , steps , player ):
519
- """Moves a checker from starting point by a given number of steps"""
525
+ """Move a checker from starting point by a given number of steps"""
520
526
dest = start + steps
521
527
dest_range = range (0 , 24 )
522
528
self .points [start ][player ] -= 1
0 commit comments