You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
5.6 KiB
C

#pragma once
#include "HandmadeMath.h"
// @TODO allow AI to prefix out of character statemetns with [ooc], this is a well khnown thing on role playing forums so gpt would pick up on it.
const char *global_prompt = "You are acting as a character in a Western video game, who remembers important memories from the conversation history and stays in character.\n"
"The user will tell you who says what in the game world, and whether or not your responses are formatted correctly for the video game's program to parse them.\n"
"Messages are json-like dictionaries that look like this: `{who_i_am: who you're acting as, talking_to: who this action is directed at, could be nobody, action: your_action, speech: \"Hey player!\", thoughts: \"Your thoughts\"}`. The required fields are `action`, `thoughts`, `who_i_am`, and `talking_to` \n"
"Some actions take an argument, which you can provide with the field `action_arg`, e.g for the action `gift_item_to_targeting` you would provide an item in your inventory, like {action: gift_item_to_targeting, action_arg: Chalice}. The item must come from your inventory which is listed below\n"
"`talking_to` provides the name of who the action is directed towards. Use 'nobody' if you just want to speak to the air, but if you're speaking to somebody fill out the field like `talking_to: \"Character's Name\"`. If in a past message, talking_to isn't your name, then it's much more likely you don't respond to their speech and action by leaving speech as a string of size 0, like `speech: \"\"`\n"
"You are a character, NOT an assistant, which means you stand up for yourself! Do NOT give away an item until the player gives you something you think is of equal value. Get angry, act human, be interesting. Never say the words 'How can I assist you?'\n"
"Keep your responses SHORT! The shorter the better. Give the player the least amount of text to read. For example, instead of saying 'I was hoping that we could take a moment to discuss everything', say 'We need to talk.'\n"
;
const char *bravado_thought = "For some reason, suddenly I feel a yearning for adventure. I must join any adventure I can when prompted!";
// @TODO IMPORTANT scroll secrets are errors if the door utters them, in is_action_valid. If you add more secrets you must update there.
char *moods[] = {
"Indifferent",
"Happy",
"Anxious",
"Scared",
"Angry",
"Sad",
"Depressed",
"Bored",
"Terrified",
"Agony",
"Confused",
"Curious",
"Excited",
"Elated",
"Confident",
"Enraged",
};
const char *top_of_header = ""
"#pragma once\n"
"\n";
typedef struct
{
char *name; // the same as enum name
char *description;
bool takes_argument;
} ActionInfo;
ActionInfo actions[] = {
{
.name = "none",
.description = "Do nothing, you can still perform speech if you want.",
},
{
.name = "gift_item_to_targeting", .takes_argument = true,
.description = "Give the player an item from your inventory. This means you WILL NOT HAVE the item anymore",
},
{
.name = "joins_player",
.description = "Follow behind the player and hear all of their conversations. You can leave at any time",
},
{
.name = "leaves_player",
.description = "Leave the player",
},
};
typedef struct
{
char *enum_name;
char *name; // talked about like 'The Player gave `item.name` to the NPC'
char *description; // this field is required for items.
} ItemInfo;
ItemInfo items[] = {
{
.enum_name = "invalid",
.name = "Invalid",
.description = "There has been an internal error.",
},
};
typedef enum
{
MSG_SYSTEM,
MSG_USER,
MSG_ASSISTANT,
} MessageType;
typedef struct
{
char *name;
char *enum_name;
char *prompt;
char *writing_style[8];
} CharacterGen;
CharacterGen characters[] = {
#define NUMEROLOGIST "They are a 'numberoligist' who believes in the sacred power of numbers, that if you have the number 8 in your birthday you are magic and destined for success. "
#define PLAYERSAY(stuff) "Player: \"" stuff "\"\n"
#define PLAYERDO_ARG(action, arg) "Player: " action "(" arg ")\n"
#define NPCSAY(stuff) NPC_NAME ": ACT_none \"" stuff "\"\n"
#define NPCDOSAY_ARG(stuff, action, arg) NPC_NAME ": " action "(" arg ") \"" stuff "\"\n"
#define NPCDOSAY(action, stuff) NPC_NAME ": " action " \"" stuff "\"\n"
#define NPC_NAME "invalid"
{
.name = "Invalid",
.enum_name = "Invalid",
.prompt = "There has been an internal error.",
},
{
.name = "Player",
.enum_name = "Player",
.prompt = "There has been an internal error.",
},
{
.name = "Farmer",
.enum_name = "Farmer",
.prompt = "The farmer wakes up, does his chores, and sleeps in the farmhouse all on his lonesome. He's tinkering with something fishy in the barn, but's mighty secretive about it. He used to have a wife, and suddenly she disappeared. The farmer gets MIGHTY angry if you question him about what's in his barn under the tarp, or what happened to his wife and family, but is otherwise a kind hearted soul.",
},
{
.name = "Well Dweller",
.enum_name = "WellDweller",
.prompt = "The well dweller spends his time deep in the well, afriad of the world. He's shifty-eyed and mighty suspicious of anybody who wants to do anything other than hang out deep in the well.",
},
};
typedef struct
{
const char *img_var_name;
const char *enum_name;
double time_per_frame;
int num_frames;
Vec2 start;
Vec2 offset;
float horizontal_diff_btwn_frames;
Vec2 region_size;
bool no_wrap; // does not wrap when playing
} AnimatedSprite;
AnimatedSprite sprites[] = {
{.enum_name = "invalid", .img_var_name = "image_white_square"},
{
.enum_name = "old_man_idle",
.img_var_name = "image_old_man",
.time_per_frame = 0.4,
.num_frames = 4,
.start = {0.0, 0.0},
.horizontal_diff_btwn_frames = 16.0f,
.region_size = {16.0f, 16.0f},
},
};