/*
* Standardowy maper obslugujacy mape.
* by Tanis - maj 1999 ( na podstawie WIELU poprzednich wersji) ;))
*
* Opis :
*  Obiekt jest standardowym maperem, konfigurowalnym w funkcji
*   create_imperium_maper() wywolywanej w obiekcie dziedziczacym ten plik.
* 
* Moze obslugiwac zarowno losowa mape, jak i stala. Zalezy od tego, czy na
*  mapie sa wyjscia losowe czy nie.
*
* Legenda mapy
*  | - / \ X  <- istniejace wyjscia ( wylosowane w trakcie pracy progamu, 
*                            badz na stale wpisane do mapy). Odpowiednio :
*                            pionowe, pozionowe, 2 po skosie i "skrzyzowanie",
*                            ale bez mozliwosci zmiany trasy. ( Skrzyzowane wyjscia )
*    * <- wyjscia pionowe/poziome ( w zaleznosci od pozycji na mapie ) 
*                 do wylosowania.
*    a <- wyjscie typu X do wylosowania
*    b <- wyjscie /, do wylosowania
*    c <- wyjscie \, do wylosowania
*    d <- wyjscie typu X, w tym / istniejace, a \ do wylosowania.
*    e <- wyjscie typu X, w tym \ istniejace, a / do wylosowania.
*    n <- brak przejscia
*    p <- brak lokacji /puste/
*    numery <- numer lokacji ( nazwa pliku, tworzona ze stalej POCZATEK + numer + .c
*                               np. lok123.c)
*
*   Maper zwraca tablice wyjsc poprze wywolanie w nim funkcji string *konfiguruj_wyjscia(int numer_lokacji);
*    --> obejrzyj przyklad wykorzystania mapera.
*  Kazda linia, na ktorej poczatku bedzie znak # bedzie pominieta /jako komentarz/
*
*                                  Tanis
*   UWAGA !! Elementy na mapie /wyjscia,lokacje/ musza byc oddzielone min. 1 spacja /moze byc tych spacji wiecej, ale min 1/
*        Dotyczy to tez barku lokacji jak i barku wyjscia.
*        Oprocz tego w numerach lokacji NIE moze byc ani jeden spacji - dla liczby 123 to nie moze wygladac w ten sposob: 1 23
*           / Nie wiem, kto tak pisze, ale na wszelki wypadek... ;-)/
*/

#pragma no_clone

inherit "/std/object.c";

#include <files.h>

#include "maper.h"
#include "forma.h"

#define KIERUNKI ({"polnocny-zachod","polnoc","polnocny-wschod", \
                   "wschod","poludniowy-wschod","poludnie", \
                   "poludniowy-zachod","zachod"})

/*
 * Glowne zmienne ("srodowisko" - ale madra nazwa ;-)) ) mapera.
 * Ustawia je sie wywolaniami z funkcji create_imperium_maper()
 *  wewnatrz obiektu dziedziczacego.
 * UWAGA ! Tam sie wlasnie ustawia wszystko, co jest szczegolne
 *  dla danego mapera - mape, sciezki, nazwy plikow itd.
 */

/*
 * Tablica przechowujaca odnosniki do obiektow przechowujacych dane.
 * Kazdy taki obiekt przechowuje tablice wielkosci mapy.
 * Indeksy tablicy 'dane' wskazuja na obiekty przechowujace rozne
 *  dane:
 *  0 - Mapa, zaznaczone wyjscia i numery lokacji.
 *  1 - Tablica 1 wymiarowa, w ktorej dla kazdej lokacji zwracana jest
 *       podtablica z numerami typow opisow dla niej. Tyle numerow ile
 *       segmentow opisu, poczynajac od komorki 1. Komorka 0 - typ shorta.
 *  2 - Tablica 1 wymiarowa, numer komorki to numer odpowiadajacej lokacji.
 *      Jesli w danej komorce jest obiekt, to jest to obiekt wirtualnej
 *       lokacji ktorego mozna uzyc. Jesli -1, to znaczy ze nalezy uzyc pliku,
 *       jesli 0 to lokacja jest do sprawdzenia (czy plik czy wirtualna),
 *       jesli 1 to nalezy uzyc wirtualnej ktora nie jest po prostu aktualnie
 *       sklonowana.
 *  3 - Tablica podobna do poprzedniej, pod numerami lokacji sa podtablice
 *       z konfiguracja lokacji. Kazda taka podtablica to: /0-wartosc domyslna/
 *          0 - zmeczenie stosowane przy wychodzeniu z tej lokacji
 *          1 - czy lokacja, jsli zostanie pusta to ma byc usuwana (0-tak, 1-nie)
 *          2 - czy dlugi opis ma byc przelosowywany za kazdym razem (0-nie, 1-tak)
 *          3 - czy short ma byc przeladowywany za kazdym razem (0-nie, 1-tak)
 *               / za kazdym razem = przy kazdym ladowaniu lokacji wirtualnej/
 *       UWAGA: Tyczy sie to tez lokacji nie-wirtualnych, wiec jesli chcemy zeby
 *         jakas nie wirtualna byla zupelnie zwyczajna, musimy odpoweidnio ustawic opcje.
 *        /czyli na ({x,0,0,0}) - x=zmeczenie, czyli w praktyce wystarczy tylko ({x}) /
 *  4 - Tablica podobna do poprzedniej, dla danej lokacji zwracana jest tablica
 *      Kolejne komorki tablicy - wylosowane numery opisow danego typu opisow kolejnych segmentow.
 *  5+ - Od 5 wzwyz to obiekty przechowujace kolejne segmenty opisu.
 *        Tu numer 5 odpowiada numerowi 0 z tablicy segmentow (zwracanych
 *         przez poprzedni obiekt (4).
 * Uwaga: Dla 4 indeks 0 dotyczy shorta a nie longa :)
 *        Tak samo 5 to short, a dopiero 6+ to longi
 *
 */
private object *dane=({});

private string poczatek_nazw_plikow=STD_POCZATEK; // Poczatek nazw plikow
                                                  // np. las123.c
                                                  // tutaj poczatkiem jest "las"
private int ile_wyjsc_obcinamy=STD_OBCINAMY; // Ilos wyjsc, ktore ma miec lokacja = 8 - OBCINAMY
                                             // Pod warunkiem, ze wyjscia nie zostaly juz wczesniej wylosowane, czyli usuwa tylko te do wylosowania jeszcze 
private string tytul_mapy=STD_TYTUL; // Tytul mapy, widoczny przy jej wyswietlaniu
private string sciezka_do_lokacji=STD_PATH; // Sciezka do lokacji danego terenu.
private string lokacja_wirtualna=STD_WIRTUAL; // Lokacja klonowana kazdorazowo przy lokac. wirtualnych
private int czy_widac_wyjscia=0; // 0 -widac, 1 - nie widac
 
/*
 * Koniec 'srodowiska' mapera.
 */

int query_czy_widac_wyjscia()
{
    return czy_widac_wyjscia;
}

string query_poczatek_nazw_plikow()
{
    return poczatek_nazw_plikow;
}    

int query_ile_wyjsc_obcinamy()
{
    return ile_wyjsc_obcinamy;
}

string query_tytul_mapy()
{
    return tytul_mapy;
}

string query_sciezka_do_lokacji()
{
    return sciezka_do_lokacji;
}

string query_lokacja_wirtualna()
{
    return lokacja_wirtualna;
}

mixed *query_all_dane(int numer)
{
    if(numer<sizeof(dane)) return dane[numer]->zwroc_all();
    else return ({});
}

mixed *query_dane(int numer, int dana)
{
   if(numer<sizeof(dane)) return dane[numer]->zwroc(dana);
   else return ({});
}

/*
 * Funkcja sprawdza czy obiekt o numerze 'numer' istnieje, jesli nie to tworzy go.
 * Dba tez o to, aby tablica zawsze byla wlasciwa, tj. jesli chcemy ustawic 10 element
 *  a tablica ma tylko 2, to funkcja brakujace 8 utworzy, wstawiajac tam zera
 *  (i numer 10 ustawi na nowopowstaly obiekt)
 */
 
void
sprawdz_dane(int numer)
{
   int a;
   
   if(numer>=(sizeof(dane)-1)) for(a=sizeof(dane);a<(numer+1);a++) dane+=({0});
    
   if(!objectp(dane[numer])) dane[numer]=clone_object(MAPER_DANA);
}    

void
ustaw_shorty(mixed *shorty)
{
    sprawdz_dane(5);
    dane[5]->ustaw_all(shorty);
}

void
ustaw_opisy(int ktory, mixed *opisy)
{
     if(ktory<1) return;
     ktory+=5;
     sprawdz_dane(ktory);
     dane[ktory]->ustaw_all(opisy);
}
 
void
ustaw_konfiguracje_opisow(mixed *konf)
{
    sprawdz_dane(1);
    dane[1]->ustaw_all(konf); 
}

/*
 * Funkcja ktora przyjmuje konfiguracje dla kazdej lokacji.
 * Indeks w tej tablicy - numer lokacji.
 *  Szczegoly - komentarz na poczatku (nie chce mi sie 2 raz psiac...)
 */
void
ustaw_konfiguracje_lokacji(mixed *konf)
{
   int a,b;
   
   b=sizeof(konf);
   
   for(a=0;a<b;a++)
   {
    konf[a]=konf[a]+({0,0,0,0});
    konf[a]=konf[a][0..3];
   }
   
   sprawdz_dane(3);
   dane[3]->ustaw_all(konf);
}
/*
 * Wczytuje plik z mapa i przerzuca owa mape do tablicy.
 *  Wywolujemy przy konfiguracji, z zewnatrz, na samiutkim poczatku :)
 */

void
wczytaj_mape(string sciezkam)
{
	string plik;
        string *tab1=({});
        int a,b;
        mixed *mapa=({ ({}) });

        setuid(); seteuid(getuid());

        if(!(file_size(sciezkam)>0)) sciezkam=STD_MAPA;

        plik=read_file(sciezkam);
        
        tab1=explode(plik,"\n")-({""});

        b=sizeof(tab1);

        for(a=0;a<b;a++)
           {
                if(tab1[a][0]!='#') mapa+=({ (explode(tab1[a]," ")-({""})) });
           }

        b=sizeof(mapa);
    
     for(a=0;a<b;a++)
     if(sizeof(mapa[a])==0) mapa[a]=-99;
     mapa=mapa-({-99}); // Wywalamy wszystkie puste pod-tablice (czasami powstaja...)
/*
 * DEBUGER !!!!!!
     for(a=0;a<sizeof(mapa);a++)
     {
         for(b=0;b<sizeof(mapa[a]);b++)
         {
         	write(mapa[a][b]);
         }
         write("\n");
     }
*/
    sprawdz_dane(0);
    dane[0]->ustaw_all(mapa);
}

/*
 * Funkcje ustawiajace wartosci zmiennych 'srodowiskowych'
 * Te zmienne sa 'private', wiec mozemy je obrabiac tylko z tego obiektu.
 */

void set_lokacja_wirtualna(string lok)
{
    lokacja_wirtualna=lok;
}

void set_czy_widac_wyjscia(int czy)
{
    czy_widac_wyjscia=czy;
}

void set_poczatek_nazw_plikow(string s)
{
    poczatek_nazw_plikow=s;
}    

void set_ile_wyjsc_obcinamy(int i)
{
    ile_wyjsc_obcinamy=i;
}

void set_tytul_mapy(string tytul)
{
    tytul_mapy=tytul;
}

void set_sciezka_do_lokacji(string path)
{
    sciezka_do_lokacji=path;
}

/*
 * Kod MAPERA
 */

void
losuj_opisy(int numer_lokacji)
{
    int *tab1,*tab2;
    int a,b;
    
    if(!dane[4]) dane[4]=clone_object(MAPER_DANA);
    
    tab1=dane[4]->zwroc(numer_lokacji); // Opisy wylosowane
    tab2=dane[1]->zwroc(numer_lokacji); // Opisy przyporzadkowane (typy)

    if(!tab1) tab1=({});

// DEBUG    write("Numer lokacji(losuj_opis):"+numer_lokacji+"\n");
        
    if((sizeof(tab1)==sizeof(tab2)) && member_array(-1,tab1)==-1) return;
    // Mamy wystarczajaca liczbe wylosowanych opisow, i zaden z wylosowanych to nie -1.
    
    if((sizeof(dane)-5)>sizeof(tab2)) b=(sizeof(tab2)-sizeof(tab1));
    else b=((sizeof(dane)-5)-sizeof(tab1));
    
    for(a=sizeof(tab1);a<b;a++) tab1+=({-1});
    
    b=sizeof(tab1);

    for(a=0;a<b;a++) if(tab1[a]==-1) tab1[a]=random(sizeof(dane[a+5]->zwroc(tab2[a])));
    
    dane[4]->ustaw(numer_lokacji,tab1);       
}

/*
 * Funkcja usuwa koncowke stringa, jesli to jest spacja albo znak konca linii (\n)
 * 
 */
string
usun_koncowki(string napis1)
{
    string napis2;
    
    if(napis1[(strlen(napis1)-1)]==' ' || napis1[(strlen(napis1)-1)] == '\n') napis2=napis1[0..(strlen(napis1)-2)];
    else napis2=napis1;

    napis1=napis2;

    if(napis1[(strlen(napis1)-1)]==' ' || napis1[(strlen(napis1)-1)] == '\n') napis2=napis1[0..(strlen(napis1)-2)];
    else napis2=napis1;
    
// To jest 2 razy, jakby ktos dodal i spacje i \n (pojedyncza operacja usuwa ostatni znak, jesli to spacja albo \n
//      a podwojna radzi sobie rowniez jesli to jest ' \n')

    return napis2;
}

string
zwroc_dlugi_opis(int numer_lokacji)
{
    string opis="";
    int a,b;

    sprawdz_dane(5);        
        
    losuj_opisy(numer_lokacji);
    
    b=sizeof(dane[4]->zwroc(numer_lokacji));
    
    for(a=1;a<b;a++)
    {
        sprawdz_dane(a+5);
        // Ech... coz za potworek ;))
        opis+=usun_koncowki(((dane[a+5]->zwroc((dane[1]->zwroc(numer_lokacji))[a]))[(dane[4]->zwroc(numer_lokacji))[a]])[0]);
        opis+=" ";
    }
    
    opis+="\b\n";
    
    return zmien_forme(opis,this_player());
}

string
zwroc_shorta(int numer_lokacji)
{
    string opis;
    
    losuj_opisy(numer_lokacji);

    sprawdz_dane(5);
    
    opis=(dane[5]->zwroc((dane[1]->zwroc(numer_lokacji))[0]))[(dane[4]->zwroc(numer_lokacji))[0]];
    
    return opis;
}

mixed *zwroc_liste_itemow(int numer_lokacji)
{
    mixed *tab=({});
    int a,b;
        
    losuj_opisy(numer_lokacji);
    
    sprawdz_dane(5);
    
    b=sizeof(dane[4]->zwroc(numer_lokacji));
    
    for(a=1;a<b;a++)
    {
        sprawdz_dane(a+5);
        // Ech... potworne:
        tab+=((dane[a+5]->zwroc((dane[1]->zwroc(numer_lokacji))[a]))[(dane[4]->zwroc(numer_lokacji))[a]])[1];
    }

    return tab;
}

void
usun_lokacje(int numer_lokacji)
{
    int *tab=dane[3]->zwroc(numer_lokacji);
    int czy_plik;
    mixed lokacja;
    string plik;
    int *opisiki=({});
    
    if(tab[1]==1) return; //Jesli tam jest 0 to nie usuwamy lokacji.
	
	lokacja=dane[2]->zwroc(numer_lokacji);
	if(lokacja==-1 || lokacja==0 || lokacja==(-1)) return; // To lokacja prawdziwa albo cos sie z... ;)

	
    if(tab[2]==1)
    {
        opisiki=({dane[4]->zwroc_xy(numer_lokacji,0),-1});
        dane[4]->ustaw(numer_lokacji,opisiki);
    }
    if(tab[3]==1)
    {
        opisiki=dane[4]->zwroc(numer_lokacji);
        opisiki[0]=-1;
        dane[4]->ustaw(numer_lokacji,opisiki);
    }
    
    plik=(explode(lokacja->nazwa_pliku_lokacji(),"#"))[0];
    
    if(plik==lokacja_wirtualna || plik+".c"==lokacja_wirtualna || plik==lokacja_wirtualna+".c") czy_plik=1; //To lokacja wirtualna!
    else czy_plik=-1; //To plik!

    lokacja->remove_object();
    dane[2]->ustaw(numer_lokacji,czy_plik);
}

int
zwroc_zmeczenie(int numer_lokacji)
{
    return (dane[3]->zwroc(numer_lokacji))[0];
}

void
create_imperium_maper()
{
}

void
create_object()
{
    add_name("_imperialny_maper_tanisa_");
    add_pname("_imperialny_maper_tanisa_");
    
    create_imperium_maper();
}

/*
 * Funkcja zwraca liczbe wyjsc, ktore istnieja lub MOGA istniec /te losowe/.
 * Czyli 8-liczba_kierunkow_w_ktorych_nie_ma_wyjscia.
 */
 
int
policz_wyjscia(string *tabliczka)
{

   int a,b=0; 

   for(a=0;a<8;a++)
      {
       switch(tabliczka[a])
           {
              case "-" :
              case "X" :
              case "d" :
              case "e" :
              case "a" :
              case "*" :
              case "|" : b++;
                         break;
              case "/" : if(a == 2 || a == 6) b++;
                         break;
              case "\\" : if(a == 0 || a == 4) b++;
                         break;
              case "b" : if(a == 2 || a == 6) b++;
                         break;
              case "c" : if(a == 0 || a == 4) b++;
                         break;
            }
      }
 return b;             
}

/*
 * Funkcja, ktora usuwa podana liczbe wyjsc /sposrod wyjsc do wylosowania,
 *      nie usuwa wyjsc juz wlaczanych badz stalych./
 * Dla wyjsc o kodzie 'a', 'd' i 'e' usuwa wyjscia prowadzace
 * OD tej lokacji, a nie od np. dwoch sasiednich.
 * Brzmi skomplikowanie, ale znaczy to tyle :
 * Np. Jesli na pln-wsch od nas jest wyjscie typu 'a'
 *      czyli mozliwe przejscie pln-wsch<->pld-zach i pln-zach<->pld-wsch
 *      to nie usuwa tego pln-zach<->pld-wsch tylko to drugie.
 * Podobnie w przypadku 'd' i 'e' -> tam jeden skos jest istniejacy,
 * wylosowany, i trzeba usunac tylko ten drugi.
 */      

string
*odejmij_wyjscia(string *tabliczka,int ile)
{
 int ile_mozliwych;
 int a,b,c;
 string s;

for(c=0;c<ile;c++)
{
 ile_mozliwych=0;
 for(a=0;a<8;a++)
    {
     s=tabliczka[a];     
     if(s=="*" || s=="a" || ((s=="b" || s=="e") && (a==2 || a==6)) || ((s=="c" || s=="d") && (a==4 || a ==0))) ile_mozliwych++;
    }
 if(!ile_mozliwych) b=0;
 else b=random(ile_mozliwych)+1;

 a=-1;
 while(b>0)
    {
     a++;
     s=tabliczka[a];
     if(s=="*" || s=="a" || ((s=="b" || s=="e") && (a==2 || a==6)) || ((s=="c" || s=="d") && (a==4 || a ==0))) b--;
    }
  if(a > -1)
   {
    switch(tabliczka[a])
         {
           case "d": tabliczka[a]="/";
                     break;
           case "e": tabliczka[a]="\\";
                     break;
           case "a": if(a==0 || a==4) tabliczka[a]="b";
                     else tabliczka[a]="c";
                     break;
           default : tabliczka[a]="n";
                     break;
         }
    }
}

return tabliczka;
}

/*
 * Zamienia pozostale /po procesie usuwania/ wyjscia do wylosowania na wyjscia wylosowane.
 */

string
*uaktywnij_wyjscia(string *tabliczka)
{
 int a;
 string s;

for(a=0;a<8;a++)
{
 switch(tabliczka[a])
         {
           case "*": if(a==1 || a==5) tabliczka[a]="|";
                     else tabliczka[a]="-";
                     break;
           case "b": tabliczka[a]="/";
                     break;
           case "c": tabliczka[a]="\\";
                     break;
           case "a": if(a==0 || a==4) tabliczka[a]="e";
                     else tabliczka[a]="d";
                     break;
           case "d": if(a==0 || a==4) tabliczka[a]="X";
                     break;
           case "e": if(a==2 || a==6) tabliczka[a]="X";
                     break;
         }
    }

return tabliczka;
}

/*
 * Dla lokacji o adresie x,y na mapie wczytuje tablice z 8 wyjsciami.
 * tablica[0] - wyjscie na pln-zach,
 * tablica[1] - wyjscie na pln,
 *  ...
 * tablica[7] - wyjscie na zach.
 */

string
*wczytaj_mapke(int x, int y)
{
  int a;

  string *tablica_wyjsc=allocate(8);

//  find_player("tanis")->catch_msg("X: "+x+", Y:"+y+"\n"); //DEBUGER !!!

  for(a=0;a<8;a++)
      {
        switch(a)
            {
                case 0 : if((x-1) < 0 || (y-1) < 0) tablica_wyjsc[a] = "E";
                         else tablica_wyjsc[a] = (dane[0]->zwroc(y-1))[x-1];
                         break;
                case 1 : if( (y-1) < 0 ) tablica_wyjsc[a] = "E";
                         else tablica_wyjsc[a] = (dane[0]->zwroc(y-1))[x];
                         break;
                case 2 : if( (y-1) < 0 || (x+1) > (dane[0]->wielkosc_x(0)-1) ) tablica_wyjsc[a] = "E";
                         else tablica_wyjsc[a] = (dane[0]->zwroc(y-1))[x+1];
                         break;
                case 3 : if( (x+1) > (dane[0]->wielkosc_x(0)-1) ) tablica_wyjsc[a] = "E";
                         else tablica_wyjsc[a] = (dane[0]->zwroc(y))[x+1];
                         break;
                case 4 : if( (y+1) > (dane[0]->wielkosc()-1) || (x+1) > (dane[0]->wielkosc_x(0)-1) ) tablica_wyjsc[a] = "E";
                         else tablica_wyjsc[a] = (dane[0]->zwroc(y+1))[x+1];
                         break;
                case 5 : if( (y+1) > (dane[0]->wielkosc()-1) ) tablica_wyjsc[a] = "E";
                         else tablica_wyjsc[a] = (dane[0]->zwroc(y+1))[x];
                         break;
                case 6 : if( (y+1) > (dane[0]->wielkosc()-1) || (x-1) < 0) tablica_wyjsc[a] = "E";
                         else tablica_wyjsc[a] = (dane[0]->zwroc(y+1))[x-1];
                         break;
                case 7 : if( (x-1) < 0 ) tablica_wyjsc[a] = "E";
                         else tablica_wyjsc[a] = (dane[0]->zwroc(y))[x-1];
                         break;
                default : break;
            }
       }

return tablica_wyjsc;
}

/*
 * Zmienia duza mape wedlug tablicy z okolicznami dla danej lokacji wyjsciami.
 * Tzn. np. usuwa te wyjscia na duzej mapie, ktore usunelismy sobie w okolicy tej lokacji.
 */

void
odswiez_mape(string *tabliczka, int x, int y)
{
   int a;

  for(a=0;a<8;a++)
      {
       switch(a)
           {
            case 0: if(!((x-1) < 0 || (y-1) < 0)) dane[0]->ustaw_xy(y-1,x-1,tabliczka[a]);
                    break;
            case 1: if(!( (y-1) < 0 )) dane[0]->ustaw_xy(y-1,x,tabliczka[a]);
                    break;
            case 2: if(!( (y-1) < 0 || (x+1) > (dane[0]->wielkosc_x(0)-1) )) dane[0]->ustaw_xy(y-1,x+1,tabliczka[a]);
                    break;
            case 3: if(!( (x+1) > (dane[0]->wielkosc_x(0)-1) )) dane[0]->ustaw_xy(y,x+1,tabliczka[a]);
                    break;
            case 4: if(!( (y+1) > (dane[0]->wielkosc()-1) || (x+1) > (dane[0]->wielkosc_x(0)-1) )) dane[0]->ustaw_xy(y+1,x+1,tabliczka[a]);
                    break;
            case 5: if(!( (y+1) > (dane[0]->wielkosc()-1) )) dane[0]->ustaw_xy(y+1,x,tabliczka[a]);
                    break;
            case 6: if(!( (y+1) > (dane[0]->wielkosc()-1) || (x-1) < 0)) dane[0]->ustaw_xy(y+1,x-1,tabliczka[a]);
                    break;
            case 7: if(!( (x-1) < 0 )) dane[0]->ustaw_xy(y,x-1,tabliczka[a]);
                    break;
           }
      }
}

/*
 * Zmienia kierunki wyjsc na numery lokacji, DO ktorych owe wyjscia prowadza.
 */
int
*znajdz_docelowe(string *tabliczka,int x, int y)
{
 int a;
 string s;
 int *numery=allocate(8);

 for(a=0;a<8;a++)
    {
     s=tabliczka[a];

     switch(a)
       {
         case 0 : if(s=="\\" || s=="X" || s=="e") tabliczka[a] = (dane[0]->zwroc(y-2))[x-2];
                  else tabliczka[a]="0";
                  break;
         case 1 : if(s=="|") tabliczka[a] = (dane[0]->zwroc(y-2))[x];
                  else tabliczka[a]="0";
                  break;
         case 2 : if(s=="/" || s=="X" || s=="d") tabliczka[a] = (dane[0]->zwroc(y-2))[x+2];
                  else tabliczka[a]="0";
                  break;
         case 3 : if(s=="-") tabliczka[a] = (dane[0]->zwroc(y))[x+2];
                  else tabliczka[a]="0";
                  break;
         case 4 : if(s=="\\" || s=="X" || s=="e") tabliczka[a] = (dane[0]->zwroc(y+2))[x+2];
                  else tabliczka[a]="0";
                  break;
         case 5 : if(s=="|") tabliczka[a] = (dane[0]->zwroc(y+2))[x];
                  else tabliczka[a]="0";
                  break;
         case 6 : if(s=="/" || s=="X" || s=="d") tabliczka[a] = (dane[0]->zwroc(y+2))[x-2];
                  else tabliczka[a]="0";
                  break;
         case 7 : if(s=="-") tabliczka[a] = (dane[0]->zwroc(y))[x-2];
                  else tabliczka[a]="0";
                  break;       
       }
     }

   for(a=0;a<8;a++)
       {
         s=tabliczka[a];

         if(s=="p" || s=="0") tabliczka[a]="0";
         
         numery[a]=atoi(tabliczka[a]);
       }

return numery;
}

/*
 * Funkcja zwraca tablice z lista wyjsc (polnoc, poludnie,..)
 */
string
*konwertuj(string *tabliczka,int x, int y)
{
 int a;
 string s;

 for(a=0;a<8;a++)
    {
     s=tabliczka[a];

     switch(a)
       {
         case 0 : if(s=="\\" || s=="X" || s=="e") tabliczka[a] = (dane[0]->zwroc(y-2))[x-2];
                  else tabliczka[a]="0";
                  break;
         case 1 : if(s=="|") tabliczka[a] = (dane[0]->zwroc(y-2))[x];
                  else tabliczka[a]="0";
                  break;
         case 2 : if(s=="/" || s=="X" || s=="d") tabliczka[a] = (dane[0]->zwroc(y-2))[x+2];
                  else tabliczka[a]="0";
                  break;
         case 3 : if(s=="-") tabliczka[a] = (dane[0]->zwroc(y))[x+2];
                  else tabliczka[a]="0";
                  break;
         case 4 : if(s=="\\" || s=="X" || s=="e") tabliczka[a] = (dane[0]->zwroc(y+2))[x+2];
                  else tabliczka[a]="0";
                  break;
         case 5 : if(s=="|") tabliczka[a] = (dane[0]->zwroc(y+2))[x];
                  else tabliczka[a]="0";
                  break;
         case 6 : if(s=="/" || s=="X" || s=="d") tabliczka[a] = (dane[0]->zwroc(y+2))[x-2];
                  else tabliczka[a]="0";
                  break;
         case 7 : if(s=="-") tabliczka[a] = (dane[0]->zwroc(y))[x-2];
                  else tabliczka[a]="0";
                  break;       
       }
     }

   for(a=0;a<8;a++)
       {
         s=tabliczka[a];

         if(s=="p" || s=="0") tabliczka[a]="0";
       }
       
    for(a=0;a<8;a++) if(tabliczka[a]!="0") tabliczka[a]=KIERUNKI[a];

return tabliczka;
}

/*
 * Szuka wspolrzednych na mapie dla lokacji o podanym numerze.
 */ 
int *znajdz_wspolrzedne(int numer_lokacji)
{
  int x,y;
  
  for(y=0;y<(dane[0]->wielkosc());y++)
     for(x=0;x<(dane[0]->wielkosc_x(y));x++)
         if((dane[0]->zwroc(y))[x]==""+numer_lokacji) return ({x,y});
  return ({-1,-1});
}

/*
 * Glowna funkcja, przyjmujaca numer lokacji a zwracajaca tablice lista wyjsc (polnoc,wschod,...)
 */
string
*zwroc_liste_wyjsc(int numer_lokacji)
{
   int a,b;
   int x,y;
   int *wspolrzedne;
   string *tablica_wyjsc=allocate(8);

   wspolrzedne=znajdz_wspolrzedne(numer_lokacji);

   x=wspolrzedne[0];
   y=wspolrzedne[1];      

   if(x==-1 || y==-1)
     {
         write("Podany numer lokacji nie istnieje na mapie !\n");
         return tablica_wyjsc;
     }

   tablica_wyjsc=wczytaj_mapke(x,y);
 
   a = policz_wyjscia(tablica_wyjsc);

   if((a + ile_wyjsc_obcinamy) > 8) tablica_wyjsc=odejmij_wyjscia(tablica_wyjsc,(a + ile_wyjsc_obcinamy - 8));
 
   tablica_wyjsc=uaktywnij_wyjscia(tablica_wyjsc);

   odswiez_mape(tablica_wyjsc,x,y);

   return konwertuj(tablica_wyjsc,x,y);   
}

/*
 * Zwraca liste wszystkich plikow wymienionych na mapie.
 */

string *zwroc_liste_plikow()
{
  int x,y;
  string *tablica=({});
  string s;
  
  for(y=0;y<(dane[0]->wielkosc());y++)
     for(x=0;x<(dane[0]->wielkosc_x(y));x++)
        {
           s=(dane[0]->zwroc(y))[x];
           
           if(s!="n" && s!="p" && s!="|" && s!="/" && s!="-" && s!="\\" && s!="X") tablica+=({s});
        }
        
  return tablica;
}

/*
 * Wyswietla mape.
 */
string
wyswietl_mape()
{
 int a,b,c,d,e,max=0;
 string s,mapka;
 
 mapka="\n"+tytul_mapy+"\n";

 d=(dane[0]->wielkosc());

 for(a=0;a<d;a++)
    {
     e=dane[0]->wielkosc_x(0);
     for(b=0;b<e;b++)
        {
         if(strlen((dane[0]->zwroc(a))[b])>max) max = strlen((dane[0]->zwroc(a))[b]);
        }
    }
    
 d=(dane[0]->wielkosc());

 for(a=0;a<d;a++)
    {
     e=dane[0]->wielkosc_x(0);
     for(b=0;b<e;b++)
        {
         if(((dane[0]->zwroc(a))[b]) != "n" && ((dane[0]->zwroc(a))[b]) != "p") s=(dane[0]->zwroc(a))[b];
         else s=" ";
         if(strlen(s)<max) for(c=0;c<(max-strlen(s));c++)
                                      {
                                        mapka=mapka+" ";
                                      }
         mapka=mapka+s;
        }
     mapka=mapka+"\n";
    }
 mapka=mapka+"\n";
 return mapka;
}

/*
 * Moja wersja funkcji wykorzystywanej przy normalnym chodzeniu.
 * Roznica z grubsza taka, ze przyjmuje sciezke a nie numer wyjscia :)
 */
object
load_room(string nazwa)
{
    string err;
    object ob;
    
    ob = find_object(nazwa);
    if (objectp(ob))
    {
	return ob;
    }
    
    if (err = LOAD_ERR(nazwa))
    {
	SECURITY->log_loaderr(nazwa, environment(this_player()), 
			      "", this_object(), err);
	write("Blad we wczytywaniu:\n" + err + " <" + nazwa +
	    ">\nKoniecznie 'zglos blad' o tym.\n");
	return 0;
    }
    return find_object(nazwa);
}

object
zwroc_obiekt_docelowy(int numer_lokacji, int kierunek)
{
   int a,b;
   int x,y;
   int *wspolrzedne;
   string *tablica_wyjsc=allocate(8);
   int lokac_n;
   mixed lokacja;
   string nazwa;
   object room;

   wspolrzedne=znajdz_wspolrzedne(numer_lokacji);

   x=wspolrzedne[0];
   y=wspolrzedne[1];      

   if(x==-1 || y==-1)
     {
         write("Podany numer lokacji nie istnieje na mapie !\n");
         return 0;
     }

   tablica_wyjsc=wczytaj_mapke(x,y);
 
   a = policz_wyjscia(tablica_wyjsc);

   if((a + ile_wyjsc_obcinamy) > 8) tablica_wyjsc=odejmij_wyjscia(tablica_wyjsc,(a + ile_wyjsc_obcinamy - 8));
 
   tablica_wyjsc=uaktywnij_wyjscia(tablica_wyjsc);

   odswiez_mape(tablica_wyjsc,x,y);

   lokac_n=(znajdz_docelowe(tablica_wyjsc,x,y))[kierunek];
   
   if(!lokac_n) return previous_object();
   
   if(lokac_n<(dane[2]->wielkosc())) lokacja=dane[2]->zwroc(lokac_n);
   else lokacja=0;
   
   if(objectp(lokacja)) return lokacja;

   nazwa=sciezka_do_lokacji+poczatek_nazw_plikow+lokac_n+".c";
   
   if(lokacja==-1)
   {
       room=load_room(nazwa);
       if(!objectp(room)) return previous_object();
       return room;
   }
   
   if(lokacja==0)
       if(file_size(nazwa)>0)
       {
          dane[2]->ustaw(lokac_n,-1); // juz wiecej nie bedziemy musieli tego 0 sprawdzac :)
          return find_object(nazwa);
       }

   if(lokacja==1 || lokacja==0) // 0 tez, bo widocznie to nie plik jesli jeszcze jestesmy ;)
   {
       sprawdz_dane(2);
// DEBUG       write("Klonujemy wirtualna lokacje!\n");
       room=clone_object(lokacja_wirtualna);
       dane[2]->ustaw(lokac_n,room);
// DEBUG       write("Konfig wirtualnej (wysylam):"+lokac_n+"!\n");
       room->konfiguruj_lokacje(lokac_n);
// DEBUG       write("Done konfig wirtualnej!\n");
       return dane[2]->zwroc(lokac_n);
   }
   
   return previous_object();
}

/*
 * Sluzy do dodawania jakichs rzeczy extra, ale indywidualnie.
 * STD nic nie dodaje.
 */
void
wlacz_dodatki()
{
}

