Hello all,

playing with the code below,
I notice that neither the new AI (created from civil war) nor the barbarians have a palace in any city.

I have started to debug but, there is a lot of code and I can waste a lot of time on try and error.

Does anyone out there have an inspired guess where I should look first?


Imhotep wrote:
Marko Lindqvist wrote:
On 8 February 2013 22:44, Imhotep <jmho...@slehr.de> wrote:
Hi there,

after trying the wiki and the forum, I'm finally trolling here.
(Not that I intend to troll but, the reactions (or the lack of) make me feel
like that).

I have recently managed to make a first version of the gameloss_style
(See my posts on the forum and the wiki.)
 It's a bit hard to comment on code one doesn't see ;-)
That indicates that you want to see it, so here it is (existing functions after my changes):

in plrhand.c:
  Murder a player in cold blood.

  Called from srv_main kill_dying_players() and edit packet handler
void kill_player(struct player *pplayer)
  bool palace;

  pplayer->is_alive = FALSE;

  /* reset player status */

  /* Remove shared vision from dead player to friends. */
  players_iterate(aplayer) {
    if (gives_shared_vision(pplayer, aplayer)) {
      remove_shared_vision(pplayer, aplayer);
  } players_iterate_end;


  /* Show entire map for players who are *not* in a team if revealmap is set
   * to REVEAL_MAP_DEAD. */
  if (game.server.revealmap & REVEAL_MAP_DEAD
      && player_list_size(team_members(pplayer->team)) == 1) {

  if (!is_barbarian(pplayer)) {
    notify_player(NULL, NULL, E_DESTROYED, ftc_server,
                  _("The %s are no more!"),

  /* Transfer back all cities not originally owned by player to their
     rightful owners, if they are still around */
  palace = game.server.savepalace;
  game.server.savepalace = FALSE; /* moving it around is dumb */
  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
         a radius of 3, give verbose messages of every unit transferred,
         and raze buildings according to raze chance (also removes palace) */
      transfer_city(pcity->original, pcity, 3, TRUE, TRUE, TRUE);
  } city_list_iterate_end;

  /* let there be civil war --- Imhotep */
  //   if (!is_barbarian(pplayer) && (city_list_size(pplayer->cities)>=2)) {
  if ((game.info.gameloss_style & 2) && city_list_size(pplayer->cities) >= GAME_MIN_CIVILWARSIZE) {
    log_verbose("Civil war strikes the remaining empire of %s", pplayer->name);
    /* out of sheer cruelty we reanimate the player so he can behold what happens to his empire */
    pplayer->is_alive = TRUE;
    (void) civil_war(pplayer);
    pplayer->is_alive = FALSE;
   } else {
     log_verbose("The empire of %s is too small for civil war, it vanishes without a trace.", pplayer->name);

  struct player *barbarians = NULL;
  if (game.info.gameloss_style & 1) {
    /* if parameter, create a barbarian, if possible */
    barbarians = create_barbarian_player_land();

  /* if there are barbarians, the will take the remaining cities */
  /* vae victis! */
  if (barbarians)
  { //Imhotep DEBUG
  adv_data_phase_init(barbarians, TRUE);

  /* Transfer any remaining cities */
  city_list_iterate(pplayer->cities, pcity) {
    transfer_city(barbarians, pcity, -1, FALSE, FALSE, FALSE);
  } city_list_iterate_end;
  game.server.savepalace = palace;

  /* Destroy all units that are still ours */
  unit_list_iterate_safe(pplayer->units, punit) {
    wipe_unit(punit, ULR_PLAYER_DIED, NULL);
  } unit_list_iterate_safe_end;

  resolve_unit_stacks(pplayer, barbarians, FALSE);

  /* Choose a capital (random). */
  city_build_free_buildings(city_list_get(barbarians->cities, fc_rand(city_list_size(barbarians->cities))));

  /* Remove ownership of tiles */
  whole_map_iterate(ptile) {
    if (tile_owner(ptile) == pplayer) {
      map_claim_ownership(ptile, NULL, NULL);
  } whole_map_iterate_end;

  } else { // Imhotep

  /* Remove all units that are still ours */
  unit_list_iterate_safe(pplayer->units, punit) {
    wipe_unit(punit, ULR_PLAYER_DIED, NULL);
  } unit_list_iterate_safe_end;

  /* Destroy any remaining cities */
  city_list_iterate(pplayer->cities, pcity) {
  } city_list_iterate_end;
  game.server.savepalace = palace;

  /* Remove ownership of tiles */
  whole_map_iterate(ptile) {
    if (tile_owner(ptile) == pplayer) {
      map_claim_ownership(ptile, NULL, NULL);
  } whole_map_iterate_end;


  /* Ensure this dead player doesn't win with a spaceship.
   * Now that would be truly unbelievably dumb - Per */
  send_spaceship_info(pplayer, NULL);

  send_player_info_c(pplayer, game.est_connections);


The other changes ar just minor things to make the main change work, and probably will change in detail.
Depending on bit 2¹ there is civil war when a GameLoss figure is killed.
Depending on bit 2⁰ the remaining cities fall to the barbarians or
completely vanish without a trace.
(Units go along with their cities, the rest is killed.)

That's all for now, because I'm quite new to the code and I want to
consolidate what I've coded before I make more extensions
(like random benefits for the player that killed the enemy leader or tech
losses for the resulting new AI).
 Note that we (or at least I) prefer contributions in small steps one
can easily validate. It's hard to see from big patch that every part
works as expected. It's much easier if you see each separate step to
get there. No step should break freeciv, though, so they must work on
their own.

That is very reasonable. That is also why I don't like to sit 3 years getting code absolutely perfect,
only to be shocked that the world has changed in the meanwhile.

I really like it when my code has some kind of review each time I dare to publish.
For example, to create the barbarians in plrhand.c I had not only to include
but also I introduced a new function create_barbarian_player_land() in

The reason I introduced a new function was that the
create_barbarian_palyer(enum barbarian_type type)
is static, and I have no idea how to find out if this has a solid reason or
might be only out of cautiousness,
as it is generally a good idea to keep as many functions as possible static.
 As it has not been needed outside the module before, we have wanted
to keep interface minimal. It's probably better to make it non-static
than to add new wrapper function.
OK, then that's what I'll do.
 IIRC, despite the name create_barbarian_player() does not necessarily
create a new player, but might return the existing one as there's at
most 1 barbarian players of each type. Maybe the function name should
be changed when its made non-static so that it would not be so
confusing in the interface.
As for my purpose, that's just the same. Some inline comment indicates that a living barbarian may be reused.

 - ML


Freeciv-dev mailing list

Reply via email to