#!/usr/bin/perl
# -*- perl -*-

require "./mkmap.pl";

$width = 13;
$height = 13;

$roomsize = 256;
$roomheight = 100;
$roomrand = 150;
$roofheight = 350;
$pillarsize = 32;
$pillarheight = $roomheight+8;
$skyheight = 1000;
$wallthick = 8;
$splay = 0;

$tga = $ARGV[0];
$tga =~ s/\.map$//;

$pillartex = 'gothic_wall/support2b';
$walltex = 'gothic_wall/goldbrick';
$floortex = 'gothic_floor/largerblock3b2';
$mazetex = "maze/$tga";
$rooftex = 'skies/toxicsky';
$notex = 'house/wkitchen';

########################################

$mx = int($width/2);
$my = int($height/2);

srand(time() ^ $$);

for ($x=0; $x<$width; $x++) {
    for ($y=0; $y<$height; $y++) {
	$maze{"$x $y"} = '----';
    }
}
for ($x=-1; $x<=$width; $x++) {
    $maze{"$x -1"} = '####';
    $maze{"$x $height"} = '####';
}
for ($y=-1; $y<=$height; $y++) {
    $maze{"-1 $y"} = '####';
    $maze{"$width $y"} = '####';
}

sub draw_maze {
    for ($x=-1; $x<=$width; $x++) {
	for ($y=-1; $y<=$height; $y++) {
	    print $maze{"$x $y"}, "  ";
	}
	print "\n";
    }
}

%setcs = ('u', 0, 'd', 1, 'l', 2, 'r', 3);
%setop = ('u', 'd', 'd', 'u', 'l', 'r', 'r', 'l');
%setdx = ('u', 0, 'd', 0, 'l', -1, 'r', 1);
%setdy = ('u', -1, 'd', 1, 'l', 0, 'r', 0);
sub set {
    my ($x, $y, $c) = @_;
    #print "set $x $y $c `", $maze{"$x $y"}, "' $setcs{$c}\n";
    substr($maze{"$x $y"}, $setcs{$c}, 1) = $c;
    $x += $setdx{$c};
    $y += $setdy{$c};
    substr($maze{"$x $y"}, $setcs{$setop{$c}}, 1) = $setop{$c};
}

sub peek {
    my ($x, $y, $c) = @_;
    $x += $setdx{$c};
    $y += $setdy{$c};
    return '*' if $maze{"$x $y"} eq '----';
    return substr($maze{"$x $y"}, $setcs{$setop{$c}}, 1);
}

&set($mx, $my, substr('udlr', rand(4), 1));
$left = $width * $height - 2;

while ($left > 0) {
    &find_starting_point();
    0 while (&wander() && rand(5) > 1);
}

sub find_starting_point {
    while (1) {
	$x = int(rand($width));
	$y = int(rand($height));
	#print "find $x $y ", $maze{"$x $y"}, "\n";
	if ($maze{"$x $y"} !~ /----|udlr/) {
	    return;
	}
    }
}

sub wander {
    @ways = ();
    for $way ('u', 'd', 'l', 'r') {
	if (&peek($x, $y, $way) eq '*') {
	    push(@ways, $way);
	}
    }
    return 0 if ($#ways < 0);
    $way = $ways[int(rand($#ways+1))];
    &set($x, $y, $way);
    $x += $setdx{$way};
    $y += $setdy{$way};
    $left --;
}

&draw_maze();

$max = $width;
$max = $height if $max < $height;

$max *= $roomsize / ($roomsize - 3 * $pillarsize);
$max = int($max + 1);

$ppr = $roomsize/$max;
$ppr = 8 if $ppr < 8;

if ($width*$roomsize > 4000) {
    printf("too wide: $width x $roomsize = %d\n", $width*$roomsize);
    &die();
}
if ($height*$roomsize > 4000) {
    printf("too high: $height x $roomsize = %d\n", $height*$roomsize);
    &die();
}

for ($x=0; $x<$max*$ppr; $x++) {
    for ($y=0; $y<$max*$ppr; $y++) {
	$ppm[$x][$y] = '0';
    }
}
sub pset {
    my($x,$y,$t,$c) = @_;
    my ($a,$b);
    $c = '1' unless $c;
    for ($a=-$t; $a<=$t; $a++) {
	for ($b=-$t; $b<=$t; $b++) {
	    $ppm[$x+$a][$y+$b] = $c;
	}
    }
}

sub rset {
    my($x,$y,$c) = @_;
    pset ($x*$ppr+$xo+$ppr/2, $y*$ppr+$yo+$ppr/2, 2, $c);
}

$xo = int((($max * $ppr) - ($width * $ppr))/2);
$yo = int((($max * $ppr) - ($height * $ppr))/2);
for ($x=0; $x<=$width; $x++) {
    for ($y=0; $y<=$height; $y++) {
	$px = $x * $ppr + $xo;
	$py = $y * $ppr + $yo;
	&pset($px,$py,0);
	$ppm[$px][$py] = '1';
	if ($maze{"$x $y"} !~ /u/ && $x < $width) {
	    for ($l=0; $l<$ppr; $l++) {
		&pset($px+$l,$py,0);
	    }
	}
	if ($maze{"$x $y"} !~ /l/ && $y < $height) {
	    for ($l=0; $l<$ppr; $l++) {
		&pset($px,$py+$l,0);
	    }
	}
    }
}

sub box {
    my ($texture, $minx, $maxx, $miny, $maxy, $h,$s) = @_;
    &add_brush();
    &add_plane($texture, $minx-$s, $miny-$s, 0, $maxx+$s, $miny-$s, 0, $maxx+$s, $maxy+$s, 0);
    &add_plane($texture, $minx, $miny, $h, $minx, $maxy, $h, $maxx, $maxy, $h);
    &add_plane($texture, $minx-$s, $miny-$s, 0, $minx, $miny, $h, $maxx, $miny, $h);
    &add_plane($texture, $maxx+$s, $miny-$s, 0, $maxx, $miny, $h, $maxx, $maxy, $h);
    &add_plane($texture, $maxx+$s, $maxy+$s, 0, $maxx, $maxy, $h, $minx, $maxy, $h);
    &add_plane($texture, $minx-$s, $maxy+$s, 0, $minx, $maxy, $h, $minx, $miny, $h);
}

$ws = &add_entity("worldspawn");

sub pillaris {
    my ($x, $y, $h) = @_;
    $pillarheight{"$x $y"} = $h+8 if $pillarheight{"$x $y"} < $h+8;
}

for ($x=0; $x<=$width; $x++) {
    for ($y=0; $y<=$height; $y++) {

	if ($maze{"$x $y"} !~ /u/ && $x < $width) {
	    $h = int($roomheight + rand($roomrand));
	    if ($y == 0 || $y == $height) {
		$h = $roofheight;
	    }
	    &box($walltex,
		 $x*$roomsize, ($x+1)*$roomsize,
		 $y*$roomsize-$wallthick, $y*$roomsize+$wallthick,
		 $h, 0);
	    &pillaris($x, $y, $h);
	    &pillaris($x+1, $y, $h);
	}
	if ($maze{"$x $y"} !~ /l/ && $y < $height) {
	    $h = int($roomheight + rand($roomrand));
	    if ($x == 0 || $x == $width) {
		$h = $roofheight;
	    }
	    &box($walltex,
		 $x*$roomsize-$wallthick, $x*$roomsize+$wallthick,
		 $y*$roomsize, ($y+1)*$roomsize,
		 $h, 0);
	    &pillaris($x, $y, $h);
	    &pillaris($x, $y+1, $h);
	}
    }
}
for ($x=0; $x<=$width; $x++) {
    for ($y=0; $y<=$height; $y++) {
	&box($pillartex,
	     $x*$roomsize-$pillarsize, $x*$roomsize+$pillarsize,
	     $y*$roomsize-$pillarsize, $y*$roomsize+$pillarsize,
	     $pillarheight{"$x $y"}, $splay);
    }
}

for ($x=0; $x<$width; $x++) {
    for ($y=0; $y<$height; $y++) {
	$tex = $floortex;
	if (($x == 0 || $x == $width-1) && ($y == 0 || $y == $height-1)) {
	    $tex = $mazetex;
	}
	&make_surface($tex,
		      $x*$roomsize, $y*$roomsize, 0,
		      $x*$roomsize, ($y+1)*$roomsize, 0,
		      ($x+1)*$roomsize, ($y+1)*$roomsize, 0,
		      ($x+1)*$roomsize, $y*$roomsize, 0);
    }
}

&make_surface($rooftex,
	      -$roomsize, -$roomsize, $skyheight,
	      ($width+1)*$roomsize, -$roomsize, $skyheight,
	      ($width+1)*$roomsize, ($height+1)*$roomsize, $skyheight,
	      -$roomsize, ($height+1)*$roomsize, $skyheight);

&make_surface($rooftex,
	      -$roomsize, -$roomsize, -2,
	      -$roomsize, -$roomsize, $skyheight,
	      -$roomsize, ($height+1)*$roomsize, $skyheight,
	      -$roomsize, ($height+1)*$roomsize, -2);

&make_surface($rooftex,
	      -$roomsize, ($height+1)*$roomsize, -2,
	      -$roomsize, ($height+1)*$roomsize, $skyheight,
	      ($width+1)*$roomsize, ($height+1)*$roomsize, $skyheight,
	      ($width+1)*$roomsize, ($height+1)*$roomsize, -2);

&make_surface($rooftex,
	      ($width+1)*$roomsize, ($height+1)*$roomsize, -2,
	      ($width+1)*$roomsize, ($height+1)*$roomsize, $skyheight,
	      ($width+1)*$roomsize, -$roomsize, $skyheight,
	      ($width+1)*$roomsize, -$roomsize, -2);

&make_surface($rooftex,
	      ($width+1)*$roomsize, -$roomsize, -2,
	      ($width+1)*$roomsize, -$roomsize, $skyheight,
	      -$roomsize, -$roomsize, $skyheight,
	      -$roomsize, -$roomsize, -2);

&make_surface('liquids/lavahell_750',
	      -$roomsize, -$roomsize, -2,
	      -$roomsize, ($height+1)*$roomsize, -2,
	      ($width+1)*$roomsize, ($height+1)*$roomsize, -2,
	      ($width+1)*$roomsize, -$roomsize, -2);

&add_entity("trigger_hurt", "dmg", 1);
&make_surface('common/nodraw',
	      -$roomsize, -$roomsize, -1,
	      -$roomsize, ($height+1)*$roomsize, -1,
	      ($width+1)*$roomsize, ($height+1)*$roomsize, -1,
	      ($width+1)*$roomsize, -$roomsize, -1);

$rs = $roomsize;

sub inroom {
    my($rx,$ry,$top) = @_;
    $room_filled{"$rx $ry"} = 1;
    if ($top == 1) {
	return ("origin", sprintf("below %d %d $roomheight", $rx*$rs+$rs/2, $ry*$rs+$rs/2));
    } elsif ($top == 0) {
	return ("origin", sprintf("above %d %d 0", $rx*$rs+$rs/2, $ry*$rs+$rs/2));
    } else {
	return ("origin", sprintf("%d %d %d", $rx*$rs+$rs/2, $ry*$rs+$rs/2, $top));
    }
}

for ($x=0; $x<$width; $x++) {
    for ($y=0; $y<$height; $y++) {
	&add_entity("item_botroam", &inroom($x, $y, 12));
	&add_entity("light", &inroom($x, $y, 1), "light", 100);
    }
}

%room_filled = ();

sub ipd_set {
    my ($x, $y, $angle) = @_;
    my ($rx, $ry, $dx, $dy);
    $room_filled{"$x $y"} = 1;
    $rx = $x * $rs + $rs/2;
    $ry = $y * $rs + $rs/2;
    for ($dx=-$rs/4; $dx<$rs/2; $dx+=$rs/2) {
	for ($dy=-$rs/4; $dy<$rs/2; $dy+=$rs/2) {
	    my ($xx,$yy);
	    $xx = $rx+$dx;
	    $yy=$ry+$dy;
	    &add_entity("info_player_deathmatch", "origin", "above $xx $yy 0", "angle", $angle);
	}
    }
    &rset($x, $y, 'i');
}

&ipd_set(0, 0, 45);
&ipd_set($width-1, 0, 135);
&ipd_set(0, $height-1, 315);
&ipd_set($width-1, $height-1, 225);

&add_entity("weapon_rocketlauncher", &inroom($mx, 0));
&rset($mx, 0, 'w');
&add_entity("weapon_grenadelauncher", &inroom($mx, $height-1));
&rset($mx, $height-1, 'w');
&add_entity("weapon_plasmagun", &inroom(0, $my));
&rset(0, $my, 'w');
&add_entity("weapon_railgun", &inroom($width-1, $my));
&rset($width-1, $my, 'w');

&add_entity("item_health", &inroom($mx-1, $my-1));
&rset($mx-1, $my-1, 'h');
&add_entity("item_health", &inroom($mx+1, $my-1));
&rset($mx+1, $my-1, 'h');
&add_entity("item_health", &inroom($mx-1, $my+1));
&rset($mx-1, $my+1, 'h');
&add_entity("item_health", &inroom($mx+1, $my+1));
&rset($mx+1, $my+1, 'h');

&add_entity("item_quad", &inroom($mx, $my));
&rset($mx, $my, 'q');

for ($x=0; $x<$width; $x++) {
    for ($y=0; $y<$height; $y++) {
	if (! $room_filled{"$x $y"} && $maze{"$x $y"} =~ /-.*-.*-/ ) {
	    if (rand(2) > 1) {
		&add_entity("item_health_small", &inroom($x, $y));
	    } else {
		&add_entity("item_armor_shard", &inroom($x, $y));
	    }
	}
    }
}

open(PPM, "| cjpeg -q 90 > ../textures/maze/$tga.jpg");

print PPM "P3\n";
printf PPM "%s %s 255\n", $max * $ppr, $max * $ppr;

for ($y=$max*$ppr-1; $y>=0; $y--) {
    for ($x=0; $x<$max*$ppr; $x++) {
	if ($ppm[$x][$y] eq '1') {
	    printf PPM "255 200 150 ";
	} elsif ($ppm[$x][$y] eq 'q') {
	    printf PPM "0 0 255 ";
	} elsif ($ppm[$x][$y] eq 'h') {
	    printf PPM "255 255 0 ";
	} elsif ($ppm[$x][$y] eq 'w') {
	    printf PPM "0 255 0 ";
	} elsif ($ppm[$x][$y] eq 'i') {
	    printf PPM "255 0 0 ";
	} else {
	    printf PPM "100 70 50 ";
	}
	if ($col++ > 30) {
	    print PPM "\n";
	    $col = 0;
	}
    }
}

close(PPM);

system ("djpeg -ppm < ../textures/maze/$tga.jpg | ppmtotga -rgb -norle > ../levelshots/maze.tga");

&save_map($ARGV[0]);
