Freeciv21
Develop your civilization from humble roots to a global empire
techtools.cpp
Go to the documentation of this file.
1 /*
2 _ ._ Copyright (c) 1996-2021 Freeciv21 and Freeciv contributors.
3  \ | This file is part of Freeciv21. Freeciv21 is free software: you
4  \_| can redistribute it and/or modify it under the terms of the
5  .' '. GNU General Public License as published by the Free
6  :O O: Software Foundation, either version 3 of the License,
7  '/ \' or (at your option) any later version. You should have
8  :X: received a copy of the GNU General Public License along with
9  :X: Freeciv21. If not, see https://www.gnu.org/licenses/.
10  */
11 // utility
12 #include "fcintl.h"
13 #include "log.h"
14 #include "rand.h"
15 #include "support.h"
16 
17 // common
18 #include "game.h"
19 #include "government.h"
20 #include "movement.h"
21 #include "player.h"
22 #include "research.h"
23 #include "tech.h"
24 #include "unit.h"
25 
26 /* common/scriptcore */
27 #include "luascript_types.h"
28 
29 // server
30 #include "citytools.h"
31 #include "cityturn.h"
32 #include "connecthand.h"
33 #include "gamehand.h"
34 #include "maphand.h"
35 #include "notify.h"
36 #include "plrhand.h"
37 #include "unittools.h"
38 
39 /* server/scripting */
40 #include "script_server.h"
41 
42 #include "techtools.h"
43 
44 // Define this to add information about tech upkeep.
45 #undef TECH_UPKEEP_DEBUGGING
46 
47 static Tech_type_id
48 pick_random_tech_to_lose(const struct research *presearch);
49 static Tech_type_id pick_random_tech(const struct research *presearch);
50 static Tech_type_id pick_cheapest_tech(const struct research *presearch);
51 static void research_tech_lost(struct research *presearch,
52  Tech_type_id tech);
53 static void forget_tech_transfered(struct player *pplayer,
54  Tech_type_id tech);
55 
59 void research_apply_penalty(struct research *presearch, Tech_type_id tech,
60  int penalty_percent)
61 {
62  if (game.server.multiresearch) {
63  return;
64  }
65  presearch->bulbs_researched -=
66  (research_total_bulbs_required(presearch, tech, false)
67  * penalty_percent)
68  / 100;
69  presearch->researching_saved = A_UNKNOWN;
70 }
71 
77 void script_tech_learned(struct research *presearch,
78  struct player *originating_plr,
79  struct advance *tech, const char *reason)
80 {
81  /* Emit signal for individual player whose action triggered the
82  * tech first */
83  if (originating_plr) {
84  fc_assert(research_get(originating_plr) == presearch);
85  script_server_signal_emit("tech_researched", tech, originating_plr,
86  reason);
87  }
88 
89  // Emit signal to remaining research teammates, if any
90  research_players_iterate(presearch, member)
91  {
92  if (member != originating_plr) {
93  script_server_signal_emit("tech_researched", tech, member, reason);
94  }
95  }
97 }
98 
102 static void tech_researched(struct research *research)
103 {
104  char research_name[MAX_LEN_NAME * 2];
105  /* Cache researched technology for event signal, because found_new_tech()
106  * changes the research target. */
108 
109  research_pretty_name(research, research_name, sizeof(research_name));
110  // Players will be notified when new tech is chosen.
112  research, nullptr, E_TECH_EMBASSY, ftc_server,
113  _("The %s have researched %s."), research_name,
114  qUtf8Printable(research_advance_name_translation(research, tech)));
115 
116  // Deduct tech cost.
120  {
121  if (j == research->researching) {
124  }
125  }
127 
128  // Do all the updates needed after finding new tech.
129  found_new_tech(research, tech, true, true);
130 
132  "researched");
133 }
134 
139 void do_tech_parasite_effect(struct player *pplayer)
140 {
141  struct effect_list *plist = effect_list_new();
142  struct research *plr_research;
143  QString effects;
144  char research_name[MAX_LEN_NAME * 2];
145  Tech_type_id tech;
146  /* Note that two EFT_TECH_PARASITE effects will combine into a single,
147  * much worse effect. */
148  int mod = get_player_bonus_effects(plist, pplayer, EFT_TECH_PARASITE);
149  int num_techs;
150 
151  if (mod <= 0) {
152  // No effect.
153  effect_list_destroy(plist);
154  return;
155  }
156 
157  // Pick a random technology.
158  tech = A_UNSET;
159  num_techs = 0;
160  plr_research = research_get(pplayer);
162  {
163  int num_teams;
164 
165  if (!research_invention_gettable(plr_research, i,
166  game.info.tech_parasite_allow_holes)
167  || TECH_KNOWN == research_invention_state(plr_research, i)) {
168  continue;
169  }
170 
171  num_teams = 0;
172  for (const auto &other_research : research_array) {
173  if (research_is_valid(other_research)) {
174  if (TECH_KNOWN == research_invention_state(&other_research, i)) {
175  if (mod <= ++num_teams) {
176  if (0 == fc_rand(++num_techs)) {
177  tech = i;
178  }
179  break;
180  }
181  }
182  }
183  };
184  }
186 
187  if (A_UNSET == tech) {
188  // No tech found.
189  effect_list_destroy(plist);
190  return;
191  }
192 
193  // Notify.
194  research_pretty_name(plr_research, research_name, sizeof(research_name));
195  auto advance_name = research_advance_name_translation(plr_research, tech);
197 
198  notify_player(pplayer, nullptr, E_TECH_GAIN, ftc_server,
199  /* TRANS: Tech from source of an effect
200  * (Great Library) */
201  Q_("?fromeffect:%s acquired from %s!"),
202  qUtf8Printable(advance_name), qUtf8Printable(effects));
203  notify_research(plr_research, pplayer, E_TECH_GAIN, ftc_server,
204  /* TRANS: Tech from source of an effect
205  * (Great Library) */
206  Q_("?fromeffect:%s acquired from %s's %s!"),
207  qUtf8Printable(advance_name), player_name(pplayer),
208  qUtf8Printable(effects));
210  plr_research, nullptr, E_TECH_EMBASSY, ftc_server,
211  /* TRANS: Tech from source of an effect
212  * (Great Library) */
213  Q_("?fromeffect:The %s have acquired %s from %s."), research_name,
214  qUtf8Printable(advance_name), qUtf8Printable(effects));
215 
216  effect_list_destroy(plist);
217 
218  // Really get tech.
219  research_apply_penalty(plr_research, tech, game.server.freecost);
220  found_new_tech(plr_research, tech, false, true);
221 
222  research_players_iterate(plr_research, member)
223  {
224  script_server_signal_emit("tech_researched", advance_by_number(tech),
225  member, "stolen");
226  }
228 }
229 
233 static inline void package_research_info(struct packet_research_info *packet,
234  const struct research *presearch)
235 {
236  packet->id = research_number(presearch);
237  packet->techs_researched = presearch->techs_researched;
238  packet->future_tech = presearch->future_tech;
239  packet->researching = presearch->researching;
240  packet->researching_cost =
241  (packet->researching != A_UNSET ? research_total_bulbs_required(
242  presearch, presearch->researching, false)
243  : 0);
244  packet->bulbs_researched = presearch->bulbs_researched;
245  packet->tech_goal = presearch->tech_goal;
246  packet->total_bulbs_prod = 0;
247  research_players_iterate(presearch, pplayer)
248  {
249  city_list_iterate(pplayer->cities, pcity)
250  {
251  packet->total_bulbs_prod += pcity->surplus[O_SCIENCE];
252  }
254  }
257  {
258  packet->inventions[i] = presearch->inventions[i].state + '0';
259  }
261  packet->inventions[advance_count()] = '\0';
262  packet->tech_goal = presearch->tech_goal;
263 #ifdef FREECIV_DEBUG
264  qDebug("Research nb %d inventions: %s", research_number(presearch),
265  packet->inventions);
266 #endif // FREECIV_DEBUG
267 }
268 
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  const struct player *pplayer;
278 
279  fc_assert_ret(nullptr != presearch);
280  if (nullptr == dest) {
281  dest = game.est_connections;
282  }
283 
284  // Packaging
285  package_research_info(&full_info, presearch);
286  restricted_info = full_info;
287  restricted_info.tech_goal = A_UNSET;
288  restricted_info.total_bulbs_prod = 0;
289 
290  conn_list_iterate(dest, pconn)
291  {
292  pplayer = conn_get_player(pconn);
293  if (nullptr != pplayer) {
294  bool intel = false; // Send intel version?
295  bool full = false; // Send full version?
296  const auto team = team_members(pplayer->team);
297 
298  // Team mates always share what they see.
299  player_list_iterate(team, team_mate)
300  {
301  if (presearch == research_get(team_mate)) {
302  full = true;
303  break;
304  }
305 
306  // Maybe there's an embassy?
307  research_players_iterate(presearch, powner)
308  {
309  if (get_player_intel_bonus(team_mate, powner, NI_TECHS,
310  EFT_NATION_INTELLIGENCE)
311  > 0) {
312  intel = true;
313  }
314  }
316 
317  if (intel || full) {
318  break;
319  }
320  }
322 
323  if (full) {
324  send_packet_research_info(pconn, &full_info);
325  } else if (intel) {
326  send_packet_research_info(pconn, &restricted_info);
327  }
328  } else if (pconn->observer) {
329  // Case global observer.
330  send_packet_research_info(pconn, &full_info);
331  }
332  }
334 }
335 
341 void found_new_tech(struct research *presearch, Tech_type_id tech_found,
342  bool was_discovery, bool saving_bulbs)
343 {
344  int had_embassies[MAX_NUM_PLAYER_SLOTS];
345  bool could_switch[MAX_NUM_PLAYER_SLOTS][government_count()];
346  bool was_first = false;
347  bool bonus_tech_hack = false;
348  int i;
349  QString advance_name;
350  struct advance *vap = valid_advance_by_number(tech_found);
351  struct city *pcity;
352 
353  if (!is_future_tech(tech_found)) {
354  fc_assert(nullptr != vap);
355  fc_assert(TECH_KNOWN != research_invention_state(presearch, tech_found));
356 
357  was_first = (!game.info.global_advances[tech_found]);
358  }
359 
360  // Assign 'advance_name' before we increase the future tech counter.
361  advance_name = research_advance_name_translation(presearch, tech_found);
362 
363  if (was_first && vap) {
364  // Alert the owners of any wonders that have been made obsolete
365  improvement_iterate(pimprove)
366  {
367  requirement_vector_iterate(&pimprove->obsolete_by, pobs)
368  {
369  if (pobs->source.kind == VUT_ADVANCE
370  && pobs->source.value.advance == vap
371  && pobs->range >= REQ_RANGE_WORLD && pobs->survives
372  && is_great_wonder(pimprove)
373  && (pcity = city_from_great_wonder(pimprove))) {
374  notify_player(city_owner(pcity), nullptr, E_WONDER_OBSOLETE,
375  ftc_server, _("Discovery of %s OBSOLETES %s in %s!"),
376  qUtf8Printable(research_advance_name_translation(
377  research_get(city_owner(pcity)), tech_found)),
379  city_link(pcity));
380  }
381  }
383  }
385  }
386 
387  if (was_first && !is_future_tech(tech_found)
388  && advance_has_flag(tech_found, TF_BONUS_TECH)) {
389  bonus_tech_hack = true;
390  }
391 
392  /* Memorize some values before the tech is marked as researched.
393  * We will check what has changed later. */
395  players_iterate(aplayer)
396  {
397  i = player_index(aplayer);
398 
399  // Count EFT_HAVE_EMBASSIES effect for each player.
400  had_embassies[i] = get_player_bonus(aplayer, EFT_HAVE_EMBASSIES);
401 
402  if (presearch != research_get(aplayer)) {
403  for (const auto &pgov : governments) {
404  could_switch[i][government_index(&pgov)] = false;
405  }
406  continue;
407  }
408 
409  /* Memorize for the players sharing the research what government
410  * they could switch on. */
411  for (const auto &pgov : governments) {
412  could_switch[i][government_index(&pgov)] =
413  can_change_to_government(aplayer, &pgov);
414  }
415  }
417 
418  /* got_tech allows us to change research without applying techpenalty
419  * (without losing bulbs) */
420  if (tech_found == presearch->researching) {
421  presearch->got_tech = true;
422  presearch->got_tech_multi = true;
423  }
424  presearch->researching_saved = A_UNKNOWN;
425  presearch->techs_researched++;
426 
427  /* Mark the tech as known in the research struct and update
428  * global_advances array. */
429  if (is_future_tech(tech_found)) {
430  presearch->future_tech++;
431  } else {
432  research_invention_set(presearch, tech_found, TECH_KNOWN);
433  research_update(presearch);
434  }
435 
436  if (was_first) {
437  /* Inform all players about new global advances to give them a
438  * chance for obsolete buildings. */
439  send_game_info(nullptr);
440  }
441 
442  /* Make proper changes for all players. Use shuffled order, in case
443  * a script would detect a signal. */
444  shuffled_players_iterate(aplayer)
445  {
446  i = player_index(aplayer);
447 
448  if (presearch == research_get(aplayer)) {
449  // Only for players sharing the research.
450  remove_obsolete_buildings(aplayer);
451 
452  // Give free infrastructure in every city
453  if (tech_found != A_FUTURE) {
454  upgrade_all_city_extras(aplayer, was_discovery);
455 
456  // Revealing of extras with visibility_req
457  whole_map_iterate(&(wld.map), ptile)
458  {
459  if (map_is_known_and_seen(ptile, aplayer, V_MAIN)) {
460  if (update_player_tile_knowledge(aplayer, ptile)) {
461  send_tile_info(aplayer->connections, ptile, false);
462  }
463  }
464  }
466  }
467 
468  /* Enhance vision of units if a player-ranged effect has changed. Note
469  * that world-ranged effects will not be updated immediately. */
470  unit_list_refresh_vision(aplayer->units);
471 
472  // Notify a player about new governments available
473  for (const auto &pgov : governments) {
474  if (!could_switch[i][government_index(&pgov)]
475  && can_change_to_government(aplayer, &pgov)) {
476  notify_player(aplayer, nullptr, E_NEW_GOVERNMENT, ftc_server,
477  _("Discovery of %s makes the government form %s"
478  " available. You may want to start a revolution."),
479  qUtf8Printable(advance_name),
481  }
482  }
483  }
484 
485  // For any player.
486  /* Update all cities in case the tech changed some effects. This is
487  * inefficient; it could be optimized if it's found to be a problem.
488  * But techs aren't researched that often. */
489  city_list_iterate(aplayer->cities, apcity)
490  {
491  // Refresh the city data; this also updates the squared city radius.
492  city_refresh(apcity);
493  city_refresh_vision(apcity);
494  send_city_info(aplayer, apcity);
495  }
497 
498  /* Send all player an updated info of the owner of the Marco Polo
499  * Wonder if this wonder has become obsolete. */
500  if (0 < had_embassies[i]
501  && 0 <= get_player_bonus(aplayer, EFT_HAVE_EMBASSIES)) {
502  send_player_all_c(aplayer, aplayer->connections);
503  players_iterate(pother_player)
504  {
505  if (aplayer != pother_player) {
506  send_player_all_c(aplayer, pother_player->connections);
507  send_player_all_c(pother_player, aplayer->connections);
508  }
509  }
511  }
512  }
514 
515  if (tech_found == presearch->tech_goal) {
516  presearch->tech_goal = A_UNSET;
517  }
518 
519  if (tech_found == presearch->researching) {
520  // Try to pick new tech to research.
521  Tech_type_id next_tech =
522  research_goal_step(presearch, presearch->tech_goal);
523 
524  /* As this function can be recursive, we need to print the messages
525  * before really picking the new technology. */
526  if (A_UNSET != next_tech) {
527  notify_research(presearch, nullptr, E_TECH_LEARNED, ftc_server,
528  _("Learned %s. Our scientists focus on %s; "
529  "goal is %s."),
530  qUtf8Printable(advance_name),
531  qUtf8Printable(research_advance_name_translation(
532  presearch, next_tech)),
533  qUtf8Printable(research_advance_name_translation(
534  presearch, presearch->tech_goal)));
535  } else {
536  if (is_future_tech(tech_found)) {
537  // Continue researching future tech.
538  next_tech = A_FUTURE;
539  } else {
540  /* If there is at least one AI player still alive, then pick
541  * a random tech, else keep A_UNSET. */
542  research_players_iterate(presearch, aplayer)
543  {
544  if (is_ai(aplayer)) {
545  next_tech = pick_random_tech(presearch);
546  break;
547  }
548  }
550  }
551 
552  if (A_UNSET == next_tech) {
553  notify_research(presearch, nullptr, E_TECH_LEARNED, ftc_server,
554  _("Learned %s. Scientists "
555  "do not know what to research next."),
556  qUtf8Printable(advance_name));
557  } else {
558  notify_research(presearch, nullptr, E_TECH_LEARNED, ftc_server,
559  _("Learned %s. Scientists choose to research %s."),
560  qUtf8Printable(advance_name),
561  qUtf8Printable(research_advance_name_translation(
562  presearch, next_tech)));
563  }
564  }
565 
566  if (A_UNSET != next_tech) {
567  choose_tech(presearch, next_tech);
568  } else {
569  presearch->researching = A_UNSET;
570  }
571  }
572 
573  if (!saving_bulbs && presearch->bulbs_researched > 0) {
574  presearch->bulbs_researched = 0;
575  }
576 
577  // Inform players about their new tech.
578  send_research_info(presearch, nullptr);
579 
580  if (bonus_tech_hack) {
581  Tech_type_id additional_tech;
582  char research_name[MAX_LEN_NAME * 2];
583 
584  research_pretty_name(presearch, research_name, sizeof(research_name));
585 
586  additional_tech = pick_free_tech(presearch);
587 
588  auto radv_name =
589  research_advance_name_translation(presearch, additional_tech);
590 
591  give_immediate_free_tech(presearch, additional_tech);
592  if (advance_by_number(tech_found)->bonus_message != nullptr
593  && additional_tech != A_UNSET) {
594  notify_research(presearch, nullptr, E_TECH_GAIN, ftc_server,
595  _(advance_by_number(tech_found)->bonus_message),
596  qUtf8Printable(radv_name));
597  } else if (additional_tech != A_UNSET) {
598  /* FIXME: "your" when it was just civilization of one of the players
599  * sharing the reseach. */
600  notify_research(presearch, nullptr, E_TECH_GAIN, ftc_server,
601  _("Great scientists from all the "
602  "world join your civilization: you learn "
603  "%s immediately."),
604  qUtf8Printable(radv_name));
605  }
606  // TODO: Ruleset should be able to customize this message too
607  notify_research_embassies(presearch, nullptr, E_TECH_EMBASSY, ftc_server,
608  _("%s acquire %s as a result of learning %s."),
609  research_name, qUtf8Printable(radv_name),
610  qUtf8Printable(advance_name));
611  }
612 }
613 
617 static bool lose_tech(struct research *research)
618 {
619  if (game.info.techloss_forgiveness < 0) {
620  // Tech loss disabled
621  return false;
622  }
623 
624  if (research->techs_researched == 0) {
625  // No tech to lose
627  return false;
628  }
629 
630  /* First check is not for optimization only - it protects
631  * research_total_bulbs_required() from getting called before research
632  * has even been set to value other than A_UNSET. */
633  return research->bulbs_researched < 0
636  research, research->researching, false)
637  * game.info.techloss_forgiveness / 100);
638 }
639 
650 void update_bulbs(struct player *pplayer, int bulbs, bool check_tech)
651 {
652  struct research *research = research_get(pplayer);
653 
654  if (!pplayer->is_alive) {
655  // Dead players do not produce research
656  return;
657  }
658 
659  // count our research contribution this turn
660  pplayer->server.bulbs_last_turn += bulbs;
661  research->bulbs_researched += bulbs;
663  {
664  if (j == research->researching) {
667  }
668  }
670 
671  do {
672  /* If we have a negative number of bulbs we do try to:
673  * - reduce the number of future techs;
674  * - or lose one random tech.
675  * After that the number of bulbs available is incresed based on the
676  * value of the lost tech. */
677  if (lose_tech(research)) {
678  Tech_type_id tech =
681 
682  if (tech != A_NONE) {
683  if (game.server.techloss_restore >= 0) {
686  * game.server.techloss_restore / 100);
687  } else {
689  }
691 
692  log_debug("%s: tech loss (%s)", research_rule_name(research),
693  (is_future_tech(tech)
694  ? "Future Tech"
695  : qUtf8Printable(
698  /* Make notification after losing the research, in case it is
699  * a future tech (for getting the right tech number). */
700  notify_research(research, nullptr, E_TECH_LOST, ftc_server,
701  _("Insufficient science output. We lost %s."),
702  qUtf8Printable(research_advance_name_translation(
703  research, tech)));
704  }
705  }
706 
707  // Check for finished research.
708  if (!check_tech || research->researching == A_UNSET
710  research, research->researching, false))) {
711  break;
712  }
713 
715  } while (research->researching != A_UNSET);
716 }
717 
721 static Tech_type_id
722 pick_random_tech_to_lose(const struct research *presearch)
723 {
724  bv_techs eligible_techs;
725  // A_NONE included in advance_count().
726  int eligible = advance_count() - 1;
727  int chosen;
728 
729  BV_SET_ALL(eligible_techs);
730 
732  {
733  if (research_invention_state(presearch, i) != TECH_KNOWN) {
734  if (BV_ISSET(eligible_techs, i)) {
735  eligible--;
736  BV_CLR(eligible_techs, i);
737  }
738  } else {
739  // Knowing this tech may make others ineligible
741  /* Never lose techs that are root_req for a currently known tech
742  * (including self root_req) */
743  if (root != A_NONE && BV_ISSET(eligible_techs, root)) {
744  eligible--;
745  BV_CLR(eligible_techs, root);
746  }
747  if (!game.info.tech_loss_allow_holes) {
748  /* Ruleset can prevent this kind of tech loss from opening up
749  * holes in the tech tree */
750  Tech_type_id prereq;
751  prereq = advance_required(i, AR_ONE);
752  if (prereq != A_NONE && BV_ISSET(eligible_techs, prereq)) {
753  eligible--;
754  BV_CLR(eligible_techs, prereq);
755  }
756  prereq = advance_required(i, AR_TWO);
757  if (prereq != A_NONE && BV_ISSET(eligible_techs, prereq)) {
758  eligible--;
759  BV_CLR(eligible_techs, prereq);
760  }
761  }
762  }
763  }
765 
766  if (eligible == 0) {
767  // no researched technology at all
768  return A_NONE;
769  }
770 
771  chosen = fc_rand(eligible) + 1;
772 
774  {
775  if (BV_ISSET(eligible_techs, i)) {
776  chosen--;
777  if (chosen == 0) {
778  return i;
779  }
780  }
781  }
783 
784  // should never be reached
785  fc_assert_msg(chosen == 0, "internal error (eligible=%d, chosen=%d)",
786  eligible, chosen);
787  return A_NONE;
788 }
789 
793 static void research_tech_lost(struct research *presearch, Tech_type_id tech)
794 {
795  char research_name[MAX_LEN_NAME * 2];
796  // Research members will be notified when new tech is chosen.
797 
798  research_pretty_name(presearch, research_name, sizeof(research_name));
799 
800  presearch->techs_researched--;
801  if (is_future_tech(tech)) {
802  presearch->future_tech--;
803  research_update(presearch);
804  /* Notify after decreasing the future tech counter, to get the right
805  * tech number in the message. */
807  presearch, nullptr, E_TECH_EMBASSY, ftc_server,
808  _("The %s have lost %s."), research_name,
809  qUtf8Printable(research_advance_name_translation(presearch, tech)));
810  // Inform players about their technology loss.
811  send_research_info(presearch, nullptr);
812  return;
813  }
814 
817  presearch, nullptr, E_TECH_EMBASSY, ftc_server,
818  // TRANS: technology loss
819  _("The %s have lost %s."), research_name,
820  qUtf8Printable(research_advance_name_translation(presearch, tech)));
821 
822  // Remove technology.
823  research_invention_set(presearch, tech, TECH_UNKNOWN);
824  research_update(presearch);
825  log_debug("%s lost tech id %d (%s)", research_rule_name(presearch), tech,
827 
828  // Inform players about their technology loss.
829  send_research_info(presearch, nullptr);
830 
831  research_players_iterate(presearch, pplayer)
832  {
833  // Check government.
834  if (!can_change_to_government(pplayer, government_of_player(pplayer))) {
835  // Lost the technology for the government; switch to Anarchy.
837 
839  pplayer, nullptr, E_NEW_GOVERNMENT, ftc_server,
840  _("The required technology for our government '%s' "
841  "was lost. The country has fallen into %s."),
845  send_player_info_c(pplayer, nullptr);
846  } else if (nullptr != pplayer->target_government
847  && !can_change_to_government(pplayer,
848  pplayer->target_government)) {
849  // Lost the technology for the target government; switch to Anarchy.
851 
852  notify_player(pplayer, nullptr, E_NEW_GOVERNMENT, ftc_server,
853  _("The required technology for our new government "
854  "'%s' was lost. The country has fallen into %s."),
855  government_name_translation(pplayer->target_government),
857  pplayer->target_government = pgov;
858  send_player_info_c(pplayer, pplayer->connections);
859  }
860 
861  // Check all units for valid activities.
862  unit_list_iterate(pplayer->units, punit)
863  {
865  log_debug("lost technology for activity of unit %s of %s (%d, %d)",
866  unit_name_translation(punit), player_name(pplayer),
867  TILE_XY(unit_tile(punit)));
868  set_unit_activity(punit, ACTIVITY_IDLE);
869  send_unit_info(nullptr, punit);
870  }
871  }
873 
874  // Check city production
875  city_list_iterate(pplayer->cities, pcity)
876  {
877  bool update = false;
878 
879  if (pcity->production.kind == VUT_UTYPE
880  && !can_city_build_unit_now(pcity,
881  pcity->production.value.utype)) {
882  notify_player(pplayer, city_tile(pcity), E_CITY_CANTBUILD,
883  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
894  pcity, pcity->production.value.building)) {
896  pplayer, city_tile(pcity), 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(pcity->production.value.building));
901  choose_build_target(pplayer, pcity);
902  update = true;
903  }
904 
905  if (update) {
906  city_refresh(pcity);
907  send_city_info(pplayer, pcity);
908  }
909  }
911  }
913 }
914 
918 static 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  {
925  if (research_invention_state(presearch, i) == TECH_PREREQS_KNOWN) {
926  if (fc_rand(++num_techs) == 0) {
927  tech = i;
928  }
929  }
930  }
932  return tech;
933 }
934 
938 static Tech_type_id pick_cheapest_tech(const struct research *presearch)
939 {
940  int cheapest_cost = -1;
941  int cheapest_amount = 0;
942  Tech_type_id cheapest = A_FUTURE; // If no real tech is found to be missing
943 
945  {
946  if (research_invention_state(presearch, i) == TECH_PREREQS_KNOWN) {
947  int cost = research_total_bulbs_required(presearch, i, false);
948 
949  if (cost < cheapest_cost || cheapest_cost == -1) {
950  cheapest_cost = cost;
951  cheapest_amount = 1;
952  cheapest = i;
953  } else if (cost == cheapest_cost && fc_rand(++cheapest_amount) == 0) {
954  cheapest = i;
955  }
956  }
957  }
959 
960  return cheapest;
961 }
962 
973 {
974  do {
976  } while (research->researching == A_UNSET);
977 }
978 
988 {
989  int bulbs_res = 0;
990 
991  if (is_future_tech(tech)) {
994  >= research_total_bulbs_required(research, tech, false))) {
996  }
997  } else {
998  if (research_invention_state(research, tech) != TECH_PREREQS_KNOWN) {
999  // Can't research this.
1000  return;
1001  }
1002  }
1003 
1004  if (game.server.multiresearch) {
1006  {
1007  // Save old tech research
1008  if (j == research->researching) {
1011  }
1012  /* New tech*/
1013  if (j == tech) {
1014  bulbs_res = research->inventions[j].bulbs_researched_saved;
1015  }
1016  }
1018  research->researching = tech;
1019  if (!research->got_tech_multi) {
1021  }
1023  research->got_tech_multi = false;
1025  >= research_total_bulbs_required(research, tech, false)) {
1027  }
1028  return;
1029  }
1030 
1034  // Subtract a penalty because we changed subject.
1035  if (research->bulbs_researched > 0) {
1037  ((research->bulbs_researched * game.server.techpenalty) / 100);
1039  }
1040  } else if (tech == research->researching_saved) {
1043  }
1044  research->researching = tech;
1046  >= research_total_bulbs_required(research, tech, false)) {
1048  }
1049 }
1050 
1055 void choose_tech_goal(struct research *presearch, Tech_type_id tech)
1056 {
1057  fc_assert_ret(presearch != nullptr);
1058 
1059  if (tech == presearch->tech_goal) {
1060  return;
1061  }
1062 
1063  /* It's been suggested that if the research target is empty then
1064  * choose_random_tech() should be called here. */
1065  presearch->tech_goal = tech;
1067  presearch, nullptr, E_TECH_GOAL, ftc_server,
1068  _("Technology goal is %s."),
1069  qUtf8Printable(research_advance_name_translation(presearch, tech)));
1070 }
1071 
1075 void init_tech(struct research *research, bool update)
1076 {
1077  research_invention_set(research, A_NONE, TECH_KNOWN);
1078 
1080  {
1081  research_invention_set(research, i, TECH_UNKNOWN);
1082  }
1084 
1085 #ifdef TECH_UPKEEP_DEBUGGING
1086  /* Print a list of the needed upkeep if 'i' techs are researched.
1087  * If the ruleset contains self-rooted techs this can not work! */
1088  {
1089  bool global_state[A_LAST];
1090  Tech_type_id tech = A_LAST;
1091 
1092  // Save the game research state.
1094  {
1095  global_state[i] = game.info.global_advances[i];
1096  }
1098 
1100  research_update(presearch);
1101 
1102  // Show research costs.
1104  {
1105  log_debug(
1106  "[research %d] %-25s (ID: %3d) cost: %6d - reachable: %-3s "
1107  "(now) / %-3s (ever)",
1110  research_invention_gettable(research, i, FALSE) ? "yes" : "no",
1111  research_invention_reachable(research, i) ? "yes" : "no");
1112  }
1114 
1115  // Update step for step each tech as known and print the upkeep.
1116  while (tech != A_NONE) {
1117  tech = A_NONE;
1119  {
1120  if (research_invention_state(research, i) == TECH_PREREQS_KNOWN) {
1121  // Found a tech which can be researched.
1122  tech = i;
1123  break;
1124  }
1125  }
1127 
1128  if (tech != A_NONE) {
1129  research->inventions[tech].state = TECH_KNOWN;
1131 
1132  // This will change the game state!
1134 
1136  {
1137  log_debug("[player %d] researched: %-25s (ID: %4d) techs: %3d "
1138  "upkeep: %4d",
1140  advance_rule_name(advance_by_number(tech)), tech,
1142  }
1144  }
1145  }
1146 
1147  // Reset the changes done.
1149  {
1150  research_invention_set(research, i, TECH_UNKNOWN);
1151  game.info.global_advances[i] = global_state[i];
1152  }
1154  }
1155 #endif // TECH_UPKEEP_DEBUGGING
1156 
1158 
1159  if (update) {
1160  Tech_type_id next_tech;
1161 
1162  // Mark the reachable techs
1164 
1166  if (A_UNSET != next_tech) {
1167  choose_tech(research, next_tech);
1168  } else {
1170  }
1171  }
1172 }
1173 
1179 void give_initial_techs(struct research *presearch, int num_random_techs)
1180 {
1181  int i;
1182 
1183  // Global techs.
1184  for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
1185  if (game.rgame.global_init_techs[i] == A_LAST) {
1186  break;
1187  }
1188  // Maybe the player already got this tech by an other way (e.g. team).
1190  != TECH_KNOWN) {
1191  found_new_tech(presearch, game.rgame.global_init_techs[i], false,
1192  true);
1193  }
1194  }
1195 
1196  // Nation techs.
1197  research_players_iterate(presearch, pplayer)
1198  {
1199  const struct nation_type *pnation = nation_of_player(pplayer);
1200 
1201  for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
1202  if (pnation->init_techs[i] == A_LAST) {
1203  break;
1204  }
1205  // Maybe the player already got this tech by an other way.
1206  if (research_invention_state(presearch, pnation->init_techs[i])
1207  != TECH_KNOWN) {
1208  found_new_tech(presearch, pnation->init_techs[i], false, true);
1209  }
1210  }
1211  }
1213 
1214  // Random free techs (N.B.: freecost penalty not applied).
1215  for (i = 0; i < num_random_techs; i++) {
1216  found_new_tech(presearch, pick_random_tech(presearch), false, true);
1217  }
1218 }
1219 
1227 Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim,
1228  Tech_type_id preferred)
1229 {
1230  struct research *presearch, *vresearch;
1231  Tech_type_id stolen_tech = A_NONE;
1232  QString advance_name;
1233  char research_name[MAX_LEN_NAME * 2];
1234 
1235  if (get_player_bonus(victim, EFT_NOT_TECH_SOURCE) > 0) {
1236  return A_NONE;
1237  }
1238 
1239  presearch = research_get(pplayer);
1240  vresearch = research_get(victim);
1241 
1242  if (preferred == A_UNSET) {
1243  int j = 0;
1244 
1246  {
1247  if (research_invention_gettable(presearch, i,
1248  game.info.tech_steal_allow_holes)
1249  && research_invention_state(presearch, i) != TECH_KNOWN
1250  && research_invention_state(vresearch, i) == TECH_KNOWN) {
1251  j++;
1252  }
1253  }
1255 
1256  if (j == 0) {
1257  // we've moved on to future tech
1258  if (vresearch->future_tech > presearch->future_tech) {
1259  stolen_tech = A_FUTURE;
1260  } else {
1261  return A_NONE;
1262  }
1263  } else {
1264  // pick random tech
1265  j = fc_rand(j) + 1;
1266  stolen_tech = A_NONE; // avoid compiler warning
1268  {
1269  if (research_invention_gettable(presearch, i,
1270  game.info.tech_steal_allow_holes)
1271  && research_invention_state(presearch, i) != TECH_KNOWN
1272  && research_invention_state(vresearch, i) == TECH_KNOWN) {
1273  j--;
1274  }
1275  if (j == 0) {
1276  stolen_tech = i;
1277  break;
1278  }
1279  }
1281  fc_assert(stolen_tech != A_NONE);
1282  }
1283  } else { // preferred != A_UNSET
1284  if (!is_future_tech(preferred)) {
1285  fc_assert(nullptr != valid_advance_by_number(preferred));
1286  fc_assert(TECH_KNOWN
1287  == research_invention_state(vresearch, preferred));
1288  }
1289  stolen_tech = preferred;
1290  }
1291 
1292  advance_name = research_advance_name_translation(presearch, stolen_tech);
1293  research_pretty_name(presearch, research_name, sizeof(research_name));
1294  notify_player(pplayer, nullptr, E_MY_DIPLOMAT_THEFT, ftc_server,
1295  _("You steal %s from the %s."), qUtf8Printable(advance_name),
1296  nation_plural_for_player(victim));
1297  notify_research(presearch, pplayer, E_TECH_GAIN, ftc_server,
1298  _("The %s stole %s from the %s and shared it with you."),
1299  nation_plural_for_player(pplayer),
1300  qUtf8Printable(advance_name),
1301  nation_plural_for_player(victim));
1302 
1303  notify_player(victim, nullptr, E_ENEMY_DIPLOMAT_THEFT, ftc_server,
1304  _("The %s stole %s from you!"),
1305  nation_plural_for_player(pplayer),
1306  qUtf8Printable(advance_name));
1307 
1308  notify_research_embassies(presearch, victim, E_TECH_EMBASSY, ftc_server,
1309  _("The %s have stolen %s from the %s."),
1310  research_name, qUtf8Printable(advance_name),
1311  nation_plural_for_player(victim));
1312 
1313  if (tech_transfer(pplayer, victim, stolen_tech)) {
1314  research_apply_penalty(presearch, stolen_tech, game.server.conquercost);
1315  found_new_tech(presearch, stolen_tech, false, true);
1316  script_tech_learned(presearch, pplayer, advance_by_number(stolen_tech),
1317  "stolen");
1318  return stolen_tech;
1319  }
1320 
1321  return A_NONE;
1322 }
1323 
1331 void handle_player_research(struct player *pplayer, int tech)
1332 {
1333  struct research *research = research_get(pplayer);
1334 
1335  if (tech != A_FUTURE && !valid_advance_by_number(tech)) {
1336  return;
1337  }
1338 
1339  if (tech != A_FUTURE
1340  && research_invention_state(research, tech) != TECH_PREREQS_KNOWN) {
1341  return;
1342  }
1343 
1344  choose_tech(research, tech);
1345 
1346  // Notify players sharing the same research.
1347  send_research_info(research, nullptr);
1348 }
1349 
1354 void handle_player_tech_goal(struct player *pplayer, int tech_goal)
1355 {
1356  struct research *research = research_get(pplayer);
1357 
1358  /* Set the tech goal to a defined state if it is
1359  * - not a future tech and not a valid goal
1360  * - not a future tech and not a valid advance
1361  * - not defined
1362  * - known (i.e. due to EFT_GIVE_IMM_TECH). */
1363  if ((tech_goal != A_FUTURE
1366  || (tech_goal == A_NONE)
1367  || (TECH_KNOWN == research_invention_state(research, tech_goal))) {
1368  tech_goal = A_UNSET;
1369  }
1370 
1372 
1373  // Notify players sharing the same research.
1374  send_research_info(research, nullptr);
1375 }
1376 
1381 {
1382  Tech_type_id tech;
1383 
1384  if (game.info.free_tech_method == FTM_CHEAPEST) {
1385  tech = pick_cheapest_tech(presearch);
1386  } else if (presearch->researching == A_UNSET
1387  || game.info.free_tech_method == FTM_RANDOM) {
1388  tech = pick_random_tech(presearch);
1389  } else {
1390  tech = presearch->researching;
1391  }
1392  return tech;
1393 }
1394 
1399 void give_immediate_free_tech(struct research *presearch, Tech_type_id tech)
1400 {
1401  research_apply_penalty(presearch, tech, game.server.freecost);
1402  found_new_tech(presearch, tech, false, true);
1403 }
1404 
1408 static void forget_tech_transfered(struct player *pplayer, Tech_type_id tech)
1409 {
1410  struct research *presearch = research_get(pplayer);
1411 
1412  research_tech_lost(presearch, tech);
1413  /* Make notification after losing the research, in case it is a future
1414  * tech (for getting the right tech number). */
1415  notify_player(
1416  pplayer, nullptr, E_TECH_LOST, ftc_server,
1417  _("Too bad! You made a mistake transferring the tech %s and "
1418  "lost it."),
1419  qUtf8Printable(research_advance_name_translation(presearch, tech)));
1421  presearch, pplayer, E_TECH_LOST, ftc_server,
1422  _("Too bad! The %s made a mistake transferring the tech "
1423  "%s and lost it."),
1424  nation_plural_for_player(pplayer),
1425  qUtf8Printable(research_advance_name_translation(presearch, tech)));
1426 }
1427 
1432 bool tech_transfer(struct player *plr_recv, struct player *plr_donor,
1433  Tech_type_id tech)
1434 {
1435  if (game.server.techlost_donor > 0) {
1436  struct research *donor_research = research_get(plr_donor);
1437  bool donor_can_lose = true;
1438 
1440  {
1441  /* Never let donor lose tech if it's root_req for some other known
1442  * tech */
1443  if (research_invention_state(donor_research, i) == TECH_KNOWN
1444  && (advance_required(i, AR_ROOT) == tech
1445  || (!game.info.tech_trade_loss_allow_holes
1446  && (advance_required(i, AR_ONE) == tech
1447  || advance_required(i, AR_TWO) == tech)))) {
1448  donor_can_lose = false;
1449  break;
1450  }
1451  }
1453  if (donor_can_lose && fc_rand(100) < game.server.techlost_donor) {
1454  forget_tech_transfered(plr_donor, tech);
1455  }
1456  }
1457 
1458  if (fc_rand(100) < game.server.techlost_recv) {
1459  forget_tech_transfered(plr_recv, tech);
1460  return false;
1461  }
1462 
1463  return true;
1464 }
#define BV_SET_ALL(bv)
Definition: bitvector.h:66
bool BV_ISSET(const BV &bv, int bit)
Definition: bitvector.h:37
#define BV_CLR(bv, bit)
Definition: bitvector.h:49
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
Definition: city.cpp:1083
struct tile * city_tile(const struct city *pcity)
Return the tile location of the city.
Definition: city.cpp:1095
bool can_city_build_improvement_now(const struct city *pcity, const struct impr_type *pimprove)
Return whether given city can build given building; returns FALSE if the building is obsolete.
Definition: city.cpp:815
bool can_city_build_unit_now(const struct city *pcity, const struct unit_type *punittype)
Return whether given city can build given unit; returns FALSE if unit is obsolete.
Definition: city.cpp:894
#define city_list_iterate(citylist, pcity)
Definition: city.h:482
#define city_list_iterate_end
Definition: city.h:484
void send_city_info(struct player *dest, struct city *pcity)
A wrapper, accessing either broadcast_city_info() (dest == nullptr), or a convenience case of send_ci...
Definition: citytools.cpp:2295
void city_refresh_vision(struct city *pcity)
Refresh the city's vision.
Definition: citytools.cpp:3261
void remove_obsolete_buildings(struct player *pplayer)
Sell obsolete buildings from all cities of the player.
Definition: cityturn.cpp:263
void choose_build_target(struct player *pplayer, struct city *pcity)
Assuming we just finished building something, find something new to build.
Definition: cityturn.cpp:2089
bool city_refresh(struct city *pcity)
Updates unit upkeeps and city internal cached data.
Definition: cityturn.cpp:147
struct player * conn_get_player(const struct connection *pconn)
Returns the player that this connection is attached to, or nullptr.
Definition: connection.cpp:693
#define conn_list_iterate(connlist, pconn)
Definition: connection.h:99
#define conn_list_iterate_end
Definition: connection.h:101
struct effect_list * effects[EFT_COUNT]
Definition: effects.cpp:102
int get_player_bonus_effects(struct effect_list *plist, const struct player *pplayer, enum effect_type effect_type)
Returns the effect sources of this type currently active at the player.
Definition: effects.cpp:889
int get_player_intel_bonus(const struct player *pplayer, const struct player *pother, enum national_intelligence nintel, enum effect_type effect_type)
Gets the player effect bonus of a national intelligence.
Definition: effects.cpp:779
QString get_effect_list_req_text(const struct effect_list *plist)
Make user-friendly text for an effect list.
Definition: effects.cpp:1040
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Returns the effect bonus for a player.
Definition: effects.cpp:673
int Tech_type_id
Definition: fc_types.h:294
#define MAX_NUM_PLAYER_SLOTS
Definition: fc_types.h:24
#define MAX_LEN_NAME
Definition: fc_types.h:61
#define MAX_NUM_TECH_LIST
Definition: fc_types.h:36
@ O_SCIENCE
Definition: fc_types.h:90
#define Q_(String)
Definition: fcintl.h:53
#define _(String)
Definition: fcintl.h:50
const struct ft_color ftc_server
const char * city_link(const struct city *pcity)
Get a text link to a city.
struct civ_game game
Definition: game.cpp:47
struct world wld
Definition: game.cpp:48
void send_game_info(struct conn_list *dest)
Send game_info packet; some server options and various stuff...
Definition: gamehand.cpp:905
struct government * government_of_player(const struct player *pplayer)
Return the government of a player.
Definition: government.cpp:107
Government_type_id government_count()
Return the number of governments.
Definition: government.cpp:64
std::vector< government > governments
Definition: government.cpp:28
bool can_change_to_government(struct player *pplayer, const struct government *gov)
Can change to government if appropriate tech exists, and one of:
Definition: government.cpp:159
Government_type_id government_number(const struct government *pgovern)
Return the government index.
Definition: government.cpp:84
Government_type_id government_index(const struct government *pgovern)
Return the government index.
Definition: government.cpp:75
const char * government_name_translation(const struct government *pgovern)
Return the (translated) name of the given government.
Definition: government.cpp:136
struct city * city_from_great_wonder(const struct impr_type *pimprove)
Get the world city with this great wonder.
bool is_great_wonder(const struct impr_type *pimprove)
Is this building a great wonder?
const char * improvement_name_translation(const struct impr_type *pimprove)
Return the (translated) name of the given improvement.
#define improvement_iterate_end
Definition: improvement.h:199
#define improvement_iterate(_p)
Definition: improvement.h:193
#define fc_assert_msg(condition, message,...)
Definition: log.h:96
#define fc_assert_ret(condition)
Definition: log.h:112
#define fc_assert(condition)
Definition: log.h:89
#define log_debug(message,...)
Definition: log.h:65
#define whole_map_iterate(_map, _tile)
Definition: map.h:473
#define whole_map_iterate_end
Definition: map.h:480
void send_tile_info(struct conn_list *dest, struct tile *ptile, bool send_unknown)
Send tile information to all the clients in dest which know and see the tile.
Definition: maphand.cpp:485
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Give pplayer the correct knowledge about tile; return TRUE iff knowledge changed.
Definition: maphand.cpp:1357
void upgrade_all_city_extras(struct player *pplayer, bool discovery)
To be called when a player gains some better extra building tech for the first time.
Definition: maphand.cpp:251
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Returns whether the layer 'vlayer' of the tile 'ptile' is known and seen by the player 'pplayer'.
Definition: maphand.cpp:894
const char * nation_plural_for_player(const struct player *pplayer)
Return the (translated) plural noun of the given nation of a player.
Definition: nation.cpp:155
struct nation_type * nation_of_player(const struct player *pplayer)
Return the nation of a player.
Definition: nation.cpp:419
void notify_research(const struct research *presearch, const struct player *exclude, enum event_type event, const struct ft_color color, const char *format,...)
Sends a message to all players that share research.
Definition: notify.cpp:386
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Similar to notify_conn_packet (see also), but takes player as "destination".
Definition: notify.cpp:284
void notify_research_embassies(const struct research *presearch, const struct player *exclude, enum event_type event, const struct ft_color color, const char *format,...)
Sends a message to all players that have embassies with someone who shares research.
Definition: notify.cpp:426
bool player_slots_initialised()
Return whether player slots are already initialized.
Definition: player.cpp:341
int player_index(const struct player *pplayer)
Return the player index.
Definition: player.cpp:748
const char * player_name(const struct player *pplayer)
Return the leader name of the player.
Definition: player.cpp:816
#define players_iterate_end
Definition: player.h:520
#define players_iterate(_pplayer)
Definition: player.h:514
#define player_list_iterate(playerlist, pplayer)
Definition: player.h:541
#define is_ai(plr)
Definition: player.h:227
#define player_list_iterate_end
Definition: player.h:543
void send_player_all_c(struct player *src, struct conn_list *dest)
Send all information about a player (player_info and all player_diplstates) to the given connections.
Definition: plrhand.cpp:1031
void send_player_info_c(struct player *src, struct conn_list *dest)
Send information about player slot 'src', or all valid (i.e.
Definition: plrhand.cpp:1048
void handle_player_change_government(struct player *pplayer, Government_type_id government)
Called by the client or AI to change government.
Definition: plrhand.cpp:427
#define shuffled_players_iterate_end
Definition: plrhand.h:93
#define shuffled_players_iterate(NAME_pplayer)
Definition: plrhand.h:83
#define fc_rand(_size)
Definition: rand.h:16
#define requirement_vector_iterate_end
Definition: requirements.h:80
#define requirement_vector_iterate(req_vec, preq)
Definition: requirements.h:78
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Returns TRUE iff the given tech is ever reachable via research by the players sharing the research by...
Definition: research.cpp:659
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Set research knowledge about tech to given state.
Definition: research.cpp:627
int player_tech_upkeep(const struct player *pplayer)
Calculate the bulb upkeep needed for all techs of a player.
Definition: research.cpp:1037
struct research * research_get(const struct player *pplayer)
Returns the research structure associated with the player.
Definition: research.cpp:110
QString research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Store the translated name of the given tech (including A_FUTURE) in 'buf'.
Definition: research.cpp:257
QString research_advance_rule_name(const struct research *presearch, Tech_type_id tech)
Store the rule name of the given tech (including A_FUTURE) in 'buf'.
Definition: research.cpp:233
int research_number(const research *presearch)
Returns the index of the research in the array.
Definition: research.cpp:91
int research_total_bulbs_required(const struct research *presearch, Tech_type_id tech, bool loss_value)
Function to determine cost for technology.
Definition: research.cpp:855
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Returns state of the tech for current research.
Definition: research.cpp:609
Tech_type_id research_goal_step(const struct research *presearch, Tech_type_id goal)
Return the next tech we should research to advance towards our goal.
Definition: research.cpp:714
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Returns TRUE iff the given tech can be given to the players sharing the research immediately.
Definition: research.cpp:686
bool research_is_valid(const struct research &presearch)
Checks whether the research object is valid in the current game.
Definition: research.cpp:125
void research_update(struct research *presearch)
Mark as TECH_PREREQS_KNOWN each tech which is available, not known and which has all requirements ful...
Definition: research.cpp:486
const char * research_rule_name(const struct research *presearch)
Returns the name of the research owner: a player name or a team name.
Definition: research.cpp:137
int research_pretty_name(const struct research *presearch, char *buf, size_t buf_len)
Set in 'buf' the name of the research owner.
Definition: research.cpp:163
#define research_players_iterate(_presearch, _pplayer)
Definition: research.h:151
#define research_players_iterate_end
Definition: research.h:155
std::vector< research > research_array
void script_server_signal_emit(const char *signal_name,...)
Invoke all the callback functions attached to a given signal.
Definition: tech.h:113
Definition: city.h:291
struct civ_game::@28::@32 server
struct conn_list * est_connections
Definition: game.h:88
int global_init_techs[MAX_NUM_TECH_LIST]
Definition: game.h:98
struct packet_game_info info
Definition: game.h:80
struct civ_game::@27 rgame
struct government * government_during_revolution
Definition: game.h:85
int init_techs[MAX_NUM_TECH_LIST]
Definition: nation.h:101
Definition: player.h:231
struct player::@65::@67 server
struct team * team
Definition: player.h:243
bool is_alive
Definition: player.h:250
enum tech_state state
Definition: research.h:66
Tech_type_id researching
Definition: research.h:45
int future_tech
Definition: research.h:35
Tech_type_id tech_goal
Definition: research.h:78
int bulbs_researching_saved
Definition: research.h:56
bool got_tech_multi
Definition: research.h:62
Tech_type_id researching_saved
Definition: research.h:55
bool got_tech
Definition: research.h:60
int techs_researched
Definition: research.h:35
struct research::research_invention inventions[A_LAST]
int bulbs_researched
Definition: research.h:46
Definition: team.cpp:35
struct civ_map map
Definition: world_object.h:21
const struct player_list * team_members(const struct team *pteam)
Returns the member list of the team.
Definition: team.cpp:427
bool is_future_tech(Tech_type_id tech)
Is the given tech a future tech.
Definition: tech.cpp:268
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Return TRUE if the tech has this flag otherwise FALSE.
Definition: tech.cpp:198
const char * advance_rule_name(const struct advance *padvance)
Return the (untranslated) rule name of the advance/technology.
Definition: tech.cpp:283
struct advance * advance_by_number(const Tech_type_id atype)
Return the advance for the given advance index.
Definition: tech.cpp:94
Tech_type_id advance_required(const Tech_type_id tech, enum tech_req require)
Accessor for requirements.
Definition: tech.cpp:108
struct advance * valid_advance_by_number(const Tech_type_id id)
Returns pointer when the advance "exists" in this game, returns nullptr otherwise.
Definition: tech.cpp:154
Tech_type_id advance_count()
Return the number of advances/technologies.
Definition: tech.cpp:68
#define A_FUTURE
Definition: tech.h:39
#define advance_index_iterate_end
Definition: tech.h:226
@ AR_TWO
Definition: tech.h:104
@ AR_ROOT
Definition: tech.h:104
@ AR_ONE
Definition: tech.h:104
#define A_FIRST
Definition: tech.h:37
#define A_NONE
Definition: tech.h:36
#define A_UNSET
Definition: tech.h:41
#define A_UNKNOWN
Definition: tech.h:42
#define A_LAST
Definition: tech.h:38
#define advance_index_iterate(_start, _index)
Definition: tech.h:221
static Tech_type_id pick_cheapest_tech(const struct research *presearch)
Returns cheapest researchable tech, random among equal cost ones.
Definition: techtools.cpp:938
void handle_player_tech_goal(struct player *pplayer, int tech_goal)
Handle incoming player_tech_goal packet Called from the network or AI code to set the player's tech g...
Definition: techtools.cpp:1354
void init_tech(struct research *research, bool update)
Initializes tech data for the research.
Definition: techtools.cpp:1075
void found_new_tech(struct research *presearch, Tech_type_id tech_found, bool was_discovery, bool saving_bulbs)
Players sharing the research have got a new technology (from somewhere).
Definition: techtools.cpp:341
static bool lose_tech(struct research *research)
Is player about to lose tech?
Definition: techtools.cpp:617
void choose_tech_goal(struct research *presearch, Tech_type_id tech)
Called when a player chooses the tech goal he wants to research (or when the server chooses it for hi...
Definition: techtools.cpp:1055
static void forget_tech_transfered(struct player *pplayer, Tech_type_id tech)
Let the player forget one tech.
Definition: techtools.cpp:1408
void research_apply_penalty(struct research *presearch, Tech_type_id tech, int penalty_percent)
Apply a penalty to the research.
Definition: techtools.cpp:59
static void tech_researched(struct research *research)
Players have researched a new technology.
Definition: techtools.cpp:102
void choose_tech(struct research *research, Tech_type_id tech)
Called when a player chooses the tech he wants to research (or when the server chooses it for him aut...
Definition: techtools.cpp:987
static Tech_type_id pick_random_tech_to_lose(const struct research *presearch)
Choose a random tech for player to lose.
Definition: techtools.cpp:722
void do_tech_parasite_effect(struct player *pplayer)
Give technologies to players with EFT_TECH_PARASITE (traditionally from the Great Library).
Definition: techtools.cpp:139
static void package_research_info(struct packet_research_info *packet, const struct research *presearch)
Fill packet fields.
Definition: techtools.cpp:233
Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim, Tech_type_id preferred)
If victim has a tech which pplayer doesn't have, pplayer will get it.
Definition: techtools.cpp:1227
void handle_player_research(struct player *pplayer, int tech)
Handle incoming research packet.
Definition: techtools.cpp:1331
Tech_type_id pick_free_tech(struct research *presearch)
Choose a free tech.
Definition: techtools.cpp:1380
void give_immediate_free_tech(struct research *presearch, Tech_type_id tech)
Give an immediate free tech (probably chosen with pick_free_tech()).
Definition: techtools.cpp:1399
void send_research_info(const struct research *presearch, const struct conn_list *dest)
Send research info for 'presearch' to 'dest'.
Definition: techtools.cpp:273
void choose_random_tech(struct research *research)
Finds and chooses (sets) a random research target from among all those available until presearch->res...
Definition: techtools.cpp:972
void update_bulbs(struct player *pplayer, int bulbs, bool check_tech)
Adds the given number of bulbs into the player's tech and (if necessary and 'check_tech' is TRUE) com...
Definition: techtools.cpp:650
static void research_tech_lost(struct research *presearch, Tech_type_id tech)
Remove one tech from the research.
Definition: techtools.cpp:793
void script_tech_learned(struct research *presearch, struct player *originating_plr, struct advance *tech, const char *reason)
Emit script signal(s) for player/team learning new tech.
Definition: techtools.cpp:77
void give_initial_techs(struct research *presearch, int num_random_techs)
Gives global (read from the game ruleset file) and nation (read from the nation ruleset files) initia...
Definition: techtools.cpp:1179
bool tech_transfer(struct player *plr_recv, struct player *plr_donor, Tech_type_id tech)
Check if the tech is lost by the donor or receiver.
Definition: techtools.cpp:1432
static Tech_type_id pick_random_tech(const struct research *presearch)
Returns random researchable tech or A_FUTURE.
Definition: techtools.cpp:918
#define TILE_XY(ptile)
Definition: tile.h:36
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Assign a new untargeted task to a unit.
Definition: unit.cpp:1011
bool can_unit_continue_current_activity(struct unit *punit)
Check if the unit's current activity is actually legal.
Definition: unit.cpp:780
#define unit_tile(_pu)
Definition: unit.h:371
#define unit_list_iterate(unitlist, punit)
Definition: unitlist.h:25
#define unit_list_iterate_end
Definition: unitlist.h:27
void send_unit_info(struct conn_list *dest, struct unit *punit)
Send the unit to the players who need the info.
Definition: unittools.cpp:2808
void unit_list_refresh_vision(struct unit_list *punitlist)
Refresh the vision of all units in the list - see unit_refresh_vision.
Definition: unittools.cpp:4834
const char * utype_name_translation(const struct unit_type *punittype)
Return the (translated) name of the unit type.
Definition: unittype.cpp:1256
const char * unit_name_translation(const struct unit *punit)
Return the (translated) name of the unit.
Definition: unittype.cpp:1265