@@ -42,39 +42,40 @@ def min_value(state):
4242# ______________________________________________________________________________ 
4343
4444def  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 
4646	includes chance nodes along with min and max nodes. [Figure 5.11]""" 
4747    player  =  game .to_move (state )
4848
49-     def  max_value (state ):
50-         if  game .terminal_test (state ):
51-             return  game .utility (state , player )
49+     def  max_value (state , dice_roll ):
5250        v  =  - infinity 
5351        for  a  in  game .actions (state ):
5452            v  =  max (v , chance_node (state , a ))
53+             game .dice_roll  =  dice_roll 
5554        return  v 
5655
57-     def  min_value (state ):
58-         if  game .terminal_test (state ):
59-             return  game .utility (state , player )
56+     def  min_value (state , dice_roll ):    
6057        v  =  infinity 
6158        for  a  in  game .actions (state ):
6259            v  =  min (v , chance_node (state , a ))
60+             game .dice_roll  =  dice_roll 
6361        return  v 
6462
6563    def  chance_node (state , action ):
6664        res_state  =  game .result (state , action )
65+         if  game .terminal_test (res_state ):
66+             return  game .utility (res_state , player )
6767        sum_chances  =  0 
6868        num_chances  =  21 
6969        dice_rolls  =  list (itertools .combinations_with_replacement ([1 , 2 , 3 , 4 , 5 , 6 ], 2 ))
7070        if  res_state .to_move  ==  'W' :
7171            for  val  in  dice_rolls :
7272                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 )
7475        elif  res_state .to_move  ==  'B' :
7576            for  val  in  dice_rolls :
7677                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 )
7879        return  sum_chances  /  num_chances 
7980
8081    # Body of expectiminimax: 
@@ -403,6 +404,8 @@ def actions(self, state):
403404        """Returns a list of legal moves for a state.""" 
404405        player  =  state .to_move 
405406        moves  =  state .moves 
407+         if  len (moves ) ==  1  and  len (moves [0 ]) ==  1 :
408+             return  moves 
406409        legal_moves  =  []
407410        for  move  in  moves :
408411            board  =  copy .deepcopy (state .board )
@@ -414,10 +417,11 @@ def result(self, state, move):
414417        board  =  copy .deepcopy (state .board )
415418        player  =  state .to_move 
416419        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 )
418422        to_move  =  ('W'  if  player  ==  'B'  else  'B' )
419423        return  GameState (to_move = to_move ,
420-                          utility = self .compute_utility (board , move , to_move ),
424+                          utility = self .compute_utility (board , move , player ),
421425                         board = board ,
422426                         moves = self .get_all_moves (board , to_move ))
423427
@@ -437,6 +441,8 @@ def get_all_moves(self, board, player):
437441        all_points  =  board .points 
438442        taken_points  =  [index  for  index , point  in  enumerate (all_points )
439443                        if  point [player ] >  0 ]
444+         if  board .checkers_at_home (player ) ==  1 :
445+             return  [(taken_points [0 ], )]
440446        moves  =  list (itertools .permutations (taken_points , 2 ))
441447        moves  =  moves  +  [(index , index ) for  index , point  in  enumerate (all_points )
442448                         if  point [player ] >=  2 ]
@@ -446,11 +452,11 @@ def display(self, state):
446452        """Display state of the game.""" 
447453        board  =  state .board 
448454        player  =  state .to_move 
455+         print ("Current State : " )
449456        for  index , point  in  enumerate (board .points ):
450457            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 )
454460
455461    def  compute_utility (self , board , move , player ):
456462        """If 'W' wins with this move, return 1; if 'B' wins return -1; else return 0.""" 
@@ -482,7 +488,7 @@ def __init__(self):
482488        self .allow_bear_off  =  {'W' : False , 'B' : False }
483489
484490    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.""" 
486492        sum_range  =  range (0 , 7 ) if  player  ==  'W'  else  range (17 , 24 )
487493        count  =  0 
488494        for  idx  in  sum_range :
@@ -516,7 +522,7 @@ def is_legal_move(self, start, steps, player):
516522        return  move1_legal  and  move2_legal 
517523
518524    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""" 
520526        dest  =  start  +  steps 
521527        dest_range  =  range (0 , 24 )
522528        self .points [start ][player ] -=  1 
0 commit comments