Freeciv21
Develop your civilization from humble roots to a global empire
team.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file
3  is part of Freeciv21. Freeciv21 is free software:
4 |\_/|,,_____,~~` you can redistribute it and/or modify it under the
5 (.".)~~ )`~}} terms of the GNU General Public License as published
6  \o/\ /---~\\ ~}} by the Free Software Foundation, either version 3 of
7  _// _// ~} the License, or (at your option) any later version.
8  You should have received a copy of the GNU General
9  Public License along with Freeciv21. If not, see
10  https://www.gnu.org/licenses/.
11  */
12 
13 #include <fc_config.h>
14 
15 // utility
16 #include "fcintl.h"
17 #include "log.h"
18 #include "shared.h"
19 #include "support.h"
20 
21 // common
22 #include "game.h"
23 #include "player.h"
24 #include "team.h"
25 
26 struct team_slot {
27  struct team *team;
28  char *defined_name; // Defined by the ruleset.
29  char *rule_name; // Usable untranslated name.
30 #ifdef FREECIV_ENABLE_NLS
31  char *name_translation; // Translated name.
32 #endif
33 };
34 
35 struct team {
36  struct player_list *plrlist;
37  struct team_slot *slot;
38 };
39 
40 static struct {
41  struct team_slot *tslots;
44 
49 {
50  int i;
51 
52  // Init team slots and names.
53  team_slots.tslots = new team_slot[team_slot_count()]();
54  /* Can't use the defined functions as the needed data will be
55  * defined here. */
56  for (i = 0; i < team_slot_count(); i++) {
57  struct team_slot *tslot = team_slots.tslots + i;
58 
59  tslot->team = nullptr;
60  tslot->defined_name = nullptr;
61  tslot->rule_name = nullptr;
62 #ifdef FREECIV_ENABLE_NLS
63  tslot->name_translation = nullptr;
64 #endif
65  }
66  team_slots.used_slots = 0;
67 }
68 
72 bool team_slots_initialised() { return (team_slots.tslots != nullptr); }
73 
78 {
79  team_slots_iterate(tslot)
80  {
81  if (nullptr != tslot->team) {
82  team_destroy(tslot->team);
83  }
84  delete[] tslot->defined_name;
85  delete[] tslot->rule_name;
86 
87 #ifdef FREECIV_ENABLE_NLS
88  delete[] tslot->name_translation;
89 #endif // FREECIV_ENABLE_NLS
90  }
92  delete[] team_slots.tslots;
93  team_slots.tslots = nullptr;
94 
95  team_slots.used_slots = 0;
96 }
97 
102 
106 struct team_slot *team_slot_first() { return team_slots.tslots; }
107 
111 struct team_slot *team_slot_next(struct team_slot *tslot)
112 {
113  tslot++;
114  return (tslot < team_slots.tslots + team_slot_count() ? tslot : nullptr);
115 }
116 
120 int team_slot_index(const struct team_slot *tslot)
121 {
123  fc_assert_ret_val(tslot != nullptr, 0);
124 
125  return tslot - team_slots.tslots;
126 }
127 
132 struct team *team_slot_get_team(const struct team_slot *tslot)
133 {
135  fc_assert_ret_val(tslot != nullptr, nullptr);
136 
137  return tslot->team;
138 }
139 
144 bool team_slot_is_used(const struct team_slot *tslot)
145 {
146  // No team slot available, if the game is not initialised.
147  if (!team_slots_initialised()) {
148  return false;
149  }
150 
151  return nullptr != tslot->team;
152 }
153 
157 struct team_slot *team_slot_by_number(int team_id)
158 {
160  || !(0 <= team_id && team_id < team_slot_count())) {
161  return nullptr;
162  }
163 
164  return team_slots.tslots + team_id;
165 }
166 
171 struct team_slot *team_slot_by_rule_name(const char *team_name)
172 {
173  fc_assert_ret_val(team_name != nullptr, nullptr);
174 
175  team_slots_iterate(tslot)
176  {
177  const char *tname = team_slot_rule_name(tslot);
178 
179  if (nullptr != tname && 0 == fc_strcasecmp(tname, team_name)) {
180  return tslot;
181  }
182  }
184 
185  return nullptr;
186 }
187 
191 static inline void team_slot_create_default_name(struct team_slot *tslot)
192 {
193  char buf[MAX_LEN_NAME];
194 
195  fc_assert(nullptr == tslot->defined_name);
196  fc_assert(nullptr == tslot->rule_name);
197 #ifdef FREECIV_ENABLE_NLS
198  fc_assert(nullptr == tslot->name_translation);
199 #endif // FREECIV_ENABLE_NLS
200 
201  fc_snprintf(buf, sizeof(buf), "Team %d", team_slot_index(tslot) + 1);
202  tslot->rule_name = fc_strdup(buf);
203 
204 #ifdef FREECIV_ENABLE_NLS
205  fc_snprintf(buf, sizeof(buf), _("Team %d"), team_slot_index(tslot) + 1);
206  tslot->name_translation = fc_strdup(buf);
207 #endif // FREECIV_ENABLE_NLS
208 
209  qDebug("No name defined for team %d! Creating a default name: %s.",
210  team_slot_index(tslot), tslot->rule_name);
211 }
212 
217 const char *team_slot_rule_name(const struct team_slot *tslot)
218 {
220  fc_assert_ret_val(nullptr != tslot, nullptr);
221 
222  if (nullptr == tslot->rule_name) {
223  // Get the team slot as changeable (not _const_) struct.
224  struct team_slot *changeable =
226  team_slot_create_default_name(changeable);
227  return changeable->rule_name;
228  }
229 
230  return tslot->rule_name;
231 }
232 
237 const char *team_slot_name_translation(const struct team_slot *tslot)
238 {
239 #ifdef FREECIV_ENABLE_NLS
241  fc_assert_ret_val(nullptr != tslot, nullptr);
242 
243  if (nullptr == tslot->name_translation) {
244  // Get the team slot as changeable (not _const_) struct.
245  struct team_slot *changeable =
247  team_slot_create_default_name(changeable);
248  return changeable->name_translation;
249  }
250 
251  return tslot->name_translation;
252 #else // FREECIV_ENABLE_NLS
253  return team_slot_rule_name(tslot);
254 #endif // FREECIV_ENABLE_NLS
255 }
256 
261 const char *team_slot_defined_name(const struct team_slot *tslot)
262 {
264  fc_assert_ret_val(nullptr != tslot, nullptr);
265 
266  return tslot->defined_name;
267 }
268 
273  const char *team_name)
274 {
276  fc_assert_ret(nullptr != tslot);
277  fc_assert_ret(nullptr != team_name);
278 
279  delete[] tslot->defined_name;
280  tslot->defined_name = fc_strdup(team_name);
281  delete[] tslot->rule_name;
282  tslot->rule_name = fc_strdup(Qn_(team_name));
283 
284 #ifdef FREECIV_ENABLE_NLS
285  delete[] tslot->name_translation;
286  tslot->name_translation = fc_strdup(Q_(team_name));
287 #endif // FREECIV_ENABLE_NLS
288 }
289 
294 struct team *team_new(struct team_slot *tslot)
295 {
296  struct team *pteam;
297 
299 
300  if (nullptr == tslot) {
301  team_slots_iterate(aslot)
302  {
303  if (!team_slot_is_used(aslot)) {
304  tslot = aslot;
305  break;
306  }
307  }
309 
310  fc_assert_ret_val(nullptr != tslot, nullptr);
311  } else if (nullptr != tslot->team) {
312  return tslot->team;
313  }
314 
315  // Now create the team.
316  log_debug("Create team for slot %d.", team_slot_index(tslot));
317  pteam = new team[1]();
318  pteam->slot = tslot;
319  tslot->team = pteam;
320 
321  // Set default values.
322  pteam->plrlist = player_list_new();
323 
324  // Increase number of teams.
325  team_slots.used_slots++;
326 
327  return pteam;
328 }
329 
333 void team_destroy(struct team *pteam)
334 {
335  struct team_slot *tslot;
336 
338  fc_assert_ret(nullptr != pteam);
339  fc_assert(0 == player_list_size(pteam->plrlist));
340 
341  tslot = pteam->slot;
342  fc_assert(tslot->team == pteam);
343 
344  player_list_destroy(pteam->plrlist);
345  delete[] pteam;
346  pteam = nullptr;
347  tslot->team = nullptr;
348  team_slots.used_slots--;
349 }
350 
354 int team_count() { return team_slots.used_slots; }
355 
359 int team_index(const struct team *pteam) { return team_number(pteam); }
360 
364 int team_number(const struct team *pteam)
365 {
366  fc_assert_ret_val(nullptr != pteam, 0);
367  return team_slot_index(pteam->slot);
368 }
369 
373 struct team *team_by_number(const int team_id)
374 {
375  const struct team_slot *tslot = team_slot_by_number(team_id);
376 
377  return (nullptr != tslot ? team_slot_get_team(tslot) : nullptr);
378 }
379 
383 const char *team_rule_name(const struct team *pteam)
384 {
385  fc_assert_ret_val(nullptr != pteam, nullptr);
386 
387  return team_slot_rule_name(pteam->slot);
388 }
389 
393 const char *team_name_translation(const struct team *pteam)
394 {
395  fc_assert_ret_val(nullptr != pteam, nullptr);
396 
397  return team_slot_name_translation(pteam->slot);
398 }
399 
405 int team_pretty_name(const struct team *pteam, QString &buf)
406 {
407  if (nullptr != pteam) {
408  if (nullptr != pteam->slot->defined_name) {
409  // TRANS: %s is ruleset-chosen team name (e.g. "Red")
410  buf =
411  QString(_("team %1")).arg(team_slot_name_translation(pteam->slot));
412  return 1;
413  } else {
414  buf = QString(_("team %1")).arg(QString::number(team_number(pteam)));
415  return 1;
416  }
417  }
418 
419  // No need to translate, it's an error.
420  buf = QStringLiteral("(null team)");
421  return -1;
422 }
423 
427 const struct player_list *team_members(const struct team *pteam)
428 {
429  fc_assert_ret_val(nullptr != pteam, nullptr);
430 
431  return pteam->plrlist;
432 }
433 
438 void team_add_player(struct player *pplayer, struct team *pteam)
439 {
440  fc_assert_ret(pplayer != nullptr);
441 
442  if (pteam == nullptr) {
443  pteam = team_new(nullptr);
444  }
445 
446  fc_assert_ret(pteam != nullptr);
447 
448  if (pteam == pplayer->team) {
449  // It is the team of the player.
450  return;
451  }
452 
453  log_debug("Adding player %d/%s to team %s.", player_number(pplayer),
454  pplayer->username, team_rule_name(pteam));
455 
456  // Remove the player from the old team, if any.
457  team_remove_player(pplayer);
458 
459  // Put the player on the new team.
460  pplayer->team = pteam;
461  player_list_append(pteam->plrlist, pplayer);
462 }
463 
471 void team_remove_player(struct player *pplayer)
472 {
473  struct team *pteam;
474 
475  if (pplayer->team) {
476  pteam = pplayer->team;
477 
478  log_debug("Removing player %d/%s from team %s (%d)",
479  player_number(pplayer), player_name(pplayer),
480  team_rule_name(pteam), player_list_size(pteam->plrlist));
481  player_list_remove(pteam->plrlist, pplayer);
482 
483  if (player_list_size(pteam->plrlist) == 0) {
484  team_destroy(pteam);
485  }
486  }
487  pplayer->team = nullptr;
488 }
#define MAX_LEN_NAME
Definition: fc_types.h:61
#define Q_(String)
Definition: fcintl.h:53
#define _(String)
Definition: fcintl.h:50
#define Qn_(String)
Definition: fcintl.h:66
#define fc_assert_ret(condition)
Definition: log.h:112
#define fc_assert(condition)
Definition: log.h:89
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
#define log_debug(message,...)
Definition: log.h:65
int player_number(const struct player *pplayer)
Return the player index/number/id.
Definition: player.cpp:756
const char * player_name(const struct player *pplayer)
Return the leader name of the player.
Definition: player.cpp:816
Definition: player.h:231
char username[MAX_LEN_NAME]
Definition: player.h:234
struct team * team
Definition: player.h:243
char * defined_name
Definition: team.cpp:28
char * rule_name
Definition: team.cpp:29
struct team * team
Definition: team.cpp:27
Definition: team.cpp:35
struct team_slot * slot
Definition: team.cpp:37
struct player_list * plrlist
Definition: team.cpp:36
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537
int fc_strcasecmp(const char *str0, const char *str1)
Compare strings like strcmp(), but ignoring case.
Definition: support.cpp:89
#define fc_strdup(str)
Definition: support.h:111
int team_index(const struct team *pteam)
Return the team index.
Definition: team.cpp:359
struct team * team_by_number(const int team_id)
Return struct team pointer for the given team index.
Definition: team.cpp:373
struct team_slot * team_slot_next(struct team_slot *tslot)
Returns the next team slot.
Definition: team.cpp:111
static void team_slot_create_default_name(struct team_slot *tslot)
Creates a default name for this team slot.
Definition: team.cpp:191
const char * team_name_translation(const struct team *pteam)
Returns the name (translated) of the team.
Definition: team.cpp:393
const char * team_rule_name(const struct team *pteam)
Returns the name (untranslated) of the team.
Definition: team.cpp:383
void team_add_player(struct player *pplayer, struct team *pteam)
Set a player to a team.
Definition: team.cpp:438
int used_slots
Definition: team.cpp:42
struct team_slot * team_slot_first()
Returns the first team slot.
Definition: team.cpp:106
const char * team_slot_defined_name(const struct team_slot *tslot)
Returns the name defined in the ruleset for this slot.
Definition: team.cpp:261
int team_count()
Return the current number of teams.
Definition: team.cpp:354
struct team * team_slot_get_team(const struct team_slot *tslot)
Returns the team corresponding to the slot.
Definition: team.cpp:132
int team_pretty_name(const struct team *pteam, QString &buf)
Set in 'buf' the name of the team 'pteam' in a format like "team <team_name>".
Definition: team.cpp:405
struct team_slot * tslots
Definition: team.cpp:41
const char * team_slot_name_translation(const struct team_slot *tslot)
Returns the name (translated) of the slot.
Definition: team.cpp:237
int team_number(const struct team *pteam)
Return the team index/number/id.
Definition: team.cpp:364
void team_destroy(struct team *pteam)
Destroys a team.
Definition: team.cpp:333
void team_slots_init()
Initialise all team slots.
Definition: team.cpp:48
const char * team_slot_rule_name(const struct team_slot *tslot)
Returns the name (untranslated) of the slot.
Definition: team.cpp:217
bool team_slots_initialised()
Returns TRUE if the team slots have been initialized.
Definition: team.cpp:72
const struct player_list * team_members(const struct team *pteam)
Returns the member list of the team.
Definition: team.cpp:427
void team_slots_free()
Remove all team slots.
Definition: team.cpp:77
int team_slot_index(const struct team_slot *tslot)
Returns the index of the team slots.
Definition: team.cpp:120
struct team * team_new(struct team_slot *tslot)
Creates a new team for the slot.
Definition: team.cpp:294
void team_remove_player(struct player *pplayer)
Remove the player from the team.
Definition: team.cpp:471
int team_slot_count()
Returns the total number of team slots (including used slots).
Definition: team.cpp:101
struct team_slot * team_slot_by_rule_name(const char *team_name)
Does a linear search for a (defined) team name.
Definition: team.cpp:171
static struct @74 team_slots
struct team_slot * team_slot_by_number(int team_id)
Return the possibly unused and uninitialized team slot.
Definition: team.cpp:157
bool team_slot_is_used(const struct team_slot *tslot)
Returns TRUE is this slot is "used" i.e.
Definition: team.cpp:144
void team_slot_set_defined_name(struct team_slot *tslot, const char *team_name)
Set the name defined in the ruleset for this slot.
Definition: team.cpp:272
#define team_slots_iterate_end
Definition: team.h:66
#define team_slots_iterate(_tslot)
Definition: team.h:62
#define MAX_NUM_TEAM_SLOTS
Definition: team.h:17