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); }
'frandom' { RET(TK_FRandom); }
'randompick' { RET(TK_RandomPick); }
'frandompick' { RET(TK_FRandomPick); }
L (L|D)* { RET(TK_Identifier); }

View file

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

View file

@ -371,8 +371,9 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
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;
TArray<FxExpression*> list;
list.Clear();
@ -398,7 +399,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
break;
sc.MustGetToken(',');
}
return new FxRandomPick(rng, list, sc);
return new FxRandomPick(rng, list, floaty, sc);
}
else if (sc.CheckToken(TK_FRandom))
{

View file

@ -587,7 +587,7 @@ protected:
public:
FxRandomPick(FRandom *, TArray<FxExpression*> mi, const FScriptPosition &pos);
FxRandomPick(FRandom *, TArray<FxExpression*> mi, bool floaty, const FScriptPosition &pos);
~FxRandomPick();
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)
{
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;
ValueType = VAL_Int;
ValueType = floaty ? VAL_Float : VAL_Int;
}
//==========================================================================
@ -1822,17 +1831,25 @@ FxExpression *FxRandomPick::Resolve(FCompileContext &ctx)
ExpVal FxRandomPick::EvalExpression(AActor *self)
{
ExpVal val;
val.Type = VAL_Int;
int max = min.Size();
if (max > 0)
{
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
{
val.Int = (*rng)();
val.Type = VAL_Float;
val.Float = (*rng)(0x40000000) / double(0x40000000);
}
assert(val.Type == ValueType);
return val;
}