|
|
1.1 root 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 [email protected].
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:
1087: if ((fp = fopen(filename, "r")) == NULL) {
1088: fprintf(stderr, "cam: Can't open rule file \"%s\"\n", filename);
1089: return;
1090: }
1091:
1092: /* XXX: Make this byte order independent!!! */
1093:
1094: #if defined(MSDOS) || defined(OSF1) || defined(IS_INTEL)
1095:
1096: #define SWAPQUAD(x) ((x = ((x <<24) & 0xff000000) | \
1097: ((x <<8) & 0x00ff0000) | \
1098: ((x >>8) & 0x0000ff00) | \
1099: ((x >>24) & 0x000000ff)), 0)
1100:
1101: #else
1102:
1103: #define SWAPQUAD(x) 0
1104:
1105: #endif
1106:
1107: if ((fread(&magic, 1, sizeof(QUAD), fp) != sizeof(QUAD)) ||
1108: SWAPQUAD(magic) ||
1109: (magic != 0xcac0cac0) ||
1110: (fread(&neighborhood, 1, sizeof(QUAD), fp) != sizeof(QUAD)) ||
1111: SWAPQUAD(neighborhood) ||
1112: (fread(&rule_size, 1, sizeof(QUAD), fp) != sizeof(QUAD)) ||
1113: SWAPQUAD(rule_size) ||
1114: ((rule = (Byte *)malloc(rule_size)) == NULL) ||
1115: (fread(rule, 1, rule_size, fp) != rule_size)) {
1116: fprintf(stderr, "cam: Bad rule file \"%s\"\n", filename);
1117: fclose(fp);
1118: return;
1119: }
1120:
1121: fclose(fp);
1122: if (cam->rule != NULL)
1123: free(cam->rule);
1124: cam->rule = rule;
1125: cam->rule_size = rule_size;
1126: cam_set_neighborhood(cam, neighborhood);
1127: }
1128:
1129:
1130: Cam *
1131: find_cam(SimCam *scam, int x, int y)
1132: {
1133: Cam *cam;
1134:
1135: for (cam = scam->cam_list; cam != NULL; cam = cam->next) {
1136: if ((x >= cam->x) &&
1137: (y >= cam->y) &&
1138: (x < cam->x + cam->width) &&
1139: (y < cam->y + cam->height)) {
1140: break;
1141: }
1142: }
1143:
1144: return cam;
1145: }
1146:
1147:
1148: Cam *
1149: find_cam_by_name(SimCam *scam, char *name)
1150: {
1151: Cam *cam;
1152:
1153: for (cam = scam->cam_list; cam != NULL; cam = cam->next) {
1154: if ((cam->name != NULL) &&
1155: (strcmp(name, cam->name) == 0)) {
1156: return cam;
1157: }
1158: }
1159:
1160: return NULL;
1161: }
1162:
1163:
1164: Cam *
1165: get_cam_number(SimCam *scam, int i)
1166: {
1167: Cam *cam;
1168:
1169: for (cam = scam->cam_list;
1170: (i != 0) && (cam != NULL);
1171: (i--), (cam = cam->next)) ;
1172:
1173: return cam;
1174: }
1175:
1176:
1177: cam_layout(SimCam *scam)
1178: {
1179: int x, y, gap, border, maxwidth, lastmax;
1180: Cam *cam;
1181:
1182: border = 8;
1183: gap = 8;
1184: x = border; y = border;
1185: maxwidth = lastmax = gap;
1186:
1187: for (cam = scam->cam_list; cam != NULL; cam = cam->next) {
1188: cam->dx = 0; cam->dy = 0;
1189: if (cam->width > maxwidth) {
1190: lastmax = maxwidth;
1191: maxwidth = cam->width;
1192: }
1193: if (y + cam->height + border > scam->w_height) {
1194: y = border; x = x + maxwidth + gap;
1195: maxwidth = lastmax = gap;
1196: }
1197: if ((x + cam->width > scam->w_width) ||
1198: (y + cam->height > scam->w_height)) {
1199: cam->x = 0; cam->y = 0;
1200: cam->front->mem = (Byte *)scam->data;
1201: maxwidth = lastmax;
1202: } else {
1203: cam->x = x; cam->y = y;
1204: cam->front->mem =
1205: scam->data + x + (scam->line_bytes * y);
1206: y = y + cam->height + gap;
1207: }
1208: }
1209: }
1210:
1211:
1212: init_scam(SimCam *scam)
1213: {
1214: scam_randomize(scam);
1215: }
1216:
1217:
1218: handle_scam(SimCam *scam)
1219: {
1220: Cam *cam;
1221:
1222: for (cam = scam->cam_list; cam != NULL; cam = cam->next) {
1223: cam_do_rule(scam, cam);
1224: }
1225: }
1226:
1227:
1228: #endif /* CAM */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.