Back to Index Page generated: Aug 1, 2026, 4:49:44 AM

Expansion GNN

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description The Galactic News Network. The Galactic News Network.
Identifier oolite.oxp.Svengali.GNN oolite.oxp.Svengali.GNN
Title GNN GNN
Category Ambience Ambience
Author Svengali Svengali
Version 1.4 1.4
Tags ambience, child, news ambience, child, news
Required Oolite Version
Maximum Oolite Version
Required Expansions
  • oolite.oxp.Svengali.Library:1.8.1
  • oolite.oxp.Svengali.Library:1.8.1
  • Optional Expansions
    Conflict Expansions
    Dependent Expansions
  • oolite.oxp.Day.Diplomacy:0.19
  • oolite.oxp.Ramirez.BlOombergMarkets:2.9
  • oolite.oxp.Svengali.HyperRadio2:2.1
  • oolite.oxp.Thargoid.Planetfall:2.34
  • oolite.oxp.Zafrusteria.ShrewsRights:0.8
  • oolite.oxp.phkb.GalCopMissions:0.14
  • Information URL https://wiki.alioth.net/index.php/GNN n/a
    Download URL https://wiki.alioth.net/img_auth.php/9/93/GNN_1.4.oxz n/a
    License CC-by-nc-sa 4.0 CC-by-nc-sa 4.0
    File Size n/a
    Upload date 1783750771

    Relationships Diagram

    Documentation

    Also read http://wiki.alioth.net/index.php/GNN

    Readme.txt

    GNN 1.4 for Oolite
    Copyright 2009-2018 by DaddyHoggy, Drew, Disembodied and Svengali.
    Licences: see below
    November 2018
    
    REQUIREMENTS:
    - Oolite v1.88
    - Library v1.7.1
    
    
    PROBLEMS:
    In case of problems, please report it: http://bb.oolite.space/viewtopic.php?f=4&t=19419
    
    Please include the following infos:
    - Oolites version (and if trunk or nightly is used the revision number)
    - OS, Graphics card (and driver version)
    - Fullscreen/Windowed mode
    - Shader mode
    - List of used OXPs (incl. versions)
    
    Licences:
    Creative Commons Attribution-NonCommercial-ShareAlike 4.0 Unported License.
    To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or
     send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
    
    Version 1.3
    - Spelling/grammar corrections.
    - Moved most text into missiontext.plist for easier localisation.
    - Tweaked interface to Library so more news items can be stored (not just the most recent).
    - Added setting to Library Config to control how many news items to retain.
    
    Version 1.4
    - Rework of phraseGen seed method for greater variety in results, and to allow for more flexible control methods.

    Equipment

    This expansion declares no equipment.

    Ships

    This expansion declares no ships.

    Models

    This expansion declares no models.

    Scripts

    Path
    Scripts/GNN.js
    /* global clock,expandDescription,expandMissionText,galaxyNumber,mission,missionVariables,player,system,worldScripts,Vector3D */
    /* (C) DaddyHoggy, Drew, Disembodied and Svengali 2009-2018, License CC-by-nc-sa-4.0 */
    (function () {
    	"use strict";
    	this.name = "GNN";
    	this.description = "The Galactic News Network";
    
    	this.$snoop = {
    		audio: true,
    		fifo: [],
    		hot: [],
    		maxDays: 24,
    		nextNews: 0,
    		unused: [],
    		newsHistory: -1
    	};
    	this.$doop = {
    		ext: [ // Some events
    			{
    				ws: "AsteroidStorm", prop: { name: "badRockKiller", v: "PLAYER" }, mV: { name: "asteroids", v: "asteroids_OVER" },
    				act: { EX: "AsteroidStorm", m: "badrock", p: 1, Model: "badrock", Spin: 1 }
    			},
    			{
    				ws: "oolite-constrictor-hunt", mV: { name: "conhunt", v: "CONSTRICTOR_DESTROYED" },
    				act: { m: "conhunt", p: 1, Model: "constrictor", Spin: 1 }
    			},
    			{
    				ws: "oolite-nova", mV: { name: "nova", v: "NOVA_ESCAPED_SYSTEM" },
    				act: {
    					m: "nova", p: 1, Mat: {
    						"lib_null.png": {
    							emission_map: "GNN_solar.png", fragment_shader: "GNN_solar.fs", vertex_shader: "lib_simple.vs",
    							textures: ["GNN_solar.png", { name: "lib_explode2.png", repeat_s: true, repeat_t: true }], uniforms: {
    								colorMap: { type: "texture", value: 0 },
    								fxMap: { type: "texture", value: 1 }, Time: "timeElapsedSinceSpawn"
    							}
    						}
    					}
    				}
    			}
    		],
    		hud: false,
    		inf: {
    			Name: "GNN", Display: expandMissionText("GNN_config"), Alive: "$doop.inf",
    			Bool: { B0: { Name: "$snoop.audio", Def: true, Desc: expandMissionText("GNN_audio") } },
    			SInt: { S0: { Name: "$snoop.maxDays", Def: 24, Min: 12, Max: 99, Desc: expandMissionText("GNN_interval") }, 
    				S1: { Name: "$snoop.newsHistory", Def: -1, Min: -1, Max: 99, Desc: expandMissionText("GNN_newsHistory") }, 
    				Info: "^GNN_INFS" }
    		},
    		intern: 206,
    		expImages: [[], [], [], []],
    		expPrefixes: []
    	};
    	this.startUp = function () {
    		var infos, oxpID, i, k = this.$snoop;
    		if (missionVariables.GNN) {
    			infos = JSON.parse(missionVariables.GNN);
    			for (i = 0; i < infos.unused.length; i++) {
    				if (!infos.unused[i]) continue;
    				oxpID = infos.unused[i].ID;
    				if (worldScripts[oxpID]) k.fifo.push(infos.unused[i]);
    				else k.unused.push(infos.unused[i]);
    			}
    			for (i = 0; i < infos.fifo.length; i++) {
    				if (!infos.fifo[i]) continue;
    				oxpID = infos.fifo[i].ID;
    				if (worldScripts[oxpID]) k.fifo.push(infos.fifo[i]);
    				else k.unused.push(infos.fifo[i]);
    			}
    			k.nextNews = infos.nextNews;
    			for (i = 0; i < infos.hot.length; i++) {
    				if (infos.hot[i]) k.hot.push(infos.hot[i]);
    			}
    			k.audio = infos.audio;
    			k.maxDays = infos.maxDays;
    		}
    		this._aid = worldScripts.Lib_Main._lib;
    		delete this.startUp;
    	};
    	this.startUpComplete = function () {
    		this._updInterface(player.ship.dockedStation);
    		this._resort();
    		worldScripts.Lib_Config._registerSet(this.$doop.inf);
    		for (var i = 0; i < this.$doop.ext.length; i++) {
    			if (!worldScripts[this.$doop.ext[i].ws]) this.$doop.ext[i] = null;
    		}
    		this.$doop.ext = this._aid.arrOmit(this.$doop.ext, null);
    		delete this.startUpComplete;
    	};
    	this.playerWillSaveGame = function () {
    		missionVariables.GNN = JSON.stringify(this.$snoop);
    	};
    	this.shipWillDockWithStation = function () {
    		var i, obj, pass;
    		for (i = 0; i < this.$doop.ext.length; i++) {
    			pass = 0;
    			obj = this.$doop.ext[i];
    			if (obj.prop) {
    				if (worldScripts[obj.ws][obj.prop.name] === obj.prop.v) pass++;
    			} else pass++;
    			if (obj.mV) {
    				if (missionVariables[obj.mV.name] === obj.mV.v) pass++;
    			} else pass++;
    			if (pass === 2) this._addHot(obj.act);
    		}
    	};
    	this.shipExitedWitchspace = function () {
    		if (galaxyNumber === 3 && missionVariables.nova === "TWO_HRS_TO_ZERO") missionVariables.GNN_nova = system.name;
    	};
    	this._addHot = function (o) {
    		var x = { ID: "GNN", Message: o.m, Priority: o.p, Delay: clock.days + 1 };
    		if (o.Model) {
    			x.Model = o.Model;
    			if (o.Spin) x.Spin = o.Spin;
    		}
    		if (o.EX) x.EX = o.EX;
    		if (o.Tex) x.Tex = o.Tex;
    		if (o.Mat) x.Mat = o.Mat;
    		this.$snoop.hot.push(x);
    	};
    	this.shipDockedWithStation = function (st) {
    		if (player.ship.docked) {
    			this._updInterface(st);
    			this._resort();
    		}
    	};
    	this.dayChanged = function (newday) {
    		var x = Math.floor(Math.random() * 100), i, obj, m, k = this.$snoop;
    		for (i = 0; i < k.hot.length; i++) {
    			obj = k.hot[i];
    			if (obj && obj.Delay <= newday) {
    				if (obj.ID === "GNN") {
    					obj.AutoPos = 1;
    					obj.Message = "GNN_" + obj.Message;
    					if (obj.EX) obj.ID = obj.EX;
    				}
    				if (worldScripts[obj.ID]) k.fifo.push(obj);
    				else k.unused.push(obj);
    				k.hot[i] = null;
    				k.hot = this._aid.arrOmit(k.hot, null);
    				i--;
    			}
    		}
    		if (k.hot.length) k.hot = this._aid.arrOmit(k.hot, null);
    		if (k.fifo.length < 3) {
    			if (newday > k.nextNews) {
    				switch (x) {
    					case 5: m = "GNN_A"; break;
    					case 9: m = "GNN_B"; break;
    					case 13: m = "GNN_C"; break;
    					case 17: m = "GNN_D"; break;
    					default: m = "Intern";
    				}
    				k.fifo.push({ ID: "GNN", Message: m, Priority: 5 });
    				k.nextNews = newday + this._aid.randXY(Math.floor(k.maxDays / 2), k.maxDays);
    			}
    		}
    		if (player.ship.docked) this._updInterface(player.ship.dockedStation);
    	};
    	this._doScreen = function () { worldScripts.GNN.$doop.hud = player.ship.hudHidden; player.ship.hudHidden = true; worldScripts.GNN._showScreen(); return; };
    	this._showScreen = function (obj) {
    		if (!player.ship.docked || system.isInterstellarSpace) return false;
    		var what, ret, ws;
    		var head = {
    			choices: { BACK: expandMissionText("GNN_back") },
    			exitScreen: "GUI_SCREEN_INTERFACES",
    			message: expandMissionText("GNN_no_news"),
    			model: "lib_ms_helper",
    			music: "GNN.ogg",
    			overlay: { name: "GNN_clean.png", height: 512 },
    			screenID: this.name,
    			spinModel: false,
    			title: ""
    		};
    		if (obj) { // Direct
    			if (this._aid.typeGet(obj) !== "object" || !obj.ID || !obj.Message) return false;
    			var news = this._setStandards(obj);
    			this._showInserted(head, news);
    		} else {
    			if (this.$snoop.fifo.length) {
    				if (this.$snoop.fifo.length > 1) {
    					head.choices.NEXT = expandMissionText("GNN_next_message");
    					head.initialChoicesKey = "NEXT";
    				}
    				what = this.$snoop.fifo[0];
    				if (what.ID === "GNN") {
    					switch (what.Message) {
    						case "Intern": ret = this._showInternal(head); break;
    						case "GNN_A":
    						case "GNN_B":
    						case "GNN_C":
    						case "GNN_D": ret = this._showInternal(head, what.Message); break;
    						default: ret = this._showInserted(head, what); break;
    					}
    				} else ret = this._showInserted(head, what);
    			} else return false;
    		}
    		if (ret) {
    			this.$snoop.fifo.shift();
    			this._updInterface(player.ship.dockedStation);
    			if (what.CB) {
    				ws = worldScripts[what.ID];
    				if (what.CBID) this._aid.objPass(ws, what.CB, what.CBID);
    				else this._aid.objPass(ws, what.CB, what.Message);
    			}
    		}
    		return true;
    	};
    	this._setHead = function (head, obj) {
    		var em, extI, ov, r, txt;
    		if (obj.Agency) {
    			switch (obj.Agency) {
    				case 1: ov = "A1" + this._aid.randXY(1, 4); em = 1; break;
    				case 2: ov = "A2" + this._aid.randXY(1, 4); em = 2; break;
    				case 3: ov = "A3" + this._aid.randXY(1, 3); em = 3; break;
    				default: ov = "A4" + this._aid.randXY(1, 4); em = 4; break;
    			}
    		} else if (obj.Pic) {
    			// External image pack?
    			if (obj.PicExt) {
    				if (this.$doop.expPrefixes.indexOf(obj.PicExt) !== -1) head.overlay = obj.Pic;
    			} else head.overlay = obj.Pic;
    		}
    		if (ov) {
    			// Expanded image pool
    			extI = this.$doop.expImages[em - 1];
    			if (extI.length && Math.random() > 0.5) {
    				r = this._aid.randXY(0, extI.length - 1);
    				head.overlay = { name: extI[r], height: 512 };
    			} else head.overlay.name = "GNN_" + ov + ".png";
    		}
    		if (obj.Music) head.music = obj.Music;
    		if (!this.$snoop.audio) head.music = null;
    		txt = expandMissionText(obj.Message);
    		if (obj.DKey) txt = expandDescription(obj.Message);
    		if (!txt) txt = obj.Message;
    		worldScripts.Lib_PAD.$config.last.news = txt;
    		this._addNewsHistory(txt);
    		head.message = "\n\n\n\n\n\n\n\n" + txt;
    		if (obj.Model) {
    			head.model = obj.Model;
    			if (obj.Spin) head.spinModel = true;
    		}
    		return head;
    	};
    	this._setModelDef = function (obj, em) {
    		var md = mission.displayModel, pa, pb, d, n;
    		if (md) {
    			if (obj.Pos) md.position = obj.Pos;
    			if (em) this._aid.setMaterials(md, { mat: { "lib_null.png": { emission_map: "GNN_" + em + ".png", fragment_shader: "GNN_" + em + ".fs", vertex_shader: "lib_simple.vs", textures: [{ name: "GNN_" + em + ".png", repeat_s: true, repeat_t: true }, { name: "GNN_blur.png", repeat_s: true, repeat_t: true }], uniforms: { colorMap: { type: "texture", value: 0 }, fxMap: { type: "texture", value: 1 }, Time: "timeElapsedSinceSpawn" } } } });
    			if (obj.Tex) this._aid.setMaterials(md, { mat: { "lib_null.png": { emission_map: obj.Tex } } });
    			if (obj.Mat) this._aid.setMaterials(md, { mat: obj.Mat });
    			if (obj.AutoPos) {
    				pa = md.position;
    				pb = new Vector3D([28.4, 20.2, 84]);
    				d = pa.z * 2.5 / pb.z;
    				if (md.name === "lib_ms_helper") d = 1;
    				n = [pb.x * d, pb.y * d, pb.z * d];
    				md.position = n;
    				md.orientation = [1, 0, 0, 0];
    			}
    			if (obj.Ori) md.orientation = obj.Ori;
    		}
    	};
    	this._showInserted = function (head, obj) {
    		head = this._setHead(head, obj);
    		mission.runScreen(head, this._choices);
    		if (obj.Model) this._setModelDef(obj);
    		else this._setModelDef(obj, obj.Agency ? obj.Agency : 1);
    		return 1;
    	};
    	this._showInternal = function (head, gen) {
    		var em, n, nstr, ov, r, txt, extI;
    		if (gen) {
    			ov = "A1" + this._aid.randXY(1, 4);
    			em = 1;
    			txt = worldScripts.GNN_PhraseGen._makePhrase(gen);
    		} else {
    			n = this._aid.randXY(1, this.$doop.intern);
    			nstr = this._aid.toNLZ(n, 4);
    			txt = expandMissionText("GNN_" + nstr);
    			if (txt[0] === "#") {
    				switch (txt[1]) {
    					case "1": ov = "A1" + this._aid.randXY(1, 4); em = 1; break;
    					case "2": ov = "A2" + this._aid.randXY(1, 4); em = 2; break;
    					case "3": ov = "A3" + this._aid.randXY(1, 3); em = 3; break;
    					default: ov = "A4" + this._aid.randXY(1, 4); em = 4; break;
    				}
    				txt = txt.substr(2);
    			} else {
    				ov = "A4" + this._aid.randXY(1, 4);
    				em = 4;
    			}
    		}
    		// Expanded image pool
    		extI = this.$doop.expImages[em - 1];
    		if (extI.length && Math.random() > 0.5) {
    			r = this._aid.randXY(0, extI.length - 1);
    			head.overlay = { name: extI[r], height: 512 };
    		} else head.overlay = { name: "GNN_" + ov + ".png", height: 512 };
    		head.message = "\n\n\n\n\n\n\n\n" + txt;
    		worldScripts.Lib_PAD.$config.last.news = txt;
    		this._addNewsHistory(txt);
    		if (!this.$snoop.audio) head.music = null;
    		mission.runScreen(head, this._choices);
    		this._setModelDef({ AutoPos: 1 }, em);
    		return 1;
    	};
    	this._choices = function (choice) {
    		switch (choice) {
    			case "NEXT": worldScripts.GNN._showScreen(); break;
    			case "BACK": player.ship.hudHidden = worldScripts.GNN.$doop.hud;
    		}
    	};
    	this._updInterface = function (st) {
    		if ((st.isMainStation || (st.scriptInfo && st.scriptInfo.GNN) || st.hasNPCTraffic) && !system.isInterstellarSpace) {
    			if (this.$snoop.fifo.length) {
    				player.ship.dockedStation.setInterface("GNN", {
    					title: expandMissionText("GNN_news", {avail: this.$snoop.fifo.length}),
    					category: expandMissionText("GNN_news_category"),
    					summary: expandMissionText("GNN_news_summary"),
    					callback: this._doScreen.bind(this)
    				}
    				);
    			} else player.ship.dockedStation.setInterface("GNN", null);
    		}
    	};
    	this._setStandards = function (obj) {
    		var o = this._aid.objClone(obj);
    		if (o.Agency) o.Pic = null;
    		if (!o.Priority) o.Priority = 3;
    		if (o.Model) o.Tex = null;
    		else {
    			o.Ori = null;
    			o.Pos = null;
    		}
    		if (!o.Pos) o.AutoPos = 1;
    		return o;
    	};
    	this._insertNews = function (obj) {
    		if (this._aid.typeGet(obj) !== "object" || !obj.ID || !obj.Message) return 1;
    		var news = this._setStandards(obj), no, i;
    		if (news.Delay) {
    			for (i = 0; i < this.$snoop.hot.length; i++) {
    				if (this.$snoop.hot[i].ID === obj.ID && this.$snoop.hot[i].Message === obj.Message) no = 1;
    			}
    			if (!no) {
    				news.Delay += clock.days;
    				this.$snoop.hot.push(news);
    			}
    		} else {
    			for (i = 0; i < this.$snoop.fifo.length; i++) {
    				if (this.$snoop.fifo[i].ID === obj.ID && this.$snoop.fifo[i].Message === obj.Message) no = 1;
    			}
    			if (!no) {
    				this.$snoop.fifo.push(news);
    				if (player.ship.docked) {
    					this._resort();
    					this._updInterface(player.ship.dockedStation);
    				}
    			}
    		}
    		return 0;
    	};
    	this._addNewsHistory = function(txt) {
    		var time = clock.clockStringForTime(clock.adjustedSeconds);
    		if (time == this._lastTime) {
    			if (!this._counter) this._counter = 0;
    			this._counter += 1;
    			time = time + " (" + this._counter + ")";
    		} else {
    			this._lastTime = time;
    			this._counter = 0;
    		}
    		worldScripts.Lib_PAD._addPageInCategory("NEWS_HISTORY." + time, {entry:clock.clockStringForTime(clock.adjustedSeconds), text:txt}, null, true);
    		worldScripts.Lib_PAD._cullNewsHistory(this.$snoop.newsHistory);
    	}
    	this._resort = function () {
    		if (this.$snoop.fifo.length > 1) this.$snoop.fifo = this._aid.arrSortBy(this.$snoop.fifo, 'Priority');
    	};
    	this._addExtImages = function (arr, ws) {
    		if (this._aid.typeGet(arr) !== "array" || typeof (ws) !== "string") return false;
    		this.$doop.expImages = this._aid.arrConcat(this.$doop.expImages, arr);
    		this.$doop.expPrefixes.push(ws);
    		return true;
    	};
    	this._Help = function (what) {
    		var h;
    		switch (what) {
    			case "_insertNews": h = "GNN_HELP_insertNews"; break;
    			case "_showScreen": h = "GNN_HELP_showScreen"; break;
    			case "_addExtImages": h = "GNN_HELP_addExtImages"; break;
    			default: h = "GNN_HELP";
    		}
    		return expandMissionText(h);
    	};
    }).call(this);
    
    Scripts/GNN_PhraseGen.js
    /* jshint bitwise:false, forin:false */
    /* global clock,expandDescription,expandMissionText,galaxyNumber,log,player,system,worldScripts,System,Timer */
    /* (C) Disembodied and Svengali 2009-2018, License CC-by-nc-sa-4.0 */
    (function () {
    	"use strict";
    	this.name = "GNN_PhraseGen";
    
    	this.$recGuard = true;
    	this.$galaxyStats = [];
    	this.startUp = function () {
    		delete this.startUp;
    		this.$init = true;
    		this.$spec = {
    			currentSystem: {},
    			rndBrew: [],
    			rndFirstName: [],
    			rndShipName: [],
    			rndSurName: [],
    			rndSystem: [],
    			idsA: ["I", "II", "III", "IV", "V", "VI", "VII", "IX", "X"],
    			idsB: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"],
    			idsC: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
    		};
    		this.$pool = worldScripts.GNN_Words.pool;
    		this.$irNouns = worldScripts.GNN_Words.irregularNouns;
    		this.$irVerbs = worldScripts.GNN_Words.irregularVerbs;
    		this.$suptive = worldScripts.GNN_Words.superlatives;
    		this._getGalaxy();
    		this._fillInBits(1);
    	};
    	/* Experimental
    	this.startUpComplete = function(){
    		var d = "",s;
    		for(var i=0;i<256;i++){
    			s = this.$galaxyStats[i];
    			d += s.name+"|"+s.description+"#";
    		}
    		worldScripts.Lib_PAD._addPageInCategory("SYSTEMS.ALMANACH",{$hide:d});
    	};
    	*/
    	// Entry point for OXPs.
    	this._makePhrase = function (set, pattern, store, seed, cst, keepRnd) {
    		if (!set) return (false);
    		if (typeof (set) === 'object') this.$stdObj = set;
    		else {
    			if (typeof (this.$pool[set]) === 'undefined') return false;
    			this.$stdObj = this.$pool[set];
    		}
    		var option = {
    			patt: null,
    			store: 0,
    			seed: 0,
    			cst: []
    		};
    		if (typeof (pattern) !== 'undefined') option.patt = pattern;
    		if (store) option.store = true;
    		if (seed) option.seed = seed;
    		if (cst) option.cst = cst;
    		if (seed) {
    			if (!keepRnd) this._setupRandomGenerator(seed);
    			this.$salt = seed;
    		} else {
    			this.$salt = 0;
    		}
    		var t = this._buildPhrase(option.patt, option.store, option.seed, option.cst);
    		return t;
    	};
    	this._setupRandomGenerator = function(seed) {
    		this.$seedSet = seed;
    		function sfc32(a, b, c, d) {
    			return function () {
    				a |= 0; b |= 0; c |= 0; d |= 0;
    				let t = (a + b | 0) + d | 0;
    				d = d + 1 | 0;
    				a = b ^ b >>> 9;
    				b = c + (c << 3) | 0;
    				c = (c << 21 | c >>> 11);
    				c = c + t | 0;
    				return (t >>> 0) / 4294967296;
    			}
    		}
    		var seedgen = [3];
    		for (var i = 0; i < 4; i++) seedgen[i] = (Math.pow(Math.random() * 2, 32)) >>> 0;
    		if (seed) {
    			for (var i = 0; i < 4; i++) {
    				seed *= 5;
    				seedgen[i] = (seed) >>> 0;
    			}
    		}
    		this._getRand = sfc32(seedgen[0], seedgen[1], seedgen[2], seedgen[3]);
    	}
    	// Entry point for OXPs.
    	this._addSample = function (samplename, obj, clone) {
    		if (typeof (obj) !== 'object' || typeof (samplename) !== 'string' || typeof (this.$pool[samplename]) !== 'undefined') return false;
    		if (clone) this.$pool[samplename] = this._cloneObj(obj);
    		else this.$pool[samplename] = obj;
    		return true;
    	};
    	this._fillInBits = function (rep) {
    		this.$spec.rndBrew = [];
    		this.$spec.rndFirstName = [];
    		this.$spec.rndShipName = [];
    		this.$spec.rndSurName = [];
    		if (rep) this.$spec.rndSystem = this.$galaxyStats;
    		this._setCur();
    		this.$spec.rndFirstName.push(this._makePhrase("GNN_Names", "1"));
    		this.$spec.rndFirstName.push(this._makePhrase("GNN_Names", "2"));
    		this.$spec.rndFirstName.push(this._makePhrase("GNN_Names", "12"));
    		this.$spec.rndSurName.push(this._makePhrase("GNN_Names", "{1"));
    		this.$spec.rndSurName.push(this._makePhrase("GNN_Names", "{1"));
    		this.$spec.rndSurName.push(this._makePhrase("GNN_Names", "{1"));
    		this.$spec.rndBrew.push(this._makePhrase("GNN_NamesBrews"));
    		this.$spec.rndShipName.push(this._makePhrase("GNN_NamesShips"));
    		delete this.$init;
    	};
    	this._setCur = function () {
    		if (system.isInterstellarSpace) this.$spec.currentSystem = { description: "interstellar", economy: -1, government: -1, ID: -1, inhabitant: "none", name: "interstellar", population: -1, productivity: -1, radius: -1, sun: false, techlevel: -1 };
    		else this.$spec.currentSystem = this.$galaxyStats[system.ID];
    	};
    	this.shipWillDockWithStation = function () {
    		if (!system.isInterstellarSpace) this._fillInBits();
    	};
    	this.shipWillLaunchFromStation = function () {
    		this._setCur();
    	};
    	this.playerEnteredNewGalaxy = function () {
    		this.$init = true;
    		this._getGalaxy();
    		this._fillInBits(1);
    	};
    	this.shipWillExitWitchspace = function () {
    		if (this.$init) return;
    		this._setCur();
    	};
    	this.$stdObj = {
    		fieldA: [], fieldB: [], fieldC: [], fieldD: [], fieldE: [], fieldF: [], fieldG: [], fieldH: [], fieldI: [],
    		fieldJ: [], fieldK: [], fieldL: [], fieldM: [], fieldN: [], fieldO: [], fieldP: [], fieldQ: [], fieldR: [],
    		sentences: [], custom: [], splitRules: []
    	};
    	this.$fields = [["fieldA", "fieldJ"], ["fieldB", "fieldK"], ["fieldC", "fieldL"], ["fieldD", "fieldM"],
    	["fieldE", "fieldN"], ["fieldF", "fieldO"], ["fieldG", "fieldP"], ["fieldH", "fieldQ"], ["fieldI", "fieldR"]];
    	this._cloneObj = function (srcInstance) {
    		if (typeof (srcInstance) !== 'object' || srcInstance === null) return srcInstance;
    		var newInstance = srcInstance.constructor();
    		for (var i in srcInstance) newInstance[i] = this._cloneObj(srcInstance[i]);
    		return newInstance;
    	};
    	this._random = function (maxnum) {
    		if (!this.$salt) {
    			return maxnum * (Math.random() % 1) | 0;
    		} else {
    			return maxnum * (this._getRand() % 1) | 0;
    		}
    	};
    	// Random number in range a-b in steps of s
    	this._rndRange = function (a, b, s) {
    		var x = this._getRand(); //Math.random();
    		var y = (b * x) - (a * x) + 1;
    		if (!y) return a;
    		var z = Math.floor(y / s);
    		return a + z * s;
    	};
    	// First letter uppercase
    	this._initialCap = function (str) {
    		if (!str) return "";
    		return str[0].toUpperCase() + str.substr(1);
    	};
    	// Rules
    	this._makePlural = function (word) {
    		// e,f,h,o,s,x,y
    		if (/[^es]s$/.test(word)) return word;
    		if (/fe$/.test(word)) return word.replace(/fe$/, "ves");
    		if (/e$/.test(word)) return word + "s";
    		if (/(?:[^ei]x|[^o]o|[es]s|[cs]h)$/.test(word)) return word + "es";
    		if (/s$/.test(word)) return word;
    		if (/[^aeou]y$/.test(word)) return word.replace(/y$/, "ies");
    		if (/[^erf]f$/.test(word)) return word.replace(/f$/, "ves");
    		if (/[ei]x$/.test(word)) return word.replace(/[ei]x$/, "ices");
    		return word + "s";
    	};
    	// Rules
    	this._makePast = function (word) {
    		// b,e,l,p,y
    		if (/e$/.test(word)) return word + "d";
    		if (/[^aeou]y$/.test(word)) return word.replace(/y$/, "ied");
    		if (/[^adeliosy][aeioy][bcdfgjklmnpqrsvz]$/.test(word)) return word + word[word.length - 1] + "ed";
    		return word + "ed";
    	};
    	this._makeVerbPhrase = function (word, tense, markPlural) {
    		var wsp = word.split(" ");
    		var wspl = wsp.length;
    		for (var i = 0; i < wspl; i++) {
    			var t = wsp[i].match(/[\$&]/g);
    			if (t && t.length) {
    				var raw = wsp[i].replace(/[\$&]/g, ""), flagP, flagS, flagH, flagI;
    				var ex = raw.match(/[^A-Za-z=]/g);
    				if (ex) raw = raw.replace(/[^A-Za-z=]/g, "");
    				var tl = t.length;
    				for (var o = 0; o < tl; o++) {
    					switch (t[o]) {
    						case "&":
    							flagI = 1;
    							raw = raw.replace(/=/, " ");
    							if (typeof (this.$irVerbs[raw]) !== 'undefined') raw = this.$irVerbs[raw][(tense < 4 ? tense : 3)];
    							else flagI = 0;
    							break;
    						case "$":
    							switch (tense) {
    								case 0: if (markPlural) flagS = 1; break;
    								case 1: if (!flagI) flagS = 1; break;
    								case 2: flagP = 1; break;
    								case 3: flagP = 1; break;
    								case 4: flagH = 1; flagP = 1; break;
    							}
    							break;
    					}
    				}
    				if (flagS) raw = this._makePlural(raw);
    				if (flagI) flagI = 0;
    				else if (flagP) raw = this._makePast(raw);
    				if (flagH) raw = (markPlural ? "have " : "has ") + raw;
    				if (ex) raw = raw + ex[0];
    				wsp[i] = raw;
    			}
    		}
    		return wsp.join(" ");
    	};
    	this._handleRules = function (wrd, tense, nextPlural, markShift, donot) {
    		if (/[\$$^&]/.test(wrd)) {
    			var irregNoun = 0;
    			// Verbs
    			if (/\$/.test(wrd)) wrd = this._makeVerbPhrase(wrd, tense, nextPlural);
    			else { // Nouns
    				var ex = wrd.match(/[^A-Za-z=]/g);
    				if (ex) wrd = wrd.replace(/[^A-Za-z=&]/g, "");
    				if (/&/g.test(wrd)) {
    					irregNoun = 1;
    					wrd = wrd.replace(/&/, "");
    				}
    				if (nextPlural) {
    					if (irregNoun && typeof (this.$irNouns[wrd]) !== 'undefined') wrd = this.$irNouns[wrd];
    					else wrd = this._makePlural(wrd);
    				}
    				if (ex) wrd = wrd + ex[0];
    			}
    		} else {
    			if (nextPlural && donot < 2) wrd = this._makePlural(wrd);
    		}
    		return wrd;
    	};
    	this._handleCombiners = function (wrd, markShift, rec) {
    		var last = 0;
    		var z = wrd.indexOf("[");
    		var y = wrd.charAt(z + 1);
    		var x = this.$fields[y - 1][markShift];
    		var w = this._getField(x, last, rec);
    		wrd = wrd.replace(/\[\d\]/, w[0]);
    		last = w[1];
    		if (rec < 5) {
    			if (/\[\d\]/g.test(w[0])) {
    				rec++;
    				wrd = this._handleCombiners(wrd, markShift, rec);
    			}
    			rec--;
    			if (/\[\d\]/g.test(wrd)) {
    				rec++;
    				wrd = this._handleCombiners(wrd, markShift, rec);
    			}
    			rec--;
    		} else if (this.$recGuard) log(this.name, "Warning! - FieldCombiner recursion limit.\n\nwrd:" + wrd + " : " + x + " : " + y + " : " + z + " : " + rec);
    		return wrd;
    	};
    	this._handleNV = function (word, tense, nextPlural, markShift) {
    		var wr = word.split(" ");
    		var n = wr.length;
    		for (var i = 0; i < n; i++) {
    			var wrd = wr[i];
    			// field combiner
    			if (/\[\d\]/g.test(wrd)) wrd = this._handleCombiners(wrd, markShift, 0);
    			// Verbs, nouns
    			var c = wrd.split(" ");
    			if (c.length > 1) {
    				var cc = c.length;
    				for (var o = 0; o < cc; o++) {
    					c[o] = this._handleRules(c[o], tense, nextPlural, markShift, cc);
    				}
    				wrd = c.join(" ");
    			} else wrd = this._handleRules(wrd, tense, nextPlural, markShift, n);
    			wrd = wrd.replace(/&$/, "");
    			wr[i] = wrd;
    		}
    		word = wr.join(" ");
    		return word;
    	};
    	this._cmpConditions = function (w, c, v, a) {
    		switch (c) {
    			case "<":
    				if (a < 2) {
    					if (this.$spec.currentSystem[w] < v) return true;
    				} else if (this.$spec.rndSystem[this.$lSys][w] < v) return true;
    				break;
    			case ">":
    				if (a < 2) {
    					if (this.$spec.currentSystem[w] > v) return true;
    				} else if (this.$spec.rndSystem[this.$lSys][w] > v) return true;
    				break;
    			case ":":
    				if (a < 2) {
    					if (this.$spec.currentSystem[w] == v) return true;
    				} else if (this.$spec.rndSystem[this.$lSys][w] == v) return true;
    				break;
    			case "!":
    				if (a < 2) {
    					if (this.$spec.currentSystem[w] != v) return true;
    				} else if (this.$spec.rndSystem[this.$lSys][w] != v) return true;
    				break;
    		}
    		return false;
    	};
    	this._parseConditions = function (wrd, remB) {
    		var left = false, right = false, compare = 1, w = wrd.split(")"), c;
    		var wl = w.length;
    		for (var q = 0; q < wl; q++) {
    			var ex = w[q].match(/\(/g);
    			if (ex) {
    				var exl = ex.length;
    				for (var i = 0; i < exl; i++) {
    					compare = 1;
    					var con = w[q].match(/\(.*/);
    					var act = con[0].split("="); // split conditions from actions (Sg:0,e<5 [4]|[7]
    					switch (act[0].charAt(1)) { // A,B,D,M,P,S,X,Y
    						case "A": compare = 5; break;
    						case "B": compare = 3; break;
    						case "D": compare = 4; break;
    						case "M": return expandMissionText(act[0].substr(3));
    						case "S":
    							compare = 2;
    							// prepare @S
    							if (this.$lSys < 0) this._getRNDSystem();
    							break;
    						case "X": return expandDescription("[" + act[0].substr(3) + "]");
    						case "Y": compare = 6; break;
    					}
    					// conditions
    					switch (compare) {
    						case 1:
    						case 2:
    							c = act[0].substr(2).split(","); // multiple conditions
    							var cl = c.length;
    							for (var u = 0; u < cl; u++) {
    								var cx = c[u][1], cy = c[u].substr(2), cz;
    								switch (c[u][0]) {
    									case "c": cz = "productivity"; break;
    									case "d":
    										var rega = new RegExp(cy, "g");
    										if (compare === 1) left = rega.test(this.$spec.currentSystem.description);
    										else left = rega.test(this.$spec.rndSystem[this.$lSys].description);
    										if (cx === '!') left = !left;
    										break;
    									case "e": cz = "economy"; break;
    									case "g": cz = "government"; break;
    									case "i":
    										var regb = new RegExp(cy, "gi");
    										if (compare === 1) left = regb.test(this.$spec.currentSystem.inhabitant);
    										else left = regb.test(this.$spec.rndSystem[this.$lSys].inhabitant);
    										if (cx === '!') left = !left;
    										break;
    									case "p": cz = "population"; break;
    									case "r": cz = "radius"; break;
    									case "s": cz = "sun"; break;
    									case "t": cz = "techlevel"; break;
    								}
    								if (cz) left = this._cmpConditions(cz, cx, cy, compare);
    								if (!left) break;
    							}
    							break;
    						case 3: //Bits
    							c = act[0].substr(2);
    							var bitID = parseInt(c) % 30;
    							if (act.length < 2) {
    								if (c[c.length - 1] === "+") {
    									this.$bits |= (1 << bitID);
    									left = true;
    								} else if (c[c.length - 1] === "-") {
    									this.$bits &= ~(1 << bitID);
    									left = true;
    								}
    							}
    							if ((this.$bits & (1 << bitID)) != 0) left = true;
    							break;
    						case 4: //Dice
    							c = act[0].substr(2);
    							if (act.length < 2) {
    								var ns = c.split(",");
    								right = this._rndRange(+ns[0], +ns[1], +ns[2]);
    								left = true;
    							} else {
    								if (c > Math.floor(this._getRand() * 100)) left = true;
    							}
    							break;
    						case 5: //All
    							c = parseInt(act[0].substr(2));
    							if ((this.$bits & c) === c) left = true;
    							break;
    						case 6: //Any
    							c = parseInt(act[0].substr(2));
    							if (this.$bits & c) left = true;
    							break;
    					}
    					// actions
    					if (act.length > 1) {
    						var acc = act[1].split("|");
    						if (!left) {
    							if (acc.length > 1) right = acc[1];
    						} else right = acc[0];
    					}
    					if (right) w[q] = w[q].replace(/\(.*/, right);
    					else w[q] = w[q].replace(/\(.*/, "");
    				}
    			}
    		}
    		wrd = w.join("");
    		if (remB) wrd = wrd.replace(/[\[\]]/g, "");
    		return wrd;
    	};
    	this._getField = function (field, last, rec) {
    		var sp = this.$stdObj[field].length;
    		var r = this._random(sp);
    		if (r === last) r = this._random(sp);
    		if (rec) {
    			if (rec === 5) r = sp - 1;
    			else r = (r + rec) % sp;
    		}
    		var wrd = this.$stdObj[field][r];
    		if (/\([ABDMPSXY]/g.test(wrd)) wrd = this._parseConditions(wrd);
    		return ([wrd, r]);
    	};
    	this._getRNDSystem = function () {
    		var sp = this.$spec.rndSystem.length, r;
    		r = this._random(sp);
    		var reselect = 0;
    		while (r === this.$lSys) {
    			r = this._random(sp);
    			reselect++;
    			if (reselect > 10) break;
    		}
    		//}
    		this.$lSys = r;
    		return r;
    	};
    	this._buildPhrase = function (OXPPattern, store, sd, cst, cpf, foo) {
    		var pattern, cp = -1;
    		if (OXPPattern) {
    			if (typeof (OXPPattern) === 'object') {
    				cp = this._random(OXPPattern.length);
    				pattern = OXPPattern[cp];
    			} else {
    				cp = 0;
    				pattern = OXPPattern;
    			}
    		} else {
    			cp = this._random(this.$stdObj.sentences.length);
    			pattern = this.$stdObj.sentences[cp];
    		}
    		var aFlag = 0, markShift = 0, tense = 0, nextPlural = 0, nextSpecial = 0, nextUpper = 1;
    		var lastA = -1, lastB = -1, lastC = -1, lastD = -1, lastE = -1, lastF = -1, lastG = -1, lastH = -1, lastI = -1;
    		var info = { num: "" }, za = [], zb = 0, zc = [], zd = 0, wOffset = 0, lasts;
    		if (!foo) {
    			this.$lSys = -1;
    			this.$bits = 0;
    			this.$limit = 0;
    			if (this.$stdObj.custom && this.$stdObj.custom.length) {
    				if (!cst) this.$bits = this.$stdObj.custom[0];
    				else {
    					this.$bits = cst[0];
    					this.$stdObj.custom = cst;
    				}
    			}
    			lasts = { rndBrew: [], rndFirstName: [], rndSurName: [], rndShipName: [], rndSystem: [], rndTitle: [], lastWords: [] };
    		} else {
    			lasts = foo;
    			wOffset = foo.lastWords.length;
    			nextUpper = 0;
    		}
    		if (/\([ABDMPSXY]/g.test(pattern)) {
    			za = pattern.match(/\([a-zA-Z0-9,:!><=\)\[\]\| @\+-_\{\}]+\)/g);
    			pattern = pattern.replace(/\([a-zA-Z0-9,:!><=\)\[\]\| @\+-_\{\}]+\)/g, "@?");
    		}
    		if (/\[[a-zA-Z_]+\]/g.test(pattern)) {
    			zc = pattern.match(/\[[a-zA-Z_]+\]/g);
    			pattern = pattern.replace(/\[[a-zA-Z_]+\]/g, "@[");
    		}
    		pattern = pattern.split(" ");
    		var denpat = pattern.length, r = -1, tmp = null;
    		for (var p = 0; p < denpat; p++) {
    			var lenpat = pattern[p].length, txt = "", wrd = "", pushit = 0;
    			for (var ichr = 0; ichr < lenpat; ichr++) {
    				var chr = pattern[p].charAt(ichr);
    				if (!nextSpecial) {
    					switch (chr) {
    						case '@': nextSpecial = 1; continue;
    						case '1':
    							tmp = this._getField(this.$fields[0][markShift], lastA);
    							wrd = tmp[0]; lastA = tmp[1]; pushit = 1;
    							wrd = this._handleNV(wrd, tense, nextPlural, markShift);
    							break;
    						case '2':
    							tmp = this._getField(this.$fields[1][markShift], lastB);
    							wrd = tmp[0]; lastB = tmp[1]; pushit = 1;
    							wrd = this._handleNV(wrd, tense, nextPlural, markShift);
    							break;
    						case '3':
    							tmp = this._getField(this.$fields[2][markShift], lastC);
    							wrd = tmp[0]; lastC = tmp[1]; pushit = 1;
    							wrd = this._handleNV(wrd, tense, nextPlural, markShift);
    							break;
    						case '4':
    							tmp = this._getField(this.$fields[3][markShift], lastD);
    							wrd = tmp[0]; lastD = tmp[1]; pushit = 1;
    							wrd = this._handleNV(wrd, tense, nextPlural, markShift);
    							break;
    						case '5':
    							tmp = this._getField(this.$fields[4][markShift], lastE);
    							wrd = tmp[0]; lastE = tmp[1]; pushit = 1;
    							wrd = this._handleNV(wrd, tense, nextPlural, markShift);
    							break;
    						case '6':
    							tmp = this._getField(this.$fields[5][markShift], lastF);
    							wrd = tmp[0]; lastF = tmp[1]; pushit = 1;
    							wrd = this._handleNV(wrd, tense, nextPlural, markShift);
    							break;
    						case '7':
    							tmp = this._getField(this.$fields[6][markShift], lastG);
    							wrd = tmp[0]; lastG = tmp[1]; pushit = 1;
    							wrd = this._handleNV(wrd, tense, nextPlural, markShift);
    							break;
    						case '8':
    							tmp = this._getField(this.$fields[7][markShift], lastH);
    							wrd = tmp[0]; lastH = tmp[1]; pushit = 1;
    							wrd = this._handleNV(wrd, tense, nextPlural, markShift);
    							break;
    						case '9':
    							tmp = this._getField(this.$fields[8][markShift], lastI);
    							wrd = tmp[0]; lastI = tmp[1]; pushit = 1;
    							wrd = this._handleNV(wrd, tense, nextPlural, markShift);
    							break;
    						case '.': wrd = chr; nextUpper = 2; break;
    						case '!': wrd = chr; nextUpper = 2; break;
    						case '?': wrd = chr; nextUpper = 2; break;
    						case '#': tense = 1; continue;
    						case '_': tense = 2; continue;
    						case '^': tense = 3; continue;
    						case '*': tense = 4; continue;
    						case '>': nextPlural = 1; continue;
    						case '<': nextPlural = 0; continue;
    						case '|': nextPlural = (this._getRand() > 0.5 ? 1 : 0); continue;
    						case '+': nextUpper = 1; continue;
    						case '{': markShift = 1; continue;
    						case '}': markShift = 0; continue;
    						default: wrd = chr;
    					}
    					if (pushit && store) {
    						if (info[p]) info[p] += wrd;
    						else info[p] = wrd;
    					}
    					tense = 0; nextPlural = 0;
    				} else { // @
    					var where = "", sys = false, ovr = false, spc;
    					switch (chr) {
    						case 'a':
    							r = this._random(this.$spec.idsA.length);
    							wrd = this.$spec.idsA[r];
    							if (store) info.num += wrd;
    							break;
    						case 'B': wrd = player.bounty + " Cr"; break;
    						case 'b':
    							r = this._random(this.$spec.idsB.length);
    							wrd = this.$spec.idsB[r];
    							if (store) info.num += wrd;
    							break;
    						case 'C': wrd = player.name; break;
    						case 'c':
    							r = this._random(this.$spec.idsC.length);
    							wrd = this.$spec.idsC[r];
    							if (store) info.num += wrd;
    							break;
    						case 'D': wrd = player.ship.displayName; break;
    						case 'd': wrd = String(clock.days - Math.floor(this._getRand() * 7)); break;
    						case 'F':
    							where = "rndFirstName";
    							break;
    						case 'f':
    							if (lasts.rndFirstName.length) {
    								if (+pattern[p].charAt(ichr + 1) + 1) { // trickery
    									wrd = lasts.rndFirstName[+pattern[p].charAt(ichr + 1)];
    									ichr++;
    								} else wrd = lasts.rndFirstName[lasts.rndFirstName.length - 1];
    							} else where = "rndFirstName";
    							break;
    						case 'h':
    							if (this.$lSys < 0) r = this._getRNDSystem();
    							wrd = this.$spec.rndSystem[this.$lSys].inhabitant.toLowerCase();
    							lasts.lastWords.push(wrd);
    							if (store) info.lastInhabitant = wrd;
    							break;
    						case 'I': wrd = player.ship.name; break;
    						case 'i':
    							if (lasts.rndShipName.length) {
    								if (+pattern[p].charAt(ichr + 1) + 1) { // trickery
    									wrd = lasts.rndShipName[+pattern[p].charAt(ichr + 1)];
    									ichr++;
    								} else wrd = lasts.rndShipName[lasts.rndShipName.length - 1];
    							} else where = "rndShipName";
    							break;
    						case 'L': wrd = player.legalStatus; break;
    						case 'N':
    							where = "rndSurName";
    							break;
    						case 'n':
    							if (lasts.rndSurName.length) {
    								if (+pattern[p].charAt(ichr + 1) + 1) { // trickery
    									wrd = lasts.rndSurName[+pattern[p].charAt(ichr + 1)];
    									ichr++;
    								} else wrd = lasts.rndSurName[lasts.rndSurName.length - 1];
    							} else where = "rndSurName";
    							break;
    						case 'P':
    							wrd = this.$spec.currentSystem.name;
    							if (store) info.currentSystemName = wrd;
    							break;
    						case 'R': wrd = player.rank; break;
    						case 'S':
    							sys = true;
    							ovr = true;
    							where = "rndSystem";
    							break;
    						case 's':
    							sys = true;
    							where = "rndSystem";
    							break;
    						case 'T': wrd = (player.ship.target ? player.ship.target.name : ""); break;
    						case 'W':
    							wrd = this._parseConditions("(Si:human=[GNN_Names]|[GNN_NamesOther])");
    							if (this.$limit < 3) {
    								this.$limit++;
    								var wwa = this.$stdObj;
    								this.$stdObj = this.$pool[wrd.substr(1, wrd.length - 2)];
    								wrd = this._buildPhrase(null, 0, sd, 0, 0, lasts);
    								if (!this.$stdObj.splitRules) lasts.lastWords.push(wrd);
    								this.$stdObj = wwa;
    								if (store) info[p] = wrd;
    								this.$limit--;
    							}
    							break;
    						case 'X':
    							if (this.$lSys < 0) r = this._getRNDSystem();
    							break;
    						case 'Y':
    							if (this.$stdObj.custom) {
    								if (+pattern[p].charAt(ichr + 1) + 1) { // trickery
    									wrd = this.$stdObj.custom[+pattern[p].charAt(ichr + 1)];
    									ichr++;
    								}
    							}
    							break;
    						case 'Z':
    							where = "rndBrew";
    							break;
    						case 'z':
    							if (lasts.rndBrew.length) {
    								if (+pattern[p].charAt(ichr + 1) + 1) { // trickery
    									wrd = lasts.rndBrew[+pattern[p].charAt(ichr + 1)];
    									ichr++;
    								} else wrd = lasts.rndBrew[lasts.rndBrew.length - 1];
    							} else where = "rndBrew";
    							break;
    						case '0':
    						case '1':
    						case '2':
    						case '3':
    						case '4':
    						case '5':
    						case '6':
    						case '7':
    						case '8':
    						case '9':
    							if (foo) {
    								if (lasts.lastWords.length > chr) wrd = lasts.lastWords[+chr + wOffset];
    							} else {
    								if (lasts.lastWords.length > chr) wrd = lasts.lastWords[+chr];
    							}
    							break;
    						case '?':
    							var zla;
    							wrd = this._parseConditions(za[zb]);
    							if (wrd.charAt(0) === " ") {
    								spc = 1;
    								wrd = wrd.trim();
    							}
    							if (/\[\d\]/.test(wrd)) wrd = this._handleCombiners(wrd, markShift, 0);
    							wrd = this._handleNV(wrd, tense, nextPlural, markShift);
    							if (this.$limit < 3 && /\[[a-zA-Z_]+\]/.test(wrd)) {
    								zla = wrd.substr(1, wrd.length - 2);
    								if (this.$pool[zla]) {
    									this.$limit++;
    									var wwb = this.$stdObj;
    									this.$stdObj = this.$pool[zla];
    									wrd = this._buildPhrase(null, 0, sd, 0, 0, lasts);
    									if (!this.$stdObj.splitRules) lasts.lastWords.push(wrd);
    									this.$stdObj = wwb;
    									if (store) info[p] = wrd;
    									wOffset = 0;
    									this.$limit--;
    								}
    							} else if (/[\{\}]/.test(wrd)) {
    								if (wrd === "{") markShift = 1;
    								if (wrd === "}") markShift = 0;
    								wrd = wrd.substr(1);
    							} else {
    								if (this.$limit > 2) {
    									if (this.$recGuard) log(this.name, "Warning! - Sample recursion limit. " + zla);
    								}
    								if (!this.$stdObj.splitRules) if (wrd) lasts.lastWords.push(wrd);
    							}
    							if (spc) wrd = " " + wrd;
    							zb++;
    							break;
    						case '[':
    							var zlb = zc[zd];
    							var zk = zlb.substr(1, zlb.length - 2);
    							if (this.$limit < 3 && this.$pool[zk]) {
    								this.$limit++;
    								var wwc = this.$stdObj;
    								this.$stdObj = this.$pool[zk];
    								wrd = this._buildPhrase(null, 0, sd, 0, 0, lasts);
    								if (!this.$stdObj.splitRules) lasts.lastWords.push(wrd);
    								this.$stdObj = wwc;
    								if (store) info[p] = wrd;
    								this.$limit--;
    							} else {
    								if (this.$limit > 2) {
    									if (this.$recGuard) log(this.name, "Warning! - Sample recursion limit. " + zlb);
    									wrd = zlb;
    								}
    							}
    							zd++;
    							break;
    						default: wrd = chr;
    					}
    					if (where) {
    						if (sys) {
    							if (ovr || (sys && this.$lSys < 0)) r = this._getRNDSystem();
    							wrd = this.$spec[where][this.$lSys].name;
    							if (nextPlural) {
    								wrd = this._makePlural(wrd);
    								nextPlural = 0;
    							}
    						} else {
    							r = this._random(this.$spec[where].length);
    							wrd = this.$spec[where][r];
    						}
    						lasts[where].push(wrd);
    					}
    					if (wrd && wrd[0] === "@") {
    						pattern[p] = pattern[p].replace(/@\?/, wrd);
    						p--;
    						nextSpecial = 0;
    						continue;
    					}
    					nextSpecial = 0;
    				}
    				if (nextUpper) {
    					if (nextUpper > 1) nextUpper--;
    					else {
    						wrd = this._initialCap(wrd);
    						nextUpper = 0;
    					}
    				}
    				txt += wrd;
    			}
    			pattern[p] = txt;
    			if (txt.length === 1) {
    				if (txt === "a") aFlag = 1;
    				else if (txt === "A") aFlag = 2;
    				else aFlag = 0;
    			} else {
    				if (aFlag) {
    					if (typeof (this.$suptive[txt]) !== 'undefined') {
    						var rep = pattern[p - 1].split(" ");
    						if (aFlag > 1) rep[rep.length - 1] = "The";
    						else rep[rep.length - 1] = "the";
    						pattern[p - 1] = rep.join(" ");
    					} else {
    						if (/^[FHLMNRSX][A-Z]/.test(txt)) pattern[p - 1] = pattern[p - 1] + "n"; // a -> an
    						else if (/^u/i.test(txt)) {
    							if (/^u[^aeiou\d\s][^aeiou\d\s]/i.test(txt)) pattern[p - 1] = pattern[p - 1] + "n"; // a -> an
    							else if (/^un[aeou]/i.test(txt)) pattern[p - 1] = pattern[p - 1] + "n"; // a -> an
    							else if (/^uni/i.test(txt) && /^unim|(?:ive|ble)$/i.test(txt)) pattern[p - 1] = pattern[p - 1] + "n"; // a -> an
    						} else {
    							if (/^(?:[aei]|o[^ne]|ho(?:ur|nest|no|mage|mbre|rs d')|he(?:ir|rb))/i.test(txt)) pattern[p - 1] = pattern[p - 1] + "n"; // a -> an
    						}
    					}
    					aFlag = 0;
    				} else if (/\ba\b$/.test(txt)) aFlag = 1;
    			}
    		}
    		if (!foo || (foo && this.$limit === 1)) {
    			if (this.$stdObj.splitRules) {
    				switch (this.$stdObj.splitRules[cp]) {
    					case 1:
    						lasts.rndFirstName.push(pattern[0]);
    						lasts.rndSurName.push(pattern[1]);
    						lasts.rndTitle.push("");
    						break;
    					case 2:
    						lasts.rndSurName.push(pattern[0]);
    						lasts.rndFirstName.push("");
    						lasts.rndTitle.push("");
    						break;
    					case 3:
    						lasts.rndFirstName.push(pattern[0]);
    						lasts.rndTitle.push(pattern[1]);
    						lasts.rndSurName.push(pattern[2]);
    						break;
    					case 4:
    						lasts.rndTitle.push(pattern[0]);
    						lasts.rndFirstName.push(pattern[1]);
    						lasts.rndSurName.push(pattern[2]);
    						break;
    					case 21:
    						lasts.rndShipName.push(pattern.join(" "));
    						break;
    					case 22:
    						lasts.rndBrew.push(pattern.join(" "));
    						break;
    				}
    			}
    		}
    		var fin = pattern.join(" ");
    		if (cpf) {
    			if (store) {
    				info.store = lasts;
    				info.bits = parseInt(this.$bits);
    				return ([fin, info, cp, lasts]);
    			} else return ([fin, cp, lasts]);
    		}
    		if (store) {
    			info.store = lasts;
    			info.bits = parseInt(this.$bits);
    			return ([fin, info]);
    		}
    		return fin;
    	};
    	this.systemInformationChanged = function (gal, sys, key, newValue) {
    		if (gal !== galaxyNumber || !this.$galaxyStats.length || sys < 0 || sys > 255) return;
    		var nope = ["description", "economy", "ID", "government", "inhabitant", "name", "population", "productivity", "radius", "sun_gone_nova", "techlevel"].indexOf(key);
    		if (nope === -1) return;
    		if (key === "sun_gone_nova") this.$galaxyStats[sys].sun = (newValue ? false : true);
    		else this.$galaxyStats[sys][key] = newValue;
    	};
    	// Still slow! The string expansion (descriptions,etc) are eating it up.
    	this._getGalaxy = function () {
    		this.$galaxyStats = [];
    		var gn = galaxyNumber, c, sy;
    		for (var i = 0; i < 256; i++) {
    			c = System.infoForSystem(gn, i);
    			sy = {
    				description: c.description,
    				economy: c.economy,
    				government: c.government,
    				ID: i,
    				inhabitant: c.inhabitant,
    				name: c.name,
    				population: c.population,
    				productivity: c.productivity,
    				radius: c.radius,
    				sun: (c.sun_gone_nova ? false : true),
    				techlevel: c.techlevel
    			};
    			this.$galaxyStats.push(sy);
    		}
    	};
    }).call(this);
    
    Scripts/GNN_Words.js
    /* (C) Disembodied and Svengali 2009-2018, License CC-by-nc-sa-4.0 */
    (function(){
    "use strict";
    this.name = "GNN_Words";
    
    this.pool = {
    	GNN_Blessing:{
    		fieldA: ["(X GNN_wish2)"],
    		fieldB: ["(X GNN_bless1)"],
    		fieldC: ["(X GNN_bless2)"],
    		fieldD: ["(X GNN_bless3)"],
    		fieldE: ["(X GNN_wish3)"],
    		fieldF: ["(X GNN_P009)"],
    		fieldG: [],
    		fieldH: [],
    		fieldI: [],
    		fieldJ: [],
    		fieldK: [],
    		fieldL: [],
    		fieldM: [],
    		fieldN: [],
    		fieldO: [],
    		fieldP: [],
    		fieldQ: [],
    		fieldR: [],
    		sentences: ["+1 [GNN_NamesGods] 2 you!","[GNN_NamesGods] 2 you!","+1 [GNN_NamesGods] 3 5 6!","+1 [GNN_NamesGods] 4 you with 5!"]
    	},
    	GNN_CommWelcome:{
    		fieldA: ["(Y0x30=[2], [7]|[3])"],
    		fieldB: ["(X GNN_status1)"],
    		fieldC: ["(Y0x6=[4].|[5], [6])"],
    		fieldD: ["(X GNN_welcome1)","(X GNN_welcome2)"],
    		fieldE: ["Glad to see you, Sir","It's good that you're here, Commander","(X GNN_welcome1)"],
    		fieldF: ["(Y0x200021=[7]|[8])"],
    		fieldG: ["(X GNN_join1)"],
    		fieldH: ["(X GNN_status2)"],
    		fieldI: ["over."],
    		fieldJ: ["(B7=[2]|[3])"],
    		fieldK: ["Who do you think you are... [9]?","You vicious [8]!","(X GNN_threat2)"],
    		fieldL: ["(Y0x4100=[4]|[5])"],
    		fieldM: ["You stupid [8]!","(X GNN_threat3)"],
    		fieldN: ["(B6=[6],|[7])"],
    		fieldO: ["Bah","Nah","Jeeze","(X GNN_inter1)"],
    		fieldP: ["(X GNN_ask1)","(X GNN_askleave1)"],
    		fieldQ: ["(X GNN_bandit1)"],
    		fieldR: ["(X GNN_bandit2)"],
    		sentences: ["(Y0x50c0={)+1 @Y1, }9","@Y1 here. (Y0x50c0={)+1","(Y0x50c0={)+(B7=[GNN_PirateInsult]|[1]) @Y1, }9"],
    		custom: [0xc0002,"Captain Illych Bartok"],
    		splitRules: []
    	},
    	GNN_Names:{
    		fieldA: ["Aga[8]","Aid[4]","Ala[5]","Al[6]","An[4]","Ar[7]","Ay[4]","Balde[3]","Bal[4]","Bar[5]","Beo[3]","Boro[5]","Bran[3]","Bray[6]","Bra[9]","Bren[9]","Cal[3]","Ced[4]","Clem[9]","Col[3]","Cor[3]","Co[9]","Dago[5]","Dan[7]","Den[9]","Dor[7]","Dor[8]","Drago[5]","Dun[7]","Ed[6]","El[4]","Eme[2]","Eo[7]","Fin[7]","Gala[3]","Gal[4]","Gar[2]","God[9]","Gor[3]","Har[7]","Jeg[3]","Jew[6]","Ker[3]","Mal[3]","Mar[3]","Nor[6]","Palo[5]","Peli[3]","Ran[4]","Rey[6]","Re[4]","Re[7]","Ri[4]","Ro[5]","Ter[2]","Wal[4]","Wes[7]","Wil[6]","Y[3]","(X GNN_names1)","(X GNN_names4)"],
    		fieldB: ["reth","rett","sch"],
    		fieldC: ["(X GNN_syl2)"],
    		fieldD: ["ders","drew","drick","dy","ek","mund","ric"],
    		fieldE: ["bar","man","mir"],
    		fieldF: ["bert","dy","gar","mon","mond"],
    		fieldG: ["gar","ley","mer","n","nall","ward"],
    		fieldH: ["karr","khan","mir","rath","son"],
    		fieldI: ["dall","dan","ders","drick"],
    		fieldJ: ["(X GNN_syl3)"],
    		fieldK: ["(X GNN_syl4)"],
    		fieldL: ["(X GNN_syl5)"],
    		fieldM: ["(X GNN_names13)"],
    		fieldN: ["(X GNN_names14)"],
    		fieldO: ["(X GNN_names15)"],
    		fieldP: [],
    		fieldQ: [],
    		fieldR: [],
    		sentences: ["1 {12","1 {13","1 +{46","1 +{56","1 +{52","1 [GNN_NamesOolite]"],
    		splitRules: [1,1,1,1,1,1]
    	},
    	GNN_NamesBrews:{
    		fieldA: ["(X GNN_brew1)"],
    		fieldB: ["(X GNN_brew2)"],
    		fieldC: ["(X GNN_brew3)"],
    		fieldD: ["(X GNN_brew4)"],
    		fieldE: ["(X GNN_brew5)"],
    		fieldF: [],
    		fieldG: [],
    		fieldH: [],
    		fieldI: [],
    		fieldJ: [],
    		fieldK: [],
    		fieldL: [],
    		fieldM: [],
    		fieldN: [],
    		fieldO: [],
    		fieldP: [],
    		fieldQ: [],
    		fieldR: [],
    		sentences: ["@s's 1 3 4","3 4","3's 5","1 3","2 3 4","2 3's 5","2 1 3"],
    		splitRules: [22,22,22,22,22,22,22]
    	},
    	GNN_NamesGods:{
    		fieldA: ["(X GNN_god4)"],
    		fieldB: ["(X GNN_god5)"],
    		fieldC: ["many","(X GNN_few2)","(X GNN_few3)"],
    		fieldD: ["eyes","heads","hands","horns","limbs","tongues","eggs","hosts"],
    		fieldE: ["eyed","headed","handed","horned"],
    		fieldF: [],
    		fieldG: [],
    		fieldH: [],
    		fieldI: [],
    		fieldJ: ["(X GNN_sh1)","(X GNN_syl6)"],
    		fieldK: ["(X GNN_sh2)","(X GNN_syl7)"],
    		fieldL: ["(X GNN_sh1)","(X GNN_syl8)"],
    		fieldM: ["(X GNN_sh2)","(X GNN_syl9)"],
    		fieldN: ["(X GNN_names3)"],
    		fieldO: [],
    		fieldP: [],
    		fieldQ: [],
    		fieldR: [],
    		sentences: ["+1 {12","{12 the }+2","{12 of the }+3 +4","+3-5 {12","+1 {12 of the }+3 +4","+1 {34","{34 the }+2","{34 of the }+3 +4","+3-5 {34","+1 {34 of the }+3 +4","+1 {5","{5 the }+2","{5 of the }+3 +4","+3-5 {5","+1 {5 of the }+3 +4"]
    	},
    	GNN_NamesOolite:{
    		fieldA: [],
    		fieldB: ["[2]-[3]","ben [3]","Mc[3]","Ol'[3]","Ath[5]","Br[9]an","Bran[4]","C[7][4]","D[7][4]","Dav[9][4]","Denn[9][4]","Eccl[5]","Fa[9]r[4]","Folk[4]","Garr[5]","Good[4]","Hector","Inn[5]","Jam[5]","Jon[4]","Kir[4]","L[9]ttle[4]","L[7][4]","Na[9]l[4]","Neil[4]","Peter[4]","Orbit[4]","Roger[4]","Sam[4]","Star[4]","Th[8]r[4]","Wilkin[4]","William[4]"],
    		fieldC: ["Ath[5]","Br[9]an","Bran[4]","C[7][4]","D[7][4]","Dav[9][4]","Denn[9][4]","Folk[4]","Garri[4]","Good[4]","Hector","Inn[5]","Jam[5]","Jon[4]","Kir[4]","L[9]ttle[4]","L[7][4]","Na[9]l[4]","Neil[4]","Peter[4]","Roger[4]","Sam[4]","Star[4]","Th[8]r[4]","Wilkin[4]","William[4]"],
    		fieldD: ["b[8]rn","f[8]r","st[8]n","sen","son","son","sdott[9]r","s","s","sby","er","f[9]re","l[9]ng"],
    		fieldE: ["e","[6]b[8]rn","[6]f[8]r","[6]st[8]n","[6]sen","[6]son","eson","[6]sdott[9]r","[6]s","es","esby","[6]f[9]re","l[9]ng"],
    		fieldF: ["i","e","e","ie"],
    		fieldG: ["ar","aw","arre","our"],
    		fieldH: ["e","o","u","ou","ai"],
    		fieldI: ["i","y"],
    		fieldJ: [],
    		fieldK: [],
    		fieldL: [],
    		fieldM: [],
    		fieldN: [],
    		fieldO: [],
    		fieldP: [],
    		fieldQ: [],
    		fieldR: [],
    		sentences: ["3","2"],
    		splitRules: [2,2]
    	},
    	GNN_NamesOther:{
    		fieldA: ["(X GNN_sh1)","(X GNN_syl6)"],
    		fieldB: ["(X GNN_syl1)"],
    		fieldC: ["(X GNN_syl7)"],
    		fieldD: ["(X GNN_names3)"],
    		fieldE: [],
    		fieldF: [],
    		fieldG: ["(B28+)(B29+)[2][3]"],
    		fieldH: ["[4]"],
    		fieldI: ["[1][2]","[2][3]"],
    		fieldJ: ["(B28+)(B29+)[2]"],
    		fieldK: ["Al","Alex","Alto","Amanda","Amber","Apollo","Baldrin","Beck[3]","Begg[3]","Biff","Bonnie","Brooke","Buck[3]","Cain","Check[3]","Chip","Churchill","Claire","Clifford","Constantine","Dakota","Darren","Dick[3]","Don","Dugg[3]","Dusty","Ernie","Fanny","Felix","Ford","Frenzy","Ginger","Hannibal","Holly","Jack","Joaquin","Kipper","Mack[3]","Marlon","Mick[3]","Mo","Montgomery","Moritz","Myles","Nat","Orion","Penny","Reav[3]","Red","Rock[3]","Ryan","Sal","Sand[3]","Tiff[3]"],
    		fieldL: ["annie","ers","ie","y"],
    		fieldM: [],
    		fieldN: ["(B28+)(B29+)[6]"],
    		fieldO: ["(X GNN_names12)"],
    		fieldP: [],
    		fieldQ: ["(B28+)(B29+)[9]"],
    		fieldR: ["(X GNN_names16)"],
    		sentences: ["{+(Si:rodent=[1]|)+(Si:feline=[1]|)+(Si:bird=[5]|)+(Si:frog=[8]|)}+(Si:lobster=[7]|)+(Si:lizard=[8]|)+(Si:insect=[9]|)+{(Si:human=[8]|) {+(B28=|[9])+(B29=[GNN_NamesOolite]|)"],
    		splitRules: [1]
    	},
    	GNN_NamesPirates:{
    		fieldA: ["(X GNN_names6)","[6]shanks"],
    		fieldB: ["(X GNN_names1)","(X GNN_names2)"],
    		fieldC: [],
    		fieldD: ["(X GNN_names7)","[8]balls","[8]beard","Mc[2]"],
    		fieldE: ["(X GNN_names11)","The Rusty [7]"],
    		fieldF: ["(X GNN_color2)"],
    		fieldG: ["Butter Cutter","Broadsword","Cutlass","Dagger","Epee","Knife","Saber","Scabbard"],
    		fieldH: ["(X GNN_color1)"],
    		fieldI: [],
    		fieldJ: [],
    		fieldK: [],
    		fieldL: [],
    		fieldM: [],
    		fieldN: [],
    		fieldO: [],
    		fieldP: [],
    		fieldQ: [],
    		fieldR: [],
    		sentences: ["2 '1' 4","2 '5' 4","2 '5' 4","2 '1' 4","Long 2 4"],
    		splitRules: [3,3,3,3,4]
    	},
    	GNN_NamesShips:{
    		fieldA: ["(X GNN_names8)","(X GNN_color1)"],
    		fieldB: ["(X GNN_names5)"],
    		fieldC: ["(X GNN_names9)"],
    		fieldD: ["(X GNN_title2)"],
    		fieldE: ["(X GNN_names10)"],
    		fieldF: [],
    		fieldG: [],
    		fieldH: [],
    		fieldI: [],
    		fieldJ: [],
    		fieldK: [],
    		fieldL: [],
    		fieldM: [],
    		fieldN: [],
    		fieldO: [],
    		fieldP: [],
    		fieldQ: [],
    		fieldR: [],
    		sentences: ["The 1 2","The 1 3","The +4 2","The +4 5"],
    		splitRules: [21,21,21,21]
    	},
    	GNN_PirateInsult:{
    		fieldA: ["(X GNN_anim1)"],
    		fieldB: ["(X GNN_body1)"],
    		fieldC: ["(X GNN_bucket1)"],
    		fieldD: ["(X GNN_spit1)"],
    		fieldE: ["(X GNN_god3)"],
    		fieldF: ["(X GNN_god2)"],
    		fieldG: ["(X GNN_god1)"],
    		fieldH: ["(X GNN_insult1)"],
    		fieldI: ["(X GNN_wish1)"],
    		fieldJ: ["(X GNN_threat1)"],
    		fieldK: [],
    		fieldL: [],
    		fieldM: [],
    		fieldN: [],
    		fieldO: [],
    		fieldP: [],
    		fieldQ: [],
    		fieldR: [],
    		sentences: ["9 5 |7 8 your 2!","9 5 |7 8 your 2, you 1!","9 5 |7 8 your 2, you 6 1!","9 5 |7 8 your 2, you 6 3 of 4!","9 5 |7 8 your 2, you 6 3 of 1 4!","9 5 |7 of @s 8 your 2!","9 5 |7 of @s 8 your 2, you 1!","9 5 |7 of @s 8 your 2, you 6 1!","9 5 |7 of @s 8 your 2, you 6 3 of 4!","9 5 |7 of @s 8 your 2, you 6 3 of 1 4!","You 1!","You 6 1!","You 6 3 of 4!","You 6 3 of 1 4!","{1 }8 you!","{1 }8 you, you 1!","{1 }8 you, you 6 1!","{1 }8 you, you 6 3 of 4!","{1 }8 you, you 6 3 of 1 4!","{1 }8 your 2!","{1 }8 your 2, you 1!","{1 }8 your 2, you 6 1!","{1 }8 your 2, you 6 3 of 4!","{1 }8 your 2, you 6 3 of 1 4!"]
    	},
    	GNN_Precious:{
    		fieldA: ["(X GNN_color1)","(X GNN_color2)","(X GNN_color3)","(X GNN_god3)"],
    		fieldB: ["(X GNN_anim1)","(X GNN_god1)","(X GNN_precious1)"],
    		fieldC: ["(X GNN_bucket1)"],
    		fieldD: ["(X GNN_bottle1)"],
    		fieldE: [],
    		fieldF: [],
    		fieldG: [],
    		fieldH: [],
    		fieldI: [],
    		fieldJ: [],
    		fieldK: [],
    		fieldL: [],
    		fieldM: [],
    		fieldN: [],
    		fieldO: [],
    		fieldP: [],
    		fieldQ: [],
    		fieldR: [],
    		sentences: ["1 +>2","3 of 1 +>2","4 of [GNN_NamesBrews]","1 +>2","3 of 1 +>2"]
    	},
    	GNN_A:{
    		fieldA: ["(X GNN_factory1)","(X GNN_govhouse1)","(X GNN_house1)","(X GNN_install1)"],
    		fieldB: ["(X GNN_incident1)"],
    		fieldC: ["(X GNN_big1)"],
    		fieldD: ["(X GNN_many1)"],
    		fieldE: ["county seat","(X GNN_major1)"],
    		fieldF: ["(X GNN_inofficial1)"],
    		fieldG: ["(X GNN_document1)"],
    		fieldH: ["(X GNN_destroy1)"],
    		fieldI: ["(X GNN_reveal1)"],
    		fieldJ: ["(X GNN_device1)"],
    		fieldK: ["(X GNN_tragedy1)"],
    		fieldL: ["(X GNN_inoperable1)"],
    		fieldM: ["(X GNN_official1)"],
    		fieldN: ["(X GNN_P006)"],
    		fieldO: ["(X GNN_P007)"],
    		fieldP: ["(X GNN_P008)"],
    		fieldQ: ["(X GNN_inoperable2)"],
    		fieldR: ["in the next days","within the next days"],
    		sentences: ["@XA 3 2 _8 4 >1 at >@s 5 district, injuring 4 (X GNN_citizen1) earlier this morning. 6 >7 9 that this {2 could have been ^3, but ^8 >1 ^3 the >7. '6,' said (Si:human=[GNN_Names]|[GNN_NamesOther]), >@s 4. 'But the }3 {2 }_8 important structures here{5 9.'"]
    	},
    	GNN_B:{
    		fieldA: ["(X GNN_citizen1)","(X GNN_trader1)"],
    		fieldB: ["expressed approval of","applauded","celebrated","cheered","hailed","acclaimed"],
    		fieldC: ["notorious","infamous","feared"],
    		fieldD: ["(X GNN_bandit1)"],
    		fieldE: ["plagued","afflicted","cursed","preyed on","attacked"],
    		fieldF: ["in recent","for many","for the last several"],
    		fieldG: ["weeks","months","years"],
    		fieldH: ["Adjudicator","Judge","(Sg:0=local chieftain|[9])","(Sg:1=Sheriff|[9])","(Sg:1=Royal Justiciar|[9])","(Sg:1=King's Hand|[9])","(Sg:3=State Prosecutor|[9])","(Sg:3=Archimandrite|[9])","(Sg!4=Priest of Justice|[9])","(Sg:4=People's Representative|[9])","(Sg:4=State Prosecutor|[9])","(Sg:4=People's Justice|[9])","(Sg:5=Protector of the Commonwealth|[9])","(Sg:6=Arbiter|[9])","(Sg:6=Counsellor|[9])","(Sg:7=Director|[9])","(Sg:7=Personnel Manager|[9])","(Sg:7=Supervisor|[9])"],
    		fieldI: ["Adjudicator","Judge","Arbiter"],
    		fieldJ: ["(Sg<5=[2]|deprogramming)","(Sg<5=[2]|brainwashing)","(Sg<5=[2]|brain wipe)","(Sg<5=[2]|re-education)","(Sg<5=[2]|community service)","(Sg<3=vitrification|[2])","(Sg:7=reduction in salary|[2])"],
    		fieldK: ["(Se<7=death|throat-cutting)","slow death","(Sg<1=drawing and quartering|immurement)","penal servitude","death of personality","brain wipe"],
    		fieldL: ["Addressing the court","On being dragged from the courtroom","With bulging eyes","With a certain dignity","Struggling with the guards","Visibly appalled","Clearly terrified","Shaking with fear"],
    		fieldM: ["prisoner","felon","miscreant","guilty party"],
    		fieldN: ["murmured","yelled","screamed","shouted","said","shrieked"],
    		fieldO: ["amuse","enrage","anger","tickle","entertain","bewilder","confuse","puzzle"],
    		fieldP: ["lively","eager","exuberant","festive","excited","feverish","frantic"],
    		fieldQ: ["crowd","rabble","throng","mob","(Sg:1=courtiers|[9])","(Sg:4=Party members|[9])","(Sg>4=media|[9])","(Sg:7=executives|[9])"],
    		fieldR: ["crowd","rabble","throng","mob"],
    		sentences: ["@s, @d.@c: Local >1 2 the capture of [GNN_NamesPirates], the 3 4 who has 5 shipping in this and nearby systems 6 7. The 8, @W, sentenced @n0 to {1. 3 the 4 5, '[GNN_PirateInsult]', which only served to 6 the 7 8.","@s, @d.@c: A {7 9 of >}1 looked on as [GNN_NamesPirates] was today found guilty on all counts. Summing up, 8 @W called the prisoner 'a 3 4, who has 5 local shipping 6 7'. {3, @n0 5, '[GNN_PirateInsult]', which seemed to 6 @n1. Traders' Guild representatives }2 @n1 as @n0 was sentenced to {1."]
    	},
    	GNN_C:{
    		fieldA: ["(X GNN_serious1)"],
    		fieldB: ["(Sg:0=tribespeople|[2])","(Sg:0=warriors|[2])","(Sg:1=nobles|[2])","(Sg:1=peasants|[2])","(Sg:3=fanatics|[2])","(Sg:4=Party members|[2])","(Sg:7=executives|[2])","(Si:human=colonists|[2])","media","inhabitants","citizens"],
    		fieldC: ["offended","transgressed","broke","violated","flouted","outraged"],
    		fieldD: ["(Sg!4=religious precepts|[4])","laws","customs","mores","morality","traditions","norms","codes of behaviour","conventions"],
    		fieldE: ["touching","looking at","speaking to","smiling at","winking at","kicking","shouting at","eating","whistling at","singing to","whistling near","tickling","abusing","insulting","(Sg!4=denying the sanctity of|[5])","(Sg:4=oppressing|[5])","coughing near","sneezing within earshot of","laughing at","soiling","ogling"],
    		fieldF: ["frozen","pickled","(Sg:1=Royal|[6])","(Sg!4=sacred|[6])","(Sg!4=holy|[6])","unwashed","veiled","blue","white","green","purple","cross-eyed","one-eyed","three-eyed","drunken","sleeping","preserved","painted","(Sg<4=low-caste|[6])","(Sg<4=high-caste|[6])"],
    		fieldG: ["(Sg!4=priest|[7])","(Sg!4=priestess|[7])","(Sg!4=idol|[7])","(Sg!4=divinity|[7])","(Sg!4=fetish|[7])","goat","monkey","shrew","chicken","poet","treeoid","bat","Elder","ant","opossum","sheep","bison","buffalo","pig","ferret","weasel","gibbon","baboon","porcupine","pachyderm","(Sg:2=courtier|[7])","(Sg:4=senior Party member|[7])","(Sg:7=member of the Board|[7])"],
    		fieldH: ["(X GNN_rumour1)"],
    		fieldI: ["twelve","twenty-four","(X GNN_few2)"],
    		fieldJ: ["hours","days"],
    		fieldK: ["(X GNN_mob1)"],
    		fieldL: ["an apology","the ambassador's resignation","the ambassador's head","compensation for mental anguish","'an end to Co-operative brutality'","the withdrawal of Co-operative forces from the system","atonement","nothing less than the breakup of the Co-operative","the ambassador's surrender","justice"],
    		fieldM: ["political reputations","delicate trade negotiations","diplomatic careers","planetary honour and pride","the fates of worlds"],
    		fieldN: ["(X GNN_ending1)"],
    		fieldO: ["scandal has erupted following the arrival of"],
    		fieldP: ["the new Co-operative ambassador to"],
    		fieldQ: ["Although the ambassador's staff have denied the allegations, calling them"],
    		fieldR: ["the Co-operative embassy has been surrounded by"],
    		sentences: ["A 1 {6 (Si:human=[GNN_Names]|[GNN_NamesOther])}, a @h from @s, as {7} @S. Local 2 claim that @n 3 @s 4 by 5 a 6 7. @n's staff deny the allegations, calling them '8'. Nevertheless, for the last 9 {1, 9 2 of protestors demanding 3. 4 hang in the balance5","(Si:human=[GNN_Names]|[GNN_NamesOther]), a @h from @s and {7} @S, is today at the centre of a 1 scandal. {2 of local }2 have surrounded the embassy, claiming that @n 3 @s 4 by 5 a 6 7. {8} '8', angry voices are demanding {3. 4 are at stake here5"],
    		custom: [0x0],
    		splitRules: []
    	},
    	GNN_D:{
    		fieldA: ["(X GNN_react1)"],
    		fieldB: ["(X GNN_claims1)"],
    		fieldC: ["(X GNN_fail1)"],
    		fieldD: ["(X GNN_P005)"],
    		fieldE: ["a number of","several","three","four","five","six","seven","eight","nine","ten","eleven","twelve","more than a dozen","more than fifteen","more than twenty","an estimated twenty-two","more than two dozen","dozens of","a great many"],
    		fieldF: ["(X GNN_ships2)"],
    		fieldG: ["ranking GalCop officer","GalCop commander","Viper squadron leader","GalCop co-ordinator"],
    		fieldH: ["we are doing the best we can within a very limited budget","we put our lives on the line every day","we do not shirk our duty","we simply do not have sufficient forces available","our own losses were considerable","our pilots are severely overstretched","we cannot work miracles","this attack was unprecedented in scale","we are not to blame here"],
    		fieldI: ["levelled accusations that","claimed that","presented evidence which purported to show that","displayed evidence that","suggested that"],
    		fieldJ: ["(Sg:1=crown officers|[1])","(Sg:1=nobles|[1])","(Sg:3=state police|[1])","(Sg:3=security|[1])","(Sg:4=Party members|[1])","(Sg:7=executives|[1])","(Sg:7=salarymen|[1])","(Sg:7=accountants|[1])","officials","administrators","agents"],
    		fieldK: ["delayed","misused","misappropriated","stolen","failed to provide","siphoned off","purloined","embezzled"],
    		fieldL: ["funds","moneys","resources","supplies","assets","stores","reserves","finances"],
    		fieldM: ["required by","intended for","needed by","urgently needed by","desperately needed for","which rightfully belonged to"],
    		fieldN: ["system patrols","Viper patrols","system police","GalCop forces","Co-operative forces","local Viper pilots"],
    		fieldO: ["at this time","at this moment","right now","For the moment","currently","at this point","just now","presently,","as things stand","given the circumstances","with so many of our members lost,"],
    		fieldP: ["who is to blame","who is at fault","who is responsible","who is culpable","where the fault lies","what the problem is"],
    		fieldQ: ["want a fighting chance","need all parties to work together","want to prevent this tragedy from repeating itself","need everyone to do their job"],
    		fieldR: ["are still unaccounted for","cannot be accounted for","are listed as 'overdue'","are missing, presumed destroyed","cannot be located","have disappeared from the system","are missing: hopefully both jumped out safely"],
    		sentences: ["@s, @d.@c: GalCop _1 2 that they 3 a 4, (X GNN_P001) 5 >6 (X GNN_P002). [GNN_Names], the 7, said, '+8,' and 9 @s {1 had 2 3 4 5. (X GNN_P003) [GNN_Names] said, '+6 we don't care 7: we just 8.' (X GNN_P004) the }6 '[GNN_NamesShips]' and '[GNN_NamesShips]' {9.","@s, @d.@c: [GNN_Names], the local 7, has 9 @s {1 have 2 3 4 5. Planetary representatives }_1 @n's statement, issuing their own 2 that {5 }3 a recent 4, which resulted in the destruction of 5 >6 across the system. Merchants' Guild representative [GNN_Names] said, '{+6 we don't care 7: we just 8.' Since the attack, the }6 '[GNN_NamesShips]' and '[GNN_NamesShips]' {9."]
    	},
    	GNN_TraderCharacter:{
    		fieldA: ["affected(B3+)","annoying","big","bohemian(B1+)","burly","cantankerous","chaotic(B0+)","childlike","cold","cosmopolitan(B1+)","dirt-encrusted","discreet","eloquent","famous","fashionable","fearless","flabby","fractured","funny","furious","gentle","greasy(B0+)","greedy","grim(B1+)","grinning(B1+)","grumpy","honourable(B1+)","lively","magnificent(B1+)","mean-spirited","memorable","miserly","misty(B0+)","mitochondrial","modest","moronic","most difficult","mysterious","nearly blind(B0+)","old","one-eyed(B0+)","paternal","pathetic","pompous(B1+)","psychotic(B1+)","raspy(B0+)","ravishing","reactionary(B0+)","respectable(B1+)","resplendent","righteous","rough","rude(B1+)","rum","salty(B0+)","shabby","slow","small","smelly(B0+)","statesmanlike(B1+)","stoic","stormy","tattered(B0+)","well-known(B1+)","worldly(B1+)"],
    		fieldB: [" and (B0=[5]|[4]) of [6]"],
    		fieldC: ["(D50=Junior Chief|[5])","Chief Scientist(B3+)","Director(B3+)","Executive Chief(B3+)","Senior Chief(B3+)","Senior Coordinator(B3+)"],
    		fieldD: ["(B1=[3]|Design Specialist)","(B1=[3]|Sales Manager)","(D50=Junior Chief|[5])","Operating [5]","Trade (D50=[5]|Coordinator)"],
    		fieldE: ["Assistant(B2+)","Attendant(B2+)","Engineer(B2+)","Manager(B2+)"],
    		fieldF: ["[8]","Amber [7]","AMS [7]","B.AT Inc","Betaex [7]","Borland [7]","Citek [7]","Citex [7]","Citgoo Express","Clifford [7]","Conestrip [7]","Connex [7]","Dalmore [7]","Daltlane [7]","deVane [7]","Dingi [7]","ETS [7]","Faulcon [7]","FreshFoods Inc","Fujio [7]","FullGrip [7]","Grupo Langostaides Azules","Huginkiss [7]","Hydrotec [7]","Inditech [7]","InterDrew [7]","Joover [7]","KMC [7]","Lave Fried Trumble Inc","Leysson [7]","Lifetec [7]","Ligoos [7]","Lucky Vole Farms","Mana [7]","Milford [7]","Monu Pharma","Nano [7]","NoVidio [7]","OO-Haul [7]","Oops Deliveries","PIn-tel Limited","PlaneOptics [7]","Plummer [7]","Ret Vesla Clothings","Saltlane [7]","Silvercon [7]","Siretex [7]","Stimtatex [7]","Subtech [7]","Takahara [7]","Texacoo Fuel [7]","the KitiTec Ltd","the Onix Inc","the Oomoo [7]","the Weyland-Yutani Corporation","Warfeld [7]","Wencoo [7]","Xenophob [7]","ZA Brew Ltd"],
    		fieldG: ["(X GNN_company2)"],
    		fieldH: ["Balder [9]","Emerson [9]","Palmer [9]","Greening [9]","Parker [9]","Nomuhare [9]"],
    		fieldI: ["and Sons Ltd","Inc","and Balder [7]","and Emerson [7]","and Palmer [7]","and Greening [7]","and Parker [7]","and Partners"],
    		fieldJ: ["co-owner of","commandeering","Commander of","holder of","operating","owner of","patron of","piloting","skipper of","taskmaster of"],
    		fieldK: ["compact (D50=[3]|[4])","escorted (D50=[3]|[4])","(B2=fast [4]|heavy [3])","finely crafted [3]","guarded [3]","(B2=un|heavily )escorted (D50=[3]|[4])","light escorted (D50=[3]|[4])","light guarded (D50=[3]|[4])","light (B1=[4]|[5])","(B3=experimental|maneuverable) (D50=[4]|[5])","medium (D50=escorted [4]|guarded [3])","medium [4]","(B2=small [5]|slim [4])"],
    		fieldL: ["(B3=Python|Anaconda) [6]","Python [6]","Boa [6]","Boa II [6]","Boa Class Cruiser","(B3=Ferdelance|Anaconda) [6]","Python [6]"],
    		fieldM: ["Cobra Mk III [7]","Ferdelance [7]","Moray Medical Boat [7]","Moray Star Boat [7]","Cobra Mk III [7]"],
    		fieldN: ["Adder(B2+) [7]","Asp(B2+) [7]","Cobra Mk I(B2+) [7]","Gecko(B2+) [8]","Krait(B2+) [8]","Mamba(B2+) [8]","Sidewinder(B2+) [8]","Cobra Mk I(B2+) [7]","Adder(B2+) [7]"],
    		fieldO: ["(B3=liner|barge)","(B3=yacht|cargo ship)","(B3=cruiser|cargo shuttle)","craft","cruiser","(B3=yacht|ferry)","(B2=ore ship|cruiser)","scientific vessel","schooner","solar-sail","starship","(B3=cargo steamer|tradeship)","transport","vessel"],
    		fieldP: ["(B3=yacht|cargo shuttle)","craft","(B3=merchant ship|ferry)","(B3=scientific|privateer) ship","skiff","sloop","scow","(B3=prototype|scout ship)","(B2=skiff|shuttle)"],
    		fieldQ: ["craft","privateer ship","skiff","sloop","scow","scout ship"],
    		fieldR: [],
    		sentences: ["@XCaptain @W, a 1 @h from @s(D30=[2]|), {1 '[GNN_NamesShips]', a 2."]
    	}
    };
    this.irregularNouns = {
    	bison:"bison",
    	carp:"carp",
    	genie:"genii",
    	gold:"gold",
    	mouse:"mice",
    	oni:"oni",
    	ox:"oxen",
    	seraph:"seraphim",
    	shrimp:"shrimp",
    	squid:"squid",
    	trout:"trout"
    };
    this.irregularVerbs = {
    	arise:["arise","arises","arose","arisen"],
    	awake:["awake","awakes","awoke","awoken"],
    	backslide:["backslide","backslides","backslid","backslid"],
    	be:["be","is","was","been"],
    	bear:["bear","bears","bore","born"],
    	beat:["beat","beats","beat","beaten"],
    	become:["become","becomes","became","become"],
    	begin:["begin","begins","began","begun"],
    	bend:["bend","bends","bent","bent"],
    	bet:["bet","bets","bet","betted"],
    	bid:["bid","bids","bid","bid"],
    	bind:["bind","binds","bound","bound"],
    	bite:["bite","bites","bit","bitten"],
    	bleed:["bleed","bleeds","bled","bled"],
    	blow:["blow","blows","blew","blown"],
    	"break":["break","breaks","broke","broken"],
    	breed:["breed","breeds","bred","bred"],
    	bring:["bring","brings","brought","brought"],
    	browbeat:["browbeat","browbeats","browbeat","browbeaten"],
    	build:["build","builds","built","built"],
    	burst:["burst","bursts","burst","burst"],
    	buy:["buy","buys","bought","bought"],
    	cast:["cast","casts","cast","cast"],
    	"catch":["catch","catches","caught","caught"],
    	choose:["choose","chooses","chose","chosen"],
    	cling:["cling","clings","clung","clung"],
    	come:["come","comes","came","come"],
    	cost:["cost","costs","cost","cost"],
    	creep:["creep","creeps","crept","crept"],
    	crossbreed:["crossbreed","crossbreeds","crossbred","crossbred"],
    	cut:["cut","cuts","cut","cut"],
    	daydream:["daydream","daydreams","daydreamt","daydreamt"],
    	deal:["deal","deals","dealt","dealt"],
    	dig:["dig","digs","dug","dug"],
    	dive:["dive","dives","dove","dived"],
    	"do":["do","does","did","done"],
    	draw:["draw","draws","drew","drawn"],
    	dream:["dream","dreams","dreamt","dreamt"],
    	drink:["drink","drinks","drank","drunk"],
    	drive:["drive","drives","drove","driven"],
    	eat:["eat","eats","ate","eaten"],
    	fall:["fall","falls","fell","fallen"],
    	"feast on":["feast on","feasts on","feasted upon","feasted upon"],
    	feed:["feed","feeds","fed","fed"],
    	feel:["feel","feels","felt","felt"],
    	fight:["fight","fights","fought","fought"],
    	find:["find","finds","found","found"],
    	fit:["fit","fits","fitted","fitted"],
    	flee:["flee","flees","fled","fled"],
    	fling:["fling","flings","flung","flung"],
    	fly:["fly","flies","flew","flown"],
    	forbid:["forbid","forbids","forbade","forbidden"],
    	forecast:["forecast","forecasts","forecast","forecast"],
    	foresee:["foresee","foresees","foresaw","foreseen"],
    	foretell:["foretell","foretells","foretold","foretold"],
    	forget:["forget","forgets","forgot","forgotten"],
    	forgive:["forgive","forgives","forgave","forgiven"],
    	forsake:["forsake","forsakes","forsook","forsaken"],
    	freeze:["freeze","freezes","froze","frozen"],
    	frostbite:["frostbite","frostbites","frostbit","frostbitten"],
    	fry:["fry","fries","fried","fried"],
    	get:["get","gets","got","gotten"],
    	give:["give","gives","gave","given"],
    	go:["go","goes","went","gone"],
    	grind:["grind","grinds","ground","ground"],
    	grow:["grow","grows","grew","grown"],
    	handwrite:["handwrite","handwrites","handwrote","handwritten"],
    	hang:["hang","hangs","hung","hung"],
    	have:["have","have","had","had"],
    	hear:["hear","hears","heard","heard"],
    	hew:["hew","hews","hewed","hewed"],
    	hide:["hide","hides","hid","hidden"],
    	hit:["hit","hit","hit","hit"],
    	hold:["hold","holds","held","held"],
    	hurt:["hurt","hurts","hurt","hurt"],
    	inbreed:["inbreed","inbreeds","inbred","inbred"],
    	inlay:["inlay","inlays","inlaid","inlaid"],
    	input:["input","inputs","input","input"],
    	keep:["keep","keeps","kept","kept"],
    	kneel:["kneel","kneels","knelt","knelt"],
    	know:["know","knows","knew","known"],
    	lay:["lay","lays","laid","laid"],
    	lead:["lead","leads","led","led"],
    	leave:["leave","leaves","left","left"],
    	lend:["lend","lends","lent","lent"],
    	let:["let","lets","let","let"],
    	lie:["lie","lies","lied","lied"],
    	light:["light","lights","lit","lit"],
    	lose:["lose","loses","lost","lost"],
    	make:["make","makes","made","made"],
    	mean:["mean","means","meant","meant"],
    	meet:["meet","meets","met","met"],
    	miscast:["miscast","miscasts","miscast","miscast"],
    	misdeal:["misdeal","misdeals","misdealt","misdealt"],
    	misdo:["misdo","misdoes","misdid","misdone"],
    	mishear:["mishear","mishears","misheard","misheard"],
    	mislay:["mislay","mislays","mislaid","mislaid"],
    	mislead:["mislead","misleads","misled","misled"],
    	misread:["misread","misreads","misread","misread"],
    	misspend:["misspend","misspends","misspent","misspent"],
    	mistake:["mistake","mistakes","mistook","mistaken"],
    	misteach:["misteach","misteachs","mistaught","mistaught"],
    	misunderstand:["misunderstand","misunderstands","misunderstood","misunderstood"],
    	miswrite:["miswrite","miswrites","miswrote","miswritten"],
    	offset:["offset","offsets","offset","offset"],
    	outbid:["outbid","outbids","outbid","outbid"],
    	outbreed:["outbreed","outbreeds","outbred","outbred"],
    	outdo:["outdo","outdoes","outdid","outdone"],
    	outdraw:["outdraw","outdraws","outdrew","outdrawn"],
    	outdrink:["outdrink","outdrinks","outdrank","outdrunk"],
    	outdrive:["outdrive","outdrives","outdrove","outdriven"],
    	outfight:["outfight","outfights","outfought","outfought"],
    	outfly:["outfly","outflies","outflew","outflown"],
    	outgrow:["outgrow","outgrows","outgrew","outgrown"],
    	outride:["outride","outrides","outrode","outridden"],
    	outrun:["outrun","outruns","outran","outrun"],
    	outsell:["outsell","outsells","outsold","outsold"],
    	outshoot:["outshoot","outshoots","outshot","outshot"],
    	outsit:["outsit","outsits","outsat","outsat"],
    	outspeak:["outspeak","outspeaks","outspoke","outspoken"],
    	outspeed:["outspeed","outspeeds","outsped","outsped"],
    	outswear:["outswear","outswears","outswore","outsworn"],
    	outthink:["outthink","outthinks","outthought","outthought"],
    	outthrow:["outthrow","outthrows","outthrew","outthrown"],
    	overbid:["overbid","overbids","overbid","overbid"],
    	overbuild:["overbuild","overbuilds","overbuilt","overbuilt"],
    	overbuy:["overbuy","overbuys","overbought","overbought"],
    	overcome:["overcome","overcomes","overcame","overcome"],
    	overdo:["overdo","overdoes","overdid","overdone"],
    	overdraw:["overdraw","overdraws","overdrew","overdrawn"],
    	overdrink:["overdrink","overdrinks","overdrank","overdrunk"],
    	overfeed:["overfeed","overfeeds","overfed","overfed"],
    	overhang:["overhang","overhangs","overhung","overhung"],
    	overhear:["overhear","overhears","overheard","overheard"],
    	overlay:["overlay","overlays","overlaid","overlaid"],
    	overpay:["overpay","overpays","overpaid","overpaid"],
    	override:["override","overrides","overrode","overridden"],
    	overrun:["overrun","overruns","overran","overrun"],
    	oversee:["oversee","oversees","oversaw","overseen"],
    	oversell:["oversell","oversells","oversold","oversold"],
    	overshoot:["overshoot","overshoots","overshot","overshot"],
    	overtake:["overtake","overtakes","overtook","overtaken"],
    	overthink:["overthink","overthinks","overthought","overthought"],
    	overthrow:["overthrow","overthrows","overthrew","overthrown"],
    	partake:["partake","partakes","partook","partaken"],
    	pay:["pay","pays","paid","paid"],
    	plead:["plead","pleads","pleaded","pleaded"],
    	prebuild:["prebuild","prebuilds","prebuilt","prebuilt"],
    	premake:["premake","premakes","premade","premade"],
    	prepay:["prepay","prepays","prepaid","prepaid"],
    	presell:["presell","presells","presold","presold"],
    	preset:["preset","presets","preset","preset"],
    	proofread:["proofread","proofreads","proofread","proofread"],
    	prove:["prove","proves","proved","proven"],
    	put:["put","puts","put","put"],
    	quit:["quit","quits","quit","quit"],
    	read:["read","reads","read","read"],
    	reawake:["reawake","reawakes","reawoke","reawaken"],
    	rebid:["rebid","rebids","rebid","rebid"],
    	rebind:["rebind","rebinds","rebound","rebound"],
    	rebuild:["rebuild","rebuilds","rebuilt","rebuilt"],
    	recast:["recast","recasts","recast","recast"],
    	recut:["recut","recuts","recut","recut"],
    	redeal:["redeal","redeals","redealt","redealt"],
    	redo:["redo","redoes","redid","redone"],
    	redraw:["redraw","redraw","redrew","redrawn"],
    	refit:["refit","refits","refitted","refitted"],
    	regrind:["regrind","regrinds","reground","reground"],
    	regrow:["regrow","regrows","regrew","regrown"],
    	rehang:["rehang","rehangs","rehung","rehung"],
    	rehear:["rehear","rehears","reheard","reheard"],
    	relight:["relight","relights","relit","relit"],
    	remake:["remake","remakes","remade","remade"],
    	rend:["rend","rends","rent","rent"],
    	repay:["repay","repays","repaid","repaid"],
    	reread:["reread","rereads","reread","reread"],
    	rerun:["rerun","reruns","reran","rerun"],
    	resell:["resell","resells","resold","resold"],
    	resend:["resend","resends","resent","resent"],
    	reset:["reset","resets","reset","reset"],
    	resew:["resew","resews","resewed","resewn"],
    	retake:["retake","retakes","retook","retaken"],
    	reteach:["reteach","reteaches","retaught","retaught"],
    	retear:["retear","retears","retore","retorn"],
    	retell:["retell","retells","retold","retold"],
    	rethink:["rethink","rethinks","rethought","rethought"],
    	retread:["retread","retreads","retread","retread"],
    	retrofit:["retrofit","retrofits","retrofitted","retrofitted"],
    	rewake:["rewake","rewakes","rewoke","rewaken"],
    	rewear:["rewear","rewears","rewore","reworn"],
    	reweave:["reweave","reweaves","rewove","rewoven"],
    	rewin:["rewin","rewins","rewon","rewon"],
    	rewind:["rewind","rewinds","rewound","rewound"],
    	rewrite:["rewrite","rewrites","rewrote","rewritten"],
    	rid:["rid","rids","rid","rid"],
    	ride:["ride","rides","rode","ridden"],
    	ring:["ring","rings","rang","rung"],
    	rip:["rip","rips","ripped","ripped"],
    	rise:["rise","rises","rose","risen"],
    	run:["run","runs","ran","run"],
    	saw:["saw","saws","sawed","sawed"],
    	say:["say","says","said","said"],
    	see:["see","sees","saw","seen"],
    	seek:["seek","seeks","sought","sought"],
    	sell:["sell","sells","sold","sold"],
    	send:["send","sends","sent","sent"],
    	set:["set","sets","set","set"],
    	sew:["sew","sews","sewed","sewn"],
    	shake:["shake","shakes","shook","shaken"],
    	shed:["shed","sheds","shed","shed"],
    	shit:["shit","shits","shit","shit"],
    	shoot:["shoot","shoots","shot","shot"],
    	show:["show","shows","showed","shown"],
    	shrink:["shrink","shrinks","shrank","shrunk"],
    	shut:["shut","shuts","shut","shut"],
    	sing:["sing","sings","sang","sung"],
    	sink:["sink","sinks","sunk","sunk"],
    	sit:["sit","sits","sat","sat"],
    	sleep:["sleep","sleeps","slept","slept"],
    	slide:["slide","slides","slid","slid"],
    	sling:["sling","slings","slung","slung"],
    	slink:["slink","slinks","slinked","slinked"],
    	slit:["slit","slits","slit","slit"],
    	smell:["smell","smells","smelled","smelled"],
    	sneak:["sneak","sneaks","sneaked","sneaked"],
    	sow:["sow","sows","sowed","sowed"],
    	speak:["speak","speaks","spoke","spoken"],
    	speed:["speed","speeds","speeded","speeded"],
    	spell:["spell","spells","spelled","spelled"],
    	spend:["spend","spends","spent","spent"],
    	spill:["spill","spills","spilled","spilled"],
    	spin:["spin","spins","spun","spun"],
    	spit:["spit","spits","spat","spat"],
    	split:["split","splits","split","split"],
    	spoil:["spoil","spoils","spoiled","spoiled"],
    	spread:["spread","spreads","spread","spread"],
    	spring:["spring","springs","sprang","sprung"],
    	stand:["stand","stands","stood","stood"],
    	steal:["steal","steals","stole","stolen"],
    	stick:["stick","sticks","stuck","stuck"],
    	sting:["sting","stings","stung","stung"],
    	stink:["stink","stinks","stunk","stunk"],
    	strike :["strike","strikes","struck","struck"],
    	string:["string","strings","strung","strung"],
    	strive:["strive","strives","strove","striven"],
    	sublet:["sublet","sublets","sublet","sublet"],
    	sunburn:["sunburn","sunburns","sunburned","sunburned"],
    	swear:["swear","swears","swore","sworn"],
    	sweat:["sweat","sweats","sweated","sweated"],
    	sweep:["sweep","sweeps","swept","swept"],
    	swell:["swell","swells","swelled","swelled"],
    	swim:["swim","swims","swam","swum"],
    	swing:["swing","swings","swung","swung"],
    	take:["take","takes","took","taken"],
    	teach:["teach","teaches","taught","taught"],
    	tear:["tear","tear","tore","torn"],
    	tell:["tell","tells","told","told"],
    	think:["think","thinks","thought","thought"],
    	"throw":["throw","throws","threw","thrown"],
    	thrust:["thrust","thrusts","thrust","thrust"],
    	tread:["tread","treads","trod","trodden"],
    	"try":["try","tries","tried","tried"],
    	unbend:["unbend","unbends","unbent","unbent"],
    	unbind:["unbind","unbind","unbound","unbound"],
    	unclothe:["unclothe","unclothes","unclothed","unclothed"],
    	underbid:["underbid","underbids","underbid","underbid"],
    	undercut:["undercut","undercuts","undercut","undercut"],
    	underfeed:["underfeed","underfeeds","underfed","underfed"],
    	undergo:["undergo","undergoes","underwent","undergone"],
    	underlie:["underlie","underlies","underlay","underlain"],
    	undersell:["undersell","undersells","undersold","undersold"],
    	understand:["understand","understands","understood","understood"],
    	undertake:["undertake","undertakes","undertook","undertaken"],
    	underwrite:["underwrite","underwrites","underwrote","underwritten"],
    	undo:["undo","undoes","undid","undone"],
    	unfreeze:["unfreeze","unfreezes","unfroze","unfrozen"],
    	unhang:["unhang","unhangs","unhung","unhung"],
    	unhide:["unhide","unhides","unhid","unhidden"],
    	unsling:["unsling","unslings","unslung","unslung"],
    	unspin:["unspin","unspins","unspun","unspun"],
    	unstick:["unstick","unsticks","unstuck","unstuck"],
    	unstring:["unstring","unstrings","unstrung","unstrung"],
    	unweave:["unweave","unweaves","unwove","unwoven"],
    	unwind:["unwind","unwinds","unwound","unwound"],
    	uphold:["uphold","upholds","upheld","upheld"],
    	upset:["upset","upsets","upset","upset"],
    	wake:["wake","wakes","woke","woken"],
    	wear:["wear","wears","wore","worn"],
    	weave:["weave","weaves","wove","woven"],
    	weep:["weep","weeps","wept","wept"],
    	wet:["wet","wets","wet","wet"],
    	win:["win","wins","won","won"],
    	wind:["wind","winds","wound","wound"],
    	withdraw:["withdraw","withdraws","withdrew","withdrawn"],
    	withhold:["withhold","withholds","withheld","withheld"],
    	withstand:["withstand","withstands","withstood","withstood"],
    	wring:["wring","wrings","wrung","wrung"],
    	write:["write","writes","wrote","written"]
    };
    this.superlatives = {
    	best:1,
    	biggest:1,
    	bulkiest:1,
    	greatest:1,
    	highest:1,
    	largest:1,
    	least:1,
    	littlest:1,
    	lowest:1,
    	max:1,
    	maximal:1,
    	merest:1,
    	minimal:1,
    	most:1,
    	mostest:1,
    	outside:1,
    	paramount:1,
    	slightest:1,
    	smallest:1,
    	superlative:1,
    	supreme:1,
    	tiniest:1,
    	top:1,
    	topmost:1,
    	ultimate:1,
    	utmost:1,
    	uttermost:1
    };
    }).call(this);