Add FRandomPick

- This is RandomPick but for floats. Considering what RandomPick
  translates into in the scripting branch, I hope I don't regret not using
  type inference on RandomPick instead of creating a new keyword.
This commit is contained in:
Randy Heit 2015-02-20 17:52:52 -06:00
parent 173dbd6bce
commit 8e0151b4c1
5 changed files with 30 additions and 10 deletions

View file

@ -159,6 +159,7 @@ std2:
'random2' { RET(TK_Random2); } 'random2' { RET(TK_Random2); }
'frandom' { RET(TK_FRandom); } 'frandom' { RET(TK_FRandom); }
'randompick' { RET(TK_RandomPick); } 'randompick' { RET(TK_RandomPick); }
'frandompick' { RET(TK_FRandomPick); }
L (L|D)* { RET(TK_Identifier); } L (L|D)* { RET(TK_Identifier); }

View file

@ -122,5 +122,6 @@ xx(TK_Array, "'array'")
xx(TK_In, "'in'") xx(TK_In, "'in'")
xx(TK_SizeOf, "'sizeof'") xx(TK_SizeOf, "'sizeof'")
xx(TK_AlignOf, "'alignof'") xx(TK_AlignOf, "'alignof'")
xx(TK_RandomPick, "'randompick'") xx(TK_RandomPick, "'randompick'")
xx(TK_FRandomPick, "'frandompick'")
#undef xx #undef xx

View file

@ -371,8 +371,9 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
return new FxRandom(rng, min, max, sc); return new FxRandom(rng, min, max, sc);
} }
else if (sc.CheckToken(TK_RandomPick)) else if (sc.CheckToken(TK_RandomPick) || sc.CheckToken(TK_FRandomPick))
{ {
bool floaty = sc.TokenType == TK_FRandomPick;
FRandom *rng; FRandom *rng;
TArray<FxExpression*> list; TArray<FxExpression*> list;
list.Clear(); list.Clear();
@ -398,7 +399,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
break; break;
sc.MustGetToken(','); sc.MustGetToken(',');
} }
return new FxRandomPick(rng, list, sc); return new FxRandomPick(rng, list, floaty, sc);
} }
else if (sc.CheckToken(TK_FRandom)) else if (sc.CheckToken(TK_FRandom))
{ {

View file

@ -587,7 +587,7 @@ protected:
public: public:
FxRandomPick(FRandom *, TArray<FxExpression*> mi, const FScriptPosition &pos); FxRandomPick(FRandom *, TArray<FxExpression*> mi, bool floaty, const FScriptPosition &pos);
~FxRandomPick(); ~FxRandomPick();
FxExpression *Resolve(FCompileContext&); FxExpression *Resolve(FCompileContext&);

View file

@ -1774,15 +1774,24 @@ ExpVal FxRandom::EvalExpression (AActor *self)
// //
// //
//========================================================================== //==========================================================================
FxRandomPick::FxRandomPick(FRandom * r, TArray<FxExpression*> mi, const FScriptPosition &pos) FxRandomPick::FxRandomPick(FRandom * r, TArray<FxExpression*> mi, bool floaty, const FScriptPosition &pos)
: FxExpression(pos) : FxExpression(pos)
{ {
for (unsigned int index = 0; index < mi.Size(); index++) for (unsigned int index = 0; index < mi.Size(); index++)
{ {
min.Push(new FxIntCast(mi[index])); FxExpression *casted;
if (floaty)
{
casted = new FxFloatCast(mi[index]);
}
else
{
casted = new FxIntCast(mi[index]);
}
min.Push(casted);
} }
rng = r; rng = r;
ValueType = VAL_Int; ValueType = floaty ? VAL_Float : VAL_Int;
} }
//========================================================================== //==========================================================================
@ -1822,17 +1831,25 @@ FxExpression *FxRandomPick::Resolve(FCompileContext &ctx)
ExpVal FxRandomPick::EvalExpression(AActor *self) ExpVal FxRandomPick::EvalExpression(AActor *self)
{ {
ExpVal val; ExpVal val;
val.Type = VAL_Int;
int max = min.Size(); int max = min.Size();
if (max > 0) if (max > 0)
{ {
int select = (*rng)(max); int select = (*rng)(max);
val.Int = min[select]->EvalExpression(self).GetInt(); val = min[select]->EvalExpression(self);
}
/* Is a default even important when the parser requires at least one
* choice? Why do we do this? */
else if (ValueType == VAL_Int)
{
val.Type = VAL_Int;
val.Int = (*rng)();
} }
else else
{ {
val.Int = (*rng)(); val.Type = VAL_Float;
val.Float = (*rng)(0x40000000) / double(0x40000000);
} }
assert(val.Type == ValueType);
return val; return val;
} }