Freeciv-3.1
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
57pick_random_tech_to_lose(const struct research *presearch);
58static Tech_type_id pick_random_tech(const struct research *presearch);
59static Tech_type_id pick_cheapest_tech(const struct research *presearch);
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/************************************************************************/
67void research_apply_penalty(struct research *presearch, Tech_type_id tech,
68 int penalty_percent)
69{
71 return;
72 }
73 presearch->bulbs_researched -=
74 (research_total_bulbs_required(presearch, tech, FALSE)
75 * penalty_percent) / 100;
76 presearch->researching_saved = A_UNKNOWN;
77}
78
79/************************************************************************/
84void script_tech_learned(struct research *presearch,
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) {
91 fc_assert(research_get(originating_plr) == presearch);
92 script_server_signal_emit("tech_researched", tech, originating_plr,
93 reason);
94 }
95
96 /* Emit signal to remaining research teammates, if any */
97 research_players_iterate(presearch, member) {
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
114 research_pretty_name(research, research_name, sizeof(research_name));
115 /* Players will be notified when new tech is chosen. */
117 (research, NULL, E_TECH_EMBASSY, ftc_server,
118 _("The %s have researched %s."),
119 research_name,
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_effect(struct player *pplayer)
144{
145 struct effect_list *plist = effect_list_new();
146 struct astring effects;
147 struct research *plr_research;
148 char research_name[MAX_LEN_NAME * 2];
149 const char *advance_name;
150 Tech_type_id tech;
151 /* Note that two EFT_TECH_PARASITE effects will combine into a single,
152 * much worse effect. */
153 int mod = get_player_bonus_effects(plist, pplayer, EFT_TECH_PARASITE);
154 int num_techs;
155
156 if (mod <= 0) {
157 /* No effect. */
158 effect_list_destroy(plist);
159 return;
160 }
161
162 /* Pick a random technology. */
163 tech = A_UNSET;
164 num_techs = 0;
165 plr_research = research_get(pplayer);
167 int num_teams;
168
169 if (!research_invention_gettable(plr_research, i,
171 || TECH_KNOWN == research_invention_state(plr_research, i)) {
172 continue;
173 }
174
175 num_teams = 0;
176 researches_iterate(other_research) {
177 if (TECH_KNOWN == research_invention_state(other_research, i)) {
178 if (mod <= ++num_teams) {
179 if (0 == fc_rand(++num_techs)) {
180 tech = i;
181 }
182 break;
183 }
184 }
187
188 if (A_UNSET == tech) {
189 /* No tech found. */
190 effect_list_destroy(plist);
191 return;
192 }
193
194 /* Notify. */
195 research_pretty_name(plr_research, research_name, sizeof(research_name));
196 advance_name = research_advance_name_translation(plr_research, tech);
199
200 notify_player(pplayer, NULL, E_TECH_GAIN, ftc_server,
201 /* TRANS: Tech from source of an effect
202 * (Great Library) */
203 Q_("?fromeffect:%s acquired from %s!"),
204 advance_name,
205 astr_str(&effects));
206 notify_research(plr_research, pplayer, E_TECH_GAIN, ftc_server,
207 /* TRANS: Tech from source of an effect
208 * (Great Library) */
209 Q_("?fromeffect:%s acquired from %s's %s!"),
210 advance_name,
211 player_name(pplayer),
212 astr_str(&effects));
213 notify_research_embassies(plr_research, NULL, E_TECH_EMBASSY, ftc_server,
214 /* TRANS: Tech from source of an effect
215 * (Great Library) */
216 Q_("?fromeffect:The %s have acquired %s from %s."),
217 research_name,
218 advance_name,
219 astr_str(&effects));
220
221 effect_list_destroy(plist);
223
224 /* Really get tech. */
225 research_apply_penalty(plr_research, tech, game.server.freecost);
226 found_new_tech(plr_research, tech, FALSE, TRUE);
227
228 research_players_iterate(plr_research, member) {
229 script_server_signal_emit("tech_researched", advance_by_number(tech),
230 member, "stolen");
232}
233
234/************************************************************************/
237static inline void
239 const struct research *presearch)
240{
241 packet->id = research_number(presearch);
242 packet->techs_researched = presearch->techs_researched;
243 packet->future_tech = presearch->future_tech;
244 packet->researching = presearch->researching;
245 packet->researching_cost =
246 (packet->researching != A_UNSET
247 ? research_total_bulbs_required(presearch, presearch->researching,
248 FALSE) : 0);
249 packet->bulbs_researched = presearch->bulbs_researched;
250 packet->tech_goal = presearch->tech_goal;
251 packet->total_bulbs_prod = 0;
252 research_players_iterate(presearch, pplayer) {
253 city_list_iterate(pplayer->cities, pcity) {
254 packet->total_bulbs_prod += pcity->surplus[O_SCIENCE];
258 packet->inventions[i] = presearch->inventions[i].state + '0';
260 packet->inventions[advance_count()] = '\0';
261 packet->tech_goal = presearch->tech_goal;
262#ifdef FREECIV_DEBUG
263 log_verbose("Research nb %d inventions: %s",
264 research_number(presearch),
265 packet->inventions);
266#endif /* FREECIV_DEBUG */
267}
268
269/************************************************************************/
273void send_research_info(const struct research *presearch,
274 const struct conn_list *dest)
275{
276 struct packet_research_info full_info, restricted_info;
277 struct packet_unknown_research unknown_info;
278 const struct player *pplayer;
279
280 fc_assert_ret(NULL != presearch);
281 if (NULL == dest) {
282 dest = game.est_connections;
283 }
284
285 /* Packaging */
286 package_research_info(&full_info, presearch);
287 restricted_info = full_info;
288 restricted_info.tech_goal = A_UNSET;
289 restricted_info.total_bulbs_prod = 0;
290 unknown_info.id = research_number(presearch);
291
292 conn_list_iterate(dest, pconn) {
293 pplayer = conn_get_player(pconn);
294 if (NULL != pplayer) {
295 if (presearch == research_get(pplayer)) {
296 /* Case research owner. */
297 send_packet_research_info(pconn, &full_info);
298 } else {
299 /* 'pplayer' may have an embassy for looking to 'presearch'. */
300 bool embassy = FALSE;
301
302 research_players_iterate(presearch, powner) {
303 if (team_has_embassy(pplayer->team, powner)) {
304 embassy = TRUE;
305 break;
306 }
308
309 if (embassy) {
310 send_packet_research_info(pconn, &restricted_info);
311 } else {
312 send_packet_unknown_research(pconn, &unknown_info);
313 }
314 }
315 } else if (pconn->observer) {
316 /* Case global observer. */
317 send_packet_research_info(pconn, &full_info);
318 }
320}
321
322/************************************************************************/
327void found_new_tech(struct research *presearch, Tech_type_id tech_found,
328 bool was_discovery, bool saving_bulbs)
329{
330 int had_embassies[player_slot_count()];
331 bool could_switch[player_slot_count()][government_count()];
332 bool was_first = FALSE;
333 bool bonus_tech_hack = FALSE;
334 int i;
335 const char *advance_name;
336 struct advance *vap = valid_advance_by_number(tech_found);
337 struct city *pcity;
338
339 if (!is_future_tech(tech_found)) {
340
341#ifndef FREECIV_NDEBUG
342 fc_assert(NULL != vap);
343 fc_assert(TECH_KNOWN != research_invention_state(presearch, tech_found));
344#endif /* FREECIV_NDEBUG */
345
346 was_first = (!game.info.global_advances[tech_found]);
347 }
348
349 /* Assign 'advance_name' before we increase the future tech counter. */
350 advance_name = research_advance_name_translation(presearch, tech_found);
351
352 if (was_first && vap) {
353 /* Alert the owners of any wonders that have been made obsolete */
354 improvement_iterate(pimprove) {
355 requirement_vector_iterate(&pimprove->obsolete_by, pobs) {
356 if (pobs->source.kind == VUT_ADVANCE
357 && pobs->source.value.advance == vap
358 && pobs->range >= REQ_RANGE_WORLD
359 && pobs->present
360 && pobs->survives
361 && is_great_wonder(pimprove)
362 && (pcity = city_from_great_wonder(pimprove))) {
363 notify_player(city_owner(pcity), NULL, E_WONDER_OBSOLETE, ftc_server,
364 _("Discovery of %s OBSOLETES %s in %s!"),
366 (research_get(city_owner(pcity)), tech_found),
368 city_link(pcity));
369 }
372 }
373
374 if (was_first
375 && !is_future_tech(tech_found)
376 && advance_has_flag(tech_found, TF_BONUS_TECH)) {
377 bonus_tech_hack = TRUE;
378 }
379
380 /* Memorize some values before the tech is marked as researched.
381 * We will check what has changed later. */
382 players_iterate(aplayer) {
383 i = player_index(aplayer);
384
385 /* Count EFT_HAVE_EMBASSIES effect for each player. */
386 had_embassies[i] = get_player_bonus(aplayer, EFT_HAVE_EMBASSIES);
387
388 if (presearch != research_get(aplayer)) {
389 continue;
390 }
391
392 /* Memorize for the players sharing the research what government
393 * they could switch on. */
394 governments_iterate(pgov) {
395 could_switch[i][government_index(pgov)]
396 = can_change_to_government(aplayer, pgov);
399
400 /* got_tech allows us to change research without applying techpenalty
401 * (without losing bulbs) */
402 if (tech_found == presearch->researching) {
403 presearch->got_tech = TRUE;
404 presearch->got_tech_multi = TRUE;
405 }
406 presearch->researching_saved = A_UNKNOWN;
407 presearch->techs_researched++;
408
409 /* Mark the tech as known in the research struct and update
410 * global_advances array. */
411 if (is_future_tech(tech_found)) {
412 presearch->future_tech++;
413 } else {
414 research_invention_set(presearch, tech_found, TECH_KNOWN);
415 research_update(presearch);
416 }
417
418 /* Inform players about their new tech. */
419 send_research_info(presearch, NULL);
420
421 if (was_first) {
422 /* Inform all players about new global advances to give them a
423 * chance for obsolete buildings. */
424 send_game_info(NULL);
425 }
426
427 /* Make proper changes for all players. Use shuffled order, in case
428 * a script would detect a signal. */
429 shuffled_players_iterate(aplayer) {
430 i = player_index(aplayer);
431
432 if (presearch == research_get(aplayer)) {
433 /* Only for players sharing the research. */
435
436 /* Give free infrastructure in every city */
437 if (tech_found != A_FUTURE) {
438 upgrade_all_city_extras(aplayer, was_discovery);
439
440 /* Revealing of extras with visibility_req */
441 whole_map_iterate(&(wld.map),ptile) {
442 if (map_is_known_and_seen(ptile, aplayer, V_MAIN)) {
443 if (update_player_tile_knowledge(aplayer, ptile)) {
444 send_tile_info(aplayer->connections, ptile, FALSE);
445 }
446 }
448 }
449
450 /* Enhance vision of units if a player-ranged effect has changed. Note
451 * that world-ranged effects will not be updated immediately. */
452 unit_list_refresh_vision(aplayer->units);
453
454 /* Notify a player about new governments available */
455 governments_iterate(pgov) {
456 if (!could_switch[i][government_index(pgov)]
457 && can_change_to_government(aplayer, pgov)) {
458 notify_player(aplayer, NULL, E_NEW_GOVERNMENT, ftc_server,
459 _("Discovery of %s makes the government form %s"
460 " available. You may want to start a revolution."),
461 advance_name,
463 }
465 }
466
467 /* For any player. */
468 /* Update all cities in case the tech changed some effects. This is
469 * inefficient; it could be optimized if it's found to be a problem.
470 * But techs aren't researched that often. */
471 city_list_iterate(aplayer->cities, apcity) {
472 /* Refresh the city data; this also updates the squared city radius. */
473 city_refresh(apcity);
474 city_refresh_vision(apcity);
475 send_city_info(aplayer, apcity);
477
478 /* Send all player an updated info of the owner of the Marco Polo
479 * Wonder if this wonder has become obsolete. */
480 if (0 < had_embassies[i]
481 && 0 <= get_player_bonus(aplayer, EFT_HAVE_EMBASSIES)) {
482 send_player_all_c(aplayer, aplayer->connections);
483 players_iterate(pother_player) {
484 if (aplayer != pother_player) {
485 send_player_all_c(aplayer, pother_player->connections);
486 send_player_all_c(pother_player, aplayer->connections);
487 }
489 }
491
492 if (tech_found == presearch->tech_goal) {
493 presearch->tech_goal = A_UNSET;
494 }
495
496 if (tech_found == presearch->researching) {
497 /* Try to pick new tech to research. */
498 Tech_type_id next_tech = research_goal_step(presearch,
499 presearch->tech_goal);
500
501 /* As this function can be recursive, we need to print the messages
502 * before really picking the new technology. */
503 if (A_UNSET != next_tech) {
504 notify_research(presearch, NULL, E_TECH_LEARNED, ftc_server,
505 _("Learned %s. Our scientists focus on %s; "
506 "goal is %s."),
507 advance_name,
509 next_tech),
511 (presearch, presearch->tech_goal));
512 } else {
513 if (is_future_tech(tech_found)) {
514 /* Use pick_random_tech() to determine if there now is
515 * a regular tech to research, e.g., if one was lost
516 * due to tech upkeep since we started researching future techs. */
517 next_tech = pick_random_tech(presearch);
518
519 /* Continue researching future tech, if possible. */
520 if (next_tech != A_FUTURE) {
521 bool ai_found = FALSE;
522
523 /* Otherwise check if there's an AI player to support
524 * randomly selected tech (one that "made" the decision) */
525 research_players_iterate(presearch, aplayer) {
526 if (is_ai(aplayer)) {
527 ai_found = TRUE;
528 }
530
531 if (!ai_found) {
532 /* Decision is humans' to make */
533 next_tech = A_UNSET;
534 }
535 }
536 } else {
537 /* If there is at least one AI player still alive, then pick
538 * a random tech, else keep A_UNSET. */
539 research_players_iterate(presearch, aplayer) {
540 if (is_ai(aplayer)) {
541 next_tech = pick_random_tech(presearch);
542 break;
543 }
545 }
546
547 if (A_UNSET == next_tech) {
548 notify_research(presearch, NULL, E_TECH_LEARNED, ftc_server,
549 _("Learned %s. Scientists "
550 "do not know what to research next."),
551 advance_name);
552 } else {
553 notify_research(presearch, NULL, E_TECH_LEARNED, ftc_server,
554 _("Learned %s. Scientists choose to research %s."),
555 advance_name,
557 next_tech));
558 }
559 }
560
561 if (A_UNSET != next_tech) {
562 choose_tech(presearch, next_tech);
563 } else {
564 presearch->researching = A_UNSET;
565 }
566 }
567
568 if (!saving_bulbs && presearch->bulbs_researched > 0) {
569 presearch->bulbs_researched = 0;
570 }
571
572 if (bonus_tech_hack) {
573 Tech_type_id additional_tech;
574 char research_name[MAX_LEN_NAME * 2];
575 const char *radv_name;
576
577 research_pretty_name(presearch, research_name, sizeof(research_name));
578
579 additional_tech = pick_free_tech(presearch);
580
581 radv_name = research_advance_name_translation(presearch, additional_tech);
582
583 give_immediate_free_tech(presearch, additional_tech);
584 if (advance_by_number(tech_found)->bonus_message != NULL
585 && additional_tech != A_UNSET) {
586 notify_research(presearch, NULL, E_TECH_GAIN, ftc_server,
587 _(advance_by_number(tech_found)->bonus_message),
588 radv_name);
589 } else if (additional_tech != A_UNSET) {
590 /* FIXME: "your" when it was just civilization of one of the players
591 * sharing the research. */
592 notify_research(presearch, NULL, E_TECH_GAIN, ftc_server,
593 _("Great scientists from all the "
594 "world join your civilization: you learn "
595 "%s immediately."), radv_name);
596 }
597 /* TODO: Ruleset should be able to customize this message too */
598 notify_research_embassies(presearch, NULL, E_TECH_EMBASSY, ftc_server,
599 _("%s acquire %s as a result of learning %s."),
600 research_name, radv_name, advance_name);
601 }
602}
603
604/************************************************************************/
607static bool lose_tech(struct research *research)
608{
610 /* Tech loss disabled */
611 return FALSE;
612 }
613
614 if (research->techs_researched == 0) {
615 /* No tech to lose */
617 return FALSE;
618 }
619
620 /* First check is not for optimization only - it protects
621 * research_total_bulbs_required() from getting called before research
622 * has even been set to value other than A_UNSET. */
626 * game.info.techloss_forgiveness / 100)) {
627 return TRUE;
628 }
629
630 return FALSE;
631}
632
633/************************************************************************/
643void update_bulbs(struct player *pplayer, int bulbs, bool check_tech)
644{
645 struct research *research = research_get(pplayer);
646
647 if (!pplayer->is_alive) {
648 /* Dead players do not produce research */
649 return;
650 }
651
652 /* Count our research contribution this turn */
653 pplayer->server.bulbs_last_turn += bulbs;
654 research->bulbs_researched += bulbs;
656 if (j == research->researching) {
658 }
662 }
663
664
665 do {
666 /* If we have a negative number of bulbs we do try to:
667 * - reduce the number of future techs;
668 * - or lose one random tech.
669 * After that the number of bulbs available is incresed based on the
670 * value of the lost tech. */
671 if (lose_tech(research)) {
674
675 if (tech != A_NONE) {
676 if (game.server.techloss_restore >= 0) {
680 } else {
682 }
684
685 log_debug("%s: tech loss (%s)",
687 (is_future_tech(tech) ? "Future Tech"
690 /* Make notification after losing the research, in case it is
691 * a future tech (for getting the right tech number). */
692 notify_research(research, NULL, E_TECH_LOST, ftc_server,
693 _("Insufficient science output. We lost %s."),
695 }
696 }
697
698 /* Check for finished research. */
699 if (!check_tech
703 FALSE))) {
704 break;
705 }
706
708 } while (research->researching != A_UNSET);
709}
710
711/************************************************************************/
714static Tech_type_id
715pick_random_tech_to_lose(const struct research *presearch)
716{
717 bv_techs eligible_techs;
718 /* A_NONE included in advance_count(). */
719 int eligible = advance_count() - 1;
720 int chosen;
721
722 BV_SET_ALL(eligible_techs);
723
725 if (research_invention_state(presearch, i) != TECH_KNOWN) {
726 if (BV_ISSET(eligible_techs, i)) {
727 eligible--;
728 BV_CLR(eligible_techs, i);
729 }
730 } else {
731 /* Knowing this tech may make others ineligible */
733 /* Never lose techs that are root_req for a currently known tech
734 * (including self root_req) */
735 if (root != A_NONE && BV_ISSET(eligible_techs, root)) {
736 eligible--;
737 BV_CLR(eligible_techs, root);
738 }
740 /* Ruleset can prevent this kind of tech loss from opening up
741 * holes in the tech tree */
742 Tech_type_id prereq;
743 prereq = advance_required(i, AR_ONE);
744 if (prereq != A_NONE && BV_ISSET(eligible_techs, prereq)) {
745 eligible--;
746 BV_CLR(eligible_techs, prereq);
747 }
748 prereq = advance_required(i, AR_TWO);
749 if (prereq != A_NONE && BV_ISSET(eligible_techs, prereq)) {
750 eligible--;
751 BV_CLR(eligible_techs, prereq);
752 }
753 }
754 }
756
757 if (eligible == 0) {
758 /* no researched technology at all */
759 return A_NONE;
760 }
761
762 chosen = fc_rand(eligible) + 1;
763
765 if (BV_ISSET(eligible_techs, i)) {
766 chosen--;
767 if (chosen == 0) {
768 return i;
769 }
770 }
772
773 /* should never be reached */
774 fc_assert_msg(chosen == 0, "internal error (eligible=%d, chosen=%d)",
775 eligible, chosen);
776 return A_NONE;
777}
778
779/************************************************************************/
782static inline struct government *
784{
785 struct government *picked = NULL;
786 int gov_nb = 0;
787
788 governments_iterate(pgov) {
789 if (can_change_to_government(pplayer, pgov) && 0 == fc_rand(++gov_nb)) {
790 picked = pgov;
791 }
793 fc_assert(NULL != picked);
794 return picked;
795}
796
797/************************************************************************/
800static void research_tech_lost(struct research *presearch, Tech_type_id tech)
801{
802 char research_name[MAX_LEN_NAME * 2];
803 /* Research members will be notified when new tech is chosen. */
804 const struct civ_map *nmap = &(wld.map);
805
806 research_pretty_name(presearch, research_name, sizeof(research_name));
807
808 presearch->techs_researched--;
809 if (is_future_tech(tech)) {
810 presearch->future_tech--;
811 research_update(presearch);
812 /* Notify after decreasing the future tech counter, to get the right
813 * tech number in the message. */
814 notify_research_embassies(presearch, NULL, E_TECH_EMBASSY, ftc_server,
815 _("The %s have lost %s."),
816 research_name,
818 tech));
819 /* Inform players about their technology loss. */
820 send_research_info(presearch, NULL);
821 return;
822 }
823
825 notify_research_embassies(presearch, NULL, E_TECH_EMBASSY, ftc_server,
826 /* TRANS: technology loss */
827 _("The %s have lost %s."),
828 research_name,
830 tech));
831
832 /* Remove technology. */
833 research_invention_set(presearch, tech, TECH_UNKNOWN);
834 research_update(presearch);
835 log_debug("%s lost tech id %d (%s)", research_rule_name(presearch), tech,
837
838 /* Inform players about their technology loss. */
839 send_research_info(presearch, NULL);
840
841 research_players_iterate(presearch, pplayer) {
842 /* Check government. */
843 if (!can_change_to_government(pplayer, government_of_player(pplayer))) {
844 /* Lost the technology for the government; switch to random
845 * available government. */
846 struct government *pgov = pick_random_government(pplayer);
847
848 notify_player(pplayer, NULL, E_NEW_GOVERNMENT, ftc_server,
849 _("The required technology for our government '%s' "
850 "was lost. The citizens have started a "
851 "revolution into '%s'."),
853 (pplayer)),
856 send_player_info_c(pplayer, NULL);
857 } else if (NULL != pplayer->target_government
858 && !can_change_to_government(pplayer,
859 pplayer->target_government)) {
860 /* Lost the technology for the target government; use a random
861 * available government as new target government. */
862 struct government *pgov = pick_random_government(pplayer);
863
864 notify_player(pplayer, NULL, E_NEW_GOVERNMENT, ftc_server,
865 _("The required technology for our new government "
866 "'%s' was lost. The citizens chose '%s' as new "
867 "target government."),
868 government_name_translation(pplayer->target_government),
870 pplayer->target_government = pgov;
871 send_player_info_c(pplayer, pplayer->connections);
872 }
873
874 /* Check all units for valid activities. */
876
877 /* Check city production */
878 city_list_iterate(pplayer->cities, pcity) {
879 bool update = FALSE;
880
881 if (pcity->production.kind == VUT_UTYPE
882 && !can_city_build_unit_now(nmap, pcity, pcity->production.value.utype)) {
883 notify_player(pplayer, city_tile(pcity),
884 E_CITY_CANTBUILD, ftc_server,
885 _("%s can't build %s. The required technology was "
886 "lost."),
887 city_link(pcity),
888 utype_name_translation(pcity->production.value.utype));
889 choose_build_target(pplayer, pcity);
890 update = TRUE;
891 }
892
893 if (pcity->production.kind == VUT_IMPROVEMENT
895 pcity->production.value.building)) {
896 notify_player(pplayer, city_tile(pcity),
897 E_CITY_CANTBUILD, ftc_server,
898 _("%s can't build %s. The required technology was "
899 "lost."),
900 city_link(pcity),
902 (pcity->production.value.building));
903 choose_build_target(pplayer, pcity);
904 update = TRUE;
905 }
906
907 if (update) {
908 city_refresh(pcity);
909 send_city_info(pplayer, pcity);
910 }
913}
914
915/************************************************************************/
918static Tech_type_id pick_random_tech(const struct research *presearch)
919{
920 Tech_type_id tech = A_FUTURE;
921 int num_techs = 0;
922
924 if (research_invention_state(presearch, i) == TECH_PREREQS_KNOWN) {
925 if (fc_rand(++num_techs) == 0) {
926 tech = i;
927 }
928 }
930 return tech;
931}
932
933/************************************************************************/
936static Tech_type_id pick_cheapest_tech(const struct research *presearch)
937{
938 int cheapest_cost = -1;
939 int cheapest_amount = 0;
940 Tech_type_id cheapest = A_FUTURE; /* If no real tech is found to be missing */
941
943 if (research_invention_state(presearch, i) == TECH_PREREQS_KNOWN) {
944 int cost = research_total_bulbs_required(presearch, i, FALSE);
945
946 if (cost < cheapest_cost || cheapest_cost == -1) {
947 cheapest_cost = cost;
948 cheapest_amount = 1;
949 cheapest = i;
950 } else if (cost == cheapest_cost && fc_rand(++cheapest_amount) == 0) {
951 cheapest = i;
952 }
953 }
955
956 return cheapest;
957}
958
959/************************************************************************/
974
975/************************************************************************/
984{
985 int bulbs_res = 0;
986
987 if (is_future_tech(tech)) {
992 }
993 } else {
994 if (research->researching == tech) {
995 return;
996 }
997 if (research_invention_state(research, tech) != TECH_PREREQS_KNOWN) {
998 /* Can't research this. */
999 return;
1000 }
1001 }
1002
1005 /* Save old tech research */
1006 if (j == research->researching) {
1008 }
1009 /* New tech*/
1010 if (j == tech) {
1012 }
1014 research->researching = tech;
1015 if (!research->got_tech_multi) {
1017 }
1023 }
1024 return;
1025 }
1026
1030 /* Subtract a penalty because we changed subject. */
1031 if (research->bulbs_researched > 0) {
1035 }
1036 } else if (tech == research->researching_saved) {
1039 }
1040 research->researching = tech;
1044 }
1045}
1046
1047/************************************************************************/
1051void choose_tech_goal(struct research *presearch, Tech_type_id tech)
1052{
1053 fc_assert_ret(presearch != NULL);
1054
1055 if (tech == presearch->tech_goal) {
1056 return;
1057 }
1058
1059 /* It's been suggested that if the research target is empty then
1060 * choose_random_tech() should be called here. */
1061 presearch->tech_goal = tech;
1062 notify_research(presearch, NULL, E_TECH_GOAL, ftc_server,
1063 _("Technology goal is %s."),
1064 research_advance_name_translation(presearch, tech));
1065}
1066
1067/************************************************************************/
1070void init_tech(struct research *research, bool update)
1071{
1073
1075 research_invention_set(research, i, TECH_UNKNOWN);
1077
1078#ifdef TECH_UPKEEP_DEBUGGING
1079 /* Print a list of the needed upkeep if 'i' techs are researched.
1080 * If the ruleset contains self-rooted techs this can not work! */
1081 {
1082 bool global_state[A_LAST];
1083 Tech_type_id tech = A_LAST;
1084
1085 /* Save the game research state. */
1087 global_state[i] = game.info.global_advances[i];
1089
1091 research_update(presearch);
1092
1093 /* Show research costs. */
1095 log_debug("[research %d] %-25s (ID: %3d) cost: %6d - reachable: %-3s "
1096 "(now) / %-3s (ever)", research_number(research),
1100 ? "yes" : "no",
1101 research_invention_reachable(research, i) ? "yes" : "no");
1103
1104 /* Update step for step each tech as known and print the upkeep. */
1105 while (tech != A_NONE) {
1106 tech = A_NONE;
1108 if (valid_advance_by_number(i) != NULL
1109 && research_invention_state(research, i) == TECH_PREREQS_KNOWN) {
1110 /* Found a tech which can be researched. */
1111 tech = i;
1112 break;
1113 }
1115
1116 if (tech != A_NONE) {
1117 research->inventions[tech].state = TECH_KNOWN;
1119
1120 /* This will change the game state! */
1122
1124 log_debug("[player %d] researched: %-25s (ID: %4d) techs: %3d "
1125 "upkeep: %4d", research_number(research),
1129 }
1130 }
1131
1132 /* Reset the changes done. */
1134 research_invention_set(research, i, TECH_UNKNOWN);
1135 game.info.global_advances[i] = global_state[i];
1137 }
1138#endif /* TECH_UPKEEP_DEBUGGING */
1139
1141
1142 if (update) {
1143 Tech_type_id next_tech;
1144
1145 /* Mark the reachable techs */
1147
1149 if (A_UNSET != next_tech) {
1150 choose_tech(research, next_tech);
1151 } else {
1153 }
1154 }
1155}
1156
1157/************************************************************************/
1162void give_initial_techs(struct research *presearch, int num_random_techs)
1163{
1164 int i;
1165
1166 /* Global techs. */
1167 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
1168 if (game.rgame.global_init_techs[i] == A_LAST) {
1169 break;
1170 }
1171 /* Maybe the player already got this tech by an other way (e.g. team). */
1173 != TECH_KNOWN) {
1175 FALSE, TRUE);
1176 }
1177 }
1178
1179 /* Nation techs. */
1180 research_players_iterate(presearch, pplayer) {
1181 const struct nation_type *pnation = nation_of_player(pplayer);
1182
1183 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
1184 if (pnation->init_techs[i] == A_LAST) {
1185 break;
1186 }
1187 /* Maybe the player already got this tech by an other way. */
1188 if (research_invention_state(presearch, pnation->init_techs[i])
1189 != TECH_KNOWN) {
1190 found_new_tech(presearch, pnation->init_techs[i], FALSE, TRUE);
1191 }
1192 }
1194
1195 /* Random free techs (N.B.: freecost penalty not applied). */
1196 for (i = 0; i < num_random_techs; i++) {
1197 found_new_tech(presearch, pick_random_tech(presearch), FALSE, TRUE);
1198 }
1199}
1200
1201/************************************************************************/
1208Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim,
1209 Tech_type_id preferred)
1210{
1211 struct research *presearch, *vresearch;
1212 Tech_type_id stolen_tech = A_NONE;
1213 const char *advance_name;
1214 char research_name[MAX_LEN_NAME * 2];
1215
1216 if (get_player_bonus(victim, EFT_NOT_TECH_SOURCE) > 0) {
1217 return A_NONE;
1218 }
1219
1220 presearch = research_get(pplayer);
1221 vresearch = research_get(victim);
1222
1223 if (preferred == A_UNSET) {
1224 int j = 0;
1225
1227 if (research_invention_gettable(presearch, i,
1229 && research_invention_state(presearch, i) != TECH_KNOWN
1230 && research_invention_state(vresearch, i) == TECH_KNOWN) {
1231 j++;
1232 }
1234
1235 if (j == 0) {
1236 /* We've moved on to future tech */
1237 if (vresearch->future_tech > presearch->future_tech) {
1238 stolen_tech = A_FUTURE;
1239 } else {
1240 return A_NONE;
1241 }
1242 } else {
1243 /* Pick random tech */
1244 j = fc_rand(j) + 1;
1245 stolen_tech = A_NONE; /* Avoid compiler warning */
1247 if (research_invention_gettable(presearch, i,
1249 && research_invention_state(presearch, i) != TECH_KNOWN
1250 && research_invention_state(vresearch, i) == TECH_KNOWN) {
1251 j--;
1252 }
1253 if (j == 0) {
1254 stolen_tech = i;
1255 break;
1256 }
1258 fc_assert(stolen_tech != A_NONE);
1259 }
1260 } else { /* preferred != A_UNSET */
1261#ifndef FREECIV_NDEBUG
1262 if (!is_future_tech(preferred)) {
1263 fc_assert(NULL != valid_advance_by_number(preferred));
1264 fc_assert(TECH_KNOWN == research_invention_state(vresearch,
1265 preferred));
1266 }
1267#endif /* FREECIV_NDEBUG */
1268 stolen_tech = preferred;
1269 }
1270
1271 advance_name = research_advance_name_translation(presearch, stolen_tech);
1272 research_pretty_name(presearch, research_name, sizeof(research_name));
1273 notify_player(pplayer, NULL, E_MY_DIPLOMAT_THEFT, ftc_server,
1274 _("You steal %s from the %s."),
1275 advance_name,
1276 nation_plural_for_player(victim));
1277 notify_research(presearch, pplayer, E_TECH_GAIN, ftc_server,
1278 _("The %s stole %s from the %s and shared it with you."),
1279 nation_plural_for_player(pplayer),
1280 advance_name,
1281 nation_plural_for_player(victim));
1282
1283 notify_player(victim, NULL, E_ENEMY_DIPLOMAT_THEFT, ftc_server,
1284 _("The %s stole %s from you!"),
1285 nation_plural_for_player(pplayer),
1286 advance_name);
1287
1288 notify_research_embassies(presearch, victim, E_TECH_EMBASSY, ftc_server,
1289 _("The %s have stolen %s from the %s."),
1290 research_name,
1291 advance_name,
1292 nation_plural_for_player(victim));
1293
1294 if (tech_transfer(pplayer, victim, stolen_tech)) {
1295 research_apply_penalty(presearch, stolen_tech, game.server.conquercost);
1296 found_new_tech(presearch, stolen_tech, FALSE, TRUE);
1297 script_tech_learned(presearch, pplayer, advance_by_number(stolen_tech),
1298 "stolen");
1299 return stolen_tech;
1300 }
1301
1302 return A_NONE;
1303}
1304
1305/************************************************************************/
1312void handle_player_research(struct player *pplayer, int tech)
1313{
1314 struct research *research = research_get(pplayer);
1315
1316 if (tech != A_FUTURE && !valid_advance_by_number(tech)) {
1317 return;
1318 }
1319
1320 if (tech != A_FUTURE
1321 && research_invention_state(research, tech) != TECH_PREREQS_KNOWN) {
1322 return;
1323 }
1324
1325 choose_tech(research, tech);
1326
1327 /* Notify players sharing the same research. */
1329}
1330
1331/************************************************************************/
1335void handle_player_tech_goal(struct player *pplayer, int tech_goal)
1336{
1337 struct research *research = research_get(pplayer);
1338
1339 /* Set the tech goal to a defined state if it is
1340 * - not a future tech and not a valid goal
1341 * - not a future tech and not a valid advance
1342 * - not defined
1343 * - known (i.e. due to EFT_GIVE_IMM_TECH). */
1344 if ((tech_goal != A_FUTURE
1347 || (tech_goal == A_NONE)
1348 || (TECH_KNOWN == research_invention_state(research, tech_goal))) {
1350 }
1351
1353
1354 /* Notify players sharing the same research. */
1356}
1357
1358/************************************************************************/
1362{
1363 Tech_type_id tech;
1364
1365 if (game.info.free_tech_method == FTM_CHEAPEST) {
1366 tech = pick_cheapest_tech(presearch);
1367 } else if (presearch->researching == A_UNSET
1368 || game.info.free_tech_method == FTM_RANDOM) {
1369 tech = pick_random_tech(presearch);
1370 } else {
1371 tech = presearch->researching;
1372 }
1373 return tech;
1374}
1375
1376/************************************************************************/
1381{
1382 research_apply_penalty(presearch, tech, game.server.freecost);
1383 found_new_tech(presearch, tech, FALSE, TRUE);
1384}
1385
1386/************************************************************************/
1389static void forget_tech_transferred(struct player *pplayer, Tech_type_id tech)
1390{
1391 struct research *presearch = research_get(pplayer);
1392
1393 research_tech_lost(presearch, tech);
1394 /* Make notification after losing the research, in case it is a future
1395 * tech (for getting the right tech number). */
1396 notify_player(pplayer, NULL, E_TECH_LOST, ftc_server,
1397 _("Too bad! You made a mistake transferring the tech %s and "
1398 "lost it."),
1399 research_advance_name_translation(presearch, tech));
1400 notify_research(presearch, pplayer, E_TECH_LOST, ftc_server,
1401 _("Too bad! The %s made a mistake transferring the tech "
1402 "%s and lost it."),
1403 nation_plural_for_player(pplayer),
1404 research_advance_name_translation(presearch, tech));
1405}
1406
1407/************************************************************************/
1411bool tech_transfer(struct player *plr_recv, struct player *plr_donor,
1412 Tech_type_id tech)
1413{
1414 if (game.server.techlost_donor > 0) {
1415 struct research *donor_research = research_get(plr_donor);
1416 bool donor_can_lose = TRUE;
1417
1419 /* Never let donor lose tech if it's root_req for some other known
1420 * tech */
1421 if (research_invention_state(donor_research, i) == TECH_KNOWN
1422 && (advance_required(i, AR_ROOT) == tech
1424 && (advance_required(i, AR_ONE) == tech
1425 || advance_required(i, AR_TWO) == tech)))) {
1426 donor_can_lose = FALSE;
1427 break;
1428 }
1430 if (donor_can_lose && fc_rand(100) < game.server.techlost_donor) {
1431 forget_tech_transferred(plr_donor, tech);
1432 }
1433 }
1434
1435 if (fc_rand(100) < game.server.techlost_recv) {
1436 struct research *presearch = research_get(plr_recv);
1437
1438 /* We've not received the tech yet, and never will.
1439 * Do not call forget_tech_transferred() that would handle it
1440 * as something we had and now lose.
1441 * (e.g. subtracting techs_researched counter) */
1442 notify_player(plr_recv, NULL, E_TECH_LOST, ftc_server,
1443 _("Too bad! You made a mistake transferring the tech %s and "
1444 "didn't get it."),
1445 research_advance_name_translation(presearch, tech));
1446 notify_research(presearch, plr_recv, E_TECH_LOST, ftc_server,
1447 _("Too bad! The %s made a mistake transferring the tech "
1448 "%s and didn't get it."),
1449 nation_plural_for_player(plr_recv),
1450 research_advance_name_translation(presearch, tech));
1451 return FALSE;
1452 }
1453
1454 return TRUE;
1455}
void astr_free(struct astring *astr)
Definition astring.c:153
void astr_init(struct astring *astr)
Definition astring.c:144
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:99
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define BV_CLR(bv, bit)
Definition bitvector.h:86
bool can_city_build_improvement_now(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:839
bool can_city_build_unit_now(const struct civ_map *nmap, const struct city *pcity, const struct unit_type *punittype)
Definition city.c:927
#define city_list_iterate(citylist, pcity)
Definition city.h:488
#define city_tile(_pcity_)
Definition city.h:544
#define city_owner(_pcity_)
Definition city.h:543
#define city_list_iterate_end
Definition city.h:490
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2327
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3338
void remove_obsolete_buildings(struct player *pplayer)
Definition cityturn.c:273
void choose_build_target(struct player *pplayer, struct city *pcity)
Definition cityturn.c:2232
bool city_refresh(struct city *pcity)
Definition cityturn.c:161
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:760
#define conn_list_iterate(connlist, pconn)
Definition connection.h:113
#define conn_list_iterate_end
Definition connection.h:115
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:120
int get_player_bonus_effects(struct effect_list *plist, const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:1052
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:771
void get_effect_list_req_text(const struct effect_list *plist, struct astring *astr)
Definition effects.c:1225
int Tech_type_id
Definition fc_types.h:347
#define MAX_LEN_NAME
Definition fc_types.h:66
#define MAX_NUM_TECH_LIST
Definition fc_types.h:44
@ O_SCIENCE
Definition fc_types.h:91
#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:57
struct world wld
Definition game.c:58
void send_game_info(struct conn_list *dest)
Definition gamehand.c:905
const char * government_name_translation(const struct government *pgovern)
Definition government.c:142
Government_type_id government_count(void)
Definition government.c:70
struct government * government_of_player(const struct player *pplayer)
Definition government.c:113
bool can_change_to_government(struct player *pplayer, const struct government *gov)
Definition government.c:165
Government_type_id government_number(const struct government *pgovern)
Definition government.c:90
Government_type_id government_index(const struct government *pgovern)
Definition government.c:81
#define governments_iterate(NAME_pgov)
Definition government.h:121
#define governments_iterate_end
Definition government.h:124
void handle_player_change_government(struct player *pplayer, Government_type_id government)
Definition plrhand.c:454
bool is_great_wonder(const struct impr_type *pimprove)
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:181
#define fc_assert_ret(condition)
Definition log.h:191
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define log_debug(message,...)
Definition log.h:115
#define whole_map_iterate(_map, _tile)
Definition map.h:539
#define whole_map_iterate_end
Definition map.h:548
void send_tile_info(struct conn_list *dest, struct tile *ptile, bool send_unknown)
Definition maphand.c:488
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1386
void upgrade_all_city_extras(struct player *pplayer, bool discovery)
Definition maphand.c:273
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:900
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:177
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
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)
int player_slot_count(void)
Definition player.c:411
const char * player_name(const struct player *pplayer)
Definition player.c:886
bool team_has_embassy(const struct team *pteam, const struct player *tgt_player)
Definition player.c:214
int player_index(const struct player *pplayer)
Definition player.c:820
#define players_iterate_end
Definition player.h:535
#define players_iterate(_pplayer)
Definition player.h:530
#define is_ai(plr)
Definition player.h:234
void send_player_all_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:983
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1000
#define shuffled_players_iterate_end
Definition plrhand.h:106
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:96
#define fc_rand(_size)
Definition rand.h:34
#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:665
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:634
const char * research_advance_rule_name(const struct research *presearch, Tech_type_id tech)
Definition research.c:238
int player_tech_upkeep(const struct player *pplayer)
Definition research.c:1040
int research_number(const struct research *presearch)
Definition research.c:107
const char * research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Definition research.c:271
int research_total_bulbs_required(const struct research *presearch, Tech_type_id tech, bool loss_value)
Definition research.c:858
const char * research_rule_name(const struct research *presearch)
Definition research.c:141
struct research * research_get(const struct player *pplayer)
Definition research.c:126
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:616
Tech_type_id research_goal_step(const struct research *presearch, Tech_type_id goal)
Definition research.c:717
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Definition research.c:690
void research_update(struct research *presearch)
Definition research.c:499
int research_pretty_name(const struct research *presearch, char *buf, size_t buf_len)
Definition research.c:167
#define research_players_iterate(_presearch, _pplayer)
Definition research.h:168
#define researches_iterate(_presearch)
Definition research.h:157
#define research_players_iterate_end
Definition research.h:172
#define researches_iterate_end
Definition research.h:160
void script_server_signal_emit(const char *signal_name,...)
Definition city.h:309
struct civ_game::@29 rgame
bool multiresearch
Definition game.h:162
struct civ_game::@30::@34 server
int techlost_recv
Definition game.h:193
struct conn_list * est_connections
Definition game.h:97
int global_init_techs[MAX_NUM_TECH_LIST]
Definition game.h:107
struct packet_game_info info
Definition game.h:89
int conquercost
Definition game.h:135
int techloss_restore
Definition game.h:191
int freecost
Definition game.h:147
int techlost_donor
Definition game.h:192
int techpenalty
Definition game.h:195
int init_techs[MAX_NUM_TECH_LIST]
Definition nation.h:121
bool tech_steal_allow_holes
bool tech_trade_loss_allow_holes
enum free_tech_method free_tech_method
bool global_advances[A_LAST]
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::@69::@71 server
enum tech_state state
Definition research.h:73
Tech_type_id researching
Definition research.h:52
int future_tech
Definition research.h:42
Tech_type_id tech_goal
Definition research.h:85
int bulbs_researching_saved
Definition research.h:63
struct research::research_invention inventions[A_ARRAY_SIZE]
bool got_tech_multi
Definition research.h:69
Tech_type_id researching_saved
Definition research.h:62
bool got_tech
Definition research.h:67
int techs_researched
Definition research.h:42
int bulbs_researched
Definition research.h:53
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
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
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:216
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:299
#define A_FUTURE
Definition tech.h:46
#define advance_index_iterate_end
Definition tech.h:248
@ AR_TWO
Definition tech.h:112
@ AR_ROOT
Definition tech.h:113
@ AR_ONE
Definition tech.h:111
static Tech_type_id advance_count(void)
Definition tech.h:170
#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:244
static Tech_type_id pick_cheapest_tech(const struct research *presearch)
Definition techtools.c:936
void handle_player_tech_goal(struct player *pplayer, int tech_goal)
Definition techtools.c:1335
void init_tech(struct research *research, bool update)
Definition techtools.c:1070
static struct government * pick_random_government(struct player *pplayer)
Definition techtools.c:783
void found_new_tech(struct research *presearch, Tech_type_id tech_found, bool was_discovery, bool saving_bulbs)
Definition techtools.c:327
static bool lose_tech(struct research *research)
Definition techtools.c:607
void choose_tech_goal(struct research *presearch, Tech_type_id tech)
Definition techtools.c:1051
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:983
static Tech_type_id pick_random_tech_to_lose(const struct research *presearch)
Definition techtools.c:715
void do_tech_parasite_effect(struct player *pplayer)
Definition techtools.c:143
static void package_research_info(struct packet_research_info *packet, const struct research *presearch)
Definition techtools.c:238
static void forget_tech_transferred(struct player *pplayer, Tech_type_id tech)
Definition techtools.c:1389
Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim, Tech_type_id preferred)
Definition techtools.c:1208
void handle_player_research(struct player *pplayer, int tech)
Definition techtools.c:1312
Tech_type_id pick_free_tech(struct research *presearch)
Definition techtools.c:1361
void give_immediate_free_tech(struct research *presearch, Tech_type_id tech)
Definition techtools.c:1380
void send_research_info(const struct research *presearch, const struct conn_list *dest)
Definition techtools.c:273
void choose_random_tech(struct research *research)
Definition techtools.c:968
void update_bulbs(struct player *pplayer, int bulbs, bool check_tech)
Definition techtools.c:643
static void research_tech_lost(struct research *presearch, Tech_type_id tech)
Definition techtools.c:800
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:1162
bool tech_transfer(struct player *plr_recv, struct player *plr_donor, Tech_type_id tech)
Definition techtools.c:1411
static Tech_type_id pick_random_tech(const struct research *presearch)
Definition techtools.c:918
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:806
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:4869
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1612