home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 10: Diskmags / nf_archive_10.iso / MAGS / ST_NEWS / STN_01_C.MSA / DATA_DOC33 < prev    next >
Text File  |  1994-03-14  |  16KB  |  437 lines

  1.  üWRITING YOUR OWN ADVENTURES Çby Stefan Posthuma
  2.  
  3. The   adventure   is  one  of  the  most   addictive   forms   of 
  4. computergames.  Every  computer  owner must have  heard  of  them 
  5. sometimes. Which ST-owner doesn't know 'The Pawn'?
  6. Adventures  are  so  attractive because they are a  test  of  the 
  7. players'  skill and creativity.  The only thing that  limits  the 
  8. capability  of an adventure is the imagination of the  author. Of 
  9. course it is great fun to write your own adventure,  because  you 
  10. really  can  let  go  your  imagination  and  create  some  juicy 
  11. location-descriptions and some tricky puzzles.
  12. If you might think it's terribly difficult to write an adventure, 
  13. you're wrong.  Everybody with a decent knowledge of BASIC can  do 
  14. the job.  An highly-structured programming language is preferable 
  15. to  write  adventures,  and there is a BASIC for the ST  that  is 
  16. really  great:  GfA-BASIC,  so all examples in this article  have 
  17. been written in it.
  18. If you want to write an adventure, the first thing you have to do 
  19. is  to think of a 'script'.  What is the final goal,  and in what 
  20. can the player achieve this goal?
  21. Dream up puzzles and exotic locations; let your imagination free!
  22. The  second step is the creation of a map with all the  locations 
  23. and the way they are connected. You can do this by taking a piece 
  24. of graph-paper and draw the locations as squares,  connected with 
  25. lines.  In this case you can use six  directions,  north,  south, 
  26. west,  east,  up  and  down.  (if you want to  make  things  more 
  27. complex,  you can also use directions like north-west, south-east 
  28. etc.)  Number each location and give it a short description  like 
  29. 'small  room'  or 'cave'.  Then make a table of all  the  objects 
  30. used, and in which locations they are found. If there is a puzzle 
  31. in a certain location, state it clearly in a list of puzzles.
  32. After this essential part,  you can start the actual programming. 
  33. The  best way to do this is to write a very  structured  program, 
  34. with  a  routine for everything,  like a  routine  for  location-
  35. desriptions,  one for command-recognition (the parser),  and  one 
  36. for  each verb you use.  The basic structure for an adventure  is 
  37. this:
  38.  
  39. GOSUB INIT Q=0;quit flag
  40. WHILE Q=0
  41.   MOVE=0
  42.   GOSUB LOCATIONS
  43.   WHILE MOVE=0
  44.     GOSUB COMMAND
  45.     GOSUB ACTION
  46.   WEND
  47. WEND
  48.  
  49. In  the routine INIT,  you define all variables and objects  used 
  50. throughout  the  program.  There  is one variable  that  is  very 
  51. important:  the location-number.  We'll call that one 'L'.  So if 
  52. the  story  starts in location number one,  make L  one  in  this 
  53. routine.
  54. Also, you have to define all objects. The best way to do this is, 
  55. is to store them in an array. Let's say you have three objects in 
  56. your adventure, a hammer, a pair of scissors and a golden key. At 
  57. the start of the story, the hammer is in location 1, the scissors 
  58. are in location 4 and you carry the key.  In this case you'll get 
  59. something like this:
  60.  
  61. DATA "",HAMMER,1,PAIR OF,SCISSORS,4,GOLDEN,KEY,0
  62. O=3   :number of objects
  63. DIM O$(O,1),O(O) FOR T=1 TO O
  64.   READ O$(T,0),O$(T,1),O(T)
  65. NEXT T
  66.  
  67. Maybe you noticed already,  the number belonging to the object is 
  68. the location in which it can be found, and if the number is zero, 
  69. the player carries it.  I divided the object names in two, so you 
  70. can refer to the golden key, just by using the word 'KEY'
  71.  
  72. The next routine,  LOCATIONS simply prints the description of the 
  73. location and the objects that can be found in it.
  74. The  first thing you have to do is to see if it is not 'too  dark 
  75. to  see'.  So if locations 10 to 20 are set underground  and  you 
  76. need a lamp to be able to see anything, you'll get this:
  77.  
  78. PROCEDURE LOCATIONS
  79.   DARK=0
  80.   No=0    ;no  movement possible in any direction  (I  used  'No' 
  81.         because 'N' is used somewhere else)
  82.   S=0
  83.   W=0
  84.   E=0
  85.   U=0
  86.   D=0   DR=0 ;no door too
  87.   IF L>=10 AND L<=20 AND LAMP=0
  88.     PRINT "It's too dark, You can't see a thing!"
  89.     DARK=1
  90.   ENDIF
  91.   ON L GOSUB L1,L2,L3,L4,L5 ect....
  92.   IF DARK=0
  93.     PRINT
  94.     GOSUB OBJECTS
  95.   ENDIF
  96. RETURN
  97.  
  98. The  variable 'LAMP' is a flag which is set to one if you have  a 
  99. lit lamp, else it is set to zero. The variable DARK is for future 
  100. use to see if it is dark.  (In which case you can do nothing  but 
  101. move to another location.)
  102. The routines L1,  L2,  L3 ect.  contain the location descriptions 
  103. and the movement-variables.
  104. For example if location 1 is a room, to the north lies location 5 
  105. and to the west location 3:
  106. PROCEDURE L1
  107.  PRINT "You are in a dimly lit room.  Everything is covered in  a 
  108. thick layer of dust.  A fat brown rat scurries away at the  sound 
  109. of your footsteps and a shutter schrieks in the  wind.....  There 
  110. is  a door to the north and a dark,  uninviting corridor  to  the 
  111. west."
  112.   N=5     ;north lies location 5
  113.   W=3     ;and west location 3
  114. RETURN 
  115. The  variables  N,S,W,E,U and D indicate the  possible  exits  to 
  116. various  locations,  if  a  variable is zero,  no  exit  in  that 
  117. direction.  Remember,  if a location is dark,  first check if you 
  118. can see anything (DARK=1)
  119.  
  120. The  routine 'OBJECTS' prints a list of all objects  present.  It 
  121. could go like this:
  122.  
  123. PROCEDURE OBJECTS
  124.   FOR T=1 TO O
  125.     IF O(T)=L
  126.       PRINT "There is a ";O$(T,0);" ";O$(T,1);" here."
  127.     ENDIF
  128.   NEXT T
  129. RETURN
  130.  
  131.  The next routine,  the one that asks for a command and evaluates 
  132. it, can be quite complex and is called a parser. If you have ever 
  133. played  'the  pawn' or and Infocom adventure you will  know  that 
  134. these parsers accept commands like 'Open the brown bag then  take 
  135. the bottle from the bag. Open the bottle and drink the water.'
  136. In  our adventure,  we'll stick to the basic  form,  a  verb-noun 
  137. parser.  Here  you  can enter commands like 'GO NORTH'  or  'TAKE 
  138. KEY'. Here is the example:
  139.  
  140. PROCEDURE COMMAND
  141.   REPEAT
  142.     LINE INPUT C$
  143.     PRINT
  144.     IF C$=""
  145.       PRINT "HUH?"
  146.       PRINT
  147.     ENDIF
  148.   UNTIL C$<>""
  149.   C$=UPPER$(C$)
  150.   Sp=INSTR(C$," ") ;find a space between verb and noun.
  151.   IF Sp=0
  152.     GOSUB SINGLE    ;you entered a single command
  153.   ELSE
  154.     V$=LEFT$(C$,Sp-1) ;store the verb in V$
  155.     N$=RIGHT$(C$,LEN(C$)-Sp) ;store the noun in N$
  156.     GOSUB INTERPRET
  157.   ENDIF
  158. RETURN
  159. The  procedure  'SINGLE'  is  just a  long  list  of  IF....ENDIF 
  160. statements e.g.:
  161.  
  162. PROCEDURE SINGLE
  163.   FLAG=0
  164.   IF C$="QUIT" OR C$="STOP" OR C$="END"
  165.     GOSUB QUIT
  166.     FLAG=1
  167.   ENDIF
  168.   IF C$="INVENTORY" OR C$="INV" OR C$="I"
  169.     GOSUB INV
  170.     FLAG=1
  171.   ENDIF
  172.   IF C$="LOOK" OR C$="L"
  173.     GOSUB LOCATIONS
  174.     FLAG=1
  175.   ENDIF
  176.   and so on.....
  177.   IF FLAG=0
  178.     PRINT "I'm not sure I can follow you.."
  179.   ENDIF
  180. RETURN
  181. I'll also give you the procedure INV.  This routine prints a list 
  182. of all ojects you carry.
  183.  
  184. PROCEDURE INV
  185.   PRINT "You are carrying:"
  186.   FLAG=0
  187.   FOR T=1 TO O
  188.     IF O(T)=0
  189.       PRINT "A ";O$(T,0);" ";O$(T,1)
  190.       FLAG=1
  191.     ENDIF
  192.   NEXT T
  193.   IF FLAG=0
  194.     PRINT "Absolutely nothing!"
  195.   ENDIF
  196. RETURN
  197.  
  198. The procedure 'INTERPRET' is a little more  complex.  First,  you 
  199. have to check if the noun exists and if it is present if it is an 
  200. object.  After  that,  you  have to check the  verb,  and  handle 
  201. accordingly.  Just like you made a list of objects, you also have 
  202. to  make  a  list  of  verbs  and  recognised  words.  (In  DATA-
  203. statements; label them clearly)
  204. PROCEDURE INTERPRET
  205.   RESTORE WORDS     ;I used the label 'WORDS'
  206.   FLAG=0
  207.   X=0     ;counter
  208.   N=0     ;noun number
  209.   O1=0    ;object chosen flag
  210.   DO
  211.     READ W$
  212.     INC X
  213.     EXIT IF W$="endwords"     ;use 'endwords' as last word in the 
  214.                               list
  215.     IF N$=W$
  216.       FLAG=1   ;word recognised
  217.       N=X      ;noun number
  218.     ENDIF
  219.   LOOP
  220.   IF FLAG=0    ;not a word
  221.     FOR T=1 TO O
  222.       IF N$=O$(T,1) OR N$=O$(T,0)+" "+O$(T,1)
  223.         FLAG=1
  224.         O1=1     ;object chosen
  225.         N=T      ;object number
  226.       ENDIF
  227.     NEXT T
  228.   ENDIF
  229.   IF FLAG=0    ;unknown word
  230.      PRINT  "I'm  sorry,  but  the  word  ";N$;"  is  not  in  my            
  231. vocabulary"
  232.   ELSE      IF O1=1   ;check if the object is present
  233.       IF O(N)<>0 AND O(N)<>L
  234.         PRINT "I can't see any ";N$
  235.         N=0
  236.       ENDIF
  237.     ENDIF
  238.   ENDIF
  239.   RESTORE VERBS     ;I used the label 'VERBS'
  240.   FLAG=0
  241.   X=0
  242.   DO
  243.     READ W$
  244.     INC X
  245.     EXIT IF W$="endverbs"   ;use 'endverbs' as last verb
  246.     IF W$=V$
  247.       FLAG=1      ;verb recognised
  248.       V=X         ;verbnumber
  249.     ENDIF
  250.   LOOP
  251.   IF FLAG=0
  252.     PRINT "I don't know how to ";V$
  253.   ELSE
  254.     IF N<>0         ;verb and noun recognised
  255.       IF V<>6 AND V<>7 AND DARK=1   ;is it dark and you   do  not 
  256.                                    move?
  257.          PRINT  "It is really hard to ";V$;" something in 
  258. the dark."             ELSE
  259.         ON V GOSUB GET,GET,DROP,EXAM,EXAM,GO,GO,EAT
  260.       ENDIF
  261.     ENDIF
  262.   ENDIF
  263. RETURN 
  264. In this case, your verb list would be this:
  265.  
  266. VERBS:
  267. DATA GET,TAKE,DROP,EXAMINE,STUDY,GO,WALK,EAT
  268. DATA endwords
  269. The  verbs 'GET and TAKE',  'EXAMINE and STUDY',  'GO  and  WALK' 
  270. refer to the same procedure because they are  synonyms.  Handling 
  271. verbs:
  272.  
  273. PROCEDURE GET  ;'N' is holds object number chosen.
  274.   IF O1=0      ;Is it an object?
  275.     PRINT "You can't take that!"
  276.   ELSE
  277.     IF O(N)=0
  278.       PRINT "You already have it!"
  279.     ELSE
  280.       IF I=5     ;'I' counts the number of object you have
  281.         PRINT "You are carrying too much!"       ELSE
  282.         PRINT "OK!"
  283.         O(N)=0   ;You now carry the object
  284.         INC I
  285.       ENDIF
  286.     ENDIF
  287.   ENDIF
  288. RETURN
  289.  
  290. PROCEDURE DROP
  291.   IF O1=0      ;is it an object?
  292.     PRINT "You're talking complete nonsense here."
  293.   ELSE
  294.     IF O(N)<>0
  295.       PRINT "You don't have it!"
  296.     ELSE
  297.       PRINT "Dropped."
  298.       O(N)=L   ;put in location number 'L' (The current location)
  299.       DEC I    ;you carry one object less.
  300.     ENDIF
  301.   ENDIF
  302. RETURN    
  303. The procedure 'EXAM' can be very large,  since the player must be 
  304. able  to examine a lot of things.  The best way to do it is  like 
  305. this:  first,  check in N$ is an object. (O1 contains 1). If it's 
  306. not,  jump to a different subroutine for every location. In these 
  307. subroutines,  check  N$ for things you can examine and print  the 
  308. description. (A long IF.....ENDIF list.) Check the sample program 
  309. if you don't understand this.
  310. The procedure 'GO' is quite simple.  For example,  if the  player 
  311. wants  to GO NORTH,  check if N equals zero.  In  that  case,  no 
  312. movement north is possible.  In the other case, make 'L' the same 
  313. as  'N' and the player has moved to a new  location.  The  sample 
  314. contains  only movement NORTH and UP,  but the procedure  is  the 
  315. same for the other directions.
  316.  
  317. PROCEDURE GO
  318.   N$=LEFT$(N$,1)
  319.   IF N$="N"
  320.     IF N=0       PRINT "You can't go that way!"
  321.     ELSE
  322.       L=N
  323.       MOVE=1   ;flag for main loop.
  324.     ENDIF
  325.   ENDIF
  326.   IF N$="U"
  327.     IF U=0
  328.       PRINT "You can't fly!"
  329.     ELSE
  330.       L=U
  331.       MOVE=1
  332.     ENDIF
  333.   ENDIF
  334.   ect...
  335.   IF N$<>"N" AND N$<>"S" AND N$<>"W" AND N$<>"E" AND N$<>"U"  AND 
  336. N$<>"D"
  337.     PRINT "You can't go there!"
  338.   ENDIF
  339. RETURN
  340.  
  341. Be sure to add the words 'NORTH',  'SOUTH',  'WEST' ect.  to your 
  342. wordlist.
  343. The  movement commands are used a lot,  and it would be handy  if 
  344. the player could input 'N' instead of 'GO NORTH'. To do this, add 
  345. this to the 'SINGLE' routine:
  346.  
  347. IF  C$="N"  OR  C$="S" OR C$="W" OR C$="E" OR  C$="U"  OR  C$="D"   
  348. N$=C$
  349.   GOSUB GO
  350. ENDIF
  351.  
  352. The  procedure 'EAT' is one of the many.  If you want to write  a 
  353. good  adventure,  inlcude  a  lot of  verbs,  and  make  a  large 
  354. vocabulary. The following procedure is merely an example, and can 
  355. be totally different in your adventure.
  356.  
  357. PROCEDURE EAT
  358.   IF O1=0 OR N<>3   ;object numer 3 is a bread or something  like 
  359.                     that.
  360.     PRINT "You have to be out of your mind!"
  361.   ELSE
  362.      PRINT  "It tasted really good until you almost broke            
  363. your teeth on a file that was in it."
  364.     O(4)=L     ;object  number  four  is  the  file       O(3)=-1    
  365.                ;the bread 'disappears'
  366.   ENDIF
  367. RETURN
  368.  
  369. Handling doors:
  370. Almost every adventure has at least one door. Doors are difficult 
  371. things  in  an adventure program.  You have to be able  to  open, 
  372. close,  lock, unlock, and examine them. Doors often form puzzles, 
  373. because you need a certain key to open them or you have to  break 
  374. them, or simply knock on them.
  375. I handle doors like this:
  376.  
  377.  
  378.  
  379. I store all information about them in an array; D. Initialise and 
  380. fill this array in the procedure INIT. A door can have 3 modes:
  381.  0 : open                1 : closed
  382.  2 : closed & locked
  383. Let's say there is a door to the north, and if you go through the 
  384. door, you enter lokation number 6. Instead of making N 6, make it 
  385. -6.  Then define another variable, called 'DR'. This one contains 
  386. the number of the door present.  In the procedure GO,  check if a 
  387. direction is negative,  if it is,  check if the door is  open.  I 
  388. think it will become clear if you study the example program.
  389.  
  390. The  procedure  ACTION,  is a procedure in which  you  count  the 
  391. number of moves made, check if the player is still healthy, check 
  392. if  the oil supply of the lamp isn't running out,  check if  that 
  393. fire-breathing dragon didn't wake up to tear you to  shreds,  and 
  394. lots more. It all depends on your story.
  395.  
  396. êAdvanced parsers
  397. Ç
  398. I am writing an adventure too,  and I am trying to develop a good 
  399. parser.  This means that it has to recognise multiple commands in 
  400. one  line,  and things like this:  TAKE ALL BUT THE LAMP AND  THE 
  401. SWORD FROM THE LARGE BOX THEN KILL THE DWARF WITH THE KNIFE.
  402. First, split up the multiple commands. They are separated by THEN 
  403. or  by full stops.  Put them in an array and handle them  one  by 
  404. one. Of course, eliminate all 'THE's because you don't need them. 
  405. So  reduce  'TAKE THE LAMP' to 'TAKE LAMP'.  But there  is  more, 
  406. things like 'TAKE ALL BUT...  are very difficult,  but somehow  I 
  407. managed to do it.  Maybe if I feel like it, I'll write an article 
  408. about it some time.
  409.  
  410. On the disk you will find a very small adventure game that brings 
  411. all  examples into practice.  Of course this is not a  full-grown 
  412. adventure,  I kept it very basic and simple, but it is just meant 
  413. for you to figure out how an adventure program works.  The object 
  414. of the game: escape from the House!
  415. Well, that concludes this article. I hope you are inspired enough 
  416. to start writing. Of course, think carefully about it, and put it 
  417. all  on paper before you start programming.  Also  document  your 
  418. program properly;  it's hard to read a very long program  without 
  419. any leads, even if it's your own.
  420. If  you  have a problem,  contact me through  the  correspondence 
  421. address of üST NEWSÇ.  Don't forget to enclose two stamps:  One for 
  422. the  editor  to  send it through to me and one for me  so  I  can 
  423. respond to your letter!
  424.  
  425. About the author:
  426.  
  427. Stefan  Posthuma started programming computers back on the VIC  20 
  428. from Commodore,  later on the Commodore 64. On the latter machine, 
  429. he  competed in the Micro Masters Holland competition with a  game 
  430. called  "Hades".  Later,  he programmed "Scuttle" (with the  music 
  431. from Jean Michel Jarre) that was marketed by Aackosoft. He won the 
  432. Micro Masters Holland and won a Philips YES PC.  He felt he didn't 
  433. have enough software,  so he swapped the machine against a 260 ST. 
  434. Now, he is proud to be in the ever increasing ST legions.
  435.  
  436.  
  437.