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    : OSITE.CPP
22 //Description : Object Site
23 
24 #include <OINFO.h>
25 #include <OWORLD.h>
26 #include <OTOWN.h>
27 #include <OFIRM.h>
28 #include <OUNIT.h>
29 #include <ONEWS.h>
30 #include <OGODRES.h>
31 #include <ONATION.h>
32 #include <OSITE.h>
33 #include <OPOWER.h>
34 
35 //-------------- Define constant -----------//
36 
37 #define EXIST_RAW_RESERVE_QTY 		(MAX_RAW_RESERVE_QTY / 20)   // only sites with reserve qty >= 5% of MAX_RAW_RESERVE_QTY are counted as raw sites
38 
39 //--------- Begin of function SiteArray::SiteArray -------//
40 
SiteArray()41 SiteArray::SiteArray() : DynArrayB(sizeof(Site), 50, DEFAULT_REUSE_INTERVAL_DAYS)
42 {
43 }
44 //----------- End of function SiteArray::SiteArray -------//
45 
46 
47 //--------- Begin of function SiteArray::~SiteArray -------//
48 
~SiteArray()49 SiteArray::~SiteArray()
50 {
51 	deinit();
52 }
53 //----------- End of function SiteArray::~SiteArray -------//
54 
55 
56 //--------- Begin of function SiteArray::init -------//
57 
init()58 void SiteArray::init()
59 {
60 	untapped_raw_count = 0;
61 	std_raw_site_count = 0;
62 }
63 //----------- End of function SiteArray::init -------//
64 
65 
66 //--------- Begin of function SiteArray::deinit -------//
67 
deinit()68 void SiteArray::deinit()
69 {
70 	if( size()==0 )
71 		return;
72 
73 	zap();       // zap the DynArrayB
74 
75 	untapped_raw_count = 0;
76 }
77 //----------- End of function SiteArray::deinit -------//
78 
79 
80 //--------- Begin of function SiteArray::add_site ---------//
81 //
82 // Add a raw item to the site array
83 //
84 // Return : 1 - the raw is added
85 //          0 - duplicated, not added
86 //
add_site(int xLoc,int yLoc,int siteType,int objectId,int reserveQty)87 int SiteArray::add_site(int xLoc, int yLoc, int siteType, int objectId, int reserveQty)
88 {
89 	//----- linkin the raw and update raw attribute ----//
90 
91 	Site site;
92 
93 	linkin(&site);
94 
95 	Site* sitePtr = (Site*) get(recno());
96 
97 	sitePtr->init(recno(), siteType, xLoc, yLoc);
98 
99 	sitePtr->object_id 	= objectId;
100 	sitePtr->reserve_qty = reserveQty;
101 
102 	switch( siteType )
103 	{
104 		case SITE_RAW:
105 			untapped_raw_count++;
106 			break;
107 
108 		case SITE_SCROLL:
109 			scroll_count++;
110 			break;
111 
112 		case SITE_GOLD_COIN:
113 			gold_coin_count++;
114 			break;
115 	}
116 
117 	return 1;
118 }
119 //----------- End of function SiteArray::add_site ----------//
120 
121 
122 //--------- Begin of function SiteArray::del_site ----------//
123 //
124 // Delete a specified site.
125 //
126 // <int> siteRecno = the record no. of the site to be deleted
127 //
del_site(int siteRecno)128 void SiteArray::del_site(int siteRecno)
129 {
130 	err_if( siteRecno == 0 )
131 		err_now( "SiteArray::del_site" );
132 
133 	Site* sitePtr = site_array[siteRecno];
134 
135 	switch( sitePtr->site_type )
136 	{
137 		case SITE_RAW:
138 			untapped_raw_count--;
139 			break;
140 
141 		case SITE_SCROLL:
142 			scroll_count--;
143 			break;
144 
145 		case SITE_GOLD_COIN:
146 			gold_coin_count--;
147 			break;
148 	}
149 
150 	//-------------------------------//
151 
152 	sitePtr->deinit();
153 
154 	linkout(siteRecno);
155 
156 	if( siteRecno == site_array.selected_recno )
157 		site_array.selected_recno = 0;
158 }
159 //--------- End of function SiteArray::del_site ----------//
160 
161 
162 //--------- Begin of function SiteArray::generate_raw_site ----------//
163 //
164 // Generate raw sites. This function is both called at the beginning
165 //	of a game and when existing raw sites are being used up.
166 //
167 // [int] rawGenCount - no. of raw sites to be generated.
168 //							  (if this is not given, it will use the existing std_raw_site_count)
169 //
generate_raw_site(int rawGenCount)170 void SiteArray::generate_raw_site(int rawGenCount)
171 {
172 	if( rawGenCount )
173 		std_raw_site_count = rawGenCount;		// use this number for determing whether new sites should emerge in the future
174 
175 	#define MAX_RAW_REGION 			  3		// maximum no. of regions that has raw sites
176 	#define SMALLEST_RAW_REGION	 50 		// only put raw on the region if its size is larger than this
177 	#define REGION_SIZE_PER_RAW  	 100
178 
179 	//----- count the no. of existing raw sites -------//
180 
181 	Site* sitePtr;
182 	int   existRawSiteCount=0;
183 
184 	int i;
185 	for( i=size() ; i>0 ; i-- )
186 	{
187 		if( site_array.is_deleted(i) )
188 			continue;
189 
190 		sitePtr = site_array[i];
191 
192 		if( sitePtr->site_type == SITE_RAW &&
193 			 sitePtr->reserve_qty >= EXIST_RAW_RESERVE_QTY )
194 		{
195 			existRawSiteCount++;
196 		}
197 	}
198 
199 	if( existRawSiteCount >= std_raw_site_count )
200 		return;
201 
202 	//----- check which regions are valid for raw sites -----//
203 
204 	int regionCount = MIN( MAX_RAW_REGION, region_array.region_info_count );
205 	int validRegionCount, totalValidSize=0;
206 	RegionInfo* regionInfo;
207 
208 	for( validRegionCount=0 ; validRegionCount<regionCount ; validRegionCount++ )
209 	{
210 		regionInfo = region_array.get_sorted_region(validRegionCount+1);
211 
212 		if( regionInfo->region_type != REGION_LAND )
213 			continue;
214 
215 		if( regionInfo->region_size < SMALLEST_RAW_REGION )
216 			break;
217 
218 		totalValidSize += regionInfo->region_size;
219 	}
220 
221 	if( validRegionCount==0 )	// valid regions are those that are big enough to put raw sites
222 		return;
223 
224 	//----- count the no. of existing raw sites in each ragion ------//
225 
226 	int   regionId;
227 	char	regionRawCountArray[MAX_REGION];
228 
229 	memset( regionRawCountArray, 0, sizeof(regionRawCountArray) );
230 
231 	for( i=size() ; i>0 ; i-- )
232 	{
233 		if( site_array.is_deleted(i) )
234 			continue;
235 
236 		sitePtr = site_array[i];
237 
238 		if( sitePtr->site_type == SITE_RAW &&
239 			 sitePtr->reserve_qty >= EXIST_RAW_RESERVE_QTY )
240 		{
241 			regionId = world.get_region_id(sitePtr->map_x_loc, sitePtr->map_y_loc);
242 
243 			regionRawCountArray[regionId-1]++;
244 
245 		}
246 	}
247 
248 	//--------- generate raw sites now ----------//
249 
250 	int avgValidSize = MIN( 10000, totalValidSize / std_raw_site_count );
251 	int j, createCount;
252 
253 	err_when( validRegionCount > region_array.region_info_count || validRegionCount > MAX_RAW_REGION );
254 
255 	for( int k=0 ; k<10 ; k++ )		//	one loop may not be enough to generate all raw sites, have more loops to make sure all are generated
256 	{
257 		for( i=0 ; i<regionCount ; i++ )
258 		{
259 			regionInfo = region_array.get_sorted_region(i+1);
260 
261 			if( regionInfo->region_type != REGION_LAND )
262 				continue;
263 
264 			if( regionInfo->region_size < SMALLEST_RAW_REGION )
265 				break;
266 
267 			createCount = regionInfo->region_size / avgValidSize;
268 			createCount = MAX(1, createCount);
269 
270 			//--------- create now --------//
271 
272 			for( j=regionRawCountArray[regionInfo->region_id-1] ; j<createCount ; j++ )	// if currently there are already some, don't create new ones
273 			{
274 				if( create_raw_site(regionInfo->region_id) )
275 				{
276 					if( ++existRawSiteCount == std_raw_site_count )
277 						return;
278 				}
279 			}
280 		}
281 	}
282 }
283 //--------- End of function SiteArray::generate_raw_site ----------//
284 
285 
286 //--------- Begin of function SiteArray::create_raw_site ----------//
287 //
288 // <int> regionId  - if this parameter is given, the raw site
289 //							will be built on this region.
290 // [int] townRecno - if this parameter is given, the raw site
291 //							will be built near this town.
292 //
create_raw_site(int regionId,int townRecno)293 int SiteArray::create_raw_site(int regionId, int townRecno)
294 {
295 	//-------- count the no. of each raw material -------//
296 
297 	Site* sitePtr;
298 	short rawCountArray[MAX_RAW];
299 
300 	memset( rawCountArray, 0, sizeof(rawCountArray) );
301 
302 	int i;
303 	for( i=size(); i>0 ; i-- )
304 	{
305 		if( site_array.is_deleted(i) )
306 			continue;
307 
308 		sitePtr = site_array[i];
309 
310 		if( sitePtr->site_type == SITE_RAW )
311 		{
312 			err_when( sitePtr->object_id < 1 || sitePtr->object_id > MAX_RAW );
313 
314 			rawCountArray[ sitePtr->object_id-1 ]++;
315 		}
316 	}
317 
318 	//---- find the minimum raw count ----//
319 
320 	int minCount=0xFFFF;
321 
322 	for( i=0 ; i<MAX_RAW ; i++ )
323 	{
324 		if( rawCountArray[i] < minCount )
325 			minCount = rawCountArray[i];
326 	}
327 
328 	//----- pick a raw material type -----//
329 
330 	int rawId = misc.random(MAX_RAW)+1;
331 
332 	for( i=0 ; i<MAX_RAW ; i++ )
333 	{
334 		if( ++rawId > MAX_RAW )
335 			rawId = 1;
336 
337 		if( rawCountArray[rawId-1] == minCount )	// don't use this raw type unless it is one of the less available ones.
338 			break;
339 	}
340 
341 	//--------- create the raw site now ------//
342 
343 	int locX1, locY1, locX2, locY2;
344 	int maxTries;
345 
346 	if( townRecno )
347 	{
348 		#define MAX_TOWN_SITE_DISTANCE   10
349 
350 		Town* townPtr = town_array[townRecno];
351 
352 		locX1 = townPtr->center_x - MAX_TOWN_SITE_DISTANCE;
353 		locX2 = townPtr->center_x + MAX_TOWN_SITE_DISTANCE;
354 		locY1 = townPtr->center_y - MAX_TOWN_SITE_DISTANCE;
355 		locY2 = townPtr->center_y + MAX_TOWN_SITE_DISTANCE;
356 
357 		if(locX1<0)
358 			locX1 = 0;
359 		else if(locX2>=MAX_WORLD_X_LOC)
360 			locX2 = MAX_WORLD_X_LOC-1;
361 
362 		if(locY1<0)
363 			locY1 = 0;
364 		else if(locY2>=MAX_WORLD_Y_LOC)
365 			locY2 = MAX_WORLD_Y_LOC-1;
366 
367 		maxTries = (locX2-locX1+1)*(locY2-locY1+1);
368 		regionId = townPtr->region_id;
369 	}
370 	else
371 	{
372 		locX1 = 0;
373 		locY1 = 0;
374 		locX2 = MAX_WORLD_X_LOC-1;
375 		locY2 = MAX_WORLD_Y_LOC-1;
376 
377 		maxTries = 10000;
378 	}
379 
380 	//----- randomly locate a space to add the site -----//
381 
382 	if( world.locate_space_random(locX1, locY1, locX2, locY2,
383 		 5, 5, maxTries, regionId, 1) )     	// 5,5 are the size of the raw site, it must be large enough for a mine to build and 1 location for the edges. The last para 1 = site building mode
384 	{
385 		int reserveQty = MAX_RAW_RESERVE_QTY * (50 + misc.random(50)) / 100;
386 
387 		add_site( locX1+2, locY1+2, SITE_RAW, rawId, reserveQty );		// xLoc+1 & yLoc+1 as the located size is 3x3, the raw site is at the center of it
388 
389 		return 1;
390 	}
391 	else
392 	{
393 		return 0;
394 	}
395 }
396 //--------- End of function SiteArray::create_raw_site ----------//
397 
398 
399 //--------- Begin of function SiteArray::scan_site ----------//
400 //
401 // Scan for the a site that is closest the given location.
402 //
403 // <int> xLoc, yLoc - the location given.
404 // [int] siteType	  - if given, only scan for this site (default: 0)
405 //
406 // return: <int> nearestSiteRecno - the recno of the raw materials
407 //											   that is nearest to the given location.
408 //
scan_site(int xLoc,int yLoc,int siteType)409 int SiteArray::scan_site(int xLoc, int yLoc, int siteType)
410 {
411 	Site* sitePtr;
412 	int   siteDis, minDis=0x7FFFFFFF, nearestSiteRecno=0;
413 
414 	for( int i=site_array.size() ; i>0 ; i-- )
415 	{
416 		if( site_array.is_deleted(i) )
417 			continue;
418 
419 		sitePtr = site_array[i];
420 
421 		if( siteType==0 || sitePtr->site_type==siteType )
422 		{
423 			siteDis = misc.points_distance( xLoc, yLoc, sitePtr->map_x_loc, sitePtr->map_y_loc );
424 
425 			if( siteDis < minDis )
426 			{
427 				minDis 		 	  = siteDis;
428 				nearestSiteRecno = i;
429 			}
430 		}
431 	}
432 
433 	return nearestSiteRecno;
434 }
435 //---------- End of function SiteArray::scan_site -----------//
436 
437 
438 //--------- Begin of function SiteArray::next_day ----------//
439 //
next_day()440 void SiteArray::next_day()
441 {
442 	if( info.game_date%30 == 0 )
443 	{
444 		generate_raw_site();		// check if we need to generate existing raw sites are being used up and if we need to generate new ones
445 	}
446 
447 	//-- if there is any scroll or gold coins available, ask AI to get them --//
448 
449 	if(scroll_count || gold_coin_count)
450 	{
451 		int aiGetSiteObject = (info.game_date%5 == 0);
452 
453 		Site* sitePtr;
454 		Location *locPtr;
455 
456 		for(int i=size(); i; i--)
457 		{
458 			if(is_deleted(i))
459 				continue;
460 
461 			sitePtr = site_array[i];
462 
463 			switch(sitePtr->site_type)
464 			{
465 				case SITE_SCROLL:
466 				case SITE_GOLD_COIN:
467 						locPtr = world.get_loc(sitePtr->map_x_loc, sitePtr->map_y_loc);
468 
469 						//---- if the unit is standing on a scroll site -----//
470 
471 						if(locPtr->has_unit(UNIT_LAND))
472 						{
473 							sitePtr->get_site_object( locPtr->unit_recno(UNIT_LAND) );
474 						}
475 						else if(aiGetSiteObject)
476 						{
477 							sitePtr->ai_get_site_object();
478                   }
479 						break;
480 			}
481 		}
482 	}
483 
484 	//-------- debug testing --------//
485 
486 #ifdef DEBUG
487 
488 	if( info.game_date%10 == 0 )
489 	{
490 		Site* sitePtr;
491 		Location* locPtr;
492 
493 		for( int i=1 ; i<=size() ; i++ )
494 		{
495 			if( site_array.is_deleted(i) )
496 				continue;
497 
498 			sitePtr = site_array[i];
499 
500 			locPtr = world.get_loc( sitePtr->map_x_loc, sitePtr->map_y_loc );
501 
502 			err_when( !locPtr->has_site() );
503 			err_when( locPtr->site_recno() != i );
504 
505 			if( sitePtr->has_mine )
506 			{
507 				err_when( !locPtr->is_firm() );
508 				err_when( firm_array[locPtr->firm_recno()]->firm_id != FIRM_MINE );
509 			}
510 			else
511 			{
512 				err_when( locPtr->is_firm() || locPtr->is_town() );
513 			}
514 		}
515 	}
516 #endif
517 }
518 //--------- End of function SiteArray::next_day ----------//
519 
520 
521 //--------- Begin of function SiteArray::ai_get_site_object -------//
522 //
523 // Notify AI units to acquire scrolls or gold coins available on the
524 // map.
525 //
ai_get_site_object()526 void SiteArray::ai_get_site_object()
527 {
528 	Site* sitePtr;
529 
530 	for( int i=1 ; i<=size() ; i++ )
531 	{
532 		if( site_array.is_deleted(i) )
533 			continue;
534 
535 		sitePtr = site_array[i];
536 
537 		if( sitePtr->site_type == SITE_SCROLL ||
538 			 sitePtr->site_type == SITE_GOLD_COIN )
539 		{
540 			sitePtr->ai_get_site_object();
541 		}
542 	}
543 }
544 //----------- End of function SiteArray::ai_get_site_object -------//
545 
546 
547 //------- Begin of function Site::ai_get_site_object -------//
548 //
549 // Ask AI units around to get the object on this site.
550 //
ai_get_site_object()551 int Site::ai_get_site_object()
552 {
553 	#define NOTIFY_GET_RANGE 	30		// only notify units within this range
554 	#define MAX_UNIT_TO_ORDER  5
555 
556 	int		 xOffset, yOffset;
557 	int		 xLoc, yLoc;
558 	Location* locPtr;
559 	Unit*	    unitPtr;
560 	int		 unitOrderedCount=0;
561 	int 		 siteRaceId = 0;
562 
563 	if( site_type == SITE_SCROLL )
564 		siteRaceId = god_res[object_id]->race_id;
565 
566 	for( int i=2 ; i<NOTIFY_GET_RANGE*NOTIFY_GET_RANGE ; i++ )
567 	{
568 		misc.cal_move_around_a_point(i, NOTIFY_GET_RANGE, NOTIFY_GET_RANGE, xOffset, yOffset);
569 
570 		xLoc = map_x_loc + xOffset;
571 		yLoc = map_y_loc + yOffset;
572 
573 		xLoc = MAX(0, xLoc);
574 		xLoc = MIN(MAX_WORLD_X_LOC-1, xLoc);
575 
576 		yLoc = MAX(0, yLoc);
577 		yLoc = MIN(MAX_WORLD_Y_LOC-1, yLoc);
578 
579 		locPtr = world.get_loc(xLoc, yLoc);
580 
581 		if( !locPtr->has_unit(UNIT_LAND) )
582 			continue;
583 
584 		//------------------------------//
585 
586 		int unitRecno = locPtr->unit_recno(UNIT_LAND);
587 
588 		if( unit_array.is_deleted(unitRecno) )
589 			continue;
590 
591 		unitPtr = unit_array[unitRecno];
592 
593 		if( !unitPtr->race_id || !unitPtr->ai_unit || unitPtr->ai_action_id )
594 			continue;
595 
596 		if( siteRaceId && siteRaceId != unitPtr->race_id )
597 			continue;
598 
599 		unitPtr->move_to(map_x_loc, map_y_loc);
600 
601 		//--- if the unit is just standing next to the site ---//
602 
603 		if( abs(map_x_loc-xLoc)<=1 && abs(map_y_loc-yLoc)<=1 )
604 		{
605 			return 1;
606 		}
607 		else		// order more than one unit to get the site at the same time
608 		{
609 			if( ++unitOrderedCount >= MAX_UNIT_TO_ORDER )
610 				return 1;
611 		}
612 	}
613 
614 	return 0;
615 }
616 //-------- End of function Site::ai_get_site_object -------//
617 
618 
619 //--------- Begin of function SiteArray::go_to_a_raw_site -------//
620 //
621 // Go to an untapped raw site.
622 //
go_to_a_raw_site()623 void SiteArray::go_to_a_raw_site()
624 {
625 	//----- try to locate an untapped raw site -----//
626 
627 	Site* sitePtr;
628 	//### begin alex 22/10 ###//
629 	int arraySize = size();
630 	int i = selected_recno ? selected_recno : 0;
631 	//#### end alex 22/10 ####//
632 
633 	//### begin alex 22/10 ###//
634 	//for( int i=1 ; i<=size() ; i++ )
635 	//{
636 	int j;
637 	for( j=1 ; j<=arraySize ; j++ )
638 	{
639 		if(++i > arraySize)
640 			i = 1;
641 	//#### end alex 22/10 ####//
642 		if( site_array.is_deleted(i) )
643 			continue;
644 
645 		sitePtr = site_array[i];
646 
647 		if( !sitePtr->has_mine )
648 		{
649 			if( world.get_loc(sitePtr->map_x_loc, sitePtr->map_y_loc)->explored() )
650 			{
651 				world.go_loc( sitePtr->map_x_loc, sitePtr->map_y_loc, 1 );		// 1-select the object on the location
652 				return;
653 			}
654 		}
655 	}
656 
657 	//---- if no untapped raw sites left, jump to built mines ----//
658 	//### begin alex 22/10 ###//
659 	i = 1;
660 	if(firm_array.selected_recno)
661 	{
662 		//------- get the site_recno if a mine is selected ---------//
663 		Firm *firmPtr = firm_array[firm_array.selected_recno];
664 		if(firmPtr->firm_id==FIRM_MINE)
665 		{
666 			int x1 = firmPtr->loc_x1;
667 			int y1 = firmPtr->loc_y1;
668 			int x2 = firmPtr->loc_x2;
669 			int y2 = firmPtr->loc_y2;
670 
671 			for(int count=1; count<=arraySize; ++count)
672 			{
673 				if(site_array.is_deleted(count))
674 					continue;
675 
676 				sitePtr = site_array[count];
677 				if(sitePtr->map_x_loc>=x1 && sitePtr->map_x_loc<=x2 && sitePtr->map_y_loc>=y1 && sitePtr->map_y_loc<=y2)
678 				{
679 					i = count;
680 					break;
681 				}
682 			}
683 		}
684 	}
685 	//#### end alex 22/10 ####//
686 
687 	//### begin alex 22/10 ###//
688 	//for( i=1 ; i<=size() ; i++ )
689 	//{
690 	for( j=1 ; j<=arraySize ; j++ )
691 	{
692 		if(++i > arraySize)
693 			i = 1;
694 	//#### end alex 22/10 ####//
695 
696 		if( site_array.is_deleted(i) )
697 			continue;
698 
699 		sitePtr = site_array[i];
700 
701 		if( world.get_loc(sitePtr->map_x_loc, sitePtr->map_y_loc)->explored() )
702 		{
703 			world.go_loc( sitePtr->map_x_loc, sitePtr->map_y_loc, 1 );		// 1-select the object on the location
704 			return;
705 		}
706 	}
707 }
708 //----------- End of function SiteArray::go_to_a_raw_site -------//
709 
710 
711 //--------- Begin of function Site::init ----------//
712 //
init(int siteRecno,int siteType,int xLoc,int yLoc)713 void Site::init(int siteRecno, int siteType, int xLoc, int yLoc)
714 {
715 	site_recno  = siteRecno;
716 	site_type   = siteType;
717 	map_x_loc   = xLoc;
718 	map_y_loc   = yLoc;
719 	has_mine    = 0;
720 
721 	//------- set world's location --------//
722 
723 	Location* locPtr = world.get_loc(xLoc, yLoc);
724 
725 	locPtr->set_site(siteRecno);
726 
727 	region_id = locPtr->region_id;
728 }
729 //---------- End of function Site::init -----------//
730 
731 
732 //--------- Begin of function Site::deinit ----------//
733 //
deinit()734 void Site::deinit()
735 {
736 	//------ reset world's location ---------//
737 
738 	world.get_loc(map_x_loc, map_y_loc)->remove_site();
739 }
740 //---------- End of function Site::deinit -----------//
741 
742 
743 //--------- Begin of function Site::get_site_object ----------//
744 //
745 // An unit takes the object from the site
746 //
747 // <int> unitRecno - recno of the unit that takes the object on the site.
748 //
get_site_object(int unitRecno)749 int Site::get_site_object(int unitRecno)
750 {
751 	Unit* unitPtr = unit_array[unitRecno];
752 	int   objectTaken=0;
753 
754 	if( !unitPtr->nation_recno )
755 		return 0;
756 
757 	//----- if this is a scroll site ------//
758 
759 	if( site_type == SITE_SCROLL )
760 	{
761 		if( god_res[object_id]->race_id == unitPtr->race_id )
762 		{
763 			god_res[object_id]->enable_know(unitPtr->nation_recno);
764 
765 			objectTaken = 1;
766 
767 			news_array.scroll_acquired(unitPtr->nation_recno, god_res[object_id]->race_id );
768 		}
769 	}
770 
771 	//------ if there are gold coins on this site -----//
772 
773 	if( site_type == SITE_GOLD_COIN )
774 	{
775 		nation_array[unitPtr->nation_recno]->add_income(INCOME_TREASURE, object_id);
776 		objectTaken = 1;
777 
778 		if( unitPtr->nation_recno == nation_array.player_recno )
779 			news_array.monster_gold_acquired(object_id);
780 	}
781 
782 	//---- if the object has been taken by the unit ----//
783 
784 	if( objectTaken )
785 	{
786 		site_array.del_site(site_recno);
787 		return 1;
788 	}
789 
790 	return 0;
791 }
792 //---------- End of function Site::get_site_object -----------//
793 
794 
795 //------- Begin of function SiteArray::is_deleted -----//
796 
is_deleted(int recNo)797 int SiteArray::is_deleted(int recNo)
798 {
799 	Site* sitePtr = (Site*) get(recNo);
800 
801 	return !sitePtr || sitePtr->site_type==0;
802 }
803 //--------- End of function SiteArray::is_deleted ----//
804 
805 #ifdef DYNARRAY_DEBUG_ELEMENT_ACCESS
806 
807 //------- Begin of function SiteArray::operator[] -----//
808 
operator [](int recNo)809 Site* SiteArray::operator[](int recNo)
810 {
811 	Site* sitePtr = (Site*) get(recNo);
812 
813 	if( !sitePtr || sitePtr->site_type==0 )
814 		err.run( "SiteArray[] is deleted" );
815 
816 	return sitePtr;
817 }
818 //--------- End of function SiteArray::operator[] ----//
819 
820 
821 //------- Begin of function SiteArray::operator() -----//
822 
operator ()()823 Site* SiteArray::operator()()
824 {
825 	Site* sitePtr = (Site*) get();
826 
827 	if( !sitePtr || sitePtr->site_type==0 )
828 		err.run( "SiteArray[recno()] is deleted" );
829 
830 	return sitePtr;
831 }
832 //--------- End of function SiteArray::operator() ----//
833 
834 #endif
835 
836 
837 //--------- Begin of function SiteArray::disp_next --------//
838 //
839 // Display the next object of the same type.
840 //
841 // <int> seekDir : -1 - display the previous one in the list.
842 // 					  1 - display the next one in the list.
843 //
844 // <int> sameNation - whether display the next object of the same
845 //							 nation only or of any nation.
846 //
disp_next(int seekDir,int sameNation)847 void SiteArray::disp_next(int seekDir, int sameNation)
848 {
849 	if( !selected_recno )
850 		return;
851 
852 	int   siteRecno = selected_recno;
853 	Site* sitePtr   = (*this)[selected_recno];
854 	int   siteType  = sitePtr->site_type;
855 
856 	while(1)
857 	{
858 		if( seekDir < 0 )
859 		{
860 			siteRecno--;
861 
862 			if( siteRecno < 1 )
863 				siteRecno = size();
864 		}
865 		else
866 		{
867 			siteRecno++;
868 
869 			if( siteRecno > size() )
870 				siteRecno = 1;
871 		}
872 
873 		if( is_deleted(siteRecno) )
874 			continue;
875 
876 		sitePtr = (*this)[siteRecno];
877 
878 		//--- check if the location of this site has been explored ---//
879 
880 		if( !world.get_loc(sitePtr->map_x_loc, sitePtr->map_y_loc)->explored() )
881 			continue;
882 
883 		//---------------------------------//
884 
885 		if( sitePtr->site_type == siteType )
886 		{
887 			power.reset_selection();
888 			selected_recno = siteRecno;
889 
890 			world.go_loc( sitePtr->map_x_loc, sitePtr->map_y_loc );
891 			return;
892 		}
893 
894 		//--- if the recno loops back to the starting one ---//
895 
896 		if( siteRecno == selected_recno )
897 			break;
898 	}
899 }
900 //----------- End of function SiteArray::disp_next --------//
901