Quote: "If I have the time I may knock something up for a simple game book based on the above datafile"
I had a couple of hours to kill, so I have put together a quick rough program. Nothing great, and uses a slightly adapted text file, but you will get the idea. Again, was chucked together hastily, but you should see what I am getting at.
Here is the code:-
`Gamebook demo - By Darren Gates June 2008
set window on
SET DISPLAY MODE 800, 600, 16
sync rate 0
sync on
color backdrop 0
`Work out on screen text
set text font "Arial"
set text size 14
fonttext$=""
for ftloop=48 to 57:fonttext$=fonttext$+chr$(ftloop):next
for ftloop=65 to 90:fonttext$=fonttext$+chr$(ftloop):next
for ftloop=97 to 122:fonttext$=fonttext$+chr$(ftloop):next
global fth
fth=text height(fonttext$)+1 `Work out max size of text from all characters (assuming numbers and letters only at the min)
global inputY
inputY=screen height()-fth
global screenlines
screenlines=int(screen height()/fth)-2 `How many lines can we get on screen?
global dim screentext$(screenlines)
global dim screencol(screenlines)
global titlecol,textcol,textcommcol,errorcol,optioncol
global IDList$,onLoc
titlecol=rgb(255,255,255):textcol=rgb(0,255,0):textcommcol=rgb(0,0,255):errorcol=rgb(255,0,0):optioncol=rgb(255,255,0)
type page
desc as string
option1text as string `Could make types and arrays within types and the like but can't be bothered...
option1link as integer
option2text as string
option2link as integer
option3text as string
option3link as integer
option4text as string
option4link as integer
option5text as string
option5link as integer
status as integer `0=Normal loc with options 1=Death 2=Complete game!
endtype
global dim loc(999) as page `Locations
addaline("Welcome to Gamebook demo by Darren Gates June 2008",titlecol)
scanlocs()
global myloc=0 `First location in datafile is first one we start with
doloc(myloc)
do
cls
for online=0 to screenlines
myline$=trim(screentext$(screenlines-online)) `Work backwards (0 is bottom line)
if myline$<>""
ink screencol(screenlines-online),0
if text size()<>14 then set text size 14 `Just incase setting text size is slow
text 0,online*fth,myline$
endif
next
select loc(myloc).status
case 0:icommand$="Select:":endcase
case 1:icommand$="You are dead. Play again Y/N?":endcase
case 2:icommand$="You have beaten the game. Play again Y/N?":endcase
endselect
command$=get_input(0,inputY,icommand$,command$,rgb(255,0,0),rgb(255,255,255)) `Obviously can use this for more than one input. But hey...
if loc(myloc).status>0 `Dead or beaten the game
if upper$(command$)="N" then exit
if upper$(command$)="Y" then myloc=0:addaline(" ",textcol):addaline("Starting Gamebook demo again",titlecol):doloc(myloc)
endif
if val(command$)>0 and val(command$)<6 then option$=command$ else option$=""
command$=""
if option$<>""
link=-1
select option$
case "1":link=loc(myloc).option1link:endcase
case "2":link=loc(myloc).option2link:endcase
case "3":link=loc(myloc).option3link:endcase
case "4":link=loc(myloc).option4link:endcase
case "5":link=loc(myloc).option5link:endcase
endselect
if link>-1
myloc=link
addaline(" ",textcol)
doloc(myloc)
endif
option$=""
endif
sync
loop
end
`Shows the location
function doLoc(thisLoc)
addaline(loc(thisLoc).desc,textcol)
optiontext$=loc(thisLoc).option1text:if showlocline(optiontext$,1,optioncol)=1 then exitfunction
optiontext$=loc(thisLoc).option2text:if showlocline(optiontext$,2,optioncol)=1 then exitfunction
optiontext$=loc(thisLoc).option3text:if showlocline(optiontext$,3,optioncol)=1 then exitfunction
optiontext$=loc(thisLoc).option4text:if showlocline(optiontext$,4,optioncol)=1 then exitfunction
optiontext$=loc(thisLoc).option5text:if showlocline(optiontext$,5,optioncol)=1 then exitfunction
endfunction
function showLocLine(myLocLine$,lineno,whatcol)
quitme=0
if myLocLine$<>""
addaline(str$(lineno)+". "+myLocLine$,whatcol)
else
quitme=1
endif
endfunction quitme
`Will scan and load in all locations
function scanlocs()
onLoc=0:IDList$="":useid=-1
if file exist("data.txt")
open to read 1,"data.txt"
if file open(1)=1
while file end(1)=0
read string 1,fileline$
lineid$=upper$(trim(pad(fileline$,5)))
select lineid$
case "MYID="
myid$=midstr(fileline$,6,0)
myln=0 `Normal link (options etc)
pos=instr(myid$,">>",1)
if pos>0
tempmyln$=upper$(trim(midstr(myid$,pos+2,0)))
myid$=left$(myid$,pos-1)
select tempmyln$
case "DEATH":myln=1:endcase
case "WINGAME":myln=2:endcase
endselect
endif
useid=findid(myid$)
if useid>-1 then loc(useid).status=myln
endcase
case "TEXT="
if useid>-1
mytext$=midstr(fileline$,6,0)
if pad(mytext$,2)=">>" `Is a link to a file
mytext2$="":mytext$=midstr(mytext$,3,0)
if file exist(mytext$)
open to read 2,mytext$
if file open(2)=1
while file end(2)=0
read string 2,externaltext$
mytext2$=mytext2$+externaltext$
endwhile
close file 2
endif
endif
else
mytext2$=mytext$
endif
loc(useid).desc=loc(useid).desc+mytext2$ `Wraps around
endif
endcase
case "OPT1=","OPT2=","OPT3=","OPT4=","OPT5="
if useid>-1
optiontext$=trim(midstr(fileline$,6,0))
pos=instr(optiontext$,">>",1)
if pos>0
linktext$=trim(midstr(optiontext$,pos+2,0))
optiontext$=trim(left$(optiontext$,pos-1))
linkedid=findid(linktext$)
if linkedid>-1
myid2$=midstr(lineid$,4,1) `Option number
select myid2$
case "1"
loc(useid).option1text=optiontext$
loc(useid).option1link=linkedid
endcase
case "2"
loc(useid).option2text=optiontext$
loc(useid).option2link=linkedid
endcase
case "3"
loc(useid).option3text=optiontext$
loc(useid).option3link=linkedid
endcase
case "4"
loc(useid).option4text=optiontext$
loc(useid).option4link=linkedid
endcase
case "5"
loc(useid).option5text=optiontext$
loc(useid).option5link=linkedid
endcase
endselect
endif
endif
endif
endcase
endselect
endwhile
close file 1
endif
endif
endfunction
`Dig out ID of location name
function findid(findID$)
foundID=-1 `Major problem
findID$=trim(upper$(findID$))
if findID$<>""
findID$="$"+findID$+"$"
pos=instr(IDList$,findID$,1)
if pos>0
foundID=val(midstr(IDList$,pos+2+len(findID$),3)) `Format is $locid$001
else `Add in new location
IDList$=IDList$+findID$+mask(onLoc,3)
foundid=onLoc
loc(foundid).option1link=-1
loc(foundid).option2link=-1
loc(foundid).option3link=-1
loc(foundid).option4link=-1
loc(foundid).option5link=-1
inc onLoc
endif
endif
endfunction foundID
`Turn number into string and mask zeroes to x chars. So 5 with 3 mask would be 005
function Mask(mynum,maskno)
mymask$=str$(mynum)
if len(mymask$)<maskno
for mloop=1 to 1+maskno-len(mymask$)
mymask$="0"+mymask$
next mloop
endif
endfunction mymask$
`Add a line to the screen
function addaline(line$,linecol)
extraline$="":newline=0
if trim(line$)<>""
newline=instr(line$,"¬",1)
if newline>0
mynl$=midstr(line$,newline+1,0)
line$=left$(line$,newline-1)
endif
wordwrapmode=0
_startWordWrap:
if text width(line$)>screen width()
do
extraline$=right$(line$,1)+extraline$
line$=left$(line$,len(line$)-1)
if text width(line$)<screen width() and (wordwrapmode=1 or right$(line$,1)=" ") then exit
loop
endif
if wordwrapmode=0 and line$="" `Was looking for word wrap at space point. Cannot do that (one word) so just wrap at width
line$=extraline$
extraline$=""
wordwrapmode=1
goto _startwordwrap
endif
endif
for aloop=screenlines to 1 step -1
screentext$(aloop)=screentext$(aloop-1)
screencol(aloop)=screencol(aloop-1)
next
screentext$(0)=line$
screencol(0)=linecol
if extraline$<>"" then addaline(extraline$,linecol)
if newline>0 then addaline(mynl$,linecol)
endfunction
`Pads text to exact size
function Pad(s$,padsize)
if padsize>-1
if len(s$)>=padsize
s$=midstr(s$,1,padsize)
else
s$=s$+space$(padsize-len(s$))
endif
endif
endfunction s$
`Find one string inside another
function Instr(s$,c$,pos)
rem --- returns position of c$ in s$ starting from pos
rem --- Requires Midstr() function
if c$="" or s$="" then exitfunction 0
lenc=len(c$)
lens=len(s$)
repeat
if Midstr(s$,pos,lenc) = c$ then exitfunction pos
inc pos
until pos +lenc> lens+1
endfunction 0
`Extended version of mid$. Basically allows length of string
function Midstr(s$,pos,ln)
if ln=0 then ln=len(s$)-pos+1
t$ = left$(right$(s$,len(s$)-(pos-1)),ln)
endfunction t$
`Reverse instr (look backwards), but cannot start at a point
function InstrRev(s$,c$)
rem --- returns position of c$ in s$ starting from pos
rem --- Requires Midstr() function
if c$="" or s$="" then exitfunction 0
lenc=len(c$)
pos=len(s$)
repeat
if Midstr(s$,pos,lenc) = c$ then exitfunction pos
dec pos
until pos=0
endfunction 0
`Trim spaces from start and end of string
function Trim(a$)
while mid$(a$,1)=" ":a$=right$(a$,len(a$)-1):endwhile
while mid$(a$,len(a$))=" ":a$=left$(a$,len(a$)-1):endwhile
endfunction a$
`Trim spaces from start of string
function LTrim(a$)
while mid$(a$,1)=" ":a$=right$(a$,len(a$)-1):endwhile
endfunction a$
`Trim spaces from end of string
function RTrim(a$)
while mid$(a$,len(a$))=" ":a$=left$(a$,len(a$)-1):endwhile
endfunction a$
`Get input from user
function get_input(x,y,p$,var$,backcol,textcol)
ink backcol,0
if p$<>""
box 0,y,screen width(),screen height() `If a command then show command box
else
box x,y,screen width(),y+text height("g") `Otherwise just cover yourself up
endif
ink textcol,0
set cursor x,y
print p$;var$; ` Display your prompt and your keypresses
if battle>0 then exitfunction `No more if in the middle of battle
if ((int(timer()/500)) && 1) ` Blink the cursor
print "_ ";
else
print " ";
endif
i$=""
if p$="" `Basically a menu or somesuch
if timer()-cursorTimer>100 `Too fast otherwise
if upkey() `Up arrow
i$="^"
else
if downkey() `Down arrow
i$="¬"
endif
endif
cursorTimer=timer()
endif
endif
if i$="" then i$=entry$() ` get the next keypress
clear entry buffer
if i$=chr$(13) ` if ENTER pressed, return the inputted variable
var$=var$+"|"
else
if i$=chr$(8) ` if backspace pressed, remove last character
if len(var$)>1
var$=left$(var$,len(var$)-1)
else
var$=""
endif
else
var$=var$+i$ ` add keypress to inputted variable
endif
endif
endfunction var$
Here is the datafile (data.txt):-
MYID=Outside_Cave
TEXT=You stubmle upon a cave¬
TEXT=Your options are:-
OPT1=Go in>>Go_In_Cave
OPT2=Forget it>>Forget_Cave
MYID=Forget_Cave>>DEATH
TEXT=You forget the cave. Unfortuantly a large eagle kills you...
TEXT= Woe is you!
MYID=Go_In_Cave
TEXT=You go in the cave. You see a torch and a skull. What will you do?
OPT1=Get torch>>Get_Torch
OPT2=Get skull>>Get_Skull
MYID=Get_Torch>>DEATH
TEXT=>>get_torch.txt
MYID=Get_Skull>>WINGAME
TEXT=You have the skull of the ancients! Well Done!
And here is an external text file for one of the location's text (get_torch.txt):-
You get the torch!¬
It lights up the whole cave and you can see clearly now.¬
Unfortuantly the flames engulf your body and you are killed. Dead. No going back. Oh dear. Does this remind you of the good old days of gamebooks? :) It does me quite a lot. Integrate a bit more functionality and could be quite good. Obviously I am rambling quite a bit just to make sure that this get wordwrapped.
A couple of points to notice is you can have upto 1000 locations, with 5 options at each (couldn't be bothered making it more complicated), each location can be a normal option location, death (many), or finish of game (many). You can link to another file for the location description (easier for writing stuff) although currently you will have to put "¬" at the end of any line for the program to realise you need a new line rather than trying to wordwrap.
Hope that helps.
Cheers
I am 99% probably lying in bed right now... so don't blame me for crappy typing
Current fave quote : "She was like a candle in the wind.... unreliable...."