When you now press 'e' the following takes place:
Because of the way lua works, there's currently a problem that in the early stages (1-3) "q" (now also accepts Escape) will cause to skip ahead to the next stage rather than leaving the process entirely, which is of course less than optimal.
I also added two new options [1] prefer_safe_chunks (defaults to true) which will offer clean chunks before contaminated ones, even if the latter happens to be older
[2] easy_eat_chunks (defaults to false) which causes the prompting to be skipped for safe (i.e. clean) chunks, so you will automatically eat the oldest chunk that applies. This is ignored for undead characters.
I also got rid of the outdated safechnk.lua and chnkdata.lua seeing how chunk effects are no longer spoily information.
Added a new wizmode command: Ctrl-H, which allows you to set your character's hunger state. (Hopefully this will make Vampire testing easier.)
Also fix 2488374: "Controlled Flight being named upon levitation even if its type is already known.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8282 c06c8d41-db1a-0410-9941-cceddc491573
HQ5FYPDFIQNNDMKDSGWAAXYIVIRK42B4OBA2LESP2OA5SPKSTLVQC
XFEX5P3FHJUQ2USQMPSYVKRVI3BWOCVL5HUPN242TNT5FZLUCH6AC
Q57GOIHVFNJHTBYNUGJNME3UF2QFRJ6CN2UXVY47NHU7XAT7JJYAC
2NFQGSR74TVX4ULEDLQVIXZF6AOXSYQTLFAR3RFZL4Q5ZLUZEPDAC
OEP75MCBPSKOSYZLM6ZHGFNBOJLM2EBVDX4B3AQ2TXYPERXBFQJAC
UQZTF7HDI7VXYYYKZKVHKB53TEQC45XHYD3XNCRDTYNUSLSIMGIQC
T57T7U2OARKQBYXPOZ4BOL7JJW4WA356CVOQ6ZZOMOV3JQSGBEVQC
N7J2IWU7B34XIUYWHJF2RTRAXXAQLVVZLWWHFWN4FC5PLNFFEWCAC
6PNVX6Q45HH733TZDXYBA6BYPJKDMND5BA4N2MP6HA3QVNCEPN2QC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
BPZF2HJ53ACONE2EUFZO7QT3OLOOCCIHOBS47CGAHZA3XRC47MIQC
F7Q7QRZACTDPP6KH3AB5J6B6B5PRVV4FURTOIGXHRHWNVSQT3TVAC
QHAYBZTRPVJMK55WXT3F63CNRSAEVN3CQAAG42GCJTONLXQLNNNQC
P2ZCF3BBG523ZEOD6XQA4X5YEHBTWH3IM33YVHXP2SQ5POXZIH4QC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
GPEJOT73KMACP33IPAKFR5ROGHCOIP22VXZMQNYTGLEA2OSZUM2AC
VIFZ6DO6GWJGYMXJZKFZ2JYNPHNE74H3OFAOCPISQG7M7A4LCOHAC
NGW2XPEX2XRK3CYC37DNUZSSB5IQLECMKRB6NX257I2X3G35LMPAC
ABLV37FMURRJPEZV2VRKOUYAKEMLI7E6RA4PDAII2EJ5L7WBHKZQC
BLN5LDH5NRRJPBY77A36Q4THEY75N42MVCJMZRUZ2D5YSXTDL4HQC
HFCPPPYI366EDKNBDGVNSAW76OGQA2NYTKLSP4LC3VYKHPLWFJ6QC
CLIEHAE2PP7ZIGLLIMYCWM4FC54KBOAN5AILOLAZJ5S26GTJM4RQC
F42F3QNVICCXWPMNYL2QQJZNOVBVF4MXZUXNUC7KKYIRZ7R5HGPAC
YFIVTYI7PMVAXV23DUPXPAQNEY3YSFIXQGSN32I3WVHMMD5XS5DQC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
RTNCVAW3IRKSTVGF2RKT4MFCXNSMA6LHW45QVO4FZNYUNMRLJT2AC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
ZKUCBJJVLHVXJG7NMSWCVRLVVLFRE7SPRAMQGSWNCLO73T44LZ2QC
SQUBRQGLCJ6QRKDFXTEW4G7KIRKZJXZSGENVL6HCSYUXDBIMFOMQC
BFYHDL4EHSPKKC6EPKDRPESHYAA2WFKC6RXQIRRTSSTF3Z2QPVCAC
IXW2IM5ITYDCXDB3ORDDVAR5XUSPVQ3BWLP3Q6TRXNTIKGMZTHXAC
L6YPJVODN32IYLEZQQZE2ENH3XDAZ63IQIDX3PB4CJEK3A4NUNSAC
25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC
UET576SVCGS2TXEDRTO7BUTOTLJ77MYHIVZJCDWGH2BAXYMKG6DAC
RQR4PTMGQLTRWLYRU3KXIIDGND7FBORESJWMWFVD3WYU5SISZXAAC
BZIUKX6D2YDH4PCSNOAB3VA6CVE73IJEMQWDB6RKDRGL5AKCDOFAC
XXUOHQJZC3ODB7UMS5FMYAOXEAJK5TRYPVFRQYHK4OZ2DZVP6ARAC
57E4T664CXRFPVW2BZBYI33UIHFS4PSEZURZYPSYSZK5DRLJJ5CQC
JCWJWGMQIKQGSSFJUQRKNIWW3HBOJSHYDTOPPE5BWOJTIJTDYUTAC
4FQAKUKUO6PCAZ3N4HUR5XL6E4VA5UQUZ3AEDGRBLVY7W2LMWI7QC
5TG5LXU4DX65KMWCZ7YJHOB3VAETQAVBUHEUSQTPMA327XV2HQWAC
PDOFPXD2X6VI23AHKCGQ5RVDBG74CNP2E3YOHKXLOARHHBXEK3HQC
RM2JXW3ATVYRYHF3NMG5ALGI64OJ7IP2F3MDUDPUT5TBKSSN4KVQC
QGVAXJZXG2HUCLELWAN6LJJOBSP2BS6TIZMPJTDOAGI2E2SUCOCQC
B7DNCNY7SXL5WAW5B3XZP5KIQSBWOJ3N2YW46WOUQKTRBRRZ7YOQC
HQSI2RK5QGNSOR5Y67GZDK4ZWFZ5DSRPASXAV4VHYVB5TUXFZWJQC
HCQBAKIE4MXJ3XID6CECTZGNWYC33C3642KOKNKO37VVRDMJ2T4QC
4C6O4H7IO3LDZPBDGRST3QUFKMNQRB4Y6JXUV3NKIJVVPLAA2AWQC
4HLF6Q3OBOOHCCJ76L2BXVIYI6EMJ2G7O4XXZPFTLFP6BQGSUZNAC
QGIFCQMDBOD3QDWNSZOZFU7AHG2J53OWR5IE3VFCBNVO4SFBF2NQC
N3BRDQWPEHQZWIX2CDM2O2VLD6DJONGILDXVCSCAVWOGIOUU5IGAC
MLZSEZWNNZMSIDQNAAIOJJR4K7VSVJICL5SAGHD3ROM7SYDVZABAC
3ZWALZFSTSIVYXY4BAY6ANGINTDACZC6RSSJTEMQSTSUIE66YOBQC
CYAVI4PYWMMKTPYT5N2B3MI4OSHZFLPKOZFSLFJUXRYAACYXWW3AC
SXTWWMONWAVOGIYRQP6ALJLLNCDNT4NNDTE2HXCUOVP6HZ7XNXFQC
UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC
DYBB7LISQQKT734KRIQZCO67OGDQWLZ2KSTDZUY4BZFCCOIDTUWAC
53QXO6XQ6QAKCN6T5ADIKZM6UZCSAOAVKIJBHRN56BUVA653OZFAC
F77HEHFP26LGS3LSDB6J7ZWZUU4X6DMYPMQEAL2JXM4Y3KJU2UDQC
VOXLOCDUHOAFIKRTSISYMOA2QFY3TSHQGR7BKGGQ2VZ5BUUKUQYAC
CKY7MRFWMNHXIPJD5ZUAJN5T2YHUIEAYBNYYV5GN74LBZJRDJMEQC
4QRLZDW4KBFG34B3MCG4375NHFR3WKWSLWQKRMQ3OE5R26WCZBBQC
LTX72QGIPNUGWQN5ULPOMFCOPZTK7472DQY4AYX5WM3WHSUVXI5QC
BINKDWGFGUPTOA7IE5KK4ZIELGU5WC3X47MYXOWU4X43EGAC5DUAC
SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC
Q5YUZONIIPGRWOIQNL6DHRGLKF4V3K5XSZCBH2SL7DP4WPLDNOSQC
UBUOMGDTBC5WVGCZWLPC7JXZRPKNODQODFEPWB5ECSJT5J445JLQC
6CWMT6I76TMTHT7BVOVZJ7ATDMZ3VBKKICIRRZBOSGLHJMDS2DWQC
TEF6ARLDBINK4KG252IWV4IFAA7F3KT55MPDBZHHFYWTBITJFKIQC
WL5WZXFJ6TONUQRSHUY4GQ5USU47ILWNN5X2JDQZO4CRJJZSRQIAC
7MMBAVNSUSNLVE2G6Z25C3TGHYAYLCOOXQ63KHXPYUMOOSKNGDKAC
RVST2QHYJ757ZHK4AUJ5NGPDZ44AD6RVFVXYPKQIBJXZBDNUCHXQC
3PBG6FJ6WGSR4UM3I7UQUYYCSYU3UBCKCIKYKUEEANIK72TUL4XAC
QTFUA7DXD2QGKBXT7S5Z7RDHZ7BYFYWZOZPOTP5ZBR3PMKH257NQC
K2B4YUKFNQX33VFTVF4WRGMXUG7OG6AKCE67MU562QNBJXGOVQTAC
EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC
4TPFZIL52CS4HPO5LQMKS3PHTE2X2C547ULEFXKM4UIQQ64FUBGAC
if ((item.base_type == OBJ_CORPSES || item.sub_type == FOOD_CHUNK)
&& (is_good_god(you.religion) && is_player_same_species(item.plus)
|| you.religion == GOD_ZIN
&& mons_class_intel(item.plus) >= I_NORMAL))
{
if (is_forbidden_food(item))
modify_stat(STAT_STRENGTH, item.plus, false, item);
if (item.plus != 0 && !artefact)
ident = ID_KNOWN_TYPE;
learn_pluses = true;
if (item.plus)
{
modify_stat(STAT_STRENGTH, item.plus, false, item);
modify_stat(STAT_DEXTERITY, item.plus, false, item);
if (item.plus != 0 && !artefact)
ident = ID_KNOWN_TYPE;
learn_pluses = true;
if (item.plus)
{
modify_stat(STAT_DEXTERITY, item.plus, false, item);
if (artefact)
fake_rap = RAP_DEXTERITY;
else
ident = ID_KNOWN_TYPE;
modify_stat(STAT_INTELLIGENCE, item.plus, false, item);
if (item.plus != 0 && !artefact)
ident = ID_KNOWN_TYPE;
learn_pluses = true;
if (item.plus)
{
modify_stat(STAT_INTELLIGENCE, item.plus, false, item);
static bool _is_bad_food(item_def food)
{
return (is_poisonous(food) || is_mutagenic(food)
|| is_forbidden_food(food) || causes_rot(food));
}
// Returns which of two food items is older (true for first, else false).
struct compare_by_freshness
{
bool operator()(item_def *food1, item_def *food2)
{
ASSERT(food1->base_type == OBJ_CORPSES || food1->base_type == OBJ_FOOD);
ASSERT(food2->base_type == OBJ_CORPSES || food2->base_type == OBJ_FOOD);
ASSERT(food1->base_type == food2->base_type);
if (is_inedible(*food1))
return (false);
if (is_inedible(*food2))
return (true);
if (food1->base_type == OBJ_FOOD)
{
// Prefer chunks to non-chunks. (Herbivores handled above.)
if (food1->sub_type != FOOD_CHUNK && food2->sub_type == FOOD_CHUNK)
return (false);
if (food2->sub_type != FOOD_CHUNK && food1->sub_type == FOOD_CHUNK)
return (true);
}
// Both food types are edible (not rotten, or player is Saprovore).
if (food1->base_type == OBJ_CORPSES
|| food1->sub_type == FOOD_CHUNK && food2->sub_type == FOOD_CHUNK)
{
// Always offer poisonous/mutagenic chunks last.
if (_is_bad_food(*food1) && !_is_bad_food(*food2))
return (false);
if (_is_bad_food(*food2) && !_is_bad_food(*food1))
return (true);
else if (food_is_rotten(*si) && !_player_can_eat_rotten_meat())
else
{
if (si->base_type != OBJ_FOOD)
continue;
// Chunks should have been handled before.
if (skip_chunks && si->sub_type == FOOD_CHUNK)
continue;
}
if (!skip_chunks && food_is_rotten(*si)
&& !_player_can_eat_rotten_meat())
mprf(MSGCH_PROMPT, "%s %s%s? (ye/n/q/i?)",
(you.species == SP_VAMPIRE ? "Drink blood from" : "Eat"),
((si->quantity > 1) ? "one of " : ""),
item_name.c_str());
int keyin = tolower(getchm(KC_CONFIRM));
switch (keyin)
if (found_valid)
{
std::sort(food_items.begin(), food_items.end(), compare_by_freshness());
for (unsigned int i = 0; i < food_items.size(); ++i)
case 'q':
canned_msg(MSG_OK);
return -1;
case 'e':
case 'y':
if (can_ingest(si->base_type, si->sub_type, false))
item_def *item = food_items[i];
std::string item_name = get_message_colour_tags(*item, DESC_NOCAP_A,
MSGCH_PROMPT);
mprf(MSGCH_PROMPT, "%s %s%s? (ye/n/q/i?)",
(you.species == SP_VAMPIRE ? "Drink blood from" : "Eat"),
((item->quantity > 1) ? "one of " : ""),
item_name.c_str());
int keyin = tolower(getchm(KC_CONFIRM));
switch (keyin)
eat_floor_item(si->index());
return 1;
case ESCAPE:
case 'q':
canned_msg(MSG_OK);
return -1;
case 'e':
case 'y':
if (can_ingest(item->base_type, item->sub_type, false))
{
int ilink = item_on_floor(*item, you.pos());
if (ilink != NON_ITEM)
{
eat_floor_item(ilink);
return (true);
}
return (false);
}
need_more = true;
break;
case 'i':
case '?':
// Directly skip ahead to inventory.
return (0);
default:
// Else no: try next one.
break;
}
bool eat_from_inventory()
{
// Corpses should have been handled before.
if (you.species == SP_VAMPIRE)
return 0;
int unusable_corpse = 0;
int inedible_food = 0;
item_def *wonteat;
bool found_valid = false;
std::vector<item_def *> food_items;
for (int i = 0; i < ENDOFPACK; ++i)
{
if (!is_valid_item(you.inv[i]))
continue;
item_def *item = &you.inv[i];
if (you.species == SP_VAMPIRE)
{
if (item->base_type != OBJ_CORPSES || item->sub_type != CORPSE_BODY)
continue;
if (!mons_has_blood(item->plus))
{
unusable_corpse++;
continue;
}
}
else
{
// Chunks should have been handled before.
if (item->base_type != OBJ_FOOD || item->sub_type == FOOD_CHUNK)
continue;
}
if (food_is_rotten(*item) && !_player_can_eat_rotten_meat())
{
unusable_corpse++;
continue;
}
else if (!can_ingest(item->base_type, item->sub_type, true))
{
if (!inedible_food)
{
wonteat = item;
inedible_food++;
}
else
{
// Increase only if we're dealing with different subtypes.
// FIXME: Use a common check for herbivorous/carnivorous
// dislikes, for e.g. "Blech! You need blood!"
ASSERT(is_valid_item(*wonteat));
if (wonteat->sub_type != item->sub_type)
inedible_food++;
}
continue;
}
found_valid = true;
food_items.push_back(item);
}
if (found_valid)
{
std::sort(food_items.begin(), food_items.end(), compare_by_freshness());
for (unsigned int i = 0; i < food_items.size(); ++i)
{
item_def *item = food_items[i];
std::string item_name = get_message_colour_tags(*item, DESC_NOCAP_A,
MSGCH_PROMPT);
mprf(MSGCH_PROMPT, "%s %s%s? (ye/n/q)",
(you.species == SP_VAMPIRE ? "Drink blood from" : "Eat"),
((item->quantity > 1) ? "one of " : ""),
item_name.c_str());
int keyin = tolower(getchm(KC_CONFIRM));
switch (keyin)
{
case ESCAPE:
case 'q':
canned_msg(MSG_OK);
return (false);
case 'e':
case 'y':
if (can_ingest(item->base_type, item->sub_type, false))
{
eat_inventory_item(item->link);
return (true);
}
break;
default:
// Else no: try next one.
break;
}
}
}
else
{
// Give a message about why these food items can not actually be eaten.
if (unusable_corpse)
{
if (you.species == SP_VAMPIRE)
{
mprf("%s devoid of blood.",
unusable_corpse == 1 ? "The corpse you are carrying is"
: "The corpses you are carrying are");
}
else
_player_can_eat_rotten_meat(true);
}
else if (inedible_food)
{
if (inedible_food == 1)
{
ASSERT(is_valid_item(*wonteat));
// Use the normal cannot ingest message.
if (can_ingest(wonteat->base_type, wonteat->sub_type, false))
{
mprf(MSGCH_DIAGNOSTICS, "Error: Can eat %s after all?",
wonteat->name(DESC_PLAIN).c_str() );
}
}
else // Several different food items.
mpr("You refuse to eat these food items.");
}
}
return (false);
}
bool eat_chunks()
{
// Herbivores cannot eat chunks.
if (player_mutation_level(MUT_HERBIVOROUS) == 3)
return (false);
bool found_valid = false;
std::vector<item_def *> chunks;
// First search the stash on the floor, unless levitating.
if (you.flight_mode() != FL_LEVITATE)
{
for (stack_iterator si(you.pos()); si; ++si)
{
if (you.species == SP_VAMPIRE)
{
if (si->base_type != OBJ_CORPSES || si->sub_type != CORPSE_BODY)
continue;
if (!mons_has_blood(si->plus))
continue;
}
else if (si->base_type != OBJ_FOOD || si->sub_type != FOOD_CHUNK)
continue;
if (food_is_rotten(*si) && !_player_can_eat_rotten_meat())
continue;
found_valid = true;
chunks.push_back(&(*si));
}
}
// Then search through the inventory.
for (int i = 0; i < ENDOFPACK; ++i)
{
if (!is_valid_item(you.inv[i]))
continue;
item_def *item = &you.inv[i];
if (you.species == SP_VAMPIRE)
{
if (item->base_type != OBJ_CORPSES || item->sub_type != CORPSE_BODY)
continue;
if (!mons_has_blood(item->plus))
continue;
}
else if (item->base_type != OBJ_FOOD || item->sub_type != FOOD_CHUNK)
continue;
if (food_is_rotten(*item) && !_player_can_eat_rotten_meat())
continue;
found_valid = true;
chunks.push_back(item);
}
if (found_valid)
{
std::sort(chunks.begin(), chunks.end(), compare_by_freshness());
for (unsigned int i = 0; i < chunks.size(); ++i)
{
bool autoeat = false;
item_def *item = chunks[i];
std::string item_name = get_message_colour_tags(*item,
DESC_NOCAP_A,
MSGCH_PROMPT);
// Excempt undead from auto-eating since:
// * Mummies don't eat.
// * Vampire feeding takes a lot more time than eating a chunk
// and may have unintended consequences.
// * Ghouls may want to wait until chunks become rotten.
if (Options.easy_eat_chunks && !you.is_undead
&& !_is_bad_food(*item) && !is_contaminated(*item))
{
// If this chunk is safe to eat, just do so without prompting.
autoeat = true;
}
else
{
mprf(MSGCH_PROMPT, "%s %s%s? (ye/n/q)",
(you.species == SP_VAMPIRE ? "Drink blood from" : "Eat"),
((item->quantity > 1) ? "one of " : ""),
item_name.c_str());
}
int keyin = autoeat ? 'y' : tolower(getchm(KC_CONFIRM));
switch (keyin)
{
case ESCAPE:
case 'q':
canned_msg(MSG_OK);
return (false);
case 'e':
case 'y':
if (can_ingest(item->base_type, item->sub_type, false))
{
if (autoeat)
{
mprf("%s %s%s.",
(you.species == SP_VAMPIRE ? "Drinking blood from"
: "Eating"),
((item->quantity > 1) ? "one of " : ""),
item_name.c_str());
}
if (in_inventory(*item))
{
eat_inventory_item(item->link);
return (true);
}
else
{
int ilink = item_on_floor(*item, you.pos());
if (ilink != NON_ITEM)
{
eat_floor_item(ilink);
return (true);
}
return (false);
}
}
break;
default:
// Else no: try next one.
break;
}
}
}
return (false);
return (false);
}
bool is_forbidden_food(const item_def &food)
{
if (food.base_type != OBJ_CORPSES
&& (food.base_type != OBJ_FOOD || food.sub_type != FOOD_CHUNK))
{
return (false);
}
// Some gods frown upon cannibalistic behaviour.
if (god_hates_cannibalism(you.religion)
&& is_player_same_species(food.plus))
{
return (true);
}
// Zin doesn't like it if you eat beings with a soul.
if (you.religion == GOD_ZIN && mons_class_intel(food.plus) >= I_NORMAL)
return (true);
// Everything else is allowed.
-- SPOILER WARNING
--
-- This file contains spoiler information. Do not read or use this file if you
-- don't want to be spoiled. Further, the Lua code in this file may use this
-- spoily information to take actions on your behalf. If you don't want
-- automatic exploitation of spoilers, don't use this.
--
---------------------------------------------------------------------------
-- safechunk.lua:
-- Determines whether a chunk of meat is safe for your character to eat.
--
-- To use this, add this line to your init.txt:
-- lua_file = lua/safechunk.lua
--
-- This file has no directly usable functions, but is needed by gourmand.lua
-- and enables auto_eat_chunks in eat.lua.
---------------------------------------------------------------------------
function sc_safechunk(rot, race, mon)
if rot then
return false
end
end
if sc_pois[mon] and you.res_poison() > 0 then
return true
end
if sc_hcl[mon] or sc_mut[mon] then
end
-- Only contaminated and clean chunks remain, in theory. We'll accept
-- either
return true
end
return race == "Ghoul"
if you.saprovorous() < 2 then
-- SPOILER WARNING
--
-- This file contains spoiler information. Do not read or use this file if you
-- don't want to be spoiled. Further, the Lua code in this file may use this
-- spoily information to take actions on your behalf. If you don't want
-- automatic exploitation of spoilers, don't use this.
--
---------------------------------------------------------------------------
-- chnkdata.lua:
-- Raw data on chunks of meat, auto-extracted from mon-data.h.
--
-- To use this, add this line to your init.txt:
-- lua_file = lua/chnkdata.lua
--
-- This file has no directly usable functions, but is needed by gourmand.lua
-- and enables auto_eat_chunks in eat.lua.
---------------------------------------------------------------------------
sc_pois = {"killer bee","killer bee larva","quasit","scorpion","yellow wasp","giant beetle","kobold","queen bee","kobold demonologist","big kobold","wolf spider","brain worm","boulder beetle","giant mite","hydra","mottled dragon","brown snake","death yak","bumblebee","redback","spiny worm","golden dragon","elephant slug","green rat","orange rat","black snake","giant centipede","iron troll","naga","yellow snake","red wasp","soldier ant","queen ant","ant larva","spiny frog","orange demon","Green Death","giant amoeba","giant slug","giant snail","boring beetle","naga mage","naga warrior","brown ooze","azure jelly","death ooze","acid blob","ooze","shining eye","greater naga","eye of devastation","gila monster"}
sc_hcl = {"necrophage","ghoul"}
sc_mut = {"guardian naga","eye of draining","giant orange brain","great orb of eyes","glowing shapeshifter","shapeshifter","very ugly thing"}
function sc_to_hash(list)
local hash = { }
for _, i in ipairs(list) do
hash[i] = true
end
return hash
end
sc_cont = sc_to_hash( sc_cont )
sc_pois = sc_to_hash( sc_pois )
sc_hcl = sc_to_hash( sc_hcl )
sc_mut = sc_to_hash( sc_mut )
sc_cont = {"program bug","ettin","goblin","jackal","manticore","orc","ugly thing","two-headed ogre","hobgoblin","ogre","troll","orc warrior","orc wizard","orc knight","minotaur","beast","iron devil","orc sorcerer","","","hell knight","necromancer","wizard","orc priest","orc high priest","human","gnoll","earth elemental","fire elemental","air elemental","Ice Fiend","Shadow Fiend","spectral warrior","pulsating lump","rock troll","stone giant","flayed ghost","insubstantial wisp","vapour","ogre-mage","dancing weapon","elf","war dog","grey rat","giant mosquito","fire giant","frost giant","firedrake","deep troll","giant blowfly","swamp dragon","swamp drake","hill giant","giant cockroach","white imp","lemure","ufetubus","manes","midge","neqoxec","hellwing","smoke demon","ynoxinul","Executioner","Blue Death","Balrug","Cacodemon","demonic crawler","sun demon","shadow imp","shadow wraith","Mnoleg","Lom Lobon","Cerebov","Gloorx Vloq","orc warlord","deep elf soldier","deep elf fighter","deep elf knight","deep elf mage","deep elf summoner","deep elf conjurer","deep elf priest","deep elf high priest","deep elf demonologist","deep elf annihilator","deep elf sorcerer","deep elf death mage","Terence","Jessica","Ijyb","Sigmund","Blork the orc","Edmund","Psyche","Erolcha","Donald","Urug","Michael","Joseph","Snorg","Erica","Josephine","Harold","Norbert","Jozef","Agnes","Maud","Louise","Francis","Frances","Rupert","Wayne","Duane","Xtahua","Norris","Frederick","Margery","Boris","Geryon","Dispater","Asmodeus","Antaeus","Ereshkigal","vault guard","Killer Klown","ball lightning","orb of fire","boggart","quicksilver dragon","iron dragon","skeletal warrior","","&","warg","","","komodo dragon"}
-- Prompts to eat chunks from inventory.
-- Prompts to eat food in the following order:
-- 1) for chunks on the floor *and* in inventory, sorted by age
-- 2) for non-chunks on the floor
-- 3) for non-chunks in inventory
-- 4) opens the food menu of your inventory
function prompt_eat(i)
local iname = item.name_coloured(i, "a")
if item.quantity(i) > 1 then
iname = "one of " .. iname
end
crawl.mpr("Eat " .. iname .. "?", "prompt")
local res
res = crawl.getch()
if res == 27 then
res = "escape"
elseif res < 32 or res > 127 then
res = ""
else
res = string.lower(string.format("%c", res))
end
return res
end
function chunk_maybe_safe(chunk)
local rot = food.rotting(chunk)
local race = you.race()
if rot then
return you.saprovorous() > 0
end
return true
end
function is_chunk_safe(chunk)
local rot = food.rotting(chunk)
local race = you.race()
-- Check if the user has sourced safechunk.lua and chnkdata.lua
if not (sc_cont and sc_pois and sc_hcl and sc_mut and sc_safechunk) then
return false
end
local cname = item.name(chunk)
local mon
_, _, mon = string.find(cname, "chunk of (.+) flesh")
return sc_safechunk(rot, race, mon)
end
function c_eat(floor, inv)
-- To enable auto_eat_chunks, you also need to source chnkdata.lua and
-- safechunk.lua. WARNING: These files contain spoily information.
local auto_eat_chunks = options.auto_eat_chunks == "yes" or
options.auto_eat_chunks == "true"
if auto_eat_chunks then
local all = { }
for _, it in ipairs(floor) do table.insert(all, it) end
for _, it in ipairs(inv) do table.insert(all, it) end
for _, it in ipairs(all) do
if food.ischunk(it) and food.can_eat(it) and is_chunk_safe(it) then
local iname = item.name(it, "a")
if item.quantity(it) > 1 then
iname = "one of " .. iname
end
crawl.mpr("Eating " .. iname)
food.eat(it)
return
end
end
function c_eat()
-- Prompt to eat chunks off floor/inventory, sorted by age.
-- Returns true if the player chose to eat a chunk.
if food.prompt_eat_chunks() then
return
for i, it in ipairs(inv) do
-- If we have chunks in inventory that the player can eat, prompt.
if food.ischunk(it) and food.can_eat(it) and chunk_maybe_safe(it) then
local answer = prompt_eat(it)
if answer == "q" then
break
end
if answer == "escape" then
return
end
if answer == "y" or answer == "e" then
food.eat(it)
return
end
end
-- Prompt to eat a non-chunk from the inventory. Returns true if the player
-- ate something.
if food.prompt_inventory() then
return
}
static int item_on_floor(const item_def &item, const coord_def& where)
{
// Check if the item is on the floor and reachable
for (int link = igrd(where); link != NON_ITEM; link = mitm[link].link)
{
if (&mitm[link] == &item)
return (link);
}
return (NON_ITEM);
{ "do_eat", food_do_eat },
{ "prompt_floor", food_prompt_floor },
{ "prompt_inventory", food_prompt_inventory },
{ "can_eat", food_can_eat },
{ "eat", food_eat },
{ "rotting", food_rotting },
{ "ischunk", food_ischunk },
{ "do_eat", food_do_eat },
{ "prompt_eat_chunks", food_prompt_eat_chunks },
{ "prompt_floor", food_prompt_floor },
{ "prompt_inventory", food_prompt_inventory },
{ "prompt_inv_menu", food_prompt_inventory_menu },
{ "can_eat", food_can_eat },
{ "eat", food_eat },
{ "rotting", food_rotting },
{ "dangerous", food_dangerous },
{ "ischunk", food_ischunk },
break;
case CONTROL('H'):
mpr( "Set hunger state to s(T)arving, (N)ear starving, (H)ungry, (S)atiated, (F)ull or (E)ngorged?", MSGCH_PROMPT );
tmp = tolower(getch());
// Values taken from food.cc.
switch (tmp)
{
case 't':
you.hunger = 500;
break;
case 'n':
you.hunger = 1200;
break;
case 'h':
you.hunger = 2400;
break;
case 's':
you.hunger = 5000;
break;
case 'f':
you.hunger = 8000;
break;
case 'e':
you.hunger = 12000;
break;
default:
canned_msg( MSG_OK );
break;
}
food_change();
if (you.species == SP_GHOUL && you.hunger_state >= HS_SATIATED)
mpr("Ghouls can never be full or above!");
prompt_for_swap, easy_quit_item_prompts, easy_exit_menu,
sort_menus
prefer_safe_chunks, easy_eat_chunks, prompt_for_swap,
easy_quit_item_prompts, easy_exit_menu, sort_menus
prefer_safe_chunks = true
If eat.lua has been sourced, the (e)at command will prompt for
all chunks on the floor and in your inventory, sorted by age.
If this option is set to true, clean chunks will be offered
before contaminated ones even if the latter are older.
Poisonous, mutagenic, rot-inducing, and chunks forbidden by
your religion will always be offered last.
easy_eat_chunks = false
If this is set to true then when using the (e)at command, the
game will automatically determine the oldest chunk that is safe
to eat, and eat it without prompting.
If prefer_safe_chunks is set to false you will be prompted if
the oldest chunk happens to be contaminated, and you will always
be prompted for harmful chunks.
Note that this option is ignored for each of the undead races.