chiark / gitweb /
overflow-tube: wip cut2
[quacks.git] / pumpkin-books.ps.pl
index cdcfc33ca3e406ab9e3eec99dbbd32169a4cb0b0..b0f07fac10bd7e343785a88c56908aee3c444fca 100755 (executable)
@@ -1,45 +1,12 @@
 #!/usr/bin/perl -w
+# Books of Pumpkins, etc.  Extensions to Quacks of Quedlinburg
+#  SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0
+# Copyright 2020-2021 Ian Jackson
 
 use strict;
 
-our $black = '0 0 0 1 setcmykcolor';
-
-my $pumpkin = ["0 .50 0 1.00 0", "0 0 0 1"];
-my $green = ["1 0 1 0", "0 0 0 0"];
-my $red = ["0 1 1 0", "0 0 0 1"];
-my $blue = ["0.6 0.6 0 0", "0 0 0 0"];
-my $yellow = ["0 0 1 0", "0 0 0 1"];
-my $moth = ["0 0 0 1", "0 0 0 0"];
-my $purple = ["0 1 0 0", "0 0 0 1"];
-
-sub chip ($$) {
-  my ($cary, $pips) = @_; # put in a gsave translate
-  my $o = <<END;
-  newpath
-  0 0 chip 0.5 mul 0 360 arc
-  gsave 1 setlinewidth $black stroke grestore
-  $cary->[0] setcmykcolor fill
-  $cary->[1] setcmykcolor
-END
-  my $spot = sub {
-    my ($x,$y) = @_;
-    $o .= <<END;
-    newpath
-    spot 0.5 sqrt mul 1.1 mul dup
-    $x mul exch $y mul
-    spot 0.5 mul
-    0 360 arc fill
-END
-  };
-
-  $spot->( 0, 0) if $pips & 1;
-  $spot->(-1,-1) if $pips & 6;
-  $spot->(+1,+1) if $pips & 6;
-  $spot->(-1,+1) if $pips & 4;
-  $spot->(+1,-1) if $pips & 4;
-
-  $o;
-}
+BEGIN { unshift @INC, '.'; }
+use Quacks;
 
 sub veepsspot ($) {
   my ($chip) = @_;
@@ -69,24 +36,11 @@ gsave
   (Any) dup stringwidth  3 2 roll show
   pop pop
   20 0 translate
-  ${\ chip(['0 0 0 0.5', '0 0 0 0'], $pips) }
+  ${\ chip($anychip, $pips) }
 grestore
 END
 }
 
-sub ruby () { # put in gsave translate
-  <<END;
-  newpath
-    rubysz neg  0 moveto
-    0  rubysz neg lineto
-    rubysz      0 lineto
-    0      rubysz lineto
-    closepath
-    0 1 0.5 0 setcmykcolor gsave fill grestore
-    $black 1 setlinewidth stroke
-END
-}
-
 sub exposition ($) {
   my ($text) = @_;
   my $fontsz = 6;
@@ -109,6 +63,31 @@ END
   $o;
 }
 
+sub num_players ($;$) {
+  my ($n, $plus) = @_;
+  my $o = '';
+
+  $o .= <<END;
+  gsave
+    -0.94 0.50 dc translate
+    0.3 dup scale
+END
+
+  $o .= <<END x $n;
+    pot_image 18 0 translate
+END
+
+  $o .= <<END if defined $plus;
+    -9 -5 moveto
+    /Helvetica-Bold findfont 25 scalefont setfont
+    ($plus) show
+END
+
+  $o .= <<END;
+  grestore
+END
+  return $o;
+}
 
 sub general_book ($$) { # put in a gsave
   my ($this, $costs) = @_;
@@ -116,7 +95,7 @@ sub general_book ($$) { # put in a gsave
 tw  0  translate
 
 3 setlinewidth
-0 0 0 0.2 setcmykcolor
+0.9 setgray
 newpath
 0 0 dc moveto
 0 1 dc lineto stroke
@@ -178,7 +157,7 @@ END
   $o;
 }
   
-sub green_book () {
+sub book_green () {
   my $o = general_book($green, [qw(5 9 15)]);
 
   $o .= <<END;
@@ -212,7 +191,7 @@ END
   $o;
 }
   
-sub red_book () {
+sub book_red () {
   my $o = general_book($red, [qw(4 9 16)]);
 
   $o .= <<END;
@@ -234,11 +213,18 @@ END
   $o;
 }
 
-sub blue_book () {
+sub book_blue () {
   my $o = general_book($blue, [qw(4 10 18)]);
 
   $o .= <<END;
 /Times-Bold findfont 15 scalefont setfont $black
+
+gsave
+  0.50 0.65 dc translate
+  0.65 dup scale
+  gsave -10 0 translate ${\ chip($pumpkin,0) } grestore
+  arrow
+grestore
 END
 
   my $exchip = sub {
@@ -267,13 +253,6 @@ gsave
   21 0 translate
 $content
 grestore
-
-gsave
-  0.50 0.65 dc translate
-  0.65 dup scale
-  gsave -10 0 translate ${\ chip($pumpkin,1) } grestore
-  arrow
-grestore
 END
   };
 
@@ -287,7 +266,8 @@ END
   $o .= $exchline->(1, 2, <<END);
   ${\ $exchip->($moth,1) }  ${\ $exslash->() }
   ${\ $exchip->($purple,1) }  ${\ $exslash->() }
-  ${\ anychip(2) }
+  ${\ $exchip->($lotus,0) }  ${\ $exslash->() }
+  ${\ $exchip->($anychip,2) }
 END
 
   $o .= $exchline->(0, 4, <<END);
@@ -304,7 +284,52 @@ END
   $o;
 }
 
-sub purple_book () {
+sub book_lotus () {
+  my $o = general_book($lotus, [8, 0]);
+
+  $o .= <<END;
+/Times-Bold findfont 15 scalefont setfont $black
+
+gsave
+  0.36 0.38 dc translate
+  0.80 dup scale
+  gsave ${\ chip($lotus,0) } grestore
+
+  9 -4 moveto (=) show
+grestore
+gsave
+  0.20 0.15 dc translate
+  0.80 dup scale
+  gsave ${\ chip($pumpkin,0) } grestore
+  chip 0.5 mul 0 translate
+  gsave ${\ chip($pumpkin,0) } grestore
+
+  10 -4.5 moveto (... +1) show
+
+grestore
+END
+<<END;
+gsave
+  0.16 0.20  dc translate
+  0.60 dup scale
+
+  gsave ${\ veepsspot(chip($pumpkin, 0)) } grestore
+  gsave 0 20 translate ${\ chip($purple, 1) } grestore
+  27 0 translate
+grestore
+END
+
+
+  $o .= exposition(<<END);
+The value of this chip is
+1 higher than the number of pumpkins
+previously placed in the pot (but max.4)
+END
+
+  $o;
+}
+
+sub book_purple () {
   my $o = general_book($purple, [10, 1]);
 
   my $input = <<END;
@@ -315,15 +340,32 @@ END
   $o .= <<END;
 /Times-Bold findfont 15 scalefont setfont $black
 gsave
-  0.16 0.15  dc translate
+  0.16 0.20  dc translate
   0.60 dup scale
 
 $input
-  10 0 translate
-  0 -10 moveto (...) show
-  20 0 translate
+  8 -12 moveto (...) show
+  27 0 translate
 $input
 grestore
+
+gsave
+/Times-Roman findfont
+  32 scalefont setfont
+  0.48 0.14 dc moveto (}) show
+grestore
+
+gsave
+   0.83 0.25 dc translate
+   0.85 dup scale
+   ${\ chip($anychip, 0) }
+grestore
+
+gsave
+  0.72 0.22 dc translate
+  0.50 dup scale
+   $black 0 0 moveto (?+?) show
+grestore
 END
 
   $o .= exposition(<<END);
@@ -336,15 +378,213 @@ END
   $o;
 }
 
+sub book_yellow () {
+  my $o = general_book($yellow, [qw(5 11 18)]);
+
+  $o .= <<END;
+gsave
+  0.52 0.32 dc translate
+  0.80 dup scale
+  -26 0 translate
+  gsave 26 0 translate ${\ chip($yellow,0) } grestore
+  gsave 46 0 translate ${\ chip($pumpkin,0) } grestore
+  34 14 translate
+  -22.5 rotate
+  1 -1 scale
+  ${\ arrow_any("
+    gsave
+     arrowlen 0 translate
+  -85 rotate
+    -40 0
+      40
+      300 0 arc
+    stroke
+    grestore
+  ") }
+grestore
+END
+
+  my $exchip = sub {
+    my ($that, $pips) = @_;
+    <<END;
+  gsave ${\ chip($that, $pips) } grestore
+END
+  };
+  my $exslash = sub {
+    <<END;
+    8 -5 moveto (/) show
+    20 0 translate
+END
+  };
+  
+  $o .= exposition(<<END);
+Move up to 1/2/4 pumpkins
+already in your pot, to after the yellow.
+(always immediately after, only one space,
+regardless of other rules)
+END
+
+  $o;
+}
+
+sub black_common ($) {
+  my ($second) = @_;
+  my $font = <<END;
+/Helvetica-Bold findfont 5.5 scalefont setfont
+END
+  <<END;
+    gsave
+      .45 .27 dc translate
+      droplet_image
+      3.5 -1 translate .7 dup scale
+      arrow
+    grestore
+    gsave
+      .40 .08 dc translate
+      $font
+      ($second) 
+        dup stringwidth .5 mul exch .5 mul exch translate
+        dup stringwidth -1 mul exch -1 mul exch moveto show
+      .7 dup scale 7 3 translate
+      ${\ ruby() }
+    grestore
+    gsave
+      .15 .37 dc translate
+
+      8.2 3.5 moveto
+      $font
+      (closest) show
+
+      .7 dup scale
+      gsave
+        17 0 translate
+        180 rotate
+        arrow
+      grestore
+      gsave
+        35 0 translate
+        arrow
+        newpath 0 0 moveto -18 0 rlineto stroke
+      grestore
+
+      ${\ chip($pumpkin,0) }
+
+      51 0 translate
+      ${\ chip($moth,   1) }
+    grestore
+END
+}
+
+sub book_black_pair () {
+  my $o = general_book($moth, [10, 1]);
+
+  $o .= num_players(2);
+  $o .= black_common('equal:');
+
+  $o .= exposition(<<END);
+The player with the shortest distance
+between a black chip and a pumpkin
+gets to move their droplet.
+
+If tied, both players get a ruby.
+END
+
+  $o;
+}
+
+sub book_black_more () {
+  my $o = general_book($moth, [10, 1]);
+
+  $o .= num_players(3,'+');
+  $o .= black_common('2nd:');
+
+  $o .= exposition(<<END);
+
+The player(s) with the shortest distance
+between a black chip and a pumpkin
+get to move their droplet.
+If only one player won a droplet, the
+player(s) with the next-shortest distance
+get a ruby.
+END
+
+  $o;
+}
+ps_start('7 30 translate');
+
+sub def_image ($$) {
+  my ($ncomps, $name) = @_;
+
+  my $ext = $ncomps == 1 ? 'pgm' : $ncomps == 3 ? 'ppm' : die;
+  my $oper = $ncomps == 1 ? 'image' :
+             $ncomps == 3 ? 'false 3 colorimage' : die;
+  my $magic = $ncomps == 1 ? 'P2' : $ncomps == 3 ? 'P3' : die;
+
+  open B, "$name.$ext" or die $!;
+  <B> eq "$magic\n" or die "$name.$ext expected $magic";
+  local $/ = undef;
+  my @d = split ' ', <B>;
+  close B;
+
+  my $w = shift @d;
+  my $h = shift @d;
+  my $maxval = shift @d;
+  die unless $maxval eq 255;
+
+  my $sz = $w/17.0;
+  my $hsz = $sz/2;
+
+  $ps_framing .= <<END . '{<';
+/${name}_image {
+  $w $h 8 
+  [ -$sz 0 0  -$sz  $w 2 div  $h 2 div  ]
+END
+  for (my $i=0; $i< $w*$h*$ncomps; $i++) {
+    $ps_framing .= sprintf "%02x", shift @d;
+  }
+  $ps_framing .= <<END;
+>} $oper
+} def
+END
+}
+
 sub tile {
+  my @tiles;
+  my $index = 1;
+
+  foreach my $spec (@_) {
+    my @datas;
+    foreach my $stem (split m{/}, $spec) {
+      my $func = $stem;
+      $func =~ y/-/_/;
+      $func = ${*::}{"book_$func"} // die "$func ?";
+      my $data = $func->();
+      $data .= <<END;
+    /Courier-Bold findfont 6 scalefont setfont
+    -0.98 0.94 dc moveto
+    ($index) show
+END
+      open F, ">book-$stem.ps" or die $!;
+      print F $ps_framing, $data, "\nshowpage\n" or die $!;
+      close F or die $!;
+      push @datas, $data;
+    }
+    foreach my $dd (@datas) {
+      push @tiles, $dd;
+    }
+    $index++;
+  }
+
   my $pos = 0;
   my $o = '';
   my $showpage = sub {
     $o .= <<END;
 showpage
+$page_pre
 END
   };
-  while (my $d = shift @_) {
+
+  while (my $d = pop @tiles) {
     if ($pos >= 5) {
       $pos -= 5;
       $showpage->();
@@ -374,56 +614,13 @@ END
   $o;
 }
 
-print <<END or die $!;
-%!
-
-72 25.4 div dup scale
-%210 0 translate
-%90 rotate
-7 10 translate
-
-/tw 57.5 def
-/th 73 def
-/bdiag 5 def
-/thirdlineh 0.45 def
-/costcirch 0.3 def
-/chip 15 def
-/spot 3.5 def
-/arrowlen 6 def
-/arrowhead 3 def
-
-/costtexth 0.215 def
-/costtextsz 12 def
-/costtextdx -0.03 def
-/costfont /Heletica-BoldOblique findfont costtextsz scalefont def
-
-/rubysz 4 def
-
-% diagonal conversion
-/dc {                    % xprop yprop
-    dup th mul           % xprop yprop y
-    3 1 roll             % y xprop yprop
-    bdiag mul neg        % y xprop x-margin-at-this-height
-    tw add               % y xprop x-width-at-this-height
-    exch mul             % y x-width-at-this-height xprop
-    exch                 % x y
-} def
+def_image(1, "bag");
+def_image(1, "pot");
+def_image(3, "droplet");
 
-/arrow {
-  $black 1 setlinewidth
-    newpath
-       0 0 moveto  arrowlen 0 rlineto
-       arrowhead dup neg exch  rmoveto
-       arrowhead dup neg       rlineto
-       arrowhead neg dup       rlineto
-       stroke
-} def
+print $ps_framing or die $!;
 
-END
+print "gsave\n" or die $!;
+
+print tile(@ARGV) or die $! if 1;
 
-print tile(
-          green_book(),
-          red_book(),
-          purple_book(),
-          blue_book(),
-         ) or die $! if 1;