#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INPUT_LIMIT 256
#define PROMPT "> "
enum action {
UNKNOWN,
LOOK,
GO_NORTH,
GO_SOUTH,
GO_EAST,
GO_WEST,
QUIT
};
enum direction {
NORTH,
SOUTH,
EAST,
WEST
};
struct room {
char *title;
char *description;
struct door **doors;
};
struct door {
enum direction direction;
struct room *src;
struct room *dst;
};
struct world {
struct player *player;
};
struct player {
char *name;
struct room *room;
};
struct command {
enum action action;
char *string;
};
struct world *genesis(void);
void apocalypse(struct world*);
enum action parse(char*);
void move(struct player*, enum direction);
void look(struct room*);
int loop(struct world*);
static struct command commands[] = {
{LOOK , "l" },
{GO_NORTH , "n" },
{GO_SOUTH , "s" },
{GO_EAST , "e" },
{GO_WEST , "w" },
{QUIT , "q" },
{UNKNOWN , NULL}
};
struct world *genesis(void)
{
struct world *w;
struct player *p;
struct room *r1, *r2, *r3;
struct door *d12, *d21, *d23, *d32;
w = (struct world*) malloc(sizeof(struct world));
p = (struct player*) malloc(sizeof(struct player));
r1 = (struct room*) malloc(sizeof(struct room));
r2 = (struct room*) malloc(sizeof(struct room));
r3 = (struct room*) malloc(sizeof(struct room));
r1->title = "The foo room";
r1->description = "You are in the foo room. Sunlight streams from the windows.";
r2->title = "The bar room";
r2->description = "You are in the bar room. A vague sense of despair washes over you.";
r3->title = "The baz room";
r3->description = "You are in the baz room. It is richly furnished.";
d12 = (struct door*) malloc(sizeof(struct door));
d21 = (struct door*) malloc(sizeof(struct door));
d23 = (struct door*) malloc(sizeof(struct door));
d32 = (struct door*) malloc(sizeof(struct door));
d12->direction = EAST;
d12->src = r1;
d12->dst = r2;
d21->direction = WEST;
d21->src = r2;
d21->dst = r1;
d23->direction = NORTH;
d23->src = r2;
d23->dst = r3;
d32->direction = SOUTH;
d32->src = r3;
d32->dst = r2;
struct door *ds1[] = {d12, NULL};
struct door *ds2[] = {d21, d23, NULL};
struct door *ds3[] = {d32, NULL};
r1->doors = ds1;
r2->doors = ds2;
r3->doors = ds3;
p->room = r1;
w->player = p;
return w;
}
void apocalypse(struct world *w)
{
free(w->player->room);
free(w->player);
free(w);
}
int main(void)
{
struct world *w;
w = genesis();
while (loop(w));
apocalypse(w);
exit(EXIT_SUCCESS);
}
void look(struct room *r)
{
printf("%s: %s\n", r->title, r->description);
return;
}
void move(struct player *p, enum direction dir)
{
struct door **ds;
for (ds = p->room->doors; *ds; ds++)
if ((*ds)->direction == dir) {
p->room = (*ds)->dst;
look(p->room);
return;
}
puts("You can't go that way.");
return;
}
enum action parse(char *s)
{
unsigned long i;
s[strcspn(s, "\n")] = 0;
for (i = 0; i < sizeof(commands) / sizeof(struct command); i++)
if (commands[i].string && !strcmp(commands[i].string, s))
return commands[i].action;
return UNKNOWN;
}
int loop(struct world *w)
{
char input[INPUT_LIMIT];
enum action a;
printf("%s", PROMPT);
if (fgets(input, INPUT_LIMIT, stdin) != NULL) {
a = parse(input);
switch (a) {
case LOOK:
look(w->player->room);
return 1;
case QUIT:
return 0;
case GO_NORTH:
move(w->player, NORTH);
return 1;
case GO_SOUTH:
move(w->player, SOUTH);
return 1;
case GO_EAST:
move(w->player, EAST);
return 1;
case GO_WEST:
move(w->player, WEST);
return 1;
case UNKNOWN:
printf("What is \"%s\"?\n", input);
return 1;
}
} else {
puts("");
return 0;
}
}