#!/usr/bin/perl -w
#
# Find the shortest path between any two Thaumcraft 4 aspects
# by Pegasus Epsilon <pegasus@pimpninjas.org>
# Distribute Unmodified - http://pegasus.pimpninjas.org/license
use strict;
# aspect database
my %aspects = (
# primary aspects are made of nothing else, they are fundamental
# # terra earth
# # aer air
# # aqua water
# # ignis fire
# # perditio entropy
# # ordo order
# secondary
"gelum" => [ "aqua", "ordo"],# ice
"lux" => [ "aer", "ignis"],# light
"motus" => [ "aer", "ordo"],# movement
"potentia" => [ "ordo", "ignis"],# power
"saxum" => [ "terra" ],# stone
"tempestas" => [ "aer", "aqua"],# storm
"vacuos" => [ "aer", "perditio"],# void
"victus" => [ "aqua", "terra"],# life
# ternary
"bestia" => [ "motus", "victus"],# animal
"fames" => [ "victus", "vacuos"],# hunger
"granum" => [ "victus", "terra"],# seed
"iter" => [ "motus", "terra"],# journey
"limux" => [ "victus", "aqua"],# slime
"metallum" => [ "saxum", "ordo"],# metal
"mortuus" => [ "victus", "perditio"],# death
"permutatio" => [ "motus", "aqua"],# change
"praecantatio" => [ "vacuos", "potentia"],# magic
"sano" => [ "victus", "victus"],# healing
"tenebrae" => [ "vacuos", "lux"],# darkness
"vinculum" => [ "motus", "perditio"],# trap
"vitreus" => [ "saxum", "aqua"],# crystal
"volatus" => [ "motus", "aer"],# flight
"tempus" => [ "vacuos", "ordo"],# time (Thaumic Tinkerer)
# quaternary
"alienis" => [ "vacuos", "tenebrae"],# alien
"auram" => [ "aer", "praecantatio"],# aura
"corpus" => [ "bestia", "mortuus"],# body
"exanimus" => [ "motus", "mortuus"],# resurrection
"herba" => [ "granum", "terra"],# plant
"spiritus" => [ "victus", "mortuus"],# spirit
"venenum" => [ "aqua", "mortuus"],# poison
"vitium" => ["perditio", "praecantatio"],# taint
# quinary
"arbor" => [ "terra", "herba"],# wood
"cognito" => [ "terra", "spiritus"],# mind
"sensus" => [ "aer", "spiritus"],# sense
# senary
"humanus" => [ "bestia", "cognito"],# man
# septenary
"instrumentum" => ["metallum", "humanus"],# tool
"lucrum" => [ "fames", "humanus"],# greed
"messis" => [ "granum", "humanus"],# crop
"perfodio" => [ "saxum", "humanus"],# dig
# octonary
"fabrico" => [ "humanus", "instrumentum"],# make
"machina" => [ "motus", "instrumentum"],# machine
"meto" => [ "messis", "humanus"],# harvest
"pannus" => [ "bestia", "instrumentum"],# fabric
"telum" => ["perditio", "instrumentum"],# weapon
"tutamen" => [ "terra", "instrumentum"] # armor
);
# add reverse associations to the database
for (sort keys %aspects) {
for my $aspect (@{$aspects{$_}}) {
$aspects{$aspect} = [] unless ($aspects{$aspect});
push @{$aspects{$aspect}}, $_ unless ($_ ~~ @{$aspects{$aspect}});
}
}
# oh look, A* path finding, in eight lines of perl
# the longest path is six degrees, but we'll give it 16 degrees to be sure
sub path {
my ($limit, $gap, $target, $path, @results) = (16, shift, shift, shift);
die "Unknown aspect" unless $aspects{$target} && $aspects{$path->[-1]};
do { for (@{$aspects{$path->[-1]}}) {
if ($#{$path} >= $gap && $_ eq $target) {
push @results, [@$path, $_];
$limit = $#{$path};
}
push @_, [@$path, $_];
} } until ($limit < $#{($path = shift)});
return @results;
}
# and then we do the thing
my @path = path($ARGV[0], $ARGV[2], [$ARGV[1]]);
for (@path) {
print "$#{$_}: ", join(", ", @{$_}), "\n";
}