1 #include "empire.h"
2
3 #include "building/count.h"
4 #include "city/constants.h"
5 #include "city/population.h"
6 #include "city/resource.h"
7 #include "core/calc.h"
8 #include "core/config.h"
9 #include "core/log.h"
10 #include "core/io.h"
11 #include "empire/city.h"
12 #include "empire/object.h"
13 #include "empire/trade_route.h"
14
15 #include <string.h>
16
17 enum {
18 EMPIRE_WIDTH = 2000,
19 EMPIRE_HEIGHT = 1000,
20 EMPIRE_HEADER_SIZE = 1280,
21 EMPIRE_DATA_SIZE = 12800
22 };
23
24 static struct {
25 int initial_scroll_x;
26 int initial_scroll_y;
27 int scroll_x;
28 int scroll_y;
29 int selected_object;
30 int viewport_width;
31 int viewport_height;
32 } data;
33
empire_load(int is_custom_scenario,int empire_id)34 void empire_load(int is_custom_scenario, int empire_id)
35 {
36 char raw_data[EMPIRE_DATA_SIZE];
37 const char *filename = is_custom_scenario ? "c32.emp" : "c3.emp";
38
39 // read header with scroll positions
40 if (!io_read_file_part_into_buffer(filename, NOT_LOCALIZED, raw_data, 4, 32 * empire_id)) {
41 memset(raw_data, 0, 4);
42 }
43 buffer buf;
44 buffer_init(&buf, raw_data, 4);
45 data.initial_scroll_x = buffer_read_i16(&buf);
46 data.initial_scroll_y = buffer_read_i16(&buf);
47
48 // read data section with objects
49 int offset = EMPIRE_HEADER_SIZE + EMPIRE_DATA_SIZE * empire_id;
50 int read_size = io_read_file_part_into_buffer(filename, NOT_LOCALIZED, raw_data, EMPIRE_DATA_SIZE, offset);
51 if (read_size != EMPIRE_DATA_SIZE) {
52 // load empty empire when loading fails
53 log_error("Unable to load empire data from file", filename, 0);
54 memset(raw_data, 0, EMPIRE_DATA_SIZE);
55 }
56 buffer_init(&buf, raw_data, EMPIRE_DATA_SIZE);
57 empire_object_load(&buf);
58 }
59
check_scroll_boundaries(void)60 static void check_scroll_boundaries(void)
61 {
62 int max_x = EMPIRE_WIDTH - data.viewport_width;
63 int max_y = EMPIRE_HEIGHT - data.viewport_height;
64
65 data.scroll_x = calc_bound(data.scroll_x, 0, max_x);
66 data.scroll_y = calc_bound(data.scroll_y, 0, max_y);
67 }
68
empire_load_editor(int empire_id,int viewport_width,int viewport_height)69 void empire_load_editor(int empire_id, int viewport_width, int viewport_height)
70 {
71 empire_load(1, empire_id);
72 empire_object_init_cities();
73
74 const empire_object *our_city = empire_object_get_our_city();
75
76 data.viewport_width = viewport_width;
77 data.viewport_height = viewport_height;
78 if (our_city) {
79 data.scroll_x = our_city->x - data.viewport_width / 2;
80 data.scroll_y = our_city->y - data.viewport_height / 2;
81 } else {
82 data.scroll_x = data.initial_scroll_x;
83 data.scroll_y = data.initial_scroll_y;
84 }
85 check_scroll_boundaries();
86 }
87
empire_init_scenario(void)88 void empire_init_scenario(void)
89 {
90 data.scroll_x = data.initial_scroll_x;
91 data.scroll_y = data.initial_scroll_y;
92 data.viewport_width = EMPIRE_WIDTH;
93 data.viewport_height = EMPIRE_HEIGHT;
94
95 empire_object_init_cities();
96 }
97
empire_set_viewport(int width,int height)98 void empire_set_viewport(int width, int height)
99 {
100 data.viewport_width = width;
101 data.viewport_height = height;
102 check_scroll_boundaries();
103 }
104
empire_adjust_scroll(int * x_offset,int * y_offset)105 void empire_adjust_scroll(int *x_offset, int *y_offset)
106 {
107 *x_offset = *x_offset - data.scroll_x;
108 *y_offset = *y_offset - data.scroll_y;
109 }
110
empire_scroll_map(int x,int y)111 void empire_scroll_map(int x, int y)
112 {
113 data.scroll_x += x;
114 data.scroll_y += y;
115 check_scroll_boundaries();
116 }
117
empire_selected_object(void)118 int empire_selected_object(void)
119 {
120 return data.selected_object;
121 }
122
empire_clear_selected_object(void)123 void empire_clear_selected_object(void)
124 {
125 data.selected_object = 0;
126 }
127
empire_select_object(int x,int y)128 void empire_select_object(int x, int y)
129 {
130 int map_x = x + data.scroll_x;
131 int map_y = y + data.scroll_y;
132
133 data.selected_object = empire_object_get_closest(map_x, map_y);
134 }
135
empire_can_export_resource_to_city(int city_id,int resource)136 int empire_can_export_resource_to_city(int city_id, int resource)
137 {
138 empire_city *city = empire_city_get(city_id);
139 if (city_id && trade_route_limit_reached(city->route_id, resource)) {
140 // quota reached
141 return 0;
142 }
143 int in_stock = city_resource_count(resource);
144 if (resource_is_food(resource) && config_get(CONFIG_GP_CH_ALLOW_EXPORTING_FROM_GRANARIES)) {
145 in_stock += city_resource_count_food_on_granaries(resource) / RESOURCE_GRANARY_ONE_LOAD;
146 }
147
148 if (in_stock <= city_resource_export_over(resource)) {
149 // stocks too low
150 return 0;
151 }
152 if (city_id == 0 || city->buys_resource[resource]) {
153 return (city_resource_trade_status(resource) & TRADE_STATUS_EXPORT) == TRADE_STATUS_EXPORT;
154 } else {
155 return 0;
156 }
157 }
158
159 /**static int get_max_stock_for_population(void)
160 {
161 int population = city_population();
162 if (population < 2000) {
163 return 10;
164 } else if (population < 4000) {
165 return 20;
166 } else if (population < 6000) {
167 return 30;
168 } else {
169 return 40;
170 }
171 }**/
172
empire_can_import_resource_from_city(int city_id,int resource)173 int empire_can_import_resource_from_city(int city_id, int resource)
174 {
175 empire_city *city = empire_city_get(city_id);
176 if (!city->sells_resource[resource]) {
177 return 0;
178 }
179 if (!(city_resource_trade_status(resource) & TRADE_STATUS_IMPORT)) {
180 return 0;
181 }
182 if (trade_route_limit_reached(city->route_id, resource)) {
183 return 0;
184 }
185
186 int in_stock = city_resource_count(resource);
187 if (resource_is_food(resource)) {
188 in_stock += city_resource_count_food_on_granaries(resource) / RESOURCE_GRANARY_ONE_LOAD;
189 }
190 int max_in_stock = 0;
191 /* NOTE: don't forget to uncomment function get_max_stock_for_population
192
193 int finished_good = RESOURCE_NONE;
194 switch (resource) {
195 // food and finished materials
196 case RESOURCE_WHEAT:
197 case RESOURCE_VEGETABLES:
198 case RESOURCE_FRUIT:
199 case RESOURCE_MEAT:
200 case RESOURCE_POTTERY:
201 case RESOURCE_FURNITURE:
202 case RESOURCE_OIL:
203 case RESOURCE_WINE:
204 max_in_stock = get_max_stock_for_population();
205 break;
206
207 case RESOURCE_MARBLE:
208 case RESOURCE_WEAPONS:
209 max_in_stock = 10;
210 break;
211
212 case RESOURCE_CLAY:
213 finished_good = RESOURCE_POTTERY;
214 break;
215 case RESOURCE_TIMBER:
216 finished_good = RESOURCE_FURNITURE;
217 break;
218 case RESOURCE_OLIVES:
219 finished_good = RESOURCE_OIL;
220 break;
221 case RESOURCE_VINES:
222 finished_good = RESOURCE_WINE;
223 break;
224 case RESOURCE_IRON:
225 finished_good = RESOURCE_WEAPONS;
226 break;
227 }
228 if (finished_good) {
229 max_in_stock = 2 + 2 * building_count_industry_active(finished_good);
230 }*/
231 max_in_stock = city_resource_import_over(resource);
232 return (max_in_stock == 0 || in_stock < max_in_stock) ? 1 : 0;
233 }
234
empire_save_state(buffer * buf)235 void empire_save_state(buffer *buf)
236 {
237 buffer_write_i32(buf, data.scroll_x);
238 buffer_write_i32(buf, data.scroll_y);
239 buffer_write_i32(buf, data.selected_object);
240 }
241
empire_load_state(buffer * buf)242 void empire_load_state(buffer *buf)
243 {
244 data.scroll_x = buffer_read_i32(buf);
245 data.scroll_y = buffer_read_i32(buf);
246 data.selected_object = buffer_read_i32(buf);
247 }
248