#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);
}