Template:Baserouting

From omni-bot

Routing Overview

Until version 0.65, omni-bot path selection relied on the shortest path to a goal. While this typically provided for very focused attacks, game play became very predictable. The solution is Routing. Routing provides alternate goals for the bots to go to before heading to their main goal. When positioned correctly, these alternate goals provide the effect of bots choosing realistic and varied paths to their main goals.

Routing requires some setup in script and in the waypoints, but the results are worth the effort. The objective of this article is to provide an overview of how the routing system works and to clearly define how to set it up by walking through a working example on Goldrush.


Goldrush Multiple Routes Example


In this picture, Squares are route nodes and the Dots are potential paths. The color of the Dots correspond to the color of the Route nodes. Once they reach a route node, they will travel along the path(s) of the same color IF the route node is set up for their current main goal.


Walking through the picture, let’s say the tank construction goal is set up for an allied engineer within the AllySpawn route nodes, and that the engineer has the tank construct as its goal. The engineer will randomly choose whether to go to the green route node (as_right) or the yellow route node (depotgate). For the purpose of this example, let’s say the bot chose to go to the green route node. From there, he will randomly choose to go to the white or red route node. The bot will continue to make these decisions until there are no route nodes left to go to. From that point, the bot will take the shortest path to the tank construct goal. As you can see, this opens up several different points of attack for the bots; which creates a sense of realism in terms of predictability. Defenses will now need to be set up to be able to react to all of the entry points rather than focusing on easily predicted choke points if the shortest path is always used.

Setting It Up

Setting up Routes involves waypointing and scripting. This section will take you step by step through the process of setting up the routes in the Goldrush example.

Step 1: Setting up the script

The first requirement for routing is that the routes are defined in the map script. The method to do this consists of building a table for the routes and calling a utility function that will register the routes.

If a map script does not exist yet, open up your favorite text editor and add the following to a new file:

 global InitializeRoutes = function()
 {
 };

Save the file as <mapname>.gm in your Omni-Bot\et\nav folder. You are now ready to start building the routes. Inside the InitializeRoutes function is where the route definitions are placed and they all start with a basic layout:

 global InitializeRoutes = function()
 {
     MapRoutes =
     {
     };
 
     Util.Routes(MapRoutes);
 };

You now have a MapRoutes table defined and are registering everything within that table with the Util.Routes function.


Step 2: Adding route goal

Route goals are fairly straight forward. They have two important properties; route name and radius. You can use any name you want for the route nodes, but they should be somewhat intuitive. To see the full guide on adding route goals see the Route_Goal page.

Route goals are placed in positions where a bot might receive the goal you want them to use alternate paths for. The bot MUST be inside the route node radius when receiving a goal for it to work. Spawn points are good spots for route nodes because bots always receive a goal when they spawn.

In the spawns area you need to place the goal over the spawn positions and give it a large radius to cover the spawn points. Issue the following commands in console:

 /bot show_spawns
 /bot goal_create route AllySpawn
 /bot goal_setproperty radius 500
 /bot goal_finish 

The radius of the route nodes at spawn positions are very critical because the bots must be inside its radius for it to work. Be sure that the radius covers the entire spawn area. Bots do not always receive goals immediately at spawn. Sometimes they receive goals 2 seconds after spawn. That's why it's always better to set bigger radius. But be careful, route nodes must not overlap.

For routing to be effective, you will need at least two defined because once they reach the route node, they will take the shortest path to their goal UNLESS there is another route node set up for them to go to. Continuing with our example, create a route node where the green square is in the picture and name it as_right:

 /bot goal_create route as_right
 /bot goal_finish 

You now have two route nodes; meeting the requirement for working routes. In our example, we want the bots to use two paths from the spawn, so add the route node depicted by the yellow square at the depot gate:

 /bot goal_create route depotgate
 /bot goal_finish 

Be sure to save the goals at this point. The next step is to set up the goals and route node selection in the script.

 /bot goal_save

Step 3: Scripting the routes

The Maproutes table is set up with the following format:

  MapRoutes =
  {
      GOALNAME =
      {
          ROUTNAME = {},
      },
      GOALNAME2 =
      {
          ROUTENAME = {},
      },
  };

If you are new to map scripting, this may appear a bit intimidating. The key is to follow the steps and syntax exactly, then let the understanding of the syntax come naturally. If you are comfortable with gm scripting, the routing set up consists of nested tables.

The goal name must match the output from show_goals and the route name is the waypoint name prepended with ROUTE_. For the Goldrush example, set up the tank construct routing as follows:

 global InitializeRoutes = function()
 {
 	MapRoutes =
 	{
 		BUILD_tank_construct =
 		{
 		},
 	};
 
 	Util.Routes(MapRoutes);
 };

You have just added a map goal to the Maproutes table. The syntax of the goal name is VERY important. Be sure to double check the goal name with /bot show_goals. Once you are sure the goal name is correct, you can add the route nodes:

 global InitializeRoutes = function()
 {
 	MapRoutes =
 	{
 		BUILD_tank_construct =
 		{
 			ROUTE_AllySpawn = {},
 		},
 	};
 
 	Util.Routes(MapRoutes);
 };

The AllySpawn route node is now a valid route node for the tank construct goal. If a bot spawns within its radius and receives the tank construct as a goal, it will use that route node. In and of itself, this route node will not do anything because at spawn the bot is already at it. So let’s add the two path options we want to give the bots from the Allied Spawn:

 global InitializeRoutes = function()
 {
 	MapRoutes =
 	{
 		BUILD_tank_construct =
 		{
  			ROUTE_AllySpawn = 
                       {
 	                    ROUTE_as_right = {},
 	                    ROUTE_depotgate = {},
                        },
 	        },
       };
 
 	Util.Routes(MapRoutes);
 };

It’s important to understand what we just did with this:

 ROUTE_AllySpawn = 
 {
     ROUTE_as_right = {},
     ROUTE_depotgate = {},
 },

The bot reaches the AllySpawn route node by default when it spawns; and because we have added the two routes inside the brackets, the bots will randomly choose between them. At this point, you have randomized routes for Allied engineers with the tank construct goal. Half the time they will choose to go to route as_right and half the time they will choose to go to route depotgate.

Let’s make them even less predictable. Looking at the example picture, you can see that we want them to have a couple different options once they reach the route nodes we just set up. Repeating step 2, add the rest of the route nodes depicted by the colored squares.

The scripting for the path options in the picture is as follows:

 global InitializeRoutes = function()
 {
     MapRoutes =
     {
         BUILD_tank_construct =
         {
             ROUTE_AllySpawn = 
             {    
                 ROUTE_as_right =
                 {
                     ROUTE_as_rightsplit1 = {},
                     ROUTE_as_rightsplit2 =
                     {
                         ROUTE_depotflank = {},
                     },
                 },
                 ROUTE_depotgate = 
                 {
                     ROUTE_cproute = {},
                     ROUTE_depotgatesplit = {},
                     ROUTE_as_rightsplit1 = {},
                 },
             },
         },
     };
 
     Util.Routes(Maproutes);
 };

Step 4: Testing the routes

Testing the routes is by far the most important step. It is recommended that you test routes individually as you start to learn the routing system. Once you are comfortable with the setup, you may want to add routes for an entire phase and then test them to make the process a bit faster.

If the routing is not working as expected, there are some basic troubleshooting options. It’s important to remember the criteria for the routes; the bot must be within the radius of the route node when receiving the goal, and the route node must be set up to support the goal. The basic troubleshooting steps are:

  1. Check in console when the map loads for any error messages. It should list any goal names not found when initializing the routes.
  2. Check the radius of the route where the bot receives the goal
  3. Make sure the bot can reach the goal
  4. Make sure the bot is getting the expected goal

For numbers 2 and 3, consider using the command /bot debugbot all goals with only one bot connected. In console, it should give success / failure messages for short term and long term goals. An example of a known problem is if there are priority type goals (like radar parts stealing) that are active when they aren’t reachable. The solution is to set them to be not active in OnMapLoad if they are unreachable.

Step 5: Adding priorities to routes

In some cases, you may want bots to use a certain route more often than others. This can be done by adding a “weight” to the route table:

 ROUTE_as_right =
 {
     Weight = 2,
     ROUTE_as_rightsplit1 = {},
     ROUTE_as_rightsplit2 =
     {
 	  Weight = 2,
 	  ROUTE_depotflank = {},
     },
 },

In this example, the bots will randomly choose to go to route as_right twice as much as route depotgate. And then they will choose to go to route as_rightsplit2 twice as much as route as_rightsplit1.

Step 6: Copying routes

If you have more than one goal that you want to share the same routing with, you can copy the routing. In the Goldrush example, say we have some attack goals in the yard that we want to route to. Rather than writing out the tables for each attack goal, we can copy them like this:

 MapRoutes["ATTACK_Depot_.*"] = MapRoutes.BUILD_tank;
 MapRoutes.MOUNT_tank = MapRoutes.BUILD_Tank;

The key point to remember when doing this is that the route table that exists must be on the right side of the equation. In this case, we have created routes for multiple attack goals and a mount goal that are the same as our example routing to build the tank.

These should be placed in OnMapLoad as well, below the Maproutes table and above the Utility function that registers the routes:

 global InitializeRoutes = function()
 {
     MapRoutes =
     {
         BUILD_Tank =
         {
 
         },
     };
 
     MapRoutes["ATTACK_Depot_.*"] = MapRoutes.BUILD_tank;
     MapRoutes.MOUNT_tank = MapRoutes.BUILD_Tank;
 
     Util.Routes(MapRoutes);
 };

Step 7: Toggling routes

Routes are treated very similar to map goals. They will show up in your list if you do a /bot show_goals. They can be turned on and off via scripting with the SetAvailableMapGoals function. As an example, say we have route that we want opened up when barrier is destroyed, then closed when that barrier is constructed. This can be done inside the OnTriggers for those events:

  Barrier_construct = function (trigger)
  {
  	Util.DisableGoal( "ROUTE_routname" ); 
  };
 
  Barrier_destroyed = function (trigger)
  {
  	Util.EnableGoal( "ROUTE_routname" ); 
  };

Step 8: Route maker

  • Windows users can use the route maker tool to easily create routes.
  • Download it from http://svn.assembla.com/svn/omnibot/Enemy-Territory/0.8/tools/route_tool/
  • Extract both RouteMaker.zip and RouteMaker2.zip into the same folder.
  • Run RouteMaker2.exe
  • You must set rcon password on your Enemy Territory or RTCW server.
  • Then use menu command File / Load From RCON
  • Drag & drop goals from left panel into middle panel.
  • Drag & drop routes from right panel into middle panel.
  • Double-click to delete routes.
  • Finally use menu command Write / Script
  • Output script will be copied to the clipboard. Paste it into the InitializeRoutes function in your map gm script.

Step 9: Ask for help

If you are having trouble with the syntax, set up, or understanding the routing system, ask for help. This guide is by no means comprehensive and complex maps will offer different challenges. Please post in the forums if you have questions / problems / bug reports.