Creating a STOS Text Adventure: Adding Objects and Inventory

in Retro Technology4 months ago

st-game-with-stos-2.png

Before in our Atari ST text adventure, all we could do is walk around a hastily thrown-together map.

We check for a limited set of directional commands, and we then check a room array to see if there are exists in the direction the player wants to go.

Now we need to do a few things to allow the player to start interacting with their environment:

  • More commands, such as get and drop.
  • Inventory, to register when the player owns an item rather than the item being in a room.
  • Keep a list of objects and where they live.

New Commands

In the interests of modularity, we check for the first letter of commands and then appropriately GOSUB to a part of the program where we will deal with the logic and return back.

This is one of the reasons the Visual Studio Code extension is so helpful, because you can simply put in a @name and after tokenization the name will be converted to a line number.

If you are using the old school STOS UI then you will need to do what I have done here and think ahead about your numbering to ensure you don't step on your own toes down the line!

150 if IN$="G" then gosub 2000 : rem get
160 if IN$="U" then gosub 3000 : rem use
170 if IN$="D" then gosub 4000 : rem drop
180 if IN$="K" then gosub 5000 : rem kill
185 if IN$="I" then gosub 6000 : rem inventory

Objects and Rooms

The way we will organize the object data is very similar to our room map.

Using a two-dimensional array we can assign objects to rooms. Note that this could have been simpler, but would have only allowed one object per room when we really will want the flexibility of some rooms having no objects and other rooms having multiple.

To test this is going to work we create new data statements for a few objects and assign them to various starter rooms:

10200 data "Key",54
10201 data "Box",55
10202 data "Skull",56

Collecting Objects

Screen Shot 2022-04-30 at 3.09.33 PM.png

By using room numbers indexed from 1 onwards, we say "room 0" is the player's inventory list, so to pick up an object we make the room equal to zero, and to put the item down, we set the room number to the room where we are currently occupying.

2010 rem GET OBJECT
2011 ofound=0
2012 for ob=1 to 100
2013 rem if objects$(ob,0)<>" " then print "comparing "+upper$(objects$(ob,0))+":"+upper$(obj$)
2014 if upper$(objects$(ob,0))=upper$(obj$) then ofound=ob : objects$(ofound,1)="0" : rem zero = inventory 
2015 next ob
2016 if ofound > 0 then print "You picked up: "+objects$(ofound,0)
2017 if ofound = 0 then print obj$ + " not found"
2040 wait key
2900 return

Adding to the Room Descriptions

When we enter a room we can go through the list of objects and see which objects match, then we output the room description followed by the object names in that room.

10031 :
10032 rem LOOKUP OBJECTS
10033 objinroom$=""
10034 for o=1 to 100
10035 if val(OBJECTS$(o,1))=room then objinroom$=objinroom$ + " " + OBJECTS$(o,0)
10036 next o
10037 if objinroom$<>"" then print "OBJECTS VISIBLE:"+objinroom$
10097 return

Object Interaction Logic and Possibilities

Screen Shot 2022-04-30 at 3.09.24 PM.png

Of course, when the player asks to interact with an object we need to check that object is in fact either in their inventory or the room they are currently in, so we need another loop that checks the name of the object against the location. Future expansions could add rules to this to create more possibilities - perhaps an object can be examined but not picked up (a grand piano, for example), perhaps an object can contain other objects (a treasure chest, desk drawer), and so on.

Full Code for Adventure V2

05 rem Adventure boilerplate by Chris Garrett @retrogamecoders
06 rem =======================================================
07 :
10 mode 1 : key off : cls
20 dim ROOMS$(10,10) : dim ROOMDESC$(100) : dim OBJECTS$(100,100) 
30 for Y=0 to 9 : for X=0 to 9 : read R : ROOMS$(X,Y)=str$(R) : next X : next Y
40 X=5 : Y=5 : gosub 10000 : rem initialize start room
45 rem ========================================
46 rem USER INPUT
47 rem ========================================
50 cls : locate 0,0 : room = (y * 10) + x : inverse on: print roomdesc$(room): inverse off: print "Available Exits:"
60 if val(ROOMS$(X,Y-1))>0 then print "> North"
70 if val(ROOMS$(X+1,Y))>0 then print "> East"
80 if val(ROOMS$(X-1,Y))>0 then print "> West"
90 if val(ROOMS$(X,Y+1))>0 then print "> South"
91 gosub 10031
100 print "Command"; : input CMD$ : IN$=upper$(left$(CMD$,1))
101 sp=instr(CMD$," ") : rem Space between words
102 obj$=right$(CMD$,len(CMD$)-sp) : rem Specified Object
110 if IN$="N" and val(ROOMS$(X,Y-1))>0 then Y=Y-1
120 if IN$="E" and val(ROOMS$(X+1,Y))>0 then X=X+1
130 if IN$="W" and val(ROOMS$(X-1,Y))>0 then X=X-1
140 if IN$="S" and val(ROOMS$(X,Y+1))>0 then Y=Y+1
150 if IN$="G" then gosub 2000 : rem get
160 if IN$="U" then gosub 3000 : rem use
170 if IN$="D" then gosub 4000 : rem drop
180 if IN$="K" then gosub 5000 : rem kill
185 if IN$="I" then gosub 6000 : rem inventory
190 if IN$="Q" then print "Goodbye!" : end 
200 goto 50
900 :
1000 rem ROOM LAYOUT
1010 data 0,0,0,0,0,0,0,0,0,0
1020 data 0,1,0,0,1,0,0,1,0,0
1030 data 0,1,0,0,1,0,0,1,0,0
1040 data 0,1,1,1,1,1,1,1,0,0
1050 data 0,0,0,1,1,1,0,1,0,0
1060 data 0,0,0,1,1,0,0,1,0,0
1070 data 0,0,0,0,0,0,0,1,0,0
1080 data 0,0,0,0,0,0,1,1,0,0
1090 data 0,0,0,0,0,0,0,0,0,0
1100 data 0,0,0,0,0,0,0,0,0,0
2000 :
2010 rem GET OBJECT
2011 ofound=0
2012 for ob=1 to 100
2013 rem if objects$(ob,0)<>" " then print "comparing "+upper$(objects$(ob,0))+":"+upper$(obj$)
2014 if upper$(objects$(ob,0))=upper$(obj$) then ofound=ob : objects$(ofound,1)="0" : rem zero = inventory 
2015 next ob
2016 if ofound > 0 then print "You picked up: "+objects$(ofound,0)
2017 if ofound = 0 then print obj$ + " not found"
2040 wait key
2900 return
3000 :
3010 rem USE OBJECT
3020 print obj$
3040 wait key
3900 return
4000 :
4010 rem DROP OBJECT
4020 print obj$
4040 wait key
4900 return
5000 :
5010 rem KILL CHARACTER
5020 print obj$
5040 wait key
5900 return

6000 :
6010 rem INVENTORY
6011 print "INVENTORY:"
6012 for ob=1 to 100
6013 if objects$(ob,1)="0" then print " . " + objects$(ob,0)
6015 next ob
6040 wait key
6900 return
6000 :


10000 :
10010 rem ROOM DATA
10020 restore 10100 : for r=0 to 99
10021 read desc$ : roomdesc$(r)=desc$
10022 next r
10023 :
10024 rem OBJECTS in ROOMS
10025 r=0 : restore 10200 : for r=1 to 100 
10026 read obj$ : read roomno
10027 objects$(r,0)=obj$ : objects$(r,1)=str$(roomno)
10028 next r
10029 :
10030 return
10031 :
10032 rem LOOKUP OBJECTS
10033 objinroom$=""
10034 for o=1 to 100
10035 if val(OBJECTS$(o,1))=room then objinroom$=objinroom$ + " " + OBJECTS$(o,0)
10036 next o
10037 if objinroom$<>"" then print "OBJECTS VISIBLE:"+objinroom$
10097 return
10098 :
10099 rem DATAS ***************************************
10100 data " "
10101 data " "
10102 data " "
10103 data " "
10104 data " "
10105 data " "
10106 data " "
10107 data " "
10108 data " "
10109 data " "
10110 data " "
10111 data " "
10112 data " "
10113 data " "
10114 data " "
10115 data " "
10116 data " "
10117 data " "
10118 data " "
10119 data " "
10120 data " "
10121 data " "
10122 data " "
10123 data " "
10124 data " "
10125 data " "
10126 data " "
10127 data " "
10128 data " "
10129 data " "
10130 data " "
10131 data " "
10132 data " "
10133 data " "
10134 data " "
10135 data " "
10136 data " "
10137 data " "
10138 data " "
10139 data " "
10140 data " "
10141 data " "
10142 data " "
10143 data " "
10144 data " "
10145 data "Room 45 "
10146 data " "
10147 data " "
10148 data " "
10149 data " "
10150 data " "
10151 data " "
10152 data " "
10153 data " "
10154 data "West Room "
10155 data "Start room"
10156 data "East Room "
10157 data " "
10158 data " "
10159 data " "
10160 data " "
10161 data " "
10162 data " "
10163 data " "
10164 data " "
10165 data "Room 65 "
10166 data " "
10167 data " "
10168 data " "
10169 data " "
10170 data " "
10171 data " "
10172 data " "
10173 data " "
10174 data " "
10175 data " "
10176 data " "
10177 data " "
10178 data " "
10179 data " "
10180 data " "
10181 data " "
10182 data " "
10183 data " "
10184 data " "
10185 data " "
10186 data " "
10187 data " "
10188 data " "
10189 data " "
10190 data " "
10191 data " "
10192 data " "
10193 data " "
10194 data " "
10195 data " "
10196 data " "
10197 data " "
10198 data " "
10199 data " "
10200 data "Key",54
10201 data "Box",55
10202 data "Skull",56
10203 data " ",999
10204 data " ",999
10205 data " ",999
10206 data " ",999
10207 data " ",999
10208 data " ",999
10209 data " ",999
10210 data " ",999
10211 data " ",999
10212 data " ",999
10213 data " ",999
10214 data " ",999
10215 data " ",999
10216 data " ",999
10217 data " ",999
10218 data " ",999
10219 data " ",999
10220 data " ",999
10221 data " ",999
10222 data " ",999
10223 data " ",999
10224 data " ",999
10225 data " ",999
10226 data " ",999
10227 data " ",999
10228 data " ",999
10229 data " ",999
10230 data " ",999
10231 data " ",999
10232 data " ",999
10233 data " ",999
10234 data " ",999
10235 data " ",999
10236 data " ",999
10237 data " ",999
10238 data " ",999
10239 data " ",999
10240 data " ",999
10241 data " ",999
10242 data " ",999
10243 data " ",999
10244 data " ",999
10245 data " ",999
10246 data " ",999
10247 data " ",999
10248 data " ",999
10249 data " ",999
10250 data " ",999
10251 data " ",999
10252 data " ",999
10253 data " ",999
10254 data " ",999
10255 data " ",999
10256 data " ",999
10257 data " ",999
10258 data " ",999
10259 data " ",999
10260 data " ",999
10261 data " ",999
10262 data " ",999
10263 data " ",999
10264 data " ",999
10265 data " ",999
10266 data " ",999
10267 data " ",999
10268 data " ",999
10269 data " ",999
10270 data " ",999
10271 data " ",999
10272 data " ",999
10273 data " ",999
10274 data " ",999
10275 data " ",999
10276 data " ",999
10277 data " ",999
10278 data " ",999
10279 data " ",999
10280 data " ",999
10281 data " ",999
10282 data " ",999
10283 data " ",999
10284 data " ",999
10285 data " ",999
10286 data " ",999
10287 data " ",999
10288 data " ",999
10289 data " ",999
10290 data " ",999
10291 data " ",999
10292 data " ",999
10293 data " ",999
10294 data " ",999
10295 data " ",999
10296 data " ",999
10297 data " ",999
10298 data " ",999
10299 data " ",999
10300 data " ",999

Next Up: Fixing the Limitations of this Method

As we expand the use of arrays, and we discuss more complex expansion of the system, we soon find ourselves having lines and lines of data commands.

Really we need to have our game engine separate from our game data, so next time we will look at having our data stored in files that can be edited and loaded without changing our game code.

Sort:  

This is pretty awesome. I grew up with a Vic-20 and C64 and did my best to learn Basic at a very young age. At the time I couldn't wrap my head around variables so wasn't able to progress far, but looking at your code here brings me right back to something like 8 years old.

I'm loving this. Looking forward to seeing what's next!