Added public files
Roughly added all public files. Probably missed some, though.
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");
+}