The
  Way Of
    The Wombat
Logic and Loops

Contents

4.0 Logic and Loops
4.1 Boolean Logic
4.2 If, Elseif and Else Statements
4.3 For Loops
4.4 While Loops
4.0 Logic and Loops Underpinning all computer languages is the Boolean logic system.

4.1 Boolean Logic

For me to do a guide to Boolean logic and calculations in SLIC would be foolish, when Locutus, whose ability to explain the subject is far superior to my own, did such a comprehensive write-up here.

Reminder:
= make equal to (put the value of the right-hand-side into the left-hand-side)
== is equal to
!= is not equal to
> is greater than
< is less than
>= greater than or equal to
<= less than or equal to
|| or
&& and

(3 > 4) returns 0 -> untrue [3 is not greater than 4]
(12 != 55) returns 1 -> true [12 does not equal 55]
(12 || 13 == 7 + 5) returns 1 -> true [12 equals 12]



4.2 If, Elseif, and Else Statements

Pretty much the same as if statements in any programming language, and even in any spoken language.

HandleEvent(SleepUnit) 'kill_the_unit' pre { unit_t tmpUnit; tmpUnit = unit[0]; player[0] = unit[0].owner; if(player[0].cities > 10){ KillUnit(tmpUnit); } }
Reading through it should be understandable.
  • Define a unit variable.
  • Give it the value of the unit that has been put to sleep.
  • Using the built-in .owner variable, make player[0] the unit's owner.
  • IF statement. The game looks up the value of player[0].cities (the number of cities the player owns). IF this is greater than 10... "THEN" is represented as {
  • Kill the unit.
  • Close the IF statement.
  • Close the handler.

If Statements return 1 or 0 , true or false.
If the if statement is true (1) then the code inside inside the brackets is executed, otherwise it is skipped over.

This leads to elseif and else statements.

HandleEvent(SleepUnit) 'kill_the_unit' pre { unit_t tmpUnit; tmpUnit = unit[0]; player[0] = unit[0].owner; if(player[0].cities > 10){ KillUnit(tmpUnit); } elseif(player[0].cities < 3){ KillUnit(tmpUnit); } else{ Heal(tmpUnit); } }
This is a natural extension of the example above
  • ...[snip]...
  • IF statement. The game looks up the value of player[0].cities (the number of cities the player owns). IF this is greater than 10... "THEN" is represented as {
  • Kill the unit.
  • Close the IF statement.
  • What if the player hasn't got more than 10 cities?
  • "ELSEIF" is only tried if the IF statement above has failed.
  • so ELSE (not greater than 10) IF (less than 3 cities) THEN {
  • Kill the unit anyway.
  • "ELSE" (not greater than 10 or less than 3 cities) THEN{
  • Heal the unit;
Despite the difficulties explaining elementary logic, this should be comprehensible. The game tries out the IF statement first, if that fails, goes to the elseif statements, and if all the elseif statements fail, goes to the else block of code.

NB: You can only have one ELSE statement for every IF statement, but almost any number of ELSEIF statements.



4.3 For Loops

This is a way of executing a bit of code many times, without having to write it out many times.
Usually, this is done by having a counter which counts the number of times the loop has been done, and when it reaches the upper boundary you set, it stops.

The basic structure of a for loop is:

int_t i; int_t limit; // give a value to "limit" for(i = 0; i < limit; i = i + 1){ // code goes here }

This works thus:
  • i begins at zero (the first instruction "i = 0").
  • The code within the loop runs once, and i is incremented by one (as instructed by "i = i + 1")
  • The condition in the middle of the parentheses is checked. (In this case, "i < limit")
  • The value of i is checked against the value of your 'limit'. This could be a normal number, e.g. 8, or a variable, such as player[0].cities, or the product of a function, e.g. random(8).
  • If the condition is true, the loop is repeated once more, i is incremented one, etc.
  • If the condition is false, the loop is broken. The code starts reading beyond the closing bracket } of the loop.
Note, "for" loops can run in reverse, starting high, and decreasing to 0.

int_t i; int_t limit; // give a value to "limit" for(i = limit; i > 0; i = i - 1){ // code goes here }


To use the for loop in context, I'll return to the ongoing slaughter of sleeping units.

HandleEvent(SleepUnit) 'kill_the_unit' pre { unit_t tmpUnit; tmpUnit = unit[0]; player[0] = unit[0].owner; if(player[0].cities > 10){ KillUnit(tmpUnit); int_t i; for(i = 0; i < player[0].cities; i = i + 1){ AddGold(player[0], 500); } } else{ Heal(tmpUnit); } }

This time, if the player has more than 10 cities, the player is given 500 gold compensation for every city he owns.


4.4 While Loops

Can run similar to for loops, so that you run some code a certain number of times.
eg.

HandleEvent(BeginTurn) 'while_loop' pre { int_t i; i = 0; while(i < player[0].cities){ AddGold(player[0], 5000); i = i + 1; } }
This loop does the same as the for loop above, setting an initial value, a condition and an increment. You can see for loops are thus obsolete, since you can replace them all with while loops like the one above. However, for loops are more compact, and easier to read what is going on.

While loops have the advantage of being far more flexible.

You can use while loops when you want to identify one thing from many. This is equivalent to running a for loop until you find the one you want, and then breaking the cycle.


HandleEvent(BeginTurn) 'while_loop2' pre { int_t i; unit_t tmpUnit; GetUnitByIndex(player[0], i, tmpUnit); while(tmpUnit.type != UnitDB(UNIT_TANK) ){ i = i + 1; GetUnitByIndex(player[0], i, tmpUnit); } KillUnit(tmpUnit); }
GetUnitByIndex(int_t<player>, int_t, unit_t) is a function that lists all the units that the "player" owns, finds the one at position "int" in the list, and stores it as "tmpUnit". Remember that in computers, position 0 is at the top of the list, not position 1.

The while loop this time has a condition completely unrelated to "i", which merely serves as a counter through the units.
WHILE( the unit currently stored in tmpUnit is not a tank* ){
   Get the next unit
}
So at the end of the loop, you have a tank stored in tmpUnit, and then you kill it.

* What you are actually doing here is comparing the tmpUnit.type (an integer) with the position in Units.txt of the UNIT_TANK record. If these numbers are the same, the unit is a tank.

Be careful with while loops, because they can very easily become infinite loops. Imagine the situation if player[0] had no tanks. i would keep getting bigger, and eventually would get to the end of the list, and keep going. At which point, you would get loads of error messages saying "Invalid Unit" or "array index[0] out of bounds" or something like that. You are trying to find a unit that isnt there.
At this point, it would be wise to put an extra condition in there.

HandleEvent(BeginTurn) 'while_loop2' pre { int_t i; unit_t tmpUnit; GetUnitByIndex(player[0], i, tmpUnit); while(tmpUnit.type != UnitDB(UNIT_TANK) && i < player[0].units){ i = i + 1; GetUnitByIndex(player[0], i, tmpUnit); } KillUnit(tmpUnit); }
The while loops continues until it finds a tank or i equals the number of units that player has. At this point, the loop breaks. If there are no tanks, then tmpUnit will be the most recent unit they built - the unit at the bottom of the list.

Note the && in the while statement. The loop will keep going if BOTH those conditions are met, and will therefore break when EITHER of them is not met.
back close forward