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 )
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 )
for( unsigned i=0; i<m_SubActors.size(); i++ )
@@ -519,7 +519,7 @@ void BGAnimationLayer::LoadFromNode( const RString& sDir, const XNode* pNode )
if( bStartOnRandomFrame )
{
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() )
return RString();
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;
GetCharacters( apCharacters );
if( apCharacters.size() )
return apCharacters[rand()%apCharacters.size()];
return apCharacters[RandomInt(apCharacters.size())];
else
return GetDefaultCharacter();
}
+2 -2
View File
@@ -160,7 +160,7 @@ void DancingCharacters::LoadNextSong()
m_pCharacter[p]->PlayAnimation( "rest" );
}
int Neg1OrPos1() { return rand()%2 ? -1 : +1; }
int Neg1OrPos1() { return RandomInt( 2 ) ? -1 : +1; }
void DancingCharacters::Update( float fDelta )
{
@@ -213,7 +213,7 @@ void DancingCharacters::Update( float fDelta )
// time for a new sweep?
if( GAMESTATE->m_fSongBeat > m_fThisCameraEndBeat )
{
if( (rand()%5) >= 2 )
if( RandomInt(5) >= 2 )
{
// sweeping camera
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() )
return;
int index = rand() % arraySoundFiles.size();
int index = RandomInt( arraySoundFiles.size( ));
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 )
{
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;
return false;
}
@@ -1331,7 +1331,7 @@ Song *MusicWheel::GetPreferredSelectionForRandomOrPortal()
if( i == NUM_PROBES/2 )
vDifficultiesToRequire.clear();
int iSelection = rand() % wid.size();
int iSelection = RandomInt( wid.size() );
if( wid[iSelection].m_Type != TYPE_SONG )
continue;
+2 -2
View File
@@ -1068,7 +1068,7 @@ static void SuperShuffleTaps( NoteData &inout, int iStartIndex, int iEndIndex )
set<int> vTriedTracks;
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
continue; // skip
vTriedTracks.insert( t2 );
@@ -1941,7 +1941,7 @@ void NoteDataUtil::AddTapAttacks( NoteData &nd, Song* pSong )
TapNote::attack,
TapNote::SubType_invalid,
TapNote::original,
szAttacks[rand()%ARRAYSIZE(szAttacks)],
szAttacks[RandomInt(ARRAYSIZE(szAttacks))],
15.0f,
false,
0 );
+2 -2
View File
@@ -460,9 +460,9 @@ void PlayerOptions::ChooseRandomModifiers()
float f;
f = RandomFloat(0,1);
if( f>0.66f )
m_fAccels[rand()%NUM_ACCELS] = 1;
m_fAccels[RandomInt(NUM_ACCELS)] = 1;
else if( f>0.33f )
m_fEffects[rand()%NUM_EFFECTS] = 1;
m_fEffects[RandomInt(NUM_EFFECTS)] = 1;
f = RandomFloat(0,1);
if( f>0.95f )
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 );
}
// Returns an integer between 0 and n-1 inclusive (replacement for rand() % n).
inline int RandomInt( int n )
{
return RandomInt( 0, n-1 );
}
/* Alternative: */
class RandomGen
{
+1 -1
View File
@@ -92,7 +92,7 @@ int RandomSample::GetNextToPlay()
int iIndexToPlay = 0;
for( int i=0; i<5; i++ )
{
iIndexToPlay = rand() % m_pSamples.size();
iIndexToPlay = RandomInt( m_pSamples.size() );
if( iIndexToPlay != m_iIndexLastPlayed )
break;
}
+2 -2
View File
@@ -131,12 +131,12 @@ void ScoreKeeperRave::LaunchAttack( AttackLevel al )
RString sAttackToGive;
if (GAMESTATE->m_pCurCharacters[pn] != NULL)
sAttackToGive = asAttacks[ rand()%NUM_ATTACKS_PER_LEVEL ];
sAttackToGive = asAttacks[ RandomInt(NUM_ATTACKS_PER_LEVEL) ];
else
{
/* 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" };
sAttackToGive = DefaultAttacks[ rand()%8 ];
sAttackToGive = DefaultAttacks[ RandomInt(8) ];
}
PlayerNumber pnToAttack = OPPOSITE_PLAYER[pn];
+5 -5
View File
@@ -650,8 +650,8 @@ static HighScore MakeRandomHighScore( float fPercentDP )
{
HighScore hs;
hs.SetName( "FAKE" );
hs.SetGrade( (Grade)SCALE( rand()%5, 0, 4, Grade_Tier01, Grade_Tier05 ) );
hs.SetScore( rand()%100*1000 );
hs.SetGrade( (Grade)SCALE( RandomInt(5), 0, 4, Grade_Tier01, Grade_Tier05 ) );
hs.SetScore( RandomInt(100*1000) );
hs.SetPercentDP( fPercentDP );
hs.SetSurviveSeconds( randomf(30.0f, 100.0f) );
PlayerOptions po;
@@ -660,11 +660,11 @@ static HighScore MakeRandomHighScore( float fPercentDP )
hs.SetDateTime( DateTime::GetNowDateTime() );
hs.SetPlayerGuid( Profile::MakeGuid() );
hs.SetMachineGuid( Profile::MakeGuid() );
hs.SetProductID( rand()%10 );
hs.SetProductID( RandomInt(10) );
FOREACH_TapNoteScore( tns )
hs.SetTapNoteScore( tns, rand() % 100 );
hs.SetTapNoteScore( tns, RandomInt(100) );
FOREACH_HoldNoteScore( hns )
hs.SetHoldNoteScore( hns, rand() % 100 );
hs.SetHoldNoteScore( hns, RandomInt(100) );
RadarValues rv;
FOREACH_RadarCategory( rc )
rv.m_Values.f[rc] = randomf( 0, 1 );
+1 -1
View File
@@ -48,7 +48,7 @@ void ScreenDemonstration::Init()
}
ASSERT( vStylePossible.size() > 0 );
const Style* pStyle = vStylePossible[ rand() % vStylePossible.size() ];
const Style* pStyle = vStylePossible[ RandomInt(vStylePossible.size()) ];
GAMESTATE->m_pCurStyle.Set( pStyle );
}
+1 -1
View File
@@ -604,7 +604,7 @@ static RString GetOneBakedRandomFile( Song *pSong, bool bTryGenre = true )
vsNamesOut,
bTryGenre );
if( !vsNamesOut.empty() )
return vsNamesOut[rand()%vsNamesOut.size()];
return vsNamesOut[RandomInt(vsNamesOut.size())];
else
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_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_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_1].iCurCombo = 0;
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].UpdateComboList( 100, false );
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W1] = rand()%2;
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W2] = rand()%2;
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W3] = rand()%2;
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W1] = rand()%2;
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W2] = rand()%2;
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W3] = rand()%2;
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W1] = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W2] = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_W3] = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W1] = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W2] = RandomInt( 2 );
STATSMAN->m_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_W3] = RandomInt( 2 );
STATSMAN->m_vPlayedStageStats.clear();
}
+7 -7
View File
@@ -106,7 +106,7 @@ ScreenEvaluation::ScreenEvaluation()
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_bSideIsJoined[p] = true;
@@ -131,9 +131,9 @@ ScreenEvaluation::ScreenEvaluation()
FOREACH_PlayerNumber( p )
{
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;
if( rand()%2 )
if( RandomInt(2) )
STATSMAN->m_CurStageStats.m_player[p].iCurCombo = 11000;
else
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].iCurCombo = 100;
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].iTapNoteScores[TNS_W1] = rand()%3;
STATSMAN->m_CurStageStats.m_player[p].iTapNoteScores[TNS_W2] = rand()%3;
STATSMAN->m_CurStageStats.m_player[p].iTapNoteScores[TNS_W3] = rand()%3;
STATSMAN->m_CurStageStats.m_player[p].iTapNoteScores[TNS_W1] = RandomInt( 3 );
STATSMAN->m_CurStageStats.m_player[p].iTapNoteScores[TNS_W2] = RandomInt( 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].fLifeRemainingSeconds = randomf( 90, 580 );
}
+3 -3
View File
@@ -76,7 +76,7 @@ void ScreenJukebox::SetSong()
if( vSongs.size() == 0 )
return;
Song* pSong = vSongs[rand()%vSongs.size()];
Song* pSong = vSongs[RandomInt(vSongs.size())];
if( !pSong->HasMusic() )
continue; // skip
@@ -85,7 +85,7 @@ void ScreenJukebox::SetSong()
if( !pSong->ShowInDemonstrationAndRanking() )
continue; // skip
Difficulty dc = vDifficultiesToShow[ rand()%vDifficultiesToShow.size() ];
Difficulty dc = vDifficultiesToShow[ RandomInt(vDifficultiesToShow.size()) ];
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, GAMESTATE->GetCurrentStyle()->m_StepsType, dc );
if( pSteps == NULL )
@@ -148,7 +148,7 @@ void ScreenJukebox::SetSong()
if( !apOptions.empty() )
{
int iIndex = rand()%apOptions.size();
int iIndex = RandomInt( apOptions.size() );
m_pCourseEntry = apOptions[iIndex];
Course *pCourse = apPossibleCourses[iIndex];
@@ -50,7 +50,7 @@ static const DeviceButton g_keys[] =
static DeviceButton GetRandomKeyboardKey()
{
int index = rand()%ARRAYSIZE(g_keys);
int index = RandomInt( ARRAYSIZE(g_keys) );
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. */
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,
NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL );