Skip to main content
GameDev.net gamedev.net
🔒 Locked

Random numbers in classes

Started by Infuscare Nov 6, 2004 at 9:59 AM 7 replies 1.6k views
Original Post
Infuscare
Infuscare
Hi, I was not sure which forum to put this in, but anyway, here goes: I've got a program that moves around little tanks, with the objective of picking up pellets. Ideally, they are supposed to all start at random locations. When I'm using two, they start at random places, but when I add more, they overlap, and since the logic is the same, they move the same too. Any idea what the problem is? here's the source for the initialization, the classes and some of the logic. And there is an 'srand(time(NULL))' at the beginning of the winmain

inline double RandDble() {return (rand()/(RAND_MAX));}

class TANK
{
protected:
	NEURALNET ANN;
	TARGET_MANAGER *TM;
	TARGET* targeted;
	float tdist, tangle;
	unsigned int fitness;
public:
	TANK(bool randstart=true);
	float position[2];
	float angle;
	TARGET* target;
	
	void RunLogic(void);
	void LockOn(void);
	void Draw(void);
	void Acquire(TARGET* target);
	
	unsigned int GetFitness();
	float GetTangle();
	float GetAngle();
};

TANK::TANK(bool randstart):ANN(5, 1, 1, 5), angle(0.0f)// in(pos,angle,tarangle,tardist),out(tleft,tright),1hid,5/hid
{
	TM=TARGET_MANAGER::GetInstance();
	if(randstart)
	{
position[0] = (float)(RandDble()*50-25);
position[1] = (float)(RandDble()*50-25);
angle = (float)(RandDble()*360);
}
	else
	{position[0] = 0; position[1] = 0;}
}

void TANK::RunLogic(void)
{
	LockOn();

	//Finite State Machine
	float temp;
	temp = tangle + 180;
	if (temp > 360)
		temp -= 360;

	if(temp - angle < 0)
		angle -= 2;
	else if(temp - angle > 0)
		angle += 2;

	if(angle > 370) angle = 10;
	if(angle < -10) angle = 350;
	
	position[0] += (float)(0.05f*cos((double)(angle*PI/180)));
	if(position[0] > 50)
		position[0] = -50;
	else if(position[0] < -50)
		position[0] = 50;
	
	position[1] -= (float)(0.05f*sin((double)(angle*PI/180)));
	if(position[1] > 35)
		position[1] = -30;
	else if(position[1] < -35)
		position[1] = 30;

	Acquire(targeted);
}


about the angles and all, don't ask, the way i did it, it inverted the y-axis, so i had to change a bunch of angle to make them correct... I don't see what could be wrong, some insight would really give me a hand... Ps. I know this is a lot of code to look at, but i'd really apprciate it PPs. You can control one of the tanks with the arrows
___________"You're just jelous because the voices only talk to me"
Dim_Yimma_H
Dim_Yimma_H
To do something about the overlapping you could write a function that checks if the tanks coordinates are too close to each other. "too close" may be the area their image covers. If the function detects that these area rectangles intersects each other move one of them to the border of the other one.

To make them not move the same way you could let the random function generate a 0 or a 1 when there are 2 alternative ways and they will choose which way to go depending on the random number.

\Jimmy H
Infuscare
Infuscare
hmmm, yea, i guess i could do that if i can't find the bug, but i would rather try to solve the problem instead of just working around it though
___________"You're just jelous because the voices only talk to me"
Dmytry
Dmytry
edit: possible problem: inline double RandDble() {return (rand()/(RAND_MAX));} must always return 0, and probably it's not what you want .

****pre-edit post:

ignore that block
I don' see any problems in that piece of code, problem must reside elsewhere, i think.

Also, tank constructor might be called before anything else, and it might badly affect random number generator.


I always prefer to use other random generator instead of rand, you can search in the internet. For example, i'm using
uint32 rseed;
inline int random(int n)// n is range, returned value is >=0 and {
rseed *= 0x08088405;
rseed += 1 ;
return ((uint64)((uint32)rseed))*((uint64)((uint32)n))>>32 ;
}
where uint32 is unsigned 32 bit integer, uint64 is unsigned 64 bit integer. Not worse than most implementations of rand, and much faster.
Xai
Xai
I haven't seen a problem yet, but are you sure RandDble is returning valid values?

it seems it should be written this way:

inline double RandDble() {return ((double)rand()/(RAND_MAX));}
Dmytry
Dmytry
Quote:
Original post by Xai
I haven't seen a problem yet, but are you sure RandDble is returning valid values?

it seems it should be written this way:

inline double RandDble() {return ((double)rand()/(RAND_MAX));}

i would write
inline double RandDble() {return ((double)rand()/((double)RAND_MAX));}
because i'm paranoid about operator precedence[grin]
Xai
Xai
actually this is probably the best:

return static_cast(rand()) / RAND_MAX;

P.S. I removed all unneeded parenthesis too, but you can put back the outermost set if it makes you feel better.

but the set around the (RAND_MAX) really just shouldn't be there ... a parenthesis around a simple value just makes it seem more complicated than it is.
Infuscare
Infuscare
well the rand() function returns an integer, so whether you write (double)rand() or whatever it doesn't make a difference (does it?).

besides, they are random enough to not be the same... here's a sequence of 20 times in a row.

0.00125122
0.563568
0.193298
0.808716
0.584991
0.479858
0.350281
0.895935
0.822815
0.746582
0.174103
0.858917
0.71048
0.513519
0.303986
0.0149841
0.0914001
0.364441
0.147308
0.165894

Ps. Dmytry: what do you mean the tank constructor must be called before anything else...? I tried putting the srand(time()) in the tank constructor, but it doesnt work well there.
___________"You're just jelous because the voices only talk to me"
uavfun
uavfun
Quote:
Original post by Infuscare
well the rand() function returns an integer, so whether you write (double)rand() or whatever it doesn't make a difference (does it?).

rand()/RAND_MAX does integer division because both values are integers. If rand() returns anything less than RAND_MAX, you get 0. double(rand())/double(RAND_MAX) (or one of the variations on that already posted) does floating point division.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.