4
|
1 /*--------------------------------------------------------------------------
|
|
2 NETREK II -- Paradise
|
|
3
|
|
4 Permission to use, copy, modify, and distribute this software and its
|
|
5 documentation, or any derivative works thereof, for any NON-COMMERCIAL
|
|
6 purpose and without fee is hereby granted, provided that this copyright
|
|
7 notice appear in all copies. No representations are made about the
|
|
8 suitability of this software for any purpose. This software is provided
|
|
9 "as is" without express or implied warranty.
|
|
10
|
|
11 Xtrek Copyright 1986 Chris Guthrie
|
|
12 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith
|
|
13 Scott Silvey
|
|
14 Paradise II (Netrek II) Copyright 1993 Larry Denys
|
|
15 Kurt Olsen
|
|
16 Brandon Gillespie
|
|
17 --------------------------------------------------------------------------*/
|
|
18
|
|
19 #include "config.h"
|
|
20 #include <stdio.h>
|
|
21 #include <sys/types.h>
|
|
22 #include <sys/time.h>
|
|
23 #include "defs.h"
|
|
24 #include "struct.h"
|
|
25 #include "data.h"
|
|
26 #include "packets.h"
|
|
27 #include "shmem.h"
|
|
28
|
|
29 extern int overload; /* 7/31/91 TC let overloaded join any team */
|
|
30
|
|
31 extern int updateShips();
|
|
32 extern int sendMaskPacket();
|
|
33 int tournamentMask();
|
|
34 extern int briefUpdateClient();
|
|
35 extern int flushSockBuf();
|
|
36 extern int socketPause();
|
|
37 extern int readFromClient();
|
|
38 extern int isClientDead();
|
|
39 extern int exitGame();
|
|
40 #ifndef IRIX
|
|
41 extern int printf();
|
|
42 #endif
|
|
43 extern int closeUdpConn();
|
|
44 extern unsigned int sleep();
|
|
45 extern int connectToClient();
|
|
46 extern int updateSelf();
|
|
47 extern int sendPickokPacket();
|
|
48 extern int allowed_ship();
|
|
49 extern int time_access();
|
|
50 int deadTeam();
|
|
51 int realNumShips();
|
|
52
|
|
53 #if 1
|
|
54
|
|
55 void
|
|
56 detourneyqueue()
|
|
57 {
|
|
58 me->p_status = POUTFIT;
|
|
59 me->p_whydead = KPROVIDENCE;
|
|
60 }
|
|
61
|
|
62 #endif
|
|
63
|
|
64
|
|
65 void
|
|
66 getEntry(team, stype)
|
|
67 int *team;
|
|
68 int *stype;
|
|
69 {
|
|
70
|
|
71
|
|
72 int switching = -1; /* confirm switches 7/27/91 TC */
|
|
73 inputMask = CP_OUTFIT;
|
|
74 for (;;)
|
|
75 {
|
|
76 /* updateShips so he knows how many players on each team */
|
|
77 if (blk_flag)
|
|
78 updateShips();
|
|
79 sendMaskPacket(tournamentMask(me->p_team));
|
|
80 if (blk_flag)
|
|
81 briefUpdateClient();
|
|
82 flushSockBuf();
|
|
83 /* Have we been busted? */
|
|
84 if (me->p_status == PFREE)
|
|
85 {
|
|
86 me->p_status = PDEAD;
|
|
87 me->p_explode = 600;
|
|
88 }
|
|
89 socketPause();
|
|
90 readFromClient();
|
|
91 if (isClientDead())
|
|
92 {
|
|
93 int i;
|
|
94
|
|
95 if (noressurect)
|
|
96 exitGame();
|
|
97 printf("Ack! The client went away!\n");
|
|
98 printf("I will attempt to resurrect him!\n");
|
|
99
|
|
100 /* UDP fail-safe */
|
|
101 commMode = COMM_TCP;
|
|
102 if (udpSock >= 0)
|
|
103 closeUdpConn();
|
|
104
|
|
105 /* For next two minutes, we try to restore connection */
|
|
106 shutdown(sock, 2);
|
|
107 sock = -1;
|
|
108 for (i = 0;; i++)
|
|
109 {
|
|
110 switch (me->p_status)
|
|
111 {
|
|
112 case PFREE:
|
|
113 me->p_status = PDEAD;
|
|
114 me->p_explode = 600;
|
|
115 break;
|
|
116 case PALIVE:
|
|
117 case POBSERVE:
|
|
118 me->p_ghostbuster = 0;
|
|
119 break;
|
|
120 case PDEAD:
|
|
121 me->p_explode = 600;
|
|
122 break;
|
|
123 default:
|
|
124 me->p_explode = 600;
|
|
125 me->p_ghostbuster = 0;
|
|
126 break;
|
|
127 }
|
|
128 sleep(5);
|
|
129 if (connectToClient(host, nextSocket))
|
|
130 break;
|
|
131 if (i == 23)
|
|
132 {
|
|
133 printf("Oh well, maybe I'm getting rusty!\n");
|
|
134 switch (me->p_status)
|
|
135 {
|
|
136 case PFREE:
|
|
137 break;
|
|
138 case PALIVE:
|
|
139 case POBSERVE:
|
|
140 me->p_ghostbuster = 100000;
|
|
141 break;
|
|
142 case PDEAD:
|
|
143 me->p_explode = 0;
|
|
144 break;
|
|
145 default:
|
|
146 me->p_explode = 0;
|
|
147 me->p_ghostbuster = 100000;
|
|
148 break;
|
|
149 }
|
|
150 exitGame();
|
|
151 }
|
|
152 }
|
|
153 printf("A miracle! He's alive!\n");
|
|
154 teamPick = -1;
|
|
155 updateSelf();
|
|
156 updateShips();
|
|
157 flushSockBuf();
|
|
158 }
|
|
159 if (teamPick != -1)
|
|
160 {
|
|
161 if (teamPick < 0 || teamPick > 3)
|
|
162 {
|
|
163 warning("Get real!");
|
|
164 sendPickokPacket(0);
|
|
165 teamPick = -1;
|
|
166 continue;
|
|
167 }
|
|
168 #if 1
|
|
169 if (!(tournamentMask(me->p_team) & (1 << teamPick)))
|
|
170 {
|
|
171 warning("I cannot allow that. Pick another team");
|
|
172 sendPickokPacket(0);
|
|
173 teamPick = -1;
|
|
174 continue;
|
|
175 }
|
|
176 #endif
|
|
177
|
|
178 if (((1 << teamPick) != me->p_team) &&
|
|
179 (me->p_team != ALLTEAM)) /* switching teams 7/27/91 TC */
|
|
180 if ((switching != teamPick)
|
|
181 && (me->p_whydead != KGENOCIDE)
|
|
182 #ifdef LEAGUE_SUPPORT
|
|
183 && !status2->league
|
|
184 #endif
|
|
185 )
|
|
186 {
|
|
187 switching = teamPick;
|
|
188 warning("Please confirm change of teams. Select the new team again.");
|
|
189 sendPickokPacket(0);
|
|
190 teamPick = -1;
|
|
191 continue;
|
|
192 }
|
|
193 /* His team choice is ok. */
|
|
194 if (shipPick < 0 || shipPick >= NUM_TYPES)
|
|
195 {
|
|
196 warning("That is an illegal ship type. Try again.");
|
|
197 sendPickokPacket(0);
|
|
198 teamPick = -1;
|
|
199 continue;
|
|
200 }
|
|
201 if (!allowed_ship(1 << teamPick, mystats->st_rank, mystats->st_royal, shipPick))
|
|
202 {
|
|
203 sendPickokPacket(0);
|
|
204 teamPick = -1;
|
|
205 continue;
|
|
206 }
|
|
207 if (shipvals[shipPick].s_nflags & SFNMASSPRODUCED)
|
|
208 {
|
|
209 warning("o)utpost, u)tility, or s)tandard?");
|
|
210 sendPickokPacket(0);
|
|
211 tmpPick = shipPick;
|
|
212 continue;
|
|
213 }
|
|
214 break;
|
|
215 }
|
|
216 #if 1
|
|
217 if (me->p_status == PTQUEUE)
|
|
218 {
|
|
219 if (status->tourn)
|
|
220 detourneyqueue();
|
|
221 /* You don't time out on the tourney queue */
|
|
222 me->p_ghostbuster = 0;
|
|
223 }
|
|
224 #endif
|
|
225 }
|
|
226 *team = teamPick;
|
|
227 if ((shipvals[tmpPick].s_nflags & SFNMASSPRODUCED) &&
|
|
228 ((shipvals[shipPick].s_numports) || (shipPick == SCOUT)))
|
|
229 {
|
|
230
|
|
231 *stype = tmpPick;
|
|
232 tmpPick = CRUISER;
|
|
233 }
|
|
234 else
|
|
235 {
|
|
236 *stype = shipPick;
|
|
237 tmpPick = CRUISER;
|
|
238 }
|
|
239 sendPickokPacket(1);
|
|
240 flushSockBuf();
|
|
241 }
|
|
242
|
|
243
|
|
244
|
|
245
|
|
246 /*------------------------------TOURNAMENTMASK----------------------------*/
|
|
247 /*
|
|
248 * This function takes the players current team and returns a mask of the
|
|
249 * teams that the player can join.
|
|
250 */
|
|
251
|
|
252 int
|
|
253 leaguemask(ishome, idx)
|
|
254 int ishome; /* team index */
|
|
255 int idx;
|
|
256 {
|
|
257 #ifdef LEAGUE_SUPPORT
|
|
258 if (status2->league == 1)
|
|
259 return idx_to_mask(ishome);
|
|
260 else
|
|
261 #endif
|
|
262 return idx_to_mask(idx);
|
|
263 }
|
|
264
|
|
265 int
|
|
266 tournamentMask(team)
|
|
267 int team; /* players current team */
|
|
268 {
|
|
269 int i; /* looping var */
|
|
270 int team1, team2; /* for getting two possible teams */
|
|
271 int num1, num2; /* to hold num players on teams */
|
|
272
|
|
273 if (!blk_flag) /* not a paradise client */
|
|
274 return (0);
|
|
275 if (status->gameup == 0) /* if game over, can join no team */
|
|
276 return (0);
|
|
277 if (overload) /* if tester slot then can join */
|
|
278 return (ALLTEAM); /* any team */
|
|
279 if (mustexit) /* should we force player out */
|
|
280 return (0);
|
|
281 if (!time_access()) /* if server closed then can join */
|
|
282 return (0); /* no team */
|
|
283
|
|
284 #ifdef LEAGUE_SUPPORT
|
|
285 /* league stuff */
|
|
286 if (status2->league)
|
|
287 {
|
|
288 if (me->p_homeaway == AWAY)
|
|
289 return leaguemask(1, status2->away.index);
|
|
290 else if (me->p_homeaway == HOME)
|
|
291 return leaguemask(0, status2->home.index);
|
|
292 else
|
|
293 {
|
|
294 warning("You have connected to a league server but aren't on a side.");
|
|
295 me->p_homeaway = (lrand48() & 1) + 1; /* dangerous int->enum cast */
|
|
296 return 0;
|
|
297 }
|
|
298 /* NOTREACHED */
|
|
299 }
|
|
300 #endif
|
|
301 if (me->p_homeaway != NEITHER)
|
|
302 {
|
|
303 warning("You have connected to a non-league server with a league ntserv.");
|
|
304 me->p_homeaway = NEITHER;
|
|
305 }
|
|
306
|
|
307 if (!status->tourn)
|
|
308 {
|
|
309 return status2->nontteamlock;
|
|
310 }
|
|
311
|
|
312 if (team != ALLTEAM && deadTeam(team)) /* if former team dead */
|
|
313 team = ALLTEAM; /* then check all others */
|
|
314 for (i = 0; i < NUMTEAM; i++)
|
|
315 { /* go through all teams and eliminate */
|
|
316 if ((team & (1 << i)) && (deadTeam(1 << i))) /* from team var all
|
|
317 * teams */
|
|
318 team &= ~(1 << i); /* that are dead */
|
|
319 }
|
|
320 team1 = 0; /* no team in team 1 */
|
|
321 num1 = 0; /* 0 players on team 1 */
|
|
322 team2 = 0; /* no team in team 2 */
|
|
323 num2 = 0; /* 0 players on team 2 */
|
|
324 for (i = 0; i < NUMTEAM; i++)
|
|
325 { /* go through all teams */
|
|
326 if (deadTeam(1 << i)) /* if team is dead then */
|
|
327 continue; /* disregard it */
|
|
328 if (realNumShips(1 << i) >= configvals->tournplayers)
|
|
329 { /* enough players */
|
|
330 if (!team1) /* if no team in team1 yet */
|
|
331 team1 = (1 << i); /* then this will be team 1 */
|
|
332 else
|
|
333 { /* otherwise its team2 */
|
|
334 team2 = (1 << i);
|
|
335 num1 = realNumShips(team1); /* get num players on two teams */
|
|
336 num2 = realNumShips(team2);
|
|
337 if (num1 == num2)
|
|
338 { /* if teams same size then */
|
|
339 if (team & (team1 | team2)) /* if player on one team */
|
|
340 return (team & (team1 | team2)); /* let him join same team */
|
|
341 return (team1 | team2); /* otherwise, he can join either */
|
|
342 }
|
|
343 else if ((num1 > num2) && (team != team1))
|
|
344 return (team2); /* if slight imabalance */
|
|
345 else if ((num1 < num2) && (team != team2))
|
|
346 return (team1); /* if slight imbalance */
|
|
347 else
|
|
348 {
|
|
349 if (ABS(num1 - num2) < 2 || (((num1 > num2) && (team == team2)) ||
|
|
350 (num2 > num1 && team == team1)))
|
|
351 return (team);
|
|
352 else
|
|
353 return (team1 | team2);
|
|
354 }
|
|
355 }
|
|
356 }
|
|
357 } /* end of for loop */
|
|
358 return (team); /* just in case */
|
|
359 }
|
|
360
|
|
361
|
|
362
|
|
363
|
|
364 /*--------------------------------REALNUMSHIPS-----------------------------*/
|
|
365 /*
|
|
366 * Count the real number of ships on a team. This function returns a count
|
|
367 * of all the ships on a team that are not PFREE.
|
|
368 */
|
|
369
|
|
370 int
|
|
371 realNumShips(owner)
|
|
372 int owner; /* the team to check for */
|
|
373 {
|
|
374 int i; /* looping var */
|
|
375 int num; /* to hold ship count */
|
|
376 struct player *p; /* to point to players */
|
|
377
|
|
378 num = 0; /* initialize count */
|
|
379 for (i = 0, p = players; i < MAXPLAYER; i++, p++)
|
|
380 {
|
|
381 if ((p->p_status != PFREE) &&
|
|
382 !(p->p_flags & (PFSNAKE | PFBIRD)) &&
|
|
383 (p->p_team == owner))
|
|
384 {
|
|
385 num++; /* if ship not free and on our team */
|
|
386 }
|
|
387 }
|
|
388 return (num); /* retun number of ships */
|
|
389 }
|
|
390
|
|
391
|
|
392
|
|
393
|
|
394 /*----------------------------------DEADTEAM-------------------------------*/
|
|
395 /*
|
|
396 * This function counts the number of planets that a team owns. It returns a
|
|
397 * 1 if the team has no planets, and a 0 if they have at least one planet.
|
|
398 */
|
|
399
|
|
400 int
|
|
401 deadTeam(owner)
|
|
402 int owner; /* team to check for */
|
|
403 {
|
|
404 int i; /* looping var */
|
|
405 struct planet *p; /* to point to a planets */
|
|
406
|
|
407 for (i = 0, p = planets; i < NUMPLANETS; i++, p++)
|
|
408 {
|
|
409 if (p->pl_owner & owner) /* if planet owned by team then */
|
|
410 return (0); /* found one planet owned by team */
|
|
411 }
|
|
412 return (1); /* no planets found, team is dead */
|
|
413 }
|
|
414
|
|
415 /*-------------------------------------------------------------------------*/
|
|
416
|
|
417
|
|
418
|
|
419
|
|
420
|
|
421 /*---------END OF FILE--------*/
|