about summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Fornax/CLI.rakumod114
1 files changed, 62 insertions, 52 deletions
diff --git a/lib/Fornax/CLI.rakumod b/lib/Fornax/CLI.rakumod
index 1cf518d..43a5fe3 100644
--- a/lib/Fornax/CLI.rakumod
+++ b/lib/Fornax/CLI.rakumod
@@ -16,6 +16,7 @@ proto MAIN(|) is export { unless so @*ARGS { put $*USAGE; exit }; {*} }
 multi sub MAIN(
     File $input, #= fornax format file (solved)
     IO() :$out = '/tmp', #= output directory (default: /tmp)
+    Int() :$batch = 4, #= batch size (generate frames in parallel)
     Rat() :$frame-rate = 1, #= frame rate (default: 1)
     Bool :$skip-video, #= skip video solution
     Bool :$verbose = True, #= verbosity
@@ -75,64 +76,73 @@ multi sub MAIN(
 
     enum IterStatus <Walking Blocked Completed>;
 
+    my Promise @p;
     for @lines.skip.kv -> $idx, $iter is rw {
-        my IterStatus $status;
-        given $iter.substr(0, 1) {
-            when '|' { $status = Completed }
-            when '!' { $status = Blocked }
-            default { $status = Walking }
-        };
-
-        # Remove marker.
-        $iter .= substr(1) if $status == Completed|Blocked;
-
-        put "[fornax] $idx $iter $status" if $verbose;
-
-        my @grid = $iter.comb.rotor: %meta<cols>;
-        warn "Invalid grid: $idx $iter $status" unless @grid.elems == %meta<rows>;
-
-        given Cairo::Image.create(
-            Cairo::FORMAT_ARGB32, %CANVAS<width>, %CANVAS<height>
-        ) {
-            given Cairo::Context.new($_) {
-                # Paint the entire canvas white.
-                .rgb: |%C<white>;
-                .rectangle(0, 0, %CANVAS<width>, %CANVAS<height>);
-                .fill;
-                .stroke;
-
-                for ^%meta<rows> -> $r {
-                    for ^%meta<cols> -> $c {
-                        my Int @target = %excess<width> div 2 + $c * $side,
-                                         %excess<height> div 2 + $r * $side,
-                                         $side, $side;
-
-                        .rectangle: |@target;
-                        given @grid[$r][$c] -> $cell {
-                            when $cell eq $CUR {
-                                .rgba: |%C<pointer>, 0.56;
-                                .rgba: |%C<pointer-green>, 0.72 if $status == Completed;
-                                .rgba: |%C<pointer-red>, 0.72 if $status == Blocked;
-                            }
-                            when $cell eq $VIS {
-                                .rgba: |%C<blue>, 0.64;
-                                .rgba: |%C<green>, 0.96 if $status == Completed;
-                                .rgba: |%C<red>, 0.96 if $status == Blocked;
+        # Wait until all scheduled jobs are finished, then empty the
+        # array and continue.
+        if @p.elems == $batch {
+            while @p.grep(*.status).elems !== $batch {};
+            @p = [];
+        }
+
+        push @p, start {
+            my IterStatus $status;
+            given $iter.substr(0, 1) {
+                when '|' { $status = Completed }
+                when '!' { $status = Blocked }
+                default { $status = Walking }
+            };
+
+            # Remove marker.
+            $iter .= substr(1) if $status == Completed|Blocked;
+
+            put "[fornax] $idx $iter $status" if $verbose;
+
+            my @grid = $iter.comb.rotor: %meta<cols>;
+            warn "Invalid grid: $idx $iter $status" unless @grid.elems == %meta<rows>;
+
+            given Cairo::Image.create(
+                Cairo::FORMAT_ARGB32, %CANVAS<width>, %CANVAS<height>
+            ) {
+                given Cairo::Context.new($_) {
+                    # Paint the entire canvas white.
+                    .rgb: |%C<white>;
+                    .rectangle(0, 0, %CANVAS<width>, %CANVAS<height>);
+                    .fill;
+
+                    for ^%meta<rows> -> $r {
+                        for ^%meta<cols> -> $c {
+                            my Int @target = %excess<width> div 2 + $c * $side,
+                                             %excess<height> div 2 + $r * $side,
+                                             $side, $side;
+
+                            .rectangle: |@target;
+
+                            given @grid[$r][$c] -> $cell {
+                                when $cell eq $CUR {
+                                    .rgba: |%C<pointer>, 0.56;
+                                    .rgba: |%C<pointer-green>, 0.72 if $status == Completed;
+                                    .rgba: |%C<pointer-red>, 0.72 if $status == Blocked;
+                                }
+                                when $cell eq $VIS {
+                                    .rgba: |%C<blue>, 0.72;
+                                    .rgba: |%C<green>, 0.96 if $status == Completed;
+                                    .rgba: |%C<red>, 0.96 if $status == Blocked;
+                                }
+                                when $cell eq $BLOK { .rgba: |%C<black>, 0.56 }
+                                when $cell eq $DEST { .rgb: |%C<green> }
+                                default { .rgba: |%C<black>, 0.08 }
                             }
-                            when $cell eq $BLOK { .rgba: |%C<black>, 0.48 }
-                            when $cell eq $DEST { .rgb: |%C<green> }
-                            default { .rgba: |%C<black>, 0.08 }
-                        }
-                        .fill :preserve;
+                            .fill :preserve;
 
-                        .rgb: |%C<black>;
-                        .rectangle: |@target;
-                        .stroke;
+                            .rgb: |%C<black>;
+                            .stroke;
+                        }
                     }
                 }
+                .write_png("%s/%08d.png".sprintf: $output, $idx);
+                .finish;
             }
-            .write_png("%s/%08d.png".sprintf: $output, $idx);
-            .finish;
         }
     }