Complete.Org: Mailing Lists: Archives: freeciv-dev: June 2005:
[Freeciv-Dev] (PR#13211) RFC: redesign of aifill system
Home

[Freeciv-Dev] (PR#13211) RFC: redesign of aifill system

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: jdorje@xxxxxxxxx
Subject: [Freeciv-Dev] (PR#13211) RFC: redesign of aifill system
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 7 Jun 2005 12:07:36 -0700
Reply-to: bugs@xxxxxxxxxxx

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

Here is a patch.

aifill is left as a server setting, but now it is immediate.  When you
first set it, AI players are created or removed to bring the total to
the given number.  Then later any time a player is created or removed,
the aifill is updated again.  This means if you join a game and aifill
5, you'll immediately get 4 extra AI players.  If another human joins
then one of the players is removed.

This basically obsoletes /create and /remove since these are controlled
through aifill (they can be removed later, but I haven't done so in this
patch).  However if the aifill is set to 0 this "turns it off" so then
create and remove will work.

maxplayers is still used as an upper limit and isn't particularly
integrated with the aifill value.  You can't simultaneously decrease the
aifill and the maxplayers.

-jason

Index: server/connecthand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/connecthand.c,v
retrieving revision 1.50
diff -u -r1.50 connecthand.c
--- server/connecthand.c        24 May 2005 16:45:39 -0000      1.50
+++ server/connecthand.c        7 Jun 2005 19:02:25 -0000
@@ -692,6 +692,8 @@
   send_game_info(NULL);
   send_player_info(pplayer, NULL);
 
+  aifill(game.aifill);
+
   return TRUE;
 }
   
Index: server/settings.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settings.c,v
retrieving revision 1.25
diff -u -r1.25 settings.c
--- server/settings.c   10 May 2005 17:27:09 -0000      1.25
+++ server/settings.c   7 Jun 2005 19:02:25 -0000
@@ -24,6 +24,7 @@
 #include "gamelog.h"
 #include "report.h"
 #include "settings.h"
+#include "srv_main.h"
 #include "stdinhand.h"
 
 /* Category names must match the values in enum sset_category. */
@@ -160,6 +161,16 @@
   return TRUE;
 }
 
+/*************************************************************************
+  Create/remove players when aifill is set.
+*************************************************************************/
+static bool aifill_callback(int value, const char **error_string)
+{
+  aifill(value);
+  error_string = NULL;
+  return TRUE;
+}
+
 #define GEN_BOOL(name, value, sclass, scateg, slevel, to_client,       \
                 short_help, extra_help, func, default)                 \
   {name, sclass, to_client, short_help, extra_help, SSET_BOOL,         \
@@ -397,10 +408,9 @@
   GEN_INT("aifill", game.aifill,
          SSET_PLAYERS, SSET_INTERNAL, SSET_VITAL, SSET_TO_CLIENT,
          N_("Total number of players (including AI players)"),
-         N_("If there are fewer than this many players when the "
-            "game starts, extra AI players will be created to "
-            "increase the total number of players to the value of "
-            "this option."), NULL, 
+         N_("If set to a positive value, then AI players will be "
+            "automatically created or removed to keep the total "
+            "number of players at this amount."), aifill_callback,
          GAME_MIN_AIFILL, GAME_MAX_AIFILL, GAME_DEFAULT_AIFILL)
 
   /* Game initialization parameters (only affect the first start of the game,
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.267
diff -u -r1.267 srv_main.c
--- server/srv_main.c   4 Jun 2005 18:11:25 -0000       1.267
+++ server/srv_main.c   7 Jun 2005 19:02:26 -0000
@@ -1409,6 +1409,75 @@
   return available[i];
 }
 
+/****************************************************************************
+  Fill or remove players to meet the given aifill.
+****************************************************************************/
+void aifill(int amount)
+{
+  int observers = 0, remove;
+  static int filled = 0;
+
+  if (amount == 0) {
+    /* Special case for value 0: do nothing. */
+    return;
+  }
+
+  amount = MIN(amount, game.info.max_players);
+
+  /* we don't want aifill to count global observers unless 
+   * aifill = MAX_NUM_PLAYERS */
+  players_iterate(pplayer) {
+    if (pplayer->is_observer) {
+      observers++;
+    }
+  } players_iterate_end;
+  if (amount == game.info.max_players) {
+    observers = 0;
+  }
+
+  while (game.info.nplayers < amount + observers) {
+    const int old_nplayers = game.info.nplayers;
+    struct player *pplayer = get_player(old_nplayers);
+    char player_name[ARRAY_SIZE(pplayer->name)];
+
+    server_player_init(pplayer, FALSE, TRUE);
+    pplayer->nation = NO_NATION_SELECTED;
+    do {
+      my_snprintf(player_name, sizeof(player_name),
+                 "AI %d", ++filled);
+    } while (find_player_by_name(player_name));
+    sz_strlcpy(pplayer->name, player_name);
+    sz_strlcpy(pplayer->username, ANON_USER_NAME);
+    pplayer->ai.skill_level = game.info.skill_level;
+    pplayer->ai.control = TRUE;
+    set_ai_level_directer(pplayer, game.info.skill_level);
+
+    freelog(LOG_NORMAL,
+           _("%s has been added as %s level AI-controlled player."),
+            pplayer->name,
+           name_of_skill_level(pplayer->ai.skill_level));
+    notify_player(NULL,
+                  _("%s has been added as %s level AI-controlled player."),
+                 pplayer->name,
+                 name_of_skill_level(pplayer->ai.skill_level));
+
+    game.info.nplayers++;
+
+    send_game_info(NULL);
+    send_player_info(pplayer, NULL);
+  }
+
+  remove = game.info.nplayers - 1;
+  while (game.info.nplayers > amount + observers && remove > 0) {
+    struct player *pplayer = get_player(remove);
+
+    if (!pplayer->is_observer && !pplayer->is_connected) {
+      server_remove_player(pplayer);
+    }
+    remove--;
+  }
+}
+
 /**************************************************************************
 generate_ai_players() - Selects a nation for players created with
    server's "create <PlayerName>" command.  If <PlayerName> matches
@@ -1417,11 +1486,6 @@
    nation the Zulus if the Zulus have not been chosen by anyone else.
    If they have, then we pick an available nation at random.)
 
-   After that, we check to see if the server option "aifill" is greater
-   than the number of players currently connected.  If so, we create the
-   appropriate number of players (game.aifill - game.info.nplayers) from
-   scratch, choosing a random nation and appropriate name for each.
-   
    If the AI player name is one of the leader names for the AI player's
    nation, the player sex is set to the sex for that leader, else it
    is chosen randomly.  (So if English are ruled by Elisabeth, she is
@@ -1430,8 +1494,6 @@
 static void generate_players(void)
 {
   Nation_type_id nation;
-  char player_name[MAX_LEN_NAME];
-  int i;
 
   /* Select nations for AI players generated with server
    * 'create <name>' command
@@ -1473,77 +1535,7 @@
 
     announce_player(pplayer);
   } players_iterate_end;
-  
-  /* Create and pick nation and name for AI players needed to bring the
-   * total number of players to equal game.aifill
-   */
-
-  if (game.control.playable_nation_count < game.aifill) {
-    game.aifill = game.control.playable_nation_count;
-    freelog(LOG_NORMAL,
-            _("Nation count smaller than aifill; aifill reduced to %d."),
-             game.control.playable_nation_count);
-  }
-
-  if (game.info.max_players < game.aifill) {
-    game.aifill = game.info.max_players;
-    freelog(LOG_NORMAL,
-            _("Maxplayers smaller than aifill; aifill reduced to %d."),
-             game.info.max_players);
-  }
-
-  /* we don't want aifill to count global observers unless 
-   * aifill = MAX_NUM_PLAYERS */
-  i = 0;
-  players_iterate(pplayer) {
-    if (pplayer->is_observer) {
-      i++;
-    }
-  } players_iterate_end;
-  if (game.aifill == MAX_NUM_PLAYERS) {
-    i = 0;
-  }
-
-  for(;game.info.nplayers < game.aifill + i;) {
-    const int old_nplayers = game.info.nplayers;
-    struct player *pplayer = get_player(old_nplayers);
-
-    server_player_init(pplayer, FALSE, TRUE);
 
-    nation = select_random_nation();
-    assert(nation != NO_NATION_SELECTED);
-    get_nation_by_idx(nation)->is_used = TRUE;
-    pick_random_player_name(nation, player_name);
-
-    sz_strlcpy(pplayer->name, player_name);
-    sz_strlcpy(pplayer->username, ANON_USER_NAME);
-
-    pplayer->ai.skill_level = game.info.skill_level;
-    freelog(LOG_NORMAL, _("%s has been added as %s level AI-controlled 
player."),
-            player_name, name_of_skill_level(pplayer->ai.skill_level));
-    notify_player(NULL,
-                  _("%s has been added as %s level AI-controlled player."),
-                  player_name, name_of_skill_level(pplayer->ai.skill_level));
-
-    game.info.nplayers++;
-
-    if (!((game.info.nplayers == old_nplayers+1)
-         && strcmp(player_name, pplayer->name)==0)) {
-      con_write(C_FAIL, _("Error creating new AI player: %s\n"),
-               player_name);
-      break;                   /* don't loop forever */
-    }
-      
-    pplayer->nation = nation;
-    pplayer->city_style = get_nation_city_style(nation);
-    pplayer->ai.control = TRUE;
-    if (check_nation_leader_name(nation, player_name)) {
-      pplayer->is_male = get_nation_leader_sex(nation, player_name);
-    } else {
-      pplayer->is_male = (myrand(2) == 1);
-    }
-    set_ai_level_directer(pplayer, pplayer->ai.skill_level);
-  }
   (void) send_server_info_to_metaserver(META_INFO);
 }
 
Index: server/srv_main.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.h,v
retrieving revision 1.33
diff -u -r1.33 srv_main.h
--- server/srv_main.h   7 May 2005 05:44:43 -0000       1.33
+++ server/srv_main.h   7 Jun 2005 19:02:26 -0000
@@ -69,6 +69,7 @@
 void server_game_init(void);
 void server_game_free(void);
 void check_for_full_turn_done(void);
+void aifill(int amount);
 
 extern struct server_arguments srvarg;
 
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.417
diff -u -r1.417 stdinhand.c
--- server/stdinhand.c  4 Jun 2005 18:20:24 -0000       1.417
+++ server/stdinhand.c  7 Jun 2005 19:02:26 -0000
@@ -926,6 +926,7 @@
   set_ai_level_directer(pplayer, game.info.skill_level);
   send_game_info(NULL);
   send_player_info(pplayer, NULL);
+  aifill(game.aifill);
   reset_all_start_commands();
   (void) send_server_info_to_metaserver(META_INFO);
   return TRUE;
@@ -963,6 +964,7 @@
     cmd_reply(CMD_REMOVE, caller, C_OK,
              _("Removed player %s from the game."), name);
   }
+  aifill(game.aifill);
   return TRUE;
 }
 

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