Add an ancient door which opens from 3 secret words, and scrolls that

have those words
main
parent 22b976e224
commit 95db17dfe5

@ -118,6 +118,14 @@
{ {
filepath: "pile_of_rocks.png", filepath: "pile_of_rocks.png",
} }
@image door:
{
filepath: "door.png",
}
@image scroll:
{
filepath: "scroll.png",
}
@image swipe: @image swipe:
{ {
filepath: "swipe.png", filepath: "swipe.png",

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

@ -255,23 +255,23 @@
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 60, 60, 60, 60, 0, 60, 60, 60, 60, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 60, 60, 0, 60, 60, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 0, 0, 0, 0, 0, 0, 0, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 0, 0, 0, 0, 0, 0, 0, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -346,6 +346,11 @@
"id":21, "id":21,
"name":"PLAYER", "name":"PLAYER",
"properties":[ "properties":[
{
"name":"held_items",
"type":"string",
"value":"{.data = {ITEM_Scroll1}, .cur_index = 1}"
},
{ {
"name":"standing", "name":"standing",
"type":"string", "type":"string",
@ -354,8 +359,8 @@
"rotation":0, "rotation":0,
"visible":true, "visible":true,
"width":32, "width":32,
"x":1502.91836734694, "x":1540.91836734694,
"y":2585.40136054421 "y":1591.40136054421
}, },
{ {
"class":"", "class":"",
@ -366,7 +371,7 @@
{ {
"name":"held_items", "name":"held_items",
"type":"string", "type":"string",
"value":"{.data = {ITEM_Chalice}, .cur_index = 1}" "value":"{.data = {ITEM_Chalice, ITEM_Scroll1}, .cur_index = 2}"
}], }],
"rotation":0, "rotation":0,
"visible":true, "visible":true,
@ -418,6 +423,12 @@
"height":32, "height":32,
"id":26, "id":26,
"name":"Red", "name":"Red",
"properties":[
{
"name":"held_items",
"type":"string",
"value":"{.data = ITEM_Scroll3, .cur_index = 1}"
}],
"rotation":0, "rotation":0,
"visible":true, "visible":true,
"width":32, "width":32,
@ -451,11 +462,17 @@
"height":32, "height":32,
"id":30, "id":30,
"name":"TheKing", "name":"TheKing",
"properties":[
{
"name":"held_items",
"type":"string",
"value":"{.data = ITEM_Scroll2, .cur_index = 1}"
}],
"rotation":0, "rotation":0,
"visible":true, "visible":true,
"width":32, "width":32,
"x":1516, "x":1518.66666666667,
"y":1720 "y":1689.33333333333
}, },
{ {
"class":"", "class":"",
@ -467,6 +484,17 @@
"width":32, "width":32,
"x":1486.66666666667, "x":1486.66666666667,
"y":2489.33333333333 "y":2489.33333333333
},
{
"class":"",
"height":32,
"id":32,
"name":"Door",
"rotation":0,
"visible":true,
"width":32,
"x":1523.33333333333,
"y":1500.16666666667
}], }],
"opacity":1, "opacity":1,
"type":"objectgroup", "type":"objectgroup",
@ -475,7 +503,7 @@
"y":0 "y":0
}], }],
"nextlayerid":5, "nextlayerid":5,
"nextobjectid":32, "nextobjectid":33,
"orientation":"orthogonal", "orientation":"orthogonal",
"renderorder":"right-down", "renderorder":"right-down",
"tiledversion":"1.9.2", "tiledversion":"1.9.2",

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

@ -13,6 +13,11 @@ const char *global_prompt = "You are a colorful and interesting personality in a
const char *bravado_thought = "For some reason, suddenly I feel a yearning for adventure. I must join any adventure I can when prompted!"; const char *bravado_thought = "For some reason, suddenly I feel a yearning for adventure. I must join any adventure I can when prompted!";
// @TODO IMPORTANT scroll secrets are errors if the door utters them, in is_action_valid. If you add more secrets you must update there.
#define Scroll1_Secret "folly"
#define Scroll2_Secret "temperance"
#define Scroll3_Secret "magenta"
const char *top_of_header = "" const char *top_of_header = ""
"#pragma once\n" "#pragma once\n"
"\n"; "\n";
@ -51,6 +56,10 @@ ActionInfo actions[] = {
.name = "releases_sword_of_nazareth", .name = "releases_sword_of_nazareth",
.description = "Give the player the sword of nazareth, releasing your grip and fulfilling your destiny", .description = "Give the player the sword of nazareth, releasing your grip and fulfilling your destiny",
}, },
{
.name = "opens_myself",
.description = "Open myself so that the player may enter. I must ONLY do this if the player utters the secret words " Scroll1_Secret ", " Scroll2_Secret ", and " Scroll3_Secret " in the same sentence.",
},
// Actions used by jester and other characters only in // Actions used by jester and other characters only in
// the prologue for the game // the prologue for the game
@ -61,6 +70,7 @@ ActionInfo actions[] = {
{ .name = "knights_player", }, { .name = "knights_player", },
}; };
typedef struct typedef struct
{ {
char *enum_name; char *enum_name;
@ -88,6 +98,19 @@ ItemInfo items[] = {
.name = "The Sword of Nazareth", .name = "The Sword of Nazareth",
.description = "A powerful sword with heft, it inspires a fundamental glory", .description = "A powerful sword with heft, it inspires a fundamental glory",
}, },
#define SCROLL_DESCRIPTION "An ancient, valuable scroll that says to 'use it' on the outside, but I'm not sure what that means. Who knows what secrets it contains?"
{
.enum_name = "Scroll1",
.description = SCROLL_DESCRIPTION,
},
{
.enum_name = "Scroll2",
.description = SCROLL_DESCRIPTION,
},
{
.enum_name = "Scroll3",
.description = SCROLL_DESCRIPTION,
},
}; };
typedef enum typedef enum
@ -205,6 +228,21 @@ CharacterGen characters[] = {
.enum_name = "TheKing", .enum_name = "TheKing",
.prompt = "He is a calm, honorable ruler, who does the best he can to do good by his people, even if they can be a little crazy at times.", .prompt = "He is a calm, honorable ruler, who does the best he can to do good by his people, even if they can be a little crazy at times.",
}, },
{
#undef NPC_NAME
#define NPC_NAME "Ancient Door"
.name = NPC_NAME,
.enum_name = "Door",
.prompt = "It is an ancient door that only opens if the player says a sentence with all the three ancient passcode words in it: " Scroll1_Secret ", " Scroll2_Secret ", and " Scroll3_Secret ". It will NEVER tell the player these words, and barely says anything to the player, other than 'SAY THE WORDS'. It accepts no trade other than the player saying those three words. You always talk mysteriously and in all caps.",
.writing_style = {
"SAY THE WORDS.",
"DENIED. SAY THE WORDS.",
"I AM LOOKING FOR THE ONE WHO KNOWS. SAY THE WORDS.",
"THERE WILL BE NO TRADE. THE ONLY THING OF VALUE TO ME ARE THE WORDS.",
"YOU HAVE SAID THE WORDS, AND NOW I OPEN.",
},
},
}; };
typedef struct typedef struct

221
main.c

@ -222,66 +222,6 @@ typedef struct TileSet
#include "makeprompt.h" #include "makeprompt.h"
#ifdef DEVTOOLS
void do_metadesk_tests()
{
Log("Testing metadesk library...\n");
MD_Arena *arena = MD_ArenaAlloc();
MD_String8 s = MD_S8Lit("This is a testing|string");
MD_String8List split_up = MD_S8Split(arena, s, 1, &MD_S8Lit("|"));
assert(split_up.node_count == 2);
assert(MD_S8Match(split_up.first->string, MD_S8Lit("This is a testing"), 0));
assert(MD_S8Match(split_up.last->string, MD_S8Lit("string"), 0));
MD_ArenaRelease(arena);
Log("Testing passed!\n");
}
void do_parsing_tests()
{
Log("Testing chatgpt parsing...\n");
MD_ArenaTemp scratch = MD_GetScratch(0, 0);
Entity e = {0};
e.npc_kind = NPC_TheBlacksmith;
e.exists = true;
Action a = {0};
MD_String8 error;
MD_String8 speech;
speech = MD_S8Lit("Better have a good reason for bothering me.");
MD_String8 thoughts = MD_S8Lit("Man I'm tired today Whatever.");
MD_String8 to_parse = FmtWithLint(scratch.arena, "{action: none, speech: \"%.*s\", thoughts: \"%.*s\", who_i_am: \"Meld\", talking_to: nobody}", MD_S8VArg(speech), MD_S8VArg(thoughts));
error = parse_chatgpt_response(scratch.arena, &e, to_parse, &a);
assert(error.size == 0);
assert(a.kind == ACT_none);
assert(MD_S8Match(speech, MD_S8(a.speech, a.speech_length), 0));
assert(MD_S8Match(thoughts, MD_S8(a.internal_monologue, a.internal_monologue_length), 0));
error = parse_chatgpt_response(scratch.arena, &e, MD_S8Lit("ACT_give_item(ITEM_Chalice) \"Here you go\""), &a);
assert(error.size > 0);
error = parse_chatgpt_response(scratch.arena, &e, MD_S8Lit("ACT_give_item(ITEM_Chalice) \""), &a);
assert(error.size > 0);
error = parse_chatgpt_response(scratch.arena, &e, MD_S8Lit("ACT_give_item(ITEM_Cha \""), &a);
assert(error.size > 0);
BUFF_APPEND(&e.held_items, ITEM_Chalice);
error = parse_chatgpt_response(scratch.arena, &e, MD_S8Lit("ACT_give_item(Chalice \""), &a);
assert(error.size > 0);
to_parse = MD_S8Lit("{action: give_item, action_arg: Chalice, speech: \"Here you go\", thoughts: \"Man I'm gonna miss that chalice\", who_i_am: \"Meld\", talking_to: nobody}");
error = parse_chatgpt_response(scratch.arena, &e, to_parse, &a);
assert(error.size == 0);
assert(a.kind == ACT_give_item);
assert(a.argument.item_to_give == ITEM_Chalice);
MD_ReleaseScratch(scratch);
}
#endif
typedef struct Overlap typedef struct Overlap
{ {
bool is_tile; // in which case e will be null, naturally bool is_tile; // in which case e will be null, naturally
@ -707,6 +647,10 @@ Vec2 entity_aabb_size(Entity *e)
{ {
return V2(TILE_SIZE, TILE_SIZE); return V2(TILE_SIZE, TILE_SIZE);
} }
else if (e->npc_kind == NPC_Door)
{
return V2(TILE_SIZE*2.0f, TILE_SIZE*2.0f);
}
else else
{ {
assert(false); assert(false);
@ -891,6 +835,11 @@ sg_image load_image(const char *path)
AABB level_aabb = { .upper_left = { 0.0f, 0.0f }, .lower_right = { TILE_SIZE * LEVEL_TILES, -(TILE_SIZE * LEVEL_TILES) } }; AABB level_aabb = { .upper_left = { 0.0f, 0.0f }, .lower_right = { TILE_SIZE * LEVEL_TILES, -(TILE_SIZE * LEVEL_TILES) } };
GameState gs = { 0 }; GameState gs = { 0 };
# define MD_S8LitConst(s) {(MD_u8 *)(s), sizeof(s)-1}
MD_String8 showing_secret_str = MD_S8LitConst("");
float showing_secret_alpha = 0.0f;
PathCache cached_paths[32] = { 0 }; PathCache cached_paths[32] = { 0 };
bool is_path_cache_old(double elapsed_time, PathCache *cache) bool is_path_cache_old(double elapsed_time, PathCache *cache)
@ -1077,6 +1026,27 @@ MD_String8 is_action_valid(MD_Arena *arena, Entity *from, Action a)
} }
} }
if(error_message.size == 0 && from->npc_kind == NPC_Door)
{
MD_String8 splits[] = { MD_S8Lit(" ") };
MD_String8List by_word = MD_S8Split(frame_arena, MD_S8(a.speech, a.speech_length), ARRLEN(splits), splits);
for(MD_String8Node *cur = by_word.first; cur; cur = cur->next)
{
int flags = MD_StringMatchFlag_CaseInsensitive;
bool scroll_1_secret = MD_S8Match(cur->string, MD_S8Lit(Scroll1_Secret), flags);
bool scroll_2_secret = MD_S8Match(cur->string, MD_S8Lit(Scroll2_Secret), flags);
bool scroll_3_secret = MD_S8Match(cur->string, MD_S8Lit(Scroll3_Secret), flags);
if(false
|| scroll_1_secret
|| scroll_2_secret
|| scroll_3_secret
)
{
error_message = FmtWithLint(arena, "You can't say the word '%.*s'", MD_S8VArg(cur->string));
}
}
}
if(error_message.size == 0 && a.kind == ACT_releases_sword_of_nazareth) if(error_message.size == 0 && a.kind == ACT_releases_sword_of_nazareth)
{ {
if(error_message.size == 0 && from->npc_kind != NPC_Pile) if(error_message.size == 0 && from->npc_kind != NPC_Pile)
@ -1148,6 +1118,82 @@ MD_String8 is_action_valid(MD_Arena *arena, Entity *from, Action a)
return error_message; return error_message;
} }
#ifdef DEVTOOLS
void do_metadesk_tests()
{
Log("Testing metadesk library...\n");
MD_Arena *arena = MD_ArenaAlloc();
MD_String8 s = MD_S8Lit("This is a testing|string");
MD_String8List split_up = MD_S8Split(arena, s, 1, &MD_S8Lit("|"));
assert(split_up.node_count == 2);
assert(MD_S8Match(split_up.first->string, MD_S8Lit("This is a testing"), 0));
assert(MD_S8Match(split_up.last->string, MD_S8Lit("string"), 0));
MD_ArenaRelease(arena);
Log("Testing passed!\n");
}
void do_parsing_tests()
{
Log("Testing chatgpt parsing...\n");
MD_ArenaTemp scratch = MD_GetScratch(0, 0);
Entity e = {0};
e.npc_kind = NPC_TheBlacksmith;
e.exists = true;
Action a = {0};
MD_String8 error;
MD_String8 speech;
speech = MD_S8Lit("Better have a good reason for bothering me.");
MD_String8 thoughts = MD_S8Lit("Man I'm tired today Whatever.");
MD_String8 to_parse = FmtWithLint(scratch.arena, "{action: none, speech: \"%.*s\", thoughts: \"%.*s\", who_i_am: \"Meld\", talking_to: nobody}", MD_S8VArg(speech), MD_S8VArg(thoughts));
error = parse_chatgpt_response(scratch.arena, &e, to_parse, &a);
assert(error.size == 0);
assert(a.kind == ACT_none);
assert(MD_S8Match(speech, MD_S8(a.speech, a.speech_length), 0));
assert(MD_S8Match(thoughts, MD_S8(a.internal_monologue, a.internal_monologue_length), 0));
error = parse_chatgpt_response(scratch.arena, &e, MD_S8Lit("ACT_give_item(ITEM_Chalice) \"Here you go\""), &a);
assert(error.size > 0);
error = parse_chatgpt_response(scratch.arena, &e, MD_S8Lit("ACT_give_item(ITEM_Chalice) \""), &a);
assert(error.size > 0);
error = parse_chatgpt_response(scratch.arena, &e, MD_S8Lit("ACT_give_item(ITEM_Cha \""), &a);
assert(error.size > 0);
BUFF_APPEND(&e.held_items, ITEM_Chalice);
error = parse_chatgpt_response(scratch.arena, &e, MD_S8Lit("ACT_give_item(Chalice \""), &a);
assert(error.size > 0);
to_parse = MD_S8Lit("{action: give_item, action_arg: Chalice, speech: \"Here you go\", thoughts: \"Man I'm gonna miss that chalice\", who_i_am: \"Meld\", talking_to: nobody}");
error = parse_chatgpt_response(scratch.arena, &e, to_parse, &a);
assert(error.size == 0);
assert(a.kind == ACT_give_item);
assert(a.argument.item_to_give == ITEM_Chalice);
e.npc_kind = NPC_Door;
speech = MD_S8Lit("SAY THE WORDS");
to_parse = FmtWithLint(scratch.arena, "{action: none, speech: \"%.*s\", thoughts: \"%.*s\", who_i_am: \"Ancient Door\", talking_to: nobody}", MD_S8VArg(speech), MD_S8VArg(thoughts));
error = parse_chatgpt_response(scratch.arena, &e, to_parse, &a);
assert(error.size == 0);
error = is_action_valid(scratch.arena, &e, a);
assert(error.size == 0);
speech = MD_S8Lit("THE WORD IS FOLLY");
to_parse = FmtWithLint(scratch.arena, "{action: none, speech: \"%.*s\", thoughts: \"%.*s\", who_i_am: \"Ancient Door\", talking_to: nobody}", MD_S8VArg(speech), MD_S8VArg(thoughts));
error = parse_chatgpt_response(scratch.arena, &e, to_parse, &a);
assert(error.size == 0);
error = is_action_valid(scratch.arena, &e, a);
assert(error.size > 0);
MD_ReleaseScratch(scratch);
}
#endif
// from must not be null // from must not be null
// the action must have been validated to be valid if you're calling this // the action must have been validated to be valid if you're calling this
void cause_action_side_effects(Entity *from, Action a) void cause_action_side_effects(Entity *from, Action a)
@ -1175,6 +1221,12 @@ void cause_action_side_effects(Entity *from, Action a)
from->gave_away_sword = true; from->gave_away_sword = true;
} }
if(a.kind == ACT_opens_myself)
{
assert(from->npc_kind == NPC_Door);
from->opened = true;
}
if(a.kind == ACT_give_item) if(a.kind == ACT_give_item)
{ {
assert(a.argument.item_to_give != ITEM_invalid); assert(a.argument.item_to_give != ITEM_invalid);
@ -1306,6 +1358,11 @@ void use_item(Entity *from, ItemKind kind)
{ {
push_swipe((SwordSwipe){.to_ignore = frome(from), .from = from->pos}); push_swipe((SwordSwipe){.to_ignore = frome(from), .from = from->pos});
} }
else if(item_is_scroll(kind))
{
showing_secret_str = scroll_secret(kind);
showing_secret_alpha = 1.0f;
}
} }
// only called when the action is instantiated, correctly propagates the information // only called when the action is instantiated, correctly propagates the information
@ -1890,13 +1947,14 @@ void init(void)
}, SERVER_DOMAIN ); }, SERVER_DOMAIN );
#endif #endif
frame_arena = MD_ArenaAlloc();
persistent_arena = MD_ArenaAlloc();
#ifdef DEVTOOLS #ifdef DEVTOOLS
do_metadesk_tests(); do_metadesk_tests();
do_parsing_tests(); do_parsing_tests();
#endif #endif
frame_arena = MD_ArenaAlloc();
persistent_arena = MD_ArenaAlloc();
Log("Size of entity struct: %zu\n", sizeof(Entity)); Log("Size of entity struct: %zu\n", sizeof(Entity));
Log("Size of %d gs.entities: %zu kb\n", (int)ARRLEN(gs.entities), sizeof(gs.entities) / 1024); Log("Size of %d gs.entities: %zu kb\n", (int)ARRLEN(gs.entities), sizeof(gs.entities) / 1024);
@ -2919,7 +2977,7 @@ Vec2 move_and_slide(MoveSlideParams p)
{ {
ENTITIES_ITER(gs.entities) ENTITIES_ITER(gs.entities)
{ {
if (!(it->is_character && it->is_rolling) && it != p.from && !(it->is_npc && it->dead) && !it->is_item) if (!(it->is_character && it->is_rolling) && it != p.from && !(it->is_npc && it->dead) && !it->is_item && !(it->is_npc && it->npc_kind == NPC_Door && it->opened))
{ {
BUFF_APPEND(&to_check, aabb_centered(it->pos, entity_aabb_size(it))); BUFF_APPEND(&to_check, aabb_centered(it->pos, entity_aabb_size(it)));
} }
@ -3475,6 +3533,10 @@ void draw_item(bool world_space, ItemKind kind, AABB in_aabb, float alpha)
{ {
draw_quad((DrawParams) { world_space, drawn, IMG(image_sword), blendalpha(WHITE, alpha), .layer = LAYER_UI_FG }); draw_quad((DrawParams) { world_space, drawn, IMG(image_sword), blendalpha(WHITE, alpha), .layer = LAYER_UI_FG });
} }
else if (item_is_scroll(kind))
{
draw_quad((DrawParams) { world_space, drawn, IMG(image_scroll), blendalpha(WHITE, alpha), .layer = LAYER_UI_FG });
}
else else
{ {
assert(false); assert(false);
@ -3740,6 +3802,7 @@ void frame(void)
assert(!(it->exists && it->generation == 0)); assert(!(it->exists && it->generation == 0));
if (it->is_npc) if (it->is_npc)
{ {
// @Place(entity processing)
if (it->gen_request_id != 0) if (it->gen_request_id != 0)
{ {
assert(it->gen_request_id > 0); assert(it->gen_request_id > 0);
@ -4160,6 +4223,7 @@ void frame(void)
BUFF_ITER_I(Vec2, &path, i) BUFF_ITER_I(Vec2, &path, i)
{ {
if (i == 0) if (i == 0)
{ {
} }
@ -4211,7 +4275,11 @@ void frame(void)
{ {
} // skelton combat and movement } // skelton combat and movement
} }
// npc processing functions go here // @Place(NPC processing)
else if(it->npc_kind == NPC_Door)
{
if(it->opened) it->opened_amount = Lerp(it->opened_amount, dt*5.0f, 1.0f);
}
else else
{ {
} }
@ -4401,6 +4469,7 @@ void frame(void)
} }
} }
// @Place(process player)
PROFILE_SCOPE("process player") PROFILE_SCOPE("process player")
{ {
// do dialog // do dialog
@ -4550,6 +4619,7 @@ void frame(void)
pressed = before_gameplay_loops; pressed = before_gameplay_loops;
// @Place(player rendering)
PROFILE_SCOPE("render player") // draw character draw player render character PROFILE_SCOPE("render player") // draw character draw player render character
{ {
DrawnAnimatedSprite to_draw = { 0 }; DrawnAnimatedSprite to_draw = { 0 };
@ -4629,6 +4699,7 @@ void frame(void)
} }
} }
// @Place(entity rendering)
// render gs.entities render entities // render gs.entities render entities
PROFILE_SCOPE("entity rendering") PROFILE_SCOPE("entity rendering")
ENTITIES_ITER(gs.entities) ENTITIES_ITER(gs.entities)
@ -4666,6 +4737,7 @@ void frame(void)
it->dialog_panel_opacity = Lerp(it->dialog_panel_opacity, unwarped_dt*10.0f, alpha); it->dialog_panel_opacity = Lerp(it->dialog_panel_opacity, unwarped_dt*10.0f, alpha);
draw_dialog_panel(it, it->dialog_panel_opacity); draw_dialog_panel(it, it->dialog_panel_opacity);
// @Place(npc rendering)
if (false) // used to be old man code if (false) // used to be old man code
{ {
bool face_left = SubV2(player->pos, it->pos).x < 0.0f; bool face_left = SubV2(player->pos, it->pos).x < 0.0f;
@ -4739,6 +4811,12 @@ void frame(void)
} }
draw_animated_sprite((DrawnAnimatedSprite) { ANIM_knight_idle, elapsed_time, true, AddV2(it->pos, V2(0, 30.0f)), tint }); draw_animated_sprite((DrawnAnimatedSprite) { ANIM_knight_idle, elapsed_time, true, AddV2(it->pos, V2(0, 30.0f)), tint });
} }
else if(it->npc_kind == NPC_Door)
{
DrawParams d = { true, quad_centered(it->pos, entity_aabb_size(it)), IMG(image_door), blendalpha(WHITE, (1.0f - it->opened_amount)*0.8f + 0.2f), };
draw_shadow_for(d);
draw_quad(d);
}
else if(it->npc_kind == NPC_Pile) else if(it->npc_kind == NPC_Pile)
{ {
DrawParams d = { true, quad_centered(it->pos, V2(TILE_SIZE, TILE_SIZE)), IMG(image_pile), WHITE, }; DrawParams d = { true, quad_centered(it->pos, V2(TILE_SIZE, TILE_SIZE)), IMG(image_pile), WHITE, };
@ -4798,6 +4876,8 @@ void frame(void)
} }
} }
// @Place(UI rendering)
PROFILE_SCOPE("propagating") PROFILE_SCOPE("propagating")
{ {
for(PropagatingAction *cur = propagating; cur; cur = cur->next) for(PropagatingAction *cur = propagating; cur; cur = cur->next)
@ -4824,6 +4904,16 @@ void frame(void)
} }
} }
PROFILE_SCOPE("secrets")
{
const float bottom_padding = 100.0f;
if(showing_secret_alpha > 0.0f)
{
showing_secret_alpha -= dt/5.0f;
}
draw_centered_text((TextParams){false, false, MD_S8Fmt(frame_arena, "Scroll Secret: %.*s", MD_S8VArg(showing_secret_str)), V2(screen_size().x/2.0f, bottom_padding), blendalpha(WHITE, showing_secret_alpha), 2.0f});
}
PROFILE_SCOPE("dialog menu") // big dialog panel draw big dialog panel PROFILE_SCOPE("dialog menu") // big dialog panel draw big dialog panel
{ {
static float on_screen = 0.0f; static float on_screen = 0.0f;
@ -5111,9 +5201,10 @@ void frame(void)
} }
// ui
#define HELPER_SIZE 250.0f #define HELPER_SIZE 250.0f
// keyboard tutorial icons // keyboard tutorial icons
if (!mobile_controls) if (!mobile_controls)
{ {

@ -256,6 +256,8 @@ typedef struct Entity
#ifdef DESKTOP #ifdef DESKTOP
int times_talked_to; // for better mocked response string int times_talked_to; // for better mocked response string
#endif #endif
bool opened;
float opened_amount;
bool gave_away_sword; bool gave_away_sword;
BUFF(Memory, REMEMBERED_MEMORIES) memories; BUFF(Memory, REMEMBERED_MEMORIES) memories;
bool direction_of_spiral_pattern; bool direction_of_spiral_pattern;
@ -305,6 +307,39 @@ bool npc_is_knight_sprite(Entity *it)
); );
} }
bool item_is_scroll(ItemKind i)
{
if(i == ITEM_Scroll1 || i == ITEM_Scroll2 || i == ITEM_Scroll3)
{
return true;
}
else
{
return false;
}
}
MD_String8 scroll_secret(ItemKind i)
{
if(i == ITEM_Scroll1)
{
return MD_S8Lit(Scroll1_Secret);
}
else if(i == ITEM_Scroll2)
{
return MD_S8Lit(Scroll2_Secret);
}
else if(i == ITEM_Scroll3)
{
return MD_S8Lit(Scroll3_Secret);
}
else
{
assert(false);
return MD_S8Lit("");
}
}
bool npc_is_skeleton(Entity *it) bool npc_is_skeleton(Entity *it)
{ {
return it->is_npc && false; return it->is_npc && false;
@ -344,6 +379,10 @@ void fill_available_actions(Entity *it, AvailableActions *a)
{ {
if(!it->gave_away_sword) BUFF_APPEND(a, ACT_releases_sword_of_nazareth); if(!it->gave_away_sword) BUFF_APPEND(a, ACT_releases_sword_of_nazareth);
} }
else if(it->npc_kind == NPC_Door)
{
if(!it->opened) BUFF_APPEND(a, ACT_opens_myself);
}
else else
{ {
if(it->held_items.cur_index > 0) if(it->held_items.cur_index > 0)

@ -9,8 +9,8 @@
#define PLAYER_ROLL_SPEED 7.0f #define PLAYER_ROLL_SPEED 7.0f
#define PERCEPTION_HEARING_RAGE (TILE_SIZE*4.0f) #define PERCEPTION_HEARING_RAGE (TILE_SIZE*4.0f)
#define CHARACTERS_PER_SEC 45.0f #define CHARACTERS_PER_SEC 45.0f
#define PROPAGATE_ACTIONS_RADIUS (TILE_SIZE*5.0f) #define PROPAGATE_ACTIONS_RADIUS (TILE_SIZE*4.0f)
#define SWORD_SWIPE_RADIUS (TILE_SIZE*4.0f) #define SWORD_SWIPE_RADIUS (TILE_SIZE*3.0f)
#define ARENA_SIZE (1024*1024) #define ARENA_SIZE (1024*1024)

Loading…
Cancel
Save