1 /* ---------------------------------------------------------------------- *
2  * port.c
3  * This file is part of lincity.
4  * Lincity is copyright (c) I J Peters 1995-1997, (c) Greg Sharp 1997-2001.
5  * (c) Corey Keasling, 2004
6  * ---------------------------------------------------------------------- */
7 
8 #include "modules.h"
9 #include "port.h"
10 
buy_food(int xt,int yt)11 static int buy_food(int xt, int yt)
12 {
13     int i = 0;
14     if (MP_GROUP(xt, yt) == GROUP_TRACK) {
15         if (MP_INFO(xt, yt).int_1 < MAX_FOOD_ON_TRACK)
16             i = MAX_FOOD_ON_TRACK - MP_INFO(xt, yt).int_1;
17     } else if (MP_GROUP(xt, yt) == GROUP_ROAD) {
18         if (MP_INFO(xt, yt).int_1 < MAX_FOOD_ON_ROAD)
19             i = MAX_FOOD_ON_ROAD - MP_INFO(xt, yt).int_1;
20     } else if (MP_GROUP(xt, yt) == GROUP_RAIL) {
21         if (MP_INFO(xt, yt).int_1 < MAX_FOOD_ON_RAIL)
22             i = MAX_FOOD_ON_RAIL - MP_INFO(xt, yt).int_1;
23     }
24     i = (i * PORT_IMPORT_RATE) / 1000;
25     MP_INFO(xt, yt).int_1 += i;
26     return (i * PORT_FOOD_RATE);
27 }
28 
buy_coal(int xt,int yt)29 static int buy_coal(int xt, int yt)
30 {
31     int i = 0;
32     if (MP_GROUP(xt, yt) == GROUP_TRACK) {
33         if (MP_INFO(xt, yt).int_3 < MAX_COAL_ON_TRACK)
34             i = MAX_COAL_ON_TRACK - MP_INFO(xt, yt).int_3;
35     } else if (MP_GROUP(xt, yt) == GROUP_ROAD) {
36         if (MP_INFO(xt, yt).int_3 < MAX_COAL_ON_ROAD)
37             i = MAX_COAL_ON_ROAD - MP_INFO(xt, yt).int_3;
38     } else if (MP_GROUP(xt, yt) == GROUP_RAIL) {
39         if (MP_INFO(xt, yt).int_3 < MAX_COAL_ON_RAIL)
40             i = MAX_COAL_ON_RAIL - MP_INFO(xt, yt).int_3;
41     }
42     i = (i * PORT_IMPORT_RATE) / 1000;
43     MP_INFO(xt, yt).int_3 += i;
44     return (i * PORT_COAL_RATE);
45 }
46 
buy_ore(int xt,int yt)47 static int buy_ore(int xt, int yt)
48 {
49     int i = 0;
50     if (MP_GROUP(xt, yt) == GROUP_TRACK) {
51         if (MP_INFO(xt, yt).int_5 < MAX_ORE_ON_TRACK)
52             i = MAX_ORE_ON_TRACK - MP_INFO(xt, yt).int_5;
53     } else if (MP_GROUP(xt, yt) == GROUP_ROAD) {
54         if (MP_INFO(xt, yt).int_5 < MAX_ORE_ON_ROAD)
55             i = MAX_ORE_ON_ROAD - MP_INFO(xt, yt).int_5;
56     } else if (MP_GROUP(xt, yt) == GROUP_RAIL) {
57         if (MP_INFO(xt, yt).int_5 < MAX_ORE_ON_RAIL)
58             i = MAX_ORE_ON_RAIL - MP_INFO(xt, yt).int_5;
59     }
60     i = (i * PORT_IMPORT_RATE) / 1000;
61     MP_INFO(xt, yt).int_5 += i;
62     return (i * PORT_ORE_RATE);
63 }
64 
buy_goods(int xt,int yt)65 static int buy_goods(int xt, int yt)
66 {
67     int i = 0;
68     if (MP_GROUP(xt, yt) == GROUP_TRACK) {
69         if (MP_INFO(xt, yt).int_4 < MAX_GOODS_ON_TRACK)
70             i = MAX_GOODS_ON_TRACK - MP_INFO(xt, yt).int_4;
71     } else if (MP_GROUP(xt, yt) == GROUP_ROAD) {
72         if (MP_INFO(xt, yt).int_4 < MAX_GOODS_ON_ROAD)
73             i = MAX_GOODS_ON_ROAD - MP_INFO(xt, yt).int_4;
74     } else if (MP_GROUP(xt, yt) == GROUP_RAIL) {
75         if (MP_INFO(xt, yt).int_4 < MAX_GOODS_ON_RAIL)
76             i = MAX_GOODS_ON_RAIL - MP_INFO(xt, yt).int_4;
77     }
78     i = (i * PORT_IMPORT_RATE) / 1000;
79     MP_INFO(xt, yt).int_4 += i;
80     return (i * PORT_GOODS_RATE);
81 }
82 
buy_steel(int xt,int yt)83 static int buy_steel(int xt, int yt)
84 {
85     int i = 0;
86     if (MP_GROUP(xt, yt) == GROUP_TRACK) {
87         if (MP_INFO(xt, yt).int_6 < MAX_STEEL_ON_TRACK)
88             i = MAX_STEEL_ON_TRACK - MP_INFO(xt, yt).int_6;
89     } else if (MP_GROUP(xt, yt) == GROUP_ROAD) {
90         if (MP_INFO(xt, yt).int_6 < MAX_STEEL_ON_ROAD)
91             i = MAX_STEEL_ON_ROAD - MP_INFO(xt, yt).int_6;
92     } else if (MP_GROUP(xt, yt) == GROUP_RAIL) {
93         if (MP_INFO(xt, yt).int_6 < MAX_STEEL_ON_RAIL)
94             i = MAX_STEEL_ON_RAIL - MP_INFO(xt, yt).int_6;
95     }
96     i = (i * PORT_IMPORT_RATE) / 1000;
97     MP_INFO(xt, yt).int_6 += i;
98     return (i * PORT_STEEL_RATE);
99 }
100 
sell_food(int xt,int yt)101 static int sell_food(int xt, int yt)
102 {
103     int i = 0;
104     i = (MP_INFO(xt, yt).int_1 * PORT_EXPORT_RATE) / 1000;
105     MP_INFO(xt, yt).int_1 -= i;
106     return (i * PORT_FOOD_RATE);
107 }
108 
sell_coal(int xt,int yt)109 static int sell_coal(int xt, int yt)
110 {
111     int i = 0;
112     i = (MP_INFO(xt, yt).int_3 * PORT_EXPORT_RATE) / 1000;
113     MP_INFO(xt, yt).int_3 -= i;
114     return (i * PORT_COAL_RATE);
115 }
116 
sell_ore(int xt,int yt)117 static int sell_ore(int xt, int yt)
118 {
119     int i = 0;
120     i = (MP_INFO(xt, yt).int_5 * PORT_EXPORT_RATE) / 1000;
121     MP_INFO(xt, yt).int_5 -= i;
122     return (i * PORT_ORE_RATE);
123 }
124 
sell_goods(int xt,int yt)125 static int sell_goods(int xt, int yt)
126 {
127     int i = 0;
128     i = (MP_INFO(xt, yt).int_4 * PORT_EXPORT_RATE) / 1000;
129     MP_INFO(xt, yt).int_4 -= i;
130     return (i * PORT_GOODS_RATE);
131 }
132 
sell_steel(int xt,int yt)133 static int sell_steel(int xt, int yt)
134 {
135     int i = 0;
136     i = (MP_INFO(xt, yt).int_6 * PORT_EXPORT_RATE) / 1000;
137     MP_INFO(xt, yt).int_6 -= i;
138     return (i * PORT_STEEL_RATE);
139 }
140 
141 /* Trade with a transport.
142  * Port is at x/y, transport at u/v. */
trade_connection(const int x,const int y,const int u,const int v,int * ic_ptr,int * et_ptr)143 static void trade_connection(const int x, const int y, const int u, const int v, int *ic_ptr, int *et_ptr)
144 {
145     if (u >= 0 && v >= 0 && (MP_INFO(u, v).flags & FLAG_IS_TRANSPORT) != 0) {
146         //printf("Port %i/%i trading with transport %i/%i\n", x,y,u,v);
147         int i, flags;
148         int ic = 0;
149         int et = 0;
150         flags = MP_INFO(x, y).flags;
151         if ((flags & FLAG_MB_FOOD) != 0) {
152             i = buy_food(u, v);
153             ic += i;
154             MP_INFO(x + 1, y).int_3 += i;
155         }
156         if ((flags & FLAG_MS_FOOD) != 0) {
157             i = sell_food(u, v);
158             et += i;
159             MP_INFO(x + 2, y).int_3 += i;
160         }
161         if ((flags & FLAG_MB_COAL) != 0) {
162             i = buy_coal(u, v);
163             ic += i;
164             MP_INFO(x + 1, y).int_4 += i;
165         }
166         if ((flags & FLAG_MS_COAL) != 0) {
167             i = sell_coal(u, v);
168             et += i;
169             MP_INFO(x + 2, y).int_4 += i;
170         }
171         if ((flags & FLAG_MB_ORE) != 0) {
172             i = buy_ore(u, v);
173             ic += i;
174             MP_INFO(x + 1, y).int_5 += i;
175         }
176         if ((flags & FLAG_MS_ORE) != 0) {
177             i = sell_ore(u, v);
178             et += i;
179             MP_INFO(x + 2, y).int_5 += i;
180         }
181         if ((flags & FLAG_MB_GOODS) != 0) {
182             i = buy_goods(u, v);
183             ic += i;
184             MP_INFO(x + 1, y).int_6 += i;
185         }
186         if ((flags & FLAG_MS_GOODS) != 0) {
187             i = sell_goods(u, v);
188             et += i;
189             MP_INFO(x + 2, y).int_6 += i;
190         }
191         if ((flags & FLAG_MB_STEEL) != 0) {
192             i = buy_steel(u, v);
193             ic += i;
194             MP_INFO(x + 1, y).int_7 += i;
195         }
196         if ((flags & FLAG_MS_STEEL) != 0) {
197             i = sell_steel(u, v);
198             et += i;
199             MP_INFO(x + 2, y).int_7 += i;
200         }
201         *ic_ptr += ic;
202         *et_ptr += et;
203     }
204 }
205 
do_port(int x,int y)206 void do_port(int x, int y)
207 {
208     /*
209        // int_1 is the money made so far this month
210        // int_2 is the money made last month
211        // int_3 holds the 'pence/pennies/bits' to add next time round.
212        // int_4 is the import costs so far this month
213        // int_5 is the import costs for last month
214        // Use int_3 to int_7 of (x+1,y) to hold the individual buy values
215        //                       (x,y+1) is last month's
216        // Use int_3 to int_7 of (x+2,y) to hold the individual sell values
217        //                       (x,y+2) is last month's
218      */
219     int i, et = 0, ic = 0, *b1, *b2, *s1, *s2, a;
220 
221     /* left connection first */
222     for (a = 0; a < 4; a++)     //try anywhere on the west side.
223         if (x >= 0 && y >= 0 && (MP_INFO(x - 1, y + a).flags & FLAG_IS_TRANSPORT) != 0) {
224             trade_connection(x, y, x - 1, y + a, &ic, &et);
225             break;
226         }
227     /* upper gate next */
228     bool deal = false;
229     for (a = 0; a < 3; a++)     //try north
230         if (x >= 0 && y >= 0 && (MP_INFO(x + a, y - 1).flags & FLAG_IS_TRANSPORT) != 0) {
231             trade_connection(x, y, x + a, y - 1, &ic, &et);
232             deal = false;
233             break;
234         }
235     if (!deal)
236         for (a = 0; a < 3; a++) //try south
237             if (x >= 0 && y >= 0 && (MP_INFO(x + a, y + 4).flags & FLAG_IS_TRANSPORT) != 0) {
238                 trade_connection(x, y, x + a, y + 4, &ic, &et);
239                 break;
240             }
241 
242     MP_INFO(x, y).int_1 += et;
243     MP_INFO(x, y).int_4 += ic;
244     if (total_time % 100 == 0) {
245         MP_INFO(x, y).int_2 = MP_INFO(x, y).int_1;
246         MP_INFO(x, y).int_1 = 0;
247         MP_INFO(x, y).int_5 = MP_INFO(x, y).int_4;
248         MP_INFO(x, y).int_4 = 0;
249         b1 = &(MP_INFO(x + 1, y).int_3);
250         s1 = &(MP_INFO(x + 2, y).int_3);
251         b2 = &(MP_INFO(x, y + 1).int_3);
252         s2 = &(MP_INFO(x, y + 2).int_3);
253         /* GCS FIX -- This obfuscation is unnecessary. */
254         for (i = 0; i < 5; i++) {
255             *(b2++) = *b1;
256             *(s2++) = *s1;
257             *(b1++) = 0;
258             *(s1++) = 0;
259         }
260     }
261     if (et > 0) {
262         sust_port_flag = 0;
263         tech_level++;
264     }
265     if (ic > 0) {
266         sust_port_flag = 0;
267         tech_level++;
268     }
269     et += MP_INFO(x, y).int_3;  /* int_3 holds the 'pence' */
270 
271     export_tax += et / 100;
272     MP_INFO(x, y).int_3 = et % 100;
273     import_cost += ic;
274 }
275 
mps_port(int x,int y)276 void mps_port(int x, int y)
277 {
278     int i = 0;
279     char buy[12], sell[12];
280 
281     mps_store_title(i++, _("Port"));
282     i++;
283 
284     num_to_ansi(buy, sizeof(buy), MP_INFO(x, y + 1).int_3 / 100);
285     num_to_ansi(sell, sizeof(sell), MP_INFO(x, y + 2).int_3 / 100);
286     mps_store_sss(i++, _("Food"), buy, sell);
287 
288     num_to_ansi(buy, sizeof(buy), MP_INFO(x, y + 1).int_4 / 100);
289     num_to_ansi(sell, sizeof(sell), MP_INFO(x, y + 2).int_4 / 100);
290     mps_store_sss(i++, _("Coal"), buy, sell);
291 
292     num_to_ansi(buy, sizeof(buy), MP_INFO(x, y + 1).int_5 / 100);
293     num_to_ansi(sell, sizeof(sell), MP_INFO(x, y + 2).int_5 / 100);
294     mps_store_sss(i++, _("Ore"), buy, sell);
295 
296     num_to_ansi(buy, sizeof(buy), MP_INFO(x, y + 1).int_6 / 100);
297     num_to_ansi(sell, sizeof(sell), MP_INFO(x, y + 2).int_6 / 100);
298     mps_store_sss(i++, _("Goods"), buy, sell);
299 
300     num_to_ansi(buy, sizeof(buy), MP_INFO(x, y + 1).int_7 / 100);
301     num_to_ansi(sell, sizeof(sell), MP_INFO(x, y + 2).int_7 / 100);
302     mps_store_sss(i++, _("Steel"), buy, sell);
303 
304     num_to_ansi(buy, sizeof(buy), MP_INFO(x, y).int_5 / 100);
305     num_to_ansi(sell, sizeof(sell), MP_INFO(x, y).int_2 / 100);
306     mps_store_sss(i++, _("Total"), buy, sell);
307 
308 }
309