CIT 591 Assignment 3: Three Musketeers
Fall 2010, David Matuszek

Purposes of this assignment

General idea of the assignment

Write a program to play the game of Three Musketeers--human against computer.

You have probably never heard of this game. That's okay, the rules are simple--that's why I chose it. The link above is to a Wikipedia article that explains the game, and I can answer questions if necessary. It also happens to be a pretty good game.

The human should be able to choose which side to play: the Musketeers, or Cardinal Richelieu's men. Once chosen, the human plays the same side for the entire game. The Musketeers always move first.

After each move--computer or human--the program should print out the new game board. This could be just a display of the pieces, or it could be a display with rows and columns labeled in some fashion. For example, you might print the board like one of these:

R R R R M
R R R R R
R R M R R
R R R R R
M R R R R
    A B C D E
  -----------
1 | R R R R M
2 | R R R R R
3 | R R M R R
4 | R R R R R
5 | M R R R R
    1 2 3 4 5
  -----------
1 | R R R R M
2 | R R R R R
3 | R R M R R
4 | R R R R R
5 | M R R R R

In addition, after each move, you should print a message telling what piece moved where. Don't make the user compare two game boards to figure out what just happened.

It's up to you and your partner to figure out the best way for the human to enter moves. When the program is run, it must explain how to enter moves; do this once, when the game is first started. If we can't figure out how to enter moves, when we grade your program, you will lose points. The easier it is to use your program, the more fun it will be to play.

Of course, the computer should prevent the human from making illegal moves. It should also tell when the game is over, and who won.

Details

Since we will be calling your methods with our own testing methods, it is essential that you follow these instructions exactly.

The "board" will be represented as a list of five lists; each of these lists represents a row, and each list contains five elements. The first list represents the first row; the first element in each list represents the first column. The values in the list must each be one of three things: an 'M', representing a Musketeer, an 'R', representing one of Cardinal Richelieu's men; and a '-', representing an empty space.

Directions will be given as one of the four strings 'left', 'right', 'up', and 'down'.

def create_board():
returns: A list of five 5-element sublists.
Creates and returns the initial board. Specifically, it should return [['R', 'R', 'R', 'R', 'M'], ['R', 'R', 'R', 'R', 'R'], ['R', 'R', 'M', 'R', 'R'], ['R', 'R', 'R', 'R', 'R'], ['M', 'R', 'R', 'R', 'R']]. The first sublist is regarded as the "top" row of the board, and the 'M' in it is in the righthand column.

def new_location(row, column, direction):
returns: A (row, column) tuple.
Given a row and column, return the tuple (new_row, new_column) that results from moving in the given direction. No error checking is done, so it is possible for this function to return an illegal location.

def is_legal_move(row, column, direction, board):

returns: True or False.
Tests if the piece in the given row, column, can move in the given direction, and returns True if the move is legal. A move is legal if: Other possibilities, such as moving off the edge of the board, or moving from a location that does not contain a piece, will cause False to be returned.

def has_legal_move(who, board):
returns: True or False.
Tests whether a legal move exists for player "who" (which must be either 'M' or 'R'). Does not provide any information on where the legal move is, if one exists.

def make_move(row, column, direction, board):
returns: A board (a list of five 5-element sublists) .
Moves the piece in board[row][column] in the indicated direction, and returns the modified board. The move is assumed to be legal (you should call is_legal_move before calling this function).

def choose_musketeer_move(board):

returns: The tuple (row, column, direction).
Decides on a move for the Musketeers (you should have previously checked that there is a legal move). Returns the row and column containing the Musketeer that should move, and the direction in which he should move. This function does not actually move the Musketeer (you have another function for that).

def choose_enemy_move(board):
returns: The tuple (row, column, direction).
Decides on a move for Cardinal Richlieu's men (you should have previously checked that there is a legal move). Returns the row and column containing the man that should move, and the direction in which he should move. This function does not actually move the man (you have another function for that).

def is_enemy_win(board):
returns: True or False.
Returns True if the Musketeers are all in the same row, or all in the same column, and False otherwise.

Note: The Musketeers win if they have no legal move and it is their turn.

def start():

returns: None.
This function starts the game. Use this and any additional methods to print instructions, print the board initially and after each move, tell who moved where, tell when the game ends and who won, etc. Please don't try to cram all this into one function; remember, a lot of little, well-named functions is much better than one great big function.

Additional constraints:

The computer does not have to play a great game--it does have to play legally. If you would like to implement a simple strategy (rather than just make random moves), here's a start:

Again, don't spend any more time than necessary on strategy until after the program is working.

Grading

Here's what we will be looking for when we grade your program:

Due date

Turn your assignment in to Blackboard before midnight Thursday, September 30. This is a pair programming assignment, so you should decide which of you will turn it in (we don't want to grade two copies of the same program). Be sure to put both of your names in a comment right at the top of the program.