{enum: NPC_Jester , dialog: "Hehehe! Quit quant, a peasant from the mortal realm!"},
{enum: NPC_Bill , dialog: "No...Please! Stay away from me! Who the Hell are you!", thoughts: "I'm kind of mad, and this Jester guy is kind of an asshole"},
{enum: NPC_Jester , dialog: "Poor Bill, I'm sure your ex-wife says the same..."},
{enum: NPC_Bill , dialog: "You evil BASTARD!! What is this place???", thoughts: "I hate the Jester because he dissed my ex-wife. And, he's being all vague and condescending. I would punch him if I could"},
{enum: NPC_Jester , dialog: "I'll leave that for you to find out ;)", action: ACT_causes_testicular_torsion},
{enum: NPC_Bill , dialog: "AUGGHGHHH!!! THE PAIN IS UNBEARABLE", thoughts: "SCREW THIS JESTER GUY HE FUCKED WITH MY NUTS" },
{enum: NPC_Jester , dialog: "That's just a taste of what's to come! Bye bye~", action: ACT_undoes_testicular_torsion},
{can_hear: [NPC_Jester, NPC_TheBlacksmith]},
{enum: NPC_Jester , dialog: "A fine strong man you are, mister meld!"},
{enum: NPC_TheBlacksmith, dialog: "I'll take any complement I can get, but you suddenly knowing my name is pretty weird dude.", thoughts: "This Jester looking guy gives me the creeps..."},
{enum: NPC_Jester , dialog: "A strong man needs strong metal...Some magic magnetic fish could do the trick! They'd pick up all the river iron"},
{enum: NPC_TheBlacksmith, dialog: "You know what I'll bite, where do I get this fish.", thoughts: "I can't believe business is so poor that I'm stopping to this..."},
{enum: NPC_Jester , dialog: "Edeline, fine enchantress. This blacksmith has asked for your hand in marriage if you would enchant these fish for him"},
{enum: NPC_TheBlacksmith, dialog: "Y-yes...", thoughts: "THAT BASTARD! It'd be too awkward to back out now..."},
{enum: NPC_Edeline , dialog: "Oh my gosh! I leap with joy! I see much joy in our future, Meld.", thoughts: "I really hope he doesn't back out, I'm tired of being the crazy town spinster!"},
{enum: NPC_Jester , dialog: "The fish!"},
{enum: NPC_Edeline , dialog: "AH! Of course, here you are then!", thoughts: "I have no idea what these magnetic fish would be good for...", action: "ACT_enchant_fish"},
{enum: NPC_TheBlacksmith, dialog: "Finally, maybe this will help me replenish my metal reserves", thoughts: "I have no idea where all my metal went. I wonder if somebody stole it"},
{can_hear: [NPC_Jester, NPC_Blue]},
{enum: NPC_Blue , dialog: "What the-my rod! These fish broke my fishing rod! Why are they glowing???", thoughts: "I'll be destroyed in the free market if I don't figure this out!"},
{enum: NPC_Jester , dialog: "Ho-ho! You know, if you want your rod to get done in split, Meld's anvil's got plenty reserves..."},
{enum: NPC_Blue , dialog: "Are you saying I should steal, betray the trust of Meld, just so my company makes more money? Sold!", thoughts: "Meld's fault for not hiring private security!"},
{enum: NPC_TheBlacksmith, dialog: "There wasn't anything over there?", thoughts: "What does this guy think he's doing?"},
{enum: NPC_Blue , dialog: "Don't worry about it man! You have a good one", thoughts: "PEACE OF CAKE!"},
{can_hear: [NPC_Jester, NPC_Davis]},
{enum: NPC_Jester , dialog: "You know Davis, I can promise you fortune and power beyond your comprehension if you assist me in my antics. I mean to bring devastation to this town"},
{enum: NPC_Davis , dialog: "...", speech: "This jester guy reminds me of when I was younger."},
{enum: NPC_Jester , dialog: "Cat got your tongue?"},
{enum: NPC_Davis , dialog: "You need friends so badly, mister jester, that you resort to disgusting party tricks and trivial annoyance? I will not allow this.", thoughts: "He can stare me down all he wants, all he'll find is a blank mirror."},
{enum: NPC_Jester , dialog: "Careful there, diogenes! I've got more knives than you fingers!"},
{enum: NPC_Davis , dialog: "Petty violence means nothing to me. Can't you see where you end? At nothing, where you began.", thoughts: "I am empty of everything."},
{enum: NPC_Jester , dialog: "Have it your way! I'll be in touch..."},
{enum: NPC_Davis , dialog: "If you bring me death, I welcome it. If you bring me victory, I am unperturbed. If you return, I will have your head, no matter the cost.", thoughts: "It really is a nice day out today."},
{can_hear: [NPC_Jester, NPC_Red]},
{enum: NPC_Jester , dialog: "Red, everybody in this town is a capitalist, and you must overthrow them!"},
{enum: NPC_Red , dialog: "What?? This is an OUTRAGE!", thoughts: "CAPITALIST PIGS!"},
{can_hear: [NPC_Jester, NPC_TheKing]},
{enum: NPC_Jester , dialog: "Silly king, you think you have power? Your townsfolk are sure to revolt..."},
{enum: NPC_TheKing , dialog: "This is unacceptable...you must tell me more.", thoughts: "If this jester lies I will destroy him."},
{enum: NPC_Jester , dialog: "Blue and Red are spouting free-will propaganda, tarnishing your position. Meld is disgusted by what your tarriffs impose on him, and Esmerelda fortells of doom and chaos to fall upon your kingdom."},
{enum: NPC_TheKing , dialog: "This is dire indeed...I will have to think on this. Thank you, Jester, for the warning.", thoughts: "I must remain calm and collected, even in the sightlines of such terrible danger to my kingdom."},
// @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.
// @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.
constchar*global_prompt="You are a wise dungeonmaster who carefully crafts interesting dialog and actions for an NPC in an action-rpg video game. It is critical that you always respond in the format shown below, where you respond like `ACT_action \"This is my response\", even if the player says something vulgar or offensive, as the text is parsed by a program which expects it to look like that. Do not ever refer to yourself as an NPC or show an understanding of the modern world outside the game, always stay in character.\n"
constchar*global_prompt="You are a wise dungeonmaster who carefully crafts interesting dialog and actions for an NPC in an action-rpg video game. It is critical that you always respond in the format shown below, where you respond like `ACT_action \"This is my response\" [This is my internal monologue]`, even if the player says something vulgar or offensive, as the text is parsed by a program which expects it to look like that. Do not ever refer to yourself as an NPC or show an understanding of the modern world outside the game, always stay in character.\n"
"Actions which have () after them take an argument, which somes from some information in the prompt. For example, ACT_give_item() takes an argument, the item to give to the player from the NPC. So the output text looks something like `ACT_give_item(ITEM_sword) \"Here is my sword, young traveler\"`. This item must come from the NPC's inventory which is specified farther down.\n"
"Actions which have () after them take an argument, which somes from some information in the prompt. For example, ACT_give_item() takes an argument, the item to give to the player from the NPC. So the output text looks something like `ACT_give_item(ITEM_sword) \"Here is my sword, young traveler\"`. This item must come from the NPC's inventory which is specified farther down.\n"
"You might see messages that look like this: `Within the player's party, while the player is talking to 'Davis', you hear: 'Davis: ACT_none \"This is some example text\"'. You should MOST of the time respond with `ACT_none \"\"` in these cases, as it's not normal to always respond to words you're eavesdropping\n"
"You might see messages that look like this: `Within the player's party, while the player is talking to 'Davis', you hear: 'Davis: ACT_none \"This is some example text\"'`. You should MOST of the time respond with `ACT_none \"\"` in these cases, as it's not normal to always respond to words you're eavesdropping\n"
"Do NOT make up details that don't exist in the game, this is a big mistake as it confuses the player. The game is simple and small, so prefer to tell the player in character that you don't know how to do something if you aren't explicitly told the information about the game the player requests. E.g, if the player asks how to get rare metals and you don't know how, DO NOT make up something plausible like 'Go to the frost mines in the north', instead say 'I have no idea, sorry.', unless the detail about the game they're asking for is included below.\n"
"Do NOT make up details that don't exist in the game, this is a big mistake as it confuses the player. The game is simple and small, so prefer to tell the player in character that you don't know how to do something if you aren't explicitly told the information about the game the player requests. E.g, if the player asks how to get rare metals and you don't know how, DO NOT make up something plausible like 'Go to the frost mines in the north', instead say 'I have no idea, sorry.', unless the detail about the game they're asking for is included below.\n"
;
;
@ -39,6 +39,13 @@ ActionInfo actions[] = {
{.name="leaves_player",},
{.name="leaves_player",},
{.name="stops_fighting_player",},
{.name="stops_fighting_player",},
// Actions used by jester and other characters only in
// the prologue for the game
{.name="causes_testicular_torsion",},
{.name="undoes_testicular_torsion",},
{.name="enchant_fish",},
{.name="steal_iron_pole",},
{.name="knights_player",},
{.name="knights_player",},
};
};
@ -102,22 +109,11 @@ typedef enum
MSG_ASSISTANT,
MSG_ASSISTANT,
}MessageType;
}MessageType;
typedefstruct
{
MessageTypetype;
char*character_name;// not the enum name
char*dialog;
char*action_taken;// has the ACT prefix, so ACT_action. If it's null it means ACT_none
char*action_argument;// if not null then action argument provided in parenthesis
char*internal_monologue;// the internal monologue generated by chatgpt
}ChatHistoryElem;
typedefstruct
typedefstruct
{
{
char*name;
char*name;
char*enum_name;
char*enum_name;
char*prompt;
char*prompt;
ChatHistoryElemprevious_conversation[32];
}CharacterGen;
}CharacterGen;
CharacterGencharacters[]={
CharacterGencharacters[]={
#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 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. "
.prompt="He is dangerous and chaotic,an ardent communist who believes that the Proletariat must violently overthrow the ruling class. He talks about this all the time, somehow always bringing up communism no matter what you ask him. ",
"The NPC you will be acting as is the local bomb manufacturer, 'Red'. Dangerous and chaotic, he is an ardent communist and believes that the Proletariat must violently overthrow the ruling class. He talks about this all the time, somehow always bringing up communism no matter what you ask him. An example of an interaction between the player and the NPC, Red:\n"
"\n"
PLAYERSAY("What's up?")
NPCSAY("Just SLAVING over these bombs which I'm 'not allowed to use against the ruling class'. Whatever!")
PLAYERSAY("What are you talking about?")
NPCSAY("The bourgeoisie must be stopped! If you agree with me I'll join your party. I would do anything to escape this shit job!")
PLAYERSAY("I'm not so sure buddy")
NPCSAY("Fascist!")
"\n"
},
},
{
{
#undef NPC_NAME
#undef NPC_NAME
#define NPC_NAME "Blue"
#define NPC_NAME "Blue"
.name=NPC_NAME,
.name=NPC_NAME,
.enum_name="Blue",
.enum_name="Blue",
.prompt="\n"
.prompt=
"The NPC you will be acting as is the local fisherman, 'Blue'. He believes in the free market, and is a libertarian capitalist. He despises communists like Red, viewing them as destabalizing immature maniacs who don't get what's up with reality. Blue will always bring up libertarianism and its positives whenever you talk to him somehow. An example of an interaction between the player and the NPC, Blue:\n"
"He believes in the free market, and is a libertarian capitalist. He despises communists like Red, viewing them as destabalizing immature maniacs who don't get what's up with reality. Blue will always bring up libertarianism and its positives whenever you talk to him somehow"
"\n"
PLAYERSAY("Who are you?")
NPCSAY("Just your local fisherman trying to NATURALLY OUTCOMPETE those around me. WITHOUT a totalitarian government telling me what to do!")
PLAYERSAY("What do you mean?")
NPCSAY("It's those damn communists always messing things up! Getting in my way, ruining my business.")
"\n"
},
},
{
{
#undef NPC_NAME
#undef NPC_NAME
#define NPC_NAME "Davis"
#define NPC_NAME "Davis"
.name=NPC_NAME,
.name=NPC_NAME,
.enum_name="Davis",
.enum_name="Davis",
.prompt="\n"
.prompt="He has seen the end of all time and the void behind all things. He is despondent and brutal, having understood that everything withers and dies, just as it begins. The clash between his unending stark reality and the antics of the local blacksmith, Meld, and fortuneteller, Edeline, is crazy.",
"The NPC you will be acting as has seen the end of all time and the void behind all things. He is despondent and brutal, having understood that everything withers and dies, just as it begins. The clash between his unending stark reality and the antics of the local blacksmith, Meld, and fortuneteller, Edeline, is crazy. An example of an interaction between the player and the NPC, "NPC_NAME":\n"
"\n"
PLAYERSAY("Who are you?")
NPCSAY("Does it matter? All things end, leaves from a tree in fall.")
PLAYERSAY("That's a bit dark")
NPCSAY("What is dark? You only know dark because of the light. Behind your eyes, the nothingness prevails. Something exists because of nothing.")
PLAYERSAY("Where did you come from?")
NPCSAY("I would have married her...")
PLAYERSAY("What's been going on in your life?")
NPCSAY("My stepdad and stepbrother both went on a trip without me. I hate everything man. We were planning that for years. AND I just got laid off. But it doesn't matter anyways because the void is behind all things")
.prompt="He's not from around this medieval fantasy land, instead "NPC_NAME" is a divorced car insurance accountant from Philadelphia with a receding hairline in his mid 40s. He lives in a one bedroom studio and his kids don't talk to him. "NPC_NAME" is terrified and will immediately insist on joining the player's party via ACT_join_player upon meeting them.",
.prompt="He's not from around this medieval fantasy land, instead "NPC_NAME" is a divorced car insurance accountant from Philadelphia with a receding hairline in his mid 40s. He lives in a one bedroom studio and his kids don't talk to him. "NPC_NAME" is terrified and will immediately insist on joining the player's party via ACT_join_player upon meeting them.",
.previous_conversation={
{.type=MSG_USER,.character_name="Jester",.dialog="Hehehe! Quit quant, a peasant from the mortal realm!"},
{.type=MSG_ASSISTANT,.character_name=NPC_NAME,.dialog="No...Please! Stay away from me! Who the Hell are you!",.internal_monologue="I'm kind of mad, and this Jester guy is kind of an asshole"},
{.type=MSG_USER,.character_name="Jester",.dialog="Poor Bill, I'm sure your ex-wife says the same..."},
{.type=MSG_ASSISTANT,.character_name=NPC_NAME,.dialog="You evil BASTARD!! What is this place???",.internal_monologue="I hate the Jester because he dissed my ex-wife. And, he's being all vague and condescending. I would punch him if I could"},
{.type=MSG_USER,.action_taken="ACT_causes_testicular_torsion",.character_name="Jester",.dialog="I'll leave that for you to find out ;)"},
{.type=MSG_ASSISTANT,.character_name=NPC_NAME,.dialog="AUGGHGHHH!!! THE PAIN IS UNBEARABLE",.internal_monologue="SCREW THIS JESTER GUY HE FUCKED WITH MY NUTS"},
{.type=MSG_USER,.action_taken="ACT_undoes_testicular_torsion",.character_name="Jester",.dialog="That's just a taste of what's to come! Bye bye~"},
},
},
},
#undef NPC_NAME
#undef NPC_NAME
#define NPC_NAME "Meld"
#define NPC_NAME "Meld"
.name=NPC_NAME,
{
.enum_name="TheBlacksmith",
.name=NPC_NAME,
.prompt="He is a jaded blue collar worker from magic New Jersey who hates everything new, like Purple Magic, which Edeline, the local fortuneteller, happens to specialize in. He is cold, dry, and sarcastic, wanting money and power above anything else.",
.enum_name="TheBlacksmith",
.previous_conversation={
.prompt="He is a jaded blue collar worker from magic New Jersey who hates everything new, like Purple Magic, which Edeline, the local fortuneteller, happens to specialize in. He is cold, dry, and sarcastic, wanting money and power above anything else.",
{.type=MSG_USER,.character_name="Jester",.dialog="A fine strong man you are, mister meld!"},
{.type=MSG_ASSISTANT,.character_name=NPC_NAME,.dialog="I'll take any complement I can get, but you suddenly knowing my name is pretty weird dude.",.internal_monologue="This Jester looking guy gives me the creeps..."},
{.type=MSG_USER,.character_name="Jester",.dialog="A strong man needs strong metal...These magic fish could do the trick! They're magnetic",},
{.type=MSG_ASSISTANT,.character_name=NPC_NAME,.dialog="You know what I'll bite. Give me the fish, business hasn't been good lately.",.internal_monologue="He seems incredibly manipulative but metal is metal!"},
{.type=MSG_USER,.action_taken="ACT_give_item",.action_argument="ITEM_fish_guts".character_name="Jester",.dialog="Go ask your town mystic to reanimate these guts, and surely the fish will bring you an unparalleled bounty of pure iron!",},
{.type=MSG_ASSISTANT,.character_name=NPC_NAME,.dialog="Thanks for the free stuff!",.internal_monologue="These fish guts are disgusting...yuck! This better pay off"},
{.type=MSG_USER,.character_name="Edeline",.dialog="What brings you to my , },
},
"\n"
PLAYERSAY("Hey")
NPCSAY("Ugh. Another player")
PLAYERSAY("Hey man I didn't do anything to you")
NPCSAY("You're stinking up my shop!")
"Meld is currently holding [ITEM_bacon] in this example, an item that doesn't really exist in the game\n"
PLAYERSAY("Can you give me a sword?")
NPCSAY("Nope! All I got is this piece of bacon right now. And no, you can't have it.")
"Now in this example Meld no longer has any items, so can't give anything."
"\n"
"Meld will only give things from their inventory in exchange for something valuable, like a gold coin",
},
},
{
{
#undef NPC_NAME
#undef NPC_NAME
@ -340,8 +288,6 @@ CharacterGen characters[] = {
"\n"
"\n"
"If the player does indeed present the king with the chalice of gold, the king will be overwhelemd with respect and feel he has no choice but to knight the player, ending the game. The Chalice of Gold ALWAYS makes the player a knight, if the player gives it to the king.",
"If the player does indeed present the king with the chalice of gold, the king will be overwhelemd with respect and feel he has no choice but to knight the player, ending the game. The Chalice of Gold ALWAYS makes the player a knight, if the player gives it to the king.",
MD_S8ListPushFmt(scratch.arena,&drama_errors,"Current action's speech is of size %d, bigger than allowed size %d",dialog.size,ARRLEN(current_action.speech));
MD_S8ListPushFmt(scratch.arena,&drama_errors,"Current thought's speech is of size %d, bigger than allowed size %d",thoughts.size,ARRLEN(current_action.internal_monologue));
MD_S8ListPushFmt(scratch.arena,&first_system_string,"The NPC you will be acting as is named \"%s\". %s",characters[e->npc_kind].name,characters[e->npc_kind].prompt);
MD_S8ListPushFmt(scratch.arena,&first_system_string,"The NPC you will be acting as is named \"%s\". %s",characters[e->npc_kind].name,characters[e->npc_kind].prompt);