Assignment due March 14, 11:15pm (PST)
Checkers is a two-person board game played on an 8×8 game board (same as chess board). Each player places their 12 pieces (usually red vs black) on the board on alternating dark squares in the three rows nearest to themselves. (See the following picture).
– Both players start the game with 12 pieces each, all sitting on black squares (as close to player as possible)
– At the start of the game, all pieces are “pawns”, and can only move forward (away from their owner/player) by 1 diagonal space (on dark squares) at a time, toward the opponent’s side of the board.
– If a piece player’s piece is directly adjacent to an opponent’s piece, it _may_ be able to “capture” the opponent’s piece.
– A piece can _only_ jump an opponent’s piece when the pieces are “diagonally adjacent”, and the following space in the forward direction is unoccupied. Only one piece can be captured per jump; however, multiple jump may be performed sequentially during a single turn, provided the condition of diagonal adjacency is met.
– Any time a move exists on the board where an opponent’s piece can be captured, the player is required to jump and capture the piece.
## The `Game` Class
It’s essential that you understand the simple interface provided by the `Game` class. It only offers a few methods for interacting with the game itself. The first three methods let you get information about the current game. Call the last method to inform the game about your move decision.
virtual size_t countAvailablePieces(PieceColor aColor)=0;
virtual const Piece* const getAvailablePiece(PieceColor aColor, int anIndex)=0;
virtual const Tile* const getTileAt(const Location &aLocation)=0;
virtual bool movePieceTo(const Piece &aPiece, const Location &aLocation)=0;
### `countAvailablePieces(PieceColor aColor)`
This method tells you how many pieces of a given color remain on the board. You might use this to control a while while analyzing options for each of your pieces on the board.
### `getAvailablePiece(PieceColor aColor, int anIndex)`
This method retrieves the **Nth** _remaining_ piece of a given color that remains on the board. The game is free to return to pieces to you in any order.
### `getTileAt(const Location &aLocation)`
This method retrieves a `Tile` object for you to inspect. Each tile knows the tile color, the location (row,col), and which `Piece` (if any) is occupying the `Tile`.
When you are considering a move, you may call the `Game` to retrieve a `Tile` you are considering. If you ask for a `Tile` at a `Location` that does not exist, this method will return a `nullptr`.
### `movePieceTo(const Piece &aPiece, const Location &aLocation)`
Call this method when you have completed your analysis and are ready to tell the game the destination (`Location`) where you want to move on of your `Piece`’s. As we mention else where, if you are doing a multi-jump, you may call this method more than once. Calling this method at any time when you _aren’t_ performing a multi-jump will disqualify your bot from the game.
### Running the game
The `Game` class we provided to you is responsible for running the game. Each player gets a turn to analyze the board, and make a move decision. Between each move, current state of the board is displayed for reference. As sample is shown below. Notice that board contains pieces marked “b” and “g”. A piece is capitalized (“B”,”G”) to indicate that piece has been “kinged” and can move more freely.
0 | . | . | . | . | . | . | . | . |
1 | . | . | . | . | . | . | . | . |
2 | . | . | . | . | . | B | . | . |
3 | . | . | . | . | . | . | g | . |
4 | . | . | . | . | . | . | . | . |
5 | . | . | . | . | . | . | . | . |
6 | . | . | . | . | . | g | . | g |
7 | G | . | . | . | . | . | G | . |
0 1 2 3 4 5 6 7
## Your Challenge
So far, all of your programming assignments have involved building classes that collectively solve a given problem. This assignment is a little different, because your solution must “plug-in” to an existing framework. Framework-oriented solutions are commonplace in the professional world, and you’ll surely encounter many of them during your career. In a framework-oriented solution, the _framework_ is responsible for overall control of the process, and your code plugs into the framework to help make decisions as necessary. This is referred to as an “inversion of control”.
In this challenge, you (and a partner if you so choose) will implement a “checker-bot” class that competes in a game of Checkers. During the course of play, your checker-bot will be given alternating “turns” to move one game piece on the board. Gameplay will continue until a terminal condition occurs:
1. A checker-bot wins the game if it can eliminate all the opponents pieces from the board
2. A checker-bot forfeits the game by making an illegal move, or when it’s detected trying to cheat
3. A checker-bot forfeits if it takes too long to decide which move to make
#### Hey, This sounds HARD — this isn’t an AI class!
Yeah, you’re right, we haven’t taught you any AI techniques. So your checker-bot is NOT expected (or permitted) to use any form of machine learning, neural-net, or other technique found in the AI playbook. Still, a clever algorithm and well-chosen data structure can help to win the game. Note: for those of you so inclined, you are not prevented from developing your own AI algorithms from scratch. Who knows, you may even invent a cool new technique. 🙂
In order to successfully complete this challenge — your checker-bot must, at a minimum, correctly apply the rules of the game, and successively choose a valid piece per turn, and indicate a valid move within the time limit. A trivial solution would merely move any available piece to the first valid (unoccupied) square. You won’t likely win, but your checker-bot will meet the minimum requirements.
Just so you don’t panic — it’s been shown that a trivial (and rather dumb) implementation of the `Player` class can be written in under 100 lines of code. Most of the time you spending on this project will involve determining the _best_ piece to moved, whether to perform a jump (if required), and the possible board location destination(s) where the piece will come to rest.
## Implementation Details
This game is an example of the `Inversion of Control` design pattern. Unlike most of the code you write — you are not in control of the main loop of this game. Your `Player` will get called each time it is your turn to move.
1. You will build a subclass of Player. Your class **must** be named after you. In my case, it’s RickgPlayer.
2. In the main.cpp file (provided), you create two instances of your player, and pass it to the `Game->run(p1,p2)` method.
3. Your checker-bot will be called alternatively against an opponent (during your testing, you’ll compete against yourself)
4. Your checker-bot will decide what to do, and tell the game engine your decision by calling `movePieceTo()`.
5. If your code is smart enough, you can execute a “double-jump” if your opponent’s pieces are exposed for such a maneuver.
6. You may **NOT** alter any file in the assignment other than your own `Player` files, without expressed permission.
7. You may **NOT** attempt to directly alter properties of any `Piece` or `Tile` on the board. Changes are made by calls to the `movePieceTo()` method.
During each your turn, your `Player::takeTurn(Game &aGame)` method will be called. You will have a limited amount of time to identify and indicate your move decision.
> NOTE: While we appreciate the hacker ethic and acknowledge the joy of defeating a dumb game engine, any checker-bot caught trying to cheat will be dealt with approprirately. Most likely, the checker-bot will be forced to work eternally as embedded code at a McDonald’s restaurant drive-through window. In other words, if your checker-bot intends to cheat, make sure it does _not_ get caught.