Compare commits

..

5 Commits

12 changed files with 137 additions and 17 deletions

View File

@ -7,7 +7,7 @@ endif
.PHONY: clean run
game: data/actions.c data/rooms.c data/words.c data/flags.c *.c
game: data/actions.c data/rooms.c data/room_ins.c data/words.c data/flags.c *.c
$(CC) *.c $(CFLAGS) -o game
data/%.c: data/%.txt

View File

@ -1,14 +1,17 @@
QUIT | * | 1000 | Bye! | QUIT_GAME()
LOOK | * | 1 | * | LOOK_ROOM()
HELP | * | 1 | Type commands to explore the environment. Use 'LOOK' to examine the room you're in, or 'LOOK <item>' to examine an item closely. 'N', 'S', 'E', and 'W' will move you in the four cardinal directions, and 'I' will let you check your inventory. The parser is not very advanced, so do your best. 'Q', 'QUIT', or 'EXIT' will let you quit. |
INVENTORY | * | 1 | Your inventory is empty. |
NORTH | * | 1 | You can't go north from here. |
SOUTH | * | 1 | You can't go south from here. |
EAST | * | 1 | You can't go east from here. |
WEST | * | 1 | You can't go west from here. |
NORTH | IN(FIRST_ROOM) | 10 | You head through the door. | GOTO(SECOND_ROOM)
SOUTH | IN(SECOND_ROOM) | 10 | You head back through the door. | GOTO(FIRST_ROOM)
EAST | IN(FIRST_ROOM) | 10 | You crouch under the beam and enter the room. | GOTO(LAST_ROOM)
WEST | IN(LAST_ROOM) | 10 | You crouch under the beam and return to the room. | GOTO(FIRST_ROOM)
EAST | IN(FIRST_ROOM) & ENABLED(LEVER_PULLED) | 20 | You crouch under the portcullis and enter the room. | GOTO(LAST_ROOM)
EAST | IN(FIRST_ROOM) | 10 | There is a portcullis in the way. |
WEST | IN(LAST_ROOM) | 10 | You crouch under the portcullis and return to the room. | GOTO(FIRST_ROOM)
PULL | * | 1 | You don't see anything to pull |
PULL | IN(FIRST_ROOM) | 10 | What do you want to pull? |
PULL LEVER | IN(FIRST_ROOM) | 100 | You pull the lever. Nice. | ENABLE(LEVER_PULLED)
PULL LEVER | IN(FIRST_ROOM) & ENABLED(LEVER_PULLED) | 1000 | You already pulled it. |
PULL | IN(SECOND_ROOM) | 10 | What do you want to pull? |
PULL LEVER | IN(SECOND_ROOM) | 100 | You pull the lever and the sound of grinding machinery comes from the first room. | ENABLE(LEVER_PULLED)
PULL LEVER | IN(SECOND_ROOM) & ENABLED(LEVER_PULLED) | 1000 | You already pulled it. |

View File

@ -0,0 +1,4 @@
FIRST_ROOM | * | 1 | You are in a plain room. A doorway is on the north wall, and a portcullis obstructs a doorway to the east.
FIRST_ROOM | ENABLED(LEVER_PULLED) | 10 | You are in a plain room. A doorway is on the north wall, and the doorway once obstructed by the portcullis is to the east.
SECOND_ROOM | * | 1 | This is a small room. It's painted blue. There's a doorway on the south wall, and a conspicuous lever in the middle of the floor.
LAST_ROOM | * | 1 | This room is in disrepair. A doorway is open to the west.

View File

@ -1,3 +1,3 @@
FIRST_ROOM|This is a plain room. A wooden door is on the north wall, and a beam semi-obstructs an open doorway to the east.
SECOND_ROOM|This is a small room. It's painted blue. There's a door on the south wall.
LAST_ROOM|This room is in disrepair. A beam partially blocks the doorway to the west.
FIRST_ROOM
SECOND_ROOM
LAST_ROOM

View File

@ -7,3 +7,5 @@ SOUTH|SOUTH,S
EAST|EAST,E
WEST|WEST,W
LOOK|LOOK,L
INVENTORY|INVENTORY,I,INV
HELP|HELP,H

View File

@ -4,6 +4,7 @@
#include "game.h"
#include "flag.h"
#include "effect.h"
#include "room_in.h"
void cause_effect(Game *g, Effect *e) {
if (e == NULL) return;
@ -12,7 +13,7 @@ void cause_effect(Game *g, Effect *e) {
case EFFECT_NOOP:
break;
case EFFECT_GOTO:
g->current_room = find_room(g->rooms, e->argument);
change_current_room(g, find_room(g->rooms, e->argument));
break;
case EFFECT_INCREMENT:
find_flag(g->flags, e->argument)->value++;
@ -30,7 +31,7 @@ void cause_effect(Game *g, Effect *e) {
g->should_close = true;
break;
case EFFECT_LOOK_ROOM:
push_line_to_log(g->input->log, g->current_room->description);
push_line_to_log(g->input->log, find_room_in(g)->description);
break;
}
}

View File

@ -20,6 +20,7 @@ Game *game_create(void) {
game_load_flags(g);
game_load_actions(g);
game_load_rooms(g);
game_load_room_ins(g);
Log *log = create_log();
g->log = log;
@ -33,6 +34,7 @@ Game *game_create(void) {
g->input = input;
change_current_room(g, &g->rooms->rooms[0]);
return g;
}
@ -84,3 +86,11 @@ void game_run_until_close(Game *g) {
game_draw(g);
}
}
void change_current_room(Game *g, Room *r) {
g->current_room = r;
if (!r->visited) {
push_line_to_log(g->input->log, find_room_in(g)->description);
}
r->visited = true;
}

View File

@ -17,6 +17,7 @@ typedef enum CommandType {
#include "input.h"
#include "room.h"
#include "room_in.h"
#include "log.h"
#include "word.h"
#include "flag.h"
@ -27,6 +28,7 @@ struct Game {
Input *input;
Log *log;
Rooms *rooms;
RoomIns *room_ins;
Room *current_room;
Words *words;
Flags *flags;
@ -41,5 +43,6 @@ void game_run_until_close(Game *g);
void game_handle_input(Game *g);
void game_draw(Game *g);
void free_game(Game *g);
void change_current_room(Game *g, Room *r);
#endif

View File

@ -11,9 +11,7 @@ void load_room(Game *g, char *line) {
g->rooms->rooms[g->rooms->count].name = malloc(strlen(token) + 1);
strcpy(g->rooms->rooms[g->rooms->count].name, token);
token = strtok(NULL, "|");
g->rooms->rooms[g->rooms->count].description = malloc(strlen(token) + 1);
strcpy(g->rooms->rooms[g->rooms->count].description, token);
g->rooms->rooms[g->rooms->count].visited = false;
g->rooms->count++;
}
@ -24,12 +22,10 @@ void game_load_rooms(Game *g) {
g->rooms->count = 0;
parse_multiline_string(g, data_rooms_txt, &load_room);
printf("loaded rooms\n");
g->current_room = &g->rooms->rooms[0];
}
void free_room(Room r) {
free(r.name);
free(r.description);
}
void free_rooms(Rooms r) {

View File

@ -4,9 +4,11 @@
typedef struct Room Room;
typedef struct Rooms Rooms;
#include <stdbool.h>
struct Room {
char *name;
char *description;
bool visited;
};
struct Rooms {

View File

@ -0,0 +1,71 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "game.h"
#include "room_in.h"
#include "util.h"
void load_room_in(Game *g, char *line) {
RoomIn *ri = &g->room_ins->room_ins[g->room_ins->count];
ri->predicates_count = 0;
char *line_token_guy;
char *line_token = strtok_r(line, "|", &line_token_guy);
Room *r = find_room(g->rooms, line_token);
g->room_ins->room_ins[g->room_ins->count].room = r;
line_token = strtok_r(NULL, "|", &line_token_guy);
char *room_in_token_guy;
char room_in_buffer[200];
strcpy(room_in_buffer, line_token);
char *room_in_word = strtok_r(room_in_buffer, " &", &room_in_token_guy);
while (room_in_word != NULL) {
Predicate *p = create_predicate(g, room_in_word);
ri->predicates[ri->predicates_count++] = p;
room_in_word = strtok_r(NULL, " &", &room_in_token_guy);
}
line_token = strtok_r(NULL, "|", &line_token_guy);
ri->priority = atoi(line_token);
line_token = strtok_r(NULL, "|", &line_token_guy);
g->room_ins->room_ins[g->room_ins->count].description = malloc(strlen(line_token) + 1);
strcpy(g->room_ins->room_ins[g->room_ins->count].description, line_token);
g->room_ins->count++;
}
#include "data/room_ins.c"
void game_load_room_ins(Game *g) {
g->room_ins = malloc(sizeof(RoomIns));
g->room_ins->count = 0;
parse_multiline_string(g, data_room_ins_txt, &load_room_in);
printf("loaded room ins\n");
}
RoomIn *find_room_in(Game *g) {
RoomIn *ri;
int priority = -1;
bool failed_predicate;
for (int i = 0; i < g->room_ins->count; i++) {
RoomIn *cri = &g->room_ins->room_ins[i];
if (cri->priority < priority) continue;
if (cri->room != g->current_room) continue;
failed_predicate = false;
for (int j = 0; j < cri->predicates_count; j++) {
if (!predicate_fulfilled(g, cri->predicates[j])) failed_predicate = true;
}
if (failed_predicate) break;
priority = cri->priority;
ri = cri;
}
if (ri) return ri;
printf("Couldn't find a valid room_in\n");
return &g->room_ins->room_ins[0];
}

View File

@ -0,0 +1,28 @@
#ifndef _FD_ROOM_IN_
#define _FD_ROOM_IN_
typedef struct RoomIn RoomIn;
typedef struct RoomIns RoomIns;
#include "game.h"
#include "room.h"
#include "predicate.h"
struct RoomIn {
Room *room;
Predicate *predicates[10];
int predicates_count;
int priority;
char *description;
};
struct RoomIns {
RoomIn room_ins[200];
int count;
};
void game_load_room_ins(Game *g);
RoomIns *find_room_ins(Room *r);
RoomIn *find_room_in(Game *g);
#endif