1 /* ---------------------------------------------------------------------- *
2  * market.c
3  * This file is part of lincity.
4  * Lincity is copyright (c) I J Peters 1995-1997, (c) Greg Sharp 1997-2001.
5  * ---------------------------------------------------------------------- */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include "common.h"
9 #include "lctypes.h"
10 #include "lin-city.h"
11 #include "stats.h"
12 #include <mps.h>
13 #include <lcintl.h>
14 #include <lcconfig.h>
15 
16 #include <market.h>
17 
18 
19 
20 int
get_jobs(int x,int y,int jobs)21 get_jobs (int x, int y, int jobs)
22 {
23   int q;
24   if (numof_markets > 0)
25     {
26       for (q = 0; q < numof_markets; q++)
27 	{
28 	  if ((abs (marketx[q] - x) < MARKET_RANGE
29 	       && abs (markety[q] - y) < MARKET_RANGE
30 	       && (MP_INFO(marketx[q],markety[q]).int_2 > (3 * jobs / 2))))
31 	    {
32 	      MP_INFO(marketx[q],markety[q]).int_2 -= jobs;
33 	      income_tax += jobs;
34 	      return (1);
35 	    }
36 	}
37     }
38   if (get_stuff (x, y, jobs, T_JOBS) != 0)
39     {
40       income_tax += jobs;
41       return (1);
42     }
43   return (0);
44 }
45 
46 int
put_jobs(int x,int y,int jobs)47 put_jobs (int x, int y, int jobs)
48 {
49   int q;
50   if (numof_markets > 0) {
51       for (q = 0; q < numof_markets; q++) {
52 	  if (MP_INFO(marketx[q],markety[q]).int_2
53 	      >= (MAX_JOBS_IN_MARKET - jobs))
54 	    continue;
55 	  if (abs (marketx[q] - x) < EMPLOYER_RANGE
56 	      && abs (markety[q] - y) < EMPLOYER_RANGE)
57 	    {
58 	      MP_INFO(marketx[q],markety[q]).int_2 += jobs;
59 	      return (1);
60 	    }
61 	}
62     }
63   if (put_stuff (x, y, jobs, T_JOBS) != 0) {
64       return (1);
65   }
66   return (0);
67 }
68 
69 int
get_food(int x,int y,int food)70 get_food (int x, int y, int food)
71 {
72   int q;
73   if (numof_markets > 0)
74     {
75       for (q = 0; q < numof_markets; q++)
76 	{
77 	  if ((abs (marketx[q] - x) < MARKET_RANGE)
78 	      && (abs (markety[q] - y) < MARKET_RANGE)
79 	      && (MP_INFO(marketx[q],markety[q]).int_1
80 		  > food))
81 	    {
82 	      MP_INFO(marketx[q],markety[q]).int_1 -= food;
83 	      return (1);
84 	    }
85 	}
86     }
87   if (get_stuff (x, y, food, T_FOOD) != 0)
88     return (1);
89   return (0);
90 }
91 
92 int
put_food(int x,int y,int food)93 put_food (int x, int y, int food)
94 {
95   int q;
96   if (numof_markets > 0)
97     {
98       for (q = 0; q < numof_markets; q++)
99 	{
100 	  if (MP_INFO(marketx[q],markety[q]).int_1
101 	      >= (MAX_FOOD_IN_MARKET - food))
102 	    continue;
103 	  if ((abs (marketx[q] - x) < ORG_FARM_RANGE)
104 	      && (abs (markety[q] - y) < ORG_FARM_RANGE))
105 	    {
106 	      MP_INFO(marketx[q],markety[q]).int_1 += food;
107 	      return (1);
108 	    }
109 	}
110     }
111   if (put_stuff (x, y, food, T_FOOD) != 0)
112     return (1);
113   return (0);
114 }
115 
116 
117 int
get_goods(int x,int y,int goods)118 get_goods (int x, int y, int goods)
119 {
120   int q;
121   if (numof_markets > 0)
122     {
123       for (q = 0; q < numof_markets; q++)
124 	{
125 	  if (abs (marketx[q] - x) < MARKET_RANGE
126 	      && abs (markety[q] - y) < MARKET_RANGE
127 	      && (MP_INFO(marketx[q],markety[q]).int_4
128 		  > goods))
129 	    {
130 	      MP_INFO(marketx[q],markety[q]).int_4 -= goods;
131 	      goods_tax += goods;
132 	      goods_used += goods;
133 	      /* make the waste here. */
134 	      MP_INFO(marketx[q],markety[q]).int_7 += goods / 3;
135 	      return (1);
136 	    }
137 	}
138     }
139   if (get_stuff (x, y, goods, T_GOODS) != 0)
140     {
141       put_stuff (x, y, goods / 3, T_WASTE);
142       goods_tax += goods;
143       goods_used += goods;
144       return (1);
145     }
146   return (0);
147 }
148 
149 int
put_goods(int x,int y,int goods)150 put_goods (int x, int y, int goods)
151 {
152   int q;
153   if (numof_markets > 0)
154     {
155       for (q = 0; q < numof_markets; q++)
156 	{
157 	  if (MP_INFO(marketx[q],markety[q]).int_4
158 	      >= (MAX_GOODS_IN_MARKET - goods))
159 	    continue;
160 	  if ((abs (marketx[q] - x) < MARKET_RANGE)
161 	      && (abs (markety[q] - y) < MARKET_RANGE))
162 	    {
163 	      MP_INFO(marketx[q],markety[q]).int_4 += goods;
164 	      return (1);
165 	    }
166 	}
167     }
168   if (put_stuff (x, y, goods, T_GOODS) != 0)
169     return (1);
170   return (0);
171 }
172 
173 int
put_waste(int x,int y,int waste)174 put_waste (int x, int y, int waste)
175 {
176   int q;
177   if (numof_markets > 0)
178     {
179       for (q = 0; q < numof_markets; q++)
180 	{
181 	  if (MP_INFO(marketx[q],markety[q]).int_7
182 	      >= (MAX_WASTE_IN_MARKET - waste))
183 	    continue;
184 	  if ((abs (marketx[q] - x) < MARKET_RANGE)
185 	      && (abs (markety[q] - y) < MARKET_RANGE))
186 	    {
187 	      MP_INFO(marketx[q],markety[q]).int_7 += waste;
188 	      return (1);
189 	    }
190 	}
191     }
192   if (put_stuff (x, y, waste, T_WASTE) != 0)
193     return (1);
194   return (0);
195 }
196 
197 int
get_waste(int x,int y,int waste)198 get_waste (int x, int y, int waste)
199 {
200   int q;
201   if (numof_markets > 0)
202     {
203       for (q = 0; q < numof_markets; q++)
204 	{
205 	  if ((abs (marketx[q] - x) < MARKET_RANGE)
206 	      && (abs (markety[q] - y) < MARKET_RANGE)
207 	      && (MP_INFO(marketx[q],markety[q]).int_7
208 		  > waste))
209 	    {
210 	      MP_INFO(marketx[q],markety[q]).int_7 -= waste;
211 	      return (1);
212 	    }
213 	}
214     }
215   if (get_stuff (x, y, waste, T_WASTE) != 0)
216     return (1);
217   return (0);
218 }
219 
220 
221 int
get_steel(int x,int y,int steel)222 get_steel (int x, int y, int steel)
223 {
224   int q;
225   if (numof_markets > 0)
226     {
227       for (q = 0; q < numof_markets; q++)
228 	{
229 	  if ((abs (marketx[q] - x) < MARKET_RANGE)
230 	      && (abs (markety[q] - y) < MARKET_RANGE)
231 	      && (MP_INFO(marketx[q],markety[q]).int_6
232 		  > steel))
233 	    {
234 	      MP_INFO(marketx[q],markety[q]).int_6 -= steel;
235 	      return (1);
236 	    }
237 	}
238     }
239   if (get_stuff (x, y, steel, T_STEEL) != 0)
240     return (1);
241   return (0);
242 }
243 
244 int
put_steel(int x,int y,int steel)245 put_steel (int x, int y, int steel)
246 {
247   int q;
248   if (numof_markets > 0)
249     {
250       for (q = 0; q < numof_markets; q++)
251 	{
252 	  if (MP_INFO(marketx[q],markety[q]).int_6
253 	      >= (MAX_STEEL_IN_MARKET - steel))
254 	    continue;
255 	  if ((abs (marketx[q] - x) < MARKET_RANGE)
256 	      && (abs (markety[q] - y) < MARKET_RANGE))
257 	    {
258 	      MP_INFO(marketx[q],markety[q]).int_6 += steel;
259 	      return (1);
260 	    }
261 	}
262     }
263   if (put_stuff (x, y, steel, T_STEEL) != 0)
264     return (1);
265   return (0);
266 }
267 
268 
269 int
get_ore(int x,int y,int ore)270 get_ore (int x, int y, int ore)
271 {
272   int q;
273   if (numof_markets > 0)
274     {
275       for (q = 0; q < numof_markets; q++)
276 	{
277 	  if ((abs (marketx[q] - x) < MARKET_RANGE)
278 	      && (abs (markety[q] - y) < MARKET_RANGE)
279 	      && (MP_INFO(marketx[q],markety[q]).int_5
280 		  > ore))
281 	    {
282 	      MP_INFO(marketx[q],markety[q]).int_5 -= ore;
283 	      return (1);
284 	    }
285 	}
286     }
287   if (get_stuff (x, y, ore, T_ORE) != 0)
288     return (1);
289   return (0);
290 }
291 
292 int
put_ore(int x,int y,int ore)293 put_ore (int x, int y, int ore)
294 {
295   int q;
296   if (numof_markets > 0)
297     {
298       for (q = 0; q < numof_markets; q++)
299 	{
300 	  if (MP_INFO(marketx[q],markety[q]).int_5
301 	      >= (MAX_ORE_IN_MARKET - ore))
302 	    continue;
303 	  if ((abs (marketx[q] - x) < MARKET_RANGE)
304 	      && (abs (markety[q] - y) < MARKET_RANGE))
305 	    {
306 	      MP_INFO(marketx[q],markety[q]).int_5 += ore;
307 	      return (1);
308 	    }
309 	}
310     }
311   if (put_stuff (x, y, ore, T_ORE) != 0)
312     return (1);
313   return (0);
314 }
315 
316 
317 int
get_coal(int x,int y,int coal)318 get_coal (int x, int y, int coal)
319 {
320   int q;
321   if (numof_markets > 0)
322     {
323       for (q = 0; q < numof_markets; q++)
324 	{
325 	  if ((abs (marketx[q] - x) < MARKET_RANGE)
326 	      && (abs (markety[q] - y) < MARKET_RANGE)
327 	      && (MP_INFO(marketx[q],markety[q]).int_3
328 		  > coal))
329 	    {
330 	      MP_INFO(marketx[q],markety[q]).int_3 -= coal;
331 	      return (1);
332 	    }
333 	}
334     }
335   if (get_stuff (x, y, coal, T_COAL) != 0)
336     return (1);
337   return (0);
338 }
339 
340 int
put_coal(int x,int y,int coal)341 put_coal (int x, int y, int coal)
342 {
343   int q;
344   if (numof_markets > 0)
345     {
346       for (q = 0; q < numof_markets; q++)
347 	{
348 	  if (MP_INFO(marketx[q],markety[q]).int_3
349 	      >= (MAX_COAL_IN_MARKET - coal))
350 	    continue;
351 	  if ((abs (marketx[q] - x) < MARKET_RANGE)
352 	      && (abs (markety[q] - y) < MARKET_RANGE))
353 	    {
354 	      MP_INFO(marketx[q],markety[q]).int_3 += coal;
355 	      return (1);
356 	    }
357 	}
358     }
359   if (put_stuff (x, y, coal, T_COAL) != 0)
360     return (1);
361   return (0);
362 }
363 
364 
365 int
add_a_market(int x,int y)366 add_a_market (int x, int y)	/* add to marketx markety to list */
367 {
368   if (numof_markets >= MAX_NUMOF_MARKETS)
369     return (0);
370   marketx[numof_markets] = x;
371   markety[numof_markets] = y;
372   numof_markets++;
373   /* oh dear. Got to bootstap markets with jobs, otherwise power won't work */
374   /* GCS: Is this still true?  */
375   MP_INFO(x,y).int_2 = 2000;
376   return (1);
377 }
378 
379 void
remove_a_market(int x,int y)380 remove_a_market (int x, int y)
381 {
382   int q;
383   for (q = 0; q < numof_markets; q++)
384     if (marketx[q] == x && markety[q] == y)
385       break;
386   for (; q < numof_markets; q++)
387     {
388       marketx[q] = marketx[q + 1];
389       markety[q] = markety[q + 1];
390     }
391   numof_markets--;
392 }
393 
394 void
do_market(int x,int y)395 do_market (int x, int y)
396 {
397   /*
398      //  int_1 contains the food it holds
399      //  int_2 contains the jobs
400      //  int_3 contains the coal
401      //  int_4 contains the goods
402      //  int_5 contains the ore
403      //  int_6 contains the steel
404      //  int_7 contains the waste
405    */
406 
407   int extra_jobs = 0;
408 
409   shuffle_markets ();
410 
411   if (x > 0 && (MP_INFO(x - 1,y).flags & FLAG_IS_TRANSPORT) != 0)
412     extra_jobs += deal_with_transport (x, y, x - 1, y);
413   if (x > 0 && (MP_INFO(x - 1,y + 1).flags & FLAG_IS_TRANSPORT) != 0)
414     extra_jobs += deal_with_transport (x, y, x - 1, y + 1);
415   if (y > 0 && (MP_INFO(x,y - 1).flags & FLAG_IS_TRANSPORT) != 0)
416     extra_jobs += deal_with_transport (x, y, x, y - 1);
417   if (y > 0 && (MP_INFO(x + 1,y - 1).flags & FLAG_IS_TRANSPORT) != 0)
418     extra_jobs += deal_with_transport (x, y, x + 1, y - 1);
419   if (x < WORLD_SIDE_LEN - 2
420       && (MP_INFO(x + 2,y).flags & FLAG_IS_TRANSPORT) != 0)
421     extra_jobs += deal_with_transport (x, y, x + 2, y);
422   if (x < WORLD_SIDE_LEN - 2
423       && (MP_INFO(x + 2,y + 1).flags & FLAG_IS_TRANSPORT) != 0)
424     extra_jobs += deal_with_transport (x, y, x + 2, y + 1);
425   if (y < WORLD_SIDE_LEN - 2
426       && (MP_INFO(x,y + 2).flags & FLAG_IS_TRANSPORT) != 0)
427     extra_jobs += deal_with_transport (x, y, x, y + 2);
428   if (y < WORLD_SIDE_LEN - 2
429       && (MP_INFO(x + 1,y + 2).flags & FLAG_IS_TRANSPORT) != 0)
430     extra_jobs += deal_with_transport (x, y, x + 1, y + 2);
431 
432   if (MP_INFO(x,y).int_1 > MAX_FOOD_IN_MARKET)
433     MP_INFO(x,y).int_1 = MAX_FOOD_IN_MARKET;
434   if (MP_INFO(x,y).int_2 > MAX_JOBS_IN_MARKET)
435     MP_INFO(x,y).int_2 = MAX_JOBS_IN_MARKET;
436   if (MP_INFO(x,y).int_4 > MAX_GOODS_IN_MARKET)
437     MP_INFO(x,y).int_4 = MAX_GOODS_IN_MARKET;
438 
439   /* now choose a graphic only dependent on food (for now anyway) */
440   if (total_time % 25 == 17)
441     {
442       if (MP_INFO(x,y).int_1 <= 0)
443 	{
444 	  if (MP_INFO(x,y).int_2 > 0)
445 	    MP_TYPE(x,y) = CST_MARKET_LOW;
446 	  else
447 	    MP_TYPE(x,y) = CST_MARKET_EMPTY;
448 	}
449       else if (MP_INFO(x,y).int_1 < (MARKET_FOOD_SEARCH_TRIGGER / 2))
450 	MP_TYPE(x,y) = CST_MARKET_LOW;
451       else if (MP_INFO(x,y).int_1
452 	       < (MAX_FOOD_IN_MARKET - MAX_FOOD_IN_MARKET / 4))
453 	MP_TYPE(x,y) = CST_MARKET_MED;
454       else
455 	MP_TYPE(x,y) = CST_MARKET_FULL;
456     }
457 
458   /* now employ some people */
459   get_jobs (x, y, 1 + (extra_jobs / 5));
460 
461   /* keep the pbars accurate */
462   inventory(x,y);
463 }
464 
465 void
shuffle_markets(void)466 shuffle_markets (void)
467 {
468   register int x;
469   int q, r, m;
470   m = (numof_markets / 4) + 1;
471   for (x = 0; x < m; x++)
472     {
473       r = rand () % numof_markets;
474       if (r == x)
475 	continue;
476       q = marketx[x];
477       marketx[x] = marketx[r];
478       marketx[r] = q;
479       q = markety[x];
480       markety[x] = markety[r];
481       markety[r] = q;
482     }
483 }
484 
485 
486 int
deal_with_transport(int x,int y,int tx,int ty)487 deal_with_transport (int x, int y, int tx, int ty)
488 {
489   int i, r, extra_jobs = 3, flags;
490   flags = MP_INFO(x,y).flags;
491   /* tracks */
492   if (MP_GROUP(tx,ty) == GROUP_TRACK)
493     {
494       /* food */
495       if ((flags & FLAG_MB_FOOD) != 0)
496 	{
497 	  r = (MAX_FOOD_IN_MARKET * 1000)
498 	    / (MAX_FOOD_ON_TRACK + MAX_FOOD_IN_MARKET);
499 	  i = MP_INFO(x,y).int_1 + MP_INFO(tx,ty).int_1;
500 	  MP_INFO(x,y).int_1 = (i * r) / 1000;
501 	  MP_INFO(tx,ty).int_1 = i - MP_INFO(x,y).int_1;
502 	}
503 
504       /* jobs */
505       if ((flags & FLAG_MB_JOBS) != 0)
506 	{
507 	  r = (MAX_JOBS_IN_MARKET * 1000)
508 	    / (MAX_JOBS_ON_TRACK + MAX_JOBS_IN_MARKET);
509 	  i = MP_INFO(x,y).int_2 + MP_INFO(tx,ty).int_2;
510 	  MP_INFO(x,y).int_2 = (i * r) / 1000;
511 	  MP_INFO(tx,ty).int_2 = i - MP_INFO(x,y).int_2;
512 	}
513 
514       /* coal */
515       if ((flags & FLAG_MB_COAL) != 0)
516 	{
517 	  r = (MAX_COAL_IN_MARKET * 1000)
518 	    / (MAX_COAL_ON_TRACK + MAX_COAL_IN_MARKET);
519 	  i = MP_INFO(x,y).int_3 + MP_INFO(tx,ty).int_3;
520 	  MP_INFO(x,y).int_3 = (i * r) / 1000;
521 	  MP_INFO(tx,ty).int_3 = i - MP_INFO(x,y).int_3;
522 	}
523 
524       /* goods */
525       if ((flags & FLAG_MB_GOODS) != 0)
526 	{
527 	  r = (MAX_GOODS_IN_MARKET * 1000)
528 	    / (MAX_GOODS_ON_TRACK + MAX_GOODS_IN_MARKET);
529 	  i = MP_INFO(x,y).int_4 + MP_INFO(tx,ty).int_4;
530 	  MP_INFO(x,y).int_4 = (i * r) / 1000;
531 	  MP_INFO(tx,ty).int_4 = i - MP_INFO(x,y).int_4;
532 	}
533 
534       /* ore */
535       if ((flags & FLAG_MB_ORE) != 0)
536 	{
537 	  r = (MAX_ORE_IN_MARKET * 1000)
538 	    / (MAX_ORE_ON_TRACK + MAX_ORE_IN_MARKET);
539 	  i = MP_INFO(x,y).int_5 + MP_INFO(tx,ty).int_5;
540 	  MP_INFO(x,y).int_5 = (i * r) / 1000;
541 	  MP_INFO(tx,ty).int_5 = i - MP_INFO(x,y).int_5;
542 	}
543 
544 
545       /* steel */
546       if ((flags & FLAG_MB_STEEL) != 0)
547 	{
548 	  r = (MAX_STEEL_IN_MARKET * 1000)
549 	    / (MAX_STEEL_ON_TRACK + MAX_STEEL_IN_MARKET);
550 	  i = MP_INFO(x,y).int_6 + MP_INFO(tx,ty).int_6;
551 	  MP_INFO(x,y).int_6 = (i * r) / 1000;
552 	  MP_INFO(tx,ty).int_6 = i - MP_INFO(x,y).int_6;
553 	}
554 
555       /* waste */
556       r = (MAX_WASTE_IN_MARKET * 1000)
557 	/ (MAX_WASTE_ON_TRACK + MAX_WASTE_IN_MARKET);
558       i = MP_INFO(x,y).int_7 + MP_INFO(tx,ty).int_7;
559       MP_INFO(x,y).int_7 = (i * r) / 1000;
560       MP_INFO(tx,ty).int_7 = i - MP_INFO(x,y).int_7;
561 
562 
563       /* if it's full of waste, burn some to make pollution. */
564       if (MP_INFO(x,y).int_7 >= (99 * MAX_WASTE_IN_MARKET / 100))
565 	{
566 	  MP_POL(x,y) += 3000;
567 	  MP_INFO(x,y).int_7 -= (7 * MAX_WASTE_IN_MARKET) / 10;
568 #if defined (commentout)
569 	  /* this should fire up the pollution mini screen within a second. */
570 	  mini_screen_flags = MINI_SCREEN_POL_FLAG;
571 #endif
572 	}
573     }
574 
575 
576   /* do rail traffic */
577   else if (MP_GROUP(tx,ty) == GROUP_RAIL)
578     {
579       /* food */
580       if ((flags & FLAG_MB_FOOD) != 0)
581 	{
582 	  r = (MAX_FOOD_IN_MARKET * 1000)
583 	    / (MAX_FOOD_ON_RAIL + MAX_FOOD_IN_MARKET);
584 	  i = MP_INFO(x,y).int_1 + MP_INFO(tx,ty).int_1;
585 	  MP_INFO(x,y).int_1 = (i * r) / 1000;
586 	  MP_INFO(tx,ty).int_1 = i - MP_INFO(x,y).int_1;
587 	}
588 
589       /* jobs */
590       if ((flags & FLAG_MB_JOBS) != 0)
591 	{
592 	  r = (MAX_JOBS_IN_MARKET * 1000)
593 	    / (MAX_JOBS_ON_RAIL + MAX_JOBS_IN_MARKET);
594 	  i = MP_INFO(x,y).int_2 + MP_INFO(tx,ty).int_2;
595 	  MP_INFO(x,y).int_2 = (i * r) / 1000;
596 	  MP_INFO(tx,ty).int_2 = i - MP_INFO(x,y).int_2;
597 	}
598 
599       /* coal */
600       if ((flags & FLAG_MB_COAL) != 0)
601 	{
602 	  r = (MAX_COAL_IN_MARKET * 1000)
603 	    / (MAX_COAL_ON_RAIL + MAX_COAL_IN_MARKET);
604 	  i = MP_INFO(x,y).int_3 + MP_INFO(tx,ty).int_3;
605 	  MP_INFO(x,y).int_3 = (i * r) / 1000;
606 	  MP_INFO(tx,ty).int_3 = i - MP_INFO(x,y).int_3;
607 	}
608 
609       /* goods */
610       if ((flags & FLAG_MB_GOODS) != 0)
611 	{
612 	  r = (MAX_GOODS_IN_MARKET * 1000)
613 	    / (MAX_GOODS_ON_RAIL + MAX_GOODS_IN_MARKET);
614 	  i = MP_INFO(x,y).int_4 + MP_INFO(tx,ty).int_4;
615 	  MP_INFO(x,y).int_4 = (i * r) / 1000;
616 	  MP_INFO(tx,ty).int_4 = i - MP_INFO(x,y).int_4;
617 	}
618 
619       /* ore */
620       if ((flags & FLAG_MB_ORE) != 0)
621 	{
622 	  r = (MAX_ORE_IN_MARKET * 1000)
623 	    / (MAX_ORE_ON_RAIL + MAX_ORE_IN_MARKET);
624 	  i = MP_INFO(x,y).int_5 + MP_INFO(tx,ty).int_5;
625 	  MP_INFO(x,y).int_5 = (i * r) / 1000;
626 	  MP_INFO(tx,ty).int_5 = i - MP_INFO(x,y).int_5;
627 	}
628 
629       /* steel */
630       if ((flags & FLAG_MB_STEEL) != 0)
631 	{
632 	  r = (MAX_STEEL_IN_MARKET * 1000)
633 	    / (MAX_STEEL_ON_RAIL + MAX_STEEL_IN_MARKET);
634 	  i = MP_INFO(x,y).int_6 + MP_INFO(tx,ty).int_6;
635 	  MP_INFO(x,y).int_6 = (i * r) / 1000;
636 	  MP_INFO(tx,ty).int_6 = i - MP_INFO(x,y).int_6;
637 	}
638 
639       /* waste */
640       r = (MAX_WASTE_IN_MARKET * 1000)
641 	/ (MAX_WASTE_ON_RAIL + MAX_WASTE_IN_MARKET);
642       i = MP_INFO(x,y).int_7 + MP_INFO(tx,ty).int_7;
643       MP_INFO(x,y).int_7 = (i * r) / 1000;
644       MP_INFO(tx,ty).int_7 = i - MP_INFO(x,y).int_7;
645 
646     }
647 
648   /* do road traffic */
649   else if (MP_GROUP(tx,ty) == GROUP_ROAD)
650     {
651       /* food */
652       if ((flags & FLAG_MB_FOOD) != 0)
653 	{
654 	  r = (MAX_FOOD_IN_MARKET * 1000)
655 	    / (MAX_FOOD_ON_ROAD + MAX_FOOD_IN_MARKET);
656 	  i = MP_INFO(x,y).int_1 + MP_INFO(tx,ty).int_1;
657 	  MP_INFO(x,y).int_1 = (i * r) / 1000;
658 	  MP_INFO(tx,ty).int_1 = i - MP_INFO(x,y).int_1;
659 	}
660 
661       /* jobs */
662       if ((flags & FLAG_MB_JOBS) != 0)
663 	{
664 	  r = (MAX_JOBS_IN_MARKET * 1000)
665 	    / (MAX_JOBS_ON_ROAD + MAX_JOBS_IN_MARKET);
666 	  i = MP_INFO(x,y).int_2 + MP_INFO(tx,ty).int_2;
667 	  MP_INFO(x,y).int_2 = (i * r) / 1000;
668 	  MP_INFO(tx,ty).int_2 = i - MP_INFO(x,y).int_2;
669 	}
670 
671       /* coal */
672       if ((flags & FLAG_MB_COAL) != 0)
673 	{
674 	  r = (MAX_COAL_IN_MARKET * 1000)
675 	    / (MAX_COAL_ON_ROAD + MAX_COAL_IN_MARKET);
676 	  i = MP_INFO(x,y).int_3 + MP_INFO(tx,ty).int_3;
677 	  MP_INFO(x,y).int_3 = (i * r) / 1000;
678 	  MP_INFO(tx,ty).int_3 = i - MP_INFO(x,y).int_3;
679 	}
680 
681       /* goods */
682       if ((flags & FLAG_MB_GOODS) != 0)
683 	{
684 	  r = (MAX_GOODS_IN_MARKET * 1000)
685 	    / (MAX_GOODS_ON_ROAD + MAX_GOODS_IN_MARKET);
686 	  i = MP_INFO(x,y).int_4 + MP_INFO(tx,ty).int_4;
687 	  MP_INFO(x,y).int_4 = (i * r) / 1000;
688 	  MP_INFO(tx,ty).int_4 = i - MP_INFO(x,y).int_4;
689 	}
690 
691       /* ore */
692       if ((flags & FLAG_MB_ORE) != 0)
693 	{
694 	  r = (MAX_ORE_IN_MARKET * 1000)
695 	    / (MAX_ORE_ON_ROAD + MAX_ORE_IN_MARKET);
696 	  i = MP_INFO(x,y).int_5 + MP_INFO(tx,ty).int_5;
697 	  MP_INFO(x,y).int_5 = (i * r) / 1000;
698 	  MP_INFO(tx,ty).int_5 = i - MP_INFO(x,y).int_5;
699 	}
700 
701       /* steel */
702       if ((flags & FLAG_MB_STEEL) != 0)
703 	{
704 	  r = (MAX_STEEL_IN_MARKET * 1000)
705 	    / (MAX_STEEL_ON_ROAD + MAX_STEEL_IN_MARKET);
706 	  i = MP_INFO(x,y).int_6 + MP_INFO(tx,ty).int_6;
707 	  MP_INFO(x,y).int_6 = (i * r) / 1000;
708 	  MP_INFO(tx,ty).int_6 = i - MP_INFO(x,y).int_6;
709 	}
710 
711       /* waste */
712       r = (MAX_WASTE_IN_MARKET * 1000)
713 	/ (MAX_WASTE_ON_ROAD + MAX_WASTE_IN_MARKET);
714       i = MP_INFO(x,y).int_7 + MP_INFO(tx,ty).int_7;
715       MP_INFO(x,y).int_7 = (i * r) / 1000;
716       MP_INFO(tx,ty).int_7 = i - MP_INFO(x,y).int_7;
717     }
718   else
719     extra_jobs = 0;
720 
721   return (extra_jobs);
722 }
723 
724 int
get_stuff(int x,int y,int stuff,int stuff_type)725 get_stuff (int x, int y, int stuff, int stuff_type)
726 {
727   int res = 0;
728   Map_Point_Info *minfo = &MP_INFO(x,y);
729 
730   switch (MP_SIZE(x,y))
731     {
732     case 2:
733       res = get_stuff2 (minfo, stuff, stuff_type);
734       break;
735     case 3:
736       res = get_stuff3 (minfo, stuff, stuff_type);
737       break;
738     case 4:
739       res = get_stuff4 (minfo, stuff, stuff_type);
740       break;
741     default:
742       do_error ("Bad area size in get_stuff()");
743     }
744   return (res);
745 }
746 
747 static const int
748   t2[8] =
749 {
750   -1,
751   WORLD_SIDE_LEN - 1,
752   2 * WORLD_SIDE_LEN,
753   2 * WORLD_SIDE_LEN + 1,
754   WORLD_SIDE_LEN + 2,
755   2,
756   1 - WORLD_SIDE_LEN,
757   -WORLD_SIDE_LEN
758 };
759 
760 /* worth inlining -- (ThMO) */
761 int
get_stuff2(Map_Point_Info * map,int stuff,int stuff_type)762 get_stuff2 (Map_Point_Info *map, int stuff, int stuff_type)
763 {
764   static int tstart2 = 0;
765   int i, st, tst, *ip, *stack[8], **ssp;	/* stack is a pipe -- (ThMO) */
766 
767   /* we'll stack our found pointers so to avoid re-looping and
768    * testing again (ThMO) */
769 
770   tst = tstart2;
771 
772   /* can we find enough on the transport? */
773 
774   for (ssp = stack, st = 0, i = 0; i < 8; i++)
775     {
776       if (map[t2[tst]].flags & FLAG_IS_TRANSPORT)
777 	{
778 	  ip = &map[t2[tst]].int_1;
779 	  ip += stuff_type;
780 	  st += *ip;
781 	  *ssp++ = ip;		/* push it -- (ThMO) */
782 	  if (st >= stuff)
783 	    {
784 	      ssp = stack;
785 	      do
786 		{
787 		  ip = *ssp++;	/* pop it -- (ThMO) */
788 		  *ip = (stuff -= *ip) < 0 ? -stuff : 0;
789 		}
790 	      while (stuff > 0);
791 	      tstart2 = ++tst & 7;
792 	      return (1);
793 	    }
794 	}
795       if (++tst >= 8)
796 	tst = 0;
797     }
798   return (0);
799 }
800 
801 static const int
802   t3[12] =
803 {
804   -1,
805   WORLD_SIDE_LEN - 1,
806   2 * WORLD_SIDE_LEN - 1,
807   3 * WORLD_SIDE_LEN,
808   3 * WORLD_SIDE_LEN + 1,
809   3 * WORLD_SIDE_LEN + 2,
810   2 * WORLD_SIDE_LEN + 3,
811   WORLD_SIDE_LEN + 3,
812   3,
813   2 - WORLD_SIDE_LEN,
814   1 - WORLD_SIDE_LEN,
815   -WORLD_SIDE_LEN
816 };
817 
818 /* worth inlining -- (ThMO) */
819 int
get_stuff3(Map_Point_Info * map,int stuff,int stuff_type)820 get_stuff3 (Map_Point_Info *map, int stuff, int stuff_type)
821 {
822   static int tstart3 = 0;
823 
824   int i, st, tst, *ip, *stack[12], **ssp;	/* stack is a pipe -- (ThMO) */
825 
826   /* we'll stack our found pointers so to avoid re-looping and
827    * testing again
828    * (ThMO)
829    */
830 
831   tst = tstart3;
832 
833   /* can we find enough on the transport? */
834 
835   for (ssp = stack, st = 0, i = 0; i < 12; i++)
836     {
837       if (map[t3[tst]].flags & FLAG_IS_TRANSPORT)
838 	{
839 	  ip = &map[t3[tst]].int_1;
840 	  ip += stuff_type;
841 	  st += *ip;
842 	  *ssp++ = ip;		/* push it -- (ThMO) */
843 	  if (st >= stuff)
844 	    {
845 	      ssp = stack;
846 	      do
847 		{
848 		  ip = *ssp++;	/* pop it -- (ThMO) */
849 		  *ip = (stuff -= *ip) < 0 ? -stuff : 0;
850 		}
851 	      while (stuff > 0);
852 	      ++tst;
853 	      tstart3 = tst >= 12 ? 0 : tst;
854 	      return (1);
855 	    }
856 	}
857       if (++tst >= 12)
858 	tst = 0;
859     }
860   return (0);
861 }
862 
863 static const int
864   t4[16] =
865 {
866   -1,
867   WORLD_SIDE_LEN - 1,
868   2 * WORLD_SIDE_LEN - 1,
869   3 * WORLD_SIDE_LEN - 1,
870   4 * WORLD_SIDE_LEN,
871   4 * WORLD_SIDE_LEN + 1,
872   4 * WORLD_SIDE_LEN + 2,
873   4 * WORLD_SIDE_LEN + 3,
874   3 * WORLD_SIDE_LEN + 4,
875   2 * WORLD_SIDE_LEN + 4,
876   WORLD_SIDE_LEN + 4,
877   4,
878   3 - WORLD_SIDE_LEN,
879   2 - WORLD_SIDE_LEN,
880   1 - WORLD_SIDE_LEN,
881   -WORLD_SIDE_LEN
882 };
883 
884 /* worth inlining -- (ThMO) */
885 int
get_stuff4(Map_Point_Info * map,int stuff,int stuff_type)886 get_stuff4 (Map_Point_Info *map, int stuff, int stuff_type)
887 {
888   static int
889     tstart4 = 0;
890 
891   int i, st, tst, *ip, *stack[16], **ssp;	/* stack is a pipe -- (ThMO) */
892 
893   /* we'll stack our found pointers so to avoid re-looping and
894    * testing again
895    * (ThMO)
896    */
897 
898   tst = tstart4;
899 
900   /* can we find enough on the transport? */
901 
902   for (ssp = stack, st = 0, i = 0; i < 16; i++)
903     {
904       if (map[t4[tst]].flags & FLAG_IS_TRANSPORT)
905 	{
906 	  ip = &map[t4[tst]].int_1;
907 	  ip += stuff_type;
908 	  st += *ip;
909 	  *ssp++ = ip;		/* push it -- (ThMO) */
910 	  if (st >= stuff)
911 	    {
912 	      ssp = stack;
913 	      do
914 		{
915 		  ip = *ssp++;	/* pop it -- (ThMO) */
916 		  *ip = (stuff -= *ip) < 0 ? -stuff : 0;
917 		}
918 	      while (stuff > 0);
919 	      tstart4 = ++tst & 15;
920 	      return (1);
921 	    }
922 	}
923       if (++tst >= 16)
924 	tst = 0;
925     }
926   return (0);
927 }
928 
929 int
put_stuff(int x,int y,int stuff,int stuff_type)930 put_stuff (int x, int y, int stuff, int stuff_type)
931 {
932     int res = 0;
933     short *type = &MP_TYPE(x,y);
934     Map_Point_Info *minfo = &MP_INFO(x,y);
935     switch (MP_SIZE(x,y))
936     {
937     case 2:
938 	res = put_stuff2 (minfo, type, stuff, stuff_type);
939 	break;
940     case 3:
941 	res = put_stuff3 (minfo, type, stuff, stuff_type);
942 	break;
943     case 4:
944 	res = put_stuff4 (minfo, type, stuff, stuff_type);
945 	break;
946     default:
947 	do_error ("Bad area size in put_stuff()");
948     }
949     return res;
950 }
951 
952 
953 int tmax[3][7] =
954 {
955   {MAX_FOOD_ON_TRACK, MAX_JOBS_ON_TRACK
956    ,MAX_COAL_ON_TRACK, MAX_GOODS_ON_TRACK, MAX_ORE_ON_TRACK
957    ,MAX_STEEL_ON_TRACK, MAX_WASTE_ON_TRACK},
958   {MAX_FOOD_ON_ROAD, MAX_JOBS_ON_ROAD
959    ,MAX_COAL_ON_ROAD, MAX_GOODS_ON_ROAD, MAX_ORE_ON_ROAD
960    ,MAX_STEEL_ON_ROAD, MAX_WASTE_ON_ROAD},
961   {MAX_FOOD_ON_RAIL, MAX_JOBS_ON_RAIL
962    ,MAX_COAL_ON_RAIL, MAX_GOODS_ON_RAIL, MAX_ORE_ON_RAIL
963    ,MAX_STEEL_ON_RAIL, MAX_WASTE_ON_RAIL}
964 };
965 
966 struct stack
967   {
968     int *ip, max_val;
969   };
970 
971 /* worth inlining -- (ThMO) */
972 int
put_stuff2(Map_Point_Info * minfo,short * type,int stuff,int stuff_type)973 put_stuff2 (Map_Point_Info *minfo, short *type, int stuff, int stuff_type)
974 {
975   static int tstart2 = 0;
976   int i, st, tst, *ip, tp = 0;
977   struct stack stack[8], *ssp;	/* stack is really a pipe -- (ThMO) */
978 
979   /* we'll stack our found pointers so to avoid re-looping and
980    * testing again (ThMO) */
981 
982   tst = tstart2;
983 
984   /* can we put enough on the transport? */
985 
986   for (ssp = stack, st = 0, i = 0; i < 8; i++) {
987     int map_index = t2[tst];
988     if (minfo[map_index].flags & FLAG_IS_TRANSPORT) {
989       switch (get_group_of_type(type[map_index]))
990 	{
991 	case GROUP_TRACK:
992 	  tp = tmax[0][stuff_type];
993 	  break;
994 	case GROUP_ROAD:
995 	  tp = tmax[1][stuff_type];
996 	  break;
997 	case GROUP_RAIL:
998 	  tp = tmax[2][stuff_type];
999 	  break;
1000 	default:
1001 	  do_error ("Bad transport type in put_stuff2");
1002 	}
1003       ip = &minfo[map_index].int_1;
1004       ssp->ip = ip += stuff_type;	/* push it -- (ThMO) */
1005       ssp++->max_val = tp;
1006       st += tp - *ip;
1007       if (st >= stuff) {
1008 	ssp = stack;
1009 	do {
1010 	  tp = ssp->max_val - *ssp->ip;		/* pop it -- (ThMO) */
1011 	  if ((stuff -= tp) < 0)
1012 	    *ssp->ip += tp + stuff;	/* == orig. stuff -- (ThMO) */
1013 	  else
1014 	    *ssp->ip = ssp->max_val;
1015 	  ++ssp;
1016 	} while (stuff > 0);
1017 	tstart2 = ++tst & 7;
1018 	return (1);
1019       }
1020     }
1021     if (++tst >= 8)
1022       tst = 0;
1023   }
1024   return (0);
1025 }
1026 
1027 /* worth inlining -- (ThMO) */
1028 int
put_stuff3(Map_Point_Info * minfo,short * type,int stuff,int stuff_type)1029 put_stuff3 (Map_Point_Info *minfo, short *type, int stuff, int stuff_type)
1030 {
1031   static int tstart3 = 0;
1032   int i, st, tst, *ip, tp = 0;
1033   struct stack stack[12], *ssp;	/* stack is really a pipe -- (ThMO)
1034 				   we'll stack our found pointers so
1035 				   to avoid re-looping and
1036 				   testing again (ThMO) */
1037 
1038   tst = tstart3;
1039 
1040   /* can we put enough on the transport? */
1041 
1042   for (ssp = stack, st = 0, i = 0; i < 12; i++) {
1043     int map_index = t3[tst];
1044     if (minfo[map_index].flags & FLAG_IS_TRANSPORT) {
1045       switch (get_group_of_type(type[map_index]))
1046 	{
1047 	case GROUP_TRACK:
1048 	  tp = tmax[0][stuff_type];
1049 	  break;
1050 	case GROUP_ROAD:
1051 	  tp = tmax[1][stuff_type];
1052 	  break;
1053 	case GROUP_RAIL:
1054 	  tp = tmax[2][stuff_type];
1055 	  break;
1056 	default:
1057 	  do_error ("Bad transport type in put_stuff3");
1058 	}
1059       ip = &minfo[map_index].int_1;
1060       ssp->ip = ip += stuff_type;	/* push it -- (ThMO) */
1061       ssp++->max_val = tp;
1062       st += tp - *ip;
1063       if (st >= stuff) {
1064 	ssp = stack;
1065 	do {
1066 	  tp = ssp->max_val - *ssp->ip;		/* pop it -- (ThMO) */
1067 	  if ((stuff -= tp) < 0)
1068 	    *ssp->ip += tp + stuff;	/* == orig. stuff -- (ThMO) */
1069 	  else
1070 	    *ssp->ip = ssp->max_val;
1071 	  ++ssp;
1072 	} while (stuff > 0);
1073 	++tst;
1074 	tstart3 = tst >= 12 ? 0 : tst;
1075 	return (1);
1076       }
1077     }
1078     if (++tst >= 12)
1079       tst = 0;
1080   }
1081   return (0);
1082 }
1083 
1084 /* worth inlining -- (ThMO) */
1085 int
put_stuff4(Map_Point_Info * minfo,short * type,int stuff,int stuff_type)1086 put_stuff4 (Map_Point_Info *minfo, short *type, int stuff, int stuff_type)
1087 {
1088   static int tstart4 = 0;
1089   int i, st, tst, *ip, tp = 0;
1090   struct stack stack[16], *ssp;	/* stack is really a pipe -- (ThMO)
1091 				 */
1092   /* we'll stack our found pointers so to avoid re-looping and
1093    * testing again (ThMO) */
1094 
1095   tst = tstart4;
1096 
1097   /* can we put enough on the transport? */
1098 
1099   for (ssp = stack, st = 0, i = 0; i < 16; i++) {
1100     int map_index = t4[tst];
1101     if (minfo[map_index].flags & FLAG_IS_TRANSPORT) {
1102       switch (get_group_of_type(type[map_index]))
1103 	{
1104 	case GROUP_TRACK:
1105 	  tp = tmax[0][stuff_type];
1106 	  break;
1107 	case GROUP_ROAD:
1108 	  tp = tmax[1][stuff_type];
1109 	  break;
1110 	case GROUP_RAIL:
1111 	  tp = tmax[2][stuff_type];
1112 	  break;
1113 	default:
1114 	  do_error ("Bad transport type in put_stuff4");
1115 	}
1116       ip = &minfo[map_index].int_1;
1117       ssp->ip = ip += stuff_type;	/* push it -- (ThMO) */
1118       ssp++->max_val = tp;
1119       st += tp - *ip;
1120       if (st >= stuff) {
1121 	ssp = stack;
1122 	do {
1123 	  tp = ssp->max_val - *ssp->ip;		/* pop it -- (ThMO) */
1124 	  if ((stuff -= tp) < 0)
1125 	    *ssp->ip += tp + stuff;	/* == orig. stuff -- (ThMO) */
1126 	  else
1127 	    *ssp->ip = ssp->max_val;
1128 	  ++ssp;
1129 	} while (stuff > 0);
1130 	tstart4 = ++tst & 15;
1131 	return (1);
1132       }
1133     }
1134     if (++tst >= 16)
1135       tst = 0;
1136   }
1137   return (0);
1138 }
1139 
1140 void
mps_market(int x,int y)1141 mps_market (int x, int y)
1142 {
1143   int i = 0;
1144 
1145   mps_store_title(i++,_("Market"));
1146 
1147   i++;
1148 
1149   mps_store_sfp(i++,_("Food"),
1150 		MP_INFO(x,y).int_1 * 100.0 / MAX_FOOD_IN_MARKET);
1151   mps_store_sfp(i++,_("Jobs"),
1152 		MP_INFO(x,y).int_2 * 100.0 / MAX_JOBS_IN_MARKET);
1153   mps_store_sfp(i++,_("Coal"),
1154 		MP_INFO(x,y).int_3 * 100.0 / MAX_COAL_IN_MARKET);
1155   mps_store_sfp(i++,_("Goods"),
1156 		MP_INFO(x,y).int_4 * 100.0 / MAX_GOODS_IN_MARKET);
1157   mps_store_sfp(i++,_("Ore"),
1158 		MP_INFO(x,y).int_5 * 100.0 / MAX_ORE_IN_MARKET);
1159   mps_store_sfp(i++,_("Steel"),
1160 		MP_INFO(x,y).int_6 * 100.0 / MAX_STEEL_IN_MARKET);
1161   mps_store_sfp(i++,_("Waste"),
1162 		MP_INFO(x,y).int_7 * 100.0 / MAX_WASTE_IN_MARKET);
1163 
1164 }
1165 
1166 
1167