/*
                                Denise-MYTH Artificial Intelligence.

                                  Copyright (C) 2000 Szymon Jessa

                                         WERSJA ANGIELSKA:

This  program  is free software; you can redistribute it and/or modify it under the terms of the GNU
General  Public  License  as  published  by  the  Free  Software Foundation; either version 2 of the
License, or (at your option) any later version.

This  program  is  distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
even  the  implied  warranty  of  MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

You  should  have received a copy of the GNU General Public License along with this program; if not,
write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

                                           WERSJA POLSKA:

Niniejszy   program   jest  oprogramowaniem  wolnodostėpnym;  moūesz  go  rozprowadzaź  dalej  i/lub
modyfikowaź na warunkach Powszechnej Licencji Publicznej GNU, wydanej przez Fundacjė Wolnodostėpnego
Oprogramowania - wedīug wersji 2-giej tej Licencji lub którejō z póśniejszych wersji.

Niniejszy   program  rozpowszechniany  jest  z  nadziejā,  iū  bėdzie  on  uūyteczny  -  jednak  BEZ
JAKIEJKOLWIEK  GWARANCJI,  nawet  domyōlnej  gwarancji  PRZYDATNOŌCI  HANDLOWEJ albo PRZYDATNOŌCI DO
OKREŌLONYCH ZASTOSOWAĻ. W celu uzyskania bliūszych informacji - Powszechna Licencja Publiczna GNU.

Z  pewnoōciā  wraz  z niniejszym programem otrzymaīeō teū egzemplarz Powszechnej Licencji Publicznej
GNU; jeōli nie - napisz do Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

                                              KONTAKT:

snail: Szymon Jessa, ul. Warszawska 20/6, 89-600 Chojnice,
email: smoczek@ue.eti.pg.gda.pl (ew. noco@box43.gnet.pl)
phone: (052) 39-707-88

****************************************************************************************************
*/
// * * * B A Z A  F A K T Ó W * * *

struct obiekt_struct * FROM fakty_malloc_obiekt(void)
{
   struct obiekt_struct *obiekt;
   if ((obiekt=(struct obiekt_struct *) malloc(sizeof(struct obiekt_struct)))==NULL) return NULL;

   obiekt->time=NULL;
   obiekt->ile_grup=0;
   obiekt->odmienione=NULL;
   obiekt->podstawowe=NULL;
   obiekt->funkcja=NULL;
   obiekt->ident_head=NULL;
   obiekt->funkc_head=NULL;
   obiekt->next=NULL;

   return obiekt;
}

struct simple_struct * FROM fakty_load_simple(FILE *stream,char *result)
{
   struct simple_struct *simple_head,*simple,*simple_next;
   char txt[MAX_LINE_LENGHT];
   char ile_grup;

   for (simple_head=NULL;;simple=simple_next)
   {
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) {*result=DATA_ERROR;return simple_head;}
      if (txt[0]==FUNKC_START || txt[0]==OBIEKT_START || txt[0]==FAKT_START || txt[0]==DATA_END) {*result=txt[0];return simple_head;}

      if ((ile_grup=(char) atoi(txt))<=0) {*result=DATA_ERROR;return simple_head;}
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) {*result=DATA_ERROR;return simple_head;}

      simple_next=(struct simple_struct *) malloc(sizeof(struct simple_struct));
      if (simple_next==NULL) {*result=NO_MEMORY;return simple_head;}

      simple_next->next=NULL;
      if ((simple_next->opis=create_array(txt,ile_grup))==NULL)
      {
         free(simple_next);
         *result=NO_MEMORY;
         return simple_head;
      }
      simple_next->ile_grup=ile_grup;

      if (simple_head==NULL) simple_head=simple_next;
      else simple->next=simple_next;
   }
}

void FROM fakty_load_learn(char nr_bazy)
{
   /*
   funkcja odczytuje nowe bazy faktów, i doīācza je do bazy aktualnej
   wywoīywana rekurencyjnie: nr_bazy - fakt<nr_bazy>.dat
   algorytm:
   - utworzenie obiektu rozbioru na podstawie danych odczytanych ze zmienionā datā
   - próba identyfikacji - rozpoznanie faktu macierzystego
   - sprawdzenie, jak fakt ma siė do danych w bazie
      - jeōli jest BRAK DANYCH (lub inaczej, ale <100%): nauka obiektu (flearn_obiekt())
      - jeōli jest SPRZECZNY: ile_sprzecznych++
      - jeōli jest ZGODNY (100%): ile_zgodnych++
   - skasowanie obiektu rozbioru
   */

   FILE *stream;
   struct obiekt_struct *obiekt;
   clock_t time=clock();
   ULONG fakty_count_old,fakty_count_obiekt_old,fakty_count_simple_old,fakty_memory_use_old;
   char txt[MAX_LINE_LENGHT];
   char result;

   // próba otwarcia pliku z faktami
   sprintf(txt,"%s%d%s",FAKTY_FILE,nr_bazy,TYPE_DAT);
   if ((stream=data_open(txt,"r"))==NULL) return;

   fakty_count_old=fakty_count();
   fakty_count_obiekt_old=fakty_count_obiekt(NULL);
   fakty_count_simple_old=fakty_count_simple(MODE_FP,NULL,NULL);
   fakty_memory_use_old=fakty_memory_use();

   sprintf(txt,"uczenie z bazy: %s%d%s (%.3fkB)\n",FAKTY_FILE,nr_bazy,TYPE_DAT,(float) file_lenght(stream)/1024);
   con_put(txt);

   if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) {fclose(stream); return;}
   if (txt[0]!=FAKT_START) goto loading_error;
   if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) {fclose(stream); return;}
   if (txt[0]!=OBIEKT_START) goto loading_error;

   // pamiėź dla obiektu
   if ((obiekt=fakty_malloc_obiekt())==NULL) goto no_memory;

   // kolejne obiekty
   for (;;)
   {
      // * * * OBIEKT START * * *
      // data
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      if ((obiekt->time=create_string(current_time(),21))==NULL) goto no_memory;

      // ile grup
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      obiekt->ile_grup=atoi(txt);

      // grupy odmienione
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      if ((obiekt->odmienione=create_string(txt,strlen(txt)))==NULL) goto no_memory;

      // grupy podstawowe
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      if ((obiekt->podstawowe=create_string(txt,strlen(txt)))==NULL) goto no_memory;

      // funkcje grup
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      if ((obiekt->funkcja=create_array(txt,obiekt->ile_grup))==NULL) goto no_memory;

      // fakty proste
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      if (txt[0]!=IDENT_START) goto loading_error;
      obiekt->ident_head=fakty_load_simple(stream,&result);
      if (result!=FUNKC_START) goto loading_error;
      obiekt->funkc_head=fakty_load_simple(stream,&result);
      if (result==NO_MEMORY || result==DATA_ERROR) goto loading_error;
      // * * * OBIEKT END * * *

      // *************** NAUKA *****************

      rozbior.fakt=NULL;
      rozbior.obiekt=obiekt;

      // próba identyfikacji - rozpoznanie faktu macierzystego
  	   rozbior.fakt=fident_mother_fakt(rozbior.obiekt,NULL);

      // sprawdzenie, jak ma siė podany obiekt do danych w bazie

    	status.quality=100;
      switch (fident_obiekt_simple(rozbior.fakt,rozbior.obiekt,NULL,FULL_DEPTH,MODE_ZGODNOSC))
   	{
   		case FAKT_ZGODNY:
            // jeōli fakt jest w bazie w 100% zgodny to nie dodajemy
	   		if (status.quality==100) goto NAUKA_END;
            // w przeciwnym razie nauka;
   			break;
   		case FAKT_SPRZECZNY:
            // jeōli fakt jest w bazie w 100% sprzeczny to nie dodajemy
            if (status.quality==100) goto NAUKA_END;
            // w przeciwnym razie nauka
   			break;
   		case FAKT_BRAK_DANYCH:
            // no, nauka, pewnie!
	   		break;
   	}

      // wywoīanie funkcji do nauki
      flearn_obiekt();

      NAUKA_END:

      rozbior.fakt=NULL;
      rozbior.obiekt=NULL;

      // ************* NAUKA END ***************

      // koniec bazy lub nowy obiekt lub nowy fakt
      if (result==DATA_END) break;
      switch (result)
      {
         case FAKT_START:
            // NOWY FAKT i NOWY OBIEKT (pierwszy obiekt w fakcie)
            if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
            if (txt[0]!=OBIEKT_START) goto loading_error;
            break;
         case OBIEKT_START: break;
         default: goto loading_error;
      }
   }

   fclose(stream);

   sprintf(txt,"nowych faktów/obiektów/fp: %ld/%ld/%ld (%.3fkB) (czas nauki: %.3fs)\n",
                fakty_count()-fakty_count_old,fakty_count_obiekt(NULL)-fakty_count_obiekt_old,fakty_count_simple(MODE_FP,NULL,NULL)-fakty_count_simple_old,
                (float) (fakty_memory_use()-fakty_memory_use_old)/1024,(float) (clock()-time)/CLK_TCK);
   con_put(txt);

   // zwalniamy pamiėź obiektu
   fakty_erase_obiekt(obiekt);

   // nastėpna baza
   fakty_load_learn(nr_bazy+1);

   // na koniec wypisujemy nowy stan bazy faktów
   if (nr_bazy==1)
   {
      sprintf(txt,"aktualny stan wiedzy: %ld/%ld/%ld (%.3fkB)\n",
                   fakty_count(),fakty_count_obiekt(NULL),fakty_count_simple(MODE_FP,NULL,NULL),
                   (float) fakty_memory_use()/1024);
      con_put(txt);
   }

   return;

   // bīād przy wczytywaniu
   loading_error:
   fclose(stream);
   con_put("bīād: nie mogė odczytaź danych (bīėdna baza)\n");
   fakty_erase_obiekt(obiekt);
   fakty_load_learn(nr_bazy+1);
   return;

   // brak pamiėci
   no_memory:
   fclose(stream);
   con_put("bīād: brak pamiėci\n");
   fakty_erase_obiekt(obiekt);
   return;
}

char FROM fakty_load(void)
{
   FILE *stream;
   clock_t time=clock();
   struct fakt_struct *fakt,*fakt_next;
   struct obiekt_struct *obiekt,*obiekt_next;
   char txt[MAX_LINE_LENGHT],result;

   fakt_head=NULL; // przed wczytaniem baza faktów jest pusta (KONIECZNE!)
   mapa_erase(); // kasujemy korelacje faktow

   if ((stream=data_open(FAKTY_FILE TYPE_DAT,"r"))==NULL) return RESULT_NO_OK;

   sprintf(txt,"(%.3fkB)\n",(float) file_lenght(stream)/1024);
   con_put(txt);

   if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) {fclose(stream); return RESULT_OK;}
   if (txt[0]!=FAKT_START) goto loading_error;
   if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) {fclose(stream); return RESULT_OK;}
   if (txt[0]!=OBIEKT_START) goto loading_error;

   // FAKT (first)
   if ((fakt=(struct fakt_struct *) malloc(sizeof(struct fakt_struct)))==NULL) goto no_memory;
   fakt->next=NULL;
   fakt->obiekt_head=NULL;
   // OBIEKT (first)
   if ((obiekt=fakty_malloc_obiekt())==NULL) {free(fakt);goto no_memory;}
   fakt->obiekt_head=obiekt;
   fakt_head=fakt;

   // wczytywanie kolejnych faktów (oraz obiektów i faktów prostych)
   for (;;)
   {
      // * * * OBIEKT START * * *
      // data
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      if ((obiekt->time=create_string(txt,strlen(txt)))==NULL) goto no_memory;
      // ile grup
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      obiekt->ile_grup=atoi(txt);
      // grupy odmienione
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      if ((obiekt->odmienione=create_string(txt,strlen(txt)))==NULL) goto no_memory;
      // grupy podstawowe
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      if ((obiekt->podstawowe=create_string(txt,strlen(txt)))==NULL) goto no_memory;
      // funkcje grup
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      if ((obiekt->funkcja=create_array(txt,obiekt->ile_grup))==NULL) goto no_memory;
      // fakty proste
      if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
      if (txt[0]!=IDENT_START) goto loading_error;
      obiekt->ident_head=fakty_load_simple(stream,&result);
      if (result!=FUNKC_START) goto loading_error;
      obiekt->funkc_head=fakty_load_simple(stream,&result);
      if (result==NO_MEMORY || result==DATA_ERROR) goto loading_error;
      // * * * OBIEKT END * * *

      // koniec bazy lub nowy obiekt lub nowy fakt
      if (result==DATA_END) break;
      switch (result)
      {
         case FAKT_START:
            // NOWY FAKT i NOWY OBIEKT (pierwszy obiekt w fakcie)
            if (fgets(txt,MAX_LINE_LENGHT,stream)==NULL) goto loading_error;
            if (txt[0]!=OBIEKT_START) goto loading_error;
            // rezerwacja pamiėci dla nowego faktu
            if ((fakt_next=(struct fakt_struct *) malloc(sizeof(struct fakt_struct)))==NULL) goto no_memory;
            // rezerwacja pamiėci dla nowego obiektu
            if ((obiekt=fakty_malloc_obiekt())==NULL) goto no_memory;
            fakt_next->obiekt_head=obiekt;
            fakt_next->next=NULL;
            // przyīāczenie do listy faktów
            fakt->next=fakt_next;
            fakt=fakt_next;
            break;
         case OBIEKT_START:
            // NOWY OBIEKT
            if ((obiekt_next=fakty_malloc_obiekt())==NULL) goto no_memory;
            obiekt->next=obiekt_next;
            obiekt=obiekt_next;
            break;
         default: goto loading_error;
      }
   }

   fclose(stream);
   sprintf(txt,"liczba odczytanych faktów/obiektów/FP: %ld/%ld/%ld (%.3fkB) (%.3fs)\n",
                fakty_count(),fakty_count_obiekt(NULL),fakty_count_simple(MODE_FP,NULL,NULL),
                (float) fakty_memory_use()/1024,(float) (clock()-time)/CLK_TCK);
   con_put(txt);

   return RESULT_OK;

   // bīād przy wczytywaniu
   loading_error:
   fclose(stream);
   con_put("bīād: nie mogė odczytaź danych\n");
   fakty_erase();
   return RESULT_NO_OK;

   no_memory:
   fclose(stream);
   con_put("bīād: brak pamiėci\n");
   fakty_erase();
   return RESULT_NO_OK;
}

char FROM fakty_save_simple(FILE *stream,struct simple_struct *simple)
{
   char nr1;
   // nagrywanie faktu prostego (identyfikacji lub funkcyjnego)
   for (;simple!=NULL;simple=simple->next)
   {
      if (fprintf(stream,"%d\n",simple->ile_grup)<0) return RESULT_NO_OK;

      for (nr1=0;nr1<simple->ile_grup-1;nr1++)
         if (fprintf(stream,"%d,",simple->opis[nr1])<0) return RESULT_NO_OK;

      if (fprintf(stream,"%d\n",simple->opis[nr1])<0) return RESULT_NO_OK;
   }
   return RESULT_OK;
}

char FROM fakty_save_obiekt(FILE *stream,struct obiekt_struct *obiekt)
{
   UBYTE nr1;
   for (;obiekt!=NULL;obiekt=obiekt->next)
   {
      if (fprintf(stream,"%c\n",OBIEKT_START)<0) return RESULT_NO_OK;
      if (fprintf(stream,"%s\n",obiekt->time)<0) return RESULT_NO_OK;
      if (fprintf(stream,"%d\n",obiekt->ile_grup)<0) return RESULT_NO_OK;
      if (fprintf(stream,"%s\n",obiekt->odmienione)<0) return RESULT_NO_OK;
      if (fprintf(stream,"%s\n",obiekt->podstawowe)<0) return RESULT_NO_OK;

      for (nr1=0;nr1<obiekt->ile_grup-1;nr1++)
         if (fprintf(stream,"%d,",obiekt->funkcja[nr1])<0) return RESULT_NO_OK;
      if (fprintf(stream,"%d\n",obiekt->funkcja[nr1])<0) return RESULT_NO_OK;

      if (fprintf(stream,"%c\n",IDENT_START)<0) return RESULT_NO_OK;
      if (fakty_save_simple(stream,obiekt->ident_head)==RESULT_NO_OK) return RESULT_NO_OK;

      if (fprintf(stream,"%c\n",FUNKC_START)<0) return RESULT_NO_OK;
      if (fakty_save_simple(stream,obiekt->funkc_head)==RESULT_NO_OK) return RESULT_NO_OK;
   }
   return RESULT_OK;
}

char FROM fakty_save(void)
{
#ifdef DEMO
   con_put("w wersji demonstracyjnej nie moūna zapisaź bazy faktów\n");
   return RESULT_OK;
#else
   FILE *stream;
   struct fakt_struct *fakt;
   char txt[MAX_LINE_LENGHT];

   // zabezpieczenie - nie nagrywamy bazy jeōli jest pusta, nie kasujemy starej
   if (fakt_head==NULL) return RESULT_OK;

   if ((stream=data_open(FAKTY_FILE TYPE_TMP,"w"))==NULL) return RESULT_NO_OK;

   for (fakt=fakt_head;fakt!=NULL;fakt=fakt->next)
   {
      if (fprintf(stream,"%c\n",FAKT_START)<0) goto saving_error;
      if (fakty_save_obiekt(stream,fakt->obiekt_head)==RESULT_NO_OK) goto saving_error;
   }
   if (fprintf(stream,"%c\n",DATA_END)<0) goto saving_error;
   fclose(stream);

   copy_and_remove(FAKTY_FILE TYPE_DAT,FAKTY_FILE TYPE_OLD);
   if (copy_and_remove(FAKTY_FILE TYPE_TMP,FAKTY_FILE TYPE_DAT)==RESULT_NO_OK) return RESULT_NO_OK;

   sprintf(txt,"liczba zapisanych faktów/obiektów/FP: %ld/%ld/%ld\n",
	       fakty_count(),fakty_count_obiekt(NULL),fakty_count_simple(MODE_FP,NULL,NULL));
   con_put(txt);

   return RESULT_OK;

   // bīād w nagrywaniu danych
   saving_error:
   fclose(stream);
   remove(FAKTY_FILE TYPE_TMP);
   con_put("bīād: nie mogė zapisaź danych\n");
   return RESULT_NO_OK;
#endif
}

void FROM fakty_erase_simple(struct simple_struct *simple)
{
   struct simple_struct *simple_next;

   for (;simple!=NULL;simple=simple_next)
   {
      simple_next=simple->next;
      free(simple->opis);
      free(simple);
   }
}

void FROM fakty_erase_obiekt(struct obiekt_struct *obiekt)
{
   if (obiekt!=NULL)
   {
      free(obiekt->time);
      free(obiekt->funkcja);
      free(obiekt->odmienione);
      free(obiekt->podstawowe);
      fakty_erase_simple(obiekt->ident_head);
      fakty_erase_simple(obiekt->funkc_head);

      free(obiekt);
   }
}

void FROM fakty_erase(void)
{
   struct fakt_struct *fakt,*fakt_next;
   struct obiekt_struct *obiekt,*obiekt_next;

   // kasowanie faktu, obiektu, faktu prostego
   for (fakt=fakt_head;fakt!=NULL;fakt=fakt_next)
   {
      fakt_next=fakt->next;
      for (obiekt=fakt->obiekt_head;obiekt!=NULL;obiekt=obiekt_next)
      {
	 obiekt_next=obiekt->next;
	 fakty_erase_obiekt(obiekt);
      }
      free(fakt);
   }

   fakt_head=NULL;

 	// kasowanie wszystkiego, co bylo zwiazane z baza faktow
    denise.fakt=NULL;
	denise.obiekt=NULL;
    rozmowca.fakt=NULL;
    rozmowca.obiekt=NULL;
    temat.fakt=NULL;
    temat.obiekt=NULL;

    // kasujemy mape korelacji faktow
    mapa_erase();
}

// * * * funkcje podajāce informacje iloōciowe o bazach * * *

ULONG FROM fakty_memory_use(void)
{
   struct fakt_struct *fakt;
   struct obiekt_struct *obiekt;
   struct simple_struct *simple;
   ULONG ile=0;

   for (fakt=fakt_head;fakt!=NULL;fakt=fakt->next,ile+=sizeof(struct fakt_struct))
   {
      for (obiekt=fakt->obiekt_head;obiekt!=NULL;obiekt=obiekt->next,ile+=sizeof(struct obiekt_struct))
      {
         ile+=strlen(obiekt->time);
         ile+=sizeof(char); // ile_grup
         ile+=sizeof(char); // odmienione
         ile+=strlen(obiekt->odmienione);
         ile+=sizeof(char); // podstawowe
         ile+=strlen(obiekt->podstawowe);
         ile+=sizeof(char); // funkcja
         ile+=strlen(obiekt->funkcja);
         for (simple=obiekt->ident_head;simple!=NULL;simple=simple->next,ile+=sizeof(struct simple_struct))
         {
            ile+=sizeof(char); // opis
            ile+=strlen(simple->opis);
            ile+=sizeof(char); // ile_grup
         }
         for (simple=obiekt->funkc_head;simple!=NULL;simple=simple->next,ile+=sizeof(struct simple_struct))
         {
            ile+=sizeof(char); // opis
            ile+=strlen(simple->opis);
            ile+=sizeof(char); // ile_grup
         }
      }
   }

   return ile;
}

ULONG FROM fakty_count(void)
{
   struct fakt_struct *fakt;
   ULONG ile=0;

   for (fakt=fakt_head;fakt!=NULL;fakt=fakt->next,ile++);

   return ile;
}

ULONG FROM fakty_count_obiekt(struct fakt_struct *from_fakt)
{
   // from_fakt!=NULL - zlicza obiekty w from_fakt
   // from_fakt==NULL - zlicza obiekty w caīej bazie

   struct fakt_struct *fakt;
   struct obiekt_struct *obiekt;
   ULONG ile=0;

   if (from_fakt==NULL)
      for (fakt=fakt_head;fakt!=NULL;fakt=fakt->next)
         for (obiekt=fakt->obiekt_head;obiekt!=NULL;obiekt=obiekt->next,ile++);
   else
      for (obiekt=from_fakt->obiekt_head;obiekt!=NULL;obiekt=obiekt->next,ile++);
      

   return ile;
}

ULONG FROM fakty_count_simple(char mode,struct fakt_struct *from_fakt,struct obiekt_struct *from_obiekt)
{
   // mode: MODE_FP,MODE_FPI,MODE_FPF - wybrane lub wszystkie fakty proste
   // from_obiekt!=NULL - zlicza FP w from_obiekt
   // from_obiekt==NULL i from_fakt!=NULL - zlicza FP w from_fakt
   // from_obiekt==NULL i from_fakt==NULL - zlicza FP w caīej bazie

   struct fakt_struct *fakt;
   struct obiekt_struct *obiekt;
   struct simple_struct *simple;
   ULONG ile=0;

   // w caīej bazie
   if (from_fakt==NULL && from_obiekt==NULL)
   {
      for (fakt=fakt_head;fakt!=NULL;fakt=fakt->next)
      {
         for (obiekt=fakt->obiekt_head;obiekt!=NULL;obiekt=obiekt->next)
         {
            if (mode!=MODE_FPF) for (simple=obiekt->ident_head;simple!=NULL;simple=simple->next,ile++);
            if (mode!=MODE_FPI) for (simple=obiekt->funkc_head;simple!=NULL;simple=simple->next,ile++);
         }
      }
   }
   // w from_fakt
   else if (from_fakt!=NULL && from_obiekt==NULL)
   {
      for (obiekt=from_fakt->obiekt_head;obiekt!=NULL;obiekt=obiekt->next)
      {
	      if (mode!=MODE_FPF) for (simple=obiekt->ident_head;simple!=NULL;simple=simple->next,ile++);
	      if (mode!=MODE_FPI) for (simple=obiekt->funkc_head;simple!=NULL;simple=simple->next,ile++);
      }
   }
   // w from_obiekt
   else if (from_obiekt!=NULL)
   {
      if (mode!=MODE_FPF) for (simple=from_obiekt->ident_head;simple!=NULL;simple=simple->next,ile++);
      if (mode!=MODE_FPI) for (simple=from_obiekt->funkc_head;simple!=NULL;simple=simple->next,ile++);
   }
   // zabezpieczenie (czysto profilaktyczne)
   else
      con_put("bīād: nieprzewidziane wywoīanie funkcji 'fakty_count_simple'!\n");


   return ile;
}
