如何创建javascript精英行星名称生成器?

时间:2014-04-04 20:34:46

标签: javascript

我尝试将Tricky's script(从精英生成名称)转换为javascript:

https://github.com/rubo77/eliteNameGen/blob/master/elite.js

但是我被这个LPC - 陷入了棘手的代码:

digrams=ABOUSEITILETSTONLONUTHNO..LEXEGEZACEBISOUSESARMAINDIREAERATENBERALAVETIEDORQUANTEISRION
...
pairs = digrams[24..<1];
...
names[0..<2]

我找不到可以解释这种语法的LPC手册。

最后我想创建一个javascript,它会从旧的C64游戏Elite中创建一个随机行星名称。

我还找到了python version,(但这对我来说似乎有点复杂)

2 个答案:

答案 0 :(得分:3)

对于LPC中的范围运算符,此链接有助于:

http://www.unitopia.de/doc/LPC/operators.html

    expr1[expr2..expr3] Extracts a
                    piece from an array or string.
                    expr2 or expr3 may be omitted, default is the begin
                    or end of expr1.
                    Negative numbers for expr2 or expr3
                    mean ``count from before the beginning'', i.e.
                    foo[-2..-1] is an empty array or string.
                    foo[<2..<1] gives the 2nd and last element of
                    the array resp. chars of the string.

所以我猜测:

pairs = digrams[24..<1];

表示从索引24开始到字符串末尾的子字符串?

答案 1 :(得分:3)

好的,我设法将代码移植过来,但我不得不调整一点算法。 Tricky提供的那个由于某种原因产生了非唯一的名称。我使用tweakseed函数来调整种子以生成随机名称列表。

答案

要回答上述问题,@ MattBurland是正确的。您将替换以下代码:

pairs = digrams[24..<1];

pairs = digrams.substring(24);

但是,以下代码实际上是打印出名称列表。所以你要为数组编制索引 - 在这种情况下:

names[0..<2]

变为

for (var i = 0; i < (names.length - 2); i++) {
  names[i]
}

分析

只是为了更深入一点。我已经对代码进行了分析,并意识到rotateltwisttweakseednext仅用于创建随机数。我对LPC了解不多,但我认为当时它可能没有伪随机数生成器。

可以删除大量此代码,并将其替换为Math.random。整个程序的关键部分是变量digram。这个字符序列产生类似外星人的名字。我认为它可能与辅音和元音的交替有关。随机抓取它们几乎总会产生某种辅音+元音配对。有一段奇怪的时间,你会得到一个像Rmrirqeg&#39;这样的名字,但在大多数情况下,这些名字显得像外星人一样。

端口

以下是代码的直接端口。您可以使用此jsFiddle查看它的实际效果,但它使用AngularJS打印出名称,而不是像提供的代码一样打印出列表。 genNames将生成一个名称数组,您可以出于任何原因使用它们。

请注意,此端口仅适用于IE9 +,因为它使用map,reduce和forEach。如果您计划在IE8或更低版本上使用它,请将这些替换为循环。

您可以调整此项以生成更长或更短的名称。但是,名称的长度取决于对数组。使用Math.random或其他东西使它完全狂野。

var digrams = "ABOUSEITILETSTONLONUTHNO" +
    "..LEXEGEZACEBISOUSESARMAINDIREA.ERATENBERALAVETIEDORQUANTEISRION";

function rotatel(x) {
    var tmp = (x & 255) * 2;
    if (tmp > 255) tmp -= 255;
    return tmp;
}

function twist(x) {
    return (256 * rotatel(x / 256)) + rotatel(x & 255);   
}

function next(seeds) {
    return seeds.map(function(seed) {
        return twist(seed);
    });
}

function tweakseed(seeds) {
    var tmp;

    tmp = seeds.reduce(function(total, seed) {
        return total += seed;        
    }, 0);

    return seeds.map( function ( seed, index, arr ) {
        return arr[index + 1] || (tmp & 65535)
    });
};


function makename(pairs, seeds)
{
    var name = [];
    /* Modify pair if you want to have names shorter or longer than 8 chars */
    /* I'll leave that as an exercise for you. */
    var pair = [0, 0, 0, 0];
    var longname = seeds[0] & 64;

    pair = pair.map(function() {
       seeds = tweakseed(seeds);
       return 2 * ((seeds[2] / 256) & 31);  
    });

    pair.forEach(function(value, index, arr) {
        if (longname || ( index < (arr.length - 1))) {
            name.push(pairs[value]);
            name.push(pairs[value + 1]);
        }
    });

    return name.join('').toLowerCase()
            .replace(/^\w/,  function(letter) {
                return letter.toUpperCase(); 
            });
}

function genNames()
{
    var names = [];
    var pairs;
    var num = 256;
    var seeds = [23114, 584, 46931];
    pairs = digrams.substring(24);

    while (--num) {
        names.push( makename(pairs, seeds) );
        seeds = tweakseed(next(seeds));
    }

    return names;
}