RPG Tilemap

I had a useful JavaScript utility hidden away in the source for my Stone Halls & Serpent Men game, so I extracted it into its own thing:

Especially with people doing the challenge, it may be helpful for quickly drawing a dungeon, roguelike style.

I'm pondering doing a full wilderness + dungeon adventure again sometime soon, and I'll likely use Tilemap for it, but I sure won't be doing a room a day or anything like that!

An Atari New Year!

I spent a little time this evening making some fireworks for tomorrow night!

Download, unzip, launch in your favorite Atari 800 emulator, like Atari800MacX

Pick Y from the menu, ESC to end, reboot to get back to the menu. See you in a year!

(I didn't get around to putting an emulator page on my site; I will before my next actual game)

Sing

Rather than my longer music playlists, I often just sing one song to fediverse, like this. It's a slightly manual process, but I have part of it automated:

nowplaying.applescript

#!/usr/bin/osascript
tell application "Music"
    set t to current track
    set msg to (t's artist & " " & t's name)
    msg
end tell

urlencode

#!/usr/bin/env python3

import sys
import urllib.parse

for line in sys.stdin:
    line = line.rstrip()
    print(urllib.parse.quote(line)) # unquote for the urldecode script

sing

#!/bin/zsh
q=`nowplaying.applescript|urlencode`
open -a Chromium "https://duckduckgo.com/?q=!yt+$q"
open -a Chromium "https://duckduckgo.com/?q=!genius+$q"

Then I just type sing, it pops up Chromium (my garbage media browser), I pick the best YT video and paste that, grab some lyrics and paste them, I have o/ bound as ♫ in Text replacements, and add a tag.

I suspect I could automate it a bit more, pick the first result on Genius and YT, but I trust neither to be right. Apple Music would be easier, but not everyone has it. I could grab cover art and paste that and a template into my appdot.net toot box. Anyway, it's the post-Human touch that shows I care. It's amusing that I have three scripting languages to get one thing done (urlencode/urldecode scripts date back to the '90s).

Mac Protip: Open URL in Browser

Not all browsers have an "Open in" service. I tend to use Chromium for media so it's a different crashy app than my main Safari. I've been manually copying URLs, pasting into it.

Open Automator, create a new Quick Action, pick Run Shell Script, paste in:

read -r url
open -a Chromium "$url"

Save it as "Open URL in Chromium". Quit Automator.

You can now right-click on any URL, Services menu, and send it there.

Old Man in the Woods Way of Argument Parsing

So, my premise is that only developers use command lines anymore. And after years of corporate enslavement, it's nice to run off to the woods, make a log cabin and all your tools yourself.

Therefore the best way to parse arguments in Scheme is:

(define debug #f)
(define outfile #f)
(define infiles '())

(define (main argv)
  (set! debug (if (member "--debug" argv) #t #f))  ;; boolean
  (set! outfile (if (member "--out" argv) (cadr (member "--out" argv)) #f))  ;; key-value
  (set! infiles (if (member "--" argv) (cdr (member "--" argv)) #f))  ;; all after --
  (unless outfile (error 'main "No outfile given")) ;; maybe show a whole usage & exit
)

This has some disadvantages. It's only discoverable by reading docs or even code, and you have to write the docs yourself. If you want short args, you have to duplicate lines and maybe set the arg twice.

But it's trivial to set up, you can't really get it wrong, and the amount of effort is appropriate to a developer interface.

(You might complain I'm using globals, you can just change those to let)

For the young over-engineering crowd, there are a variety of arg parsing libraries. And I'm too lazy to demonstrate each of them. But in the set of generates usage, is easy to use, and you'll be able to remember how it works in a year, they all get maybe 1, and need to be 3.

Gone from Suck to Blow

Want to move a URL or other text between your local computers, and they're not all Mac/iOS where universal pasteboard mostly works? There's smart ways, and then there's how I do it:

# note: needs Apache turned on. sudo apachectl start
mac% cd /Library/WebServer/Documents
mac% sudo ln -s $HOME/Sites
mac% cd
mac% cat bin/blow
#!/bin/zsh
pbpaste >$HOME/Sites/suckblow.txt

raspi% sudo apt-get xclip
…
raspi% cat bin/suck
#!/bin/zsh
curl -s "http://mac.local/Sites/suckblow.txt" |xclip -i -selection clipboard
xclip -o -selection clipboard

And in the reverse set, pbcopy is the Mac equivalent of xclip -i. In practice, I don't run a server on my RasPi but I rarely need to paste the other way, just sometimes scp files.

Now on the Mac, I copy some text, type "blow" in iTerm2. On the RasPi, I grab terminal and type "suck". It can take a few seconds, and then the text is in clipboard.

Without running Apache (or other web server, but I'm a caveman), you can use scp to grab the file, then cat it into xclip -i.

Happy blowing & sucking!

[Update 2022-12-03: Some update on raspi changed the default in xclip from clipboard to primary (X11). So I've added -selection clipboard to them all.]

Internet Archive Favorites

Part of my workflow with Internet Archive is to favorite things I go back to a lot. But the fav page there is nigh-unusable, it lists in order from most recent fave to oldest, including duplicates (Huh?), and even sorting by title doesn't put related things together. So I made a tool, and generated
Internet Archive Favorites which I'll update every so often.

My first attempt was simply scraping an RSS feed, but they only publish the last 50 faves! Bogus! Even if I cached them, I'd still have to check it often and reorganize things. Then I learned they have a developer interface, usable with an ia script or right from Python, which is more useful. It's slow without caching, but after first run it's very fast, mostly 1 API call.

Read the docs at the top of the script, look at the example config file (almost a Markdown outline, but I do some clever/stupid things in it). As usual license is BSD, an ye harm none, do what thou wilt shall be the whole of the law.

Now all I have to do is write a cfg file:

The stuff I've found that I like on [Internet Archive](https://archive.org), loosely sorted.

## Retrocomputing

+ Basic_Computer_Games_Microcomputer_Edition_1978_Creative_Computing
+ More_BASIC_Computer_Games
+ Basic_Computer_Adventures_1986_MS_Press
+ Best_of_Creative_Computing_Vol_1_1978_Creative_Computing_Press
+ creativecomputing
…

% archive-fav-extract.py -q mdhughes

And it makes a nice html file, tells me about any errors, and I paste the output file into a wordpress page.

A Computer is Like a Violin

LATITUDE OF EXPRESSION AND SPECIFICITY OF IDEAS

Finally we come to the question of what to do when we want to write a program but our idea of what is to be done, or how to do it, is incompletely specified. The non sequitur that put everyone off about this problem is very simple:

Major Premise: If I write a program it will do something particular, for every program does something definite.
Minor Premise: My idea is vague. I don't have any particular result in mind.
Conclusion: Ergo, the program won't do what I want.

So, everyone thinks, programs aren't expressive of vague ideas.

There are really two fallacies. First, it isn't enough to say that one doesn't have a particular result in mind. Instead, one has an (ill-defined) range of acceptable performances, and would be delighted if the machine's performance lies in the range. The wider the range, then, the wider is one's latitude in specifying the program. This isn't necessarily nullified, even when one writes down particular words or instructions, for one is still free to regard that program as an instance. In this sense, one could consider a particular written-down story as an instance of the concept that still may remain indefinite in the author's mind.
This may sound like an evasion, and in part it is. The second fallacy turns around the assertion that I have to write down a particular process. In each domain of uncertainty 1 am at liberty to specify (instead of particular procedures) procedure-generators, selection rules, courts of advice concerning choices, etc. So the behavior can have wide ranges-it need never twice follow the same lines, it can be made to cover roughly the same latitude of tolerance that lies in the author's mind.

At this point there might be a final objection: does it lie exactly over this range? Remember, I'm not saying that programming is an easy way to express poorly defined ideas! To take advantage of the unsurpassed flexibility of this medium requires tremendous skill-technical, intellectual, and esthetic. To constrain the behavior of a program precisely to a range may be very hard, just as a writer will need some skill to express just a certain degree of ambiguity. A computer is like a violin. You can imagine a novice trying first a phonograph and then a violin. The latter, he says, sounds terrible. That is the argument we have heard from our humanists and most of our computer scientists. Computer programs are good, they say, for particular purposes, but they aren't flexible. Neither is a violin, or a typewriter, until you learn how to use it.

Printing Code Like It's 1989

Which made me laugh, the 2016-2021 dialogue and still not implemented feature in that bug report is everything you love about Microsoft-controlled "open source but not really".

I've only ever printed code from BBEdit in the last couple decades, let's see how other editors fare:

  • BBEdit: Perfect. Print command in menu (it's a native Mac app!), prints headers, page & line numbers, nice margins. Looks perfect, like an old-timey print job. I should probably have switched from dark to light theme, but it'd be fine. ★★★★★
  • Geany: Print command, several settings in Preferences, prints headers, page & line numbers (in settings, choose either headers or page numbers at bottom, or it'll be duplicated). Hideous non-native GTK app and dialogs, but does the job perfectly well. ★★★★½
  • MacVim: Print command, produces a postscript file which immediately opens in Preview, spins a while, converts to PDF. Default has no line numbers, add set popt=header:2,number:y to your .vimrc. ★★★½☆
  • Atom: No print command in the menu, but there's multiple packages 5-6 years old, they work fine. Only shows line numbers, bad margins, it's literally a web page being printed. ★★★☆☆
  • Sublime Text: Print command, but no settings (in the horrible JSON text editor where you do settings) to make it nice. Literally dumps a web page, no page or line numbers. What's the least you could do and check off the feature? That's how subl does everything. ★★☆☆☆
  • Xcode: Takes forever to start. Prints in grayscale, which is nice, but no headers or line numbers. Fail. ★★☆☆☆
  • Panic Nova: … My demo expired, and cleaning the configs out doesn't let me try again, so who knows. Can't even give them a second try without paying $100. Trashed.

I'd be interested in seeing how others fare, and on non-Mac platforms if they have any consistent print command.

Here's a zip of PDF prints - maze2.py is a silly Python program, but at just 3 pages it's a good test case.

Mac Icons for PDFs

I have a great many folders of PDFs, mostly grabbed from archive.org magazine_rack, ataribooks, etc. The trouble is when I open a folder of these, Finder makes preview icons for a few of them, then gives up and they all show a generic "PDF" icon. What I want is a persistent icon for the first page!

First, you need osxutils:

% sudo port install osxutils
% man seticon

And my icontool.

sips (Scriptable Image Processing System) is a built-in tool on the Mac, incredibly powerful image converter. I'm not gonna do anything fancy with perspective ratios or padding, just use it to get an image.

Now create pdficonset.zsh:

#!/bin/zsh
export CG_PDF_VERBOSE=1
find . -type f -d -iname "*.pdf" |while read -r f; do
    echo $f
    sips -s format png $f -o thumb.png && \
    icontool.zsh thumb.png thumb.icns && \
    seticon -d thumb.icns $f
    rm -f thumb.png thumb.icns
done

Run it in the parent directory, and boom! All nice icons.

[update: added a little better error-safety. CG_PDF_VERBOSE just gives better but still not useful error messages.]

I don't have the problem as bad with CBZ/CBR comics; they'd be trivial to extract the first page from, since they're just ZIP/BZIP files.