|
|
1.1 root 1: /*
2: * pacman
3: * dal 1982
4: * steve 1/24/90 added ndelay for reasonable slowness on AT
5: * steve 10/4/90 kludged to make speed setting slightly more cogent
6: * steve 10/9/90 made arrow keys work
7: * steve 10/10/90 added -c option to work on video cards
8: * steve 6/10/92 added #if _I386 conditionalization for COH386;
9: * cleaned up a few of the more offensive pointer/int fubars of dal.
10: * The i386 version must be setuid sys, so it can read /dev/mem.
11: */
12:
13: #include "term.c"
14: #include "io.c"
15:
16: #if _I386
17: #define SCRBASE_M 0xB0000 /* monochrome screen base address */
18: #define SCRBASE_C 0xB8000 /* color board screen base address */
19: #else
20: #define SCRBASE_M 0xB000 /* monochrome screen base segment */
21: #define SCRBASE_C 0xB800 /* color board screen base segment */
22: #endif
23:
24: #define rand() ((rn+=rn+((((rn<<0^rn<<1^rn<<8^rn<<9)>>15)^1)&1))&1)
25: int rn;
26: #define track() (board>1)
27: #define nprox() (board>2? (board-3)/2+5 : 0)
28: #define F_VERT 22
29: #define F_HORZ 63
30: #define F_HHID 2
31: #define F_HOFF ((80-F_HORZ)/2)
32: #define F_VOFF ((24-F_VERT)/2)
33: #define S_BP 10000
34: #define S_PN 3
35: #define S_GH 200
36: #define S_FD 10
37: #define S_EN 50
38: /*
39: #define S_FR (board<5? (board-1)*200+100 : (board-4)*1000)
40: */
41: #define S_FR ((board-1)*200+100)
42: #define F_GH 0
43: #define F_PC 4
44: #define F_FR 5
45: #define F_BN 6
46: #define F_FD 7
47: #define F_EN 8
48: #define F_DR 9
49: #define F_TN 10
50: #define F_WL 11
51: #define F_BC 12
52: #define F_BMSK ((1<<F_BC)-1)
53: #define F_GMSK (((1<<F_GH+4)-1)&~((1<<F_GH+0)-1))
54: #define G_ETIM 24
55: #define G_BTIM 8
56: #define G_TMQN 8
57: #define G_TOFF(n) (5+(n)*G_TMQN)
58: enum {G_ERAS, G_WRIT, G_MOVE, G_BLUE, G_INIT};
59: #define E_TMQN 16
60: #define E_TOFF 1
61: #define P_TMQN (9*(2-P_HALF))
62: #define P_TOFF 0
63: enum {P_ERAS, P_WRIT, P_MOVE, P_UPDI, P_INIT};
64: #define axis(v) ((v)&1)
65: #define incr(v) (1-((v)&2))
66: #define hm(v) (axis(v)==0)
67: #define vm(v) (axis(v)!=0)
68: #define om(v) ((v)^2)
69:
70: int ndelay = 10;
71: int limit[2] = {F_HORZ-2, F_VERT-1};
72: int edibles;
73: int pacmen = S_PN+1;
74: int stop;
75: int e_s;
76: long score;
77: long bonus;
78: int board = 1;
79: int p_p[3];
80: int p_h[2];
81: int p_l;
82: int p_m;
83: int p_d;
84: int p_i[3];
85: unsigned p_n;
86: unsigned e_n;
87: int e_k;
88: int energ[4][2];
89: int r_s;
90: int r_t[2];
91: int r_d;
92: int r_p[2];
93: int g_g[2][2];
94: int g_v[4];
95: struct ghost {
96: int g_p[3];
97: int g_q[3];
98: int g_h[3];
99: int g_s;
100: int g_d;
101: int g_e;
102: int g_f;
103: int g_r;
104: int g_o;
105: unsigned g_n;
106: } ghost[4];
107:
108: #define D (1<<F_DR)
109: #define E (1<<F_EN)
110: #define F (1<<F_FD)
111: #define G (1<<F_GH)
112: #define P (1<<F_PC)
113: #define R (1<<F_FR)
114: #define T (1<<F_TN)
115: #define W (1<<F_WL)
116: int field[F_VERT][F_HORZ] = {
117: {W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W},
118: {W,W,W,W,W,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,W,W},
119: {W,W,W,W,W,0,F,0,W,W,W,W,W,W,W,0,F,0,W,W,W,W,W,W,W,W,W,0,F,0,W,W},
120: {W,W,W,W,W,0,E,0,W,W,W,W,W,W,W,0,F,0,W,W,W,W,W,W,W,W,W,0,F,0,W,W},
121: {W,W,W,W,W,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0},
122: {W,W,W,W,W,0,F,0,W,W,W,W,W,W,W,0,F,0,W,W,W,0,F,0,W,W,W,W,W,W,W,W},
123: {W,W,W,W,W,0,F,0,F,0,F,0,F,0,F,0,F,0,W,W,W,0,F,0,F,0,F,0,F,0,W,W},
124: {W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,0,F,0,W,W,W,W,W,W,W,W,W,0,0,0,W,W},
125: {W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,0,F,0,W,W,W,0,0,0,0,0,0,0,0,0,0,G},
126: {W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,0,F,0,W,W,W,0,0,0,W,W,W,W,W,W,D,D},
127: {T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,0,F,0,0,0,0,0,0,0,W,W,W,0,G,0,0,G},
128: {W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,0,F,0,W,W,W,0,0,0,W,W,W,W,W,W,W,W},
129: {W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,0,F,0,W,W,W,0,0,0,0,0,0,0,0,0,0,R},
130: {W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,0,F,0,W,W,W,0,0,0,W,W,W,W,W,W,W,W},
131: {W,W,W,W,W,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,W,W},
132: {W,W,W,W,W,0,F,0,W,W,W,W,W,W,W,0,F,0,W,W,W,W,W,W,W,W,W,0,F,0,W,W},
133: {W,W,W,W,W,0,E,0,F,0,F,0,W,W,W,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,0,P},
134: {W,W,W,W,W,W,W,W,W,0,F,0,W,W,W,0,F,0,W,W,W,0,F,0,W,W,W,W,W,W,W,W},
135: {W,W,W,W,W,0,F,0,F,0,F,0,F,0,F,0,F,0,W,W,W,0,F,0,F,0,F,0,F,0,W,W},
136: {W,W,W,W,W,0,F,0,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,0,F,0,W,W},
137: {W,W,W,W,W,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0,F,0},
138: {W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W}
139: };
140: #undef D
141: #undef E
142: #undef F
143: #undef G
144: #undef P
145: #undef R
146: #undef T
147: #undef W
148:
149: int cn[3];
150: unsigned scrbase = SCRBASE_M; /* monochrome screen by default */
151:
152: nc(x, y, z)
153: {
154: cn[0]=(x);
155: cn[1]=(y);
156: cn[2]=(z);
157: mc(cn);
158: return (field[cn[1]][cn[0]]);
159: }
160:
161: mc(p)
162: register *p;
163: {
164: register a, i;
165:
166: a = axis(p[2]);
167: i = incr(p[2]);
168: if ((unsigned)(p[a]+=i) > limit[a])
169: p[a] -= i*(limit[a]+1);
170: }
171:
172:
173: main(argc, argv) int argc; char *argv[];
174: {
175: char c;
176:
177: if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'c') {
178: --argc;
179: ++argv;
180: scrbase = SCRBASE_C; /* color screen if -c */
181: }
182: if (argc > 1)
183: ndelay = atoi(argv[1]);
184: setup();
185: map();
186: loop:
187: cls();
188: if (argc == 1) {
189: atrb(s_a);
190: curs(1, 0);
191: bufstr("Speed [default ");
192: dprint((long)ndelay);
193: bufstr("]? ");
194: bflush();
195: inputecho(&c);
196: if (c == '\n')
197: ; /* take old ndelay, initially 10 */
198: else if (c < '0' || c > '9')
199: goto loop; /* bogus nachos */
200: else /* input ndelay char by char, ugh */
201: for (ndelay = 0; c >= '0' && c <= '9'; inputecho(&c)) {
202: ndelay *= 10;
203: ndelay += c - '0';
204: }
205: if (c != '\n')
206: goto loop; /* bogus terminator */
207: curs(1, 0);
208: bufstr(" ");
209: bflush();
210: }
211: score = 0;
212: bonus = S_BP;
213: curs(1, 0);
214: bufstr(" ");
215: while (play())
216: ++board;
217: for (;;) {
218: cls();
219: atrb(s_a);
220: curs(1, 0);
221: bufstr("Your score was ");
222: dprint(score);
223: bufstr(" on level ");
224: bufchr(board + 'A' - 1);
225: bufstr(" at speed ");
226: dprint((long)ndelay);
227: bufchr('.');
228: curs(2, 0);
229: bufstr("Do you want to play again [y or n]? ");
230: bflush();
231: c = 0;
232: inputecho(&c);
233: switch (c) {
234: case 'Y':
235: case 'y':
236: case '\n':
237: board = 1;
238: edibles = 0;
239: pacmen = S_PN+1;
240: goto loop;
241: case 'Q':
242: case 'q':
243: case 'N':
244: case 'n':
245: reset();
246: exit(0);
247: }
248: }
249: }
250:
251: play()
252: {
253: register i, j;
254: register *f;
255: register k;
256:
257: while (pacmen) {
258: e_n = E_TOFF;
259: e_k = 0;
260: r_c[1] = board-1+'A';
261: if (edibles == 0) {
262: f = field;
263: for (j=0; j<F_VERT; ++j)
264: for (i=0; i<F_HORZ; ++i)
265: if ((*f++&=~(1<<F_BN|1<<F_PC|F_GMSK))
266: & (1<<F_FD|1<<F_EN))
267: ++edibles;
268: plot(0, 0, F_HORZ, F_VERT);
269: if (score == 0) {
270: pleft();
271: --pacmen;
272: r_d = edibles/2;
273: i = rand();
274: r_t[0] = (1+0)*edibles/(2+i);
275: i = rand();
276: r_t[1] = (2+i)*edibles/(3+i);
277: curs(1, 0);
278: atrb(s_a);
279: bufchr('0');
280: }
281: }
282: pacman(P_INIT, 0);
283: pacman(P_UPDI, 0);
284: ghosts(G_INIT, 0, F_GMSK);
285: ghosts(G_WRIT, 1, F_GMSK);
286: curs(2, 0);
287: atrb(r_c[0]);
288: bufchr(r_c[1]);
289: curs(p_h[1]+F_VOFF, p_h[0]-4+F_HOFF);
290: atrb(s_a);
291: bufstr("GET READY");
292: delay(10);
293: pleft();
294: delay(5);
295: plot(p_p[0]-4, p_p[1], 9, 1);
296: pacman(P_WRIT, 1);
297: animate();
298: if (stop) {
299: if (r_s) {
300: r_s = 0;
301: plot(r_p[0], r_p[1], 1, 1);
302: }
303: k = 0;
304: while ((stop&1<<k+F_GH) == 0)
305: ++k;
306: f = &ghost[k].g_q[2];
307: ghosts(G_ERAS, 1, ~stop&F_GMSK);
308: beep();
309: for (i=0; i<12; ++i) {
310: *f ^= 2;
311: ghosts(G_WRIT, 1, stop);
312: delay(1);
313: ghosts(G_ERAS, 1, stop);
314: }
315: for (i=0; i<12; ++i) {
316: p_p[2] += (p_d)? -1: 1;
317: p_p[2] &= 3;
318: pacman(P_WRIT, 1);
319: delay(1);
320: pacman(P_ERAS, 1);
321: }
322: --pacmen;
323: } else
324: return (1);
325: }
326: return (0);
327: }
328:
329: map()
330: {
331: register x, y, z;
332: register e, g;
333: register *f;
334:
335: e = 0;
336: g = 0;
337: f = field;
338: for (y=0; y<F_VERT; ++y)
339: for (x=0; x<=F_HORZ/2; ++x)
340: field[y][F_HORZ-x-1] = field[y][x];
341: for (y=0; y<F_VERT; ++y)
342: for (x=0; x<F_HORZ; ++f, ++x) {
343: if (*f & (1<<F_EN)) {
344: energ[e][0] = x;
345: energ[e][1] = y;
346: ++e;
347: } else if (*f & (1<<F_GH)) {
348: ghost[g].g_h[0] = x;
349: ghost[g].g_h[1] = y;
350: *f &= ~(1<<F_GH);
351: if ((g++&1) == 0) {
352: g_g[g/2][0] = x;
353: g_g[g/2][1] = y;
354: }
355: } else if (*f & (1<<F_PC)) {
356: p_h[0] = x;
357: p_h[1] = y;
358: *f &= ~(1<<F_PC);
359: } else if (*f & (1<<F_FR)) {
360: r_p[0] = x;
361: r_p[1] = y;
362: }
363: for (z=0; z<4; ++z)
364: if (nc(x, y, z) & 1<<F_WL)
365: *f |= 1<<F_WL+z+1;
366: }
367: }
368:
369:
370: animate()
371: {
372: register i, c;
373: register unsigned clock;
374: register struct ghost *g;
375: register *p;
376: char key = '\0';
377: long oscore;
378: int gscore;
379:
380: oscore = score;
381: e_s = 0;
382: stop = 0;
383: for (clock=0; !stop && edibles; ++clock) {
384: i = 0;
385: if (input(&key) || p_n==clock) switch (key) {
386: case KEY_N:
387: ++i;
388: case KEY_W:
389: ++i;
390: case KEY_S:
391: ++i;
392: case KEY_E:
393: if (vm(i) && hm(p_p[2])) {
394: c = nc(p_p[0], p_p[1], i);
395: if (c & (1<<F_DR|1<<F_WL|1<<F_WL+p_p[2]+1))
396: break;
397: if (c & 1<<F_WL+om(p_p[2])+1)
398: mc(p_p);
399: } else if (hm(i) && vm(p_p[2])) {
400: if (nc(p_p[0]+incr(i), p_p[1]+p_l, i) & 1<<F_WL)
401: break;
402: p_p[1] += p_l;
403: p_l = 0;
404: } else if (p_p[2] == i) {
405: if (p_m) {
406: key = '\0';
407: break;
408: }
409: } else if (vm(i) && p_l) {
410: p_p[1] += p_l;
411: p_l = -p_l;
412: }
413: p_p[2] = i;
414: p_m = 1;
415: p_n = clock;
416: key = '\0';
417: break;
418: case KEY_C:
419: p_m = 0;
420: key = '\0';
421: break;
422: }
423: if (p_n == clock) {
424: if (ndelay)
425: delay(1);
426: pacman(P_ERAS, 1);
427: pacman(P_MOVE, 0);
428: pacman(P_UPDI, 0);
429: p_d ^= 1;
430: pacman(P_WRIT, 1);
431: p = &field[p_p[1]+p_l][p_p[0]];
432: for (i=-1; i<2; ++i) {
433: if (r_s && (p[i]&1<<F_FR)) {
434: score += S_FR;
435: r_s = 0;
436: atrb(s_a);
437: curs(r_p[1]+F_VOFF, r_p[0]+F_HOFF);
438: c = dprint((long)S_FR);
439: delay(5);
440: plot(r_p[0], r_p[1], c, 1);
441: continue;
442: }
443: if ((c=p[i]) & 1<<F_BN)
444: continue;
445: p[i] = c | 1<<F_BN;
446: if (c & 1<<F_FD) {
447: score += S_FD;
448: } else if (c & 1<<F_EN) {
449: ghosts(G_BLUE, 1, F_GMSK);
450: gscore = S_GH;
451: score += S_EN;
452: } else
453: continue;
454: --edibles;
455: if (edibles==r_t[0] || edibles==r_t[1]) {
456: r_s = r_d;
457: plot(r_p[0], r_p[1], 1, 1);
458: }
459: }
460: if (r_s && --r_s==0)
461: plot(r_p[0], r_p[1], 1, 1);
462: if (e_s) for (g=ghost,i=1<<F_GH; i&F_GMSK; i<<=1,++g) {
463: if (g->g_s!=1 || contact(g->g_p, 3)==0)
464: continue;
465: curs(g->g_p[1]+F_VOFF, g->g_p[0]-1+F_HOFF);
466: beep();
467: atrb(s_a);
468: c = dprint((long)gscore);
469: delay(5);
470: atrb(0);
471: curs(g->g_p[1]+F_VOFF, g->g_p[0]-1+F_HOFF);
472: while (c--)
473: bufchr(' ');
474: g->g_s = 2;
475: g->g_e = 0;
476: plot(g->g_p[0]-1, g->g_p[1], 4, 1);
477: score += gscore;
478: gscore *= 2;
479: }
480: }
481: for (g=ghost,i=1<<F_GH; i&F_GMSK; i<<=1,++g) {
482: if (g->g_n != clock)
483: continue;
484: ghosts(G_ERAS, 1, i);
485: ghosts(G_MOVE, 0, i);
486: ghosts(G_WRIT, 1, i);
487: }
488: if (e_n == clock) {
489: ++e_k;
490: p = energ[(e_k&=7)&3];
491: plot(p[0], p[1], 1, 1);
492: e_n += E_TMQN;
493: }
494: if (score != oscore) {
495: curs(1, 0);
496: atrb(s_a);
497: dprint(score);
498: if (score>=bonus && oscore<bonus) {
499: bonus += S_BP;
500: if (pacmen < S_PN+1) {
501: beep();
502: ++pacmen;
503: pleft();
504: }
505: }
506: oscore = score;
507: }
508: bflush();
509: }
510: }
511:
512: dprint(l)
513: long l;
514: {
515: register c, d = 1, e = 0;
516: static long mag[] = {1, 10, 100, 1000, 10000, 100000};
517:
518: while (mag[d] <= l)
519: ++d;
520: while (d--) {
521: for (c=0; l>=mag[d]; ++c)
522: l -= mag[d];
523: bufchr(c+'0');
524: ++e;
525: }
526: return (e);
527: }
528:
529: pleft()
530: {
531: register i, j;
532: register char *c;
533:
534: for (i=0; i<S_PN+1; ++i) {
535: curs(22-2*i, 0);
536: c = p_cc[pacmen>i+1? 0 : 1];
537: for (j=0; j<3; ++j) {
538: atrb(*c++);
539: bufchr(*c++);
540: }
541: }
542: }
543:
544: pacman(s, p)
545: {
546: register i;
547: register *f;
548:
549: switch (s) {
550: case P_ERAS:
551: for (i=0; i<p_i[2]; ++i) {
552: f = &field[p_i[1]+i][p_i[0]];
553: *f++ &= ~(1<<F_PC);
554: *f++ &= ~(1<<F_PC);
555: *f &= ~(1<<F_PC);
556: }
557: plot(p_i[0], p_i[1], 3, p_i[2]);
558: break;
559: case P_WRIT:
560: for (i=0; i<p_i[2]; ++i) {
561: f = &field[p_i[1]+i][p_i[0]];
562: *f++ |= (1<<F_PC);
563: *f++ |= (1<<F_PC);
564: *f |= (1<<F_PC);
565: }
566: break;
567: case P_MOVE:
568: p_n += (P_TMQN*2-p_n%(P_TMQN*2)+P_TOFF);
569: if (p_m) {
570: i = nc(p_p[0], p_p[1], p_p[2]);
571: if (vm(p_p[2]))
572: if (p_l) {
573: p_p[1] += p_l;
574: p_l = 0;
575: } else if (i & (1<<F_WL|1<<F_DR))
576: p_m = 0;
577: else if (P_HALF)
578: p_l = incr(p_p[2]);
579: else
580: p_p[1] += incr(p_p[2]);
581: else if (i & 1<<F_WL+p_p[2]+1)
582: p_m = 0;
583: else {
584: mc(p_p);
585: if (!P_HALF && (p_p[0]&1))
586: mc(p_p);
587: }
588: }
589: break;
590: case P_UPDI:
591: p_i[0] = p_p[0]-1;
592: p_i[1] = p_p[1]+(p_l>>1);
593: p_i[2] = 1+(p_l&1);
594: break;
595: case P_INIT:
596: p_p[0] = p_h[0];
597: p_p[1] = p_h[1];
598: p_p[2] = 1;
599: p_l = 0;
600: p_m = 0;
601: p_d = 0;
602: p_n = P_TOFF;
603: break;
604: }
605: if (p)
606: plot(p_i[0], p_i[1], 3, p_i[2]);
607: }
608:
609: ghosts(s, p, m)
610: {
611: register struct ghost *g;
612: register *f;
613: register i;
614:
615: for (g=ghost,i=1<<F_GH; i&F_GMSK; i<<=1,++g) {
616: if ((m&i) == 0)
617: continue;
618: switch (s) {
619: case G_ERAS:
620: f = &field[g->g_p[1]][g->g_p[0]];
621: *f &= ~i;
622: *(f-1) &= ~i;
623: *(f+1) &= ~i;
624: break;
625: case G_WRIT:
626: f = &field[g->g_p[1]][g->g_p[0]];
627: *f |= i;
628: *(f-1) |= i;
629: *(f+1) |= i;
630: break;
631: case G_MOVE:
632: g->g_p[0] = g->g_q[0];
633: g->g_p[1] = g->g_q[1];
634: g->g_p[2] = g->g_q[2];
635: f = g_v;
636: switch (g->g_s) {
637: case 0:
638: if (field[g->g_p[1]][g->g_p[0]] & 1<<F_TN)
639: g->g_n += G_TMQN*8;
640: else
641: g->g_n += G_TMQN*4;
642: if (g->g_r > 0)
643: if (--g->g_r) {
644: g->g_f ^= 2;
645: break;
646: } else {
647: --g->g_r;
648: g->g_f = 0;
649: }
650: if (g->g_r) {
651: if (vector(g, g_g[0], 0))
652: g->g_r = 0;
653: } else if (contact(g->g_p, 3) && stop<i) {
654: stop = i;
655: break;
656: } else if (track() && sight(g->g_p)) {
657: vector(g, p_p, p_l);
658: } else if (nprox() && prox(g->g_p)<=nprox()) {
659: vector(g, p_p, p_l);
660: } else {
661: g_v[0] = g->g_p[2];
662: g_v[1] = 3&(g->g_p[2]+
663: (((g-ghost)^g->g_p[2])&2)-1);
664: g_v[2] = g_v[1]^2;
665: g_v[3] = g_v[0]^2;
666: f += (rand()&rand());
667: }
668: goto select;
669: case 1:
670: if (--g->g_e == 0) {
671: g->g_s = 0;
672: g->g_d = 0;
673: --e_s;
674: } else if (g->g_e <= G_BTIM)
675: g->g_d ^= 1;
676: g->g_n += G_TMQN*8;
677: vector(g, p_p, p_l);
678: f = g_v+2;
679: goto select;
680: case 2:
681: if (g->g_r == 0) {
682: g->g_r--;
683: g->g_d = 0;
684: }
685: g->g_n += G_TMQN*2;
686: if (vector(g, g_g[1], 0)) {
687: g->g_q[2] ^= 2;
688: while (g->g_n%(G_TMQN*4) != g->g_o)
689: g->g_n += G_TMQN*2;
690: g->g_s = 0;
691: g->g_f = 0;
692: --e_s;
693: break;
694: }
695: f = g_v;
696: select:
697: if (vm(*f)
698: && nc(g->g_p[0], g->g_p[1], *f)
699: & (1<<F_WL|1<<F_WL+1|1<<F_WL+3
700: | (!g->g_r)<<F_DR)
701: ) {
702: if (++f-g_v > 3)
703: f = g_v;
704: goto select;
705: }
706: if (hm(*f)
707: && nc(g->g_p[0]+2*incr(*f), g->g_p[1], *f)
708: & 1<<F_WL
709: ) {
710: if (++f-g_v > 3)
711: f = g_v;
712: goto select;
713: }
714: if ((*f^g->g_p[2])==2 && g->g_e<G_ETIM-1) {
715: if (++f-g_v > 3)
716: f = g_v;
717: goto select;
718: }
719: g->g_q[2] = *f;
720: do {
721: mc(g->g_q);
722: if (vm(g->g_q[2])
723: || (g->g_q[0]&1) == 0
724: )
725: break;
726: if (g->g_r
727: && (g->g_q[0] == g_g[0][0]
728: && g->g_q[1] == g_g[0][1]
729: || g->g_q[0] == g_g[1][0]
730: && g->g_q[1] == g_g[1][1]
731: ))
732: break;
733: mc(g->g_q);
734: } while (0);
735: if (g->g_p[2] == g->g_q[2])
736: g->g_f ^= 2;
737: else if ((g->g_p[2]^g->g_q[2]) & 1)
738: g->g_f = 0;
739: }
740: break;
741: case G_BLUE:
742: if (g->g_s < 2) {
743: if (g->g_s == 0)
744: if (g->g_r)
745: break;
746: else
747: ++e_s;
748: g->g_s = 1;
749: g->g_e = G_ETIM;
750: g->g_d = 0;
751: }
752: break;
753: case G_INIT:
754: g->g_p[0] = g->g_q[0] = g->g_h[0];
755: g->g_p[1] = g->g_q[1] = g->g_h[1];
756: g->g_q[2] = g_i[g-ghost];
757: g->g_s = 0;
758: g->g_d = 0;
759: g->g_e = 0;
760: g->g_f = 0;
761: g->g_r = 12*((g-ghost&1)*2+(g-ghost&2)/2);
762: g->g_n = g->g_o = G_TOFF(g-ghost);
763: break;
764: }
765: if (p)
766: plot(g->g_p[0]-1, g->g_p[1], 3, 1);
767: }
768: }
769:
770: plot(x, y, nx, ny)
771: {
772: register b, f;
773: register struct ghost *g;
774: register char *c;
775: register int *p;
776: register i;
777: register z0, z1, z2, z3;
778:
779: if (x < 0) {
780: nx -= x;
781: x = 0;
782: }
783: if ((nx+=x) > F_HORZ-F_HHID)
784: nx = F_HORZ-F_HHID;
785: for (ny+=y; y<ny; ++y) {
786: curs(y+F_VOFF, x+F_HOFF);
787: p = &field[y][x];
788: for (i=x; i<nx; ++i) {
789: if ((f=*p++&F_BMSK)==0 || i<F_HHID)
790: c = b_c;
791: else {
792: for (b=0; (f&1)==0; ++b)
793: f >>= 1;
794: switch (b) {
795: case F_GH+0:
796: case F_GH+1:
797: case F_GH+2:
798: case F_GH+3:
799: g = ghost + b - F_GH;
800: /*
801: c = g_c[b-F_GH]
802: [g->g_q[2]^(g->g_f&P_GFLP)]
803: [g->g_s-g->g_d]
804: [i-g->g_p[0]+1];
805: */
806: z0 = b-F_GH;
807: z1 = g->g_q[2]^(g->g_f&P_GFLP);
808: z2 = g->g_s-g->g_d;
809: z3 = i-g->g_p[0]+1;
810: c = g_c[z0][z1][z2][z3];
811: break;
812: case F_PC:
813: c = p_c[y-p_i[1]+(p_l&1)][p_p[2]]
814: [p_d][i-p_i[0]];
815: break;
816: case F_FR:
817: c = r_s? r_c : b_c;
818: break;
819: case F_BN:
820: c = b_c;
821: break;
822: case F_FD:
823: c = f_c;
824: break;
825: case F_EN:
826: c = e_c[e_k>>2];
827: break;
828: case F_DR:
829: c = d_c;
830: break;
831: case F_TN:
832: c = b_c;
833: break;
834: case F_WL:
835: c = w_c;
836: break;
837: }
838: }
839: atrb(*c++);
840: bufchr(*c);
841: }
842: }
843: }
844:
845: contact(p, n)
846: register *p;
847: {
848: register dx, dy;
849:
850: dx = p_p[0] - p[0];
851: dy = p_p[1]*2 + p_l - p[1]*2;
852: if ((dy==0 && n>dx && dx>-n)
853: || (dx==0 && n>dy && dy>-n)
854: )
855: return (1);
856: return (0);
857: }
858:
859: prox(p)
860: register *p;
861: {
862: register dx, dy;
863:
864: if ((dx=p_p[0]-p[0]) < 0)
865: dx = -dx;
866: if ((dy=p_p[1]*2+p_l-p[1]*2) < 0)
867: dy = -dy;
868: if (dy > dx)
869: return (dy);
870: return (dx);
871: }
872:
873: vector(g, t, o)
874: register struct ghost *g;
875: register *t;
876: {
877: register i;
878: int d[2], s[2] = {0, 0};
879:
880: if ((d[0]=t[0]-g->g_p[0]) < 0) {
881: d[0] =- d[0];
882: s[0] = 2;
883: } else if (d[0] == 0)
884: if (hm(g->g_p[2]))
885: s[0] = g->g_p[2]&2^2;
886: else
887: s[0] = rand()*2;
888: if ((d[1]=t[1]*2+o-g->g_p[1]*2) < 0) {
889: d[1] =- d[1];
890: s[1] = 2;
891: } else if (d[1] == 0)
892: if (vm(g->g_p[2]))
893: s[1] = g->g_p[2]&2^2;
894: else
895: s[1] = rand()*2;
896: if (d[0] > d[1])
897: i = 0;
898: else if (d[1] > d[0])
899: i = 1;
900: else
901: i = axis(g->g_p[2]);
902: t = g_v;
903: *t++ = i | s[i];
904: *t++ = (i^1) | s[i^1];
905: *t++ = (i^1) | (s[i^1]^2);
906: *t = i | (s[i]^2);
907: if (d[0] | d[1])
908: return (0);
909: return (1);
910: }
911:
912: sight(p)
913: register *p;
914: {
915: register v;
916: int q[3];
917:
918: if (p[0] != p_p[0]
919: && p[1] != p_p[1]
920: )
921: return (0);
922: for (v=p[2]-1; v<=p[2]+1; ++v) {
923: q[0] = p[0];
924: q[1] = p[1];
925: q[2] = v&3;
926: while ((field[q[1]][q[0]]&1<<F_WL) == 0) {
927: if (q[0]==p_p[0] && q[1]==p_p[1])
928: return (1);
929: mc(q);
930: }
931: }
932: return (0);
933: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.