[map] name = "Starting Room" width = 60 height = 25 player_start = "@" # placed by the '@' grid char (convention) [palette] " " = { archetype = "empty", tile = " ", fg = "#000000", bg = "#000000" } "#" = { archetype = "wall", tile = "#", fg = "#808080", bg = "#606060" } "+" = { archetype = "banana", tile = "#", fg = "#808080", bg = "#606060" } "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" } # 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" }`. [floor] 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 """ [floor.palette] "g" = "grass" "d" = "dirt" "s" = "stone" " " = { tile = "~", fg = "#6666ff", bg = "#000066" } [grid] content = """ ############################################################ # # # # # # # # # # # ###### # # # # # +++ # # # # # # | # # # # oo G - M @ # # # # # # # # # # # # # # # # # # # # # # # ############################################################ """ # Placed by its grid character `G` (uppercase-letter convention for objects) # rather than x/y; the cell under it loads as Empty. [[objects]] fg = "#aa3333" bg = "#000000" palette = "G" tile = "#" solid = false script_name = "greeter" # 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). [[objects]] x = 10 y = 12 fg = "#33aa33" bg = "#000000" tile = 1 script_name = "mover" [[objects]] palette = "M" tile = 15 fg = "#ffdd88" bg = "#000000" solid = true name = "muffin" script_name = "muffin" [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, traveller!"); } 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 = """ // 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) { if Queue.length() == 0 { move(East); } } // 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..."); } """