QZ qz thoughts
a blog from Eli the Bearded
Tag search results for 2020,~blog Page 1 of 4

slowcat.c and signature.c

A discussion in the Usenet group comp.sys.raspberry-pi about browsers turned to ASCII art when I brought up concerns about showing ASCII art in web pages (based on the recent notint screenshots here). And that discussion had one Charlie Gibbs reminisce about the "Andalusian Video Snail".

I found the file for him at https://grox.net/misc/vt/ — it's an ASCII art animation with VT100 escape codes so viewing it is tricky. Those animations are typically highly dependent on viewing on slow terminals, and modern hardware is anything but a slow terminal.

At grox.net there is also a slowcat.c which easily compiles. That code is essentially a loop of getchar();nanosleep();putchar(); to delay output. It worked okay for a few videos I tried, but the snails did not look so good. And it would not slow down STDIN, which would be handy for a program I wrote (more later).

So the biggest problem with the Grox slowcat.c is while it adds delays, it doesn't disable output buffering, so output ends up being large chunks showed without delay and then a delay for the next large chunk. That doesn't suit that particular animation well. Other problems include a "cat" that only shows exactly one file instead of arbitrary numbers, an awkward interface for delays (how many nanoseconds do I really want? and why does the code use usecs for presumably ╬╝seconds), and arg parsing oddness.

I decided to rewrite slowcat. I disabled buffering, switched to usleep(), employ getopt() and an arbitrary number of files, and added a option to have the program calculate a delay to emulate a particular baud rate, which is how terminal speeds were measured when these were written. Quite likely a baud of 1200 or 9600 was assumed by the animator. Baud is a measure of bits per second, so 9600 works out to 150 characters per second, or about 13 seconds for an 80x24 terminal screen. When I test time slocat -b 9600 snails.tv takes 3m33.23s while time cat snails.tv takes 0.47s. On my system stty tells me 38400 baud, which would be 4 times faster, but since it actually runs 453(ish) times faster, the baud equivalent is closer to 4,500,000 than 38,400. For most purposes, that faster speed is much appreciated.

So back to signature.c, by which I mean this program:

------                                         /* gcc signature.c -lm */
main(){int i,j,k,l;for(i=-12;i<13;i++,printf("\033[H")){for(l=61968*457+
p(10):0;}}puts("Elijah ");}p(int m){printf("%c",m);}

I use it in place of a .signature on select Usenet posts. I wrote it approximately 1995. Over the years, it's been used perhaps one or two dozen times, and I have made at least five variants with different email addresses, each of which has been reformated to have the lines the same length.

(An aside on .signatures: I have never used a proper .signature, that is to say a block of standard text appeneded automatically to the end of my posts or email. I have always done it manually, and, for Usenet posts, 99.9% of them are unique entries composed for that particular post. I have about 30 programs, most in Perl, that I have used and reused from time to time. Since I don't consider them true signatures, and do consider them part of the post, I do not use proper signature cut lines — dash dash space on a line by itself — which annoys some people, sometimes.)

The origins of that program are interesting. The program came to me in a dream where I visualized an ASCII art movie of cross-sections of a sphere that changes "color" closer to the core. The colors are represented by the characters in the string ".,:;iIJYVSOM" and the code uses some basic IOCCC obfuscation tricks, like using C arrays backwards: (offset)["array to index"], but is mostly pretty readable once reformatted. The use of +++ is very classic me, since I enjoy testing how far I can push a parser to accept the same character over and over. My extreme is perhaps this Perl one:

sub S(){@s=caller($/);$s[3]=~s s\w+:+ss&&print$s[3].q. .}$/=$^=~s/\S+/\n/;
$_="Just (eli) Another (the) Perl (bearded) Hacker";sub s($){eval$_[0];$/}
while(s&&&&& &s(qq&sub$^&.$&.q&{\&S}&)&& &{$&}&&s&&&){$/}$\=$^;print"\b,";

Five ampersands in a row, then a space because the parser choked on ampersand six. s&&& runs a substitution using the previous regexp, so the RE field between s& and the middle & is empty and replaces the match with an empty string, the middle & and third &. If that succeeds (&&) call subroutine s: &s. I needed a space on either side of the && and operator as a hint to the parser about what's going on, and I choose to go with after to get five in a row. Then I squeeze as many extra ampersands as I can in the rest of that line. I'm pleased to say that since I wrote that, the Perl parser has improved to the point that the six ampersand in a row version now works: a fragment like (s&&&&&&s( is either a nightmare or a wonderous sight depending on your tastes.

But I digress. The dream version of sphere.c did not include the use of the number 28319377 to represent "Elijah" printed on every frame, I added that when I decided that sphere.c should become signature.c. It's obfuscated enough that the average schmoe won't be able to change it, but could perhaps remove it.

But like those other ASCII art movies, signature suffered from the speed-up of terminals. The visualization cannot be appreciated at such lightning rates. The fix to have slowcat work on STDIN was added with my signature program in mind: signature | slowcat -b 9600

My slowcat and the latest version of signature.c, now fixed to have a more circular sphere, are available at github, along with various animations (the animations from grox.net and textfiles.com).


One of the better Tetris clones for the Unix terminal enviornment is TINT, a recursive acryonym for TINT Is Not Tetris. (There is more than one Tetris clone by that name, apparently obvious joke is obvious.) Clean C code, good responsiveness, color output (curses "text UI").

I bring all that up, because a couple of years ago I had a vision for changing some of the rules of Tetris to see how the game would play. To do that, I found an open source version of the game and started hacking on it. The one I first found was the version in the BSD Games package. The resulting new game I called Eastris. It showed potential, but the game was not responsive at speed. Digging I found the original code was based on an IOCCC winner. So the original source was more about size of code than playability.

Eastris screenshot

Score: 9                   ww                   ww
Status: 11 - 0             ww                   ww
                           ww                   ww
                           ww                   ww
                           ww                   ww
                           ww                   ww
                           ww    wwww           ww
                           ww  wwww             ww
                           ww                   ww
                           ww                   ww
                           ww                   ww
                           ww                   ww
                           ww                   ww
                           ww                   ww
                           ww                   ww
                           wwww ww ww      ww   ww
                           wwwwwwwwwwwwwwwwwww  ww
                           ww  ww ww  wwwwwwww  ww
                           ww  wwwwwwwwwwwwwwwwwww
                           wwwwwwwwwwwwww  wwww ww

   j - left   k - rotate   l - right   <space> - drop   p - pause   q - quit

Then I found TINT, and it plays better and has nicer code. My derivative of that I'm calling NOTINT, for "Not TINT". Besides the "easytris" mode, I've modified it to have several other play options. But maybe a discription of what easytris is would be good now.

Standard Tetris has a blocks that fall and stack. You complete rows to clear the board area, and you strive to never run out of space at the top. Easytris has all those same features. It even has the same shapes. What it doesn't have, and what made me call it "easy," is very random piece distribution. Instead you get mostly the same peice over and over again for a while, and then it changes to a random new piece to get over and over again. The way it is supposed to be easy: you have a good idea of what's coming, next, and after that, and after that. So you can plan your moves long in advance.

In practice, most of the pieces are pretty difficult to use to clear the board when you get 25 of the next 30 pieces all the same. Only the 1x4 piece is really easy. The 2x2 square piece seems simple, but is extremely unforgiving of mistakes. The T shape and the two variants of L shape are tricky, but with care can be used to clean up a board. The two S-jog shapes can maintain an equalibrium, but cannot really clean things up. Playing easytris really sharpened my Tetris skills, even if I did get bored after a while.

One that I started to notice playing a lot of tint style Tetris is that scoring is dominated by how far you drop pieces. It's much more important than clearing lines to the score. So I started adding new play modes to notint.

First was "zen mode" where the game speed never changes (unless you ask it to) and the scoring is 100% about lines cleared. Next I added a "speed mode" that makes scoring a function of lines cleared over time, but to be honest, I'm not very satisfied with that scoring and I may rework it.

After that I added "challenge mode". This has makes levels mean something different. Each level starts with a set of blocks that you have to clear. Those blocks are all incomplete lines, some levels have random patterns and some have predetermined patterns. Some levels have traditional random pieces and some have "easytris" inspired preferred pieces. Whatever the pattern or drop ratios, once you clear all the challenge blocks away, the board resets for the next level.

Notint in easytris mode screenshot

 Your level: 6             <>                    <>            STATISTICS
 Full lines: 138           <>                    <>
Blocks togo: 50            <>      YYYYYY        <>       MMMMMM        -    30
  Score  2536              <>        YY          <>       MM
                           <>                    <>           RRRRRRRR  -    30
                           <>    YY  YY          <>
    H E L P                <>  YYYYYYYYYY        <>       WWWWWW        -    47
                           <>      YYYYBBBB    YY<>           WW
 p: Pause                  <>      YYYYBBBB  YYYY<>               GGGG  -    26
 j: Left                   <>YYYY  YYYYYYYYCCCCYY<>             GGGG
 l: Right                  <>    YYYYYYYYYYYYMM  <>       CCCC          -    18
 k: Rotate                 <>YYYYYYYY  YYYYYYMMMM<>         CCCC
 s: Draw next              <>  YYYYYYYYYYYYYYYYYY<>               BBBB  -    27
 d: Toggle lines           <>YYYYYYYYYYYY  YYYYYY<>               BBBB
 a: Advance level          <>  YYYYYYYYYYYYYYYYYY<>       YYYYYY        -   184
 q: Quit                   <>YYYY  YYYYYYYYYYYYYY<>         YY
  SPACE: Drop              <>YYYYYYYYYYYYYYYY  YY<>       ---------------------
                           <>YYYYYYYY  WWWWWWYYYY<>       Sum          :    362
   Next:                   <>YYYYYYYYYYYYYYYYYY  <>
                           <>++  ++YY++YY++YY++GG<>       Challenge    :   5
                           <><><><><><><><><><><><>       Other blocks : 110

This has been my focus of late. All of the predetermined patterns I have been able to clear in random piece drop mode, but some are really hard unless you get lucky with your drops. After a while, I started to feel those were unfair, which is why I added less-random piece distributions. The really hard ones were the tall single-spaced bars and the two (one tall, one short) checkerboard patterns. Above, I'm failing pretty hard on one of those checkerboard levels with just a single challenge row left to clear.

NOTINT source at github.

Solar Opposites (Hulu)

This is a show from Justin Roiland, famous for Rick and Morty. In some ways it's just another way for Roiland to voice his frustration with the dumb things he sees in the world. Rick, the grandfather in Rick and Morty, and Korvo, the father-figure in Solar Opposites, are both science minded characters who rail against the stupidity around them. Neither is very good at empathy, and both have trouble with social conventions.

This story is much more sitcom-esque than Rick and Morty, and feels less radical. There's a basic story line of aliens trying to fit in on Earth with different levels how much they care about fitting in and different priorities. This story doesn't have much in the way to continuity between episodes. But there is a subplot involving Yumyulack's collection of shrunken people he keeps in his ant-farm-like terrarium bedroom wall; called "The Wall" by the people inside it.

(I say "he" for Yumyulack because that's the gender the character choose to emulate on Earth. The aliens, although clearly written to have human genders, are apparently supposed to biologically genderless.)

The Wall makes direct references to Escape from New York, and has a very 1970s or early 1980s future dystopia quality to it. There is a very definite story arc to these segments, and unlike the rest of the episode, seeing them out of order would be confusing.

To me, The Wall is the best part of Solar Opposites and I was very pleased with episode seven being almost entirely Wall story, with the titular story ("Terry and Korvo Steal a Bear") told wordlessly through what can be seen out of the windows of the terrarium prison. The rest of the show for the season is rather hit-or-miss.

Five of eight levels in The Wall.

Solar Opposites at IMDB
Rick and Morty at IMDB
Escape from New York at IMDB

Succession (HBO)

This is the story of a Rupert Murdoch-type media owner and the family of his that wants to take over the business. I've watched Season One of this show, there are two seasons released so far.

Second born son, although first from second marriage, Kendall Roy starts the season in a good place in the company, but is quickly sidelined by his father, Logan Roy, who has reconsiderd the C-level appointment for Ken. Only daughter Siobhan gets engaged, with a marrige ending the season; cousin (nephew to Logan) Greg gets fired from a terrible job at the company and then uses family connections to try to get a better job. First and third born sons Connor and Roman try to find themselves, one from outside the company and one inside. Third wife to Logan, Marcia, tries to establish herself and her son (from a previous marriage) to the discomfort of Logan's children.

The general premise is that Logan is a very shrewd and hardball media businessman who has never had time for his kids yet has high expectations of them. Now, at 80, he is finding that they are neither shrewd nor good at hardball business. Except that the show follows the kids' stories more than the old man's, helping to reenforce the notion that Logan is evil. (Okay, Logan is evil, but if told from his point of view, the kids are just incompetent evil to his masterful evil.)

The kids meanwhile, want to break out and do things on their own, but question their dad's continued competance in his old age. Except Greg. He is largely an outsider to the family drama and oscillates between oblivious and shrewd, with his eye set on the much more reasonable goal of staying in a cushy job.

Logan Roy and Roman Roy are the only two actors in this series I recognize from other roles. Logan is played by Brian Cox, who I most vividly remember as ex-spy Big John from L.I.E. I can almost see Logan and Big John as the same character: forceful characters used to getting their own way and good at reading other people. Roman is played by Kieran Culkin, who I remember (although not well) from Igby Goes Down, about a rich kid dissatisfied with family. The family here is also rich, but the dissatisfaction is much different.

Eight voting board members out of full twelve.

Succession at IMDB