void Hostile_NPC_Fighter::update(World & world, map<string, shared_ptr<Character>> & actors)
{
	if (i_dont_have(C::AXE_ID) && !im_planning_to_acquire(C::AXE_ID))
	{
		plan_to_get(C::AXE_ID);
	}

	if (i_dont_have(C::SWORD_ID) && !im_planning_to_acquire(C::SWORD_ID))
	{
		plan_to_get(C::SWORD_ID);
	}

	// in this block: take the item if it's here, move to the item if it is visible and reachable,
	for (deque<Objective>::iterator objective_iterator = objectives.begin();
		objective_iterator != objectives.end();)
	{

		if (objective_iterator->verb == C::AI_OBJECTIVE_ACQUIRE)
		{
			// if the item is here, take it, remove the current objective, and return
			if (world.room_at(x, y, z)->contains_item(objective_iterator->noun))
			{
				take(objective_iterator->noun, world);

				if (objective_iterator->noun == objective_iterator->purpose)
				{
					// this item is an end goal
					erase_objectives_matching_purpose(objective_iterator->purpose); // erasing all objectives
				}
				else
				{
					// this item is a means to an end
					erase_objective(objective_iterator);
				}

				return;
			}

			// see if the item is reachable
			if (pathfind_to_closest_item(objective_iterator->noun, world))
			{
				return;
			}

			// what's the difference between the above and below block?

			/*for (int cx = x - (int)C::VIEW_DISTANCE; cx <= x + (int)C::VIEW_DISTANCE; ++cx)
			{
			for (int cy = y - (int)C::VIEW_DISTANCE; cy <= y + (int)C::VIEW_DISTANCE; ++cy)
			{
			if (!R::bounds_check(cx, cy)) { continue; } // skip if out of bounds

			if (world.room_at(cx, cy, z)->contains_item(objective_iterator->noun))
			{
			if (pathfind(cx, cy, world))
			{
			return;
			}
			}
			}
			}*/

			// a path could not be found to the item, plan to craft it if it is craftable and the NPC isn't planning to already

			// if i'm not already planning on crafting the item
			// AND the item is craftable
			if (!objective_iterator->already_planning_to_craft
				&& one_can_craft(objective_iterator->noun))
			{
				// plan to craft the item
				objective_iterator->already_planning_to_craft = true;
				plan_to_craft(objective_iterator->noun);
				objective_iterator = objectives.begin(); // obligatory reset
				continue; // jump to next iteration
			}
		}

		// if I am planning on moving to an instance 
		if (objective_iterator->verb == C::AI_OBJECTIVE_GOTO)
		{
			if (one_can_craft(objective_iterator->purpose) && i_have_all_ingredients_to_craft(objective_iterator->purpose))
			{
				if (pathfind_to_closest_item(objective_iterator->noun, world))
				{
					// delete extra objectives here
					// or maybe not; perhaps the objective should be cleared when the item is taken/crafted

					return;
				}
			}
		}

		// objectives were not modified, move to next objective
		++objective_iterator;
	}



	// the next block: work through all objectives, see which objectives can be resolved through crafting attemps.
	for (deque<Objective>::iterator objective_iterator = objectives.begin();
		objective_iterator != objectives.end(); ++objective_iterator)
	{
		// try to craft the item, using obj->purpose if the (obj->verb == GOTO), else use obj->noun (most cases)
		const string craft_attempt = craft(((objective_iterator->verb == C::AI_OBJECTIVE_GOTO) ? objective_iterator->purpose : objective_iterator->noun), world);
		if (craft_attempt.find("You now have") != string::npos)
		{
			// if successful, clear completed objectives

			if (objective_iterator->verb == C::AI_OBJECTIVE_GOTO)
			{
				// the item crafted was from a "goto" objective

				// save this because our firse erase will invalidate the iterator
				const string PURPOSE = objective_iterator->purpose;

				// erase the "goto" objective
				erase_goto_objective_matching(PURPOSE);

				// erase the "aquire" objective
				erase_acquire_objective_matching(PURPOSE);
			}
			else if (objective_iterator->noun == objective_iterator->purpose)
			{
				// this item is an end goal (no "parent" goal)
				erase_objectives_matching_purpose(objective_iterator->purpose);
			}
			else
			{
				// this item is only a means to an end
				erase_objective(objective_iterator);
			}

			return;
		}
	}

	// the next block: the NPC runs to the first player it finds IF
	// - it has completed crafting the sword and the axe and has completed all other objectives
	if (i_have(C::SWORD_ID) && i_have(C::AXE_ID) && objectives.size() == 0)
	{
		// for each row in view distance
		for (int cx = x - (int)C::VIEW_DISTANCE; cx <= x + (int)C::VIEW_DISTANCE; ++cx)
		{
			// for each room in the row in view distance
			for (int cy = y - (int)C::VIEW_DISTANCE; cy <= y + (int)C::VIEW_DISTANCE; ++cy)
			{
				// skip this room if it is out of bounds
				if (!R::bounds_check(cx, cy)) { continue; }

				// for each actor in the room
				for (const string & actor_ID : world.room_at(cx, cy, z)->get_actor_ids())
				{
					// if the character is a player character
					if (R::is<PC>(actors.find(actor_ID)->second))
					{
						// [target acquired]
						pathfind(cx, cy, world);
						return;
					}
				}
			}
		}
	}
}
Пример #2
0
int main(object me, string arg)
{
	string from, item;
	object obj, *inv, env, obj2;
	int i, amount , res;
  string msg;

	all=0;
	if (!arg) return notify_fail("你要捡起什么东西?\n");
	if (me->is_busy())
		return notify_fail("你上一个动作还没有完成!\n");
	if (sscanf(arg, "%s from %s", arg, from) == 2)
	{
	//	env = present(from, me);
	    env = i_have(me,from);
//		if (!env) env = present(from, environment(me));
		if (!env) env = i_have(environment(me),from);
		if (!env)
			return notify_fail("你找不到 "+from+" 这样东西。\n");
		if ((env->query("no_get_from") ||
			living(env) && !env->query_temp("noliving/unconcious")) 
			&& (wiz_level(me) <= wiz_level(env)))
			return notify_fail("你的巫师等级必须比对方高,才能搜身。\n");
	} else env = environment(me);

	if (sscanf(arg, "%d %s", amount, item) == 2)
	{
	//	if (!objectp(obj = present(item, env)))
		if( !objectp(obj = i_have( env,item )) ) // env have item	
			return notify_fail("这里没有这样东西。\n");
		if (!obj->query_amount())
			return notify_fail(obj->name() + "不能被分开拿走。\n");
		if (amount < 1)
			return notify_fail("东西的个数至少是一个。\n");
		if (amount > obj->query_amount())
			return notify_fail("这里没那么多的"+obj->name()+"。\n");
		else
			if(amount == (int)obj->query_amount())
				return do_get(me, obj);
			else
			{
				obj2 = new(base_name(obj));
				obj2->set_amount((int)obj->query_amount()-amount);
				obj->set_amount( amount );
				res=do_get(me, obj);
				obj2->move(env);
//				if (me->is_fighting())
//					me->start_busy(3);
				return res;
			}
	}
	if (arg=="all")
	{
		if (me->is_fighting())
			return notify_fail("你还在战斗中!只能一次拿一样。\n");
		if (!env->query_max_encumbrance())
			return notify_fail("那不是容器。\n");
   	if (env->is_tree())
   		return notify_fail("这是给新手活命用的,还是不要太贪心了吧n");
		inv = all_inventory(env);
		if (!sizeof(inv))
		{
   		if (env->is_tree())
         		return notify_fail("树上什么也没有了。\n");
			return notify_fail("那里面没有任何东西。\n");
   	}        	
    if (sizeof(inv)>=20) all=1;
		for (i = 0; i < sizeof(inv); i ++)
		{
			if (inv[i]->is_character() 
			|| inv[i]->query("no_get")
			||inv[i]->query("taskobj")
			||inv[i]->query("owner"))
				continue;
			
			do_get(me, inv[i]);
		}
    if (env->is_character())
        msg = "$N从" + env->name() + "身上搜出了一堆东西。\n";
    else
     if (env == environment(me))
        msg = "$N把地上的东西都拣了起来。\n";
     else
        msg = "$N把" + env->name() + "里面的东西都拿了出来。\n";
 
		if (all!=1)
		write("捡好了。\n");
	  else
	   message_vision(msg,me);
		return 1;
	}
//	if (!objectp(obj = present(arg, env)))
	if( !objectp(obj = i_have( env,arg )) ) // me have item	
		return notify_fail("你附近没有这样东西。\n");
	else
		if( userp(obj))
		{
			if(!obj->query_temp("noliving/unconcious") )
				return notify_fail("你附近没有这样东西。\n");
		}
		else
		{
			if(living(obj))
				return notify_fail("你附近没有这样东西。\n");
		}

	if (obj->query("no_get"))
	  if (stringp(obj->query("no_get")))
      return notify_fail(obj->query("no_get"));
    else
  		return notify_fail("这个东西拿不起来。\n");
	return do_get(me, obj);
}