Don't use rand()%n. The function specified by the ANSI committee is a terrible linear congruential generator. In fact, it's so bad that the low order bit alternates. The algorithm implemented as RandomFloat() seems to be Park and Miller's "minimum standard" generator which is better (but not great). [See Knuth for more information.]

Any place where you would use rand()%n, use RandomInt(0, n) instead.
This commit is contained in:
Steve Checkoway
2006-06-26 12:14:30 +00:00
parent d2d24ceb4b
commit 80698277cf
19 changed files with 49 additions and 43 deletions
+2 -2
View File
@@ -326,7 +326,7 @@ void BGAnimationLayer::LoadFromAniLayerFile( const RString& sPath )
if( sHint.find("startonrandomframe") != RString::npos ) if( sHint.find("startonrandomframe") != RString::npos )
for( unsigned i=0; i<m_SubActors.size(); i++ ) for( unsigned i=0; i<m_SubActors.size(); i++ )
m_SubActors[i]->SetState( rand()%m_SubActors[i]->GetNumStates() ); m_SubActors[i]->SetState( RandomInt(m_SubActors[i]->GetNumStates()) );
if( sHint.find("dontanimate") != RString::npos ) if( sHint.find("dontanimate") != RString::npos )
for( unsigned i=0; i<m_SubActors.size(); i++ ) for( unsigned i=0; i<m_SubActors.size(); i++ )
@@ -519,7 +519,7 @@ void BGAnimationLayer::LoadFromNode( const RString& sDir, const XNode* pNode )
if( bStartOnRandomFrame ) if( bStartOnRandomFrame )
{ {
for( unsigned i=0; i<m_SubActors.size(); i++ ) for( unsigned i=0; i<m_SubActors.size(); i++ )
m_SubActors[i]->SetState( rand()%m_SubActors[i]->GetNumStates() ); m_SubActors[i]->SetState( RandomInt(m_SubActors[i]->GetNumStates()) );
} }
} }
+1 -1
View File
@@ -72,7 +72,7 @@ RString GetRandomFileInDir( RString sDir )
if( asFiles.empty() ) if( asFiles.empty() )
return RString(); return RString();
else else
return asFiles[rand()%asFiles.size()]; return asFiles[RandomInt(asFiles.size())];
} }
+1 -1
View File
@@ -61,7 +61,7 @@ Character* CharacterManager::GetRandomCharacter()
vector<Character*> apCharacters; vector<Character*> apCharacters;
GetCharacters( apCharacters ); GetCharacters( apCharacters );
if( apCharacters.size() ) if( apCharacters.size() )
return apCharacters[rand()%apCharacters.size()]; return apCharacters[RandomInt(apCharacters.size())];
else else
return GetDefaultCharacter(); return GetDefaultCharacter();
} }
+2 -2
View File
@@ -160,7 +160,7 @@ void DancingCharacters::LoadNextSong()
m_pCharacter[p]->PlayAnimation( "rest" ); m_pCharacter[p]->PlayAnimation( "rest" );
} }
int Neg1OrPos1() { return rand()%2 ? -1 : +1; } int Neg1OrPos1() { return RandomInt( 2 ) ? -1 : +1; }
void DancingCharacters::Update( float fDelta ) void DancingCharacters::Update( float fDelta )
{ {
@@ -213,7 +213,7 @@ void DancingCharacters::Update( float fDelta )
// time for a new sweep? // time for a new sweep?
if( GAMESTATE->m_fSongBeat > m_fThisCameraEndBeat ) if( GAMESTATE->m_fSongBeat > m_fThisCameraEndBeat )
{ {
if( (rand()%5) >= 2 ) if( RandomInt(5) >= 2 )
{ {
// sweeping camera // sweeping camera
m_CameraDistance = CAMERA_SWEEP_DISTANCE + RandomInt(-1,1) * CAMERA_SWEEP_DISTANCE_VARIANCE; m_CameraDistance = CAMERA_SWEEP_DISTANCE + RandomInt(-1,1) * CAMERA_SWEEP_DISTANCE_VARIANCE;
+1 -1
View File
@@ -270,7 +270,7 @@ static void DoPlayOnceFromDir( RString sPath )
if( arraySoundFiles.empty() ) if( arraySoundFiles.empty() )
return; return;
int index = rand() % arraySoundFiles.size(); int index = RandomInt( arraySoundFiles.size( ));
SOUNDMAN->PlayOnce( sPath + arraySoundFiles[index] ); SOUNDMAN->PlayOnce( sPath + arraySoundFiles[index] );
} }
+2 -2
View File
@@ -1065,7 +1065,7 @@ bool MusicWheel::Select() // return true if this selection ends the screen
if( m_WheelState == STATE_ROULETTE_SPINNING ) if( m_WheelState == STATE_ROULETTE_SPINNING )
{ {
m_WheelState = STATE_ROULETTE_SLOWING_DOWN; m_WheelState = STATE_ROULETTE_SLOWING_DOWN;
m_iSwitchesLeftInSpinDown = ROULETTE_SLOW_DOWN_SWITCHES/2+1 + rand()%(ROULETTE_SLOW_DOWN_SWITCHES/2); m_iSwitchesLeftInSpinDown = ROULETTE_SLOW_DOWN_SWITCHES/2+1 + RandomInt( ROULETTE_SLOW_DOWN_SWITCHES/2 );
m_fTimeLeftInState = 0.1f; m_fTimeLeftInState = 0.1f;
return false; return false;
} }
@@ -1331,7 +1331,7 @@ Song *MusicWheel::GetPreferredSelectionForRandomOrPortal()
if( i == NUM_PROBES/2 ) if( i == NUM_PROBES/2 )
vDifficultiesToRequire.clear(); vDifficultiesToRequire.clear();
int iSelection = rand() % wid.size(); int iSelection = RandomInt( wid.size() );
if( wid[iSelection].m_Type != TYPE_SONG ) if( wid[iSelection].m_Type != TYPE_SONG )
continue; continue;
+2 -2
View File
@@ -1068,7 +1068,7 @@ static void SuperShuffleTaps( NoteData &inout, int iStartIndex, int iEndIndex )
set<int> vTriedTracks; set<int> vTriedTracks;
for( int i=0; i<4; i++ ) // probe max 4 times for( int i=0; i<4; i++ ) // probe max 4 times
{ {
int t2 = rand() % inout.GetNumTracks(); int t2 = RandomInt( inout.GetNumTracks() );
if( vTriedTracks.find(t2) != vTriedTracks.end() ) // already tried this track if( vTriedTracks.find(t2) != vTriedTracks.end() ) // already tried this track
continue; // skip continue; // skip
vTriedTracks.insert( t2 ); vTriedTracks.insert( t2 );
@@ -1941,7 +1941,7 @@ void NoteDataUtil::AddTapAttacks( NoteData &nd, Song* pSong )
TapNote::attack, TapNote::attack,
TapNote::SubType_invalid, TapNote::SubType_invalid,
TapNote::original, TapNote::original,
szAttacks[rand()%ARRAYSIZE(szAttacks)], szAttacks[RandomInt(ARRAYSIZE(szAttacks))],
15.0f, 15.0f,
false, false,
0 ); 0 );
+2 -2
View File
@@ -460,9 +460,9 @@ void PlayerOptions::ChooseRandomModifiers()
float f; float f;
f = RandomFloat(0,1); f = RandomFloat(0,1);
if( f>0.66f ) if( f>0.66f )
m_fAccels[rand()%NUM_ACCELS] = 1; m_fAccels[RandomInt(NUM_ACCELS)] = 1;
else if( f>0.33f ) else if( f>0.33f )
m_fEffects[rand()%NUM_EFFECTS] = 1; m_fEffects[RandomInt(NUM_EFFECTS)] = 1;
f = RandomFloat(0,1); f = RandomFloat(0,1);
if( f>0.95f ) if( f>0.95f )
m_fAppearances[APPEARANCE_HIDDEN] = 1; m_fAppearances[APPEARANCE_HIDDEN] = 1;
+6
View File
@@ -176,6 +176,12 @@ inline int RandomInt( int nLow, int nHigh )
return int( RandomFloat() * (nHigh - nLow + 1) + nLow ); return int( RandomFloat() * (nHigh - nLow + 1) + nLow );
} }
// Returns an integer between 0 and n-1 inclusive (replacement for rand() % n).
inline int RandomInt( int n )
{
return RandomInt( 0, n-1 );
}
/* Alternative: */ /* Alternative: */
class RandomGen class RandomGen
{ {
+1 -1
View File
@@ -92,7 +92,7 @@ int RandomSample::GetNextToPlay()
int iIndexToPlay = 0; int iIndexToPlay = 0;
for( int i=0; i<5; i++ ) for( int i=0; i<5; i++ )
{ {
iIndexToPlay = rand() % m_pSamples.size(); iIndexToPlay = RandomInt( m_pSamples.size() );
if( iIndexToPlay != m_iIndexLastPlayed ) if( iIndexToPlay != m_iIndexLastPlayed )
break; break;
} }
+2 -2
View File
@@ -131,12 +131,12 @@ void ScoreKeeperRave::LaunchAttack( AttackLevel al )
RString sAttackToGive; RString sAttackToGive;
if (GAMESTATE->m_pCurCharacters[pn] != NULL) if (GAMESTATE->m_pCurCharacters[pn] != NULL)
sAttackToGive = asAttacks[ rand()%NUM_ATTACKS_PER_LEVEL ]; sAttackToGive = asAttacks[ RandomInt(NUM_ATTACKS_PER_LEVEL) ];
else else
{ {
/* If you add any note skins here, you need to make sure they're cached, too. */ /* If you add any note skins here, you need to make sure they're cached, too. */
RString DefaultAttacks[8] = { "1.5x", "2.0x", "0.5x", "reverse", "sudden", "boost", "brake", "wave" }; RString DefaultAttacks[8] = { "1.5x", "2.0x", "0.5x", "reverse", "sudden", "boost", "brake", "wave" };
sAttackToGive = DefaultAttacks[ rand()%8 ]; sAttackToGive = DefaultAttacks[ RandomInt(8) ];
} }
PlayerNumber pnToAttack = OPPOSITE_PLAYER[pn]; PlayerNumber pnToAttack = OPPOSITE_PLAYER[pn];
+5 -5
View File
@@ -650,8 +650,8 @@ static HighScore MakeRandomHighScore( float fPercentDP )
{ {
HighScore hs; HighScore hs;
hs.SetName( "FAKE" ); hs.SetName( "FAKE" );
hs.SetGrade( (Grade)SCALE( rand()%5, 0, 4, Grade_Tier01, Grade_Tier05 ) ); hs.SetGrade( (Grade)SCALE( RandomInt(5), 0, 4, Grade_Tier01, Grade_Tier05 ) );
hs.SetScore( rand()%100*1000 ); hs.SetScore( RandomInt(100*1000) );
hs.SetPercentDP( fPercentDP ); hs.SetPercentDP( fPercentDP );
hs.SetSurviveSeconds( randomf(30.0f, 100.0f) ); hs.SetSurviveSeconds( randomf(30.0f, 100.0f) );
PlayerOptions po; PlayerOptions po;
@@ -660,11 +660,11 @@ static HighScore MakeRandomHighScore( float fPercentDP )
hs.SetDateTime( DateTime::GetNowDateTime() ); hs.SetDateTime( DateTime::GetNowDateTime() );
hs.SetPlayerGuid( Profile::MakeGuid() ); hs.SetPlayerGuid( Profile::MakeGuid() );
hs.SetMachineGuid( Profile::MakeGuid() ); hs.SetMachineGuid( Profile::MakeGuid() );
hs.SetProductID( rand()%10 ); hs.SetProductID( RandomInt(10) );
FOREACH_TapNoteScore( tns ) FOREACH_TapNoteScore( tns )
hs.SetTapNoteScore( tns, rand() % 100 ); hs.SetTapNoteScore( tns, RandomInt(100) );
FOREACH_HoldNoteScore( hns ) FOREACH_HoldNoteScore( hns )
hs.SetHoldNoteScore( hns, rand() % 100 ); hs.SetHoldNoteScore( hns, RandomInt(100) );
RadarValues rv; RadarValues rv;
FOREACH_RadarCategory( rc ) FOREACH_RadarCategory( rc )
rv.m_Values.f[rc] = randomf( 0, 1 ); rv.m_Values.f[rc] = randomf( 0, 1 );
+1 -1
View File
@@ -48,7 +48,7 @@ void ScreenDemonstration::Init()
} }
ASSERT( vStylePossible.size() > 0 ); ASSERT( vStylePossible.size() > 0 );
const Style* pStyle = vStylePossible[ rand() % vStylePossible.size() ]; const Style* pStyle = vStylePossible[ RandomInt(vStylePossible.size()) ];
GAMESTATE->m_pCurStyle.Set( pStyle ); GAMESTATE->m_pCurStyle.Set( pStyle );
} }
+1 -1
View File
@@ -604,7 +604,7 @@ static RString GetOneBakedRandomFile( Song *pSong, bool bTryGenre = true )
vsNamesOut, vsNamesOut,
bTryGenre ); bTryGenre );
if( !vsNamesOut.empty() ) if( !vsNamesOut.empty() )
return vsNamesOut[rand()%vsNamesOut.size()]; return vsNamesOut[RandomInt(vsNamesOut.size())];
else else
return RString(); return RString();
} }
+8 -8
View File
@@ -53,9 +53,9 @@ ScreenEnding::ScreenEnding() : ScreenAttract( false/*dont reset GAMESTATE*/ )
STATSMAN->m_CurStageStats.m_player[PLAYER_2].SetLifeRecordAt( 1-fP1, f ); STATSMAN->m_CurStageStats.m_player[PLAYER_2].SetLifeRecordAt( 1-fP1, f );
} }
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iActualDancePoints = rand()%3; STATSMAN->m_CurStageStats.m_player[PLAYER_1].iActualDancePoints = RandomInt( 3 );
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iPossibleDancePoints = 2; STATSMAN->m_CurStageStats.m_player[PLAYER_1].iPossibleDancePoints = 2;
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iActualDancePoints = rand()%2; STATSMAN->m_CurStageStats.m_player[PLAYER_2].iActualDancePoints = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iPossibleDancePoints = 1; STATSMAN->m_CurStageStats.m_player[PLAYER_2].iPossibleDancePoints = 1;
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iCurCombo = 0; STATSMAN->m_CurStageStats.m_player[PLAYER_1].iCurCombo = 0;
STATSMAN->m_CurStageStats.m_player[PLAYER_1].UpdateComboList( 0, false ); STATSMAN->m_CurStageStats.m_player[PLAYER_1].UpdateComboList( 0, false );
@@ -66,12 +66,12 @@ ScreenEnding::ScreenEnding() : ScreenAttract( false/*dont reset GAMESTATE*/ )
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iCurCombo = 250; STATSMAN->m_CurStageStats.m_player[PLAYER_1].iCurCombo = 250;
STATSMAN->m_CurStageStats.m_player[PLAYER_1].UpdateComboList( 100, false ); STATSMAN->m_CurStageStats.m_player[PLAYER_1].UpdateComboList( 100, false );
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W1] = rand()%2; STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W1] = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W2] = rand()%2; STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W2] = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W3] = rand()%2; STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W3] = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W1] = rand()%2; STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W1] = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W2] = rand()%2; STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W2] = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W3] = rand()%2; STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W3] = RandomInt( 2 );
STATSMAN->m_vPlayedStageStats.clear(); STATSMAN->m_vPlayedStageStats.clear();
} }
+7 -7
View File
@@ -106,7 +106,7 @@ ScreenEvaluation::ScreenEvaluation()
FOREACH_PlayerNumber( p ) FOREACH_PlayerNumber( p )
{ {
if( rand() % 2 ) if( RandomInt(2) )
GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.m_bTransforms[PlayerOptions::TRANSFORM_ECHO] = true; // show "disqualified" GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.m_bTransforms[PlayerOptions::TRANSFORM_ECHO] = true; // show "disqualified"
GAMESTATE->m_bSideIsJoined[p] = true; GAMESTATE->m_bSideIsJoined[p] = true;
@@ -131,9 +131,9 @@ ScreenEvaluation::ScreenEvaluation()
FOREACH_PlayerNumber( p ) FOREACH_PlayerNumber( p )
{ {
float fSeconds = GAMESTATE->m_pCurSong->GetStepsSeconds(); float fSeconds = GAMESTATE->m_pCurSong->GetStepsSeconds();
STATSMAN->m_CurStageStats.m_player[p].iActualDancePoints = rand()%3; STATSMAN->m_CurStageStats.m_player[p].iActualDancePoints = RandomInt( 3 );
STATSMAN->m_CurStageStats.m_player[p].iPossibleDancePoints = 2; STATSMAN->m_CurStageStats.m_player[p].iPossibleDancePoints = 2;
if( rand()%2 ) if( RandomInt(2) )
STATSMAN->m_CurStageStats.m_player[p].iCurCombo = 11000; STATSMAN->m_CurStageStats.m_player[p].iCurCombo = 11000;
else else
STATSMAN->m_CurStageStats.m_player[p].iCurCombo = 0; STATSMAN->m_CurStageStats.m_player[p].iCurCombo = 0;
@@ -154,13 +154,13 @@ ScreenEvaluation::ScreenEvaluation()
STATSMAN->m_CurStageStats.m_player[p].UpdateComboList( 0.50f * fSeconds, false ); STATSMAN->m_CurStageStats.m_player[p].UpdateComboList( 0.50f * fSeconds, false );
STATSMAN->m_CurStageStats.m_player[p].iCurCombo = 100; STATSMAN->m_CurStageStats.m_player[p].iCurCombo = 100;
STATSMAN->m_CurStageStats.m_player[p].UpdateComboList( 1.00f * fSeconds, false ); STATSMAN->m_CurStageStats.m_player[p].UpdateComboList( 1.00f * fSeconds, false );
if( rand()%5 == 0 ) if( RandomInt(5) == 0 )
{ {
STATSMAN->m_CurStageStats.m_player[p].bFailedEarlier = true; STATSMAN->m_CurStageStats.m_player[p].bFailedEarlier = true;
} }
STATSMAN->m_CurStageStats.m_player[p].iTapNoteScores[TNS_W1] = rand()%3; STATSMAN->m_CurStageStats.m_player[p].iTapNoteScores[TNS_W1] = RandomInt( 3 );
STATSMAN->m_CurStageStats.m_player[p].iTapNoteScores[TNS_W2] = rand()%3; STATSMAN->m_CurStageStats.m_player[p].iTapNoteScores[TNS_W2] = RandomInt( 3 );
STATSMAN->m_CurStageStats.m_player[p].iTapNoteScores[TNS_W3] = rand()%3; STATSMAN->m_CurStageStats.m_player[p].iTapNoteScores[TNS_W3] = RandomInt( 3 );
STATSMAN->m_CurStageStats.m_player[p].iPossibleGradePoints = 4*ScoreKeeperNormal::TapNoteScoreToGradePoints(TNS_W1, false); STATSMAN->m_CurStageStats.m_player[p].iPossibleGradePoints = 4*ScoreKeeperNormal::TapNoteScoreToGradePoints(TNS_W1, false);
STATSMAN->m_CurStageStats.m_player[p].fLifeRemainingSeconds = randomf( 90, 580 ); STATSMAN->m_CurStageStats.m_player[p].fLifeRemainingSeconds = randomf( 90, 580 );
} }
+3 -3
View File
@@ -76,7 +76,7 @@ void ScreenJukebox::SetSong()
if( vSongs.size() == 0 ) if( vSongs.size() == 0 )
return; return;
Song* pSong = vSongs[rand()%vSongs.size()]; Song* pSong = vSongs[RandomInt(vSongs.size())];
if( !pSong->HasMusic() ) if( !pSong->HasMusic() )
continue; // skip continue; // skip
@@ -85,7 +85,7 @@ void ScreenJukebox::SetSong()
if( !pSong->ShowInDemonstrationAndRanking() ) if( !pSong->ShowInDemonstrationAndRanking() )
continue; // skip continue; // skip
Difficulty dc = vDifficultiesToShow[ rand()%vDifficultiesToShow.size() ]; Difficulty dc = vDifficultiesToShow[ RandomInt(vDifficultiesToShow.size()) ];
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, GAMESTATE->GetCurrentStyle()->m_StepsType, dc ); Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, GAMESTATE->GetCurrentStyle()->m_StepsType, dc );
if( pSteps == NULL ) if( pSteps == NULL )
@@ -148,7 +148,7 @@ void ScreenJukebox::SetSong()
if( !apOptions.empty() ) if( !apOptions.empty() )
{ {
int iIndex = rand()%apOptions.size(); int iIndex = RandomInt( apOptions.size() );
m_pCourseEntry = apOptions[iIndex]; m_pCourseEntry = apOptions[iIndex];
Course *pCourse = apPossibleCourses[iIndex]; Course *pCourse = apPossibleCourses[iIndex];
@@ -50,7 +50,7 @@ static const DeviceButton g_keys[] =
static DeviceButton GetRandomKeyboardKey() static DeviceButton GetRandomKeyboardKey()
{ {
int index = rand()%ARRAYSIZE(g_keys); int index = RandomInt( ARRAYSIZE(g_keys) );
return g_keys[index]; return g_keys[index];
} }
@@ -42,7 +42,7 @@ bool MemoryCardDriverThreaded_Windows::TestWrite( UsbStorageDevice* pDevice )
* the chance of corruption if the user removes the device immediately, without doing anything. */ * the chance of corruption if the user removes the device immediately, without doing anything. */
for( int i = 0; i < 10; ++i ) for( int i = 0; i < 10; ++i )
{ {
HANDLE hFile = CreateFile( ssprintf( "%stmp%i", pDevice->sOsMountDir.c_str(), rand() % 100000), HANDLE hFile = CreateFile( ssprintf( "%stmp%i", pDevice->sOsMountDir.c_str(), RandomInt(100000)),
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL ); NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL );