//--------- 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); } } }
//-------- 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; }
//--------- 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; }
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; }
//-------- 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 ); } }
//--------- 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(); }
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; }
//--------- 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); }
//--------- 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 ); }
//--------- 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 ); }
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; }
//--------- 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); }
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; }