Compare commits
	
		
			10 Commits
		
	
	
		
			c4beb89104
			...
			df0b65e097
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| df0b65e097 | |||
| 28077a0eeb | |||
| 0ff24ad65b | |||
| e8a9caf304 | |||
| 842a6852cd | |||
| 204bf6c3c9 | |||
| a09f7106de | |||
| bdab6658b3 | |||
| 4cddd76b5f | |||
| 3092e015a2 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,2 +1,4 @@ | |||||||
| raylib.h | raylib.h | ||||||
| game | game | ||||||
|  | 
 | ||||||
|  | */data/*.c | ||||||
| @ -3,9 +3,14 @@ CFLAGS=-Wall -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 | |||||||
| 
 | 
 | ||||||
| .PHONY: clean run | .PHONY: clean run | ||||||
| 
 | 
 | ||||||
| game: | game: data/actions.c data/rooms.c data/transitions.c data/words.c data/flags.c *.c | ||||||
| 	$(CC) *.c $(CFLAGS) -o game | 	$(CC) *.c $(CFLAGS) -o game | ||||||
| 
 | 
 | ||||||
|  | data/%.c: data/%.txt | ||||||
|  | 	echo -n "char *data_$*_txt = \"" > data/$*.c | ||||||
|  | 	cat data/$*.txt | perl -pe 's/\n/\\n/g' >> data/$*.c | ||||||
|  | 	echo "\";" >> data/$*.c | ||||||
|  | 
 | ||||||
| run: game | run: game | ||||||
| 	./game | 	./game | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										76
									
								
								01_text_adventure/README.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								01_text_adventure/README.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | |||||||
|  | * Fatal Distractions Chapter 1 - Text Adventures | ||||||
|  | ** Concept | ||||||
|  | I'm not looking for anything super complicated. I've spent maybe 90 minutes | ||||||
|  | in my life playing text adventures, I'm sure there are some with really good | ||||||
|  | mechanics. For this one, I'm aiming for something at about the level of | ||||||
|  | [[https://homestarrunner.com/dungeonman][Thy Dungeonman]]. A map, moving between rooms, getting items, <verb>ing <item>s | ||||||
|  | <preposition> <other item>s. If I'm pretty much finished before the end of the | ||||||
|  | month, I could add | ||||||
|  |  - visual effects | ||||||
|  |  - saving and loading | ||||||
|  |  - pictures | ||||||
|  |  - music | ||||||
|  | 
 | ||||||
|  | I'm not trying to be a purist about this; I know 99% of all text adventures are | ||||||
|  | *just* text, but music is also fun to put together. | ||||||
|  | 
 | ||||||
|  | ** Implementation | ||||||
|  | *** Flags | ||||||
|  | A flag is a combination name and uinteger value. The value can be changed as the | ||||||
|  | result of an action, or checked within a predicate. Three uses for these: | ||||||
|  |  - Boolean values, 1 or 0 | ||||||
|  |  - Countdowns, start at some positive value and eventually become 0 = false | ||||||
|  |  - Counters, start at zero and increment ("you have rung the bell 10 times") | ||||||
|  | Counters seem really optional, booleans and countdowns seem actually useful. | ||||||
|  | Values should evaluate to false if zero, true otherwise. | ||||||
|  | Effects should be able to enable (set to 1), disable (set to 0), increment, or | ||||||
|  | decrement; if there's need for it, they'll need to set (set to X), I don't think so. | ||||||
|  | *** Effects | ||||||
|  | When an action evaluates, most of the time it will have no effect ("you can't | ||||||
|  | go north from here"). Sometimes though, an action should change the world. Here | ||||||
|  | are some effects: | ||||||
|  |  - Modify a flag (detailed above) | ||||||
|  |  - Change the current room | ||||||
|  |  - Add / remove an item from the inventory | ||||||
|  |  - Do some meta thing (save or load) | ||||||
|  | *** Predicates | ||||||
|  | I guess I need a DSL for predicates. I don't think I'll need to implement "OR", | ||||||
|  | my predicates should be able to be a chain of clauses "AND"ed together. Some clauses: | ||||||
|  |  - IN(room_name), true if the current room has that name | ||||||
|  |  - HAS(item_name), true if that item is in the inventory (or in the room) | ||||||
|  |  - ENABLED(flag_name), true if that flag has a value > 0 | ||||||
|  |  - TO(item_name), this is the real tough one, for transitive verbs with an object | ||||||
|  |    - 'use key on door' | ||||||
|  |    - 'give trinket to dennis' | ||||||
|  |    - 'take torch from sconce' | ||||||
|  |  Some of these things are items, some are definitely not. Not sure how to codify. Maybe: | ||||||
|  |    - DITRANSITIVE(preposition, object), which checks that the command is of the form: | ||||||
|  |      <verb> <noun> <preposition> <object> | ||||||
|  |  - Even monotransitive verbs ("pull lever") need to specify what they'll act on. | ||||||
|  | *** Actions | ||||||
|  | Actions are a command, or part of a command, plus a predicate, plus a priority, | ||||||
|  | plus a description, plus (optionally) some effects: | ||||||
|  | PULL       | *                                      | 1    | You don't see anything to pull | | ||||||
|  | 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.    | | ||||||
|  | If the command matches all of the first column, it looks at that action. | ||||||
|  | ">PULL LEVER" would match all four, ">PULL" would only match the first two. | ||||||
|  | The game would choose between all matched actions, filter to only the ones whose | ||||||
|  | predicates are fulfilled, and choose from those the one with the highest priority. | ||||||
|  | This might require a lot of typing, but I think it will have enough flexibility | ||||||
|  | to do everything I might want to do. | ||||||
|  | 
 | ||||||
|  | An action describing a transition would look as follows: | ||||||
|  | NORTH | *                | 1 | You can't go north from here. | | ||||||
|  | NORTH | IN(initial_room) | 2 | You enter the nasty room.     | GOTO(nasty_room) | ||||||
|  | NORTH | IN(other_room)   | 2 | You enter the opulent room.   | GOTO(opulent_room) | ||||||
|  | , but there's nicer syntax for transitions I'm sure. | ||||||
|  | *** Parsing | ||||||
|  | I'm sure we want a gallery of synonyms for most verbs and nouns. I assume we split the string | ||||||
|  | by spaces, making an array of canonical words, then write the actions around those canonical | ||||||
|  | words. | ||||||
|  | PULL|PULL,YANK,TUG | ||||||
|  | ROPE|ROPE,CORD,STRING,CABLE | ||||||
|  | With the above words, "PULL ROPE", "YANK CORD", or "TUG STRING" would all check for | ||||||
|  | actions as "PULL ROPE". | ||||||
							
								
								
									
										50
									
								
								01_text_adventure/action.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								01_text_adventure/action.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include "action.h" | ||||||
|  | #include "game.h" | ||||||
|  | #include "util.h" | ||||||
|  | 
 | ||||||
|  | void load_action(Game *g, char *line) { | ||||||
|  |   Action *action = &g->actions->actions[g->actions->count]; | ||||||
|  | 
 | ||||||
|  |   char *line_token_guy; | ||||||
|  |   char *line_token = strtok_r(line, "|", &line_token_guy); | ||||||
|  | 
 | ||||||
|  |   char command_buffer[200]; | ||||||
|  |   strcpy(command_buffer, line_token); | ||||||
|  | 
 | ||||||
|  |   char *command_token_guy; | ||||||
|  |   char *command_word = strtok_r(command_buffer, " ", &command_token_guy); | ||||||
|  |   while (command_word != NULL) { | ||||||
|  |     Word *word = find_word(g->words, command_word); | ||||||
|  |     action->words[action->words_count++] = word; | ||||||
|  |     command_word = strtok_r(NULL, " ", &command_token_guy); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   line_token = strtok_r(NULL, "|", &line_token_guy); | ||||||
|  | 
 | ||||||
|  |   // predicate bullshit
 | ||||||
|  |   // char *command_predicate_strtok = strtok_r
 | ||||||
|  | 
 | ||||||
|  |   line_token = strtok_r(NULL, "|", &line_token_guy); | ||||||
|  |   action->priority = atoi(line_token); | ||||||
|  | 
 | ||||||
|  |   line_token = strtok_r(NULL, "|", &line_token_guy); | ||||||
|  |   action->description = malloc(strlen(line_token) + 1); | ||||||
|  |   strcpy(action->description, line_token); | ||||||
|  | 
 | ||||||
|  |   line_token = strtok_r(NULL, "|", &line_token_guy); | ||||||
|  | 
 | ||||||
|  |   // action bullshit
 | ||||||
|  | 
 | ||||||
|  |   g->actions->count++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #include "data/actions.c" | ||||||
|  | void game_load_actions(Game *g) { | ||||||
|  |   parse_multiline_string(g, data_actions_txt, &load_action); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Action *find_action(Actions *actions, char *command) { | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								01_text_adventure/action.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								01_text_adventure/action.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | #ifndef _FD_ACTION_ | ||||||
|  | #define _FD_ACTION_ | ||||||
|  | 
 | ||||||
|  | typedef struct Action Action; | ||||||
|  | typedef struct Actions Actions; | ||||||
|  | 
 | ||||||
|  | #include "game.h" | ||||||
|  | #include "word.h" | ||||||
|  | #include "predicate.h" | ||||||
|  | 
 | ||||||
|  | struct Action { | ||||||
|  |   Word *words[4]; | ||||||
|  |   int words_count; | ||||||
|  |   Predicate *predicates[10]; | ||||||
|  |   int predicates_count; | ||||||
|  |   int priority; | ||||||
|  |   char *description; | ||||||
|  |   // Effect *effect;
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct Actions { | ||||||
|  |   Action actions[1000]; | ||||||
|  |   int count; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void game_load_actions(Game *g); | ||||||
|  | Action *find_action(Actions *actions, char *command); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										4
									
								
								01_text_adventure/data/actions.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								01_text_adventure/data/actions.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | |||||||
|  | PULL|*|1|You don't see anything to pull| | ||||||
|  | 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.| | ||||||
							
								
								
									
										2
									
								
								01_text_adventure/data/flags.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								01_text_adventure/data/flags.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | LEVER_PULLED|0 | ||||||
|  | STEPS_TAKEN|10 | ||||||
							
								
								
									
										3
									
								
								01_text_adventure/data/words.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								01_text_adventure/data/words.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | PULL|PULL,YANK,TUG | ||||||
|  | ROPE|ROPE,CORD,STRING,CABLE | ||||||
|  | LEVER|LEVER | ||||||
							
								
								
									
										31
									
								
								01_text_adventure/flag.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								01_text_adventure/flag.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include "flag.h" | ||||||
|  | #include "game.h" | ||||||
|  | #include "util.h" | ||||||
|  | 
 | ||||||
|  | void load_flag(Game *g, char *line) { | ||||||
|  |   char *token = strtok(line, "|"); | ||||||
|  |   Flag *flag = &g->flags->flags[g->flags->count]; | ||||||
|  |   flag->key = malloc(strlen(token) + 1); | ||||||
|  |   strcpy(flag->key, token); | ||||||
|  | 
 | ||||||
|  |   token = strtok(NULL, "|"); | ||||||
|  |   flag->value = atoi(token); | ||||||
|  | 
 | ||||||
|  |   g->flags->count++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #include "data/flags.c" | ||||||
|  | void game_load_flags(Game *g) { | ||||||
|  |   parse_multiline_string(g, data_flags_txt, &load_flag); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int flag_value(Flags *f, char *key) { | ||||||
|  |   for (int i = 0; i < f->count; i++) { | ||||||
|  |     if (strcmp(f->flags[i].key, key) == 0) return f->flags[i].value; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return -1; | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								01_text_adventure/flag.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								01_text_adventure/flag.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | #ifndef _FD_FLAG_ | ||||||
|  | #define _FD_FLAG_ | ||||||
|  | 
 | ||||||
|  | typedef struct Flag Flag; | ||||||
|  | typedef struct Flags Flags; | ||||||
|  | 
 | ||||||
|  | #include "game.h" | ||||||
|  | 
 | ||||||
|  | struct Flag { | ||||||
|  |   char *key; | ||||||
|  |   int value; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct Flags { | ||||||
|  |   Flag flags[200]; | ||||||
|  |   int count; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void game_load_flags(Game *g); | ||||||
|  | int flag_value(Flags *f, char *key); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -6,6 +6,11 @@ | |||||||
| #include "transition.h" | #include "transition.h" | ||||||
| #include "input.h" | #include "input.h" | ||||||
| #include "log.h" | #include "log.h" | ||||||
|  | #include "util.h" | ||||||
|  | #include "word.h" | ||||||
|  | #include "flag.h" | ||||||
|  | #include "predicate.h" | ||||||
|  | #include "action.h" | ||||||
| 
 | 
 | ||||||
| Game *game_create(void) { | Game *game_create(void) { | ||||||
|   Game *g = malloc(sizeof(Game)); |   Game *g = malloc(sizeof(Game)); | ||||||
| @ -29,6 +34,15 @@ Game *game_create(void) { | |||||||
| 
 | 
 | ||||||
|   g->input = input; |   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; |   return g; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -118,31 +132,6 @@ void game_handle_command(Game *g, const char *command) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define ROOMS_PATH "./rooms.txt" |  | ||||||
| #define MAX_ROOM_COUNT 100 |  | ||||||
| 
 |  | ||||||
| char room_buffer[2001]; |  | ||||||
| 
 |  | ||||||
| void game_load_rooms(Game *g) { |  | ||||||
|   FILE *rooms_file = fopen(ROOMS_PATH, "r"); |  | ||||||
| 
 |  | ||||||
|   while ((fgets(room_buffer, 2000, rooms_file)) != NULL) { |  | ||||||
|     char *token = strtok(room_buffer, "|"); |  | ||||||
| 
 |  | ||||||
|     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->count++; |  | ||||||
|   } |  | ||||||
|   fclose(rooms_file); |  | ||||||
| 
 |  | ||||||
|   g->current_room = &g->rooms->rooms[0]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void game_handle_input(Game *g) { | void game_handle_input(Game *g) { | ||||||
|   handle_pressed_keys(g->input); |   handle_pressed_keys(g->input); | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,6 +18,9 @@ typedef enum Command { | |||||||
| #include "room.h" | #include "room.h" | ||||||
| #include "transition.h" | #include "transition.h" | ||||||
| #include "log.h" | #include "log.h" | ||||||
|  | #include "word.h" | ||||||
|  | #include "flag.h" | ||||||
|  | #include "action.h" | ||||||
| 
 | 
 | ||||||
| struct Game { | struct Game { | ||||||
|   bool should_close; |   bool should_close; | ||||||
| @ -26,6 +29,9 @@ struct Game { | |||||||
|   Rooms *rooms; |   Rooms *rooms; | ||||||
|   Room *current_room; |   Room *current_room; | ||||||
|   Transitions *transitions; |   Transitions *transitions; | ||||||
|  |   Words *words; | ||||||
|  |   Flags *flags; | ||||||
|  |   Actions *actions; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| Game *game_create(void); | Game *game_create(void); | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| #include "../raylib.h" | #include "../raylib.h" | ||||||
| #include "log.h" | #include "log.h" | ||||||
| #include "input.h" | #include "input.h" | ||||||
|  | #include "parse.h" | ||||||
| 
 | 
 | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| @ -15,7 +16,20 @@ int main(void) { | |||||||
| 
 | 
 | ||||||
|     Game *g = game_create(); |     Game *g = game_create(); | ||||||
|     game_load_rooms(g); |     game_load_rooms(g); | ||||||
|  |     g->current_room = &g->rooms->rooms[0]; | ||||||
|     game_load_transitions(g); |     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("|preds|%d|%s|effects", g->actions->actions[i].priority, g->actions->actions[i].description); | ||||||
|  | 
 | ||||||
|  |       printf("\n"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     game_run_until_close(g); |     game_run_until_close(g); | ||||||
|     CloseWindow(); |     CloseWindow(); | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								01_text_adventure/parse.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								01_text_adventure/parse.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | |||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include "game.h" | ||||||
|  | #include "word.h" | ||||||
|  | 
 | ||||||
|  | #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) { | ||||||
|  |     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); | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								01_text_adventure/parse.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								01_text_adventure/parse.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | #ifndef _FD_PARSE_ | ||||||
|  | #define _FD_PARSE_ | ||||||
|  | #include "game.h" | ||||||
|  | 
 | ||||||
|  | void parse(Game *g, char *typed_command); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										19
									
								
								01_text_adventure/predicate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								01_text_adventure/predicate.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include "game.h" | ||||||
|  | #include "flag.h" | ||||||
|  | #include "predicate.h" | ||||||
|  | 
 | ||||||
|  | bool predicate_fulfilled(Game *g, Predicate *p) { | ||||||
|  |   switch (p->type) { | ||||||
|  |   case PREDICATE_TRUE: | ||||||
|  |     return true; | ||||||
|  |   case PREDICATE_IN_ROOM: | ||||||
|  |     return strcmp(g->current_room->name, p->argument) == 0; | ||||||
|  |   case PREDICATE_FLAG_ENABLED: | ||||||
|  |     return flag_value(g->flags, p->argument) > 0; | ||||||
|  |   default: | ||||||
|  |     printf("Invalid predicate type\n"); | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								01_text_adventure/predicate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								01_text_adventure/predicate.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | #ifndef _FD_PREDICATE_ | ||||||
|  | #define _FD_PREDICATE_ | ||||||
|  | 
 | ||||||
|  | typedef struct Predicate Predicate; | ||||||
|  | 
 | ||||||
|  | typedef enum PredicateType { | ||||||
|  |   PREDICATE_TRUE, | ||||||
|  |   PREDICATE_IN_ROOM, | ||||||
|  |   // PREDICATE_HAS_ITEM,
 | ||||||
|  |   PREDICATE_FLAG_ENABLED, | ||||||
|  | } PredicateType; | ||||||
|  | 
 | ||||||
|  | #include "game.h" | ||||||
|  | 
 | ||||||
|  | struct Predicate { | ||||||
|  |   PredicateType type; | ||||||
|  |   char *argument; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | bool predicate_fulfilled(Game *g, Predicate *p); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -2,6 +2,26 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include "room.h" | #include "room.h" | ||||||
|  | #include "game.h" | ||||||
|  | #include "util.h" | ||||||
|  | 
 | ||||||
|  | void load_room(Game *g, char *line) { | ||||||
|  |   char *token = strtok(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->count++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #include "data/rooms.c" | ||||||
|  | void game_load_rooms(Game *g) { | ||||||
|  |   parse_multiline_string(g, data_rooms_txt, &load_room); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void free_room(Room r) { | void free_room(Room r) { | ||||||
|   free(r.name); |   free(r.name); | ||||||
|  | |||||||
| @ -3,16 +3,10 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include "transition.h" | #include "transition.h" | ||||||
| #include "game.h" | #include "game.h" | ||||||
|  | #include "util.h" | ||||||
| 
 | 
 | ||||||
| #define TRANSITIONS_PATH "./transitions.txt" | void load_transition(Game *g, char *line) { | ||||||
| 
 |   char *token = strtok(line, "|"); | ||||||
| char transition_buffer[2001]; |  | ||||||
| void game_load_transitions(Game *g) { |  | ||||||
|   FILE *transitions_file = fopen(TRANSITIONS_PATH, "r"); |  | ||||||
| 
 |  | ||||||
|   while ((fgets(transition_buffer, 2000, transitions_file)) != NULL) { |  | ||||||
|     char *token = strtok(transition_buffer, "|"); |  | ||||||
| 
 |  | ||||||
|   g->transitions->transitions[g->transitions->count].from = find_room(g->rooms, token); |   g->transitions->transitions[g->transitions->count].from = find_room(g->rooms, token); | ||||||
| 
 | 
 | ||||||
|   token = strtok(NULL, "|"); |   token = strtok(NULL, "|"); | ||||||
| @ -21,14 +15,16 @@ void game_load_transitions(Game *g) { | |||||||
|   token = strtok(NULL, "|"); |   token = strtok(NULL, "|"); | ||||||
|   g->transitions->transitions[g->transitions->count].to = find_room(g->rooms, token); |   g->transitions->transitions[g->transitions->count].to = find_room(g->rooms, token); | ||||||
| 
 | 
 | ||||||
|     token = strtok(NULL, "|"); |   token = strtok(NULL, "\n"); | ||||||
|   g->transitions->transitions[g->transitions->count].description = malloc(strlen(token) + 1); |   g->transitions->transitions[g->transitions->count].description = malloc(strlen(token) + 1); | ||||||
|   strcpy(g->transitions->transitions[g->transitions->count].description, token); |   strcpy(g->transitions->transitions[g->transitions->count].description, token); | ||||||
|      |      | ||||||
|   g->transitions->count++; |   g->transitions->count++; | ||||||
|   } | } | ||||||
| 
 | 
 | ||||||
|   fclose(transitions_file); | #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) { | Transition *find_transition(Transitions *t, Room *from, Command via) { | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								01_text_adventure/util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								01_text_adventure/util.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include "util.h" | ||||||
|  | #include "game.h" | ||||||
|  | 
 | ||||||
|  | void parse_multiline_string(Game *g, char *string, void (*parse_line)(Game *g, char *line)) { | ||||||
|  |   char *buffer = malloc(0); | ||||||
|  |   char *sol = string; | ||||||
|  |   char *eol = strchr(sol, '\n'); | ||||||
|  |   while (eol != NULL) { | ||||||
|  |     int line_length = eol - sol; | ||||||
|  |     buffer = realloc(buffer, line_length + 1); | ||||||
|  |     memcpy(buffer, sol, line_length); | ||||||
|  |     buffer[line_length] = '\0'; | ||||||
|  | 
 | ||||||
|  |     parse_line(g, buffer); | ||||||
|  | 
 | ||||||
|  |     sol = eol + 1; | ||||||
|  |     eol = strchr(sol, '\n'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   free(buffer); | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								01_text_adventure/util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								01_text_adventure/util.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | #ifndef _FD_UTIL_ | ||||||
|  | #define _FD_UTIL_ | ||||||
|  | #include "game.h" | ||||||
|  | 
 | ||||||
|  | void parse_multiline_string(Game *g, char *string, void (*parse_line)(Game *g, char *line)); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										38
									
								
								01_text_adventure/word.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								01_text_adventure/word.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include "word.h" | ||||||
|  | #include "game.h" | ||||||
|  | #include "util.h" | ||||||
|  | 
 | ||||||
|  | void load_word(Game *g, char *line) { | ||||||
|  |   char *token = strtok(line, "|"); | ||||||
|  |   Word *word = &g->words->words[g->words->count]; | ||||||
|  |   word->word = malloc(strlen(token) + 1); | ||||||
|  |   strcpy(word->word, token); | ||||||
|  | 
 | ||||||
|  |   word->synonyms_count = 0; | ||||||
|  |   while ((token = strtok(NULL, ",")) != NULL) { | ||||||
|  |     word->synonyms[word->synonyms_count] = malloc(strlen(token) + 1); | ||||||
|  |     strcpy(word->synonyms[word->synonyms_count], token); | ||||||
|  |     word->synonyms_count++; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   g->words->count++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #include "data/words.c" | ||||||
|  | void game_load_words(Game *g) { | ||||||
|  |   parse_multiline_string(g, data_words_txt, &load_word); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Word *find_word(Words *words, char *word_or_syn) { | ||||||
|  |   for (int i = 0; i < words->count; i++) { | ||||||
|  |     for (int j = 0; j < words->words[i].synonyms_count; j++) { | ||||||
|  |       if (strcmp(words->words[i].synonyms[j], word_or_syn) == 0) return &words->words[i]; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   printf("Can't find %s\n", word_or_syn); | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								01_text_adventure/word.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								01_text_adventure/word.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | #ifndef _FD_WORD_ | ||||||
|  | #define _FD_WORD_ | ||||||
|  | typedef struct Word Word; | ||||||
|  | typedef struct Words Words; | ||||||
|  | 
 | ||||||
|  | #include "game.h" | ||||||
|  | 
 | ||||||
|  | struct Word { | ||||||
|  |   char *word; | ||||||
|  |   char* synonyms[100]; | ||||||
|  |   int synonyms_count; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct Words { | ||||||
|  |   Word words[200]; | ||||||
|  |   int count; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void game_load_words(Game *g); | ||||||
|  | Word *find_word(Words *words, char *word); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user