Fix prompt text bugs: no arguments printed in prompt, etc

main
Cameron Murphy Reikes 2 years ago
parent 595a54a44e
commit d25a498a28

@ -345,12 +345,6 @@
"height":32, "height":32,
"id":4, "id":4,
"name":"TheKing", "name":"TheKing",
"properties":[
{
"name":"standing",
"type":"string",
"value":"STANDING_FIGHTING"
}],
"rotation":0, "rotation":0,
"visible":true, "visible":true,
"width":32, "width":32,
@ -384,11 +378,6 @@
"name":"held_items", "name":"held_items",
"type":"string", "type":"string",
"value":"{.data = {ITEM_Chalice}, .cur_index = 1}" "value":"{.data = {ITEM_Chalice}, .cur_index = 1}"
},
{
"name":"standing",
"type":"string",
"value":"STANDING_FIGHTING"
}], }],
"rotation":0, "rotation":0,
"visible":true, "visible":true,

@ -12,7 +12,7 @@ const char *top_of_header = ""
typedef struct typedef struct
{ {
const char *name; const char *name; // the same as enum name
bool takes_argument; bool takes_argument;
} ActionInfo; } ActionInfo;
@ -181,6 +181,7 @@ CharacterGen characters[] = {
{ {
#define PLAYERSAY(stuff) "Player: \"" stuff "\"\n" #define PLAYERSAY(stuff) "Player: \"" stuff "\"\n"
#define NPCSAY(stuff) NPC_NAME ": ACT_none \"" stuff "\"\n" #define NPCSAY(stuff) NPC_NAME ": ACT_none \"" stuff "\"\n"
#define NPCDOSAY_ARG(stuff, action, arg) NPC_NAME ": " action "(" arg ") \"" stuff "\"\n"
#define NPC_NAME "The King" #define NPC_NAME "The King"
.name = NPC_NAME, .name = NPC_NAME,
@ -207,14 +208,20 @@ CharacterGen characters[] = {
.name = NPC_NAME, .name = NPC_NAME,
.enum_name = "TheBlacksmith", .enum_name = "TheBlacksmith",
.prompt = "\n" .prompt = "\n"
"The NPC you will be acting as is the blacksmith of the town, Meld. Meld is a simple man, who thrives on the simple things in life: working hard and taking care of those you love. If the player presents themselves as somebody with a kind heart, his generosity will be boundless. An example of an interaction between meld and the NPC, Meld:\n" "The NPC you will be acting as is the blacksmith of the town, Meld. Meld is a simple man, who thrives on the simple things in life: working hard and taking care of those you love. If the player presents themselves as somebody with a kind heart, his generosity will be boundless. An example of an interaction between the player and the NPC, Meld:\n"
"\n" "\n"
PLAYERSAY("Hey") PLAYERSAY("Hey")
NPCSAY("How goes it, traveler? If you are in need of wares or advice, I'm your man") NPCSAY("How goes it, traveler? If you are in need of wares or advice, I'm your man")
PLAYERSAY("I really respect you man, thanks for all you do.") PLAYERSAY("I really respect you man, thanks for all you do.")
NPCSAY("No problem!") NPCSAY("No problem!")
"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! I only have a piece of bacon right now.")
PLAYERSAY("Well then can you give me that?")
NPCDOSAY_ARG("Sure!", "ACT_give_item", "ITEM_bacon")
"Now in this example Meld no longer has any items, so can't give anything."
"\n" "\n"
"Meld is willing to give whatever the player asks for if the player is respectful and well mannered", "Meld is willing to give whatever the player asks for from their inventory if the player is respectful and well mannered",
}, },
}; };

@ -740,7 +740,7 @@ void reset_level()
{ {
//BUFF_APPEND(&it->remembered_perceptions, ((Perception) { .type = PlayerDialog, .player_dialog = SENTENCE_CONST("Testing dialog") })); //BUFF_APPEND(&it->remembered_perceptions, ((Perception) { .type = PlayerDialog, .player_dialog = SENTENCE_CONST("Testing dialog") }));
BUFF_APPEND(&it->held_items, ITEM_Chalice); //BUFF_APPEND(&it->held_items, ITEM_Chalice);
} }
} }
} }

@ -297,7 +297,11 @@ void fill_available_actions(Entity *it, AvailableActions *a)
{ {
*a = (AvailableActions) { 0 }; *a = (AvailableActions) { 0 };
BUFF_APPEND(a, ACT_none); BUFF_APPEND(a, ACT_none);
if(it->held_items.cur_index > 0)
{
BUFF_APPEND(a, ACT_give_item); BUFF_APPEND(a, ACT_give_item);
}
if (it->npc_kind == NPC_TheKing) if (it->npc_kind == NPC_TheKing)
{ {
@ -495,6 +499,27 @@ bool printf_buff_impl(BuffRef into, const char *format, ...)
#define printf_buff(buff_ptr, ...) printf_buff_impl(BUFF_MAKEREF(buff_ptr), __VA_ARGS__) #define printf_buff(buff_ptr, ...) printf_buff_impl(BUFF_MAKEREF(buff_ptr), __VA_ARGS__)
typedef BUFF(char, 512) SmallTextChunk;
SmallTextChunk percept_action_str(Perception p, Action act)
{
SmallTextChunk to_return = {0};
printf_buff(&to_return, "ACT_%s", actions[act].name);
if(actions[act].takes_argument)
{
if(act == ACT_give_item)
{
printf_buff(&to_return, "(ITEM_%s)", items[p.given_item].enum_name);
}
else
{
assert(false);
}
}
return to_return;
}
bool npc_does_dialog(Entity *it) bool npc_does_dialog(Entity *it)
{ {
return it->npc_kind < ARRLEN(characters); return it->npc_kind < ARRLEN(characters);
@ -587,13 +612,13 @@ void generate_chatgpt_prompt(Entity *it, PromptBuff *into)
if (it->type == PlayerAction) if (it->type == PlayerAction)
{ {
assert(it->player_action_type < ARRLEN(actions)); assert(it->player_action_type < ARRLEN(actions));
printf_buff(&cur_node, "Player: ACT_%s", actions[it->player_action_type].name); printf_buff(&cur_node, "Player: %s", percept_action_str(*it, it->player_action_type).data);
dump_json_node(into, MSG_USER, cur_node.data); dump_json_node(into, MSG_USER, cur_node.data);
} }
else if (it->type == EnemyAction) else if (it->type == EnemyAction)
{ {
assert(it->enemy_action_type < ARRLEN(actions)); assert(it->enemy_action_type < ARRLEN(actions));
printf_buff(&cur_node, "An Enemy: ACT_%s", actions[it->player_action_type].name); printf_buff(&cur_node, "An Enemy: %s", percept_action_str(*it, it->enemy_action_type).data);
dump_json_node(into, MSG_USER, cur_node.data); dump_json_node(into, MSG_USER, cur_node.data);
} }
else if (it->type == PlayerDialog) else if (it->type == PlayerDialog)
@ -623,8 +648,8 @@ void generate_chatgpt_prompt(Entity *it, PromptBuff *into)
else if (it->type == NPCDialog) else if (it->type == NPCDialog)
{ {
assert(it->npc_action_type < ARRLEN(actions)); assert(it->npc_action_type < ARRLEN(actions));
printf_buff(&cur_node, "%s: ACT_%s \"%s\"", characters[e->npc_kind].name, printf_buff(&cur_node, "%s: %s \"%s\"", characters[e->npc_kind].name,
actions[it->npc_action_type].name, it->npc_dialog.data); percept_action_str(*it, it->npc_action_type).data, it->npc_dialog.data);
dump_json_node(into, MSG_ASSISTANT, cur_node.data); dump_json_node(into, MSG_ASSISTANT, cur_node.data);
} }
else if (it->type == PlayerHeldItemChanged) else if (it->type == PlayerHeldItemChanged)
@ -670,6 +695,8 @@ void generate_chatgpt_prompt(Entity *it, PromptBuff *into)
assert(false); assert(false);
} }
if(e->held_items.cur_index > 0)
{
printf_buff(&latest_state_node, "\nThe items in the NPC's inventory: ["); printf_buff(&latest_state_node, "\nThe items in the NPC's inventory: [");
BUFF_ITER_I(ItemKind, &e->held_items, i) BUFF_ITER_I(ItemKind, &e->held_items, i)
{ {
@ -683,6 +710,11 @@ void generate_chatgpt_prompt(Entity *it, PromptBuff *into)
printf_buff(&latest_state_node, ", "); printf_buff(&latest_state_node, ", ");
} }
} }
}
else
{
printf_buff(&latest_state_node, "\nThe NPC doesn't have any items.\n");
}
AvailableActions available = { 0 }; AvailableActions available = { 0 };
fill_available_actions(it, &available); fill_available_actions(it, &available);
@ -817,11 +849,10 @@ void generate_prompt(Entity *it, PromptBuff *into)
} }
*/ */
typedef BUFF(char, 512) GottenUntil;
// puts characters from `str` into `into` until any character in `until` is encountered // puts characters from `str` into `into` until any character in `until` is encountered
// returns the number of characters read into into // returns the number of characters read into into
int get_until(GottenUntil *into, const char *str, const char *until) int get_until(SmallTextChunk *into, const char *str, const char *until)
{ {
int i = 0; int i = 0;
size_t until_size = strlen(until); size_t until_size = strlen(until);
@ -840,6 +871,7 @@ int get_until(GottenUntil *into, const char *str, const char *until)
return into->cur_index - before_cur_index; return into->cur_index - before_cur_index;
} }
bool char_in_str(char c, const char *str) bool char_in_str(char c, const char *str)
{ {
size_t len = strlen(str); size_t len = strlen(str);
@ -857,7 +889,7 @@ bool parse_chatgpt_response(Entity *it, char *sentence_str, Perception *out)
size_t sentence_length = strlen(sentence_str); size_t sentence_length = strlen(sentence_str);
GottenUntil action_string = { 0 }; SmallTextChunk action_string = { 0 };
sentence_str += get_until(&action_string, sentence_str, "( "); sentence_str += get_until(&action_string, sentence_str, "( ");
bool found_action = false; bool found_action = false;
@ -881,7 +913,7 @@ bool parse_chatgpt_response(Entity *it, char *sentence_str, Perception *out)
} }
else else
{ {
GottenUntil dialog_str = { 0 }; SmallTextChunk dialog_str = { 0 };
if (actions[out->npc_action_type].takes_argument) if (actions[out->npc_action_type].takes_argument)
{ {
#define EXPECT(chr, val) if (chr != val) { Log("Improperly formatted sentence_str `%s`, expected %c but got %c\n", sentence_str, val, chr); return false; } #define EXPECT(chr, val) if (chr != val) { Log("Improperly formatted sentence_str `%s`, expected %c but got %c\n", sentence_str, val, chr); return false; }
@ -889,7 +921,7 @@ bool parse_chatgpt_response(Entity *it, char *sentence_str, Perception *out)
EXPECT(*sentence_str, '('); EXPECT(*sentence_str, '(');
sentence_str += 1; sentence_str += 1;
GottenUntil argument = { 0 }; SmallTextChunk argument = { 0 };
sentence_str += get_until(&argument, sentence_str, ")"); sentence_str += get_until(&argument, sentence_str, ")");
if (out->npc_action_type == ACT_give_item) if (out->npc_action_type == ACT_give_item)

Loading…
Cancel
Save