/* * Implementation of scrolls. */ #include "obj.h" #include "vars.h" #include "dice.h" #include "pline.h" #include "format.h" #include "structs.h" #include "display.h" #include "obj-map.h" #include "phasing.h" #include "disputil.h" #include "objtypes.h" #include "mon-@-you.h" #include "obj-scroll.h" /* * Implementation of the scroll of identify: identify an object in the * player's inventory or the player's location's inventory. * * Note that this takes care to ensure that the player can say to * identify a location object and then, after looking at the * location's inventory, switch to the player inventory. Or vice * versa, of course. */ static void scroll_of_identify(void) { int dohere; int doinv; INVOBJ *io; objtypes[OBJ_SCROLL_OF_IDENTIFY].flags |= OTF_KNOWN; pline("This is a scroll of identify!"); dohere = 0; doinv = 0; if (you->loc->objs.inv) { if (you->invent.inv) { if (inv_scan(&you->invent,&invobj_unidentified)) { doinv = 1; } if (you->loc->objs.inv->link) { if (inv_scan(&you->loc->objs,&invobj_unidentified)) { dohere = 1; pline("There are objects here"); } else { pline("There are objects here, but they are all identified already"); } } else { if (inv_scan(&you->loc->objs,&invobj_unidentified)) { dohere = 1; pline("There is an object here"); } else { pline("There is an object here, but it is identified already"); } } if (!dohere && !doinv) { pline("What a pity everything in your inventory is also identified!"); } } else { if (you->loc->objs.inv->link) { pline("You are empty-handed, but there are objects here"); if (inv_scan(&you->loc->objs,&invobj_unidentified)) { dohere = 1; } else { pline("What a pity they are all identified already!"); } } else { pline("You are empty-handed, but there is an object here"); if (inv_scan(&you->loc->objs,&invobj_unidentified)) { dohere = 1; } else { pline("What a pity it is identified already!"); } } } } else { if (you->invent.inv) { if (inv_scan(&you->invent,&invobj_unidentified)) { doinv = 1; } else { pline("What a pity everything in your inventory is already identified!"); } } else { pline("What a pity you're empty-handed!"); } } if (dohere || doinv) showmsgbuf(1); if (dohere && doinv) { do { int i; INVENT *inv; i = choose_one("Which location do you want to identify an object from?","here",1,"your inventory",2,(char *)0,-1); if (i < 0) { if (confirm("Don't identify anything?")) { io = 0; break; } continue; } switch (i) { case 1: inv = &you->loc->objs; break; case 2: inv = &you->invent; break; default: panic("impossible inventory list"); } io = pick_inventory(inv,"Identify what (ESC for more choices)? ",&invobj_unidentified); if (io) break; } while (1); } else { do { io = pick_inventory(dohere?&you->loc->objs:&you->invent,"Identify what? ",&invobj_unidentified); } while (!io && !confirm("Don't identify anything?")); } if (io) identify_it(io,1); } /* * Implementation of the scroll of magic mapping. This can either * update the map-in-use or it can _become_ the map-in-use. (XXX the * latter does not currently work; the code here is correct, but * map_replace_current() doesn't work.) */ static void scroll_of_magic_mapping(INVOBJ *io) { objtypes[OBJ_SCROLL_OF_MAGIC_MAPPING].flags |= OTF_KNOWN; pline("This is a scroll of magic mapping!"); showmsgbuf(1); if (map && confirm("Do you want to just update the map you're using?")) { inv_remove(io->inv,io); invobjfree(io); map_complete(map,you->loc->on); } else { objfree(io->v[0]); io->v[0] = obj_make(OBJ_MAP); map_complete(io->v[0],you->loc->on); if (confirm("Use this map for this level?")) map_replace_current(io->v[0]); pline_invobj(io); } cleardisp(); drawmapped(you->loc->on); } /* * Implementation of the scroll of phasing. */ static void scroll_of_phasing(void) { pline("You are now out of phase!"); phase_mon(you,roll("50d4"),roll("10+2d6")); } /* * Read something. Currently, scrolls are the only readable objects. */ void read_it(INVOBJ *io) { OBJ *o; int autodestroy; if (io->dispn > 1) panic("read_it: >1 object"); o = io->v[0]; if (objtypes[o->type].class != OC_SCROLL) { pline("Reading non-scroll?"); impossible(); return; } autodestroy = 1; switch (o->type) { case OBJ_SCROLL_OF_MAGIC_MAPPING: scroll_of_magic_mapping(io); autodestroy = 0; break; case OBJ_SCROLL_OF_IDENTIFY: inv_remove(io->inv,io); invobjfree(io); scroll_of_identify(); autodestroy = 0; break; case OBJ_SCROLL_OF_PHASING: scroll_of_phasing(); break; } if (autodestroy) { inv_remove(io->inv,io); invobjfree(io); } } /* * The identical method for scrolls. */ static int identical_scroll(OBJ *o1, OBJ *o2) { return(o1->type==o2->type); } /* * The collapsible method for scrolls. */ static int collapsible_scroll(OBJ *o1, OBJ *o2) { return(identical_scroll(o1,o2)); } /* * The identified method for scrolls. */ static int identified_scroll(INVOBJ *io) { return(!!(objtypes[io->v[0]->type].flags&OTF_KNOWN)); } /* * The identify method for scrolls. */ static INVOBJ *identify_scroll(INVOBJ *io) { objtypes[io->v[0]->type].flags |= OTF_KNOWN; return(io); } /* * The OBJOPS vector for scrolls. */ #define new_scroll noop_new #define old_scroll noop_old #define format_scroll std_format #define fmt_cond_scroll panic_fmt_cond #define fmt_spec_scroll panic_fmt_spec #define split_scroll std_split #define moved_scroll noop_moved OBJOPS objops_scroll = OBJOPS_INIT(scroll);