<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>thaumcraft thing</title>
<link rel="icon" type="image/gif" href="/images/favicon.gif" />
<link rel="stylesheet" type="text/css" href="/css" />
<style type="text/css">
html, body { height: 100%; width: 100%; }
html { display: table; }
body {
text-align: center;
display: table-cell;
vertical-align: middle;
}
select {
background: #000;
color: #fff;
font-size: 1em;
}
input {
font-size: 1em;
width: .75em;
margin-left: .25em;
text-align: center;
color: #fff;
background: #000;
border: 1px inset;
}
</style>
</head>
<body>
<div><label for="gap">gap:</label><input id="gap" value="2" /></div>
<select size="10"></select>
<select size="10"></select>
<div id="output" style="height: 5em; overflow: auto"></div>
<div style="font-size: .4em">
<div>thaumcraft thing by <a href="mailto:pegasus@pimpninjas.org">Pegasus Epsilon</a></div>
</div>
<script type="text/javascript">
// Array.shuffle please
Array.shuffle = _ => _.sort((a, b) => 0.5 - Math.random());
/* get the selects */
var select = document.getElementsByTagName("select");
/* look, ma, a database */
var aspects = {
// "aer" -- primal
"alienis" : [ "vacuos", "tenebrae" ],
// "aqua" -- primal
// "arbor" : [ "terra", "herba" ], // changed
"arbor" : [ "aer", "herba" ],
"auram" : [ "aer", "praecantatio" ],
"bestia" : [ "motus", "victus" ],
"cognito" : [ "terra", "spiritus" ], // changed
// "cognito" : [ "ignis", "spiritus" ],
"corpus" : [ "bestia", "mortuus" ],
// "desidia" : [ "vinculum", "spiritus" ], // forbidden magic
"exanimus" : [ "motus", "mortuus" ],
"fabrico" : [ "humanus", "instrumentum" ],
"fames" : [ "victus", "vacuos" ],
"gelum" : [ "aqua", "ordo" ], // changed
// "gelum" : [ "ignis", "perditio" ],
// "granum" : [ "victus", "terra" ], // changed/removed
"granum" : [ "victus", "ordo" ],
// "gula" : [ "fames", "vacuos" ], // forbidden magic
"herba" : [ "granum", "terra" ], // changed
// "herba" : [ "victus", "terra" ],
"humanus" : [ "bestia", "cognito" ],
// "ignis" -- primal
// "infernus" : [ "ignis", "praecantatio" ], // forbidden magic
// "instrumentum" : [ "metallum", "humanus" ], // changed
"instrumentum" : [ "ordo", "humanus" ],
// "ira" : [ "telum", "ignis" ], // forbidden magic
"iter" : [ "motus", "terra" ],
"limus" : [ "victus", "aqua" ], // formerly limux
"lucrum" : [ "fames", "humanus" ],
"lux" : [ "aer", "ignis" ],
"machina" : [ "motus", "instrumentum" ],
// "messis" : [ "granum", "humanus" ], // changed
"messis" : [ "herba", "humanus" ],
"metallum" : [ "saxum", "ordo" ], // changed
// "metallum" : [ "terra", "vitreus" ],
// "meto" : [ "messis", "humanus" ], // changed
"meto" : [ "messis", "instrumentum" ],
"mortuus" : [ "victus", "perditio" ],
"motus" : [ "aer", "aqua" ], // changed
// "motus" : [ "aer", "ordo" ],
// "ordo" -- primal
"pannus" : [ "bestia", "instrumentum" ],
// "perditio" -- primal
"perfodio" : [ "saxum", "humanus" ], // changed
// "perfodio" : [ "terra", "humanus" ],
"permutatio" : [ "motus", "aqua" ], // changed
// "permutatio" : [ "ordo", "perditio" ],
"potentia" : [ "ordo", "ignis" ],
"praecantatio" : [ "vacuos", "potentia" ],
"sano" : [ "victus" ], // changed
// "sano" : [ "ordo", "victus" ],
"saxum" : [ "terra" ], // removed
"sensus" : [ "aer", "spiritus" ],
"spiritus" : [ "victus", "mortuus" ],
// "superbia" : [ "volatus", "vacuos" ], // forbidden magic
"telum" : [ "perditio", "instrumentum" ], // changed
// "telum" : [ "ignis", "instrumentum" ],
// "tempestas" : [ "aer", "aqua" ],
"tempestas" : [ "aer", "gelum" ],
"tempus" : [ "vacuos", "ordo" ], // magic bees
"tenebrae" : [ "vacuos", "lux" ],
// "terra" -- primal
"tutamen" : [ "terra", "instrumentum" ],
"vacuos" : [ "aer", "perditio" ],
"venenum" : [ "aqua", "mortuus" ], // changed
// "venenum" : [ "aqua", "perditio" ],
"victus" : [ "aqua", "terra" ],
"vinculum" : [ "motus", "perditio" ],
"vitium" : [ "perditio", "praecantatio" ],
"vitreus" : [ "saxum", "aqua" ], // changed
// "vitreus" : [ "ordo", "terra" ],
"volatus" : [ "motus", "aer" ]
};
/* set up reverse associations */
for (aspect in aspects) {
for (i in aspects[aspect]) {
var ingredient = aspects[aspect][i];
if (!aspects.hasOwnProperty(ingredient))
aspects[ingredient] = [aspect];
else if (0 > aspects[ingredient].indexOf(aspect))
aspects[ingredient].push(aspect);
}
}
/* populate selects with sorted list of aspects */
var keys = Object.keys(aspects).sort();
for (var s = 0; s < select.length; s++) {
for (var k = 0; k < keys.length; k++) {
var option = document.createElement("option");
option.innerHTML = keys[k];
select[s].appendChild(option);
}
select[s].selectedIndex = 0;
}
delete keys;
var output = document.getElementById("output");
function showpaths (paths) {
output.innerHTML = '';
for (var i in paths) {
var path = document.createElement("div");
if (i % 2) path.style.background = "#111";
path.innerHTML = "["+paths[i].join(", ")+"]";
output.appendChild(path);
}
}
var gap = document.getElementById("gap");
function findpath () {
var startTime = Date.now();
var end = select[1].value;
/* hmm */
// if (0 == gap.value && end == select[0].value) return showpaths([[end]]);
var limit = 16;
var path = [select[0].value];
var paths = [];
var queue = [];
do {
var aspect = aspects[path[path.length - 1]];
for (var i = 0; i < aspect.length; i++) {
var current = aspect[i];
if (path.length > gap.value && end == current) {
paths.push(path.concat([current]));
limit = paths[paths.length - 1].length;
}
queue.push(path.concat([current]));
}
if (Date.now() - startTime > 500) return showpaths(Array.shuffle(paths));
} while (limit > (path = queue.shift()).length);
return showpaths(Array.shuffle(paths));
}
/* set up event handler */
for (var i = 0; i < select.length; i++) { select[i].onchange = findpath; }
gap.onfocus = gap.select;
gap.onkeyup = function () {
this.select();
if (gap.value > 5)
alert("Paths this long will probably not return all paths (or necessarily any at all!). It may be best to choose a random Aspect for the middle-ish of the path and connect those instead.");
findpath();
}
gap.onmouseup = function () { return false; }
findpath();
select[0].focus();
document.onkeydown = function (e) {
if (37 == e.keyCode) select[0].focus();
else if (39 == e.keyCode) select[1].focus();
}
</script>
</body>
</html>