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

The attached patch implements the migration of population between cities that 
overlap. It has an activation / deactivation option (default: on).

The patch original cames from jorneg [1]. I updated it to the svn trunk [2].

[1] http://forum.freeciv.org/viewtopic.php?t=1348
[2] http://forum.freeciv.org/viewtopic.php?t=4095
-- 
Matthias Pfafferodt - http://www.mapfa.de
Matthias.Pfafferodt <at> mapfa.de

diff -ur -X./freeciv-2.1.99svn15387/diff_ignore freeciv-2.1.99svn15387/common/game.c freeciv-2.1.99svn.patch/common/game.c
--- freeciv-2.1.99svn15387/common/game.c	2008-12-25 19:45:44.000000000 +0100
+++ freeciv-2.1.99svn.patch/common/game.c	2008-12-27 18:11:51.000000000 +0100
@@ -275,6 +275,7 @@
   game.info.celebratesize = GAME_DEFAULT_CELEBRATESIZE;
   game.info.savepalace    = GAME_DEFAULT_SAVEPALACE;
   game.info.natural_city_names = GAME_DEFAULT_NATURALCITYNAMES;
+  game.info.migration     = GAME_DEFAULT_MIGRATION;
   game.info.angrycitizen  = GAME_DEFAULT_ANGRYCITIZEN;
   game.info.foodbox       = GAME_DEFAULT_FOODBOX;
   game.info.shieldbox = GAME_DEFAULT_SHIELDBOX;
diff -ur -X./freeciv-2.1.99svn15387/diff_ignore freeciv-2.1.99svn15387/common/game.h freeciv-2.1.99svn.patch/common/game.h
--- freeciv-2.1.99svn15387/common/game.h	2008-12-25 19:45:44.000000000 +0100
+++ freeciv-2.1.99svn.patch/common/game.h	2008-12-27 18:11:26.000000000 +0100
@@ -248,6 +248,8 @@
 
 #define GAME_DEFAULT_NATURALCITYNAMES TRUE
 
+#define GAME_DEFAULT_MIGRATION       TRUE
+
 #define GAME_DEFAULT_AQUEDUCTLOSS    0
 #define GAME_MIN_AQUEDUCTLOSS        0
 #define GAME_MAX_AQUEDUCTLOSS        100
diff -ur -X./freeciv-2.1.99svn15387/diff_ignore freeciv-2.1.99svn15387/common/packets.def freeciv-2.1.99svn.patch/common/packets.def
--- freeciv-2.1.99svn15387/common/packets.def	2008-12-27 17:25:16.000000000 +0100
+++ freeciv-2.1.99svn.patch/common/packets.def	2008-12-27 19:38:02.000000000 +0100
@@ -414,6 +414,7 @@
   UINT8 razechance;
   BOOL savepalace;
   BOOL natural_city_names;
+  BOOL migration;
   BOOL turnblock;
   BOOL fixedlength;
   BOOL auto_ai_toggle;
diff -ur -X./freeciv-2.1.99svn15387/diff_ignore freeciv-2.1.99svn15387/server/cityturn.c freeciv-2.1.99svn.patch/server/cityturn.c
--- freeciv-2.1.99svn15387/server/cityturn.c	2008-12-25 19:45:49.000000000 +0100
+++ freeciv-2.1.99svn.patch/server/cityturn.c	2008-12-27 18:32:19.000000000 +0100
@@ -1867,3 +1867,121 @@
   remove_city(pcity);
   return TRUE;
 }
+
+/**************************************************************************
+ Helpful function to make a score of a city.
+
+ It computes the trade of the city, the production and the tiles of the city.
+**************************************************************************/
+static int city_score(struct city *pcity)
+{
+  int score = 0;
+
+  score = pcity->prod[O_TRADE] + pcity->prod[O_SHIELD];
+  score += 10 * pcity->size;
+  square_iterate(pcity->tile, 2, ptile) {
+    if (is_ocean(ptile->terrain)) {
+      score += 2;
+    }
+  } square_iterate_end;
+
+  city_built_iterate(pcity, pimprove) {
+    score += impr_build_shield_cost(pimprove) * 2;
+  } city_built_iterate_end;
+
+  if (find_palace(city_owner(pcity)) == pcity) {
+    score *= 2;
+  }
+
+  return score;
+}
+
+/**************************************************************************
+ Make the migrations between the cities that overlap.
+
+ Migrants go to the better city of both involved, the giver and the receiver.
+**************************************************************************/
+void make_city_migrations(struct player *pplayer)
+{
+  char city_name[100];
+
+  if ((game.info.turn % 5) > 0) {
+    return;
+  }
+
+  /* first we search for cities that overlap */
+  city_list_iterate(pplayer->cities, pcity) {
+    struct city *best_city = NULL;
+    int score_1 = city_score(pcity);
+    int best_score = 0;
+
+    square_iterate(pcity->tile, 2, ptile) {
+      struct city *acity = tile_city(ptile);
+      if (acity) {
+        /* here we have two cities that overlap... */
+        int score_2 = city_score(acity);
+
+        /* inmigrate in cities of the same owner */
+        if (city_owner(acity) != pplayer) {
+          continue;
+        }
+
+        /* inmigrate in cities that can grow */
+        if (!city_can_grow_to(acity, acity->size + 1)) {
+          score_2 /= 4;
+        }
+
+        if ((score_2 > score_1) && (score_2 > best_score)) {
+          /* select the best! */
+          best_score = score_2;
+          best_city = acity;
+        }
+      }
+    } square_iterate_end;
+
+    /* do the migration */
+    if (best_score > 0) {
+      /* we copy the city name, maybe we disband it! */
+      sz_strlcpy(city_name, pcity->name);
+      if (city_can_grow_to(best_city, best_city->size + 1)) {
+        /* reduce size of giver */
+        if (pcity->size == 1) {
+          struct city *rcity = NULL;
+          /* find closest city other than pcity */
+          rcity = find_closest_owned_city(pplayer, best_city->tile, FALSE, pcity);
+
+          if (rcity) {
+            transfer_city_units(pplayer, pplayer, pcity->units_supported, rcity, pcity, -1, TRUE);
+            remove_city(pcity);
+          } else {
+            notify_player(pplayer, pcity->tile, E_CITY_TRANSFER,
+                                      _("Game: Migrants of %s cannot integrate in %s "
+                                        "because you don't have another city around!"),
+                                        city_name, best_city->name);
+            return;
+          }
+        } else {
+          city_reduce_size(pcity, 1, pplayer);
+          city_refresh(pcity);
+        }
+        /* raise size of receiver city */
+        city_increase_size(best_city);
+        city_refresh(best_city);
+        /* message to the player */
+        notify_player(pplayer, best_city->tile, E_CITY_TRANSFER,
+                         _("Game: Migrants of %s integrated in %s "
+                           "in search for a better life."),
+                           city_name, best_city->name);
+      } else {
+        /* protest! */
+        notify_player(pplayer, best_city->tile, E_CITY_TRANSFER,
+                                  _("Game: Migrants of %s can't go to %s "
+                                    "because it needs an improvement to grow! "
+                                    "You are responsible for her poverty!"),
+                                    city_name, best_city->name);
+      }
+    }
+
+  } city_list_iterate_end;
+
+}
diff -ur -X./freeciv-2.1.99svn15387/diff_ignore freeciv-2.1.99svn15387/server/cityturn.h freeciv-2.1.99svn.patch/server/cityturn.h
--- freeciv-2.1.99svn15387/server/cityturn.h	2008-12-25 19:45:49.000000000 +0100
+++ freeciv-2.1.99svn.patch/server/cityturn.h	2008-12-27 17:26:59.000000000 +0100
@@ -46,4 +46,7 @@
 void advisor_choose_build(struct player *pplayer, struct city *pcity);
 
 void nullify_prechange_production(struct city *pcity);
+
+void make_city_migrations(struct player *pplayer);
+
 #endif  /* FC__CITYTURN_H */
diff -ur -X./freeciv-2.1.99svn15387/diff_ignore freeciv-2.1.99svn15387/server/savegame.c freeciv-2.1.99svn.patch/server/savegame.c
--- freeciv-2.1.99svn15387/server/savegame.c	2008-12-27 17:25:17.000000000 +0100
+++ freeciv-2.1.99svn.patch/server/savegame.c	2008-12-27 18:19:35.000000000 +0100
@@ -4291,6 +4291,9 @@
     game.info.allowed_city_names =
       secfile_lookup_int_default(file, game.info.allowed_city_names,
                                  "game.allowed_city_names"); 
+    game.info.migration =
+      secfile_lookup_bool_default(file, game.info.migration,
+                                 "game.migration");
 
     if(civstyle == 1) {
       string = "civ1";
@@ -4943,6 +4946,7 @@
   secfile_insert_bool(file, game.info.happyborders, "game.happyborders");
   secfile_insert_int(file, game.info.diplomacy, "game.diplomacy");
   secfile_insert_int(file, game.info.allowed_city_names, "game.allowed_city_names");
+  secfile_insert_bool(file, game.info.migration, "game.migration");
 
   {
     /* Now always save these, so the server options reflect the
diff -ur -X./freeciv-2.1.99svn15387/diff_ignore freeciv-2.1.99svn15387/server/settings.c freeciv-2.1.99svn.patch/server/settings.c
--- freeciv-2.1.99svn15387/server/settings.c	2008-12-25 19:45:49.000000000 +0100
+++ freeciv-2.1.99svn.patch/server/settings.c	2008-12-27 19:52:05.000000000 +0100
@@ -841,6 +841,14 @@
               "on the surrounding terrain."),
            NULL, GAME_DEFAULT_NATURALCITYNAMES)
 
+  GEN_BOOL("migration", game.info.migration,
+           SSET_RULES_FLEXIBLE, SSET_SOCIOLOGY, SSET_RARE, SSET_TO_CLIENT,
+           N_("Migration between overlapping cities"),
+           N_("If enabled, the population can migrate between overlapping "
+              "cities."),
+           NULL,
+           GAME_DEFAULT_MIGRATION)
+
   /* Meta options: these don't affect the internal rules of the game, but
    * do affect players.  Also options which only produce extra server
    * "output" and don't affect the actual game.
diff -ur -X./freeciv-2.1.99svn15387/diff_ignore freeciv-2.1.99svn15387/server/srv_main.c freeciv-2.1.99svn.patch/server/srv_main.c
--- freeciv-2.1.99svn15387/server/srv_main.c	2008-12-27 17:25:17.000000000 +0100
+++ freeciv-2.1.99svn.patch/server/srv_main.c	2008-12-27 19:53:34.000000000 +0100
@@ -869,6 +869,13 @@
   summon_barbarians(); /* wild guess really, no idea where to put it, but
 			  I want to give them chance to move their units */
 
+/*  if (game.info.migration) { */
+    freelog(LOG_DEBUG, "Season of migrations");
+    players_iterate(pplayer) {
+      make_city_migrations(pplayer);
+    } players_iterate_end;
+/*  } */
+
   update_environmental_upset(S_POLLUTION, &game.info.heating,
 			     &game.info.globalwarming, &game.info.warminglevel,
 			     global_warming);
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to