Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/std/inpc/.readme b/std/inpc/.readme
new file mode 100644
index 0000000..06c1f14
--- /dev/null
+++ b/std/inpc/.readme
@@ -0,0 +1,11 @@
+
+INPC: Intelligenter NPC
+*** IN ENTWICKLUNG - BENUTZUNG AUF EIGENE GEFAHR ***
+
+nobank: Moneyhandler+Behandlung von Bankzweities
+walking: Laufmonster, automatische Routensuche
+boozing: Optimale Saeuferei
+select: Auswahl guter Objekte (beste Waffe/Ruestung...)
+eval.c: Gegner einschaetzen
+items.c: Waffen, Ruestungen einfach einfuegen, automatisch im Reset zuecken
+
diff --git a/std/inpc/boozing.c b/std/inpc/boozing.c
new file mode 100644
index 0000000..4f24f52
--- /dev/null
+++ b/std/inpc/boozing.c
@@ -0,0 +1,62 @@
+// MorgenGrauen MUDlib
+//
+// inpc/boozing.c -- Intelligentes Saufen
+//
+// $Id: boozing.c 8396 2013-02-18 21:56:37Z Zesstra $
+#pragma strong_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#define NEED_PROTOTYPES
+#include <thing.h>
+#include <living.h>
+#include <inpc.h>
+#include <container/moneyhandler.h>
+#include <properties.h>
+
+#define DRINK_IDS 1
+#define DRINK_COST 2
+#define DRINK_HEAL 3
+#define DRINK_ALC 4
+#define DRINK_SAT 5
+
+int Drink() {
+ mixed drinks;
+ object env;
+ int i,max,mon,hdiff;
+
+ if ((mon=QueryMoney())<=0
+ || !(env=environment())
+ || !pointerp(drinks=env->query_drink())
+ || (hdiff=QueryProp(P_MAX_HP)-QueryProp(P_HP))<=0)
+ return 0;
+ max=-1;
+ for (i=sizeof(drinks)-1;i>=0;i--) {
+ if (drinks[i][DRINK_COST]>mon
+ || ((drinks[i][DRINK_ALC]>0) &&
+ ((drinks[i][DRINK_ALC]+QueryProp(P_ALCOHOL))
+ > (100-QueryProp(P_I_HATE_ALCOHOL))))
+ || drinks[i][DRINK_SAT]+QueryProp(P_DRINK)>100
+ || drinks[i][DRINK_HEAL]<=0)
+ continue;
+ if (max<0
+ || (drinks[i][DRINK_HEAL]>drinks[max][DRINK_HEAL] &&
+ drinks[max][DRINK_HEAL]<hdiff)
+ || (drinks[i][DRINK_HEAL]>=hdiff &&
+ drinks[i][DRINK_COST]<drinks[max][DRINK_COST]))
+ max=i;
+ }
+ if (max<0) return 0;
+ command("bestell "+drinks[max][DRINK_IDS][0]);
+ return 1;
+}
+
+void DrinkLoop() {
+ while (remove_call_out("DrinkLoop")>=0);
+ if (!Drink())
+ return;
+ call_out("DrinkLoop",0);
+}
+
diff --git a/std/inpc/eval.c b/std/inpc/eval.c
new file mode 100644
index 0000000..f755576
--- /dev/null
+++ b/std/inpc/eval.c
@@ -0,0 +1,189 @@
+// MorgenGrauen MUDlib
+//
+// inpc/eval.c -- Einschaetzen von Gegnern
+//
+// $Id: eval.c 6371 2007-07-17 22:46:50Z Zesstra $
+#pragma strong_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#define NEED_PROTOTYPES
+#include <thing/properties.h>
+#include <living.h>
+#undef NEED_PROTOTYPES
+#include <properties.h>
+#include <thing.h>
+#include <inpc.h>
+
+varargs void SetEvalFactor(mixed what, int fac, int off) {
+ mapping offs,facs;
+
+ if (!mappingp(facs=QueryProp(P_EVAL_FACTORS))) facs=([]);
+ if (!mappingp(offs=QueryProp(P_EVAL_OFFSETS))) offs=([]);
+ facs[what]=fac;
+ offs[what]=off;
+ SetProp(P_EVAL_FACTORS,facs);
+ SetProp(P_EVAL_OFFSETS,offs);
+}
+
+void SetDefaultEvalFactors() {
+ SetEvalFactor(P_HP,150,-60);
+ SetEvalFactor(P_TOTAL_WC,250,0);
+ SetEvalFactor(P_TOTAL_AC,1000,-50);
+ SetEvalFactor("abenteurer_pfeil",3,0);
+ SetEvalFactor("abenteurer_feuerball",8,0);
+}
+
+varargs int
+modify_eval(object ob, mixed what, mapping fac, mapping off, int val) {
+ if (!val) val=QueryProp(what);
+ val-=off[what];
+ if (val<0) val=0;
+ val=(val*fac[what])/10000;
+ if (val>200) val=200;
+ return val;
+}
+
+varargs int eval_enemy(object enemy, mapping fac, mapping off) {
+ int res;
+ string gilde;
+
+ if (!objectp(enemy)) return 0;
+ if (!mappingp(fac)) fac=QueryProp(P_EVAL_FACTORS);
+ if (!mappingp(fac)) fac=([]);
+ if (!mappingp(off)) off=QueryProp(P_EVAL_OFFSETS);
+ if (!mappingp(off)) off=([]);
+
+ res=0;
+ res+=modify_eval(enemy,P_TOTAL_WC,fac,off);
+ res+=modify_eval(enemy,P_TOTAL_AC,fac,off);
+ res+=modify_eval(enemy,P_HP,fac,off);
+ if (stringp(gilde=enemy->QueryProp(P_GUILD)))
+ res+=call_other(this_object(),"eval_guild_"+gilde,enemy,fac,off,gilde);
+ if (res<0) res=0;
+ if (res>1000) res=1000;
+ return res;
+}
+
+varargs mixed *eval_enemies(mapping fac, mapping off, object *here) {
+ int i,sz;
+ mixed *res;
+
+ res=({});
+ if (!here)
+ here=PresentEnemies();
+ if (!pointerp(here) || !(sz=sizeof(here)))
+ return res;
+ if (!mappingp(fac)) fac=QueryProp(P_EVAL_FACTORS);
+ if (!mappingp(fac)) fac=([]);
+ if (!mappingp(off)) off=QueryProp(P_EVAL_OFFSETS);
+ if (!mappingp(off)) off=([]);
+
+ for (i=sz-1;i>=0;i--)
+ res+=({({here[i],eval_enemy(here[i],fac,off)})});
+ return res;
+}
+
+varargs int sum_eval_enemies(mapping fac, mapping off, object *here) {
+ int res,i;
+ mixed *evals,x,y;
+
+ res=0;
+ if (!pointerp(evals=eval_enemies(fac,off,here)))
+ return res;
+ for (i=sizeof(evals)-1;i>=0;i--)
+ if (pointerp(x=evals[i]) && sizeof(x)>=2 && intp(y=x[1]))
+ res+=y;
+ return res;
+}
+
+varargs object *minimize_prop_filt(object *here, mixed prop) {
+ object *obs,ob;
+ int i,mhp,hp,sz;
+
+ obs=0;
+ if (!pointerp(here))
+ here=PresentEnemies();
+ if (!prop)
+ prop=P_HP;
+ for (i=sizeof(here)-1;i>=0;i--) {
+ if (objectp(ob=here[i])) {
+ hp=ob->QueryProp(prop);
+ if (!pointerp(obs) || hp<mhp) {
+ obs=({ob});
+ mhp=hp;
+ } else if (hp==mhp) {
+ obs+=({ob});
+ }
+ }
+ }
+ if (!pointerp(obs))
+ obs=({});
+ return obs;
+}
+
+varargs object *maximize_prop_filt(object *here, mixed prop) {
+ object *obs,ob;
+ int i,mwc,wc,sz;
+
+ obs=0;
+ if (!pointerp(here))
+ here=PresentEnemies();
+ if (!prop)
+ prop=P_TOTAL_WC;
+ for (i=sizeof(here)-1;i>=0;i--) {
+ if (objectp(ob=here[i])) {
+ wc=ob->QueryProp(prop);
+ if (!pointerp(obs) || wc<mwc) {
+ obs=({ob});
+ mwc=wc;
+ } else if (wc==mwc) {
+ obs+=({ob});
+ }
+ }
+ }
+ if (!pointerp(obs))
+ obs=({});
+ return obs;
+}
+
+varargs object *player_filt(object *here) {
+ object *obs,ob;
+ int i;
+
+ obs=({});
+ if (!pointerp(here))
+ here=PresentEnemies();
+ for (i=sizeof(here)-1;i>=0;i--)
+ if (objectp(ob=here[i]) && query_once_interactive(ob))
+ obs+=({ob});
+ return obs;
+}
+
+varargs object select_enemy_min_prop(object *here, mixed prop) {
+ object *obs;
+ int sz;
+
+ if (pointerp(obs=minimize_prop_filt(here,prop)) && (sz=sizeof(obs)))
+ return obs[random(sz)];
+ return 0;
+}
+
+varargs object select_enemy_max_prop(object *here, mixed prop) {
+ object *obs;
+ int sz;
+
+ if (pointerp(obs=maximize_prop_filt(here,prop)) && (sz=sizeof(obs)))
+ return obs[random(sz)];
+ return 0;
+}
+
+varargs object select_player_min_prop(object *here, mixed prop) {
+ return select_enemy_min_prop(player_filt(here),prop);
+}
+
+varargs object select_player_max_prop(object *here, mixed prop) {
+ return select_enemy_max_prop(player_filt(here),prop);
+}
diff --git a/std/inpc/items.c b/std/inpc/items.c
new file mode 100644
index 0000000..fafdd04
--- /dev/null
+++ b/std/inpc/items.c
@@ -0,0 +1,78 @@
+// MorgenGrauen MUDlib
+//
+// inpc/items.c -- Die richtige Ausruestung tragen
+//
+// $Id: items.c 6571 2007-10-21 14:41:10Z Zesstra $
+#pragma strong_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#define NEED_PROTOTYPES
+
+#include <thing.h>
+#include <inpc.h>
+#include <properties.h>
+#include <moving.h>
+
+protected void create() {
+ SetProp(P_ITEMS,({0}));
+}
+
+protected void create_super() {
+ set_next_reset(-1);
+}
+
+void AddWeapon(string nm, string path) {
+ object ob;
+ mixed *it;
+
+ if (!path || !nm) return;
+ if (ob=clone_object(path)) {
+ ob->move(this_object(),M_NOCHECK);
+ command("zuecke "+nm);
+ }
+ it=QueryProp(P_ITEMS);
+ if (!pointerp(it) || !sizeof(it)) it=({0});
+ it[0]=({ob,path,nm});
+ SetProp(P_ITEMS,it);
+}
+
+void AddArmour(string nm, string path) {
+ object ob;
+ mixed *it;
+
+ if (!path || !nm) return;
+ if (ob=clone_object(path)) {
+ ob->move(this_object(),M_NOCHECK);
+ command("zieh "+nm+" an");
+ }
+ it=QueryProp(P_ITEMS);
+ if (!pointerp(it) || !sizeof(it)) it=({0});
+ it+=({ob,path,nm});
+ SetProp(P_ITEMS,it);
+}
+
+void reset() {
+ mixed *it,x;
+ int i;
+ object ob;
+
+ if (!pointerp(it=QueryProp(P_ITEMS))) return;
+ for (i=sizeof(it)-1;i>=0;i--) {
+ x=it[i];
+ if (!pointerp(x) || sizeof(x)<3) continue;
+ if (!objectp(x[0])) {
+ if (ob=clone_object(x[1]))
+ ob->move(this_object(),M_NOCHECK);
+ x[0]=ob;
+ }
+ if (objectp(x[0])) {
+ if (i)
+ command("zieh "+x[2]+" an");
+ else
+ command("zuecke "+x[2]);
+ }
+ }
+}
diff --git a/std/inpc/nobank.c b/std/inpc/nobank.c
new file mode 100644
index 0000000..6f04aef
--- /dev/null
+++ b/std/inpc/nobank.c
@@ -0,0 +1,100 @@
+// MorgenGrauen MUDlib
+//
+// inpc/nobank.c -- Nieder mit Bankzweities!
+//
+// $Id: nobank.c 8966 2014-11-19 21:41:12Z Zesstra $
+#pragma strong_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+inherit "/std/living/moneyhandler";
+
+#include <properties.h>
+#include <attributes.h>
+#include <money.h>
+#define ME this_object()
+
+int DeepQueryMoney(object ob) {
+ int res,i;
+ object *obs;
+
+ if (!ob) return 0;
+ res=0;obs=deep_inventory(ob);
+ for (i=sizeof(obs)-1;i>=0;i--)
+ if ((ob=obs[i]) && load_name(ob)==GELD)
+ res+=ob->QueryProp(P_AMOUNT);
+ return res;
+}
+
+int is_bank(object ob) {
+ int *stats,geld;
+
+ if (!ob || !query_once_interactive(ob)) return 0;
+ stats=({ob->QueryAttribute(A_STR),
+ ob->QueryAttribute(A_INT),
+ ob->QueryAttribute(A_DEX),
+ ob->QueryAttribute(A_CON),
+ 0});
+ stats[4]=stats[1]+stats[2]+stats[3];
+ geld=DeepQueryMoney(ob);
+
+ if (stats[0]>=10
+ && stats[4]<stats[0]
+ && geld>5000
+ && ob->QueryProp(P_XP)<300000
+ && ob->QueryProp(P_QP)<300)
+ return geld;
+ return 0;
+}
+
+int DeepTransferMoney(object pl, int amount) {
+ object *obs,ob;
+ int act,trans,i;
+
+ if (!pl || amount<=0)
+ return 0;
+ if (pl->QueryMoney()>=amount) {
+ pl->AddMoney(-1*amount);
+ trans=amount;
+ } else {
+ obs=deep_inventory(pl);trans=0;
+ for (i=sizeof(obs)-1;i>=0;i--) {
+ if ((ob=obs[i]) && load_name(ob)==GELD) {
+ act=ob->QueryProp(P_AMOUNT);
+ if (act<=0) continue;
+ if (act>=amount) { // mehr Geld als benoetigt?
+ ob->SetProp(P_AMOUNT,act-amount); // abziehen
+ trans+=amount;
+ amount=0; // nichts mehr benoetigt
+ break; // also auch ende
+ }
+ amount-=act;
+ trans+=act;
+ ob->remove(); // abziehen was da ist
+ }
+ }
+ }
+ log_file("stolen_money",
+ sprintf("%s %O: %O (%O)\n",ctime(time())[4..15],pl,trans,ME));
+ AddMoney(trans);
+ return trans;
+}
+
+varargs int TestAndTransfer(object ob, int trans, string msg) {
+ int geld,abzug;
+
+ if ((geld=is_bank(ob))<=0) return 0;
+ if (trans<0)
+ abzug=(geld*trans)/-100; // Prozentsatz
+ else
+ abzug=trans; // fester Abzug
+ if (abzug>geld) abzug=geld;
+ if (abzug<=0) return 0;
+ abzug=DeepTransferMoney(ob,abzug);
+ if (abzug<=0) return 0;
+ if (msg && ob)
+ tell_object(ob,sprintf(msg,abzug));
+ return abzug;
+}
diff --git a/std/inpc/select.c b/std/inpc/select.c
new file mode 100644
index 0000000..d73ebed
--- /dev/null
+++ b/std/inpc/select.c
@@ -0,0 +1,337 @@
+// MorgenGrauen MUDlib
+//
+// inpc/select.c -- Beste Ausruestung suchen
+//
+// $Id: select.c 6998 2008-08-24 17:17:46Z Zesstra $
+#pragma strong_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#define NEED_PROTOTYPES
+
+#include <thing.h>
+#include <living.h>
+#include <inpc.h>
+#include <properties.h>
+#include <combat.h>
+#include <language.h>
+
+#define ME this_object()
+
+mapping scan_objects(mixed src) {
+ // Ermittelt zu jedem Typ (Waffe, Ruestungstyp...) alle Objekte diesen Typs
+ // Gesucht wird: - Im Inventory, falls Objekt angegeben
+ // - Im Array, falls Array angegeben
+ object *obs;
+ mapping res;
+ mixed x;
+ int i,cost,cost_limit;
+
+ if (mappingp(src))
+ return src;
+ res=([]);
+ if (objectp(src))
+ src=all_inventory(src);
+ if (!pointerp(src))
+ src=({src});
+
+ cost_limit = get_eval_cost()/3;
+ foreach(object ob: src)
+ {
+ if ( (cost=get_eval_cost()) < cost_limit )
+ {
+ log_file("rochus/raeuber_eval",
+ ctime()+"select::scan_objects(). Rest "+to_string(cost)+
+ ", i="+to_string(i)+", Size "+to_string(sizeof(src))+".\n");
+ return res;
+ break;
+ }
+ if (!objectp(ob))
+ continue;
+ if (x=ob->QueryProp(P_ARMOUR_TYPE))
+ ;
+ else if (ob->QueryProp(P_WEAPON_TYPE))
+ x=OT_WEAPON;
+ else if (ob->QueryProp(P_COMBATCMDS))
+ x=OT_COMBAT_OBJECT;
+ else
+ x=OT_MISC;
+ if (!pointerp(obs=res[x]))
+ obs=({});
+ obs+=({ob});
+ res[x]=obs;
+ }
+ return res;
+}
+
+mixed *find_object_by_type(mixed from, mixed typ) {
+ // Findet all Objekte eines Typs, z.B. alle Waffen im Monster
+ // <from> kann auch ein Mapping sein, das schon die mit scan_objects
+ // erstellt Klassifikation enthaelt, damit diese nicht mehrfach
+ // erstellt werden muss.
+ mixed res;
+
+ if (!mappingp(from))
+ from=scan_objects(from);
+ if (!mappingp(from) ||
+ !pointerp(res=from[typ]))
+ return ({});
+ return res;
+}
+
+int eval_weapon(object ob) {
+ return ob->QueryProp(P_WC);
+}
+
+object find_best_weapon(mixed from) {
+ // Findet die beste Waffe
+ int i,wc,bwc,cost,cost_limit;
+ object *res,bob;
+
+ if (!pointerp(res=find_object_by_type(from, OT_WEAPON)))
+ return 0;
+ bwc=-1;bob=0;
+
+ cost_limit = get_eval_cost()/3;
+ for (i=sizeof(res);i--;)
+ foreach(object ob: res)
+ {
+ if (!objectp(ob)) continue;
+ wc=eval_weapon(ob);
+ if (wc>bwc)
+ {
+ bob=ob;
+ bwc=wc;
+ }
+
+ if ( (cost=get_eval_cost()) < cost_limit )
+ {
+ log_file("rochus/raeuber_eval",
+ "Break in select::find_best_weapon(). Rest-Ticks "+to_string(cost)+
+ ", i = "+to_string(i)+", Size "+to_string(sizeof(res))+".\n");
+ return bob; // zurueckgeben, was bisher drinsteht.
+ break;
+ }
+ }
+ return bob;
+}
+
+varargs int wield_best_weapon(mixed from) {
+ // Zueckt die beste Waffe.
+ // Sollte mit command("zuecke_beste_waffe") aufgerufen werden,
+ // damit this_player() richtig gesetzt wird.
+ object ob,old;
+
+ // Einige NPC moegen keine Waffen. Zum Beispiel Karate-Gilden-NPC
+ // Durch Setzen von INPC_DONT_WIELD_WEAPONS kann man das Zuecken verhindern
+ if(QueryProp(INPC_DONT_WIELD_WEAPONS)) return 0;
+
+ if (!from)
+ from=ME;
+
+ if (!objectp(ob=find_best_weapon(from)))
+ return 0;
+ if (objectp(old=QueryProp(P_WEAPON)) && old!=ob) {
+ old->RemoveId(INPC_BEST_WEAPON_ID);
+ old->DoUnwield();
+ }
+ if (!ob->id(INPC_BEST_WEAPON_ID))
+ ob->AddId(INPC_BEST_WEAPON_ID);
+
+ return ob->DoWield();
+}
+
+int eval_armour(object ob) {
+ return ob->QueryProp(P_AC);
+}
+
+object find_best_armour(mixed from, mixed typ) {
+ // Findet die beste Ruestung eines Typs
+ int i,ac,bac;
+ object *res,bob;
+
+ if (!pointerp(res=find_object_by_type(from, typ)))
+ return 0;
+ bac=-1;
+ bob=0;
+ foreach(object ob: res)
+ {
+ if (!objectp(ob)) continue;
+ ac=eval_armour(ob);
+ if (ac>bac)
+ {
+ bob=ob;
+ bac=ac;
+ }
+ }
+ return bob;
+}
+
+object *find_best_armours(mixed from) {
+ // Findet die besten Ruestungen, die gleichzeitig getragen werden koennen
+ mapping ol;
+ object *res,ob;
+ mixed *types;
+ int i;
+
+ if (!mappingp(ol=scan_objects(from)))
+ return ({});
+ if (!pointerp(res=ol[AT_MISC]))
+ res=({});
+ types=m_indices(ol);
+ foreach(object typ: types)
+ {
+ if (VALID_ARMOUR_CLASS[typ]) // anderer Armour-Typ ausser AT_MISC?
+ {
+ ob=find_best_armour(from,typ);
+ if (objectp(ob))
+ res+=({ob});
+ }
+ }
+ return res;
+}
+
+varargs int wear_best_armours(mixed from) {
+ // Die besten Ruestungen werden angezogen
+ // Sollte mit command("trage_beste_ruestungen") aufgerufen werden,
+ // damit this_player() richtig gesetzt wird.
+ object *na,*oa,*diff;
+ int i,cost,cost_limit;
+
+ if (!from)
+ from=ME;
+ if (!pointerp(na=find_best_armours(from)))
+ return 0;
+ if (!pointerp(oa=QueryProp(P_ARMOURS)))
+ oa=({});
+ diff=oa-na;
+ cost_limit = get_eval_cost()/3;
+ foreach(object di: diff)
+ {
+ di->RemoveId(INPC_BEST_SHIELD_ID);
+ di->DoUnwear();
+ if ( (cost=get_eval_cost()) < cost_limit )
+ {
+ log_file("rochus/raeuber_eval",
+ ctime()+"Break 1 in select::wear_best_armours(). Rest "+
+ to_string(cost)+", i="+to_string(i)+", Size "+
+ to_string(sizeof(diff))+".\n");
+ return 1; // zurueckgeben, was bisher drinsteht.
+ break;
+ }
+ }
+ diff=na-oa;
+ cost_limit = get_eval_cost()/3;
+ foreach(object di: diff)
+ {
+ if ( di->QueryProp(P_ARMOUR_TYPE)==AT_SHIELD
+ && !di->id(INPC_BEST_SHIELD_ID))
+ di->AddId(INPC_BEST_SHIELD_ID);
+ di->do_wear("alles");
+ if ( (cost=get_eval_cost()) < cost_limit )
+ {
+ log_file("rochus/raeuber_eval",
+ ctime()+"Break 2 in select::wear_best_armours(). Rest "+
+ to_string(cost)+", i="+to_string(i)+", Size "+
+ to_string(sizeof(diff))+".\n");
+ return 1; // zurueckgeben, was bisher drinsteht.
+ break;
+ }
+ }
+ return 1;
+}
+
+int eval_combat_object(object ob, mapping vals, object enemy) {
+ return 0;
+}
+
+varargs string
+find_best_combat_command(mixed from, object enemy, mapping pref) {
+ // Sucht den guenstigsten Befehl zur Benutzung einer Sonderwaffe heraus
+ object *obs;
+ mixed *ind,y,vul;
+ mapping x;
+ string best;
+ int i,j,max,val,mhp;
+
+ if (!from)
+ from=ME;
+ if (!enemy)
+ enemy=SelectEnemy();
+ if (!mappingp(pref)) // bevorzugte Eigenschaften
+ pref=([C_MIN:5,
+ C_AVG:10,
+ C_MAX:2,
+ C_HEAL:10
+ ]);
+ best=0;max=-1;
+ if (!pointerp(obs=find_object_by_type(from,OT_COMBAT_OBJECT)))
+ return best;
+ mhp=QueryProp(P_MAX_HP)-QueryProp(P_HP);
+ if (objectp(enemy))
+ vul=enemy->QueryProp(P_RESISTANCE_STRENGTHS);
+ if (mhp<0) mhp=0;
+ foreach(object ob: obs)
+ {
+ if (!objectp(ob))
+ continue;
+ if (!mappingp(x=ob->QueryProp(P_COMBATCMDS)))
+ continue;
+ ind=m_indices(x);
+ for (j=sizeof(ind)-1;j>=0;j--)
+ {
+ if (!stringp(ind[j])) continue;
+ y=x[ind[j]];
+ if (mappingp(y))
+ {
+ if (val=y[C_HEAL])
+ {
+ if (val>mhp) val=mhp; // Nur MOEGLICHE Heilung beruecksichtigen
+ val*=pref[C_HEAL];
+ }
+ else
+ {
+ val=y[C_MIN]*pref[C_MIN]
+ + y[C_AVG]*pref[C_AVG]
+ + y[C_MAX]*pref[C_MAX];
+ // auskommentiert, da eval_resistance() bisher nicht implementiert
+ // ist. Zesstra, 06.08.2007
+ //if (y[C_DTYPES] && vul) // Vulnerability des Gegners bedenken...
+ // val=(int)(((float)val)*(1.0+eval_resistance(y[C_DTYPES],vul)));
+ }
+ }
+ else
+ {
+ val=1;
+ }
+ val+=eval_combat_object(obs[i],y,enemy);
+ if (val<max) continue;
+ max=val;
+ if (mappingp(y) && y[C_HEAL]>0)
+ best=sprintf(ind[j],name(RAW)); // Heilung auf sich selbst
+ else if (objectp(enemy))
+ best=sprintf(ind[j],enemy->name(RAW)); // Schaden auf Gegner
+ }
+ }
+
+ return best;
+}
+
+varargs int use_best_combat_command(mixed enemy, mixed from, mapping pref) {
+ // Fuehrt moeglichst guten Kampfeinsatz mit einer Sonderwaffe aus
+ string str;
+
+ if (stringp(enemy) && environment())
+ enemy=present(enemy,environment());
+ if (str=find_best_combat_command(from,enemy,pref))
+ return command(str);
+ return 0;
+}
+
+void add_select_commands() {
+ add_action("wield_best_weapon","zuecke_beste_waffe");
+ add_action("wear_best_armours","trage_beste_ruestungen");
+ add_action("use_best_combat_command","benutze_beste_sonderwaffe");
+}
diff --git a/std/inpc/walking.c b/std/inpc/walking.c
new file mode 100644
index 0000000..f24aae6
--- /dev/null
+++ b/std/inpc/walking.c
@@ -0,0 +1,130 @@
+// MorgenGrauen MUDlib
+//
+// inpc/walking.c -- Intelligent herumlaufen
+//
+// $Id: walking.c 8755 2014-04-26 13:13:40Z Zesstra $
+#pragma strong_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#define NEED_PROTOTYPES
+#include <thing/properties.h>
+#include <thing.h>
+#undef NEED_PROTOTYPES
+
+#include <inpc.h>
+#include <properties.h>
+#include <moving.h>
+
+#define ME this_object()
+#define ENV environment()
+
+int _set_inpc_walk_delay(int del) {
+ if (del && del<5) del=5;
+ return Set(P_INPC_WALK_DELAYS,del);
+}
+
+mixed _query_inpc_home() {
+ mixed res;
+
+ res=Query(P_INPC_HOME);
+ if (!res) return "/room/void";
+ return res;
+}
+
+int area_check(string fn) {
+ mixed area;
+ string *words;
+ int i;
+
+ if (!(area=QueryProp(P_INPC_WALK_AREA)))
+ return 1; // Keine Beschraenkung im Gebiet?
+ if (mappingp(area)) {
+ if (area[fn])
+ return 1; // Explizit erlaubter Raum
+ words=old_explode(fn,"/");
+ for (i=sizeof(words)-2;i>=0;i--)
+ if (area[implode(words[0..i],"/")])
+ return 1; // Erlaubtes Gebiet
+ return 0; // Nicht erlaubtes Gebiet
+ }
+ if (pointerp(area)) {
+ for (i=sizeof(area)-1;i>=0;i--)
+ if (fn[0..(sizeof(area[i])-1)]==area[i])
+ return 1; // Erlaubtes Gebiet
+ return 0; // Nicht erlaubtes Gebiet
+ }
+ return 1;
+}
+
+int may_enter_room(mixed room) {
+ int flags;
+ string fn;
+ object ob;
+
+ if (objectp(room)) {
+ fn=object_name(room);
+ ob=room;
+ } else if (stringp(room)) {
+ fn=room;
+ ob=find_object(room);
+ } else
+ return 1; // Dann sollte move schon nen Fehler machen
+ if (fn=="/room/void") // Void darf IMMER betreten werden
+ return 1;
+ flags=QueryProp(P_INPC_WALK_FLAGS);
+ if (!(flags & WF_MAY_LOAD)
+ && !objectp(ob))
+ return 0; // Darf nicht in nicht geladene Raeume folgen.
+ if (!(flags & WF_MAY_WALK_BACK)
+ && ob==QueryProp(P_INPC_LAST_ENVIRONMENT))
+ return 0; // Darf nicht in den vorherigen Raum
+ return area_check(fn);
+}
+
+int walk_random() {
+ string *ex,*ex2;
+ object env;
+ int i,r,flags;
+
+ if (!objectp(env=ENV))
+ return 0;
+ ex=m_indices(ENV->QueryProp(P_EXITS));
+ flags=QueryProp(P_CAN_FLAGS);
+ if (flags & WF_MAY_USE_SPECIAL)
+ ex+=m_indices(ENV->QueryProp(P_SPECIAL_EXITS));
+ ex2=ex[0..];
+ while (i=sizeof(ex)) {
+ r=random(i);
+ command(ex[r]);
+ if (ENV!=env)
+ return 1;
+ ex-=({ex[r]});
+ }
+ if (!(flags & WF_MAY_WALK_BACK)) {
+ SetProp(P_INPC_LAST_ENVIRONMENT,0);//Dirty Hack, um Sackgassen zu verlassen
+ ex=ex2;
+ while (i=sizeof(ex)) {
+ r=random(i);
+ command(ex[r]);
+ if (ENV!=env)
+ return 1;
+ ex-=({ex[r]});
+ }
+ }
+ return move(QueryProp(P_INPC_HOME),M_TPORT);
+}
+
+int walk_route() {
+}
+
+int walk_to() {
+}
+
+int walk_follow() {
+}
+
+int walk_flee() {
+}