如何创建一个 JavaScript 精英行星名称生成器
How do I create a javascript elite planet name generator?
我尝试在这里将Tricky的脚本(从精英中生成一个名称)转换为javascript:
https://github.com/rubo77/eliteNameGen/blob/master/elite.js
但是我被Tricky的这个LPC代码卡住了:
digrams=ABOUSEITILETSTONLONUTHNO..LEXEGEZACEBISOUSESARMAINDIREAERATENBERALAVETIEDORQUANTEISRION
...
pairs = digrams[24..<1];
...
names[0..<2]
我找不到可以解释此语法的 LPC 手册。
最后,我想创建一个javascript,从旧的C64游戏Elite创建一个随机的星球名称。
我还找到了一个python版本,(但这对我来说似乎有点复杂)
我设法移植了代码,但我不得不调整一些算法。由于某种原因,Tricky 提供的那个会产生非唯一名称。我使用调整种子函数来调整种子以生成随机名称列表。
答
要回答上面的问题,@MattBurland是正确的。您将替换以下代码:
pairs = digrams[24..<1];
跟
pairs = digrams.substring(24);
但是,以下代码实际上是打印出名称列表。所以你正在索引一个数组 - 在这种情况下:
names[0..<2]
成为
for (var i = 0; i < (names.length - 2); i++) {
names[i]
}
分析
只是为了给它更多的深度。我分析了代码,意识到rotatel
、twist
、tweakseed
和next
只是用来创建随机数的。我对LPC不够了解,但我认为当时它可能没有伪随机数生成器。
很多这样的代码可以删除,只是用Math.random
替换。整个程序的关键部分是 变量digram
.这一系列角色产生了类似外星人的名字。我想这可能与辅音和元音的交替有关。随机成对抓取它们几乎总是会产生某种辅音 + 元音配对。有一个奇怪的时间,你最终会得到一个像"Rmrirqeg"这样的名字,但在大多数情况下,这些名字看起来像外星人。
港口
下面是代码的直接端口。您可以使用此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;
}
对于 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
开始到字符串的末尾?