Skip to content

Instantly share code, notes, and snippets.

@rhmoller
Last active December 25, 2024 21:40
Show Gist options
  • Save rhmoller/00d92aa81f7a4a07ac8ba70a34cf52cd to your computer and use it in GitHub Desktop.
Save rhmoller/00d92aa81f7a4a07ac8ba70a34cf52cd to your computer and use it in GitHub Desktop.
A small adventure game written to explore the C3 language
// compile and run with
// c3c compile-run adventure.c3
import std::ascii;
import std::collections;
import std::io;
struct Item
{
String name;
String description;
}
def ListItem = List(<Item>);
struct Room
{
String name;
String description;
int[4] doors;
ListItem items;
}
const Room[] ROOMS =
{
{
"The Void",
"You should not be able to get here",
{0, 0, 0, 0},
{}
},
{
"Room 1",
"There is a door to the north.",
{2, 0, 0, 0},
{}
},
{
"Room 2",
"There is a door to the south.",
{0, 1, 0, 0},
{}
}
};
const Item[][] ROOM_ITEMS = {
{},
{
{"key", "A rusty old key"},
{"torchlight", "A neat torchlight"}
},
{}
};
int current_room = 1;
ListItem inventory;
fn void initialize_world()
{
foreach (i, &room : ROOMS)
{
Item[] items = ROOM_ITEMS[i];
foreach (item : items)
{
room.items.push(item);
}
}
}
fn void enter_room(int room)
{
current_room = room;
describe_room();
}
fn void describe_room()
{
Room* room = &ROOMS[current_room];
io::printfn("You are in %s", room.name);
io::printn(room.description);
ListItem items = room.items;
if (items.len() > 0)
{
io::printn("You see:");
for (int i = 0; i < items.len(); i++)
{
io::printfn(" %s", items[i].name);
}
} else {
io::printn("There is nothing here.");
}
}
fn void enter_door(int direction)
{
Room* room = &ROOMS[current_room];
int door = room.doors[direction];
if (door != 0)
{
enter_room(door);
}
else
{
io::printn("You can't go that way.");
}
}
fn void take_item(String name)
{
Room* room = &ROOMS[current_room];
foreach (i, item : room.items)
{
if (item.name == name)
{
inventory.push(item);
room.items.remove_at(i);
io::printfn("You take the %s", name);
return;
}
}
io::printfn("There is no %s here.", name);
}
fn void examine_item(String name) {
foreach (i, item : inventory)
{
if (item.name == name)
{
io::printn(item.description);
return;
}
}
Room* room = &ROOMS[current_room];
foreach (i, item : room.items)
{
if (item.name == name)
{
io::printn(item.description);
return;
}
}
}
fn void drop_item(String name) {
foreach (i, item : inventory)
{
if (item.name == name)
{
Room* room = &ROOMS[current_room];
room.items.push(item);
inventory.remove_at(i);
io::printfn("You drop the %s", name);
return;
}
}
io::printfn("You are not carrying a %s.", name);
}
fn void describe_inventory()
{
if (inventory.len() == 0)
{
io::printn("You are not carrying anything.");
}
else
{
io::printn("You are carrying:");
for (int i = 0; i < inventory.len(); i++)
{
io::printfn(" %s", inventory[i].name);
}
}
}
fn void help()
{
io::printn("Available Commands: go <direction>, north, south, east, west, look, examine, take <item>, drop <item>, inventory, exit");
}
fn bool! next_cmd()
{
io::print("> ");
String command = io::treadline()!;
// todo: figure out how to convert command to lowercase
String[] tokens = command.tsplit(" ");
for (int i = 0; i < tokens.len; i++)
{
switch (tokens[i])
{
case "help":
help();
case "go":
continue;
case "north":
enter_door(0);
case "south":
enter_door(1);
case "east":
enter_door(2);
case "west":
enter_door(3);
case "look":
describe_room();
case "examine":
if (tokens.len < i + 2)
{
io::printn("You must specify an item to examine.");
continue;
}
examine_item(tokens[i + 1]);
i++;
case "take":
if (tokens.len < i + 2)
{
io::printn("You must specify an item to take.");
continue;
}
take_item(tokens[i + 1]);
i++;
case "drop":
if (tokens.len < i + 2)
{
io::printn("You must specify an item to drop.");
continue;
}
drop_item(tokens[i + 1]);
i++;
case "inventory":
describe_inventory();
case "exit":
case "quit":
case "bye":
io::printn("Goodbye!");
return false;
default:
io::printn("I don't understand that command.");
}
}
return true;
}
fn void! main()
{
mem::@report_heap_allocs_in_scope()
{
io::printn("Welcome to the Adventure Game!");
initialize_world();
enter_room(1);
bool running = true;
while (running)
{
@pool()
{
running = next_cmd()!;
};
}
inventory.free();
foreach (&room : ROOMS)
{
room.items.free();
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment