Compare commits

..

No commits in common. '3972edb455faaff347bb10e41d5b3250bebf5dc7' and '0466612cbe6de28b94a19f9cd27a309ab568ed8b' have entirely different histories.

@ -14,10 +14,6 @@
{ {
filepath: "unread_triangle.png", filepath: "unread_triangle.png",
} }
@image skull:
{
filepath: "skull.png",
}
@image loading: @image loading:
{ {
filepath: "loading.png", filepath: "loading.png",

BIN
assets/skull.png (Stored with Git LFS)

Binary file not shown.

@ -17,22 +17,22 @@
#pragma warning(disable : 4244) // loss of data warning #pragma warning(disable : 4244) // loss of data warning
#pragma warning(disable : 4101) // unreferenced local variable #pragma warning(disable : 4101) // unreferenced local variable
#define STBSP_ADD_TO_FUNCTIONS no_ubsan #define STBSP_ADD_TO_FUNCTIONS no_ubsan
#define FUNCTION no_ubsan #define MD_FUNCTION no_ubsan
#include "md.h" #include "md.h"
#include "md.c" #include "md.c"
#pragma warning(pop) #pragma warning(pop)
void dump(Node* from) { void dump(MD_Node* from) {
printf("/ %.*s\n", S8VArg(from->string)); printf("/ %.*s\n", MD_S8VArg(from->string));
int d = 0; int d = 0;
for (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, S8VArg(child->first_tag->string), S8VArg(child->string), 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;
} }
} }
bool has_decimal(String8 s) bool has_decimal(MD_String8 s)
{ {
for (int i = 0; i < s.size; i++) for (int i = 0; i < s.size; i++)
{ {
@ -41,24 +41,24 @@ bool has_decimal(String8 s)
return false; return false;
} }
Arena *cg_arena = NULL; MD_Arena *cg_arena = NULL;
#define S8(s) S8Lit(s) #define S8(s) MD_S8Lit(s)
#define S8V(s) S8VArg(s) #define S8V(s) MD_S8VArg(s)
String8 ChildValue(Node *n, String8 name) { MD_String8 ChildValue(MD_Node *n, MD_String8 name) {
Node *child_with_value = MD_ChildFromString(n, name, 0); MD_Node *child_with_value = MD_ChildFromString(n, name, 0);
assert(child_with_value); assert(child_with_value);
assert(!NodeIsNil(child_with_value->first_child)); // S8Lit("Must have child")); assert(!MD_NodeIsNil(child_with_value->first_child)); // MD_S8Lit("Must have child"));
return child_with_value->first_child->string; return child_with_value->first_child->string;
} }
String8 asset_file_path(String8 filename) { MD_String8 asset_file_path(MD_String8 filename) {
return S8Fmt(cg_arena, "%.*s/%.*s", S8VArg(S8("assets")), S8VArg(filename)); return MD_S8Fmt(cg_arena, "%.*s/%.*s", MD_S8VArg(S8("assets")), MD_S8VArg(filename));
} }
char *nullterm(String8 s) { char *nullterm(MD_String8 s) {
char *to_return = ArenaPush(cg_arena, s.size + 1); char *to_return = MD_ArenaPush(cg_arena, s.size + 1);
memcpy(to_return, s.str, s.size); memcpy(to_return, s.str, s.size);
to_return[s.size] = '\0'; to_return[s.size] = '\0';
return to_return; return to_return;
@ -72,18 +72,18 @@ char* fillnull(char *s, char c) {
} }
s++; s++;
} }
assert(false); // S8Lit("Couldn't find char")); assert(false); // MD_S8Lit("Couldn't find char"));
return NULL; return NULL;
} }
#define StrSame(s1, s2) S8Match((s1), (s2), 0) #define StrSame(s1, s2) MD_S8Match((s1), (s2), 0)
#define EachString(it, first) String8Node *it = (first); it != 0; it = it->next #define EachString(it, first) MD_String8Node *it = (first); it != 0; it = it->next
typedef BUFF(Node*, 256) Nodes; typedef BUFF(MD_Node*, 256) Nodes;
Node* find_by_name(Nodes *n, String8 name) MD_Node* find_by_name(Nodes *n, MD_String8 name)
{ {
Node *node_with = 0; MD_Node *node_with = 0;
BUFF_ITER(Node *, n) BUFF_ITER(MD_Node *, n)
{ {
if (StrSame((*it)->string, name)) if (StrSame((*it)->string, name))
{ {
@ -107,35 +107,35 @@ char* goto_end_of(char *tomove, size_t max_move, char *pattern) {
return NULL; return NULL;
} }
#define list_printf(list_ptr, ...) S8ListPush(cg_arena, list_ptr, 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(Node* from) void dump_full(MD_Node* from)
{ {
for (EachNode(node, from)) for (MD_EachNode(node, from))
{ {
printf("@%.*s %.*s\n", S8VArg(node->first_tag->string), S8VArg(node->string)); printf("@%.*s %.*s\n", MD_S8VArg(node->first_tag->string), MD_S8VArg(node->string));
} }
/* String8List output_list = {0}; /* MD_String8List output_list = {0};
DebugDumpFromNode(cg_arena, &output_list, from, 4, S8(" "), 0); MD_DebugDumpFromNode(cg_arena, &output_list, from, 4, S8(" "), 0);
StringJoin join = (StringJoin){0}; MD_StringJoin join = (MD_StringJoin){0};
String8 debugged = S8ListJoin(cg_arena, output_list , &join); MD_String8 debugged = MD_S8ListJoin(cg_arena, output_list , &join);
printf("%.*s\n", S8VArg(debugged));*/ printf("%.*s\n", MD_S8VArg(debugged));*/
} }
#include "character_info.h" #include "character_info.h"
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
cg_arena = ArenaAlloc(); cg_arena = MD_ArenaAlloc();
assert(cg_arena); assert(cg_arena);
String8 test = S8Lit("*testing*other"); MD_String8 test = MD_S8Lit("*testing*other");
String8 to_split = S8Lit("*"); MD_String8 to_split = MD_S8Lit("*");
String8List split_up = S8Split(cg_arena, test, 1, &to_split); MD_String8List split_up = MD_S8Split(cg_arena, test, 1, &to_split);
printf("Split up: "); printf("Split up: ");
for(String8Node * cur = split_up.first; cur; cur = cur->next) for(MD_String8Node * cur = split_up.first; cur; cur = cur->next)
{ {
printf("'%.*s', ", S8VArg(cur->string)); printf("'%.*s', ", MD_S8VArg(cur->string));
} }
printf("\n"); printf("\n");
@ -154,50 +154,50 @@ int main(int argc, char **argv)
// do assets // do assets
String8 writeto = S8Fmt(cg_arena, "gen/assets.gen.c"); MD_String8 writeto = MD_S8Fmt(cg_arena, "gen/assets.gen.c");
Log("Writing to %.*s\n", S8VArg(writeto)); Log("Writing to %.*s\n", MD_S8VArg(writeto));
FILE *output = fopen(nullterm(writeto), "w"); FILE *output = fopen(nullterm(writeto), "w");
ParseResult parse = ParseWholeFile(cg_arena, S8Lit("assets.mdesk")); MD_ParseResult parse = MD_ParseWholeFile(cg_arena, MD_S8Lit("assets.mdesk"));
String8List declarations_list = { 0 }; MD_String8List declarations_list = { 0 };
String8List load_list = { 0 }; MD_String8List load_list = { 0 };
String8List level_decl_list = { 0 }; MD_String8List level_decl_list = { 0 };
String8List tileset_decls = { 0 }; MD_String8List tileset_decls = { 0 };
for (EachNode(node, parse.node->first_child)) { for (MD_EachNode(node, parse.node->first_child)) {
if (S8Match(node->first_tag->string, S8Lit("sound"), 0)) { if (MD_S8Match(node->first_tag->string, MD_S8Lit("sound"), 0)) {
String8 variable_name = S8Fmt(cg_arena, "sound_%.*s", S8VArg(node->string)); MD_String8 variable_name = MD_S8Fmt(cg_arena, "sound_%.*s", MD_S8VArg(node->string));
Log("New sound variable %.*s\n", S8VArg(variable_name)); Log("New sound variable %.*s\n", MD_S8VArg(variable_name));
String8 filepath = ChildValue(node, S8Lit("filepath")); MD_String8 filepath = ChildValue(node, MD_S8Lit("filepath"));
filepath = asset_file_path(filepath); filepath = asset_file_path(filepath);
assert(filepath.str != 0); // S8Fmt(cg_arena, "No filepath specified for sound '%.*s'", S8VArg(node->string))); assert(filepath.str != 0); // MD_S8Fmt(cg_arena, "No filepath specified for sound '%.*s'", MD_S8VArg(node->string)));
FILE *asset_file = fopen(nullterm(filepath), "r"); FILE *asset_file = fopen(nullterm(filepath), "r");
assert(asset_file); // S8Fmt(cg_arena, "Could not open filepath %.*s for asset '%.*s'", S8VArg(filepath), S8VArg(node->string))); assert(asset_file); // MD_S8Fmt(cg_arena, "Could not open filepath %.*s for asset '%.*s'", MD_S8VArg(filepath), MD_S8VArg(node->string)));
fclose(asset_file); fclose(asset_file);
S8ListPush(cg_arena, &declarations_list, S8Fmt(cg_arena, "AudioSample %.*s = {0};\n", S8VArg(variable_name))); MD_S8ListPush(cg_arena, &declarations_list, MD_S8Fmt(cg_arena, "AudioSample %.*s = {0};\n", MD_S8VArg(variable_name)));
S8ListPush(cg_arena, &load_list, S8Fmt(cg_arena, "%.*s = load_wav_audio(\"%.*s\");\n", S8VArg(variable_name), 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 (S8Match(node->first_tag->string, S8Lit("image"), 0)) { if (MD_S8Match(node->first_tag->string, MD_S8Lit("image"), 0)) {
String8 variable_name = S8Fmt(cg_arena, "image_%.*s", S8VArg(node->string)); MD_String8 variable_name = MD_S8Fmt(cg_arena, "image_%.*s", MD_S8VArg(node->string));
//Log("New image variable %.*s\n", S8VArg(variable_name)); //Log("New image variable %.*s\n", MD_S8VArg(variable_name));
String8 filepath = ChildValue(node, S8Lit("filepath")); MD_String8 filepath = ChildValue(node, MD_S8Lit("filepath"));
filepath = asset_file_path(filepath); filepath = asset_file_path(filepath);
assert(filepath.str != 0); // , S8Fmt(cg_arena, "No filepath specified for image '%.*s'", S8VArg(node->string))); assert(filepath.str != 0); // , MD_S8Fmt(cg_arena, "No filepath specified for image '%.*s'", MD_S8VArg(node->string)));
FILE *asset_file = fopen(nullterm(filepath), "rb"); FILE *asset_file = fopen(nullterm(filepath), "rb");
assert(asset_file); // , S8Fmt(cg_arena, "Could not open filepath %.*s for asset '%.*s'", S8VArg(filepath), S8VArg(node->string))); assert(asset_file); // , MD_S8Fmt(cg_arena, "Could not open filepath %.*s for asset '%.*s'", MD_S8VArg(filepath), MD_S8VArg(node->string)));
fclose(asset_file); fclose(asset_file);
S8ListPush(cg_arena, &declarations_list, S8Fmt(cg_arena, "sg_image %.*s = {0};\n", S8VArg(variable_name))); MD_S8ListPush(cg_arena, &declarations_list, MD_S8Fmt(cg_arena, "sg_image %.*s = {0};\n", MD_S8VArg(variable_name)));
S8ListPush(cg_arena, &load_list, S8Fmt(cg_arena, "%.*s = load_image(S8Lit(\"%.*s\"));\n", S8VArg(variable_name), S8VArg(filepath))); MD_S8ListPush(cg_arena, &load_list, MD_S8Fmt(cg_arena, "%.*s = load_image(MD_S8Lit(\"%.*s\"));\n", MD_S8VArg(variable_name), MD_S8VArg(filepath)));
} }
} }
StringJoin join = { 0 }; MD_StringJoin join = { 0 };
String8 declarations = S8ListJoin(cg_arena, declarations_list, &join); MD_String8 declarations = MD_S8ListJoin(cg_arena, declarations_list, &join);
String8 loads = 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", S8VArg(declarations), S8VArg(loads)); fprintf(output, "%.*s\nvoid load_assets() {\n%.*s\n}\n", MD_S8VArg(declarations), MD_S8VArg(loads));
fclose(output); fclose(output);

896
main.c

File diff suppressed because it is too large Load Diff

@ -16,8 +16,8 @@
// 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
#define PushWithLint(arena, list, ...) { S8ListPushFmt(arena, list, __VA_ARGS__); if(false) printf( __VA_ARGS__); } #define PushWithLint(arena, list, ...) { MD_S8ListPushFmt(arena, list, __VA_ARGS__); if(false) printf( __VA_ARGS__); }
#define FmtWithLint(arena, ...) (0 ? printf(__VA_ARGS__) : (void)0, S8Fmt(arena, __VA_ARGS__)) #define FmtWithLint(arena, ...) (0 ? printf(__VA_ARGS__) : (void)0, MD_S8Fmt(arena, __VA_ARGS__))
typedef BUFF(char, 1024 * 10) Escaped; typedef BUFF(char, 1024 * 10) Escaped;
@ -26,9 +26,9 @@ bool character_valid(char c)
return c <= 126 && c >= 32; return c <= 126 && c >= 32;
} }
String8 escape_for_json(Arena *arena, String8 from) MD_String8 escape_for_json(MD_Arena *arena, MD_String8 from)
{ {
u64 output_size = 0; MD_u64 output_size = 0;
#define SHOULD_ESCAPE(c) (c == '"' || c == '\n' || c == '\\') #define SHOULD_ESCAPE(c) (c == '"' || c == '\n' || c == '\\')
for (int i = 0; i < from.size; i++) for (int i = 0; i < from.size; i++)
{ {
@ -48,13 +48,13 @@ String8 escape_for_json(Arena *arena, String8 from)
} }
} }
String8 output = { MD_String8 output = {
.str = PushArray(arena, u8, output_size), .str = MD_PushArray(arena, MD_u8, output_size),
.size = output_size, .size = output_size,
}; };
u64 output_cursor = 0; MD_u64 output_cursor = 0;
for(u64 i = 0; i < from.size; i++) for(MD_u64 i = 0; i < from.size; i++)
{ {
#define APPEND(elem) APPEND_TO_NAME(output.str, output_cursor, output.size, elem); #define APPEND(elem) APPEND_TO_NAME(output.str, output_cursor, output.size, elem);
assert(output_cursor < output.size); assert(output_cursor < output.size);
@ -195,10 +195,10 @@ typedef struct
// text chunk must be a literal, not a pointer // text chunk must be a literal, not a pointer
// and this returns a s8 that points at the text chunk memory // and this returns a s8 that points at the text chunk memory
#define TextChunkString8(t) S8((u8*)(t).text, (t).text_length) #define TextChunkString8(t) MD_S8((MD_u8*)(t).text, (t).text_length)
#define TextChunkVArg(t) S8VArg(TextChunkString8(t)) #define TextChunkVArg(t) MD_S8VArg(TextChunkString8(t))
void chunk_from_s8(TextChunk *into, String8 from) void chunk_from_s8(TextChunk *into, MD_String8 from)
{ {
assert(from.size < ARRLEN(into->text)); assert(from.size < ARRLEN(into->text));
memset(into->text, 0, ARRLEN(into->text)); memset(into->text, 0, ARRLEN(into->text));
@ -207,7 +207,7 @@ void chunk_from_s8(TextChunk *into, String8 from)
} }
// returns ai understandable, human readable name, on the arena, so not the enum name // returns ai understandable, human readable name, on the arena, so not the enum name
String8 action_argument_string(Arena *arena, ActionArgument arg) MD_String8 action_argument_string(MD_Arena *arena, ActionArgument arg)
{ {
switch(arg.kind) switch(arg.kind)
{ {
@ -215,9 +215,9 @@ String8 action_argument_string(Arena *arena, ActionArgument arg)
return FmtWithLint(arena, "%s", characters[arg.targeting].name); return FmtWithLint(arena, "%s", characters[arg.targeting].name);
break; break;
case ARG_OBJECTIVE: case ARG_OBJECTIVE:
return FmtWithLint(arena, "%.*s", S8VArg(TextChunkString8(arg.objective.description))); return FmtWithLint(arena, "%.*s", MD_S8VArg(TextChunkString8(arg.objective.description)));
} }
return (String8){0}; return (MD_String8){0};
} }
@ -248,7 +248,7 @@ typedef struct Entity
Vec2 vel; // only used sometimes, like in old man and bullet Vec2 vel; // only used sometimes, like in old man and bullet
float damage; // at 1.0, dead! zero initialized float damage; // at 1.0, dead! zero initialized
bool dead; bool dead;
String8 current_room_name; MD_String8 current_room_name;
// npcs // npcs
EntityRef joined; EntityRef joined;
@ -384,9 +384,9 @@ bool npc_does_dialog(Entity *it)
} }
// for no trailing comma just trim the last character // for no trailing comma just trim the last character
String8 make_json_node(Arena *arena, MessageType type, String8 content) MD_String8 make_json_node(MD_Arena *arena, MessageType type, MD_String8 content)
{ {
ArenaTemp scratch = GetScratch(&arena, 1); MD_ArenaTemp scratch = MD_GetScratch(&arena, 1);
const char *type_str = 0; const char *type_str = 0;
if (type == MSG_SYSTEM) if (type == MSG_SYSTEM)
@ -397,75 +397,75 @@ String8 make_json_node(Arena *arena, MessageType type, String8 content)
type_str = "assistant"; type_str = "assistant";
assert(type_str); assert(type_str);
String8 escaped = escape_for_json(scratch.arena, content); MD_String8 escaped = escape_for_json(scratch.arena, content);
String8 to_return = FmtWithLint(arena, "{\"type\": \"%s\", \"content\": \"%.*s\"},", type_str, S8VArg(escaped)); MD_String8 to_return = FmtWithLint(arena, "{\"type\": \"%s\", \"content\": \"%.*s\"},", type_str, MD_S8VArg(escaped));
ReleaseScratch(scratch); MD_ReleaseScratch(scratch);
return to_return; return to_return;
} }
String8 npc_to_human_readable(Entity *me, NpcKind kind) MD_String8 npc_to_human_readable(Entity *me, NpcKind kind)
{ {
if(me->npc_kind == kind) if(me->npc_kind == kind)
{ {
return S8Lit("You"); return MD_S8Lit("You");
} }
else else
{ {
return S8CString(characters[kind].name); return MD_S8CString(characters[kind].name);
} }
} }
String8List dump_memory_as_json(Arena *arena, Memory *it) MD_String8List dump_memory_as_json(MD_Arena *arena, Memory *it)
{ {
ArenaTemp scratch = GetScratch(&arena, 1); MD_ArenaTemp scratch = MD_GetScratch(&arena, 1);
String8List current_list = {0}; MD_String8List current_list = {0};
#define AddFmt(...) PushWithLint(arena, &current_list, __VA_ARGS__) #define AddFmt(...) PushWithLint(arena, &current_list, __VA_ARGS__)
AddFmt("{"); AddFmt("{");
AddFmt("\"speech\":\"%.*s\",", TextChunkVArg(it->speech)); AddFmt("\"speech\":\"%.*s\",", TextChunkVArg(it->speech));
AddFmt("\"action\":\"%s\",", actions[it->action_taken].name); AddFmt("\"action\":\"%s\",", actions[it->action_taken].name);
String8 arg_str = action_argument_string(scratch.arena, it->action_argument); MD_String8 arg_str = action_argument_string(scratch.arena, it->action_argument);
AddFmt("\"action_argument\":\"%.*s\",", S8VArg(arg_str)); AddFmt("\"action_argument\":\"%.*s\",", MD_S8VArg(arg_str));
AddFmt("\"target\":\"%s\"}", characters[it->context.talking_to_kind].name); AddFmt("\"target\":\"%s\"}", characters[it->context.talking_to_kind].name);
#undef AddFmt #undef AddFmt
ReleaseScratch(scratch); MD_ReleaseScratch(scratch);
return current_list; return current_list;
} }
// outputs json which is parsed by the server // outputs json which is parsed by the server
String8 generate_chatgpt_prompt(Arena *arena, GameState *gs, Entity *e, CanTalkTo can_talk_to) MD_String8 generate_chatgpt_prompt(MD_Arena *arena, GameState *gs, Entity *e, CanTalkTo can_talk_to)
{ {
assert(e->is_npc); assert(e->is_npc);
assert(e->npc_kind < ARRLEN(characters)); assert(e->npc_kind < ARRLEN(characters));
ArenaTemp scratch = GetScratch(&arena, 1); MD_ArenaTemp scratch = MD_GetScratch(&arena, 1);
String8List list = {0}; MD_String8List list = {0};
PushWithLint(scratch.arena, &list, "["); PushWithLint(scratch.arena, &list, "[");
#define AddFmt(...) PushWithLint(scratch.arena, &current_list, __VA_ARGS__) #define AddFmt(...) PushWithLint(scratch.arena, &current_list, __VA_ARGS__)
#define AddNewNode(node_type) { S8ListPush(scratch.arena, &list, make_json_node(scratch.arena, node_type, S8ListJoin(scratch.arena, current_list, &(StringJoin){0}))); current_list = (String8List){0}; } #define AddNewNode(node_type) { MD_S8ListPush(scratch.arena, &list, make_json_node(scratch.arena, node_type, MD_S8ListJoin(scratch.arena, current_list, &(MD_StringJoin){0}))); current_list = (MD_String8List){0}; }
// make first system node // make first system node
{ {
String8List current_list = {0}; MD_String8List current_list = {0};
AddFmt("%s\n\n", global_prompt); AddFmt("%s\n\n", global_prompt);
AddFmt("%s\n\n", characters[e->npc_kind].prompt); AddFmt("%s\n\n", characters[e->npc_kind].prompt);
AddFmt("The characters who are near you, that you can target:\n"); AddFmt("The characters who are near you, that you can target:\n");
BUFF_ITER(Entity*, &can_talk_to) BUFF_ITER(Entity*, &can_talk_to)
{ {
assert((*it)->is_npc); assert((*it)->is_npc);
String8 info = S8Lit(""); MD_String8 info = MD_S8Lit("");
if((*it)->killed) if((*it)->killed)
{ {
info = S8Lit(" - they're currently dead, they were murdered"); info = MD_S8Lit(" - they're currently dead, they were murdered");
} }
AddFmt("%s%.*s\n", characters[(*it)->npc_kind].name, S8VArg(info)); AddFmt("%s%.*s\n", characters[(*it)->npc_kind].name, MD_S8VArg(info));
} }
AddFmt("\n"); AddFmt("\n");
@ -485,7 +485,7 @@ String8 generate_chatgpt_prompt(Arena *arena, GameState *gs, Entity *e, CanTalkT
AddNewNode(MSG_SYSTEM); AddNewNode(MSG_SYSTEM);
} }
String8List current_list = {0}; MD_String8List current_list = {0};
bool in_drama_memories = true; bool in_drama_memories = true;
assert(e->memories_first->context.drama_memory); assert(e->memories_first->context.drama_memory);
for(Memory *it = e->memories_first; it; it = it->next) for(Memory *it = e->memories_first; it; it = it->next)
@ -506,7 +506,7 @@ String8 generate_chatgpt_prompt(Arena *arena, GameState *gs, Entity *e, CanTalkT
{ {
switch(it->action_taken) switch(it->action_taken)
{ {
#define HUMAN(kind) S8VArg(npc_to_human_readable(e, kind)) #define HUMAN(kind) MD_S8VArg(npc_to_human_readable(e, kind))
case ACT_none: case ACT_none:
break; break;
case ACT_join: case ACT_join:
@ -540,22 +540,22 @@ String8 generate_chatgpt_prompt(Arena *arena, GameState *gs, Entity *e, CanTalkT
} }
if(it->speech.text_length > 0) if(it->speech.text_length > 0)
{ {
String8 target_string = S8Lit("the world"); MD_String8 target_string = MD_S8Lit("the world");
if(it->context.talking_to_kind != NPC_nobody) if(it->context.talking_to_kind != NPC_nobody)
{ {
if(it->context.talking_to_kind == e->npc_kind) if(it->context.talking_to_kind == e->npc_kind)
target_string = S8Lit("you"); target_string = MD_S8Lit("you");
else else
target_string = S8CString(characters[it->context.talking_to_kind].name); target_string = MD_S8CString(characters[it->context.talking_to_kind].name);
} }
String8 speaking_to_you_helper = S8Lit("(Speaking directly you) "); MD_String8 speaking_to_you_helper = MD_S8Lit("(Speaking directly you) ");
if(it->context.talking_to_kind != e->npc_kind) if(it->context.talking_to_kind != e->npc_kind)
{ {
speaking_to_you_helper = S8Lit("(Overheard conversation, they aren't speaking directly to you) "); speaking_to_you_helper = MD_S8Lit("(Overheard conversation, they aren't speaking directly to you) ");
} }
AddFmt("%.*s%s said \"%.*s\" to %.*s (you are %s)\n", S8VArg(speaking_to_you_helper), characters[it->context.author_npc_kind].name, TextChunkVArg(it->speech), S8VArg(target_string), characters[e->npc_kind].name); AddFmt("%.*s%s said \"%.*s\" to %.*s (you are %s)\n", MD_S8VArg(speaking_to_you_helper), characters[it->context.author_npc_kind].name, TextChunkVArg(it->speech), MD_S8VArg(target_string), characters[e->npc_kind].name);
} }
if(no_longer_wants_to_converse) if(no_longer_wants_to_converse)
@ -582,8 +582,8 @@ String8 generate_chatgpt_prompt(Arena *arena, GameState *gs, Entity *e, CanTalkT
{ {
if(cur->offending_self_output.speech.text_length > 0 || cur->offending_self_output.action_taken != ACT_none) if(cur->offending_self_output.speech.text_length > 0 || cur->offending_self_output.action_taken != ACT_none)
{ {
String8 offending_json_output = S8ListJoin(scratch.arena, dump_memory_as_json(scratch.arena, &cur->offending_self_output), &(StringJoin){0}); MD_String8 offending_json_output = MD_S8ListJoin(scratch.arena, dump_memory_as_json(scratch.arena, &cur->offending_self_output), &(MD_StringJoin){0});
AddFmt("When you output, `%.*s`, ", S8VArg(offending_json_output)); AddFmt("When you output, `%.*s`, ", MD_S8VArg(offending_json_output));
} }
AddFmt("%.*s\n", TextChunkVArg(cur->reason_why_its_bad)); AddFmt("%.*s\n", TextChunkVArg(cur->reason_why_its_bad));
} }
@ -594,34 +594,34 @@ String8 generate_chatgpt_prompt(Arena *arena, GameState *gs, Entity *e, CanTalkT
if(it->context.i_said_this) if(it->context.i_said_this)
{ {
String8List current_list = {0}; // shadow the list of human understandable sentences to quickly flush MD_String8List current_list = {0}; // shadow the list of human understandable sentences to quickly flush
current_list = dump_memory_as_json(scratch.arena, it); current_list = dump_memory_as_json(scratch.arena, it);
AddNewNode(MSG_ASSISTANT); AddNewNode(MSG_ASSISTANT);
} }
} }
String8 with_trailing_comma = S8ListJoin(scratch.arena, list, &(StringJoin){S8Lit(""),S8Lit(""),S8Lit(""),}); MD_String8 with_trailing_comma = MD_S8ListJoin(scratch.arena, list, &(MD_StringJoin){MD_S8Lit(""),MD_S8Lit(""),MD_S8Lit(""),});
String8 no_trailing_comma = S8Chop(with_trailing_comma, 1); MD_String8 no_trailing_comma = MD_S8Chop(with_trailing_comma, 1);
String8 to_return = S8Fmt(arena, "%.*s]", S8VArg(no_trailing_comma)); MD_String8 to_return = MD_S8Fmt(arena, "%.*s]", MD_S8VArg(no_trailing_comma));
ReleaseScratch(scratch); MD_ReleaseScratch(scratch);
#undef AddFmt #undef AddFmt
return to_return; return to_return;
} }
String8 get_field(Node *parent, String8 name) MD_String8 get_field(MD_Node *parent, MD_String8 name)
{ {
return MD_ChildFromString(parent, name, 0)->first_child->string; return MD_ChildFromString(parent, name, 0)->first_child->string;
} }
void parse_action_argument(Arena *error_arena, String8 *cur_error_message, ActionKind action, String8 action_argument_str, ActionArgument *out) void parse_action_argument(MD_Arena *error_arena, MD_String8 *cur_error_message, ActionKind action, MD_String8 action_argument_str, ActionArgument *out)
{ {
assert(cur_error_message); assert(cur_error_message);
if(cur_error_message->size > 0) return; if(cur_error_message->size > 0) return;
ArenaTemp scratch = GetScratch(&error_arena, 1); MD_ArenaTemp scratch = MD_GetScratch(&error_arena, 1);
String8 action_str = S8CString(actions[action].name); MD_String8 action_str = MD_S8CString(actions[action].name);
// @TODO refactor into, action argument kinds and they parse into different action argument types // @TODO refactor into, action argument kinds and they parse into different action argument types
bool arg_is_character = action == ACT_join || action == ACT_aim_shotgun || action == ACT_end_conversation; bool arg_is_character = action == ACT_join || action == ACT_aim_shotgun || action == ACT_end_conversation;
bool arg_is_gameplay_objective = action == ACT_assign_gameplay_objective; bool arg_is_gameplay_objective = action == ACT_assign_gameplay_objective;
@ -632,7 +632,7 @@ void parse_action_argument(Arena *error_arena, String8 *cur_error_message, Actio
bool found_npc = false; bool found_npc = false;
for (int i = 0; i < ARRLEN(characters); i++) for (int i = 0; i < ARRLEN(characters); i++)
{ {
if (S8Match(S8CString(characters[i].name), action_argument_str, 0)) if (MD_S8Match(MD_S8CString(characters[i].name), action_argument_str, 0))
{ {
found_npc = true; found_npc = true;
(*out).targeting = i; (*out).targeting = i;
@ -640,7 +640,7 @@ void parse_action_argument(Arena *error_arena, String8 *cur_error_message, Actio
} }
if (!found_npc) if (!found_npc)
{ {
*cur_error_message = FmtWithLint(error_arena, "Argument for action `%.*s` you gave is `%.*s`, which doesn't exist in the game so is invalid", S8VArg(action_str), S8VArg(action_argument_str)); *cur_error_message = FmtWithLint(error_arena, "Argument for action `%.*s` you gave is `%.*s`, which doesn't exist in the game so is invalid", MD_S8VArg(action_str), MD_S8VArg(action_argument_str));
} }
} }
else if (arg_is_gameplay_objective) else if (arg_is_gameplay_objective)
@ -648,8 +648,8 @@ void parse_action_argument(Arena *error_arena, String8 *cur_error_message, Actio
out->kind = ARG_OBJECTIVE; out->kind = ARG_OBJECTIVE;
if(action_argument_str.size >= MAX_SENTENCE_LENGTH) if(action_argument_str.size >= MAX_SENTENCE_LENGTH)
{ {
String8 trimmed = S8Substring(action_argument_str, action_argument_str.size - MAX_SENTENCE_LENGTH/2, action_argument_str.size); MD_String8 trimmed = MD_S8Substring(action_argument_str, action_argument_str.size - MAX_SENTENCE_LENGTH/2, action_argument_str.size);
*cur_error_message = FmtWithLint(error_arena, "What you said for your action argument, '%.*s...' is WAY too big for the game to handle, it can be a maximum of %d characters, but you output %d!.", S8VArg(trimmed), MAX_SENTENCE_LENGTH, (int)action_argument_str.size); *cur_error_message = FmtWithLint(error_arena, "What you said for your action argument, '%.*s...' is WAY too big for the game to handle, it can be a maximum of %d characters, but you output %d!.", MD_S8VArg(trimmed), MAX_SENTENCE_LENGTH, (int)action_argument_str.size);
} }
if(cur_error_message->size == 0) if(cur_error_message->size == 0)
{ {
@ -660,47 +660,47 @@ void parse_action_argument(Arena *error_arena, String8 *cur_error_message, Actio
{ {
assert(false); // don't know how to parse the argument string for this kind of action... assert(false); // don't know how to parse the argument string for this kind of action...
} }
ReleaseScratch(scratch); MD_ReleaseScratch(scratch);
} }
// if returned string has size greater than 0, it's the error message. Allocated // if returned string has size greater than 0, it's the error message. Allocated
// on arena passed into it or in constant memory // on arena passed into it or in constant memory
String8 parse_chatgpt_response(Arena *arena, Entity *e, String8 action_in_json, Action *out) MD_String8 parse_chatgpt_response(MD_Arena *arena, Entity *e, MD_String8 action_in_json, Action *out)
{ {
ArenaTemp scratch = GetScratch(&arena, 1); MD_ArenaTemp scratch = MD_GetScratch(&arena, 1);
String8 error_message = {0}; MD_String8 error_message = {0};
*out = (Action) { 0 }; *out = (Action) { 0 };
ParseResult result = ParseWholeString(scratch.arena, S8Lit("chat_message"), action_in_json); MD_ParseResult result = MD_ParseWholeString(scratch.arena, MD_S8Lit("chat_message"), action_in_json);
if(result.errors.node_count > 0) if(result.errors.node_count > 0)
{ {
Message *cur = result.errors.first; MD_Message *cur = result.errors.first;
CodeLoc loc = CodeLocFromNode(cur->node); MD_CodeLoc loc = MD_CodeLocFromNode(cur->node);
error_message = FmtWithLint(arena, "Parse Error on column %d: %.*s", loc.column, S8VArg(cur->string)); error_message = FmtWithLint(arena, "Parse Error on column %d: %.*s", loc.column, MD_S8VArg(cur->string));
} }
Node *message_obj = result.node->first_child; MD_Node *message_obj = result.node->first_child;
String8 speech_str = {0}; MD_String8 speech_str = {0};
String8 action_str = {0}; MD_String8 action_str = {0};
String8 action_argument_str = {0}; MD_String8 action_argument_str = {0};
String8 target_str = {0}; MD_String8 target_str = {0};
if(error_message.size == 0) if(error_message.size == 0)
{ {
speech_str = get_field(message_obj, S8Lit("speech")); speech_str = get_field(message_obj, MD_S8Lit("speech"));
action_str = get_field(message_obj, S8Lit("action")); action_str = get_field(message_obj, MD_S8Lit("action"));
action_argument_str = get_field(message_obj, S8Lit("action_argument")); action_argument_str = get_field(message_obj, MD_S8Lit("action_argument"));
target_str = get_field(message_obj, S8Lit("target")); target_str = get_field(message_obj, MD_S8Lit("target"));
} }
if(error_message.size == 0 && action_str.size == 0) if(error_message.size == 0 && action_str.size == 0)
{ {
error_message = S8Lit("The field `action` must be of nonzero length, if you don't want to do anything it should be `none`"); error_message = MD_S8Lit("The field `action` must be of nonzero length, if you don't want to do anything it should be `none`");
} }
if(error_message.size == 0 && action_str.size == 0) if(error_message.size == 0 && action_str.size == 0)
{ {
error_message = S8Lit("The field `target` must be of nonzero length, if you don't want to target anybody it should be `nobody`"); error_message = MD_S8Lit("The field `target` must be of nonzero length, if you don't want to target anybody it should be `nobody`");
} if(error_message.size == 0 && speech_str.size >= MAX_SENTENCE_LENGTH) } if(error_message.size == 0 && speech_str.size >= MAX_SENTENCE_LENGTH)
{ {
error_message = FmtWithLint(arena, "Speech string provided is too big, maximum bytes is %d", MAX_SENTENCE_LENGTH); error_message = FmtWithLint(arena, "Speech string provided is too big, maximum bytes is %d", MAX_SENTENCE_LENGTH);
@ -709,7 +709,7 @@ String8 parse_chatgpt_response(Arena *arena, Entity *e, String8 action_in_json,
if(error_message.size == 0) if(error_message.size == 0)
{ {
if(S8Match(target_str, S8Lit("nobody"), 0)) if(MD_S8Match(target_str, MD_S8Lit("nobody"), 0))
{ {
out->talking_to_kind = NPC_nobody; out->talking_to_kind = NPC_nobody;
} }
@ -718,7 +718,7 @@ String8 parse_chatgpt_response(Arena *arena, Entity *e, String8 action_in_json,
bool found = false; bool found = false;
for(int i = 0; i < ARRLEN(characters); i++) for(int i = 0; i < ARRLEN(characters); i++)
{ {
if(S8Match(target_str, S8CString(characters[i].name), 0)) if(MD_S8Match(target_str, MD_S8CString(characters[i].name), 0))
{ {
found = true; found = true;
out->talking_to_kind = i; out->talking_to_kind = i;
@ -726,7 +726,7 @@ String8 parse_chatgpt_response(Arena *arena, Entity *e, String8 action_in_json,
} }
if(!found) if(!found)
{ {
error_message = FmtWithLint(arena, "Unrecognized character provided in field 'target': `%.*s`", S8VArg(target_str)); error_message = FmtWithLint(arena, "Unrecognized character provided in field 'target': `%.*s`", MD_S8VArg(target_str));
} }
} }
} }
@ -742,7 +742,7 @@ String8 parse_chatgpt_response(Arena *arena, Entity *e, String8 action_in_json,
bool found_action = false; bool found_action = false;
for(int i = 0; i < ARRLEN(actions); i++) for(int i = 0; i < ARRLEN(actions); i++)
{ {
if(S8Match(S8CString(actions[i].name), action_str, 0)) if(MD_S8Match(MD_S8CString(actions[i].name), action_str, 0))
{ {
assert(!found_action); assert(!found_action);
found_action = true; found_action = true;
@ -751,7 +751,7 @@ String8 parse_chatgpt_response(Arena *arena, Entity *e, String8 action_in_json,
} }
if(!found_action) if(!found_action)
{ {
error_message = FmtWithLint(arena, "Action `%.*s` is invalid, doesn't exist in the game", S8VArg(action_str)); error_message = FmtWithLint(arena, "Action `%.*s` is invalid, doesn't exist in the game", MD_S8VArg(action_str));
} }
if(error_message.size == 0) if(error_message.size == 0)
@ -763,6 +763,6 @@ String8 parse_chatgpt_response(Arena *arena, Entity *e, String8 action_in_json,
} }
} }
ReleaseScratch(scratch); MD_ReleaseScratch(scratch);
return error_message; return error_message;
} }

32
ser.h

@ -4,32 +4,32 @@
typedef struct typedef struct
{ {
b8 failed; MD_b8 failed;
String8 why; MD_String8 why;
} SerError; } SerError;
typedef struct typedef struct
{ {
u8 *data; // set to 0 to dry run and get maximum size. max doesn't matter in this case MD_u8 *data; // set to 0 to dry run and get maximum size. max doesn't matter in this case
u64 cur; MD_u64 cur;
u64 max; MD_u64 max;
Arena *arena; // allocate everything new on this, so that if serialization fails allocations can be undone MD_Arena *arena; // allocate everything new on this, so that if serialization fails allocations can be undone
// Serializing should never allocate. So this can be null when you serialize // Serializing should never allocate. So this can be null when you serialize
int version; int version;
SerError cur_error; SerError cur_error;
Arena *error_arena; // all error messages are allocated here MD_Arena *error_arena; // all error messages are allocated here
b8 serializing; MD_b8 serializing;
} SerState; } SerState;
void ser_bytes(SerState *ser, u8 *bytes, u64 bytes_size) void ser_bytes(SerState *ser, MD_u8 *bytes, MD_u64 bytes_size)
{ {
if(!ser->data && !ser->serializing) if(!ser->data && !ser->serializing)
{ {
ser->cur_error = (SerError){.failed = true, .why = S8Lit("Deserializing but the data is null")}; ser->cur_error = (SerError){.failed = true, .why = MD_S8Lit("Deserializing but the data is null")};
} }
if(!ser->cur_error.failed) if(!ser->cur_error.failed)
@ -39,7 +39,7 @@ void ser_bytes(SerState *ser, u8 *bytes, u64 bytes_size)
// maximum doesn't matter unless writing to data // maximum doesn't matter unless writing to data
if(ser->cur + bytes_size > ser->max) if(ser->cur + bytes_size > ser->max)
{ {
ser->cur_error = (SerError){.failed = true, .why = S8Lit("Too big bro")}; ser->cur_error = (SerError){.failed = true, .why = MD_S8Lit("Too big bro")};
} }
else else
{ {
@ -61,24 +61,24 @@ void ser_bytes(SerState *ser, u8 *bytes, u64 bytes_size)
#define SER_MAKE_FOR_TYPE(type) void ser_##type(SerState *ser, type *into) \ #define SER_MAKE_FOR_TYPE(type) void ser_##type(SerState *ser, type *into) \
{ \ { \
ser_bytes(ser, (u8*)into, sizeof(*into)); \ ser_bytes(ser, (MD_u8*)into, sizeof(*into)); \
} }
SER_MAKE_FOR_TYPE(int); SER_MAKE_FOR_TYPE(int);
SER_MAKE_FOR_TYPE(u64); SER_MAKE_FOR_TYPE(MD_u64);
// Embeds the string into the serialized binary. When deserializing copies the // Embeds the string into the serialized binary. When deserializing copies the
// deserialized data onto a newly allocated buffer // deserialized data onto a newly allocated buffer
void ser_String8(SerState *ser, String8 *s, Arena *allocate_onto) void ser_MD_String8(SerState *ser, MD_String8 *s, MD_Arena *allocate_onto)
{ {
ser_u64(ser, &s->size); ser_MD_u64(ser, &s->size);
if(ser->serializing) if(ser->serializing)
{ {
ser_bytes(ser, s->str, s->size); ser_bytes(ser, s->str, s->size);
} }
else else
{ {
s->str = ArenaPush(allocate_onto, s->size); s->str = MD_ArenaPush(allocate_onto, s->size);
ser_bytes(ser, s->str, s->size); ser_bytes(ser, s->str, s->size);
} }
} }

2980
thirdparty/md.c vendored

File diff suppressed because it is too large Load Diff

1284
thirdparty/md.h vendored

File diff suppressed because it is too large Load Diff

@ -582,12 +582,12 @@ cl = lg; \
// copy the string in // copy the string in
goto scopy; goto scopy;
//~ rjf: METADESK ADDITION: %S for String8's //~ rjf: METADESK ADDITION: %S for MD_String8's
case 'S': // String8 case 'S': // MD_String8
{ {
//- rjf: pull out string //- rjf: pull out string
String8 str = va_arg(va, String8); MD_String8 str = va_arg(va, MD_String8);
//- rjf: get string length //- rjf: get string length
s = (char *)str.str; s = (char *)str.str;

@ -2,6 +2,7 @@ Urgent:
- angel doesn't have characters near you - angel doesn't have characters near you
- Remove (MD_) prefix from project
- Furcate functionality in npc entity into feature flags, streamline creation of entities/things from blender -> game, things. Make rock thing. - Furcate functionality in npc entity into feature flags, streamline creation of entities/things from blender -> game, things. Make rock thing.
- Fix camera angle on forest map, probably introduce custom camera angles per map - Fix camera angle on forest map, probably introduce custom camera angles per map
- In debugtools show number of arenas allocated, and total megabytes allocated in arenas - In debugtools show number of arenas allocated, and total megabytes allocated in arenas

Loading…
Cancel
Save