diff --git a/include/monst.h b/include/monst.h index c7de88fe8..595af0e69 100644 --- a/include/monst.h +++ b/include/monst.h @@ -6,7 +6,7 @@ #define MONST_H /* The weapon_check flag is used two ways: - * 1) When calling mon_wield_item, is 2, 3, or 4 depending on what is desired. + * 1) When calling mon_wield_item, is 2-6 depending on what is desired. * 2) Between calls to mon_wield_item, is 0 or 1 depending on whether or not * the weapon is known by the monster to be cursed (so it shouldn't bother * trying for another weapon). @@ -20,6 +20,8 @@ # define NEED_RANGED_WEAPON 2 # define NEED_HTH_WEAPON 3 # define NEED_PICK_AXE 4 +# define NEED_AXE 5 +# define NEED_PICK_OR_AXE 6 /* The following flags are used for the second argument to display_minventory * in invent.c: diff --git a/src/dogmove.c b/src/dogmove.c index 616fbe604..b6d688fe0 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -565,10 +565,7 @@ register int after; /* this is extra fast monster movement */ if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR; } if (is_giant(mtmp->data)) allowflags |= BUSTDOOR; - if (tunnels(mtmp->data) && (!needspick(mtmp->data) || - m_carrying(mtmp, PICK_AXE) || - m_carrying(mtmp, DWARVISH_MATTOCK))) - allowflags |= ALLOW_DIG; + if (tunnels(mtmp->data)) allowflags |= ALLOW_DIG; cnt = mfndpos(mtmp, poss, info, allowflags); /* Normally dogs don't step on cursed items, but if they have no @@ -714,12 +711,22 @@ newdogpos: } if (!m_in_out_region(mtmp, nix, niy)) return 1; - if(IS_ROCK(levl[nix][niy].typ) && may_dig(nix,niy) && + if (((IS_ROCK(levl[nix][niy].typ) && may_dig(nix,niy)) || + closed_door(nix, niy)) && mtmp->weapon_check != NO_WEAPON_WANTED && - tunnels(mtmp->data) && needspick(mtmp->data) && - (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp))) { - mtmp->weapon_check = NEED_PICK_AXE; - if (mon_wield_item(mtmp)) + tunnels(mtmp->data) && needspick(mtmp->data)) { + if (closed_door(nix, niy)) { + if (!(mw_tmp = MON_WEP(mtmp)) || + !is_pick(mw_tmp) || !is_axe(mw_tmp)) + mtmp->weapon_check = NEED_PICK_OR_AXE; + } else if (IS_TREE(levl[nix][niy].typ)) { + if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp)) + mtmp->weapon_check = NEED_AXE; + } else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) { + mtmp->weapon_check = NEED_PICK_AXE; + } + if (mtmp->weapon_check >= NEED_PICK_AXE && + mon_wield_item(mtmp)) return 0; } /* insert a worm_move() if worms ever begin to eat things */ diff --git a/src/mon.c b/src/mon.c index e684f2335..410cd50e7 100644 --- a/src/mon.c +++ b/src/mon.c @@ -952,6 +952,7 @@ mfndpos(mon, poss, info, flag) register uchar ntyp; uchar nowtyp; boolean wantpool,poolok,lavaok,nodiag; + boolean rockok = FALSE, treeok = FALSE, thrudoor; int maxx, maxy; x = mon->mx; @@ -963,6 +964,27 @@ mfndpos(mon, poss, info, flag) poolok = is_flyer(mdat) || is_clinger(mdat) || (is_swimmer(mdat) && !wantpool); lavaok = is_flyer(mdat) || is_clinger(mdat) || likes_lava(mdat); + thrudoor = (flag & (ALLOW_WALL|BUSTDOOR)); + if (flag & ALLOW_DIG) { + struct obj *mw_tmp; + + /* need to be specific about what can currently be dug */ + if (!needspick(mdat)) { + rockok = treeok = TRUE; + } else if ((mw_tmp = MON_WEP(mon)) && mw_tmp->cursed && + mon->weapon_check == NO_WEAPON_WANTED) { + rockok = is_pick(mw_tmp); + treeok = is_axe(mw_tmp); + } else { + rockok = (m_carrying(mon, PICK_AXE) || + (m_carrying(mon, DWARVISH_MATTOCK) && + !which_armor(mon, W_ARMS))); + treeok = (m_carrying(mon, AXE) || + (m_carrying(mon, BATTLE_AXE) && + !which_armor(mon, W_ARMS))); + } + thrudoor |= rockok || treeok; + } nexttry: /* eels prefer the water, but if there is no water nearby, they will crawl over land */ @@ -979,13 +1001,13 @@ nexttry: /* eels prefer the water, but if there is no water nearby, if(nx == x && ny == y) continue; if(IS_ROCK(ntyp = levl[nx][ny].typ) && !((flag & ALLOW_WALL) && may_passwall(nx,ny)) && - !((flag & ALLOW_DIG) && may_dig(nx,ny))) continue; + !((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx,ny))) continue; /* KMH -- Added iron bars */ if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue; if(IS_DOOR(ntyp) && !amorphous(mdat) && ((levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)) || - (levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR)) - ) && !(flag & (ALLOW_WALL|ALLOW_DIG|BUSTDOOR))) continue; + (levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))) && + !thrudoor) continue; if(nx != x && ny != y && (nodiag || #ifdef REINCARNATION ((IS_DOOR(nowtyp) && diff --git a/src/monmove.c b/src/monmove.c index 3c30c64d0..cdbf5732f 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -624,12 +624,10 @@ register int after; /* Not necessary if m_move called from this file, but necessary in * other calls of m_move (ex. leprechauns dodging) */ - can_tunnel = tunnels(ptr) && #ifdef REINCARNATION - !Is_rogue_level(&u.uz) && + if (!Is_rogue_level(&u.uz)) #endif - (!needspick(ptr) || m_carrying(mtmp, PICK_AXE) || - (m_carrying(mtmp, DWARVISH_MATTOCK) && !which_armor(mtmp, W_ARMS))); + can_tunnel = tunnels(ptr); can_open = !(nohands(ptr) || verysmall(ptr)); can_unlock = ((can_open && m_carrying(mtmp, SKELETON_KEY)) || mtmp->iswiz || is_rider(ptr)); @@ -874,13 +872,10 @@ not_special: } } - /* don't tunnel if needspick and wielding a non-pick that is known - * cursed or hostile and close enough to prefer a weapon */ + /* don't tunnel if hostile and close enough to prefer a weapon */ if (can_tunnel && needspick(ptr) && - (mw_tmp = MON_WEP(mtmp)) != 0 && !is_pick(mw_tmp) && - ((mw_tmp->cursed && mtmp->weapon_check == NO_WEAPON_WANTED) || - ((!mtmp->mpeaceful || Conflict) && - dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8))) + ((!mtmp->mpeaceful || Conflict) && + dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8)) can_tunnel = FALSE; nix = omx; @@ -955,11 +950,20 @@ not_special: if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp)) return(3); - if(IS_ROCK(levl[nix][niy].typ) && may_dig(nix,niy) && - mmoved==1 && can_tunnel && needspick(ptr) && - (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp))) { - mtmp->weapon_check = NEED_PICK_AXE; - if (mon_wield_item(mtmp)) + if (((IS_ROCK(levl[nix][niy].typ) && may_dig(nix,niy)) || + closed_door(nix, niy)) && + mmoved==1 && can_tunnel && needspick(ptr)) { + if (closed_door(nix, niy)) { + if (!(mw_tmp = MON_WEP(mtmp)) || + !is_pick(mw_tmp) || !is_axe(mw_tmp)) + mtmp->weapon_check = NEED_PICK_OR_AXE; + } else if (IS_TREE(levl[nix][niy].typ)) { + if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp)) + mtmp->weapon_check = NEED_AXE; + } else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) { + mtmp->weapon_check = NEED_PICK_AXE; + } + if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp)) return(3); } /* If ALLOW_U is set, either it's trying to attack you, or it diff --git a/src/priest.c b/src/priest.c index 22492bbf2..094f8fc2f 100644 --- a/src/priest.c +++ b/src/priest.c @@ -49,10 +49,7 @@ register xchar omx,omy,gx,gy; else allowflags = ALLOW_SSM | ALLOW_SANCT; if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL); if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK; - if (tunnels(mtmp->data) && - (!needspick(mtmp->data) || m_carrying(mtmp, PICK_AXE) || - m_carrying(mtmp, DWARVISH_MATTOCK))) - allowflags |= ALLOW_DIG; + if (tunnels(mtmp->data)) allowflags |= ALLOW_DIG; if (!nohands(mtmp->data) && !verysmall(mtmp->data)) { allowflags |= OPENDOOR; if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR; diff --git a/src/weapon.c b/src/weapon.c index a40bcb8d9..885304b8c 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -599,7 +599,23 @@ register struct monst *mon; case NEED_PICK_AXE: obj = m_carrying(mon, PICK_AXE); /* KMH -- allow other picks */ - if (!obj) obj = m_carrying(mon, DWARVISH_MATTOCK); + if (!obj && !which_armor(mon, W_ARMS)) + obj = m_carrying(mon, DWARVISH_MATTOCK); + break; + case NEED_AXE: + /* currently, only 2 types of axe */ + obj = m_carrying(mon, BATTLE_AXE); + if (!obj || which_armor(mon, W_ARMS)) + obj = m_carrying(mon, AXE); + break; + case NEED_PICK_OR_AXE: + /* prefer pick for fewer switches on most levels */ + obj = m_carrying(mon, DWARVISH_MATTOCK); + if (!obj) obj = m_carrying(mon, BATTLE_AXE); + if (!obj || which_armor(mon, W_ARMS)) { + obj = m_carrying(mon, PICK_AXE); + if (!obj) obj = m_carrying(mon, AXE); + } break; default: impossible("weapon_check %d for %s?", mon->weapon_check, mon_nam(mon));