Freeciv-3.4
Loading...
Searching...
No Matches
research.c
Go to the documentation of this file.
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 "nation.h"
28#include "player.h"
29#include "name_translation.h"
30#include "team.h"
31#include "tech.h"
32
33#include "research.h"
34
35
38 int index;
39};
40#define RESEARCH_ITER(p) ((struct research_iter *) p)
41
44 union {
45 struct player *pplayer;
47 };
48};
49#define RESEARCH_PLAYER_ITER(p) ((struct research_player_iter *) p)
50
51#define RESEARCH_ARRAY_SIZE MAX(MAX_NUM_PLAYER_SLOTS, MAX_NUM_TEAM_SLOTS)
53
57
58static struct strvec *future_rule_name;
60
61/************************************************************************/
65{
66 int i;
67
68 /* Ensure we have enough space for players or teams. */
71
73 for (i = 0; i < ARRAY_SIZE(research_array); i++) {
82 }
83
85
86 /* Set technology names. */
87 /* TRANS: "None" tech */
88 name_set(&advance_unset_name, nullptr, N_("?tech:None"));
89 name_set(&advance_future_name, nullptr, N_("Future Tech."));
90 /* TRANS: "Unknown" advance/technology */
91 name_set(&advance_unknown_name, nullptr, N_("(Unknown)"));
92
95}
96
97/************************************************************************/
105
106/************************************************************************/
110{
111 fc_assert_ret_val(presearch != nullptr, -1);
112
113 return presearch - research_array;
114}
115
116/************************************************************************/
119struct research *research_by_number(int number)
120{
121 fc_assert_ret_val(0 <= number, nullptr);
122 fc_assert_ret_val(ARRAY_SIZE(research_array) > number, nullptr);
123
124 return &research_array[number];
125}
126
127/************************************************************************/
130struct research *research_get(const struct player *pplayer)
131{
132 if (pplayer == nullptr) {
133 /* Special case used at client side. */
134 return nullptr;
135 } else if (game.info.team_pooled_research) {
136 return &research_array[team_number(pplayer->team)];
137 } else {
138 return &research_array[player_number(pplayer)];
139 }
140}
141
142/************************************************************************/
153
154/************************************************************************/
166
167/************************************************************************/
172 size_t buf_len)
173{
174 const struct player *pplayer;
175
178
180 char buf2[buf_len];
181
182 team_pretty_name(pteam, buf2, sizeof(buf2));
183 /* TRANS: e.g. "members of team 1", or even "members of team Red".
184 * Used in many places where a nation plural might be used. */
185 return fc_snprintf(buf, buf_len, _("members of %s"), buf2);
186 } else {
188 }
189 } else {
191 }
192
194}
195
196/************************************************************************/
200static inline const struct name_translation *
202{
203 if (A_UNSET == tech) {
204 return &advance_unset_name;
205 } else if (A_FUTURE == tech) {
206 return &advance_future_name;
207 } else if (A_UNKNOWN == tech) {
208 return &advance_unknown_name;
209 } else {
210 const struct advance *padvance = advance_by_number(tech);
211
212 fc_assert_ret_val(padvance != nullptr, nullptr);
213
214 return &padvance->name;
215 }
216}
217
218/************************************************************************/
222static const char *research_future_set_name(struct strvec *psv, int no,
223 const char *new_name)
224{
225 if (strvec_size(psv) <= no) {
226 /* Increase the size of the vector if needed. */
227 strvec_reserve(psv, no + 1);
228 }
229
230 /* Set in vector. */
231 strvec_set(psv, no, new_name);
232
233 /* Return duplicate of 'new_name'. */
234 return strvec_get(psv, no);
235}
236
237/************************************************************************/
244 Tech_type_id tech)
245{
246 if (A_FUTURE == tech && presearch != nullptr) {
247 const int no = presearch->future_tech;
248 const char *name;
249
251 if (name == nullptr) {
252 char buffer[256];
253
254 /* NB: 'presearch->future_tech == 0' means "Future Tech. 1". */
255 fc_snprintf(buffer, sizeof(buffer), "%s %d",
257 no + 1);
259 }
260
261 fc_assert(name != nullptr);
262
263 return name;
264 }
265
267}
268
269/************************************************************************/
275const char *
277 Tech_type_id tech)
278{
279 if (A_FUTURE == tech && presearch != nullptr) {
280 const int no = presearch->future_tech;
281 const char *name;
282
284 if (name == nullptr) {
285 char buffer[256];
286
287 /* NB: 'presearch->future_tech == 0' means "Future Tech. 1". */
288 fc_snprintf(buffer, sizeof(buffer), _("Future Tech. %d"), no + 1);
290 }
291
292 fc_assert(name != nullptr);
293
294 return name;
295 }
296
298}
299
300/************************************************************************/
306static bool reqs_may_activate(const struct req_context *context,
307 const struct req_context *other_context,
308 const struct requirement_vector *reqs,
309 const enum req_problem_type prob_type)
310{
313 return FALSE;
314 }
316 return TRUE;
317}
318
319/************************************************************************/
329static bool
331 Tech_type_id tech,
332 bool (*reqs_eval)(const struct req_context *context,
333 const struct req_context *ocontext,
334 const struct requirement_vector *reqs,
335 const enum req_problem_type ptype))
336{
337 struct advance *adv;
338
339 adv = valid_advance_by_number(tech);
340
341 if (adv == nullptr) {
342 /* Not a valid advance. */
343 return FALSE;
344 }
345
347 if (reqs_eval(&(const struct req_context) { .player = pplayer },
348 nullptr, &(adv->research_reqs), RPT_CERTAIN)) {
349 /* It is enough that one player that shares research is allowed to
350 * research it.
351 * Reasoning: Imagine a tech with that requires a nation in the
352 * player range. If the requirement applies to all players sharing
353 * research it will be illegal in research sharing games. To require
354 * that the player that fulfills the requirement must order it to be
355 * researched creates unnecessary bureaucracy. */
356 return TRUE;
357 }
359
360 return FALSE;
361}
362
363/************************************************************************/
369#define research_is_allowed(presearch, tech) \
370 research_allowed(presearch, tech, are_reqs_active)
371
372/************************************************************************/
378#define research_may_become_allowed(presearch, tech) \
379 research_allowed(presearch, tech, reqs_may_activate)
380
381/************************************************************************/
388 Tech_type_id tech)
389{
390 bv_techs done;
392 enum tech_req req;
393 int techs_num;
394 int i;
395
396 techs[0] = tech;
397 BV_CLR_ALL(done);
398 BV_SET(done, A_NONE);
399 BV_SET(done, tech);
400 techs_num = 1;
401
402 /* Check that all recursive requirements have their research_reqs
403 * in order. */
404 for (i = 0; i < techs_num; i++) {
405 if (presearch->inventions[techs[i]].state == TECH_KNOWN) {
406 /* This tech is already reached. What is required to research it and
407 * the techs it depends on is therefore irrelevant. */
408 continue;
409 }
410
412 /* It will always be illegal to start researching this tech because
413 * of unchanging requirements. Since it isn't already known and can't
414 * be researched it must be unreachable. */
415 return FALSE;
416 }
417
418 /* Check if required techs are research_reqs reachable. */
419 for (req = 0; req < AR_SIZE; req++) {
421
422 if (valid_advance_by_number(req_tech) == nullptr) {
423 return FALSE;
424 } else if (!BV_ISSET(done, req_tech)) {
427 techs_num++;
428
429 BV_SET(done, req_tech);
430 }
431 }
432 }
433
434 return TRUE;
435}
436
437/************************************************************************/
443static bool research_get_reachable(const struct research *presearch,
444 Tech_type_id tech)
445{
446 if (valid_advance_by_number(tech) == nullptr) {
447 return FALSE;
448 } else {
451 /* This tech requires itself; it can only be reached by special
452 * means (init_techs, lua script, ...).
453 * If you already know it, you can "reach" it; if not, not. (This
454 * case is needed for descendants of this tech.) */
455 if (presearch->inventions[advance_number(proot)].state != TECH_KNOWN) {
456 return FALSE;
457 }
458 } else {
459 enum tech_req req;
460
461 for (req = 0; req < AR_SIZE; req++) {
462 if (valid_advance(advance_requires(proot, req)) == nullptr) {
463 return FALSE;
464 }
465 }
466 }
468 }
469
470 /* Check research reqs reachability. */
472 return FALSE;
473 }
474
475 return TRUE;
476}
477
478/************************************************************************/
486 Tech_type_id tech)
487{
489 if (presearch->inventions[advance_number(proot)].state != TECH_KNOWN) {
490 return FALSE;
491 }
493
494 return TRUE;
495}
496
497/************************************************************************/
505{
506 enum tech_flag_id flag;
507 int techs_researched;
509
511 enum tech_state state = presearch->inventions[i].state;
512 bool root_reqs_known = TRUE;
513 bool reachable = research_get_reachable(presearch, i);
514
515 /* Finding if the root reqs of an unreachable tech isn't redundant.
516 * A tech can be unreachable via research but have known root reqs
517 * because of unfilfilled research_reqs. Unfulfilled research_reqs
518 * doesn't prevent the player from acquiring the tech by other means. */
519 root_reqs_known = research_get_root_reqs_known(presearch, i);
520
521 if (reachable) {
522 if (state != TECH_KNOWN) {
523 /* Update state. */
524 state = (root_reqs_known
525 && (presearch->inventions[advance_required(i, AR_ONE)].state
526 == TECH_KNOWN)
527 && (presearch->inventions[advance_required(i, AR_TWO)].state
528 == TECH_KNOWN)
531 }
532 } else {
533 /* We used to assert here that state already is TECH_UNKNOWN. However, there is
534 * a special case where it can be e.g. TECH_PREREQS_KNOWN and still
535 * unreachable (like in above research_get_reachable() call) because
536 * player is dead. Dead player's don't research anything. More accurately
537 * research_players_iterate() for a dead player's research iterates over
538 * zero players in research_allowed(), so it falls through to default of FALSE.
539 *
540 * Now we set the state to TECH_UNKNOWN instead of asserting that it already is. */
541 state = TECH_UNKNOWN;
542 }
543 presearch->inventions[i].state = state;
544 presearch->inventions[i].reachable = reachable;
545 presearch->inventions[i].root_reqs_known = root_reqs_known;
546
547 /* Updates required_techs, num_required_techs and bulbs_required. */
548 BV_CLR_ALL(presearch->inventions[i].required_techs);
549 presearch->inventions[i].num_required_techs = 0;
550 presearch->inventions[i].bulbs_required = 0;
551
552 if (!reachable || state == TECH_KNOWN) {
553 continue;
554 }
555
556 techs_researched = presearch->techs_researched;
559
561 continue;
562 }
563
564 BV_SET(presearch->inventions[i].required_techs, j);
565 presearch->inventions[i].num_required_techs++;
566 presearch->inventions[i].bulbs_required +=
568 /* This is needed to get a correct result for the
569 * research_total_bulbs_required() call when
570 * game.info.game.info.tech_cost_style is TECH_COST_CIV1CIV2. */
571 presearch->techs_researched++;
573 presearch->techs_researched = techs_researched;
575
576#ifdef FREECIV_DEBUG
578 char buf[advance_count() + 1];
579
581 if (BV_ISSET(presearch->inventions[i].required_techs, j)) {
582 buf[j] = '1';
583 } else {
584 buf[j] = '0';
585 }
587 buf[advance_count()] = '\0';
588
589 log_debug("%s: [%3d] %-25s => %s%s%s",
591 i,
594 presearch->inventions[i].reachable ? "" : " [unreachable]",
595 presearch->inventions[i].root_reqs_known
596 ? "" : " [root reqs aren't known]");
597 log_debug("%s: [%3d] %s", research_rule_name(presearch), i, buf);
599#endif /* FREECIV_DEBUG */
600
601 for (flag = 0; flag <= tech_flag_id_max(); flag++) {
602 /* Iterate over all possible tech flags (0..max). */
603 presearch->num_known_tech_with_flag[flag] = 0;
604
607 && advance_has_flag(i, flag)) {
608 presearch->num_known_tech_with_flag[flag]++;
609 }
611 }
612}
613
614/************************************************************************/
623 Tech_type_id tech)
624{
627
628 if (presearch != nullptr) {
629 return presearch->inventions[tech].state;
630 } else if (game.info.global_advances[tech]) {
631 return TECH_KNOWN;
632 } else {
633 return TECH_UNKNOWN;
634 }
635}
636
637/************************************************************************/
641 Tech_type_id tech,
642 enum tech_state value)
643{
644 enum tech_state old;
645
646 fc_assert_ret_val(valid_advance_by_number(tech) != nullptr, -1);
647
648 old = presearch->inventions[tech].state;
649 if (old == value) {
650 return old;
651 }
652 presearch->inventions[tech].state = value;
653
654 if (value == TECH_KNOWN) {
655 if (!game.info.global_advances[tech]) {
658 }
659 }
660
661 return old;
662}
663
664/************************************************************************/
672 const Tech_type_id tech)
673{
674 if (valid_advance_by_number(tech) == nullptr) {
675 return FALSE;
676 } else if (presearch != nullptr) {
677 return presearch->inventions[tech].reachable;
678 } else {
680 if (research_iter->inventions[tech].reachable) {
681 return TRUE;
682 }
684
685 return FALSE;
686 }
687}
688
689/************************************************************************/
697 const Tech_type_id tech,
698 bool allow_holes)
699{
700 if (valid_advance_by_number(tech) == nullptr) {
701 return FALSE;
702 } else if (presearch != nullptr) {
703 return (allow_holes
704 ? presearch->inventions[tech].root_reqs_known
705 : presearch->inventions[tech].state == TECH_PREREQS_KNOWN);
706 } else {
708 if (allow_holes
709 ? research_iter->inventions[tech].root_reqs_known
710 : research_iter->inventions[tech].state == TECH_PREREQS_KNOWN) {
711 return TRUE;
712 }
714
715 return FALSE;
716 }
717}
718
719/************************************************************************/
724 Tech_type_id goal)
725{
726 const struct advance *pgoal = valid_advance_by_number(goal);
727
728 if (pgoal == nullptr
730 return A_UNSET;
731 }
732
736 return advance_number(preq);
737 case TECH_KNOWN:
738 case TECH_UNKNOWN:
739 break;
740 };
742 return A_UNSET;
743}
744
745/************************************************************************/
754 Tech_type_id goal)
755{
756 const struct advance *pgoal = valid_advance_by_number(goal);
757
758 if (pgoal == nullptr) {
759 return 0;
760 } else if (presearch != nullptr) {
761 return presearch->inventions[goal].num_required_techs;
762 } else {
763 return pgoal->num_reqs;
764 }
765}
766
767/************************************************************************/
776 Tech_type_id goal)
777{
778 const struct advance *pgoal = valid_advance_by_number(goal);
779
780 if (pgoal == nullptr) {
781 return 0;
782 } else if (presearch != nullptr) {
783 return presearch->inventions[goal].bulbs_required;
785 int base_cost = game.info.base_tech_cost * pgoal->num_reqs
786 * (pgoal->num_reqs + 1) / 2;
787
789 return game.info.min_tech_cost;
790 } else {
791 return base_cost;
792 }
793 } else {
794 int bulbs_required = 0;
795
797 bulbs_required += preq->cost;
799
800 return bulbs_required;
801 }
802}
803
804/************************************************************************/
811 Tech_type_id goal, Tech_type_id tech)
812{
813 const struct advance *pgoal, *ptech;
814
815 if (tech == goal
816 || (pgoal = valid_advance_by_number(goal)) == nullptr
817 || (ptech = valid_advance_by_number(tech)) == nullptr) {
818 return FALSE;
819 } else if (presearch != nullptr) {
820 return BV_ISSET(presearch->inventions[goal].required_techs, tech);
821 } else {
823 if (preq == ptech) {
824 return TRUE;
825 }
827
828 return FALSE;
829 }
830}
831
832/************************************************************************/
873 Tech_type_id tech, bool loss_value)
874{
875 enum tech_cost_style tech_cost_style = game.info.tech_cost_style;
876 int members;
877 double base_cost, total_cost;
878 bool leakage = FALSE;
879
880 if (valid_advance_by_number(tech) == nullptr) {
881 return 0;
882 }
883
884 if (!loss_value
885 && presearch != nullptr
886 && !is_future_tech(tech)
888 /* A non-future tech which is already known costs nothing. */
889 return 0;
890 }
891
892 if (is_future_tech(tech)) {
893 /* Future techs use style TECH_COST_CIV1CIV2. */
894 tech_cost_style = TECH_COST_CIV1CIV2;
895 }
896
898 "Invalid tech_cost_style %d", tech_cost_style);
899 base_cost = 0.0;
900 switch (tech_cost_style) {
902 if (presearch != nullptr) {
903 base_cost = game.info.base_tech_cost * presearch->techs_researched;
904 break;
905 }
906
907 fc_assert(presearch != nullptr);
908 fc__fallthrough; /* No break; Fallback to using preset cost. */
913 case TECH_COST_LINEAR:
914 {
915 const struct advance *padvance = valid_advance_by_number(tech);
916
917 if (padvance != nullptr) {
918 base_cost = padvance->cost;
919 } else {
920 fc_assert(padvance != nullptr); /* Always fails. */
921 }
922 }
923 break;
924 }
925
926 total_cost = 0.0;
927 members = 0;
929 members++;
930 total_cost += (base_cost
932 if (!leakage && get_player_bonus(pplayer, EFT_TECH_LEAKAGE)) {
933 leakage = TRUE;
934 }
936 if (0 == members) {
937 /* There is no more alive players for this research, no need to apply
938 * complicated modifiers. */
939 return base_cost * (double) game.info.sciencebox / 100.0;
940 }
941 base_cost = total_cost / members;
942
943 if (leakage) {
944 double leak = 0.0;
945
947 "Invalid tech_leakage %d", game.info.tech_leakage);
948
949 switch (game.info.tech_leakage) {
951 /* No change */
952 break;
953
955 {
956 int players = 0, players_with_tech_and_embassy = 0;
957
959 const struct research *aresearch = research_get(aplayer);
960
961 players++;
962 if (aresearch == presearch
963 || (A_FUTURE == tech
964 ? aresearch->future_tech <= presearch->future_tech
966 continue;
967 }
968
970 if (player_has_embassy(pplayer, aplayer)) {
972 break;
973 }
976
977 fc_assert_ret_val(0 < players, base_cost);
980 * game.info.tech_leak_pct / players / 100;
981 }
982 break;
983
985 {
986 int players = 0, players_with_tech = 0;
987
989 players++;
990 if (A_FUTURE == tech
993 tech)) {
995 }
997
998 fc_assert_ret_val(0 < players, base_cost);
999 fc_assert(players >= players_with_tech);
1001 / players / 100;
1002 }
1003 break;
1004
1006 {
1007 int players = 0, players_with_tech = 0;
1008
1010 if (is_barbarian(aplayer)) {
1011 continue;
1012 }
1013 players++;
1014 if (A_FUTURE == tech
1017 tech)) {
1019 }
1021
1022 fc_assert_ret_val(0 < players, base_cost);
1023 fc_assert(players >= players_with_tech);
1025 / players / 100;
1026 }
1027 break;
1028 }
1029
1030 if (leak > base_cost) {
1031 base_cost = 0.0;
1032 } else {
1033 base_cost -= leak;
1034 }
1035 }
1036
1037 /* Assign a science penalty to the AI at easier skill levels. This code
1038 * can also be adopted to create an extra-hard AI skill level where the AI
1039 * gets science benefits. */
1040
1041 total_cost = 0.0;
1043 if (is_ai(pplayer)) {
1044 fc_assert(0 < pplayer->ai_common.science_cost);
1045 total_cost += base_cost * pplayer->ai_common.science_cost / 100.0;
1046 } else {
1047 total_cost += base_cost;
1048 }
1050 base_cost = total_cost / members;
1051
1052 base_cost *= (double) game.info.sciencebox / 100.0;
1053
1054 return MAX(base_cost, 1);
1055}
1056
1057
1058/************************************************************************/
1062int player_tech_upkeep(const struct player *pplayer)
1063{
1064 const struct research *presearch = research_get(pplayer);
1065 int f = presearch->future_tech, t = presearch->techs_researched;
1066 double tech_upkeep = 0.0;
1067 double total_research_factor;
1068 int members;
1069
1071 return 0;
1072 }
1073
1075 members = 0;
1078 + (is_ai(contributor)
1079 ? contributor->ai_common.science_cost / 100.0
1080 : 1));
1081 members++;
1083 if (0 == members) {
1084 /* No player still alive. */
1085 return 0;
1086 }
1087
1088 /* Upkeep cost for 'normal' techs (t). */
1090 "Invalid tech_cost_style %d", game.info.tech_cost_style);
1091 switch (game.info.tech_cost_style) {
1092 case TECH_COST_CIV1CIV2:
1093 /* sum_1^t x = t * (t + 1) / 2 */
1094 tech_upkeep += game.info.base_tech_cost * t * (t + 1) / 2;
1095 break;
1096 case TECH_COST_CLASSIC:
1100 case TECH_COST_LINEAR:
1104 tech_upkeep += padvance->cost;
1105 }
1107 if (0 < f) {
1108 /* Upkeep cost for future techs (f) are calculated using style 0:
1109 * sum_t^(t+f) x = (f * (2 * t + f + 1) + 2 * t) / 2 */
1110 tech_upkeep += (double) (game.info.base_tech_cost
1111 * (f * (2 * t + f + 1) + 2 * t) / 2);
1112 }
1113 break;
1114 }
1115
1116 tech_upkeep *= total_research_factor / members;
1117 tech_upkeep *= (double) game.info.sciencebox / 100.0;
1118 /* We only want to calculate the upkeep part of one player, not the
1119 * whole team! */
1120 tech_upkeep /= members;
1121 tech_upkeep /= game.info.tech_upkeep_divider;
1122
1123 switch (game.info.tech_upkeep_style) {
1124 case TECH_UPKEEP_BASIC:
1125 tech_upkeep -= get_player_bonus(pplayer, EFT_TECH_UPKEEP_FREE);
1126 break;
1128 tech_upkeep -= get_player_bonus(pplayer, EFT_TECH_UPKEEP_FREE);
1129 tech_upkeep *= city_list_size(pplayer->cities);
1130 break;
1131 case TECH_UPKEEP_NONE:
1133 tech_upkeep = 0.0;
1134 }
1135
1136 if (0.0 > tech_upkeep) {
1137 tech_upkeep = 0.0;
1138 }
1139
1140 log_debug("[%s (%d)] tech upkeep: %d", player_name(pplayer),
1141 player_number(pplayer), (int) tech_upkeep);
1142 return (int) tech_upkeep;
1143}
1144
1145
1146/************************************************************************/
1150{
1151 return sizeof(struct research_iter);
1152}
1153
1154/************************************************************************/
1157static void *research_iter_get(const struct iterator *it)
1158{
1159 return &research_array[RESEARCH_ITER(it)->index];
1160}
1161
1162/************************************************************************/
1165static void research_iter_team_next(struct iterator *it)
1166{
1167 struct research_iter *rit = RESEARCH_ITER(it);
1168
1169 if (team_slots_initialised()) {
1170 do {
1171 rit->index++;
1172 } while (rit->index < ARRAY_SIZE(research_array) && !it->valid(it));
1173 }
1174}
1175
1176/************************************************************************/
1179static bool research_iter_team_valid(const struct iterator *it)
1180{
1181 struct research_iter *rit = RESEARCH_ITER(it);
1182
1183 return (0 <= rit->index
1184 && ARRAY_SIZE(research_array) > rit->index
1185 && team_by_number(rit->index) != nullptr);
1186}
1187
1188/************************************************************************/
1192{
1193 struct research_iter *rit = RESEARCH_ITER(it);
1194
1196 do {
1197 rit->index++;
1198 } while (rit->index < ARRAY_SIZE(research_array) && !it->valid(it));
1199 }
1200}
1201
1202/************************************************************************/
1205static bool research_iter_player_valid(const struct iterator *it)
1206{
1207 struct research_iter *rit = RESEARCH_ITER(it);
1208
1209 return (0 <= rit->index
1210 && ARRAY_SIZE(research_array) > rit->index
1211 && player_by_number(rit->index) != nullptr);
1212}
1213
1214/************************************************************************/
1218{
1219 struct iterator *base = ITERATOR(it);
1220
1221 base->get = research_iter_get;
1222 it->index = -1;
1223
1227 } else {
1230 }
1231
1232 base->next(base);
1233 return base;
1234}
1235
1236/************************************************************************/
1240{
1241 return sizeof(struct research_player_iter);
1242}
1243
1244/************************************************************************/
1247static inline bool research_player_iter_valid_state(struct iterator *it)
1248{
1249 const struct player *pplayer = iterator_get(it);
1250
1251 return (pplayer == nullptr || pplayer->is_alive);
1252}
1253
1254/************************************************************************/
1257static void *research_player_iter_pooled_get(const struct iterator *it)
1258{
1260}
1261
1262/************************************************************************/
1266{
1268
1269 do {
1270 rpit->plink = player_list_link_next(rpit->plink);
1271 } while (!research_player_iter_valid_state(it));
1272}
1273
1274/************************************************************************/
1277static bool research_player_iter_pooled_valid(const struct iterator *it)
1278{
1279 return RESEARCH_PLAYER_ITER(it)->plink != nullptr;
1280}
1281
1282/************************************************************************/
1285static void *research_player_iter_not_pooled_get(const struct iterator *it)
1286{
1287 return RESEARCH_PLAYER_ITER(it)->pplayer;
1288}
1289
1290/************************************************************************/
1294{
1295 RESEARCH_PLAYER_ITER(it)->pplayer = nullptr;
1296}
1297
1298/************************************************************************/
1302{
1303 return RESEARCH_PLAYER_ITER(it)->pplayer != nullptr;
1304}
1305
1306/************************************************************************/
1310 const struct research *presearch)
1311{
1312 struct iterator *base = ITERATOR(it);
1313
1314 if (game.info.team_pooled_research && presearch != nullptr) {
1319 (presearch))));
1320 } else {
1324 it->pplayer = (presearch != nullptr
1326 }
1327
1328 /* Ensure we have consistent data. */
1331 }
1332
1333 return base;
1334}
1335
1336/************************************************************************/
1341{
1342 /* TODO: Should have the value stored at the time researches are created */
1343 int count = 0;
1344
1345 researches_iterate(dummy) {
1346 (void) dummy; /* To silence warning about unused 'dummy' */
1347 count++;
1349
1350 return count;
1351}
1352
1353/************************************************************************/
1358{
1359 int techs = 1; /* A_NONE known, and not part of below iteration */
1360
1361 advance_iterate(t) {
1362 if (valid_advance(t) != nullptr
1364 techs++;
1365 }
1367
1368 return techs + presearch->future_tech;
1369}
1370
1371/************************************************************************/
1375{
1378 return FALSE;
1379 }
1381
1382 return TRUE;
1383}
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
char * techs
Definition comments.c:31
char * incite_cost
Definition comments.c:76
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2966
struct @22::@23 reqs
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:824
int Tech_type_id
Definition fc_types.h:237
req_problem_type
Definition fc_types.h:513
@ RPT_CERTAIN
Definition fc_types.h:515
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct civ_game game
Definition game.c:62
const char * name
Definition inputfile.c:127
static void * iterator_get(const struct iterator *it)
Definition iterator.h:53
#define ITERATOR(p)
Definition iterator.h:37
static void iterator_next(struct iterator *it)
Definition iterator.h:42
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_debug(message,...)
Definition log.h:116
#define NAME_INIT
static void name_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name)
static const char * rule_name_get(const struct name_translation *ptrans)
static const char * name_translation_get(const struct name_translation *ptrans)
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
struct player * player_by_number(const int player_id)
Definition player.c:852
int player_slot_count(void)
Definition player.c:420
int player_number(const struct player *pplayer)
Definition player.c:839
const char * player_name(const struct player *pplayer)
Definition player.c:900
bool player_slots_initialised(void)
Definition player.c:378
bool player_has_embassy(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:208
static bool is_barbarian(const struct player *pplayer)
Definition player.h:491
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:552
#define players_iterate_alive(_pplayer)
Definition player.h:547
enum req_unchanging_status is_req_preventing(const struct req_context *context, const struct req_context *other_context, const struct requirement *req, enum req_problem_type prob_type)
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
int research_goal_unknown_techs(const struct research *presearch, Tech_type_id goal)
Definition research.c:753
static struct research research_array[RESEARCH_ARRAY_SIZE]
Definition research.c:52
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Definition research.c:671
bool research_goal_tech_req(const struct research *presearch, Tech_type_id goal, Tech_type_id tech)
Definition research.c:810
const char * research_name_translation(const struct research *presearch)
Definition research.c:158
#define research_may_become_allowed(presearch, tech)
Definition research.c:378
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:640
static struct name_translation advance_unknown_name
Definition research.c:56
struct research * research_by_number(int number)
Definition research.c:119
#define RESEARCH_ARRAY_SIZE
Definition research.c:51
const char * research_advance_rule_name(const struct research *presearch, Tech_type_id tech)
Definition research.c:243
int player_tech_upkeep(const struct player *pplayer)
Definition research.c:1062
bool research_future_next(const struct research *presearch)
Definition research.c:1374
static void * research_player_iter_not_pooled_get(const struct iterator *it)
Definition research.c:1285
static void * research_iter_get(const struct iterator *it)
Definition research.c:1157
static bool research_iter_player_valid(const struct iterator *it)
Definition research.c:1205
static void * research_player_iter_pooled_get(const struct iterator *it)
Definition research.c:1257
static struct name_translation advance_unset_name
Definition research.c:54
static void research_player_iter_not_pooled_next(struct iterator *it)
Definition research.c:1293
size_t research_iter_sizeof(void)
Definition research.c:1149
#define research_is_allowed(presearch, tech)
Definition research.c:369
void researches_init(void)
Definition research.c:64
static void research_player_iter_pooled_next(struct iterator *it)
Definition research.c:1265
int research_count(void)
Definition research.c:1340
static void research_iter_player_next(struct iterator *it)
Definition research.c:1191
static struct name_translation advance_future_name
Definition research.c:55
static bool research_get_root_reqs_known(const struct research *presearch, Tech_type_id tech)
Definition research.c:485
int research_number(const struct research *presearch)
Definition research.c:109
static bool research_player_iter_valid_state(struct iterator *it)
Definition research.c:1247
int research_goal_bulbs_required(const struct research *presearch, Tech_type_id goal)
Definition research.c:775
const char * research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Definition research.c:276
int research_total_bulbs_required(const struct research *presearch, Tech_type_id tech, bool loss_value)
Definition research.c:872
static const struct name_translation * research_advance_name(Tech_type_id tech)
Definition research.c:201
static bool research_allowed(const struct research *presearch, Tech_type_id tech, bool(*reqs_eval)(const struct req_context *context, const struct req_context *ocontext, const struct requirement_vector *reqs, const enum req_problem_type ptype))
Definition research.c:330
struct iterator * research_iter_init(struct research_iter *it)
Definition research.c:1217
int recalculate_techs_researched(const struct research *presearch)
Definition research.c:1357
#define RESEARCH_ITER(p)
Definition research.c:40
const char * research_rule_name(const struct research *presearch)
Definition research.c:145
static struct strvec * future_rule_name
Definition research.c:58
static bool research_get_reachable_rreqs(const struct research *presearch, Tech_type_id tech)
Definition research.c:387
struct research * research_get(const struct player *pplayer)
Definition research.c:130
void researches_free(void)
Definition research.c:100
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:622
static bool research_get_reachable(const struct research *presearch, Tech_type_id tech)
Definition research.c:443
static bool research_player_iter_not_pooled_valid(const struct iterator *it)
Definition research.c:1301
static bool research_iter_team_valid(const struct iterator *it)
Definition research.c:1179
Tech_type_id research_goal_step(const struct research *presearch, Tech_type_id goal)
Definition research.c:723
static bool reqs_may_activate(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
Definition research.c:306
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Definition research.c:696
static bool research_player_iter_pooled_valid(const struct iterator *it)
Definition research.c:1277
#define RESEARCH_PLAYER_ITER(p)
Definition research.c:49
size_t research_player_iter_sizeof(void)
Definition research.c:1239
static const char * research_future_set_name(struct strvec *psv, int no, const char *new_name)
Definition research.c:222
struct iterator * research_player_iter_init(struct research_player_iter *it, const struct research *presearch)
Definition research.c:1309
static struct strvec * future_name_translation
Definition research.c:59
void research_update(struct research *presearch)
Definition research.c:504
static void research_iter_team_next(struct iterator *it)
Definition research.c:1165
int research_pretty_name(const struct research *presearch, char *buf, size_t buf_len)
Definition research.c:171
#define research_players_iterate(_presearch, _pplayer)
Definition research.h:166
#define researches_iterate(_presearch)
Definition research.h:155
#define research_players_iterate_end
Definition research.h:170
#define researches_iterate_end
Definition research.h:158
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MAX(x, y)
Definition shared.h:54
void strvec_destroy(struct strvec *psv)
bool strvec_set(struct strvec *psv, size_t svindex, const char *string)
void strvec_reserve(struct strvec *psv, size_t reserve)
const char * strvec_get(const struct strvec *psv, size_t svindex)
struct strvec * strvec_new(void)
size_t strvec_size(const struct strvec *psv)
struct requirement_vector research_reqs
Definition tech.h:134
struct packet_ruleset_control control
Definition game.h:83
struct packet_game_info info
Definition game.h:89
bool(* valid)(const struct iterator *it)
Definition iterator.h:34
bool global_advances[A_LAST]
enum tech_upkeep_style tech_upkeep_style
enum tech_leakage_style tech_leakage
enum tech_cost_style tech_cost_style
struct city_list * cities
Definition player.h:281
struct team * team
Definition player.h:261
bool is_alive
Definition player.h:268
enum tech_state state
Definition research.h:71
struct iterator vtable
Definition research.c:37
struct iterator vtable
Definition research.c:43
struct player * pplayer
Definition research.c:45
struct player_list_link * plink
Definition research.c:46
Tech_type_id researching
Definition research.h:52
int future_tech
Definition research.h:42
Tech_type_id tech_goal
Definition research.h:83
struct research::research_invention inventions[A_ARRAY_SIZE]
Tech_type_id researching_saved
Definition research.h:62
Definition team.c:40
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define fc__fallthrough
Definition support.h:119
struct team * team_by_number(const int team_id)
Definition team.c:400
const char * team_name_translation(const struct team *pteam)
Definition team.c:420
const char * team_rule_name(const struct team *pteam)
Definition team.c:410
int team_number(const struct team *pteam)
Definition team.c:391
bool team_slots_initialised(void)
Definition team.c:77
int team_pretty_name(const struct team *pteam, char *buf, size_t buf_len)
Definition team.c:432
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
int team_slot_count(void)
Definition team.c:112
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
struct advance * valid_advance(struct advance *padvance)
Definition tech.c:152
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:216
struct advance * advance_requires(const struct advance *padvance, enum tech_req require)
Definition tech.c:136
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
Tech_type_id advance_required(const Tech_type_id tech, enum tech_req require)
Definition tech.c:121
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define A_FUTURE
Definition tech.h:46
#define advance_index_iterate_max(_start, _index, _max)
Definition tech.h:250
#define advance_index_iterate_end
Definition tech.h:246
#define advance_req_iterate(_goal, _padvance)
Definition tech.h:297
tech_req
Definition tech.h:107
@ AR_TWO
Definition tech.h:109
@ AR_ROOT
Definition tech.h:110
@ AR_ONE
Definition tech.h:108
@ AR_SIZE
Definition tech.h:111
#define advance_index_iterate_max_end
Definition tech.h:256
#define advance_req_iterate_end
Definition tech.h:301
static Tech_type_id advance_count(void)
Definition tech.h:167
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_root_req_iterate_end
Definition tech.h:317
#define advance_iterate(_p)
Definition tech.h:273
#define A_UNSET
Definition tech.h:48
#define advance_iterate_end
Definition tech.h:274
#define A_UNKNOWN
Definition tech.h:49
#define advance_index_iterate(_start, _index)
Definition tech.h:242
#define advance_root_req_iterate(_goal, _padvance)
Definition tech.h:312