1 /**********************************************************************
2 Freeciv - Copyright (C) 2005 - The Freeciv Project
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)
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 ***********************************************************************/
15 #include <fc_config.h>
33 char *defined_name
; /* Defined by the ruleset. */
34 char *rule_name
; /* Usable untranslated name. */
36 char *name_translation
; /* Translated name. */
41 struct player_list
*plrlist
;
42 struct team_slot
*slot
;
46 struct team_slot
*slots
;
50 /****************************************************************************
51 Initialise all team slots.
52 ****************************************************************************/
53 void team_slots_init(void)
57 /* Init team slots and names. */
58 team_slots
.slots
= fc_calloc(team_slot_count(), sizeof(*team_slots
.slots
));
59 /* Can't use the defined functions as the needed data will be
61 for (i
= 0; i
< team_slot_count(); i
++) {
62 struct team_slot
*tslot
= team_slots
.slots
+ i
;
65 tslot
->defined_name
= NULL
;
66 tslot
->rule_name
= NULL
;
68 tslot
->name_translation
= NULL
;
71 team_slots
.used_slots
= 0;
74 /****************************************************************************
75 Returns TRUE if the team slots have been initialized.
76 ****************************************************************************/
77 bool team_slots_initialised(void)
79 return (team_slots
.slots
!= NULL
);
82 /****************************************************************************
83 Remove all team slots.
84 ****************************************************************************/
85 void team_slots_free(void)
87 team_slots_iterate(tslot
) {
88 if (NULL
!= tslot
->team
) {
89 team_destroy(tslot
->team
);
91 if (NULL
!= tslot
->defined_name
) {
92 free(tslot
->defined_name
);
94 if (NULL
!= tslot
->rule_name
) {
95 free(tslot
->rule_name
);
98 if (NULL
!= tslot
->name_translation
) {
99 free(tslot
->name_translation
);
102 } team_slots_iterate_end
;
103 free(team_slots
.slots
);
104 team_slots
.slots
= NULL
;
106 team_slots
.used_slots
= 0;
109 /****************************************************************************
110 Returns the total number of team slots (including used slots).
111 ****************************************************************************/
112 int team_slot_count(void)
114 return (MAX_NUM_TEAM_SLOTS
);
117 /****************************************************************************
118 Returns the first team slot.
119 ****************************************************************************/
120 struct team_slot
*team_slot_first(void)
122 return team_slots
.slots
;
125 /****************************************************************************
126 Returns the next team slot.
127 ****************************************************************************/
128 struct team_slot
*team_slot_next(struct team_slot
*tslot
)
131 return (tslot
< team_slots
.slots
+ team_slot_count() ? tslot
: NULL
);
135 /****************************************************************************
136 Returns the index of the team slots.
137 ****************************************************************************/
138 int team_slot_index(const struct team_slot
*tslot
)
140 fc_assert_ret_val(team_slots_initialised(), -1);
141 fc_assert_ret_val(tslot
!= NULL
, -1);
143 return tslot
- team_slots
.slots
;
146 /****************************************************************************
147 Returns the team corresponding to the slot. If the slot is not used, it
148 will return NULL. See also team_slot_is_used().
149 ****************************************************************************/
150 struct team
*team_slot_get_team(const struct team_slot
*tslot
)
152 fc_assert_ret_val(team_slots_initialised(), NULL
);
153 fc_assert_ret_val(tslot
!= NULL
, NULL
);
158 /****************************************************************************
159 Returns TRUE is this slot is "used" i.e. corresponds to a
160 valid, initialized team that exists in the game.
161 ****************************************************************************/
162 bool team_slot_is_used(const struct team_slot
*tslot
)
164 /* No team slot available, if the game is not initialised. */
165 if (!team_slots_initialised()) {
169 return NULL
!= tslot
->team
;
172 /****************************************************************************
173 Return the possibly unused and uninitialized team slot.
174 ****************************************************************************/
175 struct team_slot
*team_slot_by_number(int team_id
)
177 if (!team_slots_initialised()
178 || !(0 <= team_id
&& team_id
< team_slot_count())) {
182 return team_slots
.slots
+ team_id
;
185 /****************************************************************************
186 Does a linear search for a (defined) team name. Returns NULL when none
188 ****************************************************************************/
189 struct team_slot
*team_slot_by_rule_name(const char *team_name
)
191 fc_assert_ret_val(team_name
!= NULL
, NULL
);
193 team_slots_iterate(tslot
) {
194 const char *tname
= team_slot_rule_name(tslot
);
196 if (NULL
!= tname
&& 0 == fc_strcasecmp(tname
, team_name
)) {
199 } team_slots_iterate_end
;
204 /****************************************************************************
205 Creates a default name for this team slot.
206 ****************************************************************************/
207 static inline void team_slot_create_default_name(struct team_slot
*tslot
)
209 char buf
[MAX_LEN_NAME
];
211 fc_assert(NULL
== tslot
->defined_name
);
212 fc_assert(NULL
== tslot
->rule_name
);
214 fc_assert(NULL
== tslot
->name_translation
);
217 fc_snprintf(buf
, sizeof(buf
), "Team %d", team_slot_index(tslot
));
218 tslot
->rule_name
= fc_strdup(buf
);
221 fc_snprintf(buf
, sizeof(buf
), _("Team %d"), team_slot_index(tslot
));
222 tslot
->name_translation
= fc_strdup(buf
);
225 log_verbose("No name defined for team %d! Creating a default name: %s.",
226 team_slot_index(tslot
), tslot
->rule_name
);
229 /****************************************************************************
230 Returns the name (untranslated) of the slot. Creates a default one if it
231 doesn't exist currently.
232 ****************************************************************************/
233 const char *team_slot_rule_name(const struct team_slot
*tslot
)
235 fc_assert_ret_val(team_slots_initialised(), NULL
);
236 fc_assert_ret_val(NULL
!= tslot
, NULL
);
238 if (NULL
== tslot
->rule_name
) {
239 /* Get the team slot as changeable (not _const_) struct. */
240 struct team_slot
*changeable
241 = team_slot_by_number(team_slot_index(tslot
));
242 team_slot_create_default_name(changeable
);
243 return changeable
->rule_name
;
246 return tslot
->rule_name
;
249 /****************************************************************************
250 Returns the name (translated) of the slot. Creates a default one if it
251 doesn't exist currently.
252 ****************************************************************************/
253 const char *team_slot_name_translation(const struct team_slot
*tslot
)
256 fc_assert_ret_val(team_slots_initialised(), NULL
);
257 fc_assert_ret_val(NULL
!= tslot
, NULL
);
259 if (NULL
== tslot
->name_translation
) {
260 /* Get the team slot as changeable (not _const_) struct. */
261 struct team_slot
*changeable
262 = team_slot_by_number(team_slot_index(tslot
));
263 team_slot_create_default_name(changeable
);
264 return changeable
->name_translation
;
267 return tslot
->name_translation
;
269 return team_slot_rule_name(tslot
);
270 #endif /* ENABLE_NLS */
273 /****************************************************************************
274 Returns the name defined in the ruleset for this slot. It may return NULL
275 if the ruleset didn't defined a such name.
276 ****************************************************************************/
277 const char *team_slot_defined_name(const struct team_slot
*tslot
)
279 fc_assert_ret_val(team_slots_initialised(), NULL
);
280 fc_assert_ret_val(NULL
!= tslot
, NULL
);
282 return tslot
->defined_name
;
285 /****************************************************************************
286 Set the name defined in the ruleset for this slot.
287 ****************************************************************************/
288 void team_slot_set_defined_name(struct team_slot
*tslot
,
289 const char *team_name
)
291 fc_assert_ret(team_slots_initialised());
292 fc_assert_ret(NULL
!= tslot
);
293 fc_assert_ret(NULL
!= team_name
);
295 if (NULL
!= tslot
->defined_name
) {
296 free(tslot
->defined_name
);
298 tslot
->defined_name
= fc_strdup(team_name
);
300 if (NULL
!= tslot
->rule_name
) {
301 free(tslot
->rule_name
);
303 tslot
->rule_name
= fc_strdup(Qn_(team_name
));
306 if (NULL
!= tslot
->name_translation
) {
307 free(tslot
->name_translation
);
309 tslot
->name_translation
= fc_strdup(Q_(team_name
));
314 /****************************************************************************
315 Creates a new team for the slot. If slot is NULL, it will lookup to a
316 free slot. If the slot already used, then just return the team.
317 ****************************************************************************/
318 struct team
*team_new(struct team_slot
*tslot
)
322 fc_assert_ret_val(team_slots_initialised(), NULL
);
325 team_slots_iterate(aslot
) {
326 if (!team_slot_is_used(aslot
)) {
330 } team_slots_iterate_end
;
332 fc_assert_ret_val(NULL
!= tslot
, NULL
);
333 } else if (NULL
!= tslot
->team
) {
337 /* Now create the team. */
338 log_debug("Create team for slot %d.", team_slot_index(tslot
));
339 pteam
= fc_calloc(1, sizeof(*pteam
));
343 /* Set default values. */
344 pteam
->plrlist
= player_list_new();
346 /* Increase number of teams. */
347 team_slots
.used_slots
++;
352 /****************************************************************************
354 ****************************************************************************/
355 void team_destroy(struct team
*pteam
)
357 struct team_slot
*tslot
;
359 fc_assert_ret(team_slots_initialised());
360 fc_assert_ret(NULL
!= pteam
);
361 fc_assert(0 == player_list_size(pteam
->plrlist
));
364 fc_assert(tslot
->team
== pteam
);
366 player_list_destroy(pteam
->plrlist
);
369 team_slots
.used_slots
--;
372 /****************************************************************************
373 Return the current number of teams.
374 ****************************************************************************/
377 return team_slots
.used_slots
;
380 /****************************************************************************
381 Return the team index.
382 ****************************************************************************/
383 int team_index(const struct team
*pteam
)
385 return team_number(pteam
);
388 /****************************************************************************
389 Return the team index/number/id.
390 ****************************************************************************/
391 int team_number(const struct team
*pteam
)
393 fc_assert_ret_val(NULL
!= pteam
, -1);
394 return team_slot_index(pteam
->slot
);
397 /****************************************************************************
398 Return struct team pointer for the given team index.
399 ****************************************************************************/
400 struct team
*team_by_number(const int team_id
)
402 const struct team_slot
*tslot
= team_slot_by_number(team_id
);
404 return (NULL
!= tslot
? team_slot_get_team(tslot
) : NULL
);
407 /****************************************************************************
408 Returns the name (untranslated) of the team.
409 ****************************************************************************/
410 const char *team_rule_name(const struct team
*pteam
)
412 fc_assert_ret_val(NULL
!= pteam
, NULL
);
414 return team_slot_rule_name(pteam
->slot
);
417 /****************************************************************************
418 Returns the name (translated) of the team.
419 ****************************************************************************/
420 const char *team_name_translation(const struct team
*pteam
)
422 fc_assert_ret_val(NULL
!= pteam
, NULL
);
424 return team_slot_name_translation(pteam
->slot
);
427 /****************************************************************************
428 Set in 'buf' the name of the team 'pteam' in a format like
429 "team <team_name>". To avoid to see "team Team 0", it only prints the
430 the team number when the name of this team is not defined in the ruleset.
431 ****************************************************************************/
432 int team_pretty_name(const struct team
*pteam
, char *buf
, size_t buf_len
)
435 if (NULL
!= pteam
->slot
->defined_name
) {
436 return fc_snprintf(buf
, buf_len
, _("team %s"),
437 team_slot_name_translation(pteam
->slot
));
439 return fc_snprintf(buf
, buf_len
, _("team %d"), team_number(pteam
));
443 /* No need to translate, it's an error. */
444 fc_strlcpy(buf
, "(null team)", buf_len
);
448 /****************************************************************************
449 Returns the member list of the team.
450 ****************************************************************************/
451 const struct player_list
*team_members(const struct team
*pteam
)
453 fc_assert_ret_val(NULL
!= pteam
, NULL
);
455 return pteam
->plrlist
;
458 /****************************************************************************
459 Set a player to a team. Removes the previous team affiliation if
461 ****************************************************************************/
462 void team_add_player(struct player
*pplayer
, struct team
*pteam
)
464 fc_assert_ret(pplayer
!= NULL
);
467 pteam
= team_new(NULL
);
470 fc_assert_ret(pteam
!= NULL
);
472 if (pteam
== pplayer
->team
) {
473 /* It is the team of the player. */
477 log_debug("Adding player %d/%s to team %s.", player_number(pplayer
),
478 pplayer
->username
, team_rule_name(pteam
));
480 /* Remove the player from the old team, if any. */
481 team_remove_player(pplayer
);
483 /* Put the player on the new team. */
484 pplayer
->team
= pteam
;
485 player_list_append(pteam
->plrlist
, pplayer
);
488 /****************************************************************************
489 Remove the player from the team. This should only be called when deleting
490 a player; since every player must always be on a team.
492 Note in some very rare cases a player may not be on a team. It's safe
493 to call this function anyway.
494 ****************************************************************************/
495 void team_remove_player(struct player
*pplayer
)
500 pteam
= pplayer
->team
;
502 log_debug("Removing player %d/%s from team %s (%d)",
503 player_number(pplayer
), player_name(pplayer
),
504 team_rule_name(pteam
), player_list_size(pteam
->plrlist
));
505 player_list_remove(pteam
->plrlist
, pplayer
);
507 if (player_list_size(pteam
->plrlist
) == 0) {
511 pplayer
->team
= NULL
;