diff --git a/2020/ferguson1/bugs.markdown b/2020/ferguson1/bugs.markdown
deleted file mode 100644
index 5ea3bf825..000000000
--- a/2020/ferguson1/bugs.markdown
+++ /dev/null
@@ -1,295 +0,0 @@
-Current bugs and things that look like bugs but are not, as of 12 September 2020.
-
-
-- [Built-in test unit for some features!](#builtin-test-unit)
-- [The snake doesn't seem to be moving](#stillsnake)
-- [getch() also accepts input from some input hardware other than keyboards](#getch)
-- [SIZE=0 is the same as SIZE=1 and other oddities](#size)
-- ['I was a few places behind my tail and I ran into it!'](#bitetail)
-- [With negative growth the snake drops from the middle of the body](#middleofsnake)
-- [It looks like the bug is in the snake](#buginsnake)
-- [On the safety of the bug placement loop](#bugplacement)
-- [Vertical snake has more space between snake char than horizontal](#verticalsnake)
-
-# Built-in test unit for some features!
-
-Fun fact: There's something of a built-in test unit for some features; much
-like some of the other features this was not intentionally designed but is
-simply a fun consequence of the features I did implement.
-
-Let's say you want to verify that the evade mode is at the right count. How
-can you verify it without modifying the code? Try:
-
- SIZE=0 SHED=1 SHEDS=1 EVADE=10 ./prog
-
-Since you start out at size 0 and you shed every movement then when you're
-size 10 (as long as you don't eat a bug of course!) the bug should evade.
-
-If you set it to `SIZE=10` there would be a difference of 10. Now every
-move you will see the size the snake is. But then...Why is it that it
-doesn't seem to move until the snake is of size 20? Because you start out at
-size 10 of course (but in fact if you observe the snake won't appear to be
-of size 20 yet).
-
-There probably are combinations that can test these types of things I just
-don't at this time remember any I might have done.
-
-
-# The snake doesn't seem to be moving
-
-One way to show this is in full is to set the initial size and growth size to a
-high value; then try each one individually. For example:
-
- SIZE=100 ./prog
-
-In this case after you make the first move the snake will keep growing and
-so the snake tail stays in the same spot until after it's the 'full size'.
-When it has reached the full size then the entire body of the snake will
-start to move too (i.e. if the tail isn't moving it is growing or else paused).
-
-In several tests I set the initial size to a high value, the max to a higher
-value still and enabled cannibalism and much of the screen was full of the snake
-before it started to move. The [cannibalism.log][] has some examples of both
-cannibalism and a long snake that didn't move for most of the game.
-
-If however you let the snake get to the full size then eat a bug there can
-be a moment of lingering where it appears the snake moves for a few places
-before it then stops moving and just grows until it's the full size.
-
-It can also appear to be not moving when the snake is extraordinarily long
-and more so when the snake has just eaten: which of course is when it would
-grow (just like when shedding). Even so sometimes it takes a moment for the
-snake tail to catch up with the body (so to speak) so that it could for a
-few moments be difficult to know if where you're going is going to be
-occupied or not.
-
-Basically if the snake head is moving you can consider the snake to be
-moving or growing and that's the important point (if you have the default
-status line you can also see the coordinates being updated to show this).
-
-
-# getch() also accepts input from some input hardware other than keyboards
-
-On my MacBook Pro the trackpad has actually triggered directions; if I were to
-swipe up and then down the snake would run into itself. I believe this has to do
-with the function call `keypad(v, 1);` which enables arrow keys.
-
-# SIZE=0 is the same as SIZE=1 and other oddities
-
-What this means is that for both you will only have the snake head. At this point
-you can safely go back on yourself even without cannibalism enabled. This is
-intentional; a snake size of 0 is pointless but why should it not be playable
-anyway?
-
-If SIZE < 0 you'll likely win straight away since it's unsigned and it'll wrap
-back to the maximum so you will win automatically (this is the same as the
-second mode the judges suggested with `SIZE=-1 ./prog`).
-
-As for the growth sizes (including shedding) if it's < 0: the snake will still
-lose its length and display will still be odd: because the snake size is
-decreased any element beyond the reduced size isn't touched so the snake
-characters will remain on the screen; only the moving snake is what matters.
-But it's likely the game will be won fairly quickly because once it's -1 in size
-it'll be at the maximum size.
-
-For example if I say `SIZE=3 GROW=-2` at two bugs the game is won.
-
-As for growing: anything > 0 it will grow that many; 0 it will not grow (which I
-show as a gameplay mode); and < 0 it will 'shrink' as I explained above. You could
-say that it's defying physics by growing and shrinking simultaneously but either
-way negative size will force a win.
-
-Here's a fun output:
-
- < <<<+
-
-That's from:
-
- SHED=1 SHEDS=-1 ./prog
-
-And right after that you would see:
-
- YOU WIN!
- X:72/156 Y:20/41 S:997/997 B:0
-
-Try this though:
-
- SHEDS=-1 SHED=25 ./prog
-
-And you'll see that you start to be the normal size but then you leave your
-head several places until you end up getting to the max size (by way of it
-being unsigned). This isn't a bug even if it might seem like one. In fact
-this is the basis of the grow/shrink mode of play that I talk about in the
-[gameplay.md][] ([gameplay.html][]) file.
-
-Here's another thing to be aware of. Let's say you do:
-
- SIZE=1 GROW=-1 ./prog
-
-How many bugs will it take before you win? In fact it's two: you would see the
-head twice: the second time once you 'shrink' down to size 0; it would then be
-that if you get another bug you will be at the 'max size':
-
- YOU WIN!
- X:81/156 Y:35/41 S:997/997 B:2
-
-# 'I was a few places behind my tail and I ran into it!'
-
-I.e. what happens if you're growing - for example after just eating a bug - and
-you're racing towards your tail? If you're behind it should be fine since you're
-going the same speed as the snake is, right? Not quite. Because you're growing
-you might end up running into your tail (depending on how much you've left to
-grow and how far away from your tail)! This happened to me once and it surprised
-me and I figured I better note it.
-
-**Remember: the tail at that point isn't moving yet; the snake is growing!**
-
-
-# With negative growth the snake drops from the middle of the body
-
-For instance it might look like this (the first line is as it happens, the
-second pointing to where it happens and the third being what's left after the
-rest of the snake has gone through). Doing `SHED=100 SHEDS=-1`:
-
- ooooooooo>ooo>
- ^
- >
-
-The ^ points to the part that's split from the snake and which will be
-there on its own after the snake passes through it. Here's an example with
-it being `SHEDS=-3`:
-
- It looks like the bug is in the snake
-
-I show a different example in the [crazy.log][] file but what defines a coordinate
-which the snake occupies? If the snake breaks apart then the only part
-of the screen the snake is occupying is the place which is actually moving: if
-the snake decreases in size by 3 then the three respective characters you can go
-through safely. But this also means that a bug can go there! So you might see
-something like:
-
- <*oooooooo
-
-This is because the snake is no longer there: in fact in this run the snake was
-quite a bit lower on the screen and 25 in length.
-
-# On the safety of the bug placement loop
-
-Ilya Kurdyukov shared concern for the loop in the bug placement routine: is it
-safe? What he refers to is that it's a potential infinite loop. But is it? I
-understand the concern and it's something I played with a lot to be sure that it
-doesn't happen. This is how it works.
-
-To explain it I will go back to the make test program `termcaps` (which is
-imperfect for the recommended terminal size but the max snake size is exactly
-how it's done in Snake and works well). The minimum terminal size I require in
-the game is 10 x 10. This includes the walls and score line.
-
-Now the default max snake size is 997 but when the terminal is too small it
-adjusts the max snake size. For 10 lines and 10 columns you would see:
-
- $ make test
- terminal supports cursor movement
- terminal supports making cursor invisible
- terminal supports bold
- terminal supports colours
-
- terminal rows 10 (7 playable)
- terminal cols 10 (8 playable)
-
- snake size: 49 (max size: 49)
- bugs: 9 (max size: 9)
-
- at least 28 columns recommended for snake size 49 (is 10)
- at least 28 columns recommended for snake size 49 (is 10)
-
- 1 problem detected (0 fatal).
- make: *** [test] Error 1
-
-First: what's the problem? It's just a warning that for the snake size of 49 the
-recommended size of columns is 28. However this is just for the score text; with
-only 10 columns it will overflow and wrap to the next line(s). But if you observe
-that 49 is the max snake size. How is this derived and why?
-
-With 10 rows and columns it's calculated as 7 * 7 (i.e. it's
-`(cols-3)*(rows-3)`. However the number of playable locations is in this case 56
-(`playable_rows * playable_columns`). I have played with this many
-times and I do not believe there should be a problem. If there is it's from a
-very poor implementation of rand() and I discuss this in
-[troubleshooting.md][] ([troubleshooting.html][]).
-
-There I also give some test outputs without the cap in place to give an idea of
-when it became a problem (or would have). In short this is known but I do not
-think it will be a problem and I have given resolutions. In any event without
-cannibal mode it's even less likely that you'll ever run into this problem.
-
-The obvious question is why didn't I put in a break? Because of the IOCCC size
-rule 2 and what would it do anyway? I guess it would win but to my mind that is
-a bug and I prefer putting in restrictions to try and make it very unlikely.
-
-# Vertical snake has more space between snake char than horizontal snake
-
-Ilya Kurdyukov also pointed out that depending on orientation of the snake there
-are different amount of spaces between the snake char 'o'. This is what he
-had to say on it:
-
-> Yes, it is the problem, space in character terminal is not isotropic
-> from a viewer (gamer) perspective so one step up look like two steps
-> right.
->
-> MATE Terminal 1.20.0, and font "Ubuntu Mono Regular 13"
->
-> But, as I said, there is no terminal problem itself, it's because
-> character tiles are not square (except for Japanese/Chinese, Japanese
-> even have so called full-width English characters in their encoding,
-> presented in UTF too).
->
-> [https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms][]
->
-> So the typical fonts are Half-width or close to it.
->
-
-
-However the function `mvaddch()` takes a `chtype` which amounts to a C char
-with additional information and so the full width Ois too big for the
-function call. He reminded me of the old DOS box chars but even if this was
-easily duplicable (and it might be and I don't remember) the logic would
-have to be changed for drawing the snake and in such a way that would change
-the source code layout too much - to say nothing else of the fact I have
-also forgotten some of what I did obfuscation wise (and the
-[spoilers][] aren't enough here!).
-
-That being said the font and font size does seem to have somewhat of an
-effect on it since his screenshots have wider gaps than mine.
-
-Once again thank you mate for bringing this to my attention and also playing
-with it and providing the resources! Much appreciated! (And although you
-suggested it is bugging me I once again here say it's not at all bugging me
-but it is very much appreciated and it means a great deal to me. Cheers.)
-
-
-[crazy.log]: crazy.log
-[gameplay.md]: gameplay.md
-[troubleshooting.md]: troubleshooting.md
-[troubleshooting.html]: troubleshooting.html
-[gameplay.html]: gameplay.html
-[cannibalism.log]: cannibalism.log
-[https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms]: https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms
-[spoilers]: spoilers.markdown
-[screenshot of halfwidth vs fullwidth]: halfwidth_vs_fullwidth.png
diff --git a/2020/ferguson1/gameplay.markdown b/2020/ferguson1/gameplay.markdown
deleted file mode 100644
index 45a68c22b..000000000
--- a/2020/ferguson1/gameplay.markdown
+++ /dev/null
@@ -1,786 +0,0 @@
-Playing the game is very simple but because there are many different modes I
-have included much more than just the input keys and a few printouts of the
-game. For normal play you probably don't even need this file at all unless it be
-for the input keys.
-
-
-1. [Testing terminal environment/capabilities](#support)
-2. [Input keys](#input)
-3. [Gameplay](#gameplay)
- * [The initial screen](#initial)
- * [Playing the game](#playing)
- * [Walls](#walls)
- * [Cannibalism](#cannibalism)
- * [Stretching (shedding)](#shedding)
- * [Winning](#winning)
- * [Quitting](#quitting)
-4. [Gameplay modes](#modes)
- * [**Photosensitive epilepsy/Stimulation overload trigger warnings**](#warning)
- * [Drawing / Practice mode](#drawing)
- * [Computer playing / Automatic mode (**Photosensitive epilepsy/Stimulation overload trigger**)](#auto)
- * [Variations](#auto-variations)
- * [Grow-Shrink (Positive/Negative Winning) mode](#grow-shrink)
- * [Hypnotic / Sleepy mode (**Photosensitive epilepsy/Stimulation overload trigger**)](#hypnotic)
- * [Stimulation / Calming mode](#stim)
- * [Other ideas](#other-ideas)
-5. [Scripts](#scripts)
- * [Colours selection](#colours)
- * [Automate the above gameplay modes](#preset)
-6. [Game variables](#variables)
- * [WAIT - Snake speed](#wait)
- * [EVADE - Bug evasion frequency](#evade)
- * [SIZE / MAXSIZE - Initial snake / max sizes](#sizes)
- * [GROW / SHEDS - Growth / Shedding sizes](#growth)
-7. [Conclusion (and inspirational words for everyone)](#conclusions)
-
-# 1. Testing terminal environment/capabilities
-
-Most people probably won't have any issue at all but for those who have any
-problems with the terminal see the [terminals.md][] file for more
-information on the terminal capabilities testing utility I include.
-
-For troubleshooting other problems see [troubleshooting.md][]
-([troubleshooting.html][]) and [bugs.md][] ([bugs.html][]).
-
-
-# 2. Input keys
-
-- Left, right, up and down **arrow keys**: Move that direction.
-
-- 'q' (and 'Q'): Quit the game.
-
-- Space (`' '`): Pause/resume the game (direction keys will also resume).
- Note that no other keys will resume the game; however if you press a key
- that `getch()` picks up on and the game is not paused then it will be as if
- you pressed the current direction key (assuming you already moved the snake).
-
-# 3. Gameplay
-
-Here I will show the initial screen as well as what a few things look like. If
-you don't feel you need this but you want to configure colours jump to [colour
-selection](#colours). You can also jump to [gameplay modes](#modes) or [game
-variables](#variables).
-
-The bug colour by default is white; the snake head colour is red and the snake
-body colour is green. The walls are cyan.
-
-
-## Gameplay: The initial screen
-
-When you load the game you will see a screen that looks something like the
-below. Note that the top line is the score/status line: the top wall is at line
-1 and the left wall is column 0. Below I use the coordinates in the X/Y order
-(ncurses is the opposite: Y/X). I will parenthesise the numbers below to refer
-to the number in the diagram:
-
- X:24/49 Y:8/16 S:5/658 B:0
- ##################################################
- # #
- # #
- # #
- # #
- # #
- # #
- # + #
- # #
- # * #
- # #
- # #
- # #
- # #
- # #
- ##################################################
-
-
-- The snake (`+`) is at (24),(8). The bug char is `*` and the wall char is
- `#`. When the snake moves the head will be an arrow facing the direction it
- is moving; the body is 'o'.
-
-- The top wall is always line (1), the left wall is always column (0), the
- bottom wall is line (16) and the right wall is column (49). If walls are
- impassable and you run into any of these the game is over (you can slither
- at the edge of the wall); else you'll come out the opposite side.
-
-- The snake size is (5): but until you start to move it's technically 1 (even
- if you set **SIZE=0** this applies). This is so that you can decide which
- direction from the centre of the screen. By default the head colour is red;
- the body is green. The snake will grow by one until it reaches the right
- size.
-
-- The maximum snake size is (997): this is the default; it can be changed but
- it will always have an upper limit depending on the terminal size.
-
-- The number of bugs eaten so far is 0.
-
-
-## Gameplay: Playing the game
-
-
- X:39/49 Y:8/16 S:5/658 B:0
- ##################################################
- # #
- # #
- # #
- # #
- # #
- # #
- # oooo> #
- # #
- # * #
- # #
- # #
- # #
- # #
- # #
- ##################################################
-
-I let the snake grow to its full size (with the head at (39),(8)) and I'm two
-places above the bug so let's go down:
-
- X:39/49 Y:9/16 S:5/658 B:0
- ##################################################
- # #
- # #
- # #
- # #
- # #
- # #
- # oooo #
- # v #
- # * #
- # #
- # #
- # #
- # #
- # #
- ##################################################
-
-
-Now you see that the snake is going down and in one move the bug will be eaten.
-Let's do that:
-
- X:36/49 Y:10/16 S:10/658 B:1
- ##################################################
- # #
- # #
- # #
- # * #
- # #
- # #
- # #
- # #
- # ^ o #
- # oooo #
- # #
- # #
- # #
- # #
- ##################################################
-
-Observe that the bug was eaten and a new bug spawned elsewhere. I went left
-three and then up one and could slither on to the bug.
-
-
-# Gameplay: Walls
-
-By default walls are passable (**WALLS=1**). Let's get to full size and go
-through the top wall:
-
-
- X:36/49 Y:15/16 S:10/658 B:1
- ##################################################
- # o #
- # o #
- # o #
- # * o #
- # o #
- # o #
- # o #
- # o #
- # o #
- # #
- # #
- # #
- # #
- # ^ #
- ##################################################
-
-There you can see I have grown to the full size and went through the top wall;
-the head is now at the opposite wall. Continuing:
-
- X:36/49 Y:11/16 S:10/658 B:1
- ##################################################
- # o #
- # o #
- # o #
- # * o #
- # o #
- # #
- # #
- # #
- # #
- # ^ #
- # o #
- # o #
- # o #
- # o #
- ##################################################
-
-I might then have turned to the left and then shortly go up to get the bug. This
-goes on until you lose, quit or win the game.
-
-
-When you specify **WALLS=0** the walls become an obstacle that end the game. It
-might look like (I set the starting size to 150 and had only just started):
-
-
- X:20/49 Y:2/16 S:150/658 B:0
- ##################################################
- # ^ #
- # o #
- # o * #
- # o #
- # o #
- # o #
- # ooooo #
- # #
- # #
- # #
- # #
- # #
- # #
- # #
- ##################################################
-
-If I continue going up I will see:
-
- OUCH!
- X:20/49 Y:1/16 S:150/658 B:0
-
-
-
-
-# Gameplay: Cannibalism
-
-By default cannibalism is disabled (**CANNIBAL=0**) so if you run into yourself it might look
-something like:
-
- X:45/49 Y:10/16 S:10/658 B:1
- ##################################################
- # #
- # #
- # #
- # * #
- # #
- # #
- # #
- # ooooo #
- # ^ o #
- # ooo #
- # #
- # #
- # #
- # #
- ##################################################
-
-If I were to do any movement but turn to the left I would run into myself. I'll
-go to the right two spaces:
-
- OW!
- X:47/49 Y:10/16 S:10/658 B:1
-
-
-But **CANNIBAL=1** can look very funny both in movement and still especially
-when you go through yourself several times when the snake is rather long. For
-example going through walls and the snake a few times:
-
- X:4/49 Y:12/16 S:165/658 B:3
- ##################################################
- #oo o ooooo o o o#
- # oooo o ooo o#
- # ooooooooooooooooooo#
- # o #
- # oooooooooo o #
- # o o o #
- # o oooo o o #
- # o o o o #
- # ooooooooooooooo #
- # o o* #
- # oo> o o #
- # o oooooooo o #
- #oooooooooooooo o oooo oooooooo#
- # o o o o o #
- ##################################################
-
-I'll go back through myself now:
-
- X:6/49 Y:14/16 S:165/658 B:3
- ##################################################
- #oo o ooooo o o o#
- # oooo o ooo o#
- # ooooooooooooooooooo#
- # o #
- # oooooooooo o #
- # o o o #
- # o oooo o o #
- # o o o o #
- # ooooooooooooooo #
- # o o* #
- # ooo o o #
- # oo oooooooo o #
- #ooooo>oooooooo o oooo oooooooo#
- # o o o o o #
- ##################################################
-
-If you note that the head is at (6),(14) I will go one more to the right and you
-will see that the arrow has moved over:
-
- X:7/49 Y:14/16 S:165/658 B:3
- ##################################################
- #oo o ooooo o o o#
- # oooo o ooo o#
- # ooooooooooooooooooo#
- # o #
- # oooooooooo o #
- # o o o #
- # o oooo o o #
- # o o o o #
- # ooooooooooooooo #
- # o o* #
- # ooo o o #
- # oo oooooooo o #
- #oooooo>ooooooo o oooo oooooooo#
- # o o o o o #
- ##################################################
-
-Try this: Get a reasonable length and then go back on yourself (if you're going
-left go right etc.) and then after some length (but before you get beyond the
-snake) turn (so that you go perpendicular) and then watch as the snake starts
-unwinding at one place and then suddenly unwinds another direction.
-
-An example of extreme cannibalism is in the [cannibalism.log][] file. It has
-more than one run the first of one has several dumps. I didn't move for a long
-time: the initial size was 1500 and I would have won before moving if I went
-after bugs right away. In the last two captures of the first invocation (the
-third and second to last dump) the bug, head and tail of the snake are at:
-
- Bug: line 87, col 47
- Head: line 88, col 62; and line 115, col 48
- Tail: line 84, col 46; and line 112, col 29
-
-The final example has the snake inside itself.
-
-# Gameplay: Shedding (stretching)
-
-This feature will make you grow by the value of **SHEDS** for every **SHED**
-movements (the counter isn't incremented when you eat a bug). Basically growing
-without eating a bug (stretching would be better name here).
-
-
-# Gameplay: Winning
-
-If you ever get to the **MAXSIZE** the game is won. You can force a win by
-setting the max size to a smaller value than the size you specify (or the
-default) or setting the size to higher than the default (or < 0 which will end
-up being > the max size though I suppose there might be some value that makes it
-less than again - I'm not going to try and figure that out however). Anyway:
-
- SIZE=-1 ./prog
- YOU WIN!
- X:24/49 Y:8/16 S:658/658 B:0
-
-Observe that the size isn't the default 997: because the screen size is too
-small for that value (see [terminals.md][]).
-
-The reason I chose 997 is that it leaves a bit of a challenge for some (maybe
-most) people but it's still winnable. Previously even I couldn't have won unless
-maybe a much bigger screen, if both cheat modes were disabled. I probably could
-win without any cheat mode enabled on my 24" monitor but I probably would need
-at least one cheat mode on my 13" laptop (I don't need both enabled).
-
-The beauty though is the game can be winnable by anyone since you can define the
-max size to win. Games are meant to be fun: who enjoys games that can never be
-won? Very few probably do and those who do enjoy them it probably are games that
-are relaxing and stimulating (which admittedly this game can be - but still I
-want it to be winnable too).
-
-Another reason I chose 997: it's prime and the judges love prime numbers.
-Actually, this is the main reason for the number: I had changed it down to 1000
-but then it occurred to me that there are prime numbers close to 1000 so why not
-choose one instead (that was less than 1000)? And so I did. Another fun fact: at
-the default starting size and growth size of 5 the number of bugs needed before
-the game is won is 199 - also a prime!
-
-
-# Gameplay: Quitting
-
-If you wish to quit you can hit 'q' (case-insensitive). For example:
-
- X:24/49 Y:8/16 S:5/658 B:0
-
-
-
-# 4. Gameplay modes
-
-Here I list a number of different modes of play. In the [bugs.md][]
-([bugs.html][]) file I even show how there's a built-in test unit for some
-modes! There are certainly other modes that could be imagined: the modes below
-happened over time and some were simply an accidental discovery or something I
-thought of by a chance; others were thought out from the beginning but were
-improved over time.
-
-The [play.sh][] script sets up some of these automatically; I describe it after
-the modes below.
-
-
-## Photosensitive epilepsy/Stimulation overload trigger warnings
-
-If you have **photosensitive epilepsy please be careful** especially with low values
-for both **WAIT** and **EVADE**. It appears that the [number of hertz (flashes)
-per second triggering seizures][] is wide but depending on the variables it
-easily can be in the range.
-
-There are different patterns and lights flashing at different speeds so please
-exercise caution. This could trigger seizures and **it might also be too much
-stimulation for some people.**
-
-**Please be careful of these if these types of things have ever affected you or if
-you have any form of epilepsy. Thank you.**
-
-## Gameplay mode: Drawing / Practice mode
-
-If you want to draw the snake wherever you like on the screen you can do this by
-modifying the wait time (for input) to -1 (or any value < 0): then the snake
-does not move until you press a movement key. For example:
-
- WAIT=-1 ./prog
-
-
-When you eat a bug the snake will grow and you can draw more. If you want to
-make it so you can go through yourself:
-
- WAIT=-1 CANNIBAL=1 ./prog
-
-If you don't want to start out so small (i.e. you want to be able to draw more
-quickly) you can just set the size to a bigger number (and you could do the same
-with growth and moult/shed):
-
- SIZE=50 CANNIBAL=1 WAIT=-1 ./prog
-
-Do note that although you're a bigger size you still grow one movement at a
-time.
-
-Okay but then if you get too many bugs the drawing will be over. If this proves
-to be a problem simply do:
-
- SIZE=100 CANNIBAL=1 WAIT=-1 GROW=0 ./prog
-
-Or something like that (maybe make the size bigger but that's up to you). You
-could also set the max size to be the highest possible by saying
-
- MAXSIZE=-1
-
-Which I've done in the [play.sh][] script.
-
-I discuss how this mode works in [spoilers.markdown][].
-
-Here's an example run where I spelt 'SNAKE'. As you can see it's far from
-perfect: the snake after all does not leave gaps and the game does not support
-diagonal movement and I also made a mistake and had to modify what I was aiming
-for. But you can consider this mode drawing or practice mode.
-
- oooooooooo ooooo o oo ooooo
- o o oo o oo o ooo o
- oooo o oo ooooooo oooo ooooo
- o o ooo oo o ooo o
- oooo o oo ooo oooooooo>
-
-
-## Gameplay mode: Computer playing / Automatic mode (Photosensitive epilepsy/Stimulation overload trigger)
-
-**Photosensitive epilepsy/stimulation overload trigger warning:**
-For those who have epilepsy or are susceptible to stimulation overload from
-flashing lights please do be careful with this mode. Depending on your
-susceptibility this could very well trigger seizures or other discomforts and I
-wouldn't want that to happen to anyone. This mode has a lot of flashing of
-different colours and depending on the exact parameters you specify it could
-easily be in the trigger range for epilepsy but potentially stimulation overload
-too.
-
-If you're still here you can create this effect like:
-
- WAIT=0 WALLS=1 CANNIBAL=1 ./prog
-
-As long as the bug evades you'll find that the snake is growing because it's
-actually eating bugs; the computer is actually playing the game by itself! You
-can still move the snake though it won't seem like you have much control over
-it. If you pause the game you can see that it's bigger (you probably will be
-able to even without pausing it).
-
-Basically the snake is moving so fast that because the bug evades the bug will
-inevitably move in the snake path's and therefore be eaten.
-
-You might find it goes quicker if you set the evade count to a lower value for
-example 1. Or you might not. But as long as the bug moves the computer can play
-by itself.
-
-Quick tests suggest that bigger dimensions it gets bigger quicker. But it also
-seems to take longer for it to get a bug as it gets longer. I believe these
-happen because the bug has to find a X and Y coordinate that's not occupied and
-so with fewer available it has a harder time finding a place in that one line.
-
-### Computer player variations
-
-Here's how to make the bug move every time the snake moves:
-
- CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 ./prog
-
-
-#### Help the computer win fairly quickly
-
-If you want to see the game 'win' try something like:
-
- CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 MAXSIZE=10 ./prog
-
-
-#### Negative growth (Shrink) Automatic mode
-
-Here's a fun one I just thought of (a long time after these other modes were
-thought of):
-
- WAIT=0 EVADE=1 GROW=-1 SIZE=9 MAXSIZE=10 CANNIBAL=1 ./prog
-
-What you'll see is that first the snake will get to the size of 9 - whether it
-shows to be 10 characters depends on whether or not it gets a bug before it can
-get to that length - and then it'll start shrinking until it's just the head
-then the head again (i.e. 1 then 0 in size) and then win! This is also in the
-[play.sh][] script.
-
-
-#### Adjusting the time/speed
-
-Of course you can also do something like:
-
- WAIT=5 WALLS=1 CANNIBAL=1 ./prog
-
-Which although might not seem like it is significantly slower.
-
-#### Moving the snake about to create patterns
-
-If you press different direction keys in some pattern you will see a pattern
-form too (entirely dependent on how fast you react, what keys you press and I
-suppose also how much the bug moves and the chance of being eaten also).
-
-#### Other ideas
-
-Here's an idea: how many moves is needed to make it possible to have some sort
-of success in catching bugs? Obviously the dimensions will affect this value.
-
-How long will it take for the snake to run into itself? For instance by doing:
-
- WAIT=0 ./prog
-
-On my 13" MacBook Pro at the default settings going horizontally the snake ran
-into itself at:
-
- OW!
- X:57/156 Y:20/41 S:155/997 B:30
-
-What if you set the size to a high value? The lowest? There are bound to be
-other games to play with this feature!
-
-## Gameplay mode: Grow-Shrink mode (Positive and Negative Winning)
-
-In this mode you're simultaneously growing and shrinking but because the max
-size is unsigned you can win both by shrinking to the point of losing your body
-or growing to the full size directly. This is how it works:
-
-You have a negative shedding growth and a positive growth size: negative and
-positive winning. Depending on the parameters specified it might go one way over
-the other. Try:
-
- SIZE=150 SHEDS=-5 GROW=10 SHED=50 MAXSIZE=250 ./prog
-
-What this does is set the size to 150 (to make it not go down so quickly) and
-then for each bug you eat it adds 5 to the size; for every 50 moves (that you
-don't get the bug) you shrink by 5. You will find that at times you might only
-decrease in size but then at other times - depending on size of screen and how
-lucky you are with where the bug is relative to where it last was - you might be
-growing. Combining this with the drawing mode could be interesting but I never
-actually tried it.
-
-The parameters above were chosen after playing with the mode a bit to find a
-value that wouldn't take that much time but still would pose a challenge. One
-could reverse it so that one shrinks more than growing.
-
-The [crazy.log][] file has several screen dumps with this idea.
-
-You could also have it so that eating a bug makes you shrink and moving so many
-moves you grow. I tried this and for me it was far more fun. The [play.sh][]
-also has this mode:
-
- SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog
-
-Obviously there are many other variations. The [play.sh][] script has some
-of them (the above is option 5; others are 4, 15 and 16 but only options 4 and 5
-are called Grow / Shrink).
-
-
-## Hypnotic / Sleepy mode (**Photosensitive epilepsy/Stimulation overload trigger**)
-
-**Photosensitive epilepsy/stimulation overload trigger warning:**
-For those who have epilepsy or are susceptible to stimulation overload from
-flashing lights and patterns please do be careful with this mode. Depending on your
-susceptibility this could very well trigger seizures or other discomforts and I
-wouldn't want that to happen to anyone. The default wait time is 231ms, the
-typical range of seizures is 3 to 30 flashes per seconds (but can be higher) and
-that means that at **EVADE=1** every 231ms there will be a flash in addition to the
-snake moving too.
-
-Anyway this might sound absurd but it can be somewhat hypnotic by doing:
-
- EVADE=1 CANNIBAL=1 ./prog
-
-And just moving the snake about not trying to catch any bugs - just let whatever
-happens happen.
-
-
-## Gameplay mode: Stimulation / Calming mode
-
-If you just need something to stimulate your mind to keep you calm or simply you
-want to play a game without having to worry about winning or losing you can set
-the growth size to 0 and then just move the snake round and round eating bugs
-until you want to quit. You can enable cannibalism so that you don't have to
-worry about even running into yourself and losing:
-
- GROW=0 CANNIBAL=1 ./prog
-
-
-## Gameplay mode: Expansibility
-
-As I was writing this document and the game modes I have thought of other game
-modes (they were added) and I have come back to this document to add more modes.
-That's the beauty of the variables I have implemented: together with the
-imagination and even just chance different modes of play can be devised. The
-drawing mode was a happy chance of how the `timeout()` function works for
-example.
-
-As a person who was heavily involved in MUD development and design I know very
-well how games need to be fun and have different options, not be too easy but
-not be too hard either. And a game developer who does not play their games is a
-game developer who is detached from their player base and the wants and needs
-are therefore disregarded if even heard. I have played this game a lot for this
-reason as well as I simply enjoy it and thinking up new modes.
-
-
-# 5. Scripts
-
-The following scripts are provided to simplify and automate some of the things
-this file discusses as well as allowing to easily change the colours.
-
-## Colours selection: snake-colours
-
-To do this use the [snake-colours][] script like so:
-
- ./snake-colours
-
-If you want to pass in specific variables you can do that too e.g.:
-
- CANNIBAL=1 ./snake-colours
-
-The script will prompt you for the colour of the walls, snake head, body and the
-bug.
-
-## Automate the above gameplay modes
-
-The [play.sh][] script has the gameplay modes described in this file and is menu
-based (there might be differences and some of the modes I include a variation).
-The script tests the terminal (allowing you to continue even if problems are
-detected), prompts you if you want to select colours (like those in
-snake-colours above) and then gives you a list of game modes to play. You can
-pass in the game variables but note that if you pass in a variable that the mode
-you choose uses then the script will override what you pass in.
-
-To use you can do something like:
-
- ./play.sh
-
-Or to make it so walls are an obstacle:
-
- WALLS=0 ./play.sh
-
-
-# 6. Game variables
-
-The game variables can be used for a variety of things including different
-gameplay modes as above but here are some notes about a few of them.
-
-## WAIT: Snake speed
-
-Besides the different game modes if you find it too fast/slow you can change it
-to a value that's better for you. Remember it's a wait time so if you want the
-snake to move slower you have to increase the wait time!
-
-
-## EVADE: Bug evasion frequency
-
-For every **EVADE** snake movements the bug will try and find a new place to
-occupy. It might be very close to it and I do not ensure it's a new place at
-all.
-
-Each time the bug is placed the counter will be reset whether from eating the
-bug or not reaching it in time. Default 300 moves.
-
-This can help you get out of a trap but it can also sometimes make it harder.
-
-
-## SIZE / MAXSIZE: Initial / Max snake sizes
-
-997 might be a bit high for many people. Or maybe you don't have enough time. Or
-you're not in the mood to lose. Or you want to get close to a size you were last
-time but quickly. It might be in conjunction with drawing mode.
-
-Note on snake size: there's a stated size (in the score line) which is what
-the snake will 'populate' in the snake arrays and the visible size: as I have
-discussed here and there the snake doesn't grow immediately so it takes time
-before the snake is visibly that many characters. In other words just because it
-says SIZE 29 doesn't mean it will instantly be 29 characters on the screen.
-
-
-## GROW / SHEDS : Growth / Shedding sizes
-
-Similar to the initial size. Notice that the above point on size applies here:
-it will take the number of movements before it is 'its full size'.
-
-
-
-# 7. Conclusion (and inspirational words for everyone)
-
-I believe that this file has given more than enough information for anyone to
-get an idea of what is possible with my implementation of Snake. I realise also
-that most people won't have read this far and that's quite all right; I'm very
-thorough and pay attention to details obsessively. Creating this game was a
-delight and I am quite proud of what I have done.
-
-Thank you for whatever level of attention you felt you could or wanted to give
-and enjoy it in whatever way you see fit!
-
-**Much more importantly is that Snake aside I hope I have demonstrated how with
-the imagination and creativity almost anything is possible.** This is something
-**that applies in our world in every way and *everyone* can do something amazing if
-they believe in themselves!** I would have never thought this the case for me
-years ago but I know it's true now. **Believe in yourself. Always.**
-
-[terminals.md]: terminals.md
-[terminals.html]: terminals.html
-[troubleshooting.md]: troubleshooting.md
-[troubleshooting.html]: troubleshooting.html
-[bugs.md]: bugs.md
-[bugs.html]: bugs.html
-[spoilers.markdown]: spoilers.markdown
-[snake-colours]: snake-colours
-[number of hertz (flashes) per second triggering seizures]: https://www.epilepsysociety.org.uk/photosensitive-epilepsy#.Xjgpwi2ZOgQ
-[termcaps.c]: termcaps.c
-[cannibalism.log]: cannibalism.log
-[crazy.log]: crazy.log
-[play.sh]: play.sh
diff --git a/2020/ferguson1/spoilers.markdown b/2020/ferguson1/spoilers.markdown
deleted file mode 100644
index d67420a74..000000000
--- a/2020/ferguson1/spoilers.markdown
+++ /dev/null
@@ -1,933 +0,0 @@
-# Introduction (SPOILER ALERT)
-
-In the [gameplay.md][] ([gameplay.html][]) file I have given enough
-information to know how the game looks, how to move the snake, how to pause etc.
-In this file I am including (some) information on how the game actually works:
-the technical details as it were, obfuscation techniques and also some of the
-ways I reduced the iocccsize so I could do more with the code. Probably this
-file causes more spoilage than the other files though that's not to say
-everything will be answered here.
-
-If you're still interested in this file (i.e. you're a judge or someone who
-wants to know more about it) read on. Yes I write a lot. But you probably
-already knew that so no harm there, hey?
-
-
-- [How does it work?](#works)
-- [How does the snake movement work?](#movement)
-- [Drawing (manual) and computer playing (automatic) modes](#manual-automatic)
-- [Collision detection](#collision)
- * [Cannibal collision detection](#cannibalcollision)
- * [Collision detection when resizing the window of the game](#resizing)
-- [Obfuscation](#obfuscation)
-- [Skinning the snake (i.e. decreasing the iocccsize)](#skinning)
-- [A few more interesting size optimisations](#size)
-
-# How does it work?
-
-The gameplay I have already described but this explains the way things are
-actually done in more detail.
-
-First I initialise curses; if this fails I print an error message ('curses
-error') and return 1. Next the screen size is determined and I subtract 1 from
-each the x/y. If it's too small curses is ended and an error message ('screen
-too small') is printed - returning 1.
-
-Next the max size of the snake is determined: if `MAXSIZE` is specified then
-it's the value of that; otherwise it's the default. But in either case if it's
-too big based on the screen dimensions it's capsized. The arrays for the snake
-are this size + 1. Other environmental variables are also processed.
-
-Then the arrays are allocated; if either return NULL curses is ended, an error
-message ('memory error') is printed and return 1.
-
-If no errors have occurred I set up colours, turn on bold, set up the keypad
-etc., place the snake, the bug, draw the walls and then it waits for the first
-move (or quit of course). Technically I don't 'wait' for input as such: unless
-the wait time is negative (drawing mode) it's just a non-blocking call up to the
-WAIT milliseconds but in no event will the snake move until it is told to at
-least once (in drawing mode it will always wait).
-
-In drawing mode if you pause then when you resume (hit space) the snake will
-move the last direction it had been told to move - because the direction is set
-and input was detected (the same goes for another key e.g. 'g' - just like in
-normal mode). But it will then wait again for input.
-
-The snake function both draws the snake and updates the arrays; if the new size
-is >= the max size the game is won (the winning size will be shown as the max).
-
-Else the arrays are updated; when the array is being updated the body of the
-snake is drawn. After this the head is drawn. Depending on the length of the
-snake wrt the size the snake technically it might be that the number of
-characters the snake takes is increased rather than having moved the snake
-forward (i.e. the tail moved by one). This registers where the snake is and
-where it was but no longer is (important particularly for negative growth/shed
-sizes).
-
-After that a bug is placed (but not drawn) in a pseudo-randomly selected area of
-the field. This function takes a parameter which if not 0 and the bug had
-already been placed somewhere (in other words if the bug was just eaten) call
-the snake function. As long as the game isn't won at that point find a new place
-to place the bug.
-
-Next the score line is updated and then whilst the game is not over (player
-loses/quits/wins) the movement proceeds; if the game hasn't started yet it will
-jump to the top of the loop. If it's paused the same thing until it's resumed.
-The rest of the loop can be described thusly.
-
-It checks the current max y/x, draws the walls, bug, gets any input from
-keyboard, and then if there is movement checks for collisions; if current max
-x/y are is/are smaller than original then it's automatically a game over from
-running into walls regardless of that feature status - this simplifies things
-greatly (see below for more details).
-
-If cannibal mode is disabled (the default) and the snake runs into itself then
-it's also game over. Or did it run into the wall? If walls are passable (the
-default) it will come out from the other side; else it's game over. If it comes
-out on the other side and the snake is there and cannibal mode is disabled then
-it's also game over.
-
-As the snake moves it will for each move grow by one up to the technical size.
-This might at times look a bit different from other times but it's a visual
-thing based on the internal data of the game and the features enabled for
-example shedding and shedding size.
-
-Finally if the snake's new coordinates are on a bug a new bug is placed on the
-field, the snake grows and the score is updated. Otherwise if the bug has waited
-the number of moves that it waits before it finds a new place the bug is placed
-in another location too (and the snake does not grow). In either event the snake
-location is updated and redrawn.
-
-There's also the processing of any shedding at this point. If the snake eats a
-bug the snake will not shed; if it sheds the snake will not move in the same
-manner as if it simply moved. Growth/movement can in some ways be conflated.
-
-
-# How does the snake movement work?
-
-The way the snake looks to move is that every time the snake moves the last
-position (the tail) is replaced with a space (`' '`). If the snake eats a bug
-then the snake will get bigger in the next `N` movements. Note that if the snake
-isn't its full size it will only be growing and so might not appear to be
-moving at the tail end; I have discussed this more than enough elsewhere.
-
-There are two arrays that store the last Y/X coordinates of the snake's
-positions that are shifted forward as the snake moves about the field looking
-for bugs.
-
-
-# Drawing (manual) and computer playing (automatic) modes
-
-How do these modes work? The `timeout()` function takes a signed int: if it's <
-0 it waits indefinitely; if it's 0 it returns immediately even if there's no
-input waiting (if input is there then it's used instead); and if it's > 0 it
-waits that many milliseconds. Thus a negative value allows for complete control
-over the snake's movement (speed and otherwise), a value of 0 means the snake
-will move as long as it's not paused etc. and otherwise it waits up to that many
-milliseconds (which is how the 0 value comes into play).
-
-
-# Collision detection
-
-This was an interesting thing to work out. Because the snake could occupy more
-than one row and more than one column at a time the two arrays approach seemed
-good to me.
-
-I already mentioned how the array is shifted but to be clear: the snake head is
-always at element size - 1 and the tail is at 0 and so it's just a matter of
-verifying if the snake head is at a place that's occupied by the snake, the wall
-or the bug.
-
-The bug does its best to avoid landing where the snake is but given that snakes
-are very flexible and cunning who can tell what might happen? As I noted these
-bugs are not bugs! :)
-
-
-## Cannibal collision detection
-
-How does cannibalism change collision detection? The fact that each time the
-snake function is called there is a space printed at the tail end was a problem
-to resolve: what happened is if the snake went through itself then at some point
-there would be a space that breaks the snake into more than one piece (where the
-tail was but that had been another part of the snake)!
-
-So what I do: first the tail is cleared, then as the snake coordinates arrays is
-being updated I redraw the snake chars. Then at the end the head is drawn (it
-used to be the head was drawn first but by drawing it after you can see where
-the head is inside itself, creepy as it is). Thinking on it this very possibly
-is why (or partly) the negative shedding leaves the head somewhere in the middle
-of the snake (or that the head of the snake is left behind) but again I don't
-think that as a problem.
-
-There are other strange ways this looks. Not only does it look like lines
-intersecting at any number of places but it looks particularly strange when the
-snake goes the opposite direction: it has to unwind as it were, and for a moment
-you might not see what is truly happening. There are two ways you can look at
-this I think.
-
-First is that it's physically impossible in real life so the fact this cheat
-mode exists for a different kind of play means it should look unnatural: for it
-*is* unnatural!
-
-The second is you can look at it as if two more snakes are having fun with each
-other. This can also appear to defy physics!
-
-Choose your poison. Or rather your venom.
-
-
-## Collision detection when resizing the window of the game
-
-What happens if the window is resized during the game? If the size is increased
-then the border can (and will) stay the same; but if the window is shrunk then
-what? It would be very difficult if not impossible to redraw the snake: where
-would the snake be and what about the border? The arrays would have to be
-adjusted too! Another issue: what if the snake is beyond the new walls?
-
-The best thing I could think of is that if the window is shrunk then the snake
-is assumed to run into the wall: in other words the game is at that point over.
-If the window is increased in size nothing happens other than the game won't be
-the full window size (or technically a few rows/columns fewer): everything will
-remain the same. This GREATLY simplified things.
-
-There was another problem at some point where the snake would quickly grow if it
-was increased in size but I believe that's resolved. Anyway what kind of field
-in real life increases in size like that so suddenly? :)
-
-
-# Obfuscation
-
-
-- I make use of the C token pasting operator. Although this is well known it's
-probably less known and either way it's not as simple as just having the code
-that it translates to. For example why have:
-
- attroff(COLOR_PAIR(L));
-
- When you can have instead:
-
- attroff(m(PAIR(L)));
-
- It's an extra layer of indirection. This used to be more used but when
- making it easier for users to change the colour pairs I no longer used it to
- set up colour pairs. It might not defeat `cpp` but it does make for more
- reading otherwise (depending on how you look at it maybe less?).
-
- It also helps save iocccsize bytes (but not as many as it used to!).
-
-
-- What is this block of code?
-
- F(MAXSIZE)g d g = f((a)((*y-2)*(y[-2]-2)),g);
- F(GROW)N d
- F(SIZE)A d
- F(WAIT)y[-3] = (int) strtol(z,NULL,0));
- F(EVADE)W d
- /* and so on */
-
- There are several things going on here but I'll focus on the main one here and
- leave the others to their own: the `F` macro and the associated `d` macro are
- here important.
-
- In addition to saving many bytes this also makes for interesting reading.
- What this actually is doing is checking for environmental variables. If
- `getenv()` does not return NULL then strtoul() is called on it (except for
- the one that clearly shows strtol()).
-
- There are other things going on (below).
-
- Now it might not defeat the cpp but can you tell me what this is even with the
- cpp?
-
- f((a)((*y-2)*(y[-2]-2)),g);
-
- The cpp might get it closer to what you might expect in a normal program but I
- refer to the array offsets (below also).
-
-- Stringification: there isn't a single `"` in the source code! The `F` macro
-uses the macro `Z` which does the real work. At first `F` was only `getenv` but
-I changed it to use stringification. Following the creation of the `Z` macro I
-made it use it instead. If I remember rightly that uses extra bytes but somehow
-it felt better this way in my head. Then to save many bytes I made the macro do
-much more than that (that is the `F` macro).
-
- As for the Z() macro it means that I could remove `"`s; for example:
-
- #define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n), Y, y[-2], X,*y,A,g, c);
-
- Which as I have discussed elsewhere is the entire set of parameters to both
-`mvprintw()` and `printf()` plus the end of the function call (i.e. `);`.
-
- BTW: There's another really cool benefit of stringification: because more than
-one space is converted to a single space I can have it spread across columns on
-the format and even new lines if necessary. This fact along with the next
-technique causes some beautifiers problems too.
-
-- Another use of the `Z` macro is this curious line:
-
- static char s[]=Z(; +<>^v);
-
- There are a number of curious parts. First is the Z() part makes it look
- like a function call. Of course that wouldn't work as such because an array
- initialiser needs an initialiser list or a string literal. Whether that's
- immediately obvious to others I don't know but then how is this even possible?
- A `;` followed by ` `, `+`, `<`, `>`, `^`, `v`?
-
- A very minor factor is that the character 'v' is there and it's (`v`) also
- used as a macro (well, define) 'might' be of something to some people. Or
- programs maybe? For instance using in vim `*` on the `v` in that array and
- it takes you other instances of `v`: as in `\`: which happens to be
- something else entirely. That itself however might or might not be
- significant for this instance!
-
- But what function would take the string (...function and string?) that it takes?
- The sequence of characters would normally cause compiler errors like that.
- I have it in the function that uses it; static since it need never change:
- only one copy is needed. Why I have it in the function is to move it further
- away from the definition of `Z()`. I will also be returning to this one
- again.
-
- Another example is using the `E()` function e.g.:
-
- E(Z(YOU WIN!));
-
- Which happens to be in the same function the above char array is defined. Also
-it's more like a string than anything but yet it's not visibly a string.
-
- Some beautifiers don't like this.
-
-- There's an `#undef` following an `if` in a way to draw attention from what to
-do if the if is true.
-
-- There are a couple case statements that fall through to the next case
-condition. Actually one falls twice: into the one below which falls into the one
-below that. This means the order it is in is required. It also reduces the
-iocccsize a reasonable amount (by having it in the main loop I could do these
-things which reduced the number of keywords needed).
-
- When quit is requested it falls into pause. But then pause falls into the
- default (so no recognised key is pressed) which does `x = 0;`. Outside the
- switch block there's `if (x) P = 0;`. So what this amounts to is: if quit
- is requested pause will be changed to the opposite state. This will then
- fall to setting x to 0. And because x is 0 the state of pause won't be
- updated again. Now because `Q = 1;` (or actually `l`) it doesn't matter if
- `P || !P` because Q will also jump to the top of the 'loop' only to exit
- since the condition no longer is true.
-
- But then if pause is pressed the same thing applies: it will be updated to
- the opposite state and then it will fall to the default case which sets `x =
- 0;` which means it won't update pause outside the switch block. If pause was
- enabled then the loop will start over only this time because quit wasn't
- requested it will re-enter the loop.
-
- So basically quit can both pause and resume but it doesn't matter because it
- will still quit; and pause will fall to the default statement without being
- updated again either. In other words the only time pause will be updated
- (disabled) *outside the switch* is if a direction key is pressed. But of
- course it's disabled inside the switch if pause key is pressed when it's
- already paused! This removed three break statements because the order allows
- it; if the order was changed then the code would break in another way and
- not the good kind!
-
-
-- On the note of pausing there's at least one instance of removing `if..else`
-(besides those in e.g. environmental variable processing) that's curious: I
-converted this:
-
- if (!P) P = 1;
- else P = 0;
-
- To this:
-
- (!P && (P = 1))||(P=0);
-
-
-- Makes use of the different 'namespaces' to have variables and labels be the
-same identifier. For example in main() there's a variable that also have the
-same name label for `goto` (there used to be two pairs in main()).
-
-- And on that note: makes use of the ugly `goto` in numerous places. This
-includes simulating a while() loop, breaking out of that 'loop', breaking out of
-two loops (a for() in the 'while()'), re-entering (as in starting over) a for()
-loop and for dealing with errors.
-
-- Why do I check for `Q || P` and then goto x only to then check for `!Q && !D`
-to then goto x? Do I need to check Q at all? In fact I do but at a quick glance
-it might be easy to miss.
-
-- Uses an unnamed array (compound literal) for several different game variables.
-The pointer to the first element is defined like `int *j`:
-
- static int Y,X,*j = (int[8]){231,0}, *U, *V, *e, *n, Q, P,x,*y,l=4,*D;
-
- Does the 231 seem familiar? It should: it's the default key delay for the
- `timeout()` call (which I will return to again). The rest are 0 default. But
- what about `j`? Is it even used? Actually in main:
-
- y = j+3;
-
- But aside from that `j` is not used. However...
-
-- Major abuse of negative pointer offsets along with confusing names. I'll say
-this in two parts: the negative offsets and then the confusing names.
-
- Can you honestly tell me that this is easy to follow?
-
- if (Y < 1 || Y >= y[-2] || X < 2 || X >= *y || y[-2] >= y[-1] || *y >= 1[y])
- {
- if (*p && !(*y>=1[y]||y[-2]>=y[-1]))
- {
- if (Y<1||Y>=y[-2])
- Y = Y<1?y[-2]-1:1;
- if (X<2||X>=*y)
- X = X<2?*y-1:2;
- }
- /* ... */
- }
-
- That's not the only place negative offsets occur! Observe the ternary operators
- there too.
-
- I'll go back to the F() macro and in particular what follows one of them:
-
- g d g = f((a)((*y-2)*(y[-2]-2)),g);
-
- To parse that at the very least you have to know that `y` points to `j + 3`.
- Then you have to know that `j` points to the first element of an unnamed
- array (compound literal). But then you also have to know that that array has
- different types of data. Once you figure out the elements in question you
- then have to account for the offset that `y` is. Then once you have that
- figured out you need to consider the negative offsets to `y` (this also
- applies to the block above of course and maybe more so). Then you have to
- think of operator precedence etc. I mean what is:
-
- (*y-2) * (y[-2]-2])
-
- ...about? An offset of -2 and subtract -2 from that. Multiply that by the `*y`
- (which is `j[3]`) - 2.
-
- But why is there a `g d g =` when the other lines only have the variable (or
- location) and a d? (Excepting the one that doesn't refer to `d`.)
-
-- On the confusing names etc.: the `getmaxyx()` function gets the maximum Y, X
-dimensions. Now in the first call in main() I have the code and tests following:
-
- getmaxyx(v, *y, y[-2]);
- --*y; --y[-2];
- if (y[-2] < 9 || *y < 9)
- return E(Z(term too small));
-
- Clearly the max x must be stored in `*y` and the max y must be stored in ..
- `y[-2]`. After all anyone knows that the coordinates are in the order (X,Y)!
- In fact the output of my entry and my documentation demonstrates this
- clearly: X before Y! It's so true in fact that the documentation for curses
- more than once states that it's actually (Y,X)! But the fact I don't even
- refer to a `x` is possibly confusing even without the negative offset.
-
- Of course I don't have to use negative offsets at all! I could use positive
- offsets for every time I use negative offsets. But where's the fun in that?
- :)
-
- BTW: Some of these are not in the table of expressions in the HACKING file.
- Also there might be some code in there that is no longer correct (it was
- before I started obfuscation) though it might be able to give an idea.
- Spoilers abound in that file (in addition to this file) but the HACKING file
- states things that are no longer true: a way of obfuscation itself! Instead
- of misleading comments it's misleading statements in the file that explains
- what some of the things are for!
-
-- Misleading variable names for coordinates. In other words the Y coordinate is
-called X and the X coordinate is called Y. This adds to the already confusing
-array references but it also adds to the confusion of the order of the curses
-functions coordinates: it appears that yes X does come first because the
-function calls that take coordinates suggest it - but in actuality it's just
-that the names are deliberately swapped. Of course that's after you determine
-that the variables `X` and `Y` are only the snake head but at that point you
-still have to figure out the array confusions. Also if you're tired `V` could
-easily be read as `Y` and I have a lot of fun with `V` which I will get to next
-(and again). Finally why not have them be two different names unrelated to
-coordinates? I thought of this and I think it's more confusing to have something
-that is associated to what it is but incorrectly rather than something unrelated
-entirely: the mind constructs things from what it has seen, what it experiences,
-what it knows, and since X and Y are used for coordinates the natural response
-of the brain is to assume Y is what is really X and X is what is really Y.
-
-
-- More confusion with variable names: If you notice the `int *U, *V` they are
-also part of the compound literal: that is they point into it:
-
- U=y+2; V=U+1;
-
- Except that these two are done in two different places: away from the
- assignment of `y` to remove them further away from the contexts they are
- used in.
-
- There's another reason for moving it further down: if you look at the bug
- drawing function (which comes before main()) you will see that there I set
- the bug location to refer to the `y` 'array'. I do blank out the old
- location at `*U, *V` but then assign the new location differently. Then in
- main() I draw it at `*U, *V` and also check for the bug being eaten there
- too.
-
-
-- There's another array that holds a variety of data.
-
- static k p[5]={1,0},W=300;
-
- It holds the following information (but not necessarily in this order):
-
- WALLS
- CANNIBAL
- SHED
- SHEDS
- EVADE
-
- But how will you know that just looking at the declaration? Many variables
- and they're part of collections but the many layers of indirection cause
- confusion to the already unhelpful variable names (for those that even have
- names!).
-
-
-- There's an array of pointers to functions too: it holds three functions but
-rather than always use the array I only do some of the times. I even use the
-same function in the same general area with both names in order to mislead.
-Incidentally `splint` seems to have a parse error on the declaration though I
-don't know why.
-
-
-- On arrays/pointers in general I also use e.g. `3[p]` and `p[3]` (there are
-many other examples that I have already shown).
-
-- Expanding on referring to the same thing in more than one way take a look at:
-
- case KEY_LEFT:
- V[1] = l-3;
- break;
- case KEY_RIGHT:
- V[l/l] = l/2;
- break;
- case KEY_UP:
- V[l-3] = l-1;
- break;
- case KEY_DOWN:
- V[l/4] = l;
- break;
-
- What's going on there? First of all the letter ell looks very much like the
- digit one but above there are only two references to the digit `1`; the
- others are the letter `l`. If you're tired though, don't have the best
- vision (I'm speaking from experience here and that's not even considering
- the font) it would be easy to miss. Online in a text editor you have syntax
- highlighting of course but there's more to it than that. Also in other parts
- of the code there are references to the digit 1 instead of the letter ell as
- part of array indexes too (so which is it?).
-
- Second is that the index referenced in each of the case statements evaluate
- to the same: 1. That's all accomplished by taking advantage of the value of
- `l`: 4.
-
- And then to further make use I have done the same for the value to assign to
- that element: 4 - 3 is 1, 4 / 2 is 2, 4 - 1 is 3 and 4 is obviously 4.
-
- But doing it this way means you have to first of all know that there's the
- variable `l` (conveniently declared at the top of the file); then you have
- to determine (once you're at this place in the code) if it's the digit or
- the letter - for each reference (since both exist)! After all it's entirely
- possible that I could have negative offsets here (and there's nothing that
- would prevent negating a variable either in this case): I have done it many
- other places! But even after all of that you still need to do the
- calculations when I could simply have had:
-
- V[1] = 1; V[1] = 2; ...
-
- Etc.
-
-- Variable reuse. For example in the function E() there's a variable that keeps
-track of whether or not it's been called; that variable is `h` and it says
-whether to call `endwin()` or not in as in some cases E() is called more than
-once. Now instead of setting the variable `h` to 1 I set it to `l`: it looks
-like a 1 yes but it's actually 4. Does it matter that it's 4? No. The only
-thing that matters is that it's a non-zero value. The same applies to `Q` which
-I also set to `l`.
-
-* I also use `*y` as a boolean. If you observe that I set x to `*y` (which
-itself might make one believe they're related in some form): it used to be just
-a 1. However it is only used as a boolean. `*y` as I described as the LINES
-variable on invocation of the program. Since I check if it's < 10 before
-continuing the game I know that it will always be non-zero. But what if someone
-tries LINES=0? In fact it will be ignored: if the terminal is 25 lines and you
-specify 0 lines then it'll be 25. Therefore I can use it as a boolean here since
-it needs there to be non-zero. Then in order to get the opposite, 0, I can do
-`!*y` which I do elsewhere.
-
-- More generally on variable reuse: the compound literals and arrays of the same
-data type but which are completely different things means I can use the same
-name in different parts and so it's then a matter of determining which
-element/offset to use.
-
-- Why do I compare if the original dimensions are >= the current when the idea
-is to make sure that they're actually bigger? How does that work? Why not just
-check if it's > than the current?
-
-- More confusion with the max x/y dimensions: Going back to max x/y dimensions
-and coordinates of the snake; I showed this code before:
-
- if (Y < 1 || Y >= y[-2] || X < 2 || X >= *y || y[-2] >= y[-1] || *y >= 1[y])
- {
- if (*p && !(*y>=1[y]||y[-2]>=y[-1]))
- {
- if (Y<1||Y>=y[-2])
- Y = Y<1?y[-2]-1:1;
- if (X<2||X>=*y)
- X = X<2?*y-1:2;
- }
- else
- {
- /* ... */
- }
- }
-
- I asked if you could honestly figure that out easily. But here's a bit more
- elaboration. I already talked about the negative offsets - and they should
- talk enough themselves - but look at the mess. Even if they weren't negative
- offsets there are a lot of array references (though by a pointer to an
- element in the unnamed array) and comparisons all jumbled together. There's
- more.
-
- I have the `!` of a `||` to flip the logic: that's not how a normal person
- would write code. Well...not usually, I guess; I have done it in times where
- it seems more appropriate but it's not the way it's usually done (I think?).
-
- Even so that part is doing more than one thing: Not only is that code making
- sure the max dimensions aren't smaller (from the original) but it also makes
- sure that the wall isn't hit (when it's not allowed) as well as making the
- snake go through to the other side of the wall if the snake is allowed to
- and hits the wall! And even when the snake is allowed to go through walls if
- the screen size has shrunk it will reach the else part.
-
- It also has the ternary operator to adjust the coordinates of the snake head
- should the snake go through a wall and those also have negative offsets. But
- how can you figure that out just looking at that mess? Unhelpfully the X/Y
- seem to both be compared to `y` but never `x` (that variable is unrelated
- and not even in this part of the code).
-
-
-- The function `B()` ends with a `goto`. Why? It's also another place where
-there's at least one negative offset.
-
-- A note on the many `#define`s in my entry. You say you dislike them:
-
- Doing masses of #defines to obscure the source has become 'old'. We
- tend to 'see thru' masses of #defines due to our pre-processor tests
- that we apply. Simply abusing #defines or -Dfoo=bar won't go as far
- as a program that is more well rounded in confusion.
-
- As I have noted though many of these save quite a lot of bytes too. It's
- true that they might aid (but barely) in obfuscation but I think that my
- entry is more rounded in confusion; certainly the other techniques I have
- mentioned include much more than just `#define`s. One of the `#define`s that
- saves a significant number of bytes is of course `J`: I use that twice and
- it would be a huge burden to include it twice!
-
- At the same time I have removed some `#define`s that have added bytes; I've
- also removed some that saved bytes and in fact I think it makes it more
- obscure if in no other way but making it more difficult to look at (for
- example I might have been able to save bytes by defining for the array
- offsets but I find that it looks much better - which is to say much worse -
- the way I have it now).
-
-- Going back to the curious `static char s[]=Z(; +<>^v);`: there's something
-magical about the number 7 isn't there? I do not refer to primes although
-certainly one could say that primes have a magic to them. No. I'm instead
-referring to another property: bitwise AND. For example consider the following:
-
- 7 & 0
- 7 & 1
- 7 & 2
- 7 & 3
- 7 & 4
- 7 & 5
- 7 & 6
- 7 & 7
-
- What is the result of each operation? Quite simply it's the number itself!
- How does this relate to the `s` array though? Let me back up. Is there any
- place in the code that has the number 7 (by itself - 997 doesn't count)? A
- quick check will answer that: no. But here's a curious thing:
-
- q X, Y, s[*D+2&(1<<3)-!Q]);
-
- We KNOW that at this place `Q` is 0 so the `!Q` has to be 1. Now `1 << 3` is 8. Therefore
-
- (1 << 3) - !Q == 7
-
- But what's `*D`? If the snake hasn't moved once yet it's 0; otherwise it's the number
- of the direction the snake is currently facing. Thus
-
- *D&(1<<3)-!Q
-
- ...refers to `*D`. However if I were to have that be the element it wouldn't
- work right: I wanted the semicolon in there but the space was needed to
- reduce the iocccsize down by one (ironic that adding a byte reduces it by
- one but there it is). I could have had it later in the array but this felt
- slightly more confusing: more operators (so precedence) to consider (and in
- fact GCC complains about this but as is clearly demonstrated it's not
- important). By adding a `+2` it adjusts the index to be the correct value in
- order to show the proper index of the char array.
-
- But how do you know this? You have to know first of all that Q will always
- be 0 at this point (so therefore !Q == 1). You also have to understand that
- in the range N = 0..7 the value of `N & 7` is `N` (which might not be
- something everyone realises). Obviously you need to know that (1 << 3) is 8
- in order to get the final `*D & 7`.
-
- You furthermore need to know that `*D` will always be in the range `0..4`
- which means that `*D & 7` will always be in the range `0..4` (If I were to
- have added a `& 7` to the end it'd still be the correct value! But the use
- of bytes couldn't be justified there.) Finally adding 2 will get the correct
- value of the array index. After all that it will print the correct character
- for the head!
-
- But there's another trick here: there's never a direct assignment to `*D`:
- `D` is set to `1 + V` and `*D` is never touched directly: it's all through
- `1[V]`. The references to directions i.e. `KEY_LEFT` etc. and also the
- switch() to see how to modify X/Y are all done through the `V` pointer. But
- then what is `V` anyway? It's `U + 1`; and `U` happens to be `y + 2`. But
- `y` happens to be `j + 3`. Of course `j` is a pointer to the first element
- of the compound literal! So there are quite a lot of levels of indirection
- in this part alone (not to mention other places)!
-
-
-# Obfuscation in prog.3.c and prog.3-j.c
-
-There are a few differences in this version that are worth noting. First of all
-is a define that's in the compiler invocation Makefile is in the source file
-itself. Second are the following obfuscation techniques. To simplify integrating
-the explanations I have simply yanked and pasted them below:
-
-- Variable reuse in ways that might not be so intuitive. For example in the
-function E() there's a variable that keeps track of whether or not it's been
-called; that variable is `h` and it says whether to call `endwin()` or not as in
-some cases E() is called more than once. Now instead of setting the variable `h`
-to 1 I set it to `*y`. Now as you can see `*y` starts as a NULL pointer; this is
-set to the compound literal `j` + 3. This in turn is what LINES is (number of
-lines). So `y = j + 3;` and `j` I discuss elsewhere. But what if LINES is set to
-0? LINES being set to 0 sets it to the terminal max size but in any event I test
-for values < 10 and if either LINES or COLUMNS is < 10 then E() is called.
-However E() always returns 1 and since this is in main() and it's an error I
-simply return E() and thus it's only called once. Similarly for `Q` I set it to
-`l`. But then..what is `l`?
-
-- In fact `l` is assigned a value 4 via a compound literal. It's declared at the
-top of the code and then in main() assigned like: `l = ++(int) { 3 } ;` which
-equates to 4. I think that's pretty cool!
-
-- What is this? `for(I=0; A&&I 0 so `A-A` is 0; however because `A`
-is non-zero the expression `A-A||A` is equivalent to `0 || A` and since A is
-non-zero we know that the value is `1` and thus it's `A - 1`! I quite like this
-technique: it doesn't make sense at first glance and it probably remains elusive
-until you look at it more thoroughly. It compares that `I < A - 1` but the `1`
-is calculated by subtracting from `A` the value of subtracting `A` from itself
-`|| A` and `A` is always non-zero (as the condition says) which means it's
-`A - 1`!
-
-There might be more things that differ but those are the significant ones.
-
-
-
-Of course none of the above is so easy to see without a beautifier. Why did I
-choose the format I did? Well it came about in a sequence of possible layouts. I
-tried first to make it look like the game might itself but the trouble with that
-is it's too random. Then I thought maybe I could spell out the words SNAKE 2020
-or IOCCC 2020 or something like that. But these were proving to be a problem for
-me; what I was seeing on the screen just wasn't looking right in my head.
-
-At that point I just started playing with different patterns and I quite like
-what it's turned out to be. I don't know what I would call it but one could look
-at it and think of columns holding up a structure. There's also a symmetry to it
-and almost certainly that's what is most attractive about it to me for I love
-symmetry.
-
-Some final notes on the layout I'd like to point out. First there are 53 lines
-counting blank lines. Second is that if you count the number of lines (of code)
-in each 'block' they should all be a prime (except the two blocks of 1, I
-guess). Third is that I tried to make sure that each column of the code (not
-counting the preprocessor - see below on that) start and stop at the same
-position (as in column in the row/column kind) on each row. Below I show the
-start and end column of each horizontal block. The `#undef` in the middle should
-be centred based on its length and the 120 columns for total. The preprocessor
-directives should also be centred in that way (that was my goal anyway).
-
-The following were intentional:
-
-* 53 lines.
-
-* The number of lines per vertical block (3, 5, 3, 11, 7, 1, 1, 5, 7).
-
-* Number of horizontal blocks (5)
-
-* Number of vertical blocks (9)
-
-* iocccsize 2053.
-
-The symmetry was even more important to my mind; observe that each vertical
-block (or column) starts and ends on the same column (or at least that was my
-goal; I think I did it but maybe I missed one here and/or there):
-
-* Vertical column #1: 5, 22
-* Vertical column #2: 25, 41
-* Vertical column #3: 49, 64
-* Vertical column #4: 73, 90
-* Vertical column #5: 97, 120
-
-Furthermore based on the length of each C preprocessor directive (the
-`#define`s, the `#includes`, the `#undef`) I have attempted to centre them in
-the file based on the 120 columns total. I believe I have succeeded in that
-though again maybe I have an off by one or two here and/or there.
-
-Most of the primes above were intentional.
-
-# Skinning the snake (i.e. decreasing the iocccsize)
-
-This happened in a number of ways and I have already documented some in other
-parts. Now there are a number of reasons to do this: amongst them to make it
-possible to obfuscate (plus a more unique layout) but also to add more features.
-
-Interestingly some of the obfuscation saved bytes; others of course added bytes.
-For example token pasting saved a few bytes; on the other hand the combining
-`if`s to the complicated one above added 9 bytes: but another one saved a byte.
-I have done this more than once so it's entirely possible there are others I am
-forgetting.
-
-Obviously a more significant one is `#define q mvprintw`: this saved a total of
-47 bytes! This was however done towards the end (or so I thought it was the end;
-it was anything but) when I started looking at obfuscation rather than adding
-features. But then because of this I looked at adding more features!
-
-Another thing that reduced a lot of bytes - 34 to be exact - is using the
-`mvvline()` and `mvhline()` ncurses functions rather than use three for loops to
-draw the walls.
-
-Much later on I made it so that the E() function returns 1; this was a clever
-way to have what I already did have - return 1 if there's an error (i.e. memory
-error or curses error or screen too small) but otherwise return 0 without having
-to have a separate int and I could get rid of two `{}` pairs as well as add
-another use for the E() function: it calls endwin() exactly once (even though
-when there isn't an error condition it can be called more than once) as well as
-printing the final score - or else an error. And now it also allows for printing
-an error and returning from main() at the same time! This also means that by
-returning E() I am returning 1 but if the end of main() is reached 0 is
-returned. In either case curses is ended.
-
-One of these optimisations saved four bytes simply by taking advantage of the
-value of a loop iterator after the loop. The loop is:
-
- for (I = 0; A && I < A - 1; ++I)
-
-However after the loop I had this:
-
- A > 1 && q(n[A - 1],e[A - 1], 'o');
-
-When I was considering moving that line to before the loop it occurred to me
-that as long as `A > 0` then `A - 1 == I` after the loop. I still had to check
-for `A > 1` but I could refer to just `I` instead of `A - 1`!
-
-There were quite a few other things besides these and these gains were useful to
-add additional features and also to add proper error reporting (when `calloc()`
-failed I called `abort()` and before that if initialising ncurses failed I also
-called `abort()` and did not report any errors in either event but I do now).
-
-# A few more interesting size optimisations
-
-As I was getting to the end of obfuscation (wrt size available - and it was
-getting pretty obfuscated too - the majority of the techniques were already in
-place at this point) I was looking at the code to see if I could figure out how
-to save even more bytes. Here are some that I found interesting ways to go about
-the problem.
-
-First, the function that turns on colours looked like:
-
- if (h) attron(m(PAIR(L)));
- else attroff(m(PAIR(L)));
-
-But I thought is that else actually needed? If I were to switch the order so
-that the `attroff()` is called first then I could just do an `if (h)` -
-therefore getting rid of the `else`! But then I thought why not do what I've
-done elsewhere? I had:
-
- attroff(m(PAIR(L)));
- if (h) attron(m(PAIR(L)));
-
-But I then saved an extra byte by making it:
-
- attroff(m(PAIR(L)));
- h && attron(m(PAIR(L)));
-
-That saved two bytes.
-
-Second let's look at the B() function: there were two things I thought of that
-would save some bytes (I no longer know how many but a few at least possibly six
-or even more). I had the following code:
-
- if (V && U && o) { S(N); b(1); }
-
-This made sure that only if the snake has caught a bug should it grow by the
-growth size and increase the bug count. But was checking for the `V` or `U`
-necessary? I gave it a look over and it occurred to me: the only time B() is
-called with `1` (thus `o` is 1 so the if is true) was if the bug actually is
-caught. That means I could remove the `V && U &&` part of the if! Thus it became
-instead:
-
- if (o) { S(N); b(1); }
-
-
-Then this
-
- !o && V && U && q U,V,' ');
-
-...is to make sure to only clear the spot the bug is (or was) at if
-the bug was NOT eaten. Why not eaten? Because if it was eaten it means the
-snake's head will be there!
-
-But why did I check for the bug having coordinates? Because I thought that if
-the bug has coordinates obviously the function has been called before which
-means that we do clear (write a space) over a place the bug was actually at. But
-I thought could there maybe be another way of verifying if the game has started
-yet?
-
-Before I ask that question I'll point out this: is there a reason it has to be
-checked? Yes because right after this line new coordinates are found. But
-unfortunately the snake has to be placed first since the bug cannot be placed
-where the snake already is. So if I had to make sure the game had started (the
-snake has moved at least once) what could I check? In fact that means the
-direction is not 0! So I could just replace it with:
-
- !o && D && q *U,*V,' ');
-
-That reduced the count further. But then I wondered if even that much is needed.
-The condition is that the bug has evaded which means the snake has moved already
-(so game started). What calls to this function happen before the game starts
-though? The original placement of the bug. Well if the above check makes sure
-that the bug isn't where the snake is at it means that the snake has already
-been placed, right? Going further the snake always starts out at the centre (or
-rather the close as possible - rounding maybe an issue depending on the max
-y/x): in other words not at 0, 0. This means that the only thing I should have
-to check for is that `!o`: because after this call before the game even starts
-the score line is updated: so the empty space will be overwritten anyway. And if
-the score line is made an empty string it doesn't matter because it'll appear as
-all spaces anyway. Thus I could save another three bytes by changing it to:
-
- !o && q *U,*V,' ');
-
-Technically it would be a `" "` (see [HACKING][] file) else for N (not referring to
-the variable though it might very well matter here too) movements (i.e. due to
-sizes) you will at times (e.g. after eating a bug) see the snake body char at
-0,0. I'm not bothered about that though because the score line is meant to
-display something, it squeezes a few more bytes and having a space is hardly an
-imposition on usage (and for that matter having a 'o' at 0,0 isn't either).
-
-
-[gameplay.md]: gameplay.md
-[gameplay.html]: gameplay.html
-[COMPILING]: COMPILING
-[HACKING]: HACKING
diff --git a/2020/ferguson1/terminals.markdown b/2020/ferguson1/terminals.markdown
deleted file mode 100644
index 22553075d..000000000
--- a/2020/ferguson1/terminals.markdown
+++ /dev/null
@@ -1,340 +0,0 @@
-# Terminals
-
-Terminals are very easy to mess up and for that reason they deserve their own
-file. I discuss terminal capabilities, dimensions (setting and how to restore
-sanity if it causes any problems) as well as colours (limitations etc.).
-
-
-
-- [Capabilities support testing program](#termcaps)
-- [Setting the game dimensions](#dimensions)
- * [The LINES and COLUMNS environmental variables](#linescolumns)
- * [Terminal insanity](#insanity)
- * [Restoring the terminal](#restore)
- * [Terminal size abuse](#abuse)
-- [Terminal limitations](#termlimitations)
-- [Terminal colours](#colours)
- * [Curses background](#background)
- * [Monochrome terminals](#monochrome)
- * [Colour limitations](#colourlimitations)
- * [Disabling colour](#disablecolour)
-
-# Capabilities support testing program
-
-Although it should be playable without the features I use (except that cursor
-movement is required) I have provided a source file that can test your terminal
-for the capabilities I use in the entry.
-
-It also tries to determine the minimum number of columns to play without the
-status line overflowing - even with the dynamic length. Try:
-
- $ make test
-
-This compiles the program and runs it; you should see something like:
-
- terminal supports cursor movement
- terminal supports making cursor invisible
- terminal supports bold
- terminal supports colours
-
- terminal rows 42 (39 playable)
- terminal cols 157 (155 playable)
-
- snake size: 997 (max size: 6006)
- bugs: 199 (max size: 1201)
-
- at least 34 columns recommended for snake size 997 (is 157)
- at least 37 columns recommended for snake size 6006 (is 157)
-
- No problems detected.
-
-If I pass in any of the variables **GROW**, **MAXSIZE**, **SIZE** and/or
-**LINES** or **COLUMNS** it bases its calculations on those variables. For
-example:
-
- $ MAXSIZE=-1 GROW=1 make test
- terminal supports cursor movement
- terminal supports making cursor invisible
- terminal supports bold
- terminal supports colours
-
- terminal rows 42 (39 playable)
- terminal cols 157 (155 playable)
-
- snake size: 6006 (max size: 6006)
- bugs: 6001 (max size: 6001)
-
- at least 37 columns recommended for snake size 6006 (is 157)
- at least 37 columns recommended for snake size 6006 (is 157)
-
- No problems detected.
-
-
-As you can see it tells you the max size (the 'capsized' snake) as well as
-the requested max size (if the requested size is bigger than the capsize then it
-will be set to that value instead) of the snake. The capped size is like in the
-Snake game itself but the suggested minimum number of columns is based on a
-number of variables.
-
-If I were to do the above but set columns to less < 35 then there would be a
-problem. But why if the utility recommends at least 37? This is because the
-max size of the snake also depends on the terminal size. This utility is not
-perfect: I don't consider shedding; I set growth to 5 if it's 0 (since it would
-be indeterminate how many bugs are possible before 'winning' since there would
-be no 'winning'); and there are probably other things too.
-
-As for capabilities: besides cursor movement the others are just nice to have.
-From my tests keeping the cursor visible doesn't ruin gameplay but it is less
-distracting if nothing else to have it invisible (in fact due to the sequence of
-function calls the cursor would mostly appear to be not in the game field itself -
-from memory at least).
-
-Maybe there are other capabilities I should check for that I'm unaware of but
-this should give you an idea.
-
-If there are any problems it will say how many (fatal and otherwise). The fatal
-problems are if curses fails to initialise or if movement of cursor cannot be
-done (both seem odd).
-
-Both scripts run this utility and prompt if there are any problems;
-you can continue either way.
-
-# Setting the game dimensions
-
-There are a number of ways to do this and only one will keep the terminal sane
-all the time but that's by running it under a terminal emulator that you can
-resize the window with first. But what if you want exacts?
-
-
-## The LINES and COLUMNS environmental variables
-
-To specify the lines/columns of curses program per instance use the `LINES` and
-`COLUMNS` environmental variables.
-
-For demonstration consider the following:
-
- $ echo $LINES $COLUMNS
- 42 157
-
-Note: I subtract 1 from the max y/x and the max coords in the game output
-include the walls and score line but these values are for the terminal itself.
-
-Say you want 55 columns:
-
- $ COLUMNS=55 ./prog
-
-This will force curses to detect the max columns (X) of your terminal (for the
-game dimensions) - to be 55; it might look like this instead:
-
- X:27/54 Y:20/41 S:5/997 B:0
-
-But problems can arise with messing with dimensions: in my tests this held only
-to lines.
-
-## Terminal insanity
-
-Terminal sanity can be compromised and it can cause all sorts of output
-problems; it might not appear right away but it will show its ugly head
-eventually if you use it. For example pager output might be screwy, echo might
-be turned off, output of commands might overwrite the input of those commands,
-etc. For the game you might not see the final score.
-
-
-### Restoring the terminal
-
-In my tests there is one thing that at least allows you to see the final score
-and that is by running `clear` before running the program. That's what the
-prog.alt version does. You might run it as one of:
-
- LINES=20 ./prog.alt
- LINES=20 ./snake.alt
-
-
-Even if the final score is visible though the terminal may very well still be
-messed up. There are numerous things you might try but probably the easiest is
-to run the game again without modifying the dimensions (and then just quit) or
-even just the `reset` command.
-
-
-The Linux man page says:
-
- You might have to run the `reset` tool like:
-
- reset
-
- (the line-feed character is normally control-J) to get the terminal
- to work, as carriage-return may no longer work in the abnormal state.
-
-
-If you don't have the reset utility you can try:
-
- echo -e \\033c
-
-Otherwise try `clear; stty sane` (that will turn on echo also) or if all else
-fails log out and back in.
-
-For more information on this subject generally see the [Linux keyboard and
-console HOWTO][] (specifically [Linux keyboard and console HOWTO section 4][]).
-Yes this works under macOS (at least it did for me).
-
-### Terminal size abuse
-
-So players 1, 2 and 3 are content with not meddling with the terminal sizes
-outside what's actually possible with their screen. But then player 4 comes
-along and thinks he/she will be clever and mess with the dimensions a bit. Let's
-say they have a 13" monitor and they think it'd be funny to see how 997 lines
-would work; they might try something like:
-
- LINES=997 ./prog
-
-What then? Well expect trouble; curses will not know any better and the max
-number of lines will be 997. If they were to do:
-
- COLUMNS=997 ./prog
-
-Then they will see a different effect. Again the same reason: the player trying
-to be funny.
-
-The game will try and be funny in return and you can expect it to not function
-properly. Because that's what funny means in this context.
-
-
-# Terminal limitations
-
-It'd be nice if curses could detect hitting more than one arrow key at the
-same time so that diagonal directions would be possible but unfortunately it's
-not (`cat -v` confirms this). Even if I were to define four extra keys what
-would they be? And what about the head character? The HACKING file has
-information on this.
-
-I also limit the terminal size to 10 lines/columns but most likely it would
-require the cheat modes to win and in any event allowing certain low values
-causes problems e.g. **LINES=6 COLUMNS=6** and **LINES=3 COLUMNS=3** caused some
-nasty issues.
-
-
-# Terminal colours
-
-N.B.: If all you're after is wanting to change the colours see the script
-[snake-colours.sh][] instead. The rest of this file was mostly notes for the
-judges; here I discuss the background, foreground as well as limitations (in
-particular runtime limitations).
-
-## Curses background
-
-The documentation I have seen says that the background will always be black and
-from a quick test this holds even with a terminal that has a white background.
-There is a way to force the background to remain white though that's by way of
-monochrome (so no colours); I discuss that and another related terminal specific
-in the troubleshooting guide (there's another way but it would take me over the
-iocccsize; I talk about it in the HACKING file).
-
-## Monochrome terminals
-
-
-According to my tests for monochrome terminals the screen has the white and
-black background; if terminal is configured to be black background white
-foreground that is the order it is too. You can try that like:
-
- TERM=linux-m ./prog
-
-But I do not specifically check if the terminal has colours. Is there a curses
-implementation that has a problem here? Below I explain what to comment out
-should you need colours to be disabled but I personally have not run into any
-problems even with monochrome terminals. Later I say what to do to remove colour
-support in the source code itself.
-
-## Colour limitations
-
-According to X/Open Curses, Issue 7 (pg. 57):
-
- With init_pair() and pair_content(), the value of pair must be in a range
- from 0 to and including COLOR_PAIRS-1. (There may be an
- implementation-specific upper limit on the valid value of pair, but any such
- limit is at least 63.) Valid values for f and b are the range from 0 to and
- including COLORS-1.
-
-The manpage for `init_pair()` says this:
-
- These limits apply to color values and color pairs. Values outside these limits are not legal, and may result in a runtime error:
-
- [...]
-
- COLOR_PAIRS corresponds to the terminal database's max_pairs capability, (see terminfo(5)).
-
-Based on the two as well as the fact that monochrome terminals (I've tried under
-both Linux and macOS) seem to work fine I believe I am fine here too. And to
-confirm this I wrote the following code with the output below:
-
- #include
-
- int main()
- {
- initscr();
- start_color();
- printw("COLORS: %d\nCOLOR_PAIRS: %d\n", COLORS, COLOR_PAIRS);
- getch();
- endwin();
- }
-
- TERM=linux-m ./colour_pairs
- COLORS: 0
- COLOR_PAIRS: 0
-
-Without specifying the TERM I get:
-
- COLORS: 256
- COLOR_PAIRS: 32767
-
-In the case that colour is supported the standard states that there will be more
-possible colour pairs than I have used so that's not a problem either. Perhaps
-even it would only be a runtime error if the colours are supported and the
-number is out of the range? To try and figure this out I did another test:
-
- int main()
- {
- initscr();
- start_color();
-
- init_pair(COLOR_PAIRS+1, COLOR_WHITE, COLOR_GREEN);
- bkgd(COLOR_PAIR(COLOR_PAIRS+1));
- init_pair(1, COLOR_WHITE, COLOR_BLACK);
- attron(COLOR_PAIR(1));
- printw("COLORS: %d\nCOLOR_PAIRS: %d\n", COLORS, COLOR_PAIRS);
-
- getch();
- endwin();
- }
-
-Running it like
-
- TERM=linux-m ./colour_pairs
-
-I got the output as if colours weren't used: 0 and 0. With coloured terminals
-however it was not visible. If I however comment out the call to `bkgd()` I get
-instead:
-
- COLORS: 256
- COLOR_PAIRS: 32767
-
-Which leads me to believe that if you try using a value outside the range it
-won't work for a colour-capable terminal but it doesn't matter for monochrome
-terminals one way or another. And since I don't go beyond the ranges (as I cited
-earlier) there shouldn't be any problem here.
-
-## Disabling colour
-
-Nevertheless if it is a problem and you don't want to use a monochrome terminal
-(or can't):
-
-First comment out the code that has `start_color();` and then add `return;` to the
-top of the `C()` function (the rest of the code won't be reached). If necessary
-you can also comment out the `init_pair()` calls.
-
-Perhaps you only need to add the `return;` to `C()`. My guess is that's the case
-but I do not know for certain.
-
-
-[Linux keyboard and console HOWTO]: https://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO.html
-[Linux keyboard and console HOWTO section 4]: https://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-4.html
-[snake-colours.sh]: snake-colours.sh
diff --git a/2020/ferguson1/troubleshooting.markdown b/2020/ferguson1/troubleshooting.markdown
deleted file mode 100644
index ebabcdc7d..000000000
--- a/2020/ferguson1/troubleshooting.markdown
+++ /dev/null
@@ -1,423 +0,0 @@
-# Troubleshooting Snake
-
-In this file I have a list of a number of possible problems that could show up
-under some situations as well as some things that might appear to be happening
-or be a problem but actually are not. For each one I have included a summary, a
-more thorough description and any resolutions (from easiest to hardest). For
-anything that can cause more than one issue I will list those separately to keep
-it as structured as possible/easiest to find.
-
-
-- [The top wall isn't (all/some of the time) visible!](#topwall)
-- [The snake isn't moving!](#notmoving)
-- [I can't see the snake head (or other part of the snake)!](#invisiblehead)
-- [I can't see the bug!](#invisiblebug)
-- [The game froze!](#froze)
-- [The game gets slower as the snake gets bigger!](#bigsnake)
-- [I set SIZE=0 GROW=1, ate a bug but still only the head was visible! Why?](#headonly)
-- [I like black text on a white background but even with a white background terminal it ends up black!](#monochrome)
-- [The text is hard to see (not bright enough)!](#toodark)
-- [Can I move the snake faster temporarily without having to modify the wait time?](#movefaster)
-- [On environmental variables more generally and string to int conversions](#envvars)
-- [Errors and error reporting](#errors)
-
-## The top wall isn't (all/some of the time) visible!
-
-Because the score line is dynamic in length depending on the terminal size it
-can happen that the score/status wraps to the next line(s). This can be fixed by
-modifying the status line (see [HACKING][]) but you shouldn't need it to be very
-wide.
-
-* RESOLUTION #0: Use a bigger screen (it doesn't take that many columns)
-
- **Tip:** try running `make test` to get an estimate of the minimum number of columns
- needed. This won't work right if you change the score line!
-
- Note that this utility is not perfect; I describe this elsewhere. Either way a
- small screen will make it harder to play esp without the cheat modes enabled
- (but they can still be fun with large screens).
-
-
-* RESOLUTION #1: Open the [prog.c][] and change the line
-
- #define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n),Y,y[-2],X, *y, A, g, c );
-
- To be something like:
-
- #define J Z(B:%zu\n), c);
-
- Recompile and try again. That will then show only the number of bugs eaten. See
- the HACKING file for other data you can include (though there are some
- discrepancies here and there as you'll see).
-
-
-## The snake isn't moving!
-
-Unless the game is paused this should not be happening. It can appear sometimes
-that there isn't movement and sometimes it might have to take a moment to
-'unwind' but as long as the head is moving then everything is fine.
-
-The tail might not always be moving which could make it seem like the snake
-isn't moving but as long as the head is moving then the snake can be assumed to
-be moving.
-
-
-* RESOLUTION #0: Unless the game is paused as long as the snake head is moving
-everything is fine even if it seems sometimes that the snake tail is still: this
-is normal and there are a few conditions that this might especially show itself
-e.g. when the snake is growing.
-
- If you want to see this in action try:
-
- SIZE=150 SHEDS=10 SHED=1 ./prog
-
- Once you start moving you'll see that the tail stays still for a while and
- when it does move you'll see it doesn't move for long.
-
- Sometimes also it might appear that the movement is delayed but there are
- numerous causes for this some of which are a busy computer but ultimately
- it'll catch up; just give it the time it needs.
-
-* BOTTOM LINE: If you want more information then see the [bugs.md][] file.
-
-
-## I can't see the snake head (or other part of the snake)!
-
-Possibly this could happen with too long a score line which I already discussed.
-It also used to be possible during cannibal mode whilst cannibalising: you would
-just have to continue moving on and you'd eventually find your head (assuming
-the rest of the screen isn't covered with your body!). And what else could you
-expect if you decided to shove your head up your .... ? :))
-
-* RESOLUTION #0: Actually I thought it would look better that you could see the
-head even when cannibalising so you should be able to lose your head and at the
-same time see it!
-
-* RESOLUTION #1: If the terminal width is too small then it could be that the
-score line is covering the wall, snake and even bug; I gave two resolutions to
-that earlier in this file. To get a recommended number of columns use `make
-test`.
-
-
-## I can't see the bug!
-
-This has happened to me a number of times and early in development there were
-times that I could swear I even saw it beyond the walls but this should not be a
-problem now if it ever was.
-
-However I have made a lot of effort to think of situations that might make the
-bug location calculation and placement be a problem and even did some debug
-output and wrote another test program to calculate the maximum number of places
-the bug could be put etc.
-
-One of the reasons I have the terminal dimensions have a minimum and also a
-maximum has to do with the way the bug placement and max size of the snake (and
-so arrays) are calculated: it could happen that because of it being unsigned
-without there being restrictions it could end up being a bad value that causes
-the bug placement loop to never end (in this case the snake would also stop
-moving).
-
-* RESOLUTION #0: If evasion mode is enabled (default after 300 moves) just wait
-it out and the bug will move to a new place and it might be easier to see in the
-new place.
-
-* RESOLUTION #1: The terminal size is too small for the score line. See the
-earlier problem for how to resolve this if that's the case.
-
-* RESOLUTION #2: Sometimes you have to look closely for it can be easy to miss.
-If it's against the wall and the screen is [Snakey][] or you're tired or the colour
-contrast isn't right for you or something like that it might be harder to see.
-Try pausing the game (space) and scan the screen for it. If you really are
-desperate copy and paste the entire file into a document and search for the bug
-char (if it's an editor like vi/vim you will have to be sure to escape the char
-since `*` is a regexp metacharacter). This has happened to me numerous times.
-
-* RESOLUTION #3: If the colour contrast is not good for your eyes use the
-[snake-colours][] script to select a different colour scheme.
-
-
-## The game froze!
-
-This should not be possible either but without certain safety checks in place I
-have caused this (and I did this deliberately in development to find all the
-conditions I could to resolve them).
-
-* RESOLUTION #0: If this does happen it likely is to do with placement of the
-bug; that is why I have the max size of the snake capped a fair bit below the
-maximum number of coordinates in the game field: because the bug isn't to be at
-a place the snake already occupies.
-
-* RESOLUTION #1: If the system `rand()` implementation is really bad maybe it's
-having a problem finding a location to place the bug. The best I can think of is
-to try increasing the screen size or decrease the max size of the snake.
-
-* BOTTOM LINE: If the bug cannot find a place to be this will likely cause the
-game to freeze because the game loops until it finds an available place for the
-bug to be; if the pRNG is so bad wrt where the snake occupies it could
-theoretically happen. If this happens you will have to kill the game by e.g.
-ctrl-c. Try increasing the screen size and/or decreasing the max size of the
-snake. See below for some tests.
-
- I removed caps in a test and then:
-
- GROW=1 COLUMNS=30 LINES=10 CANNIBAL=1 MAXSIZE=10000 ./prog
-
- It froze at this point:
-
- X:14/29 Y:5/9 S:323/10000 B:318
-
- This is because there was only one place for the bug - where the snake head
- was to be. With these parameters the limit is actually 189! This could
- perhaps be increased but the calculation I have used is easy and although I
- certainly could make it so it's one less than the max that takes more bytes
- and I don't see it actually mattering.
-
- Another time I tried:
-
- LINES=6 COLUMNS=6
-
- And it also froze (as noted I impose a minimum of >= 10 for both LINES and
- COLUMNS).
-
- Ultimately I had to kill the program due to the game being stuck in the bug
- placement routine. I could have put in a maximum number of loops but what
- good would that do? It would use more bytes and what would it do anyway,
- win? Well that's what the max size is for.
-
-
-* TERMINAL SIZE TO MAX SNAKE SIZE CALCULATION ETC.
-
- For this information and more use the termcaps utility:
-
- make test
-
- An example:
-
- terminal supports cursor movement
- terminal supports making cursor invisible
- terminal supports bold
- terminal supports colours
-
- terminal rows 42 (39 playable)
- terminal cols 157 (155 playable)
-
- snake size: 997 (max size: 6006)
- bugs: 199 (max size: 1201)
-
- at least 34 columns recommended for snake size 997 (is 157)
- at least 37 columns recommended for snake size 6006 (is 157)
-
- No problems detected.
-
- Why are there only 39 playable lines for 42 rows? The first row is the score
- line, the second is the top wall, the last is the bottom wall. For columns
- you have the left and rightmost columns for the walls.
-
- The calculation for max size takes place after decrementing the max y/x;
- then it's `(maxy - 2) * (maxx - 2)`; above that would be:
-
- (41 - 2) * (156 - 2) == 6006
-
- If for some reason the game were to stall for this purpose you would have to
- kill the game by e.g. ctrl-c since the bug placement is stuck in a loop.
- This shouldn't happen though.
-
-
-## The game gets slower as the snake gets bigger!
-
-Realistically the game shouldn't take that much memory but maybe in some very
-busy systems it would have a problem.
-
-* RESOLUTION #0: If the rand() implementation is particularly poor then it might
-be that the bug placement is taking more time.
-
-* RESOLUTION #1: It could also be the arrays being updated as the snake gets
-bigger.
-
-* BOTTOM LINE: I find it unlikely that either of these happen and I don't know
-what to say; you can try decreasing the max size to see if it doesn't reach this
-problem. Otherwise it would be good to see if you can find a pattern: is it when
-the snake is bigger i.e. the screen is rather fuller than when you first begin?
-Or is the system rather busy?
-
-
-## I set `SIZE=0 GROW=1`, ate a bug but still only the head was visible! Why?
-
-* RESOLUTION #0: The size includes the head but what should it show if the size
-is 0? The head is the obvious choice so once you do get to size 1 you will still
-only have the head. When you get to size 2 you'll have part of the body too.
-Try:
-
- SIZE=1 GROW=1
-
- And you will see that at one bug you'll have size two and just as if you had
- two bugs with the previous invocation.
-
- BTW: When you are size 1 you can go back on yourself even if cannibalism is
- disabled because there really isn't anything to go back through: it's just
- you moving the head until you find a body to use! Once you have size >= 2
- then cannibalism mode counts.
-
-* BOTTOM LINE: In some senses SIZE=0 and SIZE=1 are the same thing.
-
-
-## I like black text on a white background but even with a white background terminal it ends up black!
-
-This is a curses thing but fortunately it should be easy enough to solve.
-
-* RESOLUTION #0: Try setting the terminal to monochrome for the invocation of
-the game. Depending on what is installed on your system you might not have a
-monochrome terminal but you can certainly get them. In Red Hat systems these can
-be found in the package ncurses-term but maybe that will vary on others. I don't
-recall having to install it under macOS nor Fedora but those systems have GUIs
-so that's probably why; in CentOS I did have to install it specially.
-
- The `-m` suffix to terminal names means monochrome. Under Linux this
- terminal is under `/usr/share/terminfo/l/linux-m` and under macOS (Catalina
- at least) it's at `/usr/share/terminfo/6c/linux-m`.
-
-* BOTTOM LINE: Try using a monochrome terminal for the game by e.g.:
-
- TERM=linux-m ./prog
-
- And then on your white background terminal the game should keep the
- background white and the foreground black. This will of course mean you have
- no colour but unfortunately changing the background colour of curses would
- eat too many bytes in the entry (I cite the functions in the HACKING file).
-
- I discuss colours and terminals in much more detail in
- [terminals.md][] ([terminals.html][]).
-
-
-## The text is hard to see (not bright enough)!
-
-* RESOLUTION #0: Make sure that your terminal settings have for bold text a
-brighter font. The way I have my terminal profiles set up is to use bright
-colours for bold text. I specifically enable bold in the program so try and find
-out if enabling brighter colours is possible.
-
- If it's already set at brighter colours I do not know what to say. Try
- playing with the colours in your terminal, maybe the font size or various
- other settings. Probably better to make a new profile for this first in case
- you mess up your old one. FWIW I haven't had this problem on consoles only
- and in my systems I have the option to enable brighter colours for bold - it
- was only in testing that I came across this problem.
-
-## Can I move the snake faster temporarily without having to modify the wait time?
-
-Yes. The `getch()` call is non-blocking when the timeout value is positive so
-it's up to that number of milliseconds.
-
-* RESOLUTION #0: All you need to do then is hold down the direction key (or for
-that matter any other key that `getch()` will pick up on). You can also rapidly
-push the key instead of holding it down.
-
-* BOTTOM LINE: Depending on the key repeat rate and/or how fast you repeatedly
-hit the key you can have more control over the speed - as long as it is quicker
-than the regular wait time. For negative wait time (drawing mode) you have to
-hit a key every time to move because it is blocking.
-
-
-
-## On environmental variables more generally and string to int conversions
-
-What happens if you do:
-
- WALLS= ./prog
-
-Can you run into the wall since you didn't specify a value and the default is 1?
-No. That's not the way it works. By saying WALLS= you have told the system that
-there is that environmental variable. However the way the `strtoul()` functions
-work is that if there's no valid input it returns 0. This can be detected but
-it's wasteful (iocccsize wise) and I have never felt that having invalid input
-for a number could have a better value than 0.
-
-If however you were to give valid input followed by invalid input the valid
-input would be parsed. For example:
-
- WALLS=1test ./prog
-
-Would let you go through the walls. On the other hand
-
- WALLS=test1 ./prog
-
-Would not. Furthermore if you specify the same variable more than once it's the
-last one that counts. For example:
-
- WALLS=0 WALLS=1 CANNIBAL=1 CANNIBAL=0 ./prog
-
-Would allow you to go through walls but you could not cannibalise.
-
-Also note that I specify base 0 which means that you can also have it in hex and
-octal. These are all the same:
-
- SIZE=0x3
- SIZE=3
- SIZE=03
-
-The way the functions work is if 0x (or 0X) it's considered hex; if prefixed
-with a 0 it's octal and otherwise it's decimal. If you specify invalid data
-(even if only at the beginning of the string) the functions return 0. For
-example
-
- SIZE=0
- SIZE=f
- SIZE=-
- SIZE=f1
-
-Are all equivalent.
-
-Observe that
-
- SIZE=08
-
-Is invalid input because octal only has digits 0 - 7: the resulting size will be
-0.
-
-
-I discuss the signed/unsigned issue to do with curses and sizes in C being
-unsigned in [bugs.md][] but probably there isn't anything more to say here.
-
-## Errors and error reporting
-
-If curses fails to initialise you should get an error that says 'curses error'
-and you have every right to curse it to hell if that's what you so wish.
-Apparently curses will report an error itself if that function fails but that
-escaped my notice until later on so you might get two errors in that case.
-
-Assuming it succeeds the game obtains the maximum y/x of the terminal. The
-screen size must be at least 10 lines/columns (though in code the number will
-not be 10); if either is smaller you will get 'screen too small' and the game
-will end (yes things that haven't begun can be ended).
-
-If calloc() fails to obtain the needed memory you'll see something like (here it
-was before I added proper - to make the perfect and obvious pun - capsizing
-so that by setting the size to -1 it went to the max unsigned value):
-
- $ MAXSIZE=-1 ./prog
- memory error
- X:0/157 Y:0/42 S:3/18446744073709551614 B:0
-
-
-BTW: There are two arrays that have to be **MAXSIZE** (technically + 1).
-
-Is it possible that some value specified by the user could mess this up? I do
-not know but what I do know is that because it's unsigned it can't be negative;
-if the max size is 0 then the array size will be 1 but it won't matter because
-the snake size will be >= that max anyway. But here's a curious output:
-
- SIZE=1 MAXSIZE=0 ./prog
- YOU WIN!
- X:78/156 Y:20/41 S:0/0 B:0
-
-Why does it show snake size as 0 when I specified 1? It's because the max size
-is 0 and I limit the size to be no bigger than the max size.
-
-
-[HACKING]: HACKING
-[prog.c]: prog.c
-[bugs.md]: bugs.md
-[terminals.md]: terminals.md
-[terminals.html]: terminals.html
-[snake-colours]: snake-colours
-[Snakey]: https://www.hp-lexicon.org/character/gaunt-family/morfin-gaunt/
diff --git a/2020/ferguson2/recode.markdown b/2020/ferguson2/recode.markdown
deleted file mode 100644
index 6ab04699d..000000000
--- a/2020/ferguson2/recode.markdown
+++ /dev/null
@@ -1,564 +0,0 @@
-# The recode configurator documentation (and a fun way to explore my 2020 IOCCC Enigma simulator)
-
-N.B. At the end of this file I have given a fun exercise that can be used to
-explore my Enigma simulator. It's especially worth doing if you you like
-good chocolate and could use a delicious [Double-layered Chocolate Fudge Cake][].
-
-Alternatively if you just want the recipe you could look at my Snake entry
-'Don't tread on me award' since it's also there and not enciphered.
-
-
-- [What is recode and why is it recommended?](#recode)
-- [Options](#options)
- * [Protecting against the same I/O file](#samefile)
- * [File options parser limitation](#fileoptions)
- * [-R option validation?](#validation)
-- [Piping commands to recode](#pipingtorecode)
-- [Piping recode to the Enigma simulator](#pipingtoenigma)
-- [Manually test the recode program with the Enigma program](#manuallytest)
-- [Only write config file](#onlyconfig)
-- [Reusing a configuration](#reuseconfig)
-- [Write config file, read data file and pass to Enigma simulator](#passtoenigma)
-- [Piping directly to the Enigma code once (with randomised settings, saved)](#directlytoenigma)
-- [Usage conclusion](#conclusion)
-- [Example additions](#additions)
-- [Example uses](#exampleuses)
-- [Delicious Enigma: Double-layered Chocolate Fudge Cake](#cake)
-
-# What is recode and why is it recommended?
-
-To demonstrate how to and why you should use the recode program with the Enigma
-simulator I have included some examples here as well as brief ('brief?!' I am sure
-many would think but it's brief for me) commentary.
-
-It would not be possible to do all that the recode program does in my entry
-itself but I wanted to demonstrate the features of my entry and this seemed the
-best way to do that. It also enhances the use of the simulator to make it
-reusable etc.
-
-The recode name idea is that it recodes the input (validating first) to be input
-for the simulator itself. It can pseudo-randomly select all the settings, it can
-write the settings to a file, read from input file (e.g. for the text to
-encipher if piped to the simulator) etc.
-
-Basically it's a configurator for the Enigma simulator that makes it easier to
-use the simulator as well as to reuse the configuration to decipher messages
-that have been enciphered by those settings. But it also tries to make it look
-more like the real thing in that it shows the actual rotors (labelling them with
-the Roman numeral), the reflectors (labelling them with B, C and showing the
-actual strings) etc.
-
-In this file I will show an example of each feature and then get to the
-wonderful 'challenge' for everyone.
-
-# Options
-
- usage: ./recode [options]
- -v display selected settings
- -r pseudo-randomly select settings
- -f read file for Enigma input
- -R init settings from settings string or file
- -o