diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | LICENSE | 13 | ||||
-rw-r--r-- | README.org | 13 | ||||
-rwxr-xr-x | bin/tucana | 3 | ||||
-rw-r--r-- | lib/Tucana/CLI.rakumod | 66 |
5 files changed, 96 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4a5e4c7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +lib/.precomp diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e51df07 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2021, Andinus <andinus@nand.sh> + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.org b/README.org new file mode 100644 index 0000000..2a9194b --- /dev/null +++ b/README.org @@ -0,0 +1,13 @@ +#+SETUPFILE: ~/.emacs.d/org-templates/projects.org +#+EXPORT_FILE_NAME: index +#+OPTIONS: toc:2 +#+TITLE: Tucana + +Tucana is a program to generate puzzles like Algot's Wordsearch. + +- Website: https://andinus.nand.sh/tucana +- Source: https://git.tilde.institute/andinus/tucana +- GitHub: https://github.com/andinus/tucana + +It's a work in progress. Currently it uses a very naive approach of just +walking around the grid & chosing a random neighbor. diff --git a/bin/tucana b/bin/tucana new file mode 100755 index 0000000..c515c81 --- /dev/null +++ b/bin/tucana @@ -0,0 +1,3 @@ +#!/usr/bin/env raku + +use Tucana::CLI; diff --git a/lib/Tucana/CLI.rakumod b/lib/Tucana/CLI.rakumod new file mode 100644 index 0000000..b791d50 --- /dev/null +++ b/lib/Tucana/CLI.rakumod @@ -0,0 +1,66 @@ +unit module Tucana::CLI; + +use Octans::Neighbors; + +# If no arguments are passed then run USAGE & exit. +proto MAIN (|) is export {unless so @*ARGS {say $*USAGE; exit;}; {*}} + +multi sub MAIN (Bool :$version) { + say "Tucana v" ~ $?DISTRIBUTION.meta<version>; +} + +multi sub MAIN ( + Str $word, #= word for the puzzle + Bool :v($verbose), #= increase verbosity +) { + my @puzzle := generate-puzzle($word); + " $_".say for @puzzle; +} + +# generate-puzzle generates a 3x3 puzzle with $word in there. +sub generate-puzzle ( + Str $word, +) { + my @puzzle := [ + [<_ _ _ _>], + [<_ _ _ _>], + [<_ _ _ _>], + [<_ _ _ _>], + ]; + + my Int ($y, $x) = edges(@puzzle).pick; + @puzzle[$y][$x] = $word.comb[0]; + + my @visited; + @visited[$y][$x] = True; + + my Int $count = 1; + while $count < $word.chars { + neighbor: for neighbors(@puzzle, $y, $x).pick(*) -> ($pos-y, $pos-x) { + next neighbor if @visited[$pos-y][$pos-x]; + @visited[$pos-y][$pos-x] = True; + + @puzzle[$pos-y][$pos-x] = $word.comb[$count]; + ($y, $x) = ($pos-y, $pos-x); + last neighbor; + } + + $count++; + } + + return @puzzle; +} + +# edges takes a 2d grid & returns the list of edges, i.e. squares with +# < 4 neighbors. +sub edges ( + @puzzle --> List +) { + my List @edges; + for 0 .. @puzzle.end -> $y { + for 0 .. @puzzle[$y].end -> $x { + push @edges, ($y, $x) if neighbors(@puzzle, $y, $x).elems < 4; + } + } + return @edges; +} |