tips inside PageTitle1.jpg
This is summarized basic knowledge in a script for Blitzkrieg 1. hearts.png

Basic knowledge of LUA of Blitzkrieg

This memo is about the basic knowledge of the LUA script which I wrote in 2006.
I learned Lua the hard way through self-education and a lot of trial and error, so I cannot guarantee that the memo is free of mistakes. Writing in English is difficult for me and some things may be hard for you to understand because of my broken English.
If so please refer to a tutorial written by someone who masters speaking English better than I do. hearts.png

-- Content of this memo --

About LUA script in Blitzkrieg
 
The general rule of Lua
Character
Character strings
Upper case and lower case
Comments
Operator
Relational operator
Logical operator
Variable
The reserved word

The constitution of the script
A conditional expression and an execution command
A conditional expression
An execution command
Parameter

The example of syntax of a script
(1) The example in which a conditional expression contains "and"
(2) The example in which a conditional expression contains "and" part-II
(3) An example with one conditional expression and two execution command
(4) An example with two conditional expression and two execution command
(5) An example with two conditional expression and three execution command
(6) An example with two sets of conditional expression and execution command

Repetition processing
for
repeat
while
break
Repetition processing not using "for", "repeat" or "while"
The example of repetition processing
Another example of repetition processing
The merit of repetition processing

How to use a table (and an array) in the Lua script       02 Mar 2014
What is the table
Script example of the table
A real example
What is the Array
Associative Array
A real example 2
Consideration about the information on the unit
Other application of array
Afterword


About LUA script in Blitzkrieg

Blitzkrieg uses a scripting language called Lua to control the AI and the game.
The Lua script used in Blitzkrieg differs somewhat from the general Lua language.
That is, the Lua in Blitzkrieg has not some functions that are available in the general version but then includes functions that were especially developed for the game.

Some commands in Blitzkrieg are controlled by the game engine but most functions can be controlled by the Lua script.
Since Lua script is text-based, you can create and edit it with text editor such as a "Note-pad".
The extension of the script file is lua.

A downside of the Lua script is that the language is sensitive to syntax errors. So any syntax errors will most likely cause the script to stop running at the position the error occurs in the script or even prevent the script from running at all.
Therefore in order to debug the script you will have to know some fundamental rules, formats etc.. hearts.png


The general rule of Lua

Character

Lua does not handle a double byte character, so only alphanumeric characters and symbols can be used. Double byte characters used in local languages (e.g, Russian, German, Japanese, etc.) can be used text strings on the condition that these strings are put between quotation mark, or used in a comment. hearts.png


Character strings

The character string must be put between single quotation marks ['] or double quotation marks ["].
For example, a script-area name are defined as "ToWin" or "Area_Axis".
The character that is used as a variable is not a character string. Therefore variables are not put between quotation marks.

According to Lua's official site, as for the single quotation mark and double quotation mark, each use was decided.
But, in Lua script for Blitzkrieg only the double quotation mark can be used. hearts.png


Upper case and lower case

In Lua, a character and a character string distinguish and interpret a upper case and a lower case.
For example, "ALL", "all", "All" are interpreted differently by Lua.
This rule is applicable for character strings, variables or function names. It does not apply to comments. hearts.png


Comments

From double dashes "--" up to the end of the sentence, Lua ignores the character written there and does not execute it.
So, double dash is used for comments. Please notice the double dash can begin with the midstream of the line. hearts.png


Operator

As for an arithmetic operator, a symbol is used.

  =   +   -   *   /   ~   ^   ==   ..

Various kinds of parentheses can be used as operators.

  (   )   {   }   [   ]

In addition, there are mathematical functions, such as trigonometric functions.
But, since the author seldom uses it, they omit. hearts.png

Supplement:
Two consecutive periods [..] are connection operators to connect two character strings.
The connection operator returns the character string that connected two character string.
If a concatenation operator is used well, repetition processing can be described more briefly.
An example will be explained later. hearts.png


Relational operator

Example:
A == B A is equal with B. A < B A is smaller than B.
A <= B A is below B. A > B A is larger than B.
A >= B A is more than B. A ~= B A differs from B. (A is not the same as B)  

Single equal sign "=" is used as an assignment operator.
  Example 1: A = 8             The numerical value 8 is assigned for the variable A.
  Example 2: A = "SPG"      The character strings "SPG" is assigned to the variable A.
  Example 3: x, y = y, x      The two values x and y are replaced. hearts.png


Logical operator

Three kinds of operators, "and", "or", and "not", can be used.

A and B It is A and B.
A or B It is A or B.
A not B It is A but not B.

A relational operator and the logical operator are used in a condition judgment.
If there is plural logical operator ("and", "or", "not"), it is calculated in order of the right side from the left side.

Example:
  A <=2 and B >= 3     When A is 2 or less and B is 3 or more, it is true (this formula is approved).
  A <=2 or B >= 3       When A is 2 or less or B is 3 or more, it is true (this formula is approved).
  A <=2 not B >= 3     When A is 2 or less and B is not 3 or more, it is true (this formula is approved). hearts.png


Variable

A variable can be used in Lua. Moreover, various operators (a relational operator and a logical operator) can be used for a variable.

Example:   local P = RandomInt (8);
The integer of the range of 0 to 7 which occurred at random is assigned to the variable P.

Bits of knowledge:
"local" is declaration of a temporary variable to use only in one script. The usage of such a variable is called local variable. When the script was finished, it is reset. Therefore, in the script except the script which defined a certain local variable, it cannot use that local variable. It is necessary to use the global variable to use one variable in a different script. If "local" is not used, it become no local variable, but it can use it as a variable. hearts.png


The reserved word

Since Lua of Blitzkrieg is using these, don't use the following character string for a variable etc. as an identifier.
If these character strings are used, Lua will not perform operation expected.
and break do else elseif end for function if in
local nil not or repeat return then until while

The function name used with a script in addition to this cannot be used as an identifier, either.
Furthermore, a function name, a variable, etc. which are used inside BK and which are closed-door cannot be used.
When a script does not work, I have the experience that came to work when I change the name of the script.

The character string which starts with a capital letter can be used as an identifier. In the script of Blitzkrieg, the variable from which the first character begins with a capital letter is used.
But, some identifiers of the capital letter which starts with an underscore "_" are reserved for internal variables.
For example, "_INPUT" etc. hearts.png



The constitution of the script

Generally, the script of Blitzkrieg points at a script file. But, this is not correct.
The script file is aggregate of the plural smallest scripts.
The smallest script performs only the control of the limited range.
On this page, the minimum script and the script which gathered are not distinguished.
Those plural smallest scripts are gathered, and it becomes one script file that operates the game.
The minimum script has the following composition.

function xxx() ------------ xxx is a name of the minimum script.
 [content of script] ------- A conditional expression and/or an execution command, etc.
end; ---------------------- The end of the script xxx. hearts.png


A conditional expression and an execution command

The general script contains the conditional expression and the execution command, and a minimum script is constituted by gathering them.
Conditional expression and execution command are comprised of a function and a parameter (argument).

There is a script which has only an execution command without a conditional expression.
Also, there is a script which has continuously plural execution command. These are often used and are not exceptional. The script that has only a conditional expression does no work, it is a meaningless script.

The characters of the head of a function are capital letters other than a number. Also, there are some functions / commands which contain plural capital letter in a function. For example, RunScript etc.. If a capital letter and a small letter are mistaken, the script will not operate.
Although it is case-by-case, the whole script may stop or it may stop at the position of an error. hearts.png


A conditional expression

A conditional expression is a formula which judges whether the set-up conditions are satisfied.

Example of a form:   if ( sss ) then

Here, sss is a function which returns a certain value (a certain value is acquired).
If the result of a conditional expression is Yes ( i.e. truth), a command written after "then" is executed.
If the result of a conditional expression is No ( i.e. false), this script ends without executing a command.
Or a command to execute at the time of false is executed.
In many cases, with the condition expression, the functions such as "the number of units" or "the state of the unit" are used. hearts.png


An execution command

Execution command controls the units and the objects by describing a function with a parameter.
In addition, a command to operate a game system is included in execution command.
For example: determination of victory or defeat, set the weather, display a message on the game screen, give the reinforcement units and so on. hearts.png


Parameter

A parameter also calls it an argument and adds detailed conditions to the execution command.
Almost functions have a parameter. There is the parameter which must not be omitted and the omissible parameter.

There are the following kinds of parameters and they are decided for each of function.
 ♣ Character string --------------------- The character string should be surrounded with the quotation mark.
 ♣ The character string as a variable -- The character string is not surrounded with a quotation mark.
 ♣ Numerical value (number) ----------

When a parameter should be numerical value, the function which returns numerical expression or a numerical value can be used as a parameter.

The form which allowed to the parameter is defined beforehand. For example, it will become an error if a character string is put into the place into which a variable, numerical expression, or a number should be put. In this case, operation of the whole script stops. hearts.png



The example of syntax of a script

The following is a syntax example of a typical script with a conditional expression and an execution command.

function xxx() --------- xxx is a name of the smallest script.[*1]
  if ( yyy ) then ------ yyy is a conditional expression
    zzz; --------------- Execution command zzzz is executed if yyy is true.[*2]
    Suicide(); --------- It is not executed again.[*3]
  end; ----------------- end of "if".
end; ------------------- end of "function xxx".

[*1] The file which collected plural small scripts of this is also called the "script." Extension of those file is ".lua".
        The parenthesis after the name is intended to put an argument. In many cases, it put nothing in a parenthesis.
[*2] Nothing will be executed if conditional expression is not true (that is, yyy is false).

[*3] After command zzz is executed once, it is not executed again. hearts.png

Other notes.
Semicolon ";" is a termination operator. You can omit it though the semicolon is attached with the script of BK product version. A semicolon is not attached behind each of "function xxx()" and "if (yyy) then."

Since there is a "Suicide()" command, in the above example, if the conditional expression yyy is false, this script is again performed for every definite period of time, and if a conditional expression is true, it does not perform again after it.
"definite period of time" is time specified by command "RunScript" for starting this script.

The indention is unrelated to the practice of the script.
An indention will be effective if you want to make it easy to find a mistake of the overs and shorts of "end". hearts.png



Sentence structure example including a condition expression and an execution command is shown below.
Although there are many variations in here, be aware that the examples posted here are not all. hearts.png


(1) The example in which a conditional expression contains "and"

function Example() ------------- An example with two kinds of conditional expressions.
    if ( xxx and yyy ) then ---- if both "xxx" and "yyy" are true, [*]
      [an execution command] --- an execution command is executed.
      Suicide(); --------------- this script is not repeated again.
    end; ----------------------- end of "if"
end; --------------------------- end of "function"

[*] If one of conditional expression "xxx" or "yyy" are false, this script do nothing.
If "and" is "or", the meaning of a conditional expression is as follows.     if either "xxx" or "yyy" is true....
If "and" is "not", the meaning of a conditional expression is as follows.     if "xxx" is true but if "yyy" is false.... hearts.png

(2) The example in which a conditional expression contains "and" part-II

The example of the script of the different sentence structure with a operation same as the above.

function Example2() -------------- 2nd example with two kinds of conditional expressions 
    if ( xxx ) then -------------- if "xxx" is true, the next line is executed
      if ( yyy ) then ------------ if "yyy" is true...
        [an execution command] --- an execution command is executed.
        Suicide(); --------------- this script is not repeated again.
      end; ----------------------- end of "2nd if"
    end; ------------------------- end of "1st if"
end; ----------------------------- end of "function"
hearts.png

(3) An example with one conditional expression and two execution command

If the conditional expression "xxx" is true, the 1st executive instruction is executed, and if the conditional expression "xxx" is false, the 2nd executive instruction is executed.
After all, any of 1st execution expression or 2nd execution expression are executed once.

function Example3()
    if ( xxx ) then ------------- if "xxx" is true, 
      [1st execution command] --- 1st execution command is executed.
      Suicide(); ---------------- 1st execution command is not repeated again.
    else  ----------------------- Or, if "xxx" is false,
      [2nd execution command] --- 2nd execution command is executed.
      Suicide(); ---------------- 2nd execution command is not repeated again.
    end;
end;
hearts.png

(4) An example with two conditional expression and two execution command

If the conditional expression "xxx" is true, the 1st execution command is executed and the 2nd execution command is not executed. If the conditional expression "xxx" is false and the conditional expression "yyy" is true, the 1st execution command is not executed but the 2nd execution command is executed. If both "xxx" and "yyy" are false, they do nothing.

function Example4()
    if ( xxx ) then ------------- if "xxx" is true, 
      [1st execution command] --- 1st execution command is executed.
      Suicide(); ---------------- 1st execution command is not repeated again.
    elseif ( yyy ) then --------- if xxx is false, and if yyy is true,
      [2nd execution command] --- 2nd execution command is executed.
      Suicide(); ---------------- 2nd execution command is not repeated again.
    end;
end;
hearts.png

(5) An example with two conditional expression and three execution command

If the conditional expression "xxx" is true, the 1st executive command is executed and the other executive command is not executed. If the conditional expression "xxx" is false and the conditional expression "yyy" is true, the 1st executive command is not executed but 2nd execution command is executed. In this case, 3rd execution command is not executed. When both a conditional expression "xxx" and "yyy" are false, the third executive command is executed.
After all, one of 1st execution command, 2nd execution command, and 3rd execution command is executed.

function Example5()
    if ( xxx ) then ------------- if "xxx" is true, 
      [1st execution command] --- 1st execution command is executed.
      Suicide(); ---------------- 1st execution command is not repeated again.
    elseif ( yyy ) then --------- if xxx is false, and if yyy is true,
      [2nd execution command] --- 2nd execution command is executed.
      Suicide(); ---------------- 2nd execution command is not repeated again.
    else ------------------------ if neither "xxx" nor "yyy" are true, 
      [3rd execution command] --- 3rd execution command is executed.
      Suicide(); ---------------- 3rd execution command is not repeated again.
    end;
end;
hearts.png

(6) An example with two sets of conditional expression and execution command

Two conditional expressions are evaluated independently, and each executive commands are executed if each conditional expression is true. These are repeated again if there is no Suicide().
This form is used to start two scripts simultaneously when this script (in this case, function Example6) is called from somewhere.

function Example6()
    if ( xxx ) then ------------- if "xxx" is true, 
      [1st execution command] --- 1st execution command is executed.
      Suicide();
    end; ------------------------ The first script is ended. 

    if ( yyy ) then ------------- if "xxx" is true, 
      [2nd execution command] --- 2nd execution command is executed.
      Suicide();
    end; ------------------------ The second script is ended. 
end;
hearts.png

Repetition processing

The repetition processing means repeating a set of conditional expression and execution command (or only conditional expression) several times, and performing. They may only be called a loop or loop processing.
There are "for", "while", and "repeat" as a command for a repetition.

There is a method of acquiring the same effect without using these commands (i.e. without using repetition processing). But, by that way, there is the demerit to which a script is complicated and its size becomes large. Repetition processing has a merit which can perform many processing by the brief script. hearts.png


for

When using "for", you have to specify the value of a loop counter. It is an initial value, the last value, and a step value. When omitted the step value, it is regarded as 1. In many cases, "for" is used in combination with "do".
When "for" is used independently, it may become a syntax error.
The follows are examples laying 32 mines around a designation point.
In this example, the designation point is specified by script area "MineField."

<code>
function PutMine()
local iScriptID = 400;                         -- iScriptID of Engineering car
  if (GetNUnitsInScriptGroup(iScriptID) > 0) then
    LayMine(iScriptID, GetScriptAreaParams ("MineField"));
    Suicide();
  end;
end;

function LayMine(iScriptID, X, Y)   -- ID of unit, XY coordinates of designation
  for dx = X-144, X+144, 96 do      -- X coordinates of designation point [*]
    for dy = Y-144, Y+144, 96 do    -- Y coordinates of designation point [*]
      QCmd(11, iScriptID, dx, dy);  -- execution command of laying maine
      DisplayTrace (" LayMine x%g y%g",dx,dy); -- for test
    end;
  end;
end;
</code>

[*] The point changes to four places. The step of the coordinate is 96. hearts.png


repeat

Repeat is combined with until and performs repetition processing. At "repeat", operation is determined in the last part.
That is, it is judgment of whether a repetition is performed or not.
Therefor, the command in a script is executed once at least. Refer to the GetUnitsIDInArea for an actual example.

<code>
function Example_repeat()
    repeat                             -- If during xxx = false, returns to here
      [execution command]
    until ( xxx );                     -- this is repeated during xxx = true
end;                                   -- if it becomes xxx = true, this will be end
</code>
hearts.png
 

while

"while" is used in combination with "do" like "for". When this function is called, conditional expression "xxx" is checked first. Operation is not started if a conditional expression is false. That is, at "while", it is judged in the top of the script whether it performs or not.

<code>
function Abc()
    while ( xxx ) do
      [execution command]
    end;
end;
</code>

The following is an actual example of the repetition processing using "while".
Engineering car places 36 mines in order toward the east (that is, to the X-axis) from the specified place.
Standard Engineering car expend all his resources, if a mine is placed 18 times (36 mines are placed).

<code>
function LayMine_X()
local iScriptID = 400;                        -- iScriptID of Engineering car
local mine = 0;                               -- a initial value of the placed mine
local X, Y = GetScriptAreaParams ("MF");      -- coordinates to begin to put a mine

  if ( GetNUnitsInScriptGroup (iScriptID) > 0 ) then 
    while mine < 18 do             -- A script is run if the placed mine is 18 or less
      QCmd(11, iScriptID, X, Y);              -- execution command to put a mine
      X = X+64;                               -- to change the position to put a mine
      mine = mine + 1;                        -- "mine" is a number of placed mines
      DisplayTrace (" Mine: %g", mine);       -- for test
    end;                                      -- end of "while"
    Suicide();                         -- it doesn't repeat, if placed mine become 18
  end;                                        -- end of "if"
end;                                          -- end of "function"
</code>
hearts.png
 

break

Although "break" is not directly related to repetition processing, it is a command often used in repetition processing. "break" finishes on the way the practice of the loop ("while", "repeat", "for") which it is included in, and moves the control to the next sentence of the loop. As a rule of LUA, you have to place "break" before "end".
Have you understood by explanation like this? In my case, time was needed in order that I might understand. Okay, let me show an actual example. This is a script of GetUnitsIDInArea.
GetUnitsIDInArea looks for iScriptID of the unit which is in "ScriptAreaName".
In this example, that range is set as 99 from 1. If a unit with iScriptID of this range is found, that iScriptID is outputted as return, then this script is ended.

<code>
function GetUnitsIDInArea(strScriptAreaName)
local X = 1;
local Max = 99;
  repeat
    if (GetNScriptUnitsInArea (X,strScriptAreaName) > 0) then -- [1]
      break;
    end;
    X = X + 1;
  until X > Max;        -- [conditional expression 2]
    if ( X > Max ) then
      X = -1;
    end;
  return X;
end;
</code>

When this script starts, iScriptID of a unit is evaluated by the conditional expression [1].
Have you noticed that "break" is under a conditional expression?
Since the following sentence, i.e., "end", is performed if a conditional expression is true, this script stops.
Please be aware that a script ends even if it does not evaluate all units.
In "ScriptAreaName", there might be a unit that has iScriptID which this script did not evaluated yet.
If it is necessary to evaluate all the units which are in "ScriptAreaName", you should not use "break". hearts.png


Repetition processing not using "for", "repeat" or "while"

It is possible. The simplest method is to enumerate commands of the necessary number.
But, that way is not realistic except for the case of the small number of commands.

Repetition processing can be performed by calling two scripts mutually.
Actual processing is performed with one of scripts.
Other script is used in order to call the script which processes.
When one of condition expressions of both scripts became false, the repetition is finished.
Since each script has Suicide(), one of scripts has always stop.

<code>
function Sample1()
    if ( xxx ) then                     -- condition expression 1
       [execution command 1]
       RunScript("Sample2",2000);
       Suicide();
    end;
end;

function Sample2()
    if ( yyy ) then                     -- condition expression 2
       [execution command 2]
       RunScript("Sample1",3000);
       Suicide();
    end;
end;
</code>

In order to use RunScript processing speed becomes slower than "for", "repeat", and "while" in this way.
But, it will be rare for processing speed to become a problem, probably.
This way does not contribute to the simplification of a script.
But, since it is the combination of a fundamental script, it may be easy to understand and debugging may be easy.

Although those are omitted in this example, when carrying out repetition processing, there are the important things.
It is the scheme of changing the execution command by the value of a loop counter and a loop counter.
Please refer to other actual example for those scheme. In order to transfer the parameter between 2 scripts, a global variable is used. hearts.png


The example of repetition processing

This is a memo about a script repeating operation.
The script without Suicide function repeats operation simply, but in many case it does not have utility value.
The script which carries out plural operations needs to have plural execution types.
But, when those operations are alike, a script may be simplified by repetition processing.

For example, assume the case where the unit of five groups is reinforced simultaneously.
ID (iScriptID) of the reinforced unit group are 100, 101, 112, 143, and 154.
If it is a conventional script, it may be written as follows.

<code>
function Reinf_A()
    LandReinforcement (100);
    LandReinforcement (101);
    LandReinforcement (112);
    LandReinforcement (143);
    LandReinforcement (154);
    Suicide ();
end;
</code>

This script will operate correctly. But, the execution type must add more, if the reinforced unit group increases more.
The following is an example of the script using "repeat" syntax.
This carries out the same operation as the above-mentioned script. hearts.png

<code>
function Reinf_B()
local i = 0;
local X = {100,101,112,143,154};
    repeat
        LandReinforcement (X[i]);
        i = i + 1;
    until(i > 4);
    Suicide ();
end;
</code>

This script has the loop index "i" and it increases from 0 to 4.
The index "i" refer to the table "X", and obtain a ID of the unit group which should reinforce.
"{ }" is a table in Lua. As for contents of the table, the index is sequentially put from the left.
For instance, when the table is referred with index=2, it returns 101. hearts.png


Another example of repetition processing

<code>
function EtherealBridge()
local num, totalnum = 901, 903;               -- ID of bridges, top:901 end:903
local MaxHP = 1500;                           -- maximam HP of each asphalt bridge
  while (num <= totalnum)                     -- the following processing is
  do                                          --  repeated until ID becomes 903.
   if ( GetNUnitsInScriptGroup(num) > 0) then -- if the bridge exists.
         HP = GetObjectHPs(num);              -- if the bridge whose ID of num
      if ( HP < MaxHP) then                   --                has damage.
        DamageObject( num, HP - MaxHP);       -- the bridge is repaired until 
      end;                                    --   bridge's HP become MaxHP.
    else                                      -- if bridge was destroyed,
        DamageObject( num, -MaxHP);           -- the bridge is perfectly repaired
    end;
    num = num + 1;                            -- next ID of bridges.
  end;                                 -- if all ID is processed, this script ends.
end;
</code>

This is an example used in the map included in the Blitzkrieg. In this script, the bridge is repaired when there is damage. In this example, the repeat operation is done by the while - do syntax. This script is executed repeatedly because there is no Suicide. hearts.png


The merit of repetition processing

GetUnitsIDInArea looks for ID of a unit. It is repeated about 100 times. But, the script is only written 14 lines.
Thus, when carrying out many simple operations, repetition processing has a merit.
The biggest merit is that a script becomes easy. This means that debugging becomes easier.
On the other hand, in repetition processing, processing speed becomes slow a little. hearts.png



How to use a table (and an array) in the Lua script

Draft: 06 Feb. 2014   Post: 02 Mar. 2014

This is a memo about using a table for the script of Blitzkrieg. I have the experience which wrote the script using a table. But I did not leave a memo. So, I put here the memo which written before.

A table is one of the data type, such as a numerical value and a character string. It can have plural data (a numerical value, a character string, a formula, etc.). By using an index, a table takes out data or can put in data. bit

     t = {2345, -7, "Txt", 16+4};   -- This is equivalent to the following

     t = { };                       -- Declare a table as a variable "t"
     t[1] =  2345;                  -- a numerical value, index 1 of table t.
     t[2] =  -7;                    -- a numerical value
     t[3] =  "Txt";                 -- a character string
     t[4] =  16+4;                  -- a formula

What is the table

A table is one of the means to structurize data. Blitzkrieg's script can use a table but its usage is not known widely.
A table is not omnipotent and is not a magic wand which offers a new function. In many cases, the function of the script using a table is realizable by other methods.
But a brief script will be realizable if a table is used expertly. I put here some script example which confirmed operation in Blitzkrieg. bit

Script example of the table

Note that the table X is not a local variable. If to do this way, the same table can be used with plural scripts.

X = {100,101,102,103,104};

function S1()
local i = 1;
    repeat
        DisplayTrace (" X=%g",(X[i]));
        i = i + 1;
    until(i > 5);
    Suicide ();
end;
  If this is run, it will be displayed as follows.
    X=100
    X=101
    X=102
    X=103
    X=104

That is, the table X is read in order. The index of the head of a table is 1.
Therefore, X [1] means the data of the head of the table X. bit

This is an example which changes the data (or input a data) of the table X. Be aware that the table X is the same as the table of the above-mentioned example. When run function S2, the data 999 is substituted for the 3rd field of the table X. The function S1 is run after that. So, it is displayed as follows. bit

function S2()
    X[3] = 999;
    RunScript("S1", 1000);
    Suicide();
end;
    X=100
    X=101
    X=999
    X=103
    X=104

A real example

This script reinforces five unit groups (iScriptID: 100,101,112,143,154 ) at once.
An execution speed is slower than the script which wrote five LandReinforcement functions for loop processing.
If the unit groups reinforced are 10, rewrite a table X and change "until(i > 5)"...
Or, do you write ten LandReinforcement? bit

function Reinforcement()
local i = 1;
local X = {100,101,112,143,154}; -- iScriptID of the units that will be reinforced
    repeat
        LandReinforcement (X[i]);
        i = i + 1;
    until(i > 5);  -- the number of units reinforced
    Suicide ();
end;

What is the Array

Array is a data structure which stores several data. Calvin which is an author of "BlitzKrieg Guide to Programming Lua functions" is saying the array the Table. But I use Array in this memo.

The data stored in array is called an element. Array can be nested. That is, we can put array into the element of array. A multidimensional array can be expressed by this technique. The example using a multidimensional array is described later.

For example, it is assumed that there are three one-dimensional tables. bit

    a = {1, 2, 3}
    b = {4, 5, 6}
    c = {7, 8, 9}

If to make a array from those, it is as follows.

    ARY = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}

This is an example which takes out the data of array. When the array ARY is the following.

    ARY = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}

    ARY[1][3] -- This means the 3rd data of the first element of array. 
              -- And this result is 3.
    ARY[2][2] -- similarly, this result is 5
    ARY[3][1] -- similarly, this result is 7

For example, you can check the data of arrangement by using DisplayTrace.

    DisplayTrace (" ARY:[1][3] = %g",ARY[1][3]);

The following is an example which changes the 3rd data of the first element into 33.

    ARY[1][3] = 33;

Associative Array

Array specifies an element by the numerical value. On the contrary, in an associative array, an element is specified by the data called a key. Generally, a character string is used for the key of an associative array.

The following is an example which has two data in a element of the array. The key of x and y is contained in the data of this associative array. And, note that the array X is not a local variable as is the case with the above-mentioned.

X = {{x = 16, y = 16},{x = 16, y = 6},{x = 16, y = 16},{x = 2, y = 16}};

function S3()
local U = 201;   -- 201 is iScriptID of a unit
        Cmd (0, U, 64*X[1].x, 64*X[1].y );
        QCmd (0, U, 64*X[2].x, 64*X[2].y );
        QCmd (0, U, 64*X[3].x, 64*X[3].y );
        QCmd (0, U, 64*X[4].x, 64*X[4].y );
    Suicide ();
end;

When this script is run, a unit will move four points in order.
This associative array was used for the patrol of the old Blitzkrieg map. bit

This is an example which changes the data(or input a data) of the array X.
When run function S4, the 3rd data of the array X is changed.
The function S3 is run after that. That is, a unit's movements course is changed. bit

function S4()
    X[3] = {x = 16, y = 24};
    RunScript("S3", 1000);
    Suicide();
end;

Let's return to a previous memo.
There were an example of two arrays and an example which changes a part of the data.

-- Example 1
ARY = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}  -- data before being changed
      ARY[1][3] = 33;                    -- data is changed by this

ARY = {{1, 2, 33}, {4, 5, 6}, {7, 8, 9}} -- a result of having changed data

-- Example 2
X = {{x = 16, y = 16},{x = 16, y = 6},{x = 16, y = 16},{x = 2, y = 16}}; -- before
      X[3] = {x = 16, y = 24};           -- data is changed by this.

X = {{x = 16, y = 16},{x = 16, y = 6},{x = 16, y = 24},{x = 2, y = 16}}; -- after 

Note that the forms which change data differ in two examples. Because the array of example 2 has the key to x and y, it is using the format that is different from example 1. bit

A real example 2

I released the demonstration map named AutoSearch before in May, 2010. This finds the enemy outside a field of view, and attacks it automatically. This script operated as expected. But, this script was too complicated and its size was also too large.
By using array, I expect that a script can be made more simpler and smaller. The following is attempt for that preparation.

I put an unit's position and unit's information into array. I name this array "U" and assume the unit's number to be 5.
I decided the unit's ID (iScriptID) of the head in this array is 301. For example, the unit's data of iScriptID=305 is put in the 5th of array. I selected the unit-state as an unit's information. I will reconsider later about an unit's informations. bit

-- U[][1] x-coordinate of a unit,
-- U[][2] y-coordinate of a unit,
-- U[][3] unit's information (unit's state)

U = {{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
-- Array which does not still have data

The example which inputs the data of the unit of iScriptID 301 only.
In this example, the routine which displays the inputted data is contained. bit

function DataInput301()
local x, y = GetObjCoord(301);  -- unit's position

    if x > 0 and y > 0 then   -- It checks that the unit of iScriptID=301 exists
        U[1][1] = x;
        U[1][2] = y;
        U[1][3] = GetUnitState(301);
        DisplayTrace (" Data for ID=301: %g, %g, %g",U[1][1],U[1][2],U[1][3]); --*
        Suicide();
    end;
end;
-- * The example which checks the data of array

In my plan, the array U should have data of five units. But, I am not going to write the five above-mentioned scripts.
I input the data of five units into the array U using loop processing. I guess that the number of units required for a practical small map will be twenty or more.

When the unit's information is input to the array U, a unit's existence is checked. If it is going to input the data of the unit which does not exist, the data in the array U will still be 0. Therefore, if the data is 0 when the data of a unit is taken out from the array U, it means that it was destroyed or the unit has not been reinforced yet.

function DataInput()
local j = 1;

    repeat
    local ID = j +300; -- iScriptID of the unit
    local x, y = GetObjCoord(ID);
        if x > 0 and y > 0 then
            U[j][1] = x;
            U[j][2] = y;
            U[j][3] = GetUnitState(ID);
        DisplayTrace (" Data for ID=%g: %g, %g, %g",ID,U[j][1],U[j][2],U[j][3]);
        end;
            j = j + 1;
    until(j > 5);
    Suicide ();
end;

The above-mentioned script can be written as follows. bit

function DataInput()
local j = 1;
    while (j <= 5) do
    local ID = j +300;
    local x, y = GetObjCoord(ID);
        if x > 0 and y > 0 then
            U[j][1] = x;
            U[j][2] = y;
            U[j][3] = GetUnitState(ID);
        DisplayTrace (" Data for ID=%g: %g, %g, %g",ID,U[j][1],U[j][2],U[j][3]);
        end;
        j = j + 1;
    end;
    Suicide ();
end;

By using such array, we can know where a unit is and what it is doing. I guess that the information can give quasi-intelligence to an AI unit. However, in order to get the information of the unit, we have to know its script ID.
As the method, there is the way of checking array one by one and the other ways.
But those are not mentioned here because it is not the theme of this memo. bit

Consideration about the information on the unit

In the above-mentioned example, the array included a unit's information.
But, it has not been verified yet whether this information is useful.
If the unit's script-ID is known, the unit's information of the following can be acquired by using a function.

coordinate: it can get with a GetObjCoord function.
unit-state: it can get with a GetUnitState function.
direction:  it can get with a GetFrontDir function.
ammunition: it can get with a GetNAmmo function.
formation:  it can get with a GetSquadInfo function.

The unit on the map moves with progress of the time and does some actions.
And so, be careful that they may not be the newest information, even if an array updates data at fixed periods. bit

On the other hand, there is the information which is not provided by only the unit's script ID.
Let's list up some of those.

Unit-type: This may be useful. But, there is no function which can acquire a unit type.

A GetNUnitsOfType function returns only the number of applicable units.

Capability (performance) of a unit: The index of the unit's assault capability and protective capability. (See below *1)

Unit's name: The military names (platoon, squadron, battalion etc.).

I will not adopt it because I think that this information is not so useful for execution of missions.

(*1) I wrote the memo about the capability index of a unit in September, 2008.
That memo remarked that the sum of the front-armor's thickness and the main gun's penetration capability may be appropriate as an index which shows a unit's overall capability. But, the usefulness of this index was not evaluated enough till now. bit

Other application of array

This is an example which gives the destination point to a unit by using an array.
In this example, the array has eight kinds of the destination points. This script was simplified for illustration.
So, I do not comment by force about the merit and demerit of this way. bit

function Alert()
local AI = 108;                          -- iScriptID of AI unit
local X0, Y0 = GetObjCoord (AI);         -- coordinates AI unit
local R = 20*64;                         -- Moving range by VIS coordinates
local P = {
{x =X0-R, y =Y0+R},{x =X0-R, y =Y0},{x =X0-R, y =Y0-R},{x =X0, y =Y0-R},
{x =X0+R, y =Y0-R},{x =X0+R, y =Y0},{x =X0+R, y =Y0+R},{x =X0, y =Y0+R}};

    if Res >= 2 then       -- see note*  Res = from 0 to 7
        j = Res -1;        -- j = 1 to 6
        Suicide();
    elseif Res < 2 then
        j = Res +7;        -- j = 7 or 8
        Suicide();
    end;

    Cmd (0, AI, P[j].x, P[j].y );
end;

-- note* Res is a code (from 0 to 7) which orders a destination place to an AI.
--       When alert was given, Res is generated with other scripts. 

Afterword

If I make the AutoSearch version 2, an important thing will be a script which gives more appropriate judgment to AI.
A table or an array is one of the mere tools for the script. Although there is a still more interesting example about an array, I will not mention any further because it is the purpose that this memo summarizes the information about a table (and an array).

Hope it helps. bit



knowledgeLUA