#!/usr/bin/perl # # This program simulates a battle to the death between two space fleets # in Anacreon. # # # This program may be freely redistributed and modified, as long as the # revisions history remains complete and accurate. # # # Revisions History: # # # v 1.0.0 01 Jan 2002 Christopher Thomas # This version allows only one ship type per fleet. # # Known Bugs: # none # # Change Requests: # - Allow fleets of mixed ship types. # - Write a Perl/Tk wrapper script to provide a GUI front-end if desired. # # # Libraries # use strict; # # Constants # # Combat efficiency table. # Lifted from "http://www.anacreon.hoffyland.com/a-strat-info.html". # First index is attacker. Second index is defender. my (%attack_table); %attack_table = ( 'trn'=> { 'trn'=>0.05, 'jtn'=>0.01, 'fgt'=>0.12, 'jmp'=>0.00, 'hkr'=>0.00, 'pen'=>0.00, 'str'=>0.00 }, 'jtn'=> { 'trn'=>0.10, 'jtn'=>0.05, 'fgt'=>0.25, 'jmp'=>0.01, 'hkr'=>0.01, 'pen'=>0.00, 'str'=>0.00 }, 'fgt'=> { 'trn'=>0.25, 'jtn'=>0.20, 'fgt'=>0.25, 'jmp'=>0.08, 'hkr'=>0.15, 'pen'=>0.12, 'str'=>0.01 }, 'jmp'=> { 'trn'=>1.50, 'jtn'=>0.50, 'fgt'=>1.50, 'jmp'=>0.38, 'hkr'=>0.25, 'pen'=>0.25, 'str'=>0.01 }, 'hkr'=> { 'trn'=>0.75, 'jtn'=>0.50, 'fgt'=>0.50, 'jmp'=>0.75, 'hkr'=>0.50, 'pen'=>0.50, 'str'=>0.04 }, 'pen'=> { 'trn'=>2.50, 'jtn'=>1.25, 'fgt'=>0.50, 'jmp'=>1.05, 'hkr'=>0.65, 'pen'=>0.50, 'str'=>0.05 }, 'str'=> { 'trn'=>5.00, 'jtn'=>5.00, 'fgt'=>10.00, 'jmp'=>3.00, 'hkr'=>2.50, 'pen'=>1.00, 'str'=>0.15 } ); # # Helper Functions # # Prints a help screen. # No arguments. # No return value. sub PrintHelp { print << "Endofblock"; Usage: anacreon-combat.pl "a" is the attacking force, and "d" is the defending force. is in the range of 1-9999. is one of "trn", "jtn", "fgt", "jmp", "hkr", "pen", "str". Endofblock } # Prints the result of a battle. # Argument values are assumed to be checked by the caller. # Arg 1 is the number of ships in the attacking fleet. # Arg 2 is the attacking ship type. # Arg 3 is the number of ships in the defending fleet. # Arg 4 is the defending ship type. # No return value. sub PrintBattleResult { my ($acount, $atype, $dcount, $dtype); my ($rcount); my ($old_acount, $old_dcount); # Get args. $acount = $_[0]; $atype = $_[1]; $dcount = $_[2]; $dtype = $_[3]; # Sanity check. if (!( (defined $acount) && (defined $atype) && (defined $dcount) && (defined $dtype) )) { die "Bad arguments passed to PrintBattleResult()"; } else { # Padding. print "\n"; $rcount = 1; $old_acount = -1; $old_dcount = -1; while ( ($acount > 0) && ($dcount > 0) && (($old_acount != $acount) || ($old_dcount != $dcount)) ) { # Print status. printf ("Round %2d: %4d %s vs. %4d %s\n", $rcount, $acount, $atype, $dcount, $dtype); # Update ship counts. $old_acount = $acount; $old_dcount = $dcount; $acount = $old_acount - ($old_dcount * $attack_table{$dtype}{$atype}); $dcount = $old_dcount - ($old_acount * $attack_table{$atype}{$dtype}); $acount = int($acount); $dcount = int($dcount); # Increment round number. $rcount++; } # Sanify final numbers. if ($acount < 0) { $acount = 0; } if ($dcount < 0) { $dcount = 0; } # Print final result. printf ("Result : %4d %s vs. %4d %s\n", $acount, $atype, $dcount, $dtype); # Padding. print "\n"; } } # # Main Program # my ($acount, $atype, $dcount, $dtype); # Read args. $acount = $ARGV[0]; $atype = $ARGV[1]; $dcount = $ARGV[2]; $dtype = $ARGV[3]; # Check args. if (!( (defined $acount) && (defined $atype) && (defined $dcount) && (defined $dtype) )) { # Not enough args. Print help screen. PrintHelp(); } elsif (($acount < 1) || ($acount > 9999) || ($dcount < 1) || ($dcount > 9999)) { print "\nShip counts must be in the range 1-9999.\n\n"; } elsif (! (defined ($attack_table{$atype}{$dtype})) ) { print "\nShip types must be one of \"trn\", \"jtn\", \"fgt\"," ." \"jmp\", \"hkr\", \"pen\", \"str\",\n" ."in lower-case, without the \" marks.\n\n"; } else { # Input looks ok. # Simulate the battle. PrintBattleResult(int($acount), $atype, int($dcount), $dtype); } # # This is the end of the file. #