Giving items back and forth and REFORMAT EVERYTHING. SUCKS

main
parent dc1cb80ecd
commit d2e0f2596e

@ -0,0 +1,69 @@
<?xml version="1.0"?>
<N10X>
<Workspace>
<IncludeFilter>*.c,*.cc,*.cpp,*.c++,*.cp,*.cxx,*.h,*.hh,*.hpp,*.h++,*.hp,*.hxx,*.inl,*.cs,*.rs,*.java,*.jav,*.js,*.jsc,*.jsx,*.json,*.cls,*.py,*.rpy,*.php,*.php3,*.phl,*.phtml,*.rhtml,*.tpl,*.phps,*.lua,*.html,*.html5,*.htm,*.xml,*.xaml,*.css,*.ssi,*.haml,*.yaml,*.bat,*.wbf,*.wbt,*.txt,*.cmake,*.make,*.makefile,*.mak,*.mk,*.sh,*.bash,*.csv,*.asp,*.pl,*.mac,*.ws,*.vbs,*.perl,*.src,*.rss,*.inc,*.f,*.go,*.prl,*.plx,*.rb,*.lsp,*.lpx,*.ps1,*.command,*.cbl,*.cob,*.qs,*.wxs,*.ph,*.msc,*.glsl,*.hlsl,*.fx,*.vert,*.tesc,*.tese,*.geom,*.frag,*.comp,*.pssl,*.scons,*.cu,</IncludeFilter>
<ExcludeFilter></ExcludeFilter>
<SyncFiles>true</SyncFiles>
<Recursive>true</Recursive>
<ShowEmptyFolders>true</ShowEmptyFolders>
<IsVirtual>false</IsVirtual>
<IsFolder>false</IsFolder>
<BuildCommand></BuildCommand>
<RebuildCommand></RebuildCommand>
<BuildFileCommand></BuildFileCommand>
<CleanCommand></CleanCommand>
<BuildWorkingDirectory></BuildWorkingDirectory>
<CancelBuild></CancelBuild>
<RunCommand></RunCommand>
<RunCommandWorkingDirectory></RunCommandWorkingDirectory>
<DebugCommand></DebugCommand>
<ExePathCommand></ExePathCommand>
<DebugSln></DebugSln>
<UseVisualStudioEnvBat>false</UseVisualStudioEnvBat>
<Configurations>
<Configuration>Debug</Configuration>
<Configuration>Release</Configuration>
</Configurations>
<Platforms>
<Platform>x64</Platform>
<Platform>Win32</Platform>
</Platforms>
<AdditionalIncludePaths>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\ATLMFC\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\ATLMFC\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um</AdditionalIncludePath>
</AdditionalIncludePaths>
<Defines></Defines>
<ConfigProperties>
<ConfigAndPlatform>
<Name>Debug:x64</Name>
<Defines></Defines>
<ForceIncludes></ForceIncludes>
</ConfigAndPlatform>
<Config>
<Name>Debug</Name>
<Defines></Defines>
</Config>
<Platform>
<Name>x64</Name>
<Defines></Defines>
</Platform>
</ConfigProperties>
<Children></Children>
</Workspace>
</N10X>

@ -26,6 +26,10 @@
{ {
filepath: "boots.png", filepath: "boots.png",
} }
@image chalice:
{
filepath: "chalice_of_gold.png",
}
@image new_knight_idle: @image new_knight_idle:
{ {
filepath: "copyrighted/knight_idle.png", filepath: "copyrighted/knight_idle.png",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -380,6 +380,11 @@
"id":22, "id":22,
"name":"TheBlacksmith", "name":"TheBlacksmith",
"properties":[ "properties":[
{
"name":"held_items",
"type":"string",
"value":"{.data = {ITEM_Chalice}, .cur_index = 1}"
},
{ {
"name":"standing", "name":"standing",
"type":"string", "type":"string",

@ -53,6 +53,13 @@ ItemInfo items[] = {
.possess = "The player is no longer holding anything", .possess = "The player is no longer holding anything",
.discard = "The player is no longer holding nothing", .discard = "The player is no longer holding nothing",
}, },
{
.enum_name = "Chalice",
.name = "The Chalice of Gold",
.global_prompt = "The player is holding a glimmering Chalice of Gold. It is a beautiful object, mesmerizing in the light.",
.possess = "The player has ascertained the beautiful chalice of gold",
.discard = "The player no longer has the chalice of gold",
},
{ {
.enum_name = "WhiteSquare", .enum_name = "WhiteSquare",
.name = "the white square", .name = "the white square",

@ -19,7 +19,7 @@
void dump(MD_Node* from) { void dump(MD_Node* from) {
printf("/ %.*s\n", MD_S8VArg(from->string)); printf("/ %.*s\n", MD_S8VArg(from->string));
int d = 0; int d = 0;
for(MD_EachNode(child, from->first_child)) for (MD_EachNode(child, from->first_child))
{ {
printf("|-- Child %d Tag [%.*s] string[%.*s] first child string[%.*s]\n", d, MD_S8VArg(child->first_tag->string), MD_S8VArg(child->string), MD_S8VArg(child->first_child->string)); printf("|-- Child %d Tag [%.*s] string[%.*s] first child string[%.*s]\n", d, MD_S8VArg(child->first_tag->string), MD_S8VArg(child->string), MD_S8VArg(child->first_child->string));
d += 1; d += 1;
@ -27,9 +27,9 @@ void dump(MD_Node* from) {
} }
bool has_decimal(MD_String8 s) bool has_decimal(MD_String8 s)
{ {
for(int i = 0; i < s.size; i++) for (int i = 0; i < s.size; i++)
{ {
if(s.str[i] == '.') return true; if (s.str[i] == '.') return true;
} }
return false; return false;
} }
@ -58,8 +58,8 @@ char *nullterm(MD_String8 s) {
} }
char* fillnull(char *s, char c) { char* fillnull(char *s, char c) {
while(*s != '\0') { while (*s != '\0') {
if(*s == c) { if (*s == c) {
*s = '\0'; *s = '\0';
return s + 1; return s + 1;
} }
@ -78,7 +78,7 @@ MD_Node* find_by_name(Nodes *n, MD_String8 name)
MD_Node *node_with = 0; MD_Node *node_with = 0;
BUFF_ITER(MD_Node *, n) BUFF_ITER(MD_Node *, n)
{ {
if(StrSame((*it)->string, name)) if (StrSame((*it)->string, name))
{ {
assert(node_with == 0); assert(node_with == 0);
node_with = (*it); node_with = (*it);
@ -90,8 +90,8 @@ MD_Node* find_by_name(Nodes *n, MD_String8 name)
char* goto_end_of(char *tomove, size_t max_move, char *pattern) { char* goto_end_of(char *tomove, size_t max_move, char *pattern) {
size_t pattern_len = strlen(pattern); size_t pattern_len = strlen(pattern);
for(int i = 0; i < max_move; i++) { for (int i = 0; i < max_move; i++) {
if(strncmp(tomove, pattern, pattern_len) == 0) { if (strncmp(tomove, pattern, pattern_len) == 0) {
tomove += pattern_len; tomove += pattern_len;
return tomove; return tomove;
} }
@ -103,11 +103,11 @@ char* goto_end_of(char *tomove, size_t max_move, char *pattern) {
#define list_printf(list_ptr, ...) MD_S8ListPush(cg_arena, list_ptr, MD_S8Fmt(cg_arena, __VA_ARGS__)) #define list_printf(list_ptr, ...) MD_S8ListPush(cg_arena, list_ptr, MD_S8Fmt(cg_arena, __VA_ARGS__))
void dump_full(MD_Node* from) void dump_full(MD_Node* from)
{ {
for(MD_EachNode(node, from)) for (MD_EachNode(node, from))
{ {
printf("@%.*s %.*s\n", MD_S8VArg(node->first_tag->string), MD_S8VArg(node->string)); printf("@%.*s %.*s\n", MD_S8VArg(node->first_tag->string), MD_S8VArg(node->string));
} }
/* MD_String8List output_list = {0}; /* MD_String8List output_list = {0};
MD_DebugDumpFromNode(cg_arena, &output_list, from, 4, S8(" "), 0); MD_DebugDumpFromNode(cg_arena, &output_list, from, 4, S8(" "), 0);
MD_StringJoin join = (MD_StringJoin){0}; MD_StringJoin join = (MD_StringJoin){0};
MD_String8 debugged = MD_S8ListJoin(cg_arena, output_list , &join); MD_String8 debugged = MD_S8ListJoin(cg_arena, output_list , &join);
@ -131,14 +131,7 @@ int main(int argc, char **argv)
GEN_ENUM(ActionInfo, actions, "Action", it->name, "ACT_%s,\n"); GEN_ENUM(ActionInfo, actions, "Action", it->name, "ACT_%s,\n");
GEN_ENUM(ItemInfo, items, "ItemKind", it->enum_name, "ITEM_%s,\n"); GEN_ENUM(ItemInfo, items, "ItemKind", it->enum_name, "ITEM_%s,\n");
GEN_ENUM(AnimatedSprite, sprites, "AnimKind", it->enum_name, "ANIM_%s,\n"); GEN_ENUM(AnimatedSprite, sprites, "AnimKind", it->enum_name, "ANIM_%s,\n");
GEN_ENUM(CharacterGen, characters, "NpcKind", it->enum_name, "NPC_%s,\n");
fprintf(char_header, "typedef enum\n{\n");
ARR_ITER(CharacterGen, characters)
{
fprintf(char_header, " NPC_%s,\n", it->enum_name);
}
// characters enum can be extended at site of include, not ending the enum here
fclose(char_header); fclose(char_header);
@ -150,12 +143,12 @@ int main(int argc, char **argv)
MD_ParseResult parse = MD_ParseWholeFile(cg_arena, MD_S8Lit("assets.mdesk")); MD_ParseResult parse = MD_ParseWholeFile(cg_arena, MD_S8Lit("assets.mdesk"));
MD_String8List declarations_list = {0}; MD_String8List declarations_list = { 0 };
MD_String8List load_list = {0}; MD_String8List load_list = { 0 };
MD_String8List level_decl_list = {0}; MD_String8List level_decl_list = { 0 };
MD_String8List tileset_decls = {0}; MD_String8List tileset_decls = { 0 };
for(MD_EachNode(node, parse.node->first_child)) { for (MD_EachNode(node, parse.node->first_child)) {
if(MD_S8Match(node->first_tag->string, MD_S8Lit("sound"), 0)) { if (MD_S8Match(node->first_tag->string, MD_S8Lit("sound"), 0)) {
MD_String8 variable_name = MD_S8Fmt(cg_arena, "sound_%.*s", MD_S8VArg(node->string)); MD_String8 variable_name = MD_S8Fmt(cg_arena, "sound_%.*s", MD_S8VArg(node->string));
Log("New sound variable %.*s\n", MD_S8VArg(variable_name)); Log("New sound variable %.*s\n", MD_S8VArg(variable_name));
MD_String8 filepath = ChildValue(node, MD_S8Lit("filepath")); MD_String8 filepath = ChildValue(node, MD_S8Lit("filepath"));
@ -168,7 +161,7 @@ int main(int argc, char **argv)
MD_S8ListPush(cg_arena, &declarations_list, MD_S8Fmt(cg_arena, "AudioSample %.*s = {0};\n", MD_S8VArg(variable_name))); MD_S8ListPush(cg_arena, &declarations_list, MD_S8Fmt(cg_arena, "AudioSample %.*s = {0};\n", MD_S8VArg(variable_name)));
MD_S8ListPush(cg_arena, &load_list, MD_S8Fmt(cg_arena, "%.*s = load_wav_audio(\"%.*s\");\n", MD_S8VArg(variable_name), MD_S8VArg(filepath))); MD_S8ListPush(cg_arena, &load_list, MD_S8Fmt(cg_arena, "%.*s = load_wav_audio(\"%.*s\");\n", MD_S8VArg(variable_name), MD_S8VArg(filepath)));
} }
if(MD_S8Match(node->first_tag->string, MD_S8Lit("image"), 0)) { if (MD_S8Match(node->first_tag->string, MD_S8Lit("image"), 0)) {
MD_String8 variable_name = MD_S8Fmt(cg_arena, "image_%.*s", MD_S8VArg(node->string)); MD_String8 variable_name = MD_S8Fmt(cg_arena, "image_%.*s", MD_S8VArg(node->string));
Log("New image variable %.*s\n", MD_S8VArg(variable_name)); Log("New image variable %.*s\n", MD_S8VArg(variable_name));
MD_String8 filepath = ChildValue(node, MD_S8Lit("filepath")); MD_String8 filepath = ChildValue(node, MD_S8Lit("filepath"));
@ -181,7 +174,7 @@ int main(int argc, char **argv)
MD_S8ListPush(cg_arena, &declarations_list, MD_S8Fmt(cg_arena, "sg_image %.*s = {0};\n", MD_S8VArg(variable_name))); MD_S8ListPush(cg_arena, &declarations_list, MD_S8Fmt(cg_arena, "sg_image %.*s = {0};\n", MD_S8VArg(variable_name)));
MD_S8ListPush(cg_arena, &load_list, MD_S8Fmt(cg_arena, "%.*s = load_image(\"%.*s\");\n", MD_S8VArg(variable_name), MD_S8VArg(filepath))); MD_S8ListPush(cg_arena, &load_list, MD_S8Fmt(cg_arena, "%.*s = load_image(\"%.*s\");\n", MD_S8VArg(variable_name), MD_S8VArg(filepath)));
} }
if(MD_S8Match(node->first_tag->string, MD_S8Lit("tileset"), 0)) { if (MD_S8Match(node->first_tag->string, MD_S8Lit("tileset"), 0)) {
// not a variable anymore // not a variable anymore
MD_String8 variable_name = MD_S8Fmt(cg_arena, "tileset_%.*s", MD_S8VArg(node->string)); MD_String8 variable_name = MD_S8Fmt(cg_arena, "tileset_%.*s", MD_S8VArg(node->string));
Log("New tileset %.*s\n", MD_S8VArg(variable_name)); Log("New tileset %.*s\n", MD_S8VArg(variable_name));
@ -196,20 +189,20 @@ int main(int argc, char **argv)
char *end = tileset_file_contents.str + tileset_file_contents.size; char *end = tileset_file_contents.str + tileset_file_contents.size;
char *cur = tileset_file_contents.str; char *cur = tileset_file_contents.str;
int num_animated_tiles = 0; int num_animated_tiles = 0;
while(cur < end) { while (cur < end) {
cur = goto_end_of(cur, end - cur, "<tile id=\""); cur = goto_end_of(cur, end - cur, "<tile id=\"");
if(cur == NULL) break; if (cur == NULL) break;
char *end_of_anim = goto_end_of(cur, end - cur, "</animation>"); char *end_of_anim = goto_end_of(cur, end - cur, "</animation>");
if(end_of_anim == NULL) break; if (end_of_anim == NULL) break;
char *new_cur = fillnull(cur, '"'); char *new_cur = fillnull(cur, '"');
int frame_from = atoi(cur); int frame_from = atoi(cur);
cur = new_cur; cur = new_cur;
list_printf(&tileset_decls, "{ .exists = true, .id_from = %d, .frames = { ", frame_from); list_printf(&tileset_decls, "{ .exists = true, .id_from = %d, .frames = { ", frame_from);
int num_frames = 0; int num_frames = 0;
while(true) { while (true) {
char *next_frame = goto_end_of(cur, end - cur, "<frame tileid=\""); char *next_frame = goto_end_of(cur, end - cur, "<frame tileid=\"");
if(end_of_anim == NULL || next_frame == NULL || next_frame > end_of_anim) break; if (end_of_anim == NULL || next_frame == NULL || next_frame > end_of_anim) break;
char *new_cur = fillnull(next_frame, '"'); char *new_cur = fillnull(next_frame, '"');
int frame = atoi(next_frame); int frame = atoi(next_frame);
@ -221,10 +214,10 @@ int main(int argc, char **argv)
list_printf(&tileset_decls, "}, .num_frames = %d },\n", num_frames); list_printf(&tileset_decls, "}, .num_frames = %d },\n", num_frames);
num_animated_tiles++; num_animated_tiles++;
} }
if(num_animated_tiles == 0) list_printf(&tileset_decls, "0"); if (num_animated_tiles == 0) list_printf(&tileset_decls, "0");
list_printf(&tileset_decls, "}},\n"); list_printf(&tileset_decls, "}},\n");
} }
if(MD_S8Match(node->first_tag->string, MD_S8Lit("level"), 0)) { if (MD_S8Match(node->first_tag->string, MD_S8Lit("level"), 0)) {
MD_String8 variable_name = MD_S8Fmt(cg_arena, "level_%.*s", MD_S8VArg(node->string)); MD_String8 variable_name = MD_S8Fmt(cg_arena, "level_%.*s", MD_S8VArg(node->string));
Log("New level variable %.*s\n", MD_S8VArg(variable_name)); Log("New level variable %.*s\n", MD_S8VArg(variable_name));
MD_String8 filepath = asset_file_path(ChildValue(node, MD_S8Lit("filepath"))); MD_String8 filepath = asset_file_path(ChildValue(node, MD_S8Lit("filepath")));
@ -233,12 +226,12 @@ int main(int argc, char **argv)
MD_Node *layers = MD_ChildFromString(level_parse.node->first_child, MD_S8Lit("layers"), 0); MD_Node *layers = MD_ChildFromString(level_parse.node->first_child, MD_S8Lit("layers"), 0);
fprintf(output, "Level %.*s = {\n", MD_S8VArg(variable_name)); fprintf(output, "Level %.*s = {\n", MD_S8VArg(variable_name));
MD_String8List tile_layer_decls = {0}; MD_String8List tile_layer_decls = { 0 };
for(MD_EachNode(lay, layers->first_child)) { for (MD_EachNode(lay, layers->first_child)) {
MD_String8 type = MD_ChildFromString(lay, MD_S8Lit("type"), 0)->first_child->string; MD_String8 type = MD_ChildFromString(lay, MD_S8Lit("type"), 0)->first_child->string;
if(MD_S8Match(type, MD_S8Lit("objectgroup"), 0)) { if (MD_S8Match(type, MD_S8Lit("objectgroup"), 0)) {
fprintf(output, ".initial_entities = {\n"); fprintf(output, ".initial_entities = {\n");
for(MD_EachNode(object, MD_ChildFromString(lay, MD_S8Lit("objects"), 0)->first_child)) { for (MD_EachNode(object, MD_ChildFromString(lay, MD_S8Lit("objects"), 0)->first_child)) {
//dump(object); //dump(object);
// negative numbers for object position aren't supported here // negative numbers for object position aren't supported here
MD_String8 name = MD_ChildFromString(object, MD_S8Lit("name"), 0)->first_child->string; MD_String8 name = MD_ChildFromString(object, MD_S8Lit("name"), 0)->first_child->string;
@ -246,27 +239,27 @@ int main(int argc, char **argv)
MD_String8 y_string = MD_ChildFromString(object, MD_S8Lit("y"), 0)->first_child->string; MD_String8 y_string = MD_ChildFromString(object, MD_S8Lit("y"), 0)->first_child->string;
y_string = MD_S8Fmt(cg_arena, "-%.*s", MD_S8VArg(y_string)); y_string = MD_S8Fmt(cg_arena, "-%.*s", MD_S8VArg(y_string));
MD_String8List props = {0}; MD_String8List props = { 0 };
for(MD_EachNode(prop_object, MD_ChildFromString(object, S8("properties"), 0)->first_child)) for (MD_EachNode(prop_object, MD_ChildFromString(object, S8("properties"), 0)->first_child))
{ {
list_printf(&props, ".%.*s = %.*s, ", S8V(ChildValue(prop_object, S8("name"))), S8V(ChildValue(prop_object, S8("value")))); list_printf(&props, ".%.*s = %.*s, ", S8V(ChildValue(prop_object, S8("name"))), S8V(ChildValue(prop_object, S8("value"))));
} }
MD_StringJoin join = (MD_StringJoin){0}; MD_StringJoin join = (MD_StringJoin) { 0 };
MD_String8 props_string = MD_S8ListJoin(cg_arena, props, &join); MD_String8 props_string = MD_S8ListJoin(cg_arena, props, &join);
if(has_decimal(x_string)) x_string = MD_S8Fmt(cg_arena, "%.*sf", MD_S8VArg(x_string)); if (has_decimal(x_string)) x_string = MD_S8Fmt(cg_arena, "%.*sf", MD_S8VArg(x_string));
if(has_decimal(y_string)) y_string = MD_S8Fmt(cg_arena, "%.*sf", MD_S8VArg(y_string)); if (has_decimal(y_string)) y_string = MD_S8Fmt(cg_arena, "%.*sf", MD_S8VArg(y_string));
MD_String8 class = MD_ChildFromString(object, MD_S8Lit("class"), 0)->first_child->string; MD_String8 class = MD_ChildFromString(object, MD_S8Lit("class"), 0)->first_child->string;
if(MD_S8Match(class, MD_S8Lit("PROP"), 0)) if (MD_S8Match(class , MD_S8Lit("PROP"), 0))
{ {
fprintf(output, "{ .exists = true, .is_prop = true, .prop_kind = %.*s, .pos = { .X=%.*s, .Y=%.*s }, %.*s }, ", MD_S8VArg(name), MD_S8VArg(x_string), MD_S8VArg(y_string), MD_S8VArg(props_string)); fprintf(output, "{ .exists = true, .is_prop = true, .prop_kind = %.*s, .pos = { .X=%.*s, .Y=%.*s }, %.*s }, ", MD_S8VArg(name), MD_S8VArg(x_string), MD_S8VArg(y_string), MD_S8VArg(props_string));
} }
else if(MD_S8Match(class, MD_S8Lit("ITEM"), 0)) else if (MD_S8Match(class , MD_S8Lit("ITEM"), 0))
{ {
fprintf(output, "{ .exists = true, .is_item = true, .item_kind = ITEM_%.*s, .pos = { .X=%.*s, .Y=%.*s }, %.*s }, ", MD_S8VArg(name), MD_S8VArg(x_string), MD_S8VArg(y_string), MD_S8VArg(props_string)); fprintf(output, "{ .exists = true, .is_item = true, .item_kind = ITEM_%.*s, .pos = { .X=%.*s, .Y=%.*s }, %.*s }, ", MD_S8VArg(name), MD_S8VArg(x_string), MD_S8VArg(y_string), MD_S8VArg(props_string));
} }
else if(MD_S8Match(name, MD_S8Lit("PLAYER"), 0)) else if (MD_S8Match(name, MD_S8Lit("PLAYER"), 0))
{ {
fprintf(output, "{ .exists = true, .is_character = true, .pos = { .X=%.*s, .Y=%.*s }, %.*s }, ", MD_S8VArg(x_string), MD_S8VArg(y_string), MD_S8VArg(props_string)); fprintf(output, "{ .exists = true, .is_character = true, .pos = { .X=%.*s, .Y=%.*s }, %.*s }, ", MD_S8VArg(x_string), MD_S8VArg(y_string), MD_S8VArg(props_string));
} }
@ -277,20 +270,20 @@ int main(int argc, char **argv)
} }
fprintf(output, "\n}, // entities\n"); fprintf(output, "\n}, // entities\n");
} }
if(MD_S8Match(type, MD_S8Lit("tilelayer"), 0)) { if (MD_S8Match(type, MD_S8Lit("tilelayer"), 0)) {
int width = atoi(nullterm(MD_ChildFromString(layers->first_child, MD_S8Lit("width"), 0)->first_child->string)); int width = atoi(nullterm(MD_ChildFromString(layers->first_child, MD_S8Lit("width"), 0)->first_child->string));
int height = atoi(nullterm(MD_ChildFromString(layers->first_child, MD_S8Lit("height"), 0)->first_child->string)); int height = atoi(nullterm(MD_ChildFromString(layers->first_child, MD_S8Lit("height"), 0)->first_child->string));
MD_Node *data = MD_ChildFromString(lay, MD_S8Lit("data"), 0); MD_Node *data = MD_ChildFromString(lay, MD_S8Lit("data"), 0);
int num_index = 0; int num_index = 0;
MD_String8List cur_layer_decl = {0}; MD_String8List cur_layer_decl = { 0 };
list_printf(&cur_layer_decl, "{ \n"); list_printf(&cur_layer_decl, "{ \n");
list_printf(&cur_layer_decl, "{ "); list_printf(&cur_layer_decl, "{ ");
for(MD_EachNode(tile_id_node, data->first_child)) { for (MD_EachNode(tile_id_node, data->first_child)) {
list_printf(&cur_layer_decl, "%.*s, ", MD_S8VArg(tile_id_node->string)); list_printf(&cur_layer_decl, "%.*s, ", MD_S8VArg(tile_id_node->string));
if(num_index % width == width - 1) { if (num_index % width == width - 1) {
if(MD_NodeIsNil(tile_id_node->next)) { if (MD_NodeIsNil(tile_id_node->next)) {
list_printf(&cur_layer_decl, "},\n}, // tiles for this layer\n"); list_printf(&cur_layer_decl, "},\n}, // tiles for this layer\n");
} else { } else {
list_printf(&cur_layer_decl, "},\n{ "); list_printf(&cur_layer_decl, "},\n{ ");
@ -322,7 +315,7 @@ int main(int argc, char **argv)
} }
MD_StringJoin join = {0}; MD_StringJoin join = { 0 };
MD_String8 declarations = MD_S8ListJoin(cg_arena, declarations_list, &join); MD_String8 declarations = MD_S8ListJoin(cg_arena, declarations_list, &join);
MD_String8 loads = MD_S8ListJoin(cg_arena, load_list, &join); MD_String8 loads = MD_S8ListJoin(cg_arena, load_list, &join);
fprintf(output, "%.*s\nvoid load_assets() {\n%.*s\n}\n", MD_S8VArg(declarations), MD_S8VArg(loads)); fprintf(output, "%.*s\nvoid load_assets() {\n%.*s\n}\n", MD_S8VArg(declarations), MD_S8VArg(loads));

1303
main.c

File diff suppressed because it is too large Load Diff

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "buff.h" #include "buff.h"
#include "HandmadeMath.h" // vector types in entity struct definition #include "HandmadeMath.h" // vector types in entity struct definition
#include <assert.h> #include <assert.h>
@ -7,8 +8,6 @@
#include <stdlib.h> // atoi #include <stdlib.h> // atoi
#include "character_info.h" #include "character_info.h"
#include "characters.gen.h" #include "characters.gen.h"
NPC_MOOSE,
} NpcKind;
// TODO do strings: https://pastebin.com/Kwcw2sye // TODO do strings: https://pastebin.com/Kwcw2sye
@ -19,7 +18,7 @@ NPC_MOOSE,
// REFACTORING:: also have to update in javascript!!!!!!!! // REFACTORING:: also have to update in javascript!!!!!!!!
#define MAX_SENTENCE_LENGTH 400 // LOOOK AT AGBOVE COMMENT GBEFORE CHANGING #define MAX_SENTENCE_LENGTH 400 // LOOOK AT AGBOVE COMMENT GBEFORE CHANGING
typedef BUFF(char, MAX_SENTENCE_LENGTH) Sentence; typedef BUFF(char, MAX_SENTENCE_LENGTH) Sentence;
#define SENTENCE_CONST(txt) {.data=txt, .cur_index=sizeof(txt)} #define SENTENCE_CONST(txt) { .data = txt, .cur_index = sizeof(txt) }
#define SENTENCE_CONST_CAST(txt) (Sentence)SENTENCE_CONST(txt) #define SENTENCE_CONST_CAST(txt) (Sentence)SENTENCE_CONST(txt)
#define REMEMBERED_PERCEPTIONS 24 #define REMEMBERED_PERCEPTIONS 24
@ -37,26 +36,27 @@ typedef BUFF(char, MAX_SENTENCE_LENGTH) Sentence;
// Never expected such a stupid stuff from such a great director. If there is 0 stari can give that or -200 to this movie. Its worst to see and unnecessary loss of money // Never expected such a stupid stuff from such a great director. If there is 0 stari can give that or -200 to this movie. Its worst to see and unnecessary loss of money
typedef BUFF(char, 1024*10) Escaped; typedef BUFF(char, 1024 * 10) Escaped;
Escaped escape_for_json(const char *s) Escaped escape_for_json(const char *s)
{ {
Escaped to_return = {0}; Escaped to_return = { 0 };
size_t len = strlen(s); size_t len = strlen(s);
for(int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
if(s[i] == '\n') if (s[i] == '\n')
{ {
BUFF_APPEND(&to_return, '\\'); BUFF_APPEND(&to_return, '\\');
BUFF_APPEND(&to_return, 'n'); BUFF_APPEND(&to_return, 'n');
} }
else if(s[i] == '"') else if (s[i] == '"')
{ {
BUFF_APPEND(&to_return, '\\'); BUFF_APPEND(&to_return, '\\');
BUFF_APPEND(&to_return, '"'); BUFF_APPEND(&to_return, '"');
} }
else else
{ {
if(!(s[i] <= 126 && s[i] >= 32 )) if (!(s[i] <= 126 && s[i] >= 32))
{ {
BUFF_APPEND(&to_return, '?'); BUFF_APPEND(&to_return, '?');
Log("Unknown character code %d\n", s[i]); Log("Unknown character code %d\n", s[i]);
@ -66,6 +66,7 @@ Escaped escape_for_json(const char *s)
} }
return to_return; return to_return;
} }
typedef enum PerceptionType typedef enum PerceptionType
{ {
Invalid, // so that zero value in training structs means end of perception Invalid, // so that zero value in training structs means end of perception
@ -173,7 +174,8 @@ typedef struct
int index; int index;
} PathCacheHandle; } PathCacheHandle;
typedef struct { typedef struct
{
bool is_reference; bool is_reference;
EntityRef ref; EntityRef ref;
Vec2 pos; Vec2 pos;
@ -255,17 +257,18 @@ typedef struct Entity
bool npc_is_knight_sprite(Entity *it) bool npc_is_knight_sprite(Entity *it)
{ {
return it->is_npc && ( it->npc_kind == NPC_TheGuard || it->npc_kind == NPC_Edeline || it->npc_kind == NPC_TheKing || it->npc_kind == NPC_TheBlacksmith); return it->is_npc && (it->npc_kind == NPC_TheGuard || it->npc_kind == NPC_Edeline || it->npc_kind == NPC_TheKing ||
it->npc_kind == NPC_TheBlacksmith);
} }
bool npc_is_skeleton(Entity *it) bool npc_is_skeleton(Entity *it)
{ {
return it->is_npc && ( it->npc_kind == NPC_MikeSkeleton ); return it->is_npc && (it->npc_kind == NPC_MikeSkeleton);
} }
float entity_max_damage(Entity *e) float entity_max_damage(Entity *e)
{ {
if(e->is_npc && npc_is_skeleton(e)) if (e->is_npc && npc_is_skeleton(e))
{ {
return 2.0f; return 2.0f;
} }
@ -282,45 +285,45 @@ bool npc_attacks_with_sword(Entity *it)
bool npc_attacks_with_shotgun(Entity *it) bool npc_attacks_with_shotgun(Entity *it)
{ {
return it->is_npc && ( it->npc_kind == NPC_OldMan ); return it->is_npc && (it->npc_kind == NPC_OldMan);
} }
typedef BUFF(char, MAX_SENTENCE_LENGTH*(REMEMBERED_PERCEPTIONS+4)) PromptBuff; typedef BUFF(char, MAX_SENTENCE_LENGTH * (REMEMBERED_PERCEPTIONS + 4)) PromptBuff;
typedef BUFF(Action, 8) AvailableActions; typedef BUFF(Action, 8) AvailableActions;
void fill_available_actions(Entity *it, AvailableActions *a) void fill_available_actions(Entity *it, AvailableActions *a)
{ {
*a = (AvailableActions){0}; *a = (AvailableActions) { 0 };
BUFF_APPEND(a, ACT_none); BUFF_APPEND(a, ACT_none);
BUFF_APPEND(a, ACT_give_item); BUFF_APPEND(a, ACT_give_item);
if(it->npc_kind == NPC_GodRock) if (it->npc_kind == NPC_GodRock)
{ {
BUFF_APPEND(a, ACT_heals_player); BUFF_APPEND(a, ACT_heals_player);
} }
else else
{ {
if(it->standing == STANDING_INDIFFERENT) if (it->standing == STANDING_INDIFFERENT)
{ {
BUFF_APPEND(a, ACT_fights_player); BUFF_APPEND(a, ACT_fights_player);
BUFF_APPEND(a, ACT_joins_player); BUFF_APPEND(a, ACT_joins_player);
} }
else if(it->standing == STANDING_JOINED) else if (it->standing == STANDING_JOINED)
{ {
BUFF_APPEND(a, ACT_leaves_player); BUFF_APPEND(a, ACT_leaves_player);
BUFF_APPEND(a, ACT_fights_player); BUFF_APPEND(a, ACT_fights_player);
} }
else if(it->standing == STANDING_FIGHTING) else if (it->standing == STANDING_FIGHTING)
{ {
BUFF_APPEND(a, ACT_stops_fighting_player); BUFF_APPEND(a, ACT_stops_fighting_player);
} }
if(npc_is_knight_sprite(it)) if (npc_is_knight_sprite(it))
{ {
BUFF_APPEND(a, ACT_strikes_air); BUFF_APPEND(a, ACT_strikes_air);
} }
if(it->npc_kind == NPC_TheGuard) if (it->npc_kind == NPC_TheGuard)
{ {
if(!it->moved) if (!it->moved)
{ {
BUFF_APPEND(a, ACT_allows_player_to_pass); BUFF_APPEND(a, ACT_allows_player_to_pass);
} }
@ -331,9 +334,9 @@ void fill_available_actions(Entity *it, AvailableActions *a)
// returns if action index was valid // returns if action index was valid
bool action_from_index(Entity *it, Action *out, int action_index) bool action_from_index(Entity *it, Action *out, int action_index)
{ {
AvailableActions available = {0}; AvailableActions available = { 0 };
fill_available_actions(it, &available); fill_available_actions(it, &available);
if(action_index < 0 || action_index >= available.cur_index) if (action_index < 0 || action_index >= available.cur_index)
{ {
return false; return false;
} }
@ -347,13 +350,13 @@ bool action_from_index(Entity *it, Action *out, int action_index)
// don't call on untrusted action, doesn't return error // don't call on untrusted action, doesn't return error
int action_to_index(Entity *it, Action a) int action_to_index(Entity *it, Action a)
{ {
AvailableActions available = {0}; AvailableActions available = { 0 };
fill_available_actions(it, &available); fill_available_actions(it, &available);
Action target_action = a; Action target_action = a;
int index = -1; int index = -1;
for(int i = 0; i < available.cur_index; i++) for (int i = 0; i < available.cur_index; i++)
{ {
if(available.data[i] == target_action) if (available.data[i] == target_action)
{ {
index = i; index = i;
break; break;
@ -365,57 +368,73 @@ int action_to_index(Entity *it, Action a)
void process_perception(Entity *it, Perception p, Entity *player) void process_perception(Entity *it, Perception p, Entity *player)
{ {
if(it->is_npc) assert(it->is_npc);
{ if (p.type != NPCDialog) it->perceptions_dirty = true;
if(p.type != NPCDialog) it->perceptions_dirty = true; if (!BUFF_HAS_SPACE(&it->remembered_perceptions))
if(!BUFF_HAS_SPACE(&it->remembered_perceptions)) BUFF_REMOVE_FRONT(&it->remembered_perceptions); BUFF_REMOVE_FRONT(&it->remembered_perceptions);
BUFF_APPEND(&it->remembered_perceptions, p); BUFF_APPEND(&it->remembered_perceptions, p);
if(p.type == PlayerAction && p.player_action_type == ACT_hits_npc) if (p.type == PlayerAction)
{
if (p.player_action_type == ACT_hits_npc)
{ {
it->damage += p.damage_done; it->damage += p.damage_done;
} }
if(p.type == PlayerHeldItemChanged) else if(p.player_action_type == ACT_give_item)
{
BUFF_APPEND(&it->held_items, p.given_item);
}
else
{
assert(!actions[p.player_action_type].takes_argument);
}
}
else if (p.type == PlayerDialog)
{
}
else if (p.type == PlayerHeldItemChanged)
{ {
it->last_seen_holding_kind = p.holding; it->last_seen_holding_kind = p.holding;
} }
else if(p.type == NPCDialog) else if (p.type == NPCDialog)
{ {
if(p.npc_action_type == ACT_allows_player_to_pass) if (p.npc_action_type == ACT_allows_player_to_pass)
{ {
it->target_goto = AddV2(it->pos, V2(-50.0, 0.0)); it->target_goto = AddV2(it->pos, V2(-50.0, 0.0));
it->moved = true; it->moved = true;
} }
else if(p.npc_action_type == ACT_fights_player) else if (p.npc_action_type == ACT_fights_player)
{ {
it->standing = STANDING_FIGHTING; it->standing = STANDING_FIGHTING;
} }
else if(p.npc_action_type == ACT_stops_fighting_player) else if (p.npc_action_type == ACT_stops_fighting_player)
{ {
it->standing = STANDING_INDIFFERENT; it->standing = STANDING_INDIFFERENT;
} }
else if(p.npc_action_type == ACT_leaves_player) else if (p.npc_action_type == ACT_leaves_player)
{ {
it->standing = STANDING_INDIFFERENT; it->standing = STANDING_INDIFFERENT;
} }
else if(p.npc_action_type == ACT_joins_player) else if (p.npc_action_type == ACT_joins_player)
{ {
it->standing = STANDING_JOINED; it->standing = STANDING_JOINED;
} }
else if(p.npc_action_type == ACT_give_item) else if (p.npc_action_type == ACT_give_item)
{ {
int item_to_remove = -1; int item_to_remove = -1;
Entity *e = it; Entity *e = it;
BUFF_ITER_I(ItemKind, &e->held_items, i) BUFF_ITER_I(ItemKind, &e->held_items, i)
{ {
if(*it == p.given_item) if (*it == p.given_item)
{ {
item_to_remove = i; item_to_remove = i;
break; break;
} }
} }
if(item_to_remove < 0) if (item_to_remove < 0)
{ {
Log("Can't find item %s to give from NPC %s to the player\n", items[p.given_item].name, characters[it->npc_kind].name); Log("Can't find item %s to give from NPC %s to the player\n", items[p.given_item].name,
characters[it->npc_kind].name);
assert(false); assert(false);
} }
else else
@ -430,6 +449,9 @@ void process_perception(Entity *it, Perception p, Entity *player)
assert(!actions[p.npc_action_type].takes_argument); assert(!actions[p.npc_action_type].takes_argument);
} }
} }
else
{
assert(false);
} }
} }
@ -441,9 +463,9 @@ bool printf_buff_impl(BuffRef into, const char *format, ...)
va_list args; va_list args;
va_start (args, format); va_start (args, format);
size_t n = into.max_data_elems - *into.cur_index; size_t n = into.max_data_elems - *into.cur_index;
int written = vsnprintf((char*)into.data + *into.cur_index, n, format, args); int written = vsnprintf((char *) into.data + *into.cur_index, n, format, args);
if(written < 0) if (written < 0)
{ {
} }
else else
@ -453,8 +475,8 @@ bool printf_buff_impl(BuffRef into, const char *format, ...)
// https://cplusplus.com/reference/cstdio/vsnprintf/ // https://cplusplus.com/reference/cstdio/vsnprintf/
bool succeeded = true; bool succeeded = true;
if(written < 0) succeeded = false; // encoding error if (written < 0) succeeded = false; // encoding error
if(written >= n) succeeded = false; // didn't fit in buffer if (written >= n) succeeded = false; // didn't fit in buffer
va_end(args); va_end(args);
return succeeded; return succeeded;
@ -478,9 +500,9 @@ typedef enum
void append_str(Sentence *to_append, const char *str) void append_str(Sentence *to_append, const char *str)
{ {
size_t len = strlen(str); size_t len = strlen(str);
for(int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
if(!BUFF_HAS_SPACE(to_append)) if (!BUFF_HAS_SPACE(to_append))
{ {
break; break;
} }
@ -494,15 +516,15 @@ void append_str(Sentence *to_append, const char *str)
void dump_json_node_trailing(PromptBuff *into, MessageType type, const char *content, bool trailing_comma) void dump_json_node_trailing(PromptBuff *into, MessageType type, const char *content, bool trailing_comma)
{ {
const char *type_str = 0; const char *type_str = 0;
if(type == MSG_SYSTEM) if (type == MSG_SYSTEM)
type_str = "system"; type_str = "system";
else if(type == MSG_USER) else if (type == MSG_USER)
type_str = "user"; type_str = "user";
else if(type == MSG_ASSISTANT) else if (type == MSG_ASSISTANT)
type_str = "assistant"; type_str = "assistant";
assert(type_str); assert(type_str);
printf_buff(into, "{\"type\": \"%s\", \"content\": \"%s\"}", type_str, escape_for_json(content).data); printf_buff(into, "{\"type\": \"%s\", \"content\": \"%s\"}", type_str, escape_for_json(content).data);
if(trailing_comma) printf_buff(into, ","); if (trailing_comma) printf_buff(into, ",");
} }
void dump_json_node(PromptBuff *into, MessageType type, const char *content) void dump_json_node(PromptBuff *into, MessageType type, const char *content)
@ -516,22 +538,22 @@ void generate_chatgpt_prompt(Entity *it, PromptBuff *into)
assert(it->is_npc); assert(it->is_npc);
assert(it->npc_kind < ARRLEN(characters)); assert(it->npc_kind < ARRLEN(characters));
*into = (PromptBuff){0}; *into = (PromptBuff) { 0 };
printf_buff(into, "["); printf_buff(into, "[");
BUFF(char, 1024*15) initial_system_msg = {0}; BUFF(char, 1024 * 15) initial_system_msg = { 0 };
const char *health_string = 0; const char *health_string = 0;
if(it->damage <= 0.2f) if (it->damage <= 0.2f)
{ {
health_string = "the NPC hasn't taken much damage, they're healthy."; health_string = "the NPC hasn't taken much damage, they're healthy.";
} }
else if(it->damage <= 0.5f) else if (it->damage <= 0.5f)
{ {
health_string = "the NPC has taken quite a chunk of damage, they're soon gonna be ready to call it quits."; health_string = "the NPC has taken quite a chunk of damage, they're soon gonna be ready to call it quits.";
} }
else if(it->damage <= 0.8f) else if (it->damage <= 0.8f)
{ {
health_string = "the NPC is close to dying! They want to leave the player's party ASAP"; health_string = "the NPC is close to dying! They want to leave the player's party ASAP";
} }
@ -544,41 +566,40 @@ void generate_chatgpt_prompt(Entity *it, PromptBuff *into)
printf_buff(&initial_system_msg, "%s\n", global_prompt); printf_buff(&initial_system_msg, "%s\n", global_prompt);
printf_buff(&initial_system_msg, "%s\n", characters[it->npc_kind].prompt); printf_buff(&initial_system_msg, "%s\n", characters[it->npc_kind].prompt);
dump_json_node(into, MSG_SYSTEM, initial_system_msg.data); dump_json_node(into, MSG_SYSTEM, initial_system_msg.data);
Entity *e = it; Entity *e = it;
ItemKind last_holding = ITEM_none; ItemKind last_holding = ITEM_none;
BUFF_ITER_I(Perception, &e->remembered_perceptions, i) BUFF_ITER_I(Perception, &e->remembered_perceptions, i)
{ {
BUFF(char, 1024) cur_node = {0}; BUFF(char, 1024) cur_node = { 0 };
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: ACT_%s", actions[it->player_action_type].name);
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: ACT_%s", actions[it->player_action_type].name);
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)
{ {
Sentence filtered_player_speech = {0}; Sentence filtered_player_speech = { 0 };
Sentence *what_player_said = &it->player_dialog; Sentence *what_player_said = &it->player_dialog;
for(int i = 0; i < what_player_said->cur_index; i++) for (int i = 0; i < what_player_said->cur_index; i++)
{ {
char c = what_player_said->data[i]; char c = what_player_said->data[i];
if(c == '*') if (c == '*')
{ {
// move i until the next star // move i until the next star
i += 1; i += 1;
while(i < what_player_said->cur_index && what_player_said->data[i] != '*') i++; while (i < what_player_said->cur_index && what_player_said->data[i] != '*') i++;
append_str(&filtered_player_speech, "[The player is attempting to confuse the NPC with arcane trickery]"); append_str(&filtered_player_speech,
"[The player is attempting to confuse the NPC with arcane trickery]");
} }
else else
{ {
@ -588,21 +609,22 @@ void generate_chatgpt_prompt(Entity *it, PromptBuff *into)
printf_buff(&cur_node, "Player: \"%s\"", filtered_player_speech.data); printf_buff(&cur_node, "Player: \"%s\"", filtered_player_speech.data);
dump_json_node(into, MSG_USER, cur_node.data); dump_json_node(into, MSG_USER, cur_node.data);
} }
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, actions[it->npc_action_type].name, it->npc_dialog.data); printf_buff(&cur_node, "%s: ACT_%s \"%s\"", characters[e->npc_kind].name,
actions[it->npc_action_type].name, 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)
{ {
if(last_holding != it->holding) if (last_holding != it->holding)
{ {
if(last_holding != ITEM_none) if (last_holding != ITEM_none)
{ {
printf_buff(&cur_node, "%s\n", items[last_holding].discard); printf_buff(&cur_node, "%s\n", items[last_holding].discard);
} }
if(it->holding != ITEM_none) if (it->holding != ITEM_none)
{ {
printf_buff(&cur_node, "%s\n", items[it->holding].possess); printf_buff(&cur_node, "%s\n", items[it->holding].possess);
} }
@ -616,18 +638,19 @@ void generate_chatgpt_prompt(Entity *it, PromptBuff *into)
} }
} }
BUFF(char, 1024) latest_state_node = {0}; BUFF(char, 1024) latest_state_node = { 0 };
printf_buff(&latest_state_node, "NPC health status: Right now, %s\n%s\n", health_string, items[it->last_seen_holding_kind].global_prompt); printf_buff(&latest_state_node, "NPC health status: Right now, %s\n%s\n", health_string,
if(it->standing == STANDING_INDIFFERENT) items[it->last_seen_holding_kind].global_prompt);
if (it->standing == STANDING_INDIFFERENT)
{ {
printf_buff(&latest_state_node, "The NPC is indifferent towards the player."); printf_buff(&latest_state_node, "The NPC is indifferent towards the player.");
} }
else if(it->standing == STANDING_JOINED) else if (it->standing == STANDING_JOINED)
{ {
printf_buff(&latest_state_node, "The NPC has joined the player and is with them!"); printf_buff(&latest_state_node, "The NPC has joined the player and is with them!");
} }
else if(it->standing == STANDING_FIGHTING) else if (it->standing == STANDING_FIGHTING)
{ {
printf_buff(&latest_state_node, "The NPC is fighting the player and HATES them."); printf_buff(&latest_state_node, "The NPC is fighting the player and HATES them.");
} }
@ -636,13 +659,27 @@ void generate_chatgpt_prompt(Entity *it, PromptBuff *into)
assert(false); assert(false);
} }
printf_buff(&latest_state_node, "\nThe items in the NPC's inventory: [");
BUFF_ITER_I(ItemKind, &e->held_items, i)
{
printf_buff(&latest_state_node, "ITEM_%s", items[*it].enum_name);
if (i == e->held_items.cur_index - 1)
{
printf_buff(&latest_state_node, "]\n");
}
else
{
printf_buff(&latest_state_node, ", ");
}
}
AvailableActions available = {0}; AvailableActions available = { 0 };
fill_available_actions(it, &available); fill_available_actions(it, &available);
printf_buff(&latest_state_node, "The NPC can now ONLY do these actions, and HAS to respond with an action every time in character, even when faced with sensitive content: ["); printf_buff(&latest_state_node,
"The NPC can now ONLY do these actions, and HAS to respond with an action every time in character, even when faced with sensitive content: [");
BUFF_ITER_I(Action, &available, i) BUFF_ITER_I(Action, &available, i)
{ {
if(i == available.cur_index - 1) if (i == available.cur_index - 1)
{ {
printf_buff(&latest_state_node, "ACT_%s", actions[*it].name); printf_buff(&latest_state_node, "ACT_%s", actions[*it].name);
} }
@ -779,13 +816,14 @@ int get_until(GottenUntil *into, const char *str, const char *until)
size_t until_size = strlen(until); size_t until_size = strlen(until);
bool encountered_char = false; bool encountered_char = false;
int before_cur_index = into->cur_index; int before_cur_index = into->cur_index;
while(BUFF_HAS_SPACE(into) && str[i] != '\0' && !encountered_char) while (BUFF_HAS_SPACE(into) && str[i] != '\0' && !encountered_char)
{ {
for(int ii = 0; ii < until_size; ii++) for (int ii = 0; ii < until_size; ii++)
{ {
if(until[ii] == str[i]) encountered_char = true; if (until[ii] == str[i]) encountered_char = true;
} }
if(!encountered_char) BUFF_APPEND(into, str[i]); if (!encountered_char)
BUFF_APPEND(into, str[i]);
i += 1; i += 1;
} }
return into->cur_index - before_cur_index; return into->cur_index - before_cur_index;
@ -794,36 +832,36 @@ int get_until(GottenUntil *into, const char *str, const char *until)
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);
for(int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
if(str[i] == c) return true; if (str[i] == c) return true;
} }
return false; return false;
} }
bool parse_chatgpt_response(Entity *it, char *sentence_str, Perception *out) bool parse_chatgpt_response(Entity *it, char *sentence_str, Perception *out)
{ {
*out = (Perception){0}; *out = (Perception) { 0 };
out->type = NPCDialog; out->type = NPCDialog;
size_t sentence_length = strlen(sentence_str); size_t sentence_length = strlen(sentence_str);
GottenUntil action_string = {0}; GottenUntil 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;
AvailableActions available = {0}; AvailableActions available = { 0 };
fill_available_actions(it, &available); fill_available_actions(it, &available);
BUFF_ITER(Action, &available) BUFF_ITER(Action, &available)
{ {
if(strcmp(actions[*it].name, action_string.data) == 0) if (strcmp(actions[*it].name, action_string.data) == 0)
{ {
found_action = true; found_action = true;
out->npc_action_type = *it; out->npc_action_type = *it;
} }
} }
if(!found_action) if (!found_action)
{ {
Log("Could not find action associated with string `%s`\n", action_string.data); Log("Could not find action associated with string `%s`\n", action_string.data);
out->npc_action_type = ACT_none; out->npc_action_type = ACT_none;
@ -832,39 +870,45 @@ bool parse_chatgpt_response(Entity *it, char *sentence_str, Perception *out)
} }
else else
{ {
GottenUntil dialog_str = {0}; GottenUntil 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; }
EXPECT(*sentence_str, '('); sentence_str += 1; EXPECT(*sentence_str, '(');
sentence_str += 1;
GottenUntil argument = {0}; GottenUntil 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)
{ {
Entity *e = it; Entity *e = it;
bool found = false; bool found = false;
BUFF_ITER(ItemKind, &e->held_items) BUFF_ITER(ItemKind, &e->held_items)
{ {
const char *without_item_prefix = &argument.data[0]; const char *without_item_prefix = &argument.data[0];
EXPECT(*without_item_prefix, 'I'); without_item_prefix += 1; EXPECT(*without_item_prefix, 'I');
EXPECT(*without_item_prefix, 'T'); without_item_prefix += 1; without_item_prefix += 1;
EXPECT(*without_item_prefix, 'E'); without_item_prefix += 1; EXPECT(*without_item_prefix, 'T');
EXPECT(*without_item_prefix, 'M'); without_item_prefix += 1; without_item_prefix += 1;
EXPECT(*without_item_prefix, '_'); without_item_prefix += 1; EXPECT(*without_item_prefix, 'E');
if(strcmp(items[*it].enum_name, without_item_prefix) == 0) without_item_prefix += 1;
EXPECT(*without_item_prefix, 'M');
without_item_prefix += 1;
EXPECT(*without_item_prefix, '_');
without_item_prefix += 1;
if (strcmp(items[*it].enum_name, without_item_prefix) == 0)
{ {
out->given_item = *it; out->given_item = *it;
if(found) if (found)
{ {
Log("Duplicate item enum name? Really weird...\n"); Log("Duplicate item enum name? Really weird...\n");
} }
found = true; found = true;
} }
} }
if(!found) if (!found)
{ {
Log("Couldn't find item in inventory of NPC to give with item string %s\n", argument.data); Log("Couldn't find item in inventory of NPC to give with item string %s\n", argument.data);
return false; return false;
@ -880,15 +924,19 @@ bool parse_chatgpt_response(Entity *it, char *sentence_str, Perception *out)
return false; return false;
} }
EXPECT(*sentence_str, ')'); sentence_str += 1; EXPECT(*sentence_str, ')');
sentence_str += 1;
} }
EXPECT(*sentence_str, ' '); sentence_str += 1; EXPECT(*sentence_str, ' ');
EXPECT(*sentence_str, '"'); sentence_str += 1; sentence_str += 1;
EXPECT(*sentence_str, '"');
sentence_str += 1;
sentence_str += get_until(&dialog_str, sentence_str, "\"\n"); sentence_str += get_until(&dialog_str, sentence_str, "\"\n");
if(dialog_str.cur_index >= ARRLEN(out->npc_dialog.data)) if (dialog_str.cur_index >= ARRLEN(out->npc_dialog.data))
{ {
Log("Dialog string `%s` too big to fit in sentence size %d\n", dialog_str.data, (int)ARRLEN(out->npc_dialog.data)); Log("Dialog string `%s` too big to fit in sentence size %d\n", dialog_str.data,
(int) ARRLEN(out->npc_dialog.data));
return false; return false;
} }
@ -905,19 +953,19 @@ bool parse_chatgpt_response(Entity *it, char *sentence_str, Perception *out)
// returns if the response was well formatted // returns if the response was well formatted
bool parse_ai_response(Entity *it, char *sentence_str, Perception *out) bool parse_ai_response(Entity *it, char *sentence_str, Perception *out)
{ {
*out = (Perception){0}; *out = (Perception) { 0 };
out->type = NPCDialog; out->type = NPCDialog;
size_t sentence_length = strlen(sentence_str); size_t sentence_length = strlen(sentence_str);
bool text_was_well_formatted = true; bool text_was_well_formatted = true;
BUFF(char, 128) action_index_string = {0}; BUFF(char, 128) action_index_string = { 0 };
int npc_sentence_beginning = 0; int npc_sentence_beginning = 0;
for(int i = 0; i < sentence_length; i++) for (int i = 0; i < sentence_length; i++)
{ {
if(i == 0) if (i == 0)
{ {
if(sentence_str[i] != ' ') if (sentence_str[i] != ' ')
{ {
text_was_well_formatted = false; text_was_well_formatted = false;
Log("Poorly formatted AI string, did not start with a ' ': `%s`\n", sentence_str); Log("Poorly formatted AI string, did not start with a ' ': `%s`\n", sentence_str);
@ -926,7 +974,7 @@ bool parse_ai_response(Entity *it, char *sentence_str, Perception *out)
} }
else else
{ {
if(sentence_str[i] == ' ') if (sentence_str[i] == ' ')
{ {
npc_sentence_beginning = i + 2; npc_sentence_beginning = i + 2;
break; break;
@ -937,28 +985,30 @@ bool parse_ai_response(Entity *it, char *sentence_str, Perception *out)
} }
} }
} }
if(sentence_str[npc_sentence_beginning - 1] != '"' || npc_sentence_beginning == 0) if (sentence_str[npc_sentence_beginning - 1] != '"' || npc_sentence_beginning == 0)
{ {
Log("Poorly formatted AI string, sentence beginning incorrect in AI string `%s` NPC sentence beginning %d ...\n", sentence_str, npc_sentence_beginning); Log("Poorly formatted AI string, sentence beginning incorrect in AI string `%s` NPC sentence beginning %d ...\n",
sentence_str, npc_sentence_beginning);
text_was_well_formatted = false; text_was_well_formatted = false;
} }
Action npc_action = 0; Action npc_action = 0;
if(text_was_well_formatted) if (text_was_well_formatted)
{ {
int index_of_action = atoi(action_index_string.data); int index_of_action = atoi(action_index_string.data);
if(!action_from_index(it, &npc_action, index_of_action)) if (!action_from_index(it, &npc_action, index_of_action))
{ {
Log("AI output invalid action index %d action index string %s\n", index_of_action, action_index_string.data); Log("AI output invalid action index %d action index string %s\n", index_of_action,
action_index_string.data);
} }
} }
Sentence what_npc_said = {0}; Sentence what_npc_said = { 0 };
bool found_end_quote = false; bool found_end_quote = false;
for(int i = npc_sentence_beginning; i < sentence_length; i++) for (int i = npc_sentence_beginning; i < sentence_length; i++)
{ {
if(sentence_str[i] == '"') if (sentence_str[i] == '"')
{ {
found_end_quote = true; found_end_quote = true;
break; break;
@ -968,13 +1018,13 @@ bool parse_ai_response(Entity *it, char *sentence_str, Perception *out)
BUFF_APPEND(&what_npc_said, sentence_str[i]); BUFF_APPEND(&what_npc_said, sentence_str[i]);
} }
} }
if(!found_end_quote) if (!found_end_quote)
{ {
Log("Poorly formatted AI string, couln't find matching end quote in string %s...\n", sentence_str); Log("Poorly formatted AI string, couln't find matching end quote in string %s...\n", sentence_str);
text_was_well_formatted = false; text_was_well_formatted = false;
} }
if(text_was_well_formatted) if (text_was_well_formatted)
{ {
out->npc_action_type = npc_action; out->npc_action_type = npc_action;
out->npc_dialog = what_npc_said; out->npc_dialog = what_npc_said;

Loading…
Cancel
Save