view src/enter.c @ 2:2719a89505ba

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:01 +0000
parents
children
line wrap: on
line source

/*--------------------------------------------------------------------------
NETREK II -- Paradise

Permission to use, copy, modify, and distribute this software and its
documentation, or any derivative works thereof, for any NON-COMMERCIAL
purpose and without fee is hereby granted, provided that this copyright
notice appear in all copies.  No representations are made about the
suitability of this software for any purpose.  This software is provided
"as is" without express or implied warranty.

    Xtrek Copyright 1986                            Chris Guthrie
    Netrek (Xtrek II) Copyright 1989                Kevin P. Smith
                                                    Scott Silvey
    Paradise II (Netrek II) Copyright 1993          Larry Denys
                                                    Kurt Olsen
                                                    Brandon Gillespie
--------------------------------------------------------------------------*/


#include "config.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <pwd.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "defs.h"
#include "struct.h"
#include "data.h"
#include "shmem.h"
#include "grid.h"

void auto_peace();
static void placeIndependent();
extern int
pmessage2(			/* char *str, int recip, int group, char
	      address, unsigned char from */ );
extern int
pmessage(			/* char *str, int recip, int group, char
	     address */ );



/*------------------------------NUMBER DEFINES-----------------------------*/
#define INDEP (GWIDTH/3)	/* width of region in the center of galaxy */
/* that independents can join in */

#define MIN_DIST_FROM_STAR 3000.0	/* min distance from a star that
					 * enter() */
/* will place you */
/*-------------------------------------------------------------------------*/


int
find_start_planet(team, flag)
  int team, flag;
{
  int valid[MAXPLANETS];
  int nvalid;
  int i;

  nvalid = 0;
  for (i = 0; i < NUMPLANETS; i++)
  {
    struct planet *pl = &planets[i];
    if (pl->pl_owner == team && (!flag || pl->pl_flags & flag))
      valid[nvalid++] = i;
  }
  if (nvalid < 1)
    return -1;

  return valid[lrand48() % nvalid];
}



/*------------------------------VISIBLE FUNCTIONS-------------------------*/

#define BOSSMAN		NUMROYALRANKS-1
#define SIDEKICK	NUMROYALRANKS-2
#define AMBASSADOR	NUMROYALRANKS-3

#ifdef UFL
#undef SIDEKICK
#define SIDEKICK	NUMROYALRANKS-1
#undef AMBASSADOR
#define AMBASSADOR	NUMROYALRANKS-1
#endif

/*--------------------------------PEANUT_GALLERY--------------------------*/
/*
 * This function checks too see if certain "important" people have logged in,
 * and displays a special message to the rest of the players.  As the chief
 * Paradise hack, I forbid removal of any of the code in this function.
 * Other names may be added.  If you choose to disregard this, a malefiction
 * will be leveled upon your head and all of your progeny will be born with
 * their noses two times too large.
 */

#define AT_LEAST(rank) if (me->p_stats.st_royal<rank) me->p_stats.st_royal = rank;


void
peanut_gallery()
{
  char buf[90];

  if (strcmp(me->p_name, "a fungusamongus") == 0)
  {				/* that's me! */
    pmessage2("  ", 0, MALL, "LDDENYS > ", me->p_no);
    pmessage2("Yikes.  EEK!  Help.  There seems to be a fungus among us!", 0, MALL, "LDDENYS > ", me->p_no);
    pmessage2("  ", 0, MALL, "LDDENYS > ", me->p_no);

  }
  else if (strcmp(me->p_name, "Lynx") == 0)
  {
    pmessage2("\"GAME OVER MAN, GAME OVER!\"", 0, MALL, "Lynx->ALL ", me->p_no);

  }
  else if (strcmp(me->p_name, "Hammor") == 0)
  {
    pmessage2("Please don't hurt 'em, Hammor!", 0, MALL, "GOD->ALL", me->p_no);

  }
  else if (strcmp(me->p_name, "Bubbles") == 0)
  {
    pmessage2("Whoa!", 0, MALL, "KAOLSEN > ", me->p_no);
    pmessage2("Dudes.", 0, MALL, "KAOLSEN > ", me->p_no);
    pmessage2("Cool.", 0, MALL, "KAOLSEN > ", me->p_no);

  }
  else if (strcmp(me->p_name, "KnightRaven") == 0)
  {
    pmessage2("Insert Heiji quote here", 0, MALL, "KAOLSEN > ", me->p_no);
    AT_LEAST(AMBASSADOR);

  }
  else if (strcmp(me->p_name, "wibble") == 0)
  {
    pmessage("No mountain is unclimbable, no river uncrossable, no client RSA"
	     ,0, MALL, "EGO->wibble", me->p_no);
    pmessage("key unbreakable.  We can just make it bloody difficult!",
	     0, MALL, "EGO->wibble", me->p_no);

  }
  else if (strcmp(me->p_name, "Key") == 0)
  {
    time_t curtime;
    struct tm *tmstruct;
    int hour;

    (void) time(&curtime);
    tmstruct = localtime(&curtime);
    if (!(hour = tmstruct->tm_hour % 12))
      hour = 12;

    sprintf(buf, "It's %d:%02d%s, time [for me] to die.", hour,
	    tmstruct->tm_min, tmstruct->tm_hour >= 12 ? "pm" : "am");
    pmessage(buf, 0, MALL, "GOD->ALL", me->p_no);

  }
  else if (strcmp(me->p_name, "MikeL") == 0)
  {
    pmessage("<This space for rent>", 0, MALL, "GOD->ALL", me->p_no);


  }
  else if (strcmp(me->p_name, "Bolo") == 0)
  {
    pmessage("Bolo Mk. MCLXVII On-line.", 0, MALL, MSERVA, me->p_no);
  }
}



void
advertise_tourney_queue()
{
  char buf[80], addrbuf[10];
  int count = 0;
  int i;

  if (status->tourn)
    return;

  for (i = 0; i < MAXPLAYER; i++)
  {
    if (players[i].p_status == PTQUEUE)
      count++;
  }

  sprintf(addrbuf, "%s->YOU ", SERVNAME);
  sprintf(buf, "There %s %d player%s on the tournament queue",
	  (count == 1) ? "is" : "are", count, (count == 1) ? "" : "s");
  pmessage(buf, me->p_no, MINDIV, addrbuf);
}




/*------------------------------------ENTER-------------------------------*/
/*
 * This function places a player into the game.  It initializes fields in the
 * player structure and his ship.  It determines where in the galaxy to put
 * the player.  This function is also used to place robots and independents.
 * If tno = 4, then the player is independent.  If it is 5 then the player is
 * a robot.
 */

/*
 * CRD feature: starting planet (for robots) - MAK,  2-Jun-93 Also added
 * starting planet number as a useful return value.
 */

int
enter(tno, disp, pno, s_type, startplanet)
  int tno;			/* team player is on */
  int disp;			/* not used, so I used it 7/27/91 TC */
  int pno;			/* player's number */
  int s_type;			/* player's ship type */
  int startplanet;		/* planet to enter near (or -1) */
{
  static int lastteam = -1;	/* to hold team of last enter */
  static int lastrank = -1;	/* to hold rank of last enter */
  char buf[80];			/* to sprintf into */
  char buf2[80];		/* to sprintf into */
  char addrbuf[10];		/* to hold address */

  if ((startplanet < 0) || (startplanet >= NUMPLANETS))
    startplanet = -1;

  (void) strncpy(me->p_name, pseudo, sizeof(me->p_name));	/* get name */
  me->p_name[sizeof(me->p_name) - 1] = '\0';	/* delimiet just in case */

  me->p_kills = 0.0;		/* have no kills yet */
  get_ship_for_player(me, s_type);	/* get the player's ship type */

  if (me->p_ship.s_nflags & SFNHASFIGHTERS)
    me->p_ship.s_missilestored = 0;

  me->p_docked = 0;		/* not docked to anyone */
  me->p_updates = 0;		/* start updating immediately */
  me->p_flags = PFSHIELD;
  if (allows_docking(me->p_ship))
    me->p_flags |= PFDOCKOK;	/* enable docking */
  me->p_dir = 0;		/* direction angle of zero */
  me->p_desdir = 0;		/* desired direction of zero */
  me->p_speed = 0;		/* speed of zero */
  me->p_desspeed = 0;		/* desired speed of zero */
  me->p_subspeed = 0;		/* fractional part of speed zero */

  /* Gunboat docked to ships stuff */
  if ((me->p_ship.s_nflags & SFNMASSPRODUCED) &&
      (shipvals[shipPick].s_numports))
  {
    int i;

    me->p_team = (1 << tno);
    for (i = 0; i < MAXPLAYER; i++)
      if ((players[i].p_ship.s_type == shipPick) &&
	  (players[i].p_team == me->p_team) &&
	  (players[i].p_status == PALIVE) &&	/* if all this stuff... */
	  (players[i].p_flags & PFDOCKOK) &&
	  (players[i].p_docked < players[i].p_ship.s_numports) &&
	  (players[i].p_ship.s_missilestored))
      {
	me->p_x = players[i].p_x;	/* ...dock em on */
	me->p_y = players[i].p_y;
	newdock(i);
	if (players[i].p_ship.s_missilestored != -1)
	  players[i].p_ship.s_missilestored--;
	if (players[i].p_flags & PFCLOAK)
	{
	  me->p_flags |= PFCLOAK;
	  me->p_cloakphase = players[i].p_cloakphase;
	}
	else
	  me->p_cloakphase = 0;
	break;
      }
  }
  /* End Gunboat stuff */

  if ((tno == 4) || (tno == 5))
  {				/* if player indep or a robot */
    me->p_team = 0;		/* he has no team */
  }
  else
  {				/* else player is normal player--find planet */
    me->p_team = (1 << tno);	/* set players team number */

    /*
     * forgive me father, for I have used short-circuiting to emulate control
     * flow
     */
    (startplanet >= 0		/* start planet already specified? */
     || (((startplanet = me->p_lastrefit) >= 0	/* we've got a home planet */
	  && (planets[startplanet].pl_flags & PLSHIPYARD)	/* and it's a yard */
	  && (planets[startplanet].pl_owner == me->p_team))	/* and it's ours */
	 || 0 < (me->p_lastrefit = -1))	/* oops, no more home shipyard, F */
     || (startplanet = find_start_planet(me->p_team, PLSHIPYARD)) != -1
     || (startplanet = find_start_planet(me->p_team, PLREPAIR)) != -1
     || (startplanet = find_start_planet(me->p_team, PLAGRI)) != -1
     || (startplanet = find_start_planet(me->p_team, PLFUEL)) != -1
     || (startplanet = find_start_planet(me->p_team, PLHOME)) != -1
     || (startplanet = find_start_planet(me->p_team, 0)) != -1
      );
  }
  if (startplanet == -1)
  {
    placeIndependent();
  }
  else
  {
    int i;
    double dx, dy;
    struct planet *l;

    /* we have a planet */
    /* use p_x and y as scratch registers */
    while (1)
    {
      me->p_x = planets[startplanet].pl_x + (lrand48() % 10000) - 5000;
      me->p_y = planets[startplanet].pl_y + (lrand48() % 10000) - 5000;
      if (me->p_x < 0)		/* can't come in outside of borders */
	me->p_x = 0;		/* now can we?  */
      if (me->p_y < 0)
	me->p_y = 0;
      if (me->p_x >= GWIDTH)
	me->p_x = GWIDTH - 1;
      if (me->p_y >= GWIDTH)
	me->p_y = GWIDTH - 1;
      for (i = 0, l = &planets[0]; i < NUMPLANETS; i++, l++)
      {
	if (PL_TYPE(*l) == PLSTAR)
	{
	  dx = ABS(l->pl_x - me->p_x);
	  dy = ABS(l->pl_y - me->p_y);
	  if (dx * dx + dy * dy <
	      MIN_DIST_FROM_STAR * MIN_DIST_FROM_STAR)
	    break;
	}
      }
      if (i == NUMPLANETS)
	break;
    }
    /* legitimize p_x and p_y */
    move_player(me->p_no, me->p_x, me->p_y, 0);
  }
  me->p_ntorp = 0;		/* have not fired torps yete */
  if (!((me->p_ship.s_nflags & SFNMASSPRODUCED) &&
	(shipvals[shipPick].s_numports)))
    me->p_cloakphase = 0;	/* no cloaking phase--not cloaked */
  me->p_nplasmatorp = 0;	/* no plasma torps */
  me->p_swar = 0;		/* at war with nobody */
  me->p_armies = 0;		/* carrying no armies */
  tmpPick = 0;

  switch_special_weapon();

  if (!keeppeace)		/* if keep peace mode then */
    auto_peace();		/* set do automatic peace */
  me->p_hostile &= ~me->p_team;	/* hostile to all but own team */
  me->p_swar &= ~me->p_team;
#if 0
  sprintf(buf, "%c%c", teamlet[me->p_team], shipnos[me->p_no]);
  strncpy(me->p_mapchars, buf, 2);
#endif
  if ((lastteam != tno) || (lastrank != mystats->st_rank))
  {
    if ((lastteam > 0) && (lastteam < NUMTEAM) && (lastteam != tno))
      declare_war((1 << lastteam) | me->p_hostile);	/* if changing then
							 * adjust war stat */
    lastteam = tno;		/* store team number in static */
    lastrank = mystats->st_rank;/* store rank in static */
    sprintf(addrbuf, " %s->ALL", twoletters(me));
    if ((tno == 4) && (strcmp(me->p_monitor, "Nowhere") == 0))
    {
      time_t curtime;		/* if a robot and independent */
      struct tm *tmstruct;	/* to hold time */
      int queuesize;		/* to hold queue size */
      int hour;			/* to hold hour */

      time(&curtime);		/* get the time */
      tmstruct = localtime(&curtime);	/* convert to local time */
      if (!(hour = tmstruct->tm_hour % 12))	/* get the hour */
	hour = 12;
      sprintf(buf, "It's %d:%02d%s, time to die.", hour, tmstruct->tm_min,
	      tmstruct->tm_hour >= 12 ? "pm" : "am");
      if ((queuesize = status->count - status->wait) > 0)
      {
	/* lint: queuesize set but not used in function enter */
	sprintf(buf2, "  Approximate queue size: %d.", status->answer);
	strcat(buf, buf2);	/* get queue size if queue */
      }
      pmessage2(buf, 0, MALL, addrbuf, me->p_no);	/* display message */
    }
    else if (tno == 5)
    {				/* if a robot then */
      if (players[disp].p_status != PFREE)
      {
	sprintf(buf2, "%s has been targeted for termination.",
		twoletters(&players[disp]));
	pmessage2(buf2, 0, MALL, addrbuf, me->p_no);
      }
    }
#ifdef LEAGUE_SUPPORT
    if (!status2->league)	/* no peanut messages in a league game */
#endif
      peanut_gallery();		/* check for important people */

    if (me->p_stats.st_royal == 0)
      sprintf(buf, "%s %.16s is now %2.2s (%.16s@%.32s)",
	      ranks[me->p_stats.st_rank].name, me->p_name,
	      twoletters(me), me->p_login, me->p_full_hostname);
    else
      sprintf(buf, "%s %.16s is now %2.2s (%.16s@%.32s)",
	      royal[me->p_stats.st_royal].name, me->p_name,
	      twoletters(me), me->p_login, me->p_full_hostname);

    pmessage2(buf, 0, MALL | MJOIN, addrbuf, me->p_no);

#if 1
    advertise_tourney_queue();
#endif

  }
  delay = 0;
  return startplanet;
}




/*--------------------------------AUTOPEACE------------------------------*/
/*
 * This function set the player as hostile to all teams with at least one
 * player on them if it is t-mode.  Otherwise if it is not t-mode the player
 * is set as hositle to everyone.
 */

void
auto_peace()
{
  int i, num[MAXTEAM + 1];	/* to hold team's player counts */
  struct player *p;		/* looping var */

  num[0] = num[FED] = num[ROM] = num[KLI] = num[ORI] = 0;	/* zero counts */
  for (i = 0, p = players; i < MAXPLAYER; i++, p++)	/* loop all players */
    if (p->p_status != PFREE)	/* ince the count of the team the */
      num[p->p_team]++;		/* player is on */
  if (status->tourn)		/* if t-mode then make player hostile */
    me->p_hostile =		/* make all teams with a player on */
      ((FED * (num[FED] >= configvals->tournplayers)) |
       (ROM * (num[ROM] >= configvals->tournplayers)) |
       (KLI * (num[KLI] >= configvals->tournplayers)) |
       (ORI * (num[ORI] >= configvals->tournplayers)));
  else				/* else if not t-mode then */
    me->p_hostile = FED | ROM | KLI | ORI;	/* hostile to everyone */
}




/*------------------------------PLACEINDEPENDENT---------------------------*/
/*
 * This function places an independent player in the game so he is not near
 * any other players.
 */

static void
placeIndependent()
{
  int i;			/* ye olde looping var */
  struct player *p;		/* to point to players */
  int good, failures;		/* flag for success, count of tries */

  failures = 0;			/* have started loops yet */
  while (failures < 10)
  {				/* only try 10 times */
    me->p_x = GWIDTH / 2 + (lrand48() % INDEP) - INDEP / 2;	/* middle 9th of */
    me->p_y = GWIDTH / 2 + (lrand48() % INDEP) - INDEP / 2;	/* galaxy */
    good = 1;
    for (i = 0, p = players; i < MAXPLAYER; i++, p++)
    {
      if ((p->p_status != PFREE) && (p != me))
      {
	if ((ABS(p->p_x - me->p_x) < 2 * TRACTDIST) &&
	    (ABS(p->p_y - me->p_y) < 2 * TRACTDIST))
	{
	  failures++;		/* found a player too close */
	  good = 0;		/* position not good */
	  break;		/* try another positon */
	}
      }
    }
    if (good)			/* if good placement found then */
      return;			/* return */
  }
  fprintf(stderr, "Couldn't place the bot successfully.\n");
}




/*------------------------------------------------------------------------*/




/*----------END OF FILE--------*/