Files
kiln/maps/start.toml
T

305 lines
12 KiB
TOML
Raw Normal View History

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 = """
2026-07-07 23:55:27 -05:00
fn init(me) {
log(`hello from object — player at ${Player.x}, ${Player.y}`);
2026-06-13 01:25:58 -05:00
set_tile(2); // change my glyph to ☻ — proves the write path
say("Hello there,\\ntraveller!");
2026-07-07 23:55:27 -05:00
log(`Player health: ${Player.health}`);
2026-06-13 01:25:58 -05:00
}
2026-07-07 23:55:27 -05:00
fn tick(me, dt) {
if Player.x == me.x && Player.y == me.y && !me.waiting {
2026-06-13 01:25:58 -05:00
say("Hey! Get offa me!");
2026-06-28 00:12:52 -05:00
me.delay(5.0);
2026-06-13 01:25:58 -05:00
}
}
"""
mover = """
2026-07-07 23:55:27 -05:00
fn init(me) {
log(`q: ${me.queue.length}`);
if Board.registry.get("dancer_x") != () {
let new_x = Board.registry.get("dancer_x");
let new_y = Board.registry.get("dancer_y");
2026-06-28 00:12:52 -05:00
if me.x != new_x || me.y != new_y {
2026-07-08 10:06:25 -05:00
teleport(me.id, new_x, new_y);
2026-06-13 18:43:29 -05:00
}
2026-06-13 17:58:04 -05:00
} else {
Board.registry.set("dancer_x", me.x);
Board.registry.set("dancer_y", me.y);
2026-06-28 00:12:52 -05:00
log(`Set reg to ${me.x} ${me.y}`);
2026-06-13 17:58:04 -05:00
}
}
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).
2026-07-10 01:20:26 -05:00
fn tick(me, dt) {
2026-06-28 00:12:52 -05:00
if !me.waiting { dance(me); }
2026-06-13 15:33:04 -05:00
}
2026-06-28 00:12:52 -05:00
fn dance(me) {
2026-06-13 15:33:04 -05:00
move(East);
move(South);
move(North);
move(East);
say("Hey!", 0.5);
2026-06-28 00:12:52 -05:00
delay(me, 0.5);
2026-06-13 15:33:04 -05:00
move(West);
move(South);
move(North);
move(West);
say("Ho!", 0.5);
2026-06-28 00:12:52 -05:00
me.delay(0.5);
2026-06-13 01:25:58 -05:00
}
2026-07-08 13:21:27 -05:00
// Fires when a solid (the player, an object, or a pushed crate) presses into this
// object; dir is the direction the bump came from.
fn bump(me, dir) {
log(`mover bumped from ${dir}`);
2026-06-13 01:25:58 -05:00
say("Ow!");
}
"""
muffin = """
2026-07-08 13:21:27 -05:00
fn bump(me, _dir) {
2026-06-13 01:25:58 -05:00
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."]
]);
}
2026-07-07 23:55:27 -05:00
fn eat(me) {
2026-06-25 00:04:42 -05:00
say("Yeah it was poisoned.");
alter_health(-2);
2026-06-13 01:25:58 -05:00
}
fn ignore() {
log("You walk away from the muffin. Wise.");
say("Suspicious...");
}
"""
noticeboard = """
2026-07-08 13:21:27 -05:00
fn bump(me, _dir) {
2026-06-13 01:25:58 -05:00
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.",
2026-06-28 00:12:52 -05:00
" Unauthorized notices will be removed.",
2026-06-13 01:25:58 -05:00
]);
}
"""
2026-06-13 13:59:13 -05:00
bookshelf = """
2026-07-08 13:21:27 -05:00
fn bump(me, _dir) {
2026-06-13 13:59:13 -05:00
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 = """
2026-07-08 13:21:27 -05:00
fn bump(me, _dir) {
2026-06-13 13:59:13 -05:00
say("The fire crackles warmly.\\nYou feel at ease.");
}
"""
chest = """
2026-07-08 13:21:27 -05:00
fn bump(me, _dir) {
2026-06-13 13:59:13 -05:00
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 = """
2026-07-07 23:55:27 -05:00
fn tick(me, dt) {
2026-06-28 00:12:52 -05:00
if !me.waiting {
2026-06-13 13:59:13 -05:00
say("blahblahblah");
delay(1);
}
}
"""
2026-06-21 22:04:10 -05:00
shifter = """
2026-07-07 23:55:27 -05:00
fn tick(me, dt) {
2026-06-28 00:12:52 -05:00
let x = me.x;
let y = me.y;
2026-06-21 22:04:10 -05:00
2026-06-28 00:12:52 -05:00
if !me.waiting {
2026-06-21 22:04:10 -05:00
shift([[x-1, y], [x, y-1], [x+1, y], [x, y+1]]);
delay(0.25);
}
}
"""
2026-07-10 23:16:28 -05:00
# A trigger script: no glyph, not solid — it just watches for the player stepping
# onto its cell and logs. Triggers are placed via [[boards.NAME.triggers]].
tripwire = """
fn tick(me, dt) {
if Player.x == me.x && Player.y == me.y && !me.waiting {
log("tripwire: the player crossed here");
me.delay(2.0);
}
}
"""
2026-06-12 23:35:40 -05:00
[boards.start.map]
name = "Starting Room"
width = 60
height = 25
2026-07-10 23:16:28 -05:00
# A single procedural grass floor across the whole board (the old mixed
# grass/dirt/stone/water floor is not representable with one floor attribute).
floor = { generator = "grass" }
2026-07-10 23:16:28 -05:00
# The single grid: all solids and most non-solids (terrain, the player, objects and
# the portal). A space is always a transparent empty cell, so the floor shows through.
[boards.start.grid]
content = """
############################################################
# #
2026-06-21 22:04:10 -05:00
# o #
# oS #
# #
2026-06-13 16:24:29 -05:00
# 1 #
2026-07-08 10:06:25 -05:00
# )######( B #
# # #
2026-07-08 10:06:25 -05:00
# +++ # v #
# # #
2026-06-06 20:01:07 -05:00
# | #
# #
2026-06-15 23:35:18 -05:00
# V oo G - @ #
2026-06-21 18:27:45 -05:00
# /# #
# t #
# #
2026-06-13 21:33:38 -05:00
# >| #
# #
2026-06-13 21:33:38 -05:00
# - #
# ^ #
2026-06-11 18:53:52 -05:00
# M #
# #
# #
# #
############################################################
"""
2026-07-10 23:16:28 -05:00
[boards.start.grid.palette]
2026-06-15 23:35:18 -05:00
"#" = { kind = "wall", tile = "#", fg = "#808080", bg = "#606060" }
"+" = { kind = "banana", tile = "#", fg = "#808080", bg = "#606060" } # unknown kind -> ErrorBlock demo
"o" = { kind = "crate", tile = 254, fg = "#aaaaaa", bg = "#000000" }
"-" = { kind = "hcrate", tile = 29, fg = "#aaaaaa", bg = "#000000" }
"|" = { kind = "vcrate", tile = 18, fg = "#aaaaaa", bg = "#000000" }
">" = { kind = "pusher_east" }
"^" = { kind = "pusher_north" }
"@" = { kind = "player" }
"1" = { kind = "portal", name = "to_house", target_map = "house", target_entry = "from_start" }
"G" = { kind = "object", tile = "#", fg = "#aa3333", bg = "#000000", solid = false, script_name = "greeter" }
"V" = { kind = "object", tile = 1, fg = "#33aa33", bg = "#000000", script_name = "mover" }
"M" = { kind = "object", tile = 15, fg = "#ffdd88", bg = "#000000", solid = true, name = "muffin", script_name = "muffin" }
"B" = { kind = "object", tile = 240, fg = "#cc9944", bg = "#000000", solid = true, name = "noticeboard", script_name = "noticeboard" }
2026-06-21 22:04:10 -05:00
"S" = { kind = "object", tile = 240, fg = "#cc9944", bg = "#000000", solid = true, name = "shifter", script_name = "shifter" }
2026-06-21 18:27:45 -05:00
"/" = { kind = "spinner_cw" }
"t" = { kind = "gem" }
2026-07-08 10:06:25 -05:00
"v" = { kind = "transporter_south" }
")" = { kind = "transporter_east" }
"(" = { kind = "transporter_west" }
2026-05-30 21:22:36 -05:00
2026-07-10 23:16:28 -05:00
# Triggers: invisible, non-solid, script-only objects placed off the grid. This one
# watches for the player and logs when they reach its cell.
[[boards.start.triggers]]
x = 40
y = 12
script_name = "tripwire"
2026-06-13 16:24:29 -05:00
2026-06-13 13:59:13 -05:00
[boards.house.map]
name = "The House"
width = 60
height = 25
2026-07-10 23:16:28 -05:00
# A single fixed floor glyph across the whole board.
floor = { tile = 176, fg = "#888888", bg = "#444444" }
2026-06-13 13:59:13 -05:00
2026-07-10 23:16:28 -05:00
# The single grid: terrain, the player, objects and the return portal.
[boards.house.grid]
2026-06-13 13:59:13 -05:00
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 # # #
# ############# #
# #
# #
# #
# #
# #
# #
############################################################
"""
2026-07-10 23:16:28 -05:00
[boards.house.grid.palette]
2026-06-15 23:35:18 -05:00
"#" = { kind = "wall", tile = 178, fg = "#888888", bg = "#555555" }
"@" = { kind = "player" }
"1" = { kind = "portal", name = "from_start", target_map = "start", target_entry = "to_house" }
"K" = { kind = "object", tile = 240, fg = "#aa7733", bg = "#3d1c00", solid = true, name = "bookshelf", script_name = "bookshelf" }
"F" = { kind = "object", tile = 15, fg = "#ff8800", bg = "#220000", solid = true, name = "fireplace", script_name = "fireplace" }
"C" = { kind = "object", tile = 240, fg = "#ccaa44", bg = "#222200", solid = true, name = "chest", script_name = "chest" }
"T" = { kind = "object", tile = 1, fg = "#99ff44", bg = "#000000", solid = true, script_name = "yammerer" }
2026-06-13 13:59:13 -05:00