Compare commits
	
		
			No commits in common. "df0b65e0973e78f3471aa6c12c2819af65129586" and "c4beb89104cdd44f0ea85c546d4bc275397e92f9" have entirely different histories.
		
	
	
		
			df0b65e097
			...
			c4beb89104
		
	
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,4 +1,2 @@ | |||||||
| raylib.h | raylib.h | ||||||
| game | game | ||||||
| 
 |  | ||||||
| */data/*.c |  | ||||||
| @ -3,14 +3,9 @@ CFLAGS=-Wall -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 | |||||||
| 
 | 
 | ||||||
| .PHONY: clean run | .PHONY: clean run | ||||||
| 
 | 
 | ||||||
| game: data/actions.c data/rooms.c data/transitions.c data/words.c data/flags.c *.c | game: | ||||||
| 	$(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 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,76 +0,0 @@ | |||||||
| * 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". |  | ||||||
| @ -1,50 +0,0 @@ | |||||||
| #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; |  | ||||||
| } |  | ||||||
| @ -1,29 +0,0 @@ | |||||||
| #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 |  | ||||||
| @ -1,4 +0,0 @@ | |||||||
| 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.| |  | ||||||
| @ -1,2 +0,0 @@ | |||||||
| LEVER_PULLED|0 |  | ||||||
| STEPS_TAKEN|10 |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| PULL|PULL,YANK,TUG |  | ||||||
| ROPE|ROPE,CORD,STRING,CABLE |  | ||||||
| LEVER|LEVER |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| #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; |  | ||||||
| } |  | ||||||
| @ -1,22 +0,0 @@ | |||||||
| #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,11 +6,6 @@ | |||||||
| #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)); | ||||||
| @ -34,15 +29,6 @@ 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; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -132,6 +118,31 @@ 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,9 +18,6 @@ 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; | ||||||
| @ -29,9 +26,6 @@ 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,7 +2,6 @@ | |||||||
| #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> | ||||||
| @ -16,20 +15,7 @@ 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(); | ||||||
|  | |||||||
| @ -1,30 +0,0 @@ | |||||||
| #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); |  | ||||||
| } |  | ||||||
| @ -1,7 +0,0 @@ | |||||||
| #ifndef _FD_PARSE_ |  | ||||||
| #define _FD_PARSE_ |  | ||||||
| #include "game.h" |  | ||||||
| 
 |  | ||||||
| void parse(Game *g, char *typed_command); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| #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; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @ -1,22 +0,0 @@ | |||||||
| #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,26 +2,6 @@ | |||||||
| #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,10 +3,16 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include "transition.h" | #include "transition.h" | ||||||
| #include "game.h" | #include "game.h" | ||||||
| #include "util.h" |  | ||||||
| 
 | 
 | ||||||
| void load_transition(Game *g, char *line) { | #define TRANSITIONS_PATH "./transitions.txt" | ||||||
|   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, "|"); | ||||||
| @ -15,16 +21,14 @@ void load_transition(Game *g, char *line) { | |||||||
|     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, "\n"); |     token = strtok(NULL, "|"); | ||||||
|     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++; | ||||||
| } |   } | ||||||
| 
 | 
 | ||||||
| #include "data/transitions.c" |   fclose(transitions_file); | ||||||
| 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) { | ||||||
|  | |||||||
| @ -1,23 +0,0 @@ | |||||||
| #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); |  | ||||||
| } |  | ||||||
| @ -1,7 +0,0 @@ | |||||||
| #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 |  | ||||||
| @ -1,38 +0,0 @@ | |||||||
| #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; |  | ||||||
| } |  | ||||||
| @ -1,22 +0,0 @@ | |||||||
| #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