Previous Lecture |
Top Level
How to Finish the Monopoly Engine
Contents
Next Section |
Contents
What do we already have?
Constructing large programs is generally accomplished in three steps:
- Build Foundation:
- If you look at the
class hierarchy, you can consider all
non-terminal nodes of the tree to be part of the foundation. These
classes are not specific to the monopoly project and could be used for
any other project. You couldn't tell, just by looking at those
classes, that you are actually building a monopoly engine.
One the other hand, we did make some decisions on which kind
of foundation class to use, based on our later intended usage. For
example, we chose to use linked lists instead of arrays. We chose to
use a specific implementation of smart pointers.
- Build Framework
- The terminal nodes of the
class hierarchy are specific to our
monopoly project. At this stage, though, we kept the implementation of
several member functions open and restricted ourselves to function
stubs, to be filled out later.
For example, the Space object has two functions,
pass() and stop() which are to be called whenever we
pass or stop in the space. As you can see, the first
implementation of Space::pass()
and Space::stop() simply print out debugging information.
- Fill in Framework
- The final step in constructing large
programs consists of filling in the function stubs defined in the
previous phase.
At the end of Change 26, we are just
about finished with the framework building phase and may begin with
the filling in phase.
Next Section |
Previous Section
Which objects are still missing?
Although we now have all the objects required to represent the
state of a monopoly game, we still need some objects to
specify the possible actions of the players. Obviously, we
will stick to the now well established scheme and start by defining
Action and derivatives thereof. We will then put those
actions in a list (ActionList) and process this list at some
stage:
Here are some actions that come to my mind:
- ClaimRentAction
- A player notices that the current player is on his
property. You simply take the money.
- BuyDeedAction
- The current player buys the property he is on.
- BidDeedAction
- In case of an auction, the highest bidding player takes the property.
- PayBailAction
- Pay bail to exit from the jail.
- FreeJailCardAction
- Get out of jail using a saved chest or chance card.
- GivePlayerMoneyAction
- A player gives the current player money.
- MortgageAction
- Mortgage property.
- UnmortgageAction
- Repay mortgage.
- BuildHouseAction
- Build a house on a property.
- SellHouseAction
- Sell houses.
- GivePlayerDeedAction
- A player gives a deed to the current player.
This is probably not a complete list, but should give you an idea...
Contents |
Previous Section
How do we make it work?
When talking about actions, think of player
decisions. Obviously, in a real monopoly game, people do a lot of
things but don't really get a choice. For example, rolling dice is not
an action, nor is moving your piece, nor is taking a card and
following those instructions. All these things can be done
automatically.
The moment we need player actions is when we run out of
things to do automatically. So, when we start our monopoly engine, the
first thing we do is process the player actions, then process all the
automatic stuff like rolling dice, moving pieces etc... The engine
terminates if we run out of things to do. The main program of the
finished monopoly engine should look something like this:
#include <Game.h>
#include <ActionList.h>
main()
{
Game game;
ActionList actions;
game.read();
actions.read();
actions.execute(); // call the execute() member functions
// of all the actions in the list.
game.execute(); // do the automatic stuff
game.write();
}
The actions are pretty much self contained. A little thought is
required for the Game::execute() function. Here is a possible sequence
of events:
- Check for Bankruptcy
- If, after all the actions have been processed, a player has a
negative account, it is assumed that the player failed to raise enough
money to pay his debts. His properties revert back to the bank, any
houses that for some reason remain on the property disappear, any
cards the player holds are discarded and the player is deleted from
the player loop. If only one player remains, he has won and the game is
over.
- Determine Current Player
- If there is no current player, the game is just
beginning. Shuffle the cards and choose a player at random. If the
last roll was a double, or if the current player just got out of jail,
keep the current player, otherwise select the next player.
- Roll Dice
- Put the player into prison if this is his 3rd consecutive double
and proceed immediatly to the next player.
- Move Player
- If the current player is in prison, only move him if he rolls a
double. Call the Space::pass() and Space::stop() functions while you
move. Some of these functions may trigger another movement...
One thing to watch out for is when to stop. For example, if a player
rolls a double, you cannot simply let him move twice, as players might
want to act between the two moves. This is why we have step two in the
list above.
Remember that this is just a suggestion, and now that the graded
project work is over, you may feel free to adopt any line you
want.
Most important: Happy Coding - It's supposed to be fun!
Previous Lecture |
Contents
Christian Goetze