########################################### # # Fuse # # A minimalist reinterpretation of # the classic Pipe Dream. Assemble lines # to guide a burning fuse. Don't let it # burn out! # # Press WASD to move the current line # fragments and E to lay them down. # You cannot lay down a line overlapping # any existing lines. # # Runs best at 7 cycles/frame. # # John Earnest # ########################################### :alias ex vd # fuse position x :alias ey vc # fuse position y :alias px vb # cursor position x :alias py va # cursor position y :alias tile v9 # selected tile :alias timer-0 v8 # fuse movement cookoff :alias timer-1 v7 # score (low digits) :alias timer-2 v6 # score (high digits) :const tile-mask 0b111000 :const fuse-speed 3 # higher is slower : main init-game # draw starting cursor: i := tiles i += tile sprite px py 8 # wait for an initial key press: show-title v0 := key show-title loop i := tiles i += tile v0 := 6 if v0 key begin # keyboard E # wait for key release: loop if v0 key then again # we can't drop a tile overlapping # any existing lines: sprite px py 8 # erase sprite px py 8 # redraw if vf == 0 begin # drop a tile: tile := random tile-mask i := tiles i += tile sprite px py 8 end else # erase the cursor: sprite px py 8 # move cursor: v0 := 5 if v0 key then py += -1 # keyboard W v0 := 8 if v0 key then py += 1 # keyboard S v0 := 7 if v0 key then px += -1 # keyboard A v0 := 9 if v0 key then px += 1 # keyboard D # handle fuse movement without # the cursor drawn, to avoid # extreme weirdness: move-fuse # redraw cursor: i := tiles i += tile sprite px py 8 end # sync framerate loop vf := delay if vf != 0 then again vf := 6 delay := vf again : init-game clear # set up a random starting position: ex := random 15 ex += 8 ey := random 31 ey += 16 v0 := random 0b11000 i := starts i += v0 sprite ex ey 8 # initialize the cursor: tile := random tile-mask px := 1 py := 1 # reset score: timer-0 := 0 timer-1 := 0 timer-2 := 0 ; : move-fuse # don't move every single frame: timer-0 += 1 if timer-0 != fuse-speed then return timer-0 := 0 # increment score: timer-1 += 1 if timer-1 == 100 begin timer-1 := 0 timer-2 += 1 end :macro try-move SPRITE REG DELTA { i := SPRITE sprite ex ey 5 if vf != 0 begin REG += DELTA return end sprite ex ey 5 } try-move dot-n ey -1 # north try-move dot-e ex 1 # east try-move dot-s ey 1 # south try-move dot-w ex -1 # west : game-over # no trail, so we've failed! i := dot v0 := 6 # keyboard E loop sprite ex ey 5 if v0 -key then # key down again loop if v0 key then # key up again clear : show-score v3 := 37 # x position v4 := 10 # y position # draw low two digits: i := digit-buffer bcd timer-1 show-score-byte # draw high two digits: i := digit-buffer bcd timer-2 show-score-byte # wait for any key: v0 := key init-game ; : show-score-byte load v2 i := hex v2 sprite v3 v4 5 v3 += -5 i := hex v1 sprite v3 v4 5 v3 += -5 ; : show-title v0 := 52 v1 := 2 v2 := 1 i := title loop sprite v0 v1 1 v1 += 1 i += v2 if v1 != 30 then again ; : digit-buffer 0 0 0 : title 0x7F 0xFF 0xC0 0xFC 0xC0 0xC0 0x00 0xC3 0xC3 0xC3 0xFF 0x7E 0x00 0x7F 0xFF 0xC0 0xFF 0x03 0xFF 0xFE 0x00 0x7F 0xFF 0xC0 0xFC 0xC0 0xFF 0x7F : dot 0x00 0x00 0x00 0x10 0x00 : dot-n 0x00 0x00 0x10 0x00 0x00 : dot-s 0x00 0x00 0x00 0x00 0x10 : dot-e 0x00 0x00 0x00 0x08 0x00 : dot-w 0x00 0x00 0x00 0x20 0x00 : starts 0x40 0x5C 0x54 0x44 0x44 0x7C 0x00 0x00 # N 0x00 0x7F 0x40 0x4C 0x44 0x7C 0x00 0x00 # E 0x00 0x7C 0x44 0x44 0x54 0x74 0x04 0x00 # S 0x00 0x3C 0x24 0x24 0x04 0xFC 0x00 0x00 # W : tiles 0x20 0x20 0xE0 0x00 0x0F 0x08 0x08 0x08 # cross 1 0x04 0x04 0x0C 0x08 0xEF 0x20 0x20 0x20 # cross 2 0x02 0x7E 0x40 0x7E 0x02 0x7E 0x40 0x7E # zig n-s 0xC0 0x5C 0x54 0x55 0x55 0x55 0x57 0x70 # zig e-w 0x14 0x14 0x34 0xE7 0x00 0x7E 0xC3 0x00 # tee N 0x40 0x5F 0x50 0x57 0x54 0x54 0x54 0x54 # tee E 0x00 0xF0 0x1F 0xC0 0x6E 0x2A 0x2B 0x28 # tee S 0x22 0xE2 0x02 0x72 0x56 0x54 0xD4 0x14 # tee W