#!/usr/bin/perl

use warnings;
use strict;

#====================================================================
# собственно сам генератор файлов
#====================================================================
use Getopt::Long;
select STDERR; $|=1; select STDOUT;

my ($output_file, $header_file, $input_file);

sub usage()
{
  print <<eof;
  Usage $0 input_file [ -c output_file.c ] [ -h output_file.h ]
eof
  exit -1;
}


GetOptions(
  "c=s"       =>  \$output_file,
  "h=s"       =>  \$header_file,
)  or usage;

$input_file=shift @ARGV or usage;

# если указан выходной файл то делаем его
# вместо stdout
if ($output_file)
{
  open OUTPUT, ">", $output_file 
    or die "Can not open '$output_file': $!";
  select OUTPUT;
}


# читаем конфиг-файл
open my $config, "<", $input_file 
  or die "Can not open '$input_file': $!";
my @lines=grep /^\s*unit\d/, <$config>;
close $config;

s/\s+$//, s/^\s+//, s/#.*$// for @lines;

my @units;

# сюда складываем некоторые defines'ы для h-файла
my @defines; 

for (my $uno=1; my @ulines=grep /^unit$uno\./, @lines; $uno++)
{
  my %unit;

  for my $field (qw(name order structure 
      shield attack capacity ground metal crystal deut
      large_chargo small_chargo recycler))
  {
    ($unit{$field})=grep /^unit$uno\.$field/, @ulines 
      and $unit{$field}=~s/^.*?=\s*//;
    defined $unit{$field} or $unit{$field}=0;
  }

  unless ($unit{metal}+$unit{crystal}==$unit{structure}) 
  {
    print STDERR "'$unit{name}': error defined cost parameters\n",
      "\tmetal=$unit{metal}\n\tcrystal=$unit{crystal}\n\t",
      "deuterium=$unit{deut}\n\tstructere=$unit{structure}\n";
    exit 10;
  }

  my @rapid;

  for (my $rno=1; my @rlines=grep /^unit$uno\.rapid$rno\./, @ulines; $rno++)
  {
    my ($rapin_unit)=grep /unit$uno\.rapid$rno\.name/, @rlines;
    my ($rapin_value)=grep /unit$uno\.rapid$rno\.value/, @rlines;
    $rapin_unit=~s/^.*?=\s*//; $rapin_value=~s/^.*?=\s*//;
    push @rapid, [ $rapin_unit => $rapin_value ];
  }

  $unit{rapids}=\@rapid if @rapid;
  push @units, \%unit;
}
@units=sort { $a->{order} <=> $b->{order} } @units;

print <<eof;
/* 
  Этот файл сгенерирован при помощи утилиты '$0'
  поэтому менять его руками не стоит.
  При генерации данные взяты из файла '$input_file'

*/
eof
print qq(#include "unit.h"\n\n);
print "/* Oбщее описание юнитов */\n";
print "unit_info units[]=\n{\n";
my ($rno, $maxrapids)=(1,0);

my $uno=0;
for (@units)
{
  print "  {\n    \"$_->{name}\" /* name */,\n";


  for my $field(qw(shield structure attack capacity metal crystal deut))
  {
    printf "    %-8d /* %s */,\n", $_->{$field}, $field;
  }
  
  print "    {\n";
  for my $field (qw(ground large_chargo small_chargo recycler))
  {
    printf "      %-6d /* %s */,\n", $_->{$field}, $field;

    if ($field ne 'ground' and $_->{$field})
    {
      my $name=$field;
      $name=~tr/a-z/A-Z/;
      push @defines, "#define $name $uno";
    }
  }
  print "    },\n";
  
  if ($_->{rapids})
  {
    printf "    %-8d /* rapidno */\n", $rno;
    $rno++;
    $maxrapids=scalar @{$_->{rapids}} 
      if $maxrapids < scalar @{$_->{rapids}};
  }
  else 
  {
    printf "    %-8d /* rapidno */\n", 0;
  }
  print "  },\n";
  $uno++;
}
print "};\n\n";

my $units_count=scalar @units;
$maxrapids++;
print "/* Скорострелы */\n";
print "rapidfire rapids[$rno][$maxrapids]=\n{\n";

print "  { { 0, 0, 0 }, },\n";
for my $unit (@units)
{
  defined $unit->{rapids} or next;
  print "\n  /* $unit->{name} */\n  {\n";
  
  for (@{$unit->{rapids}})
  {
    my ($uname, $rapid)=@{$_};
    my $uid=0;
    
    # определяем ID юнита против которого скорострел
    for ($uid=0; $uid<scalar @units; $uid++)
    {
      $uname eq $units[$uid]->{name} and last;
    }

    my $chance=0;

    # шанс = (1/e) в степени 1/скорострел
    $rapid and $chance=1-(1/$rapid);

    printf "    { %2d, %5d, $chance },\n", $uid, $rapid;
  }
  print "  },\n";
}
print "};\n";


select STDOUT;
if ($header_file)
{
  open HEADER, ">", $header_file
    or die "Can not open '$header_file': $!";
  select HEADER;
}

my $defines=join "\n", @defines;

print <<eof;
#ifndef __UNITS__INFO__H__
#define __UNITS__INFO__H__

#include "unit.h"
/*
  Этот файл сгенерирован при помощи утилиты '$0'
  поэтому менять его руками не стоит.
  При генерации данные взяты из файла '$input_file'
*/

#define UNITS_COUNT   $units_count
#define RAPIDS_COUNT  ($maxrapids-1)

$defines

extern unit_info units[$units_count];
extern rapidfire rapids[$rno][$maxrapids];

#endif
eof

