예제 #1
0
/*
 * shk_move: return 1: he moved  0: he didnt  -1: let m_move do it
 */
int
shk_move(struct monst *shkp)
{
	struct monst *mtmp;
	struct permonst *mdat = shkp->data;
	xchar gx, gy, omx, omy, nx, ny, nix, niy;
	schar appr, i;
	int udist;
	int z;
	schar shkroom, chi, chcnt, cnt;
	boolean uondoor = 0, satdoor, avoid = 0, badinv;
	coord poss[9];
	int info[9];
	struct obj *ib = NULL;

	omx = shkp->mx;
	omy = shkp->my;

	if ((udist = dist(omx, omy)) < 3) {
		if (ANGRY(shkp)) {
			hitu(shkp, d(mdat->damn, mdat->damd) + 1);
			return (0);
		}
		if (ESHK(shkp)->following) {
			if (strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)) {
				pline("Hello %s! I was looking for %s.",
				      plname, ESHK(shkp)->customer);
				ESHK(shkp)->following = 0;
				return (0);
			}
			if (!ESHK(shkp)->robbed) {	/* impossible? */
				ESHK(shkp)->following = 0;
				return (0);
			}
			if (moves > followmsg + 4) {
				pline("Hello %s! Didn't you forget to pay?",
				      plname);
				followmsg = moves;
			}
			if (udist < 2)
				return (0);
		}
	}

	shkroom = inroom(omx, omy);
	appr = 1;
	gx = ESHK(shkp)->shk.x;
	gy = ESHK(shkp)->shk.y;
	satdoor = (gx == omx && gy == omy);
	if (ESHK(shkp)->following || ((z = holetime()) >= 0 && z * z <= udist)) {
		gx = u.ux;
		gy = u.uy;
		if (shkroom < 0 || shkroom != inroom(u.ux, u.uy))
			if (udist > 4)
				return (-1);	/* leave it to m_move */
	} else if (ANGRY(shkp)) {
		long saveBlind = Blind;
		Blind = 0;
		if (shkp->mcansee && !Invis && cansee(omx, omy)) {
			gx = u.ux;
			gy = u.uy;
		}
		Blind = saveBlind;
		avoid = FALSE;
	} else {
#define	GDIST(x, y)	((x - gx) * (x - gx) + (y - gy) * (y - gy))
		if (Invis)
			avoid = FALSE;
		else {
			uondoor = (u.ux == ESHK(shkp)->shd.x &&
				   u.uy == ESHK(shkp)->shd.y);
			if (uondoor) {
				if (ESHK(shkp)->billct)
					pline("Hello %s! Will you please pay before leaving?",
					    plname);
				badinv = (carrying(PICK_AXE) || carrying(ICE_BOX));
				if (satdoor && badinv)
					return (0);
				avoid = !badinv;
			} else {
				avoid = (u.uinshop && dist(gx, gy) > 8);
				badinv = FALSE;
			}

			if (((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
			    && GDIST(omx, omy) < 3) {
				if (!badinv && !online(omx, omy))
					return (0);
				if (satdoor)
					appr = gx = gy = 0;
			}
		}
	}
	if (omx == gx && omy == gy)
		return (0);
	if (shkp->mconf) {
		avoid = FALSE;
		appr = 0;
	}
	nix = omx;
	niy = omy;
	cnt = mfndpos(shkp, poss, info, ALLOW_SSM);
	if (avoid && uondoor) {	/* perhaps we cannot avoid him */
		for (i = 0; i < cnt; i++)
			if (!(info[i] & NOTONL))
				goto notonl_ok;
		avoid = FALSE;
notonl_ok:
		;
	}
	chi = -1;
	chcnt = 0;
	for (i = 0; i < cnt; i++) {
		nx = poss[i].x;
		ny = poss[i].y;
		if (levl[nx][ny].typ == ROOM
		    || shkroom != ESHK(shkp)->shoproom
		    || ESHK(shkp)->following) {
#ifdef STUPID
			/* cater for stupid compilers */
			int zz;
#endif /* STUPID */
			if (uondoor && (ib = sobj_at(ICE_BOX, nx, ny))) {
				nix = nx;
				niy = ny;
				chi = i; break;
			}
			if (avoid && (info[i] & NOTONL))
				continue;
			if ((!appr && !rn2(++chcnt)) ||
#ifdef STUPID
			    (appr && (zz = GDIST(nix, niy)) && zz > GDIST(nx, ny))
#else
			    (appr && GDIST(nx, ny) < GDIST(nix, niy))
#endif /* STUPID */
			    ) {
				nix = nx;
				niy = ny;
				chi = i;
			}
		}
	}
	if (nix != omx || niy != omy) {
		if (info[chi] & ALLOW_M) {
			mtmp = m_at(nix, niy);
			if (hitmm(shkp, mtmp) == 1 && rn2(3) &&
			    hitmm(mtmp, shkp) == 2)
				return (2);
			return (0);
		} else if (info[chi] & ALLOW_U) {
			hitu(shkp, d(mdat->damn, mdat->damd) + 1);
			return (0);
		}
		shkp->mx = nix;
		shkp->my = niy;
		pmon(shkp);
		if (ib) {
			freeobj(ib);
			mpickobj(shkp, ib);
		}
		return (1);
	}
	return (0);
}
예제 #2
0
/*
 * shk_move: return 1: he moved  0: he didnt  -1: let m_move do it
 * (what about "return 2" ???
 */
Short shk_move(monst_t *shkp)
{
  monst_t *mtmp;
  permonst_t *mdat = shkp->data;
  UChar gx,gy,omx,omy,nx,ny,nix,niy;
  Int8 appr,i;
  Short udist;
  Short z;
  Int8 shkroom,chi,chcnt,cnt;
  Boolean uondoor=false, satdoor, avoid=false, badinv;
  coord poss[9];
  Short info[9];
  obj_t *ib = NULL;

  omx = shkp->mx;
  omy = shkp->my;

  if ((udist = dist(omx,omy)) < 3) {
    if (ANGRY(shkp)) {
      hit_you(shkp, dice(mdat->damn, mdat->damd)+1);
      return 0;
    }
    if (ESHK(shkp)->following) {
      if (StrNCompare(ESHK(shkp)->customer, plname, PL_NSIZ)) {
	StrPrintF(ScratchBuffer, "Hello %s! I was looking for %s.",
		  plname, ESHK(shkp)->customer);
	message(ScratchBuffer);
	ESHK(shkp)->following = false;
	return 0;
      }
      if (!ESHK(shkp)->robbed) {	/* impossible? */
	ESHK(shkp)->following = false;
	return 0;
      }
      if (moves > followmsg+4) {
	StrPrintF(ScratchBuffer, "Hello %s! Didn't you forget to pay?",
		  plname);
	message(ScratchBuffer);
	followmsg = moves;
      }
      if (udist < 2)
	return 0;
    }
  }

  shkroom = inroom(omx,omy);
  appr = 1;
  gx = ESHK(shkp)->shk.x;
  gy = ESHK(shkp)->shk.y;
  satdoor = (gx == omx && gy == omy);
  if (ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){
    gx = you.ux;
    gy = you.uy;
    if (shkroom < 0 || shkroom != inroom(you.ux,you.uy))
      if (udist > 4)
	return -1;	/* leave it to m_move */
  } else if (ANGRY(shkp)) {
    Long saveBlind = Blind;
    Blind = 0;
    if ((shkp->mcansee_and_blinded & M_CAN_SEE) && !Invis && cansee(omx,omy)) {
      gx = you.ux;
      gy = you.uy;
    }
    Blind = saveBlind;
    avoid = false;
  } else {
#define	GDIST(x,y)	((x-gx)*(x-gx)+(y-gy)*(y-gy))
    if (Invis)
      avoid = false;
    else {
      uondoor = (you.ux == ESHK(shkp)->shd.x &&
		 you.uy == ESHK(shkp)->shd.y);
      if (uondoor) {
	if (ESHK(shkp)->billct) {
	  StrPrintF(ScratchBuffer,
		    "Hello %s! Will you please pay before leaving?", plname);
	  message(ScratchBuffer);
	}
	badinv = (carrying(PICK_AXE) || carrying(ICE_BOX));
	if (satdoor && badinv)
	  return 0;
	avoid = !badinv;
      } else {
	avoid = (you.uinshop && dist(gx,gy) > 8);
	badinv = false;
      }

      if (((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
	  && GDIST(omx,omy) < 3) {
	if (!badinv && !online(omx,omy))
	  return 0;
	if (satdoor)
	  appr = gx = gy = 0;
      }
    }
  }
  if (omx == gx && omy == gy)
    return 0;
  if (shkp->bitflags & M_IS_CONFUSED) {
    avoid = false;
    appr = 0;
  }
  nix = omx;
  niy = omy;
  cnt = mfindpos(shkp,poss,info,ALLOW_SSM);
  if (avoid && uondoor) {		/* perhaps we cannot avoid him */
    for (i=0; i<cnt; i++)
      if (!(info[i] & NOTONL)) goto notonl_ok;
    avoid = false;
  notonl_ok:
    ;
  }
  chi = -1;
  chcnt = 0;
  for (i = 0 ; i < cnt ; i++) {
    nx = poss[i].x;
    ny = poss[i].y;
    if (get_cell_type(floor_info[nx][ny]) == ROOM
	|| shkroom != ESHK(shkp)->shoproom
	|| ESHK(shkp)->following) {
#ifdef STUPID
      /* cater for stupid compilers */
      Short zz;
#endif STUPID
      if (uondoor && (ib = sobj_at(ICE_BOX, nx, ny))) {
	nix = nx; niy = ny; chi = i; break;
      }
      if (avoid && (info[i] & NOTONL))
	continue;
      if ((!appr && !rund(++chcnt)) ||
#ifdef STUPID
	  (appr && (zz = GDIST(nix,niy)) && zz > GDIST(nx,ny))
#else
	  (appr && GDIST(nx,ny) < GDIST(nix,niy))
#endif STUPID
	  ) {
	nix = nx;
	niy = ny;
	chi = i;
      }
    }
  }
  if (nix != omx || niy != omy) {
    if (info[chi] & ALLOW_M){
      mtmp = mon_at(nix,niy);
      if (hitmm(shkp,mtmp) == 1 && rund(3) &&
	  hitmm(mtmp,shkp) == 2) return 2;
      return 0;
    } else if (info[chi] & ALLOW_U){
      hit_you(shkp, dice(mdat->damn, mdat->damd)+1);
      return 0;
    }
    shkp->mx = nix;
    shkp->my = niy;
    pmon(shkp);
    if (ib) {
      unlink_obj(ib);//freeobj
      mpickobj(shkp, ib);
    }
    return 1;
  }
  return 0;
}