DROIDARENA

ROBOT SCRIPTING LANGUAGE v1.2

 

 

DECKER'S MANUAL

 

INDEX

  1. Basics
    1. Registers
    2. Constants
    3. Events
    4. Functions
    5. Commands
  2. A Simple Script
  3. Registers and constants
    1. Robotid
    2. Position
    3. Message
    4. Numeric
    5. Boolean
    6. Behaviors
      1. Fight
      2. Scout
      3. Sniper
      4. Assassin
      5. Berserker
    7. Validity
    8. Remarks in RSL
    9. Doll Register
    10. RSL Registers
  4. Events
    1. ATKD
    2. ATXXX
    3. DLIM
    4. DLOS
    5. DPIK
    6. DOLL
    7. EAPP
    8. HELP
    9. INIT
    10. MSGR
    11. NEXT
    12. POSI
    13. RAPP
    14. SEEP
    15. SEEE
    16. STEP
    17. WALL
  5. Properties
    1. ATPR
    2. BHVR
    3. DMLT
  6. Commands
    1. AAID
    2. ATAK
    3. CALL
    4. ESCP
    5. FRND
    6. FLEE
    7. FOLL
    8. GOTO
    9. HALT
    10. IFBF
    11. IFBT
    12. IFEQ
    13. IFFR
    14. IFGT
    15. IFHI
    16. IFIN
    17. IFLO
    18. IFLT
    19. IFNE
    20. IFNF
    21. IFNV
    22. IFVA
    23. IFVI
    24. ISEQ
    25. LOG
    26. SHOT
    27. SMSG
    28. SOS
    29. TEST
    30. TURN
    31. VAL
    32. VISI
    33. WAIT
  7. Functions
    1. _ADD
    2. _DIV
    3. _MUL
    4. _SET
    5. _SUB
    6. ALLY
    7. BSET
    8. CNAM
    9. COPY
    10. CPID
    11. CPOS
    12. GATR
    13. GDIS
    14. GPOS
    15. GRPS
    16. INVA
    17. LSMG
    18. LRID
    19. NEAR
    20. QBHV
    21. SNMY
  8. Sub Routines
  9. Advice
  10. Planned Features
  11. Version Info
  12. Examples



I. Basics

Hi. My name is Konrad, and I would like to give you a quick overview on basic programming theories, and the meanings of a few expressions that you will meet throughout playing the game.

If you ever did a little bit of programming, you could as well skip this part, although reading it won't hurt you. If you do not understand a term used in this manual, just turn back here, you will probably find it.

I am going to talk generally about basic terms of most programming languages bending their explanation towards RSL.

Before you get too scared of the material that's about to come - a driver's license is ten times worse and harder than understanding what I am about to tell you, so read on.

I am not teaching you how to program, I don't find myself capable of that at all, but I'm going to tell you what terms like registers, constants, events, functions, commands and other weird words mean on a level that will be sufficient for you to have an idea about what I am going to try to tell you in the following chapters.

Ok, lets start with registers.

 

Registers

Imagine registers as little containers that can contain anything you put in them. Although I am using the term registers, because RSL uses this term as well, these are usually referred to as variables. You usually put data in registers. However, it matters what type of data you put in them.

One register is usually meant to hold one specific kind of data. The most common types of data in most programming languages are:

- numbers

- strings (arrays of characters)

- booleans (can have a value of true or false, (1/0, yes/no)

Variables are called variables because their held values can vary. Their values can be changed. Same goes for registers, you can change their contents.

 

Constants

Constants are registers too, but you cannot change their values.

 

Events

When something happens, that is called an event. For example you click a button, then that triggers an event that will do what you expect it to do after clicking that button.

The main idea is that you do not have to check if the button was checked over and over again. Your events will execute when the event happens.

Functions

Think of functions as little boxes that output a result depending on the input.

If I have a function that converts conventional Arabic numbers (0..9) to Roman numbers, and I enter 4 as the input, it will return the value "IV". Hopefully. It should.

Pretty simple, right? Functions return a value based on their input value(s). Ok, that's just enough about functions.

 

Commands

This is pretty simple. Think of commands as functions that do not return a value. They just do stuff, whatever you want them to. Of course, commands can have input values as well.

Return to Top


II. A simple RSL Script

In Droidarena you program your robot using the RSL language that was developed exactly for this task. This chapter will give you an idea what an RSL script looks like.

Let's take a look what an RSL script looks like. Let me quickly tell you that RSL is case insensitive, which means that it doesn't matter if you use lowcase or highcase letters, they all are converte to highcase when your script is executed. From now on everything I say is about RSL - the Robot Scripting Language of Droidarena.

The following script is a really simple one:

[INIT]
	GRPS
	GOTO #ps

[POSI]
	GRPS
	GOTO #ps

It's only 6 lines, yet it makes your robot wander around.

How does it do that?

Remember we had a quick and most inexact yet sufficient definition for events. Events are the skeletons of an RSL script.[INIT] signs the start of an event, the end of an event is the next event, or the end of the script.[INIT] is an event that runs every time an arena fight begins. It can be used to set initial values, and even to kick your robot into motion.

There is another event in this script, [POSI]. [POSI] is executed when your robot reaches its destination, and is an abbreviation for OnPosition.

You can also see two commands there, GRPS and GOTO. GRPS is a function - it returns a value. GOTO is a command.Before we understand what they mean and do, we need an overview of how values are stored in Droidarena.Your robot's memory has place for different data. These data can be of any kind that is allowed in the game. You will learn more about RSL's data types, constants and registers in the next chapter.

HINT: If you ever programmed in 8088 Assembly, Droidarena treats all variables as if they were registers, in a very similar way like ASM does. You can read and write these registers.

In this case, we use the register #ps that always stores the Position of something. GRPS is an abbreviation for Get Random Position. GRPS finds a random Position on the map, and by the definition of GRPS, it loads this value into the register #ps.

GOTO has one parameter. We used #ps here. This parameter must be of Position type, so #ps is ok to use. Since #ps now contains the Position of a random spot in the arena, GOTO #ps will order our robot to go to this new random Position.

I can imagine you asking what happens if you do not use GRPS, what value does #ps have then, by default? You will find the answer in the next chapter, soon.For now, let's overview what happens to our script when run.

First of all, as I said, [INIT] will be executed. This means that all the commands following [INIT] until the next event or the end of the script will be evaluated and run. In this case [INIT] contains a command that will set a new value for #ps by finding a new random (accessible) Position in the arena, and one that will tell the robot to treat that Position as its destination. Let's say #ps contains the Position 37:12.

[POSI] will be executed when our robot reaches its destination. When is that? In the above example when it reaches 37:12.

You might have realized that [POSI] does exactly the same (had the same commands within) as [INIT] did. It looks for a random Position in the arena, loads that into #ps, and sets it as a destination with GOTO. The goal of [INIT] in our example is to trigger [POSI] - to give our robot a target to go to, and when it reaches this target, [POSI] could be executed. We could as well set our current Position in [INIT], and that would instantly trigger [POSI] for us, but I do not want to confuse you with that, and by the time you read this document, you will be able to do it easily.

Later, when it reaches the new destination, [POSI] will be triggered again, and a new random Position will be loaded into #ps, and the same thing goes all over again until the arena fight is over. Your bot will do nothing but walk up and down from one Position to the other. It will not engage in combat, and will not even fire back when attacked, so this robot is quite dumb, but this little script made it walk!

By adding more commands and events, we would be able to make our robot smarter. If you don't understand how the above script works, just read on, you will get it soon via other examples.

 

Return to Top


III. Registers and constants

By now you should have a dim idea about how RSL treats data. It stores them in registers. Each of these registers are meant to store one type of data, so let's talk about the different data types you will be using.

 

Return to Top


RobotId

In an arena fight robots are given numbers that they are identified by. This number is not the same as the 6 digit player id, this is a number that each robot is assigned once the fight begins.

RobotId will help you identify any robot. For example, if you are attacked by a robot, the event that is executed when you are attacked will automatically give you the RobotId of the attacker, so you can attack back or query its Position, or even give this id to your teammates asking them to help you out. You can do that easily, since when you attack it, you use the same RobotId that you were given when the attack happened.

If it's not too clear, just read on. Remember that RobotId is used to identify robots in an arena.

 

Position

Position is used to handle arena Positions. It is the same as using a pair of coordinates without actually knowing what these coordinates are. Remember that simple script we checked out in the chapter before this one? #ps is a Position type register, it can only store Positions.

 

Message

To exchange user defined messages between robots, you will be using Message type registers. They can contain any string. As you will see, you have the option to check what a message type register contains and act accordingly. You can use message type registers to taunt the enemy (never use bad words!), or to talk with your teammates, and execute a predefined plan for example.

 

Numeric

Numeric registers are generally used for counting values and storing these values. In RSL these numeric values are always integer values. An example of using a numeric register is when you want to count how many steps your robot made, or another more useful example is to check the distance between your robot's Position and another Position. All numeric registers are signed 32 bit number registers, which means that they can hold a value between -2147483648 and 2147483647. If you increase the highest value or decrease the lowest value, the result will wrap around, so -2147483648 - 1 will be 2147483647, but it is likely that you will not have to worry about that at all.

 

Boolean

Boolean registers store values which are TRUE or FALSE. These registers could be used as little flags (markers). For example, you could use such a register to quickly check if you have passed a specific event in the arena. This register type can be of a great use, read on for now, and see Boolean related examples later on to understand why. Although boolean registers store a TRUE / FALSE value they still have their validity. If a Boolean register is not valid, then its value will be disregarded just like it happens with all other registers. Read on to find out more about the validity of registers.

 

Behavior

Each robot in an arena is assigned a Behavior that can give the robot bonus points on specific properties like speed or defense at the cost of subtracting points from other properties. A Behavior register can have 5 different values. If a value other than these is used then the default value will be assumed. Let's dive a little into game design as well - after all RSL was meant to be a scripting language for Droidarena.

Fighter 

This is the default Behavior for all robots unless you set it to another value. Fighters do not have any pros nor contras.

Scout

A scout tries to gather information and tries to avoid conflicts. Modifiers:+30% speed,-20% damage, -10% defense.

Sniper 

A sniper prefers to keep a distance from the enemy. Available It receives +20% for accuracy,+10% for weapon and radar ranges, -10% for speed and -20% for defense.

Assassin 

An assassin will try to overrule its enemies by its quick strikes. It receives +10% for speed,+5% for weapon reload speed,+10% for damage,-15% for accuracy and -10% for defense.

Berserker   

A robot that has gone berserk will treat all robots as enemies, and will try to inflict as much damage as possible. It receives +30% for damage,-20% for defense and -10% for accuracy.

About the validity of registers (very important!)

All registers have a property called validity. Validity shows if the register contains a valid value or not. As an example, the #ps register does not have a valid value when you begin a fight (all registers start from an invalid state). The value of #ps will be valid when you (or any event or function) give it a value for the first time during the fight.

The following two script parts show you two examples similar to the one we already checked out.

[INIT]
	; #ps is not valid
	GOTO #ps
	; Since #ps was not valid, GOTO received an invalid
	; parameter causing it to not do anything
	; Here your robot does not have a destination

The following script is a lot better:

[INIT]
	; #ps is not valid
	GRPS
	; #ps has a valid value here
	GOTO #ps
	; Here your robot's destination is set to #ps

Of course you can use another command other than GRPS to give #ps a value.

There are cases when a register has a valid value, but if you try to give it a new value, and it is not possible, it will be invalidated.Use the functions TEST, IFVA, IFIN to verify the validity of registers, and INVA to force the invalidation of a register.

Look at the following example. Let's assume the player "Lizard" plays in the actual arena, but the player "MaxManiac" doesn't. See the function CNAM to understand why it works like this.

[INIT]
	; #id is not valid
	CNAM Lizard
	; #id has a valid value (Lizard's robot's RobotId)
	CNAM MaxManiac
	; #id has an invalid value since MaxManiac does not play

If you store the RobotId of a player in &id0 for example, and that robot is destroyed, &id0 does not automatically become invalid. It will store that value as long as it is not overwritten, however, if you use this &id0 register for a command that needs a working RobotId to work, the command will be disregarded, and most likely &id0 will not change. The following could be an example:

[INIT]
	CNAM Sally
	COPY #id &id0

[ATKD]
	ATAK &id0

Let's assume that Sally's robot is destroyed when our [ATKD] event is executed. Although &id0 contains a valid value - the RobotId of Sally's robot - since the robot is already destroyed, ATAK will not be executed.Robots that are destroyed become invisible automatically.

 

Remarks in RSL

In RSL - as you might have realized already - with the help of semicolons you can place remarks in your script. Always place comments on a line by themselves, do not use remarks on the same line of script after commands as they will interfere with the parsing of the command.

[INIT]
	; I could write anything here
	; as it all will be disregarded
	; when my script is executed.

The #dl register

The #dl register is a special kind of register. It is used to show if your robot owns the doll or not. According to this, the #dl register can contain a true or a false value. If your robot owns the doll, it is true. That is, it can be tested for validity. If the register is valid, your robot has the doll, if not, then it doesn't. The #dl register is not a boolean type register, it never has an actual value as other registers do, yet we can check its validity - but that's just enough for us to use this register very effectively.

RSL knows the following registers:

#me [RobotId] Always stores your own robot's id.
#mp [Position] Stores your robot's actual Position. (MyPosition)
#le [Position] Stores the Position left to your robot.
#ri [Position] Stores the Position right to your robot.
#fw [Position] Stores the Position ahead your robot. (Forward)
#bk [Position] Stores the Position behind your robot. (Back)
#mb [Behavior] Stores your robot's actual behavior.
#dl [Special] Shows if your robot has the doll. (valid or invalid)
#id [RobotId] General purpose registers
#ie [RobotId]
#ps [Position]
#bh [Behavior]
#ms [Message]
#nr [Numeric]
#bl [Boolean]
&id0-&id9 [RobotId] User registers
&ps0-&ps9 [Position]
&bh0-&bh9 [Behavior]
&ms0-&ms9 [Message]
&nr0-&nr9 [Numeric]
&bl0-&bl9 [Boolean]

Return to Top


IV. Events

In our early example with the simple RSL script we have met two events. This chapter is meant to tell you what other events exist, when they are executed, and what values they set if they do at all.

There are a few basic rules that apply to all the events in RSL:

1. They set register values only if you are using the event in your script. For example, if your robot sees a new enemy appear, it will only set #id to the RobotId of this new enemy if you have at least the following line in your script:

[EAPP]

2. For each player events are checked in a specific order. This order is important, because if there are many events occuring at the same tick, it might be useful to know which event is checked for first, and which one is the last one. Although your event scripts are executed when the event happens and your robot acknowledges it, if there are several events that change one specific register, it is a good idea to save registers using the COPY command, because they do not hold their values for a long time.

The event order is the following:

1. INIT
2. ATxxx
3. STEP
4. NEXT
5. WALL
6. POSI
7. SEEP
8. SEEE
9. EAPP
10. RAPP
11. DOLL

3. Events that are not on the above list are executed whenever the event that triggers the execution happens. For example, MSGR will trigger exactly when a message is sent to the player - in another player's run cycle, out of our run cycle - this is why it is hard to tell if other events execute before or after the above list of events. One thing is for sure: They execute either before or after the above events have been checked. To learn more about how you can tell the order of all events in your script, please see the GOTO command description along with IFHI and IFLO.

The events that are currently available in RSL are the following:

 

ATKD[#id]

OnAttacked: When the robot is attacked by an enemy it will execute and give you the RobotId of the attacking enemy in #id. The robot is considered to be attacked when it is SHOT, and the SHOT does not miss. A missing SHOT will not trigger [ATKD].

 

ATxxx

AtTick: Triggers at the specified tick. (ie. AT728 or AT13)

 

DLIM

OnDamageLimit: Runs when the damagelimit set by the DMLT property is reached. May run only once per arena. If you have several shields on your robot, they will try to absorb damage equally. If one of the shields' damage limit drops below the set value, DLIM is executed.

 

DLOS

OnDollLost: Executed when you lose the doll. This happens usually when someone shoots your robot, and half of the accuracy of the attacking weapon would still be enough to hit your robot. However, this will not do additional damage, but the doll will be tossed away to a random Position that is viewable from the Position of the doll, and is closer than 11 squares, but further than 3 squares.

 

DPIK

OnDollPickedUp: Executed when you pick up the doll. When the doll is picked up, it becomes invisible to every robot. Currently there is no way they can tell who has the doll to protect the doll owner.

 

DOLL[#ps]

OnDollVisible: If the doll can be seen, this event is executed. The event puts the doll's Position into #ps. If you reach the doll's Position, your robot will automatically pick it up. After it has been picked up, the doll is not visible, and DPIK is executed.

 

EAPP[#id]

OnEnemyAppearance: Triggered when a new enemy appears on the radar. The RobotId of this new enemy is put into #id.

To be more exact, EAPP is executed when an enemy who was not visible in the previous tick appears on your radar. Identical to RAPP, except it only works for enemy units.

 

HELP[#id]

OnHelpRequest: If a friendly unit is attacked and broadcasts an SOS! signal on the radio or sends a direct AAID command to your robot, it will trigger this event. #id is set to the id of the friendly unit asking for help. If [HELP] is triggered by SOS! then the #ie register will not be valid. If [HELP] is triggered by AAID then the #ie register will be valid, and will contain the RobotId of the target to be attacked.

 

INIT

Oninitialization: This is triggered when the battle begins in the arena. It can be used for setting properties, and making the robot start moving. (By default the robot does not have a destination to go to!)

 

MSGR[#id,#ms]

OnMessageReceived: #id is set to the sender of the message, #ms is set to the message sent. When a message is received, this event is triggered.

 

NEXT[#id]

OnNextTo: Triggered when the robot reaches a Position next to another robot. The id of the robot next to it is put in #id.

 

POSI

OnPosition: Triggered when the robot reaches its destination Position set by the GOTO, FOLL, ESCP or the FLEE command. POSI is executed when the target Position is reached. HALT and WAIT do not change the target Position of the robot, so when you issue HALT or WAIT, your robot will keep walking towards the target Position until it is reached once the HALT or WAIT command has no more effect on your robot.

A continous movement for your robot can be best achieved by using POSI. When POSI executes it is advised that you find another Position for it to go so it will keep on moving.

Note, that the target Position could be your own Position (#mp) that would trigger POSI in the next tick. Although it is the same Position, when you give a new target Position for your robot, it schedules POSI to execute once this Position is reached - no matter what Position that is.

Be careful when assigning target Positions to your robot (using the GOTO command). If the Position is an obstacle (WALL) then your robot will never be able to step onto that Position (actually it will not even bother walking there, as it is not possible) and that could cause POSI to not execute for the remaining time in the arena. This might be a problem when using CPOS (Convert Position), but if you prefer to use GRPS (GetRandomPosition), it will always return a valid, non-obstacle Position. POSI is generally the spine of your robot's movement if you will, but you could even create a script without checking POSI at all.

 

SEEE[#id]

OnSeeEnemy: When the radar scan sees an enemy it will automatically enter the id of that enemy into the actual enemy spool. This is executed at every tick. Check the event EAPP to see which one you want to use. The RobotId of the robot in question is put into #id. By default this event will return the RobotId of the enemy which is the farthest away from your robot. This default setting can be changed by using the ATPR property setting command.

 

SEEP[#ps]

OnSeePowerup: This event is triggered when the radar scan identifies a powerup in the arena. The type of powerup can never be determined. The Position of the powerup is put into the #ps register. To pick up a powerup, walk your robot onto the same Position as the powerup is on.

 

RAPP[#id]

OnRobotAppearance: Triggered when a new robot appears on the radar. The RobotId of this new robot is put into #id.

To be more exact, RAPP is executed when a robot who was not visible in the previous tick appears on your radar. Identical to EAPP except it works for both friendly and enemy units.

 

STEP

OnStep: Triggered at every tick.

 

WALL

OnWallAhead: Triggered if there is a wall in front of your robot. Useful if you want to use your own path finding algorythm, and lead the robot step by step.

 

Return to Top


V. Properties

 

Properties can have a huge impact on your robot's performance in the arenas. They can be set and changed any time within any of the events. It is recommended that you always set these properties in your [INIT] event before the fight begins.

 

ATPR

Parameter: A string ["weak", "strong", "close", "far", "lowhp", "highhp", "random"]. Default value is "far".

AttackPriority: Sets a priority for the robot to use when engaging multiple targets. The value you set to this property primarily affects what enemy RobotId SEEE will give you.

Weak - The robot with the least experience

Strong - The robot with the most experience

Close - The robot closest to your Position

Far - The robot farthest away from you but still visible

LowHP - The robot, which seems to be the most battle-worn

HighHP - The robot, which seems to be in the best shape

Random - Randomly chooses any robot that is visible

Example: 

[INIT]
ATPR weak

 

BHVR

Parameter: A string ["scout", "sniper", "assassin", "fighter", "berserk"]. Default value is "fighter".

Behavior: Defines the type of behavior the robot should follow, and enters it into #mb. See Registers and Constants - Behavior for detailed information.

HINT: If you enter a string that is not one of the above, #mb will still hold the value. Because of this, there is much more to BHVR, as it can store any string you want. The drawback is that when passing strings that are not one of the allowed values, the behavior of your robot will always default to fighter until you change it using a parameter that is acceptable.

Example: 

[INIT]
BHVR scout

 

DMLT

Parameter: A number from 0 to 99. Default value is 0.

DamageLimit: Sets a percentage. If your defense is damaged below this level, the DLIM event will trigger. If you set DMLT to 0, DLIM will never trigger, which is the default behavior.

Example:

[INIT]
DMLT 25

 

In RSL when using strings as parameters, you will see that strings are always the last parameters of a command. Because of this, it is not necessary to include brackets around strings. If you use brackets, the parameter will include the brackets as well. Example:

[INIT]
BHVR scout
; or another example could be:
SMSG &id5 This is my message to another robot.
; so the message is "This is my message to another robot."
SMSG &id6 "And this is to another."
; where the message is ""And this is to another.""

 

Return to Top


VI. Commands

Here is a list of commands that are available for you in the game. These do not set any of the registers automatically. They only take certain parameters and act accordingly, but they do not modify your robot's registers.

 

AAID <HelperId> <TargetId>

AskForAid: The command basically asks HelperId to aid your robot in taking out TargetId. HelperId needs to be an ally, TargetId must be an enemy robot. They both have to be operational. This command will execute a [HELP] event for HelperId, and sets HelperId's #id register to the robot requesting aid, and HelperId's #ie register to the robot to attack (TargetId).

[ATKD]
; assuming that &id1 has the RobotId of a friendly unit:
AAID &id1 #id

 

ATAK <RobotId>

Attack: This will Initiate an attack of the enemy mentioned until it is destroyed, it exits or it gets out of sight on the radar. It will be followed if there is no chance to shoot at it (because of obstacles or malfunction for example). This will also Initiate an OnAttacked ([ATKD]) event on the target robot when the ATAK command is issued. RobotId must be an enemy unit.

[EAPP]
ATAK #id

 

CALL <Subroutine>

Call: Continues execution by jumping to a user made subroutine or an event. Execution in the procedure where CALL is issued from will not continue! Parameter must include the name of the subroutine without brackets. Example: The line "CALL INIT" will cause your robot to execute anything that is set in its [INIT] event. If CALL runs into an infinite loop, your robot is instantly fired from the arena. Watch out for infinite loops! An infinite loop is when for example CALL calls the subroutine in which it resides. Example:

[INIT]
CALL INIT

 

ESCP <RobotId>

EscapeEnemy: Escapes a specific enemy robot by fleeing to a Position that is not seen by the enemy robot. This command changes the target Position of your robot, and basically acts like a GOTO command.

[EAPP]
ESCP #id

 

FRND <RobotId> <AllySub> <EnemySub>

IsFriendlyUnit: Verifies if the target robot (RobotId) is an enemy or an ally. If robotid is an ally, allysub is executed, if robotid is an enemy, enemysub is executed. Execution does not continue in the calling procedure after FRND. If you would like execution to continue, consider using the commands IFFR or IFNF.

[INIT]
LRID #id 1
FRND #id Ally Enemy
[ALLY]
; ally code here
[ENEMY]
; enemy code here

 

FLEE

Flee: Tries to go to a Position from which its original Position is not visible. In other words, it tries to take cover. This command changes the target Position of your robot, and basically acts like a GOTO command.

[EAPP]
FLEE

 

FOLL <RobotId>

Follow: Follows the target until it arrives at an adjacent Position next to the target. If the target is destroyed, POSI will be executed as if your robot reached the target. The following example follows Tom's robot only.

[INIT]
CNAM Tom
COPY #id &id0
[EAPP]
IFNE #id &id0 It_is_not_Tom
FOLL #id

 

GOTO <Position>

GoTo: Specifies a destination for your robot to move to. Your robot will automatically find the optimal path to the target position if there is such a path, and if the position is valid. When your robot reaches this destination, the [POSI] event is executed. If you issue more commands that affect the target Position where your robot is moving to (ie. GOTO, FLEE, ESCP, etc..) then the last of these commands will apply.

[INIT]
GOTO #mp
[POSI]
GRPS
GOTO #ps

 

If we have two GOTO commands issued in the same tick, the second one will apply:

[POSI]
CPOS 24 25
GOTO #ps
GRPS
GOTO #ps
; so the robot goes to a random Position

 

Also, if you have something like the following script, and POSI and SEEE are executed in the same tick:

[POSI]
GRPS
GOTO #ps
[SEEE]
FLEE

 

In that case according to the event order list - check the events section for the list - the last event checked will overwrite all previous target Position settings, and the value set under SEEE will apply.

However, some events are executed whenever another player sets it off - like [ATKD], see the following script as an example:

[POSI]
GRPS
GOTO #ps
[ATKD]
FLEE

 

In this case it is very difficult to tell which event will be executed as the last one of the two. If the RobotId of the robot that triggers [ATKD] is smaller than your RobotId, then [ATKD] is executed before, if it is larger than your RobotId, [ATKD] is executed after POSI.

To solve this problem, there could be several workarounds. One is that you keep track of your enemies using LRID, which although requires a lot of effort, it will let you control the flow of your script better.

There is an easier way to handle this problem through the use of the IFHI and IFLO commands. These will redirect execution depending on which RobotId is higher or lower. Please see the explanation of the two above commands for more details. RSL becomes a bit tricky here.

 

HALT <Number>

Halt: Shuts down the robot for a certain amount of time. This will turn the robot off for the given number of ticks. It will not emit any heat signals and will be seen as destroyed. If you previously had the doll, you will then lose the doll, or to be more exact, others will see it. This command may be used only once in a fight, any other uses of this command will be disregarded. 250 ticks before the end of the arena, all the HALT commands are cancelled.

Be careful when using HALT, as it instantly shuts your robot down - it will not be able to execute any commands following HALT!

[DLIM]
HALT 100

 

IFBF <Boolean> <TrueSUB>

IfBooleanIsFalse: Checks if the value of the Boolean type register (first parameter) is false. If it is false then it will continue execution in TrueSUB otherwise it will go on with the next command in the actual subroutine. If the register is not a valid one then the command will be disregarded and execution will continue with the next command in the actual subroutine. The following example checks if we have passed tick 500 in the fight yet:

[INIT]
BSET &bl0 FALSE
[AT500]
BSET &bl0 TRUE
[SEEE]
IFBF &bl0 WE_ARE_BEFORE_TICK_500

 

IFBT <Boolean> <TrueSUB>

IfBooleanIsTrue: Checks if the value of the Boolean type register (first parameter) is true. If it is true then it will continue execution in TrueSUB otherwise it will go on with the next command in the actual subroutine. If the register is not a valid one then the command will be disregarded and execution will continue with the next command in the actual subroutine. The following example checks if we have passed tick 500 in the fight yet:

[INIT]
BSET &bl0 FALSE
[AT500]
BSET &bl0 TRUE
[SEEE]
IFBT &bl0 WE_ARE_AFTER_TICK_500

 

IFEQ <Register1> <Register2> <TrueSUB>

IfEqual: Directs execution to TrueSUB if Register1 equals to Register2. If the two registers are not equal, execution continues after IFEQ.

 

[INIT]
CNAM Amy
COPY #id &id0
[EAPP]
IFEQ #id &id0 Its_Amy
ATAK #id

 

IFFR <RobotId> <TrueSUB>

IfFriendly: Checks if the robot represented by the value of the RobotId register is an ally. If it is, execution continues in TrueSUB, otherwise execution continues with the command after IFFR.

[NEXT] 
IFFR #id I_am_next_to_an_ally_of_mine
ATAK #id

 

IFGT <Numeric1> <Numeric2> <TrueSUB>

IfGreaterThan: Checks if Numeric1 is greater than Numeric2. If so, execution goes on in TrueSUB, otherwise execution continues in the current subroutine. If one of the values are not valid then the command is disregarded. The following example is not so useful, but it does help you understand how IFGT works. It sets a Position and checks if your robot has stepped on this Position more than 10 times. If so, it continues execution in the subroutine BEEN_HERE_10_TIMES.

[INIT]
CPOS 32:16
COPY #ps &ps0
_SET &nr0 0
_SET &nr1 1
_SET &nr2 10
[STEP]
IFEQ #mp &ps0 INCREASE
[INCREASE]
IFLT &nr0 &nr2 BEEN_HERE_10_TIMES
_ADD &nr0 &nr1
[BEEN_HERE_10_TIMES]
; either coincidence, or didn't move for some reason

 

IFHI <RobotId1> <RobotId2> <TrueSUB>

IfHigher: If RobotId1 represents a value that is higher than RobotId2 then TrueSUB is executed otherwise execution continues with the commands following IFHI.

[INIT]
GRPS
GOTO #ps
[ATKD]
IFHI #me #id POSI_was_not_executed_yet
COPY #id &id9
; &id9 must be valid
[POSI_WAS_NOT_EXECUTED_YET]
INVA &id9
[POSI]
IFVA &id9 FLEE_NOW
GRPS
COPY #ps &ps0
[FLEE_NOW]
FLEE

 

IFIN <Register> <TrueSUB>

IfInvalid: Checks a register for invalidity. If the register is invalid, execution continues in TrueSUB, else the script runs on.

[INIT] 
CNAM Ariadne
IFIN #id Ariadne_does_not_play_this_arena
COPY #id &id0

 

IFLO <RobotId1> <RobotId2> <TrueSUB>

IfLower: If RobotId1 represents a value that is lower than RobotId2 then TrueSUB is executed otherwise execution continues with the commands following IFLO.

[INIT]
GRPS
GOTO #ps
[ATKD]
IFLO #id #me POSI_was_not_executed_yet
COPY #id &id9
; &id9 must be valid
[POSI_WAS_NOT_EXECUTED_YET]
INVA &id9
[POSI]
IFVA &id9 FLEE_NOW
GRPS
COPY #ps &ps0
[FLEE_NOW]
FLEE

 

IFLT <Numeric1> <Numeric2> <TrueSUB>

IfLessThan: Checks if Numeric1 is less than Numeric2. If so, execution goes on in TrueSUB, otherwise execution continues in the current subroutine. If one of the values are not valid then the command is disregarded. The following example is not so useful, but it does help you understand how IFLT works. It sets a Position and checks if your robot has stepped on this Position more than 10 times. If so, it continues execution in the subroutine BEEN_HERE_10_TIMES.

[INIT]
CPOS 32:16
COPY #ps &ps0
_SET &nr0 0
_SET &nr1 1
_SET &nr2 10
[STEP]
IFEQ #mp &ps0 INCREASE
[INCREASE]
IFLT &nr2 &nr0 BEEN_HERE_10_TIMES
_ADD &nr0 &nr1
[BEEN_HERE_10_TIMES]
; either coincidence, or didn't move for some reason

 

IFNE <Register1> <Register2> <TrueSUB>

IfNotEqual: Checks if two registers are different. If they are different, execution continues in TrueSUB, else the command following IFNE will be executed.

[INIT]
CNAM Dave
COPY #id &id0
[EAPP]
IFNE #id &id0 Dave
ATAK #id

 

IFNF <RobotId> <TrueSUB>

IfNotFriendly: Checks if RobotId is an enemy robot. If it is an enemy robot, execution continues in TrueSUB, else execution continues in the current procedure with the commands following IFNF.

[NEXT]
IFNF #id Attack_this_enemy
SMSG #id Hello mate! I am right next to you.

 

IFNV <RobotId> <TrueSUB>

IfNotVisible: Checks if the robot represented by RobotId is not visible. If it can not be seen, execution continues in TrueSUB, else execution continues with the commands following IFNV.

[AT300] 
; assuming &id0 has a valid value
IFNV &id0 I_can_not_see_you

 

IFVA <Register> <TrueSUB>

IfValid: Checks the validity of a register. If the register is valid execution continues in TrueSUB, else execution continues with the commands following IFVA.

[INIT]
CNAM Ariadne
IFVA #id Ariadne_plays_this_arena

 

IFVI <RobotId> <TrueSUB>

IfVisible: Checks if a robot represented by RobotId is visible. If it is visible, execution continues in TrueSUB, else execution continues with the commands after IFVI.

[AT300]
; assuming &id0 has a valid value
IFVI &id0 I_can_see_you

 

ISEQ <Register1> <Register2> <TrueSUB> <FalseSUB>

IsEqualTo: Checks if Register1 register is equal to Register2 register. If they are equal, TrueSub will be executed. If not, then execution will be redirected to FalseSub. Two other commands help you to achieve the same result without leaving the calling procedure. See IFEQ and IFNE for more details.

[INIT]
CNAM Tom
COPY #id &id0
 
[EAPP]
ISEQ #id &id0 It_is_Tom It_is_not_Tom

 

LOG <string>

Log: Logs any line in your black box. This is useful to debug your scripts.

[INIT]
LOG initializing...
[POSI]
LOG Finding new Position to move to...
GRPS
GOTO #ps

 

The following parameters are reserved for LOG:

LOG TICK: Will log the actual tick.

- LOG BOTPOS: Will log the actual Position of your robot.

- LOG HP: Will log all your equipments' actual hp and defense values.

 

SHOT <Position>

Shoot: It will tell the robot to shoot at the specified Position with the fastest available weapon. If you have several weapons then you can issue several SHOT commands. The first command will activate the fastest weapon, and eventually the slower weapons will be fired as well if they are not recharging and they are not damaged beyond a point where they become useless. The SHOT will be made without any respect to range, obstacles or radar information. If the SHOT is accurate, it can injure any robot on the target Position - either an ally or an enemy! (Setting off an [ATKD] event for the target robot). Shooting the doll owner tosses the doll towards a random Position if the SHOT is extremely accurate. Do not forget that you can shoot allies with this command.

[SEEE]
GPOS #id
SHOT #ps

 

SMSG <RobotId> <text message>

SendMessage: Sends a message to RobotId. You can not send a message to yourself.

[EAPP]
SMSG #id Welcome, are you ready to die?

 

SOS!

SOS: Sends out an SOS signal to all friendly units. This executes a

HELP event for all of them. Your robot is often regarded as an ally of yours, but in this case if you issue the SOS! Command it will not trigger a [HELP] event on your own robot.

[DLIM]
SOS!
FLEE

 

TEST <Register> <ValidSUB> <InvalidSUB>

Test: Tests any register for validity. If the register is valid, execution continues at the subroutine provided as the second parameter. If the register is invalid, execution continues at the subroutine provided as the third parameter. Example: "TEST #id GOOD BAD". If #id is valid, execution continues in [GOOD], else in [BAD]. Since execution will not continue in the calling procedure after TEST is executed, there are two other commands that you could use as a workaround to that problem: IFVA and IFIN. See the explanation of these commands for more details.

The following example will continue execution in the subroutine [TRUE_SUB]. It couldn't really happen otherwise, since [EAPP] is triggered when a new robot appears on our radar screen. It then loads the RobotId of this new unit into #id. Therefore, #id will always have a valid value after [EAPP].

[EAPP]
TEST #id TRUE_SUB FALSE_SUB

 

TURN <Position>

Turn: Makes your robot face any adjacent Position. The parameter must be an adjacent Position. This adjacent Position could best be specified by using the constants #le, #ri, #fw and #bk. Note, that the 3D representation of the fight will turn your robot only if it steps into another direction than what it was facing previously. This means that issuing four TURN #ri will not make your robot dance in the arena, especially because you make a 360 degrees turn with that, and you will be facing the same Position. Also, the use of any commands that might affect or auto-manage which way your robot faces (like GOTO, FLEE, FOLL, etc) will override your TURN command. Lets see an example to a good and a bad use of this command:

The following example will make your robot turn right and go ahead when it hits a wall.

[INIT]
GOTO #mp
[POSI]
GOTO #fw
[WALL]
TURN #ri
GOTO #fw

 

But the following example will not turn your robot or move it since GOTO #ps will override it.

[INIT]
GOTO #mp
[POSI]
TURN #ri
GOTO #fw
GRPS
GOTO #ps

 

...and will be basically the same as if we would have run the following:

[INIT]
GOTO #mp
[POSI]
GRPS
GOTO #ps

 

VAL <Register>

Value: Logs the value of any register. If the register is valid, it will log the value of the register. If the register is invalid, it will log that the register is invalid, and there is no value associated with it.

[INIT]
VAL #ps
; will log: #ps=[invalid]
GRPS
VAL #ps
; will log: #ps=xx:yy

 

For the #dl register, if the register is valid, it will log #dl=[valid].

 

VISI <RobotId> <VisibleSUB> <NotVisibleSUB>

IsVisible: Checks if the RobotId in question is visible for the robot. Destroyed and halted robots are not visible. Visibility is determined by the range of your robot's radar, and arena obstacles (walls). Execution does not continue in the calling procedure after VISI, but there are two other commands that can help you work around that problem. They are IFVI and IFNV. See them for more information about how they work. And now here is a VISI example:

[INIT]
CNAM Sheela
COPY #id &id0
[AT500]
VISI &id0 I_See_Sheela I_can_not_see_Sheela

 

WAIT <Number>

Wait: Will cause the robot to stop moving for the specified number of ticks. It will however not stop shooting or triggering events. It will not change its Position for the number of ticks specified. When issued while waiting, it will reset, and process the new command's Number parameter as the delay value.

[AT400]
WAIT 100

 

The above example will tell your robot to stop moving for the following 100 ticks from tick 400. If we already had a WAIT command issued, that will not matter. At tick 500 the robot will start moving again to the Position that was set as its target Position by the last GOTO (or FLEE, ESCP, FOLL, etc...) command.

 

Return to Top


VII. Functions

 

_ADD <Numeric1> <Numeric2> [Parameter 1]

NumericAdd: Adds Numeric2 value to Numeric1 value, and loads the result into Numeric 1.

[INIT]
_SET &nr0 16
_SET &nr1 3
_ADD &nr0 &nr1
; now &nr0 has a valid value of 19

 

_DIV <Numeric1> <Numeric2> [Parameter 1]

NumericDivide: Divides Numeric2 value by Numeric1 value, and loads the rounded result into Numeric 1. If Numeric2 is 0 then Numeric1 is invalidated.

[INIT]
_SET &nr0 16
_SET &nr1 3
_DIV &nr0 &nr1
; now &nr0 has a valid value of 5

 

_SET <Numeric> <Number>[Parameter 1]

NumericSet: Loads a numeric integer value (Number) into a Numeric register. If the second parameter represents a real, non-integer number (such as 1.7) or if the second parameter is not a numeric value then the value of 0 will be loaded into the Numeric register specified as the first parameter. Example:

[INIT]
; loads 3 into &nr0:
_SET &nr0 3
; loads 0 into &nr0:
_SET &nr0 3.2
; loads 0 into &nr0:
_SET &nr0 2.7
; loads 0 into &nr0:
_SET &nr0 foo

 

_MUL <Numeric1> <Numeric2> [Parameter 1]

NumericMultiply: Multiplies Numeric 2 value by Numeric 1 value, and loads the result into Numeric 1.

[INIT]
_SET &nr0 16
_SET &nr1 3
_MUL &nr0 &nr1
; now &nr0 has a valid value of 48

 

_SUB <Numeric1> <Numeric2> [Parameter 1]

NumericSubtract: Subtracts Numeric 2 value from Numeric 1 value, and loads the result into Numeric 1.

[INIT]
_SET &nr0 16
_SET &nr1 3
_SUB &nr0 &nr1
; now &nr0 has a valid value of 13

 

ALLY <RobotId> [#id]

FindAlly: Retrieves any ally of RobotId. #id will contain the RobotId of this ally. If there is no ally found, #id will not change. Ally will always return the ally with the highest RobotId value.

[EAPP] 
ALLY #id
VISI #id There_are_more_of_them It_is_alone

 

BSET <Boolean> TRUE/FALSE[Parameter 1]

BooleanSet: Sets the value of a Boolean register passed as the first parameter to the value specified by the second parameter, and validates it automatically. The value can be either TRUE or FALSE. If the second parameter is neither "TRUE" nor "FALSE" then the command will be disregarded. Example:

[INIT]
BSET &bl0 FALSE
; this would validate &bl0 and set it to FALSE
; remember that this is not the same as invalidating the
; &bl0 register, since in our case it has a value of FALSE
; but if we invalidate it then it does not have a value

 

CNAM <PlyrNam> [#id]

ConvertPlayerNameToRobotId: Converts a player's name to a RobotId. The player must play in the actual arena.

[INIT]
CNAM Soleado
COPY #id &id0

 

COPY <Register1> <Register2> [Parameter 2]

Copy: Copies the value of Register1 into Register2. Both have to be registers of the same type. Since the command is successful only if the first register is valid, it can't be used to copy invalidity. Of course the second register can be either invalid or valid, it doesn't really matter, since it is the register we want to write over.

[EAPP]
COPY #id &id0

 

CPID <6 digit Id> [#id]

ConvertPlayerIdToRobotId: Converts a player's 6 digit player id to a RobotId. The player must play in the actual arena.

[INIT]
CPID 468368
COPY #id &id0

 

CPOS <x> <y> converts to [#ps]

ConvertXYToPosition: Converts two integer values into a Position type value. Both X and Y must be numeric values, they must be between 0 and 65.

[AT300]
CPOS 13 5
GOTO #ps

GDIS <Position>[#nr]

GetDistanceFrom: Counts the distance between the robot's Position and the Position passed as a parameter. The result will be a numeric value, and will be put into the #nr register.

[SEEE]
; this example checks if the enemy is further away than
; 10 places in the arena
GPOS #id
GDIS #ps
_SET &nr0 10
IFGT #nr &nr0 ENEMY_IS_FAR_AWAY
; else it looks like the enemy is close..

 

GATR <RobotId> [#id]

GetAttacker: Retrieves one of the attackers of RobotId if there is any.

[HELP]
GATR #id
; now #id contains not our ally, who triggered [HELP]
; but someone who is attacking him/her.
; lets check if the attacking robot is around here
; somewhere - if we can see him/her
IFNV #id The_attacker_is_not_visible
; since IFNV goes to [THE_ATTACKER_IS_NOT_VISIBLE] only
; if it is not visible, we can go on with our script
; and attack the attacker of our ally.
ATAK #id

 

GPOS <RobotId> [#ps]

GetPosition: Retrieves the Position of a robot in the arena. The function retrieves the position of any member of your team in the entire arena, and that of any robot within your radar range.

[EAPP] 
GPOS #id
GOTO #ps

 

GRPS [#ps]

GetRandomPosition: Finds a random Position in the arena.

This Position is always a valid Position. It could even be your current Position though, so you could make sure to check if it is. The following is an example for checking this:

[POSI] 
GRPS
IFEQ #ps #mp POSI
GOTO #ps

 

Although there is a possibility that your robot gets into a loop like this and is thrown out of the arena - if the random Position is your own Position every time. This however has a very little chance.

 

INVA <Register> [Parameter 1]

Invalidate: Invalidates any register.

[SEEE]
GPOS #id
SHOT #ps
INVA #id

 

LMSG <Message> <text message>[Parameter 1]

LoadMessage: Loads a message into a message type register.

[INIT]
LMSG &ms0 Hello World!

 

LRID <RobotId> <Number (1-20)>[Parameter 1]

LoadRobotID: Checks if the robot represented by the numeric value is non-functional. Depending on the functionality of the target RobotId becomes either valid (target represented by the numeric parameter is functional) or invalid. I will try to make it more detailed for you, as many of you asked.

Say your robot is having fun in the arena. Lets stick to using VISI in our example. How would you follow a friendly robot that is visible to you? Without LRID, all events are usually triggered if you see an enemy robot, so we can forget SEEE. (Now we have the RAPP event, so you could as well use that, but this was added only later on.) We must check if this ally of ours is visible in the room we are in, but how would you do it? You could either CNAM or CPID all your allies into &id registers and then check them individually, but how could you do it for any ally that joins an arena with you without rewriting the names or player IDs in your script?

You would check in [INIT] which robots are friendly and save them into one of the registers. (Of course we could save all of them, but I'll leave that to you).

You could use something like the following. I'm only going to check the first 4 players here. So the basic goal here is to check if there is an ally within the first 4 players who joined an arena, and save them into &id1. So if &id1 is valid later on, we have one of the ids of our allies. No big deal, but you don't have to check for names.

[INIT]
LRID &id0 1
CALL CHECKALLIES
[CHECKALLIES]
CALL CHECK1
[CHECK1]
FRND &id0 SAVE1 INC1
[CHECK2]
FRND &id0 SAVE2 INC2
[CHECK3]
FRND &id0 SAVE3 INC3
[CHECK4]
FRND &id0 SAVE4 INC4
[INC1]
LRID &id0 2
CALL CHECK2
[INC2]
LRID &id0 3
CALL CHECK3
[INC3]
LRID &id0 4
CALL CHECK4
[INC4]
CALL OVER
[SAVE1]
COPY &id0 &id1
CALL INC1
[SAVE2]
COPY &id0 &id1
CALL INC2
[SAVE3]
COPY &id0 &id1
CALL INC3
[SAVE4]
COPY &id0 &id1
CALL INC4
[OVER]
BHVR fighter
; insert more init stuff here

 

The best usage of LRID is basically to be able to identify allies without the need to list their names or player identifiers. I am sure there are much simpler and better uses to it, I will let you find out. LRID is the only way to directly set a RobotId. It can be a powerful command when you use it well.

Why does it have 2 parameters? Because one is to sign which RobotId type register should be set (#id, &id0-9, #ie) and the numeric parameter that has a value between 1 and 20 shows what the value to be loaded into the register specified in the first parameter should be. So the result does not automatically gets put into #id, but you can choose which register should get this value. Most other commands do not let you specify this, although this might change in the future.

Say, the arena has 4 players:

1. Q
2. W
3. E
4. R

If you do this:

	LRID &id0 1 

then &id0 will contain the RobotId of Player Q. You could also do this:

	CNAM Q 
COPY #id &id0

but in this arena, CNAM Q would fail:

1. T
2. W
3. E
4. R

CNAM would, but LRID would not, so the same command

	LRID &id0 1 

would put the RobotId of Player T into &id0. It would probably be a good idea to play a few arenas before you start experimenting with LRID.

 

NEAR [#id]

GetNearest: Finds the nearest enemy robot, and puts its RobotId into #id. If there are no enemies visible, #id becomes invalidated.

[AT500]
NEAR
IFNV #id Go_explore_there_are_no_enemies_in_sight
; else attack the enemy in sight
ATAK #id

 

QBHV <RobotId> [#bh]

QueryBehavior: Queries the behavior of the target. Target must be visible or allied. Behavior is stored in #bh. If the target is not visible, #bh becomes invalidated.

[INIT]
BHVR scout
COPY #bh &bh0
[EAPP]
QBHV #id
IFEQ #bh &bh0 Its_a_scout
; else it is not a scout, and we can just FLEE - if we wanted to kill off
; scouts only for example
ESCP #id
[ITS_A_SCOUT]
ATAK #id

 

SNMY <RobotId> [#id]

ScanForEnemyOf: Attempts to find one of the enemies of RobotId, and if successful, puts the resulting RobotId into #id. If there are no enemies visible for RobotId, or RobotId is not friendly unit, or RobotId is not functional, #id becomes invalidated.

[HELP]
; assuming that &id0 contains an ally
SNMY &id0
IFVA #id There_we_have_an_enemy
; else that robot has no enemies in sight
; so lets just move to where our buddy is
GPOS &id0
GOTO #ps

 

   

Return to Top


VIII. Subroutines

In RSL you can easily make your own subroutines only by specifying a name that is not the name of an event. For example, in a previous example we saw how test worked. The example was:

TEST #id GOOD BAD 

As I told you before, this command checks if a register is valid or not. If it is valid, it will continue in the subroutine given as the second parameter, if not, it will execute the subroutine given as the third parameter. Let's see how a whole script using it would look like.

[INIT]
CNAM Ivo
; CNAM converts the name of an arena player
; into a RobotId value that is put into #id.
; If Ivo plays in the arena, we know that #id
; will contain a valid value, but if he does not
; play in the arena, #id will be invalid.
; Let's check the validity of #id now
TEST #id IVO_IS_HERE IVO_IS_NOT_HERE
; TEST will redirect execution to either of the
; subroutines in its parameters.
[IVO_IS_HERE]
; we could save his RobotId to use later,
; for example to identify him quickly when we
; meet another robot.
COPY #id &id0
; we just have to remember that &id0 contains his
; robot's RobotId.
; lets move out and try to find him...
GRPS
GOTO #ps
[IVO_IS_NOT_HERE]
; Seems like he's not around.
; Although it makes no sense, but we could be sad,
; and just wait for 200 ticks from now on.
; But first we need to set a destination for our robot
; so after WAIT is over, it will move.
; Let it be the Position at 14:53.
; We do this because when WAIT ends it does not trigger
; an event, we keep continuity this way.
CPOS 14 53
GOTO #ps
WAIT 200

 

Return to Top


IX. A few advices

Before you upload your script into your robot, it is useful to check for the following errors:

1. Make sure you have one instance of each event in your script. Several instances will cause only the first one to run. The following script would cause your robot to not do anything on INIT:

[INIT]
[INIT]
GRPS
GOTO #ps

 

2. You need to place each command, function and event in separate lines. The following would not be understood by your robot, and would be disregarded:

[INIT]	GRPS
GOTO #ps

 

3. Take the time to think about how your script will execute. Keep a list of functions, events and commands on a piece of paper, so you can check what they exactly do, and how they do it. Problems could often arise because of mixing parameters. The following is a good example, look at the COPY command:

[INIT]
GRPS
; the following copies the value of #ps into &ps0
COPY #ps &ps0
; if we'd use the following, nothing would happen,
; since &ps0 is probably invalid, and if the first
; parameter of COPY is invalid, then nothing happens
COPY &ps0 #ps
; So the order of the parameters does matter!

 

4. It is very important that you do not make infINITe loops. A simple infINITe loop could be the following, but of course it could become pretty complex as well. The basic rule is that you should not issue more than 256 commands within one tick. If your robot detects an infinite loop, it will immediately shut down. Check out the following infinite loop as an example:

[INIT]
CALL INIT

 

5. Commands like GOTO, SHOT, and generally most movement and weapon related commands require time to be completed by your robot. This means that they are triggered only once, and until they are executed, all further similar commands will be disregarded. The following two scripts are good examples if you have one weapon equipped:

[SEEE]
GPOS #id
SHOT #ps
SHOT #ps
SHOT #ps
; This will not make your robot shoot 3 times at the
; Position where your enemy was seen, but it will make
; it shoot once. The following script does just the same
; as the one above:
[SEEE]
GPOS #id
SHOT #ps

 

If you have several weapons equipped, the second SHOT will fire the next available weapon, so in that case, it does make sense to issue several SHOT commands one after the other.

GOTO, SHOT, WAIT, HALT and ATAK behave like this, but TURN for example can be used several times in a script to make your robot turn, so this is possible:

[WALL] 
TURN #ri
TURN #ri
TURN #ri
; but of course you could as well turn left instead of
; turning right 3 times.
[WALL]
TURN #le

  

Return to Top


X. Planned features list

- Make CALL return to a procedure, not just jump from it (RCAL)

- USEW command that would let you fire any specific weapon.

- END command that stops script execution for the actual tick.

- Long command names usable also along with short ones.

- SEEM and DEPM fix and re-implementation.

 

Return to Top


XI. Version info

V1.2

- Added Numeric and Boolean registers: #nr, &nr0 - &nr9, #bl, &bl0 - &bl9.

- New commands: GDIS, BSET, IFBT, IFBF, IFLT, IFGT, _SET, _ADD, _SUB, _DIV, _MUL.

- Added new parameters for ATPR ("lowhp" and "highhp" and "random").

 

V1.11

- Modified VAL to output player name when you use it with a valid RobotId register.

- Added a new parameter for LOG (the full command is: "LOG HP"), which will output statistics about the HPs and defenses of your equipment on your robot.

- Fixed arena messaging (LMSG, SMSG, MSGR).

- InfINITe loops will be handled strictly: no resources or kills are gained if your script goes into an infINITe loop!

 

V1.1

- Descriptions were rewritten, the whole document has changed a lot as far as command explanations go. They are more detailed generally.

- New commands: LOG, VAR, IFEQ, IFNE, IFFR, IFNF, IFVA, IFIN, IFVI, IFNV, IFHI, IFLO, INVA, and a new event: RAPP.

- Most of the IFxx commands are a workaround to the problem that execution does not continue after a procedure is called in the calling procedure. See their explanations for more details.

- Some commands, events and functions did not work exactly as they should have, these were all fixed.

- Introduced the Planned features list so you know what to expect in a following RSL version.

 

V1.07

- Introduced the Version info section to be able to easily follow changes in this document.

- Added new command: LRID to give players the ability of iterating through all the robots, it is available to everyone by default.

- Changed FOLL to execute POSI when the target that is being followed is destroyed.

- Made blackbox logs more verbose. Now you will get info when an event or command is executed. This applies only to some of the events and commands, generally to the ones that are not too frequent. It should help debugging your scripts.

- Fixed an authorization problem that prevented CPOS from working.

- Corrected some typos.

- Marked SEEM and DEPM temporary unavailable.

 

Return to Top


XII. Examples, help

For additional help please visit the RSL thread on MonsterNet or join #rsl on IRC (irc.droidarena.com). If you would like to have a more detailed explanation about a command, event or function, please send an email to rsl@droidarena.net. This is a list where we will try to answer any questions you might have about RSL. We only ask you to contact us only when you have checked all the other alternatives and you can not find help.

 

1. LMSG, SMSG example

[INIT]
; I could save a few messages (although we only have 10
; &ms variables to save to, at least we can change
; these any time)
LMSG &ms0 Meet me at our secret Position!
[MSGR]
; Seems like I got a message!
; I save the sender here, so I can answer later on
COPY #id &id0
; I check if the message is what I am expecting it to be
; (if it's the one in &ms0)
; if yes, i jump to MEET_NOW, else execution should
; continue in OTHER_MESSAGE
ISEQ #ms &ms0 MEET_NOW OTHER_MESSAGE
[MEET_NOW]
; Lets say the secret Position is at 23:48
CPOS 23 48
GOTO #ps
; I could answer as well, the sender was saved into &id0
SMSG &id0 Roger! I'm going there.
[OTHER_MESSAGE]
; This is a message that I was not prepared for.
; We could check if it's an ally or an enemy who sent
; this message, and respond according to that, but for now
; we could just say "Huh???"
SMSG &id0 Huh???

 

2. FRND example

Using FRND in the previous example, [OTHER_MESSAGE] could be:

[OTHER_MESSAGE]
FRND &id0 MSG_FROM_FRIEND MSG_FROM_ENEMY
[MSG_FROM_FRIEND]
; the message arrived from a friendly unit
SMSG &id0 I don't understand, mate.
[MSG_FROM_ENEMY]
; the message arrived from an enemy unit
SMSG &id0 Threats? Prepare to die!
; and then we could check if this enemy is visible, etc..

 

3. DOLL, DPIK, DLOS and #dl example

DOLL is executed when the robot sees the doll. Be careful, as it is executed in every tick as long as the doll is visible to the robot. The most obvious thing to do when we see the doll could be getting it, although in some situations you would probably want to call someone else pick it up in your team. Let's see two simple examples:

[DOLL]
; we see the doll finally! #ps - the Position of the doll
; is passed, so we can use it for a GOTO command
GOTO #ps
; However, we might want to do something else when we see it.
; Lets assume we want to call "Webbed" over to get the doll.
; Since we can not pass the Position of the doll, the best
; would be if he would come to where we stand at the moment.
; If we agreed with him, that he will come to our Position
; whenever we send him the message "I see the doll!", it will
; be pretty easy for him to do so (since he knows we sent the
; message, and he can get our Position by using GPOS).
; We could wait as long as he gets there (we see him) and then
; we could follow him. (Be careful, if he'd be destroyed on the
; way there, we could wait for him for a long time - I leave
; it to you to solve that problem).
 

[INIT]
; We set &id to Webbed's RobotId to be able to identify him
; later during the game
CNAM Webbed
COPY #id &id0
; After this we can just roam around and hope to find the
; doll. Let's trigger [POSI] by going to our own Position
; stored in #mp.
GOTO #mp
[DOLL]
; We send Webbed the message "I see the doll!"
SMSG &id0 I see the doll!
; and check if he's here yet. Since [DOLL] executes
; each tick as long as the doll is visible, it is just the
; right place to check. It doesn't matter if we send the
; message several times, that should be Webbed's problem ;)
VISI &id0 WEBBED_IS_HERE WEBBED_IS_NOT_HERE_YET
[WEBBED_IS_HERE]
; Seems like he made it. Let's follow him then.
; Don't forget that
FOLL &id0
[WEBBED_IS_NOT_HERE_YET]
; He's not here yet, we should probably wait a little
; longer. If we use WAIT, the bot will not move
WAIT 10
[POSI]
; To search for the doll, we will need to use POSI, but
; since we don't necessarily want it to look for random
; Positions to move to - whether we see Webbed or not,
; again, we can use VISI to do the trick.
; If we can't see Webbed, then we could go to a random
; spot, else we could follow him.
VISI &id0 WEBBED_IS_HERE GOTO_RANDOM_Position
[GOTO_RANDOM_Position]
GRPS
GOTO #ps
 

Thank you for reading through this reference. If you have a question or you have a good example for us to put in this document, please let us know! Email us: rsl@droidarena.net.