Rulesave saves trade.type and trade.bonus correctly.
[freeciv.git] / client / plrdlg_common.c
blob9a181beb4fae84eec5c8487f764635ae5675623a
1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <string.h>
20 /* utility */
21 #include "fcintl.h"
22 #include "log.h"
23 #include "support.h"
25 /* common */
26 #include "connection.h"
27 #include "game.h"
29 /* client */
30 #include "client_main.h"
31 #include "climisc.h"
32 #include "options.h"
33 #include "text.h"
35 /* client/include */
36 #include "plrdlg_g.h"
38 #include "plrdlg_common.h"
41 /******************************************************************
42 The player-name (aka nation leader) column of the plrdlg.
43 *******************************************************************/
44 static const char *col_name(const struct player *player)
46 return player_name(player);
49 /****************************************************************************
50 Compares the names of two players in players dialog.
51 ****************************************************************************/
52 static int cmp_name(const struct player *pplayer1,
53 const struct player *pplayer2)
55 return fc_stricoll(player_name(pplayer1), player_name(pplayer2));
58 /******************************************************************
59 The username (connection name) column of the plrdlg.
60 *******************************************************************/
61 static const char *col_username(const struct player *player)
63 return player->username;
66 /******************************************************************
67 The name of the player's nation for the plrdlg.
68 *******************************************************************/
69 static const char *col_nation(const struct player *player)
71 return nation_adjective_for_player(player);
74 /******************************************************************
75 The name of the player's team (or empty) for the plrdlg.
76 *******************************************************************/
77 static const char *col_team(const struct player *player)
79 return team_name_translation(player->team);
82 /******************************************************************
83 TRUE if the player is AI-controlled.
84 *******************************************************************/
85 static bool col_ai(const struct player *plr)
87 return plr->ai_controlled;
90 /******************************************************************
91 Returns a translated string giving the embassy status
92 (none/with us/with them/both).
93 *******************************************************************/
94 static const char *col_embassy(const struct player *player)
96 return get_embassy_status(client.conn.playing, player);
99 /******************************************************************
100 Returns a translated string giving the diplomatic status
101 ("war" or "ceasefire (5)").
102 *******************************************************************/
103 static const char *col_diplstate(const struct player *player)
105 static char buf[100];
106 const struct player_diplstate *pds;
108 if (NULL == client.conn.playing || player == client.conn.playing) {
109 return "-";
110 } else {
111 pds = player_diplstate_get(client.conn.playing, player);
112 if (pds->type == DS_CEASEFIRE || pds->type == DS_ARMISTICE) {
113 fc_snprintf(buf, sizeof(buf), "%s (%d)",
114 diplstate_type_translated_name(pds->type),
115 pds->turns_left);
116 return buf;
117 } else {
118 return diplstate_type_translated_name(pds->type);
123 /******************************************************************
124 Return a numerical value suitable for ordering players by
125 their diplomatic status in the players dialog
127 A lower value stands for more friendly diplomatic status.
128 *******************************************************************/
129 static int diplstate_value(const struct player *plr)
131 /* these values are scaled so that adding/subtracting
132 the number of turns left makes sense */
133 static const int diplstate_cmp_lookup[DS_LAST] = {
134 [DS_TEAM] = 1 << 16,
135 [DS_ALLIANCE] = 2 << 16,
136 [DS_PEACE] = 3 << 16,
137 [DS_ARMISTICE] = 4 << 16,
138 [DS_CEASEFIRE] = 5 << 16,
139 [DS_WAR] = 6 << 16,
140 [DS_NO_CONTACT] = 7 << 16
143 const struct player_diplstate *pds;
144 int ds_value;
146 if (NULL == client.conn.playing || plr == client.conn.playing) {
147 /* current global player is as close as players get
148 -> return value smaller than for DS_TEAM */
149 return 0;
152 pds = player_diplstate_get(client.conn.playing, plr);
153 ds_value = diplstate_cmp_lookup[pds->type];
155 if (pds->type == DS_ARMISTICE || pds->type == DS_CEASEFIRE) {
156 ds_value += pds->turns_left;
159 return ds_value;
162 /******************************************************************
163 Compares diplomatic status of two players in players dialog
164 *******************************************************************/
165 static int cmp_diplstate(const struct player *player1,
166 const struct player *player2)
168 return diplstate_value(player1) - diplstate_value(player2);
171 /******************************************************************
172 Return a string displaying the AI's love (or not) for you...
173 *******************************************************************/
174 static const char *col_love(const struct player *player)
176 if (NULL == client.conn.playing || player == client.conn.playing
177 || !player->ai_controlled) {
178 return "-";
179 } else {
180 return love_text(player->ai_common.love[player_index(client.conn.playing)]);
184 /******************************************************************
185 Compares ai's attitude toward the player
186 ******************************************************************/
187 static int cmp_love(const struct player *player1,
188 const struct player *player2)
190 int love1, love2;
192 if (NULL == client.conn.playing) {
193 return player_number(player1) - player_number(player2);
196 if (player1 == client.conn.playing || !player1->ai_controlled) {
197 love1 = MAX_AI_LOVE + 999;
198 } else {
199 love1 = player1->ai_common.love[player_index(client.conn.playing)];
202 if (player2 == client.conn.playing || !player2->ai_controlled) {
203 love2 = MAX_AI_LOVE + 999;
204 } else {
205 love2 = player2->ai_common.love[player_index(client.conn.playing)];
208 return love1 - love2;
211 /******************************************************************
212 Returns a translated string giving our shared-vision status.
213 *******************************************************************/
214 static const char *col_vision(const struct player *player)
216 return get_vision_status(client.conn.playing, player);
219 /******************************************************************
220 Returns a translated string giving the player's "state".
222 FIXME: These terms aren't very intuitive for new players.
223 *******************************************************************/
224 const char *plrdlg_col_state(const struct player *plr)
226 if (!plr->is_alive) {
227 /* TRANS: Dead -- Rest In Peace -- Reqia In Pace */
228 return _("R.I.P.");
229 } else if (!plr->is_connected) {
230 struct option *opt;
231 bool consider_tb = FALSE;
233 if (plr->ai_controlled) {
234 return "";
237 opt = optset_option_by_name(server_optset, "turnblock");
238 if (opt != NULL) {
239 consider_tb = option_bool_get(opt);
242 if (!consider_tb) {
243 /* TRANS: No connection */
244 return _("noconn");
247 if (!is_player_phase(plr, game.info.phase)) {
248 return _("waiting");
249 } else if (plr->phase_done) {
250 return _("done");
251 } else {
252 /* TRANS: Turnblocking & player not connected */
253 return _("blocking");
255 } else {
256 if (!is_player_phase(plr, game.info.phase)) {
257 return _("waiting");
258 } else if (plr->phase_done) {
259 return _("done");
260 } else {
261 return _("moving");
266 /******************************************************************
267 Returns a string telling the player's client's hostname (the
268 machine from which he is connecting).
269 *******************************************************************/
270 static const char *col_host(const struct player *player)
272 return player_addr_hack(player);
275 /******************************************************************
276 Returns a string telling how many turns the player has been idle.
277 *******************************************************************/
278 static const char *col_idle(const struct player *plr)
280 int idle;
281 static char buf[100];
283 if (plr->nturns_idle > 3) {
284 idle = plr->nturns_idle - 1;
285 } else {
286 idle = 0;
288 fc_snprintf(buf, sizeof(buf), "%d", idle);
289 return buf;
292 /******************************************************************
293 Compares score of two players in players dialog
294 *******************************************************************/
295 static int cmp_score(const struct player* player1,
296 const struct player* player2)
298 return player1->score.game - player2->score.game;
301 /******************************************************************
303 *******************************************************************/
304 struct player_dlg_column player_dlg_columns[] = {
305 {TRUE, COL_TEXT, N_("?Player:Name"), col_name, NULL, cmp_name, "name"},
306 {FALSE, COL_TEXT, N_("Username"), col_username, NULL, NULL, "username"},
307 {TRUE, COL_FLAG, N_("Flag"), NULL, NULL, NULL, "flag"},
308 {TRUE, COL_TEXT, N_("Nation"), col_nation, NULL, NULL, "nation"},
309 {TRUE, COL_COLOR, N_("Border"), NULL, NULL, NULL, "border"},
310 {TRUE, COL_RIGHT_TEXT, N_("Score"), get_score_text, NULL, cmp_score, "score"},
311 {TRUE, COL_TEXT, N_("Team"), col_team, NULL, NULL, "team"},
312 {TRUE, COL_BOOLEAN, N_("AI"), NULL, col_ai, NULL, "ai"},
313 {TRUE, COL_TEXT, N_("Attitude"), col_love, NULL, cmp_love, "attitude"},
314 {TRUE, COL_TEXT, N_("Embassy"), col_embassy, NULL, NULL, "embassy"},
315 {TRUE, COL_TEXT, N_("Dipl.State"), col_diplstate, NULL, cmp_diplstate,
316 "diplstate"},
317 {TRUE, COL_TEXT, N_("Vision"), col_vision, NULL, NULL, "vision"},
318 {TRUE, COL_TEXT, N_("State"), plrdlg_col_state, NULL, NULL, "state"},
319 {FALSE, COL_TEXT, N_("?Player_dlg:Host"), col_host, NULL, NULL, "host"},
320 {FALSE, COL_RIGHT_TEXT, N_("?Player_dlg:Idle"), col_idle, NULL, NULL, "idle"},
321 {FALSE, COL_RIGHT_TEXT, N_("Ping"), get_ping_time_text, NULL, NULL, "ping"}
324 const int num_player_dlg_columns = ARRAY_SIZE(player_dlg_columns);
326 /******************************************************************
327 Return default player dlg sorting column.
328 *******************************************************************/
329 int player_dlg_default_sort_column(void)
331 return 3;
334 /****************************************************************************
335 Translate all titles
336 ****************************************************************************/
337 void init_player_dlg_common()
339 int i;
341 for (i = 0; i < num_player_dlg_columns; i++) {
342 player_dlg_columns[i].title = Q_(player_dlg_columns[i].title);
346 /**************************************************************************
347 The only place where this is used is the player dialog.
348 Eventually this should go the way of the dodo with everything here
349 moved into col_host above, but some of the older clients (+win32) still
350 use this function directly.
352 This code in this function is only really needed so that the host is
353 kept as a blank address if no one is controlling a player, but there are
354 observers.
355 **************************************************************************/
356 const char *player_addr_hack(const struct player *pplayer)
358 conn_list_iterate(pplayer->connections, pconn) {
359 if (!pconn->observer) {
360 return pconn->addr;
362 } conn_list_iterate_end;
364 return blank_addr_str;