;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)
	)
)

