- Added random2 function to DECORATE's expression evaluator. This is to

better emulate some calculation of internal code pointers.
- Added named RNG support to DECORATE's expression evaluator. Just use
  random[name](min, max).


SVN r391 (trunk)
This commit is contained in:
Christoph Oelckers 2006-11-26 12:13:12 +00:00
parent 04b80f8de5
commit d840d9b68a
8 changed files with 133 additions and 43 deletions

View file

@ -1,3 +1,9 @@
November 26, 2006 (Changes by Graf Zahl)
- Added random2 function to DECORATE's expression evaluator. This is to
better emulate some calculation of internal code pointers.
- Added named RNG support to DECORATE's expression evaluator. Just use
random[name](min, max).
November 25, 2006 November 25, 2006
- Reverted updaterevision.vcproj to r385 and added a note as a build event - Reverted updaterevision.vcproj to r385 and added a note as a build event
explaining the need to use mt.exe 6.0 or newer. Here is the note: explaining the need to use mt.exe 6.0 or newer. Here is the note:

View file

@ -250,6 +250,53 @@ void FRandom::StaticReadRNGState (PNGHandle *png)
} }
} }
// This function attempts to find an RNG with the given name.
// If it can't it will create a new one. Duplicate CRCs will
// be ignored and if it happens map to the same RNG.
// This is for use by DECORATE.
extern FRandom pr_exrandom;
class NewRNGList : public TArray<FRandom*>
{
public:
~NewRNGList()
{
for(unsigned i=0;i<Size();i++)
{
delete (*this)[i];
}
}
};
static NewRNGList NewRNGs;
FRandom *FRandom::StaticFindRNG (const char *name)
{
DWORD NameCRC = CalcCRC32 ((const BYTE *)name, (unsigned int)strlen (name));
// Use the default RNG if this one happens to have a CRC of 0.
if (NameCRC==0) return &pr_exrandom;
// Find 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;
}
// Found one so return it.
if (probe == NULL || probe->NameCRC != NameCRC)
{
// A matching RNG doesn't exist yet so create it.
probe = new FRandom(name);
// Store the new RNG for destruction when ZDoom quits.
NewRNGs.Push(probe);
}
return probe;
}
#ifdef _DEBUG #ifdef _DEBUG
void FRandom::StaticPrintSeeds () void FRandom::StaticPrintSeeds ()
{ {
@ -267,3 +314,4 @@ CCMD (showrngs)
FRandom::StaticPrintSeeds (); FRandom::StaticPrintSeeds ();
} }
#endif #endif

View file

@ -77,6 +77,7 @@ public:
static DWORD StaticSumSeeds (); static DWORD StaticSumSeeds ();
static void StaticReadRNGState (PNGHandle *png); static void StaticReadRNGState (PNGHandle *png);
static void StaticWriteRNGState (FILE *file); static void StaticWriteRNGState (FILE *file);
static FRandom *StaticFindRNG(const char *name);
#ifdef _DEBUG #ifdef _DEBUG
static void StaticPrintSeeds (); static void StaticPrintSeeds ();

View file

@ -1066,32 +1066,6 @@ typedef ActorProps (*ActorPropHandler) (register const char *str, register unsig
static const ActorProps *is_actorprop (const char *str); static const ActorProps *is_actorprop (const char *str);
//==========================================================================
//
// Some functions which check for simple tokens
//
//==========================================================================
inline void ChkCom()
{
SC_MustGetStringName (",");
}
inline void ChkBraceOpn()
{
SC_MustGetStringName ("{");
}
inline bool TestBraceCls()
{
return SC_CheckString ("}");
}
inline bool TestCom()
{
return SC_CheckString (",");
}
//========================================================================== //==========================================================================
// //
// Find a state address // Find a state address
@ -1610,7 +1584,7 @@ bool DoSpecialFunctions(FState & state, bool multistate, int * statecount, Bagga
{ {
StateParameters[paramindex+i+1]=ParseExpression (false); StateParameters[paramindex+i+1]=ParseExpression (false);
i++; i++;
if (!TestCom()) break; if (!SC_CheckString (",")) break;
} }
SC_MustGetStringName (")"); SC_MustGetStringName (")");
} }
@ -1719,9 +1693,9 @@ static int ProcessStates(FActorInfo * actor, AActor * defaults, Baggage &bag)
intptr_t lastlabel = -1; intptr_t lastlabel = -1;
int minrequiredstate = -1; int minrequiredstate = -1;
ChkBraceOpn(); SC_MustGetStringName ("{");
SC_SetEscape(false); // disable escape sequences in the state parser SC_SetEscape(false); // disable escape sequences in the state parser
while (!TestBraceCls() && !sc_End) while (!SC_CheckString ("}") && !sc_End)
{ {
memset(&state,0,sizeof(state)); memset(&state,0,sizeof(state));
statestring = ParseStateString(); statestring = ParseStateString();
@ -1853,7 +1827,7 @@ do_stop:
SC_MustGetStringName("("); SC_MustGetStringName("(");
SC_MustGetNumber(); SC_MustGetNumber();
state.Misc1=sc_Number; state.Misc1=sc_Number;
ChkCom(); SC_MustGetStringName (",");
SC_MustGetNumber(); SC_MustGetNumber();
state.Misc2=sc_Number; state.Misc2=sc_Number;
SC_MustGetStringName(")"); SC_MustGetStringName(")");
@ -2092,7 +2066,7 @@ do_stop:
{ {
goto endofstate; goto endofstate;
} }
ChkCom(); SC_MustGetStringName (",");
} }
} }
SC_MustGetStringName(")"); SC_MustGetStringName(")");
@ -2418,8 +2392,8 @@ void ParseActorProperties (Baggage &bag)
const PClass *info; const PClass *info;
const ActorProps *prop; const ActorProps *prop;
ChkBraceOpn (); SC_MustGetStringName ("{");
while (!TestBraceCls()) while (!SC_CheckString ("}"))
{ {
if (sc_End) if (sc_End)
{ {

View file

@ -52,7 +52,7 @@
void InitExpressions (); void InitExpressions ();
void ClearExpressions (); void ClearExpressions ();
static FRandom pr_exrandom ("EX_Random"); FRandom pr_exrandom ("EX_Random");
enum ExpOp enum ExpOp
{ {
@ -86,6 +86,7 @@ enum ExpOp
EX_Cond, // exp ? exp : exp EX_Cond, // exp ? exp : exp
EX_Random, // random (min, max) EX_Random, // random (min, max)
EX_Random2, // random2 ([mask])
EX_Sin, // sin (angle) EX_Sin, // sin (angle)
EX_Cos, // cos (angle) EX_Cos, // cos (angle)
EX_ActionSpecial, EX_ActionSpecial,
@ -254,6 +255,7 @@ struct ExpData
Type = EX_NOP; Type = EX_NOP;
Value.Type = VAL_Int; Value.Type = VAL_Int;
Value.Int = 0; Value.Int = 0;
RNG = NULL;
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
Children[i] = NULL; Children[i] = NULL;
} }
@ -321,7 +323,8 @@ struct ExpData
if (Type != other->Type || if (Type != other->Type ||
Value.Type != other->Value.Type || Value.Type != other->Value.Type ||
Value.Float != other->Value.Float) Value.Float != other->Value.Float ||
RNG != other->RNG)
{ {
return false; return false;
} }
@ -338,6 +341,7 @@ struct ExpData
ExpOp Type; ExpOp Type;
ExpVal Value; ExpVal Value;
ExpData *Children[2]; ExpData *Children[2];
FRandom *RNG; // only used by random and random2
}; };
TArray<ExpData *> StateExpressions; TArray<ExpData *> StateExpressions;
@ -699,11 +703,24 @@ static ExpData *ParseExpressionA ()
} }
else if (SC_CheckString ("random")) else if (SC_CheckString ("random"))
{ {
FRandom *rng;
if (SC_CheckString("["))
{
SC_MustGetString();
rng = FRandom::StaticFindRNG(sc_String);
SC_MustGetStringName("]");
}
else
{
rng = &pr_exrandom;
}
if (!SC_CheckString ("(")) if (!SC_CheckString ("("))
SC_ScriptError ("'(' expected"); SC_ScriptError ("'(' expected");
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Random; data->Type = EX_Random;
data->RNG = rng;
data->Children[0] = ParseExpressionM (); data->Children[0] = ParseExpressionM ();
@ -717,6 +734,34 @@ static ExpData *ParseExpressionA ()
return data; return data;
} }
else if (SC_CheckString ("random2"))
{
FRandom *rng;
if (SC_CheckString("["))
{
SC_MustGetString();
rng = FRandom::StaticFindRNG(sc_String);
SC_MustGetStringName("]");
}
else
{
rng = &pr_exrandom;
}
SC_MustGetStringName("(");
ExpData *data = new ExpData;
data->Type = EX_Random2;
data->RNG = rng;
if (!SC_CheckString(")"))
{
data->Children[0] = ParseExpressionM();
SC_MustGetStringName(")");
}
return data;
}
else if (SC_CheckString ("sin")) else if (SC_CheckString ("sin"))
{ {
if (!SC_CheckString ("(")) if (!SC_CheckString ("("))
@ -1419,22 +1464,38 @@ static ExpVal EvalExpression (ExpData *data, AActor *self)
{ {
int num1,num2,num3,num4; int num1,num2,num3,num4;
num1 = pr_exrandom(); num1 = (*data->RNG)();
num2 = pr_exrandom(); num2 = (*data->RNG)();
num3 = pr_exrandom(); num3 = (*data->RNG)();
num4 = pr_exrandom(); num4 = (*data->RNG)();
val.Int = ((num1 << 24) | (num2 << 16) | (num3 << 8) | num4); val.Int = ((num1 << 24) | (num2 << 16) | (num3 << 8) | num4);
} }
else else
{ {
val.Int = pr_exrandom(); val.Int = (*data->RNG)();
} }
val.Int %= (max - min + 1); val.Int %= (max - min + 1);
val.Int += min; val.Int += min;
} }
break; break;
case EX_Random2:
{
if (data->Children[0] == NULL)
{
val.Type = VAL_Int;
val.Int = data->RNG->Random2();
}
else
{
ExpVal a = EvalExpression (data->Children[0], self);
val.Type = VAL_Int;
val.Int = data->RNG->Random2((a.Type == VAL_Int) ? a.Int : (int)a.Float);
}
}
break;
case EX_Sin: case EX_Sin:
{ {
ExpVal a = EvalExpression (data->Children[0], self); ExpVal a = EvalExpression (data->Children[0], self);

View file

@ -30,7 +30,7 @@ ACTOR Clink 90
Melee: Melee:
CLNK E 5 A_FaceTarget CLNK E 5 A_FaceTarget
CLNK F 4 A_FaceTarget CLNK F 4 A_FaceTarget
CLNK G 7 A_CustomMeleeAttack(random(3,9), "clink/attack", "clink/attack") CLNK G 7 A_CustomMeleeAttack(random[ClinkAttack](3,9), "clink/attack", "clink/attack")
Goto See Goto See
Pain: Pain:
CLNK H 3 CLNK H 3

View file

@ -30,7 +30,7 @@ ACTOR Beggar : StrifeHumanoid
Loop Loop
Melee: Melee:
BEGR D 8 BEGR D 8
BEGR D 8 A_CustomMeleeAttack(2*random(1,5)+2) BEGR D 8 A_CustomMeleeAttack(2*random[PeasantAttack](1,5)+2)
BEGR E 1 A_Chase BEGR E 1 A_Chase
BEGR D 8 A_SentinelRefire BEGR D 8 A_SentinelRefire
Loop Loop

View file

@ -29,7 +29,7 @@ ACTOR Peasant : StrifeHumanoid
Loop Loop
Melee: Melee:
PEAS E 10 A_FaceTarget PEAS E 10 A_FaceTarget
PEAS F 8 A_CustomMeleeAttack(2*random(1,5)+2) PEAS F 8 A_CustomMeleeAttack(2*random[PeasantAttack](1,5)+2)
PEAS E 8 PEAS E 8
Goto See Goto See
Pain: Pain: