diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/cityturn.c freeciv-patched/server/cityturn.c
--- freeciv-cvs/server/cityturn.c	2003-07-10 11:50:34.000000000 +0100
+++ freeciv-patched/server/cityturn.c	2003-07-10 11:50:34.000000000 +0100
@@ -914,6 +914,41 @@
 }
 
 /**************************************************************************
+  Gives immediate tech advances if we've just built a city improvement
+  that confers the Give_Imm_Adv effect (e.g. Darwin's Voyage)
+**************************************************************************/
+static void check_boost_research(struct city *pcity, struct player *pplayer)
+{
+  int numadv = 0;
+
+  impr_effects_iterate(iter, B_LAST, pcity, NULL) {
+    if (iter.imeff->type == EFT_GIVE_IMM_ADV
+        && eff_iterator_get_improvement(&iter) == pcity->currently_building) {
+      numadv = iter.imeff->amount;
+      break;
+    }
+  } impr_effects_iterate_end;
+
+  if (numadv) {
+    notify_player(pplayer, PL_("Game: %s boosts research; you gain %d "
+		  "immediate advance.", "Game: %s boosts research; you "
+		  "gain %d immediate advances.", numadv),
+		    get_improvement_name(pcity->currently_building),
+		    numadv);
+    while (numadv) {
+      do_free_cost(pplayer);
+      notify_embassies(pplayer, NULL,
+          	       _("Game: The %s have acquired %s from %s."),
+                       get_nation_name_plural(pplayer->nation),
+                       get_tech_name(pplayer, pplayer->research.researching),
+                       get_improvement_name(pcity->currently_building));
+      found_new_tech(pplayer, pplayer->research.researching, TRUE, TRUE);
+      numadv--;
+    }
+  }
+}
+
+/**************************************************************************
 ...
 **************************************************************************/
 static bool city_build_building(struct player *pplayer, struct city *pcity)
@@ -986,31 +1021,8 @@
 		     _("Game: %s has finished building %s."), pcity->name,
 		     improvement_types[pcity->currently_building].name);
 
-    if (pcity->currently_building == B_DARWIN) {
-      Tech_Type_id first, second;
-      char buffer[200];
-
-      notify_player(pplayer, _("Game: %s boosts research, "
-			       "you gain 2 immediate advances."),
-		    improvement_types[B_DARWIN].name);
-
-      do_free_cost(pplayer);
-      first = pplayer->research.researching;
-      found_new_tech(pplayer, pplayer->research.researching, TRUE, TRUE);
-
-      do_free_cost(pplayer);
-      second = pplayer->research.researching;
-      found_new_tech(pplayer, pplayer->research.researching, TRUE, TRUE);
-
-      (void) mystrlcpy(buffer, get_tech_name(pplayer, first),
-		       sizeof(buffer));
+    check_boost_research(pcity, pplayer);
 
-      notify_embassies(pplayer, NULL,
-		       _("Game: The %s have acquired %s and %s from %s."),
-		       get_nation_name_plural(pplayer->nation), buffer,
-		       get_tech_name(pplayer, second),
-		       improvement_types[B_DARWIN].name);
-    }
     if (space_part && pplayer->spaceship.state == SSHIP_NONE) {
       notify_player_ex(NULL, pcity->x, pcity->y, E_SPACESHIP,
 		       _("Game: The %s have started "
diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/plrhand.c freeciv-patched/server/plrhand.c
--- freeciv-cvs/server/plrhand.c	2003-07-07 18:23:58.000000000 +0100
+++ freeciv-patched/server/plrhand.c	2003-07-10 11:50:34.000000000 +0100
@@ -120,34 +120,41 @@
 }
 
 /**************************************************************************
-...
+  Grants techs that other players have researched, as a result of owning
+  an active Great Library Wonder, or other building that confers the
+  Adv_Parasite effect
 **************************************************************************/
 void great_library(struct player *pplayer)
 {
-  int i;
-  if (wonder_obsolete(B_GREAT)) 
-    return;
-  if (find_city_wonder(B_GREAT)) {
-    if (pplayer->player_no==find_city_wonder(B_GREAT)->owner) {
-      for (i=0;i<game.num_tech_types;i++) {
-	if (get_invention(pplayer, i) != TECH_KNOWN
-	    && tech_is_available(pplayer, i)
-	    && game.global_advances[i]>=2) {
-	  notify_player_ex(pplayer, -1, -1, E_TECH_GAIN,
-			   _("Game: %s acquired from The Great Library!"),
-			   advances[i].name);
-	  gamelog(GAMELOG_TECH, _("%s discover %s (Library)"),
-		  get_nation_name_plural(pplayer->nation), advances[i].name);
-	  notify_embassies(pplayer, NULL,
-			   _("Game: The %s have acquired %s"
-			     " from the Great Library."),
-			   get_nation_name_plural(pplayer->nation),
-			   advances[i].name);
-
-	  do_free_cost(pplayer);
-	  found_new_tech(pplayer, i, FALSE, FALSE);
-	  break;
-	}
+  int i, playreq = 0;
+  Impr_Type_id impr = B_LAST;
+
+  impr_effects_iterate(iter, B_LAST, NULL, pplayer) {
+    if (iter.imeff->type == EFT_ADV_PARASITE
+	&& (playreq == 0 || iter.imeff->amount < playreq)) {
+      playreq = iter.imeff->amount;
+      impr = eff_iterator_get_improvement(&iter);
+    }
+  } impr_effects_iterate_end;
+
+  if (playreq > 0 && impr != B_LAST) {
+    for (i = 0; i < game.num_tech_types; i++) {
+      if (get_invention(pplayer, i) != TECH_KNOWN 
+	  && tech_is_available(pplayer, i)
+	  && game.global_advances[i] >= playreq) {
+	notify_player_ex(pplayer, -1, -1, E_TECH_GAIN,
+			 _("Game: %s acquired from %s!"),
+			 advances[i].name, get_improvement_name(impr));
+	gamelog(GAMELOG_TECH, _("%s discover %s (Library)"),
+		get_nation_name_plural(pplayer->nation), advances[i].name);
+	notify_embassies(pplayer, NULL,
+			 _("Game: The %s have acquired %s from %s."),
+			 get_nation_name_plural(pplayer->nation),
+			 advances[i].name, get_improvement_name(impr));
+
+	do_free_cost(pplayer);
+	found_new_tech(pplayer, i, FALSE, FALSE);
+	break;
       }
     }
   }
diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/ruleset.c freeciv-patched/server/ruleset.c
--- freeciv-cvs/server/ruleset.c	2003-07-10 11:49:36.000000000 +0100
+++ freeciv-patched/server/ruleset.c	2003-07-10 11:50:34.000000000 +0100
@@ -1132,6 +1132,17 @@
 	problem = TRUE;
       }
 
+      /* For some effects the range doesn't really matter - so we fix it
+	 to the most convenient range for the code to deal with */
+      switch(e->type) {
+      case EFT_ADV_PARASITE:
+        e->range = EFR_PLAYER; break;
+      case EFT_GIVE_IMM_ADV:
+        e->range = EFR_CITY; break;
+      default:
+        break;
+      }
+
       e->amount =
 	secfile_lookup_int_default(file, 0, "%s.effect%d.amount", sec[i], j);
 
