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

Hello all,

missed to small changes (city_refresh => city_refresh_vision)

Matthias

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-30 19:04:41.000000000 +0100
@@ -275,6 +275,9 @@
   game.info.celebratesize = GAME_DEFAULT_CELEBRATESIZE;
   game.info.savepalace    = GAME_DEFAULT_SAVEPALACE;
   game.info.natural_city_names = GAME_DEFAULT_NATURALCITYNAMES;
+  game.info.migrationdist = GAME_DEFAULT_MIGRATION_DIST;
+  game.info.migrationworld = GAME_DEFAULT_MIGRATION_WORLD;
+  game.info.migrationplayer = GAME_DEFAULT_MIGRATION_PLAYER;
   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-30 21:38:38.000000000 +0100
@@ -248,6 +248,18 @@
 
 #define GAME_DEFAULT_NATURALCITYNAMES TRUE
 
+#define GAME_DEFAULT_MIGRATION_DIST   4
+#define GAME_MIN_MIGRATION_DIST       0 /* 0 = no migration */
+#define GAME_MAX_MIGRATION_DIST       7
+
+#define GAME_DEFAULT_MIGRATION_PLAYER 70
+#define GAME_MIN_MIGRATION_PLAYER    0
+#define GAME_MAX_MIGRATION_PLAYER    100
+
+#define GAME_DEFAULT_MIGRATION_WORLD 10
+#define GAME_MIN_MIGRATION_WORLD     0
+#define GAME_MAX_MIGRATION_WORLD     100
+
 #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-30 19:01:07.000000000 +0100
@@ -414,6 +414,9 @@
   UINT8 razechance;
   BOOL savepalace;
   BOOL natural_city_names;
+  UINT8 migrationdist;
+  UINT8 migrationplayer;
+  UINT8 migrationworld;
   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-30 22:56:57.000000000 +0100
@@ -1867,3 +1867,303 @@
   remove_city(pcity);
   return TRUE;
 }
+
+/**************************************************************************
+ Helpful function to make a score of a city.
+
+ formula:
+   score = (city size + feeling) * factors
+
+ * feeling of the citizens
+         + 1.00 * happy citizens
+         + 0.00 * content citizens
+         - 0.25 * unhappy citizens
+         - 0.50 * unhappy citizens
+
+ * factors
+   * the build costs of all buildings
+     f = (1.0 + [build shield cost]/1000)
+   * the trade of the city
+     f = (1 + [city surplus trade]/100)
+   * the gold within the city
+     f = (1 + [city surplus gold]/100)
+   * the luxury within the city
+     f = (1 + [city surplus luxury]/100)
+   * the science within the city
+     f = (1 + [city surplus science]/100)
+**************************************************************************/
+static float city_score(struct city *pcity)
+{
+  float score = 0.0;
+  float feeling = 0.0;
+  float f_build_cost, f_trade, f_gold, f_luxury, f_science = 0.0;
+  int build_shield_cost = 0;
+
+  /* feeling of the citizens */
+  feeling = 1.00 * pcity->feel[CITIZEN_HAPPY][FEELING_FINAL]
+          + 0.00 * pcity->feel[CITIZEN_CONTENT][FEELING_FINAL]
+          - 0.25 * pcity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]
+          - 0.50 * pcity->feel[CITIZEN_ANGRY][FEELING_FINAL];
+
+  /* take shild costs of all buidings into account */
+  city_built_iterate(pcity, pimprove) {
+    build_shield_cost += impr_build_shield_cost(pimprove);
+  } city_built_iterate_end;
+  f_build_cost = (1.0 + (float)build_shield_cost/1000);
+  /* take trade into account */
+  f_trade      = (1.0 + (float)pcity->surplus[O_TRADE]/100);
+  /* take gold into account */
+  f_gold       = (1.0 + (float)pcity->surplus[O_GOLD]/100);
+  /* take luxury into account */
+  f_luxury     = (1.0 + (float)pcity->surplus[O_LUXURY]/100);
+  /* take science into account */
+  f_science    = (1.0 + (float)pcity->surplus[O_SCIENCE]/100);
+
+  score = (pcity->size + feeling) * f_build_cost * f_trade * f_gold
+                                  * f_luxury * f_science;
+
+  freelog(LOG_DEBUG, "[M] %s score: (%d + %6.3f) * (%5.3f * %5.3f "
+                      "* %5.3f * %5.3f * %5.3f) = %6.3f",
+                      city_name(pcity), pcity->size, feeling,
+                      f_build_cost, f_trade, f_gold, f_luxury,
+                      f_science, score);
+
+  return score;
+}
+
+/**************************************************************************
+ Make citizens migrate between two cities.
+**************************************************************************/
+static void make_city_migration(
+               struct player *pplayer_from, struct city *pcity_from,
+               struct player *pplayer_to, struct city *pcity_to)
+{
+  char city_from_name[MAX_LEN_NAME];
+  struct city *rcity = NULL;
+
+  /* we copy the city name, maybe we disband it! */
+  sz_strlcpy(city_from_name, city_name(pcity_from));
+  if (city_can_grow_to(pcity_to, pcity_to->size + 1)) {
+    /* reduce size of giver */
+    if (pcity_from->size == 1) {
+      /* find closest city other of the same player than pcity_from */
+      rcity = find_closest_owned_city(pplayer_from, pcity_from->tile,
+                    FALSE, pcity_from);
+
+      if (rcity) {
+        notify_player(pplayer_from, pcity_from->tile, E_CITY_TRANSFER,
+                       _("Game: %s was disbanded by its citizens."),
+                         city_from_name);
+
+        /* transfer all units to the closest city */
+        transfer_city_units(pplayer_from, pplayer_from,
+                    pcity_from->units_supported,
+                    rcity, pcity_from, -1, TRUE);
+        remove_city(pcity_from);
+      } else {
+        /* it's the only city of the nation; stop here */
+        notify_player(pplayer_from, pcity_from->tile, E_CITY_TRANSFER,
+                   _("Game: Citizen of %s are unhappy and want to migrate "
+                     "to %s of %s in search for a better life."),
+                     city_from_name, city_name(pcity_to),
+                     player_name(pplayer_to));
+        return;
+      }
+    } else {
+      city_reduce_size(pcity_from, 1, pplayer_from);
+      city_refresh_vision(pcity_from);
+    }
+    /* raise size of receiver city */
+    city_increase_size(pcity_to);
+    city_refresh_vision(pcity_to);
+
+    if (pplayer_from == pplayer_to) {
+      /* migration between one nation */
+      notify_player(pplayer_from, pcity_to->tile, E_CITY_TRANSFER,
+                     _("Game: Migrants of %s integrated in %s "
+                       "in search for a better life."),
+                       city_from_name, city_name(pcity_to));
+    } else {
+      /* migration between different nations */
+      notify_player(pplayer_from, pcity_to->tile, E_CITY_TRANSFER,
+                     _("Game: Migrants of %s integrated in %s of %s "
+                       "in search for a better life."),
+                       city_from_name, city_name(pcity_to),
+                       player_name(pplayer_to));
+      notify_player(pplayer_to, pcity_to->tile, E_CITY_TRANSFER,
+                     _("Game: Migrants of %s of %s integrated in %s "
+                       "in search for a better life."),
+                       city_from_name, player_name(pplayer_from),
+                       city_name(pcity_to));
+    }
+
+    freelog(LOG_NORMAL, "[M] T%d migration successful (%s -> %s)",
+            game.info.turn, city_from_name, city_name(pcity_to));
+
+  } else {
+    /* protest! */
+    if (pplayer_from == pplayer_to) {
+      /* migration between one nation */
+      notify_player(pplayer_to, pcity_to->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_from_name, city_name(pcity_to));
+    } else {
+      /* migration between different nations */
+      notify_player(pplayer_from, pcity_to->tile, E_CITY_TRANSFER,
+                     _("Game: Migrants of %s can't go to %s of %s "
+                       "because it needs an improvement to grow! "
+                       "Improve your city to keep your citizens!"),
+                       city_from_name, city_name(pcity_to),
+                       player_name(pplayer_to));
+      notify_player(pplayer_to, pcity_to->tile, E_CITY_TRANSFER,
+                     _("Game: Migrants of %s of %s can't go to %s "
+                       "because it needs an improvement to grow! "
+                       "You are responsible for her poverty!"),
+                       city_from_name, player_name(pplayer_from),
+                       city_name(pcity_to));
+    }
+  }
+}
+
+/**************************************************************************
+ Check for citizens who want to migrate between the cities that overlap.
+
+ Migrants go to the better city of both involved, the giver and the receiver.
+**************************************************************************/
+void check_city_migrations(struct player *pplayer)
+{
+  float best_city_player_score;
+  struct city *best_city_player = NULL;
+
+  float best_city_world_score;
+  struct city *best_city_world = NULL;
+
+  float score_from;
+  float score_tmp;
+
+  struct city *acity = NULL;
+  int dist = 0;
+
+  /* do the calculation only if migration is activated */
+  if (game.info.migrationdist == 0
+    || (game.info.migrationworld == 0
+      && game.info.migrationplayer == 0)) {
+    return;
+  }
+
+  /* first we search for cities that overlap */
+  city_list_iterate(pplayer->cities, pcity) {
+    /* no migration out of the capital */
+    if (find_palace(city_owner(pcity)) == pcity) {
+      continue;
+    }
+
+    /* check only each 5th turn (counted from the funding turn) */
+    if (((game.info.turn - pcity->turn_founded) % 5) > 0) {
+      continue;
+    }
+
+    /* score of the actual city
+     * taking into account a persistence factor of 2 */
+    score_from = city_score(pcity) * 2;
+
+    freelog(LOG_NORMAL, "[M] T%d check city: %s score: %6.3f (%s)",
+                        game.info.turn, city_name(pcity), score_from,
+                        player_name(pplayer));
+
+    best_city_player_score = 0;
+    best_city_world_score = 0;
+
+    /* loop over all tiles in a square of game.info.migrationdist size */
+    square_iterate(pcity->tile, (game.info.migrationdist - 1), ptile) {
+      acity = tile_city(ptile);
+
+      if (!acity || acity == pcity) {
+        /* no city or the city in the center */
+        continue;
+      }
+
+      /* distance between the two cities*/
+      dist = real_map_distance(pcity->tile, acity->tile);
+
+      /* score of the second city, weighted by the distance */
+      score_tmp = city_score(acity)
+          * (GAME_MAX_MIGRATION_DIST - dist) / GAME_MAX_MIGRATION_DIST;
+
+      freelog(LOG_NORMAL, "[M] T%d - compare city: %s (%s) dist: %d score: %6.3f",
+                          game.info.turn, city_name(acity),
+                          player_name(city_owner(acity)), dist, score_tmp);
+
+      if (game.info.migrationplayer != 0
+        && city_owner(acity) == pplayer) {
+        /* inmigrate in cities of the same owner */
+        if ((score_tmp > score_from)
+          && (score_tmp > best_city_player_score)) {
+          /* select the best! */
+          best_city_player_score = score_tmp;
+          best_city_player = acity;
+
+          freelog(LOG_NORMAL, "[M] T%d - best city (player): "
+                              "%s (%s) score: %6.3f (> %6.3f)",
+                              game.info.turn, city_name(best_city_player),
+                              player_name(pplayer),
+                              best_city_player_score, score_from);
+        }
+      } else if (game.info.migrationworld != 0
+        && city_owner(acity) != pplayer) {
+        /* inmigrate between cities of different owners */
+        if ((score_tmp > score_from)
+          && (score_tmp > best_city_world_score)) {
+          /* select the best! */
+          best_city_world_score = score_tmp;
+          best_city_world = acity;
+
+          freelog(LOG_NORMAL, "[M] T%d - best city (world): "
+                              "%s (%s) score: %6.3f (> %6.3f)",
+                              game.info.turn, city_name(best_city_world),
+                              player_name(pplayer),
+                              best_city_world_score, score_from);
+        }
+      }
+    } square_iterate_end;
+
+    if (best_city_player_score > 0) {
+      /* first, do the migration within one nation */
+      if (myrand (100) >= game.info.migrationplayer) {
+        /* no migration */
+        notify_player(pplayer, pcity->tile, E_CITY_TRANSFER,
+                      _("Game: Citizens of %s are thinking about migration "
+                        "to %s in search for a better life."),
+                        pcity->name, city_name(best_city_player));
+      } else {
+        make_city_migration(pplayer, pcity,
+                pplayer, best_city_player);
+      }
+
+      continue;
+    }
+
+    if (best_city_world_score > 0) {
+      /* second, do the migration between all nations */
+      struct player *pplayer_best_city_world = city_owner(best_city_world);
+
+      if (myrand (100) >= game.info.migrationworld) {
+        /* no migration */
+        notify_player(pplayer, pcity->tile, E_CITY_TRANSFER,
+                      _("Game: Citizens of %s are thinking about migration "
+                        "to %s of %s in search for a better life."),
+                        city_name(pcity), city_name(best_city_world),
+                        player_name(pplayer_best_city_world));
+      } else {
+        make_city_migration(pplayer, pcity,
+                pplayer_best_city_world, best_city_world);
+      }
+
+      continue;
+    }
+
+  } 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-30 01:12:01.000000000 +0100
@@ -46,4 +46,7 @@
 void advisor_choose_build(struct player *pplayer, struct city *pcity);
 
 void nullify_prechange_production(struct city *pcity);
+
+void check_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-30 19:01:48.000000000 +0100
@@ -4291,6 +4291,15 @@
     game.info.allowed_city_names =
       secfile_lookup_int_default(file, game.info.allowed_city_names,
                                  "game.allowed_city_names"); 
+    game.info.migrationdist =
+      secfile_lookup_int_default(file, game.info.migrationdist,
+                                 "game.migrationdist");
+    game.info.migrationplayer =
+      secfile_lookup_int_default(file, game.info.migrationplayer,
+                                 "game.migrationplayer");
+    game.info.migrationworld =
+      secfile_lookup_int_default(file, game.info.migrationworld,
+                                 "game.migrationworld");
 
     if(civstyle == 1) {
       string = "civ1";
@@ -4943,6 +4952,9 @@
   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_int(file, game.info.migrationdist, "game.migrationdist");
+  secfile_insert_int(file, game.info.migrationplayer, "game.migrationplayer");
+  secfile_insert_int(file, game.info.migrationworld, "game.migrationworld");
 
   {
     /* 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-30 20:19:29.000000000 +0100
@@ -841,6 +841,34 @@
               "on the surrounding terrain."),
            NULL, GAME_DEFAULT_NATURALCITYNAMES)
 
+  GEN_INT("migrationdist", game.info.migrationdist,
+          SSET_RULES_FLEXIBLE, SSET_SOCIOLOGY, SSET_RARE, SSET_TO_CLIENT,
+          N_("Distance for migration between cities"),
+          N_("If two cities overlap or are close to each over, citizens "
+             "can migrate between both cities. For example, when this "
+             "value is 3, there can be up to two empty fields between "
+             "two cities for citizens to migrate. "
+             "Setting this value to 0 will deactivate migration."),
+          NULL,
+          GAME_MIN_MIGRATION_DIST, GAME_MAX_MIGRATION_DIST,
+          GAME_DEFAULT_MIGRATION_DIST)
+
+  GEN_INT("migrationplayer", game.info.migrationplayer,
+          SSET_RULES_FLEXIBLE, SSET_SOCIOLOGY, SSET_RARE, SSET_TO_CLIENT,
+           N_("Chance for migration within one nation"),
+           N_("Possibility of migration between overlapping cities"
+              "within one nation."),
+          NULL, GAME_MIN_MIGRATION_PLAYER, GAME_MAX_MIGRATION_PLAYER,
+          GAME_DEFAULT_MIGRATION_PLAYER)
+
+  GEN_INT("migrationworld", game.info.migrationworld,
+          SSET_RULES_FLEXIBLE, SSET_SOCIOLOGY, SSET_RARE, SSET_TO_CLIENT,
+           N_("Chance for migration between all cities"),
+           N_("Possibility of migration between overlapping cities"
+              "taking into account cities of all nations."),
+          NULL, GAME_MIN_MIGRATION_WORLD, GAME_MAX_MIGRATION_WORLD,
+          GAME_DEFAULT_MIGRATION_WORLD)
+
   /* 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-29 11:51:47.000000000 +0100
@@ -869,6 +869,11 @@
   summon_barbarians(); /* wild guess really, no idea where to put it, but
 			  I want to give them chance to move their units */
 
+  freelog(LOG_DEBUG, "Season of migrations");
+  players_iterate(pplayer) {
+    check_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