#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "cartograph.h"
#include "utils.h"
#include "tokendb.h"
struct tokenrec token[MAX_TOKEN];
char pathstr[] = "NARBL\0";
char bitstr[] = "SUD\0";
void free_record(int index)
{
switch(token[index].type) {
case TYPE_ROOM:
free((struct arearec *) token[index].record);
break;
case TYPE_DOOR:
free(((struct doorrec *) token[index].record)->name);
free((struct doorrec *) token[index].record);
break;
case TYPE_PATH:
free((struct pathrec *) token[index].record);
break;
}
token[index].type = TYPE_NONE;
token[index].record = 0;
}
int ok_token(int tokenid, int linenum, char *fn)
{
char buf[256];
if (tokenid < 33) {
sprintf(buf, "Illegal ASCII token %d\n", tokenid);
warning(buf, linenum, fn);
return(0);
}
if ((struct arearec *) token[tokenid].record) {
sprintf(buf, "Redefinition of token '%c'\n", tokenid);
warning(buf, linenum, fn);
free_record(tokenid);
}
return(1);
}
void define_new_area(char *s, int linenum, char *fn)
{
char ptr, buf[256], flagtext[100], *temp;
long flags;
int sector, i, tokenid;
if (sscanf(s, "%s %c %s %d", buf, &ptr, flagtext, §or) < 4) {
warning("Missing arguments for #ROOM definition\n", linenum, fn);
return;
}
/* Grab possible room name v3.10 - 04/26/95 */
temp = s;
for(i = 0; i < 4; i++) {
while(*temp && !isspace(*temp))
temp++;
while(isspace(*temp))
temp++;
}
if (*temp == ';')
temp = 0;
else {
strcpy(buf, temp);
if ((temp = strchr(buf, ';')))
*temp = 0;
while(*buf && isspace(buf[strlen(buf) - 1]))
buf[strlen(buf) - 1] = 0;
temp = buf;
}
if (!ok_token(ptr, linenum, fn))
return;
tokenid = ptr;
if ((flags = decipher_flag_text(flagtext)) < 0)
warning("Illegal ASCII bitvector in #ROOM definition\n", linenum, fn);
token[tokenid].type = TYPE_ROOM;
token[tokenid].record = (struct arearec *) malloc(sizeof(struct arearec));
/* Set up possible room name v3.10 - 04/26/95 */
if (temp)
((struct arearec *) token[tokenid].record)->name = str_dup(temp);
else
((struct arearec *) token[tokenid].record)->name = 0;
((struct arearec *) token[tokenid].record)->room_flags = flags;
((struct arearec *) token[tokenid].record)->sector = sector;
}
char *skip_spaces(char *ptr)
{
while(isspace(*ptr))
ptr++;
return(ptr);
}
void define_new_path(char *s, int linenum, char *fn)
{
struct pathrec *path;
int index, startdir, tokenid;
char buf[256], *cnt, *ptr;
cnt = skip_spaces(s + strlen("#PATH"));
if (!ok_token(tokenid = *cnt++, linenum, fn))
return;
token[tokenid].type = TYPE_PATH;
token[tokenid].record = (struct pathrec *) malloc(sizeof(struct pathrec));
path = (struct pathrec *) token[tokenid].record;
for(index = ABOVE; index <= LEFT; index++) {
path->dir[index].newdir = NOWHERE;
path->dir[index].bitvector = 0;
}
cnt = skip_spaces(cnt);
while ((*cnt != '\n') && (*cnt != '\r') && (*cnt)) {
if (*cnt == ';')
break;
if ((ptr = strchr(pathstr, *cnt)) == NULL) {
sprintf(buf, "Illegal direction %c in #PATH definition\n", *cnt);
warning(buf, linenum, fn);
free_record(tokenid);
break;
}
startdir = strlen(pathstr) - strlen(ptr) - 1;
cnt = skip_spaces(++cnt);
if (*cnt++ != '-') {
warning("Illegal format in #PATH definition\n", linenum, fn);
free_record(tokenid);
break;
}
cnt = skip_spaces(cnt);
while (isalpha(*cnt)) {
if ((ptr = strchr(pathstr, *cnt)) != NULL) {
if (startdir != NOWHERE) {
if (path->dir[startdir].newdir != NOWHERE) {
sprintf(buf,"Direction %c redefined in #PATH statement\n",
pathstr[startdir + 1]);
warning(buf, linenum, fn);
}
path->dir[startdir].newdir = ptr - pathstr - 1;
}
} else if ((ptr = strchr(bitstr, *cnt)) != NULL) {
if (startdir != NOWHERE)
path->dir[startdir].bitvector |= (1 << (ptr - bitstr));
} else {
sprintf(buf, "Illegal character %c in #PATH definition\n", *cnt);
warning(buf, linenum, fn);
free_record(tokenid);
}
cnt++;
}
cnt = skip_spaces(cnt);
}
}
void define_new_door(char *s, int linenum, char *fn)
{
char *cnt, *ptr;
int tokenid;
struct doorrec *door;
cnt = skip_spaces(s + strlen("#DOOR"));
if (!ok_token(tokenid = *cnt++, linenum, fn))
return;
token[tokenid].type = TYPE_DOOR;
token[tokenid].record = (struct doorrec *) malloc(sizeof(struct doorrec));
door = (struct doorrec *) token[tokenid].record;
cnt = skip_spaces(cnt);
if (sscanf(cnt, "%d %d", &(door->doortype), &(door->key)) != 2) {
warning("Missing parameters in #DOOR definition\n", linenum, fn);
free_record(tokenid);
return;
}
while (!isspace(*cnt))
cnt++;
cnt = skip_spaces(cnt);
while (!isspace(*cnt))
cnt++;
cnt = skip_spaces(cnt);
if ((ptr = strchr(cnt, ';')))
*ptr = 0;
if ((ptr = strchr(cnt, '~')))
*ptr = 0;
if ((ptr = strchr(cnt, '\n')))
*ptr = 0;
while (isspace(cnt[strlen(cnt) - 1]))
cnt[strlen(cnt) - 1] = 0;
door->name = str_dup(cnt);
}
void analyze_line(char *s, int linenum, char *fn)
{
char cmd[256];
char *ptr;
if ((ptr = strchr(s, '\n')))
*ptr = 0;
strcpy(cmd, s);
if (!(ptr = strtok(cmd, " \t")))
return;
if (!strcmp(ptr, "#ROOM"))
define_new_area(s, linenum, fn);
else if (!strcmp(ptr, "#PATH"))
define_new_path(s, linenum, fn);
else if (!strcmp(ptr, "#DOOR"))
define_new_door(s, linenum, fn);
}
void read_token_types(char *arg0)
{
FILE *fp;
char s[256];
int linenum = 0;
if ((fp = fopen(ARCHETYPE_FILE, "rt")) == NULL) {
/* Look at argv[0] to find archetype file v3.10 - 05/04/95 */
strcpy(s, arg0);
while(*s && (s[strlen(s) - 1] != '/'))
s[strlen(s) - 1] = 0;
strcat(s, ARCHETYPE_FILE);
if ((fp = fopen(s, "rt")) == NULL) {
error("Couldn't find startup file.\n\n");
exit(1);
}
}
while(fgets(s, 255, fp) != NULL)
analyze_line(s, ++linenum, ARCHETYPE_FILE);
fclose(fp);
}
void print_dir_string(int tokenid, int dir)
{
char special[10];
int index;
*special = 0;
for(index = 0; bitstr[index]; index++)
if (((struct pathrec *) token[tokenid].record)->dir[dir].bitvector &
(1 << index))
sprintf(special + strlen(special), "%c", bitstr[index]);
if (((struct pathrec *) token[tokenid].record)->dir[dir].newdir != NOWHERE)
printf("%c-%s%c ", pathstr[dir + 1], special, pathstr[
((struct pathrec *) token[tokenid].record)->dir[dir].newdir + 1]);
}
void print_token_list()
{
int index, dir;
for(index = 0; index < MAX_TOKEN; index++)
if ((struct arearec *) token[index].record) {
printf("%c: ", index);
switch(token[index].type) {
case TYPE_ROOM:
printf("Flags: %ld Sector: %d\n",
((struct arearec *) token[index].record)->room_flags,
((struct arearec *) token[index].record)->sector);
break;
case TYPE_DOOR:
printf("Name %s Type: %d Key: %d\n",
((struct doorrec *) token[index].record)->name,
((struct doorrec *) token[index].record)->doortype,
((struct doorrec *) token[index].record)->key);
break;
case TYPE_PATH:
for(dir = ABOVE; dir <= LEFT; dir++)
print_dir_string(index, dir);
printf("\n");
break;
}
}
}
void init_tokendb(char *arg0)
{
int index;
for(index = 0; index < MAX_TOKEN; index++) {
token[index].type = TYPE_NONE;
token[index].record = 0;
}
read_token_types(arg0);
}
void free_all_tokens()
{
int index;
for(index = 0; index < MAX_TOKEN; index++)
if ((struct arearec *) token[index].record)
free_record(index);
}
int get_token_room(int tokenid)
{
if (token[tokenid].type != TYPE_ROOM)
return(0);
return(tokenid);
}
int get_token_path(int tokenid)
{
if (token[tokenid].type != TYPE_PATH)
return(0);
return(tokenid);
}
int get_token_door(int tokenid)
{
if (token[tokenid].type != TYPE_DOOR)
return(0);
return(tokenid);
}
struct doorrec *get_door(int tokenid)
{
return((struct doorrec *) token[tokenid].record);
}
int find_new_direction(int tokenid, int fromdir)
{
return(((struct pathrec *) token[tokenid].record)->dir[fromdir].newdir);
}
long find_path_bitvector(int tokenid, int fromdir)
{
return(((struct pathrec *) token[tokenid].record)->dir[fromdir].bitvector);
}
void get_room_data(int tokenid, struct roomrec *room)
{
room->name = ((struct arearec *) token[tokenid].record)->name;
room->room_flags = ((struct arearec *) token[tokenid].record)->room_flags;
room->sector = ((struct arearec *) token[tokenid].record)->sector;
}