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 | ||||
| game | ||||
| 
 | ||||
| */data/*.c | ||||
| @ -3,9 +3,14 @@ CFLAGS=-Wall -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 | ||||
| 
 | ||||
| .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 | ||||
| 
 | ||||
| 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 | ||||
| 	./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 "input.h" | ||||
| #include "log.h" | ||||
| #include "util.h" | ||||
| #include "word.h" | ||||
| #include "flag.h" | ||||
| #include "predicate.h" | ||||
| #include "action.h" | ||||
| 
 | ||||
| Game *game_create(void) { | ||||
|   Game *g = malloc(sizeof(Game)); | ||||
| @ -29,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; | ||||
| } | ||||
| 
 | ||||
| @ -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) { | ||||
|   handle_pressed_keys(g->input); | ||||
| } | ||||
|  | ||||
| @ -18,6 +18,9 @@ typedef enum Command { | ||||
| #include "room.h" | ||||
| #include "transition.h" | ||||
| #include "log.h" | ||||
| #include "word.h" | ||||
| #include "flag.h" | ||||
| #include "action.h" | ||||
| 
 | ||||
| struct Game { | ||||
|   bool should_close; | ||||
| @ -26,6 +29,9 @@ struct Game { | ||||
|   Rooms *rooms; | ||||
|   Room *current_room; | ||||
|   Transitions *transitions; | ||||
|   Words *words; | ||||
|   Flags *flags; | ||||
|   Actions *actions; | ||||
| }; | ||||
| 
 | ||||
| Game *game_create(void); | ||||
|  | ||||
| @ -2,6 +2,7 @@ | ||||
| #include "../raylib.h" | ||||
| #include "log.h" | ||||
| #include "input.h" | ||||
| #include "parse.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| @ -15,7 +16,20 @@ int main(void) { | ||||
| 
 | ||||
|     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("|preds|%d|%s|effects", g->actions->actions[i].priority, g->actions->actions[i].description); | ||||
| 
 | ||||
|       printf("\n"); | ||||
|     } | ||||
| 
 | ||||
|     game_run_until_close(g); | ||||
|     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 <stdio.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) { | ||||
|   free(r.name); | ||||
|  | ||||
| @ -3,16 +3,10 @@ | ||||
| #include <string.h> | ||||
| #include "transition.h" | ||||
| #include "game.h" | ||||
| #include "util.h" | ||||
| 
 | ||||
| #define TRANSITIONS_PATH "./transitions.txt" | ||||
| 
 | ||||
| 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, "|"); | ||||
| 
 | ||||
| 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, "|"); | ||||
| @ -21,14 +15,16 @@ void game_load_transitions(Game *g) { | ||||
|   token = strtok(NULL, "|"); | ||||
|   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); | ||||
|   strcpy(g->transitions->transitions[g->transitions->count].description, token); | ||||
|      | ||||
|   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) { | ||||
|  | ||||
							
								
								
									
										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