]> git.zerfleddert.de Git - micropolis/blob - src/sim/g_map.c
5a65e00cf5db5ea554e0037bb9a3b62b7657c775
[micropolis] / src / sim / g_map.c
1 /* g_map.c
2 *
3 * Micropolis, Unix Version. This game was released for the Unix platform
4 * in or about 1990 and has been modified for inclusion in the One Laptop
5 * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If
6 * you need assistance with this program, you may contact:
7 * http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org.
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details. You should have received a
18 * copy of the GNU General Public License along with this program. If
19 * not, see <http://www.gnu.org/licenses/>.
20 *
21 * ADDITIONAL TERMS per GNU GPL Section 7
22 *
23 * No trademark or publicity rights are granted. This license does NOT
24 * give you any right, title or interest in the trademark SimCity or any
25 * other Electronic Arts trademark. You may not distribute any
26 * modification of this program using the trademark SimCity or claim any
27 * affliation or association with Electronic Arts Inc. or its employees.
28 *
29 * Any propagation or conveyance of this program must include this
30 * copyright notice and these terms.
31 *
32 * If you convey this program (or any modifications of it) and assume
33 * contractual liability for the program to recipients of it, you agree
34 * to indemnify Electronic Arts for any liability that those contractual
35 * assumptions impose on Electronic Arts.
36 *
37 * You may not misrepresent the origins of this program; modified
38 * versions of the program must be marked as such and not identified as
39 * the original program.
40 *
41 * This disclaimer supplements the one included in the General Public
42 * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
43 * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
44 * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF
45 * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS
46 * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
47 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
48 * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
49 * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
50 * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST
51 * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
52 * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
53 * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
54 * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
55 * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
56 * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME
57 * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
58 * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
59 * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
60 * NOT APPLY TO YOU.
61 */
62 #include "sim.h"
63
64
65 #define VAL_NONE 0
66 #define VAL_LOW 1
67 #define VAL_MEDIUM 2
68 #define VAL_HIGH 3
69 #define VAL_VERYHIGH 4
70 #define VAL_PLUS 5
71 #define VAL_VERYPLUS 6
72 #define VAL_MINUS 7
73 #define VAL_VERYMINUS 8
74
75 short valMap[] = {
76 -1, COLOR_LIGHTGRAY, COLOR_YELLOW, COLOR_ORANGE, COLOR_RED,
77 COLOR_DARKGREEN, COLOR_LIGHTGREEN, COLOR_ORANGE, COLOR_YELLOW
78 };
79
80 short valGrayMap[] = {
81 -1, 31, 127, 191, 255,
82 223, 255, 31, 0
83 };
84
85
86 void (*mapProcs[NMAPS])();
87
88 void drawPopDensity(SimView *view);
89 void drawRateOfGrowth(SimView *view);
90 void drawTrafMap(SimView *view);
91 void drawPolMap(SimView *view);
92 void drawCrimeMap(SimView *view);
93 void drawLandMap(SimView *view);
94 void drawFireRadius(SimView *view);
95 void drawPoliceRadius(SimView *view);
96 void ditherMap(SimView *view);
97 void drawRect(SimView *view, int pixel, int solid,
98 int x, int y, int w, int h);
99 void maybeDrawRect(SimView *view, int val,
100 int x, int y, int w, int h);
101
102
103 short GetCI(short x)
104 {
105 if (x < 50) return(VAL_NONE);
106 if (x < 100) return(VAL_LOW);
107 if (x < 150) return(VAL_MEDIUM);
108 if (x < 200) return(VAL_HIGH);
109 return(VAL_VERYHIGH);
110 }
111
112
113 void
114 drawPopDensity(SimView *view)
115 {
116 short x, y;
117
118 drawAll(view);
119 for (x = 0; x < HWLDX; x++) {
120 for (y = 0; y < HWLDY; y++) {
121 maybeDrawRect(view, GetCI(PopDensity[x][y]),
122 x * 6, y * 6, 6, 6);
123 }
124 }
125 }
126
127
128 void
129 drawRateOfGrowth(SimView *view)
130 {
131 short x, y;
132
133 drawAll(view);
134 for (x = 0; x < SmX; x++) {
135 for (y = 0; y < SmY; y++) {
136 short val, z = RateOGMem[x][y];
137
138 if (z > 100) val = VAL_VERYPLUS;
139 else {
140 if (z > 20) val = VAL_PLUS;
141 else {
142 if (z < -100) val = VAL_VERYMINUS;
143 else {
144 if (z < -20) val = VAL_MINUS;
145 else val = VAL_NONE;
146 }
147 }
148 }
149 maybeDrawRect(view, val,
150 x * 24, y * 24, 24, 24);
151 }
152 }
153 }
154
155
156 void
157 drawTrafMap(SimView *view)
158 {
159 short x;
160 short y;
161
162 drawLilTransMap(view);
163
164 for (x = 0; x < HWLDX; x++) {
165 for (y = 0; y < HWLDY; y++) {
166 maybeDrawRect(view, GetCI(TrfDensity[x][y]),
167 x * 6, y * 6, 6, 6);
168 }
169 }
170 }
171
172
173 void
174 drawPolMap(SimView *view)
175 {
176 short x, y;
177
178 drawAll(view);
179
180 for (x = 0; x < HWLDX; x++) {
181 for (y = 0; y < HWLDY; y++) {
182 maybeDrawRect(view, GetCI(10 + PollutionMem[x][y]),
183 x * 6, y * 6, 6, 6);
184 }
185 }
186 }
187
188
189 void
190 drawCrimeMap(SimView *view)
191 {
192 short x, y;
193
194 drawAll(view);
195
196 for (x = 0; x < HWLDX; x++) {
197 for (y = 0; y < HWLDY; y++) {
198 maybeDrawRect(view, GetCI(CrimeMem[x][y]),
199 x * 6, y * 6, 6, 6);
200 }
201 }
202 }
203
204
205 void
206 drawLandMap(SimView *view)
207 {
208 short x, y;
209
210 drawAll(view);
211
212 for (x = 0; x < HWLDX; x++) {
213 for (y = 0; y < HWLDY; y++) {
214 maybeDrawRect(view, GetCI(LandValueMem[x][y]),
215 x * 6, y * 6, 6, 6);
216 }
217 }
218 }
219
220
221 void
222 drawFireRadius(SimView *view)
223 {
224 short x, y;
225
226 drawAll(view);
227 for (x = 0; x < SmX; x++) {
228 for (y = 0; y < SmY; y++) {
229 maybeDrawRect(view, GetCI(FireRate[x][y]),
230 x * 24, y * 24, 24, 24);
231 }
232 }
233 }
234
235
236 void
237 drawPoliceRadius(SimView *view)
238 {
239 short x, y;
240
241 drawAll(view);
242 for (x = 0; x < SmX; x++) {
243 for (y = 0; y < SmY; y++) {
244 maybeDrawRect(view, GetCI(PoliceMapEffect[x][y]),
245 x * 24, y * 24, 24, 24);
246 }
247 }
248 }
249
250
251 void
252 setUpMapProcs(void)
253 {
254 mapProcs[ALMAP] = drawAll;
255 mapProcs[REMAP] = drawRes;
256 mapProcs[COMAP] = drawCom;
257 mapProcs[INMAP] = drawInd;
258 mapProcs[PRMAP] = drawPower;
259 mapProcs[RDMAP] = drawLilTransMap;
260 mapProcs[PDMAP] = drawPopDensity;
261 mapProcs[RGMAP] = drawRateOfGrowth;
262 mapProcs[TDMAP] = drawTrafMap;
263 mapProcs[PLMAP] = drawPolMap;
264 mapProcs[CRMAP] = drawCrimeMap;
265 mapProcs[LVMAP] = drawLandMap;
266 mapProcs[FIMAP] = drawFireRadius;
267 mapProcs[POMAP] = drawPoliceRadius;
268 mapProcs[DYMAP] = drawDynamic;
269 }
270
271
272 void
273 MemDrawMap(SimView *view)
274 {
275 (*mapProcs[view->map_state])(view);
276 if (!view->x->color) {
277 ditherMap(view);
278 XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_BLACK]);
279 XSetBackground(view->x->dpy, view->x->gc, view->pixels[COLOR_WHITE]);
280 XPutImage(view->x->dpy, view->pixmap, view->x->gc, view->image,
281 0, 0, 0, 0, view->m_width, view->m_height);
282 }
283 }
284
285
286 void
287 ditherMap(SimView *view)
288 {
289 int i, x, y, width, height;
290 int err, pixel1, pixel8;
291 int line_bytes1 = view->line_bytes;
292 int line_bytes8 = view->line_bytes8;
293 unsigned char *image1 = view->data;
294 unsigned char *image8 = view->data8;
295 int *errors;
296
297 width = view->m_width; height = view->m_height;
298
299 errors = (int *)malloc(sizeof(int) * (width));
300
301 for (i = 0; i < width; i++)
302 errors[i] = (Rand16() & 15) - 7;
303
304 err = (Rand16() & 15) - 7;
305
306 for (y = 0; y < height; y += 2) {
307 unsigned char *i1 = image1;
308 unsigned char *i8 = image8;
309
310 image1 += line_bytes1;
311 image8 += line_bytes8;
312
313 for (x = 0; x < width; x += 8) {
314 pixel1 = 0;
315 for (i = 0; i < 8; i++) {
316 pixel1 <<= 1;
317 pixel8 = *(i8++) + err + errors[x + i];
318 if (pixel8 > 127) {
319 err = pixel8 - 255;
320 } else {
321 pixel1 |= 1;
322 err = pixel8;
323 }
324 errors[x + i] = err/2;
325 err = err/2;
326 }
327 *(i1++) = pixel1;
328 }
329
330 i1 = image1 + (width / 8) - 1;
331 i8 = image8 + width - 1;
332
333 image1 += line_bytes1;
334 image8 += line_bytes8;
335
336 for (x = width - 8; x >= 0; x -= 8) {
337 pixel1 = 0;
338 for (i = 7; i >= 0; i--) {
339 pixel1 >>= 1;
340 pixel8 = *(i8--) + err + errors[x + i];
341 if (pixel8 > 127) {
342 err = pixel8 - 255;
343 } else {
344 pixel1 |= 128;
345 err = pixel8;
346 }
347 errors[x + i] = err/2;
348 err = err/2;
349 }
350 *(i1--) = pixel1;
351 }
352 }
353
354 free(errors);
355 }
356
357
358 void
359 maybeDrawRect(SimView *view, int val,
360 int x, int y, int w, int h)
361 {
362 if (val == VAL_NONE) return;
363
364 if (view->x->color) {
365 drawRect(view, view->pixels[valMap[val]], 0, x, y, w, h);
366 } else {
367 drawRect(view, valGrayMap[val], 1, x, y, w, h);
368 }
369 }
370
371
372 void
373 drawRect(SimView *view, int pixel, int solid,
374 int x, int y, int w, int h)
375 {
376 int W = view->m_width, H = view->m_height;
377
378 if (x < 0) {
379 if ((w += x) < 0) w = 0;
380 x = 0;
381 } else if (x > W) {
382 x = 0; w = 0;
383 }
384 if (x + w > W) {
385 w = W - x;
386 }
387 if (y < 0) {
388 if ((h += y) < 0) h = 0;
389 y = 0;
390 } else if (y > H) {
391 y = 0; h = 0;
392 }
393 if (y + h > H) {
394 h = H - y;
395 }
396
397 if (w && h) {
398 int i, j, stipple = (x ^ y) & 1;
399 #if 0
400 unsigned char *data =
401 view->x->color ? view->data : view->data8;
402 #endif
403
404 /* In the case of black and white, we use an 8 bit buffer and dither it. */
405 int pixelBytes =
406 view->x->color ? view->pixel_bytes : 1;
407 QUAD line =
408 view->x->color ? view->line_bytes : view->line_bytes8;
409
410 #if 0
411 unsigned char *image =
412 &(data[(line * y) + (x * pixelBytes)]);
413 #endif
414
415 switch (pixelBytes) {
416
417 case 1:
418 {
419 unsigned char *data =
420 view->data8;
421 unsigned char *image =
422 &data[(line * y) + (x * pixelBytes)];
423
424 for (i = h; i > 0; i--) {
425 for (j = w; j > 0; j--) {
426 if (solid || stipple++ & 1)
427 *image = pixel;
428 image++;
429 }
430 if (!(w & 1))
431 stipple++;
432 image += line - w;
433 }
434 }
435 break;
436
437 case 2:
438 {
439 unsigned short *data =
440 (unsigned short *)view->data;
441 unsigned short *image;
442 line >>= 1; /* Convert from byte offset to short offset */
443 image =
444 &data[(line * y) + x];
445
446 for (i = h; i > 0; i--) {
447 for (j = w; j > 0; j--) {
448 if (solid || stipple++ & 1) {
449 if (view->x->x_big_endian) {
450 *image = ((pixel & 0xff) << 8) | ((pixel & 0xff00) >> 8);
451 } else {
452 *image = pixel;
453 }
454 }
455 image++;
456 }
457 if (!(w & 1))
458 stipple++;
459 image += line - w;
460 }
461
462 }
463 break;
464
465 case 3:
466 case 4:
467 {
468 unsigned char *data =
469 (unsigned char *)view->data;
470 unsigned char *image;
471 image =
472 &data[(line * y) + x * pixelBytes];
473
474 for (i = h; i > 0; i--) {
475 for (j = w; j > 0; j--) {
476 if (view->x->x_big_endian) {
477 if (pixelBytes == 4) {
478 image++;
479 }
480 if (solid || stipple++ & 1) {
481 *(image++) = (pixel >> 16) & 0xff;
482 *(image++) = (pixel >> 8) & 0xff;
483 *(image++) = (pixel >> 0) & 0xff;
484 } else {
485 image += 3;
486 }
487 } else {
488 if (solid || stipple++ & 1) {
489 *(image++) = (pixel >> 0) & 0xff;
490 *(image++) = (pixel >> 8) & 0xff;
491 *(image++) = (pixel >> 16) & 0xff;
492 } else {
493 image += 3;
494 }
495 if (pixelBytes == 4) {
496 image++;
497 }
498 }
499 }
500 if (!(w & 1)) {
501 stipple++;
502 }
503 image += line - w * pixelBytes;
504 }
505 }
506 break;
507
508 default:
509 assert(0); /* Undefined depth */
510 break;
511 }
512
513 }
514 }
515
516
517
Impressum, Datenschutz