inherit "/d/Imperium/std/zol_imp";

#include "std_imp.h"
#include <pl.h>
#include <macros.h>
#include <composite.h>

#define GW_LOG "/d/Imperium/private/gwardia.log"

string * sciezka=({});
mixed *odejscie=({}); /* mixed * bo glupi compilator nie wierzy w moja madrosc */
mapping str_podwl=([]);
object * obj_podwl=({});
string start_loc, patrol_loc;
float delay=15.0;
int patrol_alarm,where_patrol,is_patrol_stopped,al_gone=0;


nomask void wykonaj_ruch(int ktory);
nomask void start_patrol();
nomask void add_podwladny(string file, int ile=1);
nomask void set_start_loc(string loc);
nomask void set_sciezka(string * sc);

loguj(string co)
{
   seteuid("silvy");
   write_file(GW_LOG, ctime(time()) + " : " + co + "\n");
}

string pom_nazwy(mixed obs,int przyp=0)
{
   int i;
   string *tmp=({});
   
   if (objectp(obs)) obs=({obs});
   if (!pointerp(obs)) return "";
   
   for (i=0;i<sizeof(obs);i++)
       {
          tmp+=interactive(obs[i])?({obs[i]->query_name(przyp)}):
          		({obs[i]->query_nonmet_name(przyp)});
       }
   
   return COMPOSITE_WORDS(tmp);
}

public void
create_dowodca_patrolu()
{
   ustaw_nazwe(({ "oficer", "oficera", "oficerowi", "oficera", "oficerem",
       "oficerze" }), ({ "oficerowie", "oficerow", "oficerom", "oficerow",
       "oficerami", "oficerach" }), PL_MESKI_OS);
   set_stats(({90,90,90,90,90,90}));
   
   ustaw_shorty(({ "oficer", "oficera", "oficerowi", "oficera",
       "oficerem", "oficerze" }), ({ "oficerowie", "oficerow", "oficerom",
       "oficerow", "oficerami", "oficerach" }), PL_MESKI_OS);
   
   ustaw_odmiane_rasy(PL_CZLOWIEK);
   add_podwladny("/d/Imperium/tigr/patrol_podwl",6);
   set_start_loc("/d/Imperium/tigr/pustkowia/lokacje/lokacja");
   set_sciezka( ({"w","se","ne","nw","n","s","s"}) );
}

nomask int
is_here(object ob)
{
   return environment(ob)==ENTO;
}

nomask object *
filter_here(object * arr)
{
   return filter(arr,is_here);
}

nomask void
stop_patrol()
{
   if (get_alarm(patrol_alarm))
      {
         remove_alarm(patrol_alarm);
         patrol_alarm=0; 
         patrol_loc=file_name(ENTO);
      }
   is_patrol_stopped=1;
}

nomask void
continue_patrol()
{
   if (sizeof(get_alarm(patrol_alarm))||query_attack()||query_follow()) 
      return;
   patrol_alarm=set_alarm(delay/3.0,0.0,&wykonaj_ruch(where_patrol));
   is_patrol_stopped=0;
   odejscie=({});
}

/* Sprawdza, czy mozemy wrocic do patrolowania i robi to gdy mozemy.
   Zwraca 1 gdy zaczynamy powrot do patrolowania i 0 wpp. */

private nomask mixed
square_to_line(mixed * arr)
{
   int i;
   mixed tmp=({});
   
   for (i=0;i<sizeof(arr);i++)
       {
          if (!pointerp(arr[i])) return 0;
          tmp+=arr[i];
       }
   return tmp;
}

private mixed *
obetnij_ostatnie(mixed * arr, int ile=1)
{
   mixed * tmp=allocate(sizeof(arr)-ile);
   int i;
   
   for (i=0;i<sizeof(tmp);i++) tmp[i]=arr[i];
   
   return tmp;
}

nomask void
return_to_patrol_loc()
{
   int nr=sizeof(odejscie);
   
   if (file_name(ENTO)==patrol_loc||nr==0) continue_patrol();
   else {
           command(odejscie[nr-1]);
           odejscie=obetnij_ostatnie(odejscie);
           set_alarm(1.0,0.0,&return_to_patrol_loc());
        }
}

nomask int
return_to_patrol(object dead_enemy=0)
{
   object *nasi=obj_podwl+({TO});
   object *enems=filter_here(square_to_line(nasi->query_enemy(-1)));
      
   if (objectp(dead_enemy)) 
      { 
        seteuid("silvy");
        write_file("/d/Imperium/tigr/gwa.log", ctime(time()) + " : " +
        	MASTER_OB(dead_enemy) + "\n");
        if (enems && pointerp(enems) && sizeof(enems))
        	enems -= ({dead_enemy});
      }
   
   if (sizeof(enems))
      return 0;
   
   set_alarm(2.0,0.0,&return_to_patrol_loc());
   
   is_patrol_stopped=2; //Patrol zaczyna wracac do zadania
   
   return 1;
}

nomask void
create_zolnierz()
{
    set_random_adj(1);
    create_dowodca_patrolu();
    set_follow_enemy(1);
    
    set_whimpy(60);
    
    set_alarm(1.0,0.0,&start_patrol());    
}

private nomask int
czy_nie_ranny(object kto)
{
   int hp=kto->query_hp(),
       hp_max=kto->query_max_hp(),
       whimp=kto->query_whimpy();
   if (!hp_max) return 0;
   return (itof(hp)/itof(hp_max))*100.0>itof(whimp);
}

private nomask object
szukaj_nie_rannego(object *arr)
{
   object *tmp=filter(arr,czy_nie_ranny);
   int i=sizeof(tmp);
   
   if (!i) return 0;
   i=random(i);
   return tmp[i];
}

nomask void
rozkaz_zaslonic(object kogo)
{
   object zasl=szukaj_nie_rannego(obj_podwl-({kogo}));
   object *enems=filter_here(kogo->query_enemy(-1));
   
   if (!sizeof(enems)||!objectp(zasl)) return;
   
   enems->attack_object(zasl);
   
   tell_room(ENTO, "Na rozkaz " + QIMIE(TO, PL_DOP) + " " +
   	QIMIE(zasl,PL_MIA) + " rzuca sie zaslonic " + QIMIE(kogo, PL_BIE) + 
   	" przed ciosami " + COMPOSITE_LIVE(enems,PL_DOP) + ".\n",
   	   enems+({kogo})+obj_podwl+({TO}));
   enems->catch_msg(QCIMIE(zasl,PL_MIA) + " zaslania " + QIMIE(kogo, PL_BIE) +
   	" przed twoimi ciosami.\n");
}

public void
run_away()
{
   rozkaz_zaslonic(TO);   
}

nomask void
start_patrol()
{
   string *files=m_indexes(str_podwl);
   int i,j;
   object pom;
   
   for (i=0;i<sizeof(files);i++)
       for (j=0;j<str_podwl[files[i]];j++)
           {
             pom=clone_object(files[i]);
             obj_podwl+=({pom});
             team_join(pom);
           }
   
   obj_podwl->szykuj();
   obj_podwl->set_my_leader(TO);
   obj_podwl->move(ENTO, 1);
   
   if (sizeof(sciezka)&&!patrol_alarm) patrol_alarm=set_alarm(5.0,0.0,&wykonaj_ruch(0));
   
   is_patrol_stopped=0;
}

nomask void
wykonaj_ruch(int ktory)
{
   if (ktory<sizeof(sciezka)) command(check_call(sciezka[ktory]));
   
   if (++ktory>sizeof(sciezka)-1) ktory=0;
   patrol_alarm=set_alarm(delay,0.0,&wykonaj_ruch(ktory));
   where_patrol=ktory;
}

nomask void
set_sciezka(string * sc)
{
   sciezka=sc;
}  

nomask void
set_start_loc(string loc)
{
   start_loc=loc;
}

nomask void
add_podwladny(string file, int ile=1)
{
   str_podwl[file]=ile;
}

nomask void
set_delay(mixed jaka)
{
   if (floatp(jaka))  { delay=jaka; return; }
   if (intp(jaka))  {delay=itof(jaka); return; }
   return;
}

nomask void
patrol_attack(object kogo)
{
   object *pom=obj_podwl+({TO});
   
   if (!living(kogo)||ENTO!=environment(kogo)) return;
   
   pom->patrol_hook_attacks(kogo);
   
   //command("powiedz Atakuje " + kogo->query_nonmet_name(PL_DOP));
   
   pom->attack_object(kogo);
}

public void
patrol_hook_attacks(object kogo)
{
   kogo->catch_msg(capitalize(TO->short(kogo,PL_MIA)) + " atakuje cie!\n");
   tell_room(ENTO, QCIMIE(TO,PL_MIA) + " atakuje " + QIMIE(kogo, PL_BIE) + 
   ".\n",kogo);
}

public void
patrol_hook_zaslania(object kogo, object * przed_kim)
{
   int i;
   object *nasi=obj_podwl+({TO});
   object *widzowie=filter(INV(ENTO),living);
   widzowie-=(przed_kim+( ({kogo})+( nasi )));
   
   kogo->catch_msg(capitalize(FO_COMPOSITE_LIVE(nasi,kogo,PL_MIA)) + 
   	" wlaczaja sie do walki, zaslaniajac ciebie przed ciosami " +
   	FO_COMPOSITE_LIVE(przed_kim,kogo,PL_DOP) + ".\n");

   for (i=0;i<sizeof(widzowie);i++)
       {
          widzowie[i]->catch_msg(
            capitalize(FO_COMPOSITE_LIVE(nasi,widzowie[i],PL_MIA)) +
            " wlaczaja sie do walki, zaslaniajac " + 
            kogo->short(widzowie[i],PL_BIE) + " przed ciosami " + 
            FO_COMPOSITE_LIVE(przed_kim,widzowie[i],PL_DOP) + ".\n");
       }
   
   for (i=0;i<sizeof(nasi);i++)
       {
          nasi[i]->catch_msg(
            "Wlaczasz sie do walki, zaslaniajac " +
            kogo->short(nasi[i],PL_BIE) + " przed ciosami " +
            FO_COMPOSITE_LIVE(przed_kim,nasi[i],PL_DOP) + ".\n");
       }
   
   for (i=0;i<sizeof(przed_kim);i++)
       {
          przed_kim[i]->catch_msg(
            capitalize(FO_COMPOSITE_LIVE(nasi,przed_kim[i],PL_MIA)) +
            " wlaczaja sie do walki, zaslaniajac " + 
            kogo->short(przed_kim[i],PL_BIE) + " przed twoimi ciosami.\n"); 
       }
}

nomask void
patrol_zaslon(object kogo, object *przed_kim)
{
   object *pom=obj_podwl+({TO});
   object *pom2=filter_here(kogo->query_enemy(-1));
   
   przed_kim-=pom2;
   
   pom2+=przed_kim;
   
   if (!living(kogo)||ENTO!=environment(kogo)||!sizeof(pom2)) return;
   
   patrol_hook_zaslania(kogo, pom2);
   
   pom2->stop_fight(kogo);
   pom2->attack_object(TO);
   pom->attack_object(pom2[0]);
   
   filter(przed_kim,interactive)->add_prop(IMPERIUM_I_BIJE_W_MIESCIE);
   
   loguj("Patrol zaatakowal " + pom_nazwy(przed_kim,3) + " zaslaniajac " +
   	kogo->query_nonmet_name(3)+ ".");
}

nomask void
patrol_assist(object kogo)
{
   object *pom=(obj_podwl+({TO}));
   object pom2=kogo->query_attack();
   int i;
   
   pom-=({kogo});
   if (!living(kogo)||ENTO!=environment(kogo)||
       !living(pom2)||ENTO!=environment(pom2)) return;
   
   for (i=0;i<sizeof(pom);i++)
       {
          if (pom[i]->query_attack()!=pom2)
             {
                pom[i]->patrol_hook_attacks(pom2);
                pom[i]->attack_object(pom2);
             }
       }
   
   loguj ("Patrol zaatakowal " + pom_nazwy(pom2,3) +".");
}

/* public void
aggressive_attack()
{
   ::aggressive_attack();
   
   
}
*/

public void
attack_object(object ob)
{
   stop_patrol();
   ::attack_object(ob);
   patrol_assist(TO);
}

public void
attacked_by(object ob)
{
   stop_patrol();
   ::attacked_by(ob);
   patrol_assist(TO);
}

loguj_zabicie(object dead)
{
   loguj("Patrol zabil " + pom_nazwy(dead,3) + ".");
}

public void
notify_you_killed_me(object dead)
{
   if (return_to_patrol(dead))
      {
         if (!dead->query_prop(IMPERIUM_I_STWOR_CHAOSU))
            command("emote oglasza: Przestepca zostal ukarany!");
         else
            command("emote oglasza: Kolejny pomiot chaosu dostal za swoje!");
      }
   loguj_zabicie(dead);
   
   ::notify_you_killed_me(dead);
}

public void
patrol_hook_enemy_gone(object enemy)
{
   command("emote drapie sie po szyi.");
   command("machnij");
   command("powiedz Wracamy do patrolowania.");
}

nomask void
enemy_gone(object loc, object enemy)
{
   if (objectp(enemy))
   {
    if (ENTO!=loc) return;
    if (query_attack()) return;
    if (!present(enemy,ENTO)||!CAN_SEE(TO,enemy)) return;
   }
   
   if (return_to_patrol())
      patrol_hook_enemy_gone(enemy);
}

public void
notify_enemy_gone(object enemy)
{
   if (!sizeof(get_alarm(al_gone)))
      al_gone=set_alarm(3.0,0.0,&enemy_gone(ENTO, enemy));
}

void
enter_env(object dest, object old)
{
   int pom;
   
   if (is_patrol_stopped==1)
      {
         pom=member_array(file_name(old),dest->query_exit_rooms());
         if (pom<0) pom=member_array(file_name(old)+".c",dest->query_exit_rooms());
         if (pom>-1)
            odejscie+=({dest->query_exit_cmds()[pom]});
      }
}

void
unset_follow()
{
   notify_enemy_gone(query_follow());
   ::unset_follow();
}

public int
query_have_random_adj()
{
   return 1;
}