Compare commits
4 Commits
e09013036f
...
eb43986876
Author | SHA1 | Date | |
---|---|---|---|
eb43986876 | |||
868c2211be | |||
faccabcafc | |||
b786a0fa04 |
@ -1,13 +1,9 @@
|
||||
CC=gcc
|
||||
ifeq ($(shell uname),Darwin)
|
||||
CFLAGS=-Wall -lraylib -lm -lpthread -ldl -lX11
|
||||
else
|
||||
CFLAGS=-Wall -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
|
||||
endif
|
||||
CFLAGS=-Wall -lraylib -lm -lpthread -ldl -lX11
|
||||
|
||||
.PHONY: clean run
|
||||
|
||||
game: data/actions.c data/rooms.c data/room_ins.c data/words.c data/flags.c *.c
|
||||
game: data/actions.c data/rooms.c data/room_ins.c data/words.c data/flags.c data/items.c *.c
|
||||
$(CC) *.c $(CFLAGS) -o game
|
||||
|
||||
data/%.c: data/%.txt
|
||||
|
@ -1,7 +1,7 @@
|
||||
QUIT | * | 1000 | Bye! | QUIT_GAME()
|
||||
LOOK | * | 1 | * | LOOK_ROOM()
|
||||
HELP | * | 1 | Type commands to explore the environment. Use 'LOOK' to examine the room you're in, or 'LOOK <item>' to examine an item closely. 'N', 'S', 'E', and 'W' will move you in the four cardinal directions, and 'I' will let you check your inventory. The parser is not very advanced, so do your best. 'Q', 'QUIT', or 'EXIT' will let you quit. |
|
||||
INVENTORY | * | 1 | Your inventory is empty. |
|
||||
INVENTORY | * | 1 | * | CHECK_INVENTORY()
|
||||
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. |
|
||||
@ -15,3 +15,8 @@ PULL | * | 1 | You don't see anyth
|
||||
PULL | IN(SECOND_ROOM) | 10 | What do you want to pull? |
|
||||
PULL LEVER | IN(SECOND_ROOM) | 100 | You pull the lever and the sound of grinding machinery comes from the first room. | ENABLE(LEVER_PULLED)
|
||||
PULL LEVER | IN(SECOND_ROOM) & ENABLED(LEVER_PULLED) | 1000 | You already pulled it. |
|
||||
TAKE TORCH | ITEM_HERE(UNLIT_TORCH) | 1000 | You pick up the torch | TAKE(UNLIT_TORCH)
|
||||
TAKE TORCH | HAS_ITEM(UNLIT_TORCH) | 1001 | You already have a torch |
|
||||
TAKE TORCH | * | 100 | What torch? |
|
||||
DROP TORCH | * | 100 | What torch? |
|
||||
DROP TORCH | HAS_ITEM(UNLIT_TORCH) | 1000 | You lay the torch carefully on the ground. | DROP(UNLIT_TORCH)
|
||||
|
4
01_text_adventure/data/items.txt
Normal file
4
01_text_adventure/data/items.txt
Normal file
@ -0,0 +1,4 @@
|
||||
UNLIT_TORCH | a torch | true | A sturdy torch. It's unlit.
|
||||
LIT_TORCH | a lit torch | true | A sturdy torch. It's on fire, and illuminates its surroundings.
|
||||
FLASK | a flask | true | An empty glass flask, with a cork.
|
||||
ANVIL | an anvil | false | A heavy iron anvil.
|
@ -9,3 +9,8 @@ WEST|WEST,W
|
||||
LOOK|LOOK,L
|
||||
INVENTORY|INVENTORY,I,INV
|
||||
HELP|HELP,H
|
||||
ANVIL|ANVIL
|
||||
FLASK|FLASK,BOTTLE,JAR
|
||||
TORCH|TORCH
|
||||
TAKE|TAKE,PICKUP,GET
|
||||
DROP|DROP
|
||||
|
@ -32,6 +32,16 @@ void cause_effect(Game *g, Effect *e) {
|
||||
break;
|
||||
case EFFECT_LOOK_ROOM:
|
||||
push_line_to_log(g->input->log, find_room_in(g)->description);
|
||||
log_items_in_room(g, g->current_room);
|
||||
break;
|
||||
case EFFECT_TAKE_ITEM:
|
||||
take_item(g, e->argument);
|
||||
break;
|
||||
case EFFECT_DROP_ITEM:
|
||||
drop_item(g, e->argument);
|
||||
break;
|
||||
case EFFECT_CHECK_INVENTORY:
|
||||
check_inventory(g);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -60,6 +70,12 @@ Effect *create_effect(Game *g, const char *string) {
|
||||
e->type = EFFECT_QUIT_GAME;
|
||||
} else if (strcmp(token, "LOOK_ROOM") == 0) {
|
||||
e->type = EFFECT_LOOK_ROOM;
|
||||
} else if (strcmp(token, "TAKE") == 0) {
|
||||
e->type = EFFECT_TAKE_ITEM;
|
||||
} else if (strcmp(token, "DROP") == 0) {
|
||||
e->type = EFFECT_DROP_ITEM;
|
||||
} else if (strcmp(token, "CHECK_INVENTORY") == 0) {
|
||||
e->type = EFFECT_CHECK_INVENTORY;
|
||||
}
|
||||
|
||||
token = strtok_r(NULL, ")", &strtok_guy);
|
||||
@ -99,5 +115,14 @@ void print_effect(Effect *e) {
|
||||
case EFFECT_LOOK_ROOM:
|
||||
printf("LOOK_ROOM()");
|
||||
break;
|
||||
case EFFECT_TAKE_ITEM:
|
||||
printf("TAKE(%s)", e->argument);
|
||||
break;
|
||||
case EFFECT_DROP_ITEM:
|
||||
printf("DROP(%s)", e->argument);
|
||||
break;
|
||||
case EFFECT_CHECK_INVENTORY:
|
||||
printf("CHECK_INVENTORY()");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,9 @@ typedef enum EffectType {
|
||||
EFFECT_DISABLE,
|
||||
EFFECT_QUIT_GAME,
|
||||
EFFECT_LOOK_ROOM,
|
||||
EFFECT_TAKE_ITEM,
|
||||
EFFECT_DROP_ITEM,
|
||||
EFFECT_CHECK_INVENTORY,
|
||||
} EffectType;
|
||||
|
||||
#include "game.h"
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "predicate.h"
|
||||
#include "action.h"
|
||||
#include "parse.h"
|
||||
#include "item.h"
|
||||
|
||||
Game *game_create(void) {
|
||||
Game *g = malloc(sizeof(Game));
|
||||
@ -21,6 +22,9 @@ Game *game_create(void) {
|
||||
game_load_actions(g);
|
||||
game_load_rooms(g);
|
||||
game_load_room_ins(g);
|
||||
game_load_items(g);
|
||||
|
||||
g->items->items[0].location = &g->rooms->rooms[0];
|
||||
|
||||
Log *log = create_log();
|
||||
g->log = log;
|
||||
|
@ -22,6 +22,7 @@ typedef enum CommandType {
|
||||
#include "word.h"
|
||||
#include "flag.h"
|
||||
#include "action.h"
|
||||
#include "item.h"
|
||||
|
||||
struct Game {
|
||||
bool should_close;
|
||||
@ -33,6 +34,7 @@ struct Game {
|
||||
Words *words;
|
||||
Flags *flags;
|
||||
Actions *actions;
|
||||
Items *items;
|
||||
};
|
||||
|
||||
Game *game_create(void);
|
||||
|
95
01_text_adventure/item.c
Normal file
95
01_text_adventure/item.c
Normal file
@ -0,0 +1,95 @@
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "game.h"
|
||||
#include "room.h"
|
||||
#include "item.h"
|
||||
#include "util.h"
|
||||
|
||||
void load_item(Game *g, char *line) {
|
||||
char *token = strtok(line, "|");
|
||||
Item *item = &g->items->items[g->items->count];
|
||||
item->name = malloc(strlen(token) + 1);
|
||||
strcpy(item->name, token);
|
||||
|
||||
token = strtok(NULL, "|");
|
||||
item->indefinite = malloc(strlen(token) + 1);
|
||||
strcpy(item->indefinite, token);
|
||||
|
||||
token = strtok(NULL, "|");
|
||||
item->pickuppable = strcmp("true", token) == 0;
|
||||
|
||||
token = strtok(NULL, "|");
|
||||
item->description = malloc(strlen(token) + 1);
|
||||
strcpy(item->description, token);
|
||||
|
||||
item->in_inventory = false;
|
||||
item->location = NULL;
|
||||
|
||||
g->items->count++;
|
||||
}
|
||||
|
||||
#include "data/items.c"
|
||||
void game_load_items(Game *g) {
|
||||
g->items = malloc(sizeof(Items));
|
||||
g->items->count = 0;
|
||||
parse_multiline_string(g, data_items_txt, &load_item);
|
||||
printf("loaded items\n");
|
||||
}
|
||||
|
||||
#define ITEM_IN_ROOM "There is %s here."
|
||||
void log_item_in_room(Game *g, Item *i) {
|
||||
char *response = malloc(strlen(ITEM_IN_ROOM) + strlen(i->indefinite) + 1);
|
||||
sprintf(response, ITEM_IN_ROOM, i->indefinite);
|
||||
push_line_to_log(g->input->log, response);
|
||||
free(response);
|
||||
}
|
||||
|
||||
#define ITEM_IN_INVENTORY "You have %s."
|
||||
void log_item_in_inventory(Game *g, Item *i) {
|
||||
char *response = malloc(strlen(ITEM_IN_INVENTORY) + strlen(i->indefinite) + 1);
|
||||
sprintf(response, ITEM_IN_INVENTORY, i->indefinite);
|
||||
push_line_to_log(g->input->log, response);
|
||||
free(response);
|
||||
}
|
||||
|
||||
void log_items_in_room(Game *g, Room *r) {
|
||||
for (int i = 0; i < g->items->count; i++) {
|
||||
if (g->items->items[i].location == r) log_item_in_room(g, &g->items->items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Item *find_item(Items *items, char *item_name) {
|
||||
for (int i = 0; i < items->count; i++) {
|
||||
if (strcmp(items->items[i].name, item_name) == 0) return &items->items[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void take_item(Game *g, char *item_name) {
|
||||
Item *item = find_item(g->items, item_name);
|
||||
item->location = NULL;
|
||||
item->in_inventory = true;
|
||||
}
|
||||
|
||||
void drop_item(Game *g, char *item_name) {
|
||||
Item *item = find_item(g->items, item_name);
|
||||
item->location = g->current_room;
|
||||
item->in_inventory = false;
|
||||
}
|
||||
|
||||
void check_inventory(Game *g) {
|
||||
bool empty = true;
|
||||
for (int i = 0; i < g->items->count; i++) {
|
||||
if (g->items->items[i].in_inventory) {
|
||||
empty = false;
|
||||
log_item_in_inventory(g, &g->items->items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
push_line_to_log(g->input->log, "Your inventory is empty.");
|
||||
}
|
||||
}
|
31
01_text_adventure/item.h
Normal file
31
01_text_adventure/item.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef _FD_ITEM_
|
||||
#define _FD_ITEM_
|
||||
|
||||
typedef struct Item Item;
|
||||
typedef struct Items Items;
|
||||
|
||||
#include "game.h"
|
||||
#include "room.h"
|
||||
|
||||
struct Item {
|
||||
char *name;
|
||||
char *indefinite;
|
||||
bool pickuppable;
|
||||
char *description;
|
||||
bool in_inventory;
|
||||
Room *location;
|
||||
};
|
||||
|
||||
struct Items {
|
||||
Item items[200];
|
||||
int count;
|
||||
};
|
||||
|
||||
void game_load_items(Game *g);
|
||||
void log_items_in_room(Game *g, Room *r);
|
||||
Item *find_item(Items *items, char *item_name);
|
||||
void take_item(Game *g, char *item_name);
|
||||
void drop_item(Game *g, char *item_name);
|
||||
void check_inventory(Game *g);
|
||||
|
||||
#endif
|
@ -3,6 +3,7 @@
|
||||
#include <string.h>
|
||||
#include "game.h"
|
||||
#include "flag.h"
|
||||
#include "item.h"
|
||||
#include "predicate.h"
|
||||
|
||||
bool predicate_fulfilled(Game *g, Predicate *p) {
|
||||
@ -11,6 +12,10 @@ bool predicate_fulfilled(Game *g, Predicate *p) {
|
||||
return true;
|
||||
case PREDICATE_IN_ROOM:
|
||||
return strcmp(g->current_room->name, p->argument) == 0;
|
||||
case PREDICATE_ITEM_HERE:
|
||||
return find_item(g->items, p->argument)->location == g->current_room;
|
||||
case PREDICATE_HAS_ITEM:
|
||||
return find_item(g->items, p->argument)->in_inventory;
|
||||
case PREDICATE_FLAG_ENABLED:
|
||||
return flag_value(g->flags, p->argument) > 0;
|
||||
default:
|
||||
@ -33,6 +38,16 @@ Predicate *create_predicate(Game *g, const char *string) {
|
||||
token = strtok_r(NULL, ")", &strtok_guy);
|
||||
p->argument = malloc(strlen(token) + 1);
|
||||
strcpy(p->argument, token);
|
||||
} else if (strcmp(token, "ITEM_HERE") == 0) {
|
||||
p->type = PREDICATE_ITEM_HERE;
|
||||
token = strtok_r(NULL, ")", &strtok_guy);
|
||||
p->argument = malloc(strlen(token) + 1);
|
||||
strcpy(p->argument, token);
|
||||
} else if (strcmp(token, "HAS_ITEM") == 0) {
|
||||
p->type = PREDICATE_HAS_ITEM;
|
||||
token = strtok_r(NULL, ")", &strtok_guy);
|
||||
p->argument = malloc(strlen(token) + 1);
|
||||
strcpy(p->argument, token);
|
||||
} else if (strcmp(token, "ENABLED") == 0) {
|
||||
p->type = PREDICATE_FLAG_ENABLED;
|
||||
token = strtok_r(NULL, ")", &strtok_guy);
|
||||
@ -52,6 +67,12 @@ void print_predicate(Predicate *p) {
|
||||
case PREDICATE_IN_ROOM:
|
||||
printf("IN(%s)", p->argument);
|
||||
break;
|
||||
case PREDICATE_ITEM_HERE:
|
||||
printf("ITEM_HERE(%s)", p->argument);
|
||||
break;
|
||||
case PREDICATE_HAS_ITEM:
|
||||
printf("HAS_ITEM(%s)", p->argument);
|
||||
break;
|
||||
case PREDICATE_FLAG_ENABLED:
|
||||
printf("ENABLED(%s)", p->argument);
|
||||
break;
|
||||
|
@ -6,7 +6,8 @@ typedef struct Predicate Predicate;
|
||||
typedef enum PredicateType {
|
||||
PREDICATE_TRUE,
|
||||
PREDICATE_IN_ROOM,
|
||||
// PREDICATE_HAS_ITEM,
|
||||
PREDICATE_ITEM_HERE,
|
||||
PREDICATE_HAS_ITEM,
|
||||
PREDICATE_FLAG_ENABLED,
|
||||
} PredicateType;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user