var MODE-MOVE var MODE-WAIT ( T I C K ) defer party defer entities var objects : obj-entity ( optr -- entity ) cell + @ ; : single-entity-at ( x y 0 entity -- x y entity|0 b ) swap drop >r 2dup ( x y x y r:e ) r@ entity.x @ r@ entity.y @ world>tile 2= ( x y b r:e ) if r r@ obj-entity single-entity-at if rdrop 0 else rot drop drop ; ( P L A Y E R ) var player.state userword var player.prevdir 1 const MOVING userword 2 const NOCLIP userword 4 const ISNEUT userword 8 const HASNEUT userword : noclip player.state NOCLIP fnot! ; userword : isneut? player.state ISNEUT f@ ; userword : isjaye? isneut? not ; userword : {jaye} isjaye? player.state MOVING f@ and if {jeanne-walk} else {jeanne} then ; : player.canmove? ( x y -- ) player.state NOCLIP f@ not if isneut? if NEUTABLE else WALKABLE then mapflag? else drop drop 1 then ; 14 9 N ' {jaye} defentity pjaye 17 5 N ' {neut} defentity pneut : player isneut? if pneut else pjaye then ; : sched-move-entity ( entity -- ) :| jobdata move-entity |; sched-with ; : move-player 1 player.state MOVING f! isneut? not if ( only jaye can have a party ) player.prevdir @ party each dup player != if dup entity.dir @ >r dup >rot entity.dir ! sched-move-entity rot mapsize ( b x y w h ) rot ( b b x w ) >= or or ; : leaving? ( x y dir -- b ) dup N = if drop swap drop 0 < else dup W = if drop drop 0 < else S = if swap drop mapsize swap drop >= else drop mapsize drop >= then then then ; defer jaye-touch ( x y -- b ) defer neut-touch ( x y -- b ) : player-touch isneut? if neut-touch else jaye-touch then ; : touch-begin each 2dup more >rot drop drop ; : touch-next dup if rdrop done then drop rswap ; : touch-last ' done , ; immediate : ;touch [ ' touch-last , ' [ , ] ; immediate : check-player-touch ( x y -- b ) touch-begin entity-at dup if EVTOUCH entity>do 1 then touch-next player-touch touch-next out-of-bounds touch-next player.canmove? not ;touch : try-move-player player entity-dst check-player-touch not if move-player then ; : follow ( e -- ) player entity>pos do more ) entities each EVTICK entity>do more party each EVTICK entity>do more pneut EVTICK entity>do tick-mapedit jiles tick-debounce q-level @ dup if 0 q-level ! reset-level loadlevel q-player.x @ q-player.y @ tile>world player entity.pos! party each follow more else drop then ; ' mode-move MODE-MOVE ! ' tick-debounce MODE-WAIT ! : draw-entity >r r@ entity.x @ r@ entity.y @ r@ entity.dir @ sprite sprite-bob draw-sprite ; var showmouse 1 showmouse ! var glitchlevel var quaking var _dorubber : rubber _dorubber @ not _dorubber ! ; : full-draw quaking @ not if player entity.x @ 152 - player entity.y @ 92 - scroll else 0 ticks 3 % 13 * 8 % scroll then _dorubber @ objects @ and if objects @ links each dup obj-entity draw-entity more then entities each draw-entity more party each draw-entity more player.state HASNEUT f@ if pneut draw-entity then showmouse @ if mouseworldpos 4 draw-sprite then glitchlevel @ glitch draw-screen draw-footer ; var defining-objects-head var defining-objects-ptr : objects: create here 0 , 0 defining-objects-head ! defining-objects-ptr ! does> @ objects ! ; : link-object ( entity -- ) here defining-objects-head @ , swap , dup defining-objects-head ! defining-objects-ptr @ ! ; 4 const COMP-OFF 5 const COMP-ON 9 const DOOR-CLOSED 10 const DOOR-OPENED 11 const SWITCH-OFF 12 const SWITCH-ON : entity>tile ( entity -- tile ) entity>pos world>tile tile ; : entity>tile? ( entity expected - b ) swap entity>tile b@ = ; : toggleval ( off on val -- off|on ) over = not if swap then drop ; : toggletile ( entity off on -- ) r r@ entity>tile b@ toggleval tile b! invalidate-map ; : respondertile! ( tile -- ) responder entity>tile b! invalidate-map ; : handle-onoff ( ev on off -- ) rot toggletile else drop drop drop then then then ; : statechange? ( ev -- b ) dup EVACT = over EVDEACT = or swap EVTOG = or ; : blankentity array here >r N ' {duck} allotentity tile? if EVACT else EVDEACT then responder entity.user @ swap entity>do else drop then ; : door blankentity dup link-object :| dup EVTOUCH = isjaye? and responder DOOR-OPENED entity>tile? and if move-player then DOOR-OPENED DOOR-CLOSED handle-onoff |; swap ! ; : switch blankentity swap , dup link-object :| dup EVTOUCH = isneut? and if move-player then dup EVTOUCH = if responder EVTOG entity>do then dup SWITCH-ON SWITCH-OFF handle-onoff SWITCH-ON handle-link |; swap ! ; : computer blankentity swap , dup link-object :| dup EVTOUCH = isjaye? and if responder EVACT entity>do then dup EVTOUCH = isneut? and if move-player then dup COMP-ON COMP-OFF handle-onoff COMP-ON handle-link |; swap ! ; : chainev ( entity xp -- ) swap dup @ , ! ; immediate :noname reset-level MODE-MOVE @ ' tick redefine ' full-draw ' draw redefine :| pjaye yield done |; ' party redefine :| MODE-WAIT @ ' tick redefine |; ' any-job-started redefine :| MODE-MOVE @ ' tick redefine hide-footer |; ' all-jobs-complete redefine ; ' onload redefine