1 /* ---------------------------------------------------------------------- *
2  * shrtypes.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 "lcconfig.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "lcstring.h"
10 #include "common.h"
11 #include "lctypes.h"
12 #include "lin-city.h"
13 #include "typeinit.h"
14 #include "cliglobs.h"
15 #include "engglobs.h"
16 
17 
18 void
set_mappoint_used(int fromx,int fromy,int x,int y)19 set_mappoint_used (int fromx, int fromy, int x, int y)
20 {
21     MP_TYPE(x,y) = CST_USED;
22     MP_GROUP(x,y) = GROUP_USED;
23     MP_INFO(x,y).int_1 = fromx;
24     MP_INFO(x,y).int_2 = fromy;
25 }
26 
27 
28 void
set_mappoint(int x,int y,short selected_type)29 set_mappoint (int x, int y, short selected_type)
30 {
31   int grp;
32 
33   if ((grp = get_group_of_type(selected_type)) < 0) return;
34 
35   MP_TYPE(x,y) = selected_type;
36   MP_GROUP(x,y) = grp;
37 
38   if (main_groups[grp].size == 2)
39     {
40       set_mappoint_used (x, y, x + 1, y);
41       set_mappoint_used (x, y, x, y + 1);
42       set_mappoint_used (x, y, x + 1, y + 1);
43     }
44   else if (main_groups[grp].size == 3)
45     {
46       set_mappoint_used (x, y, x + 1, y);
47       set_mappoint_used (x, y, x + 2, y);
48       set_mappoint_used (x, y, x + 1, y + 1);
49       set_mappoint_used (x, y, x + 2, y + 1);
50       set_mappoint_used (x, y, x + 1, y + 2);
51       set_mappoint_used (x, y, x + 2, y + 2);
52       set_mappoint_used (x, y, x, y + 1);
53       set_mappoint_used (x, y, x, y + 2);
54     }
55   else if (main_groups[grp].size == 4)
56     {
57       set_mappoint_used (x, y, x + 1, y);
58       set_mappoint_used (x, y, x + 2, y);
59       set_mappoint_used (x, y, x + 1, y + 1);
60       set_mappoint_used (x, y, x + 2, y + 1);
61       set_mappoint_used (x, y, x + 1, y + 2);
62       set_mappoint_used (x, y, x + 2, y + 2);
63       set_mappoint_used (x, y, x, y + 1);
64       set_mappoint_used (x, y, x, y + 2);
65 
66       set_mappoint_used (x, y, x + 3, y);
67       set_mappoint_used (x, y, x + 3, y + 1);
68       set_mappoint_used (x, y, x + 3, y + 2);
69       set_mappoint_used (x, y, x + 3, y + 3);
70       set_mappoint_used (x, y, x, y + 3);
71       set_mappoint_used (x, y, x + 1, y + 3);
72       set_mappoint_used (x, y, x + 2, y + 3);
73     }
74 }
75 
76 
77 void
connect_transport(int originx,int originy,int w,int h)78 connect_transport (int originx, int originy, int w, int h)
79 {
80   int x, y, mask, tflags;
81   short group, type;
82 
83   static const short power_table[16] =
84   {
85     CST_POWERL_H_D, CST_POWERL_V_D, CST_POWERL_H_D, CST_POWERL_RD_D,
86     CST_POWERL_H_D, CST_POWERL_LD_D, CST_POWERL_H_D, CST_POWERL_LDR_D,
87     CST_POWERL_V_D, CST_POWERL_V_D, CST_POWERL_RU_D, CST_POWERL_UDR_D,
88     CST_POWERL_LU_D, CST_POWERL_LDU_D, CST_POWERL_LUR_D, CST_POWERL_LUDR_D
89   };
90   static const short track_table[16] =
91   {
92     CST_TRACK_LR, CST_TRACK_LR, CST_TRACK_UD, CST_TRACK_LU,
93     CST_TRACK_LR, CST_TRACK_LR, CST_TRACK_UR, CST_TRACK_LUR,
94     CST_TRACK_UD, CST_TRACK_LD, CST_TRACK_UD, CST_TRACK_LUD,
95     CST_TRACK_DR, CST_TRACK_LDR, CST_TRACK_UDR, CST_TRACK_LUDR
96   };
97   static const short road_table[16] =
98   {
99     CST_ROAD_LR, CST_ROAD_LR, CST_ROAD_UD, CST_ROAD_LU,
100     CST_ROAD_LR, CST_ROAD_LR, CST_ROAD_UR, CST_ROAD_LUR,
101     CST_ROAD_UD, CST_ROAD_LD, CST_ROAD_UD, CST_ROAD_LUD,
102     CST_ROAD_DR, CST_ROAD_LDR, CST_ROAD_UDR, CST_ROAD_LUDR
103   };
104   static const short rail_table[16] =
105   {
106     CST_RAIL_LR, CST_RAIL_LR, CST_RAIL_UD, CST_RAIL_LU,
107     CST_RAIL_LR, CST_RAIL_LR, CST_RAIL_UR, CST_RAIL_LUR,
108     CST_RAIL_UD, CST_RAIL_LD, CST_RAIL_UD, CST_RAIL_LUD,
109     CST_RAIL_DR, CST_RAIL_LDR, CST_RAIL_UDR, CST_RAIL_LUDR
110   };
111   static const short water_table[16] =
112   {
113     CST_WATER, CST_WATER_D, CST_WATER_R, CST_WATER_RD,
114     CST_WATER_L, CST_WATER_LD, CST_WATER_LR, CST_WATER_LRD,
115     CST_WATER_U, CST_WATER_UD, CST_WATER_UR, CST_WATER_URD,
116     CST_WATER_LU, CST_WATER_LUD, CST_WATER_LUR, CST_WATER_LURD
117   };
118 
119   /* Adjust originx,originy,w,h to proper range */
120   if (originx <= 0) {
121     w -= 1 - originx;
122     originx = 1;
123   }
124   if (originy <= 0) {
125     h -= 1 - originy;
126     originy = 1;
127   }
128   if (originx + w >= WORLD_SIDE_LEN) {
129     w = WORLD_SIDE_LEN - originx;
130   }
131   if (originy + h >= WORLD_SIDE_LEN) {
132     h = WORLD_SIDE_LEN - originy;
133   }
134 
135   for (x = originx; x < originx + w; x++) {
136     for (y = originy; y < originy + h; y++) {
137       switch (MP_GROUP(x,y))
138 	{
139 	case GROUP_POWER_LINE:
140 	  /* First, set up a mask indicating into which directions
141 	     power may be transferred */
142 	  mask = 0;
143 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
144 	  if (y > 0)
145 #endif
146 	    {		/* up -- (ThMO) */
147 	      group = MP_GROUP(x,y-1);
148 
149 	      /* see if dug under track, rail or road */
150 
151 	      if (y > 1 && (group == GROUP_TRACK
152 			    || group == GROUP_RAIL
153 			    || group == GROUP_ROAD
154 			    || group == GROUP_WATER))
155 		group = MP_GROUP(x,y-2);
156 	      switch (group)
157 		{
158 		case GROUP_POWER_LINE:
159 		case GROUP_SOLAR_POWER:
160 		case GROUP_SUBSTATION:
161 		case GROUP_COAL_POWER:
162 		  mask |= 8;
163 		  break;
164 		}
165 	    }
166 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
167 	  if (x > 0)
168 #endif
169 	    {		/* left -- (ThMO) */
170 	      group = MP_GROUP(x-1,y);
171 	      if (x > 1 && (group == GROUP_TRACK
172 			    || group == GROUP_RAIL
173 			    || group == GROUP_ROAD
174 			    || group == GROUP_WATER))
175 		group = MP_GROUP(x-2,y);
176 	      switch (group)
177 		{
178 		case GROUP_POWER_LINE:
179 		case GROUP_SOLAR_POWER:
180 		case GROUP_SUBSTATION:
181 		case GROUP_COAL_POWER:
182 		  mask |= 4;
183 		  break;
184 		}
185 	    }
186 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
187 	  if (x < WORLD_SIDE_LEN - 1)
188 #endif
189 	    {		/* right -- (ThMO) */
190 	      group = MP_GROUP(x+1,y);
191 	      if (x < WORLD_SIDE_LEN - 2 && (group == GROUP_TRACK
192 					     || group == GROUP_RAIL
193 					     || group == GROUP_ROAD
194 					     || group == GROUP_WATER))
195 		group = MP_GROUP(x+2,y);
196 	      switch (group)
197 		{
198 		case GROUP_WINDMILL:
199 		  if (MP_INFO(x + 1,y).int_2 < MODERN_WINDMILL_TECH)
200 		    break;
201 		case GROUP_POWER_LINE:
202 		case GROUP_SOLAR_POWER:
203 		case GROUP_SUBSTATION:
204 		case GROUP_COAL_POWER:
205 		  mask |= 2;
206 		  break;
207 		}
208 	    }
209 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
210 	  if (y < WORLD_SIDE_LEN - 1)
211 #endif
212 	    {		/* down -- (ThMO) */
213 	      group = MP_GROUP(x,y+1);
214 	      if (y < WORLD_SIDE_LEN - 2 && (group == GROUP_TRACK
215 					     || group == GROUP_RAIL
216 					     || group == GROUP_ROAD
217 					     || group == GROUP_WATER))
218 		group = MP_GROUP(x,y+2);
219 	      switch (group)
220 		{
221 		case GROUP_WINDMILL:
222 		  if (MP_INFO(x,y + 1).int_2 < MODERN_WINDMILL_TECH)
223 		    break;
224 		case GROUP_POWER_LINE:
225 		case GROUP_SOLAR_POWER:
226 		case GROUP_SUBSTATION:
227 		case GROUP_COAL_POWER:
228 		  ++mask;
229 		  break;
230 		}
231 	    }
232 	  /* Next, set the connectivity into MP_TYPE */
233 	  MP_TYPE(x,y) = power_table[mask];
234 	  /* Finally, adjust MP_TYPE to show electon bolt */
235 #ifdef commentout
236 	   WCK: This is done in do_power_line now
237 	  	  if (MP_INFO(x,y).int_1 != 0)
238 		  MP_TYPE(x,y) -= 11;
239 #endif
240 	  break;
241 
242 	case GROUP_TRACK:
243 #if	FLAG_LEFT != 1 || FLAG_UP != 2 || FLAG_RIGHT != 4 || FLAG_DOWN != 8
244 #error  check_track_graphics(): you loose
245 #error  this algorithm depends on proper flag settings -- (ThMO)
246 #endif
247 	  mask = 0;
248 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
249 	  if (y > 0)
250 #endif
251 	    {
252 	      if (MP_GROUP(x,y-1) == GROUP_TRACK)
253 		mask |= FLAG_UP;
254 	    }
255 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
256 	  if (x > 0)
257 #endif
258 	    {
259 	      if (MP_GROUP(x-1,y) == GROUP_TRACK)
260 		mask |= FLAG_LEFT;
261 	    }
262 	  tflags = mask;
263 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
264 	  if (x < WORLD_SIDE_LEN - 1)
265 #endif
266 	    {
267 	      switch (MP_GROUP(x+1,y))
268 		{
269 		case GROUP_TRACK:
270 		  tflags |= FLAG_RIGHT;
271 		case GROUP_COMMUNE:
272 		case GROUP_COALMINE:
273 		case GROUP_OREMINE:
274 		case GROUP_INDUSTRY_L:
275 		case GROUP_INDUSTRY_H:
276 		case GROUP_RECYCLE:
277 		case GROUP_TIP:
278 		case GROUP_PORT:
279 		  mask |= FLAG_RIGHT;
280 		  break;
281 		default:
282 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
283 		  if (y > 0)
284 #endif
285 		    if (MP_GROUP(x+1,y-1) == GROUP_COAL_POWER)
286 		      mask |= FLAG_RIGHT;
287 		  break;
288 		}
289 	    }
290 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
291 	  if (y < WORLD_SIDE_LEN - 1)
292 #endif
293 	    {
294 	      switch (MP_GROUP(x,y+1))
295 		{
296 		case GROUP_TRACK:
297 		  tflags |= FLAG_DOWN;
298 		case GROUP_COMMUNE:
299 		case GROUP_COALMINE:
300 		case GROUP_OREMINE:
301 		case GROUP_INDUSTRY_L:
302 		case GROUP_INDUSTRY_H:
303 		case GROUP_RECYCLE:
304 		case GROUP_TIP:
305 		case GROUP_PORT:
306 		  mask |= FLAG_DOWN;
307 		  break;
308 		default:
309 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
310 		  if (x > 0)
311 #endif
312 		    if (MP_GROUP(x-1,y+1) == GROUP_COAL_POWER)
313 		      mask |= FLAG_DOWN;
314 		  break;
315 		}
316 	    }
317 	  MP_INFO(x,y).flags &= ~(FLAG_UP | FLAG_DOWN | FLAG_LEFT
318 				  | FLAG_RIGHT);
319 	  MP_INFO(x,y).flags |= tflags;
320 	  MP_TYPE(x,y) = track_table[mask];
321 	  break;
322 
323 	case GROUP_ROAD:
324 #if	FLAG_LEFT != 1 || FLAG_UP != 2 || FLAG_RIGHT != 4 || FLAG_DOWN != 8
325 #error  check_road_graphics(): you loose
326 #error  this algorithm depends on proper flag settings -- (ThMO)
327 #endif
328 	  mask = 0;
329 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
330 	  if (y > 0)
331 #endif
332 	    {
333 	      if (MP_GROUP(x,y-1) == GROUP_ROAD)
334 		mask |= FLAG_UP;
335 	    }
336 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
337 	  if (x > 0)
338 #endif
339 	    {
340 	      if (MP_GROUP(x-1,y) == GROUP_ROAD)
341 		mask |= FLAG_LEFT;
342 	    }
343 	  tflags = mask;
344 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
345 	  if (x < WORLD_SIDE_LEN - 1)
346 #endif
347 	    {
348 	      switch (MP_GROUP(x+1,y))
349 		{
350 		case GROUP_ROAD:
351 		  tflags |= FLAG_RIGHT;
352 		case GROUP_COMMUNE:
353 		case GROUP_COALMINE:
354 		case GROUP_OREMINE:
355 		case GROUP_INDUSTRY_L:
356 		case GROUP_INDUSTRY_H:
357 		case GROUP_RECYCLE:
358 		case GROUP_TIP:
359 		case GROUP_PORT:
360 		  mask |= FLAG_RIGHT;
361 		  break;
362 		default:
363 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
364 		  if (y > 0)
365 #endif
366 		    if (MP_GROUP(x+1,y-1) == GROUP_COAL_POWER)
367 		      mask |= FLAG_RIGHT;
368 		  break;
369 		}
370 	    }
371 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
372 	  if (y < WORLD_SIDE_LEN - 1)
373 #endif
374 	    {
375 	      switch (MP_GROUP(x,y+1))
376 		{
377 		case GROUP_ROAD:
378 		  tflags |= FLAG_DOWN;
379 		case GROUP_COMMUNE:
380 		case GROUP_COALMINE:
381 		case GROUP_OREMINE:
382 		case GROUP_INDUSTRY_L:
383 		case GROUP_INDUSTRY_H:
384 		case GROUP_RECYCLE:
385 		case GROUP_TIP:
386 		case GROUP_PORT:
387 		  mask |= FLAG_DOWN;
388 		  break;
389 		default:
390 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
391 		  if (x > 0)
392 #endif
393 		    if (MP_GROUP(x-1,y+1) == GROUP_COAL_POWER)
394 		      mask |= FLAG_DOWN;
395 		  break;
396 		}
397 	    }
398 	  MP_INFO(x,y).flags &= ~(FLAG_UP | FLAG_DOWN | FLAG_LEFT
399 				  | FLAG_RIGHT);
400 	  MP_INFO(x,y).flags |= tflags;
401 	  MP_TYPE(x,y) = road_table[mask];
402 	  break;
403 
404 	case GROUP_RAIL:
405 #if	FLAG_LEFT != 1 || FLAG_UP != 2 || FLAG_RIGHT != 4 || FLAG_DOWN != 8
406 #error  check_rail_graphics(): you loose
407 #error  this algorithm depends on proper flag settings -- (ThMO)
408 #endif
409 	  mask = 0;
410 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
411 	  if (y > 0)
412 #endif
413 	    {
414 	      if (MP_GROUP(x,y-1) == GROUP_RAIL)
415 		mask |= FLAG_UP;
416 	    }
417 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
418 	  if (x > 0)
419 #endif
420 	    {
421 	      if (MP_GROUP(x-1,y) == GROUP_RAIL)
422 		mask |= FLAG_LEFT;
423 	    }
424 	  tflags = mask;
425 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
426 	  if (x < WORLD_SIDE_LEN - 1)
427 #endif
428 	    {
429 	      switch (MP_GROUP(x+1,y))
430 		{
431 		case GROUP_RAIL:
432 		  tflags |= FLAG_RIGHT;
433 		case GROUP_COMMUNE:
434 		case GROUP_COALMINE:
435 		case GROUP_OREMINE:
436 		case GROUP_INDUSTRY_L:
437 		case GROUP_INDUSTRY_H:
438 		case GROUP_RECYCLE:
439 		case GROUP_TIP:
440 		case GROUP_PORT:
441 		  mask |= FLAG_RIGHT;
442 		  break;
443 		default:
444 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
445 		  if (y > 0)
446 #endif
447 		    if (MP_GROUP(x+1,y-1) == GROUP_COAL_POWER)
448 		      mask |= FLAG_RIGHT;
449 		  break;
450 		}
451 	    }
452 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
453 	  if (y < WORLD_SIDE_LEN - 1)
454 #endif
455 	    {
456 	      switch (MP_GROUP(x,y + 1))
457 		{
458 		case GROUP_RAIL:
459 		  tflags |= FLAG_DOWN;
460 		case GROUP_COMMUNE:
461 		case GROUP_COALMINE:
462 		case GROUP_OREMINE:
463 		case GROUP_INDUSTRY_L:
464 		case GROUP_INDUSTRY_H:
465 		case GROUP_RECYCLE:
466 		case GROUP_TIP:
467 		case GROUP_PORT:
468 		  mask |= FLAG_DOWN;
469 		  break;
470 		default:
471 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
472 		  if (x > 0)
473 #endif
474 		    if (MP_GROUP(x - 1,y + 1)
475 			== GROUP_COAL_POWER)
476 		      mask |= FLAG_DOWN;
477 		  break;
478 		}
479 	    }
480 	  MP_INFO(x,y).flags &= ~(FLAG_UP | FLAG_DOWN | FLAG_LEFT
481 				  | FLAG_RIGHT);
482 	  MP_INFO(x,y).flags |= tflags;
483 	  MP_TYPE(x,y) = rail_table[mask];
484 	  break;
485 
486 	case GROUP_WATER:
487 	  mask = 0;
488 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
489 	  if (y > 0)
490 #endif
491 	    {		/* up -- (ThMO) */
492 	      if (MP_GROUP(x,y - 1)
493 		  == GROUP_WATER)
494 		mask |= 8;
495 	    }
496 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
497 	  if (x > 0)
498 #endif
499 	    {		/* left -- (ThMO) */
500 	      type = MP_TYPE(x - 1,y);
501 	      if ((type == CST_USED &&
502 		   MP_GROUP(MP_INFO(x-1,y).int_1,MP_INFO(x-1,y).int_2)
503 		   == GROUP_PORT)
504 		  || get_group_of_type(type) == GROUP_WATER)
505 		mask |= 4;
506 	    }
507 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
508 	  if (x < WORLD_SIDE_LEN - 1)
509 #endif
510 	    {		/* right -- (ThMO) */
511 	      if (MP_GROUP(x + 1,y)
512 		  == GROUP_WATER)
513 		mask |= 2;
514 	    }
515 #ifdef	THOMMY_MAY_BE_WRONG	/* just in case -- (ThMO) */
516 	  if (y < WORLD_SIDE_LEN - 1)
517 #endif
518 	    {		/* down -- (ThMO) */
519 	      if (MP_GROUP(x,y + 1)
520 		  == GROUP_WATER)
521 		++mask;
522 	    }
523 	  MP_TYPE(x,y) = water_table[mask];
524 	  break;
525 	} /* end switch */
526     } /* end for */
527   } /* end for */
528 }
529 
530