Beispiel #1
7
void
shHero::payDoctor (shMonster *doctor)
{
    static const char *MedicalProcedureNames[] =
    { "Wound Treatment",
      "Restoration Treatment",
      "Intestinal Examination",
      "Systems Diagnostics",
      "Radiation Purge",
      "Caesarean Section",
      "Canister Amputation",
      "Teef Extraction",
      "Tail Amputation"
    };

    static bool hadamputation = false;
    char buf[200];
    shMenu *menu = I->newMenu ("Medical Services Menu", 0);
    int serv;
    const int TREATMENT_COST = 200;

    if (tryToTranslate (doctor)) {
        /* make all services known */
        for (int i = 0; i < kMedMaxService; ++i) {
            MedicalProcedureData[i].mNameKnown = 1;
        }
    }

    char letter = 'a';
    for (int i = 0; i < kMedMaxService; ++i) {
        serv = doctor->mDoctor.mPermute[i];

        /* try not to offer unneeded services */
        switch (serv) {
        case kMedHealing:
            if (Hero.mHP != Hero.mMaxHP or
                Hero.is (kViolated) or
                Hero.is (kConfused) or
                Hero.is (kStunned))
            {
                break;
            }
            continue;
        case kMedRestoration: {
            int add = 0;
            FOR_ALL_ABILITIES (j) {
                int abil = Hero.mAbil.getByIndex (j);
                if (kPsi == j) {
                    abil += Hero.mPsiDrain;
                }
                if (abil < Hero.mMaxAbil.getByIndex (j)) {
                    add = 1;
                    break;
                }
            }
            if (add) break;
            continue;
        }
        case kMedRectalExam:
        case kMedDiagnostics:
        case kMedRadPurification:
            /* these services are always available: */
            break;
        case kMedCaesareanSection:
            if (Hero.getStoryFlag ("impregnation"))
                break;
            continue;
        case kMedCanisterAmputation:
            if (Hero.getStoryFlag ("superglued tongue"))
                break;
            continue;
        case kMedTeefExtraction:
            if (!Hero.getStoryFlag ("lost teef") and Hero.isOrc ())
                break;
            continue;
        case kMedTailAmputation:
            if (Hero.mIlkId == kMonXelNaga and !Hero.getStoryFlag ("lost tail"))
                break;
            continue;
        default:
            continue;
        }

        snprintf (buf, sizeof(buf), "%s ($%d)",
                  MedicalProcedureData[serv].mNameKnown
                      ? MedicalProcedureNames[serv]
                      : MedicalProcedureData[serv].mDesc,
                 TREATMENT_COST);
        menu->addIntItem (letter++, buf, serv);
    }

    int res;
    if (!menu->getIntResult (&res))
        return; /* nothing picked */
    delete menu;

    MedicalProcedures choice = MedicalProcedures (res);
    int price = TREATMENT_COST;

    if (countMoney () < price) {
        I->p ("You don't have enough money for that.");
        return;
    }

    if (Hero.is (kFrightened) and choice == kMedTeefExtraction and
        MedicalProcedureData[choice].mNameKnown)
    {
        I->p ("No way!  You are too afraid of the dentist at the moment!");
        return;
    }

    loseMoney (price);
    doctor->gainMoney (price);

    const char *who = doctor->the ();
    shObjectIlk *ilk;

    switch (choice) {
    case kMedHealing:
        ilk = &AllIlks[kObjHealingRayGun];
        I->p ("%s injects you with a %s serum!", who,
            !Hero.isBlind () ? ilk->getRayGunColor () : "kind of");
        if (Hero.healing (NDX (10, 5), 0) and !Hero.isBlind ()) {
            ilk->mFlags |= kIdentified;
            MedicalProcedureData[choice].mNameKnown = 1;
        }
        break;
    case kMedRestoration:
        ilk = &AllIlks[kObjRestorationRayGun];
        I->p ("%s injects you with a %s serum!", who,
            !Hero.isBlind () ? ilk->getRayGunColor () : "kind of");
        if (Hero.restoration (NDX (3, 2))) {
            MedicalProcedureData[choice].mNameKnown = 1;
            if (!Hero.isBlind ())  ilk->mFlags |= kIdentified;
        }
        break;
    case kMedRectalExam:
    {
        int probed = 0;
        /* Was loser option pre PRIME 1.7 but why not make it useful
           in a border case? */
        MedicalProcedureData[choice].mNameKnown = 1;
        I->p ("%s probes you!", who);
        /* Any resistance is treated like obstacle. */
        if (!Hero.mResistances[kViolating]) {
            Hero.sufferDamage (kAttProbe);
            probed = 1;
        } else { /* If hero wears loser anorak he is immune. */
            I->p ("You seem unaffected.");
            Hero.mCloak->setKnown ();
            if (Hero.tryToTranslate (doctor)) {
                I->p ("\"I cannot perform the service while you wear %s.\"",
                    THE (Hero.mCloak));
                Hero.mCloak->setKnown ();
                /* Get rid of buggy loser anorak for 200 BZ. */
                if (I->yn ("\"May I remove it?\"")) {
                    I->p ("%s removes %s.", who, YOUR (Hero.mCloak));
                    Hero.doff (Hero.mCloak);
                    I->p ("%s probes you again!", who);
                    Hero.sufferDamage (kAttProbe);
                    probed = 1;
                } else {
                    I->p ("Money-back guarantee requires me to refuse payment.");
                    gainMoney (price);
                    doctor->loseMoney (price);
                }
            } else {
                I->p ("%s chirps something and gives back your money.", who);
                gainMoney (price);
                doctor->loseMoney (price);
            }
            if (probed and Hero.getStoryFlag ("impregnation")) {
                I->p ("\"You have a parasite.\"");
            }   /* Thank you, Captain Obvious! */
        }
        break;
    }
    case kMedDiagnostics:
        MedicalProcedureData[choice].mNameKnown = 1;
        I->p ("%s probes you!", who);
        Hero.doDiagnostics (0);
        break;
    case kMedRadPurification:
        MedicalProcedureData[choice].mNameKnown = 1;
        I->p ("%s injects you with a %s serum!", who,
            !Hero.isBlind () ? "bubbly" : "kind of");
        Hero.mRad = maxi (0, Hero.mRad - RNG (50, 200));
        if (!Hero.mRad)
            I->p ("You feel purified.");
        else
            I->p ("You feel less contaminated.");
        break;
    case kMedCaesareanSection:
    {
        if (!Hero.getStoryFlag ("impregnation"))
            break;

        MedicalProcedureData[choice].mNameKnown = 1;
        Hero.setStoryFlag ("impregnation", 0);

        int x = Hero.mX;
        int y = Hero.mY;
        int queen = !RNG (0, 17);
        int colicky = !RNG (0, 5);
        shMonster *baby = new shMonster (queen ? kMonAlienPrincess : kMonChestburster);
        if (!colicky) {
            baby->mDisposition = shMonster::kIndifferent;
        }
        Level->findNearbyUnoccupiedSquare (&x, &y);
        if (!baby) {
            I->p ("Unfortunately, your baby was stillborn.");
        } else {
            I->p ("It's a %s!", queen ? "girl" : "boy");
            if (Level->putCreature (baby, x, y)) {
                /* FIXME: something went wrong */
            } else {
                I->drawScreen ();
            }
        }

        I->p ("You lose a lot of blood during the operation.");
        if (Hero.sufferDamage (kAttCaesareanSection)) {
            Hero.shCreature::die (kKilled, "complications in childbirth");
        }
        break;
    }
    case kMedCanisterAmputation:
    {
        if (!Hero.getStoryFlag ("superglued tongue"))
            break;

        MedicalProcedureData[choice].mNameKnown = 1;
        I->p ("%s cuts away the glued canister.", who);
        Hero.resetStoryFlag ("superglued tongue");
        amputationDiscount (doctor, this, &hadamputation, price);
    }
    case kMedTeefExtraction:
    {
        if (Hero.getStoryFlag ("lost teef"))
            break;

        int sum = NDX (11, 100);
        Hero.setStoryFlag ("lost teef", sum);
        MedicalProcedureData[choice].mNameKnown = 1; /* Kind of pointless. */
        if (Hero.is (kFrightened)) {
            char *buf = GetBuf ();
            strcpy (buf, who);
            buf[0] = toupper (buf[0]);
            I->p ("Oh no!!  %s gets at your teef!", buf);
            I->p ("You panic and try to flee but %s has immobilized you already.", who);
        } else
            I->p ("%s extracts your teef.", who);
        I->p ("Your magnificent teef are worth $%d buckazoids.", sum);
        gainMoney (sum);
        break;
    }
    case kMedTailAmputation:
    {
        if (Hero.getStoryFlag ("lost tail"))
            break;

        Hero.setStoryFlag ("lost tail", 1);
        MedicalProcedureData[choice].mNameKnown = 1;
        I->p ("%s amputates your tail!", who);

        Hero.amputateTail ();

        amputationDiscount (doctor, this, &hadamputation, price);
    }
    case kMedMaxService:
        break;
    }
    I->drawSideWin ();
}
Beispiel #2
0
void
kma_free(void* ptr, kma_size_t size)
{
	// return size is larger than half page
	// simply free the page
	if(size > MAXSPACE / 2)
	{
		kpage_t* page = *((kpage_t**)((void*)ptr - sizeof(kpage_t*)));
		free_page(page);
		return;
	}

	// put the return buffer into the freelist
	int index = NDX(size + sizeof(bufHeader_t));
	kma_size_t reqSpace = SPACE(index);
 	bufHeader_t* bufPtr;
	bufPtr = (bufHeader_t*)(ptr - sizeof(bufHeader_t));
	bufPtr->ptr = kflPtr->p2fl[index];
	kflPtr->p2fl[index] = bufPtr;
	kflPtr->spaceUsed -= reqSpace;

	// if all buffers are returned, free all pages
	cleanupKFL();
}
Beispiel #3
0
//constructor:
shMonster::shMonster (shMonId id, int extralevels /* = 0 */ )
    :shCreature ()
{
    int do_or = 0;
    int do_and = 0;
    int gotweapon = 0;
    shMonsterIlk *ilk = &MonIlks[id];
    mIlkId = id;

    mType = ilk->mType;
    strncpy (mName, ilk->mName, 30);
    mCLevel = ilk->mBaseLevel;
    mNaturalArmorBonus = ilk->mNaturalArmorBonus;
    mReflexSaveBonus = 0;

    mDir = kNoDirection;
    mTame = 0;
    mStrategy = ilk->mDefaultStrategy;
    mDisposition = ilk->mDefaultDisposition;
    mTactic = kReady;
    mDestX = -1;
    mEnemyX = -1;
    mPlannedMoveIndex = -1;
    mSpellTimer = 0;

    memcpy (mInnateResistances, ilk->mInnateResistances,
            sizeof (mInnateResistances));
    mInnateIntrinsics = ilk->mInnateIntrinsics;
    for (int i = 0; i < ilk->mNumPowers; ++i)
        if (ilk->mPowers[i] == kTelepathyPower)
            mInnateIntrinsics |= kTelepathy; /* Assume always on. */
    mFeats = ilk->mFeats;

#define IMMUNE 122

    switch (mType) {
    case kMutant:
        mInnateResistances[kRadiological] = IMMUNE;
        mInnateResistances[kMagnetic] = IMMUNE;
        break;
    case kHumanoid:
        mInnateResistances[kMagnetic] = IMMUNE;
        break;
    case kAnimal:
        mInnateResistances[kMagnetic] = IMMUNE;
        mInnateIntrinsics |= kScent;
        break;
    case kInsect:
        mInnateResistances[kMagnetic] = IMMUNE;
        mInnateResistances[kRadiological] = IMMUNE;
        mInnateIntrinsics |= kScent;
        break;
    case kOutsider:
        mInnateResistances[kMagnetic] = IMMUNE;
        break;
    case kBot:
        mInnateResistances[kToxic] = IMMUNE;
        mInnateResistances[kPsychic] = IMMUNE;
        mInnateResistances[kRadiological] = IMMUNE;
        mInnateResistances[kViolating] = IMMUNE;
        mInnateResistances[kMesmerizing] = IMMUNE;
        mInnateResistances[kBlinding] = IMMUNE;
        mInnateIntrinsics |= kBreathless;
        break;
    case kDroid:
        mInnateResistances[kToxic] = IMMUNE;
        mInnateResistances[kPsychic] = IMMUNE;
        mInnateResistances[kRadiological] = IMMUNE;
        mInnateResistances[kViolating] = IMMUNE;
        mInnateResistances[kMesmerizing] = IMMUNE;
        mInnateResistances[kBlinding] = IMMUNE;
        mInnateIntrinsics |= kBreathless;
        break;
    case kProgram:
        mInnateResistances[kToxic] = IMMUNE;
        mInnateResistances[kRadiological] = IMMUNE;
        mInnateResistances[kViolating] = IMMUNE;
        /* Processes can be put to sleep so no kMesmerizing immunity. */
        mInnateIntrinsics |= kBreathless;
        break;
    case kConstruct:
        mInnateResistances[kToxic] = IMMUNE;
        mInnateResistances[kPsychic] = IMMUNE;
        mInnateResistances[kRadiological] = IMMUNE;
        mInnateResistances[kStunning] = IMMUNE;
        mInnateResistances[kConfusing] = IMMUNE;
        mInnateResistances[kViolating] = IMMUNE;
        mInnateResistances[kParalyzing] = IMMUNE;
        mInnateResistances[kMesmerizing] = IMMUNE;
        mInnateResistances[kBlinding] = IMMUNE;
        mInnateIntrinsics |= kBreathless;
        break;
    case kOoze:
        mInnateResistances[kToxic] = 3;
        mInnateResistances[kMagnetic] = IMMUNE;
        mInnateResistances[kRadiological] = IMMUNE;
        mInnateResistances[kViolating] = IMMUNE;
        mInnateResistances[kWebbing] = IMMUNE;
        mInnateIntrinsics |= kBreathless;
        break;
    case kAberration:
        mInnateResistances[kMagnetic] = IMMUNE;
        mInnateResistances[kRadiological] = IMMUNE;
        mInnateResistances[kViolating] = IMMUNE;
        break;
    case kCyborg:
        mInnateResistances[kToxic] = 2;
        mInnateResistances[kRadiological] = 10;
        mInnateIntrinsics |= kBreathless;
        break;
    case kEgg:
        mInnateResistances[kViolating] = IMMUNE;
        mInnateIntrinsics |= kBreathless;
        /* fall through */
    case kBeast:
        mInnateResistances[kMagnetic] = IMMUNE;
        mInnateIntrinsics |= kScent;
        break;
    case kVermin:
        mInnateResistances[kMagnetic] = IMMUNE;
        mInnateIntrinsics |= kScent;
        mInnateIntrinsics |= kCanSwim;
        break;
    case kAlien:
        mAlienEgg.mHatchChance = 0;
        mInnateResistances[kMagnetic] = IMMUNE;
        mInnateResistances[kRadiological] = 10;
        mInnateResistances[kCorrosive] = IMMUNE;
        mInnateIntrinsics |= kScent;
        if (!isA (kMonAlienQueen)) /* Too heavy and bloated. */
            mInnateIntrinsics |= kJumpy;
        gainRank (kUnarmedCombat, mCLevel/2);
        break;
    default:
        debug.log ("Alert! Unknown monster type");
        mInnateResistances[kMagnetic] = IMMUNE;
    }

#undef IMMUNE

    if (3 == ilk->mGender) {
        mGender = RNG (1, 2);
    } else {
        mGender = ilk->mGender;
    }

    /* roll ability scores */
    rollAbilityScores (ilk->mStr, ilk->mCon, ilk->mAgi,
                       ilk->mDex, ilk->mInt, ilk->mPsi);

    /* roll hit points */
    rollHitPoints (ilk->mHitDice, 8);

    /* setup speed */
    mSpeed = ilk->mSpeed;
    computeAC ();

    mGlyph = ilk->mGlyph;
    if (isA (kMonMutantNinjaTurtle))
        mGlyph.mTileX += RNG (4); /* Got four of those. */
    mState = kActing;

    if (equipment[id].mPtr) /* Does monster get standard equipment? */
    for (int i = 0; i < equipment[id].mCnt; ++i) {
        const char *str = equipment[id].mPtr[i];

        if ('|' == str[0]) { /* the or symbol indicates don't try to create
                                the object unless the previous obj failed */
            if (0 == do_or) {
                do_or = 1;
                do_and = 0;
                continue;
            } else {
                ++str;
            }
        } else if (',' == str[0]) { /* the comma symbol indicates create the
                                       object only if the prev obj was made */
            if (1 == do_and) {
                ++str;
            } else {
                continue;
            }
        }

        shObject *obj = createObject (str, 0);

        if (NULL == obj) {
            do_or = 1;
            do_and = 0;
            debug.log ("unable to equip %s", str);
            continue;
        }
        do_or = 0;
        do_and = 1;
        addObjectToInventory (obj);
        if (!mWeapon and obj->isA (kWeapon)) {
            if (obj->myIlk ()->mMeleeSkill != kNoSkillCode) {
                gainRank (obj->myIlk ()->mMeleeSkill, 1 + mCLevel * 2/3);
            }
            if (obj->myIlk ()->mGunSkill != kNoSkillCode) {
                gainRank (obj->myIlk ()->mGunSkill, 1 + mCLevel * 2/3);
            }
            ++gotweapon;
            /* don't wield until hero is in sight so he can see message */
            //wield (obj, 1);
        } else if (obj->isA (kArmor) or obj->isA (kImplant)) {
            don (obj, 1);
        }
    }

    if (!gotweapon) {
        gainRank (kUnarmedCombat, 1 + mCLevel);
    }

    /* Maybe monster gets some more treasure. */
    if (noTreasure () or
        kAnimal == mType  or kBeast == mType    or kAberration == mType or
        kInsect == mType  or kVermin == mType   or kOutsider == mType or
        kEgg == mType     or kOoze == mType     or kAlien == mType or
        kBot == mType     or kConstruct == mType)
    { /* No treasure requested or a monster does not want treasure. */
    } else {
        if (RNG (50) <= 5 + mCLevel) {
            shObject *cash = new shObject (kObjMoney);
            cash->mCount = NDX (mCLevel + 1, 10);
            addObjectToInventory (cash);
        }
        if (RNG (80) <= 5 + mCLevel) {
            shObject *obj = generateObject (-1);

            while (obj->getMass () > 5000) {
                delete obj;
                obj = generateObject (-1);
            }

            addObjectToInventory (obj);
        }
    }

    computeIntrinsics ();

    if (RNG (100) < ilk->mPeacefulChance) {
        mDisposition = kIndifferent;
    }

    debug.log ("spawned %s with %d HP speed %d", mName, mHP, mSpeed);
}
Beispiel #4
0
void*
kma_malloc(kma_size_t size)
{
	// Check if the request is valid
	if(size > MAXSPACE)
	{
		printf("ERROR: too large request!\n");
		return NULL;
	}

	// If no page is present in kernel
	// get a new page and initialize the header
	if(kflPtr == NULL)
	{
		if(initKFL(size))
			return NULL;
	}

	// If the request size is larger than half page
	// simply return a whole page
	if(size > MAXSPACE / 2)
	{
		kpage_t* page;
		page = get_page();
		*((kpage_t**)(page->ptr)) = page;
		return page->ptr + sizeof(kpage_t*);
	}
	
	// Roundup the size and calculate the index and size
	int index = NDX(size + sizeof(bufHeader_t));
	kma_size_t reqSpace = SPACE(index);
	bufHeader_t* bufPtr;
	bool reqNewPage;
//	printf("size: %d\tindex: %d\t request space: %d\n", size, index, reqSpace);

	do {
		reqNewPage = FALSE;
		if(kflPtr->p2fl[index] == NULL)		// No avalible buffer in freelist
		{
			if((reqSpace <= kflPtr->freespaceSize)) // cut a buffer from the current page
			{
				bufPtr = (bufHeader_t*) kflPtr->freespacePtr;
				kflPtr->freespaceSize -= reqSpace;
				kflPtr->freespacePtr += reqSpace;
				kflPtr->spaceUsed += reqSpace;
				return (void*)bufPtr + sizeof(bufHeader_t);
			}
			else	// get a new page and initialize the header
			{
				allocSpaceLeft(index-1);
				initKFL(size);
				reqNewPage = TRUE;
			}
		}
		else	// remove the buffer from the freelist and return it
		{
			bufPtr = kflPtr->p2fl[index];
			kflPtr->p2fl[index] = (bufHeader_t*)bufPtr->ptr;
			kflPtr->spaceUsed += (int)reqSpace;
			return (void*)bufPtr + sizeof(bufHeader_t);
		}
	}while(reqNewPage);
	return NULL;
}
Beispiel #5
0
int
shMapLevel::buildSewer ()
{
    int x, y, i, n;
    int lighting = RNG (2) ? -1 : 1;
    SewerRoom nodes[NODECOLS][NODEROWS];

    mMapType = kSewer;

    x = RNG (NODECOLS);
    y = RNG (NODEROWS);

    //first pass
    buildSewerHelper (nodes, x, y, 0);

    //second pass, make more tightly connected
    for (n = 10; n; n--) {
        if (RNG(3)) {
            x = RNG (NODECOLS-1);
            y = RNG (NODEROWS);
            nodes[x][y].mWalls[1] = 0;
            nodes[x+1][y].mWalls[2] = 0;
        } else {
            x = RNG (NODECOLS);
            y = RNG (NODEROWS-1);
            nodes[x][y].mWalls[3] = 0;
            nodes[x][y+1].mWalls[0] = 0;
        }
    }

    for (x = 0; x < NODECOLS; x++) {
        for (y = 0; y < NODEROWS; y++) {
            if (nodes[x][y].mDeadEnd or !RNG(7)) {
                nodes[x][y].mBulbous = 1;
            }
        }
    }

    // force 2 bulbous rooms
    x = RNG (NODECOLS/3); y = RNG (NODEROWS);
    nodes[x][y].mBulbous = 1;
    x = NODECOLS - 1 - RNG (NODECOLS/3); y = RNG (NODEROWS);
    nodes[x][y].mBulbous = 1;

    // don't have adjacent bulbous rooms (looks bad)
    for (x = 0; x < NODECOLS-1; x++) {
        for (y = 0; y < NODEROWS; y++) {
            if (nodes[x][y].mBulbous and nodes[x+1][y].mBulbous and
                nodes[x][y].mWalls[1])
            {
                if (RNG(2))
                    nodes[x][y].mBulbous = 0;
                else
                    nodes[x+1][y].mBulbous = 0;
            }
        }
    }

    for (x = 0; x < NODECOLS; x++) {
        for (y = 0; y < NODEROWS-1; y++) {
            if (nodes[x][y].mBulbous and nodes[x][y+1].mBulbous and
                nodes[x][y].mWalls[3])
            {
                if (RNG(2))
                    nodes[x][y].mBulbous = 0;
                else
                    nodes[x][y+1].mBulbous = 0;
            }
        }
    }

    for (x = 0; x < NODECOLS; x++) {
        for (y = 0; y < NODEROWS; y++) {
            buildSewerRoom (nodes, x, y);
        }
    }

    for (n = NDX(2,4); n; n--) {
        floodMuck (RNG(NODECOLS)*6+5, RNG(NODEROWS)*4+2, kSewage, NDX(8,20));
    }

    for (i = NDX (2, 3); i; --i) {
        findUnoccupiedSquare (&x, &y);
        switch (RNG (4)) {
        case 0:
            addTrap (x, y, shFeature::kPit); break;
        case 1:
            addTrap (x, y, shFeature::kHole); break;
        case 2:
            addTrap (x, y, shFeature::kTrapDoor); break;
        case 3:
            addTrap (x, y, shFeature::kRadTrap); break;
        }
    }

    for (i = 0; i < 8; i++) {
        findUnoccupiedSquare (&x, &y);
        putObject (generateObject (mDLevel), x, y);
    }

    for (x = 0; x < mColumns; x++)
        for (y = 0; y < mRows; y++)
            setLit (x, y, lighting, lighting, lighting, lighting);



    return 1;
}
Beispiel #6
0
void
shHero::quaffFromVat (shFeature *vat)
{
    assert (vat->mX == Hero.mX and vat->mY == Hero.mY);

    int dryup = 3;
    int result;

    if (isInShop ()) {
        quaffFromOwnedVat (vat);
    }

    if (vat->mVat.mHealthy <= -3) {
        /* You need to pour some nasty stuff in to achieve this. */
        result = -2;
    } else if (vat->mVat.mRadioactive and !RNG (10 + vat->mVat.mHealthy)) {
        result = -1;
    } else if (RNG (2) < vat->mVat.mHealthy) {
        /* Healthy vats are quite likely to give a good effect, and they're
           the only way to get the gain ability effect. */
        result = RNG (0, 6);
    } else if (vat->mVat.mHealthy < 0) {
        /* Extraordinarily unhealthy vats may poison. */
        result = RNG (1, 10);
    } else {
        result = RNG (1, 9);
    }

    switch (result) {
        case -2:
            I->p ("Arrgghh!!  You vomit.");
            if (sufferDamage (kAttVatPlague)) {
                shCreature::die (kKilled, "a filthy sludge vat");
            }
            vat->mVat.mAnalyzed = 1;
            break;
        case -1:
            mRad += RNG (1, 100);
            I->p ("Ick!  That had a toxic taste!");
            break;
        case 0:
            Hero.gainAbility (false, 1);
            vat->mVat.mAnalyzed = 1;
            break;
        case 1:
            if (vat->mVat.mRadioactive) {
                getMutantPower ();
                dryup = 2;
                break;
            } /* else fall through... */
        case 2:
            mRad -= RNG (1, 200);
            mRad = maxi (0, mRad);
            if (!mRad)
                I->p ("You feel purified!");
            else
                I->p ("You feel less contaminated.");
            break;
        case 3:
            mHP += NDX (4, 6);
            mHP = mini (mHP, mMaxHP);
            I->p ("You feel better!");
            break;
        case 4:
        {
            int amt = RNG (1, 6);
            Hero.mPsiDrain -= amt;
            Hero.mAbil.mPsi += amt;
            I->p ("You feel invigorated!");
            break;
        }
        case 5:
            I->p ("Mmmm... bouncy bubbly beverage!");
            if (Hero.getStoryFlag ("impregnation")) {
                abortion (1); /* Here message given is slightly different. */
                I->p ("You feel the alien embryo inside you die.");
            }
            break;
        case 6:
            I->p ("Mmmm... hot fun!");
            if (Hero.needsRestoration ())
                Hero.restoration (RNG (2) + mini (3, vat->mVat.mHealthy));
            break;
        case 7:
            I->p ("Oops!  You fall in!  You are covered in slime!");
            damageEquipment (kAttVatCorrosion, kCorrosive);
            I->p ("You climb out of the vat.");
            break;
        case 8:
        {
            int x = mX;
            int y = mY;

            shMonster *monster = new shMonster (kMonVatSlime);
            if (0 != Level->findNearbyUnoccupiedSquare (&x, &y) or
                0 != Level->putCreature (monster, x, y))
            {
                I->p ("The sludge gurgles!");
            } else {
                I->p ("It's alive!");
            }
            break;
        }
        case 9:
            I->p ("You are jolted by an electric shock!");
            if (sufferDamage (kAttVatShock)) {
                shCreature::die (kKilled, "an improperly grounded sludge vat");
            }
            dryup = 2;
            break;
        case 10:
            I->p ("This stuff is poisonous!");
            Hero.abortion ();
            if (sufferDamage (kAttVatPoison)) {
                shCreature::die (kKilled, "drinking some unhealthy sludge");
            }
            dryup = 2;
            vat->mVat.mAnalyzed = 1;
            break;
    }

    if (!RNG (dryup)) {
        I->p ("The vat dries up!");
        Level->forgetFeature (vat->mX, vat->mY);
        Level->removeFeature (vat);
    }
}