Since its birth and up to version 1.2, the scripting facility of TurboRisk was based on the free Delphi Interpreter by S.Kurinny & S.Kostinsky (Delphin). From version 2.0 on, TurboRisk uses the Delphi-style RemObjects Pascal Script (ROPS) runtime interpreter .
This documents explains some of the differences between the two script languages and their implementation in TurboRisk, and deals with some of the issues to face when converting a TRP from the older version to the current one.
The typical program structure of a TRP expected by the current version of TurboRisk is described in the document programs.html. There are few differences between this structure and the previous one.
Program MyProgram;
statement. It is allowed for clarity, but has no effect.
procedure Assignment(var ToTerritory: integer);
procedure Placement(var ToTerritory: integer);
procedure Attack(var FromTerritory, ToTerritory: integer);
procedure Occupation(FromTerritory, ToTerritory: integer; var Armies: integer);
procedure Fortification(var FromTerritory, ToTerritory, Armies: integer);
For those of you not very familiar with Pascal, the word var
before the declaration of a parameter means that this is passed "by reference"
instead of "by value". That is, if the procedure modifies its value, the calling
program receives the modified value.
As in TurboRisk 1.2, all the variables you define will be LOCAL variables, no matter their scope. This happens because TurboRisk uses the same space to load and execute all of the different computer player programs, turn after turn. You still have to store GLOBAL values using the TurboRisk internal buffers, which you can have access to through the UBufferSet and UBufferGet functions.
The possibility of defining global scope variables is still a new useful feature, which makes possible for a procedure to share values with other called procedures.
The real type is no more supported. Use double instead.
ROPS uses standard PASCAL conventions about the syntax and priorities of operators, including the logical one. The following statement was legal in TurboRisk 1.2:
if TIsMine(x) and TArmies(x)=TArmies(x) then begin
but it's no more legal in current TurboRisk. In PASCAL the and operator has a higher priority than the "equal", "greater than", "less then" and the other comparation operators, so the proper syntax for that statement shall be:
if TIsMine(x) and (TArmies(x)=TArmies(x)) then begin
ROPS is not very tolerant about type mixing in expression and logical conditions. The following code aborts execution, because it compares an integer value with a double value:
var
TotalArmies: integer;
begin
if PArmiesCount(T)>TotalArmies * 0.35 then
The correct code fragment is the following:
var
TotalArmies: integer;
begin
if PArmiesCount(T)>trunc(TotalArmies * 0.35) then
You need to be careful when using this method though. Consider the following example:
var
TotalArmies: integer;
begin
if PArmiesCount(T)<trunc(TotalArmies * 0.35) then
Notice that the comparative operator has changed. If PArmiesCount(T) is 17 and
TotalArmies * 0.35 is 17.5, then 17.5 will be truncated to 17 and the statement
will be false even though it should be true.
You can use type casting in this case to get the correct result:
var
TotalArmies: integer;
begin
if double(PArmiesCount(T))<TotalArmies * 0.35 then
There are some other reported issues about ROPS and type mixing in logical expressions. For example the code:
var
i: integer;
d: double;
begin
...
if (TArmies(T) / i) < d then ...
stops the interpreter any time TArmies(T)/i is not a whole number. The trunc() function won't work in this case, so it is necessary to use type casting instead:
var
i: integer;
d: double;
begin
...
if (double(TArmies(T))) / (double(i)) < d then ...
Some of the interface functions have a new syntax:
procedure UMessage(M: string);
Previously it accepted an unlimited number of parameters, of any kind:
UMessage('Error: ',MyIntVar+4,... );
Now you have to pass a single string value. Thus the previous example becomes:
UMessage('Error: '+IntToStr(MyIntVar+4)+... );
procedure ULog(M: string);
Same as UMessage.
procedure UBufferSet(B: integer; V: double);
Previously the value stored in the buffer was of type variant. Now it is a
double.
function UBufferGet(B: integer): double;
function URandom(R: integer): double;
This function as well returns a double;