Code Samples
//**********************************************************************************
//**********************************************************************************
// DEMO CODE
//
// Demonstrates Object-Oriented Design using C++
// Written January 20, 2002 by C.Stewart
//
//**********************************************************************************
//**********************************************************************************
//
//
class Unit
{
// A unit is a 'playing piece' in a strategic simulation war game. It is a base class containing attributes
// common to all unit types. Classes derived from Unit represent the various unit types such as infantry, // armor, fighter, submarine, etc.
public:
Unit( ); // Default constructor
Unit( const Unit& ); // Copy constructor
Unit& operator = ( const Unit& ); // Assignment operator
~Unit( ); // Destructor
// ******** Member functions ********
int getUnitNumber( ) const;
void setUnitNumber( int );
int getUnitType( ) const;
void setUnitType( int );
int getCost( ) const;
void setCost( int );
int getInitMovePoints( ) const;
void setInitMovePoints( int );
int getCurrMovePoints( ) const;
void setCurrMovePoints( int );
int getAttackValue( ) const;
void setAttackValue( int );
int getDefenseValue( ) const;
void setDefenseValue( int );
int getMovedCombat( ) const;
void setMovedCombat( int );
int getAttackStatus( ) const;
void setAttackStatus( int );
landTerr* getLandTerr( );
void setLandTerr( landTerr* );
seaZone* getSeaZone( );
void setSeaZone( seaZone* );
private:
// ******** Member Data ********
int unit_number; // Identifies this unit
int unit_type; // Infantry, armor, fighter, etc.
int unit_cost; // How much the unit costs
int init_move_points; // Initial movement points
int curr_move_points; // Updated with movement
int attack_value; // Value unit attacks with
int defense_value; // Value unit defends with
flag moved_combat; // If true, no non-combat movement
flag attack_status; // Attacking, defending, or neither
landTerr *land_terr; // The land territory the unit is in; 0 if not
seaZone *sea_zone; // The sea zone the unit is in, 0 if not
List land_terr_list; // Tracks territories entered ( used in retreats )
List sea_zone_list; // Tracks sea zones entered
List land_sea_order; // Tracks order of territories and sea zones
};
// Strategic Simulation Game
//
include "includes.h" // namespace, typedefs, class definitions, etc.
int main( )
{
initialize( );
extern Control control;
while ( !control.game_over )
{
control -> *locator( );
control -> *choice( );
control.screen.render( );
}
return 0;
}
void Control::determine_locator( )
{
// Determines locator when cursor is over the playfield.
switch( logic_table.curr_entry )
{
case LAND_TERRITORY: // enum constant
locator = land_terr_loc; // Function pointer
break;
case SEA_ZONE:
locator = sea_zone_loc;
break;
case UNIT_ICON:
locator = unit_icon_loc;
break;
case SCROLL_ICON;
locator = scroll_icon_loc;
break;
}
}
// Combat Movement Phase land to land movement
//
void Control::landLandCombatMove( )
{
if ( actual_movement ) // Returns 1 if true; updates attempt variables
{
if ( icon_selected )
{
if ( alert && crossover ( ) ) // Only need to make these checks if border is crossed
{
switch ( unit_code ) // Different units have different move criteria
{
case INFANTRY: // enum constant
alert = landLandCombatMove( attempt_land_terr -> infantry_list );
break;
case ARMOR:
alert = landLandCombatMove( attempt_land_terr -> armor_list );
break;
case AAGUN:
alert = landLandCombatMove( attempt_land_terr -> aagun_list );
break;
case FIGHTER:
alert = landLandCombatMove( attempt_land_terr -> fighter_list );
break;
case BOMBER:
alert = landLandCombatMove( attempt_land_terr -> bomber_list );
break;
case FACTORY:
alert = landLandCombatMove( attempt_land_terr -> factory_list );
break;
}
}
}
}
// If there is no icon selected, only move arrow cursor. The physical movement, of course, is done during // the render phase.
if ( !alert )
{
screen.moveCursor( ); // Updates current screen variables
checkLocatorAndChoice( ); // May set menu bar, alert, etc. locator and choice
}
}
// Function to move units from one land region object to another. First it checks if it is possible for each // unit to move. Then, if so, moves the units from active_land_terr's unitList to attempt_land_terr's
// unitList. Finally, it makes the necessary adjustments to all appropriate class objects to indicate a move // was in fact made.
int Control::landLandCombatMove( unitList inf_list )
{
alert = attemptEnemyRegion( );
unitList::iterator it = infantry_list.begin( );
while ( ( !alert ) || ( it != infantry_list.end( ) ) )
{
alert = enoughMovePoints( *it ); // Template function instance
if ( !alert )
alert = withinLimits( *it ); // Template function instance
if ( !alert )
++it;
}
// All units passed if alert equals 0, it is now ok to move
if ( !alert )
infantry_list.moveFriendly( floater ); // Physically moves from one unitList to another
// Everything so far so good; just need to make final adjustments to the necessary class objects to
// indicate changes caused by move
it = infantry_list.begin( ); // Reset iterator to traverse unitList again
while ( it != infantry_list.end( ) )
{
it -> setLandTerr( attempt_land_terr ); // New land territory unit is in
it -> decMovePoints( ); // Decrement move points
it -> setLandTerrList( ); // Update region path used in retreats, etc.
++it;
}
// Finally, update the Control class object members
setPrevLandTerr( active_land_terr );
setActiveLandTerr( attempt_land_terr );
}
bool Control::attemptEnemyLandTerr( )
{
// This function returns 0 if attempt_land_terr is friendly, or 1 if it is an enemy.
// Alliances are determined by the Player.player_number class member. Players of one side have even
// player numbers; players of the other side have odd player numbers. Modulus division is used to
// determine this odd or even status.
int result = 0;
int value1 = ( active_player -> player_number ) % 2;
int value2 = ( attempt_player -> player_number ) % 2;
if ( value1!= value2 )
result = 1;
return result;
}
bool Control::crossover( )
{
// Will movement cross a region border? Return 1 if it does, otherwise 0.
int value = 0;
if ( active_land_terr )
{
if ( active_land_terr != attempt_land_terr )
value = 1;
}
if (active_sea_zone )
}
if ( active_sea_zone != attempt_sea_zone )
value = 1;
}
return value;
}
int infantry::boardTransports( Control& control )
{
// This is the definition of the virtual function used by the infantry class to move infantry units onto
// transports. Three lists are of importance here. The actual infantry units are stored in
// active_land_terr.infantry_list. The transport units are contained in attempt_sea_zone.transport_list. // Each transport in turn contains a list of pointers to the infantry units on the transport. This member
// list is called infantry_ptr_list.
//
// This function basically traverses the same infantry and transport lists twice. Once to see if there are
// actually enough transports to move onto, and again to actually move each unit. The logic works this
// way because the user interface is designed to move a 'stack' of infantry units rather than one at a
// time. Therefore we have to look ahead first to see if there is enough room for the units, and then we // actually move them. If there are not enough transports, an alert value is returned.
//
int alert = 0;
landTerr* source_land_terr = control.active_land_terr;
seaZone* dest_sea_zone = control.attempt_sea_zone;
// First traversal of lists
unitList::iterator it! = source_land_terr -> infantry_list.begin( );
unitList::iterator it2 = dest_sea_zone -> transport_list.begin( );
int onboard_units = it2 -> infantry_ptr_list.count( );
while ( !alert || it1 != source_land_terr -> infantry_list.end( ) )
{
if ( onboard_units -> units_per_transport )
{
++it1;
++onboard_units;
}
else
{
if ( it2 = = dest_sea_zone -> transport_list.end( ) )
{
alert = NOT_ENOUGH_TRANSPORTS; // enum constant
}
else
{
++it2;
onboard_units = it2 -> infantry_ptr_list.count( );
}
}
}
// Second traversal of lists
if ( !alert )
{
it1 = source_land_terr -> infantry_list.begin( ); // reset iterators
it2 = dest_sea_zone -> transport_list.begin( );
int onboard_units = it2 -> infantry_ptr_list.count( );
while ( !alert || it1 != source_land_terr -> infantry_list.end( ) )
{
if ( onboard_units < it1 -> units_per_transport )
{
// Make changes to object members to indicate move
it1 -> transport = it2 -> unit_number; // Infantry knows what transport it's on
it2 -> infantry_ptr_list.add( it1); // Transport knows what infantry is on it
it1 -> setSeaZone( dest_sea_zone ); // Sea zone the unit is now in
it1 -> setLandTerr( 0 ); // No longer on a land territory
it1 -> decMovePoints( ); // Decrement move points
it1 -> sea_zone_list.add( dest_sea_zone ); // Updates region path used in retreats
it1 -> setLandSeaOrder( 1 ); // 1 indicates sea zone
++it1;
++onboard_units;
}
else
{
++it2;
onboard_units = it2 -> infantry_ptr_list.count( );
}
} // End while loop
} // End outer if
return alert
}