Project General Description
For our second project, we will be creating a simplified version of
the game Stratego. If you've never heard of it, that's alright, it's a
board game played between two people, playing with Red and
Blue pieces. The goal of this game is essentially to capture the
enemy's flag or to capture all of the enemy pieces.
However, we will not be implementing this entire game since it's
probably too complicated for a cmsc201 project. So instead we'll
be implementing a simplified version of the game, that I call
Tactego.
Rules of the Game
1. The game of tactego is set up on a board which is a 2d grid of size
length x width which will be specified at the start of the game.
2. The pieces will be specified in a file, which will have lines
indicating the strength of the piece and the number of pieces
with that strength.
3. Players alternate by taking turns.
4. A player selects a piece and then moves that piece.
a. The position the player selects must be one of their pieces,
you must test for this.
b. The position that you select as the destination must be at
most one place away up, down, left, right, or diagonally from
the original position.
c. The position must not contain one of the player's own
pieces.
d. If the destination contains an enemy's piece, then combat
ensues.
e. Flags cannot move.
5. Combat is determined by strength.
a. If a higher strength piece attacks a lower or equal strength
piece then it wins.
b. If a lower strength piece attacks a higher strength piece,
then it loses.
c. If any piece (that can move) attacks a flag, then it captures
that flag.
d. The winner of the combat takes the position that the piece
was moving into.
6. Victory for a player is when the other player has lost all of their
flags.
Design Details and Flow
This is a specification for how the project should be implemented.
1. Get the size of the board.
2. Get the filename with the pieces.
3. Create the board and the pieces, and place them onto the
board randomly as specified here:
a. Use the random.shuffle method on the pieces inputted
from the file in order to randomize placement of the
pieces.
i. If you have a pieces list you can simply do
random.shuffle(pieces) once, for each set of pieces.
b. For the red player, place them at the top of the board,
starting at position (0, 0) and going to (0, width - 1) then
go to the next line (1, 0) and scan across the row. Keep
going in that fashion until all of the pieces have been
placed.
c. For the blue player, place them on the bottom of the
board starting at (length - 1, 0) going up to (length - 1,
width - 1) before resetting to (length - 2, 0) and scanning
across that row. Keep going until all pieces have been
placed.
d. The reason we're specifying this so carefully is so that we
can all use a seed and generate the same placements of
pieces. It will help both you and the graders to be able
to test.
4. Enter the main game loop. Stay in the game loop until one of
the players wins.
5. Draw the board.
6. Get the player's move.
a. A starting position should have two coordinates
separated by a space.
b. Check that the starting position is valid, return to (a) if
not.
c. Then get the ending position also two coordinates
separated by a space.
d. Check if the ending position is valid, return to ( c ) if not.
7. Move the piece.
8. Determine the result of any combat
9. Return to (4) until there is a winning player.
10.Report the player who won and end the game.
Implementation Requirements
1. You must have a main function called tactego:
def tactego(pieces_file, length, width):
2. You must import random in order to use shuffle.
3. Your main block should be:
if __name__ == '__main__':
random.seed(input('What is seed? '))
file_name = input('What is the filename for the pieces? ')
length = int(input('What is the length? '))
width = int(input('What is the width? '))
tactego(file_name, length, width)
This will ensure that we can all have the same placement of
pieces with different random seeds, which determines the
output of the shuffles.
4. Other than tactego, you should implement at least 4
additional functions. Keep in mind that my solution has
approximately 8 functions, so you shouldn't be afraid to
create far more than 5 total. You won't be rewarded for
smashing too much functionality into each function so think
about what the job of each function is and try to have it do
that one job.
5. The only global variables that you have should be constants
(and technically the inputs in main at the beginning of the
program that you send into the tactego function). The game
board, pieces, and all of the other things that you create for
this project should be local to the tactego function. This will
force you to pass them as parameters to the functions that
need that data.
6. Load the pieces from the file in the order that they are given
there, don't sort them or do anything before you run the
shuffle on them. Run shuffle twice, once on the red pieces
then once on the blue pieces in that order.
7. Output the board at least once per turn so that the player can
see what they're doing.
8. Ask for the starting and ending positions in separate input
statements, so that we can maintain consistency for testing.
Pieces File Format
The pieces file format will be like this, each line will take one of
these forms:
1. [piece strength] [number of pieces] for example 7 3 means
that there are 3 pieces with strength 7.
2. F [number of flags] for instance F 1 or F 2 [there is a space
between them]
Coding Standards
Coding standards can be found here.
1. At least one inline comment per function explaining
something about your code.
2. Constants above your function definitions, outside of the "if
__name__ == '__main__':" block.
a. A magic value is a string which is outside of a print or
input statement, but is used to check a variable, so for
instance:
i. print(first_creature_name, 'has died in the fight. ') does not
involve magic values.
ii. However, if my_string == 'EXIT': exit is a magic value since
it's being used to compare against variables within
your code, so it should be:
EXIT_STRING = 'EXIT'
if my_string == EXIT_STRING:
b. A number is a magic value when it is not 0, 1, and if it is
not 2 being used to test parity (even/odd).
c. A number is magic if it is a position in an array, like
my_array[23], where we know that at the 23rd position,
there is some special data. Instead it should be
USERNAME_INDEX = 23
my_array[USERNAME_INDEX]
d. Constants in mathematical formulas can either be made
into official constants or kept in a formula.
3. Previously checked coding standards involving:
a. snake_case_variable_names
b. CAPITAL_SNAKE_CASE_CONSTANT_NAMES
c. Use of whitespace (2 before and after a function, 1 for
readability.)
Forbidden Built-ins/Methods/etc
This is not a complete listing, but it includes:
● break, continue
● methods outside those permitted within allowed types
○ for instance str.endswith
○ list.index, list.count, etc.
● Keywords you definitely don't need: await, as, assert, async,
class, except, finally, global, lambda, nonlocal, raise, try, yield
● The is keyword is forbidden, not because it's necessarily bad,
but because it doesn't behave as you might expect (it's not
the same as ==).
○ The only exception is if you use the python None, you
may use the expressions "x is not None" or "x is None".
● built in functions: any, all, breakpoint, callable, classmethod,
compile, exec, delattr, divmod, enumerate, filter, map, max,
min, isinstance, issubclass, iter, locals, oct, next, memoryview,
property, repr, reversed, round, set, setattr, sorted,
staticmethod, sum, super, type, vars, zip
● If you have read this section, then you know the secret word
is: alacrity.
● exit() or quit()
● If something is not on the allowed list, not on this list, then it
is probably forbidden.
● The forbidden list can always be overridden by a particular
problem, so if a problem allows something on this list, then it
is allowed for that problem.