/* To jest obiekt zakonu...
 	Odnosi sie do niego przez PRAWA
 	Zabezpieczenia robimy w integerach... bit 1 moze, bit 0 nie.
 	tutaj sprawdzamy jaka kto ma range, jaki wiek...
*/

#pragma no_clone

#include "mith.h" //sciezki
#include "ryc_zak.h"		// plik ze wszystkimi definicjami, prawami 
				// itp. Wszystkie obiekty zakonu go includuja
				// i dzieki temu _powinnismy_ uniknac roznego
				// nazwenictwa etc.

inherit "/d/Imperium/std/room";

#define PRAWO 0
#define RANGA 1
#define WIEK 2


mapping spis=([]);
string *kapitula=({0,0,0,0});
mapping zabite_npce=([]);
string *usunieci=({});

int sprawdz_prawa(int numer_pokoju, mixed komu);

create_imperium_room()
{
	setuid();
	seteuid(getuid());
	restore_object(ENGINE+"zakon");
}

/*
 * Zapisujemy wartosci przed usunieciem obiektu
 */
remove_object()
{
	rm(ENGINE + "zakon.o");
	save_object(ENGINE+"zakon");
	::remove_object();
}

zniszcz()
{
	destruct();
}

/*
 * Argumenty:	urzad - numer urzedu wg prawa.h
 * Zwraca:	imie urzednika, albo zero jesli stanowisko jest 
 			wolne ( teoretycznie niemozliwe )
 */

string
query_urzednik(int urzad)
{
	return kapitula[urzad];
}

/*
 * Argmuenty:	urzednik - imie gracza w mianowniku
 * Zwraca: 	numer urzedu wg prawa.h
 */

int
query_urzad(string urzednik)
{
	return member_array(urzednik,kapitula);
}
	
	
/*
 * Argmunety: urzednik - imie urzednika do usuniecia
 * Usuwa podanego urzednika z kapituly. UWAGA: nie zabiera mu praw 
 * ( nalezy sprawdzic kod pod tym katem ).
 */
usun_z_kapituly(string urzednik)
{
	int n=member_array(urzednik,kapitula);
// Stara wersja:	if (n!=-1) kapitula[n]=-1; 
// Poprawilem:
	if (n!=-1) kapitula[n]=0; 			
}

/* 
 * Argumenty: imie - imie nowego mistrza w mianowniku
 * Ustawia nowego mistrza. UWAGA: nie daje mu zadnych dodatkowych praw.
 */
set_mistrz(string imie)
{
	kapitula[MISTRZ]=imie;
}

/*
 * Zwraca aktualnego mistrza. 
 */
 
string
query_mistrz()
{
	return kapitula[MISTRZ];
}

/*
 * Zwraca aktualna kapitule zakonu, bez podzialu na stanowiska. 
 * UWAGA: najprawdopodobniej zwraca mistrza dwa razy.
 */

string *
query_kapitula()
{
   string *kap=kapitula;
   
   kap = filter(kap,stringp);
   
   return kap;
}


/*
 * Usuwa z mappingu spis wszystkich wizow i nieistniejacych graczy.
 */
 
czystka()
{
   string *imiona=m_indexes(spis);
   int i=0;
   
   while (i<sizeof(imiona))
      {
         if (!stringp(imiona[i])||(SECURE->query_wiz_rank(imiona[i]))||
         			  (!SECURE->exist_player(imiona[i]))) 
            {
               spis = m_delete(spis,imiona[i]);
               imiona=m_indexes(spis);
               i=0;
            }
         else i++;
      }
}

/* 
 * Argumenty: imie - imie gracza, ktorego zapis ma zostac skasowany.
 * Kasuje wzynaczonego gracza z mappingu, zerujac jego prawa. 
 */
 
kasuj_imie(string imie)
{
   string *imiona=m_indexes(spis);
   
   if (member_array(imie,imiona)==-1) return;
   
   spis = m_delete(spis, imie);
}

/*
 * Argumenty: 	zapis - integer z calkowita liczba praw gracza.
 * 		numer - numer bita wg prawa.h
 * Zwraca 1, jesli w zapisie ustawiony jest bit numer.
 */
 

int 
test_bit(int zapis, int numer)
{
	int tmp;
	tmp=zapis>>numer-1; // liczba, ktorej ostatni bit zawiera szukana wartosc;
	return !(tmp/2*2==tmp); // zwraca 0 dla parzystych, 1 dla nieparzystych.
}

/*
 * Argumenty: 	zapis - integer z calkowita liczba praw gracza.
 * 		numer - numer bita wg prawa.h
 * Zwraca zapis z dodanym bitem numer.
 */

int 
set_bit(int zapis, int numer)
{
	if (test_bit(zapis,numer)) return zapis; // jesli juz jest, to nie zmienia;
	return zapis + ftoi(pow(2.0,itof(numer-1))); // dodaje odpowiednia lcizbe.
}


/*
 * Argumenty: 	zapis - integer z calkowita liczba praw gracza.
 * 		numer - numer bita wg prawa.h
 * Zwraca zapis z usunietym bitem numer.
 */

int 
clear_bit(int zapis, int numer)
{
	if (!test_bit(zapis,numer)) return zapis; // jesli nie ma, to nie zmienia
	return zapis-ftoi(pow(2.0,itof(numer-1))); // odejmuje odpowiednia liczbe.
	
}
	
/*
 * Argumenty: komu - imie lub odnosnik do obiektu gracza do zarejestrowania.
 * Jesli gracz nie ma wlasnego pola w spisie, jest ono tworzone i ustawiany 
 * odpowiedni wiek.
 */
	
rejestruj(mixed komu)
{
	string imie = stringp(komu) ? komu : komu->query_real_name();
	mixed *tabl=allocate(3);
	
//	if (SECURE->query_wiz_rank(imie)) return;
/*	
 * Mithandir: wykomentowalem te linie. Nie ma powodu, dla ktorego wizowie
 * mieli by byc tutaj specjalnie szykanowani. Trzeba zrobic zabezpieczenie,
 * zeby niepotrzebnych osob ( tych z zerowymi prawami ) nie zapisywal.
 */
	
	if (member_array(imie,m_indices(spis))==-1)
		spis[imie]=tabl;
	if (!spis[imie][WIEK]) 
		spis[imie][WIEK]=find_player(imie)->query_age();
}

/*
 * Argumenty:	 numer - numer prawa do dodania wg prawa.h
 * 		 komu - imie lub odnosnik do obiektu gracza
 * Dodaje graczowi odpowiednie prawo.
 *	
 */



dodaj_prawa(int numer, mixed komu)
{
	string imie = stringp(komu) ? komu : komu->query_real_name();
	int tmp;
	rejestruj(imie);
	tmp=spis[imie][PRAWO];
	if (test_bit(tmp, numer)) return;
        spis[imie][PRAWO] = set_bit(tmp, numer);
        return spis[imie][PRAWO];
}


/* 
 * Argumenty: numery - tablica z numerami praw do dodania
 	      komu - gracz ktoremu chcemy dodac prawa
 * Jak dodaj_prawa, ale dodaje wiele praw naraz.
 */


	}
}

/*
 * Argumenty:	 numer - numer prawa do sprawdzenia wg prawa.h
 * 		 komu - imie lub odnosnik do obiektu gracza
 * Prawdziwe, jesli gracz ma odpowiednie prawo.
 *	
 */

int
sprawdz_prawa(int numer, mixed komu)
{
	string imie = stringp(komu) ? komu : komu->query_real_name();
//	if (find_player(imie)->query_guild_name_occ()!=GUILD_NAME && !find_player(imie)->query_wiz_level()) return 0;
/*
 * Mithandir: To wydaje sie byc niepotrzebne i nie do przyjecia w nowym systemie praw.
 */

	if (find_player(imie)->query_wiz_level()) return 1;

//	rejestruj(imie);

	if (!spis[imie]) return 0;
/*
 * Mithandir: Wykomentowalem te linie. Powinno teraz jesli kogos nie ma w
 * spisie zwracac brak prawa. Nie ma sensu rejestrwac przy sprawdzaniu,
 * nalezy to robic tylko przy dodawaniu.
 */
	return (test_bit(spis[imie][PRAWO], numer));
}

/*
 * Argumenty:	 numer - numer prawa do usniecia wg prawa.h
 * 		 komu - imie lub odnosnik do obiektu gracza
 * Usuwa graczowi odpowiednie prawo.
 *	
 */
 
usun_prawa(int numer, mixed komu)
{
	string imie = stringp(komu) ? komu : komu->query_real_name();
	int tmp;
//	rejestruj(imie);

/* 
 * Mithandir: Ta linie tez wykomentowalem, z powodow jak wyzej. 
 */
	if (!spis[imie]) return 0;
	tmp = spis[imie][PRAWO];
	if (!test_bit(tmp, numer)) return;
	if (numer==CZLONEK_RADY) usun_z_kapituly(imie);
	if (spis[imie][PRAWO]==0)
		kasuj_imie(imie);
		// Usuwamy osoby, ktore nie maja zadnego prawa.
	return spis[imie][PRAWO] = clear_bit(tmp, numer);
}

/*
 * Argumenty: imie - imie gracz do sprawdzenia.
 * Zwraca 1, jesli gracz jest bratem zakonnym.
 */

// Mithandir: zmieniam. Stara wersja:    return (spis[imie][PRAWO]>1);

int
query_rycerz(string imie)
{
   return sprawdz_prawa(PRAWA_RYCERZA, imie);
}



/*
 * Zwraca imiona wszystkich braci zakonnych.
 */
 
string *
query_rycerze()
{
   string *imiona=m_indexes(spis);
   imiona=filter(imiona,stringp);
   imiona=filter(imiona,query_rycerz);
   
   return imiona;
}

/*
 * Argumenty: imie - imie gracza do sprawdzenia.
 * Prawdziwe, jesli gracz ma tylko prawo sluzebngo. W obecnej sytuacji
 * oznacza to, ze jest sluzebnym i nie jest rycerzem. Nalezy zmienic przed
 * reforma systemu praw.
 */
int
query_sluzebny(string imie)
{
   return (spis[imie][PRAWO] && !query_rycerz(imie));
}

/* 
 * Zwraca imiona wszystkich braci sluzebnych.
 */

string *
query_sluzebni()
{
   string *imiona=m_indexes(spis);
   imiona=filter(imiona,stringp);   
   imiona=filter(imiona,query_sluzebny);
   
   return imiona;
}

/*
 * Argumenty: komu - imie lub odnosnik do obiektu gracza, ktorego range 
 * chcesz sprawdzic.
 * Zwraca range zakonna gracza. UWAGA: rangi dotycza dopiero braci zakonnych, 
 * bracia sluzebni maja range 0.
 */

int
query_ranga(mixed komu)
{	
	string imie = stringp(komu) ? komu : komu->query_real_name();
	rejestruj(imie);
	if (query_urzad(imie)>-1) return 9;
	return spis[imie][RANGA];
}

/*
 * Argumenty: komu - imie lub odnosnik do obiektu gracza, ktorego range
 * 			chcesz ustawic.
 *	      jaka - Jaka range chcesz ustawic. Jesli podasz -1, lub nie 
 *	      		podasz zadnej gracz zostanie po prostu awansowany 
 *	      		o jeden poziom.
 * Ustawia graczowi podana range. Jesli jest ona wieksza niz maksymalna
 * dostepna dla tego gracza, ustawiona zostanie maksymalna.
 */

int
set_ranga(mixed komu, int jaka=-1)
{
	string imie = stringp(komu) ? komu : komu->query_real_name();
	rejestruj(imie);
	komu=find_player(imie);
	(jaka==-1) ? spis[imie][RANGA]++ : (spis[imie][RANGA]=jaka);
	if (spis[imie][RANGA]>komu->query_guild_rank_occ())
	{
		return spis[imie][RANGA]=komu->query_guild_rank_occ();
	}
	return spis[imie][RANGA];
}

/*
 * Argumenty: komu - imie lub odnosnik do obiektu gracza ktorego wiek chcesz 
 *			sprawdzic.
 * Zwraca czas, jaki gracz spedzil w gildii ( przyrost wieku gracza od
 * wstapienia do gildii )
 */

int
query_wiek(mixed komu)
{
	 string imie = stringp(komu) ? komu : komu->query_real_name();
	 rejestruj(imie);
	 return find_player(imie)->query_age()-spis[imie][WIEK];
}

/* 
 * Argumenty: imie - imie brata.
 * Ta funkcja ustawia standardowe prawa brata sluzebnego. 
 */
dodaj_prawa_brata_sluzebnego(string imie)
{
	dodaj_wiele_praw(({	PRAWA_BRATA, 
				BIBLIOTEKA_SLUZEBNI,
				PIETRO_ZAMKU,
				ZBROJOWNIA}), imie);
}

/* 
 * Argumenty: imie - imie rycerza.
 * Ta funkcja ustawia standardowe prawa brata zakonnego. 
 */

dodaj_prawa_brata_zakonnego(string imie)
{
	dodaj_wiele_praw(	({PRAWA_RYCERZA, 
				BIBLIOTEKA_SLUZEBNI,
				DRUGIE_PIETRO,
				SKRZYNIA}),imie);
	dodaj_prawa_brata_sluzebnego(imie);
}

/*
 * Argumenty: 	urzednik - imie gracza, ktorego chcesz mianowac.
 *		urzad - na jaki urzad chcesz go mianowac.
 * Funkcja ustawia wszystkie potrzebne prawa. UWAGA: nie sprawdza, czy 
 * stanowisko juz jest zajete. Nalezy wiec wczesniej sprawdzic to samemu, i 
 * odpowiednia osobe usunac.
 */

string
mianuj(string urzednik, int urzad)
{
	kapitula[urzad]=urzednik;
	switch(urzad)
	{
		case MISTRZ:
			dodaj_prawa(BLOGOSLAWIENIE_NA_BRATA_ZAKONNEGO, urzednik);
                        dodaj_prawa(OTWIERANIE_SKRZYNI, urzednik);
                        dodaj_prawa(WIELKI_MISTRZ, urzednik);
                        break;
                case MARSZALEK:
                        dodaj_prawa(BLOGOSLAWIENIE_NA_BRATA_SLUZEBNEGO, urzednik);
                        break;
		case SZATNY:
			break;
	}
        dodaj_prawa(GLOSOWANIE_NA_MISTRZA, urzednik);
        dodaj_prawa(PODANIA, urzednik);
        dodaj_prawa(CZLONEK_RADY, urzednik);
        dodaj_prawa(POKOJ_RADY, urzednik);
	dodaj_prawa_brata_zakonnego(urzednik);
                                                                                                                               
}	


/*
 * Argumenty: kto - obiekt gracza, ktory zabil.
  	      kogo - obiekt zabitego npca.
 * Zapisuje w tablicy, ze gracz zabil dobrego npca.
 */
 

notify_zabil_npca(object kto, object kogo)
{
	 string imie = stringp(kto) ? kto : kto->query_real_name();
	 (zabite_npce[imie]) ? (zabite_npce[imie]+=({MASTER_OB(kogo)})) :
	 	 (zabite_npce[imie]=({MASTER_OB(kogo)}));
}

/*
 * Argumenty: kto - imie lub odnosnik do obiektu gracza.
 * Zwraca tablice master_obiektow npcow, ktorych zabil gracz.
 */

string *
query_zabite_npce(mixed kto)
{
    string imie = stringp(kto) ? kto : kto->query_real_name();
	return zabite_npce[imie];
}

/*
 * Argumenty: kto - imie lub odnosnik do obiektu gracza.
 * Usuwa gracza z zakonu, jesli jest on w grze. 
 * W przeciwnym razi zapisuje go do specjalnej tablicy.
 */

usun(mixed str)
{
	object kogo=((objectp(str))?(str):(find_player(str)));
	str=kogo->query_real_name();
	if (kogo)
	{
		if (kogo->wyrzucmy_go(kogo))
		{	
			spis=m_delete(spis,str);
			kogo->catch_msg("Zostales usuniety z grona Braci Zakonnych Zakonu Rycerskiego Sigmara Mlotodzierzcy.\n");
			write_file(LOG,C(str)+" usuniety. "+ctime(time())+"\n");
		}
		else
		{
			write_file(LOG,C(str)+" nie moze zostac usuniety.\n"+ctime(time())+"\n");
			kogo->catch_msg("Wystapil powazny blad. Zglos sie do Wielkiego Mistrza.\n");
		}			
	}
	else
	{
		usunieci+=({str});
	}
}

/*
 * Argumenty: imie - imie gracza, ktorego chcemy sprawdzic, czy ma byc usuniety.
 * Funkcja sprawdza, czy gracz jest na liscie osob do usuniecia, i jesli tak to
 * go usuwa
 */
  
int
trzeba_usunac(string imie)
{
	if (member_array(imie, usunieci)==-1) return 0;
	usunieci-=({imie});
	usun(imie);
	usunieci-=({imie});
	return 1;
}	

pokaz(string kogo)
{
	write(spis[kogo][PRAWO]);
}


/*
 * Tymczasowa funkcja, aktualizujaca prawa do znowelizowanego systemu.
 */
aktualizuj_prawa(string imie)
{
	if (sprawdz_prawa(PRAWA_RYCERZA, imie))
		dodaj_prawa_brata_zakonnego(imie);
	if (sprawdz_prawa(PRAWA_BRATA, imie))
		dodaj_prawa_brata_sluzebnego(imie);
	if (query_urzad(imie)>-1) mianuj (imie, query_urzad(imie));
	return;
}

/*
 * Funkcja uruchamia w odniesieniu do this_player() wszystkie funkcje, 
 * ktore z jakichs powodow powinny byc uruchomione tuz po zalogowaniu gracza.
 */

aktualne()
{
	string imie=TP->query_real_name();
	trzeba_usunac(imie);
	aktualizuj_prawa(imie);
}	