Don't use metadesk for training data, actions
parent
abc6abe1a2
commit
49751f8cfa
@ -0,0 +1,147 @@
|
|||||||
|
let SessionLoad = 1
|
||||||
|
let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1
|
||||||
|
let v:this_session=expand("<sfile>:p")
|
||||||
|
silent only
|
||||||
|
silent tabonly
|
||||||
|
cd ~/Documents/rpgpt
|
||||||
|
if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''
|
||||||
|
let s:wipebuf = bufnr('%')
|
||||||
|
endif
|
||||||
|
let s:shortmess_save = &shortmess
|
||||||
|
if &shortmess =~ 'A'
|
||||||
|
set shortmess=aoOA
|
||||||
|
else
|
||||||
|
set shortmess=aoO
|
||||||
|
endif
|
||||||
|
badd +0 codegen.c
|
||||||
|
badd +0 main.c
|
||||||
|
badd +0 buff.h
|
||||||
|
badd +0 makeprompt.h
|
||||||
|
badd +0 profiling.h
|
||||||
|
badd +0 term://~/Documents/rpgpt//42668:C:/Windows/system32/cmd.exe
|
||||||
|
argglobal
|
||||||
|
%argdel
|
||||||
|
$argadd codegen.c
|
||||||
|
$argadd main.c
|
||||||
|
$argadd buff.h
|
||||||
|
$argadd makeprompt.h
|
||||||
|
$argadd profiling.h
|
||||||
|
set stal=2
|
||||||
|
tabnew +setlocal\ bufhidden=wipe
|
||||||
|
tabrewind
|
||||||
|
let s:save_splitbelow = &splitbelow
|
||||||
|
let s:save_splitright = &splitright
|
||||||
|
set splitbelow splitright
|
||||||
|
wincmd _ | wincmd |
|
||||||
|
vsplit
|
||||||
|
1wincmd h
|
||||||
|
wincmd w
|
||||||
|
let &splitbelow = s:save_splitbelow
|
||||||
|
let &splitright = s:save_splitright
|
||||||
|
wincmd t
|
||||||
|
let s:save_winminheight = &winminheight
|
||||||
|
let s:save_winminwidth = &winminwidth
|
||||||
|
set winminheight=0
|
||||||
|
set winheight=1
|
||||||
|
set winminwidth=0
|
||||||
|
set winwidth=1
|
||||||
|
exe 'vert 1resize ' . ((&columns * 124 + 104) / 209)
|
||||||
|
exe 'vert 2resize ' . ((&columns * 84 + 104) / 209)
|
||||||
|
argglobal
|
||||||
|
enew
|
||||||
|
setlocal fdm=manual
|
||||||
|
setlocal fde=0
|
||||||
|
setlocal fmr={{{,}}}
|
||||||
|
setlocal fdi=#
|
||||||
|
setlocal fdl=0
|
||||||
|
setlocal fml=1
|
||||||
|
setlocal fdn=20
|
||||||
|
setlocal fen
|
||||||
|
wincmd w
|
||||||
|
argglobal
|
||||||
|
if bufexists(fnamemodify("term://~/Documents/rpgpt//42668:C:/Windows/system32/cmd.exe", ":p")) | buffer term://~/Documents/rpgpt//42668:C:/Windows/system32/cmd.exe | else | edit term://~/Documents/rpgpt//42668:C:/Windows/system32/cmd.exe | endif
|
||||||
|
if &buftype ==# 'terminal'
|
||||||
|
silent file term://~/Documents/rpgpt//42668:C:/Windows/system32/cmd.exe
|
||||||
|
endif
|
||||||
|
setlocal fdm=manual
|
||||||
|
setlocal fde=0
|
||||||
|
setlocal fmr={{{,}}}
|
||||||
|
setlocal fdi=#
|
||||||
|
setlocal fdl=0
|
||||||
|
setlocal fml=1
|
||||||
|
setlocal fdn=20
|
||||||
|
setlocal fen
|
||||||
|
let s:l = 1 - ((0 * winheight(0) + 24) / 49)
|
||||||
|
if s:l < 1 | let s:l = 1 | endif
|
||||||
|
keepjumps exe s:l
|
||||||
|
normal! zt
|
||||||
|
keepjumps 1
|
||||||
|
normal! 0
|
||||||
|
wincmd w
|
||||||
|
exe 'vert 1resize ' . ((&columns * 124 + 104) / 209)
|
||||||
|
exe 'vert 2resize ' . ((&columns * 84 + 104) / 209)
|
||||||
|
tabnext
|
||||||
|
let s:save_splitbelow = &splitbelow
|
||||||
|
let s:save_splitright = &splitright
|
||||||
|
set splitbelow splitright
|
||||||
|
wincmd _ | wincmd |
|
||||||
|
vsplit
|
||||||
|
1wincmd h
|
||||||
|
wincmd w
|
||||||
|
let &splitbelow = s:save_splitbelow
|
||||||
|
let &splitright = s:save_splitright
|
||||||
|
wincmd t
|
||||||
|
let s:save_winminheight = &winminheight
|
||||||
|
let s:save_winminwidth = &winminwidth
|
||||||
|
set winminheight=0
|
||||||
|
set winheight=1
|
||||||
|
set winminwidth=0
|
||||||
|
set winwidth=1
|
||||||
|
exe 'vert 1resize ' . ((&columns * 104 + 104) / 209)
|
||||||
|
exe 'vert 2resize ' . ((&columns * 104 + 104) / 209)
|
||||||
|
argglobal
|
||||||
|
enew
|
||||||
|
balt term://~/Documents/rpgpt//42668:C:/Windows/system32/cmd.exe
|
||||||
|
setlocal fdm=manual
|
||||||
|
setlocal fde=0
|
||||||
|
setlocal fmr={{{,}}}
|
||||||
|
setlocal fdi=#
|
||||||
|
setlocal fdl=0
|
||||||
|
setlocal fml=1
|
||||||
|
setlocal fdn=20
|
||||||
|
setlocal fen
|
||||||
|
wincmd w
|
||||||
|
argglobal
|
||||||
|
enew
|
||||||
|
balt term://~/Documents/rpgpt//42668:C:/Windows/system32/cmd.exe
|
||||||
|
setlocal fdm=manual
|
||||||
|
setlocal fde=0
|
||||||
|
setlocal fmr={{{,}}}
|
||||||
|
setlocal fdi=#
|
||||||
|
setlocal fdl=0
|
||||||
|
setlocal fml=1
|
||||||
|
setlocal fdn=20
|
||||||
|
setlocal fen
|
||||||
|
wincmd w
|
||||||
|
exe 'vert 1resize ' . ((&columns * 104 + 104) / 209)
|
||||||
|
exe 'vert 2resize ' . ((&columns * 104 + 104) / 209)
|
||||||
|
tabnext 2
|
||||||
|
set stal=1
|
||||||
|
if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'
|
||||||
|
silent exe 'bwipe ' . s:wipebuf
|
||||||
|
endif
|
||||||
|
unlet! s:wipebuf
|
||||||
|
set winheight=1 winwidth=20
|
||||||
|
let &shortmess = s:shortmess_save
|
||||||
|
let &winminheight = s:save_winminheight
|
||||||
|
let &winminwidth = s:save_winminwidth
|
||||||
|
let s:sx = expand("<sfile>:p:r")."x.vim"
|
||||||
|
if filereadable(s:sx)
|
||||||
|
exe "source " . fnameescape(s:sx)
|
||||||
|
endif
|
||||||
|
let &g:so = s:so_save | let &g:siso = s:siso_save
|
||||||
|
set hlsearch
|
||||||
|
nohlsearch
|
||||||
|
doautoall SessionLoadPost
|
||||||
|
unlet SessionLoad
|
||||||
|
" vim: set ft=vim :
|
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"activeFile": "",
|
||||||
|
"expandedProjectPaths": [
|
||||||
|
],
|
||||||
|
"fileStates": {
|
||||||
|
"assets/level0.json": {
|
||||||
|
"scale": 0.17733333333333334,
|
||||||
|
"selectedLayer": 0,
|
||||||
|
"viewCenter": {
|
||||||
|
"x": 1843.9849624060148,
|
||||||
|
"y": 1240.6015037593986
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"assets/testsmalllevel.json": {
|
||||||
|
"scale": 3.3249999999999997,
|
||||||
|
"selectedLayer": 0,
|
||||||
|
"viewCenter": {
|
||||||
|
"x": 128.1203007518797,
|
||||||
|
"y": 128.1203007518797
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"openFiles": [
|
||||||
|
],
|
||||||
|
"project": "main.tiled-project",
|
||||||
|
"recentFiles": [
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,383 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "buff.h"
|
||||||
|
#include "HandmadeMath.h" // vector types in entity struct definition
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h> // atoi
|
||||||
|
#include "characters.gen.h"
|
||||||
|
NPC_Skeleton,
|
||||||
|
NPC_MOOSE,
|
||||||
|
} NpcKind;
|
||||||
|
|
||||||
|
#define Log(...) { printf("%s Log %d | ", __FILE__, __LINE__); printf(__VA_ARGS__); }
|
||||||
|
|
||||||
|
// REFACTORING:: also have to update in javascript!!!!!!!!
|
||||||
|
#define MAX_SENTENCE_LENGTH 400 // LOOOK AT AGBOVE COMMENT GBEFORE CHANGING
|
||||||
|
typedef BUFF(char, MAX_SENTENCE_LENGTH) Sentence;
|
||||||
|
#define SENTENCE_CONST(txt) {.data=txt, .cur_index=sizeof(txt)}
|
||||||
|
#define SENTENCE_CONST_CAST(txt) (Sentence)SENTENCE_CONST(txt)
|
||||||
|
|
||||||
|
#define REMEMBERED_PERCEPTIONS 24
|
||||||
|
|
||||||
|
typedef enum PerceptionType
|
||||||
|
{
|
||||||
|
Invalid, // so that zero value in training structs means end of perception
|
||||||
|
PlayerAction,
|
||||||
|
PlayerDialog,
|
||||||
|
NPCDialog, // includes an npc action in every npc dialog. So it's often nothing
|
||||||
|
PlayerHeldItemChanged,
|
||||||
|
} PerceptionType;
|
||||||
|
|
||||||
|
typedef struct Perception
|
||||||
|
{
|
||||||
|
PerceptionType type;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
// player action
|
||||||
|
Action player_action_type;
|
||||||
|
|
||||||
|
// player dialog
|
||||||
|
Sentence player_dialog;
|
||||||
|
|
||||||
|
// npc dialog
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Action npc_action_type;
|
||||||
|
Sentence npc_dialog;
|
||||||
|
};
|
||||||
|
|
||||||
|
// player holding item. MUST precede any perceptions which come after the player is holding the item
|
||||||
|
ItemKind holding;
|
||||||
|
};
|
||||||
|
} Perception;
|
||||||
|
|
||||||
|
typedef enum PropKind
|
||||||
|
{
|
||||||
|
TREE0,
|
||||||
|
TREE1,
|
||||||
|
TREE2,
|
||||||
|
} PropKind;
|
||||||
|
|
||||||
|
typedef struct EntityRef
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
int generation;
|
||||||
|
} EntityRef;
|
||||||
|
|
||||||
|
typedef enum CharacterState
|
||||||
|
{
|
||||||
|
CHARACTER_WALKING,
|
||||||
|
CHARACTER_IDLE,
|
||||||
|
CHARACTER_ATTACK,
|
||||||
|
CHARACTER_TALKING,
|
||||||
|
} CharacterState;
|
||||||
|
|
||||||
|
typedef struct Entity
|
||||||
|
{
|
||||||
|
bool exists;
|
||||||
|
bool destroy;
|
||||||
|
int generation;
|
||||||
|
|
||||||
|
// fields for all gs.entities
|
||||||
|
Vec2 pos;
|
||||||
|
Vec2 vel; // only used sometimes, like in old man and bullet
|
||||||
|
float damage; // at 1.0, dead! zero initialized
|
||||||
|
bool facing_left;
|
||||||
|
double dead_time;
|
||||||
|
bool dead;
|
||||||
|
// multiple gs.entities have a sword swing
|
||||||
|
BUFF(EntityRef, 8) done_damage_to_this_swing; // only do damage once, but hitbox stays around
|
||||||
|
|
||||||
|
bool is_bullet;
|
||||||
|
|
||||||
|
// props
|
||||||
|
bool is_prop;
|
||||||
|
PropKind prop_kind;
|
||||||
|
|
||||||
|
// items
|
||||||
|
bool is_item;
|
||||||
|
bool held_by_player;
|
||||||
|
ItemKind item_kind;
|
||||||
|
|
||||||
|
// npcs
|
||||||
|
bool is_npc;
|
||||||
|
bool perceptions_dirty;
|
||||||
|
BUFF(Perception, REMEMBERED_PERCEPTIONS) remembered_perceptions;
|
||||||
|
double character_say_timer;
|
||||||
|
int characters_said;
|
||||||
|
NpcKind npc_kind;
|
||||||
|
ItemKind last_seen_holding_kind;
|
||||||
|
#ifdef WEB
|
||||||
|
int gen_request_id;
|
||||||
|
#endif
|
||||||
|
bool aggressive;
|
||||||
|
bool walking;
|
||||||
|
double shotgun_timer;
|
||||||
|
bool moved;
|
||||||
|
Vec2 target_goto;
|
||||||
|
// only for skeleton npc
|
||||||
|
double swing_timer;
|
||||||
|
|
||||||
|
// character
|
||||||
|
bool is_character;
|
||||||
|
EntityRef holding_item;
|
||||||
|
Vec2 to_throw_direction;
|
||||||
|
int boots_modifier;
|
||||||
|
CharacterState state;
|
||||||
|
EntityRef talking_to; // Maybe should be generational index, but I dunno. No death yet
|
||||||
|
bool is_rolling; // can only roll in idle or walk states
|
||||||
|
double time_not_rolling; // for cooldown for roll, so you can't just hold it and be invincible
|
||||||
|
double roll_progress;
|
||||||
|
double swing_progress;
|
||||||
|
} Entity;
|
||||||
|
|
||||||
|
bool npc_is_knight_sprite(Entity *it)
|
||||||
|
{
|
||||||
|
return it->is_npc && ( it->npc_kind == NPC_Max || it->npc_kind == NPC_Hunter || it->npc_kind == NPC_John || it->npc_kind == NPC_Blocky);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef BUFF(char, MAX_SENTENCE_LENGTH*(REMEMBERED_PERCEPTIONS+4)) PromptBuff;
|
||||||
|
typedef BUFF(Action, 8) AvailableActions;
|
||||||
|
|
||||||
|
void fill_available_actions(Entity *it, AvailableActions *a)
|
||||||
|
{
|
||||||
|
*a = (AvailableActions){0};
|
||||||
|
BUFF_APPEND(a, ACT_none);
|
||||||
|
if(it->npc_kind == NPC_GodRock)
|
||||||
|
{
|
||||||
|
BUFF_APPEND(a, ACT_heals_player);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BUFF_APPEND(a, ACT_fights_player);
|
||||||
|
if(npc_is_knight_sprite(it))
|
||||||
|
{
|
||||||
|
BUFF_APPEND(a, ACT_strikes_air);
|
||||||
|
}
|
||||||
|
if(it->npc_kind == NPC_Blocky)
|
||||||
|
{
|
||||||
|
if(!it->moved)
|
||||||
|
{
|
||||||
|
BUFF_APPEND(a, ACT_allows_player_to_pass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_perception(Entity *it, Perception p)
|
||||||
|
{
|
||||||
|
if(p.type != NPCDialog) it->perceptions_dirty = true;
|
||||||
|
if(!BUFF_HAS_SPACE(&it->remembered_perceptions)) BUFF_REMOVE_FRONT(&it->remembered_perceptions);
|
||||||
|
BUFF_APPEND(&it->remembered_perceptions, p);
|
||||||
|
if(p.type == PlayerHeldItemChanged)
|
||||||
|
{
|
||||||
|
it->last_seen_holding_kind = p.holding;
|
||||||
|
}
|
||||||
|
else if(p.type == NPCDialog)
|
||||||
|
{
|
||||||
|
if(p.npc_action_type == ACT_allows_player_to_pass)
|
||||||
|
{
|
||||||
|
it->target_goto = AddV2(it->pos, V2(-50.0, 0.0));
|
||||||
|
it->moved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define printf_buff(buff_ptr, ...) { int written = snprintf((buff_ptr)->data+(buff_ptr)->cur_index, ARRLEN((buff_ptr)->data) - (buff_ptr)->cur_index, __VA_ARGS__); assert(written >= 0); (buff_ptr)->cur_index += written; };
|
||||||
|
|
||||||
|
// returns if action index was valid
|
||||||
|
bool action_from_index(Entity *it, Action *out, int action_index)
|
||||||
|
{
|
||||||
|
AvailableActions available = {0};
|
||||||
|
fill_available_actions(it, &available);
|
||||||
|
if(action_index < 0 || action_index >= available.cur_index)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*out = available.data[action_index];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't call on untrusted action, doesn't return error
|
||||||
|
int action_to_index(Entity *it, Action a)
|
||||||
|
{
|
||||||
|
AvailableActions available = {0};
|
||||||
|
fill_available_actions(it, &available);
|
||||||
|
Action target_action = a;
|
||||||
|
int index = -1;
|
||||||
|
for(int i = 0; i < available.cur_index; i++)
|
||||||
|
{
|
||||||
|
if(available.data[i] == target_action)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(index != -1);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void generate_prompt(Entity *it, PromptBuff *into)
|
||||||
|
{
|
||||||
|
assert(it->is_npc);
|
||||||
|
*into = (PromptBuff){0};
|
||||||
|
|
||||||
|
// global prompt
|
||||||
|
printf_buff(into, "%s", global_prompt);
|
||||||
|
printf_buff(into, "%s", "\n");
|
||||||
|
|
||||||
|
// npc description prompt
|
||||||
|
assert(it->npc_kind < ARRLEN(prompt_table));
|
||||||
|
printf_buff(into, "%s", prompt_table[it->npc_kind]);
|
||||||
|
printf_buff(into, "%s", "\n");
|
||||||
|
|
||||||
|
// item prompt
|
||||||
|
if(it->last_seen_holding_kind != ITEM_nothing)
|
||||||
|
{
|
||||||
|
assert(it->last_seen_holding_kind < ARRLEN(item_prompt_table));
|
||||||
|
printf_buff(into, "%s", item_prompt_table[it->last_seen_holding_kind]);
|
||||||
|
printf_buff(into, "%s", "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// available actions prompt
|
||||||
|
AvailableActions available = {0};
|
||||||
|
fill_available_actions(it, &available);
|
||||||
|
printf_buff(into, "%s", "The NPC possible actions array, indexed by ACT_INDEX: [");
|
||||||
|
BUFF_ITER(Action, &available)
|
||||||
|
{
|
||||||
|
printf_buff(into, "%s", action_strings[*it]);
|
||||||
|
printf_buff(into, "%s", ", ");
|
||||||
|
}
|
||||||
|
printf_buff(into, "%s", "]\n");
|
||||||
|
|
||||||
|
Entity *e = it;
|
||||||
|
ItemKind last_holding = ITEM_nothing;
|
||||||
|
BUFF_ITER(Perception, &e->remembered_perceptions)
|
||||||
|
{
|
||||||
|
if(it->type == PlayerAction)
|
||||||
|
{
|
||||||
|
assert(it->player_action_type < ARRLEN(action_strings));
|
||||||
|
printf_buff(into, "Player: ACT %s \n", action_strings[it->player_action_type]);
|
||||||
|
}
|
||||||
|
else if(it->type == PlayerDialog)
|
||||||
|
{
|
||||||
|
printf_buff(into, "%s", "Player: \"");
|
||||||
|
printf_buff(into, "%s", it->player_dialog.data);
|
||||||
|
printf_buff(into, "%s", "\"\n");
|
||||||
|
}
|
||||||
|
else if(it->type == NPCDialog)
|
||||||
|
{
|
||||||
|
printf_buff(into, "%s: ACT %s \"%s\"\n", name_table[e->npc_kind], action_strings[it->npc_action_type], it->npc_dialog.data);
|
||||||
|
}
|
||||||
|
else if(it->type == PlayerHeldItemChanged)
|
||||||
|
{
|
||||||
|
if(last_holding != it->holding)
|
||||||
|
{
|
||||||
|
if(last_holding != ITEM_nothing)
|
||||||
|
{
|
||||||
|
printf_buff(into, "%s", item_discard_message_table[last_holding]);
|
||||||
|
printf_buff(into, "%s", "\n");
|
||||||
|
}
|
||||||
|
if(it->holding != ITEM_nothing)
|
||||||
|
{
|
||||||
|
printf_buff(into, "%s", item_possess_message_table[it->holding]);
|
||||||
|
printf_buff(into, "%s", "\n");
|
||||||
|
}
|
||||||
|
last_holding = it->holding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf_buff(into, "%s: ACT_INDEX", name_table[e->npc_kind]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns if the response was well formatted
|
||||||
|
bool parse_ai_response(Entity *it, char *sentence_str, Perception *out)
|
||||||
|
{
|
||||||
|
*out = (Perception){0};
|
||||||
|
out->type = NPCDialog;
|
||||||
|
|
||||||
|
size_t sentence_length = strlen(sentence_str);
|
||||||
|
bool text_was_well_formatted = true;
|
||||||
|
|
||||||
|
BUFF(char, 128) action_index_string = {0};
|
||||||
|
int npc_sentence_beginning = 0;
|
||||||
|
for(int i = 0; i < sentence_length; i++)
|
||||||
|
{
|
||||||
|
if(i == 0)
|
||||||
|
{
|
||||||
|
if(sentence_str[i] != ' ')
|
||||||
|
{
|
||||||
|
text_was_well_formatted = false;
|
||||||
|
Log("Poorly formatted AI string, did not start with a ' ': `%s`\n", sentence_str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(sentence_str[i] == ' ')
|
||||||
|
{
|
||||||
|
npc_sentence_beginning = i + 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BUFF_APPEND(&action_index_string, sentence_str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
text_was_well_formatted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Action npc_action = 0;
|
||||||
|
if(text_was_well_formatted)
|
||||||
|
{
|
||||||
|
int index_of_action = atoi(action_index_string.data);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sentence what_npc_said = {0};
|
||||||
|
bool found_end_quote = false;
|
||||||
|
for(int i = npc_sentence_beginning; i < sentence_length; i++)
|
||||||
|
{
|
||||||
|
if(sentence_str[i] == '"')
|
||||||
|
{
|
||||||
|
found_end_quote = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BUFF_APPEND(&what_npc_said, sentence_str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found_end_quote)
|
||||||
|
{
|
||||||
|
Log("Poorly formatted AI string, couln't find matching end quote in string %s...\n", sentence_str);
|
||||||
|
text_was_well_formatted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(text_was_well_formatted)
|
||||||
|
{
|
||||||
|
out->npc_action_type = npc_action;
|
||||||
|
out->npc_dialog = what_npc_said;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text_was_well_formatted;
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
#pragma warning(disable : 4996) // nonsense about fopen being insecure
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "makeprompt.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
NpcKind npc_kind;
|
||||||
|
Perception perceptions[32];
|
||||||
|
} TrainingSample;
|
||||||
|
|
||||||
|
#define PlayerAct(act) { .type = PlayerAction, .player_action_type = act, }
|
||||||
|
#define PlayerSay(txt) { .type = PlayerDialog, .player_dialog = SENTENCE_CONST(txt), }
|
||||||
|
#define NPCDoSay(d, txt) { .type = NPCDialog, .npc_action_type = d, .npc_dialog = SENTENCE_CONST(txt) }
|
||||||
|
#define NPCSay(txt) NPCDoSay(ACT_none, txt)
|
||||||
|
#define PlayerItemChange(new_item) { .type = PlayerHeldItemChanged, .holding = new_item, }
|
||||||
|
|
||||||
|
TrainingSample samples[] = {
|
||||||
|
{
|
||||||
|
.npc_kind = NPC_OldMan,
|
||||||
|
.perceptions = {
|
||||||
|
PlayerAct(ACT_walks_up),
|
||||||
|
NPCSay("Young warrior! You must stop Death, there isn't much time."),
|
||||||
|
PlayerAct(ACT_leaves),
|
||||||
|
NPCSay("Please!"),
|
||||||
|
PlayerAct(ACT_walks_up),
|
||||||
|
NPCSay("There you are! You must fight death!"),
|
||||||
|
PlayerSay("What what butt ass"),
|
||||||
|
NPCSay("You must stop death in his tracks and let the village live on!"),
|
||||||
|
PlayerSay("Nah"),
|
||||||
|
NPCSay("PLEASE!"),
|
||||||
|
PlayerAct(ACT_hits_npc),
|
||||||
|
NPCDoSay(ACT_fights_player, "Ready your sword!"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.npc_kind = NPC_Blocky,
|
||||||
|
.perceptions = {
|
||||||
|
PlayerAct(ACT_walks_up),
|
||||||
|
PlayerSay("Do you think I should use webgl1 or webgl2?"),
|
||||||
|
NPCSay("What are either of those things?"),
|
||||||
|
PlayerSay("Let me pass"),
|
||||||
|
NPCSay("No"),
|
||||||
|
PlayerAct(ACT_leaves),
|
||||||
|
NPCDoSay(ACT_strikes_air, "Goodbye"),
|
||||||
|
PlayerItemChange(ITEM_Tripod),
|
||||||
|
PlayerSay("Let me pass"),
|
||||||
|
NPCDoSay(ACT_allows_player_to_pass, "A beautiful sight, that tripod is."),
|
||||||
|
PlayerSay("Thanks"),
|
||||||
|
NPCSay("Of course."),
|
||||||
|
PlayerSay("Let me pass"),
|
||||||
|
NPCSay("I can't do that, I already let you pass"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.npc_kind = NPC_Blocky,
|
||||||
|
.perceptions = {
|
||||||
|
PlayerSay("hey"),
|
||||||
|
NPCSay("I'm just standing here, what are you doing?"),
|
||||||
|
PlayerItemChange(ITEM_nothing),
|
||||||
|
PlayerSay("nothing much"),
|
||||||
|
NPCSay("You don't have a tripod."),
|
||||||
|
PlayerSay("True"),
|
||||||
|
NPCSay("Do you want me to be standing there?"),
|
||||||
|
PlayerSay("Yes"),
|
||||||
|
NPCSay("Alright then"),
|
||||||
|
PlayerSay("No"),
|
||||||
|
NPCSay("What do you mean?"),
|
||||||
|
PlayerSay("What are you doing?"),
|
||||||
|
NPCSay("I'm just standing here"),
|
||||||
|
PlayerItemChange(ITEM_Tripod),
|
||||||
|
PlayerSay("How about now?"),
|
||||||
|
NPCSay("Mighty fine tripod you have there."),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.npc_kind = NPC_GodRock,
|
||||||
|
.perceptions = {
|
||||||
|
PlayerAct(ACT_walks_up),
|
||||||
|
NPCSay("I am"),
|
||||||
|
PlayerSay("Whaddup?"),
|
||||||
|
NPCSay("The clouds part and reveal only me."),
|
||||||
|
PlayerSay("uhhh. GIve me gold"),
|
||||||
|
NPCSay("To the greedy, come few"),
|
||||||
|
PlayerSay("I repent"),
|
||||||
|
NPCDoSay(ACT_heals_player, "And you are forgiven."),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.npc_kind = NPC_GodRock,
|
||||||
|
.perceptions = {
|
||||||
|
PlayerAct(ACT_walks_up),
|
||||||
|
NPCSay("I am"),
|
||||||
|
PlayerSay("Who are you?"),
|
||||||
|
NPCSay("Have you heard of the high elves?"),
|
||||||
|
PlayerSay("Yes"),
|
||||||
|
NPCDoSay(ACT_heals_player, "No need for me to speak then."),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef BUFF(char, 1024*10) Escaped;
|
||||||
|
Escaped escape_for_json(char *s)
|
||||||
|
{
|
||||||
|
Escaped to_return = {0};
|
||||||
|
size_t len = strlen(s);
|
||||||
|
for(int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if(s[i] == '\n')
|
||||||
|
{
|
||||||
|
BUFF_APPEND(&to_return, '\\');
|
||||||
|
BUFF_APPEND(&to_return, 'n');
|
||||||
|
}
|
||||||
|
else if(s[i] == '"')
|
||||||
|
{
|
||||||
|
BUFF_APPEND(&to_return, '\\');
|
||||||
|
BUFF_APPEND(&to_return, '"');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BUFF_APPEND(&to_return, s[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return to_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
Log("Starting to generate training data\n");
|
||||||
|
FILE *out = fopen("gen/training_data.jsonl", "w");
|
||||||
|
assert(out);
|
||||||
|
int total_samples = 0;
|
||||||
|
for(int i = 0; i < ARRLEN(samples); i++)
|
||||||
|
{
|
||||||
|
TrainingSample s = samples[i];
|
||||||
|
Entity this_entity = (Entity){.is_npc = true, .npc_kind = s.npc_kind};
|
||||||
|
PromptBuff cur_prompt = {0};
|
||||||
|
for(int i = 0; i < ARRLEN(s.perceptions); i++)
|
||||||
|
{
|
||||||
|
if(s.perceptions[i].type == Invalid) break;
|
||||||
|
if(s.perceptions[i].type == NPCDialog)
|
||||||
|
{
|
||||||
|
Log("Generating sample of length %d for NPC %s...\n", i, name_table[s.npc_kind]);
|
||||||
|
total_samples++;
|
||||||
|
generate_prompt(&this_entity, &cur_prompt);
|
||||||
|
BUFF(char, 1024) completion = {0};
|
||||||
|
|
||||||
|
// get index from action
|
||||||
|
int index = action_to_index(&this_entity, s.perceptions[i].npc_action_type);
|
||||||
|
printf_buff(&completion, " %d \"%s\"\n", index, s.perceptions[i].npc_dialog.data);
|
||||||
|
|
||||||
|
fprintf(out, "{\"prompt\": \"%s\", \"completion\": \"%s\"}\n", escape_for_json(cur_prompt.data).data, escape_for_json(completion.data).data);
|
||||||
|
}
|
||||||
|
process_perception(&this_entity, s.perceptions[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log("Finished. Total training samples: %d\n", total_samples);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue