What are the rules for Pkunk ship regeneration/resurrection

star-control-2

Pkunk ships seem to have the ability to regenerate/resurrect if killed in battle.

However, it seems pretty random when they do or don't regenerate.

Are there specific known rules for when regeneration does/doesn't happen?

Best Answer

After some digging through the available source code (or at least the git repository debian uses to maintain this package) I tracked the effect down to the following code snippet in ships/pkunk/pkunk.c, in the function pkunk_preprocess():

        if (((BYTE)TFB_Random () & 1)
                        && (hPhoenix = AllocElement ()))
        {

                LockElement (hPhoenix, &PhoenixPtr);
                PhoenixPtr->state_flags =
                                FINITE_LIFE | NONSOLID | IGNORE_SIMILAR
                                | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY));
                PhoenixPtr->life_span = 1;

                PhoenixPtr->death_func = intercept_pkunk_death;

                SetElementStarShip (PhoenixPtr, StarShipPtr);

                UnlockElement (hPhoenix);
                InsertElement (hPhoenix, GetHeadElement ());
        }

If I've interpreted this right, what happens is that the resurrection is predetermined when the ship is spawned -- if TFB_Random() returns an odd value, the death_func() call is replaced with intercept_pkunk_death() which is defined a little further down in the code and triggers the "HAAAAAllelujah!" reincarnation before spawning a new Pkunk ship -- which itself calls pkunk_preprocess() and continues the cycle.

TL;DR: According to at least the source code as it exists in Debian, the odds of a respawn are as close to 50% as a software random generator can get.

(No, I don't think other versions behave wildly differently, but this is the only version I can be absolutely certain about; if you want to know for sure whether your version is the same, check the source code for the function described above)

EDIT Whoops, spoke slightly too soon.

In the function intercept_pkunk_death():

        if (GRAVITY_MASS (ShipPtr->mass_points + 1))
        {
                ElementPtr->state_flags |= DISAPPEARING;
                ElementPtr->life_span = 0;
        }
        else
        {
                ShipPtr->mass_points = MAX_SHIP_MASS + 1;
                StarShipPtr->RaceDescPtr->preprocess_func = ShipPtr->preprocess_func;
                StarShipPtr->RaceDescPtr->postprocess_func = ShipPtr->postprocess_func;
                StarShipPtr->RaceDescPtr->init_weapon_func =
                                (COUNT (*) (PELEMENT ElementPtr,
                                                HELEMENT Weapon[]))
                                                ShipPtr->death_func;

                ElementPtr->death_func = new_pkunk;
        }

GRAVITY_MASS() is a defined function that tests whether a value's mass is higher than MAX_SHIP_MASS * 10 (which in turn is a defined value of 10).

So there is another nondeterministic factor that can determine whether the reincarnation is called off, involving the ship's mass_points. It's a little harder to figure out how those are calculated, but Pkunk ships start off at a mass of '1' and this check doesn't trip unless mass_points are higher than 100...