1 /* ---------------------------------------------------------------------- *
2  * transport.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 <assert.h>
9 #include "common.h"
10 #include "lctypes.h"
11 #include "lin-city.h"
12 #include "transport.h"
13 #include "power.h"
14 #include "stats.h" /* for transport_cost */
15 
16 /* ---------------------------------------------------------------------
17    For track, road and rail:
18 
19    int_1 contains the amount of food
20    int_2 contains the amount of jobs
21    int_3 contains the amount of coal
22    int_4 contains the amount of goods
23    int_5 contains the amount of ore
24    int_6 contains the amount of steel
25    int_7 contains the amount of waste
26   --------------------------------------------------------------------- */
27 
28 void
general_transport(Map_Point_Info * minfo,int * pol,int max_waste,int * waste_count)29 general_transport (Map_Point_Info *minfo, int *pol,
30 		   int max_waste, int *waste_count)
31 {
32     int tot, av, *base, xm1, xp1, ym1, yp1;
33 
34     /* 30. Oct 1996:
35      * we'll use a loop with pointers here instead of doin' each
36      * operation by hand.  this reduces code complexity and should
37      * lead to a higher cache hit ratio - theoretically
38      * (ThMO)
39      *
40      * 12. Dec 1996:
41      * as this is a heavy used routine, another speedup improvement is
42      * needed.  we'll now use 1 pointer, which will be incremented and
43      * 1 .. 4 constant indices, which replaces the old pointer-pure
44      * version.
45      * advantages:  elimination of unnecessary pointer increments.
46      * Note:  this *only* works, if the related addresses use one and the
47      *        same address space - which is naturally for 2-dimensional
48      *        arrays.
49      * (ThMO)
50      */
51 
52     base = &minfo->int_1;
53     switch (minfo->flags & 0x0F)
54     {
55     case 0:
56 	return;
57 
58     case 1:			/* inlined t_av_l() -- (ThMO) */
59 	xm1 = &minfo[-WORLD_SIDE_LEN].int_1 - base;
60 	do {
61 	    tot = *base + base[xm1];
62 	    av = tot / 2;
63 	    base[xm1] = av;
64 	    *base++ = av + tot % 2;
65 	} while (base <= &minfo->int_7);
66 	break;
67 
68     case 2:			/* inlined t_av_u() -- (ThMO) */
69 	ym1 = &minfo[-1].int_1 - base;
70 	do {
71 	    tot = *base + base[ym1];
72 	    av = tot / 2;
73 	    base[ym1] = av;
74 	    *base++ = av + tot % 2;
75 	} while (base <= &minfo->int_7);
76 	break;
77 
78     case 3:			/* inlined t_av_lu() -- (ThMO) */
79 	xm1 = &minfo[-WORLD_SIDE_LEN].int_1 - base;
80 	ym1 = &minfo[-1].int_1 - base;
81 	do {
82 	    tot = *base + base[xm1] + base[ym1];
83 	    av = tot / 3;
84 	    base[xm1] = base[ym1] = av;
85 	    *base++ = av + tot % 3;
86 	} while (base <= &minfo->int_7);
87 	break;
88 
89     case 4:			/* inlined t_av_r() -- (ThMO) */
90 	xp1 = &minfo[WORLD_SIDE_LEN].int_1 - base;
91 	do {
92 	    tot = *base + base[xp1];
93 	    av = tot / 2;
94 	    base[xp1] = av;
95 	    *base++ = av + tot % 2;
96 	} while (base <= &minfo->int_7);
97 	break;
98 
99     case 5:			/* inlined t_av_lr() -- (ThMO) */
100 	xm1 = &minfo[-WORLD_SIDE_LEN].int_1 - base;
101 	xp1 = &minfo[WORLD_SIDE_LEN].int_1 - base;
102 	do {
103 	    tot = *base + base[xm1] + base[xp1];
104 	    av = tot / 3;
105 	    base[xm1] = base[xp1] = av;
106 	    *base++ = av + tot % 3;
107 	} while (base <= &minfo->int_7);
108 	break;
109 
110     case 6:			/* inline t_av_ur() -- (ThMO) */
111 	ym1 = &minfo[-1].int_1 - base;
112 	xp1 = &minfo[WORLD_SIDE_LEN].int_1 - base;
113 	do {
114 	    tot = *base + base[ym1] + base[xp1];
115 	    av = tot / 3;
116 	    base[ym1] = base[xp1] = av;
117 	    *base++ = av + tot % 3;
118 	} while (base <= &minfo->int_7);
119 	break;
120 
121     case 7:			/* inlined t_av_lur() -- (ThMO) */
122 	xm1 = &minfo[-WORLD_SIDE_LEN].int_1 - base;
123 	ym1 = &minfo[-1].int_1 - base;
124 	xp1 = &minfo[WORLD_SIDE_LEN].int_1 - base;
125 	do {
126 	    tot = *base + base[xm1] + base[ym1] + base[xp1];
127 	    av = tot / 4;
128 	    base[xm1] = base[ym1] = base[xp1] = av;
129 	    *base++ = av + tot % 4;
130 	} while (base <= &minfo->int_7);
131 	break;
132 
133     case 8:			/* inlined t_av_d() -- (ThMO) */
134 	yp1 = &minfo[1].int_1 - base;
135 	do {
136 	    tot = *base + base[yp1];
137 	    av = tot / 2;
138 	    base[yp1] = av;
139 	    *base++ = av + tot % 2;
140 	} while (base <= &minfo->int_7);
141 	break;
142 
143     case 9:			/* inlined t_av_ld() -- (ThMO) */
144 	xm1 = &minfo[-WORLD_SIDE_LEN].int_1 - base;
145 	yp1 = &minfo[1].int_1 - base;
146 	do {
147 	    tot = *base + base[xm1] + base[yp1];
148 	    av = tot / 3;
149 	    base[xm1] = base[yp1] = av;
150 	    *base++ = av + tot % 3;
151 	} while (base <= &minfo->int_7);
152 	break;
153 
154     case 10:			/* inlined t_av_ud() -- (ThMO) */
155 	ym1 = &minfo[-1].int_1 - base;
156 	yp1 = &minfo[1].int_1 - base;
157 	do {
158 	    tot = *base + base[ym1] + base[yp1];
159 	    av = tot / 3;
160 	    base[ym1] = base[yp1] = av;
161 	    *base++ = av + tot % 3;
162 	} while (base <= &minfo->int_7);
163 	break;
164 
165     case 11:			/* inlined t_av_lud() -- (ThMO) */
166 	xm1 = &minfo[-WORLD_SIDE_LEN].int_1 - base;
167 	ym1 = &minfo[-1].int_1 - base;
168 	yp1 = &minfo[1].int_1 - base;
169 	do {
170 	    tot = *base + base[xm1] + base[ym1] + base[yp1];
171 	    av = tot / 4;
172 	    base[xm1] = base[ym1] = base[yp1] = av;
173 	    *base++ = av + tot % 4;
174 	} while (base <= &minfo->int_7);
175 	break;
176 
177     case 12:			/* inlined t_av_rd() -- (ThMO) */
178 	xp1 = &minfo[WORLD_SIDE_LEN].int_1 - base;
179 	yp1 = &minfo[1].int_1 - base;
180 	do {
181 	    tot = *base + base[xp1] + base[yp1];
182 	    av = tot / 3;
183 	    base[xp1] = base[yp1] = av;
184 	    *base++ = av + tot % 3;
185 	} while (base <= &minfo->int_7);
186 	break;
187 
188     case 13:			/* inlined t_av_lrd() -- (ThMO) */
189 	xm1 = &minfo[-WORLD_SIDE_LEN].int_1 - base;
190 	xp1 = &minfo[WORLD_SIDE_LEN].int_1 - base;
191 	yp1 = &minfo[1].int_1 - base;
192 	do {
193 	    tot = *base + base[xm1] + base[xp1] + base[yp1];
194 	    av = tot / 4;
195 	    base[xm1] = base[xp1] = base[yp1] = av;
196 	    *base++ = av + tot % 4;
197 	} while (base <= &minfo->int_7);
198 	break;
199 
200     case 14:			/* inlined t_av_urd() -- (ThMO) */
201 	ym1 = &minfo[-1].int_1 - base;
202 	xp1 = &minfo[WORLD_SIDE_LEN].int_1 - base;
203 	yp1 = &minfo[1].int_1 - base;
204 	do {
205 	    tot = *base + base[ym1] + base[xp1] + base[yp1];
206 	    av = tot / 4;
207 	    base[ym1] = base[xp1] = base[yp1] = av;
208 	    *base++ = av + tot % 4;
209 	} while (base <= &minfo->int_7);
210 	break;
211 
212     case 15:			/* inlined t_av_lurd() -- (ThMO) */
213 	xm1 = &minfo[-WORLD_SIDE_LEN].int_1 - base;
214 	ym1 = &minfo[-1].int_1 - base;
215 	xp1 = &minfo[WORLD_SIDE_LEN].int_1 - base;
216 	yp1 = &minfo[1].int_1 - base;
217 	do {
218 	    tot = *base + base[xm1] + base[ym1] + base[xp1] + base[yp1];
219 	    av = tot / 5;
220 	    base[xm1] = base[ym1] = base[xp1] = base[yp1] = av;
221 	    *base++ = av + tot % 5;
222 	} while (base <= &minfo->int_7);
223 	break;
224     }
225     if (*--base >= max_waste) {
226 	*base -= WASTE_BURN_ON_TRANSPORT;
227 	++*pol;
228 	if (*waste_count > TRANSPORT_BURN_WASTE_COUNT) {
229 	    *waste_count = 0;
230 	} else {
231 	    ++ * waste_count;
232 	}
233     }
234 }
235 
236