COLS ROWS * constant dngsize
0 0 COLS 1- ROWS 1- rect update-rect
0 value |update-points|
200 constant |update-points-max|
\ create update-points 2 |update-points-max| * allot
here value update-points ( -- adr )
: update-point[] ( n -- pointx pointy )
2* update-points + dup 1+ ;
\ (dungeon) is initialized in runtime by allot-dungeon
\ static version is simply:
\ create (dungeon) dngsize allot
\ but we want to reduce the binary image size, so:
here value (dungeon) ( -- adr )
: allot-dungeon ( -- )
here to (dungeon) dngsize allot
here to update-points 2 |update-points-max| * allot
;
: dcell ( i -- a )
(dungeon) + ;
: dcell! ( val idx -- )
dcell c! ;
: dcell@ ( idx -- val )
dcell c@ ;
: dcell-make-visible
dup dcell@ c-make-visible swap dcell! ;
: dcell-visible?
dcell c@ c-visible? ;
: dcellyx ( x y -- ofs )
[COLS*] + ;
: dcellyx! ( value x y -- )
[COLS*] + dcell! ;
: dcellyx@ ( x y -- val )
[COLS*] + (dungeon) + c@ ;
( paint a cell at x,y visible )
: dcellyx-make-visible ( x y -- )
[COLS*] + dup dcell@ c-make-visible swap dcell! ;
( paint a cell @ptr visible )
: visible! ( char-ptr -- )
dup c@ c-make-visible swap c! ;
: dclear ( val -- )
(dungeon) dngsize rot fill ;
: make-all-visible ( -- )
dngsize 0 do i dcell-make-visible loop ;
( set thing or monster presence flag )
: dset-thing ( x y -- )
dcellyx dcell dup c@
[ B-THING ] literal or swap c! ;
: dreset-thing ( x y -- )
dcellyx dcell dup c@
[ B-THING invert ] literal and swap c! ;
: dset-monster ( x y -- )
dcellyx dcell dup c@
[ B-MONSTER ] literal or swap c! ;
: dset-monster- ( x y -- newvalue )
dcellyx dcell dup c@
[ B-MONSTER ] literal or dup -rot swap c! ;
: dreset-monster ( x y -- )
dcellyx dcell dup c@
[ B-MONSTER invert ] literal and swap c! ;
: c-skip?
dup [ NOTHING ] literal = swap
c-visible? not or ;
\ apply xt ( ptr -- ) to width elements at ptr
: apply-span ( xt width ptr -- )
swap 0 do
( xt ptr -- )
2dup swap execute
1+
loop
2drop ;
\ fill width elements at ptr with val
: dfillln ( val width ptr -- )
-rot swap fill ;
: dfillcol ( val height ptr -- )
swap 0 do
2dup c! COLS+
loop 2drop ;
: dfillrect ( val r1 -- )
dup rect-topleft dcellyx (dungeon) + swap ( v & r1 -- )
dup rect-height 1+ swap rect-width 1+ ( v & h w -- )
-rot ( v w & h -- )
0 do
3dup dfillln ( v w & )
COLS+
loop
3drop ;
: dfill-visible ( x1 y1 x2 y2 -- )
( vertical bounds to r )
1+ rot 2>R
( calc start pointer y1 * COLS + x1 )
1+ over - swap ( w x1 -- )
2R@ nip COLS* + dcell ( w ptr -- )
2R> do
2dup ( w ptr w ptr -- )
['] visible! -rot apply-span
COLS+
loop
2drop ;
: dlineh ( char x1 y1 x2 -- )
rot swap ( char y1 x1 x2 -- )
2dup > if swap then
over - 1- ( char y1 x1 w -- )
dup 0> if
swap rot ( char w x1 y1 -- )
COLS* + (dungeon) + 1+ dfillln
else
2drop 2drop
then ;
: dlinev ( char x1 y1 y2 -- )
2dup > if swap then
over - 1- ( char x1 y1 h -- )
dup 0> if
rot 1- rot 1+ COLS* +
(dungeon) + 1+ ( char w ptr )
dfillcol
else
2drop 2drop
then ;
: invalidate ( x1 y1 x2 y2 -- )
norm4 update-rect rect-add ;
: invalidate-all ( -- )
0 0 COLS 1- ROWS 1- invalidate
0 to |update-points| ;
: validate-all ( -- )
COLS ROWS 0 0 update-rect rect!
0 to |update-points| ;
: (ntu-rect?)
[ COLS ROWS ] literal literal 0 0 update-rect rect-eq? ;
: (0=up-pts)
|update-points| 0= ;
: nothing-to-update?
(ntu-rect?) (0=up-pts) and ;
: dupd-pt ( x y -- )
2dup dcellyx@ dup c-visible? if
dup (?stuff) if
drop 2dup char@xy
else
bits2print
then
-rot vtxy emit
else
drop 2drop
then ;
: dupdate-points ( -- )
(0=up-pts) if exit then
|update-points| 0 do
i update-point[] p-xy@ ( -- x y )
2dup update-rect xy-in-r? not if
dupd-pt
else
2drop
then
loop ;
: (updaterect-row-increment) ( -- increment )
COLS update-rect }rx2@ update-rect }rx1@ - 1+ - ;
: dupdate-invalid ( -- )
nothing-to-update? if exit then
dupdate-points
(updaterect-row-increment)
0 (dungeon) ( inc nspaces dungeon -- )
update-rect rect-topleft dcellyx + ( + start adr )
update-rect }ry2@ 1+ update-rect }ry1@ do
nip 0 swap ( nspaces = 0 )
update-rect }rx1@ i vtxy
update-rect }rx2@ 1+ update-rect }rx1@ do
dup c@ ( inc nsp dng c )
( inc nsp dng c )
dup c-skip? if ( inc nspaces &dng -- )
drop
swap 1+ swap
else
( inc nsp dng c )
rot if
i j vtxy
then
0 -rot ( nspaces = 0 )
dup (?stuff) if
drop i j char@xy
else
bits2print
then
emit
then
1+ ( inc nspaces &++dng -- )
loop
2 pick +
loop 3drop
validate-all ;
: dprint ( -- )
(dungeon)
ROWS 0 do
COLS 0 do
dup c@ bits2print emit 1+
loop
cr
loop drop ;
( invalidate a single location )
: invalidate1 ( x1 y1 -- )
|update-points| update-point[] p-xy!
|update-points| 1+ to |update-points|
|update-points| |update-points-max| = if
\ abort" invalidate1 overflow"
dupdate-invalid
then ;