/
lib/banish/
lib/d/coronos/
lib/d/coronos/w/alena/
lib/d/coronos/w/angel/
lib/d/coronos/w/angel/caves/
lib/d/coronos/w/angel/caves/monst/
lib/d/coronos/w/angel/city/chambers/
lib/d/coronos/w/angel/city/monst/
lib/d/coronos/w/angel/city/obj/
lib/d/coronos/w/angel/city/streets/
lib/d/coronos/w/angel/farms/plains/
lib/d/coronos/w/angel/monst/
lib/d/tempus/
lib/d/tempus/w/angel/
lib/d/tempus/w/kingbill/
lib/d/tempus/w/mirak/
lib/d/tempus/w/mirak/monst/
lib/d/tempus/w/mirak/obj/
lib/d/tempus/w/relgar/planes/baat/
lib/d/tempus/w/sarak/
lib/d/tempus/w/serepion/mon/
lib/d/tempus/w/valrejn/
lib/doc/
lib/doc/domains/
lib/doc/efun/
lib/include/fn_specs/
lib/info/
lib/inherit/base/
lib/log/
lib/log/mailbox/
lib/log/main/
lib/news/
lib/obj/party/
lib/objects/componen/
lib/open/
lib/open/party/
lib/open/paste/
lib/open/spells/
lib/open/valrejn/
lib/players/
lib/players/alena/
lib/players/alena/obj/
lib/players/alena/open/
lib/players/alena/private/
lib/players/angel/
lib/players/angel/obj/
lib/players/ash/
lib/players/biggs/
lib/players/biggs/food/
lib/players/biggs/gobkeep/
lib/players/biggs/mnstr/
lib/players/biggs/town/caves/
lib/players/biggs/town/tower/
lib/players/biggs/wpns/
lib/players/calris/
lib/players/deathurg/
lib/players/deathurg/open/
lib/players/deathurg/private/thief/
lib/players/dogberry/
lib/players/dogberry/library/
lib/players/dogberry/open/
lib/players/epsilon/
lib/players/epsilon/private/
lib/players/farewell/
lib/players/hippo/
lib/players/hippo/open/
lib/players/hippo/tools/
lib/players/jimpa/
lib/players/josh/
lib/players/josh/room/
lib/players/josh/room/mage/dungeon/
lib/players/josh/room/mage/dungeon/obj/
lib/players/josh/wep/
lib/players/kingbill/
lib/players/metatron/
lib/players/miette/
lib/players/mirak/
lib/players/mirak/open/
lib/players/parsilan/
lib/players/relgar/
lib/players/relgar/private/
lib/players/sarak/
lib/players/sarak/bugs/
lib/players/sarak/feelings/
lib/players/sarak/magical/
lib/players/sarak/minotaur/island/
lib/players/sarak/open/
lib/players/sarak/private/
lib/players/serepion/
lib/players/serepion/open/
lib/players/serepion/private/
lib/players/spike/
lib/players/spike/open/
lib/players/spike/private/
lib/players/spike/seaworld/
lib/players/valrejn/
lib/players/valrejn/open/
lib/players/valrejn/private/
lib/players/virus/
lib/players/wrath/
lib/players/wrath/arm/
lib/players/wrath/mon/
lib/players/wrath/room/
lib/players/wrath/room/entry/
lib/players/wrath/room/zolgath/
lib/players/wrath/weap/
lib/players/zil/
lib/room/
lib/room/city/arena/
lib/room/city/creator/
lib/room/city/garden/monst/
lib/room/city/library/
lib/room/city/library/open/books/
lib/room/city/shop/
lib/room/death/
lib/room/death/open/
lib/room/island/
lib/room/keeps/
lib/room/registry/
lib/room/ships/crew/
lib/room/ships/open/
lib/room/ships/open/types/bounty/
lib/room/ships/open/types/nebula/
lib/room/ships/open/types/phoenix/
lib/secure/udp_cmd_/
lib/skills/
lib/skills/fighter/
lib/skills/psionici/
lib/skills/thief/
lib/usr/
lib/usr/creators/
lib/usr/no_banis/
lib/usr/players/
/* Sailing Ship v3.03, Angel January 1994.
 *
 * This sailing ship is designed to travel between ports of call,
 * organised into an array read from the open directory within
 * /room/islands/open. Any player can write a jetty of their own which
 * they want the ship to visit on its route around the realms.
 * It is designed to be copied, altered, and inherited as needed.
 *
 * The ships are also in an open dir so that players can buy ships
 * with automatic writes to the directory
 */

#define PORT_FILE             "/room/ships/open/ports.h"
#define SHIP_DIR              "/room/ships/open/types/"
#define DISTANCE              "/room/ships/distance"
#define START                 "/room/city/jetty"
#define ABANDON_SHIP          "/room/island/beach5"
#define SHIP_OB_FILE          "stern"     /* where to find other ship fns  */

#define NAME                  (string)this_player()->query_name()
#define SHIP_NAME             capitalize(this_object()->query_short())
#define CAPTAIN               "Captain"

#define WAIT_TIME             60       /* a few minutes                  */
#define X                     0        /* members of an array for coords */
#define Y                     1
#define SPEED                 5        /* default speed of ship          */
#define SIGHT_RANGE           100      /* range of the looking glass     */
#define CLOSE_ENUFF           2
#define HP                    1000     /* hp for the ship                */

#include <mudlib.h>
#include <linewrap.h>
#include PORT_FILE

inherit ROOM;

mixed *destinations;          /* places to sail to                 */
status sailing;               /* for the init to set_heart_beat()  */
status waiting;               /* if the ship is waiting to move on */

string ship_name;             /* name of the ship for exit array   */
string captain;               /* captain's name */

string port, port_file, port_long, port_list;
int timer, counter, distance, *old_port_coords, *port_coords, wait_time;
int speed, hull_points;

/*************************************************************************/
/* Fn Specs */
int    query_coordinates();
mixed *check_ships();
void   set_sail(string str);
void   msg(string message);


/*************************************************************************/
/* Room Stuff */
void reset(status arg) {
  string txt;
  if(arg) return;

  set_short("the sutherland");
  set_long(
     "A tall mast with spinnaker flying from it towers above you on this \n"+
     "grand sailing ship. Three other sails are full with the sea winds  \n"+
     "pushing the ship ever closer to its port of call; your destination.\n");

  set_items(({
     "spinnaker",
          "A huge sail full of wind. Upon the spinnaker is a design \n"+
          "of a naked woman with the lower body of a great wave",
     "mast",
          "The spinnaker flies from the mast",
     "ship",
          "You're standing on it",
     "sail#sails",
          "The wind fills them, pushing the ship along in the water",
     "wind#winds", 
          "You can't see the wind!",  /* someone is bound to do it! */
     "sea#water#wave#waves",
          "They crash against the ship, making it toss up and "+
          "down in the water",
     "wheel",
          "The ships wheel is painted a rusty brown, matching the wood \n"+
          "on the rest of the ship. Beside it is a compass, as well as "+
          "a brass telescope",
  }));

  set_weather(2, 4, 6);
  set_exits(({  "room/city/jetty", "gang plank",  }));

  set_night_desc(
     "A lantern hangs by the wheel, lighting the upper decks.\n");
  set_night_items(({
     "lantern", "A simple oil lantern made from brass",
  }));

}


void long(status wiz) {
  string tmp, temp;
  ::long(wiz);

  temp = capitalize(ship_name);
  tmp = "There is a map beside the ships' wheel with the destination "+
        capitalize(destinations[counter][0]+" circled in ink. ");

  if(hull_points > hull_points/2)
    tmp += "The "+temp+" is in excelent shape.\n";
  else if(hull_points > hull_points/3)
    tmp += "The "+temp+" is looking a little shabby.\n";
  else if(hull_points > hull_points/4)
    tmp += "The "+temp+" is showing some wear and tear.\n";
  else if(hull_points > hull_points/5)
    tmp += "The "+temp+" looks quite damaged.\n";
  else
    tmp += "The "+temp+" is falling appart!\n";
  if(hull_points < 0)
    tmp += "The "+temp+" is sinking!\n";
  writelw(tmp);
}


void init() {
  if(!sailing) {
    if(!destinations) {
      destinations = PORTS;  /* from the included file */
      destinations += ({ ({ "tempus city",  START, ({ 0, 0, }), }), });
      /* array is as follows: harbour       file   ({ x,y coords }) */
    }
    if(!wait_time)   wait_time   = WAIT_TIME;
    if(!captain)     captain     = CAPTAIN;
    if(!hull_points) hull_points = HP;
    if(!ship_name)   ship_name   = "sutherland";   /* data's nebula ship! */

    counter = 0;
    port_file = START;  /* where we start off */
    port = "skol island";
    old_port_coords = ({ 0, 0, });
    port_long = port_file -> query_long();
    call_out("set_sail", WAIT_TIME, destinations[0][0]);
    sailing = 1;
    waiting = 1;
    distance = 141;   /* an arbitary distance */
  }

  ::init();
}

/*************************************************************************/
/* Special looks at functions */
status look_at(string str) {
  string tmp, tmp1, tmp2;
  int i, j, *ship_xy, *my_xy, *dest_xy;
  string ship_file;
  mixed *ships;

  if(str == "map") {
    tmp = "The map shows that the ship has many destinations, including ";
    for(i=0; i<sizeof(destinations); i++) {
      if((sizeof(destinations)-1) == i)
        tmp += "and "+capitalize(destinations[i][0])+". ";
      else
        tmp += capitalize(destinations[i][0])+", ";
    }
    tmp += "From the map "+capitalize(destinations[counter][0])+
           " is about "+(distance - timer)+" nautical miles away from here.\n";
    writelw(tmp);
    return 1;
  }


  if(str == "compass") {
    tmp     = "From the compass settings you think you're sailing in ";
    my_xy   = (int *)this_object()->query_coordinates();
    dest_xy = (int *)this_object()->query_port_coords();

    tmp1 = (string)DISTANCE -> calc_direction(my_xy, dest_xy);
    if(tmp1[0] == 'e') tmp += "an "+tmp1;
    else
      tmp += "a "+tmp1;

    tmp += "erly direction.\n";
    writelw(tmp);
    return 1;
  }


  if(str == "telescope") {
    ships = check_ships();  /* placement of other ships ...except outs */

    write("You look through the telescope...\n");
    say(this_player()->query_name()+" looks through the telescope.\n",
      this_player());

    if(!sizeof(ships))
      write("There are no ships within sight.\n");
    else {
      for(i=0; i<sizeof(ships); i++) {
        if(ships[i][1] < SIGHT_RANGE) {
          tmp  = "You can see the ";
          tmp += capitalize(ships[i][0]);
          if(ships[i][1] < CLOSE_ENUFF)
            tmp += ". It's only a few yards ";
          else {
            tmp += ". It's about "+ships[i][1]+" nautical miles ";
            tmp += ships[i][2]+" from here.\n";
          }
          j++;
          writelw(tmp);
        }
      } 
    }
    if(!j) {
      write("There are no ships within sight.\n");
    }

    if((distance - timer) < SIGHT_RANGE) {
      write("You can see that "+capitalize(port)+" is only "+
      (distance - timer)+" nautical miles away.\n");
    }
    else {
      write("You can't see your destination yet.\n");
    }
    return 1;
  } 

          
  return ::look_at(str);
}
/*************************************************************************/
/* Set Funs */
int set_ship_hp(int i)              { return hull_points = i;    }
int set_ship_speed(int i)           { return speed = i;          }
int set_wait_time(int i)            { return wait_time = i;      }
mixed *set_destinations(mixed *arr) { return destinations = arr; }
string set_ship_name(string str)    { return ship_name = str;    }
string set_captain(string str)      { return captain = str;      }


/*************************************************************************/
/* Major Ship Sailing Fn */
void heart_beat() {
  mixed *arr;
  int i;

  if(!speed && hull_points > 0) speed = SPEED;
  timer += speed;

  /* wait for a while before setting off again */
  if(waiting) {
    if(timer > WAIT_TIME) {
      set_sail(destinations[counter][0]);
      timer = 0;
      waiting = 0;
      return;
    }
  }


  if(timer >= distance) {
    msg("The ship finally reaches "+capitalize(port)+".\n"+
        capitalize(captain)+" says: Right then, we're here mates!\n"+
        "The gang plank is pulled out toward the jetty\n");


    port_long = port_file->query_long();
    port_file -> set_long(port_long+
          SHIP_NAME+" has dropped anchor here, "+
          "in the harbour.\n");
    this_object() -> add_exit(port_file, "gang plank");
    port_file -> add_exit(file_name(this_object()), ship_name);
    port_file -> add_item("gang plank#plank", "It leads onto the "+ship_name);
    port_file -> add_item(ship_name, 
          SHIP_NAME+", with its gang plank set down close by.\n"+
          "The ship looks as if it may set sail at any moment");

    tell_room(port_file, SHIP_NAME+" sails into the harbour...\n");
    old_port_coords = destinations[counter][2];  /* where we are now */

    if(counter >= sizeof(destinations)-1)
      counter = 0;  /* next destination */
    else
      counter ++;
    waiting = 1;    /* wait for a little while before setting off */
    timer = 0;
    return;
  }    
  if(!random(10)) {
    if(arr = check_ships())
    for(i=0; i<sizeof(arr); i++) {
      if(arr[i][1] < CLOSE_ENUFF) {
        msg("You notice the "+capitalize(arr[i][0])+" passing close by to "+
        "the "+arr[i][2]+"...\n");
      }
    }
  }

}


void set_sail(string str) {
  msg(capitalize(captain)+" exclaims: Right then maties! Set sail for "+
    capitalize(str)+" harbour!\n");

  set_heart_beat(1);
  if(port_file) {  /* put the room back the way we found it */
    port_file -> remove_exit(ship_name);
    port_file -> remove_item("gang plank#plank");
    port_file -> remove_item(ship_name);
    port_file -> set_long(port_long);  
    tell_room(port_file, SHIP_NAME+" sails out of the harbour...\n");
  }

  this_object() -> remove_exit("gang plank");
  port        = destinations[counter][0];
  port_file   = destinations[counter][1];
  port_coords = destinations[counter][2];  /* where we want to go */

  /* calc distance from here to there */
  distance = (int)DISTANCE->calc_distance(port_coords, old_port_coords);
  msg("The anchor is pulled up onto the deck.\n");
  msg("The gang plank is pulled in, and the ship sets sail.\n");

  timer   = 0;
  waiting = 0;
  return; 
}


mixed *check_ships() {
  int i, j, *dest_xy, *my_xy;
  string *ships, tmp, ship_file, k;
  mixed *result;

  ships = get_dir(SHIP_DIR);
  if(!sizeof(ships)) return 0;
  result = ({});

  for(i=0; i<sizeof(ships); i++) {
    if(!sscanf(ships[i], "%s.c", tmp)) {
      ship_file = SHIP_DIR+ships[i]+"/"+SHIP_OB_FILE;

      if((string)ship_file->query_ship_name() != 
        ((string)this_object()->query_ship_name())) {

        dest_xy = (int *)call_other(ship_file, "query_coordinates");
        my_xy   = (int *)this_object()->query_coordinates();

        if(dest_xy && my_xy) {
          j = (int)DISTANCE->calc_distance(my_xy, dest_xy);
          tmp =  capitalize((string)ship_file->query_ship_name());
          k = (string)DISTANCE->calc_direction(my_xy, dest_xy);
          result += ({ ({ tmp, j, k, }), });
        }
      }
    }
  }
  return result;
} 


mixed *query_coordinates() {
  int x1, x2, y1, y2, dx, dy;
  int gradient;
  int x, y;

  if(waiting) return old_port_coords;
  if(!timer) return old_port_coords;

  x1 = old_port_coords[X];  x2 = port_coords[X];
  y1 = old_port_coords[Y];  y2 = port_coords[Y];

  dx = x2 - x1;
  dy = y2 - y1;

  x = (dx * timer)/distance;
  y = (dy * timer)/distance;
  return ({ (x1 + x), (y1 + y), });
}

void msg(string message) {
  tell_room(this_object(), message);
  return;
}

int hit_ship(int dmg) {  
  hull_points -= dmg;
  if(hull_points < 0) {
    msg("The ship starts to sink!\n");
    msg(capitalize(captain)+" exclaims: Abandon ship! We're sinking!\n");
    set_heart_beat(0);
    this_object()->add_exit(ABANDON_SHIP, "overboard");
  }
  else {
    if(hull_points/dmg)
      speed /= (hull_points/dmg);
    if(speed < 1) speed = 1;
    msg(SHIP_NAME+" slows in the water due to hull damage.\n");
    set_heart_beat(1);
  }
  return hull_points;
}

int   *query_port_coords()     { return port_coords;     }
int   *query_old_port_coords() { return old_port_coords; }
int   query_ship_hp()          { return hull_points;     }

string query_ship_name()       { return ship_name;       }
string query_captain()         { return captain;         }
mixed *query_destinations()    { return destinations;    }