A long time ago, I suggested something like this for ZDoom. I've finally programmed it.
Clamps down and returns one of the two numbers entered, and nothing else. To get more results, pick inside of pick can happen:
I think a better implementation would be to allow an infinite amount of parameters and then randomly select one instead of nesting these calls.
Re: RClamp (Random Clamp)
Posted: Sat Dec 13, 2014 3:29 pm
by Gez
The name is misleading, that's not a clamp. (Thread title had me scratching my head, what's a random clamp and how could it be useful?)
It's something that randomly picks one of the numbers given, right? Then why not call it pick?
And what Graf said. pick(x, ...)
Re: RClamp (Random Clamp)
Posted: Sat Dec 13, 2014 3:50 pm
by Major Cooke
Name change: Done. Now Pick.
And I have no idea how I'm going to allow unlimited parameters, truthfully. Mind giving me a hand?
Re: Pick
Posted: Sat Dec 13, 2014 4:27 pm
by Nightfall
After scanning the initial '(', read in variables until ')' is encountered. Store these in a TArray<FxExpression*> and pass that to FxPick which then processes this further with the casting.
I think 'choose' would make a better name.
Re: Pick
Posted: Sat Dec 13, 2014 4:43 pm
by Major Cooke
The question then comes to mind, what if we have something like pick(1,2,(user_somenumber*82))? Wouldn't that throw it off?
Re: Pick
Posted: Sat Dec 13, 2014 4:57 pm
by Graf Zahl
Not if parsed properly. The ParseExpression functions parse an entire expression and store it as an FxExpression object. This object can be anything, ranging from a constant to some complex constructs that requires several levels of recursion to be evaluated.
Re: Pick
Posted: Sat Dec 13, 2014 6:50 pm
by Major Cooke
I'm not sure what to do about resolving with the array though. Any ideas?
Here's my code so far. Again, this is... very alien territory for me so it shouldn't be a surprise if I completely screwed the code up entirely.
Currently, it doesn't work. Access violation occurs in the Resolve call.
else if (sc.CheckToken(TK_Pick))
{
FRandom *rng;
TArray<FxExpression*> list;
list.Clear();
int index = 0;
if (sc.CheckToken('['))
{
sc.MustGetToken(TK_Identifier);
rng = FRandom::StaticFindRNG(sc.String);
sc.MustGetToken(']');
}
else
{
rng = &pr_exrandom;
}
sc.MustGetToken('(');
while (!(sc.CheckToken(')')))
{
FxExpression *min = ParseExpressionM(sc, cls);
list.Push(min);
if (sc.CheckToken(')'))
break;
else
sc.MustGetToken(',');
}
return new FxPick(rng, list, sc);
}
Re: Pick
Posted: Sun Dec 14, 2014 2:59 am
by Graf Zahl
You try to get the size of your array by calling min.Max() when you should call min.Size(). Max() returns the amount of reserved memory, not the amount of elements in use.
Re: Pick
Posted: Sun Dec 14, 2014 4:46 am
by Major Cooke
That did the trick! Thanks Graf!
The pull request has been updated.
Re: Pick
Posted: Sun Dec 14, 2014 5:02 am
by Graf Zahl
Added, but I had to plug a memory leak. You forgot to delete the array's contents.
Re: Pick
Posted: Sun Dec 14, 2014 7:34 am
by Major Cooke
Aw hell. Sorry. Yeah, I still have a lot to learn.
Thanks for that though!
Re: Pick
Posted: Tue Dec 16, 2014 9:05 am
by D2JK
Perhaps a dumb question, but is this supposed to work in decorate? For me, using it in an action function makes ZDoom shut down in the startup, without any error message.
Re: Pick
Posted: Tue Dec 16, 2014 10:47 am
by Major Cooke
Copy and paste your code, and I'll take a look at it. I only really designed this for DECORATE usage though. Whether it works in ACS or not was something I didn't have in mind for this to begin with. This is mainly because I don't want to make Graf clean up after my abysmal mess again.
Actor MM
{
var int user_t;
+NOINTERACTION
States
{
Spawn:
TNT1 A 0 NoDelay A_SetUserVar("user_t",pick(1,4,12,16))
TNT1 A 0 A_JumpIf(user_t == 1,"s1")
TNT1 A 0 A_JumpIf(user_t == 4,"s2")
TNT1 A 0 A_JumpIf(user_t == 12,"s3")
TNT1 A 0 A_JumpIf(user_t == 16,"s4")
Err:
TNT1 A 35 A_PrintBold("Apparently it didnt work.")
Goto Spawn
s1:
TNT1 A 35 A_PrintBold("One")
Goto Spawn
s2:
TNT1 A 35 A_PrintBold("Four")
Goto Spawn
s3:
TNT1 A 35 A_PrintBold("Twelve")
Goto Spawn
s4:
TNT1 A 35 A_PrintBold("Sixteen")
Goto Spawn
}
}