]> git.zerfleddert.de Git - micropolis/blob - src/sim/g_cam.c
allow overriding $CC for tclx
[micropolis] / src / sim / g_cam.c
1 /* g_cam.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 #ifdef CAM
66
67
68 Can *
69 new_can(int w, int h, Byte *mem, int line_bytes)
70 {
71 Can *can = (Can *)malloc(sizeof(Can));
72
73 can->width = w;
74 can->height = h;
75 can->line_bytes = line_bytes;
76 can->mem = mem;
77
78 return (can);
79 }
80
81
82 Cam *
83 new_cam(SimCam *scam, int x, int y, int w, int h, int dx, int dy, vf func)
84 {
85 Cam *cam = (Cam *)malloc(sizeof(Cam));
86 int ww, hh;
87
88 cam->x = x;
89 cam->y = y;
90 cam->ideal_width = w;
91 cam->ideal_height = h;
92 w = (w + 1) & ~1;
93 h = (h + 1) & ~1;
94 ww = w + 2;
95 hh = h + 2;
96 cam->width = w;
97 cam->height = h;
98 cam->back = new_can(ww, hh, (Byte *)malloc(ww * hh), ww);
99 cam->front = new_can(w, h,
100 (Byte *)scam->data + x + (y * scam->line_bytes),
101 scam->line_bytes);
102 cam->neighborhood = func;
103 cam->rule = NULL;
104 cam->rule_size = 0;
105 cam->phase = 0;
106 cam->wrap = 3;
107 cam->frob = -1;
108 cam->steps = 1;
109 cam->dx = dx;
110 cam->dy = dy;
111 cam->gx = 0;
112 cam->gy = 0;
113 cam->dragging = 0;
114 cam->set_x = -1;
115 cam->set_y = -1;
116 cam->set_width = -1;
117 cam->set_height = -1;
118 cam->set_x0 = -1;
119 cam->set_y0 = -1;
120 cam->set_x1 = -1;
121 cam->set_y1 = -1;
122 cam->name = NULL;
123 cam->next = scam->cam_list;
124 scam->cam_list = cam;
125 scam->cam_count++;
126
127 return (cam);
128 }
129
130
131 scam_randomize(SimCam *scam)
132 {
133 u_char *data = scam->data;
134 int line_bytes = scam->line_bytes;
135 int pixels = line_bytes * scam->w_height;
136 int i;
137
138 for (i = 0; i < pixels; i++) {
139 *data = (char)(Rand16() >>4);
140 data++;
141 }
142 }
143
144
145 cam_randomize(Cam *cam)
146 {
147 int x, y, w, h, lb;
148 Byte *image;
149
150 w = cam->width;
151 h = cam->height;
152 lb = cam->front->line_bytes;
153 image = cam->front->mem;
154
155 for (y = 0; y < h; y++, image += lb) {
156 for (x = 0; x < w; x++) {
157 image[x] = (char)(Rand16() >> 4);
158 }
159 }
160 }
161
162
163 cam_do_rule(SimCam *scam, Cam *cam)
164 {
165 Byte *back, *front;
166 int frontline, backline;
167 int w, h;
168 int steps = cam->steps;
169 int step;
170
171 back = cam->back->mem;
172 backline = cam->back->line_bytes;
173
174 front = cam->front->mem;
175 frontline = cam->front->line_bytes;
176
177 w = cam->width;
178 h = cam->height;
179
180 for (step=0; step < steps; step++) {
181 int x, y;
182 Byte *p = back + backline + 1,
183 *f = front;
184 /*
185 * Copy wrapping edges from front=>back:
186 *
187 * 0 ff f0 f1 ... fe ff f0
188 *
189 * 1 0f 00 01 ... 0e 0f 00
190 * 2 1f 10 11 ... 1e 1f 10
191 * .. .. .. .. .. ..
192 * ef e0 e1 ... ee ef e0
193 * h ff f0 f1 ... fe ff f0
194 *
195 * h+1 0f 00 01 ... 0e 0f 00
196 *
197 * wrap value: effect:
198 * 0 no effect
199 * 1 copy front=>back, no wrap
200 * 2 no copy, wrap edges
201 * 3 copy front=>back, wrap edges
202 * 4 copy front=>back, same edges
203 * 5 copy edges from screen
204 */
205
206 switch (cam->wrap) {
207
208 case 0:
209 break;
210
211 case 1:
212 for (y=0; y<h; y++) {
213 memcpy(p, f, w);
214 p += backline;
215 f += frontline;
216 }
217 break;
218
219 case 2:
220 for (y=0; y<h; y++) {
221 p[-1] = p[w-1];
222 p[w] = p[0];
223 p += backline;
224 f += frontline;
225 }
226 memcpy(back, back + backline*h, backline);
227 memcpy(back + backline*(h+1), back + backline, backline);
228 break;
229
230 case 3:
231 for (y=0; y<h; y++) {
232 memcpy(p, f, w);
233 p[-1] = p[w-1];
234 p[w] = p[0];
235 p += backline;
236 f += frontline;
237 }
238 memcpy(back, back + backline*h, backline);
239 memcpy(back + backline*(h+1), back + backline, backline);
240 break;
241
242 case 4:
243 for (y=0; y<h; y++) {
244 memcpy(p, f, w);
245 p[-1] = p[0];
246 p[w] = p[w-1];
247 p += backline;
248 f += frontline;
249 }
250 memcpy(back + (backline * (h + 1)), back + backline*h, backline);
251 memcpy(back, back + backline, backline);
252 break;
253
254 case 5:
255 { int left = (cam->x == 0) ? 1 : 0;
256 int right = (cam->x + cam->front->width == scam->w_width) ? 1 : 0;
257 int top = (cam->y == 0) ? 1 : 0;
258 int bottom = (cam->y + cam->front->height == scam->w_height) ? 1 : 0;
259
260 if (!left && !right && !top && !bottom) {
261 p = back;
262 f = front - 1 - frontline;
263 for (y=-1; y<=h; y++) {
264 memcpy(p, f, w + 2);
265 p += backline;
266 f += frontline;
267 }
268 } else {
269 p = back + backline + 1;
270 f = front;
271
272 p[-1 - backline] = f[left - 1 - (top ? 0 : frontline)];
273 memcpy(p - backline, f, w);
274 p[w - backline] = f[w - right - (top ? 0 : frontline)];
275
276 for (y=0; y<h; y++) {
277 p[-1] = f[left - 1];
278 memcpy(p, f, w);
279 p[w] = f[w - right];
280 p += backline;
281 f += frontline;
282 }
283 }
284 }
285 break;
286
287 }
288
289 cam_slide(scam, cam);
290
291 (*cam->neighborhood)(cam);
292 cam->phase = !cam->phase;
293
294 cam_update(scam, cam);
295
296 cam_adjust(scam, cam);
297 } /* for step */
298 }
299
300
301 cam_slide(SimCam *scam, Cam *cam)
302 {
303 int x = cam->x;
304 int y = cam->y;
305 int last_x = x;
306 int last_y = y;
307 int width = cam->width;
308 int height = cam->height;
309 int dx = cam->dx;
310 int dy = cam->dy;
311 int dragging = cam->dragging;
312 int bounce = 0;
313 int dagnabit = 0;
314
315 if (dragging ||
316 (cam->set_x >= 0) ||
317 (cam->set_y >= 0)) {
318 if (cam->set_x >= 0) {
319 x = cam->set_x;
320 cam->set_x = -1;
321 }
322 if (cam->set_y >= 0) {
323 y = cam->set_y;
324 cam->set_y = -1;
325 }
326 } else {
327 x += dx;
328 y += dy;
329 }
330
331 if (x < 0) {
332 x = 0;
333 if (!dragging) {
334 dx = ABS(dx);
335 bounce = 1;
336 }
337 } else if ((x + width) > scam->w_width) {
338 x = scam->w_width - width;
339 if (!dragging) {
340 dx = -ABS(dx);
341 bounce = 1;
342 }
343 }
344
345 if (y < 0) {
346 y = 0;
347 if (!dragging) {
348 dy = ABS(dy);
349 bounce = 1;
350 }
351 else {
352 dagnabit = 1;
353 printf("dagnabit\n");
354 }
355 } else if ((y + height) > scam->w_height) {
356 y = scam->w_height - height;
357 if (!dragging) {
358 dy = -ABS(dy);
359 bounce = 1;
360 }
361 }
362
363 if (dragging) {
364 dx = x - last_x;
365 dy = y - last_y;
366 } else {
367 if (bounce) {
368 cam->frob = (Rand16() & 15) * ((cam->frob > 0) ? -1 : 1);
369 }
370 }
371
372 cam->x = x;
373 cam->y = y;
374 cam->front->mem = (Byte *)scam->data + x + (scam->line_bytes * y);
375 cam->dx = dx + cam->gx;
376 cam->dy = dy + cam->gy;
377 if (dagnabit) {
378 printf("x %d y %d dx %d dy %d\n", cam->x, cam->y, cam->dx, cam->dy);
379 }
380 }
381
382
383 cam_update(SimCam *scam, Cam *cam)
384 {
385 if (scam->x->shared) {
386 XShmPutImage(scam->x->dpy, Tk_WindowId(scam->tkwin), scam->x->gc,
387 scam->image, cam->x, cam->y,
388 cam->x, cam->y, cam->width, cam->height,
389 False);
390 } else {
391 XPutImage(scam->x->dpy, Tk_WindowId(scam->tkwin), scam->x->gc,
392 scam->image, cam->x, cam->y,
393 cam->x, cam->y, cam->width, cam->height);
394 }
395 }
396
397
398 cam_adjust(SimCam *scam, Cam *cam)
399 {
400 int x0 = cam->set_x0;
401 int y0 = cam->set_y0;
402 int x1 = cam->set_x1;
403 int y1 = cam->set_y1;
404 int width = cam->set_width;
405 int height = cam->set_height;
406 int min_size = 8;
407 int tmp;
408
409 if ((x0 >= 0) ||
410 (y0 >= 0) ||
411 (x1 >= 0) ||
412 (y1 >= 0) ||
413 (width > 0) ||
414 (height > 0)) {
415 if (x0 < 0) x0 = cam->x;
416 if (y0 < 0) y0 = cam->y;
417 if (x1 < 0) x1 = cam->x + cam->ideal_width;
418 if (y1 < 0) y1 = cam->y + cam->ideal_height;
419 if (width > 0) x1 = x0 + width;
420 if (height > 0) y1 = y0 + height;
421
422 cam->set_width = cam->set_height =
423 cam->set_x0 = cam->set_y0 =
424 cam->set_x1 = cam->set_y1 = -1;
425
426 if (x0 > x1) {
427 tmp = x0; x0 = x1; x1 = tmp;
428 }
429
430 if (y0 > y1) {
431 tmp = y0; y0 = y1; y1 = tmp;
432 }
433
434 if (x0 < 0) x0 = 0;
435 if (y0 < 0) y0 = 0;
436 if (x0 > scam->w_width - min_size) x0 = scam->w_width - min_size;
437 if (y0 > scam->w_height - min_size) x0 = scam->w_height - min_size;
438 if (x1 < x0 + min_size) x1 = x0 + min_size;
439 if (y1 < y0 + min_size) y1 = y0 + min_size;
440 if (x1 > scam->w_width) x1 = scam->w_width;
441 if (y1 > scam->w_height) y1 = scam->w_height;
442
443 cam->x = x0;
444 cam->y = y0;
445 cam->ideal_width = x1 - x0;
446 cam->ideal_height = y1 - y0;
447 cam->width = cam->ideal_width & ~1;
448 cam->height = cam->ideal_height & ~1;
449 cam->front->mem = (Byte *)scam->data + x0 + (y0 * scam->line_bytes);
450 cam->front->width = cam->width;
451 cam->front->height = cam->height;
452 free(cam->back->mem);
453 cam->back->mem = (Byte *)malloc((cam->width + 2) * (cam->height + 2));
454 cam->back->width = cam->width + 2;
455 cam->back->height = cam->height + 2;
456 cam->back->line_bytes = cam->back->width;
457 }
458 }
459
460
461 void
462 n_moore_a(Cam *cam)
463 {
464 /* 0 1 2 3 4 5 6 7 8 9 */
465 /* c c' se sw ne nw e w s n */
466 /* 0x1 0x2 0x4 0x8 0x10 0x20 0x40 0x80 0x100 0x200 */
467
468 #define MOORE_A ( \
469 ((NORTHWEST&1)<<5) | ((NORTH&1)<<9) |((NORTHEAST&1)<<4) | \
470 ((WEST&1)<<7) | (CENTER&3) | ((EAST&1)<<6) | \
471 ((SOUTHWEST&1)<<3) | ((SOUTH&1)<<8) |((SOUTHEAST&1)<<2) \
472 )
473
474 CAM_TABLE_LOOP(MOORE_A)
475 }
476
477
478 void
479 n_moore_ab(Cam *cam)
480 {
481 /* 0 1 2 3 4 5 6 7 8 9 10 11 */
482 /* c c' se sw ne nw e w s n &c &c' */
483 /* 0x1 0x2 0x4 0x8 0x10 0x20 0x40 0x80 0x100 0x200 0x400 0x800 */
484
485 #define MOORE_AB (MOORE_A | ((CENTER&12)<<8))
486
487 CAM_TABLE_LOOP(MOORE_AB)
488 }
489
490
491 void
492 n_vonn_neumann(Cam *cam)
493 {
494 /* 0 1 2 3 4 5 6 7 8 9 */
495 /* c c' e' w' s' n' e w s n */
496 /* 0x1 0x2 0x4 0x8 0x10 0x20 0x40 0x80 0x100 0x200 */
497
498 #define VON_NEUMANN ( \
499 (CENTER&3) | \
500 ((EAST&1)<<6) | ((EAST&2)<<1) | \
501 ((WEST&1)<<7) | ((WEST&2)<<2) | \
502 ((SOUTH&1)<<8) | ((SOUTH&2)<<3) | \
503 ((NORTH&1)<<9) | ((NORTH&2)<<4) \
504 )
505
506 CAM_TABLE_LOOP(VON_NEUMANN)
507 }
508
509
510 void
511 n_margolis(Cam *cam)
512 {
513 register Byte i;
514
515 /* 0 1 2 3 4 5 6 7 8 9 */
516 /* c c' cw ccw opp cw' ccw' opp' */
517 /* 0x1 0x2 0x4 0x8 0x10 0x20 0x40 0x80 0x100 0x200 */
518
519 #define MARGOLIS_ODD ( \
520 (CENTER & 3) | \
521 (i=(x&1 ? (y&1 ? (EAST) : (NORTH)) \
522 : (y&1 ? (SOUTH) : (WEST))), \
523 (((i&1)<<2) | ((i&2)<<4))) | \
524 (i=(x&1 ? (y&1 ? (SOUTH) : (EAST)) \
525 : (y&1 ? (WEST) : (NORTH))), \
526 (((i&1)<<3) | ((i&2)<<5))) | \
527 (i=(x&1 ? (y&1 ? (SOUTHEAST):(NORTHEAST)) \
528 : (y&1 ? (SOUTHWEST):(NORTHWEST))), \
529 (((i&1)<<4) | ((i&2)<<6))) \
530 )
531
532 #define MARGOLIS_EVEN ( \
533 (CENTER & 3) | \
534 (i=(x&1 ? (y&1 ? (WEST) : (SOUTH)) \
535 : (y&1 ? (NORTH) : (EAST))), \
536 (((i&1)<<2) | ((i&2)<<4))) | \
537 (i=(x&1 ? (y&1 ? (NORTH) : (WEST)) \
538 : (y&1 ? (EAST) : (SOUTH))), \
539 (((i&1)<<3) | ((i&2)<<5))) | \
540 (i=(x&1 ? (y&1 ? (NORTHWEST) : (SOUTHWEST)) \
541 : (y&1 ? (NORTHEAST) : (SOUTHEAST))), \
542 (((i&1)<<4) | ((i&2)<<6))) \
543 )
544
545 if (cam->phase) {
546 CAM_TABLE_LOOP(MARGOLIS_ODD)
547 } else {
548 CAM_TABLE_LOOP(MARGOLIS_EVEN)
549 }
550 }
551
552
553 void
554 n_margolis_ph(Cam *cam)
555 {
556 register Byte i;
557
558 /* 0 1 2 3 4 5 6 7 8 9 */
559 /* c c' cw ccw opp cw' ccw' opp' pha pha' */
560 /* 0x1 0x2 0x4 0x8 0x10 0x20 0x40 0x80 0x100 0x200 */
561
562 #define MARGOLIS_ODD_PH (MARGOLIS_ODD | 0x100)
563 #define MARGOLIS_EVEN_PH (MARGOLIS_EVEN | 0x200)
564
565 if (cam->phase) {
566 CAM_TABLE_LOOP(MARGOLIS_ODD_PH)
567 } else {
568 CAM_TABLE_LOOP(MARGOLIS_EVEN_PH)
569 }
570 }
571
572
573 void
574 n_margolis_hv(Cam *cam)
575 {
576 register Byte i;
577
578 /* 0 1 2 3 4 5 6 7 8 9 */
579 /* c c' cw ccw opp cw' ccw' opp' horz vert */
580 /* 0x1 0x2 0x4 0x8 0x10 0x20 0x40 0x80 0x100 0x200 */
581
582 #define MARGOLIS_ODD_HV (MARGOLIS_ODD | ((x&1)<<8) | ((y&1)<<9))
583 #define MARGOLIS_EVEN_HV (MARGOLIS_EVEN | ((x&1)<<8) | ((y&1)<<9))
584
585 if (cam->phase) {
586 CAM_TABLE_LOOP(MARGOLIS_ODD_HV)
587 } else {
588 CAM_TABLE_LOOP(MARGOLIS_EVEN_HV)
589 }
590 }
591
592
593 void
594 n_life(Cam *cam)
595 {
596 int s;
597
598 #define LIFE ( \
599 ((CENTER&1) ? (((s = SUM8) == 2) || (s == 3)) \
600 : (SUM8 == 3)) | \
601 (CENTER<<1) \
602 )
603
604 CAM_LOOP(LIFE)
605 }
606
607
608 void
609 n_brain(Cam *cam)
610 {
611 int s;
612
613 #define BRAIN ( \
614 (((((s = CENTER)&3) == 0) && (SUM8 == 2)) ? 1 : 0) | \
615 (s<<1) \
616 )
617
618 CAM_LOOP(BRAIN)
619 }
620
621
622 void
623 n_heat(Cam *cam)
624 {
625 int frob = cam->frob;
626
627 #define HEAT ( \
628 ((QUAD)(NORTHWEST + NORTH + NORTHEAST + \
629 WEST + EAST + \
630 SOUTHWEST + SOUTH + SOUTHEAST + frob)) >> 3 \
631 )
632
633 CAM_LOOP(HEAT)
634 }
635
636
637 void
638 n_dheat(Cam *cam)
639 {
640 int frob = cam->frob;
641 int last = 0;
642
643 #define DHEAT \
644 last += NORTHWEST + NORTH + NORTHEAST + \
645 WEST + frob + EAST + \
646 SOUTHWEST + SOUTH + SOUTHEAST; \
647 *front = last >> 3; \
648 last &= 7;
649 CAM_LOOP_BODY(DHEAT)
650
651 }
652
653
654 void
655 n_lheat(Cam *cam)
656 {
657 int frob = cam->frob;
658
659 #define LHEAT ( \
660 ((QUAD)(NORTH + WEST + EAST + SOUTH + frob)) >> 2 \
661 )
662
663 CAM_LOOP(LHEAT)
664 }
665
666
667 void
668 n_ldheat(Cam *cam)
669 {
670 int frob = cam->frob;
671 int last; /* I meant to do that! */
672
673 #define LDHEAT ( \
674 ((last = (QUAD)(NORTH + WEST + EAST + SOUTH + frob \
675 + (last&0x03))), last >> 2) \
676 )
677
678 CAM_LOOP(LDHEAT)
679 }
680
681
682 void
683 n_abdheat(Cam *cam)
684 {
685 int frob = cam->frob;
686 int lasta = 0, lastb = 0; /* I meant to do that! */
687
688 #define YUM(x) (((QUAD)(x))&0x0f)
689 #define YUK(x) (((QUAD)(x))&0xf0)
690
691 #define ABDHEAT ( \
692 (lasta = (QUAD)(YUM(NORTHWEST) + YUM(NORTH) + YUM(NORTHEAST) + \
693 YUM(WEST) + YUM(EAST) + \
694 YUM(SOUTHWEST) + YUM(SOUTH) + YUM(SOUTHEAST) + \
695 frob + (lasta&0x07))), \
696 (lastb = (QUAD)(YUK(NORTHWEST) + YUK(NORTH) + YUK(NORTHEAST) + \
697 YUK(WEST) + YUK(EAST) + \
698 YUK(SOUTHWEST) + YUK(SOUTH) + YUK(SOUTHEAST) + \
699 (frob<<4) + (lastb&0x70))), \
700 (((lasta>>3)&0x0f) | ((lastb>>3)&0xf0)) \
701 )
702
703 CAM_LOOP(ABDHEAT)
704 }
705
706
707 void
708 n_abcdheat(Cam *cam)
709 {
710 int last;
711 int frob = cam->frob;
712
713 CAM_LOOP(HEAT)
714 }
715
716
717 void
718 n_edheat(Cam *cam)
719 {
720 int frob = cam->frob;
721 int last = 0;
722
723 #define EDHEAT ( \
724 (last = (QUAD)(YUM(NORTHWEST) + YUM(NORTH) + YUM(NORTHEAST) + \
725 YUM(WEST) + YUM(EAST) + \
726 YUM(SOUTHWEST) + YUM(SOUTH) + YUM(SOUTHEAST) + \
727 frob + (last&0x07))), \
728 (((last>>3)&0x0f) | ((CENTER<<4)&0xf0)) \
729 )
730
731 CAM_LOOP(EDHEAT)
732 }
733
734
735 int ranch(QUAD l0, QUAD l1, QUAD l2)
736 {
737 int s = SUM8;
738 int v = SUM9p(1);
739 int o = 0;
740
741 o = (CENTER&4)<<1;
742
743 if (v < 4 || v == 5) {
744 o |= 0x04;
745 } else {
746 }
747
748 return (o);
749 }
750
751
752 void
753 n_ranch(Cam *cam)
754 {
755 #define RANCH ranch(l0, l1, l2)
756
757 CAM_LOOP(RANCH)
758 }
759
760
761 void
762 n_anneal(Cam *cam)
763 {
764 int s;
765
766 #define ANNEAL ( \
767 ((s = SUM9) > 5) || (s == 4) \
768 )
769 CAM_LOOP(ANNEAL)
770 }
771
772
773 void
774 n_anneal4(Cam *cam)
775 {
776 int s;
777
778 #define ANNEAL4 ( \
779 ((((s = SUM9p(0)) > 5) || (s == 4)) ? 1 : 0) | \
780 ((((s = SUM9p(1)) > 5) || (s == 4)) ? 2 : 0) | \
781 ((((s = SUM9p(2)) > 5) || (s == 4)) ? 4 : 0) | \
782 ((((s = SUM9p(3)) > 5) || (s == 4)) ? 8 : 0) | \
783 (CENTER << 4) \
784 )
785 CAM_LOOP(ANNEAL4)
786 }
787
788
789 void
790 n_anneal8(Cam *cam)
791 {
792 int s;
793
794 #define ANNEAL8 ( \
795 ((((s = SUM9p(0)) > 5) || (s == 4)) ? 1 : 0) | \
796 ((((s = SUM9p(1)) > 5) || (s == 4)) ? 2 : 0) | \
797 ((((s = SUM9p(2)) > 5) || (s == 4)) ? 4 : 0) | \
798 ((((s = SUM9p(3)) > 5) || (s == 4)) ? 8 : 0) | \
799 ((((s = SUM9p(4)) > 5) || (s == 4)) ? 16 : 0) | \
800 ((((s = SUM9p(5)) > 5) || (s == 4)) ? 32 : 0) | \
801 ((((s = SUM9p(6)) > 5) || (s == 4)) ? 64 : 0) | \
802 ((((s = SUM9p(7)) > 5) || (s == 4)) ? 128 : 0) \
803 )
804 CAM_LOOP(ANNEAL8)
805 }
806
807
808 void
809 n_eco(Cam *cam)
810 {
811 int s;
812
813 #define ANTILIFE ( \
814 ((CENTER&1) ? (SUM8 != 5) \
815 : (((s = SUM8) != 5) && (s != 6))) | \
816 (CENTER<<1) \
817 )
818
819 #define ECO ( \
820 (((s = SUM9p(7)) > 5) || (s == 4) ? 128 : 0) | \
821 ((CENTER&128) ? ((ANTILIFE)&127) : ((BRAIN)&127)) \
822 )
823 CAM_LOOP(ECO)
824 }
825
826
827 void
828 n_torben(Cam *cam)
829 {
830 int s;
831
832 /* 0 0 0 1 0 1 0 1 1 1 */
833
834 #define TORBEN ( \
835 (CENTER << 1) | ((((s = SUM9) > 6) || (s == 5) || (s == 3)) ? 1 : 0) \
836 )
837 CAM_LOOP(TORBEN)
838 }
839
840
841 void
842 n_torben2(Cam *cam)
843 {
844 int s;
845
846
847 /* 0 0 0 1 0 1 0 1 1 1 */
848 /* 0 0 1 0 1 0 1 0 1 1 */
849 #define TORBEN2 ( \
850 TORBEN | (CENTER <<1) \
851 )
852 CAM_LOOP(TORBEN2)
853 }
854
855
856 void
857 n_torben3(Cam *cam)
858 {
859 int s;
860
861 /* 0 0 0 1 1 0 0 1 1 1 */
862
863 #define TORBEN3 ( \
864 ((s = SUM9) > 6) || (s == 3) || (s == 4) \
865 )
866 CAM_LOOP(TORBEN3)
867 }
868
869
870 void
871 n_torben4(Cam *cam)
872 {
873 int s;
874
875
876 /* 0 0 0 1 0 1 0 1 1 1 */
877 /* 0 0 1 0 1 0 1 0 1 1 */
878 #define TORBEN4 ( \
879 TORBEN3 | (CENTER <<1) \
880 )
881 CAM_LOOP(TORBEN4)
882 }
883
884
885 void
886 n_ball(Cam *cam)
887 {
888 char p = (cam->phase ? 1 : 0);
889 int x, y, r = Rand16();
890 int backline = cam->back->line_bytes,
891 frontline = cam->front->line_bytes;
892 Byte *back = cam->back->mem,
893 *front = cam->front->mem;
894
895 if (!p) {
896 back += 1 + backline;
897 }
898
899 for (y = p + (cam->height >>1); y > 0; y--) {
900 for (x = p + (cam->width >>1); x > 0; x--) {
901 Byte nw = back[0], ne = back[1],
902 sw = back[backline], se = back[backline+1];
903
904 r += nw + ne + sw + sw; r >>= 1;
905
906 switch ((nw&1) + (ne&1) + (sw&1) + (se&1)) {
907 case 0:
908 case 3:
909 case 4:
910 /* same */
911 back[0] = nw; back[1] = ne;
912 back[backline] = sw; back[backline+1] = se;
913 break;
914 case 1:
915 /* reflect */
916 back[0] = se; back[1] = sw;
917 back[backline] = ne; back[backline+1] = nw;
918 break;
919 case 2:
920 /* turn */
921 switch (((nw&1) <<3) | ((ne&1) <<2) | ((sw&1) <<1) | (se&1)) {
922 case 6:
923 case 9:
924 if (r&1) {
925 /* clockwise */
926 back[0] = sw; back[1] = nw;
927 back[backline] = se; back[backline+1] = ne;
928 } else {
929 /* counterclockwise */
930 back[0] = ne; back[1] = se;
931 back[backline] = nw; back[backline+1] = sw;
932 }
933 default:
934 back[0] = nw; back[1] = ne;
935 back[backline] = sw; back[backline+1] = se;
936 break;
937 }
938 break;
939 }
940
941 back += 2;
942 }
943 back += backline + backline - cam->width - (2*p);
944 }
945 back = cam->back->mem + backline + 1,
946 front = cam->front->mem;
947
948 for (y = cam->height; y > 0; y--) {
949 memcpy(front, back, cam->width);
950 back += backline;
951 front += frontline;
952 }
953 }
954
955
956 void
957 n_logic(Cam *cam)
958 {
959 char p = (cam->phase ? 1 : 0);
960 int x, y;
961 int backline = cam->back->line_bytes,
962 frontline = cam->front->line_bytes;
963 Byte tmp;
964 Byte *back = cam->back->mem,
965 *front = cam->front->mem;
966
967 /* bit 8 is center' */
968 /* bit 7 is center */
969
970 if (cam->phase) {
971 back += 1 + backline;
972 front += 1 + frontline;
973 }
974
975 for (y = cam->height >>1; y > 0; y--) {
976 for (x = cam->width >>1; x > 0; x--) {
977 Byte nw = back[0], ne = back[1],
978 sw = back[backline], se = back[backline+1];
979
980 switch (((nw&128) >>4) | ((ne&128) >>5) |
981 ((sw&128) >>6) | ((se&128) >>7)) {
982 case 0:
983 break;
984
985 case 1:
986 break;
987
988 case 2:
989 break;
990
991 case 3:
992 break;
993
994 case 4:
995 break;
996
997 case 5:
998 break;
999
1000 case 6:
1001 break;
1002
1003 case 7:
1004 break;
1005
1006 case 8:
1007 break;
1008
1009 case 9:
1010 break;
1011
1012 case 10:
1013 break;
1014
1015 case 11:
1016 break;
1017
1018 case 12:
1019 break;
1020
1021 case 13:
1022 break;
1023
1024 case 14:
1025 break;
1026
1027 case 15:
1028 tmp = nw; nw = se; se = tmp;
1029 tmp = sw; ne = sw; sw = tmp;
1030 break;
1031
1032 }
1033
1034 back += 2; front += 2;
1035 }
1036 back += backline + backline - cam->width;
1037 front += frontline + frontline - cam->width;
1038 }
1039
1040 back = cam->back->mem + backline + 1,
1041 front = cam->front->mem;
1042
1043 for (y = cam->height; y > 0; y--) {
1044 memcpy(front, back, cam->width);
1045 back += backline;
1046 front += frontline;
1047 }
1048 }
1049
1050
1051 void
1052 n_party(Cam *cam)
1053 {
1054 #define PARTY (CENTER ^ NORTH ^ SOUTH ^ EAST ^ WEST)
1055 CAM_LOOP(PARTY)
1056 }
1057
1058
1059 vf neighborhoods[] = {
1060 /* 0 1 2 3 */
1061 &n_moore_a, &n_moore_a, &n_moore_ab, &n_vonn_neumann,
1062 /* 4 5 6 */
1063 &n_margolis, &n_margolis_ph, &n_margolis_hv,
1064 /* 7 8 9 10 11 12 */
1065 &n_life, &n_brain, &n_heat, &n_dheat, &n_lheat, &n_ldheat,
1066 /* 13 14 15 16 17 */
1067 &n_ranch, &n_anneal, &n_anneal4, &n_anneal8, &n_eco,
1068 /* 18 19 20 21 22 */
1069 &n_abdheat, &n_edheat, &n_abcdheat, &n_torben, &n_torben2,
1070 /* 23 24 25 26 27 */
1071 &n_torben3, &n_torben4, &n_ball, &n_logic, &n_party
1072 };
1073
1074
1075 cam_set_neighborhood(Cam *cam, int code)
1076 {
1077 cam->neighborhood = neighborhoods[code];
1078 }
1079
1080
1081 cam_load_rule(Cam *cam, char *filename)
1082 {
1083 FILE *fp;
1084 QUAD magic, neighborhood, rule_size;
1085 Byte *rule;
1086 int test = 1;
1087
1088 if ((fp = fopen(filename, "r")) == NULL) {
1089 fprintf(stderr, "cam: Can't open rule file \"%s\"\n", filename);
1090 return;
1091 }
1092
1093
1094 #define SWAPQUAD(x) ((x = ((x <<24) & 0xff000000) | \
1095 ((x <<8) & 0x00ff0000) | \
1096 ((x >>8) & 0x0000ff00) | \
1097 ((x >>24) & 0x000000ff)), 0)
1098
1099 /* XXX: Make this byte order independent!!! */
1100 if ((*(unsigned char*) (&test))) {
1101 if ((fread(&magic, 1, sizeof(QUAD), fp) != sizeof(QUAD)) ||
1102 SWAPQUAD(magic) ||
1103 (magic != 0xcac0cac0) ||
1104 (fread(&neighborhood, 1, sizeof(QUAD), fp) != sizeof(QUAD)) ||
1105 SWAPQUAD(neighborhood) ||
1106 (fread(&rule_size, 1, sizeof(QUAD), fp) != sizeof(QUAD)) ||
1107 SWAPQUAD(rule_size) ||
1108 ((rule = (Byte *)malloc(rule_size)) == NULL) ||
1109 (fread(rule, 1, rule_size, fp) != rule_size)) {
1110 fprintf(stderr, "cam: Bad rule file \"%s\"\n", filename);
1111 fclose(fp);
1112 return;
1113 }
1114 } else {
1115 if ((fread(&magic, 1, sizeof(QUAD), fp) != sizeof(QUAD)) ||
1116 (magic != 0xcac0cac0) ||
1117 (fread(&neighborhood, 1, sizeof(QUAD), fp) != sizeof(QUAD)) ||
1118 (fread(&rule_size, 1, sizeof(QUAD), fp) != sizeof(QUAD)) ||
1119 ((rule = (Byte *)malloc(rule_size)) == NULL) ||
1120 (fread(rule, 1, rule_size, fp) != rule_size)) {
1121 fprintf(stderr, "cam: Bad rule file \"%s\"\n", filename);
1122 fclose(fp);
1123 return;
1124 }
1125 }
1126
1127 fclose(fp);
1128 if (cam->rule != NULL)
1129 free(cam->rule);
1130 cam->rule = rule;
1131 cam->rule_size = rule_size;
1132 cam_set_neighborhood(cam, neighborhood);
1133 }
1134
1135
1136 Cam *
1137 find_cam(SimCam *scam, int x, int y)
1138 {
1139 Cam *cam;
1140
1141 for (cam = scam->cam_list; cam != NULL; cam = cam->next) {
1142 if ((x >= cam->x) &&
1143 (y >= cam->y) &&
1144 (x < cam->x + cam->width) &&
1145 (y < cam->y + cam->height)) {
1146 break;
1147 }
1148 }
1149
1150 return cam;
1151 }
1152
1153
1154 Cam *
1155 find_cam_by_name(SimCam *scam, char *name)
1156 {
1157 Cam *cam;
1158
1159 for (cam = scam->cam_list; cam != NULL; cam = cam->next) {
1160 if ((cam->name != NULL) &&
1161 (strcmp(name, cam->name) == 0)) {
1162 return cam;
1163 }
1164 }
1165
1166 return NULL;
1167 }
1168
1169
1170 Cam *
1171 get_cam_number(SimCam *scam, int i)
1172 {
1173 Cam *cam;
1174
1175 for (cam = scam->cam_list;
1176 (i != 0) && (cam != NULL);
1177 (i--), (cam = cam->next)) ;
1178
1179 return cam;
1180 }
1181
1182
1183 cam_layout(SimCam *scam)
1184 {
1185 int x, y, gap, border, maxwidth, lastmax;
1186 Cam *cam;
1187
1188 border = 8;
1189 gap = 8;
1190 x = border; y = border;
1191 maxwidth = lastmax = gap;
1192
1193 for (cam = scam->cam_list; cam != NULL; cam = cam->next) {
1194 cam->dx = 0; cam->dy = 0;
1195 if (cam->width > maxwidth) {
1196 lastmax = maxwidth;
1197 maxwidth = cam->width;
1198 }
1199 if (y + cam->height + border > scam->w_height) {
1200 y = border; x = x + maxwidth + gap;
1201 maxwidth = lastmax = gap;
1202 }
1203 if ((x + cam->width > scam->w_width) ||
1204 (y + cam->height > scam->w_height)) {
1205 cam->x = 0; cam->y = 0;
1206 cam->front->mem = (Byte *)scam->data;
1207 maxwidth = lastmax;
1208 } else {
1209 cam->x = x; cam->y = y;
1210 cam->front->mem =
1211 scam->data + x + (scam->line_bytes * y);
1212 y = y + cam->height + gap;
1213 }
1214 }
1215 }
1216
1217
1218 init_scam(SimCam *scam)
1219 {
1220 scam_randomize(scam);
1221 }
1222
1223
1224 handle_scam(SimCam *scam)
1225 {
1226 Cam *cam;
1227
1228 for (cam = scam->cam_list; cam != NULL; cam = cam->next) {
1229 cam_do_rule(scam, cam);
1230 }
1231 }
1232
1233
1234 #endif /* CAM */
Impressum, Datenschutz