6f818d4754
git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@170 127b21dd-08f5-0310-b4b7-95ae10353056
242 lines
4.9 KiB
C
242 lines
4.9 KiB
C
/*
|
|
* legacy_random.c
|
|
*
|
|
* Oolite
|
|
*
|
|
* Created by Giles Williams on Sat Apr 03 2004.
|
|
* Copyright (c) 2004 for aegidian.org. All rights reserved.
|
|
*
|
|
|
|
Copyright (c) 2004, Giles C Williams
|
|
All rights reserved.
|
|
|
|
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike License.
|
|
To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.0/
|
|
or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
|
|
|
|
You are free:
|
|
|
|
• to copy, distribute, display, and perform the work
|
|
• to make derivative works
|
|
|
|
Under the following conditions:
|
|
|
|
• Attribution. You must give the original author credit.
|
|
|
|
• Noncommercial. You may not use this work for commercial purposes.
|
|
|
|
• Share Alike. If you alter, transform, or build upon this work,
|
|
you may distribute the resulting work only under a license identical to this one.
|
|
|
|
For any reuse or distribution, you must make clear to others the license terms of this work.
|
|
|
|
Any of these conditions can be waived if you get permission from the copyright holder.
|
|
|
|
Your fair use and other rights are in no way affected by the above.
|
|
|
|
*/
|
|
|
|
#ifdef GNUSTEP
|
|
#include "oolite-linux.h"
|
|
#endif
|
|
#include "legacy_random.h"
|
|
|
|
static struct random_seed rnd_seed;
|
|
|
|
static int checksum;
|
|
void clear_checksum()
|
|
{
|
|
checksum = 0;
|
|
}
|
|
|
|
int munge_checksum(int value)
|
|
{
|
|
int mult1 = (value & 15) + 8;
|
|
checksum += value;
|
|
checksum *= mult1;
|
|
checksum += mult1;
|
|
checksum &= 0xffff;
|
|
return checksum;
|
|
}
|
|
|
|
// cunning price rounding routine:
|
|
//
|
|
float cunningFee(float value)
|
|
{
|
|
float fee = value;
|
|
float superfee = 100000;
|
|
int rounded_fee = superfee * floor(0.5 + fee / superfee);
|
|
if (!rounded_fee)
|
|
rounded_fee = 1;
|
|
float ratio = fee / (float)rounded_fee;
|
|
while (((ratio < 0.95)||(ratio > 1.05))&&(superfee > 1))
|
|
{
|
|
superfee /= 10;
|
|
rounded_fee = superfee * floor(0.5 + fee / superfee);
|
|
if (!rounded_fee)
|
|
rounded_fee = 1;
|
|
ratio = fee / (float)rounded_fee;
|
|
}
|
|
if ((ratio > 0.95)&&(ratio < 1.05))
|
|
fee = rounded_fee;
|
|
return fee;
|
|
}
|
|
|
|
|
|
// an implementation of RANROT
|
|
// pseudo random number generator
|
|
//
|
|
unsigned int m_high;
|
|
unsigned int m_low;
|
|
inline void ranrot_srand(unsigned int seed)
|
|
{
|
|
|
|
// printf("***** DEBUG Random seed %d\n", seed);
|
|
//
|
|
m_low = seed;
|
|
m_high = ~seed;
|
|
ranrot_rand(); ranrot_rand(); ranrot_rand(); // mix it up a bit
|
|
}
|
|
inline int ranrot_rand()
|
|
{
|
|
m_high = (m_high<<16) + (m_high>>16);
|
|
m_high += m_low;
|
|
m_low += m_high;
|
|
return m_high & 0x7FFFFFFF;
|
|
}
|
|
|
|
// a method used to determine interplanetary distances,
|
|
// if accurate, it has to scale distance down by a factor of 7.15:7.0
|
|
// to allow routes navigable in the original!
|
|
double distanceBetweenPlanetPositions ( int x1, int y1, int x2, int y2)
|
|
{
|
|
int dx = x1 - x2;
|
|
int dy = (y1 - y2)/2;
|
|
int dist = sqrt(dx*dx + dy*dy); // here's where the rounding errors come in!
|
|
return 0.4*dist;
|
|
}
|
|
|
|
double accurateDistanceBetweenPlanetPositions ( int x1, int y1, int x2, int y2)
|
|
{
|
|
double dx = x1 - x2;
|
|
double dy = (y1 - y2)/2;
|
|
double dist = sqrt(dx*dx + dy*dy); // here's where the rounding errors come in!
|
|
return 0.4*dist;
|
|
}
|
|
|
|
void seed_for_planet_description (Random_Seed s_seed)
|
|
{
|
|
rnd_seed.a = s_seed.c;
|
|
rnd_seed.b = s_seed.d;
|
|
rnd_seed.c = s_seed.e;
|
|
rnd_seed.d = s_seed.f;
|
|
|
|
ranrot_srand(rnd_seed.a * 0x1000000 + rnd_seed.b * 0x10000 + rnd_seed.c * 0x100 + rnd_seed.d);
|
|
}
|
|
|
|
void seed_RNG_only_for_planet_description (Random_Seed s_seed)
|
|
{
|
|
rnd_seed.a = s_seed.c;
|
|
rnd_seed.b = s_seed.d;
|
|
rnd_seed.c = s_seed.e;
|
|
rnd_seed.d = s_seed.f;
|
|
}
|
|
|
|
RNG_Seed currentRandomSeed (void)
|
|
{
|
|
return rnd_seed;
|
|
}
|
|
|
|
void setRandomSeed (RNG_Seed a_seed)
|
|
{
|
|
rnd_seed = a_seed;
|
|
}
|
|
|
|
|
|
inline float randf (void)
|
|
{
|
|
return 0.0009765625 * (ranrot_rand() & 1023);
|
|
}
|
|
|
|
inline float bellf (int n)
|
|
{
|
|
int i = n;
|
|
float total = 0;
|
|
|
|
if (i <= 0)
|
|
{
|
|
printf("***** ERROR - attempt to generate bellf(%d)\n", n);
|
|
return 0.0; // catch possible div-by-zero problem
|
|
}
|
|
|
|
while (i-- > 0)
|
|
total += (ranrot_rand() & 1023);
|
|
return 0.0009765625 * total / n;
|
|
}
|
|
|
|
int gen_rnd_number (void)
|
|
{
|
|
int a,x;
|
|
|
|
x = (rnd_seed.a * 2) & 0xFF;
|
|
a = x + rnd_seed.c;
|
|
if (rnd_seed.a > 127)
|
|
a++;
|
|
rnd_seed.a = a & 0xFF;
|
|
rnd_seed.c = x;
|
|
|
|
a = a / 256; /* a = any carry left from above */
|
|
x = rnd_seed.b;
|
|
a = (a + x + rnd_seed.d) & 0xFF;
|
|
rnd_seed.b = a;
|
|
rnd_seed.d = x;
|
|
return a;
|
|
}
|
|
|
|
|
|
void rotate_seed (struct rand_seed_6uc *seed_ptr)
|
|
{
|
|
unsigned int x;
|
|
unsigned int y;
|
|
|
|
x = seed_ptr->a + seed_ptr->c;
|
|
y = seed_ptr->b + seed_ptr->d;
|
|
|
|
|
|
if (x > 0xFF)
|
|
y++;
|
|
|
|
x &= 0xFF;
|
|
y &= 0xFF;
|
|
|
|
seed_ptr->a = seed_ptr->c;
|
|
seed_ptr->b = seed_ptr->d;
|
|
seed_ptr->c = seed_ptr->e;
|
|
seed_ptr->d = seed_ptr->f;
|
|
|
|
x += seed_ptr->c;
|
|
y += seed_ptr->d;
|
|
|
|
|
|
if (x > 0xFF)
|
|
y++;
|
|
|
|
x &= 0xFF;
|
|
y &= 0xFF;
|
|
|
|
seed_ptr->e = x;
|
|
seed_ptr->f = y;
|
|
}
|
|
|
|
int rotate_byte_left (int x)
|
|
{
|
|
return ((x << 1) | (x >> 7)) & 255;
|
|
}
|
|
|
|
|
|
int equal_seeds (Random_Seed seed1, Random_Seed seed2)
|
|
{
|
|
return ((seed1.a == seed2.a)&&(seed1.b == seed2.b)&&(seed1.c == seed2.c)&&(seed1.d == seed2.d)&&(seed1.e == seed2.e)&&(seed1.f == seed2.f));
|
|
}
|
|
|