<link rel=apple-touch-icon href=favicon_192.png>
<link rel=stylesheet href=ogre.css>
<script src=fastclick.js></script>
+ <script src=rrr.js></script>
<script src=units.js></script>
<script src=ogre.js></script>
<!-- <script src=brain.js></script> -->
var FIRST_EMPTY = /☐/;
var LAST_TICKED = /☒([^☒]*)$/;
-function choice (a) {
- return a[(Math.random() * a.length) | 0];
-}
-
-function cap (s) {
- return s && s[0].toUpperCase() + s.slice(1);
-}
-
-function letters (n) {
- var r = "";
- n = n || 1;
- while (n-- > 0)
- r += choice("abcdefghijklmnopqrstuvwxyz");
- return r;
-}
-
-function range (a, b) {
- return a + (Math.random() * (b - a)) | 0;
-}
-
-function numerals (n) {
- var r = "";
- n = n || 1;
- while (n-- > 0)
- r += choice("0123456789");
- return r;
-}
-
-function pid () {
- return letters(range(1, 4)).toUpperCase()
- + choice(["‑", "", ".", "/"])
- + numerals(range(1, 4));
-}
-
-function roman () {
- return choice(["I", "II", "III", "IV", "V", "VI",
- "VII", "VIII", "IX", "X", "XI", "XII",
- "XIV"]);
-}
-
-function oid () {
- return choice([letters(1).toUpperCase() + choice("-./") + numerals(2)]);
-}
-
function randomName (scheme) {
- switch (scheme) {
- case "id":
- return choice([pid() + " " + cap(choice(NOUNS))],
- [cap(choice(NOUNS)) + " " + pid()]);
- case "air":
- return choice([
- oid() + " " + cap(choice(ADJECTIVES)) + " " + cap(choice(BIRDS)),
- cap(choice(ADJECTIVES)) + " " + cap(choice(BIRDS)) + " " + roman()]);
- default:
- return choice([
- oid() + " " + cap(choice(ADJECTIVES)) + " " + cap(choice(NOUNS)),
- cap(choice(ADJECTIVES)) + " " + cap(choice(NOUNS)) + " " + roman()]);
- }
+ return G.expand(scheme);
}
var STATS = ["attack", "range", "defense", "aside"];
--- /dev/null
+/* rrr - recursive random rewrites
+ Copyright 2014 Joe Wreschnig
+ Licensed under the terms of the GNU GPL v2 or later
+ @license https://www.gnu.org/licenses/gpl-2.0.html
+ @source: https://yukkurigames.com/rrr/
+*//*
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ As additional permission, you may distribute the program or works
+ based on it without the copy of the GNU GPL normally required,
+ provided you include this license notice and a URL through which
+ recipients can access the corresponding source code.
+*/
+
+(function (exports) {
+ "use strict";
+
+ function randfloat (hi) { return Math.random() * hi; }
+ function randint (hi) { return randfloat(hi) | 0; }
+ function randchoice (seq) { return seq[randint(seq.length)]; }
+ function randrange (lo, hi) { return lo + randint(hi - lo); }
+
+ function Productions (dfn) {
+ this.__total = 0;
+ if (Array.isArray(dfn) || dfn.toString() === dfn) {
+ this.__rules = Array.prototype.slice.call(dfn);
+ } else if (typeof dfn === "function") {
+ this.__rules = dfn;
+ } else {
+ this.__rules = {};
+ Object.keys(dfn).forEach(function (key) {
+ var value = dfn[key];
+ this.__total += value;
+ this.__rules[key] = value;
+ }, this);
+ }
+ }
+
+ Productions.prototype.randproduction = function () {
+ if (Array.isArray(this.__rules))
+ return randchoice(this.__rules);
+
+ else if (typeof this.__rules === "function")
+ return this.__rules();
+
+ var x = randfloat(this.__total);
+ for (var k in this.__rules) {
+ x -= this.__rules[k];
+ if (x < 0)
+ return k;
+ }
+ return null;
+ };
+
+ function Grammar (productions, start) {
+ this.start = start || "";
+ this.productions = {};
+ for (var k in productions)
+ this.productions[k] = new Productions(productions[k]);
+ }
+
+ function randcount (lo, hi, rep) {
+ var n = hi ? randrange(+lo, +hi + 1)
+ : lo ? +lo
+ : 1;
+
+ var m = 1;
+ switch (rep) {
+ case '*': m = 0; while (Math.random() < 0.5) ++m; break;
+ case '+': while (Math.random() < 0.5) ++m; break;
+ case '?': m = +(Math.random() < 0.5); break;
+ }
+ return n * m;
+ }
+
+ function repeat (n, f) {
+ var r = [];
+ while (n-- > 0)
+ r.push(f());
+ return r;
+ }
+
+ var R = /<([^> ]+)( ?)>(?:{([0-9]+)(?:,([0-9]+))?}|(\*|\+|\?))?/g;
+ Grammar.prototype.expand = function (start) {
+ var g = this;
+ start = start || this.start;
+ return start.replace(R, function _ (match, p, w, lo, hi, rep) {
+ var prod = g.productions[p];
+ return repeat(randcount(lo, hi, rep), function () {
+ return prod.randproduction().replace(R, _);
+ }).join(w);
+ });
+ };
+
+ exports.Grammar = Grammar;
+})(typeof module !== "undefined" ? module.exports : this.rrr = {});
See https://creativecommons.org/publicdomain/zero/1.0/ for details.
*/
-var ADJECTIVES = [
- "angry",
- "cold",
- "deadly",
- "easy",
- "faithful",
- "fatal",
- "fiery",
- "harsh",
- "lost",
- "mean",
- "mighty",
- "noisy",
- "old",
- "proud",
- "pure",
- "quiet",
- "sharp",
- "slow",
- "strong",
- "true",
- "",
- "",
- "",
-];
+var G = new rrr.Grammar({
-var BIRDS = [
- "angel",
- "arrow",
- "cloud",
- "eagle",
- "falcon",
- "owl",
- "raptor",
- "storm",
- "swan",
- "swarm",
-];
+ Model: ["<Oid> <Adjective> <noun>", "<Adjective> <noun> <roman>"],
+ Flying: ["<Oid> <Adjective> <bird>", "<Adjective> <bird> <roman>"],
+ Id: ["<Pid> <noun>", "<noun> <Pid>"],
-var NOUNS = [
- "axe",
- "boar",
- "brute",
- "claw",
- "cobra",
- "dagger",
- "demon",
- "fox",
- "hyena",
- "knife",
- "lion",
- "lynx",
- "saber",
- "scout",
- "snake",
- "spear",
- "spire",
- "stone",
- "stream",
- "sword",
- "talon",
- "thorn",
- "tide",
- "tooth",
- "tower",
- "tusk",
- "venom",
- "viper",
- "wall",
- "wave",
- "wolf",
- "worker",
-];
+ Adjective: { "<adjective>": 0.9, "": 0.1 },
+ Separator: { "<separator>": 1, "": 0.25 },
+ Oid: ["<letter><separator><digit>{2}"],
+ Pid: ["<letter>{1,4}<Separator><digit>{1,4}"],
+
+ adjective: [
+ "Angry",
+ "Cold",
+ "Deadly",
+ "Easy",
+ "Faithful",
+ "Fatal",
+ "Fiery",
+ "Harsh",
+ "Lost",
+ "Mean",
+ "Mighty",
+ "Noisy",
+ "Old",
+ "Proud",
+ "Pure",
+ "Quiet",
+ "Sharp",
+ "Slow",
+ "Strong",
+ "True",
+ ],
+
+ bird: [
+ "Angel",
+ "Arrow",
+ "Cloud",
+ "Eagle",
+ "Falcon",
+ "Owl",
+ "Raptor",
+ "Storm",
+ "Swan",
+ "Swarm",
+ ],
+
+ noun: [
+ "Axe",
+ "Boar",
+ "Brute",
+ "Claw",
+ "Cobra",
+ "Dagger",
+ "Demon",
+ "Fox",
+ "Hyena",
+ "Knife",
+ "Lion",
+ "Lynx",
+ "Saber",
+ "Scout",
+ "Snake",
+ "Spear",
+ "Spire",
+ "Stone",
+ "Stream",
+ "Sword",
+ "Talon",
+ "Thorn",
+ "Tide",
+ "Tooth",
+ "Tower",
+ "Tusk",
+ "Venom",
+ "Viper",
+ "Wall",
+ "Wave",
+ "Wolf",
+ "Worker",
+ ],
+
+ roman: ["I", "II", "III", "IV", "V", "VI",
+ "VII", "VIII", "IX", "X", "XI", "XII",
+ "XIV"],
+
+ letter: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ digit: "0123456789",
+ separator: "-./",
+}, "<Model>");
// Most game data in this file based on
// http://www.sjgames.com/ogre/kickstarter/ogre-rec-sheets.pdf
var UNITS = {
"Superheavy Tank": {
weapons: ["3 Main Guns", "3 Antipersonnel"],
- nameScheme: "id",
+ nameScheme: "<Id>",
tread: 18,
size: 5,
au: 3
au: 25
},
"Ogre Mk. VI": {
- nameScheme: "grand",
weapons: [
"3 Main Battery",
"6 Secondary Battery",
au: "25+"
},
"Doppelsoldner": {
- nameScheme: "grand",
weapons: [
"2 Main Battery",
"8 Secondary Battery",
},
// http://www.sjgames.com/ogre/articles/csa.html
"CSA-10 (Magi)": {
- nameScheme: "air",
+ nameScheme: "<Flying>",
weapons: [
"2 Bombloads",
"1 Air-to-Air Missile",
propulsion: 48,
},
"CSA-15 (Magi)": {
- nameScheme: "air",
+ nameScheme: "<Flying>",
weapons: [
"4 Bombloads",
"3 Air-to-Air Missiles",