function rnd(x) { return Math.floor(Math.random() * x); }

// Main node Class
function N(text) {
    if (text == undefined) throw "Only text allowed in text"
    this.text = text; 
    this.next = new Array();

    // Add one element to the next node array
    // Return none to avoid an addition if used as N argument!
    this.push_next = function(x) {
	this.next.push(x);
	return undefined;
    }

    // Set the next node. Only if they belong to the same type of object
    for (i = 1; i < arguments.length; i++) {
	var x = arguments[i];
	if (x == undefined || x.prototype != this.prototype)
	    continue;
	this.push_next(x);
    }


    // Get random next node
    this.get_next = function() {
	var r = rnd(this.next.length);
	return this.next.length == 0 ? undefined : this.next[r];
    }

    // Create a similar node with the same followers
    this.similar = function(txt) {
        var w = new N(txt);
	for (var i = 0; i < this.next.length; i++) 
	    w.next[i] = this.next[i];
	return w;
    }
}

// Build up the tree
var f = new N("A FĂśld", 
  new N("elĂŠg, eljegesedik, vagy a Napba zuhan",
    new N("ĂŠs mindenki meghal."),
    new N("ĂŠs majdnem mindenki meghal.")
  ),
  new N("_et eltalĂĄlja egy gigantikus ĂźstĂśkĂśs ĂŠs",
    new N("megsemmisĂ­ti."),
    new N("megmenti."),
    new N("nem semmisĂ­ti meg, de",
      new N("mindenki meghal."),
      new N("majdnem mindenki meghal.")
      )
  ),
  new N("[ctrlPLURAL]", // Set if there are multiple beings
    new N("[ctrlOBJECT]", // Being are objects
      new N("tudĂłsai",
	f2 = new N("felfedeznek",
	  f1 = new N("[PLURAL:egy :]parĂĄnyi",
	    f3 = new N("rovar[BOTH::t:ok:okat]",
	      new N("_, amely[PLURAL::ek]",
	        f5 = new N("asszonyainkat akarj[PLURAL:a:ĂĄk]",
		  new N("ĂŠs",
		    f7 = new N("",
		      new N("rĂĄdiĂłaktĂ­v[PLURAL::ak] ĂŠs",
		        new N("megsemmisítheti[PLURAL:: őket]",
			  new N("egy csapat fĂĄklyĂĄs paraszt."),
			  new N("a hadsereg, a haditengerészet, a légierő és/vagy a parti őrség."),
			  new N("az atombomba.")
			),
		        new N("nem semmisítheti meg[PLURAL:: őket]",
			  f8 = new N("az atombomba",
			    f9 = new N("_, de",
			      fA = new N("egy ĂŠrtelmes gyerek elmagyarĂĄzza neki[PLURAL::k], hogy az emberisĂŠg O.K.",
			        new N("ĂŠs meghal[PLURAL::nak]."),
			        new N("ĂŠs elhagyj[PLURAL:a:ĂĄk] a FĂśldet."),
			        new N("ĂŠs fĂśrtelmes nyĂĄlkĂĄs kupaccĂĄ vĂĄltoz[PLURAL:i:na]k.")
			      ),
			      fA.similar("egy pap elmesĂŠli nekik, hogy van Isten"),
			      fB = fA.similar("beleszeret[PLURAL::nek] egy csinos lĂĄnyba"),
			      new N("bárányhimlőben elpusztul[PLURAL::nak]."),
			      fB.push_next(new N("ĂŠs ĂśsszehĂĄzasodnak ĂŠs boldogok ĂŠs ma is ĂŠlnek, ha meg nem haltak."))
			    ),
			    new N("_. Mire a tudĂłsok kidolgoznak egy fegyvert, amely",
			      new N("megöli[PLURAL:: őket]."),
			      new N("förtelmes nyálkás kupaccá változtatja[PLURAL:: őket]."),
			      fC = new N("hatĂĄstalannak bizonyul",
			        new N("ĂŠs megsemmisĂ­t[PLURAL::enek] bennĂźnket."),
			        new N("és tűrhető diktatatúráj[PLURAL:a:uk] alá vet[PLURAL::nek] bennünket."),
			        new N("ĂŠs felfal[PLURAL::nak] bennĂźnket.")
			      ),
			      fC.push_next(f9)
			    )
			  ),
			  f8.similar("a hadsereg, a haditengerészet, a légierő és/vagy a parti őrség"),
			  f8.similar("egy csapat fĂĄklyĂĄs paraszt")
			)
		      )
		    ),
		    f7.similar("nem")
		  )
		),
		new N("barĂĄtsĂĄgos[PLURAL::ak]."),
		f5.similar("barátságos[PLURAL::ak], de félreértik ő[PLURAL::ke]t"),
		f5.similar("fĂŠlreĂŠrt[PLURAL::enek] bennĂźnket"),
		f5.similar("csak jĂłt akar[PLURAL::nak] nekĂźnk"),
		f6 = f5.similar("kizĂĄrĂłlag ĂŠlelmiszernek tekint[PLURAL::enek] bennĂźnket"),
		f5.push_next(new N("_. NĂŠhĂĄnyat mag[PLURAL:ĂĄval:ukkal] visz[PLURAL::nek] ĂŠs elhagyj[PLURAL:a:ĂĄk] a FĂśldet.")),
		f6.push_next(new N("ĂŠs felfal[PLURAL::nak]."))
	      )
	    ),
	    f3.similar("gyĂ­k[BOTH::ot:ok:okat]"),
	    f3.similar("harci gĂŠp[BOTH::et:ek:eket]"),
	    f3.similar("szuperlĂŠny[BOTH::t:ek:eket]"),
	    f3.similar("meghatĂĄrozhatatlan ĂŠletform[BOTH:a:ĂĄt:ĂĄk:ĂĄkat]")
	  ),
	  f1.similar("[PLURAL:egy :]ĂłriĂĄsi")
	),
	f2.similar("feltalĂĄlnak")
      )
    ),
    new N("_et megtĂĄmadj[PLURAL:a:ĂĄk]",
      f4 = new N("[PLURAL:egy :]parĂĄnyi",
        f1.similar("Marsról, Holdról, Betelgeuzéről, más galaxisról származó")
      ),
      f4.similar("[PLURAL:egy :]ĂłriĂĄsi")
    )
  )
);

// Control flow Class
function CTRL() {
    this.ctrlPLURAL = function() {
        this.PLURAL = rnd(2);
	this.BOTH |= this.PLURAL * 2;
    }

    this.ctrlOBJECT = function() {
        this.OBJECT = 1;
	this.BOTH |= 1;
    }
}

// Create a novel from f
function Novel() {
    var h = new CTRL();
    var txt = new Array();

    for(var i = f; typeof i != 'undefined'; i = i.get_next()) {
	var t = i.text;
	while (1) {
	    var p = t.indexOf("[");
	    if (p == -1) break;
	    var p1 = t.indexOf("]");
	    if (p1 == -1) throw "Missing ']'";

	    var arr = t.substring(p + 1, p1).split(":");
	    var ctrl = arr.shift();
	    if(h[ctrl] == undefined) throw "No such control exists as " + ctrl;
	    var repl = "";

	    if (arr.length == 0) {
		h[ctrl]();
	    } else {
		repl = arr[h[ctrl]];
	    }

	    t = t.substring(0, p) + repl + t.substr(p1 + 1);
	} 
	if (t > "") txt.push(t);
    }
    text = txt.join(" ").replace(/ _/g, "");
    return text + " VÉGE";
}

// Create 5 unique novels
var novel_no = 5;
var novel = new Array();
for(var i = 0; i < novel_no; i++) {
    novel.unshift(Novel());
    do {
	for (j = 1; j < novel.length; j++)
	    if(novel[0] == novel[j]) {
		novel[0] = Novel();
	        break;
	    }
    } while(j < novel.length);
}

for(var i = 0; i < novel.length; i++) 
    novel[i] = '<LI STYLE="margin-bottom: 1em;">' + novel[i] + '</LI>';
document.writeln('<DIV STYLE="margin: 50;"><OL>' + novel.join('\n') + '</OL></DIV>');