Compare commits

..

No commits in common. "465ac02048052da64c6d432624a02b3a23bc57f4" and "9ef8e88b9a382dedd0e39877ef821e5bd6dbe52d" have entirely different histories.

19 changed files with 220 additions and 128 deletions

View File

@ -3,7 +3,7 @@ CFLAGS=-Wall -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
.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/transitions.c data/words.c data/flags.c *.c
$(CC) *.c $(CFLAGS) -o game
data/%.c: data/%.txt

View File

@ -1,11 +1,9 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "action.h"
#include "effect.h"
#include "predicate.h"
#include "game.h"
#include "parse.h"
#include "util.h"
void load_action(Game *g, char *line) {
@ -61,33 +59,9 @@ void load_action(Game *g, char *line) {
#include "data/actions.c"
void game_load_actions(Game *g) {
g->actions = malloc(sizeof(Actions));
g->actions->count = 0;
parse_multiline_string(g, data_actions_txt, &load_action);
printf("loaded actions\n");
}
Action *find_action(Game *g, const char *command) {
Command *c = parse(g, command);
int priority = -1;
Action *a = NULL;
bool failed_predicate;
for (int i = 0; i < g->actions->count; i++) {
Action *ca = &g->actions->actions[i];
if (ca->priority < priority) continue;
for (int j = 0; j < ca->words_count; j++) {
if (c->words[j] == NULL) break;
if (c->words[j] != ca->words[j]) break;
failed_predicate = false;
for (int k = 0; k < ca->predicates_count; k++) {
if (!predicate_fulfilled(g, ca->predicates[k])) failed_predicate = true;
}
if (failed_predicate) break;
if (j == ca->words_count - 1) {
priority = ca->priority;
a = ca;
}
}
}
return a;
Action *find_action(Actions *actions, char *command) {
return NULL;
}

View File

@ -26,6 +26,6 @@ struct Actions {
};
void game_load_actions(Game *g);
Action *find_action(Game *g, const char *command);
Action *find_action(Actions *actions, char *command);
#endif

View File

@ -1,14 +1,4 @@
QUIT | * | 1000 | Bye! | QUIT_GAME()
LOOK | * | 1 | * | LOOK_ROOM()
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)
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(LEVER_ROOM) | 10 | What do you want to pull? |
PULL LEVER | IN(LEVER_ROOM) | 100 | You pull the lever. Nice. | ENABLE(LEVER_PULLED)
PULL LEVER | IN(LEVER_ROOM) & ENABLED(LEVER_PULLED) | 1000 | You already pulled it. |

View File

@ -0,0 +1,4 @@
FIRST_ROOM|N|SECOND_ROOM|You head through the door.
SECOND_ROOM|S|FIRST_ROOM|You head back through the door.
FIRST_ROOM|E|LAST_ROOM|You crouch under the beam and enter the room.
LAST_ROOM|W|FIRST_ROOM|You crouch under the beam and return to the room.

View File

@ -1,9 +1,3 @@
PULL|PULL,YANK,TUG
ROPE|ROPE,CORD,STRING,CABLE
LEVER|LEVER
QUIT|QUIT,Q,EXIT
NORTH|NORTH,N
SOUTH|SOUTH,S
EAST|EAST,E
WEST|WEST,W
LOOK|LOOK,L

View File

@ -26,12 +26,6 @@ void cause_effect(Game *g, Effect *e) {
case EFFECT_DISABLE:
find_flag(g->flags, e->argument)->value = 0;
break;
case EFFECT_QUIT_GAME:
g->should_close = true;
break;
case EFFECT_LOOK_ROOM:
push_line_to_log(g->input->log, g->current_room->description);
break;
}
}
@ -55,17 +49,11 @@ Effect *create_effect(Game *g, const char *string) {
e->type = EFFECT_ENABLE;
} else if (strcmp(token, "DISABLE") == 0) {
e->type = EFFECT_DISABLE;
} else if (strcmp(token, "QUIT_GAME") == 0) {
e->type = EFFECT_QUIT_GAME;
} else if (strcmp(token, "LOOK_ROOM") == 0) {
e->type = EFFECT_LOOK_ROOM;
}
token = strtok_r(NULL, ")", &strtok_guy);
if (token) {
e->argument = malloc(strlen(token) + 1);
strcpy(e->argument, token);
}
e->argument = malloc(strlen(token) + 1);
strcpy(e->argument, token);
}
free(buffer);
@ -92,11 +80,5 @@ void print_effect(Effect *e) {
case EFFECT_DISABLE:
printf("DISABLE(%s)", e->argument);
break;
case EFFECT_QUIT_GAME:
printf("QUIT_GAME()");
break;
case EFFECT_LOOK_ROOM:
printf("LOOK_ROOM()");
break;
}
}

View File

@ -10,8 +10,6 @@ typedef enum EffectType {
EFFECT_DECREMENT,
EFFECT_ENABLE,
EFFECT_DISABLE,
EFFECT_QUIT_GAME,
EFFECT_LOOK_ROOM,
} EffectType;
#include "game.h"

View File

@ -13,16 +13,14 @@ void load_flag(Game *g, char *line) {
token = strtok(NULL, "|");
flag->value = atoi(token);
printf("AGH %s\n", token);
g->flags->count++;
}
#include "data/flags.c"
void game_load_flags(Game *g) {
g->flags = malloc(sizeof(Flags));
g->flags->count = 0;
parse_multiline_string(g, data_flags_txt, &load_flag);
printf("loaded flags\n");
}
int flag_value(Flags *f, char *key) {

View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include "game.h"
#include "transition.h"
#include "input.h"
#include "log.h"
#include "util.h"
@ -10,16 +11,16 @@
#include "flag.h"
#include "predicate.h"
#include "action.h"
#include "parse.h"
Game *game_create(void) {
Game *g = malloc(sizeof(Game));
g->should_close = false;
game_load_words(g);
game_load_flags(g);
game_load_actions(g);
game_load_rooms(g);
g->rooms = malloc(sizeof(Rooms));
g->rooms->count = 0;
g->transitions = malloc(sizeof(Transitions));
g->transitions->count = 0;
Log *log = create_log();
g->log = log;
@ -33,6 +34,15 @@ Game *game_create(void) {
g->input = input;
g->words = malloc(sizeof(Words));
g->words->count = 0;
g->flags = malloc(sizeof(Flags));
g->flags->count = 0;
g->actions = malloc(sizeof(Actions));
g->actions->count = 0;
return g;
}
@ -43,26 +53,83 @@ void free_game(Game *g) {
free(g);
}
#define INVALID_COMMAND "I don't know how to %s"
void game_handle_command(Game *g, const char *command) {
if (strlen(command) == 0) {
push_line_to_log(g->input->log, "?");
return;
bool string_in(const char *input, ...) {
va_list argp;
va_start(argp, input);
char *candidate;
while ((candidate = va_arg(argp, char*))) {
if (strcmp(input, candidate) == 0) {
va_end(argp);
return true;
}
}
Action *a = find_action(g, command);
if (a) {
if (strcmp(a->description, "*") != 0) push_line_to_log(g->input->log, a->description);
for (int i = 0; i < a->effects_count; i++) {
cause_effect(g, a->effects[i]);
}
return false;
}
Command command_from_string(const char *string) {
if (string_in(string, "QUIT", "Q", "EXIT", "CLOSE", NULL)) {
return COMMAND_QUIT;
}
if (string_in(string, "LOOK", "L", NULL)) {
return COMMAND_LOOK;
}
if (string_in(string, "NORTH", "N", NULL)) {
return COMMAND_NORTH;
}
if (string_in(string, "SOUTH", "S", NULL)) {
return COMMAND_SOUTH;
}
if (string_in(string, "EAST", "E", NULL)) {
return COMMAND_EAST;
}
if (string_in(string, "WEST", "W", NULL)) {
return COMMAND_WEST;
}
return COMMAND_UNKNOWN;
}
#define INVALID_DIRECTIONAL_COMMAND "I can't go %s from here"
void game_handle_directional_command(Game *g, const char *c) {
Room *r = g->current_room;
Transition *transition = find_transition(g->transitions, r, command_from_string(c));
if (transition) {
push_line_to_log(g->input->log, transition->description);
g->current_room = transition->to;
} else {
char *response = malloc(strlen(INVALID_COMMAND) + strlen(command) + 1);
sprintf(response, INVALID_COMMAND, command);
char *response = malloc(strlen(INVALID_DIRECTIONAL_COMMAND) + strlen(c) + 1);
sprintf(response, INVALID_DIRECTIONAL_COMMAND, c);
push_line_to_log(g->input->log, response);
free(response);
}
return;
}
#define INVALID_COMMAND "I don't know how to %s"
void game_handle_command(Game *g, const char *command) {
Input *input = g->input;
switch (command_from_string(command)) {
case COMMAND_QUIT:
g->should_close = true;
break;
case COMMAND_LOOK:
push_line_to_log(input->log, g->current_room->description);
break;
case COMMAND_NORTH:
case COMMAND_SOUTH:
case COMMAND_EAST:
case COMMAND_WEST:
game_handle_directional_command(g, command);
break;
default:
char *response = malloc(strlen(INVALID_COMMAND) + strlen(command) + 1);
sprintf(response, INVALID_COMMAND, command);
push_line_to_log(input->log, response);
free(response);
break;
}
}
void game_handle_input(Game *g) {

View File

@ -1,11 +1,9 @@
#ifndef _FD_GAME_
#define _FD_GAME_
#include <stdbool.h>
typedef struct Game Game;
typedef enum CommandType {
typedef enum Command {
COMMAND_LOOK,
COMMAND_QUIT,
COMMAND_UNKNOWN,
@ -13,10 +11,12 @@ typedef enum CommandType {
COMMAND_SOUTH,
COMMAND_EAST,
COMMAND_WEST,
} CommandType;
} Command;
#include <stdbool.h>
#include "input.h"
#include "room.h"
#include "transition.h"
#include "log.h"
#include "word.h"
#include "flag.h"
@ -28,13 +28,14 @@ struct Game {
Log *log;
Rooms *rooms;
Room *current_room;
Transitions *transitions;
Words *words;
Flags *flags;
Actions *actions;
};
Game *game_create(void);
CommandType command_from_string(const char *string);
Command command_from_string(const char *string);
void game_handle_command(Game *g, const char *command);
void game_load_rooms(Game *g);
void game_run_until_close(Game *g);

View File

@ -1,16 +1,53 @@
#include "game.h"
#include "../raylib.h"
#include "log.h"
#include "input.h"
#include "parse.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "../raylib.h"
#include "game.h"
#define TARGET_FPS 60
int main(void) {
InitWindow(800, 450, "Text Adventure");
SetTargetFPS(60);
SetTargetFPS(TARGET_FPS);
Game *g = game_create();
game_load_rooms(g);
g->current_room = &g->rooms->rooms[0];
game_load_transitions(g);
game_load_words(g);
game_load_flags(g);
game_load_actions(g);
for (int i = 0; i < g->actions->count; i++) {
for (int j = 0; j < g->actions->actions[i].words_count; j++) {
printf("%s ", g->actions->actions[i].words[j]->word);
}
printf("|");
for (int j = 0; j < g->actions->actions[i].predicates_count; j++) {
if (j > 0) printf(" & ");
print_predicate(g->actions->actions[i].predicates[j]);
}
printf("|%d|%s|", g->actions->actions[i].priority, g->actions->actions[i].description);
for (int j = 0; j < g->actions->actions[i].effects_count; j++) {
if (j > 0) printf(" & ");
print_effect(g->actions->actions[i].effects[j]);
}
printf("\n");
}
printf("before action\n");
printf("lever_pulled: %d\n", flag_value(g->flags, "LEVER_PULLED"));
cause_effect(g, g->actions->actions[2].effects[0]);
printf("after action\n");
printf("lever_pulled: %d\n", flag_value(g->flags, "LEVER_PULLED"));
game_run_until_close(g);
CloseWindow();

View File

@ -3,27 +3,28 @@
#include <string.h>
#include "game.h"
#include "word.h"
#include "parse.h"
Command *parse(Game *g, const char *typed_command) {
Command *c = malloc(sizeof(Command));
for (int i = 0; i < MAX_WORDS_IN_COMMAND; i++) {
c->words[i] = NULL;
}
#define MAX_WORDS_IN_COMMAND 4
void parse(Game *g, char *typed_command) {
printf("Typed command: %s\n", typed_command);
char *bluh = malloc(strlen(typed_command) + 1);
strcpy(bluh, typed_command);
Word **command = malloc(MAX_WORDS_IN_COMMAND * sizeof(Word));
int word_count = 0;
char *token = strtok(bluh, " ");
while (word_count < MAX_WORDS_IN_COMMAND && token != NULL) {
c->words[word_count] = find_word(g->words, token);
command[word_count] = find_word(g->words, token);
word_count++;
token = strtok(NULL, " ");
}
for(int i = 0; i < word_count; i++) {
printf("%s ", command[i]->word);
}
printf("\n");
free(bluh);
return c;
}

View File

@ -1,15 +1,7 @@
#ifndef _FD_PARSE_
#define _FD_PARSE_
typedef struct Command Command;
#include "game.h"
#include "word.h"
#define MAX_WORDS_IN_COMMAND 4
struct Command {
Word *words[4];
};
Command *parse(Game *g, const char *typed_command);
void parse(Game *g, char *typed_command);
#endif

View File

@ -20,11 +20,7 @@ void load_room(Game *g, char *line) {
#include "data/rooms.c"
void game_load_rooms(Game *g) {
g->rooms = malloc(sizeof(Rooms));
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) {

View File

@ -0,0 +1,37 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "transition.h"
#include "game.h"
#include "util.h"
void load_transition(Game *g, char *line) {
char *token = strtok(line, "|");
g->transitions->transitions[g->transitions->count].from = find_room(g->rooms, token);
token = strtok(NULL, "|");
g->transitions->transitions[g->transitions->count].via = command_from_string(token);
token = strtok(NULL, "|");
g->transitions->transitions[g->transitions->count].to = find_room(g->rooms, token);
token = strtok(NULL, "\n");
g->transitions->transitions[g->transitions->count].description = malloc(strlen(token) + 1);
strcpy(g->transitions->transitions[g->transitions->count].description, token);
g->transitions->count++;
}
#include "data/transitions.c"
void game_load_transitions(Game *g) {
parse_multiline_string(g, data_transitions_txt, &load_transition);
}
Transition *find_transition(Transitions *t, Room *from, Command via) {
for (int i = 0; i < t->count; i++) {
Transition *candidate = &t->transitions[i];
if (candidate->from == from && candidate->via == via) return candidate;
}
return NULL;
}

View File

@ -0,0 +1,25 @@
#ifndef _FD_TRANSITION_
#define _FD_TRANSITION_
typedef struct Transition Transition;
typedef struct Transitions Transitions;
#include "game.h"
#include "room.h"
struct Transition {
Room *from;
Command via;
Room *to;
char *description;
};
struct Transitions {
Transition transitions[200];
int count;
};
void game_load_transitions(Game *g);
Transition *find_transition(Transitions *t, Room *from, Command via);
#endif

View File

@ -23,10 +23,7 @@ void load_word(Game *g, char *line) {
#include "data/words.c"
void game_load_words(Game *g) {
g->words = malloc(sizeof(Words));
g->words->count = 0;
parse_multiline_string(g, data_words_txt, &load_word);
printf("loaded words\n");
}
Word *find_word(Words *words, char *word_or_syn) {

View File

@ -2,7 +2,6 @@
#define _FD_WORD_
typedef struct Word Word;
typedef struct Words Words;
typedef struct Words Words;
#include "game.h"