Beispiel #1
0
//------- Begin of function FirmHarbor::assign_unit -----------//
//
void FirmHarbor::assign_unit(int unitRecno)
{
	//------- if this is a construction worker -------//

	if( unit_array[unitRecno]->skill.skill_id == SKILL_CONSTRUCTION )
	{
		set_builder(unitRecno);
		return;
	}

	//---------------------------------------//

	//if( ship_count==MAX_SHIP_IN_HARBOR )
	//	return;
	if(ship_count + (build_unit_id>0) == MAX_SHIP_IN_HARBOR)
		return; // leave a room for the building unit

	add_hosted_ship(unitRecno);

	unit_array[unitRecno]->deinit_sprite();

	UnitMarine *unitPtr = (UnitMarine*) unit_array[unitRecno];
	unitPtr->extra_move_in_beach = NO_EXTRA_MOVE;
	unitPtr->deinit_sprite();

	//------------------------------------------------//

	if( firm_array.selected_recno == firm_recno )
		info.disp();
}
Beispiel #2
0
//-------- Begin of function Nation::ai_sea_travel -------//
//
// action_x_loc, action_y_loc - location of the destination
//
// group_unit_array - array of units that will do the sea travel
// instance_count - no. of units in the array
//
// action_para  - the action of units after they have arrived the region,
//					   it is one of the following:
//
// SEA_ACTION_SETTLE		 	  - settle into a town
//	SEA_ACTION_BUILD_CAMP 	  - build and assign to a firm
//	SEA_ACTION_ASSIGN_TO_FIRM - assign to a firm
//	SEA_ACTION_MOVE			  - just move to the destination
//								 	    (this include moving to the location of a battle field.)
//
//---------------------------------------------//
//
// Procedures:
// * 1. Locate a ship, build one if cannot locate any.
// * 2. Assign the units to the ship.
//   3. Move the ship to the destination region.
//   4. Units disembark on the coast.
//   5. Units move to the destination.
//
// This function deal with the 1st and 2nd procedures,
// when they are finished, action ACTION_AI_SEA_TRAVEL2
// will be added.
//
//---------------------------------------------//
//
int Nation::ai_sea_travel(ActionNode* actionNode)
{
	err_when( actionNode->instance_count < 1 ||
				 actionNode->instance_count > ActionNode::MAX_ACTION_GROUP_UNIT );

	Unit* unitPtr = unit_array[actionNode->group_unit_array[0]];

	err_when( unitPtr->nation_recno != nation_recno );
	err_when( !unitPtr->is_visible() );

	//---- figure out the sea region id which the ship should appear ----//

	int unitRegionId = world.get_region_id(unitPtr->next_x_loc(), unitPtr->next_y_loc());
	int destRegionId = world.get_region_id(actionNode->action_x_loc, actionNode->action_y_loc);

	int seaRegionId = region_array.get_sea_path_region_id(unitRegionId, destRegionId);

	//------- 1. try to locate a ship --------//

	int shipUnitRecno = ai_find_transport_ship(seaRegionId, unitPtr->next_x_loc(), unitPtr->next_y_loc());

	if( !shipUnitRecno )
		return -1;					// must return -1 instead of 0 as the action must be executed immediately otherwise the units will be assigned with other action and the unit list may no longer be valid

	//---- if this ship is in the harbor, sail it out ----//

	UnitMarine* unitMarine = (UnitMarine*) unit_array[shipUnitRecno];

	if( unitMarine->unit_mode == UNIT_MODE_IN_HARBOR )
	{
		FirmHarbor*	firmHarbor = (FirmHarbor*) firm_array[unitMarine->unit_mode_para];

		firmHarbor->sail_ship(unitMarine->sprite_recno, COMMAND_AI);
	}

	if( !unitMarine->is_visible() )		// no space in the sea for placing the ship 
		return -1;

	//------ 2. Assign the units to the ship -------//

	unitMarine->ai_action_id = actionNode->action_id;

	err_when( unit_res[unitMarine->unit_id]->unit_class != UNIT_CLASS_SHIP );

	// ##### patch begin Gilbert 5/8 #######//
	unit_array.assign_to_ship(unitMarine->next_x_loc(), unitMarine->next_y_loc(), 0, actionNode->group_unit_array, actionNode->instance_count, COMMAND_AI, unitMarine->sprite_recno );
	// ##### patch end Gilbert 5/8 #######//

	for( int i=0 ; i<actionNode->instance_count ; i++ )
		unit_array[ actionNode->group_unit_array[i] ]->ai_action_id = actionNode->action_id;

	actionNode->instance_count++;		// +1 for the ship

	actionNode->processing_instance_count = actionNode->instance_count-1;		// -1 because when we return 1, it will be increased by 1 automatically
	actionNode->action_para2 = 0;		// reset it, it is set in Nation::action_finished()

	return 1;
}
Beispiel #3
0
//--------- Begin of function UnitArray::update_selected_trade_unit_info ---------//
// update trade information of trading units if these units are selected
//
void UnitArray::update_selected_trade_unit_info()
{
	short playerNationRecno = nation_array.player_recno;

	Unit *unitPtr;
	UnitMarine *marinePtr;
	if(remote.is_enable())
	{
		for(int i=size(); i>0; --i)
		{
			if(is_deleted(i))
				continue;

			unitPtr = (Unit*)get_ptr(i);
			if(!unitPtr->is_visible())
				continue;

			switch(unitPtr->unit_id)
			{
				case UNIT_CARAVAN:
						if(mp_is_selected_caravan(i))
							((UnitCaravan*) unitPtr)->update_stop_and_goods_info();
						break;

				case UNIT_VESSEL: case UNIT_CARAVEL: case UNIT_GALLEON:
						marinePtr = ((UnitMarine*) unitPtr);
						if(marinePtr->auto_mode && mp_is_selected_ship(i))
							marinePtr->update_stop_and_goods_info();
						break;

				default: break;
			}
		}
	}
	else if(selected_recno && !is_deleted(selected_recno))
	{
		unitPtr = (Unit*)get_ptr(selected_recno);
		if(unitPtr->nation_recno==playerNationRecno || config.show_ai_info)
		{
			switch(unitPtr->unit_id)
			{
				case UNIT_CARAVAN:
					((UnitCaravan*) unitPtr)->update_stop_and_goods_info();
					break;

				case UNIT_VESSEL: case UNIT_CARAVEL: case UNIT_GALLEON:
					marinePtr = ((UnitMarine*) unitPtr);
					if(marinePtr->auto_mode)
						marinePtr->update_stop_and_goods_info();
					break;

				default:
					break;
			}
		}
	}
}
Beispiel #4
0
//------- Begin of function FirmHarbor::think_trade -----------//
//
int FirmHarbor::think_trade()
{
	//---- see if we have any free ship available ----//

	Nation*     ownNation  = nation_array[nation_recno];
	UnitMarine* unitMarine = ai_get_free_trade_ship();

	if( !unitMarine )
		return 0;

	//--- if this harbor is not linked to any trade firms, return now ---//

	if( total_linked_trade_firm() == 0 )
		return 0;

	//----- scan for another harbor to trade with this harbor ----//

	Firm* 		firmPtr;
	FirmHarbor* firmHarbor;

	int i;
	for( i=firm_array.size() ; i>0 ; i-- )
	{
		if( firm_array.is_deleted(i) )
			continue;

		firmPtr = firm_array[i];

		//### begin alex 24/9 ###//
		if(firmPtr->firm_id!=FIRM_HARBOR)
			continue;
		//#### end alex 24/9 ####//

		firmHarbor = (FirmHarbor*) firmPtr;

		if( firmHarbor->total_linked_trade_firm() == 0 )
			continue;

		if( !ownNation->has_trade_ship(firm_recno, i) )		// if there has been any ships trading between these two harbors yet
			break;
	}

	if( i==0 )
		return 0;

	//------ try to set up a sea trade now ------//

	unitMarine->set_stop( 1, loc_x1, loc_y1, COMMAND_AI);
	unitMarine->set_stop( 2, firmHarbor->loc_x1, firmHarbor->loc_y1, COMMAND_AI);

	unitMarine->set_stop_pick_up(1, AUTO_PICK_UP, COMMAND_AI);
	unitMarine->set_stop_pick_up(2, AUTO_PICK_UP, COMMAND_AI);

	return 1;
}
Beispiel #5
0
//------- Begin of function FirmHarbor::should_show_harbor_info -------//
//
int FirmHarbor::should_show_harbor_info()
{
	if( should_show_info() )
		return 1;

	//--- if any of the ships in the harbor has the spies of the player ---//

	UnitMarine* unitMarine;

	for( int i=0 ; i<ship_count ; i++ )
	{
		unitMarine = (UnitMarine*) unit_array[ ship_recno_array[i] ];

		if( unitMarine->should_show_info() )
			return 1;
	}

	return 0;
}
Beispiel #6
0
//------ Begin of function Nation::ai_sea_attack_target ------//
//
// <int> targetXLoc, targetYLoc - the location of the target.
//
int Nation::ai_sea_attack_target(int targetXLoc, int targetYLoc)
{
	UnitMarine* unitMarine;
	int 		   targetRegionId = world.get_region_id(targetXLoc, targetYLoc);
	int			rc = 0;

	for( int i=0 ; i<ai_ship_count ; i++ )
	{
		unitMarine = (UnitMarine*) unit_array[ ai_ship_array[i] ];

		if( unitMarine->attack_count==0 )
			continue;

		if( !unitMarine->is_ai_all_stop() )
			continue;

		//----- if the ship is in the harbor now -----//

		if( unitMarine->unit_mode == UNIT_MODE_IN_HARBOR )
		{
			FirmHarbor*	firmHarbor = (FirmHarbor*) firm_array[unitMarine->unit_mode_para];

			if( firmHarbor->sea_region_id != targetRegionId )
				continue;

			firmHarbor->sail_ship(unitMarine->sprite_recno, COMMAND_AI);
		}

		if( !unitMarine->is_visible() )		// no space in the sea for placing the ship
			continue;

		if( unitMarine->region_id() != targetRegionId )
			continue;

		//------ order the ship to attack the target ------//

		unitMarine->attack_unit( targetXLoc, targetYLoc );
		rc = 1;
	}

	return rc;
}
Beispiel #7
0
//-------- Begin of function Nation::ai_sea_travel2 -------//
//
// action_x_loc, action_y_loc - location of the destination
// action_para2 					- the recno of the ship
//										  (this is set when the ship has moved to the beach,
//											the function responsible for setting this is Nation::action_finished() )
//
//---------------------------------------------//
//
// Procedures:
//   1. Locate a ship, build one if cannot locate any.
//   2. Assign the units to the ship.
// * 3. Move the ship to the destination region.
//   4. Units disembark on the coast.
//   5. Units move to the destination.
//
//---------------------------------------------//
//
int Nation::ai_sea_travel2(ActionNode* actionNode)
{
	if( unit_array.is_deleted(actionNode->action_para2) )
		return -1;

	UnitMarine* unitMarine = (UnitMarine*) unit_array[actionNode->action_para2];

	if( unit_res[unitMarine->unit_id]->unit_class != UNIT_CLASS_SHIP )
		return -1;

	if( unitMarine->nation_recno != nation_recno )
		return -1;

	//--------------------------------------------------------//

	int realDestXLoc, realDestYLoc;		// reference vars for returning vars. 

	unitMarine->ship_to_beach( actionNode->action_x_loc, actionNode->action_y_loc, realDestXLoc, realDestYLoc );		// the real destination the ship is moving towards.
	unitMarine->ai_action_id = actionNode->action_id;

	return 1;
}
Beispiel #8
0
//--------- Begin of function Unit::process_ship_to_beach ---------//
// process unit action SHIP_TO_BEACH
//
void Unit::process_ship_to_beach()
{
	//----- action_mode never clear, in_beach to skip idle checking
	if(cur_action==SPRITE_IDLE)
	{
		int shipXLoc = next_x_loc();
		int shipYLoc = next_y_loc();
		if(shipXLoc==move_to_x_loc && shipYLoc==move_to_y_loc)
		{
			if(abs(move_to_x_loc-action_x_loc2)<=2 && abs(move_to_y_loc-action_y_loc2)<=2)
			{
				UnitMarine *shipPtr = (UnitMarine*) this;
				//------------------------------------------------------------------------------//
				// determine whether extra_move is required
				//------------------------------------------------------------------------------//
				switch(shipPtr->extra_move_in_beach)
				{
					case NO_EXTRA_MOVE:
							if(abs(shipXLoc-action_x_loc2)>1 || abs(shipYLoc-action_y_loc2)>1)
							{
								err_when(abs(shipXLoc-action_x_loc2)>2 || abs(shipYLoc-action_y_loc2)>2);
								err_when(result_node_array);

								shipPtr->extra_move();
							}
							else
							{
								//shipPtr->in_beach = 1;
								shipPtr->extra_move_in_beach = NO_EXTRA_MOVE;
								
							//#### trevor 23/10 #####//
								if(ai_action_id)
									nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
							//#### trevor 23/10 #####//
							}
							break;

					case EXTRA_MOVING_IN:
					case EXTRA_MOVING_OUT:
							//err_when(cur_action!=SPRITE_SHIP_EXTRA_MOVE);
							break;

							//#### trevor 23/10 #####//

					case EXTRA_MOVE_FINISH:
							if(ai_action_id)
								nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
							break;

							//#### trevor 23/10 #####//

					default: err_here();
								break;
				}
			}
		}			
		else
			reset_action_para();
	}
	else if(cur_action==SPRITE_TURN && is_dir_correct())
		set_move();
}
Beispiel #9
0
//--------- Begin of function Unit::process_assign_to_ship ---------//
// process unit action of assigning units to ship
//
void Unit::process_assign_to_ship()
{
	err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
	
	//---------------------------------------------------------------------------//
	// clear unit's action if situation is changed
	//---------------------------------------------------------------------------//
	UnitMarine *shipPtr;
	if(unit_array.is_deleted(action_para2))
	{
		stop2();
		return; // stop the unit as the ship is deleted
	}
	else
	{
		shipPtr = (UnitMarine*) unit_array[action_para2];
		if(shipPtr->nation_recno != nation_recno)
		{
			stop2();
			return; // stop the unit as the ship's nation_recno != the unit's nation_recno
		}
	}

	if(shipPtr->action_mode2!=ACTION_SHIP_TO_BEACH)
	{
		stop2(); // the ship has changed its action
		return;
	}

	int curXLoc = next_x_loc();
	int curYLoc = next_y_loc();
	int shipXLoc = shipPtr->next_x_loc();
	int shipYLoc = shipPtr->next_y_loc();

	if(shipPtr->cur_x==shipPtr->next_x && shipPtr->cur_y==shipPtr->next_y &&
		abs(shipXLoc-curXLoc)<=1 && abs(shipYLoc-curYLoc)<=1)
	{
		//----------- assign the unit now -----------//
		if(abs(cur_x-next_x)<sprite_info->speed && abs(cur_y-next_y)<sprite_info->speed)
		{
			if(ai_action_id)
				nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);

			stop2();
			set_dir(curXLoc, curYLoc, shipXLoc, shipYLoc);
			shipPtr->load_unit(sprite_recno);
			return;
		}
	}
	else if(cur_action==SPRITE_IDLE)
		set_dir(curXLoc, curYLoc, shipPtr->move_to_x_loc, shipPtr->move_to_y_loc);

	//---------------------------------------------------------------------------//
	// update location to embark
	//---------------------------------------------------------------------------//
	int shipActionXLoc = shipPtr->action_x_loc2;
	int shipActionYLoc = shipPtr->action_y_loc2;
	if(abs(shipActionXLoc-action_x_loc2)>1 || abs(shipActionYLoc-action_y_loc2)>1)
	{
		if(shipActionXLoc!=action_x_loc2 || shipActionYLoc!=action_y_loc2)
		{
			Location *unitLocPtr = world.get_loc(curXLoc, curYLoc);
			Location *shipActionLocPtr = world.get_loc(shipActionXLoc, shipActionYLoc);
			if(unitLocPtr->region_id != shipActionLocPtr->region_id)
			{
				stop2();
				return;
			}

			assign_to_ship(shipActionXLoc, shipActionYLoc, action_para2);
			return;
		}
	}
}
Beispiel #10
0
//-------- Begin of function Nation::ai_find_transport_ship -------//
//
// Locate a ship for transporting units.
//
// <int> seaRegionId			 - region id. of the sea which the ship should appear in.
// <int> unitXLoc, unitYLoc - the location of the units to be picked up,
//									   try to select a harbor close to this location.
// [int] findBest           - whether need to find the best ship or just return
//									   one if there is one found. (default: 1)
//
// return: <int> the recno of the ship located.
//
int Nation::ai_find_transport_ship(int seaRegionId, int unitXLoc, int unitYLoc, int findBest)
{
	//------- locate a suitable ship --------//

	UnitMarine* unitMarine;
	int			curRating, bestRating=0, bestUnitRecno=0;

	for( int i=0 ; i<ai_ship_count ; i++ )
	{
		unitMarine = (UnitMarine*) unit_array[ ai_ship_array[i] ];

		err_when( unit_res[unitMarine->unit_id]->unit_class != UNIT_CLASS_SHIP );

		if( unitMarine->unit_count > 0 ||										// if there are already units in the ship
			 unit_res[unitMarine->unit_id]->carry_unit_capacity==0 )		// if the ship does not carry units
		{
			continue;
		}

		//------- if this ship is in the harbor ---------//

		if( unitMarine->unit_mode == UNIT_MODE_IN_HARBOR )
		{
			FirmHarbor* firmHarbor = (FirmHarbor*) firm_array[unitMarine->unit_mode_para];

			err_when( firmHarbor->firm_id != FIRM_HARBOR );

			if( firmHarbor->sea_region_id != seaRegionId )
				continue;
		}

		//--------- if this ship is on the sea ----------//

		else
		{
			if( !unitMarine->is_ai_all_stop() )
				continue;

			if( unitMarine->region_id() != seaRegionId )
				continue;

			err_when( !unitMarine->is_visible() );

			if( !unitMarine->is_visible() )
				continue;
		}

		//--------- check if the sea region is matched ---------//

		if( !findBest )		// return immediately when a suitable one is found
			return unitMarine->sprite_recno;

		curRating = world.distance_rating( unitXLoc, unitYLoc,
						unitMarine->next_x_loc(), unitMarine->next_y_loc() );

		curRating += (int)unitMarine->hit_points/10				// damage
						 + (int)unitMarine->max_hit_points/10;	// ship class

		if( curRating > bestRating )
		{
			bestRating 	  = curRating;
			bestUnitRecno = unitMarine->sprite_recno;
		}
	}

	return bestUnitRecno;
}
Beispiel #11
0
//-------- Begin of function Nation::ai_sea_travel3 -------//
//
// action_x_loc, action_y_loc - location of the destination
// action_para2 					- the recno of the ship
//
//---------------------------------------------//
//
// Procedures:
//   1. Locate a ship, build one if cannot locate any.
//   2. Assign the units to the ship.
//   3. Move the ship to the destination region.
// * 4. Units disembark on the coast.
// * 5. Units move to the destination.
//
//---------------------------------------------//
//
int Nation::ai_sea_travel3(ActionNode* actionNode)
{
	if( unit_array.is_deleted(actionNode->action_para2) )
		return -1;

	UnitMarine* unitMarine = (UnitMarine*) unit_array[actionNode->action_para2];

	if( unit_res[unitMarine->unit_id]->unit_class != UNIT_CLASS_SHIP )
		return -1;

	if( unitMarine->nation_recno != nation_recno )
		return -1;

	//-------- 4. Units disembark on the coast. -------//

	if( !unitMarine->can_unload_unit() )
		return 0;

	//--- make a copy of the recnos of the unit on the ship ---//

	short unitRecnoArray[MAX_UNIT_IN_SHIP];
	short unitCount;

	memcpy( unitRecnoArray, unitMarine->unit_recno_array, sizeof(unitRecnoArray) );
	unitCount = unitMarine->unit_count;

	unitMarine->unload_all_units(COMMAND_AI);		// unload all units now

	return 1;		// finish the action.

/*
	//---------- 5. Validate all units ----------//

	for( int i=unitCount-1 ; i>=0 ; i-- )
	{
		if( unit_array.is_deleted( unitRecnoArray[i] ) ||
			 unit_array[ unitRecnoArray[i] ]->nation_recno != nation_recno )
		{
			err_when( unitCount > MAX_UNIT_IN_SHIP );

			m.del_array_rec( unitRecnoArray, unitCount, sizeof(unitRecnoArray[0]), i+1 );
			unitCount--;
		}
	}

	if( unitCount==0 )
		return -1;

	err_when( unitCount < 0 );

	//--- 6. Unit actions after they have arrived the destination region ----//

	int	destXLoc = actionNode->action_x_loc;
	int	destYLoc = actionNode->action_y_loc;
	Location* locPtr = world.get_loc(destXLoc, destYLoc);

	switch(actionNode->action_para)
	{
		case SEA_ACTION_SETTLE:
			if( locPtr->is_town() && town_array[locPtr->town_recno()]->nation_recno == nation_recno )
			{
				Town *townPtr = town_array[locPtr->town_recno()];
				unit_array.assign(townPtr->loc_x1, townPtr->loc_y1, 0, COMMAND_AI, unitRecnoArray, unitCount);		// assign to an existing town
			}
			else  //-- if there is no town there, the unit will try to settle, if there is no space for settle, settle() will just have the units move to the destination
			{
				unit_array.settle(destXLoc, destYLoc, 0, COMMAND_AI, unitRecnoArray, unitCount);		// settle as a new town
			}
			break;

		case SEA_ACTION_BUILD_CAMP:
		{
			Unit* unitPtr = unit_array[ unitRecnoArray[0] ];

			unitPtr->build_firm(destXLoc, destYLoc, FIRM_CAMP, COMMAND_AI );

			unitPtr->ai_action_id = actionNode->action_id;
			actionNode->processing_instance_count++;
			break;
		}

		case SEA_ACTION_ASSIGN_TO_FIRM:
			if( check_firm_ready(destXLoc, destYLoc) )
				unit_array.assign(destXLoc, destYLoc, 0, COMMAND_AI, unitRecnoArray, unitCount);
			break;

		case SEA_ACTION_MOVE:
			unit_array.move_to(destXLoc, destYLoc, 0, unitRecnoArray, unitCount, COMMAND_AI);
			break;

		case SEA_ACTION_NONE:		// just transport them to the specific region and disemark and wait for their own actions
			break;
	}

	//---------- set the action id. of the units ---------//

	if( actionNode->action_para != SEA_ACTION_BUILD_CAMP )		// with the exception of SEA_ACTION_BUILD_CAMP, units in all other actions are immediately executed
	{
		for( int i=unitCount-1 ; i>=0 ; i-- )
		{
			unit_array[ unitRecnoArray[i] ]->ai_action_id = actionNode->action_id;
			actionNode->processing_instance_count++;
		}
	}

	//---------------------------------------------//

	actionNode->processing_instance_count--;		// decrease it by one as it will be increased in process_action()

	actionNode->instance_count = actionNode->processing_instance_count+1;		// set the instance count so process_action() won't cause error.

	return 1;
*/
}