1 /*
2  * Seven Kingdoms: Ancient Adversaries
3  *
4  * Copyright 1997,1998 Enlight Software Ltd.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 //Filename    : OSPY.CPP
22 //Description : Object Spy
23 
24 #include <OPOWER.h>
25 #include <OGAME.h>
26 #include <ODATE.h>
27 #include <ONEWS.h>
28 #include <OFONT.h>
29 #include <OUNIT.h>
30 #include <OWORLD.h>
31 #include <OBUTTON.h>
32 #include <OFIRM.h>
33 #include <OTOWN.h>
34 #include <ONATION.h>
35 #include <ORACERES.h>
36 #include <OSYS.h>
37 #include <OSPY.h>
38 #include <OREMOTE.h>
39 // ###### begin Gilbert 10/10 #######//
40 #include <OSE.h>
41 // ###### end Gilbert 10/10 #######//
42 #include "gettext.h"
43 
44 
45 //--------- Begin of function Spy::Spy ----------//
46 //
Spy()47 Spy::Spy()
48 {
49 	memset( this, 0, sizeof(Spy) );
50 }
51 //---------- End of function Spy::Spy ----------//
52 
53 
54 //--------- Begin of function Spy::deinit ----------//
55 //
deinit()56 void Spy::deinit()
57 {
58 	set_place(SPY_UNDEFINED, 0);		// reset spy place vars
59 
60 	race_res[race_id]->free_name_id(name_id);
61 
62 	spy_recno = 0;
63 }
64 //---------- End of function Spy::deinit ----------//
65 
66 
67 //--------- Begin of function Spy::set_action_mode ----------//
68 //
set_action_mode(int actionMode)69 void Spy::set_action_mode(int actionMode)
70 {
71 	action_mode = actionMode;
72 }
73 //---------- End of function Spy::set_action_mode ----------//
74 
75 
76 //--------- Begin of function Spy::set_place ----------//
77 //
78 // Meaning of spy_place_para:
79 //
80 // SPY_MOBILE - unit recno of the spy
81 // SPY_TOWN   - town recno
82 // SPY_FIRM   - firm recno
83 // SPY_SHIP	  - unit recno of the ship
84 //
set_place(int spyPlace,int spyPlacePara)85 void Spy::set_place(int spyPlace, int spyPlacePara)
86 {
87 	//----- reset spy counter of the current place ----//
88 
89 	if( spy_place == SPY_FIRM )
90 	{
91 		if( true_nation_recno == nation_array.player_recno )
92 		{
93 			if( !firm_array.is_deleted(spy_place_para) )
94 			{
95 				firm_array[spy_place_para]->player_spy_count--;
96 				err_when( firm_array[spy_place_para]->player_spy_count<0 );
97 			}
98 		}
99 	}
100 
101 	else if( spy_place == SPY_TOWN )
102 	{
103 		if( !town_array.is_deleted(spy_place_para) )
104 		{
105 			town_array[spy_place_para]->race_spy_count_array[race_id-1]--;
106 			err_when( town_array[spy_place_para]->race_spy_count_array[race_id-1]<0 );
107 		}
108 	}
109 
110 	//------- set the spy place now ---------//
111 
112 	spy_place = spyPlace;
113 	spy_place_para = spyPlacePara;
114 
115 	action_mode = SPY_IDLE;		// reset the spy mode
116 
117 	//------- set the spy counter of the new place ------//
118 
119 	if( spy_place == SPY_FIRM )
120 	{
121 		if( true_nation_recno == nation_array.player_recno )
122 			firm_array[spy_place_para]->player_spy_count++;
123 
124 		cloaked_nation_recno = (char) firm_array[spy_place_para]->nation_recno;
125 
126 		if( firm_array[spy_place_para]->nation_recno != true_nation_recno )
127 			notify_cloaked_nation_flag = 1;	// when a spy has been assigned to a firm, its notification flag should be set to 1, so the nation can control it as it is one of its own units
128 	}
129 	else if( spy_place == SPY_TOWN )
130 	{
131 		town_array[spy_place_para]->race_spy_count_array[race_id-1]++;
132 
133 		//-----------------------------------------------------------//
134 		// We need to update it here as this spy may have resigned from
135 		// a foreign firm and go back to its home village. And the
136 		// nation recno of the foreign firm and the home village are
137 		// different.
138 		//-----------------------------------------------------------//
139 
140 		cloaked_nation_recno = (char) town_array[spy_place_para]->nation_recno;
141 
142 		if( town_array[spy_place_para]->nation_recno != true_nation_recno )		// if it's our own town, don't change notify_cloaked_nation_flag
143 			notify_cloaked_nation_flag = 1;
144 	}
145 }
146 //---------- End of function Spy::set_place ----------//
147 
148 
149 //--------- Begin of function Spy::get_loc ----------//
150 //
151 // Return the location of the spy.
152 //
153 // <int&> xLoc, yLoc - vars for returning the locatin.
154 //
get_loc(int & xLoc,int & yLoc)155 int Spy::get_loc(int& xLoc, int& yLoc)
156 {
157 	switch( spy_place )
158 	{
159 		case SPY_FIRM:
160 			if( !firm_array.is_deleted(spy_place_para) )
161 			{
162 				xLoc = firm_array[spy_place_para]->center_x;
163 				yLoc = firm_array[spy_place_para]->center_y;
164 				return 1;
165 			}
166 			break;
167 
168 		case SPY_TOWN:
169 			if( !town_array.is_deleted(spy_place_para) )
170 			{
171 				xLoc = town_array[spy_place_para]->center_x;
172 				yLoc = town_array[spy_place_para]->center_y;
173 				return 1;
174 			}
175 			break;
176 
177 		case SPY_MOBILE:
178 			if( !unit_array.is_deleted(spy_place_para) )
179 			{
180 				xLoc = unit_array[spy_place_para]->next_x_loc();
181 				yLoc = unit_array[spy_place_para]->next_y_loc();
182 				return 1;
183 			}
184 			break;
185 	}
186 
187 	return 0;
188 }
189 //---------- End of function Spy::get_loc ----------//
190 
191 
192 //------ Begin of function Spy::spy_place_nation_recno -------//
193 //
194 // Return the nation recno of the place where the spy stays.
195 //
spy_place_nation_recno()196 int Spy::spy_place_nation_recno()
197 {
198 	if( spy_place == SPY_TOWN )
199 		return town_array[spy_place_para]->nation_recno;
200 
201 	else if( spy_place == SPY_FIRM )
202 		return firm_array[spy_place_para]->nation_recno;
203 
204 	else
205 		return 0;
206 }
207 //-------- End of function Spy::spy_place_nation_recno --------//
208 
209 
210 //--------- Begin of function Spy::next_day ----------//
211 //
next_day()212 void Spy::next_day()
213 {
214 	SpyArrayLock arrayLock;
215 
216 	//------- pay expenses --------//
217 
218 	pay_expense();
219 
220 	//------ when the spy has been exposed -------//
221 
222 	if( exposed_flag )
223 	{
224 		//-- he will be killed immediately unless he is back in his original nation color ---//
225 
226 		if( true_nation_recno != cloaked_nation_recno )
227 		{
228 			get_killed();
229 			return;
230 		}
231 		else
232 			exposed_flag = 0;		// reset exposed_flag.
233 	}
234 
235 	//------ process actions ---------//
236 
237 	if( info.game_date%30 == spy_recno%30 )
238 	{
239 		if( spy_place == SPY_TOWN )
240 			process_town_action();
241 
242 		else if( spy_place == SPY_FIRM )
243 			process_firm_action();
244 	}
245 
246 	//------ increase skill --------//
247 
248 	int rc;
249 
250 	if( action_mode==SPY_IDLE )		// increase slower when in sleep mode
251 		rc = info.game_date%80 == spy_recno%80;
252 	else
253 		rc = info.game_date%40 == spy_recno%40;
254 
255 	if( rc && spy_skill < 100 )
256 		spy_skill++;
257 
258 	//----- update loyalty & think betray -------//
259 
260 	if( info.game_date%60 == spy_recno%60 )
261 	{
262 		update_loyalty();
263 
264 		if( think_betray() )
265 			return;
266 	}
267 
268 	//----------- visit map (for fog of war) ----------//
269 
270 	if( true_nation_recno == nation_array.player_recno )
271 	{
272 		if( spy_place == SPY_TOWN )
273 		{
274 			Town* townPtr = town_array[spy_place_para];
275 			world.visit( townPtr->loc_x1, townPtr->loc_y1, townPtr->loc_x2, townPtr->loc_y2, EXPLORE_RANGE-1 );
276 		}
277 		else if( spy_place == SPY_FIRM )
278 		{
279 			Firm* firmPtr = firm_array[spy_place_para];
280 			world.visit( firmPtr->loc_x1, firmPtr->loc_y1, firmPtr->loc_x2, firmPtr->loc_y2, EXPLORE_RANGE-1 );
281 		}
282 	}
283 
284 	//---------- debug code -----------//
285 
286 #ifdef DEBUG
287 
288 	err_when( race_id<1 || race_id>MAX_RACE );
289 
290 	switch( spy_place )
291 	{
292 		case SPY_MOBILE:
293 		{
294 			Unit* unitPtr = unit_array[spy_place_para];
295 
296 			err_when( unitPtr->rank_id == RANK_KING );
297 			err_when( unitPtr->spy_recno != spy_recno );
298 			err_when( unitPtr->skill.skill_id == SKILL_SPYING );
299 			break;
300 		}
301 
302 		case SPY_TOWN:
303 			err_when( town_array[spy_place_para]->nation_recno != cloaked_nation_recno );
304 			break;
305 
306 		case SPY_FIRM:
307 			err_when( firm_array.is_deleted(spy_place_para) );
308 			{
309 				Firm* firmPtr = firm_array[spy_place_para];
310 
311 				int i;
312 				for( i=0 ; i<firmPtr->worker_count ; i++ )
313 				{
314 					if( firmPtr->worker_array[i].spy_recno==spy_recno )
315 						break;
316 				}
317 
318 				if( i==firmPtr->worker_count )		// not found in worker_array
319 				{
320 					err_when( !firmPtr->overseer_recno ||
321 								 unit_array[firmPtr->overseer_recno]->spy_recno != spy_recno );
322 				}
323 			}
324 			break;
325 	}
326 #endif
327 }
328 //---------- End of function Spy::next_day ----------//
329 
330 
331 //--------- Begin of function Spy::process_town_action ----------//
332 //
process_town_action()333 void Spy::process_town_action()
334 {
335 	SpyArrayLock arrayLock;
336 
337 	Town* townPtr = town_array[spy_place_para];
338 
339 	if( action_mode == SPY_SOW_DISSENT )
340 	{
341 		if( townPtr->race_pop_array[race_id-1] > townPtr->race_spy_count_array[race_id-1] )	// only when there are non-spy people
342 		{
343 			float decValue = (float)spy_skill / 5 / townPtr->race_pop_array[race_id-1];		// the more people there, the longer it takes to decrease the loyalty
344 
345 			//----- if this is an independent town -----//
346 
347 			if( townPtr->nation_recno==0 )
348 			{
349 				townPtr->race_resistance_array[race_id-1][true_nation_recno-1] -= decValue;
350 
351 				if( townPtr->race_resistance_array[race_id-1][true_nation_recno-1] < 0 )
352 					townPtr->race_resistance_array[race_id-1][true_nation_recno-1] = (float) 0;
353 			}
354 
355 			//--- if this is an enemy town, decrease the town people's loyalty ---//
356 
357 			else
358 			{
359 				townPtr->race_loyalty_array[race_id-1] -= decValue;
360 
361 				if( townPtr->race_loyalty_array[race_id-1] < (float) 0 )
362 					townPtr->race_loyalty_array[race_id-1] = (float) 0;
363 			}
364 		}
365 	}
366 }
367 //---------- End of function Spy::process_town_action ----------//
368 
369 
370 //--------- Begin of function Spy::process_firm_action ----------//
371 //
process_firm_action()372 void Spy::process_firm_action()
373 {
374 	SpyArrayLock arrayLock;
375 
376 	Firm* firmPtr = firm_array[spy_place_para];
377 
378 	//---------- Sow Dissent ----------//
379 
380 	if( action_mode == SPY_SOW_DISSENT )
381 	{
382 		//---- decrease the loyalty of the overseer if there is any -----//
383 
384 		if( firmPtr->overseer_recno )
385 		{
386 			Unit* unitPtr = unit_array[firmPtr->overseer_recno];
387 
388 			if( unitPtr->race_id == race_id )
389 			{
390 				if( misc.random(10 - spy_skill/10 + unitPtr->skill.skill_level/10)==0  // a commander with a higher leadership skill will be less influenced by the spy's dissents
391 					 && unitPtr->loyalty>0 )
392 				{
393 					unitPtr->change_loyalty( -1 );
394 				}
395 			}
396 		}
397 
398 		//----- decrease the loyalty of the workers in the firm -----//
399 
400 		Worker* workerPtr = firmPtr->worker_array;
401 
402 		for( int i=0 ; i<firmPtr->worker_count ; i++, workerPtr++ )
403 		{
404 			if( workerPtr->race_id != race_id )
405 				continue;
406 
407 			//---- if the worker lives in a town ----//
408 
409 			if( workerPtr->town_recno )
410 			{
411 				Town* townPtr = town_array[workerPtr->town_recno];
412 				int   raceId  = workerPtr->race_id;
413 
414 				if( townPtr->race_pop_array[raceId-1] > townPtr->race_spy_count_array[raceId-1] )	// only when there are non-spy people
415 				{
416 					townPtr->change_loyalty( raceId, (float) -spy_skill / 5 / townPtr->race_pop_array[raceId-1] );		// the more people there, the longer it takes to decrease the loyalty
417 				}
418 			}
419 			else //---- if the worker does not live in a town ----//
420 			{
421 				if( !workerPtr->spy_recno )		// the loyalty of the spy himself does not change
422 				{
423 					if( misc.random(10-spy_skill/10)==0 && workerPtr->worker_loyalty>0 )
424 						workerPtr->worker_loyalty--;
425 				}
426 			}
427 		}
428 	}
429 }
430 //---------- End of function Spy::process_firm_action ----------//
431 
432 
433 //--------- Begin of function Spy::set_next_action_mode ----------//
434 //
set_next_action_mode()435 void Spy::set_next_action_mode()
436 {
437 	if( spy_place==SPY_TOWN )
438 	{
439 		if( action_mode == SPY_IDLE )
440 			set_action_mode(SPY_SOW_DISSENT);
441 		else
442 			set_action_mode(SPY_IDLE);
443 	}
444 	else if( spy_place==SPY_FIRM )
445 	{
446 		switch( action_mode )
447 		{
448 			case SPY_IDLE:
449 				if( can_sabotage() )
450 				{
451 					set_action_mode(SPY_SABOTAGE);
452 					break;
453 				}
454 
455 			case SPY_SABOTAGE:
456 				set_action_mode(SPY_SOW_DISSENT);
457 				break;
458 
459 			case SPY_SOW_DISSENT:
460 				set_action_mode(SPY_IDLE);
461 				break;
462 		}
463 	}
464 	else
465 		err_here();
466 }
467 //---------- End of function Spy::set_next_action_mode ----------//
468 
469 
470 //--------- Begin of function Spy::can_sabotage ----------//
471 //
can_sabotage()472 int Spy::can_sabotage()
473 {
474 	return spy_place == SPY_FIRM &&
475 			 firm_array[spy_place_para]->firm_id != FIRM_CAMP; 	// no sabotage actino for military camp
476 }
477 //---------- End of function Spy::can_sabotage ----------//
478 
479 
480 //--------- Begin of function Spy::get_killed ----------//
481 //
482 // [int] dispNews - whether display a news message or not
483 //						  (default: 1)
484 //
get_killed(int dispNews)485 void Spy::get_killed(int dispNews)
486 {
487 	SpyArrayLock arrayLock;
488 
489 	//-------- add news --------//
490 
491 	if( true_nation_recno == nation_array.player_recno ||		// the player's spy is killed
492 		 cloaked_nation_recno == nation_array.player_recno )				// a spy cloaked as the player's people is killed in the player's firm or firm
493 	{
494 		news_array.spy_killed(spy_recno);
495 		// ####### begin Gilbert 10/10 #######//
496 		se_ctrl.immediate_sound("SPY_DIE");
497 		// ####### end Gilbert 10/10 #######//
498 	}
499 
500 	//--- If a spy is caught, the spy's nation's reputation wil decrease ---//
501 
502 	nation_array[true_nation_recno]->change_reputation((float)-SPY_KILLED_REPUTATION_DECREASE);
503 
504 	//------- if the spy is in a town -------//
505 
506 	int hostNationRecno=0;
507 	//### begin alex 31/3 ###//
508 	int mobileUnit = 0;
509 	//#### end alex 31/3 ####//
510 
511 	if( spy_place==SPY_TOWN )
512 	{
513 		Town* townPtr = town_array[spy_place_para];
514 
515 		hostNationRecno = townPtr->nation_recno;
516 
517 		townPtr->dec_pop(race_id, 0);
518 	}
519 
520 	//------- if the spy is in a firm -------//
521 
522 	else if( spy_place==SPY_FIRM )
523 	{
524 		Firm* firmPtr = firm_array[spy_place_para];
525 
526 		hostNationRecno = firmPtr->nation_recno;
527 
528 		//------- check if the overseer is the spy -------//
529 
530 		if( firmPtr->overseer_recno )
531 		{
532 			Unit* unitPtr = unit_array[firmPtr->overseer_recno];
533 
534 			if( unitPtr->spy_recno == spy_recno )
535 			{
536 				firmPtr->kill_overseer();
537 				return;
538 			}
539 		}
540 
541 		//---- check if any of the workers is the spy ----//
542 
543 		for( int i=0 ; i<firmPtr->worker_count ; i++ )
544 		{
545 			if( firmPtr->worker_array[i].spy_recno == spy_recno )
546 			{
547 				firmPtr->kill_worker(i+1);
548 				return;
549 			}
550 		}
551 
552 		err_here();		// the spy is not found here
553 	}
554 	else if( spy_place == SPY_MOBILE )
555 	{
556 		//### begin alex 31/3 ###//
557 		//err_here();		// only spies in towns and firms will get killed instantly
558 		unit_array.del(spy_place_para);
559 		mobileUnit = 1;
560 		//#### end alex 31/3 ####//
561 	}
562 	else
563 	{
564 		err_here();
565 	}
566 
567 	//--- If the spy is in an AI town or firm, the AI's relationship towards the spy's owner nation will decrease ---//
568 
569 	if( hostNationRecno && nation_array[hostNationRecno]->is_ai() )
570 	{
571 		nation_array[hostNationRecno]->change_ai_relation_level(true_nation_recno, -5);
572 	}
573 
574 	//---- delete the spy from spy_array ----//
575 	//### begin alex 31/3 ###//
576 	if(!mobileUnit)
577 		spy_array.del_spy(spy_recno);
578 	//else spy_array.del_spy() is called in unit_array.del()
579 	//#### end alex 31/3 ####//
580 }
581 //---------- End of function Spy::get_killed ----------//
582 
583 
584 //--------- Begin of function Spy::action_str ----------//
585 //
action_str()586 const char* Spy::action_str()
587 {
588 	switch( action_mode )
589 	{
590 		case SPY_IDLE:
591 		{
592 			//---- if the spy is in a firm or town of its own nation ---//
593 
594 			if( (spy_place==SPY_TOWN &&
595 				  town_array[spy_place_para]->nation_recno == true_nation_recno) ||
596 				 (spy_place==SPY_FIRM &&
597 				  firm_array[spy_place_para]->nation_recno == true_nation_recno) )
598 			{
599 				return _("Counter-Spy");
600 			}
601 			else
602 				return _("Sleep");
603 		}
604 
605 		case SPY_SOW_DISSENT:
606 			return _("Sow Dissent");
607 
608 		case SPY_SABOTAGE:
609 			return _("Sabotage");
610 
611 		default:
612 			err_here();
613 	}
614 
615 	return "";
616 }
617 //---------- End of function Spy::action_str ----------//
618 
619 
620 //--------- Begin of function Spy::pay_expense ---------//
621 //
622 // -Each spy costs $5 dollars to maintain per month.
623 //
624 // -If your spies are mobile:
625 //  >your nation pays them 1 food and $5 dollars per month
626 //
627 // -If your spies are in an enemy's town or firm:
628 //  >the enemy pays them 1 food and the normal salary of their jobs.
629 //  >your nation pays them $5 dollars per month. (your nation pays them no food)
630 //
631 // -If your spies are in your own town or firm:
632 //  >your nation pays them 1 food and $5 dollars per month
633 //
pay_expense()634 void Spy::pay_expense()
635 {
636 	Nation* nationPtr = nation_array[true_nation_recno];
637 
638 	//---------- reduce cash -----------//
639 
640 	if( nationPtr->cash > 0 )
641 	{
642 		nationPtr->add_expense( EXPENSE_SPY, (float) SPY_YEAR_SALARY / 365, 1 );
643 	}
644 	else     // decrease loyalty if the nation cannot pay the unit
645 	{
646 		change_loyalty(-1);
647 	}
648 
649 	//---------- reduce food -----------//
650 
651 	int inOwnFirm=0;
652 
653 	if( spy_place == SPY_FIRM )
654 	{
655 		Firm* firmPtr = firm_array[spy_place_para];
656 
657 		if( firmPtr->nation_recno == true_nation_recno &&
658 			 firmPtr->overseer_recno &&
659 			 unit_array[firmPtr->overseer_recno]->spy_recno == spy_recno )
660 		{
661 			inOwnFirm = 1;
662 		}
663 	}
664 
665 	if( spy_place == SPY_MOBILE || inOwnFirm )
666 	{
667 		if( nationPtr->food > 0 )
668 		{
669 			nationPtr->consume_food((float) PERSON_FOOD_YEAR_CONSUMPTION / 365);
670 		}
671 		else
672 		{
673 			if( info.game_date%NO_FOOD_LOYALTY_DECREASE_INTERVAL == 0 )		// decrease 1 loyalty point every 2 days
674 				change_loyalty(-1);
675 		}
676 	}
677 }
678 //----------- End of function Spy::pay_expense -----------//
679 
680 
681 //--------- Begin of function Spy::update_loyalty ----------//
682 //
update_loyalty()683 void Spy::update_loyalty()
684 {
685 	Nation* ownNation = nation_array[true_nation_recno];
686 
687 	int targetLoyalty = 50 + (int)ownNation->reputation/4 +
688 							  ownNation->overall_rank_rating()/4;
689 
690 	if( race_id == ownNation->race_id )
691 		targetLoyalty += 20;
692 
693 	targetLoyalty = MIN( targetLoyalty, 100 );
694 
695 	if( spy_loyalty > targetLoyalty )
696 		spy_loyalty--;
697 
698 	else if( spy_loyalty < targetLoyalty )
699 		spy_loyalty++;
700 }
701 //---------- End of function Spy::update_loyalty ----------//
702 
703 
704 //--------- Begin of function Spy::change_loyalty ----------//
705 //
change_loyalty(int changeAmt)706 void Spy::change_loyalty(int changeAmt)
707 {
708 	int newLoyalty = spy_loyalty + changeAmt;
709 
710 	newLoyalty = MAX(0, newLoyalty);
711 
712 	spy_loyalty = MIN(100, newLoyalty);
713 }
714 //---------- End of function Spy::change_loyalty ----------//
715 
716 
717 //--------- Begin of function Spy::think_betray ----------//
718 //
719 // Think about turning towards to the current cloaked nation,
720 // become a normal unit and lose its spy identity.
721 //
think_betray()722 int Spy::think_betray()
723 {
724 	SpyArrayLock arrayLock;
725 
726 	if( spy_loyalty >= UNIT_BETRAY_LOYALTY )		// you when unit is
727 		return 0;
728 
729 	if( cloaked_nation_recno == true_nation_recno || cloaked_nation_recno==0 )
730 		return 0;
731 
732 	//--- think whether the spy should turn towards the nation ---//
733 
734 	Nation* nationPtr = nation_array[cloaked_nation_recno];
735 
736 	int nationScore = (int) nationPtr->reputation;	// reputation can be negative
737 
738 	if( race_res.is_same_race(nationPtr->race_id, race_id) )
739 		nationScore += 30;
740 
741 	if( spy_loyalty < nationScore || spy_loyalty==0 )
742 	{
743 		drop_spy_identity();
744 		return 1;
745 	}
746 
747 	return 0;
748 }
749 //---------- End of function Spy::think_betray ----------//
750 
751 
752 //--------- Begin of function Spy::drop_spy_identity ----------//
753 //
754 // Drop its spy identity. If it is currently cloaked to another
755 // nation, it will become units of that nation.
756 //
drop_spy_identity()757 void Spy::drop_spy_identity()
758 {
759 	SpyArrayLock arrayLock;
760 
761 	if( spy_place == SPY_FIRM )
762 	{
763 		Firm* firmPtr = firm_array[spy_place_para];
764 		int   rc = 0;
765 
766 		if( firmPtr->overseer_recno )
767 		{
768 			Unit* unitPtr = unit_array[firmPtr->overseer_recno];
769 
770 			if( unitPtr->spy_recno == spy_recno )
771 			{
772 				unitPtr->spy_recno = 0;
773 				rc = 1;
774 			}
775 		}
776 
777 		if( !rc )
778 		{
779 			for( int i=0 ; i<firmPtr->worker_count ; i++ )
780 			{
781 				if( firmPtr->worker_array[i].spy_recno==spy_recno )
782 				{
783 					firmPtr->worker_array[i].spy_recno = 0;
784 					rc = 1;
785 					break;
786 				}
787 			}
788 
789 			err_when( !rc );
790 		}
791 	}
792 	else if( spy_place == SPY_MOBILE )
793 	{
794 		Unit* unitPtr = unit_array[spy_place_para];
795 
796 		unitPtr->spy_recno = 0;
797 	}
798 
799 	//------ delete this Spy record from spy_array ----//
800 
801 	spy_array.del_spy(spy_recno);		// Spy::deinit() will take care of the rest of the initialization for the spy
802 }
803 //---------- End of function Spy::drop_spy_identity ----------//
804 
805 
806 //--------- Begin of function Spy::change_true_nation ----------//
807 //
808 // Change the spy's true nation recno.
809 //
change_true_nation(int newNationRecno)810 void Spy::change_true_nation(int newNationRecno)
811 {
812 	SpyArrayLock arrayLock;
813 
814 	err_when( nation_array.is_deleted(newNationRecno) );
815 
816 	true_nation_recno = newNationRecno;
817 
818 	//--- update Firm::player_spy_count if the spy is in a firm ---//
819 
820 	if( spy_place == SPY_FIRM )
821 	{
822 		spy_array.update_firm_spy_count(spy_place_para);
823 	}
824 }
825 //---------- End of function Spy::change_true_nation ----------//
826 
827 
828 //--------- Begin of function Spy::change_cloaked_nation ----------//
829 //
830 // Change a spy's cloaked nation. This nation is when the caller
831 // only have spy_recno as the reference. While Unit::spy_change_nation()
832 // is called when the caller has unit_recno as the reference.
833 //
834 // <int>  newNationRecno - the new nation the spy changes its cloack to
835 //
change_cloaked_nation(int newNationRecno)836 void Spy::change_cloaked_nation(int newNationRecno)
837 {
838 	SpyArrayLock arrayLock;
839 
840 	if( newNationRecno == cloaked_nation_recno )
841 		return;
842 
843 	//--- only mobile units and overseers can change nation, spies in firms or towns cannot change nation, their nation recno must be the same as the town or the firm's nation recno
844 
845 	if( spy_place == SPY_MOBILE )
846 	{
847 		unit_array[spy_place_para]->spy_change_nation(newNationRecno, COMMAND_AUTO);
848 		return;
849 	}
850 	else if( spy_place == SPY_FIRM )
851 	{
852 		Firm* firmPtr = firm_array[spy_place_para];
853 
854 		if( firmPtr->overseer_recno &&
855 			 unit_array[firmPtr->overseer_recno]->spy_recno == spy_recno )
856 		{
857 			unit_array[firmPtr->overseer_recno]->spy_change_nation(newNationRecno, COMMAND_AUTO);
858 			return;
859 		}
860 	}
861 
862 	err_here();		// cannot change a spy's cloaked_nation_recno in a firm and town as the spy's cloaked nation recno must be the same as the firm and town's nation recno
863 }
864 //---------- End of function Spy::change_cloaked_nation ----------//
865 
866 
867 //--------- Begin of function Spy::can_change_cloaked_nation ----------//
868 //
869 // Return whether this spy can change its cloaked to the specific
870 // nation right now.
871 //
872 // <int>  newNationRecno - the new nation the spy changes its cloak to
873 //
can_change_cloaked_nation(int newNationRecno)874 int Spy::can_change_cloaked_nation(int newNationRecno)
875 {
876 	//---- can always change back to its original nation ----//
877 
878 	if( newNationRecno == true_nation_recno )
879 		return 1;
880 
881 	//--- only mobile units and overseers can change nation, spies in firms or towns cannot change nation, their nation recno must be the same as the town or the firm's nation recno
882 
883 	if( spy_place == SPY_MOBILE )
884 	{
885 		return unit_array[spy_place_para]->can_spy_change_nation();
886 	}
887 	else		// can't change in firms or towns.
888 	{
889 		return 0;
890 	}
891 }
892 //---------- End of function Spy::can_change_cloaked_nation ----------//
893 
894 
895 //--------- Begin of function Spy::capture_firm ----------//
896 //
897 // Order the spy to capture the firm he currently stays.
898 //
capture_firm()899 int Spy::capture_firm()
900 {
901 	SpyArrayLock arrayLock;
902 
903 	if( spy_place != SPY_FIRM )
904 		return 0;
905 
906 	Firm* firmPtr = firm_array[spy_place_para];
907 
908 	//------- if the spy is the overseer of the firm --------//
909 
910 	if( firm_res[firmPtr->firm_id]->need_overseer )
911 	{
912 		//-----------------------------------------------------//
913 		//
914 		// If the firm needs an overseer, the firm can only be
915 		// captured if the spy is the overseer of the firm.
916 		//
917 		//-----------------------------------------------------//
918 
919 		if( !firmPtr->overseer_recno ||
920 			 unit_array[firmPtr->overseer_recno]->spy_recno != spy_recno )
921 		{
922 			return 0;
923 		}
924 
925 		//---------------------------------------------------//
926 		//
927 		// For those soldiers who disagree with the spy general will
928 		// leave the command base and attack it. Soldiers who are not
929 		// racially homogenous to the spy general tend to disagree. Also
930 		// if the spy has a higher leadership, there will be a higher
931 		// chance for the soldiers to follow the general.
932 		//
933 		//---------------------------------------------------//
934 
935 		Unit* unitPtr = unit_array[firmPtr->overseer_recno];
936 
937 		if( !firm_res[firmPtr->firm_id]->live_in_town )		// if the workers of the firm do not live in towns
938 		{
939 			Worker* workerPtr = firmPtr->worker_array;
940 			int	  unitLeadership = unitPtr->skill.skill_level;
941 			int	  nationReputation = (int) nation_array[true_nation_recno]->reputation;
942 			int	  obeyChance, obeyFlag;
943 
944 			for( int i=0 ; i<firmPtr->worker_count ; i++, workerPtr++ )
945 			{
946 				//-- if this worker is a spy, it will stay with you --//
947 
948 				if( workerPtr->spy_recno )
949 					continue;
950 
951 				//---- if this is a normal worker -----//
952 
953 				obeyChance = unitLeadership/2 + nationReputation/2;
954 
955 				if( race_res.is_same_race(workerPtr->race_id, race_id) )
956 					obeyChance += 50;
957 
958 				obeyFlag = misc.random(100) < obeyChance; 		// if obeyChance >= 100, all units will object the overseer
959 
960 				//--- if the worker obey, update its loyalty ---//
961 
962 				if( obeyFlag )
963 					workerPtr->worker_loyalty = MAX(UNIT_BETRAY_LOYALTY, obeyChance/2);
964 
965 				//--- if the worker does not obey, it is mobilized and attack the base ---//
966 
967 				else
968 					firmPtr->mobilize_worker(i+1, COMMAND_AUTO);
969 			}
970 		}
971 
972 		//--------- add news message --------//
973 
974 		if( firmPtr->nation_recno == nation_array.player_recno )
975 			news_array.firm_captured(spy_place_para, true_nation_recno, 1);		// 1 - the capturer is a spy
976 
977 		//-------- if this is an AI firm --------//
978 
979 		if( firmPtr->firm_ai )
980 			firmPtr->ai_firm_captured(true_nation_recno);
981 
982 		//----- the spy change nation and capture the firm -------//
983 
984 		unitPtr->spy_change_nation(true_nation_recno, COMMAND_AUTO);
985 	}
986 	else
987 	{
988 		//------ otherwise the spy is a worker of the firm -------//
989 
990 		//---- check whether it's true that the only units in the firms are our spies ---//
991 
992 		Worker* workerPtr = firmPtr->worker_array;
993 
994 		for( int i=0 ; i<firmPtr->worker_count ; i++, workerPtr++ )
995 		{
996 			if( !workerPtr->spy_recno )		// this worker is not a spy
997 				return 0;
998 
999 			if( spy_array[workerPtr->spy_recno]->true_nation_recno != true_nation_recno )
1000 				return 0;							// this worker is a spy, but not belong to the same nation
1001 		}
1002 
1003 		//--------- add news message --------//
1004 
1005 		if( firmPtr->nation_recno == nation_array.player_recno )
1006 			news_array.firm_captured(spy_place_para, true_nation_recno, 1);		// 1 - the capturer is a spy
1007 
1008 		//-------- if this is an AI firm --------//
1009 
1010 		if( firmPtr->firm_ai )
1011 			firmPtr->ai_firm_captured(true_nation_recno);
1012 
1013 		//----- change the firm's nation recno -----//
1014 
1015 		firmPtr->change_nation(true_nation_recno);		// the firm change nation and the spies inside the firm will have their cloaked nation recno changed
1016 	}
1017 
1018 	return 1;
1019 }
1020 //---------- End of function Spy::capture_firm ----------//
1021 
1022 
1023 //-------- Begin of function Spy::mobilize_spy ------//
1024 //
1025 // return: recno of the mobilized unit.
1026 //
mobilize_spy()1027 int Spy::mobilize_spy()
1028 {
1029 	SpyArrayLock arrayLock;
1030 
1031 	switch( spy_place )
1032 	{
1033 		case SPY_TOWN:
1034 			return mobilize_town_spy();
1035 
1036 		case SPY_FIRM:
1037 			return mobilize_firm_spy();
1038 
1039 		case SPY_MOBILE:
1040 			err_when( !unit_array[spy_place_para]->is_visible() );
1041 			return spy_place_para;
1042 
1043 		default:
1044 			return 0;
1045 	}
1046 }
1047 //---------- End of function Spy::mobilize_spy --------//
1048 
1049 
1050 //-------- Begin of function Spy::mobilize_town_spy ------//
1051 //
1052 // [int] decPop - whether need to decrease the population of town when the spy is mobilized.
1053 //					   should set to no when it's calling from training a unit. (default: 1)
1054 //
1055 // return: recno of the mobilized unit.
1056 //
mobilize_town_spy(int decPop)1057 int Spy::mobilize_town_spy(int decPop)
1058 {
1059 	SpyArrayLock arrayLock;
1060 
1061 	err_when( spy_place != SPY_TOWN );
1062 
1063 	if( spy_place != SPY_TOWN )
1064 		return 0;
1065 
1066 	Town* townPtr = town_array[spy_place_para];
1067 
1068 	int unitRecno = townPtr->mobilize_town_people(race_id, decPop, 1);		//1-mobilize spies
1069 
1070 	if( !unitRecno )
1071 		return 0;
1072 
1073 	Unit* unitPtr = unit_array[unitRecno];  // set the spy vars of the mobilized unit
1074 
1075 	err_when( !unitPtr->is_visible() );
1076 
1077 	unitPtr->spy_recno = spy_recno;
1078 	unitPtr->set_name(name_id);		// set the name id. of this unit
1079 
1080 	set_place(SPY_MOBILE, unitRecno);
1081 
1082 	return unitRecno;
1083 }
1084 //---------- End of function Spy::mobilize_town_spy --------//
1085 
1086 
1087 //-------- Begin of function Spy::mobilize_firm_spy ------//
1088 //
1089 // return: <int> unit recno of the spy mobilized.
1090 //
mobilize_firm_spy()1091 int Spy::mobilize_firm_spy()
1092 {
1093 	SpyArrayLock arrayLock;
1094 
1095 	err_when( spy_place != SPY_FIRM );
1096 
1097 	if( spy_place != SPY_FIRM )
1098 		return 0;
1099 
1100 	Firm* firmPtr = firm_array[spy_place_para];
1101 	int 	spyUnitRecno=0;
1102 
1103 	//---- check if the spy is the overseer of the firm -----//
1104 
1105 	if( firmPtr->overseer_recno )
1106 	{
1107 		Unit* unitPtr = unit_array[firmPtr->overseer_recno];
1108 
1109 		if( unitPtr->spy_recno == spy_recno )
1110 			spyUnitRecno = firmPtr->mobilize_overseer();
1111 	}
1112 
1113 	//---- check if the spy is one of the workers of the firm ----//
1114 
1115 	if( !spyUnitRecno )
1116 	{
1117 		int i;
1118 		for( i=0 ; i<firmPtr->worker_count ; i++ )
1119 		{
1120 			if( firmPtr->worker_array[i].spy_recno == spy_recno )
1121 				break;
1122 		}
1123 
1124 		err_when( i==firmPtr->worker_count );
1125 
1126 		//---------- create a mobile unit ---------//
1127 
1128 		spyUnitRecno = firmPtr->mobilize_worker(i+1, COMMAND_AUTO);		// note: mobilize_woker() will decrease Firm::player_spy_count
1129 	}
1130 
1131 	return spyUnitRecno;
1132 }
1133 //---------- End of function Spy::mobilize_firm_spy --------//
1134 
1135 
1136 //-------- Begin of function Spy::think_become_king ------//
1137 //
1138 // If a nation has picked your spy to succeed to the died king,
1139 // you spy will either:
1140 //
1141 // >he captures the entire nation for you.
1142 // >he betrays you and rule his new empire.
1143 //
think_become_king()1144 void Spy::think_become_king()
1145 {
1146 	SpyArrayLock arrayLock;
1147 
1148 	err_when( spy_place != SPY_MOBILE );		// it must be mobile
1149 
1150 	int hisNationPower = nation_array[cloaked_nation_recno]->overall_rating;
1151 	int parentNationPower = nation_array[true_nation_recno]->overall_rating;
1152 
1153 	//--- if his nation is more power than the player's nation, the chance of handing his nation over to his parent nation will be low unless the loyalty is very high ---//
1154 
1155 	int acceptLoyalty = 90 + hisNationPower - parentNationPower;
1156 
1157 	if( spy_loyalty >= acceptLoyalty &&
1158 		 nation_array[cloaked_nation_recno]->is_ai() )	// never will a spy take over the player's nation
1159 	{
1160 		//------ hand his nation over to his parent nation ------//
1161 
1162 		nation_array[cloaked_nation_recno]->surrender(true_nation_recno);
1163 	}
1164 	else //--- betray his parent nation and rule the nation himself ---//
1165 	{
1166 		drop_spy_identity();
1167 	}
1168 }
1169 //---------- End of function Spy::think_become_king --------//
1170 
1171 
1172 //-------- Begin of function Spy::cloaked_rank_id ------//
1173 //
1174 // Return the cloaked rank id. of this spy.
1175 //
cloaked_rank_id()1176 int Spy::cloaked_rank_id()
1177 {
1178 	switch( spy_place )
1179 	{
1180 		case SPY_TOWN:
1181 			return RANK_SOLDIER;
1182 
1183 		case SPY_FIRM:
1184 		{
1185 			Firm* firmPtr = firm_array[spy_place_para];
1186 
1187 			if( firmPtr->overseer_recno &&
1188 				 unit_array[firmPtr->overseer_recno]->spy_recno == spy_recno )
1189 			{
1190 				return RANK_GENERAL;
1191 			}
1192 			else
1193 			{
1194 				return RANK_SOLDIER;
1195 			}
1196 		}
1197 
1198 		case SPY_MOBILE:
1199 			return unit_array[spy_place_para]->rank_id;
1200 
1201 		default:
1202 			return RANK_SOLDIER;
1203 	}
1204 }
1205 //---------- End of function Spy::cloaked_rank_id --------//
1206 
1207 
1208 //-------- Begin of function Spy::cloaked_skill_id ------//
1209 //
1210 // Return the cloaked skill id. of this spy.
1211 //
cloaked_skill_id()1212 int Spy::cloaked_skill_id()
1213 {
1214 	switch( spy_place )
1215 	{
1216 		case SPY_TOWN:
1217 			return 0;
1218 
1219 		case SPY_FIRM:
1220 			return firm_array[spy_place_para]->firm_skill_id;
1221 
1222 		case SPY_MOBILE:
1223 			return unit_array[spy_place_para]->skill.skill_id;
1224 
1225 		default:
1226 			return 0;
1227 	}
1228 }
1229 //---------- End of function Spy::cloaked_skill_id --------//
1230 
1231 
1232 //-------- Begin of function Spy::reward ------//
1233 //
1234 // The owner nation of the spy rewards him.
1235 //
reward(int remoteAction)1236 void Spy::reward(int remoteAction)
1237 {
1238 	if( !remoteAction && remote.is_enable() )
1239 	{
1240 		// packet structure <spy recno>
1241 		short *shortPtr = (short *)remote.new_send_queue_msg(MSG_SPY_REWARD, sizeof(short));
1242 		shortPtr[0] = spy_recno;
1243 		return;
1244 	}
1245 
1246 	change_loyalty(REWARD_LOYALTY_INCREASE);
1247 
1248 	nation_array[true_nation_recno]->add_expense(EXPENSE_REWARD_UNIT, (float)REWARD_COST);
1249 }
1250 //---------- End of function Spy::reward --------//
1251 
1252 
1253 //-------- Begin of function Spy::set_exposed ------//
1254 //
1255 // Enable the exposed_flag of the spy. The spy will get killed
1256 // should when he has been exposed.
1257 //
set_exposed(int remoteAction)1258 void Spy::set_exposed(int remoteAction)
1259 {
1260 	// ##### begin Gilbert 26/9 #######//
1261 	if( !remoteAction && remote.is_enable() )
1262 	{
1263 		// packet structure <spy recno>
1264 		short *shortPtr = (short *)remote.new_send_queue_msg(MSG_SPY_EXPOSED, sizeof(short));
1265 		shortPtr[0] = spy_recno;
1266 		return;
1267 	}
1268 	// ##### end Gilbert 26/9 #######//
1269 	exposed_flag = 1;
1270 }
1271 //---------- End of function Spy::set_exposed --------//
1272 
1273 
1274 //-------- Begin of function Spy::assassinate ------//
1275 //
1276 // <int> targetUnitRecno - the recno of the unit to assassinate.
1277 // <int> remoteAction 	 - remote action type.
1278 //
1279 // If this is a player's spy, the result of the assassination
1280 // will be set to Firm::assassinate_result.
1281 //
assassinate(int targetUnitRecno,int remoteAction)1282 int Spy::assassinate(int targetUnitRecno, int remoteAction)
1283 {
1284 	if( !remoteAction && remote.is_enable() )
1285 	{
1286 		// packet structure <spy recno>
1287 		short *shortPtr = (short *)remote.new_send_queue_msg(MSG_SPY_ASSASSINATE, sizeof(short)*2);
1288 		shortPtr[0] = spy_recno;
1289 		shortPtr[1] = targetUnitRecno;
1290 		return 0;
1291 	}
1292 
1293 	//---------- validate first -----------//
1294 
1295 	if( spy_place != SPY_FIRM )
1296 		return 0;
1297 
1298 	Unit* targetUnit = unit_array[targetUnitRecno];
1299 
1300 	if( targetUnit->unit_mode != UNIT_MODE_OVERSEE )
1301 		return 0;
1302 
1303 	Firm* firmPtr = firm_array[ targetUnit->unit_mode_para ];
1304 
1305 	if( firmPtr->firm_recno != spy_place_para )
1306 		return 0;
1307 
1308 	//---- get the attack and defense rating ----//
1309 
1310 	int attackRating, defenseRating, otherDefenderCount;
1311 
1312 	if( !get_assassinate_rating(targetUnitRecno, attackRating, defenseRating, otherDefenderCount) )
1313 		return 0;
1314 
1315 	//-------------------------------------------//
1316 
1317 	int rc;
1318 	int trueNationRecno = true_nation_recno;		// need to save it first as the spy may be killed later
1319 
1320 	if( attackRating >= defenseRating )
1321 	{
1322 		//--- whether the spy will be get caught and killed in the mission ---//
1323 
1324 		int spyKillFlag = otherDefenderCount > 0 && attackRating - defenseRating < 80;
1325 
1326 		//--- if the unit assassinated is the player's unit ---//
1327 
1328 		if( targetUnit->nation_recno == nation_array.player_recno )
1329 			news_array.unit_assassinated(targetUnit->sprite_recno, spyKillFlag);
1330 
1331 		firmPtr->kill_overseer();
1332 
1333 		//-----------------------------------------------------//
1334 		// If there are other defenders in the firm and
1335 		// the difference between the attack rating and defense rating
1336 		// is small, then then spy will be caught and executed.
1337 		//-----------------------------------------------------//
1338 
1339 		if( spyKillFlag )
1340 		{
1341 			get_killed(0);		// 0 - don't display new message for the spy being killed
1342 
1343 			rc = ASSASSINATE_SUCCEED_KILLED;
1344 		}
1345 		else
1346 		{
1347 			rc = ASSASSINATE_SUCCEED_AT_LARGE;
1348 		}
1349 	}
1350 	else //----- if the assassination fails --------//
1351 	{
1352 		//-- if the spy is attempting to assassinate the player's general or king --//
1353 
1354 		// don't display the below news message as the killing of the spy will already be displayed in news_array.spy_killed()
1355 
1356 //		if( targetUnit->nation_recno == nation_array.player_recno )
1357 //			news_array.assassinator_caught(spy_recno, targetUnit->rank_id);
1358 
1359 		get_killed(0);		// 0 - don't display new message for the spy being killed
1360 
1361 		rc = ASSASSINATE_FAIL;
1362 	}
1363 
1364 	//--- if this firm is the selected firm and the spy is the player's spy ---//
1365 
1366 	if( trueNationRecno == nation_array.player_recno &&
1367 		 firmPtr->firm_recno == firm_array.selected_recno )
1368 	{
1369 		firmPtr->assassinate_result = rc;
1370 		firmPtr->firm_menu_mode = FIRM_MENU_ASSASSINATE_RESULT;
1371 		info.disp();
1372 	}
1373 
1374 	return rc;
1375 }
1376 //---------- End of function Spy::assassinate --------//
1377 
1378 
1379 //-------- Begin of function Spy::get_assassinate_rating ------//
1380 //
get_assassinate_rating(int targetUnitRecno,int & attackRating,int & defenseRating,int & otherDefenderCount)1381 int Spy::get_assassinate_rating(int targetUnitRecno, int& attackRating, int& defenseRating, int& otherDefenderCount)
1382 {
1383 	//---------- validate first -----------//
1384 
1385 	if( spy_place != SPY_FIRM )
1386 		return 0;
1387 
1388 	Unit* targetUnit = unit_array[targetUnitRecno];
1389 
1390 	if( targetUnit->unit_mode != UNIT_MODE_OVERSEE )
1391 		return 0;
1392 
1393 	Firm* firmPtr = firm_array[ targetUnit->unit_mode_para ];
1394 
1395 	if( firmPtr->firm_recno != spy_place_para )
1396 		return 0;
1397 
1398 	//------ get the hit points of the spy ----//
1399 
1400 	int spyHitPoints;
1401 
1402 	int i;
1403 	for( i=0 ; i<firmPtr->worker_count ; i++ )
1404 	{
1405 		if( firmPtr->worker_array[i].spy_recno == spy_recno )
1406 		{
1407 			spyHitPoints = firmPtr->worker_array[i].hit_points;
1408 			break;
1409 		}
1410 	}
1411 
1412 	err_when( i==firmPtr->worker_count );
1413 
1414 	//------ calculate success chance ------//
1415 
1416 	attackRating  = spy_skill + spyHitPoints/2;
1417 	defenseRating = (int) targetUnit->hit_points/2;
1418 	otherDefenderCount=0;
1419 
1420 	if( targetUnit->spy_recno )
1421 		defenseRating += spy_array[targetUnit->spy_recno]->spy_skill;
1422 
1423 	if( targetUnit->rank_id == RANK_KING )
1424 		defenseRating += 50;
1425 
1426 	for( i=0 ; i<firmPtr->worker_count ; i++ )
1427 	{
1428 		int spyRecno = firmPtr->worker_array[i].spy_recno;
1429 
1430 		//------ if this worker is a spy ------//
1431 
1432 		if( spyRecno )
1433 		{
1434 			Spy* spyPtr = spy_array[spyRecno];
1435 
1436 			if( spyPtr->true_nation_recno == true_nation_recno )	// our spy
1437 			{
1438 				attackRating += spyPtr->spy_skill/4;
1439 			}
1440 			else if( spyPtr->true_nation_recno == firmPtr->nation_recno ) // enemy spy
1441 			{
1442 				defenseRating += spyPtr->spy_skill/2;
1443 				otherDefenderCount++;
1444 			}
1445 		}
1446 		else //----- if this worker is not a spy ------//
1447 		{
1448 			defenseRating += 4 + firmPtr->worker_array[i].hit_points/30;
1449 			otherDefenderCount++;
1450 		}
1451 	}
1452 
1453 	//-------- if the assassination succeeds -------//
1454 
1455 	defenseRating += 30 + misc.random(30);
1456 
1457 	return 1;
1458 }
1459 //---------- End of function Spy::get_assassinate_rating --------//
1460