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 //cFilename : OTOWN.CPP
22 //Description : Object Town
23
24 #include <string.h>
25 #include <ALL.h>
26 #include <OVGA.h>
27 #include <OWORLD.h>
28 #include <OSYS.h>
29 #include <OIMGRES.h>
30 #include <ONEWS.h>
31 #include <OCONFIG.h>
32 #include <OFONT.h>
33 #include <OINFO.h>
34 #include <OPLANT.h>
35 #include <ODATE.h>
36 #include <OSPY.h>
37 #include <OCONFIG.h>
38 #include <OF_MARK.h>
39 #include <OF_CAMP.h>
40 #include <OUNIT.h>
41 #include <OTERRAIN.h>
42 #include <OREBEL.h>
43 #include <OSPRTRES.h>
44 #include <ORACERES.h>
45 #include <ONATION.h>
46 #include <OREMOTE.h>
47 #include <OTOWN.h>
48 #include <OTownNetwork.h>
49 #include <ONEWS.h>
50 #include <OANLINE.h>
51 // ##### begin Gilbert 9/10 ######//
52 #include <OSE.h>
53 // ##### end Gilbert 9/10 ######//
54 #include <OSERES.h>
55 #include <OLOG.h>
56 #include <ConfigAdv.h>
57
58 static char random_race();
59
60
61 //--------- Begin of function Town::Town ----------//
62 //
Town()63 Town::Town()
64 {
65 memset( this, 0, sizeof(Town) );
66 }
67 //---------- End of function Town::Town ----------//
68
69
70 //--------- Begin of function Town::init ----------//
71 //
72 // <int> nationRecno - the nation recno
73 // <int> raceId - the race of the majority of the town poulation
74 // <int> xLoc, yLoc - location of the town
75 //
init(int nationRecno,int raceId,int xLoc,int yLoc)76 void Town::init(int nationRecno, int raceId, int xLoc, int yLoc)
77 {
78 nation_recno = nationRecno;
79 race_id = raceId;
80
81 err_when( raceId<1 || raceId>MAX_RACE );
82
83 //---- set the town section's absolute positions on the map ----//
84
85 loc_x1 = xLoc;
86 loc_y1 = yLoc;
87 loc_x2 = loc_x1 + STD_TOWN_LOC_WIDTH - 1;
88 loc_y2 = loc_y1 + STD_TOWN_LOC_HEIGHT - 1;
89
90 abs_x1 = xLoc * ZOOM_LOC_WIDTH;
91 abs_y1 = yLoc * ZOOM_LOC_HEIGHT;
92 abs_x2 = abs_x1 + STD_TOWN_LOC_WIDTH * ZOOM_LOC_WIDTH - 1;
93 abs_y2 = abs_y1 + STD_TOWN_LOC_HEIGHT * ZOOM_LOC_HEIGHT - 1;
94
95 center_x = (loc_x1+loc_x2)/2;
96 center_y = (loc_y1+loc_y2)/2;
97
98 region_id = world.get_region_id( center_x, center_y );
99
100 ai_town = !nation_recno || nation_array[nation_recno]->nation_type == NATION_AI; // nation_recno==0 for independent towns
101 ai_link_checked = 1; // check the linked towns and firms connected only if ai_link_checked==0
102
103 independent_unit_join_nation_min_rating = 100 + misc.random(150); // the minimum rating a nation must have in order for an independent unit to join it
104
105 setup_date = info.game_date;
106
107 //-------- init resistance ------------//
108
109 if( nationRecno==0 )
110 {
111 for( int i=0 ; i<MAX_RACE ; i++ )
112 {
113 for( int j=0 ; j<MAX_NATION ; j++ )
114 {
115 race_resistance_array[i][j] = (float) 60 + misc.random(40);
116 race_target_resistance_array[i][j] = -1;
117 }
118 }
119
120 //--- some independent towns have higher than normal combat level for its defender ---//
121
122 switch( config.independent_town_resistance )
123 {
124 case OPTION_LOW:
125 town_combat_level = CITIZEN_COMBAT_LEVEL;
126 break;
127
128 case OPTION_MODERATE:
129 town_combat_level = 10 + misc.random(20);
130 break;
131
132 case OPTION_HIGH:
133 town_combat_level = 10 + misc.random(30);
134 if( misc.random(5)==0 )
135 town_combat_level += misc.random(30);
136 break;
137
138 default:
139 err_here();
140 }
141 }
142
143 //-------------------------------------//
144
145 town_name_id = town_res.get_new_name_id(raceId);
146
147 set_world_matrix();
148
149 setup_link();
150
151 //-------- if this is an AI town ------//
152
153 if( ai_town && nation_recno )
154 {
155 nation_array[nation_recno]->add_town_info(town_recno);
156
157 update_base_town_status();
158 }
159
160 //------ set national auto policy -----//
161
162 if( nation_recno )
163 {
164 Nation* nationPtr = nation_array[nation_recno];
165
166 set_auto_collect_tax_loyalty( nationPtr->auto_collect_tax_loyalty );
167 set_auto_grant_loyalty( nationPtr->auto_grant_loyalty );
168 }
169
170 //--------- setup town network ---------//
171
172 town_network_pulsed = false;
173 town_network_recno = town_network_array.town_created(town_recno, nation_recno, linked_town_array, linked_town_count);
174 }
175 //--------- End of function Town::init ----------//
176
177
178 //--------- Begin of function Town::deinit ----------//
179 //
deinit()180 void Town::deinit()
181 {
182 if( !town_recno )
183 return;
184
185 //--------- remove from town network ---------//
186
187 town_network_array.town_destroyed(town_recno);
188
189
190 clear_defense_mode();
191
192 //------- if it's an AI town --------//
193
194 if( ai_town && nation_recno )
195 nation_array[nation_recno]->del_town_info(town_recno);
196
197 //------ if this town is the nation's larget town, reset it ----//
198
199 if( nation_recno &&
200 nation_array[nation_recno]->largest_town_recno == town_recno )
201 {
202 nation_array[nation_recno]->largest_town_recno = 0;
203 }
204
205 //-----------------------------------//
206
207 restore_world_matrix();
208
209 release_link();
210
211 //-- if there is a unit being trained when the town vanishes --//
212
213 if(train_unit_recno)
214 unit_array.disappear_in_town(train_unit_recno, town_recno);
215
216 //------- if the current town is the selected -----//
217
218 if( town_array.selected_recno == town_recno )
219 {
220 town_array.selected_recno = 0;
221 info.disp();
222 }
223
224 //------- reset parameters ---------//
225
226 town_recno = 0;
227 town_network_recno = 0;
228 }
229 //--------- End of function Town::deinit ----------//
230
231
232 //------- Begin of function Town::set_world_matrix --------//
233 //
234 // Set the cargo id of current town section on the world matrix
235 //
set_world_matrix()236 void Town::set_world_matrix()
237 {
238 //--- if a nation set up a town in a location that the player has explored, contact between the nation and the player is established ---//
239
240 int xLoc, yLoc;
241 Location* locPtr;
242
243 for( yLoc=loc_y1 ; yLoc<=loc_y2 ; yLoc++ )
244 {
245 for( xLoc=loc_x1 ; xLoc<=loc_x2 ; xLoc++ )
246 {
247 locPtr = world.get_loc(xLoc, yLoc);
248
249 if(!locPtr->cargo_recno) // skip the location where the settle unit is standing
250 locPtr->set_town(town_recno);
251 }
252 }
253
254 //--- if a nation set up a town in a location that the player has explored, contact between the nation and the player is established ---//
255
256 establish_contact_with_player();
257
258 //---- set this town's influence on the map ----//
259
260 if( nation_recno )
261 world.set_power(loc_x1, loc_y1, loc_x2, loc_y2, nation_recno);
262
263 //------------ reveal new land ----------//
264
265 if( nation_recno == nation_array.player_recno ||
266 ( nation_recno && nation_array[nation_recno]->is_allied_with_player ) )
267 {
268 world.unveil( loc_x1, loc_y1, loc_x2, loc_y2 );
269 world.visit( loc_x1, loc_y1, loc_x2, loc_y2, EXPLORE_RANGE-1 );
270 }
271
272 //---- if the newly built firm is visual in the zoom window, redraw the zoom buffer ----//
273
274 if( is_in_zoom_win() )
275 sys.zoom_need_redraw = 1; // set the flag on so it will be redrawn in the next frame
276 }
277 //-------- End of function Town::set_world_matrix --------//
278
279
280 //------- Begin of function Town::establish_contact_with_player --------//
281 //
282 // See if the town's location is an explored area, establish contact
283 // with the player.
284 //
establish_contact_with_player()285 void Town::establish_contact_with_player()
286 {
287 if( !nation_recno )
288 return;
289
290 //--- if a nation set up a town in a location that the player has explored, contact between the nation and the player is established ---//
291
292 int xLoc, yLoc;
293 Location* locPtr;
294
295 for( yLoc=loc_y1 ; yLoc<=loc_y2 ; yLoc++ )
296 {
297 for( xLoc=loc_x1 ; xLoc<=loc_x2 ; xLoc++ )
298 {
299 locPtr = world.get_loc(xLoc, yLoc);
300
301 if( locPtr->explored() && nation_array.player_recno )
302 {
303 NationRelation *relation = (~nation_array)->get_relation(nation_recno);
304
305 if( !remote.is_enable() )
306 {
307 relation->has_contact = 1;
308 }
309 else
310 {
311 if( !relation->contact_msg_flag && !relation->has_contact )
312 {
313 // packet structure : <player nation> <explored nation>
314 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_NATION_CONTACT, 2*sizeof(short));
315 *shortPtr = nation_array.player_recno;
316 shortPtr[1] = nation_recno;
317 relation->contact_msg_flag = 1;
318 }
319 }
320 }
321 }
322 }
323 }
324 //-------- End of function Town::establish_contact_with_player --------//
325
326
327 //--------- Begin of function Town::restore_world_matrix --------//
328 //
329 // When the town section is destroyed, restore the original land id
330 //
restore_world_matrix()331 void Town::restore_world_matrix()
332 {
333 int xLoc, yLoc;
334
335 for( yLoc=loc_y1 ; yLoc<=loc_y2 ; yLoc++ )
336 {
337 for( xLoc=loc_x1 ; xLoc<=loc_x2 ; xLoc++ )
338 {
339 world.get_loc(xLoc,yLoc)->remove_town();
340 }
341 }
342
343 //---- restore this town's influence on the map ----//
344
345 if( nation_recno )
346 world.restore_power(loc_x1, loc_y1, loc_x2, loc_y2, town_recno, 0);
347
348 //---- if the newly built firm is visual in the zoom window, redraw the zoom buffer ----//
349
350 if( is_in_zoom_win() )
351 sys.zoom_need_redraw = 1;
352 }
353 //----------- End of function Town::restore_world_matrix --------//
354
355
356 //---------- Begin of function Town::next_day --------//
357 //
next_day()358 void Town::next_day()
359 {
360 err_when( population>MAX_TOWN_POPULATION );
361 err_when( town_recno<1 );
362 err_when( town_recno>town_array.size() );
363
364 int townRecno = town_recno;
365
366 //------ update quality_of_life --------//
367
368 update_quality_of_life();
369
370 //---------- update population ----------//
371
372 #if defined(DEBUG) && defined(ENABLE_LOG)
373 String logStr;
374 logStr = "begin Town::next_day, town_recno = ";
375 logStr += townRecno;
376 logStr += " nation=";
377 logStr += nation_recno;
378 LOG_MSG(logStr);
379 #endif
380
381 if( info.game_date%30 == town_recno%30 )
382 {
383 LOG_MSG(" population_grow");
384 population_grow();
385 LOG_MSG(misc.get_random_seed());
386 }
387
388 err_when(population>MAX_TOWN_POPULATION);
389
390 //------- update link status to camps ------//
391
392 LOG_MSG(" update_camp_link");
393 update_camp_link();
394 LOG_MSG(misc.get_random_seed());
395
396 //------ update target loyalty/resistance -------//
397
398 if( info.game_date%15 == town_recno%15 )
399 {
400 if( nation_recno )
401 {
402 LOG_MSG(" update_target_loyalty");
403 update_target_loyalty();
404 }
405 else
406 {
407 LOG_MSG(" update_target_resistance");
408 update_target_resistance(); // update resistance for independent towns
409 }
410 LOG_MSG(misc.get_random_seed());
411 }
412
413 //------ update loyalty/resistance -------//
414
415 if( info.game_date%5 == town_recno%5 )
416 {
417 if( nation_recno )
418 {
419 LOG_MSG(" update_target_loyalty");
420 update_loyalty();
421 }
422 else
423 {
424 LOG_MSG(" update_target_resistance");
425 update_resistance();
426 }
427 LOG_MSG(misc.get_random_seed());
428
429 if( town_array.is_deleted(townRecno) )
430 return;
431 }
432
433 //------ think town people migration -------//
434
435 LOG_MSG(" think_migrate");
436 think_migrate();
437 LOG_MSG(misc.get_random_seed());
438
439 if( town_array.is_deleted(townRecno) )
440 return;
441
442 //-------- think about rebel -----//
443
444 if( nation_recno && info.game_date%15 == town_recno%15 )
445 {
446 LOG_MSG(" think_rebel");
447 think_rebel();
448 LOG_MSG(misc.get_random_seed() );
449
450 if( town_array.is_deleted(townRecno) )
451 return;
452 }
453
454 //-------- think about surrender -----//
455
456 if( nation_recno &&
457 ( info.game_date%15==town_recno%15 || average_loyalty()==0 ) )
458 {
459 LOG_MSG(" think_surrender");
460 think_surrender(); // for nation town only, independent town surrender is handled in update_resistance()
461 LOG_MSG(misc.get_random_seed() );
462
463 if( town_array.is_deleted(townRecno) )
464 return;
465 }
466
467 //------- process training -------//
468
469 //### begin alex 6/9 ###//
470 /*if( nation_recno && train_unit_recno )
471 {
472 process_train();
473
474 if( town_array.is_deleted(townRecno) ) // when the last peasant in the town is trained, the town disappear
475 return;
476 }*/
477 if(nation_recno)
478 {
479 if(train_unit_recno)
480 {
481 LOG_MSG(" process_train");
482 process_train();
483 LOG_MSG(misc.get_random_seed() );
484 }
485 else
486 {
487 LOG_MSG(" process_queue");
488 process_queue();
489 LOG_MSG(misc.get_random_seed() );
490 }
491
492 if( town_array.is_deleted(townRecno) ) // when the last peasant in the town is trained, the town disappear
493 return;
494 }
495 //#### end alex 6/9 ####//
496
497 //-------- process food ---------//
498
499 if( nation_recno )
500 {
501 LOG_MSG(" process_food");
502 process_food();
503 LOG_MSG(misc.get_random_seed());
504
505 if( town_array.is_deleted(townRecno) )
506 return;
507 }
508
509 //------ auto collect tax and auto grant -------//
510
511 if( nation_recno )
512 {
513 LOG_MSG(" process_auto");
514 process_auto();
515 LOG_MSG(misc.get_random_seed() );
516
517 if( town_array.is_deleted(townRecno) )
518 return;
519 }
520
521 //------ collect yearly tax -------//
522
523 if( nation_recno && info.game_month==1 && info.game_day==1 )
524 {
525 collect_yearly_tax();
526 }
527
528 //------ catching spies -------//
529
530 LOG_MSG(" process_auto");
531
532 if( info.game_date%30 == town_recno%30 )
533 spy_array.catch_spy(SPY_TOWN, town_recno);
534
535 LOG_MSG(misc.get_random_seed() );
536
537 if( town_array.is_deleted(townRecno) )
538 return;
539
540 //-------- update visibility ---------//
541
542 if( nation_recno == nation_array.player_recno ||
543 (nation_recno && nation_array[nation_recno]->is_allied_with_player) )
544 {
545 world.visit( loc_x1, loc_y1, loc_x2, loc_y2, EXPLORE_RANGE-1 );
546 }
547
548 //--- recheck no_neighbor_space after a period, there may be new space available now ---//
549
550 if( no_neighbor_space && info.game_date%180 == town_recno%180 )
551 {
552 LOG_MSG("begin finding neighor space");
553 short buildXLoc, buildYLoc;
554
555 //--- for independent town, since we can't call find_best_firm_loc(), we just set no_neighbor_space to 0 every 6 months, if it still has no space, then no_neighbor_space will be set 1 again. ---//
556
557 if( nation_recno==0 || nation_array[nation_recno]->find_best_firm_loc(FIRM_INN, loc_x1, loc_y1, buildXLoc, buildYLoc) ) // whether it's FIRM_INN or not really doesn't matter, just any firm type will do
558 no_neighbor_space = 0;
559
560 LOG_MSG(misc.get_random_seed());
561 }
562
563 //------ decrease penalties -----//
564
565 if( accumulated_collect_tax_penalty > 0 )
566 accumulated_collect_tax_penalty--;
567
568 if( accumulated_reward_penalty > 0 )
569 accumulated_reward_penalty--;
570
571 if( accumulated_recruit_penalty > 0 )
572 accumulated_recruit_penalty--;
573
574 if( accumulated_enemy_grant_penalty > 0 )
575 accumulated_enemy_grant_penalty--;
576
577 //------------------------------------------------------------//
578 // check for population for each town
579 //------------------------------------------------------------//
580
581 //err_when( town_array.is_deleted(townRecno) );
582 if( town_array.is_deleted(townRecno) )
583 return;
584
585 #ifdef DEBUG
586 Firm *firmPtr;
587 int i, j;
588 short pop[MAX_RACE];
589
590 memset(pop, 0, sizeof(short)*MAX_RACE);
591 for(i=linked_firm_count-1; i>=0; i--)
592 {
593 err_when(!linked_firm_array[i] || firm_array.is_deleted(linked_firm_array[i]));
594 firmPtr = firm_array[linked_firm_array[i]];
595
596 if(firmPtr->overseer_recno)
597 {
598 if(firmPtr->overseer_town_recno==town_recno)
599 {
600 Unit *unitPtr = unit_array[firmPtr->overseer_recno];
601 pop[unitPtr->race_id-1]++;
602 }
603 }
604
605 if(firmPtr->worker_count)
606 {
607 for(j=firmPtr->worker_count-1; j>=0; j--)
608 {
609 if((firmPtr->worker_array[j]).town_recno==town_recno)
610 pop[(firmPtr->worker_array[j]).race_id-1]++;
611 }
612 }
613 }
614
615 for(i=0; i<MAX_RACE; i++)
616 err_when(pop[i]+jobless_race_pop_array[i] != race_pop_array[i]);
617 #endif
618
619 //------------------------------------------------------------//
620 // check the spy count
621 //------------------------------------------------------------//
622
623 #ifdef DEBUG
624 short raceSpyCountArray[MAX_RACE];
625
626 memset( raceSpyCountArray, 0, sizeof(raceSpyCountArray) );
627
628 for( i=spy_array.size() ; i>0 ; i-- )
629 {
630 if( spy_array.is_deleted(i) )
631 continue;
632
633 Spy* spyPtr = spy_array[i];
634
635 if( spyPtr->spy_place == SPY_TOWN && spyPtr->spy_place_para == town_recno )
636 raceSpyCountArray[spyPtr->race_id-1]++;
637 }
638
639 for( i=0 ; i<MAX_RACE ; i++ )
640 {
641 err_when( race_spy_count_array[i] != raceSpyCountArray[i] );
642
643 err_when( race_spy_count_array[i] > jobless_race_pop_array[i] );
644 }
645
646 town_res.get_name(town_name_id);
647 #endif
648 }
649 //----------- End of function Town::next_day ---------//
650
651
652 //---------- Begin of function Town::process_food --------//
653 //
process_food()654 void Town::process_food()
655 {
656 //--------- Peasants produce food ---------//
657
658 nation_array[nation_recno]->add_food( (float) jobless_population * PEASANT_FOOD_YEAR_PRODUCTION / 365 );
659
660 //---------- People consume food ----------//
661
662 nation_array[nation_recno]->consume_food( (float) population * PERSON_FOOD_YEAR_CONSUMPTION / 365 );
663 }
664 //----------- End of function Town::process_food ---------//
665
666
667 //---------- Begin of function Town::process_auto --------//
668 //
process_auto()669 void Town::process_auto()
670 {
671 if( !has_linked_own_camp ) // can only collect or grant when there is a linked camp of its own.
672 return;
673
674 Nation* nationPtr = nation_array[nation_recno];
675
676 //----- auto collect tax -----//
677
678 if( auto_collect_tax_loyalty > 0 )
679 {
680 if( accumulated_collect_tax_penalty == 0 &&
681 average_loyalty() >= auto_collect_tax_loyalty )
682 {
683 collect_tax(COMMAND_AI);
684 }
685 }
686
687 //---------- auto grant -----------//
688
689 if( auto_grant_loyalty > 0 )
690 {
691 if( accumulated_reward_penalty == 0 &&
692 average_loyalty() < auto_grant_loyalty && nationPtr->cash > 0 )
693 {
694 reward(COMMAND_AI);
695 }
696 }
697 }
698 //----------- End of function Town::process_auto ---------//
699
700
701 //---------- Begin of function Town::set_nation --------//
702 //
703 // Set the nation of this town.
704 //
705 // Possible changes:
706 //
707 // independent town -> nation town
708 // nation A's town -> nation B's town (surrender)
709 //
set_nation(int newNationRecno)710 void Town::set_nation(int newNationRecno)
711 {
712 if( nation_recno == newNationRecno )
713 return;
714
715 //--------- update town network (pre-step) ---------//
716 town_network_array.town_pre_changing_nation(town_recno);
717
718
719 clear_defense_mode();
720
721 //------------- stop all actions to attack this town ------------//
722 unit_array.stop_attack_town(town_recno);
723 rebel_array.stop_attack_town(town_recno);
724
725 //--------- update AI town info ---------//
726
727 if( ai_town && nation_recno )
728 {
729 nation_array[nation_recno]->del_town_info(town_recno);
730 }
731
732 //--------- reset vars ---------//
733
734 is_base_town = 0;
735 town_defender_count = 0; // reset defender count
736
737 //----- set power region of the new nation ------//
738
739 world.restore_power(loc_x1, loc_y1, loc_x2, loc_y2, town_recno, 0); // restore power of the old nation
740 world.set_power(loc_x1, loc_y1, loc_x2, loc_y2, newNationRecno); // set power of the new nation
741
742 //--- update the cloaked_nation_recno of all spies in the firm ---//
743
744 spy_array.change_cloaked_nation(SPY_TOWN, town_recno, nation_recno, newNationRecno); // check the cloaked nation recno of all spies in the firm
745
746 //--------- set nation_recno --------//
747
748 int oldNationRecno = nation_recno;
749 nation_recno = newNationRecno;
750
751 if( nation_recno ) // reset rebel_recno if the town is then ruled by a nation
752 {
753 if( rebel_recno )
754 {
755 Rebel* rebelPtr = rebel_array[rebel_recno];
756
757 err_when( rebelPtr->mobile_rebel_count > 0 ); // change nation shouldn't happen if mobile_rebel_count > 0
758
759 rebel_array.del_rebel(rebel_recno); // delete the rebel group
760 rebel_recno = 0;
761 }
762 }
763
764 //--------- update ai_town ----------//
765
766 ai_town = 0;
767
768 if( nation_recno==0 ) // independent town
769 {
770 ai_town = 1;
771 }
772 else if( nation_array[nation_recno]->nation_type==NATION_AI )
773 {
774 ai_town = 1;
775 nation_array[nation_recno]->add_town_info(town_recno);
776 }
777
778 //------ set the loyalty of the town people ------//
779
780 int i, nationRaceId;
781
782 if( nation_recno )
783 nationRaceId = nation_array[nation_recno]->race_id;
784
785 for( i=0 ; i<MAX_RACE ; i++ )
786 {
787 if( nation_recno == 0 ) // independent town set up by rebel
788 race_loyalty_array[i] = (float) 80; // this affect the no. of defender if you attack the independent town
789 else
790 {
791 if( nationRaceId == i+1 )
792 race_loyalty_array[i] = (float) 40; // loyalty is higher if the ruler and the people are the same race
793 else
794 race_loyalty_array[i] = (float) 30;
795 }
796 }
797
798 //------- reset town_combat_level -------//
799
800 town_combat_level = 0;
801
802 //------ reset accumulated penalty ------//
803
804 accumulated_collect_tax_penalty = 0;
805 accumulated_reward_penalty = 0;
806 accumulated_enemy_grant_penalty = 0;
807 accumulated_recruit_penalty = 0;
808
809 //---- if there is unit being trained currently, change its nation ---//
810
811 if( train_unit_recno )
812 unit_array[train_unit_recno]->change_nation(newNationRecno);
813
814 //-------- update loyalty ---------//
815
816 update_target_loyalty();
817
818 //--- if a nation set up a town in a location that the player has explored, contact between the nation and the player is established ---//
819
820 establish_contact_with_player();
821
822 //----- if an AI nation took over this town, see if the AI can capture all firms linked to this town ----//
823
824 if( nation_recno && nation_array[nation_recno]->is_ai() )
825 think_capture_linked_firm();
826
827 //--- when a town change nation, call the AI function of call linked firms ---//
828
829 Firm* firmPtr;
830
831 for( i=0 ; i<linked_firm_count ; i++ )
832 {
833 firmPtr = firm_array[ linked_firm_array[i] ];
834
835 if( firmPtr->firm_ai ) // tell linked firms that this town has changed nation
836 firmPtr->think_linked_town_change_nation(town_recno, oldNationRecno, newNationRecno);
837 }
838
839 //------ set national auto policy -----//
840
841 if( nation_recno )
842 {
843 Nation* nationPtr = nation_array[nation_recno];
844
845 set_auto_collect_tax_loyalty( nationPtr->auto_collect_tax_loyalty );
846 set_auto_grant_loyalty( nationPtr->auto_grant_loyalty );
847 }
848
849 //---- reset the action mode of all spies in this town ----//
850
851 spy_array.set_action_mode( SPY_TOWN, town_recno, SPY_IDLE ); // we need to reset it. e.g. when we have captured an enemy town, SPY_SOW_DISSENT action must be reset to SPY_IDLE
852
853 //--------- update town network (post-step) ---------//
854 town_network_array.town_post_changing_nation(town_recno, newNationRecno);
855
856 //-------- refresh display ----------//
857
858 if( town_array.selected_recno == town_recno )
859 info.disp();
860 }
861 //----------- End of function Town::set_nation ---------//
862
863
864 //------ Begin of function Town::set_hostile_nation -------//
set_hostile_nation(int nationRecno)865 void Town::set_hostile_nation(int nationRecno)
866 {
867 if(nationRecno==0)
868 return;
869
870 err_when(nationRecno>7); // only 8 bits
871 independ_town_nation_relation |= (0x1 << nationRecno);
872 }
873 //----------- End of function Town::set_hostile_nation ---------//
874
875
876 //------ Begin of function Town::reset_hostile_nation -------//
reset_hostile_nation(int nationRecno)877 void Town::reset_hostile_nation(int nationRecno)
878 {
879 if(nationRecno==0)
880 return;
881
882 err_when(nationRecno>7); // only 8 bits
883 independ_town_nation_relation &= ~(0x1 << nationRecno);
884 }
885 //----------- End of function Town::reset_hostile_nation ---------//
886
887
888 //------ Begin of function Town::is_hostile_nation -------//
889 // return 1 for hostile nation
890 // return 0 otherwise
891 //
is_hostile_nation(int nationRecno)892 int Town::is_hostile_nation(int nationRecno)
893 {
894 if(nationRecno==0)
895 return 0;
896
897 err_when(nationRecno>7); // only 8 bits
898 return (independ_town_nation_relation & (0x1 << nationRecno));
899 }
900 //----------- End of function Town::is_hostile_nation ---------//
901
902
903 //--------- Begin of function Town::init_pop ----------//
904 //
905 // Initialize population of the town.
906 //
907 // <int> raceId - the id. of the race to add.
908 // <int> addPop - the no. of people to add.
909 // <int> addLoyalty - loyalty of the people to add to the town
910 // [int] hasJob - whether the units will have jobs or not after moving into this town
911 // (default: 0)
912 // [int] firstInit - first initialization at the beginning of the game
913 // (default: 0)
914 //
init_pop(int raceId,int addPop,int addLoyalty,int hasJob,int firstInit)915 void Town::init_pop(int raceId, int addPop, int addLoyalty, int hasJob, int firstInit)
916 {
917 if(population>=MAX_TOWN_POPULATION)
918 return;
919
920 int addPopulation = MIN(addPop, MAX_TOWN_POPULATION-population);
921
922 //-------- update population ---------//
923
924 race_pop_array[raceId-1] += addPopulation;
925 population += addPopulation;
926
927 err_when( race_pop_array[raceId-1] > MAX_TOWN_POPULATION );
928 err_when( population > MAX_TOWN_POPULATION );
929
930 if( !hasJob )
931 {
932 jobless_population += addPopulation;
933 jobless_race_pop_array[raceId-1] += addPopulation;
934 }
935
936 err_when( jobless_race_pop_array[raceId-1] > MAX_TOWN_POPULATION );
937 err_when( jobless_population > MAX_TOWN_POPULATION );
938
939 //------- update loyalty --------//
940
941 err_when( race_loyalty_array[raceId-1]<0 || race_loyalty_array[raceId-1]>100 );
942
943 if( firstInit ) // first initialization at the beginning of the game
944 {
945 if( nation_recno )
946 {
947 race_loyalty_array[raceId-1] = (float) addLoyalty;
948 race_target_loyalty_array[raceId-1] = addLoyalty;
949 }
950 else
951 {
952 for( int j=0 ; j<MAX_NATION ; j++) // reset resistance for non-existing races
953 {
954 race_resistance_array[raceId-1][j] = (float) addLoyalty;
955 race_target_resistance_array[raceId-1][j] = addLoyalty;
956 }
957 }
958 }
959 else
960 {
961 if( nation_recno )
962 {
963 race_loyalty_array[raceId-1] =
964 ( race_loyalty_array[raceId-1] * (race_pop_array[raceId-1]-addPopulation)
965 + (float) addLoyalty * addPopulation ) / race_pop_array[raceId-1];
966
967 race_target_loyalty_array[raceId-1] = (char) race_loyalty_array[raceId-1];
968 }
969 else
970 {
971 for( int j=0 ; j<MAX_NATION ; j++) // reset resistance for non-existing races
972 {
973 race_resistance_array[raceId-1][j] =
974 ( race_resistance_array[raceId-1][j] * (race_pop_array[raceId-1]-addPopulation)
975 + (float) addLoyalty * addPopulation ) / race_pop_array[raceId-1];
976
977 race_target_resistance_array[raceId-1][j] = (char) race_resistance_array[raceId-1][j];
978 }
979 }
980 }
981
982 err_when( addLoyalty<0 || addLoyalty>100 );
983 err_when( race_loyalty_array[raceId-1]<0 || race_loyalty_array[raceId-1]>100 );
984 err_when( race_target_loyalty_array[raceId-1]<0 || race_target_loyalty_array[raceId-1]>100 );
985
986 //---------- update town parameters ----------//
987
988 town_array.distribute_demand();
989
990 if( nation_recno )
991 update_loyalty();
992 else
993 update_resistance();
994 }
995 //--------- End of function Town::init_pop ----------//
996
997
998 //--------- Begin of function Town::inc_pop -------//
999 //
1000 // <int> raceId - the race id. of the population
1001 // <int> unitHasJob - whether the unit will get a job after moving into the town
1002 // <int> unitLoyalty - loyalty of the unit.
1003 //
inc_pop(int raceId,int unitHasJob,int unitLoyalty)1004 void Town::inc_pop(int raceId, int unitHasJob, int unitLoyalty)
1005 {
1006 err_when( unitLoyalty < 0 );
1007
1008 //---------- increase population ----------//
1009
1010 population++;
1011 race_pop_array[raceId-1]++;
1012
1013 err_when( race_pop_array[raceId-1] > MAX_TOWN_POPULATION );
1014 err_when( population > MAX_TOWN_POPULATION );
1015
1016 if( !unitHasJob )
1017 {
1018 jobless_population++;
1019 jobless_race_pop_array[raceId-1]++;
1020
1021 err_when( jobless_race_pop_array[raceId-1] > MAX_TOWN_POPULATION );
1022 err_when( jobless_population > MAX_TOWN_POPULATION );
1023 }
1024
1025 //------- update loyalty --------//
1026
1027 if( nation_recno ) // if the unit has an unit
1028 {
1029 err_when( race_loyalty_array[raceId-1]<0 || race_loyalty_array[raceId-1]>100 );
1030
1031 race_loyalty_array[raceId-1] =
1032 ( race_loyalty_array[raceId-1] * (race_pop_array[raceId-1]-1)
1033 + (float) unitLoyalty ) / race_pop_array[raceId-1];
1034
1035 err_when( unitLoyalty<0 || unitLoyalty>100 );
1036 err_when( race_loyalty_array[raceId-1]<0 || race_loyalty_array[raceId-1]>100 );
1037 }
1038
1039 //-- if the race's population exceeds the capacity of the town layout --//
1040
1041 if( race_pop_array[raceId-1] > max_race_pop_array[raceId-1] )
1042 {
1043 auto_set_layout();
1044 }
1045 }
1046 //---------- End of function Town::inc_pop --------//
1047
1048
1049 //--------- Begin of function Town::dec_pop -------//
1050 //
1051 // <int> raceId - the race id. of the population
1052 // <int> unitHasJob - whether the unit current has a job or not
1053 //
dec_pop(int raceId,int unitHasJob)1054 void Town::dec_pop(int raceId, int unitHasJob)
1055 {
1056 population--;
1057 race_pop_array[raceId-1]--;
1058
1059 err_when( population < 0 );
1060 err_when( race_pop_array[raceId-1] < 0 );
1061
1062 if( !unitHasJob )
1063 {
1064 jobless_population--;
1065 jobless_race_pop_array[raceId-1]--;
1066
1067 err_when( jobless_population < 0 );
1068 err_when( jobless_race_pop_array[raceId-1] < 0 );
1069 }
1070
1071 err_when( race_pop_array[raceId-1] < jobless_race_pop_array[raceId-1] );
1072
1073 //------- if all the population are gone --------//
1074
1075 if( population==0 ) // it will be deleted in TownArray::process()
1076 {
1077 if( nation_recno == nation_array.player_recno )
1078 news_array.town_abandoned(town_recno);
1079
1080 deinit();
1081 return;
1082 }
1083
1084 //-- if the race's population drops to too low, change the town layout --//
1085
1086 if( race_pop_array[raceId-1] <= max_race_pop_array[raceId-1]-POPULATION_PER_HOUSE )
1087 {
1088 auto_set_layout();
1089 }
1090 }
1091 //---------- End of function Town::dec_pop --------//
1092
1093
1094 //--------- Begin of function Town::population_grow --------//
1095 //
population_grow()1096 void Town::population_grow()
1097 {
1098 if( town_defender_count )
1099 return;
1100
1101 if( population >= MAX_TOWN_GROWTH_POPULATION || population >= MAX_TOWN_POPULATION )
1102 return;
1103
1104 //-------- population growth by birth ---------//
1105
1106 #ifdef DEBUG
1107 short debugPopulation = population;
1108 char debugRaceGrowth[MAX_RACE] = {0};
1109 #endif
1110
1111 int i, autoSetFlag=0;
1112
1113 for( i=0 ; i<MAX_RACE ; i++ )
1114 {
1115 //-- the population growth in an independent town is slower than in a nation town ---//
1116
1117 if( nation_recno )
1118 race_pop_growth_array[i] += race_pop_array[i] * (100+quality_of_life) / 100;
1119 else
1120 race_pop_growth_array[i] += race_pop_array[i];
1121
1122 int loopCount=0;
1123
1124 while( race_pop_growth_array[i] > 100 )
1125 {
1126 err_when( loopCount++ > 100 );
1127
1128 race_pop_growth_array[i] -= 100;
1129
1130 race_pop_array[i]++;
1131 jobless_race_pop_array[i]++;
1132
1133 population++;
1134 jobless_population++;
1135
1136 err_when( race_pop_array[i] > MAX_TOWN_POPULATION );
1137 err_when( jobless_race_pop_array[i] > MAX_TOWN_POPULATION );
1138
1139 err_when( population > MAX_TOWN_POPULATION );
1140 err_when( jobless_population > MAX_TOWN_POPULATION );
1141
1142 #ifdef DEBUG
1143 debugRaceGrowth[i]++;
1144 #endif
1145
1146 //-- if the race's population grows too high, change the town layout --//
1147
1148 if( race_pop_array[i] > max_race_pop_array[i] )
1149 {
1150 autoSetFlag = 1;
1151 }
1152
1153 if(population>=MAX_TOWN_POPULATION)
1154 break;
1155 }
1156
1157 if(population>=MAX_TOWN_POPULATION)
1158 break;
1159 }
1160
1161 if( autoSetFlag )
1162 auto_set_layout();
1163 }
1164 //----------- End of function Town::population_grow --------//
1165
1166
1167 //-------- Begin of function Town::race_harmony --------//
1168 //
1169 // Return a harmony rating of the given race.
1170 //
1171 // <int> raceId - id. of the race
1172 //
race_harmony(int raceId)1173 int Town::race_harmony(int raceId)
1174 {
1175 if( population==0 )
1176 return 0;
1177 else
1178 return 100 * race_pop_array[raceId-1] / population;
1179 }
1180 //--------- End of function Town::race_harmony ---------//
1181
1182
1183 //---------- Begin of function Town::update_target_loyalty --------//
1184 //
1185 // Update loyalty for nation towns.
1186 //
update_target_loyalty()1187 void Town::update_target_loyalty()
1188 {
1189 if( !nation_recno ) // return if independent towns
1190 return;
1191
1192 //----- update loyalty of individual races -------//
1193 //
1194 // Loyalty is determined by:
1195 //
1196 // - residential harmony
1197 // - whether the people are racially homogeneous to the king
1198 // - the nation's reputation
1199 // - command bases overseeing the town.
1200 // - quality of life
1201 // - employment rate
1202 //
1203 // Quality of life is determined by:
1204 //
1205 // - The provision of goods to the villagers. A more constant
1206 // supply and a bigger variety of goods give to high quality of life.
1207 //
1208 //------------------------------------------------//
1209
1210 //------- set target loyalty of each race --------//
1211
1212 Nation* nationPtr = nation_array[nation_recno];
1213 int i, targetLoyalty;
1214 int nationRaceId = nationPtr->race_id;
1215
1216 for( i=0 ; i<MAX_RACE ; i++ )
1217 {
1218 if( race_pop_array[i] == 0 )
1219 continue;
1220
1221 //------- calculate the target loyalty -------//
1222
1223 targetLoyalty = race_harmony(i+1)/3 + // 0 to 33
1224 (int)nationPtr->reputation/4; // -25 to +25
1225
1226 //---- employment help increase loyalty ----//
1227
1228 targetLoyalty += 30 - 30 * jobless_race_pop_array[i] / race_pop_array[i]; // +0 to +30
1229
1230 if( race_res.is_same_race(i+1, nationRaceId) )
1231 targetLoyalty += 10;
1232
1233 if( targetLoyalty < 0 ) // targetLoyalty can be negative if there are hostile races conflicts
1234 targetLoyalty = 0;
1235
1236 if( targetLoyalty > 100 )
1237 targetLoyalty = 100;
1238
1239 //----------------------------------------//
1240
1241 race_target_loyalty_array[i] = targetLoyalty;
1242
1243 err_when( targetLoyalty<0 || targetLoyalty>100 );
1244 }
1245
1246 //----- process command bases that have influence on this town -----//
1247
1248 int baseInfluence, thisInfluence, commanderRaceId;
1249 Firm* firmPtr;
1250 Nation *baseNationPtr;
1251 Unit* unitPtr;
1252
1253 for( i=0 ; i<linked_firm_count ; i++ )
1254 {
1255 if( linked_firm_enable_array[i] != LINK_EE )
1256 continue;
1257
1258 firmPtr = firm_array[linked_firm_array[i]];
1259
1260 if( firmPtr->firm_id!=FIRM_CAMP || !firmPtr->overseer_recno )
1261 continue;
1262
1263 //-------- get nation and commander info ------------//
1264
1265 unitPtr = unit_array[firmPtr->overseer_recno];
1266 commanderRaceId = unitPtr->race_id;
1267
1268 baseNationPtr = nation_array[firmPtr->nation_recno];
1269
1270 //------ if this race is the overseer's race -------//
1271
1272 baseInfluence = unitPtr->skill.get_skill(SKILL_LEADING)/3; // 0 to 33
1273
1274 if( unitPtr->rank_id == RANK_KING ) // 20 points bonus for king
1275 baseInfluence += 20;
1276
1277 //------------ update all race -----------//
1278
1279 for( int j=0 ; j<MAX_RACE ; j++ )
1280 {
1281 if( !race_pop_array[j] )
1282 continue;
1283
1284 //---- if the overseer's race is the same as this race ---//
1285
1286 thisInfluence = baseInfluence;
1287
1288 if( unitPtr->race_id == j+1 )
1289 thisInfluence += 8;
1290
1291 //--- if the overseer's nation's race is the same as this race ---//
1292
1293 if( baseNationPtr->race_id == j+1 )
1294 thisInfluence += 8;
1295
1296 //------------------------------------------//
1297
1298 if( firmPtr->nation_recno == nation_recno ) // if the command base belongs to the same nation
1299 {
1300 targetLoyalty = race_target_loyalty_array[j] + thisInfluence;
1301 race_target_loyalty_array[j] = MIN(100, targetLoyalty);
1302 }
1303 else if( unitPtr->race_id == j+1 ) // for enemy camps, only decrease same race peasants
1304 {
1305 targetLoyalty = race_target_loyalty_array[j] - thisInfluence;
1306 race_target_loyalty_array[j] = MAX(0, targetLoyalty);
1307 }
1308 }
1309 }
1310
1311 //------- apply quality of life -------//
1312
1313 int qolContribution = config_adv.town_loyalty_qol ?
1314 (quality_of_life-50)/3 : // -17 to +17
1315 0; // off
1316 for( i=0 ; i<MAX_RACE ; i++ )
1317 {
1318 if( race_pop_array[i] == 0 )
1319 continue;
1320
1321 targetLoyalty = race_target_loyalty_array[i];
1322
1323 // Quality of life only applies to the part above 30 loyalty
1324 if (targetLoyalty > 30)
1325 {
1326 targetLoyalty = MAX(30, targetLoyalty + qolContribution);
1327 race_target_loyalty_array[i] = MIN(100, targetLoyalty);
1328 }
1329 }
1330
1331 //------- update link status to linked enemy camps -------//
1332
1333 for( i=0 ; i<linked_firm_count ; i++ )
1334 {
1335 firmPtr = firm_array[linked_firm_array[i]];
1336
1337 if( firmPtr->firm_id != FIRM_CAMP )
1338 continue;
1339
1340 //------------------------------------------//
1341 // If this town is linked to a own camp,
1342 // disable all links to enemy camps, otherwise
1343 // enable all links to enemy camps.
1344 //------------------------------------------//
1345
1346 if( firmPtr->nation_recno != nation_recno )
1347 toggle_firm_link( i+1, !has_linked_own_camp, COMMAND_AUTO );
1348 }
1349 }
1350 //----------- End of function Town::update_target_loyalty ---------//
1351
1352
1353 //------ Begin of function Town::update_loyalty -----//
1354 //
1355 // Update loyalty and resistance towards the target.
1356 //
update_loyalty()1357 void Town::update_loyalty()
1358 {
1359 if( !nation_recno )
1360 return;
1361
1362 //------------- update loyalty -------------//
1363
1364 float targetLoyalty, loyaltyInc, loyaltyDec;
1365
1366 for(int i=0; i<MAX_RACE; i++)
1367 {
1368 if( race_pop_array[i] == 0 )
1369 continue;
1370
1371 targetLoyalty = (float) race_target_loyalty_array[i];
1372
1373 if(race_loyalty_array[i] < targetLoyalty)
1374 {
1375 //--- if this town is linked to enemy camps, but no own camps, no increase in loyalty, only decrease ---//
1376
1377 if( !has_linked_own_camp && has_linked_enemy_camp )
1378 continue;
1379
1380 //-------------------------------------//
1381
1382 loyaltyInc = (targetLoyalty-race_loyalty_array[i]) / 30;
1383
1384 change_loyalty( i+1, MAX(loyaltyInc, (float)0.5) );
1385 }
1386 else if(race_loyalty_array[i] > targetLoyalty)
1387 {
1388 loyaltyDec = (race_loyalty_array[i]-targetLoyalty) / 30;
1389
1390 change_loyalty( i+1, -MAX(loyaltyDec, (float)0.5) );
1391 }
1392 }
1393 }
1394 //------- End of function Town::update_loyalty ------//
1395
1396
1397 //------ Begin of function Town::change_loyalty -----//
1398 //
1399 // <int> raceId - id. of the race to be changed in loyalty.
1400 // <float> loyaltyChange - the amount of change in loyalty.
1401 //
change_loyalty(int raceId,float loyaltyChange)1402 void Town::change_loyalty(int raceId, float loyaltyChange)
1403 {
1404 float newLoyalty = race_loyalty_array[raceId-1] + loyaltyChange;
1405
1406 newLoyalty = MIN( 100, newLoyalty );
1407 newLoyalty = MAX( 0, newLoyalty );
1408
1409 race_loyalty_array[raceId-1] = newLoyalty;
1410 }
1411 //------- End of function Town::change_loyalty ------//
1412
1413
1414 //------ Begin of function Town::change_resistance -----//
1415 //
1416 // <int> raceId - id. of the race to be changed in loyalty.
1417 // <int> nationRecno - recno of the nation which the resistance is towards
1418 // <float> resistanceChange - the amount of change in resistance.
1419 //
change_resistance(int raceId,int nationRecno,float resistanceChange)1420 void Town::change_resistance(int raceId, int nationRecno, float resistanceChange)
1421 {
1422 err_when( raceId < 1 || raceId > MAX_RACE );
1423 err_when( nation_array.is_deleted(nationRecno) );
1424
1425 float newResistance = race_resistance_array[raceId-1][nationRecno-1] + resistanceChange;
1426
1427 newResistance = MIN( 100, newResistance );
1428 newResistance = MAX( 0, newResistance );
1429
1430 race_resistance_array[raceId-1][nationRecno-1] = newResistance;
1431 }
1432 //------- End of function Town::change_resistance ------//
1433
1434
1435 //------ Begin of function Town::update_target_resistance ------//
1436 //
1437 // Influence from a command base to a town (simplied version)
1438 // ----------------------------------------------------------
1439 // -Reputation of the nation
1440 // -Race of the general and the king (whether its race is the same as the town people's race)
1441 // -Leadership of the general
1442 //
1443 // If the conqueror's race id is the same as the town people's race id.
1444 // Influence = reputation/2
1445 // else
1446 // Influence = reputation/4
1447 //
1448 // If the general's race is the same as the town people's race,
1449 // Influence += general leadership/2
1450 // else
1451 // Influence += general leadership/4
1452 //
update_target_resistance()1453 void Town::update_target_resistance()
1454 {
1455 int i, j;
1456 Firm* firmPtr;
1457 Unit* unitPtr;
1458
1459 if( population==0 || linked_firm_count==0 )
1460 return;
1461
1462 for( i=0 ; i<MAX_RACE ; i++ )
1463 {
1464 for( j=0 ; j<MAX_NATION ; j++ )
1465 {
1466 race_target_resistance_array[i][j] = -1; // -1 means influence is not present
1467 }
1468 }
1469
1470 //---- if this town is controlled by rebels, no decrease in resistance ----//
1471
1472 if( rebel_recno )
1473 return;
1474
1475 //----- count the command base that has influence on this town -----//
1476
1477 int curValue, newValue;
1478
1479 for( i=0 ; i<linked_firm_count ; i++ )
1480 {
1481 if( linked_firm_enable_array[i] != LINK_EE )
1482 continue;
1483
1484 firmPtr = firm_array[linked_firm_array[i]];
1485
1486 if( firmPtr->firm_id!=FIRM_CAMP || !firmPtr->overseer_recno )
1487 continue;
1488
1489 //-------- get nation and commander info ------------//
1490
1491 unitPtr = unit_array[firmPtr->overseer_recno];
1492
1493 curValue = race_target_resistance_array[unitPtr->race_id-1][unitPtr->nation_recno-1];
1494 newValue = 100-camp_influence(firmPtr->overseer_recno);
1495
1496 err_when( newValue < 0 );
1497
1498 if( curValue == -1 || newValue < curValue ) // need to do this comparsion as there may be more than one command bases of the same nation linked to this town, we use the one with the most influence.
1499 race_target_resistance_array[unitPtr->race_id-1][unitPtr->nation_recno-1] = newValue;
1500 }
1501 }
1502 //------- End of function Town::update_target_resistance ------//
1503
1504
1505 //------ Begin of function Town::camp_influence ------//
1506 //
1507 // Return a specific military camp's influence on this town.
1508 //
1509 // The influence is calculated based on :
1510 // - the leadership of the commander
1511 // - whether the leader is racially homogenous to this town.
1512 // - whether the king is racially homogenous to this town.
1513 // - the reputation of the nation
1514 //
1515 // <int> unitRecno - unit recno of the commander in the military camp.
1516 //
1517 // return: <int> influence index (0-100)
1518 //
camp_influence(int unitRecno)1519 int Town::camp_influence(int unitRecno)
1520 {
1521 Unit* unitPtr = unit_array[unitRecno];
1522 Nation* nationPtr = nation_array[unitPtr->nation_recno]; // nation of the unit
1523
1524 int thisInfluence = unitPtr->skill.get_skill(SKILL_LEADING)*2/3; // 66% of the leadership
1525
1526 if( race_res.is_same_race(nationPtr->race_id, unitPtr->race_id) )
1527 thisInfluence += thisInfluence/3; // 33% bonus if the king's race is also the same as the general
1528
1529 thisInfluence += (int) nationPtr->reputation/2;;
1530
1531 thisInfluence = MIN(100, thisInfluence);
1532
1533 return thisInfluence;
1534 }
1535 //------- End of function Town::camp_influence ------//
1536
1537
1538 //------ Begin of function Town::update_resistance -----//
1539 //
1540 // Update loyalty and resistance towards the target.
1541 //
update_resistance()1542 void Town::update_resistance()
1543 {
1544 //------------- update resistance ----------------//
1545
1546 int i, j, maxNation = nation_array.size();
1547 char zeroResistance[MAX_NATION];
1548 float targetResistance;
1549
1550 memset( zeroResistance, 1, MAX_NATION );
1551
1552 for(i=0; i<MAX_RACE; i++)
1553 {
1554 if( race_pop_array[i]==0 )
1555 {
1556 for(j=0; j<maxNation; j++) // reset resistance for non-existing races
1557 race_resistance_array[i][j] = (float) 0;
1558
1559 continue;
1560 }
1561
1562 for(j=0; j<maxNation; j++)
1563 {
1564 if( nation_array.is_deleted(j+1) )
1565 continue;
1566
1567 if( race_target_resistance_array[i][j] >= 0 )
1568 {
1569 targetResistance = (float) race_target_resistance_array[i][j];
1570
1571 if(race_resistance_array[i][j] > targetResistance) // only decrease, no increase for resistance
1572 {
1573 float decValue = (race_resistance_array[i][j]-targetResistance) / 30;
1574
1575 race_resistance_array[i][j] -= MAX(1, decValue);
1576
1577 if(race_resistance_array[i][j] < targetResistance) // avoid resistance oscillate between taregtLoyalty-1 and taregtLoyalty+1
1578 race_resistance_array[i][j] = (float)targetResistance;
1579 }
1580 }
1581
1582 if( race_resistance_array[i][j] >= (float) 1 ) // also values between consider 0 and 1 as zero as they are displayed as 0 in the interface
1583 zeroResistance[j] = 0;
1584 }
1585 }
1586
1587 //--- if the town is zero resistance towards any nation, convert to that nation ---//
1588
1589 for(j=0; j<maxNation; j++)
1590 {
1591 if( nation_array.is_deleted(j+1) )
1592 continue;
1593
1594 if( zeroResistance[j] )
1595 {
1596 surrender(j+1);
1597 break;
1598 }
1599 }
1600 }
1601 //------- End of function Town::update_resistance ------//
1602
1603
1604 //---------- Begin of function Town::collect_yearly_tax --------//
1605 //
1606 // Collect yearly tax from villagers - this does not decrease their
1607 // loyalty.
1608 //
collect_yearly_tax()1609 void Town::collect_yearly_tax()
1610 {
1611 nation_array[nation_recno]->add_income(INCOME_TAX, (float)population * TAX_PER_PERSON );
1612 }
1613 //----------- End of function Town::collect_yearly_tax ---------//
1614
1615
1616 //---------- Begin of function Town::collect_tax --------//
1617 //
1618 // Collect tax from this town.
1619 //
collect_tax(char remoteAction)1620 void Town::collect_tax(char remoteAction)
1621 {
1622 if( !has_linked_own_camp )
1623 return;
1624
1625 //------------------------------------------//
1626
1627 if( !remoteAction && remote.is_enable() )
1628 {
1629 // packet structure : <town recno> <race id>
1630 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_COLLECT_TAX, sizeof(short));
1631 shortPtr[0] = town_recno;
1632 return;
1633 }
1634
1635 //----- calculate the loyalty decrease amount ------//
1636 //
1637 // If you reward too frequently, the negative effect
1638 // on loyalty will get larger.
1639 //
1640 //--------------------------------------------------//
1641
1642 int loyaltyDecrease = COLLECT_TAX_LOYALTY_DECREASE + accumulated_collect_tax_penalty/5;
1643
1644 loyaltyDecrease = MIN(loyaltyDecrease, COLLECT_TAX_LOYALTY_DECREASE+10);
1645
1646 accumulated_collect_tax_penalty += 10;
1647
1648 //------ decrease the loyalty of the town people ------//
1649
1650 // ##### patch begin Gilbert 5/8 ######//
1651 // for( int i=0 ; i<MAX_RACE ; i++ )
1652 // change_loyalty( i+1, (float) -loyaltyDecrease );
1653 //----------- increase cash ------------//
1654 // nation_array[nation_recno]->add_income(INCOME_TAX, (float)population * TAX_PER_PERSON );
1655
1656 // ------ cash increase depend on loyalty drop --------//
1657 float taxCollected = 0.0f;
1658 for( int i = 0; i < MAX_RACE; i++ )
1659 {
1660 float beforeLoyalty = race_loyalty_array[i];
1661 change_loyalty( i+1, (float) -loyaltyDecrease );
1662 taxCollected += (beforeLoyalty - race_loyalty_array[i]) * race_pop_array[i] * TAX_PER_PERSON / loyaltyDecrease;
1663 }
1664
1665 //----------- increase cash ------------//
1666
1667 nation_array[nation_recno]->add_income(INCOME_TAX, taxCollected );
1668
1669 // ##### patch end Gilbert 5/8 ######//
1670
1671 //------------ think rebel -------------//
1672
1673 think_rebel();
1674 }
1675 //----------- End of function Town::collect_tax ---------//
1676
1677
1678 //---------- Begin of function Town::reward --------//
1679 //
1680 // Reward cash to the peasants.
1681 //
reward(char remoteAction)1682 void Town::reward(char remoteAction)
1683 {
1684 if( !has_linked_own_camp )
1685 return;
1686
1687 //------------------------------------------//
1688
1689 if( !remoteAction && remote.is_enable() )
1690 {
1691 // packet structure : <town recno> <race id>
1692 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_REWARD, sizeof(short));
1693 shortPtr[0] = town_recno;
1694 return;
1695 }
1696
1697 //----- calculate the loyalty increase amount ------//
1698 //
1699 // If you reward too frequently, the effect of the
1700 // granting will be diminished.
1701 //
1702 //--------------------------------------------------//
1703
1704 int loyaltyIncrease = TOWN_REWARD_LOYALTY_INCREASE - accumulated_reward_penalty/5;
1705
1706 loyaltyIncrease = MAX(3, loyaltyIncrease);
1707
1708 accumulated_reward_penalty += 10;
1709
1710 //------ increase the loyalty of the town people ------//
1711
1712 for( int i=0 ; i<MAX_RACE ; i++ )
1713 change_loyalty( i+1, (float) loyaltyIncrease );
1714
1715 //----------- decrease cash ------------//
1716
1717 nation_array[nation_recno]->add_expense(EXPENSE_GRANT_OWN_TOWN, (float)population * TOWN_REWARD_PER_PERSON );
1718 }
1719 //----------- End of function Town::reward ---------//
1720
1721
1722 //------- Begin of function Town::think_surrender ---------//
1723 //
1724 // Think about surrendering to a nation with camps linked to
1725 // this town.
1726 //
think_surrender()1727 int Town::think_surrender()
1728 {
1729 if( !nation_recno ) // if it's an independent town
1730 return 0;
1731
1732 //--- only surrender when there is no own camps, but has enemy camps linked to this town ---//
1733
1734 if( has_linked_own_camp || !has_linked_enemy_camp )
1735 return 0;
1736
1737 //--- surrender if 2/3 of the population think about surrender ---//
1738
1739 int i, discontentedCount=0;
1740
1741 for( i=0 ; i<MAX_RACE ; i++ )
1742 {
1743 if( race_pop_array[i] <= race_spy_count_array[i] ) // spies do not rebel together with the rebellion
1744 continue;
1745
1746 if( race_loyalty_array[i] <= SURRENDER_LOYALTY )
1747 discontentedCount += race_pop_array[i];
1748 }
1749
1750 if( discontentedCount < population * 2 / 3 )
1751 return 0;
1752
1753 //-------- think about surrender to which nation ------//
1754
1755 int curRating, bestRating=average_loyalty(), bestNationRecno=0;
1756 Firm* firmPtr;
1757
1758 for( i=0 ; i<linked_firm_count ; i++ )
1759 {
1760 firmPtr = firm_array[linked_firm_array[i]];
1761
1762 //---- if this is an enemy camp ----//
1763
1764 if( firmPtr->firm_id == FIRM_CAMP &&
1765 firmPtr->nation_recno != nation_recno &&
1766 firmPtr->nation_recno &&
1767 firmPtr->overseer_recno )
1768 {
1769 curRating = camp_influence(firmPtr->overseer_recno); // see camp_influence() for details on how the rating is calculated
1770
1771 if( curRating > bestRating )
1772 {
1773 bestRating = curRating;
1774 bestNationRecno = firmPtr->nation_recno;
1775 }
1776 }
1777 }
1778
1779 //------------------------------------//
1780
1781 if( bestNationRecno )
1782 {
1783 surrender( bestNationRecno );
1784 return 1;
1785 }
1786 else
1787 return 0;
1788 }
1789 //------- End of function Town::think_surrender ---------//
1790
1791
1792 //------- Begin of function Town::surrender ---------//
1793 //
1794 // This town surrenders to another nation.
1795 //
1796 // <int> toNationRecno - the recno of the nation this town surrenders to.
1797 //
surrender(int toNationRecno)1798 void Town::surrender(int toNationRecno)
1799 {
1800 err_when( !toNationRecno );
1801
1802 //--- if this is a rebel town and the mobile rebel count is > 0, don't surrender (this function can be called by update_resistance() when resistance drops to zero ---//
1803
1804 if( rebel_recno )
1805 {
1806 Rebel* rebelPtr = rebel_array[rebel_recno];
1807
1808 if( rebelPtr->mobile_rebel_count > 0 )
1809 return;
1810 }
1811
1812 //----------------------------------------//
1813
1814 if( nation_recno == nation_array.player_recno ||
1815 toNationRecno == nation_array.player_recno )
1816 {
1817 news_array.town_surrendered(town_recno, toNationRecno);
1818 // ##### begin Gilbert 9/10 ######//
1819 // sound effect
1820 if( toNationRecno == nation_array.player_recno )
1821 {
1822 se_ctrl.immediate_sound("GET_TOWN");
1823 }
1824 // ##### end Gilbert 9/10 ######//
1825 }
1826
1827 set_nation( toNationRecno );
1828 }
1829 //------- End of function Town::surrender ---------//
1830
1831
1832 //------- Begin of function Town::think_rebel ---------//
1833 //
think_rebel()1834 void Town::think_rebel()
1835 {
1836 if( !nation_recno )
1837 return;
1838
1839 #define REBEL_INTERVAL_MONTH 3 // don't rebel twice in less than 3 months
1840
1841 if( info.game_date < last_rebel_date + REBEL_INTERVAL_MONTH*30 )
1842 return;
1843
1844 if( town_defender_count > 0 || info.game_date < last_being_attacked_date + 10 ) // don't rebel within ten days after being attacked by a hostile unit
1845 return;
1846
1847 //--- rebel if 2/3 of the population becomes discontented ---//
1848
1849 int i, discontentedCount=0, rebelLeaderRaceId=0, largestRebelRace=0;
1850
1851 for( i=0 ; i<MAX_RACE ; i++ )
1852 {
1853 if( race_pop_array[i] <= race_spy_count_array[i] ) // spies do not rebel together with the rebellion
1854 continue;
1855
1856 if( race_loyalty_array[i] <= REBEL_LOYALTY )
1857 {
1858 discontentedCount += race_pop_array[i];
1859
1860 if( race_pop_array[i] > largestRebelRace )
1861 {
1862 largestRebelRace = race_pop_array[i];
1863 rebelLeaderRaceId = i+1;
1864 }
1865 }
1866 }
1867
1868 if( population == 1 ) // if population is 1 only, handle otherwise
1869 {
1870 if( !rebelLeaderRaceId )
1871 return;
1872 }
1873 else
1874 {
1875 if( discontentedCount < population * 2 / 3 )
1876 return;
1877 }
1878
1879 //----- if there was just one unit in the town and he rebels ----//
1880
1881 int oneRebelOnly=0;
1882
1883 if( population==1 )
1884 {
1885 news_array.town_rebel(town_recno, 1);
1886 oneRebelOnly = 1;
1887 }
1888
1889 //----- create the rebel leader and the rebel group ------//
1890
1891 int rebelCount=1;
1892 int leaderUnitRecno = create_rebel_unit(rebelLeaderRaceId, 1); // 1-the unit is the rebel leader
1893
1894 if( !leaderUnitRecno )
1895 return;
1896
1897 uint32_t curGroupId = unit_array.cur_group_id++;
1898 Unit *unitPtr = unit_array[leaderUnitRecno];
1899 unitPtr->unit_group_id = curGroupId;
1900
1901 if( oneRebelOnly ) // if there was just one unit in the town and he rebels
1902 {
1903 rebel_array.create_rebel(leaderUnitRecno, nation_recno);
1904 return;
1905 }
1906
1907 int rebelRecno = rebel_array.create_rebel(leaderUnitRecno, nation_recno, REBEL_ATTACK_TOWN, town_recno); // create a rebel group
1908
1909 //------- create other rebel units in the rebel group -----//
1910
1911 int j, unitRecno, raceRebelCount;
1912
1913 for( i=0 ; i<MAX_RACE ; i++ )
1914 {
1915 if( race_pop_array[i] <= race_spy_count_array[i] || race_loyalty_array[i] > REBEL_LOYALTY )
1916 continue;
1917
1918 if( population==1 ) // if only one peasant left, break, so not all peasants will rebel
1919 break;
1920
1921 raceRebelCount = (int) (race_pop_array[i]-race_spy_count_array[i]) * (30+misc.random(30)) / 100; // 30% - 60% of the unit will rebel.
1922 err_when(raceRebelCount+1 > MAX_TOWN_POPULATION); // plus 1 for the leader, cannot excess MAX_TOWN_POPULATION, consider the case these units settle immediately
1923
1924 for( j=0 ; j<raceRebelCount ; j++ ) // no. of rebel units of this race
1925 {
1926 unitRecno = create_rebel_unit(i+1, 0);
1927
1928 if( !unitRecno ) // 0-the unit is not the rebel leader
1929 break;
1930
1931 unitPtr = unit_array[unitRecno];
1932 unitPtr->unit_group_id = curGroupId;
1933 unitPtr->leader_unit_recno = leaderUnitRecno;
1934
1935 rebel_array[rebelRecno]->join(unitRecno);
1936
1937 rebelCount++;
1938 }
1939
1940 //--- when disloyal units left, the average loyalty increases ---//
1941
1942 change_loyalty( i+1, (float) 50 * j / race_pop_array[i] );
1943 }
1944
1945 //---------- add news -------------//
1946
1947 last_rebel_date = info.game_date;
1948
1949 news_array.town_rebel(town_recno, rebelCount); // add the news first as after callijng ai_spy_town_rebel, the town may disappear as all peasants are gone
1950
1951 //--- tell the AI spies in the town that a rebellion is happening ---//
1952
1953 spy_array.ai_spy_town_rebel(town_recno);
1954 }
1955 //------- End of function Town::think_rebel ---------//
1956
1957
1958 //-------- Begin of function Town::create_rebel_unit --------//
1959 //
1960 // Create a rebel unit from a town.
1961 //
1962 // <int> raceId - race id. of the unit
1963 // <int> isLeader - whether the unit is a rebel leader
1964 //
1965 // return: <int> recno of the unit created.
1966 //
create_rebel_unit(int raceId,int isLeader)1967 int Town::create_rebel_unit(int raceId, int isLeader)
1968 {
1969 /* //--- do not mobilize spies as rebels ----//
1970
1971 //---------------------------------------//
1972 //
1973 // If there are spies in this town, first mobilize
1974 // the spies whose actions are "Sow Dissent".
1975 //
1976 //---------------------------------------//
1977
1978 int idleSpyCount=0;
1979
1980 if( race_spy_count_array[raceId-1] > 0 )
1981 {
1982 Spy* spyPtr;
1983
1984 for( int i=spy_array.size() ; i>0 ; i-- )
1985 {
1986 if( spy_array.is_deleted(i) )
1987 continue;
1988
1989 spyPtr = spy_array[i];
1990
1991 if( spyPtr->spy_place==SPY_TOWN &&
1992 spyPtr->spy_place_para==town_recno &&
1993 spyPtr->race_id==raceId )
1994 {
1995 if( spyPtr->action_mode == SPY_SOW_DISSENT )
1996 {
1997 int unitRecno = spyPtr->mobilize_town_spy();
1998
1999 if( isLeader )
2000 unit_array[unitRecno]->set_rank(RANK_GENERAL);
2001
2002 return unitRecno;
2003 }
2004
2005 idleSpyCount++;
2006 }
2007 }
2008 }
2009 //---- if the remaining population are all sleep spy, no new rebels ----//
2010
2011 if( race_pop_array[raceId-1] == idleSpyCount )
2012 return 0;
2013
2014 err_when( race_pop_array[raceId-1] < idleSpyCount );
2015 */
2016
2017 //---- if no jobless people, make workers and overseers jobless ----//
2018
2019 if( recruitable_race_pop(raceId, 0)==0 ) // 0-don't recruit spies as the above code should have handle spies already
2020 {
2021 if( !unjob_town_people(raceId, 0) ) // 0-don't unjob overseer
2022 return 0;
2023
2024 if( recruitable_race_pop(raceId,0)==0 ) // if the unjob unit is a spy too, then don't rebel
2025 return 0;
2026 }
2027
2028 //----look for an empty locatino for the unit to stand ----//
2029 //--- scan for the 5 rows right below the building ---//
2030
2031 int unitId = race_res[raceId]->basic_unit_id;
2032 SpriteInfo* spriteInfo = sprite_res[unit_res[unitId]->sprite_id];
2033 int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
2034
2035 if( !world.locate_space( &xLoc, &yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height ) )
2036 return 0;
2037
2038 //---------- add the unit now -----------//
2039
2040 int rankId;
2041
2042 if( isLeader )
2043 rankId = RANK_GENERAL;
2044 else
2045 rankId = RANK_SOLDIER;
2046
2047 int unitRecno = unit_array.add_unit( unitId, 0, rankId, 0, xLoc, yLoc );
2048
2049 dec_pop(raceId, 0); // decrease the town's population
2050
2051 //------- set the unit's parameters --------//
2052
2053 Unit* unitPtr = unit_array[unitRecno];
2054
2055 if( isLeader )
2056 {
2057 int combatLevel = 10 + population*2 + misc.random(10); // the higher the population is, the higher the combat level will be
2058 int leadershipLevel = 10 + population + misc.random(10); // the higher the population is, the higher the combat level will be
2059
2060 unitPtr->set_combat_level( MIN(combatLevel, 100) );
2061
2062 unitPtr->skill.skill_id = SKILL_LEADING;
2063 unitPtr->skill.skill_level = MIN(leadershipLevel, 100);
2064 }
2065 else
2066 {
2067 unitPtr->set_combat_level(CITIZEN_COMBAT_LEVEL); // combat: 10
2068 }
2069
2070 return unitRecno;
2071 }
2072 //--------- End of function Town::create_rebel_unit ---------//
2073
2074
2075 //--------- Begin of function Town::assign_unit --------//
2076 //
assign_unit(int unitRecno)2077 void Town::assign_unit(int unitRecno)
2078 {
2079 //-----------------------------------------//
2080
2081 Unit* unitPtr = unit_array[unitRecno];
2082
2083 if( population >= MAX_TOWN_POPULATION || unitPtr->rank_id == RANK_KING )
2084 {
2085 unitPtr->stop2();
2086 //----------------------------------------------------------------------//
2087 // codes for handle_blocked_move
2088 // set unit_group_id to a different value s.t. the members in this group
2089 // will not blocked by this unit.
2090 //----------------------------------------------------------------------//
2091 unitPtr->unit_group_id = unit_array.cur_group_id++;
2092 return;
2093 }
2094
2095 //------ if the unit is a general, demote it first -------//
2096
2097 if( unitPtr->rank_id == RANK_GENERAL )
2098 unitPtr->set_rank(RANK_SOLDIER);
2099
2100 //-------- increase population -------//
2101
2102 inc_pop(unitPtr->race_id, 0, unitPtr->loyalty);
2103
2104 //---- free the unit's name from the name database ----//
2105
2106 race_res[unitPtr->race_id]->free_name_id( unitPtr->name_id );
2107
2108 //----- if it's a town defending unit -----//
2109
2110 if( unitPtr->unit_mode == UNIT_MODE_DEFEND_TOWN )
2111 {
2112 #define RESISTANCE_INCREASE 2 // if the defender defeat the attackers and return the town with victory, the resistance will further increase
2113
2114 //---------------------------------------------//
2115 //
2116 // If this unit is a defender of the town, add back the
2117 // loyalty which was deducted from the defender left the
2118 // town.
2119 //
2120 //---------------------------------------------//
2121
2122 if( unitPtr->nation_recno == nation_recno &&
2123 unitPtr->unit_mode_para == town_recno )
2124 {
2125 //-- if the unit is a town defender, skill.skill_level is temporary used for storing the loyalty that will be added back to the town if the defender returns to the town
2126
2127 int loyaltyInc = unitPtr->skill.skill_level;
2128
2129 if( nation_recno ) // set the loyalty later for nation_recno > 0
2130 {
2131 change_loyalty( unitPtr->race_id, (float) loyaltyInc );
2132 }
2133 else
2134 {
2135 for( int i=0 ; i<MAX_NATION ; i++ ) // set the resistance
2136 {
2137 float newResistance = race_resistance_array[unitPtr->race_id-1][i]
2138 + loyaltyInc + RESISTANCE_INCREASE;
2139
2140 race_resistance_array[unitPtr->race_id-1][i] = MIN(newResistance, 100);
2141 }
2142 }
2143 }
2144 }
2145
2146 //------ if the unit is a spy -------//
2147
2148 if( unitPtr->spy_recno > 0 )
2149 {
2150 spy_array[unitPtr->spy_recno]->set_place(SPY_TOWN, town_recno);
2151 unitPtr->spy_recno = 0; // reset it so Unit::deinit() won't delete the spy
2152 }
2153
2154 //----- if this is an independent town -----//
2155
2156 if( nation_recno==0 ) // update the town people's combat level with this unit's combat level
2157 {
2158 town_combat_level = ( (int)town_combat_level*(population-1) + (int)unitPtr->skill.combat_level ) / population;
2159 }
2160
2161 //--------- delete the unit --------//
2162
2163 unit_array.disappear_in_town(unitRecno, town_recno); // the unit disappear from the map because it has moved into a town
2164 }
2165 //---------- End of function Town::assign_unit --------//
2166
2167
2168 //------- Begin of function Town::think_migrate ---------//
2169 //
2170 // Let the town people (only those jobless) think if they want
2171 // to migrate or not.
2172 //
2173 // People who have jobs will think in Firm::think_worker_migrate()
2174 //
2175 // Migration Possibilities:
2176 //
2177 // Independent town people migrate to -> nation town
2178 // Nation town people migrate to -> nation town
2179 //
2180 // But nation town people will NOT migrate to independent towns.
2181 //
think_migrate()2182 void Town::think_migrate()
2183 {
2184 #define MIGRATE_PROCESS_CYCLE 90
2185 #define MAX_MIGRATE_PER_DAY 4 // don't migrate more than 4 units per day
2186
2187 if( jobless_population==0 )
2188 return;
2189
2190 int i, j, raceId, migratedCount, townDistance;
2191 int saveTownRecno = town_recno;
2192 int saveTownNationRecno = nation_recno;
2193 Town* townPtr;
2194
2195 int cycleId = (info.game_date+town_recno)/MIGRATE_PROCESS_CYCLE;
2196
2197 for( i=town_array.size() ; i>0 ; i-- )
2198 {
2199 if( i%MIGRATE_PROCESS_CYCLE != cycleId ) // while this function is called every day, it only processes a certain number of towns (not all) once a day
2200 continue;
2201
2202 if( town_array.is_deleted(i) )
2203 continue;
2204
2205 townPtr = town_array[i];
2206
2207 if( townPtr->population>=MAX_TOWN_POPULATION )
2208 continue;
2209
2210 townDistance = misc.points_distance(center_x, center_y, townPtr->center_x, townPtr->center_y);
2211
2212 //---- scan all jobless population, see if any of them want to migrate ----//
2213
2214 raceId = random_race();
2215
2216 for( j=0 ; j<MAX_RACE ; j++ )
2217 {
2218 if( ++raceId > MAX_RACE )
2219 raceId = 1;
2220
2221 err_when( race_spy_count_array[raceId-1] < 0 );
2222
2223 if( recruitable_race_pop(raceId, 0) <= race_spy_count_array[raceId-1] ) // only if there are peasants who are jobless and are not spies
2224 continue;
2225
2226 //--- migrate a number of people of the same race at the same time ---//
2227
2228 migratedCount=0;
2229
2230 int loopCount=0;
2231
2232 while( think_migrate_one(townPtr, raceId, townDistance) )
2233 {
2234 err_when( ++loopCount > 100 );
2235
2236 migratedCount++;
2237
2238 if( townDistance > EFFECTIVE_TOWN_TOWN_DISTANCE ) // don't migrate more than one unit at a time for migrating to non-linked towns
2239 break;
2240
2241 if( migratedCount >= MAX_MIGRATE_PER_DAY )
2242 break;
2243 }
2244
2245 //------------- add news --------------//
2246
2247 if( migratedCount > 0 )
2248 {
2249 if( saveTownNationRecno==nation_array.player_recno ||
2250 townPtr->nation_recno==nation_array.player_recno )
2251 {
2252 news_array.migrate(saveTownRecno, townPtr->town_recno, raceId, migratedCount);
2253 }
2254
2255 return;
2256 }
2257 }
2258 }
2259 }
2260 //-------- End of function Town::think_migrate -----------//
2261
2262
2263 //------- Begin of function Town::think_migrate_one ---------//
2264 //
2265 // Think about migrating one person of the given race to the
2266 // given town.
2267 //
2268 //------------------------------------------------//
2269 //
2270 // Calculate the attractive factor, it is based on:
2271 //
2272 // - the reputation of the target nation (+0 to 100)
2273 // - the racial harmony of the race in the target town (+0 to 100)
2274 // - distance between the current town and the target town (-0 to 100)
2275 //
2276 // Attractiveness level range: 0 to 200
2277 //
2278 //------------------------------------------------//
2279 //
think_migrate_one(Town * targetTown,int raceId,int townDistance)2280 int Town::think_migrate_one(Town* targetTown, int raceId, int townDistance)
2281 {
2282 //-- only if there are peasants who are jobless and are not spies --//
2283
2284 if( recruitable_race_pop(raceId,0)==0 ) //0-don't recruit spies
2285 return 0;
2286
2287 //---- if the target town's population has already reached its MAX ----//
2288
2289 if( targetTown->population>=MAX_TOWN_POPULATION )
2290 return 0 ;
2291
2292 //-- do not migrate if the target town's population of that race is less than half of the population of the current town --//
2293
2294 if( targetTown->race_pop_array[raceId-1] < race_pop_array[raceId-1]/2 )
2295 return 0;
2296
2297 //--- calculate the attractiveness rating of the current town ---//
2298
2299 int curAttractLevel = race_harmony(raceId);
2300
2301 //--- if the target town is not linked to the current town, reduce attractiveness ---//
2302
2303 if( townDistance > EFFECTIVE_TOWN_TOWN_DISTANCE )
2304 {
2305 curAttractLevel -= 20 + townDistance/2; // 20 to 70 negative
2306 }
2307
2308 //------- loyalty/resistance affecting the attractivness ------//
2309
2310 if( nation_recno )
2311 {
2312 curAttractLevel += (int) nation_array[nation_recno]->reputation +
2313 (int) (race_loyalty_array[raceId-1] - 40); // loyalty > 40 is considered as positive force, < 40 is considered as negative force
2314 }
2315 else
2316 {
2317 if( targetTown->nation_recno )
2318 curAttractLevel += (int) race_resistance_array[raceId-1][targetTown->nation_recno-1];
2319 }
2320
2321 //--- calculate the attractiveness rating of the target town ---//
2322
2323 int targetAttractLevel = targetTown->race_harmony(raceId);
2324
2325 if( targetTown->nation_recno )
2326 targetAttractLevel += (int) nation_array[targetTown->nation_recno]->reputation;
2327
2328 //--------- compare the attractiveness ratings ---------//
2329
2330 if( targetAttractLevel > curAttractLevel && targetAttractLevel > 0 )
2331 {
2332 //--- if this is non-linked town, there are 50% chance that the migrating units will get lost on their way and never reach the destination ---//
2333
2334 if( townDistance > EFFECTIVE_TOWN_TOWN_DISTANCE )
2335 {
2336 if( misc.random(2)==0 )
2337 {
2338 dec_pop(raceId, 0);
2339 return 1;
2340 }
2341 }
2342
2343 //---------- migrate now ----------//
2344
2345 int newLoyalty = MAX( targetAttractLevel/2, 40 );
2346
2347 migrate(raceId, targetTown->town_recno, newLoyalty);
2348 return 1;
2349 }
2350
2351 return 0;
2352 }
2353 //-------- End of function Town::think_migrate_one -----------//
2354
2355
2356 //------- Begin of function Town::migrate ---------//
2357 //
2358 // People migrate from one town to another.
2359 //
2360 // <int> raceId - id. of the race that migrates
2361 // <int> destTownRecno - recno of the destination town.
2362 // <int> newLoyalty - loyalty of the unit in the target town.
2363 //
2364 // return: <int> 1 - migrated successfully
2365 // 0 - no building space in the target town for that race
2366 //
migrate(int raceId,int destTownRecno,int newLoyalty)2367 void Town::migrate(int raceId, int destTownRecno, int newLoyalty)
2368 {
2369 Town* destTown = town_array[destTownRecno];
2370
2371 if(destTown->population>=MAX_TOWN_POPULATION)
2372 return;
2373
2374 //------- decrease the population of this town ------//
2375
2376 dec_pop(raceId, 0);
2377
2378 //--------- increase the population of the target town ------//
2379
2380 destTown->inc_pop(raceId, 0, newLoyalty);
2381 }
2382 //-------- End of function Town::migrate -----------//
2383
2384
2385 //------- Begin of function Town::migrate_to ---------//
2386
migrate_to(int destTownRecno,char remoteAction,int raceId,int count)2387 int Town::migrate_to(int destTownRecno, char remoteAction, int raceId, int count)
2388 {
2389 if (count <= 0 || count > MAX_TOWN_POPULATION)
2390 {
2391 err_here();
2392 return 0;
2393 }
2394
2395 if( !raceId )
2396 {
2397 raceId = browse_selected_race_id();
2398
2399 if( !raceId )
2400 return 0;
2401 }
2402
2403 if( !remoteAction && remote.is_enable() )
2404 {
2405 // packet structure : <town recno> <dest town recno> <race id> <count>
2406 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_MIGRATE, 4*sizeof(short));
2407 shortPtr[0] = town_recno;
2408 shortPtr[1] = destTownRecno;
2409 shortPtr[2] = raceId;
2410 shortPtr[3] = count;
2411 return 0;
2412 }
2413
2414 bool continueMigrate = true;
2415 int migrated = 0;
2416 while( continueMigrate && migrated < count )
2417 {
2418 continueMigrate = can_migrate(destTownRecno, 1, raceId); // 1- migrate now, 1-allow migrate spy
2419 if (continueMigrate) ++migrated;
2420 }
2421
2422 return migrated;
2423 }
2424 //-------- End of function Town::migrate_to -----------//
2425
2426
2427 //------- Begin of function Town::can_migrate ---------//
2428 //
2429 // Check if it is okay for migrating one person from
2430 // the current town to the given town.
2431 //
2432 // <int> destTownRecno - the recno of the town the people
2433 // will migrate to.
2434 //
2435 // [int] migrateNow - migrate now or not if the result is true
2436 // (default: false)
2437 //
2438 // [int] raceId - race to check migrate
2439 // (default: 0, to find from the selected_race_id() )
2440 //
2441 // return: <int> true - migration allowed
2442 // false - migration not allowed
2443 //
can_migrate(int destTownRecno,bool migrateNow,int raceId)2444 bool Town::can_migrate(int destTownRecno, bool migrateNow, int raceId)
2445 {
2446 if(!raceId)
2447 {
2448 raceId = browse_selected_race_id();
2449
2450 if( !raceId )
2451 return false;
2452 }
2453
2454 Town* destTown = town_array[destTownRecno];
2455
2456 if( destTown->population>=MAX_TOWN_POPULATION )
2457 return false;
2458
2459 //---- if there are still jobless units ----//
2460
2461 if( recruitable_race_pop(raceId, 1) > 0 ) // 1-allow migrate spy
2462 {
2463 if( migrateNow )
2464 move_pop(destTown, raceId, 0); // 0-doesn't have job
2465
2466 return true;
2467 }
2468
2469 //--- if there is no jobless units left -----//
2470
2471 int i, j;
2472 Firm* firmPtr;
2473 Worker* workerPtr;
2474
2475 if( race_pop_array[raceId-1] > 0 )
2476 {
2477 //---- scan for firms that are linked to this town ----//
2478
2479 for( i=linked_firm_count-1 ; i>=0 ; i-- )
2480 {
2481 firmPtr = firm_array[linked_firm_array[i]];
2482
2483 //---- only for firms whose workers live in towns ----//
2484
2485 if( !firm_res[firmPtr->firm_id]->live_in_town )
2486 continue;
2487
2488 //---- if the target town is within the effective range of this firm ----//
2489
2490 if( misc.points_distance( destTown->center_x, destTown->center_y,
2491 firmPtr->center_x, firmPtr->center_y ) > EFFECTIVE_FIRM_TOWN_DISTANCE )
2492 {
2493 continue;
2494 }
2495
2496 //------- scan for workers -----------//
2497
2498 workerPtr=firmPtr->worker_array;
2499
2500 for( j=firmPtr->worker_count-1 ; j>=0 ; j--, workerPtr++ )
2501 {
2502 //--- if the worker lives in this town ----//
2503
2504 if( workerPtr->race_id == raceId &&
2505 workerPtr->town_recno == town_recno )
2506 {
2507 if( migrateNow )
2508 {
2509 if( firm_res[firmPtr->firm_id]->live_in_town )
2510 workerPtr->town_recno = destTownRecno;
2511 else
2512 workerPtr->town_recno = 0;
2513
2514 move_pop(destTown, raceId, 1); // 1-has job
2515 }
2516
2517 return true;
2518 }
2519 }
2520 }
2521 }
2522
2523 return false;
2524 }
2525 //-------- End of function Town::can_migrate -----------//
2526
2527
2528 //------- Begin of function Town::move_pop ---------//
2529 //
2530 // This function is called by Town::can_migrate() only to move a unit
2531 // from one town to another.
2532 //
move_pop(Town * destTown,int raceId,int hasJob)2533 void Town::move_pop(Town* destTown, int raceId, int hasJob)
2534 {
2535 //--- if the only pop of this race in the source town are spies ---//
2536
2537 if( !hasJob ) // only for peasant, for job unit, spy_place==SPY_FIRM and it isn't related to race_spy_count_array[]
2538 {
2539 err_when( race_spy_count_array[raceId-1] > jobless_race_pop_array[raceId-1] );
2540
2541 if( race_spy_count_array[raceId-1] == jobless_race_pop_array[raceId-1] )
2542 {
2543 int spySeqId = misc.random( race_spy_count_array[raceId-1] ) + 1; // randomly pick one of the spies
2544
2545 int spyRecno = spy_array.find_town_spy(town_recno, raceId, spySeqId);
2546
2547 err_when( !spyRecno );
2548
2549 spy_array[spyRecno]->spy_place_para = destTown->town_recno; // set the place_para of the spy
2550
2551 race_spy_count_array[raceId-1]--;
2552 destTown->race_spy_count_array[raceId-1]++;
2553 }
2554 }
2555
2556 //------------------------------------------//
2557
2558 err_when( destTown->population>MAX_TOWN_POPULATION );
2559
2560 destTown->inc_pop( raceId, hasJob, (int) race_loyalty_array[raceId-1] );
2561
2562 dec_pop( raceId, hasJob ); // the unit doesn't have a job - this must be called finally as dec_pop() will have the whole town deleted if there is only one pop left
2563
2564 err_when( race_spy_count_array[raceId-1] > jobless_race_pop_array[raceId-1] );
2565 err_when( destTown->race_spy_count_array[raceId-1] > destTown->jobless_race_pop_array[raceId-1] );
2566 }
2567 //-------- End of function Town::move_pop -----------//
2568
2569
2570 //-------- Begin of function Town::mobilize_town_people --------//
2571 //
2572 // Call out a citizen of the town population and make it
2573 // as an unit.
2574 //
2575 // <int> raceId - race id. of the unit
2576 // <int> decPop - whether decrease the population or not,
2577 // if 0, only a unit will be created and no population will
2578 // be reduced.
2579 // <int> mobileSpyFlag - whether spies will be mobilized
2580 //
2581 // return: <int> recno of the unit created.
2582 //
mobilize_town_people(int raceId,int decPop,int mobileSpyFlag)2583 int Town::mobilize_town_people(int raceId, int decPop, int mobileSpyFlag)
2584 {
2585 //---- if no jobless people, make workers and overseers jobless ----//
2586
2587 if( recruitable_race_pop(raceId, mobileSpyFlag)==0 )
2588 {
2589 if( !unjob_town_people(raceId, 0) ) // 0-don't unjob overseer
2590 return 0;
2591
2592 err_when( recruitable_race_pop(raceId, mobileSpyFlag)==0 );
2593 }
2594
2595 //----look for an empty locatino for the unit to stand ----//
2596 //--- scan for the 5 rows right below the building ---//
2597
2598 int unitId = race_res[raceId]->basic_unit_id;
2599 SpriteInfo* spriteInfo = sprite_res[unit_res[unitId]->sprite_id];
2600 int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
2601
2602 if( !world.locate_space( &xLoc, &yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height ) )
2603 return 0;
2604
2605 //---------- add the unit now -----------//
2606
2607 int unitRecno = unit_array.add_unit( unitId,
2608 nation_recno, RANK_SOLDIER, (int) race_loyalty_array[raceId-1], xLoc, yLoc );
2609
2610 //------- set the unit's parameters --------//
2611
2612 Unit* unitPtr = unit_array[unitRecno];
2613
2614 unitPtr->set_combat_level(CITIZEN_COMBAT_LEVEL);
2615
2616 //-------- decrease the town's population ------//
2617
2618 if( decPop )
2619 dec_pop(raceId, 0);
2620
2621 return unitRecno;
2622 }
2623 //--------- End of function Town::mobilize_town_people ---------//
2624
2625
2626 //--------- Begin of function Town::being_attacked -------//
2627 //
2628 // This function is called by Unit::hit_town()
2629 //
2630 // <int> attackerUnitRecno - recno of the unit attacking this town.
2631 // <float> attackDamage - damage caused by the attack
2632 //
being_attacked(int attackerUnitRecno,float attackDamage)2633 void Town::being_attacked(int attackerUnitRecno, float attackDamage)
2634 {
2635 if( rebel_recno ) // if this town is controlled by a rebel group
2636 rebel_array[rebel_recno]->town_being_attacked(attackerUnitRecno);
2637
2638 if( population==0 )
2639 return;
2640
2641 defend_target_recno = attackerUnitRecno; // store the target recno
2642
2643 Unit* attackerUnit = unit_array[attackerUnitRecno];
2644
2645 if( attackerUnit->nation_recno == nation_recno ) // this can happen when the unit has just changed nation
2646 return;
2647
2648 int attackerNationRecno = attackerUnit->nation_recno;
2649
2650 last_being_attacked_date = info.game_date;
2651
2652 //--------- store attacker nation recno -----------//
2653
2654 err_when(attackerNationRecno<0 || attackerNationRecno>MAX_NATION);
2655 set_hostile_nation(attackerNationRecno);
2656
2657 //----------- call out defender -----------//
2658
2659 // only call out defender when the attacking unit is within the effective defending distance
2660
2661 if( misc.points_distance( attackerUnit->cur_x_loc(), attackerUnit->cur_y_loc(),
2662 center_x, center_y ) <= EFFECTIVE_DEFEND_TOWN_DISTANCE )
2663 {
2664 int loopCount=0;
2665
2666 while(1)
2667 {
2668 if( !mobilize_defender(attackerNationRecno) )
2669 break;
2670
2671 err_when( loopCount++ > 1000 );
2672 }
2673 }
2674
2675 auto_defense(attackerUnitRecno);
2676
2677 //----- pick a race to be attacked by the attacker randomly -----//
2678
2679 int raceId = pick_random_race(1, 1); // 1-pick has job people, 1-pick spies
2680
2681 err_when( !raceId );
2682
2683 //-------- town people get killed ---------//
2684
2685 received_hit_count += attackDamage;
2686
2687 if( received_hit_count >= RECEIVED_HIT_PER_KILL )
2688 {
2689 received_hit_count = (float) 0;
2690
2691 int townRecno = town_recno;
2692
2693 kill_town_people(raceId, attackerNationRecno); // kill a town people
2694
2695 if( town_array.is_deleted(townRecno) ) // the town may have been deleted when all pop are killed
2696 return;
2697 }
2698
2699 //---- decrease resistance if this is an independent town ----//
2700
2701 if( town_defender_count==0 )
2702 {
2703 //--- Resistance/loyalty of the town people decrease if the attacking continues ---//
2704 //
2705 // Resistance/Loyalty decreases faster:
2706 //
2707 // -when there are few people in the town
2708 // -when there is no defender
2709 //
2710 //---------------------------------------//
2711
2712 float loyaltyDec;
2713
2714 if( nation_recno ) // if the town belongs to a nation
2715 {
2716 //---- decrease loyalty of all races in the town ----//
2717
2718 for( raceId=1 ; raceId<=MAX_RACE ; raceId++ )
2719 {
2720 if( race_pop_array[raceId-1] == 0 )
2721 continue;
2722
2723 if( has_linked_own_camp ) // if it is linked to one of its camp, the loyalty will decrease slower
2724 loyaltyDec = (float) 5 / race_pop_array[raceId-1];
2725 else
2726 loyaltyDec = (float) 10 / race_pop_array[raceId-1];
2727
2728 loyaltyDec = MIN( loyaltyDec, (float) 1 );
2729
2730 change_loyalty( raceId, -loyaltyDec * attackDamage / (20/ATTACK_SLOW_DOWN) );
2731 }
2732
2733 //--- if the resistance of all the races are zero, think_change_nation() ---//
2734
2735 int i;
2736 for( i=0 ; i<MAX_RACE ; i++ )
2737 {
2738 if( race_loyalty_array[i] >= (float) 1 ) // values between 0 and 1 are considered as 0
2739 break;
2740 }
2741
2742 if( i==MAX_RACE ) // if resistance of all races drop to zero
2743 think_surrender();
2744 }
2745 else // if the town is an independent town
2746 {
2747 if( !attackerNationRecno ) // if independent units do not attack independent towns
2748 return;
2749
2750 //---- decrease resistance of all races in the town ----//
2751
2752 for( raceId=1 ; raceId<=MAX_RACE ; raceId++ )
2753 {
2754 if( race_pop_array[raceId-1] == 0 )
2755 continue;
2756
2757 loyaltyDec = (float) 10 / race_pop_array[raceId-1]; // decrease faster for independent towns than towns belonging to nations
2758 loyaltyDec = MIN( loyaltyDec, (float) 1 );
2759
2760 race_resistance_array[raceId-1][attackerNationRecno-1] -= loyaltyDec * attackDamage / (20/ATTACK_SLOW_DOWN);
2761
2762 if( race_resistance_array[raceId-1][attackerNationRecno-1] < 0 )
2763 race_resistance_array[raceId-1][attackerNationRecno-1] = (float) 0;
2764 }
2765
2766 //--- if the resistance of all the races are zero, think_change_nation() ---//
2767
2768 int i;
2769 for( i=0 ; i<MAX_RACE ; i++ )
2770 {
2771 if( race_resistance_array[i][attackerNationRecno-1] >= (float) 1 )
2772 break;
2773 }
2774
2775 if( i==MAX_RACE ) // if resistance of all races drop to zero
2776 surrender(attackerNationRecno);
2777 }
2778 }
2779
2780 //------ reinforce troops to defend against the attack ------//
2781
2782 if( town_defender_count==0 && nation_recno )
2783 {
2784 if( attackerUnit->nation_recno != nation_recno ) // they may become the same when the town has been captured
2785 nation_array[nation_recno]->ai_defend(attackerUnitRecno);
2786 }
2787 }
2788 //---------- End of function Town::being_attacked -----//
2789
2790
2791 //--------- Begin of function Town::clear_defense_mode -------//
clear_defense_mode()2792 void Town::clear_defense_mode()
2793 {
2794 //------------------------------------------------------------------//
2795 // change defense unit's to non-defense mode
2796 //------------------------------------------------------------------//
2797 Unit *unitPtr;
2798 for(int i=unit_array.size(); i>=1; --i)
2799 {
2800 if(unit_array.is_deleted(i))
2801 continue;
2802
2803 unitPtr = unit_array[i];
2804 if(!unitPtr)
2805 continue;
2806
2807 err_when(unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE || unitPtr->hit_points<=0);
2808 if(unitPtr->in_defend_town_mode() && unitPtr->action_misc==ACTION_MISC_DEFEND_TOWN_RECNO &&
2809 unitPtr->action_misc_para==town_recno)
2810 unitPtr->clear_town_defend_mode(); // note: maybe, unitPtr->nation_recno != nation_recno
2811 }
2812 }
2813 //---------- End of function Town::clear_defense_mode -----//
2814
2815
2816 //--------- Begin of function Town::mobilize_defender -------//
2817 //
mobilize_defender(int attackerNationRecno)2818 int Town::mobilize_defender(int attackerNationRecno)
2819 {
2820 if( population==1 ) // do not call out defenders any more if there is only one person left in the town, otherwise the town will be gone.
2821 return 0;
2822
2823 //------- pick a race to mobilize randomly --------//
2824
2825 int randomPersonId = misc.random(population)+1;
2826 int popSum=0, raceId=0;
2827
2828 int i;
2829 for( i=0 ; i<MAX_RACE ; i++ )
2830 {
2831 popSum += race_pop_array[i];
2832
2833 if( randomPersonId <= popSum )
2834 {
2835 raceId = i+1;
2836 break;
2837 }
2838 }
2839
2840 if( raceId==0 )
2841 return 0;
2842
2843 //---- check if the current loyalty allows additional defender ----//
2844 //
2845 // if the loyalty is high, then there will be more town defenders
2846 //
2847 //-----------------------------------------------------------------//
2848
2849 float curLoyalty;
2850
2851 if( nation_recno )
2852 curLoyalty = race_loyalty_array[raceId-1];
2853 else
2854 {
2855 if( !attackerNationRecno ) // if independent units do not attack independent towns
2856 return 0;
2857
2858 curLoyalty = race_resistance_array[raceId-1][attackerNationRecno-1];
2859 }
2860
2861 //--- only mobilize new defenders when there aren't too many existing ones ---//
2862
2863 if( rebel_recno ) // if this town is controlled by rebels
2864 {
2865 if( curLoyalty < town_defender_count*2 ) // rebel towns have more rebel units coming out to defend
2866 return 0;
2867 }
2868 else
2869 {
2870 if( curLoyalty < town_defender_count*5 ) // if no more defenders are allowed for the current loyalty
2871 return 0;
2872 }
2873
2874 //----- check if the loyalty/resistance is high enough -----//
2875
2876 if( nation_recno )
2877 {
2878 if( curLoyalty < MIN_NATION_DEFEND_LOYALTY )
2879 return 0;
2880 }
2881 else
2882 {
2883 if( curLoyalty < MIN_INDEPENDENT_DEFEND_LOYALTY )
2884 return 0;
2885 }
2886
2887 //------ check if there are peasants to defend ------//
2888
2889 if( recruitable_race_pop(raceId, 0) == 0 ) // 0-don't recruit spies
2890 return 0;
2891
2892 //---------- create a defender unit --------------------//
2893
2894 //--------------------------------------------------------------//
2895 // loyalty of that race
2896 // decrease loyalty by: -------------------------------
2897 // no. of town people of that race
2898 //--------------------------------------------------------------//
2899
2900 float loyaltyDec = curLoyalty/race_pop_array[raceId-1]; // decrease in loyalty or resistance
2901
2902 if( nation_recno )
2903 {
2904 change_loyalty( raceId, -loyaltyDec );
2905 }
2906 else
2907 {
2908 for( i=0 ; i<MAX_NATION ; i++ )
2909 race_resistance_array[raceId-1][i] -= loyaltyDec;
2910 }
2911
2912 //------- mobilize jobless people if there are any -------//
2913
2914 int unitRecno = mobilize_town_people(raceId, 1, 0); // 1-dec pop, 0-don't mobilize spy town people
2915
2916 Unit* unitPtr = unit_array[unitRecno];
2917
2918 err_when( town_array.is_deleted(town_recno) );
2919
2920 unitPtr->set_mode( UNIT_MODE_DEFEND_TOWN, town_recno );
2921
2922 unitPtr->skill.skill_level = (char) loyaltyDec; // if the unit is a town defender, this var is temporary used for storing the loyalty that will be added back to the town if the defender returns to the town
2923
2924 int combatLevel = town_combat_level + misc.random(20) - 10; // -10 to +10 random difference
2925
2926 combatLevel = MIN(combatLevel, 100);
2927 combatLevel = MAX(combatLevel, 10);
2928
2929 unitPtr->set_combat_level(combatLevel);
2930
2931 //-----------------------------------------------------//
2932 // enable unit defend_town mode
2933 //-----------------------------------------------------//
2934
2935 unitPtr->stop2();
2936 unitPtr->action_mode2 = ACTION_DEFEND_TOWN_DETECT_TARGET;
2937 unitPtr->action_para2 = UNIT_DEFEND_TOWN_DETECT_COUNT;
2938
2939 unitPtr->action_misc = ACTION_MISC_DEFEND_TOWN_RECNO;
2940 unitPtr->action_misc_para = town_recno;
2941
2942 town_defender_count++;
2943
2944 //------- if this town is controlled by rebels --------//
2945
2946 if( rebel_recno )
2947 rebel_array[rebel_recno]->mobile_rebel_count++; // increase the no. of mobile rebel units
2948
2949 return unitRecno;
2950 }
2951 //---------- End of function Town::mobilize_defender -----//
2952
2953
2954 //--------- Begin of function Town::reduce_defender_count -------//
2955
reduce_defender_count()2956 void Town::reduce_defender_count()
2957 {
2958 if( --town_defender_count==0 )
2959 independ_town_nation_relation = 0;
2960
2961 //------- if this town is controlled by rebels --------//
2962
2963 if( rebel_recno )
2964 rebel_array[rebel_recno]->mobile_rebel_count--; // decrease the no. of mobile rebel units
2965 }
2966 //---------- End of function Town::reduce_defender_count -----//
2967
2968
2969 //--------- Begin of function Town::kill_town_people -------//
2970 //
kill_town_people(int raceId,int attackerNationRecno)2971 void Town::kill_town_people(int raceId, int attackerNationRecno)
2972 {
2973 if( !raceId )
2974 raceId = pick_random_race(1, 1); // 1-pick has job unit, 1-pick spies
2975
2976 if( !raceId )
2977 return ;
2978
2979 //---- jobless town people get killed first, if all jobless are killed, then kill workers ----//
2980
2981 if( recruitable_race_pop(raceId,1)==0 )
2982 {
2983 if( !unjob_town_people(raceId, 1) ) // unjob overseer if the only person left is a overseer
2984 return;
2985
2986 err_when( recruitable_race_pop(raceId,1)==0 );
2987 }
2988
2989 //------ the killed unit can be a spy -----//
2990
2991 if( misc.random(recruitable_race_pop(raceId,1)) < race_spy_count_array[raceId-1] )
2992 {
2993 int spyRecno = spy_array.find_town_spy(town_recno, raceId, misc.random(race_spy_count_array[raceId-1])+1 );
2994
2995 spy_array.del_spy(spyRecno);
2996 }
2997
2998 //---- killing civilian people decreases loyalty -----//
2999
3000 if( nation_recno && attackerNationRecno ) // your people's loyalty decreases because you cannot protect them.
3001 nation_array[nation_recno]->civilian_killed(raceId, -1); // but only when your units are killed by enemies, neutral disasters are not counted
3002
3003 if( attackerNationRecno ) // the attacker's people's loyalty decreases because of the killing actions.
3004 nation_array[attackerNationRecno]->civilian_killed(raceId, 2); // the nation is the attacking one
3005
3006 // -------- sound effect ---------//
3007
3008 se_res.sound( center_x, center_y, 1, 'R', raceId, "DIE" );
3009
3010 //-------- decrease population now --------//
3011
3012 dec_pop( raceId, 0 ); // 0-doesn't have a job
3013 }
3014 //---------- End of function Town::kill_town_people -----//
3015
3016
3017 //--------- Begin of function Town::unjob_town_people -------//
3018 //
3019 // Make one town people of the specific race jobless.
3020 // Workers are processed first, overseers are processed next.
3021 //
3022 // <int> raceId - race id.
3023 // <int> unjobOverseer - whether unjob overseer or not
3024 // <int> killOverseer - kill the overseer if possible
3025 //
3026 // return: <int> a town person has been made jobless
3027 //
unjob_town_people(int raceId,int unjobOverseer,int killOverseer)3028 int Town::unjob_town_people(int raceId, int unjobOverseer, int killOverseer)
3029 {
3030 //---- if no jobless people, workers will then get killed -----//
3031
3032 int i, workerId;
3033 Firm* firmPtr;
3034 Worker* workerPtr;
3035
3036 int racePop = jobless_race_pop_array[raceId-1];
3037
3038 for( i=linked_firm_count-1 ; i>=0 ; i-- )
3039 {
3040 firmPtr = firm_array[linked_firm_array[i]];
3041
3042 //------- scan for workers -----------//
3043
3044 workerPtr=firmPtr->worker_array;
3045
3046 for( workerId=1 ; workerId<=firmPtr->worker_count ; workerId++, workerPtr++ )
3047 {
3048 //--- if the worker lives in this town ----//
3049
3050 if( workerPtr->race_id == raceId &&
3051 workerPtr->town_recno == town_recno )
3052 {
3053 if(!firmPtr->resign_worker(workerId))
3054 return 0;
3055
3056 err_when(population>MAX_TOWN_POPULATION);
3057 err_when( jobless_race_pop_array[raceId-1] != racePop+1 );
3058 return 1;
3059 }
3060 }
3061 }
3062
3063 //----- if no worker killed, try to kill overseers ------//
3064
3065 if( unjobOverseer )
3066 {
3067 Unit* overseerUnit;
3068
3069 for( i=linked_firm_count-1 ; i>=0 ; i-- )
3070 {
3071 firmPtr = firm_array[linked_firm_array[i]];
3072
3073 //------- scan for overseer -----------//
3074
3075 if( firmPtr->overseer_recno )
3076 {
3077 //--- if the overseer lives in this town ----//
3078
3079 overseerUnit = unit_array[firmPtr->overseer_recno];
3080
3081 if( overseerUnit->race_id == raceId &&
3082 firmPtr->overseer_town_recno == town_recno )
3083 {
3084 if(killOverseer)
3085 firmPtr->kill_overseer();
3086 else
3087 {
3088 int overseerUnitRecno = firmPtr->overseer_recno;
3089 Unit *unitPtr = unit_array[overseerUnitRecno];
3090 firmPtr->assign_overseer(0);
3091 if(!unit_array.is_deleted(overseerUnitRecno) && unitPtr->is_visible())
3092 unit_array.disappear_in_town(overseerUnitRecno, town_recno);
3093 }
3094 err_when( jobless_race_pop_array[raceId-1] != racePop+1 );
3095 return 1;
3096 }
3097 }
3098 }
3099 }
3100
3101 return 0;
3102 }
3103 //---------- End of function Town::unjob_town_people -----//
3104
3105
3106 //--------- Begin of function Town::distribute_demand ---------//
3107 //
3108 // Distribute demands among
3109 //
distribute_demand()3110 void Town::distribute_demand()
3111 {
3112 #define MAX_ACTIVE_MARKET_COUNT 20
3113
3114 //------------ define struct MarketInfo --------------//
3115
3116 struct MarketGoodsInfo
3117 {
3118 FirmMarket* market_ptr[MAX_ACTIVE_MARKET_COUNT];
3119 float total_supply;
3120 float total_own_supply;
3121 short market_count;
3122 };
3123
3124 //------ scan for a firm to input raw materials --------//
3125
3126 int i, j;
3127 Firm* firmPtr;
3128 MarketGoodsInfo marketGoodsInfoArray[MAX_PRODUCT];
3129 MarketGoodsInfo* marketGoodsInfo;
3130 float thisSupply;
3131 MarketGoods* marketGoods;
3132
3133 memset( marketGoodsInfoArray, 0, sizeof(marketGoodsInfoArray) );
3134
3135 //------- count the no. of market place that are near to this town ----//
3136
3137 for( int linkedFirmId=0 ; linkedFirmId<linked_firm_count ; linkedFirmId++ )
3138 {
3139 firmPtr = firm_array[ linked_firm_array[linkedFirmId] ];
3140
3141 if( firmPtr->firm_id != FIRM_MARKET )
3142 continue;
3143
3144 if( linked_firm_enable_array[linkedFirmId] != LINK_EE )
3145 continue;
3146
3147 firmPtr = firm_array[linked_firm_array[linkedFirmId]];
3148
3149 //---------- process market -------------//
3150
3151 for( i=0 ; i<MAX_PRODUCT ; i++ )
3152 {
3153 marketGoods = ((FirmMarket*)firmPtr)->market_product_array[i];
3154 marketGoodsInfo = marketGoodsInfoArray+i;
3155
3156 if( marketGoods && marketGoodsInfo->market_count < MAX_ACTIVE_MARKET_COUNT )
3157 {
3158 thisSupply = marketGoods->stock_qty;
3159
3160 marketGoodsInfo->market_ptr[marketGoodsInfo->market_count] = (FirmMarket*) firmPtr;
3161
3162 marketGoodsInfo->total_supply += thisSupply;
3163
3164 if( firmPtr->nation_recno == nation_recno ) // vars for later use, so that towns will always try to buy goods from their own markets first.
3165 marketGoodsInfo->total_own_supply += thisSupply;
3166
3167 marketGoodsInfo->market_count++;
3168 }
3169 }
3170 }
3171
3172 //-- set the monthly demand of the town on each product --//
3173
3174 float townDemand = (float) jobless_population * (float) PEASANT_GOODS_MONTH_DEMAND
3175 + (float) worker_population() * (float) WORKER_GOODS_MONTH_DEMAND;
3176
3177 float ownShareDemand; // the share of demand for own markets
3178
3179 //---------- sell goods now -----------//
3180
3181 FirmMarket* firmMarket;
3182
3183 for( i=0 ; i<MAX_PRODUCT ; i++ )
3184 {
3185 marketGoodsInfo = marketGoodsInfoArray+i;
3186
3187 for( j=0 ; j<marketGoodsInfo->market_count ; j++ )
3188 {
3189 //----------------------------------//
3190 //
3191 // If the totalSupply < town demand:
3192 // a market's demand = its_supply + (town_demand-totalSupply) / market_count
3193 //
3194 // If the totalSupply > town demand:
3195 // a market's demand = town_demand * its_supply / totalSupply
3196 //
3197 //----------------------------------//
3198
3199 firmMarket = marketGoodsInfo->market_ptr[j];
3200
3201 marketGoods = firmMarket->market_product_array[i];
3202
3203 if( marketGoods )
3204 {
3205 //---- if the demand is larger than the supply -----//
3206
3207 if( marketGoodsInfo->total_supply <= townDemand )
3208 {
3209 marketGoods->month_demand += marketGoods->stock_qty +
3210 (townDemand - marketGoodsInfo->total_supply)
3211 / marketGoodsInfo->market_count; // evenly distribute the excessive demand on all markets
3212 }
3213 else //---- if the supply is larger than the demand -----//
3214 {
3215 //--- towns always try to buy goods from their own markets first ---//
3216
3217 ownShareDemand = MIN(townDemand, marketGoodsInfo->total_own_supply);
3218
3219 if( firmMarket->nation_recno == nation_recno )
3220 {
3221 if (marketGoodsInfo->total_own_supply > 0.0f) // if total_own_supply is 0 then ownShareDemand is also 0 and we put no demand on the product
3222 marketGoods->month_demand += ownShareDemand * marketGoods->stock_qty / marketGoodsInfo->total_own_supply;
3223 }
3224 else
3225 {
3226 // Note: total_supply > 0.0f, because else the first case above (demand larger than supply) will be triggered
3227 marketGoods->month_demand += (townDemand-ownShareDemand) * marketGoods->stock_qty / marketGoodsInfo->total_supply;
3228 }
3229 }
3230 }
3231 }
3232 }
3233 }
3234 //----------- End of function Town::distribute_demand -----------//
3235
3236
3237 //------- Begin of function Town::setup_link ---------//
3238 //
setup_link()3239 void Town::setup_link()
3240 {
3241 //-----------------------------------------------------------------------------//
3242 // check the connected firms location and structure if ai_link_checked is true
3243 //-----------------------------------------------------------------------------//
3244 if(ai_town)
3245 ai_link_checked = 0;
3246
3247 //----- build town-to-firm link relationship -------//
3248
3249 int firmRecno, defaultLinkStatus;
3250 Firm* firmPtr;
3251 FirmInfo* firmInfo;
3252
3253 linked_firm_count = 0;
3254
3255 for( firmRecno=firm_array.size() ; firmRecno>0 ; firmRecno-- )
3256 {
3257 if( firm_array.is_deleted(firmRecno) )
3258 continue;
3259
3260 firmPtr = firm_array[firmRecno];
3261 firmInfo = firm_res[firmPtr->firm_id];
3262
3263 if( !firmInfo->is_linkable_to_town )
3264 continue;
3265
3266 //---------- check if the firm is close enough to this firm -------//
3267
3268 if( misc.points_distance( firmPtr->center_x, firmPtr->center_y,
3269 center_x, center_y ) > EFFECTIVE_FIRM_TOWN_DISTANCE )
3270 {
3271 continue;
3272 }
3273
3274 //------ check if both are on the same terrain type ------//
3275
3276 if( (world.get_loc(firmPtr->center_x, firmPtr->center_y)->is_plateau()==1)
3277 != (world.get_loc(center_x, center_y)->is_plateau()==1) )
3278 {
3279 continue;
3280 }
3281
3282 //------- determine the default link status ------//
3283
3284 if( firmPtr->nation_recno == nation_recno ) // if the two firms are of the same nation, get the default link status which is based on the types of the firms
3285 defaultLinkStatus = LINK_EE;
3286 else
3287 defaultLinkStatus = LINK_DD; // if the two firms are of different nations, default link status is both side disabled
3288
3289 //----- a town cannot disable a camp's link to it ----//
3290
3291 if( firmPtr->firm_id==FIRM_CAMP ) // for capturing the town
3292 defaultLinkStatus = LINK_EE;
3293
3294 //-------- add the link now -------//
3295
3296 if( linked_firm_count < MAX_LINKED_FIRM_TOWN )
3297 {
3298 linked_firm_array[linked_firm_count] = firmRecno;
3299 linked_firm_enable_array[linked_firm_count] = defaultLinkStatus;
3300
3301 linked_firm_count++;
3302 }
3303 else
3304 {
3305 err_here();
3306 }
3307
3308 if( firmPtr->linked_town_count < MAX_LINKED_TOWN_TOWN )
3309 {
3310 if( defaultLinkStatus==LINK_ED ) // Reverse the link status for the opposite linker
3311 defaultLinkStatus=LINK_DE;
3312
3313 else if( defaultLinkStatus==LINK_DE )
3314 defaultLinkStatus=LINK_ED;
3315
3316 firmPtr->linked_town_array[firmPtr->linked_town_count] = town_recno;
3317 firmPtr->linked_town_enable_array[firmPtr->linked_town_count] = defaultLinkStatus;
3318
3319 firmPtr->linked_town_count++;
3320 if(firmPtr->firm_ai)
3321 firmPtr->ai_link_checked = 0;
3322 }
3323 else
3324 {
3325 err_here();
3326 }
3327 }
3328
3329 //----- build town-to-town link relationship -------//
3330
3331 linked_town_count = 0;
3332
3333 int townRecno;
3334 Town* townPtr;
3335
3336 for( townRecno=town_array.size() ; townRecno>0 ; townRecno-- )
3337 {
3338 if( town_array.is_deleted(townRecno) || townRecno==town_recno )
3339 continue;
3340
3341 townPtr = town_array[townRecno];
3342
3343 //------ check if the town is close enough to this firm -------//
3344
3345 if( misc.points_distance( townPtr->center_x, townPtr->center_y,
3346 center_x, center_y ) > EFFECTIVE_TOWN_TOWN_DISTANCE )
3347 {
3348 continue;
3349 }
3350
3351 //------ check if both are on the same terrain type ------//
3352
3353 if( (world.get_loc(townPtr->center_x, townPtr->center_y)->is_plateau()==1)
3354 != (world.get_loc(center_x, center_y)->is_plateau()==1) )
3355 {
3356 continue;
3357 }
3358
3359 //------- determine the default link status ------//
3360
3361 defaultLinkStatus = LINK_EE;
3362
3363 //-------- add the link now -------//
3364
3365 if( linked_town_count < MAX_LINKED_TOWN_TOWN )
3366 {
3367 linked_town_array[linked_town_count] = townRecno;
3368 linked_town_enable_array[linked_town_count] = defaultLinkStatus;
3369
3370 linked_town_count++;
3371 }
3372 else
3373 {
3374 err_here();
3375 }
3376
3377 if( townPtr->linked_town_count < MAX_LINKED_TOWN_TOWN )
3378 {
3379 if( defaultLinkStatus==LINK_ED ) // Reverse the link status for the opposite linker
3380 defaultLinkStatus=LINK_DE;
3381
3382 else if( defaultLinkStatus==LINK_DE )
3383 defaultLinkStatus=LINK_ED;
3384
3385 townPtr->linked_town_array[townPtr->linked_town_count] = town_recno;
3386 townPtr->linked_town_enable_array[townPtr->linked_town_count] = defaultLinkStatus;
3387
3388 townPtr->linked_town_count++;
3389 if(townPtr->ai_town)
3390 townPtr->ai_link_checked = 0;
3391 }
3392 else
3393 {
3394 err_here();
3395 }
3396 }
3397 }
3398 //-------- End of function Town::setup_link -----------//
3399
3400
3401 //------- Begin of function Town::release_link ---------//
3402 //
release_link()3403 void Town::release_link()
3404 {
3405 int i;
3406 Firm *firmPtr;
3407 Town *townPtr;
3408
3409 //------ release linked firms ------//
3410
3411 for( i=0 ; i<linked_firm_count ; i++ )
3412 {
3413 firmPtr = firm_array[linked_firm_array[i]];
3414 firmPtr->release_town_link(town_recno);
3415
3416 if(firmPtr->firm_ai)
3417 firmPtr->ai_link_checked = 0;
3418 }
3419
3420 //------ release linked towns ------//
3421
3422 for( i=0 ; i<linked_town_count ; i++ )
3423 {
3424 townPtr = town_array[linked_town_array[i]];
3425 townPtr->release_town_link(town_recno);
3426
3427 if(townPtr->ai_town)
3428 townPtr->ai_link_checked = 0;
3429 }
3430 }
3431 //-------- End of function Town::release_link -----------//
3432
3433
3434 //------- Begin of function Town::release_firm_link ---------//
3435 //
release_firm_link(int releaseFirmRecno)3436 void Town::release_firm_link(int releaseFirmRecno)
3437 {
3438 //-----------------------------------------------------------------------------//
3439 // check the connected firms location and structure if ai_link_checked is true
3440 //-----------------------------------------------------------------------------//
3441 if(ai_town)
3442 ai_link_checked = 0;
3443
3444 for( int i=0 ; i<linked_firm_count ; i++ )
3445 {
3446 if( linked_firm_array[i] == releaseFirmRecno )
3447 {
3448 err_when( linked_firm_count > MAX_LINKED_FIRM_TOWN );
3449
3450 misc.del_array_rec( linked_firm_array , linked_firm_count, sizeof(linked_firm_array[0]), i+1 );
3451 misc.del_array_rec( linked_firm_enable_array, linked_firm_count, sizeof(linked_firm_enable_array[0]), i+1 );
3452 linked_firm_count--;
3453 return;
3454 }
3455 }
3456
3457 err_here();
3458 }
3459 //------- End of function Town::release_firm_link ---------//
3460
3461
3462 //------- Begin of function Town::release_town_link ---------//
3463 //
release_town_link(int releaseTownRecno)3464 void Town::release_town_link(int releaseTownRecno)
3465 {
3466 //-----------------------------------------------------------------------------//
3467 // check the connected firms location and structure if ai_link_checked is true
3468 //-----------------------------------------------------------------------------//
3469 if(ai_town)
3470 ai_link_checked = 0;
3471
3472 for( int i=0 ; i<linked_town_count ; i++ )
3473 {
3474 if( linked_town_array[i] == releaseTownRecno )
3475 {
3476 err_when( linked_town_count > MAX_LINKED_TOWN_TOWN );
3477
3478 misc.del_array_rec( linked_town_array , linked_town_count, sizeof(linked_town_array[0]), i+1 );
3479 misc.del_array_rec( linked_town_enable_array, linked_town_count, sizeof(linked_town_enable_array[0]), i+1 );
3480 linked_town_count--;
3481 return;
3482 }
3483 }
3484
3485 err_here();
3486 }
3487 //------- End of function Town::release_town_link ---------//
3488
3489
3490 //------- Begin of function Town::toggle_firm_link ---------//
3491 //
3492 // Toggle the firm link of the current town.
3493 //
3494 // <int> linkId - id. of the link
3495 // <int> toggleFlag - 1-enable, 0-disable
3496 // <char> remoteAction - remote action type
3497 // [int] setBoth - if this is 1, it will set the link to either LINK_EE or LINK_DD (and no LINK_ED or LINK_DD)
3498 // if this is -1, the only one side will be set even though the nation recno of the firm and town are the same
3499 // (default: 0)
3500 //
toggle_firm_link(int linkId,int toggleFlag,char remoteAction,int setBoth)3501 void Town::toggle_firm_link(int linkId, int toggleFlag, char remoteAction, int setBoth)
3502 {
3503 if( !remoteAction && remote.is_enable() )
3504 {
3505 // packet structure : <town recno> <link Id> <toggle Flag>
3506 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_TOGGLE_LINK_FIRM, 3*sizeof(short));
3507 shortPtr[0] = town_recno;
3508 shortPtr[1] = linkId;
3509 shortPtr[2] = toggleFlag;
3510 return;
3511 }
3512
3513 Firm* linkedFirm = firm_array[linked_firm_array[linkId-1]];
3514 int linkedNationRecno = linkedFirm->nation_recno;
3515
3516 int sameNation = linkedNationRecno == nation_recno || // if one of the linked end is an indepdendent firm/nation, consider this link as a single nation link
3517 linkedNationRecno == 0 ||
3518 nation_recno == 0;
3519
3520 if( toggleFlag )
3521 {
3522 if( (sameNation && setBoth==0) || setBoth==1 ) // 0 if setBoth == -1
3523 linked_firm_enable_array[linkId-1] = LINK_EE;
3524 else
3525 linked_firm_enable_array[linkId-1] |= LINK_ED;
3526 }
3527 else
3528 {
3529 if( (sameNation && setBoth==0) || setBoth==1 )
3530 linked_firm_enable_array[linkId-1] = LINK_DD;
3531 else
3532 linked_firm_enable_array[linkId-1] &= ~LINK_ED;
3533 }
3534
3535 //------ set the linked flag of the opposite firm -----//
3536
3537 Firm* firmPtr = firm_array[ linked_firm_array[linkId-1] ];
3538 int i;
3539
3540 for(i=firmPtr->linked_town_count-1; i>=0; i--)
3541 {
3542 if( firmPtr->linked_town_array[i] == town_recno )
3543 {
3544 if( toggleFlag )
3545 {
3546 if( (sameNation && setBoth==0) || setBoth==1 )
3547 firmPtr->linked_town_enable_array[i] = LINK_EE;
3548 else
3549 firmPtr->linked_town_enable_array[i] |= LINK_DE;
3550 }
3551 else
3552 {
3553 if( (sameNation && setBoth==0) || setBoth==1 )
3554 firmPtr->linked_town_enable_array[i] = LINK_DD;
3555 else
3556 firmPtr->linked_town_enable_array[i] &= ~LINK_DE;
3557 }
3558
3559 break;
3560 }
3561 }
3562
3563 //-------- update the town's influence --------//
3564
3565 if( nation_recno==0 )
3566 update_target_resistance();
3567
3568 //--- redistribute demand if a link to market place has been toggled ---//
3569
3570 if( linkedFirm->firm_id == FIRM_MARKET )
3571 town_array.distribute_demand();
3572 }
3573 //-------- End of function Town::toggle_firm_link ---------//
3574
3575
3576 //------- Begin of function Town::toggle_town_link ---------//
3577 //
3578 // Toggle the town link of the current town.
3579 //
3580 // NOTE: This function is not used
3581 //
3582 // <int> linkId - id. of the link
3583 // <int> toggleFlag - 1-enable, 0-disable
3584 // [int] setBoth - if this is 1, it will set the link to either LINK_EE or LINK_DD (and no LINK_ED or LINK_DD)
3585 // if this is -1, the only one side will be set even though the nation recno of the firm and town are the same
3586 // (default: 0)
3587 //
toggle_town_link(int linkId,int toggleFlag,char remoteAction,int setBoth)3588 void Town::toggle_town_link(int linkId, int toggleFlag, char remoteAction, int setBoth)
3589 {
3590 // Function is unused, and not updated to support town networks.
3591 return;
3592
3593 if( !remoteAction && remote.is_enable() )
3594 {
3595 // packet structure : <town recno> <link Id> <toggle Flag>
3596 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_TOGGLE_LINK_TOWN, 3*sizeof(short));
3597 shortPtr[0] = town_recno;
3598 shortPtr[1] = linkId;
3599 shortPtr[2] = toggleFlag;
3600 return;
3601 }
3602
3603 int linkedNationRecno = town_array[linked_town_array[linkId-1]]->nation_recno == nation_recno;
3604
3605 int sameNation = linkedNationRecno == nation_recno || // if one of the linked end is an indepdendent firm/nation, consider this link as a single nation link
3606 linkedNationRecno == 0 ||
3607 nation_recno == 0;
3608
3609 if( toggleFlag )
3610 {
3611 if( (sameNation && setBoth==0) || setBoth==1 )
3612 linked_town_enable_array[linkId-1] = LINK_EE;
3613 else
3614 linked_town_enable_array[linkId-1] |= LINK_ED;
3615 }
3616 else
3617 {
3618 if( (sameNation && setBoth==0) || setBoth==1 )
3619 linked_town_enable_array[linkId-1] = LINK_DD;
3620 else
3621 linked_town_enable_array[linkId-1] &= ~LINK_ED;
3622 }
3623
3624 //------ set the linked flag of the opposite town -----//
3625
3626 Town* townPtr = town_array[ linked_town_array[linkId-1] ];
3627 int i;
3628
3629 for(i=townPtr->linked_town_count-1; i>=0; i--)
3630 {
3631 if( townPtr->linked_town_array[i] == town_recno )
3632 {
3633 if( toggleFlag )
3634 {
3635 if( (sameNation && setBoth==0) || setBoth==1 )
3636 townPtr->linked_town_enable_array[i] = LINK_EE;
3637 else
3638 townPtr->linked_town_enable_array[i] |= LINK_DE;
3639 }
3640 else
3641 {
3642 if( (sameNation && setBoth==0) || setBoth==1 )
3643 townPtr->linked_town_enable_array[i] = LINK_DD;
3644 else
3645 townPtr->linked_town_enable_array[i] &= ~LINK_DE;
3646 }
3647
3648 break;
3649 }
3650 }
3651 }
3652 //-------- End of function Town::toggle_town_link ---------//
3653
3654
3655 //-------- Begin of function Town::linked_active_camp_count ------//
3656 //
3657 // No. of linked military camp to this town which has a general in it.
3658 //
linked_active_camp_count()3659 int Town::linked_active_camp_count()
3660 {
3661 int i, linkedCount=0;
3662 Firm* firmPtr;
3663
3664 for( i=0 ; i<linked_firm_count ; i++ )
3665 {
3666 if( linked_firm_enable_array[i] == LINK_EE )
3667 {
3668 firmPtr = firm_array[linked_firm_array[i]];
3669
3670 if( firmPtr->firm_id == FIRM_CAMP &&
3671 firmPtr->overseer_recno )
3672 {
3673 linkedCount++;
3674 }
3675 }
3676 }
3677
3678 return linkedCount;
3679 }
3680 //---------- End of function Town::linked_active_camp_count --------//
3681
3682
3683 //------- Begin of function Town::auto_defense ---------//
3684 //
auto_defense(short targetRecno)3685 void Town::auto_defense(short targetRecno)
3686 {
3687 Firm *firmPtr;
3688 FirmCamp *campPtr;
3689 short townRecno = town_recno;
3690
3691 for(int i=linked_firm_count-1; i>=0; i--)
3692 {
3693 err_when(!linked_firm_array[i] || firm_array.is_deleted(linked_firm_array[i]));
3694 firmPtr = firm_array[linked_firm_array[i]];
3695
3696 if(firmPtr->nation_recno!=nation_recno || firmPtr->firm_id!=FIRM_CAMP)
3697 continue;
3698
3699 //-------------------------------------------------------//
3700 // the firm is a military camp of our nation
3701 //-------------------------------------------------------//
3702 campPtr = firmPtr->cast_to_FirmCamp();
3703 campPtr->defense(targetRecno);
3704
3705 if(town_array.is_deleted(townRecno))
3706 break; // the last unit in the town has be mobilized
3707 }
3708 }
3709 //-------- End of function Town::auto_defense ---------//
3710
3711
3712 //-------- Begin of function Town::cancel_train_unit ------//
cancel_train_unit()3713 void Town::cancel_train_unit()
3714 {
3715 if( train_unit_recno )
3716 {
3717 //### begin alex 17/3 ###//
3718 //unit_array.disappear_in_town(train_unit_recno, town_recno);
3719 //train_unit_recno = 0;
3720
3721 err_when(train_unit_recno==0);
3722 Unit *unitPtr = unit_array[train_unit_recno];
3723 if(unitPtr->spy_recno && unitPtr->skill.skill_id) // check whether the unit is already a spy before training
3724 {
3725 spy_array[unitPtr->spy_recno]->set_place(SPY_TOWN, town_recno);
3726 unitPtr->spy_recno = 0; // reset it so Unit::deinit() won't delete the spy
3727 }
3728
3729 unit_array.disappear_in_town(train_unit_recno, town_recno);
3730 train_unit_recno = 0;
3731 //#### end alex 17/3 ####//
3732 }
3733 }
3734 //----------- End of function Town::cancel_train_unit -----------//
3735
3736
3737 //-------- Begin of function Town::auto_set_layout ------//
3738 //
auto_set_layout()3739 void Town::auto_set_layout()
3740 {
3741 /*
3742 //------ debugging code -----//
3743
3744 static int lastLayoutId=0;
3745
3746 if( ++lastLayoutId > town_res.town_layout_count )
3747 lastLayoutId=1;
3748
3749 layout_id = lastLayoutId;
3750 */
3751 //------------------//
3752
3753 layout_id = think_layout_id();
3754
3755 err_when( !layout_id );
3756
3757 TownLayout* townLayout = town_res.get_layout(layout_id);
3758 TownSlot* firstTownSlot = town_res.get_slot(townLayout->first_slot_recno);
3759 short raceNeedBuildCount[MAX_RACE];
3760
3761 memset( slot_object_id_array, 0, sizeof(slot_object_id_array) );
3762 memset( max_race_pop_array , 0, sizeof(max_race_pop_array) );
3763 memset( raceNeedBuildCount, 0, sizeof(raceNeedBuildCount) );
3764
3765 int i;
3766 for( i=0 ; i<MAX_RACE ; i++ )
3767 {
3768 if( race_pop_array[i] > 0 )
3769 raceNeedBuildCount[i] += (race_pop_array[i]-1)/POPULATION_PER_HOUSE+1;
3770 }
3771
3772 //--- assign the first house to each race, each present race will at least have one house ---//
3773
3774 int firstRaceId = random_race(); // random match
3775 int raceId = firstRaceId;
3776
3777 for( i=0 ; i<townLayout->slot_count ; i++ )
3778 {
3779 if( firstTownSlot[i].build_type == TOWN_OBJECT_HOUSE )
3780 {
3781 int loopCount=0;
3782
3783 while(1) // next race
3784 {
3785 if( ++raceId > MAX_RACE )
3786 raceId = 1;
3787
3788 if( raceId == (firstRaceId==MAX_RACE)?1:(firstRaceId+1) ) // finished the first house for all races
3789 goto label_distribute_house;
3790
3791 if( raceNeedBuildCount[raceId-1] > 0 ) // if this race need buildings, skip all races that do not need buildings
3792 break;
3793
3794 err_when( loopCount++ > 1000 );
3795 }
3796
3797 slot_object_id_array[i] = town_res.scan_build( townLayout->first_slot_recno+i, raceId);
3798
3799 raceNeedBuildCount[raceId-1]--;
3800 max_race_pop_array[raceId-1] += POPULATION_PER_HOUSE;
3801 }
3802 }
3803
3804 err_when( raceId != firstRaceId ); // some races are not assigned with a house
3805
3806 //------- distribute the remaining houses -------//
3807
3808 label_distribute_house:
3809
3810 int bestRaceId, maxNeedBuildCount;
3811
3812 for( i=0 ; i<townLayout->slot_count ; i++ )
3813 {
3814 if( firstTownSlot[i].build_type == TOWN_OBJECT_HOUSE && !slot_object_id_array[i] )
3815 {
3816 bestRaceId=0;
3817 maxNeedBuildCount=0;
3818
3819 for( raceId=1 ; raceId<=MAX_RACE ; raceId++ )
3820 {
3821 if( raceNeedBuildCount[raceId-1] > maxNeedBuildCount )
3822 {
3823 bestRaceId = raceId;
3824 maxNeedBuildCount = raceNeedBuildCount[raceId-1];
3825 }
3826 }
3827
3828 if( !bestRaceId ) // all races have assigned with their needed houses
3829 break;
3830
3831 slot_object_id_array[i] = town_res.scan_build( townLayout->first_slot_recno+i, bestRaceId);
3832 raceNeedBuildCount[bestRaceId-1]--;
3833 max_race_pop_array[bestRaceId-1] += POPULATION_PER_HOUSE;
3834 }
3835 }
3836
3837 //------- set plants in the town layout -------//
3838
3839 for( i=0 ; i<townLayout->slot_count ; i++ )
3840 {
3841 switch(firstTownSlot[i].build_type)
3842 {
3843 case TOWN_OBJECT_PLANT:
3844 slot_object_id_array[i] = plant_res.scan(0, 'T', 0); // 'T'-town only, 1st 0-any zone area, 2nd 0-any terain type, 3rd-age level
3845 break;
3846
3847 case TOWN_OBJECT_FARM:
3848 slot_object_id_array[i] = firstTownSlot[i].build_code;
3849 err_when( slot_object_id_array[i] < 1 || slot_object_id_array[i] > 9 );
3850 break;
3851
3852 case TOWN_OBJECT_HOUSE:
3853 if( !slot_object_id_array[i] )
3854 slot_object_id_array[i] = town_res.scan_build( townLayout->first_slot_recno+i, random_race() );
3855 break;
3856 }
3857 }
3858 }
3859 //---------- End of function Town::auto_set_layout --------//
3860
3861
3862 //-------- Begin of function Town::think_layout_id ------//
3863 //
think_layout_id()3864 int Town::think_layout_id()
3865 {
3866 int i, countDiff;
3867 int needBuildCount=0; // basic buildings needed
3868 int extraBuildCount=0; // extra buildings needed beside the basic one
3869
3870 //---- count the needed buildings of each race ----//
3871
3872 for( i=0 ; i<MAX_RACE ; i++ )
3873 {
3874 if( race_pop_array[i] == 0 )
3875 continue;
3876
3877 needBuildCount++; // essential buildings needed
3878
3879 if( race_pop_array[i] > POPULATION_PER_HOUSE ) // extra buildings, which are not necessary, but will look better if the layout plan fits with this number
3880 extraBuildCount += (race_pop_array[i]-POPULATION_PER_HOUSE-1)/POPULATION_PER_HOUSE+1;
3881 }
3882
3883 //---------- scan the town layout ---------//
3884
3885 int layoutId;
3886 TownLayout* townLayout;
3887
3888 for( layoutId=town_res.town_layout_count ; layoutId>0 ; layoutId-- ) // scan from the most densed layout to the least densed layout
3889 {
3890 townLayout = town_res.get_layout(layoutId);
3891
3892 //--- if this plan has less than the essential need ---//
3893
3894 countDiff = townLayout->build_count - (needBuildCount+extraBuildCount);
3895
3896 if( countDiff==0 ) // the match is perfect, return now
3897 break;
3898
3899 if( countDiff < 0 ) // since we scan from the most densed town layout to the least densed one, if cannot find anyone matched now, there won't be any in the lower positions of the array
3900 {
3901 layoutId = town_res.town_layout_count;
3902 break;
3903 }
3904 }
3905
3906 err_when( layoutId==0 );
3907
3908 //--- if there are more than one layout with the same number of building, pick one randomly ---//
3909
3910 int layoutBuildCount = town_res.get_layout(layoutId)->build_count;
3911 int layoutId2;
3912
3913 for( layoutId2=layoutId-1 ; layoutId2>0 ; layoutId2-- )
3914 {
3915 townLayout = town_res.get_layout(layoutId2);
3916
3917 if( layoutBuildCount != townLayout->build_count )
3918 break;
3919 }
3920
3921 layoutId2++; // the lowest layout id. that has the same no. of buildings
3922
3923 err_when( layoutId2<1 || layoutId2>town_res.town_layout_count );
3924
3925 //------- return the result layout id -------//
3926
3927 return layoutId2 + misc.random(layoutId-layoutId2+1);
3928 }
3929 //---------- End of function Town::think_layout_id --------//
3930
3931
3932 //-------- Begin of function Town::average_loyalty ------//
3933 //
average_loyalty()3934 int Town::average_loyalty()
3935 {
3936 int i, totalLoyalty=0;
3937
3938 for( i=0 ; i<MAX_RACE ; i++ )
3939 totalLoyalty += (int) race_loyalty_array[i] * race_pop_array[i];
3940
3941 return totalLoyalty / population;
3942 }
3943 //---------- End of function Town::average_loyalty --------//
3944
3945
3946 //-------- Begin of function Town::average_target_loyalty ------//
3947 //
average_target_loyalty()3948 int Town::average_target_loyalty()
3949 {
3950 int i, totalLoyalty=0;
3951
3952 for( i=0 ; i<MAX_RACE ; i++ )
3953 totalLoyalty += (int) race_target_loyalty_array[i] * race_pop_array[i];
3954
3955 return totalLoyalty / population;
3956 }
3957 //---------- End of function Town::average_target_loyalty --------//
3958
3959
3960 //------- Begin of function Town::average_resistance --------//
3961 //
3962 // Return the average resistance of all the races in the town
3963 // against a specific nation.
3964 //
average_resistance(int nationRecno)3965 int Town::average_resistance(int nationRecno)
3966 {
3967 int thisPop;
3968 float totalResistance=(float)0;
3969
3970 for( int i=0 ; i<MAX_RACE ; i++ )
3971 {
3972 thisPop = race_pop_array[i];
3973
3974 if( thisPop > 0 )
3975 totalResistance += race_resistance_array[i][nationRecno-1] * thisPop;
3976 }
3977
3978 return int(totalResistance / population);
3979 }
3980 //-------- End of function Town::average_resistance ---------//
3981
3982
3983 //------- Begin of function Town::average_target_resistance --------//
3984 //
3985 // Return the average target resistance of all the races in the town
3986 // against a specific nation.
3987 //
average_target_resistance(int nationRecno)3988 int Town::average_target_resistance(int nationRecno)
3989 {
3990 int thisPop, t, totalResistance=0;
3991
3992 for( int i=0 ; i<MAX_RACE ; i++ )
3993 {
3994 thisPop = race_pop_array[i];
3995
3996 if( thisPop > 0 )
3997 {
3998 t = race_target_resistance_array[i][nationRecno-1];
3999
4000 if( t >= 0 ) // -1 means no target
4001 totalResistance += t * thisPop;
4002 else
4003 totalResistance += (int) race_resistance_array[i][nationRecno-1] * thisPop;
4004 }
4005 }
4006
4007 return int(totalResistance / population);
4008 }
4009 //-------- End of function Town::average_target_resistance ---------//
4010
4011
4012 //-------- Begin of function Town::can_recruit ------//
4013 //
can_recruit(int raceId)4014 int Town::can_recruit(int raceId)
4015 {
4016 //----------------------------------------------------//
4017 // Cannot recruit when you have none of your own camps
4018 // linked to this town, but your enemies have camps
4019 // linked to it.
4020 //----------------------------------------------------//
4021
4022 if( !has_linked_own_camp && has_linked_enemy_camp )
4023 return 0;
4024
4025 if( recruitable_race_pop(raceId,1)==0 )
4026 return 0;
4027
4028 err_when( recruitable_race_pop(raceId,1) < 0 );
4029
4030 //---------------------------------//
4031
4032 int minRecruitLoyalty = MIN_RECRUIT_LOYALTY;
4033
4034 //--- for the AI, only recruit if the loyalty still stay at 30 after recruiting the unit ---//
4035
4036 if(ai_town && nation_recno)
4037 minRecruitLoyalty += 3+recruit_dec_loyalty(raceId, 0); // 0-don't actually decrease it, just return the loyalty to be decreased.
4038
4039 return race_loyalty_array[raceId-1] >= minRecruitLoyalty;
4040 }
4041 //---------- End of function Town::can_recruit --------//
4042
4043
4044 //-------- Begin of function Town::can_train ------//
4045 //
can_train(int raceId)4046 int Town::can_train(int raceId)
4047 {
4048 int recruitableCount = jobless_race_pop_array[raceId-1];
4049
4050 return has_linked_own_camp && recruitableCount > 0 &&
4051 nation_array[nation_recno]->cash > TRAIN_SKILL_COST;
4052 }
4053 //---------- End of function Town::can_train --------//
4054
4055
4056 //-------- Begin of function Town::pick_random_race ------//
4057 //
4058 // Randonly pick a race of town people who live in the town.
4059 //
4060 // <int> pickNonRecruitableAlso - whether also pick units that have jobs.
4061 // <int> pickSpyFlag - whether will pick spies or not.
4062 //
4063 // return: <int> id. of the race picked.
4064 // 0 - no race picked.
4065 //
pick_random_race(int pickNonRecruitableAlso,int pickSpyFlag)4066 int Town::pick_random_race(int pickNonRecruitableAlso, int pickSpyFlag)
4067 {
4068 int totalPop;
4069
4070 if( pickNonRecruitableAlso )
4071 totalPop = population;
4072 else
4073 {
4074 totalPop = jobless_population - (train_unit_recno>0);
4075
4076 if( !pickSpyFlag ) // if don't pick spies
4077 {
4078 for( int i=0 ; i<MAX_RACE ; i++ )
4079 totalPop -= race_spy_count_array[i];
4080
4081 if( totalPop == -1 ) // it can be -1 if the unit being trained is a spy
4082 totalPop = 0;
4083 }
4084
4085 err_when( totalPop < 0 );
4086 }
4087
4088 if( totalPop==0 )
4089 return 0;
4090
4091 int randomPersonId = misc.random(totalPop)+1;
4092 int popSum=0;
4093
4094 for( int i=0 ; i<MAX_RACE ; i++ )
4095 {
4096 if( pickNonRecruitableAlso )
4097 popSum += race_pop_array[i];
4098 else
4099 popSum += recruitable_race_pop(i+1, pickSpyFlag);
4100
4101 if( randomPersonId <= popSum )
4102 return i+1;
4103 }
4104
4105 err_here();
4106 return 0;
4107 }
4108 //---------- End of function Town::pick_random_race --------//
4109
4110
4111 //-------- Begin of function Town::get_most_populated_race ------//
4112 //
4113 // <int&> raceId1, raceId2 - return the id. of the most and
4114 // 2nd most populated races.
4115 //
get_most_populated_race(int & mostRaceId1,int & mostRaceId2)4116 void Town::get_most_populated_race(int& mostRaceId1, int& mostRaceId2)
4117 {
4118 //--- find the two races with most population in the town ---//
4119
4120 int racePop;
4121 int mostRacePop1=0, mostRacePop2=0;
4122
4123 mostRaceId1=0;
4124 mostRaceId2=0;
4125
4126 if( population==0 )
4127 return;
4128
4129 for( int i=0 ; i<MAX_RACE ; i++ )
4130 {
4131 racePop = race_pop_array[i];
4132
4133 if( racePop==0 )
4134 continue;
4135
4136 if( racePop >= mostRacePop1 )
4137 {
4138 mostRacePop2 = mostRacePop1;
4139 mostRacePop1 = racePop;
4140
4141 mostRaceId2 = mostRaceId1;
4142 mostRaceId1 = i+1;
4143 }
4144 else if( racePop >= mostRaceId2 )
4145 {
4146 mostRacePop2 = racePop;
4147 mostRaceId2 = i+1;
4148 }
4149 }
4150 }
4151 //---------- End of function Town::get_most_populated_race --------//
4152
4153
4154 //-------- Begin of function Town::majority_race ------//
4155 //
majority_race()4156 int Town::majority_race()
4157 {
4158 int mostRaceCount=0, mostRaceId=0;
4159
4160 for( int i=0 ; i<MAX_RACE ; i++ )
4161 {
4162 if( race_pop_array[i] > mostRaceCount )
4163 {
4164 mostRaceCount = race_pop_array[i];
4165 mostRaceId = i+1;
4166 }
4167 }
4168
4169 return mostRaceId;
4170 }
4171 //---------- End of function Town::majority_race --------//
4172
4173
4174 //-------- Begin of function Town::recruitable_race_pop ------//
4175 //
4176 // Return the number of units can be recruited from this town.
4177 //
4178 // <int> raceId - id. of the race to recruit
4179 //
4180 // <int> recruitSpy - whether spies will be recruited or not.
4181 // if no, spies are not counted in the
4182 // total no. of units that can be recruited.
4183 //
recruitable_race_pop(int raceId,int recruitSpy)4184 int Town::recruitable_race_pop(int raceId, int recruitSpy)
4185 {
4186 err_when( raceId<1 || raceId>MAX_RACE );
4187
4188 short recruitableCount = jobless_race_pop_array[raceId-1];
4189
4190 if( train_unit_recno && unit_array[train_unit_recno]->race_id==raceId )
4191 recruitableCount--;
4192
4193 if( !recruitSpy )
4194 {
4195 recruitableCount -= race_spy_count_array[raceId-1];
4196
4197 if( recruitableCount == -1 ) // it may have been reduced twice if the unit being trained is a spy
4198 recruitableCount = 0;
4199 }
4200
4201 err_when( recruitableCount < 0 );
4202
4203 return recruitableCount;
4204 }
4205 //---------- End of function Town::recruitable_race_pop --------//
4206
4207
4208 //------ Begin of function Town::verify_slot_object_id_array ------//
4209 //
4210 // This function is for debugging only.
4211 //
verify_slot_object_id_array()4212 void Town::verify_slot_object_id_array()
4213 {
4214 TownLayout* townLayout = town_res.get_layout(layout_id);
4215 TownSlot* townSlot = town_res.get_slot(townLayout->first_slot_recno);
4216
4217 for( int i=0 ; i<townLayout->slot_count ; i++, townSlot++ )
4218 {
4219 //----- build_type==0 if plants -----//
4220
4221 switch(townSlot->build_type)
4222 {
4223 //----- build_type>0 if town buildings -----//
4224
4225 case TOWN_OBJECT_HOUSE:
4226 town_res.get_build( slot_object_id_array[i] );
4227 break;
4228
4229 case TOWN_OBJECT_PLANT:
4230 plant_res.get_bitmap( slot_object_id_array[i] );
4231 break;
4232
4233 case TOWN_OBJECT_FARM:
4234 err_when( slot_object_id_array[i]<1 || slot_object_id_array[i]>9 );
4235 break;
4236 }
4237 }
4238 }
4239 //-------- End of function Town::verify_slot_object_id_array ------//
4240
4241
4242 //----- Begin of function Town::set_auto_collect_tax_loyalty -----//
4243 //
4244 // Note:
4245 //
4246 // Auto collect tax loyalty must always be higher than the auto grant
4247 // loyalty. If the player has set it incorrectly, the program
4248 // will automatically adjust it. e.g. If the player sets the auto
4249 // grant level to 80 while the auto tax level is currently 60,
4250 // the program will adjust auto tax level to 90. And if the player
4251 // sets the auto grant level to 100, auto tax will be disabled.
4252 //
set_auto_collect_tax_loyalty(int loyaltyLevel)4253 void Town::set_auto_collect_tax_loyalty(int loyaltyLevel)
4254 {
4255 auto_collect_tax_loyalty = loyaltyLevel;
4256
4257 if( loyaltyLevel && auto_grant_loyalty >= auto_collect_tax_loyalty )
4258 {
4259 auto_grant_loyalty = auto_collect_tax_loyalty-10;
4260 }
4261 }
4262 //------ End of function Town::set_auto_collect_tax_loyalty -----//
4263
4264
4265 //----- Begin of function Town::set_auto_grant_loyalty -----//
4266 //
set_auto_grant_loyalty(int loyaltyLevel)4267 void Town::set_auto_grant_loyalty(int loyaltyLevel)
4268 {
4269 auto_grant_loyalty = loyaltyLevel;
4270
4271 if( loyaltyLevel && auto_grant_loyalty >= auto_collect_tax_loyalty )
4272 {
4273 auto_collect_tax_loyalty = auto_grant_loyalty+10;
4274
4275 if( auto_collect_tax_loyalty > 100 )
4276 auto_collect_tax_loyalty = 0; // disable auto collect tax if it's over 100
4277 }
4278 }
4279 //------ End of function Town::set_auto_grant_loyalty -----//
4280
4281
4282 //------ Begin of function Town::update_quality_of_life -------//
4283 //
4284 // Quality of life is determined by:
4285 //
4286 // - The provision of goods to the villagers. A more constant
4287 // supply and a bigger variety of goods give to high quality of life.
4288 //
update_quality_of_life()4289 void Town::update_quality_of_life()
4290 {
4291 Firm* firmPtr;
4292 FirmMarket* firmMarket;
4293
4294 //--- calculate the estimated total purchase from this town ----//
4295
4296 float townDemand = (float) jobless_population * (float) PEASANT_GOODS_MONTH_DEMAND
4297 + (float) worker_population() * (float) WORKER_GOODS_MONTH_DEMAND;
4298
4299 float totalPurchase = (float) 0;
4300
4301 for( int i=0 ; i<linked_firm_count ; i++ )
4302 {
4303 if( linked_firm_enable_array[i] != LINK_EE )
4304 continue;
4305
4306 firmPtr = firm_array[ linked_firm_array[i] ];
4307
4308 if( firmPtr->firm_id != FIRM_MARKET )
4309 continue;
4310
4311 firmMarket = (FirmMarket*) firmPtr;
4312
4313 //-------------------------------------//
4314
4315 MarketGoods* marketGoods = firmMarket->market_goods_array;
4316
4317 for( int j=0 ; j<MAX_MARKET_GOODS ; j++, marketGoods++ )
4318 {
4319 if( !marketGoods->product_raw_id || marketGoods->month_demand==0 )
4320 continue;
4321
4322 float monthSaleQty = marketGoods->sale_qty_30days();
4323
4324 if( monthSaleQty > marketGoods->month_demand )
4325 {
4326 totalPurchase += townDemand;
4327 }
4328 else if( marketGoods->month_demand > townDemand )
4329 {
4330 totalPurchase += monthSaleQty * townDemand / marketGoods->month_demand;
4331 }
4332 else
4333 totalPurchase += monthSaleQty;
4334 }
4335 }
4336
4337 //------ return the quality of life ------//
4338
4339 quality_of_life = int( (float)100 * totalPurchase / (townDemand * MAX_PRODUCT) );
4340 }
4341 //----------- End of function Town::update_quality_of_life ---------//
4342
4343
4344 //----- Begin of function Town::has_linked_camp -----//
4345 //
4346 // Return whether there is a camp of the specific nation
4347 // linked to this town.
4348 //
4349 // <int> nationRecno - recno of the nation.
4350 // <int> needOverseer - whether only count camps with overseers or not.
4351 //
has_linked_camp(int nationRecno,int needOverseer)4352 int Town::has_linked_camp(int nationRecno, int needOverseer)
4353 {
4354 Firm* firmPtr;
4355
4356 for( int i=0 ; i<linked_firm_count ; i++ )
4357 {
4358 firmPtr = firm_array[ linked_firm_array[i] ];
4359
4360 if( firmPtr->firm_id == FIRM_CAMP &&
4361 firmPtr->nation_recno == nationRecno )
4362 {
4363 if( !needOverseer || firmPtr->overseer_recno )
4364 return 1;
4365 }
4366 }
4367
4368 return 0;
4369 }
4370 //------ End of function Town::has_linked_camp -----//
4371
4372
4373 //----- Begin of function Town::can_grant_to_non_own_town -----//
4374 //
4375 // Return whether the given nation is allowed to grant to
4376 // this independent town. Only when the nation has a camp (with
4377 // an overseer) linked to the town, the nation will be able
4378 // to grant the independent village.
4379 //
4380 // <int> grantNationRecno - the recno of the nation that
4381 // is going to grant this town.
4382 //
can_grant_to_non_own_town(int grantNationRecno)4383 int Town::can_grant_to_non_own_town(int grantNationRecno)
4384 {
4385 if( nation_recno == grantNationRecno ) // only for independent town
4386 return 0;
4387
4388 if( nation_recno == 0 ) // independent town
4389 {
4390 return has_linked_camp( grantNationRecno, 1 ); // 1-only count camps with overseers
4391 }
4392 else // for nation town, when the enemy doesn't have camps linked to it and the granting nation has camps linked to it
4393 {
4394 return has_linked_camp( nation_recno, 0 )==0 && // 0-count camps regardless of the presence of overseers
4395 has_linked_camp( grantNationRecno, 1 ); // 1-only count camps with overseers
4396 }
4397 }
4398 //------ End of function Town::can_grant_to_non_own_town -----//
4399
4400
4401 //----- Begin of function Town::grant_to_non_own_town -----//
4402 //
4403 // <int> grantNationRecno - the recno of the nation that
4404 // is going to grant this town.
4405 //
grant_to_non_own_town(int grantNationRecno,int remoteAction)4406 int Town::grant_to_non_own_town(int grantNationRecno, int remoteAction)
4407 {
4408 if( !can_grant_to_non_own_town(grantNationRecno) )
4409 return 0;
4410
4411 Nation* grantNation = nation_array[grantNationRecno];
4412
4413 if( grantNation->cash < 0 )
4414 return 0;
4415
4416 if( !remoteAction && remote.is_enable() )
4417 {
4418 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_GRANT_INDEPENDENT, 2*sizeof(short) );
4419 shortPtr[0] = town_recno;
4420 shortPtr[1] = grantNationRecno;
4421 return 1;
4422 }
4423
4424 //---- calculate the resistance to be decreased -----//
4425
4426 int resistanceDec = IND_TOWN_GRANT_RESISTANCE_DECREASE - accumulated_enemy_grant_penalty/5;
4427
4428 resistanceDec = MAX(3, resistanceDec);
4429
4430 accumulated_enemy_grant_penalty += 10;
4431
4432 //------ decrease the resistance of the independent villagers ------//
4433
4434 for( int i=0 ; i<MAX_RACE ; i++ )
4435 {
4436 if( race_pop_array[i]==0 )
4437 continue;
4438
4439 //----- if this is an independent town ------//
4440
4441 if( nation_recno==0 )
4442 {
4443 race_resistance_array[i][grantNationRecno-1] -= resistanceDec;
4444
4445 if( race_resistance_array[i][grantNationRecno-1] < 0 )
4446 race_resistance_array[i][grantNationRecno-1] = (float) 0;
4447 }
4448 else //----- if this is an nation town ------//
4449 {
4450 race_loyalty_array[i] -= resistanceDec;
4451
4452 if( race_loyalty_array[i] < 0 )
4453 race_loyalty_array[i] = (float) 0;
4454 }
4455 }
4456
4457 //----------- decrease cash ------------//
4458
4459 grantNation->add_expense(EXPENSE_GRANT_OTHER_TOWN, (float)population * IND_TOWN_GRANT_PER_PERSON );
4460
4461 return 1;
4462 }
4463 //------ End of function Town::grant_to_non_own_town -----//
4464
4465
4466 //----- Begin of function Town::update_camp_link -----//
4467 //
4468 // Update the status of links from this town to camps.
4469 //
update_camp_link()4470 void Town::update_camp_link()
4471 {
4472 //--- enable the link of the town's side to all linked camps ---//
4473
4474 Firm* firmPtr;
4475
4476 int i;
4477 for( i=0 ; i<linked_firm_count ; i++ )
4478 {
4479 firmPtr = firm_array[linked_firm_array[i]];
4480
4481 if( firmPtr->firm_id != FIRM_CAMP )
4482 continue;
4483
4484 //--- don't set it if the town and camp both belong to a human player, the player will set it himself ---//
4485
4486 if( firmPtr->nation_recno == nation_recno &&
4487 nation_recno && !nation_array[nation_recno]->is_ai() )
4488 {
4489 continue;
4490 }
4491
4492 //--------------------------------------------//
4493
4494 toggle_firm_link( i+1, 1, COMMAND_AUTO );
4495 }
4496
4497 //------- update camp link status -------//
4498
4499 has_linked_own_camp = 0;
4500 has_linked_enemy_camp = 0;
4501
4502 for( i=0 ; i<linked_firm_count ; i++ )
4503 {
4504 if( linked_firm_enable_array[i] != LINK_EE )
4505 continue;
4506
4507 firmPtr = firm_array[linked_firm_array[i]];
4508
4509 if( firmPtr->firm_id!=FIRM_CAMP || !firmPtr->overseer_recno )
4510 continue;
4511
4512 if( firmPtr->nation_recno == nation_recno )
4513 has_linked_own_camp = 1;
4514 else
4515 has_linked_enemy_camp = 1;
4516 }
4517 }
4518 //------ End of function Town::update_camp_link -----//
4519
4520
4521 //------- Begin of function Town::closest_own_camp -------//
4522 //
4523 // Return the firm recno of the camp that is closest to this town.
4524 //
closest_own_camp()4525 int Town::closest_own_camp()
4526 {
4527 Firm *firmPtr;
4528 int curDistance, minDistance=1000, closestFirmRecno=0;
4529
4530 for( int i=linked_firm_count-1 ; i>=0 ; i-- )
4531 {
4532 firmPtr = firm_array[ linked_firm_array[i] ];
4533
4534 if( firmPtr->firm_id != FIRM_CAMP ||
4535 firmPtr->nation_recno != nation_recno )
4536 {
4537 continue;
4538 }
4539
4540 curDistance = misc.points_distance( center_x, center_y,
4541 firmPtr->center_x, firmPtr->center_y );
4542
4543 if( curDistance < minDistance )
4544 {
4545 minDistance = curDistance;
4546 closestFirmRecno = firmPtr->firm_recno;
4547 }
4548 }
4549
4550 return closestFirmRecno;
4551 }
4552 //-------- End of function Town::closest_own_camp ---------//
4553
4554
4555 //-------- Begin of static function random_race --------//
4556 //
4557 // Uses misc.random() for random race
4558 //
random_race()4559 static char random_race()
4560 {
4561 int num = misc.random(config_adv.race_random_list_max);
4562 return config_adv.race_random_list[num];
4563 }
4564 //--------- End of static function random_race ---------//
4565