1: /* Copyright Massachusetts Institute of Technology 1984, 1985 */ 2: 3: #include <X/Xlib.h> 4: #include <stdio.h> 5: #include <sgtty.h> 6: #define MAZE_SIZE 36 7: #define PIXSIZE 768 8: #define SCANSIZE (PIXSIZE/16) 9: #define HALFSIZE (SCANSIZE/2) 10: #define CENTER (PIXSIZE/2) 11: #define SIDE (PIXSIZE/3) 12: #define MASK_SIZE ((PIXSIZE*PIXSIZE)/16) 13: #define STRIP_SIZE (((PIXSIZE/6)*PIXSIZE)/16) 14: 15: struct room { 16: struct room *north; 17: struct room *south; 18: struct room *east; 19: struct room *west; 20: }; 21: 22: struct room *front(dir, rm) 23: int dir; 24: struct room *rm; 25: { 26: if(rm == NULL) { 27: printf("NULL room\n"); 28: exit(1); 29: } 30: switch (dir) { 31: case 2: return(rm->south); 32: case 1: return(rm->east); 33: case 0: return(rm->north); 34: case 3: return(rm->west); 35: default: printf("dir = %d\n",dir); 36: exit(1); 37: } 38: } 39: 40: struct room *left(dir, rm) 41: int dir; 42: struct room *rm; 43: { 44: return(front((dir + 3) % 4, rm)); 45: } 46: 47: struct room *right(dir, rm) 48: int dir; 49: struct room *rm; 50: { 51: return(front((dir + 1) % 4, rm)); 52: } 53: 54: Window win; 55: int forepix, backpix; 56: Bitmap pat[20]; 57: 58: main(argc,argv) 59: int argc; 60: char **argv; 61: { 62: int dir,i,fd,moved; 63: struct room m[MAZE_SIZE],*this_room,*next_room; 64: char c; 65: XEvent ev; 66: char *str, *prog; 67: char *maze_file = NULL; 68: char *display = NULL; 69: int nbytes; 70: int bwidth; 71: char *fore_color, *back_color, *brdr_color; 72: Pixmap bground, border; 73: int reverse = 0; 74: ColorDef cdef; 75: WindowInfo info; 76: 77: prog = *argv; 78: if ((str = XGetDefault(prog, "ReverseVideo")) && strcmp(str, "on") == 0) 79: reverse = 1; 80: bwidth = 2; 81: if (str = XGetDefault(prog, "BorderWidth")) 82: bwidth = atoi(str); 83: fore_color = XGetDefault(prog, "ForeGround"); 84: back_color = XGetDefault(prog, "BackGround"); 85: brdr_color = XGetDefault(prog, "Border"); 86: for (argv++; --argc; argv++) { 87: if (!strcmp(*argv, "-rv")) { 88: reverse = 1; 89: } else if (!strcmp(*argv, "-fg") && argc) { 90: argv++; 91: argc--; 92: fore_color = *argv; 93: } else if (!strcmp(*argv, "-bg") && argc) { 94: argv++; 95: argc--; 96: back_color = *argv; 97: } else if (!strcmp(*argv, "-bd") && argc) { 98: argv++; 99: argc--; 100: brdr_color = *argv; 101: } else if (index(*argv, ':')) { 102: display = *argv; 103: } else if (**argv == '-' || maze_file != NULL) { 104: printf("usage: maze [-rv] [-fg <color>] [-bg <color>] [-bd <color>] [host:display] [file]\n"); 105: exit(1); 106: } else { 107: maze_file = *argv; 108: } 109: } 110: if (!XOpenDisplay(display)) { 111: perror(prog); 112: exit(1); 113: } 114: if (reverse) { 115: forepix = BlackPixel; 116: backpix = WhitePixel; 117: bground = WhitePixmap; 118: border = BlackPixmap; 119: } else { 120: forepix = WhitePixel; 121: backpix = BlackPixel; 122: bground = BlackPixmap; 123: border = WhitePixmap; 124: } 125: if (DisplayCells() > 2) { 126: if (fore_color && XParseColor(fore_color, &cdef) && 127: XGetHardwareColor(&cdef)) 128: forepix = cdef.pixel; 129: if (back_color && XParseColor(back_color, &cdef) && 130: XGetHardwareColor(&cdef)) 131: bground = XMakeTile(backpix = cdef.pixel); 132: if (brdr_color && XParseColor(brdr_color, &cdef) && 133: XGetHardwareColor(&cdef)) 134: border = XMakeTile(cdef.pixel); 135: } 136: 137: get_maze(m, maze_file); 138: this_room = &m[0]; 139: next_room = NULL; 140: dir = 1; 141: XQueryWindow(RootWindow, &info); 142: win = XCreateWindow(RootWindow, 143: (info.width - PIXSIZE - (bwidth<<1))>>1, 144: (info.height - PIXSIZE - (bwidth<<1))>>1, 145: PIXSIZE,PIXSIZE,bwidth,border,bground); 146: XMapWindow(win); 147: XSelectInput(win, ButtonPressed|KeyPressed|ExposeWindow); 148: set_up_maze(); 149: while (1) { 150: XClear(win); 151: next_room = this_room; 152: for(i=0;i<9;i++){ 153: if(right(dir,next_room) != NULL) draw_pass(i-1,1); 154: else draw_wall(i-1,1); 155: if(left(dir,next_room) != NULL) draw_pass(i-1,-1); 156: else draw_wall(i-1,-1); 157: if((next_room = front(dir,next_room)) == NULL){ 158: draw_block(i); 159: break; 160: } 161: } 162: if(i==9) XPixSet(win,CENTER-1,0,2,PIXSIZE,backpix); 163: moved = 0; 164: while(!moved){ 165: XNextEvent(&ev); 166: switch(ev.type){ 167: case ButtonPressed: 168: switch(((XButtonPressedEvent *)&ev)->detail & ValueMask) { 169: case LeftButton: 170: str = "l"; 171: break; 172: case MiddleButton: 173: if (((XButtonPressedEvent *)&ev)->detail & ShiftMask) 174: str = "b"; 175: else 176: str = "f"; 177: break; 178: case RightButton: 179: str = "r"; 180: break; 181: } 182: nbytes = 1; 183: break; 184: case KeyPressed: 185: str = XLookupMapping (&ev, &nbytes); 186: break; 187: case ExposeWindow: 188: XSync(0); 189: while (QLength()) { 190: XPeekEvent(&ev); 191: if (ev.type != ExposeWindow) 192: break; 193: XNextEvent(&ev); 194: } 195: nbytes = 0; 196: moved++; 197: } 198: if (nbytes == 1) 199: switch (*str) { 200: case 'r': 201: dir = (dir + 1) % 4; 202: moved++; 203: break; 204: case 'l': 205: dir = (dir + 3) % 4; 206: moved++; 207: break; 208: case 'f': 209: next_room = front(dir,this_room); 210: if(next_room != NULL){ 211: this_room = next_room; 212: moved++; 213: } 214: break; 215: case 'b': 216: next_room = front((dir+2)%4,this_room); 217: if(next_room != NULL){ 218: this_room = next_room; 219: moved++; 220: } 221: break; 222: case 'q': 223: exit(0); 224: default: 225: break; 226: } 227: } 228: } 229: } 230: 231: #ifdef notdef 232: #define MAZE_SIDE 6 233: print_maze(m) 234: struct room m[MAZE_SIZE]; 235: { 236: register int x, y; 237: 238: for(x=0;x<MAZE_SIDE;x++){ 239: for(y=0;y<MAZE_SIDE;y++){ 240: if(m[6*x+y].north == NULL){ 241: printf("+--+"); 242: } 243: else printf("+ +"); 244: } 245: printf("\n"); 246: for(y=0;y<MAZE_SIDE;y++){ 247: if(m[6*x+y].west == NULL){ 248: printf("| "); 249: } 250: else printf(" "); 251: if(m[6*x+y].east == NULL){ 252: printf("|"); 253: } 254: else printf(" "); 255: } 256: printf("\n"); 257: for(y=0;y<MAZE_SIDE;y++){ 258: if(m[6*x+y].south == NULL){ 259: printf("+--+"); 260: } 261: else printf("+ +"); 262: } 263: printf("\n"); 264: } 265: } 266: #endif 267: 268: draw_wall(dist,side) 269: int dist,side; 270: { 271: int x3,x4; 272: 273: x3 = SIDE>>dist; 274: x4 = SIDE>>(dist+1); 275: 276: if (x3>CENTER) { 277: x4 >>= 1; 278: if (side < 0) { 279: XPixFill(win,0,0,x4,PIXSIZE,forepix,pat[0],GXcopy,AllPlanes); 280: } else { 281: XPixFill(win,PIXSIZE-x4+1,0,x4-1,PIXSIZE,forepix,pat[19-dist-1],GXcopy,AllPlanes); 282: } 283: } else { 284: if(side<0) { 285: XPixFill(win,CENTER-x3+1,0,x4-1,PIXSIZE,forepix,pat[dist+1],GXcopy,AllPlanes); 286: } else { 287: XPixFill(win,CENTER+x4+1,0,x4-1,PIXSIZE,forepix,pat[19-dist-1],GXcopy,AllPlanes); 288: } 289: } 290: } 291: 292: draw_pass(dist,side) 293: int dist,side; 294: { 295: int x3,x4,i; 296: 297: x3 = SIDE>>dist; 298: x4 = SIDE>>(dist+1); 299: 300: if(side < 0){ 301: XPixSet(win,CENTER-x3,CENTER-x4,x4,x3,forepix); 302: XPixSet(win,CENTER-x3,0,1,PIXSIZE,backpix); 303: XPixSet(win,CENTER-x4,0,1,PIXSIZE,backpix); 304: } 305: else { 306: XPixSet(win,CENTER+x4,CENTER-x4,x4,x3,forepix); 307: XPixSet(win,CENTER+x4,0,1,PIXSIZE,backpix); 308: XPixSet(win,CENTER+x3,0,1,PIXSIZE,backpix); 309: } 310: } 311: 312: draw_block(dist) 313: int dist; 314: { 315: int x3,x4,i; 316: Vertex verts[5]; 317: 318: x3 = SIDE>>dist; 319: x4 = SIDE>>(dist+1); 320: 321: XPixSet(win,CENTER-x3+1,CENTER-x3,2*x3-1,2*x3,forepix); 322: } 323: 324: int default_maze[] = {-1,-1,6,-1, 325: -1,2,-1,-1, 326: -1,-1,8,1, 327: -1,4,9,-1, 328: -1,5,-1,3, 329: -1,-1,-1,4, 330: 0,7,12,11, 331: -1,8,-1,6, 332: 2,9,-1,7, 333: 3,10,-1,8, 334: -1,11,16,9, 335: -1,6,-1,10, 336: 6,-1,18,-1, 337: -1,14,19,-1, 338: -1,15,20,13, 339: -1,-1,21,-1, 340: 10,17,-1,-1, 341: -1,-1,-1,16, 342: 12,19,-1,-1, 343: 13,-1,-1,18, 344: 14,-1,26,-1, 345: 15,22,27,-1, 346: -1,23,28,21, 347: -1,-1,-1,22, 348: -1,25,30,-1, 349: -1,-1,31,24, 350: 20,27,-1,-1, 351: 21,-1,-1,26, 352: 22,29,34,-1, 353: -1,-1,-1,28, 354: 24,-1,-1,-1, 355: 25,32,-1,-1, 356: -1,33,-1,31, 357: -1,34,-1,32, 358: 28,35,-1,33, 359: -1,-1,-1,34}; 360: 361: get_maze(m, maze_file) 362: struct room m[MAZE_SIZE]; 363: char *maze_file; 364: { 365: FILE *fp; 366: int i,j,n,e,s,w; 367: 368: if (maze_file == NULL) { 369: for (i=0,j=0;i<MAZE_SIZE;i++){ 370: n=default_maze[j++]; 371: e=default_maze[j++]; 372: s=default_maze[j++]; 373: w=default_maze[j++]; 374: if(n == -1) m[i].north = NULL; 375: else m[i].north = &m[n]; 376: if(s == -1) m[i].south = NULL; 377: else m[i].south = &m[s]; 378: if(e == -1) m[i].east = NULL; 379: else m[i].east = &m[e]; 380: if(w == -1) m[i].west = NULL; 381: else m[i].west = &m[w]; 382: } 383: return; 384: } 385: if((fp = fopen(maze_file,"r")) == NULL){ 386: perror("maze"); 387: exit(1); 388: } 389: for(i=0;i<MAZE_SIZE;i++){ 390: fscanf(fp,"%d,%d,%d,%d\n",&n,&e,&s,&w); 391: if(n == -1) m[i].north = NULL; 392: else m[i].north = &m[n]; 393: if(s == -1) m[i].south = NULL; 394: else m[i].south = &m[s]; 395: if(e == -1) m[i].east = NULL; 396: else m[i].east = &m[e]; 397: if(w == -1) m[i].west = NULL; 398: else m[i].west = &m[w]; 399: } 400: fclose(fp); 401: } 402: 403: set_up_maze() 404: { 405: Bitmap b; 406: int i,bound[21],top[21],k,j,x; 407: short *strips[21],*mask; 408: 409: bound[0] = 0; 410: bound[10] = CENTER; 411: bound[20] = PIXSIZE; 412: for(i=1;i<10;i++){ 413: bound[10-i]=CENTER-(SIDE/(1<<(9-i))); 414: bound[10+i]=CENTER+(SIDE/(1<<(9-i))); 415: } 416: for(i=0;i<21;i++) 417: top[i] = 0; 418: mask = (short *)calloc(MASK_SIZE, sizeof(short)); 419: for (i=0;i<21;i++) 420: strips[i]=(short *)malloc(STRIP_SIZE * sizeof(short)); 421: for(i=0;i<HALFSIZE;i++){ 422: for(j=0;j<16;j++){ 423: mask[SCANSIZE*(16*i+j)+i] = 0xaaaa>>(15-j); 424: mask[SCANSIZE*(16*i+j)+SCANSIZE-1-i] = 0xaaaa<<(15-j); 425: mask[SCANSIZE*(PIXSIZE-1-16*i-j)+i] = 0x5555>>(15-j); 426: mask[SCANSIZE*(PIXSIZE-1-16*i-j)+SCANSIZE-1-i] = 0x5555<<(15-j); 427: } 428: } 429: for(i=0;i<(HALFSIZE-1);i++){ 430: for(j=(i+1)*16;j<CENTER;j++){ 431: if((j % 2) == 1){ 432: mask[SCANSIZE*j+i] = 0xaaaa; 433: mask[SCANSIZE*j+SCANSIZE-1-i] = 0xaaaa; 434: mask[SCANSIZE*(PIXSIZE-1-j)+i] = 0x5555; 435: mask[SCANSIZE*(PIXSIZE-1-j)+SCANSIZE-1-i] = 0x5555; 436: } 437: else { 438: mask[SCANSIZE*j+i] = 0x5555; 439: mask[SCANSIZE*j+SCANSIZE-1-i] = 0x5555; 440: mask[SCANSIZE*(PIXSIZE-1-j)+i] = 0xaaaa; 441: mask[SCANSIZE*(PIXSIZE-1-j)+SCANSIZE-1-i] = 0xaaaa; 442: } 443: } 444: } 445: for(j=0;j<PIXSIZE;j++){ 446: for(i=0;i<SCANSIZE;i++){ 447: for(k=1;k<21;k++){ 448: if((i*16) < bound[k]) { 449: strips[k-1][top[k-1]++] = mask[SCANSIZE*j+i]; 450: break; 451: } 452: } 453: } 454: } 455: for(i=5;i<15;i++) 456: top[i] = 0; 457: for(i=0;i<PIXSIZE;i++){ 458: strips[5][top[5]++] = mask[SCANSIZE*i+HALFSIZE-1]; 459: strips[6][top[6]++] = mask[SCANSIZE*i+HALFSIZE-1]>>8; 460: strips[7][top[7]++] = mask[SCANSIZE*i+HALFSIZE-1]>>12; 461: strips[8][top[8]++] = mask[SCANSIZE*i+HALFSIZE-1]>>14; 462: strips[9][top[9]++] = mask[SCANSIZE*i+HALFSIZE-1]>>15; 463: strips[10][top[10]++] = mask[SCANSIZE*i+HALFSIZE]; 464: strips[11][top[11]++] = mask[SCANSIZE*i+HALFSIZE]>>1; 465: strips[12][top[12]++] = mask[SCANSIZE*i+HALFSIZE]>>2; 466: strips[13][top[13]++] = mask[SCANSIZE*i+HALFSIZE]>>4; 467: strips[14][top[14]++] = mask[SCANSIZE*i+HALFSIZE]>>8; 468: } 469: for(k=1;k<21;k++){ 470: if (bound[k] != bound[k-1]) { 471: pat[k-1] = XStoreBitmap(bound[k]-bound[k-1],PIXSIZE,strips[k-1]); 472: if (pat[k-1] == NULL) 473: exit(1); 474: } else 475: pat[k-1] = NULL; 476: } 477: free(mask); 478: for (i=0;i<21;i++) 479: free(strips[i]); 480: }