/******************************************************************************
* Sailing Ship v4.01, (c) Angel February 1994.
* Original code Jan 1994, Angel
*
* Ships designed for two purposes:
* 1) For future type domain use
* 2) For sailing ships
*
* Ships have the following functions:
* 1) Travel from place to place either, (a) automated, or (b) manual
* Players are able to make the ships travel from place to place so
* long as they are able to programm the conn. Automated travel is
* done without player intervention. A ship travels from port to port
* all by itself.
*
* 2) PK'ing through attacking other ships is possible through the
* tactical display (in what ever form it may be in).
*
* 3) Messages are diplayed in all rooms, and attacking messages are
* displayed in all rooms of the enemy ship.
*
* 4) Scans are able to be performed to determine where places/ships are
*
*
*/
#include <mudlib.h>
#include "/room/ships/ships.cfg"
int x1, y1, z1, x2, y2, z2; /* handy coordinates */
int distance; /* how far the trip is */
int speed; /* max speed the ship goes */
int waiting; /* time the ship is waiting somewhere */
int timer; /* how far we've currently travelled */
int counter; /* counter for automated travel */
int *destination_coordinates; /* where we currently are */
int *old_destination_coordinates; /* where we came from */
int hp; /* dmg the ship can take */
status automated; /* is the ship automated? */
string ship_name; /* this ships designation */
string destination_file; /* file we're travelling to right now! */
string destination; /* name of the place we're going to */
string destination_long; /* long of the place we're going */
mixed *destinations; /* ALL the places we're going to */
string msgout; /* ships' leaving message */
string msgin; /* ships' arriving message */
inherit ROOM;
void reset(status arg) {
if(arg) return;
#ifndef STAR_SHIP
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_night_desc(
"A lantern hangs by the wheel, lighting the upper decks.\n");
set_night_items(({
"lantern", "A simple oil lantern made from brass",
}));
#else
set_short("the miranda");
set_long(
"You stand on the bridge of the Miranda, the first of its class, \n"+
"named after the character of the same name in Shakespeare's play\n"+
"the tempest. The Miranda was commissioned in the late 23rd century.\n");
set_weather(2, 1, 0);
#endif /* SCI_FI */
}
/*************************************************************************/
/* Set Funs */
string set_ship_name(string str) { return ship_name = str; }
string set_msgin(string str) { return msgin = str; }
string set_msgout(string str) { return msgout = str; }
string *set_destinations(string *arr) { return destinations = arr; }
int set_ship_speed(int i) { return speed = i; }
/*************************************************************************/
/* Cfg prototypes for ships */
void msg(string msg, string ship);
mixed *get_ships_data();
int *query_coordinates();
int *relative_bearing(int *coordinates1, int *coordinates2);
int calc_direction(int *coordinates1, int *coordinates2);
int calc_distance(int *coordinates1, int *coordinates2);
int calc_elevation(int *coordinates1, int *coordinates2);
int square_root(float i);
status ship_sail(string str);
status check_destination(string place);
/*************************************************************************/
/* Actions */
void init() {
if(waiting)
add_action("ship_disembark", "disembark");
if(!automated) {
add_action("ship_sail", "sail");
add_action("ship_programme_coordinates", "input");
add_action("ship_speed", "speed");
}
if(!destinations) destinations = PORTS_OF_CALL;
if(!ship_name) ship_name = "Miranda";
if(!hp) hp = HP;
if(!speed) speed = IMPULSE_POWER;
if(!old_destination_coordinates) old_destination_coordinates = ({ 0,0,0, });
add_action("ship_scan", "scan");
::init();
}
status ship_speed(string str) {
int i, j;
if(sscanf(str, "warp %d", i) == 1) {
if(i >= MAX_WARP) {
write("The computer chirps: Exceeding maximum warp capability.\n"+
" Enter warp speed again.\n");
return 1;
}
write("You enter warp "+i+" into the conn.\n");
say(NAME+" engages the warp engines.\n");
set_ship_speed(i*WARP_SPEED);
set_heart_beat(1);
return 1;
}
else if(sscanf(str, "impulse %d/%d", i, j) == 2) {
write("You slow the engines down to "+i+"/"+j+" impulse power.\n");
say(NAME+" engages the impulse engines.\n");
set_ship_speed((IMPULSE_POWER * i)/j);
set_heart_beat(1);
return 1;
}
else {
write("The computer chirps: Incorrect input.\n"+
"Usage: speed warp <number> | impulse <fraction>\n");
return 1;
}
return 0;
}
status ship_disembark() {
write("You disembark from the "+SHIP_NAME+".\n");
this_player()->move_player("off the "+SHIP_NAME+"#"+destination_file);
return 1;
}
status ship_programme_coordinates(string str) {
int x, y, z;
int i;
if(!str) {
write("The computer chirps: Invalid input.\n");
return 1;
}
if(sscanf(str, "%dx %dy %dz", x, y, z) != 3) {
notify_fail("The computer chirps: Incorrect input. "+
"Programme 'x y z' coordinates.\n");
return 0;
}
write("The computer chirps: Coordinates ["+x+", "+y+", "+z+"] entered.\n");
say(NAME+" programmes some coordinates into the conn.\n",this_player());
destination_coordinates = ({ x, y, z, });
for(i=0; i<sizeof(destinations); i++) {
if(destination_coordinates == destinations[i][2]) {
ship_sail(destinations[0][i]);
return 1;
break;
}
}
if(destination_file) { /* put the room back the way we found it */
destination_file -> remove_exit(ship_name);
destination_file -> remove_item(ship_name);
destination_file -> set_long(destination_long);
tell_room(destination_file, SHIP_NAME+" "+msgout);
}
destination_file = DEFAULT_DESTINATION;
destination = DEFAULT_DESTINATION_NAME;
distance=calc_distance(destination_coordinates,old_destination_coordinates);
write("Distance:"+ distance+"\n");
write("Destination: "+destination+"\n");
write("File: "+destination_file+"\n");
waiting = 0;
timer = 0;
set_heart_beat(1);
return 1;
}
status ship_sail(string str) {
int *arr;
if(!automated) {
if(!check_destination(str)) {
write("There is no such place.\n");
return 1;
}
}
set_heart_beat(1);
if(destination_file) { /* put the room back the way we found it */
write("destination_file: "+destination_file+"\n");
destination_file -> remove_exit(ship_name);
destination_file -> remove_item(ship_name);
destination_file -> set_long(destination_long);
tell_room(destination_file, SHIP_NAME+" "+msgout);
}
if(automated) {
destination = destinations[counter][0];
destination_file = destinations[counter][1];
destination_coordinates = destinations[counter][2];
}
distance = calc_distance(destination_coordinates,old_destination_coordinates);
waiting = 0;
timer = 0;
arr = destination_coordinates;
tell_room(this_object(), "Computer chirps: Parabolic course projected, "+
"coordinates ["+arr[X]+"x, "+arr[Y]+"y, "+arr[Z]+"z]\n");
return 1;
}
status ship_scan() {
string *ship_data, ship_file;
int i, *my_xyz, *your_xyz, *data;
status flag;
ship_data = get_ships_data();
write("You scan the sector.\n");
say(NAME+" scans the sector.\n",this_player());
if(!ship_data) {
notify_fail("There are no ships in the sector.\n");
return 0;
}
for(i=0; i<sizeof(ship_data); i++) {
ship_file = SHIP_DIR+ship_data[i]+"/"+SHIP_FILE;
your_xyz = (int *)ship_file->query_coordinates();
my_xyz = query_coordinates();
data = relative_bearing(my_xyz, your_xyz);
write(ship_data[0]+" bearing "+data[0]+", mark "+data[1]+"\n");
flag = 1;
}
if(!sizeof(ship_data) || !flag) {
notify_fail("There are no ships in the sector.\n");
return 0;
}
return 1;
}
/*****************************************************************************/
/* Functions & guts of the ship */
void heart_beat() {
mixed *arr;
int i;
timer += speed;
tell_room(this_object(), "Testing heart beat: "+timer+"\n");
if(automated) {
if(waiting && (timer > WAIT_TIME)) {
ship_sail(destinations[counter][0]);
timer = 0;
waiting = 0;
return;
}
}
if(timer >= distance) {
destination_long = (string)destination_file->query_long();
destination_file -> add_exit(file_name(this_object()), ship_name);
destination_file -> set_long(destination_long+
SHIP_NAME+" has docked "+
"at "+destination_file->query_short()+".\n");
destination_file -> add_item(ship_name,
SHIP_NAME+" is docked to "+destination_file->query_short()+
" and looks as though it may leave at any moment.\n");
tell_room(destination_file, SHIP_NAME+" "+msgin+"...\n");
tell_room(this_object(), "Computer chirps: Arrived at destination\n");
if(automated) {
old_destination_coordinates = destinations[counter][2];
if(counter >= sizeof(destinations)-1)
counter = 0; /* next destination */
else
counter ++;
waiting = 1; /* wait for a little while before setting off */
timer = 0;
}
else { /* not automated */
tell_room(this_object(), "Computer chirps: Awaiting conn input.\n");
set_heart_beat(0);
}
return;
}
}
int *relative_bearing(int *coordinates1, int *coordinates2) {
int direction, elevation;
direction = calc_direction(coordinates1, coordinates2);
elevation = calc_elevation(coordinates1, coordinates2);
return ({ direction, elevation, });
}
int calc_distance(int *coordinates1, int *coordinates2) {
x1 = coordinates1[X]; y1 = coordinates1[Y]; z1 = coordinates1[Z];
x2 = coordinates2[X]; y2 = coordinates2[Y]; z2 = coordinates2[Z];
return square_root(
((x2-x1) * (x2-x1)) +
((y2-y1) * (y2-y1)) +
((z2-z1) * (z2-z1)));
}
/* Finding absolute direction relative to this ship, in compass bearings */
int calc_direction(int *coordinates1, int *coordinates2) {
float result;
x1 = coordinates1[X];
y1 = coordinates1[Y];
x2 = coordinates2[X];
y2 = coordinates2[Y]; /* only need x & y for relative compas bearings */
if(x2>x1 && y2>y1)
result = atan(to_float((x2-x1)/(y2-y1)));
else if(x2>x1 && y2<y1)
result = atan(to_float((y2-y1)/(x2-x1)) + 90/R_TO_D);
else if(x2<x1 && y2<y1)
result = atan(to_float((x1-x2)/(y1-y2)) + 180/R_TO_D);
else
result = atan(to_float((y2-y1)/(x1-x2)) + 270/R_TO_D);
result = result * R_TO_D;
return to_int(result);
}
int calc_elevation(int *coordinates1, int *coordinates2) {
float result;
z1 = coordinates1[Z];
y1 = coordinates1[Y];
z2 = coordinates2[Z];
y2 = coordinates2[Y];
if(z2>z1 && y2>y1)
result = atan(to_float((y2-y1)/(z2-z1)));
else if(z1>z2 && y2>y1)
result = atan(to_float((z1-z2)/(y2-y1)) + 90/R_TO_D);
else if(z1>z2 && y1>y2)
result = atan(to_float((y1-y2)/(z1-z2)) + 180/R_TO_D);
else
result = atan(to_float((z2-z1)/(y1-y2)) + 270/R_TO_D);
result = result * R_TO_D;
return to_int(result);
}
int square_root(int i) { return to_int(sqrt(to_float(i))); }
mixed *get_ships_data() {
int i;
int *dest_xyz, *my_xyz;
string *ships;
string ship_name, ship_file;
int ship_direction; /* as compass degrees */
int ship_dist;
mixed *result;
ships = get_dir(SHIP_DIR); /* get files in that dir */
if(!sizeof(ships)) return 0;
result = ({});
for(i=0; i<sizeof(ships); i++) {
ship_file = SHIP_DIR+ships[i]+"/"+SHIP_FILE;
if((string)ship_file->query_ship_name() !=
((string)this_object()->query_ship_name())) {
dest_xyz = (int *)call_other(ship_file, "query_coordinates");
my_xyz = query_coordinates();
if(dest_xyz && my_xyz) {
ship_direction = calc_direction(my_xyz, dest_xyz);
ship_dist = calc_distance(my_xyz, dest_xyz);
ship_name = capitalize((string)ship_file->query_ship_name());
result += ({ ({ ship_name, ship_dist, ship_direction, }), });
}
}
}
return result;
}
mixed *query_coordinates() {
int dx, dy, dz, x, y, z;
if(!destination_coordinates)
return old_destination_coordinates;
x1 = old_destination_coordinates[X]; x2 = destination_coordinates[X];
y1 = old_destination_coordinates[Y]; y2 = destination_coordinates[Y];
z1 = old_destination_coordinates[Z]; z2 = destination_coordinates[Z];
dx = x2 - x1;
dy = y2 - y1;
dz = z2 - z1;
x = (dx * timer)/distance;
y = (dy * timer)/distance;
z = (dz * timer)/distance;
return ({ (x1 + x), (y1 + y), (z1 + z), });
}
status check_destination(string str) {
int i;
status flag;
for(i=0; i<sizeof(destinations); i++) {
if(str == destinations[i][0]) {
flag = 1;
destination_coordinates = destinations[i][2];
destination_file = destinations[i][1];
destination = destinations[i][0];
break;
}
}
return flag;
}
void msg(string msg, string ship_to_tell) {
int i;
string *files;
if(!ship_to_tell)
ship_to_tell = SHIP_DIR+"/"+SHIP_NAME;
else
ship_to_tell = SHIP_DIR+"/"+ship_to_tell;
files = get_dir(ship_to_tell+"/");
for(i=0; i<sizeof(files); i++) {
ship_to_tell = SHIP_DIR+files[i];
tell_room(ship_to_tell, msg);
}
}
mixed *query_destinations() { return destinations; }