Real Time Example

You can easily write a real-time scripting engine. Here's a settings file:

# init.bsd

: MODE = (STRICT, TRUE)

# Init
$ win_apptitle = Real Time Scripting Example
! win_width = 640
! win_height = 480
! win_depth = 32
? win_mode = CONST_WIN_WINDOWED
! win_flags = CONST_WIN_SHOWBORDER + CONST_WIN_SHOWMINIMIZE + CONST_WIN_SHOWCLOSE

# Real Time
! rtv_width = win_width
! rtv_height = win_height
$ rtv_message = Hello#COMMA# World!


: MODE = (STRICT, FALSE)
: DUMP = (vvars.txt)

And here's a real-time script that our program will read:

Don't worry about reading it all - it just contains some conditions, and some functions with parameters to execute if those conditions are true.

# script.brt


# listener condition="expression" compare="type" priority="int"

# Compare is the sort of comparasion that is done
# on the expression - string, integer, real or boolean

# Priority is how often the script is executed,
# e.g. 1 is once per loop (always)
# 10 is once every 10 loops, (less often)



<listener condition="TRUE" compare="boolean" priority="1">
  <function name="cls" params="" />
</listener>


<listener condition="MOUSEX < 200" compare="integer" priority="1">
  <function name="rect" params="0,0,200,rtv_height, 255,0,0" />
</listener>

<listener condition="MOUSEX < 100" compare="integer" priority="1">
  <function name="rect" params="0,0,100,rtv_height, 255,255,0" />
</listener>

<listener condition="MOUSEX > (rtv_width - 200)" compare="integer" priority="1">
  <function name="rect" params="rtv_width - 200,0,200,rtv_height, 255,0,0" />
</listener>

<listener condition="MOUSEX > (rtv_width - 100)" compare="integer" priority="1">
  <function name="rect" params="rtv_width - 100,0,100,rtv_height, 255,255,0" />
</listener>



<listener condition="TRUE" compare="boolean" priority="1">
  <function name="text" params="10,10,This is all scripted in real-time" />
  <function name="text" params="10,30,Move the mouse to the left or right to see the scripted program in action" />
  <function name="text" params="10,50,MouseX: MOUSEX, MouseY: MOUSEY" />
  <function name="text" params="10,70,Screen Width: [rtv_width]#COMMA# Height: [rtv_height]" />
  <function name="text" params="MOUSEX + 20,MOUSEY+10,[rtv_message]" />
</listener>

If you notice, it can use variables from the settings file.

Here's a program to put the two together:

Program
  Uses
pure2d, basilisk, keyset

Const
   MAX_SCRIPT_LENGTH = 20

Type Listeners = Record
   ListenerFunc : Array [MAX_SCRIPT_LENGTH] of String
   ListenerParams : Array [MAX_SCRIPT_LENGTH] of String
   ListenerPriority : Integer
   ListenerCondition : String
   ListenerCompare : Integer
   ListenerLength : Integer
EndType


Procedure Error(msg: String)
Begin
   MessageBox(msg,"Real Time Scripting Example Error")
End

Procedure LoadRealTimeScript(fname: String)
Var
 myfile : Element
 fileIn : String
 
 ladddone : Boolean
 laddcount : Integer
 laddcomp : String
Begin

 myfile = ReadFile(fname)
 
 While Not EOF(myfile)  
   fileIn = TrimSpaces(ReadLn(myfile))
 
   Conditions
       (Left(fileIn,1) = "#"):
       (fileIn=""):
       (Left(fileIn,10)="<listener "):
       
           Listener = NewItem(ListenerList)
           
           Listener.ListenerCondition = AttributeAsString(fileIn,"condition")
           Listener.ListenerPriority  = AttributeAsInteger(fileIn,"priority")
           
           laddcomp = Lower(AttributeAsString(fileIn,"compare"))
           Conditions
               (laddcomp="integer"): Listener.ListenerCompare = VVAR_INTEGER
               (laddcomp="real"): Listener.ListenerCompare = VVAR_REAL
               (laddcomp="string"): Listener.ListenerCompare = VVAR_STRING
               (laddcomp="boolean"): Listener.ListenerCompare = VVAR_BOOLEAN
               Default: Error("Unknown comparason mode: "+laddcomp)
           EndConditions
       
           ladddone = FALSE
           laddcount = 0
           
           While ladddone=FALSE
               If EOF(myfile) then ladddone=TRUE
               fileIn = TrimSpaces(ReadLn(myfile))
               If fileIn = "</listener>" then
                   ladddone = TRUE
               Else
                   If
fileIn <> "" then
                       Listener.ListenerFunc[laddcount] = AttributeAsString(fileIn,"name")
                       Listener.ListenerParams[laddcount] = ","+AttributeAsString(fileIn,"params")
                       Inc(laddcount)
                   Endif
               Endif                
           Wend

           
           Listener.ListenerLength = laddcount - 1
           
       Default:
           Error("Error reading script instrucion: "+fileIn)
   EndConditions
 Wend


 CloseFile(myfile)
End

Procedure UpdateListeners()
Var
   count : static Integer
   sdo : Boolean
   i : Integer
   
   lfunc, lparams : String
Begin
   Inc
(count)
   If (count>10000) then count = 1
   
   Loop Listener Through ListenerList
    If (count Mod Listener.ListenerPriority = 0) then
           sdo = FALSE
           
           Case Listener.ListenerCompare of
               (VVAR_INTEGER): If IntegerExpressionIsTrue(ListenerVarReplace(Listener.ListenerCondition)) then sdo=TRUE
               (VVAR_REAL): If RealExpressionIsTrue(ListenerVarReplace(Listener.ListenerCondition)) then sdo=TRUE
               (VVAR_STRING): If StringExpressionIsTrue(ListenerVarReplace(Listener.ListenerCondition)) then sdo=TRUE
               (VVAR_BOOLEAN): If BooleanExpressionIsTrue(ListenerVarReplace(Listener.ListenerCondition)) then sdo=TRUE
           EndCase

           If
sdo Then
               For
i = 0 to Listener.ListenerLength
                   lfunc = Listener.ListenerFunc[i]
                   lparams = ListenerVarReplace(Listener.ListenerParams[i])
               
                   Conditions
                       (lfunc="cls"): Cls
                       (lfunc="text"):
                           Text(ParameterAsInteger(lparams,1,TRUE),ParameterAsInteger(lparams,2,TRUE),NiceText(ParameterAsString(lparams,3,TRUE)))
                       (lfunc="rect"):
                           Rect(ParameterAsInteger(lparams,1,TRUE), ParameterAsInteger(lparams,2,TRUE), ParameterAsInteger(lparams,3,TRUE), ParameterAsInteger(lparams,4,TRUE), ToRGBA(ParameterAsInteger(lparams,5,TRUE),ParameterAsInteger(lparams,6,TRUE),ParameterAsInteger(lparams,7,TRUE)),TRUE)
                       Default: Error("Unknown function: '"+lfunc+"'")
                   EndConditions
               Next
           Endif
           
       Endif
   EndLoop
   
End


Function ListenerVarReplace(str: String) : String
Begin

   str = Replace(str, "MOUSEX", MouseX, FALSE)
   str = Replace(str, "MOUSEY", MouseY, FALSE)
   
   result = str
End

Function NiceText(str: String) : String
Begin

   str = Replace(str, "#COMMA#",",", FALSE)
   
   result = str
End

Var
   ListenerList : List of Listeners
Listener : ^Listeners

Begin
   InitBasilisk(TRUE)

   ReadSettings("init.bsd")
   SetAppName(VirtualString("win_apptitle"))   
   OpenScreen(VirtualInteger("win_width"),VirtualInteger("win_height"),VirtualInteger("win_depth"),VirtualBoolean("win_mode"),VirtualInteger("win_flags"))
   FreeVirtualVariablesPrefixed("win_")
   
   LoadRealTimeScript("script.brt")
   
   While Not ExitRequested
       UpdateListeners()
       Flip
       Pause
(1)
       If (KeyHits(VK_ESCAPE) > 0) then RequestExit
   Wend
  
End