Complete.Org: Mailing Lists: Archives: freeciv-dev: October 2005:
[Freeciv-Dev] Re: (PR#14289) Different Gameloss Outcomes
Home

[Freeciv-Dev] Re: (PR#14289) Different Gameloss Outcomes

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#14289) Different Gameloss Outcomes
From: "Benedict Adamson" <badamson@xxxxxxxxxxx>
Date: Fri, 14 Oct 2005 17:46:24 -0700
Reply-to: bugs@xxxxxxxxxxx

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

Benedict Adamson wrote:
...
> Perhaps we could have multiple possible [Gameloss] outcomes? A ruleset option 
> could 
> select which was wanted.
...
Jason replied:
> IMO we don't need an option here.  The obvious best choice is to make
> them all barbarians.

Here is a patch that provides two ruleset choices: the traditional 
outcome, and changing them all to barbarians. The civ1, civ2 and history 
rulesets use the traditional outcome; the default ruleset uses the new 
outcome. This patch also adds a command 'debug murder <player>', which 
is useful for testing the Gameloss code.


diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/common/packets.def freeciv.PR14289/common/packets.def
--- vendor.freeciv.current/common/packets.def   2005-10-13 21:54:24.000000000 
+0100
+++ freeciv.PR14289/common/packets.def  2005-10-15 01:33:13.000000000 +0100
@@ -428,6 +428,7 @@
   UINT8 granary_food_inc;
   UINT8 tech_cost_style;
   UINT8 tech_leakage;
+  UINT8 gameloss_style;
   YEAR tech_cost_double_year;
   BOOL killstack;
   UINT8 autoupgrade_veteran_loss;
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/data/civ1/game.ruleset 
freeciv.PR14289/data/civ1/game.ruleset
--- vendor.freeciv.current/data/civ1/game.ruleset       2005-10-13 
21:54:01.000000000 +0100
+++ freeciv.PR14289/data/civ1/game.ruleset      2005-10-15 01:32:51.000000000 
+0100
@@ -75,6 +75,16 @@
 ;     players (human and AI) which already know the tech.
 tech_leakage = 0
 
+; What happens when a 'GameLoss' unit is destroyed,
+; in addition to the player losing the game.
+; 0 - Cities that the player conquered are returned to their
+;     original owners, were possible. All other units and cities are destroyed.
+;     This is the traditional outcome.
+; 1 - Cities that the player conquered are returned to their
+;     original owners, were possible. Other and cities and units become
+;     barbarians, if possible. Remaining units and cities are destroyed.
+gameloss_style = 0;
+
 ; Research cost doubles after this year. Set to zero to disable.
 tech_cost_double_year = 1
 
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/data/civ2/game.ruleset 
freeciv.PR14289/data/civ2/game.ruleset
--- vendor.freeciv.current/data/civ2/game.ruleset       2005-10-13 
21:54:02.000000000 +0100
+++ freeciv.PR14289/data/civ2/game.ruleset      2005-10-15 01:32:51.000000000 
+0100
@@ -75,6 +75,16 @@
 ;     players (human and AI) which already know the tech.
 tech_leakage = 0
 
+; What happens when a 'GameLoss' unit is destroyed,
+; in addition to the player losing the game.
+; 0 - Cities that the player conquered are returned to their
+;     original owners, were possible. All other units and cities are destroyed.
+;     This is the traditional outcome.
+; 1 - Cities that the player conquered are returned to their
+;     original owners, were possible. Other and cities and units become
+;     barbarians, if possible. Remaining units and cities are destroyed.
+gameloss_style = 0;
+
 ; Research cost doubles after this year. Set to zero to disable.
 tech_cost_double_year = 1
 
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/data/default/game.ruleset 
freeciv.PR14289/data/default/game.ruleset
--- vendor.freeciv.current/data/default/game.ruleset    2005-10-13 
21:54:03.000000000 +0100
+++ freeciv.PR14289/data/default/game.ruleset   2005-10-15 01:32:52.000000000 
+0100
@@ -94,6 +94,16 @@
 ;     players (human and AI) which already know the tech.
 tech_leakage = 0
 
+; What happens when a 'GameLoss' unit is destroyed,
+; in addition to the player losing the game.
+; 0 - Cities that the player conquered are returned to their
+;     original owners, were possible. All other units and cities are destroyed.
+;     This is the traditional outcome.
+; 1 - Cities that the player conquered are returned to their
+;     original owners, were possible. Other and cities and units become
+;     barbarians, if possible. Remaining units and cities are destroyed.
+gameloss_style = 1;
+
 ; Research cost doubles after this year. Set to zero to disable.
 tech_cost_double_year = 0
 
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/data/history/game.ruleset 
freeciv.PR14289/data/history/game.ruleset
--- vendor.freeciv.current/data/history/game.ruleset    2005-10-13 
21:54:12.000000000 +0100
+++ freeciv.PR14289/data/history/game.ruleset   2005-10-15 01:33:01.000000000 
+0100
@@ -75,6 +75,16 @@
 ;     players (human and AI) which already know the tech.
 tech_leakage = 0
 
+; What happens when a 'GameLoss' unit is destroyed,
+; in addition to the player losing the game.
+; 0 - Cities that the player conquered are returned to their
+;     original owners, were possible. All other units and cities are destroyed.
+;     This is the traditional outcome.
+; 1 - Cities that the player conquered are returned to their
+;     original owners, were possible. Other and cities and units become
+;     barbarians, if possible. Remaining units and cities are destroyed.
+gameloss_style = 0;
+
 ; Research cost doubles after this year. Set to zero to disable.
 tech_cost_double_year = 0
 
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/server/barbarian.c freeciv.PR14289/server/barbarian.c
--- vendor.freeciv.current/server/barbarian.c   2005-10-13 21:53:56.000000000 
+0100
+++ freeciv.PR14289/server/barbarian.c  2005-10-15 01:32:46.000000000 +0100
@@ -109,7 +109,7 @@
 
   Dead barbarians forget the map and lose the money.
 **************************************************************************/
-static struct player *create_barbarian_player(bool land)
+struct player *create_barbarian_player(bool land)
 {
   int newplayer = game.info.nplayers;
   struct player *barbarians;
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/server/barbarian.h freeciv.PR14289/server/barbarian.h
--- vendor.freeciv.current/server/barbarian.h   2005-10-13 21:53:56.000000000 
+0100
+++ freeciv.PR14289/server/barbarian.h  2005-10-15 01:32:46.000000000 +0100
@@ -31,5 +31,6 @@
 bool unleash_barbarians(struct tile *ptile);
 void summon_barbarians(void);
 bool is_land_barbarian(struct player *pplayer);
+struct player *create_barbarian_player(bool land);
 
 #endif  /* FC__BARBARIAN_H */
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/server/commands.c freeciv.PR14289/server/commands.c
--- vendor.freeciv.current/server/commands.c    2005-10-13 21:53:56.000000000 
+0100
+++ freeciv.PR14289/server/commands.c   2005-10-15 01:32:46.000000000 +0100
@@ -118,10 +118,11 @@
   },
   {"debug",    ALLOW_CTRL,
    N_("debug [ player <player> | city <x> <y> | units <x> <y> | unit <id> "
-      "| tech <player> | timing | info]"),
-   N_("Turn on or off AI debugging of given entity."),
+      "| tech <player> | timing | info | murder <player> ]"),
+   N_("Turn on or off AI debugging of given entity or do test operations."),
    N_("Print AI debug information about given entity and turn continous "
-      "debugging output for this entity on or off."),
+      "debugging output for this entity on or off, "
+      "or directly perform an action on the entity."),
   },
   {"set",      ALLOW_CTRL,
    N_("set <option-name> <value>"),
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/server/plrhand.c freeciv.PR14289/server/plrhand.c
--- vendor.freeciv.current/server/plrhand.c     2005-10-13 22:20:18.000000000 
+0100
+++ freeciv.PR14289/server/plrhand.c    2005-10-15 01:32:46.000000000 +0100
@@ -34,6 +34,7 @@
 
 #include "script.h"
 
+#include "barbarian.h"
 #include "citytools.h"
 #include "cityturn.h"
 #include "connecthand.h"
@@ -119,12 +120,13 @@
   } players_iterate_end;
 }
 
+static void dispose_player_legacy_remove(struct player *pplayer);
+static void dispose_player_legacy_barbarian(struct player *pplayer);
+
 /**************************************************************************
   Murder a player in cold blood.
 **************************************************************************/
 void kill_player(struct player *pplayer) {
-  bool palace;
-
   pplayer->is_dying = FALSE; /* Can't get more dead than this. */
   pplayer->is_alive = FALSE;
 
@@ -146,16 +148,39 @@
     gamelog(GAMELOG_GENO, pplayer, 
                           "The feared barbarian leader %s is no more");
     return;
-  } else {
-    notify_player(NULL, NULL, E_DESTROYED, _("The %s are no more!"),
-                     get_nation_name_plural(pplayer->nation));
-    gamelog(GAMELOG_GENO, pplayer, "%s civilization destroyed");
   }
+  gamelog(GAMELOG_GENO, pplayer, "%s civilization destroyed");
 
-  /* Transfer back all cities not originally owned by player to their
-     rightful owners, if they are still around */
-  palace = game.info.savepalace;
-  game.info.savepalace = FALSE; /* moving it around is dumb */
+  /* Dispose of the cities and units belonging to the player */
+  switch(game.info.gameloss_style) {
+  case 0:
+    dispose_player_legacy_remove(pplayer);
+    break;
+  case 1:
+    dispose_player_legacy_barbarian(pplayer);
+    break;
+  default: /*never happens */
+    dispose_player_legacy_remove(pplayer);
+    break;
+  }
+
+  /* Ensure this dead player doesn't win with a spaceship.
+   * Now that would be truly unbelievably dumb - Per */
+  spaceship_init(&pplayer->spaceship);
+  send_spaceship_info(pplayer, NULL);
+
+  send_player_info_c(pplayer, game.est_connections);
+}
+
+/**************************************************************************
+  Transfer back all cities not originally owned by player to their
+  rightful owners, if they are still around.
+
+  You should set game.info.savepalace = FALSE before calling this,
+  to prevent palaces moving around.
+**************************************************************************/
+static void return_conquests(struct player *pplayer)
+{
   city_list_iterate(pplayer->cities, pcity) {
     if (pcity->original != pplayer && pcity->original->is_alive) {
       /* Transfer city to original owner, kill all its units outside of
@@ -164,7 +189,13 @@
       transfer_city(pcity->original, pcity, 3, TRUE, TRUE, TRUE);
     }
   } city_list_iterate_end;
+}
 
+/**************************************************************************
+  Remove the units and cities that belonged to a player that is now dead.
+**************************************************************************/
+static void remove_legacy(struct player *pplayer)
+{
   /* Remove all units that are still ours */
   unit_list_iterate_safe(pplayer->units, punit) {
     wipe_unit(punit);
@@ -174,14 +205,85 @@
   city_list_iterate(pplayer->cities, pcity) {
     remove_city(pcity);
   } city_list_iterate_end;
+}
+
+/**************************************************************************
+  Dispose of the units and cities that belonged to a player that is now dead,
+  in the traditional manner: remove anything that can not be returned to its
+  original owner.
+**************************************************************************/
+static void dispose_player_legacy_remove(struct player *pplayer)
+{
+  const bool palace = game.info.savepalace;
+
+  game.info.savepalace = FALSE; /* moving it around is dumb */
+
+  /* Transfer back all cities not originally owned by player to their
+     rightful owners, if they are still around */
+  return_conquests(pplayer);
+  remove_legacy(pplayer);
+
   game.info.savepalace = palace;
 
-  /* Ensure this dead player doesn't win with a spaceship.
-   * Now that would be truly unbelievably dumb - Per */
-  spaceship_init(&pplayer->spaceship);
-  send_spaceship_info(pplayer, NULL);
+  notify_player(NULL, NULL, E_DESTROYED, _("The %s are no more!"),
+                get_nation_name_plural(pplayer->nation));
+}
 
-  send_player_info_c(pplayer, game.est_connections);
+/**************************************************************************
+  Dispose of the units and cities that belonged to a player that is now dead,
+  turning to barbarity were possible.
+**************************************************************************/
+static unsigned fall_to_barbarity(struct player *pplayer,
+                                  struct player *barbarians)
+{
+  unsigned int count = 0;
+
+  city_list_iterate(pplayer->cities, pcity) {
+    /* This will also transfer the units that have the city as a home city */
+    transfer_city(barbarians, pcity, 3, TRUE, TRUE, TRUE);
+    count++;
+  } city_list_iterate_end;
+
+  return count;
+}
+
+/**************************************************************************
+  Dispose of the units and cities that belonged to a player that is now dead,
+  by tring to return them to their original owner or by turning to barbarity.
+**************************************************************************/
+static void dispose_player_legacy_barbarian(struct player *pplayer)
+{
+  struct player *barbarians = create_barbarian_player(FALSE);
+  const bool palace = game.info.savepalace;
+  unsigned int fallen_cities = 0;
+
+  assert(!is_barbarian(pplayer)); /* else indestructable barbarians */
+  game.info.savepalace = FALSE; /* moving it around is dumb */
+
+  /* Transfer back all cities not originally owned by player to their
+     rightful owners, if they are still around */
+  return_conquests(pplayer);
+
+  if (barbarians) {
+    fallen_cities = fall_to_barbarity(pplayer, barbarians);
+  }
+  /* else was unable to create barbarians */
+
+  /* There will be cities and units left, if we were unable to create
+   * a barbarian player.
+   * Units that do not have a home city will also be left. */
+  remove_legacy(pplayer);
+
+  game.info.savepalace = palace;
+
+  if (fallen_cities) {
+    notify_player(NULL, NULL, E_DESTROYED,
+                  _("The %s have fallen into barbarity!"),
+                  get_nation_name_plural(pplayer->nation));
+  } else {
+    notify_player(NULL, NULL, E_DESTROYED, _("The %s are no more!"),
+                  get_nation_name_plural(pplayer->nation));
+  }
 }
 
 /**************************************************************************
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/server/ruleset.c freeciv.PR14289/server/ruleset.c
--- vendor.freeciv.current/server/ruleset.c     2005-10-13 22:20:18.000000000 
+0100
+++ freeciv.PR14289/server/ruleset.c    2005-10-15 01:32:46.000000000 +0100
@@ -2600,6 +2600,14 @@
     freelog(LOG_ERROR, "Switching to tech_leakage 0.");
     game.info.tech_leakage = 0;
   }
+
+  game.info.gameloss_style =
+      secfile_lookup_int(&file, "civstyle.gameloss_style");
+  if (game.info.gameloss_style < 0 || game.info.gameloss_style > 1) {
+    freelog(LOG_ERROR, "Bad value %i for gameloss_style. Using 0.",
+           game.info.gameloss_style);
+    game.info.gameloss_style = 0;
+  }
     
   /* City incite cost */
   game.info.base_incite_cost =
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/server/stdinhand.c freeciv.PR14289/server/stdinhand.c
--- vendor.freeciv.current/server/stdinhand.c   2005-10-13 21:53:56.000000000 
+0100
+++ freeciv.PR14289/server/stdinhand.c  2005-10-15 01:32:46.000000000 +0100
@@ -2188,7 +2188,8 @@
   int ntokens = 0, i;
   const char *usage = _("Undefined arguments. Usage: debug <diplomacy "
                        "<player> | city <x> <y> | units <x> <y> | "
-                       "unit <id> | tech <player> | timing | info>.");
+                       "unit <id> | tech <player> | timing | info| "
+                        "murder <player> >.");
 
   if (server_state != RUN_GAME_STATE) {
     cmd_reply(CMD_DEBUG, caller, C_SYNTAX,
@@ -2354,6 +2355,25 @@
       UNIT_LOG(LOG_NORMAL, punit, _("%s's %s debugged."),
                unit_owner(punit)->name, unit_name(punit->type));
     }
+  } else if (ntokens > 0 && strcmp(arg[0], "murder") == 0) {
+    /* This is more a 'testing' command than a 'debugging' comand,
+     * but we want to ensure it is available only in debugging mode,
+     * and only someone interested in testing & debugging should
+     * be able to use it */
+    struct player *pplayer;
+    enum m_pre_result match_result;
+
+    if (ntokens != 2) {
+      cmd_reply(CMD_DEBUG, caller, C_SYNTAX, usage);
+      goto cleanup;
+    }
+    pplayer = find_player_by_name_prefix(arg[1], &match_result);
+    if (pplayer == NULL) {
+      cmd_reply_no_such_player(CMD_DEBUG, caller, arg[1], match_result);
+      goto cleanup;
+    }
+
+    pplayer->is_dying = TRUE;    
   } else {
     cmd_reply(CMD_DEBUG, caller, C_SYNTAX, usage);
   }

[Prev in Thread] Current Thread [Next in Thread]