123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OUNITI.CPP
- //Description : Object Unit idle processing
- //Owner : Alex
- #include <ALL.h>
- #include <OWORLD.h>
- #include <OU_MARI.h>
- #include <ONATION.h>
- #include <OF_MONS.h>
- #include <OTOWN.h>
- #include <OSPY.h>
- #include <OREBEL.h>
- #include <OSYS.h>
- #include <OU_GOD.h>
- #ifdef NO_DEBUG_UNIT
- #undef err_when
- #undef err_here
- #undef err_if
- #undef err_else
- #undef err_now
- #define err_when(cond)
- #define err_here()
- #define err_if(cond)
- #define err_else
- #define err_now(msg)
- #undef DEBUG
- #endif
- //-------------- define static variables -----------//
- static char idle_detect_has_unit;
- static char idle_detect_has_firm;
- static char idle_detect_has_town;
- static char idle_detect_has_wall;
- static short idle_detect_target_unit_recno;
- static short idle_detect_target_firm_recno;
- static short idle_detect_target_town_recno;
- static short idle_detect_target_wall_x1;
- static short idle_detect_target_wall_y1;
- static int idle_detect_default_mode;
- static int help_mode;
- static short help_attack_target_recno;
- //--------- Begin of function Unit::process_idle ---------//
- // process actions for idle units
- //
- void Unit::process_idle()
- {
- err_when(result_path_dist || result_node_array);
- //---- if the unit is defending the town ----//
- switch( unit_mode )
- {
- case UNIT_MODE_REBEL:
- if(action_mode2==ACTION_STOP)
- {
- process_rebel(); // redirect to process_rebel for rebel units
- return;
- }
- break;
- case UNIT_MODE_MONSTER:
- if(action_mode2==ACTION_STOP)
- {
- if(unit_mode_para)
- {
- if(!firm_array.is_deleted(unit_mode_para))
- {
- //-------- return to monster firm -----------//
- FirmMonster *monsterFirmPtr = (FirmMonster*) firm_array[unit_mode_para];
- assign(monsterFirmPtr->loc_x1, monsterFirmPtr->loc_y1);
- return;
- }
- else
- unit_mode_para = 0;
- }
- }
- break;
- }
- //------------- process way point ------------//
- if(action_mode==ACTION_STOP && action_mode2==ACTION_STOP && way_point_count)
- {
- err_when(way_point_count < 0);
- if(way_point_count==1)
- reset_way_point_array();
- else
- process_way_point();
- return;
- }
-
- //-------- randomize direction --------//
- err_when(result_node_array!=NULL);
- //-------------------------------------------------------//
- // when the unit is idle, the following should be always true
- // move_to_x_loc == next_x_loc()
- // move_to_y_loc == next_y_loc()
- //-------------------------------------------------------//
- err_when(move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc());
- //move_to_x_loc = next_x_loc(); //***************BUGHERE
- //move_to_y_loc = next_y_loc();
- err_when(next_x!=cur_x || next_y!=cur_y);
- if(match_dir())
- {
- if(!is_guarding() && race_id ) // only these units can move
- {
- if(!m.random(150)) // change direction randomly
- set_dir(m.random(8));
- }
- }
- else
- return;
- err_when(turn_delay);
- //------- call Sprite::process_idle() -------//
- Sprite::process_idle();
- //-*********************** simulate ship movment ***************************-//
- /*if(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP)
- {
- unit_group_id = 1;
- if(cur_action==SPRITE_IDLE)
- {
- if(m.random(50))
- return;
- }
- else if(cur_action!=SPRITE_READY_TO_MOVE)
- {
- if(m.random(30)==0)
- return;
- }
- int xOffset = m.random(30)*(m.random(2) ? 1 : -1);
- int yOffset = m.random(30)*(m.random(2) ? 1 : -1);
- int curXLoc = next_x_loc();
- int curYLoc = next_y_loc();
- int destXLoc = curXLoc+xOffset;
- int destYLoc = curYLoc+yOffset;
- if(destXLoc<0) destXLoc = 0;
- else if(destXLoc>=MAX_WORLD_X_LOC) destXLoc = MAX_WORLD_X_LOC-1;
- if(destYLoc<0) destYLoc = 0;
- else if(destYLoc>=MAX_WORLD_Y_LOC) destYLoc = MAX_WORLD_Y_LOC-1;
- Location *locPtr = world.get_loc(destXLoc, destYLoc);
- int tempX, tempY;
- if(terrain_res[locPtr->terrain_id]->average_type==TERRAIN_OCEAN)
- move_to(destXLoc, destYLoc);
- else
- ship_to_beach(destXLoc, destYLoc, tempX, tempY);
- Nation *nationPtr = nation_array[nation_recno];
- if(nationPtr->cash<5000)
- nationPtr->cash += 10000;
- if(nationPtr->food<5000)
- nationPtr->food += 10000;
- if(hit_points<max_hit_points)
- hit_points = max_hit_points;
- return;
- }
- */
- //-*********************** simulate ship movment ***************************-//
- //---------------------------------------------------------------------------//
- // reset idle blocked attacking unit. If the previous condition is totally
- // blocked for attacking target, try again now
- // Note: reset blocked_edge is essentail for idle unit to reactivate attack
- // action
- //---------------------------------------------------------------------------//
- if(action_mode>=ACTION_ATTACK_UNIT && action_mode<=ACTION_ATTACK_WALL)
- {
- if(unit_array.idle_blocked_unit_reset_count && *(long*)blocked_edge)
- {
- unit_array.idle_blocked_unit_reset_count = 0;
- memset(blocked_edge, 0, sizeof(char)*4);
- err_when(blocked_edge[0] || blocked_edge[1] || blocked_edge[2] || blocked_edge[3]);
- }
- }
- err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
- err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
- //--------- reactivate action -----------//
- if(reactivate_idle_action())
- {
- err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
- err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
- return; // true if an action is reactivated
- }
- //-**************** simulate aat ********************-//
- #ifdef DEBUG
- if(debug_sim_game_type==2)
- {
- //int curXLoc = next_x_loc();
- //int curYLoc = next_y_loc();
- //int destXLoc, destYLoc;
- if(m.random(30))
- move_to(m.random(MAX_WORLD_X_LOC), m.random(MAX_WORLD_Y_LOC));
- Nation *nationPtr = nation_array[nation_recno];
- if(nationPtr->cash<2000)
- nationPtr->cash += 8000;
- if(nationPtr->food<2000)
- nationPtr->food += 8000;
- return;
- }
- #endif
- //-**************** simulate aat ********************-//
- err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
- err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
- //----------- for ai unit idle -----------//
- if( action_mode != ACTION_STOP || action_mode2 != ACTION_STOP ) // only detect attack when the unit is really idle
- return;
- if( !can_attack() )
- return; // cannot attack
- err_when(!can_attack());
- err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
- err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
- //--- only detect attack if in aggressive mode or the unit is a monster ---//
- UnitInfo* unitInfo = unit_res[unit_id];
- if( unitInfo->unit_class == UNIT_CLASS_MONSTER || aggressive_mode )
- {
- //----------- detect target to attack -----------//
- if( idle_detect_attack() )
- {
- err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
- err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
- return; // target detected
- }
- err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
- err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
- }
- //------------------------------------------------------------------//
- // wander around for monster
- //------------------------------------------------------------------//
- if( unitInfo->unit_class == UNIT_CLASS_MONSTER )
- {
- if(m.random(500)==0)
- {
- #define WANDER_DIST 20
- int xOffset = m.random(WANDER_DIST)-WANDER_DIST/2;
- int yOffset = m.random(WANDER_DIST)-WANDER_DIST/2;
- int destX = next_x_loc()+xOffset;
- int destY = next_y_loc()+yOffset;
- if(destX<0) destX = 0;
- else if(destX>=MAX_WORLD_X_LOC) destX = MAX_WORLD_X_LOC-1;
- if(destY<0) destY = 0;
- else if(destY>=MAX_WORLD_Y_LOC) destY = MAX_WORLD_Y_LOC-1;
- move_to(destX, destY);
- }
- }
- }
- //----------- End of function Unit::process_idle -----------//
- //--------- Begin of function Unit::reactivate_idle_action --------//
- // resume actions for idle units
- //
- // return 1 if an action is reactivated
- // return 0 otherwise
- //
- int Unit::reactivate_idle_action()
- {
- if(action_mode2==ACTION_STOP)
- return 0; // return for no idle action
- if(!is_dir_correct())
- return 1; // cheating for turning the direction
- //------------------- declare parameters ----------------------//
- Location *locPtr;
- Firm *firmPtr;
- FirmInfo *firmInfo;
- Unit *unitPtr;
- UnitMarine *shipPtr;
- SpriteInfo *spriteInfo;
- int canMove = 1;
- int returnFlag = 0;
- int curXLoc = move_to_x_loc;
- int curYLoc = move_to_y_loc;
- int dummyX, dummyY;
- int hasSearch = 0;
- int validSearch = seek_path.is_valid_searching();
- seek_path.set_status(PATH_WAIT);
- err_when(seek_path.path_status==PATH_NODE_USED_UP);
- switch(action_mode2)
- {
- case ACTION_STOP:
- case ACTION_DIE:
- return 0; // do nothing
- case ACTION_ATTACK_UNIT:
- if(unit_array.is_deleted(action_para2))
- stop2();
- else
- {
- unitPtr = unit_array[action_para2];
- spriteInfo = unitPtr->sprite_info;
- if(space_for_attack(action_x_loc2, action_y_loc2, unitPtr->mobile_type, spriteInfo->loc_width, spriteInfo->loc_height))
- {
- //------ there should be place for this unit to attack the target, attempts to attack it ------//
- attack_unit(action_para2, 0, 0, 0); // last 0 for not reset blocked_edge
- hasSearch++;
- returnFlag = 1;
- break;
- }
- }
- break;
- case ACTION_ATTACK_FIRM:
- locPtr = world.get_loc(action_x_loc2, action_y_loc2);
- if(!locPtr->is_firm())
- stop2(); // stop since target is already destroyed
- else
- {
- firmPtr = firm_array[action_para2];
- firmInfo = firm_res[firmPtr->firm_id];
- if(space_for_attack(action_x_loc2, action_y_loc2, UNIT_LAND, firmInfo->loc_width, firmInfo->loc_height))
- {
- //-------- attack target since space is found for this unit to move to ---------//
- attack_firm(action_x_loc2, action_y_loc2, 0, 0, 0); // last 0 for not reset blocked_edge
- hasSearch++;
- returnFlag = 1;
- break;
- }
- }
- break;
- case ACTION_ATTACK_TOWN:
- locPtr = world.get_loc(action_x_loc2, action_y_loc2);
- if(!locPtr->is_town())
- stop2(); // stop since target is deleted
- else if(space_for_attack(action_x_loc2, action_y_loc2, UNIT_LAND, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
- {
- //---------- attack target --------//
- attack_town(action_x_loc2, action_y_loc2, 0, 0, 0); // last 0 for not reset blocked_edge
- hasSearch++;
- returnFlag = 1;
- break;
- }
- break;
- case ACTION_ATTACK_WALL:
- locPtr = world.get_loc(action_x_loc2, action_y_loc2);
- if(!locPtr->is_wall())
- stop2(); // stop since target doesn't exist
- else if(space_for_attack(action_x_loc2, action_y_loc2, UNIT_LAND, 1, 1))
- {
- //----------- attack target -----------//
- attack_wall(action_x_loc2, action_y_loc2, 0, 0, 0); // last 0 for not reset blocked_edge
- hasSearch++;
- returnFlag = 1;
- break;
- }
- break;
- case ACTION_ASSIGN_TO_FIRM:
- case ACTION_ASSIGN_TO_TOWN:
- case ACTION_ASSIGN_TO_VEHICLE:
- //---------- resume assign actions -------------//
- err_when(action_x_loc2==-1 || action_y_loc2==-1 || !action_para2);
- assign(action_x_loc2, action_y_loc2);
- hasSearch++;
- waiting_term = 0;
- returnFlag = 1;
- break;
- case ACTION_ASSIGN_TO_SHIP:
- //------------ try to assign to marine ------------//
- err_when(action_x_loc2==-1 || action_y_loc2==-1 || !action_para2);
- assign_to_ship(action_x_loc2, action_y_loc2, action_para2);
- hasSearch++;
- waiting_term = 0;
- returnFlag = 1;
- break;
- case ACTION_BUILD_FIRM:
- //-------------- build again ----------------//
- err_when(action_x_loc2==-1 || action_y_loc2==-1 || !action_para2);
- build_firm(action_x_loc2, action_y_loc2, action_para2, COMMAND_AUTO);
- hasSearch++;
- waiting_term = 0;
- returnFlag = 1;
- break;
- case ACTION_SETTLE:
- //------------- try again to settle -----------//
- err_when(action_x_loc2==-1 || action_y_loc2==-1 || action_para2);
- settle(action_x_loc2, action_y_loc2);
- hasSearch++;
- waiting_term = 0;
- returnFlag = 1;
- break;
- case ACTION_BURN:
- //---------------- resume burn action -----------------//
- err_when(action_x_loc2==-1 || action_y_loc2==-1 || action_para2);
- burn(action_x_loc2, action_y_loc2, COMMAND_AUTO);
- hasSearch++;
- waiting_term = 0;
- returnFlag = 1;
- break;
- case ACTION_MOVE:
- //if(!avail_node_enough_for_search())
- //{
- // returnFlag = 1;
- // break;
- //}
- if(move_to_x_loc!=action_x_loc2 || move_to_y_loc!=action_y_loc2)
- {
- //------- move since the unit has not reached its destination --------//
- move_to(action_x_loc2, action_y_loc2, 1);
- hasSearch++;
- returnFlag = 1;
- break;
- }
- waiting_term = 0;
- break;
- case ACTION_AUTO_DEFENSE_ATTACK_TARGET:
- if(unit_search_node_used<500) // limit the no. of nods to reactivate idle process
- {
- //---------- resume action -----------//
- process_auto_defense_attack_target();
- hasSearch++;
- }
- returnFlag = 1;
- break;
- case ACTION_AUTO_DEFENSE_DETECT_TARGET:
- process_auto_defense_detect_target();
- returnFlag = 1;
- break;
- case ACTION_AUTO_DEFENSE_BACK_CAMP:
- process_auto_defense_back_camp();
- hasSearch++;
- returnFlag = 1;
- break;
- case ACTION_DEFEND_TOWN_ATTACK_TARGET:
- process_defend_town_attack_target();
- hasSearch++;
- returnFlag = 1;
- break;
- case ACTION_DEFEND_TOWN_DETECT_TARGET:
- process_defend_town_detect_target();
- returnFlag = 1;
- break;
- case ACTION_DEFEND_TOWN_BACK_TOWN:
- process_defend_town_back_town();
- hasSearch++;
- returnFlag = 1;
- break;
- case ACTION_MONSTER_DEFEND_ATTACK_TARGET:
- process_monster_defend_attack_target();
- hasSearch++;
- returnFlag = 1;
- break;
- case ACTION_MONSTER_DEFEND_DETECT_TARGET:
- process_monster_defend_detect_target();
- returnFlag = 1;
- break;
- case ACTION_MONSTER_DEFEND_BACK_FIRM:
- process_monster_defend_back_firm();
- hasSearch++;
- returnFlag = 1;
- break;
- case ACTION_SHIP_TO_BEACH:
- shipPtr = (UnitMarine*) this;
- if(!shipPtr->in_beach || shipPtr->extra_move_in_beach==EXTRA_MOVE_FINISH)
- {
- //----------- the ship has not reached inlet, so move again --------------//
- ship_to_beach(action_x_loc2, action_y_loc2, dummyX, dummyY);
- hasSearch++;
- }
- returnFlag = 1;
- break;
- case ACTION_GO_CAST_POWER:
- go_cast_power(action_x_loc2, action_y_loc2, ((UnitGod*)this)->cast_power_type, COMMAND_AUTO);
- returnFlag = 1;
- break;
- default: err_here();
- break;
- }
- if(validSearch && hasSearch && seek_path.path_status==PATH_NODE_USED_UP &&
- next_x_loc()==move_to_x_loc && next_y_loc()==move_to_y_loc)
- {
- //-------------------------------------------------------------------------//
- // abort actions since the unit trys to move and move no more.
- //-------------------------------------------------------------------------//
- stop2(KEEP_DEFENSE_MODE);
- return 1;
- }
- int abort=0;
- if(returnFlag)
- {
- if(curXLoc==move_to_x_loc && curYLoc==move_to_y_loc && seek_path.path_status==PATH_NODE_USED_UP)
- {
- //---------------------------------------------------------------------------------//
- // insufficient nodes for searching
- //---------------------------------------------------------------------------------//
- if(action_mode2==ACTION_ASSIGN_TO_SHIP || action_mode2==ACTION_SHIP_TO_BEACH || in_any_defense_mode())
- return 1;
- //------- number of nodes is not enough to find the destination -------//
- if(action_misc!=ACTION_MISC_STOP)
- {
- if(action_misc==ACTION_MISC_PRE_SEARCH_NODE_USED_UP)
- {
- if(action_misc_para<20)
- {
- action_misc_para++;
- return 0;
- }
- else
- action_misc_para++;
- }
- abort++; // assume destination unreachable, abort action
- }
- else
- {
- action_misc = ACTION_MISC_PRE_SEARCH_NODE_USED_UP;
- action_misc_para = 0;
- }
- }
- else // action resumed, return true
- return 1;
- }
- if(!returnFlag || abort)
- {
- stop2(KEEP_DEFENSE_MODE);
- }
- return 0;
- }
- //----------- End of function Unit::reactivate_idle_action -----------//
- //--------- Begin of function Unit::idle_detect_attack --------//
- // detect target for idle units
- //
- // [int] startLoc - (default = 0), used to select region of the square
- // for checking
- // [int] dimensionInput - (default = 0), the detected size is calculated as
- // 2*dimensionInput+1. this unit is located in
- // the center of the square.
- // [char] defenseMode - true for defensive mode on.
- //
- // return 1 if any target is detected
- // return 0 otherwise
- //
- int Unit::idle_detect_attack(int startLoc, int dimensionInput, char defenseMode)
- {
- err_when(attack_count==0);
- //---------------------------------------------------//
- // Set detectDelay.
- //
- // The larger its value, the less CPU time it will takes,
- // but it will also take longer to detect enemies.
- //---------------------------------------------------//
- int detectDelay = 1+unit_array.packed_size()/10;
- Location *locPtr;
- Unit *unitPtr;
- //Unit *unitPtr, *targetUnitPtr;
- //Firm *firmPtr, *targetFirmPtr;
- //Town *townPtr, *targetTownPtr;
- //int targetWallXLoc, targetWallYLoc;
- //char hasUnit=0, hasFirm=0, hasTown=0, hasWall=0;
- char targetMobileType;
- int dimension, countLimit;
- short targetRecno, i;
- int xOffset, yOffset, checkXLoc, checkYLoc;
- idle_detect_default_mode = (!startLoc && !dimensionInput && !defenseMode); //----- true when all zero
- idle_detect_has_unit = idle_detect_has_firm = idle_detect_has_town = idle_detect_has_wall = 0;
- help_mode = HELP_NOTHING;
-
- err_when(idle_detect_default_mode!=0 && idle_detect_default_mode!=1);
- //-----------------------------------------------------------------------------------------------//
- // adjust waiting_term for default_mode
- //-----------------------------------------------------------------------------------------------//
- int lowestBit = (++waiting_term)%detectDelay;
- if(action_mode2==ACTION_STOP)
- {
- err_when(action_mode!=ACTION_STOP);
- waiting_term = lowestBit;
- }
- (dimension = (dimensionInput ? dimensionInput : ATTACK_DETECT_DISTANCE)<<1)++;
- countLimit = dimension*dimension;
- i = startLoc ? startLoc : 1+lowestBit;
- int incAmount = (idle_detect_default_mode) ? detectDelay : 1;
- //-----------------------------------------------------------------------------------------------//
- // check the location around the unit
- //
- // The priority to choose target is (value of targetType)
- // 1) Unit, 2) firm, 3) wall
- //-----------------------------------------------------------------------------------------------//
- err_when(defenseMode && action_mode2!=ACTION_AUTO_DEFENSE_DETECT_TARGET &&
- action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET && action_mode2!=ACTION_MONSTER_DEFEND_DETECT_TARGET);
- err_when(incAmount<1 || incAmount>100000);
- for(; i<=countLimit; i+=incAmount) // 1 is the self location
- {
- m.cal_move_around_a_point(i, dimension, dimension, xOffset, yOffset);
- checkXLoc = move_to_x_loc+xOffset;
- checkYLoc = move_to_y_loc+yOffset;
- if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
- continue;
- //------------------ verify location ---------------//
- locPtr = world.get_loc(checkXLoc, checkYLoc);
- if(defenseMode && action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET)
- {
- if(action_mode2==ACTION_AUTO_DEFENSE_DETECT_TARGET)
- if(locPtr->power_nation_recno!=nation_recno && locPtr->power_nation_recno)
- continue; // skip this location because it is not neutral nation or our nation
- }
- //----------------------------------------------------------------------------//
- // checking the target type
- //----------------------------------------------------------------------------//
- if((targetMobileType=locPtr->has_any_unit(i==1 ? mobile_type : UNIT_LAND)) &&
- (targetRecno=locPtr->unit_recno(targetMobileType)) && !unit_array.is_deleted(targetRecno))
- {
- //=================== is unit ======================//
- if(idle_detect_has_unit || (action_para==targetRecno && action_mode==ACTION_ATTACK_UNIT &&
- checkXLoc==action_x_loc && checkYLoc==action_y_loc))
- continue; // same target as before
- unitPtr = unit_array[targetRecno];
- if(nation_recno && unitPtr->nation_recno==nation_recno && help_mode!=HELP_ATTACK_UNIT)
- idle_detect_helper_attack(targetRecno); // help our troop
- else if((help_mode==HELP_ATTACK_UNIT && help_attack_target_recno==targetRecno) ||
- (unitPtr->nation_recno!=nation_recno && idle_detect_unit_checking(targetRecno)))
- {
- idle_detect_target_unit_recno = targetRecno;
- idle_detect_has_unit++;
- break; // break with highest priority
- }
- }
- else if(locPtr->is_firm() && (targetRecno = locPtr->firm_recno()))
- {
- //=============== is firm ===============//
- if(idle_detect_has_firm || (action_para==targetRecno && action_mode==ACTION_ATTACK_FIRM &&
- action_x_loc==checkXLoc && action_y_loc==checkYLoc))
- continue; // same target as before
- if(idle_detect_firm_checking(targetRecno))
- {
- idle_detect_target_firm_recno = targetRecno;
- idle_detect_has_firm++;
- }
- }
- /*else if(locPtr->is_town() && (targetRecno = locPtr->town_recno()))
- {
- //=============== is town ===========//
- if(idle_detect_has_town || (action_para==targetRecno && action_mode==ACTION_ATTACK_TOWN &&
- action_x_loc==checkXLoc && action_y_loc==checkYLoc))
- continue; // same target as before
- if(idle_detect_town_checking(targetRecno))
- {
- idle_detect_target_town_recno = targetRecno;
- idle_detect_has_town++;
- }
- }
- else if(locPtr->is_wall())
- {
- //================ is wall ==============//
- if(idle_detect_has_wall || (action_mode==ACTION_ATTACK_WALL && action_para==targetRecno &&
- action_x_loc==checkXLoc && action_y_loc==checkYLoc))
- continue; // same target as before
- if(idle_detect_wall_checking(checkXLoc, checkYLoc))
- {
- idle_detect_target_wall_x1 = checkXLoc;
- idle_detect_target_wall_y1 = checkYLoc;
- idle_detect_has_wall++;
- }
- }*/
- //if(hasUnit && hasFirm && hasTown && hasWall)
- //if(hasUnit && hasFirm && hasWall)
- // break; // there is target for attacking
- }
- return idle_detect_choose_target(defenseMode);
- }
- //----------- End of function Unit::idle_detect_attack -----------//
- //--------- Begin of function Unit::idle_detect_unit_checking --------//
- // check whether to attack the unit with recno = targetRecno
- //
- // <short> targetRecno - recno of unit being checked
- //
- // return 1 if situation is suitable for attacking
- // return 0 otherwise
- //
- int Unit::idle_detect_unit_checking(short targetRecno)
- {
- Unit *targetUnitPtr = unit_array[targetRecno];
- if(targetUnitPtr->unit_id == UNIT_CARAVAN)
- return 0;
- //###### trevor 15/10 #######//
- //-------------------------------------------//
- // If the target is moving, don't attack it.
- // Only attack when the unit stands still or
- // is attacking.
- //-------------------------------------------//
- if( targetUnitPtr->cur_action != SPRITE_ATTACK &&
- targetUnitPtr->cur_action != SPRITE_IDLE )
- {
- return 0;
- }
- //-------------------------------------------//
- // If the target is a spy of our own and the
- // notification flag is set to 0, then don't
- // attack.
- //-------------------------------------------//
- if( targetUnitPtr->spy_recno ) // if the target unit is our spy, don't attack
- {
- Spy* spyPtr = spy_array[targetUnitPtr->spy_recno];
- if( spyPtr->true_nation_recno == nation_recno &&
- spyPtr->notify_cloaked_nation_flag == 0 )
- {
- return 0;
- }
- }
- if( spy_recno ) // if this unit is our spy, don't attack own units
- {
- Spy* spyPtr = spy_array[spy_recno];
- if( spyPtr->true_nation_recno == targetUnitPtr->nation_recno &&
- spyPtr->notify_cloaked_nation_flag == 0 )
- {
- return 0;
- }
- }
- //###### trevor 15/10 #######//
- SpriteInfo *spriteInfo = targetUnitPtr->sprite_info;
- Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
- short targetNationRecno = targetUnitPtr->nation_recno;
- //-------------------------------------------------------------------//
- // checking nation relationship
- //-------------------------------------------------------------------//
- if(nation_recno)
- {
- if(targetNationRecno)
- {
- //------- don't attack own units and non-hostile units -------//
- err_when(targetNationRecno==nation_recno);
- //--------------------------------------------------------------//
- // if the unit is hostile, only attack if should_attack flag to
- // that nation is true or the unit is attacking somebody or something.
- //--------------------------------------------------------------//
- NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
- if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
- return 0;
- }
- else if(!targetUnitPtr->independent_nation_can_attack(nation_recno))
- return 0;
- }
- else if(!independent_nation_can_attack(targetNationRecno)) // independent unit
- return 0;
- //---------------------------------------------//
- if(space_for_attack(targetUnitPtr->next_x_loc(), targetUnitPtr->next_y_loc(), targetUnitPtr->mobile_type,
- spriteInfo->loc_width, spriteInfo->loc_height))
- return 1;
- else
- return 0;
- }
- //----------- End of function Unit::idle_detect_unit_checking -----------//
- //--------- Begin of function Unit::idle_detect_firm_checking --------//
- // check whether to attack the firm
- //
- // <short> targetRecno - recno of the firm being checked
- //
- // return 1 if situation is suitable
- // return 0 otherwise
- //
- int Unit::idle_detect_firm_checking(short targetRecno)
- {
- Firm *firmPtr = firm_array[targetRecno];
- //------------ code to select firm for attacking -----------//
- switch(firmPtr->firm_id)
- {
- case FIRM_CAMP:case FIRM_BASE: case FIRM_WAR_FACTORY:
- break;
-
- default: return 0;
- }
- Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
- short targetNationRecno = firmPtr->nation_recno;
- char targetMobileType = mobile_type==UNIT_SEA ? UNIT_SEA : UNIT_LAND;
- //-------------------------------------------------------------------------------//
- // checking nation relationship
- //-------------------------------------------------------------------------------//
- if(nation_recno)
- {
- if(targetNationRecno)
- {
- //------- don't attack own units and non-hostile units -------//
- if( targetNationRecno==nation_recno )
- return 0;
- //--------------------------------------------------------------//
- // if the unit is hostile, only attack if should_attack flag to
- // that nation is true or the unit is attacking somebody or something.
- //--------------------------------------------------------------//
- NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
- if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
- return 0;
- }
- else // independent firm
- {
- FirmMonster *monsterFirmPtr = (FirmMonster*) firm_array[targetRecno];
- if(!monsterFirmPtr->is_hostile_nation(nation_recno))
- return 0;
- }
- }
- else if(!independent_nation_can_attack(targetNationRecno)) // independent town
- return 0;
- FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
- if(space_for_attack(firmPtr->loc_x1, firmPtr->loc_y1, UNIT_LAND, firmInfo->loc_width, firmInfo->loc_height))
- return 1;
- else
- return 0;
- }
- //----------- End of function Unit::idle_detect_firm_checking -----------//
- //--------- Begin of function Unit::idle_detect_town_checking --------//
- // check town to attack
- //
- // <short> targetRecno - recno of town
- //
- // return 1 if situation is suitable for attacking
- // return 0 otherwise
- //
- int Unit::idle_detect_town_checking(short targetRecno)
- {
- Town *townPtr = town_array[targetRecno];
- Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
- short targetNationRecno = townPtr->nation_recno;
- //-------------------------------------------------------------------------------//
- // checking nation relationship
- //-------------------------------------------------------------------------------//
- if(nation_recno)
- {
- if(targetNationRecno)
- {
- //------- don't attack own units and non-hostile units -------//
- if( targetNationRecno==nation_recno )
- return 0;
- //--------------------------------------------------------------//
- // if the unit is hostile, only attack if should_attack flag to
- // that nation is true or the unit is attacking somebody or something.
- //--------------------------------------------------------------//
- NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
- if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
- return 0;
- }
- else if(!townPtr->is_hostile_nation(nation_recno))
- return 0; // false if the indepentent unit don't want to attack us
- }
- else if(!independent_nation_can_attack(targetNationRecno)) // independent town
- return 0;
- if(space_for_attack(townPtr->loc_x1, townPtr->loc_y1, UNIT_LAND, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
- return 1;
- else
- return 0;
- }
- //----------- End of function Unit::idle_detect_town_checking -----------//
- //--------- Begin of function Unit::idle_detect_wall_checking --------//
- // check wall to attack
- //
- // <int> targetXLoc - wall x location
- // <int> targetYLoc - wall y location
- //
- // return 1 if situation is suitable for attacking
- // return 0 otherwise
- //
- int Unit::idle_detect_wall_checking(int targetXLoc, int targetYLoc)
- {
- Location *locPtr = world.get_loc(targetXLoc, targetYLoc);
- Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
- short targetNationRecno = locPtr->wall_nation_recno();
- //-------------------------------------------------------------------------------//
- // checking nation relationship
- //-------------------------------------------------------------------------------//
- if(nation_recno)
- {
- if(targetNationRecno)
- {
- //------- don't attack own units and non-hostile units -------//
- if( targetNationRecno==nation_recno )
- return 0;
- //--------------------------------------------------------------//
- // if the unit is hostile, only attack if should_attack flag to
- // that nation is true or the unit is attacking somebody or something.
- //--------------------------------------------------------------//
- NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
- if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
- return 0;
- }
- else
- return 0;
- }
- else if(!independent_nation_can_attack(targetNationRecno)) // independent town
- return 0;
- if(space_for_attack(targetXLoc, targetYLoc, UNIT_LAND, 1, 1))
- return 1;
- else
- return 0;
- }
- //----------- End of function Unit::idle_detect_wall_checking -----------//
- //--------- Begin of function Unit::idle_detect_choose_target --------//
- //
- // <char> defenseMode - indicate whether defensive mode is on
- //
- int Unit::idle_detect_choose_target(char defenseMode)
- {
- //-----------------------------------------------------------------------------------------------//
- // Decision making for choosing target to attack
- //-----------------------------------------------------------------------------------------------//
- if(defenseMode)
- {
- if(action_mode2==ACTION_AUTO_DEFENSE_DETECT_TARGET)
- {
- //----------- defense units allow to attack units and firms -----------//
- err_when(!in_auto_defense_mode());
- if(idle_detect_has_unit)
- defense_attack_unit(idle_detect_target_unit_recno);
- else if(idle_detect_has_firm)
- {
- Firm *targetFirmPtr = firm_array[idle_detect_target_firm_recno];
- defense_attack_firm(targetFirmPtr->loc_x1, targetFirmPtr->loc_y1);
- }
- /*else if(idle_detect_has_town)
- {
- TownPtr *targetTownPtr = town_array[idle_detect_target_town_recno];
- defense_attack_town(targetTownPtr->loc_x1, targetTownPtr->loc_y1);
- }
- else if(idle_detect_has_wall)
- defense_attack_wall(idle_detect_target_wall_x1, idle_detect_target_wall_y1);*/
- else
- return 0;
- return 1;
- }
- else if(action_mode2==ACTION_DEFEND_TOWN_DETECT_TARGET)
- {
- //----------- town units only attack units ------------//
- err_when(!in_defend_town_mode());
- if(idle_detect_has_unit)
- defend_town_attack_unit(idle_detect_target_unit_recno);
- else
- return 0;
- return 1;
- }
- else if(action_mode2==ACTION_MONSTER_DEFEND_DETECT_TARGET)
- {
- //---------- monsters can attack units and firms -----------//
- err_when(!in_monster_defend_mode());
- if(idle_detect_has_unit)
- monster_defend_attack_unit(idle_detect_target_unit_recno);
- else if(idle_detect_has_firm)
- {
- Firm *targetFirmPtr = firm_array[idle_detect_target_firm_recno];
- monster_defend_attack_firm(targetFirmPtr->loc_x1, targetFirmPtr->loc_y1);
- }
- /*else if(idle_detect_has_town)
- {
- Town *targetTownPtr = town_array[idle_detect_target_town_recno];
- monster_defend_attack_town(targetTownPtr->loc_x1, targetTownPtr->loc_y1);
- }
- else if(idle_detect_has_wall)
- monster_defend_attack_wall(idle_detect_target_wall_x1, idle_detect_target_wall_y1);*/
- else
- return 0;
- return 1;
- }
- else
- err_here();
- }
- else // default mode
- {
- //#### begin trevor 9/10 ####//
- int rc = 0;
- if(idle_detect_has_unit)
- {
- attack_unit(idle_detect_target_unit_recno);
- //--- set the original position of the target, so the unit won't chase too far away ---//
- Unit* unitPtr = unit_array[idle_detect_target_unit_recno];
- original_target_x_loc = unitPtr->next_x_loc();
- original_target_y_loc = unitPtr->next_y_loc();
- rc = 1;
- }
- else if(help_mode==HELP_ATTACK_UNIT)
- {
- attack_unit(help_attack_target_recno);
- //--- set the original position of the target, so the unit won't chase too far away ---//
- Unit* unitPtr = unit_array[help_attack_target_recno];
- original_target_x_loc = unitPtr->next_x_loc();
- original_target_y_loc = unitPtr->next_y_loc();
- rc = 1;
- }
- else if(idle_detect_has_firm)
- {
- Firm *targetFirmPtr = firm_array[idle_detect_target_firm_recno];
- attack_firm(targetFirmPtr->loc_x1, targetFirmPtr->loc_y1);
- }
- /*else if(idle_detect_has_town)
- {
- Town *targetTownPtr = town_array[idle_detect_target_town_recno];
- attack_town(targetTownPtr->loc_x1, targetTownPtr->loc_y1);
- }
- else if(idle_detect_has_wall)
- attack_wall(idle_detect_target_wall_x1, idle_detect_target_wall_y1);*/
- else
- return 0;
- //---- set original action vars ----//
- if( rc && original_action_mode==0 )
- {
- original_action_mode = ACTION_MOVE;
- original_action_para = 0;
- original_action_x_loc = next_x_loc();
- original_action_y_loc = next_y_loc();
- }
- return 1;
- //#### end trevor 9/10 ####//
- }
- return 0;
- }
- //----------- End of function Unit::idle_detect_choose_target -----------//
- //--------- Begin of function Unit::idle_detect_helper_attack --------//
- // check the action_mode of the unit being checked, which has same nation
- // recno as this unit. If the unit attacks other unit, this unit help to
- // attack the same target.
- //
- // <short> unitRecno - recno of the unit of nation recno same as this unit
- //
- void Unit::idle_detect_helper_attack(short unitRecno)
- {
- #define HELP_DISTANCE 15
- Unit *unitPtr = unit_array[unitRecno];
- if(unitPtr->unit_id == UNIT_CARAVAN)
- return;
- //char actionMode;
- short actionPara;
- //short actionXLoc, actionYLoc;
- char isUnit = 0;
- //------------- is the unit attacking other unit ------------//
- switch(unitPtr->action_mode2)
- {
- case ACTION_ATTACK_UNIT:
- actionPara = unitPtr->action_para2;
- isUnit++;
- break;
- default:
- switch(unitPtr->action_mode)
- {
- case ACTION_ATTACK_UNIT:
- actionPara = unitPtr->action_para;
- isUnit++;
- break;
- }
- }
- if(isUnit && !unit_array.is_deleted(actionPara))
- {
- Unit *targetUnit = unit_array[actionPara];
- if(targetUnit->nation_recno==nation_recno)
- return;
- if(m.points_distance(next_x_loc(), next_y_loc(), targetUnit->next_x_loc(), targetUnit->next_y_loc())<HELP_DISTANCE)
- {
- if(idle_detect_unit_checking(actionPara))
- {
- help_attack_target_recno = actionPara;
- help_mode = HELP_ATTACK_UNIT;
- }
- memset(blocked_edge, 0, sizeof(blocked_edge));
- }
- }
- }
- //----------- End of function Unit::idle_detect_helper_attack -----------//
|