Beispiel #1
0
//--------- Begin of function Unit::think_build_camp --------//
//
// Think about building a camp next to the town which is
// closest to the unit.
//
int Unit::think_build_camp()
{
	//---- select a town to build the camp ---//

	Nation* ownNation = nation_array[nation_recno];
	Town *townPtr, *bestTown=NULL;
	int   curRating=0, bestRating=0;
	int	regionId = world.get_region_id( next_x_loc(), next_y_loc() );
	int  	curXLoc = next_x_loc(), curYLoc = next_y_loc();

	for( int i=ownNation->ai_town_count-1 ; i>=0 ; i-- )
	{
		townPtr = town_array[ ownNation->ai_town_array[i] ];

		if( townPtr->region_id != regionId )
			continue;

		if( !townPtr->is_base_town || townPtr->no_neighbor_space )
			continue;

		curRating = world.distance_rating(curXLoc, curYLoc, townPtr->center_x, townPtr->center_y );

		if( curRating > bestRating )
		{
			bestRating = curRating;
			bestTown   = townPtr;
		}
	}

	if( bestTown )
		return bestTown->ai_build_neighbor_firm(FIRM_CAMP);

	return 0;
}
Beispiel #2
0
//--------- Begin of function Unit::ai_move_to_nearby_town --------//
//
// [int] shouldAssign - this tells whether the unit should be assigned
//								to the town. (default: 0)
//
void Unit::ai_move_to_nearby_town(int shouldAssign)
{
	//---- look for towns to move to -----//

	Nation* ownNation = nation_array[nation_recno];
	Town *townPtr, *bestTown=NULL;
	int  regionId = world.get_region_id( next_x_loc(), next_y_loc() );
	int  curDistance, curRating, bestRating=0;
	int  curXLoc = next_x_loc(), curYLoc = next_y_loc();

	for( int i=town_array.size() ; i>0 ; i-- )		// can't use ai_town_array[] because this function will be called by Unit::betray() when a unit defected to the player's kingdom
	{
		if( town_array.is_deleted(i) )
			continue;

		townPtr = town_array[i];

		if( townPtr->nation_recno != nation_recno )
			continue;

		if( townPtr->region_id != regionId )
			continue;

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

		curDistance = misc.points_distance(curXLoc, curYLoc, townPtr->center_x, townPtr->center_y );

		if( curDistance < 10 )		// no need to move if the unit is already close enough to the town.
			return;

		curRating = 100 - 100 * curDistance / MAX_WORLD_X_LOC;

		curRating += townPtr->population;

		if( race_id == townPtr->race_id )
			curRating += 100;

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

		if( curRating > bestRating )
		{
			bestRating = curRating;
			bestTown   = townPtr;
		}
	}

	if( bestTown )
	{
		if( shouldAssign )
			assign(bestTown->loc_x1, bestTown->loc_y1);
		else
			move(bestTown->loc_x1, bestTown->loc_y1);
	}
}
Beispiel #3
0
//---------- Begin of function UnitB::process_blocked -----//
// 
// retry move to destination if the unit is blocked
//
void UnitB::process_blocked()
{
	if(number_of_times_being_blocked++ > MAX_UNIT_BLOCKED_TIME  || 
		(next_x_loc() == move_to_loc_x && next_y_loc() == move_to_loc_y) || 
		((abs(move_to_loc_x - next_x_loc()) <= obj_loc_width()) && 
		 (abs(move_to_loc_y - next_y_loc()) <= obj_loc_height()) && 
		 !can_move(move_to_loc_x, move_to_loc_y) &&
		 !checking_who_occupy_the_place_i_want_to_go(move_to_loc_x, move_to_loc_y)))
	{
		set_no_longer_blocked();
		stop_move();
	}
	else
		move_to(move_to_loc_x, move_to_loc_y);
}
Beispiel #4
0
//--------- Begin of function Unit::detect_basic_info ---------//
//
int Unit::detect_basic_info()
{
	//--- detect pressing on the name to center the unit on the screen ---//

	if( is_visible() && mouse.single_click( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+21 ) )
	{
		world.go_loc( next_x_loc(), next_y_loc() );
		return 1;
	}

	//-------- detect resign button ----------//

	// ###### patch begin Alex 10/1 ########//
	// if( is_own() && rank_id != RANK_KING )
	if( nation_recno == nation_array.player_recno && rank_id != RANK_KING )
	{
		if( button_resign.detect(KEY_DEL) )
		{
			group_resign();
			return 1;
		}
	}
	// ###### patch end Alex 10/1 ########//

	return 0;
}
Beispiel #5
0
//--------- Begin of function UnitMonster::assign_to_firm --------//
//
int UnitMonster::assign_to_firm()
{
	int 	i, firmCount=firm_array.size();
	Firm* firmPtr;
	int	curXLoc = next_x_loc(), curYLoc = next_y_loc();
	BYTE	regionId = world.get_region_id(curXLoc, curYLoc);

	int firmRecno = m.random(firm_array.size())+1;

	for( i=0 ; i<firmCount ; i++ )
	{
		if( ++firmRecno > firmCount )
			firmRecno = 1;

		if( firm_array.is_deleted(firmRecno) )
			continue;

		firmPtr = firm_array[firmRecno];

		if( firmPtr->region_id != regionId )
			continue;

		if( firmPtr->firm_id == FIRM_MONSTER )
		{
			if( ((FirmMonster*)firmPtr)->can_assign_monster(sprite_recno) )
			{
				group_order_monster(firmPtr->loc_x1, firmPtr->loc_y1, 2);	// 2-the action is assign
				return 1;
			}
		}
	}

	return 0;
}
Beispiel #6
0
//--------- Begin of function UnitGod::viking_summon_tornado ---------//
//
void UnitGod::viking_summon_tornado()
{
	// ######## begin Gilbert 14/10 ########//
	short xLoc = next_x_loc();
	short yLoc = next_y_loc();
	char dir = final_dir % 8;
	// ######## end Gilbert 14/10 ########//

	// put a tornado one location ahead
	if( dir == 0 || dir == 1 || dir == 7 )
		if( yLoc > 0 )
			yLoc--;
	if( dir >= 1 && dir <= 3 )
		if( xLoc < MAX_WORLD_X_LOC-1 )
			xLoc++;
	if( dir >= 3 && dir <= 5 )
		if( yLoc < MAX_WORLD_Y_LOC-1)
			yLoc++;
	if( dir >= 5 && dir <= 7 )
		if( xLoc > 0 )
			xLoc--;

	tornado_array.add_tornado( xLoc, yLoc, 600 );
	magic_weather.cast_wind(10, 1, dir * 45 );              // 10 days
}
Beispiel #7
0
//------------- Begin of function Unit::defend_town_follow_target --------------//
// check the unit should follow the target or not
//
// return 0 if aborting attack the current target and go back to military camp
// return 1 otherwise
//
int Unit::defend_town_follow_target()
{
	err_when(unit_mode!=UNIT_MODE_DEFEND_TOWN);

	if(cur_action==SPRITE_ATTACK)
		return 1;

	if(town_array.is_deleted(unit_mode_para))
	{
		stop2(); //**** BUGHERE
		set_mode(0); //***BUGHERE
		return 0;
	}

	int curXLoc = next_x_loc();
	int curYLoc = next_y_loc();

	Town *townPtr = town_array[unit_mode_para];
	if((curXLoc<townPtr->center_x-UNIT_DEFEND_TOWN_DISTANCE) || (curXLoc>townPtr->center_x+UNIT_DEFEND_TOWN_DISTANCE) ||
		(curYLoc<townPtr->center_y-UNIT_DEFEND_TOWN_DISTANCE) || (curYLoc>townPtr->center_y+UNIT_DEFEND_TOWN_DISTANCE))
	{
		defend_town_back_town(unit_mode_para);
		return 0;
	}

	return 1;
}
Beispiel #8
0
//--------- Begin of function UnitMarine::is_on_coast ---------//
//
// Return whether the unit is on the coast and ready for unloading.
//
int UnitMarine::is_on_coast()
{
	Location *locPtr;
	int 		xShift, yShift, checkXLoc, checkYLoc, found=0;
	int 		curXLoc = next_x_loc();	// ship location
	int 		curYLoc = next_y_loc();

	for(int i=2; i<=9; i++) // checking for the surrouding location
	{
		m.cal_move_around_a_point(i, 3, 3, xShift, yShift);

		checkXLoc = curXLoc + xShift;
		checkYLoc = curYLoc + yShift;

		if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
			continue;

		locPtr = world.get_loc(checkXLoc, checkYLoc);

		if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN && // a territory nearby
			locPtr->walkable())
		{
			return 1;
		}
	}

	return 0;
}
Beispiel #9
0
//------- Begin of function UnitMonster::die -------//
//
void UnitMonster::die()
{
	if( !is_visible() )
		return;

	//--- check if the location where the unit dies already has an item ---//

	int xLoc = cur_x_loc();
	int yLoc = cur_y_loc();

	if( !world.get_loc(xLoc, yLoc)->can_build_site() )
	{
		int txLoc, tyLoc, foundFlag=0;

		for( tyLoc=max(yLoc-1,0) ; tyLoc<=min(yLoc+1,MAX_WORLD_Y_LOC-1) && !foundFlag ; tyLoc++ )
		{
			for( txLoc=max(xLoc-1,0) ; txLoc<=min(xLoc+1,MAX_WORLD_X_LOC-1) ; txLoc++ )
			{
				if( world.get_loc(txLoc,tyLoc)->can_build_site() )
				{
					xLoc = txLoc;
					yLoc = tyLoc;
					foundFlag = 1;
					break;
				}
			}
		}

		if( !foundFlag )
			return;
	}

	//--- when a general monster is killed, it leaves gold coins ---//

	if( !nation_recno && get_monster_id() != 0)	// to skip monster_res[ get_monster_id() ] error in test game 2
	{
		MonsterInfo* monsterInfo = monster_res[ get_monster_id() ];

		if( rank_id == RANK_GENERAL )
		{
			int goldAmount = 2 * max_hit_points * monsterInfo->level * (100+m.random(30)) / 100;

			site_array.add_site( xLoc, yLoc, SITE_GOLD_COIN, goldAmount );
			site_array.ai_get_site_object();		// ask AI units to get the gold coins
		}

		//--- when a king monster is killed, it leaves a scroll of power ---//

		else if( rank_id == RANK_KING )
		{
			king_leave_scroll();
		}
	}

	//---------- add news ----------//

	if( rank_id == RANK_KING )
		news_array.monster_king_killed( get_monster_id(), next_x_loc(), next_y_loc() );
}
Beispiel #10
0
//------------- Begin of function Unit::sound --------------//
//
void Unit::sound(const char* soundCode)
{
	if( se_res.mark_command_time() )
	{
		se_res.far_sound( next_x_loc(), next_y_loc(), 1,
			'S', sprite_id, soundCode );
	}
}
Beispiel #11
0
//------- Begin of function Unit::think_change_attack_target -------//
//
// When the unit is attacking a firm or town, look out for enemy units
// to attack. Enemy units should be attacked first.
//
int Unit::think_change_attack_target()
{
	err_when( !nation_recno );		// only for nation units

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

	int attackRange	  = MAX(attack_range, 8);
	int attackScanRange = attackRange*2+1;

	int		 xOffset, yOffset;
	int		 xLoc, yLoc;
	Location* locPtr;
	int		 curXLoc = next_x_loc(), curYLoc = next_y_loc();
	BYTE	 	 regionId = world.get_region_id(curXLoc, curYLoc);

	for( int i=2 ; i<attackScanRange*attackScanRange ; i++ )
	{
		m.cal_move_around_a_point(i, attackScanRange, attackScanRange, xOffset, yOffset);

		xLoc = curXLoc + xOffset;
		yLoc = curYLoc + yOffset;

		xLoc = MAX(0, xLoc);
		xLoc = MIN(MAX_WORLD_X_LOC-1, xLoc);

		yLoc = MAX(0, yLoc);
		yLoc = MIN(MAX_WORLD_Y_LOC-1, yLoc);

		locPtr = world.get_loc(xLoc, yLoc);

		if( locPtr->region_id != regionId )
			continue;

		//----- if there is a unit on the location ------//

		if( locPtr->has_unit(UNIT_LAND) )
		{
			int unitRecno = locPtr->unit_recno(UNIT_LAND);

			if( unit_array.is_deleted(unitRecno) )
				continue;

			if( unit_array[unitRecno]->nation_recno != nation_recno &&
				 idle_detect_unit_checking(unitRecno) )
			{
				save_original_action();

				original_target_x_loc = xLoc;
				original_target_y_loc = yLoc;

				attack_unit(xLoc, yLoc);
				return 1;
			}
		}
	}

	return 0;
}
Beispiel #12
0
//--------- Begin of function Unit::ai_move_to_nearby_firm --------//
//
// <int> firmId  - move to this firm.
// [int] firmId2 - optional. If given will also move to this firm.
//
void Unit::ai_move_to_nearby_firm(int firmId, int firmId2)
{
	//---- look for towns to move to -----//

	Nation* ownNation = nation_array[nation_recno];
	Firm *firmPtr, *bestFirm=NULL;
	int  regionId = world.get_region_id( next_x_loc(), next_y_loc() );
	int  curRating, bestRating=0;
	int  curXLoc = next_x_loc(), curYLoc = next_y_loc();

	for( int i=firm_array.size() ; i>0 ; i-- )		// can't use ai_firm_array[] because this function will be called by Unit::betray() when a unit defected to the player's kingdom
	{
		if( firm_array.is_deleted(i) )
			continue;

		firmPtr = firm_array[i];

		if( firmPtr->nation_recno != nation_recno )
			continue;

		if( firmPtr->region_id != regionId )
			continue;

		if( firmPtr->firm_id != firmId && firmPtr->firm_id != firmId2 )
			continue;

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

		curRating = world.distance_rating( curXLoc, curYLoc, firmPtr->center_x, firmPtr->center_y );

		if( race_id == firmPtr->race_id )
			curRating += 100;

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

		if( curRating > bestRating )
		{
			bestRating = curRating;
			bestFirm   = firmPtr;
		}
	}

	if( bestFirm )
		move(bestFirm->loc_x1, bestFirm->loc_y1);
}
Beispiel #13
0
// -------- begin of function Unit::explore_area --------//
//
// explore whole rectangle
// called when init_sprite, change nation, spy::end_camouflage
//
void Unit::explore_area()
{
	//------ unveil the area where the unit is added to ------//

	if( explore_for_player() )
	{
		int scoutRange = item.ability(ITEM_ABILITY_SCOUT_RANGE);
		// do not call use_now, let next_day to use its energy

		world.unveil( next_x_loc()-scoutRange, next_y_loc()-scoutRange,
			next_x_loc() + loc_width + scoutRange -1,
			next_y_loc() + loc_height + scoutRange -1 );

		world.visit(next_x_loc(), next_y_loc(), next_x_loc()+loc_width-1,
			next_y_loc()+loc_height-1, unit_res[unit_id]->visual_range + scoutRange,
			unit_res[unit_id]->visual_extend);
	}
}
Beispiel #14
0
//--------- Begin of function Unit::ai_escape_fire --------//
//
// Move away if the unit currently stands on a burning ground.
//
int Unit::ai_escape_fire()
{
	if(cur_action!=SPRITE_IDLE)
		return 0;

	if(mobile_type!=UNIT_LAND)
		return 0;

	Location *locPtr = world.get_loc(next_x_loc(), next_y_loc());

	if( !locPtr->fire_str() )
		return 0;

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

	int checkLimit = 400; // checking for 400 location
	int xShift, yShift, checkXLoc, checkYLoc;
	int curXLoc = next_x_loc();
	int curYLoc = next_y_loc();

	for(int i=2; i<checkLimit; i++)
	{
		misc.cal_move_around_a_point(i, 20, 20, xShift, yShift);

		checkXLoc = curXLoc + xShift;
		checkYLoc = curYLoc + yShift;

		if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
			continue;

		if(!locPtr->can_move(mobile_type))
			continue;

		locPtr = world.get_loc(checkXLoc, checkYLoc);

		if( locPtr->fire_str()==0 )		// move to a safe place now
		{
			move_to(checkXLoc, checkYLoc);
			return 1;
		}
	}

	return 0;
}
Beispiel #15
0
//--------- Begin of function Unit::detect_unit_profile ---------//
//
int Unit::detect_unit_profile()
{
	if( is_visible() && mouse.single_click( INFO_X1, INFO_Y1+54, INFO_X2, INFO_Y1+97 ) )
	{
		world.go_loc( next_x_loc(), next_y_loc() );
		return 1;
	}

	return 0;
}
Beispiel #16
0
int Unit::think_assign_weapon_to_camp()
{
	Nation 	*nationPtr = nation_array[nation_recno];
	FirmCamp *firmCamp, *bestCamp=NULL;
	int      curRating=0, bestRating=0;
	int		regionId = world.get_region_id( next_x_loc(), next_y_loc() );
	int		curXLoc = next_x_loc(), curYLoc = next_y_loc();

	for( int i=0 ; i<nationPtr->ai_camp_count ; i++ )
	{
		firmCamp = firm_array[ nationPtr->ai_camp_array[i] ]->cast_to_FirmCamp();

		if( firmCamp->region_id	!= regionId || firmCamp->is_soldier_full() )
			continue;

		if( !firmCamp->can_accept_assign(sprite_recno) )
			continue;

		//-------- calculate the rating ---------//

		curRating = world.distance_rating(curXLoc, curYLoc, firmCamp->center_x, firmCamp->center_y );

		curRating += (MAX_SOLDIER - firmCamp->soldier_count) * 10;

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

		if( curRating > bestRating )
		{
			bestRating = curRating;
			bestCamp   = firmCamp;
		}
	}

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

	if( bestCamp )
	{
		assign(bestCamp->loc_x1, bestCamp->loc_y1);
		return 1;
	}

	return 0;
}
Beispiel #17
0
//--------- Begin of function Unit::region_id ---------//
//
// Return the region id. of this unit.
//
BYTE Unit::region_id()
{
   if( is_visible() )
   {
      return world.get_region_id( next_x_loc(), next_y_loc() );
	}
	else
	{
		if( unit_mode == UNIT_MODE_OVERSEE )
			return firm_array[unit_mode_para]->region_id;
	}

	return 0;
}
Beispiel #18
0
//-------- Begin of function Unit::should_show_info ------//
//
int Unit::should_show_info()
{
	if( config.show_ai_info || is_own() )
		return 1;

	//---- if there is a phoenix of the player over this firm ----//

	if( nation_array.player_recno &&
		 (~nation_array)->revealed_by_phoenix(next_x_loc(), next_y_loc()) )
	{
		return 1;
	}

	return 0;
}
Beispiel #19
0
//--------- Begin of function UnitGod::detect_info ---------//
//
void UnitGod::detect_info()
{
	if( detect_basic_info() )
		return;

	if( detect_unit_profile() )
		return;

	if( !is_own() )
		return;

	if( game.game_mode == GAME_TEST )
		return;

	if( god_res[god_id]->can_cast_power )
	{
		// ###### begin Gilbert 14/10 ######//
		int rc=0;
		char castPowerType = 0;

		if( button_cast.detect() )
		{
			// cast_power_type = 1;
			castPowerType = 1;
			rc = 1;
		}

		if( button_cast2.detect() )
		{
			castPowerType = 2;
			//cast_power_type = 2;
			//cast_origin_x = cur_x_loc();
			//cast_origin_y = cur_y_loc();
			rc = 1;
		}

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

		if( rc && castPowerType)
		{
			if( god_id == GOD_VIKING && castPowerType == 1 )	// summon rain, summon immediately, no need to select target
				go_cast_power(next_x_loc(), next_y_loc(), castPowerType, COMMAND_PLAYER);
			else
				power.issue_command(COMMAND_GOD_CAST_POWER, sprite_recno, castPowerType);
		}
		// ###### end Gilbert 14/10 ######//
	}
}
Beispiel #20
0
//----------- Begin of function UnitB::process_idle----------//
//
// when a unit is idling, if it is block, process block
// if it is in formation but fnot yet reach destination, go there again
//
void UnitB::process_idle()
{
	cur_action = SPRITE_IDLE;
	if(is_blocked() && cur_order.mode != UNIT_ATTACK)
		process_blocked();
	else
	if(/*is_in_formation() && */
		is_blocked() &&
		((next_x_loc() != move_to_loc_x) || (next_y_loc() != move_to_loc_y)) &&
		can_move(move_to_loc_x, move_to_loc_y))

		move_to(move_to_loc_x, move_to_loc_y);
	
	else
		Sprite::process_idle();
}
Beispiel #21
0
//--------- Begin of function Unit::ship_leave_beach ---------//
void Unit::ship_leave_beach(int shipOldXLoc, int shipOldYLoc)
{
	err_when(cur_x!=next_x || cur_y!=next_y);

	UnitMarine *shipPtr = (UnitMarine*) this;
	err_when(!shipPtr->in_beach && shipPtr->extra_move_in_beach==EXTRA_MOVE_FINISH);

	//--------------------------------------------------------------------------------//
	// scan for location to leave the beach
	//--------------------------------------------------------------------------------//
	int curXLoc = next_x_loc();
	int curYLoc = next_y_loc();
	int xShift, yShift, checkXLoc, checkYLoc, found=0;
	Location *locPtr;

	//------------- find a location to leave the beach ------------//
	for(int i=2; i<=9; i++)
	{
		misc.cal_move_around_a_point(i, 3, 3, xShift, yShift);
		checkXLoc = curXLoc + xShift;
		checkYLoc = curYLoc + yShift;

		if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
			continue;
		
		if(checkXLoc%2 || checkYLoc%2)
			continue;

		locPtr = world.get_loc(checkXLoc, checkYLoc);
		if(terrain_res[locPtr->terrain_id]->average_type==TERRAIN_OCEAN &&
			locPtr->can_move(mobile_type))
		{
			found++;
			break;
		}
	}

	if(!found)
		return; // no suitable location, wait until finding suitable location

	//---------------- leave now --------------------//
	set_dir(shipOldXLoc, shipOldYLoc, checkXLoc, checkYLoc);
	set_ship_extra_move();
	go_x = checkXLoc*ZOOM_LOC_WIDTH;
	go_y = checkYLoc*ZOOM_LOC_HEIGHT;
	err_when(cur_x==go_x && cur_y==go_y);
}
Beispiel #22
0
//----------- Begin of function Unit::get_cur_loc -----------//
//
// <short&> xLoc, yLoc - reference vars for returning the
//								 location of this unit
//
// return : 0 - if this unit is invisible
//				1 - if a location has been returned.
//
int Unit::get_cur_loc(short& xLoc, short& yLoc)
{
	if( is_visible() )
	{
		xLoc = next_x_loc();		// update location
		yLoc = next_y_loc();
	}
	else if( unit_mode == UNIT_MODE_OVERSEE ||
				unit_mode==UNIT_MODE_CONSTRUCT_FIRM ||
				unit_mode == UNIT_MODE_IN_HARBOR )
	{
		Firm* firmPtr = firm_array[unit_mode_para];

		xLoc = firmPtr->center_x;
		yLoc = firmPtr->center_y;
	}
	else if( unit_mode==UNIT_MODE_CONSTRUCT_TOWN )
	{
		Town* townPtr = town_array[unit_mode_para];

		xLoc = townPtr->center_x;
		yLoc = townPtr->center_y;
	}
	else if( unit_mode == UNIT_MODE_ON_SHIP )
	{
		Unit* unitPtr = unit_array[unit_mode_para];

		if(unitPtr->is_visible())
		{
			xLoc = unitPtr->next_x_loc();
			yLoc = unitPtr->next_y_loc();
		}
		else
		{
			err_when(unitPtr->unit_mode!=UNIT_MODE_IN_HARBOR);
			Firm *firmPtr = firm_array[unitPtr->unit_mode_para];
			xLoc = firmPtr->center_x;
			yLoc = firmPtr->center_y;
		}
	}
	else
		return 0;

	return 1;
}
Beispiel #23
0
//--------- Begin of function Unit::ai_build_firm --------//
//
// Order this unit to build a camp in its region.
//
int Unit::ai_build_firm()
{
	//--- don't build if the race of the nation and the unit is different ----//

	if( nation_array[nation_recno]->is_human() != is_human() )
		return 0;

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

	int firmId;

	if( is_human() )
		firmId = FIRM_FORT;
	else
		firmId = FIRM_LAIR;

	if( !firm_res[firmId]->can_build(sprite_recno) )
		return 0;

	//--- to prevent building more than one camp at the same time ---//

	int     curRegionId = region_id();
	Nation* ownNation = nation_array[nation_recno];

	if( ownNation->is_action_exist( ACTION_AI_BUILD_FIRM, firmId, curRegionId ) )
		return 0;

	//------- locate a place for the camp --------//

	FirmInfo* firmInfo = firm_res[firmId];
	char 	 	 teraMask = UnitRes::mobile_type_to_mask(UNIT_LAND);
	int 		 xLoc=next_x_loc(), yLoc=next_y_loc();

	if( world.locate_space(xLoc, yLoc, xLoc, yLoc,
		 firmInfo->loc_width+INTER_PLACE_SPACE*2,
		 firmInfo->loc_height+INTER_PLACE_SPACE*2,   // leave at least one location space around the building
		 UNIT_LAND, curRegionId, 1) )
	{
		return ownNation->add_action( xLoc, yLoc, -1, -1,
					ACTION_AI_BUILD_FIRM, firmId, 1, sprite_recno );
	}

	return 0;
}
Beispiel #24
0
//--------- Begin of function Unit::push_order ---------//
//
// Note: the stack only has space for one Order object.
//
void Unit::push_order()
{
	err_when( has_pushed_order() > 0 );		// cannot push when the only one stack space is used

	pushed_order = cur_order;

	// ##### begin Gilbert 31/5 ########//
	// if the unit is stopped, store current location, used when resuming the action
	if( pushed_order.mode == UNIT_STOP )
	{
		pushed_order.set(UNIT_STOP, -2, next_x_loc(), next_y_loc() );
		// para = -2; to identify resume move, see execute_attack
	}
	// ##### end Gilbert 31/5 ########/

	cur_order.set(UNIT_STOP);

	stop_move();
}
Beispiel #25
0
//------------- Begin of function Unit::monster_defend_follow_target --------------//
// make decision to choose to follow target or return
//
// return 0 if aborting attack the current target and go back to military camp
// return 1 otherwise
//
int Unit::monster_defend_follow_target()
{
//######## begin trevor 22/8 ##########//
	err_when( unit_mode!=UNIT_MODE_MONSTER || !unit_mode_para );

	if(cur_action==SPRITE_ATTACK)
		return 1;
/*
	if(firm_array.is_deleted(action_misc_para))
	{
		stop2(); //**** BUGHERE
		//set_mode(0); //***BUGHERE
		if(monster_array.is_deleted(unit_mode_para))
			return 0;

		Monster *monsterPtr = monster_array[unit_mode_para];
		monsterPtr->firm_recno = 0;
		return 0;
	}
*/
//######## end trevor 22/8 ##########//

	//--------------------------------------------------------------------------------//
	// choose to return to firm
	//--------------------------------------------------------------------------------//
	int curXLoc = next_x_loc();
	int curYLoc = next_y_loc();

	Firm *firmPtr = firm_array[action_misc_para];
	if((curXLoc<firmPtr->center_x-MONSTER_DEFEND_FIRM_DISTANCE) || (curXLoc>firmPtr->center_x+MONSTER_DEFEND_FIRM_DISTANCE) ||
		(curYLoc<firmPtr->center_y-MONSTER_DEFEND_FIRM_DISTANCE) || (curYLoc>firmPtr->center_y+MONSTER_DEFEND_FIRM_DISTANCE))
	{
		monster_defend_back_firm(firmPtr->loc_x1, firmPtr->loc_y1);
		return 0;
	}

	return 1;
}
Beispiel #26
0
//------ Begin of function Unit::handle_blocked_same_target_attack ---------//
// the target of the blocked unit and this unit are same
//
// <Unit*>	unitPtr		-	pointer to blocking uit
// <Unit*>	targetPtr	-	pointer to target unit
//
void Unit::handle_blocked_same_target_attack(Unit* unitPtr, Unit* targetPtr)
{
	//----------------------------------------------------------//
	// this unit is now waiting and the unit pointed by unitPtr
	// is attacking the unit pointed by targetPtr
	//----------------------------------------------------------//
	err_when(cur_x%ZOOM_LOC_WIDTH || cur_y%ZOOM_LOC_HEIGHT);
	err_when(cur_x!=next_x || cur_y!=next_y);
	err_when(cur_x==go_x && cur_y==go_y);

	if(space_for_attack(action_x_loc, action_y_loc, targetPtr->mobile_type, targetPtr->sprite_info->loc_width, targetPtr->sprite_info->loc_height))
	{
		err_when(action_x_loc!=action_x_loc2 || action_y_loc!=action_y_loc2);
		search_or_stop(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_TO_ATTACK, targetPtr->sprite_recno);
		//search(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_TO_ATTACK, targetPtr->sprite_recno);
	}
	else if(in_any_defense_mode())
	{
		err_when(action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET &&
					action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET);

		general_defend_mode_detect_target();
	}
	else if(m.points_distance(next_x_loc(), next_y_loc(), action_x_loc, action_y_loc)<ATTACK_DETECT_DISTANCE)
	{
		//------------------------------------------------------------------------//
		// if the target is within the detect range, stop the unit's action to detect
		// another target if any exist. In case, there is no other target, the unit
		// will still attack the original target since it is the only target in the
		// detect range
		//------------------------------------------------------------------------//
		stop2(KEEP_DEFENSE_MODE);
	}
	else
		set_wait(); // set wait to stop the movement
}
Beispiel #27
0
void UnitMarine::process_extra_move()
{
	static short vector_x_array[] = { 0,  1, 1, 1, 0, -1, -1, -1};	// default vectors, temporary only
	static short vector_y_array[] = {-1, -1, 0, 1, 1,  1,  0, -1};

	if(!match_dir()) // process turning
		return;

	if(cur_x!=go_x || cur_y!=go_y)
	{
		//------------------------------------------------------------------------//
		// set cargo_recno, extra_move_in_beach
		//------------------------------------------------------------------------//
		if(cur_x==next_x && cur_y==next_y)
		{
			int goXLoc = go_x>>ZOOM_X_SHIFT_COUNT;
			int goYLoc = go_y>>ZOOM_Y_SHIFT_COUNT;
			if(!world.get_loc(goXLoc, goYLoc)->can_move(mobile_type))
			{
				go_x = next_x;
				go_y = next_y;
				return;
			}

			int curXLoc = next_x_loc();
			int curYLoc = next_y_loc();
			world.set_unit_recno(curXLoc, curYLoc, mobile_type, 0);
			world.set_unit_recno(goXLoc, goYLoc, mobile_type, sprite_recno);
			next_x = go_x;
			next_y = go_y;
			
			err_when( ((curXLoc%2)|(curYLoc%2)) + ((goXLoc%2)|(goYLoc%2)) != 1); // one pair location must be even, another is not even
			in_beach = !(curXLoc%2 || curYLoc%2);
			
			if(goXLoc%2 || goYLoc%2) // not even location
				extra_move_in_beach = EXTRA_MOVING_IN;
			else // even location
				extra_move_in_beach = EXTRA_MOVING_OUT;
		}
		//else
		//	int debug = 0;
		
		//---------- process moving -----------//
		short stepX = sprite_info->speed;
		short stepY = sprite_info->speed;
		short vectorX = vector_x_array[final_dir] * sprite_info->speed;	// cur_dir may be changed in the above set_next() call
		short vectorY = vector_y_array[final_dir] * sprite_info->speed;

		if(abs(cur_x-go_x) <= stepX)
			cur_x = go_x;
		else
			cur_x += vectorX;

		if(abs(cur_y-go_y) <= stepY)
			cur_y = go_y;
		else
			cur_y += vectorY;

		err_when(extra_move_in_beach!=EXTRA_MOVING_IN && extra_move_in_beach!=EXTRA_MOVING_OUT);
		err_when(cur_action!=SPRITE_SHIP_EXTRA_MOVE);
	}
Beispiel #28
0
//--------- Begin of function UnitMarine::extra_move ---------//
void UnitMarine::extra_move()
{
	static char offset[3] = {0, 1, -1};

	int curXLoc = next_x_loc();
	int curYLoc = next_y_loc();
	
	int vecX = action_x_loc2 - curXLoc;
	int vecY = action_y_loc2 - curYLoc;
	int checkXLoc, checkYLoc, i, found=0;

	if(vecX==0 || vecY==0)
	{
		if(vecX==0)
		{
			vecY /= abs(vecY);
			checkYLoc = curYLoc + vecY;
		}
		else // vecY==0
		{
			vecX /= abs(vecX);
			checkXLoc = curXLoc + vecX;
		}

		for(i=0; i<3; i++)
		{
			if(vecX==0)
				checkXLoc = curXLoc + offset[i];
			else
				checkYLoc = curYLoc + offset[i];

			if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
				continue;

			if(world.get_loc(checkXLoc, checkYLoc)->can_move(mobile_type))
			{
				found++;
				break;
			}
		}
	}
	else
	{
		vecX /= abs(vecX);
		vecY /= abs(vecY);
		checkXLoc = curXLoc + vecX;
		checkYLoc = curYLoc + vecY;

		if(world.get_loc(checkXLoc, checkYLoc)->can_move(mobile_type))
			found++;
	}

	if(!found)
		return;

	set_dir(curXLoc, curYLoc, checkXLoc, checkYLoc);
	cur_action = SPRITE_SHIP_EXTRA_MOVE;
	go_x = checkXLoc*ZOOM_LOC_WIDTH;
	go_y = checkYLoc*ZOOM_LOC_HEIGHT;
	err_when(cur_x==go_x && cur_y==go_y);
	//extra_move_in_beach = EXTRA_MOVING_IN;
}
Beispiel #29
0
//--------- Begin of function UnitMarine::unloading_unit ---------//
//
//	<int> isAll			- 1 for unload all the units
//							- otherwise 0
// <int>	unitSeqId	- if(isAll==0) unitSeqId+1 is the recno of the
//							  selected unit in unit_recno_array[]
//
int UnitMarine::unloading_unit(int isAll, int unitSeqId)
{
	if( !is_on_coast() )
		return 0;

	//-------------------------------------------------------------------------//
	// return if no territory is nearby the ship
	//-------------------------------------------------------------------------//

	int curXLoc = next_x_loc();	// ship location
	int curYLoc = next_y_loc();
	int unprocess = isAll ? unit_count : 1;
	Unit *unitPtr = isAll ? unit_array[unit_recno_array[unprocess-1]] : unit_array[unit_recno_array[unitSeqId]];
	Location *locPtr;
	int xShift, yShift, checkXLoc, checkYLoc;
	int regionId = 0; // unload all the units in the same territory
	int found, i = 2;
	int sqtSize = 3, sqtArea = sqtSize*sqtSize;

	#ifdef DEBUG
		long debugCount = 0L;
	#endif

	if(isAll &&  nation_recno == nation_array.player_recno )		// for player's camp, patrol() can only be called when the player presses the button.
		power.reset_selection();

	while(unprocess) // using the calculated 'i' to reduce useless calculation
	{
		err_when(debugCount++ > 4*long(MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC));

		m.cal_move_around_a_point(i, MAX_WORLD_X_LOC, MAX_WORLD_Y_LOC, xShift, yShift);
		checkXLoc = curXLoc+xShift;
		checkYLoc = curYLoc+yShift;
		if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
		{
			i++;
			continue;
		}
		
		locPtr = world.get_loc(checkXLoc, checkYLoc);
	
		//-------------------------------------------------------------------------//
		// check for space to unload the unit
		//-------------------------------------------------------------------------//
		if(!regionId || locPtr->region_id == regionId)
		{
			if(locPtr->walkable())
				found = 1;

			if(locPtr->can_move(UNIT_LAND))//unitPtr->mobile_type))
			{
				regionId = locPtr->region_id;

				unitPtr->init_sprite(checkXLoc, checkYLoc);
				unitPtr->set_mode(0);

				if( isAll && nation_recno == nation_array.player_recno )		// for player's camp, patrol() can only be called when the player presses the button.
				{
					unitPtr->selected_flag = 1; // mark selected if unload all
					unit_array.selected_count++;

					if( !unit_array.selected_recno )
						unit_array.selected_recno = unitPtr->sprite_recno;
				}

				unprocess--;
				unit_count--;

				if(unprocess)
					unitPtr = unit_array[unit_recno_array[unprocess-1]]; // point to next unit
				else
					break;	// finished, all have been unloaded
			}
		}

		//-------------------------------------------------------------------------//
		// stop checking if there is totally bouned by unacessible location
		//-------------------------------------------------------------------------//
		if(i==sqtArea)
		{
			if(found)
			{
				found = 0;	// reset found
				sqtSize += 2;
				sqtArea = sqtSize*sqtSize;
			}
			else // no continuous location for the unit to unload, some units can't be unloaded
				return 0;
		}

		i++;
	}

	//-------- display info --------//

	if( nation_recno == nation_array.player_recno )		// for player's camp, patrol() can only be called when the player presses the button.
		info.disp();

	return 1;
}
Beispiel #30
0
void UnitMarine::draw_outlined()
{
	// -------- update splash parameter --------//
	// ###### begin Gilbert 8/9 #######//
	char oldSplashAction = splash.cur_action;

	switch(cur_action)
	{
	case SPRITE_MOVE:
		splash.cur_action = SPRITE_MOVE;
		if( splash.cur_action != oldSplashAction)
			splash.cur_frame = 1;
		else
		{
			++splash.cur_frame;
			if( splash.cur_frame < 1 || splash.cur_frame > splash.cur_sprite_move()->frame_count )
				splash.cur_frame = 1;
		}
		break;

	default:
		splash.cur_action = SPRITE_IDLE;
		if( splash.cur_action != oldSplashAction)
			splash.cur_frame = 1;
		else
		{
			++splash.cur_frame;
			if( splash.cur_frame < 1 || splash.cur_frame > splash.cur_sprite_stop()->frame_count)
				splash.cur_frame = 1;
		}
		break;
	}
	// ###### end Gilbert 8/9 #######//

	splash.cur_x = cur_x;
	splash.cur_y = cur_y - wave_height(7);
	splash.cur_dir = cur_dir;
	splash.final_dir = final_dir;
	splash.turn_delay = turn_delay;

	// --------- draw splash and then the unit --------//
	// ###### begin Gilbert 24/9 #######//
	if( cur_action != SPRITE_DIE )
		splash.draw();
	// ###### end Gilbert 24/9 #######//
	Unit::draw_outlined();

	#ifdef DEBUG2
		if(selected_flag && 0)
		{
			vga.d3_panel_up( INFO_X1, INFO_Y1+144, INFO_X2, INFO_Y1+144+87 );

			int 	 x=INFO_X1+4, y=INFO_Y1+200, refreshFlag=INFO_REPAINT;
			font_san.field( x, y, " " , x+2, sprite_recno, 1, INFO_X2-2, refreshFlag);
			font_san.field( x+20, y, " " , x+22, next_x_loc(), 1, INFO_X2-2, refreshFlag);
			font_san.field( x+50, y, " " , x+52, next_y_loc(), 1, INFO_X2-2, refreshFlag);
			font_san.field( x+70, y, " " , x+72, nation_recno, 1, INFO_X2-2, refreshFlag);

			font_san.field( x+100, y, " " , x+102, action_mode, 1, INFO_X2-2, refreshFlag);
			font_san.field( x+120, y, " " , x+122, action_para, 1, INFO_X2-2, refreshFlag);
			font_san.field( x+140, y, " " , x+142, action_x_loc, 1, INFO_X2-2, refreshFlag);
			font_san.field( x+160, y, " " , x+162, action_y_loc, 1, INFO_X2-2, refreshFlag);
			y-=20;
			font_san.field( x+100, y, " " , x+102, action_mode2, 1, INFO_X2-2, refreshFlag);
			font_san.field( x+120, y, " " , x+122, action_para2, 1, INFO_X2-2, refreshFlag);
			font_san.field( x+140, y, " " , x+142, action_x_loc2, 1, INFO_X2-2, refreshFlag);
			font_san.field( x+160, y, " " , x+162, action_y_loc2, 1, INFO_X2-2, refreshFlag);
			y-=20;
			font_san.field( x+160, y, " " , x+162, cur_action, 1, INFO_X2-2, refreshFlag);
		}
	#endif
}