summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndinus <andinus@nand.sh>2021-01-22 13:24:29 +0530
committerAndinus <andinus@nand.sh>2021-01-22 13:24:29 +0530
commit337356b3adb1fe10874fb1ea42a5da24963d9881 (patch)
treebdd0b1d47b26e01e7321ac6d4ca9781b4255686b
downloadtucana-337356b3adb1fe10874fb1ea42a5da24963d9881.tar.gz
Initial commit
-rw-r--r--.gitignore1
-rw-r--r--LICENSE13
-rw-r--r--README.org13
-rwxr-xr-xbin/tucana3
-rw-r--r--lib/Tucana/CLI.rakumod66
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;
+}