1 // Hyperbolic Rogue - items
2 // Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
3 
4 /** \file item.cpp
5  *  \brief routines related to items
6  */
7 
8 #include "hyper.h"
9 
10 namespace hr {
11 
12 EX int currentLocalTreasure;
13 
14 /** for treasures, the number collected; for orbs, the number of charges */
15 EX array<int, ittypes> items;
16 
17 EX map<modecode_t, array<int, ittypes> > hiitems;
18 
cannotPickupItem(cell * c,bool telekinesis)19 EX bool cannotPickupItem(cell *c, bool telekinesis) {
20   return itemHidden(c) && !telekinesis && !(isWatery(c) && markOrb(itOrbFish));
21   }
22 
canPickupItemWithMagnetism(cell * c,cell * from)23 EX bool canPickupItemWithMagnetism(cell *c, cell *from) {
24   if(!c->item || c->item == itOrbYendor || isWall(c) || cannotPickupItem(c, false))
25     return false;
26   if(c->item == itCompass && from->item)
27     return false;
28   return true;
29   }
30 
doPickupItemsWithMagnetism(cell * c)31 EX bool doPickupItemsWithMagnetism(cell *c) {
32   /* repulsion works first -- Magnetism will collect the item if not repulsed */
33   if(items[itCurseRepulsion])
34     forCellIdEx(c3, i, c) if(c3->item) {
35       cellwalker cw(c, i);
36       cw += wstep;
37       for(int j=1; j<c3->type; j++) {
38         cell *c4 = (cw+j).peek();
39         if(!isNeighbor(c, c4) && c3->item && !c4->item && passable(c4, c3, ZERO)) {
40           changes.ccell(c3);
41           changes.ccell(c4);
42           c4->item = c3->item;
43           moveEffect(movei(c3, c4, (cw+j).spin), moDeadBird);
44           c3->item = itNone;
45           }
46         }
47       }
48   cell *csaf = NULL;
49   if(items[itOrbMagnetism])
50     forCellEx(c3, c) if(canPickupItemWithMagnetism(c3, c)) {
51       changes.ccell(c3);
52       changes.ccell(c);
53       if(c3->item == itCompass) {
54         if(!c->item)
55           moveItem(c3, c, false);
56         }
57       else if(c3->item == itOrbSafety || c3->item == itBuggy || c3->item == itBuggy2)
58         csaf = c3;
59       else if(markOrb(itOrbMagnetism))
60         collectItem(c3, false);
61       }
62   if(csaf)
63     return collectItem(csaf, false);
64   return false;
65   }
66 
pickupMovedItems(cell * c)67 EX void pickupMovedItems(cell *c) {
68   if(!c->item) return;
69   if(c->item == itOrbSafety) return;
70   if(isPlayerOn(c)) collectItem(c, true);
71   if(items[itOrbMagnetism])
72     forCellEx(c2, c)
73       if(isPlayerOn(c2) && canPickupItemWithMagnetism(c, c2)) {
74         changes.ccell(c2);
75         changes.ccell(c);
76         collectItem(c, true);
77         }
78   }
79 
in_lovasz()80 EX bool in_lovasz() {
81   return specialland == laMotion && bounded && ls::single() && !daily::on;
82   }
83 
collectItem(cell * c2,bool telekinesis IS (false))84 EX bool collectItem(cell *c2, bool telekinesis IS(false)) {
85 
86   bool dopickup = true;
87   bool had_choice = false;
88 
89   if(cannotPickupItem(c2, telekinesis))
90     return false;
91 
92   if(items[itCurseGluttony] && c2->item) {
93     addMessage(XLAT("%The1 is consumed!", c2->item));
94     playSound(c2, "apple");
95     items[itCurseGluttony] = 0;
96     c2->item = itNone;
97     return false;
98     }
99 
100   /* if(c2->item == itHolyGrail && telekinesis)
101     return false; */
102 
103   if(c2->item) {
104     invismove = false;
105     if(shmup::on) shmup::visibleFor(2000);
106     string s0 = "";
107 
108     if(c2->item == itPalace && items[c2->item] == 12)
109       changes.value_set(princess::forceVizier, true);
110 
111     if(!cantGetGrimoire(c2, false)) collectMessage(c2, c2->item);
112     if(c2->item == itDodeca && peace::on) peace::simon::extend();
113     }
114 
115   #if CAP_COMPLEX2
116   if(c2->land == laHunting && c2->item && !inv::activating) {
117     ambush::ambush(c2, ambush::size(c2, c2->item));
118     }
119   #endif
120 
121   if(isRevivalOrb(c2->item) && multi::revive_queue.size()) {
122     multiRevival(cwt.at, c2);
123     }
124   else if(isShmupLifeOrb(c2->item) && shmup::on) {
125     playSound(c2, "pickup-orb"); // TODO summon
126     gainLife();
127     }
128   else if(orbcharges(c2->item)) {
129     eItem it = c2->item;
130     if(it == itOrbRecall && !dual::state) {
131       cellwalker cw2 = cwt;
132       cw2++;
133       cw2.at = c2;
134       saveRecall(cw2);
135       }
136     if(it == itOrbFire) playSound(c2, "fire");
137     else if(it == itOrbFire) playSound(c2, "fire");
138     else if(it == itOrbWinter) playSound(c2, "pickup-winter");
139     else if(it == itOrbSpeed) playSound(c2, "pickup-speed");
140     else if(it == itRevolver) playSound(c2, "pickup-key");
141     else playSound(c2, "pickup-orb");
142     if(items[itOrbChoice]) items[itOrbChoice] = 0, had_choice = true;
143     int oc = orbcharges(it);
144     if(dual::state && among(it, itOrbTeleport, itOrbFrog, itOrbPhasing, itOrbDash, itOrbRecall)) {
145       oc = 10;
146       it = itOrbSpeed;
147       }
148     if(c2->land == laAsteroids) oc = 10;
149     if(markOrb(itOrbIntensity)) oc = intensify(oc);
150     if(!items[it]) items[it]++;
151     items[it] += oc;
152 
153     if(it == itOrbPurity) {
154       bool no_curses = true;
155       for(cell *c: dcal) if(c->land == laCursed) no_curses = false;
156       if(no_curses) {
157         items[itOrbSpeed] += 5;
158         items[itOrbWinter] += 5;
159         items[itOrbSlaying] += 5;
160         items[itOrbTime] += 5;
161         items[itOrbMagnetism] += 5;
162         items[itOrbChoice] += 5;
163         }
164       }
165     }
166   else if(c2->item == itOrbLife) {
167     playSound(c2, "pickup-orb"); // TODO summon
168     placeGolem(cwt.at, c2, moGolem);
169     if(cwt.at->monst == moGolem) cwt.at->stuntime = 0;
170     }
171   else if(c2->item == itOrbFriend) {
172     playSound(c2, "pickup-orb"); // TODO summon
173     placeGolem(cwt.at, c2, moTameBomberbird);
174     if(cwt.at->monst == moTameBomberbird) cwt.at->stuntime = 0;
175     }
176 #if CAP_TOUR
177   else if(tour::on && (c2->item == itOrbSafety || c2->item == itOrbRecall)) {
178     addMessage(XLAT("This Orb is not compatible with the Tutorial."));
179     if(changes.on) changes.rollback();
180     return true;
181     }
182 #endif
183   else if(c2->item == itOrbSafety) {
184 
185     if(changes.on) {
186       if(changes.checking) {
187         changes.rollback();
188         return true;
189         }
190       changes.commit();
191       }
192 
193     playSound(c2, "pickup-orb"); // TODO safety
194     if(!dual::state) items[c2->item] = 7;
195     if(shmup::on || multi::players > 1) {
196       shmup::delayed_safety = true;
197       shmup::delayed_safety_land = c2->land;
198       }
199     else
200       activateSafety(c2->land);
201     return true;
202     }
203   else if(c2->item == itBabyTortoise) {
204     using namespace tortoise;
205     int bnew = babymap[c2];
206     changes.map_value(babymap, c2);
207     babymap.erase(c2);
208     int bold = seekbits;
209     changes.value_set(tortoise::seekbits, bnew);
210     changes.value_set(tortoise::last, seekbits);
211     if(seek()) {
212       cell *c = passable(cwt.at, NULL, 0) ? cwt.at : c2;
213       changes.ccell(c);
214       c->item = itBabyTortoise;
215       if(c == c2) dopickup = false;
216       changes.map_value(babymap, c);
217       babymap[c] = bold;
218       }
219     else items[itBabyTortoise]++;
220     }
221   else if(c2->item == itOrbYendor && peace::on) {
222     if(!items[itDodeca]) {
223       addMessage(XLAT("Collect as many Dodecahedra as you can, then return here!"));
224       }
225     else {
226       addMessage(XLAT("Your score: %1", its(items[itDodeca])));
227       peace::simon::restore();
228       }
229     dopickup = false;
230     }
231   else if(c2->item == itOrbYendor && yendor::state(c2) != yendor::ysUnlocked) {
232     dopickup = false;
233     }
234   else if(c2->item == itOrbYendor)
235     yendor::collected(c2);
236   else if(c2->item == itHolyGrail) {
237     playSound(c2, "tada");
238     int v = newRoundTableRadius() + 12;
239     items[itOrbTeleport] += v;
240     items[itOrbSpeed] += v;
241     items[itHolyGrail]++;
242     addMessage(XLAT("Congratulations! You have found the Holy Grail!"));
243     if(!eubinary) changes.value_keep(c2->master->alt->emeraldval);
244     if(!eubinary) c2->master->alt->emeraldval |= GRAIL_FOUND;
245     achievement_collection(c2->item);
246     }
247   else if(c2->item == itKey) {
248     playSound(c2, "pickup-key");
249     for(int i=0; i<isize(yendor::yi); i++) if(yendor::yi[i].actual_key() == c2)
250       changes.value_set(yendor::yi[i].found, true);
251     items[itKey]++;
252     }
253   else if(!telekinesis && cantGetGrimoire(c2)) {
254     // telekinesis checks the condition earlier
255     dopickup = false;
256     }
257   else if(c2->item == itCompass) {
258     dopickup = false;
259     }
260   else if(c2->item == itBuggy || c2->item == itBuggy2) {
261 
262     if(changes.on) {
263       if(changes.checking) {
264         changes.rollback();
265         return true;
266         }
267       changes.commit();
268       }
269 
270     items[itOrbSafety] += 7;
271     if(shmup::on)
272       shmup::delayed_safety = true;
273     else {
274       buggyGeneration = false;
275       activateSafety(laCrossroads);
276       }
277     return true;
278     }
279   else if(c2->item == itTreat) {
280     playSound(c2, "pickup-scroll");
281     halloween::getTreat(c2);
282     }
283   else {
284     if(c2->item == itBarrow)
285       for(int i=0; i<c2->landparam; i++) gainItem(c2->item);
286     else if(c2->item) gainItem(c2->item);
287 
288     if(c2->item && (vid.bubbles_all || (among(items[c2->item], 5, 10, 25, 50, 100, 250, 500) && vid.bubbles_threshold))) {
289       drawBubble(c2, iinf[c2->item].color, its(items[c2->item]), 0.5);
290       }
291 
292     if(c2->item) {
293       char ch = iinf[c2->item].glyph;
294       if(ch == '*') playSound(c2, "pickup-gem");
295       else if(ch == '$' || ch == 'x') playSound(c2, "pickup-gold");
296       else if(ch == '%' || ch == ';') playSound(c2, "pickup-potion");
297       else if(c2->item == itApple) playSound(c2, "apple");
298       else playSound(c2, "pickup-scroll");
299       }
300     }
301 
302   if(dopickup && c2->item) {
303 #if CAP_HISTORY
304     // temporary variable to avoid the "cannot bind bitfield" problem in C++11
305     eItem dummy = c2->item;
306     history::findhistory.emplace_back(c2, dummy);
307 #endif
308 
309     if(c2->item == itBombEgg && c2->land == laMinefield) {
310       c2->landparam |= 2;
311       c2->landparam &= ~1;
312       }
313 
314     if(!had_choice)
315       c2->item = itNone;
316     }
317 //    if(c2->land == laHive)
318 //      c2->heat = 1;
319 
320   int numOrb = 0;
321   for(int i=0; i<ittypes; i++)
322     if(itemclass(eItem(i)) == IC_ORB && items[i])
323       numOrb++;
324   if(numOrb) achievement_count("ORB", numOrb, 0);
325 
326   if(princess::reviveAt && gold(NO_LOVE) >= princess::reviveAt && !inv::on) {
327     changes.value_set(princess::reviveAt, 0);
328     items[itSavedPrincess] = 1;
329     addMessage("You have enough treasure now to revive the Princess!");
330     }
331 
332   return false;
333   }
334 
glance_message()335 EX void glance_message() {
336   if(gold() >= 300)
337     addMessage(XLAT("You feel great, like a true treasure hunter."));
338   else if(gold() >= 200)
339     addMessage(XLAT("Your eyes shine like gems."));
340   else if(gold() >= 100)
341     addMessage(XLAT("Your eyes shine as you glance at your precious treasures."));
342   else if(gold() >= 50)
343     addMessage(XLAT("You glance at your great treasures."));
344   else if(gold() >= 10)
345     addMessage(XLAT("You glance at your precious treasures."));
346   else if(gold() > 0)
347     addMessage(XLAT("You glance at your precious treasure."));
348   else
349     addMessage(XLAT("Your inventory is empty."));
350   }
351 
dropGreenStone(cell * c)352 EX void dropGreenStone(cell *c) {
353   if(items[itGreenStone] && !passable(c, NULL, P_MONSTER)) {
354     // NOTE: PL/CZ translations assume that itGreenStone is dropped to avoid extra forms!
355     addMessage(XLAT("Cannot drop %the1 here!", itGreenStone));
356     return;
357     }
358   if(items[itGreenStone] && c->item == itNone) {
359     changes.ccell(c);
360     changes.value_keep(items[itGreenStone]);
361     items[itGreenStone]--;
362     if(false) {
363       c->item = itNone;
364       spill(c, eWall(c->wall ^ waFloorA ^ waFloorB), 3);
365       addMessage(XLAT("The slime reacts with %the1!", itGreenStone));
366       }
367     else {
368       c->item = itGreenStone;
369       addMessage(XLAT("You drop %the1.", itGreenStone));
370       if(isHaunted(cwt.at->land))
371         fail_survivalist();
372       }
373     }
374   else {
375     if(items[itGreenStone] && c->item == itGreenStone)
376       addMessage(XLAT("You juggle the Dead Orbs."));
377     else if(items[itGreenStone] && c->item)
378       addMessage(XLAT("You give %the1 a grim look.", c->item));
379     else if(items[itGreenStone]) {
380       addMessage(XLAT("Cannot drop %the1 here!", itGreenStone));
381       return;
382       }
383     else glance_message();
384     }
385   }
386 
moveItem1(cell * from,cell * to,bool activateYendor)387 EX void moveItem1(cell *from, cell *to, bool activateYendor) {
388   if(from->item == itOrbYendor) {
389     bool xnew = true;
390     for(int i=0; i<isize(yendor::yi); i++)
391       if(yendor::yi[i].path[0] == from) xnew = false;
392     if(xnew && activateYendor) yendor::check(from);
393     for(int i=0; i<isize(yendor::yi); i++)
394       if(yendor::yi[i].path[0] == from)
395         changes.value_set(yendor::yi[i].path[0], to);
396     }
397 
398   if(from->item == itKey) {
399     for(int i=0; i<isize(yendor::yi); i++) if(yendor::yi[i].path[YDIST-1] == from) {
400       changes.value_set(yendor::yi[i].path[YDIST-1], to);
401       }
402     for(int i=0; i<isize(yendor::yi); i++) if(yendor::yi[i].actualKey == from)
403       changes.value_set(yendor::yi[i].actualKey, to);
404     }
405 
406   if(from->item == itBabyTortoise || to->item == itBabyTortoise) {
407     tortoise::move_baby(from, to);
408     }
409 
410   eItem i = to->item;
411   to->item = from->item;
412   from->item = i;
413   }
414 
moveItem(cell * from,cell * to,bool activateYendor)415 EX void moveItem (cell *from, cell *to, bool activateYendor) {
416   static cell dummy;
417   dummy.item = itNone;
418   moveItem1(from, &dummy, activateYendor);
419   moveItem1(to, from, activateYendor);
420   moveItem1(&dummy, to, activateYendor);
421   }
422 
itemHidden(cell * c)423 EX bool itemHidden(cell *c) {
424   return isWatery(c) && !(shmup::on && shmup::boatAt(c));
425   }
426 
localTreasureType()427 EX eItem localTreasureType() {
428   lastland = singlepos()->land;
429   return treasureType(lastland);
430   }
431 
countLocalTreasure()432 EX void countLocalTreasure() {
433   eItem i = localTreasureType();
434   currentLocalTreasure = i ? items[i] : 0;
435   if(i != itHyperstone) for(int i=0; i<isize(dcal); i++) {
436     cell *c2 = dcal[i];
437     if(c2->cpdist > 3) break;
438     eItem i2 = treasureType(c2->land);
439     if(i2 && items[i2] < currentLocalTreasure)
440       currentLocalTreasure = items[i2];
441     }
442   }
443 
444 #if HDR
445 static const int NO_TREASURE = 1;
446 static const int NO_YENDOR = 2;
447 static const int NO_GRAIL = 4;
448 static const int NO_LOVE = 8;
449 #endif
450 
451 EX int gold(int no IS(0)) {
452   int i = 0;
453   if(!(no & NO_YENDOR)) i += items[itOrbYendor] * 50;
454   if(!(no & NO_GRAIL)) i += items[itHolyGrail] * 10;
455   if(!(no & NO_LOVE)) {
456     bool love = items[itOrbLove];
457 #if CAP_INV
458     if(inv::on && inv::remaining[itOrbLove])
459       love = true;
460 #endif
461 #if CAP_DAILY
462     if(daily::on) love = false;
463 #endif
464     if(love) i += 30;
465     }
466 
467   if(!(no & NO_TREASURE))
468     for(int t=0; t<ittypes; t++)
469       if(itemclass(eItem(t)) == IC_TREASURE)
470         i += items[t];
471   return i;
472   }
473 
maxgold()474 EX int maxgold() {
475   int mg = 0;
476   for(int i=0; i<ittypes; i++)
477     if(itemclass(eItem(i)) == IC_TREASURE && items[i] > mg)
478       mg = items[i];
479   return mg;
480   }
481 
updateHi_for_code(eItem it,int v,modecode_t xcode)482 EX void updateHi_for_code(eItem it, int v, modecode_t xcode) {
483   if(!yendor::on)
484     if(v > hiitems[xcode][it])
485       changes.value_set(hiitems[xcode][it], v);
486   }
487 
updateHi(eItem it,int v)488 EX void updateHi(eItem it, int v) {
489   updateHi_for_code(it, v, modecode());
490   }
491 
gainItem(eItem it)492 EX void gainItem(eItem it) {
493   int g = gold();
494   bool lhu = landUnlocked(laHell);
495   items[it]++; if(it != itLotus) updateHi(it, items[it]);
496   if(it == itRevolver && items[it] > 6) items[it] = 6;
497   achievement_collection(it);
498   multi::treasures[multi::cpid]++;
499 #if CAP_DAILY
500     if(daily::on) achievement_final(false);
501 #endif
502 
503   int g2 = gold();
504   if(items[itFireShard] && items[itAirShard] && items[itWaterShard] && items[itEarthShard]) {
505     items[itFireShard]--;
506     items[itAirShard]--;
507     items[itWaterShard]--;
508     items[itEarthShard]--;
509     gainItem(itElemental);
510     gainItem(itElemental);
511     gainItem(itElemental);
512     gainItem(itElemental);
513     addMessage(XLAT("You construct some Elemental Gems!", it) + itemcounter(items[itElemental]));
514     playSound(cwt.at, "elementalgem");
515     }
516 
517   if(it == itBounty)
518     items[itRevolver] = 6;
519 
520   if(it == itHyperstone && items[itHyperstone] == 10)
521     achievement_victory(true);
522 
523   if(ls::any_chaos() && gold() >= 300)
524     achievement_gain_once("CHAOS", rg::chaos);
525 
526 #if ISMOBILE
527   if(g < lastsafety + R30*3/2 && g2 >= lastsafety + R30*3/2)
528     addMessage(XLAT("The Orb of Safety from the Land of Eternal Motion might save you."));
529 #endif
530 
531 #define IF(x) if(g < (x) && g2 >= x && !peace::on)
532 
533   if(in_full_game()) {
534     IF(R60/4)
535       addMessage(XLAT("Collect treasure to access more different lands..."));
536     IF(R30)
537       addMessage(XLAT("You feel that you have enough treasure to access new lands!"));
538     IF(R30*3/2)
539       addMessage(XLAT("Collect more treasures, there are still more lands waiting..."));
540     IF(R60)
541       addMessage(XLAT("You feel that the stars are right, and you can access R'Lyeh!"));
542     IF(R30*5/2)
543       addMessage(XLAT("Kill monsters and collect treasures, and you may get access to Hell..."));
544     IF(R10 * 9)
545       addMessage(XLAT("To access Hell, collect %1 treasures each of 9 kinds...", its(R10)));
546     if(landUnlocked(laHell) && !lhu) {
547       addMessage(XLAT("Abandon all hope, the gates of Hell are opened!"));
548       addMessage(XLAT("And the Orbs of Yendor await!"));
549       }
550     }
551   }
552 
itemcounter(int qty)553 EX string itemcounter(int qty) {
554   string s = ""; s += " ("; s += its(qty); s += ")"; return s;
555   }
556 
gainShard(cell * c2,const char * msg)557 EX void gainShard(cell *c2, const char *msg) {
558   invismove = false;
559   string s = XLAT(msg);
560   if(is_mirrorland(c2) && !peace::on) {
561      collectMessage(c2, itShard);
562      gainItem(itShard);
563      s += itemcounter(items[itShard]);
564      }
565   addMessage(s);
566   c2->wall = waNone;
567   invismove = false;
568   }
569 
placeItems(int qty,eItem it)570 EX void placeItems(int qty, eItem it) {
571   int dcs = isize(dcal);
572   for(int i=1; qty && i<dcs; i++) {
573     cell *c = dcal[i];
574     if(!c->monst && !c->item && passable(c, NULL, 0))
575       c->item = it, qty--;
576     }
577   }
578 
cantGetGrimoire(cell * c2,bool verbose IS (true))579 EX bool cantGetGrimoire(cell *c2, bool verbose IS(true)) {
580   if(ls::any_chaos()) return false;
581   if(!eubinary && !c2->master->alt) return false;
582   if(c2->item == itGrimoire && items[itGrimoire] > celldistAlt(c2)/-temple_layer_size()) {
583     if(verbose)
584       addMessage(XLAT("You already have this Grimoire! Seek new tomes in the inner circles."));
585     return true;
586     }
587   return false;
588   }
589 
gainLife()590 EX void gainLife() {
591   items[itOrbLife] ++;
592   if(items[itOrbLife] > 5 && !inv::on) items[itOrbLife] = 5;
593   }
594 
collectMessage(cell * c2,eItem which)595 EX void collectMessage(cell *c2, eItem which) {
596   bool specialmode = yendor::on || princess::challenge || cheater || !in_full_game();
597 
598   if(which == itDodeca && peace::on) return;
599   if(which == itTreat) ;
600   else if(isElementalShard(which)) {
601     int tsh =
602       items[itFireShard] + items[itAirShard] + items[itWaterShard] + items[itEarthShard] +
603       items[itElemental];
604     if(tsh == 0) {
605       addMessage(XLAT("Collect four different Elemental Shards!"));
606       addMessage(XLAT("Unbalanced shards in your inventory are dangerous."));
607       }
608     else {
609       string t = XLAT("You collect %the1. (%2)", which, its(items[which]+1));
610       addMessage(t);
611       }
612     }
613   else if(which == itKey) {
614     addMessage(XLAT("You have found the Key! Now unlock this Orb of Yendor!"));
615     }
616   else if(which == itGreenStone && !items[itGreenStone])
617     addMessage(XLAT("This orb is dead..."));
618   else if(which == itGreenStone)
619     addMessage(XLAT("Another Dead Orb."));
620   else if(itemclass(which) != IC_TREASURE) {
621     if(!inv::activating)
622       addMessage(XLAT("You have found %the1!", which));
623     }
624   else if(which == itBabyTortoise) {
625     playSound(c2, playergender() ? "speak-princess" : "speak-prince");
626     addMessage(XLAT("Aww, poor %1... where is your family?", which));
627     }
628   else if(gold() == 0 && !specialmode)
629     addMessage(XLAT("Wow! %1! This trip should be worth it!", which));
630   else if(gold() == 1 && !specialmode)
631     addMessage(XLAT("For now, collect as much treasure as possible..."));
632   else if(gold() == 2 && !specialmode)
633     addMessage(XLAT("Prove yourself here, then find new lands, with new quests..."));
634   else if(!items[which] && itemclass(which) == IC_TREASURE)
635     addMessage(XLAT("You collect your first %1!", which));
636   else if(items[which] == 4 && maxgold() == U5-1 && !specialmode) {
637     addMessage(XLAT("You feel that %the2 become%s2 more dangerous.", which, c2->land));
638     addMessage(XLAT("With each %1 you collect...", which, c2->land));
639     }
640   else if(items[which] == 9 && maxgold() == 9 && !specialmode) {
641     if(inv::on) {
642       addMessage(XLAT("The treasure gives your magical powers!", c2->land));
643       if(!ISMOBILE)
644         addMessage(XLAT("Press 'i' to access your magical powers.", c2->land));
645       }
646     else
647       addMessage(XLAT("Are there any magical orbs in %the1?...", c2->land));
648     }
649   else if(items[which] == R10 && maxgold() == R10 && !specialmode && !inv::on) {
650     addMessage(XLAT("You feel that %the1 slowly become%s1 dangerous...", c2->land));
651     addMessage(XLAT("Better find some other place."));
652     }
653   else if(which == itHunting && items[itHunting] == 4 && !specialmode && !ISMOBWEB)
654     addMessage(XLAT("Hint: hold Alt to highlights enemies and other important features."));
655   else if(which == itSpice && items[itSpice] == U10*7/10 && !specialmode && isLandIngame(laHell))
656     addMessage(XLAT("You have a vision of the future, fighting demons in Hell..."));
657   else if(which == itSpice && items[itSpice] == U10-1 && !specialmode && isLandIngame(laRedRock))
658     addMessage(XLAT("You will be fighting red rock snakes, too..."));
659   else if(which == itKraken && items[itKraken] == U10-1 && !specialmode)
660     addMessage(XLAT("You feel that a magical weapon is waiting for you..."));
661 //  else if(which == itFeather && items[itFeather] == 10)
662 //    addMessage(XLAT("There should be a Palace somewhere nearby..."));
663   else if(which == itElixir && items[itElixir] == U5-1 && !specialmode)
664     addMessage(XLAT("With this Elixir, your life should be long and prosperous..."));
665   else if(which == itRuby && items[itRuby] == U5-1 && !specialmode && isLandIngame(laMountain)) {
666     addMessage(XLAT("You feel something strange about gravity here..."));
667     }
668   else if(which == itPalace && items[itPalace] == U5-1 && !specialmode && isLandIngame(laDungeon)) {
669     addMessage(XLAT("The rug depicts a man in a deep dungeon, unable to leave."));
670     }
671   else if(which == itFeather && items[itFeather] == 25-1 && !specialmode && inv::on && !ls::any_chaos())
672     addMessage(XLAT("You feel the presence of free saves on the Crossroads."));
673   else if(which == itHell && items[itHell] == 25-1 && !specialmode && inv::on && !ls::any_chaos())
674     addMessage(XLAT("You feel the Orbs of Yendor nearby..."));
675   else if(which == itHell && items[itHell] == 50-1 && !specialmode && inv::on && !ls::any_chaos())
676     addMessage(XLAT("You feel the Orbs of Yendor in the Crossroads..."));
677   else if(which == itHell && items[itHell] == 100-1 && !specialmode && inv::on && !ls::any_chaos())
678     addMessage(XLAT("You feel the Orbs of Yendor everywhere..."));
679   else if(which == itBone && items[itBone] % 25 == 24 && !specialmode && inv::on)
680     addMessage(XLAT("You have gained an offensive power!"));
681   else if(which == itHell && items[itHell] >= 100 && items[itHell] % 25 == 24 && !specialmode && inv::on)
682     addMessage(XLAT("A small reward for braving the Hell."));
683   else if(which == itIvory && items[itIvory] == U5-1 && !specialmode && (isLandIngame(laMountain) || isLandIngame(laDungeon))) {
684     addMessage(XLAT("You feel attuned to gravity, ready to face mountains and dungeons."));
685     }
686   else if(which == itBone && items[itBone] == U5+1 && !specialmode && isLandIngame(laHell))
687     addMessage(XLAT("The Necromancer's Totem contains hellish incantations..."));
688   else if(which == itStatue && items[itStatue] == U5+1 && !specialmode)
689     addMessage(XLAT("The inscriptions on the Statue of Cthulhu point you toward your destiny..."));
690   else if(which == itStatue && items[itStatue] == U5-1 && isLandIngame(laTemple))
691     addMessage(XLAT("There must be some temples of Cthulhu in R'Lyeh..."));
692   else if(which == itDiamond && items[itDiamond] == U10-2 && !specialmode)
693     addMessage(XLAT("Still, even greater treasures lie ahead..."));
694   else if(which == itFernFlower && items[itFernFlower] == U5-1 && isLandIngame(laEmerald))
695     addMessage(XLAT("You overheard Hedgehog Warriors talking about emeralds..."));
696   else if(which == itEmerald && items[itEmerald] == U5-1 && !specialmode && isLandIngame(laCamelot))
697     addMessage(XLAT("You overhear miners talking about a castle..."));
698   else if(which == itEmerald && items[itEmerald] == U5 && !specialmode && isLandIngame(laCamelot))
699     addMessage(XLAT("A castle in the Crossroads..."));
700   else if(which == itShard) ;
701   else {
702     int qty = (which == itBarrow) ? c2->landparam : 1;
703     string t;
704     if(which == itBarrow && items[which] < 25 && items[which] + qty >= 25)
705       t = XLAT("Your energy swords get stronger!");
706     else if(maxgold() < 25 && items[which] + qty >= 25)
707       t = XLAT("You feel even more attuned to the magic of this land!");
708     else t = XLAT("You collect %the1. (%2)", which, its(items[which]+qty));
709     addMessage(t);
710     }
711   }
712 
itemHiddenFromSight(cell * c)713 EX bool itemHiddenFromSight(cell *c) {
714   return isWatery(c) && !items[itOrbInvis] && !(items[itOrbFish] && playerInWater())
715     && !(shmup::on && shmup::boatAt(c));
716   }
717 
718 }
719