~collinp/paradise-netrek/3.1p0

« back to all changes in this revision

Viewing changes to src/common/enter.c

  • Committer: Collin Pruitt
  • Date: 2009-05-22 04:40:09 UTC
  • Revision ID: collinp111@gmail.com-20090522044009-gw30zywb9oaae4nr
Initial upload - just the source release of 3.1p0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*------------------------------------------------------------------
 
2
  Copyright 1989                Kevin P. Smith
 
3
                                Scott Silvey
 
4
 
 
5
Permission to use, copy, modify, and distribute this
 
6
software and its documentation for any purpose and without
 
7
fee is hereby granted, provided that the above copyright
 
8
notice appear in all copies.
 
9
 
 
10
  NETREK II -- Paradise
 
11
 
 
12
  Permission to use, copy, modify, and distribute this software and
 
13
  its documentation, or any derivative works thereof,  for any 
 
14
  NON-COMMERCIAL purpose and without fee is hereby granted, provided
 
15
  that this copyright notice appear in all copies.  No
 
16
  representations are made about the suitability of this software for
 
17
  any purpose.  This software is provided "as is" without express or
 
18
  implied warranty.
 
19
 
 
20
        Xtrek Copyright 1986                    Chris Guthrie
 
21
        Netrek (Xtrek II) Copyright 1989        Kevin P. Smith
 
22
                                                Scott Silvey
 
23
        Paradise II (Netrek II) Copyright 1993  Larry Denys
 
24
                                                Kurt Olsen
 
25
                                                Brandon Gillespie
 
26
                                Copyright 2000  Bob Glamm
 
27
 
 
28
--------------------------------------------------------------------*/
 
29
 
 
30
#include "config.h"
 
31
#include "proto.h"
 
32
#include "data.h"
 
33
#include "shmem.h"
 
34
 
 
35
/*------------------------------NUMBER DEFINES-----------------------------*/
 
36
#define INDEP (GWIDTH/3)        /* width of region in the center of galaxy */
 
37
                                /* that independents can join in */
 
38
 
 
39
#define MIN_DIST_FROM_STAR 3000.0 /* min distance from a star that enter() */
 
40
                                /* will place you */
 
41
/*-------------------------------------------------------------------------*/
 
42
 
 
43
 
 
44
static int 
 
45
find_start_planet(int team, int flag)
 
46
{
 
47
    int     valid[MAXPLANETS];
 
48
    int     nvalid;
 
49
    int     i;
 
50
 
 
51
    nvalid = 0;
 
52
    for (i = 0; i < NUMPLANETS; i++) {
 
53
        struct planet *pl = &planets[i];
 
54
        if (pl->pl_owner == team && (!flag || pl->pl_flags & flag))
 
55
            valid[nvalid++] = i;
 
56
    }
 
57
    if (nvalid < 1)
 
58
        return -1;
 
59
 
 
60
    return valid[lrand48() % nvalid];
 
61
}
 
62
 
 
63
/*------------------------------VISIBLE FUNCTIONS-------------------------*/
 
64
 
 
65
#define BOSSMAN         NUMROYALRANKS-1
 
66
#define SIDEKICK        NUMROYALRANKS-2
 
67
#define AMBASSADOR      NUMROYALRANKS-3
 
68
 
 
69
#ifdef UFL
 
70
#undef SIDEKICK
 
71
#define SIDEKICK        NUMROYALRANKS-1
 
72
#undef AMBASSADOR
 
73
#define AMBASSADOR      NUMROYALRANKS-1
 
74
#endif
 
75
 
 
76
/*--------------------------------PEANUT_GALLERY--------------------------*/
 
77
/*  This function checks too see if certain "important" people have logged
 
78
in, and displays a special message to the rest of the players.  As the chief
 
79
Paradise hack, I forbid removal of any of the code in this function.  Other
 
80
names may be added.  If you choose to disregard this, a malefiction will be
 
81
leveled upon your head and all of your progeny will be born with their noses
 
82
two times too large.  */
 
83
 
 
84
#define AT_LEAST(rank) if (me->p_stats.st_royal<rank) me->p_stats.st_royal = rank;
 
85
 
 
86
 
 
87
static void 
 
88
peanut_gallery(void)
 
89
{
 
90
    char    buf[90];
 
91
 
 
92
    if (strcmp(me->p_name, "a fungusamongus") == 0) {   /* that's me! */
 
93
        pmessage2("  ", 0, MALL, "LDDENYS > ", me->p_no);
 
94
        pmessage2("Yikes.  EEK!  Help.  There seems to be a fungus among us!", 0, MALL, "LDDENYS > ", me->p_no);
 
95
        pmessage2("  ", 0, MALL, "LDDENYS > ", me->p_no);
 
96
 
 
97
    }
 
98
    else if (strcmp(me->p_name, "Lynx") == 0) {
 
99
        pmessage2("\"GAME OVER MAN, GAME OVER!\"", 0, MALL, "Lynx->ALL ", me->p_no);
 
100
 
 
101
    }
 
102
    else if (strcmp(me->p_name, "Hammor") == 0) {
 
103
        pmessage2("Please don't hurt 'em, Hammor!", 0, MALL, "GOD->ALL", me->p_no);
 
104
 
 
105
    }
 
106
    else if (strcmp(me->p_name, "Bubbles") == 0) {
 
107
        pmessage2("Whoa!", 0, MALL, "KAOLSEN > ", me->p_no);
 
108
        pmessage2("Dudes.", 0, MALL, "KAOLSEN > ", me->p_no);
 
109
        pmessage2("Cool.", 0, MALL, "KAOLSEN > ", me->p_no);
 
110
 
 
111
    }
 
112
    else if (strcmp(me->p_name, "KnightRaven") == 0) {
 
113
        pmessage2("Insert Heiji quote here", 0, MALL, "KAOLSEN > ", me->p_no);
 
114
        AT_LEAST(AMBASSADOR);
 
115
 
 
116
    }
 
117
    else if (strcmp(me->p_name, "wibble") == 0) {
 
118
        pmessage2("No mountain is unclimbable, no river uncrossable, no client RSA"
 
119
                 ,0, MALL, "EGO->wibble", me->p_no);
 
120
        pmessage2("key unbreakable.  We can just make it bloody difficult!",
 
121
                 0, MALL, "EGO->wibble", me->p_no);
 
122
 
 
123
    }
 
124
    else if (strcmp(me->p_name, "Key") == 0) {
 
125
        time_t  curtime;
 
126
        struct tm *tmstruct;
 
127
        int     hour;
 
128
 
 
129
        (void) time(&curtime);
 
130
        tmstruct = localtime(&curtime);
 
131
        if (!(hour = tmstruct->tm_hour % 12))
 
132
            hour = 12;
 
133
 
 
134
        sprintf(buf, "It's %d:%02d%s, time [for me] to die.", hour,
 
135
                tmstruct->tm_min, tmstruct->tm_hour >= 12 ? "pm" : "am");
 
136
        pmessage2(buf, 0, MALL, "GOD->ALL", me->p_no);
 
137
 
 
138
    }
 
139
    else if (strcmp(me->p_name, "MikeL") == 0) {
 
140
        pmessage2("<This space for rent>", 0, MALL, "GOD->ALL", me->p_no);
 
141
 
 
142
 
 
143
    }
 
144
    else if (strcmp(me->p_name, "Bolo") == 0) {
 
145
        pmessage2("Bolo Mk. MCLXVII On-line.", 0, MALL, MSERVA, me->p_no);
 
146
    }
 
147
}
 
148
 
 
149
static void 
 
150
advertise_tourney_queue(void)
 
151
{
 
152
    char    buf[80], addrbuf[10];
 
153
    int     count = 0;
 
154
    int     i;
 
155
 
 
156
    if (status->tourn)
 
157
        return;
 
158
 
 
159
    for (i = 0; i < MAXPLAYER; i++) {
 
160
        if (players[i].p_status == PTQUEUE)
 
161
            count++;
 
162
    }
 
163
 
 
164
    sprintf(addrbuf, "%s->YOU ", SERVNAME);
 
165
    sprintf(buf, "There %s %d player%s on the tournament queue",
 
166
            (count == 1) ? "is" : "are", count, (count == 1) ? "" : "s");
 
167
    pmessage (buf, me->p_no, MINDIV, addrbuf);
 
168
}
 
169
 
 
170
/*--------------------------------AUTOPEACE------------------------------*/
 
171
/*  This function set the player as hostile to all teams with at least one
 
172
player on them if it is t-mode.  Otherwise if it is not t-mode the player
 
173
is set as hositle to everyone.  */
 
174
 
 
175
static void 
 
176
auto_peace(void)
 
177
{
 
178
    int     i, num[MAXTEAM + 1];/* to hold team's player counts */
 
179
    struct player *p;           /* looping var */
 
180
 
 
181
    num[0] = num[FED] = num[ROM] = num[KLI] = num[ORI] = 0;     /* zero counts */
 
182
    for (i = 0, p = players; i < MAXPLAYER; i++, p++)   /* loop all players */
 
183
        if (p->p_status != PFREE)       /* ince the count of the team the */
 
184
            num[p->p_team]++;   /* player is on */
 
185
    if (status->tourn)          /* if t-mode then make player hostile */
 
186
        me->p_hostile =         /* make all teams with a player on */
 
187
            ((FED * (num[FED] >= configvals->tournplayers)) |
 
188
             (ROM * (num[ROM] >= configvals->tournplayers)) |
 
189
             (KLI * (num[KLI] >= configvals->tournplayers)) |
 
190
             (ORI * (num[ORI] >= configvals->tournplayers)));
 
191
    else                        /* else if not t-mode then */
 
192
        me->p_hostile = FED | ROM | KLI | ORI;  /* hostile to everyone */
 
193
}
 
194
 
 
195
/*------------------------------PLACEINDEPENDENT---------------------------*/
 
196
/*  This function places an independent player in the game so he is not
 
197
near any other players.  */
 
198
 
 
199
static void 
 
200
placeIndependent(void)
 
201
{
 
202
    int     i;                  /* ye olde looping var */
 
203
    struct player *p;           /* to point to players */
 
204
    int     good, failures;     /* flag for success, count of tries */
 
205
 
 
206
    failures = 0;               /* have started loops yet */
 
207
    while (failures < 10) {     /* only try 10 times */
 
208
        me->p_x = GWIDTH / 2 + (lrand48() % INDEP) - INDEP / 2; /* middle 9th of */
 
209
        me->p_y = GWIDTH / 2 + (lrand48() % INDEP) - INDEP / 2; /* galaxy */
 
210
        good = 1;
 
211
        for (i = 0, p = players; i < MAXPLAYER; i++, p++) {
 
212
            if ((p->p_status != PFREE) && (p != me)) {
 
213
                if ((ABS(p->p_x - me->p_x) < 2 * TRACTDIST) &&
 
214
                    (ABS(p->p_y - me->p_y) < 2 * TRACTDIST)) {
 
215
                    failures++; /* found a player too close */
 
216
                    good = 0;   /* position not good */
 
217
                    break;      /* try another positon */
 
218
                }
 
219
            }
 
220
        }
 
221
        if (good)               /* if good placement found then */
 
222
            return;             /* return */
 
223
    }
 
224
    fprintf(stderr, "Couldn't place the bot successfully.\n");
 
225
}
 
226
 
 
227
static int
 
228
findtestslot(void)
 
229
{
 
230
    register int i;
 
231
 
 
232
    for (i = MAXPLAYER - configvals->ntesters; i < MAXPLAYER; i++) {
 
233
        if (players[i].p_status == PFREE) {     /* We have a free slot */
 
234
            players[i].p_status = POUTFIT;      /* possible race code */
 
235
            break;
 
236
        }
 
237
    }
 
238
    if (i == MAXPLAYER) {
 
239
        return -1;              /* no room in tester slots */
 
240
    }
 
241
    memset(&players[i].p_stats, 0, sizeof(struct stats));
 
242
    players[i].p_stats.st_tticks = 1;
 
243
    return (i);
 
244
}
 
245
 
 
246
int
 
247
findrslot(void)
 
248
{
 
249
    register int i;
 
250
 
 
251
    /* look for tester slot first */
 
252
    i = findtestslot();
 
253
    if (i > -1)
 
254
        return i;
 
255
 
 
256
    for (i = 0; i < MAXPLAYER; i++) {
 
257
        if (players[i].p_status == PFREE) {     /* We have a free slot */
 
258
            players[i].p_status = POUTFIT;      /* possible race code */
 
259
            break;
 
260
        }
 
261
    }
 
262
    if ((i == MAXPLAYER) || (i == -1)) {
 
263
        return -1;
 
264
    }
 
265
    memset(&players[i].p_stats, 0, sizeof(struct stats));
 
266
    players[i].p_stats.st_tticks = 1;
 
267
    return (i);
 
268
}
 
269
 
 
270
/*------------------------------------ENTER-------------------------------*/
 
271
/*  This function places a player into the game.  It initializes fields in
 
272
the player structure and his ship.  It determines where in the galaxy to
 
273
put the player.  This function is also used to place robots and independents.
 
274
If tno = 4, then the player is independent.  If it is 5 then the player is
 
275
a robot.  */
 
276
 
 
277
/* CRD feature: starting planet (for robots) - MAK,  2-Jun-93
 
278
 * Also added starting planet number as a useful return value.
 
279
 */
 
280
 
 
281
/* args:
 
282
   tno - team player is on
 
283
   disp - "not used, so I used it 7/27/91 TC"
 
284
   pno - player's number
 
285
   s_type - player's ship type
 
286
   startplanet - planet to enter near (or -1) */
 
287
 
 
288
int 
 
289
enter(int tno, int disp, int pno, int s_type, int startplanet)
 
290
{
 
291
    static int lastteam = -1;   /* to hold team of last enter */
 
292
    static int lastrank = -1;   /* to hold rank of last enter */
 
293
    char    buf[80];            /* to sprintf into */
 
294
    char    buf2[80];           /* to sprintf into */
 
295
    char    addrbuf[10];        /* to hold address */
 
296
 
 
297
    if ((startplanet < 0) || (startplanet >= NUMPLANETS))
 
298
        startplanet = -1;
 
299
 
 
300
    (void) strncpy(me->p_name, pseudo, sizeof(me->p_name));     /* get name */
 
301
    me->p_name[sizeof(me->p_name) - 1] = '\0';  /* delimiet just in case */
 
302
 
 
303
    me->p_kills = 0.0;          /* have no kills yet */
 
304
    get_ship_for_player(me, s_type);    /* get the player's ship type */
 
305
 
 
306
    if (me->p_ship.s_nflags & SFNHASFIGHTERS)
 
307
        me->p_ship.s_missilestored = 0;
 
308
 
 
309
    me->p_docked = 0;           /* not docked to anyone */
 
310
    me->p_updates = 0;          /* start updating immediately */
 
311
    me->p_flags = PFSHIELD;
 
312
    if (allows_docking(me->p_ship))
 
313
        me->p_flags |= PFDOCKOK;/* enable docking */
 
314
    me->p_dir = 0;              /* direction angle of zero */
 
315
    me->p_desdir = 0;           /* desired direction of zero */
 
316
    me->p_speed = 0;            /* speed of zero */
 
317
    me->p_desspeed = 0;         /* desired speed of zero */
 
318
    me->p_subspeed = 0;         /* fractional part of speed zero */
 
319
 
 
320
/*  Gunboat docked to ships stuff */
 
321
    if ((me->p_ship.s_nflags & SFNMASSPRODUCED) &&
 
322
        (shipvals[shipPick].s_numports)) {
 
323
        int     i;
 
324
 
 
325
        me->p_team = (1 << tno);
 
326
        for (i = 0; i < MAXPLAYER; i++)
 
327
            if ((players[i].p_ship.s_type == shipPick) &&
 
328
                (players[i].p_team == me->p_team) &&
 
329
                (players[i].p_status == PALIVE) &&      /* if all this stuff... */
 
330
                (players[i].p_flags & PFDOCKOK) &&
 
331
                (players[i].p_docked < players[i].p_ship.s_numports) &&
 
332
                (players[i].p_ship.s_missilestored)) {
 
333
                me->p_x = players[i].p_x;       /* ...dock em on */
 
334
                me->p_y = players[i].p_y;
 
335
                newdock(i);
 
336
                if (players[i].p_ship.s_missilestored != -1)
 
337
                   players[i].p_ship.s_missilestored--;
 
338
                if (players[i].p_flags & PFCLOAK) {
 
339
                   me->p_flags |= PFCLOAK;
 
340
                   me->p_cloakphase = players[i].p_cloakphase;
 
341
                } else me->p_cloakphase = 0;
 
342
                break;
 
343
            }
 
344
    }
 
345
/* End Gunboat stuff */
 
346
 
 
347
    if ((tno == 4) || (tno == 5)) {     /* if player indep or a robot */
 
348
        me->p_team = 0;         /* he has no team */
 
349
    }
 
350
    else {                      /* else player is normal player--find planet */
 
351
        me->p_team = (1 << tno);/* set players team number */
 
352
 
 
353
        /* forgive me father, for I have used short-circuiting to
 
354
           emulate control flow */
 
355
        (startplanet >= 0       /* start planet already specified? */
 
356
         || (((startplanet = me->p_lastrefit) >= 0      /* we've got a home
 
357
                                                           planet */
 
358
              && (planets[startplanet].pl_flags & PLSHIPYARD)   /* and it's a yard */
 
359
              &&(planets[startplanet].pl_owner == me->p_team))  /* and it's ours */
 
360
             ||0 < (me->p_lastrefit = -1))      /* oops, no more home
 
361
                                                   shipyard, F */
 
362
         ||(startplanet = find_start_planet(me->p_team, PLSHIPYARD)) != -1
 
363
         || (startplanet = find_start_planet(me->p_team, PLREPAIR)) != -1
 
364
         || (startplanet = find_start_planet(me->p_team, PLAGRI)) != -1
 
365
         || (startplanet = find_start_planet(me->p_team, PLFUEL)) != -1
 
366
         || (startplanet = find_start_planet(me->p_team, PLHOME)) != -1
 
367
         || (startplanet = find_start_planet(me->p_team, 0)) != -1
 
368
            );
 
369
    }
 
370
    if (startplanet == -1) {
 
371
        placeIndependent();
 
372
    }
 
373
    else {
 
374
        int i;
 
375
        double dx, dy;
 
376
        struct planet *l;
 
377
 
 
378
        /* we have a planet */
 
379
        /* use p_x and y as scratch registers */
 
380
        while(1) {
 
381
            me->p_x = planets[startplanet].pl_x + (lrand48() % 10000) - 5000;
 
382
            me->p_y = planets[startplanet].pl_y + (lrand48() % 10000) - 5000;
 
383
            if (me->p_x < 0)    /* can't come in outside of borders */
 
384
                me->p_x = 0;    /* now can we?  */
 
385
            if (me->p_y < 0)
 
386
                me->p_y = 0;
 
387
            if (me->p_x >= GWIDTH)
 
388
                me->p_x = GWIDTH-1;
 
389
            if (me->p_y >= GWIDTH)
 
390
                me->p_y = GWIDTH-1;
 
391
            for(i = 0, l = &planets[0]; i < NUMPLANETS; i++, l++) {
 
392
                if(PL_TYPE(*l) == PLSTAR) {
 
393
                    dx = ABS(l->pl_x - me->p_x);
 
394
                    dy = ABS(l->pl_y - me->p_y);
 
395
                    if(dx * dx + dy * dy <
 
396
                                MIN_DIST_FROM_STAR * MIN_DIST_FROM_STAR)
 
397
                        break;
 
398
                }
 
399
            }
 
400
            if(i == NUMPLANETS)
 
401
                break;
 
402
        }
 
403
        /* legitimize p_x and p_y */
 
404
        move_player(me->p_no, me->p_x, me->p_y, 0);
 
405
    }
 
406
    me->p_ntorp = 0;            /* have not fired torps yete */
 
407
    if (!((me->p_ship.s_nflags & SFNMASSPRODUCED) &&
 
408
        (shipvals[shipPick].s_numports)))
 
409
       me->p_cloakphase = 0;    /* no cloaking phase--not cloaked */
 
410
    me->p_nplasmatorp = 0;      /* no plasma torps */
 
411
    me->p_swar = 0;             /* at war with nobody */
 
412
    me->p_armies = 0;           /* carrying no armies */
 
413
    tmpPick = 0;
 
414
 
 
415
    switch_special_weapon();
 
416
 
 
417
    if (!keeppeace)             /* if keep peace mode then */
 
418
        auto_peace();           /* set do automatic peace */
 
419
    me->p_hostile &= ~me->p_team;       /* hostile to all but own team */
 
420
    me->p_swar &= ~me->p_team;
 
421
    if ((lastteam != tno) || (lastrank != mystats->st_rank)) {
 
422
        if ((lastteam > 0) && (lastteam < NUMTEAM) && (lastteam != tno))
 
423
            declare_war((1 << lastteam) | me->p_hostile);       /* if changing then
 
424
                                                                   adjust war stat */
 
425
        lastteam = tno;         /* store team number in static */
 
426
        lastrank = mystats->st_rank;    /* store rank in static */
 
427
        sprintf(addrbuf, " %s->ALL", twoletters(me));
 
428
        if ((tno == 4) && (strcmp(me->p_monitor, "Nowhere") == 0)) {
 
429
            time_t  curtime;    /* if a robot and independent */
 
430
            struct tm *tmstruct;/* to hold time */
 
431
            int     queuesize;  /* to hold queue size */
 
432
            int     hour;       /* to hold hour */
 
433
 
 
434
            time(&curtime);     /* get the time */
 
435
            tmstruct = localtime(&curtime);     /* convert to local time */
 
436
            if (!(hour = tmstruct->tm_hour % 12))       /* get the hour */
 
437
                hour = 12;
 
438
            sprintf(buf, "It's %d:%02d%s, time to die.", hour, tmstruct->tm_min,
 
439
                    tmstruct->tm_hour >= 12 ? "pm" : "am");
 
440
            if ((queuesize = status->count - status->wait) > 0) {
 
441
                /* lint: queuesize set but not used in function enter */
 
442
                sprintf(buf2, "  Approximate queue size: %d.", status->answer);
 
443
                strcat(buf, buf2);      /* get queue size if queue */
 
444
            }
 
445
            pmessage2(buf, 0, MALL, addrbuf, me->p_no); /* display message */
 
446
        }
 
447
        else if (tno == 5) {    /* if a robot then */
 
448
            if (players[disp].p_status != PFREE) {
 
449
                sprintf(buf2, "%s has been targeted for termination.",
 
450
                        twoletters(&players[disp]));
 
451
                pmessage2(buf2, 0, MALL, addrbuf, me->p_no);
 
452
            }
 
453
        }
 
454
 
 
455
        if (!status2->league)   /* no peanut messages in a league game */
 
456
            peanut_gallery();   /* check for important people */
 
457
 
 
458
        if (me->p_stats.st_royal == 0)
 
459
            sprintf(buf, "%s %.16s is now %2.2s (%.16s@%.32s)",
 
460
                    ranks[me->p_stats.st_rank].name, me->p_name,
 
461
                    twoletters(me), me->p_login, me->p_full_hostname);
 
462
        else
 
463
            sprintf(buf, "%s %.16s is now %2.2s (%.16s@%.32s)",
 
464
                    royal[me->p_stats.st_royal].name, me->p_name,
 
465
                    twoletters(me), me->p_login, me->p_full_hostname);
 
466
 
 
467
        pmessage2(buf, 0, MALL | MJOIN, addrbuf, me->p_no);
 
468
 
 
469
        advertise_tourney_queue();
 
470
 
 
471
    }
 
472
    delay = 0;
 
473
    return startplanet;
 
474
}
 
475
 
 
476
/*----------END OF FILE--------*/