Complete.Org: Mailing Lists: Archives: freeciv-dev: June 2005:
[Freeciv-Dev] (PR#13314) new source file: research.c
Home

[Freeciv-Dev] (PR#13314) new source file: research.c

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#13314) new source file: research.c
From: "Mateusz Stefek" <mstefek@xxxxxxxxx>
Date: Thu, 23 Jun 2005 01:52:28 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=13314 >

The attached patch moves research related stuff from plrhand.c into a
new file research.c

--
mateusz
? core.22373
? core.23940
? core.26863
? core.26869
? core.26873
? shared.c
? data/ft
? po/pl.back
? po/pl.po2
? server/research.c
? server/research.h
Index: ai/aitech.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitech.c,v
retrieving revision 1.59
diff -u -r1.59 aitech.c
--- ai/aitech.c 21 Jun 2005 16:21:00 -0000      1.59
+++ ai/aitech.c 23 Jun 2005 08:40:47 -0000
@@ -24,6 +24,7 @@
 #include "tech.h"
 
 #include "plrhand.h"
+#include "research.h"
 
 #include "advmilitary.h"
 #include "ailog.h"
Index: server/Makefile.am
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/Makefile.am,v
retrieving revision 1.42
diff -u -r1.42 Makefile.am
--- server/Makefile.am  1 May 2005 12:01:15 -0000       1.42
+++ server/Makefile.am  23 Jun 2005 08:40:54 -0000
@@ -54,6 +54,8 @@
                plrhand.h       \
                report.c        \
                report.h        \
+               research.c      \
+               research.h      \
                ruleset.c       \
                ruleset.h       \
                sanitycheck.c   \
Index: server/barbarian.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/barbarian.c,v
retrieving revision 1.92
diff -u -r1.92 barbarian.c
--- server/barbarian.c  24 May 2005 16:45:39 -0000      1.92
+++ server/barbarian.c  23 Jun 2005 08:40:54 -0000
@@ -43,6 +43,7 @@
 #include "gamelog.h"
 #include "maphand.h"
 #include "plrhand.h"
+#include "research.h"
 #include "srv_main.h"
 #include "stdinhand.h"
 #include "unithand.h"
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.328
diff -u -r1.328 citytools.c
--- server/citytools.c  14 May 2005 15:34:41 -0000      1.328
+++ server/citytools.c  23 Jun 2005 08:41:03 -0000
@@ -43,6 +43,7 @@
 #include "gamelog.h"
 #include "maphand.h"
 #include "plrhand.h"
+#include "research.h"
 #include "sanitycheck.h"
 #include "sernet.h"
 #include "settlers.h"
Index: server/cityturn.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityturn.c,v
retrieving revision 1.319
diff -u -r1.319 cityturn.c
--- server/cityturn.c   21 Jun 2005 16:21:02 -0000      1.319
+++ server/cityturn.c   23 Jun 2005 08:41:07 -0000
@@ -41,6 +41,7 @@
 #include "gamelog.h"
 #include "maphand.h"
 #include "plrhand.h"
+#include "research.h"
 #include "sanitycheck.h"
 #include "settlers.h"
 #include "spacerace.h"
Index: server/diplhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/diplhand.c,v
retrieving revision 1.94
diff -u -r1.94 diplhand.c
--- server/diplhand.c   11 May 2005 14:57:10 -0000      1.94
+++ server/diplhand.c   23 Jun 2005 08:41:09 -0000
@@ -36,6 +36,7 @@
 #include "gamelog.h"
 #include "maphand.h"
 #include "plrhand.h"
+#include "research.h"
 #include "settlers.h"
 #include "unittools.h"
 
Index: server/diplomats.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/diplomats.c,v
retrieving revision 1.79
diff -u -r1.79 diplomats.c
--- server/diplomats.c  21 Jun 2005 16:21:02 -0000      1.79
+++ server/diplomats.c  23 Jun 2005 08:41:12 -0000
@@ -31,6 +31,7 @@
 #include "gamelog.h"
 #include "gotohand.h"
 #include "plrhand.h"
+#include "research.h"
 #include "unithand.h"
 #include "unittools.h"
 
Index: server/plrhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v
retrieving revision 1.391
diff -u -r1.391 plrhand.c
--- server/plrhand.c    23 Jun 2005 08:01:09 -0000      1.391
+++ server/plrhand.c    23 Jun 2005 08:41:18 -0000
@@ -41,6 +41,7 @@
 #include "gamehand.h"
 #include "gamelog.h"
 #include "maphand.h"
+#include "research.h"
 #include "sernet.h"
 #include "settlers.h"
 #include "srv_main.h"
@@ -53,7 +54,6 @@
 #include "advmilitary.h"
 #include "aidata.h"
 #include "aihand.h"
-#include "aitech.h"
 
 #include "plrhand.h"
 
@@ -65,8 +65,6 @@
                                 struct player *receiver,
                                 enum plr_info_level min_info_level);
 static Nation_type_id pick_available_nation(Nation_type_id *choices);
-static void tech_researched(struct player* plr);
-static bool choose_goal_tech(struct player *plr);
 static enum plr_info_level player_info_level(struct player *plr,
                                             struct player *receiver);
 
@@ -135,63 +133,6 @@
   send_global_city_turn_notifications(dest);
 }
 
-/**************************************************************************
-  Give technologies to players with EFT_TECH_PARASITE (traditionally from
-  the Great Library).
-**************************************************************************/
-void do_tech_parasite_effect(struct player *pplayer)
-{
-  int mod;
-  struct effect_list *plist = effect_list_new();
-
-  /* Note that two EFT_TECH_PARASITE effects will combine into a single,
-   * much worse effect. */
-  if ((mod = get_player_bonus_effects(plist, pplayer,
-                                     EFT_TECH_PARASITE)) > 0) {
-    char buf[512];
-
-    buf[0] = '\0';
-    effect_list_iterate(plist, peffect) {
-      if (buf[0] != '\0') {
-       sz_strlcat(buf, ", ");
-      }
-      get_effect_req_text(peffect, buf, sizeof(buf));
-    } effect_list_iterate_end;
-
-    tech_type_iterate(i) {
-      if (get_invention(pplayer, i) != TECH_KNOWN
-         && tech_is_available(pplayer, i)) {
-       int num_players = 0;
-       players_iterate(aplayer) {
-         if (get_invention(aplayer, i) == TECH_KNOWN) {
-           num_players++;
-         }
-       } players_iterate_end;
-       if (num_players >= mod) {
-         notify_player_ex(pplayer, NULL, E_TECH_GAIN,
-                          _("%s acquired from %s!"),
-                          get_tech_name(pplayer, i), buf);
-         script_signal_emit("tech_researched", 3,
-                            API_TYPE_TECH_TYPE, &advances[i],
-                            API_TYPE_PLAYER, pplayer,
-                            API_TYPE_STRING, "stolen");
-          gamelog(GAMELOG_TECH, pplayer, NULL, i, "steal");
-         notify_embassies(pplayer, NULL,
-                          _("The %s have acquired %s from %s."),
-                          get_nation_name_plural(pplayer->nation),
-                          get_tech_name(pplayer, i), buf);
-
-         do_free_cost(pplayer);
-         found_new_tech(pplayer, i, FALSE, TRUE, A_NONE);
-         break;
-       }
-      }
-    } tech_type_iterate_end;
-  }
-  effect_list_unlink_all(plist);
-  effect_list_free(plist);
-}
-
 /****************************************************************************
   Check all players to see if they are dying.  Kill them if so.
 
@@ -281,526 +222,6 @@
 }
 
 /**************************************************************************
-  Player has a new technology (from somewhere). was_discovery is passed 
-  on to upgrade_city_rails. Logging & notification is not done here as 
-  it depends on how the tech came. If next_tech is other than A_NONE, this 
-  is the next tech to research.
-**************************************************************************/
-void found_new_tech(struct player *plr, int tech_found, bool was_discovery,
-                   bool saving_bulbs, int next_tech)
-{
-  bool bonus_tech_hack = FALSE;
-  bool was_first = FALSE;
-  bool had_embassy[MAX_NUM_PLAYERS];
-  struct city *pcity;
-  bool can_switch[game.control.government_count];
-  struct player_research* research = get_player_research(plr);
-
-  players_iterate(aplr) {
-    had_embassy[aplr->player_no]
-      = (get_player_bonus(aplr, EFT_HAVE_EMBASSIES) > 0);
-  } players_iterate_end;
-
-  /* HACK: A_FUTURE doesn't "exist" and is thus not "available".  This may
-   * or may not be the correct thing to do.  For these sanity checks we
-   * just special-case it. */
-  assert((tech_exists(tech_found)
-         && get_invention(plr, tech_found) != TECH_KNOWN)
-        || tech_found == A_FUTURE);
-  assert(tech_is_available(plr, tech_found) || tech_found == A_FUTURE);
-
-  research->got_tech = TRUE;
-  research->changed_from = -1;
-  research->techs_researched++;
-  was_first = (!game.info.global_advances[tech_found]);
-
-  if (was_first) {
-    /* We used to have a gamelog() for first-researched, but not anymore. */
-
-    /* Alert the owners of any wonders that have been made obsolete */
-    impr_type_iterate(id) {
-      if (is_great_wonder(id) && great_wonder_was_built(id) &&
-         improvement_types[id].obsolete_by == tech_found &&
-         (pcity = find_city_from_great_wonder(id))) {
-       notify_player_ex(city_owner(pcity), NULL, E_WONDER_OBSOLETE,
-                        _("Discovery of %s OBSOLETES %s in %s!"), 
-                        get_tech_name(city_owner(pcity), tech_found),
-                        get_improvement_name(id),
-                        pcity->name);
-      }
-    } impr_type_iterate_end;
-  }
-
-  government_iterate(gov) {
-    /* We do it this way so all requirements are checked, including
-     * statue-of-liberty effects. */
-    can_switch[gov->index] = can_change_to_government(plr, gov->index);
-  } government_iterate_end;
-
-  if (tech_flag(tech_found, TF_BONUS_TECH) && was_first) {
-    bonus_tech_hack = TRUE;
-  }
-
-  set_invention(plr, tech_found, TECH_KNOWN);
-  update_research(plr);
-  remove_obsolete_buildings(plr);
-
-  if (tech_flag(tech_found, TF_RAILROAD)) {
-    players_iterate(aplayer) {
-      if (players_on_same_team(aplayer, plr)) {
-        upgrade_city_rails(plr, was_discovery);
-      }
-    } players_iterate_end;
-  }
-
-  government_iterate(gov) {
-    if (!can_switch[gov->index]
-       && can_change_to_government(plr, gov->index)) {
-      notify_player_ex(plr, NULL, E_NEW_GOVERNMENT,
-                      _("Discovery of %s makes the government form %s"
-                        " available. You may want to start a revolution."),
-                      get_tech_name(plr, tech_found), gov->name);
-    }
-  } government_iterate_end;
-
-  /* enhance vision of units inside a fortress */
-  if (tech_flag(tech_found, TF_WATCHTOWER)) {
-    unit_list_iterate(plr->units, punit) {
-      if (tile_has_special(punit->tile, S_FORTRESS)
-         && is_ground_unit(punit)) {
-       unfog_area(plr, punit->tile, get_watchtower_vision(punit));
-       fog_area(plr, punit->tile,
-                unit_type(punit)->vision_range);
-      }
-    }
-    unit_list_iterate_end;
-  }
-
-  if (tech_found == research->tech_goal) {
-    research->tech_goal = A_UNSET;
-  }
-
-  if (tech_found == research->researching && next_tech == A_NONE) {
-    /* try to pick new tech to research */
-
-    if (choose_goal_tech(plr)) {
-      notify_player_ex(plr, NULL, E_TECH_LEARNED,
-                      _("Learned %s.  "
-                        "Our scientists focus on %s, goal is %s."),
-                      get_tech_name(plr, tech_found),
-                      get_tech_name(plr, research->researching),
-                      get_tech_name(plr, research->tech_goal));
-    } else {
-      if (plr->ai.control || !was_discovery) {
-        choose_random_tech(plr);
-      } else if (is_future_tech(tech_found)) {
-        /* Continue researching future tech. */
-        research->researching = A_FUTURE;
-      } else {
-        research->researching = A_UNSET;
-      }
-      if (research->researching != A_UNSET 
-          && (!is_future_tech(research->researching)
-             || !is_future_tech(tech_found))) {
-       notify_player_ex(plr, NULL, E_TECH_LEARNED,
-                        _("Learned %s.  Scientists "
-                          "choose to research %s."),
-                        get_tech_name(plr, tech_found),
-                        get_tech_name(plr, research->researching));
-      } else if (research->researching != A_UNSET) {
-       char buffer1[300];
-       char buffer2[300];
-
-       my_snprintf(buffer1, sizeof(buffer1), _("Learned %s. "),
-                   get_tech_name(plr, research->researching));
-       research->future_tech++;
-       my_snprintf(buffer2, sizeof(buffer2), _("Researching %s."),
-                   get_tech_name(plr, research->researching));
-       notify_player_ex(plr, NULL, E_TECH_LEARNED, "%s%s", buffer1,
-                        buffer2);
-      } else {
-       notify_player_ex(plr, NULL, E_TECH_LEARNED,
-                        _("Learned %s.  Scientists "
-                          "do not know what to research next."),
-                        get_tech_name(plr, tech_found));
-      }
-    }
-  } else if (tech_found == research->researching && next_tech > A_NONE) {
-    /* Next target already determined. We always save bulbs. */
-    research->researching = next_tech;
-  }
-
-  if (!saving_bulbs && research->bulbs_researched > 0) {
-    research->bulbs_researched = 0;
-  }
-
-  if (bonus_tech_hack) {
-    if (advances[tech_found].bonus_message) {
-      notify_player(plr, _("%s"),
-                   _(advances[tech_found].bonus_message));
-    } else {
-      notify_player(plr, _("Great scientists from all the "
-                          "world join your civilization: you get "
-                          "an immediate advance."));
-    }
-    if (research->researching == A_UNSET) {
-      choose_random_tech(plr);
-    }
-    tech_researched(plr);
-  }
-
-  /*
-   * Inform all players about new global advances to give them a
-   * chance to obsolete buildings.
-   */
-  send_game_info(NULL);
-
-  /*
-   * Inform player about his new tech.
-   */
-  send_player_info(plr, plr);
-
-  /*
-   * Update all cities in case the tech changed some effects. This is
-   * inefficient; it could be optimized if it's found to be a problem.  But
-   * techs aren't researched that often.
-   */
-  cities_iterate(pcity) {
-    city_refresh(pcity);
-    send_city_info(city_owner(pcity), pcity);
-  } cities_iterate_end;
-
-  /*
-   * Send all player an updated info of the owner of the Marco Polo
-   * Wonder if this wonder has become obsolete.
-   */
-  players_iterate(owner) {
-    if (had_embassy[owner->player_no]
-       && get_player_bonus(owner, EFT_HAVE_EMBASSIES) == 0) {
-      players_iterate(other_player) {
-       send_player_info(owner, other_player);
-      } players_iterate_end;
-    }
-  } players_iterate_end;
-
-  /* Update Team */
-  if (next_tech > A_NONE) {
-    /* Avoid unnecessary recursion. */
-    return;
-  }
-  players_iterate(aplayer) {
-    if (plr != aplayer
-        && plr->diplstates[aplayer->player_no].type == DS_TEAM
-        && aplayer->is_alive
-        && get_invention(aplayer, tech_found) != TECH_KNOWN) {
-      if (tech_exists(research->researching)) {
-        notify_player_ex(aplayer, NULL, E_TECH_LEARNED,
-                         _("Learned %s in cooperation with %s. "
-                           "Scientists choose to research %s."),
-                         get_tech_name(aplayer, tech_found), plr->name,
-                         get_tech_name(plr, research->researching));
-      } else {
-        notify_player_ex(aplayer, NULL, E_TECH_LEARNED,
-                         _("Learned %s in cooperation with %s. "
-                           "Scientists do not know what to research next."),
-                         get_tech_name(aplayer, tech_found), plr->name);
-      }
-    }
-    send_player_info(aplayer, NULL);
-  } players_iterate_end;
-}
-
-/**************************************************************************
-Player has a new future technology (from somewhere). Logging &
-notification is not done here as it depends on how the tech came.
-**************************************************************************/
-void found_new_future_tech(struct player *pplayer)
-{
-  get_player_research(pplayer)->future_tech++;
-  get_player_research(pplayer)->techs_researched++;
-}
-
-/**************************************************************************
-Player has researched a new technology
-**************************************************************************/
-static void tech_researched(struct player* plr)
-{
-  struct player_research * research = get_player_research(plr);
-  /* plr will be notified when new tech is chosen */
-  Tech_type_id tech_id = research->researching;
-  struct advance *tech = &advances[tech_id];
-
-  if (!is_future_tech(research->researching)) {
-    notify_embassies(plr, NULL,
-                    _("The %s have researched %s."), 
-                    get_nation_name_plural(plr->nation),
-                    get_tech_name(plr, research->researching));
-
-  } else {
-    notify_embassies(plr, NULL,
-                    _("The %s have researched Future Tech. %d."), 
-                    get_nation_name_plural(plr->nation),
-                    research->future_tech);
-  
-  }
-  script_signal_emit("tech_researched", 3,
-                    API_TYPE_TECH_TYPE, tech, API_TYPE_PLAYER, plr,
-                    API_TYPE_STRING, "researched");
-  gamelog(GAMELOG_TECH, plr, NULL, research->researching);
-
-  /* Deduct tech cost */
-  research->bulbs_researched = 
-      MAX(research->bulbs_researched - total_bulbs_required(plr), 0);
-
-  /* do all the updates needed after finding new tech */
-  found_new_tech(plr, research->researching, TRUE, TRUE, A_NONE);
-}
-
-/**************************************************************************
-  Called from each city to update the research->
-**************************************************************************/
-void update_tech(struct player *plr, int bulbs)
-{
-  int excessive_bulbs;
-  struct player_research* research = get_player_research(plr);
-
-  /* count our research contribution this turn */
-  plr->bulbs_last_turn += bulbs;
-
-  research->bulbs_researched += bulbs;
-  
-  excessive_bulbs =
-      (research->bulbs_researched - total_bulbs_required(plr));
-
-  if (excessive_bulbs >= 0 && research->researching != A_UNSET) {
-    tech_researched(plr);
-    if (research->researching != A_UNSET) {
-      update_tech(plr, 0);
-    }
-  }
-}
-
-/**************************************************************************
-...
-**************************************************************************/
-static bool choose_goal_tech(struct player *plr)
-{
-  int sub_goal;
-  struct player_research* research = get_player_research(plr);
-
-  sub_goal = get_next_tech(plr, research->tech_goal);
-
-  if (sub_goal != A_UNSET) {
-    research->researching = sub_goal;
-    return TRUE;
-  }
-  return FALSE;
-}
-
-/**************************************************************************
-...
-**************************************************************************/
-void choose_random_tech(struct player *plr)
-{
-  int chosen, researchable = 0;
-
-  tech_type_iterate(i) {
-    if (get_invention(plr, i) == TECH_REACHABLE) {
-      researchable++;
-    }
-  } tech_type_iterate_end;
-  if (researchable == 0) {
-    choose_tech(plr, A_FUTURE);
-    return;
-  }
-  chosen = myrand(researchable) + 1;
-  
-  tech_type_iterate(i) {
-    if (get_invention(plr, i) == TECH_REACHABLE) {
-      chosen--;
-      if (chosen == 0) {
-       choose_tech(plr, i);
-       break;
-      }
-    }
-  } tech_type_iterate_end;
-}
-
-/****************************************************************************
-  Called when the player chooses the tech he wants to research (or when
-  the server chooses it for him automatically).
-
-  This takes care of all side effects so the player's research target
-  probably shouldn't be changed outside of this function (doing so has
-  been the cause of several bugs).
-****************************************************************************/
-void choose_tech(struct player *plr, int tech)
-{
-  struct player_research * research = get_player_research(plr);
-
-  if (research->researching == tech) {
-    return;
-  }
-  if (get_invention(plr, tech) != TECH_REACHABLE) {
-    /* can't research this */
-    return;
-  }
-  if (!research->got_tech && research->changed_from == -1) {
-    research->bulbs_researched_before = research->bulbs_researched;
-    research->changed_from = research->researching;
-    /* subtract a penalty because we changed subject */
-    if (research->bulbs_researched > 0) {
-      research->bulbs_researched
-       -= ((research->bulbs_researched * game.info.techpenalty) / 100);
-      assert(research->bulbs_researched >= 0);
-    }
-  } else if (tech == research->changed_from) {
-    research->bulbs_researched = research->bulbs_researched_before;
-    research->changed_from = -1;
-  }
-  research->researching=tech;
-  if (research->bulbs_researched > total_bulbs_required(plr)) {
-    tech_researched(plr);
-  }
-}
-
-/****************************************************************************
-  Called when the player chooses the tech goal he wants to research (or when
-  the server chooses it for him automatically).
-****************************************************************************/
-void choose_tech_goal(struct player *plr, int tech)
-{
-  /* It's been suggested that if the research target is empty then
-   * choose_random_tech should be called here. */
-  notify_player(plr, _("Technology goal is %s."),
-               get_tech_name(plr, tech));
-  get_player_research(plr)->tech_goal = tech;
-}
-
-/****************************************************************************
-  Initializes tech data for the player.
-
-  The 'tech' parameter gives the number of random techs to assign to the
-  player.
-****************************************************************************/
-void init_tech(struct player *plr, int tech)
-{
-  int i;
-  struct nation_type *nation = get_nation_by_plr(plr);
-
-  tech_type_iterate(i) {
-    set_invention(plr, i, TECH_UNKNOWN);
-  } tech_type_iterate_end;
-  set_invention(plr, A_NONE, TECH_KNOWN);
-
-  get_player_research(plr)->techs_researched = 1;
-
-  /*
-   * Give game wide initial techs
-   */
-  for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
-    if (game.rgame.global_init_techs[i] == A_LAST) {
-      break;
-    }
-    set_invention(plr, game.rgame.global_init_techs[i], TECH_KNOWN);
-  }
-
-  /*
-   * Give nation specific initial techs
-   */
-  for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
-    if (nation->init_techs[i] == A_LAST) {
-      break;
-    }
-    set_invention(plr, nation->init_techs[i], TECH_KNOWN);
-  }
-
-  for (i = 0; i < tech; i++) {
-    update_research(plr);
-    choose_random_tech(plr); /* could be choose_goal_tech -- Syela */
-    set_invention(plr, get_player_research(plr)->researching, TECH_KNOWN);
-  }
-
-  /* Mark the reachable techs */
-  update_research(plr);
-  if (!choose_goal_tech(plr)) {
-    choose_random_tech(plr);
-  }
-}
-
-/**************************************************************************
-  If target has more techs than pplayer, pplayer will get a random of
-  these, the clients will both be notified and the conquer cost
-  penalty applied. Used for diplomats and city conquest.
-**************************************************************************/
-void get_a_tech(struct player *pplayer, struct player *target)
-{
-  Tech_type_id stolen_tech;
-  int j=0;
-
-  tech_type_iterate(i) {
-    if (get_invention(pplayer, i) != TECH_KNOWN
-       && get_invention(target, i) == TECH_KNOWN
-       && tech_is_available(pplayer, i)) {
-      j++;
-    }
-  } tech_type_iterate_end;
-  if (j == 0)  {
-    /* we've moved on to future tech */
-    if (get_player_research(target)->future_tech
-        > get_player_research(pplayer)->future_tech) {
-      found_new_future_tech(pplayer);
-      stolen_tech
-       = game.control.num_tech_types
-         + get_player_research(pplayer)->future_tech;
-    } else {
-      return; /* nothing to learn here, move on */
-    }
-    return;
-  } else {
-    /* pick random tech */
-    j = myrand(j) + 1;
-    stolen_tech = A_NONE; /* avoid compiler warning */
-    tech_type_iterate(i) {
-      if (get_invention(pplayer, i) != TECH_KNOWN
-         && get_invention(target, i) == TECH_KNOWN
-         && tech_is_available(pplayer, i)) {
-       j--;
-      }
-      if (j == 0) {
-       stolen_tech = i;
-       break;
-      }
-    } tech_type_iterate_end;
-    assert(stolen_tech != A_NONE);
-  }
-  script_signal_emit("tech_researched", 3,
-                    API_TYPE_TECH_TYPE, &advances[stolen_tech],
-                    API_TYPE_PLAYER, pplayer,
-                    API_TYPE_STRING, "stolen");
-  gamelog(GAMELOG_TECH, pplayer, target, stolen_tech, "steal");
-
-  notify_player_ex(pplayer, NULL, E_TECH_GAIN,
-                  _("You steal %s from the %s."),
-                  get_tech_name(pplayer, stolen_tech),
-                  get_nation_name_plural(target->nation));
-
-  notify_player_ex(target, NULL, E_ENEMY_DIPLOMAT_THEFT,
-                   _("The %s stole %s from you!"),
-                  get_nation_name_plural(pplayer->nation),
-                  get_tech_name(pplayer, stolen_tech));
-
-  notify_embassies(pplayer, target,
-                  _("The %s have stolen %s from the %s."),
-                  get_nation_name_plural(pplayer->nation),
-                  get_tech_name(pplayer, stolen_tech),
-                  get_nation_name_plural(target->nation));
-
-  do_conquer_cost(pplayer);
-  found_new_tech(pplayer, stolen_tech, FALSE, TRUE, A_NONE);
-}
-
-/**************************************************************************
   Handle a client or AI request to change the tax/luxury/science rates.
   This function does full sanity checking.
 **************************************************************************/
@@ -851,48 +272,6 @@
 }
 
 /**************************************************************************
-  Set the player to be researching the given tech.
-
-  If there are enough accumulated research points, the tech may be
-  acquired immediately.
-**************************************************************************/
-void handle_player_research(struct player *pplayer, int tech)
-{
-  choose_tech(pplayer, tech);
-  send_player_info(pplayer, pplayer);
-
-  /* Notify Team members. 
-   * They share same research struct.
-   */
-  players_iterate(aplayer) {
-    if (pplayer != aplayer
-       && pplayer->diplstates[aplayer->player_no].type == DS_TEAM
-       && aplayer->is_alive) {
-      send_player_info(aplayer, aplayer);
-    }
-  } players_iterate_end;
-}
-
-/**************************************************************************
-...
-**************************************************************************/
-void handle_player_tech_goal(struct player *pplayer, int tech)
-{
-  choose_tech_goal(pplayer, tech);
-  send_player_info(pplayer, pplayer);
-
-  /* Notify Team members */
-  players_iterate(aplayer) {
-    if (pplayer != aplayer
-        && pplayer->diplstates[aplayer->player_no].type == DS_TEAM
-        && aplayer->is_alive
-        && get_player_research(aplayer)->tech_goal != tech) {
-      handle_player_tech_goal(aplayer, tech);
-    }
-  } players_iterate_end;
-}
-
-/**************************************************************************
   Finish the revolution and set the player's government.  Call this as soon
   as the player has set a target_government and the revolution_finishes
   turn has arrived.
Index: server/plrhand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.h,v
retrieving revision 1.74
diff -u -r1.74 plrhand.h
--- server/plrhand.h    24 May 2005 16:45:39 -0000      1.74
+++ server/plrhand.h    23 Jun 2005 08:41:18 -0000
@@ -35,7 +35,7 @@
 void kill_player(struct player *pplayer);
 void kill_dying_players(void);
 void update_revolution(struct player *pplayer);
-void do_tech_parasite_effect(struct player *pplayer);
+
 void check_player_government_rates(struct player *pplayer);
 void make_contact(struct player *pplayer1, struct player *pplayer2,
                  struct tile *ptile);
@@ -63,16 +63,6 @@
 
 struct conn_list *player_reply_dest(struct player *pplayer);
 
-void found_new_tech(struct player *plr, int tech_found, bool was_discovery,
-                    bool saving_bulbs, int next_tech);
-void found_new_future_tech(struct player *pplayer);
-void update_tech(struct player *plr, int bulbs);
-void init_tech(struct player *plr, int tech);
-void choose_random_tech(struct player *plr);
-void choose_tech(struct player *plr, int tech);
-void choose_tech_goal(struct player *plr, int tech);
-void get_a_tech(struct player *pplayer, struct player *target);
-
 void send_player_turn_notifications(struct conn_list *dest);
 
 void do_dipl_cost(struct player *pplayer);
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.256
diff -u -r1.256 savegame.c
--- server/savegame.c   21 Jun 2005 16:21:02 -0000      1.256
+++ server/savegame.c   23 Jun 2005 08:41:27 -0000
@@ -52,6 +52,7 @@
 #include "maphand.h"
 #include "meta.h"
 #include "plrhand.h"
+#include "research.h"
 #include "ruleset.h"
 #include "savegame.h"
 #include "score.h"
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.273
diff -u -r1.273 srv_main.c
--- server/srv_main.c   21 Jun 2005 16:21:02 -0000      1.273
+++ server/srv_main.c   23 Jun 2005 08:41:34 -0000
@@ -83,6 +83,7 @@
 #include "meta.h"
 #include "plrhand.h"
 #include "report.h"
+#include "research.h"
 #include "ruleset.h"
 #include "sanitycheck.h"
 #include "savegame.h"
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.339
diff -u -r1.339 unithand.c
--- server/unithand.c   7 Jun 2005 06:17:14 -0000       1.339
+++ server/unithand.c   23 Jun 2005 08:41:36 -0000
@@ -43,6 +43,7 @@
 #include "gotohand.h"
 #include "maphand.h"
 #include "plrhand.h"
+#include "research.h"
 #include "settlers.h"
 #include "spacerace.h"
 #include "srv_main.h"
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.359
diff -u -r1.359 unittools.c
--- server/unittools.c  21 Jun 2005 16:21:02 -0000      1.359
+++ server/unittools.c  23 Jun 2005 08:41:44 -0000
@@ -46,6 +46,7 @@
 #include "gotohand.h"
 #include "maphand.h"
 #include "plrhand.h"
+#include "research.h"
 #include "script_signal.h"
 #include "sernet.h"
 #include "settlers.h"
Index: server/scripting/api_actions.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/scripting/api_actions.c,v
retrieving revision 1.2
diff -u -r1.2 api_actions.c
--- server/scripting/api_actions.c      21 Jun 2005 16:21:02 -0000      1.2
+++ server/scripting/api_actions.c      23 Jun 2005 08:41:44 -0000
@@ -16,6 +16,7 @@
 #endif
 
 #include "plrhand.h"
+#include "research.h"
 #include "citytools.h"
 #include "unittools.h"
 
/********************************************************************** 
 Freeciv - Copyright (C) 2005 The Freeciv Team
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
***********************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <assert.h>

#include "fcintl.h"
#include "log.h"
#include "mem.h"
#include "rand.h"
#include "shared.h"
#include "support.h"


#include "game.h"
#include "government.h"
#include "movement.h"
#include "player.h"

#include "tech.h"
#include "unit.h"

#include "script.h"

#include "citytools.h"
#include "cityturn.h"
#include "gamehand.h"
#include "gamelog.h"
#include "maphand.h"
#include "plrhand.h"
#include "unittools.h"

#include "research.h"

static void tech_researched(struct player* plr);
static bool choose_goal_tech(struct player *plr);

/**************************************************************************
  Give technologies to players with EFT_TECH_PARASITE (traditionally from
  the Great Library).
**************************************************************************/
void do_tech_parasite_effect(struct player *pplayer)
{
  int mod;
  struct effect_list *plist = effect_list_new();

  /* Note that two EFT_TECH_PARASITE effects will combine into a single,
   * much worse effect. */
  if ((mod = get_player_bonus_effects(plist, pplayer,
                                      EFT_TECH_PARASITE)) > 0) {
    char buf[512];

    buf[0] = '\0';
    effect_list_iterate(plist, peffect) {
      if (buf[0] != '\0') {
        sz_strlcat(buf, ", ");
      }
      get_effect_req_text(peffect, buf, sizeof(buf));
    } effect_list_iterate_end;

    tech_type_iterate(i) {
      if (get_invention(pplayer, i) != TECH_KNOWN
          && tech_is_available(pplayer, i)) {
        int num_players = 0;
        players_iterate(aplayer) {
          if (get_invention(aplayer, i) == TECH_KNOWN) {
            num_players++;
          }
        } players_iterate_end;
        if (num_players >= mod) {
          notify_player_ex(pplayer, NULL, E_TECH_GAIN,
                           _("%s acquired from %s!"),
                           get_tech_name(pplayer, i), buf);
          script_signal_emit("tech_researched", 3,
                             API_TYPE_TECH_TYPE, &advances[i],
                             API_TYPE_PLAYER, pplayer,
                             API_TYPE_STRING, "stolen");
          gamelog(GAMELOG_TECH, pplayer, NULL, i, "steal");
          notify_embassies(pplayer, NULL,
                           _("The %s have acquired %s from %s."),
                           get_nation_name_plural(pplayer->nation),
                           get_tech_name(pplayer, i), buf);

          do_free_cost(pplayer);
          found_new_tech(pplayer, i, FALSE, TRUE, A_NONE);
          break;
        }
      }
    } tech_type_iterate_end;
  }
  effect_list_unlink_all(plist);
  effect_list_free(plist);
}

/**************************************************************************
  Player has a new technology (from somewhere). was_discovery is passed 
  on to upgrade_city_rails. Logging & notification is not done here as 
  it depends on how the tech came. If next_tech is other than A_NONE, this 
  is the next tech to research.
**************************************************************************/
void found_new_tech(struct player *plr, int tech_found, bool was_discovery,
                    bool saving_bulbs, int next_tech)
{
  bool bonus_tech_hack = FALSE;
  bool was_first = FALSE;
  bool had_embassy[MAX_NUM_PLAYERS];
  struct city *pcity;
  bool can_switch[game.control.government_count];
  struct player_research* research = get_player_research(plr);

  players_iterate(aplr) {
    had_embassy[aplr->player_no]
      = (get_player_bonus(aplr, EFT_HAVE_EMBASSIES) > 0);
  } players_iterate_end;

  /* HACK: A_FUTURE doesn't "exist" and is thus not "available".  This may
   * or may not be the correct thing to do.  For these sanity checks we
   * just special-case it. */
  assert((tech_exists(tech_found)
          && get_invention(plr, tech_found) != TECH_KNOWN)
         || tech_found == A_FUTURE);
  assert(tech_is_available(plr, tech_found) || tech_found == A_FUTURE);

  research->got_tech = TRUE;
  research->changed_from = -1;
  research->techs_researched++;
  was_first = (!game.info.global_advances[tech_found]);

  if (was_first) {
    /* We used to have a gamelog() for first-researched, but not anymore. */

    /* Alert the owners of any wonders that have been made obsolete */
    impr_type_iterate(id) {
      if (is_great_wonder(id) && great_wonder_was_built(id) &&
          improvement_types[id].obsolete_by == tech_found &&
          (pcity = find_city_from_great_wonder(id))) {
        notify_player_ex(city_owner(pcity), NULL, E_WONDER_OBSOLETE,
                         _("Discovery of %s OBSOLETES %s in %s!"), 
                         get_tech_name(city_owner(pcity), tech_found),
                         get_improvement_name(id),
                         pcity->name);
      }
    } impr_type_iterate_end;
  }

  government_iterate(gov) {
    /* We do it this way so all requirements are checked, including
     * statue-of-liberty effects. */
    can_switch[gov->index] = can_change_to_government(plr, gov->index);
  } government_iterate_end;

  if (tech_flag(tech_found, TF_BONUS_TECH) && was_first) {
    bonus_tech_hack = TRUE;
  }

  set_invention(plr, tech_found, TECH_KNOWN);
  update_research(plr);
  remove_obsolete_buildings(plr);

  if (tech_flag(tech_found, TF_RAILROAD)) {
    players_iterate(aplayer) {
      if (players_on_same_team(aplayer, plr)) {
        upgrade_city_rails(plr, was_discovery);
      }
    } players_iterate_end;
  }

  government_iterate(gov) {
    if (!can_switch[gov->index]
        && can_change_to_government(plr, gov->index)) {
      notify_player_ex(plr, NULL, E_NEW_GOVERNMENT,
                       _("Discovery of %s makes the government form %s"
                         " available. You may want to start a revolution."),
                       get_tech_name(plr, tech_found), gov->name);
    }
  } government_iterate_end;

  /* enhance vision of units inside a fortress */
  if (tech_flag(tech_found, TF_WATCHTOWER)) {
    unit_list_iterate(plr->units, punit) {
      if (tile_has_special(punit->tile, S_FORTRESS)
          && is_ground_unit(punit)) {
        unfog_area(plr, punit->tile, get_watchtower_vision(punit));
        fog_area(plr, punit->tile,
                 unit_type(punit)->vision_range);
      }
    }
    unit_list_iterate_end;
  }

  if (tech_found == research->tech_goal) {
    research->tech_goal = A_UNSET;
  }

  if (tech_found == research->researching && next_tech == A_NONE) {
    /* try to pick new tech to research */

    if (choose_goal_tech(plr)) {
      notify_player_ex(plr, NULL, E_TECH_LEARNED,
                       _("Learned %s.  "
                         "Our scientists focus on %s, goal is %s."),
                       get_tech_name(plr, tech_found),
                       get_tech_name(plr, research->researching),
                       get_tech_name(plr, research->tech_goal));
    } else {
      if (plr->ai.control || !was_discovery) {
        choose_random_tech(plr);
      } else if (is_future_tech(tech_found)) {
        /* Continue researching future tech. */
        research->researching = A_FUTURE;
      } else {
        research->researching = A_UNSET;
      }
      if (research->researching != A_UNSET 
          && (!is_future_tech(research->researching)
              || !is_future_tech(tech_found))) {
        notify_player_ex(plr, NULL, E_TECH_LEARNED,
                         _("Learned %s.  Scientists "
                           "choose to research %s."),
                         get_tech_name(plr, tech_found),
                         get_tech_name(plr, research->researching));
      } else if (research->researching != A_UNSET) {
        char buffer1[300];
        char buffer2[300];

        my_snprintf(buffer1, sizeof(buffer1), _("Learned %s. "),
                    get_tech_name(plr, research->researching));
        research->future_tech++;
        my_snprintf(buffer2, sizeof(buffer2), _("Researching %s."),
                    get_tech_name(plr, research->researching));
        notify_player_ex(plr, NULL, E_TECH_LEARNED, "%s%s", buffer1,
                         buffer2);
      } else {
        notify_player_ex(plr, NULL, E_TECH_LEARNED,
                         _("Learned %s.  Scientists "
                           "do not know what to research next."),
                         get_tech_name(plr, tech_found));
      }
    }
  } else if (tech_found == research->researching && next_tech > A_NONE) {
    /* Next target already determined. We always save bulbs. */
    research->researching = next_tech;
  }

  if (!saving_bulbs && research->bulbs_researched > 0) {
    research->bulbs_researched = 0;
  }

  if (bonus_tech_hack) {
    if (advances[tech_found].bonus_message) {
      notify_player(plr, _("%s"),
                    _(advances[tech_found].bonus_message));
    } else {
      notify_player(plr, _("Great scientists from all the "
                           "world join your civilization: you get "
                           "an immediate advance."));
    }
    if (research->researching == A_UNSET) {
      choose_random_tech(plr);
    }
    tech_researched(plr);
  }

  /*
   * Inform all players about new global advances to give them a
   * chance to obsolete buildings.
   */
  send_game_info(NULL);

  /*
   * Inform player about his new tech.
   */
  send_player_info(plr, plr);

  /*
   * Update all cities in case the tech changed some effects. This is
   * inefficient; it could be optimized if it's found to be a problem.  But
   * techs aren't researched that often.
   */
  cities_iterate(pcity) {
    city_refresh(pcity);
    send_city_info(city_owner(pcity), pcity);
  } cities_iterate_end;

  /*
   * Send all player an updated info of the owner of the Marco Polo
   * Wonder if this wonder has become obsolete.
   */
  players_iterate(owner) {
    if (had_embassy[owner->player_no]
        && get_player_bonus(owner, EFT_HAVE_EMBASSIES) == 0) {
      players_iterate(other_player) {
        send_player_info(owner, other_player);
      } players_iterate_end;
    }
  } players_iterate_end;

  /* Update Team */
  if (next_tech > A_NONE) {
    /* Avoid unnecessary recursion. */
    return;
  }
  players_iterate(aplayer) {
    if (plr != aplayer
        && plr->diplstates[aplayer->player_no].type == DS_TEAM
        && aplayer->is_alive
        && get_invention(aplayer, tech_found) != TECH_KNOWN) {
      if (tech_exists(research->researching)) {
        notify_player_ex(aplayer, NULL, E_TECH_LEARNED,
                         _("Learned %s in cooperation with %s. "
                           "Scientists choose to research %s."),
                         get_tech_name(aplayer, tech_found), plr->name,
                         get_tech_name(plr, research->researching));
      } else {
        notify_player_ex(aplayer, NULL, E_TECH_LEARNED,
                         _("Learned %s in cooperation with %s. "
                           "Scientists do not know what to research next."),
                         get_tech_name(aplayer, tech_found), plr->name);
      }
    }
    send_player_info(aplayer, NULL);
  } players_iterate_end;
}

/**************************************************************************
Player has a new future technology (from somewhere). Logging &
notification is not done here as it depends on how the tech came.
**************************************************************************/
void found_new_future_tech(struct player *pplayer)
{
  get_player_research(pplayer)->future_tech++;
  get_player_research(pplayer)->techs_researched++;
}

/**************************************************************************
Player has researched a new technology
**************************************************************************/
static void tech_researched(struct player* plr)
{
  struct player_research * research = get_player_research(plr);
  /* plr will be notified when new tech is chosen */
  Tech_type_id tech_id = research->researching;
  struct advance *tech = &advances[tech_id];

  if (!is_future_tech(research->researching)) {
    notify_embassies(plr, NULL,
                     _("The %s have researched %s."), 
                     get_nation_name_plural(plr->nation),
                     get_tech_name(plr, research->researching));

  } else {
    notify_embassies(plr, NULL,
                     _("The %s have researched Future Tech. %d."), 
                     get_nation_name_plural(plr->nation),
                     research->future_tech);
  
  }
  script_signal_emit("tech_researched", 3,
                     API_TYPE_TECH_TYPE, tech, API_TYPE_PLAYER, plr,
                     API_TYPE_STRING, "researched");
  gamelog(GAMELOG_TECH, plr, NULL, research->researching);

  /* Deduct tech cost */
  research->bulbs_researched = 
      MAX(research->bulbs_researched - total_bulbs_required(plr), 0);

  /* do all the updates needed after finding new tech */
  found_new_tech(plr, research->researching, TRUE, TRUE, A_NONE);
}

/**************************************************************************
  Called from each city to update the research->
**************************************************************************/
void update_tech(struct player *plr, int bulbs)
{
  int excessive_bulbs;
  struct player_research* research = get_player_research(plr);

  /* count our research contribution this turn */
  plr->bulbs_last_turn += bulbs;

  research->bulbs_researched += bulbs;
  
  excessive_bulbs =
      (research->bulbs_researched - total_bulbs_required(plr));

  if (excessive_bulbs >= 0 && research->researching != A_UNSET) {
    tech_researched(plr);
    if (research->researching != A_UNSET) {
      update_tech(plr, 0);
    }
  }
}

/**************************************************************************
...
**************************************************************************/
static bool choose_goal_tech(struct player *plr)
{
  int sub_goal;
  struct player_research* research = get_player_research(plr);

  sub_goal = get_next_tech(plr, research->tech_goal);

  if (sub_goal != A_UNSET) {
    research->researching = sub_goal;
    return TRUE;
  }
  return FALSE;
}

/**************************************************************************
...
**************************************************************************/
void choose_random_tech(struct player *plr)
{
  int chosen, researchable = 0;

  tech_type_iterate(i) {
    if (get_invention(plr, i) == TECH_REACHABLE) {
      researchable++;
    }
  } tech_type_iterate_end;
  if (researchable == 0) {
    choose_tech(plr, A_FUTURE);
    return;
  }
  chosen = myrand(researchable) + 1;
  
  tech_type_iterate(i) {
    if (get_invention(plr, i) == TECH_REACHABLE) {
      chosen--;
      if (chosen == 0) {
        choose_tech(plr, i);
        break;
      }
    }
  } tech_type_iterate_end;
}

/****************************************************************************
  Called when the player chooses the tech he wants to research (or when
  the server chooses it for him automatically).

  This takes care of all side effects so the player's research target
  probably shouldn't be changed outside of this function (doing so has
  been the cause of several bugs).
****************************************************************************/
void choose_tech(struct player *plr, int tech)
{
  struct player_research * research = get_player_research(plr);

  if (research->researching == tech) {
    return;
  }
  if (get_invention(plr, tech) != TECH_REACHABLE) {
    /* can't research this */
    return;
  }
  if (!research->got_tech && research->changed_from == -1) {
    research->bulbs_researched_before = research->bulbs_researched;
    research->changed_from = research->researching;
    /* subtract a penalty because we changed subject */
    if (research->bulbs_researched > 0) {
      research->bulbs_researched
        -= ((research->bulbs_researched * game.info.techpenalty) / 100);
      assert(research->bulbs_researched >= 0);
    }
  } else if (tech == research->changed_from) {
    research->bulbs_researched = research->bulbs_researched_before;
    research->changed_from = -1;
  }
  research->researching=tech;
  if (research->bulbs_researched > total_bulbs_required(plr)) {
    tech_researched(plr);
  }
}

/****************************************************************************
  Called when the player chooses the tech goal he wants to research (or when
  the server chooses it for him automatically).
****************************************************************************/
void choose_tech_goal(struct player *plr, int tech)
{
  /* It's been suggested that if the research target is empty then
   * choose_random_tech should be called here. */
  notify_player(plr, _("Technology goal is %s."),
                get_tech_name(plr, tech));
  get_player_research(plr)->tech_goal = tech;
}

/****************************************************************************
  Initializes tech data for the player.

  The 'tech' parameter gives the number of random techs to assign to the
  player.
****************************************************************************/
void init_tech(struct player *plr, int tech)
{
  int i;
  struct nation_type *nation = get_nation_by_plr(plr);

  tech_type_iterate(i) {
    set_invention(plr, i, TECH_UNKNOWN);
  } tech_type_iterate_end;
  set_invention(plr, A_NONE, TECH_KNOWN);

  get_player_research(plr)->techs_researched = 1;

  /*
   * Give game wide initial techs
   */
  for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
    if (game.rgame.global_init_techs[i] == A_LAST) {
      break;
    }
    set_invention(plr, game.rgame.global_init_techs[i], TECH_KNOWN);
  }

  /*
   * Give nation specific initial techs
   */
  for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
    if (nation->init_techs[i] == A_LAST) {
      break;
    }
    set_invention(plr, nation->init_techs[i], TECH_KNOWN);
  }

  for (i = 0; i < tech; i++) {
    update_research(plr);
    choose_random_tech(plr); /* could be choose_goal_tech -- Syela */
    set_invention(plr, get_player_research(plr)->researching, TECH_KNOWN);
  }

  /* Mark the reachable techs */
  update_research(plr);
  if (!choose_goal_tech(plr)) {
    choose_random_tech(plr);
  }
}

/**************************************************************************
  If target has more techs than pplayer, pplayer will get a random of
  these, the clients will both be notified and the conquer cost
  penalty applied. Used for diplomats and city conquest.
**************************************************************************/
void get_a_tech(struct player *pplayer, struct player *target)
{
  Tech_type_id stolen_tech;
  int j=0;

  tech_type_iterate(i) {
    if (get_invention(pplayer, i) != TECH_KNOWN
        && get_invention(target, i) == TECH_KNOWN
        && tech_is_available(pplayer, i)) {
      j++;
    }
  } tech_type_iterate_end;
  if (j == 0)  {
    /* we've moved on to future tech */
    if (get_player_research(target)->future_tech
        > get_player_research(pplayer)->future_tech) {
      found_new_future_tech(pplayer);
      stolen_tech
        = game.control.num_tech_types
          + get_player_research(pplayer)->future_tech;
    } else {
      return; /* nothing to learn here, move on */
    }
    return;
  } else {
    /* pick random tech */
    j = myrand(j) + 1;
    stolen_tech = A_NONE; /* avoid compiler warning */
    tech_type_iterate(i) {
      if (get_invention(pplayer, i) != TECH_KNOWN
          && get_invention(target, i) == TECH_KNOWN
          && tech_is_available(pplayer, i)) {
        j--;
      }
      if (j == 0) {
        stolen_tech = i;
        break;
      }
    } tech_type_iterate_end;
    assert(stolen_tech != A_NONE);
  }
  script_signal_emit("tech_researched", 3,
                     API_TYPE_TECH_TYPE, &advances[stolen_tech],
                     API_TYPE_PLAYER, pplayer,
                     API_TYPE_STRING, "stolen");
  gamelog(GAMELOG_TECH, pplayer, target, stolen_tech, "steal");

  notify_player_ex(pplayer, NULL, E_TECH_GAIN,
                   _("You steal %s from the %s."),
                   get_tech_name(pplayer, stolen_tech),
                   get_nation_name_plural(target->nation));

  notify_player_ex(target, NULL, E_ENEMY_DIPLOMAT_THEFT,
                   _("The %s stole %s from you!"),
                   get_nation_name_plural(pplayer->nation),
                   get_tech_name(pplayer, stolen_tech));

  notify_embassies(pplayer, target,
                   _("The %s have stolen %s from the %s."),
                   get_nation_name_plural(pplayer->nation),
                   get_tech_name(pplayer, stolen_tech),
                   get_nation_name_plural(target->nation));

  do_conquer_cost(pplayer);
  found_new_tech(pplayer, stolen_tech, FALSE, TRUE, A_NONE);
}

/**************************************************************************
  Set the player to be researching the given tech.

  If there are enough accumulated research points, the tech may be
  acquired immediately.
**************************************************************************/
void handle_player_research(struct player *pplayer, int tech)
{
  choose_tech(pplayer, tech);
  send_player_info(pplayer, pplayer);

  /* Notify Team members. 
   * They share same research struct.
   */
  players_iterate(aplayer) {
    if (pplayer != aplayer
       && pplayer->diplstates[aplayer->player_no].type == DS_TEAM
       && aplayer->is_alive) {
      send_player_info(aplayer, aplayer);
    }
  } players_iterate_end;
}

/**************************************************************************
...
**************************************************************************/
void handle_player_tech_goal(struct player *pplayer, int tech)
{
  choose_tech_goal(pplayer, tech);
  send_player_info(pplayer, pplayer);

  /* Notify Team members */
  players_iterate(aplayer) {
    if (pplayer != aplayer
        && pplayer->diplstates[aplayer->player_no].type == DS_TEAM
        && aplayer->is_alive
        && get_player_research(aplayer)->tech_goal != tech) {
      handle_player_tech_goal(aplayer, tech);
    }
  } players_iterate_end;
}
/********************************************************************** 
 Freeciv - Copyright (C) 2005 The Freeciv Team
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
***********************************************************************/
#ifndef FC__RESEARCH_H
#define FC__RESEARCH_H

#include "player.h"
#include "tech.h"

void do_tech_parasite_effect(struct player *pplayer);
void found_new_tech(struct player *plr, int tech_found, bool was_discovery,
                    bool saving_bulbs, int next_tech);
void found_new_future_tech(struct player *pplayer);
void update_tech(struct player *plr, int bulbs);
void init_tech(struct player *plr, int tech);
void choose_random_tech(struct player *plr);
void choose_tech(struct player *plr, int tech);
void choose_tech_goal(struct player *plr, int tech);
void get_a_tech(struct player *pplayer, struct player *target);

#endif


[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#13314) new source file: research.c, Mateusz Stefek <=