Hey Charles,
I found 2 scripts from QfG1. You might want to use them for reverse engineering the game's scripts.
CHARSAVE.SC
;charsave.sc Hero's Quest...save character stats.
(script# CHARSAVE)
(public
CharSave 0
)
;; Bits in svMiscEquip
(define SWORD_BIT 1)
(define CHAIN_BIT 2)
(define PICK_BIT 4)
(define TOOL_BIT 8)
(define MIRROR_BIT 16)
(define BABA_BIT 32)
(define SCORE_BIT 64)
(define EXTRA_DATA 18) ; Data items other than stats and name
(define CHECK_DATA 10) ; Data items that are in check sums
(local
;; local data for saving hero stats for next game
;;;;;;;;;;;;;;;;;;start;;;;;;;;;;;;;;;;;;
statsKey = $53 ;;;;;;;;order dependent variables;;;;;;;;
svCharType ;;;;;;;;order dependent variables;;;;;;;;
svHighGold ;;;;;;;;order dependent variables;;;;;;;;
svLowGold ;;;;;;;;order dependent variables;;;;;;;;
svScore ;;;;;;;;order dependent variables;;;;;;;;
svMiscEquip ;;;;;;;;order dependent variables;;;;;;;;
[codedStats NUMSTATS] ;;;;;;;;order dependent variables;;;;;;;;
svDaggers ;;;;;;;;order dependent variables;;;;;;;;
svHealing ;;;;;;;;order dependent variables;;;;;;;;
svMana ;;;;;;;;order dependent variables;;;;;;;;
svStamina ;;;;;;;;order dependent variables;;;;;;;;
svGhostOil ;;;;;;;;order dependent variables;;;;;;;;
bogus0 = $79 ;;;;;;;;order dependent variables;;;;;;;;
bogus1 = $86 ;;;;;;;;order dependent variables;;;;;;;;
checkSum1 ;;;;;;;;order dependent variables;;;;;;;;
checkSum2 ;;;;;;;;order dependent variables;;;;;;;;
bogus2 = $43 ;;;;;;;;order dependent variables;;;;;;;;
bogus3 = $88 ;;;;;;;;order dependent variables;;;;;;;;
bogus4 = $ad ;;;;;;;;order dependent variables;;;;;;;;
bogus5 = $f0 ;;;;;;;;order dependent variables;;;;;;;;
checkSumKey = $ce ;;;;;;;;order dependent variables;;;;;;;;
;;;;;;;;;;;;;;;;;;;end;;;;;;;;;;;;;;;;;;;
check1
check2
[YNSTR 5]
[heroFileName 16]
[bigStr 400]
hasSaved ;TRUE if hero saved
[str 40]
)
(enum ;states of saveHero Script
askSave
getInfoFileName
getInfoFileName2
openFile
writeHeroInfo
writeComplete
tryAgain
badAnswer
saveDone
)
;(procedure
; makeChar
; makeZero
; restoreHero
; convWord
; convByte
;)
;
;(procedure (makeZero &tmp whichSkill)
; (HighPrint "make Zero")
; (for ((= whichSkill 0))
; (< whichSkill NUMSTATS)
; ((++ whichSkill))
; (= [egoStats whichSkill] 0)
; )
; (= [invNum iGold] (= [invNum iSilver] (= score 0)))
; (ego use: iSword)
; (ego use: iChainMail)
; (ego use: iLockPick)
; (ego use: iThiefKit)
; (ego use: iMagicMirror)
; (Bclr fBabaFrog)
; (= [invNum iDagger] 0)
; (= [invNum iHealingPotion] 0)
; (= [invNum iManaPotion] 0)
; (= [invNum iStaminaPotion] 0)
; (= [invNum iGhostOil] 0)
; (= score 0)
; (= heroType 0)
; (StrCpy @userName {xxxxxxxxxxy})
; (for ((= whichSkill 0))
; (< whichSkill (+ NUMSTATS EXTRA_DATA))
; ((++ whichSkill))
; (= [statsKey (+ whichSkill 1)] 0)
; )
; (HighPrint "char Zeroed")
; (return)
;)
;
;(procedure (makeChar &tmp whichSkill)
; (HighPrint "make Char")
; (for ((= whichSkill 0))
; (< whichSkill NUMSTATS)
; ((++ whichSkill))
; (= [egoStats whichSkill] whichSkill)
; )
; (= [invNum iDagger] 1)
; (= [invNum iHealingPotion] 2)
; (= [invNum iManaPotion] 3)
; (= [invNum iStaminaPotion] 4)
; (= [invNum iGhostOil] 5)
; (= score 432)
; (HighPrint "Char made")
; (return)
;)
;
;(procedure (restoreHero &tmp whichSkill)
; (HighPrint "restore Hero")
; (if (not (heroinfo open: fRead))
; (HighPrint "Failure in opening file")
; (return)
; )
; (heroinfo readString: @userName 52)
; (heroinfo readString: @bigStr 90)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; (for ((= whichSkill 0))
; (< whichSkill (+ NUMSTATS EXTRA_DATA))
; ((++ whichSkill))
;
; (= [statsKey (+ whichSkill 1)] (convWord [bigStr whichSkill]))
;
; )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; (for ((= whichSkill (+ NUMSTATS EXTRA_DATA)))
; (< 0 whichSkill)
; ((-- whichSkill))
;
; (^= [statsKey whichSkill] (& [statsKey (- whichSkill 1)] 127))
;
; )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; (= check1 checkSumKey)
; (for ((= whichSkill 0))
; (< whichSkill (+ NUMSTATS CHECK_DATA))
; ((+= whichSkill 2))
; (= [statsKey (+ whichSkill 1)] (& [statsKey (+ whichSkill 1)] 127))
; (+= check1 [statsKey (+ whichSkill 1)])
; )
; (= check2 0)
; (for ((= whichSkill 1))
; (< whichSkill (+ NUMSTATS CHECK_DATA))
; ((+= whichSkill 2))
; (= [statsKey (+ whichSkill 1)] (& [statsKey (+ whichSkill 1)] 127))
; (+= check2 [statsKey (+ whichSkill 1)])
; )
; (&= check1 127)
; (&= check2 127)
; (if (or (!= check1 checkSum1) (!= check2 checkSum2))
; (HighPrint "CHECKSUM ERROR")
; )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; (for ((= whichSkill 0))
; (< whichSkill NUMSTATS)
; ((++ whichSkill))
; (= [egoStats whichSkill] [codedStats whichSkill])
; )
; (= [invNum iDagger] svDaggers)
; (= [invNum iHealingPotion] svHealing)
; (= [invNum iManaPotion] svMana)
; (= [invNum iStaminaPotion] svStamina)
; (= [invNum iGhostOil] svGhostOil)
; (= [invNum iGold] (+ (* svHighGold 100) svLowGold))
; (= score (+ svScore 128))
; (if (& svMiscEquip SCORE_BIT) (+= score 256))
; (if (& svMiscEquip SWORD_BIT) (= [invNum iSword] 1))
; (if (& svMiscEquip CHAIN_BIT) (= [invNum iChainMail] 1))
; (if (& svMiscEquip PICK_BIT) (= [invNum iLockPick] 1))
; (if (& svMiscEquip TOOL_BIT) (= [invNum iThiefKit] 1))
; (if (& svMiscEquip MIRROR_BIT) (= [invNum iMagicMirror] 1))
; (HighPrint "Hero restored")
; (return)
;)
;
;(procedure (convWord ascii)
; (return (+ (convByte (>> ascii 8)) (* (convByte (& ascii 255)) 16)))
;)
;
;(procedure (convByte ascii)
; (cond
; ((== ascii 32)
; (return 0)
; )
; ((<= 48 ascii 57)
; (return (- ascii 48))
; )
; (else
; (return (- ascii 87))
; )
; )
;)
(instance CharSave of Room
(properties
picture pBlueSkyForCarpet
horizon 0
style IRISOUT
)
(method (dispose)
(StatusLine code: dftStatusCode)
(super dispose:)
)
(method (init)
(StatusLine
code: endStatus,
enable:)
(super init: &rest)
(cSound stop:)
; don't let'm control anything!
(User canControl: FALSE, canInput: FALSE)
;; (User canControl: FALSE, canInput: TRUE)
(self setScript: saveHero)
)
; (method (handleEvent event)
; (if (Said 'quit')
; (= quit TRUE)
; )
; (if (Said 'make/zero')
; (makeZero)
; )
; (if (Said 'make/hero')
; (makeChar)
; )
; (if (and (Said 'restore/hero') hasSaved)
; (restoreHero)
; )
; )
)
(instance heroinfo of File
(properties
name {hq1_hero.sav})
)
(instance saveHero of Script
(method (changeState newState &tmp whichSkill oldGold)
(switch (= state newState)
(askSave
; (makeChar)
(Format @heroFileName "a:hq1\_hero.sav")
(if (>= score 500)
(HighPrint "CONGRATULATIONS!!__You have successfully
completed \"Hero's Quest I:__So You Want To Be
A Hero\" with the maximum possible score, 500 of 500!!_
We welcome you to the ranks of the few, the proud,
the True Heroes!")
else
(HighPrint (Format @bigStr "Congratulations!__You have
successfully completed \"Hero's Quest I:__So You
Want To Be A Hero.\"__Your final score was %d of
500 possible Puzzle Points." score))
)
(HighPrint "If you have not already done so,
we encourage you to play \"Hero's Quest I\" again
with the other two character types; many of the
puzzles are different, or have alternate solutions.")
(HighPrint "In the meantime, you are already a winner!__Please
insert a writeable disk in your floppy drive to
save your winning Hero for use in\n
\"Hero's Quest II:__Trial By Fire.\"")
(self cue:)
)
(getInfoFileName
(= cycles 2)
)
(getInfoFileName2
(if (GetInput @heroFileName 30
{Disk file in which to save your Hero.})
(heroinfo name: @heroFileName)
(= cycles 2)
else
(self changeState: tryAgain)
)
)
(openFile
(if (heroinfo open: fTrunc)
(heroinfo close:)
(= seconds 2)
else
(HighPrint (Format @bigStr "Could not create file -- %s."
(heroinfo name?)))
(self changeState: tryAgain)
)
)
(writeHeroInfo
(if (not (heroinfo open: fAppend))
(self changeState: tryAgain)
(return)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(for ((= whichSkill 0))
(< whichSkill NUMSTATS)
((++ whichSkill))
(= [codedStats whichSkill] [egoStats whichSkill])
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(= oldGold (+ [invNum iGold] (/ [invNum iSilver] 10)))
(= svCharType heroType)
(= svHighGold ( / oldGold 100))
(= svLowGold (mod oldGold 100))
(= svScore score)
(= svMiscEquip 0)
(if (ego has: iSword) (|= svMiscEquip SWORD_BIT))
(if (ego has: iChainMail) (|= svMiscEquip CHAIN_BIT))
(if (ego has: iLockPick) (|= svMiscEquip PICK_BIT))
(if (ego has: iThiefKit) (|= svMiscEquip TOOL_BIT))
(if (ego has: iMagicMirror) (|= svMiscEquip MIRROR_BIT))
(if (Btst fBabaFrog) (|= svMiscEquip BABA_BIT))
(if (< 255 score) (|= svMiscEquip SCORE_BIT))
(= svDaggers [invNum iDagger])
; (= svHealing [invNum iHealingPotion])
; (= svMana [invNum iManaPotion])
; (= svStamina [invNum iStaminaPotion])
(= svGhostOil [invNum iGhostOil])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(= checkSum1 checkSumKey)
(for ((= whichSkill 0))
(< whichSkill (+ NUMSTATS CHECK_DATA))
((+= whichSkill 2))
(= [statsKey (+ whichSkill 1)] (& [statsKey (+ whichSkill 1)] 127))
(+= checkSum1 [statsKey (+ whichSkill 1)])
)
(= checkSum2 0)
(for ((= whichSkill 1))
(< whichSkill (+ NUMSTATS CHECK_DATA))
((+= whichSkill 2))
(= [statsKey (+ whichSkill 1)] (& [statsKey (+ whichSkill 1)] 127))
(+= checkSum2 [statsKey (+ whichSkill 1)])
)
(&= checkSum1 127)
(&= checkSum2 127)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(for ((= whichSkill 0))
(< whichSkill (+ NUMSTATS EXTRA_DATA))
((++ whichSkill))
(= [statsKey (+ whichSkill 1)] (& [statsKey (+ whichSkill 1)] 127))
(^= [statsKey (+ whichSkill 1)] [statsKey whichSkill])
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(heroinfo writeString: @userName)
(heroinfo writeString: {\n})
(for ((= whichSkill 1))
( < whichSkill (+ NUMSTATS EXTRA_DATA 1))
((++ whichSkill))
(Format @bigStr "%2x" [statsKey whichSkill])
(heroinfo writeString: @bigStr)
)
(heroinfo writeString: {\n})
(heroinfo close:)
(= seconds 2)
)
(writeComplete
(HighPrint "The save character file has been created.__Save
this disk for use with \"Hero's Quest II:__Trial By Fire\"
from Sierra On-Line.")
(= hasSaved TRUE)
(= cycles 2)
)
(tryAgain
(Format @YNSTR "n")
(if (GetInput @YNSTR 2
{If you wish to try saving your character again,
type \"y\", then ENTER.__Otherwise type \"n\",
then ENTER.}
)
(if (StrCmp @YNSTR {y})
(self changeState: saveDone)
else
(= bogus0 $79)
(= bogus1 $86)
(= bogus2 $43)
(= bogus3 $88)
(= bogus4 $ad)
(= bogus5 $f0)
(self changeState: getInfoFileName)
)
else
(= cycles 2)
)
)
(badAnswer
(HighPrint "Please answer \"y\" or \"n\".")
(self changeState: tryAgain)
)
(saveDone
(HighPrint "Thank you for playing \"Hero's Quest I:__So You
Want To Be A Hero,\" and congratulations again on
winning.__We'll see you again soon in\n
\"Hero's Quest II:__Trial By Fire.\"")
(= quit TRUE)
)
)
)
)
(instance endStatus of Code
(method (doit strg)
(Format strg "___Wow!__You're Really A Hero!__[score %d of 500]" score)
)
)
MAZEBUG.SC
; MazeBug class to handle behavior of bugs in wizard's game (Mages' Mazes)
(script# MAZEBUG)
(include wizgame.sh)
(procedure
setDeltaX
setDeltaY
)
(class MazeBug kindof Actor
(properties
xStep 2
yStep 2
startX 0 ; Where to come back after dying
startY 0
deadTime 0 ; How long before we resurrect
otherBug 0 ; I.D. of opponent
form smallBug ; Which type (size) of creature
smarts 5 ; How far bug thinks/looks ahead
path 0 ; Which path we're following
)
(methods
highPri ; Switch to higher priority
lowPri ; Switch to lower priority
changeForm ; Trigger changes to next size/shape
fixState ; Set illegalBits and such based on priority/size
die ; Fall into the chasm and start game over
nearRock ; Are we close to a rock?
nearBridge ; Are we close to a bridge?
nearLadder ; Are we close to a ladder?
)
(method (init)
(super init: &rest)
(self
setPri: LowPri,
fixState:
)
)
(method (highPri)
(self
setPri: HighPri,
fixState:
)
)
(method (lowPri)
(self
setPri: LowPri,
fixState:
)
)
(method (changeForm &tmp newLoop)
(= newLoop (+ loop 1))
(if (> (++ form) largeBug)
( = form smallBug)
(-= newLoop 3)
)
(self
setLoop: newLoop,
fixState:
)
(if (and (!= form mediumBug) (== (self onControl: origin) cGREEN))
(self die:) ; Changing form while on a ladder
)
)
(method (fixState) ; Account for current creature size
(= illegalBits cWHITE)
(if (<= priority LowPri)
( |= illegalBits cYELLOW) ; On lower path
else
( |= illegalBits cLMAGENTA) ; On upper path
)
(switch form
(smallBug
( |= illegalBits cGREEN) ; Too small for ladders
( = moveSpeed (= cycleSpeed 0))
)
(mediumBug
; Too big to enter tunnels
;; ( |= illegalBits (| cMAGENTA cLMAGENTA))
( |= illegalBits cLMAGENTA)
( = moveSpeed (= cycleSpeed 1))
)
(largeBug
; Too big to enter tunnels or climb ladders (clumsy)
;; ( |= illegalBits ( | cMAGENTA cLMAGENTA cGREEN))
( |= illegalBits ( | cLMAGENTA cGREEN))
( = moveSpeed (= cycleSpeed 2))
)
)
)
(method (doit &tmp whichControl)
(cond
(deadTime
(if (not (-- deadTime)) ; Time to be resurrected
(self
posn: startX startY,
setLoop: (- loop (- form smallBug)),
form: smallBug,
lowPri:,
fixState:
)
)
)
(else
(super doit:)
)
)
)
(method (canBeHere &tmp canWe ctrls)
(if (= canWe (super canBeHere:))
(= ctrls (self onControl: 0))
(if (or
(and (& ctrls cLRED) (self nearRock: 25))
(and (& ctrls cLCYAN) (not (self nearBridge: 25)))
(and (& ctrls cGREEN) (not (self nearLadder: 25)))
)
(= canWe FALSE)
)
)
(return canWe)
)
(method (die)
(= deadTime 20) ; Disappear for 20 cycles
)
(method (nearRock dist) ; Are we close to a rock?
(return FALSE) ; Implemented in instance
)
(method (nearBridge dist) ; Are we close to a bridge?
(return TRUE) ; Implemented in instance
)
(method (nearLadder dist) ; Are we close to a ladder?
(return TRUE) ; Implemented in instance
)
)
(class MazeMove kindof Motion ; Motion class for bugs in maze
(properties
client 0 ; Actor we are controlling
caller 0 ; Object to cue when complete/blocked
x 0 ; Eventual destination
y 0
b-moveCnt 0 ; Iterations of doit to skip
curDir mazeSW ; Which way we're going (compass direction)
prevDir mazeSW ; Which way we last went (compass direction)
ditherTime 0 ; How long we should stand and dither
completed 0 ; Set to TRUE when move is complete
altMove 0 ; Kludge to make diagonal moves close to correct
prevControl 0 ; Which control color we were on last doit cycle
)
(methods
calcDir ; Calculate compass direction from angle
doMove ; Do next step of move
tryStep ; Try to take a step
chooseRoute ; Find best path for next move(s)
checkRoute ; See if specified route works
setHeading ; Set client's heading based on compass direction
)
;; Initialize mover -- do *not* do a (super init:)
(method (init actor xTo yTo toCall &tmp cy theAngle)
(if (>= argc 1) (= client actor)
(if (>= argc 2) (= x xTo)
(if (>= argc 3) (= y yTo)
(if (>= argc 4) (= caller toCall)
)
)
)
)
;Set actor's heading.
(client heading: (= theAngle (GetAngle (client x?) (client y?) x y)))
(= prevDir (= curDir (self calcDir: theAngle)))
(= b-moveCnt 0)
(if (= cy (client cycler?)) ; Keep cycler in synch with mover
(cy cycleCnt: 0)
)
)
(method (calcDir theHeading)
(return
(cond
(HEADING_N mazeN)
(HEADING_NE mazeNE)
(HEADING_E mazeE)
(HEADING_SE mazeSE)
(HEADING_S mazeS)
(HEADING_SW mazeSW)
(HEADING_W mazeW)
(HEADING_NW mazeNW)
)
)
)
;; Do next step -- do *not* do a (super doit:)
(method (doit &tmp clForm thisControl)
(if ditherTime
(-- ditherTime)
(return)
)
(if (> (++ b-moveCnt) (client moveSpeed?))
(= b-moveCnt 0)
(= clForm (client form?))
(= thisControl (client onControl: origin))
(if (and (!= thisControl prevControl) (< (client priority?) LowPri))
(client setPri: LowPri) ; (Maybe) just left a tunnel
)
(switch thisControl
(cGREY
(client lowPri:)
)
(cLBLUE
(client highPri:)
)
(cGREEN ; On a ladder -- get off quickly
(if (not (client nearLadder: 25))
(client die:) ; Somebody yanked away our ladder
)
)
(cLCYAN ; On a bridge, or where one should be
(if (not (client nearBridge: 25))
(client die:) ; Fall into the chasm
)
)
(cBROWN ; At an intersection -- choose best path
(self chooseRoute: FALSE)
)
(cLMAGENTA
(if (== (client priority?) LowPri)
(client setPri: (- LowPri 2))
)
)
(cMAGENTA
(if (== (client priority?) LowPri)
(client setPri: (- LowPri 2))
)
)
)
(= prevControl thisControl)
(self doMove:) ; Make next move (if we can)
)
;If our client is where he should be, we terminate.
(if (and (<= (Abs (- x (client x?))) 2) (<= (Abs (- y (client y?))) 2))
(self moveDone:)
(return)
)
)
; Actually do next step of motion
(method (doMove &tmp oldX oldY DX DY newDir newAngle mSpeed)
(if (== (Random 1 10) 7)
(self setHeading: (= newDir (Random 0 7))) ; Monkey wrench
)
(= oldX (client x?))
(= oldY (client y?))
(if (self tryStep: oldX oldY curDir)
(= prevDir curDir) ; Don't care about previous bump anymore
else
(self chooseRoute: TRUE) ; Blocked -- get a new route
(= mSpeed (client moveSpeed?))
(= ditherTime (+ 1 mSpeed mSpeed)) ; Dither for a bit
(client
signal: (| (client signal?) blocked),
forceUpd:
)
(return FALSE)
)
(client forceUpd:)
(return TRUE)
)
(method (tryStep oldX oldY theDir &tmp DX DY)
(= DX (client xStep?))
(= DY (client yStep?))
(if (== (++ altMove) 2)
(= altMove 0)
(if (& curDir 1) ; Moving at a diagonal
(<<= DX 1)
(<<= DY 1)
)
)
(= DX (setDeltaX theDir DX))
(= DY (setDeltaY theDir DY))
(client
x: (+ oldX DX),
y: (+ oldY DY)
)
(BaseSetter client)
(if (client canBeHere:)
(return TRUE)
else
(if (== (++ altMove) 2)
(= altMove 0)
)
(client
x: oldX,
y: oldY
)
(BaseSetter client)
(client
signal: (| (client signal?) blocked),
forceUpd:
)
(return FALSE)
)
)
(method (chooseRoute wasBlocked
&tmp theAngle newDir incr aDir sm best cur bestDir other forms dist)
(= newDir curDir)
(if (== (Random 1 3) 2)
(= theAngle (GetAngle (client x?) (client y?) x y))
(= newDir (self calcDir: theAngle))
)
(= other (client otherBug?))
(= dist (client distanceTo: other))
(if (< dist ChaseRange)
(= forms (- (client form?) (other form?)))
(cond
((== forms -1) ; Other bug wants to eat us -- run away!
(= theAngle
(GetAngle (other x?) (other y?) (client x?) (client y?)))
(= newDir (self calcDir: theAngle))
)
((and (< dist 12)
(== forms 1)
(== (client priority?) (other priority?))
)
; Yum -- we caught dinner!
(other die:)
)
; Oh, what a cute/tasty little bug -- let's chase it!
; (if merely "cute", only a 1 in 4 of chasing it)
((or (== forms 1) (and (== forms 0) (not (Random 0 3))))
(= theAngle
(GetAngle (client x?) (client y?) (other x?) (other y?)))
(= newDir (self calcDir: theAngle))
)
)
)
;; Check routes, preferring one selected above. If none of them
;; work, stick with the pre-chosen one.
;; (= sm (client smarts?))
(= bestDir newDir)
(for ((= incr (= best 0))) (<= incr 4) ((++ incr))
(= cur (self checkRoute: (= aDir (mod (+ newDir incr) 8))))
(if (== aDir (mod (+ curDir 4) 8))
(-= cur 4) ; Try not to reverse directions
)
(if (> cur best)
(= best cur)
(= bestDir aDir)
)
(= cur (self checkRoute: (= aDir (mod (- (+ newDir 8) incr) 8))))
(if (== aDir (mod (+ curDir 4) 8))
(-= cur 4) ; Try not to reverse directions
)
(if (> cur best)
(= best cur)
(= bestDir aDir)
)
)
(= newDir bestDir)
(while (and wasBlocked (== curDir newDir))
(= newDir (Random 0 7))
)
(self setHeading: newDir)
(client forceUpd:)
(return curDir)
)
;; See if endpoint of potential route is legal place for creature to be
;; (look-ahead distance determined by creature's smarts).
(method (checkRoute theDir &tmp oldX oldY curX curY sm index)
(= curX (= oldX (client x?)))
(= curY (= oldY (client y?)))
(= sm (/ (client smarts?) 2))
;; (= sm (- 11 (client smarts?))) ; Shorter looks are smarter (??)
(for ((= index 0)) (< index sm) ((++ index))
(if (not (self tryStep: curX curY theDir))
(break)
)
)
(client
x: oldX,
y: oldY
)
(BaseSetter client)
(return index)
)
(method (setHeading newHeading)
(= prevDir curDir)
(= curDir newHeading)
(client heading:
(switch newHeading
(mazeN 0)
(mazeNE 45)
(mazeE 90)
(mazeSE 135)
(mazeS 180)
(mazeSW 225)
(mazeW 270)
(mazeNW 315)
)
)
)
)
(procedure (setDeltaX theDir DX)
(switch theDir
(mazeN (= DX 0))
(mazeS (= DX 0))
(mazeSW (= DX (- DX)))
(mazeW (= DX (- DX)))
(mazeNW (= DX (- DX)))
)
(return DX)
)
(procedure (setDeltaY theDir DY)
(switch theDir
(mazeN (= DY (- DY)))
(mazeNE (= DY (- DY)))
(mazeE (= DY 0))
(mazeW (= DY 0))
(mazeNW (= DY (- DY)))
)
(return DY)
)