StarGraft ASM Compiler - ver .55

Put your PseudoCode here:

(Click here for a Quick Reference; Beginners read below)


Notes and Instructions: PseudoCode Syntax:

Right now there are only 2 types of statements: "Actions" and "special form" statements (like 'if's and 'for' and 'while' loops). See also all the variables you can use.


Actions - All actions look something like this: action-name(argument1,argument2);
The semi-colon terminates it, and (usually) the result of an action is assigned to the first argument (like in normal assembly). For example, add(HITPOINTS,KILL_COUNT); will add the current unit's kill count to its hitpoints. Here's a list:

add(arg1,arg2); - arg1 can be any symbolic variable (i.e., not a number) and arg2 can be any variable or a number (decimal, no need to mess with hex or anything :). Examples:

add(HITPOINTS,10); adds 10 to the selected unit's current HP.
add(HITPOINTS,SHIELDS); adds the current unit's shield amount to its HP (shield amount is unchanged; only HP is assigned the sum)
add(ENERGY,ACT_VAR); adds the ACT_VAR to the current unit's energy count. (ACT_VAR is the action variable input in the Stargraft button)

subtract(arg1,arg2); - same format as above. Examples:

subtract(HITPOINTS,10); subtracts 10 from the selected unit's current HP.
subtract(HITPOINTS,SHIELDS); subtracts the current unit's shield amount from its HP (shield amount is unchanged; only HP is assigned the difference)
subtract(ENERGY,ACT_VAR); subtracts the ACT_VAR from the current unit's energy count. (ACT_VAR is the action variable input in the Stargraft button)

assign(arg1,arg2); - assign the value of arg2 to arg1. Arg1 must be a symbolic (duh), arg2 may be a number or symbolic. ('Assign' means give the value of arg2 to arg1 -- like "set arg1 to arg2"). Examples:

assign(HITPOINTS,50); sets this unit's HP to 50 exactly.
assign(ENERGY,SHIELDS); sets this unit's energy count to its current shield count. (shields remain the same; only energy is assigned the value)
assign(SHIELDS,MAX_SH_0); sets this unit's current shields count to the marine's maximum shield count (the marine is unit number 0, so MAX_SH_0 refers to its max shield value)

set(SWITCH,arg2); - arg2 can be any number (but not a symbolic variable). You can use other variables for the first argument, but I can't guarantee that it will work (use assign() if you want to set another variable; this one is special because it has to bit shift). This right here sets SWITCH number (whatever you put in arg2). Only works for the first 32 switches (the pre-Broodwar ones). Examples:

set(SWITCH,1); set the second switch to the "on" state. (switches start counting from 0, so the first would be 0)
set(SWITCH,10); set the 11th switch.

clear(SWITCH,arg2); - same format as above.

clear(SWITCH,1); clear the second switch to the "off" state.
clear(SWITCH,10); clear the 11th switch.

toggle(SWITCH,arg2); - ditto the format again.

toggle(SWITCH,1); toggle the second switch (if it was "on" then turn it "off", if it was "off" then turn it "on")
toggle(SWITCH,10); toggle the 11th switch.

order(arg1); - This action makes the unit "do" order number (whatever arg1 is). E.G., order(0); will make the unit die (order #0 is die -- see orders.dat). You can also use symbolic variables, so order(ENERGY); will make the unit do whatever order corresponds to its energy count at the moment. :) A more useful version might be order(ACT_VAR);. (valid values are like 1-189 or something like that; see orders.dat in Arsenal III for a full list) Some orders don't work (they'll do nothing). This action will always bring up a targeting cursor and you have to select a target before it carries out the action. Examples:

order(0); when your action fully completes you will get a targeting cursor. After selecting a target for the unit it will die (since die is order #0).
order(ACT_VAR); same as above, but the unit will do whatever order number is in the ACT_VAR (input in StarGraft).

action(arg1,arg2); - This action is special. The first argument it takes is the offset to a "built-in" action in Starcraft (you can get these offsets from an older version of Stargraft). Value in decimal. The second argument is optional, but if you include it, it is the ACT_VAR you want to give to this "built-in" action funtion (Act Fn) you are using. This action will "execute" the internal Starcraft action, optionally with the ACT_VAR. E.G., action(4699376,10); is equivalent to executing the "cloak" action with the action variable 10, just as if you had made a button do that in SG. (4699376 is the offset of the cloak function) You can use this action to "compose" built-in actions with your own little additions. You can get an older version of SG to grab Act Fn offsets off of at SCER, but here are a couple of them:

4699376 - cloak. (both ghost and wraith)
4699552 - decloak. (ditto)
4697568 - train unit (unit in ACT_VAR). This is the normal training function for terran and protoss buildings.
4698912 - construct terran building. (building number in ACT_VAR)
4699072 - morph into building. (building number in ACT_VAR)
4698976 - warp in protoss building. (building number in ACT_VAR)
4699248 - larva morph into unit. (unit in ACT_VAR) Normal unit training function for Zerg larva.
4699248 - morph into unit. (unit in ACT_VAR) Normal morph for hydra to lurker or mutalisk to guardian or devourer.
4697920 - build subunit. (subunit in ACT_VAR) Normal for building scarabs in reavers or interceptors in carriers.
4698768 - stimpack.
4697712 - stop command
4698000 - generic "use technology" spell casting action function. (tech number in ACT_VAR)

There are a lot more. But I am not sure if they all (or any of them) work. I have not tested this at all so use at your own risk. :) Here are some examples:

action(4698000,19); if this works, it should make the current unit cast psi storm (tech number 19).
action(4698768); if this works it will give the unit a stimpack. (Note: if the second arg is omitted then it is assumed to be 0)
action(4699248,ACT_VAR); if this works it will make the unit morph into whatever unit equals the ACT_VAR that you passed in through SG. (Any symbolic variable will work for the second argument, but not the first; it must be a decimal offset)
action(4697712); makes the unit stop

More to come. Just lazy right now. :) I'll take suggestions.


Special Form Statements - All special form statements are fully enclosed in curley brackets. Right now you can not nest special form statements within each other. (e.g., you can't put an if within an if or a while within a for loop; the only things allowed inside are actions)

if - The 'if' statement looks like this:

{if(predicate[argument1,argument2])
action1();
action2();
.
.
.
actionN();
}

(Again, whitespace is ignored, so format however you like) If the predicate is TRUE then it will do all the actions (which are just statements like those explained above, nothing different). Otherwise it just skips over all of it. Reminder: YOU CAN NOT HAVE EMBEDDED IFs. At least not yet. And only 1 predicate per if please.

Predicates look like this: predicate[arg1,arg2]. Here are all of 'em so far:

eq[arg1,arg2] - true if arg1 = arg2. Arg1 must be a symbolic variable. Arg2 can be a number or symbolic variale. Examples:

eq[HITPOINTS,MAX_HP_1] this is true if the current HP of the unit is equal to the max HP of the ghost (unit number 1);
eq[SHIELDS,ACT_VAR] this is true if the current unit's shields is equal to the ACT_VAR input in Stargraft.

ne[arg1,arg2] - true if not equal.

ne[HITPOINTS,MAX_HP_1] this is true if the current HP of the unit is not equal to the max HP of the ghost (unit number 1);
ne[SHIELDS,ACT_VAR] this is true if the current unit's shields is not equal to the ACT_VAR input in Stargraft.

gt[arg1,arg2] - true if arg1 greater than arg2.

  gt[HITPOINTS,MAX_HP_1] this is true if the current HP of the unit is greater than the max HP of the ghost (unit number 1);
gt[SHIELDS,ACT_VAR] this is true if the current unit's shields is greater than the ACT_VAR input in Stargraft.

gte[arg1,arg2] - greater than or equal to.

gte[HITPOINTS,MAX_HP_1] this is true if the current HP of the unit is greater than or equal to the max HP of the ghost (unit number 1);
gte[SHIELDS,ACT_VAR] this is true if the current unit's shields is greater than or equal to the ACT_VAR input in Stargraft.

lt[arg1,arg2] - less than.

lt[HITPOINTS,MAX_HP_1] this is true if the current HP of the unit is less than the max HP of the ghost (unit number 1);
lt[SHIELDS,ACT_VAR] this is true if the current unit's shields is less than the ACT_VAR input in Stargraft.

lte[arg1,arg2] - less than or equal to.

lte[HITPOINTS,MAX_HP_1] this is true if the current HP of the unit is less than or equal to the max HP of the ghost (unit number 1);
lte[SHIELDS,ACT_VAR] this is true if the current unit's shields is less than or equal to the ACT_VAR input in Stargraft.

Here are some sample if statements:

{if (eq[HITPOINTS,SHIELDS])
subtract(HITPOINTS,10);
}
if the unit's HP equals its current shield amount then subtract ten from its HP.

{if (lt[ENERGY,250])
assign(ENERGY,250);
add(SHIELDS,1);
subtract(HITPOINTS,10);
}
if the current unit's energy count is less than 250 then set its energy count to 250, add 1 to its sheilds, and subract 10 from its HP.

{if (gte[HITPOINTS,11])
assign(MAX_HP_0,HITPOINTS);
order(0);
}
if the current unit's HP is greater than or equal to 11 then set the max HP of all marines on the map to the hit point value of the current unit. (remember, marines are unit number 0). Then make give this unit a targeting cursor which will make it die when it selects a target. :)

for - the 'for' loop statement looks like this:

{for(arg1)
action1();
action2();
.
.
.
actionN();
}

The for loop will do all the actions in the braces X times, where X = arg1. For example, for(10) would go through the actions 10 times. Nothing fancy. You can use symbolic variables as arg1 also. Examples:

{for (20)
add(HITPOINTS,1);
}
add 1 to the unit's HP 20 times.

{for (HITPOINTS)
subtract(SHIELDS,1);
add(ENERGY,1);
}
subtract 1 from the unit's sheilds and add 1 to its energy for each point of HP it currently has. So if its current HP was 20, it would repeat 20 times and thus subtract 20 from its shields and add 20 to its energy.

while - the 'while' loop statement looks like this:

{while(predicate[arg1,arg2])
action1();
action2();
.
.
.
actionN();
}

The while loop will keep repeating all the actions inside its braces until the predicate is no longer true (if it was never true to begin with then no actions ever get executed). predicate is the same as the predicates you used for the if statement. For example while(gt[HITPOINTS,10]) will keep repeating its actions until the hitpoints of the current unit are not greater than 10. (Be careful! You might make an infinite loop :) Examples:

{while (ne[HITPOINTS,1])
subtract(HITPOINTS,1);
add(SHIELDS,1);
}
while the current unit's HP is not equal to 1, then subtract 1 from its HP and add 1 to its shields. (Note that eventually its HP will get down to 1 because during each loop we subtract 1 from it)

{while (gte[SHIELDS,10])
add(ENERGY,10);
subtract(SHIELDS,ENERGY);
}
while this unit's sheilds are greater than or equal to 10, add 10 to its energy and then subtract its energy from its shields. (Again, hopefully its shields will get down below 10 from subtracting its energy eventually so we don't get into an infinite loop)


Variables - And here are all the symbolic variables that you can use in your actions:

ACT_VAR - This is the value of the action variable input in Stargraft
HITPOINTS - hit points of the current unit.
SHIELDS - sheilds of current unit.
ENERGY - duh.
KILL_COUNT - number of kills this unit has.
UNIT_NUM - units.dat number of current unit.
STIM_TIME - units.dat number of current unit.
TEAM_COLOR - team color of current unit (0-7 are "normal" and then there's 8-11 or something that are decent, like green, light blue, etc., and the rest are pretty messed. See a palette for more info)

Here's some stuff from the unit structure (for 0 <= N <= 227):

MAX_HP_N - maximum health of unit number N (e.g., MAX_HP_0 is the max HP of the marine, MAX_HP_1 is the max HP of the ghost). Note: this effects ALL units of that type, not just the currently selected one.
MAX_SH_N - max shields of unit N. (see units.dat to get unit numbers)
SH_ENABLE_N - shield enable flag of unit number N. (setting it to 1 means it uses shields, else don't use shields)
G_WEAPON_N - ground weapon that unit number N uses. (use weapons.dat number of weapon)
A_WEAPON_N - air weapon that unit number N uses.
SIGHT_N - sight range of unit number N. Max is 12.
ARMOR_N - armor amount of unit number N. (before upgrades)
MINERALS_N - mineral cost of unit number N.
PORT_N - smk portrait of unit number N.
GAS_N - gas cost of unit number N.
TIME_N - amount of time it takes to build unit number N.

Here's some stuff from the weapons structure (for 0 <= N <= 206):

WEAP_M_N - missile sprite being used by this weapon (N=weapon number)
 

There's a ton more... I'll have Ius add them. :)~ Or just ask. I'm not sure which ones people want, but I don't have time to add them all.

I have no idea to what exent this all works, but if you have any problems, please give me your CODE YOU ENTERED, not just "uh, starcraft crashed" or "it didn't assemble."

- DI

Source Code (perl): here (updated 3/27/00)
Offline Version: here (updated 3/18/00)