Add several functions for later improved handling of stacks of !blood.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4109 c06c8d41-db1a-0410-9941-cceddc491573
VXSORUQOM2VZA4CAZDC6KPAY373NQIN3UT7CXQXTRCYXO2WM62DAC Z5K63RTQ7GBQFNOWQ27RR2K7B6J6KLT42IM3CMNT52JNVYDPY7IQC H53LXVICYVVJNETLDPVZGZV7U3SLB2XUOYSMFM2VM6ST226MTBHQC RG7ASPEZNL3OIYMMNABKIBEYGI7USZITHRVJ65HMWKTU4X3FVPYAC XL7E3EW5RPRYR7XHURIVKUJ3ATQAXMEGDLI3RSG3V4PGMLQ7CY3AC Y3N66XTY5HEWDFX2UV2KK4JFLZ3GTFAFBYPD7IHWCBBGMR6EJ6XAC 4RYFMDXFDD6CDZ73T2A4LBPBJEZ7N5DANPY6EVGFH43IQX2ZEFEQC 7G3PQFF6KRL7XLFTHVDNPFNFHNJRACG2SQK32WXK2D22AMUPFP3QC L2G3D7YWKDUA6FMEIWBCAJQVHEWE5RELWMWWLGBXFUDSVP7ZKUSQC JE5K2LGM25NQQ3VIBZ25WJEQ4AJJVFLZWOH5RLNX66NVGQWI3YMQC 45EMD3KLQPMERNMIKU5G76H6556XOMIW352TSBP7VLWJX2YYGS7AC C5U3HSOOQ7BKXKXIDS7MLVXUKDTHAWJ5NXNX6YDXTM3GWY5UWX4QC OYYZVCE3QHBVJM6IEKK5HTJRG5YOVQNCBRMSJENTHOI2WPJLNCFAC HC35ORPWMUNGV4G2TVNPID4ZDRNTWXE4U37LYT4QGSEQR2EXQJNAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC 6GSGCC5JQJ5NOKX36UHRNOCXNHDBS2A2TDMAR34UBOGWE2DORXIQC 2H32CFFM2FNS63JJPNM2S6HMO543EX72GMPOU5GI6HTMQYPL6I3AC 7CMQLE4XIFMWDEUZAOKIKDW7BHAJCK5S26APMEZ6TEFEH63TEZ6AC 3BYA46OYLVN6ZPGAZD5OGIMMH5PRWGNSU3ITJRCVBE6P5HYYYAYQC BZMLXBTB63CXPZZPFXM4VLE7IBXPBEZ6YLM4MSNQGJR4L5IBM3OAC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC QVVC7AYGVA6U64PTNA7L27422NLMO327P22BQKXEVIMPZHIHO7MQC P2ZCF3BBG523ZEOD6XQA4X5YEHBTWH3IM33YVHXP2SQ5POXZIH4QC J7KCPTGASQNRAKVKQ5FCXZ75E75PK7I2BB6MFSI3COWU6HRKTWSAC TFNFP2YQA4EOVE4VIXBEQSGACZSXHWIQ2T4TIPQ46R2MJW2C4B5AC FBK5ECMQ6HJSQSN7C3DICKJIRJ3CSO3CHCQ3ONPBKLLSHDGPBQ7QC 7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC I2B33Z7NZGC33AMDSSK446AZZYWKPHWLAGULVHKKZU4MVB4BNJOAC V3GWLMX6JL3YOYB427VLHPOTGHGWZK64HI6LLUU4X6CFMD2MEQMQC ILO5P5FRDUY4SEQEXMTUDKOPXAUBJRSORHHUVTLLCYOYSXBXOVRAC F42F3QNVICCXWPMNYL2QQJZNOVBVF4MXZUXNUC7KKYIRZ7R5HGPAC LJK4ZQATLSB4MKZG3ARZX5V6RFGTN3NLCN6GTCUGJQKU26SOXMUAC 77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC YCL3W2PFE6ILTGBFODCSXNPDIA46KVSZP2TI7HDMYAOEJT65RIEAC 25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC 74LQ7JXVLAFSHLI7LCBKFX47CNTYSKGUQSXNX5FCIUIGCC2JTR3QC ENOQQ6DEA6ECRNTBGYYNK7G3DFEILMKQBNKP4SUQIZW2L6HWVR7QC QHAYBZTRPVJMK55WXT3F63CNRSAEVN3CQAAG42GCJTONLXQLNNNQC APCC5AQ77EHT57NWJA4SRRQOFNTIZDDUJRAFAXJS75Q235TTPDDQC TRCCLE5RJ4VJULBOWOI2WC3RJU7WTEGS7RRQTDQL6W5UU246LKTQC F7Q7QRZACTDPP6KH3AB5J6B6B5PRVV4FURTOIGXHRHWNVSQT3TVAC QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC T2SN3NCG67IWNPYKDUUO45JADBS5QHFHAOD5V4ZYRRZ5CDTSEB6AC M5ZDZJBTOJ7SWQPZZQPC24JYZKP26MWSRDHXBWQE2MPPL6WCXOIQC HFCPPPYI366EDKNBDGVNSAW76OGQA2NYTKLSP4LC3VYKHPLWFJ6QC KXE7V7TPV4DW3Z4D6A2MJHEOBEX2WIIT4XGWLNIT4EL5QRBFNFIQC XPCGZBHHSL6MB3ORMUJI64BAERU6AZTIY6RK56BBW7SNB3IK24IAC UZ6N6HOUPGVSPC5NQROEEDWMEGJA5XUWUY2AKH5QG65AZ25PVXDAC KBBSDMAXAGEDFMIVL6BSPMMSOBZKWPJTFCLBGCHRLE5DGTVAACSAC XEC3L6W6TGIRWHINULNLKCIP4UBMHFYE33WJL7272I2GRRCFZBWAC ZJLJGSB2XSBQU42OFQMXL3EG4CXAQGOYAU6YTV2SAWZEJIPFH2CAC TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC BIZDHHK5LIO57S5AKHEPJFLWV5DAFKZIKYBGOUNGICSWTX7DCXKAC Z63Q4DA5J5TZAC5LN55UD4CLADUMU5Z73TGEVE2YUXCHIST2Y4QAC SJOTTUZMA3UTGT5D6LKUTBDP2CZFXT24FB5IAWCUFHSHLLACM75QC OXQNVH5GIMZERIBTC2S4EXHOEE4ZRIYZNY6IIY7HITBNBNI42DKAC 2RSY5J2ED2GM5R564UF5NEPDAEJDGLJJ6U3YO6UBQOX4KSLGNY7QC 6SSW2WIX3LUPDP2QI6Z75YUE53G5H3CZBAPCQA7OEQEPOCIXT73AC 23I5KJ245D43B6QYWS4TDQYJO2W2PKTDCLFBWPVAFDWS6L7NMGKQC DOZORMA366M4HB5JKSS27BMCR6ET7QNZNND2B7KV3NVEEPR5H7EAC JDM5R3HYGXKQKZWY35QZ2KOB24TFZ3FW2PCNXCRCMWG72AZC5ZXQC 6O5667Y65C5GTP4V3NBKWUN22IRGCAXEELJ6MCANMYPBOKDUO75QC JJULXW764V5C2HJKZNWQAEWB6QM5YZADD7ZCE35LYTBFEM6PMYCAC UKYGZDI6PYZPXDACCQGVPHANUP5ADCSNROOZIE7LYIZQWSNFHJZAC PNRMCHHEBCAUD2XBSSH6JOEQ6A6CFEZBCIX436DVD26DA52OCYTQC M2HMYLYYXSP5XGX6MCI77IT6UW5K4YSEUJWHPQPYXVSW5L36BJ2AC HODV46TCH5AGI42Z5JKVDX4VCRVQCNREJUL6W3TUJK6S77SXQNLQC 6LT6USGJOTDMRJGXLAN2NSZXK2GKWEXDKKUV6SVV7ZC6WI6EKMDQC DE2BXPJDLWN7F3LAYKUSWI5CFEYZMV2ZN4K2Y356NWIX4AIGD73QC VDMADGWYGYZJWAEWU3WE7UCPVDS2O6HOHCXLOML64U5UCH4FER3AC XRZPPYWPWUOM4SFNI6BHKH2UKJQNLKOV6Y7XIEPEZXE5QYRT26PAC ZBPZZ5A7AB2VFZKQ2UJXVDGUK22OCZJCEN2RWTGDGK3VXFCCDKVAC LUNOTEIMYZJ7JL5P55GEHUVSDEZMYX3TWYUB2ABRHAYJEWQSSXIAC GUXTGUEMZYBRGV5QUAQSJHG3AOIQDWWCDIMOX4LASFJAZVGL2WQAC RBC6SN3MFBHGSIHAMKBUD7S7ULXOW7AX3WLAB2DPFMHAADOEIL2QC RGWUYJO74FDGTH22CYSHBKFDGJ4S76WTLIULKPXA4QT5ZCNOB4LQC B5OK4FEITJ6MUT7J76OJJH2TOPTZGG7J7UPIJ6Z6WA5FC526FLTAC FW3BFOY6UIWUMYNALIJMPEBTRQIMKUVRHOVFOHDKB3KRGA2QOGPQC WTBQLBYFLQCF3NRAMB4Z2YA4MHYVFYI5YS7FXXBPICY2KCBA63AQC 4O3VTUJT5T7NBNF3Q45XO2WHS6TCJXVLH6CKX4K36WUBDRT5F6KAC TW7QOMTSLYPGUUWHGHLY5G5LV6QQRQIKK4BSE64RY7RDGKVDHCEAC JR2RAQ523LOWNDYJNK6AZVKI6WVMI622PIV72XWOVZYPXPUKSQWAC 3A3OAIFRFU3IHF6SDNDPCN3XYOFYIBYCEYJAXAFASCFDY76SMFXQC LJSES3YZH4RECLXVBRJXS54NJOLWXVBKV5GXBPVQBLRCYXX23X4AC Z6343ZVG2VOE7WOLBS7YLIWJ6XGCRCGJRJLP5WUVRTG7VOIXRRLAC S4BRP4VHB23F2FCC6BXNAN2MZRVUGW7QMXUEOAVZVGFXKXJPVLLQC LAMIVDKY7LO5ONX5Z273ZCCEA5UBENOJD5VWNE4AK2EXGFED6BFQC CJKEUBURR2NB7I43WBO3LGPSNMCM6SGR5HOPQKK5IKC3PN47JUDQC QHABWX5UYQAREZC4B6JGSRXSUH6DQLRD7WB4YGV4HHUHMTXY3ERAC YYMVEFSCN7DGZC74WGG53XOLQF42KY2KGBXF2GOAXCR6WEE5VHCQC XVRZIUEK3PHCL6JIBTIBYEUWOVLZ6MQZYUIFYCH454WDGDSBADLAC JXOE7KJIEAJHPLMZAJ6O4YHDTRB6BGNP6XT3ZSEFYGSIUMHR77KQC DMRXDEKHHBQNY37NPGZFAGUQPALWFANGGK4CUWIOQUPSLM2JBNFQC 3BJ2OOF4F524G6UKVGOZVT6W3FSTSHHTKRJADUBZCHDXZWV3KANQC G3HJCS277WA2VONPOJW6FAOQO7VHMSMLXZWYIXKFE4N4Y3OV7UZAC HSN6H5HDKBALFSBCGJMCNEG6M5KSCXGWPPHJGHUWOZI5EIERCBFQC Q3XHNSHW6FI4JCXSEABATRFBJPMCF7PXNG2K6ZQTRRPVMIZFHUBQC JM7UAK777RAVDAVLQLEOBRTGNW2B47S5G55XITJXO243IUNZHVYQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC MJWFTUS66PTCNEYXEJA3CUJFXNWXIKDD6H3V24PW7HK64NSVOFSAC 2WVP47RBNL5OVYMAZH7TKRYD7F2TGSZ5X74PWVGAYCQP26G3JUHQC L4RYVF46EQKMVOEADGRG4WMPVTQ6NNFGYMU4SHAH6XJIKWVHT77QC TLO257LZSB6ZO36STDUEWJBO2LETXFKTFGXELA6Y4BZBVAEIIINAC 7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC RM2JXW3ATVYRYHF3NMG5ALGI64OJ7IP2F3MDUDPUT5TBKSSN4KVQC OR7VGWIBRR55M7HATPIORQMMB4YQ7EQXO2IWAFFFPEJ4VV3ASRRQC F4WAQJD7KLOXHZOTOT6WG26PVIDHYNVS3AV6ZNXGAS7PDR4HBWQAC W5VEC2PBIM5DMU5233HOWAZUEPTGWJRZZIA3H35YYQQW6BTP6XUAC IWMCGZ57ZVHE6WSPYD2CZNSG7ZDKGRBNZVY3KLR53TGEM3OQJLBAC BPSH3LUDUTXMK2QZKSMFDTBNDD6HPILMCBLZNMCRLZZQKPS5QOQQC 7KWDC7XFNMBLSUO2HISIROBINZBX5T67LJEEXTAORXW2YZ7VWFGAC GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC EWC3J3FZP62OZWT3JBBPNPZUB7NR5ZF6MAJNMPCVV75E3TFBFYYAC OP6CTAKWCAU64JXQ3USQYR5E5IFHQHNCACII5UMVRXUTZXJQOAZAC R325RPUV26YH65VIJKYEFZ2XCVXQHO5N3ELPX6RNQ5TSI3JJNQGQC ZP2KE7A2LE7Z2S7AC45WE4CXDSEVDTWIMV2EM4IBUKXYJIDU6R7QC B62ICMDTN5V7R7RBL4JALFVKEMVOOVLRSJASRNYS6CGFWBEEF5JQC 5XSXMOBGXFLTIQE6WDXWWFVDOTUPZSIQ2FWT3YI5QMVU6D76IUYQC hunger += you.mutation[MUT_FAST_METABOLISM];
if (you.species == SP_VAMPIRE){switch (you.hunger_state){case HS_STARVING:case HS_NEAR_STARVING:hunger -= 3;break;case HS_VERY_HUNGRY:hunger -= 2;break;case HS_HUNGRY:hunger--;break;case HS_SATIATED:break;case HS_FULL:hunger++;break;case HS_VERY_FULL:hunger += 2;break;case HS_ENGORGED:hunger += 3;}}else{hunger += you.mutation[MUT_FAST_METABOLISM];
hunger += 6 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM );hunger += 9 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRES_TOOTH );
hunger += 6 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM );hunger += 9 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRES_TOOTH );
case HS_STARVING:attrib.push_back("resist poison");attrib.push_back("are susceptible to fire");attrib.push_back("significantly resist cold");attrib.push_back("strongly resist negative energy");attrib.push_back("resist torment");if (you.experience_level >= 13)attrib.push_back("are in touch with the powers of death");if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT)attrib.push_back("heal slowly (as a bat)!");elseattrib.push_back("do not heal!");break;case HS_NEAR_STARVING:attrib.push_back("resist poison");attrib.push_back("significantly resist cold");attrib.push_back("strongly resist negative energy");if (you.experience_level >= 13)attrib.push_back("are in touch with the powers of death");attrib.push_back("heal slowly!");break;case HS_HUNGRY:case HS_VERY_HUNGRY:attrib.push_back("resist poison");attrib.push_back("resist cold");attrib.push_back("significantly resist negative energy");if (you.experience_level >= 13)attrib.push_back("are in touch with the powers of death");attrib.push_back("heal slowly!");break;case HS_SATIATED:attrib.push_back("resist negative energy.");break;case HS_FULL:case HS_VERY_FULL:attrib.push_back("heal quickly.");break;case HS_ENGORGED:attrib.push_back("heal extremely quickly.");break;
case HS_STARVING:attrib.push_back("resist poison");attrib.push_back("are susceptible to fire");attrib.push_back("significantly resist cold");attrib.push_back("strongly resist negative energy");attrib.push_back("resist torment");if (you.experience_level >= 13)attrib.push_back("are in touch with the powers of death");if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT)attrib.push_back("heal slowly (as a bat)!");elseattrib.push_back("do not heal!");break;case HS_NEAR_STARVING:attrib.push_back("resist poison");attrib.push_back("significantly resist cold");attrib.push_back("strongly resist negative energy");if (you.experience_level >= 13)attrib.push_back("are in touch with the powers of death")attrib.push_back("have an extremely slow metabolism");attrib.push_back("heal slowly!");break;case HS_HUNGRY:case HS_VERY_HUNGRY:attrib.push_back("resist poison");attrib.push_back("resist cold");attrib.push_back("significantly resist negative energy");if (you.experience_level >= 13)attrib.push_back("are in touch with the powers of death");if (you.hunger_state == HS_HUNGRY)attrib.push_back("have a slow metabolism");elseattrib.push_back("have a very slow metabolism");attrib.push_back("heal slowly!");break;case HS_SATIATED:attrib.push_back("resist negative energy.");break;case HS_FULL:attrib.push_back("have a fast metabolism");attrib.push_back("heal quickly.");break;case HS_VERY_FULL:attrib.push_back("have a very fast metabolism");attrib.push_back("heal quickly.");break;case HS_ENGORGED:attrib.push_back("have an extremely fast metabolism");attrib.push_back("heal extremely quickly.");break;
// The values that are considerably different (ie level 13 is now 29000,// down from 41040 are because the second derivative goes from 9040 to
// The values that are considerably different (ie level 13 is now 29000,// down from 41040 are because the second derivative goes from 9040 to
// Note: The stats in in this list aren't intended to sum the same// for all races. The fact that Mummies and Ghouls are really low
// Note: The stats in in this list aren't intended to sum the same// for all races. The fact that Mummies and Ghouls are really low
void init_stack_blood_potions( item_def &stack, int age = -1 );void maybe_coagulate_blood_potions_floor( item_def &blood );void remove_oldest_potion_inv( item_def &stack );void drop_blood_potions_stack( int item, int quant );void pick_up_blood_potions_stack( int item, int quant );
}// initialize blood potions with a vector of timersvoid init_stack_blood_potions(item_def &stack, int age){ASSERT(stack.base_type == OBJ_POTIONS);ASSERT(stack.sub_type == POT_BLOOD);CrawlHashTable &props = stack.props;props.set_default_flags(SFLAG_CONST_TYPE);props["timer"].new_vector(SV_LONG);CrawlVector &timer = props["timer"];// for a newly created stack, all potions use the same timerconst long max_age = you.num_turns + (age == -1 ? 1200 : age);for (int i = 0; i < stack.quantity; i++)timer.push_back(max_age);ASSERT(timer.size() == stack.quantity);props.assert_validity();}// sort a CrawlVector<long>, should probably be done properly with templatesstatic void _long_sort(CrawlVector &vec){std::vector<long> help;while (!vec.empty())help.push_back(vec.pop_back());std::sort(help.begin(), help.end());long val;while (!help.empty()){val = help[help.size() - 1];help.pop_back();vec.push_back(val);}}void maybe_coagulate_blood_floor(item_def &blood){ASSERT(is_valid_item(blood));ASSERT(blood.base_type == OBJ_POTIONS);ASSERT (blood.sub_type == POT_BLOOD|| blood.sub_type == POT_BLOOD_COAGULATED);CrawlHashTable &props = blood.props;ASSERT(props.exists("timer"));CrawlVector &timer = props["timer"];ASSERT(timer.size() == blood.quantity);ASSERT(!timer.empty());// blood.sub_type could be POT_BLOOD or POT_BLOOD_COAGULATED// -> need different handlingint rot_limit = you.num_turns;int coag_limit = you.num_turns + 200; // check 200 turns later// first count whether coagulating is even necessaryint rot_count = 0;int coag_count = 0;std::vector<long> age_timer;long current;int size = timer.size();for (int i = 0; i < size; i++){current = timer.pop_back();if (rot_limit >= current)rot_count++;else if (coag_limit >= current){coag_count++;age_timer.push_back(current);}else // still some time until rotting/coagulating{timer.push_back(current);_long_sort(timer);break;}}if (!rot_count && !coag_count)return; // nothing to be doneif (!coag_count){dec_mitm_item_quantity(blood.link, rot_count);// timer is already up to datereturn;}// coagulated blood cannot coagulate any further...ASSERT(blood.sub_type == POT_BLOOD);// now that coagulating is necessary, check square for !coagulated bloodint o = igrd[blood.x][blood.y];while (o != NON_ITEM){if (mitm[o].base_type == OBJ_POTIONS&& mitm[o].sub_type == POT_BLOOD_COAGULATED){CrawlHashTable &props2 = mitm[o].props;ASSERT(props2.exists("timer"));CrawlVector &timer2 = props2["timer"];ASSERT(timer2.size() == mitm[o].quantity);// update timer -> push(pop)long val;while (!age_timer.empty()){val = age_timer[age_timer.size() - 1];age_timer.pop_back();timer2.push_back(val);}_long_sort(timer2);dec_mitm_item_quantity(blood.link, rot_count + coag_count);return;}o = mitm[o].link;}// if we got here nothing was found// create a new stack of potionso = get_item_slot( 100 + random2(200) );if (o == NON_ITEM)return;// these values are common to all: {dlb}mitm[o].base_type = OBJ_POTIONS;mitm[o].sub_type = POT_BLOOD_COAGULATED;mitm[o].quantity = coag_count;mitm[o].plus = 0;mitm[o].plus2 = 0;mitm[o].special = 0;mitm[o].flags = 0;item_colour(mitm[o]);CrawlHashTable &props_new = mitm[o].props;props_new.set_default_flags(SFLAG_CONST_TYPE);props_new["timer"].new_vector(SV_LONG);CrawlVector &timer_new = props_new["timer"];long val;while (!age_timer.empty()){val = age_timer[age_timer.size() - 1];age_timer.pop_back();timer_new.push_back(val);}ASSERT(timer_new.size() == coag_count);props_new.assert_validity();move_item_to_grid( &o, blood.x, blood.y );dec_mitm_item_quantity(blood.link, rot_count + coag_count);}// used for (q)uaff, (f)ire, and Evaporatevoid remove_oldest_potion_inv(item_def &stack){ASSERT(is_valid_item(stack));ASSERT(stack.base_type == OBJ_POTIONS);ASSERT (stack.sub_type == POT_BLOOD|| stack.sub_type == POT_BLOOD_COAGULATED);CrawlHashTable &props = stack.props;ASSERT(props.exists("timer"));CrawlVector &timer = props["timer"];ASSERT(timer.size() == stack.quantity);ASSERT(!timer.empty());// assuming already sorted, and first (oldest) potion validtimer.pop_back();// the quantity will be decreased elsewhere
item_def &stack = you.inv[item];ASSERT(stack.base_type == OBJ_POTIONS);ASSERT(stack.sub_type == POT_BLOOD|| stack.sub_type == POT_BLOOD_COAGULATED);CrawlHashTable &props = stack.props;ASSERT(props.exists("timer"));CrawlVector &timer = props["timer"];ASSERT(!timer.empty());// first check whether we can merge with an existing stack on the floorint o = igrd[you.x_pos][you.y_pos];while (o != NON_ITEM){if (mitm[o].base_type == OBJ_POTIONS&& mitm[o].sub_type == stack.sub_type){CrawlHashTable &props2 = mitm[o].props;ASSERT(props2.exists("timer"));CrawlVector &timer2 = props2["timer"];// update timer -> push(pop)for (int i = 0; i < quant; i++)timer2.push_back(timer.pop_back());ASSERT(timer2.size() == mitm[o].quantity);// re-sort timer_long_sort(timer2);// now the stack timer should be correct againASSERT(timer.size() == stack.quantity);return;}o = mitm[o].link;}// If we got here nothing was found.// Stuff could have been destroyed or offered, either case we'll// have to reduce the timer vector anyway.while (!timer.empty() && quant-- > 0)timer.pop_back();ASSERT(stack.quantity == timer.size());}// Should be called *after* move_item_to_player// unless the stack has been picked up in its entirety.void pick_up_blood_potions_stack(int item, int quant){ASSERT(quant > 0);// entire stack was taken?if (!is_valid_item(mitm[item]))return;item_def &stack = mitm[item];ASSERT(stack.base_type == OBJ_POTIONS);ASSERT(stack.sub_type == POT_BLOOD|| stack.sub_type == POT_BLOOD_COAGULATED);CrawlHashTable &props = stack.props;ASSERT(props.exists("timer"));CrawlVector &timer = props["timer"];ASSERT(!timer.empty());// first check whether we can merge with an existing stack in inventoryfor (int m = 0; m < ENDOFPACK; m++){if (!is_valid_item(you.inv[m]))continue;if (you.inv[m].base_type == OBJ_POTIONS&& you.inv[m].sub_type == stack.sub_type){CrawlHashTable &props2 = you.inv[m].props;ASSERT(props2.exists("timer"));CrawlVector &timer2 = props2["timer"];// update timer -> push(pop)for (int i = 0; i < quant; i++)timer2.push_back(timer.pop_back());ASSERT(timer2.size() == you.inv[m].quantity);// re-sort timer_long_sort(timer2);// now the stack timer should be correct againASSERT(timer.size() == stack.quantity);return;}}// If we got here nothing was found. Huh?ASSERT(stack.quantity == timer.size());}