#include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <string.h> #include "cartograph.h" #include "utils.h" #include "tokendb.h" #include "parse.h" struct roomrec graph[MAX_ROOMS]; char map[MAX_HEIGHT + 2][MAX_WIDTH + 3]; int numlines = 0; int numrooms = 0; int oppositedir[4] = { BELOW, LEFT, ABOVE, RIGHT }; int dirxmod[4] = { 0, 1, 0, -1 }; int dirymod[4] = { -1, 0, 1, 0 }; char dirstr[] = "NESWUD"; void check_special(char *up, char *down, int *x, int *y, int dir) { char upslide = 0, downslide = 0; long vector; vector = find_path_bitvector(map[*y][*x], oppositedir[dir]); if (vector & PATH_SKIP) { *x += dirxmod[dir]; *y += dirymod[dir]; } if (vector & PATH_UP) upslide = 1; else if (vector & PATH_DOWN) downslide = 1; if (upslide) { if (*down) *down = 0; else *up = 1; } else if (downslide) { if (*up) *up = 0; else *down = 1; } } int ok_location(int x, int y) { if ((y > 0) && (x > 0) && (y < numlines) && (x < strlen(map[y]))) return(1); return(0); } int follow_path(int *xl, int *yl, int *door, int dir) { char up = 0, down = 0; char done = 0; int move, x, y, temp; x = *xl + dirxmod[dir]; y = *yl + dirymod[dir]; move = dir; *xl = *yl = -1; while (!done) { if (!ok_location(x, y)) return(dir); if (get_token_room(map[y][x])) { *xl = x; *yl = y; done = 1; } else if ((temp = get_token_path(map[y][x]))) { if ((move = find_new_direction(temp, oppositedir[move])) == NOWHERE) done = 1; else { check_special(&up, &down, &x, &y, move); x += dirxmod[move]; y += dirymod[move]; } } else if ((temp = get_token_door(map[y][x]))) { if (!*door) *door = temp; x+= dirxmod[move]; y+= dirymod[move]; } else done = 1; } if (up) return(UP); else if (down) return(DOWN); else return(dir); } void init_map(char *mapfile) { int index, curline, linenum; FILE *fp; char buf[MAX_WIDTH + 1]; char *comment; if ((fp = fopen(mapfile, "rt")) == NULL) { sprintf(buf, "Input file \"%s\" not found!\n", mapfile); error(buf); exit(1); } curline = linenum = 0; while((fgets(buf, MAX_WIDTH, fp) != NULL) && (curline <= MAX_HEIGHT)) { linenum++; comment = buf; while (isspace(*comment)) comment++; if (*comment == '#') analyze_line(buf, linenum, mapfile); else { /* BugFix v2.01 - 05/05/94 */ if ((comment = strchr(buf, '\n')) != NULL) *comment = 0; if ((comment = strchr(buf, ';')) != NULL) *comment = 0; sprintf(map[++curline], " %s ", buf); } } fclose(fp); if (curline > MAX_HEIGHT) { error("Input file too long - Raise MAX_HEIGHT constant in parse.c\n"); exit(1); } for(index = 0; index < MAX_WIDTH; index++) { map[0][index] = ' '; map[curline + 1][index] = ' '; } numlines = curline + 1; } void identify_rooms(long def_flags) { int index, index2, index3, roomtype, errorcnt = 0; char s[256]; for(index = 1; index < numlines; index++) for(index2 = 1; index2 < strlen(map[index]); index2++) if ((roomtype = get_token_room(map[index][index2]))) { /* Sanity Check v3.01 - 11/14/94 */ if (numrooms >= MAX_ROOMS) { errorcnt++; continue; } graph[numrooms].xcoord = index2; graph[numrooms].ycoord = index; get_room_data(map[index][index2], &graph[numrooms]); graph[numrooms].room_flags |= def_flags; for(index3 = NORTH; index3 <= DOWN; index3++) { graph[numrooms].dir[index3].toroom = NOWHERE; graph[numrooms].dir[index3].doortype = 0; graph[numrooms].dir[index3].key = -1; graph[numrooms].dir[index3].name = 0; } numrooms++; } /* Sanity Check v3.01 - 11/14/94 */ if (errorcnt) { sprintf(s, "Too many rooms - Map truncated.\n " "Raise MAX_ROOMS in cartograph.h to %d.\n", errorcnt + MAX_ROOMS); error(s); } } void connect_rooms() { int curroom, dir, finaldir, dest, x, y, doornum; struct doorrec *door; for(curroom = 0; curroom < numrooms; curroom++) for(dir = NORTH; dir <= WEST; dir++) { x = graph[curroom].xcoord; y = graph[curroom].ycoord; doornum = 0; finaldir = follow_path(&x, &y, &doornum, dir); for(dest = 0; dest < numrooms; dest++) { if ((graph[dest].xcoord == x) && (graph[dest].ycoord == y)) graph[curroom].dir[finaldir].toroom = dest; if (doornum) { door = get_door(doornum); graph[curroom].dir[finaldir].name = str_dup(door->name); graph[curroom].dir[finaldir].doortype = door->doortype; graph[curroom].dir[finaldir].key = door->key; } } } } void parse_map(long def_flags) { identify_rooms(def_flags); connect_rooms(); } void save_map(char *mapfile, int offset) { FILE *fp; int index, dir; char worldfile[256], buf[256]; sprintf(worldfile, "%s.wld", mapfile); if ((fp = fopen(worldfile, "wt")) == NULL) { sprintf(buf, "Can not write to world file \"%s\"\n", worldfile); error(buf); exit(1); } /* Added optional room name v3.10 - 04/26/95 */ for(index = 0; index < numrooms; index++) { fprintf(fp, "#%d\n", index + offset); if (graph[index].name) fprintf(fp, "%s~\n", graph[index].name); else fprintf(fp, "Room #%d~\n", index + offset); fprintf(fp, "This description is yet unfinished...\n"); fprintf(fp, "~\n"); fprintf(fp, "%d %ld %d\n", offset / 100, graph[index].room_flags, graph[index].sector); printf("#: %3d X:%4d Y:%4d", index + offset, graph[index].xcoord, graph[index].ycoord); for(dir = 0; dir < 6; dir++) { if (graph[index].dir[dir].toroom > NOWHERE) graph[index].dir[dir].toroom += offset; printf(" %c:%4d", dirstr[dir], graph[index].dir[dir].toroom); if (graph[index].dir[dir].toroom > NOWHERE) { fprintf(fp, "D%d\n~\n", dir); if (graph[index].dir[dir].name) fprintf(fp, "%s", graph[index].dir[dir].name); fprintf(fp, "~\n%d %d %d\n", graph[index].dir[dir].doortype, graph[index].dir[dir].key, graph[index].dir[dir].toroom); } } fprintf(fp, "S\n"); printf("\n"); } fclose(fp); }