 SMALL ADVENTURE BUILDER / RUNNER / TOOLS
 (c) Jim Grimwood 2005 - jg27paw4@globalnet.co.uk
 inspired by "Assault of the Ogroids" by Gary Chalk from Sinclair User, May 1987


 "Assault of the Ogroids" was a random event adventure table-top game
 published in Sinclair User magazine, together with a small type-in
 listing for an accompanying player's aid utility. The original program,
 map and text are in the Sinclair User section at The Type Fantastic:
 http://www.users.globalnet.co.uk/~jg27paw4/type-ins/typehome.htm
 The simple computer-moderation program printed in the magazine still
 left the player needing to keep a paper record of various actions and
 allowed them to cheat fairly easily, so I decided to write a fully
 automated version where the computer recorded and controlled everything
 and the player only needed to make decisions on what to do next.
 Rather than just copy the listed game I wrote a general utility which
 allows any game of that type to be written, which became the three
 Small Adventure programs as described below. As I rewrote the text of
 the Ogroids game when setting up the data files for this particular
 game, I renamed it "Attack of the Ogres".
 I hope that the programs might provide a little entertainment. Please
 send any bug reports or suggestions for improvements to me at the
 email address above. The Small Adventure files are on the Spot's Pourri
 page at Your Spectrum Unofficial Archive:
 http://www.users.globalnet.co.uk/~jg27paw4/
 

 FILES
 =====
 SAB.TXT       Small Adventure Builder/Runner/Tools documentation
 SAD.TAP       Small Adventure data files for "Attack of the Ogres"
 SAD.TXT       print-out of "Attack of the Ogres" data files
 TRAP.ASM      error trap assembler listing in plain text format
 UPDATE.ASM    other assembler listings in plain text format
 UPDATE.TAP    m/code & assembler listings in OCP's Editor/Assembler format


 RECORD DEFINITIONS
 ==================
 (in entry order)
 
 One-byte negative numbers are held as (ABS value + 128).
 Two-byte numbers are stored in the usual way (low+256*high).
 CS = combat skill; HS = hit strength
 Fields marked (calc) may not be entered directly.
 Fields marked (text) are free text.
 
 T$ - Terrain - size (Ts,12)
 ---------------------------
 Array position indicates associated UDG (1=A, 2=B, etc.)
 1     "0"-"3"  time cost in days
 2     "0"-"3"  attrition unit cost
 3-11  (text)   terrain name
 12    (calc)   attribute setting (flash*128 + bright*64 + paper*8 + ink)
 
 W$ - Weapons - size (Ws,Wc)
 ----------------------------
 For the two "special enhancement" entries, the value may be entered as
 the variable name 'fcs' or 'fhs', which is held as the associated UDG
 value (158=O, 159=P), indicating that after victory in combat (and if
 the enhancement condition is true) the defeated foe's CS or HS is added
 to the player's basic attribute (vampiric).
 1     0-20     basic CS enhancement
 2     0-20     basic HS enhancement
 3     0-99     special CS enhancement (99=invincible)
 4     0-99     special HS enhancement (99=deadly)
 5     0-99     special enhancement duration (99=continuous while held)
 6     (calc)   start pointer for basic CS condition string (NOT USED)
 7     (calc)   start pointer for basic HS condition string (NOT USED)
 8     (calc)   start pointer for special CS condition string
 9     (calc)   start pointer for special HS condition string
 10    (calc)   end of conditions pointer
 11-24 (text)   weapon name
 25-Wc          space for enhancement condition strings (BASIC syntax)
 
 P$ - PouchItems - size (Ps,21)
 ------------------------------
 The "Use?" flag indicates if the item may be used by the "pouch"
 command line option (eg. drinking a potion) as opposed to being
 triggered by an event.
 1     1-99     maximum quantity which may be carried
 2     "?"-"Z"  identifying code letter (?=lodestone, @=gold, otherwise A-Z)
                If the item is one which protects against a particular
                type of foe, then the item's code letter in P$
                should match the foe's code letter in F$.
 3     "Y","N"  Use?
 4     0-9      CS enhancement
 5     0-9      HS enhancement
 6-21  (text)   item name
 
 F$ - Foes - size (Fs,20)
 ------------------------
 1     "[AGHMO]"identifying code letter
 2     1-99     combat skill
 3     1-99     hit strength
 4     1-9      number of foes (+128 if "Strikes 1st?" = "Y")
 5-20  (text)   foe description
 
 M$ - Map - size (Ms+1,Mc)
 -------------------------
 Rows 1 - Ms are simply strings of UDGs defining the map.
 Row Ms+1 is used as follows:
 1     (number) time limit in days (range Ms+5 to Ms*2+5)
 2     1-Ms     start location row
 3     1-Mc     start location column
 4     1-Ms     finish location row
 5     1-Mc     finish location column
 
 N$ - Narrative - size (Ns)
 ------------------------------
 The first byte holds the maximum number of narrative entries allowed
 (1-98), which should match Es. The next Es*2+2 bytes hold two-byte
 pointers for each of the following narrative entries (thus the first
 narrative entry starts at Es*2+4). The extra value at the end marks
 the pointer for the end of all text.
 
 E$ - Events - size (Es+1,16)
 ----------------------------
 Bytes (2 TO Ts+1) of row Es+1 are used to hold the row numbers of the
 first E$ entry for each terrain type (to speed up searching - the
 first byte of row Es+1 = "z").
 Each terrain type has a number of primary entries defining events
 which occur depending on a random range within 1-100. These are
 identified by having the "primary segment code" = "@".
 Each primary entry may be linked to a secondary entry defining a
 related group of events which might occur subsequent to the primary
 event. The existence of a link is indicated in the primary entry by
 "secondary segment code" <> "@" (ie. "A"-"I"). The entries for the linked
 secondary group are identified by having their "primary segment code"
 = "secondary segment code" value from the primary entry.
 If a primary entry has a secondary entry link then fields 6-16 are not
 used in the primary entry.
 The format for the rows in the main part of E$ is as follows:
 1     "1"-Ts   Terrain pointer (T$)
 2     "@"-"I"  Primary segment code
 3     1-100    Upper limit for random selection
 4     1-Es     Narrative pointer (N$)
 5     "@"-"I"  Secondary segment code ("@"=none)
 6     0-100    Chance % to flee encounter
 7     -99-+99  CS modifier
 8     -99-+99  HS modifier
 9     -9-+9    Time modifier
 10    "Y","N"  Make a random move after the event?
 11    0-20     Item cost in GP
 12    -1-+Ws   Weapon pointer found (W$); -1 = lose weapon; 127 = find any
 13    -1-+Ps   PouchItem pointer found (P$); -1 = lose item
 14    0-20     PouchItem quantity
 15    0-As     Assistance pointer (A$)
 16    0-Fs     Foe pointer (F$)
 
 A$ - Assistance - size (As,15)
 ------------------------------
 1     1-99     Minimum distance
 2     1-99     Maximum distance
 3     0-Ts     Terrain number restriction (0=no restriction)
 4     "Y","N"  Optional?
 5     0-9      Time elapsed per league (or +128 if in total)
 6-14  "0","1"  A string of "0"s and "1"s indicating allowed directions
 15    "Y","N"  Attrition? ("Y"=normal for terrain crossed, "N"=none)
 

 GENERAL VARIABLES
 =================

 a$()     ASSISTANCE data
 b$(32)   blanks; also temporary work space
 c$       temporary input character
 d$()     data array flags
 e$()     EVENTS data
 f$()     FOES data
 g$       movement modifiers
 h$       option headings
 i$       item menu option
 j$       extended tokens
 k$       extended token lengths
 l$       temporary string variable
 m$()     MAP data
 n$()     NARRATIVE data
 o$       main menu option
 p$()     POUCHITEMS data
 q$       valid directions
 r$       random move flag
 s$       temporary string variable
 t$()     TERRAIN data
 u$       print mode channels
 v$(5)    temporary input array
 w$()     WEAPONS data
 x$       error trap action flag
 y$()     transfer array
 z$       message display line

 em       extended mode flag
 mlen     edit length: maximum
 nlen     edit length: new
 olen     edit length: old
 t1       edit s$ pointer
 t2       edit direction (-/+)
 t3       edit line
 t4       edit column
 t5       edit display length of character or token
 t1-t5    are also used as general temporary variables

 br       bright
 fl       flash
 in       ink
 pa       paper

 a(8,5)   data array dimensions
 a,b,c,d  loop counters
 attr     attributes
 t(13)    temporary input array
 

 SAR VARIABLES (also uses some general variables)
 =============

 assd     assistance distance
 assp     assistance pointer
 bcs      player's base combat skill
 bhs      player's base hit strength
 cost     item cost
 days     days left
 eve      event pointer
 fcs      foes's combat skill
 fhs      foes's hit strength
 flee     chance to flee
 foe      foe pointer
 lc       location column
 lr       location row
 lt       location type
 mcs      player's modified combat skill
 mhs      player's modified hit strength
 pitm     pouchitem pointer
 pqty     pouchitem quantity
 q(5)     assistance parameters
 wdur     weapon special effect duration
 weap     weapon pointer


 GENERAL FUNCTIONS
 =================

 a$(a)=("+" AND a>=k0)+STR$ a
 b$(a)=CHR$ (a+k48+(k7 AND a>=kA))
 c$(a$)=CHR$ (CODE a$-(32 AND a$>="a" AND a$<="z"))
 g(g,a,b)=g+(NOT a)+(k2 AND FN r(a,k1,b))
 h(a)=INT (a/kH2)
 h$(a,b)=h$(a*kA+k1 TO a*kA+b)
 i$(a)=("L" AND a<k0)+("G" AND a>k0)+("N" AND NOT a)+(b$( TO k21) AND a<=k0)
 k(a$)=CODE k$(CODE a$-163)-CODE k$(CODE a$-164)
 l(a)=a-kH2*FN h(a)
 n(a)=CODE n$(a)+kH2*CODE n$(a+k1)
 o$(a)=("0" AND a>=k0 AND a<kA)+STR$ a
 p$(a$,b)=b$( TO b-LEN FN s$(a$))+FN s$(a$)
 q(a$,b$,c$)=LEN a$=k1 AND a$>=b$ AND a$<=c$
 r(a,b,c)=a=INT a AND a>=b AND a<=c
 s(a$,b,c)=VAL a$>=b AND VAL a$<=c
 s$(a$)=STR$ (CODE a$(k1)+kH2*CODE a$(k2 TO LEN a$))
 v(a)=PEEK a+kH2*PEEK (a+k1)
 w(k)=CODE w$(a,k+k1)-CODE w$(a,k)


 SAR FUNCTIONS (also uses some general functions)
 =============

 a(a,b)=a-(a AND a<k0)-(a-b AND a>b)
 i(a,b,c)=k4+(k2 AND a<=b)-(k4 AND a<=c)
 l$(a$)=CHR$ (CODE a$+(k32 AND a$>="A" AND a$<="Z"))
 r$(a)=g$(a*k2+43 TO a*k2+44)
 t()=VAL "65536-168-50-456-27-1"
 w$(a$)="Ready "+a$+" tape then Press a key"
 y()=c$="Y" OR c$="N"
 z(a)=INT (RND*a)+k1


 SAB/SAT MACHINE CODE
 ====================
 64833 FD41 s_to_y build y$() display from s$ input
 65004 FDEC resize resize n$() in situ
 65229 FECD find   find a string or string array
 65252 FEE4 update update n$() pointers
 65318 FF26 trap   error trap - jumps to 9910


 SAR MACHINE CODE
 ================
 64835 FD43 find   find a string or string array
 64862 FD5E prnt42 42-column print from z$
 65318 FF26 trap   error trap - jumps to BASIC line 9910

 prnt42 is a slightly modified version of the routine by Paul Wardle
 from the article "42 and 64" in Your Sinclair #78 (Jun.1992).

