////////////////////////////////////////////////////////////////////
// JalTrek.js
////////////////////////////////////////////////////////////////////

// Jal Trek
// Copyright 2005 by James Larson. All rights reserved. 
// Programmer/Analyst Consultant
// http://www.dst-corp.com/james
// http://www.email-chess.com
// In God We Trust...
// Version History
// 1.00 -- 06Dec2005 -- Initial Release
// 1.01 -- 07Dec2005 -- changed "No Klingons in this sector" to "..quadrant"
//                      added = between ID name and { in <style>
//						Worked on the <style> block, adding "LinkC"
// 2.00 -- 07Jun2006 -- Minor fixes and support for Visitor counting

var Version = "2.00";
var TradeMarkNotice = "\
<small>\n\
<b>Star Trek</b>&copy; is a registered trademark of Paramount Pictures\n\
registered in the United States Patent and Trademark Office.\n\
</small>\n";

////////////////////////////////////////////////////////////////////
// Control Constants
////////////////////////////////////////////////////////////////////

// True when the user agent is...
var IsIE = navigator.appName == "Microsoft Internet Explorer";

// True when a game state is part of this page.
var IsGameState = (typeof GameDate == "string");

// True when this page's source is the Internet
var IsHTTP = (document.URL.toUpperCase().indexOf("HTTP://") == 0);

var Pi = 3.141592653589793;
var Pi2 = 2 * Pi;

////////////////////////////////////////////////////////////////////
// Common Display Constants 
////////////////////////////////////////////////////////////////////

var ColLets = 'ABCDEFGHIJ';	// Used to create quadrant & sector addresses
var RowNums = '0123456789';

////////////////////////////////////////////////////////////////////
// Sector Occupent Constants
////////////////////////////////////////////////////////////////////

var Star = 10;
var Starbase = 20;
var Klingon = 30;
var Enterprise = 40;

////////////////////////////////////////////////////////////////////
// Game Parameters
////////////////////////////////////////////////////////////////////

var MissionTurnsLo = 500;	// Lo and high range for total number of
var MissionTurnsHi = 530;	//   turns for this game.
var MissionBegin = 27340;	// Star Date of start of mission times ten 

var CaptainLogHead;			// Captain's log chain pointer Head
var CaptainLogTail;			//   & Tail
var CaptainLogCnt;			// Captain's log entry count
var MaxCaptainLog = 50;		// Maximum Captain's Log entries

var MaxShipEnergy = 3000;   // Maximum amount of energy ship can store
var EnergyPerTurn = 10;		// Energy used each turn

var MaxPhotonTorps = 12;	// Maximum Number of photon torpedoes

var MaxShieldEnergy = 600;	// Maximum Shield Energy budget

var StarsPerQuadrantLo = 3;	// Lo and high range of starts that can be 
var StarsPerQuadrantHi = 6;	//    Placed in a single quadrant

var StarbasesLo = 10;		// Lo and high range for number of starbases in
var StarbasesHi = 18;		//   game.

var KlingonsLo = 35;			// Lo and high range for total number of
var KlingonsHi = 39;		   	//   Klingons in a game.
var KlingonsPerQuadrantLo = 2;	// Lo and high range for number of Klingons
var KlingonsPerQuadrantHi = 4;	//   that can be placed in a quadrant.

var PhasorKillLo = 56;			// Lo and high range of Energy Units needed 
var PhasorKillHi = 145;			//   to kill Klingon with Phasor blast

var PhasorHiRange = 10;			// Probability percent 2nd range choosen
var PhasorKill2Lo = 145			// 2nd Lo and high range of Energy Units needed 
var PhasorKill2Hi = 245;		//   to kill Klingon with Phasor blast


////////////////////////////////////////////////////////////////////
// Game Working Storage
////////////////////////////////////////////////////////////////////

var GalactHistA = new Array();	// Galactic History Array

var GameStateVars = new Array ( // Scalar vars included in the Game State
	"CurrentQuadrant",			// Current location of Enterprise 
	"CurrentSector",			// Current location of Enterprise
	"PhotonTorps",				// Current number of photon torpedoes
	"ShipEnergy",				// Current amount of energy available to Commander
	"ShieldEnergy",				// Current Shield Energy budget 
	"StarCnt",					// Total stars in Galaxy
	"StarbaseCnt",				// Total Starbases in Galaxy
	"KlingonCnt",				// Number of Klingons left to destroy
	"StarTime",					// Current Star Time (Star date times ten)
	"MissionEnd",				// Deadline for success. (Star date times ten)
	"LastWarpIndex",			// Last Warp Factor Select Index
	"LastWarpDirIndex",			// Last Warp Direction Select Index
	"LastImpulseIndex",			// Last Impulse Distance Select Index
	"LastImpulseDirIndex",		// Last Impulse Direction Select Index 
	"LastPhotonDirIndex",		// Last Photon Torpedo Launch Direction
	"LastPhasorInput");			// Last Phasor Blast Input

var DefaultWarpIndex;			// Default Warp Factor Select Index
var	DefaultWarpDirIndex;		// Default Warp Direction Select Index
var	DefaultImpulseIndex;		// Default Impulse Distance Select Index
var	DefaultImpulseDirIndex;		// Default Impulse Direction Select Index 
var	DefaultPhotonDirIndex;		// Default Photon Torpedo Launch Direction
var	DefaultPhasorInput;			// Default Phasor Blast Input


////////////////////////////////////////////////////////////////////
// Ship Damage Variables
////////////////////////////////////////////////////////////////////

var DamageVars = new Array (	// Var names of Number turns system non-functional
	"WarpDriveDmg",		
	"ImpulseDriveDmg",	
	"PhotonTorpsDmg",	
	"PhasorDmg",			
	"ShortScanDmg",		
	"LongScanDmg",		
	"GalactHistDmg",		
	"ShieldDmg",			
	"LibraryComputerDmg");

////////////////////////////////////////////////////////////////////
// Ship Damage Constants
////////////////////////////////////////////////////////////////////

function DamageRec (Chance, DownLo, DownHi, Desc) {
	var o = new Object();
	o.Chance = Chance;	// Chance value of damage to system
	o.DownLo = DownLo;  // Lo and Hi range of turns system down when damaged
	o.DownHi = DownHi;
	o.Desc = Desc;		// System Description
	return o;
}

var DamageA = new Array (	// Array of Damage Info Records
	DamageRec (8, 10, 35, "Warp Drive"),		
	DamageRec (5, 10, 15, "Impulse Drive"), 
	DamageRec (8, 5,  20, "Photon Torpedoes"), 
	DamageRec (4, 6,  24, "Phasors"), 
	DamageRec (3, 12, 15, "Short Range Scan"), 
	DamageRec (6, 12, 25, "Long Range Scan"), 
	DamageRec (9, 11, 22, "Galactic History Report"), 
	DamageRec (2, 5,  15, "Shields"),			
	DamageRec (9, 4,  20, "Library Computer"));

function SumChances () { // Compute sum of changes of damage
	var i, s;
	for (i = s = 0; i < DamageA.length; i++) {
		s += DamageA [i].Chance;
	}
	return s;
}

var DamageChances = SumChances();
var ShieldHitLo = 30;		// Lo and Hi range of Energy hits on Enterprise Shield
var ShieldHitHi = 53;		//   as each Klingon in quadrant attacks.
var ShieldPierceProb = 3;	// % Probability Klingon attack pierces shield.
var PercentOfDown = 20;		// % of Down Days if shield pierced rather than just
							//   zero energy.

var GalaxyA = new Array();	// State of Galaxy (Stars, starbases, Klingons, etc.)
var DisplayQuadrant;		// State of current quadrant at last successful
							//   run of Short Range Scan

var SaveMode;				// Controls LoadSaveRecord()
var StateFormHTML;			// Form HTML created by LoadSaveRecord() in save mode

////////////////////////////////////////////////////////////////////
// List of all Image File Names
////////////////////////////////////////////////////////////////////

var ImageFileNamesA = new Array (
	"Space0.jpg", "Space1.jpg", "Space2.jpg", "Space3.jpg",
	"Enterprise.jpg", "Klingon.jpg", "Base.jpg", "Star.jpg",
	"Directions.jpg", "Pointer.jpg", "Spacer.jpg"
);

////////////////////////////////////////////////////////////////////
// Page Frame Variables
////////////////////////////////////////////////////////////////////

var LPane;					// Left Pane documet (Menu and commander input)
var LPaneW;					// Left Pane Window
var TRPane;					// Top Right Pane document (Command output)
var TRPaneW;				// Top Right Pane Window
var TRPaneMode;				// Top Right Pane now showing
var CurrentTRPane;			// Top Right Pane's HTML from last output
var BRPane;					// Bottom Right Pane document (Captain's Log)
var BRPaneW;				// Bottom Right Pane Window


////////////////////////////////////////////////////////////////////
// Help System Variables 
////////////////////////////////////////////////////////////////////

var HelpData = new Array ();	// Database of help topics	
var HelpIndex = new Array ();	// Translates help id strings to help object index	
var HelpHist = new Array();	// Remembers order in which help topics are visited
var HelpI = -1;				// Current entry in Help History array
var HelpE = -1;				// Last entry in Help History array
var HelpP = 0;				// Help topic pointer
var AtTop;					// Indicates where left pane is 

////////////////////////////////////////////////////////////////////
// Helper functions
////////////////////////////////////////////////////////////////////

function Rtrim (s) {
	var i;
	return (i = s.search(/\s+$/)) >= 0 ? s.substr (0, i) : s;
}

function Ltrim (s) {
	return s.search(/(^\s+)/) >= 0 ? s.substr (RegExp.$1.length) : s;
}


function INT(v) {
	return Math.floor(v);
}

function RND (m) {
	return INT(Math.random() * m) % m;
}

function Prob (p) {
	return RND(100) < p;
} 

function range (Lo, Hi) {
	return Lo + RND (Hi - Lo);
}

function Add2Int (s) {
	var c, r;
	s = Ltrim(Rtrim(s.toUpperCase()));
	if ((c = ColLets.search (s.substr(0,1))) < 0)
		return -1;
	return (r = RowNums.search (s.substr(1,1))) < 0 ? -1 : r * 10 + c;	
}


function max (a, b) {
	return a > b ? a : b;
}

function min (a, b) {
	return a < b ? a : b;
}

function Round (v, h) {
	return Math.round(v * h) / h; 
}


function WindowW (w) {
	return IsIE ? w.document.body.clientWidth  : w.innerWidth; 
}

function WindowH (w) {
	return IsIE ? w.document.body.clientHeight  : w.innerHeight
}

function WrPane (p, s) {
	p.open();
	p.write (s);
	p.close();
	return s;
}

////////////////////////////////////////////////////////////////////
// Save and Load Game State Logic
////////////////////////////////////////////////////////////////////

function GenGalactHistStr () {
	var i;
	for (i = 0, s = ""; i < 100; i++) {
		s += GalactHistA [i] + "Z";
	}
	return s;
}

function LoadGalactHistStr (GalStr) {
	var i, a = GalStr.match (/-*\d+Z/ig);
	for (i = 0; i < a.length; i++) {
		GalactHistA [i] = parseInt (a [i], 10);
	}
}

function GenGalaxyStr() {
	var i, j, s;
	for (i = 0, s = ""; i < 100; i++) {
		for (j = 0; j < 100; j++) {
			if (GalaxyA [i][j] >= Star)
				s += i + "Z" + j + "Z" + GalaxyA [i][j] + "Z"; 
		}
	}
	return s;
}

function LoadGalaxyStr (GalaxyStr) {
	RandomGalaxy();
	if (GalaxyStr == "")
		return;
	var i, j, k = 0;
	var a = GalaxyStr.match (/-*\d+Z/ig);
	while (k < a.length) {
		i = parseInt (a [k++],10);
		j = parseInt (a [k++],10);
		GalaxyA [i][j] = parseInt (a [k++],10);
	}
}

function GenCaptainLogStr () {
	var i, s, r, o;
	for (s = "", o = CaptainLogHead; o != null; o = o.Next) {
		for (r = "", i = 0; i < o.length; i++) {
			r += o [i] + "X";
		}
		s = r + "Y" + s;
	}
	return s;
}

function InitCaptainLog () {
	CaptainLogHead = CaptainLogTail = null; CaptainLogCnt = 0;
}

function LoadCaptainLogStr (LogStr) {
	var i, j, o, a = LogStr.match (/[^Y]*Y/ig);
	InitCaptainLog();
	if (LogStr == "")
		return;
	for (i = 0; i < a.length; i++) {
		b = a [i].match (/-*\d+X/ig);
		o = new Array();
		for (j = 0; j < b.length; j++) {
			o [j] = parseInt (b [j], 10);
		}
		if (CaptainLogTail == null)
			CaptainLogTail = o;
		o.Next = CaptainLogHead; CaptainLogHead = o;
		CaptainLogCnt++;
	}
}

function LoadGameState () {
	StateRecord (false); 
	TRPaneMode = ShortScanMsg;
	CurrentTRPane = GenShortScanHTML();
	OnPlayGame();
}

function Hinput (n, d) {
	return "<input type='hidden' name='" + n + "' value=\"" + d + "\">\n";
}

var GameSavePage = "\
<center><big>Save Game In Progress...</big></center>\n\
<p>The state of this game is being sent to a server to create a page\n\
you can save on your Hard Drive. It may open a new window or replace this one.\n\
When it finishes loading, you may save it or continue playing.</p>\n\
<form method='post' target='top' action='" + SaveActionHref + "'>\n";


function Today() {
	var d = new Date();
	return d.toLocaleString()
}

function StateItem (StateVar, SaveFunc, LoadFunc) {
	if (SaveMode) 
		StateFormHTML += Hinput (StateVar, SaveFunc());
	else
		LoadFunc (window [StateVar]);
}

function GenNumStr (VarNameA) {
	var i, s = "";
	for (i = 0; i < VarNameA.length; i++) {
		s += window [VarNameA [i]] + "Z";
	}
	return s;
}

function LoadNumVars (VarNameA, ValStr) {
	var i, a = ValStr.match (/-*\d+Z/ig);
	for (i = 0; i < VarNameA.length; i++) {
		 window [VarNameA [i]] = parseInt (a [i], 10);
	}
}

function StateItemA (StateVar, VarNameA) {
	if (SaveMode) 
		StateFormHTML += Hinput (StateVar, GenNumStr(VarNameA));
	else
		LoadNumVars (VarNameA, window [StateVar]);
}


function StateRecord (SaveMode_) {
	if (SaveMode = SaveMode_)
		StateFormHTML += Hinput ("PageHTML", PageHTML)
			+ Hinput ("GameDate", Today());
	StateItem  ("State0", GenGalaxyStr, LoadGalaxyStr);
	StateItem  ("State1", GenCaptainLogStr, LoadCaptainLogStr);
	StateItemA ("State2", GameStateVars);
	StateItemA ("State3", DamageVars);
	StateItem  ("State4", GenGalactHistStr, LoadGalactHistStr);
	if (SaveMode = SaveMode_) 
		StateFormHTML += Hinput ("SRC1", SRC1)
			+ Hinput ("SRC2", SRC2)
			+ Hinput ("SRC3", SRC3)
			+ Hinput ("SRC4", SRC4);
}


function GameStateHTML () {
	StateFormHTML = GameSavePage;
	StateRecord (true);
	return StateFormHTML + "</form>\n";
}

function OnSaveGame () {
	WrPane (TRPane, Head("parent.GameStateSubmit()") + GameStateHTML() + Tail);
}

function GameStateSubmit() {
	TRPane.forms[0].submit();
}


////////////////////////////////////////////////////////////////////
// Create the Known Galaxy
////////////////////////////////////////////////////////////////////

function ScanQuadrant (q) {
	var i, v;
	for (v = i = 0; i < 100; i++) {
		if (Star <= q [i] && q [i] < Enterprise) 
			v += Math.pow (10, INT (q [i] / 10) - 1);
	}
	return v;
}

function ClearDamage () {
	var i;
	for (i = 0; i < DamageVars.length; i++) {
		window [DamageVars [i]] = 0;
		window [DamageVars [i] + "I"] = i;
	}
}

function ClearAllGameStateVars () {
	var i;
	for (i = 0; i < GameStateVars.length; i++) {
		window [GameStateVars [i]] = 0;
		window [GameStateVars [i] + "I"] = i;
	}
}

function SetCurrent () {
	ClearDamage ();
	PhotonTorps = MaxPhotonTorps;
	ShipEnergy = MaxShipEnergy - ShieldEnergy;
}

function RandomGalaxy () {
	var i, j, o;
	for (i = 0; i < 100; i++) {
		GalactHistA [i] = 0;
		o = new Array();
		for (j = 0; j < 100; j++) {
			o [j] = RND(4);
		}
		GalaxyA [i] = o;
	}
}

function RandomStars() {
	var c, i, k, q;
	StarCnt = 0;
	for (i = 0; i < 100; i++) {
		q = GalaxyA [i];
		c = range (StarsPerQuadrantLo, StarsPerQuadrantHi);
		StarCnt += c;
		while (c-- > 0) {
			while (q [k = RND (100)] >= Star) 
				;
			q [k] += Star;
		}
	}
}

function RandomStarbases() {
	StarbaseCnt = range (StarbasesLo, StarbasesHi);
	var q, i, r, a = new Array();
	for (i = 0; i < StarbaseCnt; i++) {
		while (a [r = RND (100)])
			;
		q = GalaxyA [r]; a [r] = true;
		while (q [r = RND (100)] >= Star)
			;
		q [r] += Starbase;
	}
}

function RandomKlingons() {
	var a, i, j, k, q, r;
	a = new Array ();
	KlingonCnt = range (KlingonsLo, KlingonsHi);
	for (i = 0;;) {
		while (a [r = RND(100)])
			;
		q = GalaxyA [r]; a [r] = true;
		j = range (KlingonsPerQuadrantLo, KlingonsPerQuadrantHi);
		while (j--) {
			while (q [r = RND(100)] >= Star)
				;
			q [r] += Klingon; 
			if (++i >= KlingonCnt)
				return;
		}
	}
}

function RandomEnterprise () {
	var q = GalaxyA [CurrentQuadrant = RND(100)];
	while (q [CurrentSector = RND (100)] >= Star)
		;
	q [CurrentSector] += Enterprise;
}

function OnNewGame () {
	ClearAllGameStateVars ();
	RandomGalaxy();
	RandomStars ();
	RandomStarbases ();
	RandomKlingons ();
	RandomEnterprise();
	MissionEnd = (StarTime = MissionBegin) + range (MissionTurnsLo, MissionTurnsHi);
	InitCaptainLog();
	SetCurrent();
	AddCaptainLog (NewGameMsg, StarCnt, KlingonCnt, MissionEnd - StarTime,
		StarbaseCnt, CurrentQuadrant, CurrentSector);
	TRPaneMode = ShortScanMsg;
	CurrentTRPane = GenShortScanHTML();
	OnHelp (-1);
	ShowCaptainLog();
}

////////////////////////////////////////////////////////////////////
// Menu Routines
////////////////////////////////////////////////////////////////////

function Head (s, bc) {
	s = s ? " onload='pp." + s + "'" : "";
	bc = bc ? " bgcolor='" + bc + "'" : "";
	return "<html><head><title>Output</title>\n"
		+ "<style type='text/css'>\n"
		+ (IsIE ? ".HandC {cursor: hand;}\n" : "")
		+ ".LinkC {cursor: hand; cursor: pointer;}\n"
		+ ".FloatImg {float: left;}\n"
		+ "</style>\n"
		+ "</head>\n<body" + bc + s + ">\n"
		+ "<script>var pp = parent;<"+"/script>\n";
}

var Tail = "</body></html>\n";

var MenuHTML = "\
<center><big><big><b>Jal Trek</b></big></big><br>\n\
<small>Version "+Version+"</small></center>\n\
<table align='center' border='1' BGCOLOR='black'>\n\
<tr><th bgcolor='yellow'>Command Menu\n";

var HelpMenuHTML = "\
<center><big><big><b>Jal Trek</b></big></big><br>\n\
<small>Version "+Version+"</small></center>\n\
<table align='center' cellpadding='2' border='1' BGCOLOR='black'>\n\
<tr><th bgcolor='yellow' colspan='2'>Help Menu</th>\n";
 

function MenuItem (fn, label, i) {
	fn = "onclick='pp." + fn + "(" + i + ")'";
	return (IsIE 
		? "<th bgcolor='#BFBFBF' class='HandC' " + fn + ">" + label + "</th>\n"
		: "<th><input type='button' value='" + label + "' " + fn + "></th>\n");
} 


function AddHelpItem (s) {
	HelpIndex [s.toUpperCase()] = HelpData.length
}

function HelpObj (cmd, fn, desc) {
	var i = HelpData.length, o = new Object();
	o.cmd = cmd; o.fn = fn; o.desc = desc;
	if (fn)
		MenuHTML += "<tr>"+MenuItem (fn, cmd, i);
	HelpMenuHTML += "<tr><td bgcolor='white'><img name='P' width='20' "
		+ "height='20' onclick='pp.GenHelpHTML(" + i + ")'></img></td>"
		+ MenuItem ("GenHelpHTML", cmd, HelpData.length);
	AddHelpItem (cmd);
	HelpData [i] = o;
}	

function HL (s) {
	return "<b><u><span class='LinkC' onclick='pp.FindHelpLink(\""+s+"\")'>"
		+ s + "</span></u></b>";
}

function FindHelpLink (s) {
	s = s.toUpperCase();
	if (typeof HelpIndex [s] == "number")
		return GenHelpHTML (HelpIndex [s]);
	return -1;
}

function Himg (n) {
	return "<img src='" + ImgBase + n + "'></img>";
}

var LoadGameHTML = "<big>" + (IsGameState 
	? (IsHTTP 
		? "To save this page for later play, click on "
			+ "<font color='blue'><b>File</b></font> then "
			+ "<font color='blue'><b>Save As</b></font>. "
			+ "Be sure to save it as type HTML.<br><br>" 
		: "")
		+ "This page contains a game paused on " + GameDate
		+ ". You may resume this game or play a new one. "
	: "This page has no game state to resume.")
	+ "</big><br><br>\n<center>"
	+ Button (IsGameState, "Resume Game", "LoadGameState()")
	+ "</center>";

function ShowLoadGameHTML (HelpI) {
	WrPane (TRPane, Head() + LoadGameHTML + Tail);
}

var NewGameHTML = "\
To restart the game by randomizing the number and placement \
of "+HL("stars")+", "+HL("Klingons")+", "+HL("Starbases")
+ " and the location of the "+HL("Enterprise")
+", click on the button below.<br><br>\n<center>"
+ Button (true, "New Game", "OnNewGame()")
+ "</center>";

function ShowNewGameHTML (HelpI) {
	WrPane (TRPane, Head() + NewGameHTML + Tail);
} 

var SaveGameHTML = "\
To save your game state for play at a later time, click on the button \n\
below. It will send the state to a server which will create a custom \n\
page with the game state in it. Save the new page as an HTML file \n\
to your local Hard Drive. Then, when you want to restart it, \n\
reload the saved page into your browser from your Hard Drive.<br><br>\n<center>"
+ Button (true, "Save Game", "OnSaveGame()")
+ "</center>";


function ShowSaveGameHTML (HelpI) {
	WrPane (TRPane, Head() + SaveGameHTML + Tail);
}

var DirImg = "\
<table border='1' BGCOLOR='black' class='FloatImg'><tr><td>"
+Himg("Directions.jpg")+"</table>\n"; 


////////////////////////////////////////////////////////////////////
// Build Help Database
////////////////////////////////////////////////////////////////////

HelpObj ("Introduction", 0, "\
<table border=1><tr><td>You are Visitor # " + Visitor + "</table>\n\
Welcome to Jal Trek. This simulation is a version of the venerable computer\n\
game classic, Star Trek, which has been coded by many programmers for\n\
just about every imaginable computer system. This version is loosely based on\n\
STRR1, which could be found on most HP2000C time shared computer systems circa \n\
1972.<br><br>Live long and prosper!<br><br>\n"
+ TradeMarkNotice
+ "<br><br>James Larson<br>Programmer/Analyst Consultant<br>\n\
<a href='http://www.dst-corp.com/james'>http://www.dst-corp.com/james</a><br>\n\
<a href='http://www.email-chess.com'>http://www.email-chess.com</a><br>\n\
In God We Trust...\n");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

AddHelpItem ("mission");
HelpObj ("The Mission", 0, "\
Greatings, Captain! Welcome to the "+HL("Starship") + " " + HL("Enterprise")
+ ". Your mission is to rid " + HL("The Galaxy") + " of the dreaded "
+ HL("Klingon") + " menace. They threaten Earth's domination\n\
of the galaxy and must be ruthlessly destroyed -- before <b>they</b> destroy you!\n");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

AddHelpItem ("enterprise");
AddHelpItem ("starship");
AddHelpItem ("federation");
HelpObj ("Your Ship", 0, 
Himg ('Enterprise.jpg')+" To allow you to accomplish your "+HL("mission")+",\n\
you are in command of the greatest Starship ever launched by the Federation.\n\
The menu of buttons on the left will allow you to communicate with the ship \n\
through the Computer, which will in turn keep you posted on the progress of the\n\
mission, as well as the operational status of your ship.\n");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

AddHelpItem ("quadrant");
AddHelpItem ("quadrants");
AddHelpItem ("sector");
AddHelpItem ("sectors");
AddHelpItem ("galaxy");
AddHelpItem ("space");
HelpObj ("The Galaxy", 0, "\
The known galaxy is divided up into <b>10 x 10</b> quadrants\n\
which in turn are divided up into <b>10 x 10</b> sectors. \n\
Each quadrant and sector is\n\
addressed by a column letter <b>A</b> through <b>J</b>\n\
and row digit <b>0</b> through <b>9</b>.\n");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

AddHelpItem ("date");
AddHelpItem ("Star Date");
HelpObj ("Star Dates", 0, "\
You have a limited number of <b>Star Dates</b> to complete this important\n\
mission. Each Star Date represents <b>10</b> turns.\n\
Each use of the "+HL("Warp Drive")+" consumes <b>10</b> turns, so use it wisely.\n");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

AddHelpItem ("energy");
AddHelpItem ("power");
HelpObj ("Ship Energy", 0, "\
Another limited resource is <b>Ship Energy</b>. Each "
+ HL("Star Date") + " the " 
+ HL("Enterprise") + " is on its mission, \n<b>"
+ (EnergyPerTurn * 10)+"</b> Energy Units are consumed, or \n<b>" 
+ EnergyPerTurn + "</b> per turn. You can take on at most <b>"
+ MaxShipEnergy + " Units</b> from " 
+ HL("Starbases") + " when you dock. The "
+ HL("Phasors") + " use up the energy input for the blast, and the\n"
+ HL("Shields")+" consume energy during enemy attacks.<br><br>\n\
Be warned! If you run out of energy before your "
+ HL("mission") + " is complete, you will have failed your duty,\n\
and will drift around, lost in "
+ HL("space") + ", until you and your crew run out of oxygen and perish!");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

AddHelpItem ("klingon");
HelpObj ("Klingons", 0,
Himg ('Klingon.jpg')+" Your mortal enemy! Seek them out and annihilate them!\n");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HelpObj ("Starbases", 0,
Himg ('Base.jpg') + " To assist you in your "
+ HL("mission") + ", the "
+ HL("Federation") + " has gone to horrendous expense to establish starbases\n\
throughout the known "
+ HL("galaxy") + ". You may dock with them to replenish and repair your ship.\n\
To achieve docking status, merely navigate the "
+ HL("Enterprise") + " to the "
+ HL("sector") + " next to a base.");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HelpObj ("Stars", 0, 
Himg ('Star.jpg')+" These tend to get in your way. If they do, feel free to\n\
obliterate them with your "
+ HL("Photon Torpedoes")+".");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HelpObj ("Warp Drive", "OnWarpDrive", "\
Warp Drive allows the "
+ HL("Enterprise")+" to travel faster than light to any\n"
+ HL("quadrant")+" in the known "
+ HL("galaxy")+". To move within the current "
+ HL("quadrant") + ", use the "
+ HL("Impulse Drive")+". When this command is issued,\n\
you will need to input a direction and distance value.\n"
+ DirImg + "Direction values are a fractional number from 0 to 7.9, just like\n"
+ HL("Impulse Drive")+", and "
+ HL("Photon Torpedoes") + " Distances are measured in "
+ HL("quadrants") + ". Each use of the Warp Drive will consume one "
+ HL("Star Date") + " The Warp Drive can be damaged by enemy action,\n\
which will prevent it from being used more than <b>2</b> "
+ HL("quadrants")+" at a time. See \n"
+ HL("Damage Report")+" for more details.");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HelpObj ("Impulse Drive", "OnImpulse", "\
Impulse Drive allows the "
+ HL("Enterprise")+" to manuever within its current\n"
+ HL("quadrant")+". To move to another "
+ HL("quadrant")+", use the "
+ HL("Warp Drive") + ". Impulse Drive consumes one turn per sector traveled.\n\
You cannot travel through "
+ HL("stars")+", "
+ HL("bases")+" or "
+ HL("Klingons") + ". You will be asked to specify a direction and distance.\n\
Distances are measured in "
+ HL("sectors") + DirImg + ". Direction values are a fractional number from 0 to 7.9\n\
, just like " 
+ HL("Warp Drive")+", and "
+ HL("Photon Torpedoes")+ "The Impulse Drive can be damaged by enemy action, \n\
which will prevent it from being used more than <b>2</b> "
+ HL("sectors")+" at a time. See \n"
+ HL("Damage Report")+" for more details.");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

AddHelpItem ("photon torpedoe");
HelpObj ("Photon Torpedoes", "OnPhotonTorp", "\
This device is based on anti-matter explosives. It cancels all matter within\n\
an entire "
+ HL("sector")+"! This includes "
+ HL("stars") + "! Pretty potent stuff. The "
+ HL("Enterprise")+" carries <b>"+MaxPhotonTorps+"</b> maximum at any one time.\n\
However, they are replenished upon docking with "
+ HL("Starbases") + DirImg + ". Direction values are a fractional \n\
number from 0 to 7.9, just as with the\n"
+ HL("Warp Drive")+", and "
+ HL("Impulse Drive"));

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HelpObj ("Library Computer", 0, "\
To assist in computing directions and distances, the <b>Library Computer</b>\n\
is available. To access it, merely click on an empty "
+ HL("sector")+" on the\n"
+ HL("Short Range Scan")+" and the distance and direction will be computed \n\
and entered in the <b>Commander Input</b> panel of the "
+ HL("Impulse Drive") + ". Clicking on a "
+ HL("star")+", "
+ HL("Klingon")+", or even a "
+ HL("Starbase") +" will enter the distance in the <b>Commander Input</b>\n\
panel of the "
+ HL("Photon Torpedoe")+" fire control system. Finaly, clicking on\n\
any sector in either the "
+ HL("Long Range Scan")+" or "
+ HL("Galactic History")
+ " report will cause the direction and distance to be computed and entered in the\n"
+ HL("Warp Drive")+ " <b>Commander Input</b> panel, ready to engage. If the\n\
<b>Library Computer</b> is damaged by enemy action, you will not be able to use it\n\
until repaired or the next docking with a "+HL("Starbase")+".");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

AddHelpItem ("phasors");
HelpObj ("Fire Phasors","OnPhasors", "\
Upon activation, you will be required to input the number of "
+ HL("energy") + " units to expend. Once firing commences, it is entirely\n\
controled by the Computer. The Computer will divide this energy evenly\n\
among all the\n"
+ HL("Klingons") + " in the current "
+ HL("quadrant") + ". If it is greater than the Klingon's shield energy,\n\
it will be destroyed.");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HelpObj ("Short Range Scan", "OnShortScan", "\
This is the primary way of navigating within a "
+ HL("quadrant")+" and finding the "
+ HL("Klingon") + " ships.\n\
It will provide you with valuable status information, and the location of enemy\n\
targets. It will also show where "+HL("Starbases")+" are.");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

AddHelpItem ("long range scans");
HelpObj ("Long Range Scan", "OnLongScan", "\
This device allows you to check neighboring "
+ HL("quadrants")+" for the enemy and "
+ HL("Starbases")+".\nIt will provide a count of "
+ HL("Klingons")+", Starbases, and "
+ HL("stars")+ ". The results of each scan are stored for later reference in the "
+ HL("Galactic History")+" report. Each time you enter a quadrant, execute the\n\
<b>Long Range Scan</b> to see what the 8 surrounding quadrants hold to build\n\
a map of the known "
+ HL("Galaxy")+".");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HelpObj ("Galactic History", "OnGalacHist", "\
This is the cummulative repository of all past "
+ HL("Long Range Scans") + " you perform. You may consult it anytime during your\n"
+ HL("mission")+" to recall where you found "
+ HL("Starbases")+" and "
+ HL("Klingons")+".\nAs Klingons are destroyed, it's database will be updated.");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HelpObj ("Damage Report", "OnDamageRep", "\
All ship systems are subject to failure as a result of enemy action. \n\
When damaged, they will no longer function until repaired. Repair time \n\
is measured in " + HL("Star Dates") + ", or fractions thereof. Docking with\n"
+ HL("Starbases") + " will cause all repairs to be completed immediately, as\n\
the crew of Starbases are particularly adept at repairing damage.");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

AddHelpItem ("shields");
HelpObj ("Set Shield Energy", "OnSetShields", "\
Shields protect you, "
+ HL("your ship")+", and your crew from merciless "
+ HL("Klingon") + " attacks.\nThis command allows you to establish an "
+ HL("energy") + " budget of up to <b>"+MaxShieldEnergy
+ " Energy Units</b>. As Klingons attack you, this energy will be depleted.\n\
As long as your shields have energy, your ship will be protected from most\n\
damage, but violent assaults can still disrupt things sufficiently to cause\n\
minor glitches. Consult the " 
+ HL("Damage Report")+" when things go wrong.");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HelpObj ("Help", "OnHelp", "\
Clicking on the <b>Help</b> pad will display the help menu. Then click on the \n\
subject pad of interest for more information. You may also click on the \n\
<b>Next</b> and <b>Previous</b> pads to move through the help topics.\n\
As you visit these topics, an entry is made in a history list. Click on \n\
<b>Back</b> and <b>Forward</b> to move through this list.");

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HelpObj ("New Game", "ShowNewGameHTML", NewGameHTML);

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HelpObj ("Save Game", "ShowSaveGameHTML", SaveGameHTML);

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HelpObj ("Load Game", "ShowLoadGameHTML", LoadGameHTML);

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HelpObj ("Play Game", 0, "\
Are you ready to begin the "
+ HL("Mission")+ "? If so, please click on the button <b>Play Game</b> above.\n");

MenuHTML += "</table>\n";
HelpMenuHTML += "</table>\n";

////////////////////////////////////////////////////////////////////
// Help Routines
////////////////////////////////////////////////////////////////////

function Button (Cond, label, onclick) {
	return (IsIE || ! Cond 
		?  "<table border='1' BGCOLOR='black' class='HandC'><tr>"
			+ "<th class='HandC'" 
				+ (Cond ? " bgcolor='#BFBFBF' onclick='pp."+onclick+"'" 
						: " bgcolor='white'") + ">" 
			+ label + "</th></tr></table>"
		: "<input type='button' value='"+ label +"' onclick='pp." + onclick + "'>")
	+ "\n "
}

function OnBFButton (i) {
	GenHelpHTML (HelpHist [HelpI += i], true);
}


function ScrollIntoView (n) {
	var Half = LPane.P.length / 2;
//	var PosY = LPane.P.length * 40;
	if (AtTop && n > Half) {
		AtTop = false; LPaneW.scrollTo (0, WindowH (LPaneW));
	}
	if (!AtTop && n < Half) {
		AtTop = true; LPaneW.scrollTo (0, 0);
	}
}

function GenHelpHTML (i, BF) {
	var Td = "<td width='20%' align='center'>";
	ScrollIntoView(i);
	LPane.P[HelpP].src = ImgBase + 'Spacer.jpg';
	LPane.P[HelpP = i].src = ImgBase + 'Pointer.jpg';
	if (!BF) {
		HelpHist [++HelpI] = i;
		HelpE = HelpI;
	}
	var hd = HelpData[i];
	var h = "<table cellpadding=2 width='100%' border='1'><tr><td>\n"
		+ "<table width='100%'  bgcolor='lightblue' cols=3><tr>\n"
		+ Td + Button (i > 0, "Previous", "GenHelpHTML("+(i-1)+")")
		+ Td + Button (HelpI > 0, "Back", "OnBFButton(-1)")
		+ Td + Button (true, "Play Game", "OnPlayGame()") 
		+ Td + Button (HelpI < HelpE, "Forward", "OnBFButton(1)")
		+ Td + Button (i < HelpData.length - 1,	"Next", "GenHelpHTML("+(i+1)+")")
		+ "</table>\n"
		+ "<tr><td align='center' bgcolor='yellow'>" 
			+(hd.fn?"Command -- ":"") + "<b>" + hd.cmd
		+ "</b><tr><td>" + hd.desc + "</table>\n";
	WrPane (TRPane, Head() + h + Tail);
}


function ObjectName (i) {
	switch (INT(i / 10) * 10) {
		case Star : return "Star";
		case Starbase : return "Starbase";
		case Enterprise : return "Enterprise";
		case Klingon : return "Klingon";
	}
	return "&nbsp;";
}

function HelpOnLoad () {
	var i;
	for (i = 0; i < LPane.P.length; i++) {
		LPane.P [i].src = ImgBase + 'Spacer.jpg';
	}
}

function FrameOnLoad () {
	LPane = (LPaneW = window.frames[0]).document;
	TRPane = (TRPaneW = window.frames[1]).document;
	BRPane = (BRPaneW = window.frames[2]).document;
	OnNewGame ();
}

////////////////////////////////////////////////////////////////////
// Captain's Log Routines
////////////////////////////////////////////////////////////////////

var PhasorBlastMsg = 0;
var PhasorNoKlingonsMsg = 1;
var PhasorNoKillMsg = 2;
var PhasorKillMsg = 3;
var ShortScanMsg = 4;
var LongScanMsg = 5;
var GalacHistMsg = 6;
var DamageReportMsg = 7;
var SetShieldMsg = 8;
var NewGameMsg = 9;
var StillDamagedMsg = 10;
var DamageFixedMsg = 11;
var DamageMsg = 12;
var OutOfTimeMsg = 13;
var OutOfEnergyMsg = 14;
var PlayerWinsMsg = 15;
var DistanceReachedMsg = 16;
var CollisionDetectedMsg = 18;
var TargetHitMsg = 19;
var QuadrantEdgeMsg = 20;
var PhotonLostMsg = 21;
var GalaxyEdgeMsg = 22;
var NewQuadrantMsg = 24;
var BaseDestroyedMsg = 25;
var LibraryComputerDmgMsg = 26;
var ShieldPiercedMsg = 27;
var ShieldDownMsg = 28;
var KlingonsLeftMsg = 29;
var ShieldsLeftMsg = 30;
var StarbaseHereMsg = 31;
var KlingonLocationMsg = 32;

var LogQuadrant;		// Quadrant being output 
var LogDate;			// Star Date now being output

function LogText (lo) {
	var i, o, rows, s = "<tr>";
	if (LogDate != lo[0]) {
		LogDate = lo[0];
		for (o = lo, rows = 0; o != null && LogDate == o[0]; o = o.Next) {
			rows++;
		}
		s +="<td rowspan='"+rows+"' bgcolor='white'>" + (lo[0]/10);
	}
	s += "<td bgcolor='white'>";
	switch (lo [1]) {
		case PhasorBlastMsg :
			return s + "Phasor attack against <b>" 
				+ lo[3] + "</b> Klingons commences in quadrant <b>" 
				+ LetNum(lo[2]) + "</b>.";
		case PhasorNoKlingonsMsg :
			return s + "Attempt to shoot Phasors with no targets in quadrant <b>"
				+ lo[2] + "</b>.";
		case PhasorNoKillMsg :
			return s + "Attempt to kill Klingon at sector <b>" 
				+ LetNum(lo [2]) + "</b> failed because it required <b>" 
				+ lo[3] + "</b> energy units when only <b>" 
				+ lo[4] + "</b> was used.";
		case PhasorKillMsg :
			return s + "Klingon at sector <b>" 
				+ LetNum(lo [2]) + "</b> destroyed with <b>" 
				+ lo[4] + "</b> energy units even when only <b>" 
				+ lo[3] + "</b> were needed. <b>";
		case SetShieldMsg: 
			return s + "Shield energy changed from " 
				+ lo[2] + " to <b>" 
				+ lo[3] + "</b>"; 
		case NewGameMsg : 
			return s + "New game began. Stars=" 
				+ lo[2] + "; Klingons=" 
				+ lo[3] + "; Turns=" 
				+ lo[4] + "; Starbases=" 
				+ lo[5] + "; Enterprise @ "
				+ LetNum(lo[6]) + ", "
				+ LetNum(lo[7]);
		case StillDamagedMsg : 
			return s + "Sorry, Captain, but the <b>"
				+ DamageA [lo[2]].Desc 
				+ "</b> is still damaged. It is expected to be down for <b>"
				+ (lo [3]/10) + "</b> more star days.";
		case DamageFixedMsg :
			return s + "Captain, Engineering reports that <b>"
				+ DamageA [lo [2]].Desc + "</b> has been returned to <b>"
				+ "Operational Status.</b>";
		case DamageMsg :
			return s + "Captain! Engineering reports that <b>"
				+ DamageA [lo [2]].Desc + "</b> has been damaged for <b>"
				+ (lo [3]/10) + "</b> star days!";
		case OutOfTimeMsg : 
			return s + "Your time is up! The deadline, <b>" + 
				+ (lo [2] / 10) + "</b> is reached! There are still <b>"
				+ lo[3] + "</b> Klingons loose in the Galaxy.";
		case OutOfEnergyMsg :
			return s + "Your ship has run out of energy, leaving you to drift "
			    + "to your inevitable demise, and there are still <b>"
				+ lo[3] + "</b> Klingons still loose in the Galaxy!";
		case PlayerWinsMsg :
			return s + "You have accomplished your mission with <b>"
				+ (lo[2]/10) + "</b> Star Dates left on the clock.";
		case DistanceReachedMsg :
			return s + "Enterprise has traveled to sector "
				+ LetNum(lo[2]);
		case CollisionDetectedMsg :
			return s + "Enterprise has collided with celestial object! "
				+ "Stopped at sector "
				+ LetNum(lo[2]);
		case QuadrantEdgeMsg :
			LogQuadrant = lo [2];
			return s + "Enterprise has reached the edge of the quadrant "
				+ "and has pulled back to "+LetNum(lo[2]);
		case GalaxyEdgeMsg :
			LogQuadrant = lo [2];
			return s + "Enterprise almost exited the known galaxy! "
				+ " It is now located at Quadrant <b>" 
				+ LetNum(lo[2]) + "</b> Sector <b>" 
				+ LetNum(lo[3]) + "</b>";
		case NewQuadrantMsg :
			LogQuadrant = lo [2];
			return s + "Enterprise has warped to Quadrant <b>" 
				+ LetNum(lo[2]) + "</b> Sector <b>" 
				+ LetNum(lo[3]) + "</b>";
		case TargetHitMsg :
			return s + "Photon Torpedo has destroyed a "
				+ ObjectName(lo [3]) + " at Sector <b>" 
				+ LetNum(lo[2]) + "</b>";
		case PhotonLostMsg :
			return s + "Photon Torpedo has self destructed at the "
				+ "edge of the quadrant at sector <b>"
				+ LetNum(lo[2])+"</b>.";
		case BaseDestroyedMsg :
			return s + "Moron! Youv'e gone and destroyed a Starbase! "
				+ "That leaves only <b>"
				+ lo[2]+"</b> left! They won't like this back at Star Fleet Command!";
		case LibraryComputerDmgMsg :
			return s + "The <b>Library Computer</b> is damaged and inoperable. "
				+ "It will be repaired in <b>"
				+ (lo[2]/10) +" Star Dates</b>";
		case ShieldPiercedMsg : 
			return s + "Klingon attack of <b>"
				+ lo[2] + " Energy Units</b> from ship at sector <b>"
				+ LetNum(lo[3]) + "</b> has pierced shields! <b>"
				+ DamageA[lo[4]].Desc + "</b> has been damaged! <b>"
				+ (lo[5] / 10) + "Star Dates </b> will be needed to affect repair!";
		case ShieldDownMsg :
			return s + "Captain! Shields are down! Klingon attack of <b>"
				+ lo[2] + " Energy Units</b> from ship at sector <b>"
				+ LetNum(lo[3]) + "</b> has damaged <b>"
				+ DamageA[lo[4]].Desc +"</b> for <b>"
				+ (lo[5] / 10) + " Star Dates</b>!";
		case KlingonsLeftMsg :
			return s + "There are now only <b> " 
				+ lo[2] + "</b> pesky Klingons left.";
		case ShieldsLeftMsg :
			return s + "Shields are down to <b>"
				+ lo[2] + " Energy Units</b>.";
		case StarbaseHereMsg :
			return s + "Starbase at sector <b>"
				+ LetNum(lo[2]) + "</b> in this quadrant.";
		case KlingonLocationMsg :
			if (lo.length <= 2)
				return s + "<b>No</b> Klingons in this quadrant.";
			s += "Klingons located at <b>sectors ";
			for (i = 2; i < lo.length; i++) {
				s += LetNum (lo [i]) + " ";
			}
			return s + "</b>";

	}
	return s;
}

var CaptainLogTable = "\
<table width='100%' border='1' BGCOLOR='black'>\n\
<tr><th colspan='2' bgcolor='yellow'><big>Captain's Log</big></tr>\n\
<tr><th bgcolor='yellow'>Star Date<th bgcolor='yellow'>Message</tr>";

function GenCaptainLogHTML () {
	var o, s = ""; 
	LogQuadrant = CurrentQuadrant; 
	LogDate = -1;
	for (o = CaptainLogHead; o != null; o = o.Next) {
		s += LogText (o);
	}
	return CaptainLogTable + s + "</table>";
}

function ShowCaptainLog () {
	WrPane (BRPane, Head(0, "lightgreen") + GenCaptainLogHTML() + Tail);
}


function AddCaptainLog () {
	var i, o = new Array();
	o [0] = StarTime;
	for (i = 0; i < arguments.length; i++) {
		o [o.length] = arguments [i];
	}
	if (CaptainLogTail == null)
		CaptainLogTail = o;
	o.Next = CaptainLogHead; CaptainLogHead = o;
	if (CaptainLogCnt < MaxCaptainLog)
		CaptainLogCnt++;
	else
		CaptainLogTail = CaptainLogTail.Next;
}

function AddCaptainLogArg (v) {
	CaptainLogHead [CaptainLogHead.length] = v;
}


////////////////////////////////////////////////////////////////////
// Command Handlers
////////////////////////////////////////////////////////////////////

function OnWarpDrive(HelpI) {
	WrWarpDrive (LastWarpDirIndex, LastWarpIndex);
}

function OnImpulse(HelpI) {
	WrImpulseInput(LastImpulseDirIndex, LastImpulseIndex);
}

function OnPhotonTorp(HelpI) {
	WrPhotonTorpInput(LastPhotonDirIndex);
}

function OnPhasors (HelpI) {
	WrPane (LPane, Head(0, "lightblue") + GenPhasorInputHTML() + Tail);
}

function OnShortScan(HelpI) {
	TRPaneMode = ShortScanMsg; NextTurn();
}

function OnLongScan (HelpI) {
	TRPaneMode = LongScanMsg; NextTurn();
}

function OnGalacHist(HelpI) {
	TRPaneMode = GalacHistMsg; NextTurn();
}

function OnDamageRep(HelpI) {
	TRPaneMode = DamageReportMsg; NextTurn();
}

function OnSetShields (HelpI) {
	WrPane (LPane, Head(0,"lightblue") + ShieldInputHTML() + Tail);
}

function OnHelp (HelpI) {
	WrPane (LPane, Head("HelpOnLoad()", "lightblue") + HelpMenuHTML + Tail);
	AtTop = true;
	GenHelpHTML (IsGameState && HelpI < 0 ? HelpIndex ["LOAD GAME"]: 0);
}

function OnPlayGame(HelpI) {
	WrPane (LPane, Head(0, "lightblue") + MenuHTML + Tail);
	WrPane (TRPane, CurrentTRPane);
	ShowCaptainLog();
}

////////////////////////////////////////////////////////////////////
// Next Turn & Game End Logic
////////////////////////////////////////////////////////////////////

var GameEndMenu = "\
<center><big><big><b>Jal Trek</b></big></big></center>\n\
<table align='center' border='1' BGCOLOR='black'>\n\
<tr><th bgcolor='yellow'>Game Over</tr>\n<tr>"
+ MenuItem ("OnNewGame", "New Game", 0)
+ "</table>";

var DemotionMsgs = new Array (
	1, "Not bad. This one <b>Klingon</b> will be swiftly dealt with by others.",
	2, "It is annoying that two <b>Klingons</b> are still harrassing the <b>Federation</b>",
	3, "Not good. Your failure will be noted in your record.",
	8, "Your performance is unsatisfactory. Your reassignment to a garbage scow is emminent.",
	12, "Unacceptable performance! Your reassignment to an oxe cart may prove problematic!", 
	20, "Your <i>immdediate</i> resignation from Star Fleet Command is demanded!",
	25, "Star Fleet Command has <i>fired</i> you! Your name will be forever held in derision!",
	30, "Captain, you have failed <i>miserably</i> in your mission! Even as we speak, "
		+ "<b>Klingons</b> are overrunning the known galaxy, pillaging "
		+ "and destroying and subjugating mankind! All is lost! <i>all is lost!</i>");


var PromotionMsgs = new Array (
	1,	"You have completed your mission in the nick of time.",
	5,	"You have succeeded with plenty of time to spare.",
	15,	"Bravo! An outstanding performance! The Galaxy has been saved!",
	25,	"A fabulous performance that will go down in Federation history!",
	30,	"Your promotion to <b>Admiral</b> is under serious consideration!",
	35, "You will be promoted to <b>Admiral</b> forthwith!",
	40,	"You are being promoted to <b>Supreme Ruler of the Federation</b>! "
		+ "Women all over the Galaxy are vying for your attentions!"
);


function FindRank (a, v) {
	var i, s = "";
	for (i = a.length - 2; i >= 0; i -= 2) {
		s = a [i + 1];
		if (a [i] <= v)
			break;
	}
	return s;
}

function PlayerLooses (TimeUp) {
	return "<big><center>Game Over</center></big><p>"
		+ (TimeUp 
			? "You have reached the <b>mission deadline</b>."
			: "Your ship has <b>run out of energy</b>, leaving you to die a slow, "
				+ "lingering death in the loneliness of space.")
		+ "</p><p>" + FindRank (DemotionMsgs, KlingonCnt) + "</p>";
}

function PlayerWins () {
	return "<big><center>Game Over</center></big><p>"
		+ FindRank (PromotionMsgs, MissionEnd - StarTime) + "</p>";
}

function CheckDamage(DeltaTime) {
	var i;
	for (i = 0; i < DamageVars.length; i++) {
		if (window [DamageVars [i]] > 0 
				&& (window [DamageVars [i]] -= DeltaTime) <= 0) {
			window [DamageVars [i]] = 0;
			AddCaptainLog (DamageFixedMsg, i); 
		}
	}
}


function NextTurn (DeltaTime) {
	var TimeUp;
	GalactHistA [CurrentQuadrant] = ScanQuadrant(GalaxyA [CurrentQuadrant]);
	if (! DeltaTime)
		DeltaTime = 1;
	if (KlingonCnt <= 0) {
		WrPane (LPane, Head(0,"lightblue") + GameEndMenu + Tail);
		WrPane (TRPane, Head() + PlayerWins() + Tail);
		AddCaptainLog (PlayerWinsMsg, MissionEnd - StarTime);
		ShowCaptainLog();
		return;
	}
	StarTime += DeltaTime; CheckDamage(DeltaTime);
	KlingonAttack();
	ShipEnergy -= EnergyPerTurn;
	if ((TimeUp = StarTime > MissionEnd) || ShipEnergy <= 0) {
		WrPane (LPane, Head(0,"lightblue") + GameEndMenu + Tail);
		WrPane (TRPane, Head() + PlayerLooses(TimeUp) + Tail);
		AddCaptainLog (TimeUp ? OutOfTimeMsg : OutOfEnergyMsg, 
			MissionEnd, KlingonCnt);
		ShowCaptainLog();
		return;
	}
	switch (TRPaneMode) {
		case ShortScanMsg :
			if (ShortScanDmg)
				AddCaptainLog (StillDamagedMsg, ShortScanDmgI, ShortScanDmg);
			else
				CurrentTRPane = GenShortScanHTML();
			break;
		case LongScanMsg :
			if (LongScanDmg) 
				AddCaptainLog (StillDamagedMsg, LongScanDmgI, LongScanDmg);
			else
				CurrentTRPane = GenLongRangeScanHTML();
			break;
		case GalacHistMsg :
			if (GalactHistDmg)
				AddCaptainLog (StillDamagedMsg, GalactHistDmgI, GalactHistDmg);
			else
				CurrentTRPane = GenGalacHistHTML();
			break;
		case DamageReportMsg :
			CurrentTRPane = GenDamageRepHTML();
			break;
	}
	OnPlayGame();
}

////////////////////////////////////////////////////////////////////
// Library Computer Logic
////////////////////////////////////////////////////////////////////

function XYObj (i) {
	var o = new Object();
	o.x = (o.i = i) % 10;
	o.y = INT(i / 10);
	return o;
}
/*
	if (1 < d && d <= 3) {
		o.my = -1; o.mx = dx / dy;
	} else if (3 < d && d <= 5) {
		o.mx = -1; o.my = dy / dx;
	} else if (5 < d && d <= 7) {
		o.my = 1;  o.mx = - dx / dy;
	} else {
		o.mx = 1;  o.my = - dy / dx;
	}
*/
/*      
       2			1..3   x < y
   3   |   1 
     \ | /  
  4 -- * -- 0
     / | \  
   5   |   7 
       6 

*/
function DistanceDir (si, di) {
	var EntObj = XYObj(si);
	var DestObj = XYObj(di);
	DestObj.DistIndex = INT(Math.sqrt(Squ(EntObj.x - DestObj.x) 
		+ Squ (EntObj.y - DestObj.y)) * 2) - 2;
	var dy = DestObj.y - EntObj.y;
	var dx = DestObj.x - EntObj.x;
	var d, r;
	if (dx == 0) {
		d = dy > 0 ? 6 : 2; r = 0;
	} else {
		d = dx > 0 ? 0 : 4; r = - Math.atan (dy / dx);
	}
	DestObj.DirIndex = (80 + Math.round ((d + 8 * r / Pi2) * 10)) % 80;
	return DestObj;
}

function ShortRangeLib (di) {
	if (LibraryComputerDmg) {
		AddCaptainLog (LibraryComputerDmgMsg, LibraryComputerDmg);
		ShowCaptainLog();
		return;
	}
	var q = GalaxyA [CurrentQuadrant];
	var DestObj = DistanceDir (CurrentSector, di); 
	if (di == CurrentSector)
		return;
	if (q [di] < Star)
		WrImpulseInput (DestObj.DirIndex, DestObj.DistIndex);
	else 
		WrPhotonTorpInput (DestObj.DirIndex);
}

function WarpDriveLib (di) {
	if (LibraryComputerDmg) {
		AddCaptainLog (LibraryComputerDmgMsg, LibraryComputerDmg);
		ShowCaptainLog();
		return;
	}
	var DestObj = DistanceDir (CurrentQuadrant, di);
	if (di != CurrentQuadrant)
		WrWarpDrive (DestObj.DirIndex, DestObj.DistIndex);
}


function GenLibSelect (n, l) {
	var i, s = "<select name='"+ n +"'>\n<option> \n";
	for (i = 0; i < 10; i++) {
		s += "<option>"+l.substr (i,1);
	}
	return s + "</select>\n";
}


function LibraryCompute (f) {
	var r = LPane.forms[0].RowSelect.selectedIndex;
	var c = LPane.forms[0].ColSelect.selectedIndex;
	if (r && c)
		f ((r - 1) * 10 + c - 1);
}

function LibraryHTML (Desc, Fname) {
	return "<tr><td BGCOLOR='white'>"
		+ (LibraryComputerDmg 
		? "Library Computer will be down for <b>"
			+ (LibraryComputerDmg/10) + "</b> Star Dates."
		: "<tr><td  BGCOLOR='white'>Enter target <b>"
			+ Desc 
			+ "</b><tr><td><table align='center' border='1' bgcolor='black'>\n"
			+ "<tr><td>" + GenLibSelect ("ColSelect", ColLets)
			+ "<td>" + GenLibSelect ("RowSelect", RowNums)
			+ MenuItem ("LibraryCompute", "Compute", Fname)
			+ "</table>");

}

////////////////////////////////////////////////////////////////////
// Command: Generate Short Range Scan
////////////////////////////////////////////////////////////////////


function SectorFile (i, s) {
	var fn, m = INT (s / 10) * 10;
	if (m == Star)
		fn = "Star";
	else if (m == Starbase)
		fn = "Base";
	else if (m == Klingon)
		fn = "Klingon";
	else if (m == Enterprise)
		fn = "Enterprise";
	else if (s < 4)
		fn = "Space" + s;
	else 
		fn = "Spacer";
	TRPane.I [i].src = ImgBase + fn + ".jpg"; 
}

function AllSectorFiles () {
	var i;
	for (i = 0; i < 100; i++) {
		SectorFile (i, DisplayQuadrant [i]);
	}
}


function QuadrantHTML (Iq) {
	DisplayQuadrant = new Array();
	var i, rn, q, b, h, t = "<table cellpadding=0 cellspacing=0>\n";
	b = "";
	for (i = 0; i < 100; i++) {
		DisplayQuadrant [i] = Iq [i];
		if (i % 10 == 0) 
			b += "<tr>" 
				+ (q = "<td width='20' align='center' valign='top'><font size='3'>" 
				+ (rn = RowNums.substr(INT(i / 10), 1)) + "</font></td>");
		b += "<td valign='top' title='"	+ ColLets.substr(i % 10, 1) + rn 
			+ "' onclick='pp.ShortRangeLib (" + i
			+ ")'><img width='20' height='20' name='I'></td>\n";
		if (i % 10 == 9)
			b += q; 
	}
	h = "<tr><td width='20' height='20'>&nbsp;</td>";
	for (i = 0; i < 10; i++)
		h += "<th>" + ColLets.substr(i,1) + "</th>";
	return t + h + b + h + "</table>";
}

function LetNum (i) {
	return ColLets.substr(i % 10, 1)+RowNums.substr(INT(i / 10), 1);
}

/*  
    -1,-1   0,-1   1,-1    
	-1, 0   0, 0   1, 0
	-1, 1   0, 1   1, 1   
*/

var Neighbors = new Array (    
    -1,-1,  0,-1,  1,-1,
	-1, 0,         1, 0,
	-1, 1,  0, 1,  1, 1);  


function StarbaseHere () {
	var q = GalaxyA [CurrentQuadrant], B = INT(Starbase / 10), i;
	for (i = 0; i < 100; i++) {
		if (INT (q [i] / 10) == B) 
			AddCaptainLog (StarbaseHereMsg, i);
	}
}

function IsDocked (q, Cs) {
	var B = INT(Starbase / 10), r0, c0, r = INT(Cs / 10), c = Cs % 10;
	for (j = 0; j < Neighbors.length; j += 2) {
		c0 = c + Neighbors [j];	r0 = r + Neighbors [j + 1];
		if (0 <= r0 && r0 <= 9 && 0 <= c0 && c0 <= 9
			&& INT(q [r0 * 10 + c0] / 10) == B)
				return true; 
	}
	return false;
}

function StatusHTML () {
	var q = GalaxyA [CurrentQuadrant], v = ScanQuadrant (q);
	if (v >= 100)
		return "<font color='red'>Red</font>";	
	if (v < 10)
		return "<font color='green'>Green</font>";
	if (IsDocked (q, CurrentSector))
		return "<font color='blue'>Docked</font>";
	return "<font color='blue'>Blue</font>";
}

function GenShortScanHTML () {
	return Head("AllSectorFiles ()") 
		+ "<table cellpadding='3' border='1'>\n"
		+ "<tr><th rowspan='10' bgcolor='yellow'>Short<br>Range<br>Scan</th>"
		+ "<td rowspan='10'>" + QuadrantHTML (GalaxyA [CurrentQuadrant])
		+ "<td>Star Date<td><b>"+(StarTime/10)+"</b></tr>\n"
		+ "<tr><td>Deadline<td><b>"+(MissionEnd/10)+"</b></tr>\n"
		+ "<tr><td>Shields<td><b>"+ShieldEnergy+"</b></tr>\n"
		+ "<tr><td>Ship Energy<td><b>"+ShipEnergy+"</b></tr>\n"
		+ "<tr><td>Quadrant<td><b>"+LetNum(CurrentQuadrant)+"</b></tr>\n"
		+ "<tr><td>Sector<td><b>"+LetNum(CurrentSector)+"</b></tr>\n"
		+ "<tr><td>Status<td><b>"+StatusHTML()+"</b></tr>\n"
		+ "<tr><td>Klingons<td><b>"+KlingonCnt+"</b></tr>\n"
		+ "<tr><td>Torpedoes<td><b>"+PhotonTorps+"</b></tr>\n"
		+ "</table>\n"
		+ Tail
}

////////////////////////////////////////////////////////////////////
// Command: Set Shields
////////////////////////////////////////////////////////////////////

var InputTable = "\
<center><big><big><b>Jal Trek</b></big></big></center>\n\
<table bgcolor='lightblue' border='1' BGCOLOR='black'>\n\
<tr><th bgcolor='yellow'>Commander Input</tr>";


function OnShieldInput () {
	var me = min(MaxShieldEnergy, ShipEnergy + ShieldEnergy);
	var ei = LPane.forms[0].ShieldEnergyInput;
	var e = parseInt (ei.value, 10);
	if (e < 0)
		ei.value = 0;
	else if (me < e)
		ei.value = me;
	else {
		AddCaptainLog (SetShieldMsg, ShieldEnergy, e); 
		ShipEnergy += ShieldEnergy - e;
		ShieldEnergy = e;
		NextTurn();		
	}
	return false;
}


function ShieldInputHTML () {
	return "<form onsubmit='return(pp.OnShieldInput())'>"
		+ InputTable 
		+ "<tr><td bgcolor='white'>"
		+ (ShieldDmg
			? "Shields have been damaged. They will be down for <b>"
				+ ShieldDmg + "</b> Star Dates.</tr>"
			: "Please enter the amount of energy you wish to budget "
				+ "for the shields. Shields protect the Enterprise from damage "
				+ "during battle with the dreaded Klingons. The maximum allowed is <b>"
				+ min(MaxShieldEnergy, ShipEnergy + ShieldEnergy)
				+ "</b><tr><td><input name='ShieldEnergyInput' value='"
					+ShieldEnergy+"'>"
				+ "<tr>" + MenuItem ("OnShieldInput", "Go", 0) +"</tr>")
		+ "<tr>" + MenuItem ("OnPlayGame", "Cancel", 1)+"</tr>"
		+ "</table></form>";
}

////////////////////////////////////////////////////////////////////
// Command: Generate Damage Report
////////////////////////////////////////////////////////////////////

function GenDamageRepHTML () {
	var i, v, s = Head()
		+ "<table  cellpadding='3' align='center' border='1'>\n"
		+ "<tr><th rowspan='"+(DamageVars.length+2)
		+ "' bgcolor='yellow'>Damage<br>Report</tr>\n"
		+ "<th bgcolor='yellow'>System<th bgcolor='yellow'>Repair Days</tr>\n";
	for (i = 0; i < DamageVars.length; i++) {
		s += "<tr><td>"+DamageA[i].Desc+"<th>"
			+ ((v = window[DamageVars[i]]) == 0 ? "None" : v/10)+"</tr>\n";
	}
	return s + "</table>"+ Tail;
}

////////////////////////////////////////////////////////////////////
// Generate Galactic History Report & Long Range Scan
////////////////////////////////////////////////////////////////////


function DoScroll (cq) {
	var x = cq % 10;
	var y = INT (cq / 10);
	TRPaneW.scrollTo (x <= 5 ? 0 : WindowW (TRPaneW), 
		y <= 3 ? 0 : WindowH(TRPaneW));
}

function ScanImgOnLoad(w) {
	var i, e = TRPane.K.length;
	for (i = 0; i < e; i++) {
		TRPane.K [i].src = ImgBase + "Klingon.jpg";
		TRPane.B [i].src = ImgBase + "Base.jpg";
		TRPane.S [i].src = ImgBase + "Star.jpg";
	}
	if (w == 9)
		DoScroll(CurrentQuadrant);
}

var GTable = "<table cellpadding='0' cellspacing='0'>";
var GeTd = "<td width='60' height='20'>&nbsp;</td>";

function GiTd (n) {
	return "<td><img width='20' height='20' name='" + n + "'></td>";
}

function GsTd (i, d) {
	return "<th width='20' height='20'>" + INT(GalactHistA [i] / d) % 10 + "</th>";
}

function GenQuadrantCell (r, c) {
	var i = r * 10 + c;
	var bc = i == CurrentQuadrant ? " bgcolor='lightgreen'" : "";
	if (0 <= c && c < 10)
		return "<td valign='top' title='" + LetNum(i) + "'" + bc 
			+ " onclick='pp.WarpDriveLib(" + i + ")'>"
			+ (GalactHistA [i]
				? GTable + GsTd(i, 100) + GsTd (i, 10) + GsTd (i, 1) 
					+ "</table></td>\n"
				: "&nbsp;</td>");
	return GeTd;
}

function GenQuadrantHTML (h, r0, r1, c0, c1) {
	var r, c, t, s = Head("ScanImgOnLoad("+(r1-r0)+")")
		+ "<table cellpadding='3' align='center' border='1'>\n"
		+ "<tr><th colspan='" + (c1 - c0 + 3) 
		+ "' bgcolor='yellow'>"+ h +"</tr>\n";
	s += "<tr><td>&nbsp;";
	for (c = c0; c <= c1; c++) {
		s += "<th>" + (0 <= c && c <= 9 ? ColLets.substr(c, 1) : "&nbsp;");
	}
	s += "<td>&nbsp;</td><tr><td>&nbsp;</td>";
	for (c = c0; c <= c1; c++) {
		s += "<td valign='top'>" + (0 <= c && c <= 9
			? GTable + GiTd("K") + GiTd ("B") + GiTd ("S") + "</table></td>"
			: "&nbsp;</td>"); 
	}
	s += "<td>&nbsp;</td>";
	for (r = r0; r <= r1; r++) {
		s += "<tr>";
		if (0 <= r && r < 10) {
			s += (t = "<td align='center'>"+ RowNums.substr(r, 1));
			for (c = c0; c <= c1; c++) {
				s += GenQuadrantCell (r, c);
			}
		}
		else { 
			s += (t = "<td>&nbsp;</td>");
			for (c = c0; c <= c1; c++) {
				s += GeTd;
			}
		}
		s += t;
	}
	return s + "</table>" + Tail;
}

function GenGalacHistHTML () {
	return GenQuadrantHTML ("Galactic History Report", 0, 9, 0, 9);
}

////////////////////////////////////////////////////////////////////
// Command: Long Range Scan
////////////////////////////////////////////////////////////////////

function QLimit (i) {
	return max (0, min (i, 9));
}

function ComputeLongRangeScan (r0, r1, c0, c1) {
	var i, r, c; 
	r0 = QLimit (r0); r1 = QLimit (r1);
	c0 = QLimit (c0); c1 = QLimit (c1); 
	for (r = r0; r <= r1; r++) {
		for (c = c0; c <= c1; c++) {
			i = r * 10 + c;
			GalactHistA [i] = ScanQuadrant (GalaxyA [i]);
		}
	}
}

function GenLongRangeScanHTML () {
	var r0, r1, c0, c1;
	r1 = (r0 = INT(CurrentQuadrant / 10) - 1) + 2;
	c1 = (c0 = CurrentQuadrant % 10 - 1) + 2;
	ComputeLongRangeScan (r0, r1, c0, c1);
	return GenQuadrantHTML ("Long Range Scan", r0, r1, c0, c1);
}

////////////////////////////////////////////////////////////////////
// Warp Drive & Impulse Drive support
////////////////////////////////////////////////////////////////////

function SelectAdjust (n, i) {
	var e = LPane.forms[0][n];
	e.selectedIndex = (e.options.length + e.selectedIndex + i) % e.options.length;
}

function GenSelectHTML (name, beg, end, delta) {
	var i, s = "<table align='center' border='1' bgcolor='black'>\n"
		+ "<tr><td bgcolor='white'><select name='"+name+"'>\n";
	end = Math.round(end / delta);
	for (i = Math.round(beg / delta); i <= end; i++) {
		s += "<option>" + Round(i * delta, 10);
	}
	s += "</select>\n"
		+ MenuItem ("SelectAdjust", "Down", '"' + name + '",-1')
		+ MenuItem ("SelectAdjust", "Up", '"' + name + '",1')
		+ "</table>\n"
	return s;
}


function DirOnClick(i) {
	LPane.forms[0].DirectionInput.selectedIndex = i;
}

function Area (i, x0, y0, x1, y1, x2, y2) {
	return "<area onclick='pp.DirOnClick("+i+")' shape='poly' "
		+ "coords='"+x0+","+y0+","+x1+","+y1+","+x2+","+y2+"'>\n";
}

function GenDirMap () {
	var rad, x1, y1, x2, y2, i;
	var s = "<map name='DirMap'>\n", Cx = 34, Cy = 34;
	for (i = 0; i < 80; i++) {
		x1 = Math.round(Cx + Cx * Math.cos(rad = (i - 0.5) * Pi2 / 80));
		y1 = Math.round(Cy - Cy * Math.sin(rad));
		x2 = Math.round(Cx + Cx * Math.cos(rad = (i + 0.5) * Pi2 / 80));
		y2 = Math.round(Cy - Cy * Math.sin(rad));
		s += Area (i, Cx, Cy, x1, y1, x2, y2);
	}
	return s + "</map>\n";
}

var DirMapHTML = GenDirMap(); 

/*      
       2 
   3   |   1 
     \ | /  
  4 -- * -- 0
     / | \  
   5   |   7 
       6 

*/

function Cartesian (d, Cq, Cs) {
	var o = new Object(); o.Cq = Cq;
	var dx = Math.cos(o.radians = (o.d = d) / 8.00 * Pi2);
	var dy = Math.sin(o.radians);
	if (1 < d && d <= 3) {
		o.my = -1; o.mx = dx / dy;
	} else if (3 < d && d <= 5) {
		o.mx = -1; o.my = dy / dx;
	} else if (5 < d && d <= 7) {
		o.my = 1;  o.mx = - dx / dy;
	} else {
		o.mx = 1;  o.my = - dy / dx;
	}
	o.cy = INT ((o.Cs = Cs) / 10);
	o.cx = Cs % 10;
	o.Lo = 0;
	o.Hi = 9;
	return o;
}


function InLimit (o, Lo, Hi) {
	return Lo <= o.x && o.x <= Hi && Lo <= o.y && o.y <= Hi;
}

function NextPoint (o) { 
	o.x = o.cx + Math.round (o.i * o.mx); 
	o.y = o.cy + Math.round (o.i * o.my); 
	o.ns = o.x + o.y * 10;
	return InLimit (o, o.Lo, o.Hi);
}

function Index (o) {
	return o.x + o.y * 10;
}

function Squ (x) {
	return x * x;
}


function RayTrace (o, Dist) {
	for (o.i = 1; NextPoint (o); o.i++) {
		if (GalaxyA [o.Cq][o.ns] >= Star)
			return o.r = CollisionDetectedMsg;
		if (Math.sqrt(Squ(o.cx - o.x) + Squ (o.cy - o.y)) >= Dist)
			return o.r = DistanceReachedMsg;
	}
	o.i--; NextPoint(o);
	return o.r = QuadrantEdgeMsg;
}

function WarpTrace (o, Dist) {
	for (o.i = 1; NextPoint (o); o.i++) {
		if (Math.sqrt(Squ(o.cx - o.x) + Squ (o.cy - o.y)) >= Dist)
			return o.r = NewQuadrantMsg;
	}
	o.i--; NextPoint(o);
	return o.r = GalaxyEdgeMsg;
}

////////////////////////////////////////////////////////////////////
// Command: Warp Drive
////////////////////////////////////////////////////////////////////

function WarpInputOnLoad() {
	LPane.I.src = ImgBase + "Directions.jpg";
	LPane.forms[0].WarpFactorInput.selectedIndex = DefaultWarpIndex;
	LPane.forms[0].DirectionInput.selectedIndex = DefaultWarpDirIndex;
}

function FindKlingons () {
	var K = INT(Klingon/10), i, q = GalaxyA [CurrentQuadrant];
	AddCaptainLog (KlingonLocationMsg);
	for (i = 0; i < 100; i++) {
		if (INT(q [i] / 10) == K)
			AddCaptainLogArg (i);
	}
}
	
function OnWarpInput() {
	var d, f, o, q;
	LastWarpIndex = (f = LPane.forms[0].WarpFactorInput).selectedIndex;
	LastWarpDirIndex = (d = LPane.forms[0].DirectionInput).selectedIndex;
	o = Cartesian (parseFloat (d.options [LastWarpDirIndex].text),
		0, CurrentQuadrant);
	WarpTrace (o, parseFloat (f.options [LastWarpIndex].text));
	GalaxyA [CurrentQuadrant][CurrentSector] %= 10;
	q = GalaxyA [CurrentQuadrant = o.ns];
	while (q [CurrentSector = RND(100)] >= Star)
		;
	AddCaptainLog (o.r, CurrentQuadrant, CurrentSector);
	GalaxyA [CurrentQuadrant] [CurrentSector] += Enterprise;
	StarbaseHere ();
	if (IsDocked (GalaxyA [CurrentQuadrant], CurrentSector))
		SetCurrent();
	FindKlingons();
	NextTurn (10);
}

function GenWarpInputHTML(DirIndex, WarpIndex) {
	DefaultWarpDirIndex = DirIndex;
	DefaultWarpIndex = min (WarpDriveDmg ? 2 : 15, WarpIndex);
	return "<form onsubmit='return(pp.OnWarpInput())'>"
		+ DirMapHTML
		+ InputTable 
		+ "<tr><td bgcolor='white'>Please select <b>Warp Factor</b>."
		+ (WarpDriveDmg
			? " The Drive is damaged, and is limited to a maximum Warp Factor of 2" 
			: "") + "</tr>"
		+ "<tr><td align='center'>" 
			+ GenSelectHTML ("WarpFactorInput", 1, WarpDriveDmg ? 2 : 15, 0.5) 
		+ "<tr><td bgcolor='white'>Please select Warp <b>Direction</b>.</tr>"
		+ "<tr><td align='center'><img usemap='#DirMap' name='I'></tr>"
		+ "<tr><td align='center'>" 
			+ GenSelectHTML ("DirectionInput", 0, 7.9, 0.1) 
		+ LibraryHTML ("quadrant", "pp.WarpDriveLib")
		+ "<tr>" + MenuItem ("OnWarpInput", "Engage", 0) + "</tr>"
		+ "<tr>" + MenuItem ("OnPlayGame", "Cancel", 1) + "</tr>"
		+ "</table></form>";
}

function WrWarpDrive(DirIndex, WarpIndex) {
	WrPane (LPane, Head("WarpInputOnLoad()", "lightblue") 
		+ GenWarpInputHTML(DirIndex, WarpIndex) + Tail);
}

////////////////////////////////////////////////////////////////////
// Command: Impulse Drive
////////////////////////////////////////////////////////////////////

function ImpulseInputOnLoad() {
	LPane.I.src = ImgBase + "Directions.jpg";
	LPane.forms[0].ImpulseFactorInput.selectedIndex = DefaultImpulseIndex;
	LPane.forms[0].DirectionInput.selectedIndex = DefaultImpulseDirIndex;
}

function OnImpulseInput() {
	var f, d, o;
	LastImpulseIndex = (f = LPane.forms[0].ImpulseFactorInput).selectedIndex;
	LastImpulseDirIndex = (d = LPane.forms[0].DirectionInput).selectedIndex;
	o = Cartesian (parseFloat (d.options [LastImpulseDirIndex].text), 
		CurrentQuadrant, CurrentSector);
	o.f = parseFloat (f.options [LastImpulseIndex].text);
	if (RayTrace (o, o.f) == CollisionDetectedMsg) {
		o.i--; NextPoint (o);
	}
	AddCaptainLog (o.r, o.ns);
	GalaxyA [CurrentQuadrant][CurrentSector] %= 10;
	GalaxyA [CurrentQuadrant][CurrentSector = o.ns] += Enterprise;
	if (IsDocked (GalaxyA [CurrentQuadrant], CurrentSector))
		SetCurrent();
	NextTurn (Math.round(o.f));
}
function GenImpulseInputHTML(DirIndex, ImpulseIndex) {
	DefaultImpulseIndex = min (ImpulseDriveDmg ? 2 : 15, ImpulseIndex);
	DefaultImpulseDirIndex = DirIndex;
	return "<form onsubmit='return(pp.OnImpulseInput())'>"
		+ DirMapHTML
		+ InputTable 
		+ "<tr><td bgcolor='white'>Please select Impulse <b>Distance</b> in Sectors."
		+ (ImpulseDriveDmg
			? " The Drive is damaged, and is limited to a maximum Impulse Distance of 2" 
			: "") + "</tr>"
		+ "<tr><td align='center'>" 
			+ GenSelectHTML ("ImpulseFactorInput", 1, ImpulseDriveDmg ? 2 : 15, 0.5) 
		+ "<tr><td bgcolor='white'>Please select Impulse <b>Direction</b>.</tr>"
		+ "<tr><td align='center'><img usemap='#DirMap' name='I'></tr>"
		+ "<tr><td align='center'>" 
			+ GenSelectHTML ("DirectionInput", 0, 7.9, 0.1) 
		+ LibraryHTML ("sector", "pp.ShortRangeLib")
		+ "<tr>" + MenuItem ("OnImpulseInput", "Engage", 0) + "</tr>"
		+ "<tr>" + MenuItem ("OnPlayGame", "Cancel", 1) + "</tr>"
		+ "</table></form>";
}

function WrImpulseInput(DirIndex, ImpulseIndex) {
	WrPane (LPane, Head("ImpulseInputOnLoad()", "lightblue") 
		+ GenImpulseInputHTML(DirIndex, ImpulseIndex) + Tail);
}

////////////////////////////////////////////////////////////////////
// Command: Photon Torpedoes
////////////////////////////////////////////////////////////////////

function PhotonInputOnLoad() {
	if (typeof LPane.I != "object")
		return;
	LPane.I.src = ImgBase + "Directions.jpg";
	LPane.forms[0].DirectionInput.selectedIndex = DefaultPhotonDirIndex;
}

function OnLaunchInput() {
	var d, o, h = 0;
	LastPhotonDirIndex = (d = LPane.forms[0].DirectionInput).selectedIndex;
	o = Cartesian (parseFloat (d.options [LastPhotonDirIndex].text), 
		CurrentQuadrant, CurrentSector);
	PhotonTorps--;
	if (RayTrace (o, 30) == CollisionDetectedMsg) {
		h = GalaxyA [CurrentQuadrant] [o.ns];
		GalaxyA [CurrentQuadrant] [o.ns] %= 10;
		switch (INT (h / 10) * 10) {
			case Klingon : KlingonCnt--; break;
			case Star	 : StarCnt--; break;
			case Starbase: StarbaseCnt--; 
				AddCaptainLog (BaseDestroyedMsg, StarbaseCnt);
				break;
		}
	}
	AddCaptainLog (o.r + 1, o.ns, h);
	NextTurn();
}

function GenPhotonInputHTML(DirIndex) {
	DefaultPhotonDirIndex = DirIndex;
	return "<form onsubmit='return(pp.OnLaunchInput())'>"
		+ DirMapHTML
		+ InputTable + "<tr><td bgcolor='white'>" 
		+ (PhotonTorps 
			? (PhotonTorpsDmg
				? " The launcher is damaged and cannot be used. "
				    + "It will be fixed in <b>" + (PhotonTorpsDmg / 10) 
					+ "</b> Star Dates.</tr>" 
				:	"Please select Torpedo <b>Direction</b>.</tr>"
					+ "<tr><td align='center'><img usemap='#DirMap' name='I'></tr>"
					+ "<tr><td align='center'>"
						+ GenSelectHTML ("DirectionInput", 0, 7.9, 0.1) 
					+ LibraryHTML ("sector", "pp.ShortRangeLib")
					+ "<tr>" + MenuItem ("OnLaunchInput", "Fire", 0) + "</tr>")
			: "You have no more Photon Torpedoes left. Find and dock with a "
			  + "Starbase to replenish your supply.</tr>")
		+ "<tr>" + MenuItem ("OnPlayGame", "Cancel", 1) + "</tr>"
		+ "</table></form>";
	
}

function WrPhotonTorpInput (DirIndex) {
	WrPane (LPane, Head("PhotonInputOnLoad()", "lightblue")	
		+ GenPhotonInputHTML(DirIndex) + Tail);
}

////////////////////////////////////////////////////////////////////
// Command: Phasors
////////////////////////////////////////////////////////////////////


function KlingonDefense () {
	return Prob (PhasorHiRange) 
		? range (PhasorKill2Lo, PhasorKill2Hi)
		: range (PhasorKillLo, PhasorKillHi);
}

function PhasorBlast (Energy) {
	var k, te, ae, i, q = GalaxyA [CurrentQuadrant], OldCnt = KlingonCnt;
	k = INT(ScanQuadrant (q) / 100);
	if (k == 0) {
		AddCaptainLog (PhasorNoKlingonsMsg, CurrentQuadrant);
		return;
	}
	ShipEnergy -= Energy; ae = Energy / k;
	AddCaptainLog (PhasorBlastMsg, CurrentQuadrant, k);
	for (i = 0; i < 100; i++) {
		if (INT(q [i] / 10) * 10 != Klingon)
			continue; 
		if (ae > (te = KlingonDefense ())) {
			q [i] %= 10; KlingonCnt--;
			AddCaptainLog (PhasorKillMsg, i, te, Round(ae,10));
			continue;
		}
		AddCaptainLog (PhasorNoKillMsg, i, te, Round(ae,10));
	}
	if (OldCnt > KlingonCnt)
		AddCaptainLog (KlingonsLeftMsg, KlingonCnt);
}

function OnPhasorInput () {
	var e, i = LPane.forms [0].PhasorEnergyInput, e = parseInt(i.value,10);
	if (e <= 0) {
		i.value = 0;
		return;
	}
	if (e > ShipEnergy) {
		i.value = ShipEnergy;
		return;
	}
	PhasorBlast (LastPhasorInput = e);
	NextTurn();
	return false;
}

function GenPhasorInputHTML () {
	if (LastPhasorInput > ShipEnergy)
		LastPhasorInput = ShipEnergy;
	return "<form onsubmit='return(pp.OnPhasorInput())'>"
		+ InputTable + "<tr><td bgcolor='white'>" 
		+ (PhasorDmg 
			? "Phasors are damaged and cannot be used. "
				+ "They will be operational again in <b>"+(PhasorDmg / 10) 
				+ "</b> Star Dates.</tr>"
			: "Please enter the amount of <b>energy</b> to expend on this blast. "
				+ "The energy entered will be divided evenly among the Klingons "
				+ "in this quadrant. There is a maximum of <b>"
				+ ShipEnergy + "</b> available.</tr>"
				+ "<tr><td><input name='PhasorEnergyInput' value='"
					+ LastPhasorInput + "'></tr>"
				+ "<tr>" + MenuItem ("OnPhasorInput", "Fire", 0) + "</tr>")
		+ "<tr>" + MenuItem ("OnPlayGame", "Cancel", 1) + "</tr>"
		+ "</table></form>";
}

////////////////////////////////////////////////////////////////////
// Klingon Attack Logic
////////////////////////////////////////////////////////////////////

function FindChance (c) {
	var i, s;
	for (i = s = 0; i < DamageA.length; i++) {
		s += DamageA [i].Chance;
		if (c < s)
			return i;
	}
	return i;
}



function RandomDamage (DamageFactor) {
	var o = new Object();
	var d = DamageA [o.SystemIndex = FindChance (RND (DamageChances))];
	o.DownTurns = Math.round (DamageFactor * range(d.DownLo, d.DownHi) / 100);
	window [DamageVars [o.SystemIndex]] += o.DownTurns;
	return o;
}

function KlingonAttack() {
	var o, i, ae, K = Klingon/10, OldShield = ShieldEnergy;
	var q = GalaxyA [CurrentQuadrant];
	for (i = 0; i < 100; i++) {
		if (INT(q [i] / 10) == K) {
			ae = range (ShieldHitLo, ShieldHitHi);
			ShieldEnergy = max (0, ShieldEnergy - ae);
			if (ShieldEnergy > 0) {
				if (Prob (ShieldPierceProb)) {
					o = RandomDamage (PercentOfDown);
					AddCaptainLog (ShieldPiercedMsg, 
						ae, i, o.SystemIndex, o.DownTurns);
				}
				continue;
			}
			o = RandomDamage (100);
			AddCaptainLog (ShieldDownMsg, ae, i, o.SystemIndex, o.DownTurns);
		}
	}
	if (OldShield > ShieldEnergy)
		AddCaptainLog (ShieldsLeftMsg, ShieldEnergy);
}

////////////////////////////////////////////////////////////////////
// END OF PROGRAM -- Have a GREAT day!
////////////////////////////////////////////////////////////////////

