Esempio n. 1
0
void
ReUpdatePracticeCurRes(tCarElt *car, bool bForceNew)
{
	if (bForceNew)
	{
		static const char* pszTableHeader =
			"Lap     \tTime          \tBest      \tTop spd  \tMin spd  \tDamages";
		ReUI().setResultsTableHeader(pszTableHeader);
		char* t1 = GfTime2Str(car->_lastLapTime, 0, false, 3);
		char* t2 = GfTime2Str(car->_bestLapTime, 0, false, 3);
		char buf[128];

		// Cancel hightlight on first line
		if (car->_laps == 2) ReUI().setResultsTableRow(0, "");

		tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]);
		static int nLastLapDamages = 0;
		if (car->_laps <= 2)
			nLastLapDamages = 0;
		snprintf(buf, sizeof(buf), "%.3d  \t%-12s \t%-12s    \t%5.1f   \t%5.1f \t %.5d (%d)",
				 car->_laps - 1, t1, t2, info->topSpd * 3.6, info->botSpd * 3.6,
				 car->_dammage ? car->_dammage - nLastLapDamages : 0, car->_dammage);
		nLastLapDamages = car->_dammage;
		free(t1);
		free(t2);
		
		ReUI().addResultsTableRow(buf);
	}
	else
	{
		ReUpdateQualifCurRes(car);
	}
}
Esempio n. 2
0
void
ReInitCurRes()
{
	if (ReInfo->_displayMode != RM_DISP_MODE_NORMAL)
	{
		if (ReInfo->s->_raceType == RM_TYPE_QUALIF)
		{
			ReUpdateQualifCurRes(ReInfo->s->cars[0]);
		}
		else if (ReInfo->s->_raceType == RM_TYPE_PRACTICE && ReInfo->s->_ncars > 1)
		{
			ReUpdatePracticeCurRes(ReInfo->s->cars[0]);
		}
		else
		{
			static const char* pszTableHeader = "Rank    Time     Driver               Car";
			char pszTitle[128];
			snprintf(pszTitle, sizeof(pszTitle), "%s at %s", 
					 ReInfo->_reRaceName, ReInfo->track->name);
			char pszSubTitle[128];
			snprintf(pszSubTitle, sizeof(pszSubTitle), "%s (%s)",
					 ReInfo->s->cars[0]->_name, ReInfo->s->cars[0]->_carName);
			ReUI().setResultsTableTitles(pszTitle, pszSubTitle);
			ReUI().setResultsTableHeader(pszTableHeader);
		}
	}//if displayMode != normal
}
Esempio n. 3
0
void
ReCarsManageCar(tCarElt *car, bool& bestLapChanged)
{
	char msg[64];
	int i;
	int xx;
	tTrackSeg *sseg;
	tdble wseg;
	static const float ctrlMsgColor[] = {0.0, 0.0, 1.0, 1.0};
	tSituation *s = ReInfo->s;
	
	tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]);

	// Update top speeds.
	if (car->_speed_x > car->_topSpeed)
		car->_topSpeed = car->_speed_x;

	// (practice and qualification only).
	if (car->_speed_x > info->topSpd)
		info->topSpd = car->_speed_x;
	if (car->_speed_x < info->botSpd)
		info->botSpd = car->_speed_x;
	
	// Pitstop management.
	if (car->_pit) {

		// If the driver can ask for a pit, update control messages whether slot occupied or not.
		if (car->ctrl.raceCmd & RM_CMD_PIT_ASKED) {
			// Pit already occupied?
			if (car->_pit->pitCarIndex == TR_PIT_STATE_FREE)
				snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Can Pit");
			else
				snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Pit Occupied");
			car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so.
			memcpy(car->ctrl.msgColor, ctrlMsgColor, sizeof(car->ctrl.msgColor));
		}

		// If pitting, check if pitting delay over, and end up with pitting process if so.
		if (car->_state & RM_CAR_STATE_PIT) {
			car->ctrl.raceCmd &= ~RM_CMD_PIT_ASKED; // clear the flag.
			// Note: Due to asynchronous behaviour of the main updater and the situation updater,
			//       we have to wait for car->_scheduledEventTime being set to smthg > 0.
			if (car->_scheduledEventTime > 0.0) {
				if (car->_scheduledEventTime < s->currentTime) {
					car->_state &= ~RM_CAR_STATE_PIT;
					car->_pit->pitCarIndex = TR_PIT_STATE_FREE;
					snprintf(msg, sizeof(msg), "%s pit stop %.1f s", car->_name, info->totalPitTime);
					msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so.
					ReSituation::self().setRaceMessage(msg, 5);
					GfLogInfo("%s exiting pit (%.1f s elapsed).\n", car->_name, info->totalPitTime);
				} else {
					snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "In pits %.1f s",
							s->currentTime - info->startPitTime);
					car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so.
				}
			}
			
		// If the driver asks for a pit, check if the car is in the right conditions
		// (position, speed, ...) and start up pitting process if so.
		} else if ((car->ctrl.raceCmd & RM_CMD_PIT_ASKED) &&
				   car->_pit->pitCarIndex == TR_PIT_STATE_FREE &&	
				   (s->_maxDammage == 0 || car->_dammage <= s->_maxDammage)) {
			snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Pit request");
			car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so.
 
			tdble lgFromStart = car->_trkPos.seg->lgfromstart;
			
			switch (car->_trkPos.seg->type) {
				case TR_STR:
					lgFromStart += car->_trkPos.toStart;
					break;
				default:
					lgFromStart += car->_trkPos.toStart * car->_trkPos.seg->radius;
					break;
			}
		
			if ((lgFromStart > car->_pit->lmin) && (lgFromStart < car->_pit->lmax)) {
				int side;
				tdble toBorder;
				if (ReInfo->track->pits.side == TR_RGT) {
					side = TR_SIDE_RGT;
					toBorder = car->_trkPos.toRight;
				} else {
					side = TR_SIDE_LFT;
					toBorder = car->_trkPos.toLeft;
				}
				
				sseg = car->_trkPos.seg->side[side];
				wseg = RtTrackGetWidth(sseg, car->_trkPos.toStart);
				if (sseg->side[side]) {
					sseg = sseg->side[side];
					wseg += RtTrackGetWidth(sseg, car->_trkPos.toStart);
				}
				if (((toBorder + wseg) < (ReInfo->track->pits.width - car->_dimension_y / 2.0)) &&
					(fabs(car->_speed_x) < 1.0) && (fabs(car->_speed_y) < 1.0))
				{
					// All conditions fullfilled => enter pitting process
					car->_state |= RM_CAR_STATE_PIT;
					car->_scheduledEventTime = 0.0; // Pit will really start when set to smthg > 0.
					car->_nbPitStops++;
					for (i = 0; i < car->_pit->freeCarIndex; i++) {
						if (car->_pit->car[i] == car) {
							car->_pit->pitCarIndex = i;
							break;
						}
					}
					info->startPitTime = s->currentTime;
					snprintf(msg, sizeof(msg), "%s in pits", car->_name);
					msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so.
					ReSituation::self().setRaceMessage(msg, 5);
					GfLogInfo("%s entering in pit slot.\n", car->_name);
					if (car->robot->rbPitCmd(car->robot->index, car, s) == ROB_PIT_MENU) {
						// the pit cmd is modified by menu.
						reCarsSchedulePitMenu(car);
					} else {
						ReCarsUpdateCarPitTime(car);
					}
				}
				else
				{   // The cars speed or offset is out of accepted range
					// Show the user/developer/robot the reason of the issue
  				    tTeamDriver* TeamDriver = RtTeamDriverByCar(car);
					if (TeamDriver)
					{
					  TeamDriver->StillToGo  = 0.0;
					  TeamDriver->MoreOffset = 0.0;
					  TeamDriver->TooFastBy  = 0.0;
					}

					float Offset = (float) ((toBorder + wseg) - (ReInfo->track->pits.width - car->_dimension_y / 2.0));
  				    if (Offset >= 0.0)
					{
						// The car's position across the track is out of accepted range 
						snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Offset: %.02f",Offset);
						car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so.
						if (TeamDriver)
						  TeamDriver->MoreOffset = Offset;
					}

					float TooFastBy = MAX(fabs(car->_speed_x),fabs(car->_speed_y));
  				    if (TooFastBy >= 1.0)
					{
						// The car's speed is out of accepted range 
						snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Speed: %.02f",TooFastBy);
						car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so.
						if (TeamDriver)
						  TeamDriver->TooFastBy = TooFastBy;
					}
				}
			}
			else
			{	// The car's position along the track is out of accepted range
				// Show the user/developer/robot the reason of the issue
				tTeamDriver* TeamDriver = RtTeamDriverByCar(car);
				if (TeamDriver)
				{
				  TeamDriver->StillToGo  = 0.0;
				  TeamDriver->MoreOffset = 0.0;
				  TeamDriver->TooFastBy  = 0.0;
				}

				if (car->_pit->lmin > lgFromStart)
				{
				  float StillToGo = car->_pit->lmin - lgFromStart;
				  snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Still to go: %0.2f m" ,StillToGo);
				  car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so.
				  if (TeamDriver)
				    TeamDriver->StillToGo = StillToGo;
				}
				else if (car->_pit->lmax < lgFromStart)
				{
  				  float StillToGo = lgFromStart - car->_pit->lmax;
				  snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Overrun: %0.2f m" ,StillToGo);
				  car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so.
				  if (TeamDriver)
				    TeamDriver->StillToGo = -StillToGo;
				}
			}
		}
	}

	/* Check if it is in a new sector */
	while (true)
	{
		if (car->_currentSector < ReInfo->track->numberOfSectors - 1 && car->_laps > 0 && info->lapFlag == 0)
		{
			/* Must pass at least one sector before the finish */
			if (RtGetDistFromStart(car) > ReInfo->track->sectors[car->_currentSector])
			{
				/* It is in a new sector : update split time */
				car->_curSplitTime[car->_currentSector] = car->_curLapTime;
				++car->_currentSector;
				continue;
			}
		}
		break;
	}
	
	/* Start Line Crossing */
	if (info->prevTrkPos.seg != car->_trkPos.seg) {
		
		if ((info->prevTrkPos.seg->raceInfo & TR_LAST)
			&& (car->_trkPos.seg->raceInfo & TR_START)) {
			
			if (info->lapFlag == 0) {

				// If the car has not yet finished the race :
				if (!(car->_state & RM_CAR_STATE_FINISH)) {

					// 1 more lap completed
					// (Note: lap with index 0 finishes when the car crosses the start line the 1st time,
					//        and is thus considered a real lap, whereas it is not).
					car->_laps++;

					/*if (NetGetNetwork())
						NetGetNetwork()->SendLapStatusPacket(car);*/

					car->_remainingLaps--;
					if (car->_pos == 1 && s->currentTime < s->_totTime
						&& s->_raceType == RM_TYPE_RACE)
					{
						/* First car passed finish time before the time ends: increase the number of laps for everyone */
						for (xx = 0; xx < s->_ncars; ++xx)
							++ReInfo->s->cars[xx]->_remainingLaps;
						++s->_totLaps;
					}
					
					car->_currentSector = 0;
					if (car->_laps > 1) {
						car->_lastLapTime = s->currentTime - info->sTime;
						if (car->_bestLapTime != 0) {
							car->_deltaBestLapTime = car->_lastLapTime - car->_bestLapTime;
						}
						if ((car->_lastLapTime < car->_bestLapTime) || (car->_bestLapTime == 0)) {
							car->_bestLapTime = car->_lastLapTime;
							memcpy(car->_bestSplitTime, car->_curSplitTime, sizeof(double)*(ReInfo->track->numberOfSectors - 1) );
							if (s->_raceType != RM_TYPE_RACE && s->_ncars > 1)
							{
								/* Best lap time is made better : update times behind leader */
								bestLapChanged = true;
								car->_timeBehindLeader = car->_bestLapTime - s->cars[0]->_bestLapTime;
								if (car->_pos > 1)
								{
									car->_timeBehindPrev = car->_bestLapTime - s->cars[car->_pos - 1]->_bestLapTime;
								}
								else
								{
									/* New best time for the leader : update the differences */
									for (xx = 1; xx < s->_ncars; ++xx)
									{
										if (s->cars[xx]->_bestLapTime > 0.0f)
											s->cars[xx]->_timeBehindLeader = s->cars[xx]->_bestLapTime - car->_bestLapTime;
									}
								}
								if (car->_pos + 1 < s->_ncars && s->cars[car->_pos+1]->_bestLapTime > 0.0f)
									car->_timeBeforeNext = s->cars[car->_pos + 1]->_bestLapTime - car->_bestLapTime;
								else
									car->_timeBeforeNext = 0;
							}
						}
					}
					if (car->_laps > 0) {
						car->_curTime += s->currentTime - info->sTime;
						
						if (car->_pos != 1 && s->_raceType == RM_TYPE_RACE) {
							car->_timeBehindLeader = car->_curTime - s->cars[0]->_curTime;
							car->_lapsBehindLeader = s->cars[0]->_laps - car->_laps;
							car->_timeBehindPrev = car->_curTime - s->cars[car->_pos - 2]->_curTime;
							s->cars[car->_pos - 2]->_timeBeforeNext = car->_timeBehindPrev;
						} else if (s->_raceType == RM_TYPE_RACE) {
							car->_timeBehindLeader = 0;
							car->_lapsBehindLeader = 0;
							car->_timeBehindPrev = 0;
						}
						
						info->sTime = (tdble)s->currentTime;

						if (ReInfo->s->_raceType == RM_TYPE_PRACTICE && 
								(car->_laps > 1 || s->_totLaps == 0))
							ReSavePracticeLap(car);
					}

					if (ReInfo->_displayMode == RM_DISP_MODE_NONE)
					{
						switch(s->_raceType)
						{
							case RM_TYPE_PRACTICE:
								ReUpdatePracticeCurRes(car);
								break;
							case RM_TYPE_QUALIF:
								ReUpdateQualifCurRes(car);
								break;
							case RM_TYPE_RACE:
								ReUpdateRaceCurRes();
								break;
							default:
								break;
						}
					}
	
					info->topSpd = car->_speed_x;
					info->botSpd = car->_speed_x;
					if ((car->_remainingLaps < 0 && s->currentTime > s->_totTime) || (s->_raceState == RM_RACE_FINISHING)) {
						car->_state |= RM_CAR_STATE_FINISH;
						s->_raceState = RM_RACE_FINISHING;
						if (ReInfo->s->_raceType == RM_TYPE_RACE) {
							if (car->_pos == 1) {
								snprintf(msg, sizeof(msg), "Winner %s", car->_name);
								msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so.
								ReSituation::self().setRaceMessage(msg, 10, /*big=*/true);
								if (NetGetServer())
								{
									NetGetServer()->SetFinishTime(s->currentTime+FINISHDELAY);
								}
							} else {
								const char *numSuffix = "th";
								if (abs(12 - car->_pos) > 1) { /* leave suffix as 'th' for 11 to 13 */
									switch (car->_pos % 10) {
										case 1:
											numSuffix = "st";
											break;
										case 2:
											numSuffix = "nd";
											break;
										case 3:
											numSuffix = "rd";
											break;
										default:
											break;
									}
								}
								snprintf(msg, sizeof(msg), "%s finished %d%s", car->_name, car->_pos, numSuffix);
								msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so.
								ReSituation::self().setRaceMessage(msg, 5);
							}
						}
					}
					
					// Notify the UI when a lap is completed (by the leader)
					// and race results have been updated.
					if (car->_pos == 1)
						ReUI().onLapCompleted(car->_laps - 1);

				} else {
					// Prevent infinite looping of cars around track,
					// allowing one lap after finish for the first car, but no more
					for (i = 0; i < s->_ncars; i++) {
						s->cars[i]->_state |= RM_CAR_STATE_FINISH;
					}
					return;
				}

			} else {
				info->lapFlag--;
			}
		}
		if ((info->prevTrkPos.seg->raceInfo & TR_START)
			&& (car->_trkPos.seg->raceInfo & TR_LAST)) {
			/* going backward through the start line */
			info->lapFlag++;
		}
	} // Start Line Crossing


	// Apply race rules (penalties if enabled).
	reCarsApplyRaceRules(car);

	// Update misc car info.
	info->prevTrkPos = car->_trkPos;
	car->_curLapTime = s->currentTime - info->sTime;
	car->_distFromStartLine = car->_trkPos.seg->lgfromstart +
		(car->_trkPos.seg->type == TR_STR ? car->_trkPos.toStart : car->_trkPos.toStart * car->_trkPos.seg->radius);
	car->_distRaced = (car->_laps - 1) * ReInfo->track->length + car->_distFromStartLine;
}
static void
ReManage(tCarElt *car)
{
	int i, pitok;
	tTrackSeg *sseg;
	tdble wseg;
	static float color[] = {0.0, 0.0, 1.0, 1.0};
	tSituation *s = ReInfo->s;
	
	tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]);
	
	if (car->_speed_x > car->_topSpeed) {
		car->_topSpeed = car->_speed_x;
	}

	// For practice and qualif.
	if (car->_speed_x > info->topSpd) {
		info->topSpd = car->_speed_x;
	}
	if (car->_speed_x < info->botSpd) {
		info->botSpd = car->_speed_x;
	}
	
	// Pitstop.
	if (car->_pit) {
		if (car->ctrl.raceCmd & RM_CMD_PIT_ASKED) {
			// Pit already occupied?
			if (car->_pit->pitCarIndex == TR_PIT_STATE_FREE) {
				sprintf(car->ctrl.msg[2], "Can Pit");
			} else {
				sprintf(car->ctrl.msg[2], "Pit Occupied");
			}
			memcpy(car->ctrl.msgColor, color, sizeof(car->ctrl.msgColor));
		}
		
		if (car->_state & RM_CAR_STATE_PIT) {
			car->ctrl.raceCmd &= ~RM_CMD_PIT_ASKED; // clear the flag.
			if (car->_scheduledEventTime < s->currentTime) {
				car->_state &= ~RM_CAR_STATE_PIT;
				car->_pit->pitCarIndex = TR_PIT_STATE_FREE;
				sprintf(buf, "%s pit stop %.1fs", car->_name, info->totalPitTime);
				ReRaceMsgSet(buf, 5);
			} else {
				sprintf(car->ctrl.msg[2], "in pits %.1fs", s->currentTime - info->startPitTime);
			}
		} else if ((car->ctrl.raceCmd & RM_CMD_PIT_ASKED) &&
					car->_pit->pitCarIndex == TR_PIT_STATE_FREE &&	
				   (s->_maxDammage == 0 || car->_dammage <= s->_maxDammage))
		{
			tdble lgFromStart = car->_trkPos.seg->lgfromstart;
			
			switch (car->_trkPos.seg->type) {
				case TR_STR:
					lgFromStart += car->_trkPos.toStart;
					break;
				default:
					lgFromStart += car->_trkPos.toStart * car->_trkPos.seg->radius;
					break;
			}
		
			if ((lgFromStart > car->_pit->lmin) && (lgFromStart < car->_pit->lmax)) {
				pitok = 0;
				int side;
				tdble toBorder;
				if (ReInfo->track->pits.side == TR_RGT) {
					side = TR_SIDE_RGT;
					toBorder = car->_trkPos.toRight;
				} else {
					side = TR_SIDE_LFT;
					toBorder = car->_trkPos.toLeft;
				}
				
				sseg = car->_trkPos.seg->side[side];
				wseg = RtTrackGetWidth(sseg, car->_trkPos.toStart);
				if (sseg->side[side]) {
					sseg = sseg->side[side];
					wseg += RtTrackGetWidth(sseg, car->_trkPos.toStart);
				}
				if (((toBorder + wseg) < (ReInfo->track->pits.width - car->_dimension_y / 2.0)) &&
					(fabs(car->_speed_x) < 1.0) &&
					(fabs(car->_speed_y) < 1.0))
				{
					pitok = 1;
				}
				
				if (pitok) {
					car->_state |= RM_CAR_STATE_PIT;
					car->_nbPitStops++;
					for (i = 0; i < car->_pit->freeCarIndex; i++) {
						if (car->_pit->car[i] == car) {
							car->_pit->pitCarIndex = i;
							break;
						}
					}
					info->startPitTime = s->currentTime;
					sprintf(buf, "%s in pits", car->_name);
					ReRaceMsgSet(buf, 5);
					if (car->robot->rbPitCmd(car->robot->index, car, s) == ROB_PIT_MENU) {
						// the pit cmd is modified by menu.
						ReStop();
						RmPitMenuStart(car, (void*)car, ReUpdtPitCmd);
					} else {
						ReUpdtPitTime(car);
					}
				}
			}
		}
	}
	
	/* Start Line Crossing */
	if (info->prevTrkPos.seg != car->_trkPos.seg) {
	if ((info->prevTrkPos.seg->raceInfo & TR_LAST) && (car->_trkPos.seg->raceInfo & TR_START)) {
		if (info->lapFlag == 0) {
		if ((car->_state & RM_CAR_STATE_FINISH) == 0) {
			car->_laps++;
			car->_remainingLaps--;
			if (car->_laps > 1) {
			car->_lastLapTime = s->currentTime - info->sTime;
			car->_curTime += car->_lastLapTime;
			if (car->_bestLapTime != 0) {
				car->_deltaBestLapTime = car->_lastLapTime - car->_bestLapTime;
			}
			if ((car->_lastLapTime < car->_bestLapTime) || (car->_bestLapTime == 0)) {
				car->_bestLapTime = car->_lastLapTime;
			}
			if (car->_pos != 1) {
				car->_timeBehindLeader = car->_curTime - s->cars[0]->_curTime;
				car->_lapsBehindLeader = s->cars[0]->_laps - car->_laps;
				car->_timeBehindPrev = car->_curTime - s->cars[car->_pos - 2]->_curTime;
				s->cars[car->_pos - 2]->_timeBeforeNext = car->_timeBehindPrev;
			} else {
				car->_timeBehindLeader = 0;
				car->_lapsBehindLeader = 0;
				car->_timeBehindPrev = 0;
			}
			info->sTime = s->currentTime;
			switch (ReInfo->s->_raceType) {
			case RM_TYPE_PRACTICE:
				if (ReInfo->_displayMode == RM_DISP_MODE_NONE) {
				ReInfo->_refreshDisplay = 1;
				char *t1, *t2;
				t1 = GfTime2Str(car->_lastLapTime, 0);
				t2 = GfTime2Str(car->_bestLapTime, 0);
				sprintf(buf,"lap: %02d   time: %s  best: %s  top spd: %.2f    min spd: %.2f    damage: %d",
					car->_laps - 1, t1, t2,
					info->topSpd * 3.6, info->botSpd * 3.6, car->_dammage);
				ReResScreenAddText(buf);
				free(t1);
				free(t2);
				}
				/* save the lap result */
				ReSavePracticeLap(car);
				break;
				
			case RM_TYPE_QUALIF:
				if (ReInfo->_displayMode == RM_DISP_MODE_NONE) {
				ReUpdateQualifCurRes(car);
				}
				break;
			}
			} else {
			if ((ReInfo->_displayMode == RM_DISP_MODE_NONE) && (ReInfo->s->_raceType == RM_TYPE_QUALIF)) {
				ReUpdateQualifCurRes(car);
			}
			}
	
			info->topSpd = car->_speed_x;
			info->botSpd = car->_speed_x;
			if ((car->_remainingLaps < 0) || (s->_raceState == RM_RACE_FINISHING)) {
			car->_state |= RM_CAR_STATE_FINISH;
			s->_raceState = RM_RACE_FINISHING;
			if (ReInfo->s->_raceType == RM_TYPE_RACE) {
				if (car->_pos == 1) {
				sprintf(buf, "Winner %s", car->_name);
				ReRaceBigMsgSet(buf, 10);
				} else {
				const char *numSuffix = "th";
				if (abs(12 - car->_pos) > 1) { /* leave suffix as 'th' for 11 to 13 */
					switch (car->_pos % 10) {
					case 1:
					numSuffix = "st";
					break;
					case 2:
					numSuffix = "nd";
					break;
					case 3:
					numSuffix = "rd";
					break;
					default:
					break;
					}
				}
				sprintf(buf, "%s Finished %d%s", car->_name, car->_pos, numSuffix);
				ReRaceMsgSet(buf, 5);
				}
			}
			}
		} else {
			/* prevent infinite looping of cars around track, allow one lap after finish for the first car */
			for (i = 0; i < s->_ncars; i++) {
				s->cars[i]->_state |= RM_CAR_STATE_FINISH;
			}
			return;
		}
		} else {
		info->lapFlag--;
		}
	}
	if ((info->prevTrkPos.seg->raceInfo & TR_START) && (car->_trkPos.seg->raceInfo & TR_LAST)) {
		/* going backward through the start line */
		info->lapFlag++;
	}
	}
	ReRaceRules(car);
	
	info->prevTrkPos = car->_trkPos;
	car->_curLapTime = s->currentTime - info->sTime;
	car->_distFromStartLine = car->_trkPos.seg->lgfromstart +
	(car->_trkPos.seg->type == TR_STR ? car->_trkPos.toStart : car->_trkPos.toStart * car->_trkPos.seg->radius);
	car->_distRaced = (car->_laps - 1) * ReInfo->track->length + car->_distFromStartLine;
}
Esempio n. 5
0
void ReSituationUpdater::runOneStep(double deltaTimeIncrement)
{
	tRmInfo* pCurrReInfo = ReSituation::self().data();
	tSituation *s = pCurrReInfo->s;

	// Race messages life cycle management.
	ReRaceMsgManage(pCurrReInfo);
	
	if (NetGetNetwork())
	{
		// Resync clock in case computer falls behind
		if (s->currentTime < 0.0)
		{
			s->currentTime = GfTimeClock() - NetGetNetwork()->GetRaceStartTime();
		}

		if (s->currentTime < -2.0)
		{
			std::ostringstream ossMsg;
			ossMsg << "Race will start in " << -(int)s->currentTime << " seconds";
			ReRaceMsgSetBig(pCurrReInfo, ossMsg.str().c_str());
		}
	}

	//GfLogDebug("ReSituationUpdater::runOneStep: currTime=%.3f\n", s->currentTime);
	if (s->currentTime >= -2.0 && s->currentTime < deltaTimeIncrement - 2.0) {
		ReRaceMsgSetBig(pCurrReInfo, "Ready", 1.0);
		GfLogInfo("Ready.\n");
	} else if (s->currentTime >= -1.0 && s->currentTime < deltaTimeIncrement - 1.0) {
		ReRaceMsgSetBig(pCurrReInfo, "Set", 1.0);
		GfLogInfo("Set.\n");
	} else if (s->currentTime >= 0.0 && s->currentTime < deltaTimeIncrement) {
		ReRaceMsgSetBig(pCurrReInfo, "Go", 1.0);
		GfLogInfo("Go.\n");
	}

	// Update times.
	pCurrReInfo->_reCurTime += deltaTimeIncrement * pCurrReInfo->_reTimeMult; /* "Real" time */
	s->currentTime += deltaTimeIncrement; /* Simulated time */

	if (s->currentTime < 0) {
		/* no simu yet */
		pCurrReInfo->s->_raceState = RM_RACE_PRESTART;
	} else if (pCurrReInfo->s->_raceState == RM_RACE_PRESTART) {
		pCurrReInfo->s->_raceState = RM_RACE_RUNNING;
		s->currentTime = 0.0; /* resynchronize */
		pCurrReInfo->_reLastRobTime = 0.0;
	}

	tTrackLocalInfo *trackLocal = &ReInfo->track->local;
	if (s->currentTime > 0 && trackLocal->timeofdayindex == 9) { //RM_VAL_TIME_24HR
		if (s->_totTime > 0) {
			// Scaled on Total Time
			s->accelTime = 24 * 3600 * s->currentTime / s->_totTime;
		} else {
			// Scaled on Number of Laps that the lead driver has completed
			if (s->cars[0]->_laps > 0 && s->cars[0]->_laps <= s->_totLaps) {
				// prevent issues if lead driver crosses line the wrong way
				if (pCurrReInfo->raceEngineInfo.carInfo->lapFlag)
					s->accelTime = s->cars[0]->_laps - 1;
				else
					s->accelTime = s->cars[0]->_laps - 1 + (s->cars[0]->_distFromStartLine / pCurrReInfo->track->length);

				s->accelTime = 24 * 3600 * s->accelTime / s->_totLaps;
			} else
				s->accelTime = 0;
		}
	} else
		s->accelTime = s->currentTime;

	GfProfStartProfile("rbDrive*");
	GfSchedBeginEvent("raceupdate", "robots");
	if ((s->currentTime - pCurrReInfo->_reLastRobTime) >= RCM_MAX_DT_ROBOTS) {
		s->deltaTime = s->currentTime - pCurrReInfo->_reLastRobTime;
		tRobotItf *robot;
		for (int i = 0; i < s->_ncars; i++) {
			if ((s->cars[i]->_state & RM_CAR_STATE_NO_SIMU) == 0) {
				robot = s->cars[i]->robot;
				robot->rbDrive(robot->index, s->cars[i], s);
			}
			else if (! (s->cars[i]->_state & RM_CAR_STATE_ENDRACE_CALLED ) && ( s->cars[i]->_state & RM_CAR_STATE_OUT ) == RM_CAR_STATE_OUT )
			{ // No simu, look if it is out
				robot = s->cars[i]->robot;
				if (robot->rbEndRace)
					robot->rbEndRace(robot->index, s->cars[i], s);
				s->cars[i]->_state |= RM_CAR_STATE_ENDRACE_CALLED;
			}
		}
		pCurrReInfo->_reLastRobTime = s->currentTime;
	}
	GfSchedEndEvent("raceupdate", "robots");
	GfProfStopProfile("rbDrive*");


	if (NetGetNetwork())
		ReNetworkOneStep();

	GfProfStartProfile("physicsEngine.update*");
	GfSchedBeginEvent("raceupdate", "physics");
	RePhysicsEngine().updateSituation(s, deltaTimeIncrement);
	bool bestLapChanged = false;
	for (int i = 0; i < s->_ncars; i++)
		ReCarsManageCar(s->cars[i], bestLapChanged);

	GfSchedEndEvent("raceupdate", "physics");
	GfProfStopProfile("physicsEngine.update*");
	
	ReCarsSortCars();

	// Update results if a best lap changed
	if (pCurrReInfo->_displayMode == RM_DISP_MODE_NONE && s->_ncars > 1 && bestLapChanged)
	{
		if (pCurrReInfo->s->_raceType == RM_TYPE_PRACTICE)
			ReUpdatePracticeCurRes(pCurrReInfo->s->cars[0]);
		else if (pCurrReInfo->s->_raceType == RM_TYPE_QUALIF)
			ReUpdateQualifCurRes(pCurrReInfo->s->cars[0]);
	}
}
Esempio n. 6
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;
}