Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2005:
[Freeciv-Dev] Re: (PR#13717) Karma
Home

[Freeciv-Dev] Re: (PR#13717) Karma

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: per@xxxxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#13717) Karma
From: "Peter Schaefer" <peter.schaefer@xxxxxxxxx>
Date: Sat, 20 Aug 2005 08:43:57 -0700
Reply-to: bugs@xxxxxxxxxxx

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

So I can improve my Karma by building nuclears and militia and then
disbanding them?
Weird ;-)

Wouldn't it be more useful to have a structured karma tracking with
several kategories? Then you could have several different punishments
for different transgressions .. For example, why should barbarians
punish you for pollution, not the traditional Godzilla or the AC
fauna?

Also, does this mean the Eiffel Tower wonder will be back?

On 8/20/05, Per I. Mathisen <per@xxxxxxxxxxx> wrote:
> 
> <URL: http://bugs.freeciv.org/Ticket/Display.html?id=13717 >
> 
> This patch adds a new game concept: Karma.
> 
> A new concept of 'karma' is introduced. This is meant to balance out some
> game strategies that we can deem somehow 'evil'. What comes around comes
> around. The chickens come home to roost. And so on. The idea is that if
> you carry out stuff that others see as evil, it (or rather, they) will
> come back to haunt you.
> 
> Eventually, this will be used (or that is the idea) to generate barbarians
> in a not-random, but also not-predictable manner that can be used also in
> multiplayer games. I would also like to use it to balance the 'raze city'
> functionality I want to add.
> 
> See http://www.freeciv.org/index.php/Barbarians for the full plans and
> karma description.
> 
> In this patch, all that it does is that players with positive karma (a
> rare thing), will never generate barbarians from huts. This is the only
> benefit from having positive karma I plan to add.
> 
>   - Per
> 
> 
> 
> Index: server/cityturn.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/server/cityturn.c,v
> retrieving revision 1.331
> diff -u -r1.331 cityturn.c
> --- server/cityturn.c   18 Aug 2005 06:44:28 -0000      1.331
> +++ server/cityturn.c   20 Aug 2005 13:42:59 -0000
> @@ -529,6 +529,8 @@
>  **************************************************************************/
>  static void city_populate(struct city *pcity)
>  {
> +  struct player *pplayer = city_owner(pcity);
> +
>    pcity->food_stock += pcity->surplus[O_FOOD];
>    if (pcity->food_stock >= city_granary_size(pcity->size)
>       || city_rapture_grow(pcity)) {
> @@ -551,6 +553,7 @@
> 
>          gamelog(GAMELOG_UNITLOSS, punit, NULL, "famine");
>          wipe_unit(punit);
> +        pplayer->karma += KARMA_FAMINE_UNIT_LOSS;
> 
>         pcity->food_stock = (city_granary_size(pcity->size)
>                              * granary_savings(pcity)) / 100;
> @@ -561,9 +564,11 @@
>        notify_player_ex(city_owner(pcity), pcity->tile, E_CITY_FAMINE,
>                        _("Famine causes population loss in %s."),
>                        pcity->name);
> +      pplayer->karma += KARMA_FAMINE_CITY_REDUCTION;
>      } else {
>        notify_player_ex(city_owner(pcity), pcity->tile, E_CITY_FAMINE,
>                        _("Famine destroys %s entirely."), pcity->name);
> +      pplayer->karma += KARMA_FAMINE_CITY_LOSS;
>      }
>      pcity->food_stock = (city_granary_size(pcity->size - 1)
>                          * granary_savings(pcity)) / 100;
> @@ -1001,6 +1006,7 @@
>                          _("%s can't upkeep %s, unit disbanded."),
>                          pcity->name, unit_type(punit)->name);
>          handle_unit_disband(pplayer, punit->id);
> +        pplayer->karma += KARMA_DISBAND_UNSUPPORTABLE;
>         /* pcity->surplus[O_SHIELD] is automatically updated. */
>        }
>      } unit_list_iterate_safe_end;
> @@ -1019,6 +1025,7 @@
>         notify_player_ex(pplayer, pcity->tile, E_UNIT_LOST,
>                          _("Citizens in %s perish for their failure to "
>                          "upkeep %s!"), pcity->name, unit_type(punit)->name);
> +        pplayer->karma += KARMA_FAMINE_UNIT_UNDISBANDABLE;
>         if (!city_reduce_size(pcity, 1)) {
>           return FALSE;
>         }
> @@ -1222,6 +1225,7 @@
>         (food) needed. */
>      if (pop_cost > 0) {
>        city_reduce_size(pcity, pop_cost);
> +      pplayer->karma += KARMA_BUILD_UNIT_POPLOSS * pop_cost;
>      }
> 
>      /* to eliminate micromanagement, we only subtract the unit's
> @@ -1287,11 +1291,15 @@
>  }
> 
>  /**************************************************************************
> - Add some Pollution if we have waste
> +  Maybe pollute some tiles if we have pollution.
>  **************************************************************************/
>  static void check_pollution(struct city *pcity)
>  {
> +  struct player *pplayer = city_owner(pcity);
>    int k=100;
> +
> +  pplayer->karma += KARMA_POLLUTION * pcity->pollution;
> +
>    if (pcity->pollution != 0 && myrand(100) <= pcity->pollution) {
>      while (k > 0) {
>        /* place pollution somewhere in city radius */
> @@ -1309,7 +1317,7 @@
>           && !tile_has_special(ptile, S_POLLUTION)) {
>         tile_set_special(ptile, S_POLLUTION);
>         update_tile_knowledge(ptile);
> -       notify_player_ex(city_owner(pcity), pcity->tile,
> +       notify_player_ex(pplayer, pcity->tile,
>                          E_POLLUTION, _("Pollution near %s."),
>                          pcity->name);
>         return;
> Index: server/diplhand.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/server/diplhand.c,v
> retrieving revision 1.100
> diff -u -r1.100 diplhand.c
> --- server/diplhand.c   20 Jul 2005 18:28:48 -0000      1.100
> +++ server/diplhand.c   20 Aug 2005 13:43:00 -0000
> @@ -340,6 +340,7 @@
>                           _("%s allowed you to create an embassy!"),
>                           pgiver->name);
>          gamelog(GAMELOG_TREATY, GL_EMBASSY, pgiver, pdest);
> +        pgiver += KARMA_GAVE_EMBASSY;
>          break;
>        case CLAUSE_ADVANCE:
>          /* It is possible that two players open the diplomacy dialog
> @@ -370,7 +371,7 @@
>          gamelog(GAMELOG_TECH, pdest, pgiver, pclause->value, "acquire");
>          gamelog(GAMELOG_TREATY, GL_TECH, pgiver, pdest);
>         do_dipl_cost(pdest, pclause->value);
> -
> +        pgiver->karma += KARMA_GAVE_TECH;
>         found_new_tech(pdest, pclause->value, FALSE, TRUE);
>         break;
>        case CLAUSE_GOLD:
> @@ -434,6 +435,11 @@
>         check_city_workers(pother);
>         break;
>        case CLAUSE_PEACE:
> +        if (pgiver->diplstates[pdest->player_no].max_state < DS_PEACE) {
> +          /* This bonus given only once */
> +          pgiver->karma += KARMA_FIRST_PEACE;
> +          pdest->karma += KARMA_FIRST_PEACE;
> +        }
>         pgiver->diplstates[pdest->player_no].type=DS_PEACE;
>         pdest->diplstates[pgiver->player_no].type=DS_PEACE;
>         pgiver->diplstates[pdest->player_no].max_state =
> @@ -454,6 +460,11 @@
>         check_city_workers(pother);
>         break;
>        case CLAUSE_ALLIANCE:
> +        if (pgiver->diplstates[pdest->player_no].max_state < DS_ALLIANCE) {
> +          /* This bonus given only once */
> +          pgiver->karma += KARMA_FIRST_ALLIANCE;
> +          pdest->karma += KARMA_FIRST_ALLIANCE;
> +        }
>         pgiver->diplstates[pdest->player_no].type=DS_ALLIANCE;
>         pdest->diplstates[pgiver->player_no].type=DS_ALLIANCE;
>         pgiver->diplstates[pdest->player_no].max_state =
> Index: server/diplomats.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/server/diplomats.c,v
> retrieving revision 1.90
> diff -u -r1.90 diplomats.c
> --- server/diplomats.c  26 Jul 2005 16:36:00 -0000      1.90
> +++ server/diplomats.c  20 Aug 2005 13:43:01 -0000
> @@ -104,7 +104,8 @@
>    freelog (LOG_DEBUG, "poison: succeeded");
> 
>    /* Poison people! */
> -  city_reduce_size(pcity, 1);
> +  city_reduce_size(pcity, 1); /* random amount? not used as is now */
> +  pplayer->karma += KARMA_DIPLOMAT_POISON;
> 
>    /* Notify everybody involved. */
>    notify_player_ex(pplayer, pcity->tile, E_MY_DIPLOMAT_POISON,
> @@ -994,6 +995,7 @@
> 
>    /* this may cause a diplomatic incident */
>    maybe_cause_incident(DIPLOMAT_SABOTAGE, pplayer, NULL, pcity);
> +  pplayer->karma += KARMA_DIPLOMAT_SABOTAGE;
> 
>    /* Check if a spy survives her mission. Diplomats never do. */
>    diplomat_escape(pplayer, pdiplomat, pcity);
> Index: server/plrhand.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v
> retrieving revision 1.410
> diff -u -r1.410 plrhand.c
> --- server/plrhand.c    18 Aug 2005 18:30:08 -0000      1.410
> +++ server/plrhand.c    20 Aug 2005 13:43:05 -0000
> @@ -609,6 +606,11 @@
>    }
>    if (new_type == DS_WAR) {
>      ai_incident_war(pplayer, pplayer2);
> +    if (pplayer->diplstates[pplayer2->player_no].has_reason_to_cancel <= 0) {
> +      pplayer->karma += KARMA_WAR_UNPROVOKED;
> +    } else {
> +      pplayer->karma += KARMA_WAR_PROVOKED;
> +    }
>    }
>    pplayer->diplstates[pplayer2->player_no].has_reason_to_cancel = 0;
> 
> Index: server/plrhand.h
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/server/plrhand.h,v
> retrieving revision 1.80
> diff -u -r1.80 plrhand.h
> --- server/plrhand.h    18 Jul 2005 22:46:29 -0000      1.80
> +++ server/plrhand.h    20 Aug 2005 13:43:06 -0000
> @@ -102,4 +102,53 @@
> 
>  void update_players_after_alliance_breakup(struct player* pplayer,
>                                            struct player* pplayer2);
> +
> +/* Karma
> + *
> + * Karma is not about why you do something, but about the
> + * consequences of your actions spreading like ripples in the
> + * water. */
> +
> +/* Negative karma. Pretty much anything but sitting on your ass
> + * will generate some bad karma. */
> +#define KARMA_FAMINE_UNIT_LOSS          -5
> +#define KARMA_FAMINE_CITY_REDUCTION    -20
> +#define KARMA_FAMINE_UNIT_UNDISBANDABLE        -40
> +#define KARMA_FAMINE_CITY_LOSS         -60
> +#define KARMA_DISBAND_UNSUPPORTABLE     -5
> +/* moving lots of people around penalty */
> +#define KARMA_BUILD_UNIT_POPLOSS        -5
> +/* just because there is not a big fancy civ there, does not mean
> + * the territory is not populated; the original population of hunters
> + * and gatherers may not be thrilled to see you settling in their back
> + * yard... */
> +#define KARMA_BUILD_CITY               -10
> +#define KARMA_EXPLODE_NUCLEAR         -200
> +#define KARMA_POLLUTION                         -1
> +#define KARMA_WAR_UNPROVOKED           -40
> +#define KARMA_WAR_PROVOKED              -5
> +/* mining is usually slavery and/or highly destructive to nature */
> +#define KARMA_TERRAIN_MINE              -5
> +/* transforming terrain disrupts nature and/or aboriginal peoples */
> +#define KARMA_TERRAIN_TRANSFORM                -15
> +#define KARMA_DIPLOMAT_POISON         -100
> +#define KARMA_DIPLOMAT_SABOTAGE                 -5
> +#define KARMA_CITY_RAIDED              -20
> +
> +/* Positive karma. It is much like the Nobel's Peace Prize -
> + * if you do something horrible and then clean up after yourself,
> + * then you are a hero; but if you never did something bad, you
> + * are just nobody. Sigh. */
> +#define KARMA_DISBAND_MILITARY           5
> +#define KARMA_DISBAND_NUCLEAR           20
> +#define KARMA_CLEAN_POLLUTION           10
> +#define KARMA_CLEAN_FALLOUT             20
> +#define KARMA_GAVE_EMBASSY              50
> +#define KARMA_GAVE_TECH                         10
> +#define KARMA_FIRST_PEACE              100
> +#define KARMA_FIRST_ALLIANCE            50
> +
> +/* Cost of bad stuff, fuelled by negative karma. */
> +#define KARMA_BARBARIAN_COST           100
> +
>  #endif  /* FC__PLRHAND_H */
> Index: server/savegame.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
> retrieving revision 1.275
> diff -u -r1.275 savegame.c
> --- server/savegame.c   18 Aug 2005 06:44:29 -0000      1.275
> +++ server/savegame.c   20 Aug 2005 13:43:10 -0000
> @@ -1760,6 +1752,7 @@
> 
>    plr->nturns_idle=0;
>    plr->is_male=secfile_lookup_bool_default(file, TRUE, "player%d.is_male", 
> plrno);
> +  plr->karma = secfile_lookup_int_default(file, 0, "player%d.karma", plrno);
>    plr->is_alive=secfile_lookup_bool(file, "player%d.is_alive", plrno);
>    plr->is_observer=secfile_lookup_bool_default(file, FALSE,
>                                                 "player%d.is_observer", 
> plrno);
> @@ -2506,6 +2499,7 @@
>                        "player%d.city_style_by_name", plrno);
> 
>    secfile_insert_bool(file, plr->is_male, "player%d.is_male", plrno);
> +  secfile_insert_int(file, plr->karma, "player%d.karma", plrno);
>    secfile_insert_bool(file, plr->is_alive, "player%d.is_alive", plrno);
>    secfile_insert_bool(file, plr->is_observer, "player%d.is_observer", plrno);
>    secfile_insert_bool(file, plr->ai.control, "player%d.ai.control", plrno);
> Index: server/unithand.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
> retrieving revision 1.346
> diff -u -r1.346 unithand.c
> --- server/unithand.c   26 Jul 2005 16:36:00 -0000      1.346
> +++ server/unithand.c   20 Aug 2005 13:43:18 -0000
> @@ -35,7 +35,6 @@
>  #include "shared.h"
>  #include "unit.h"
> 
> -#include "barbarian.h"
>  #include "citytools.h"
>  #include "cityturn.h"
>  #include "diplomats.h"
> @@ -389,6 +388,13 @@
>      send_city_info(city_owner(pcity), pcity);
>    }
> 
> +  if (is_military_unit(punit)) {
> +    if (unit_flag(punit, F_NUCLEAR)) {
> +      pplayer->karma += KARMA_DISBAND_NUCLEAR;
> +    } else {
> +      pplayer->karma += KARMA_DISBAND_MILITARY;
> +    }
> +  }
>    wipe_unit(punit);
>  }
> 
> @@ -529,12 +535,14 @@
> 
>    res = test_unit_add_or_build_city(punit);
> 
> -  if (res == AB_BUILD_OK)
> +  if (res == AB_BUILD_OK) {
>      city_build(pplayer, punit, name);
> -  else if (res == AB_ADD_OK)
> +  } else if (res == AB_ADD_OK) {
>      city_add_unit(pplayer, punit);
> -  else
> +    pplayer->karma += KARMA_BUILD_CITY;
> +  } else {
>      city_add_or_build_error(pplayer, punit, res);
> +  }
>  }
> 
>  /**************************************************************************
> Index: server/unittools.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
> retrieving revision 1.375
> diff -u -r1.375 unittools.c
> --- server/unittools.c  13 Aug 2005 05:27:24 -0000      1.375
> +++ server/unittools.c  20 Aug 2005 13:43:20 -0000
> @@ -729,6 +729,7 @@
>      if (total_activity(ptile, ACTIVITY_POLLUTION)
>         >= tile_activity_time(ACTIVITY_POLLUTION, ptile)) {
>        tile_clear_special(ptile, S_POLLUTION);
> +      pplayer->karma += KARMA_CLEAN_POLLUTION;
>        unit_activity_done = TRUE;
>      }
>    }
> @@ -737,6 +738,7 @@
>      if (total_activity(ptile, ACTIVITY_FALLOUT)
>         >= tile_activity_time(ACTIVITY_FALLOUT, ptile)) {
>        tile_clear_special(ptile, S_FALLOUT);
> +      pplayer->karma += KARMA_CLEAN_FALLOUT;
>        unit_activity_done = TRUE;
>      }
>    }
> @@ -804,6 +806,7 @@
>        struct terrain *old = tile_get_terrain(ptile);
> 
>        tile_apply_activity(ptile, ACTIVITY_MINE);
> +      pplayer->karma += KARMA_TERRAIN_MINE;
>        check_terrain_change(ptile, old);
>        unit_activity_done = TRUE;
>        check_adjacent_units = TRUE;
> @@ -816,6 +819,7 @@
>        struct terrain *old = tile_get_terrain(ptile);
> 
>        tile_apply_activity(ptile, ACTIVITY_TRANSFORM);
> +      pplayer->karma += KARMA_TERRAIN_TRANSFORM;
>        check_terrain_change(ptile, old);
>        unit_activity_done = TRUE;
>        check_adjacent_units = TRUE;
> @@ -1995,6 +1999,7 @@
> 
>    notify_conn_ex(game.game_connections, ptile, E_NUKE,
>                  _("%s detonated a nuke!"), pplayer->name);
> +  pplayer->karma += KARMA_EXPLODE_NUCLEAR;
>  }
> 
>  /**************************************************************************
> @@ -2183,7 +2188,8 @@
>    bool ok = TRUE;
> 
>    if (city_exists_within_city_radius(punit->tile, TRUE)
> -      || unit_flag(punit, F_GAMELOSS)) {
> +      || unit_flag(punit, F_GAMELOSS)
> +      || pplayer->karma >= 0) {
>      notify_player_ex(pplayer, punit->tile, E_HUT_BARB_CITY_NEAR,
>                      _("An abandoned village is here."));
>    } else {
> Index: common/player.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/common/player.c,v
> retrieving revision 1.190
> diff -u -r1.190 player.c
> --- common/player.c     18 Aug 2005 06:44:28 -0000      1.190
> +++ common/player.c     20 Aug 2005 14:11:11 -0000
> @@ -108,6 +115,7 @@
>    sz_strlcpy(plr->name, ANON_PLAYER_NAME);
>    sz_strlcpy(plr->username, ANON_USER_NAME);
>    plr->is_male = TRUE;
> +  plr->karma = 0;
>    plr->government = NULL;
>    plr->target_government = NULL;
>    plr->nation = NO_NATION_SELECTED;
> Index: common/player.h
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
> retrieving revision 1.163
> diff -u -r1.163 player.h
> --- common/player.h     18 Aug 2005 06:44:28 -0000      1.163
> +++ common/player.h     20 Aug 2005 14:11:11 -0000
> @@ -154,6 +142,7 @@
>    char name[MAX_LEN_NAME];
>    char username[MAX_LEN_NAME];
>    bool is_male;
> +  int karma;
>    struct government *government; /* may be NULL in pregame */
>    struct government *target_government; /* may be NULL */
>    struct nation_type *nation;
> 
> 
>





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