Пример #1
0
//--------- Begin of function Unit::ai_leader_being_attacked --------//
//
// This function is called when the king is under attack.
//
// <BaseObj*> attackerObj - BaseObj of the attacker object.
//
void Unit::ai_leader_being_attacked(BaseObj* attackerObj)
{
	err_when( !team_info );

	if( !attackerObj || attackerObj->nation_recno == nation_recno )		// this can happen when the unit has just changed nation
		return;

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

	int rc=0, callIntervalDays;

	if( rank_id == RANK_KING )
	{
		rc = 1;
		callIntervalDays = 7;
	}
	else if( rank_id == RANK_GENERAL )
	{
		rc = skill_level() >= 30 + (100-nation_array[nation_recno]->pref_keep_general)/2;		// 30 to 80
		callIntervalDays = 15;		// don't call too freqently
	}

	if( rc )
	{
		if( info.game_date > team_info->ai_last_request_defense_date + callIntervalDays )
		{
			team_info->ai_last_request_defense_date = info.game_date;
			nation_array[nation_recno]->ai_defend(attackerObj);
		}
	}
}
Пример #2
0
//-------- Begin of function Trainee::basic_train ------//
//
// Non-basic training: train the unit if it has potential.
//
void Trainee::basic_train(int firmRecno)
{
	int trainedFlag=0;

	//------ train spy skill --------//

	if( train_spy_potential && spy_skill < BASIC_SKILL_TRAIN )
	{
		spy_skill += 1;

		if( spy_skill > MAX_SKILL_TRAIN )
			spy_skill = MAX_SKILL_TRAIN;

		trainedFlag=1;
	}

	//------ train combat --------//

	if( train_type == TRAIN_UNIT_CIVILIAN )
	{
		if( combat_level() < CITIZEN_COMBAT_LEVEL )
		{
			skill.inc_combat_level(1);
			trainedFlag=1;
		}
	}
	else		//----- military unit -----//
	{
		int basicCombatLevel = BASIC_COMBAT_TRAIN;
		int nationRecno = firm_array[firmRecno]->nation_recno;
		// ##### patch begin Gilbert 16/2 ######//
		// if( nationRecno && race_id == RACE_ROMAN 
		//	&& god_res[GOD_ROMAN]->nation_prayer_count(nationRecno) > 0 )
		if( nationRecno && god_res[GOD_ROMAN]->nation_prayer_count(nationRecno) > 0 )
		// ##### patch end Gilbert 16/2 ######//
		{
			basicCombatLevel += BASIC_COMBAT_TRAIN / 2;		// roman can train to combat level 30
		}

		if( train_combat_potential && combat_level() < basicCombatLevel )
		{
			float incPoints = (float) basicCombatLevel / unit_res[unit_id]->build_days;

			skill.inc_combat_level(incPoints);
			trainedFlag=1;
		}
	}

	//------ train leadership --------//

	if( train_skill_potential && skill_level() < BASIC_SKILL_TRAIN )
	{
		skill.inc_skill_level(1);
		trainedFlag=1;
	}

	if( !trainedFlag )                        // this unit has completed training
		is_under_training = 0;
}
Пример #3
0
//--------- Begin of function Unit::ai_handle_seek_path_fail --------//
//
// This function is used for handling cases when AI units are not
// able to seek a path successfully.
//
int Unit::ai_handle_seek_path_fail()
{
	if( seek_path_fail_count < 5*SEEK_PATH_FAIL_INCREMENT )		// wait unit it has failed many times
		return 0;

	//----- try to move to a new location -----//

	if( seek_path_fail_count==5*SEEK_PATH_FAIL_INCREMENT )
	{
		stop_order();		// stop the unit and think for new action
		return 0;
	}

	//--- if the seek path has failed too many times, resign the unit ---//

	int resignFlag = 0;

	if( rank_id == RANK_SOLDIER && !leader_unit_recno )
	{
		if( seek_path_fail_count>=7*SEEK_PATH_FAIL_INCREMENT )
			resignFlag = 1;
	}
	else if( rank_id == RANK_GENERAL )
	{
		if( seek_path_fail_count >= (7+skill_level()/10)*SEEK_PATH_FAIL_INCREMENT )
			resignFlag = 1;
	}
	else
	{
		if( seek_path_fail_count >= 7*SEEK_PATH_FAIL_INCREMENT )
			resignFlag = 1;
	}

	if( resignFlag && is_visible() )
	{
		resign(COMMAND_AI);
		return 1;
	}
	else
		return 0;
}
Пример #4
0
int Unit::think_general_action()
{
	if( think_leader_action() )
		return 1;

	//--- if the general is not assigned to a camp due to its low competency ----//

	Nation* ownNation = nation_array[nation_recno];
	int 	  rc = 0;

	if( team_info->member_count <= 1 )
	{
		rc = 1;
	}

	//--- if the skill of the general and the number of soldiers he commands is not large enough to justify building a new camp ---//

	else if( skill_level() + team_info->member_count*4
				< 40 + ownNation->pref_keep_general/5 )					// 40 to 60
	{
		rc = 1;
	}

	//-- think about splitting the team and assign them into other forts --//

	else if( ownNation->ai_has_too_many_camp() )
	{
		rc = 1;
	}

	//--------- demote the general to soldier and disband the troop -------//

	if( rc )
	{
		set_rank(RANK_SOLDIER);
		return think_normal_human_action();
	}

	return 0;
}
Пример #5
0
//-------- Begin of function Trainee::advanced_train ------//
//
// Non-basic training: train the unit if it has potential.
//
void Trainee::advanced_train(int firmRecno)
{
	int nationRecno = firm_array[firmRecno]->nation_recno;

	//------ train spy skill --------//

	if( train_spy_potential && spy_skill < MAX_SKILL_TRAIN )
	{
		int incValue = (MAX_SKILL_TRAIN - (int)spy_skill)
			* train_spy_potential / 100;

		incValue = MAX(20,incValue);

		spy_skill += (float) incValue / 100;

		if( spy_skill > MAX_SKILL_TRAIN )
			spy_skill = MAX_SKILL_TRAIN;
	}

	//------ train combat --------//

	if( train_combat_potential && combat_level() < MAX_COMBAT_TRAIN )
	{
		int incValue = (MAX_COMBAT_TRAIN - (int)combat_level() )
			* train_combat_potential / 100;

		incValue = MAX(20,incValue);

		// ###### patch begin Gilbert 16/2 #######//
		// ------ effect of god ----------//

		//if( race_id == RACE_CELTIC && nationRecno 
		//	&& god_res[GOD_CELTIC]->nation_prayer_count(nationRecno) > 0 )
		if( nationRecno && god_res[GOD_CELTIC]->nation_prayer_count(nationRecno) > 0 )
		{
			if( race_id == RACE_CELTIC )
				incValue += incValue / 2;		// 50% skill increase in fort
			else
				incValue += incValue / 5;		// 20% skill increase in fort
		}
		// ###### patch end Gilbert 16/2 #######//

		// ###### patch begin Gilbert 23/12 #########//
		// penalty of egyptain
		if( race_id == RACE_EGYPTIAN && nationRecno
			&& god_res[GOD_EGYPTIAN]->nation_prayer_count(nationRecno) > 0 )
		{
			incValue = incValue * (MAX_WORKER*2) / (MAX_WORKER*2+god_res[GOD_EGYPTIAN]->nation_prayer_count(nationRecno));
		}
		// ###### patch end Gilbert 23/12 #########//

		skill.inc_combat_level( (float)incValue/100 );
	}

	//------ train leadership --------//

	if( train_skill_potential && skill_level() < MAX_SKILL_TRAIN )
	{
		int incValue = (MAX_SKILL_TRAIN - (int)skill_level() )
			* train_skill_potential / 100;

		skill.inc_skill_level( (float)incValue/100 );
	}
}
Пример #6
0
//--------- Begin of function Unit::set_rank ---------//
//
// Only if the unit has leadership skill, it can be a general or king.
//
void Unit::set_rank(int rankId)
{
	err_when( !race_id );

	if( rank_id == rankId )
		return;

   err_when( unit_mode != UNIT_MODE_REBEL && rankId >= RANK_GENERAL && is_civilian() );

   //------- promote --------//

   if( rankId > rank_id )
		change_loyalty(PROMOTE_LOYALTY_INCREASE);

	//------- demote -----------//

	else if( rankId < rank_id && rank_id != RANK_KING )      // no decrease in loyalty if a spy king hands his nation to his parent nation and become a general again
		change_loyalty(-DEMOTE_LOYALTY_DECREASE);

	//---- update nation_general_count_array[] ----//

	if( nation_recno )
	{
		UnitInfo* unitInfo = unit_res[unit_id];

		if( rank_id == RANK_GENERAL )    // if it was a general originally
			unitInfo->dec_nation_general_count(nation_recno);

		if( rankId == RANK_GENERAL )     // if the new rank is general
			unitInfo->inc_nation_general_count(nation_recno);

		//------ if demote a king to a unit ------//

		if( rank_id == RANK_KING && rankId != RANK_KING )
			unitInfo->inc_nation_unit_count(nation_recno);     // since kings are not included in nation_unit_count, when it is no longer a king, we need to re-increase it.

		//------ if promote a unit to a king ------//

		if( rank_id != RANK_KING && rankId == RANK_KING )
			unitInfo->dec_nation_unit_count(nation_recno);     // since kings are not included in nation_unit_count, we need to decrease it
	}

	//----- reset leader_unit_recno if demote a general to soldier ----//

	if( rank_id == RANK_GENERAL && rankId == RANK_SOLDIER )
	{
		//----- reset leader_unit_recno of the units he commands ----//

		for( int i=unit_array.size() ; i>0 ; i-- )
		{
			Unit* unitPtr = (Unit*) unit_array.get_ptr(i);		// don't use is_deleted() as it filters out units that are currently dying 

			if( unitPtr && unitPtr->leader_unit_recno == sprite_recno )
			{
				unitPtr->leader_unit_recno = 0;
//				unitPtr->team_id = 0;
			}
		}

		//--------- deinit team_info ---------//

		err_when( !team_info );

		mem_del(team_info);
		team_info = NULL;
//		team_id   = 0;
	}

	//----- if this is a soldier being promoted to a general -----//

	else if( rank_id == RANK_SOLDIER && rankId == RANK_GENERAL )
	{
		//-- if this soldier is formerly commanded by a general, detech it ---//

		if( leader_unit_recno )
		{
			if( !unit_array.is_deleted(leader_unit_recno) )    // the leader unit may have been killed at the same time
			{
				err_when( !unit_array[leader_unit_recno]->team_info );
				unit_array[leader_unit_recno]->team_info->del_member(sprite_recno);
			}

			leader_unit_recno = 0;
		}
	}

	// ###### patch begin Gilbert 27/9 #######//
	// ------- clear royal in campaign mode -----//

	if( rankId == RANK_KING )
	{
		is_royal = 0;
	}
	// ###### patch end Gilbert 27/9 #######//

	//-------------- update AI info --------------//

	if( nation_recno )
	{
		if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
			nation_array[nation_recno]->del_general_info(sprite_recno);

		rank_id = rankId;

		if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
			nation_array[nation_recno]->add_general_info(sprite_recno);
	}
   else
   {
      rank_id = rankId;
   }

   //----- if this is a general/king ------//

   if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
   {
      //--------- init team_info -------//

      if( !team_info )
      {
         team_info = (TeamInfo*) mem_add( sizeof(TeamInfo) );
			memset( team_info, 0, sizeof(TeamInfo) );
      }

      //--- set leadership if this unit does not have any now ----//

		if( skill_level() < 10 )
			skill.set_skill_level( + m.random(40) );
   }

   //------ refresh if the current unit is selected -----//

	if( unit_array.selected_recno == sprite_recno )
		info.disp();
}
Пример #7
0
void
command_interpreter (CHAR_DATA * ch, char *argument)
{
	char buf[MAX_STRING_LENGTH];
	char *command_args, *p, *social_args;
	int cmd_level = 0;
	int i = 0, echo = 1;
	AFFECTED_TYPE *craft_affect = NULL;
	AFFECTED_TYPE *af;
	ALIAS_DATA *alias;
	extern int second_affect_active;

	if (!ch)
		return;

	*buf = '\0';

	p = argument;

	while (*p == ' ')
		p++;

	if (strchr (p, '%'))
	{
		send_to_char ("Input with the '%' character is not permitted.\n", ch);
		return;
	}

	if (strchr (p, '#') && IS_MORTAL (ch) && strncmp (p, "ge", 2) != 0
		&& strncmp (p, "buy", 3) != 0)
	{
		send_to_char ("Input with the '#' character is not permitted.\n", ch);
		return;
	}

	if (IS_MORTAL (ch) && strchr (p, '$'))
	{
		send_to_char ("Input with the '$' character is not permitted.\n", ch);
		return;
	}

	std::multimap<int, room_prog>::iterator it;
	if (IS_NPC(ch))
		it = mob_prog_list.find(ch->mob->nVirtual); 
	if (IS_NPC(ch) && !get_second_affect (ch, SA_DOANYWAY, 0) && it != mob_prog_list.end())
	{
		if (m_prog(ch, p))
		{
			return;
		}
	}
	std::pair<std::multimap<int, room_prog>::iterator, std::multimap<int, room_prog>::iterator> pair;

	if (ch->right_hand && !get_second_affect (ch, SA_DOANYWAY, 0))
	{
		pair = obj_prog_list.equal_range(ch->right_hand->nVirtual);
		for (it = pair.first; it != pair.second; it++)
		{
			if (it->second.type != 1 && it->second.type != 3 && it->second.type != 5)
				continue;
			if (o_prog(ch, p, it->second))
				return;
		}
	}
	if (ch->left_hand && !get_second_affect (ch, SA_DOANYWAY, 0))
	{
		pair = obj_prog_list.equal_range(ch->left_hand->nVirtual);
		for (it = pair.first; it != pair.second; it++)
		{
			if (it->second.type != 1 && it->second.type != 3 && it->second.type != 5)
				continue;
			if (o_prog(ch, p, it->second))
				return;
		}
	}
	for (OBJ_DATA *tobj = ch->equip; tobj; tobj = tobj->next_content)
	{
		if (get_second_affect (ch, SA_DOANYWAY, 0))
			break;

		pair = obj_prog_list.equal_range(tobj->nVirtual);
		for (it = pair.first; it != pair.second; it++)
		{
			if (it->second.type != 2 && it->second.type != 3 && it->second.type != 5)
				continue;
			if (o_prog(ch, p, it->second))
				return;
		}

	}

	/* this is where it crashes on the hour - Grommit */

	if (!ch->room )
	{
		std::ostringstream stream;
		stream << "Error in command_interpreter:commands.cpp. Command \"" << 
			argument << "\" called by \"" << ch->tname << "\" with null room. Previously in "
			<< (ch->last_room) << " entering null room from the " << (dirs[ch->from_dir]) << ".";

		system_log(stream.str().c_str(),true);
		return;
	}

	/* end grommit diagnostics to avoid segfaulting on the below for loop */

	for (OBJ_DATA *tobj = ch->room->contents; tobj; tobj = tobj->next_content)
	{
		if (get_second_affect (ch, SA_DOANYWAY, 0))
			break;

		pair = obj_prog_list.equal_range(tobj->nVirtual);
		for (it = pair.first; it != pair.second; it++)
		{
			if (it->second.type != 4 && it->second.type != 5)
				continue;
			if (o_prog(ch, p, it->second))
				return;
		}

	}

	for (CHAR_DATA *temp_char = ch->room->people; temp_char; temp_char = temp_char->next_in_room)
	{
		if (get_second_affect (ch, SA_DOANYWAY, 0))
			break;

		if (temp_char == ch)
			continue;

		if (!IS_NPC(temp_char))
			continue;

		pair = mob_prog_list.equal_range(temp_char->mob->nVirtual);

		for (it = pair.first; it != pair.second; ++it)
		{
			if (m_prog(ch, p, it->second))
				return;
		}
	}

	if (ch->room && ch->room->prg && !get_second_affect(ch, SA_DOANYWAY, 0) && r_program (ch, p))
	{
		if (!IS_NPC (ch)
			|| (ch->desc && (ch->pc && str_cmp (ch->pc->account_name, "Guest"))))
		{
			player_log (ch, "[RPROG]", p);
		}
		if (!IS_SET (commands[i].flags, C_NWT))
			show_to_watchers (ch, argument);
		return;
	}
	if (get_second_affect(ch, SA_DOANYWAY, 0))
		remove_second_affect(get_second_affect(ch, SA_DOANYWAY, 0));

	if (!IS_MORTAL (ch) && !str_cmp (argument, "sho wl"))
	{
		send_to_char
			("Heh heh. Glad I added in this check, aren't we? No shouting for you.\n",
			ch);
		return;
	}

	if (ch->desc)
	{
		last_descriptor = ch->desc;
		sprintf (full_last_command, "Last Command Issued, by %s [%d]: %s",
			ch->tname, ch->in_room, argument);
		sprintf (last_command, "%s", argument);
	}

	social_args = argument;

	command_args = one_argument (argument, buf);

	if (!*buf)
		return;

	while (*command_args == ' ')
		command_args++;

	if (ch->pc && !GET_FLAG (ch, FLAG_ALIASING))
	{

		if ((alias = is_alias (ch, buf)))
		{

			ch->flags |= FLAG_ALIASING;

			while (alias)
			{

				command_interpreter (ch, alias->line);

				if (ch->deleted)
					return;

				alias = alias->next_line;
			}

			ch->flags &= ~FLAG_ALIASING;

			return;
		}
	}

	for (i = 1; *commands[i].command; i++)
		if (is_abbrev (buf, commands[i].command))
			break;

	if ((craft_affect = is_craft_command (ch, argument)))
		i = 0;

	if (IS_SET (commands[i].flags, C_IMP)) {
		cmd_level = 6;
	}
	else if (IS_SET (commands[i].flags, C_LV5)) {
		cmd_level = 5;
	}
	else if (IS_SET (commands[i].flags, C_LV4)) {
		cmd_level = 4;
	}
	else if (IS_SET (commands[i].flags, C_LV3)) {
		cmd_level = 3;
	}
	else if (IS_SET (commands[i].flags, C_LV2)) {
		cmd_level = 2;
	}
	else if (IS_SET (commands[i].flags, C_LV1)) {
		cmd_level = 1;
	}

	if (IS_SET (commands[i].flags, C_GDE)
		&& (IS_NPC (ch) || (!ch->pc->is_guide && !ch->pc->level)))
	{
		send_to_char ("Eh?\n\r", ch);
		return;
	}
	/* 
	Need to pass the CHAR_DATA pointer for the person who made the command and modify
	the following line to test the commanding char's trust against the trust level for
	the command.  - Methuselah
	*/

	if ((!*commands[i].command) 
		|| (cmd_level > GET_TRUST (ch)))
	{
		if (!social (ch, argument))
		{
			echo = number (1, 9);
			if (echo == 1)
				send_to_char ("Eh?\n\r", ch);
			else if (echo == 2)
				send_to_char ("Huh?\n\r", ch);
			else if (echo == 3)
				send_to_char ("I'm afraid that just isn't possible...\n\r", ch);
			else if (echo == 4)
				send_to_char ("I don't recognize that command.\n\r", ch);
			else if (echo == 5)
				send_to_char ("What?\n\r", ch);
			else if (echo == 6)
				send_to_char
				("Perhaps you should try typing it a different way?\n\r", ch);
			else if (echo == 7)
				send_to_char
				("Try checking your typing - I don't recognize it.\n\r", ch);
			else if (echo == 8)
				send_to_char
				("That isn't a recognized command, craft, or social.\n\r", ch);
			else
				send_to_char ("Hmm?\n\r", ch);
		}
		else
		{
			if (!IS_SET (commands[i].flags, C_NWT))
				show_to_watchers (ch, argument);
		}
		return;
	}

	if (ch->stun)
	{
		send_to_char ("You're still reeling.\n", ch);
		return;
	}

	if (ch->roundtime)
	{
		sprintf (buf, "You'll need to wait another %d seconds.\n",
			ch->roundtime);
		send_to_char (buf, ch);
		return;
	}

	if (IS_SET (commands[i].flags, C_WLK) &&
		(ch->moves || GET_FLAG (ch, FLAG_LEAVING)
		|| GET_FLAG (ch, FLAG_ENTERING)))
	{
		send_to_char ("Stop traveling first.\n\r", ch);
		return;
	}

	if (IS_SET (commands[i].flags, C_MNT) && IS_RIDER (ch))
	{
		send_to_char ("Get off your mount first.\n", ch);
		return;
	}

	if (commands[i].min_position > GET_POS (ch))
	{
		switch (GET_POS (ch))
		{
		case DEAD:
			if (IS_MORTAL (ch))
			{
				send_to_char ("You are dead.  You can't do that.\n\r", ch);
				return;
			}
		case UNCON:
		case MORT:
			send_to_char ("You're seriously wounded and unconscious.\n\r", ch);
			return;

		case STUN:
			send_to_char ("You're too stunned to do that.\n\r", ch);
			return;

		case SLEEP:
			send_to_char ("You can't do that while sleeping.\n\r", ch);
			return;

		case REST:
			send_to_char ("You can't do that while lying down.\n\r", ch);
			return;

		case SIT:
			send_to_char ("You can't do that while sitting.\n\r", ch);
			return;

		case FIGHT:
			send_to_char ("No way! You are fighting for your life!\n\r", ch);
			return;
		}

		return;
	}

	if (!IS_NPC (ch) && ch->pc->create_state == STATE_DIED &&
		!IS_SET (commands[i].flags, C_DOA))
	{
		send_to_char ("You can't do that when you're dead.\n\r", ch);
		return;
	}

	if (!IS_SET (commands[i].flags, C_BLD) && is_blind (ch))
	{
		if (get_equip (ch, WEAR_BLINDFOLD))
			send_to_char ("You can't do that while blindfolded.\n\r", ch);
		else
			send_to_char ("You can't do that while blind.\n\r", ch);
		return;
	}

	if ((af = get_affect (ch, MAGIC_AFFECT_PARALYSIS)) &&
		!IS_SET (commands[i].flags, C_PAR) && IS_MORTAL (ch))
	{
		send_to_char ("You can't move.\n", ch);
		return;
	}

	if (IS_SUBDUEE (ch) && !IS_SET (commands[i].flags, C_SUB) && !cmd_level)
	{
		act ("$N won't let you.", false, ch, 0, ch->subdue, TO_CHAR);
		return;
	}

	/* Most commands break delays */

	if (ch->delay && !IS_SET (commands[i].flags, C_DEL))
		break_delay (ch);

	/* Send this command to the log */
	if (!second_affect_active && (!IS_NPC (ch) || ch->desc))
	{
		if (IS_SET (commands[i].flags, C_NLG))
			;
		else if (i > 0)
		{			/* Log craft commands separately. */
			if (!str_cmp (commands[i].command, "."))
				player_log (ch, "say", command_args);
			else if (!str_cmp (commands[i].command, ","))
				player_log (ch, "emote", command_args);
			else if (!str_cmp (commands[i].command, ":"))
				player_log (ch, "emote", command_args);
			else if (!str_cmp (commands[i].command, ";"))
				player_log (ch, "wiznet", command_args);
			else
				player_log (ch, commands[i].command, command_args);
		}
	}

	if (IS_MORTAL (ch) && get_affect (ch, MAGIC_HIDDEN) &&
		!IS_SET (commands[i].flags, C_HID) &&
		skill_level (ch, SKILL_SNEAK, 0) < number (1, MAX(100, skill_level(ch, SKILL_SNEAK, 0))) &&
		would_reveal (ch))
	{
		remove_affect_type (ch, MAGIC_HIDDEN);
		act ("$n reveals $mself.", true, ch, 0, 0, TO_ROOM | _ACT_FORMAT);
		act ("Your actions have compromised your concealment.", true, ch, 0, 0,
			TO_CHAR);
	}

	/* Execute command */

	if (!IS_SET (commands[i].flags, C_NWT))
		show_to_watchers (ch, social_args);

	if (!i)			/* craft_command */
		craft_command (ch, command_args, craft_affect);
	else

		(*commands[i].proc) (ch, command_args, 0);

	last_descriptor = NULL;
}
Пример #8
0
//--------- Begin of function Unit::think_independent_hero --------//
//
void Unit::think_independent_hero()
{
	//------ think about go to serve a kingdom -------//

	int bestNationRecno=0, curRating;

	int bestRating = (skill_level() + combat_level()/2) / 3;

	if( item.id )
		bestRating += (item_res.rareness(item.id)+1) * 10;

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

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

		Nation* nationPtr = nation_array[i];

		curRating = (int) nationPtr->reputation + nationPtr->overall_rating;

		if( sprite_recno%2==0 )			// some heroes look at kill_monster_score, but some don't
			curRating += (int) nationPtr->kill_monster_score/10;

		if( race_id == nationPtr->race_id )
			curRating += 10;

		if( curRating > bestRating )
		{
			bestRating = curRating;
			bestNationRecno = i;
		}
	}

	if( bestNationRecno )
	{
		//------ change nation now --------//

		if( !betray(bestNationRecno) )
			return;

		//---- the unit moves close to the newly joined nation ----//

		ai_move_to_nearby_town();
		return;
	}

	//---- randomly locate a destination to walk to ----//

	int xLoc, yLoc, regionId = region_id();

	for( i=100 ; i>0 ; i-- )
	{
		xLoc = m.random(MAX_WORLD_X_LOC);
		yLoc = m.random(MAX_WORLD_Y_LOC);

		Location* locPtr = world.get_loc(xLoc, yLoc);

		if( locPtr->walkable() && locPtr->region_id == regionId )
			break;
	}

	if( i==0 )
		return;

	move(xLoc, yLoc);
}
Пример #9
0
//--------- Begin of function Unit::update_loyalty ---------//
//
// How loyalty of units are updated:
//
// General: in a military camp - updated in FirmCamp::update_loyalty()
//          mobile - no update
//
// Soldiers led by a general: in a military camp - updated in FirmCamp::update_loyalty()
//                            mobile - updated here
//
// Other units: no update.
//
void Unit::update_loyalty()
{
	if( !nation_recno || rank_id==RANK_KING || !race_id )
		return;

	if( unit_mode == UNIT_MODE_CONSTRUCT_FIRM || 		// constructor worker will not change their loyalty when they are in a building
		 unit_mode == UNIT_MODE_CONSTRUCT_TOWN )
	{
		return;
   }

	//--- the loyalty of civilians does not change when they are mobile ---//

	if( is_civilian() )
	{
		target_loyalty = loyalty;
		return;
	}

	//-------- if this is a general ---------//

	Nation* ownNation = nation_array[nation_recno];
	int 	  rc=0;

	if( rank_id==RANK_GENERAL )
	{
		//----- the general's power affect his loyalty ----//

		int targetLoyalty = commander_power();

		//----- the king's race affects the general's loyalty ----//

		if( ownNation->race_id == race_id )
			targetLoyalty += 20;

		//----- the kingdom's reputation affects the general's loyalty ----//

		targetLoyalty += (int)ownNation->reputation/4;

		//--- the king's leadership also affect the general's loyalty -----//

		if( ownNation->king_unit_recno )
			targetLoyalty += unit_array[ownNation->king_unit_recno]->skill_level() / 4;

		//-- if the unit is rewarded less than the amount of contribution he made, he will become unhappy --//

		if( nation_contribution > total_reward*2 )
		{
			int decLoyalty = (nation_contribution - total_reward*2)/2;
			targetLoyalty -= min(50, decLoyalty);		// this affect 50 points at maximum
		}

		targetLoyalty = min( targetLoyalty, 100 );
		target_loyalty = max( targetLoyalty, 0 );

		//----- if this unit is a spy, set its fake loyalty ------//

		if( spy_recno )		// it should never go below the rebel level
			target_loyalty = max( 30+sprite_recno%10, target_loyalty );
	}

	//-------- if this is a soldier ---------//

	else if( rank_id==RANK_SOLDIER )
	{
		if( leader_unit_recno )
		{
			//----------------------------------------//
			//
			// If this soldier is led by a general,
			// the targeted loyalty
			//
			// = race friendliness between the unit and the general / 2
			//   + the leader unit's leadership / 2
			//
			//----------------------------------------//

			if( unit_array.is_deleted(leader_unit_recno) )
			{
				leader_unit_recno = 0;
				return;
			}

			Unit* leaderUnit = unit_array[leader_unit_recno];

			int targetLoyalty = 30 + leaderUnit->skill_level();

			//---------------------------------------------------//
			//
			// Soldiers with higher combat and leadership skill
			// will get discontented if they are led by a general
			// with low leadership.
			//
			//---------------------------------------------------//

			targetLoyalty -= combat_level()/2;
			targetLoyalty -= skill_level();

			if( leaderUnit->rank_id == RANK_KING )
				targetLoyalty += 20;

			if( race_res.is_same_race(race_id, leaderUnit->race_id) )
				targetLoyalty += 20;

			if( targetLoyalty < 0 )
				targetLoyalty = 0;

			targetLoyalty = min( targetLoyalty, 100 );
			target_loyalty = max( targetLoyalty, 0 );
		}
		else
		{
			target_loyalty = 0;
		}
	}

	//--------- update loyalty ---------//

	err_when( target_loyalty < 0 || target_loyalty > 100 );

	if( target_loyalty > loyalty )      // only increase, no decrease. Decrease are caused by events. Increases are made gradually
	{
		int incValue = (target_loyalty - loyalty)/10;

		int newLoyalty = (int) loyalty + max(1, incValue);

		if( newLoyalty > target_loyalty )
			newLoyalty = target_loyalty;

		loyalty = newLoyalty;
	}
	else if( target_loyalty < loyalty )      // only increase, no decrease. Decrease are caused by events. Increases are made gradually
	{
		loyalty--;
	}

	err_when( loyalty < 0 || loyalty > 100 );
}
Пример #10
0
//--------- Begin of function InnUnit::set_hire_cost ---------//
//
void InnUnit::set_hire_cost()
{
	hire_cost = hero_res.hire_cost( combat_level(), skill.max_combat_level,
					skill_level(), spy_skill, &item );
}
Пример #11
0
int Unit::think_assign_soldier_to_camp()
{
	//---- think about assign the unit to a camp/fort that needs soldiers ----//

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

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

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

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

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

		curRating = 0;

		//----- if the camp is already full of soldier ------//

		if( firmCamp->is_soldier_full() )
		{
			//---- get the lowest skill soldier of the firm -----//

			Soldier* soldierPtr = firmCamp->soldier_array;
			int	   minSkill=100;

			for( int j=0 ; j<firmCamp->soldier_count ; j++, soldierPtr++ )
			{
				if( soldierPtr->is_under_training() )
					continue;

				if( soldierPtr->skill_level() < minSkill )
					minSkill = soldierPtr->skill_level();
			}

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

			if( firmCamp->majority_race() == race_id )
			{
				if( skill_level() < minSkill+10 )
					continue;
			}
			else //-- for different race, only assign if the skill is significantly higher than the existing ones --//
			{
				if( skill_level() < minSkill+30 )
					continue;
			}
		}
		else
		{
			curRating += 300;		// if the firm is not full, rating + 300
		}

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

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

		if( firmCamp->majority_race() == race_id )
			curRating += 70;

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

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

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

	if( bestFirm )
	{
		assign(bestFirm->loc_x1, bestFirm->loc_y1);
		return 1;
	}
	else
		return 0;
}
Пример #12
0
//--------- Begin of function Unit::think_leader_action --------//
//
// Think about the action of a leader (either a general or a king).
//
int Unit::think_leader_action()
{
	Nation*   nationPtr = nation_array[nation_recno];
	FirmCamp *firmCamp, *bestCamp=NULL;
	int		 curRating, bestRating=10, delActionRecno=0;
	int		 curXLoc = next_x_loc(), curYLoc = next_y_loc();
	int		 curRegionId = world.get_region_id( curXLoc, curYLoc );

	if( rank_id == RANK_KING )		// if this unit is the king, always assign it to a camp regardless of whether the king is a better commander than the existing one
		bestRating = -1000;

	//----- think about which camp to move to -----//

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

		if( firmCamp->region_id != curRegionId )
			continue;

		if( firmCamp->should_close_flag )
			continue;

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

		//--- if the commander of this camp is the king, never replace him ---//

		if( firmCamp->overseer_recno == nationPtr->king_unit_recno )
			continue;

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

		int curLeadership = firmCamp->cur_commander_leadership();
		int newLeadership = firmCamp->new_commander_leadership(race_id, skill_level());

		curRating = newLeadership - curLeadership;

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

		if( curRating > bestRating )
		{
			//--- if there is already somebody being assigned to it ---//

			int actionRecno=0;

			if( rank_id != RANK_KING )			// don't check this if the current unit is the king
			{
				actionRecno = nationPtr->is_action_exist(firmCamp->loc_x1, firmCamp->loc_y1,
								  -1, -1, ACTION_AI_ASSIGN_OVERSEER, firmCamp->firm_id);

				if( actionRecno && nationPtr->get_action(actionRecno)->processing_instance_count )
					continue;
			}

			bestRating = curRating;
			bestCamp   = firmCamp;
			delActionRecno = actionRecno;
		}
	}

	if( !bestCamp )
		return 0;

	//----- delete an unprocessed queued action if there is any ----//

	if( delActionRecno )
		nationPtr->del_action(delActionRecno);

	//--------- move to the camp now ---------//

	//-- if there is room in the camp to host all soldiers led by this general --//

	if( team_info->member_count-1 <= MAX_SOLDIER-bestCamp->soldier_count )
	{
		team_info->validate();

		if( team_info->member_count > 0 )
		{
			unit_group.set(team_info->member_unit_array, team_info->member_count);
			unit_group.assign( bestCamp->loc_x1, bestCamp->loc_y1, UNIT_LAND, COMMAND_AI );
			return 1;
		}
	}
	
	//--- otherwise assign the general only ---//

	return nationPtr->add_action(bestCamp->loc_x1, bestCamp->loc_y1, -1,
			 -1, ACTION_AI_ASSIGN_OVERSEER, bestCamp->firm_id, 1, sprite_recno);
}
Пример #13
0
int Unit::think_reward()
{
	Nation* ownNation = nation_array[nation_recno];

	//----------------------------------------------------------//
	// The need to secure high loyalty on this unit is based on:
	// -its skill
	// -its combat level 
	// -soldiers commanded by this unit
	//----------------------------------------------------------//

	if( spy_recno && true_nation_recno() == nation_recno )		// if this is a spy of ours
	{
		return 0;		// Spy::think_reward() will handle this.
	}

	int curLoyalty = loyalty;
	int neededLoyalty;

	//----- if this unit is on a mission ------/

	if( cur_order.ai_action_id )
	{
		neededLoyalty = UNIT_BETRAY_LOYALTY+10;
	}

	//----- otherwise only reward soldiers and generals ------//

	else if( !is_civilian() )		// it is a military unit
	{
		//----- calculate the needed loyalty --------//

		neededLoyalty = commanded_soldier_count()*5 + skill_level();

		if( unit_mode == UNIT_MODE_OVERSEE )		// if this unit is an overseer
		{
			if( loyalty < UNIT_BETRAY_LOYALTY )		// if this unit's loyalty is < betrayel level, reward immediately
			{
				reward(nation_recno);		// reward it immediatley if it's an overseer, don't check ai_should_spend()
				return 1;
			}

			neededLoyalty += 30;
		}

		neededLoyalty = MAX( UNIT_BETRAY_LOYALTY+10, neededLoyalty );		// 10 points above the betray loyalty level to prevent betrayal
		neededLoyalty = MIN( 100, neededLoyalty );
	}
	else
	{
		return 0;
	}

	//------- if the loyalty is already high enough ------//

	if( curLoyalty >= neededLoyalty )
		return 0;

	//---------- see how many cash & profit we have now ---------//

	int rewardNeedRating = neededLoyalty - curLoyalty;

	if( curLoyalty < UNIT_BETRAY_LOYALTY+5 )
		rewardNeedRating += 50;

	if( ownNation->ai_should_spend(rewardNeedRating) )
	{
		reward(nation_recno);
		return 1;
	}

	return 0;
}