1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2026-01-22 18:15:59 +00:00

Maze game and improve random numbers

This commit is contained in:
David Schmenk
2026-01-02 14:39:51 -08:00
parent 0d4b0f9607
commit 0424867ead
3 changed files with 396 additions and 1 deletions

View File

@@ -811,7 +811,7 @@ def a2tone(duration, delay)
return 0
end
def a2rnd
*a2rndnum = (*a2rndnum << 1) + *a2rndnum + 123
*a2rndnum = ^a2rndh ^ ^a2rndl ^ (*a2rndnum << 1) + 127
return *a2rndnum & $7FFF
end
//

View File

@@ -151,6 +151,7 @@ cp samplesrc/grtest.pla prodos/bld/samples/GRTEST.PLA.TXT
cp samplesrc/dgrtest.pla prodos/bld/samples/DGRTEST.PLA.TXT
cp samplesrc/hgrtest.pla prodos/bld/samples/HGRTEST.PLA.TXT
cp samplesrc/tiletest.pla prodos/bld/samples/TILETEST.PLA.TXT
cp samplesrc/maze.pla prodos/bld/samples/MAZE.PLA.TXT
cp samplesrc/fibertest.pla prodos/bld/samples/FIBERTEST.PLA.TXT
cp samplesrc/mousetest.pla prodos/bld/samples/MOUSETEST.PLA.TXT
cp samplesrc/memtest.pla prodos/bld/samples/MEMTEST.PLA.TXT

394
src/samplesrc/maze.pla Normal file
View File

@@ -0,0 +1,394 @@
include "inc/cmdsys.plh"
include "inc/conio.plh"
include "inc/args.plh"
include "inc/hgrlib.plh"
include "inc/hgrtile.plh"
sysflags reshgr1 // Reserve HGR page 1
const rndnum = $4E // ZP location of RND
const WALL_NONE = 0
const WALL_TOP = 1
const WALL_LEFT = 2
const DIR_UP = 1
const DIR_LEFT = 2
const DIR_DOWN = 4
const DIR_RIGHT = 8
const CELL_TRACED = 16
const CELL_SOLVED = 32
const MAZE_WIDTH = 39
const MAZE_HEIGHT = 23
const PLAYER = 4*8
const CRUMB = 5*8
byte mazeTileSet = $00, $00, $00, $00, $00, $00, $00, $00 // No walls
byte = $7F, $00, $00, $00, $00, $00, $00, $00 // Top wall
byte = $03, $03, $03, $03, $03, $03, $03, $03 // Left wall
byte = $7F, $03, $03, $03, $03, $03, $03, $03 // Top & Left walls
byte = $00, $00, $10, $54, $54, $54, $10, $00 // Player
byte = $00, $00, $00, $00, $08, $00, $00, $00 // Bread crumb
word maze[] = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780
word = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8
word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0
word arg, seed, moveCnt
byte entry, exit, solved
def cellSetFlags(x, y, flags)#0
maze.[y, x] = maze.[y, x] | flags
end
def cellClearFlags(x, y, flags)#0
maze.[y, x] = maze.[y, x] & ~flags
end
def branchUp(x, y)
byte flags
if y > 0
flags = maze.[y - 1, x]
if (flags & CELL_SOLVED) or !(flags & CELL_TRACED)
cellClearFlags(x, y, WALL_TOP)
tileDraw(x, y, @mazeTileSet + 8 * (maze.[y, x] & 3))
return TRUE
fin
fin
return FALSE
end
def branchLeft(x, y)
byte flags
if x > 0
flags = maze.[y, x - 1]
if (flags & CELL_SOLVED) or !(flags & CELL_TRACED)
cellClearFlags(x, y, WALL_LEFT)
tileDraw(x, y, @mazeTileSet + 8 * (maze.[y, x] & 3))
return TRUE
fin
fin
return FALSE
end
def branchDown(x, y)
byte flags
if y < MAZE_HEIGHT-1
flags = maze.[y + 1, x]
if (flags & CELL_SOLVED) or !(flags & CELL_TRACED)
cellClearFlags(x, y + 1, WALL_TOP)
tileDraw(x, y + 1, @mazeTileSet + 8 * (maze.[y + 1, x] & 3))
return TRUE
fin
fin
return FALSE
end
def branchRight(x, y)
byte flags
if x < MAZE_WIDTH-1
flags = maze.[y, x + 1]
if (flags & CELL_SOLVED) or !(flags & CELL_TRACED)
cellClearFlags(x + 1, y, WALL_LEFT)
tileDraw(x + 1, y, @mazeTileSet + 8 * (maze.[y, x + 1] & 3))
return TRUE
fin
fin
return FALSE
end
def branchNew(x, y)
byte flags, dir, cnt
cnt = 0
dir = 1 << (conio:rnd() & 3)
repeat
when dir
is DIR_DOWN
if y < MAZE_HEIGHT-1
flags = maze.[y + 1, x]
if (flags & CELL_SOLVED) or !(flags & CELL_TRACED)
return DIR_DOWN
fin
fin
cnt++
//break
is DIR_RIGHT
if x < MAZE_WIDTH-1
flags = maze.[y, x + 1]
if (flags & CELL_SOLVED) or !(flags & CELL_TRACED)
return DIR_RIGHT
fin
fin
cnt++
//break
is DIR_UP
if y > 0
flags = maze.[y - 1, x]
if (flags & CELL_SOLVED) or !(flags & CELL_TRACED)
return DIR_UP
fin
fin
cnt++
//break
is DIR_LEFT
if x > 0
flags = maze.[y, x - 1]
if (flags & CELL_SOLVED) or !(flags & CELL_TRACED)
return DIR_LEFT
fin
fin
cnt++
//break
wend
until cnt > 3
return 0
end
def cellSolve(x, y)#0
byte flags, moveDir, searchCnt
word traceStart, traceEnd, traceBack
traceStart = heapmark
searchCnt = 0
while !(maze.[y, x] & CELL_SOLVED)
if searchCnt == 0
cellSetFlags(x, y, CELL_TRACED)
traceEnd = heapalloc(2)
*traceEnd = x | (y << 8)
moveDir = 1 << (conio:rnd() & 3)
fin
//
// Look for a possible direction to move
//
when moveDir
is DIR_UP
if branchUp(x, y)
searchCnt = 0
y--
else
searchCnt++
moveDir = DIR_RIGHT
fin
break
is DIR_LEFT
if branchLeft(x, y)
searchCnt = 0
x--
else
searchCnt++
moveDir = DIR_DOWN
fin
break
is DIR_DOWN
if branchDown(x, y)
searchCnt = 0
y++
else
searchCnt++
moveDir = DIR_LEFT
fin
break
is DIR_RIGHT
if branchRight(x, y)
searchCnt = 0
x++
else
searchCnt++
moveDir = DIR_UP
fin
break
otherwise
//
// Shouldn't happen
//
heaprelease(traceStart)
return
wend
if searchCnt > 3
//
// Dead end - back up and try new branch
//
moveDir = 0
traceBack = traceEnd + 2
repeat
traceBack = traceBack - 2
x = traceBack->0
y = traceBack->1
moveDir = branchNew(x, y)
until moveDir or traceBack == traceStart
if not moveDir
//
// Shouldn't happen
//
heaprelease(traceStart)
return
fin
fin
loop
//
// Mark all traced cells as solved
//
traceBack = traceEnd + 2
repeat
traceBack = traceBack - 2
cellSetFlags(traceBack->0, traceBack->1, CELL_SOLVED)
until traceBack == traceStart
heaprelease(traceStart)
end
def mazeGen#0
byte x, y
//cellSetFlags(MAZE_WIDTH-1, exit, CELL_SOLVED)
//cellSolve(0, entry)
cellSetFlags(0, entry, CELL_SOLVED)
cellSolve(MAZE_WIDTH-1, exit)
//for x = 0 to MAZE_WIDTH-1
for x = MAZE_WIDTH-1 downto 0
for y = 0 to MAZE_HEIGHT-1
if !(maze.[y, x] & CELL_SOLVED)
cellSolve(x, y)
fin
next
next
//
// Clear all flags used to generate
//
for x = 0 to MAZE_WIDTH-1
for y = 0 to MAZE_HEIGHT-1
cellClearFlags(x, y, CELL_SOLVED | CELL_TRACED)
next
next
end
def mazeInit#0
byte y
for y = 0 to MAZE_HEIGHT-1
memset(maze[y], $0303, MAZE_WIDTH)
maze.[y, MAZE_WIDTH] = WALL_LEFT
next
memset(maze[MAZE_HEIGHT], $0101, MAZE_WIDTH)
maze.[MAZE_HEIGHT, MAZE_WIDTH] = 0
entry = conio:rnd() % MAZE_HEIGHT
exit = conio:rnd() % MAZE_HEIGHT
maze.[entry, 0] = WALL_TOP
maze.[exit, MAZE_WIDTH] = WALL_TOP
if exit < MAZE_HEIGHT
maze.[exit + 1, MAZE_WIDTH] = WALL_TOP|WALL_LEFT
else
maze.[exit + 1, MAZE_WIDTH] = WALL_TOP
fin
end
def moveUp(x, y)
return !(maze.[y, x] & WALL_TOP)
end
def moveLeft(x, y)
return !(maze.[y, x] & WALL_LEFT)
end
def moveDown(x, y)
return !(maze.[y + 1, x] & WALL_TOP)
end
def moveRight(x, y)
return !(maze.[y, x + 1] & WALL_LEFT)
end
def mazePlay
byte x, y, quit, pulse
x = 0
y = entry
while TRUE
tileXorDraw(x, y, @mazeTileSet + PLAYER)
while !conio:keypressed(); loop
tileXorDraw(x, y, @mazeTileSet + PLAYER)
when toupper(conio:getkey() & $7F)
is 'I'
if !(maze.[y, x] & WALL_TOP)
tileOrDraw(x, y, @mazeTileSet + CRUMB)
y--
moveCnt++
fin
break
is 'M'
if !(maze.[y + 1, x] & WALL_TOP)
tileOrDraw(x, y, @mazeTileSet + CRUMB)
y++
moveCnt++
fin
break
is 'J'
if !(maze.[y, x] & WALL_LEFT)
tileOrDraw(x, y, @mazeTileSet + CRUMB)
x--
moveCnt++
fin
break
is 'K'
if !(maze.[y, x + 1] & WALL_LEFT)
tileOrDraw(x, y, @mazeTileSet + CRUMB)
x++
moveCnt++
if x == MAZE_WIDTH; return TRUE; fin // Solved!
fin
break
is 'Q'
return FALSE
wend
loop
end
def atoi(strptr)#1
var num, len, sign
sign = 1
num = 0
len = ^strptr
strptr++
if ^strptr == '-'
sign = -1
strptr++
len--
elsif ^strptr == '+'
strptr++
len--
fin
while len and ^strptr >= '0' and ^strptr <= '9'
num = num * 10 + ^strptr - '0'
strptr++
len--
loop
return num * sign
end
arg = argNext(argFirst)
if ^arg
*rndnum = atoi(arg)
else
puts("Press a key to generate the maze...")
while not conio:keypressed()
conio:rnd()
loop
getc
fin
seed = *rndnum
hgrMode(hgrPage1)
tileDrawBuf(hgrPage1)
mazeInit
tileFromText(0, @mazeTileSet)
mazeGen
solved = mazePlay
hgrMode(hgrOff)
if solved
puts("Solved!\n")
fin
puts("Seed = "); puti(seed); putln
puts("Moves = "); puti(moveCnt); putln
done