/
rogue25b1/
rogue25b1/space/planets/
rogue25b1/space/prototypes/
rogue25b1/space/ships/
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>

#include "merc.h"
#include "olc.h"
#include "clans.h"
#include "space.h"
#include "interp.h"

#define flabs(i)	((i) < 0 ? -(i) : (i))

SHIP_DATA *first_ship;
SHIP_DATA *last_ship;

MISSILE_DATA *first_missile;
MISSILE_DATA *last_missile;

SPACE_DATA *first_starsystem;
SPACE_DATA *last_starsystem;

PLANET_DATA *first_planet;
PLANET_DATA *last_planet;

// local functions
void	fread_ship		args( (SHIP_DATA *ship, FILE *fp) );
void	fread_planet		args( (PLANET_DATA *planet, FILE *fp) );
void	write_ship_list		args( (void) );
void	fread_starsystem	args( (SPACE_DATA *starsystem, FILE *fp) );
void	write_starsystem_list	args( (void) );

void	save_ship		args( (SHIP_DATA *ship) );
void	reset_ship		args( (SHIP_DATA *ship) );
void	land_ship		args( (SHIP_DATA *ship, char *arg) );
void	launch_ship		args( (SHIP_DATA *ship) );
void	damage_ship		args( (CHAR_DATA *ch, SHIP_DATA *ship, int min, int max) );
void	destroy_ship		args( (SHIP_DATA *ship, CHAR_DATA *ch) );
void	new_missile		args( (SHIP_DATA *ship, SHIP_DATA *target, CHAR_DATA *ch) );
void	create_ship_rooms	args( (SHIP_DATA *ship) );
void	ship_to_starsystem	args( (SHIP_DATA *ship, SPACE_DATA *starsystem) );
void	ship_from_starsystem	args( (SHIP_DATA *ship, SPACE_DATA *starsystem) );
void	echo_to_room		args( (ROOM_INDEX_DATA *room, char *argument) );
/*
void	sound_to_ship		args( (SHIP_DATA *ship, char *argument) );
*/

bool	load_ship_file		args( (char *shipfile) );
bool	load_starsystem		args( (char *starsystemfile) );
bool	load_planet_file	args( (char *planetfile) );
bool	autofly			args( (SHIP_DATA *ship) );
bool	is_facing		args( (SHIP_DATA *ship, SHIP_DATA *target) );

int	extract_missile		args( (MISSILE_DATA *missile) );

SPACE_DATA *starsystem_from_name(char *name);
SHIP_DATA *get_ship_here(char *name, SPACE_DATA *starsystem);

void move_ships(void) {
    CHAR_DATA *ch;
    PLANET_DATA *planet;
    bool ch_found = FALSE;
    float dx, dy, dz, change;
    char buf[MAX_STRING_LENGTH];
    MISSILE_DATA *missile, *m_next;
    SHIP_DATA *ship, *nextship, *target;

    for (missile = first_missile; missile; missile = m_next) {
	m_next	= missile->next;
	ship	= missile->fired_from;
	target	= missile->target;

	if (target && target->starsystem &&
	target->starsystem == missile->starsystem) {
	    if (missile->mx < target->vx)
		missile->mx += UMIN(missile->speed/5, target->vx - missile->mx);
	    else if (missile->mx > target->vx)
		missile->mx -= UMIN(missile->speed/5, missile->mx - target->vx);

	    if (missile->my < target->vy)
		missile->my += UMIN(missile->speed/5, target->vy - missile->my);
	    else if (missile->my > target->vy)
		missile->my -= UMIN(missile->speed/5, missile->my - target->vy);

	    if (missile->mz < target->vz)
		missile->mz += UMIN(missile->speed/5, target->vz - missile->mz);
	    else if (missile->mz > target->vz)
		missile->mz -= UMIN(missile->speed/5, missile->mz - target->vz);

	    if (flabs(missile->mx) - flabs(target->vx) <= 20 &&
	    flabs(missile->mx) - flabs(target->vx) >= -20
	    && flabs(missile->my) - flabs(target->vy) <= 20 &&
	    flabs(missile->my) - flabs(target->vy) >= -20
	    && flabs(missile->mz) - flabs(target->vz) <= 20 &&
	    flabs(missile->mz) - flabs(target->vz) >= -20) {
		if (target->chaff_released <= 0) {
		    echo_to_ship(TO_GUNSEAT, ship, "`YYour missile hits its target dead on!`n");
		    echo_to_ship(TO_COCKPIT, target, "`RThe ship is hit by a missile.`n");
		    echo_to_ship(TO_SHIP, target, "`RA loud explosion shake the ship violently!`n");
		    echo_to_system(target, ship, "`yYou see a small explosion as %s is hit by a missile.`n", target->name);

		    for (ch = char_list; ch != NULL; ch = ch->next) {
			if (!IS_NPC(ch) && strstr(missile->fired_by,ch->name))
			    damage_ship(ch, target, 30, 50);
			else
			    damage_ship(NULL, target, 30, 50);
			extract_missile(missile);
		    }
		} else {
		    echo_to_ship(TO_GUNSEAT, ship, "`YYour missile explodes harmlessly in a cloud of chaff!`n");
		    echo_to_ship(TO_COCKPIT, target, "`YA missile explodes in your chaff.`n");
		    extract_missile(missile);
		}
		continue;
	    } else {
		missile->age++;
		if (missile->age >= 50) {
		    extract_missile(missile);
		    continue;
		}
	    }
	} else {
	    extract_missile(missile);
	    continue;
	}
    }

    for (ship = first_ship; ship; ship = nextship) {
	nextship = ship->next;

	if (!ship->starsystem)
	    continue;

	if (ship->currspeed > 0) {
	    change = sqrt(ship->hx * ship->hx + ship->hy * ship->hy + ship->hz * ship->hz);

	    if (change > 0) {
		dx = ship->hx / change;
		dy = ship->hy / change;
		dz = ship->hz / change;
		ship->vx += (dx * ship->currspeed / 5);
		ship->vy += (dy * ship->currspeed / 5);
		ship->vz += (dz * ship->currspeed / 5);
	    }
	}

	if (autofly(ship))
	    continue;

	if (ship->starsystem->star1 && strcmp(ship->starsystem->star1,"") &&
	flabs(ship->vx - ship->starsystem->s1x) < 10 &&
	flabs(ship->vy - ship->starsystem->s1y) < 10 &&
	flabs(ship->vz - ship->starsystem->s1z) < 10) {
	    echo_to_ship(TO_COCKPIT, ship, "`R`fYou fly directly into the sun.`n");
	    echo_to_system(ship, NULL, "`y%s flies directly into %s!`n", ship->name, ship->starsystem->star1);
	    destroy_ship(ship, NULL);
	    continue;
	}

	if (ship->starsystem->star2 && strcmp(ship->starsystem->star2,"") &&
	flabs(ship->vx - ship->starsystem->s2x) < 10 &&
	flabs(ship->vy - ship->starsystem->s2y) < 10 &&
	flabs(ship->vz - ship->starsystem->s2z) < 10) {
	    echo_to_ship(TO_COCKPIT, ship, "`r`fYou fly directly into the sun.`n");
	    echo_to_system(ship, NULL, "`y%s flies directly into %s!`n", ship->name, ship->starsystem->star2);
	    destroy_ship(ship, NULL);
	    continue;
	}

	if (ship->currspeed > 0) {
	    for (planet = ship->starsystem->first_planet; planet; planet = planet->next_in_system) {
		if (flabs(ship->vx - planet->x) < 10 &&
		flabs(ship->vy - planet->y) < 10 &&
		flabs(ship->vz - planet->z) < 10) {
		    echo_to_ship(TO_COCKPIT, ship, "`YYou begin orbiting %s.`n", planet->name);
		    echo_to_system(ship, NULL, "`y%s begins orbiting %s.`n", ship->name, planet->name);
		    ship->currspeed = 0;
		    continue;
		}
	    }
	}
    }

    for (ship = first_ship; ship; ship = nextship) {
	nextship = ship->next;
	if (ship->collision) {
	    echo_to_ship(TO_COCKPIT, ship, "`W`fYou have collided with another ship!`n");
	    echo_to_ship(TO_SHIP, ship, "`RA loud explosion shakes the ship violently!`n");
	    damage_ship(NULL, ship, ship->collision, ship->collision);
	    ship->collision = 0;
	}
    }
}

void recharge_ships(void) {
    TURRET_DATA *turret;
    SHIP_DATA *ship, *nextship;
    char buf[MAX_STRING_LENGTH];

    for (ship = first_ship; ship; ship = nextship) {
	nextship = ship->next;

	for (turret = ship->first_turret; turret; turret = turret->next) {
	    if (turret->laserstate > 0) {
		ship->energy -= turret->laserstate;
		turret->laserstate = 0;
	    }

	    if (ship->laserstate > 0) {
		ship->energy -= ship->laserstate;
		ship->laserstate = 0;
	    }

	    if (ship->missilestate == MISSILE_RELOAD_2) {
		ship->missilestate = MISSILE_READY;
		if (ship->missiles > 0)
		    echo_to_ship(TO_GUNSEAT, ship, "`YMissile launcher reloaded.`n");
	    }

	    if (ship->missilestate == MISSILE_RELOAD)
		ship->missilestate = MISSILE_RELOAD_2;

	    if (ship->missilestate == MISSILE_FIRED)
		ship->missilestate = MISSILE_RELOAD;

	    if (autofly(ship)) {
		if (ship->starsystem) {
		    if (ship->target && ship->laserstate != LASER_DAMAGED) {
			int shots;
			float chance = 100;
			SHIP_DATA *target = ship->target;

			for (shots = 0; shots <= ship->lasers; shots++) {
			    if (!ship->target)
				break;

			    if (ship->shipstate != SHIP_HYPERSPACE && ship->energy > 25
			    && ship->target->starsystem == ship->starsystem
			    && flabs(target->vx - ship->vx) <= 1000
			    && flabs(target->vy - ship->vy) <= 1000
			    && flabs(target->vz - ship->vz) <= 1000
			    && ship->laserstate < ship->lasers) {
				if (ship->shipclass == SPACE_STATION || is_facing(ship, target)) {
				    chance += target->model*10;
				    chance -= target->manuever/10;
				    chance -= target->currspeed/20;
				    chance -= (flabs(target->vx - ship->vx) / 70);
				    chance -= (flabs(target->vy - ship->vy) / 70);
				    chance -= (flabs(target->vz - ship->vz) / 70);
				    chance = URANGE(10, chance, 90);
				    if (number_percent() > chance) {
					echo_to_ship(TO_COCKPIT, target, "`y%s fires at you but misses.`n", ship->name);
					echo_to_system(target, NULL, "`yLaserfire from %s barely misses %s.`n", ship->name, target->name);
				    } else {
					echo_to_system(ship, NULL, "`yLaserfire from %s hits %s.`n", ship->name, target->name);
					echo_to_ship(TO_COCKPIT, target, "`rYou are hit by lasers from %s!`n", ship->name);
					echo_to_ship(TO_SHIP, target, "`RA small explosion vibrates through the ship.`n");
					if (autofly(target))
					    target->target = ship;
					damage_ship(NULL, target, 5, 10);
				    }
				    ship->laserstate++;
				}
			    }
			}
		    }
		}
	    }
	}
    }
}

void space_update(void) {
    SHIP_DATA *target;
    SHIP_DATA *ship, *nextship;
    char buf[MAX_STRING_LENGTH];
    SInt32 recharge, too_close, target_too_close;

    for (ship = first_ship; ship; ship = nextship) {
	nextship = ship->next;

	if (ship->starsystem) {
	    if (ship->energy > 0 && ship->shipstate == SHIP_DISABLED && ship->shipclass != SPACE_STATION)
		ship->energy -= 100;
	    else
		ship->energy += 5 + ship->model * 2;
	}

	if (ship->chaff_released > 0)
	    ship->chaff_released = FALSE;

	if (ship->shipstate == SHIP_HYPERSPACE) {
	    ship->hyperdistance -= ship->hyperspeed * 2;
	    if (ship->hyperdistance <= 0) {
		ship_to_starsystem(ship, ship->currjump);
		if (ship->starsystem == NULL)
		    echo_to_ship(TO_COCKPIT, ship, "`RShip lost in hyperspace. Make new calculations.`n");
		else {
		    echo_to_ship(TO_PILOTSEAT, ship, "`YHyperjump complete.`n");
		    echo_to_ship(TO_SHIP, ship, "`YThe ship lurches slightly as it comes out of hyperspace.`n");
		    echo_to_system(ship, NULL, "`Y%s enters the starsystem at %.0f %.0f %.0f`n", ship->name, ship->vx, ship->vy, ship->vz);
		    ship->shipstate = SHIP_READY;
		    free_string(ship->home);
		    ship->home = str_dup(ship->starsystem->name);
		}
	    } else
		echo_to_ship(TO_PILOTSEAT, ship, "`YRemaining jump distance: `W%d`n", ship->hyperdistance);
	}

	if (ship->shipstate == SHIP_BUSY_3) {
	    echo_to_ship(TO_PILOTSEAT, ship, "`YManuever complete.`n");
	    ship->shipstate = SHIP_READY;
	}
	if (ship->shipstate == SHIP_BUSY_2)
	    ship->shipstate = SHIP_BUSY_3;
	if (ship->shipstate == SHIP_BUSY)
	    ship->shipstate = SHIP_BUSY_2;

	if (ship->shipstate == SHIP_LAND_2)
	    land_ship(ship, ship->dest);
	if (ship->shipstate == SHIP_LAND)
	    ship->shipstate = SHIP_LAND_2;

	if (ship->shipstate == SHIP_LAUNCH_2)
	    launch_ship(ship);
	if (ship->shipstate == SHIP_LAUNCH)
	    ship->shipstate = SHIP_LAUNCH_2;

	ship->shield = UMAX(0, ship->shield - 1 - ship->model / 5);

	if (ship->autorecharge && ship->maxshield > ship->shield && ship->energy > 100) {
	    recharge = UMIN(ship->maxshield - ship->shield, 10 + ship->model * 2);
	    recharge = UMIN(recharge, ship->energy - 100);
	    recharge = UMAX(1, recharge);
	    ship->shield += recharge;
	    ship->energy -= recharge;
 	}

	if (ship->shield > 0) {
	    if (ship->energy > 200) {
		ship->shield = 0;
		echo_to_ship(TO_COCKPIT, ship, "`RThe ships shields fizzle and die.`n");
		ship->autorecharge = FALSE;
	    }
	}

	if (ship->starsystem && ship->currspeed > 0)
	    echo_to_ship(TO_PILOTSEAT, ship, "`BSpeed: `C%d  `BCoords: `C%.0f %.0f %.0f`n", ship->currspeed, ship->vx, ship->vy, ship->vz);

	if (ship->starsystem) {
	    too_close = ship->currspeed + 50;
	    for (target = ship->starsystem->first_ship; target; target = target->next_in_starsystem) {
		target_too_close = too_close + target->currspeed;
		if (target != ship &&
		flabs(ship->vx - target->vx) < target_too_close &&
		flabs(ship->vy - target->vy) < target_too_close &&
		flabs(ship->vz - target->vz) < target_too_close)
		    echo_to_ship(TO_PILOTSEAT, ship, "`RProximity alert: %s  %.0f %.0f %.0f`n", target->name, target->vx, target->vy, target->vz);
	    }

	    too_close = ship->currspeed + 100;
	    if (ship->starsystem->star1 && strcmp(ship->starsystem->star1, "") &&
	    flabs(ship->vx - ship->starsystem->s1x) < too_close &&
	    flabs(ship->vy - ship->starsystem->s1y) < too_close &&
	    flabs(ship->vz - ship->starsystem->s1z) < too_close)
		echo_to_ship(TO_PILOTSEAT, ship, "`RProximity alert: %s  %.0f %.0f %.0f`n", ship->starsystem->star1, ship->starsystem->s1x, ship->starsystem->s1y, ship->starsystem->s1z);

	    if (ship->target) {
		echo_to_ship(TO_PILOTSEAT, ship, "`BTarget: `C%s  %.0f %.0f %.0f`n", ship->target->name, ship->target->vx, ship->target->vy, ship->target->vz);
		if (ship->starsystem != ship->target->starsystem)
		    ship->target = NULL;
	    }

	    if (ship->energy < 100 && ship->starsystem)
		echo_to_ship(TO_COCKPIT, ship, "`RWarning: Ship fuel low.`n");

	    ship->energy = URANGE(0, ship->energy, ship->maxenergy);
	}
    }

    for (ship = first_ship; ship; ship = ship->next) {
	if (ship->autotrack && ship->target && ship->shipclass < SPACE_STATION) {
	    target = ship->target;
	    too_close = ship->currspeed + 10;
	    target_too_close = too_close + target->currspeed;

	    if (target != ship && ship->shipstate == SHIP_READY &&
	    flabs(ship->vx - target->vx) < target_too_close &&
	    flabs(ship->vy - target->vy) < target_too_close &&
	    flabs(ship->vz - target->vz) < target_too_close) {
		ship->hx = 0 - (ship->target->vx - ship->vx);
		ship->vy = 0 - (ship->target->vy - ship->vy);
		ship->vz = 0 - (ship->target->vz - ship->vz);
		ship->energy -= ship->currspeed / 10;
		echo_to_ship(TO_PILOTSEAT, ship, "`RAutotrack: Evading to avoid collision!`n");
		if (ship->manuever > 100)
		    ship->shipstate = SHIP_BUSY_3;
		else if (ship->manuever > 50)
		    ship->shipstate = SHIP_BUSY_2;
		else
		    ship->shipstate = SHIP_BUSY;
	    } else if (!is_facing(ship, ship->target)) {
		ship->hx = ship->target->vx - ship->vx;
		ship->hy = ship->target->vy - ship->vy;
		ship->hz = ship->target->vz - ship->vz;
		echo_to_ship(TO_PILOTSEAT, ship, "`BAutotracking target ... setting new course.`n");
		if (ship->manuever > 100)
		    ship->shipstate = SHIP_BUSY_3;
		else if (ship->manuever > 50)
		    ship->shipstate = SHIP_BUSY_2;
		else
		    ship->shipstate = SHIP_BUSY;
	    }
	}

	if (autofly(ship)) {
	    if (ship->starsystem) {
		if (ship->target) {
		    float chance = 100;

		    target = ship->target;
		    ship->autotrack = TRUE;
		    if (ship->shipclass != SPACE_STATION)
			ship->currspeed = ship->realspeed;
		    if (ship->energy > 200)
			ship->autorecharge = TRUE;

		    if (ship->shipstate != SHIP_HYPERSPACE && ship->energy > 200
		    && ship->hyperspeed > 0 && ship->target->starsystem == ship->starsystem
		    && (flabs(target->vx - ship->vx) > 5000
		    || flabs(target->vy - ship->vy) > 5000
		    || flabs(target->vz - ship->vz) > 5000)
		    && number_bits(2) == 0) {
			ship->currjump = ship->starsystem;
			ship->hyperdistance = 1;

			echo_to_system(ship, NULL, "`Y%s disappears from your scanner.`n", ship->name);
			ship_from_starsystem(ship, ship->starsystem);
			ship->shipstate = SHIP_HYPERSPACE;
			ship->energy -= 100;
			ship->jx = target->vx;
			ship->jy = target->vy;
			ship->jz = target->vz;
		    }

		    if (ship->shipstate != SHIP_HYPERSPACE && ship->energy > 25
		    && ship->missilestate == MISSILE_READY
		    && ship->target->starsystem == ship->starsystem
		    && flabs(target->vx - ship->vx) <= 1200
		    && flabs(target->vy - ship->vy) <= 1200
		    && flabs(target->vz - ship->vz) <= 1200
		    && ship->missiles > 0) {
			if (ship->shipclass == SPACE_STATION || is_facing(ship, target)) {
			    chance -= target->manuever / 5;
			    chance -= target->currspeed / 20;
			    chance += target->model * target->model * 2;
			    chance -= (flabs(target->vx - ship->vx) / 100);
			    chance -= (flabs(target->vy - ship->vy) / 100);
			    chance -= (flabs(target->vz - ship->vz) / 100);
			    chance += 30;
			    chance = URANGE(10 , chance, 90);

			    if (number_percent() < chance) {
				new_missile(ship, target, NULL);
				ship->missiles--;
				echo_to_ship(TO_COCKPIT, target, "`rIncoming missile from %s.`n", ship->name);
				echo_to_system(target, NULL, "`y%s fires a missile towards %s.`n", ship->name, target->name);

				if (ship->shipclass == SPACE_STATION)
				    ship->missilestate = MISSILE_RELOAD_2;
				else
				    ship->missilestate = MISSILE_RELOAD;
			    }
			}
		    }

		    if (ship->missilestate == MISSILE_DAMAGED)
			ship->missilestate = MISSILE_READY;
		    if (ship->laserstate == LASER_DAMAGED)
			ship->laserstate = LASER_READY;
		    if (ship->shipstate == SHIP_DISABLED)
			ship->shipstate = SHIP_READY;
		} else {
		    int targetok;
		    CHAR_DATA *passenger = NULL;
		    ROOM_INDEX_DATA *room = NULL;

		    ship->currspeed = 0;
			// nya nya
		}
	    } else if ((ship->shipclass == SPACE_STATION || ship->type == MOB_SHIP) && ship->home) {
		if (number_range(1, 25) == 25) {
		    ship_to_starsystem(ship, starsystem_from_name(ship->home));
		    ship->vx = number_range(-5000, 5000);
		    ship->vy = number_range(-5000, 5000);
		    ship->vz = number_range(-5000, 5000);
		    ship->hx = ship->hy = ship->hz = 1;
		    ship->autopilot = TRUE;
		}
	    }
	}
	if (ship->shipclass == SPACE_STATION && ship->target == NULL) {
	    if (ship->missiles < ship->maxmissiles)
		ship->missiles++;
	}
    }
}

void echo_to_ship(Flags type, SHIP_DATA *ship, char *argument, ...) {
    va_list args;
    char send_buf[MAX_STRING_LENGTH];

    if (!argument || !*argument)
	return;

    va_start(args, argument);
    vsprintf(send_buf, argument, args);
    va_end(args);

    if (IS_SET(type, TO_SHIP)) {
	ROOM_INDEX_DATA *room;
	for (room = ship->first_room; room; room = room->next_in_ship)
	    echo_to_room(room, send_buf);
    }

    if (IS_SET(type, TO_PILOTSEAT))
	echo_to_room(ship->pilotseat, send_buf);

    if (IS_SET(type, TO_COCKPIT)) {
	TURRET_DATA *turret;

	echo_to_room(ship->pilotseat, send_buf);
	if (ship->pilotseat != ship->gunseat)
	    echo_to_room(ship->gunseat, send_buf);
	if (ship->pilotseat != ship->viewscreen && ship->viewscreen != ship->gunseat)
	    echo_to_room(ship->viewscreen, send_buf);
	for (turret = ship->first_turret; turret; turret = turret->next)
	    if (turret->room)
		echo_to_room(turret->room, send_buf);
    }
}

void echo_to_system(SHIP_DATA *ship, SHIP_DATA *ignore, char *argument, ...) {
    va_list args;
    SHIP_DATA *target;
    char send_buf[MAX_STRING_LENGTH];

    if (!ship->starsystem || !argument || !*argument)
	return;

    va_start(args, argument);
    vsprintf(send_buf, argument, args);
    va_end(args);

    for (target = ship->starsystem->first_ship; target; target = target->next_in_starsystem) {
	if (target != ship && target != ignore)
	    echo_to_ship(TO_COCKPIT, target, send_buf);
    }
    return;
}

void echo_to_room(ROOM_INDEX_DATA *room, char *argument) {
    CHAR_DATA *to;

    if (room == NULL)
	return;

    for (to = room->people; to; to = to->next_in_room)
	to->Send("%s\n\r", argument);

    return;
}

bool is_facing(SHIP_DATA *ship, SHIP_DATA *target) {
    float dx, dy, dz, hx, hy, hz, cosofa;

    hx = ship->hx;
    hy = ship->hy;
    hz = ship->hz;

    dx = target->vx - ship->vx;
    dy = target->vy - ship->vy;
    dz = target->vz - ship->vz;

    cosofa = (hx*dx + hy*dy + hz*dz) /
	(sqrt(hx*hx + hy*hy + hz*hz) + sqrt(dx*dx + dy*dy + dz*dz));

    if (cosofa > 0.75)
	return TRUE;

    return FALSE;
}

bool autofly(SHIP_DATA *ship) {
    if (!ship)
	return FALSE;

    if (ship->type == MOB_SHIP)
	return TRUE;

    return ship->autopilot;
}

bool check_pilot(CHAR_DATA *ch, SHIP_DATA *ship) {
    if (NO_STAFF_HASSLE(ch))
	return TRUE;

    if (!str_cmp(ch->name, ship->owner))
	return TRUE;

    return FALSE;
}

bool extract_ship(SHIP_DATA *ship) {
    ROOM_INDEX_DATA *room;

    if ((room = ship->in_room) != NULL) {
	UNLINK(ship, room->first_ship, room->last_ship, next_in_room, prev_in_room);
	ship->in_room = NULL;
    }
    return TRUE;
}

bool ship_to_room(SHIP_DATA *ship, UInt32 vnum) {
    ROOM_INDEX_DATA *shipto;

    if ((shipto = get_room_index(vnum)) == NULL)
	return FALSE;

    LINK(ship, shipto->first_ship, shipto->last_ship, next_in_room, prev_in_room);
    ship->in_room = shipto;
    return TRUE;
}

SPACE_DATA *starsystem_from_name(char *name) {
    SPACE_DATA *starsystem;

    for (starsystem = first_starsystem; starsystem; starsystem = starsystem->next)
	if (!str_cmp(name, starsystem->name))
	    return starsystem;

    for (starsystem = first_starsystem; starsystem; starsystem = starsystem->next)
	if (!str_prefix(name, starsystem->name))
	    return starsystem;

    return NULL;
}

SHIP_DATA *ship_from_room(ROOM_INDEX_DATA *room) {
    SHIP_DATA *ship;
    ROOM_INDEX_DATA *sRoom;

    if (room == NULL)
	return NULL;

    for (ship = first_ship; ship; ship = ship->next)
	for (sRoom = ship->first_room; sRoom; sRoom = sRoom->next_in_ship)
	    if (room == sRoom)
		return ship;

    return NULL;
}

SHIP_DATA *ship_from_cockpit(ROOM_INDEX_DATA *room) {
    SHIP_DATA *ship;
    TURRET_DATA *turret;

    if (room == NULL)
	return NULL;

    for (ship = first_ship; ship; ship = ship->next) {
	if (room == ship->pilotseat)
	    return ship;
	if (room == ship->gunseat)
	    return ship;
	if (room == ship->viewscreen)
	    return ship;
	for (turret = ship->first_turret; turret; turret = turret->next)
	    if (room == turret->room)
		return ship;
    }
    return NULL;
}

SHIP_DATA *ship_from_pilotseat(ROOM_INDEX_DATA *room) {
    SHIP_DATA *ship;

    if (room == NULL)
	return NULL;

    for (ship = first_ship; ship; ship = ship->next)
	if (room == ship->pilotseat)
	    return ship;

    return NULL;
}

SPACE_DATA *starsystem_from_room(ROOM_INDEX_DATA *room) {
    SHIP_DATA *ship;
    ROOM_INDEX_DATA *sRoom;

    if (room == NULL)
	return NULL;

    if (room->area != NULL && room->area->planet != NULL)
	return room->area->planet->starsystem;

    for (ship = first_ship; ship; ship = ship->next) {
	for (sRoom = ship->first_room; sRoom; sRoom = sRoom->next_in_ship)
	    if (room == sRoom)
		return ship->starsystem;
    }
    return NULL;
}

void land_ship(SHIP_DATA *ship, char *argument) {
    SHIP_DATA *target;
    PLANET_DATA *planet;
    RNum vnum, dest = 0;
    ROOM_INDEX_DATA *room;
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH], arg1[MAX_INPUT_LENGTH];

    strcpy(arg, argument);
    argument = one_argument(argument, arg1);

    for (planet = ship->starsystem->first_planet; planet; planet = planet->next_in_system) {
	if (!str_prefix(arg1, planet->name)) {
	    if (!planet->area)
		continue;
	    for (vnum = planet->area->min_vnum; vnum <= planet->area->max_vnum; vnum++) {
		if ((room = get_room_index(vnum)) != NULL && ROOM_FLAGGED(room, ROOM_CAN_LAND) && !str_prefix(argument, room->name)) {
		    dest = room->vnum;
		    break;
		}
	    }
	    break;
	}
    }

    if (!dest) {
	target = get_ship_here(arg, ship->starsystem);
	if (target != ship && target != NULL)
	    dest = 0;
	dest = 0;	// disabled landing on ships
    }

    if (!ship_to_room(ship, dest)) {
	echo_to_room(ship->pilotseat, "`YCould not complete aproach. Landing aborted.`n");
	echo_to_ship(TO_SHIP, ship, "`YThe ship pulls back up out of its landing sequence.`n");
	if (ship->shipstate != SHIP_DISABLED)
	    ship->shipstate = SHIP_READY;
	return;
    }

    echo_to_room(ship->pilotseat, "`YLanding sequence complete.`n");
    echo_to_ship(TO_SHIP, ship, "`YYou feel a slight thud as the ship sets down on the ground.`n");
    echo_to_system(ship, NULL, "`Y%s enters the atmosphere of %s.`n", ship->name, planet->name);

    ship->location = dest;
    ship->lastdoc = ship->location;
    if (ship->shipstate != SHIP_DISABLED)
	ship->shipstate = SHIP_DOCKED;
    ship_from_starsystem(ship, ship->starsystem);

    sprintf(buf, "`Y%s lands on the platform.`n", ship->name);
    echo_to_room(get_room_index(ship->location), buf);

    ship->energy = ship->energy - 25 - 5 * ship->model;
    save_ship(ship);
}

void launch_ship(SHIP_DATA *ship) {
    SHIP_DATA *source;
    ROOM_INDEX_DATA *room;
    char buf[MAX_STRING_LENGTH];

    ship_to_starsystem(ship, starsystem_from_room(ship->in_room));

    if (ship->starsystem == NULL) {
	echo_to_ship(TO_PILOTSEAT, ship, "`YLaunch path unavailable.. Launch aborted.`n");
	echo_to_ship(TO_SHIP, ship, "`YThe ship slowly sets back back down on the landing pad.`n");
	ship->shipstate = SHIP_DOCKED;
	return;
    }

    source = ship_from_room(ship->in_room);
    extract_ship(ship);
    ship->location = 0;

    if (ship->shipstate != SHIP_DISABLED)
	ship->shipstate = SHIP_READY;

    ship->hx = number_range(-1, 1);
    ship->hy = number_range(-1, 1);
    ship->hz = number_range(-1, 1);

    if ((room = get_room_index(ship->lastdoc)) != NULL
    && room->area && room->area->planet && room->area->planet->starsystem
    && room->area->planet->starsystem == ship->starsystem) {
	ship->vx = room->area->planet->x;
	ship->vy = room->area->planet->y;
	ship->vz = room->area->planet->z;
    } else if (source) {
	ship->vx = source->vx;
	ship->vy = source->vy;
	ship->vz = source->vz;
    }

    ship->energy -= (100 + 10 * ship->model);
    ship->vx += (ship->hx * ship->currspeed * 2);
    ship->vy += (ship->hy * ship->currspeed * 2);
    ship->vz += (ship->hz * ship->currspeed * 2);

    echo_to_room(get_room_index(ship->location), "`GLaunch complete.`n");
    echo_to_ship(TO_SHIP, ship, "`YThe ship leaves the platform far behind as it flies into space.`n");
    echo_to_system(ship, NULL, "`Y%s enters the starsystem at %.0f %.0f %.0f`n", ship->name, ship->vx, ship->vy, ship->vz);
    sprintf(buf, "`Y%s lifts off into space.`n", ship->name);
    echo_to_room(get_room_index(ship->lastdoc), buf);
}

void damage_ship(CHAR_DATA *ch, SHIP_DATA *ship, int min, int max) {
}

void destroy_ship(SHIP_DATA *ship, CHAR_DATA *ch) {
}

void new_missile(SHIP_DATA *ship, SHIP_DATA *target, CHAR_DATA *ch) {
    MISSILE_DATA *missile;
    SPACE_DATA *starsystem;

    if (ship == NULL || target == NULL)
	return;

    if ((starsystem = ship->starsystem) == NULL)
	return;

    missile = (MISSILE_DATA *)alloc_mem(sizeof(MISSILE_DATA));
    LINK(missile, first_missile, last_missile, next, prev);

    missile->age	= 0;
    missile->speed	= 200;
    missile->target	= target;
    missile->fired_from	= ship;
    missile->fired_by	= str_dup(ch ? ch->name : "");
    missile->mx		= ship->vx;
    missile->my		= ship->vy;
    missile->mz		= ship->vz;

    if (starsystem->first_missile == NULL)
	starsystem->first_missile = missile;

    if (starsystem->last_missile) {
	starsystem->last_missile->next_in_starsystem = missile;
	missile->prev_in_starsystem = starsystem->last_missile;
    }
    starsystem->last_missile = missile;
    missile->starsystem = starsystem;
}

void ship_to_starsystem(SHIP_DATA *ship, SPACE_DATA *starsystem) {
    if (ship == NULL || starsystem == NULL)
	return;

    LINK(ship, starsystem->first_ship, starsystem->last_ship, next_in_starsystem, prev_in_starsystem);
    ship->starsystem = starsystem;
}

void ship_from_starsystem(SHIP_DATA *ship, SPACE_DATA *starsystem) {
    if (ship == NULL || starsystem == NULL)
	return;

    UNLINK(ship, starsystem->first_ship, starsystem->last_ship, next_in_starsystem, prev_in_starsystem);
    ship->starsystem = NULL;
}

SHIP_DATA *get_ship_here(char *name, SPACE_DATA *starsystem) {
    SHIP_DATA *ship;

    if (starsystem == NULL)
	return NULL;

    for (ship = starsystem->first_ship; ship; ship = ship->next_in_starsystem)
	if (is_name(name, ship->name))
	    return ship;

    return NULL;
}

SHIP_DATA *ship_in_room(ROOM_INDEX_DATA *room, char *name) {
    SHIP_DATA *ship;

    if (room == NULL)
	return NULL;

    for (ship = room->first_ship; ship; ship = ship->next_in_room)
	if (!str_cmp(name, ship->name) || !str_prefix(name, ship->name) || is_name(name, ship->name))
	    if (ship->owner && ship->owner[0] != '\0')
		return ship;

    return NULL;
}

SHIP_DATA *ship_from_entrance(ROOM_INDEX_DATA *room) {
    SHIP_DATA *ship;

    if (room == NULL)
	return NULL;

    for (ship = first_ship; ship; ship = ship->next)
	if (room == ship->entrance)
	    return ship;

    return NULL;
}

int extract_missile(MISSILE_DATA *missile) {
    SPACE_DATA *starsystem;
    return 0;
}

void write_starsystem_list(void) {
    FILE *fp;
    SPACE_DATA *system;

    if (!(fp = fopen(SPACE_LIST, "w"))) {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: Couldn't open %s for writing.", SPACE_LIST);
	return;
    }

    for (system = first_starsystem; system; system = system->next)
	fprintf(fp, "%s\n", system->filename);
    fprintf(fp, "$\n");
    fclose(fp);
}

void save_starsystem(SPACE_DATA *starsystem) {
    FILE *fp;
    char buf[MAX_STRING_LENGTH];

    if (!starsystem) {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: save_starsystem: null starsystem!");
	return;
    }

    if (!starsystem->filename || !*starsystem->filename) {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: save_starsystem: %s has no filename", starsystem->name);
	return;
    }

    fclose(fpReserve);
    if ((fp = fopen(STARSYSTEM_FILE, "w")) == NULL) {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: save_starsystem: Couldn't open %s for writing.", STARSYSTEM_FILE);
	return;
    }

    fprintf(fp, "#SPACE\n");
    fprintf(fp, "Name %s~\n", starsystem->name);
    fprintf(fp, "FName %s~\n", starsystem->filename);
    fprintf(fp, "Star1 %s~\n", starsystem->star1);
    fprintf(fp, "Star2 %s~\n", starsystem->star2);
    fprintf(fp, "S1xyz %.0f %.0f %.0f\n",
	starsystem->s1x, starsystem->s1y, starsystem->s1z);
    fprintf(fp, "S2xyz %.0f %.0f %.0f\n",
	starsystem->s2x, starsystem->s2y, starsystem->s2z);
    fprintf(fp, "End\n");
    fprintf(fp, "#END\n");

    fclose(fp);
    fpReserve = fopen(NULL_FILE, "r");
    return;
}

#if defined(KEY)
#undef KEY
#endif

#define KEY(literal, field, value)		\
	if (!str_cmp(word, literal)) {		\
	    field = value;			\
	    fMatch = TRUE;			\
	    break;				\
	}

#if defined(KEYS)
#undef KEYS
#endif

#define KEYS(literal, field, value)		\
	if (!str_cmp(word, literal)) {		\
	    free_string(field);			\
	    field = value;			\
	    fMatch = TRUE;			\
	    break;				\
	}

void fread_starsystem(SPACE_DATA *starsystem, FILE *fp) {
    char *word;
    bool fMatch;
    char buf[MAX_STRING_LENGTH];

    for (;;) {
	word = feof(fp) ? (char *)"End" : fread_word(fp);
	fMatch = FALSE;

	switch(UPPER(*word)) {
	    case '*':
		fMatch = TRUE;
		fread_to_eol(fp);
		break;

	    case 'E':
		if (!str_cmp(word, "End")) {
		    if (!starsystem->name)
			starsystem->name = str_dup("");
		    if (!starsystem->star1)
			starsystem->star1 = str_dup("");
		    if (!starsystem->star2)
			starsystem->star2 = str_dup("");
		    return;
		}
		break;

	    case 'F':
		KEY("FName", starsystem->filename, fread_string(fp));
		break;

	    case 'N':
		KEY("Name", starsystem->name, fread_string(fp));
		break;

	    case 'S':
		KEY("Star1", starsystem->star1, fread_string(fp));
		KEY("Star2", starsystem->star2, fread_string(fp));
		if (!str_cmp(word, "S1xyz")) {
		    fMatch = TRUE;
		    starsystem->s1x = fread_number(fp);
		    starsystem->s1y = fread_number(fp);
		    starsystem->s1z = fread_number(fp);
		    break;
		}
		if (!str_cmp(word, "S2xyz")) {
		    fMatch = TRUE;
		    starsystem->s2x = fread_number(fp);
		    starsystem->s2y = fread_number(fp);
		    starsystem->s2z = fread_number(fp);
		    break;
		}
		break;
	}
	if (!fMatch)
	    mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: fread_starsystem: no match: %s", word);
    }
}

bool load_starsystem(char *systemfile) {
    FILE *fp;
    SPACE_DATA *starsystem;
    char filename[MAX_INPUT_LENGTH];

    starsystem = (SPACE_DATA *)alloc_perm(sizeof(SPACE_DATA));

    starsystem->first_planet	= NULL;
    starsystem->last_planet	= NULL;
    starsystem->first_ship	= NULL;
    starsystem->last_ship	= NULL;
    starsystem->first_missile	= NULL;
    starsystem->last_missile	= NULL;

    sprintf(filename, "%s%s", SPACE_DIR, systemfile);

    if ((fp = fopen(filename, "r")) == NULL) {
	free_mem(starsystem, sizeof(starsystem));
	return FALSE;
    } else {
	LINK(starsystem, first_starsystem, last_starsystem, next, prev);
	for (;;) {
	    char *word, letter = fread_letter(fp);

	    if (letter == '*') {
		fread_to_eol(fp);
		continue;
	    }
	    if (letter != '#') {
		mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: load_starsystem: # not found.");
		break;
	    }

	    word = fread_word(fp);
	    if (!str_cmp(word, "SPACE")) {
		fread_starsystem(starsystem, fp);
		break;
	    } else if (!str_cmp(word, "END"))
		break;
	    else {
		mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: load_starsystem: bad section: %s.", word);
		break;
	    }
	}
	fclose(fp);
	return TRUE;
    }
}

bool load_planet_file(char *planetfile) {
    FILE *fp;
    PLANET_DATA *planet;
    char filename[MAX_INPUT_LENGTH];

    planet = (PLANET_DATA *)alloc_perm(sizeof(*planet));

    planet->governed_by		= NULL;
    planet->next_in_system	= NULL;
    planet->prev_in_system	= NULL;
    planet->starsystem		= NULL;
    planet->area		= NULL;

    sprintf(filename, "%s%s", PLANET_DIR, planetfile);
    if ((fp = fopen(filename, "r")) == NULL) {
	free_mem(planet, sizeof(planet));
	return FALSE;
    } else {
	LINK(planet, first_planet, last_planet, next, prev);
	for (;;) {
	    char *word, letter = fread_letter(fp);

	    if (letter == '*') {
		fread_to_eol(fp);
		continue;
	    }
	    if (letter != '#') {
		mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: load_planet_file: # not found.");
		break;
	    }

	    word = fread_word(fp);
	    if (!str_cmp(word, "PLANET")) {
		fread_planet(planet, fp);
		break;
	    } else if (!str_cmp(word, "END"))
		break;
	    else {
		mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: load_planet_file: bad section: %s", word);
		break;
	    }
	}
	fclose(fp);
	return TRUE;
    }
}

void load_space(void) {
    FILE *fp;
    char *filename;

    first_starsystem = NULL;
    last_starsystem = NULL;

    fclose(fpReserve);
    if ((fp = fopen(SPACE_LIST, "r")) == NULL) {
	perror(SPACE_LIST);
	exit(1);
    }

    for (;;) {
	filename = feof(fp) ? (char *)"$" : fread_word(fp);
	if (*filename == '$')
	    break;

	if (!load_starsystem(filename))
	    mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: Cannot load starsystem file: %s", filename);
    }
    fclose(fp);
    fpReserve = fopen(NULL_FILE, "r");
    return;
}

void load_planets(void) {
    FILE *fp;
    char *filename;

    first_planet	= NULL;
    last_planet		= NULL;

    fclose(fpReserve);
    if ((fp = fopen(PLANET_LIST, "r")) == NULL) {
	perror(PLANET_LIST);
	exit(1);
    }

    for (;;) {
	filename = feof(fp) ? (char *)"$" : fread_word(fp);

	if (*filename == '$')
	    break;

	if (!load_planet_file(filename))
	    mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: Cannot load starsystem file: %s", filename);
    }
    fclose(fp);
    fpReserve = fopen(NULL_FILE, "r");
    return;
}

void write_ship_list(void) {
    FILE *fp;
    SHIP_DATA *ship;

    if (!(fp = fopen(SHIP_LIST, "w"))) {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: Could not open %s for writing.", SHIP_LIST);
	return;
    }

    for (ship = first_ship; ship; ship = ship->next)
	if (ship->type != MOB_SHIP && ship->owner && *ship->owner)
	    fprintf(fp, "%s\n", ship->filename);
    fprintf(fp, "$\n");
    fclose(fp);
}

void save_ship(SHIP_DATA *ship) {
    FILE *fp;
    ROOM_INDEX_DATA *room;
    char filename[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];

    if (!ship) {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: save_ship: null pointer");
	return;
    }

    if (ship->type == MOB_SHIP)
	return;

    if (!ship->filename || !*ship->filename) {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: save_ship: %s has no filename.", ship->name);
	return;
    }

    sprintf(filename, "%s%s", SHIP_DIR, ship->filename);

    fclose(fpReserve);
    if ((fp = fopen(filename, "w")) == NULL) {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: save_ship: Cannot open %s for writing.", filename);
	perror(filename);
    } else {
	fprintf(fp, "#SHIP\n");
	fprintf(fp, "Name %s~\n", ship->name);
	fprintf(fp, "FName %s~\n", ship->filename);
	for (room = ship->first_room; room; room = room->next_in_ship)
	    fprintf(fp, "Desc %s~\n", room->description);

	fprintf(fp, "Owner %s~\n", ship->owner);
	fprintf(fp, "Pilot %s~\n", ship->pilot);
	fprintf(fp, "Copilot %s~\n", ship->copilot);
	fprintf(fp, "Model %d\n", ship->model);
	fprintf(fp, "Class %d\n", ship->shipclass);
	fprintf(fp, "Shipyard %d\n", ship->shipyard);
	fprintf(fp, "Lasers %d\n", ship->lasers);
	fprintf(fp, "Laserstate %d\n", ship->laserstate);
	fprintf(fp, "Missiles %d\n", ship->missiles);
	fprintf(fp, "Maxmissiles %d\n", ship->maxmissiles);
	fprintf(fp, "Lastdoc %d\n", ship->lastdoc);
	fprintf(fp, "Shield %d\n", ship->shield);
	fprintf(fp, "Maxshield %d\n", ship->maxshield);
	fprintf(fp, "Hull %d\n", ship->hull);
	fprintf(fp, "Maxhull %d\n", ship->maxhull);
	fprintf(fp, "Maxenergy %d\n", ship->maxenergy);
	fprintf(fp, "Hyperspeed %d\n", ship->hyperspeed);
	fprintf(fp, "Chaff %d\n", ship->chaff);
	fprintf(fp, "Maxchaff %d\n", ship->maxchaff);
	fprintf(fp, "Realspeed %d\n", ship->realspeed);
	fprintf(fp, "Type %d\n", ship->type);
	fprintf(fp, "Shipstate %d\n", ship->shipstate);
	fprintf(fp, "Missilestate %d\n", ship->missilestate);
	fprintf(fp, "Energy %d\n", ship->energy);
	fprintf(fp, "Manuever %d\n", ship->manuever);
	fprintf(fp, "Home %s~\n", ship->home);
	fprintf(fp, "End\n\n");
	fprintf(fp, "#END\n");
    }
    fclose(fp);
    fpReserve = fopen(NULL_FILE, "r");
    return;
}

void fread_ship(SHIP_DATA *ship, FILE *fp) {
    char *word;
    bool fMatch;
    SInt32 dIndex = 0;

    for (;;) {
	word = feof(fp) ? (char *)"End" : fread_word(fp);
	fMatch = FALSE;

	switch (UPPER(word[0])) {
	    case '*':
		fMatch = TRUE;
		fread_to_eol(fp);
		break;
	    case 'C':
		KEY("Class",	ship->shipclass,	fread_number(fp));
		KEY("Chaff",	ship->chaff,		fread_number(fp));
		KEYS("Copilot",	ship->copilot,		fread_string(fp));
		break;
	    case 'D':
		if (dIndex < MAX_SHIP_ROOMS)
		    KEYS("Desc", ship->description[dIndex++], fread_string(fp));
		break;
	    case 'E':
		KEY("Energy",	ship->energy,		fread_number(fp));
		if (!str_cmp(word, "End")) {
		    if (!ship->home)
			ship->home = str_dup("");
		    if (!ship->name)
			ship->name = str_dup("");
		    if (!ship->owner)
			ship->owner = str_dup("");
		    if (!ship->pilot)
			ship->pilot = str_dup("");
		    if (!ship->copilot)
			ship->copilot = str_dup("");
		    if (ship->shipstate != SHIP_DISABLED)
			ship->shipstate = SHIP_DOCKED;
		    if (ship->laserstate != LASER_DAMAGED)
			ship->laserstate = LASER_READY;
		    if (ship->missilestate != MISSILE_DAMAGED)
			ship->missilestate = MISSILE_READY;
		    if (ship->shipyard <= 0)
			ship->shipyard = ROOM_SHIP_LIMBO;
		    if (ship->lastdoc <= 0)
			ship->lastdoc = ship->shipyard;

		    ship->autopilot = FALSE;
		    ship->hatchopen = FALSE;
		    ship->starsystem = NULL;

		    ship->hull = ship->maxhull;
		    ship->energy = ship->maxenergy;

		    ship->in_room = NULL;
		    ship->next_in_room = NULL;
		    ship->prev_in_room = NULL;
		    ship->first_turret = NULL;
		    ship->last_turret = NULL;
		    ship->first_hanger = NULL;
		    ship->last_hanger = NULL;
		    create_ship_rooms(ship);
		    return;
		}
		break;
	    case 'F':
		KEYS("FName",	ship->filename,		fread_string(fp));
		break;
	    case 'H':
		KEY("Hyperspeed", ship->hyperspeed,	fread_number(fp));
		KEY("Hull",	ship->hull,		fread_number(fp));
		KEYS("Home",	ship->home,		fread_string(fp));
		break;
	    case 'L':
		KEY("Lasers",	ship->lasers,		fread_number(fp));
		KEY("Laserstate", ship->laserstate,	fread_number(fp));
		KEY("Lastdoc",	ship->lastdoc,		fread_number(fp));
		break;
	    case 'M':
		KEY("Model",	ship->model,		fread_number(fp));
		KEY("Manuever",	ship->manuever,		fread_number(fp));
		KEY("Missiles",	ship->missiles,		fread_number(fp));
		KEY("Maxmissiles", ship->maxmissiles,	fread_number(fp));
		KEY("Maxshield",ship->maxshield,	fread_number(fp));
		KEY("Maxenergy",ship->maxenergy,	fread_number(fp));
		KEY("Maxhull",	ship->maxhull,		fread_number(fp));
		KEY("Maxchaff",	ship->maxchaff,		fread_number(fp));
		KEY("Missilestate", ship->missilestate,	fread_number(fp));
		break;
	    case 'N':
		KEYS("Name",	ship->name,		fread_string(fp));
		break;
	    case 'O':
		KEYS("Owner",	ship->owner,		fread_string(fp));
		break;
	    case 'P':
		KEYS("Pilot",	ship->pilot,		fread_string(fp));
		break;
	    case 'R':
		KEY("Realspeed",ship->realspeed,	fread_number(fp));
		break;
	    case 'S':
		KEY("Shipyard",	ship->shipyard,		fread_number(fp));
		KEY("Shield",	ship->shield,		fread_number(fp));
		KEY("Shipstate",ship->shipstate,	fread_number(fp));
		break;
	    case 'T':
		KEY("Type",	ship->type,		fread_number(fp));
		break;
	}
	if (!fMatch)
	    mudlogf(BRF, LVL_STAFF, TRUE, "fread_ship: no match: %s", word);
    }
}

void fread_planet(PLANET_DATA *planet, FILE *fp) {
    bool fMatch;
    char *word, buf[MAX_STRING_LENGTH];

    for (;;) {
	fMatch = FALSE;
	word = feof(fp) ? (char *)"End" : fread_word(fp);

	switch (UPPER(word[0])) {
	    case '*':
		fMatch = TRUE;
		fread_to_eol(fp);
		break;

	    case 'A':
		if (!str_cmp(word, "Area")) {
		    AREA_DATA *pArea;
		    char area_name[MAX_STRING_LENGTH];

		    sprintf(area_name, fread_string(fp));
		    for (pArea = area_first; pArea; pArea = pArea->next)
			if (pArea->file_name && !str_cmp(pArea->file_name, area_name)) {
			    ROOM_INDEX_DATA *room;

			    planet->size = 0;
			    planet->citysize = 0;
			    planet->wilderness = 0;
			    planet->farmland = 0;
			    planet->barracks = 0;
			    planet->controls = 0;
			    pArea->planet = planet;
			    planet->area = pArea;
			}
		    fMatch = TRUE;
		}
		break;

	    case 'E':
		if (!str_cmp(word, "End")) {
		    if (!planet->name)
			planet->name = str_dup("");
		    return;
		}
		break;

	    case 'F':
		KEYS("Filename",	planet->filename,	fread_string(fp));
		break;

	    case 'G':
		if (!str_cmp(word, "GovernedBy")) {
//		    planet->governed_by = -1;
		    fMatch = TRUE;
		}
		break;

	    case 'N':
		KEYS("Name",	planet->name,	fread_string(fp));
		break;

	    case 'P':
		KEY("Popsupport",	planet->pop_support,	fread_number(fp));
		break;

	    case 'S':
		KEY("Sector",	planet->sector,		fread_number(fp));
		if (!str_cmp(word, "Starsystem")) {
		    planet->starsystem = starsystem_from_name(fread_string(fp));
		    if (planet->starsystem) {
			SPACE_DATA *starsystem = planet->starsystem;
			LINK(planet, starsystem->first_planet, starsystem->last_planet, next_in_system, prev_in_system);
		    }
		    fMatch = TRUE;
		}
		break;

	    case 'X':
		KEY("X",	planet->x,	fread_number(fp));
		break;

	    case 'Y':
		KEY("Y",	planet->y,	fread_number(fp));
		break;

	    case 'Z':
		KEY("Z",	planet->z,	fread_number(fp));
		break;
	}

	if (!fMatch)
	    mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: fread_planet: no match %s", word);
    }
}

bool load_ship_file(char *shipfile) {
    FILE *fp;
    SHIP_DATA *ship;
    CLAN_DATA *clan;
    char filename[MAX_INPUT_LENGTH];

    ship = (SHIP_DATA *)alloc_mem(sizeof(SHIP_DATA));
    sprintf(filename, "%s%s", SHIP_DIR, shipfile);

    if ((fp = fopen(filename, "r")) == NULL) {
	free_mem(ship, sizeof(ship));
	return FALSE;
    } else {
	for (;;) {
	    char *word, letter;

	    letter = fread_letter(fp);
	    if (letter == '*') {
		fread_to_eol(fp);
		continue;
	    }
	    if (letter != '#') {
		mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: load_ship_file: # not found.");
		break;
	    }

	    word = fread_word(fp);
	    if (!str_cmp(word, "SHIP")) {
		fread_ship(ship, fp);
		break;
	    } else if (!str_cmp(word, "END"))
		break;
	    else {
		mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: load_ship_file: bad section: %s", word);
		break;
	    }
	}
    }
    fclose(fp);

    LINK(ship, first_ship, last_ship, next, prev);
    if (ship->shipclass == SPACE_STATION || ship->type == MOB_SHIP) {
	ship->currspeed = 0;
	ship->shield	= 0;
	ship->currjump	= NULL;
	ship->target	= NULL;
	ship->energy	= ship->maxenergy;
	ship->chaff	= ship->maxchaff;
	ship->hull	= ship->maxhull;
	ship->missiles	= ship->maxmissiles;
	ship->shield	= ship->maxshield;

	ship->laserstate	= LASER_READY;
	ship->missilestate	= MISSILE_READY;

	ship->hatchopen		= FALSE;
	ship->autorecharge	= FALSE;
	ship->autotrack		= FALSE;
	ship->autospeed		= FALSE;

	ship_to_starsystem(ship, starsystem_from_name(ship->home));
	ship->vx = number_range(-5000, 5000);
	ship->vy = number_range(-5000, 5000);
	ship->vz = number_range(-5000, 5000);
	ship->hx = ship->hy = ship->hz = 1;
	ship->shipstate = SHIP_READY;
	ship->autopilot = TRUE;
	ship->autorecharge = TRUE;
    } else {
	ship_to_room(ship, ship->lastdoc);
	ship->location = ship->lastdoc;
    }

    if (ship->type != MOB_SHIP && ship->clan != -1) {
	if (ship->shipclass <= SPACE_STATION)
	;
//	    clan->spacecraft++;
	else
	;
//	    clan->vehicles++;
    }
    return TRUE;
}

void load_ships(void) {
    FILE *fp;
    char *filename;

    first_ship		= NULL;
    last_ship		= NULL;
    first_missile	= NULL;
    last_missile	= NULL;

    fclose(fpReserve);
    if ((fp = fopen(SHIP_LIST, "r")) == NULL) {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: Couldn't open %s for reading.", SHIP_LIST);
	exit(1);
    }

    for (;;) {
	filename = feof(fp) ? (char *)"$" : fread_word(fp);

	if (filename[0] == '$')
	    break;

	if (!load_ship_file(filename))
	    mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: Couldn't load ship file: %s", filename);
    }
    fclose(fp);
    fpReserve = fopen(NULL_FILE, "r");
    return;
}

void reset_ship(SHIP_DATA *ship) {
    ship->shipstate = SHIP_READY;

    if (ship->shipclass != SPACE_STATION && ship->type != MOB_SHIP) {
	extract_ship(ship);
	ship_to_room(ship, ship->lastdoc);
	ship->location = ship->lastdoc;
	ship->shipstate = SHIP_DOCKED;
	free_string(ship->home);
	ship->home = str_dup("");
    }

    if (ship->starsystem)
	ship_from_starsystem(ship, ship->starsystem);

    ship->shield	= 0;
    ship->currspeed	= 0;
    ship->hull		= ship->maxhull;
    ship->chaff		= ship->maxchaff;
    ship->energy	= ship->maxenergy;
    ship->missiles	= ship->maxmissiles;

    ship->laserstate	= LASER_READY;
    ship->missilestate	= MISSILE_READY;

    ship->target	= NULL;
    ship->currjump	= NULL;

    ship->hatchopen	= FALSE;
    ship->autotrack	= FALSE;
    ship->autospeed	= FALSE;
    ship->autorecharge	= FALSE;

    save_ship(ship);
}

ROOM_INDEX_DATA *make_ship_room(SHIP_DATA *ship) {
    ROOM_INDEX_DATA *pRoomIndex = new_room_index();

    pRoomIndex->area		= NULL;
    pRoomIndex->vnum		= -1;
    pRoomIndex->name		= str_dup(ship->name);
    pRoomIndex->description	= str_dup("Inside the ship.\n\r");
    pRoomIndex->sector_type	= SECT_INSIDE;

    SET_BIT(ROOM_FLAGS(pRoomIndex), ROOM_INDOORS | ROOM_SPACECRAFT);
    LINK(pRoomIndex, ship->first_room, ship->last_room, next_in_ship, prev_in_ship);
    top_room++;

    return pRoomIndex;
}

void create_ship_rooms(SHIP_DATA *ship) {
    int roomnum, numrooms;
    ROOM_INDEX_DATA *room[24];

    if (ship->shipclass != SPACECRAFT)
	ship->model = 0;

    numrooms = UMIN(1, MAX_SHIP_ROOMS-1);

    for (roomnum = 0; roomnum < numrooms; roomnum++)
	room[roomnum] = make_ship_room(ship);

    switch (ship->model) {
	default:
	    ship->pilotseat	= room[0];
	    ship->gunseat	= room[0];
	    ship->viewscreen	= room[0];
	    ship->entrance	= room[0];
	    ship->engine	= room[0];
	    break;
    }

    for (roomnum = 0; roomnum < numrooms; roomnum++) {
	if (ship->description[roomnum] && ship->description[roomnum][0] != '\0') {
	    free_string(room[roomnum]->description);
	    room[roomnum]->description = str_dup(ship->description[roomnum]);
	}
    }
}

ACMD(do_openhatch) {
    SHIP_DATA *ship;
    char buf[MAX_STRING_LENGTH];

    if (!argument || argument[0] == '\0' || !str_cmp(argument, "hatch")) {
	if ((ship = ship_from_entrance(ch->in_room)) == NULL) {
	    ch->Send("Open what?\n\r");
	    return;
	} else {
	    if (!ship->hatchopen) {
		if (ship->shipclass == SPACE_STATION) {
		    ch->Send("Try one of the docking bays!\n\r");
		    return;
		}
		if (ship->location != ship->lastdoc
		|| (ship->shipstate != SHIP_DOCKED && ship->shipstate != SHIP_DISABLED)) {
		    ch->Send("Please wait until the ship lands!\n\r");
		    return;
		}
		ship->hatchopen = TRUE;
		ch->Send("You open the hatch.\n\r");
		act("$n opens the hatch.", ch, 0, 0, TO_ROOM);
		sprintf(buf, "The hatch on %s opens.", ship->name);
		echo_to_room(get_room_index(ship->location), buf);
		return;
	    } else {
		ch->Send("It's already open.\n\r");
		return;
	    }
	}
    }

    argument = one_argument(argument, buf);
    if ((ship = ship_in_room(ch->in_room, argument)) == NULL) {
	act("I see no $T here.", ch, NULL, argument, TO_CHAR);
	return;
    }

    if (ship->shipstate != SHIP_DOCKED && ship->shipstate != SHIP_DISABLED) {
	ch->Send("That ship has already started to launch.\n\r");
	return;
    }

    if (!check_pilot(ch, ship)) {
	ch->Send("That's not your ship!\n\r");
	return;
    }

    if (!ship->hatchopen) {
	ship->hatchopen = TRUE;
	act("You open the hatch on $T.", ch, 0, ship->name, TO_CHAR);
	act("$n opens the hatch on $T.", ch, 0, ship->name, TO_ROOM);
	echo_to_room(ship->entrance, "The hatch opens from the outside.`n");
	return;
    }
    ch->Send("Its already open!\n\r");
}

ACMD(do_boardship) {
    SHIP_DATA *ship;
    ROOM_INDEX_DATA *toroom, *fromroom;

    if (!argument || argument[0] == '\0') {
	ch->Send("Board what?\n\r");
	return;
    }

    if ((ship = ship_in_room(ch->in_room, argument)) == NULL) {
	act("I see no $T here.", ch, 0, argument, TO_CHAR);
	return;
    }

    fromroom = ch->in_room;

    if ((toroom = ship->entrance) != NULL) {
	if (!ship->hatchopen) {
	    ch->Send("The hatch is closed!\n\r");
	    return;
	}
	if (ship->shipstate == SHIP_LAUNCH || ship->shipstate == SHIP_LAUNCH_2) {
	    ch->Send("That ship has already started launching!\n\r");
	    return;
	}

	act("You enter $T.", ch, 0, ship->name, TO_CHAR);
	act("$n enters $T.", ch, 0, ship->name, TO_ROOM);
	char_from_room(ch);
	char_to_room(ch, toroom);
	act("$n enters the ship.", ch, 0, 0, TO_ROOM);
	do_look(ch, "", 0);
    } else
	ch->Send("That ship has no entrance!\n\r");
}

ACMD(do_land) {
    RNum vnum;
    PLANET_DATA *planet;
    ROOM_INDEX_DATA *room;
    SHIP_DATA *ship, *target;
    bool rfound = FALSE, pfound = FALSE;
    char arg[MAX_INPUT_LENGTH], arg1[MAX_INPUT_LENGTH];

    strcpy(arg, argument);
    argument = one_argument(argument, arg1);

    if ((ship = ship_from_pilotseat(IN_ROOM(ch))) == NULL) {
	ch->Send("`RYou must be in the pilots seat of a ship to do that!`n\n\r");
	return;
    }

    if (ship->shipclass > SPACE_STATION) {
	ch->Send("`RThis isn't a spacecraft!`n\n\r");
	return;
    }

    if (autofly(ship)) {
	ch->Send("`RYou'll have to turn off the ships autopilot first.`n\n\r");
	return;
    }

    if (ship->shipclass == SPACE_STATION) {
	ch->Send("`RYou can't land space stations.`n\n\r");
	return;
    }

    switch (ship->shipstate) {
	case SHIP_DISABLED:
	    ch->Send("`RThe ships drive is disabled. Unable to land.`n\n\r");
	    return;
	case SHIP_DOCKED:
	    ch->Send("`RThe ship is already docked!`n\n\r");
	    return;
	case SHIP_HYPERSPACE:
	    ch->Send("`RYou can only do that in realspace!`n\n\r");
	    return;
	default:
	    break;
    }

    if (ship->shipstate != SHIP_READY) {
	ch->Send("`RPlease wait until the ship has finished its current manouver.`n\n\r");
	return;
    }

    if (ship->starsystem == NULL) {
	ch->Send("`RThere's nowhere to land around here.`n\n\r");
	return;
    }

    if (!*arg) {
	ch->Send("`CLand where? Choices:\n\r");
	for (target = ship->starsystem->first_ship; target; target = target->next_in_starsystem) {
	    if (target->shipclass == SPACE_STATION && target != ship)
		ch->Send("%-24.24s    %.0f %.0f %.0f\n\r", target->name, target->vx, target->vy, target->vz);
	}
	for (planet = ship->starsystem->first_planet; planet; planet = planet->next_in_system)
	    ch->Send("%-24.24s   %.0f %.0f %.0f\n\r", planet->name, planet->x, planet->y, planet->z);

	ch->Send("\n\rYour Coordinates: %.0f %.0f %.0f`n\n\r", ship->vx, ship->vy, ship->vz);
	return;
    }

    for (planet = ship->starsystem->first_planet; planet; planet = planet->next_in_system) {
	if (!str_prefix(arg1, planet->name)) {
	    pfound = TRUE;

	    if (!planet->area) {
		ch->Send("`RThat planet doesn't have any landing areas.`n\n\r");
		return;
	    }
	    if ((planet->x > ship->vx + 200) || (planet->x < ship->vx - 200) ||
	    (planet->y > ship->vy + 200) || (planet->y < ship->vy - 200) ||
	    (planet->z > ship->vz + 200) || (planet->z < ship->vz - 200)) {
		ch->Send("`RThat planet is too far away! You'll have to fly a little closer.`n\n\r");
		return;
	    }
	    if (*argument) {
		for (vnum = planet->area->min_vnum; vnum <= planet->area->max_vnum; vnum++) {
		    if ((room = get_room_index(vnum)) != NULL
		    && ROOM_FLAGGED(room, ROOM_CAN_LAND)
		    && !str_prefix(argument, room->name)) {
			rfound = TRUE;
			break;
		    }
		}
	    }
	    if (!rfound) {
		ch->Send("`CPlease type the location after the planet name.`n\n\r");
		ch->Send("Possible choices for %s:\n\r\n\r", planet->name);
		for (vnum = planet->area->min_vnum; vnum <= planet->area->max_vnum; vnum++)
		    if ((room = get_room_index(vnum)) != NULL && ROOM_FLAGGED(room, ROOM_CAN_LAND))
			ch->Send("%s\n\r", room->name);
		return;
	    }
	    break;
	}
    }

    if (!pfound) {
	if ((target = get_ship_here(arg, ship->starsystem)) != NULL) {
	    if (target == ship) {
		ch->Send("`RYou can't land your ship inside itself!`n\n\r");
		return;
	    }
	    if (target->shipclass != SPACE_STATION) {
		ch->Send("`RThat ship has no hanger for you to land in!`n\n\r");
		return;
	    }
	    if ((target->vx > ship->vx + 200) || (target->vx < ship->vx - 200) ||
	    (target->vy > ship->vy + 200) || (target->vy < ship->vy - 200) ||
	    (target->vz > ship->vz + 200) || (target->vz < ship->vz - 200)) {
		ch->Send("`RThat ship is too far away! You'll have to fly a little closer.`n\n\r");
		return;
	    }
	} else {
	    ch->Send("`RI don't see that here.`n\n\r");
	    do_land(ch, "", 0);
	    return;
	}
    }

    ch->Send("`GLanding sequence initiated.`n\n\r");
    act("$n begins the landing sequence.", ch, NULL, NULL, TO_ROOM);
    echo_to_ship(TO_SHIP, ship, "`YThe ship slowly begins its landing aproach.`n");
    ship->dest = str_dup(arg);
    ship->shipstate = SHIP_LAND;
    ship->currspeed = 0;
}

ACMD(do_launch) {
    SHIP_DATA *ship;
    char buf[MAX_STRING_LENGTH];

    if ((ship = ship_from_pilotseat(IN_ROOM(ch))) == NULL) {
	ch->Send("You must be in the pilot's seat of a ship to do that!\n\r");
	return;
    }

    if (ship->shipclass > SPACE_STATION) {
	ch->Send("`RThis isn't a spacecraft.`n\n\r");
	return;
    }
    if (ship->shipclass == SPACE_STATION) {
	ch->Send("You can't do that here.\n\r");
	return;
    }
    if (ship->lastdoc != ship->location) {
	ch->Send("`rYou don't seem to be docked right now.`n\n\r");
	return;
    }
    if (ship->shipstate != SHIP_DOCKED && ship->shipstate != SHIP_DISABLED) {
	ch->Send("The ship is not docked right now.\n\r");
	return;
    }

    if (ship->hatchopen) {
	ship->hatchopen = FALSE;
	sprintf(buf, "`YThe hatch on %s closes.`n",ship->name);
	echo_to_room(get_room_index(ship->location), buf);
	echo_to_room(ship->entrance, "`YThe hatch slides shut.`n");
    }

    ship->shield	= 0;
    ship->hull		= ship->maxhull;
    ship->chaff		= ship->maxchaff;
    ship->energy	= ship->maxenergy;
    ship->missiles	= ship->maxmissiles;
    ship->autorecharge	= FALSE;
    ship->autotrack	= FALSE;
    ship->autospeed	= FALSE;

    ship->shipstate	= SHIP_READY;
    ship->laserstate	= LASER_READY;
    ship->missilestate	= MISSILE_READY;

    ch->Send("`GLaunch sequence initiated.`n\n\r");
    echo_to_ship(TO_SHIP, ship, "`YThe ship hums as it lifts off the ground.`n");
    sprintf(buf, "`Y%s begins to launch.`n", ship->name);
    echo_to_room(get_room_index(ship->location), buf);
    ship->shipstate	= SHIP_LAUNCH;
    ship->currspeed	= ship->realspeed;
}

ACMD(do_radar) {
    PLANET_DATA *planet;
    MISSILE_DATA *missile;
    SHIP_DATA *ship, *target;
    double x, y, z, distance;

    if ((ship = ship_from_cockpit(ch->in_room)) == NULL) {
	ch->Send("`RYou must be in the cockpit or turret of a ship to do that!`n\n\r");
	return;
    }

    if (ship->shipclass > SPACE_STATION) {
	ch->Send("`RThis isn't a spacecraft!`n\n\r");
	return;
    }

    switch (ship->shipstate) {
	case SHIP_DOCKED:
	    ch->Send("`RWait until after you launch!`n\n\r");
	    return;
	case SHIP_HYPERSPACE:
	    ch->Send("`RYou can only do that in normal space.`n\n\r");
	    return;
	default:
	    break;
    }

    if (ship->starsystem == NULL) {
	ch->Send("`RYou can't do that unless the ship is flying in normal space.`n\n\r");
	return;
    }

    act("$n checks the radar.", ch, 0, 0, TO_ROOM);
    ch->Send("%s\n\r\n\r", ship->starsystem->name);

    if (ship->starsystem->star1 && ship->starsystem->star1[0] != '\0') {
	x = ship->vx - ship->starsystem->s1x;
	y = ship->vy - ship->starsystem->s1y;
	z = ship->vz - ship->starsystem->s1z;
	distance = sqrt(x*x + y*y + z*z);

	ch->Send("`Y%-14.14s   %.0f %.0f %.0f; (%.0f)`n\n\r",
	    ship->starsystem->star1,
	    ship->starsystem->s1x, ship->starsystem->s1y,
	    ship->starsystem->s1z, distance);
    }

    if (ship->starsystem->star2 && ship->starsystem->star2[0] != '\0') {
	x = ship->vx - ship->starsystem->s2x;
	y = ship->vy - ship->starsystem->s2y;
	z = ship->vz - ship->starsystem->s2z;
	distance = sqrt(x*x + y*y + z*z);

	ch->Send("`Y%-14.14s   %.0f %.0f %.0f; (%.0f)`n\n\r",
	    ship->starsystem->star2,
	    ship->starsystem->s2x, ship->starsystem->s2y,
	    ship->starsystem->s2z, distance);
    }

    for (planet = ship->starsystem->first_planet; planet; planet = planet->next_in_system) {
	x = ship->vx - planet->x;
	y = ship->vy - planet->y;
	z = ship->vz - planet->z;
	distance = sqrt(x*x + y*y + z*z);

	ch->Send("`G%-14.14s   %.0f %.0f %.0f; (%.0f)`n\n\r",
	    planet->name,
	    planet->x, planet->y, planet->z, distance);
    }

    ch->Send("\n\r");
    for (missile = ship->starsystem->first_missile; missile; missile = missile->next_in_starsystem) {
	x = ship->vx - missile->mx;
	y = ship->vy - missile->my;
	z = ship->vz - missile->mz;
	distance = sqrt(x*x + y*y + z*z);

	ch->Send("`R%-14.14s   %.0f %.0f %.0f; (%.0f)`n\n\r",
	    "A missile", missile->mx, missile->my, missile->mz, distance);
    }

    ch->Send("\n\r");
    for (target = ship->starsystem->first_ship; target; target = target->next_in_starsystem) {
	if (target == ship)
	    continue;

	x = ship->vx - target->vx;
	y = ship->vy - target->vy;
	z = ship->vz - target->vz;
	distance = sqrt(x*x + y*y + z*z);

	ch->Send("`C%s    %.0f %.0f %.0f; (%.0f)`n\n\r",
	    target->name, target->vx, target->vy, target->vz, distance);
    }

    ch->Send("\n\r`WYour coordinates: %.0f %.0f %.0f\n\r",
	ship->vx, ship->vy, ship->vz);
}

ACMD(do_accelerate) {
    int change;
    SHIP_DATA *ship;

    if ((ship = ship_from_pilotseat(ch->in_room)) == NULL) {
	ch->Send("`RYou must be at the controls of a ship to do that!n\n\r");
	return;
    }

    if (ship->shipclass > SPACE_STATION) {
	ch->Send("`RThis isn't a spacecraft!`n\n\r");
	return;
    }

    if (autofly(ship)) {
	ch->Send("`RYou'll have to turn off the ships autopilot first.`n\n\r");
	return;
    }

    if (ship->shipclass == SPACE_STATION) {
	ch->Send("`RPlatforms don't fly!`n\n\r");
	return;
    }

    switch (ship->shipstate) {
	case SHIP_HYPERSPACE:
	    ch->Send("`RYou can only do that in realspace!`n\n\r");
	    return;
	case SHIP_DISABLED:
	    ch->Send("`RThe ships drive is disabled. Unable to accelerate.`n\n\r");
	    return;
	case SHIP_DOCKED:
	    ch->Send("`RYou can't do that until after you've launched!`n\n\r");
	    return;
	default:
	    break;
    }

    change = atoi(argument);
    if (ship->energy < flabs((change - flabs(ship->currspeed)) / 10)) {
	ch->Send("`RThere is not enough fuel!`n\n\r");
	return;
    }

    act("$n manipulates the ship's controls.", ch, 0, 0, TO_ROOM);

    if (ship->currspeed < change) {
	ch->Send("`GAccelerating`n\n\r");
	echo_to_ship(TO_COCKPIT, ship, "`YThe ship begins to accelerate.`n");
	echo_to_system(ship, NULL, "`y%s begins to speed up.`n", ship->name);
    }

    if (ship->currspeed > change) {
	ch->Send("`GDecelerating`n\n\r");
	echo_to_ship(TO_COCKPIT, ship, "`YThe ship begins to slow down.`n");
	echo_to_system(ship, NULL, "`y%s begins to slow down.`n", ship->name);
    }

    ship->energy -= flabs((change - flabs(ship->currspeed))/10);
    ship->currspeed = URANGE(0 , change, ship->realspeed);
}

ACMD(do_course) {
    SHIP_DATA *ship;
    float vx, vy, vz;
    char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];

    if ((ship = ship_from_pilotseat(ch->in_room)) == NULL) {
	ch->Send("`RYou must be at the healm of a ship to do that!`n\n\r");
	return;
    }

    if (ship->shipclass > SPACE_STATION) {
	ch->Send("`RThis is not a spacecraft.`n\n\r");
	return;
    }

    if (autofly(ship)) {
	ch->Send("`RYou'll have to turn off the ships autopilot first.`n\n\r");
	return;
    }

    if (ship->shipstate == SHIP_DISABLED) {
	ch->Send("`RThe ships drive is disabled. Unable to manuever.`n\n\r");
	return;
    }

    if (ship->shipclass == SPACE_STATION) {
	ch->Send("`RPlatforms cannot fly.`n\n\r");
	return;
    }

    switch (ship->shipstate) {
	case SHIP_HYPERSPACE:
	    ch->Send("`RYou can only do that in realspace!`n\n\r");
	    return;
	case SHIP_DOCKED:
	    ch->Send("`RYou can't do that until after you've launched!`n\n\r");
	    return;
	default:
	    break;
    }

    if (ship->shipstate != SHIP_READY) {
	ch->Send("`RPlease wait until the ship has finished its current manouver.`n\n\r");
	return;
    }

    if (ship->energy < (ship->currspeed / 10)) {
	ch->Send("`RThere is not enough fuel!`n\n\r");
	return;
    }

    argument = one_argument(argument, arg1);
    argument = one_argument(argument, arg2);

    vx = atof(arg1);
    vy = atof(arg2);
    vz = atof(argument);

    if (vx == ship->vx && vy == ship->vy && vz == ship->vz) {
	ch->Send("The ship is already at %.0f %.0f %.0f!\n\r", vx, vy, vz);
	return;
    }

    ship->hx = vx - ship->vx;
    ship->hy = vy - ship->vy;
    ship->hz = vz - ship->vz;
    ship->energy -= (ship->currspeed / 10);

    ch->Send("`GNew course set, aproaching %.0f %.0f %.0f.`n\n\r", vx, vy, vz);
    act("$n manipulates the ships controls.", ch, 0, 0, TO_ROOM);
    echo_to_ship(TO_COCKPIT, ship, "`YThe ship begins to turn.`n");
    echo_to_system(ship, NULL, "`y%s turns altering its present course.`n", ship->name);

    if (ship->manuever > 100)
	ship->shipstate = SHIP_BUSY_3;
    else if (ship->manuever > 50)
	ship->shipstate = SHIP_BUSY_2;
    else
	ship->shipstate = SHIP_BUSY;
}

ACMD(do_shipstat) {
    SHIP_DATA *ship, *target;

    if ((ship = ship_from_cockpit(IN_ROOM(ch))) == NULL) {
	ch->Send("`RYou must be in the cockpit, turret or engineroom of a ship to do that!`n\n\r");
	return;
    }

    if (!*argument)
	target = ship;
    else
	target = get_ship_here(argument, ship->starsystem);

    if (target == NULL) {
	ch->Send("`RI don't see that here.`n\n\r"
	"`RTry the radar, or type status by itself for your ship's status.`n\n\r");
	return;
    }

    act("$n checks various gages and displays on the control panel.", ch, 0, 0, TO_ROOM);
    ch->Send(
	"`W%s:`n\n\r"
	"`yCurrent Speed      : `Y%d`y/`Y%d`n\n\r"
	"`yCurrent Heading    : `Y%.0f %.0f %.0f`n\n\r"
	"`yCurrent Coordinates: `Y%.0f %.0f %.0f`n\n\r"
	"`yCurrent Target     : `Y%s`n\n\r"
	"`yShip Condition     : `Y%s`n\n\r"
	"`yLaser Condition    : `Y%-11.11s  `yMissile Condition: `Y%s`n\n\r"
	"`yHull               : `Y%5d`y/`Y%-5d  `yShields : `Y%d`y/`Y%d`n\n\r"
	"`yEnergy (fuel)      : `Y%5d`y/`Y%-5d  `yMissiles: `Y%d`y/`Y%d`n\n\r",
	target->name, target->currspeed, target->realspeed,
	target->hx, target->hy, target->hz,
	target->vx, target->vy, target->vz,
	target->target ? target->target->name : "None",
	target->shipstate == SHIP_DISABLED ? "Disabled" : "Running",
	target->laserstate == LASER_DAMAGED ? "Damaged" : "Good",
	target->missilestate == MISSILE_DAMAGED ? "Damaged" : "Good",
	target->hull, target->maxhull, target->shield, target->maxshield,
	target->energy, target->maxenergy, target->missiles, target->maxmissiles);
}

ACMD(do_calculate) {
    int count = 0;
    SHIP_DATA *ship;
    PLANET_DATA *planet;
    SPACE_DATA *starsystem;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];

    argument = one_argument(argument, arg1);
    argument = one_argument(argument, arg2);
    argument = one_argument(argument, arg3);

    if ((ship = ship_from_pilotseat(IN_ROOM(ch))) == NULL) {
	ch->Send("`RYou must be in control of a ship to do that!`n\n\r");
	return;
    }

    if (ship->shipclass > SPACE_STATION) {
	ch->Send("`RThis isn't a space craft.`n\n\r");
	return;
    }

    if (autofly(ship)) {
	ch->Send("`RYou'll have to turn off the ships autopilot first.`n\n\r");
	return;
    }

    if (ship->shipclass == SPACE_STATION) {
	ch->Send("`RThis station is a little too big for hyperspace.`n\n\r");
	return;
    }

    if (ship->hyperspeed == 0) {
	ch->Send("`RThis ship is not equipped with a hyperdrive!\n\r");
	return;
    }

    if (ship->shipstate == SHIP_DOCKED) {
	ch->Send("`RYou can't do that until after you've launched!`n\n\r");
	return;
    }

    if (ship->starsystem == NULL) {
	ch->Send("`RYou can only do that in real space.`n\n\r");
	return;
    }

    if (!*argument) {
	ch->Send("`WUsage: Calculate <starsystem> <entry x> <entry y> <entry z>\n\r");
	ch->Send("Possible destinations:`n\n\r");

	for (starsystem = first_starsystem; starsystem; starsystem = starsystem->next) {
	    count++;
	    ch->Send("%-12.12s%s",
		starsystem->name, !(count % 6) ? "\n\r" : " ");
	}
	if (!count)
	    ch->Send("No starsystems found.\n\r");
	return;
    }

    ship->currjump = starsystem_from_name(arg1);
    ship->jx = atoi(arg2);
    ship->jy = atoi(arg3);
    ship->jz = atoi(argument);

    if (ship->currjump == NULL) {
	ch->Send("`RYou can't seem to find that starsytem on your charts.`n\n\r");
	return;
    } else {
	starsystem = ship->currjump;

	if (starsystem->star1 && *starsystem->star1
	&& flabs(ship->jx - starsystem->s1x) < 300
	&& flabs(ship->jy - starsystem->s1y) < 300
	&& flabs(ship->jz - starsystem->s1z) < 300) {
	    echo_to_ship(TO_COCKPIT, ship, "`RWARNING.. Jump coordinates too close to stellar object.`n");
	    echo_to_ship(TO_COCKPIT, ship, "`RWARNING.. Hyperjump NOT set.`n");
	    ship->currjump = NULL;
	    return;
	}

	if (starsystem->star2 && *starsystem->star2
	&& flabs(ship->jx - starsystem->s2x) < 300
	&& flabs(ship->jy - starsystem->s2y) < 300
	&& flabs(ship->jz - starsystem->s2z) < 300) {
	    echo_to_ship(TO_COCKPIT, ship, "`RWARNING.. Jump coordinates too close to stellar object.`n");
	    echo_to_ship(TO_COCKPIT, ship, "`RWARNING.. Hyperjump NOT set.`n");
	    ship->currjump = NULL;
	    return;
	}

	for (planet = starsystem->first_planet; planet; planet = planet->next_in_system) {
	    if (flabs(ship->jx - planet->x) < 300
	    && flabs(ship->jy - planet->y) < 300
	    && flabs(ship->jz - planet->z) < 300) {
		echo_to_ship(TO_COCKPIT, ship, "`RWARNING.. Jump coordinates too close to stellar object.`n");
		echo_to_ship(TO_COCKPIT, ship, "`RWARNING.. Hyperjump NOT set.`n");
		ship->currjump = NULL;
		return;
	    }
	}

	ship->jx += number_range(-250, 250);
	ship->jy += number_range(-250, 250);
	ship->jz += number_range(-250, 250);
    }

    if (ship->starsystem == ship->currjump)
	ship->hyperdistance = number_range(0, 250);
    else
	ship->hyperdistance = number_range(500, 2000);

    ch->Send("`GHyperspace course set. Ready for the jump to lightspeed.`n\n\r");
    act("$n does some calculations using the ships computer.", ch, 0, 0, TO_ROOM);
    if (!NO_STAFF_HASSLE(ch))
	WAIT_STATE(ch, 2 * PULSE_VIOLENCE);
}

ACMD(do_hyperspace) {
    SHIP_DATA *ship;

    if ((ship = ship_from_pilotseat(IN_ROOM(ch))) == NULL) {
	ch->Send("`RYou must be in control of a ship to do that!`n\n\r");
	return;
    }

    if (ship->shipclass > SPACE_STATION) {
	ch->Send("`RThis isn't a spacecraft.`n\n\r");
	return;
    }

    if (autofly(ship)) {
	ch->Send("`RYou'll have to turn off the ships autopilot first.`n\n\r");
	return;
    }

    if (ship->shipclass == SPACE_STATION) {
	ch->Send("Space platforms can't move!\n\r");
	return;
    }

    if (ship->hyperspeed == 0) {
	ch->Send("`RThis ship is not equipped with a hyperdrive!`n\n\r");
	return;
    }

    switch (ship->shipstate) {
	case SHIP_HYPERSPACE:
	    ch->Send("`RYou are already travelling lightspeed!`n\n\r");
	    return;
	case SHIP_DISABLED:
	    ch->Send("`RThe ships drive is disabled. Unable to manuever.`n\n\r");
	    return;
	case SHIP_DOCKED:
	    ch->Send("`RYou can't do that until after you've launched!`n\n\r");
	    return;
	default:
	    break;
    }

    if (ship->shipstate != SHIP_READY) {
	ch->Send("`RPlease wait until the ship has finished its current manouver.`n\n\r");
	return;
    }

    if (ship->currjump == NULL) {
	ch->Send("`RYou need to calculate your jump first!`n\n\r");
	return;
    }

    if (ship->energy < (200 + ship->hyperdistance)) {
	ch->Send("`RThere is not enough fuel!`n\n\r");
	return;
    }

    if (ship->currspeed <= 0) {
	ch->Send("`RYou need to speed up first.`n\n\r");
	return;
    }

    echo_to_system(ship, NULL, "`Y%s disapears from your scanner.`n", ship->name);
    ship_from_starsystem(ship, ship->starsystem);
    ship->shipstate = SHIP_HYPERSPACE;
    ch->Send("`GYou push forward the hyperspeed lever.`n\n\r");
    act("$n pushes a lever forward on the control panel.", ch, 0, 0, TO_ROOM);
    echo_to_ship(TO_SHIP, ship, "`YThe ship lurches slightly as it makes the jump to lightspeed.`n");
    echo_to_ship(TO_COCKPIT, ship, "`YThe stars become streaks of light as you enter hyperspace.`n");

    ship->energy -= (100 + ship->hyperdistance);
    ship->vx = ship->jx;
    ship->vy = ship->jy;
    ship->vz = ship->jz;
}