FUNCTION (FU)
RECEIVER

Used to create a separate section of code that can be accessed from more than one place and thus reused. A function is called by using the function receiver. The function trigger then defines the start of the function code.

If you want a script to occur when a function is activated, use a function TRIGGER

NEW FU RECEIVER SYNTAX. See below

!!FU#:XXXX; Function receiver - transfers control to ERM code following function trigger)
# = 1 to 30000.
!!FU#:XXXX; Local function receiver - transfers control to ERM code following local function trigger) See below
# = -1 to -100.

OPTIONS

C$; Check for wrong y vars usage
May be used without parameters, like !!FU:C1;
    $=0 - enables run time check
    $=1 - disable run time check (default if just !!FU:C)
  It will check only if you try to set a y var outside of a function body (execution time), for this is the main case of the problem (reading is not a problem at all if it worked correct).
   By default the checking is disabled.
   This is most logical to use as an instruction and may be useful when testing scripts. Very simple usage.
Example:
************
ZVSE
!#FU:C;

!#TM1:S1/999/1/1;
set TM1 for red

!?TM1;
!!VRy1:S1;
!!FU123:P;

!?FU123;
!!VRy1:S2;
************
   Here when the timer section is executed, you will get a message that y var is set outside of the function body.
D$/$/$... 
up to 16
#s.
Call the function at opposite side. 
Syntax is the same as for FU:P
 Now during a battle you may pass the values of v vars to the other side and call functions at
the other side. Say, you run a user dependent script (like stack splitting). The script runs at one side because it runs as a reaction to a human action (mouse click). So all that you change at this side will not be changed on the other side. Now you can pass all changed values to the other side not running a script there.
Example.
On the one side you run a mouse event driven script:
...
!!VRv1234:S999;
On the other side v1234 will still keep the old value.
To fix it use:
...
!!VRv1234:S999;
!!IP:V1234/1234;

The last command will immediately send the value of v1234 to the other side.
Now to the second part of the problem. Say you use some specific command that has some
effects on the battlefield (say you cast a spell with ERM).
Again, if it is done only at one side, there will be a problem because it is not done on the
other side. Now you may use a distant call for those cases. This means that you call a function
but it runs not at this local PC but at a distant one (the opponent's PC).
Up to 16 x parameters are transferred.
Example.
On one side you have:
...
!!BMv10:Mi/y5/5;
To make it run correctly you should make some changes:
...
!!BMv10:Mi/y5/5;
!!FU12345:Dv10/i/y5/5;

!?FU12345;
!!BMx1:Mx2/x3/x4;

That is all. How it works. FU:D immediately transfer all x parameters to the other side and
makes a call of FU1234 there. So BMv10:M... command runs at one PC and BMx1:M... at the other PC. If you pass all in the right order, you will see the same effect at both sides.
Note that you can pass some vars with IP:V command and then call FU:D to pass more than 16 x parameters to the other side.

Now, an example that you can check (tested):
***********
ZVSE

!?BG0;
!!IF:M^Hi!^;
!!VRv99:S99;
!!VRv100:S100;
!!VRv101:S101;
!!IP:V99/100;
!!FU123:D1/2/3/4/5;

!?FU123;
!!IF:M^V99=%V99, V100=%V100, V101=%V101, X1=%X1, X2=%X2, X3=%X3, X4=%X4, X5=%X5^;
***********
You will see "Hi!" message at any action of a stack, then you will see a message "V99=99,
V100=100, V101=0, X1=1, X2=2, X3=3, X4=4, X5=5
" at the other PC. Then you get "Hi!" at the other
PC.
If you continue, you may notice that the next time the message will be: "V99=99, V100=100,
V101=101, X1=1, X2=2, X3=3, X4=4, X5=5
". So v101 is changed. This is because first you send v99
and v100 through the network and call a function that shows a message (and this is why
v101 is 0). But then the BG0 trigger will work out at the defender's side and v101 will be set
to 101.
This example is only an example because in the script:
!?BG0;
!!IF:M^Hi!^;
!!VRv99:S99; !!VRv100:S100; !!VRv101:S101;

will work fine (identical) at both sides.
But if you run a script as a reaction to a human related event (mouse click generally), you need to think how to transfer changes to the other side.
E;
E0;
Exit the current function immediately
May be used in instructions: !#FU:#; though not sure how this is going to work. Need tests.
You can use this command to avoid re-entering the function.
Example
It was:
!?FU123;
...
!!VRv10:S0 T10;
[get random value]
!?FU123&v10<5; [continue only if random value <5]
...
  Now you can do it this way:
!?FU123;
...
!!VRv10:S0 T10; [get random value]
!!FU&v10>=5:E;  [exit the function only if random value >=5]
[continue only if random value <5]

...

  The plus of this technology is that you have the same set of y and other local vars and you can use it in triggers also.

  Another example (complete):
***************
ZVSE
!?LE3/4/0;   
[all is attached to local event]
!!IF:M^L0-0^;
!!FU123:P;
!!IF:M^L0-1^;
!!FU:E;      
[leave]
!!IF:M^L0-2^;

!?FU123;
!!IF:M^L1-0^;
!!FU124:P;
!!IF:M^L1-1^;
!!FU:E;      
[leave]
!!IF:M^L1-2^;

!?FU124;
!!IF:M^L2-0^;
!!FU125:P;
!!IF:M^L2-1^;
!!IF:M^L2-1a^;

!?FU125;
!!IF:M^L3-0^;
!!FU126:P;
!!IF:M^L3-1^;
!!FU:E;      
[leave]
!!IF:M^L3-2^;

!?FU126;
!!IF:M^L4-0^;
!!IF:M^L4-1^;
!!FU:E;      
[leave]
!!IF:M^L4-2^;

***************
  You will get the next messages:
L0-0
L1-0
L2-0
L3-0
L4-0
L4-1
L3-1
L2-1
L2-1a
L1-1
L0-1
E#;
Extended syntax

Go-to statement
# might be both positive and negative. Jump to previous/next trigger of same kind.
Check GoTo for more information.

P$/$/$... 
up to 16
#s.

Call the function
To get access to parameters use x# (#=1...16) syntax.
They may be used anywhere (within the function) that standard variables are used.
When you call another function (see example), all parameters that are not set will be inherited.

Note: the :P parameter must be placed in the !!FU calling (even if no values are to be transfered to the function) for the command to work correctly .
Example
!!FU1:P;
is right
but !!FU1; is wrong command
All ERM commands (receivers, instructions) have to use at least one parameter in order to work correctly.

X#/?$;

Get type of argument x#
Type is stored in $. Get only.

Types are:
-2 'd?'
-1 'd'
0 (normal)
1 ?
2 =
3 <>
4 >
5 <
6 >=
7 <=

Note 1: Type 'd' and checks are only hints for the function. They are handled like there was no such sign unless the function handles them differently based on FU:X value.
Note 2: Type '=' have a special meaning in DO reciever.

Declarations and Instruction usage
If you call a function with an instruction, the function must be declared *before* the instruction.

So, for example, if you want to call function 100 at the start of a map, you can put in the instruction !#FU100:P; but it won't work if the function trigger follows the instruction. Instead, the function trigger (and code within it) must be first.

So:

ZVSE

!?FU100;
!!IF:M^This is function 100.^;

!#FU100:P;

The above will work but if !#FU100:P; would have been put first (right after ZVSE), it wouldn't work. You wouldn't get an error message but the function wouldn't execute.


Usage of a variable in a function receiver
You can use a variable in a function receiver. So you could put, for example, !!FUv10:P; and the function called (if it exists) would be the function number *currently* stored in v10.


Function Examples:

Example:

!?FU1;
!!IF:M^Here we are before. %X1 %X16^;
!!VRx1:+1;
!!FU2:Px1;
!!IF:M^Here we are after. %X1 %X16^;

To call a function use a receiver FU# (#=1...1000)

Example:
!!FU1:P5;
This calls the function above with one parameter (5)

Local Variable in functions:
In functions you have local variables (up to 100).
To get access to local variables use y# (#=1...100) syntax.
You can set/check/get these vars. Every call creates a unique set of local variables that all equal to zero at entrance.
So all operation with local variable take place inside a function only.
You can make recursive calls.

Another example:
!!FU1:Pi/102/v10/35; means that in the body of the function we have:
!?FU1; x1=i, x2=102, x3=v10, x4=35 others x5...x16 are undefined
!!IF:M^x1=%X1, x2=%X2^;

Then if you call a function with other parameters, x1...x16
variables in a body of a function will have corresponding values.
!!FU1:P10/20; will show "x1=10, x2=20"
!!VRv5:S33; 
!!FU1:Pv5/0; will show "x1=33, x2=0"

Y variables y1...y100 are local variables. You can use them inside
functions for any purpose. All functions have their OWN y variable
set, even if you call recursively one function. When you go out of a
function a previous set of y vars is restored.
!!FU1:P; call FU1

!?FU1; y1 is undefined (=0)
!!VRy1:S1; y1=1
!!FU2:P; call FU2
!!IF:M^y1=%Y1^; "y1=1" (y1 take its original value 1 that was before calling FU2)
!?FU2; y1 is undefined (=0)
!
!VRy1:S2; y1=2
!!IF:M^y1=%Y1^; "y1=2"

Can we make a generic function where I terra transform a big square?
But I still recommend to pass all arguments to the function like this:
!!FU#:Px1/y1/x2/y2/level/type/subtype;


This is a call:
!!FU20000:P5/15/7/28/0/2/50; x1=5,y1=15,x2=7,y2=28,level=0,type=2,subtype=50

Function:
!?FU20000; transform an area
!!DO20001/0/144/1:Px1/x2/x3/x4/x5/x6/x7;
!?FU20001&x16>=x1/x16<=x3; transform a column
!!DO20002/0/144/1:Px16/x2/x4/x5/x6/x7;
!?FU20002&x16>=x2/x16<=x3; Transform one square
!!VRv1:Sx1; X coordinate
!!VRv2:Sx16; Y coordinate
!!VRv3:Sx4; level
!!TR1:Tx5/x6/d/d/d/d/d/d; start retain type

Functions

A function is an entry point as a trigger and a body as receivers.
The trigger is !?FU# (#=1...1000)
Receivers are any receivers.

Example:
!?FU1;
!!IF:M^Here we are before. %X1 %X16^;
!!VRx1:+1;
!!FU2:Px1;
!!IF:M^Here we are after. %X1 %X16^;

To call a function use a receiver !!FU# (#=1...1000)
It has only one command: P
P$/$/$... up to 16 #s.

Example:
!!FU1:P5;

This calls the function above with one parameter (5)

To get access to parameters use x# (#=1...16) syntax.
They may be used everywhere when f...t variables.
When you make a next call to another function (see example) all parameters that are not set will be inherited.

In functions you have local variables (up to 100).
To get access to local variables use y# (#=1...100) syntax.
You can set/check/get these variables. Every call creates a unique set of local variables that all equal to zero at entrance.
So all operation with local variables take place inside a function only.
You can make recursive calls.

Coupling.

You can add a code (receivers) to already exist triggers using the same triggers two or more times.
Example:
!?FU1;
!!... receivers 1
...
!?FU1;
!!... receivers 2
...
!!FU1:...
Last call execute all receivers 1 and then all receivers 2 at the same context.

Example:
!!IFv10:S5;
!!SG4/3/0:M1/v10; set sign message to string var z[v10] or z5
!!SG4/3/0:M1/?z10; get current sign message to z10 string var

NEW FU RECEIVER SYNTAX

FU and DO Receivers have extended syntax to provide return values.

  Now you may use "?var" syntax to return values from the call.
  You can use a v, y- or y variable to store the return value.
  Say:
!!FU...:Pv1/v2/v3/?v4;
  Now if you change x4 value inside of the function, say:
!!VRx4:Sx1;
  it will be copied to v4 after function return.

Comments:
  The value of the variable itself (v4) is not transferred to x4 at a function call. Instead the index of the var is transferred (so x4 will keep value 4).
  In DO loop the index value (4) will be passed at every iteration.
 So if you set it inside of the function body, it will be copied to the variable-receiver after the end of the iteration and restored to index value at the beginning of the next iteration.
  Also you may use "=var" syntax to set (parse) the value at every DO loop iteration (make no difference with standard "var" syntax for FU call).
  Say:
!!VRv35:S10;
!!DO...:P=v35;
  Now if you change the v35 inside of the loop body it will be passed to the next iteration taking account changes made for v35: !!VRv35:Sx1+1;
  So now it gives you x1 equal 10,11,12,13... at every iteration.
  If you use the standard syntax:
!!VRv35:S10;
!!DO...:Pv35;
  you will have x1 = 10,10,10,... at every iteration.

Comments:
  You may use any number of such variables in the call.
  You may use the same var (see example below) with ? and = syntax.
  Example 1:
!?FU2;
!!VRx2:Sx2+17;
!!VRx3:Sx1+17;

!?FU1;
!!FU2:P13/?y-1/?y-2;

!#IF:M^%Y-1,%Y-2^;
!#FU1:P;
!#IF:M^%Y-1,%Y-2^;

  You will see "0,0" and then "16,30".

  Example 2:
!?FU2;
!!VRx2:Sx1+17;
!!IF:M^x=%X1^;

!?FU1;
!!VRy-1:S33;
!!DO2/1/20/1:P=y-1/?y-1;

!#FU1:P;


You will see 33,50,67...



LOCAL FUNCTIONS' SYNTAX

Local functions are the ones with index from -1 to -100:
?FU-5; [start local function -5]
!!FU-5:P...; [call a local function -5]
Those functions are local and can be reached ONLY by calls within this script. This means if you have !?FU-5; triggers used in scriptX.erm and scriptY.erm, using !!FU-5:P; within scriptX.erm will trigger ONLY !?FU-5; inside scriptY.erm.

Also it gives a specific functionality.
Say you have two scripts: 23 and 456.

Script 23 has:
!?FU-34; #1
...
!?FU657;
!!FU-34:P...;
...
!?FU-34; #2
...

Script 456 has:
!?FU-34; #3
...
!?TM6;
!!FU-34:P...;
!!FU657:P...;
...
!?FU-34; #4
...

Now say timer 6 executed. The ERM interpreter will find a trigger body (!?TM6) in the script 456. So first !?TM6 section is executed. Call to FU-34 will execute function #3 and then #4 because both of them are located in the script that call is executed (script 456). Then call to FU657 will move the current call scope to the script 23 because the body of the global function 657 is located there. So now call to FU-34 will execute functions #1 and #2.

This means that all local functions are independent and may be cross referenced only through the global function calls.