Back to index
Last updated: 18 July 2023 (complete changelog since 26 July 2020)

Introduction

On 26 July 2020 it came to my attention that two of my 2020 IOCCC entries have won! I'm very very happy and incredibly proud. This brings my total to three now. In time here I will give more information but for now these tweets is all there is for this entry: tweet announcing my Don't tread on me award winning IOCCC entry

Also the who won page on the official IOCCC website.

As of 22 July I have a few items of possible interest. Most interesting perhaps is some of my comments (much shorter than my entry documentation itself!) and my comments on Ilya Kurdyukov's version inspired by my winning entry. As will be seen some of his ideas I already had but due to contest size restrictions I could not implement. Eventually I will probably have his many interesting comments here too.

The winning entry (Last updated: 22 Jul 2021)

The winning entry can be found here.

My comments of interest (Last updated: 23 Jul 2021)

There's a lot that can be said for this entry but I'll not include too many things (I hope - I often fail there). I had A LOT of fun writing this and play-testing this (and even after winning I sometimes play it)! So where to begin?

- There's a terminal test utility to try determining any possible problems.

To compile and run make test and you will see something like:

$ make test
You should see something like:
terminal supports cursor movement
terminal supports making cursor invisible
terminal supports bold
terminal supports colours

terminal rows  41 (38  playable)
terminal cols 159 (157 playable)

snake size:   997 (max size: 5928)
      bugs:   199 (max size: 1185)

at least 34 columns recommended for snake size 997   (is 159)
at least 37 columns recommended for snake size 5928  (is 159)

No problems detected.
	
This utility accepts some of the environmental variables but it's far from perfect and it does not take everything into account. It does however test the terminal capabilities that are needed.

- Environmental variables / Different Gameplay Modes

Please be very careful with low values for the WAIT and EVADE variables (< 0 for WAIT notwithstanding) if you have any photosensitive triggers like epilepsy.

Note the play.sh script (try it: ./play) sets up many different gameplay modes that these variables can create. Over time I came up with more and more certainly can be thought up. You can specify variables to this script but some are incompatible with different modes.

To use the variable do e.g. WAIT=100 ./prog.

  • WAIT: How many milliseconds in between each snake movement/growth. < 0 is drawing mode (it blocks on read input); 0 is instance. Default 231 and you can move faster by holding or pressing the arrow keys down/faster.
  • EVADE: After this many snake movements the bug will try and find a new place (if it's eaten the counter is reset); default 300 moves.
  • CANNIBAL: Whether you can go through yourself; default no.
  • WALLS: Whether the snake can go through walls; default yes.
  • SIZE / MAXSIZE: The starting size (note that it grows one at a time so if you specify a larger size it won't immediately be that size) and maximum size respectively. Depending on the terminal dimensions the max size is capped; -1 max size is the max size based on the dimensions. If SIZE is < 0 you will automatically win.
  • GROW: Size to grow every time you eat a bug.
  • SHED / SHEDS: This is hard to explain simply but every SHED movements your snake will either grow or lose its length by SHEDS which can be negative or positive (a unique feature that can look quite crazy!). In gameplay.text I give example uses and the play.sh script does too. The variable is a misnomer: snakes grow via shedding (called moulting) rather than every time they eat like the game has. Note that this mode allows you to grow or shrink every SHED movement; positive or negative growth I called it.

There might be other variables I have forgotten but that's the majority of them.

- There's a built-in test unit for some features!

This was not intentionally programmed. For information on this see the bugs.text/bugs.html files.

- The game can play by itself

I demonstrate this in gameplay.html (or how to set it up); this one can be a photosensitive trigger.

A bunch of other gameplay options are in gameplay.html and the play.sh script sets up most of them for you automatically (I don't recall if this is in the script though).

- You can pause the game

Simply press the space bar. To resume hit a direction or space again. It might be that pressing any other key will continue you moving in the direction you left off; I no longer recall. This is one of the reasons the characters used for the head is useful.

- The judges' comments on the obfuscation

I really like how they put it:

Read ONLY if you really must give up trying to de-obfuscate!

...because it seems they really appreciated the effort I made into obfuscating it. Although not the cleverest of the year I think some of the techniques I used were unique and at least some quite clever though of course I'm obviously biased and I also have forgotten everything I did; I could not easily add features now without some work!

Ilya Kurdyukov's version (New: 22 July 2021)

Here you can find Ilya's snake implementation and here are my comments on them. Note that I haven't actually tested it (since he originally made it); I'm merely writing about his features and changes.

- Renaming variables: I simply chose what fit well and didn't consume too many bytes against the contest entry though I felt CANNIBAL particularly relevant for snakes even though technically the snake doesn't eat itself.

- Invocation differences: Whereas in his game you have to run it like: ./prog WAIT=100 in mine you have to do: WAIT=100 ./prog.

- Disallowing turning in the opposite direction: I can kind of see the appeal to this but my entry was also inspired by the old video game Surround which could do this. Also for cannibalism it added for some interesting game effects. I show some of these in the file crazy.log. But other than that I actually prefer it being able to go backwards even if it's unrealistic (going through walls is also unrealistic but this was also a feature of Surround and it's why I implemented it).

- My game you can pause: I don't know if his allows this but it was very useful for me. I also have the snake head be <, > ^ and v so you can see which direction you are going and this is especially useful when you've paused the game.

- Different characters: Using unicode would be ideal for the size of vertical versus horizontal but the way I did it was simpler and less code (well, maybe). I quite like how it turned out though but I can see the appeal of his way too. I personally prefer the snake head as I have it however. Personally I'm also not big on emojis; although I use them at times they often annoy me.

- Number of 'bugs' on the screen: I actually thought of this and I think I even mentioned it in the HACKING (a file I gave many other ideas to improve the game) file but due to size restrictions in the contest I did not implement it.

- His has a snake safety feature: He describes it like: if you encounter an obstacle this option gives you a delay to change direction before losing. I personally don't think I'd ever use that but it's an interesting idea. I did however think (and I'm almost certain it's in the HACKING file) of having a save option so you can resume the game after it ends (so you can start where you left off). This however would have complicated things much more so the closest there is is that you can specify the starting size.

- His expiry option differs from my evasion option: Mine is a constant value: if you specify 500 movements then it's every 500 movements full stop; his is randomly selected in the range of EXPIRY/2 to EXPIRY.

- ANSI sequences versus curses: My game uses libcurses and I like it that way; this has the added bonus of allowing the drawing mode since the function to get input can be set to block or not. There are probably other bonuses. It's also of course more portable. He has code that allows you to use curses though.

- The segments spawn as in classic games: I don't know what this might be; it's too long since I played the original.

- The random colour for winning message: I think that would probably annoy me but that's a personal thing. Different games have different winning scenes and some games never end. Depending on if you run into the wall (and they're not passable) or yourself (and cannibalism isn't enabled) or you won a different message is shown as well as the status/score bar. That bar is updated every movement as the snake's head coordinates are also printed. You can change that but that's the default and changing requires changing the code. This format string is used more than once.

That's all I can think of at this time without actually playing it but I do thank him for his comments (which I hope to put here eventually) and also for testing etc..

Drawing mode demonstration (Last updated: 18 July 2023)

Whilst I was waiting for the judges to publish the code I decided to make a tweet demonstrating the drawing mode. It's far from perfect due to the nature of terminals but this is a screenshot of the tweet that once was:

Drawing of the word Snake in Snake game
Errata on this entry (New: 12 Aug 2020)

In the bugs file I noted that it appears that some input devices other than the keyboard can trigger input; I gave the example of on my MacBook Pro the trackpad if I swipe down and then up the snake runs into itself. I learnt today, 12 August 2020, that it's because of the keypad being enabled - in order to accept arrow keys. Thus this is a necessary consequence of using arrow keys (which have always felt more natural to me than other keys for movement).