Stop sharing requirement_unit_state_ereq().
[freeciv.git] / client / unitselect_common.c
blobb9a61bca17c13b31e96a014edfdf6f77cbf41776
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 /* common */
19 #include "fc_types.h"
20 #include "game.h"
21 #include "player.h"
22 #include "unit.h"
23 #include "unitlist.h"
24 #include "unittype.h"
26 /* client */
27 #include "client_main.h"
28 #include "control.h"
30 #include "unitselect_common.h"
32 static void usdlg_data_add_unit(struct usdata_hash *ushash,
33 const struct tile *ptile,
34 struct unit *punit);
36 static bool usdlg_check_unit_activity(const struct unit *punit,
37 enum unit_activity act);
38 static bool usdlg_check_unit_location(const struct unit *punit,
39 const struct tile *ptile,
40 enum unit_select_location_mode loc);
42 static struct usdata *usdata_new(void);
43 static void usdata_destroy(struct usdata *data);
45 /*****************************************************************************
46 Create a unit selection data struct.
47 *****************************************************************************/
48 static struct usdata *usdata_new(void)
50 enum unit_select_location_mode loc;
51 enum unit_activity act;
53 struct usdata *data = fc_calloc(1, sizeof(*data));
55 data->utype = NULL;
57 for (loc = unit_select_location_mode_begin();
58 loc != unit_select_location_mode_end();
59 loc = unit_select_location_mode_next(loc)) {
60 for (act = 0; act < ACTIVITY_LAST; act++) {
61 /* Create a unit list for all activities - even invalid once. */
62 data->units[loc][act] = unit_list_new();
66 return data;
69 /*****************************************************************************
70 Destroy a unit selection struct.
71 *****************************************************************************/
72 static void usdata_destroy(struct usdata *data)
74 if (data != NULL) {
75 enum unit_select_location_mode loc;
76 enum unit_activity act;
78 for (loc = unit_select_location_mode_begin();
79 loc != unit_select_location_mode_end();
80 loc = unit_select_location_mode_next(loc)) {
81 for (act = 0; act < ACTIVITY_LAST; act++) {
82 if (data->units[loc][act] != NULL) {
83 unit_list_destroy(data->units[loc][act]);
87 free(data);
91 /*****************************************************************************
92 Create a unit selection data set.
93 *****************************************************************************/
94 struct usdata_hash *usdlg_data_new(const struct tile *ptile)
96 struct usdata_hash *ushash = usdata_hash_new();
98 /* Add units of the player(s). */
99 if (client_is_global_observer()) {
100 players_iterate(pplayer) {
101 unit_list_iterate(pplayer->units, punit) {
102 usdlg_data_add_unit(ushash, ptile, punit);
103 } unit_list_iterate_end;
104 } players_iterate_end;
105 } else {
106 struct player *pplayer = client_player();
107 unit_list_iterate(pplayer->units, punit) {
108 usdlg_data_add_unit(ushash, ptile, punit);
109 } unit_list_iterate_end;
112 /* Add units on the tile (SELLOC_UNITS). */
113 unit_list_iterate(ptile->units, punit) {
114 /* Save all top level transporters on the tile (SELLOC_UNITS) as 'idle'
115 * units (ACTIVITY_IDLE). */
116 if (!unit_transported(punit)) {
117 struct usdata *data;
118 struct unit_type *ptype = unit_type_get(punit);
120 usdata_hash_lookup(ushash, utype_index(ptype), &data);
122 if (!data) {
123 data = usdata_new();
124 data->utype = ptype;
125 usdata_hash_insert(ushash, utype_index(ptype), data);
128 unit_list_append(data->units[SELLOC_UNITS][ACTIVITY_IDLE], punit);
130 } unit_list_iterate_end;
132 return ushash;
135 /*****************************************************************************
136 Destroy a unit selection data set.
137 *****************************************************************************/
138 void usdlg_data_destroy(struct usdata_hash *ushash)
140 usdata_hash_data_iterate(ushash, data) {
141 usdata_destroy(data);
142 } usdata_hash_data_iterate_end;
143 usdata_hash_destroy(ushash);
146 /*****************************************************************************
147 Add a unit into the unit selection data hash.
148 *****************************************************************************/
149 static void usdlg_data_add_unit(struct usdata_hash *ushash,
150 const struct tile *ptile,
151 struct unit *punit)
153 struct usdata *data;
154 enum unit_activity act;
155 struct unit_type *ptype = unit_type_get(punit);
157 fc_assert_ret(ushash);
158 fc_assert_ret(punit);
160 usdata_hash_lookup(ushash, utype_index(ptype), &data);
162 if (!data) {
163 data = usdata_new();
164 data->utype = ptype;
165 usdata_hash_insert(ushash, utype_index(ptype), data);
168 for (act = 0; act < ACTIVITY_LAST; act++) {
169 if (usdlg_check_unit_activity(punit, act)) {
170 enum unit_select_location_mode loc;
172 for (loc = unit_select_location_mode_begin();
173 loc != unit_select_location_mode_end();
174 loc = unit_select_location_mode_next(loc)) {
175 if (usdlg_check_unit_location(punit, ptile, loc)) {
176 unit_list_append(data->units[loc][act], punit);
183 /*****************************************************************************
184 Returns TRUE if the unit activity is equal to 'act'.
185 *****************************************************************************/
186 static bool usdlg_check_unit_activity(const struct unit *punit,
187 enum unit_activity act)
189 fc_assert_ret_val(punit != NULL, FALSE);
191 return (punit->activity == act);
194 /*****************************************************************************
195 Returns TRUE if the unit locations corresponds to 'loc'.
196 *****************************************************************************/
197 static bool usdlg_check_unit_location(const struct unit *punit,
198 const struct tile *ptile,
199 enum unit_select_location_mode loc)
201 struct tile *utile;
203 fc_assert_ret_val(punit != NULL, FALSE);
205 utile = unit_tile(punit);
207 fc_assert_ret_val(utile != NULL, FALSE);
209 switch (loc) {
210 case SELLOC_UNITS:
211 /* Special case - never TRUE. See usdlg_data_new(). */
212 return FALSE;
213 break;
214 case SELLOC_TILE:
215 if (utile == ptile) {
216 return TRUE;
218 break;
219 case SELLOC_CONT:
220 if (!is_ocean(tile_terrain(utile))
221 && utype_move_type(unit_type_get(punit)) == UMT_LAND
222 && tile_continent(utile) == tile_continent(ptile)) {
223 return TRUE;
225 break;
226 case SELLOC_WORLD:
227 return TRUE;
228 break;
229 case SELLOC_LAND:
230 if (utype_move_type(unit_type_get(punit)) == UMT_LAND
231 && (!is_ocean(tile_terrain(utile)) || tile_city(utile) != NULL)) {
232 return TRUE;
234 break;
235 case SELLOC_SEA:
236 if (utype_move_type(unit_type_get(punit)) == UMT_SEA
237 && (is_ocean(tile_terrain(utile)) || tile_city(utile) != NULL)) {
238 return TRUE;
240 break;
241 case SELLOC_BOTH:
242 if (utype_move_type(unit_type_get(punit)) == UMT_BOTH) {
243 return TRUE;
245 break;
246 case SELLOC_COUNT:
247 /* Invalid. */
248 fc_assert_ret_val(loc != SELLOC_COUNT, FALSE);
249 break;
252 return FALSE;