WORKING AI GENERATED NPC DIALOG

main
Cameron Murphy Reikes 2 years ago
parent 2d144149ff
commit ffd428ace7

@ -18,6 +18,10 @@
{
filepath: "_Roll.png",
}
@image thinking:
{
filepath: "thinking.png",
}
@image old_man:
{
filepath: "small_old_man.png",

@ -5,15 +5,6 @@
{
"data":[53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 158, 213, 53, 53, 209, 213, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 158, 159, 159, 159, 159, 159, 160, 53, 53, 53, 53, 261, 265, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 261, 316, 367, 367, 367, 367, 368, 53, 53, 53, 53, 261, 265, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 313, 368, 53, 53, 313, 317, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 158, 160, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 261, 212, 213, 53, 53, 53, 53, 53, 53, 209, 159, 160, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 366, 314, 212, 160, 53, 53, 53, 53, 158, 210, 316, 368, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 313, 317, 53, 53, 53, 53, 53, 53, 53, 366, 314, 212, 159, 159, 159, 159, 210, 316, 317, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 313, 367, 367, 367, 367, 367, 367, 368, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
@ -21,20 +12,29 @@
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 209, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 160, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 212, 213, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 158, 210, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 212, 159, 159, 159, 159, 159, 159, 159, 213, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 316, 367, 314, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 261, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 366, 314, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 313, 367, 367, 367, 367, 367, 368, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 366, 314, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 209, 159, 159, 159, 159, 159, 159, 213, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 209, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 160, 53, 53, 53, 53, 53, 53, 53, 366, 367, 367, 367, 367, 367, 314, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 212, 213, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 158, 210, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 212, 159, 159, 159, 159, 159, 159, 159, 213, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 316, 367, 314, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 261, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 366, 314, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 313, 367, 367, 367, 314, 316, 368, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 261, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 366, 314, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 261, 212, 159, 159, 159, 159, 159, 210, 265, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 261, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 265, 53, 53, 53, 53, 53, 366, 367, 367, 367, 367, 367, 367, 367, 368, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 313, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 317, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
@ -86,8 +86,8 @@
"rotation":0,
"visible":true,
"width":32,
"x":960,
"y":928
"x":893,
"y":915
},
{
"class":"",
@ -97,8 +97,8 @@
"rotation":0,
"visible":true,
"width":32,
"x":804.666333333333,
"y":770.666333333333
"x":1598.666,
"y":448.666
},
{
"class":"",
@ -108,8 +108,8 @@
"rotation":0,
"visible":true,
"width":32,
"x":834,
"y":916
"x":1103,
"y":664
},
{
"class":"",
@ -119,8 +119,8 @@
"rotation":0,
"visible":true,
"width":32,
"x":970,
"y":761.333333333333
"x":1495,
"y":453.333
}],
"opacity":1,
"type":"objectgroup",

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 B

@ -5,7 +5,7 @@ mkdir build_web
call run_codegen.bat || goto :error
emcc -sEXPORTED_FUNCTIONS=_main,_end_text_input -sEXPORTED_RUNTIME_METHODS=ccall,cwrap -O2 -s ALLOW_MEMORY_GROWTH --source-map-base . -gsource-map -DDEVTOOLS -Ithirdparty -Igen main.c -o build_web\index.html --preload-file assets --shell-file web_template.html || goto :error
emcc -sEXPORTED_FUNCTIONS=_main,_end_text_input -sEXPORTED_RUNTIME_METHODS=ccall,cwrap -O0 -s ALLOW_MEMORY_GROWTH --source-map-base . -gsource-map -DDEVTOOLS -Ithirdparty -Igen main.c -o build_web\index.html --preload-file assets --shell-file web_template.html || goto :error
goto :EOF

185
main.c

@ -105,7 +105,14 @@ typedef enum EntityKind
ENTITY_BULLET,
} EntityKind;
#define BUFF(type, max_size) struct { type data[max_size]; int cur_index; }
#ifdef DEVTOOLS
#define SERVER_URL "http://localhost:8090"
#else
#error "No release server url defined"
#endif
// null terminator always built into buffers so can read properly from data
#define BUFF(type, max_size) struct { int cur_index; type data[max_size]; char null_terminator; }
#define BUFF_HAS_SPACE(buff_ptr) ( (buff_ptr)->cur_index < ARRLEN((buff_ptr)->data) )
#define BUFF_APPEND(buff_ptr, element) { (buff_ptr)->data[(buff_ptr)->cur_index++] = element; assert((buff_ptr)->cur_index < ARRLEN((buff_ptr)->data)); }
#define BUFF_ITER(type, buff_ptr) for(type *it = &((buff_ptr)->data[0]); it < (buff_ptr)->data + (buff_ptr)->cur_index; it++)
@ -126,6 +133,9 @@ typedef struct Entity
// for all NPCS (maybe make this allocated somewhere instead of in every entity? it's kind of big...)
Dialog player_dialog;
#ifdef WEB
int gen_request_id;
#endif
// fields for all entities
Vec2 pos;
@ -184,6 +194,65 @@ typedef struct Arena
Entity *player = NULL; // up here, used in text backend callback
void make_space_and_append(Dialog *d, Sentence *s)
{
if(d->cur_index + 1 >= ARRLEN(d->data))
{
assert(ARRLEN(d->data) >= 1);
for(int i = 0; i < ARRLEN(d->data) - 1; i++)
{
d->data[i] = d->data[i + 1];
}
d->cur_index--;
}
BUFF_APPEND(d, *s);
}
void add_new_npc_sentence(Entity *npc, char *sentence)
{
size_t sentence_len = strlen(sentence);
assert(sentence_len < MAX_SENTENCE_LENGTH);
Sentence new_sentence = {0};
BUFF(char, MAX_SENTENCE_LENGTH) match_buffer = {0};
bool inside_star = false;
for(int i = 0; i < sentence_len; i++)
{
if(sentence[i] == '"') break;
if(sentence[i] == '\n') continue;
if(inside_star)
{
if(sentence[i] == '*')
{
if(strcmp(match_buffer.data, "becomes aggressive") == 0)
{
npc->aggressive = true;
break;
}
BUFF_CLEAR(&match_buffer);
inside_star = false;
}
else
{
BUFF_APPEND(&match_buffer, sentence[i]);
}
}
else
{
if(sentence[i] == '*') inside_star = true;
}
BUFF_APPEND(&new_sentence, sentence[i]);
}
make_space_and_append(&npc->player_dialog, &new_sentence);
}
// just straight up gpt generation function, calls to golang backend
char *get_ai_response(char* prompt);
void begin_text_input(); // called when player engages in dialog, must say something and fill text_input_buffer
// a callback, when 'text backend' has finished making text
void end_text_input(char *what_player_said)
@ -194,7 +263,9 @@ void end_text_input(char *what_player_said)
#endif
size_t player_said_len = strlen(what_player_said);
if(player_said_len == 0)
int actual_len = 0;
for(int i = 0; i < player_said_len; i++) if(what_player_said[i] != '\n') actual_len++;
if(actual_len == 0)
{
// this just means cancel the dialog
}
@ -202,26 +273,59 @@ void end_text_input(char *what_player_said)
{
Sentence what_player_said_sentence = {0};
assert(player_said_len < ARRLEN(what_player_said_sentence.data));
memcpy(what_player_said_sentence.data, what_player_said, player_said_len);
for(int i = 0; i < player_said_len; i++)
{
char c = what_player_said[i];
if(c == '\n') break;
BUFF_APPEND(&what_player_said_sentence, c);
}
// the new elements wouldn't fit!
Dialog *to_append = &player->talking_to->player_dialog;
if(to_append->cur_index + 2 >= ARRLEN(to_append->data))
make_space_and_append(to_append, &what_player_said_sentence);
// the npc response will be appended here, or at least be async queued to be appended here
BUFF(char, 4000) prompt_buff = {0};
BUFF(char *, 100) to_join = {0};
BUFF_APPEND(&to_join, "This is dialog which takes place in a simple action RPG, where the player can only talk to NPCs, or fight. The characters influence the game world by saying specific actions from these possibilities: [*becomes aggressive*]. They don't say anything else that has '*' between them. Example dialog with an Old Man NPC:\nPlayer: \"Hello old man. Do you know that you're in a video game?\"\nOld Man: \"What are you talking about, young boy? What is a 'video game'?\"\nPlayer: \"You have no idea. You look ugly and stupid.\"\nOld Man: \"How juvenile! That's it, *becomes aggressive*\"\n\nThe NPCs exist on a small lush island, on a remote village, in a fantasy setting where monsters roam freely, posing a danger to the NPCs, and the player. They don't know about modern technology. They are very slow to say *becomes aggressive*, because doing so means killing the player, their friends, and potentially themselves. But if the situation demands it, they will not hesitate to open fire.\n");
// characters prompt
assert(player->talking_to->kind == ENTITY_OLD_MAN);
BUFF_APPEND(&to_join, "The player is talking to an old man who is standing around on the island. He's eager to bestow his wisdom upon the young player, but the player must act polite, not rude. If the player acts rude, the old man will say exactly the text '*becomes aggressive*' as shown in the above example, turning the interaction into a skirmish, where the old man takes out his well concealed shotgun. The old man is also a bit of a joker.\n\n");
// all the dialog
int i = 0;
BUFF_ITER(Sentence, &player->talking_to->player_dialog)
{
BUFF_APPEND(&to_join, i % 2 == 0 ? "Player: \"" : "Old Man: \"");
BUFF_APPEND(&to_join, it->data);
BUFF_APPEND(&to_join, "\"\n");
i++;
}
BUFF_APPEND(&to_join, "Old Man: \"");
// concatenate into prompt_buff
BUFF_ITER(char *, &to_join)
{
// do it twice
for(int i = 0; i < 2; i++)
size_t cur_len = strlen(*it);
for(int i = 0; i < cur_len; i++)
{
// shift array elements backwards, once
assert(ARRLEN(to_append->data) >= 1);
for(int i = 0; i < ARRLEN(to_append->data) - 1; i++)
{
to_append->data[i] = to_append->data[i + 1];
}
to_append->cur_index--;
BUFF_APPEND(&prompt_buff, (*it)[i]);
}
}
BUFF_APPEND(to_append, what_player_said_sentence);
BUFF_APPEND(to_append, SENTENCE_CONST("NPC response"));
const char * prompt = prompt_buff.data;
#ifdef WEB
// fire off generation request, save id
int req_id = EM_ASM_INT({
return make_generation_request(UTF8ToString($1), UTF8ToString($0));
}, SERVER_URL, prompt);
player->talking_to->gen_request_id = req_id;
#endif
#ifdef DESKTOP
add_new_npc_sentence(player->talking_to, "response *becomes aggressive*");
#endif
}
}
@ -252,6 +356,8 @@ void begin_text_input()
#endif // desktop
Vec2 FloorV2(Vec2 v)
{
return V2(floorf(v.x), floorf(v.y));
@ -668,6 +774,8 @@ Vec2 img_size(sg_image img)
return V2((float)info.width, (float)info.height);
}
#define IMG(img) img, full_region(img)
// full region in pixels
AABB full_region(sg_image img)
{
@ -1254,6 +1362,7 @@ float draw_wrapped_text(Vec2 at_point, float max_width, char *text, float text_s
return cursor.Y;
}
#define ROLL_KEY SAPP_KEYCODE_K
double elapsed_time = 0.0;
double last_frame_processing_time = 0.0;
@ -1387,9 +1496,49 @@ void frame(void)
}
#endif // devtools
// entities
// process entities
ENTITIES_ITER(entities)
{
#ifdef WEB
if(it->gen_request_id != 0)
{
assert(it->gen_request_id > 0);
draw_quad(true, quad_centered(AddV2(it->pos, V2(0.0, 50.0)), V2(100.0,100.0)), IMG(image_thinking), WHITE);
int status = EM_ASM_INT({
return get_generation_request_status($0);
}, it->gen_request_id);
if(status == 0)
{
// simply not done yet
}
else
{
if(status == 1)
{
// done! we can get the string
char sentence_str[400] = {0};
EM_ASM({
let generation = get_generation_request_content($0);
stringToUTF8(generation, $1, $2);
}, it->gen_request_id, sentence_str, ARRLEN(sentence_str));
add_new_npc_sentence(it, sentence_str);
EM_ASM({
done_with_generation_request($0);
}, it->gen_request_id);
}
else if(status == 2)
{
Log("Failed to generate dialog! Fuck!");
// need somethin better here. Maybe each sentence has to know if it's player or NPC, that way I can remove the player's dialog
make_space_and_append(&it->player_dialog, &SENTENCE_CONST("I'm not sure..."));
}
it->gen_request_id = 0;
}
}
#endif
if(it->kind == ENTITY_OLD_MAN)
{
if(it->aggressive)
@ -1491,7 +1640,7 @@ void frame(void)
// talking to them feedback
draw_quad(true, quad_centered(talking_to->pos, V2(TILE_SIZE, TILE_SIZE)), image_dialog_circle, full_region(image_dialog_circle), WHITE);
float panel_width = 250.0f;
float panel_height = 100.0f;
float panel_height = 150.0f;
float panel_vert_offset = 30.0f;
AABB dialog_panel = (AABB){
.upper_left = AddV2(talking_to->pos, V2(-panel_width/2.0f, panel_vert_offset+panel_height)),

22
server/.gitignore vendored

@ -0,0 +1,22 @@
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work

@ -0,0 +1,2 @@
github.com/sashabaranov/go-gpt3 v1.2.1 h1:kfU+vQ1ThI7p+xfwwJC8olEEEWjK3smgKZ3FcYbaLRQ=
github.com/sashabaranov/go-gpt3 v1.2.1/go.mod h1:BIZdbwdzxZbCrcKGMGH6u2eyGe1xFuX9Anmh3tCP8lQ=

@ -0,0 +1,54 @@
package main
import (
"fmt"
"net/http"
"io"
"os"
"context"
gogpt "github.com/sashabaranov/go-gpt3"
)
var c *gogpt.Client
func index(w http.ResponseWriter, req *http.Request) {
//time.Sleep(4 * time.Second)
(w).Header().Set("Access-Control-Allow-Origin", "*")
req.Body = http.MaxBytesReader(w, req.Body, 1024 * 1024) // no sending huge files to crash the server
promptBytes, err := io.ReadAll(req.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
} else {
promptString := string(promptBytes)
fmt.Println("Println line prompt string: ", promptString)
ctx := context.Background()
req := gogpt.CompletionRequest{
Model: gogpt.GPT3Curie,
MaxTokens: 30,
Prompt: promptString,
Temperature: 0.9,
Stop: []string{"\""},
N: 1,
}
resp, err := c.CreateCompletion(ctx, req)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
response := resp.Choices[0].Text
fmt.Println("Println response: ", response)
fmt.Fprintf(w, "%s", response)
}
}
func main() {
c = gogpt.NewClient(os.Getenv("OPENAI_KEY"))
http.HandleFunc("/", index)
http.ListenAndServe(":8090", nil)
}

@ -2,7 +2,7 @@
<!-- saved from url=(0055)https://floooh.github.io/sokol-html5/triangle-sapp.html -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>triangle</title>
<title>AI RPG</title>
<style type="text/css">
body {
margin: 0;
@ -103,7 +103,7 @@ body {
<link id="sokol-app-favicon" rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAZdJREFUOE9VUzFSw0AMlGihggekwhV0eQGZ8AQggQ4chlR5CjSeAUwHOHkCZPALoEuVVHkAdCnxMVpJd8YzHt/5pNXuSsdkDxNRkHfSC8REIZB88ASSXxrBdzU+tiVmBHs6UQMAiwgK6kCy4NsPACBPcfQ4VPtSSLdSfbjEmg0kVBkKMQ7lfIXKAoTnt8okPVbjwUqCJR//mtdMpaEa09ZwCZyopfk5g5Doye7UTz0JuUovfti0EIXvAbS7ebw3BaFIwaQAAwAqxzwAUTBYrE8AokG2AIpmHnZmzkG9aLHGcrE+1VoC14a3Nh90ZsKLOSTP/2OYc9pZxReq5Vce5UnqVfdJDlIXEklzOhkFpeXnJQQ7aN4tZcCsi0w0ehtrgMm/7xemAJ2n6/mNdtBseegXykCtJsrfx0ZC3RWA9hCO5uM0r4Ho8bjwgYwWIODoZYPZj8326UCpQPXFjsnAPEvtdA9k2XvegCV6ZZeq3av6fBvUvYZKsBbZiQI4tG0kQzW6kzrE1qfW/cWk+i1w14WuGxgvBOD+AP0MuCLRb/uuAAAAAElFTkSuQmCC"></head>
<body style="background:black">
<div id="inputdiv" class="inputdiv">
<textarea id="inputtext">
<textarea onkeyup='if(event.key === "Enter") end_dialog();' id="inputtext">
</textarea>
<button id="inputbutton" onclick="end_dialog()"> Submit </button>
</div>
@ -137,18 +137,105 @@ body {
};
</script>
<script type="text/javascript">
function start_dialog() {
document.getElementById("inputtext").value = "";
setTimeout(function(){document.getElementById("inputtext").focus();},200); // for some reason focus doesn't work immediately here
document.getElementById("inputdiv").style.display = "flex";
}
function end_dialog() {
document.getElementById("inputdiv").style.display = "none";
Module.ccall('end_text_input', 'void', ['string'], [document.getElementById("inputtext").value]);
function start_dialog() {
document.getElementById("inputtext").value = "";
setTimeout(function(){document.getElementById("inputtext").focus();},200); // for some reason focus doesn't work immediately here
document.getElementById("inputdiv").style.display = "flex";
}
function end_dialog() {
document.getElementById("inputdiv").style.display = "none";
Module.ccall('end_text_input', 'void', ['string'], [document.getElementById("inputtext").value]);
}
function textarea_key_up() {
end_dialog();
}
const max_retries = 5;
let cur_id = 1; // zero is not a valid id, the zero value means no async request currently active
let generation_requests = []; // array of dictionaries with structure:
/*
{ id: number,
request: XMLHTTPRequest,
request_info: { url: string, body: string }
retries_remaining: number, // on failure, retries over and over until out of retries
}
*/
function resend_request(r) {
r.request.open("POST", r.request_info.url, true);
r.request.send(r.request_info.body);
}
// Returns an integer, a "handle" into the generation request. Takes in the string prompt, and api URL
// the api url must start with `http://` or https.
function make_generation_request(p, api) {
cur_id += 1;
let to_push = {
"id": cur_id,
"request": new XMLHttpRequest(),
"retries_remaining": 5,
"request_info": {"url": api, "body": p}
}
console.log("Making generation request with id " + to_push.id);
generation_requests.push(to_push)
resend_request(to_push)
return cur_id;
}
// returns 0 if not done yet, 1 if succeeded, 2 if failed after too many retries (i.e server down, or no internet)
// -1 if it doesn't exist
function get_generation_request_status(id) {
for(let i = 0; i < generation_requests.length; i++) {
if(generation_requests[i].id == id) {
let http_status = generation_requests[i].request.status;
if(http_status == 200) {
return 1;
}
else if(http_status == 0) { // not done yet
return 0;
}
else { // errored
if(generation_requests[i].retries_remaining > 0) {
generation_requests[i].retries_remaining -= 1;
resend_request(generation_requests[i]);
return 0;
} else {
return 2; // too many retries, failed
}
}
}
}
return -1;
}
function done_with_generation_request(id) {
console.log("Removing request with id " + id);
let new_generation_requests = [];
for(let i = 0; i < generation_requests.length; i++) {
if(generation_requests[i].id == id)
{
} else {
new_generation_requests.push(generation_requests[i])
}
}
generation_requests = new_generation_requests;
}
// doesn't fill string if not done yet, or the id doesn't exist
function get_generation_request_content(id) {
let to_return = "";
for(let i = 0; i < generation_requests.length; i++) {
if(generation_requests[i].id == id) {
to_return = generation_requests[i].request.responseText;
break;
}
}
return to_return;;
}
</script>
{{{ SCRIPT }}}
</body></html>

Loading…
Cancel
Save