diff -c -r sl_orig/include/config.h sl_give/include/config.h *** sl_orig/include/config.h Fri Nov 30 05:28:32 2001 --- sl_give/include/config.h Wed Dec 26 21:56:14 2001 *************** *** 404,409 **** --- 404,411 ---- /* Originally added by zaga. */ #define OTHER_SERVICES /* shopkeeper services */ + #define GIVE_PATCH + /* #define SHOUT */ /* JRN -- shouting and petcommands - not implemented */ /* #define DEVEL_BRANCH */ /* Include development code */ diff -c -r sl_orig/include/extern.h sl_give/include/extern.h *** sl_orig/include/extern.h Fri Nov 30 05:27:48 2001 --- sl_give/include/extern.h Thu Dec 13 22:38:04 2001 *************** *** 2310,2315 **** --- 2310,2316 ---- E void FDECL(m_dowear, (struct monst *,BOOLEAN_P)); E struct obj *FDECL(which_armor, (struct monst *,long)); E void FDECL(mon_break_armor, (struct monst *)); + E void FDECL(mon_remove_armor, (struct monst *, struct obj *)); /* ### write.c ### */ diff -c -r sl_orig/src/cmd.c sl_give/src/cmd.c *** sl_orig/src/cmd.c Fri Nov 30 05:27:54 2001 --- sl_give/src/cmd.c Wed Dec 26 21:55:12 2001 *************** *** 69,74 **** --- 69,75 ---- extern int NDECL(dowhatis); /**/ extern int NDECL(doquickwhatis); /**/ extern int NDECL(dowhatdoes); /**/ + extern int NDECL(dogive); /* D: Give command */ extern int NDECL(dohelp); /**/ extern int NDECL(dohistory); /**/ extern int NDECL(doloot); /**/ *************** *** 522,527 **** --- 523,700 ---- return 0; } + static NEARDATA const char give_types[] = + { ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, 0 }; + + /* D: Give object to monster - borrows heavily from other code. + * The basic idea is to help the player to equip pets. We can't, + * however, restrict ourselves to this. #give should work like + * other commands where appropriate - giving tripe to a hostile + * cat should tame it just as throwing tripe does. + */ + STATIC_PTR int + dogive() + { + register int x, y; + struct monst *rec; /* The monster that gets your gift */ + struct obj *obj; /* The object you're giving away */ + boolean is_intel = FALSE; + int done = 0; + + if (nohands(youmonst.data)) { + pline("Could be hard without hands ..."); + return(0); + } + + if (u.uswallow) { + pline("You're in no position to give anything to anyone."); + return(0); + } + + if (*u.ushops) { + struct monst *shk = shop_keeper(*u.ushops); + if (shk) { + pline("Not in here, %s might get the wrong idea...", + mon_nam(shk)); + return(0); + } + } + + obj = getobj(give_types, "give away"); + + if (!obj) + return (0); + + if (obj->oclass != GOLD_CLASS) + freeinv(obj); + else { + pline("Try to (p)ay instead"); + goto abort_give; + } + + if (!canletgo(obj, "give away")) + goto abort_give; + + if(obj == uwep && welded(uwep)) { + weldmsg(obj); + goto abort_give; + } + + if(!getdir(NULL)) goto abort_give; + if (!u.dx && !u.dy) goto abort_give; + + x = u.ux + u.dx; + y = u.uy + u.dy; + + if (!MON_AT(x, y)) { + You("gesture generously at nothing."); + goto abort_give; + } + + done = 1; + + rec = m_at(x, y); + + /* D: Verify that we're not giving anything to a sleeping monster */ + /* Keep the check specific to monsters that can normally be + * #given stuff */ + if (rec->mtame || + (obj->oclass == FOOD_CLASS && is_domestic(rec->data))) { + if (!rec->mcanmove || rec->msleeping) { + pline("%s seems not to notice.", Monnam(rec)); + goto abort_give; + } + } + + is_intel = !is_animal(rec->data) && !mindless(rec->data); + + /* D: Keep things simple - don't deal with anything but pets */ + /* Special case taming, but nothing else */ + if (!rec->mtame && + obj->oclass == FOOD_CLASS && is_domestic(rec->data)) { + boolean was_hostile = !rec->mpeaceful; + + if(obj == uwep) { + setuwep((struct obj *)0); + } + + if(obj == uquiver) { + setuqwep((struct obj *)0); + } + if (obj == uswapwep) { + setuswapwep((struct obj *)0); + } + + /* Taming attempt failed */ + if (!tamedog(rec, obj)) { + if (was_hostile && rec->mpeaceful) { + pline("%s isn't interested, but appreciates your offer.", Monnam(rec)); + goto abort_give; + } + } else { + return (1); + } + } + + /* D: More complex interactions could potentially be added, making + * #give more interesting, but most of the scenarios I see + * make #give duplicate the function of other commands, which + * is unnecessary. Therefore, fob player off with a stock + * message when s/he tries something we don't allow. + */ + if (!rec->mtame) { + if (rec->isshk && obj->oclass == GOLD_CLASS) /* Won't happen */ + pline("Try (p)aying %s instead.", mon_nam(rec)); + else if (rec->mpeaceful) { + if (Role_if(PM_ROGUE)) + pline("The thought of charity appalls you."); + else + pline("You decide that this isn't the place for charity."); + } else + pline("%s isn't interested." , Monnam(rec)); + goto abort_give; + } + + /* D: Decide whether the pet should have this or not */ + if ((is_intel || obj->oclass == FOOD_CLASS) && + can_carry(rec, obj)) { + if(obj == uwep) { + setuwep((struct obj *)0); + } + + if(obj == uquiver) { + setuqwep((struct obj *)0); + } + if (obj == uswapwep) { + setuswapwep((struct obj *)0); + } + You("give %s to %s.", doname(obj), mon_nam(rec)); + mpickobj(rec, obj); + + if (attacktype(rec->data, AT_WEAP) && + rec->weapon_check == NEED_WEAPON) { + rec->weapon_check = NEED_HTH_WEAPON; + (void) mon_wield_item(rec); + } + m_dowear(rec, FALSE); + + return (1); + } else { + long objmask = obj->owornmask; + obj->owornmask = 0; + You("offer %s to %s.", doname(obj), mon_nam(rec)); + obj->owornmask = objmask; + pline("%s ignores your offer.", Monnam(rec)); + } + + /* D: No return here - if #give succeeds, a return should be done + * immediately after transferring the object to the monster's + * inventory */ + abort_give: + addinv(obj); + return(done); + } + STATIC_PTR int playersteal() *************** *** 590,604 **** if (chanch < 5) chanch = 5; if (chanch > 95) chanch = 95; if (rnd(100) < chanch || mdat->mtame) { ! if (mdat->mgold) { temp = (u.ulevel * rn1(25,25)); if (temp > mdat->mgold) temp = mdat->mgold; u.ugold += temp; mdat->mgold -= temp; ! You("steal %d gold.",temp); ! } else ! You("don't find anything to steal."); exercise(A_DEX, TRUE); return(1); --- 763,947 ---- if (chanch < 5) chanch = 5; if (chanch > 95) chanch = 95; if (rnd(100) < chanch || mdat->mtame) { ! boolean attempted_borrow = FALSE; ! if (mdat->mtame && mdat->minvent) { ! struct obj *split; ! ! menu_item *pick_list = 0; ! int n, i; ! ! /* To save ourselves grief, wake up sleepers */ ! if (mdat->msleeping) ! mdat->msleeping = 0; ! ! /* If in shop, chicken out */ ! if (*u.ushops) { ! struct monst *shk = shop_keeper(*u.ushops); ! if (shk) { ! pline("Not in here, %s might get the wrong idea...", ! mon_nam(shk)); ! return(0); ! } ! } ! ! attempted_borrow = TRUE; ! /* D: You can now #borrow all kinds of stuff ! * from pets ! */ ! n = query_objlist("Borrow what?", ! mdat->minvent, ! INVORDER_SORT, ! &pick_list, ! PICK_ANY, ! allow_all); ! for (i = 0; i < n; ++i) { ! struct obj *obj = pick_list[i].item.a_obj; ! int count = pick_list[i].count; ! boolean given = FALSE; ! ! if (!obj || obj == &zeroobj) ! continue; ! ! if (count > obj->quan) ! count = obj->quan; ! ! if (count <= 0) { ! impossible("Negative count for item?"); ! continue; ! } ! ! /* Verify available inventory slots */ ! if (obj->oclass != GOLD_CLASS && inv_cnt() >= 52 ! && !merge_choice(invent, obj)) { ! Your("knapsack cannot accommodate any more items."); ! continue; ! } ! ! if (obj->owornmask) { ! if (obj->cursed) { ! if ((obj->owornmask == W_WEP && obj->otyp != CORPSE) ! || obj->owornmask != W_WEP) { ! char buf[BUFSZ]; ! strcpy(buf, s_suffix(mon_nam(mdat))); ! You("can't take %s %s. %s to be cursed.", ! buf, xname(obj), ! is_boots(obj) || is_gloves(obj) ! || obj->quan > 1L? ! "They seem" : "It seems" ! ); ! obj->bknown = TRUE; ! continue; ! } ! } ! ! if (is_gloves(obj) && mdat->mw && ! mdat->mw->otyp == CORPSE) { ! if (touch_petrifies(&mons[mdat->mw->corpsenm])) { ! char buf[BUFSZ]; ! strcpy(buf, Monnam(mdat)); ! pline("%s refuses to give you %s %s.", ! buf, his[pronoun_gender(mdat)], ! xname(obj)); ! continue; ! } ! } ! } ! ! /* Beyond this point, we can assume the ! * object's as good as given */ ! if (count < obj->quan) { ! split = splitobj(obj, ! obj->quan - count); ! ! /* And hereafter, deal only with ! * 'split' */ ! if (split) ! obj = split; ! } ! ! obj_extract_self(obj); ! ! if (obj->owornmask) { ! ! if (obj->owornmask != W_WEP) { ! char buf[BUFSZ]; ! mon_remove_armor(mdat, obj); ! ! if (!is_animal(mdat->data) && ! !nohands(mdat->data) && ! !mindless(mdat->data) && ! mdat->mcanmove) ! given = TRUE; ! } else { ! obj->owornmask = 0; ! possibly_unwield(mdat); ! } ! } ! ! { ! char buf[BUFSZ]; ! if (given) { ! strcpy(buf, Monnam(mdat)); ! pline("%s gives you %s %s.", ! buf, ! his[pronoun_gender(mdat)], ! xname(obj)); ! } else { ! strcpy(buf, ! s_suffix(mon_nam(mdat))); ! You("take %s %s.", ! buf, xname(obj)); ! } ! } ! if (obj->oartifact && ! !touch_artifact(obj, &youmonst)) ! dropy(obj); ! else { ! /* Can we lift this? */ ! /* Petrifying corpse? */ ! if (obj->otyp == CORPSE ! && touch_petrifies(&mons[obj->corpsenm]) ! && !uarmg && !Stone_resistance) { ! if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) ! display_nhwindow(WIN_MESSAGE, FALSE); ! else { ! char kbuf[BUFSZ]; ! ! pline("Touching %s corpse is a fatal mistake.", ! an(mons[obj->corpsenm].mname)); ! Sprintf(kbuf, "%s corpse", an(mons[obj->corpsenm].mname)); ! addinv(obj); ! instapetrify(kbuf); ! if (pick_list) ! free((genericptr_t) pick_list); ! return -1; ! } ! } ! addinv(obj); ! { ! char buf[BUFSZ]; ! sprintf(buf, "%c - %s ", ! obj->invlet, ! doname(obj)); ! pline(buf); ! } ! } ! } ! if (pick_list) ! free((genericptr_t) pick_list); ! } ! if (mdat->mgold) { temp = (u.ulevel * rn1(25,25)); if (temp > mdat->mgold) temp = mdat->mgold; u.ugold += temp; mdat->mgold -= temp; ! You("%s %d gold.", ! mdat->mtame? "borrow" : "steal", ! temp); ! } else if (!attempted_borrow) ! You("don't find anything to %s.", ! mdat->mtame? "borrow" : "steal"); exercise(A_DEX, TRUE); return(1); *************** *** 613,619 **** } return(0); ! } #ifdef WIZARD STATIC_PTR int --- 956,962 ---- } return(0); ! } #ifdef WIZARD STATIC_PTR int *************** *** 1554,1559 **** --- 1897,1903 ---- {'d', FALSE, dokick, "Do Kick"}, /* {'e', FALSE, specialpower, "Use your Class Ability [M-e]"},*/ {'e', TRUE, enhance_weapon_skill, "Weapon Skills [M-k]"}, + {'g', TRUE, dogive, "Give item to pet [M-g]"}, {'m', TRUE, domonability, "Use your Monster Ability [M-m]"}, {'o', FALSE, dosacrifice, "Offer a Sacrifice [M-o]"}, {'p', FALSE, dopay, "Pay the Shopkeeper"}, *************** *** 1885,1890 **** --- 2229,2235 ---- /* 'F' : fight (one time) */ {M('f'), FALSE, doforce}, /* 'g', 'G' : multiple go */ + {M('g'), FALSE, dogive}, /* D: Give command */ /* 'h', 'H' : go west */ {'h', TRUE, dohelp}, /* if number_pad is set */ {'i', TRUE, ddoinv}, *************** *** 1988,1993 **** --- 2333,2339 ---- #endif {"explore", "enter explore mode", enter_explore_mode, TRUE}, {"force", "force a lock", doforce, FALSE}, + {"give", "give object to pet", dogive, FALSE}, {"invoke", "invoke an object's powers", doinvoke, TRUE}, {"jump", "jump to a location", dojump, FALSE}, {"loot", "loot a box on the floor", doloot, FALSE}, diff -c -r sl_orig/src/worn.c sl_give/src/worn.c *** sl_orig/src/worn.c Fri Nov 30 05:28:08 2001 --- sl_give/src/worn.c Thu Dec 13 22:43:36 2001 *************** *** 485,490 **** --- 485,507 ---- newsym(mon->mx, mon->my); } + /* D: Remove piece of armor with appropriate checks - just a proxy for + * m_lose_armor + */ + void mon_remove_armor(mon, obj) + struct monst *mon; + struct obj *obj; + { + if (!(mon && obj)) + impossible("NULL monster or armor"); + /* D: We don't check that this is really the monster's obj */ + if (mon->misc_worn_check & obj->owornmask) { + m_lose_armor(mon, obj); + obj_extract_self(obj); + newsym(mon->mx, mon->my); + } + } + void mon_break_armor(mon) struct monst *mon;