Directory restructuring to make it easier to version projects that don't build zdoom.exe.
SVN r4 (trunk)
This commit is contained in:
commit
cf11cbdb30
821 changed files with 361202 additions and 0 deletions
253
src/m_random.cpp
Normal file
253
src/m_random.cpp
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id: m_random.c,v 1.6 1998/05/03 23:13:18 killough Exp $
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Random number LUT.
|
||||
//
|
||||
// 1/19/98 killough: Rewrote random number generator for better randomness,
|
||||
// while at the same time maintaining demo sync and backward compatibility.
|
||||
//
|
||||
// 2/16/98 killough: Made each RNG local to each control-equivalent block,
|
||||
// to reduce the chances of demo sync problems.
|
||||
//
|
||||
// [RH] Changed to use different class instances for different RNGs. Be
|
||||
// sure to compile with _DEBUG if you want to catch bad RNG names.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "doomstat.h"
|
||||
#include "m_random.h"
|
||||
#include "farchive.h"
|
||||
#include "b_bot.h"
|
||||
#include "m_png.h"
|
||||
#include "m_crc32.h"
|
||||
#include "i_system.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "files.h"
|
||||
|
||||
#define RAND_ID MAKE_ID('r','a','N','d')
|
||||
|
||||
FRandom M_Random;
|
||||
|
||||
inline int UpdateSeed (DWORD &seed)
|
||||
{
|
||||
DWORD oldseed = seed;
|
||||
seed = oldseed * 1664525ul + 221297ul;
|
||||
return (int)oldseed;
|
||||
}
|
||||
|
||||
DWORD rngseed = 1993; // killough 3/26/98: The seed
|
||||
|
||||
FRandom *FRandom::RNGList;
|
||||
|
||||
FRandom::FRandom ()
|
||||
: Seed (0), Next (NULL), NameCRC (0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
Name = NULL;
|
||||
#endif
|
||||
Next = RNGList;
|
||||
RNGList = this;
|
||||
}
|
||||
|
||||
FRandom::FRandom (const char *name)
|
||||
: Seed (0)
|
||||
{
|
||||
NameCRC = CalcCRC32 ((const BYTE *)name, (unsigned int)strlen (name));
|
||||
#ifdef _DEBUG
|
||||
Name = name;
|
||||
// A CRC of 0 is reserved for nameless RNGs that don't get stored
|
||||
// in savegames. The chance is very low that you would get a CRC of 0,
|
||||
// but it's still possible.
|
||||
assert (NameCRC != 0);
|
||||
#endif
|
||||
|
||||
// Insert the RNG in the list, sorted by CRC
|
||||
FRandom **prev = &RNGList, *probe = RNGList;
|
||||
|
||||
while (probe != NULL && probe->NameCRC < NameCRC)
|
||||
{
|
||||
prev = &probe->Next;
|
||||
probe = probe->Next;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (probe != NULL)
|
||||
{
|
||||
// Because RNGs are identified by their CRCs in save games,
|
||||
// no two RNGs can have names that hash to the same CRC.
|
||||
// Obviously, this means every RNG must have a unique name.
|
||||
assert (probe->NameCRC != NameCRC);
|
||||
}
|
||||
#endif
|
||||
|
||||
Next = probe;
|
||||
*prev = this;
|
||||
}
|
||||
|
||||
FRandom::~FRandom ()
|
||||
{
|
||||
FRandom *rng, **prev;
|
||||
|
||||
FRandom *last = NULL;
|
||||
|
||||
prev = &RNGList;
|
||||
rng = RNGList;
|
||||
|
||||
while (rng != NULL && rng != this)
|
||||
{
|
||||
last = rng;
|
||||
rng = rng->Next;
|
||||
}
|
||||
|
||||
if (rng != NULL)
|
||||
{
|
||||
*prev = rng->Next;
|
||||
}
|
||||
}
|
||||
|
||||
int FRandom::operator() ()
|
||||
{
|
||||
return (UpdateSeed (Seed) >> 20) & 255;
|
||||
}
|
||||
|
||||
int FRandom::Random2 ()
|
||||
{
|
||||
int t = (UpdateSeed (Seed) >> 20) & 255;
|
||||
int u = (UpdateSeed (Seed) >> 20) & 255;
|
||||
return t - u;
|
||||
}
|
||||
|
||||
int FRandom::Random2 (int mask)
|
||||
{
|
||||
int t = (UpdateSeed (Seed) >> 20) & mask;
|
||||
int u = (UpdateSeed (Seed) >> 20) & mask;
|
||||
return t - u;
|
||||
}
|
||||
|
||||
int FRandom::HitDice (int count)
|
||||
{
|
||||
return (1 + ((UpdateSeed (Seed) >> 20) & 7)) * count;
|
||||
}
|
||||
|
||||
// Initialize all the seeds
|
||||
//
|
||||
// This initialization method is critical to maintaining demo sync.
|
||||
// Each seed is initialized according to its class. killough
|
||||
//
|
||||
|
||||
void FRandom::StaticClearRandom ()
|
||||
{
|
||||
const DWORD seed = rngseed*2+1; // add 3/26/98: add rngseed
|
||||
FRandom *rng = FRandom::RNGList;
|
||||
|
||||
// go through each RNG and set each starting seed differently
|
||||
while (rng != NULL)
|
||||
{
|
||||
// [RH] Use the RNG's name's CRC to modify the original seed.
|
||||
// This way, new RNGs can be added later, and it doesn't matter
|
||||
// which order they get initialized in.
|
||||
rng->Seed = seed * rng->NameCRC;
|
||||
rng = rng->Next;
|
||||
}
|
||||
}
|
||||
|
||||
// This function produces a DWORD that can be used to check the consistancy
|
||||
// of network games between different machines. Only a select few RNGs are
|
||||
// used for the sum, because not all RNGs are important to network sync.
|
||||
|
||||
extern FRandom pr_spawnmobj;
|
||||
extern FRandom pr_acs;
|
||||
extern FRandom pr_chase;
|
||||
extern FRandom pr_lost;
|
||||
extern FRandom pr_slam;
|
||||
|
||||
DWORD FRandom::StaticSumSeeds ()
|
||||
{
|
||||
return pr_spawnmobj.Seed + pr_acs.Seed + pr_chase.Seed + pr_lost.Seed + pr_slam.Seed;
|
||||
}
|
||||
|
||||
void P_WriteRNGState (FILE *file)
|
||||
{
|
||||
FRandom *rng;
|
||||
const DWORD seed = rngseed*2+1;
|
||||
FPNGChunkArchive arc (file, RAND_ID);
|
||||
|
||||
arc << rngseed;
|
||||
|
||||
// Only write those RNGs that have been used
|
||||
for (rng = FRandom::RNGList; rng != NULL; rng = rng->Next)
|
||||
{
|
||||
if (rng->NameCRC != 0 && rng->Seed != seed + rng->NameCRC)
|
||||
{
|
||||
arc << rng->NameCRC << rng->Seed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void P_ReadRNGState (PNGHandle *png)
|
||||
{
|
||||
FRandom *rng;
|
||||
|
||||
size_t len = M_FindPNGChunk (png, RAND_ID);
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
const int rngcount = (int)((len-4) / 8);
|
||||
int i;
|
||||
DWORD crc;
|
||||
|
||||
FPNGChunkArchive arc (png->File->GetFile(), RAND_ID, len);
|
||||
|
||||
arc << rngseed;
|
||||
FRandom::StaticClearRandom ();
|
||||
|
||||
for (i = rngcount; i; --i)
|
||||
{
|
||||
arc << crc;
|
||||
for (rng = FRandom::RNGList; rng != NULL; rng = rng->Next)
|
||||
{
|
||||
if (rng->NameCRC == crc)
|
||||
{
|
||||
arc << rng->Seed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
png->File->ResetFilePtr();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void FRandom::StaticPrintSeeds ()
|
||||
{
|
||||
FRandom *rng = RNGList;
|
||||
|
||||
while (rng != NULL)
|
||||
{
|
||||
Printf ("%s: %08lx\n", rng->Name, rng->Seed);
|
||||
rng = rng->Next;
|
||||
}
|
||||
}
|
||||
|
||||
CCMD (showrngs)
|
||||
{
|
||||
FRandom::StaticPrintSeeds ();
|
||||
}
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue