CS 204: Software Design
Due 9:50AM Monday, 11 October 2010
You may work with a partner for this assignment.
Implementing part of the Mancala engine
See the previous assignment for a description
of the context of this assignment.
Your job for this assignment will be to implement the
move
method described in the following MancalaBoard class, and the PyUnit
test infrastructure described in the listing below it. On Monday, we will
meet in the lab and run your implementation
against everybody else's test cases to see if we can find and fix
problems in your program.
'''
mancala.py
This file contains a rudimentary Mancala engine (the
MancalaBoard class) and lots of Exception subclasses for
use by MancalaBoard.
'''
class MancalaException(Exception):
def __init__(self):
self.errorMessage = ''
def __str__(self):
return self.errorMessage
class WrongPlayerError(MancalaException):
def __init__(self, playerNumber):
self.errorMessage = 'Player moving out of turn'
self.playerNumber = playerNumber
class BinIndexOutOfRangeError(MancalaException):
def __init__(self, binNumber):
self.errorMessage = 'Bin number out of range'
self.binNumber = binNumber
class AttemptToMoveFromEmptyBinError(MancalaException):
def __init__(self, binNumber):
self.errorMessage = 'Attempt to move from empty bin'
self.binNumber = binNumber
class AttemptToMoveFromStoreError(MancalaException):
def __init__(self, binNumber):
self.errorMessage = 'Attempt to move from store'
self.binNumber = binNumber
class GameAlreadyOverError(MancalaException):
def __init__(self):
self.errorMessage = 'Game over'
class MancalaBoard:
def __init__(self):
self.reset()
def reset(self):
'''Initializes the board to the starting game state.
Bins 0-5 are Player 1's bins, bin 6 is Player 1's store
(i.e. the big bin), bins 7-12 are Player 2's bins, and
bin 13 is Player 2's store.'''
self.bins = [3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0]
self.isFirstPlayerTurn = True
def move(self, binIndex):
'''If the move starting in the specified bin index is legal,
this method adjusts the game state accordingly.
If the move specified by binIndex is not legal, this
method will raise one of the following types of exception:
to one of the following:
GameAlreadyOverError
BinIndexOutOfRangeError
WrongPlayerError
AttemptToMoveFromStoreError
AttemptToMoveFromEmptyBinError
as described in the test-cases assignment.
Player 1 owns bins 0-6, and Player 2 owns bins 7-13.
Thus, a move from bin 6 is AttemptToMoveFromStore,
not WrongPlayer.
'''
pass
Here's a framework for the PyUnit test program. Here, we're assuming
that the test cases as described in the previous assignment are stored
in a text file called scenarios.txt.
import unittest
from mancala import *
class Scenario:
def __init__(self, scenarioText):
# Use the scenarioText (i.e. one line of the
# scenarios.txt file) to initialize the following
# instance variables.
self.moves = a list of the bin/move numbers from the scenario
self.errorName = the name of the resulting error code
self.finalBins = a list of how the bins look at the end of the case
self.comment = the scenario's comment
class MancalaTest(unittest.TestCase):
def setUp(self):
self.board = MancalaBoard()
self.scenarioList = a list of the Scenario objects
extracted from scenarios.txt
def tryMoves(self, listOfMoves):
''' You may find it helpful to use this utility method. '''
for move in listOfMoves:
self.board.move(move)
def testNoError(self):
pass
def testWrongPlayer(self):
'''Something like this:'''
for scenario in self.scenarioList:
if this scenario is a WrongPlayer scenario:
call self.tryMoves on the list of moves in the scenario
and check to make sure it raises a WrongPlayerError
exception.
Don't forget to call self.board.reset() here or you'll be sad.
def testGameAlreadyOver(self):
pass
def testAttemptToMoveFromStore(self):
pass
def testAttemptToMoveFromEmptyBin(self):
pass
if __name__ == '__main__':
unittest.main()