Last active
December 24, 2015 08:25
-
-
Save musiKk/7134d4c5b602eb392149 to your computer and use it in GitHub Desktop.
AoC 23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env perl | |
| use strict; | |
| use warnings; | |
| use v5.20; | |
| use List::Util qw/ min max /; | |
| use Data::Dumper; | |
| $Data::Dumper::Indent = 0; | |
| $Data::Dumper::Terse = 1; | |
| my $hard_mode = 1; | |
| my @spells = ( | |
| # name , cost, timer, dmg, heal, armor, mana recharge | |
| [ 'missile' , 53, 1, 4, 0, 0, 0 ], | |
| [ 'drain' , 73, 1, 2, 2, 0, 0 ], | |
| [ 'shield' , 113, 6, 0, 0, 7, 0 ], | |
| [ 'poison' , 173, 6, 3, 0, 0, 0 ], | |
| [ 'recharge', 229, 5, 0, 0, 0, 101 ] | |
| ); | |
| my ($monster_hp, $monster_dmg) = (51, 9); | |
| my ($hp, $mana) = (50, 500); | |
| # my ($monster_hp, $monster_dmg) = (13, 8); | |
| # my ($hp, $mana) = (10, 250); | |
| # name -> spell | |
| my %current_spells = (); | |
| say recurse([ $hp, $mana ], [ $monster_hp, $monster_dmg ], \%current_spells, 0, 0); | |
| sub recurse { | |
| my ($me, $monster, $current_spells, $mana_spent, $depth) = @_; | |
| my @manas_spent = (); | |
| for my $spell (@spells) { | |
| # copies for the recursion | |
| my $new_me = [ @$me ]; | |
| my $new_monster = [ @$monster ]; | |
| my $new_current_spells = { map | |
| { $_ => [ @{$current_spells->{$_}} ] } | |
| keys %$current_spells }; | |
| my $new_mana_spent = $mana_spent + $spell->[1]; | |
| # player turn | |
| if ($hard_mode) { | |
| $new_me->[0]--; | |
| if ($new_me->[0] <= 0) { | |
| next; | |
| } | |
| } | |
| apply_spells($new_me, $new_monster, $new_current_spells, $depth); | |
| next if exists $new_current_spells->{$spell->[0]}; | |
| next if $spell->[1] > $me->[1]; | |
| # msay($depth, Dumper($me) . ' v ' . $monster->[0] . ' active spells ' . join ', ', sort keys %$current_spells); | |
| # msay($depth, 'player casts ' . $spell->[0]); | |
| $new_me->[1] -= $spell->[1]; | |
| if ($spell->[0] eq 'missile' || $spell->[0] eq 'drain') { | |
| $new_monster->[0] -= $spell->[3]; | |
| $new_me->[0] += $spell->[4]; | |
| } else { | |
| $new_current_spells->{$spell->[0]} = [ @$spell ]; | |
| } | |
| # msay($depth, 'current spells now ' . join ', ', sort keys %$new_current_spells); | |
| if ($new_monster->[0] <= 0) { | |
| # msay($depth, "win with mana spent $new_mana_spent"); | |
| push @manas_spent, $new_mana_spent; | |
| next; | |
| } | |
| # monster turn | |
| apply_spells($new_me, $new_monster, $new_current_spells, $depth); | |
| if ($new_monster->[0] <= 0) { | |
| # msay($depth, "win with mana spent $new_mana_spent"); | |
| push @manas_spent, $new_mana_spent; | |
| next; | |
| } | |
| my $my_armor = exists $current_spells->{'shield'} ? 7 : 0; | |
| my $monster_dmg = max(1, $new_monster->[1] - $my_armor); | |
| $new_me->[0] -= $monster_dmg; | |
| # msay($depth, "monster attacks for $monster_dmg (armor $my_armor, @{[$new_me->[0]]} remaining)"); | |
| if ($new_me->[0] <= 0) { | |
| # msay($depth, "lost!"); | |
| next; | |
| } | |
| push @manas_spent, recurse($new_me, $new_monster, $new_current_spells, $new_mana_spent, $depth + 1); | |
| } | |
| return 100000 if 0 == scalar(@manas_spent); | |
| return min(@manas_spent); | |
| } | |
| sub apply_spells { | |
| my ($me, $monster, $current_spells, $depth) = @_; | |
| for my $spell_name (keys %$current_spells) { | |
| my $spell = $current_spells->{$spell_name}; | |
| # msay($depth, "using $spell_name dealing @{[$spell->[3]]} damage"); | |
| $monster->[0] -= $spell->[3]; | |
| $me->[1] += $spell->[6]; | |
| $spell->[2]--; | |
| # my $description = 'MISSING DESCRIPTION'; | |
| # if ($spell_name eq 'missile') { | |
| # $description = "Player casts magic missile, dealing @[{$spell->[3] damage"; | |
| # } elsif ($spell_name eq 'drain') { | |
| # $description = "Player casts drain, dealing @[{$spell->[3]]} damage and healing @{[$spell->[4]]} hit points"; | |
| # } else { | |
| # if ($spell_name eq 'shield') { | |
| # $description = 'shield'; | |
| # } elsif ($spell_name eq 'poison') { | |
| # $description = "poison deals @{[$spell->[3]]} damage"; | |
| # } elsif ($spell_name eq 'recharge') { | |
| # $description = "recharge provides @{[$spell->[6]]} mana"; | |
| # } | |
| # $description .= "; it's timer is now @{[$spell->[2]]}"; | |
| # } | |
| # msay($depth, $description); | |
| # msay($depth, $spell_name . ' wears off') if $spell->[2] <= 0; | |
| delete $current_spells->{$spell_name} if $spell->[2] <= 0; | |
| } | |
| } | |
| sub msay { | |
| my ($depth, @list) = @_; | |
| say '| 'x$depth, @list; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment