]> git.zerfleddert.de Git - micropolis/blob - src/sim/g_map.c
667cfae5000a2344eecad485c896c51a55265f7c
[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 int (*mapProcs[NMAPS])();
87
88 int drawAll(SimView *view);
89 int drawRes(SimView *view);
90 int drawCom(SimView *view);
91 int drawInd(SimView *view);
92 int drawPower(SimView *view);
93 int drawLilTransMap(SimView *view);
94 int drawPopDensity(SimView *view);
95 int drawRateOfGrowth(SimView *view);
96 int drawTrafMap(SimView *view);
97 int drawPolMap(SimView *view);
98 int drawCrimeMap(SimView *view);
99 int drawLandMap(SimView *view);
100 int drawFireRadius(SimView *view);
101 int drawPoliceRadius(SimView *view);
102 int drawDynamic(SimView *view);
103
104
105 short GetCI(short x)
106 {
107 if (x < 50) return(VAL_NONE);
108 if (x < 100) return(VAL_LOW);
109 if (x < 150) return(VAL_MEDIUM);
110 if (x < 200) return(VAL_HIGH);
111 return(VAL_VERYHIGH);
112 }
113
114
115 drawPopDensity(SimView *view)
116 {
117 short x, y;
118
119 drawAll(view);
120 for (x = 0; x < HWLDX; x++) {
121 for (y = 0; y < HWLDY; y++) {
122 maybeDrawRect(view, GetCI(PopDensity[x][y]),
123 x * 6, y * 6, 6, 6);
124 }
125 }
126 }
127
128
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 drawTrafMap(SimView *view)
157 {
158 short x;
159 short y;
160
161 drawLilTransMap(view);
162
163 for (x = 0; x < HWLDX; x++) {
164 for (y = 0; y < HWLDY; y++) {
165 maybeDrawRect(view, GetCI(TrfDensity[x][y]),
166 x * 6, y * 6, 6, 6);
167 }
168 }
169 }
170
171
172 drawPolMap(SimView *view)
173 {
174 short x, y;
175
176 drawAll(view);
177
178 for (x = 0; x < HWLDX; x++) {
179 for (y = 0; y < HWLDY; y++) {
180 maybeDrawRect(view, GetCI(10 + PollutionMem[x][y]),
181 x * 6, y * 6, 6, 6);
182 }
183 }
184 }
185
186
187 drawCrimeMap(SimView *view)
188 {
189 short x, y;
190
191 drawAll(view);
192
193 for (x = 0; x < HWLDX; x++) {
194 for (y = 0; y < HWLDY; y++) {
195 maybeDrawRect(view, GetCI(CrimeMem[x][y]),
196 x * 6, y * 6, 6, 6);
197 }
198 }
199 }
200
201
202 drawLandMap(SimView *view)
203 {
204 short x, y;
205
206 drawAll(view);
207
208 for (x = 0; x < HWLDX; x++) {
209 for (y = 0; y < HWLDY; y++) {
210 maybeDrawRect(view, GetCI(LandValueMem[x][y]),
211 x * 6, y * 6, 6, 6);
212 }
213 }
214 }
215
216
217 drawFireRadius(SimView *view)
218 {
219 short x, y;
220
221 drawAll(view);
222 for (x = 0; x < SmY; x++) {
223 for (y = 0; y < SmY; y++) {
224 maybeDrawRect(view, GetCI(FireRate[x][y]),
225 x * 24, y * 24, 24, 24);
226 }
227 }
228 }
229
230
231 drawPoliceRadius(SimView *view)
232 {
233 short x, y;
234
235 drawAll(view);
236 for (x = 0; x < SmX; x++) {
237 for (y = 0; y < SmY; y++) {
238 maybeDrawRect(view, GetCI(PoliceMapEffect[x][y]),
239 x * 24, y * 24, 24, 24);
240 }
241 }
242 }
243
244
245 setUpMapProcs(void)
246 {
247 mapProcs[ALMAP] = drawAll;
248 mapProcs[REMAP] = drawRes;
249 mapProcs[COMAP] = drawCom;
250 mapProcs[INMAP] = drawInd;
251 mapProcs[PRMAP] = drawPower;
252 mapProcs[RDMAP] = drawLilTransMap;
253 mapProcs[PDMAP] = drawPopDensity;
254 mapProcs[RGMAP] = drawRateOfGrowth;
255 mapProcs[TDMAP] = drawTrafMap;
256 mapProcs[PLMAP] = drawPolMap;
257 mapProcs[CRMAP] = drawCrimeMap;
258 mapProcs[LVMAP] = drawLandMap;
259 mapProcs[FIMAP] = drawFireRadius;
260 mapProcs[POMAP] = drawPoliceRadius;
261 mapProcs[DYMAP] = drawDynamic;
262 }
263
264
265 MemDrawMap(SimView *view)
266 {
267 (*mapProcs[view->map_state])(view);
268 if (!view->x->color) {
269 ditherMap(view);
270 XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_BLACK]);
271 XSetBackground(view->x->dpy, view->x->gc, view->pixels[COLOR_WHITE]);
272 XPutImage(view->x->dpy, view->pixmap, view->x->gc, view->image,
273 0, 0, 0, 0, view->m_width, view->m_height);
274 }
275 }
276
277
278 ditherMap(SimView *view)
279 {
280 int i, x, y, width, height;
281 int err, pixel1, pixel8;
282 int line_bytes1 = view->line_bytes;
283 int line_bytes8 = view->line_bytes8;
284 unsigned char *image1 = view->data;
285 unsigned char *image8 = view->data8;
286 int *errors;
287
288 width = view->m_width; height = view->m_height;
289
290 errors = (int *)malloc(sizeof(int) * (width));
291
292 for (i = 0; i < width; i++)
293 errors[i] = (Rand16() & 15) - 7;
294
295 err = (Rand16() & 15) - 7;
296
297 for (y = 0; y < height; y += 2) {
298 unsigned char *i1 = image1;
299 unsigned char *i8 = image8;
300
301 image1 += line_bytes1;
302 image8 += line_bytes8;
303
304 for (x = 0; x < width; x += 8) {
305 pixel1 = 0;
306 for (i = 0; i < 8; i++) {
307 pixel1 <<= 1;
308 pixel8 = *(i8++) + err + errors[x + i];
309 if (pixel8 > 127) {
310 err = pixel8 - 255;
311 } else {
312 pixel1 |= 1;
313 err = pixel8;
314 }
315 errors[x + i] = err/2;
316 err = err/2;
317 }
318 *(i1++) = pixel1;
319 }
320
321 i1 = image1 + (width / 8) - 1;
322 i8 = image8 + width - 1;
323
324 image1 += line_bytes1;
325 image8 += line_bytes8;
326
327 for (x = width - 8; x >= 0; x -= 8) {
328 pixel1 = 0;
329 for (i = 7; i >= 0; i--) {
330 pixel1 >>= 1;
331 pixel8 = *(i8--) + err + errors[x + i];
332 if (pixel8 > 127) {
333 err = pixel8 - 255;
334 } else {
335 pixel1 |= 128;
336 err = pixel8;
337 }
338 errors[x + i] = err/2;
339 err = err/2;
340 }
341 *(i1--) = pixel1;
342 }
343 }
344
345 free(errors);
346 }
347
348
349 maybeDrawRect(SimView *view, int val,
350 int x, int y, int w, int h)
351 {
352 if (val == VAL_NONE) return;
353
354 if (view->x->color) {
355 drawRect(view, view->pixels[valMap[val]], 0, x, y, w, h);
356 } else {
357 drawRect(view, valGrayMap[val], 1, x, y, w, h);
358 }
359 }
360
361
362 drawRect(SimView *view, int pixel, int solid,
363 int x, int y, int w, int h)
364 {
365 int W = view->m_width, H = view->m_height;
366
367 if (x < 0) {
368 if ((w += x) < 0) w = 0;
369 x = 0;
370 } else if (x > W) {
371 x = 0; w = 0;
372 }
373 if (x + w > W) {
374 w = W - x;
375 }
376 if (y < 0) {
377 if ((h += y) < 0) h = 0;
378 y = 0;
379 } else if (y > H) {
380 y = 0; h = 0;
381 }
382 if (y + h > H) {
383 h = H - y;
384 }
385
386 if (w && h) {
387 int i, j, stipple = (x ^ y) & 1;
388 unsigned char *data =
389 view->x->color ? view->data : view->data8;
390
391 /* In the case of black and white, we use an 8 bit buffer and dither it. */
392 int pixelBytes =
393 view->x->color ? view->pixel_bytes : 1;
394 QUAD line =
395 view->x->color ? view->line_bytes : view->line_bytes8;
396
397 unsigned char *image =
398 &(data[(line * y) + (x * pixelBytes)]);
399
400 switch (pixelBytes) {
401
402 case 1:
403 {
404 unsigned char *data =
405 view->data8;
406 unsigned char *image =
407 &data[(line * y) + (x * pixelBytes)];
408
409 for (i = h; i > 0; i--) {
410 for (j = w; j > 0; j--) {
411 if (solid || stipple++ & 1)
412 *image = pixel;
413 image++;
414 }
415 if (!(w & 1))
416 stipple++;
417 image += line - w;
418 }
419 }
420 break;
421
422 case 2:
423 {
424 unsigned short *data =
425 (unsigned short *)view->data;
426 unsigned short *image;
427 line >>= 1; /* Convert from byte offset to short offset */
428 image =
429 &data[(line * y) + x];
430
431 for (i = h; i > 0; i--) {
432 for (j = w; j > 0; j--) {
433 if (solid || stipple++ & 1) {
434 if (view->x->x_big_endian) {
435 *image = ((pixel & 0xff) << 8) | ((pixel & 0xff00) >> 8);
436 } else {
437 *image = pixel;
438 }
439 }
440 image++;
441 }
442 if (!(w & 1))
443 stipple++;
444 image += line - w;
445 }
446
447 }
448 break;
449
450 case 3:
451 case 4:
452 {
453 unsigned char *data =
454 (unsigned char *)view->data;
455 unsigned char *image;
456 image =
457 &data[(line * y) + x * pixelBytes];
458
459 for (i = h; i > 0; i--) {
460 for (j = w; j > 0; j--) {
461 if (view->x->x_big_endian) {
462 if (pixelBytes == 4) {
463 image++;
464 }
465 if (solid || stipple++ & 1) {
466 *(image++) = (pixel >> 16) & 0xff;
467 *(image++) = (pixel >> 8) & 0xff;
468 *(image++) = (pixel >> 0) & 0xff;
469 } else {
470 image += 3;
471 }
472 } else {
473 if (stipple++ & 1) {
474 *(image++) = (pixel >> 0) & 0xff;
475 *(image++) = (pixel >> 8) & 0xff;
476 *(image++) = (pixel >> 16) & 0xff;
477 } else {
478 image += 3;
479 }
480 if (pixelBytes == 4) {
481 image++;
482 }
483 }
484 }
485 if (!(w & 1)) {
486 stipple++;
487 }
488 image += line - w * pixelBytes;
489 }
490 }
491 break;
492
493 default:
494 assert(0); /* Undefined depth */
495 break;
496 }
497
498 }
499 }
500
501
502
Impressum, Datenschutz