๐พ Archived View for laniakea.rodoste.de โบ md โบ journal.md captured on 2024-02-05 at 09:34:41.
โฌ ๏ธ Previous capture (2023-12-28)
-=-=-=-=-=-=-
# record the screen and save as .gif 2023-12-14 A relatively simple program to record a section of the screen and store it as animated gif The commands available on the Linux shell are *much* more powerful than one thinks. Case in point: I had the need to record a small section of my screen and convert that into an animated .gif to share in an online forum. I already had a script that records a video file and was wondering if `ffmpeg` can convert video to gif. Of course it can. The naive approach yields gifs that look okay-ish, with some flickering pixels and huge in size. Introducing an intermediate step to extract a color palette from the video first and then encode a gif using the video and the color palette yields fantastic results. I didn't come up with this myself, the people behind the GIPHY platform were kind enough to share their approach, link below. My script uses the more readable version of their approach.
#!/usr/bin/env zsh
if [ $# -ne 1 ]; then
basename=$(basename $0)
echo "Usage: $basename filename.gif"
echo "records a selection of the screen and saves it as animated gif"
echo
exit 1
fi
gifname=$1
videofile="$gifname.mp4"
palettefile=$(mktemp /tmp/palette-XXXXXXXX.png)
echo "draw selection to record"
geometry="$(slurp)"
stoprecord() {
echo "converting to gif now..."
}
# record video
trap stoprecord INT
wf-recorder -g "$geometry" -f "$videofile"
trap - INT
# create color palette
ffmpeg -y -i "$videofile" -filter_complex "[0:v] palettegen" "$palettefile"
# convert video to gif, using palette
ffmpeg -i "$videofile" -i "$palettefile" \
-filter_complex "[0:v][1:v] paletteuse" "$gifname"
# clean up
rm "$palettefile"
rm "$videofile"
The script works well enough. I'm happy with the resulting files but I'm not happy with how verbose the script is. Oh well, I might improve it later. One thing I should note is that `wf-recorder` is a tool for the Wayland compositor, it probably won't exist/work if you're using X11, but alternatives will. ## Links - [GIPHY explaining how to convert video to gif and vice versa](https://engineering.giphy.com/how-to-make-gifs-with-ffmpeg/) --- # a simple docker shortcut 2023-12-08 I found a simple CLI shortcut for docker. Actually it is an alias for `docker ps -a` which I do use a lot. Typing this isn't tough but what annoys me is that the default output is too broad and that makes finding the right information in a long list of multi-column output tedious. It turns out you can tweak the table formatting. The command becomes unwieldy but this is what shell aliases are for so here we go:
alias dls="docker ps -a --format 'table {{.ID}}\t{{.Names}}\t{{.RunningFor}}\t{{.Status}}\t{{.Networks}}'"
It lists everything I need to know and it fits on a half-screen terminal on a full-HD monitor โ you know, tmux... That's it, just a quick one. --- # ๐ฒ Scoundrel 2023-11-26 A single player dungeon crawler Thanks to Lettuce for their โe-zine of solo gamesโ in which they mention Scoundrel, a game by Zach Gage and Kurt Bieg. It is a solo dungeon crawler of sorts that is played with a single deck of normal playing cards. Me and the wife have adapted the rules slightly and made it a cooperative game. It is quite fun. Each game takes only ten minutes or so and the minimum space requirements โ both in materials to carry and playing space โ make it an ideal travel game. The goal is to slay monsters โ you know, as you do in a dungeon crawler โ and clear all rooms of the dungeon. If you make it out alive you win. There is a point mechanic but to be honest we didn't care. ## setup Jokers are discarded before playing, so are Ace, King, Queen, Jack of hearts and diamonds. The remaining cards are shuffled and form the dungeon pile. You draw four cards and place them face-up. This is a room in the dungeon. You start with 20 points of health. ## cards - clubs โฃ and spades โ suit are monsters. They deal damage equal to their face value. (A=14, K=13, Q=12, J=11) - cards of the hearts โฅ suit are healing potions. They heal their face value in points, up to your maximum of 20. - cards of the diamonds โฆ suit are weapons. They reduce monster damage by their face value, your health pool takes the rest. I guess this makes them more like shields rather than weapons? ## rules and gameplay The player can heal only once per room, additional healing potions can be discarded but won't have an effect. Monsters always die after being fought, and are discarded. Weapons get used up by fighting monsters. Defeated monsters are placed on top of the weapon (with the weapon face value still visible). From then on the weapon can only fight monsters that are weaker (have a lower face value) than the monster before. The player can chose to fight a monster bare handed, taking their full damage, but preserving the weapon. > Example: > A Eight of Diamonds weapon is equiped. I fight a Queen of Spades monster with it. The queen deals 12 damage, my weapon reduces it by 8, I take 4 damage. From now on the weapon can only be used against Jack-level monsters or lower. You progress through the dungeon by clearing rooms. For that you need to use at least three of the four cards of a room in order to progress. Rooms can be skipped but not more than one room in a row. Skipped rooms are placed back at the end of the dungeon pile, so you will eventually face the room. Used cards are discarded. Once one or zero cards of a room remain, you may move to the next room and draw more cards to get back to four. ## two-player variants So far we've come up with three playstyles work for us: In all playstyles, all rules from above remain in place. Both players equip and heal from the same four-card rooms as before and fight the same monsters. ### Truely cooperative gameplay A player may chose to act as many times as they both agree to. So one player may clear multiple rooms completely and equip weapons if the other player is low on health and there is no healing potion available. The flexibility of this game style makes winning relatively easy. It might make sense to remove more high-grade weapons and healing potions or add a second deck of cards (with the same cards removed as outlined above) since that adds more monster damage points than weapons/heals. ### Room-based turns This is like a relay race. Again both players equip/heal/fight the same four-card rooms but one player is responsible to deal with one room. The other player must tackle the next, and so on. Honestly this works really well. Cooperation still exists in the form of consciously leaving a heal or weapon of one room for the next player. ### Single-card turns Each player gets one action before the next player takes over. One action is using a heal, equiping a new weapon, fighting a monster. This does require significant amount of planning and talking. This feels like hard-mode. ## Links - [Lettuce's solo game e-zine <3](gemini://gemini.ctrl-c.club/~lettuce/1x1.gmi) - [Scoundrel on boardgamegeek.com](https://boardgamegeek.com/boardgame/191095/scoundrel) - [The official rules as PDF](http://stfj.net/art/2011/Scoundrel.pdf) --- # signing git commits with GPG 2023-11-09 I had recently written about publishing this blog through git to make it available offline. Signing commits with GPG makes sense for this, to prove authenticity. We live in a world of fake news, fake images, fake videos, fake revenge porn โฆall of them both manually crafted or AI-generated. Proof of authenticity of content is becoming more and more relevant. Proof of authenticity is why I GPG-sign my emails. I usually don't and can't encrypt them, because GPG (or PGP) is so absolutely unknown to the wider public. At least my emails can prove โ to anyone who cares โ that they really originate from me. If you're curious about proving authenticity of your own emails or even encrypting them so no one except the intended audience can read them: I highly recommend the โemail self-defenseโ article by the Free Software Foundation, link below. For the last couple of weeks, I am providing this journal through a git repository for offline browsing. How can I prove that the commits are really me, that the articles committed are really reflecting my opinions and that the site hasn't been hijacked or โalternative versionsโ pop up, giving an impression of reflecting my views and not someone elses? It turns out the same principle applies: Simply sign the git commits with GPG. So I've started to do that earlier this month. At least from now on, authenticity can be verified. It is surprisingly simple, too. You add the GPG key to sign with to your git config and then set a flag to automatically sign each commit. You can do this either globally or on a per-repository level:
# use my key to sign all commits
git config --global user.signingkey 0123456789ABCDEF
# automatically sign all commits
git config --global commit.gpgsign true
New commits will then automatically be signed and you'll be prompted to enter your GPG password every now and then. To verify this works simply call `gpg log --show-signature` after you've completed a signed commit. If you're annoyed by the frequency at which GPG asks you to confirm the password, you can extend the period: Set `default-cache-ttl 86400` in `~/.gnupg/gpg-agent.conf` and restart your gpg-agent to be asked only once every 24 hours. I learned all this from an article by Daniel Doubrovkine from 2021, link below. ## why bother? The question seems relevant. I'm no one important. My ramblings here are on niche topics, and on a niche medium. Who would bother faking my journal and claiming to be me? Probably: Absolutely no one. Then again, trolls simply exist. Also, maybe someone finds my gemini page generation scripts useful and adopts them for their own page through an innocent git fork: My commits are now part of their site. Fact of the matter is, it doesn't matter how likely it is. I have GPG in place and setting the GPG-signing up takes less time than reading this article. It did cost me nothing, while providing reassurance to me and anyone who reads this. ## Links - [email self-defense](https://emailselfdefense.fsf.org/en/) - [my article about providing this site through git](/journal/2023-10-21-read-this-from-git.gmi) - [signing git commits by Daniel Doubrovkine](https://code.dblock.org/2021/04/16/adding-work-email-to-a-gpg-key-and-signing-git-commits.html) - [this gemini site through git](git://rodoste.de/laniakea.git) --- # base conversion script for BASH 2023-11-04 I got tired of starting a calculator or wasting energy by doing an internet query to convert numerical bases so I wrote a script. > Update 2023-11-08: Emilis reached out and suggested to swap the order of the input parameters. This would make aliassing the script much easier. That's a great idea! Thanks Emilis! The script below is updated as per their suggestion. Shell scripts are powerful. Each shell command โ and there are many of them โ does one thing and does it well. It is the combination of these building blocks that multiply their potential. Anyway. At times I need to do a lot of conversions between decimal, hexadecimal and binary numbers. Over time I've gotten somewhat okay of doing _some_ of them in my head or simply remembering them. But regardless I had to use a calculator or use a conversion website, which was tiring. So eventually I got around to writing a short shell script.
#!/usr/bin/env bash
if [ $# -ne 2 ]; then
basename=$(basename $0)
echo "Converts a decimal number into another base"
echo "Usage: $basename target_base decimal_number"
echo
echo "Examples:"
echo " $basename 2 30 converts decimal 30 to binary 11110"
echo " $basename 16 73 converts decimal 73 to hexadecimal 4B"
exit 1
fi
decimalNum=$2
obase=$1
prefix=""
# convert bases
if [[ $obase == "h" || $obase == "hex" ]]; then obase=16
elif [[ $obase == "o" || $obase == "oct" ]]; then obase=8
elif [[ $obase == "b" || $obase == "bin" ]]; then obase=2
fi
# helpful prefixes
if [ $obase -eq 16 ]; then prefix="0x"
fi
targetNum=$(echo "obase=$obase;$decimalNum" | bc)
echo "$decimalNum in base $obase is $prefix$targetNum"
As is usually the case, the actual logic of the script is quite short โ in this case: a single line โ and the majority is taken up by input sanitation, usage hints and convenience conversion. `bc` is actually a complete calculator, capable of so much more. But I'm scripting it by setting it to an output conversion base and then simply passing a decimal number. ## aliases Let's say you need conversion to hexadecimal more than anything else. With the updated parameter order you can make an alias like `alias to-hex='bases.sh 16'` and use it conveniently as `# to-hex 73`. Nice. Thanks again Emilis! ## Links - [bc on gemini](gemini://freeshell.de/tldr/bc.gmi) - [https link to the bc man page](https://manned.org/man/bc.1) --- # why cellular automata fascinate me 2023-11-03 Cellular automata have been fascinating me for a while now. Time to talk about it. Cellular automata come in all sorts of varieties, in one to any number of dimensions. But to get to the bottom of they do fascinate me it is enough to look at simple one-dimensional cellular automata. ## the basics A cellular automaton is a system which works on an endless grid. In the horizontal axis one end quite often wraps around to the other one, to form a ring. The vertical axis can in some forms also wrap around (forming a torus), or just continue infinitely, for examples as rows in an output. The grid consists of cells (x/y coordinates). Each cell can โ in the simplest cellular automata, which I'm focussing on here โ either be alive or dead, active or inactive, binary one or binary zero. ## primer on neighbourhoods Whether or not a cell is alive or dead depends on the combination of states of its neighbours. This dependency forms the rule of a cellular automaton. For 1-dimensional cellular automata, the active world / grid consists of a single row. The neighbourhood which determines the state of a cell are in the previous state of the world: The row above it. Specifically, the neighbourhood of a cell in 1d automata usually consists of the cell directly above it and the two neighbours of that cell:
....LMR....
.....X.....
`X` here is the cell we're looking at, its neighbourhood is the cell directly above it `M`, and its two neighbours `L` and `R`. The individual states of these three neighbourhood cells determine the state of the `X` cell. ## Wolfram rules Stephen Wolfram has formulated a very useful convention to declare what a specific rule for a 1d cellular automaton is: You can consider the three neighbourhood cell states as three bits of information. For each combination of these three bits (8 possible combinations) we need to determine whether the target cell `X` is alive or dead, 1 or 0. This realization makes way to a binary notation of 1s and 0s for all 8 combinations. And since eight bits make up one byte, we can conveniently communicate the rule for any given 1d cellular automaton as a number between 0 and 255. ## somewhat well-known 1d automata rules You may not it by name but most of you will have seen this shape:
1
1 1
1 1
1 1 1 1
1 1
1 1 1 1
1 1 1 1
1 1 1 1 1 1 1 1
1 1
1 1 1 1
1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1
1 1 1 1
1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
This is the Sierpinsky Triangle. It is a fractal, a self-similar shape. The Sierpinsky triangle can be generated by a 1-dimensional cellular automaton with rule 90. 90 in binary being `01011010`. Just this rule and a single active cell in the top row, will lead to an endlessly growing shape like the one above. Let's decompose the binary representation of rule 90, `01011010`, to see how it generates that shape:
111 110 101 100 011 010 001 000 <-- 8 possible combinations of neighbour states
0 1 0 1 1 0 1 0 <-- resulting state of the cell
So you see, if only the `M` cell directly above `X` is alive, we have neighbourhood `010` and according to the table above, the `X` cell will die. But the cell immediately to the left of `X` will have its `R` neighbour as the only alive one (`001`), and as per rule 90 it'll become alive. The same is true in a mirrored way for the cell immediately to the right of `X`: Its neighbourhood is `100`, which also means it'll become active under rule 90. The cellular automaton calculates all states of all cells in a row based on the cells of the previous one, then repeat with the next row. Another interesting rule is rule 110, or `01101110` in binary. It generates a somewhat random looking triangle shape. The curious thing about rule 110 is that it has been proven to be Turing complete in a truely infinite grid. That is to say, with the right initial cell configuration (you'd need _lots_ of predetermined cells) you can compute anything. In theory you can implement a whole computer operating system with rule 110. Not that it is practical: It'd be slow and enormous. A third honorary mention must be rule 30. It also generates random shapes, but the randomness or 1s and 0s in every column is so good that it has been used as a pseudo random-number generator in computer programs. ## about my fascination Cellular automata exhibit emergent complexity out of very simple rules and preconditions. When you have a single active cell on a grid and a single byte of instructions how to build all future states, you wouldn't think this can possibly lead to anything even remotely complex or interesting. And yet it does. Emergent complexity is everywhere in our world, and cellular automata are a great simple way to shine a light and to simulate a small part of that. I invite you to take some time with the search engine of your choice and tumble down the rabbit hole of cellular automata. It leads to truely crazy places. And it keeps reminding me that to produce something complex, evolving and seemingly โaliveโ, we don't need very much. --- # better cellular automata in ORCฮ 2023-11-02 The initial version of cellular automata in ORCฮ wouldn't let me rest, so I made a better one. My first version of 1d cellular automata in ORCฮ [1] was very limited: It could plot a playing field of 18 cells width at most. For some reason my brain wouldn't let go of this and kept returning to the problem of expanding the width. What I've come up with is a relay system that transmits information over longer distances but also over several time steps. This mandated a stoppable clock to allow signals to reach the other end of the field before being read. Ultimately the solution has an elegance in simplicity but it took a couple of hours to figure out. I've also rewritten the part that reads the three neighbouring cells from the playing field before calculating the value for the cell to be written. Devine, the creator of ORCฮ kindly pointed me to the `Q` operator as a better alternative of using three separate `O`. - [screenshot: generating Sierpinsky triangles.](/gfx/20231102/1dcellautom.jpg)
.....cVo...Vc.......Cz......................................#.1d.cellular.automata.....version.2.....2023.anmd.#......................................................
.........zCo........dzT1111123456789abcdefghijklmnopqrstuv............................................................................................................
........yV3...Vy....xVa...............................................................................................................................................
..............3Ac.....................................................................................................................................................
.............rVf....................Vr.............................Vr.............................Vr.............................Vr...................................
......................Vy..........1Xf............................1Xf............................1Xf............................1Xf....................................
........Vc..........3A3Y3A1.......Vx.............................Vx.............................Vx.............................Vx.....................................
.Vr...1Xo..........nV6.mV4........af3Q...........................af3Q...........................af3Q...........................af3Q...................................
.fBb.1X..........................4M...Y.........................4M...Y.........................4M...Y.........................4M...Y..................................
..4YY4Io............Vc..........1X0.J..J.......................1X0.J..J.......................1X0.J..J.......................1X0.J..J.................................
....4A4......Vr...1Xo........Vx..42M...J....................Vx..42M...J....................Vx..42M...J....................Vx..42M...J.................................
...wV8.......fBb.1X.......92Xa9..0A0...J.................92Xa9..0A0...J.................92Xa9..0A0...J.................92Xa9..0A0...J.................................
..............4YY4Io.........Vw...0YY0A.....................Vw...0YY0A.....................Vw...0YY0A.....................Vw...0YY0A..................................
................2A4.......a0X8........08T.1.11.1.........a0X8........08T.1.11.1.........a0X8........08T.1.11.1.........a0X8........08T.1.11.1.........................
...............oV6...................a8X............................a8X............................a8X............................a8X.................Vo..............
.....................................Vm.............................................................................................Vn.............20X6.3O............
.........................42O...Vo.20X4t2O..................2O........t2O..................2O........t2O..................2O........t6O................c6X.............
........................z.X...76O.....4X.................x.X..........X.................x.X..........X.................x.X..........X.................................
#.INTERESTING.AUTOMATA.....#...#.l.....rL.......x.............l........r.......x.............l........r.......x.............l........r.......x.............l.......Rl#
#.124:.#..11111.#..........#...#...0.#...............................1...1.......................................................1...1................................
#.110:.#.111.11.#..........#...#...1.#..............................1.1.1.1.....................................................1.1.1.1...............................
#.102:.#.11..11.#..........#...#...2.#.............................1.......1...................................................1.......1..............................
#..90:.#.1.11.1.#..........#...#...3.#............................1.1.....1.1.................................................1.1.....1.1.............................
#..30:.#.1111...#..........#...#...4.#...............1...................1...1.......................................................1...1...........1...1...1...1....
#..16:.#....1...#..........#...#...5.#..1.1.1.1.1.1.1.1.............................................................................................1.1.1.1.1.1.1.1.1.
#...2:.#.1......#..........#...#...6.#.................1...........................................................................................1..................
#..........................#...#...7.#................1.1.........................................................................................1.1.................
#.enter.code.into.Ts.above.#...#...8.#...............1...1.......................................................................................1...1................
...............................#...9.#..............1.1.1.1.....................................................................................1.1.1.1...............
#.VARIABLES................#...#...a.#.............1.......1...................................................................................1.......1..............
#.o:.number.of.rows..const.#...#...b.#............1.1.....1.1.................................................................................1.1.....1.1.............
#.x:.read.and.write.column.#...#...c.#...........1...1...1...1...............................................................................1...1...1...1............
#.y:.raw.row.counter.......#...#...d.#..........1.1.1.1.1.1.1.1.............................................................................1.1.1.1.1.1.1.1...........
#..........................#...#...e.#.........1...............1...........................................................................1...............1..........
#.m:.r2l.wrap.read.row.....#...#...f.#........1.1.............1.1.........................................................................1.1.............1.1.........
#.n:.r2l.wrap.write.row....#...#...g.#.......1...1...........1...1.......................................................................1...1...........1...1........
#.o:.l2r.wrap.row.counter..#...#...h.#......1.1.1.1.........1.1.1.1.....................................................................1.1.1.1.........1.1.1.1.......
#..........................#...#...i.#.....1.......1.......1.......1...................................................................1.......1.......1.......1......
#.r:.read.row.counter......#...#...j.#....1.1.....1.1.....1.1.....1.1.................................................................1.1.....1.1.....1.1.....1.1.....
#.w:.write.row.counter.....#...#...k.#...1...1...1...1...1...1...1...1...............................................................1...1...1...1...1...1...1...1....
...............................#...l.#..1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.............................................................1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.
...............................#...m.#.................................1...........................................................1..................................
...............................#...n.#................................1.1.........................................................1.1.................................
......................................................................................................................................................................
## Links - [[1] my initial article on cellular automata in ORCฮ](/journal/2023-10-28-cellular-automata-in-ORCฮ.gmi) - [ORCฮ thread in the lines community forums](https://llllllll.co/t/orca-livecoding-tool/17689/) - [ORCฮ on Hundred Rabbits' internet page](https://100r.co/site/orca.html) --- # 1-dimensional cellular automata in ORCฮ 2023-10-28 Encouraged by randomly discovering a binary counter, I made a cellular automaton. I've introduced the ORCฮ only recently on this gemlog. It's a grid-based system that can generate MIDI messages to be picked up by external instruments, to compose / compute music in a live-coding kind of way. The thing is, ORCฮ is not a musical instrument. It is a language. A weird one, made by weird people living on a boat. A minimal one, a cryptic one. I _love_ minimal, cryptical geek-things. The other day I created a binary counter in ORCฮ through a lucky typo. Musical instruments don't generally do binary counters, programming languages do. For reasons that deserve at least one separate journal article, I've taken that happy accident and ran with it. I made a one-dimensional cellular automaton. It is limited by the fact that ORCฮ โ to my knowledge โ has no means of counting further than 36. Due to the math I'm doing to calculate cells and their neighbours, the playing field is limited to a width of 36 / 2 == 18 cells. Not very impressive but it does get the message across. What I _really_ like is that the code can produce all 256 varieties of 1-dimensional cellular automata simply by entering the associated Wolfram code in binary form into the sequence of the `T` operator of ORCฮ. Another happy accident in a way. I've tried to make the code somewhat well-commented. It was important to me to keep the code itself compact, to get as much space as possible for the playing field itself. I unfortunatelly have no easy way to introduce syntax-highlighting here on gemini so the code will look somewhat crappy in the gemini browser of your choice. It _will be_ somewhat more readable once loaded into ORCฮ.
#....................................#......#.numeric.pointers.................#
#.......1d.cellular.automaton........#...................Ci......Ci........iCm..
#....................................#.................hAf.1X..1Af.1X.....aA2...
..................................................Ci....wYYwIi..gYYgIi...yVc....
.#.block:.inject.y.offsets.#....................xVf.......0Ve.....2Vg...........
......Vy....................................#.middle.cell.left...right..column.#
....Vyc...Vy....................................................................
.d2Xc.Jd2Xc...#.block:.read.3.neighbour.cells.#.................................
...8..J..5......V0.Vx.V2........................................................
...e0Xc.......6Ae3Af0Ag.........................................................
...............kcOicOgcO......#...read.from.offsets...........#.................
...............4M.2M.1M.......#...multiply.with.powers.of.two.#.................
..............lV0mV0rV0.......#...store.in.variables.l.m.r....#.................
..............#.block:.calculate.child.cell.value.#.............................
................Vl..Vm..........................................................
#write.offsets#.0Y0A0..Vr.......................................................
.......Vy..........0Y0A0........................................................
.....9Bc...Vx.........0B7......#.build.decimal.sum.of.binary..#.................
...i0X3.c0Xf...........78T...1111....#.......T:.Wolfram.rule.in.binary.........#
.....3................f3X......#.write.child.cell.value.......#.................
............#.0.#...............1...............................................
............#.1.#...............................................................
............#.2.#...............................................................
............#.3.#...............................................................
............#.4.#...............................................................
............#.5.#...............................................................
............#.6.#...............................................................
............#.7.#...............................................................
............#.8.#...............................................................
............#.9.#...............................................................
............#.a.#...............................................................
............#.b.#...............................................................
............#.c.#...............................................................
............#.d.#...............................................................
............#.e.#...............................................................
............#.f.#...............................................................
............#.g.#...............................................................
............#.h.#...............................................................
............#.i.#...............................................................
............#.j.#...............................................................
............#.k.#...............................................................
............#.l.#...............................................................
............#.m.#...............................................................
## update: 2023-10-29 I've restructured a lot of the code to make the generator more compact. While doing that I've also removed the comments. The code is now a bit less readable but with the first version above this shouldn't be an issue. Currently I'm working on widening the usable playing field to generate wider patterns but I'm suffering a lot of brain-fog today, this will have to wait.
#.1d.cellular.automaton.#..................................
...........................................................
..Ci..............zVo...#.z.is.number.of.rows.to.generate.#
mVeYYYYYYYe.........J......................................
..J.......J.......iCo......................................
hAe.1X..1Ae.1X...9Aa.......................................
.vYYvIi..fYYfIi.yVj....Vy..Vy..Vy..........................
...lVd.....rVf......22Xj12Xj.2Xj...........................
........................Vl.Vm.Vr...........................
......................6Ad.Ae.Af............................
.......................jjOhjOfjO...........................
.......................4M12M.....#.interesting.rules......#
.....................21X4..0...J.#..30.00011110....a.RNG..#
.................Vz........J...J.#..90.01011010.Sierpinsky#
............Vy.1Xo.......4A0...J.#.110.01101110....Turing.#
..........8Bj.1X..........4YY4A............................
...........bYYbIo.....Vm......4B7#.Wolfram.rule.in.binary.#
............h.Xb...90Xe........38T...1111..................
..............................ebX1.........................
..........................#.0.#.........1..................
## Links - [My journal on ORCฮ and Sunvox, my music-making setup](/journal/2023-10-22-ORCฮ-and-sunvox.gmi) - [ORCฮ on Hundred Rabbits' internet page](https://100r.co/site/orca.html) - [Wolfram code for 1d cellular automata](https://en.wikipedia.org/wiki/Wolfram_code) --- # Tech degrowth is a process 2023-10-27 Progressing to a simpler life takes time, more than anything. It's been a little over a year now since I've started to be fully aware of the wasteful and energy intensive life I was living. Some things that are just normal now seemed ludicrous back then. And I am acutely conscious of the fact that I'm not actually doing anything drastic yet. Examples: Our microwave oven kicked the bucket a few months ago and we simply haven't replaced it. Re-heating leftover food on the electric stove probably isn't saving any electricity compared to the microwave (I have a suspicion it costs more energy) but it is one less โthingโ in our home that will only partially recycled at the end of its life. Plus we have some reclaimed space on the kitchen counter which we really value. Our dishwasher still works but we're not using it either, same for the clothes dryer. We went through last winter without ever needing the dryer and somehow we just stopped using the dishwasher. Washing dirty dishes by hand (we're a two adult household) is _no_ big deal whatsoever and it gives us some more time to talk and just be with each other. We switched off the TV one evening after finishing the last episode of a nondescript Netflix series and haven't switched it back on since. Its been unplugged from the wall for a while now and I'm certain the remote is dead. We used to eat dinner watching Netflix or some other stream and we do enjoy good entertainment. But now we spend time talking about our days, make plans for the upcoming days and simply _be_ with each other. I barely switch on the second monitor on my computer anymore. With tmux in place and generally me working mostly with commandline programs, the need to see two screens at the same time is much less. My company forced me to get a new company phone the other week. Apparently my 4 year old iphone will stop receiving updates. I politely told them that I had just gotten an update a few days before their request and that a one day batterylife is plenty since I'm spending 80% of my workdays at home. But no, I had to get a new one. When I asked whether we have something like a Fairphone or similar alternatives to pick from I only received empty stares. Only Samsung or Apple devices. Grmpf. Apple it is then. I'm not happy with either company but I'd rather not have GoogleOS, thank you very much. I'm seriously considering spending some of my energy to join the โgreen and socialโ initiative we have to make a change there. Buying local produce and valuing quality over price is another thing. Local food produce is the thing everyone thinks about first. But there is more. I have a leather laptop slingbag for work. It feels good to use it. One of the hoops that hold the shoulder straps snapped the other day. So I found a local leatherworker and gave the bag for repair. It cost me 50 โฌ to get it done, plus three hours with public transport to bring and take the bag. Totally worth it. The bag is fantastic and the craftsman did an awesome job. That new hoop will probably outlive me. Not only did I get to keep a piece of equipment I really enjoy, I did a small part in keeping a local artisan in business and had a very interesting chat with him. For 50 โฌ I can easily get a nylon slingbag made in China and moved halfway across the globe while paying Amazon. No thanks. Anyway, what is my message here? We all can change something in our lives toward degrowth. The first steps probably won't be drastic. But they'll put something into motion, form a new normal, from which we'll take another step. And another. I'm very certain that this a way forward we can all take. --- # I made a binary counter in ORCฮ by accident 2023-10-26 Pretty much what the title says: I made a binary counter in ORCฮ by accident. It does work in all four directions (n, e, w, s) but I like w best since you can see the digits move more nicely.
#.binary.counter.
.........D4......
..........Y.H.D2.
.........30xw.*..
.#.#.............
..#.1...........#
..#.0521........#
..#.2152631.....#
..#.42684268421.#
## Links - [ORCฮ on Hundred Rabbits' internet page](https://100r.co/site/orca.html) --- # ORCฮ and Sunvox 2023-10-22 User Nono on Bubble suggested to share Sonic Pi creations over gemini since it is essentially text. Well I don't use Sonic Pi but I do like the idea so here we go. ## an introduction of sorts Sonic Pi is a program that allows you to โprogramโ music, quite literally. It is one of several environments that form the โlive-coding musicโ subspace. All of these environments allow the code to be tweaked while the song is playing, allowing for a performative element. There are even algo-raves. I mean of course there are. If you're curious, find artists like โDJ_DAVEโ, โdeerfulโ or โLil Dataโ on YouTube. There are more of course, these were mentioned in the thread on Bubble. Since compositions are essentially code (text) it is easy to share them and doing so doesn't take much bandwidth. ## me in all this I dabbled with Sonic Pi but I don't like it too much: It is a coding IDE. And I stare at similar pieces of software most of my days at work. So when I dabble in music in front of my computer, I prefer the ORCฮ system by Hundred Rabbits. It is quite esoteric but that's why I like it: It takes my mind to new spaces. It has a puzzle element to it in the sense that getting it to do certain things isn't always straight forward. So I'm using ORCฮ to generate tunes, beats, and such, but ORCฮ merely generates MIDI notes (or OSC, or UDP) โ it cannot make sound. I'm using Sunvox for that. Sunvox originally is a tracker but I have never used it as such. It has a variety of nodes that can be interconnected to create instruments and effects. I've made a standard instrument template with Sunvox that is MIDI mapped to ORCฮ. The combination is good enough for what I do. If you're curious, you can download the Sunvox template below. My latest ORCฮ composition is this:
#.floating.in.Laniakea.#..#.random.melodies.#
#.set.BPM.to.60........#..........Dd.........
............#.kick.#.........................
..............D4.................0r4.........
..#.rnd.key.#..:51C...............34TFCEA....
...R5..R7...#.prime.number.pad.#.77XA.0R4....
...1Y1F2....D2..D3..D5..D7..Db.........13TFAG
.......Y.H...Y.H*Y*H.Y.H.Y.H.Y.H......26XA...
......05xE..00xE02xE04xE03xE01xE#.xylophone.#
.......................................:12C..
.......................................:12F..
.......................................:13C..
.......................................:13F..
.......................................:14A..
.......................................:14A..
Now, I'm aware that if you're unfamiliar with ORCฮ then this will look beyond crypticโฆ sorry not sorry I guess. Come to think of it, you can of course play this composition with _your_ MIDI instruments and totally change the feel. ## Links - [My Sunvox instrumentation](/music/midimapped.sunvox) - [the thread on Bubble](gemini://bbs.geminispace.org/s/music/6325) - [Gemini site of Hundred Rabbits](gemini://gemini.circumlunar.space/users/hundredrabbits/) - [ORCฮ on Hundred Rabbits' internet page](https://100r.co/site/orca.html) - [SunVox Tracker and MIDI Synth](https://warmplace.ru/soft/sunvox/) - [Sonic Pi](https://sonic-pi.net/) --- # Read this from git 2023-10-21 You can now read Laniakea offline through git, or download daily-updated Markdown summaries. I got inspired by an article by Solderpunk to provide my blog articles as easily distributable offline copy through git. Solderpunks article goes conceptually further than I do with my implementation. Nonetheless this was a satisfying experiment. You can now 1. have a offline copy of this website through git and update it whenever you are online 2. download Markdown summaries of all blog articles in one file and all tui cheatsheets in another 3. use your local git copy from 1. to generate the Markdown files from 2. yourself ## How to do this ### some context Laniakea (this website) is generated by some commandline tools. This allows me to keep the content separate and โwrapโ it in scaffolding that make up headers, footers and such. If you only want to read my articles offline, this doesn't matter to you. If you want to build a local gemini page to *browse* offline, you'll need Linux, cygwin or something comparable since I'm using `awk`, `sed` and such to get the job done. ### get your offline git copy
git clone git://rodoste.de/laniakea.git
After this you'll find the raw content of my journal in `./journal` and the TUI cheatsheets in `./tui`. ### download pre-generated Markdown files A chronological archive of all journal entries can be downloaded through gemini: - [Laniakea Journal](gemini://laniakea.rodoste.de/md/journal.md) The same goes for my TUI cheatsheets: - [Laniakea TUI cheatsheets](gemini://laniakea.rodoste.de/md/tui.md) Both files are markdown-ish. I've taken care to convert gemini links to markdown links. Links to other articles won't work though. Some other peculiarities in gemini script aren't converted to perfectly correct markdown. The resulting files read fine through a plain-text editor and markdown renderers such as `glow` seem to have no problem either. So this is good enough. ### generate the Markdown summaries from your local git copy If you have cloned my git repository you can generate the Markdown archives yourself:
./build offline
The .md files will be written to `./static/md` ## conclusion The idea initially outlined by Solderpunk resonates quite strongly with me. It adds a layer of resilience to online content. In the year that I'm part of gemini space, many of the more interesting articles have already vanished, or changed URLs so I don't find them anymore. Having the option to clone a git repository solves the link-rot issue almost entirely. Gemini pages are uniquely qualified for this (along with gopher pages) since they are human readable and largely non-interactive. They are text files, essentially. As such, cloning an entire repository just to read a few articles isn't unreasonable. Text files are small. Even blogs of much more productive writers than myself will hardly ever exceed a few megabyte in size after years of frantic writing. Interestingly I was hesitant to implement this though. Are my ramblings really relevant enough to offer them as archives and as offline copies? Probably not. What made me decide to go ahead with it is that it doesn't matter. I'm not putting myself on a pedestal. I don't think my writings are specially important. Maybe this is useful to someone. Laniakea has always been in a git repository, all I've done is provide read-only access and add the Markdown archive generation. ## Links - [Solderpunks article on content distribution with git](gemini://zaibatsu.circumlunar.space/~solderpunk/gemlog/low-budget-p2p-content-distribution-with-git.gmi) --- # I finally have offline backups 2023-10-06 My brothers company got hit by an encryption-attack the other week. Time to get an offline backup myself. So my brothers company got hit by a cyber attack the other week that encrypted all their data, on every server, printer, copier and every client machine that was in the (virtual) network. The company was smart, having everything backed up on offline tapes. They lost one day of data and one week work to get everything back up and running. I can only assume they took measures to get the infection out, too. This reminded me that while I believe that I have a reasonable backup strategy resembling 3-2-1 (three copies of the data, two local but on different media, one offsite copy) what I do not have is a cold offline backup. Something that isn't connected to anything and can't be reached no matter how badly the network is infected. Time to get on that. ## Starting point All machines (mine, my wifes, my selfhosting, our phones) do backup their vital data onto a central point in our home network in addition to machine-local backups for most machines. The central backup store then pushes the delta to an offsite hoster in another country weekly. So all I need to do was to backup everything from that central point. ## Other desires An 8TB harddrive as backup solution was an obvious choice: It has enough storage to hold all data. It is relatively cheap. It is small and light enough to quickly grab and run in case of natural desaster. Keeping that last point in mind, I want a self-contained unit. Not only a dumb harddrive with data, but a system that can boot and be used to bootstrap the recovery. ## My approach The solution I've settled with is this: The harddrive has a boot partition and a 5GB partition for Debian Bookworm for ARM64 devices. A third partition is also 5GB large but empty, this is meant to be free space to create a bootable system for x64 systems. Granted, I probably have to sacrifice the boot partition to swap between ARM64 and x64 but such is life. The fourth and last partition is an almost-8TB NTFS storage space that houses all backups along with backup / restore tools. ## Setting it up This section is mostly for my own benefit and serves as documentation. Getting a Debian image for Raspberry Pi to boot from a >2TB HDD took some time. In the end what worked for me was this: First, download the debian image and write it onto the HDD with
xzcat 20230612_raspi_4_bookworm.img.xz \
| sudo dd of=/dev/sdb bs=64k oflag=dsync status=progress
Then, convert the partition table from Master Boot Record to GUID. This is the step that allows partitions larger than 2TB and it seems to be crucial to do this _before_ booting that system. Debian will try to expand the root partition to maximum size and that hangs if the partition table is still MBR but the drive is larger than 2TB. I used the `mbr2gpt` bash script from the usb-boot tools zip file that I found in a Raspberry Pi forum to achieve this, link below. The system is then ready to be booted and will expand the root partition to fill the entire disk. Once that is done, I again reboot into my actual system, mount the backup HDD and re-shrink the boot partition to 5GB. I also add the additional partitions as mentioned above. Lastly, I can boot back into the Debian system and configure it. I've kept track of the cornerstone steps of installation in this script:
#!/usr/bin/env bash
# this script ISN'T a 100% faithful recreation of this system
# but it outlines the most important parts that set it apart
# from a baseline Debian Bookworm
# set the hostname to something sensible
hostnamectl hostname backupper
# ensure up to date packages
apt update
apt -y upgrade
# install essentials
apt -y install avahi-daemon ntfs-3g
# install backup / restore related packages
apt -y install ecryptfs-utils clonezilla
apt -y install rsync rclone duplicity
apt -y install zulumount-cli zulucrypt-cli zulusafe-cli
# various utilities
apt -y install git wget tmux
apt -y install figlet lolcat
ln -s /usr/games/lolcat /usr/bin/lolcat
wget http://www.figlet.org/fonts/chunky.flf /usr/share/figlet/
# create a better pre-login banner
figlet -f chunky "I make backups" | lolcat -S 3 -F 0.2 -f > /etc/issue
echo >> /etc/issue
# install a browser
apt -y install w3m
# backup sessions can be long, so here's the original rogue
apt -y install bsdgames-nonfree
ln -s /usr/games/rogue /usr/bin/rogue
The system only has a root user without password. This isn't an issue since the disk will be offline and off-power nearly all the time. In addition to the steps above I have disabled some daemons, moved SSHd to another port and secured the daemon. I can SSH into the machine with my default key if I ever need to. ## Backup Scripts Here's an overview of the backup scripts that come with the disk:
#!/usr/bin/env zsh
doTint=1
doGrayscale=0
pastels=("#FEDDB2" "#F0ADDC" "#A47DCA" "#9EC8F3" "#C4F0C2")
color="#ffffff"
if [ $doTint -eq 1 ]; then
n=$((1 + $RANDOM % $#pastels))
color=$pastels[n]
doGrayscale=1
fi
if [ $doGrayscale -eq 1 ]; then
# convert center-crop image, dither it to 8 colors and tint with identified color
convert $1 \
-gravity center -crop 2:1 \
-resize 800x400 \
-colorspace gray -fill $color -tint 100 \
-dither FloydSteinberg -colors 8 -
else
convert $1 \
-gravity center -crop 2:1 \
-resize 800x400 \
-dither FloydSteinberg -colors 8 -
fi
It generates output images in the reduced colorspace of the original, plain grayscale or tinted. Output looks like this: - [Earth, in the original colorspace](/gfx/dither-earth-asis.jpg) - [Earth, in grayscale](/gfx/dither-earth-gray.jpg) - [Earth, tint variation 1](/gfx/dither-earth-tint1.jpg) - [Earth, tint variation 2](/gfx/dither-earth-tint2.jpg) - [Earth, tint variation 3](/gfx/dither-earth-tint3.jpg) - [Earth, tint variation 3](/gfx/dither-earth-tint4.jpg) It will print the raw image data to stdout so to use, call it like this:
dither.zsh path/to/image.jpg > output.jpg
or pipe it into an image previewer
dither.zsh path/to/image.jpg | feh -
โโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโ
โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ
โ โ โ โ โ โ โ โ โ โ โ
โโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโ
โ โ โ โ โ โ โ โ โ โ โ
โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ
โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ
โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ
โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ
โโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโ
My soroban has twenty rods. This is purely because I got the counting beads in a pack of one hundred, so that is the most rods I could make. It is imensely satisfying to have made a physical thing, more or less from scratch, that serves a purpose. I probably won't abandon the calculator on my phone anytime soon but I want to hone my calculation skills on the Soroban. Right now I know how to do addition and substraction on it. I had started to learn multiplication when I stopped practicing, by now I forgot completely how that works. Oh well. I'm not going to pretend that I'm knowledgable enough to talk about doing math on a Soroban yet but I want to shed a dim light on how it works: The right-most rod represents the one's digit of a number. The one to the left of that represents the ten's digit and so on. The four bottom beads are called โearth beadsโ, when pushed toward the center beam each count one, or ten, or hundred, ... depending on which rod they are. The single bead on top is called the โheaven beadโ, when pushed toward the center beam it counts for five, fifty, five hundred, ... So if you'd represent the number 5917 on a Soroban, you'd need the four right-most rods and it would look like this:
โโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโโโคโโ
โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โ โ โโ โถ โ
โ โ โ โ โ โ โ โโ โถ โโ โถ โ โโ โถ
โโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโโโชโโ
โ โ โ โ โ โ โ โ โโ โถ โโ โถ โโ โถ
โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โ โโ โถ
โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โ
โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ
โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โโ โถ โ โโ โถ โโ โถ
โโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโโโงโโ
0 0 0 0 0 0 0 5 9 1 7
I'm in a happy place right now. --- # Garden season has begun 2023-04-17 A brief overview of our gardening plans this year. We're dialing down our gardening efforts for this year, since we hope to shift to another appartment later this year. Regardless, after returning from Spain we've put the first seeds into the ground. On the 10th I've planted ten gherkin seeds for pickling and by today they have all sprouted and the sprouts are already about 5cm long โ these guys are fast! On the same day I also planted a bunch of Cayenne Chillis โ no sign of them yet โ and six tomato seeds. The tomatos have just broken surface. All these seeds are in our living room โ outside is still a bit cold for them. We also want to try to grow our own potatos this year โ not an economic endeavour since all we have is a balcony, we'll try a bunch of growbags, for science โ so I put a bunch of them out next to the gherkins to sprout before I put them into the growbags. The last thing I did last weekend was to clear one clay planter box on the balcony and sowed fresh Dill seeds. They'll be the only herbs I attempt this year โ not counting the basil that we have from last year. My wife planted some Indian chilli plants midway through last week. No sign of that yet. Chillis are a bit slower. We have a few more growbags that won't be taken up by potatos, so we are contemplating planting onions or ginger. Neither of which seems ideal: Onions to our understanding won't multiply unless you grow them to flower and collect the seeds. An onion seed will give you one onion, unlike potatoes. Ginger will grow slowly into more ginger, so we're not sure whether or not that's worth it since we're shifting. Anyway, gardening season has started and we're both excited! --- # Retrocomputing as form of progress 2023-04-15 I honestly believe much less power-hungry computers for the average user are the way forward. I couldn't sleep the other night, and instead of doing anything that might actually help me sleep I went down an internet rabbithole of self-made 8-bit computers built around the Zilog Z80. Now, the Z80 might need some introduction these days: It is a CPU that is 50 years old and still in production. Let that sink in. It has an 8-bit address-space and a 16-bit memory address space: 64 kilobyte of memory is all you're ever going to get (unless you cheat with paging ;) ). It still being in production makes it a CPU that is quite commmonly used in DIY retrocomputing projects โ common as far as anything in a niche culture can be. Finding those projects made me remember my own abandonned Z80 project. Fond memories came up, and the urge to dust if off and complete it. Building a computer around the Z80 is actually very simple: CPU, a clock circuit, ROM and RAM chips are all that's required. It gets tricky โ or trickier at least โ when it comes to input / output. I/O over a serial connection is relatively easy but then you're using the Z80 by means of another computer and that somewhat defeats the purpose. But creative and clever people have developed all sorts of interface options: Storage on SDcards, Compact Flash, even IDE hard drives. None of which existed in the era of the Z80. Soundcards and video cards. USB keyboard and mouse. The list goes on. Most video options in the retrocomputing scene involve microcontrollers clocked many times faster than the Z80 itself and with more RAM, too. That seems odd but todays' monitors and the digital interfaces needed for them make more โera-correctโ solutions prohibitively complex. This apparent paradox made one approach I found in at least two designs quite appealing: Build a Z80 computer core as described initially, out of discrete ROM, RAM, โฆ chips. Then connect it to a โvirtualizedโ I/O ecosystem, simulated by a microcontroller. This enables you to use a USB-keyboard for input, SDcard for storage and a SPI-connected LCD display with relative ease. The whole system would still have a relatively low part-count due to the feature density of the microcontroller, and low cost since most microcontrollers cost less than the Z80 and its memory components these days. This still begs the question of why use the Z80 at all. If a microcontroller can simulate the whole I/O ecosystem, it can probably do a little computing โon the sideโ as well and replace the Z80 altogether. The answer I found for myself to this question can be summed up in one word: โlongevityโ. The Z80 is easy to understand and being in production after 50 years is testament to its utility. I could use the microcontroller as โbootstrapโ. An initial version of a computer that can be built somewhat quickly. The initial version of the working system would serve as a point to jump off of to complete the system and grow it into something permanent, without needing the microcontroller. Later, when the microcontroller will inevitably go out of production and be replaced by a newer model, the Z80 will probably still be there. Parts could be replaced and the whole tyranny of obsolescence could be avoided. What does this all have to do with the โprogressโ mentioned in the title? Reading the books that I decently did has changed my view on what progress is for me. I no longer apply the โprogressโ tag automatically to the latest, newest, shiniest thing that gets thrown onto the market. โProgressโ has (again?) gotten a correlation to the question โis it better?โ The latest AMD Threadripper is many orders of magnitude more powerful than a Z80, but my journey from such a machine to a Raspberry Pi as my main computer has shown me that โmore powerfulโ doesn't automatically mean โbetterโ. I am definitely getting more done on the Raspberry Pi than I did on the Threadripper. I do procrastinate less (that means โbetterโ for me). I am less distracted by YouTube, Netflix and such. App notification bubbles simply do not exist on my system (again โbetterโ for me). My system uses a lot less electricity (better for the wallet and the planet). So in that view, the much less powerful system still allows me to do everything I need to get done, gives me a healthier setting and is more eco-friendly. At the same time there are no real downsides โ minor inconveniences yes, but no downsides. Bottom line is this: The less powerful system is progress for me. It is better โ for my situation โ than the one before it and thus marks progress. Progress could be described as one more step in the given direction (towards a worthy goal). In that sense the Raspberry Pi system is one such step. Ever more powerful computers are not automatically โprogressโ. Think about it: One more step in the given direction will eventually bring you past your goal. From then on any step in the same direction will move you further and further away from that goal. Is my current Raspberry Pi system the ultimate achievement, have I reached the goal? Of course not. The Raspberry Pi system โ naturally โ still has complexities and complications that I have a hard time to control or get rid of. It still runs a modern Linux system. Linux is fantastic, but it is complex and not always intuitive. So why not look for another step in that direction of lower power, fewer-moving parts computer systems as a form of progress? This form of progress, like all, will have its end of course. There certainly is such a thing as a too-simplistic computer system for every day use. But during that long, sleepless night I came to the conclusion that it is hard to foresee where that tipping-point actually is. Maybe it is already reached when my main computer can no longer use the internet ๐ค. Maybe I learn to live without internet altogether or internet only on my phone. Maybe a Z80 system would show me a way to another step of progress, one that doesn't need computers at all. Food for thought! ## Links - [Oberdada - It seems we share some thoughts on progress](gemini://oberdada.pollux.casa/gemlog/2023-02-18_smile.gmi) - [Z80 on Hackaday.io](https://hackaday.io/search?term=z80) - [Z80 Family official support page](http://www.z80.info/) - [Ben Eater 8 bit computer](https://eater.net/8bit/) --- # Progress and computers 2023-04-12 Many of the common microcontrollers available in the maker scene today are clocked at over 100MHz and will have more available RAM and flash memory than the Commodore C64 I had as a boy. It makes me wonder if it would be possible to build an operating system with a shell and programs you can interact with, input via keyboard, output to a relatively low-resolution, ... on a microcontroller. Not a gaming emulator platform, but a computer with applications to do some actual work. Granted, a microcontroller usually is architecturally very different from a general purpose computer and might not be as suitable to general purpose use because of that. Reading about Forth and learning it made me come across fome Forth implementations for microcontrollers like the Teensy 3.1 or the newer Raspberry Pico. I'll need to bootstrap one of my spare microcontrollers and find out to what abstraction levels the Forth implementations take it. I have no illusion that my level of spare time and existing knowledge of low-level programming would be sufficient to build my own ecosystem, but with a decent platform to start off of, building applications would be within reach. Of course, the obvious question to building a general purpose computing ecosystem on a microcontroller is โwhyโ. For most applications, the system will be pretty useless and โbecause we canโ isn't really a valid answer for me in this context. With a microcontroller you can certainly use an SDcard or some USB device as storage device. Connecting it to geminispace might work as well but the modern internet will likely be out of reach, probably even email. So why then? I think minimizing my setup โ or rather having an even more minimal setup as option โ would be an interesting exercise in simplification and would alter what I do with computers and how I do it. So I've done some homework and I found many interesting projects around the idea. Two of them stood out: One is PotatoP, a computer built around the Sparkfun Artemis platform that won the Low-Power Challenge. It is written from scratch in Lisp. See the link section below. It neatly shows what a single person can do these days with enough determination. The other one _really_ caught my attention, it is the ESP32ForthStation. It is based on the LilyGo TTGO VGA32 device as platform which provides the microcontroller (ESP32), PS/2 sockets for keyboard and mouse, an SDcard slot and VGA output. The hardware really provides all the I/O needed to qualify as an independent computer in my opinion. The ESP32ForthStation is a mixup of several open-source projects that brings this whole thing to life. Go check out the github and some of the videos linked there if you're interested. It turns out the TTGO VGA32 hardware can also be used to run other, old operating systems like the C64 and it is cheap. Ooooh, tempting. Honorable mention of course is uxn which I've mentioned before. I haven't found a microcontroller implementation that takes this to a full computing stack level though. ## Links - [PotatoP on hackaday](https://hackaday.io/project/184340-potatop) - [ESP32forthStation](https://github.com/uho/ESP32forthStation) --- # yesterday was a good day 2023-04-11 Yesterday was the first day in a really long time where I had the energy and the mental headspace to get stuff done. We've returned from our vacation in Spain last Friday and had spent the weekend more or less doing nothing, reacclimatizing to our home. I had some IT maintenance to do with our selfhosting services but other than that I'm not quite sure what we did this weekend. But yesterday was a really good day. I take from it that the vacation really helped and I was able to recharge my batteries and gain some mental distance to every day life. First thing in the morning I did bake a bread. Since I'm the main bread eater in the house I might as well start to learn how to make my own. Bread from the stores here isn't bad but baking it from dough and yeast is a skill I wanted to learn anyways and it frankly tastes better. I let it cool, then cut the whole loaf and put the slices into bags of four and put those in the freezer. Without preservatives the bread lasts for about a week outside of the freezer but with freezing it comfortably lasts longer so I can eat it all. Next, I planted some seeds and started the gardening season. Should have done that before the vacation but they would have wilted anyway so I didn't. Now I'm a bit late but in a way I'm glad because the nights here are still very cold, spring is late. I planted four Tomato seeds, about ten Gherkins for pickling (something I want to try this year) and a few Chilli plants. Oh and Dill as the only herb. We've rediscovered Dill as a herb in Spain. Last year my herb-growing adventures didn't go too well, I'll stick with only Dill this year and give it more attention. All seeds except for the Dill are in small sprouting pots inside the apartment near the south-facing window. The Gherkins take around a week to sprout, the others longer. This gives us enough time to buy more soil before we move the sprouts onto the balcony. Hopefully by then it is warmer. We discovered that we have a Mason Bee that dug a hole into the building facade, right into the insulation. I've tried to convince the bee that this is not a good place for its offspring by means of gipsum but to no avail. Ok fine, I'll seal the hole when the next bee generation has left. We used the remaining gypsum on some drill holes inside the apartment and sealed them off nicely. Although this is a simple thing to do I'm quite proud that we got this done. Some of these holes are older than I want to admitโฆ Once that was done the bread had sufficiently cooled and we made brunch from it with some of the Chorizo we brought from Spain, and local Cheese / Paprika / Gherkins. Yummy. After dinner I went for a 9km walk to stretch my legs. I'm quite out of shape after winter so that felt good. The day before I had started to do some back and shoulder exercises again since my back was giving me trouble โ I need to consistently do the exercises. In the evening we tried to get rid off a facebook account of my wife's dad who died last year but Facebook is refusing to log us in even though we have the password. It demands uploading an official ID. Which is kind of stupid for only shutting it down โ I won't go into why I think this is excessive to begin with โ so we left it. I'm guessing the ID requirement might be since no one has logged in for such a long time and now we're trying to do it from a country different than what usually used for the account. Oh well. Maybe my wife can get in when she goes to visit her mom next month. And if not, so be it. So yeah, just a simple update about a simple but very positive dayโฆ have a good one, too! --- # Progress (?) 2023-04-09 Musings on some of the latest improvements on local city busses. The city transport corporation apparently has recently purchased a new bus model. It is this bus that triggered a whole line of thoughts. There are a few additions on the bus that struck me as utterly pointless; progress for the sake of progress. Bus addition number one: USB charging ports, prominently illuminated by blue LEDs. This is an inner-city bus, no one spends more than 30 minutes on it before they've reached their destination. I'd say the actual demand for battery-life saving USB-power on that bus is next to zero. Certainly I have never seen one of these plug points in use. Think about it โ would you have a charging cable with you on your normal city trips to even use the damn thing? The highest demand for those would probably be by schoolkids, who carry their own powerbank to begin with. Bus addition number two is a monochrome LCD display sporting an animated arrow pointing toward the โstop pleaseโ button. It was backlit. Come onโฆ we all know what the push buttons do, the display isn't needed. Why then, are these two things being put there? The answer is obvious: The commerce sales machine needs to keep running. Every new model of anything needs to be better than its predecessor, why else would anyone buy an upgrade? This is fine in itself, progress has gotten us where we are. But progress in itself shouldn't be a goal, but a tool. New models should be _better_ in order to sell them. I challenge the notion that either of these addition makes for a better bus. The bus for me is an example of โprogress saturationโ. The bus as a concept is mature, of course. The interior is being changed to better comfort the elderly, parents with prems, etc. Certainly, creature comforts for the driver are also improving โ which is a good thing โ as are safety and security measures, engine and steering mechanisms. etc. But why not stop there and focus our efforts on very marketable aspects of fuel-efficiency, mileage, cleaner exhausts, and similar things? Certainly that is also done. What I've called โprogress saturationโ before indicates features being added that serve no actual purpose. When I teach my customers lean-agile thinking, customer-centricity is paramount. Unterstanding the customers needs is essential to building products that customers want to buy. In a restaurant, the concept of customer-centricity is simple: The product is the food (also more indirectly: good service, atmosphere and other factors). Would the restaurant serve you food you didn't ask for, you would likely not eat it or pay for it. You would likely not recommend the restaurant to friends and maybe not return. With busses, the concept of customer-centricity is less trivial. In the case of the bus manufacturer, the customer is not you or me, the schoolkids, or the commuters. No. The customer is the city transport corporation that buys the busses. The people on the bus are certainly one user group of the bus, but not a customer of the manufacturer (the driver being another, the service crew a third, and so on). However the people on the bus _are_ the customers of the city transportation corporation. So which one โ transport corp or manufacturer โ is at fault here? Or is it us? Do we actually demand these features? Do we _seem_ to demand these features? Working on the assumption that we do not, it would be advantageous for the bus manufacturer not to add the USB charging ports or the LCD displays for the buttons. Probably the bus would not be measurably more fuel-efficient without them but not adding them would reduce the part count, overall complexity of the system and thus streamline its manufacturing a little bit. It would allow for work hours to be spent elsewhere, and/or drive the cost down a tiny fraction. Apply this fat-trimming exercise often enough โ the one-percent rule โ and you're dealing with exponential returns in efficiency-gains. I wonder what it would take for our society and collective value-system to recognize a focussed, efficient, streamlined system as desirable and marketable. --- # I am spent 2023-03-15 About over-extending, Spain and the wonders of stack machines. This place has been quiet. I am completely and utterly spent. Haven't been this tired in years. I took a break from working on my self hosting setup now that it is mostly functional โ not complete! โ and mostly stable. I also haven't really worked on getting myself off the cloud in two weeks. I believe I have cleared and deleted two google accounts since I last spoke about it here and certainly I have requested deletion of a bunch more online accounts. But there is more to do. I'll pick this up again once we're back from our vacation. Thank god for the vacation. Starting this Saturday we're leaving for Spain. Three weeks of decompression, deeeeeep breaths, lots of sleep, good food and drink, reading, talking, connecting with people and hopefully starting aquarell painting again. We plan to also do some scouting for properties, Spain is kinda-sorta on our radar as a retirement plan. Were we live now retirement is too expensive. I'll take two books with me to Spain:
#!/usr/bin/env zsh
autoload colors
colors
# ensure files exist, load lists
FILE_DIR=~/.todos; FILE_TODO=$FILE_DIR"/todos.txt"; FILE_DONE=$FILE_DIR"/done.txt"
if [[ ! -d $FILE_DIR ]]; then echo "directory '$FILE_DIR' not found"; exit 1; fi
touch $FILE_TODO $FILE_DONE
TODOS=$(<$FILE_TODO); DONES=$(<$FILE_DONE)
# prepare glyphs. if you want to use plain ASCII, I recommend o, x, ^, v
GE=$reset_color
G=($fg[red]" ๏ฐ "$GE $fg[green]" ๏ด "$GE $fg_bold[yellow]"๏ฑ"$GE $fg[cyan]"๏ธ"$GE)
# functions
move_tasks() {
for i in $s; do echo $1 | awk 'NR=='$i' {print;exit}' >> $2; sed -i $i'd' $3; done
}
# run commands
if [[ $# -ne 0 ]]; then
COMMAND=$1
shift
IFS=