<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
[email protected]
https://mail.gna.org/listinfo/freeciv-dev