/* Race Engine Initialization */
void
ReInit(void)
{
	char *dllname;
	char key[256];
	tRmMovieCapture *capture;

	ReShutdown();

	ReInfo = (tRmInfo *)calloc(1, sizeof(tRmInfo));
	ReInfo->s = (tSituation *)calloc(1, sizeof(tSituation));
	ReInfo->modList = &ReRaceModList;

	char buf[1024];
	snprintf(buf, 1024, "%s%s", GetLocalDir(), RACE_ENG_CFG);

	ReInfo->_reParam = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);

	GfOut("Loading Track Loader...\n");
	dllname = GfParmGetStr(ReInfo->_reParam, "Modules", "track", "");
	sprintf(key, "%smodules/track/%s.%s", GetLibDir (), dllname, DLLEXT);
	if (GfModLoad(0, key, &reEventModList)) return;
	reEventModList->modInfo->fctInit(reEventModList->modInfo->index, &ReInfo->_reTrackItf);

	GfOut("Loading Graphic Engine...\n");
	dllname = GfParmGetStr(ReInfo->_reParam, "Modules", "graphic", "");
	sprintf(key, "%smodules/graphic/%s.%s", GetLibDir (), dllname, DLLEXT);
	if (GfModLoad(0, key, &reEventModList)) return;
	reEventModList->modInfo->fctInit(reEventModList->modInfo->index, &ReInfo->_reGraphicItf);

	capture = &(ReInfo->movieCapture);
	if (strcmp(GfParmGetStr(ReInfo->_reParam, RM_SECT_MOVIE_CAPTURE, RM_ATT_CAPTURE_ENABLE, "no"), "no") == 0){
		capture->enabled = 0;
	} else {
		capture->enabled = 1;
		capture->state = 0;
		capture->deltaFrame = 1.0 / GfParmGetNum(ReInfo->_reParam, RM_SECT_MOVIE_CAPTURE, RM_ATT_CAPTURE_FPS, NULL, 1.0);
		capture->outputBase = GfParmGetStr(ReInfo->_reParam, RM_SECT_MOVIE_CAPTURE, RM_ATT_CAPTURE_OUT_DIR, "/tmp");
		capture->deltaSimu = RCM_MAX_DT_SIMU;
	}

	ReInfo->_reGameScreen = ReHookInit();
}
Ejemplo n.º 2
0
/** Initialization of a telemetry session.
    @ingroup	telemetry
    @param	ymin	Minimum value for Y.
    @param	ymax	Maximum value for Y.
    @return	None
 */
void RtTelemInit(tdble ymin, tdble ymax)
{
#ifdef later
    char	buf[256];
    tModInfo	*curModInfo;

    memset(&tlm, 0, sizeof(tTelemItf));
    sprintf(buf, "%smodules/telemetry/%s.%s", "telemetry", GetLibDir (), DLLEXT);
    if (GfModLoad(TLM_IDENT, buf, &modlist)) return;
    GfOut("--- %s loaded ---\n", modlist->modInfo->name);
    curModInfo = modlist->modInfo;
    curModInfo->fctInit(curModInfo->index, &tlm);

    tlm.init(ymin, ymax);
#endif
}
Ejemplo n.º 3
0
static void
Generate(void)
{
	char *trackdllname;
	char *extName;
	FILE *outfd = NULL;

	// Get the trackgen paramaters.
	sprintf(buf, "%s", CFG_FILE);
	CfgHandle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);

	trackdllname = GfParmGetStr(CfgHandle, "Modules", "track", "track");
	sprintf(buf, "%smodules/track/%s.%s", GetLibDir (), trackdllname, DLLEXT);
	if (GfModLoad(TRK_IDENT, buf, &modlist) < 0) {
		GfFatal("Failed to find the track module %s", buf);
	}

	if (modlist->modInfo->fctInit(modlist->modInfo->index, &TrackItf)) {
		GfFatal("Failed to init the track module %s", buf);
	}

	// This is the track definition.
	sprintf(trackdef, "tracks/%s/%s/%s.xml", TrackCategory, TrackName, TrackName);
	TrackHandle = GfParmReadFile(trackdef, GFPARM_RMODE_STD);
	if (!TrackHandle) {
		fprintf(stderr, "Cannot find %s\n", trackdef);
		exit(1);
	}

	// Build the track structure with graphic extensions.
	Track = TrackItf.trkBuildEx(trackdef);

	if (!JustCalculate) {
		// Get the output file radix.
		sprintf(buf2, "tracks/%s/%s/%s", Track->category, Track->internalname, Track->internalname);
		OutputFileName = strdup(buf2);

		// Number of goups for the complete track.
		if (TrackOnly) {
			sprintf(buf2, "%s.ac", OutputFileName);
			// Track.
			outfd = Ac3dOpen(buf2, 1);
		} else if (MergeAll) {
			sprintf(buf2, "%s.ac", OutputFileName);
			// track + terrain + objects.
			outfd = Ac3dOpen(buf2, 2 + GetObjectsNb(TrackHandle));
		}

		// Main Track.
		if (bump) {
			extName = "trk-bump";
		} else {
			extName = "trk";
		}

		sprintf(buf2, "%s-%s.ac", OutputFileName, extName);
		OutTrackName = strdup(buf2);
	}

	if (JustCalculate){
		CalculateTrack(Track, TrackHandle, bump);
		return;
	}

	GenerateTrack(Track, TrackHandle, OutTrackName, outfd, bump);

	if (TrackOnly) {
		return;
	}

	// Terrain.
	if (MergeTerrain && !MergeAll) {
		sprintf(buf2, "%s.ac", OutputFileName);
		/* terrain + objects  */
		outfd = Ac3dOpen(buf2, 1 + GetObjectsNb(TrackHandle));
	}

	extName = "msh";
	sprintf(buf2, "%s-%s.ac", OutputFileName, extName);
	OutMeshName = strdup(buf2);

	GenerateTerrain(Track, TrackHandle, OutMeshName, outfd, saveElevation);

	if (saveElevation != -1) {
		if (outfd) {
			Ac3dClose(outfd);
		}
		switch (saveElevation) {
		case 0:
		case 1:
			sprintf(buf2, "%s.ac", OutputFileName);
			sprintf(buf, "%s-elv.png", OutputFileName);
			SaveElevation(Track, TrackHandle, buf, buf2, 1);
			if (saveElevation) {
			break;
			}
		case 2:
			sprintf(buf, "%s-elv2.png", OutputFileName);
			SaveElevation(Track, TrackHandle, buf, OutMeshName, 1);
			if (saveElevation) {
			break;
			}
		case 3:
			sprintf(buf, "%s-elv3.png", OutputFileName);
			SaveElevation(Track, TrackHandle, buf, OutMeshName, 0);
			if (saveElevation) {
			break;
			}
		case 4:
			sprintf(buf, "%s-elv4.png", OutputFileName);
			SaveElevation(Track, TrackHandle, buf, OutTrackName, 2);
			break;
		}
		return;
	}

	GenerateObjects(Track, TrackHandle, CfgHandle, outfd, OutMeshName);
}
Ejemplo n.º 4
0
/** Interactive Drivers list selection
    @param	vs	Pointer on tRmDrvSelect structure (cast to void)
    @warning	The race manager params are modified but not saved.
 */
void
RmDriversSelect(void *vs)
{
    tModList	*list;
    tModList	*curmod;
    char	dname[256];
    char	*sp;
    char	*cardllname;
    int		i, index;
    tDrvElt	*curDrv;
    int		nCars, robotIdx;
    void	*robhdle;
    struct stat st;
    char	*carName;
    void	*carhdle;
    int		human;

#define B_BASE  380
#define B_HT    30

    ds = (tRmDrvSelect*)vs;

    GF_TAILQ_INIT(&DrvList);

    scrHandle = GfuiScreenCreateEx((float*)NULL, NULL, rmdsActivate, NULL, (tfuiCallback)NULL, 1);
    GfuiScreenAddBgImg(scrHandle, "data/img/splash-qrdrv.png");

    GfuiTitleCreate(scrHandle, "Select Drivers", sizeof("Select Drivers"));

    GfuiLabelCreate(scrHandle,
		    "Selected",
		    GFUI_FONT_LARGE,
		    120, 400, GFUI_ALIGN_HC_VB,
		    0);

    GfuiLabelCreate(scrHandle,
		    "Not Selected",
		    GFUI_FONT_LARGE,
		    496, 400, GFUI_ALIGN_HC_VB,
		    0);

    selectedScrollList = GfuiScrollListCreate(scrHandle, GFUI_FONT_MEDIUM_C, 20, 80, GFUI_ALIGN_HL_VB,
					      200, 310, GFUI_SB_RIGHT, NULL, rmdsClickOnDriver);
    unselectedScrollList = GfuiScrollListCreate(scrHandle, GFUI_FONT_MEDIUM_C, 396, 80, GFUI_ALIGN_HL_VB,
						200, 310, GFUI_SB_RIGHT, NULL, rmdsClickOnDriver);


    GfuiButtonCreate(scrHandle, "Accept", GFUI_FONT_LARGE, 210, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
		     NULL, rmdsSelect, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);

    GfuiButtonCreate(scrHandle, "Cancel", GFUI_FONT_LARGE, 430, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
		     ds->prevScreen, rmdsDeactivate, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);

    GfuiButtonCreate(scrHandle, "Move Up", GFUI_FONT_MEDIUM, 320, B_BASE, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
		     (void*)-1, rmMove, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);

    GfuiButtonCreate(scrHandle, "Move Down", GFUI_FONT_MEDIUM, 320, B_BASE - B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
		     (void*)1, rmMove, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
    
    GfuiButtonCreate(scrHandle, "(De)Select", GFUI_FONT_MEDIUM, 320, B_BASE - 2 * B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
		     (void*)0, rmSelectDeselect, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
    
    GfuiButtonCreate(scrHandle, "Set Focus", GFUI_FONT_MEDIUM, 320, B_BASE - 3 * B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
		     NULL, rmdsSetFocus, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
    
    list = (tModList *)NULL;
    sprintf(buf, "%sdrivers", GetLibDir ());
    GfModInfoDir(CAR_IDENT, buf, 1, &list);

    curmod = list;
	if (curmod != NULL) {
		do {
			curmod = curmod->next;
			for (i = 0; i < MAX_MOD_ITF; i++) {
				if (curmod->modInfo[i].name) {
					sp = strrchr(curmod->sopath, '/');
					if (sp == NULL) {
						sp = curmod->sopath;
					} else {
						sp++;
					}
					strcpy(dname, sp);
					dname[strlen(dname) - strlen(DLLEXT) - 1] = 0; /* cut .so or .dll */
					sprintf(buf, "%sdrivers/%s/%s.xml", GetLocalDir(), dname, dname);
					robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
					if (!robhdle) {
						sprintf(buf, "drivers/%s/%s.xml", dname, dname);
						robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
					}
					sprintf(path, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, curmod->modInfo[i].index);
					carName = GfParmGetStr(robhdle, path, ROB_ATTR_CAR, "");
					if (strcmp(GfParmGetStr(robhdle, path, ROB_ATTR_TYPE, ROB_VAL_ROBOT), ROB_VAL_ROBOT)) {
						human = 1;
					} else {
						human = 0;
					}
					sprintf(path, "cars/%s/%s.xml", carName, carName);
					if (!stat(path, &st)) {
						carhdle = GfParmReadFile(path, GFPARM_RMODE_STD);
						if (carhdle) {
							curDrv = (tDrvElt*)calloc(1, sizeof(tDrvElt));
							curDrv->index = curmod->modInfo[i].index;
							curDrv->dname = strdup(dname);
							curDrv->name = strdup(curmod->modInfo[i].name);
							curDrv->car = carhdle;
							if (human) {
								curDrv->human = 1;
								GF_TAILQ_INSERT_HEAD(&DrvList, curDrv, link);
							} else {
								curDrv->human = 0;
								GF_TAILQ_INSERT_TAIL(&DrvList, curDrv, link);
							}
						} else {
							GfOut("Driver %s not selected because car %s is not readable\n", curmod->modInfo[i].name, carName);
						}
					} else {
						GfOut("Driver %s not selected because car %s is not present\n", curmod->modInfo[i].name, carName);
					}
					GfParmReleaseHandle(robhdle);
				}
			}
		} while (curmod != list);
	}

    nbSelectedDrivers = 0;
    nbMaxSelectedDrivers = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_MAXNUM, NULL, 0);
    nCars = GfParmGetEltNb(ds->param, RM_SECT_DRIVERS);
    index = 1;
    for (i = 1; i < nCars+1; i++) {
	sprintf(dname, "%s/%d", RM_SECT_DRIVERS, i);
	cardllname = GfParmGetStr(ds->param, dname, RM_ATTR_MODULE, "");
	robotIdx = (int)GfParmGetNum(ds->param, dname, RM_ATTR_IDX, (char*)NULL, 0);

	curDrv = GF_TAILQ_FIRST(&DrvList);
	if (curDrv != NULL) {
	    do {
		if ((curDrv->index == robotIdx) && (strcmp(curDrv->dname, cardllname) == 0)) {
		    if (nbSelectedDrivers < nbMaxSelectedDrivers) {
			GfuiScrollListInsertElement(scrHandle, selectedScrollList, curDrv->name, index, (void*)curDrv);
			curDrv->sel = index++;
			nbSelectedDrivers++;
		    }
		    break;
		}
	    } while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL);
	}
    }

    curDrv = GF_TAILQ_FIRST(&DrvList);
    if (curDrv != NULL) {
	do {
	    if (curDrv->sel == 0) {
		GfuiScrollListInsertElement(scrHandle, unselectedScrollList, curDrv->name, 1000, (void*)curDrv);
	    }
	} while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL);
    }

    GfuiLabelCreate(scrHandle, "Focused:", GFUI_FONT_MEDIUM, 320, B_BASE - 5 * B_HT, GFUI_ALIGN_HC_VB, 0);
    cardllname = GfParmGetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
    robotIdx = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0);
    curDrv = GF_TAILQ_FIRST(&DrvList);
    if (curDrv != NULL) {
	do {
	    if ((curDrv->index == robotIdx) && (strcmp(curDrv->dname, cardllname) == 0)) {
		break;
	    }
	} while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL);
    }
    if (curDrv == NULL) {
	curDrv = GF_TAILQ_FIRST(&DrvList);
    }
    if (curDrv == NULL) {
	FocDrvLabelId = GfuiLabelCreate(scrHandle, "", GFUI_FONT_MEDIUM_C,
					320, B_BASE - 5 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256);
    } else {
	FocDrvLabelId = GfuiLabelCreate(scrHandle, curDrv->name, GFUI_FONT_MEDIUM_C,
					320, B_BASE - 5 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256);
    }

    /* Picked Driver Info */
    GfuiLabelCreate(scrHandle, "Driver:", GFUI_FONT_MEDIUM, 320, B_BASE - 7 * B_HT, GFUI_ALIGN_HC_VB, 0);
    PickDrvNameLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C,
					   320, B_BASE - 7 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256);
    GfuiLabelCreate(scrHandle, "Car:", GFUI_FONT_MEDIUM, 320, B_BASE - 8 * B_HT, GFUI_ALIGN_HC_VB, 0);
    PickDrvCarLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C,
					  320, B_BASE - 8 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256);
    GfuiLabelCreate(scrHandle, "Category:", GFUI_FONT_MEDIUM, 320, B_BASE - 9 * B_HT, GFUI_ALIGN_HC_VB, 0);
    PickDrvCategoryLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C,
					       320, B_BASE - 9 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256);
    GfuiMenuDefaultKeysAdd(scrHandle);
    rmdsAddKeys();

    GfuiScreenActivate(scrHandle);
}
Ejemplo n.º 5
0
/* return state mode */
static int
reRaceRealStart(void)
{
	int i, j;
	int sw, sh, vw, vh;
	tRobotItf *robot;
	tReCarInfo *carInfo;
	const int BUFSIZE = 1024;
	char buf[BUFSIZE];
	int foundHuman;
	void *params = ReInfo->params;
	void *results = ReInfo->results;
	tSituation *s = ReInfo->s;

	RmLoadingScreenSetText("Loading Simulation Engine...");
	const char* dllname = GfParmGetStr(ReInfo->_reParam, "Modules", "simu", "");
	snprintf(buf, BUFSIZE, "%smodules/simu/%s.%s", GetLibDir (), dllname, DLLEXT);
	if (GfModLoad(0, buf, &ReRaceModList)) return RM_QUIT;
	ReRaceModList->modInfo->fctInit(ReRaceModList->modInfo->index, &ReInfo->_reSimItf);

	if (ReInitCars()) {
		return RM_QUIT;
	}

	/* Blind mode or not */
	if (ReInfo->_displayMode != RM_DISP_MODE_CONSOLE) {
		ReInfo->_displayMode = RM_DISP_MODE_NORMAL;
		ReInfo->_reGameScreen = ReScreenInit();
		foundHuman = 0;
		for (i = 0; i < s->_ncars; i++) {
			if (s->cars[i]->_driverType == RM_DRV_HUMAN) {
				foundHuman = 1;
				break;
			}
		}
		if (!foundHuman) {
			if (!strcmp(GfParmGetStr(params, ReInfo->_reRaceName, RM_ATTR_DISPMODE, RM_VAL_VISIBLE), RM_VAL_INVISIBLE)) {
				ReInfo->_displayMode = RM_DISP_MODE_NONE;
				ReInfo->_reGameScreen = ReResScreenInit();
			}
		}
	}

	if (!(ReInfo->s->_raceType == RM_TYPE_QUALIF) ||
	((int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1) == 1))
	{
		RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-qrloading.png");
	}

	for (i = 0; i < s->_ncars; i++) {
		snprintf(buf, BUFSIZE, "Initializing Driver %s...", s->cars[i]->_name);
		RmLoadingScreenSetText(buf);
		robot = s->cars[i]->robot;
		robot->rbNewRace(robot->index, s->cars[i], s);
	}
	carInfo = ReInfo->_reCarInfo;

	ReInfo->_reSimItf.update(s, RCM_MAX_DT_SIMU, -1);
	for (i = 0; i < s->_ncars; i++) {
		carInfo[i].prevTrkPos = s->cars[i]->_trkPos;
	}

	RmLoadingScreenSetText("Running Prestart...");
	for (i = 0; i < s->_ncars; i++) {
		memset(&(s->cars[i]->ctrl), 0, sizeof(tCarCtrl));
		s->cars[i]->ctrl.brakeCmd = 1.0;
	}
	for (j = 0; j < ((int)(1.0 / RCM_MAX_DT_SIMU)); j++) {
		ReInfo->_reSimItf.update(s, RCM_MAX_DT_SIMU, -1);
	}

	if (ReInfo->_displayMode == RM_DISP_MODE_NONE) {
		if (ReInfo->s->_raceType == RM_TYPE_QUALIF) {
			ReUpdateQualifCurRes(s->cars[0]);
		} else {
			snprintf(buf, BUFSIZE, "%s on %s", s->cars[0]->_name, ReInfo->track->name);
			ReResScreenSetTitle(buf);
		}
	}

	RmLoadingScreenSetText("Ready.");

	ReInfo->_reTimeMult = 1.0;
	ReInfo->_reLastTime = -1.0;
	ReInfo->s->currentTime = -2.0;
	ReInfo->s->deltaTime = RCM_MAX_DT_SIMU;

	ReInfo->s->_raceState = RM_RACE_STARTING;

	if ((ReInfo->_displayMode != RM_DISP_MODE_CONSOLE) &&  ReInfo->_reGraphicItf.initview != 0) {
		GfScrGetSize(&sw, &sh, &vw, &vh);
		ReInfo->_reGraphicItf.initview((sw-vw)/2, (sh-vh)/2, vw, vh, GR_VIEW_STD, ReInfo->_reGameScreen);

		if (ReInfo->_displayMode == RM_DISP_MODE_NORMAL) {
			/* RmLoadingScreenSetText("Loading Cars 3D Objects..."); */
			stopMenuMusic();
			ReInfo->_reGraphicItf.initcars(s);
		}

		GfuiScreenActivate(ReInfo->_reGameScreen);
	}

	// If the race is adaptive, initialize performance measurement. Uses strategy pattern, pass in the desired performance measurement object.
	if (taManager->IsActive())
	{
		if (taManager->GetRaceType() == torcsAdaptive::TARaceType::Adaptive)
			taManager->InitPerfMeasurement(new RaceLineEvaluation(&ReInfo->carList[0], Pathfinder::K1999, ReInfo->track, ReInfo->s));
	}
	return RM_SYNC | RM_NEXT_STEP;
}
/** Initialize the cars for a race.
    The car are positionned on the starting grid.
    @return	0 Ok
		-1 Error
 */
int
ReInitCars(void)
{
	int nCars;
	int index;
	int i, j, k;
	char *cardllname;
	int robotIdx;
	tModInfo *curModInfo;
	tRobotItf *curRobot;
	void *handle;
	char *category;
	void *cathdle;
	void *carhdle;
	void *robhdle;
	tCarElt *elt;
	char *focused;
	char *str;
	int focusedIdx;
	void *params = ReInfo->params;

	/* Get the number of cars racing */
	nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS_RACING);
	GfOut("loading %d cars\n", nCars);

	FREEZ(ReInfo->carList);
	ReInfo->carList = (tCarElt*)calloc(nCars, sizeof(tCarElt));
	FREEZ(ReInfo->rules);
	ReInfo->rules = (tRmCarRules*)calloc(nCars, sizeof(tRmCarRules));
	focused = GfParmGetStr(ReInfo->params, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
	focusedIdx = (int)GfParmGetNum(ReInfo->params, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, NULL, 0);
	index = 0;

	for (i = 1; i < nCars + 1; i++) {
		/* Get Shared library name */
		sprintf(path, "%s/%d", RM_SECT_DRIVERS_RACING, i);
		cardllname = GfParmGetStr(ReInfo->params, path, RM_ATTR_MODULE, "");
		robotIdx = (int)GfParmGetNum(ReInfo->params, path, RM_ATTR_IDX, NULL, 0);
		sprintf(path, "%sdrivers/%s/%s.%s", GetLibDir (), cardllname, cardllname, DLLEXT);

		/* load the robot shared library */
		if (GfModLoad(CAR_IDENT, path, ReInfo->modList)) {
			GfTrace("Pb with loading %s driver\n", path);
			break;
		}

		/* search for corresponding index */
		for (j = 0; j < MAX_MOD_ITF; j++) {
			if ((*(ReInfo->modList))->modInfo[j].index == robotIdx) {
				/* good robot found */
				curModInfo = &((*(ReInfo->modList))->modInfo[j]);
				GfOut("Driver's name: %s\n", curModInfo->name);
				/* retrieve the robot interface (function pointers) */
				curRobot = (tRobotItf*)calloc(1, sizeof(tRobotItf));
				curModInfo->fctInit(robotIdx, (void*)(curRobot));
				sprintf(buf, "%sdrivers/%s/%s.xml", GetLocalDir(), cardllname, cardllname);
				robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
				if (!robhdle) {
					sprintf(buf, "drivers/%s/%s.xml", cardllname, cardllname);
					robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
				}
				if (robhdle != NULL) {
					elt = &(ReInfo->carList[index]);
					GF_TAILQ_INIT(&(elt->_penaltyList));

					elt->index = index;
					elt->robot = curRobot;
					elt->_paramsHandle = robhdle;
					elt->_driverIndex = robotIdx;
					strncpy(elt->_modName, cardllname, MAX_NAME_LEN - 1);
					elt->_modName[MAX_NAME_LEN - 1] = 0;

					sprintf(path, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, robotIdx);
					strncpy(elt->_name, GfParmGetStr(robhdle, path, ROB_ATTR_NAME, "<none>"), MAX_NAME_LEN - 1);
					elt->_name[MAX_NAME_LEN - 1] = 0;
					strncpy(elt->_teamname, GfParmGetStr(robhdle, path, ROB_ATTR_TEAM, "<none>"), MAX_NAME_LEN - 1);
					elt->_teamname[MAX_NAME_LEN - 1] = 0;
					
					strncpy(elt->_carName, GfParmGetStr(robhdle, path, ROB_ATTR_CAR, ""), MAX_NAME_LEN - 1);
					elt->_carName[MAX_NAME_LEN - 1] = 0;
					elt->_raceNumber = (int)GfParmGetNum(robhdle, path, ROB_ATTR_RACENUM, (char*)NULL, 0);
					if (strcmp(GfParmGetStr(robhdle, path, ROB_ATTR_TYPE, ROB_VAL_ROBOT), ROB_VAL_ROBOT)) {
						elt->_driverType = RM_DRV_HUMAN;
					} else {
						elt->_driverType = RM_DRV_ROBOT;
					}
					elt->_skillLevel = 0;
					str = GfParmGetStr(robhdle, path, ROB_ATTR_LEVEL, ROB_VAL_SEMI_PRO);
					for(k = 0; k < (int)(sizeof(level_str)/sizeof(char*)); k++) {
						if (strcmp(level_str[k], str) == 0) {
							elt->_skillLevel = k;
							break;
						}
					}
					elt->_startRank  = index;
					elt->_pos        = index+1;
					elt->_remainingLaps = ReInfo->s->_totLaps;

					/* handle contains the drivers modifications to the car */
					/* Read Car model specifications */
					sprintf(buf, "cars/%s/%s.xml", elt->_carName, elt->_carName);
					GfOut("Car Specification: %s\n", buf);
					carhdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
					category = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, NULL);
					sprintf(buf, "Loading Driver %-20s... Car: %s", curModInfo->name, elt->_carName);
					RmLoadingScreenSetText(buf);
					if (category != 0) {
						strncpy(elt->_category, category, MAX_NAME_LEN - 1);
						elt->_category[MAX_NAME_LEN - 1] = '\0';

						/* Read Car Category specifications */
						sprintf(buf, "categories/%s.xml", category);
						GfOut("Category Specification: %s\n", buf);
						cathdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
						if (GfParmCheckHandle(cathdle, carhdle)) {
							GfTrace("Car %s not in Category %s (driver %s) !!!\n", elt->_carName, category, elt->_name);
							break;
						}
						carhdle = GfParmMergeHandles(cathdle, carhdle,
										GFPARM_MMODE_SRC | GFPARM_MMODE_DST | GFPARM_MMODE_RELSRC | GFPARM_MMODE_RELDST);
										curRobot->rbNewTrack(robotIdx, ReInfo->track, carhdle, &handle, ReInfo->s);
						if (handle != NULL) {
							if (GfParmCheckHandle(carhdle, handle)) {
								GfTrace("Bad Car parameters for driver %s\n", elt->_name);
								break;
							}
							handle = GfParmMergeHandles(carhdle, handle,
										GFPARM_MMODE_SRC | GFPARM_MMODE_DST | GFPARM_MMODE_RELSRC | GFPARM_MMODE_RELDST);
						} else {
							handle = carhdle;
						}
						elt->_carHandle = handle;
						//GfParmWriteFile("toto.xml", handle, "toto");
					} else {
						elt->_category[0] = '\0';
						GfTrace("Bad Car category for driver %s\n", elt->_name);
						break;
					}
					index ++;
				} else {
					GfTrace("Pb No description file for driver %s\n", cardllname);
				}
				break;
			}
		}
    }

	nCars = index; /* real number of cars */
	if (nCars == 0) {
		GfTrace("No driver for that race...\n");
		return -1;
	} else {
		GfOut("%d drivers ready to race\n", nCars);
	}

	ReInfo->s->_ncars = nCars;
	FREEZ(ReInfo->s->cars);
	ReInfo->s->cars = (tCarElt **)calloc(nCars, sizeof(tCarElt *));
	for (i = 0; i < nCars; i++) {
		ReInfo->s->cars[i] = &(ReInfo->carList[i]);
	}

	// TODO: reconsider splitting the call into one for cars, track and maybe other objects.
	// I stuff for now anything into one call because collision detection works with the same
	// library on all objects, so it is a bit dangerous to distribute the handling to various
	// locations (because the library maintains global state like a default collision handler etc.).
    ReInfo->_reSimItf.init(nCars, ReInfo->track);

    initStartingGrid();

    initPits();

    return 0;
}