Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2005:
[Freeciv-Dev] (PR#12668) Change how to win the game
Home

[Freeciv-Dev] (PR#12668) Change how to win the game

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12668) Change how to win the game
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Sun, 24 Apr 2005 15:22:59 -0700
Reply-to: bugs@xxxxxxxxxxx

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

Another attempt:
 - Add /surrender command. This marks you as willing to concede the game.
 - If all but one player (or team) has either died or conceded (by
   /surrender), then the game ends in victory to this player (or team).
 - /endgame is made a hack level command that ends the game in a draw.

Also fixes team victory conditions and removes some no longer needed code.

Opinions?

  - Per

Index: ai/aicity.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v
retrieving revision 1.213
diff -u -r1.213 aicity.c
--- ai/aicity.c 23 Apr 2005 17:40:21 -0000      1.213
+++ ai/aicity.c 24 Apr 2005 22:16:24 -0000
@@ -239,9 +239,7 @@
   struct impr_type *pimpr = get_improvement_type(id);
   int v = 0;
   int cities[REQ_RANGE_LAST];
-  int nplayers = game.nplayers
-                 - game.nbarbarians
-                 - team_count_members_alive(pplayer->team);
+  int nplayers = game.nplayers - game.nbarbarians;
   struct ai_data *ai = ai_data_get(pplayer);
   struct tile *ptile = pcity->tile;
   bool capital = is_capital(pcity);
@@ -251,6 +249,15 @@
     .value = {.building = id}
   };
 
+  /* Remove team members from the equation */
+  players_iterate(aplayer) {
+    if (aplayer->team != TEAM_NONE
+        && aplayer->team == pplayer->team
+        && aplayer != pplayer) {
+      nplayers--;
+    }
+  } players_iterate_end;
+
   /* Base want is calculated above using a more direct approach. */
   v += base_want(pplayer, pcity, id);
   if (v != 0) {
Index: common/nation.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/nation.c,v
retrieving revision 1.45
diff -u -r1.45 nation.c
--- common/nation.c     13 Apr 2005 02:13:49 -0000      1.45
+++ common/nation.c     24 Apr 2005 22:16:24 -0000
@@ -343,26 +343,6 @@
 }
 
 /***************************************************************
-  Count living members of given team
-***************************************************************/
-int team_count_members_alive(Team_Type_id id)
-{
-  struct team *pteam = team_get_by_id(id);
-  int count = 0;
-
-  if (pteam == NULL) {
-    return 0;
-  }
-  assert(pteam->id < MAX_NUM_TEAMS && pteam->id != TEAM_NONE);
-  players_iterate(pplayer) {
-    if (pplayer->is_alive && pplayer->team == pteam->id) {
-      count++;
-    }
-  } players_iterate_end;
-  return count;
-}
-
-/***************************************************************
   Set a player to a team. Removes previous team affiliation,
   creates a new team if it does not exist.
 ***************************************************************/
Index: common/nation.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/nation.h,v
retrieving revision 1.42
diff -u -r1.42 nation.h
--- common/nation.h     13 Apr 2005 02:13:49 -0000      1.42
+++ common/nation.h     24 Apr 2005 22:16:24 -0000
@@ -129,7 +129,6 @@
 struct team *team_get_by_id(Team_Type_id id);
 void team_add_player(struct player *pplayer, const char *team_name);
 void team_remove_player(struct player *pplayer);
-int team_count_members_alive(Team_Type_id id);
 
 struct nation_group* add_new_nation_group(const char* name);
 int get_nation_groups_count(void);
Index: common/player.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.c,v
retrieving revision 1.174
diff -u -r1.174 player.c
--- common/player.c     23 Apr 2005 17:40:27 -0000      1.174
+++ common/player.c     24 Apr 2005 22:16:28 -0000
@@ -121,6 +121,7 @@
   plr->was_created = FALSE;
   plr->is_alive=TRUE;
   plr->is_dying = FALSE;
+  plr->surrendered = FALSE;
   plr->embassy=0;
   plr->reputation=GAME_DEFAULT_REPUTATION;
   for(i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
Index: common/player.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
retrieving revision 1.145
diff -u -r1.145 player.h
--- common/player.h     19 Apr 2005 22:05:58 -0000      1.145
+++ common/player.h     24 Apr 2005 22:16:28 -0000
@@ -198,6 +198,7 @@
   bool is_alive;
   bool is_observer; /* is the player a global observer */ 
   bool is_dying; /* set once the player is in the process of dying */
+  bool surrendered; /* has indicated willingness to surrender */
 
   /* Turn in which the player's revolution is over; see update_revolution. */
   int revolution_finishes;
Index: server/commands.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/commands.c,v
retrieving revision 1.9
diff -u -r1.9 commands.c
--- server/commands.c   19 Apr 2005 22:05:58 -0000      1.9
+++ server/commands.c   24 Apr 2005 22:16:28 -0000
@@ -310,12 +310,18 @@
       "to <turn> and multiply <value> by <valuemult>.  Use this command in "
       "concert with the option \"timeout\". Defaults are 0 0 0 1")
   },
-  {"endgame",  ALLOW_CTRL,
+  {"endgame",  ALLOW_HACK,
    /* TRANS: translate text between <> only */
-   N_("endgame <player1 player2 player3 ...>"),
-   N_("End the game.  If players are listed, these win the game."),
-   N_("This command ends the game immediately and credits the given players, "
-      "if any, with winning it.")
+   N_("endgame"),
+   N_("End the game immediately in a draw."), NULL,
+  },
+  {"surrender",        ALLOW_INFO,
+   /* TRANS: translate text between <> only */
+   N_("surrender"),
+   N_("Concede the game."),
+   N_("This tells everyone else that you concede the game, and if all "
+      "but one player (or one team) have conceded the game in this way "
+      "then the game ends."),
   },
   {"remove",   ALLOW_CTRL,
    /* TRANS: translate text between <> only */
Index: server/commands.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/commands.h,v
retrieving revision 1.5
diff -u -r1.5 commands.h
--- server/commands.h   25 Mar 2005 11:25:09 -0000      1.5
+++ server/commands.h   24 Apr 2005 22:16:28 -0000
@@ -75,6 +75,7 @@
 
   /* potentially harmful: */
   CMD_END_GAME,
+  CMD_SURRENDER, /* not really harmful, info level */
   CMD_REMOVE,
   CMD_SAVE,
   CMD_LOAD,
Index: server/gamelog.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gamelog.c,v
retrieving revision 1.45
diff -u -r1.45 gamelog.c
--- server/gamelog.c    23 Apr 2005 17:40:29 -0000      1.45
+++ server/gamelog.c    24 Apr 2005 22:16:28 -0000
@@ -632,20 +632,6 @@
     }
   } players_iterate_end;
 
-  /* Draws and team victories */
-  count = 0;
-  players_iterate(pplayer) {
-    if (!is_barbarian(pplayer)) {
-      if ((BV_ISSET_ANY(srvarg.draw)
-           && BV_ISSET(srvarg.draw, pplayer->player_no))
-          || players_on_same_team(pplayer, highest_plr)) {
-        /* We win a shared victory, so equal the score. */
-        rank[count].value = highest;
-      }
-      count++;
-    }
-  } players_iterate_end;
-
   buffer[0] = '\0';
   qsort(rank, count, sizeof(struct player_score_entry), secompare1);
 
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.245
diff -u -r1.245 srv_main.c
--- server/srv_main.c   13 Apr 2005 18:41:11 -0000      1.245
+++ server/srv_main.c   24 Apr 2005 22:16:29 -0000
@@ -108,7 +108,6 @@
 
 
 static void end_turn(void);
-static bool is_game_over(void);
 static void save_game_auto(const char *save_reason);
 static void generate_ai_players(void);
 static void mark_nation_as_used(Nation_Type_id nation);
@@ -187,7 +186,6 @@
   srvarg.saves_pathname = "";
 
   srvarg.quitidle = 0;
-  BV_CLR_ALL(srvarg.draw);
 
   srvarg.auth_enabled = FALSE;
   srvarg.auth_allow_guests = FALSE;
@@ -212,7 +210,7 @@
 /**************************************************************************
   Returns TRUE if any one game end condition is fulfilled, FALSE otherwise
 **************************************************************************/
-static bool is_game_over(void)
+bool is_game_over(void)
 {
   int barbs = 0, alive = 0, observers = 0;
   bool all_allied;
@@ -244,7 +242,9 @@
 
   /* count the living */
   players_iterate(pplayer) {
-    if (pplayer->is_alive && !is_barbarian(pplayer)) {
+    if (pplayer->is_alive
+        && !is_barbarian(pplayer)
+        && !pplayer->surrendered) {
       alive++;
       victor = pplayer;
     }
@@ -252,7 +252,19 @@
 
   /* quit if we have team victory */
   team_iterate(pteam) {
-    if (team_count_members_alive(pteam->id) == alive) {
+    bool win = TRUE; /* optimistic */
+
+    /* If there are any players alive and unconceded outside our
+     * team, we have not yet won. */
+    players_iterate(pplayer) {
+      if (pplayer->is_alive
+          && !pplayer->surrendered
+          && pplayer->team != pteam->id) {
+        win = FALSE;
+        break;
+      }
+    } players_iterate_end;
+    if (win) {
       notify_conn_ex(game.est_connections, NULL, E_GAME_END,
                     _("Team victory to %s"), pteam->name);
       gamelog(GAMELOG_JUDGE, GL_TEAMWIN, pteam);
@@ -1602,7 +1614,7 @@
     freelog(LOG_DEBUG, "Sendinfotometaserver");
     (void) send_server_info_to_metaserver(META_REFRESH);
 
-    if (is_game_over()) {
+    if (server_state != GAME_OVER_STATE && is_game_over()) {
       server_state=GAME_OVER_STATE;
     }
   }
@@ -1959,5 +1971,4 @@
   } players_iterate_end;
   game_free();
   ruleset_cache_free();
-  BV_CLR_ALL(srvarg.draw);
 }
Index: server/srv_main.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.h,v
retrieving revision 1.29
diff -u -r1.29 srv_main.h
--- server/srv_main.h   12 Apr 2005 14:44:36 -0000      1.29
+++ server/srv_main.h   24 Apr 2005 22:16:29 -0000
@@ -43,8 +43,6 @@
   int quitidle;
   /* exit the server on game ending */
   bool exit_on_end;
-  /* what kind of end game we should use */
-  bv_draw draw;
   /* authentication options */
   bool auth_enabled;            /* defaults to FALSE */
   bool auth_allow_guests;       /* defaults to TRUE */
@@ -56,6 +54,8 @@
 void srv_main(void);
 void server_quit(void);
 
+bool is_game_over(void);
+
 bool handle_packet_input(struct connection *pconn, void *packet, int type);
 void start_game(void);
 void save_game(char *orig_filename, const char *save_reason);
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.396
diff -u -r1.396 stdinhand.c
--- server/stdinhand.c  20 Apr 2005 16:54:33 -0000      1.396
+++ server/stdinhand.c  24 Apr 2005 22:16:29 -0000
@@ -93,6 +93,7 @@
 static bool detach_command(struct connection *caller, char *name, bool check);
 static bool start_command(struct connection *caller, char *name, bool check);
 static bool end_command(struct connection *caller, char *str, bool check);
+static bool surrender_command(struct connection *caller, char *str, bool 
check);
 
 enum vote_type {
   VOTE_NONE, VOTE_YES, VOTE_NO
@@ -3549,6 +3550,8 @@
     return start_command(caller, arg, check);
   case CMD_END_GAME:
     return end_command(caller, arg, check);
+  case CMD_SURRENDER:
+    return surrender_command(caller, arg, check);
   case CMD_NUM:
   case CMD_UNRECOGNIZED:
   case CMD_AMBIGUOUS:
@@ -3560,56 +3563,23 @@
 }
 
 /**************************************************************************
-  End the game and accord victory to the listed players, if any.
+  End the game immediately in a draw.
 **************************************************************************/
 static bool end_command(struct connection *caller, char *str, bool check)
 {
   if (server_state == RUN_GAME_STATE) {
-    char *arg[MAX_NUM_PLAYERS];
-    int ntokens = 0, i;
-    enum m_pre_result plr_result;
-    bool result = TRUE;
-    char buf[MAX_LEN_CONSOLE_LINE];
-
-    if (str != NULL || strlen(str) > 0) {
-      sz_strlcpy(buf, str);
-      ntokens = get_tokens(buf, arg, MAX_NUM_PLAYERS, TOKEN_DELIMITERS);
-    }
-    /* Ensure players exist */
-    for (i = 0; i < ntokens; i++) {
-      struct player *pplayer = find_player_by_name_prefix(arg[i], &plr_result);
-
-      if (!pplayer) {
-        cmd_reply_no_such_player(CMD_TEAM, caller, arg[i], plr_result);
-        result = FALSE;
-        goto cleanup;
-      } else if (pplayer->is_alive == FALSE) {
-        cmd_reply(CMD_END_GAME, caller, C_FAIL, _("But %s is dead!"),
-                  pplayer->name);
-        result = FALSE;
-        goto cleanup;
-      }
-    }
     if (check) {
-      goto cleanup;
-    }
-    if (ntokens > 0) {
-      /* Mark players for victory. */
-      for (i = 0; i < ntokens; i++) {
-        BV_SET(srvarg.draw, 
-               find_player_by_name_prefix(arg[i], &plr_result)->player_no);
-      }
+      return TRUE;
     }
+    notify_conn_ex(game.est_connections, NULL, E_GAME_END,
+                   _("Game ended in a draw."));
+    gamelog(GAMELOG_JUDGE, GL_DRAW,
+            "Game ended in a draw by /endgame.");
     server_state = GAME_OVER_STATE;
     force_end_of_sniff = TRUE;
     cmd_reply(CMD_END_GAME, caller, C_OK,
               _("Ending the game. The server will restart once all clients "
               "have disconnected."));
-
-    cleanup:
-    for (i = 0; i < ntokens; i++) {
-      free(arg[i]);
-    }
     return TRUE;
   } else {
     cmd_reply(CMD_END_GAME, caller, C_FAIL, 
@@ -3619,6 +3589,31 @@
 }
 
 /**************************************************************************
+  Concede the game.  You still continue playing until all but one player
+  or team remains un-conceded.
+**************************************************************************/
+static bool surrender_command(struct connection *caller, char *str, bool check)
+{
+  if (server_state == RUN_GAME_STATE && caller && caller->player) {
+    if (check) {
+      return TRUE;
+    }
+    notify_conn_ex(game.est_connections, NULL, E_GAME_END,
+                   _("%s has conceded the game and can no longer win."),
+                   caller->player->name);
+    caller->player->surrendered = TRUE;
+    if (is_game_over()) {
+      server_state = GAME_OVER_STATE;
+      force_end_of_sniff = TRUE;
+    }
+    return TRUE;
+  } else {
+    cmd_reply(CMD_END_GAME, caller, C_FAIL, _("You cannot surrender now."));
+    return FALSE;
+  }
+}
+
+/**************************************************************************
 ...
 **************************************************************************/
 static bool start_command(struct connection *caller, char *name, bool check)

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