File: OUNIT.h

package info (click to toggle)
7kaa 2.15.6%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 131,312 kB
  • sloc: cpp: 134,790; asm: 3,523; ansic: 1,949; perl: 1,665; makefile: 1,181; sh: 126; pascal: 27
file content (869 lines) | stat: -rw-r--r-- 35,282 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
/*
 * 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    : OUNIT.H
//Description : Header file of Object Unit

#ifndef __OUNIT_H
#define __OUNIT_H

#ifndef __OSPRITE_H
#include <OSPRITE.h>
#endif

#ifndef __OSPATH_H
#include <OSPATH.h>
#endif

#ifndef __OUNITRES_H
#include <OUNITRES.h>
#endif

#ifndef __OBUTTON_H
#include <OBUTTON.h>
#endif

#ifndef __OSKILL_H
#include <OSKILL.h>
#endif

#ifndef __OSPREUSE_H
#include <OSPREUSE.h>
#endif

#ifdef NO_DEBUG_UNIT
#undef DEBUG
#endif

#define GAME_FRAMES_PER_DAY 10

//-------- action code for action_mode ---------//

enum { ACTION_STOP,
       ACTION_ATTACK_UNIT,
       ACTION_ATTACK_FIRM,
       ACTION_ATTACK_TOWN,
       ACTION_ATTACK_WALL,
       ACTION_ASSIGN_TO_FIRM,
       ACTION_ASSIGN_TO_TOWN,
       ACTION_ASSIGN_TO_VEHICLE,
       ACTION_ASSIGN_TO_SHIP,
       ACTION_SHIP_TO_BEACH,  // used for UNIT_SEA only
       ACTION_BUILD_FIRM,
       ACTION_SETTLE,
       ACTION_BURN,
       ACTION_DIE,
       ACTION_MOVE,
       ACTION_GO_CAST_POWER,  // for god only

       //------------ used only for action_mode2 -----------------//
       //------- put the following nine parameters together -------//

       ACTION_AUTO_DEFENSE_ATTACK_TARGET, // move to target for attacking
       ACTION_AUTO_DEFENSE_DETECT_TARGET, // is idle, detect target to attack or waiting for defense action, (detect range is larger as usual)
       ACTION_AUTO_DEFENSE_BACK_CAMP,     // go back to camp for training or ready for next defense action
       ACTION_DEFEND_TOWN_ATTACK_TARGET,
       ACTION_DEFEND_TOWN_DETECT_TARGET,
       ACTION_DEFEND_TOWN_BACK_TOWN,
       ACTION_MONSTER_DEFEND_ATTACK_TARGET,
       ACTION_MONSTER_DEFEND_DETECT_TARGET,
       ACTION_MONSTER_DEFEND_BACK_FIRM,
     };

//-------- define action type for action_misc ----------//

enum  {  ACTION_MISC_STOP = 0,
         ACTION_MISC_CAPTURE_TOWN_RECNO,
         ACTION_MISC_DEFENSE_CAMP_RECNO,
         ACTION_MISC_DEFEND_TOWN_RECNO,
         ACTION_MISC_MONSTER_DEFEND_FIRM_RECNO,
         ACTION_MISC_PRE_SEARCH_NODE_USED_UP,
      };

//--------- unit mode ------------//

enum { UNIT_MODE_OVERSEE=1,         // unit_mode_para is the recno of the firm the unit is overseeing
       UNIT_MODE_DEFEND_TOWN,       // unit_mode_para is the recno of the town the unit is defending
       UNIT_MODE_CONSTRUCT,         // unit_mode_para is the recno of the firm the unit is constructing
       UNIT_MODE_REBEL,             // unit_mode_para is the recno of the rebel group the unit belongs to
       UNIT_MODE_MONSTER,           // unit_mode_para is the recno of the firm recno of the monster firm it belongs to
       UNIT_MODE_ON_SHIP,           // unit_mode_para is the recno of the ship unit this unit is on
		 UNIT_MODE_IN_HARBOR,         // for ships only, unit_mode_para is the recno of the harbor this marine unit is in
		 UNIT_MODE_UNDER_TRAINING,
     };

//-------------- unit rank -------------//

enum { MAX_RANK=3 };

enum { RANK_SOLDIER,
       RANK_GENERAL,
       RANK_KING,
     };

//------------- unit salary -----------//

enum { SOLDIER_YEAR_SALARY  = 10,
		 GENERAL_YEAR_SALARY  = 50,
		 SPY_YEAR_SALARY      = 100 };

//------- other constant ----------//

enum { EFFECTIVE_LEADING_DISTANCE = 10 };

enum { ATTACK_DIR = 8 };      // define number of attacking direction

enum { MAX_TEAM_MEMBER = 9 }; // maximum no. of units a general/king can lead

enum { MAX_NATION_CONTRIBUTION = 10000 };		// there is an upper limit nation_contribution as it is a <short>  

//---------- used in set_move_to_surround -----------//

enum  { BUILDING_TYPE_FIRM_MOVE_TO,       // firm already exists
        BUILDING_TYPE_FIRM_BUILD,         // no firm there
        BUILDING_TYPE_TOWN_MOVE_TO,       // town already exists
        BUILDING_TYPE_SETTLE,             // no town there
        BUILDING_TYPE_VEHICLE,            // location is blocked by the vehicle
        BUILDING_TYPE_WALL,               // location is occupied by the wall
      };

//------------ define help mode ----------//
enum  {  HELP_NOTHING =0,
         HELP_ATTACK_UNIT,
         HELP_ATTACK_FIRM,
         HELP_ATTACK_TOWN,
         HELP_ATTACK_WALL,
       };

//---------- misc constant parameters ----------//

enum  {  KEEP_PRESERVE_ACTION = 1,  // used for stop2() to keep preserve action
         KEEP_DEFENSE_MODE = 2,     // used for stop2() to keep the defense mode
         KEEP_DEFEND_TOWN_MODE = 3, // used for stop2() to keep the defend town mode

         MAX_WAITING_TERM_SAME = 3, // wait for same nation, used in handle_blocked...()
         MAX_WAITING_TERM_DIFF = 3, // wait for diff. nation, used in handle_blocked...()

			ATTACK_DETECT_DISTANCE = 6,// the distance for the unit to detect target while idle
         ATTACK_SEARCH_TRIES = 250, // the node no. used to process searching when target is close to this unit
         ATTACK_WAITING_TERM = 10,  // terms no. to wait before calling searching to attack target

         //MAX_SEARCH_OR_STOP_WAIT_TERM = 15, // note: should be the largetest default value in waiting_term

         AUTO_DEFENSE_STAY_OUTSIDE_COUNT = 4, //4 days
         AUTO_DEFENSE_DETECT_COUNT = 3 + GAME_FRAMES_PER_DAY*AUTO_DEFENSE_STAY_OUTSIDE_COUNT,
         EFFECTIVE_AUTO_DEFENSE_DISTANCE = 9,
         AUTO_DEFENSE_SEARCH_TRIES = 100,

         UNIT_DEFEND_TOWN_DISTANCE = 8,
         UNIT_DEFEND_TOWN_STAY_OUTSIDE_COUNT = 4, // 4 days
         UNIT_DEFEND_TOWN_DETECT_COUNT = 3 + GAME_FRAMES_PER_DAY*UNIT_DEFEND_TOWN_STAY_OUTSIDE_COUNT,
         UNIT_DEFEND_TOWN_WAITING_TERM = 4,
         EFFECTIVE_DEFEND_TOWN_DISTANCE = 9,

         MONSTER_DEFEND_FIRM_DISTANCE = 8,
         MONSTER_DEFEND_STAY_OUTSIDE_COUNT = 4, // 4 days
         MONSTER_DEFEND_DETECT_COUNT = 3 + GAME_FRAMES_PER_DAY*MONSTER_DEFEND_STAY_OUTSIDE_COUNT,
         EFFECTIVE_MONSTER_DEFEND_FIRM_DISTANCE = 9,

         DO_CAST_POWER_RANGE = 3,   // for god to cast power
      };

//----------- Define TeamInfo -------------//

#pragma pack(1)
struct TeamInfo
{
	TeamInfo();

   char  member_count;
   short member_unit_array[MAX_TEAM_MEMBER];
   int   ai_last_request_defense_date;
};
#pragma pack()

struct UnitCrc;

//----------- Define class Unit -----------//

#pragma pack(1)
class Unit : public Sprite
{
public:
	char        unit_id;
	char        rank_id;
	char        race_id;
	char        nation_recno;
	char        ai_unit;
	uint16_t    name_id;             // id. of the unit's name in RaceRes::first_name_array;

	uint32_t       unit_group_id;       // the group id this unit belong to if it is selected
	uint32_t       team_id;             // id. of defined team
	char        selected_flag;       // whether the unit has been selected or not
	char        group_select_id;     // id for group selection

	char        waiting_term;        // for 2x2 unit only, the term to wait before recalling A* to get a new path
	char        blocked_by_member;
	char        swapping;

	short       leader_unit_recno;   // recno of this unit's leader

	int           is_visible()      { return cur_x >= 0; }     // whether the unit is visible on the map, it is not invisable if cur_x == -1
	virtual char* unit_name(int withTitle=1);
	uint8_t          region_id();

	//--------- action vars ------------//
	char        action_misc;
	short       action_misc_para;

	char        action_mode;
	short       action_para;
	short       action_x_loc;
	short       action_y_loc;

	char        action_mode2;  // store the existing action for speeding up the performance if same action is ordered.
	short       action_para2;  // to re-activiate the unit if its cur_action is idle
	short       action_x_loc2;
	short       action_y_loc2;

	char        blocked_edge[4];        // for calling searching in attacking
	uint8_t       attack_dir;

	//------------ attack parameters -----------//

	short       range_attack_x_loc;     // -1 for unable to do range_attack, use to store previous range attack location
	short       range_attack_y_loc;     // -1 for unable to do range_attack, use to store previous range attack location

	//------------- for unit movement ---------------//

	short       move_to_x_loc;          // the location the unit should be moving to
	short       move_to_y_loc;

	//---------- game vars -------------//

	char        loyalty;
	char        target_loyalty;

	float       hit_points;
	short       max_hit_points;

	Skill       skill;

	char        unit_mode;
	short       unit_mode_para;      // if unit_mode==UNIT_MODE_REBEL, unit_mode_para is rebel_recno this unit belongs to
	short       rebel_recno()        { return unit_mode==UNIT_MODE_REBEL ? unit_mode_para : 0; }

	short       spy_recno;              // spy parameters

	short       nation_contribution;    // For humans: contribution to the nation. For weapons: the tech level!
	short       total_reward;           // total amount of reward you have given to the unit

	int			commander_power();

	//---- share the use of nation_contribution and total_reward ----//

	int         get_monster_id()              { return nation_contribution; }
	void        set_monster_id(int monsterId) { nation_contribution = monsterId; }

	int         get_monster_soldier_id()                     { return total_reward; }
	void        set_monster_soldier_id(int monsterSoldierId) { total_reward = monsterSoldierId; }

	int         get_weapon_version()                   { return nation_contribution; }
	void        set_weapon_version(int weaponVersion)  { nation_contribution = weaponVersion; }
	int			unit_power();

	//------- attack parameters --------//

	AttackInfo* attack_info_array;
	char        attack_count;
	char        attack_range;
	short       cur_power;              // power for power attack
	short       max_power;

	//------- path seeking vars --------//

	ResultNode* result_node_array;
	int         result_node_count;
	short       result_node_recno;
	short       result_path_dist;

	//----------- way points -----------//
	enum	{ WAY_POINT_ADJUST_SIZE	= 5};
	ResultNode*	way_point_array;
	short			way_point_array_size;
	short			way_point_count;

	//--------- AI parameters ------------//

	uint16_t        ai_action_id;     			// an unique id. for locating the AI action node this unit belongs to in Nation::action_array

	char  		original_action_mode;
	short			original_action_para;
	short			original_action_x_loc;
	short			original_action_y_loc;

	short			original_target_x_loc;     // the original location of the attacking target when the attack() function is called
	short			original_target_y_loc;		// action_x_loc2 & action_y_loc2 will change when the unit move, but these two will not.

	short			ai_original_target_x_loc;	// for AI only
	short			ai_original_target_y_loc;

	char			ai_no_suitable_action;

	//-------- defense blocking ability flag ----------//

	char        can_guard_flag;         // bit0= standing guard, bit1=moving guard
													// copy from sprite_info->can_guard_flag when skill.combat level is high enough
	char        can_attack_flag;        // 1 able to attack, 0 unable to attack no matter what attack_count is
	char        force_move_flag;

	short			home_camp_firm_recno;

	char			aggressive_mode;

	char			seek_path_fail_count;
	char			ignore_power_nation;

	//------ TeamInfo structure for general and king only ------//

	TeamInfo*   team_info;

	int         commanded_soldier_count();

public:
	Unit();
	virtual ~Unit();

	//------- derived functions from Sprite ------//

	virtual void init(int unitId, int nationRecno, int rankId=0, int unitLoyalty=0, int startX= -1, int startY= -1);
	virtual void deinit();
	virtual void init_derived()      {;}

			  void init_sprite(int startXLoc, int startYLoc);
			  void deinit_sprite(int keepSelected=0);

			  void init_unit_id(int unitId);
			  void deinit_unit_id();
			  void deinit_unit_mode();
			  void del_team_member(int);
			  void validate_team();

			  void draw();
	virtual void draw_outlined();
			  void draw_selected();
			  void draw_skill_icon();

			  void set_spy(int spyRecno);
			  void set_name(uint16_t newNameId);
			  void set_mode(char modeId, short modePara=0) { unit_mode=modeId; unit_mode_para=modePara; }
			  int  is_shealth();
			  int  is_civilian();
			  int  is_own();
			  int  is_own_spy();
			  int  is_nation(int nationRecno);
			  int  true_nation_recno();            // the true nation recno of the unit, taking care of the situation where the unit is a spy
	virtual int  is_ai_all_stop();
			  int  get_cur_loc(short& xLoc, short& yLoc);
			  int  get_cur_loc2(short& xLoc, short& yLoc);
			  short is_leader_in_range();

	virtual void die()         {;}

			  //-------------- AI functions -------------//

	virtual void process_ai();

			  int  think_king_action();
			  int  think_general_action();
			  int  think_leader_action();
			  int  think_normal_human_action();
			  int  think_weapon_action();
			  int  think_ship_action();
			  int  think_assign_weapon_to_camp();
			  int  think_build_camp();
			  int  think_reward();
			  void think_independent_unit();
			  void think_spy_action();
			  int  think_king_flee();
			  int  think_general_flee();
			  int  think_stop_chase();

			  void ai_move_to_nearby_town();
			  int  ai_escape_fire();
			  void ai_leader_being_attacked(int attackerUnitRecno);
			  int  ai_build_camp();
			  int  ai_settle_new_town();
			  int  ai_handle_seek_path_fail();

	//------- functions for unit AI mode ---------//

			  int  think_aggressive_action();
			  int  think_change_attack_target();
			  int  think_resume_original_action();

			  void save_original_action();
			  void resume_original_action();
			  void resume_original_attack_action();

			  void ask_team_help_attack(Unit* attackerUnit);

	//------------- processing functions --------------------//

	virtual void pre_process();
	virtual void process_idle();     // derived function of Sprite
	virtual void process_move();     // derived function of Sprite
	virtual void process_wait();     // derived function of Sprite
	virtual void process_extra_move() {;}// derived function of Sprite, for ship only
	virtual int  process_die();

	virtual void next_day();

			  void set_next(int nextX, int nextY, int para=0, int blockedChecked=0);

	//------------------------------------//

	virtual void disp_info(int refreshFlag);
	virtual void disp_unit_profile(int dispY1, int refreshFlag);
	virtual int  detect_unit_profile();
	virtual void detect_info();
	virtual bool is_in_build_menu();
	int			 should_show_info();

			  int  return_camp();

	//----------- parameters reseting functions ------------//
	virtual void   stop(int preserveAction=0);
	void           stop2(int preserveAction=0);
	void           reset_action_para();    // reset action_mode parameters
	void           reset_action_para2(int keepMode=0); // reset action_mode2 parameters
	void           reset_action_misc_para();

	//--------------- die actions --------------//
	int   is_unit_dead() {  return (hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE); }

	//------------ movement action -----------------//
	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);
	void  move_to_unit_surround(int destXLoc, int destYLoc, int width, int height, int miscNo=0, int readyDist=0);
	void  move_to_firm_surround(int destXLoc, int destYLoc, int width, int height, int miscNo=0, int readyDist=0);
	void  move_to_town_surround(int destXLoc, int destYLoc, int width, int height, int miscNo=0, int readyDist=0);
	void  move_to_wall_surround(int destXLoc, int destYLoc, int width, int height, int miscNo=0, int readyDist=0);

	void  enable_force_move();
	void  disable_force_move();
	void  select_search_sub_mode(int sx, int sy, int dx, int dy, short nationRecno, short searchMode);
	void  different_territory_destination(int& destX, int& destY); // calculate new destination for move to location on different territory

	//----------------- attack action ----------------//
	void  attack_unit(int targetXLoc, int targetYLoc, int xOffset=0, int yOffset=0, int resetBlockedEdge=1);
	void  attack_unit(short targetRecno, int xOffset=0, int yOffset=0, int resetBlockedEdge=1);
	void  attack_firm(int firmXLoc, int firmYLoc, int xOffset=0, int yOffset=0, int resetBlockedEdge=1);
	void  attack_town(int townXLoc, int townYLoc, int xOffset=0, int yOffset=0, int resetBlockedEdge=1);
	void  attack_wall(int wallXLoc, int wallYLoc, int xOffset=0, int yOffset=0, int resetBlockedEdge=1);

	void  hit_target(Unit* parentUnit, Unit* targetUnit, float attackDamage, short parentNationRecno);
	void  hit_building(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage, short attackNationRecno);
	void  hit_firm(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage, short attackNationRecno);
	void  hit_town(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage, short attackNationRecno);
	void  hit_wall(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage, short attackNationRecno);

	int   max_attack_range();
	void  gain_experience();
	virtual float  actual_damage();
	int   nation_can_attack(short nationRecno); // can this nation be attacked, no if alliance or etc..
	int   independent_nation_can_attack(short nationRecno);
	void  cycle_eqv_attack();
	int   is_action_attack();
	inline int  can_attack() { return (can_attack_flag && attack_count); }

	//-----------------  defense actions ---------------------//
	//========== unit's defense mode ==========//
	void  defense_attack_unit(short targetRecno);
	void  defense_attack_firm(int targetXLoc, int targetYLoc);
	void  defense_attack_town(int targetXLoc, int targetYLoc);
	void  defense_attack_wall(int targetXLoc, int targetYLoc);
	void  defense_detect_target();
	int   in_auto_defense_mode();
	int   in_defend_town_mode();
	int   in_monster_defend_mode();
	void  clear_unit_defense_mode();
	void  clear_town_defend_mode();
	void  clear_monster_defend_mode();

	//---------- embark to ship and other ship functions ---------//
	void  assign_to_ship(int destX, int destY, short shipRecno, int miscNo=0);
	void  ship_to_beach(int destX, int destY, int& finalDestX, int& finalDestY);  // for ship only

	//----------- other main action functions -------------//
	void  build_firm(int buildXLoc, int buildYLoc, int firmId, char remoteAction);
	void  burn(int burnXLoc, int burnYLoc, char remoteAction);
	void  settle(int settleXLoc, int settleYLoc, short curSettleUnitNum=1);
	void  assign(int buildXLoc, int buildYLoc, short curAssignUnitNum=1);
	void  go_cast_power(int castXLoc, int castYLoc, char castPowerType, char remoteAction);
	void	add_way_point(short x, short y);
	void	reset_way_point_array();
	void	process_way_point();

	//------------------------------------//

	void  change_nation(int newNationRecno);
	void  overseer_migrate(int destTownRecno);
	int   caravan_in_firm() { return cur_x==-2; }

	void  update_loyalty();
	void  set_combat_level(int);
	void  inc_minor_combat_level(int);
	void  inc_minor_skill_level(int);
	void  set_rank(int rankId);
	virtual int	can_resign();
	void  resign(int remoteAction);
	void  embark(int vehicleRecno);
	void  reward(int rewardNationRecno);
	void  transform();
	void  group_transform(char remoteAction, short *selectedArray=NULL, short selectedCount=0);
	void  spy_change_nation(int nationRecno, char remoteAction, int groupDefect = 0);
	int   can_spy_change_nation();

	void  change_hit_points(float changePoints);
	void  change_loyalty(int loyaltyChange);

	int   think_betray();
	int   betray(int newNationRecno);

	int   can_stand_guard()  { return can_guard_flag & 1;}
	int   can_move_guard()  { return can_guard_flag & 2;}
	int   can_attack_guard()  { return can_guard_flag & 4;}

	int   firm_can_assign(short firmRecno);

	void  set_idle();
	void  set_ready();
	void  set_move();
	void  set_wait();
	void  set_attack();
	void  set_turn();
	void  set_ship_extra_move();
	void  set_die();

	int   write_file(File* filePtr);
	int   read_file(File* filePtr);

	virtual int write_derived_file(File* filePtr);
	virtual int read_derived_file(File* filePtr);
	virtual void fix_attack_info();         // set attack_info_array appropriately

	//-------------- multiplayer checking codes ---------------//
	virtual	uint8_t crc8();
	virtual	void	clear_ptr();
	virtual	void	init_crc(UnitCrc *c);

private:
	//------------------ idle functions -------------------//
	int            reactivate_idle_action();
	int            idle_detect_attack(int startLoc=0, int dimensionInput=0, char defenseMode=0); // detect target to attack
	int            idle_detect_choose_target(char defenseMode);
	void           idle_detect_helper_attack(short unitRecno);
	int            idle_detect_unit_checking(short targetRecno);
	int            idle_detect_firm_checking(short targetRecno);
	int            idle_detect_town_checking(short targetRecno);
	int            idle_detect_wall_checking(int targetXLoc, int targetYLoc);

	//------------ movement action -----------------//
	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);
	int   searching(int destX, int destY, int preserveAction, short searchMode, short miscNo, short numOfPath, short reuseMode, short pathReuseStatus);
	int   set_move_to_surround(int buildXLoc, int buildYLoc, int width, int height, int buildingType, int miscNo=0, int readyDist=0, short curSettleUnitNum=1);
	int   edit_path_to_surround(int x1, int y1, int x2, int y2, int readyDist);
	void  search_or_stop(int destX, int destY, int preserveAction=0, short searchMode=1, short miscNo=0);
	void  search_or_wait();
	//void   move_to_surround_s2(int destXLoc, int destYLoc); // for 2x2 unit only
	int   move_to_range_attack(int targetXLoc, int targetYLoc, short miscNo, short searchMode, short maxRange); // move to target for using range attack

	void  abort_searching(int reuseSetNext);
	void  set_search_tries(int tries);     // set parameters to limit the nodes used in searching
	void  reset_search_tries();            // reset parameters for using default nodes in searching

	//---------------- handle blocked action ------------------//
	void  move_to_my_loc(Unit* unitPtr);
	void  handle_blocked_move(Location* blockedLoc); // used to determine unit size and call other handle_blocked_move.. functions
	void  handle_blocked_move_s11(Unit* unitPtr);
	//void  handle_blocked_move_s12(Unit* unitPtr);
	//void  handle_blocked_move_s21(Unit* unitPtr);
	//void  handle_blocked_move_s22(Unit* unitPtr);
	//int blocked_move_new_handle();
	//void   set_path_to(int destXLoc, int destYLoc);
	void  handle_blocked_by_idle_unit(Unit *unitPtr);
	int   on_my_path(short checkXLoc, short checkYLoc);

	void  handle_blocked_wait(Unit* unitPtr);
	void  cycle_wait_shift_recno(Unit* curUnit, Unit* nextUnit);
	void  opposite_direction_blocked(short vecX, short vecY, short unitPtrVecX, short unitPtrVecY, Unit* unitPtr);

	void  handle_blocked_attack_unit(Unit *unitPtr, Unit *targetPtr);
	void  handle_blocked_attack_firm(Unit *unitPtr);
	void  handle_blocked_attack_town(Unit *unitPtr);
	void  handle_blocked_attack_wall(Unit *unitPtr);
	void  handle_blocked_same_target_attack(Unit* unitPtr, Unit* targetPtr);

	//====== support functions for process_attack_unit()
	void  target_move(Unit* targetUnit);
	void  attack_target(Unit* targetUnit);
	int   on_way_to_attack(Unit* targetUnit);
	int   detect_surround_target();
	int   update_attack_path_dist();
	void  set_attack_dir(short curX, short curY, short targetX, short targetY);

	//====== functions for attacking between UNIT_LAND, UNIT_SEA, UNIT_AIR
	int   move_try_to_range_attack(Unit* targetUnit);
	//void   move_to_range_attack(int targetXLoc, int targetYLoc, short miscNo, short searchMode, short maxRange); //---defined above
	int   can_attack_different_target_type();
	int   possible_place_for_range_attack(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, int maxRange);

	//====== functions for reactivating idle units and blocked units that are ordered to attack
	int   space_for_attack(int targetXLoc, int targetYLoc, char targetMobileType, int targetWidth, int targetHeight);
	int   space_around_target(int squareXLoc, int squareYLoc, int width, int height);
	int   space_around_target_ver2(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight);
	int   ship_surr_has_free_land(int targetXLoc, int targetYLoc, uint8_t regionId);
	int   free_space_for_range_attack(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, int targetMobileType, int maxRange);

	void  choose_best_attack_mode(int attackDistance, char targetMobileType=UNIT_LAND);
	void  unit_auto_guarding(Unit *attackUnit);
	void  set_unreachable_location(int xLoc, int yLoc);
	void  check_self_surround();
	int   can_attack_with(int i);               // 0 to attack_count-1
	int   can_attack_with(AttackInfo *attackInfo);
	void  get_hit_x_y(short *xPtr, short *yPtr);
	void  add_close_attack_effect();

	//-----------------  defense actions ---------------------//
	//=========== unit's defend mode generalized functions ============//
	int   in_any_defense_mode();
	void  general_defend_mode_detect_target(int checkDefendMode=0);
	int   general_defend_mode_process_attack_target();

	//========== unit's defense mode ==========//
	void  defense_back_camp(int targetXLoc, int targetYLoc);
	void  process_auto_defense_attack_target();
	void  process_auto_defense_detect_target();
	void  process_auto_defense_back_camp();
	int   defense_follow_target();

	//========== town unit's defend mode ==========//
	void  defend_town_attack_unit(short targetRecno);
	void  defend_town_detect_target();
	void  defend_town_back_town(short townRecno);
	void  process_defend_town_attack_target();
	void  process_defend_town_detect_target();
	void  process_defend_town_back_town();
	int   defend_town_follow_target();

	//========== monster unit's defend mode ==========//
	void  monster_defend_attack_unit(short targetRecno);
	void  monster_defend_attack_firm(int targetXLoc, int targetYLoc);
	void  monster_defend_attack_town(int targetXLoc, int targetYLoc);
	void  monster_defend_attack_wall(int targetXLoc, int targetYLoc);
	void  monster_defend_detect_target();
	void  monster_defend_back_firm(int targetXLoc, int targetYLoc);
	void  process_monster_defend_attack_target();
	void  process_monster_defend_detect_target();
	void  process_monster_defend_back_firm();
	int   monster_defend_follow_target();

	//---------- embark to ship and other ship functions ---------//
	int   ship_to_beach_path_edit(int& resultXLoc, int& resultYLoc, uint8_t regionId);
	void  ship_leave_beach(int shipOldXLoc, int shipOldYLoc);

	//---------------- other functions -----------------//
	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
	int   is_in_surrounding(int checkXLoc, int checkYLoc, int width, int targetXLoc, int targetYLoc, int targetWidth, int targetHeight);
	int   avail_node_enough_for_search(short x1, short y1, short x2, short y2);
	// int   firm_can_assign(short firmRecno);

protected:
	void  disp_main_menu(int);
	void  detect_main_menu();
	void  disp_build_menu(int);
	void  detect_build_menu();
	void  disp_button(int dispY1);
	void  detect_button();
	void  disp_build(int);
	void  detect_build();
	void  disp_settle(int);
	void  detect_settle();
	void  disp_unit_info(int dispY1, int refreshFlag);
	void  disp_basic_info(int dispY1, int refreshFlag);
	int   detect_basic_info();
	void  disp_spy_menu(int dispY1, int refreshFlag);
	void  detect_spy_menu(int dispY1);
	int   spy_menu_height();
	void  disp_hit_point(int dispY1);
	int   detect_select_hotkey();

	void  process_attack_unit();
	void  process_attack_firm();
	void  process_build_firm();
	void  process_attack_town();
	void  process_attack_wall();
	void  process_assign();
	void  process_burn();
	void  process_settle();
	void  process_assign_to_ship();
	void  process_ship_to_beach();
	void  process_rebel();
	void  process_go_cast_power();

	void  next_move();

	void  terminate_move();
	void  reset_path();

	void  king_die();
	void  general_die();
	void  pay_expense();
	void  process_recover();
};
#pragma pack()

//--------------------------------------------------------------------------------------------//

//------- Define class UnitArray ---------//

class UnitArray : public SpriteArray
{
public:
	short selected_recno;
	short selected_count;

	uint32_t cur_group_id;            // for Unit::unit_group_id
	uint32_t cur_team_id;             // for Unit::team_id

	short idle_blocked_unit_reset_count; // used to improve performance for searching related to attack

	short visible_unit_count;

	static short   selected_land_unit_count;
	static short   selected_sea_unit_count;
	static short   selected_air_unit_count;
	static short   *selected_land_unit_array;
	static short   *selected_sea_unit_array;
	static short   *selected_air_unit_array;

public:
	UnitArray(int);

	void  init();

	int   add_unit(int unitId, int nationRecno, int rankId=0, int unitLoyalty=0, int startXLoc= -1, int startYLoc= -1);
	Unit* create_unit(int unitId);
	int   unit_class_size(int);

	void  disappear_in_town(int unitRecno, int townRecno);
	void  disappear_in_firm(int unitRecno);
	void  die(int unitRecno);
	void	return_camp(int remoteAction, short* selectedUnitArray=NULL, int selectedCount=0);

	void  draw_dot();
	void	draw_profile();
	void  process();

	void  stop(short* selectedUnitArray, int selectedCount, char remoteAction);
	void  stop_all_war(short oldNationRecno);
	void  stop_war_between(short nationRecno1, short nationRecno2);
	void  stop_attack_unit(short unitRecno);
	void  stop_attack_firm(short firmRecno);
	void  stop_attack_town(short townRecno);

	//---------- move main functions -------------//
	void  move_to(int destX, int destY, int divided, short* selectedUnitArray, int selectedCount, char remoteAction);

	//------------- attack main functions ----------//
	// ###### patch begin Gilbert 5/8 ######//
	void  attack(int destX, int destY, int divided, short* selectedUnitArray, int selectedCount, char remoteAction, int unitRecno);
	// ###### patch end Gilbert 5/8 ######//
	void  attack_unit(int targetXLoc, int targetYLoc, short targetUnitRecno, short* selectedUnitArray, int selectedCount);
	void  attack_firm(int targetXLoc, int targetYLoc, short firmRecno, short* selectedUnitArray, int selectedCount);
	void  attack_town(int targetXLoc, int targetYLoc, short townRecno, short* selectedUnitArray, int selectedCount);
	void  attack_wall(int targetXLoc, int targetYLoc, short* selectedUnitArray, int selectedCount);

	//---------- other actions functions -----------//
	void  assign(int destX, int destY, int divided, char remoteAction, short* selectedUnitArray=NULL, int selectedCount=0);
	void  assign_to_camp(int destX, int destY, char remoteAction, short* selectedUnitArray=NULL, int selectedCount=0);
	void  settle(int destX, int destY, int divided, char remoteAction, short *selectedUnitArray=NULL, int selectedCount=0);
	// ##### patch begin Gilbert 5/8 ######//
	void  assign_to_ship(int shipXLoc, int shipYLoc, int divided, short* selectedArray, int selectedCount, char remoteAction, int shipRecno);
	// ##### patch end Gilbert 5/8 ######//
	void  ship_to_beach(int destX, int destY, int divided, short* selectedArray, int selectedCount, char remoteAction);
	void	add_way_point(int pointX, int pointY, short* selectedArray, int selectedCount, char remoteAction);

	//--------- unit filter function ----------//
	int   divide_attack_by_nation(short nationRecno, short *selectedArray, int selectedCount);

	int   write_file(File* filePtr);
	int   read_file(File* filePtr);

	#ifdef DYNARRAY_DEBUG_ELEMENT_ACCESS
		Unit* operator[](int recNo);
	#else
		Unit* operator[](int recNo)   { return (Unit*) get_ptr(recNo); }
	#endif

	int   is_deleted(int recNo);
	int   is_truly_deleted(int recNo);

	void  disp_next(int seekDir, int sameNation);

private:
	void  divide_array(int locX, int locY, short* selectedArray, int selectedCount, int excludeSelectedLocUnit=0);
	void  set_group_id(short* selectedArray, int selectedCount);

	//------------ move sub-functions --------------//
	void  move_to_now_with_filter(int destX, int destY, short* selectedUnitArray, int selectedCount);
	void  move_to_now(int destX, int destY, short* selectedUnitArray, int selectedCount);
	void  construct_sorted_array(short* selectedUnitArray, int selectedCount);
	void  determine_position_to_construct_table(int selectedCount, int destXLoc, int destYLoc, char mobileType);

	//-------------- attack sub-functions -----------//
	// ###### patch begin Gilbert 5/8 #######//
	void  attack_call(int destX, int destY, char mobileType, char targetMobileType, int divided, short* selectedUnitArray, int selectedCount, int targetUnitRecno);
	// ###### patch end Gilbert 5/8 #######//
	void  update_unreachable_table(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, char mobileType, int &analyseResult);
	char  get_target_surround_loc(int targetWidth, int targetHeight);
	char* get_target_x_offset(int targetWidth, int targetHeight, char curDir);
	char* get_target_y_offset(int targetWidth, int targetHeight, char curDir);

	void  arrange_units_in_group(int xLoc1, int yLoc1, int xLoc2, int yLoc2, short* selectedUnitArray, int selectedCount, uint32_t unitGroupId, int targetType);
	int   analyse_surround_location(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, char mobileType);
	void  check_nearby_location(int targetXLoc, int targetYLoc, char xOffset, char yOffset, int targetWidth, int targetHeight, char targetMobileType, int& analyzeResult);
	void  handle_attack_target_totally_blocked(int targetXLoc, int targetYLoc, short targetRecno, short *selectedUnitArray, short selectedCount, int targetType);

	//---------- other actions functions -----------//
	void  group_assign(int destX, int destY, short* selectedArray, int selectedCount);
	void  group_settle(int destX, int destY, short* selectedArray, int selectedCount);
};

extern UnitArray unit_array;
extern int unit_search_node_used;
extern int     unit_search_tries;        // the number of tries used in the current searching
extern char    unit_search_tries_flag;   // indicate num of tries is set, reset after searching
#ifdef DEBUG
extern int check_unit_dir1, check_unit_dir2;
#endif

#endif