/****************************************************************************** * 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; }