Permalink
Browse files

Merge pull request #17 from VanNostrand/rng

slightly fairer RNG
  • Loading branch information...
2 parents fe29971 + 2bef958 commit 3a9b5cd7d8bad0faf864addf9401bd31463991ae @lynxlynxlynx lynxlynxlynx committed May 30, 2014
View
@@ -152,6 +152,8 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
if (NOT APPLE AND NOT UNSAFE_PLUGIN)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined")
endif (NOT APPLE AND NOT UNSAFE_PLUGIN)
+ # GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning
+ ADD_DEFINITIONS("-DSFMT_MEXP=19937")
ENDIF()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
@@ -27,6 +27,7 @@
#include "Map.h"
#include "Sprite2D.h"
#include "Video.h"
+#include "RNG/RNG_SFMT.h"
namespace GemRB {
@@ -35,7 +36,7 @@ Animation::Animation(int count)
frames = (Sprite2D **) calloc(count, sizeof(Sprite2D *));
indicesCount = count;
if (count) {
- pos = rand() % count;
+ pos = RAND(0, count-1);
}
else {
pos = 0;
@@ -118,6 +118,8 @@ FILE(GLOB gemrb_core_LIB_SRCS
GUI/TextEdit.cpp
GUI/Window.cpp
GUI/WorldMapControl.cpp
+ RNG/RNG_SFMT.cpp
+ RNG/sfmt/SFMT.c
Scriptable/Actor.cpp
Scriptable/CombatInfo.cpp
Scriptable/Container.cpp
@@ -30,6 +30,7 @@
#include "Interface.h"
#include "Map.h"
#include "Palette.h"
+#include "RNG/RNG_SFMT.h"
namespace GemRB {
@@ -1406,7 +1407,7 @@ void CharAnimations::AddPSTSuffix(char* ResRef, unsigned char StanceID,
Prefix="wlk"; break;
case IE_ANI_HEAD_TURN:
Cycle=SixteenToFive[Orient];
- if (rand()&1) {
+ if (RAND(0,1)) {
Prefix="sf2";
sprintf(ResRef,"%c%3s%4s",this->ResRef[0], Prefix, this->ResRef+1);
if (gamedata->Exists(ResRef, IE_BAM_CLASS_ID) ) {
@@ -1792,7 +1793,7 @@ void CharAnimations::AddVHRSuffix(char* ResRef, unsigned char StanceID,
break;
case IE_ANI_HEAD_TURN:
- if (rand()&1) {
+ if (RAND(0,1)) {
strcat( ResRef, "g12" );
Cycle += 18;
} else {
@@ -27,6 +27,7 @@
#include "GlobalTimer.h"
#include "Interface.h"
#include "GUI/Button.h"
+#include "RNG/RNG_SFMT.h"
namespace GemRB {
@@ -88,11 +89,14 @@ void ControlAnimation::UpdateAnimation(bool paused)
if (anim_phase == 0) {
frame = 0;
anim_phase = 1;
- time = 500 + 500 * (rand() % 20);
+ // note: the granularity of time should be
+ // one of twenty values from [500, 10000]
+ // but not the full range.
+ time = 500 + 500 * RAND(0, 19);
cycle&=~1;
Cycle=cycle;
} else if (anim_phase == 1) {
- if (rand() % 30 == 0) {
+ if (!RAND(0,29)) {
cycle|=1;
Cycle=cycle;
}
@@ -23,6 +23,7 @@
#include "win32def.h"
#include "GameScript/GameScript.h"
+#include "RNG/RNG_SFMT.h"
namespace GemRB {
@@ -85,7 +86,7 @@ int Dialog::FindRandomState(Scriptable* target)
unsigned int i;
unsigned int max = TopLevelCount;
if (!max) return -1;
- unsigned int pick = rand()%max;
+ unsigned int pick = RAND(0, max-1);
for (i=pick; i < max; i++) {
Condition *cond = GetState(i)->condition;
if (cond && cond->Evaluate(target)) {
@@ -41,6 +41,7 @@
#include "GUI/EventMgr.h"
#include "GUI/TextArea.h"
#include "GUI/Window.h"
+#include "RNG/RNG_SFMT.h"
#include "Scriptable/Container.h"
#include "Scriptable/Door.h"
#include "Scriptable/InfoPoint.h"
@@ -839,7 +840,7 @@ bool GameControl::OnKeyRelease(unsigned char Key, unsigned short Mod)
Actor *target;
int i = game->GetPartySize(true);
if(i<2) break;
- i=rand()%i;
+ i=RAND(0, i-1);
do
{
target = game->GetPC(i, true);
@@ -972,7 +973,7 @@ bool GameControl::OnKeyRelease(unsigned char Key, unsigned short Mod)
core->GetDictionary()->DebugDump();
break;
case 'v': //marks some of the map visited (random vision distance)
- area->ExploreMapChunk( p, rand()%30, 1 );
+ area->ExploreMapChunk( p, RAND(0,29), 1 );
break;
case 'w': // consolidates found ground piles under the pointed pc
area->MoveVisibleGroundPiles(p);
@@ -44,6 +44,7 @@
#include "WorldMap.h"
#include "GUI/GameControl.h"
#include "GUI/EventMgr.h"
+#include "RNG/RNG_SFMT.h"
#include "Scriptable/Container.h"
#include "Scriptable/Door.h"
#include "Scriptable/InfoPoint.h"
@@ -988,7 +989,7 @@ void GameScript::WaitRandom(Scriptable* Sender, Action* parameters)
if (width<2) {
width = parameters->int0Parameter;
} else {
- width = rand() % width + parameters->int0Parameter;
+ width = RAND(0, width-1) + parameters->int0Parameter;
}
Sender->CurrentActionState = width * AI_UPDATE_TIME;
} else {
@@ -1041,7 +1042,7 @@ void GameScript::SmallWaitRandom(Scriptable* Sender, Action* parameters)
if (random<1) {
random = 1;
}
- Sender->CurrentActionState = rand() % random + parameters->int0Parameter;
+ Sender->CurrentActionState = RAND(0, random-1) + parameters->int0Parameter;
} else {
Sender->CurrentActionState--;
}
@@ -1679,7 +1680,7 @@ void GameScript::FloatMessageFixedRnd(Scriptable* Sender, Action* parameters)
Log(ERROR, "GameScript", "Cannot display resource!");
return;
}
- DisplayStringCore(target, rndstr->at(rand()%rndstr->size()), DS_CONSOLE|DS_HEAD);
+ DisplayStringCore(target, rndstr->at(RAND(0, rndstr->size()-1)), DS_CONSOLE|DS_HEAD);
FreeSrc(rndstr, parameters->string0Parameter);
}
@@ -1696,7 +1697,7 @@ void GameScript::FloatMessageRnd(Scriptable* Sender, Action* parameters)
Log(ERROR, "GameScript", "Cannot display resource!");
return;
}
- DisplayStringCore(target, rndstr->at(rand()%rndstr->size()), DS_CONSOLE|DS_HEAD);
+ DisplayStringCore(target, rndstr->at(RAND(0, rndstr->size()-1)), DS_CONSOLE|DS_HEAD);
FreeSrc(rndstr, parameters->string0Parameter);
}
@@ -5395,7 +5396,7 @@ void GameScript::RandomFly(Scriptable* Sender, Action* /*parameters*/)
return;
}
Actor* actor = ( Actor* ) Sender;
- int x = rand()&31;
+ int x = RAND(0,31);
if (x<10) {
actor->SetOrientation(actor->GetOrientation()-1, false);
} else if (x>20) {
@@ -5646,7 +5647,7 @@ void GameScript::RandomTurn(Scriptable* Sender, Action* /*parameters*/)
return;
}
Actor *actor = (Actor *) Sender;
- actor->SetOrientation(rand() % MAX_ORIENT, true);
+ actor->SetOrientation(RAND(0, MAX_ORIENT-1), true);
actor->SetWait( 1 );
Sender->ReleaseCurrentAction(); // todo, blocking?
}
@@ -44,6 +44,7 @@
#include "Video.h"
#include "WorldMap.h"
#include "GUI/GameControl.h"
+#include "RNG/RNG_SFMT.h"
#include "Scriptable/Container.h"
#include "Scriptable/Door.h"
#include "Scriptable/InfoPoint.h"
@@ -2479,7 +2480,7 @@ void SetupWishCore(Scriptable *Sender, int column, int picks)
}
} else {
for(i=0;i<picks;i++) {
- selects[i]=rand()%count;
+ selects[i]=RAND(0, count-1);
retry:
for(j=0;j<i;j++) {
if(selects[i]==selects[j]) {
@@ -30,6 +30,7 @@
#include "Interface.h"
#include "PluginMgr.h"
#include "TableMgr.h"
+#include "RNG/RNG_SFMT.h"
#include "System/StringBuffer.h"
namespace GemRB {
@@ -1952,7 +1953,7 @@ bool GameScript::Update(bool *continuing, bool *done)
bool continueExecution = false;
if (continuing) continueExecution = *continuing;
- RandomNumValue=rand();
+ RandomNumValue=RNG_SFMT::getInstance()->rand();
for (size_t a = 0; a < script->responseBlocks.size(); a++) {
ResponseBlock* rB = script->responseBlocks[a];
if (rB->condition->Evaluate(MySelf)) {
@@ -2258,7 +2259,7 @@ int ResponseSet::Execute(Scriptable* Sender)
maxWeight += responses[i]->weight;
}
if (maxWeight) {
- randWeight = rand() % maxWeight;
+ randWeight = RAND(0, maxWeight-1);
}
else {
randWeight = 0;
@@ -25,6 +25,7 @@
#include "Interface.h"
#include "Video.h"
#include "GUI/GameControl.h"
+#include "RNG/RNG_SFMT.h"
namespace GemRB {
@@ -139,10 +140,10 @@ void GlobalTimer::DoStep(int count)
}
if (shakeCounter) {
if (shakeX) {
- x += rand()%shakeX;
+ x += RAND(0, shakeX-1);
}
if (shakeY) {
- y += rand()%shakeY;
+ y += RAND(0, shakeY-1);
}
}
}
@@ -81,6 +81,7 @@
#include "GUI/TextArea.h"
#include "GUI/Window.h"
#include "GUI/WorldMapControl.h"
+#include "RNG/RNG_SFMT.h"
#include "Scriptable/Container.h"
#include "System/FileStream.h"
#include "System/VFS.h"
@@ -90,8 +91,6 @@
#include <unistd.h>
#endif
-#include <cstdlib>
-#include <time.h>
#include <vector>
namespace GemRB {
@@ -1658,10 +1657,6 @@ int Interface::Init(InterfaceConfig* config)
}
plugin->RunInitializers();
- time_t t;
- t = time( NULL );
- srand( ( unsigned int ) t );
-
Log(MESSAGE, "Core", "GemRB Core Initialization...");
Log(MESSAGE, "Core", "Initializing Video Driver...");
video = ( Video * ) PluginMgr::Get()->GetDriver(&Video::ID, VideoDriverName.c_str());
@@ -3678,7 +3673,7 @@ int Interface::Roll(int dice, int size, int add) const
return add + dice * size / 2;
}
for (int i = 0; i < dice; i++) {
- add += rand() % size + 1;
+ add += RAND(1, size);
}
return add;
}
View
@@ -51,6 +51,7 @@
#include "GameScript/GSUtils.h"
#include "GUI/GameControl.h"
#include "GUI/Window.h"
+#include "RNG/RNG_SFMT.h"
#include "Scriptable/Container.h"
#include "Scriptable/Door.h"
#include "Scriptable/InfoPoint.h"
@@ -2411,7 +2412,7 @@ void Map::AdjustPosition(Point &goal, unsigned int radiusx, unsigned int radiusy
while(radiusx<Width || radiusy<Height) {
//lets make it slightly random where the actor will appear
- if (rand()&1) {
+ if (RAND(0,1)) {
if (AdjustPositionX(goal, radiusx, radiusy)) {
return;
}
@@ -3126,7 +3127,7 @@ void Map::TriggerSpawn(Spawn *spawn)
//check day or night chance
bool day = core->GetGame()->IsDay();
- int chance = rand() % 100;
+ int chance = RAND(0, 99);
if ((day && chance > spawn->DayChance) ||
(!day && chance > spawn->NightChance)) {
spawn->NextSpawn = time + spawn->Frequency * AI_UPDATE_TIME * 60;
@@ -3135,7 +3136,7 @@ void Map::TriggerSpawn(Spawn *spawn)
}
//create spawns
int difficulty = spawn->Difficulty * core->GetGame()->GetPartyLevel(true);
- unsigned int spawncount = 0, i = rand() % spawn->Count;
+ unsigned int spawncount = 0, i = RAND(0, spawn->Count-1);
while (difficulty >= 0 && spawncount < spawn->Maximum) {
if (!SpawnCreature(spawn->Pos, spawn->Creatures[i], 0, 0, &difficulty, &spawncount)) {
break;
@@ -3192,13 +3193,13 @@ int Map::CheckRestInterruptsAndPassTime(const Point &pos, int hours, int day)
//based on ingame timer
int chance=day?RestHeader.DayChance:RestHeader.NightChance;
- bool interrupt = rand()%100 < chance;
+ bool interrupt = (int) RAND(0, 99) < chance;
unsigned int spawncount = 0;
int spawnamount = core->GetGame()->GetPartyLevel(true) * RestHeader.Difficulty;
if (spawnamount < 1) spawnamount = 1;
for (int i=0;i<hours;i++) {
if (interrupt) {
- int idx = rand()%RestHeader.CreatureNum;
+ int idx = RAND(0, RestHeader.CreatureNum-1);
Actor *creature = gamedata->GetCreature(RestHeader.CreResRef[idx]);
if (!creature) {
core->GetGame()->AdvanceTime(300*AI_UPDATE_TIME);
@@ -33,6 +33,7 @@
#include "Sprite2D.h"
#include "VEFObject.h"
#include "Video.h"
+#include "RNG/RNG_SFMT.h"
#include "Scriptable/Actor.h"
#include <cmath>
@@ -140,7 +141,7 @@ void Projectile::CreateAnimations(Animation **anims, const ieResRef bamres, int
}
if((ExtFlags&PEF_CYCLE) && !Seq) {
- Seq=rand()%Max;
+ Seq=RAND(0, Max-1);
}
//this hack is needed because bioware .pro files are sometimes
@@ -1478,7 +1479,7 @@ void Projectile::DrawExplosion(const Region &screen)
if (children[i])
continue;
if(apflags&APF_BOTH) {
- if(rand()&1) {
+ if(RAND(0,1)) {
tmp = Extension->Secondary;
} else {
tmp = Extension->Spread;
@@ -1522,12 +1523,12 @@ void Projectile::DrawExplosion(const Region &screen)
//a bit of difference in case crowding is needed
//make this a separate flag if speed difference
//is not always wanted
- pro->Speed-=rand()&7;
+ pro->Speed-=RAND(0,7);
delay = Extension->Delay*extension_explosioncount;
if(apflags&APF_BOTH) {
if (delay) {
- delay = rand()%delay;
+ delay = RAND(0, delay-1);
}
}
//this needs to be commented out for ToB horrid wilting
Oops, something went wrong.

0 comments on commit 3a9b5cd

Please sign in to comment.