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 #ifdef HAVE_CONFIG_H
14 #include <fc_config.h>
15 #endif
16 
17 /* utility */
18 #include "iterator.h"
19 #include "log.h"
20 #include "shared.h"
21 #include "string_vector.h"
22 #include "support.h"
23 
24 /* common */
25 #include "fc_types.h"
26 #include "game.h"
27 #include "player.h"
28 #include "name_translation.h"
29 #include "team.h"
30 #include "tech.h"
31 
32 #include "research.h"
33 
34 
35 struct research_iter {
36   struct iterator vtable;
37   int index;
38 };
39 #define RESEARCH_ITER(p) ((struct research_iter *) p)
40 
41 struct research_player_iter {
42   struct iterator vtable;
43   union {
44     struct player *pplayer;
45     struct player_list_link *plink;
46   };
47 };
48 #define RESEARCH_PLAYER_ITER(p) ((struct research_player_iter *) p)
49 
50 static struct research research_array[MAX_NUM_PLAYER_SLOTS];
51 
52 static struct name_translation advance_unset_name = NAME_INIT;
53 static struct name_translation advance_future_name = NAME_INIT;
54 static struct name_translation advance_unknown_name = NAME_INIT;
55 
56 static struct strvec *future_rule_name;
57 static struct strvec *future_name_translation;
58 
59 /****************************************************************************
60   Initializes all player research structure.
61 ****************************************************************************/
researches_init(void)62 void researches_init(void)
63 {
64   int i;
65 
66   /* Ensure we have enough space for players or teams. */
67   fc_assert(ARRAY_SIZE(research_array) >= team_slot_count());
68   fc_assert(ARRAY_SIZE(research_array) >= player_slot_count());
69 
70   memset(research_array, 0, sizeof(research_array));
71   for (i = 0; i < ARRAY_SIZE(research_array); i++) {
72     research_array[i].tech_goal = A_UNSET;
73     research_array[i].researching = A_UNSET;
74     research_array[i].researching_saved = A_UNKNOWN;
75     research_array[i].future_tech = 0;
76     research_array[i].inventions[A_NONE].state = TECH_KNOWN;
77   }
78 
79   game.info.global_advances[A_NONE] = TRUE;
80 
81   /* Set technology names. */
82   /* TRANS: "None" tech */
83   name_set(&advance_unset_name, NULL, N_("?tech:None"));
84   name_set(&advance_future_name, NULL, N_("Future Tech."));
85   /* TRANS: "Unknown" advance/technology */
86   name_set(&advance_unknown_name, NULL, N_("(Unknown)"));
87 
88   future_rule_name = strvec_new();
89   future_name_translation = strvec_new();
90 }
91 
92 /****************************************************************************
93   Free all resources allocated for the research system
94 ****************************************************************************/
researches_free(void)95 void researches_free(void)
96 {
97   strvec_destroy(future_rule_name);
98   strvec_destroy(future_name_translation);
99 }
100 
101 /****************************************************************************
102   Returns the index of the research in the array.
103 ****************************************************************************/
research_number(const struct research * presearch)104 int research_number(const struct research *presearch)
105 {
106   fc_assert_ret_val(NULL != presearch, -1);
107   return presearch - research_array;
108 }
109 
110 /****************************************************************************
111   Returns the research for the given index.
112 ****************************************************************************/
research_by_number(int number)113 struct research *research_by_number(int number)
114 {
115   fc_assert_ret_val(0 <= number, NULL);
116   fc_assert_ret_val(ARRAY_SIZE(research_array) > number, NULL);
117   return &research_array[number];
118 }
119 
120 /****************************************************************************
121   Returns the research structure associated with the player.
122 ****************************************************************************/
research_get(const struct player * pplayer)123 struct research *research_get(const struct player *pplayer)
124 {
125   if (NULL == pplayer) {
126     /* Special case used at client side. */
127     return NULL;
128   } else if (game.info.team_pooled_research) {
129     return &research_array[team_number(pplayer->team)];
130   } else {
131     return &research_array[player_number(pplayer)];
132   }
133 }
134 
135 /****************************************************************************
136   Returns the name of the research owner: a player name or a team name.
137 ****************************************************************************/
research_rule_name(const struct research * presearch)138 const char *research_rule_name(const struct research *presearch)
139 {
140   if (game.info.team_pooled_research) {
141     return team_rule_name(team_by_number(research_number(presearch)));
142   } else {
143     return player_name(player_by_number(research_number(presearch)));
144   }
145 }
146 
147 /****************************************************************************
148   Returns the name of the research owner: a player name or a team name.
149   For most uses you probably want research_pretty_name() instead.
150 ****************************************************************************/
research_name_translation(const struct research * presearch)151 const char *research_name_translation(const struct research *presearch)
152 {
153   if (game.info.team_pooled_research) {
154     return team_name_translation(team_by_number(research_number(presearch)));
155   } else {
156     return player_name(player_by_number(research_number(presearch)));
157   }
158 }
159 
160 /****************************************************************************
161   Set in 'buf' the name of the research owner. It may be either a nation
162   plural name, or something like "members of team Red".
163 ****************************************************************************/
research_pretty_name(const struct research * presearch,char * buf,size_t buf_len)164 int research_pretty_name(const struct research *presearch, char *buf,
165                          size_t buf_len)
166 {
167   const struct player *pplayer;
168 
169   if (game.info.team_pooled_research) {
170     const struct team *pteam = team_by_number(research_number(presearch));
171 
172     if (1 != player_list_size(team_members(pteam))) {
173       char buf2[buf_len];
174 
175       team_pretty_name(pteam, buf2, sizeof(buf2));
176       /* TRANS: e.g. "members of team 1", or even "members of team Red".
177        * Used in many places where a nation plural might be used. */
178       return fc_snprintf(buf, buf_len, _("members of %s"), buf2);
179     } else {
180       pplayer = player_list_front(team_members(pteam));
181     }
182   } else {
183     pplayer = player_by_number(research_number(presearch));
184   }
185 
186   return fc_strlcpy(buf, nation_plural_for_player(pplayer), buf_len);
187 }
188 
189 /****************************************************************************
190   Return the name translation for 'tech'. Utility for
191   research_advance_rule_name() and research_advance_translated_name().
192 ****************************************************************************/
193 static inline const struct name_translation *
research_advance_name(Tech_type_id tech)194 research_advance_name(Tech_type_id tech)
195 {
196   if (A_UNSET == tech) {
197     return &advance_unset_name;
198   } else if (A_FUTURE == tech) {
199     return &advance_future_name;
200   } else if (A_UNKNOWN == tech) {
201     return &advance_unknown_name;
202   } else {
203     const struct advance *padvance = advance_by_number(tech);
204 
205     fc_assert_ret_val(NULL != padvance, NULL);
206     return &padvance->name;
207   }
208 }
209 
210 /****************************************************************************
211   Set a new future tech name in the string vector, and return the string
212   duplicate stored inside the vector.
213 ****************************************************************************/
research_future_set_name(struct strvec * psv,int no,const char * new_name)214 static const char *research_future_set_name(struct strvec *psv, int no,
215                                             const char *new_name)
216 {
217   if (strvec_size(psv) <= no) {
218     /* Increase the size of the vector if needed. */
219     strvec_reserve(psv, no + 1);
220   }
221 
222   /* Set in vector. */
223   strvec_set(psv, no, new_name);
224 
225   /* Return duplicate of 'new_name'. */
226   return strvec_get(psv, no);
227 }
228 
229 /****************************************************************************
230   Store the rule name of the given tech (including A_FUTURE) in 'buf'.
231   'presearch' may be NULL.
232   We don't return a static buffer because that would break anything that
233   needed to work with more than one name at a time.
234 ****************************************************************************/
research_advance_rule_name(const struct research * presearch,Tech_type_id tech)235 const char *research_advance_rule_name(const struct research *presearch,
236                                        Tech_type_id tech)
237 {
238   if (A_FUTURE == tech && NULL != presearch) {
239     const int no = presearch->future_tech;
240     const char *name;
241 
242     name = strvec_get(future_rule_name, no);
243     if (name == NULL) {
244       char buffer[256];
245 
246       /* NB: 'presearch->future_tech == 0' means "Future Tech. 1". */
247       fc_snprintf(buffer, sizeof(buffer), "%s %d",
248                   rule_name_get(&advance_future_name),
249                   no + 1);
250       name = research_future_set_name(future_rule_name, no, buffer);
251     }
252 
253     fc_assert(name != NULL);
254 
255     return name;
256   }
257 
258   return rule_name_get(research_advance_name(tech));
259 }
260 
261 /****************************************************************************
262   Store the translated name of the given tech (including A_FUTURE) in 'buf'.
263   'presearch' may be NULL.
264   We don't return a static buffer because that would break anything that
265   needed to work with more than one name at a time.
266 ****************************************************************************/
267 const char *
research_advance_name_translation(const struct research * presearch,Tech_type_id tech)268 research_advance_name_translation(const struct research *presearch,
269                                   Tech_type_id tech)
270 {
271   if (A_FUTURE == tech && NULL != presearch) {
272     const int no = presearch->future_tech;
273     const char *name;
274 
275     name = strvec_get(future_name_translation, no);
276     if (name == NULL) {
277       char buffer[256];
278 
279       /* NB: 'presearch->future_tech == 0' means "Future Tech. 1". */
280       fc_snprintf(buffer, sizeof(buffer), _("Future Tech. %d"), no + 1);
281       name = research_future_set_name(future_name_translation, no, buffer);
282     }
283 
284     fc_assert(name != NULL);
285 
286     return name;
287   }
288 
289   return name_translation_get(research_advance_name(tech));
290 }
291 
292 /****************************************************************************
293   Returns TRUE iff the given tech is ever reachable by the players sharing
294   the research by checking tech tree limitations.
295 
296   Helper for research_update().
297 ****************************************************************************/
research_get_reachable(const struct research * presearch,Tech_type_id tech)298 static bool research_get_reachable(const struct research *presearch,
299                                    Tech_type_id tech)
300 {
301   if (valid_advance_by_number(tech) == NULL) {
302     return FALSE;
303   } else {
304     advance_root_req_iterate(advance_by_number(tech), proot) {
305       if (advance_requires(proot, AR_ROOT) == proot) {
306         /* This tech requires itself; it can only be reached by special
307          * means (init_techs, lua script, ...).
308          * If you already know it, you can "reach" it; if not, not. (This
309          * case is needed for descendants of this tech.) */
310         if (presearch->inventions[advance_number(proot)].state != TECH_KNOWN) {
311           return FALSE;
312         }
313       } else {
314         enum tech_req req;
315 
316         for (req = 0; req < AR_SIZE; req++) {
317           if (valid_advance(advance_requires(proot, req)) == NULL) {
318             return FALSE;
319           }
320         }
321       }
322     } advance_root_req_iterate_end;
323   }
324 
325   return TRUE;
326 }
327 
328 /****************************************************************************
329   Returns TRUE iff the players sharing 'presearch' already have got the
330   knowledge of all root requirement technologies for 'tech' (without which
331   it's impossible to gain 'tech').
332 
333   Helper for research_update().
334 ****************************************************************************/
research_get_root_reqs_known(const struct research * presearch,Tech_type_id tech)335 static bool research_get_root_reqs_known(const struct research *presearch,
336                                          Tech_type_id tech)
337 {
338   advance_root_req_iterate(advance_by_number(tech), proot) {
339     if (presearch->inventions[advance_number(proot)].state != TECH_KNOWN) {
340       return FALSE;
341     }
342   } advance_root_req_iterate_end;
343 
344   return TRUE;
345 }
346 
347 /****************************************************************************
348   Mark as TECH_PREREQS_KNOWN each tech which is available, not known and
349   which has all requirements fullfiled.
350 
351   Recalculate presearch->num_known_tech_with_flag
352   Should always be called after research_invention_set().
353 ****************************************************************************/
research_update(struct research * presearch)354 void research_update(struct research *presearch)
355 {
356   enum tech_flag_id flag;
357   int techs_researched;
358 
359   advance_index_iterate(A_FIRST, i) {
360     enum tech_state state = presearch->inventions[i].state;
361     bool root_reqs_known = TRUE;
362     bool reachable = research_get_reachable(presearch, i);
363 
364     if (reachable) {
365       root_reqs_known = research_get_root_reqs_known(presearch, i);
366       if (state != TECH_KNOWN) {
367         /* Update state. */
368         state = (root_reqs_known
369                  && (presearch->inventions[advance_required(i, AR_ONE)].state
370                      == TECH_KNOWN)
371                  && (presearch->inventions[advance_required(i, AR_TWO)].state
372                      == TECH_KNOWN)
373                  ? TECH_PREREQS_KNOWN : TECH_UNKNOWN);
374       }
375     } else {
376       fc_assert(state == TECH_UNKNOWN);
377       root_reqs_known = FALSE;
378     }
379     presearch->inventions[i].state = state;
380     presearch->inventions[i].reachable = reachable;
381     presearch->inventions[i].root_reqs_known = root_reqs_known;
382 
383     /* Updates required_techs, num_required_techs and bulbs_required. */
384     BV_CLR_ALL(presearch->inventions[i].required_techs);
385     presearch->inventions[i].num_required_techs = 0;
386     presearch->inventions[i].bulbs_required = 0;
387 
388     if (!reachable || state == TECH_KNOWN) {
389       continue;
390     }
391 
392     techs_researched = presearch->techs_researched;
393     advance_req_iterate(valid_advance_by_number(i), preq) {
394       Tech_type_id j = advance_number(preq);
395 
396       if (TECH_KNOWN == research_invention_state(presearch, j)) {
397         continue;
398       }
399 
400       BV_SET(presearch->inventions[i].required_techs, j);
401       presearch->inventions[i].num_required_techs++;
402       presearch->inventions[i].bulbs_required +=
403           research_total_bulbs_required(presearch, j, FALSE);
404       /* This is needed to get a correct result for the
405        * research_total_bulbs_required() call when
406        * game.info.game.info.tech_cost_style is TECH_COST_CIV1CIV2. */
407       presearch->techs_researched++;
408     } advance_req_iterate_end;
409     presearch->techs_researched = techs_researched;
410   } advance_index_iterate_end;
411 
412 #ifdef FREECIV_DEBUG
413   advance_index_iterate(A_FIRST, i) {
414     char buf[advance_count() + 1];
415 
416     advance_index_iterate(A_NONE, j) {
417       if (BV_ISSET(presearch->inventions[i].required_techs, j)) {
418         buf[j] = '1';
419       } else {
420         buf[j] = '0';
421       }
422     } advance_index_iterate_end;
423     buf[advance_count()] = '\0';
424 
425     log_debug("%s: [%3d] %-25s => %s%s%s",
426               research_rule_name(presearch),
427               i,
428               advance_rule_name(advance_by_number(i)),
429               tech_state_name(research_invention_state(presearch, i)),
430               presearch->inventions[i].reachable ? "" : " [unrechable]",
431               presearch->inventions[i].root_reqs_known
432               ? "" : " [root reqs aren't known]");
433     log_debug("%s: [%3d] %s", research_rule_name(presearch), i, buf);
434   } advance_index_iterate_end;
435 #endif /* FREECIV_DEBUG */
436 
437   for (flag = 0; flag <= tech_flag_id_max(); flag++) {
438     /* Iterate over all possible tech flags (0..max). */
439     presearch->num_known_tech_with_flag[flag] = 0;
440 
441     advance_index_iterate(A_NONE, i) {
442       if (TECH_KNOWN == research_invention_state(presearch, i)
443           && advance_has_flag(i, flag)) {
444         presearch->num_known_tech_with_flag[flag]++;
445       }
446     } advance_index_iterate_end;
447   }
448 }
449 
450 /****************************************************************************
451   Returns state of the tech for current research.
452   This can be: TECH_KNOWN, TECH_UNKNOWN, or TECH_PREREQS_KNOWN
453   Should be called with existing techs.
454 
455   If 'presearch' is NULL this checks whether any player knows the tech
456   (used by the client).
457 ****************************************************************************/
research_invention_state(const struct research * presearch,Tech_type_id tech)458 enum tech_state research_invention_state(const struct research *presearch,
459                                          Tech_type_id tech)
460 {
461   fc_assert_ret_val(NULL != valid_advance_by_number(tech), -1);
462 
463   if (NULL != presearch) {
464     return presearch->inventions[tech].state;
465   } else if (game.info.global_advances[tech]) {
466     return TECH_KNOWN;
467   } else {
468     return TECH_UNKNOWN;
469   }
470 }
471 
472 /****************************************************************************
473   Set research knowledge about tech to given state.
474 ****************************************************************************/
research_invention_set(struct research * presearch,Tech_type_id tech,enum tech_state value)475 enum tech_state research_invention_set(struct research *presearch,
476                                        Tech_type_id tech,
477                                        enum tech_state value)
478 {
479   enum tech_state old;
480 
481   fc_assert_ret_val(NULL != valid_advance_by_number(tech), -1);
482 
483   old = presearch->inventions[tech].state;
484   if (old == value) {
485     return old;
486   }
487   presearch->inventions[tech].state = value;
488 
489   if (value == TECH_KNOWN) {
490     game.info.global_advances[tech] = TRUE;
491   }
492   return old;
493 }
494 
495 /****************************************************************************
496   Returns TRUE iff the given tech is ever reachable by the players sharing
497   the research by checking tech tree limitations.
498 
499   'presearch' may be NULL in which case a simplified result is returned
500   (used by the client).
501 ****************************************************************************/
research_invention_reachable(const struct research * presearch,const Tech_type_id tech)502 bool research_invention_reachable(const struct research *presearch,
503                                   const Tech_type_id tech)
504 {
505   if (valid_advance_by_number(tech) == NULL) {
506     return FALSE;
507   } else if (presearch != NULL) {
508     return presearch->inventions[tech].reachable;
509   } else {
510     researches_iterate(research_iter) {
511       if (research_iter->inventions[tech].reachable) {
512         return TRUE;
513       }
514     } researches_iterate_end;
515 
516     return FALSE;
517   }
518 }
519 
520 /****************************************************************************
521   Returns TRUE iff the given tech can be given to the players sharing the
522   research immediately.
523 
524   If allow_holes is TRUE, any reachable tech is ok. If it's FALSE,
525   getting the tech must not leave holes to the known techs tree.
526 ****************************************************************************/
research_invention_gettable(const struct research * presearch,const Tech_type_id tech,bool allow_holes)527 bool research_invention_gettable(const struct research *presearch,
528                                  const Tech_type_id tech,
529                                  bool allow_holes)
530 {
531   if (valid_advance_by_number(tech) == NULL) {
532     return FALSE;
533   } else if (presearch != NULL) {
534     return (allow_holes
535             ? presearch->inventions[tech].root_reqs_known
536             : presearch->inventions[tech].state == TECH_PREREQS_KNOWN);
537   } else {
538     researches_iterate(research_iter) {
539       if (allow_holes
540           ? research_iter->inventions[tech].root_reqs_known
541           : research_iter->inventions[tech].state == TECH_PREREQS_KNOWN) {
542         return TRUE;
543       }
544     } researches_iterate_end;
545 
546     return FALSE;
547   }
548 }
549 
550 /****************************************************************************
551   Return the next tech we should research to advance towards our goal.
552   Returns A_UNSET if nothing is available or the goal is already known.
553 ****************************************************************************/
research_goal_step(const struct research * presearch,Tech_type_id goal)554 Tech_type_id research_goal_step(const struct research *presearch,
555                                 Tech_type_id goal)
556 {
557   const struct advance *pgoal = valid_advance_by_number(goal);
558 
559   if (NULL == pgoal
560       || !research_invention_reachable(presearch, goal)) {
561     return A_UNSET;
562   }
563 
564   advance_req_iterate(pgoal, preq) {
565     switch (research_invention_state(presearch, advance_number(preq))) {
566     case TECH_PREREQS_KNOWN:
567       return advance_number(preq);
568     case TECH_KNOWN:
569     case TECH_UNKNOWN:
570        break;
571     };
572   } advance_req_iterate_end;
573   return A_UNSET;
574 }
575 
576 /****************************************************************************
577   Returns the number of technologies the player need to research to get
578   the goal technology. This includes the goal technology. Technologies
579   are only counted once.
580 
581   'presearch' may be NULL in which case it will returns the total number
582   of technologies needed for reaching the goal.
583 ****************************************************************************/
research_goal_unknown_techs(const struct research * presearch,Tech_type_id goal)584 int research_goal_unknown_techs(const struct research *presearch,
585                                 Tech_type_id goal)
586 {
587   const struct advance *pgoal = valid_advance_by_number(goal);
588 
589   if (NULL == pgoal) {
590     return 0;
591   } else if (NULL != presearch) {
592     return presearch->inventions[goal].num_required_techs;
593   } else {
594     return pgoal->num_reqs;
595   }
596 }
597 
598 /****************************************************************************
599   Function to determine cost (in bulbs) of reaching goal technology.
600   These costs _include_ the cost for researching the goal technology
601   itself.
602 
603   'presearch' may be NULL in which case it will returns the total number
604   of bulbs needed for reaching the goal.
605 ****************************************************************************/
research_goal_bulbs_required(const struct research * presearch,Tech_type_id goal)606 int research_goal_bulbs_required(const struct research *presearch,
607                                  Tech_type_id goal)
608 {
609   const struct advance *pgoal = valid_advance_by_number(goal);
610 
611   if (NULL == pgoal) {
612     return 0;
613   } else if (NULL != presearch) {
614     return presearch->inventions[goal].bulbs_required;
615   } else if (game.info.tech_cost_style == TECH_COST_CIV1CIV2) {
616      return game.info.base_tech_cost * pgoal->num_reqs
617             * (pgoal->num_reqs + 1) / 2;
618   } else {
619     int bulbs_required = 0;
620 
621     advance_req_iterate(pgoal, preq) {
622       bulbs_required += preq->cost;
623     } advance_req_iterate_end;
624     return bulbs_required;
625   }
626 }
627 
628 /****************************************************************************
629   Returns if the given tech has to be researched to reach the goal. The
630   goal itself isn't a requirement of itself.
631 
632   'presearch' may be NULL.
633 ****************************************************************************/
research_goal_tech_req(const struct research * presearch,Tech_type_id goal,Tech_type_id tech)634 bool research_goal_tech_req(const struct research *presearch,
635                             Tech_type_id goal, Tech_type_id tech)
636 {
637   const struct advance *pgoal, *ptech;
638 
639   if (tech == goal
640       || NULL == (pgoal = valid_advance_by_number(goal))
641       || NULL == (ptech = valid_advance_by_number(tech))) {
642     return FALSE;
643   } else if (NULL != presearch) {
644     return BV_ISSET(presearch->inventions[goal].required_techs, tech);
645   } else {
646     advance_req_iterate(pgoal, preq) {
647       if (preq == ptech) {
648         return TRUE;
649       }
650     } advance_req_iterate_end;
651     return FALSE;
652   }
653 }
654 
655 /****************************************************************************
656   Function to determine cost for technology.  The equation is determined
657   from game.info.tech_cost_style and game.info.tech_leakage.
658 
659   tech_cost_style:
660   TECH_COST_CIV1CIV2: Civ (I|II) style. Every new tech add base_tech_cost to
661                       cost of next tech.
662   TECH_COST_CLASSIC: Cost of technology is:
663                        base_tech_cost * (1 + reqs) * sqrt(1 + reqs) / 2
664                      where reqs == number of requirement for tech, counted
665                      recursively.
666   TECH_COST_CLASSIC_PRESET: Cost are read from tech.ruleset. Missing costs
667                             are generated by style "Classic".
668   TECH_COST_EXPERIMENTAL: Cost of technology is:
669                             base_tech_cost * (reqs^2
670                                               / (1 + sqrt(sqrt(reqs + 1)))
671                                               - 0.5)
672                           where reqs == number of requirement for tech,
673                           counted recursively.
674   TECH_COST_EXPERIMENTAL_PRESET: Cost are read from tech.ruleset. Missing
675                                  costs are generated by style "Experimental".
676 
677   tech_leakage:
678   TECH_LEAKAGE_NONE: No reduction of the technology cost.
679   TECH_LEAKAGE_EMBASSIES: Technology cost is reduced depending on the number
680                           of players which already know the tech and you have
681                           an embassy with.
682   TECH_LEAKAGE_PLAYERS: Technology cost is reduced depending on the number of
683                         all players (human, AI and barbarians) which already
684                         know the tech.
685   TECH_LEAKAGE_NO_BARBS: Technology cost is reduced depending on the number
686                          of normal players (human and AI) which already know
687                          the tech.
688 
689   At the end we multiply by the sciencebox value, as a percentage.  The
690   cost can never be less than 1.
691 
692   'presearch' may be NULL in which case a simplified result is returned
693   (used by client and manual code).
694 ****************************************************************************/
research_total_bulbs_required(const struct research * presearch,Tech_type_id tech,bool loss_value)695 int research_total_bulbs_required(const struct research *presearch,
696                                   Tech_type_id tech, bool loss_value)
697 {
698   enum tech_cost_style tech_cost_style = game.info.tech_cost_style;
699   int members;
700   double base_cost, total_cost;
701 
702   if (!loss_value
703       && NULL != presearch
704       && !is_future_tech(tech)
705       && research_invention_state(presearch, tech) == TECH_KNOWN) {
706     /* A non-future tech which is already known costs nothing. */
707     return 0;
708   }
709 
710   if (is_future_tech(tech)) {
711     /* Future techs use style TECH_COST_CIV1CIV2. */
712     tech_cost_style = TECH_COST_CIV1CIV2;
713   }
714 
715   fc_assert_msg(tech_cost_style_is_valid(tech_cost_style),
716                 "Invalid tech_cost_style %d", tech_cost_style);
717   base_cost = 0.0;
718   switch (tech_cost_style) {
719   case TECH_COST_CIV1CIV2:
720     if (NULL != presearch) {
721       base_cost = game.info.base_tech_cost * presearch->techs_researched;
722       break;
723     }
724 
725     fc_assert(presearch != NULL);
726     fc__fallthrough; /* No break; Fallback to using preset cost. */
727   case TECH_COST_CLASSIC:
728   case TECH_COST_CLASSIC_PRESET:
729   case TECH_COST_EXPERIMENTAL:
730   case TECH_COST_EXPERIMENTAL_PRESET:
731     {
732       const struct advance *padvance = valid_advance_by_number(tech);
733 
734       if (NULL != padvance) {
735         base_cost = padvance->cost;
736       } else {
737         fc_assert(NULL != padvance); /* Always fails. */
738       }
739     }
740     break;
741   }
742 
743   total_cost = 0.0;
744   members = 0;
745   research_players_iterate(presearch, pplayer) {
746     members++;
747     total_cost += (base_cost
748                    * get_player_bonus(pplayer, EFT_TECH_COST_FACTOR));
749   } research_players_iterate_end;
750   if (0 == members) {
751     /* There is no more alive players for this research, no need to apply
752      * complicated modifiers. */
753     return base_cost * (double) game.info.sciencebox / 100.0;
754   }
755   base_cost = total_cost / members;
756 
757   fc_assert_msg(tech_leakage_style_is_valid(game.info.tech_leakage),
758                 "Invalid tech_leakage %d", game.info.tech_leakage);
759   switch (game.info.tech_leakage) {
760   case TECH_LEAKAGE_NONE:
761     /* no change */
762     break;
763 
764   case TECH_LEAKAGE_EMBASSIES:
765     {
766       int players = 0, players_with_tech_and_embassy = 0;
767 
768       players_iterate_alive(aplayer) {
769         const struct research *aresearch = research_get(aplayer);
770 
771         players++;
772         if (aresearch == presearch
773             || (A_FUTURE == tech
774                 ? aresearch->future_tech <= presearch->future_tech
775                 : TECH_KNOWN != research_invention_state(aresearch, tech))) {
776           continue;
777         }
778 
779         research_players_iterate(presearch, pplayer) {
780           if (player_has_embassy(pplayer, aplayer)) {
781             players_with_tech_and_embassy++;
782             break;
783           }
784         } research_players_iterate_end;
785       } players_iterate_alive_end;
786 
787       fc_assert_ret_val(0 < players, base_cost);
788       fc_assert(players >= players_with_tech_and_embassy);
789       base_cost *= (double) (players - players_with_tech_and_embassy);
790       base_cost /= (double) players;
791     }
792     break;
793 
794   case TECH_LEAKAGE_PLAYERS:
795     {
796       int players = 0, players_with_tech = 0;
797 
798       players_iterate_alive(aplayer) {
799         players++;
800         if (A_FUTURE == tech
801             ? research_get(aplayer)->future_tech > presearch->future_tech
802             : TECH_KNOWN == research_invention_state(research_get(aplayer),
803                                                      tech)) {
804           players_with_tech++;
805         }
806       } players_iterate_alive_end;
807 
808       fc_assert_ret_val(0 < players, base_cost);
809       fc_assert(players >= players_with_tech);
810       base_cost *= (double) (players - players_with_tech);
811       base_cost /= (double) players;
812     }
813     break;
814 
815   case TECH_LEAKAGE_NO_BARBS:
816     {
817       int players = 0, players_with_tech = 0;
818 
819       players_iterate_alive(aplayer) {
820         if (is_barbarian(aplayer)) {
821           continue;
822         }
823         players++;
824         if (A_FUTURE == tech
825             ? research_get(aplayer)->future_tech > presearch->future_tech
826             : TECH_KNOWN == research_invention_state(research_get(aplayer),
827                                                      tech)) {
828           players_with_tech++;
829         }
830       } players_iterate_alive_end;
831 
832       fc_assert_ret_val(0 < players, base_cost);
833       fc_assert(players >= players_with_tech);
834       base_cost *= (double) (players - players_with_tech);
835       base_cost /= (double) players;
836     }
837     break;
838   }
839 
840   /* Assign a science penalty to the AI at easier skill levels. This code
841    * can also be adopted to create an extra-hard AI skill level where the AI
842    * gets science benefits. */
843 
844   total_cost = 0.0;
845   research_players_iterate(presearch, pplayer) {
846     if (pplayer->ai_controlled) {
847       fc_assert(0 < pplayer->ai_common.science_cost);
848       total_cost += base_cost * pplayer->ai_common.science_cost / 100.0;
849     } else {
850       total_cost += base_cost;
851     }
852   } research_players_iterate_end;
853   base_cost = total_cost / members;
854 
855   base_cost *= (double) game.info.sciencebox / 100.0;
856 
857   return MAX(base_cost, 1);
858 }
859 
860 
861 /****************************************************************************
862   Calculate the bulb upkeep needed for all techs of a player. See also
863   research_total_bulbs_required().
864 ****************************************************************************/
player_tech_upkeep(const struct player * pplayer)865 int player_tech_upkeep(const struct player *pplayer)
866 {
867   const struct research *presearch = research_get(pplayer);
868   int f = presearch->future_tech, t = presearch->techs_researched;
869   double tech_upkeep = 0.0;
870   double total_research_factor;
871   int members;
872 
873   if (TECH_UPKEEP_NONE == game.info.tech_upkeep_style) {
874     return 0;
875   }
876 
877   total_research_factor = 0.0;
878   members = 0;
879   research_players_iterate(presearch, contributor) {
880     total_research_factor += (get_player_bonus(contributor, EFT_TECH_COST_FACTOR)
881                               + (contributor->ai_controlled
882                                  ? contributor->ai_common.science_cost / 100.0
883                                  : 1));
884     members++;
885   } research_players_iterate_end;
886   if (0 == members) {
887     /* No player still alive. */
888     return 0;
889   }
890 
891   /* Upkeep cost for 'normal' techs (t). */
892   fc_assert_msg(tech_cost_style_is_valid(game.info.tech_cost_style),
893                 "Invalid tech_cost_style %d", game.info.tech_cost_style);
894   switch (game.info.tech_cost_style) {
895   case TECH_COST_CIV1CIV2:
896     /* sum_1^t x = t * (t + 1) / 2 */
897     tech_upkeep += game.info.base_tech_cost * t * (t + 1) / 2;
898     break;
899   case TECH_COST_CLASSIC:
900   case TECH_COST_CLASSIC_PRESET:
901   case TECH_COST_EXPERIMENTAL:
902   case TECH_COST_EXPERIMENTAL_PRESET:
903     advance_iterate(A_FIRST, padvance) {
904       if (TECH_KNOWN == research_invention_state(presearch,
905                                                  advance_number(padvance))) {
906         tech_upkeep += padvance->cost;
907       }
908     } advance_iterate_end;
909     if (0 < f) {
910       /* Upkeep cost for future techs (f) are calculated using style 0:
911        * sum_t^(t+f) x = (f * (2 * t + f + 1) + 2 * t) / 2 */
912       tech_upkeep += (double) (game.info.base_tech_cost
913                                * (f * (2 * t + f + 1) + 2 * t) / 2);
914     }
915     break;
916   }
917 
918   tech_upkeep *= total_research_factor / members;
919   tech_upkeep *= (double) game.info.sciencebox / 100.0;
920   /* We only want to calculate the upkeep part of one player, not the
921    * whole team! */
922   tech_upkeep /= members;
923   tech_upkeep /= game.info.tech_upkeep_divider;
924 
925   switch (game.info.tech_upkeep_style) {
926   case TECH_UPKEEP_BASIC:
927     tech_upkeep -= get_player_bonus(pplayer, EFT_TECH_UPKEEP_FREE);
928     break;
929   case TECH_UPKEEP_PER_CITY:
930     tech_upkeep -= get_player_bonus(pplayer, EFT_TECH_UPKEEP_FREE);
931     tech_upkeep *= city_list_size(pplayer->cities);
932     break;
933   case TECH_UPKEEP_NONE:
934     fc_assert(game.info.tech_upkeep_style != TECH_UPKEEP_NONE);
935     tech_upkeep = 0.0;
936   }
937 
938   if (0.0 > tech_upkeep) {
939     tech_upkeep = 0.0;
940   }
941 
942   log_debug("[%s (%d)] tech upkeep: %d", player_name(pplayer),
943             player_number(pplayer), (int) tech_upkeep);
944   return (int) tech_upkeep;
945 }
946 
947 
948 /****************************************************************************
949   Returns the real size of the player research iterator.
950 ****************************************************************************/
research_iter_sizeof(void)951 size_t research_iter_sizeof(void)
952 {
953   return sizeof(struct research_iter);
954 }
955 
956 /****************************************************************************
957   Returns the research structure pointed by the iterator.
958 ****************************************************************************/
research_iter_get(const struct iterator * it)959 static void *research_iter_get(const struct iterator *it)
960 {
961   return &research_array[RESEARCH_ITER(it)->index];
962 }
963 
964 /****************************************************************************
965   Jump to next team research structure.
966 ****************************************************************************/
research_iter_team_next(struct iterator * it)967 static void research_iter_team_next(struct iterator *it)
968 {
969   struct research_iter *rit = RESEARCH_ITER(it);
970 
971   if (team_slots_initialised()) {
972     do {
973       rit->index++;
974     } while (rit->index < ARRAY_SIZE(research_array) && !it->valid(it));
975   }
976 }
977 
978 /****************************************************************************
979   Returns FALSE if there is no valid team at current index.
980 ****************************************************************************/
research_iter_team_valid(const struct iterator * it)981 static bool research_iter_team_valid(const struct iterator *it)
982 {
983   struct research_iter *rit = RESEARCH_ITER(it);
984 
985   return (0 <= rit->index
986           && ARRAY_SIZE(research_array) > rit->index
987           && NULL != team_by_number(rit->index));
988 }
989 
990 /****************************************************************************
991   Jump to next player research structure.
992 ****************************************************************************/
research_iter_player_next(struct iterator * it)993 static void research_iter_player_next(struct iterator *it)
994 {
995   struct research_iter *rit = RESEARCH_ITER(it);
996 
997   if (player_slots_initialised()) {
998     do {
999       rit->index++;
1000     } while (rit->index < ARRAY_SIZE(research_array) && !it->valid(it));
1001   }
1002 }
1003 
1004 /****************************************************************************
1005   Returns FALSE if there is no valid player at current index.
1006 ****************************************************************************/
research_iter_player_valid(const struct iterator * it)1007 static bool research_iter_player_valid(const struct iterator *it)
1008 {
1009   struct research_iter *rit = RESEARCH_ITER(it);
1010 
1011   return (0 <= rit->index
1012           && ARRAY_SIZE(research_array) > rit->index
1013           && NULL != player_by_number(rit->index));
1014 }
1015 
1016 /****************************************************************************
1017   Initializes a player research iterator.
1018 ****************************************************************************/
research_iter_init(struct research_iter * it)1019 struct iterator *research_iter_init(struct research_iter *it)
1020 {
1021   struct iterator *base = ITERATOR(it);
1022 
1023   base->get = research_iter_get;
1024   it->index = -1;
1025 
1026   if (game.info.team_pooled_research) {
1027     base->next = research_iter_team_next;
1028     base->valid = research_iter_team_valid;
1029   } else {
1030     base->next = research_iter_player_next;
1031     base->valid = research_iter_player_valid;
1032   }
1033 
1034   base->next(base);
1035   return base;
1036 }
1037 
1038 /****************************************************************************
1039   Returns the real size of the research player iterator.
1040 ****************************************************************************/
research_player_iter_sizeof(void)1041 size_t research_player_iter_sizeof(void)
1042 {
1043   return sizeof(struct research_player_iter);
1044 }
1045 
1046 /****************************************************************************
1047   Returns whether the iterator is currently at a valid state.
1048 ****************************************************************************/
research_player_iter_valid_state(struct iterator * it)1049 static inline bool research_player_iter_valid_state(struct iterator *it)
1050 {
1051   const struct player *pplayer = iterator_get(it);
1052 
1053   return (NULL == pplayer || pplayer->is_alive);
1054 }
1055 
1056 /****************************************************************************
1057   Returns player of the iterator.
1058 ****************************************************************************/
research_player_iter_pooled_get(const struct iterator * it)1059 static void *research_player_iter_pooled_get(const struct iterator *it)
1060 {
1061   return player_list_link_data(RESEARCH_PLAYER_ITER(it)->plink);
1062 }
1063 
1064 /****************************************************************************
1065   Returns the next player sharing the research.
1066 ****************************************************************************/
research_player_iter_pooled_next(struct iterator * it)1067 static void research_player_iter_pooled_next(struct iterator *it)
1068 {
1069   struct research_player_iter *rpit = RESEARCH_PLAYER_ITER(it);
1070 
1071   do {
1072     rpit->plink = player_list_link_next(rpit->plink);
1073   } while (!research_player_iter_valid_state(it));
1074 }
1075 
1076 /****************************************************************************
1077   Returns whether the iterate is valid.
1078 ****************************************************************************/
research_player_iter_pooled_valid(const struct iterator * it)1079 static bool research_player_iter_pooled_valid(const struct iterator *it)
1080 {
1081   return NULL != RESEARCH_PLAYER_ITER(it)->plink;
1082 }
1083 
1084 /****************************************************************************
1085   Returns player of the iterator.
1086 ****************************************************************************/
research_player_iter_not_pooled_get(const struct iterator * it)1087 static void *research_player_iter_not_pooled_get(const struct iterator *it)
1088 {
1089   return RESEARCH_PLAYER_ITER(it)->pplayer;
1090 }
1091 
1092 /****************************************************************************
1093   Invalidate the iterator.
1094 ****************************************************************************/
research_player_iter_not_pooled_next(struct iterator * it)1095 static void research_player_iter_not_pooled_next(struct iterator *it)
1096 {
1097   RESEARCH_PLAYER_ITER(it)->pplayer = NULL;
1098 }
1099 
1100 /****************************************************************************
1101   Returns whether the iterate is valid.
1102 ****************************************************************************/
research_player_iter_not_pooled_valid(const struct iterator * it)1103 static bool research_player_iter_not_pooled_valid(const struct iterator *it)
1104 {
1105   return NULL != RESEARCH_PLAYER_ITER(it)->pplayer;
1106 }
1107 
1108 /****************************************************************************
1109   Initializes a research player iterator.
1110 ****************************************************************************/
research_player_iter_init(struct research_player_iter * it,const struct research * presearch)1111 struct iterator *research_player_iter_init(struct research_player_iter *it,
1112                                            const struct research *presearch)
1113 {
1114   struct iterator *base = ITERATOR(it);
1115 
1116   if (game.info.team_pooled_research && NULL != presearch) {
1117     base->get = research_player_iter_pooled_get;
1118     base->next = research_player_iter_pooled_next;
1119     base->valid = research_player_iter_pooled_valid;
1120     it->plink = player_list_head(team_members(team_by_number(research_number
1121                                                              (presearch))));
1122   } else {
1123     base->get = research_player_iter_not_pooled_get;
1124     base->next = research_player_iter_not_pooled_next;
1125     base->valid = research_player_iter_not_pooled_valid;
1126     it->pplayer = (NULL != presearch
1127                    ? player_by_number(research_number(presearch)) : NULL);
1128   }
1129 
1130   /* Ensure we have consistent data. */
1131   if (!research_player_iter_valid_state(base)) {
1132     iterator_next(base);
1133   }
1134 
1135   return base;
1136 }
1137