/*

	Noctis galactic guide / FNDPLNT command.
	GOES Net Module.
	
	The purpose of this module is to find planets or moons which fit some characteristic. The characteristic is programmed in, so this gets modified every so often.
	
Module written by SL, with a good part of the code copied from other modules' source. (You can probably tell what's mine (or mostly so), since I use CamelCase for the names of functions I write)
	Note: FindSystems() is a modified version of isthere(): Instead of checking each system or planet to see if its ID matches one we're searching for, FindSystems calls CheckSystem for every system it finds. Note that CheckSystem can tell it to exit (if the user presses escape) - this is because it can be a long time between slices in FindSystems.

	Previous jobs of this module:
		1) Locate felisian planets or moons with fast rotation speeds. It looks for the fastest one it can find,
			with closeness to 0,0,0 being the second priority. Searching can take a long time, but it actually takes a lot less time when restricted to felisian planets. :)
		2) Find a system with 20 planets 
		3) Find planets or moons that are really frickin' far from the main star.

	Modified Feb 13 2005 by SL to fix possible bug due to use of align_m and align_e, now uses start_y and start_z instead.
	I haven't unified this yet with modshare.hpp.
*/

const double MAX_OBJECTS_PER_STAR = 80;

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <dos.h>
#include <io.h>
int CheckSystem ();
#define ISTHEREACTION if (CheckSystem()) return 1;
#include "modshare.hpp"

//////////////////////////////////////////////////////////////////////////////


long flat_rnd_seed;

void fast_srand (long seed) // selezione tabella pseudo.
			    // 4.294.967.295 tabelle possibili.
			    // (ca. 20000 elementi diversi per tabella)
{
	asm {
		or word ptr seed, 3
		db 0x66; mov ax, word ptr seed
		db 0x66; mov word ptr flat_rnd_seed, ax
	}
}

long fast_random (long mask) // estrazione di un numero: "mask" attiva i bits.
{
	long num;

	asm {
		db 0x66; mov ax, word ptr flat_rnd_seed
		db 0x66; mov dx, word ptr flat_rnd_seed
		db 0x66; mul dx
			 add al, dl
		db 0x66; add word ptr flat_rnd_seed, ax
		db 0x66; and ax, word ptr mask
		db 0x66; mov word ptr num, ax
	}

	return (num);
}

int ranged_fast_random (int range)
{
	if (range<=0) range = 1;
	return (fast_random(0x7FFF) % range);
}

float flandom ()
{ return ((float)random(32767) * 0.000030518); }

float fast_flandom ()
{ return ((float)fast_random(32767) * 0.000030518); }



char   *situation_file  = "..\\DATA\\Current.BIN";

char   sync               = 1;		// 0
char   anti_rad           = 1;          // 1
char   pl_search          = 0;          // 2
char   field_amplificator = 0;          // 3
char   ilight             = 63;         // 4
char   ilightv            = 1;          // 5
char   charge             = 3;          // 6
char   revcontrols        = 0;          // 7
char   ap_targetting      = 0;          // 8
char   ap_targetted       = 0;          // 9
char   ip_targetting      = 0;          // 10
char   ip_targetted       = -1;		// 11
char   ip_reaching        = 0;          // 12
char   ip_reached         = 0;          // 13
char   ap_target_spin     = 0;          // 14
char   ap_target_r        = 0;          // 15
char   ap_target_g        = 0;          // 16
char   ap_target_b        = 0;          // 17
char   nearstar_spin      = 0;          // 18
char   nearstar_r         = 0;          // 19
char   nearstar_g         = 0;          // 20
char   nearstar_b         = 0;          // 21
char   gburst	          = 0;          // 22
char   menusalwayson      = 1;		// 23
char   depolarize  	  = 0;          // 24
int    sys                = 4;		// 25
int    pwr                = 15000;	// 27
int    dev_page           = 0;		// 29
int    ap_target_class    = 0;		// 31
int    f_ray_elapsed	  = 0;		// 33
int    nearstar_class     = 0;		// 35
int    nearstar_nop       = 0;		// 37
float  pos_x              = 0;		// 39
float  pos_y              = 0;		// 43
float  pos_z              = -500;	// 47
float  user_alfa          = 0;		// 51
float  user_beta          = 0;		// 55
float  navigation_beta    = 0;		// 59
float  ap_target_ray      = 0;		// 63
float  nearstar_ray       = 1000;	// 67
double dzat_x             = +3797120;
double dzat_y             = -4352112;
double dzat_z             = -925018;
double ap_target_x        = 0;
double ap_target_y        = 1E9;
double ap_target_z        = 0;
double nearstar_x         = 0;
double nearstar_y         = 1E9;
double nearstar_z         = 0;
double helptime           = 0;
double ip_target_initial_d= 0;
double requested_approach_coefficient = 1;
double current_approach_coefficient = 1;
double reaction_time      = 0.01;
char   fcs_status[11]     = "STANDBY";
int    fcs_status_delay   = 0;
int    psys               = 4;
double ap_target_initial_d= 0;
double requested_vimana_coefficient = 1;
double current_vimana_coefficient = 1;
double vimana_reaction_time = 0.01;
char   lithium_collector  = 0;
char   autoscreenoff	  = 0;
char   ap_reached         = 0;
int    lifter		  = 0;
double secs		  = 0;

void unfreeze ()
{
	int fh = _open (situation_file, 0);
	if (fh>-1) {
		_read (fh, &sync, 244);
		_close (fh);
	}
}


double 	object_id = 12345;
char   	object_label[25];
double 	s_object_id = 12345;
char   	s_object_label[25];

double	subject_id = 12345;
double  idscale = 0.00001;

int	sts;
char	query;

long	round;
int 	i, fh, gh;
int 	analyzed_sectors_range;
char	*file = "..\\DATA\\STARMAP.BIN";
char    *comm = "..\\DATA\\COMM.BIN";

char	outbuffer[40];
char	textbuffer[40];
char	parbuffer[160];
char	nullbuffer[128];
char	objectname[21];
char	subjectname[21];
double s_m;

//////////////////////////////////////////////////////////////////////////////

const double deg = M_PI / 180;

#define qt_M_PI   4*M_PI/3

#define star_classes    12
#define planet_types    10
#define avgmoons        4
#define log2avgmoons	2
#define maxbodies	20 * avgmoons

char class_rgb[3*star_classes] = {
	63, 58, 40,
	30, 50, 63,
	63, 63, 63,
	63, 30, 20,
	63, 55, 32,
	32, 16, 10,
	32, 28, 24,
	10, 20, 63,
	63, 32, 16,
	48, 32, 63,
	40, 10, 10,
	00, 63, 63
};

int class_ray[star_classes] = { 5000, 15000, 300, 20000, 15000, 1000, 3000,
				2000, 4000, 1500, 30000, 250 };

int class_rayvar[star_classes] = { 2000, 10000, 200, 15000, 5000, 1000, 3000,
				   500, 5000, 10000, 1000, 10 };

int class_act[star_classes] = { 2, 4, 1, 6, 5, 10, 100, 1, 2, 1, 10, 1 };

char class_planets[star_classes] = { 12, 18, 8, 15, 20, 3, 0, 1, 7, 20, 2, 5 };

char   nearstar_p_type       [maxbodies];
int    nearstar_p_owner	     [maxbodies];
char   nearstar_p_moonid     [maxbodies];
double nearstar_p_ring       [maxbodies];
double nearstar_p_tilt       [maxbodies];
double nearstar_p_ray        [maxbodies];
double nearstar_p_orb_ray    [maxbodies];
double nearstar_p_orb_seed   [maxbodies];
double nearstar_p_orb_tilt   [maxbodies];
double nearstar_p_orb_orient [maxbodies];
double nearstar_p_orb_ecc    [maxbodies];

int planet_possiblemoons[] = { 1, 1, 2, 3, 2, 2, 18, 2, 3, 20, 20 };

const double planet_orb_scaling=  5.0;
const double avg_planet_sizing =  2.4;
const double moon_orb_scaling  = 12.8;
const double avg_moon_sizing   =  1.8;

double avg_planet_ray[] = { 0.007, 0.003, 0.010, 0.011, 0.010,
			    0.008, 0.064, 0.009, 0.012, 0.125,
			    2.000 };

double laststar_x, laststar_y, laststar_z, beststar_x, beststar_y, beststar_z;
int bestplanet=-1; int bestmoon=-1; int bestrotation=-1;
double bestdistance=-1;
float  zrandom (int range) { return (random(range) - random(range)); }
double nearstar_identity;
int    nearstar_nob;


void extract_ap_target_infos ()
{
	srand (ap_target_x/100000*ap_target_y/100000*ap_target_z/100000);

	ap_target_class = random (star_classes);
	ap_target_ray = ((float)class_ray[ap_target_class] + (float)random(class_rayvar[ap_target_class])) * 0.001;

	ap_target_r = class_rgb[3*ap_target_class+0];
	ap_target_g = class_rgb[3*ap_target_class+1];
	ap_target_b = class_rgb[3*ap_target_class+2];

	ap_target_spin = 0;
	if (ap_target_class==11) ap_target_spin = random (30) + 1;
	if (ap_target_class==7) ap_target_spin = random (12) + 1;
	if (ap_target_class==2) ap_target_spin = random (4) + 1;
}

double	      plx, ply, plz;



/* Calcola la posizione di un certo pianeta in orbita attorno ad una certa
   stella (quella vicina), sulla base dei parametri orbitali (inclinazione,
   eccentricit…, raggio ed orientamento dell'asse maggiore) e ritorna i
   valori in plx, ply, plz. */

double mox, moy, moz;
void   moonorigin (int n)
{
	double xx;
	double p_riv, ors;
	double alfa, beta;

	ors = nearstar_p_orb_ray[n] * nearstar_p_orb_ray[n];
	p_riv = sqrt (s_m / ors);

	beta = (secs * p_riv * M_PI) / 180;
	alfa = nearstar_p_orb_tilt[n] * deg;

	xx  = -nearstar_p_orb_ray[n] * sin(beta) * cos(alfa);
	moz =  nearstar_p_orb_ray[n] * cos(beta) * cos(alfa);
	moy =  nearstar_p_orb_ray[n] * sin(alfa);

	moz *= nearstar_p_orb_ecc[n];

	beta = nearstar_p_orb_orient[n];

	mox = xx * cos(beta) + moz * sin(beta);
	moz = moz * cos(beta) - xx * sin(beta);
}

void planet_xyz (int n)
{
	double xx;
	double alfa, beta;
	double p_m, p_riv, ors;

	ors = nearstar_p_orb_ray[n] * nearstar_p_orb_ray[n];

	if (nearstar_p_owner[n] > -1) {
		xx = nearstar_p_ray[nearstar_p_owner[n]];
		p_m = qt_M_PI * xx * xx * xx * 0.44e-4;
		p_riv = sqrt (p_m / ors);
	}
	else
		p_riv = sqrt (s_m / ors);

	beta = (secs * p_riv * M_PI) / 180;
	alfa = nearstar_p_orb_tilt[n] * deg;

	xx  = -nearstar_p_orb_ray[n] * sin(beta) * cos(alfa);
	plz =  nearstar_p_orb_ray[n] * cos(beta) * cos(alfa);
	ply =  nearstar_p_orb_ray[n] * sin(alfa);

	plz *= nearstar_p_orb_ecc[n];

	beta = nearstar_p_orb_orient[n];

	plx = xx * cos(beta) + plz * sin(beta);
	plz = plz * cos(beta) - xx * sin(beta);

	plx += nearstar_x;
	ply += nearstar_y;
	plz += nearstar_z;

	if (nearstar_p_owner[n] > -1) {
		moonorigin (nearstar_p_owner[n]);
		plx += mox;
		ply += moy;
		plz += moz;
	}
}

void prepare_nearstar ()
{
	int    n, c, q, r, s, t;
	double key_radius;

	nearstar_class = ap_target_class;
	nearstar_x = ap_target_x;
	nearstar_y = ap_target_y;
	nearstar_z = ap_target_z;
	nearstar_ray = ap_target_ray;
	nearstar_spin = ap_target_spin;
	nearstar_r = ap_target_r;
	nearstar_g = ap_target_g;
	nearstar_b = ap_target_b;

	s_m = qt_M_PI * nearstar_ray * nearstar_ray * nearstar_ray * 0.01e-7;
	
	nearstar_identity = nearstar_x/100000*nearstar_y/100000*nearstar_z/100000;

	srand ((long)nearstar_x%10000*(long)nearstar_y%10000*(long)nearstar_z%10000);

	nearstar_nop = random (class_planets[nearstar_class] + 1);

	for (n=0; n<nearstar_nop; n++) {
		nearstar_p_owner[n]	 = -1;
		nearstar_p_orb_orient[n] = (double) deg * (double) random (360);
		nearstar_p_orb_seed[n]   = 3 * (n*n+1) * nearstar_ray + (float) random (300 * nearstar_ray) / 100;
		nearstar_p_tilt[n]       = zrandom (10*nearstar_p_orb_seed[n]) / 500;
		nearstar_p_orb_tilt[n]   = zrandom (10*nearstar_p_orb_seed[n]) / 5000;
		nearstar_p_orb_ecc[n]    = 1 - (double) random (nearstar_p_orb_seed[n] + 10*fabs(nearstar_p_orb_tilt[n])) / 2000;
		nearstar_p_ray[n]        = (double) random (nearstar_p_orb_seed[n]) * 0.001 + 0.01;
		nearstar_p_ring[n]	 = zrandom (nearstar_p_ray[n]) * (1 + (double) random (1000) / 100);
		if (nearstar_class != 8)
			nearstar_p_type[n] = random (planet_types);
		else {
			if (random(2)) {
				nearstar_p_type[n] = 10;
				nearstar_p_orb_tilt[n] *= 100;
			}
			else
				nearstar_p_type[n] = random (planet_types);
		}
		if (nearstar_class==2||nearstar_class==7||nearstar_class==15)
			nearstar_p_orb_seed[n] *= 10;
	}

	if (!nearstar_class) {
		if (random(4)==2) nearstar_p_type[2] = 3;
		if (random(4)==2) nearstar_p_type[3] = 3;
		if (random(4)==2) nearstar_p_type[4] = 3;
	}

	for (n=0; n<nearstar_nop; n++) {
		switch (nearstar_class) {
			case 2: while (nearstar_p_type[n]==3)
					nearstar_p_type[n] = random (10);
				break;
			case 5: while (nearstar_p_type[n]==6||
				       nearstar_p_type[n]==9)
					nearstar_p_type[n] = random (10);
				break;
			case 7:	nearstar_p_type[n] = 9;
				break;
			case 9: while (nearstar_p_type[n]!=0&&
				       nearstar_p_type[n]!=6&&
				       nearstar_p_type[n]!=9)
					nearstar_p_type[n] = random (10);
				break;
			case 11:while (nearstar_p_type[n]!=1&&
				       nearstar_p_type[n]!=7)
					nearstar_p_type[n] = random (10);
		}
	}

	for (n=0; n<nearstar_nop; n++) {
		switch (nearstar_p_type[n]) {
			case 0:
				if (random(8))
					nearstar_p_type[n] ++;
				break;
			case 3:
				if ((n<2)||(n>6)||(nearstar_class&&random(4))) {
					if (random(2))
						nearstar_p_type[n]++;
					else
						nearstar_p_type[n]--;
				}
				break;
			case 7:
				if (n<7) {
					if (random(2))
						nearstar_p_type[n] --;
					else
						nearstar_p_type[n] -= 2;
				}
				break;
		}
	}

	nearstar_nob = nearstar_nop;

	if (nearstar_class==2||nearstar_class==7||nearstar_class==15)
		goto no_moons;

	for (n=0; n<nearstar_nop; n++) {
		// (t=) Numero di satelliti per pianeta.
		s = nearstar_p_type[n];
		if (n < 2) {
			t = 0;
			if (s == 10)
				t = random (3);
		}
		else
			t = random (planet_possiblemoons[s] + 1);
		if (nearstar_nob + t > maxbodies)
			t = maxbodies - nearstar_nob;
		for (c=0; c<t; c++) {
			q 			 = nearstar_nob + c;
			nearstar_p_owner[q]	 = n;
			nearstar_p_moonid[q]	 = c;
			nearstar_p_orb_orient[q] = (double) deg * (double) random (360);
			nearstar_p_orb_seed[q]   = (c*c+4) * nearstar_p_ray[n] + (float) zrandom (300 * nearstar_p_ray[n]) / 100;
			nearstar_p_tilt[q]       = zrandom (10*nearstar_p_orb_seed[q]) / 50;
			nearstar_p_orb_tilt[q]   = zrandom (10*nearstar_p_orb_seed[q]) / 500;
			nearstar_p_orb_ecc[q]    = 1 - (double) random (nearstar_p_orb_seed[q] + 10*fabs(nearstar_p_orb_tilt[q])) / 2000;
			nearstar_p_ray[q]        = (double) random (nearstar_p_orb_seed[n]) * 0.05 + 0.1;
			nearstar_p_ring[q]	 = 0;
			nearstar_p_type[q]       = random (planet_types);
			r = nearstar_p_type[q];
			if (r==9 && s != 10) r = 2;
			if (r==6 && s < 9) r = 5;
			if (n > 7 && random(c)) r = 7;
			if (n > 9 && random(c)) r = 7;
			if (r==2 || r==3 || r==4 || r==8) {
				if (s != 6 && s < 9)
					r = 1;
			}
			if (r==3 && s < 9) {
				if (n > 7)
					r = 7;
				if (nearstar_class && random(4))
					r = 5;
				if (nearstar_class == 2 ||
				    nearstar_class == 7 ||
				    nearstar_class == 11)
					r = 8;
			}
			if (r==7 && n <= 5) r = 1;
			if ((nearstar_class==2||nearstar_class==5||
			     nearstar_class==7||nearstar_class==11)
			     && random(n)) r = 7;
			nearstar_p_type[q] = r;
		}
		nearstar_nob += t;
	}

no_moons:
	key_radius = nearstar_ray * planet_orb_scaling;
	if (nearstar_class == 8) key_radius *= 2;
	if (nearstar_class == 2) key_radius *= 16;
	if (nearstar_class == 7) key_radius *= 18;
	if (nearstar_class == 11) key_radius *= 20;
	for (n=0; n<nearstar_nop; n++) {
		nearstar_p_ray[n] = avg_planet_ray[nearstar_p_type[n]]
				  + avg_planet_ray[nearstar_p_type[n]] * zrandom (100) / 200;
		nearstar_p_ray[n] *= avg_planet_sizing;
		nearstar_p_orb_ray[n] = key_radius + key_radius * zrandom (100) / 500;
		nearstar_p_orb_ray[n] += key_radius * avg_planet_ray[nearstar_p_type[n]];
		if (n < 8)
			key_radius += nearstar_p_orb_ray[n];
		else
			key_radius += 0.22 * nearstar_p_orb_ray[n];
	}

	n = nearstar_nop;
	while (n < nearstar_nob) {
		q = 0;
		c = nearstar_p_owner[n];
		key_radius = nearstar_p_ray[c] * moon_orb_scaling;
		while (n<nearstar_nob && nearstar_p_owner[n] == c) {
			nearstar_p_ray[n] = avg_planet_ray[nearstar_p_type[n]]
					  + avg_planet_ray[nearstar_p_type[n]] * zrandom (100) / 200;
			nearstar_p_ray[n] *= avg_moon_sizing;
			nearstar_p_orb_ray[n] = key_radius + key_radius * zrandom (100) / 250;
			nearstar_p_orb_ray[n] += key_radius * avg_planet_ray[nearstar_p_type[n]];
			if (q < 2) key_radius += nearstar_p_orb_ray[n];
			if (q >= 2 && q < 8) key_radius += 0.12 * nearstar_p_orb_ray[n];
			if (q >= 8) key_radius += 0.025 * nearstar_p_orb_ray[n];
			q++;
			n++;
		}
	}

	for (n = 0; n < nearstar_nop; n++) {
		nearstar_p_ring[n] = 0.75 * nearstar_p_ray[n] * (2 + random(3));
		s = nearstar_p_type[n];
		if (s != 6 && s != 9) {
			if (random(5))
				nearstar_p_ring[n] = 0;
		}
		else {
			if (random(2))
				nearstar_p_ring[n] = 0;
		}
	}
}

//////////////////////////////////////////////////////////////////////////////

int GetRotationPeriod(double seedval) {
	fast_srand (seedval + 4112);

	/* "rtperiod" Š il tempo, in secondi, che il pianeta impiega a
	   ruotare di un grado sul proprio asse. Il tempo impiegato per
	   una rotazione completa Š quindi, in secondi, 360 * rtperiod. */

	int rtperiod = 10 * (ranged_fast_random(50) + 1)
					+ 10 * ranged_fast_random(25)
					+ ranged_fast_random (250)
					+ 41;
	return rtperiod;
}

long numWorlds = 0;
long numApes[11];
				   
inline int modRandom(int size) {
	return (int)(((long)rand()%size));
}

long global_surface_seed_raw;
long best_gssr;

int CheckPlanet(int n, int type, int is_moon) {
	planet_xyz(n);
	double dx = nearstar_x - plx;
	double dy = nearstar_y - ply;
	double dz = nearstar_z - plz;
	double ddist = (dx*dx) + (dy*dy) + (dz*dz);
		
	//if ((type>=1 && type<=5) || type==7 || type==8) {
	/*if (type==3) {
		if (is_moon) {
			if (type) {
				return GetRotationPeriod (
					 1000000		*
					 nearstar_ray		*
					 type     *
					 orb_orient);
			}
			else {
				return GetRotationPeriod (
					 2000000 * n		*
					 nearstar_ray		*
					 orb_orient);
			}
		}
		else {
			if (type) {
				return GetRotationPeriod (
					 1000000		*
					 type     *
					 orb_seed *
					 orb_tilt *
					 orb_ecc  *
					 orb_orient);
			}
			else {
				return GetRotationPeriod (
					 2000000 * n		*
					 orb_seed *
					 orb_tilt *
					 orb_ecc  *
					 orb_orient);
			}
		}
	}*/
	
	return ddist;
}

long int systemsChecked = 0;
long int outofrangeSystems = 0;

int CheckSystem ()
{
	char warnbuffer[640];
	ap_target_x = foundstar_x;
	ap_target_y = foundstar_y;
	ap_target_z = foundstar_z;
	
	double dxx = sqrt (ap_target_x * ap_target_x + ap_target_z * ap_target_z);
	dxx += fabs(ap_target_y * 30);
	if (dxx > 2E9) {
		outofrangeSystems++;
		sprintf (warnbuffer, "CHECKED %li SYSTEMS, IGNORED %li OUTOFRANGE.", systemsChecked, outofrangeSystems);
		warnMsg (warnbuffer, 0);
		while (kbhit()) {
			if (getch() == 27) {
				return 1;
			}
		}
		return 0;
	}
	//warn("extract_ap_target_infos", -1);
	extract_ap_target_infos ();
	//warn("prepare_nearstar", -1);
	prepare_nearstar ();
	//warn("continuing", -1);
	
	if (nearstar_nob==0) return 0;
	long p1, p2, p3, p4;
	
	for (int n=0; n<nearstar_nob; n++) {
		int isMoon = (nearstar_p_owner[n]!=-1);
		int rotation = CheckPlanet(n, nearstar_p_type[n], isMoon);
		//if (rotation>0 && (rotation>bestrotation || bestrotation==-1 || (rotation==bestrotation && dxx<bestdistance))) {
		if (rotation>0 && (rotation>bestrotation || bestrotation==-1 || (rotation==bestrotation && dxx<bestdistance))) {
			bestrotation = rotation;
			beststar_x = nearstar_x;
			beststar_y = nearstar_y;
			beststar_z = nearstar_z;
			bestdistance = dxx;
			best_gssr=global_surface_seed_raw;
			/*p1 = bestrotation; p1 *= 360;
			p2 = p1 / 1000; p2 /= 1000;
			p3 = p1 / 1000; p3 %= 1000;
			p4 = p1 % 1000;*/
			//sprintf (warnbuffer, "BEST ROTATION TRIADS %03ld:%03ld:%03ld AT DISTANCE OF %lf", p2, p3, p4, dxx);
			//sprintf (warnbuffer, "BEST ROTATION TRIADS %03ld:%03ld:%03ld", p2, p3, p4);
			sprintf (warnbuffer, "BEST RESULT %i", bestrotation);
										
			memset(warnbuffer+strlen(warnbuffer), 32, 64-strlen(warnbuffer));
			warnbuffer[64]=0;
			warnMsg (warnbuffer, 2);
			sprintf (warnbuffer, "DISTANCE %8.3f", bestdistance);
			warnMsg (warnbuffer, 4);
			
			if (isMoon) {
				bestmoon = nearstar_p_moonid[n];
				bestplanet = nearstar_p_owner[n];
			} else {
				bestplanet=n;
				bestmoon=-1;
			}
			
		}
	}
	systemsChecked++;
	sprintf (warnbuffer, "CHECKED %li SYSTEMS, IGNORED %li OUTOFRANGE.", systemsChecked, outofrangeSystems);
	warnMsg (warnbuffer, 0);
	while (kbhit()) {
		if (getch() == 27) {
			return 1;
		}
	}
	return 0;
}

void FindSystems ()
{
	char warnbuffer[41];
	for (int a=0; a<11; a++) {
		numApes[a]=0;
	}
	
	isthere2(0, analyzed_sectors_range, 0, 0, 0, sts>10);
}

void main ()
{
	CHECK_SITUATION;
	long p1, p2, p3, p4;
	/*asm {	xor	ax, ax
		mov	es, ax
		cmp	byte ptr es:[0x449], 0x13
		je	startup }

	printf ("\nGalactic Organization of Explorers and Stardrifters (G.O.E.S)\n");
	printf ("-------------------------------------------------------------\n");
	printf ("This is a GOES NET module and must be run from a stardrifter.\n");
	printf ("Please use the onboard computer console to run this module.\n");
	printf ("\n\t- GOES NET onboard microsystem, EPOC 6011 REVISION 2\n");
	return;

	startup:*/
	msg ("LOOKING FOR TARGET...");
	msg (divider);
	
	i = 2;
	strcpy (parbuffer, _argv[1]);
	
	i = 0;
	while (parbuffer[i]) {
		if (parbuffer[i] == '_')
			parbuffer[i] = 32;
		i++;
	}
	if (i==0) {
		analyzed_sectors_range = 100;
	} else {
		sts = atoi (parbuffer);
		if (sts <= 2 || sts > 10000)
			analyzed_sectors_range = 100;
		else
			analyzed_sectors_range = sts;
	}
	unfreeze ();
	warnMsg ("SCANNING THE GALAXY: ESC TO STOP", -1);

	FindSystems ();
	int ch = _creat (comm, 0);
	if (ch > -1) {
		_write (ch, &beststar_x, 8);
		_write (ch, &beststar_y, 8);
		_write (ch, &beststar_z, 8);
		_close (ch);
		msg ("REM. TARGET DATA SENT");
		msg ("STARTING VIMANA DRIVE");
		char tmp[120];
		if (bestmoon>-1) {
			sprintf(tmp, "MOON %i/%i", bestmoon+1, bestplanet+1);
		} else {
			sprintf(tmp, "PLANET %i", bestplanet+1);
		}
		msg(tmp);
		sprintf(tmp, "BGSSR %li", best_gssr);
		msg(tmp);
		/*p1 = bestrotation; p1 *= 360;
		p2 = p1 / 1000; p2 /= 1000;
		p3 = p1 / 1000; p3 %= 1000;
		p4 = p1 % 1000;
		msg ("BEST ROTATION TRIADS");
		sprintf (tmp, "%03ld:%03ld:%03ld", p2, p3, p4);*/
		sprintf(tmp, "APECH %i", bestrotation); msg(tmp);
		sprintf(tmp, "WORLDS %li", numWorlds); msg(tmp);
		for (int a=0; a<11; a++) {
			sprintf(tmp, "NA[%i]=%li", a, numApes[a]); msg(tmp);
			sprintf(tmp, "NAP[%i]=%0.3f", a, 100.0*numApes[a]/numWorlds); msg(tmp);
		}
		
	}
	else
		msg ("COMMUNICATION ERROR.");

	_close (fh);
}