(local util (require :lib.util)) (local tiles (util.require :game.tiles)) (local {: vm : org : itile} (require :game.defs)) (local {: lo : hi} util) ; Entity memory layout: ; +0 - yx ; +2 - event handler ; +4 - link word ; +6 - link pointer ; All entities exist in a single page in RAM - with this structure we can have up to 32 ; (players are handled specially and never require a link) ; if we really need more we could have one page for entities and one page for link data ; hellmaze level 2 from MS-DOS Neut Tower has 36 entities - good excuse to simplify IMO ; The entity count for a level is stored after the map. (local ev { :touch 0 :untouch 1 :act 2 :deact 3 :tog 4 }) (vm:word :entity-count :lit :map-entity-count :bget) (vm:def :lookup-entity ; i -- entity [:lda vm.TOP :x] [:asl :a] [:asl :a] [:asl :a] ; x8 [:sta vm.TOP :x] [:lda #(hi org.entity.org)] [:sta vm.TOPH :x]) (vm:word :entity-at ; yx -- entity|0 :>r 0 :entity-count (vm:while [:dup] :dec ; entity|0 i :dup :lookup-entity :get :rtop := (vm:when :lookup-entity :swap) ) :drop :rdrop) (vm.code:append :responder [:dw 0]) (vm:word :get-responder :lit :responder :get) (vm:word :responder-itile :get-responder :get :itile-at) (vm:word :entity>do ; entity ev -- :over :lit :responder :dup :get :>r :set :swap 2 :+ :get :execute :r> :lit :responder :set) (vm:word :linked-entity :get-responder :dup 4 :+ :get :dup (vm:if [:dup :. :execute] [:drop 6 :+ :dup :. :get]) :dup :.) (vm:word :touch-entity ; yx -- f :entity-at :dup (vm:when ev.touch :entity>do vm.true)) (vm:word :untouch-entity ; yx -- :entity-at :dup (vm:if [ev.untouch :entity>do] [:drop])) (vm:word :set-entitytile ; e itile -- :swap :get :swap :update-itile) (vm:word :set-respondertile ; itile -- :get-responder :get :swap :update-itile) (vm:word :handle-onoff ; ev off on -- :do ] [:drop])) (vm:word :door ; ev -- (vm:if-and [[:is-jaye?] [:dup ev.touch :=] [:responder-itile (itile :dooropen) :=]] [:move-jaye :drop] [(itile :doorclosed) (itile :dooropen) :handle-onoff])) (vm:word :move-neut-to-responder :get-responder :get :move-neut-to) (vm:word :switch ; ev -- :dup ev.touch := (vm:when :drop ev.tog :is-neut? (vm:when :move-neut-to-responder)) :dup (itile :switchoff) (itile :switchon) :handle-onoff (itile :switchon) :activate-link) (vm:word :term ; ev -- :dup ev.touch := (vm:when :is-jaye? (vm:if [:drop ev.act] [:linked-entity :dup :get :itile-at (itile :termon) := (vm:if [:get :move-neut-to] [:drop])])) :dup (itile :termoff) (itile :termon) :handle-onoff) (vm:word :handle-scan ; ev -- :dup (itile :scanoff) (itile :scanon) :handle-onoff :linked-entity :swap :entity>do) (vm:word :scan ; ev -- :is-neut? (vm:if [ (vm:case [ev.touch ev.act :handle-scan :move-neut-to-responder] [ev.untouch ev.deact :handle-scan] [:else]) ] [:drop])) (fn append-from-map [map entity-org] (each [_ entity (ipairs map.objects)] (when entity.name (entity-org:append entity.name)) (entity-org:append [:db (- entity.x 1)] [:db (- entity.y 1)] [:ref entity.func] (if (and entity.linkword (> (length entity.linkword) 0)) [:ref entity.linkword] [:dw 0]) (if entity.link [:dw (+ entity-org.org (* (- entity.link 1) 8))] [:dw 0])))) {: ev : append-from-map}