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; } } } } } }
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); }