
#ifndef _tudinc_H
#define _tudinc_H
// Anzahl der untergruende 
#define anzunter 7
/******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************

        T U D    H A U P T M O D U L

	H E A D E R D A T E I

*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
******************************************************************************/

#include <sys/time.h>
#include "listen2.H"
#include "sprite01.H"
#include "communic.H"
#include <strstream.h>
#include <string>

// ********************************************* Globale Prozeduren
// ********************************************* Globale Prozeduren
// ********************************************* Globale Prozeduren

/// check directions
void chkdir(float *dir);

// Liefert die vergangene Zeit zw. 2 Zeitpunkten (in Sekunden)
// Achtung die Zeitpunkte duerfen nicht zu weit auseinanderliegen !

/// difference in seconds between two points in time
float getdeltatime(timeval *alte_zeit,timeval *neue_zeit);


// Untergrundtabelle ************************************************************
// Untergrundtabelle ************************************************************
// Untergrundtabelle ************************************************************

/// Ground definition table
class untergrundtabtype
{
public:
  untergrundtabtype(char *dateiname,int8 mode=CFG_TEXT_MODE);
  void change(iotype *ioptr,int8 mode=CFG_TEXT_MODE);
  int16 anzahl;
  int8 tab[256];
};

// Relationships ************************************************************
// Relationships ************************************************************
// Relationships ************************************************************

#define REL_FRIEND 1
#define REL_ENEMY 0
/// Relationship class
class spieler_relation_zeigerelemtype : public zeigerelem_changetype<spieler_relation_zeigerelemtype>
{
public:
  spieler_relation_zeigerelemtype();
  int32 spielernummer;
  // !=0 => Friede   0 => Krieg
  int8 relation;
  void change(iotype *ioptr,int8 mode);
  int compare(int32 spnr)
  {
    return (spnr==spielernummer);
  }
};

machekette_changetype(spieler_relation);

// Spielerdaten ***************************************************************
// Spielerdaten ***************************************************************
// Spielerdaten ***************************************************************
/// player's data
class spieler_zeigerelemtype : public zeigerelem_changetype<spieler_zeigerelemtype>
{
public:
  string spielername;
  string passwd;
  string flaggenname;
  string dateiname;
  int32 spielernummer;
  int32 akteinheitnr;
  spieler_relation_kettetype spieler_relation_kette;
  
  spieler_zeigerelemtype();
  void ladespieler (const char *name);
  // todo nicht der weisheit letzter schluss !!
  void change_short(iotype *ioptr,int8 mode);
  void change(iotype *ioptr,int8 mode);
  int compare(int32 spnr)
  {
    return (spielernummer==spnr);
  }
};
machekette_changetype(spieler);
  

// producttype **********************************************************************
// producttype **********************************************************************
// producttype **********************************************************************
// producttype **********************************************************************
// producttype **********************************************************************
// producttype **********************************************************************

/*
  wird benoetigt fuer firmen, damit lassen sich objekte und einheiten gleich erstellen
  muss koennen:
  sich malen an einer bestimmten pos. in einem sprite
  sich verwandeln in ein objekt oder in eine einheit
  brauche ich nich
 */
/*
/// product
class producttype
{
public:
  virtual void paint(int x,int y,spritetype *spriteptr)
  {
    cout << "producttype::paint(...) aufgerufen\n";
  }
protected:
};
*/

// Objekttype **********************************************************************
// Objekttype **********************************************************************
// Objekttype **********************************************************************
// Objekttype **********************************************************************
// Objekttype **********************************************************************

class objekt_datentype;


class objekt_zeigerelemtype : public zeigerelem_changetype<objekt_zeigerelemtype>//, public producttype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! =>benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  virtual const char *getheaderstring();

  int32 anzahl;
  string objekt_datenname;
  objekt_datentype *objekt_datenptr;
  objekt_zeigerelemtype();
  objekt_zeigerelemtype(const char *name,int32 _anzahl);
  virtual ~objekt_zeigerelemtype();
  void change(iotype *ioptr,int8 mode);
  int compare(const char* name)
  {
    return (objekt_datenname==string(name));
  }
  void init();
  void deinit();
};

ostream &operator<<(ostream &ost,const objekt_zeigerelemtype &z);


// objekt_kettetype **********************************************************************
// objekt_kettetype **********************************************************************
// objekt_kettetype **********************************************************************
// objekt_kettetype **********************************************************************
// objekt_kettetype **********************************************************************

class objekt_kettetype : public kette_changetype<objekt_zeigerelemtype>
{
public:
  objekt_kettetype(){maxvolume=0;}
  objekt_zeigerelemtype *get_or_create(const char* name);
  objekt_zeigerelemtype *getobjekt(const char* name) const;
  // should add anz of name and returns how much really was added
  int32 add(const char *name,int32 anz);
  // restrict anz of obj to max volume
  int32 calc_newanz(int32 anz,objekt_datentype *obj_datenptr);
  // give togive of objekt *name
  void give(const char *name,int32 togive,objekt_kettetype &otherkette);

  void giveuntil(const char *name,int32 giveuntil,objekt_kettetype &otherkette);
  void check();
  int32 volume() const;
  void set_maxvolume(int32 _max){maxvolume=_max;}
 private:
  int32 maxvolume;
};




// product_datentype *********************************************************************
// product_datentype *********************************************************************
// product_datentype *********************************************************************
// product_datentype *********************************************************************
// product_datentype *********************************************************************


class product_datentype 
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! =>benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  virtual const char *getheaderstring();

  string spritename;
  spritetype *spriteptr;

  virtual void change(iotype *ioptr,int8 mode);
  // ruft beim laden erst deinit() und dann init() auf
  virtual void change_intern(iotype *ioptr,int8 mode);

  virtual void paint_icon(int x, int y,sprite_lineartype *destspriteptr)
  {
    spriteptr->copysprite_clip(x,y,destspriteptr);
  }
  virtual void paint_icon_to(sprite_lineartype *spr,const rechtecktype &rect)
    {
      spriteptr->copysprite_maxpect_to(spr,rect);
      spr->map(rect);
    }

  product_datentype()
  {
    spriteptr=NULL;
  }
  virtual ~product_datentype()
  {
    deinit();
  }
  float reltime_tobuild;
  
  objekt_kettetype *missing_objects(const objekt_kettetype &objkette)
    {
      objekt_kettetype *erg=new objekt_kettetype;
      objekt_zeigerelemtype *akt=needed_objekt_kette.anfang->next;
      while(akt!=needed_objekt_kette.ende)
	{
	  objekt_zeigerelemtype *akt_avail=objkette.getobjekt(akt->objekt_datenname.c_str());
	  if (akt_avail)
	    {
	      if (akt_avail->anzahl<akt->anzahl)
		{
		  // Some more of this obj type needed
		  objekt_zeigerelemtype *newone=new objekt_zeigerelemtype(akt->objekt_datenname.c_str(),akt->anzahl-akt_avail->anzahl);
		  erg->zeiger_push(newone);
		}
	    }
	  else
	    {
	      // none of this type available => all of this type missing
	      objekt_zeigerelemtype *newone=new objekt_zeigerelemtype(akt->objekt_datenname.c_str(),akt->anzahl);
	      erg->zeiger_push(newone);
	    }
	  akt=akt->next;
	}
      return erg;
    }

protected:
  // Objekts needed to build
  objekt_kettetype needed_objekt_kette;
private:
  void init()
  {
    spriteptr=allsprites_ketteptr->make_elementadress(spritename.c_str());
  }
  void deinit()
  {
    if (spriteptr)
      allsprites_ketteptr->delete_elementadress(spriteptr);
  }
};

// objekt_datentype *****************************************************************
// objekt_datentype *****************************************************************
// objekt_datentype *****************************************************************
// objekt_datentype *****************************************************************
// objekt_datentype *****************************************************************
class ammo_datentype;

/// object data
class objekt_datentype : public zeigerelem_iqtype<objekt_datentype>, public product_datentype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! =>benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  // Platzbedarf
  int32 volume;
  // wieviele von diesem Objekt werden als eines dargestellt
  int32 unit;

  static objekt_datentype *create(iotype *ioptr,int8 mode);

  void change_intern(iotype *ioptr,int8 mode);
  virtual ~objekt_datentype();
  ammo_datentype *cast_ammo_datentype();
};
typedef kette_iqtype<objekt_datentype> objekt_daten_kette_iqtype;


// ammo_datentype ************************************************************
// ammo_datentype ************************************************************
// ammo_datentype ************************************************************

/// Ammunition data
class ammo_datentype : public objekt_datentype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! =>benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  float muehexplosion;
  float explosionsradius;    // loaded in [m] but converted to [dots]
  int32 explosionsradiusint; // just for calculations
  string sound;              // file name of the sample

  void change_intern(iotype *ioptr,int8 mode);
  virtual ~ammo_datentype();
};



// Statische Einheitdaten *****************************************************
// Statische Einheitdaten *****************************************************
// Statische Einheitdaten *****************************************************

// muesste eigentlich heissen: einheit_daten_zeigerelem_iqtype
// habe ich aber der einfachheit halber weggelassen
class firma_datentype;
class panzer_datentype;

/// statical data of unit
class einheit_datentype : public zeigerelem_iqtype<einheit_datentype>, public product_datentype
{
public:
  // Spezial routine um objekte mit abgeleiteten virtuellen routinen einheitlich zu erstellen !!
  // wird in listen2.H verwendet (kette_iqtype)
  // erstellt einen einheit_datentype aus einem stream 
  // (und erkennt anhand eines headerstrings was fuer ein einheit_datentype es ist)
  static einheit_datentype *create(iotype *ioptr,int8 mode);

  // Typeinfo -Achtung statisch wird nicht vererbt !!! =>benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  // Randlinien !! - Zugriff nur ueber eine Routine wegen veraenderlichen Randlinien !
  linie2_polpunkt_poldir_kettetype randlinien_kette;

  int32 sichtradius;

  // Schutz
  float einheitradius;
  float muehmine;
  float muehgranate;

  // Fuel to use and how much fuel units per second
  string fuelname;
  float fuelpersec;

  // Kapazitaet
  float capacity;

  einheit_datentype();
  virtual ~einheit_datentype();

  // ACHTUNG kann bis jetzt nur laden !!
  virtual void change_intern(iotype *ioptr,int8 mode);

  // Konvertieren in anderen Typ falls moeglich !! 
  void convert(panzer_datentype **result);
  void convert(firma_datentype **result);
private:
};

typedef kette_iqtype<einheit_datentype> einheit_daten_kette_iqtype;

// Statische Firmadaten ******************************************************
// Statische Firmadaten ******************************************************
// Statische Firmadaten ******************************************************

/// statical data of factory
class firma_datentype : public einheit_datentype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  firma_datentype();
  ~firma_datentype();

  string firma_offen_spritename;
  spritetype *firma_offen_spriteptr;
  float time_tobuild_tiger;
  kette_changetype <string_zeigerelemtype> buildable_objekt_kette;
  kette_changetype <string_zeigerelemtype> buildable_vehicle_kette;  

  void change_intern(iotype *ioptr,int8 mode);
  // todo weg  producttype *create_product();
private:
  // laedt sprites
  void init();  
  // gibt sprites frei
  void deinit();
};


// StatischeCanondaten  ******************************************************
// StatischeCanondaten  ******************************************************
// StatischeCanondaten  ******************************************************

/// statical data of canons
class canon_datentype : public zeigerelem_changetype<canon_datentype>
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  string turm_spritename;
  spritetype *turm_spriteptr;
  //Turmposition
  vektor2_poltype turmpos;
  float vturmdreh;
  float vturmdrehhand;
  float vturmfahr;
  float vturmfahrhand;
  float relturmdirlinksmax;
  float relturmdirrechtsmax;
  float turmfahrmax;
  float turmfahrmin;
  float fuelpersec;

  float ladedauer;
  float richtzeit;
  string ammoname;
  
  float vschuss;

  canon_datentype()
  {  
    turm_spriteptr=NULL;
  }
  ~canon_datentype()
  {
    deinit();
  }

  void change(iotype *ioptr,int8 mode);
  void init()
  {
    turm_spriteptr=allsprites_ketteptr->make_elementadress(turm_spritename.c_str());
    //    cout <<"Turmsprite erstellt: "<<turm_spritename.c_str()<<endl;
  }
  void deinit()
  {
    if (turm_spriteptr)
      {
	allsprites_ketteptr->delete_elementadress(turm_spriteptr);  
	turm_spriteptr=NULL;
      }
  }
};
typedef kette_changetype<canon_datentype> canon_daten_kettetype;


// StatischePanzerdaten  ******************************************************
// StatischePanzerdaten  ******************************************************
// StatischePanzerdaten  ******************************************************

/// statical data of vehicles
class panzer_datentype : public einheit_datentype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  // Statische Daten !!!!!
  string vehiclename;
    
  // todo muss anders werden => beliebig viele Tuerme

  // Raddots
  vektor2_pol_kettetype raddots_kette;

  // Randlinien jetzt im Einheittype
  //  linie2_polpunkt_poldir_kettetype randlinien_kette;

  // Untergrundcheck:
  float speedfaktor[anzunter];
  float destroyfaktor[anzunter];
  int8 verbotenezone[anzunter];
  
  // Fahrtdaten: 
  float vpanzvor;
  float vpanzback;
  float vdreh;
  float vdrehstand;

  //Zerstören
  float minelegdauer;
  canon_daten_kettetype canon_daten_kette;

  panzer_datentype();
  ~panzer_datentype();

  void change_intern(iotype *ioptr,int8 mode);
  // todo weg  producttype *create_product();

private:
  // laedt sprites
  void init();  
  // gibt sprites frei
  void deinit();
};





// Der allgemeine Einheittype ************************************************************
// Der allgemeine Einheittype ************************************************************
// Der allgemeine Einheittype ************************************************************
// Darf nicht konstruktoriert werden !!! macht keinen Sinn !!

/// virtual base type of all dynamical unit data
class einheittype //: public producttype
{
public:
  enum changemodetype
  {
    short_mode, detailed_mode
  };

  // Typeinfo - Achtung statisch wird nicht vererbt !!! =>benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  virtual const char *getheaderstring();

  // todo sollte auch nicht public sein
  // player number
  int32 spielernummer;
  // real owners
  list<int32> lendlist;

  vektor2_koordtype pos;
  float einheitdir;
  // Identifikation der Einheit !!
  int32 einheitnummer; 

  // todo sollte auch nicht public sein
  string einheit_daten_dateiname;
  einheit_datentype *einheit_datenptr;
  float substanz;
  objekt_kettetype objekt_kette;
  objekt_zeigerelemtype *fuelptr;

  // Laden speichern (ACHTUNG bei einem reload darf sich der einheit_datenname nicht aendern !)
  void change(iotype *ioptr,int8 mode);
  virtual void change_intern(iotype *ioptr,int8 mode);


  // Zum suchen !!! s.h. listen2.H search !!
  int compare(int32 _einheitnummer)
  {
    return (einheitnummer==_einheitnummer);
  }

  // Ist die andere Einheit ein Freund ??
  // VB: other muss auf eine vorhandene einheit zeigen
  // NB: 0 <=> other ist feind  !=0 <=> other ist freund
  int friendship(einheittype *other);

  // ist die Einheit im Abstand von dist ?
  int near(einheittype *akt,float dist);
  // Schneiden sich die Kreise der Einheiten ?
  int near(einheittype *akt);

  // todo =0 !! schlecht geht net weil listen so aufgebaut sind dass sie ein obj konstruktorieren
  virtual void eingabechange(iotype *,int8)
  {fatalfehler("eingabechange vom einheittype aufgerufen");}

  virtual linie2_polpunkt_poldir_kettetype *get_randlinien_kette()
  {
    return &(einheit_datenptr->randlinien_kette);
  }

  virtual float get_standzeit()
  {
    // todo
    return 999999;
  }

  bool fuel_avail()
    {
      if (fuel>0.0)
	return true;
      //      else
      while ((fuelptr)&&(fuel<=0.0)&&(fuelptr->anzahl>0))
	{
	  fuelptr->anzahl-=1;
	  fuel+=1.0;
	}
      return (fuel>0.0);
    }

  void fuel_sub(float anz)
    {
      fuel-=anz;
      if (!fuel_avail())
	cout << "Vehicle No.: "<<einheitnummer<<" is out of fuel\n";
    }
  void newowner(int32 sp)
    {
      spielernummer=sp;
    }
  void lend(int32 sp)
    {
      lendlist.push_back(spielernummer);
      spielernummer=sp;
    }
  void takeback(int32 sp)
    {
      list<int32>::iterator pos;
      pos=find(lendlist.begin(),lendlist.end(),sp);
      if (pos!=lendlist.end())
	{
	  lendlist.erase(pos,lendlist.end());
	  spielernummer=sp;
	  return;
	}
      cout << "tudinc.H: einheittype::takeback(): Player "<<sp<<" wants to take back unit but isn't owner\n";
    }
  void giveback()
    {
      if (!lendlist.empty())
	{
	  list<int32>::reverse_iterator pos=lendlist.rbegin();
	  spielernummer=*pos;
	  lendlist.pop_back();
	}
    }
  bool is_owner(int32 sp)
    {
      list<int32>::iterator pos;
      pos=find(lendlist.begin(),lendlist.end(),sp);
      return (pos!=lendlist.end());
    }

  einheittype();
  einheittype(const char *_einheit_daten_dateiname,vektor2_koordtype *_pos, int32 _spielernummer,
			 float _einheitdir,int32 _einheitnummer);
  virtual ~einheittype();

  void setmode(changemodetype _changemode)
  {changemode=_changemode;}
  changemodetype getmode()
  {return changemode;}
private:
  changemodetype changemode;
  void init();
  void deinit();
  float fuel;
};


// Die Firma **********************************************************************
// Die Firma **********************************************************************
// Die Firma **********************************************************************

/// dynamical data of factory
class firmatype : public virtual einheittype
{
public:  
  // Typeinfo - Achtung statisch wird nicht vererbt !!! =>benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  firma_datentype *firma_datenptr; // eigentlich das selbe wie der einheit_datenptr

  firmatype();
  firmatype(const char *_panzer_daten_dateiname,vektor2_koordtype *_pos,
	    int32 _spielernummer,float _einheitdir,int32 _einheitnummer);

  // Time until object is build 
  float countdown;

  // Welche Einheit soll gebaut werden
  string tobuild;
  // Welcher Art ist diese Einheit (none => nicht bauen)
  string typeof_tobuild;

  void eingabechange(iotype *,int8){}

  // todo fehler an change ist dass der firma_datentype sich im Spiel 
  //nicht aendern darf s.h. auch panzertype !!
  void change_intern(iotype *ioptr,int8 mode);

  // Zeit ausrechnen um die ausgewaehlte Einheit zu bauen
  float time_tobuild();

  // Is this factory building something ?
  bool building()
    {
      return (typeof_tobuild!="none");
    }
  
  kettetype<string_zeigerelemtype> *akt_buildable_objekts();
  kettetype<string_zeigerelemtype> *akt_buildable_vehicles();


private:
  // Wird beim laden aufgerufen !!
  void einheit_datenptr_to_firma_datenptr();
};


// Eingabedaten ***************************************************************
// Eingabedaten ***************************************************************
// Eingabedaten ***************************************************************
    
// Input Data of vehicles (panzertype)
class eingabetype
{
public:
  // pedal
  float gas;
  // steering
  float drehen;
  // autodrive mode (0=off 1=waypoint drive 2=Follow 3=Follow formation)
  int16 autodrive;
  // list of waypoints
  vektor2_koord_kettetype autodriveto_kette;
  // aktive waypoint
  vektor2_koord_zeigerelemtype *autodrivetoptr;

  // follow this vehicle
  int32 autofollow_number;
  // min. distance to autofollow_number (normal follow mode)
  float autofollow_distance;
  // For Formation follow (rel. coords to autofollow_number
  vektor2_koordtype autofollow_relto;
  // This unit follows me
  int32 follower;
  
  // load and save
  void change(iotype *ioptr,int8 mode);
  // check the values 
  int checkbereich();
  // set standard values
  void init();

  eingabetype()
  {
    init();
  }
};

// Die Daten, die nur der Besitzer kennt ! ************************************
// Die Daten, die nur der Besitzer kennt ! ************************************
// Die Daten, die nur der Besitzer kennt ! ************************************

// Achtung wenn sie den Dateninhalt veraendern muessen Sie auch den change 
// aendern !!!

/// Datas only visible to the owner of a unit which is of type panzertype
class besitzerdatentype
{
public:
  // "not" important just the name of the unit f.e. "Enterprise"
  string fahrzeug_name; 
  // The input datas (acceleration, autoshot..)
  eingabetype eingabe; 
  // How long the unit didn't move 
  float standzeit; 
  // not yet implemented  
  float restminelegdauer; 
  // load and save	
  void change(iotype *ioptr,int8 mode); 
  // set default values
  void init(); 
};



// Dynamische canondaten  ****************************************************
// Dynamische canondaten  ****************************************************
// Dynamische canondaten  ****************************************************

/// Base type for List of canons (weapons)
class canon_kette_basetype
{
public:
  // Shoot at this vehicle if possible
  int32 priorityaim;
  // Shoot at all enemies 
  int16 autoaim;   
};

/// Dynamic data of canons (weapons)
class canontype 
{
public:
  ///short informations
  // direction of canon relative to the unit
  float relturmdir;  

  ///detailed informations
  // horizontal direction of canon
  float dirhorizon; 
  // time left to load the canon
  float restladedauer; 
  // active aim
  int32 shotat_number; 
  // Type of automatic shot 1=priority autoshoot 2=normal autoshoot
  int autoshot; 

  /// input
  // turn canon
  float turmdrehen; 
  // turn canon horizontally
  float turmfahren; 
  // shoot
  int16 schiessen;  

  canontype(canon_datentype *_canon_datenptr, canon_kette_basetype *_canon_kette_baseptr,einheittype *_einheitptr) : canon_datenptr(_canon_datenptr) , canon_kette_baseptr(_canon_kette_baseptr), einheitptr(_einheitptr)
  {
    ammoptr=einheitptr->objekt_kette.get_or_create(canon_datenptr->ammoname.c_str());
    ammo_datenptr=ammoptr->objekt_datenptr->cast_ammo_datentype();
  }
  // load and save
  void change(iotype *ioptr,int8 mode); 
  // check the canon directions 
  void chkturmdirbereich(); 
  // check input data for corectness
  int checkbereich(); 
  // Calculate the psotion of the canon
  void calc_aktturmpos(vektor2_koordtype &erg); 
  // Maximum Shot Distance +10%
  float maxreichweite(); 

protected:
  // Pointer to "statical" canon data
  canon_datentype *canon_datenptr; 
  // Pointer to the canon list
  canon_kette_basetype *canon_kette_baseptr; 
  // Pointer to unit (the canon is placed on)
  einheittype *einheitptr; 
  // Pointer to ammuntion to use
  objekt_zeigerelemtype *ammoptr;
  // Pointer to data of ammo to use 
  ammo_datentype *ammo_datenptr; 
};

/// List of Canons (one unit may have many canons
template <class objtype>
class canon_kettetype : public canon_kette_basetype, public kettetype<objtype>
{
public:
  void change(iotype *ioptr,int8 mode,
	      canon_daten_kettetype *canon_daten_ketteptr, einheittype *_einheitptr)
  {
    if (ioptr->getmode()==IOTYPE_READ_MODE)
      clear();
    int32 toload;
    if (ioptr->getmode()==IOTYPE_WRITE_MODE)
	toload=anzzeigerelem;
    
    // Elementanzahl changen !
    cfgtype *cfgptr=choose_cfgtype(ioptr,mode);
    cfgptr->change_int32_check(&toload);
    delete cfgptr;

    if (toload!=canon_daten_ketteptr->anzzeigerelem)
      fatalfehler("canon_kettetype::change: a vehicle has more canons than data is stored for it\n");

    // LADEN ******************************************************************
    if (ioptr->getmode()==IOTYPE_READ_MODE)
	{
	  canon_datentype *aktdat=canon_daten_ketteptr->anfang->next;
	  while (toload)
	    {
	      objtype *akt=objtype::create(ioptr,mode,aktdat,this,_einheitptr);
	      zeiger_push(akt);
	      toload--;
	      aktdat=aktdat->next;
	    }
	  return;
	}
    // SPEICHERN **************************************************************
    iteratortype laufzeiger=anfang->next;
    while (laufzeiger!=ende)
	{
	    laufzeiger->change(ioptr,mode);
	    laufzeiger=laufzeiger->next;
	}
  }
};


// Dynamische Panzerdaten  ****************************************************
// Dynamische Panzerdaten  ****************************************************
// Dynamische Panzerdaten  ****************************************************

/// Dynamic tank data 
class panzertype : public virtual einheittype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! =>benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  // Datas only visible to the owner of this unit
  besitzerdatentype besitz;
  // pointer to the "statical" data
  panzer_datentype *panzer_datenptr; 
protected:
  panzertype();
  panzertype(const char *_panzer_daten_dateiname,vektor2_koordtype *_pos,
	     int32 _spielernummer,float _einheitdir,int32 _einheitnummer);
  virtual ~panzertype();
  // load save
  void change_intern(iotype *ioptr,int8 mode); 

  // How long the unit didn't move ?
  float get_standzeit()
  {
    return besitz.standzeit;
  }

  // todo ??  void setmaxbereich();

  void eingabechange(iotype *ioptr,int8 mode)
  {
    besitz.eingabe.change(ioptr,mode);
  }

private:
  // Checked type cast (should use dynamic_cast<> as soon as possible)
  void einheit_datenptr_to_panzer_datenptr();
};



// Schussobjekt **************************************************************
// Schussobjekt **************************************************************
// Schussobjekt **************************************************************

/// A shot
class schusstype
{
public:
  // Position
  vektor2_koordtype pos;
  // Direction
  float dir;
  // Speed
  float speed;
  // Time until explusion
  float restzeit;
  // Destroy value
  float muehexplosion;
  // Destroy circle
  float explosionsradius;
  // Sound name
  string sound;

  schusstype();
  //  schusstype(iotype *ioptr,int8 mode);
  //  ~schusstype();
  
  //load save
  void change(iotype *ioptr,int8 mode);
private:
};

// Explosionsobjekt **********************************************************
// Explosionsobjekt **********************************************************
// Explosionsobjekt **********************************************************

/// A Explusion
class explosionstype
{
public:
  // Postion
  vektor2_koordtype pos;
  // Destroy value
  float muehexplosion;
  // Destroy circle
  float explosionsradius;
  // Sound name
  string sound;
  explosionstype();
  // load save
  void change(iotype *ioptr,int8 mode);
private:
};







// ***************************************************************** Landschaft
// ***************************************************************** Landschaft
// ***************************************************************** Landschaft

/// Landscape data
class landschafttype{
public:
  // Filename
  string name;
  // How many meters is one dot ?
  float massstab;
  // Gravity
  float gravity;
  // The landscape sprite
  string spritename;
  // Pointer to the landscape sprite
  spritetype *landspriteptr;
    
  landschafttype(const char *n);
  ~landschafttype();
  // load and save
  void change(iotype *ioptr,int8 mode);
};



// Kommunikation *****************************************************************************
// Kommunikation *****************************************************************************
// Kommunikation *****************************************************************************
// Kommunikation *****************************************************************************

/// Eventmask
class eventmasktype
{
public:
  // Send explosions
  int16 explosions;
  // Send playlist changes
  int16 playerlist;
  eventmasktype();
  // load save (send recv)
  void change(iotype *ioptr,int8 mode);
};

/// Tud Protocol class 
class tud_streamtype : public communication_streamtype
{
public:
  tud_streamtype(){}
  tud_streamtype(verbindungstype *verbindung) : communication_streamtype(verbindung){}
  
  // Send Message
  void send_stream_msg(const string& str);
  // Parse message
  void verarbeite_stream_msg(char *msg,int32 laenge);
};






/******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************

         D I E   G L O B A L E N   T Y P E N   D E S   M O D U L E S

*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
******************************************************************************/

#define REQ_SPIELERANZ_MSG       101 //OK    Client->Server
#define SEND_SPIELERANZ_MSG      102 //OK    Server->client

#define REQ_SPIELERDATEI_MSG     103 //OK    Client->Server

#define REQ_SPIELERPLATZ_MSG     104 //OK    Client->Server
#define DENY_SPIELERPLATZ_MSG    105 //OK    Server->client
#define GIVE_SPIELERPLATZ_MSG    106 //OK    Server->client

#define REQ_LANDSNAME_MSG        107 //OK    Client->Server
#define LANDSNAME_MSG            108 //OK    Server->Client

#define REQ_PANZER_KETTE_MSG     109 //OK    Client->Server
#define SEND_PANZER_KETTE_MSG    110 //OK    Server->Client

#define SEND_EINGABE_MSG         111 //OK    Client->Server

#define SEND_PING_MSG            112 //OK    Client<->Server

#define SEND_EXPLOSION_KETTE_MSG 113 // OK   Server->Client
#define SEND_EVENTMASK_MSG       114 // OK   Client->Server

#define REQ_SPIELER_KETTE_MSG    115
#define SEND_SPIELER_KETTE_MSG   116

#define REQ_FREESPIELERDATEI_MSG  117 //      Client->Server
#define SEND_FREESPIELERDATEI_MSG 118 //      Server->Client

#define REQ_FREESPIELERPLATZ_MSG  119 //      Client->Server
#define SEND_FREESPIELERPLATZ_MSG 120 //      Server->Client

#define SEND_STREAM_MSG           121 //      Client<->Server


// Taktlaenge
extern float deltati;

extern landschafttype *landscapeptr;
extern spieler_kettetype *spieler_ketteptr;
extern einheit_daten_kette_iqtype *einheit_daten_ketteptr;
extern objekt_daten_kette_iqtype *objekt_daten_ketteptr;
extern untergrundtabtype *untergrundtabptr;

#endif











