#!/usr/bin/perl use strict; use warnings; use lib "../adv"; use include; # CONFIGURATION die "Usage: sim.pl [unit_size] [map] [single|multi] [rndfile|-]\n" unless @ARGV == 4; my ($unit_size, $area, $mode, $rnds) = @ARGV; # Rnd Starting Positions CONFIG->rndload("../sim/$rnds") unless $rnds eq "-"; #my $unit_size = 20; # [small], [large] #my $area = "halls"; # beard, halls, squiggle #my $mode = "single"; # single, multi # SET UP UI use HexedUI; my $ui = create HexedUI { Main => { Type => "Map", At => [0, 0], Size => ["100%", "100%"], Border => 1, Render => sub { my $tile = shift; my ($char, $color); if (ref $tile->{_}) { ($char, $color) = $tile->{_}->symbol; } elsif ($tile->{color}) { $char = $tile->{_}; $color = $tile->{color}; } else { $char = $tile->{_}; $color = { "#" => "orange", "." => "grey" }->{$char}; $color ||= "yellow"; } return ord($char) | HexedUI::paint($color); } }, }; GAME->{UI} = $ui; # SET UP MAP use BDSM::Transform; my $map = loadmap("../maps/$area"); $ui->{Main}->setup($map); $map->{OnChange} = sub { my ($map, $y, $x, $new) = @_; $ui->{Main}->_mod($y, $x, $map->{Map}[$y][$x]); }; use Highway; preprock($map); sub run { # ################################################################### # Initialize units use Unit; my @units; GAME->{UnitSize} = $unit_size; # leader needs to know to make room foreach (1 .. $unit_size) { my $unit = GAME->{Classes}{Unit}->new(Map => $map, Num => $_); if ($_ == 1) { $unit->{Magnet}{Last} = "h"; } else { $unit->{Magnet}{Buddy} = $units[$_ - 2]; # Whilst assembling, just form a line. $unit->{Magnet}{Dir} = [0, 1]; } push @units, $unit; } # Choose a random destination. my ($goy, $gox); while (1) { $goy = CONFIG->random(0, $map->height); $gox = CONFIG->random(0, $map->width); my $tile = $map->{Map}[$goy][$gox]; last if $map->{Map}[$goy][$gox]{Hiway}; } # ################################################################## # PART ONE: Assembly # Single: Find the highway and then our buddy, then give control to next unit. # Multi: Everybody find the highway at once. If our buddy is on too, find # them; otherwise wait. GAME->{AssCnt} = 0; my %found; while (1) { my $cntr = 0; foreach my $unit (@units) { if ($mode eq "single") { 1 until $unit->gethi; 1 until $unit->assemble == 42 and $unit->{Laster} = [$unit->{Y}, $unit->{X}]; $cntr++; } else { $unit->gethi and $found{ $unit->{Num} }++ unless $found{ $unit->{Num} }; next unless $found{ $unit->{Num} }; $unit->assemble == 42 and $unit->{Laster} = [$unit->{Y}, $unit->{X}] and $cntr++; } } last if $cntr == @units; } $units[0]->{Magnet}{Buddy} = { Y => $goy, X => $gox, Laster => [-1, -1] }; $units[0]->{Magnet}{Dir} = [0, 0]; # PART TWO: Movement # Single & Multi: Follow our buddy until everybody reaches the destination. GAME->{MvCnt} = 0; while (1) { GAME->{UI}{Main}->draw; debug "to $goy, $gox. at $units[0]->{Y}, $units[0]->{X}" if $map->{Map}[$goy][$gox]{_} ne "."; foreach my $unit (@units) { ($unit->{Num} == 1) ? ctrl($goy, $gox, @units) : $unit->magnet($goy, $gox); } } } sub ctrl { my $goy = shift; my $gox = shift; my $me = shift; debug "to $goy, $gox. at $me->{Y}, $me->{X}"; my @units = @_; GAME->{MvCnt}++; my $code = $me->assemble(42); die "SUCCESS. Ass " . GAME->{AssCnt} . ". Mv " . GAME->{MvCnt} . "." if $me->{Y} == $goy and $me->{X} == $gox; return unless $code; my $in = { 1 => "k", 2 => "j", 3 => "h", 4 => "l", 5 => "y", 6 => "u", 7 => "b", 8 => "n", }->{$code}; # Update the vectors for the troops. $_->{Magnet}{Dir} = { l => [0, -1], h => [0, +1], k => [+1, 0], j => [-1, 0], y => [+1, +1], u => [+1, -1], b => [-1, +1], n => [-1, -1], }->{$in} foreach @units; } run;