Freeciv-3.1: /fast/freeciv/nightly/S3_1/server/techtools.c Source File

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
57 pick_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/************************************************************************/
67 void research_apply_penalty(struct research *presearch, Tech_type_id tech,
68 int penalty_percent)
69{
70 if (game.server.multiresearch) {
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/************************************************************************/
84 void 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 }
101 } research_players_iterate_end;
102}
103
104/************************************************************************/
107 static void tech_researched(struct research *research)
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. */
112 Tech_type_id tech = research->researching;
113
114 research_pretty_name(research, research_name, sizeof(research_name));
115 /* Players will be notified when new tech is chosen. */
116 notify_research_embassies
117 (research, NULL, E_TECH_EMBASSY, ftc_server,
118 _("The %s have researched %s."),
119 research_name,
120 research_advance_name_translation(research, tech));
121
122 /* Deduct tech cost. */
123 research->bulbs_researched -= research_total_bulbs_required(research, tech,
124 FALSE);
125 advance_index_iterate(A_FIRST, j) {
126 if (j == research->researching) {
127 research->inventions[j].bulbs_researched_saved
128 = research_total_bulbs_required(research, tech, FALSE);
129 }
130 } advance_index_iterate_end;
131
132
133 /* Do all the updates needed after finding new tech. */
134 found_new_tech(research, tech, TRUE, TRUE);
135
136 script_tech_learned(research, NULL, advance_by_number(tech), "researched");
137}
138
139/************************************************************************/
143 void 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);
166 advance_index_iterate(A_FIRST, i) {
167 int num_teams;
168
169 if (!research_invention_gettable(plr_research, i,
170 game.info.tech_parasite_allow_holes)
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 }
185 } researches_iterate_end;
186 } advance_index_iterate_end;
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);
197 astr_init(&effects);
198 get_effect_list_req_text(plist, &effects);
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);
222 astr_free(&effects);
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");
231 } research_players_iterate_end;
232}
233
234/************************************************************************/
237static inline void
238package_research_info(struct packet_research_info *packet,
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];
255 } city_list_iterate_end;
256 } research_players_iterate_end;
257 advance_index_iterate(A_NONE, i) {
258 packet->inventions[i] = presearch->inventions[i].state + '0';
259 } advance_index_iterate_end;
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/************************************************************************/
273 void 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 }
307 } research_players_iterate_end;
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 }
319 } conn_list_iterate_end;
320}
321
322/************************************************************************/
327 void 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!"),
365 research_advance_name_translation
366 (research_get(city_owner(pcity)), tech_found),
367 improvement_name_translation(pimprove),
368 city_link(pcity));
369 }
370 } requirement_vector_iterate_end;
371 } improvement_iterate_end;
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);
397 } governments_iterate_end;
398 } players_iterate_end;
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. */
434 remove_obsolete_buildings(aplayer);
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 }
447 } whole_map_iterate_end;
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,
462 government_name_translation(pgov));
463 }
464 } governments_iterate_end;
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);
476 } city_list_iterate_end;
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 }
488 } players_iterate_end;
489 }
490 } shuffled_players_iterate_end;
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,
508 research_advance_name_translation(presearch,
509 next_tech),
510 research_advance_name_translation
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 }
529 } research_players_iterate_end;
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 }
544 } research_players_iterate_end;
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,
556 research_advance_name_translation(presearch,
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/************************************************************************/
607 static bool lose_tech(struct research *research)
608{
609 if (game.info.techloss_forgiveness < 0) {
610 /* Tech loss disabled */
611 return FALSE;
612 }
613
614 if (research->techs_researched == 0) {
615 /* No tech to lose */
616 fc_assert(research->future_tech == 0);
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. */
623 if (research->bulbs_researched < 0
624 && research->bulbs_researched <
625 (-research_total_bulbs_required(research, research->researching, FALSE)
626 * game.info.techloss_forgiveness / 100)) {
627 return TRUE;
628 }
629
630 return FALSE;
631}
632
633/************************************************************************/
643 void 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;
655 advance_index_iterate(A_FIRST, j) {
656 if (j == research->researching) {
657 research->inventions[j].bulbs_researched_saved = research->bulbs_researched;
658 }
659 } advance_index_iterate_end;
660 if (A_UNKNOWN != research->researching_saved) {
661 research->bulbs_researching_saved += bulbs;
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)) {
672 Tech_type_id tech = (research->future_tech > 0
673 ? A_FUTURE : pick_random_tech_to_lose(research));
674
675 if (tech != A_NONE) {
676 if (game.server.techloss_restore >= 0) {
677 research->bulbs_researched +=
678 (research_total_bulbs_required(research, tech, TRUE)
679 * game.server.techloss_restore / 100);
680 } else {
681 research->bulbs_researched = 0;
682 }
683 research->researching_saved = A_UNKNOWN;
684
685 log_debug("%s: tech loss (%s)",
686 research_rule_name(research),
687 (is_future_tech(tech) ? "Future Tech"
688 : research_advance_rule_name(research, tech)));
689 research_tech_lost(research, 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."),
694 research_advance_name_translation(research, tech));
695 }
696 }
697
698 /* Check for finished research. */
699 if (!check_tech
700 || research->researching == A_UNSET
701 || (research->bulbs_researched
702 < research_total_bulbs_required(research, research->researching,
703 FALSE))) {
704 break;
705 }
706
707 tech_researched(research);
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
724 advance_index_iterate(A_FIRST, i) {
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 */
732 Tech_type_id root = advance_required(i, AR_ROOT);
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 }
739 if (!game.info.tech_loss_allow_holes) {
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 }
755 } advance_index_iterate_end;
756
757 if (eligible == 0) {
758 /* no researched technology at all */
759 return A_NONE;
760 }
761
762 chosen = fc_rand(eligible) + 1;
763
764 advance_index_iterate(A_FIRST, i) {
765 if (BV_ISSET(eligible_techs, i)) {
766 chosen--;
767 if (chosen == 0) {
768 return i;
769 }
770 }
771 } advance_index_iterate_end;
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 *
783pick_random_government(struct player *pplayer)
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 }
792 } governments_iterate_end;
793 fc_assert(NULL != picked);
794 return picked;
795}
796
797/************************************************************************/
800 static 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
805 research_pretty_name(presearch, research_name, sizeof(research_name));
806
807 presearch->techs_researched--;
808 if (is_future_tech(tech)) {
809 presearch->future_tech--;
810 research_update(presearch);
811 /* Notify after decreasing the future tech counter, to get the right
812 * tech number in the message. */
813 notify_research_embassies(presearch, NULL, E_TECH_EMBASSY, ftc_server,
814 _("The %s have lost %s."),
815 research_name,
816 research_advance_name_translation(presearch,
817 tech));
818 /* Inform players about their technology loss. */
819 send_research_info(presearch, NULL);
820 return;
821 }
822
823 fc_assert_ret(valid_advance_by_number(tech));
824 notify_research_embassies(presearch, NULL, E_TECH_EMBASSY, ftc_server,
825 /* TRANS: technology loss */
826 _("The %s have lost %s."),
827 research_name,
828 research_advance_name_translation(presearch,
829 tech));
830
831 /* Remove technology. */
832 research_invention_set(presearch, tech, TECH_UNKNOWN);
833 research_update(presearch);
834 log_debug("%s lost tech id %d (%s)", research_rule_name(presearch), tech,
835 advance_rule_name(advance_by_number(tech)));
836
837 /* Inform players about their technology loss. */
838 send_research_info(presearch, NULL);
839
840 research_players_iterate(presearch, pplayer) {
841 /* Check government. */
842 if (!can_change_to_government(pplayer, government_of_player(pplayer))) {
843 /* Lost the technology for the government; switch to random
844 * available government. */
845 struct government *pgov = pick_random_government(pplayer);
846
847 notify_player(pplayer, NULL, E_NEW_GOVERNMENT, ftc_server,
848 _("The required technology for our government '%s' "
849 "was lost. The citizens have started a "
850 "revolution into '%s'."),
851 government_name_translation(government_of_player
852 (pplayer)),
853 government_name_translation(pgov));
854 handle_player_change_government(pplayer, government_number(pgov));
855 send_player_info_c(pplayer, NULL);
856 } else if (NULL != pplayer->target_government
857 && !can_change_to_government(pplayer,
858 pplayer->target_government)) {
859 /* Lost the technology for the target government; use a random
860 * available government as new target government. */
861 struct government *pgov = pick_random_government(pplayer);
862
863 notify_player(pplayer, NULL, E_NEW_GOVERNMENT, ftc_server,
864 _("The required technology for our new government "
865 "'%s' was lost. The citizens chose '%s' as new "
866 "target government."),
867 government_name_translation(pplayer->target_government),
868 government_name_translation(pgov));
869 pplayer->target_government = pgov;
870 send_player_info_c(pplayer, pplayer->connections);
871 }
872
873 /* Check all units for valid activities. */
874 unit_activities_cancel_all_illegal_plr(pplayer);
875
876 /* Check city production */
877 city_list_iterate(pplayer->cities, pcity) {
878 bool update = FALSE;
879
880 if (pcity->production.kind == VUT_UTYPE
881 && !can_city_build_unit_now(pcity, pcity->production.value.utype)) {
882 notify_player(pplayer, city_tile(pcity),
883 E_CITY_CANTBUILD, ftc_server,
884 _("%s can't build %s. The required technology was "
885 "lost."),
886 city_link(pcity),
887 utype_name_translation(pcity->production.value.utype));
888 choose_build_target(pplayer, pcity);
889 update = TRUE;
890 }
891
892 if (pcity->production.kind == VUT_IMPROVEMENT
893 && !can_city_build_improvement_now(pcity,
894 pcity->production.value.building)) {
895 notify_player(pplayer, city_tile(pcity),
896 E_CITY_CANTBUILD, ftc_server,
897 _("%s can't build %s. The required technology was "
898 "lost."),
899 city_link(pcity),
900 improvement_name_translation
901 (pcity->production.value.building));
902 choose_build_target(pplayer, pcity);
903 update = TRUE;
904 }
905
906 if (update) {
907 city_refresh(pcity);
908 send_city_info(pplayer, pcity);
909 }
910 } city_list_iterate_end;
911 } research_players_iterate_end;
912}
913
914/************************************************************************/
917 static Tech_type_id pick_random_tech(const struct research *presearch)
918{
919 Tech_type_id tech = A_FUTURE;
920 int num_techs = 0;
921
922 advance_index_iterate(A_FIRST, i) {
923 if (research_invention_state(presearch, i) == TECH_PREREQS_KNOWN) {
924 if (fc_rand(++num_techs) == 0) {
925 tech = i;
926 }
927 }
928 } advance_index_iterate_end;
929 return tech;
930}
931
932/************************************************************************/
935 static Tech_type_id pick_cheapest_tech(const struct research *presearch)
936{
937 int cheapest_cost = -1;
938 int cheapest_amount = 0;
939 Tech_type_id cheapest = A_FUTURE; /* If no real tech is found to be missing */
940
941 advance_index_iterate(A_FIRST, i) {
942 if (research_invention_state(presearch, i) == TECH_PREREQS_KNOWN) {
943 int cost = research_total_bulbs_required(presearch, i, FALSE);
944
945 if (cost < cheapest_cost || cheapest_cost == -1) {
946 cheapest_cost = cost;
947 cheapest_amount = 1;
948 cheapest = i;
949 } else if (cost == cheapest_cost && fc_rand(++cheapest_amount) == 0) {
950 cheapest = i;
951 }
952 }
953 } advance_index_iterate_end;
954
955 return cheapest;
956}
957
958/************************************************************************/
967 void choose_random_tech(struct research *research)
968{
969 do {
970 choose_tech(research, pick_random_tech(research));
971 } while (research->researching == A_UNSET);
972}
973
974/************************************************************************/
982 void choose_tech(struct research *research, Tech_type_id tech)
983{
984 int bulbs_res = 0;
985
986 if (is_future_tech(tech)) {
987 if (is_future_tech(research->researching)
988 && (research->bulbs_researched
989 >= research_total_bulbs_required(research, tech, FALSE))) {
990 tech_researched(research);
991 }
992 } else {
993 if (research->researching == tech) {
994 return;
995 }
996 if (research_invention_state(research, tech) != TECH_PREREQS_KNOWN) {
997 /* Can't research this. */
998 return;
999 }
1000 }
1001
1002 if (game.server.multiresearch) {
1003 advance_index_iterate(A_FIRST, j) {
1004 /* Save old tech research */
1005 if (j == research->researching) {
1006 research->inventions[j].bulbs_researched_saved = research->bulbs_researched;
1007 }
1008 /* New tech*/
1009 if (j == tech) {
1010 bulbs_res = research->inventions[j].bulbs_researched_saved;
1011 }
1012 } advance_index_iterate_end;
1013 research->researching = tech;
1014 if (!research->got_tech_multi) {
1015 research->bulbs_researched = 0;
1016 }
1017 research->bulbs_researched = research->bulbs_researched + bulbs_res;
1018 research->got_tech_multi = FALSE;
1019 if (research->bulbs_researched
1020 >= research_total_bulbs_required(research, tech, FALSE)) {
1021 tech_researched(research);
1022 }
1023 return;
1024 }
1025
1026 if (!research->got_tech && research->researching_saved == A_UNKNOWN) {
1027 research->bulbs_researching_saved = research->bulbs_researched;
1028 research->researching_saved = research->researching;
1029 /* Subtract a penalty because we changed subject. */
1030 if (research->bulbs_researched > 0) {
1031 research->bulbs_researched
1032 -= ((research->bulbs_researched * game.server.techpenalty) / 100);
1033 fc_assert(research->bulbs_researched >= 0);
1034 }
1035 } else if (tech == research->researching_saved) {
1036 research->bulbs_researched = research->bulbs_researching_saved;
1037 research->researching_saved = A_UNKNOWN;
1038 }
1039 research->researching = tech;
1040 if (research->bulbs_researched
1041 >= research_total_bulbs_required(research, tech, FALSE)) {
1042 tech_researched(research);
1043 }
1044}
1045
1046/************************************************************************/
1050 void choose_tech_goal(struct research *presearch, Tech_type_id tech)
1051{
1052 fc_assert_ret(presearch != NULL);
1053
1054 if (tech == presearch->tech_goal) {
1055 return;
1056 }
1057
1058 /* It's been suggested that if the research target is empty then
1059 * choose_random_tech() should be called here. */
1060 presearch->tech_goal = tech;
1061 notify_research(presearch, NULL, E_TECH_GOAL, ftc_server,
1062 _("Technology goal is %s."),
1063 research_advance_name_translation(presearch, tech));
1064}
1065
1066/************************************************************************/
1069 void init_tech(struct research *research, bool update)
1070{
1071 research_invention_set(research, A_NONE, TECH_KNOWN);
1072
1073 advance_index_iterate(A_FIRST, i) {
1074 research_invention_set(research, i, TECH_UNKNOWN);
1075 } advance_index_iterate_end;
1076
1077#ifdef TECH_UPKEEP_DEBUGGING
1078 /* Print a list of the needed upkeep if 'i' techs are researched.
1079 * If the ruleset contains self-rooted techs this can not work! */
1080 {
1081 bool global_state[A_LAST];
1082 Tech_type_id tech = A_LAST;
1083
1084 /* Save the game research state. */
1085 advance_index_iterate(A_FIRST, i) {
1086 global_state[i] = game.info.global_advances[i];
1087 } advance_index_iterate_end;
1088
1089 research->techs_researched = 1;
1090 research_update(presearch);
1091
1092 /* Show research costs. */
1093 advance_index_iterate(A_NONE, i) {
1094 log_debug("[research %d] %-25s (ID: %3d) cost: %6d - reachable: %-3s "
1095 "(now) / %-3s (ever)", research_number(research),
1096 advance_rule_name(advance_by_number(i)), i,
1097 research_total_bulbs_required(research, i, FALSE),
1098 research_invention_gettable(research, i, FALSE)
1099 ? "yes" : "no",
1100 research_invention_reachable(research, i) ? "yes" : "no");
1101 } advance_index_iterate_end;
1102
1103 /* Update step for step each tech as known and print the upkeep. */
1104 while (tech != A_NONE) {
1105 tech = A_NONE;
1106 advance_index_iterate(A_FIRST, i) {
1107 if (valid_advance_by_number(i) != NULL
1108 && research_invention_state(research, i) == TECH_PREREQS_KNOWN) {
1109 /* Found a tech which can be researched. */
1110 tech = i;
1111 break;
1112 }
1113 } advance_index_iterate_end;
1114
1115 if (tech != A_NONE) {
1116 research->inventions[tech].state = TECH_KNOWN;
1117 research->techs_researched++;
1118
1119 /* This will change the game state! */
1120 research_update(research);
1121
1122 research_players_iterate(research, pplayer) {
1123 log_debug("[player %d] researched: %-25s (ID: %4d) techs: %3d "
1124 "upkeep: %4d", research_number(research),
1125 advance_rule_name(advance_by_number(tech)), tech,
1126 research->techs_researched, player_tech_upkeep(pplayer));
1127 } research_players_iterate_end;
1128 }
1129 }
1130
1131 /* Reset the changes done. */
1132 advance_index_iterate(A_FIRST, i) {
1133 research_invention_set(research, i, TECH_UNKNOWN);
1134 game.info.global_advances[i] = global_state[i];
1135 } advance_index_iterate_end;
1136 }
1137#endif /* TECH_UPKEEP_DEBUGGING */
1138
1139 research->techs_researched = 1;
1140
1141 if (update) {
1142 Tech_type_id next_tech;
1143
1144 /* Mark the reachable techs */
1145 research_update(research);
1146
1147 next_tech = research_goal_step(research, research->tech_goal);
1148 if (A_UNSET != next_tech) {
1149 choose_tech(research, next_tech);
1150 } else {
1151 choose_random_tech(research);
1152 }
1153 }
1154}
1155
1156/************************************************************************/
1161 void give_initial_techs(struct research *presearch, int num_random_techs)
1162{
1163 int i;
1164
1165 /* Global techs. */
1166 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
1167 if (game.rgame.global_init_techs[i] == A_LAST) {
1168 break;
1169 }
1170 /* Maybe the player already got this tech by an other way (e.g. team). */
1171 if (research_invention_state(presearch, game.rgame.global_init_techs[i])
1172 != TECH_KNOWN) {
1173 found_new_tech(presearch, game.rgame.global_init_techs[i],
1174 FALSE, TRUE);
1175 }
1176 }
1177
1178 /* Nation techs. */
1179 research_players_iterate(presearch, pplayer) {
1180 const struct nation_type *pnation = nation_of_player(pplayer);
1181
1182 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
1183 if (pnation->init_techs[i] == A_LAST) {
1184 break;
1185 }
1186 /* Maybe the player already got this tech by an other way. */
1187 if (research_invention_state(presearch, pnation->init_techs[i])
1188 != TECH_KNOWN) {
1189 found_new_tech(presearch, pnation->init_techs[i], FALSE, TRUE);
1190 }
1191 }
1192 } research_players_iterate_end;
1193
1194 /* Random free techs (N.B.: freecost penalty not applied). */
1195 for (i = 0; i < num_random_techs; i++) {
1196 found_new_tech(presearch, pick_random_tech(presearch), FALSE, TRUE);
1197 }
1198}
1199
1200/************************************************************************/
1207 Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim,
1208 Tech_type_id preferred)
1209{
1210 struct research *presearch, *vresearch;
1211 Tech_type_id stolen_tech = A_NONE;
1212 const char *advance_name;
1213 char research_name[MAX_LEN_NAME * 2];
1214
1215 if (get_player_bonus(victim, EFT_NOT_TECH_SOURCE) > 0) {
1216 return A_NONE;
1217 }
1218
1219 presearch = research_get(pplayer);
1220 vresearch = research_get(victim);
1221
1222 if (preferred == A_UNSET) {
1223 int j = 0;
1224
1225 advance_index_iterate(A_FIRST, i) {
1226 if (research_invention_gettable(presearch, i,
1227 game.info.tech_steal_allow_holes)
1228 && research_invention_state(presearch, i) != TECH_KNOWN
1229 && research_invention_state(vresearch, i) == TECH_KNOWN) {
1230 j++;
1231 }
1232 } advance_index_iterate_end;
1233
1234 if (j == 0) {
1235 /* We've moved on to future tech */
1236 if (vresearch->future_tech > presearch->future_tech) {
1237 stolen_tech = A_FUTURE;
1238 } else {
1239 return A_NONE;
1240 }
1241 } else {
1242 /* Pick random tech */
1243 j = fc_rand(j) + 1;
1244 stolen_tech = A_NONE; /* Avoid compiler warning */
1245 advance_index_iterate(A_FIRST, i) {
1246 if (research_invention_gettable(presearch, i,
1247 game.info.tech_steal_allow_holes)
1248 && research_invention_state(presearch, i) != TECH_KNOWN
1249 && research_invention_state(vresearch, i) == TECH_KNOWN) {
1250 j--;
1251 }
1252 if (j == 0) {
1253 stolen_tech = i;
1254 break;
1255 }
1256 } advance_index_iterate_end;
1257 fc_assert(stolen_tech != A_NONE);
1258 }
1259 } else { /* preferred != A_UNSET */
1260#ifndef FREECIV_NDEBUG
1261 if (!is_future_tech(preferred)) {
1262 fc_assert(NULL != valid_advance_by_number(preferred));
1263 fc_assert(TECH_KNOWN == research_invention_state(vresearch,
1264 preferred));
1265 }
1266#endif /* FREECIV_NDEBUG */
1267 stolen_tech = preferred;
1268 }
1269
1270 advance_name = research_advance_name_translation(presearch, stolen_tech);
1271 research_pretty_name(presearch, research_name, sizeof(research_name));
1272 notify_player(pplayer, NULL, E_MY_DIPLOMAT_THEFT, ftc_server,
1273 _("You steal %s from the %s."),
1274 advance_name,
1275 nation_plural_for_player(victim));
1276 notify_research(presearch, pplayer, E_TECH_GAIN, ftc_server,
1277 _("The %s stole %s from the %s and shared it with you."),
1278 nation_plural_for_player(pplayer),
1279 advance_name,
1280 nation_plural_for_player(victim));
1281
1282 notify_player(victim, NULL, E_ENEMY_DIPLOMAT_THEFT, ftc_server,
1283 _("The %s stole %s from you!"),
1284 nation_plural_for_player(pplayer),
1285 advance_name);
1286
1287 notify_research_embassies(presearch, victim, E_TECH_EMBASSY, ftc_server,
1288 _("The %s have stolen %s from the %s."),
1289 research_name,
1290 advance_name,
1291 nation_plural_for_player(victim));
1292
1293 if (tech_transfer(pplayer, victim, stolen_tech)) {
1294 research_apply_penalty(presearch, stolen_tech, game.server.conquercost);
1295 found_new_tech(presearch, stolen_tech, FALSE, TRUE);
1296 script_tech_learned(presearch, pplayer, advance_by_number(stolen_tech),
1297 "stolen");
1298 return stolen_tech;
1299 }
1300
1301 return A_NONE;
1302}
1303
1304/************************************************************************/
1311 void handle_player_research(struct player *pplayer, int tech)
1312{
1313 struct research *research = research_get(pplayer);
1314
1315 if (tech != A_FUTURE && !valid_advance_by_number(tech)) {
1316 return;
1317 }
1318
1319 if (tech != A_FUTURE
1320 && research_invention_state(research, tech) != TECH_PREREQS_KNOWN) {
1321 return;
1322 }
1323
1324 choose_tech(research, tech);
1325
1326 /* Notify players sharing the same research. */
1327 send_research_info(research, NULL);
1328}
1329
1330/************************************************************************/
1334 void handle_player_tech_goal(struct player *pplayer, int tech_goal)
1335{
1336 struct research *research = research_get(pplayer);
1337
1338 /* Set the tech goal to a defined state if it is
1339 * - not a future tech and not a valid goal
1340 * - not a future tech and not a valid advance
1341 * - not defined
1342 * - known (i.e. due to EFT_GIVE_IMM_TECH). */
1343 if ((tech_goal != A_FUTURE
1344 && (!valid_advance_by_number(tech_goal)
1345 || !research_invention_reachable(research, tech_goal)))
1346 || (tech_goal == A_NONE)
1347 || (TECH_KNOWN == research_invention_state(research, tech_goal))) {
1348 tech_goal = A_UNSET;
1349 }
1350
1351 choose_tech_goal(research, tech_goal);
1352
1353 /* Notify players sharing the same research. */
1354 send_research_info(research, NULL);
1355}
1356
1357/************************************************************************/
1360 Tech_type_id pick_free_tech(struct research *presearch)
1361{
1362 Tech_type_id tech;
1363
1364 if (game.info.free_tech_method == FTM_CHEAPEST) {
1365 tech = pick_cheapest_tech(presearch);
1366 } else if (presearch->researching == A_UNSET
1367 || game.info.free_tech_method == FTM_RANDOM) {
1368 tech = pick_random_tech(presearch);
1369 } else {
1370 tech = presearch->researching;
1371 }
1372 return tech;
1373}
1374
1375/************************************************************************/
1379 void give_immediate_free_tech(struct research *presearch, Tech_type_id tech)
1380{
1381 research_apply_penalty(presearch, tech, game.server.freecost);
1382 found_new_tech(presearch, tech, FALSE, TRUE);
1383}
1384
1385/************************************************************************/
1388 static void forget_tech_transferred(struct player *pplayer, Tech_type_id tech)
1389{
1390 struct research *presearch = research_get(pplayer);
1391
1392 research_tech_lost(presearch, tech);
1393 /* Make notification after losing the research, in case it is a future
1394 * tech (for getting the right tech number). */
1395 notify_player(pplayer, NULL, E_TECH_LOST, ftc_server,
1396 _("Too bad! You made a mistake transferring the tech %s and "
1397 "lost it."),
1398 research_advance_name_translation(presearch, tech));
1399 notify_research(presearch, pplayer, E_TECH_LOST, ftc_server,
1400 _("Too bad! The %s made a mistake transferring the tech "
1401 "%s and lost it."),
1402 nation_plural_for_player(pplayer),
1403 research_advance_name_translation(presearch, tech));
1404}
1405
1406/************************************************************************/
1410 bool tech_transfer(struct player *plr_recv, struct player *plr_donor,
1411 Tech_type_id tech)
1412{
1413 if (game.server.techlost_donor > 0) {
1414 struct research *donor_research = research_get(plr_donor);
1415 bool donor_can_lose = TRUE;
1416
1417 advance_index_iterate(A_FIRST, i) {
1418 /* Never let donor lose tech if it's root_req for some other known
1419 * tech */
1420 if (research_invention_state(donor_research, i) == TECH_KNOWN
1421 && (advance_required(i, AR_ROOT) == tech
1422 || (!game.info.tech_trade_loss_allow_holes
1423 && (advance_required(i, AR_ONE) == tech
1424 || advance_required(i, AR_TWO) == tech)))) {
1425 donor_can_lose = FALSE;
1426 break;
1427 }
1428 } advance_index_iterate_end;
1429 if (donor_can_lose && fc_rand(100) < game.server.techlost_donor) {
1430 forget_tech_transferred(plr_donor, tech);
1431 }
1432 }
1433
1434 if (fc_rand(100) < game.server.techlost_recv) {
1435 struct research *presearch = research_get(plr_recv);
1436
1437 /* We've not received the tech yet, and never will.
1438 * Do not call forget_tech_transferred() that would handle it
1439 * as something we had and now lose.
1440 * (e.g. subtracting techs_researched counter) */
1441 notify_player(plr_recv, NULL, E_TECH_LOST, ftc_server,
1442 _("Too bad! You made a mistake transferring the tech %s and "
1443 "didn't get it."),
1444 research_advance_name_translation(presearch, tech));
1445 notify_research(presearch, plr_recv, E_TECH_LOST, ftc_server,
1446 _("Too bad! The %s made a mistake transferring the tech "
1447 "%s and didn't get it."),
1448 nation_plural_for_player(plr_recv),
1449 research_advance_name_translation(presearch, tech));
1450 return FALSE;
1451 }
1452
1453 return TRUE;
1454}
astr_free
void astr_free(struct astring *astr)
Definition astring.c:153
astr_init
void astr_init(struct astring *astr)
Definition astring.c:144
astring.h
astr_str
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
BV_SET_ALL
#define BV_SET_ALL(bv)
Definition bitvector.h:99
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
BV_CLR
#define BV_CLR(bv, bit)
Definition bitvector.h:86
can_city_build_improvement_now
bool can_city_build_improvement_now(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:838
can_city_build_unit_now
bool can_city_build_unit_now(const struct city *pcity, const struct unit_type *punittype)
Definition city.c:925
city_list_iterate
#define city_list_iterate(citylist, pcity)
Definition city.h:488
city_tile
#define city_tile(_pcity_)
Definition city.h:544
city_owner
#define city_owner(_pcity_)
Definition city.h:543
city_list_iterate_end
#define city_list_iterate_end
Definition city.h:490
send_city_info
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2313
city_refresh_vision
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3324
citytools.h
remove_obsolete_buildings
void remove_obsolete_buildings(struct player *pplayer)
Definition cityturn.c:272
choose_build_target
void choose_build_target(struct player *pplayer, struct city *pcity)
Definition cityturn.c:2230
city_refresh
bool city_refresh(struct city *pcity)
Definition cityturn.c:161
cityturn.h
connecthand.h
conn_get_player
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:760
conn_list_iterate
#define conn_list_iterate(connlist, pconn)
Definition connection.h:113
conn_list_iterate_end
#define conn_list_iterate_end
Definition connection.h:115
cost
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
effects
struct effect_list * effects[EFT_COUNT]
Definition effects.c:120
get_player_bonus_effects
int get_player_bonus_effects(struct effect_list *plist, const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:1052
get_player_bonus
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:771
get_effect_list_req_text
void get_effect_list_req_text(const struct effect_list *plist, struct astring *astr)
Definition effects.c:1225
Tech_type_id
int Tech_type_id
Definition fc_types.h:347
MAX_LEN_NAME
#define MAX_LEN_NAME
Definition fc_types.h:66
MAX_NUM_TECH_LIST
#define MAX_NUM_TECH_LIST
Definition fc_types.h:44
O_SCIENCE
@ O_SCIENCE
Definition fc_types.h:91
fcintl.h
Q_
#define Q_(String)
Definition fcintl.h:70
_
#define _(String)
Definition fcintl.h:67
ftc_server
const struct ft_color ftc_server
Definition featured_text.c:77
city_link
const char * city_link(const struct city *pcity)
Definition featured_text.c:1072
game
struct civ_game game
Definition game.c:57
wld
struct world wld
Definition game.c:58
game.h
send_game_info
void send_game_info(struct conn_list *dest)
Definition gamehand.c:905
gamehand.h
government_name_translation
const char * government_name_translation(const struct government *pgovern)
Definition government.c:142
government_count
Government_type_id government_count(void)
Definition government.c:70
government_of_player
struct government * government_of_player(const struct player *pplayer)
Definition government.c:113
can_change_to_government
bool can_change_to_government(struct player *pplayer, const struct government *gov)
Definition government.c:165
government_number
Government_type_id government_number(const struct government *pgovern)
Definition government.c:90
government_index
Government_type_id government_index(const struct government *pgovern)
Definition government.c:81
government.h
governments_iterate
#define governments_iterate(NAME_pgov)
Definition government.h:120
governments_iterate_end
#define governments_iterate_end
Definition government.h:123
handle_player_change_government
void handle_player_change_government(struct player *pplayer, Government_type_id government)
Definition plrhand.c:454
is_great_wonder
bool is_great_wonder(const struct impr_type *pimprove)
Definition improvement.c:767
improvement_name_translation
const char * improvement_name_translation(const struct impr_type *pimprove)
Definition improvement.c:241
city_from_great_wonder
struct city * city_from_great_wonder(const struct impr_type *pimprove)
Definition improvement.c:989
improvement_iterate_end
#define improvement_iterate_end
Definition improvement.h:211
improvement_iterate
#define improvement_iterate(_p)
Definition improvement.h:205
log.h
fc_assert_msg
#define fc_assert_msg(condition, message,...)
Definition log.h:181
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
log_verbose
#define log_verbose(message,...)
Definition log.h:109
fc_assert
#define fc_assert(condition)
Definition log.h:176
log_debug
#define log_debug(message,...)
Definition log.h:115
luascript_types.h
whole_map_iterate
#define whole_map_iterate(_map, _tile)
Definition map.h:539
whole_map_iterate_end
#define whole_map_iterate_end
Definition map.h:548
send_tile_info
void send_tile_info(struct conn_list *dest, struct tile *ptile, bool send_unknown)
Definition maphand.c:488
update_player_tile_knowledge
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1383
upgrade_all_city_extras
void upgrade_all_city_extras(struct player *pplayer, bool discovery)
Definition maphand.c:273
map_is_known_and_seen
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:900
maphand.h
mem.h
movement.h
nation_of_player
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:443
nation_plural_for_player
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:177
notify_research
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:394
notify_player
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:292
notify_research_embassies
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:434
notify.h
send_packet_unknown_research
int send_packet_unknown_research(struct connection *pc, const struct packet_unknown_research *packet)
Definition packets_gen.c:37322
send_packet_research_info
int send_packet_research_info(struct connection *pc, const struct packet_research_info *packet)
Definition packets_gen.c:37143
player_slot_count
int player_slot_count(void)
Definition player.c:411
player_name
const char * player_name(const struct player *pplayer)
Definition player.c:886
team_has_embassy
bool team_has_embassy(const struct team *pteam, const struct player *tgt_player)
Definition player.c:214
player_index
int player_index(const struct player *pplayer)
Definition player.c:820
player.h
players_iterate_end
#define players_iterate_end
Definition player.h:535
players_iterate
#define players_iterate(_pplayer)
Definition player.h:530
is_ai
#define is_ai(plr)
Definition player.h:234
send_player_all_c
void send_player_all_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:983
send_player_info_c
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1000
plrhand.h
shuffled_players_iterate_end
#define shuffled_players_iterate_end
Definition plrhand.h:106
shuffled_players_iterate
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:96
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:34
requirement_vector_iterate_end
#define requirement_vector_iterate_end
Definition requirements.h:93
requirement_vector_iterate
#define requirement_vector_iterate(req_vec, preq)
Definition requirements.h:91
research_invention_reachable
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Definition research.c:665
research_invention_set
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:634
research_advance_rule_name
const char * research_advance_rule_name(const struct research *presearch, Tech_type_id tech)
Definition research.c:238
player_tech_upkeep
int player_tech_upkeep(const struct player *pplayer)
Definition research.c:1040
research_number
int research_number(const struct research *presearch)
Definition research.c:107
research_advance_name_translation
const char * research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Definition research.c:271
research_total_bulbs_required
int research_total_bulbs_required(const struct research *presearch, Tech_type_id tech, bool loss_value)
Definition research.c:858
research_rule_name
const char * research_rule_name(const struct research *presearch)
Definition research.c:141
research_get
struct research * research_get(const struct player *pplayer)
Definition research.c:126
research_invention_state
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:616
research_goal_step
Tech_type_id research_goal_step(const struct research *presearch, Tech_type_id goal)
Definition research.c:717
research_invention_gettable
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Definition research.c:690
research_update
void research_update(struct research *presearch)
Definition research.c:499
research_pretty_name
int research_pretty_name(const struct research *presearch, char *buf, size_t buf_len)
Definition research.c:167
research.h
research_players_iterate
#define research_players_iterate(_presearch, _pplayer)
Definition research.h:168
researches_iterate
#define researches_iterate(_presearch)
Definition research.h:157
research_players_iterate_end
#define research_players_iterate_end
Definition research.h:172
researches_iterate_end
#define researches_iterate_end
Definition research.h:160
script_server_signal_emit
void script_server_signal_emit(const char *signal_name,...)
Definition script_server.c:408
script_server.h
shared.h
advance
Definition tech.h:124
astring
Definition astring.h:36
city
Definition city.h:309
civ_game::rgame
struct civ_game::@29 rgame
civ_game::multiresearch
bool multiresearch
Definition game.h:162
civ_game::server
struct civ_game::@30::@34 server
civ_game::techlost_recv
int techlost_recv
Definition game.h:193
civ_game::est_connections
struct conn_list * est_connections
Definition game.h:97
civ_game::global_init_techs
int global_init_techs[MAX_NUM_TECH_LIST]
Definition game.h:107
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::conquercost
int conquercost
Definition game.h:135
civ_game::techloss_restore
int techloss_restore
Definition game.h:191
civ_game::freecost
int freecost
Definition game.h:147
civ_game::techlost_donor
int techlost_donor
Definition game.h:192
civ_game::techpenalty
int techpenalty
Definition game.h:195
government
Definition government.h:52
nation_type
Definition nation.h:97
nation_type::init_techs
int init_techs[MAX_NUM_TECH_LIST]
Definition nation.h:121
packet_game_info::tech_steal_allow_holes
bool tech_steal_allow_holes
Definition packets_gen.h:211
packet_game_info::techloss_forgiveness
int techloss_forgiveness
Definition packets_gen.h:230
packet_game_info::tech_trade_loss_allow_holes
bool tech_trade_loss_allow_holes
Definition packets_gen.h:213
packet_game_info::free_tech_method
enum free_tech_method free_tech_method
Definition packets_gen.h:231
packet_game_info::global_advances
bool global_advances[A_LAST]
Definition packets_gen.h:163
packet_game_info::tech_loss_allow_holes
bool tech_loss_allow_holes
Definition packets_gen.h:215
packet_game_info::tech_parasite_allow_holes
bool tech_parasite_allow_holes
Definition packets_gen.h:214
packet_research_info
Definition packets_gen.h:613
packet_research_info::tech_goal
int tech_goal
Definition packets_gen.h:620
packet_research_info::researching
int researching
Definition packets_gen.h:617
packet_research_info::inventions
char inventions[A_LAST+1]
Definition packets_gen.h:622
packet_research_info::techs_researched
int techs_researched
Definition packets_gen.h:615
packet_research_info::id
int id
Definition packets_gen.h:614
packet_research_info::future_tech
int future_tech
Definition packets_gen.h:616
packet_research_info::bulbs_researched
int bulbs_researched
Definition packets_gen.h:619
packet_research_info::researching_cost
int researching_cost
Definition packets_gen.h:618
packet_research_info::total_bulbs_prod
int total_bulbs_prod
Definition packets_gen.h:621
packet_unknown_research
Definition packets_gen.h:625
packet_unknown_research::id
int id
Definition packets_gen.h:626
player
Definition player.h:249
player::bulbs_last_turn
int bulbs_last_turn
Definition player.h:351
player::team
struct team * team
Definition player.h:261
player::is_alive
bool is_alive
Definition player.h:268
player::server
struct player::@69::@71 server
research::research_invention::bulbs_researched_saved
int bulbs_researched_saved
Definition research.h:80
research::research_invention::state
enum tech_state state
Definition research.h:73
research
Definition research.h:39
research::researching
Tech_type_id researching
Definition research.h:52
research::future_tech
int future_tech
Definition research.h:42
research::tech_goal
Tech_type_id tech_goal
Definition research.h:85
research::bulbs_researching_saved
int bulbs_researching_saved
Definition research.h:63
research::inventions
struct research::research_invention inventions[A_ARRAY_SIZE]
research::got_tech_multi
bool got_tech_multi
Definition research.h:69
research::researching_saved
Tech_type_id researching_saved
Definition research.h:62
research::got_tech
bool got_tech
Definition research.h:67
research::techs_researched
int techs_researched
Definition research.h:42
research::bulbs_researched
int bulbs_researched
Definition research.h:53
world::map
struct civ_map map
Definition world_object.h:38
support.h
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
advance_by_number
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
is_future_tech
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
advance_has_flag
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:216
valid_advance_by_number
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
advance_required
Tech_type_id advance_required(const Tech_type_id tech, enum tech_req require)
Definition tech.c:121
advance_rule_name
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
tech.h
A_FUTURE
#define A_FUTURE
Definition tech.h:46
advance_index_iterate_end
#define advance_index_iterate_end
Definition tech.h:248
AR_TWO
@ AR_TWO
Definition tech.h:112
AR_ROOT
@ AR_ROOT
Definition tech.h:113
AR_ONE
@ AR_ONE
Definition tech.h:111
advance_count
static Tech_type_id advance_count(void)
Definition tech.h:170
A_FIRST
#define A_FIRST
Definition tech.h:44
A_NONE
#define A_NONE
Definition tech.h:43
A_UNSET
#define A_UNSET
Definition tech.h:48
A_UNKNOWN
#define A_UNKNOWN
Definition tech.h:49
A_LAST
#define A_LAST
Definition tech.h:45
advance_index_iterate
#define advance_index_iterate(_start, _index)
Definition tech.h:244
pick_cheapest_tech
static Tech_type_id pick_cheapest_tech(const struct research *presearch)
Definition techtools.c:935
handle_player_tech_goal
void handle_player_tech_goal(struct player *pplayer, int tech_goal)
Definition techtools.c:1334
init_tech
void init_tech(struct research *research, bool update)
Definition techtools.c:1069
pick_random_government
static struct government * pick_random_government(struct player *pplayer)
Definition techtools.c:783
found_new_tech
void found_new_tech(struct research *presearch, Tech_type_id tech_found, bool was_discovery, bool saving_bulbs)
Definition techtools.c:327
lose_tech
static bool lose_tech(struct research *research)
Definition techtools.c:607
choose_tech_goal
void choose_tech_goal(struct research *presearch, Tech_type_id tech)
Definition techtools.c:1050
research_apply_penalty
void research_apply_penalty(struct research *presearch, Tech_type_id tech, int penalty_percent)
Definition techtools.c:67
tech_researched
static void tech_researched(struct research *research)
Definition techtools.c:107
choose_tech
void choose_tech(struct research *research, Tech_type_id tech)
Definition techtools.c:982
pick_random_tech_to_lose
static Tech_type_id pick_random_tech_to_lose(const struct research *presearch)
Definition techtools.c:715
do_tech_parasite_effect
void do_tech_parasite_effect(struct player *pplayer)
Definition techtools.c:143
package_research_info
static void package_research_info(struct packet_research_info *packet, const struct research *presearch)
Definition techtools.c:238
forget_tech_transferred
static void forget_tech_transferred(struct player *pplayer, Tech_type_id tech)
Definition techtools.c:1388
steal_a_tech
Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim, Tech_type_id preferred)
Definition techtools.c:1207
handle_player_research
void handle_player_research(struct player *pplayer, int tech)
Definition techtools.c:1311
pick_free_tech
Tech_type_id pick_free_tech(struct research *presearch)
Definition techtools.c:1360
give_immediate_free_tech
void give_immediate_free_tech(struct research *presearch, Tech_type_id tech)
Definition techtools.c:1379
send_research_info
void send_research_info(const struct research *presearch, const struct conn_list *dest)
Definition techtools.c:273
choose_random_tech
void choose_random_tech(struct research *research)
Definition techtools.c:967
update_bulbs
void update_bulbs(struct player *pplayer, int bulbs, bool check_tech)
Definition techtools.c:643
research_tech_lost
static void research_tech_lost(struct research *presearch, Tech_type_id tech)
Definition techtools.c:800
script_tech_learned
void script_tech_learned(struct research *presearch, struct player *originating_plr, struct advance *tech, const char *reason)
Definition techtools.c:84
give_initial_techs
void give_initial_techs(struct research *presearch, int num_random_techs)
Definition techtools.c:1161
tech_transfer
bool tech_transfer(struct player *plr_recv, struct player *plr_donor, Tech_type_id tech)
Definition techtools.c:1410
pick_random_tech
static Tech_type_id pick_random_tech(const struct research *presearch)
Definition techtools.c:917
techtools.h
unit.h
unit_activities_cancel_all_illegal_plr
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:810
unit_list_refresh_vision
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:4867
unittools.h
utype_name_translation
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1612