4
** Copyright (c) 1993-2001 by Hans-Ulrich Kiel & Joerg Czeranski
5
** All rights reserved.
7
** Redistribution and use in source and binary forms, with or without
8
** modification, are permitted provided that the following conditions are
11
** 1. Redistributions of source code must retain the above copyright
12
** notice, this list of conditions and the following disclaimer.
13
** 2. Redistributions in binary form must reproduce the above copyright
14
** notice, this list of conditions and the following disclaimer in the
15
** documentation and/or other materials provided with the distribution.
16
** 3. The name of the authors may not be used to endorse or promote
17
** products derived from this software without specific prior written
19
** 4. The name ``iMaze'' may not be used for products derived from this
20
** software unless a prefix or a suffix is added to the name.
22
** THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
23
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
** DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
26
** INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30
** STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
31
** IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
** POSSIBILITY OF SUCH DAMAGE.
39
** und die Routinen, die Netzwerk, 3D-Berechnung und Grafik verbinden
52
#include "labyrinth.h"
57
#include "ereignisse.h"
63
static char sccsid[] = "@(#)client.c 3.20 12/3/01";
66
struct arg_option argv_opts[] =
68
{ Arg_Include, NULL, net_opts },
69
{ Arg_Include, NULL, einaus_opts },
74
/* Breite und Laenge des aktuellen Spielfeldes: */
75
u_int feldbreite, feldlaenge;
76
block **spielfeld; /* das Spielfeld */
77
block **feld_himricht[4]; /* das Spielfeld, in 4 Richtungen gedreht */
79
static int puffer_nr = 0; /* Index auf Spieldaten-Puffer
80
(welcher zuletzt gelesen wurde) */
81
static int puffer_gueltig = 0; /* Index auf Spieldaten-Puffer
82
(welcher zuletzt beschrieben wurde) */
84
/* die Spieldaten werden in einem Doppelpuffer gespeichert;
85
einer kann gelesen, der andere beschrieben werden */
87
static int spieler_aktiv[2]; /* der Spieler selbst ist im Spiel */
88
static int schuss_aktiv[2]; /* der Spieler selbst hat einen Schuss im
90
static int gegneranz[2]; /* Anzahl der aktuell sichtbaren Mitspieler */
91
static int schussanz[2]; /* Anzahl der sichtbaren Mitspieler-Schuesse */
92
static int abgeschossen_durch[2]; /* Farbe des Spielers, von dem man
94
static char *abschuss_spruch[2] = { NULL, NULL }; /* Spruch des Spielers, von
98
/* Daten aller sichtbaren Spieler und Schuesse (Position, Farbe, ...): */
99
static struct spieler alle_spieler[2][SPIELERANZ];
100
static struct schuss alle_schuesse[2][SPIELERANZ];
102
static int alle_punkte[2][SPIELERANZ]; /* Punktestand aller Spieler; -1 fuer
103
Spieler, die nicht existieren */
104
static char ereignisse[2][ERG_ANZ]; /* Ereignisse
105
(siehe ereignisse.h) */
106
static char ereignisse_uebrig[ERG_ANZ]; /* noch nicht verarbeitete
107
Ereignisse (temporaer) */
109
static int karteneu = 1; /* Flag, muss der Grundriss der Karte neu
110
gezeichnet werden? Dann alles andere auch. */
111
static int spieler_farbe = 0; /* letzte bekannte Farbe des eigenen Spielers,
114
/* Fehlermeldung und -knopf von milder_fehler (fuer milden_fehler_abfragen) */
115
static char **fehlermeldung = NULL, *fehlerknopf = NULL;
117
/* fuer das Verhindern ueberfluessigen Zeichnens */
118
static int alt_gueltig = 0;
119
static struct objektdaten alt_blick_vor, alt_blick_zurueck;
120
static int alt_spieler_index, alt_anzkreise;
121
static struct kartenkreis *alt_kreise;
122
static int alt_kompass;
123
static struct punktedaten alt_punkte;
128
** dreht das Spielfeld in 4 Richtungen (0, 90, 180, 270 Grad)
129
** (damit die Projektionen nur fuer Richtung Norden implementiert werden
133
** feld_himricht wird erzeugt
135
static void drehlab(void)
137
int i; /* Index ueber die 4 Richtungen */
138
int x, y; /* Index ueber Breite/Laenge des Spielfeldes */
140
/* Speicher fuer 4 Spielfelder anlegen */
141
/* bei ungeradem i Breite und Laenge tauschen */
142
for (i = 1; i < 4; i++)
143
speicher_belegen((void **)&feld_himricht[i],
144
(i % 2 ? feldlaenge : feldbreite) * sizeof(block *));
146
for (i = 1; i < 4; i++)
147
for (y = 0; y < (i % 2 ? feldlaenge : feldbreite); y++)
148
speicher_belegen((void **)&feld_himricht[i][y],
149
(i % 2 ? feldbreite : feldlaenge) * sizeof(block));
151
/* feld_himricht[0] wird nicht gedreht */
152
feld_himricht[0] = spielfeld;
154
/* feld_himricht[0] gedreht in feld_himricht[1,2,3] kopieren */
155
for (y = 0; y < feldlaenge; y++)
156
for (x = 0; x < feldbreite; x++)
157
/* NORD = 0, WEST = 1, SUED = 2, OST = 3 */
158
for (i = 0; i < 4; i++)
160
memcpy(&feld_himricht[1][feldlaenge - 1 - y]
162
&spielfeld[x][y][i], sizeof(struct wand));
163
memcpy(&feld_himricht[2][feldbreite - 1 - x]
164
[feldlaenge - 1 - y][(i + 2) % 4],
165
&spielfeld[x][y][i], sizeof(struct wand));
166
memcpy(&feld_himricht[3][y]
167
[feldbreite - 1 - x][(i + 1) % 4],
168
&spielfeld[x][y][i], sizeof(struct wand));
174
** objekt_listen_init
175
** Listen anlegen fuer die Grafikobjekte, die rechne3d berechnet
178
** objekte: Zeiger auf die Struktur, die die Listen enthaelt
181
** *objekte wird veraendert
183
static void objekt_listen_init(struct objektdaten *objekte)
185
/* Waende- und Kugelliste anlegen */
186
liste_initialisieren(&objekte->anzwaende, (void **)&objekte->waende);
187
liste_initialisieren(&objekte->anzkugeln, (void **)&objekte->kugeln);
189
/* Spruch des Gegners loeschen */
190
objekte->text = NULL;
195
** objekt_listen_freigeben
196
** gibt die Listen mit zu zeichnenden Grafikobjekten wieder frei
199
** objekte: Zeiger auf die Struktur, die die Listen enthaelt
201
static void objekt_listen_freigeben(struct objektdaten *objekte)
203
int i; /* Index fuer die Kugelliste */
205
liste_freigeben(&objekte->anzwaende, (void **)&objekte->waende);
207
/* Unterliste (Sichbarkeitsbereiche der Kugeln) freigeben */
208
for (i = 0; i < objekte->anzkugeln; i++)
209
liste_freigeben(&objekte->kugeln[i].sichtanz,
210
(void **)&objekte->kugeln[i].sichtbar);
211
liste_freigeben(&objekte->anzkugeln, (void **)&objekte->kugeln);
213
/* Speicher fuer Spruch des Gegners freigeben */
214
if (objekte->text != NULL)
215
speicher_freigeben((void **)&objekte->text);
221
** vergleicht zwei Punktestaende und gibt zurueck, in welcher Reihenfolge
222
** sie angezeigt werden sollen
225
** p1: Zeiger auf einen Punktestand
226
** p2: Zeiger auf anderen Punktestand
229
** < 0, falls Punktestand 1 vor Punktestand 2
231
** > 0, falls Punktestand 2 vor Punktestand 1
233
static int punkte_vergleich(const void *p1, const void *p2)
235
const struct punktestand *punkte1 = p1;
236
const struct punktestand *punkte2 = p2;
238
/* verschieden viele Punkte? */
239
if (punkte1->punkte != punkte2->punkte)
240
return punkte2->punkte - punkte1->punkte;
242
/* sonst nach Farbe sortieren */
243
return (int)punkte1->farbe - (int)punkte2->farbe;
247
static int flaechen_gleich(int n, struct flaeche *f1, struct flaeche *f2)
251
for (i = 0; i < n; i++)
253
for (j = 0; j < 4; j++)
254
if (f1->ecke[j].x != f2->ecke[j].x ||
255
f1->ecke[j].y != f2->ecke[j].y)
258
if (f1->farbe != f2->farbe || f1->tuer != f2->tuer)
269
static int kugeln_gleich(int n, struct kugel *k1, struct kugel *k2)
273
for (i = 0; i < n; i++)
275
struct ausschnitt *a1, *a2;
277
if (k1->mittelpunkt.x != k2->mittelpunkt.x ||
278
k1->mittelpunkt.y != k2->mittelpunkt.y)
281
if (k1->sichtanz != k2->sichtanz ||
282
k1->radiusx != k2->radiusx ||
283
k1->radiusy != k2->radiusy ||
284
k1->schatteny != k2->schatteny ||
285
k1->schattenry != k2->schattenry ||
286
k1->blick != k2->blick || k1->farbe != k2->farbe)
291
for (j = 0; j < k1->sichtanz; j++)
293
if (a1->x != a2->x || a1->breite != a2->breite)
308
static int objektdaten_gleich(struct objektdaten *o1, struct objektdaten *o2)
310
return o1->hintergrund_zeichnen == o2->hintergrund_zeichnen &&
311
o1->anzwaende== o2->anzwaende &&
312
o1->anzkugeln == o2->anzkugeln &&
313
(o1->text == NULL && o2->text == NULL ||
314
o1->text != NULL && o2->text != NULL &&
315
!strcmp(o1->text, o2->text)) &&
316
flaechen_gleich(o1->anzwaende, o1->waende, o2->waende) &&
317
kugeln_gleich(o1->anzkugeln, o1->kugeln, o2->kugeln);
321
static int kartenkreise_gleich(int n, struct kartenkreis *k1,
322
struct kartenkreis *k2)
326
for (i = 0; i < n; i++)
328
if (k1->mittelpunkt.x != k2->mittelpunkt.x ||
329
k1->mittelpunkt.y != k2->mittelpunkt.y ||
330
k1->radiusx != k2->radiusx ||
331
k1->radiusy != k2->radiusy ||
332
k1->farbe != k2->farbe)
343
static int punkte_gleich(struct punktedaten *p1, struct punktedaten *p2)
345
return p1->anzpunkte == p2->anzpunkte &&
346
(p1->anzpunkte == 0 || !memcmp(p1->punkte, p2->punkte,
347
p1->anzpunkte * sizeof *p1->punkte));
353
** erhaelt die neuen Spieldaten und startet die Grafikberechnung
357
** spieler_aktiv: Flag, ist der Spieler selbst im Spiel
358
** gegneranz: Anzahl der aktuell sichtbaren Mitspieler
359
** alle_spieler: Feld mit den Daten ueber alle sichtbaren Spieler
360
** schuss_aktiv: Flag, hat der Spieler selbst einen Schuss im Spiel
361
** schussanz: Anzahl der sichtbaren Schuesse der Mitspieler
362
** alle_schuesse: Feld mit den Daten ueber alle sichtbaren Schuesse
363
** abgeschossen_durch: Farbe des Spieler, von dem man abgeschossen wurde
364
** abschuss_spruch: Spruch des Spieler, von dem man abgeschossen wurde
365
** ereignisse: Feld mit den neuen Ereignissen
366
** alle_punkte: Feld mit den Punktestaenden aller Spieler
369
** karteneu wird veraendert
371
static void neuaufbau(int spieler_aktiv, int gegneranz,
372
struct spieler alle_spieler[SPIELERANZ], int schuss_aktiv,
373
int schussanz, struct schuss alle_schuesse[SPIELERANZ],
374
int abgeschossen_durch, char *abschuss_spruch,
375
char ereignisse[ERG_ANZ], int alle_punkte[SPIELERANZ])
377
/* Struktur mit allen Grafik-Daten fuer die 3D-Sicht nach vorn und
379
struct objektdaten blick_vor, blick_zurueck;
380
int anzlinien; /* Anzahl der Linien auf der Karte */
381
int anzkreise; /* Anzahl der Kreise auf der karte */
382
struct kartenkreis *kreise; /* Liste mit den Grafik-Daten der Linien
384
struct kartenlinie *linien; /* Liste mit den Grafik-Daten der Kreise
386
struct spieler spieler_rueck; /* Daten des Spielers um 180 gedreht */
387
struct punktedaten punkte; /* Struktur mit den Daten der
390
/* Listen anlegen, in den die Grafik-Daten abgelegt werden */
391
objekt_listen_init(&blick_vor);
392
objekt_listen_init(&blick_zurueck);
393
liste_initialisieren(&anzkreise, (void **)&kreise);
395
/* falls Karten-Grundriss gezeichnet werden muss, Grafik-Daten dafuer
399
liste_initialisieren(&anzlinien, (void **)&linien);
401
rechne_karte_linien(&anzlinien, &linien);
404
/* falls der Spieler lebt, muss der Horizont gezeichnet werden */
405
blick_vor.hintergrund_zeichnen = blick_zurueck.hintergrund_zeichnen =
408
/* spieler_rueck entspricht dem Spieler mit Blick um 180 Grad gedreht */
409
memcpy(&spieler_rueck, &alle_spieler[0], sizeof(struct spieler));
410
spieler_rueck.blick = (spieler_rueck.blick + WINKANZ / 2) % WINKANZ;
412
/* falls der Spieler lebt, werden die 3D-Berechungen fuer Front- und
413
Rueckansicht aufgerufen */
416
/* Spielerfarbe merken */
417
spieler_farbe = alle_spieler[0].farbe;
419
rechne3d(&blick_vor, &alle_spieler[0], gegneranz,
420
&alle_spieler[1], schussanz + schuss_aktiv,
421
&alle_schuesse[1 - schuss_aktiv]);
422
rechne3d(&blick_zurueck, &spieler_rueck, gegneranz,
423
&alle_spieler[1], schussanz + schuss_aktiv,
424
&alle_schuesse[1 - schuss_aktiv]);
426
else if (abgeschossen_durch >= 0)
427
/* falls der Spieler nach einem Abschuss tot ist, wird das Gesicht des
428
Verursachers angezeigt */
430
struct kugel *kugel; /* Daten des Gegnergesichts */
431
struct ausschnitt *ausschnitt; /* Sichtbarkeitsbereich
434
/* Listen mit Grafik-Daten erweitern */
435
liste_verlaengern(&blick_vor.anzkugeln, (void **)&blick_vor.kugeln,
436
sizeof(struct kugel));
437
kugel = &blick_vor.kugeln[blick_vor.anzkugeln - 1];
439
/* Grafik-Daten eines Gegnergesichts im Vollbild */
440
kugel->mittelpunkt.x = FENSTER_BREITE / 2;
441
kugel->mittelpunkt.y = FENSTER_HOEHE / 2;
442
kugel->radiusx = FENSTER_BREITE / 4;
443
kugel->radiusy = kugel->radiusx * 3 / 2;
444
kugel->schatteny = kugel->schattenry = 0;
445
kugel->blick = TRIGANZ / 2;
446
kugel->farbe = abgeschossen_durch;
448
/* Liste mit Sichtbarkeitsbereich (Gegner ist voll sichtbar) */
449
liste_initialisieren(&kugel->sichtanz, (void **)&kugel->sichtbar);
450
liste_verlaengern(&kugel->sichtanz, (void **)&kugel->sichtbar,
451
sizeof(struct ausschnitt));
452
ausschnitt = &kugel->sichtbar[kugel->sichtanz - 1];
455
ausschnitt->breite = FENSTER_BREITE;
457
/* Abschussspruch des Gegners bekannt? */
458
if (abschuss_spruch != NULL)
460
/* dann Speicher belegen und kopieren */
461
speicher_belegen((void **)&blick_vor.text,
462
strlen(abschuss_spruch) + 1);
463
strcpy(blick_vor.text, abschuss_spruch);
467
/* falls Spieler an Leben, Karte mit ihm berechnen */
469
rechne_karte_kreise(&anzkreise, &kreise,
470
gegneranz + 1, alle_spieler);
472
/* sonst nur die Mitspieler */
473
rechne_karte_kreise(&anzkreise, &kreise,
474
gegneranz, &alle_spieler[1]);
477
int i; /* Index fuer Spieler */
479
/* Punktestaende in Liste kopieren */
480
liste_initialisieren(&punkte.anzpunkte, (void **)&punkte.punkte);
481
for (i = 0; i < SPIELERANZ; i++)
482
if (alle_punkte[i] >= 0)
484
struct punktestand *stand; /* temporaerer Zeiger in Liste */
486
/* Punktestand und Farbe des Spielers an Liste haengen */
487
liste_verlaengern(&punkte.anzpunkte, (void **)&punkte.punkte,
488
sizeof(struct punktestand));
489
stand = &punkte.punkte[punkte.anzpunkte - 1];
491
/* initialisieren, fuer den Vergleich */
492
memset(stand, 0, sizeof *stand);
494
stand->punkte = alle_punkte[i]; /* Punkte */
495
stand->farbe = i + 1; /* Farbe */
497
spieler_farbe == i + 1; /* ich? */
499
else if (spieler_farbe == i + 1)
500
/* ich, ohne Punktestand */
502
struct punktestand *stand; /* temporaerer Zeiger in Liste */
504
/* Punktestand und Farbe des Spielers an Liste haengen */
505
liste_verlaengern(&punkte.anzpunkte, (void **)&punkte.punkte,
506
sizeof(struct punktestand));
507
stand = &punkte.punkte[punkte.anzpunkte - 1];
509
/* initialisieren, fuer den Vergleich */
510
memset(stand, 0, sizeof *stand);
512
stand->punkte = -1; /* Punkte */
513
stand->farbe = i + 1; /* Farbe */
514
stand->hervorheben = 1; /* ja, ich */
517
/* Punkte sortieren */
518
if (punkte.anzpunkte)
519
qsort(punkte.punkte, punkte.anzpunkte,
520
sizeof(struct punktestand), punkte_vergleich);
523
/* Zeichenvorgang synchronisieren */
524
zeichne_sync_anfang();
526
/* Karten-Grundriss, falls notwendig, neuzeichnen */
528
zeichne_grundriss(anzlinien, linien);
530
/* 3D-Frontansicht zeichnen */
531
if (!alt_gueltig || karteneu ||
532
!objektdaten_gleich(&blick_vor, &alt_blick_vor))
533
zeichne_blickfeld(&blick_vor);
535
objekt_listen_freigeben(&alt_blick_vor);
536
memcpy(&alt_blick_vor, &blick_vor, sizeof alt_blick_vor);
538
/* Rueckspiegel zeichnen */
539
if (!alt_gueltig || karteneu ||
540
!objektdaten_gleich(&blick_zurueck, &alt_blick_zurueck))
541
zeichne_rueckspiegel(&blick_zurueck);
543
objekt_listen_freigeben(&alt_blick_zurueck);
544
memcpy(&alt_blick_zurueck, &blick_zurueck, sizeof alt_blick_zurueck);
546
/* Kreise auf der Karte zeichnen; falls Spieler tot, ihn selbst nicht */
550
spieler_index = spieler_aktiv ? 0 : -1;
551
if (!alt_gueltig || spieler_index != alt_spieler_index ||
552
anzkreise != alt_anzkreise ||
553
!kartenkreise_gleich(anzkreise, kreise, alt_kreise))
554
zeichne_karte(spieler_index, anzkreise, kreise);
556
liste_freigeben(&alt_anzkreise, (void **)&alt_kreise);
557
alt_spieler_index = spieler_index;
558
alt_anzkreise = anzkreise;
562
/* Kompass zeichnen */
566
/* falls Spieler tot, Kompass ohne Nadel zeichnen */
568
kompass = alle_spieler[0].blick * (TRIGANZ / WINKANZ);
572
if (!alt_gueltig || karteneu || kompass != alt_kompass)
573
zeichne_kompass(kompass);
575
alt_kompass = kompass;
578
/* Punktestand zeichnen */
579
if (!alt_gueltig || karteneu || !punkte_gleich(&punkte, &alt_punkte))
580
zeichne_punkte(&punkte);
582
liste_freigeben(&alt_punkte.anzpunkte,
583
(void **)&alt_punkte.punkte);
584
memcpy(&alt_punkte, &punkte, sizeof alt_punkte);
586
/* audio-visuelle Darstellung der Ereignisse */
587
ereignisse_darstellen(ereignisse);
589
/* Zeichenvorgang synchronisieren */
594
liste_freigeben(&anzlinien, (void **)&linien);
596
/* falls Karten-Grundriss neu gezeichnet wurde, muss dies naechstes
597
Mal vorerst nicht wiederholt werden */
607
** beendet das Programm ohne Rueckfrage
609
static void client_ende(void)
611
/* lokale Datenstrukturen aufraeumen */
614
/* alle Netzverbindungen beenden */
621
/* bis hier lokaler Teil */
622
/***********************************************/
623
/* ab hier globaler Teil */
627
** spiel_puffer_anlegen
628
** ermittelt die Zeiger auf die aktuellen Puffer, in die die neuen
629
** Spieldaten abgelegt werden sollen
632
** spieler_aktiv_var: Zeiger auf Zeiger auf Flag,
633
** ist der Spieler selbst im Spiel?
634
** spieler_var: Zeiger auf Zeiger auf Daten des Spielers selbst
635
** gegneranz_var: Zeiger auf Zeiger auf Anzahl der aktuell
636
** sichtbaren Mitspieler
637
** gegner_feld: Zeiger auf Liste mit den Daten der sichtbaren Mitspieler
638
** schuss_aktiv_var: Zeiger auf Zeiger auf Flag, hat der Spieler
639
** selbst einen Schuss im Spiel?
640
** schuss_var: Zeiger auf Zeiger auf Daten des eigenen Schusses
641
** schussanz_var: Zeiger auf Zeiger auf Anzahl der sichtbaren
642
** Schuesse der Mitspieler
643
** schuesse_feld: Zeiger auf Liste mit den Daten der sichtbaren
644
** Schuesse der Mitspieler
645
** abgechossen_durch_var: Zeiger auf Zeiger auf Farbe des Spieler,
646
** von dem man abgeschossen wurde
647
** abschluss_spruch_var: Zeiger auf Zeiger auf Spruch des Spieler,
648
** von dem man abgeschossen wurde
649
** ereignisse_feld: Zeiger auf Liste mit den neuen Ereignissen
650
** punkte_feld: Zeiger auf Liste mit den Punktestaenden
653
** ereignisse_uebrig wird gesetzt
655
void spiel_puffer_anlegen(int **spieler_aktiv_var,
656
struct spieler **spieler_var, int **gegneranz_var,
657
struct spieler **gegner_feld, int **schuss_aktiv_var,
658
struct schuss **schuss_var, int **schussanz_var,
659
struct schuss **schuesse_feld, int **abgeschossen_durch_var,
660
char ***abschuss_spruch_var, char **ereignisse_feld, int **punkte_feld)
662
/* Speicher fuer alten Spruch freigeben */
663
if (abschuss_spruch[1 - puffer_nr] != NULL)
664
speicher_freigeben((void **)&abschuss_spruch[1 - puffer_nr]);
666
/* Zeiger auf die Puffer ermitteln; jeweils der andere als puffer_nr */
667
*spieler_aktiv_var = &spieler_aktiv[1 - puffer_nr];
668
*spieler_var = alle_spieler[1 - puffer_nr];
669
*gegneranz_var = &gegneranz[1 - puffer_nr];
670
*gegner_feld = &alle_spieler[1 - puffer_nr][1];
672
*schuss_aktiv_var = &schuss_aktiv[1 - puffer_nr];
673
*schuss_var = alle_schuesse[1 - puffer_nr];
674
*schussanz_var = &schussanz[1 - puffer_nr];
675
*schuesse_feld = &alle_schuesse[1 - puffer_nr][1];
677
*abgeschossen_durch_var = &abgeschossen_durch[1 - puffer_nr];
679
*abschuss_spruch_var = &abschuss_spruch[1 - puffer_nr];
681
*ereignisse_feld = ereignisse[1 - puffer_nr];
683
*punkte_feld = alle_punkte[1 - puffer_nr];
685
/* falls die vorigen Pufferinhalte noch nicht abgearbeitet wurden,
686
alle Ereignisse retten */
687
if (puffer_gueltig != puffer_nr)
691
for (i = 0; i < ERG_ANZ; i++)
692
ereignisse_uebrig[i] = (*ereignisse)[i];
698
** netzwerk_spielende
699
** wird aufgerufen, wenn der Server den Client aus dem Spiel genommen hat;
700
** es wird auf der Stelle eine Meldung ausgegben und das Programm beendet
702
void netzwerk_spielende(void)
704
static char *meldung[] = { "iMaze - Fatal Error", "",
705
"Disconnected by server.", NULL };
707
uebler_fehler(meldung, NULL);
713
** wird aufgerufen, wenn die neuen Daten in die Puffer uebertragen wurden.
714
** Liest die Eingabe-Signale aus
717
** signale: Feld mit allen Signalen
720
** puffer_gueltig wird gesetzt
722
void signale_abfragen(char signale[SIGNALANZ])
724
/* falls der vorige Pufferinhalt noch nicht abgearbeitet wurde,
725
werden die unbearbeiteten Ereignisse wieder uebernommen */
726
if (puffer_gueltig != puffer_nr)
730
for (i = 0; i < ERG_ANZ; i++)
731
(*ereignisse)[i] |= ereignisse_uebrig[i];
734
/* der andere Puffer hat jetzt die aktuelle Daten */
735
puffer_gueltig = 1 - puffer_nr;
737
/* Abfrage der Eingabe-Signale */
738
eingabe_abfragen(signale);
743
** bewegung_deskriptor
744
** liefert einen Deskriptor fuer die Verbindung zum Server im Spiel-Modus
747
** ein Zeiger auf den Deskriptor, NULL, falls es noch keine gibt
749
void *bewegung_deskriptor(void)
751
/* nur den Deskriptor vom Netzwerkteil abfragen und weiterreichen */
752
return spiel_deskriptor();
758
** wartet auf Daten vom Server und initiiert evtl. die Neuberechnung und
759
** -zeichnung aller Grafikausgaben
762
** ms: Zeit in Millisekunden, die maximal gewartet werden darf;
763
** oder -1 fuer unbegrenztes Warten
764
** zeichnen: Flag, ob die Grafik neu berechnet und gezeichnet werden soll
767
** 1 fuer Fehler, sonst 0
770
** puffer_nr wird veraendert
772
int bewegung(int ms, int zeichnen)
775
static int rekursion = 0; /* Flag, ob spiel_paket_erwarten laeuft */
777
/* Rekursion von spiel_paket_erwarten verhindern */
784
/* Daten vom Server erwarten */
785
if (spiel_paket_erwarten(ms))
789
/* Fehler aufgetreten */
796
/* falls nicht gezeichnet werden soll, fertig */
801
if (puffer_gueltig == puffer_nr)
802
/* in diesem Fall liegen keine neuen Daten vor; kein Fehler */
805
/* der andere Puffer enthaelt die neuen Daten */
806
puffer_nr = puffer_gueltig;
808
/* Neuberechnung und -zeichnung aller Grafikausgaben mit neuen Daten */
809
neuaufbau(spieler_aktiv[puffer_nr], gegneranz[puffer_nr],
810
alle_spieler[puffer_nr], schuss_aktiv[puffer_nr],
811
schussanz[puffer_nr], alle_schuesse[puffer_nr],
812
abgeschossen_durch[puffer_nr], abschuss_spruch[puffer_nr],
813
ereignisse[puffer_nr], alle_punkte[puffer_nr]);
821
** client_spiel_starten
822
** wird aufgerufen, um die Verbindung zum Server aufzubauen
825
** server_name: Name des Servers
826
** spruch: Spruch des Spielers oder NULL
827
** kamera: Flag, ob der Spieler nur zusehen will
830
** 1 fuer Fehler, sonst 0
833
** Daten werden vom Server empfangen; karteneu wird initialisiert
835
int client_spiel_starten(char *server_name, char *spruch, int kamera)
837
/* Verbindung zum angegebenen Server aufbauen */
838
if (verbindung_aufbauen(server_name))
841
/* Spielparameter / Labyrinth empfangen */
842
if (spielparameter_empfangen("iMaze 3D client JC/HUK 1.4",
843
"Anonymous User", strlen(spruch) ? spruch : NULL, kamera,
844
&feldbreite, &feldlaenge, &spielfeld, NULL, 1 /* starten */))
847
/* Spielfeld drehen */
850
/* Karte neu aufbauen */
853
/* Spielerfarbe noch unbekannt */
856
/* jetzt kanns losgehen */
857
if (verbindung_auf_spiel())
866
** client_spiel_beenden
867
** wird aufgerufen, wenn eine Spielrunde verlassen wird (disconnect)
869
void client_spiel_beenden(void)
871
/* Verbindung zum Server beenden */
878
** zeigt eine Fehlermeldung an und beendet nach Druecken eines Knopfes
882
** meldung: Feld von Strings, die die Zeilen des auszugebenden Textes
884
** knopf: Text der auf dem Knopf stehen soll;
885
** falls NULL, so wird ein Standardtext verwendet
887
void uebler_fehler(char **meldung, char *knopf)
889
/* Fehler anzeigen */
890
ueblen_fehler_anzeigen(meldung, knopf);
892
/* Programm beenden */
899
** merkt sich eine Fehlermeldung fuer die Routine milden_fehler_abfragen
902
** meldung: Feld von Strings, die die Zeilen des auszugebenden Textes
904
** knopf: Text, der auf dem Knopf stehen soll;
905
** falls NULL, so wird ein Standardtext verwendet
908
** fehlermeldung und fehlerknopf werden gesetzt
910
void milder_fehler(char **meldung, char *knopf)
912
int n; /* Anzahl der Fehlerstrings */
913
int i; /* Index fuer Fehlerstrings */
915
/* Speicher fuer vorige Fehlermeldung freigeben */
916
if (fehlermeldung != NULL)
918
for (i = 0; fehlermeldung[i] != NULL; i++)
919
speicher_freigeben((void **)&fehlermeldung[i]);
920
speicher_freigeben((void **)&fehlermeldung);
923
/* Strings zaehlen */
924
for (n = 0; meldung[n] != NULL; n++);
926
/* Speicher fuer das Feld belegen und durch Nullzeiger begrenzen */
927
speicher_belegen((void **)&fehlermeldung, (n + 1) * sizeof *fehlermeldung);
928
fehlermeldung[n] = NULL;
930
/* Fehlerstrings kopieren */
931
for (i = 0; i < n; i++)
933
speicher_belegen((void **)&fehlermeldung[i], strlen(meldung[i]) + 1);
934
strcpy(fehlermeldung[i], meldung[i]);
937
/* Speicher fuer vorige Knopfbeschriftung freigeben */
938
if (fehlerknopf != NULL)
939
speicher_freigeben((void **)&fehlerknopf);
941
/* Knopfbeschriftung kopieren */
946
speicher_belegen((void **)&fehlerknopf, strlen(knopf) + 1);
947
strcpy(fehlerknopf, knopf);
953
** milden_fehler_abfragen
954
** fragt den in milder_fehler gemerkten Fehlertext und -knopf ab
957
** meldung: Zeiger auf Feld von Strings, das die Zeilen des
958
** auszugebenden Textes beinhalten soll
959
** knopf: Zeiger auf Text, der auf dem Knopf stehen soll
962
** *meldung und *knopf werden gesetzt
964
void milden_fehler_abfragen(char ***meldung, char **knopf)
966
/* Rueckgabewerte setzen */
967
*meldung = fehlermeldung;
968
*knopf = fehlerknopf;
972
char *get_server_name(int *override)
974
return net_get_server_name(override);
983
** argc: Anzahl der Argumente inklusive Programmname
984
** argv: Argumentliste
986
int main(int argc, char **argv)
988
/* Optionen via argv.h auswerten */
989
process_args(&argc, argv);
991
/* Netzwerkroutinen initialisieren */
993
/* bei Fehler beenden */
996
/* Fenster oeffnen und lokale Datenstrukturen initialisieren */
997
/* XXX argv ist hier immer leer */
998
if (grafik_init(&argc, argv))
999
/* bei Fehler beenden */
1005
/* Programm beenden */