// 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

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