2.4 Basic Implementation

Overview

This chapter will just cover the very basic initialization and shutdown of the module for multiple robots. More topics will follow in the next section. All discussed changes apply to bt.cpp.

Initialization

First we define how many robots we want to handle (sorry about mixing up the terms "cars", "drivers" and "robots") and the size of the buffer to generate the names.

#define BUFSIZE 20
#define NBBOTS 3

We also need an array of char pointers to remember the memory locations of the names to free them on shutdown.

static char * botname[NBBOTS];

We modify the module entry point:

/*
 * Module entry point
*/
extern "C" int
bt(tModInfo *modInfo)
{
    char buffer[BUFSIZE];
    int i;

    /* clear all structures */
    memset(modInfo, 0, 10*sizeof(tModInfo));

    for (i = 0; i < NBBOTS; i++) {
        sprintf(buffer, "bt %d", i+1);
        botname[i] = strdup(buffer);      /* store pointer */
        modInfo[i].name    = botname[i];  /* name of the module (short) */
        modInfo[i].desc    = "";          /* description of the module */
        modInfo[i].fctInit = InitFuncPt;  /* init function */
        modInfo[i].gfId    = ROB_IDENT;   /* supported framework version */
        modInfo[i].index   = i;           /* indices from 0 to 9 */
    }
    return 0;
}

Now we loop NBBOTS times to initialize all robots. You can see how the name is assembled in the buffer. We have to store the pointers to the names because strdup(buffer) will allocate memory on the heap, which we have to release on shutdown (there is no garbage collector in C or C++).
In case you don't want such systematic names, like "bt 1, bt 2, bt 3", you can also implement them as static character arrays:

static char * botname[NBBOTS] = { "tiger", "penguin", "rat" };

The loop would look like that then:

...
for (i = 0; i < NBBOTS; i++) {
    modInfo[i].name = botname[i];  /* name of the module (short) */
...

This has also the advantage that you don't need to free memory on shutdown. The advantage of the first method is, if you want to add a driver, you just need to increment NBBOTS. Remember that the names should match with the names defined in the bt.xml file.

Shutdown

We have also to change the shutdown of the module to free the memory on the heap. Because shutdown is called for every robot, we need just to release the memory of botname with index i.

/* Called before the module is unloaded */
static void
shutdown(int index)
{
    free(botname[index]);
}

You should now implement the above stuff. In case you try it out, keep in mind, that if you run more than one robot of this module, they will share the stuck variable. So there could be weird effects. Anyway, try a quickrace with your three robots to check if everything is ok so far.

Downloads

In case you got lost, you can download my robot for TORCS 1.2.0 or later.

Summary

  • You understand how initialization and shutdown works.
  • You know how to add more cars.
  • You have implemented it.