Merge pull request #1766 from xexyl/ferguson12020
This commit is contained in:
12 files changed
+53
-3254
No files matched your search
@@ -1,334 +0,0 @@
|
||||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.2.2">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=utf-8"> <link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<CENTER>
|
||||
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
|
||||
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
|
||||
<div id="bar">
|
||||
<ul>
|
||||
<li><a href="../index.html">About the 27th IOCCC</a></li>
|
||||
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
|
||||
<li><a href="/index.html">IOCCC home</a></li>
|
||||
<li><a href="/winners.html">List of All Winners</a></li>
|
||||
<li><a href="/judges.html">The Judges</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<P><FONT size="6"><B>Supplemental Info</B></FONT></P>
|
||||
</CENTER>
|
||||
|
||||
|
||||
<p>Current bugs and things that look like bugs but are not, as of 12 September 2020.</p>
|
||||
|
||||
<p><a name="toc"></a></p>
|
||||
<ul>
|
||||
<li><p><a href="#builtin-test-unit">Built-in test unit for some features!</a></p></li>
|
||||
<li><p><a href="#stillsnake">The snake doesn't seem to be moving</a></p></li>
|
||||
<li><p><a href="#getch">getch() also accepts input from some input hardware other than keyboards</a></p></li>
|
||||
<li><p><a href="#size">SIZE=0 is the same as SIZE=1 and other oddities</a></p></li>
|
||||
<li><p><a href="#bitetail">'I was a few places behind my tail and I ran into it!'</a></p></li>
|
||||
<li><p><a href="#middleofsnake">With negative growth the snake drops from the middle of the body</a></p></li>
|
||||
<li><p><a href="#buginsnake">It looks like the bug is in the snake</a></p></li>
|
||||
<li><p><a href="#bugplacement">On the safety of the bug placement loop</a></p></li>
|
||||
<li><p><a href="#verticalsnake">Vertical snake has more space between snake char than horizontal</a></p></li>
|
||||
</ul>
|
||||
|
||||
<h1><a name="builtin-test-unit" href="#toc">Built-in test unit for some features!</a></h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> SIZE=0 SHED=1 SHEDS=1 EVADE=10 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>If you set it to <code>SIZE=10</code> 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).</p>
|
||||
|
||||
<p>There probably are combinations that can test these types of things I just
|
||||
don’t at this time remember any I might have done.</p>
|
||||
|
||||
<h1><a name="stillsnake" href="#toc">The snake doesn’t seem to be moving</a></h1>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> SIZE=100 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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 <a href="cannibalism.log">cannibalism.log</a> has some examples of both
|
||||
cannibalism and a long snake that didn’t move for most of the game.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<h1><a name="getch" href="#toc">getch() also accepts input from some input hardware other than keyboards</a></h1>
|
||||
|
||||
<p>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 <code>keypad(v, 1);</code> which enables arrow keys.</p>
|
||||
|
||||
<h1><a name="size" href="#toc">SIZE=0 is the same as SIZE=1 and other oddities</a></h1>
|
||||
|
||||
<p>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?</p>
|
||||
|
||||
<p>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 <code>SIZE=-1 ./prog</code>).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>For example if I say <code>SIZE=3 GROW=-2</code> at two bugs the game is won.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>Here’s a fun output:</p>
|
||||
|
||||
<pre><code> < <<<+
|
||||
</code></pre>
|
||||
|
||||
<p>That’s from:</p>
|
||||
|
||||
<pre><code> SHED=1 SHEDS=-1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>And right after that you would see:</p>
|
||||
|
||||
<pre><code> YOU WIN!
|
||||
X:72/156 Y:20/41 S:997/997 B:0
|
||||
</code></pre>
|
||||
|
||||
<p>Try this though:</p>
|
||||
|
||||
<pre><code> SHEDS=-1 SHED=25 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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
|
||||
<a href="gameplay.md">gameplay.md</a> (<a href="gameplay.html">gameplay.html</a>) file.</p>
|
||||
|
||||
<p>Here’s another thing to be aware of. Let’s say you do:</p>
|
||||
|
||||
<pre><code> SIZE=1 GROW=-1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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’:</p>
|
||||
|
||||
<pre><code> YOU WIN!
|
||||
X:81/156 Y:35/41 S:997/997 B:2
|
||||
</code></pre>
|
||||
|
||||
<h1><a name="bitetail" href="#toc">‘I was a few places behind my tail and I ran into it!’</a></h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p><strong>Remember: the tail at that point isn’t moving yet; the snake is growing!</strong></p>
|
||||
|
||||
<h1><a name="middleofsnake" href="#toc">With negative growth the snake drops from the middle of the body</a></h1>
|
||||
|
||||
<p>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 <code>SHED=100 SHEDS=-1</code>:</p>
|
||||
|
||||
<pre><code> ooooooooo>ooo>
|
||||
^
|
||||
>
|
||||
</code></pre>
|
||||
|
||||
<p>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 <code>SHEDS=-3</code>:</p>
|
||||
|
||||
<pre><code> <ooo<ooooo
|
||||
^^^
|
||||
<oo
|
||||
</code></pre>
|
||||
|
||||
<p>If you go through the part that has split (which for some might be difficult
|
||||
to see whilst the snake has not fully left its skin) you won’t run into
|
||||
yourself; if you run into another part though you do. This might be a bit
|
||||
confusing I know but what kind of animal shrinks in size by leaving its head
|
||||
behind only to sprout up a new head? Actually…on second thought, I won’t
|
||||
go there! :)</p>
|
||||
|
||||
<p>Anyway it’s an odd idea for the snake to shrink by leaving part of its skin:
|
||||
that’s how they grow in the wild so it’s a misnomer. The shrinking was only
|
||||
‘discovered’ because it’s an unsigned number but happily it allows for different
|
||||
gameplay modes.</p>
|
||||
|
||||
<h1><a name="buginsnake" href="#toc">It looks like the bug is in the snake</a></h1>
|
||||
|
||||
<p>I show a different example in the <a href="crazy.log">crazy.log</a> 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:</p>
|
||||
|
||||
<pre><code> <*oooooooo
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h1><a name="bugplacement" href="#toc">On the safety of the bug placement loop</a></h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>To explain it I will go back to the make test program <code>termcaps</code> (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.</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> $ 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
|
||||
</code></pre>
|
||||
|
||||
<p>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?</p>
|
||||
|
||||
<p>With 10 rows and columns it’s calculated as 7 * 7 (i.e. it’s
|
||||
<code>(cols-3)*(rows-3)</code>. However the number of playable locations is in this case 56
|
||||
(<code>playable_rows * playable_columns</code>). 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
|
||||
<a href="troubleshooting.md">troubleshooting.md</a> (<a href="troubleshooting.html">troubleshooting.html</a>).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h1><a name="verticalsnake" href="#toc">Vertical snake has more space between snake char than horizontal snake</a></h1>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<blockquote><p>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.</p>
|
||||
|
||||
<p>MATE Terminal 1.20.0, and font “Ubuntu Mono Regular 13”</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p><a href="https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms">https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms</a></p>
|
||||
|
||||
<p>So the typical fonts are Half-width or close to it.</p>
|
||||
|
||||
<p><img src="halfwidth_vs_fullwidth.png"></p></blockquote>
|
||||
|
||||
<p>However the function <code>mvaddch()</code> takes a <code>chtype</code> 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
|
||||
<a href="spoilers.markdown">spoilers</a> aren’t enough here!).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.)</p>
|
||||
<BR>
|
||||
<HR>
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2020,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,203 +0,0 @@
|
||||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.2.2">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=utf-8"> <link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<CENTER>
|
||||
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
|
||||
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
|
||||
<div id="bar">
|
||||
<ul>
|
||||
<li><a href="../index.html">About the 27th IOCCC</a></li>
|
||||
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
|
||||
<li><a href="/index.html">IOCCC home</a></li>
|
||||
<li><a href="/winners.html">List of All Winners</a></li>
|
||||
<li><a href="/judges.html">The Judges</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<P><FONT size="6"><B>Supplemental Info</B></FONT></P>
|
||||
</CENTER>
|
||||
|
||||
<h1>Double-layered Chocolate Fudge Cake</h1>
|
||||
|
||||
<p>Here's a delicious double-layered chocolate fudge cake that is
|
||||
something of my mum's speciality. It's complicated and I should warn that nobody
|
||||
has seemed to get it down as well as she has but it's well worth the effort if
|
||||
you love chocolate. My late stepmum who only liked white chocolate loved this
|
||||
cake!</p>
|
||||
|
||||
<p><img src='cake.jpg' alt='picture of the double-layered chocolate fudge cake'></p>
|
||||
|
||||
<p>There are two sets of ingredients and instructions; the cake and the icing. In
|
||||
addition there are some notes to pay attention to; some will be repeated because
|
||||
they're really important for the quality of the cake.</p>
|
||||
|
||||
<p>Below I have included the ingredients separately but I include them within the
|
||||
instructions as well and in bold. Also in bold are some of the special notes.</p>
|
||||
|
||||
<p>Finally note that depending on where you are in the world this might not work in
|
||||
the warmer months of the year for the icing in particular. Oh and here's an
|
||||
amusing fact about the <a href="http://www.gomc.com/firstpage/200103068.pdf">IOCCC and chocolate</a>. Did I say 'the IOCCC'? I actually
|
||||
meant <strong>'an IOCCC'</strong>: it stands also for <strong>'International Office of Cocoa, Chocolate
|
||||
and Sugar Confectionery'</strong>. Perfect.</p>
|
||||
|
||||
<p>See also the <a href="https://web.archive.org/web/20200805053007/https://twitter.com/ilyakurdyukov/status/1290520266087571458">International Original Chocolate Cake Contest tweet</a> from
|
||||
<a href="https://www.ioccc.org/winners.html#Ilya_Kurdyukov">fellow IOCCC winner Ilya Kurdyukov</a> (<a href="https://github.com/ilyakurdyukov">GitHub</a>) as well as the
|
||||
<a href="ioccc-cake.jpg">IOCCC cake source image</a> of the picture in the tweet (which he painted over
|
||||
my photo of the cake with GIMP).</p>
|
||||
|
||||
<h2>Measurements</h2>
|
||||
|
||||
<p>This was originally from an American cookery book so the measurements are in the
|
||||
US standards. A nice resource (that has much more than just cooking) is
|
||||
<a href="http://www.onlineconversion.com/cooking.htm">http://www.onlineconversion.com/cooking.htm</a>. This will particularly matter
|
||||
for cups, teaspoons, tablespoons and ounces.</p>
|
||||
|
||||
<h2>Baker's chocolate</h2>
|
||||
|
||||
<p>Baker's chocolate is a brand name and the product in question is unsweetened
|
||||
chocolate bars used for baking. According to a <a href="https://www.davidlebovitz.com/chocolate-faqs/">chocolates FAQ</a> it might be
|
||||
called different things:</p>
|
||||
|
||||
<pre><code>Bitter chocolate contains no sugar and is often called 'unsweetened' or
|
||||
'baking' chocolate. In some countries it's called 100% cacao since it's
|
||||
composed only of ground up cocoa beans, and nothing else.
|
||||
</code></pre>
|
||||
|
||||
<p>The FAQ suggests that you might have to look for a baking supply shop but I
|
||||
cannot offer any specific advice other than it's unsweetened chocolate bars for
|
||||
baking. The FAQ talks about what looks like substitutes but I have no idea what
|
||||
that would turn out as; I somehow suspect it wouldn't be good.</p>
|
||||
|
||||
<p>Either way please <strong>still pay attention to the notes on the chocolate in the recipe and
|
||||
recipe notes because they're really important!</strong></p>
|
||||
|
||||
<h2>Special notes for the cake</h2>
|
||||
|
||||
<p><strong>PAY CLOSE ATTENTION TO THESE:</strong></p>
|
||||
|
||||
<ul>
|
||||
<li><p><strong>USE MARGARINE</strong>. Butter does not work well. If you think it will come out
|
||||
better by using butter you're very mistaken; it will come out badly!</p></li>
|
||||
<li><p>Over the years they changed the size of the unsweetened chocolate squares;
|
||||
they used to be one ounce each now they are 1/4 ounce each square so be sure to
|
||||
note the amount is by ounce not squares as listed. See the measurements link
|
||||
if there's any doubt.</p></li>
|
||||
<li><p>Pay careful attention to <strong>COOK FOR ONLY THE INDICATED TIME</strong>.</p></li>
|
||||
<li><p><strong>REMOVE THE CAKE FROM THE PANS 2 MINUTES AFTER REMOVING FROM OVEN</strong>. Then allow
|
||||
to fully cool on racks. The important point is that they don't overcook.</p></li>
|
||||
<li><p>When the recipe was first written they sold powdered sugar in a box; now
|
||||
it's confectioners sugar in a bag. My mum experimented with the amount and
|
||||
found that 4 cups seems about right.</p></li>
|
||||
<li><p>She uses <strong>WHOLE MILK</strong> for this recipe; she doesn't know if it really matters
|
||||
but given that she and I both prefer skim milk except for here and in
|
||||
chocolate milk I would recommend whole milk for this recipe too. In any case
|
||||
it turns out great <strong>if you follow <em>everything</em> to a T!</strong></p></li>
|
||||
<li><p>Use only <strong>PURE VANILLA EXTRACT</strong>! Do <strong>NOT USE imitation vanilla!</strong></p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Cake Ingredients</h2>
|
||||
|
||||
<ul>
|
||||
<li>3 oz unsweetened (Baker's) chocolate</li>
|
||||
<li>2 and 1/4 cups flour</li>
|
||||
<li>2 tbsp baking soda</li>
|
||||
<li>1/2 tsp salt</li>
|
||||
<li>2 and 1/4 cups packed brown sugar</li>
|
||||
<li>3 eggs</li>
|
||||
<li>1 and 1/2 tsp vanilla</li>
|
||||
<li>1/2 cups margarine</li>
|
||||
<li>1 cup (boiling) water</li>
|
||||
<li>1 cup sour cream</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Cake Preparation</h2>
|
||||
|
||||
<ol>
|
||||
<li><p>Lightly grease two 9 x 1.5 inch round pans; lightly dust with flour.</p></li>
|
||||
<li><p>Preheat oven to 350 F (176.67 C).</p></li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h2>Cake Directions</h2>
|
||||
|
||||
<ol>
|
||||
<li><p>Melt <strong>3 oz unsweetened chocolate</strong> in double boiler or small bowl over
|
||||
<strong>hot (<em>but not boiling</em>) water</strong>; let cool whilst proceeding.</p></li>
|
||||
<li><p>Sift <strong>2 1/4 cups flour</strong>, <strong>2 tsp baking soda</strong>, and <strong>1/2 tsp salt</strong></p></li>
|
||||
<li><p>Beat <strong>1 stick margarine</strong> in large bowl <em>until soft</em>.</p></li>
|
||||
<li><p>Add <strong>2 1/4 cups packed brown sugar</strong> and <strong>3 eggs</strong>. Beat until light and
|
||||
fluffy.</p></li>
|
||||
<li><p>Beat in <strong>1 1/2 tsp vanilla</strong> and <strong>cooled melted chocolate</strong>.</p></li>
|
||||
<li><p>Stir in dry ingredients alternately with <strong>1 cup sour cream</strong>; always beat
|
||||
until smooth.</p></li>
|
||||
<li><p>Stir in <strong>1 cup boiling water</strong>.</p></li>
|
||||
<li><p>Pour into prepared pans.</p></li>
|
||||
<li><p>Bake for <strong>ONLY 35 minutes</strong> (NO LONGER) at 350 F (176.67 C).</p></li>
|
||||
<li><p>When you take the cake out put the cake pans on a cooling rack for <strong>TWO
|
||||
MINUTES ONLY AND THEN IMMEDIATELY TURN CAKES OUT ON TO RACK</strong>. Let cool
|
||||
completely.</p></li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h2>Icing Ingredients</h2>
|
||||
|
||||
<ul>
|
||||
<li>4 oz unsweetened chocolate (Baker's chocolate)</li>
|
||||
<li>1/2 cup margarine</li>
|
||||
<li>4 cups powdered sugar</li>
|
||||
<li>1/2 cup whole milk</li>
|
||||
<li>2 tsp vanilla</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>You will also need a bigger pan or bowl that can have ice water that the icing
|
||||
bowl can sit in.</p>
|
||||
|
||||
<h2>Special notes for the icing</h2>
|
||||
|
||||
<p><strong>PAY CLOSE ATTENTION TO THESE:</strong></p>
|
||||
|
||||
<ul>
|
||||
<li><p>Make sure that the melted chocolate and margarine does not get solid.</p></li>
|
||||
<li><p>For step #4 put <strong>8 to 10 ice cubes</strong> in a pan or big bowl (that's big
|
||||
enough that another bowl can fit in it). Add an inch of water and then set
|
||||
the bowl with the icing in the pan or bowl of ice water. <strong>Do not let the
|
||||
icing get wet!</strong></p></li>
|
||||
<li><p>Do not let icing get too thick.</p></li>
|
||||
<li><p>Use <strong>whole milk.</strong></p></li>
|
||||
<li><p>Use only <strong>pure vanilla extract</strong>! Do <strong>not use imitation vanilla!</strong></p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Icing Directions</h2>
|
||||
|
||||
<ol>
|
||||
<li><p>Combine <strong>4 oz unsweetened chocolate</strong> and <strong>1/2 cup margarine</strong> in pan.
|
||||
Melt and remove from heat. <strong>DO NOT LET IT GET SOLID.</strong></p></li>
|
||||
<li><p>Combine <strong>3 1/4 cups powdered sugar</strong>, <strong>1/2 cups whole milk</strong> and <strong>2 tsp
|
||||
vanilla</strong> into a bowl. <strong>Stir until smooth</strong>.</p></li>
|
||||
<li><p>Add chocolate mixture.</p></li>
|
||||
<li><p>Set bowl in pan/bowl of ice and water. Beat with spoon/mixer until it's
|
||||
thick BUT not too thick. Make sure icing doesn't get wet! The idea is to
|
||||
<strong>MAKE THE BOWL IT'S IN COLD <em>but not let the icing get wet</em></strong>.</p></li>
|
||||
</ol>
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2020,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,7 +3,7 @@
|
||||
Here's a delicious double-layered chocolate fudge cake that is
|
||||
something of my mum's speciality. It's complicated and I should warn that nobody
|
||||
has seemed to get it down as well as she has but it's well worth the effort if
|
||||
you love chocolate. My late stepmum who only liked white chocolate loved this
|
||||
you love chocolate. My late stepmum who only liked white 'chocolate' loved this
|
||||
cake!
|
||||
|
||||

|
||||
@@ -69,21 +69,23 @@ recipe notes because they're really important!**
|
||||
note the amount is by ounce not squares as listed. See the measurements link
|
||||
if there's any doubt.
|
||||
|
||||
* Pay careful attention to **COOK FOR ONLY THE INDICATED TIME**.
|
||||
* Pay careful attention to **COOK FOR ONLY THE INDICATED TIME**. Note that if
|
||||
your oven cooks a bit hotter you might have to adjust the timing a bit. This
|
||||
is likely the case if the cake comes out a little bit dry.
|
||||
|
||||
* **REMOVE THE CAKE FROM THE PANS 2 MINUTES AFTER REMOVING FROM OVEN**. Then allow
|
||||
to fully cool on racks. The important point is that they don't overcook.
|
||||
* **REMOVE THE CAKE FROM THE PANS 2 MINUTES AFTER REMOVING FROM OVEN** and
|
||||
then allow to **FULLY COOL *ON RACKS*!** The important point is that they
|
||||
don't overcook.
|
||||
|
||||
* When the recipe was first written they sold powdered sugar in a box; now
|
||||
it's confectionery sugar in a bag. My mum experimented with the amount and
|
||||
found that 4 cups seems about right.
|
||||
|
||||
* She uses **WHOLE MILK** for this recipe; she doesn't know if it really matters
|
||||
but given that she and I both prefer skim milk except for here and in
|
||||
chocolate milk I would recommend whole milk for this recipe too. In any case
|
||||
it turns out great **IF YOU FOLLOW *EVERYTHING* TO A T!**
|
||||
* Use **WHOLE MILK**. It's just better for something like this and skim milk
|
||||
or low fat milk is completely untested.
|
||||
|
||||
* Use only **PURE VANILLA EXTRACT**! Do **NOT USE imitation vanilla!**
|
||||
* Use only **PURE VANILLA EXTRACT**! Do **NOT USE imitation vanilla!** Not
|
||||
following this rule will lead to a worse outcome.
|
||||
|
||||
|
||||
## Cake Ingredients
|
||||
@@ -161,7 +163,11 @@ bowl can sit in.
|
||||
|
||||
* Use **WHOLE MILK.**
|
||||
|
||||
* Use **ONLY PURE VANILLA EXTRACT**! **DO NOT USE IMITATION VANILLA!**
|
||||
* Use **ONLY PURE VANILLA EXTRACT**! **DO NOT USE IMITATION VANILLA!** Not
|
||||
following this rule will lead to a worse outcome. As I recall the icing was
|
||||
quite a bit worse (but still good) the times we had imitation vanilla. Just
|
||||
don't do it.
|
||||
|
||||
|
||||
|
||||
## Icing Directions
|
||||
@@ -181,7 +187,7 @@ bowl can sit in.
|
||||
|
||||
[picture]: cake.jpg
|
||||
[http://www.onlineconversion.com/cooking.htm]: http://www.onlineconversion.com/cooking.htm
|
||||
[IOCCC and chocolate]: http://www.gomc.com/firstpage/200103068.pdf
|
||||
[IOCCC and chocolate]: ioccc-and-chocolate.pdf
|
||||
[International Original Chocolate Cake Contest tweet]: https://web.archive.org/web/20200805053007/https://twitter.com/ilyakurdyukov/status/1290520266087571458
|
||||
[fellow IOCCC winner Ilya Kurdyukov GitHub]: https://github.com/ilyakurdyukov
|
||||
[GitHub]: https://github.com/ilyakurdyukov
|
||||
|
||||
@@ -1,838 +0,0 @@
|
||||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.2.2">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=utf-8"> <link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<CENTER>
|
||||
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
|
||||
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
|
||||
<div id="bar">
|
||||
<ul>
|
||||
<li><a href="../index.html">About the 27th IOCCC</a></li>
|
||||
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
|
||||
<li><a href="/index.html">IOCCC home</a></li>
|
||||
<li><a href="/winners.html">List of All Winners</a></li>
|
||||
<li><a href="/judges.html">The Judges</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<P><FONT size="6"><B>Supplemental Info</B></FONT></P>
|
||||
</CENTER>
|
||||
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p><a name="toc"></a></p>
|
||||
|
||||
<ol>
|
||||
<li><p><a href="#support">Testing terminal environment/capabilities</a></p></li>
|
||||
<li><p><a href="#input">Input keys</a></p></li>
|
||||
<li><p><a href="#gameplay">Gameplay</a></p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="#initial">The initial screen</a></p></li>
|
||||
<li><p><a href="#playing">Playing the game</a></p></li>
|
||||
<li><p><a href="#walls">Walls</a></p></li>
|
||||
<li><p><a href="#cannibalism">Cannibalism</a></p></li>
|
||||
<li><p><a href="#shedding">Stretching (shedding)</a></p></li>
|
||||
<li><p><a href="#winning">Winning</a></p></li>
|
||||
<li><p><a href="#quitting">Quitting</a></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a href="#modes">Gameplay modes</a></p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="#warning"><strong>Photosensitive epilepsy/Stimulation overload trigger warnings</strong></a></p></li>
|
||||
<li><p><a href="#drawing">Drawing / Practice mode</a></p></li>
|
||||
<li><p><a href="#auto">Computer playing / Automatic mode (<strong>Photosensitive epilepsy/Stimulation overload trigger</strong>)</a></p>
|
||||
|
||||
<ul>
|
||||
<li><a href="#auto-variations">Variations</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a href="#grow-shrink">Grow-Shrink (Positive/Negative Winning) mode</a></p></li>
|
||||
<li><p><a href="#hypnotic">Hypnotic / Sleepy mode (<strong>Photosensitive epilepsy/Stimulation overload trigger</strong>)</a></p></li>
|
||||
<li><p><a href="#stim">Stimulation / Calming mode</a></p></li>
|
||||
<li><p><a href="#other-ideas">Other ideas</a></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a href="#scripts">Scripts</a></p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="#colours">Colours selection</a></p></li>
|
||||
<li><p><a href="#preset">Automate the above gameplay modes</a></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a href="#variables">Notes about some of the game variables</a></p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="#wait">WAIT - Snake speed</a></p></li>
|
||||
<li><p><a href="#evade">EVADE - Bug evasion frequency</a></p></li>
|
||||
<li><p><a href="#sizes">SIZE / MAXSIZE - Initial snake / max sizes</a></p></li>
|
||||
<li><p><a href="#growth">GROW / SHEDS - Growth / Shedding sizes</a></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a href="#conclusions">Conclusion (and inspirational words for everyone)</a></p></li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h1>1. <a name="support" href="#toc">Testing terminal environment/capabilities</a></h1>
|
||||
|
||||
<p>Most people probably won’t have any issue at all but for those who have any
|
||||
problems with the terminal see the <a href="terminals.md">terminals.md</a> file for more
|
||||
information on the terminal capabilities testing utility I include.</p>
|
||||
|
||||
<p>For troubleshooting other problems see <a href="troubleshooting.md">troubleshooting.md</a>
|
||||
(<a href="troubleshooting.html">troubleshooting.html</a>) and <a href="bugs.md">bugs.md</a> (<a href="bugs.html">bugs.html</a>).</p>
|
||||
|
||||
<h1>2. <a name="input" href="#toc">Input keys</a></h1>
|
||||
|
||||
<ul>
|
||||
<li><p>Left, right, up and down <strong>arrow keys</strong>: Move that direction.</p></li>
|
||||
<li><p>‘q’ (and ‘Q’): Quit the game.</p></li>
|
||||
<li><p>Space (<code>' '</code>): 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 <code>getch()</code> 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).</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h1>3. <a name="gameplay" href="#toc">Gameplay</a></h1>
|
||||
|
||||
<p>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 <a href="#colours">colour
|
||||
selection</a>. You can also jump to <a href="#modes">gameplay modes</a> or <a href="#variables">game
|
||||
variables</a>.</p>
|
||||
|
||||
<p>The bug colour by default is white; the snake head colour is red and the snake
|
||||
body colour is green. The walls are cyan.</p>
|
||||
|
||||
<h2><a name="initial" href="#toc">Gameplay: The initial screen</a></h2>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> X:24/49 Y:8/16 S:5/658 B:0
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# + #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<ul>
|
||||
<li><p>The snake (<code>+</code>) is at (24),(8). The bug char is <code>*</code> and the wall char is
|
||||
<code>#</code>. When the snake moves the head will be an arrow facing the direction it
|
||||
is moving; the body is ‘o’.</p></li>
|
||||
<li><p>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.</p></li>
|
||||
<li><p>The snake size is (5): but until you start to move it’s technically 1 (even
|
||||
if you set <strong>SIZE=0</strong> 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.</p></li>
|
||||
<li><p>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.</p></li>
|
||||
<li><p>The number of bugs eaten so far is 0.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="playing" href="#toc">Gameplay: Playing the game</a></h2>
|
||||
|
||||
<pre><code> X:39/49 Y:8/16 S:5/658 B:0
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# oooo> #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> X:39/49 Y:9/16 S:5/658 B:0
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# oooo #
|
||||
# v #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<p>Now you see that the snake is going down and in one move the bug will be eaten.
|
||||
Let’s do that:</p>
|
||||
|
||||
<pre><code> X:36/49 Y:10/16 S:10/658 B:1
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ^ o #
|
||||
# oooo #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h1><a name="walls" href="#toc">Gameplay: Walls</a></h1>
|
||||
|
||||
<p>By default walls are passable (<strong>WALLS=1</strong>). Let’s get to full size and go
|
||||
through the top wall:</p>
|
||||
|
||||
<pre><code> X:36/49 Y:15/16 S:10/658 B:1
|
||||
##################################################
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# * o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ^ #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> X:36/49 Y:11/16 S:10/658 B:1
|
||||
##################################################
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# * o #
|
||||
# o #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ^ #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>When you specify <strong>WALLS=0</strong> 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):</p>
|
||||
|
||||
<pre><code> X:20/49 Y:2/16 S:150/658 B:0
|
||||
##################################################
|
||||
# ^ #
|
||||
# o #
|
||||
# o * #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# ooooo #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<p>If I continue going up I will see:</p>
|
||||
|
||||
<pre><code> OUCH!
|
||||
X:20/49 Y:1/16 S:150/658 B:0
|
||||
</code></pre>
|
||||
|
||||
<h1><a name="cannibalism" href="#toc">Gameplay: Cannibalism</a></h1>
|
||||
|
||||
<p>By default cannibalism is disabled (<strong>CANNIBAL=0</strong>) so if you run into yourself it might look
|
||||
something like:</p>
|
||||
|
||||
<pre><code> X:45/49 Y:10/16 S:10/658 B:1
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ooooo #
|
||||
# ^ o #
|
||||
# ooo #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> OW!
|
||||
X:47/49 Y:10/16 S:10/658 B:1
|
||||
</code></pre>
|
||||
|
||||
<p>But <strong>CANNIBAL=1</strong> 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:</p>
|
||||
|
||||
<pre><code> 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 #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<p>I’ll go back through myself now:</p>
|
||||
|
||||
<pre><code> 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 #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> 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 #
|
||||
##################################################
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>An example of extreme cannibalism is in the <a href="cannibalism.log">cannibalism.log</a> 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:</p>
|
||||
|
||||
<pre><code> 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
|
||||
</code></pre>
|
||||
|
||||
<p>The final example has the snake inside itself.</p>
|
||||
|
||||
<h1><a name="shedding" href="#toc">Gameplay: Shedding (stretching)</a></h1>
|
||||
|
||||
<p>This feature will make you grow by the value of <strong>SHEDS</strong> for every <strong>SHED</strong>
|
||||
movements (the counter isn’t incremented when you eat a bug). Basically growing
|
||||
without eating a bug (stretching would be better name here).</p>
|
||||
|
||||
<h1><a name="winning" href="#toc">Gameplay: Winning</a></h1>
|
||||
|
||||
<p>If you ever get to the <strong>MAXSIZE</strong> 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:</p>
|
||||
|
||||
<pre><code> SIZE=-1 ./prog
|
||||
YOU WIN!
|
||||
X:24/49 Y:8/16 S:658/658 B:0
|
||||
</code></pre>
|
||||
|
||||
<p>Observe that the size isn’t the default 997: because the screen size is too
|
||||
small for that value (see <a href="terminals.md">terminals.md</a>).</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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!</p>
|
||||
|
||||
<h1><a name="quitting" href="#toc">Gameplay: Quitting</a></h1>
|
||||
|
||||
<p>If you wish to quit you can hit ‘q’ (case-insensitive). For example:</p>
|
||||
|
||||
<pre><code> X:24/49 Y:8/16 S:5/658 B:0
|
||||
</code></pre>
|
||||
|
||||
<h1>4. <a name="modes" href="#toc">Gameplay modes</a></h1>
|
||||
|
||||
<p>Here I list a number of different modes of play. In the <a href="bugs.md">bugs.md</a>
|
||||
(<a href="bugs.html">bugs.html</a>) 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.</p>
|
||||
|
||||
<p>The <a href="play.sh">play.sh</a> script sets up some of these automatically; I describe it after
|
||||
the modes below.</p>
|
||||
|
||||
<h2><a name="warning" href="#toc">Photosensitive epilepsy/Stimulation overload trigger warnings</a></h2>
|
||||
|
||||
<p>If you have <strong>photosensitive epilepsy please be careful</strong> especially with low values
|
||||
for both <strong>WAIT</strong> and <strong>EVADE</strong>. It appears that the <a href="https://www.epilepsysociety.org.uk/photosensitive-epilepsy#.Xjgpwi2ZOgQ">number of hertz (flashes)
|
||||
per second triggering seizures</a> is wide but depending on the variables it
|
||||
easily can be in the range.</p>
|
||||
|
||||
<p>There are different patterns and lights flashing at different speeds so please
|
||||
exercise caution. This could trigger seizures and <strong>it might also be too much
|
||||
stimulation for some people.</strong></p>
|
||||
|
||||
<p><strong>Please be careful of these if these types of things have ever affected you or if
|
||||
you have any form of epilepsy. Thank you.</strong></p>
|
||||
|
||||
<h2><a name="drawing" href="#toc">Gameplay mode: Drawing / Practice mode</a></h2>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> WAIT=-1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> WAIT=-1 CANNIBAL=1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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):</p>
|
||||
|
||||
<pre><code> SIZE=50 CANNIBAL=1 WAIT=-1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>Do note that although you’re a bigger size you still grow one movement at a
|
||||
time.</p>
|
||||
|
||||
<p>Okay but then if you get too many bugs the drawing will be over. If this proves
|
||||
to be a problem simply do:</p>
|
||||
|
||||
<pre><code> SIZE=100 CANNIBAL=1 WAIT=-1 GROW=0 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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</p>
|
||||
|
||||
<pre><code> MAXSIZE=-1
|
||||
</code></pre>
|
||||
|
||||
<p>Which I’ve done in the <a href="play.sh">play.sh</a> script.</p>
|
||||
|
||||
<p>I discuss how this mode works in <a href="spoilers.markdown">spoilers.markdown</a>.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<pre><code> 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>
|
||||
</code></pre>
|
||||
|
||||
<h2><a name="auto" href="#toc">Gameplay mode: Computer playing / Automatic mode (Photosensitive epilepsy/Stimulation overload trigger)</a></h2>
|
||||
|
||||
<p><strong>Photosensitive epilepsy/stimulation overload trigger warning:</strong>
|
||||
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.</p>
|
||||
|
||||
<p>If you’re still here you can create this effect like:</p>
|
||||
|
||||
<pre><code> WAIT=0 WALLS=1 CANNIBAL=1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h3><a name="auto-variations" href="#toc">Computer player variations</a></h3>
|
||||
|
||||
<p>Here’s how to make the bug move every time the snake moves:</p>
|
||||
|
||||
<pre><code> CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<h4>Help the computer win fairly quickly</h4>
|
||||
|
||||
<p>If you want to see the game ‘win’ try something like:</p>
|
||||
|
||||
<pre><code> CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 MAXSIZE=10 ./prog
|
||||
</code></pre>
|
||||
|
||||
<h4>Negative growth (Shrink) Automatic mode</h4>
|
||||
|
||||
<p>Here’s a fun one I just thought of (a long time after these other modes were
|
||||
thought of):</p>
|
||||
|
||||
<pre><code> WAIT=0 EVADE=1 GROW=-1 SIZE=9 MAXSIZE=10 CANNIBAL=1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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
|
||||
<a href="play.sh">play.sh</a> script.</p>
|
||||
|
||||
<h4>Adjusting the time/speed</h4>
|
||||
|
||||
<p>Of course you can also do something like:</p>
|
||||
|
||||
<pre><code> WAIT=5 WALLS=1 CANNIBAL=1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>Which although might not seem like it is significantly slower.</p>
|
||||
|
||||
<h4>Moving the snake about to create patterns</h4>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<h4>Other ideas</h4>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>How long will it take for the snake to run into itself? For instance by doing:</p>
|
||||
|
||||
<pre><code> WAIT=0 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>On my 13" MacBook Pro at the default settings going horizontally the snake ran
|
||||
into itself at:</p>
|
||||
|
||||
<pre><code> OW!
|
||||
X:57/156 Y:20/41 S:155/997 B:30
|
||||
</code></pre>
|
||||
|
||||
<p>What if you set the size to a high value? The lowest? There are bound to be
|
||||
other games to play with this feature!</p>
|
||||
|
||||
<h2><a name="grow-shrink" href="#toc">Gameplay mode: Grow-Shrink mode (Positive and Negative Winning)</a></h2>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> SIZE=150 SHEDS=-5 GROW=10 SHED=50 MAXSIZE=250 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>The <a href="crazy.log">crazy.log</a> file has several screen dumps with this idea.</p>
|
||||
|
||||
<p>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 <a href="play.sh">play.sh</a>
|
||||
also has this mode:</p>
|
||||
|
||||
<pre><code> SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>Obviously there are many other variations. The <a href="play.sh">play.sh</a> 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).</p>
|
||||
|
||||
<h2><a name="hypnotic" href="#toc">Hypnotic / Sleepy mode (<strong>Photosensitive epilepsy/Stimulation overload trigger</strong>)</a></h2>
|
||||
|
||||
<p><strong>Photosensitive epilepsy/stimulation overload trigger warning:</strong>
|
||||
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 <strong>EVADE=1</strong> every 231ms there will be a flash in addition to the
|
||||
snake moving too.</p>
|
||||
|
||||
<p>Anyway this might sound absurd but it can be somewhat hypnotic by doing:</p>
|
||||
|
||||
<pre><code> EVADE=1 CANNIBAL=1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>And just moving the snake about not trying to catch any bugs - just let whatever
|
||||
happens happen.</p>
|
||||
|
||||
<h2><a name="stim" href="#toc">Gameplay mode: Stimulation / Calming mode</a></h2>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> GROW=0 CANNIBAL=1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<h2><a name="expansibility" href="#toc">Gameplay mode: Expansibility</a></h2>
|
||||
|
||||
<p>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 <code>timeout()</code> function works for
|
||||
example.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h1>5. <a name="scripts" href="#toc">Scripts</a></h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h2><a name="colours" href="#toc">Colours selection: snake-colours</a></h2>
|
||||
|
||||
<p>To do this use the <a href="snake-colours">snake-colours</a> script like so:</p>
|
||||
|
||||
<pre><code> ./snake-colours
|
||||
</code></pre>
|
||||
|
||||
<p>If you want to pass in specific variables you can do that too e.g.:</p>
|
||||
|
||||
<pre><code> CANNIBAL=1 ./snake-colours
|
||||
</code></pre>
|
||||
|
||||
<p>The script will prompt you for the colour of the walls, snake head, body and the
|
||||
bug.</p>
|
||||
|
||||
<h2><a name="preset" href="#toc">Automate the above gameplay modes</a></h2>
|
||||
|
||||
<p>The <a href="play.sh">play.sh</a> 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.</p>
|
||||
|
||||
<p>To use you can do something like:</p>
|
||||
|
||||
<pre><code> ./play.sh
|
||||
</code></pre>
|
||||
|
||||
<p>Or to make it so walls are an obstacle:</p>
|
||||
|
||||
<pre><code> WALLS=0 ./play.sh
|
||||
</code></pre>
|
||||
|
||||
<h1>6. <a name="variables" href="#toc">Notes about some of the game variables</a></h1>
|
||||
|
||||
<p>The game variables can be used for a variety of things including different
|
||||
gameplay modes (as shown above) but here are some notes about a few of them.</p>
|
||||
|
||||
<h2><a name="wait" href="#toc">WAIT: Snake speed</a></h2>
|
||||
|
||||
<p>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!</p>
|
||||
|
||||
<h2><a name="evade" href="#toc">EVADE: Bug evasion frequency</a></h2>
|
||||
|
||||
<p>For every <strong>EVADE</strong> 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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>This can help you get out of a trap but it can also sometimes make it harder.</p>
|
||||
|
||||
<h2><a name="sizes" href="#toc">SIZE / MAXSIZE: Initial / Max snake sizes</a></h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h2><a name="growth" href="#toc">GROW / SHEDS : Growth / Shedding sizes</a></h2>
|
||||
|
||||
<p>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’.</p>
|
||||
|
||||
<h1>7. <a name="conclusions" href="#toc">Conclusion (and inspirational words for everyone)</a></h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>Thank you for whatever level of attention you felt you could or wanted to give
|
||||
and enjoy it in whatever way you see fit!</p>
|
||||
|
||||
<p><strong>Much more importantly is that Snake aside I hope I have demonstrated how with
|
||||
the imagination and creativity almost anything is possible.</strong> This is something
|
||||
<strong>that applies in our world in every way and <em>everyone</em> can do something amazing if
|
||||
they believe in themselves!</strong> I would have never thought this the case for me
|
||||
years ago but I know it’s true now. <strong>Believe in yourself. Always.</strong></p>
|
||||
<BR>
|
||||
<HR>
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2020,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
@@ -229,7 +229,7 @@ function play()
|
||||
|
||||
while true; do
|
||||
menu
|
||||
read -rp "Make your selection (0 - 7 or any other key to exit): " mode
|
||||
read -rp "Make your selection (0 - 16 or any other key to exit): " mode
|
||||
|
||||
case "${mode}" in
|
||||
0) # Drawing mode 0
|
||||
|
||||
@@ -1,970 +0,0 @@
|
||||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.2.2">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=utf-8"> <link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<CENTER>
|
||||
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
|
||||
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
|
||||
<div id="bar">
|
||||
<ul>
|
||||
<li><a href="../index.html">About the 27th IOCCC</a></li>
|
||||
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
|
||||
<li><a href="/index.html">IOCCC home</a></li>
|
||||
<li><a href="/winners.html">List of All Winners</a></li>
|
||||
<li><a href="/judges.html">The Judges</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<P><FONT size="6"><B>Supplemental Info</B></FONT></P>
|
||||
</CENTER>
|
||||
|
||||
|
||||
<h1>Introduction (SPOILER ALERT)</h1>
|
||||
|
||||
<p>In the <a href="gameplay.md">gameplay.md</a> (<a href="gameplay.html">gameplay.html</a>) 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.</p>
|
||||
|
||||
<p>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?</p>
|
||||
|
||||
<p><a name="toc"></a></p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="#works">How does it work?</a></p></li>
|
||||
<li><p><a href="#movement">How does the snake movement work?</a></p></li>
|
||||
<li><p><a href="#manual-automatic">Drawing (manual) and computer playing (automatic) modes</a></p></li>
|
||||
<li><p><a href="#collision">Collision detection</a></p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="#cannibalcollision">Cannibal collision detection</a></p></li>
|
||||
<li><p><a href="#resizing">Collision detection when resizing the window of the game</a></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a href="#obfuscation">Obfuscation</a></p></li>
|
||||
<li><p><a href="#skinning">Skinning the snake (i.e. decreasing the iocccsize)</a></p></li>
|
||||
<li><p><a href="#size">A few more interesting size optimisations</a></p></li>
|
||||
</ul>
|
||||
|
||||
<h1><a name="works" href="#toc">How does it work?</a></h1>
|
||||
|
||||
<p>The gameplay I have already described but this explains the way things are
|
||||
actually done in more detail.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>Next the max size of the snake is determined: if <code>MAXSIZE</code> 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.</p>
|
||||
|
||||
<p>Then the arrays are allocated; if either return NULL curses is ended, an error
|
||||
message (‘memory error’) is printed and return 1.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h1><a name="movement" href="#toc">How does the snake movement work?</a></h1>
|
||||
|
||||
<p>The way the snake looks to move is that every time the snake moves the last
|
||||
position (the tail) is replaced with a space (<code>' '</code>). If the snake eats a bug
|
||||
then the snake will get bigger in the next <code>N</code> 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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h1><a name="manual-automatic" href="#toc">Drawing (manual) and computer playing (automatic) modes</a></h1>
|
||||
|
||||
<p>How do these modes work? The <code>timeout()</code> 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).</p>
|
||||
|
||||
<h1><a name="collision" href="#toc">Collision detection</a></h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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! :)</p>
|
||||
|
||||
<h2><a name="cannibalcollision" href="#toc">Cannibal collision detection</a></h2>
|
||||
|
||||
<p>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)!</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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
|
||||
<em>is</em> unnatural!</p>
|
||||
|
||||
<p>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!</p>
|
||||
|
||||
<p>Choose your poison. Or rather your venom.</p>
|
||||
|
||||
<h2><a name="resizing" href="#toc">Collision detection when resizing the window of the game</a></h2>
|
||||
|
||||
<p>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?</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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? :)</p>
|
||||
|
||||
<h1><a name="obfuscation" href="#toc">Obfuscation</a></h1>
|
||||
|
||||
<ul>
|
||||
<li><p>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:</p>
|
||||
|
||||
<pre><code> attroff(COLOR_PAIR(L));
|
||||
</code></pre>
|
||||
|
||||
<p> When you can have instead:</p>
|
||||
|
||||
<pre><code> attroff(m(PAIR(L)));
|
||||
</code></pre>
|
||||
|
||||
<p> 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 <code>cpp</code> but it does make for more
|
||||
reading otherwise (depending on how you look at it maybe less?).</p>
|
||||
|
||||
<p> It also helps save iocccsize bytes (but not as many as it used to!).</p></li>
|
||||
<li><p>What is this block of code?</p>
|
||||
|
||||
<pre><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 */
|
||||
</code></pre>
|
||||
|
||||
<p> There are several things going on here but I’ll focus on the main one here and
|
||||
leave the others to their own: the <code>F</code> macro and the associated <code>d</code> macro are
|
||||
here important.</p>
|
||||
|
||||
<p> In addition to saving many bytes this also makes for interesting reading.
|
||||
What this actually is doing is checking for environmental variables. If
|
||||
<code>getenv()</code> does not return NULL then strtoul() is called on it (except for
|
||||
the one that clearly shows strtol()).</p>
|
||||
|
||||
<p> There are other things going on (below).</p>
|
||||
|
||||
<p> Now it might not defeat the cpp but can you tell me what this is even with the
|
||||
cpp?</p>
|
||||
|
||||
<pre><code> f((a)((*y-2)*(y[-2]-2)),g);
|
||||
</code></pre>
|
||||
|
||||
<p> The cpp might get it closer to what you might expect in a normal program but I
|
||||
refer to the array offsets (below also).</p></li>
|
||||
<li><p>Stringification: there isn’t a single <code>"</code> in the source code! The <code>F</code> macro
|
||||
uses the macro <code>Z</code> which does the real work. At first <code>F</code> was only <code>getenv</code> but
|
||||
I changed it to use stringification. Following the creation of the <code>Z</code> 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 <code>F</code> macro).</p>
|
||||
|
||||
<p> As for the Z() macro it means that I could remove <code>"</code>s; for example:</p>
|
||||
|
||||
<pre><code> #define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n), Y, y[-2], X,*y,A,g, c);
|
||||
</code></pre>
|
||||
|
||||
<p> Which as I have discussed elsewhere is the entire set of parameters to both
|
||||
<code>mvprintw()</code> and <code>printf()</code> plus the end of the function call (i.e. <code>);</code>.</p>
|
||||
|
||||
<p> 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.</p></li>
|
||||
<li><p>Another use of the <code>Z</code> macro is this curious line:</p>
|
||||
|
||||
<pre><code> static char s[]=Z(; +<>^v);
|
||||
</code></pre>
|
||||
|
||||
<p> 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 <code>;</code> followed by <code></code>, <code>+</code>, <code><</code>, <code>></code>, <code>^</code>, <code>v</code>?</p>
|
||||
|
||||
<p> A very minor factor is that the character ‘v’ is there and it’s (<code>v</code>) also
|
||||
used as a macro (well, define) ‘might’ be of something to some people. Or
|
||||
programs maybe? For instance using in vim <code>*</code> on the <code>v</code> in that array and
|
||||
it takes you other instances of <code>v</code>: as in <code>\<v\></code>: which happens to be
|
||||
something else entirely. That itself however might or might not be
|
||||
significant for this instance!</p>
|
||||
|
||||
<p> 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 <code>Z()</code>. I will also be returning to this one
|
||||
again.</p>
|
||||
|
||||
<p> Another example is using the <code>E()</code> function e.g.:</p>
|
||||
|
||||
<pre><code> E(Z(YOU WIN!));
|
||||
</code></pre>
|
||||
|
||||
<p> 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.</p>
|
||||
|
||||
<p> Some beautifiers don’t like this.</p></li>
|
||||
<li><p>There’s an <code>#undef</code> following an <code>if</code> in a way to draw attention from what to
|
||||
do if the if is true.</p></li>
|
||||
<li><p>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).</p>
|
||||
|
||||
<p> When quit is requested it falls into pause. But then pause falls into the
|
||||
default (so no recognised key is pressed) which does <code>x = 0;</code>. Outside the
|
||||
switch block there’s <code>if (x) P = 0;</code>. 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 <code>Q = 1;</code> (or actually <code>l</code>) it doesn’t matter if
|
||||
<code>P || !P</code> because Q will also jump to the top of the ‘loop’ only to exit
|
||||
since the condition no longer is true.</p>
|
||||
|
||||
<p> 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 <code>x =
|
||||
0;</code> 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.</p>
|
||||
|
||||
<p> 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) <em>outside the switch</em> 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!</p></li>
|
||||
<li><p>On the note of pausing there’s at least one instance of removing <code>if..else</code>
|
||||
(besides those in e.g. environmental variable processing) that’s curious: I
|
||||
converted this:</p>
|
||||
|
||||
<pre><code> if (!P) P = 1;
|
||||
else P = 0;
|
||||
</code></pre>
|
||||
|
||||
<p> To this:</p>
|
||||
|
||||
<pre><code> (!P && (P = 1))||(P=0);
|
||||
</code></pre></li>
|
||||
<li><p>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 <code>goto</code> (there used to be two pairs in main()).</p></li>
|
||||
<li><p>And on that note: makes use of the ugly <code>goto</code> 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.</p></li>
|
||||
<li><p>Why do I check for <code>Q || P</code> and then goto x only to then check for <code>!Q && !D</code>
|
||||
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.</p></li>
|
||||
<li><p>Uses an unnamed array (compound literal) for several different game variables.
|
||||
The pointer to the first element is defined like <code>int *j</code>:</p>
|
||||
|
||||
<pre><code> static int Y,X,*j = (int[8]){231,0}, *U, *V, *e, *n, Q, P,x,*y,l=4,*D;
|
||||
</code></pre>
|
||||
|
||||
<p> Does the 231 seem familiar? It should: it’s the default key delay for the
|
||||
<code>timeout()</code> call (which I will return to again). The rest are 0 default. But
|
||||
what about <code>j</code>? Is it even used? Actually in main:</p>
|
||||
|
||||
<pre><code> y = j+3;
|
||||
</code></pre>
|
||||
|
||||
<p> But aside from that <code>j</code> is not used. However…</p></li>
|
||||
<li><p>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.</p>
|
||||
|
||||
<p> Can you honestly tell me that this is easy to follow?</p>
|
||||
|
||||
<pre><code> 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;
|
||||
}
|
||||
/* ... */
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<p> That’s not the only place negative offsets occur! Observe the ternary operators
|
||||
there too.</p>
|
||||
|
||||
<p> I’ll go back to the F() macro and in particular what follows one of them:</p>
|
||||
|
||||
<pre><code> g d g = f((a)((*y-2)*(y[-2]-2)),g);
|
||||
</code></pre>
|
||||
|
||||
<p> To parse that at the very least you have to know that <code>y</code> points to <code>j + 3</code>.
|
||||
Then you have to know that <code>j</code> 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 <code>y</code> is. Then once you have that
|
||||
figured out you need to consider the negative offsets to <code>y</code> (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:</p>
|
||||
|
||||
<pre><code> (*y-2) * (y[-2]-2])
|
||||
</code></pre>
|
||||
|
||||
<p> …about? An offset of -2 and subtract -2 from that. Multiply that by the <code>*y</code>
|
||||
(which is <code>j[3]</code>) - 2.</p>
|
||||
|
||||
<p> But why is there a <code>g d g =</code> when the other lines only have the variable (or
|
||||
location) and a d? (Excepting the one that doesn’t refer to <code>d</code>.)</p></li>
|
||||
<li><p>On the confusing names etc.: the <code>getmaxyx()</code> function gets the maximum Y, X
|
||||
dimensions. Now in the first call in main() I have the code and tests following:</p>
|
||||
|
||||
<pre><code> getmaxyx(v, *y, y[-2]);
|
||||
--*y; --y[-2];
|
||||
if (y[-2] < 9 || *y < 9)
|
||||
return E(Z(term too small));
|
||||
</code></pre>
|
||||
|
||||
<p> Clearly the max x must be stored in <code>*y</code> and the max y must be stored in ..
|
||||
<code>y[-2]</code>. 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 <code>x</code> is possibly confusing even without the negative offset.</p>
|
||||
|
||||
<p> 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?
|
||||
:)</p>
|
||||
|
||||
<p> 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!</p></li>
|
||||
<li><p>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 <code>X</code> and <code>Y</code> are only the snake head but at that point you
|
||||
still have to figure out the array confusions. Also if you’re tired <code>V</code> could
|
||||
easily be read as <code>Y</code> and I have a lot of fun with <code>V</code> 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.</p></li>
|
||||
<li><p>More confusion with variable names: If you notice the <code>int *U, *V</code> they are
|
||||
also part of the compound literal: that is they point into it:</p>
|
||||
|
||||
<pre><code> U=y+2; V=U+1;
|
||||
</code></pre>
|
||||
|
||||
<p> Except that these two are done in two different places: away from the
|
||||
assignment of <code>y</code> to remove them further away from the contexts they are
|
||||
used in.</p>
|
||||
|
||||
<p> 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 <code>y</code> ‘array’. I do blank out the old
|
||||
location at <code>*U, *V</code> but then assign the new location differently. Then in
|
||||
main() I draw it at <code>*U, *V</code> and also check for the bug being eaten there
|
||||
too.</p></li>
|
||||
<li><p>There’s another array that holds a variety of data.</p>
|
||||
|
||||
<pre><code> static k p[5]={1,0},W=300;
|
||||
</code></pre>
|
||||
|
||||
<p> It holds the following information (but not necessarily in this order):</p>
|
||||
|
||||
<pre><code> WALLS
|
||||
CANNIBAL
|
||||
SHED
|
||||
SHEDS
|
||||
EVADE
|
||||
</code></pre>
|
||||
|
||||
<p> 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!).</p></li>
|
||||
<li><p>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 <code>splint</code> seems to have a parse error on the declaration though I
|
||||
don’t know why.</p></li>
|
||||
<li><p>On arrays/pointers in general I also use e.g. <code>3[p]</code> and <code>p[3]</code> (there are
|
||||
many other examples that I have already shown).</p></li>
|
||||
<li><p>Expanding on referring to the same thing in more than one way take a look at:</p>
|
||||
|
||||
<pre><code> 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;
|
||||
</code></pre>
|
||||
|
||||
<p> 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 <code>1</code>; the
|
||||
others are the letter <code>l</code>. 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?).</p>
|
||||
|
||||
<p> 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
|
||||
<code>l</code>: 4.</p>
|
||||
|
||||
<p> 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.</p>
|
||||
|
||||
<p> But doing it this way means you have to first of all know that there’s the
|
||||
variable <code>l</code> (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:</p>
|
||||
|
||||
<pre><code> V[1] = 1; V[1] = 2; ...
|
||||
</code></pre>
|
||||
|
||||
<p> Etc.</p></li>
|
||||
<li><p>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 <code>h</code> and it says
|
||||
whether to call <code>endwin()</code> or not in as in some cases E() is called more than
|
||||
once. Now instead of setting the variable <code>h</code> to 1 I set it to <code>l</code>: 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 <code>Q</code> which
|
||||
I also set to <code>l</code>.</p></li>
|
||||
<li><p>I also use <code>*y</code> as a boolean. If you observe that I set x to <code>*y</code> (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. <code>*y</code> 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
|
||||
<code>!*y</code> which I do elsewhere.</p></li>
|
||||
<li><p>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.</p></li>
|
||||
<li><p>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?</p></li>
|
||||
<li><p>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:</p>
|
||||
|
||||
<pre><code> 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
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<p> 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.</p>
|
||||
|
||||
<p> I have the <code>!</code> of a <code>||</code> 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?).</p>
|
||||
|
||||
<p> 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.</p>
|
||||
|
||||
<p> 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 <code>y</code> but never <code>x</code> (that variable is unrelated
|
||||
and not even in this part of the code).</p></li>
|
||||
<li><p>The function <code>B()</code> ends with a <code>goto</code>. Why? It’s also another place where
|
||||
there’s at least one negative offset.</p></li>
|
||||
<li><p>A note on the many <code>#define</code>s in my entry. You say you dislike them:</p>
|
||||
|
||||
<pre><code> 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.
|
||||
</code></pre>
|
||||
|
||||
<p> 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 <code>#define</code>s. One of the <code>#define</code>s that
|
||||
saves a significant number of bytes is of course <code>J</code>: I use that twice and
|
||||
it would be a huge burden to include it twice!</p>
|
||||
|
||||
<p> At the same time I have removed some <code>#define</code>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).</p></li>
|
||||
<li><p>Going back to the curious <code>static char s[]=Z(; +<>^v);</code>: 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:</p>
|
||||
|
||||
<pre><code> 7 & 0
|
||||
7 & 1
|
||||
7 & 2
|
||||
7 & 3
|
||||
7 & 4
|
||||
7 & 5
|
||||
7 & 6
|
||||
7 & 7
|
||||
</code></pre>
|
||||
|
||||
<p> What is the result of each operation? Quite simply it’s the number itself!
|
||||
How does this relate to the <code>s</code> 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:</p>
|
||||
|
||||
<pre><code> q X, Y, s[*D+2&(1<<3)-!Q]);
|
||||
</code></pre>
|
||||
|
||||
<p> We KNOW that at this place <code>Q</code> is 0 so the <code>!Q</code> has to be 1. Now <code>1 << 3</code> is 8. Therefore</p>
|
||||
|
||||
<pre><code> (1 << 3) - !Q == 7
|
||||
</code></pre>
|
||||
|
||||
<p> But what’s <code>*D</code>? 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</p>
|
||||
|
||||
<pre><code> *D&(1<<3)-!Q
|
||||
</code></pre>
|
||||
|
||||
<p> …refers to <code>*D</code>. 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 <code>+2</code> it adjusts the index to be the correct value in
|
||||
order to show the proper index of the char array.</p>
|
||||
|
||||
<p> 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 <code>N & 7</code> is <code>N</code> (which might not be
|
||||
something everyone realises). Obviously you need to know that (1 << 3) is 8
|
||||
in order to get the final <code>*D & 7</code>.</p>
|
||||
|
||||
<p> You furthermore need to know that <code>*D</code> will always be in the range <code>0..4</code>
|
||||
which means that <code>*D & 7</code> will always be in the range <code>0..4</code> (If I were to
|
||||
have added a <code>& 7</code> 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!</p>
|
||||
|
||||
<p> But there’s another trick here: there’s never a direct assignment to <code>*D</code>:
|
||||
<code>D</code> is set to <code>1 + V</code> and <code>*D</code> is never touched directly: it’s all through
|
||||
<code>1[V]</code>. The references to directions i.e. <code>KEY_LEFT</code> etc. and also the
|
||||
switch() to see how to modify X/Y are all done through the <code>V</code> pointer. But
|
||||
then what is <code>V</code> anyway? It’s <code>U + 1</code>; and <code>U</code> happens to be <code>y + 2</code>. But
|
||||
<code>y</code> happens to be <code>j + 3</code>. Of course <code>j</code> 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)!</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h1>Obfuscation in prog.3.c and prog.3-j.c</h1>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<ul>
|
||||
<li><p>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 <code>h</code> and it says whether to call <code>endwin()</code> or not as in
|
||||
some cases E() is called more than once. Now instead of setting the variable <code>h</code>
|
||||
to 1 I set it to <code>*y</code>. Now as you can see <code>*y</code> starts as a NULL pointer; this is
|
||||
set to the compound literal <code>j</code> + 3. This in turn is what LINES is (number of
|
||||
lines). So <code>y = j + 3;</code> and <code>j</code> 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 <code>Q</code> I set it to
|
||||
<code>l</code>. But then..what is <code>l</code>?</p></li>
|
||||
<li><p>In fact <code>l</code> is assigned a value 4 via a compound literal. It’s declared at the
|
||||
top of the code and then in main() assigned like: <code>l = ++(int) { 3 } ;</code> which
|
||||
equates to 4. I think that’s pretty cool!</p></li>
|
||||
<li><p>What is this? <code>for(I=0; A&&I<A-(A-A||A); ++I)</code> In fact the <code>A-(A-A||A)</code> is
|
||||
equivalent to <code>A-1</code>: <code>A</code> here is always > 0 so <code>A-A</code> is 0; however because <code>A</code>
|
||||
is non-zero the expression <code>A-A||A</code> is equivalent to <code>0 || A</code> and since A is
|
||||
non-zero we know that the value is <code>1</code> and thus it’s <code>A - 1</code>! 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 <code>I < A - 1</code> but the <code>1</code>
|
||||
is calculated by subtracting from <code>A</code> the value of subtracting <code>A</code> from itself
|
||||
<code>|| A</code> and <code>A</code> is always non-zero (as the condition says) which means it’s
|
||||
<code>A - 1</code>!</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>There might be more things that differ but those are the significant ones.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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 <code>#undef</code> 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).</p>
|
||||
|
||||
<p>The following were intentional:</p>
|
||||
|
||||
<ul>
|
||||
<li><p>53 lines.</p></li>
|
||||
<li><p>The number of lines per vertical block (3, 5, 3, 11, 7, 1, 1, 5, 7).</p></li>
|
||||
<li><p>Number of horizontal blocks (5)</p></li>
|
||||
<li><p>Number of vertical blocks (9)</p></li>
|
||||
<li><p>iocccsize 2053.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>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):</p>
|
||||
|
||||
<ul>
|
||||
<li>Vertical column #1: 5, 22</li>
|
||||
<li>Vertical column #2: 25, 41</li>
|
||||
<li>Vertical column #3: 49, 64</li>
|
||||
<li>Vertical column #4: 73, 90</li>
|
||||
<li>Vertical column #5: 97, 120</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Furthermore based on the length of each C preprocessor directive (the
|
||||
<code>#define</code>s, the <code>#includes</code>, the <code>#undef</code>) 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.</p>
|
||||
|
||||
<p>Most of the primes above were intentional.</p>
|
||||
|
||||
<h1><a name="skinning" href="#toc">Skinning the snake (i.e. decreasing the iocccsize)</a></h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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
|
||||
<code>if</code>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.</p>
|
||||
|
||||
<p>Obviously a more significant one is <code>#define q mvprintw</code>: 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!</p>
|
||||
|
||||
<p>Another thing that reduced a lot of bytes - 34 to be exact - is using the
|
||||
<code>mvvline()</code> and <code>mvhline()</code> ncurses functions rather than use three for loops to
|
||||
draw the walls.</p>
|
||||
|
||||
<p>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 <code>{}</code> 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.</p>
|
||||
|
||||
<p>One of these optimisations saved four bytes simply by taking advantage of the
|
||||
value of a loop iterator after the loop. The loop is:</p>
|
||||
|
||||
<pre><code> for (I = 0; A && I < A - 1; ++I)
|
||||
</code></pre>
|
||||
|
||||
<p>However after the loop I had this:</p>
|
||||
|
||||
<pre><code> A > 1 && q(n[A - 1],e[A - 1], 'o');
|
||||
</code></pre>
|
||||
|
||||
<p>When I was considering moving that line to before the loop it occurred to me
|
||||
that as long as <code>A > 0</code> then <code>A - 1 == I</code> after the loop. I still had to check
|
||||
for <code>A > 1</code> but I could refer to just <code>I</code> instead of <code>A - 1</code>!</p>
|
||||
|
||||
<p>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 <code>calloc()</code>
|
||||
failed I called <code>abort()</code> and before that if initialising ncurses failed I also
|
||||
called <code>abort()</code> and did not report any errors in either event but I do now).</p>
|
||||
|
||||
<h1><a name="size" href="#toc">A few more interesting size optimisations</a></h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>First, the function that turns on colours looked like:</p>
|
||||
|
||||
<pre><code> if (h) attron(m(PAIR(L)));
|
||||
else attroff(m(PAIR(L)));
|
||||
</code></pre>
|
||||
|
||||
<p>But I thought is that else actually needed? If I were to switch the order so
|
||||
that the <code>attroff()</code> is called first then I could just do an <code>if (h)</code> -
|
||||
therefore getting rid of the <code>else</code>! But then I thought why not do what I’ve
|
||||
done elsewhere? I had:</p>
|
||||
|
||||
<pre><code> attroff(m(PAIR(L)));
|
||||
if (h) attron(m(PAIR(L)));
|
||||
</code></pre>
|
||||
|
||||
<p>But I then saved an extra byte by making it:</p>
|
||||
|
||||
<pre><code> attroff(m(PAIR(L)));
|
||||
h && attron(m(PAIR(L)));
|
||||
</code></pre>
|
||||
|
||||
<p>That saved two bytes.</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> if (V && U && o) { S(N); b(1); }
|
||||
</code></pre>
|
||||
|
||||
<p>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 <code>V</code> or <code>U</code>
|
||||
necessary? I gave it a look over and it occurred to me: the only time B() is
|
||||
called with <code>1</code> (thus <code>o</code> is 1 so the if is true) was if the bug actually is
|
||||
caught. That means I could remove the <code>V && U &&</code> part of the if! Thus it became
|
||||
instead:</p>
|
||||
|
||||
<pre><code> if (o) { S(N); b(1); }
|
||||
</code></pre>
|
||||
|
||||
<p>Then this</p>
|
||||
|
||||
<pre><code> !o && V && U && q U,V,' ');
|
||||
</code></pre>
|
||||
|
||||
<p>…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!</p>
|
||||
|
||||
<p>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?</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> !o && D && q *U,*V,' ');
|
||||
</code></pre>
|
||||
|
||||
<p>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 <code>!o</code>: 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:</p>
|
||||
|
||||
<pre><code> !o && q *U,*V,' ');
|
||||
</code></pre>
|
||||
|
||||
<p>Technically it would be a <code>" "</code> (see <a href="HACKING">HACKING</a> 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).</p>
|
||||
<BR>
|
||||
<HR>
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2020,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
+26
-27
@@ -274,7 +274,7 @@ technique causes some beautifiers problems too.
|
||||
|
||||
- Another use of the `Z` macro is this curious line:
|
||||
|
||||
static char s[]=Z(; +<>^v);
|
||||
static const 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
|
||||
@@ -285,7 +285,7 @@ technique causes some beautifiers problems too.
|
||||
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 `\<v\>`: which happens to be
|
||||
it takes you to other instances of `v`: as in `\<v\>`: which happens to be
|
||||
something else entirely. That itself however might or might not be
|
||||
significant for this instance!
|
||||
|
||||
@@ -301,9 +301,9 @@ technique causes some beautifiers problems too.
|
||||
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.
|
||||
it's more like a string than anything but yet it's not visibly a string.
|
||||
|
||||
Some beautifiers don't like this.
|
||||
Some beautifiers didn't like this at all.
|
||||
|
||||
- There's an `#undef` following an `if` in a way to draw attention from what to
|
||||
do if the if is true.
|
||||
@@ -353,14 +353,14 @@ converted this:
|
||||
|
||||
- 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()).
|
||||
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.
|
||||
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`
|
||||
- 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.
|
||||
|
||||
@@ -397,7 +397,7 @@ this in two parts: the negative offsets and then the confusing names.
|
||||
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:
|
||||
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);
|
||||
|
||||
@@ -412,30 +412,29 @@ this in two parts: the negative offsets and then the confusing names.
|
||||
|
||||
(*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.
|
||||
...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`.)
|
||||
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:
|
||||
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)!
|
||||
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
|
||||
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?
|
||||
:)
|
||||
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.html][] ([HACKING.md][] on GitHub) file. Also there might be some
|
||||
@@ -446,10 +445,10 @@ dimensions. Now in the first call in main() I have the code and tests following:
|
||||
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
|
||||
- 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
|
||||
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
|
||||
@@ -459,8 +458,8 @@ easily be read as `Y` and I have a lot of fun with `V` which I will get to next
|
||||
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.
|
||||
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
|
||||
@@ -473,10 +472,10 @@ also part of the compound literal: that is they point into it:
|
||||
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
|
||||
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
|
||||
`main()` I draw it at `*U, *V` and also check for the bug being eaten there
|
||||
too.
|
||||
|
||||
|
||||
|
||||
@@ -1,394 +0,0 @@
|
||||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.2.2">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=utf-8"> <link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<CENTER>
|
||||
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
|
||||
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
|
||||
<div id="bar">
|
||||
<ul>
|
||||
<li><a href="../index.html">About the 27th IOCCC</a></li>
|
||||
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
|
||||
<li><a href="/index.html">IOCCC home</a></li>
|
||||
<li><a href="/winners.html">List of All Winners</a></li>
|
||||
<li><a href="/judges.html">The Judges</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<P><FONT size="6"><B>Supplemental Info</B></FONT></P>
|
||||
</CENTER>
|
||||
|
||||
|
||||
<h1>Terminals</h1>
|
||||
|
||||
<p>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.).</p>
|
||||
|
||||
<p><a name="toc"></a></p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="#termcaps">Capabilities support testing program</a></p></li>
|
||||
<li><p><a href="#dimensions">Setting the game dimensions</a></p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="#linescolumns">The LINES and COLUMNS environmental variables</a></p></li>
|
||||
<li><p><a href="#insanity">Terminal insanity</a></p></li>
|
||||
<li><p><a href="#restore">Restoring the terminal</a></p></li>
|
||||
<li><p><a href="#abuse">Terminal size abuse</a></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a href="#termlimitations">Terminal limitations</a></p></li>
|
||||
<li><p><a href="#colours">Terminal colours</a></p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="#background">Curses background</a></p></li>
|
||||
<li><p><a href="#monochrome">Monochrome terminals</a></p></li>
|
||||
<li><p><a href="#colourlimitations">Colour limitations</a></p></li>
|
||||
<li><p><a href="#disablecolour">Disabling colour</a></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h1><a name="termcaps" href="#toc">Capabilities support testing program</a></h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>It also tries to determine the minimum number of columns to play without the
|
||||
status line overflowing - even with the dynamic length. Try:</p>
|
||||
|
||||
<pre><code> $ make test
|
||||
</code></pre>
|
||||
|
||||
<p>This compiles the program and runs it; you should see something like:</p>
|
||||
|
||||
<pre><code> 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.
|
||||
</code></pre>
|
||||
|
||||
<p>If I pass in any of the variables <strong>GROW</strong>, <strong>MAXSIZE</strong>, <strong>SIZE</strong> and/or
|
||||
<strong>LINES</strong> or <strong>COLUMNS</strong> it bases its calculations on those variables. For
|
||||
example:</p>
|
||||
|
||||
<pre><code> $ 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.
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>Maybe there are other capabilities I should check for that I’m unaware of but
|
||||
this should give you an idea.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>Both scripts run this utility and prompt if there are any problems;
|
||||
you can continue either way.</p>
|
||||
|
||||
<h1><a name="dimensions" href="#toc">Setting the game dimensions</a></h1>
|
||||
|
||||
<p>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?</p>
|
||||
|
||||
<h2><a name="linescolumns" href="#toc">The LINES and COLUMNS environmental variables</a></h2>
|
||||
|
||||
<p>To specify the lines/columns of curses program per instance use the <code>LINES</code> and
|
||||
<code>COLUMNS</code> environmental variables.</p>
|
||||
|
||||
<p>For demonstration consider the following:</p>
|
||||
|
||||
<pre><code> $ echo $LINES $COLUMNS
|
||||
42 157
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>Say you want 55 columns:</p>
|
||||
|
||||
<pre><code> $ COLUMNS=55 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> X:27/54 Y:20/41 S:5/997 B:0
|
||||
</code></pre>
|
||||
|
||||
<p>But problems can arise with messing with dimensions: in my tests this held only
|
||||
to lines.</p>
|
||||
|
||||
<h2><a name="insanity" href="#toc">Terminal insanity</a></h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h3><a name="restore" href="#toc">Restoring the terminal</a></h3>
|
||||
|
||||
<p>In my tests there is one thing that at least allows you to see the final score
|
||||
and that is by running <code>clear</code> before running the program. That’s what the
|
||||
prog.alt version does. You might run it as one of:</p>
|
||||
|
||||
<pre><code> LINES=20 ./prog.alt
|
||||
LINES=20 ./snake.alt
|
||||
</code></pre>
|
||||
|
||||
<p>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 <code>reset</code> command.</p>
|
||||
|
||||
<p>The Linux man page says:</p>
|
||||
|
||||
<pre><code>You might have to run the `reset` tool like:
|
||||
|
||||
<LF>reset<LF>
|
||||
|
||||
(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.
|
||||
</code></pre>
|
||||
|
||||
<p>If you don’t have the reset utility you can try:</p>
|
||||
|
||||
<pre><code> echo -e \\033c
|
||||
</code></pre>
|
||||
|
||||
<p>Otherwise try <code>clear; stty sane</code> (that will turn on echo also) or if all else
|
||||
fails log out and back in.</p>
|
||||
|
||||
<p>For more information on this subject generally see the <a href="https://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO.html">Linux keyboard and
|
||||
console HOWTO</a> (specifically <a href="https://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-4.html">Linux keyboard and console HOWTO section 4</a>).
|
||||
Yes this works under macOS (at least it did for me).</p>
|
||||
|
||||
<h3><a name="abuse" href="#toc">Terminal size abuse</a></h3>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> LINES=997 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> COLUMNS=997 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>Then they will see a different effect. Again the same reason: the player trying
|
||||
to be funny.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h1><a name="termlimitations" href="#toc">Terminal limitations</a></h1>
|
||||
|
||||
<p>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 (<code>cat -v</code> 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.</p>
|
||||
|
||||
<p>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. <strong>LINES=6 COLUMNS=6</strong> and <strong>LINES=3 COLUMNS=3</strong> caused some
|
||||
nasty issues.</p>
|
||||
|
||||
<h1><a name="colours" href="#toc">Terminal colours</a></h1>
|
||||
|
||||
<p>N.B.: If all you’re after is wanting to change the colours see the script
|
||||
<a href="snake-colours.sh">snake-colours.sh</a> 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).</p>
|
||||
|
||||
<h2><a name="background" href="#toc">Curses background</a></h2>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<h2><a name="monochrome" href="#toc">Monochrome terminals</a></h2>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> TERM=linux-m ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h2><a name="colourlimitations" href="#toc">Colour limitations</a></h2>
|
||||
|
||||
<p>According to X/Open Curses, Issue 7 (pg. 57):</p>
|
||||
|
||||
<pre><code>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.
|
||||
</code></pre>
|
||||
|
||||
<p>The manpage for <code>init_pair()</code> says this:</p>
|
||||
|
||||
<pre><code> 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)).
|
||||
</code></pre>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> #include <curses.h>
|
||||
|
||||
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
|
||||
</code></pre>
|
||||
|
||||
<p>Without specifying the TERM I get:</p>
|
||||
|
||||
<pre><code> COLORS: 256
|
||||
COLOR_PAIRS: 32767
|
||||
</code></pre>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> 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();
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<p>Running it like</p>
|
||||
|
||||
<pre><code> TERM=linux-m ./colour_pairs
|
||||
</code></pre>
|
||||
|
||||
<p>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 <code>bkgd()</code> I get
|
||||
instead:</p>
|
||||
|
||||
<pre><code> COLORS: 256
|
||||
COLOR_PAIRS: 32767
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h2><a name="disablecolour" href="#toc">Disabling colour</a></h2>
|
||||
|
||||
<p>Nevertheless if it is a problem and you don’t want to use a monochrome terminal
|
||||
(or can’t):</p>
|
||||
|
||||
<p>First comment out the code that has <code>start_color();</code> and then add <code>return;</code> to the
|
||||
top of the <code>C()</code> function (the rest of the code won’t be reached). If necessary
|
||||
you can also comment out the <code>init_pair()</code> calls.</p>
|
||||
|
||||
<p>Perhaps you only need to add the <code>return;</code> to <code>C()</code>. My guess is that’s the case
|
||||
but I do not know for certain.</p>
|
||||
<BR>
|
||||
<HR>
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2020,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,474 +0,0 @@
|
||||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.2.2">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=utf-8"> <link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<CENTER>
|
||||
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
|
||||
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
|
||||
<div id="bar">
|
||||
<ul>
|
||||
<li><a href="../index.html">About the 27th IOCCC</a></li>
|
||||
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
|
||||
<li><a href="/index.html">IOCCC home</a></li>
|
||||
<li><a href="/winners.html">List of All Winners</a></li>
|
||||
<li><a href="/judges.html">The Judges</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<P><FONT size="6"><B>Supplemental Info</B></FONT></P>
|
||||
</CENTER>
|
||||
|
||||
|
||||
<h1>Troubleshooting Snake</h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p><a name="toc"></a>
|
||||
- <a href="#topwall">The top wall isn’t (all/some of the time) visible!</a>
|
||||
- <a href="#notmoving">The snake isn’t moving!</a>
|
||||
- <a href="#invisiblehead">I can’t see the snake head (or other part of the snake)!</a>
|
||||
- <a href="#invisiblebug">I can’t see the bug!</a>
|
||||
- <a href="#froze">The game froze!</a>
|
||||
- <a href="#bigsnake">The game gets slower as the snake gets bigger!</a>
|
||||
- <a href="#headonly">I set SIZE=0 GROW=1, ate a bug but still only the head was visible! Why?</a>
|
||||
- <a href="#monochrome">I like black text on a white background but even with a white background terminal it ends up black!</a>
|
||||
- <a href="#toodark">The text is hard to see (not bright enough)!</a>
|
||||
- <a href="#movefaster">Can I move the snake faster temporarily without having to modify the wait time?</a>
|
||||
- <a href="#envvars">On environmental variables more generally and string to int conversions</a>
|
||||
- <a href="#errors">Errors and error reporting</a></p>
|
||||
|
||||
<h2><a name="topwall" href="#toc">The top wall isn’t (all/some of the time) visible!</a></h2>
|
||||
|
||||
<p>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 <a href="HACKING">HACKING</a>) but you shouldn’t need it to be very
|
||||
wide.</p>
|
||||
|
||||
<ul>
|
||||
<li><p>RESOLUTION #0: Use a bigger screen (it doesn’t take that many columns)</p>
|
||||
|
||||
<p> <strong>Tip:</strong> try running <code>make test</code> to get an estimate of the minimum number of columns
|
||||
needed. This won’t work right if you change the score line!</p>
|
||||
|
||||
<p> 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).</p></li>
|
||||
<li><p>RESOLUTION #1: Open the <a href="prog.c">prog.c</a> and change the line</p>
|
||||
|
||||
<pre><code> #define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n),Y,y[-2],X, *y, A, g, c );
|
||||
</code></pre>
|
||||
|
||||
<p> To be something like:</p>
|
||||
|
||||
<pre><code> #define J Z(B:%zu\n), c);
|
||||
</code></pre>
|
||||
|
||||
<p> 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).</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="notmoving" href="#toc">The snake isn’t moving!</a></h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<ul>
|
||||
<li><p>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.</p>
|
||||
|
||||
<p> If you want to see this in action try:</p>
|
||||
|
||||
<pre><code> SIZE=150 SHEDS=10 SHED=1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p> 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.</p>
|
||||
|
||||
<p> 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.</p></li>
|
||||
<li><p>BOTTOM LINE: If you want more information then see the <a href="bugs.md">bugs.md</a> file.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="invisiblehead" href="#toc">I can’t see the snake head (or other part of the snake)!</a></h2>
|
||||
|
||||
<p>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 …. ? :))</p>
|
||||
|
||||
<ul>
|
||||
<li><p>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!</p></li>
|
||||
<li><p>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 <code>make
|
||||
test</code>.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="invisiblebug" href="#toc">I can’t see the bug!</a></h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<ul>
|
||||
<li><p>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.</p></li>
|
||||
<li><p>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.</p></li>
|
||||
<li><p>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 <a href="https://www.hp-lexicon.org/character/gaunt-family/morfin-gaunt/">Snakey</a> 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 <code>*</code> is a regexp metacharacter). This has happened to me numerous times.</p></li>
|
||||
<li><p>RESOLUTION #3: If the colour contrast is not good for your eyes use the
|
||||
<a href="snake-colours">snake-colours</a> script to select a different colour scheme.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="froze" href="#toc">The game froze!</a></h2>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<ul>
|
||||
<li><p>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.</p></li>
|
||||
<li><p>RESOLUTION #1: If the system <code>rand()</code> 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.</p></li>
|
||||
<li><p>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.</p>
|
||||
|
||||
<p> I removed caps in a test and then:</p>
|
||||
|
||||
<pre><code> GROW=1 COLUMNS=30 LINES=10 CANNIBAL=1 MAXSIZE=10000 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p> It froze at this point:</p>
|
||||
|
||||
<pre><code> X:14/29 Y:5/9 S:323/10000 B:318
|
||||
</code></pre>
|
||||
|
||||
<p> 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.</p>
|
||||
|
||||
<p> Another time I tried:</p>
|
||||
|
||||
<pre><code> LINES=6 COLUMNS=6
|
||||
</code></pre>
|
||||
|
||||
<p> And it also froze (as noted I impose a minimum of >= 10 for both LINES and
|
||||
COLUMNS).</p>
|
||||
|
||||
<p> 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.</p></li>
|
||||
<li><p>TERMINAL SIZE TO MAX SNAKE SIZE CALCULATION ETC.</p>
|
||||
|
||||
<p> For this information and more use the termcaps utility:</p>
|
||||
|
||||
<pre><code> make test
|
||||
</code></pre>
|
||||
|
||||
<p> An example:</p>
|
||||
|
||||
<pre><code> 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.
|
||||
</code></pre>
|
||||
|
||||
<p> 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.</p>
|
||||
|
||||
<p> The calculation for max size takes place after decrementing the max y/x;
|
||||
then it’s <code>(maxy - 2) * (maxx - 2)</code>; above that would be:</p>
|
||||
|
||||
<pre><code> (41 - 2) * (156 - 2) == 6006
|
||||
</code></pre>
|
||||
|
||||
<p> 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.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="bigsnake" href="#toc">The game gets slower as the snake gets bigger!</a></h2>
|
||||
|
||||
<p>Realistically the game shouldn’t take that much memory but maybe in some very
|
||||
busy systems it would have a problem.</p>
|
||||
|
||||
<ul>
|
||||
<li><p>RESOLUTION #0: If the rand() implementation is particularly poor then it might
|
||||
be that the bug placement is taking more time.</p></li>
|
||||
<li><p>RESOLUTION #1: It could also be the arrays being updated as the snake gets
|
||||
bigger.</p></li>
|
||||
<li><p>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?</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="headonly" href="#toc">I set <code>SIZE=0 GROW=1</code>, ate a bug but still only the head was visible! Why?</a></h2>
|
||||
|
||||
<ul>
|
||||
<li><p>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:</p>
|
||||
|
||||
<pre><code> SIZE=1 GROW=1
|
||||
</code></pre>
|
||||
|
||||
<p> 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.</p>
|
||||
|
||||
<p> 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.</p></li>
|
||||
<li><p>BOTTOM LINE: In some senses SIZE=0 and SIZE=1 are the same thing.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="monochrome" href="#toc">I like black text on a white background but even with a white background terminal it ends up black!</a></h2>
|
||||
|
||||
<p>This is a curses thing but fortunately it should be easy enough to solve.</p>
|
||||
|
||||
<ul>
|
||||
<li><p>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.</p>
|
||||
|
||||
<p> The <code>-m</code> suffix to terminal names means monochrome. Under Linux this
|
||||
terminal is under <code>/usr/share/terminfo/l/linux-m</code> and under macOS (Catalina
|
||||
at least) it’s at <code>/usr/share/terminfo/6c/linux-m</code>.</p></li>
|
||||
<li><p>BOTTOM LINE: Try using a monochrome terminal for the game by e.g.:</p>
|
||||
|
||||
<pre><code> TERM=linux-m ./prog
|
||||
</code></pre>
|
||||
|
||||
<p> 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).</p>
|
||||
|
||||
<p> I discuss colours and terminals in much more detail in
|
||||
<a href="terminals.md">terminals.md</a> (<a href="terminals.html">terminals.html</a>).</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="toodark" href="#toc">The text is hard to see (not bright enough)!</a></h2>
|
||||
|
||||
<ul>
|
||||
<li><p>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.</p>
|
||||
|
||||
<p> 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.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="movefaster" href="#toc">Can I move the snake faster temporarily without having to modify the wait time?</a></h2>
|
||||
|
||||
<p>Yes. The <code>getch()</code> call is non-blocking when the timeout value is positive so
|
||||
it’s up to that number of milliseconds.</p>
|
||||
|
||||
<ul>
|
||||
<li><p>RESOLUTION #0: All you need to do then is hold down the direction key (or for
|
||||
that matter any other key that <code>getch()</code> will pick up on). You can also rapidly
|
||||
push the key instead of holding it down.</p></li>
|
||||
<li><p>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.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a name="envvars" href="#toc">On environmental variables more generally and string to int conversions</a></h2>
|
||||
|
||||
<p>What happens if you do:</p>
|
||||
|
||||
<pre><code> WALLS= ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>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 <code>strtoul()</code> 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.</p>
|
||||
|
||||
<p>If however you were to give valid input followed by invalid input the valid
|
||||
input would be parsed. For example:</p>
|
||||
|
||||
<pre><code> WALLS=1test ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>Would let you go through the walls. On the other hand</p>
|
||||
|
||||
<pre><code> WALLS=test1 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>Would not. Furthermore if you specify the same variable more than once it’s the
|
||||
last one that counts. For example:</p>
|
||||
|
||||
<pre><code> WALLS=0 WALLS=1 CANNIBAL=1 CANNIBAL=0 ./prog
|
||||
</code></pre>
|
||||
|
||||
<p>Would allow you to go through walls but you could not cannibalise.</p>
|
||||
|
||||
<p>Also note that I specify base 0 which means that you can also have it in hex and
|
||||
octal. These are all the same:</p>
|
||||
|
||||
<pre><code> SIZE=0x3
|
||||
SIZE=3
|
||||
SIZE=03
|
||||
</code></pre>
|
||||
|
||||
<p>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</p>
|
||||
|
||||
<pre><code> SIZE=0
|
||||
SIZE=f
|
||||
SIZE=-
|
||||
SIZE=f1
|
||||
</code></pre>
|
||||
|
||||
<p>Are all equivalent.</p>
|
||||
|
||||
<p>Observe that</p>
|
||||
|
||||
<pre><code> SIZE=08
|
||||
</code></pre>
|
||||
|
||||
<p>Is invalid input because octal only has digits 0 - 7: the resulting size will be
|
||||
0.</p>
|
||||
|
||||
<p>I discuss the signed/unsigned issue to do with curses and sizes in C being
|
||||
unsigned in <a href="bugs.md">bugs.md</a> but probably there isn’t anything more to say here.</p>
|
||||
|
||||
<h2><a name="errors" href="#toc">Errors and error reporting</a></h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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):</p>
|
||||
|
||||
<pre><code> $ MAXSIZE=-1 ./prog
|
||||
memory error
|
||||
X:0/157 Y:0/42 S:3/18446744073709551614 B:0
|
||||
</code></pre>
|
||||
|
||||
<p>BTW: There are two arrays that have to be <strong>MAXSIZE</strong> (technically + 1).</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> SIZE=1 MAXSIZE=0 ./prog
|
||||
YOU WIN!
|
||||
X:78/156 Y:20/41 S:0/0 B:0
|
||||
</code></pre>
|
||||
|
||||
<p>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.</p>
|
||||
<BR>
|
||||
<HR>
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2020,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3601,7 +3601,7 @@ If you have audible bells enabled the program will beep at every turn.
|
||||
### Information: [2020/ferguson1/README.md](2020/ferguson1/README.md)
|
||||
|
||||
There are some things that might appear to be bugs but are actually features or
|
||||
things that are misinterpreted as bugs. See his
|
||||
things that are misinterpreted as bugs. See the
|
||||
[bugs.md](2020/ferguson1/bugs.md) and
|
||||
[troubleshooting.md](2020/ferguson1/troubleshooting.md) files for details.
|
||||
|
||||
|
||||
+8
-1
@@ -4359,7 +4359,8 @@ layered chocolate fudge cake recipe](/2020/ferguson1/chocolate-cake.md) :-)
|
||||
|
||||
Yes the irony here is as rich as the chocolate cake: the question is do you know
|
||||
how rich it is? If not and you like chocolate I (that is Cody :-) ) highly
|
||||
recommend you give it a go! :-)
|
||||
recommend you give it a go! :-) You're welcome to ask me questions if you wish
|
||||
and I encourage you to do so as the cake is quite picky!
|
||||
|
||||
|
||||
## <a name="2020_ferguson2"></a>[2020/ferguson2](/2020/ferguson2/prog.c) ([README.md](/2020/ferguson2/README.md))
|
||||
@@ -4374,6 +4375,12 @@ Most importantly he also added some corrections to the vital [Double
|
||||
layered chocolate fudge cake recipe](/2020/ferguson2/chocolate-cake.md),
|
||||
enciphered though it is :-)
|
||||
|
||||
Yes the irony here is as rich as the chocolate cake: the question is do you know
|
||||
how rich it is? If not and you like chocolate I (that is Cody :-) ) highly
|
||||
recommend you give it a go! :-) You're welcome to ask me questions if you wish
|
||||
and I encourage you to do so as the cake is quite picky!
|
||||
|
||||
|
||||
|
||||
## <a name="2020_kurdyukov2"></a>[2020/kurdyukov2](/2020/kurdyukov2/prog.c) ([README.md](/2020/kurdyukov2/README.md))
|
||||
|
||||
|
||||
Reference in new issue
Block a user