#include #include /* matrices of open squares, and of visible squares */ int open[200][200]; int seen[200][200]; /* current map dimensions, and player coords */ int height, width; int px, py; /* call this to read a map from a textfile and initialize the globals */ void init_map(char *path) { FILE *fp = fopen(path, "r"); char c; int y = 0; int x = 0; while(666) { c = fgetc(fp); if(c == EOF) break; else if(c == '\n') { if(y == 0) width = x; else if(x != width) { printf("row %d has invalid width: %d (%d)", y, x, width); exit(1); } x = 0; y++; } else { if(c == '@') { px = x; py = y; open[y][x] = 1; } else if(c == '.') open[y][x] = 1; else if(c == '#') open[y][x] = 0; else { printf("invalid char %c (%hho) at row %d, col %d", c, c, y, x); exit(1); } x++; } } height = y; fclose(fp); } /* output the map and los data in ASCII */ void draw_map(void) { int y, x; printf("+"); for(x = 0; x < width; x++) printf("-"); printf("+\n"); for(y = 0; y < height; y++) { printf("|"); for(x = 0; x < width; x++) { if(y == py && x == px) printf("@"); else if(seen[y][x] && open[y][x]) printf("."); else if(seen[y][x]) printf("#"); else if(open[y][x]) printf(" "); else printf("+"); } printf("|\n"); } printf("+"); for(x = 0; x < width; x++) printf("-"); printf("+\n\n"); } /* calculate all squares the player can see, using get_los() */ void mark_all_los(void) { int x, y; for(y=0; y < height; y++) for(x=0; x < width; x++) seen[y][x] = get_los(px, py, x, y); } /* determine if (x1, y1) can see (x2, y2) */ int get_los(x1, y1, x2, y2) { int dx = x2 - x1; int dy = y2 - y1; int ax = abs(dx); int ay = abs(dy); int ix = dx > 0 ? 1 : -1; int iy = dy > 0 ? 1 : -1; int i; int xoff = 0; int yoff = 0; /* horizontal line case */ if(ay == 0) { for(i = 1; i < ax; i++) { x1 += ix; if(!open[y1][x1]) return 0; } return 1; } /* vertical line case */ if(ax == 0) { for(i = 1; i < ay; i++) { y1 += iy; if(!open[y1][x1]) return 0; } return 1; } /* more horizontal movement case */ if(ax > ay) { for(i = 1; i < ax; i++) { xoff += ix; yoff = (xoff * dy) / dx; if(yoff * dx % dy == 0) if(!open[y1 + yoff][x1 + xoff]) return 0; else if(!open[y1 + yoff][x1 + xoff] && !open[y1 + yoff + iy][x1 + xoff]) return 0; } return 1; } /* more vertical movement case */ if(ay > ax) { for(i = 1; i < ay; i++) { yoff += iy; xoff = (yoff * dx) / dy; if(yoff * dx % dy == 0) if(!open[y1 + yoff][x1 + xoff]) return 0; else if(!open[y1 + yoff][x1 + xoff] && !open[y1 + yoff][x1 + xoff + ix]) return 0; } return 1; } /* exact diagonal movement case */ if(ay == ax) { for(i = 1; i < ax; i++) { x1 += ix; y1 += iy; if(!open[y1][x1]) return 0; } return 1; } } int main(int argc, char **argv) { int i; if(argc == 1) { printf("usage: %s map1 [map2 ...]\n\n", argv[0]); printf("maps are text files in the following style:\n"); printf("#####.\n#...#.\n#..@#.\n#.....\n#####.\n"); exit(0); } for(i = 1; i < argc; i++) { init_map(argv[i]); mark_all_los(); draw_map(); } }