2026-06-12 23:35:40 -05:00
|
|
|
[world]
|
|
|
|
|
name = "Kiln Demo"
|
2026-06-13 15:33:04 -05:00
|
|
|
start = "start"
|
2026-06-12 23:35:40 -05:00
|
|
|
|
2026-06-13 01:25:58 -05:00
|
|
|
# Named Rhai scripts shared across all boards in this world.
|
|
|
|
|
# Objects reference a script by name via `script_name`.
|
|
|
|
|
[scripts]
|
|
|
|
|
greeter = """
|
|
|
|
|
fn init() {
|
|
|
|
|
log(`hello from object — player at ${Board.player_x}, ${Board.player_y}`);
|
|
|
|
|
set_tile(2); // change my glyph to ☻ — proves the write path
|
|
|
|
|
say("Hello there,\\ntraveller!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn tick(dt) {
|
|
|
|
|
//log(`x: ${Me.x} ${Board.player_x} y: ${Me.y} ${Board.player_y} q: ${Queue.length()}`);
|
|
|
|
|
if Board.player_x == Me.x && Board.player_y == Me.y && Queue.length() == 0 {
|
|
|
|
|
say("Hey! Get offa me!");
|
|
|
|
|
delay(5.0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
mover = """
|
2026-06-13 17:58:04 -05:00
|
|
|
fn init() {
|
|
|
|
|
if Registry.get("dancer_x") != () {
|
|
|
|
|
teleport(Registry.get("dancer_x"), Registry.get("dancer_y"));
|
|
|
|
|
} else {
|
|
|
|
|
Registry.set("dancer_x", Me.x);
|
|
|
|
|
Registry.set("dancer_y", Me.y);
|
|
|
|
|
log(`Set reg to ${Me.x} ${Me.y}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-06-13 01:25:58 -05:00
|
|
|
// move() costs 250 ms, so the object steps ~4 cells/sec no matter how often
|
|
|
|
|
// tick() runs. Queue.length() avoids piling up moves; blocked() avoids walking
|
|
|
|
|
// into a wall (or another object's already-queued move this tick).
|
|
|
|
|
fn tick(dt) {
|
2026-06-13 17:58:04 -05:00
|
|
|
if Queue.length() == 0 { dance(); }
|
2026-06-13 15:33:04 -05:00
|
|
|
}
|
2026-06-13 17:58:04 -05:00
|
|
|
fn dance() {
|
2026-06-13 15:33:04 -05:00
|
|
|
move(East);
|
|
|
|
|
move(South);
|
|
|
|
|
move(North);
|
|
|
|
|
move(East);
|
|
|
|
|
say("Hey!", 0.5);
|
|
|
|
|
delay(0.5);
|
|
|
|
|
move(West);
|
|
|
|
|
move(South);
|
|
|
|
|
move(North);
|
|
|
|
|
move(West);
|
|
|
|
|
say("Ho!", 0.5);
|
|
|
|
|
delay(0.5);
|
2026-06-13 01:25:58 -05:00
|
|
|
}
|
|
|
|
|
// Fires when something steps into this object; id is the bumper's object id,
|
|
|
|
|
// or -1 for the player.
|
|
|
|
|
fn bump(id) {
|
|
|
|
|
log(`mover bumped by ${id}`);
|
|
|
|
|
say("Ow!");
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
muffin = """
|
|
|
|
|
fn bump(id) {
|
|
|
|
|
scroll([
|
|
|
|
|
"You find a small muffin on the ground, your favorite kind.",
|
|
|
|
|
"It smells of cinnamon and warm mornings.",
|
|
|
|
|
["eat", "Pick up the muffin and eat it."],
|
|
|
|
|
["ignore", "This is obviously a trap — ignore it."]
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
fn eat() {
|
|
|
|
|
log("You ate the muffin. Delicious.");
|
|
|
|
|
say("Mmm!");
|
|
|
|
|
}
|
|
|
|
|
fn ignore() {
|
|
|
|
|
log("You walk away from the muffin. Wise.");
|
|
|
|
|
say("Suspicious...");
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
noticeboard = """
|
|
|
|
|
fn bump(id) {
|
|
|
|
|
scroll([
|
|
|
|
|
" TOWN NOTICE BOARD",
|
|
|
|
|
" ",
|
|
|
|
|
"ROAD CLOSURE — The eastern road through Miller's Crossing remains closed",
|
|
|
|
|
"following flood damage to the main bridge. Repairs are underway but travellers",
|
|
|
|
|
"should expect delays of at least three weeks. The north fork via Ashwell is",
|
|
|
|
|
"passable, though it adds half a day to the journey.",
|
|
|
|
|
" ",
|
|
|
|
|
"LOST ANIMAL — One grey mule, answers to the name Pepper. Last seen grazing",
|
|
|
|
|
"near the old mill on the morning of the 14th. The animal has a notched left",
|
|
|
|
|
"ear and wears a blue rope halter. Any information to the innkeeper; a reward",
|
|
|
|
|
"of two silver pieces is offered for her safe return.",
|
|
|
|
|
" ",
|
|
|
|
|
"POSITION AVAILABLE — Captain Aldric of the town garrison seeks an experienced",
|
|
|
|
|
"wilderness guide for an expedition into the Darkwood. Duration: ten to fourteen",
|
|
|
|
|
"days. Pay is good and provisions will be supplied. Candidates must present",
|
|
|
|
|
"themselves at the barracks before the evening bell. Some risk is involved and",
|
|
|
|
|
"the captain asks that only those in sound health and good standing apply.",
|
|
|
|
|
" ",
|
|
|
|
|
"HARVEST FESTIVAL — The annual Harvest Festival will be held on the last",
|
|
|
|
|
"Saturday of the month. The market square will be closed to carts from dawn.",
|
|
|
|
|
"Stall permits must be obtained from the clerk's office no later than Thursday.",
|
|
|
|
|
"There will be music, a pie competition, and the traditional lantern parade at",
|
|
|
|
|
"dusk. All residents are warmly encouraged to attend.",
|
|
|
|
|
" ",
|
|
|
|
|
" Posted by order of the Town Council.",
|
|
|
|
|
" Unauthorised notices will be removed.",
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
|
2026-06-13 13:59:13 -05:00
|
|
|
bookshelf = """
|
|
|
|
|
fn bump(id) {
|
|
|
|
|
scroll([
|
|
|
|
|
" THE BOOKSHELF",
|
|
|
|
|
" ",
|
|
|
|
|
"A well-worn shelf packed with old volumes. You scan the spines:",
|
|
|
|
|
" ",
|
|
|
|
|
" 'Practical Herbalism and Country Remedies'",
|
|
|
|
|
" 'A History of the Seven Kingdoms, Vol. II'",
|
|
|
|
|
" 'Monsters of the Northern Reach'",
|
|
|
|
|
" 'The Innkeeper's Handbook'",
|
|
|
|
|
" 'Common Stars and Their Names'",
|
|
|
|
|
" 'Letters to No One in Particular' (handwritten)",
|
|
|
|
|
" ",
|
|
|
|
|
"One has a pressed flower tucked in as a bookmark.",
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
fireplace = """
|
|
|
|
|
fn bump(id) {
|
|
|
|
|
say("The fire crackles warmly.\\nYou feel at ease.");
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
chest = """
|
|
|
|
|
fn bump(id) {
|
|
|
|
|
scroll([
|
|
|
|
|
" THE CHEST",
|
|
|
|
|
" ",
|
|
|
|
|
"A sturdy oak chest with iron fittings. The latch is unlocked.",
|
|
|
|
|
" ",
|
|
|
|
|
"Inside you find:",
|
|
|
|
|
"",
|
|
|
|
|
"- A wool blanket, slightly moth-eaten",
|
|
|
|
|
"- Three copper coins",
|
|
|
|
|
"- A half-empty bottle of something medicinal",
|
|
|
|
|
"- A child's wooden toy horse",
|
|
|
|
|
"- A folded letter, sealed but never sent",
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
yammerer = """
|
|
|
|
|
fn tick(dt) {
|
|
|
|
|
if Queue.length() == 0 {
|
|
|
|
|
say("blahblahblah");
|
|
|
|
|
delay(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
|
2026-06-12 23:35:40 -05:00
|
|
|
[boards.start.map]
|
2026-05-16 01:50:05 -05:00
|
|
|
name = "Starting Room"
|
|
|
|
|
width = 60
|
|
|
|
|
height = 25
|
2026-06-06 14:11:20 -05:00
|
|
|
player_start = "@" # placed by the '@' grid char (convention)
|
2026-05-16 01:50:05 -05:00
|
|
|
|
2026-06-12 23:35:40 -05:00
|
|
|
[boards.start.palette]
|
2026-05-19 00:07:04 -05:00
|
|
|
" " = { archetype = "empty", tile = " ", fg = "#000000", bg = "#000000" }
|
|
|
|
|
"#" = { archetype = "wall", tile = "#", fg = "#808080", bg = "#606060" }
|
|
|
|
|
"+" = { archetype = "banana", tile = "#", fg = "#808080", bg = "#606060" }
|
2026-06-06 14:11:20 -05:00
|
|
|
"o" = { archetype = "crate", tile = 254, fg = "#aaaaaa", bg = "#000000" }
|
|
|
|
|
"-" = { archetype = "hcrate", tile = 29, fg = "#aaaaaa", bg = "#000000" }
|
|
|
|
|
"|" = { archetype = "vcrate", tile = 18, fg = "#aaaaaa", bg = "#000000" }
|
2026-05-16 01:50:05 -05:00
|
|
|
|
2026-06-06 18:49:45 -05:00
|
|
|
# Optional visual floor layer, drawn under every empty cell (and revealed when a
|
|
|
|
|
# crate is pushed away). This is a grid form with its own palette: `g`/`d`/`s`
|
|
|
|
|
# name the built-in generators (random dark, low-saturation texture cached at
|
|
|
|
|
# load); a palette entry could also be a fixed glyph like
|
|
|
|
|
# `{ tile = ".", fg = "#222", bg = "#000" }`.
|
2026-06-12 23:35:40 -05:00
|
|
|
[boards.start.floor]
|
2026-06-06 18:49:45 -05:00
|
|
|
content = """
|
|
|
|
|
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggg gggggggggggggsggggdddddddddddddddddddddggggggggg
|
|
|
|
|
gggggg gggggggggggggsggggdddddddddddddddddddddggggggggg
|
|
|
|
|
gggggg gggggggggggggsggggdddddddddddddddddddddggggggggg
|
|
|
|
|
gggggg gggggggggggggsggggdddddddddddddddddddddggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsggggdddddddddddddddddddddggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsggggdddddddddddddddddddddggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsggggdddddddddddddddddddddggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggsgggggggggggggggggggggggggggggggggg
|
|
|
|
|
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
|
|
|
|
|
"""
|
|
|
|
|
|
2026-06-12 23:35:40 -05:00
|
|
|
[boards.start.floor.palette]
|
2026-06-06 18:49:45 -05:00
|
|
|
"g" = "grass"
|
|
|
|
|
"d" = "dirt"
|
|
|
|
|
"s" = "stone"
|
|
|
|
|
" " = { tile = "~", fg = "#6666ff", bg = "#000066" }
|
|
|
|
|
|
2026-06-12 23:35:40 -05:00
|
|
|
[boards.start.grid]
|
2026-05-16 01:50:05 -05:00
|
|
|
content = """
|
|
|
|
|
############################################################
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
2026-06-13 16:24:29 -05:00
|
|
|
# 1 #
|
2026-06-11 18:53:52 -05:00
|
|
|
# ###### B #
|
2026-05-16 01:50:05 -05:00
|
|
|
# # #
|
2026-05-17 15:20:46 -05:00
|
|
|
# +++ # #
|
2026-05-16 01:50:05 -05:00
|
|
|
# # #
|
2026-06-06 20:01:07 -05:00
|
|
|
# | #
|
2026-05-16 01:50:05 -05:00
|
|
|
# #
|
2026-06-11 18:53:52 -05:00
|
|
|
# oo G - @ #
|
2026-05-16 01:50:05 -05:00
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
2026-06-11 18:53:52 -05:00
|
|
|
# M #
|
2026-05-16 01:50:05 -05:00
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
############################################################
|
|
|
|
|
"""
|
2026-05-30 21:22:36 -05:00
|
|
|
|
2026-06-06 01:37:19 -05:00
|
|
|
# Placed by its grid character `G` (uppercase-letter convention for objects)
|
|
|
|
|
# rather than x/y; the cell under it loads as Empty.
|
2026-06-12 23:35:40 -05:00
|
|
|
[[boards.start.objects]]
|
2026-05-30 21:22:36 -05:00
|
|
|
fg = "#aa3333"
|
|
|
|
|
bg = "#000000"
|
2026-06-06 01:37:19 -05:00
|
|
|
palette = "G"
|
2026-05-30 21:22:36 -05:00
|
|
|
tile = "#"
|
2026-06-06 01:37:19 -05:00
|
|
|
solid = false
|
2026-06-04 20:11:55 -05:00
|
|
|
script_name = "greeter"
|
|
|
|
|
|
2026-06-06 17:36:00 -05:00
|
|
|
# A solid object placed by x/y that paces east on its own. Demonstrates the
|
|
|
|
|
# rate-limited move(), the blocked() collision check, the Queue object, and the
|
|
|
|
|
# bump() hook (walk the player into it to trigger a bump).
|
2026-06-12 23:35:40 -05:00
|
|
|
[[boards.start.objects]]
|
2026-06-06 17:36:00 -05:00
|
|
|
x = 10
|
|
|
|
|
y = 12
|
|
|
|
|
fg = "#33aa33"
|
|
|
|
|
bg = "#000000"
|
|
|
|
|
tile = 1
|
|
|
|
|
script_name = "mover"
|
|
|
|
|
|
2026-06-12 23:35:40 -05:00
|
|
|
[[boards.start.objects]]
|
2026-06-10 01:42:33 -05:00
|
|
|
palette = "M"
|
|
|
|
|
tile = 15
|
|
|
|
|
fg = "#ffdd88"
|
|
|
|
|
bg = "#000000"
|
|
|
|
|
solid = true
|
|
|
|
|
name = "muffin"
|
|
|
|
|
script_name = "muffin"
|
|
|
|
|
|
2026-06-11 18:53:52 -05:00
|
|
|
# Notice board — long scroll to test overflow and scrolling.
|
2026-06-12 23:35:40 -05:00
|
|
|
[[boards.start.objects]]
|
2026-06-11 18:53:52 -05:00
|
|
|
palette = "B"
|
|
|
|
|
tile = 240
|
|
|
|
|
fg = "#cc9944"
|
|
|
|
|
bg = "#000000"
|
|
|
|
|
solid = true
|
|
|
|
|
name = "noticeboard"
|
|
|
|
|
script_name = "noticeboard"
|
2026-06-13 13:59:13 -05:00
|
|
|
|
2026-06-13 16:24:29 -05:00
|
|
|
[[boards.start.portals]]
|
|
|
|
|
name = "to_house"
|
|
|
|
|
palette = "1"
|
|
|
|
|
target_map = "house"
|
|
|
|
|
target_entry = "from_start"
|
|
|
|
|
|
2026-06-13 13:59:13 -05:00
|
|
|
[boards.house.map]
|
|
|
|
|
name = "The House"
|
|
|
|
|
width = 60
|
|
|
|
|
height = 25
|
|
|
|
|
player_start = "@"
|
|
|
|
|
|
|
|
|
|
[boards.house.palette]
|
|
|
|
|
" " = { archetype = "empty", tile = " ", fg = "#000000", bg = "#000000" }
|
|
|
|
|
"#" = { archetype = "wall", tile = 178, fg = "#888888", bg = "#555555" }
|
|
|
|
|
|
|
|
|
|
[boards.house.floor]
|
|
|
|
|
tile = 176
|
|
|
|
|
fg = "#888888"
|
|
|
|
|
bg = "#444444"
|
|
|
|
|
|
|
|
|
|
[boards.house.grid]
|
|
|
|
|
content = """
|
|
|
|
|
############################################################
|
|
|
|
|
# #
|
|
|
|
|
# K ###F### #
|
|
|
|
|
# # # #
|
|
|
|
|
# ####### #
|
2026-06-13 16:24:29 -05:00
|
|
|
# 1 #
|
2026-06-13 13:59:13 -05:00
|
|
|
# #
|
|
|
|
|
# ######### T #
|
|
|
|
|
# # # T #
|
|
|
|
|
# ######### #
|
|
|
|
|
# T T #
|
|
|
|
|
# #
|
|
|
|
|
# @ T #
|
|
|
|
|
# #
|
|
|
|
|
# T #
|
|
|
|
|
# ######C###### #
|
|
|
|
|
# T # # #
|
|
|
|
|
# ############# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
# #
|
|
|
|
|
############################################################
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
[[boards.house.objects]]
|
|
|
|
|
palette = "K"
|
|
|
|
|
tile = 240
|
|
|
|
|
fg = "#aa7733"
|
|
|
|
|
bg = "#3d1c00"
|
|
|
|
|
solid = true
|
|
|
|
|
name = "bookshelf"
|
|
|
|
|
script_name = "bookshelf"
|
|
|
|
|
|
|
|
|
|
[[boards.house.objects]]
|
|
|
|
|
palette = "F"
|
|
|
|
|
tile = 15
|
|
|
|
|
fg = "#ff8800"
|
|
|
|
|
bg = "#220000"
|
|
|
|
|
solid = true
|
|
|
|
|
name = "fireplace"
|
|
|
|
|
script_name = "fireplace"
|
|
|
|
|
|
|
|
|
|
[[boards.house.objects]]
|
|
|
|
|
palette = "C"
|
|
|
|
|
tile = 240
|
|
|
|
|
fg = "#ccaa44"
|
|
|
|
|
bg = "#222200"
|
|
|
|
|
solid = true
|
|
|
|
|
name = "chest"
|
|
|
|
|
script_name = "chest"
|
|
|
|
|
|
|
|
|
|
[[boards.house.objects]]
|
|
|
|
|
palette = "T"
|
|
|
|
|
tile = 1
|
|
|
|
|
fg = "#99ff44"
|
|
|
|
|
bg = "#000000"
|
|
|
|
|
solid = true
|
|
|
|
|
script_name = "yammerer"
|
2026-06-13 16:24:29 -05:00
|
|
|
|
|
|
|
|
[[boards.house.portals]]
|
|
|
|
|
name = "from_start"
|
|
|
|
|
palette = "1"
|
|
|
|
|
target_map = "start"
|
|
|
|
|
target_entry = "to_house"
|