/*
* 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 : ONATION.H
//Description : Header of class Nation
//Owner : Alex
#ifndef __ONATION_H
#define __ONATION_H
#ifndef __ONATIONB_H
#include
#endif
#ifndef __OUNIT_H
#include
#endif
#ifndef __OTOWN_H
#include
#endif
//--------- define parameters ----------//
#define MAX_AI_REGION 20
#define AI_TOWN_INIT_SIZE 60
#define AI_BASE_TOWN_INIT_SIZE 60
#define AI_BASE_INIT_SIZE 20
#define AI_MINE_INIT_SIZE 10
#define AI_FACTORY_INIT_SIZE 50
#define AI_MARKET_INIT_SIZE 50
#define AI_INN_INIT_SIZE 10
#define AI_CAMP_INIT_SIZE 60
#define AI_RESEARCH_INIT_SIZE 30
#define AI_WAR_INIT_SIZE 30
#define AI_HARBOR_INIT_SIZE 10
#define AI_GENERAL_INIT_SIZE 50
#define AI_CARAVAN_INIT_SIZE 100
#define AI_SHIP_INIT_SIZE 50
#define AI_TOWN_INC_SIZE 30
#define AI_BASE_TOWN_INC_SIZE 30
#define AI_BASE_INC_SIZE 10
#define AI_MINE_INC_SIZE 10
#define AI_FACTORY_INC_SIZE 10
#define AI_MARKET_INC_SIZE 10
#define AI_INN_INC_SIZE 10
#define AI_CAMP_INC_SIZE 10
#define AI_RESEARCH_INC_SIZE 10
#define AI_WAR_INC_SIZE 10
#define AI_HARBOR_INC_SIZE 10
#define AI_GENERAL_INC_SIZE 20
#define AI_CARAVAN_INC_SIZE 30
#define AI_SHIP_INC_SIZE 20
//--------------------------------------//
enum { STD_ACTION_RETRY_COUNT = 4, // retry this number of times before giving up
MAX_SCORE = 600,
MIGRATE_DEMAND_SUPPLY_DIFF=25, // suppy > demand + MIGRATE_DEMAND_SUPPLY_DIFF
MIGRATE_STOCK_QTY=150,
TRADE_STOCK_QTY=125,
MAX_TRADE_MARKET = 4,
MAX_BASE_TOWN = 10,
};
enum { ACTION_DYNAMIC, // for ActionNode::action_type
ACTION_FIXED };
enum { ACTION_AI_BUILD_FIRM=1, // define ActionNode action_type
ACTION_AI_ASSIGN_OVERSEER,
ACTION_AI_ASSIGN_CONSTRUCTION_WORKER,
ACTION_AI_ASSIGN_WORKER,
ACTION_AI_ASSIGN_SPY,
ACTION_AI_SCOUT,
ACTION_AI_SETTLE_TO_OTHER_TOWN,
ACTION_AI_PROCESS_TALK_MSG,
ACTION_AI_SEA_TRAVEL,
ACTION_AI_SEA_TRAVEL2,
ACTION_AI_SEA_TRAVEL3,
};
enum { SEA_ACTION_SETTLE=1, // for AI marine actions
SEA_ACTION_BUILD_CAMP,
SEA_ACTION_ASSIGN_TO_FIRM,
SEA_ACTION_MOVE,
SEA_ACTION_NONE, // just transport them to the specific region and disemark and wait for their own actions
};
//--------- define AIRegion ---------//
#pragma pack(1)
struct AIRegion
{
BYTE region_id;
char town_count;
char base_town_count;
};
#pragma pack()
//-------- define ActionNode structure -------//
#pragma pack(1)
struct ActionNode
{
enum { MAX_ACTION_GROUP_UNIT = 9 };
char action_mode; // eg build firm, attack, etc
char action_type;
short action_para; // parameter for the action. e.g. firmId for AI_BUILD_FIRM
short action_para2; // parameter for the action. e.g. firm race id. for building FirmBase
WORD action_id; // an unique id. for identifying this node
long add_date; // when this action is added
short unit_recno;
short action_x_loc; // can be firm loc, or target loc, etc
short action_y_loc;
short ref_x_loc; // reference x loc, eg the raw material location
short ref_y_loc;
char retry_count; // number of term to wait before this action is removed from the array if it cannot be processed
char instance_count; // no. of times this action needs to be carried out
short group_unit_array[MAX_ACTION_GROUP_UNIT]; // for group unit actions, the no. of units in the array is stored in instance_count
char processing_instance_count;
char processed_instance_count;
long next_retry_date; // continue processing this action after this date, this is used when training a unit for construction
};
#pragma pack()
//------- Define struct AttackCamp --------//
#define MAX_SUITABLE_ATTACK_CAMP 30 // total no. of useful camps
#pragma pack(1)
struct AttackCamp
{
short firm_recno;
short combat_level;
short distance;
int patrol_date;
};
#pragma pack()
//--------- Define class Nation ---------//
class Firm;
class Town;
class Spy;
struct TalkMsg;
#pragma pack(1)
class Nation : public NationBase
{
public:
DynArray action_array;
WORD last_action_id; // a 16-bit id. for identifying ActionNode
public:
Nation();
~Nation();
//------------------------------------------------------//
// array used to store the the waiting and procesing actions
//------------------------------------------------------//
int action_count() { return action_array.size(); }
ActionNode* get_action(int recNo) { return (ActionNode*) action_array.get(recNo); }
ActionNode* get_action_based_on_id(int actionId);
//------------------------------------------------------//
// array used to store the info. of the firms
//------------------------------------------------------//
short* ai_town_array;
short* ai_base_array;
short* ai_mine_array;
short* ai_factory_array;
short* ai_camp_array;
short* ai_research_array;
short* ai_war_array;
short* ai_harbor_array;
short* ai_market_array;
short* ai_inn_array;
short* ai_general_array;
short* ai_caravan_array;
short* ai_ship_array;
//--------------------------------------------------------//
// parameters used to make decisions
//--------------------------------------------------------//
short ai_town_size;
short ai_base_size;
short ai_mine_size;
short ai_factory_size;
short ai_camp_size;
short ai_research_size;
short ai_war_size;
short ai_harbor_size;
short ai_market_size;
short ai_inn_size;
short ai_general_size;
short ai_caravan_size;
short ai_ship_size;
short ai_town_count;
short ai_base_count;
short ai_mine_count;
short ai_factory_count;
short ai_camp_count;
short ai_research_count;
short ai_war_count;
short ai_harbor_count;
short ai_market_count;
short ai_inn_count;
short ai_general_count;
short ai_caravan_count;
short ai_ship_count;
short ai_base_town_count;
short firm_should_close_array[MAX_FIRM_TYPE];
//------------------------------------------------------//
// parameters about the nation itself
//------------------------------------------------------//
AIRegion ai_region_array[MAX_AI_REGION];
char ai_region_count;
//------------------------------------------------------//
// AI personalties
//------------------------------------------------------//
char pref_force_projection;
char pref_military_development; // pref_military_development + pref_economic_development = 100
char pref_economic_development;
char pref_inc_pop_by_capture; // pref_inc_pop_by_capture + pref_inc_pop_by_growth = 100
char pref_inc_pop_by_growth;
char pref_peacefulness;
char pref_military_courage;
char pref_territorial_cohesiveness;
char pref_trading_tendency;
char pref_allying_tendency;
char pref_honesty;
char pref_town_harmony;
char pref_loyalty_concern;
char pref_forgiveness;
char pref_collect_tax;
char pref_hire_unit;
char pref_use_weapon;
char pref_keep_general; // whether to keep currently non-useful the general, or demote them.
char pref_keep_skilled_unit; // whether to keep currently non-useful skilled units, or assign them to towns.
char pref_diplomacy_retry; // tedency to retry diplomatic actions after previous ones have been rejected.
char pref_attack_monster;
char pref_spy;
char pref_counter_spy;
char pref_food_reserve;
char pref_cash_reserve;
char pref_use_marine;
char pref_unit_chase_distance;
char pref_repair_concern;
char pref_scout;
//------- AI action vars --------//
short ai_capture_enemy_town_recno;
int ai_capture_enemy_town_plan_date;
int ai_capture_enemy_town_start_attack_date;
char ai_capture_enemy_town_use_all_camp;
int ai_last_defend_action_date;
short ai_attack_target_x_loc;
short ai_attack_target_y_loc;
short ai_attack_target_nation_recno; // nation recno of the target
AttackCamp attack_camp_array[MAX_SUITABLE_ATTACK_CAMP];
short attack_camp_count;
short lead_attack_camp_recno; // the firm recno of the lead attacking firm
public:
//--------------------------------------------------------------//
// functions to init. parameters and process ai actions
//--------------------------------------------------------------//
void init(int nationType, int raceId, int colorSchemeId, DWORD playerId); // init local parameters
void deinit();
void init_all_ai_info();
void init_ai_info(short** aiInfoArray, short& aiInfoCount, short& aiInfoSize, int arrayInitSize );
void deinit_all_ai_info();
void init_personalty();
void process_ai(); // entry point to start ai
void process_ai_main();
void process_on_going_action();
//---------------------------------------------------------------//
// main AI thinking functions
//---------------------------------------------------------------//
void think_trading();
void think_explore();
int think_capture();
void ai_improve_relation();
//---------------------------------------------------------------//
// functions for processing waiting actions
//---------------------------------------------------------------//
int ai_build_firm(ActionNode*);
int ai_assign_overseer(ActionNode*);
int ai_assign_construction_worker(ActionNode*);
int ai_assign_worker(ActionNode*);
int ai_scout(ActionNode*);
int ai_settle_to_other_town(ActionNode*);
int ai_assign_spy(ActionNode*);
//-----------------------------------------------------------//
// functions used to update internal parameters
//-----------------------------------------------------------//
short* update_ai_firm_array(int firmId, int actionType, int actionRecno, int& arrayCount);
short* update_ai_array(short& aiInfoCount, short& aiInfoSize,
short** aiInfoArray, int arrayIncSize, int actionType, int actionRecno);
void add_town_info(short townRecno); // add town information
void del_town_info(short townRecno); // remove town information
void add_firm_info(char firmId, short firmRecno);// add firm information
void del_firm_info(char firmId, short firmRecno);// remove useless information as firm is removed
void add_general_info(short unitRecno);
void del_general_info(short unitRecno);
void add_caravan_info(short unitRecno);
void del_caravan_info(short unitRecno);
void add_ship_info(short unitRecno);
void del_ship_info(short unitRecno);
void assign_firm_overseer(char firm_id, short firm_recno, short overseerUnitRecno); // add overseer information
void remove_firm_overseer(char firm_id, short firm_recno); // remove overseer information
int is_caravan_exist(int firstMarket, int secondMarket, int setStopInternal=0);
void update_ai_region();
AIRegion* get_ai_region(int regionId);
int has_base_town_in_region(int regionId);
//-----------------------------------------------------------//
// functions for building firms
//-----------------------------------------------------------//
void think_build_firm();
int think_build_mine();
int think_destroy_raw_site_guard();
int ai_supported_inn_count();
int ai_has_should_close_camp(int regionId);
int ai_should_build_mine();
//-----------------------------------------------------------//
// functions used to locate position to build firms
//-----------------------------------------------------------//
int seek_mine(short& xLoc, short& yLoc, short& refXLoc, short& refYLoc);
void seek_best_build_mine_location(short& xLoc, short& yLoc, short mapXLoc, short mapYLoc);
void cal_location_score(short x1, short y1, short width, short height, int& weight);
int find_best_firm_loc(short firmId, short refXLoc, short refYLoc, short& resultXLoc, short& resultYLoc);
//------------------------------------------------------------//
// functions for dealing with the AI action array
//------------------------------------------------------------//
int add_action(short xLoc, short yLoc, short refXLoc, short refYLoc, int actionType, int actionPara, int instanceCount=1, int unitRecno=0, int actionPara2=0, short* groupUnitArray=NULL);
int add_action(ActionNode* actionNode, int immediateProcess=0);
void del_action(int actionRecno);
int is_action_exist(short actionXLoc, short actionYLoc, short refXLoc, short refYLoc, int actionType, int actionPara, int unitRecno=0, int checkMode=0);
int is_action_exist(int actionType, int actionPara, int regionId=0);
int is_build_action_exist(int firmId, int xLoc, int yLoc);
int process_action(int priorityActionRecno=0, int processActionMode=0); // waiting --> processing
int process_action_id(int actionId);
void action_finished(WORD aiActionId, short unitRecno=0, int actionFailure=0);
void action_failure(WORD aiActionId, short unitRecno=0);
void auto_next_action(ActionNode* actionNode);
void stop_unit_action(short unitRecno);
int check_firm_ready(short xLoc, short yLoc, int firmId=0); // check whether firm exists and belongs to our nation
int check_town_ready(short xLoc, short yLoc); // check whether town exists and belongs to our nation
//------------------------------------------------------------//
// functions used to find skilled units
//------------------------------------------------------------//
Unit* get_skilled_unit(int skillId, int raceId, ActionNode* actionNode);
Unit* find_skilled_unit(int skillId, int raceId, short destX, short destY, char& resultFlag, int actionId=0);
int hire_unit(int skillId, int raceId, short destX, short destY);
int train_unit(int skillId, int raceId, short destX, short destY, int& trainTownRecno, int actionId=0);
int recruit_jobless_worker(Firm* firmPtr, int preferedRaceId=0);
int recruit_on_job_worker(Firm* firmPtr, int preferedRaceId=0);
int ai_should_hire_unit(int considerProfit);
//------------------------------------------------------------//
// other functions
//------------------------------------------------------------//
void settle_to_other_town();
int can_ai_build(int firmId);
int think_succeed_king();
int closest_enemy_firm_distance(int firmId, int xLoc, int yLoc);
//------------------------------------------------------------//
// military related functions
//------------------------------------------------------------//
void think_military();
int think_secret_attack();
int think_attack_town();
int think_close_camp();
int ai_attack_target(int targetXLoc, int targetYLoc, int targetCombatLevel, int defenseMode=0, int justMoveToFlag=0, int attackerMinCombatLevel=0, int attackerCampRecno=0, int useAllCamp=0);
void ai_attack_target_sync();
void ai_attack_target_execute(int directAttack);
int ai_attack_order_nearby_mobile(int targetXLoc, int targetYLoc, int targetCombatLevel);
int ai_sea_attack_target(int targetXLoc, int targetYLoc);
void ai_attack_unit_in_area(int xLoc1, int yLoc1, int xLoc2, int yLoc2);
int ai_defend(int attackerUnitRecno);
int ai_request_military_aid();
void reset_ai_attack_target();
int think_attack_monster();
int think_monster_target(int& targetCombatLevel);
int ai_should_expand_military();
int ai_is_troop_need_new_camp();
int ai_has_too_many_camp();
int ai_should_attack_friendly(int friendlyNationRecno, int attackTemptation);
void enable_should_attack_on_target(int targetXLoc, int targetYLoc);
//------------------------------------------------------------//
// economic related functions
//------------------------------------------------------------//
void think_reduce_expense();
int surplus_supply_rating();
int ai_trade_with_rating(int withNationRecno);
int ai_should_spend(int importanceRating, float spendAmt=0);
int ai_should_spend_war(int enemyMilitaryRating, int considerCeaseFire=0);
int ai_has_enough_food();
//------------------------------------------------------------//
// town related functions
//------------------------------------------------------------//
void think_town();
void optimize_town_race();
void optimize_town_race_region(int regionId);
//--------------------------------------------------------------//
// functions for capturing independent and enemy towns
//--------------------------------------------------------------//
int think_capture_independent();
int capture_expected_resistance(int townRecno);
int start_capture(int townRecno);
int capture_build_camp(int townRecno, int raceId);
int find_best_capturer(int townRecno, int raceId, int& bestResistanceReduce);
int hire_best_capturer(int townRecno, int raceId);
int mobilize_capturer(int unitRecno);
int think_capture_new_enemy_town(Town* capturerTown, int useAllCamp=0);
void think_capturing_enemy_town();
int attack_enemy_town_defense(Town* targetTown, int useAllCamp=0);
Town* think_capture_enemy_town_target(Town* capturerTown);
int enemy_town_combat_level(Town* targetTown, int returnIfWar, int hasWar);
int enemy_firm_combat_level(Firm* targetFirm, int returnIfWar, int hasWar);
int mobile_defense_combat_level(int targetXLoc, int targetYLoc, int targetNationRecno, int returnIfWar, int& hasWar);
int should_use_cash_to_capture();
//--------------------------------------------------------------//
// marine functions
//--------------------------------------------------------------//
void think_marine();
int think_build_harbor_network();
int think_move_between_region();
int think_move_troop_between_region();
int think_move_people_between_region();
int think_sea_attack_enemy();
int think_move_to_region_with_mine();
int ai_build_camp_town_next_to(int xLoc1, int yLoc1, int xLoc2, int yLoc2);
int ai_settle_to_region(int destXLoc, int destYLoc, int seaActionId);
int ai_patrol_to_region(int destXLoc, int destYLoc, int seaActionId);
int ai_should_sail_to_rating(int regionStatId);
int ai_build_harbor(int landRegionId, int seaRegionId);
int ai_sea_travel(ActionNode* actionNode);
int ai_sea_travel2(ActionNode* actionNode);
int ai_sea_travel3(ActionNode* actionNode);
int ai_find_transport_ship(int seaRegionId, int unitXLoc, int unitYLoc, int findBest=1);
int ai_build_ship(int seaRegionId, int preferXLoc, int preferYLoc, int needTransportUnit);
int has_trade_ship(int firmRecno1, int firmRecno2);
int ai_is_sea_travel_safe();
int max_human_battle_ship_count();
//--------------------------------------------------------------//
// spy functions
//--------------------------------------------------------------//
void think_spy();
int ai_assign_spy(int targetXLoc, int targetYLoc, int spyRaceId, int mobileOnly);
int ai_assign_spy_to_town(int townRecno, int raceId=0);
int ai_assign_spy_to_firm(int firmRecno);
Spy* ai_find_spy(int targetXLoc, int targetYLoc, int targetRaceId, int mobileOnly);
int think_assign_spy_target_camp(int raceId, int regionId);
int think_assign_spy_target_town(int raceId, int regionId);
int think_assign_spy_own_town(int raceId, int regionId);
//--------------------------------------------------------------//
// strategic grand planning functions
//--------------------------------------------------------------//
void think_grand_plan();
int total_alliance_military();
int total_enemy_military();
int total_enemy_count();
int think_against_mine_monopoly();
int think_ally_against_big_enemy();
int think_unite_against_big_enemy();
void think_deal_with_all_enemy();
void think_deal_with_one_enemy(int enemyNationRecno);
int think_eliminate_enemy_town(int enemyNationRecno);
int think_eliminate_enemy_firm(int enemyNationRecno);
int think_eliminate_enemy_unit(int enemyNationRecno);
int think_attack_enemy_firm(int enemyNationRecno, int firmId);
int think_surrender();
int ai_surrender_to_rating(int nationRecno);
//--------------------------------------------------------------//
// functions for responsing to diplomatic messages
//--------------------------------------------------------------//
void think_diplomacy();
int think_trade_treaty();
int think_propose_friendly_treaty();
int think_propose_alliance_treaty();
int think_end_treaty();
int think_request_cease_war();
int think_request_buy_food();
int think_declare_war();
int think_give_tech();
int think_demand_tech();
int think_demand_tribute_aid();
int think_give_tribute_aid(TalkMsg* rejectedMsg);
int think_request_surrender();
int ai_process_talk_msg(ActionNode* actionNode);
void ai_notify_reply(int talkMsgRecno);
int should_diplomacy_retry(int talkId, int nationRecno);
void ai_end_treaty(int nationRecno);
int consider_talk_msg(TalkMsg* talkMsg);
void notify_talk_msg(TalkMsg* talkMsg);
int consider_trade_treaty(int withNationRecno);
int consider_friendly_treaty(int withNationRecno);
int consider_alliance_treaty(int withNationRecno);
int consider_military_aid(TalkMsg* talkMsg);
int consider_trade_embargo(TalkMsg* talkMsg);
int consider_cease_war(int withNationRecno);
int consider_declare_war(TalkMsg* talkMsg);
int consider_sell_food(TalkMsg* talkMsg);
int consider_take_tribute(TalkMsg* talkMsg);
int consider_give_tribute(TalkMsg* talkMsg);
int consider_take_aid(TalkMsg* talkMsg);
int consider_give_aid(TalkMsg* talkMsg);
int consider_take_tech(TalkMsg* talkMsg);
int consider_give_tech(TalkMsg* talkMsg);
int consider_accept_surrender_request(TalkMsg* talkMsg);
int consider_alliance_rating(int nationRecno);
int should_consider_friendly(int withNationRecno);
int ai_overall_relation_rating(int withNationRecno);
//--------- file functions -----------//
int write_file(File* filePtr);
int read_file(File* filePtr);
};
#pragma pack()
#ifndef __ONATIONA_H
#include
#endif
//-------------------------------------//
#endif