1 /****************************************************************************
2  Freeciv - Copyright (C) 2004 - The Freeciv Team
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 ****************************************************************************/
13 
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17 
18 /* utility */
19 #include "rand.h"
20 #include "string_vector.h"
21 
22 /* common */
23 #include "base.h"
24 #include "game.h"
25 #include "map.h"
26 #include "road.h"
27 
28 #include "extras.h"
29 
30 static struct extra_type extras[MAX_EXTRA_TYPES];
31 
32 static struct extra_type_list *caused_by[EC_LAST];
33 static struct extra_type_list *removed_by[ERM_COUNT];
34 
35 /****************************************************************************
36   Initialize extras structures.
37 ****************************************************************************/
extras_init(void)38 void extras_init(void)
39 {
40   int i;
41 
42   for (i = 0; i < EC_LAST; i++) {
43     caused_by[i] = extra_type_list_new();
44   }
45   for (i = 0; i < ERM_COUNT; i++) {
46     removed_by[i] = extra_type_list_new();
47   }
48 
49   for (i = 0; i < MAX_EXTRA_TYPES; i++) {
50     requirement_vector_init(&(extras[i].reqs));
51     requirement_vector_init(&(extras[i].rmreqs));
52     extras[i].id = i;
53     extras[i].hiders = NULL;
54     extras[i].data.special_idx = -1;
55     extras[i].data.base = NULL;
56     extras[i].data.road = NULL;
57     extras[i].causes = 0;
58     extras[i].rmcauses = 0;
59     extras[i].helptext = NULL;
60   }
61 }
62 
63 /****************************************************************************
64   Free the memory associated with extras
65 ****************************************************************************/
extras_free(void)66 void extras_free(void)
67 {
68   int i;
69 
70   base_types_free();
71   road_types_free();
72 
73   for (i = 0; i < game.control.num_extra_types; i++) {
74     if (extras[i].data.base != NULL) {
75       FC_FREE(extras[i].data.base);
76       extras[i].data.base = NULL;
77     }
78     if (extras[i].data.road != NULL) {
79       FC_FREE(extras[i].data.road);
80       extras[i].data.road = NULL;
81     }
82   }
83 
84   for (i = 0; i < EC_LAST; i++) {
85     extra_type_list_destroy(caused_by[i]);
86     caused_by[i] = NULL;
87   }
88 
89   for (i = 0; i < ERM_COUNT; i++) {
90     extra_type_list_destroy(removed_by[i]);
91     removed_by[i] = NULL;
92   }
93 
94   for (i = 0; i < MAX_EXTRA_TYPES; i++) {
95     requirement_vector_free(&(extras[i].reqs));
96     requirement_vector_free(&(extras[i].rmreqs));
97 
98     if (NULL != extras[i].helptext) {
99       strvec_destroy(extras[i].helptext);
100       extras[i].helptext = NULL;
101     }
102   }
103 
104   extra_type_iterate(pextra) {
105     if (pextra->hiders != NULL) {
106       extra_type_list_destroy(pextra->hiders);
107       pextra->hiders = NULL;
108     }
109   } extra_type_iterate_end;
110 }
111 
112 /**************************************************************************
113   Return the number of extra_types.
114 **************************************************************************/
extra_count(void)115 int extra_count(void)
116 {
117   return game.control.num_extra_types;
118 }
119 
120 /**************************************************************************
121   Return the extra id.
122 **************************************************************************/
extra_number(const struct extra_type * pextra)123 int extra_number(const struct extra_type *pextra)
124 {
125   fc_assert_ret_val(NULL != pextra, -1);
126 
127   return pextra->id;
128 }
129 
130 #ifndef extra_index
131 /**************************************************************************
132   Return the extra index.
133 **************************************************************************/
extra_index(const struct extra_type * pextra)134 int extra_index(const struct extra_type *pextra)
135 {
136   fc_assert_ret_val(NULL != pextra, -1);
137 
138   return pextra - extras;
139 }
140 #endif /* extra_index */
141 
142 /****************************************************************************
143   Return extras type of given id.
144 ****************************************************************************/
extra_by_number(int id)145 struct extra_type *extra_by_number(int id)
146 {
147   fc_assert_ret_val(id >= 0 && id < MAX_EXTRA_TYPES, NULL);
148 
149   return &extras[id];
150 }
151 
152 /****************************************************************************
153   Get extra of the given special
154 ****************************************************************************/
special_extra_get(int spe)155 struct extra_type *special_extra_get(int spe)
156 {
157   struct extra_type_list *elist = extra_type_list_by_cause(EC_SPECIAL);
158 
159   if (spe < extra_type_list_size(elist)) {
160     return extra_type_list_get(elist, spe);
161   }
162 
163   return NULL;
164 }
165 
166 /**************************************************************************
167   Return the (translated) name of the extra type.
168   You don't have to free the return pointer.
169 **************************************************************************/
extra_name_translation(const struct extra_type * pextra)170 const char *extra_name_translation(const struct extra_type *pextra)
171 {
172   return name_translation_get(&pextra->name);
173 }
174 
175 /**************************************************************************
176   Return the (untranslated) rule name of the extra type.
177   You don't have to free the return pointer.
178 **************************************************************************/
extra_rule_name(const struct extra_type * pextra)179 const char *extra_rule_name(const struct extra_type *pextra)
180 {
181   return rule_name_get(&pextra->name);
182 }
183 
184 /**************************************************************************
185   Returns extra type matching rule name or NULL if there is no extra type
186   with such name.
187 **************************************************************************/
extra_type_by_rule_name(const char * name)188 struct extra_type *extra_type_by_rule_name(const char *name)
189 {
190   const char *qs;
191 
192   if (name == NULL) {
193     return NULL;
194   }
195 
196   qs = Qn_(name);
197 
198   extra_type_iterate(pextra) {
199     if (!fc_strcasecmp(extra_rule_name(pextra), qs)) {
200       return pextra;
201     }
202   } extra_type_iterate_end;
203 
204   return NULL;
205 }
206 
207 /**************************************************************************
208   Returns extra type matching the translated name, or NULL if there is no
209   extra type with that name.
210 **************************************************************************/
extra_type_by_translated_name(const char * name)211 struct extra_type *extra_type_by_translated_name(const char *name)
212 {
213   extra_type_iterate(pextra) {
214     if (0 == strcmp(extra_name_translation(pextra), name)) {
215       return pextra;
216     }
217   } extra_type_iterate_end;
218 
219   return NULL;
220 }
221 
222 /**************************************************************************
223   Returns extra type for given cause.
224 **************************************************************************/
extra_type_list_by_cause(enum extra_cause cause)225 struct extra_type_list *extra_type_list_by_cause(enum extra_cause cause)
226 {
227   fc_assert(cause < EC_LAST);
228 
229   return caused_by[cause];
230 }
231 
232 /**************************************************************************
233   Return random extra type for given cause that is native to the tile.
234 **************************************************************************/
rand_extra_for_tile(struct tile * ptile,enum extra_cause cause)235 struct extra_type *rand_extra_for_tile(struct tile *ptile, enum extra_cause cause)
236 {
237   struct extra_type_list *full_list = extra_type_list_by_cause(cause);
238   struct extra_type_list *potential = extra_type_list_new();
239   int options;
240   struct extra_type *selected = NULL;
241 
242   extra_type_list_iterate(full_list, pextra) {
243     if (is_native_tile_to_extra(pextra, ptile)) {
244       extra_type_list_append(potential, pextra);
245     }
246   } extra_type_list_iterate_end;
247 
248   options = extra_type_list_size(potential);
249 
250   if (options > 0) {
251     selected = extra_type_list_get(potential, fc_rand(options));
252   }
253 
254   extra_type_list_destroy(potential);
255 
256   return selected;
257 }
258 
259 /**************************************************************************
260   Add extra type to list of extra caused by given cause.
261 **************************************************************************/
extra_to_caused_by_list(struct extra_type * pextra,enum extra_cause cause)262 void extra_to_caused_by_list(struct extra_type *pextra, enum extra_cause cause)
263 {
264   fc_assert(cause < EC_LAST);
265 
266   extra_type_list_append(caused_by[cause], pextra);
267 }
268 
269 /**************************************************************************
270   Returns extra type for given rmcause.
271 **************************************************************************/
extra_type_list_by_rmcause(enum extra_rmcause rmcause)272 struct extra_type_list *extra_type_list_by_rmcause(enum extra_rmcause rmcause)
273 {
274   fc_assert(rmcause < ERM_COUNT);
275 
276   return removed_by[rmcause];
277 }
278 
279 /**************************************************************************
280   Add extra type to list of extra removed by given cause.
281 **************************************************************************/
extra_to_removed_by_list(struct extra_type * pextra,enum extra_rmcause rmcause)282 void extra_to_removed_by_list(struct extra_type *pextra,
283                               enum extra_rmcause rmcause)
284 {
285   fc_assert(rmcause < ERM_COUNT);
286 
287   extra_type_list_append(removed_by[rmcause], pextra);
288 }
289 
290 /**************************************************************************
291   Is given cause one of the removal causes for the given extra?
292 **************************************************************************/
is_extra_removed_by(const struct extra_type * pextra,enum extra_rmcause rmcause)293 bool is_extra_removed_by(const struct extra_type *pextra,
294                          enum extra_rmcause rmcause)
295 {
296   return (pextra->rmcauses & (1 << rmcause));
297 }
298 
299 /****************************************************************************
300   Is there extra of the given type cardinally near tile?
301   (Does not check ptile itself.)
302 ****************************************************************************/
is_extra_card_near(const struct tile * ptile,const struct extra_type * pextra)303 bool is_extra_card_near(const struct tile *ptile, const struct extra_type *pextra)
304 {
305   cardinal_adjc_iterate(ptile, adjc_tile) {
306     if (tile_has_extra(adjc_tile, pextra)) {
307       return TRUE;
308     }
309   } cardinal_adjc_iterate_end;
310 
311   return FALSE;
312 }
313 
314 /****************************************************************************
315   Is there extra of the given type near tile?
316   (Does not check ptile itself.)
317 ****************************************************************************/
is_extra_near_tile(const struct tile * ptile,const struct extra_type * pextra)318 bool is_extra_near_tile(const struct tile *ptile, const struct extra_type *pextra)
319 {
320   adjc_iterate(ptile, adjc_tile) {
321     if (tile_has_extra(adjc_tile, pextra)) {
322       return TRUE;
323     }
324   } adjc_iterate_end;
325 
326   return FALSE;
327 }
328 
329 /****************************************************************************
330   Tells if extra can build to tile if all other requirements are met.
331 ****************************************************************************/
extra_can_be_built(const struct extra_type * pextra,const struct tile * ptile)332 bool extra_can_be_built(const struct extra_type *pextra,
333                         const struct tile *ptile)
334 {
335   if (!pextra->buildable) {
336     /* Extra type not buildable */
337     return FALSE;
338   }
339 
340   if (tile_has_extra(ptile, pextra)) {
341     /* Extra exist already */
342     return FALSE;
343   }
344 
345   return TRUE;
346 }
347 
348 /****************************************************************************
349   Tells if player can build extra to tile with suitable unit.
350 ****************************************************************************/
can_build_extra_base(const struct extra_type * pextra,const struct player * pplayer,const struct tile * ptile)351 static bool can_build_extra_base(const struct extra_type *pextra,
352                                  const struct player *pplayer,
353                                  const struct tile *ptile)
354 {
355   if (is_extra_caused_by(pextra, EC_BASE)
356       && !base_can_be_built(extra_base_get(pextra), ptile)) {
357     return FALSE;
358   }
359 
360   if (is_extra_caused_by(pextra, EC_ROAD)
361       && !can_build_road_base(extra_road_get(pextra), pplayer, ptile)) {
362     return FALSE;
363   }
364 
365   if (!extra_can_be_built(pextra, ptile)) {
366     return FALSE;
367   }
368 
369   return TRUE;
370 }
371 
372 /****************************************************************************
373   Tells if player can build extra to tile with suitable unit.
374 ****************************************************************************/
player_can_build_extra(const struct extra_type * pextra,const struct player * pplayer,const struct tile * ptile)375 bool player_can_build_extra(const struct extra_type *pextra,
376                             const struct player *pplayer,
377                             const struct tile *ptile)
378 {
379   if (!can_build_extra_base(pextra, pplayer, ptile)) {
380     return FALSE;
381   }
382 
383   return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
384                          NULL, NULL, NULL, NULL, &pextra->reqs,
385                          RPT_POSSIBLE);
386 }
387 
388 /****************************************************************************
389   Tells if unit can build extra on tile.
390 ****************************************************************************/
can_build_extra(const struct extra_type * pextra,const struct unit * punit,const struct tile * ptile)391 bool can_build_extra(const struct extra_type *pextra,
392                      const struct unit *punit,
393                      const struct tile *ptile)
394 {
395   struct player *pplayer = unit_owner(punit);
396 
397   if (!can_build_extra_base(pextra, pplayer, ptile)) {
398     return FALSE;
399   }
400 
401   return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
402                          punit, unit_type_get(punit), NULL, NULL, &pextra->reqs,
403                          RPT_CERTAIN);
404 }
405 
406 /****************************************************************************
407   Is it possible at all to remove this extra now
408 ****************************************************************************/
can_extra_be_removed(const struct extra_type * pextra,const struct tile * ptile)409 static bool can_extra_be_removed(const struct extra_type *pextra,
410                                  const struct tile *ptile)
411 {
412   struct city *pcity = tile_city(ptile);
413 
414   /* Cannot remove EF_ALWAYS_ON_CITY_CENTER extras from city center. */
415   if (pcity != NULL) {
416     if (extra_has_flag(pextra, EF_ALWAYS_ON_CITY_CENTER)) {
417       return FALSE;
418     }
419     if (extra_has_flag(pextra, EF_AUTO_ON_CITY_CENTER)) {
420       struct tile *vtile = tile_virtual_new(ptile);
421 
422       /* Would extra get rebuilt if removed */
423       tile_remove_extra(vtile, pextra);
424       if (player_can_build_extra(pextra, city_owner(pcity), vtile)) {
425         /* No need to worry about conflicting extras - extra would had
426          * not been here if conflicting one is. */
427         tile_virtual_destroy(vtile);
428 
429         return FALSE;
430       }
431 
432       tile_virtual_destroy(vtile);
433     }
434   }
435 
436   return TRUE;
437 }
438 
439 /****************************************************************************
440   Tells if player can remove extra from tile with suitable unit.
441 ****************************************************************************/
player_can_remove_extra(const struct extra_type * pextra,const struct player * pplayer,const struct tile * ptile)442 bool player_can_remove_extra(const struct extra_type *pextra,
443                              const struct player *pplayer,
444                              const struct tile *ptile)
445 {
446   if (!can_extra_be_removed(pextra, ptile)) {
447     return FALSE;
448   }
449 
450   return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
451                          NULL, NULL, NULL, NULL, &pextra->rmreqs,
452                          RPT_POSSIBLE);
453 }
454 
455 /****************************************************************************
456   Tells if unit can remove extra from tile.
457 ****************************************************************************/
can_remove_extra(const struct extra_type * pextra,const struct unit * punit,const struct tile * ptile)458 bool can_remove_extra(const struct extra_type *pextra,
459                       const struct unit *punit,
460                       const struct tile *ptile)
461 {
462   struct player *pplayer;
463 
464   if (!can_extra_be_removed(pextra, ptile)) {
465     return FALSE;
466   }
467 
468   pplayer = unit_owner(punit);
469 
470   return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
471                          punit, unit_type_get(punit), NULL, NULL,
472                          &pextra->rmreqs, RPT_CERTAIN);
473 }
474 
475 /****************************************************************************
476   Is tile native to extra?
477 ****************************************************************************/
is_native_tile_to_extra(const struct extra_type * pextra,const struct tile * ptile)478 bool is_native_tile_to_extra(const struct extra_type *pextra,
479                              const struct tile *ptile)
480 {
481   struct terrain *pterr = tile_terrain(ptile);
482 
483   if (is_extra_caused_by(pextra, EC_IRRIGATION)
484       && pterr->irrigation_result != pterr) {
485     return FALSE;
486   }
487 
488   if (is_extra_caused_by(pextra, EC_MINE)
489       && pterr->mining_result != pterr) {
490     return FALSE;
491   }
492 
493   if (is_extra_caused_by(pextra, EC_BASE)) {
494     if (pterr->base_time == 0) {
495       return FALSE;
496     }
497     if (tile_city(ptile) != NULL && extra_base_get(pextra)->border_sq >= 0) {
498       return FALSE;
499     }
500   }
501 
502   if (is_extra_caused_by(pextra, EC_ROAD)) {
503     struct road_type *proad = extra_road_get(pextra);
504 
505     if (road_has_flag(proad, RF_RIVER)) {
506       if (!terrain_has_flag(pterr, TER_CAN_HAVE_RIVER)) {
507         return FALSE;
508       }
509     } else if (pterr->road_time == 0) {
510       return FALSE;
511     }
512   }
513 
514   return are_reqs_active(NULL, NULL, NULL, NULL, ptile,
515                          NULL, NULL, NULL, NULL,
516                          &pextra->reqs, RPT_POSSIBLE);
517 }
518 
519 /****************************************************************************
520   Returns next extra by cause that unit or player can build to tile.
521 ****************************************************************************/
next_extra_for_tile(const struct tile * ptile,enum extra_cause cause,const struct player * pplayer,const struct unit * punit)522 struct extra_type *next_extra_for_tile(const struct tile *ptile, enum extra_cause cause,
523                                        const struct player *pplayer,
524                                        const struct unit *punit)
525 {
526   if (cause == EC_IRRIGATION) {
527     struct terrain *pterrain = tile_terrain(ptile);
528 
529     if (pterrain->irrigation_result != pterrain) {
530       /* No extra can be created by irrigation the tile */
531       return NULL;
532     }
533   }
534   if (cause == EC_MINE) {
535     struct terrain *pterrain = tile_terrain(ptile);
536 
537     if (pterrain->mining_result != pterrain) {
538       /* No extra can be created by mining the tile */
539       return NULL;
540     }
541   }
542 
543   extra_type_by_cause_iterate(cause, pextra) {
544     if (!tile_has_extra(ptile, pextra)) {
545       if (punit != NULL) {
546         if (can_build_extra(pextra, punit, ptile)) {
547           return pextra;
548         }
549       } else {
550         /* punit is certainly NULL, pplayer can be too */
551         if (player_can_build_extra(pextra, pplayer, ptile)) {
552           return pextra;
553         }
554       }
555     }
556   } extra_type_by_cause_iterate_end;
557 
558   return NULL;
559 }
560 
561 /****************************************************************************
562   Returns prev extra by cause that unit or player can remove from tile.
563 ****************************************************************************/
prev_extra_in_tile(const struct tile * ptile,enum extra_rmcause rmcause,const struct player * pplayer,const struct unit * punit)564 struct extra_type *prev_extra_in_tile(const struct tile *ptile,
565                                       enum extra_rmcause rmcause,
566                                       const struct player *pplayer,
567                                       const struct unit *punit)
568 {
569   fc_assert(punit != NULL || pplayer != NULL);
570 
571   extra_type_by_rmcause_iterate(rmcause, pextra) {
572     if (tile_has_extra(ptile, pextra)) {
573       if (punit != NULL) {
574         if (can_remove_extra(pextra, punit, ptile)) {
575           return pextra;
576         }
577       } else {
578         if (player_can_remove_extra(pextra, pplayer, ptile)) {
579           return pextra;
580         }
581       }
582     }
583   } extra_type_by_rmcause_iterate_end;
584 
585   return NULL;
586 }
587 
588 /****************************************************************************
589   Is extra native to unit class?
590 ****************************************************************************/
is_native_extra_to_uclass(const struct extra_type * pextra,const struct unit_class * pclass)591 bool is_native_extra_to_uclass(const struct extra_type *pextra,
592                                const struct unit_class *pclass)
593 {
594   return BV_ISSET(pextra->native_to, uclass_index(pclass));
595 }
596 
597 /****************************************************************************
598   Is extra native to unit type?
599 ****************************************************************************/
is_native_extra_to_utype(const struct extra_type * pextra,const struct unit_type * punittype)600 bool is_native_extra_to_utype(const struct extra_type *pextra,
601                               const struct unit_type *punittype)
602 {
603   return is_native_extra_to_uclass(pextra, utype_class(punittype));
604 }
605 
606 /****************************************************************************
607   Check if extra has given flag
608 ****************************************************************************/
extra_has_flag(const struct extra_type * pextra,enum extra_flag_id flag)609 bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
610 {
611   return BV_ISSET(pextra->flags, flag);
612 }
613 
614 /****************************************************************************
615   Returns TRUE iff any cardinally adjacent tile contains an extra with
616   the given flag (does not check ptile itself).
617 ****************************************************************************/
is_extra_flag_card_near(const struct tile * ptile,enum extra_flag_id flag)618 bool is_extra_flag_card_near(const struct tile *ptile, enum extra_flag_id flag)
619 {
620   extra_type_iterate(pextra) {
621     if (extra_has_flag(pextra, flag)) {
622       cardinal_adjc_iterate(ptile, adjc_tile) {
623         if (tile_has_extra(adjc_tile, pextra)) {
624           return TRUE;
625         }
626       } cardinal_adjc_iterate_end;
627     }
628   } extra_type_iterate_end;
629 
630   return FALSE;
631 }
632 
633 /****************************************************************************
634   Returns TRUE iff any adjacent tile contains an extra with the given flag
635   (does not check ptile itself).
636 ****************************************************************************/
is_extra_flag_near_tile(const struct tile * ptile,enum extra_flag_id flag)637 bool is_extra_flag_near_tile(const struct tile *ptile, enum extra_flag_id flag)
638 {
639   extra_type_iterate(pextra) {
640     if (extra_has_flag(pextra, flag)) {
641       adjc_iterate(ptile, adjc_tile) {
642         if (tile_has_extra(adjc_tile, pextra)) {
643           return TRUE;
644         }
645       } adjc_iterate_end;
646     }
647   } extra_type_iterate_end;
648 
649   return FALSE;
650 }
651 
652 /**************************************************************************
653   Can two extras coexist in same tile?
654 **************************************************************************/
can_extras_coexist(const struct extra_type * pextra1,const struct extra_type * pextra2)655 bool can_extras_coexist(const struct extra_type *pextra1,
656                         const struct extra_type *pextra2)
657 {
658   if (pextra1 == pextra2) {
659     return TRUE;
660   }
661 
662   return !BV_ISSET(pextra1->conflicts, extra_index(pextra2));
663 }
664 
665 /**************************************************************************
666   Does the extra count toward environment upset?
667 **************************************************************************/
extra_causes_env_upset(struct extra_type * pextra,enum environment_upset_type upset)668 bool extra_causes_env_upset(struct extra_type *pextra,
669                             enum environment_upset_type upset)
670 {
671   switch (upset) {
672   case EUT_GLOBAL_WARMING:
673     return extra_has_flag(pextra, EF_GLOBAL_WARMING);
674   case EUT_NUCLEAR_WINTER:
675     return extra_has_flag(pextra, EF_NUCLEAR_WINTER);
676   }
677 
678   return FALSE;
679 }
680 
681 /**************************************************************************
682   Is the extra caused by some kind of worker action?
683 **************************************************************************/
is_extra_caused_by_worker_action(const struct extra_type * pextra)684 bool is_extra_caused_by_worker_action(const struct extra_type *pextra)
685 {
686   /* Is any of the worker build action bits set? */
687   return (pextra->causes
688           & (1 << EC_IRRIGATION
689              | 1 << EC_MINE
690              | 1 << EC_BASE
691              | 1 << EC_ROAD));
692 }
693 
694 /**************************************************************************
695   Is the extra removed by some kind of worker action?
696 **************************************************************************/
is_extra_removed_by_worker_action(const struct extra_type * pextra)697 bool is_extra_removed_by_worker_action(const struct extra_type *pextra)
698 {
699   /* Is any of the worker remove action bits set? */
700   return (pextra->rmcauses
701           & (1 << ERM_CLEANPOLLUTION
702              | 1 << ERM_CLEANFALLOUT
703              | 1 << ERM_PILLAGE));
704 }
705 
706 /**************************************************************************
707   Is the extra caused by specific worker action?
708 **************************************************************************/
is_extra_caused_by_action(const struct extra_type * pextra,enum unit_activity act)709 bool is_extra_caused_by_action(const struct extra_type *pextra,
710                                enum unit_activity act)
711 {
712   return is_extra_caused_by(pextra, activity_to_extra_cause(act));
713 }
714 
715 /**************************************************************************
716   Is the extra removed by specific worker action?
717 **************************************************************************/
is_extra_removed_by_action(const struct extra_type * pextra,enum unit_activity act)718 bool is_extra_removed_by_action(const struct extra_type *pextra,
719                                 enum unit_activity act)
720 {
721   return is_extra_removed_by(pextra, activity_to_extra_rmcause(act));
722 }
723 
724 /**************************************************************************
725   What extra cause activity is considered to be?
726 **************************************************************************/
activity_to_extra_cause(enum unit_activity act)727 enum extra_cause activity_to_extra_cause(enum unit_activity act)
728 {
729   switch(act) {
730   case ACTIVITY_IRRIGATE:
731     return EC_IRRIGATION;
732   case ACTIVITY_MINE:
733     return EC_MINE;
734   case ACTIVITY_BASE:
735     return EC_BASE;
736   case ACTIVITY_GEN_ROAD:
737     return EC_ROAD;
738   default:
739     break;
740   }
741 
742   return EC_NONE;
743 }
744 
745 /**************************************************************************
746   What extra rmcause activity is considered to be?
747 **************************************************************************/
activity_to_extra_rmcause(enum unit_activity act)748 enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
749 {
750   switch(act) {
751   case ACTIVITY_PILLAGE:
752     return ERM_PILLAGE;
753   case ACTIVITY_POLLUTION:
754     return ERM_CLEANPOLLUTION;
755   case ACTIVITY_FALLOUT:
756     return ERM_CLEANFALLOUT;
757   default:
758     break;
759   }
760 
761   return ERM_NONE;
762 }
763 
764 /**************************************************************************
765   Who owns extras on tile
766 **************************************************************************/
extra_owner(const struct tile * ptile)767 struct player *extra_owner(const struct tile *ptile)
768 {
769   return ptile->extras_owner;
770 }
771