1 /*
2  * Seven Kingdoms: Ancient Adversaries
3  *
4  * Copyright 1997,1998 Enlight Software Ltd.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 //Filename    : OUNIT.H
22 //Description : Header file of Object Unit
23 
24 #ifndef __OUNIT_H
25 #define __OUNIT_H
26 
27 #ifndef __OSPRITE_H
28 #include <OSPRITE.h>
29 #endif
30 
31 #ifndef __OSPATH_H
32 #include <OSPATH.h>
33 #endif
34 
35 #ifndef __OUNITRES_H
36 #include <OUNITRES.h>
37 #endif
38 
39 #ifndef __OBUTTON_H
40 #include <OBUTTON.h>
41 #endif
42 
43 #ifndef __OSKILL_H
44 #include <OSKILL.h>
45 #endif
46 
47 #ifndef __OSPREUSE_H
48 #include <OSPREUSE.h>
49 #endif
50 
51 #ifdef NO_DEBUG_UNIT
52 #undef DEBUG
53 #endif
54 
55 #define GAME_FRAMES_PER_DAY 10
56 
57 //-------- action code for action_mode ---------//
58 
59 enum { ACTION_STOP,
60        ACTION_ATTACK_UNIT,
61        ACTION_ATTACK_FIRM,
62        ACTION_ATTACK_TOWN,
63        ACTION_ATTACK_WALL,
64        ACTION_ASSIGN_TO_FIRM,
65        ACTION_ASSIGN_TO_TOWN,
66        ACTION_ASSIGN_TO_VEHICLE,
67        ACTION_ASSIGN_TO_SHIP,
68        ACTION_SHIP_TO_BEACH,  // used for UNIT_SEA only
69        ACTION_BUILD_FIRM,
70        ACTION_SETTLE,
71        ACTION_BURN,
72        ACTION_DIE,
73        ACTION_MOVE,
74        ACTION_GO_CAST_POWER,  // for god only
75 
76        //------------ used only for action_mode2 -----------------//
77        //------- put the following nine parameters together -------//
78 
79        ACTION_AUTO_DEFENSE_ATTACK_TARGET, // move to target for attacking
80        ACTION_AUTO_DEFENSE_DETECT_TARGET, // is idle, detect target to attack or waiting for defense action, (detect range is larger as usual)
81        ACTION_AUTO_DEFENSE_BACK_CAMP,     // go back to camp for training or ready for next defense action
82        ACTION_DEFEND_TOWN_ATTACK_TARGET,
83        ACTION_DEFEND_TOWN_DETECT_TARGET,
84        ACTION_DEFEND_TOWN_BACK_TOWN,
85        ACTION_MONSTER_DEFEND_ATTACK_TARGET,
86        ACTION_MONSTER_DEFEND_DETECT_TARGET,
87        ACTION_MONSTER_DEFEND_BACK_FIRM,
88      };
89 
90 //-------- define action type for action_misc ----------//
91 
92 enum  {  ACTION_MISC_STOP = 0,
93          ACTION_MISC_CAPTURE_TOWN_RECNO,
94          ACTION_MISC_DEFENSE_CAMP_RECNO,
95          ACTION_MISC_DEFEND_TOWN_RECNO,
96          ACTION_MISC_MONSTER_DEFEND_FIRM_RECNO,
97          ACTION_MISC_PRE_SEARCH_NODE_USED_UP,
98       };
99 
100 //--------- unit mode ------------//
101 
102 enum { UNIT_MODE_OVERSEE=1,         // unit_mode_para is the recno of the firm the unit is overseeing
103        UNIT_MODE_DEFEND_TOWN,       // unit_mode_para is the recno of the town the unit is defending
104        UNIT_MODE_CONSTRUCT,         // unit_mode_para is the recno of the firm the unit is constructing
105        UNIT_MODE_REBEL,             // unit_mode_para is the recno of the rebel group the unit belongs to
106        UNIT_MODE_MONSTER,           // unit_mode_para is the recno of the firm recno of the monster firm it belongs to
107        UNIT_MODE_ON_SHIP,           // unit_mode_para is the recno of the ship unit this unit is on
108 		 UNIT_MODE_IN_HARBOR,         // for ships only, unit_mode_para is the recno of the harbor this marine unit is in
109 		 UNIT_MODE_UNDER_TRAINING,
110      };
111 
112 //-------------- unit rank -------------//
113 
114 enum { MAX_RANK=3 };
115 
116 enum { RANK_SOLDIER,
117        RANK_GENERAL,
118        RANK_KING,
119      };
120 
121 //------------- unit salary -----------//
122 
123 enum { SOLDIER_YEAR_SALARY  = 10,
124 		 GENERAL_YEAR_SALARY  = 50,
125 		 SPY_YEAR_SALARY      = 100 };
126 
127 //------- other constant ----------//
128 
129 enum { EFFECTIVE_LEADING_DISTANCE = 10 };
130 
131 enum { ATTACK_DIR = 8 };      // define number of attacking direction
132 
133 enum { MAX_TEAM_MEMBER = 9 }; // maximum no. of units a general/king can lead
134 
135 enum { MAX_NATION_CONTRIBUTION = 10000 };		// there is an upper limit nation_contribution as it is a <short>
136 
137 //---------- used in set_move_to_surround -----------//
138 
139 enum  { BUILDING_TYPE_FIRM_MOVE_TO,       // firm already exists
140         BUILDING_TYPE_FIRM_BUILD,         // no firm there
141         BUILDING_TYPE_TOWN_MOVE_TO,       // town already exists
142         BUILDING_TYPE_SETTLE,             // no town there
143         BUILDING_TYPE_VEHICLE,            // location is blocked by the vehicle
144         BUILDING_TYPE_WALL,               // location is occupied by the wall
145       };
146 
147 //------------ define help mode ----------//
148 enum  {  HELP_NOTHING =0,
149          HELP_ATTACK_UNIT,
150          HELP_ATTACK_FIRM,
151          HELP_ATTACK_TOWN,
152          HELP_ATTACK_WALL,
153        };
154 
155 //---------- misc constant parameters ----------//
156 
157 enum  {  KEEP_PRESERVE_ACTION = 1,  // used for stop2() to keep preserve action
158          KEEP_DEFENSE_MODE = 2,     // used for stop2() to keep the defense mode
159          KEEP_DEFEND_TOWN_MODE = 3, // used for stop2() to keep the defend town mode
160 
161          MAX_WAITING_TERM_SAME = 3, // wait for same nation, used in handle_blocked...()
162          MAX_WAITING_TERM_DIFF = 3, // wait for diff. nation, used in handle_blocked...()
163 
164 			ATTACK_DETECT_DISTANCE = 6,// the distance for the unit to detect target while idle
165          ATTACK_SEARCH_TRIES = 250, // the node no. used to process searching when target is close to this unit
166          ATTACK_WAITING_TERM = 10,  // terms no. to wait before calling searching to attack target
167 
168          //MAX_SEARCH_OR_STOP_WAIT_TERM = 15, // note: should be the largetest default value in waiting_term
169 
170          AUTO_DEFENSE_STAY_OUTSIDE_COUNT = 4, //4 days
171          AUTO_DEFENSE_DETECT_COUNT = 3 + GAME_FRAMES_PER_DAY*AUTO_DEFENSE_STAY_OUTSIDE_COUNT,
172          EFFECTIVE_AUTO_DEFENSE_DISTANCE = 9,
173          AUTO_DEFENSE_SEARCH_TRIES = 100,
174 
175          UNIT_DEFEND_TOWN_DISTANCE = 8,
176          UNIT_DEFEND_TOWN_STAY_OUTSIDE_COUNT = 4, // 4 days
177          UNIT_DEFEND_TOWN_DETECT_COUNT = 3 + GAME_FRAMES_PER_DAY*UNIT_DEFEND_TOWN_STAY_OUTSIDE_COUNT,
178          UNIT_DEFEND_TOWN_WAITING_TERM = 4,
179          EFFECTIVE_DEFEND_TOWN_DISTANCE = 9,
180 
181          MONSTER_DEFEND_FIRM_DISTANCE = 8,
182          MONSTER_DEFEND_STAY_OUTSIDE_COUNT = 4, // 4 days
183          MONSTER_DEFEND_DETECT_COUNT = 3 + GAME_FRAMES_PER_DAY*MONSTER_DEFEND_STAY_OUTSIDE_COUNT,
184          EFFECTIVE_MONSTER_DEFEND_FIRM_DISTANCE = 9,
185 
186          DO_CAST_POWER_RANGE = 3,   // for god to cast power
187       };
188 
189 //----------- Define TeamInfo -------------//
190 
191 #pragma pack(1)
192 struct TeamInfo
193 {
194 	TeamInfo();
195 
196    char  member_count;
197    short member_unit_array[MAX_TEAM_MEMBER];
198    int   ai_last_request_defense_date;
199 };
200 #pragma pack()
201 
202 struct UnitCrc;
203 
204 //----------- Define class Unit -----------//
205 
206 #pragma pack(1)
207 class Unit : public Sprite
208 {
209 public:
210 	char        unit_id;
211 	char        rank_id;
212 	char        race_id;
213 	char        nation_recno;
214 	char        ai_unit;
215 	uint16_t    name_id;             // id. of the unit's name in RaceRes::first_name_array;
216 
217 	uint32_t       unit_group_id;       // the group id this unit belong to if it is selected
218 	uint32_t       team_id;             // id. of defined team
219 	char        selected_flag;       // whether the unit has been selected or not
220 	char        group_select_id;     // id for group selection
221 
222 	char        waiting_term;        // for 2x2 unit only, the term to wait before recalling A* to get a new path
223 	char        blocked_by_member;
224 	char        swapping;
225 
226 	short       leader_unit_recno;   // recno of this unit's leader
227 
is_visible()228 	int           is_visible()      { return cur_x >= 0; }     // whether the unit is visible on the map, it is not invisable if cur_x == -1
229 	virtual char* unit_name(int withTitle=1);
230 	uint8_t          region_id();
231 
232 	//--------- action vars ------------//
233 	char        action_misc;
234 	short       action_misc_para;
235 
236 	char        action_mode;
237 	short       action_para;
238 	short       action_x_loc;
239 	short       action_y_loc;
240 
241 	char        action_mode2;  // store the existing action for speeding up the performance if same action is ordered.
242 	short       action_para2;  // to re-activiate the unit if its cur_action is idle
243 	short       action_x_loc2;
244 	short       action_y_loc2;
245 
246 	char        blocked_edge[4];        // for calling searching in attacking
247 	uint8_t       attack_dir;
248 
249 	//------------ attack parameters -----------//
250 
251 	short       range_attack_x_loc;     // -1 for unable to do range_attack, use to store previous range attack location
252 	short       range_attack_y_loc;     // -1 for unable to do range_attack, use to store previous range attack location
253 
254 	//------------- for unit movement ---------------//
255 
256 	short       move_to_x_loc;          // the location the unit should be moving to
257 	short       move_to_y_loc;
258 
259 	//---------- game vars -------------//
260 
261 	char        loyalty;
262 	char        target_loyalty;
263 
264 	float       hit_points;
265 	short       max_hit_points;
266 
267 	Skill       skill;
268 
269 	char        unit_mode;
270 	short       unit_mode_para;      // if unit_mode==UNIT_MODE_REBEL, unit_mode_para is rebel_recno this unit belongs to
rebel_recno()271 	short       rebel_recno()        { return unit_mode==UNIT_MODE_REBEL ? unit_mode_para : 0; }
272 
273 	short       spy_recno;              // spy parameters
274 
275 	short       nation_contribution;    // For humans: contribution to the nation. For weapons: the tech level!
276 	short       total_reward;           // total amount of reward you have given to the unit
277 
278 	int			commander_power();
279 
280 	//---- share the use of nation_contribution and total_reward ----//
281 
get_monster_id()282 	int         get_monster_id()              { return nation_contribution; }
set_monster_id(int monsterId)283 	void        set_monster_id(int monsterId) { nation_contribution = monsterId; }
284 
get_monster_soldier_id()285 	int         get_monster_soldier_id()                     { return total_reward; }
set_monster_soldier_id(int monsterSoldierId)286 	void        set_monster_soldier_id(int monsterSoldierId) { total_reward = monsterSoldierId; }
287 
get_weapon_version()288 	int         get_weapon_version()                   { return nation_contribution; }
set_weapon_version(int weaponVersion)289 	void        set_weapon_version(int weaponVersion)  { nation_contribution = weaponVersion; }
290 	int			unit_power();
291 
292 	//------- attack parameters --------//
293 
294 	AttackInfo* attack_info_array;
295 	char        attack_count;
296 	char        attack_range;
297 	short       cur_power;              // power for power attack
298 	short       max_power;
299 
300 	//------- path seeking vars --------//
301 
302 	ResultNode* result_node_array;
303 	int         result_node_count;
304 	short       result_node_recno;
305 	short       result_path_dist;
306 
307 	//----------- way points -----------//
308 	enum	{ WAY_POINT_ADJUST_SIZE	= 5};
309 	ResultNode*	way_point_array;
310 	short			way_point_array_size;
311 	short			way_point_count;
312 
313 	//--------- AI parameters ------------//
314 
315 	uint16_t        ai_action_id;     			// an unique id. for locating the AI action node this unit belongs to in Nation::action_array
316 
317 	char  		original_action_mode;
318 	short			original_action_para;
319 	short			original_action_x_loc;
320 	short			original_action_y_loc;
321 
322 	short			original_target_x_loc;     // the original location of the attacking target when the attack() function is called
323 	short			original_target_y_loc;		// action_x_loc2 & action_y_loc2 will change when the unit move, but these two will not.
324 
325 	short			ai_original_target_x_loc;	// for AI only
326 	short			ai_original_target_y_loc;
327 
328 	char			ai_no_suitable_action;
329 
330 	//-------- defense blocking ability flag ----------//
331 
332 	char        can_guard_flag;         // bit0= standing guard, bit1=moving guard
333 													// copy from sprite_info->can_guard_flag when skill.combat level is high enough
334 	char        can_attack_flag;        // 1 able to attack, 0 unable to attack no matter what attack_count is
335 	char        force_move_flag;
336 
337 	short			home_camp_firm_recno;
338 
339 	char			aggressive_mode;
340 
341 	char			seek_path_fail_count;
342 	char			ignore_power_nation;
343 
344 	//------ TeamInfo structure for general and king only ------//
345 
346 	TeamInfo*   team_info;
347 
348 	int         commanded_soldier_count();
349 
350 public:
351 	Unit();
352 	virtual ~Unit();
353 
354 	//------- derived functions from Sprite ------//
355 
356 	virtual void init(int unitId, int nationRecno, int rankId=0, int unitLoyalty=0, int startX= -1, int startY= -1);
357 	virtual void deinit();
init_derived()358 	virtual void init_derived()      {;}
359 
360 			  void init_sprite(int startXLoc, int startYLoc);
361 			  void deinit_sprite(int keepSelected=0);
362 
363 			  void init_unit_id(int unitId);
364 			  void deinit_unit_id();
365 			  void deinit_unit_mode();
366 			  void del_team_member(int);
367 			  void validate_team();
368 
369 			  void draw();
370 	virtual void draw_outlined();
371 			  void draw_selected();
372 			  void draw_skill_icon();
373 
374 			  void set_spy(int spyRecno);
375 			  void set_name(uint16_t newNameId);
376 			  void set_mode(char modeId, short modePara=0) { unit_mode=modeId; unit_mode_para=modePara; }
377 			  int  is_shealth();
378 			  int  is_civilian();
379 			  int  is_own();
380 			  int  is_own_spy();
381 			  int  is_nation(int nationRecno);
382 			  int  true_nation_recno();            // the true nation recno of the unit, taking care of the situation where the unit is a spy
383 	virtual int  is_ai_all_stop();
384 			  int  get_cur_loc(short& xLoc, short& yLoc);
385 			  int  get_cur_loc2(short& xLoc, short& yLoc);
386 			  short is_leader_in_range();
387 
die()388 	virtual void die()         {;}
389 
390 			  //-------------- AI functions -------------//
391 
392 	virtual void process_ai();
393 
394 			  int  think_king_action();
395 			  int  think_general_action();
396 			  int  think_leader_action();
397 			  int  think_normal_human_action();
398 			  int  think_weapon_action();
399 			  int  think_ship_action();
400 			  int  think_assign_weapon_to_camp();
401 			  int  think_build_camp();
402 			  int  think_reward();
403 			  void think_independent_unit();
404 			  void think_spy_action();
405 			  int  think_king_flee();
406 			  int  think_general_flee();
407 			  int  think_stop_chase();
408 
409 			  void ai_move_to_nearby_town();
410 			  int  ai_escape_fire();
411 			  void ai_leader_being_attacked(int attackerUnitRecno);
412 			  int  ai_build_camp();
413 			  int  ai_settle_new_town();
414 			  int  ai_handle_seek_path_fail();
415 
416 	//------- functions for unit AI mode ---------//
417 
418 			  int  think_aggressive_action();
419 			  int  think_change_attack_target();
420 			  int  think_resume_original_action();
421 
422 			  void save_original_action();
423 			  void resume_original_action();
424 			  void resume_original_attack_action();
425 
426 			  void ask_team_help_attack(Unit* attackerUnit);
427 
428 	//------------- processing functions --------------------//
429 
430 	virtual void pre_process();
431 	virtual void process_idle();     // derived function of Sprite
432 	virtual void process_move();     // derived function of Sprite
433 	virtual void process_wait();     // derived function of Sprite
process_extra_move()434 	virtual void process_extra_move() {;}// derived function of Sprite, for ship only
435 	virtual int  process_die();
436 
437 	virtual void next_day();
438 
439 			  void set_next(int nextX, int nextY, int para=0, int blockedChecked=0);
440 
441 	//------------------------------------//
442 
443 	virtual void disp_info(int refreshFlag);
444 	virtual void disp_unit_profile(int dispY1, int refreshFlag);
445 	virtual int  detect_unit_profile();
446 	virtual void detect_info();
447 	virtual bool is_in_build_menu();
448 	int			 should_show_info();
449 
450 			  int  return_camp();
451 
452 	//----------- parameters reseting functions ------------//
453 	virtual void   stop(int preserveAction=0);
454 	void           stop2(int preserveAction=0);
455 	void           reset_action_para();    // reset action_mode parameters
456 	void           reset_action_para2(int keepMode=0); // reset action_mode2 parameters
457 	void           reset_action_misc_para();
458 
459 	//--------------- die actions --------------//
is_unit_dead()460 	int   is_unit_dead() {  return (hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE); }
461 
462 	//------------ movement action -----------------//
463 	virtual void   move_to(int destX, int destY, int preserveAction=0, short searchMode=1, short miscNo=0, short numOfPath=1, short reuseMode=GENERAL_GROUP_MOVEMENT, short pathReuseStatus=0);
464 	void  move_to_unit_surround(int destXLoc, int destYLoc, int width, int height, int miscNo=0, int readyDist=0);
465 	void  move_to_firm_surround(int destXLoc, int destYLoc, int width, int height, int miscNo=0, int readyDist=0);
466 	void  move_to_town_surround(int destXLoc, int destYLoc, int width, int height, int miscNo=0, int readyDist=0);
467 	void  move_to_wall_surround(int destXLoc, int destYLoc, int width, int height, int miscNo=0, int readyDist=0);
468 
469 	void  enable_force_move();
470 	void  disable_force_move();
471 	void  select_search_sub_mode(int sx, int sy, int dx, int dy, short nationRecno, short searchMode);
472 	void  different_territory_destination(int& destX, int& destY); // calculate new destination for move to location on different territory
473 
474 	//----------------- attack action ----------------//
475 	void  attack_unit(int targetXLoc, int targetYLoc, int xOffset=0, int yOffset=0, int resetBlockedEdge=1);
476 	void  attack_unit(short targetRecno, int xOffset=0, int yOffset=0, int resetBlockedEdge=1);
477 	void  attack_firm(int firmXLoc, int firmYLoc, int xOffset=0, int yOffset=0, int resetBlockedEdge=1);
478 	void  attack_town(int townXLoc, int townYLoc, int xOffset=0, int yOffset=0, int resetBlockedEdge=1);
479 	void  attack_wall(int wallXLoc, int wallYLoc, int xOffset=0, int yOffset=0, int resetBlockedEdge=1);
480 
481 	void  hit_target(Unit* parentUnit, Unit* targetUnit, float attackDamage, short parentNationRecno);
482 	void  hit_building(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage, short attackNationRecno);
483 	void  hit_firm(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage, short attackNationRecno);
484 	void  hit_town(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage, short attackNationRecno);
485 	void  hit_wall(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage, short attackNationRecno);
486 
487 	int   max_attack_range();
488 	void  gain_experience();
489 	virtual float  actual_damage();
490 	int   nation_can_attack(short nationRecno); // can this nation be attacked, no if alliance or etc..
491 	int   independent_nation_can_attack(short nationRecno);
492 	void  cycle_eqv_attack();
493 	int   is_action_attack();
can_attack()494 	inline int  can_attack() { return (can_attack_flag && attack_count); }
495 
496 	//-----------------  defense actions ---------------------//
497 	//========== unit's defense mode ==========//
498 	void  defense_attack_unit(short targetRecno);
499 	void  defense_attack_firm(int targetXLoc, int targetYLoc);
500 	void  defense_attack_town(int targetXLoc, int targetYLoc);
501 	void  defense_attack_wall(int targetXLoc, int targetYLoc);
502 	void  defense_detect_target();
503 	int   in_auto_defense_mode();
504 	int   in_defend_town_mode();
505 	int   in_monster_defend_mode();
506 	void  clear_unit_defense_mode();
507 	void  clear_town_defend_mode();
508 	void  clear_monster_defend_mode();
509 
510 	//---------- embark to ship and other ship functions ---------//
511 	void  assign_to_ship(int destX, int destY, short shipRecno, int miscNo=0);
512 	void  ship_to_beach(int destX, int destY, int& finalDestX, int& finalDestY);  // for ship only
513 
514 	//----------- other main action functions -------------//
515 	void  build_firm(int buildXLoc, int buildYLoc, int firmId, char remoteAction);
516 	void  burn(int burnXLoc, int burnYLoc, char remoteAction);
517 	void  settle(int settleXLoc, int settleYLoc, short curSettleUnitNum=1);
518 	void  assign(int buildXLoc, int buildYLoc, short curAssignUnitNum=1);
519 	void  go_cast_power(int castXLoc, int castYLoc, char castPowerType, char remoteAction);
520 	void	add_way_point(short x, short y);
521 	void	reset_way_point_array();
522 	void	process_way_point();
523 
524 	//------------------------------------//
525 
526 	void  change_nation(int newNationRecno);
527 	void  overseer_migrate(int destTownRecno);
caravan_in_firm()528 	int   caravan_in_firm() { return cur_x==-2; }
529 
530 	void  update_loyalty();
531 	void  set_combat_level(int);
532 	void  inc_minor_combat_level(int);
533 	void  inc_minor_skill_level(int);
534 	void  set_rank(int rankId);
535 	virtual int	can_resign();
536 	void  resign(int remoteAction);
537 	void  embark(int vehicleRecno);
538 	void  reward(int rewardNationRecno);
539 	void  transform();
540 	void  group_transform(char remoteAction, short *selectedArray=NULL, short selectedCount=0);
541 	void  spy_change_nation(int nationRecno, char remoteAction, int groupDefect = 0);
542 	int   can_spy_change_nation();
543 
544 	void  change_hit_points(float changePoints);
545 	void  change_loyalty(int loyaltyChange);
546 
547 	int   think_betray();
548 	int   betray(int newNationRecno);
549 
can_stand_guard()550 	int   can_stand_guard()  { return can_guard_flag & 1;}
can_move_guard()551 	int   can_move_guard()  { return can_guard_flag & 2;}
can_attack_guard()552 	int   can_attack_guard()  { return can_guard_flag & 4;}
553 
554 	int   firm_can_assign(short firmRecno);
555 
556 	void  set_idle();
557 	void  set_ready();
558 	void  set_move();
559 	void  set_wait();
560 	void  set_attack();
561 	void  set_turn();
562 	void  set_ship_extra_move();
563 	void  set_die();
564 
565 	int   write_file(File* filePtr);
566 	int   read_file(File* filePtr);
567 
568 	virtual int write_derived_file(File* filePtr);
569 	virtual int read_derived_file(File* filePtr);
570 	virtual void fix_attack_info();         // set attack_info_array appropriately
571 
572 	//-------------- multiplayer checking codes ---------------//
573 	virtual	uint8_t crc8();
574 	virtual	void	clear_ptr();
575 	virtual	void	init_crc(UnitCrc *c);
576 
577 private:
578 	//------------------ idle functions -------------------//
579 	int            reactivate_idle_action();
580 	int            idle_detect_attack(int startLoc=0, int dimensionInput=0, char defenseMode=0); // detect target to attack
581 	int            idle_detect_choose_target(char defenseMode);
582 	void           idle_detect_helper_attack(short unitRecno);
583 	int            idle_detect_unit_checking(short targetRecno);
584 	int            idle_detect_firm_checking(short targetRecno);
585 	int            idle_detect_town_checking(short targetRecno);
586 	int            idle_detect_wall_checking(int targetXLoc, int targetYLoc);
587 
588 	//------------ movement action -----------------//
589 	int   search(int destX, int destY, int preserveAction=0, short searchMode=1, short miscNo=0, short numOfPath=1, short reuseMode=GENERAL_GROUP_MOVEMENT, short pathReuseStatus=0);
590 	int   searching(int destX, int destY, int preserveAction, short searchMode, short miscNo, short numOfPath, short reuseMode, short pathReuseStatus);
591 	int   set_move_to_surround(int buildXLoc, int buildYLoc, int width, int height, int buildingType, int miscNo=0, int readyDist=0, short curSettleUnitNum=1);
592 	int   edit_path_to_surround(int x1, int y1, int x2, int y2, int readyDist);
593 	void  search_or_stop(int destX, int destY, int preserveAction=0, short searchMode=1, short miscNo=0);
594 	void  search_or_wait();
595 	//void   move_to_surround_s2(int destXLoc, int destYLoc); // for 2x2 unit only
596 	int   move_to_range_attack(int targetXLoc, int targetYLoc, short miscNo, short searchMode, short maxRange); // move to target for using range attack
597 
598 	void  abort_searching(int reuseSetNext);
599 	void  set_search_tries(int tries);     // set parameters to limit the nodes used in searching
600 	void  reset_search_tries();            // reset parameters for using default nodes in searching
601 
602 	//---------------- handle blocked action ------------------//
603 	void  move_to_my_loc(Unit* unitPtr);
604 	void  handle_blocked_move(Location* blockedLoc); // used to determine unit size and call other handle_blocked_move.. functions
605 	void  handle_blocked_move_s11(Unit* unitPtr);
606 	//void  handle_blocked_move_s12(Unit* unitPtr);
607 	//void  handle_blocked_move_s21(Unit* unitPtr);
608 	//void  handle_blocked_move_s22(Unit* unitPtr);
609 	//int blocked_move_new_handle();
610 	//void   set_path_to(int destXLoc, int destYLoc);
611 	void  handle_blocked_by_idle_unit(Unit *unitPtr);
612 	int   on_my_path(short checkXLoc, short checkYLoc);
613 
614 	void  handle_blocked_wait(Unit* unitPtr);
615 	void  cycle_wait_shift_recno(Unit* curUnit, Unit* nextUnit);
616 	void  opposite_direction_blocked(short vecX, short vecY, short unitPtrVecX, short unitPtrVecY, Unit* unitPtr);
617 
618 	void  handle_blocked_attack_unit(Unit *unitPtr, Unit *targetPtr);
619 	void  handle_blocked_attack_firm(Unit *unitPtr);
620 	void  handle_blocked_attack_town(Unit *unitPtr);
621 	void  handle_blocked_attack_wall(Unit *unitPtr);
622 	void  handle_blocked_same_target_attack(Unit* unitPtr, Unit* targetPtr);
623 
624 	//====== support functions for process_attack_unit()
625 	void  target_move(Unit* targetUnit);
626 	void  attack_target(Unit* targetUnit);
627 	int   on_way_to_attack(Unit* targetUnit);
628 	int   detect_surround_target();
629 	int   update_attack_path_dist();
630 	void  set_attack_dir(short curX, short curY, short targetX, short targetY);
631 
632 	//====== functions for attacking between UNIT_LAND, UNIT_SEA, UNIT_AIR
633 	int   move_try_to_range_attack(Unit* targetUnit);
634 	//void   move_to_range_attack(int targetXLoc, int targetYLoc, short miscNo, short searchMode, short maxRange); //---defined above
635 	int   can_attack_different_target_type();
636 	int   possible_place_for_range_attack(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, int maxRange);
637 
638 	//====== functions for reactivating idle units and blocked units that are ordered to attack
639 	int   space_for_attack(int targetXLoc, int targetYLoc, char targetMobileType, int targetWidth, int targetHeight);
640 	int   space_around_target(int squareXLoc, int squareYLoc, int width, int height);
641 	int   space_around_target_ver2(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight);
642 	int   ship_surr_has_free_land(int targetXLoc, int targetYLoc, uint8_t regionId);
643 	int   free_space_for_range_attack(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, int targetMobileType, int maxRange);
644 
645 	void  choose_best_attack_mode(int attackDistance, char targetMobileType=UNIT_LAND);
646 	void  unit_auto_guarding(Unit *attackUnit);
647 	void  set_unreachable_location(int xLoc, int yLoc);
648 	void  check_self_surround();
649 	int   can_attack_with(int i);               // 0 to attack_count-1
650 	int   can_attack_with(AttackInfo *attackInfo);
651 	void  get_hit_x_y(short *xPtr, short *yPtr);
652 	void  add_close_attack_effect();
653 
654 	//-----------------  defense actions ---------------------//
655 	//=========== unit's defend mode generalized functions ============//
656 	int   in_any_defense_mode();
657 	void  general_defend_mode_detect_target(int checkDefendMode=0);
658 	int   general_defend_mode_process_attack_target();
659 
660 	//========== unit's defense mode ==========//
661 	void  defense_back_camp(int targetXLoc, int targetYLoc);
662 	void  process_auto_defense_attack_target();
663 	void  process_auto_defense_detect_target();
664 	void  process_auto_defense_back_camp();
665 	int   defense_follow_target();
666 
667 	//========== town unit's defend mode ==========//
668 	void  defend_town_attack_unit(short targetRecno);
669 	void  defend_town_detect_target();
670 	void  defend_town_back_town(short townRecno);
671 	void  process_defend_town_attack_target();
672 	void  process_defend_town_detect_target();
673 	void  process_defend_town_back_town();
674 	int   defend_town_follow_target();
675 
676 	//========== monster unit's defend mode ==========//
677 	void  monster_defend_attack_unit(short targetRecno);
678 	void  monster_defend_attack_firm(int targetXLoc, int targetYLoc);
679 	void  monster_defend_attack_town(int targetXLoc, int targetYLoc);
680 	void  monster_defend_attack_wall(int targetXLoc, int targetYLoc);
681 	void  monster_defend_detect_target();
682 	void  monster_defend_back_firm(int targetXLoc, int targetYLoc);
683 	void  process_monster_defend_attack_target();
684 	void  process_monster_defend_detect_target();
685 	void  process_monster_defend_back_firm();
686 	int   monster_defend_follow_target();
687 
688 	//---------- embark to ship and other ship functions ---------//
689 	int   ship_to_beach_path_edit(int& resultXLoc, int& resultYLoc, uint8_t regionId);
690 	void  ship_leave_beach(int shipOldXLoc, int shipOldYLoc);
691 
692 	//---------------- other functions -----------------//
693 	int   cal_distance(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight); // calculate distance from this unit(can be 1x1, 2x2) to a known size object
694 	int   is_in_surrounding(int checkXLoc, int checkYLoc, int width, int targetXLoc, int targetYLoc, int targetWidth, int targetHeight);
695 	int   avail_node_enough_for_search(short x1, short y1, short x2, short y2);
696 	// int   firm_can_assign(short firmRecno);
697 
698 protected:
699 	void  disp_main_menu(int);
700 	void  detect_main_menu();
701 	void  disp_build_menu(int);
702 	void  detect_build_menu();
703 	void  disp_button(int dispY1);
704 	void  detect_button();
705 	void  disp_build(int);
706 	void  detect_build();
707 	void  disp_settle(int);
708 	void  detect_settle();
709 	void  disp_unit_info(int dispY1, int refreshFlag);
710 	void  disp_basic_info(int dispY1, int refreshFlag);
711 	int   detect_basic_info();
712 	void  disp_spy_menu(int dispY1, int refreshFlag);
713 	void  detect_spy_menu(int dispY1);
714 	int   spy_menu_height();
715 	void  disp_hit_point(int dispY1);
716 	int   detect_select_hotkey();
717 
718 	void  process_attack_unit();
719 	void  process_attack_firm();
720 	void  process_build_firm();
721 	void  process_attack_town();
722 	void  process_attack_wall();
723 	void  process_assign();
724 	void  process_burn();
725 	void  process_settle();
726 	void  process_assign_to_ship();
727 	void  process_ship_to_beach();
728 	void  process_rebel();
729 	void  process_go_cast_power();
730 
731 	void  next_move();
732 
733 	void  terminate_move();
734 	void  reset_path();
735 
736 	void  king_die();
737 	void  general_die();
738 	void  pay_expense();
739 	void  process_recover();
740 };
741 #pragma pack()
742 
743 //--------------------------------------------------------------------------------------------//
744 
745 //------- Define class UnitArray ---------//
746 
747 class UnitArray : public SpriteArray
748 {
749 public:
750 	short selected_recno;
751 	short selected_count;
752 
753 	uint32_t cur_group_id;            // for Unit::unit_group_id
754 	uint32_t cur_team_id;             // for Unit::team_id
755 
756 	short idle_blocked_unit_reset_count; // used to improve performance for searching related to attack
757 
758 	short visible_unit_count;
759 
760 	static short   selected_land_unit_count;
761 	static short   selected_sea_unit_count;
762 	static short   selected_air_unit_count;
763 	static short   *selected_land_unit_array;
764 	static short   *selected_sea_unit_array;
765 	static short   *selected_air_unit_array;
766 
767 public:
768 	UnitArray(int);
769 
770 	void  init();
771 
772 	int   add_unit(int unitId, int nationRecno, int rankId=0, int unitLoyalty=0, int startXLoc= -1, int startYLoc= -1);
773 	Unit* create_unit(int unitId);
774 	int   unit_class_size(int);
775 
776 	void  disappear_in_town(int unitRecno, int townRecno);
777 	void  disappear_in_firm(int unitRecno);
778 	void  die(int unitRecno);
779 	void	return_camp(int remoteAction, short* selectedUnitArray=NULL, int selectedCount=0);
780 
781 	void  draw_dot();
782 	void	draw_profile();
783 	void  process();
784 
785 	void  stop(short* selectedUnitArray, int selectedCount, char remoteAction);
786 	void  stop_all_war(short oldNationRecno);
787 	void  stop_war_between(short nationRecno1, short nationRecno2);
788 	void  stop_attack_unit(short unitRecno);
789 	void  stop_attack_firm(short firmRecno);
790 	void  stop_attack_town(short townRecno);
791 
792 	//---------- move main functions -------------//
793 	void  move_to(int destX, int destY, int divided, short* selectedUnitArray, int selectedCount, char remoteAction);
794 
795 	//------------- attack main functions ----------//
796 	// ###### patch begin Gilbert 5/8 ######//
797 	void  attack(int destX, int destY, int divided, short* selectedUnitArray, int selectedCount, char remoteAction, int unitRecno);
798 	// ###### patch end Gilbert 5/8 ######//
799 	void  attack_unit(int targetXLoc, int targetYLoc, short targetUnitRecno, short* selectedUnitArray, int selectedCount);
800 	void  attack_firm(int targetXLoc, int targetYLoc, short firmRecno, short* selectedUnitArray, int selectedCount);
801 	void  attack_town(int targetXLoc, int targetYLoc, short townRecno, short* selectedUnitArray, int selectedCount);
802 	void  attack_wall(int targetXLoc, int targetYLoc, short* selectedUnitArray, int selectedCount);
803 
804 	//---------- other actions functions -----------//
805 	void  assign(int destX, int destY, int divided, char remoteAction, short* selectedUnitArray=NULL, int selectedCount=0);
806 	void  assign_to_camp(int destX, int destY, char remoteAction, short* selectedUnitArray=NULL, int selectedCount=0);
807 	void  settle(int destX, int destY, int divided, char remoteAction, short *selectedUnitArray=NULL, int selectedCount=0);
808 	// ##### patch begin Gilbert 5/8 ######//
809 	void  assign_to_ship(int shipXLoc, int shipYLoc, int divided, short* selectedArray, int selectedCount, char remoteAction, int shipRecno);
810 	// ##### patch end Gilbert 5/8 ######//
811 	void  ship_to_beach(int destX, int destY, int divided, short* selectedArray, int selectedCount, char remoteAction);
812 	void	add_way_point(int pointX, int pointY, short* selectedArray, int selectedCount, char remoteAction);
813 
814 	//--------- unit filter function ----------//
815 	int   divide_attack_by_nation(short nationRecno, short *selectedArray, int selectedCount);
816 
817 	int   write_file(File* filePtr);
818 	int   read_file(File* filePtr);
819 
820 	#ifdef DYNARRAY_DEBUG_ELEMENT_ACCESS
821 		Unit* operator[](int recNo);
822 	#else
823 		Unit* operator[](int recNo)   { return (Unit*) get_ptr(recNo); }
824 	#endif
825 
826 	int   is_deleted(int recNo);
827 	int   is_truly_deleted(int recNo);
828 
829 	void  disp_next(int seekDir, int sameNation);
830 
831 private:
832 	void  divide_array(int locX, int locY, short* selectedArray, int selectedCount, int excludeSelectedLocUnit=0);
833 	void  set_group_id(short* selectedArray, int selectedCount);
834 
835 	//------------ move sub-functions --------------//
836 	void  move_to_now_with_filter(int destX, int destY, short* selectedUnitArray, int selectedCount);
837 	void  move_to_now(int destX, int destY, short* selectedUnitArray, int selectedCount);
838 	void  construct_sorted_array(short* selectedUnitArray, int selectedCount);
839 	void  determine_position_to_construct_table(int selectedCount, int destXLoc, int destYLoc, char mobileType);
840 
841 	//-------------- attack sub-functions -----------//
842 	// ###### patch begin Gilbert 5/8 #######//
843 	void  attack_call(int destX, int destY, char mobileType, char targetMobileType, int divided, short* selectedUnitArray, int selectedCount, int targetUnitRecno);
844 	// ###### patch end Gilbert 5/8 #######//
845 	void  update_unreachable_table(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, char mobileType, int &analyseResult);
846 	char  get_target_surround_loc(int targetWidth, int targetHeight);
847 	char* get_target_x_offset(int targetWidth, int targetHeight, char curDir);
848 	char* get_target_y_offset(int targetWidth, int targetHeight, char curDir);
849 
850 	void  arrange_units_in_group(int xLoc1, int yLoc1, int xLoc2, int yLoc2, short* selectedUnitArray, int selectedCount, uint32_t unitGroupId, int targetType);
851 	int   analyse_surround_location(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, char mobileType);
852 	void  check_nearby_location(int targetXLoc, int targetYLoc, char xOffset, char yOffset, int targetWidth, int targetHeight, char targetMobileType, int& analyzeResult);
853 	void  handle_attack_target_totally_blocked(int targetXLoc, int targetYLoc, short targetRecno, short *selectedUnitArray, short selectedCount, int targetType);
854 
855 	//---------- other actions functions -----------//
856 	void  group_assign(int destX, int destY, short* selectedArray, int selectedCount);
857 	void  group_settle(int destX, int destY, short* selectedArray, int selectedCount);
858 };
859 
860 extern UnitArray unit_array;
861 extern int unit_search_node_used;
862 extern int     unit_search_tries;        // the number of tries used in the current searching
863 extern char    unit_search_tries_flag;   // indicate num of tries is set, reset after searching
864 #ifdef DEBUG
865 extern int check_unit_dir1, check_unit_dir2;
866 #endif
867 
868 #endif
869 
870