|
|
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.