#!/usr/bin/env perl use strict; use warnings; use Getopt::Long; use List::Util 'max'; use Games::SMTNocturne::Demons; sub _demon { Games::SMTNocturne::Demons::demon(@_) } sub _fuse { Games::SMTNocturne::Demons::fuse(@_) } sub _fusions_for { Games::SMTNocturne::Demons::fusions_for(@_) } my $command = shift @ARGV; my ($max_level, $deathstones, $kagatsuchi, $bosses); GetOptions( "max_level=i" => \$max_level, "deathstones=i" => \$deathstones, "kagatsuchi=i" => \$kagatsuchi, "boss=s@" => \$bosses, ) or die "couldn't parse options"; my $options = { max_level => $max_level, deathstone => $deathstones, kagatsuchi => $kagatsuchi, bosses => $bosses, }; if ($command !~ /^_/ && defined &$command) { { no strict 'refs'; &{ $command }(@ARGV) } } else { die "unknown command $command"; } sub demon { my ($demon) = @_; print _demon($demon), "\n"; } sub fuse { my ($demon1, $demon2) = @_; print _fuse($demon1, $demon2, $options), "\n"; } sub fusions_for { my ($demon) = @_; print join("\n", _fusions_for($demon, $options)), "\n"; } sub min_level_for { my ($demon) = @_; my @fusions = _fusions_for($demon, $options); my $min_level = 99; my @min_level_fusions; for my $fusion (@fusions) { my $max_level = max(map { $_->level } $fusion->all_demons); if ($max_level < $min_level) { @min_level_fusions = ($fusion); $min_level = $max_level; } elsif ($max_level == $min_level) { push @min_level_fusions, $fusion; } } print "Level $min_level:\n"; print join("\n", @min_level_fusions), "\n"; } sub party_fusion { my @demons = @_; my $seen = _party_fusion_recursive_fuse( {}, $deathstones, map { _demon($_) } @demons ); print join("\n", sort { $a->level <=> $b->level } map { _demon($_) } keys %$seen ), "\n"; } sub _party_fusion_recursive_fuse { my ($seen, $deathstones, @demons) = @_; $seen->{$_} = 1 for map { $_->name } @demons; if (@demons > 1) { my $check_fusion = sub { my ($demon1, $demon2, $sacrifice, $phase) = @_; my $fused = _fuse( $demon1, $demon2, { %$options, sacrifice => $sacrifice, deathstone => $deathstones, kagatsuchi => $phase, }, ); return unless $fused; return if defined $max_level && $fused->level > $max_level; my @new_party = ( $fused, grep { $_ ne $demon1 && $_ ne $demon2 && (!$sacrifice || $_ ne $sacrifice) } @demons ); _party_fusion_recursive_fuse( $seen, ($fused->type eq 'Fiend' ? $deathstones - 1 : $deathstones), @new_party ); }; for my $demon1 (@demons) { for my $demon2 (grep { $_ ne $demon1 } @demons) { if ($deathstones) { for my $phase (0..8) { $check_fusion->($demon1, $demon2, undef, $phase); } } else { $check_fusion->($demon1, $demon2); } for my $demon3 (grep { $_ ne $demon1 && $_ ne $demon2 } @demons) { $check_fusion->($demon1, $demon2, $demon3); } } } } return $seen; }