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    : OTOWN.H
22 //Description : Header file of Object Town
23 
24 #ifndef __OTOWN_H
25 #define __OTOWN_H
26 
27 #ifndef __ODYNARRB_H
28 #include <ODYNARRB.h>
29 #endif
30 
31 #ifndef __OSKILL_H
32 #include <OSKILL.h>
33 #endif
34 
35 #ifndef __OFIRMID_H
36 #include <OFIRMID.h>
37 #endif
38 
39 #ifndef __ORAWRES_H
40 #include <ORAWRES.h>
41 #endif
42 
43 #ifndef __OTOWNRES_H
44 #include <OTOWNRES.h>
45 #endif
46 
47 //------- define constant --------//
48 
49 #define MAX_TOWN_GROWTH_POPULATION  60		// grow up to 60 persons in a town
50 #define MAX_TOWN_POPULATION  60		// MAX number of units in a town
51 
52 //-------- Define constant -----------//
53 
54 #define STD_TOWN_LOC_WIDTH       4
55 #define STD_TOWN_LOC_HEIGHT      4
56 
57 //--------- Define training cost and level --------//
58 
59 #define TRAIN_SKILL_COST				30
60 #define TRAIN_SKILL_LEVEL        	20
61 #define TOTAL_TRAIN_DAYS				 5		 // No. of days needed for training an unit
62 
63 #define MIN_RECRUIT_LOYALTY			   30 	// only when loyalty > this, the unit can be recruited
64 #define MIN_NATION_DEFEND_LOYALTY		50    // if the loyalty of the town people > this, they will defense against the attack
65 #define MIN_INDEPENDENT_DEFEND_LOYALTY 30
66 #define SURRENDER_LOYALTY				   29	   // when the loyalty of the town is <= this, and being attacked by a nation, the town will surrender
67 #define REBEL_LOYALTY					   29    // if loyalty <= REBEL_LOYALTY, the unit may rebel
68 
69 #define INDEPENDENT_LINK_RESISTANCE  50	 // only if the resistance of an independent town is lower than this, the town will enable its link with a foreign firm
70 
71 #define TAX_PER_PERSON           	  5	 // amount of tax can be collected from each person
72 #define COLLECT_TAX_LOYALTY_DECREASE 10	 // Reduce 10 loyalty points per tax collection
73 
74 #define TOWN_REWARD_PER_PERSON		   10
75 #define TOWN_REWARD_LOYALTY_INCREASE   10
76 
77 #define IND_TOWN_GRANT_PER_PERSON			   30		// independent town granting cost per person
78 #define IND_TOWN_GRANT_RESISTANCE_DECREASE   10		// resistance decrease per grant
79 
80 #define RECEIVED_HIT_PER_KILL			 (200/ATTACK_SLOW_DOWN)	 // no. of received hits will result in one death of town people
81 
82 #define MAX_TRAIN_QUEUE					10
83 
84 //-------- Define class Town ----------//
85 
86 class Unit;
87 #pragma pack(1)
88 class Town
89 {
90 public:
91 	enum { TOWN_NAME_LEN=20 };
92 
93 	short town_recno;
94 	short	town_name_id;
town_name()95 	char* town_name()			{ return town_res.get_name(town_name_id); }
96 
97 	short nation_recno;
98 	short rebel_recno;		// whether this town is controlled by a rebel
99 	char	race_id;
100 
101 	int	setup_date;			// the setup date of this town
102 
103 	char  ai_town;
104 	char	ai_link_checked; // AI check firm and town locatin by links, disable checking by setting this parameter to 1
105 
106 	char	independ_town_nation_relation; // each bit n is high representing this independent town will attack nation n.
107 	char	has_linked_own_camp;					 // whether the town has linked military camps of the same nation
108 	char	has_linked_enemy_camp;				 // whether the town has linked military camps of the same nation
109 
110 	char	is_base_town;		// whether this town is base town or not
111 
112 	short loc_x1, loc_y1, loc_x2, loc_y2;
113 	short abs_x1, abs_y1, abs_x2, abs_y2;
114 
loc_width()115 	short loc_width()    { return loc_x2-loc_x1+1; }
loc_height()116 	short loc_height()   { return loc_y2-loc_y1+1; }
117 
118 	short center_x;
119 	short center_y;
120 	uint8_t	region_id;
121 
122 	short layout_id;           // town layout id.
123 	short first_slot_id;       // the first slot id. of the layout
124 
125 	short slot_object_id_array[MAX_TOWN_LAYOUT_SLOT];  // the race id. of each slot building
126 
127 	//---------- game vars ----------//
128 
129 	short population;
130 	short jobless_population;
worker_population()131 	short worker_population()		{ return population-jobless_population; }
132 
133 	short	max_race_pop_array[MAX_RACE];			// the MAX population the current town layout supports
134 	short race_pop_array[MAX_RACE];     		// population of each race
135 	unsigned char race_pop_growth_array[MAX_RACE];		// population growth, when it reaches 100, there will be one more person in the town
136 	short jobless_race_pop_array[MAX_RACE];
137 	int   recruitable_race_pop(int raceId, int recruitSpy);
138 
139 	float race_loyalty_array[MAX_RACE];
140 	char  race_target_loyalty_array[MAX_RACE];
141 	short	race_spy_count_array[MAX_RACE];		  // no. of spies in each race
142 
143 	float race_resistance_array[MAX_RACE][MAX_NATION];
144 	char  race_target_resistance_array[MAX_RACE][MAX_NATION];
145 
146 	int   race_harmony(int raceId);
147 	int   majority_race();		// the race that has the majority of the population
148 
149 	int	average_loyalty();
150 	int	average_target_loyalty();
151 	int	average_resistance(int nationRecno);
152 	int	average_target_resistance(int nationRecno);
153 
154 	short	town_defender_count;			// no. of units currently defending this town
155 	int	last_being_attacked_date;
156 	float received_hit_count;		// no. of received hit by attackers, when this > RECEIVED_HIT_PER_KILL, a town people will be killed
157 
158 	char  train_queue_skill_array[MAX_TRAIN_QUEUE];	// it stores the skill id.
159 	char  train_queue_race_array[MAX_TRAIN_QUEUE];	// it stores the race id.
160 	char  train_queue_count;
161 	short	train_unit_recno;			// race id. of the unit the town is currently training, 0-if currently not training any
162 	int	train_unit_action_id;	// id. of the action to be assigned to this unit when it is finished training.
163 	uint32_t start_train_frame_no;
164 	short defend_target_recno; 	// used in defend mode, store recno of latest target atttacking this town
165 
166 	enum {TOWN_TRAIN_BATCH_COUNT = 8}; // Number of units enqueued when holding shift - ensure this is less than MAX_TRAIN_QUEUE
167 
168 	//-------- other vars ----------//
169 
170 	int   accumulated_collect_tax_penalty;
171 	int   accumulated_reward_penalty;
172 	int   accumulated_recruit_penalty;
173 	int   accumulated_enemy_grant_penalty;
174 
175 	int	last_rebel_date;
176 	short independent_unit_join_nation_min_rating;
177 
178 	short quality_of_life;
179 	void	update_quality_of_life();
180 
181 	//------- auto policy -------------//
182 
183 	short	auto_collect_tax_loyalty;		// auto collect tax if the loyalty reaches this level
184 	short	auto_grant_loyalty;				// auto grant if the loyalty drop below this level
185 
186 	//----------- AI vars ------------//
187 
188 	char	town_combat_level;						// combat level of the people in this town
189 	char	has_product_supply[MAX_PRODUCT];		// whether this town has the supply of these products
190 	char	no_neighbor_space;						// 1 if there is no space to build firms/towns next to this town
191 
192 	//------ inter-relationship -------//
193 
194 	short  linked_firm_count;
195 	short  linked_town_count;
196 
197 	short  linked_firm_array[MAX_LINKED_FIRM_TOWN];
198 	short  linked_town_array[MAX_LINKED_TOWN_TOWN];
199 
200 	char   linked_firm_enable_array[MAX_LINKED_FIRM_TOWN];
201 	char   linked_town_enable_array[MAX_LINKED_TOWN_TOWN];
202 
203 	int 	 closest_own_camp();
204 
205 	//========== NOTE: The following members are not loaded from/saved to file ==========//
206 	enum {SIZEOF_NONSAVED_ELEMENTS = sizeof(int)+sizeof(bool)};
207 
208 	//--------- town network ----------//
209 	int		town_network_recno;						// The recno of the town network this town belongs to. Note: this value can change between saving and loading.
210 	bool	town_network_pulsed;					// Used for pulsing the town network to check which parts are still connected. Must always be set to false, and can only be true during a pulse-operation
211 
212 	//------ static class member var ------//
213 
214 	static short  if_town_recno;
215 
216 public:
217 	Town();
218 
219 	void  init(int,int,int,int);
220 	void  deinit();
221 
222 	void  next_day();
223 	void  draw(int displayLayer=1);
224 	void  process_ai();
225 
226 	void  disp_info(int refreshFlag);
227 	void  detect_info();
228 	int	browse_selected_race_id();
229 
230 	void  assign_unit(int unitRecno);
231 	int   recruit(int withTraining, int raceId, char remoteAction);
232 	int  	recruit_dec_loyalty(int raceId, int decNow=1);
233 	void	cancel_train_unit();
234 	int  	form_new_nation();
235 
236 	int	can_recruit(int raceId);
237 	int	can_train(int raceId);
238 	bool   can_migrate(int destTownRecno, bool migrateNow=false, int raceId=0);		 // if not called by Town::migrate, don't set migrateNow to TRUE
239 	void	move_pop(Town* destTown, int raceId, int hasJob);
240 	int 	pick_random_race(int pickNonRecruitableAlso, int pickSpyFlag);
241 	int 	camp_influence(int unitRecno);
242 
243 	void  setup_link();
244 	void  release_link();
245 	void  release_firm_link(int);
246 	void  release_town_link(int);
247 	int	  linked_active_camp_count();
248 	int   can_toggle_firm_link(int firmRecno);
249 	void  update_camp_link();
250 
251 	void  init_pop(int raceId, int addPop, int loyalty, int hasJob=0, int firstInit=0);
252 	void  inc_pop(int raceId, int unitHasJob, int unitLoyalty);
253 	void  dec_pop(int raceId, int unitHasJob);
254 
255 	void  draw_selected();
256 	int   draw_detect_link_line(int);
257 	int   is_in_zoom_win();
258 
259 	int 	has_linked_camp(int nationRecno, int needOverseer);
260 
261 	void	auto_set_layout();
262 	void  set_nation(int nationRecno);
263 	void 	surrender(int toNationRecno);
264 
265 	void	set_hostile_nation(int nationRecno);
266 	void	reset_hostile_nation(int nationRecno);
267 	int	is_hostile_nation(int nationRecno);
268 
269 	int 	create_rebel_unit(int raceId, int isLeader);
270 	int   mobilize_town_people(int raceId, int decPop, int mobilizeSpy);
271 	int	mobilize_defender(int attackerNationRecno);
272 
273 	int	migrate_to(int destTownRecno, char remoteAction, int raceId=0, int count=1);
274 	void	collect_yearly_tax();
275 	void  collect_tax(char remoteAction);
276 	void  reward(char remoteAction);
277 	void  distribute_demand();
278 	void	being_attacked(int attackerUnitRecno, float attackDamage);
279 	void	clear_defense_mode();
280 	void	reduce_defender_count();
281 	void	kill_town_people(int raceId, int attackerUnitRecno=0);
282 
283 	int 	can_grant_to_non_own_town(int grantNationRecno);
284 	int 	grant_to_non_own_town(int grantNationRecno, int remoteAction);
285 
286 	void 	get_most_populated_race(int& mostRaceId1, int& mostRaceId2);
287 
288 	void  update_target_loyalty();
289 	void  update_target_resistance();
290 	void  update_loyalty();
291 	void  update_resistance();
292 	void	update_product_supply();
293 	void	change_loyalty(int raceId, float loyaltyChange);
294 	void	change_resistance(int raceId, int nationRecno, float loyaltyChange);
295 
296 	void  toggle_firm_link(int linkId, int toggleFlag, char remoteAction, int setBoth=0);
297 	void  toggle_town_link(int linkId, int toggleFlag, char remoteAction, int setBoth=0);
298 
299 	void	auto_defense(short targetRecno);
300 	int	has_player_spy();
301 	void 	verify_slot_object_id_array();
302 
303 	void 	set_auto_collect_tax_loyalty(int loyaltyLevel);
304 	void 	set_auto_grant_loyalty(int loyaltyLevel);
305 	void 	disp_auto_loyalty();
306 
307 	void	add_queue(char skillId, char raceId, int amount = 1);
308 	void	remove_queue(char skillId, int amount = 1);
309 
310 	int   write_file(File*);
311 	int   read_file(File*);
312 
313 	//-------- ai functions ---------//
314 
315 	void	think_collect_tax();
316 	void	think_reward();
317 	int	think_build_firm(int firmId, int maxFirm);
318 	int	think_build_market();
319 	int	think_build_camp();
320 	int 	think_build_research();
321 	int 	think_build_war_factory();
322 	int 	think_build_base();
323 	int 	think_build_inn();
324 	int 	think_ai_migrate();
325 	int 	think_ai_migrate_to_town();
326 	void	think_defense();
327 	int 	think_split_town();
328 	void	think_move_between_town();
329 	int 	think_attack_nearby_enemy();
330 	int 	think_attack_linked_enemy();
331 	void	think_capture_linked_firm();
332 	int 	think_capture_enemy_town();
333 	int   think_scout();
334 
335 	void 	update_base_town_status();
336 	int	new_base_town_status();
337 
338 	int 	think_counter_spy();
339 	int 	needed_anti_spy_level();
340 
341 	int 	think_spying_town();
342 	int 	think_spying_town_assign_to(int raceId);
343 
344 	int	should_ai_migrate();
345 	int   detect_enemy(int);
346 
347 	int	protection_needed();			// an index from 0 to 100 indicating the military protection needed for this town
348 	int	protection_available();
349 
350 	int 	ai_build_neighbor_firm(int firmId, int firmRaceId=0);
351 	int 	ai_settle_new(int raceId);
352 
353 	//-------- independent town ai functions ---------//
354 
355 	void	think_independent_town();
356 	void 	think_independent_set_link();
357 	int  	think_independent_form_new_nation();
358 	int  	think_independent_unit_join_nation();
359 	int  	independent_unit_join_nation(int raceId, int toNationRecno);
360 
361 	//--------- function for cheat key ----------//
362 	int	get_selected_race();
363 
364 	//-------------- multiplayer checking codes ---------------//
365 	uint8_t crc8();
366 	void	clear_ptr();
367 
368 	//-------------------------------//
369 
370 private:
371 	void  set_world_matrix();
372 	void  restore_world_matrix();
373 	void 	establish_contact_with_player();
374 
375 	void 	process_food();
376 	void	process_auto();
377 	void  process_train();
378 	void	finish_train(Unit*);
379 	void  population_grow();
380 	void	process_queue();
381 	void  think_migrate();
382 	int 	think_migrate_one(Town* targetTown, int raceId, int townDistance);
383 	void  migrate(int raceId, int destTownZoneRecno, int newLoyalty);
384 	int	unjob_town_people(int raceId, int unjobOverseer, int killOverseer=0);
385 
386 	int	think_layout_id();
387 
388 	void  draw_flag(int,int);
389 	void  draw_farm(int,int,int);
390 
391 	void  disp_basic_info(int refreshFlag);
392 	void	disp_train_info(int refreshFlag);
393 
394 	void  disp_main_menu(int refreshFlag);
395 	int   detect_main_menu();
396 	void 	disp_debug_resistance(int refreshFlag);
397 
398 	void  disp_train_menu(int refreshFlag);
399 	int   detect_train_menu();
400 
401 	void  disp_auto_menu(int modeCollectTax);
402 	int   detect_auto_menu(int modeCollectTax);
403 
404 	void  disp_spy_menu(int refreshFlag);
405 	int   detect_spy_menu();
406 
407 	void  think_rebel();
408 	int	think_surrender();
409 };
410 #pragma pack()
411 
412 //-------- Begin of class TownArray ------------//
413 
414 class TownArray : public DynArrayB
415 {
416 public:
417 	int   selected_recno;      // the firm current being selected
418 	int	race_wander_pop_array[MAX_RACE];		// no. of wandering people of each race. They are people for setting up independent towns later
419 
420 public:
421    TownArray();
422    ~TownArray();
423 
424 	void  init();
425    void  deinit();
426 
427    int   add_town(int nationRecno, int raceId, int xLoc, int yLoc);
428 	void  del_town(int townRecno);
429 	Town* create_town();
430 
431    void  draw();
432    void  draw_dot();
433 	void	draw_profile();
434 
435 	void	process();
436 
437 	int	independent_town_resistance();
438 	void	think_new_independent_town();
439 
440 	int 	think_town_loc(int maxTries, int& xLoc, int& yLoc);
441 	int   find_nearest_town(int xLoc, int yLoc, int nationRecno=0);
442 
443 	int   settle(int unitRecno, int xLoc, int yLoc);
444 	void  distribute_demand();
445 
446 	void	stop_attack_nation(short nationRecno);
447 
448    int   write_file(File*);
449    int   read_file(File*);
450 
451 	int   is_deleted(int recNo);
452 
453    #ifdef DYNARRAY_DEBUG_ELEMENT_ACCESS
454 		Town* operator[](int recNo);
455 	#else
456 		Town* operator[](int recNo)  { return (Town*) get_ptr(recNo); }
457 	#endif
458 
459 	void  disp_next(int seekDir, int sameNation);
460 };
461 
462 extern TownArray town_array;
463 
464 //---------------------------------------------------//
465 
466 #endif
467