Probability Quake



  • An old but well-known game contains this code section:

            case TE_SPIKE:                  // spike hitting wall
                    pos[0] = MSG_ReadCoord ();
                    pos[1] = MSG_ReadCoord ();
                    pos[2] = MSG_ReadCoord ();
                    R_RunParticleEffect (pos, vec3_origin, 0, 10);

                    if ( rand() % 5 )
                            S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
                    else
                    {
                            rnd = rand() & 3;
                            if (rnd == 1)
                                    S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
                            else if (rnd == 2)
                                    S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
                            else
                                    S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
                    }
                    break;

    Okay, tink1 gets played at 80% probability, and the other sounds can only be played in the other 20% of the cases. That is fine. But there is SOMETHING unusual about the ricochet sounds...

    (I know, this is just a "technical" bug, and really a minor one - I doubt any player ever noticed that in game - but nevertheless, it made me go WTF and in my had, I even guessed the probabilities for the ricochet sounds wrong TWICE until I understood the code).

    I wonder if this was an optimization... but I'd doubt that, as R_RunParticleEffect, S_StartSound and rand() should take long enough so that doing it right should not harm performance at all.



  • Is that Quake.NET or is the Source from Quake 1 released to??



  • @Ice^^Heat said:

    Is that Quake.NET or is the Source from Quake 1 released to??

     The source for Quake (and Quake 2 and Quake 3) has been available for a long time. See http://www.idsoftware.com/business/techdownloads/.
     



  • That's fun - it's obviously a typo, but it still works nearly correctly. You're right - I doubt anyone's likely to notice one ricochet sound being played more often than the others.



  • @OperatorBastardusInfernalis said:

    (I know, this is just a "technical" bug, and really a minor one - I doubt any player ever noticed that in game - but nevertheless, it made me go WTF and in my had, I even guessed the probabilities for the ricochet sounds wrong TWICE until I understood the code).

    I wonder if this was an optimization... but I'd doubt that, as R_RunParticleEffect, S_StartSound and rand() should take long enough so that doing it right should not harm performance at all.

     

    E(ric1)=.25

    E(ric2)=.25

    E(ric3)=.5 

     Am I right? ( I can't even remember what the richocets sound like.)
     



  • And you haven't even taken into account the fact that on standard systems, rand() is a linear congruential generator.

     

    You could probably calculate the probability of each event more accurately, and I think it'll make it even more uneven. 



  • Actually, I wouldn't expect it to be uneven, but "just" repetitive... which the LCG on http://en.wikipedia.org/wiki/Linear_congruential_generator is a good example of (in that RNG, rand() & 3 is just 3, 2, 1, 0, 3, 2, 1, 0, 3, 2, 1, 0, ... and rand() % 5 looks random). The intended rand() % 3, however, would have a "good enough" distribution again. Note that rand does not get called a fixed number of times between two calls of this sound... much more stuff in Quake uses the random number generator. It's funny that Quake almost always takes the RNG's result modulo a power of two... but I have no idea which libc it was originally compiled with and which RNG was used.

    BTW, I found this one when looking at the code of some more advanced and still being developed on Quake 1 derived engine... it's scary that one can assume that such code is still in there...



  • At least it wasn't: 

                            rnd = rand() & 3;
                            if (rnd == 0)
                                    S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
                            else if (rnd == 1)
                                    S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
                            else if(rnd == 2)
                                    S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);

     
    The author may have noticed the bug but just didn't care. 



  • Being too lazy to change a single & into a % (okay, actually, two of them, this code is copypasted to two places in Quake)?

    That's genuine laziness. If that's what happened, the author is a real genius. A lazy one...


Log in to reply