diff --git a/2020/carlini/README.md b/2020/carlini/README.md
index 8963a32da..94bf37cdd 100644
--- a/2020/carlini/README.md
+++ b/2020/carlini/README.md
@@ -5,6 +5,17 @@ make
```
+### Bugs and (Mis)features:
+
+The current status of this entry is:
+
+```
+STATUS: INABIAF - please **DO NOT** fix
+```
+
+For more detailed information see [2020 carlini in bugs.md](/bugs.md#2020-carlini).
+
+
## To use:
```sh
@@ -15,16 +26,22 @@ make
### Try:
```sh
-# Play with a friend, P1 and P2, squares are numbered 1..9
+./try.sh
+```
+
+Or if you actually want to play:
+
+```sh
+# Play with a friend, real or imagined, P1 and P2, squares are numbered 1..9
./prog
```
## Judges' remarks:
-This program consists of a single print statement wrapped in a while loop. You
-would not think that this would amount to much, but you would be very, very
-wrong. A clue to what is happening and how this works is encoded in the
+This program consists of a single `printf(3)` statement wrapped in a `while`
+loop. You would not think that this would amount to much, but you would be very,
+very wrong. A clue to what is happening and how this works is encoded in the
ASCII art of the program source.
@@ -51,9 +68,10 @@ Alternates between P1 and P2. Enter a digit [1-9] to move:
The game ends if:
- * A player completes three in a row; that player wins
- * All squares are taken; neither player wins
- * A player makes an illegal move; their opponent wins
+ * A player completes three in a row; that player wins.
+ * All squares are taken; neither player wins.
+ * A player makes an illegal move; their opponent wins.
+
### LIMITATIONS
@@ -69,8 +87,8 @@ the program ... is hard at work processing your move! That is! Please be
patient.
After macro expansion the format string is roughly 100K. This makes some
-compilers unhappy, and others slow. (For example, passing GCC the flags -Wall
--Wextra -pedantic will result in a warning about oversized strings.)
+compilers unhappy, and others slow. (For example, passing GCC the flags `-Wall
+-Wextra -pedantic` will result in a warning about oversized strings.)
Under some terminals the program may exit early. The following should always work:
@@ -80,7 +98,7 @@ echo "1 2 3 4 5 6 7" | ./prog
### OBFUSCATION
-The entirety of the program consists of a single iterated call to printf.
+The entirety of the program consists of a single iterated call to `printf(3)`.
```c
int main() {
@@ -88,25 +106,27 @@ int main() {
}
```
-Here, `fmt` is a single string, and `arg` is a series of arguments to printf.
+Here, `fmt` is a single string, and `arg` is a series of arguments to
+`printf(3)`.
-While its primary purpose is to serve as The One True Debugger, printf also happens
+While its primary purpose is to serve as The One True Debugger, `printf(3)` also happens
to be Turing complete. (See "Control-Flow Bending: On the Effectiveness of Control-Flow
Integrity" where we introduced this in an actual, published, academic paper. The
things you can get away with sometimes.)
We abuse this fact to implement the logic of tic-tac-toe entirely within
-this one printf call (and a call to scanf() to read user input).
+this one `printf(3)` call (and a call to `scanf(3)` to read user input).
Here's (briefly) how it works.
+
#### Preliminaries
-This program uses three printf format specifiers.
+This program uses three `printf(3)` format specifiers.
-- `%d` takes an integer argument and prints it
+- `%d` takes an integer argument and prints it.
-- `%s` takes a string argument and prints it
+- `%s` takes a string argument and prints it.
- `%n` takes a pointer and writes (!!) the number of bytes printed so far.
@@ -114,13 +134,13 @@ Okay, everyone probably knows this. Let's get a bit more advanced.
Format specifiers can take extra "arguments".
-- `"%hhn"`: store the number of bytes written mod 256 to the char pointer
+- `"%hhn"`: store the number of bytes written mod 256 to the `char` pointer.
-- `"%2$d"`: print argument 2 to printf (and not the sequentially next argument)
+- `"%2$d"`: print argument 2 to `printf(3)` (and not the sequentially next argument).
-- `"%8d"`: pad the printed integer to 8 characters
+- `"%8d"`: pad the printed integer to 8 characters.
-- `"%3$.*4$d"`: print argument 3 to printf with as many zeros as in argument 4.
+- `"%3$.*4$d"`: print argument 3 to `printf(3)` with as many zeros as in argument 4.
For example, the following expression
@@ -135,16 +155,17 @@ x = 10;
```
because it will print out `0000000005` (5 padded to size 10) and then write the
-number of bytes written to x.
+number of bytes written to `x`.
-#### Printf Oriented Programming
+
+#### `printf(3)` Oriented Programming
Alright, now we can get to the real fun.
-We perform arbitrary computation with printf treating memory as a binary
+We perform arbitrary computation with `printf(3)` treating memory as a binary
array--one bit per pair of bytes:
-- The zero bit is represented by the sequence `00 00`
+- The zero bit is represented by the sequence `00 00`.
- The one-bit is represented by the sequence `xx 00` where `xx` is any non-zero byte.
@@ -190,13 +211,14 @@ and again, because `strlen(x)` is either `1` or `0` we have
From here we can compute any binary circuit. Doing something efficient,
though, still takes work.
+
#### Tic-Tac-Toe
The game itself is represented as a board of 18 bits, 9 bits per player, along
with a turn counter that alternates between player 1 and player 2.
-To detect who has won, we implement the following logic. Let A, B, and C be
-pointers to three squares in a row to test, and D be where to save if there is a
+To detect who has won, we implement the following logic. Let `A`, `B`, and `C` be
+pointers to three squares in a row to test, and `D` be where to save if there is a
win or not.
```c
@@ -217,7 +239,7 @@ the following expression
"%1$hhn%1$s" (repeated 256 times)
```
-where argument 1 is a pointer to a temporary variable followed by a null byte.
+where argument 1 is a pointer to a temporary variable followed by a NUL byte.
This works because if the current count is 0 mod 256, then `"%1$hhn"` will write
zero to argument 1 and then "%1$s" will never emit any text. If, on the other
@@ -229,8 +251,8 @@ Checking if there has been an invalid move is achieved similarly.
In order to decide what to print out, we have to cast the "in-memory" array of
bits to Xs and Os to print out. This is actually rather straightforward. Given
-in 1$ the pointer to player 1's square, and 2$ the pointer to player 2's, and
-in 3$ the pointer to the board string, we can compute
+in `1$` the pointer to player 1's square, and `2$` the pointer to player 2's, and
+in `3$` the pointer to the board string, we can compute
```c
"%1$s" (repeated 47 times) "%2$s" (repeated 56 times) %1$32d%3$hhn"
@@ -242,21 +264,22 @@ which will, in effect, compute
*r3 = (*r1) * 47 + (*r2) * 56 + 32
```
-which will output `' '` if neither are true, `'X'` if r1 is, or `'O'` if r2 is.
+which will output `' '` if neither are true, `'X'` if `r1` is true, or `'O'` if
+`r2` is true.
#### Further Obfuscations
In order to be able to finally display the board, while still only using one
-printf statement, we finish the statement with
+`printf(3)` statement, we finish the statement with
```c
"\n\033[2J\n%26$s"
```
which is the escape sequence to clear the screen, and then prints argument 26.
-Argument 26 is a pointer to a char* in memory, that initially is undefined,
-but within the printf statement we will construct this string to look like a
+Argument 26 is a pointer to a `char*` in memory, that initially is undefined,
+but within the `printf(3)` statement we will construct this string to look like a
tic-tac-toe board.
After the board, we need to print one of the following strings:
@@ -282,10 +305,10 @@ before, we set byte four to be
The byte `'I'` and `'S'` can always be the same, and we do the same for `'E'`/`'N'`.
-We do this same on-the-fly creation of the `scanf()` format string, but for a
-different reason. We first want to run `printf()` to show the first board, and
-then alternate between runs to `scanf()` and `printf()` reading and then
-displaying moves. Importantly, we *do not* want a final scanf when the game
+We do this same on-the-fly creation of the `scanf(3)` format string, but for a
+different reason. We first want to run `printf(3)` to show the first board, and
+then alternate between runs to `scanf(3)` and `printf(3)` reading and then
+displaying moves. Importantly, we *do not* want a final `scanf(3)` when the game
ends. It should just exit.
One option would be to implement the logic as
@@ -298,7 +321,7 @@ while (*ok) {
}
```
-but this would DOUBLE the number of calls to printf we require. So instead we
+but this would DOUBLE the number of calls to `printf(3)` we require. So instead we
implement it like this
```c
@@ -308,13 +331,13 @@ while (*ok) {
}
```
-(In reality we actually pass `scanf()` as an argument to avoid the extra
+(In reality we actually pass `scanf(3)` as an argument to avoid the extra
statement, but it has the same effect.)
-Notice there is now no initial `printf()`. In order make sure the program doesn't
-block before the first `printf()`, but we initialize the `scanf()` format to the null
-string so that it returns right away without blocking. The first time the `printf()`
-call runs, it writes out `"%hhd"` to create the `scanf()` format string.
+Notice there is now no initial `printf(3)`. In order make sure the program doesn't
+block before the first `printf(3)`, we initialize the `scanf(3)` format to the NUL
+string so that it returns right away without blocking. The first time the
+`printf(3)` call runs, it writes out `"%hhd"` to create the `scanf(3)` format string.
## Copyright and CC BY-SA 4.0 License:
diff --git a/2020/carlini/try.sh b/2020/carlini/try.sh
new file mode 100755
index 000000000..3fd8b4ede
--- /dev/null
+++ b/2020/carlini/try.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+#
+# try.sh - demonstrate IOCCC winner 2020/carlini
+#
+
+# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
+# this way allows us to have the user specify a different compiler in an easy
+# way.
+if [[ -z "$CC" ]]; then
+ CC="cc"
+fi
+
+make CC="$CC" all >/dev/null || exit 1
+
+# clear screen after compilation so that only the entry is shown
+clear
+
+read -r -n 1 -p "Press any key to run: echo 1 2 3 4 5 6 7 | ./prog: "
+echo 1>&2
+echo 1 2 3 4 5 6 7 | ./prog
+echo 1>&2
+
+echo "... now go and play for real, with a friend, real or imagined." 1>&2
diff --git a/bugs.md b/bugs.md
index 4f2cc1a8b..b30bf7859 100644
--- a/bugs.md
+++ b/bugs.md
@@ -3575,6 +3575,25 @@ It will also show funny output with more than one arg. This should not be fixed
either. But can you figure out why this happens?
+## 2020 carlini
+
+### STATUS: INABIAF - please **DO NOT** fix
+### Source code: [2020/carlini/prog.c](2020/carlini/prog.c)
+### Information: [2020/carlini/README.md](2020/carlini/README.md)
+
+The author stated that bad things happen if the entered move is outside of the
+range [1..9]. We observed a crash but we also observed a tie and other things
+besides (say with the input `-1`, `-`, `-10` and others).
+
+If a player makes a move over their opponent's place they will automatically
+lose.
+
+If a player tries to play a move they already played they will forfeit their
+move.
+
+If you have audible bells enabled the program will beep at every turn.
+
+
## 2020 ferguson1
### STATUS: INABIAF - please **DO NOT** fix
diff --git a/thanks-for-help.md b/thanks-for-help.md
index 991243a56..4f878f44c 100644
--- a/thanks-for-help.md
+++ b/thanks-for-help.md
@@ -4291,6 +4291,14 @@ showing nothing at all.
Cody also added the [try.sh](/2020/burton/try.sh) script.
+## [2020/carlini](/2020/carlini/prog.c) ([README.md](/2020/carlini/README.md))
+
+[Cody](#cody) added the [try.sh](/2020/carlini/try.sh) script which although at
+first glance might not appear to have a point, it actually does, namely showing
+how you can automate play and then reminding you to actually play for real, with
+a friend, whether that's real or imagined.
+
+
## [2020/endoh2](/2020/endoh2/prog.c) ([README.md](/2020/endoh2/README.md))
[Cody](#cody) copied the files from the spoiler.zip file that was password protected with