Spiel.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. #include "Spiel.h"
  2. #define TICK 0.03333333
  3. // Konstruktor
  4. Spiel::Spiel()
  5. {
  6. nextId = 0;
  7. isRunning = 0;
  8. log = 0;
  9. spielerAnzahl = 0;
  10. zAccounts = 0;
  11. spielId = 0;
  12. karteId = 0;
  13. pause = 0;
  14. gameTicks = 0;
  15. ende = 1;
  16. stat = new Statistik();
  17. ref = 1;
  18. }
  19. // Destruktor
  20. Spiel::~Spiel()
  21. {
  22. stat->release();
  23. if( psqldb )
  24. psqldb->release();
  25. }
  26. // nicht constant
  27. void Spiel::setPSQLK( SSDatenbankV *psqldb )
  28. {
  29. if( this->psqldb )
  30. this->psqldb->release();
  31. this->psqldb = psqldb;
  32. stat->setPSQLDB( psqldb->getThis() );
  33. }
  34. // call 1
  35. void Spiel::setSpielId( int id )
  36. {
  37. spielId = id;
  38. stat->setSpielId( id );
  39. }
  40. // call 2
  41. void Spiel::setKarteId( int karteId )
  42. {
  43. this->karteId = karteId;
  44. stat->setKarteId( karteId );
  45. }
  46. // call 3
  47. void Spiel::setTempPfad( char *pfad )
  48. {
  49. mapPfad = pfad;
  50. mapPfad += "/";
  51. }
  52. // call 3.5
  53. void Spiel::setAccounts( int anzahl, Array< int > *zAccounts )
  54. {
  55. this->zAccounts = zAccounts->getThis();
  56. spielerAnzahl = anzahl;
  57. }
  58. // call 4
  59. void Spiel::setKlients( int anzahl, RCArray< SSKlientV > *zKlients )
  60. {
  61. this->zKlients = zKlients->getThis();
  62. }
  63. // call 5
  64. void Spiel::setSpielerNummern( int anzahl, Array< int > *spielerNummern )
  65. {
  66. MapReader *reader = new MapReader( karteId, psqldb->getThis(), mapPfad );
  67. reader->ladeKarte( this );
  68. reader->release();
  69. for( int i = 0; i < anzahl; i++ )
  70. {
  71. for( auto s = spieler.getIterator(); s; s++ )
  72. {
  73. if( s->getSpielerNummer() == spielerNummern->get( i ) )
  74. {
  75. s->setAccount( zAccounts->get( i ) );
  76. s->setKlient( new Klient( zKlients->get( i ) ) );
  77. break;
  78. }
  79. }
  80. }
  81. zAccounts = zAccounts->release();
  82. zKlients = zKlients->release();
  83. stat->setTeams( spielerAnzahl, &teams );
  84. stat->setSpieler( spielerAnzahl, &spieler );
  85. }
  86. // call 6
  87. void Spiel::run()
  88. {
  89. log = new Datei();
  90. Text *pfad = new Text( "../spiel log/" );
  91. pfad->append( spielId );
  92. pfad->append( "/verlauf.ksggl" );
  93. log->setDatei( pfad );
  94. log->remove();
  95. log->erstellen();
  96. log->open( Datei::Style::schreiben );
  97. time_t t;
  98. time( &t );
  99. srand( (unsigned int)t );
  100. log->schreibe( (char *)& spielerAnzahl, 4 );
  101. for( int i = 0; i < spielerAnzahl; i++ )
  102. {
  103. Spieler *tmp = spieler.z( i );
  104. if( tmp && tmp->zKlient() )
  105. {
  106. tmp->zKlient()->sendeInit( &spieler, -1 );
  107. log->schreibe( (char *)& i, 4 );
  108. int sNum = tmp->getSpielerNummer();
  109. log->schreibe( (char *)& sNum, 4 );
  110. tmp->zKlient()->sendeSpielerNummer( sNum, -1 );
  111. Text * name = psqldb->getAccountRufName( tmp->getAccountId() );
  112. char len = (char)( name ? name->getLength() : 0 );
  113. log->schreibe( &len, 1 );
  114. if( len )
  115. log->schreibe( name->getText(), len );
  116. if( name )
  117. name->release();
  118. }
  119. }
  120. __int64 randSeed = randG.getSeed();
  121. log->schreibe( (char *)& randSeed, 8 );
  122. Array< char > spielerStatus;
  123. ZeitMesser * zeit = new ZeitMesser();
  124. zeit->messungStart();
  125. isRunning = 1;
  126. ende = 0;
  127. double ausgleich = 0;
  128. double sZ = 0;
  129. gameTicks = -1;
  130. for( int i = 0; i < spielerAnzahl; i++ )
  131. {
  132. Spieler *tmp = spieler.z( i );
  133. if( tmp && tmp->zKlient() )
  134. tmp->zKlient()->sendeStart( gameTicks );
  135. }
  136. throwEvent( new Ereignis( INITIALISIERUNG ) );
  137. double rZeit = 0;
  138. while( !ende )
  139. {
  140. zeit->messungEnde();
  141. zeit->messungStart();
  142. double z = zeit->getSekunden();
  143. ausgleich += TICK - z;
  144. if( ausgleich > 0 )
  145. Sleep( (int)( ausgleich * 1000 ) );
  146. rZeit += z;
  147. while( sZ + TICK < rZeit && !ende )
  148. {
  149. c.lock();
  150. sZ += TICK;
  151. gameTicks++;
  152. char ch = 0;
  153. log->schreibe( &ch, 1 );
  154. tick( TICK );
  155. c.unlock();
  156. }
  157. }
  158. zeit->messungEnde();
  159. zeit->release();
  160. for( int i = 0; i < spielerAnzahl; i++ )
  161. {
  162. if( spieler.z( i ) && spieler.z( i )->zKlient() )
  163. {
  164. if( !spieler.z( i )->zTeam()->getPunkte() )
  165. {
  166. spielerStatus.set( 1, i ); // Datenbank Verloren
  167. spieler.z( i )->zKlient()->sendeSpielEnde( 0, 0 );
  168. }
  169. else
  170. {
  171. spielerStatus.set( 2, i ); // Datenbank Gewonnen
  172. spieler.z( i )->zKlient()->sendeSpielEnde( 1, 0 );
  173. }
  174. }
  175. if( spieler.z( i ) && ( !spieler.z( i )->zKlient() || !spieler.z( i )->zKlient()->istOnline() ) )
  176. spielerStatus.set( 3, i );
  177. }
  178. psqldb->setSpielStatusBeendet( spielId, 5 );
  179. for( int i = 0; i < spielerAnzahl; i++ )
  180. {
  181. Spieler *tmp = spieler.z( i );
  182. if( tmp )
  183. {
  184. psqldb->setSpielSpielerStatus( spielId, tmp->getAccountId(), tmp->getPunkte(), spielerStatus.get( i ) );
  185. psqldb->addSpielerStatistik( tmp->getAccountId(), spielId );
  186. }
  187. }
  188. log->close();
  189. log = log->release();
  190. isRunning = 0;
  191. }
  192. // call 7
  193. void Spiel::klientOffline( int accountId )
  194. {
  195. for( int i = 0; i < spielerAnzahl; i++ )
  196. {
  197. if( spieler.z( i )->getAccountId() == accountId )
  198. spieler.z( i )->zKlient()->offline();
  199. }
  200. }
  201. void Spiel::klientOnline( int accountId, SSKlientV * zKlient )
  202. {
  203. for( int i = 0; i < spielerAnzahl; i++ )
  204. {
  205. if( spieler.z( i )->getAccountId() == accountId )
  206. {
  207. c.lock();
  208. Spieler *s = spieler.z( i );
  209. Klient *tmp = s->zKlient();
  210. tmp->online( zKlient );
  211. tmp->sendeSpielerNummer( s->getSpielerNummer(), 0 );
  212. //--------------------------
  213. c.unlock();
  214. }
  215. }
  216. }
  217. void Spiel::nachricht( int accountId, int len, char *bytes )
  218. {
  219. if( !isRunning )
  220. return;
  221. c.lock();
  222. if( ende )
  223. {
  224. c.unlock();
  225. return;
  226. }
  227. char *msgBeg = bytes;
  228. int msgLen = len;
  229. int msgAccount = accountId;
  230. bool saveMSG = 1;
  231. len--;
  232. switch( *bytes )
  233. {
  234. case 0: // key press
  235. bytes++;
  236. len--;
  237. for( int i = 0; i < spielerAnzahl; i++ )
  238. {
  239. Spieler *tmp = spieler.z( i );
  240. if( tmp && tmp->getAccountId() == accountId )
  241. {
  242. if( !tmp->setTastenStand( *bytes, 1 ) )
  243. {
  244. saveMSG = 0;
  245. break;
  246. }
  247. Ereignis *e = new Ereignis( SPIELER_KEY_PRESSED );
  248. char buff[] = { *bytes, 0 };
  249. e->addParameter( "Betroffene Taste", new String( buff ) );
  250. e->addParameter( "Ausführender Spieler", tmp->getThis() );
  251. throwEvent( e );
  252. for( int j = 0; j < spielerAnzahl; j++ )
  253. {
  254. Spieler *s = spieler.z( j );
  255. if( s && s->zKlient() )
  256. s->zKlient()->sendeTastaturStatus( tmp->getSpielerNummer(), *bytes, 1, gameTicks );
  257. }
  258. break;
  259. }
  260. }
  261. break;
  262. case 1: // key release
  263. bytes++;
  264. len--;
  265. for( int i = 0; i < spielerAnzahl; i++ )
  266. {
  267. Spieler *tmp = spieler.z( i );
  268. if( tmp && tmp->getAccountId() == accountId )
  269. {
  270. if( !tmp->setTastenStand( *bytes, 0 ) )
  271. {
  272. saveMSG = 0;
  273. break;
  274. }
  275. Ereignis *e = new Ereignis( SPIELER_KEY_RELEASED );
  276. char buff[] = { *bytes, 0 };
  277. e->addParameter( "Betroffene Taste", new String( buff ) );
  278. e->addParameter( "Ausführender Spieler", tmp->getThis() );
  279. throwEvent( e );
  280. for( int j = 0; j < spielerAnzahl; j++ )
  281. {
  282. Spieler *s = spieler.z( j );
  283. if( s && s->zKlient() )
  284. s->zKlient()->sendeTastaturStatus( tmp->getSpielerNummer(), *bytes, 0, gameTicks );
  285. }
  286. break;
  287. }
  288. }
  289. break;
  290. case 3: // chat Nachricht
  291. if( 1 )
  292. {
  293. bytes++;
  294. Text *txt = psqldb->getAccountRufName( accountId );
  295. txt->append( ": " );
  296. txt->append( bytes, len );
  297. for( int i = 0; i < spielerAnzahl; i++ )
  298. {
  299. Spieler *tmp = spieler.z( i );
  300. if( tmp && tmp->zKlient() )
  301. tmp->zKlient()->sendeChatNachricht( txt->getText(), gameTicks );
  302. }
  303. txt->release();
  304. len = 0;
  305. }
  306. break;
  307. default:
  308. saveMSG = 0;
  309. }
  310. if( len )
  311. {
  312. // error
  313. }
  314. if( log && log->istOffen() && saveMSG )
  315. {
  316. char c = 1;
  317. log->schreibe( &c, 1 );
  318. int spielerNum = 0;
  319. for( int i = 0; i < spielerAnzahl; i++ )
  320. {
  321. Spieler *tmp = spieler.z( i );
  322. if( tmp && tmp->getAccountId() == msgAccount )
  323. {
  324. spielerNum = tmp->getSpielerNummer();
  325. break;
  326. }
  327. }
  328. log->schreibe( (char *)& spielerNum, 4 );
  329. short l = (short)msgLen;
  330. log->schreibe( (char *)& l, 2 );
  331. log->schreibe( msgBeg, l );
  332. }
  333. c.unlock();
  334. }
  335. void Spiel::setPausiert( bool pausiert )
  336. {
  337. this->pause = pausiert;
  338. }
  339. void Spiel::tick( double zeit )
  340. {
  341. // spieler bewegungen
  342. for( auto s = spieler.getIterator(); s; s++ )
  343. {
  344. s->tick( zeit );
  345. if( s->getX() < 0 || s->getY() < 0 || s->getX() + s->getWidth() >= mapSize.x || s->getY() + s->getHeight() >= mapSize.y )
  346. s->tick( -zeit );
  347. else
  348. {
  349. for( auto b = barieren.getIterator(); b; b++ )
  350. { // spieler - bariere intersection
  351. if( b->hatStyle( Bariere::Style::Aktiv ) && ( b->zTeam() != s->zTeam() ) && b->intersectsWith( s ) )
  352. s->tick( -zeit );
  353. }
  354. }
  355. }
  356. // barieren bewegung
  357. for( auto b = barieren.getIterator(); b; b++ )
  358. b->tick( zeit );
  359. // geschoss bewegung
  360. for( int i = 0; i < shots.getEintragAnzahl(); i++ )
  361. {
  362. Geschoss *g = shots.z( i );
  363. g->tick( zeit );
  364. bool removed = 0;
  365. // geschoss - bariere intersection
  366. bool intersectsWithBariere = 0;
  367. for( auto b = barieren.getIterator(); b; b++ )
  368. {
  369. if( b->hatStyle( Bariere::Style::Aktiv ) && b->intersectsWith( g ) )
  370. {
  371. intersectsWithBariere = 1;
  372. break;
  373. }
  374. }
  375. if( intersectsWithBariere || g->getX() < 0 || g->getY() < 0 || g->getX() + g->getWidth() >= mapSize.x || g->getY() + g->getHeight() >= mapSize.y )
  376. {
  377. g->tick( -zeit );
  378. switch( g->getTyp() )
  379. {
  380. case GESCHOSS_PFEIL:
  381. shots.remove( i );
  382. i--;
  383. removed = 1;
  384. break;
  385. case GESCHOSS_KUGEL:
  386. case GESCHOSS_DRACHENAUGE:
  387. g->invertDirection();
  388. break;
  389. case GESCHOSS_FEUERBALL:
  390. if( intersectsWithBariere )
  391. {
  392. feuer.add( new FeuerballTreffer( ++nextId, g->getX() - 70, g->getY() - 70, g->getBesitzer(), 10 ) );
  393. shots.remove( i );
  394. i--;
  395. removed = 1;
  396. }
  397. else
  398. g->invertDirection();
  399. break;
  400. }
  401. }
  402. if( !removed )
  403. { // geschoss - tunnel intersection
  404. for( auto t = tunnel.getIterator(); t; t++ )
  405. {
  406. if( t->istAktiv() && t->intersectsWith( g ) )
  407. {
  408. Ereignis *e = new Ereignis( TUNNEL_BENUTZT );
  409. e->addParameter( "Betroffes Geschoss", g->getThis() );
  410. e->addParameter( "Betroffer Tunnel", t->getThis() );
  411. throwEvent( e );
  412. g->setX( g->getX() + t->getZielX() - t->getX() );
  413. g->setY( g->getY() + t->getZielY() - t->getY() );
  414. }
  415. }
  416. // geschoss - schalter intersection
  417. if( g->getTyp() == GESCHOSS_PFEIL )
  418. {
  419. for( auto s = schalter.getIterator(); s; s++ )
  420. {
  421. if( s->isAktive() && s->intersectsWith( g ) )
  422. {
  423. shots.remove( i );
  424. i--;
  425. removed = 1;
  426. activateShalter( s->getId() );
  427. }
  428. }
  429. }
  430. if( !removed )
  431. {
  432. // geschoss - umlenkung intersection
  433. if( g->getTyp() != GESCHOSS_PFEIL )
  434. {
  435. for( auto u = umlenkungen.getIterator(); u; u++ )
  436. {
  437. if( u->isAktive() && !u->hatAbklingzeit() && g->getTyp() != GESCHOSS_PFEIL && u->intersectsWith( g ) )
  438. {
  439. Ereignis *e = new Ereignis( UMLENKUNG_LENKT_UM );
  440. e->addParameter( "Betroffes Geschoss", g->getThis() );
  441. e->addParameter( "Betroffe Umlenkung", u->getThis() );
  442. throwEvent( e );
  443. g->setRichtung( u->getRichtung() );
  444. u->addBenutzt();
  445. }
  446. }
  447. }
  448. // geschoss - spieler intersection
  449. for( auto s = spieler.getIterator(); s; s++ )
  450. {
  451. if( s->istAmLeben() && s != g->zBesitzer() )
  452. {
  453. switch( g->getTyp() )
  454. {
  455. case GESCHOSS_PFEIL:
  456. case GESCHOSS_KUGEL:
  457. {
  458. double schaden = 100 + ( g->zBesitzer() ? g->zBesitzer()->getSchadenBonus() : 0 );
  459. s->nimmSchaden( schaden );
  460. if( g->zBesitzer() )
  461. {
  462. g->zBesitzer()->addGemachterSchaden( schaden );
  463. if( !s->istAmLeben() )
  464. g->zBesitzer()->addKill();
  465. }
  466. break;
  467. }
  468. case GESCHOSS_DRACHENAUGE:
  469. s->addEffekt( new DrachenAugeEffekt( g->zBesitzer(), s._, 10 ) );
  470. break;
  471. case GESCHOSS_FEUERBALL:
  472. feuer.add( new FeuerballTreffer( ++nextId, g->getX() - 70, g->getY() - 70, g->getBesitzer(), 10 ) );
  473. }
  474. if( g->zBesitzer() )
  475. g->zBesitzer()->addTreffer();
  476. s->addGetroffen();
  477. shots.remove( i );
  478. i--;
  479. removed = 1;
  480. }
  481. }
  482. }
  483. }
  484. }
  485. // Drop Ticks
  486. for( auto d = drops.getIterator(); d; d++ )
  487. d->tick( zeit, this );
  488. // Timer Ticks
  489. for( auto t = timer.getIterator(); t; t++ )
  490. t->tick( zeit, this );
  491. // Umlenkung Ticks
  492. for( auto u = umlenkungen.getIterator(); u; u++ )
  493. u->tick( zeit );
  494. // Base Ticks
  495. for( auto b = basen.getIterator(); b; b++ )
  496. b->tick( zeit, this );
  497. // aktive trigger Ticks
  498. for( int i = 0; i < triggerRuns.getEintragAnzahl(); i++ )
  499. {
  500. if( !triggerRuns.z( i )->runNext( zeit ) )
  501. {
  502. Ereignis *e = new Ereignis( AUSLOESER_RUNNED );
  503. e->addParameter( "Betroffener Auslöser", triggerRuns.z( i )->getTrigger() );
  504. throwEvent( e );
  505. triggerRuns.remove( i );
  506. i--;
  507. }
  508. }
  509. }
  510. void Spiel::addVariable( const char *name, Variable * var )
  511. {
  512. bool found = 0;
  513. for( auto v = variablen.getIterator(); v; v++ )
  514. {
  515. if( v->zName()->istGleich( name ) )
  516. {
  517. found = 1;
  518. break;
  519. }
  520. }
  521. if( !found )
  522. variablen.add( new VarPointer( name, var ) );
  523. else
  524. var->release();
  525. }
  526. void Spiel::setVariable( const char *name, Variable * var )
  527. {
  528. bool found = 0;
  529. for( auto v = variablen.getIterator(); v; v++ )
  530. {
  531. if( v->zName()->istGleich( name ) )
  532. {
  533. v->setVariable( var );
  534. break;
  535. }
  536. }
  537. if( !found )
  538. var->release();
  539. }
  540. void Spiel::addTeam( Team * team )
  541. {
  542. teams.add( team );
  543. }
  544. void Spiel::addSpieler( Spieler * spieler )
  545. {
  546. this->spieler.add( spieler );
  547. }
  548. void Spiel::addBariere( Bariere * bariere )
  549. {
  550. barieren.add( bariere );
  551. }
  552. void Spiel::addBase( Base * base )
  553. {
  554. basen.add( base );
  555. }
  556. void Spiel::addDrop( Drop * drop )
  557. {
  558. drops.add( drop );
  559. }
  560. void Spiel::addGegenstand( Gegenstand * gegenstand )
  561. {
  562. items.add( gegenstand );
  563. }
  564. void Spiel::addGeschoss( Geschoss * geschoss )
  565. {
  566. shots.add( geschoss );
  567. }
  568. void Spiel::addSchalter( Schalter * schalter )
  569. {
  570. this->schalter.add( schalter );
  571. }
  572. void Spiel::addSchiene( Schiene * schiene )
  573. {
  574. schienen.add( schiene );
  575. }
  576. void Spiel::addTimer( Timer * timer )
  577. {
  578. this->timer.add( timer );
  579. }
  580. void Spiel::addTunnel( Tunnel * tunnel )
  581. {
  582. this->tunnel.add( tunnel );
  583. }
  584. void Spiel::addUmlenkung( Umlenkung * umlenkung )
  585. {
  586. umlenkungen.add( umlenkung );
  587. }
  588. void Spiel::addTrigger( Trigger * trigger )
  589. {
  590. this->trigger.add( trigger );
  591. }
  592. void Spiel::addTriggerRun( TriggerRun * tRun )
  593. {
  594. triggerRuns.add( tRun );
  595. }
  596. Team *Spiel::getTeam( int id ) const
  597. {
  598. for( auto t = teams.getIterator(); t; t++ )
  599. {
  600. if( t->getTeamNummer() == id )
  601. return (Team *)t->getThis();
  602. }
  603. return 0;
  604. }
  605. Variable *Spiel::getVariable( const char *name ) const
  606. {
  607. for( auto v = variablen.getIterator(); v; v++ )
  608. {
  609. if( v->zName()->istGleich( name ) )
  610. return v->getVariable();
  611. }
  612. return 0;
  613. }
  614. Variable *Spiel::zVariable( const char *name ) const
  615. {
  616. for( auto v = variablen.getIterator(); v; v++ )
  617. {
  618. if( v->zName()->istGleich( name ) )
  619. return v->zVariable();
  620. }
  621. return 0;
  622. }
  623. bool Spiel::istPausiert() const
  624. {
  625. return pause;
  626. }
  627. void Spiel::activateShalter( int id )
  628. {
  629. for( auto s = schalter.getIterator(); s; s++ )
  630. {
  631. if( s->getId() == id )
  632. {
  633. Ereignis *e = new Ereignis( SCHALTER_AKTIVIERT );
  634. e->addParameter( "Betroffener Schalter", s->getThis() );
  635. throwEvent( e );
  636. }
  637. }
  638. }
  639. void Spiel::throwEvent( Ereignis *e )
  640. {
  641. for( auto t = trigger.getIterator(); t; t++ )
  642. {
  643. if( t->hatEreignis( e->getTyp() ) )
  644. triggerRuns.add( t->runTrigger( e->getThis(), this ) );
  645. }
  646. e->release();
  647. }
  648. bool Spiel::needEvent( EreignisTyp typ ) const
  649. {
  650. for( auto t = trigger.getIterator(); t; t++ )
  651. {
  652. if( t->hatEreignis( typ ) )
  653. return 1;
  654. }
  655. return 0;
  656. }
  657. int Spiel::getNextId()
  658. {
  659. return ++nextId;
  660. }
  661. StatistikV *Spiel::getStatistik() const
  662. {
  663. return stat->getThis();
  664. }
  665. // Reference Counting
  666. SpielKlasse *Spiel::getThis()
  667. {
  668. ref++;
  669. return this;
  670. }
  671. SpielKlasse *Spiel::release()
  672. {
  673. if( !--ref )
  674. delete this;
  675. return 0;
  676. }