#!/usr/bin/perl -w
#Invention fixer for Victoria II. 
#(c) D.Damerell 2013, GNU General Public License v3 or later.
#
#This assumes that a file composed of all the Vicky II inventions files
#concatenated together in alphabetical order exists in the directory it 
#is run in, called "allinvs" (eg "cat inventions/*txt > allinvs" to make it
#and hopefully you're not in a locale with an oddball alphabet)
#
#It reads a Vicky II save "in.v2", and writes a file called "out.v2".
#
#First of all it adds all invention numbers from the HoD files to the "illegal"
#list for each country. Some inventions are just missing in a converted game,
#and this seems to lead to the "got technology but invention never triggers"
#issue.
#
#For a country with only illegal inventions, it does nothing else.
#This seems to be how the savefile is constructed for an inactive nation.
#
#Otherwise, it ignores "oddball" inventions, those with prerequisites which
#aren't just one technology. (For example, the oligopoly/monopoly/polypoly
#inventions which lock out each other). Those mostly come later in the game
#so should not affect a converted save which hasn't been played.
#
#For non-oddball inventions, if the invention is marked active or possible but
#the country does not have the relevant technology, it marks it illegal.
#
#If the invention is marked illegal, but the country does have the relevant
#technology, it is marked possible. (This will catch inventions added in the
#stage above which added all the ones that were missing altogether).
#
#It is normal that it complains once about a country with no inventions. The
#REB tag is different and has no inventions.
#
#If you tinker with this don't forget the stupid MSDOS line endings in the save
#file matter. If you suddenly become a primitive nation with 0 population you
#forgot about them.
open ALLINVS, "<allinvs";
$invno=0;
while (<ALLINVS>) {
    if (/^([^\#\s]\S+)/) {
	$invens[++$invno]=$1;
	print "Found invention $invno $1.\n";
	$oddball[$invno]=0;
    } elsif (/^\s+limit\s+\=\s+\{/) {
	if (/\{\s+(\S+)\s+\=\s+\d\s+\}\s*$/) {
	    print "Depends on $1\n";
	    $technology[$invno]=$1;
	    push @{$inventions{$1}}, $invno;
	} else {
	    print "But it's an oddball.\n";
	    $oddball[$invno]=1;
	}
    }
}
#We never actually use this
#open ALLTECHS, "<technologies/alltechs";
#$techno=0;
#while (<ALLTECHS>) {
#    if (/^(\S+)\s+\=\s+\{/){
#	$techs[++$techno]=$1;
#	print "Found technology $techno $1:\n";
#	foreach $invno (@{$inventions{$1}}) {
#	    print " $invens[$invno].\n";
#	}
#    }
#}
$foundtag=0;
open INPUT, "<in.v2" or die "Could not read in.v2!\n";
open OUT, ">out.v2";
while (<INPUT>) {
    if (/^([A-Z]{3})\=/) {
	print OUT;
	next if $1=~/REB/;
	$tag=$1; @active=@possible=@illegal=();
	$gottech=0; undef(%techs);
	print "Found tag $tag\n";
	if ($foundtag==0) {
	    $foundtag=1;
	} else {
	    print STDERR "Wah, I haven't tidied up the last country at $tag.\n";
	}
    } elsif (/technology/) {
	print OUT;
	print STDERR "Wah, tech with no country.\n" unless $foundtag;
	$gottech=1;
	while (<INPUT>) {
	    print OUT;
	    if (/^\s+(\S+)\=\{/) {
		$techs{$1}=1;
		print "$tag has technology $1\n";
	    }
	    last if /^\s+\}/;
	}
    } elsif (/inventions/) {
	print STDERR "Wah, inventions with no country.\n" unless $foundtag;
	print STDERR "Wah, inventions with no tech.\n" unless $gottech;
	if (/active_inventions/) {
	    @invs=&readahead;
	    @active=@invs;
	} elsif (/possible_inventions/) {
	    @invs=&readahead;
	    @possible=@invs;
	} elsif (/illegal_inventions/) {
	    @invs=&readahead;
	    @illegal=@invs;
	    @seen=(); $seen[$#invens]=0;
	    foreach $seen (@active,@possible,@illegal) {
		$seen[$seen]=1;
	    }
	    foreach $seen (1..$#invens) {
		if (!$seen[$seen]) {
		    print "Added $invens[$seen] to illegal list\n";
		    push @illegal,$seen;
		}
	    }
	    @newactive=@newpossible=@newillegal=();
	    if (scalar(@active) or scalar(@possible)) {
		foreach $inv (@active) {
		    next unless $inv;
		    if ($oddball[$inv] or $techs{$technology[$inv]}) {
			push @newactive,$inv;
		    } else {
			push @newillegal,$inv;
			print "Moved active $invens[$inv] to illegal list.\n"
		    }
		}
		foreach $inv (@possible) {
		    next unless $inv;
		    if ($oddball[$inv] or $techs{$technology[$inv]}) {
			push @newpossible,$inv;
		    } else {
			push @newillegal,$inv;
			print "Moved poss $invens[$inv] to illegal list.\n"
		    }
		}
		foreach $inv (@illegal) {
		    next unless $inv;
		    if ($oddball[$inv] or !($techs{$technology[$inv]})) {
			push @newillegal,$inv;
		    } else {
			push @newpossible,$inv;
			print "Moved illegal $invens[$inv] to possible list.\n"
		    }
		}
	    } else {
		@newillegal=@illegal;
	    }
	    $foundtag=0;
	    $active=join " ",@newactive;
	    $possible=join " ",@newpossible;
	    $illegal=join " ",@newillegal;
	    if (scalar(@active) or scalar(@possible)) {
		print OUT "\tactive_inventions=\r
\t{\r
\t\t$active\t}\r
\tpossible_inventions=\r
\t{\r
\t\t$possible\t}\r\n";
	    }
	    print OUT "\tillegal_inventions=\r
\t{\r
\t\t$illegal\t}\r\n";
	}
    } else {
	print OUT;
    }
}

exit;

sub readahead {
    while (<INPUT>) {
	last if (/\}/);
    }
    if (/\d/) {
	s/\s+\}//; s/^\s+//;
	return split /\s+/;
    } else {
	return ();
    }
}
	
