include, plotscr.hsd include, scancode.hsi include, baconthulhu.hsi #----------------------------------------------------------------------- global variable(0, recursion) global variable(1, growth cycles) global variable(3, effects) global variable(4, hero atk frames) global variable(5, metadata) global variable(6, find x) global variable(7, find y) global variable(8, generating) global variable(9, stairs ignore) global variable(10, update counter) global variable(11, spawn x) global variable(12, spawn y) global variable(13, meters) global variable(14, health meter) global variable(15, stamina meter) global variable(16, monster meter) global variable(17, monster meter ticks) global variable(18, regen state) global variable(19, select menu done) global variable(20, current monster hp) global variable(21, current monster max) global variable(22, spawn cultist x) global variable(23, spawn cultist y) global variable(24, spawn misa x) global variable(25, spawn misa y) global variable(26, spawn bacontologist x) global variable(27, spawn bacontologist y) global variable(28, baconthulhu dead) global variable(29, monster kills on date) global variable(30, death count) global variable(31, c:recursion) global variable(32, c:not okay) global variable(33, c:okay) global variable(34, c:zone) global variable(35, chalk meter) global variable(36, chalk decay) global variable(37, jiffy level) global variable(38, jiffy meter) global variable(39, cur floor variant) global variable(40, repel level) global variable(41, repel meter) global variable(42, force save steps) global variable(43, money sl) global variable(44, passage ms) global variable(45, baconthulhu anim) global variable(46, step count) global variable(47, v:hour) global variable(48, v:min) global variable(49, v:sec) define constant(200, monster kill count) # Stair position variables are stored starting at global 500 define constant(500, stair pos var) # All globals starting with ID 1000 are used as temporary space for # exporting/importing saved map state to save slots. define constant(1000, savetmp) define constant(1008, tilestart) #----------------------------------------------------------------------- # string constants define constant(1, msg) # +4 strings used by console define constant(6, money str) define constant(7, tmp str) define constant(9, str:end thanks) # timer constants define constant(0, main loop timer) define constant(1, temp timer) define constant(2, spawn timer) define constant(3, regen timer) define constant(4, victory timer) define constant(5, monster meter timer) define constant(6, spawn cultist timer) define constant(7, spawn misa timer) define constant(8, spawn bacontologist timer) define constant(9, end of game timer) define constant(10, timer:console decay) define constant(11, timer:idle save) # using NPC extra data as bitsets define constant(0, nbit:deadend) define constant(1, nbit:justturned) # hero frames define constant(1, hero walking) define constant(4, hero attacking) define constant(11, hero celebrating) define constant(18, hero waiting) # non-monster npcs define constant(97, bacontologist) define constant(98, misa the hamster) define constant(99, robed cultist) # special monsters define constant(35, bacon body) # walkabout effects define constant(7, effect:miss) define constant(3, effect:punch) define constant(5, effect:sword) define constant(6, effect:axe) define constant(15, effect:tofu) define constant(14, effect:bacon explosion) define constant(29, effect:wavy) # attack effects define constant(0, teleport cloud) # weapon effects define constant(1, magic:fire) define constant(2, magic:bat) define constant(3, magic:monarch) define constant(4, magic:love) # regen constants define constant(0, regen:stamina) define constant(1, regen:health) define constant(2, regen:health skip) # Map Layer constants define constant(0, layer:base) define constant(1, layer:chalk) define constant(2, layer:item) define constant(3, layer:fog) # Sfx constants define constant(0, s:coin pickup) # other constants define constant(18, seconds) define constant(-1, counterclockwise) define constant(1, clockwise) define constant(6, threshhold) define constant(5, last map) define constant(0, void) define constant(64, first floor) define constant(67, last floor) define constant(1, first chalk floor) define constant(8, last chalk floor) define constant(1, chalk x mark) define constant(2, chalk circle) define constant(7, chalk heart) define constant(8, chalk spiral) define constant(3, chalk up) define constant(4, chalk right) define constant(5, chalk down) define constant(6, chalk left) define constant(2, first wall) define constant(48, last wall) define constant(49, stairs up) define constant(50, stairs down) define constant(1, first treasure) define constant(4, treasure types) define constant(15, item icons) define constant(1, fog of war) define constant(25, treasure rate) define constant(1, spawn delay) define constant(6, last monster slot) define constant(12, monsters per kilotile) define constant(33, monster item rate) define constant(6, chalk use count) define constant(100, full jiffy charge) define constant(80, full repel charge) define constant(80, first crack tile) define constant(88, last crack tile) define constant(1, smashed wall floor) define constant(50, force save step frequency) #----------------------------------------------------------------------- script, suspend all, begin suspend player suspend npcs suspend timers end script, resume all, begin resume player resume npcs resume timers end script, anchor align, sl, edge, begin set horiz anchor(sl, edge) set horiz align(sl, edge) end #----------------------------------------------------------------------- plotscript, init game, begin show select screen init for new game and load game init map end script, init for new game and load game, begin create effects layer create meters create map metadata set timer(regen timer, 1, seconds, @hero regen) end script, show death screen, begin reset to title screen end script, show select screen, begin select menu done := false show backdrop(1) reset palette update palette set tag(tag:save game exists, save slot used(1)) import globals(1, @death count, @death count) if(death count >= 1) then( set tag(tag:save scummer, ON) set tag(tag:save game exists, OFF) ) while(select menu done == false) do( open menu(3) if(keyval(key:ESC) > 0) then(reset to title screen) wait for text box wait(1) ) # Starting a new game! erase saves set tag(tag:save scummer, OFF) death count := 0 show map end plotscript, exit select menu, begin select menu done := true end plotscript, reset to title screen, begin game over end plotscript, on close main menu, begin save progress update meters end plotscript, save and quit from menu, begin # Don't actually need to call "save progress" here because # it will have always been called just a moment before in # "on close main menu" reset to title screen end script, save progress, begin force save steps := 0 if(baconthulhu dead) then(exit script) # This only knows how to save the state of the current map, so it is # vital that it should always be called before you change maps. save in slot(1) # Prepare globals to save this map into another save slot write global(1000, 1) # save format version number write global(1001, map width) write global(1002, map height) write global(1003, get up stairs x(current map)) write global(1004, get up stairs y(current map)) write global(1005, get down stairs x(current map)) write global(1006, get down stairs y(current map)) write global(1007, get map creation(current map)) # Store the map tile state variable(p, x, y, v) p := tilestart for(y, 0, map height -- 1) do( for(x, 0, map width -- 1) do( v := read map block(x, y, layer:base) + read map block(x, y, layer:item) * 256 + read map block(x, y, layer:fog) * 65536 + read map block(x, y, layer:chalk) * 16777216 write global(p, v) p += 1 ) ) # Store the NPC state variable(ref, id, how many p, how many) how many := 0 how many p := p p += 1 for(ref, -300, -1) do( id := get npc id(ref) if(id >= 0) then( v := id + npc x(ref) * 256 + npc y(ref) * 65536 + npc direction(ref) * 16777216 write global(p, v) p += 1 if(is monster(ref)) then( v := get monster hp(ref) )else( v := 0 ) write global(p, v) p += 1 how many += 1 ) ) write global(how many p, how many) # Flush the remainder of the globals while(p < 16383) do( write global(p, 0) p += 1 ) # Write the globals for this map to a save slot export globals(2 + current map, savetmp) # Flush all temporary globals variable(i) for(i, savetmp, 16383) do( write global(i, 0) ) end plotscript, load saved progress, begin if(death count >= 1) then( show text box(131) wait for text box if(check tag(tag:save scum choice) == OFF) then( # Decided not to save scum after all exit script ) ) load from slot(1) end plotscript, on load game, begin init for new game and load game # Even if you somehow save after killing baconthulhu, reset him baconthulhu dead := false set hero position(0, hero x(0), hero y(0)) init map money sl := 0 update money display if(death count >= 1) then( save scum ) end script, try to load map, begin # Returns true if the load worked, or false if the map needs to be generated write global(1000, 0) import globals(2 + current map, 1000, 16383) if(read global(1000) == 0) then(exit returning(false)) if(read global(1000) <> 1) then( show text box(130) wait for text box erase saves reset to title screen ) # Load map metadata if(read global(1001) <> map width) then( $msg="Map width mismatch, hope it doesn't matter!" trace(msg) ) if(read global(1002) <> map height) then( $msg="Map height mismatch, hope it doesn't matter!" trace(msg) ) set up stairs x(current map, read global(1003)) set up stairs y(current map, read global(1004)) set down stairs x(current map, read global(1005)) set down stairs y(current map, read global(1006)) set map creation(current map, read global(1007)) # Load the map tile state variable(p, x, y, v, tile, passage count) p := tilestart for(y, 0, read global(1002) -- 1) do( for(x, 0, read global(1001) -- 1) do( v := read global(p) tile := v ,AND, 255 write map block(x, y, tile, layer:base) if(is a wall(tile)) then( safe write pass block(x, y, northwall,or,eastwall,or,southwall,or,westwall) ) write map block(x, y, (v ,AND, 65535) / 256, layer:item) write map block(x, y, (v ,AND, 16777215) / 65536 , layer:fog) write map block(x, y, v / 16777216 , layer:chalk) if(is a passage(tile)) then( passage count += 1 ) p += 1 ) ) # Sanity test if(passage count == 0) then( exit returning(false) ) # Load the NPC state variable(i, how many, ref, id, d, hp, max hp) how many := read global(p) p += 1 for(i, 0, how many -- 1) do( v := read global(p) id := v ,AND, 255 x := (v ,AND, 65535) / 256 y := (v ,AND, 16777215) / 65536 d := v / 16777216 tile := read map block(x, y, layer:base) if(not(is a passage(tile))) then( $msg="SANITY: " append number(msg, i) $msg+" monster " append number(msg, id) $msg+" loaded in wall " append number(msg, x) $msg+"," append number(msg, y) if(find monster spawn pos) then( x := find x y := find y )else( $msg+" unfixed" ) trace(msg) ) ref := create npc(id, x, y, d) p += 1 hp := read global(p) p += 1 if(is monster(ref)) then( max hp := get monster max hp(ref) if(hp > max hp) then( $msg="SANITY: monster " append number(msg, id) $msg+" " append number(msg, ref) $msg+" loaded " append number(msg, hp) $msg+" hp" trace(msg) hp := max hp ) set monster hp(ref, hp) ) ) # Done! exit returning(true) end script, erase saves, begin variable(slot) for(slot, 1, 32) do( delete save(slot) ) end plotscript, save scum, begin set tag(tag:save scummer, ON) scroll of instakill heal hero(999) invigorate hero(999) $msg = "" append number(msg, death count) $msg + " deaths." update console $msg = "You have been branded a save scummer." update console create teleport cloud(hero x, hero y) resume all end script, init map, begin resume player set each step script(@each step) set on keypress script(@on keypress) expire all effects each tick reset spawn timer set timer(temp timer, 0, 1, @first step) if(try to load map) then( $msg="Continuing your quest..." )else( generate map ) if(current map == last map) then( if(baconthulhu dead == false) then( spawn baconthulhu ) ) sanity check talkers update meters end plotscript, first step, begin each step(hero x, hero y, hero direction, true) end plotscript, each step, x, y, d, no stairs=false, begin step count += 1 fix more surrounding walls(x, y) clear fog of war(x, y) pick up treasure(x, y) metabolize jiffy potion diffuse repel spell if(no stairs == false) then(climb stairs) # Set the timer for an idle save after 5 seconds of not walking set timer(timer:idle save, 4, 18, @do idle save) force save steps += 1 if(force save steps >= force save step frequency) then( # If we have been walking a long time without a save, shorten the idle timeout to 1 sec set timer(timer:idle save, 0, 18, @do idle save) ) end script, do idle save, begin force save steps := 0 save progress end script, metabolize jiffy potion, begin if(jiffy level > 0) then( jiffy level -= 1 update jiffy meter if(jiffy level == 0) then( $msg="The jiffy potion wore off." update console ) ) adjust speed for jiffy end script, diffuse repel spell, begin if(repel level > 0) then( repel level -= 1 create burst particle(hero x(0), hero y(0), 241, 154, 0, -14, 0, 3) update repel meter if(repel level == 0) then( $msg="Beware! The repel effect has expired!" update console ) update repel meter ) end script, adjust speed for jiffy, begin if(jiffy level > 0) then( set hero speed(0, 10) )else( set hero speed(0, 4) ) end plotscript, on keypress, begin if(keyval(key:tilde)>0) then( # cheat keys if(keyval(key:M)>1) then(reveal map) if(keyval(key:G)>1) then(get money(100), update money display) if(keyval(key:D)>1) then(use shop(4)) if(keyval(key:V)>1) then(show ending) ) if(keyval(key:period)>0 && keyval(key:comma)>0) then(try cheat shop) while(true) do( # hack loop so we can use "break" if(keyval(key:up)>1) then(hero motion(up), break) if(keyval(key:right)>1) then(hero motion(right), break) if(keyval(key:down)>1) then(hero motion(down), break) if(keyval(key:left)>1) then(hero motion(left), break) if(current text box >= 0) then( if(keyval(key:E)>1) then(advance text box) if(keyval(key:I)>1) then(advance text box) if(keyval(key:Z)>1) then(advance text box) if(keyval(key:X)>1) then(advance text box) if(keyval(key:C)>1) then(advance text box) )else( if(tool key pressed) then(talk or use tool) if(keyval(key:E)>1) then(show equip) if(keyval(key:I)>1) then(show inventory) if(keyval(key:X)>1) then(drink potion) if(keyval(key:C)>1) then(read scroll) ) break ) end script, talk or use tool, begin variable(x, y, i, ref) for(i, 0, 3) do( x := hero x(0) + compass x(i) y := hero y(0) + compass y(i) ref := npc at spot(x, y) if(ref) then( if(is talker(ref)) then( talker action for this map(ref) exit script ) ) ) use tool end script, tool key pressed, begin exit returning(keyval(key:Z)>1 || keyval(key:space) > 1 || keyval(key:enter) > 1) end script, try cheat shop, begin # To enter the cheat shop, unequip your potion and scroll, # then stand next to a diamond and hold: comma+period+x+c # Or on OUYA L2+R2+U+Y if(check equipment(0, slot:scroll) > -1) then(exit script) if(check equipment(0, slot:potion) > -1) then(exit script) if(keyval(key:X) == 0) then(exit script) if(keyval(key:C) == 0) then(exit script) variable(i, x, y, tile) for(i, 0, 3) do( x := hero x(0) + compass x(i) y := hero y(0) + compass y(i) tile := read map block(x, y, layer:item) if(tile == 4) then( # Standing next to diamond use shop(4) exit script ) ) end script, each tick, begin update hero update effects update monsters if(keyval(key:1) > 1) then(show help) set timer(main loop timer, 0, 1, @each tick) end script, climb stairs, begin variable(tile) tile := safe read map block(hero x, hero y) if(is a stairs(tile) && not(stairs ignore)) then( if(generating) then( $msg = "Can't climb stairs while map grows!" update console exit script ) suspend player $msg = "Saving progress..." update console save progress variable(dest) if(tile == stairs up) then( play sound(sfx:stairs up) dest := current map -- 1 teleport to map(dest, get down stairs x(dest), get down stairs y(dest)) ) if(tile == stairs down) then( play sound(sfx:stairs down) dest := current map + 1 teleport to map(dest, get up stairs x(dest), get up stairs y(dest)) ) stairs ignore := true init map exit script ) stairs ignore := false end #----------------------------------------------------------------------- plotscript, show inventory, begin items menu update meters end plotscript, show equip, begin equip menu(0) update meters end plotscript, show help, begin suspend all hide all strings if(running on console) then( variable(sl) if(running on ouya) then( sl := load slice collection(2) )else( sl := load slice collection(3) ) wait(1) while(true) do( if( keyval(key:enter) > 1 || keyval(key:space) > 1 || keyval(key:ctrl) > 1 || keyval(key:esc) > 1 || keyval(key:alt) > 1 || keyval(key:1) > 1 ) then(break) wait(1) ) free slice(sl) )else if(running on mobile) then( show text box(201) wait for text box )else( show text box(1) wait for text box ) show all strings resume all end plotscript, scroll of burning, begin variable(ref) for(ref, -300, -1) do( if(is attackable(ref)) then( if(distance to monster in pixels under(ref, 190)) then( create weapon effect(magic:fire, npc x(ref), npc y(ref), 18) damage monster(ref, random(3, 7)) ) ) ) play sound(sfx:burning) end plotscript, scroll of instakill, begin variable(ref, id) for(ref, -300, -1) do( if(is attackable(ref)) then( id := get npc id(ref) if(id == bacon body) then( # Baconthulhu's bacon bodies are immune to instakill continue ) if(distance to monster in pixels under(ref, 190)) then( damage monster(ref, 999) ) ) ) end plotscript, scroll of bat, begin variable(ref) ref := npc reference(robed cultist) if(not(ref)) then( $msg = "There are no cultists on this floor." update console ) create weapon effect(magic:bat, hero x, hero y, 999) play sound(sfx:bat) if(check tag(tag:date with Misa)) then( if(not(check tag(tag:misa saw bat))) then( suspend all show text box(152) wait for text box resume all set tag(tag:misa saw bat, ON) ) ) end plotscript, scroll of monarch, begin if(current map == last map) then( )else( $msg = "This is the final floor of the crypt." update console ) create weapon effect(magic:monarch, hero x, hero y, 999) play sound(sfx:monarch) if(check tag(tag:date with Misa)) then( if(not(check tag(tag:misa saw monarch))) then( suspend all show text box(153) wait for text box resume all set tag(tag:misa saw monarch, ON) ) ) end plotscript, scroll of vegify, begin variable(ref, x, y) for(ref, -300, -1) do( if(is attackable(ref)) then( if(distance to monster in pixels under(ref, 190)) then( x := npc x(ref) y := npc y(ref) # insta-kill monsters in range damage monster(ref, 999) # create a soybean, overwriting any other item dropped by this monster create item(x, y, item:soybean) ) ) ) play sound(sfx:vegify) end plotscript, scroll of repel, begin repel level := full repel charge $msg="The monsters flee in confusion!" update console update repel meter play sound(sfx:repel) end plotscript, scroll of telepo, begin variable(x, y, stand) create teleport cloud(hero x(0), hero y(0)) stand := read map block(hero x(0), hero y(0), layer:chalk) if(is teleportable chalk mark(stand) && find teleportable chalk mark(stand)) then( $msg="You step carefully through hyperspace." update console )else if(is directional chalk mark(stand)) then( find directional teleport spot(stand -- chalk up) $msg="You advance slightly through hyperspace." update console )else if(is backtrack chalk mark(stand) && find backtrack teleport spot) then( $msg="You backtrack through hyperspace." update console )else( find random teleport spot $msg="You stumble through hyperspace!" update console ) set hero position(0, find x, find y) create teleport cloud(find x, find y) play sound(sfx:teleport) first step end script, is teleportable chalk mark, tile, begin if(tile == chalk x mark || tile == chalk circle || tile == chalk heart) then(exit returning(true)) exit returning(false) end script, is directional chalk mark, tile, begin if(tile >= chalk up && tile <= chalk left) then(exit returning(true)) exit returning(false) end script, is backtrack chalk mark, tile, begin if(tile == chalk spiral) then(exit returning(true)) exit returning(false) end script, find teleportable chalk mark, mark, begin # returns results in findx and findy # Return true if a valid destination was found variable(sl, x, y, tile, hero at, spot) sl := create container(0, 0) hero at := -1 # Build a list of all matching chalk marks for(y, 1, map height -- 2) do( for(x, 1, map width -- 2) do( tile := read map block(x, y, layer:chalk) if(tile == mark) then( if(x == hero x(0) && y == hero y(0)) then(hero at := child count(sl)) spot := create container(0, 0) set slice x(spot, x) set slice y(spot, y) set parent(spot, sl) ) ) ) if(child count(sl) <= 1) then( # Need 2 or more matching marks to teleport between them exit returning(false) ) variable(dest, dest sl) dest := hero at + 1 if(dest >= child count(sl)) then(dest := 0) dest sl := slice child(sl, dest) find x := slice x(dest sl) find y := slice y(dest sl) free slice(sl) exit returning(true) end script, find backtrack teleport spot, begin # returns results in findx and findy # Return true if a valid destination was found variable(sx, sy, i, x, y, tile) # Find the up stairs sx := get up stairs x(current map) sy := get up stairs y(current map) for(i, 0, 3) do( x := sx + compass x(i) y := sy + compass y(i) tile := read map block(x, y, layer:base) if(is a passage(tile)) then( find x := x find y := y exit returning(true) ) ) exit returning(false) end script, find random teleport spot, begin # Return results in findx and findy. # Favor unexplored passages variable(i, x, y, tile, fog) for(i, 0, 60) do( x := random(1, map width -- 2) y := random(1, map height -- 2) if(x == hero x(0) && y == hero y(0)) then(continue) tile := read map block(x, y, layer:base) if(is a passage(tile)) then( if(i <= 30) then( if(not(fog at spot(x, y))) then(continue) ) find x := x find y := y exit script ) ) # if all else fails, the hero's current position is safe enough find x := hero x(0) find y := hero y(0) end script, find directional teleport spot, dir, begin # returns result in findx and findy variable(x, y, found wall, tile) x := hero x(0) y := hero y(0) while(x >= 1 && x <= map width -- 2 && y >= 1 && y <= map height -- 2) do( x += compass x(dir) y += compass y(dir) tile := read map block(x, y, layer:base) if(found wall) then( if(is a passage(tile)) then( find x := x find y := y exit script ) )else( if(is a wall(tile)) then( found wall := true ) ) ) # Reached the edge of the map without finding a passage find x := hero x(0) find y := hero y(0) end #----------------------------------------------------------------------- script, use tool, begin variable(item) item := check equipment(0, slot:tool) if(item == -1) then( $msg = "No tool equipped." update console exit script ) switch(item) do( case(item:debug) do(use debug goggles) case(item:chalk) do(use chalk) case(item:maul) do(use maul) case(item:lazy) do(use lazy maul) ) end script, use maul, begin if(not(hero can attack)) then( $msg="Too exhausted to swing the maul" update console exit script ) variable(x, y, tile) x := hero x(0) + compass x(hero direction(0)) y := hero y(0) + compass y(hero direction(0)) tile := safe read map block(x, y, layer:base) if(not(is a wall(tile))) then( miss effect(x, y) exit script ) create walkabout effect(effect:punch, x, y, 0, 4) tile := safe read map block(x, y, layer:chalk) if(tile >= first crack tile && tile <= last crack tile) then( if(tile == last crack tile) then( # Broke the wall write map block(x, y, smashed wall floor, layer:base) write map block(x, y, void, layer:chalk) write pass block(x, y, none) $msg="The wall shudders and crumbles" update console play sound(sfx:wallcrumble) )else( # weaken the wall write map block(x, y, tile + 1, layer:chalk) play sound(sfx:impact) ) )else( play sound(sfx:solid wall) ) modify hero stamina(-1) if(percent(50)) then( # take an extra point of stamina 1/2 of the time modify hero stamina(-1) ) end script, use lazy maul, begin if(not(hero can attack)) then( $msg="Too exhausted to swing the maul" update console exit script ) variable(x, y, tile) x := hero x(0) + compass x(hero direction(0)) y := hero y(0) + compass y(hero direction(0)) tile := safe read map block(x, y, layer:base) if(is a wall(tile)) then( if(count compass void(x,y) == 0) then( create walkabout effect(effect:punch, x, y, 0, 4) tile := safe read map block(x, y, layer:chalk) if(tile >= first crack tile && tile <= last crack tile) then( # Broke the wall write map block(x, y, smashed wall floor, layer:base) write map block(x, y, void, layer:chalk) write pass block(x, y, none) $msg="There goes another perfectly good wall." update console play sound(sfx:wallcrumble) modify hero stamina(-1) )else( # Crack this solid wall crack wall(x, y) play sound(sfx:impact) create walkabout effect(effect:punch, x, y, 0, 4) modify hero stamina(-1) exit script ) )else( # Not safe to crack create walkabout effect(effect:punch, x, y, 0, 4) play sound(sfx:solid wall) exit script ) )else( miss effect(x, y) exit script ) end script, use chalk, begin variable(choice) choice := open menu(10) update chalk meter end plotscript, chalk action, num, begin variable(ftile, ctile) ftile := read map block(hero x(0), hero y(0), layer:base) if(is a passage(ftile)) then( if(num == -1) then( # Erase existing mark ctile := 0 )else( # Create/change mark ctile := first chalk floor + num if(ctile < first chalk floor || ctile > last chalk floor) then(exit script) wear down chalk ) write map block(hero x(0), hero y(0), ctile, layer:chalk) if(ctile == chalk heart) then( if(not(check tag(tag:drew heart for Misa))) then( show text box(134) wait for text box ) ) ) end script, wear down chalk, begin chalk decay += 1 if(chalk decay >= chalk use count) then( # chalk has broken chalk decay := 0 if(inventory(item:chalk) == 0) then( unequip(0, slot:tool) $msg="Your last chalk broke." update console )else( $msg="Chalk broke. (" append number(msg, inventory(item:chalk)) $msg+" left)" update console ) delete item(item:chalk) play sound(sfx:chalk snap) )else( play sound(sfx:chalk write) ) update chalk meter end script, use debug goggles, begin variable(x, y) x := hero x(0) + compass x(hero direction(0)) y := hero y(0) + compass y(hero direction(0)) $msg="Tile at x=" append number(msg, x) $msg+" y=" append number(msg, y) $msg+" is ID#" append number(msg, read map block(x,y,layer:base)) $msg+" Wall=" append number(msg, read pass block(x,y)) update console # NPC location $msg="" variable(ref) ref := npc reference(97) if(ref) then( $msg+"NPC@", append number(msg, npc x(ref)), $msg+",", append number(msg, npc y(ref)) ) ref := npc reference(98) if(ref) then( $msg+"NPC@", append number(msg, npc x(ref)), $msg+",", append number(msg, npc y(ref)) ) if(string length(msg)) then($msg+" ") ref := npc reference(99) if(ref) then( $msg+"SHOP@", append number(msg, npc x(ref)), $msg+",", append number(msg, npc y(ref)) ) # Stairs locations $msg+" ", append ascii(msg, 186), append number(msg, get up stairs x(current map)), $msg+",", append number(msg, get up stairs y(current map)) $msg+" ", append ascii(msg, 188), append number(msg, get down stairs x(current map)), $msg+",", append number(msg, get down stairs y(current map)) update console end script, drink potion, begin variable(item) item := check equipment(0, slot:potion) if(item == -1) then( $msg = "No potion equipped." update console exit script ) switch(item) do( case(item:tonic) do(potion particle effect(85, 90)) case(item:brew) do(potion particle effect(217, 212)) case(item:jiffy) do(potion particle effect(248, 245)) ) variable(atk) atk := lookup item attack(item) if(atk) then( if(atk == atk:Soma) then( drink soma potion )else( outside battle cure(atk--1, 0, 0) ) ) play sound(sfx:tonic) if(inventory(item)) then( $msg = "Drank a " get item name(tmp str, item) msg $+ tmp str $msg + ". (" append number(msg, inventory(item)) $msg + " left)" )else( $msg = "Drank your last " get item name(tmp str, item) msg $+ tmp str $msg + "." unequip(0, slot:potion) ) update console delete item(item) if(item == item:jiffy) then( wait for hero(0) drink jiffy potion adjust speed for jiffy ) update meters end plotscript, drink soma potion, begin set hero stat(0, stat:health, get hero stat(0, stat:health, maximum stat) + 1, maximum stat) set hero stat(0, stat:health, get hero stat(0, stat:health) + 1) $msg="The potion makes you feel healthier" update console update meters play sound(sfx:tonic) potion particle effect(240, 109) end plotscript, drink jiffy potion, begin jiffy level := full jiffy charge $msg="You feel fast... very fast!" update console update jiffy meter end script, read scroll, begin variable(item) item := check equipment(0, slot:scroll) if(item == -1) then( $msg = "No scroll equipped." update console exit script ) read scroll action(item) if(inventory(item)) then( $msg = "The " get item name(tmp str, item) msg $+ tmp str $msg + " scroll crumbles. (" append number(msg, inventory(item)) $msg + " left)" )else( $msg = "Your last " get item name(tmp str, item) msg $+ tmp str $msg + " crumbles." unequip(0, slot:scroll) ) delete item(item) update console end script, read scroll action, item, begin switch(item) do( case(item:burning) do(scroll of burning) case(item:bat) do(scroll of bat) case(item:monarch) do(scroll of monarch) case(item:vegify) do(scroll of vegify) case(item:repel) do(scroll of repel) case(item:telepo) do(scroll of telepo) else( get item name(msg, item) $msg + " cannot be read as a scroll" update console ) ) end script, lookup item attack, item, begin # This is a hack to compensate for the fact that item data cannot be read switch(item) do( case(item:Tonic) do(exit returning(atk:Tonic)) case(item:Brew) do(exit returning(atk:Brew)) case(item:Soma) do(exit returning(atk:Soma)) ) exit returning(false) end #----------------------------------------------------------------------- script, setup map specials, begin switch(current map) do( case(0) do( place special item(item:sword) place special item(item:tonic, 2) place special item(item:brew) place special item(item:chalk, 2) place special item(item:burning) place cultist ) case(1) do( place special item(item:axe) place special item(item:maul) place special item(item:tonic) place special item(item:brew) place special item(item:chalk, 2) place special item(item:repel) place special item(item:telepo) place cultist ) case(2) do( place special item(item:tonic) place special item(item:brew) place special item(item:chalk) place special item(item:jiffy) place special item(item:repel) place cultist place bacontologist ) case(3) do( place special item(item:chalk) place special item(item:jiffy) place special item(item:repel) place special item(item:burning) place special item(item:brew) place cultist ) case(4) do( place special item(item:chalk) place special item(item:jiffy, 2) place special item(item:burning) place special item(item:brew, 3) place special item(item:telepo) place special item(item:blade) place special item(item:pommel) place special item(item:tape) place cultist place misa ) ) end script, sanity check talkers, begin # If talkers are missing, create them switch(current map) do( case(0) do( ensure cultist ) case(1) do( ensure cultist ) case(2) do( ensure cultist ensure bacontologist ) case(3) do( ensure cultist ) case(4) do( ensure cultist ensure misa ) case(5) do( $msg="You heart sizzles with terror" update console ) ) end script, ensure cultist, begin if(npc copy count(robed cultist) == 0) then( $msg="You feel a strange chill." update console place cultist ) end script, ensure bacontologist, begin if(npc copy count(bacontologist) == 0) then( $msg="You feel a reasonable chill." update console place bacontologist ) end script, ensure misa, begin if(check tag(tag:date with Misa)) then(exit script) if(npc copy count(misa the hamster) == 0) then( $msg="You feel a distant warmth." update console place misa ) end script, talker action for this map, ref, begin face nearby talker variable(id) id := get npc id(ref) switch(id) do( case(robed cultist) do( switch(current map) do( case(0) do(talk menu(menu:shop 1)) case(1) do(talk menu(menu:shop 2)) case(2) do(talk menu(menu:shop 3)) case(3) do(talk menu(menu:shop 4)) case(4) do(talk menu(menu:shop 5)) ) ) case(bacontologist) do( talk menu(menu:bacontologist) ) case(misa the hamster) do( talk menu(menu:misa) ) ) end plotscript, bacontologist long explanation, begin suspend all show text box(69) wait for text box show text box after fade(71) show text box after fade(72) show text box after fade(73) show text box after fade(77) show text box after fade(74) resume all end plotscript, high priest wavy sword repair, begin suspend all show text box(163) wait for text box if(check tag(tag:own broken blade) || check tag(tag:own broken pommel)) then( show text box(165) wait for text box if(check tag(tag:own broken blade) && check tag(tag:own broken pommel)) then( # Have both parts show text box(167) wait for text box variable(i) for(i, 0, 5) do( wait(12) play sound(sfx:fixing) ) delete item(item:blade) delete item(item:pommel) delete item(item:tape) show get item(item:wavy) show text box(168) wait for text box )else( # Need both parts show text box(166) wait for text box ) ) resume all end script, show text box after fade, box, begin fade screen out show text box(box) fade screen in wait for text box end script, face nearby talker, begin variable(i, x, y, ref) for(i, 0, 3) do( x := hero x(0) + compass x(i) y := hero y(0) + compass y(i) ref := npc at spot(x, y) if(is talker(ref)) then( set hero direction(0, i) ) ) end script, talk menu, menu id, begin suspend all advance text box open menu(menu id) wait for text box update money display resume all save progress end script, find place for special, begin variable(i) # try 12 times, avoid locations too close to your curent location for (i, 0, 11) do( find tunnel end if(close to hero(find x, find y, 4) == false) then( break ) ) end script, place special item, item, count=1, begin variable(j, i, tile) # try 5 times, avoid overwriting existing special items for(j, 1, count) do( for(i, 0, 5) do( # Several attempts to find a good location (to discourage overwriting other items) find place for special tile := safe read map block(find x, find y, layer:item) if(is item icon(tile) == false) then(break) ) create item(find x, find y, item) ) end script, close to hero, x, y, dist, begin variable(diff x, diff y) diff x := hero x -- x diff y := hero y -- y exit returning(abs(diff x) <= dist && abs(diff y) <= dist) end script, place cultist, begin find place for special start spawn cultist(find x, find y) end script, place misa, begin find place for special start spawn misa(find x, find y) end script, place bacontologist, begin find place for special start spawn bacontologist(find x, find y) end #----------------------------------------------------------------------- script, say, box, begin suspend all show text box(box) wait for text box resume all end script, heart above misa, begin variable(slot) slot := rank in caterpillar(hero:misa the hamster) create weapon effect(magic:love, hero x(slot), hero y(slot) -- 1, seconds * 2) end script, misa reaction to monster kill, begin if(baconthulhu dead) then(exit script) if(check tag(tag:date with misa)) then( monster kills on date += 1 switch(monster kills on date) do( case(1) do(say(123)) # comment on first monster kill case(4) do(say(124)) case(12) do(say(125)) case(20) do(say(127)) case(100) do(heart above misa, say(129)) ) ) end #----------------------------------------------------------------------- script, hide all strings, begin variable(i) for(i, msg+1, msg+4) do( hide string(i) ) if(money sl) then( set slice visible(money sl, false) ) end script, show all strings, begin variable(i) for(i, 0, 3) do( show string at(msg+1+i, 0, 190 -- i * 10) ) if(money sl) then( set slice visible(money sl, true) ) end #----------------------------------------------------------------------- script, create meters, begin meters := create container(320, 200) variable(sl) variable(col) col := 5 * 16 health meter := create meter(1, 1, col + 7, col + 12) col := 13 * 16 stamina meter := create meter(1, 9, col + 7, col + 12) col := 7 * 16 monster meter := create meter(1, 1, col + 7, col + 12) anchor align(monster meter, edge:right) anchor align(first child(monster meter), edge:right) set slice visible(monster meter, false) col := 12 * 16 chalk meter := create meter(71, 1, col + 7, col + 12) set slice visible(chalk meter, false) col := 15 * 16 jiffy meter := create meter(71, 9, col + 7, col + 12) set slice visible(jiffy meter, false) col := 10 * 16 repel meter := create meter(141, 1, col + 7, col + 12) set slice visible(repel meter, false) update meters end script, create meter, x, y, bg col, border col, begin variable(meter) meter := create rect(60, 6, -1) set slice x(meter, x) set slice y(meter, y) set rect fg col(meter, bg col) variable(sl) sl := create rect(0, 6, -1) set parent(sl, meter) set rect bg col(sl, bg col) set rect fg col(sl, border col) exit returning(meter) end script, update meter, meter, cur, max, begin if(max == 0) then(exit script) variable(sl, w) w := slice width(meter) sl := first child(meter) set slice width(sl, (w * 100) / max * cur / 100) end script, update meters, begin update health meter update stamina meter update monster meter update chalk meter update jiffy meter update repel meter end script, update health meter, begin variable(cur, max) cur := get hero stat(0, stat:health, current stat) max := get hero stat(0, stat:health, maximum stat) update meter(health meter, cur, max) end script, update stamina meter, begin variable(cur, max) cur := get hero stat(0, stat:stamina, current stat) max := get hero stat(0, stat:stamina, maximum stat) update meter(stamina meter, cur, max) end script, update monster meter, begin variable(cur, max) cur := current monster hp max := current monster max update meter(monster meter, cur, max) end script, show monster meter, begin set sprite visible(monster meter, true) set timer(monster meter timer, 2, seconds, @hide monster meter) end script, hide monster meter, begin set sprite visible(monster meter, false) end script, hero victory, begin suspend player set hero picture(0, hero celebrating, outside battle) give experience(0, 1) if(hero levelled > 0) then( do level up ) set timer(victory timer, 0, 1, @start hero victory) end script, do level up, begin $msg = "Your experience level has increased!" update console $msg = "You have reached level ", append number(msg, get hero level(0)) update console open menu(12) wait(1) save progress end script, update chalk meter, begin variable(cur, max) cur := chalk use count -- chalk decay max := chalk use count update meter(chalk meter, cur, max) set slice visible(chalk meter, using chalk) end plotscript, level up max hp, begin $msg="You feel healthier" update console max stat bonus(stat:health) end plotscript, level up max stamina, begin $msg="You feel more energetic" update console max stat bonus(stat:stamina) end plotscript, level up max hit rate, begin $msg="You feel more precise" update console max stat bonus(stat:hit rate, 2) end script, max stat bonus, stat, amount=1, begin set hero stat(0, stat, get hero stat(0, stat, maximum stat) + amount, maximum stat) set hero stat(0, stat, get hero stat(0, stat) + amount) update meters play sound(sfx:level up) potion particle effect(240, 109) end script, using chalk, begin variable(item) item := check equipment(0, slot:tool) exit returning(item == item:chalk) end script, update jiffy meter, begin variable(cur, max) cur := jiffy level max := full jiffy charge update meter(jiffy meter, cur, max) set slice visible(jiffy meter, jiffy level > 0) end script, update repel meter, begin variable(cur, max) cur := repel level max := full repel charge update meter(repel meter, cur, max) set slice visible(repel meter, repel level > 0) end script, start hero victory, begin set hero picture(0, hero celebrating, outside battle) set timer(victory timer, 0, 7, @mid hero victory) end script, mid hero victory, begin resume player set timer(victory timer, 0, 7, @finish hero victory) end script, finish hero victory, begin set hero picture(0, hero walking, outside battle) end #----------------------------------------------------------------------- script, create map metadata, begin metadata := create container(0,0) set sprite visible(metadata, false) variable(i, sl) for(i, 0, last map) do( sl := create container(0,0) set parent(sl, metadata) ) end script, get map metadata, map, begin variable(i, sl) sl := first child(metadata) for(i, 1, map) do( sl := next sibling(sl) ) exit returning(sl) end script, get up stairs x, map, begin exit returning(read global(stair pos var + map * 10 + 0)) end script, get up stairs y, map, begin exit returning(read global(stair pos var + map * 10 + 1)) end script, get down stairs x, map, begin exit returning(read global(stair pos var + map * 10 + 2)) end script, get down stairs y, map, begin exit returning(read global(stair pos var + map * 10 + 3)) end script, set up stairs x, map, n, begin write global(stair pos var + map * 10 + 0, n) end script, set up stairs y, map, n, begin write global(stair pos var + map * 10 + 1, n) end script, set down stairs x, map, n, begin write global(stair pos var + map * 10 + 2, n) end script, set down stairs y, map, n, begin write global(stair pos var + map * 10 + 3, n) end script, get map creation, map, begin variable(sl) sl := get map metadata(map) exit returning(get slice extra(sl, extra 0)) end script, set map creation, map, n, begin variable(sl) sl := get map metadata(map) set slice extra(sl, extra 0, n) end #----------------------------------------------------------------------- script, hero dies, begin if(baconthulhu dead) then(exit script) $msg = "You have been defeated!" update console suspend all set on keypress script(none) show text box(2) death count += 1 save progress play sound(sfx:death laugh) wait(1) tweak palette(30,-30,-30) fade screen in wait for text box wait(3) show death screen resume all set on keypress script(@on keypress) end script, update hero, begin if(hero atk frames > 0) then( hero atk frames -= 1 if(hero atk frames == 0) then( set hero picture(0, hero walking) ) ) end script, hero motion, d, begin if(hero is aligned) then( if(hero atk frames == 0) then( hero motion action(d) ) ) end script, hero motion action, d, begin variable(ref) ref := get monster ahead of hero(d) if(is attackable(ref)) then( hero attack monster(ref) ) if(is talker(ref)) then( if(current textbox == -1) then( talker action for this map(ref) ) ) end script, is attackable, ref, begin exit returning(is monster(ref)) end script, is monster, ref, begin variable(id) if(ref >= 0) then(exit returning(false)) id := get npc id(ref) if(id == -1) then(exit returning(false)) # empty slot if(is talker(id)) then(exit returning(false)) exit returning(true) end script, is talker, ref, begin # this should work on both refs and ids variable(id) id := get npc id(ref) exit returning(id >= 80) end script, is cultist, ref, begin variable(id) id := get npc id(ref) if(id == robed cultist) then(exit returning(true)) exit returning(false) end script, hero attack monster, ref, begin if(hero can attack == false) then(exit script) variable(x, y) x := npc x(ref) y := npc y(ref) if(hero attack attempt) then( hero attack effect(x, y, hero facing(ref)) damage monster(ref, hero atk power) )else( miss effect(x, y) ) set hero picture(0, hero attacking) hero atk frames := 5 apply encumbrance current monster hp := get monster hp(ref) current monster max := get monster max hp(ref) show monster meter update monster meter end script, hero facing, ref, begin variable(i, x, y) for(i, 0, 3) do( x := hero x(0) + compass x(i) y := hero y(0) + compass y(i) if(npc x(ref) == x && npc y(ref) == y) then( exit returning(i) ) ) exit returning(hero direction(0)) end script, percent, n, begin exit returning(random(0, 99) < n) end script, hero attack attempt, begin exit returning(percent(get hero stat(0, stat:hit rate))) end script, hero can attack, begin variable(stamina, burden) stamina := get hero stat(0, stat:stamina, current stat) burden := get hero stat(0, stat:burden) if (stamina -- burden < 0) then(exit returning(false)) exit returning(true) end script, hero is aligned, begin exit returning((hero pixel x, mod, 20)==0 && (hero pixel y, mod, 20)==0) end script, get monster ahead of hero, d, begin variable(x, y) x := hero x + compass x(d) y := hero y + compass y(d) variable(i, ref) for(i, 0, NPC at spot(x, y, get count)) do( ref := npc at spot(x, y, i) if(npc is walking(ref) == false) then(exit returning(ref)) ) exit returning(false) end script, hero atk power, begin exit returning(get hero stat(0, stat:attack)) end script, hero attack effect, x, y, d, begin variable(effect) switch(check equipment(0, slot:melee)) do( case(item:punch) do(effect := effect:punch, play sound(sfx:punch)) case(item:sword) do(effect := effect:sword, play sound(sfx:slash)) case(item:axe) do(effect := effect:axe, play sound(sfx:slash)) case(item:tofu) do(effect := effect:tofu, play sound(sfx:slash)) case(item:wavy) do(effect := effect:wavy, play sound(sfx:slash)) ) create walkabout effect(effect, x, y, d, 4) end script, miss effect, x, y, begin create walkabout effect(effect:miss, x, y, 0, 2) play sound(sfx:miss) end script, apply encumbrance, begin variable(n) n := get hero stat(0, stat:burden) modify hero stamina(n * -1) end script, modify hero stamina, amount, begin variable(n, max) n := get hero stat(0, stat:stamina, current stat) max := get hero stat(0, stat:stamina, maximum stat) n += amount if(n < 0) then(n := 0) if(n > max) then(n := max) set hero stat(0, stat:stamina, n, current stat) update stamina meter end script, stamina is full, begin exit returning(get hero stat(0, stat:stamina, current stat) == get hero stat(0, stat:stamina, maximum stat)) end script, hero regen, begin if(not(stamina is full)) then(regen state := regen:stamina) switch(regen state) do( case(regen:stamina) do( variable(stamina) modify hero stamina(1) if(stamina is full) then(regen state := regen:health skip) ) case(regen:health) do( heal hero(1) regen state := regen:health skip ) case(regen:health skip) do( regen state := regen:health ) ) variable(delay) delay := 26 -- get hero stat(0, stat:recovery) if(delay < 8) then(delay := 8) set timer(regen timer, 1, delay, @hero regen) end script, damage hero, amount, begin variable(hp) hp := get hero stat(0, stat:health, current stat) hp -= amount if(hp <= 0) then(hp := 0) set hero stat(0, stat:health, hp, current stat) update health meter if(hp == 0) then(hero dies) if(hp >= 1 && hp <= 2) then( play sound(sfx:low hp alert) ) end script, heal hero, amount, begin variable(hp, max) hp := get hero stat(0, stat:health, current stat) max := get hero stat(0, stat:health, maximum stat) hp += amount if(hp >= max) then(hp := max) set hero stat(0, stat:health, hp, current stat) update health meter end script, invigorate hero, amount, begin variable(stamina, max) stamina := get hero stat(0, stat:stamina, current stat) max := get hero stat(0, stat:stamina, maximum stat) stamina += amount if(stamina >= max) then(stamina := max) set hero stat(0, stat:stamina, stamina, current stat) update stamina meter end #----------------------------------------------------------------------- script, reveal map, begin fix all walls clear all fog $msg = "knowledge floods into your mind." update console end #----------------------------------------------------------------------- script, create effects layer, begin effects := lookup slice(sl:map layer 3) end script, update effects, begin variable(sl, type, age, ticks, deleteme) sl := first child(effects) while(sl) do( deleteme := false toggle effect frame(sl) update effect(sl) age := age effect(sl, 1) ticks := get effect ticks(sl) if(age >= ticks && ticks > -1) then(deleteme := sl) sl := next sibling(sl) if(deleteme) then(free slice(deleteme)) ) update counter += 1 if(update counter>9999999) then(update counter := 0) end script, update effect, sl, begin variable(ref) switch(get sprite type(sl)) do( case(spritetype:weapon) do( switch(get sprite set number(sl)) do( case(magic:bat) do( if(percent(70)) then( ref := NPC reference(robed cultist) effect flutters after npc(sl, ref, 4, @effect decay callback) ) ) case(magic:monarch) do( if(percent(70)) then( effect flutters after stairs down(sl, 4, @effect decay callback) ) ) ) ) case(spritetype:large enemy) do( switch(get sprite set number(sl)) do( case(1,2,3) do( update baconthulhu(sl) ) ) ) case(spritetype:walkabout) do( switch(get sprite set number(sl)) do( case(effect:bacon explosion) do( # bacon body explosion explode toward hero(sl) ) ) ) ) end script, explode toward hero, sl, begin variable(diff x, diff y) diff x := hero x -- slice x(sl) / 20 diff y := hero y -- slice y(sl) / 20 if(diff x < 0) then(diff x := random(-5, -2)) if(diff x > 0) then(diff x := random(2, 5)) if(diff y < 0) then(diff y := random(-5, -2)) if(diff y > 0) then(diff y := random(2, 5)) if(diff x == 0 && diff y == 0) then(diff x := random(-5, 5), diff y := random(-5, 5)) set slice x(sl, slice x(sl) + diff x) set slice y(sl, slice y(sl) + diff y) flutter slice(sl) end script, expire all effects, begin for each effect(@effect vanish callback) end script, for each effect, callback, begin variable(sl) sl := first child(effects) while(sl) do( run script by id(callback, sl) sl := next sibling(sl) ) end script, effect vanish callback, sl, begin # Make non-expiring effects expireable if(get effect ticks(sl) == -1) then(set effect ticks(sl, 0)) # force immediate expiration of this effect set effect age(sl, get effect ticks(sl) + 1) end script, effect decay callback, sl, begin set effect age(sl, get effect age(sl) -- 5) # greatly accelerate expiration of this effect end script, effect follows npc, sl, ref, speed=2, threshold=4, callback=none, begin variable(x, y) x := npc pixel x(ref) + 10 y := npc pixel y(ref) + 10 effect follows pos(sl, x, y, speed, threshold, callback) end script, effect follows pos, sl, x, y, speed=2, threshold=4, callback=none, begin variable(diff x, diff y) diff x := x -- slice x(sl) diff y := y -- slice y(sl) if(abs(diff x) <= threshold && abs(diff y) <= threshold) then( if(callback) then( run script by id(callback, sl) ) ) variable(xgo, ygo) xgo := speed if(speed > abs(diff x)) then(xgo := abs(diff x)) ygo := speed if(speed > abs(diff y)) then(ygo := abs(diff y)) if(diff x < 0) then(set slice x(sl, slice x(sl) -- speed)) if(diff x > 0) then(set slice x(sl, slice x(sl) + speed)) if(diff y < 0) then(set slice y(sl, slice y(sl) -- speed)) if(diff y > 0) then(set slice y(sl, slice y(sl) + speed)) end script, effect flutters after npc, sl, ref, threshold=4, callback=none, begin variable(x, y) if(ref) then( x := npc pixel x(ref) y := npc pixel y(ref) )else( x := random(0, map width) * 20 y := random(0, map height) * 20 ) effect flutters after pos(sl, x, y, threshold, callback) end script, effect flutters after stairs down, sl, threshold=4, callback=none, begin variable(x, y) if(current map < last map) then( x := get down stairs x(current map) * 20 y := get down stairs y(current map) * 20 )else( x := random(0, map width) * 20 y := random(0, map height) * 20 ) effect flutters after pos(sl, x, y, threshold, callback) end script, effect flutters after pos, sl, x, y, threshold=4, callback=none, begin effect follows pos(sl, x, y, 1, threshold, callback) flutter slice(sl) end script, flutter slice, sl, begin set slice x(sl, slice x(sl) + random(-1, 1)) set slice y(sl, slice y(sl) + random(-1, 1)) end script, create teleport cloud, x, y, begin create attack effect(teleport cloud, x, y, 6) end script, center effect, sl, begin set horiz anchor(sl, edge:center) set vert anchor(sl, edge:center) set slice x(sl, slice x(sl) + 10) set slice y(sl, slice y(sl) + 10) end script, create attack effect, sprite id, x, y, ticks, begin variable(sl) sl := load attack sprite(sprite id) create effect(sl, x, y, ticks) set sprite frame(sl, sprite frame count(sl) -- 1) center effect(sl) end script, create walkabout effect, sprite id, x, y, d, ticks, begin variable(sl) sl := load walkabout sprite(sprite id) create effect(sl, x, y, ticks) set sprite frame(sl, d * 2) end script, create weapon effect, sprite id, x, y, ticks, begin variable(sl) sl := load weapon sprite(sprite id) create effect(sl, x, y, ticks) center effect(sl) end script, create large enemy effect, sprite id, x, y, ticks, begin variable(sl) sl := load large enemy sprite(sprite id) create effect(sl, x, y, ticks) set vert anchor(sl, edge:bottom) set horiz anchor(sl, edge:center) end script, create effect, sl, x, y, ticks, begin # ticks is -1 for effects that don't expire set parent(sl, effects) set slice x(sl, x * 20) set slice y(sl, y * 20) set effect age(sl, 0) set effect ticks(sl, ticks) end script, age effect, sl, age, begin variable(n) n := get effect age(sl) n += age set effect age(sl, n) exit returning(n) end script, get effect age, sl, begin exit returning(get slice extra(sl, extra 0)) end script, set effect age, sl, n, begin set slice extra(sl, extra 0, n) end script, get effect ticks, sl, begin exit returning(get slice extra(sl, extra 1)) end script, set effect ref, sl, n, begin set slice extra(sl, extra 2, n) end script, get effect ref, sl, begin exit returning(get slice extra(sl, extra 2)) end script, set effect ticks, sl, n, begin set slice extra(sl, extra 1, n) end script, toggle effect frame, sl, begin if(update counter,mod,2 <> 0) then(exit script) if(slice is ellipse(sl)) then( # burst particles variable(age) age := get effect age(sl) if(age <= 11) then( # Only show up after a couple ticks set slice visible(sl, true) ) set slice width(sl, slice width(sl) -- 1) set slice height(sl, slice height(sl) -- 1) exit script ) variable(frame) frame := get sprite frame(sl) switch(get sprite type(sl)) do( case(spritetype:walkabout) do(frame := frame,xor,1) case(spritetype:weapon) do(frame := frame,xor,1) case(spritetype:attack) do( frame += 1 if(frame >= sprite frame count(sl)--1) then(frame := 0) ) ) set sprite frame(sl, frame) end #----------------------------------------------------------------------- script, spawn baconthulhu, begin variable(x, y) x := get down stairs x(current map) y := get down stairs y(current map) create large enemy effect(1, x, y, -1) end script, update baconthulhu, sl, begin variable(ref) if(baconthulhu dead) then( variable(x, y) x := slice x(sl) / 20 y := slice y(sl) / 20 create walkabout effect(effect:bacon explosion, x, y, random(0, 3), 99) animate baconthulhu(sl) exit script ) ref := get effect ref(sl) if(ref) then( if(get npc id(ref) == -1) then( # Baconthulhu had a bacon body, but lost it. ref := 0 baconthulhu kill attempt(sl) ) ) if(ref == 0) then( # Baconthulhu needs a bacon body, find one! ref := random monster ref of id(bacon body) ) if(ref == 0) then( # still no bacon body, flutter for awhile animate baconthulhu(sl) )else( if(distance from effect to monster in pixels under(sl, ref, 20)) then( # close to the bacon body, latch onto it set slice x(sl, npc pixel x(ref)+10) set slice y(sl, npc pixel y(ref)+10) )else( # far from the bacon body, seek it effect follows npc(sl, ref, 6, 10) ) animate baconthulhu(sl) ) set effect ref(sl, ref) end script, animate baconthulhu, sl, begin baconthulhu anim += 1 if(baconthulhu anim > 2) then(baconthulhu anim := -1) set sprite set number(sl, 1 + abs(baconthulhu anim)) end script, baconthulhu kill attempt, sl, begin if(current map <> 5) then(exit script) if(check equipment(0, slot:melee) == item:tofu) then( if(check tag(tag:date with misa)) then( baconthulhu defeated(sl) exit script ) $msg = "The Tofu Dagger wounds Baconthulhu, but" update console $msg = "not quite enough! What can weaken him?" update console set tag(tag:tofu failed, ON) exit script ) $msg = "Mundane weapons can't kill Baconthulhu!" update console if(check tag(tag:date with misa)) then( baconthulhu almost defeated ) end script, baconthulhu almost defeated, begin suspend all show text box(104) wait for text box resume all end script, baconthulhu defeated, sl, begin suspend all hide all strings wait(1) show text box(103) $msg = "You have defeated Baconthulhu!", update console wait for text box resume all show all strings baconthulhu dead := true set effect age(sl, 1) set effect ticks(sl, seconds * 10) set timer (end of game timer, 11, seconds, @show ending) end script, show ending, begin suspend all hide all strings fade screen out wait(seconds) if(check tag(tag:save scummer)) then( bad ending )else( good ending ) game over end script, bad ending, begin play song(2) show text box(105) wait(1) fade screen in wait for text box fade screen out scroll credits(1) play song(0) end script, good ending, begin show text box(107) wait(1) fade screen in teleport to map(8, 15, 14) if(find hero(hero:misa the hamster) == -1) then( # Normally it is impossible to win without Misa, but you might have used the ~V cheat code add hero(hero:misa the hamster) # Same with the Tofu dagger force equip(0, slot:melee, item:tofu) ) # Ending textboxes wait for text box # Ending walkabout scene set hero position(0, 15, 14) set hero position(1, 14, 14) set hero direction(0, left) set hero direction(1, right) wait(18) variable(i) for(i, 0, 3) do( set hero direction(0, i) wait(3) ) show text box(144) wait for text box wait(2) set hero direction(0, right) wait(2) set hero picture(0, hero attacking) hero attack effect(16, 14, right) wait(3) set hero picture(0, hero walking) expire all effects, update effects wait(3) set hero direction(0, down) set hero picture(0, hero attacking) hero attack effect(15, 15, down) wait(3) set hero picture(0, hero walking) expire all effects, update effects wait(3) set hero direction(0, left) wait(2) show text box(146) wait for text box wait(2) set hero direction(1, down) wait(4) set hero direction(1, left) wait(4) set hero direction(1, down) wait(2) set hero direction(1, right) show text box(147) wait for text box show text box(148) wait for text box heart above misa show text box(149) wait for text box expire all effects, update effects suspend caterpillar swap by position(0, 1) set hero position(0, 14, 14) set hero position(1, 15, 14) walk hero(0, down, 1) walk hero(0, right, 1) wait for hero(0) resume caterpillar walk hero to y(0, 25) wait for hero(0) pan camera(right, 10, 1) walk hero to x(0, 27) wait for hero(0) fade screen out wait(1) swap by position(0, 1) # Show the good credits scroll credits(0) # After the credits wait(18) teleport to map(9, 0, 0) play song(0) wait(1) fade screen in wait(12) show text box(150) wait for text box for(i, 0, 2) do( walk npc(89, left, 1) wait for npc(89) play sound(0) write map block(npc x(89), npc y(89), void, layer:item) ) walk npc(89, left, 1) wait for npc(89) play sound(1) write map block(npc x(89), npc y(89), void, layer:item) wait(2) set NPC direction(89, right) wait(4) show text box(151) wait for text box fade screen out wait(3) end script, scroll credits, collection, begin variable(col sl) col sl := load slice collection(collection) variable(text sl, bob sl, misa sl) text sl := lookup slice(sli:credits text, col sl) bob sl := lookup slice(sli:credits bob, col sl) misa sl := lookup slice(sli:credits misa, col sl) if(has donated) then( $str:end thanks="Thank you for donating!" )else( $str:end thanks="Please consider donating." ) v:hour := hours of play + days of play * 24 v:min := minutes of play v:sec := seconds of play get slice text(tmpstr, text sl) expand string(tmpstr) set slice text(text sl, tmpstr) variable(ticks) set slice screen y(text sl, 200) ticks := slice height(text sl) * 2 move slice to(text sl, slice x(text sl), slice height(text sl) * -1 + 100, ticks) if(bob sl) then( move slice by(bob sl, 5, 0, ticks) ) if(misa sl) then( move slice by(misa sl, -6, 0, ticks) ) wait(1) fade screen in variable(fr) while(slice is moving(text sl)) do( fr := (fr + 1) ,mod, 4 animate bob and misa walking(bob sl, misa sl, fr) wait(1) ) while(true) do( if(key is pressed(key:enter) || key is pressed(key:space) || key is pressed(key:ctrl) || key is pressed(key:esc) || key is pressed(key:alt)) then( break ) fr := (fr + 1) ,mod, 4 animate bob and misa walking(bob sl, misa sl, fr) wait(1) ) fade screen out free slice(col sl) end script, animate bob and misa walking, bob sl, misa sl, fr, begin if(bob sl) then( set sprite set number(bob sl, 1 + (fr / 2)) ) if(misa sl) then( set sprite set number(misa sl, 3 + (fr / 2)) ) end #----------------------------------------------------------------------- script, has donated, begin if(check tag(tag:donation small)) then(exit returning(true)) if(check tag(tag:donation large)) then(exit returning(true)) exit returning(false) end #----------------------------------------------------------------------- script, check ahead passage, x, y, d, npcs=false, begin variable(ix, iy, tile) ix := compass x(d) iy := compass y(d) tile := safe read map block(x+ix, y+iy, layer:base) if(not(is a passage(tile))) then(exit returning(false)) if(npcs) then( if(npc at spot(x+ix, y+iy)) then(exit returning(false)) ) exit returning(true) end script, check side passages, x, y, d, npcs=false, begin # returns true if at least one side passage is available variable(p1, p2) p1 := check ahead passage(x, y, rotate(d, counterclockwise), npcs) p2 := check ahead passage(x, y, rotate(d, clockwise), npcs) exit returning(p1 || p2) end script, rotate, d, wise, begin d += wise if(d < 0) then(d := 3) if(d > 3) then(d := 0) exit returning(d) end #----------------------------------------------------------------------- script, update monsters, begin variable(ref, id, near) # loop to handle monsters for(ref, -300, -1) do( id := get npc id(ref) if(id == -1) then(continue) # Skip all empty NPC slots if(is talker(ref)) then( # Talkers don't attack continue ) decrement monster atk frames(ref) if(npc is aligned(ref)) then( if(monster can hit hero(ref)) then( turn npc towards hero(ref) monster hits hero(ref) continue ) if(npc can turn(ref)) then( # it is possible to turn down a side passage if(npc should turn(ref)) then( variable(turn) turn := npc choose turn(ref) rotate npc(ref, turn) set npc exbit(ref, nbit:deadend, false) set npc exbit(ref, nbit:justturned, true) continue ) ) if(npc dead end(ref)) then( set npc exbit(ref, nbit:deadend, true) ) )else( # Not aligned set npc exbit(ref, nbit:justturned, false) ) ) end script, get npc exbit, ref, bit, begin variable(n) n := npc extra(ref, extra 2) if(n,and,2^bit) then(exit returning(true)) exit returning(false) end script, set npc exbit, ref, bit, value=1, begin variable(n) n := npc extra(ref, extra 2) if(value) then(n := n, or, 2^bit) else(n := n, and, (-1, xor, 2^bit)) set npc extra(ref, extra 2, n) end script, npc should turn, ref, begin if(get npc exbit(ref, nbit:justturned)) then( # Just turned, probably don't want to turn again (but still turn occasionally, to avoid getting stuck) if(percent(85)) then( exit returning(false) ) ) exit returning(percent(75) || get npc exbit(ref, nbit:deadend)) end script, npc dead end, ref, begin exit returning(not(npc can advance(ref)) && not(npc can turn(ref))) end script, npc can advance, ref, begin exit returning(check ahead passage(npc x(ref), npc y(ref), npc direction(ref), true)) end script, npc can turn, ref, begin exit returning(check side passages(npc x(ref), npc y(ref), npc direction(ref), true)) end script, rotate npc, ref, wise, begin variable(d) d := npc direction(ref) d := rotate(d, wise) set npc direction(ref, d) end script, npc is aligned, ref, begin exit returning((npc pixel x(ref),mod,20) == 0 && (npc pixel y(ref),mod,20) == 0) end script, npc choose turn, ref, begin variable(turn) if(random(0, 1) == 0) then(turn := clockwise) else(turn := counterclockwise) exit returning(turn) end script, turn npc towards hero, ref, begin variable(d, diff x, diff y) d := npc direction(ref) diff x := hero x -- npc x(ref) diff y := hero y -- npc y(ref) if(diff x == 0) then( if(diff y > 0) then(d := down) if(diff y < 0) then(d := up) ) if(diff y == 0) then( if(diff x > 0) then(d := right) if(diff x < 0) then(d := left) ) if(diff x <> 0 && diff y <> 0) then( if(diff x > diff y) then( if(diff y > 0) then(d := down) if(diff y < 0) then(d := up) ) if(diff x < diff y) then( if(diff x > 0) then(d := right) if(diff x < 0) then(d := left) ) ) if(repel level > 0) then( d := (d + 2) ,mod, 4 ) set npc direction(ref, d) end script, distance to monster in pixels under, ref, dist, begin variable(diff x, diff y) diff x := hero pixel x -- npc pixel x(ref) diff y := hero pixel y -- npc pixel y(ref) exit returning(diff x ^ 2 + diff y ^ 2 < dist ^ 2) end script, distance from effect to monster in pixels under, sl, ref, dist, begin variable(diff x, diff y) diff x := slice x(sl) -- npc pixel x(ref) diff y := slice y(sl) -- npc pixel y(ref) exit returning(diff x ^ 2 + diff y ^ 2 < dist ^ 2) end #----------------------------------------------------------------------- script, max monsters for this map, begin variable(n) n := ((monsters per kilotile * 1000) / 1024 * (map width * map height)) / 1000 if (n > 64) then(n := 64) # Max of 64 exit returning(n) end script, random monster spawn, begin if(monster count < max monsters for this map && generating == false) then( if(find monster spawn pos) then( start spawn monster(find x, find y) exit script ) ) reset spawn timer end script, find monster spawn pos, begin # Results are returned in findx and findy # Returns true if location was found. variable(i, x, y, tile) for(i, 0, 49) do( # make 50 attempts to spawn x:= random(1, map width--2) y:= random(1, map height--2) if(abs(x -- hero x) <= 2 && abs(y -- hero y) <= 2) then(continue) tile := read map block(x, y, layer:base) if(is a passage(tile)) then( find x := x find y := y exit returning(true) ) ) exit returning(false) end script, monster count, begin variable(ref, count) count := 0 for(ref, -300, -1) do( if(is monster(ref)) then(count += 1) ) exit returning(count) end script, reset spawn timer, begin set timer(spawn timer, spawn delay, seconds, @random monster spawn) end script, start spawn monster, x, y, begin if(not(fog at spot(x, y))) then( create teleport cloud(x, y) ) spawn x := x spawn y := y set timer(spawn timer, 6, 1, @spawn monster complete) end script, spawn monster complete, begin create monster(spawn x, spawn y) reset spawn timer end script, create monster, x, y, begin variable(ref) variable(id) id := random monster for this map ref := create NPC(id, x, y, random(0,3)) set monster hp(ref, get monster max hp(ref)) exit returning(ref) end script, random monster for this map, begin switch(current map) do( case(0) do(exit returning(random(0,2))) #3 case(1) do(exit returning(random(0,4))) #5 case(2) do(exit returning(random(0,5))) #6 case(3) do(exit returning(random(1,7))) #7 case(4) do(exit returning(random(2,9))) #8 case(last map) do(exit returning(bacon body)) else(exit returning(random(0, last monster slot))) ) end script, random monster ref of id, id, begin variable(count, ref) count := npc copy count(id) if(count == 0) then(exit returning(0)) ref := npc reference(id, random(0, count--1)) exit returning(ref) end script, get monster hp, ref, begin exit returning(npc extra(ref, extra 0)) end script, set monster hp, ref, n, begin set npc extra(ref, extra 0, n) end script, get monster atk frames, ref, begin exit returning(npc extra(ref, extra 1)) end script, set monster atk frames, ref, n, begin set npc extra(ref, extra 1, n) end script, get monster max hp, ref, begin variable(id, max) id := get npc id(ref) switch(id) do( case(0) do(max := 2) # Pink Plip case(1) do(max := 2) # Skellyton case(2) do(max := 2) # Octo-Peril case(3) do(max := 3) # Wellsian Martian case(4) do(max := 4) # Purple Cogre case(5) do(max := 4) # Monocular Blarb case(6) do(max := 1) # Meat Man is weak (but fast!) case(7) do(max := 4) # Crypt Yuk case(8) do(max := 5) # Jelly Coiler case(9) do(max := 6) # Doom Sponge case(bacon body) do(max := 8) # Bacon Spawn is very strong else(max := 2) ) exit returning(max) end script, decrement monster atk frames, ref, begin variable(n) n := get monster atk frames(ref) n -= 1 if(n < 0) then(n := 0) set monster atk frames(ref, n) end script, damage monster, ref, amount, begin variable(hp) hp := get monster hp(ref) hp -= amount if(hp < 0) then(hp := 0) set monster hp(ref, hp) if(hp == 0) then(kill monster(ref)) end script, kill monster, ref, begin variable(id) id := get npc id(ref) write global(monster kill count + id, read global(monster kill count + id) + 1) monster drops treasure(ref) create burst on npc(ref) destroy npc(ref) play sound(sfx:enemy die) misa reaction to monster kill hero victory end script, monster blood color, ref, begin variable(id) id := get npc id(ref) switch(id) do( case(0) do(exit returning(rand num(91, 90, 23))) #Pink Plip case(1) do(exit returning(rand num(240, 160))) #Skellyton case(2) do(exit returning(rand num(171, 168, 166))) #Octo-Peril case(3) do(exit returning(rand num(107, 105, 232))) #Wellsian Martian case(4) do(exit returning(rand num(54, 116, 57))) #Purple Cogre case(5) do(exit returning(rand num(37, 70, 35, 185))) #Monocular Blarb case(6) do(exit returning(rand num(86, 88))) #Meat Man case(7) do(exit returning(rand num(27, 25, 22))) #Crypt Yuk case(8) do(exit returning(rand num(75, 73, 71, 69))) #Jelly Coiler case(9) do(exit returning(rand num(183, 217, 214, 219))) #Doom Sponge case(bacon body) do(exit returning(rand num(89, 240, 88))) #Bacon Spawn ) end script, rand num, n1, n2, n3=-99999, n4=-99999, n5=-99999, n6=-99999, n7=-99999, n8=-99999, begin variable(i) while(true) do( i := random(1, 8) switch(i) do( case(1) do(exit returning(n1)) case(2) do(exit returning(n2)) case(3) do(if(n3 <> -99999) then(exit returning(n3))) case(4) do(if(n4 <> -99999) then(exit returning(n4))) case(5) do(if(n5 <> -99999) then(exit returning(n5))) case(6) do(if(n6 <> -99999) then(exit returning(n6))) case(7) do(if(n7 <> -99999) then(exit returning(n7))) case(8) do(if(n8 <> -99999) then(exit returning(n8))) ) ) end script, create burst on npc, ref, begin variable(i) for(i, 0, 7) do( create burst particle( npc x(ref), npc y(ref), monster blood color(ref), monster blood color(ref), random(-5, 5), random(-5, 5), random(-20, 20), random(-20, 20), ) ) end script, create burst particle, x, y, color, border, rand x, rand y, dest x, dest y, begin variable(sl) sl := create ellipse(8, 8, border, color) set horiz anchor(sl, edge:center) set vert anchor(sl, edge:center) create effect(sl, x, y, 12) set slice x(sl, slice x(sl) + 10 + rand x) set slice y(sl, slice y(sl) + 10 + rand y) move slice to(sl, slice x(sl) + dest x, slice y(sl) + dest y, 12) set slice visible(sl, false) # hide at first slice to back(sl) end script, potion particle effect, color, border, begin create burst particle(hero x(0), hero y(0), color, border, 0, 0, 0, -14) create burst particle(hero x(0), hero y(0), color, border, 0, 0, 14, 0) create burst particle(hero x(0), hero y(0), color, border, 0, 0, 0, 14) create burst particle(hero x(0), hero y(0), color, border, 0, 0, -14, 0) end script, monster drops treasure, ref, begin variable(x, y) x := npc x(ref) y := npc y(ref) if(is item at spot(x, y)) then(exit script) if(percent(monster item rate)) then( # create an item create item(x, y, get monster item(ref)) )else( # create money create treasure(x, y, 100) ) end script, get monster item, ref, begin variable(id, item) id := get npc id(ref) switch(id) do( case(0) do( # Pink Plip item := item:brew ) case(1) do( # Skeleton if(percent(2)) then( item := item:bone )else( item := item:tonic ) ) case(2) do( # Land Squid item := item:brew ) case(3) do( # Bird Jellyfish item := item:tonic ) case(4) do( # Purple Cogre item := item:bone ) case(5) do( # Monocular Blarb if(percent(40)) then( item := item:tonic )else if(percent(80)) then( item := item:brew )else( item := item:jiffy ) ) else( # Meat Man, Crypt Yuk, Jelly Coiler, Doom Sponge if(percent(50)) then( item := item:tonic )else( item := item:brew ) ) ) if(percent(4)) then( #Rare drop switch(random(0, 7)) do( case(0) do(item := item:burning) case(1) do(item := item:bat) case(2) do(item := item:monarch) case(3) do(item := item:burning) case(4) do(item := item:chalk) case(5) do(item := item:jiffy) case(6) do(item := item:repel) case(7) do(item := item:telepo) ) ) exit returning(item) end script, monster can hit hero, ref, begin variable(i, ix, iy) for(i, 0, 3) do( ix := compass x(i) iy := compass y(i) if (npc x(ref) + ix == hero x && npc y(ref) + iy == hero y) then( exit returning(true) ) ) exit returning(false) end script, monster hits hero, ref, begin if(monster can attack(ref) == false) then(exit script) if(monster attack attempt(ref)) then( monster attack effect(ref, hero x, hero y, npc direction(ref)) damage hero(monster atk power(ref)) )else( miss effect(hero x, hero y) ) set monster atk frames(ref, 8) end script, monster attack attempt, ref, begin exit returning(percent(50)) end script, monster can attack, ref, begin exit returning (get monster atk frames(ref) <= 0) end script, monster attack effect, ref, x, y, d, begin variable(effect) # special case for other enemies switch(get npc id(ref)) do( case(0) do(effect := effect:punch) else(effect := effect:punch) ) create walkabout effect(effect, x, y, d, 3) play sound(sfx:punch) end script, monster atk power, ref, begin switch(get npc id(ref)) do( case(0) do(exit returning(1)) ) exit returning(1) end #----------------------------------------------------------------------- script, start spawn cultist, x, y, begin if(not(fog at spot(x, y))) then( create teleport cloud(x, y) ) spawn cultist x := x spawn cultist y := y set timer(spawn cultist timer, 6, 1, @spawn cultist complete) end script, spawn cultist complete, begin create talker(robed cultist, spawn cultist x, spawn cultist y) end script, start spawn misa, x, y, begin if(not(fog at spot(x, y))) then( create teleport cloud(x, y) ) spawn misa x := x spawn misa y := y set timer(spawn misa timer, 6, 1, @spawn misa complete) end script, spawn misa complete, begin create talker(misa the hamster, spawn misa x, spawn misa y) end script, start spawn bacontologist, x, y, begin if(not(fog at spot(x, y))) then( create teleport cloud(x, y) ) spawn bacontologist x := x spawn bacontologist y := y set timer(spawn bacontologist timer, 6, 1, @spawn bacontologist complete) end script, spawn bacontologist complete, begin create talker(bacontologist, spawn bacontologist x, spawn bacontologist y) end script, create talker, id, x, y, begin variable(ref) ref := create NPC(id, x, y, random(0,3)) end plotscript, do se do, begin variable(d, x, y, ref) d := hero direction(0) x := hero x(0) + compass x(d) y := hero y(0) + compass y(d) wait for hero(0) ref := npc at spot(x, y) wait for npc(ref) if(is talker(ref)) then( suspend all suspend obstruction set npc direction(ref, d + 2) walk hero(0, d, 1) walk npc(ref, npc direction(ref), 1) wait for hero(0) set hero direction(0, d + 2) wait for npc(ref) set npc direction(ref, d) resume all resume obstruction ) end #----------------------------------------------------------------------- script, pick up treasure, x, y, begin variable(tile) tile := safe read map block(x, y, layer:item) variable(i) for(i, 0, treasure types--1) do( if(tile == first treasure + i) then( get money(3 ^ i) update money display safe write map block(x, y, void, layer:item) if(i == 0) then( switch(random(0,2)) do( case(0) do(play sound(0)) case(1) do(play sound(4)) case(2) do(play sound(5)) ) )else( play sound(s:coin pickup + i) ) exit script ) ) if(is item icon(tile)) then( safe write map block(x, y, void, layer:item) variable(item) item := tile -- item icons show get item(item) ) end script, show get item, item, begin get item(item) $msg="Found " get item name(tmp str, item) msg $+ tmp str update console $msg="" get item description(tmp str, item) msg $+ tmp str update console play sound(sfx:item pickup) end script, update money display, begin $money str = "$" append number(money str, party money) if(not(money sl)) then( money sl := create text set outline(money sl, true) ) set slice text(money sl, money str) put slice(money sl, 0, 17) end plotscript, trade tinfoil pants for science, begin if(check equipment(0, slot:pants) == item:tinfoil) then( unequip(0, slot:pants) ) delete item(item:tinfoil) get item(item:science) update meters end #----------------------------------------------------------------------- script, safe write map block, x, y, tile, layer=0, begin if(x < 0) then(exit returning(true)) if(x >= map width) then(exit returning(true)) if(y < 0) then(exit returning(true)) if(y >= map height) then(exit returning(true)) write map block(x, y, tile, layer) exit returning(false) end script, safe read map block, x, y, layer=0, begin if(x < 0) then(exit returning(-1)) if(x >= map width) then(exit returning(-1)) if(y < 0) then(exit returning(-1)) if(y >= map height) then(exit returning(-1)) exit returning(read map block(x, y, layer)) end script, safe write pass block, x, y, pass, begin if(x < 0) then(exit returning(true)) if(x >= map width) then(exit returning(true)) if(y < 0) then(exit returning(true)) if(y >= map height) then(exit returning(true)) write pass block(x, y, pass) exit returning(false) end plotscript, generate map, begin if(get map creation(current map) == true) then(exit script) suspend all growth cycles := 0 variable(x, y) x := random(1, map width -- 2) y := random(1, map height -- 2) set hero position(leader, x, y) place stairs up(x, y) $msg="Please wait!" update console $msg="The dungeon lives and grows..." update console wait(1) generating := true cur floor variant := 0 passage ms := milliseconds recursion := 0 create passage(x, y) create more passages generating := false place stairs down(x, y) crack some walls(10 + current map * 2) setup map specials set map creation(current map, true) $msg="The dungeon has matured." update console resume all save progress end script, create passage, x, y, begin # Returns true if the passage was created growth cycles += 1 #if(growth cycles ,mod, 1000 == 0) then( # $msg=" ok=" # append number(msg, c:okay) # $msg+" nok=" # append number(msg, c:not okay) # $msg+" r=" # append number(msg, c:recursion) # $msg+" z=" # append number(msg, c:zone) # trace(msg) #) if(recursion > 100) then( c:recursion += 1 exit returning(false) ) if(read zone(1, x, y)) then( c:zone += 1 exit returning(false) ) # Avoid unresponsive script timeouts if(milliseconds -- passage ms > 1000) then( write map block(hero x(0), hero y(0), void, layer:fog) wait(1) passage ms := milliseconds ) if(passage okay(x, y) == false) then( write zone(1, x, y, true) c:not okay += 1 exit returning(false) ) create floor at(x, y) safe write map block(x, y, fog of war, layer:fog) safe write pass block(x, y, none) create treasure(x, y) write zone(1, x, y, false) variable(i, ix, iy) for(i, 0, 7) do( ix := around x(i) iy := around y(i) create wall(x + ix, y + iy) write zone(1, x + ix, y + iy, false) ) #--now dig side passages recursion += 1 variable(digs, ok, safety) for(digs, 0, 1) do( ok := false safety := 0 while(not(ok)) do( i := random(0, 3) ix := compass x(i) iy := compass y(i) ok := create passage(x + ix, y + iy) safety += 1 if(safety > 5) then(ok := true) ) ) recursion -= 1 c:okay += 1 exit returning(true) end script, create more passages, begin variable(i, x, y) x := map width / 2 y := map height / 2 for(i, 0, 7) do( next floor variant if(find passage near edge(x, y, i)) then( create passage(find x, find y) ) ) end script, next floor variant, begin cur floor variant += 1 if(first floor + cur floor variant > last floor) then( cur floor variant := 0 ) end script, find passage near edge, x, y, d, begin # Attempts to locate a passageway close to the edge of the void. # Returns true of successful. tile position returned in find x/find y globals variable(tile, ix, iy, f) # First, based on our current location, decide what type of tile to search for tile := safe read map block(x, y, layer:base) if(tile == void) then( # If void is found, search for a wall f := @is wall at spot )else( # If non-void is found, search for a wall near void f := @is wall near void at spot ) ix := x iy := y while(pos is on map minus edge(ix, iy)) do( ix += around x(d) iy += around y(d) if(run script by id(f, ix, iy)) then( if(find edge wall(ix, iy)) then( exit returning(true) ) break ) ) exit returning(false) end script, is wall at spot, x, y, begin variable(tile) tile := safe read map block(x, y, layer:base) exit returning(is a wall(tile)) end script, is wall near void at spot, x, y, begin if(is wall at spot(x, y)) then( variable(i, ix, iy, tile) for(i, 0, 7) do( ix := around x(i) iy := around y(i) tile := safe read map block(x+ix, y+iy, layer:base) if(tile == void) then(exit returning(true)) ) ) exit returning(false) end script, find edge wall, x, y, begin variable(ix, iy, tile) for(iy, y--2, y+2) do( for(ix, x--2, x+2) do( tile := safe read map block(ix, iy, layer:base) if(is a wall(tile)) then( if(is nearby passage(ix, iy)) then( find x := ix find y := iy exit returning(true) ) ) ) ) exit returning(false) end script, is nearby passage, x, y, begin variable(i, ix, iy, tile) # check compass points first for(i, 0, 3) do( ix := compass x(i) iy := compass y(i) tile := safe read map block(x + ix, y + iy, layer:base) if(is a passage(tile)) then( exit returning(true) ) ) exit returning(false) end script, pos is on map, x, y, begin if(x < 0) then(exit returning(false)) if(x >= map width) then(exit returning(false)) if(y < 0) then(exit returning(false)) if(y >= map height) then(exit returning(false)) exit returning(true) end script, pos is on map minus edge, x, y, begin if(x < 1) then(exit returning(false)) if(x >= map width--1) then(exit returning(false)) if(y < 1) then(exit returning(false)) if(y >= map height--1) then(exit returning(false)) exit returning(true) end script, create floor at, x, y, begin variable(tile) tile := safe read map block(x, y, layer:base) if(is a stairs(tile)) then(exit script) # already has stairs here, no need to write floor safe write map block(x, y, first floor + cur floor variant, layer:base) end script, passage okay, x, y, begin # first prevent passages near the edges if(x <= 0) then(exit returning(false)) if(x >= map width--1) then(exit returning(false)) if(y <= 0) then(exit returning(false)) if(y >= map height--1) then(exit returning(false)) # Check the tile that already exists at the dest location variable(tile) tile := safe read map block(x, y, layer:base) if(tile == void) then(exit returning(true)) # void, passage is okay if(tile == stairs up || tile == stairs down) then(exit returning(true)) # stairs, passage okay if(is a wall(tile)) then( # this is already a wall variable(near) near := count surrounding walls(x, y) if(near >= threshhold) then( # threshold or more nearby walls, allow this passage exit returning(true) ) ) exit returning(false) end script, crack some walls, count, begin variable(i) for(i, 1, count) do( crack a wall ) end script, crack a wall, begin variable(i, x, y, tile) for(i, 0, 100) do( # first try to find a good wall x := random(1, map width -- 2) y := random(1, map height -- 2) tile := read map block(x, y, layer:base) if(is a wall(tile)) then( if(detect opposing passages(x,y)) then( if(count compass void(x,y) == 0) then( crack wall(x, y) exit script ) ) ) ) for(i, 0, 100) do( # then settle for an adequate wall x := random(1, map width -- 2) y := random(1, map height -- 2) tile := read map block(x, y, layer:base) if(is a wall(tile)) then( if(count compass walls(x,y) == 2) then( if(count compass void(x,y) == 0) then( crack wall(x, y) exit script ) ) ) ) end script, crack wall, x, y, begin write map block(x, y, first crack tile + random(0, 1), layer:chalk) end script, count surrounding walls, x, y, begin variable(i, ix, iy, tile, count) count := 0 for(i, 0, 7) do( ix := around x(i) iy := around y(i) tile := safe read map block(x + ix, y + iy, layer:base) if(not(is a passage(tile))) then(count += 1) # actually count any non-passages as walls ) exit returning(count) end script, detect opposing passages, x, y, begin variable(n, e, s, w) n := safe read map block(x, y -- 1, layer:base) e := safe read map block(x + 1, y, layer:base) s := safe read map block(x, y + 1, layer:base) w := safe read map block(x -- 1, y, layer:base) if (not(is a passage(n)) && not(is a passage(s)) && is a passage(e) && is a passage(w)) then(exit returning(true)) if (not(is a passage(e)) && not(is a passage(w)) && is a passage(n) && is a passage(s)) then(exit returning(true)) exit returning(false) end script, count compass walls, x, y, begin variable(i, ix, iy, tile, count) count := 0 for(i, 0, 3) do( ix := compass x(i) iy := compass y(i) tile := safe read map block(x + ix, y + iy, layer:base) if(not(is a passage(tile))) then(count += 1) # actually count any non-passages as walls ) exit returning(count) end script, count compass void, x, y, begin variable(i, ix, iy, tile, count) count := 0 for(i, 0, 3) do( ix := compass x(i) iy := compass y(i) tile := safe read map block(x + ix, y + iy, layer:base) if(tile == void) then(count += 1) ) exit returning(count) end script, create wall, x, y, begin variable(tile, new tile) tile := safe read map block(x, y, layer:base) if(tile == 0) then( safe write map block(x, y, first wall, layer:base) safe write map block(x, y, fog of war, layer:fog) safe write pass block(x, y, northwall,or,eastwall,or,southwall,or,westwall) ) end script, is a passage, tile, begin if(tile >= first floor && tile <= last floor) then(exit returning(true)) exit returning(false) end script, is a stairs, tile, begin if(tile == stairs up || tile == stairs down) then(exit returning(true)) exit returning(false) end script, is a wall, tile, begin if(tile >= first wall, and, tile <= last wall) then(exit returning(true)) exit returning(false) end script, is item icon, tile, begin exit returning(tile > item icons) end script, fix all walls, begin variable(x, y) for(y, 0, map height--1) do( for(x, 0, map width--1) do( fix wall at(x, y) ) ) end script, fix more surrounding walls, x, y, begin fix surrounding walls(x, y) variable(i, ix, iy) for(i, 0, 11) do( ix := further around x (i) iy := further around y (i) fix wall at(x + ix, y + iy) ) end script, fix surrounding walls, x, y, begin variable(i, ix, iy) for(i, 0, 7) do( ix := around x (i) iy := around y (i) fix wall at(x + ix, y + iy) ) end script, fix wall at, x, y, begin variable(tile) tile := get fixed wall(x, y) if(tile <> false) then( safe write map block(x, y, tile, layer:base) ) end script, get fixed wall, x, y, begin return(false) variable(tile, nw, n, ne, e, se, s, sw, w) tile := safe read map block(x, y) if (is a wall(tile)) then( n := safe read map block(x , y--1) e := safe read map block(x+1 , y) s := safe read map block(x , y+1) w := safe read map block(x--1, y) # horizontal/vertical walls if(two of four open(n, s, e, w)) then(exit returning(7)) if(two of four open(e, w, n, s)) then(exit returning(8)) # one wall with three open if(one of four blocked(n, e, s, w)) then(exit returning(9)) if(one of four blocked(e, s, w, n)) then(exit returning(10)) if(one of four blocked(s, w, n, e)) then(exit returning(11)) if(one of four blocked(w, n, e, s)) then(exit returning(12)) # island wall if(all four open(n, e, s, w)) then(exit returning(13)) # If we have gotten this far, read the diagonals nw := safe read map block(x--1, y--1) ne := safe read map block(x+1 , y--1) se := safe read map block(x+1 , y+1) sw := safe read map block(x--1, y+1) # corner walls if(two of five open(n, e, s, w, sw)) then(exit returning(14)) if(two of five open(e, s, w, n, nw)) then(exit returning(15)) if(two of five open(s, w, n, e, ne)) then(exit returning(16)) if(two of five open(w, n, e, s, se)) then(exit returning(17)) if(three of five open(sw, n, e, s, w)) then(exit returning(18)) if(three of five open(nw, e, s, w, n)) then(exit returning(19)) if(three of five open(ne, s, w, n, e)) then(exit returning(20)) if(three of five open(se, w, n, e, s)) then(exit returning(21)) # three walls with one open if(one of six open(n, e, s, w, se, sw)) then(exit returning(3)) if(one of six open(e, s, w, n, nw, sw)) then(exit returning(4)) if(one of six open(s, w, n, e, ne, nw)) then(exit returning(5)) if(one of six open(w, n, e, s, se, ne)) then(exit returning(6)) if(two of six open(sw, n, e, s, w, se)) then(exit returning(22)) if(two of six open(nw, e, s, w, n, sw)) then(exit returning(23)) if(two of six open(ne, s, w, n, e, nw)) then(exit returning(24)) if(two of six open(se, w, n, e, s, ne)) then(exit returning(25)) if(two of six open(se, n, e, s, w, sw)) then(exit returning(26)) if(two of six open(sw, e, s, w, n, nw)) then(exit returning(27)) if(two of six open(nw, s, w, n, e, ne)) then(exit returning(28)) if(two of six open(ne, w, n, e, s, se)) then(exit returning(29)) if(three of six open(sw, se, n, e, s, w)) then(exit returning(30)) if(three of six open(nw, sw, e, s, w, n)) then(exit returning(31)) if(three of six open(ne, nw, s, w, n, e)) then(exit returning(32)) if(three of six open(se, ne, w, n, e, s)) then(exit returning(33)) # no walls, only darn rotten corners if(all four blocked(n, e, s, w)) then( # Single corners if(one of four open(nw, ne, se, sw)) then(exit returning(34)) if(one of four open(ne, se, sw, nw)) then(exit returning(35)) if(one of four open(se, sw, nw, ne)) then(exit returning(36)) if(one of four open(sw, nw, ne, se)) then(exit returning(37)) # Double corners if(two of four open(nw, ne, se, sw)) then(exit returning(38)) if(two of four open(ne, se, sw, nw)) then(exit returning(39)) if(two of four open(se, sw, nw, ne)) then(exit returning(40)) if(two of four open(sw, nw, ne, se)) then(exit returning(41)) # Triple corners if(one of four blocked(sw, nw, ne, se)) then(exit returning(42)) if(one of four blocked(nw, ne, se, sw)) then(exit returning(43)) if(one of four blocked(ne, se, sw, nw)) then(exit returning(44)) if(one of four blocked(se, sw, nw, ne)) then(exit returning(45)) # Diagonal corners if(two of four open(ne, sw, nw, se)) then(exit returning(46)) if(two of four open(nw, se, ne, sw)) then(exit returning(47)) # All corners if(all four open(ne, nw, sw, se)) then(exit returning(48)) ) ) end script, fog at spot, x, y, begin variable(fog tile) fog tile := safe read map block(x, y, layer:fog) exit returning(fog tile == fog of war) end script, clear fog of war, x, y, begin clear fog at (x, y) variable(i, ix, iy) for(i, 0, 7) do( ix := around x (i) iy := around y (i) clear fog at(x + ix, y + iy) ) for(i, 0, 11) do( ix := further around x (i) iy := further around y (i) clear fog at(x + ix, y + iy) ) for(i, 0, 11) do( ix := further around x (i) iy := further around y (i) fix fog edge at(x + ix, y + iy) ) for(i, 0, 15) do( ix := even further around x (i) iy := even further around y (i) fix fog edge at(x + ix, y + iy) ) end script, clear fog at, x, y, begin safe write map block(x, y, void, layer:fog) end script, fix fog edge at, x, y, begin variable(tile, cleared fog) tile := safe read map block(x, y, layer:fog) if(tile == fog of war) then( # fully fogged, no changes needed exit script ) cleared fog := get fog edge(x, y) safe write map block(x, y, cleared fog, layer:fog) end script, get fog edge, x, y, begin variable(n, e, s, w) n := safe read map block(x , y--1, layer:fog) e := safe read map block(x+1 , y , layer:fog) s := safe read map block(x , y+1 , layer:fog) w := safe read map block(x--1, y , layer:fog) if(two of four fogged(w, n, e, s)) then(exit returning(fog of war + 1)) if(two of four fogged(n, e, s, w)) then(exit returning(fog of war + 2)) if(two of four fogged(e, s, w, n)) then(exit returning(fog of war + 3)) if(two of four fogged(s, w, n, e)) then(exit returning(fog of war + 4)) if(one of four fogged(n, e, s, w)) then(exit returning(fog of war + 5)) if(one of four fogged(e, s, w, n)) then(exit returning(fog of war + 6)) if(one of four fogged(s, w, n, e)) then(exit returning(fog of war + 7)) if(one of four fogged(w, n, s, e)) then(exit returning(fog of war + 8)) if(two of four fogged(n, s, e, w)) then(exit returning(fog of war + 9)) if(two of four fogged(e, w, n, s)) then(exit returning(fog of war + 10)) exit returning(void) end script, clear all fog, begin variable(x, y) for(y, 0, map height--1) do( for(x, 0, map width--1) do( clear fog at(x, y) ) ) end script, place stairs up, x, y, begin if(get up stairs x(current map) == 0 && get up stairs y(current map) == 0) then( if(current map > 0) then( safe write map block(x, y, stairs up) end set up stairs x(current map, x) set up stairs y(current map, y) ) end script, place stairs down, up x, up y, begin if(get down stairs x(current map) == 0 && get down stairs y(current map) == 0) then( variable(i, down x, down y) # first get a random passage find tunnel end down x := find x down y := find y # try 10 times, use the furthest from the starting point for (i, 0, 9) do( find tunnel end if(found was further(up x, up y, down x, down y)) then( down x := find x down y := find y ) ) if(current map < last map) then( safe write map block(down x, down y, stairs down) safe write map block(down x, down y, void, layer:item) # no treasure on stairs! end set down stairs x(current map, down x) set down stairs y(current map, down y) ) end script, find tunnel end, begin variable(x, y, tile, safety, count) # try 100 times to find a tunnel ending while(safety < 100) do( x := random(1, map width--2) y := random(1, map height--2) tile := safe read map block(x, y) if(is a passage(tile)) then( count := count compass walls(x, y) if(count == 3) then( break ) ) safety += 1 ) if(safety >= 100) then( # Failed to find a tunnel end. Find a floor instead. while(safety < 1000) do( x := random(1, map width--2) y := random(1, map height--2) tile := safe read map block(x, y) if(is a passage(tile)) then( break ) safety += 1 ) ) if(safety >= 1000) then( $tmpstr="Failed to find a tunnel ending after 1000 tries!" trace(tmpstr) ) find x := x find y := y end script, found was further, origin x, origin y, compare x, compare y, begin variable(diff1 x, diff1 y, diff2 x, diff2 y) diff1 x := abs(origin x -- find x) diff1 y := abs(origin y -- find y) diff2 x := abs(origin x -- compare x) diff2 y := abs(origin y -- compare y) variable(dist1, dist2) dist1 := diff1 x^2 + diff1 y^2 dist2 := diff2 x^2 + diff2 y^2 exit returning(dist1 > dist2) end #----------------------------------------------------------------------- script, create treasure, x, y, rate=-1, level=0, begin if(rate == -1) then(rate := treasure rate) variable(tile) tile := safe read map block(x, y) if(is a stairs(tile)) then(exit script) # no treasure on staircases! if(random(0,99) >= rate) then( variable(old treas) old treas := read treasure(x, y) if(old treas) then(level := old treas -- first treasure + 1) if(level >= treasure types) then(level := treasure types -- 1) safe write map block(x, y, first treasure+level, layer:item) )else( if(level < treasure types--1) then( create treasure(x, y, -1, level+1) ) ) end script, read treasure, x, y, begin variable(tile) tile := safe read map block(x, y, layer:item) if(tile >= first treasure && tile < first treasure + treasure types) then( exit returning(tile) ) exit returning(false) end script, create item, x, y, item, begin safe write map block(x, y, item + item icons, layer:item) end script, is item at spot, x, y, begin variable(tile) tile := read map block(x, y, layer:item) exit returning(is item icon(tile)) end #----------------------------------------------------------------------- script, update console, begin variable(i) for(i, 3, 0, -1) do( copy string(msg+i+1, msg+i) ) for(i, 0, 3) do( show string at(msg+1+i, 0, 190 -- i * 10) string color(msg+1+i, 174 -- i * 4) ) set timer(timer:console decay, 7, 18, @console decay) end script, console decay, begin variable(i) for(i, 4, 1, -1) do( if(string length(msg+i) > 0) then( $msg+i="" set timer(timer:console decay, 7, 18, @console decay) exit script ) ) end #----------------------------------------------------------------------- # Awkward corner-detection code. There has gotta be a better way :P script, one of four open, d1, d2, d3, d4, begin if(is a wall(d1)) then(exit returning(false)) if(is a wall(d2)==false) then(exit returning(false)) if(is a wall(d3)==false) then(exit returning(false)) if(is a wall(d4)==false) then(exit returning(false)) exit returning(true) end script, two of four open, d1, d2, d3, d4, begin if(is a wall(d1)) then(exit returning(false)) if(is a wall(d2)) then(exit returning(false)) if(is a wall(d3)==false) then(exit returning(false)) if(is a wall(d4)==false) then(exit returning(false)) exit returning(true) end script, one of four blocked, d1, d2, d3, d4, begin if(is a wall(d1)==false) then(exit returning(false)) if(is a wall(d2)) then(exit returning(false)) if(is a wall(d3)) then(exit returning(false)) if(is a wall(d4)) then(exit returning(false)) exit returning(true) end script, two of five open, d1, d2, d3, d4, d5, begin if(is a wall(d1)) then(exit returning(false)) if(is a wall(d2)) then(exit returning(false)) if(is a wall(d3)==false) then(exit returning(false)) if(is a wall(d4)==false) then(exit returning(false)) if(is a wall(d5)==false) then(exit returning(false)) exit returning(true) end script, three of five open, d1, d2, d3, d4, d5, begin if(is a wall(d1)) then(exit returning(false)) if(is a wall(d2)) then(exit returning(false)) if(is a wall(d3)) then(exit returning(false)) if(is a wall(d4)==false) then(exit returning(false)) if(is a wall(d5)==false) then(exit returning(false)) exit returning(true) end script, one of six open, d1, d2, d3, d4, d5, d6, begin if(is a wall(d1)) then(exit returning(false)) if(is a wall(d2)==false) then(exit returning(false)) if(is a wall(d3)==false) then(exit returning(false)) if(is a wall(d4)==false) then(exit returning(false)) if(is a wall(d5)==false) then(exit returning(false)) if(is a wall(d6)==false) then(exit returning(false)) exit returning(true) end script, two of six open, d1, d2, d3, d4, d5, d6, begin if(is a wall(d1)) then(exit returning(false)) if(is a wall(d2)) then(exit returning(false)) if(is a wall(d3)==false) then(exit returning(false)) if(is a wall(d4)==false) then(exit returning(false)) if(is a wall(d5)==false) then(exit returning(false)) if(is a wall(d6)==false) then(exit returning(false)) exit returning(true) end script, three of six open, d1, d2, d3, d4, d5, d6, begin if(is a wall(d1)) then(exit returning(false)) if(is a wall(d2)) then(exit returning(false)) if(is a wall(d3)) then(exit returning(false)) if(is a wall(d4)==false) then(exit returning(false)) if(is a wall(d5)==false) then(exit returning(false)) if(is a wall(d6)==false) then(exit returning(false)) exit returning(true) end script, all four open, d1, d2, d3, d4, begin if(is a wall(d1)) then(exit returning(false)) if(is a wall(d2)) then(exit returning(false)) if(is a wall(d3)) then(exit returning(false)) if(is a wall(d4)) then(exit returning(false)) exit returning(true) end script, all four blocked, d1, d2, d3, d4, begin if(is a wall(d1)==false) then(exit returning(false)) if(is a wall(d2)==false) then(exit returning(false)) if(is a wall(d3)==false) then(exit returning(false)) if(is a wall(d4)==false) then(exit returning(false)) exit returning(true) end script, two of four fogged, d1, d2, d3, d4, begin if(d1 <> fog of war) then(exit returning(false)) if(d2 <> fog of war) then(exit returning(false)) if(d3 == fog of war) then(exit returning(false)) if(d4 == fog of war) then(exit returning(false)) exit returning(true) end script, one of four fogged, d1, d2, d3, d4, begin if(d1 <> fog of war) then(exit returning(false)) if(d2 == fog of war) then(exit returning(false)) if(d3 == fog of war) then(exit returning(false)) if(d4 == fog of war) then(exit returning(false)) exit returning(true) end #----------------------------------------------------------------------- # Functions for iterating through relative coordinates script, around x, i, begin switch(i) do( case(0) do(exit returning(-1)) case(1) do(exit returning(0)) case(2) do(exit returning(1)) case(3) do(exit returning(1)) case(4) do(exit returning(1)) case(5) do(exit returning(0)) case(6) do(exit returning(-1)) case(7) do(exit returning(-1)) ) exit returning(0) end script, around y, i, begin switch(i) do( case(0) do(exit returning(-1)) case(1) do(exit returning(-1)) case(2) do(exit returning(-1)) case(3) do(exit returning(0)) case(4) do(exit returning(1)) case(5) do(exit returning(1)) case(6) do(exit returning(1)) case(7) do(exit returning(0)) ) exit returning(0) end script, compass x, i, begin switch(i) do( case(0) do(exit returning(0)) case(1) do(exit returning(1)) case(2) do(exit returning(0)) case(3) do(exit returning(-1)) ) end script, compass y, i, begin switch(i) do( case(0) do(exit returning(-1)) case(1) do(exit returning(0)) case(2) do(exit returning(1)) case(3) do(exit returning(0)) ) end script, further around x, i, begin switch(i) do( case(0) do(exit returning(-1)) case(1) do(exit returning(0)) case(2) do(exit returning(1)) case(3) do(exit returning(2)) case(4) do(exit returning(2)) case(5) do(exit returning(2)) case(6) do(exit returning(1)) case(7) do(exit returning(0)) case(8) do(exit returning(-1)) case(9) do(exit returning(-2)) case(10) do(exit returning(-2)) case(11) do(exit returning(-2)) ) exit returning(0) end script, further around y, i, begin switch(i) do( case(0) do(exit returning(-2)) case(1) do(exit returning(-2)) case(2) do(exit returning(-2)) case(3) do(exit returning(-1)) case(4) do(exit returning(0)) case(5) do(exit returning(1)) case(6) do(exit returning(2)) case(7) do(exit returning(2)) case(8) do(exit returning(2)) case(9) do(exit returning(1)) case(10) do(exit returning(0)) case(11) do(exit returning(-1)) ) exit returning(0) end script, even further around x, i, begin switch(i) do( case(0) do(exit returning(-1)) case(1) do(exit returning(0)) case(2) do(exit returning(1)) case(3) do(exit returning(2)) case(4) do(exit returning(3)) case(5) do(exit returning(3)) case(6) do(exit returning(3)) case(7) do(exit returning(2)) case(8) do(exit returning(1)) case(9) do(exit returning(0)) case(10) do(exit returning(-1)) case(11) do(exit returning(-2)) case(12) do(exit returning(-3)) case(13) do(exit returning(-3)) case(14) do(exit returning(-3)) case(15) do(exit returning(-2)) ) exit returning(0) end script, even further around y, i, begin switch(i) do( case(0) do(exit returning(-3)) case(1) do(exit returning(-3)) case(2) do(exit returning(-3)) case(3) do(exit returning(-2)) case(4) do(exit returning(-1)) case(5) do(exit returning(0)) case(6) do(exit returning(1)) case(7) do(exit returning(2)) case(8) do(exit returning(3)) case(9) do(exit returning(3)) case(10) do(exit returning(3)) case(11) do(exit returning(2)) case(12) do(exit returning(1)) case(13) do(exit returning(0)) case(14) do(exit returning(-1)) case(15) do(exit returning(-2)) ) exit returning(0) end #-----------------------------------------------------------------------