I am writing a program to generate characters for a role-playing game (Avalon-Hill/Chaosium RuneQuest 3e from the 1980's. Real old school.). The main routine and all subroutines written so far worked to spec, so I moved them all into a project subdirectory, { HOME XGEN }.
Now suddenly there is a problem: in the $$ATTRS routine, which sets up the values for an INFORM dialog box in ATTRS, the system reports an error 'Undefined local name' on encountering GHP. The thing is, GHP is already defined with a dummy value in the global scope, and the name is not lower-case, nor does it have a back-arrow prefix.
It is referenced inside a local-variable structure, and the calculation of GHP involves two of those compiled local variables, but I doubt that is the problem.
Any ideas on what I'm doing wrong would be really appreciated.
Complete listing follows.
Code:
HPHP48-W,*°Â
@ RcDarwin (c) 2022
@ XGEN2 - main routine
@
«
INI$LOG
LOAD$$
"->X XGEN" LOGGIT
CLFX
DO
SP$PICK
UNTIL 1 ==
END
@ spcode on stack is DW$$ | EL$$ | HU$$ | etc, unquoted hence evaluated
BUMPX
ADJX
EDITX @ returns a list of ten items
DUP 'CHRXCX' STO
OBJ→ DROP
→
←str ←con ←siz ←int ←pow ←dex ←app ←mov ←age ←gnr
«
ATTRS
'CHRXAT' STO
SCMS
'CHRXSC' STO
PR$EXP
'CHRXPE' STO
»
"X-> XGEN" LOGGIT
LOG$S @ show the log
»
'XGEN2' STO
@ ENUM - basic enum(), doesn't re-base like 'enum(a, b, c=10)' in C
«
→ lsx @ make sure that lsx is a list!
« 1 lsx SIZE FOR i
i
lsx i GET
STO
NEXT
»
»
'ENUM' STO
@ INI$LOG - really basic logger routine
@ \ ---
«
{}
DATE + TIME +
LOGGIT
»
'INI$LOG' STO
@ LOGGIT -- append string to log
@ \ str ----
«
LOG$S SWAP +
'LOG$S' STO
»
'LOGGIT' STO
@ LOAD$$ - load the main data structures.
@ \ ---
«
" ->X LOAD$$" LOGGIT
{ 'STR' 'C0N' 'SIZ' 'INT' 'POW' 'DEX' 'APP' 'MOV' 'age' 'gnr' }
'XN' STO
XN ENUM
{ 'DW' 'EL' 'HU' 'TR' 'AR' 'AN' 'BR' 'CE' 'DU' 'EF' 'GO' 'HA' 'NA' 'OG' 'RC' 'PA' }
'SP' STO
SP ENUM
{ 'DW$$' 'EL$$' 'HU$$' 'TR$$' 'ms$$' 'AR$$' 'AN$$' 'BR$$' 'CE$$' 'DU$$' 'EF$$' 'GO$$' 'HA$$' 'NA$$' 'OG$$' 'RC$$' 'PA$$' }
'SP$$' STO
{ 'Dwarf' 'Elf' 'Human' 'Troll' '$ms$' 'Aardvark' 'Anemid' 'Broo' 'Centaur' 'Duck' 'Eftling' 'Goblin' 'Halfling' 'Nachaak' 'Ogre' 'Orc' 'Pandry' }
'SP$NOM' STO
SP$NOM SP$$ « 2 →LIST » DOLIST 'ZIP$2SP' STO
{ {'n'} {'h'} {'m' 'f'} {'m' 'f' 'a'} {'j' 'b' 'e'} { m a } }
'GNRA' STO
{}
'CHRXCX' STO
{}
'CHRXAT' STO
{}
'CHRXSC' STO.
{}
'CHRXPE' STO
0 'GHP' STO
0 'MP' STO
0 'FTG' STO
"" 'D$A' STO
(0,0) 'D$S' STO
0 'A$G' STO
" X-> LOAD$$" LOGGIT
»
'LOAD$$' STO
@ CLFX - clear user flags 1-7 for use by XX$$ routines and BUMPX
«
" ->X CLFX" LOGGIT
1 7 FOR i
i CF
NEXT
" X-> CLFX" LOGGIT
»
'CLFX' STO
@ SP$PICK - choose "Species" from box, return 'SP$$' from sublist
«
" ->X SP$PICK" LOGGIT
"PICK SPECIES"
@ {{"Dwarf" 'DW$$'}{"Elf" 'EL$$'}{"Human" 'HU$$'}{"Troll" 'TR$$'}
{ }{"Aardvark" 'AR$$'}{"Anemid" 'AN$$'}{"Centaur" 'CE$$'}
{"Duck" 'DU$$'}{"Eftling" 'EF$$'}{"Goblin" 'GO$$'}{"Halfling" 'HA$$'}
{"Nachaak" 'NA$$'}{"Ogre" 'OG$$'}{"Orc " 'RC$$'}{"Pandry" 'PA$$'}} @
ZIP$2SP @ list of fields
3 @ Human by default
CHOOSE
" X-> SP$PICK" LOGGIT
»
'SP$PICK' STO
@ GNR$GET - determine gender of this chrx
«
" ->X GNR$GET" LOGGIT
'GNRA' SWAP @ using stack-top as index,
GET @ get one sublist, eg., {'m' 'f'}
"Pick "
SPNAME
" Gender"
+ + @ title
SWAP @ set up the available genders
1
CHOOSE @ pick one
DROP @ just the char value, not the OK flag
" X-> GNR$GET" LOGGIT
»
'GNR$GET' STO
@ BUMPX - average values in CHRXCX are 'low-side' integers, eg 10
@ if flag i is set, add 1 half the time, simulating eg 10.5 as average on 3D6
«
" ->X BUMPX" LOGGIT
1 7 FOR i
IF i FS? RAND 0.5 >= AND
THEN CHRXCX i GET
1 +
CHRXCX i ROT
PUT
END
NEXT
" X-> BUMPX" LOGGIT
»
'BUMPX' STO
@ ADJX - adjust each charax by 2D4-4
«
" ->X ADJX" LOGGIT
1 7 FOR i
CHRXCX i GET
4 DIE
4 DIE +
4 -
+
CHRXCX i ROT
PUT
NEXT
" X-> ADJX" c LOGGIT
»
'ADJX' STO
@ $$EDITX - parameters for EDITX INFORM
{
"EDIT CHARAX"
@ fields: 0 -> real , 1 -> complex, 2 -> string, 13 -> unit_type
{{"STR:" "" 0}{"CON:" "" 0}{"SIZ:" "" 0}
{"INT:" "" 0}{"POW:" "" 0}{"DEX:" "" 0}
{"APP:" "" 0}{"MOV:" "ms" 13}{}
{"age:" "yr" 0}{} {"gnr:" "m,f,..." }}
@ 3 columns, 4 tab stops between fields
{3 4}
@ no reset values
{}
@ the changeable recipient
'CHRXCX' EVAL
}
'$$EDITX' STO
@ EDITX - edit and show charax values
«
" ->X EDITX" LOGGIT
DO
@ set up the input form's levels:
$$EDITX
OBJ→ DROP
EVAL
INFORM @ show the input form, get value list on L2, 1|0 on L1
IF 1 ==
THEN
1
ELSE]
0
END
UNTIL 1 ==
END
" X-> EDITX" LOGGIT
»
'EDITX' STO
@
@ Second big section
@
@ AGE$GET - get current age of chrx, calc prev.exp. years, return as 2-tuple
«
" ->X AGE$GET" LOGGIT
CLLCD
"Current Age (xx): "
PROMPT DUP
'CURR$AGE' STO
CHRXCX 9 GET 2DUP -
'PREV$EXP' STO
SWAP DROP
PREV$EXP
R→C @ -- (C,P)
" X-> AGE$GET" LOGGIT
»
'AGE$GET' STO
@ $$ATTRS - parameters for ATTRS
«
{ } 'CHRXAT' STO
@ gHP
←con ←siz + 2 / CEIL
'GHP' STO
@ mp
←pow
'MP' STO
@ Ftg
←str ←con +
'FTG' STO
@ Dmg Adj
DMG$ADJ
'D$A' STO
@ SR
DO$SR
'D$S' STO
@ age
AGE$GET
'A$G' STO
{ GHP MP FTG D$A D$S A$G }
'CHRXAT' STO
@ here is the five-level parameterset for INFORM
{
@ title
"ATTRIBUTES"
@ field specs
{{" gHP:" "" 0}{" mp:" "" 0}{" Ftg:" "" 0}
{"DmgA:" "" 0}{" SR:" "Fdex ,Tot" 1}{ }{" age:" "22" 0}{ }}
@ format
{ 2 4}
@ defaults
{ }
}
@ add in the initial values ←→
'CHRXAT' EVAL EVAL 6 →LIST 1 →LIST
+
»
'$$ATTRS' STO
@ ATTRS - show the values for Attributes: gHP, mp, Fatigue,...
«
" ->X ATTRS" LOGGIT
@ we want this to just show not edit
$$ATTRS
OBJ→ DROP
INFORM DROP
" X-> ATTRS" LOGGIT
»
'ATTRS' STO
@ DMG$ADJ - calculate Damage Adjustment
«
" ->X DMG$ADJ" LOGGIT
'←str+←siz-1' EVAL
DUP
32 SWAP
IF <
THEN
12 / IP
$D4 EVAL
ELSE
24 -
16 / IP
1 +
$D6 EVAL
END
" X-> DMG$ADJ" LOGGIT
»
'DMG$ADJ' STO
@ $D4 - calculate D4-sized value of Damage Adjustment
«
" ->X $D4" LOGGIT
←x
« CASE
'←x == 0' THEN "-" END
'←x == 1' THEN "0]" END
'←x == 2' THEN "+" END
" "
END
"D4"
+
»
" X-> $D4" LOGGIT
»
'$D4' STO
@ $D6 - calculate D6-sized value of Damage Adjustment
«
" ->X $D6" LOGGIT
48 +
CHR
"D6"
+
" X-> $D6" LOGGIT
»
'$D6' STO
@ DO$SR - calculate sr
«
" ->X DO$SR" + LOGGIT
5 ←dex $SR
4 ←siz $SR
0 MAX @ -- DX SZ|0
OVER @ -- DX SZ|0 DX
+
R→C @ DX,Tot -> (DX,Tot)
" X-> DO$SR" LOGGIT
»
'DO$SR' STO
@ $SR - calculate one term of SR
«
" ->X $SR" LOGGIT
→
←spx
«
CASE
←spx 10 < THEN 1 - END
←spx 16 < THEN 2 - END
←spx 20 < THEN 3 - END
←spx 23 < THEN 4 - END
0
END
»
" X-> $SR" LOGGIT
»
'$SR' STO
@ $$SCMS - parameters for INFORM in SCMS
«
←dex PRIM ←str SECN + ←siz PRIM -
'AGL' STO
←int PRIM ←pow SECN + ←app SECN +
'C0M' STO
←int PRIM
'KNO' STO
←int PRIM ←dex PRIM + ←pow SECN +
'MAN' STO
←int PRIM ←pow SECN + ←con SECN +
'PER' STO
←dex PRIM ←siz PRIM - ←pow PRIM -
'STL' STO
←int PRIM ←pow PRIM + ←dex SECN +
'MGK' STO
←int PRIM ←dex SECN +
'TEK' STO
{
@ title
"SCMs"
@ field specs
{{"Agl" "" 0}{"Com" "" 0}{"Kno" "" 0}
{"Man" "" 0}{"Per" "" 0}{"Stl" "" 0}{"Mgk" "" 0}{"Tek" "" 0}{}}
@ format
{ 2 4 }
@ initial
{}
@defaults
{ AGL C0M KNO MAN PER STL MGK TEK } EVAL EVAL 8 →LIST 1 →LIST
}
»
'$$SCMS' STO
@ SCMS - show values for SCMS: Agl, Com, etc.
«
@ again, we just want to show, not edit
" ->X SCMS" LOGGIT
'$$SCMS'
OBJ→ DROP
INFORM DROP @ get rid of Boolean in Level 1
" X-> SCMS" LOGGIT
»
'SCMS' STO
@
@ Third big section
@
@ PR$EXP - calculate previous experience: a big task!!!
«
" ->X PR$EXP" LOGGIT
CLLCD
"Under construction"
MSGBOX
{
SPNAME ←gnr Vrty "OCC_BACK" CURR$AGE
"Skills"
"Agl" [ B C D J Rb S Th ]
"Com" [ FA O S ]
"Kno" { "Lor" [ A S M P W ]
"Dsc" [ E FA MA Sh TD TW ]
"Cra"[ A B C ] }
"Man" [ C D Pi S ]
"Per" [ L VC VE S T Tr ]
"Stl" [ H S T ]
"Mgk" { "Rit" [ C E S ]
"Sor" [ I D R M ] }
"Tek" [ A B C D E F ]
"Languages" { "own" [spk lit]
"other1" [spk lit] }
"Magic" {
"primitive" {}
"Divine" {}
"Sorcery" {} }
"Gear" {armour {}
weapons {}
other {} }
} EVAL
" X-> PR$EXP" LOGGIT
»
'PR$EXP' STO
@
@ Low-level routines
@
@ PRIM - return primary value (x - 10)
«
10 -
»
'PRIM' STO
@ SECN - return secondary value, fn(prim(x))
«
PRIM DUP
2 /
ABS 0.5 + IP
SWAP
SIGN *
10 MIN
»
'SECN' STO
@DIE - given n, return i | i in 1{..n}
«
RAND *
1 + IP
»
'DIE' STO
@
@ Fourth
big section
@
@ 2019-08-21 15:24
@ DW$$ - parameters for Dwarf
«
"DWARF" 'SPNAME' STO
{ 14 15 7 13 10 10 10 '2_ms' 12 }
3 GNR$GET
+
'CHRXCX' STO
{ 2 5 6 7 } « SF » DOLIST
»
'DW$$' STO
@ EL$$ - parameters for Elf
«
"ELF" 'SPNAME' STO
{ 9 10 9 16 13 13 10 '4_ms' 20}
3 GNR$GET
+
'CHRXCX' STO
{ 2 4 6 7 } « SF » DOLIST
»
'EL$$' STO
@ HU$$ - parameters for Human
«
"HUMAN" 'SPNAME' STO
{ 10 10 13 13 10 10 10 '3_ms' '15' m }
4 GNR$GET
+
'CHRXCX' STO
{ 1 2 5 6 7 } « SF » DOLIST
»
'HU$$' STO
@ TR$$ - parameters for Troll
«
"TROLL" 'SPNAME' STO
{ 16 10 18 13 10 10 10 '3_ms' '15' }
3 GNR$GET
+
'CHRXCX' STO
{ 1 2 3 5 6 7 } « SF » DOLIST
»
'TR$$' STO
@ --------- minor species ---------
@ AR$$ - parameters for Aardvark (why not?)
«
"AARDVARK" 'SPNAME' STO
{14 12 5 13 10 10 7 '2_ms' 15 }
3 GNR$GET
+
'CHRXCX' STO
{ 1 2 5 6 } « SF » DOLIST
»
'AR$$' STO
@ AN$$ - parameters for Anemid (winged humanoids)
«
"ANEMID" 'SPNAME' STO
{7 10. 7 13 13 17 10. '2.9_ms' 15 }
3 GNR$GET
+
'CHRXCX' STO
{ 2 7 } « SF » DOLIST
»
'AN$$' STO
@ BR$$ - parameters for Broo (nasty chaotic brutes)
«
"BROO" 'SPNAME' STO
{13 15 15 13 10 10 7 '4_ms' 15 }
3 GNR$GET
+
'CHRXCX' STO
{ 2 3 5 6 } « SF » DOLIST
»
'BR$$' STO
@ CE$$ - parameters for Centaur
«
"CENTAUR" 'SPNAME' STO
{16 10 15 13 10 13 10 '10_ms' 15 }
3 GNR$GET
+
'CHRXCX' STO
{ 1 2 4 5 6 7} « SF » DOLIST
»
'CE$$' STO
@ DU$$ - parameters for Duck
«
"DUCK" 'SPNAME' STO
{8 13 5 13 10 13 7 '2_ms' 15 }
3 GNR$GET
+
'CHRXCX' STO
{ 3 5 } « SF » DOLIST
»
'DU$$' STO
@ EF$$ - parameters for Eftling (amphibian folk)
«
"EFTLING" 'SPNAME' STO
{10 10 7 13 10 13 10 '2_ms' 3 }
3 GNR$GET
+
'CHRXCX' STO
{ 1 2 5 7 } « SF » DOLIST
»
'EF$$' STO
@ GO$$ - parameters for Goblin
«
"GOBLIN" 'SPNAME' STO
{14 10 7 9 8 13 10 '2_ms' 15 }
3 GNR$GET
+
'CHRXCX' STO
{ 2 7 } « SF » DOLIST
»
'GO$$' STO
@ HA$$ - parameters for Halfling
«
"HALFLING" 'SPNAME' STO
{7 19 4 13 10 17 10 '2_ms' 15 }
3 GNR$GET
+
'CHRXCX' STO
{ 7 } « SF » DOLIST
»
'HA$$' STO
@ NA$$ - parameters for Nachaak (badger folk)
«
"NACHAAK" 'SPNAME' STO
{7 10 5 13 13 14 7 '3_ms' 13 }
3 GNR$GET
+
'CHRXCX' STO
{ 2 } « SF » DOLIST
»
'NA$$' STO
@ OG$$ - parameters for Ogre
«
"OGRE" 'SPNAME' STO
{19 13 13 13 13 10 13 '3_ms' 15 }
3 GNR$GET
+
'CHRXCX' STO
{ 6 7 } « SF » DOLIST
»
'OG$$' STO
@ RC$$ - parameters for Orc
«
"ORC" 'SPNAME' STO
{14 10 9 13 10 14 7 '3_ms' 15 }
3 GNR$GET
+
'CHRXCX' STO
{ 2 4 } « SF » DOLIST
»
'RC$$' STO
@ PA$$ - parameters for Pandry (hermaphroditic cyborgs)
«
"PANDRY" 'SPNAME' STO
{12 13 11 15 10 13 13 '4_ms' 13 }
2 GNR$GET
+
'CHRXCX' STO
{ 3 6 7 } « SF » DOLIST
»
'PA$$' STO