static void reCarsRemovePenalty(tCarElt *car, tCarPenalty *penalty) { GF_TAILQ_REMOVE(&(car->_penaltyList), penalty, link); //GfLogDebug("reCarsRemovePenalty(car #%d) : Removed penalty %p\n", // car->index, penalty); FREEZ(penalty); }
static void rmFreeDrvList(void) { tDrvElt *cur; while ((cur = GF_TAILQ_FIRST(&DrvList)) != NULL) { GF_TAILQ_REMOVE(&DrvList, cur, link); free(cur->name); free(cur->dname); GfParmReleaseHandle(cur->car); free(cur); } }
void ReSituationUpdater::freezSituation(tRmInfo*& pSituation) { if (pSituation) { // carList if (pSituation->carList) { for (int nCarInd = 0; nCarInd < _nInitDrivers; nCarInd++) { tCarElt* pTgtCar = &pSituation->carList[nCarInd]; tCarPenalty *penalty; while ((penalty = GF_TAILQ_FIRST(&(pTgtCar->_penaltyList))) != GF_TAILQ_END(&(pTgtCar->_penaltyList))) { GF_TAILQ_REMOVE (&(pTgtCar->_penaltyList), penalty, link); free(penalty); } free(pTgtCar->_curSplitTime); free(pTgtCar->_bestSplitTime); } free(pSituation->carList); } // s if (pSituation->s) free(pSituation->s); // rules if (pSituation->rules) free(pSituation->rules); // raceEngineInfo if (pSituation->_reMessage) free(pSituation->_reMessage); if (pSituation->_reBigMessage) free(pSituation->_reBigMessage); if (pSituation->_reCarInfo) free(pSituation->_reCarInfo); free(pSituation); pSituation = 0; } }
/* Compute the race rules and penalties */ static void ReRaceRules(tCarElt *car) { tCarPenalty *penalty; tTrack *track = ReInfo->track; tRmCarRules *rules = &(ReInfo->rules[car->index]); tTrackSeg *seg = RtTrackGetSeg(&(car->_trkPos)); tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]); tTrackSeg *prevSeg = RtTrackGetSeg(&(info->prevTrkPos)); static float color[] = {0.0, 0.0, 1.0, 1.0}; // DNF cars which need too much time for the current lap, this is mainly to avoid // that a "hanging" driver can stop the quali from finishing. // Allowed time is longest pitstop possible + time for tracklength with speed??? (currently fixed 10 [m/s]). // for simplicity. Human driver is an exception to this rule, to allow explorers // to enjoy the landscape. // TODO: Make it configurable. if ((car->_curLapTime > 84.5 + ReInfo->track->length/10.0) && (car->_driverType != RM_DRV_HUMAN)) { car->_state |= RM_CAR_STATE_ELIMINATED; return; } if (car->_skillLevel < 3) { /* only for the pros */ return; } penalty = GF_TAILQ_FIRST(&(car->_penaltyList)); if (penalty) { if (car->_laps > penalty->lapToClear) { /* too late to clear the penalty, out of race */ car->_state |= RM_CAR_STATE_ELIMINATED; return; } switch (penalty->penalty) { case RM_PENALTY_DRIVETHROUGH: sprintf(car->ctrl.msg[3], "Drive Through Penalty"); break; case RM_PENALTY_STOPANDGO: sprintf(car->ctrl.msg[3], "Stop And Go Penalty"); break; default: *(car->ctrl.msg[3]) = 0; break; } memcpy(car->ctrl.msgColor, color, sizeof(car->ctrl.msgColor)); } if (prevSeg->raceInfo & TR_PITSTART) { /* just entered the pit lane */ if (seg->raceInfo & TR_PIT) { /* may be a penalty can be cleaned up */ if (penalty) { switch (penalty->penalty) { case RM_PENALTY_DRIVETHROUGH: sprintf(buf, "%s DRIVE THROUGH PENALTY CLEANING", car->_name); ReRaceMsgSet(buf, 5); rules->ruleState |= RM_PNST_DRIVETHROUGH; break; case RM_PENALTY_STOPANDGO: sprintf(buf, "%s STOP&GO PENALTY CLEANING", car->_name); ReRaceMsgSet(buf, 5); rules->ruleState |= RM_PNST_STOPANDGO; break; } } } } else if (prevSeg->raceInfo & TR_PIT) { if (seg->raceInfo & TR_PIT) { /* the car stopped in pits */ if (car->_state & RM_CAR_STATE_PIT) { if (rules->ruleState & RM_PNST_DRIVETHROUGH) { /* it's not more a drive through */ rules->ruleState &= ~RM_PNST_DRIVETHROUGH; } else if (rules->ruleState & RM_PNST_STOPANDGO) { rules->ruleState |= RM_PNST_STOPANDGO_OK; } } else { if(rules->ruleState & RM_PNST_STOPANDGO_OK && car->_pitStopType != RM_PIT_STOPANDGO) { rules->ruleState &= ~ ( RM_PNST_STOPANDGO | RM_PNST_STOPANDGO_OK ); } } } else if (seg->raceInfo & TR_PITEND) { /* went out of the pit lane, check if the current penalty is cleared */ if (rules->ruleState & (RM_PNST_DRIVETHROUGH | RM_PNST_STOPANDGO_OK)) { /* clear the penalty */ sprintf(buf, "%s penalty cleared", car->_name); ReRaceMsgSet(buf, 5); penalty = GF_TAILQ_FIRST(&(car->_penaltyList)); GF_TAILQ_REMOVE(&(car->_penaltyList), penalty, link); FREEZ(penalty); } rules->ruleState = 0; } else { /* went out of the pit lane illegally... */ /* it's a new stop and go... */ if (!(rules->ruleState & RM_PNST_STNGO)) { sprintf(buf, "%s STOP&GO PENALTY", car->_name); ReRaceMsgSet(buf, 5); penalty = (tCarPenalty*)calloc(1, sizeof(tCarPenalty)); penalty->penalty = RM_PENALTY_STOPANDGO; penalty->lapToClear = car->_laps + 5; GF_TAILQ_INSERT_TAIL(&(car->_penaltyList), penalty, link); rules->ruleState = RM_PNST_STNGO; } } } else if (seg->raceInfo & TR_PITEND) { rules->ruleState = 0; } else if (seg->raceInfo & TR_PIT) { /* entrered the pits not from the pit entry... */ /* it's a new stop and go... */ if (!(rules->ruleState & RM_PNST_STNGO)) { sprintf(buf, "%s STOP&GO PENALTY", car->_name); ReRaceMsgSet(buf, 5); penalty = (tCarPenalty*)calloc(1, sizeof(tCarPenalty)); penalty->penalty = RM_PENALTY_STOPANDGO; penalty->lapToClear = car->_laps + 5; GF_TAILQ_INSERT_TAIL(&(car->_penaltyList), penalty, link); rules->ruleState = RM_PNST_STNGO; } } if (seg->raceInfo & TR_SPEEDLIMIT) { if (!(rules->ruleState & (RM_PNST_SPD | RM_PNST_STNGO)) && (car->_speed_x > track->pits.speedLimit)) { sprintf(buf, "%s DRIVE THROUGH PENALTY", car->_name); ReRaceMsgSet(buf, 5); rules->ruleState |= RM_PNST_SPD; penalty = (tCarPenalty*)calloc(1, sizeof(tCarPenalty)); penalty->penalty = RM_PENALTY_DRIVETHROUGH; penalty->lapToClear = car->_laps + 5; GF_TAILQ_INSERT_TAIL(&(car->_penaltyList), penalty, link); } } }