/*
* Seven Kingdoms: Ancient Adversaries
*
* Copyright 1997,1998 Enlight Software Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
//Filename : OFIRMAI.CPP
//Description : AI functions for the class Firm
#include
#include
#include
#include
#include
#include
#include
#include
//--------- Begin of function Firm::process_common_ai --------//
//
// AI processing functions common for all firm types.
//
void Firm::process_common_ai()
{
if( info.game_date%30==firm_recno%30 )
think_repair();
//------ think about closing this firm ------//
if( !should_close_flag )
{
if( ai_should_close() )
{
should_close_flag = 1;
nation_array[nation_recno]->firm_should_close_array[firm_id-1]++;
}
}
}
//--------- End of function Firm::process_common_ai --------//
//------- Begin of function Firm::think_repair -----------//
//
void Firm::think_repair()
{
Nation* ownNation = nation_array[nation_recno];
//----- check if the damage is serious enough -----//
if( hit_points >=
max_hit_points * (70+ownNation->pref_repair_concern/4) / 100 ) // 70% to 95%
{
return;
}
//--- if it's no too heavily damaged, it is just that the AI has a high concern on this ---//
if( hit_points >= max_hit_points * 80 / 100 )
{
if( ownNation->total_jobless_population < 15 )
return;
}
//------- queue assigning a construction worker now ------//
ownNation->add_action(loc_x1, loc_y1, -1, -1, ACTION_AI_ASSIGN_CONSTRUCTION_WORKER, firm_id);
}
//--------- End of function Firm::think_repair -----------//
//------- Begin of function Firm::ai_del_firm -----------//
//
// Delete the firm no matter what status this firm is in.
//
void Firm::ai_del_firm()
{
if( under_construction )
{
cancel_construction(COMMAND_PLAYER);
}
else
{
if( can_sell() )
sell_firm(COMMAND_AI);
else
destruct_firm(COMMAND_AI);
}
}
//--------- End of function Firm::ai_del_firm -----------//
//------- Begin of function Firm::ai_should_close -----------//
//
// This is function is for derived class to overload.
//
int Firm::ai_should_close()
{
return 0;
}
//--------- End of function Firm::ai_should_close -----------//
//------- Begin of function Firm::think_hire_inn_unit -------//
//
int Firm::think_hire_inn_unit()
{
if( !nation_array[nation_recno]->ai_should_hire_unit(30) ) // 30 - importance rating
return 0;
//---- one firm only hire one foreign race worker ----//
int i, foreignRaceCount=0;
int majorityRace = majority_race();
if( majorityRace )
{
for( i=0 ; ipref_town_harmony;
for( i=0 ; iai_inn_count ; i++ )
{
firmInn = (FirmInn*) firm_array[ nationPtr->ai_inn_array[i] ];
if( firmInn->region_id != region_id )
continue;
InnUnit* innUnit = firmInn->inn_unit_array;
for( int j=0 ; jinn_unit_count ; j++, innUnit++ )
{
if( innUnit->skill.skill_id != firm_skill_id )
continue;
//-------------------------------------------//
// Rating of a unit to be hired is based on:
//
// -distance between the inn and this firm.
// -whether the unit is racially homogenous to the majority of the firm workers
//
//-------------------------------------------//
curRating = world.distance_rating( center_x, center_y,
firmInn->center_x, firmInn->center_y );
curRating += innUnit->skill.skill_level;
if( majorityRace == unit_res[innUnit->unit_id]->race_id )
{
curRating += prefTownHarmony;
}
else
{
//----------------------------------------------------//
// Don't pick this unit if it isn't racially homogenous
// to the villagers, and its pref_town_harmony is higher
// than its skill level. (This means if its skill level
// is low, its chance of being selected is lower.
//----------------------------------------------------//
if( majorityRace )
{
if( foreignRaceCount>0 || prefTownHarmony > innUnit->skill.skill_level-50 )
continue;
}
}
if( curRating > bestRating )
{
bestRating = curRating;
bestInn = firmInn;
bestInnUnitId = j+1;
}
}
}
//-----------------------------------------//
if( bestInn )
{
int unitRecno = bestInn->hire(bestInnUnitId);
if( unitRecno )
{
unit_array[unitRecno]->assign(loc_x1, loc_y1);
return 1;
}
}
return 0;
}
//--------- End of function Firm::think_hire_inn_unit -------//
//------- Begin of function Firm::being_attacked -----------//
//
void Firm::being_attacked(int attackerUnitRecno)
{
last_attacked_date = info.game_date;
if( nation_recno && firm_ai )
{
if( unit_array[attackerUnitRecno]->nation_recno == nation_recno ) // this can happen when the unit has just changed nation
return;
nation_array[nation_recno]->ai_defend(attackerUnitRecno);
}
}
//--------- End of function Firm::being_attacked -----------//
//------- Begin of function Firm::ai_recruit_worker -----------//
//
int Firm::ai_recruit_worker()
{
if( worker_count == MAX_WORKER )
return 0;
Nation* nationPtr = nation_array[nation_recno];
Town* townPtr;
for( int i=0; ination_recno != nation_recno &&
nationPtr->total_jobless_population > MAX_WORKER )
{
continue;
}
if( townPtr->jobless_population > 0 )
return 0; // don't order units to move into it as they will be recruited from the town automatically
}
//---- order workers to move into the firm ----//
nationPtr->add_action(loc_x1, loc_y1, -1, -1, ACTION_AI_ASSIGN_WORKER, firm_id, MAX_WORKER-worker_count);
return 1;
}
//--------- End of function Firm::ai_recruit_worker -----------//
//------- Begin of function Firm::ai_build_neighbor_firm -----------//
//
int Firm::ai_build_neighbor_firm(int firmId)
{
short buildXLoc, buildYLoc;
Nation* nationPtr = nation_array[nation_recno];
if( !nationPtr->find_best_firm_loc(firmId, loc_x1, loc_y1, buildXLoc, buildYLoc) )
{
no_neighbor_space = 1;
return 0;
}
nationPtr->add_action(buildXLoc, buildYLoc, loc_x1, loc_y1, ACTION_AI_BUILD_FIRM, firmId);
return 1;
}
//--------- End of function Firm::ai_build_neighbor_firm -----------//
//--------- Begin of function Firm::ai_update_link_status ---------//
//
// Updating link status of this firm with towns.
//
void Firm::ai_update_link_status()
{
err_when( firm_id == FIRM_CAMP ); // FirmCamp has its own ai_update_link_status(), this version shouldn't be called.
if( !worker_array ) // if this firm does not need any workers.
return;
if( is_worker_full() ) // if this firm already has all the workers it needs.
return;
//------------------------------------------------//
Nation* ownNation = nation_array[nation_recno];
int i, rc;
for( i=0 ; ination_recno==0 || // either it's an independent town or it's friendly or allied to our nation
ownNation->get_relation_status(townPtr->nation_recno) >= NATION_FRIENDLY;
toggle_town_link( i+1, rc, COMMAND_AI );
}
}
//----------- End of function Firm::ai_update_link_status ----------//
//------- Begin of function Firm::think_build_factory -----------//
//
int Firm::think_build_factory(int rawId)
{
if( no_neighbor_space ) // if there is no space in the neighbor area for building a new firm.
return 0;
Nation* nationPtr = nation_array[nation_recno];
//--- check whether the AI can build a new firm next this firm ---//
if( !nationPtr->can_ai_build(FIRM_FACTORY) )
return 0;
//---------------------------------------------------//
int factoryCount=0;
FirmFactory* firmPtr;
Firm* firmMarket;
for(int i=0; ifirm_id!=FIRM_FACTORY)
continue;
if( firmPtr->nation_recno != nation_recno )
continue;
if( firmPtr->product_raw_id != rawId )
continue;
//--- if one of own factories still has not recruited enough workers ---//
if( firmPtr->worker_count < MAX_WORKER )
return 0;
//---------------------------------------------------//
//
// If this factory has a medium to high level of stock,
// this means the bottleneck is not at the factories,
// building more factories won't solve the problem.
//
//---------------------------------------------------//
if( firmPtr->stock_qty > firmPtr->max_stock_qty * 0.1 )
return 0;
//---------------------------------------------------//
//
// Check if this factory is just outputing goods to
// a market and it is actually not overcapacity.
//
//---------------------------------------------------//
for( int j=firmPtr->linked_firm_count-1 ; j>=0 ; j-- )
{
if( firmPtr->linked_firm_enable_array[j] != LINK_EE )
continue;
firmMarket = firm_array[ firmPtr->linked_firm_array[j] ];
if( firmMarket->firm_id != FIRM_MARKET )
continue;
//--- if this factory is producing enough goods to the market place, then it means it is still quite efficient
MarketGoods *marketGoods = ((FirmMarket*)firmMarket)->market_product_array[rawId-1];
if( marketGoods && marketGoods->stock_qty > 100 )
return 0;
}
//----------------------------------------------//
factoryCount++;
}
//---- don't build additional factory if we don't have enough peasants ---//
if( factoryCount>=1 && !nationPtr->ai_has_enough_food() )
return 0;
//-- if there isn't much raw reserve left, don't build new factories --//
if( firm_id == FIRM_MINE )
{
if( ((FirmMine*)this)->reserve_qty < 1000 && factoryCount>=1 )
return 0;
}
//--- only build additional factories if we have a surplus of labor ---//
if( nationPtr->total_jobless_population < factoryCount * MAX_WORKER )
return 0;
//--- only when we have checked it three times and all say it needs a factory, we then build a factory ---//
if( ++ai_should_build_factory_count >= 3 )
{
short buildXLoc, buildYLoc;
if( !nationPtr->find_best_firm_loc(FIRM_FACTORY, loc_x1, loc_y1, buildXLoc, buildYLoc) )
{
no_neighbor_space = 1;
return 0;
}
nationPtr->add_action(buildXLoc, buildYLoc, loc_x1, loc_y1, ACTION_AI_BUILD_FIRM, FIRM_FACTORY);
ai_should_build_factory_count = 0;
}
return 1;
}
//--------- End of function Firm::think_build_factory -----------//
//------- Begin of function Firm::think_capture -----------//
//
int Firm::think_capture()
{
Nation* nationPtr;
int i;
for( i=nation_array.size() ; i>0 ; i-- )
{
if( nation_array.is_deleted(i) )
continue;
nationPtr = nation_array[i];
if( nationPtr->is_ai() && can_worker_capture(i) )
break;
}
if( i==0 )
return 0;
//------- capture the firm --------//
capture_firm(i);
//------ order troops to attack nearby enemy camps -----//
Firm *firmPtr, *bestTarget=NULL;
int curDistance, minDistance=0x1000;
for( i=firm_array.size() ; i>0 ; i-- )
{
if( firm_array.is_deleted(i) )
continue;
firmPtr = firm_array[i];
//----- only attack enemy camps -----//
if( firmPtr->nation_recno != nation_recno ||
firmPtr->firm_id != FIRM_CAMP )
{
continue;
}
curDistance = m.points_distance(center_x, center_y,
firmPtr->center_x, firmPtr->center_y );
//--- only attack camps within 15 location distance to this firm ---//
if( curDistance < 15 && curDistance < minDistance )
{
minDistance = curDistance;
bestTarget = firmPtr;
}
}
if( bestTarget )
{
int useAllCamp = nationPtr->pref_military_courage > 60 || m.random(3)==0;
nationPtr->ai_attack_target( bestTarget->loc_x1, bestTarget->loc_y1,
((FirmCamp*)bestTarget)->total_combat_level(), 0, 0, 0, 0, useAllCamp );
}
return 1;
}
//--------- End of function Firm::think_capture -----------//
//------- Begin of function Firm::think_linked_town_change_nation ------//
//
// This function is called by Town::set_nation() when a town linked
// to this firm has changed nation.
//
// linkedTownRecno - the recno of the town that has changed nation.
// oldNationRecno - the old nation recno of the town
// newNationRecno - the new nation recno of the town
//
void Firm::think_linked_town_change_nation(int linkedTownRecno, int oldNationRecno, int newNationRecno)
{
}
//-------- End of function Firm::think_linked_town_change_nation ------//
//--------- Begin of function Firm::ai_firm_captured --------//
//
// This is function is called when the AI's firm is just
// about to be captured.
//
void Firm::ai_firm_captured(int capturerNationRecno)
{
Nation* ownNation = nation_array[nation_recno];
if( !ownNation->is_ai() ) //**BUGHERE
return;
if( ownNation->get_relation(capturerNationRecno)->status >= NATION_FRIENDLY )
ownNation->ai_end_treaty(capturerNationRecno);
talk_res.ai_send_talk_msg(capturerNationRecno, nation_recno, TALK_DECLARE_WAR);
}
//--------- End of function Firm::ai_firm_captured --------//