1 #include "construction_clear.h"
2 
3 #include "building/building.h"
4 #include "city/warning.h"
5 #include "core/config.h"
6 #include "figuretype/migrant.h"
7 #include "game/undo.h"
8 #include "graphics/window.h"
9 #include "map/aqueduct.h"
10 #include "map/bridge.h"
11 #include "map/building.h"
12 #include "map/building_tiles.h"
13 #include "map/grid.h"
14 #include "map/property.h"
15 #include "map/routing_terrain.h"
16 #include "map/terrain.h"
17 #include "map/tiles.h"
18 #include "window/popup_dialog.h"
19 
20 static struct {
21     int x_start;
22     int y_start;
23     int x_end;
24     int y_end;
25     int bridge_confirmed;
26     int fort_confirmed;
27 } confirm;
28 
get_deletable_building(int grid_offset)29 static building *get_deletable_building(int grid_offset)
30 {
31     int building_id = map_building_at(grid_offset);
32     if (!building_id) {
33         return 0;
34     }
35     building *b = building_main(building_get(building_id));
36     if (b->type == BUILDING_BURNING_RUIN || b->type == BUILDING_NATIVE_CROPS ||
37         b->type == BUILDING_NATIVE_HUT || b->type == BUILDING_NATIVE_MEETING) {
38         return 0;
39     }
40     if (b->state == BUILDING_STATE_DELETED_BY_PLAYER || b->is_deleted) {
41         return 0;
42     }
43     return b;
44 }
45 
clear_land_confirmed(int measure_only,int x_start,int y_start,int x_end,int y_end)46 static int clear_land_confirmed(int measure_only, int x_start, int y_start, int x_end, int y_end)
47 {
48     int items_placed = 0;
49     game_undo_restore_building_state();
50     game_undo_restore_map(0);
51 
52     int x_min, x_max, y_min, y_max;
53     map_grid_start_end_to_area(x_start, y_start, x_end, y_end, &x_min, &y_min, &x_max, &y_max);
54 
55     int visual_feedback_on_delete = config_get(CONFIG_UI_VISUAL_FEEDBACK_ON_DELETE);
56 
57     for (int y = y_min; y <= y_max; y++) {
58         for (int x = x_min; x <= x_max; x++) {
59             int grid_offset = map_grid_offset(x, y);
60             if (measure_only && visual_feedback_on_delete) {
61                 building *b = get_deletable_building(grid_offset);
62                 if (map_property_is_deleted(grid_offset) || (b && map_property_is_deleted(b->grid_offset))) {
63                     continue;
64                 }
65                 map_building_tiles_mark_deleting(grid_offset);
66                 if (map_terrain_is(grid_offset, TERRAIN_BUILDING)) {
67                     if (b) {
68                         items_placed++;
69                     }
70                 } else if (map_terrain_is(grid_offset, TERRAIN_ROCK | TERRAIN_ELEVATION)) {
71                     continue;
72                 } else if (map_terrain_is(grid_offset, TERRAIN_WATER)) { // keep the "bridge is free" bug from C3
73                     continue;
74                 } else if (map_terrain_is(grid_offset, TERRAIN_AQUEDUCT)
75                     || map_terrain_is(grid_offset, TERRAIN_NOT_CLEAR)) {
76                     items_placed++;
77                 }
78                 continue;
79             }
80             if (map_terrain_is(grid_offset, TERRAIN_ROCK | TERRAIN_ELEVATION)) {
81                 continue;
82             }
83             if (map_terrain_is(grid_offset, TERRAIN_BUILDING)) {
84                 building *b = get_deletable_building(grid_offset);
85                 if (!b) {
86                     continue;
87                 }
88                 if (b->type == BUILDING_FORT_GROUND || b->type == BUILDING_FORT) {
89                     if (!measure_only && confirm.fort_confirmed != 1) {
90                         continue;
91                     }
92                     if (!measure_only && confirm.fort_confirmed == 1) {
93                         game_undo_disable();
94                     }
95                 }
96                 if (b->house_size && b->house_population && !measure_only) {
97                     figure_create_homeless(b->x, b->y, b->house_population);
98                     b->house_population = 0;
99                 }
100                 if (b->state != BUILDING_STATE_DELETED_BY_PLAYER) {
101                     items_placed++;
102                     game_undo_add_building(b);
103                 }
104                 b->state = BUILDING_STATE_DELETED_BY_PLAYER;
105                 b->is_deleted = 1;
106                 building *space = b;
107                 for (int i = 0; i < 9; i++) {
108                     if (space->prev_part_building_id <= 0) {
109                         break;
110                     }
111                     space = building_get(space->prev_part_building_id);
112                     game_undo_add_building(space);
113                     space->state = BUILDING_STATE_DELETED_BY_PLAYER;
114                 }
115                 space = b;
116                 for (int i = 0; i < 9; i++) {
117                     space = building_next(space);
118                     if (space->id <= 0) {
119                         break;
120                     }
121                     game_undo_add_building(space);
122                     space->state = BUILDING_STATE_DELETED_BY_PLAYER;
123                 }
124             } else if (map_terrain_is(grid_offset, TERRAIN_AQUEDUCT)) {
125                 map_terrain_remove(grid_offset, TERRAIN_CLEARABLE);
126                 items_placed++;
127                 map_aqueduct_remove(grid_offset);
128             } else if (map_terrain_is(grid_offset, TERRAIN_WATER)) {
129                 if (!measure_only && map_bridge_count_figures(grid_offset) > 0) {
130                     city_warning_show(WARNING_PEOPLE_ON_BRIDGE);
131                 } else if (confirm.bridge_confirmed == 1) {
132                     map_bridge_remove(grid_offset, measure_only);
133                     items_placed++;
134                 }
135             } else if (map_terrain_is(grid_offset, TERRAIN_NOT_CLEAR)) {
136                 if (map_terrain_is(grid_offset, TERRAIN_ROAD)) {
137                     map_property_clear_plaza_or_earthquake(grid_offset);
138                 }
139                 map_terrain_remove(grid_offset, TERRAIN_CLEARABLE);
140                 items_placed++;
141             }
142         }
143     }
144     if (!measure_only || !visual_feedback_on_delete) {
145         int radius;
146         if (x_max - x_min <= y_max - y_min) {
147             radius = y_max - y_min + 3;
148         } else {
149             radius = x_max - x_min + 3;
150         }
151         map_tiles_update_region_empty_land(x_min, y_min, x_max, y_max);
152         map_tiles_update_region_meadow(x_min, y_min, x_max, y_max);
153         map_tiles_update_region_rubble(x_min, y_min, x_max, y_max);
154         map_tiles_update_all_gardens();
155         map_tiles_update_area_roads(x_min, y_min, radius);
156         map_tiles_update_all_plazas();
157         map_tiles_update_area_walls(x_min, y_min, radius);
158         map_tiles_update_region_aqueducts(x_min - 3, y_min - 3, x_max + 3, y_max + 3);
159     }
160     if (!measure_only) {
161         map_routing_update_land();
162         map_routing_update_walls();
163         map_routing_update_water();
164         window_invalidate();
165     }
166     return items_placed;
167 }
168 
confirm_delete_fort(int accepted)169 static void confirm_delete_fort(int accepted)
170 {
171     if (accepted == 1) {
172         confirm.fort_confirmed = 1;
173     } else {
174         confirm.fort_confirmed = -1;
175     }
176     clear_land_confirmed(0, confirm.x_start, confirm.y_start, confirm.x_end, confirm.y_end);
177 }
178 
confirm_delete_bridge(int accepted)179 static void confirm_delete_bridge(int accepted)
180 {
181     if (accepted == 1) {
182         confirm.bridge_confirmed = 1;
183     } else {
184         confirm.bridge_confirmed = -1;
185     }
186     clear_land_confirmed(0, confirm.x_start, confirm.y_start, confirm.x_end, confirm.y_end);
187 }
188 
building_construction_clear_land(int measure_only,int x_start,int y_start,int x_end,int y_end)189 int building_construction_clear_land(int measure_only, int x_start, int y_start, int x_end, int y_end)
190 {
191     confirm.fort_confirmed = 0;
192     confirm.bridge_confirmed = 0;
193     if (measure_only) {
194         return clear_land_confirmed(measure_only, x_start, y_start, x_end, y_end);
195     }
196 
197     int x_min, x_max, y_min, y_max;
198     map_grid_start_end_to_area(x_start, y_start, x_end, y_end, &x_min, &y_min, &x_max, &y_max);
199 
200     int ask_confirm_bridge = 0;
201     int ask_confirm_fort = 0;
202     for (int y = y_min; y <= y_max; y++) {
203         for (int x = x_min; x <= x_max; x++) {
204             int grid_offset = map_grid_offset(x, y);
205             int building_id = map_building_at(grid_offset);
206             if (building_id) {
207                 building *b = building_get(building_id);
208                 if (b->type == BUILDING_FORT || b->type == BUILDING_FORT_GROUND) {
209                     ask_confirm_fort = 1;
210                 }
211             }
212             if (map_is_bridge(grid_offset)) {
213                 ask_confirm_bridge = 1;
214             }
215         }
216     }
217     confirm.x_start = x_start;
218     confirm.y_start = y_start;
219     confirm.x_end = x_end;
220     confirm.y_end = y_end;
221     if (ask_confirm_fort) {
222         window_popup_dialog_show(POPUP_DIALOG_DELETE_FORT, confirm_delete_fort, 2);
223         return -1;
224     } else if (ask_confirm_bridge) {
225         window_popup_dialog_show(POPUP_DIALOG_DELETE_BRIDGE, confirm_delete_bridge, 2);
226         return -1;
227     } else {
228         return clear_land_confirmed(measure_only, x_start, y_start, x_end, y_end);
229     }
230 }
231