#!/usr/bin/perl -w

# Contains routines to create startingpoint patrolroutes etc

# usage: 

# use Route;

# $ru1 = Cowgen::Route->create(); # empty route
# $ru1->addPoint ( 0,0,0 ); # add a point as last
# $ru1->addPoint ( 0,10,0 ); # add another point as last
# $ru1->addPoint ( 20,0,0,1 ); # add another point between 0, and last point
# $ru1->replacePoint ( 10,0,0,1 ); # replace it
# # shorter variant:
# $ru2 = Cowgen::Route->create( 0,0,0, 10,0,0, 10,10,0 ); # three pointroute
# #or use :
# $names = { 0 => "kitchen_000", 1 => "hallway_000" };
# $ru = Cowgen::Route->fromNames($tp, $names);

# (c) Copyright by Tels 1999. All Rights Reserved. Do NOT distribute.
# Updates and support on bloodgate.com/thief
# Thanx to Doug Church at TLG

# 1999-12-19 v0.0.1 - first (startingpoint and stubs)
# 1999-12-20 v0.0.2 - completed all the route stuff 
# 1999-12-25 v0.0.3 - did I say "completed"? added: circular backnforth
# 2000-01-07 v0.0.4 - added FromNames

package Cowgen::Route;
require Exporter;
@ISA    = qw(Exporter);
@EXPORT = qw( 
            circular backnforth shuffle
            );
#@EXPORT_OK = qw();

#doc: create addPoint replacePoint numPoints asBunch asText
#doc: fromNames 

use Cowgen::Bunch;
use strict 'vars';

my $count = "000";

sub circular { 0; } # default
sub backnforth { 1; }
sub shuffle { 0x100; }

sub create 
  { 
  # create route object
  # parameters: x,y,z (actually list of x;y;z pairs)
  my $c = shift; 
  my $s = {}; bless $s, $c; $s->init(@_); 
  return $s; 
  }

sub fromNames
  { 
  # create route object out of a list of terrain points and patrol 
  # point names
  # parameters: terrainpointlist (ref, delivered by worldAsBunch),
  # namelist (ref to hash)
  my ($c,$tp,$names) = @_;  
  my $s = {}; bless $s, $c; 
  $s->{points} = [];
  my ($tph,$n,$t,$p,$ln);
  foreach $n (keys %{$names})
    {
    $tph = $names->{$n};
    if (ref($tph) ne "HASH")
      {
      $tph = { name => $tph }; # make dummy hash
      }
    $t = $tp->{$tph->{name}};
    if (!defined $t)
      {
      # fuzzy search
      $ln = lc($tph->{name});
      foreach $p (keys %{$tp})
        {
        if (lc($p) =~ /$ln/) { $t = $tp->{$p}; last; }
        }      
      }
    if (!defined $t)
      {
      print "Route.pm: Warning: Cant find terrain point for '$tph->{name}'.\n"; 
      next;
      }
#    print "$n => $names->{$n}: $t->[0], $t->[1], $t->[2]\n";
    $s->replacePoint ($n, $t->[0], $t->[1], $t->[2] );
    }
  return $s; 
  }

sub init
  {
  my $s = shift; 
  $s->{points} = [];
  my ($x,$y,$z);
  while (@_ > 0)
    {
    $x = shift || 0; $y = shift || 0; $z = shift || 0;
    $s->addPoint ($x,$y,$z,-1);
    }
  }

sub replacePoint
  { 
  # replace a point (defined by its index), or add it when it
  # was not there
  # parameters: index (-1 meaning last patrol point), 
  # x,y,z 
  my $s = shift; 
  my $i = shift || 0; 
  $s->{points}->[$i] = [ @_ ];
  return scalar @{$s->{points}}; # number of points
  }

sub addPoint
  { 
  # add a point to patrol route
  # parameters: first index (defaults to -1; meaning last patrol point),
  # x,y,z (actually list of x,y,z triples)
  my $s = shift; 
  my $i = shift || -1; 
  my ($x,$y,$z,$p);
  while (@_ > 0)
    {
    $x = shift || 0; $y = shift || 0; $z = shift || 0;
    $p = [ $x,$y,$z ];
    if ($i < 0)
      {
      push (@{$s->{points}}, $p);
      }
    else
      {
      splice (@{$s->{points}}, $i, 0, $p);
      }
    }
  return scalar @{$s->{points}}; # number of points
  }

sub numPoints
  {
  # return number of points in route
  my $s = shift;
  return scalar @{$s->{points}};
  }

sub asBunch
  {
  # generate bunch with markers from route and connect them in
  # a circle, forthnback doesnt work yet
  # parameters: gamefile, type (circular() or forthnback(); + shuffle())
  my $s = shift || return;
  my $gf = shift || return;
  my $type = shift || circular();
  my $shuffle = $type >> 8; $type = $type & 0xFF;
  my $b = Cowgen::Bunch->create("patrol##num##");
  my ($p,$po,$last,$first,$x,$y,$z,$n);
  my $ob = { base => $gf->obj("TrolPt") };
  $n ="Route##num##"; $n =~ s/##num##/ $count++; /e; 
  my $i = 0; 
  foreach $p (@{$s->{points}})
    {
    next if (!defined $p); # skip holes in index
    $ob->{name} = $n . "_$i"; $i++; 
    ($x,$y,$z) = @$p;
    if ($shuffle != 0)
      {
      $x += int(rand(5))/4-0.5;
      $y += int(rand(5))/4-0.5;
      $z += int(rand(5))/4-0.5;
      }
    $po = $b->addObject ($x,$y,$z, 0,0,0, $ob);
  #  print "$i $po => $p->[0], $p->[1], $p->[2] => $x, $y, $z\n";
    $first = $po if ($i == 1); # store first point
    if (defined $last)
      {
      $b->addLink ($last,$po, $gf->flavour("AIPatrol") );
      }
    $last = $po;
    }
  if ((defined $first) && ($first != $last) && ($type == circular()))
    {
    $b->addLink ($last,$first, $gf->flavour("AIPatrol") );
    }
  $b; # route
  }

sub asText
  {
  # generate text with markers from route, not ready yet
  my $s = shift;
  my $t = " Route\n  {\n";
  $t .= "  # not ready yet\n  } # route\n";
  $t; # route
  }

1;

