Freeciv-3.4
Loading...
Searching...
No Matches
techtools.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2005 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 "astring.h"
19#include "fcintl.h"
20#include "log.h"
21#include "mem.h"
22#include "rand.h"
23#include "shared.h"
24#include "support.h"
25
26/* common */
27#include "game.h"
28#include "government.h"
29#include "movement.h"
30#include "player.h"
31#include "research.h"
32#include "tech.h"
33#include "unit.h"
34
35/* common/scriptcore */
36#include "luascript_types.h"
37
38/* server */
39#include "citytools.h"
40#include "cityturn.h"
41#include "connecthand.h"
42#include "gamehand.h"
43#include "maphand.h"
44#include "notify.h"
45#include "plrhand.h"
46#include "unittools.h"
47
48/* server/scripting */
49#include "script_server.h"
50
51#include "techtools.h"
52
53/* Define this to add information about tech upkeep. */
54#undef TECH_UPKEEP_DEBUGGING
55
56static Tech_type_id
60static void research_tech_lost(struct research *presearch,
61 Tech_type_id tech);
62static void forget_tech_transferred(struct player *pplayer, Tech_type_id tech);
63
64/************************************************************************/
69{
71 return;
72 }
73 presearch->bulbs_researched -=
75 * penalty_percent) / 100;
76 presearch->researching_saved = A_UNKNOWN;
77}
78
79/************************************************************************/
85 struct player *originating_plr, struct advance *tech,
86 const char *reason)
87{
88 /* Emit signal for individual player whose action triggered the
89 * tech first */
90 if (originating_plr) {
92 script_server_signal_emit("tech_researched", tech, originating_plr,
93 reason);
94 }
95
96 /* Emit signal to remaining research teammates, if any */
98 if (member != originating_plr) {
99 script_server_signal_emit("tech_researched", tech, member, reason);
100 }
102}
103
104/************************************************************************/
108{
109 char research_name[MAX_LEN_NAME * 2];
110 /* Cache researched technology for event signal, because found_new_tech()
111 * changes the research target. */
113
115 /* Players will be notified when new tech is chosen. */
118 _("The %s have researched %s."),
121
122 /* Deduct tech cost. */
124 FALSE);
126 if (j == research->researching) {
129 }
131
132
133 /* Do all the updates needed after finding new tech. */
135
136 script_tech_learned(research, NULL, advance_by_number(tech), "researched");
137}
138
139/************************************************************************/
143void do_tech_parasite_effects(struct player *pplayer)
144{
147 struct effect_list *plist;
148 struct astring effects;
149 struct research *plr_research;
150 char research_name[MAX_LEN_NAME * 2];
151 const char *advance_name;
152 Tech_type_id tech;
153 /* Note that two EFT_TECH_PARASITE* effects will combine into a single,
154 * much worse effect. */
155 int mod_abs;
156 int mod_pct;
157 int mod;
158 int num_techs;
159 int rcount = research_count();
160
163
164 mod = (rcount * mod_pct) / 100;
165
166 if (mod <= 0 && mod_abs <= 0) {
167 /* No effects. */
170 return;
171 }
172
173 if (mod > 0 && (mod_abs <= 0 || mod_abs > mod)) {
176 } else {
177 mod = mod_abs;
180 }
181
182 /* Pick a random technology. */
183 tech = A_UNSET;
184 num_techs = 0;
185 plr_research = research_get(pplayer);
187 int num_teams;
188
192 continue;
193 }
194
195 num_teams = 0;
198 if (mod <= ++num_teams) {
199 if (0 == fc_rand(++num_techs)) {
200 tech = i;
201 }
202 break;
203 }
204 }
207
208 if (A_UNSET == tech) {
209 /* No tech found. */
211 return;
212 }
213
214 /* Notify. */
219
221 /* TRANS: Tech from source of an effect
222 * (Great Library) */
223 Q_("?fromeffect:%s acquired from %s!"),
225 astr_str(&effects));
227 /* TRANS: Tech from source of an effect
228 * (Great Library) */
229 Q_("?fromeffect:%s acquired from %s's %s!"),
231 player_name(pplayer),
232 astr_str(&effects));
234 /* TRANS: Tech from source of an effect
235 * (Great Library) */
236 Q_("?fromeffect:The %s have acquired %s from %s."),
239 astr_str(&effects));
240
243
244 /* Really get tech. */
247
249 script_server_signal_emit("tech_researched", advance_by_number(tech),
250 member, "stolen");
252}
253
254/************************************************************************/
257static inline void
259 const struct research *presearch)
260{
261 packet->id = research_number(presearch);
262 packet->techs_researched = presearch->techs_researched;
263 packet->future_tech = presearch->future_tech;
264 packet->researching = presearch->researching;
265 packet->researching_cost =
266 (packet->researching != A_UNSET
268 FALSE) : 0);
269 packet->bulbs_researched = presearch->bulbs_researched;
270 packet->tech_goal = presearch->tech_goal;
271 packet->total_bulbs_prod = 0;
273 city_list_iterate(pplayer->cities, pcity) {
274 packet->total_bulbs_prod += pcity->surplus[O_SCIENCE];
278 packet->inventions[i] = presearch->inventions[i].state + '0';
280 packet->inventions[advance_count()] = '\0';
281 packet->tech_goal = presearch->tech_goal;
282#ifdef FREECIV_DEBUG
283 log_verbose("Research nb %d inventions: %s",
285 packet->inventions);
286#endif /* FREECIV_DEBUG */
287}
288
289/************************************************************************/
294 const struct conn_list *dest)
295{
298 const struct player *pplayer;
299
301 if (NULL == dest) {
302 dest = game.est_connections;
303 }
304
305 /* Packaging */
308 restricted_info.tech_goal = A_UNSET;
309 restricted_info.total_bulbs_prod = 0;
311
312 conn_list_iterate(dest, pconn) {
313 pplayer = conn_get_player(pconn);
314 if (NULL != pplayer) {
315 if (presearch == research_get(pplayer)) {
316 /* Case research owner. */
318 } else {
319 /* 'pplayer' may have an embassy for looking to 'presearch'. */
320 bool embassy = FALSE;
321
323 if (team_has_embassy(pplayer->team, powner)) {
324 embassy = TRUE;
325 break;
326 }
328
329 if (embassy) {
331 } else {
333 }
334 }
335 } else if (pconn->observer) {
336 /* Case global observer. */
338 }
340}
341
342/************************************************************************/
348 bool was_discovery, bool saving_bulbs)
349{
352 bool was_first = FALSE;
353 bool bonus_tech_hack = FALSE;
354 int i;
355 const char *advance_name;
357 struct city *pcity;
358
360
361#ifndef FREECIV_NDEBUG
362 fc_assert(NULL != vap);
364#endif /* FREECIV_NDEBUG */
365
366 /* global_advances has not yet been updated */
368 }
369 /* improvement_obsolete() depends on updated global_advances,
370 * so need to do the code that updates it now,
371 * research_invention_set() does it */
372
373 /* Memorize some values before the tech is marked as researched.
374 * We will check what has changed later. */
377
378 /* Count EFT_HAVE_EMBASSIES effect for each player. */
381
383
384 /* Getting tech allows us to change research without applying techpenalty
385 * (without losing bulbs) */
386 if (tech_found == presearch->researching) {
387 presearch->free_bulbs = presearch->bulbs_researched;
388 }
389 presearch->researching_saved = A_UNKNOWN;
390 presearch->techs_researched++;
391
392 /* Assign 'advance_name' before we increase the future tech counter. */
394
395 /* Mark the tech as known in the research struct and update
396 * global_advances array. */
398 presearch->future_tech++;
399 } else {
402 }
403
404 if (vap) {
405 /* Alert the owners of any wonders that have been made obsolete */
406 improvement_iterate(pimprove) {
407 requirement_vector_iterate(&pimprove->obsolete_by, pobs) {
408 struct player *city_owner_player = NULL;
409 bool is_obsolete = FALSE;
410
411 if (is_great_wonder(pimprove)) {
412 pcity = city_from_great_wonder(pimprove);
413 if (pcity) {
416 pimprove, pcity);
417 }
418 }
419 if (is_obsolete
420 && pobs->source.kind == VUT_ADVANCE
421 && pobs->source.value.advance == vap
422 && pobs->present) {
423 bool is_range_ok = FALSE;
424 struct player *tech_player =
426 struct team *tech_team = NULL;
427
428 /* research owner is a team if shared research is enabled */
431 }
432 switch (pobs->range) {
433 case REQ_RANGE_LOCAL:
434 case REQ_RANGE_TILE:
437 case REQ_RANGE_CITY:
440 /* these ranges not supported for req type "Tech" */
441 break;
442 case REQ_RANGE_PLAYER:
444 if (tech_team == city_owner_player->team) {
446 }
447 } else {
450 }
451 }
452 break;
453 case REQ_RANGE_TEAM:
455 if (tech_team == city_owner_player->team) {
457 }
458 } else {
461 }
462 }
463 break;
469 }
471 } else {
474 }
475 }
476 break;
477 case REQ_RANGE_WORLD:
479 break;
480 default:
481 break;
482 }
483 if (is_range_ok) {
486 _("Discovery of %s OBSOLETES %s in %s!"),
491 }
492 }
495 }
496
497 if (was_first
501 }
502
503 /* Inform players about their new tech. */
505
506 if (was_first) {
507 /* Inform all players about new global advances to give them a
508 * chance for obsolete buildings. */
510 }
511
512 /* Make proper changes for all players. Use shuffled order, in case
513 * a script would detect a signal. */
517
518 if (shares_research) {
519 char buf[250];
520
521 /* Give free infrastructure in every city */
522 if (tech_found != A_FUTURE) {
524
525 /* Revealing of extras with visibility_req */
526 whole_map_iterate(&(wld.map), ptile) {
527 if (map_is_known_and_seen(ptile, aplayer, V_MAIN)) {
529 send_tile_info(aplayer->connections, ptile, FALSE);
530 }
531 }
533 }
534
535 /* Enhance vision of units if a player-ranged effect has changed. Note
536 * that world-ranged effects will not be updated immediately. */
538
539 if (shares_research) {
540 fc_snprintf(buf, sizeof(buf), _("Discovery of %s"), advance_name);
541
543 }
544 }
545
546 /* For any player. */
547 /* Update all cities in case the tech changed some effects. This is
548 * inefficient; it could be optimized if it's found to be a problem.
549 * But techs aren't researched that often. */
551 /* Refresh the city data; this also updates the squared city radius. */
556
557 /* Send all player an updated info of the owner of the Marco Polo
558 * Wonder if this wonder has become obsolete. */
559 if (had_embassies[i] > 0
561 send_player_all_c(aplayer, aplayer->connections);
563 if (aplayer != pother_player) {
566 }
568 }
570
572
573 if (tech_found == presearch->tech_goal) {
574 presearch->tech_goal = A_UNSET;
575 }
576
577 if (tech_found == presearch->researching) {
578 /* Try to pick new tech to research. */
580 presearch->tech_goal);
581
582 /* As this function can be recursive, we need to print the messages
583 * before really picking the new technology. */
584 if (A_UNSET != next_tech) {
586 _("Learned %s. Our scientists focus on %s; "
587 "goal is %s."),
590 next_tech),
592 (presearch, presearch->tech_goal));
593 } else {
595 /* Use pick_random_tech() to determine if there now is
596 * a regular tech to research, e.g., if one was lost
597 * due to tech upkeep since we started researching future techs. */
599
600 /* Continue researching future tech, if possible. */
601 if (next_tech != A_FUTURE) {
602 bool ai_found = FALSE;
603
604 /* Otherwise check if there's an AI player to support
605 * randomly selected tech (one that "made" the decision) */
607 if (is_ai(aplayer)) {
608 ai_found = TRUE;
609 }
611
612 if (!ai_found) {
613 /* Decision is humans' to make */
615 }
616 }
617 } else {
618 /* If there is at least one AI player still alive, then pick
619 * a random tech, else keep A_UNSET. */
621 if (is_ai(aplayer)) {
623 break;
624 }
626 }
627
628 if (A_UNSET == next_tech) {
630 _("Learned %s. Scientists "
631 "do not know what to research next."),
633 } else {
635 _("Learned %s. Scientists choose to research %s."),
638 next_tech));
639 }
640 }
641
642 if (A_UNSET != next_tech) {
644 } else {
645 presearch->researching = A_UNSET;
646 }
647 }
648
649 if (!saving_bulbs && presearch->bulbs_researched > 0) {
650 presearch->bulbs_researched = 0;
651 }
652
653 if (bonus_tech_hack) {
655 char research_name[MAX_LEN_NAME * 2];
656 const char *radv_name;
657
659
661
663
665 if (advance_by_number(tech_found)->bonus_message != NULL
666 && additional_tech != A_UNSET) {
668 _(advance_by_number(tech_found)->bonus_message),
669 radv_name);
670 } else if (additional_tech != A_UNSET) {
671 /* FIXME: "your" when it was just civilization of one of the players
672 * sharing the research. */
674 _("Great scientists from all the "
675 "world join your civilization: you learn "
676 "%s immediately."), radv_name);
677 }
678 /* TODO: Ruleset should be able to customize this message too */
680 _("%s acquire %s as a result of learning %s."),
682 }
683}
684
685/************************************************************************/
688static bool lose_tech(struct research *research)
689{
691 /* Tech loss disabled */
692 return FALSE;
693 }
694
695 if (research->techs_researched == 0) {
696 /* No tech to lose */
698 return FALSE;
699 }
700
701 /* First check is not for optimization only - it protects
702 * research_total_bulbs_required() from getting called before research
703 * has even been set to value other than A_UNSET. */
707 * game.info.techloss_forgiveness / 100)) {
708 return TRUE;
709 }
710
711 return FALSE;
712}
713
714/************************************************************************/
726void update_bulbs(struct player *pplayer, int bulbs, bool check_tech,
727 bool free_bulbs)
728{
729 struct research *research = research_get(pplayer);
730
731 if (!pplayer->is_alive) {
732 /* Dead players do not produce research */
733 return;
734 }
736
737 /* Count our research contribution this turn */
738 pplayer->server.bulbs_last_turn += bulbs;
743 }
747 }
749 if (j == research->researching) {
751 }
753
754
755 do {
756 /* If we have a negative number of bulbs we do try to:
757 * - reduce the number of future techs;
758 * - or lose one random tech.
759 * After that the number of bulbs available is increased based on the
760 * value of the lost tech. */
761 if (lose_tech(research)) {
764
765 if (tech != A_NONE) {
766 if (game.server.techloss_restore >= 0) {
770 } else {
772 }
774
775 log_debug("%s: tech loss (%s)",
777 (is_future_tech(tech) ? "Future Tech"
780 /* Make notification after losing the research, in case it is
781 * a future tech (for getting the right tech number). */
783 _("Insufficient science output. We lost %s."),
785 }
786 }
787
788 /* Check for finished research. */
789 if (!check_tech
793 FALSE))) {
794 break;
795 }
796
798 } while (research->researching != A_UNSET);
799}
800
801/************************************************************************/
804static Tech_type_id
806{
809 /* A_NONE included in advance_count(). */
810 int eligible = full_count - 1;
811 int chosen;
812
814
817 if (BV_ISSET(eligible_techs, i)) {
818 eligible--;
820 }
821 } else {
822 /* Knowing this tech may make others ineligible */
824
825 /* Never lose techs that are root_req for a currently known tech
826 * (including self root_req) */
827 if (root != A_NONE && BV_ISSET(eligible_techs, root)) {
828 eligible--;
830 }
832 /* Ruleset can prevent this kind of tech loss from opening up
833 * holes in the tech tree */
835
838 eligible--;
840 }
843 eligible--;
845 }
846 }
847 }
849
850 if (eligible == 0) {
851 /* no researched technology at all */
852 return A_NONE;
853 }
854
855 chosen = fc_rand(eligible) + 1;
856
858 if (BV_ISSET(eligible_techs, i)) {
859 chosen--;
860 if (chosen == 0) {
861 return i;
862 }
863 }
865
866 /* should never be reached */
867 fc_assert_msg(chosen == 0, "internal error (eligible=%d, chosen=%d)",
869 return A_NONE;
870}
871
872/************************************************************************/
875static inline struct government *
877{
878 struct government *picked = NULL;
879 int gov_nb = 0;
880
882 if (can_change_to_government(pplayer, pgov) && 0 == fc_rand(++gov_nb)) {
883 picked = pgov;
884 }
887 return picked;
888}
889
890/************************************************************************/
894{
895 char research_name[MAX_LEN_NAME * 2];
896 /* Research members will be notified when new tech is chosen. */
897 const struct civ_map *nmap = &(wld.map);
898
900
901 presearch->techs_researched--;
902 if (is_future_tech(tech)) {
903 presearch->future_tech--;
905 /* Notify after decreasing the future tech counter, to get the right
906 * tech number in the message. */
908 _("The %s have lost %s."),
911 tech));
912 /* Inform players about their technology loss. */
914 return;
915 }
916
919 /* TRANS: technology loss */
920 _("The %s have lost %s."),
923 tech));
924
925 /* Remove technology. */
928 log_debug("%s lost tech id %d (%s)", research_rule_name(presearch), tech,
930
931 /* Inform players about their technology loss. */
933
935 /* Check government. */
936 if (!can_change_to_government(pplayer, government_of_player(pplayer))) {
937 /* Lost the technology for the government; switch to random
938 * available government. */
939 struct government *pgov = pick_random_government(pplayer);
940
942 _("The required technology for our government '%s' "
943 "was lost. The citizens have started a "
944 "revolution into '%s'."),
946 (pplayer)),
949 send_player_info_c(pplayer, NULL);
950 } else if (NULL != pplayer->target_government
951 && !can_change_to_government(pplayer,
952 pplayer->target_government)) {
953 /* Lost the technology for the target government; use a random
954 * available government as new target government. */
955 struct government *pgov = pick_random_government(pplayer);
956
958 _("The required technology for our new government "
959 "'%s' was lost. The citizens chose '%s' as new "
960 "target government."),
961 government_name_translation(pplayer->target_government),
963 pplayer->target_government = pgov;
964 send_player_info_c(pplayer, pplayer->connections);
965 }
966
967 /* Check all units for valid activities. */
969
970 /* Check city production */
971 city_list_iterate(pplayer->cities, pcity) {
972 bool update = FALSE;
973
974 if (pcity->production.kind == VUT_UTYPE
975 && !can_city_build_unit_now(nmap, pcity, pcity->production.value.utype,
976 RPT_CERTAIN)) {
977 notify_player(pplayer, city_tile(pcity),
979 _("%s can't build %s. The required technology was "
980 "lost."),
982 utype_name_translation(pcity->production.value.utype));
983 choose_build_target(pplayer, pcity);
984 update = TRUE;
985 }
986
987 if (pcity->production.kind == VUT_IMPROVEMENT
989 pcity->production.value.building,
990 RPT_CERTAIN)) {
991 notify_player(pplayer, city_tile(pcity),
993 _("%s can't build %s. The required technology was "
994 "lost."),
997 (pcity->production.value.building));
998 choose_build_target(pplayer, pcity);
999 update = TRUE;
1000 }
1001
1002 if (update) {
1004 send_city_info(pplayer, pcity);
1005 }
1008}
1009
1010/************************************************************************/
1014{
1015 Tech_type_id tech = A_FUTURE;
1016 int num_techs = 0;
1017
1020 if (fc_rand(++num_techs) == 0) {
1021 tech = i;
1022 }
1023 }
1025
1026 return tech;
1027}
1028
1029/************************************************************************/
1033{
1034 int cheapest_cost = -1;
1035 int cheapest_amount = 0;
1036 Tech_type_id cheapest = A_FUTURE; /* If no real tech is found to be missing */
1037
1041
1042 if (cost < cheapest_cost || cheapest_cost == -1) {
1044 cheapest_amount = 1;
1045 cheapest = i;
1046 } else if (cost == cheapest_cost && fc_rand(++cheapest_amount) == 0) {
1047 cheapest = i;
1048 }
1049 }
1051
1052 return cheapest;
1053}
1054
1055/************************************************************************/
1065{
1066 do {
1068 } while (research->researching == A_UNSET);
1069}
1070
1071/************************************************************************/
1080{
1081 int bulbs_res = 0;
1082
1083 if (is_future_tech(tech)) {
1088 }
1089 } else {
1090 if (research->researching == tech) {
1091 return;
1092 }
1094 /* Can't research this. */
1095 return;
1096 }
1097 }
1098
1101 /* Save old tech research */
1102 if (j == research->researching) {
1104 }
1105 /* New tech*/
1106 if (j == tech) {
1108 }
1110 research->researching = tech;
1112 research->free_bulbs = 0;
1116 }
1117 return;
1118 }
1119
1120 /* The first check implies we have NOT recently got a technology
1121 * and are changing from one we were researching at tc. */
1126 /* Subtract a penalty because we changed subject. */
1127 if (research->bulbs_researched > 0) {
1130 * game.server.techpenalty) / 100;
1131 /* If free_bulbs were for some reason negative... */
1133 }
1134 } else if (tech == research->researching_saved) {
1137 }
1138 research->researching = tech;
1142 }
1143}
1144
1145/************************************************************************/
1150{
1152
1153 if (tech == presearch->tech_goal) {
1154 return;
1155 }
1156
1157 /* It's been suggested that if the research target is empty then
1158 * choose_random_tech() should be called here. */
1159 presearch->tech_goal = tech;
1161 _("Technology goal is %s."),
1163}
1164
1165/************************************************************************/
1168void init_tech(struct research *research, bool update)
1169{
1171
1173
1177
1178#ifdef TECH_UPKEEP_DEBUGGING
1179 /* Print a list of the needed upkeep if 'i' techs are researched.
1180 * If the ruleset contains self-rooted techs this can not work! */
1181 {
1182 bool global_state[A_LAST];
1183 Tech_type_id tech = A_LAST;
1184
1185 /* Save the game research state. */
1189
1192
1193 /* Show research costs. */
1195 log_debug("[research %d] %-25s (ID: %3d) cost: %6d - reachable: %-3s "
1196 "(now) / %-3s (ever)", research_number(research),
1200 ? "yes" : "no",
1201 research_invention_reachable(research, i) ? "yes" : "no");
1203
1204 /* Update step for step each tech as known and print the upkeep. */
1205 while (tech != A_NONE) {
1206 tech = A_NONE;
1210 /* Found a tech which can be researched. */
1211 tech = i;
1212 break;
1213 }
1215
1216 if (tech != A_NONE) {
1219
1220 /* This will change the game state! */
1222
1224 log_debug("[player %d] researched: %-25s (ID: %4d) techs: %3d "
1225 "upkeep: %4d", research_number(research),
1229 }
1230 }
1231
1232 /* Reset the changes done. */
1237 }
1238#endif /* TECH_UPKEEP_DEBUGGING */
1239
1241
1242 if (update) {
1244
1245 /* Mark the reachable techs */
1247
1249 if (A_UNSET != next_tech) {
1251 } else {
1253 }
1254 }
1255}
1256
1257/************************************************************************/
1263{
1264 int i;
1265
1266 /* Global techs. */
1267 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
1269 break;
1270 }
1271 /* Maybe the player already got this tech by an other way (e.g. team). */
1273 != TECH_KNOWN) {
1275 FALSE, TRUE);
1276 }
1277 }
1278
1279 /* Nation techs. */
1281 const struct nation_type *pnation = nation_of_player(pplayer);
1282
1283 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
1284 if (pnation->init_techs[i] == A_LAST) {
1285 break;
1286 }
1287 /* Maybe the player already got this tech by an other way. */
1289 != TECH_KNOWN) {
1291 }
1292 }
1294
1295 /* Random free techs (N.B.: freecost penalty not applied). */
1296 for (i = 0; i < num_random_techs; i++) {
1298 }
1299}
1300
1301/************************************************************************/
1310{
1311 struct research *presearch, *vresearch;
1313 const char *advance_name;
1314 char research_name[MAX_LEN_NAME * 2];
1315
1317 return A_NONE;
1318 }
1319
1320 presearch = research_get(pplayer);
1322
1323 if (preferred == A_UNSET) {
1324 int j = 0;
1326
1332 j++;
1333 }
1335
1336 if (j == 0) {
1337 /* We've moved on to future tech */
1338 if (vresearch->future_tech > presearch->future_tech) {
1340 } else {
1341 return A_NONE;
1342 }
1343 } else {
1344 /* Pick random tech */
1345 j = fc_rand(j) + 1;
1346 stolen_tech = A_NONE; /* Avoid compiler warning */
1352 j--;
1353 }
1354 if (j == 0) {
1355 stolen_tech = i;
1356 break;
1357 }
1360 }
1361 } else { /* preferred != A_UNSET */
1362#ifndef FREECIV_NDEBUG
1363 if (!is_future_tech(preferred)) {
1366 preferred));
1367 }
1368#endif /* FREECIV_NDEBUG */
1370 }
1371
1375 _("You steal %s from the %s."),
1379 _("The %s stole %s from the %s and shared it with you."),
1380 nation_plural_for_player(pplayer),
1383
1385 _("The %s stole %s from you!"),
1386 nation_plural_for_player(pplayer),
1387 advance_name);
1388
1390 _("The %s have stolen %s from the %s."),
1394
1395 if (tech_transfer(pplayer, victim, stolen_tech)) {
1399 "stolen");
1400 return stolen_tech;
1401 }
1402
1403 return A_NONE;
1404}
1405
1406/************************************************************************/
1413void handle_player_research(struct player *pplayer, int tech)
1414{
1415 struct research *research = research_get(pplayer);
1416
1417 if (tech != A_FUTURE && !valid_advance_by_number(tech)) {
1418 return;
1419 }
1420
1421 if (tech != A_FUTURE
1423 return;
1424 }
1425
1426 choose_tech(research, tech);
1427
1428 /* Notify players sharing the same research. */
1430}
1431
1432/************************************************************************/
1436void handle_player_tech_goal(struct player *pplayer, int tech_goal)
1437{
1438 struct research *research = research_get(pplayer);
1439
1440 /* Set the tech goal to a defined state if it is
1441 * - not a future tech and not a valid goal
1442 * - not a future tech and not a valid advance
1443 * - not defined
1444 * - known (i.e. due to EFT_GIVE_IMM_TECH). */
1445 if ((tech_goal != A_FUTURE
1448 || (tech_goal == A_NONE)
1451 }
1452
1454
1455 /* Notify players sharing the same research. */
1457}
1458
1459/************************************************************************/
1463{
1464 Tech_type_id tech;
1465
1468 } else if (presearch->researching == A_UNSET
1471 } else {
1472 tech = presearch->researching;
1473 }
1474 return tech;
1475}
1476
1477/************************************************************************/
1486
1487/************************************************************************/
1490static void forget_tech_transferred(struct player *pplayer, Tech_type_id tech)
1491{
1492 struct research *presearch = research_get(pplayer);
1493
1495 /* Make notification after losing the research, in case it is a future
1496 * tech (for getting the right tech number). */
1498 _("Too bad! You made a mistake transferring the tech %s and "
1499 "lost it."),
1502 _("Too bad! The %s made a mistake transferring the tech "
1503 "%s and lost it."),
1504 nation_plural_for_player(pplayer),
1506}
1507
1508/************************************************************************/
1513 Tech_type_id tech)
1514{
1515 if (game.server.techlost_donor > 0) {
1517 bool donor_can_lose = TRUE;
1518
1520 /* Never let donor lose tech if it's root_req for some other known
1521 * tech */
1523 && (advance_required(i, AR_ROOT) == tech
1525 && (advance_required(i, AR_ONE) == tech
1526 || advance_required(i, AR_TWO) == tech)))) {
1528 break;
1529 }
1533 }
1534 }
1535
1536 if (fc_rand(100) < game.server.techlost_recv) {
1538
1539 /* We've not received the tech yet, and never will.
1540 * Do not call forget_tech_transferred() that would handle it
1541 * as something we had and now lose.
1542 * (e.g. subtracting techs_researched counter) */
1544 _("Too bad! You made a mistake transferring the tech %s and "
1545 "didn't get it."),
1548 _("Too bad! The %s made a mistake transferring the tech "
1549 "%s and didn't get it."),
1552 return FALSE;
1553 }
1554
1555 return TRUE;
1556}
1557
1558/************************************************************************/
1565{
1566 struct cur_govs_data *data = fc_malloc(sizeof(struct cur_govs_data));
1567
1568 data->players = fc_malloc(sizeof(*data->players) * player_slot_count());
1569
1570 players_iterate(pplayer) {
1571 data->players[player_index(pplayer)].govs = fc_malloc(sizeof(bool) * government_count());
1573
1575 /* Memorize for the players sharing the research what government
1576 * they could switch on. */
1579 = can_change_to_government(pplayer, pgov);
1582
1583 return data;
1584}
1585
1586/************************************************************************/
1593{
1594 struct cur_govs_data *data = fc_malloc(sizeof(struct cur_govs_data));
1595
1596 data->players = fc_malloc(sizeof(*data->players) * player_slot_count());
1597
1598 players_iterate(pplayer) {
1599 data->players[player_index(pplayer)].govs = fc_malloc(sizeof(bool) * government_count());
1602 = can_change_to_government(pplayer, pgov);
1605
1606 return data;
1607}
1608
1609/************************************************************************/
1613{
1614 players_iterate(pplayer) {
1615 free(data->players[player_index(pplayer)].govs);
1617
1618 free(data->players);
1619 free(data);
1620}
1621
1622/************************************************************************/
1627 struct cur_govs_data *data,
1628 const char *reason)
1629{
1630 struct government *available = NULL;
1631
1633 if (!data->players[player_index(pplayer)].govs[government_index(pgov)]
1634 && can_change_to_government(pplayer, pgov)) {
1635 if (available != NULL) {
1637 /* TRANS: "Discovery of <tech>" */
1638 _("%s makes several new government forms"
1639 " available. You may want to start a revolution."),
1640 reason);
1641 return;
1642 }
1643
1644 available = pgov;
1645 }
1647
1648 if (available != NULL) {
1650 /* TRANS: "Discovery of <tech>" */
1651 _("%s makes the government form %s"
1652 " available. You may want to start a revolution."),
1653 reason,
1655 }
1656}
void astr_free(struct astring *astr)
Definition astring.c:148
void astr_init(struct astring *astr)
Definition astring.c:139
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define BV_SET_ALL(bv)
Definition bitvector.h:107
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
bool can_city_build_improvement_now(const struct city *pcity, const struct impr_type *pimprove, const enum req_problem_type prob_type)
Definition city.c:860
bool can_city_build_unit_now(const struct civ_map *nmap, const struct city *pcity, const struct unit_type *punittype, const enum req_problem_type prob_type)
Definition city.c:957
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:565
#define city_owner(_pcity_)
Definition city.h:564
#define city_list_iterate_end
Definition city.h:510
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2374
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3460
void choose_build_target(struct player *pplayer, struct city *pcity)
Definition cityturn.c:2567
bool city_refresh(struct city *pcity)
Definition cityturn.c:159
char * incite_cost
Definition comments.c:77
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:765
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:77
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int cost
Definition dialogs_g.h:73
struct effect_list * effects[EFT_COUNT]
Definition effects.c:127
struct effect_list * govs[G_LAST]
Definition effects.c:133
int get_player_bonus_effects(struct effect_list *plist, const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:1134
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:824
void get_effect_list_req_text(const struct effect_list *plist, struct astring *astr)
Definition effects.c:1309
int Tech_type_id
Definition fc_types.h:238
@ RPT_CERTAIN
Definition fc_types.h:516
#define MAX_LEN_NAME
Definition fc_types.h:68
#define MAX_NUM_TECH_LIST
Definition fc_types.h:44
@ O_SCIENCE
Definition fc_types.h:103
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
const struct ft_color ftc_server
const char * city_link(const struct city *pcity)
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
void send_game_info(struct conn_list *dest)
Definition gamehand.c:910
const char * government_name_translation(const struct government *pgovern)
Definition government.c:141
Government_type_id government_count(void)
Definition government.c:73
struct government * government_of_player(const struct player *pplayer)
Definition government.c:115
bool can_change_to_government(struct player *pplayer, const struct government *gov)
Definition government.c:166
Government_type_id government_number(const struct government *pgovern)
Definition government.c:92
Government_type_id government_index(const struct government *pgovern)
Definition government.c:84
#define governments_iterate(NAME_pgov)
Definition government.h:136
#define governments_iterate_end
Definition government.h:139
bool is_great_wonder(const struct impr_type *pimprove)
bool improvement_obsolete(const struct player *pplayer, const struct impr_type *pimprove, const struct city *pcity)
const char * improvement_name_translation(const struct impr_type *pimprove)
struct city * city_from_great_wonder(const struct impr_type *pimprove)
#define improvement_iterate_end
#define improvement_iterate(_p)
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define log_debug(message,...)
Definition log.h:116
int send_packet_unknown_research(struct connection *pc, const struct packet_unknown_research *packet)
int send_packet_research_info(struct connection *pc, const struct packet_research_info *packet)
void handle_player_change_government(struct player *pplayer, Government_type_id government)
Definition plrhand.c:565
#define whole_map_iterate(_map, _tile)
Definition map.h:582
#define whole_map_iterate_end
Definition map.h:591
void send_tile_info(struct conn_list *dest, struct tile *ptile, bool send_unknown)
Definition maphand.c:490
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1406
void upgrade_all_city_extras(struct player *pplayer, bool discovery)
Definition maphand.c:274
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:927
#define fc_malloc(sz)
Definition mem.h:34
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:443
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
void notify_research(const struct research *presearch, const struct player *exclude, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:393
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:291
void notify_research_embassies(const struct research *presearch, const struct player *exclude, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:433
struct player * player_by_number(const int player_id)
Definition player.c:837
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1468
int player_slot_count(void)
Definition player.c:415
const char * player_name(const struct player *pplayer)
Definition player.c:885
bool team_has_embassy(const struct team *pteam, const struct player *tgt_player)
Definition player.c:225
int player_index(const struct player *pplayer)
Definition player.c:818
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1397
#define players_iterate_end
Definition player.h:552
#define players_iterate(_pplayer)
Definition player.h:547
#define player_list_iterate(playerlist, pplayer)
Definition player.h:570
#define is_ai(plr)
Definition player.h:232
#define player_list_iterate_end
Definition player.h:572
void send_player_all_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1131
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1148
#define shuffled_players_iterate_end
Definition plrhand.h:108
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:98
#define fc_rand(_size)
Definition rand.h:56
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Definition research.c:671
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:640
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
int research_count(void)
Definition research.c:1340
int research_number(const struct research *presearch)
Definition research.c:109
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
const char * research_rule_name(const struct research *presearch)
Definition research.c:145
struct research * research_get(const struct player *pplayer)
Definition research.c:130
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:622
Tech_type_id research_goal_step(const struct research *presearch, Tech_type_id goal)
Definition research.c:723
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Definition research.c:696
void research_update(struct research *presearch)
Definition research.c:504
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
void script_server_signal_emit(const char *signal_name,...)
#define MAX(x, y)
Definition shared.h:54
Definition city.h:318
bool multiresearch
Definition game.h:170
int techlost_recv
Definition game.h:201
struct conn_list * est_connections
Definition game.h:97
int global_init_techs[MAX_NUM_TECH_LIST]
Definition game.h:110
struct packet_game_info info
Definition game.h:89
int conquercost
Definition game.h:143
int techloss_restore
Definition game.h:199
int freecost
Definition game.h:155
struct civ_game::@31 rgame
struct civ_game::@32::@36 server
int techlost_donor
Definition game.h:200
int techpenalty
Definition game.h:203
bool * govs
Definition techtools.h:25
struct cur_govs_data::@127 * players
int init_techs[MAX_NUM_TECH_LIST]
Definition nation.h:122
bool tech_steal_allow_holes
bool global_advances[A_LAST]
bool tech_trade_loss_allow_holes
enum free_tech_method free_tech_method
bool tech_parasite_allow_holes
char inventions[A_LAST+1]
int bulbs_last_turn
Definition player.h:351
struct team * team
Definition player.h:261
bool is_alive
Definition player.h:268
struct player::@73::@75 server
enum tech_state state
Definition research.h:71
Tech_type_id researching
Definition research.h:52
int future_tech
Definition research.h:42
Tech_type_id tech_goal
Definition research.h:83
int bulbs_researching_saved
Definition research.h:63
struct research::research_invention inventions[A_ARRAY_SIZE]
Tech_type_id researching_saved
Definition research.h:62
int techs_researched
Definition research.h:42
int bulbs_researched
Definition research.h:53
int free_bulbs
Definition research.h:67
Definition team.c:40
const struct unit_type * utype
Definition unit.h:140
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:925
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct team * team_by_number(const int team_id)
Definition team.c:391
const struct player_list * team_members(const struct team *pteam)
Definition team.c:443
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:110
bool is_future_tech(Tech_type_id tech)
Definition tech.c:286
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:221
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:181
Tech_type_id advance_required(const Tech_type_id tech, enum tech_req require)
Definition tech.c:124
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:314
#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
@ AR_TWO
Definition tech.h:109
@ AR_ROOT
Definition tech.h:110
@ AR_ONE
Definition tech.h:108
#define advance_index_iterate_max_end
Definition tech.h:256
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 A_UNSET
Definition tech.h:48
#define A_UNKNOWN
Definition tech.h:49
#define A_LAST
Definition tech.h:45
#define advance_index_iterate(_start, _index)
Definition tech.h:242
static Tech_type_id pick_cheapest_tech(const struct research *presearch)
Definition techtools.c:1032
void handle_player_tech_goal(struct player *pplayer, int tech_goal)
Definition techtools.c:1436
void init_tech(struct research *research, bool update)
Definition techtools.c:1168
static struct government * pick_random_government(struct player *pplayer)
Definition techtools.c:876
void found_new_tech(struct research *presearch, Tech_type_id tech_found, bool was_discovery, bool saving_bulbs)
Definition techtools.c:347
void free_current_governments_data(struct cur_govs_data *data)
Definition techtools.c:1612
static bool lose_tech(struct research *research)
Definition techtools.c:688
void choose_tech_goal(struct research *presearch, Tech_type_id tech)
Definition techtools.c:1149
void research_apply_penalty(struct research *presearch, Tech_type_id tech, int penalty_percent)
Definition techtools.c:67
static void tech_researched(struct research *research)
Definition techtools.c:107
void choose_tech(struct research *research, Tech_type_id tech)
Definition techtools.c:1079
static Tech_type_id pick_random_tech_to_lose(const struct research *presearch)
Definition techtools.c:805
static void package_research_info(struct packet_research_info *packet, const struct research *presearch)
Definition techtools.c:258
static void forget_tech_transferred(struct player *pplayer, Tech_type_id tech)
Definition techtools.c:1490
Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim, Tech_type_id preferred)
Definition techtools.c:1308
void notify_new_government_options(struct player *pplayer, struct cur_govs_data *data, const char *reason)
Definition techtools.c:1626
void handle_player_research(struct player *pplayer, int tech)
Definition techtools.c:1413
Tech_type_id pick_free_tech(struct research *presearch)
Definition techtools.c:1462
void give_immediate_free_tech(struct research *presearch, Tech_type_id tech)
Definition techtools.c:1481
struct cur_govs_data * create_current_governments_data(struct research *presearch)
Definition techtools.c:1564
void send_research_info(const struct research *presearch, const struct conn_list *dest)
Definition techtools.c:293
void choose_random_tech(struct research *research)
Definition techtools.c:1064
struct cur_govs_data * create_current_governments_data_all(void)
Definition techtools.c:1592
static void research_tech_lost(struct research *presearch, Tech_type_id tech)
Definition techtools.c:893
void script_tech_learned(struct research *presearch, struct player *originating_plr, struct advance *tech, const char *reason)
Definition techtools.c:84
void give_initial_techs(struct research *presearch, int num_random_techs)
Definition techtools.c:1262
bool tech_transfer(struct player *plr_recv, struct player *plr_donor, Tech_type_id tech)
Definition techtools.c:1512
static Tech_type_id pick_random_tech(const struct research *presearch)
Definition techtools.c:1013
void do_tech_parasite_effects(struct player *pplayer)
Definition techtools.c:143
void update_bulbs(struct player *pplayer, int bulbs, bool check_tech, bool free_bulbs)
Definition techtools.c:726
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:827
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:5046
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586