class BarMove(object): """ Methods for removing checkers from the Bar. """ def __init__(self, player, die, board, end): self.player = player self.other_player = Board.get_opponent(player) self.die = die self.board = Board(board) # check if end is on the board if not Board.on_board(end): raise IllegalMoveException("End is not on the Board!") else: self.end = end def move_possible(self): """ Checks if""" def make_move(self): """ Validates the movement given the provided board situation. """ if not (self.die == abs(Board.get_home(self.other_player) - self.end)): raise IllegalMoveException("Off-Bar not possible: \ Die cannot be used to perform this movement!") # check if bar is empty and raise error if yes if self.board.get_bar(self.player) == 0: raise IllegalMoveException("Off-Bar not possible: \ No checkers on the Bar!") # check if end position is in the homeboard of the other player # if not raise Error, checkers leaving the bar must be placed in the # homeboard of the opponent (your starting quadrant) if not Board.in_home_board(self.other_player, self.end): raise IllegalMoveException("Off-Bar not possible: \ Checkers must go into the opponents home board!") # check if there is more than one opponent checker at end position # and raise error when yes if self.board.get_checkers(self.end, self.other_player) > 1: raise IllegalMoveException("Off-Bar not possible: \ Location occupied by other player") # now make the movement: # first kick enemy checkers onto the bar if there are any if self.board.get_checkers(self.end, self.other_player) == 1: self.board.remove_from_location(self.other_player, self.end) self.board.move_to_bar(self.other_player) self.board.remove_from_bar(self.player) self.board.move_to_location(self.player, self.end) # update move history of the board self.board.update_move_history(self.__str__()) return self.board def __str__(self): """ Returns string representation of this movement. """ return "bar --> %s" %(self.end + 1) def __eq__(self, other): """ Returns whether this movement is equal to the provided object. """ if isinstance(other, BarMovement): return other.end == self.end else: return False def __ne__(self, other): return not self == other
class BearOffMove(object): """ Methods for bearing off a checker. """ # rules for bear-off: # - all checkers must be in the homeboard of a color (end area) # - endboard numbered 1...6 with 1 closest to end of gameboard # and 6 closest to bar # - roll a 1, bear off checker from 1 # - roll a 6, bear off checker from 6 # - if no checker at rolled position in homeboard, make legal move # within the homeboard # - when number is rolled that is higher than the highest point with checkers, # bear off next highest checker def __init__(self, player, die, board, start): self.player = player self.die = die self.board = Board(board) if not Board.on_board(start): raise IllegalMoveException("Start is not on the board!") else: self.start = start def can_use(self): """ Returns whether or not this movement can use the given dice roll to perform its movement. """ if self.die == abs(self.start - Board.get_home(self.player)): return True # if no checker in rolled number, the player is required to remove # a checker from the highest point elif self.die > abs(self.start - Board.get_home(self.player)): direction = Board.get_direction(self.player) # check if there are no other checkers left to start point # loop from start towards the bar for i in range(self.start - direction, Board.get_home(self.player) \ - (7 * direction), - direction): if self.board.get_checkers(i, self.player) > 0: return False return True else: return False def make_move(self): """ Validates this movement given the provided board situation. """ if not self.can_use(): raise IllegalMoveException("Bear-off not possible: \ Cannot use dice for this movement!") if self.board.get_checkers(self.start, self.player) == 0: raise IllegalMoveException("Bear-off not possible: \ No checkers at location!") if self.board.get_bar(self.player) > 0: raise IllegalMoveException("Bear-off not possible: \ Checkers from the bar must be moved first!") # loop over whole board and check whether all checkers are in the homeboard # if not all checkers are in the homeboard, bear-off is NOT allowed for i in range(Board.NUM_POINTS): if (self.board.get_checkers(i, self.player) > 0) and \ (not Board.in_home_board(self.player, i)): raise IllegalMoveException("Bear-off not possible: \ Still checkers outside of the home board!") # now make the move self.board.remove_from_location(self.player, self.start) self.board.move_off(self.player) # update move history of the board self.board.update_move_history(self.__str__()) return self.board def __str__(self): """ Returns string representation of this movement. """ return "%s --> off" %(self.start + 1) def __eq__(self, other): """ Returns whether this movement is equal to the provided object. """ if isinstance(other, BearOffMovement): return other.start == self.start else: return False def __ne__(self, other): return not self == other
class NormalMove(object): """ Methods for a normal movement. """ def __init__(self, player, die, board, start, end): self.player = player self.other_player = Board.get_opponent(player) self.die = die self.board = Board(board) if (not Board.on_board(start)) or (not Board.on_board(end)): raise IllegalMoveException("Start or end is not on the board!") else: self.start = start self.end = end def make_move(self): """ Validates this movement given the provided board situation. """ if not (self.die == abs(self.start - self.end)): #print "make_move2" raise IllegalMoveException("Normal move not possible: \ Cannot use die for this movement!") if self.start == self.end: raise IllegalMoveException("Normal move not possible: \ Start and end must not be the same position!") if abs(self.start - self.end) > Dice.MAX_VALUE: raise IllegalMoveException("Normal move not possible: \ Move distance larger than 6!") if self.board.get_bar(self.player) > 0: raise IllegalMoveException("Normal move not possible:: \ Checkers from the bar must be moved first!") if self.board.get_checkers(self.start, self.player) == 0: raise IllegalMoveException("Normal move not possible: \ No checkers at the start location!") if ((self.start > self.end) and (Board.get_direction(self.player) > 0) or (self.start < self.end) and (Board.get_direction(self.player) < 0)): raise IllegalMoveException("Normal move not possible: \ Backward movements are not allowed!") if self.board.get_checkers(self.end, self.other_player) > 1: raise IllegalMoveException("Normal move not possible: \ End location already occupied by opponent checkers!") # now perform movement: # check first whether the move bumps the opponent if self.board.get_checkers(self.end, self.other_player) == 1: self.board.remove_from_location(self.other_player, self.end) self.board.move_to_bar(self.other_player) # now perform the move self.board.remove_from_location(self.player, self.start) self.board.move_to_location(self.player, self.end) # update move history of the board self.board.update_move_history(self.__str__()) return self.board def __str__(self): """ Returns a String representation of this movement. """ return "%s --> %s" %(self.start + 1, self.end + 1) def __eq__(self, other): """ Returns whether this movement is equal to the provided object. """ if isinstance(other, NormalMovement): return (other.start == self.start) and (other.end == self.end) else: return False def __ne__(self, other): return not self == other