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)
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>
27 #include "client_main.h"
30 #include "unitselect_common.h"
32 static void usdlg_data_add_unit(struct usdata_hash
*ushash
,
33 const struct tile
*ptile
,
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
));
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();
69 /*****************************************************************************
70 Destroy a unit selection struct.
71 *****************************************************************************/
72 static void usdata_destroy(struct usdata
*data
)
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
]);
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
;
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
)) {
118 struct unit_type
*ptype
= unit_type_get(punit
);
120 usdata_hash_lookup(ushash
, utype_index(ptype
), &data
);
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
;
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
,
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
);
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
)
203 fc_assert_ret_val(punit
!= NULL
, FALSE
);
205 utile
= unit_tile(punit
);
207 fc_assert_ret_val(utile
!= NULL
, FALSE
);
211 /* Special case - never TRUE. See usdlg_data_new(). */
215 if (utile
== ptile
) {
220 if (!is_ocean(tile_terrain(utile
))
221 && utype_move_type(unit_type_get(punit
)) == UMT_LAND
222 && tile_continent(utile
) == tile_continent(ptile
)) {
230 if (utype_move_type(unit_type_get(punit
)) == UMT_LAND
231 && (!is_ocean(tile_terrain(utile
)) || tile_city(utile
) != NULL
)) {
236 if (utype_move_type(unit_type_get(punit
)) == UMT_SEA
237 && (is_ocean(tile_terrain(utile
)) || tile_city(utile
) != NULL
)) {
242 if (utype_move_type(unit_type_get(punit
)) == UMT_BOTH
) {
248 fc_assert_ret_val(loc
!= SELLOC_COUNT
, FALSE
);