Tinybot 101

Tinybot is a robot designed specifically with size in mind. They are typically hard to read as they contain no comments, one letter variable names and possibly some complicated math.

Tinybots are often designed for tinybot contests, which usually have a size limit of some 500 bytes. Contest hosts usually require the bots to use the and  commands but subtract them from the final size of the robot.

Techniques
The smallest robot that can be made is six bytes long:

Init{}

However, this robot does not do anything. A fighting robot could be built in 65 bytes:

Init{lockgun(1) regcore(c)} c{gunleft(5) scan fire(dtcrobot*7)}

Note that bytes cannot be saved by switching to a while loop from a core event handler. If an infinite while-loop is used, the code still takes 65 bytes due to one extra row and the.

If you want to take this further, you can move the core routine into the init, and save 3 bytes by using 0 to refer to init, because function names and their indexes are interchangeable. You can save another byte by changing regcore to gosub, at the cost of having infinite recursion errors in long games. And you can save one more byte by using _dtcid, which returns -1 if nothing is detected, instead of using dtcrobot, at the cost of firing 7 at cookies and mines. Both those costs can be outweighed by turning the gun 9 instead of 5, giving you a 60 byte robot that beats the above by firing more often.

Init{lockgun(1) gunleft(9) scan fire(_dtcid*7+7) gosub(0)}

True equals 1, false equals 0
While creating tinybots, all means are typically used to achieve the smallest possible size. The sample bot above demonstrates a few of them.

Firstly, or even  should not be used as they are the same as 1. This is seen in the lockgun function. On the second line is the regcore-function. A one letter name is given to the section.

Left is shorter word than right
On the third line is used instead of, say,, which is three bytes longer than gunleft but in this case achives practically the same result. Note that even is one byte longer than gunleft. The gunleft takes 5 as its parameter, which is one byte shorter than, say, 10.

Old version helps and true still equals 1
Scan-functions cannot be shortened, but the firing routine is interesting. Effectively, fire(dtcrobot*7) roughly equates to...

if( _dtcrobot == _true ) fire(7) endif

in just one line and 16 bytes! The variable increments if a robot is seen, and resets to 0 otherwise, thus the formula yelds 0*7=0 when a robot is not detected and 7 or more when a robot is detected. Notice that the underscore is omitted from the dtcrobot system variable. This can be done because Robot Battle is backwards compatible with the version 1.3, which did not use underscores in front of system variables. Not nearly all system variables were present in Robot Battle 1.3 but the ones that were do not need the underscore.

Did you notice the bug in the longer code? Comparing a value to _true really compares it to 1, rather than performing a boolean comparison as you might expect. If you detect a robot a second time in a row, _dtcrobot becomes 2, and so on. If(2==_true) equates to if(2==1), which is false, and the robot does not fire. This bug can go unnoticed if the robot constantly turns its gun, ensuring that _dtcrobot will reset to 0 before it can fire again. But it can cause a headache if you find your robot locking its gun on an enemy and only firing once.

Even line breaks matter
An "invisible" way of saving bytes is to use Unix-format when saving the file: in Unix systems, the end of line is represented with a line feed (ASCII character 10) when in Windows world the end of line is represented with a carriage return + line feed (ASCII 13 + 10) combination. Most decent text editors allow the user to choose, which format to use when saving a file. Using only one character for line ends the tiny bot is shrunken down a byte per line.

Using an alias
Using an alias for system variables is another way to really crunch the size of your Tiny Bot. When you find that you need to use a particular system variable more than once, then you may want to consider this method. Basically, you just assign a single character variable name to hold the system variable, usually assigned right after a or at the start of the core.

Core{ scan d=scandist e=dtcenergy b=dtcbearing }

Now, if you only ned to use the system variable once, then this isn't efficient however, if needed twice(or more) then...


 * d=scandist : results in a 7 byte reduction in size for every instance this variable is used, after the first.
 * e=dtcenergy : results in a 8 byte reduction in size for every instance this variable is used, after the first.
 * b=dtcbearing : results in a 9 byte reduction in size for every instance this variable is used, after the first.

Examples
Here's a Tiny Rammer.

Example #1:

init{ lockall(1) regcore(c) regdtcrobot(r,1) } c{ gunleft(5) scan } r{ if(scandist<99) ahead(scandist) endif }

Example #2: 4 bytes less than example #1, -7 bytes for each use after the first for a total of 11 bytes saved!

init{ lockall(1) regcore(c) regdtcrobot(r,1) } c{ gunleft(9) scan } r{ d=scandist if(d<99) ahead(d) endif }

As you can see, the savings can add up, and this gives you more power to program versatility into your Tiny Bot.

Aliasing constants
You can also use alias' for constants that are used several times as well, but this is a little tricky. Only use an alias for constants that are 2 or more digits in length, and only if used more than 5 times. The real savings start when the constant has 3 digits or more.

Here's why...

c=9. No matter how many times I use the c I will still be 2 bytes over than if I had just used the 9, because of the added characters "c=".

c=22. Using "c" twice, I lose 2 bytes due to the length of "c=22cc" > "2222".
 * "c=22ccc" > "222222". Three times, Gains 1 byte
 * "c=22cccc" = "22222222". Four times, No loss or gain.
 * "c=22ccccc" < "2222222222". Five times, Reduced by 1 byte.

Now lets consider a 3 digit constant, like 360.
 * "c=360cc" < "360360". Two times, Gains 1 byte.
 * "c=360ccc" < "360360360". Three times, Reduced by 1 byte.
 * "c=360cccc" < "360360360360". Four times, Reduced by 3 bytes.
 * "c=360ccccc" < "360360360360360". Five times, Reduced by 5 bytes.

Formula to determine if the use of a constant(or system variable) alias going to reduce the size of a robot. (2 + NumberOfDigits + NumberOfUses) - (NumberOfUses * NumberOfDigits)

Postive number = gain in byte size. Negative number = loss in byte size.

Shrunken logical operators
Yet another way of saving bytes, is to use shrunken logical operators. This works by replacing the two-byte logical operators such as == or && with their 1-character equivalents that the game internally uses.

Using modulus (remainder) for angle arithmetic
Many sample robots use a function called MinDegreesRight to find the difference between two headings. This long function can be shortened to:

(b-a+540)%360-180

This returns number of degrees to turn right to get from heading a to heading b, or to turn left to get from b to a. 540 (360+180) is needed instead of 180 because the modulus/remainder operator (%) behaves differently with negative numbers, which we want to avoid.

Size vs. performance
Creation of a tiny bot is balancing between the size and performance. The bot in the example would probably not do very well as it does not move to evade missiles and does not lock to an enemy but always keeps rotating its radar. Implementing either of these features would add some ten or fifteen bytes to the size but would also increase the performance drastically.

Teams
Some tinybot teams have also been created. As using the radio is very inefficient considering the size of the code, various other teaming methods have been developed. They are not bullet-proof and sometimes can hurt the bot itself, but a team of bots usually beats lone bots even if they would be better in 1-on-1 matches.


 * Energy : A popular method is to keep the energy in the multiple of some number, like 7. If a robot is hit and (energy % 7) does not equal 0 anymore, it shoots out a missile to get rid of the extra energy. The dtcenergy variable is in a key position when deciding if a detected robot is an enemy or not.
 * Heading : Keeping the heading to some certain degree is another popular method: in this case the bots compare variables to identify if a detected bot is a friend or foe.
 * Location : The bots could also decide not to shoot a bot that, for example, lies in exactly the opposite corner of the arena. They could also position initially so that they do not even scan the section where the other team member is, fighting kind of back-on-back.