Expand all leading tabs in markdown files
Given how problematic leading tabs in markdown files can be,
we have expanded all leading tabs in markdown files by:
```sh
find * -type f -name '*.md' -print |
while read -r file; do
rm -f "$file.tmp" ;
expand < "$file" > "$file.tmp" ;
mv -f -v "$file.tmp" "$file" ;
done
```
Given the previous changes to `bin/pandoc-wrapper.sh` and other recent
commits and recent pull requests, the were were **NO** changes to
any HTML files. This is a **good thing** as the expression goes.
No there are no leading tabs in any markdown files.
A check to catch any re-introduction of leading tabs
into any markdown file is on the way.
BTW: We do not have anything against leading tabs in files,
even though we have had to deal with their impact on forming
HTML from markdown files (as well as the calc source code).
It is just that this is one of those cases where tabs conflict
(sometimes caused by people wanting to change the classic
8-space tab model) with a desired outcome.
Perform `make www` to perform the above and test under macOS.
This commit is contained in:
1 parent
bf28cac593
commit
7712db4a17
117 files changed
+1758
-1758
No files matched your search
@@ -102,7 +102,7 @@ The entirety of the program consists of a single iterated call to `printf(3)`.
|
||||
|
||||
``` <!---c-->
|
||||
int main() {
|
||||
while(*d) printf(fmt, arg);
|
||||
while(*d) printf(fmt, arg);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -316,8 +316,8 @@ One option would be to implement the logic as
|
||||
``` <!---c-->
|
||||
printf()
|
||||
while (*ok) {
|
||||
scanf();
|
||||
printf();
|
||||
scanf();
|
||||
printf();
|
||||
}
|
||||
```
|
||||
|
||||
@@ -326,8 +326,8 @@ implement it like this
|
||||
|
||||
``` <!---c-->
|
||||
while (*ok) {
|
||||
scanf();
|
||||
printf();
|
||||
scanf();
|
||||
printf();
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ flagged.
|
||||
```
|
||||
? ? ? ? ! ? ? ?
|
||||
? 3 1 2 => ! 3 1 2
|
||||
2 2 . . 2 2 . .
|
||||
2 2 . . 2 2 . .
|
||||
```
|
||||
|
||||
`A` and `B` are probed cells whose numbers are, respectively, 3 and 1. The
|
||||
|
||||
+16
-16
@@ -29,7 +29,7 @@ snake's syllabary) for all snake and herpetologist programmers alike.
|
||||
* Modifications
|
||||
|
||||
- Modifying the colours
|
||||
- Background colour
|
||||
- Background colour
|
||||
- Modifying the characters for the wall, bug and snake
|
||||
- Modifying input keys
|
||||
- Modifying the status/score line
|
||||
@@ -40,7 +40,7 @@ snake's syllabary) for all snake and herpetologist programmers alike.
|
||||
- Health (and/or Lives)
|
||||
- Saving the game
|
||||
- Different types of walls
|
||||
- Blockades
|
||||
- Blockades
|
||||
- Diagonal movement
|
||||
- Special abilities
|
||||
- Obstacles
|
||||
@@ -228,27 +228,27 @@ More generally the following expressions and data types (with format specifiers)
|
||||
come to mind as information that might be of interest.
|
||||
|
||||
```
|
||||
DESCRIPTION EXPRESSION TYPE FORMAT SPECIFIER
|
||||
DESCRIPTION EXPRESSION TYPE FORMAT SPECIFIER
|
||||
|
||||
Snake size A size_t %zu
|
||||
Snake size A size_t %zu
|
||||
|
||||
Y coordinate Y int %d
|
||||
Y coordinate Y int %d
|
||||
of snake head
|
||||
|
||||
X coordinate X int %d
|
||||
X coordinate X int %d
|
||||
of snake head
|
||||
|
||||
Max snake size g size_t %zu
|
||||
Max snake size g size_t %zu
|
||||
|
||||
Bugs eaten c size_t %zu
|
||||
Bugs eaten c size_t %zu
|
||||
|
||||
Bug line (Y) *U int %d
|
||||
Bug line (Y) *U int %d
|
||||
|
||||
Bug column (X) *V int %d
|
||||
Bug column (X) *V int %d
|
||||
|
||||
Snake size A size_t %zu
|
||||
Snake size A size_t %zu
|
||||
|
||||
Growth size (per N size_t %zu
|
||||
Growth size (per N size_t %zu
|
||||
bug)
|
||||
```
|
||||
|
||||
@@ -398,10 +398,10 @@ coordinates. This of course is very different now but the idea remains the same:
|
||||
``` <!---c-->
|
||||
if (p && !(*O>=O[1]||H>=M(1)))
|
||||
{
|
||||
if (X<1||X>=H)
|
||||
X = X<1?H-1:1;
|
||||
if (Y<2||Y>=*O)
|
||||
Y = Y<2?*O-1:2;
|
||||
if (X<1||X>=H)
|
||||
X = X<1?H-1:1;
|
||||
if (Y<2||Y>=*O)
|
||||
Y = Y<2?*O-1:2;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+11
-11
@@ -161,8 +161,8 @@ Here are some other features of the game:
|
||||
* A drawing/practising mode (**WAIT** < 0 makes `timeout()` block).
|
||||
|
||||
* Computer plays the game (**WAIT=0**).<br>
|
||||
- **EPILEPSY/STIMULATION OVERLOAD WARNING** included in the relevant
|
||||
section (this goes for a low **EVADE** value too).
|
||||
- **EPILEPSY/STIMULATION OVERLOAD WARNING** included in the relevant
|
||||
section (this goes for a low **EVADE** value too).
|
||||
|
||||
* Grow-Shrink mode (Positive and Negative Winning) mode (see
|
||||
[gameplay.html](gameplay.html) for more details).
|
||||
@@ -234,15 +234,15 @@ very important.
|
||||
<div id="toc">
|
||||
* ['Bugs'](#bugs)
|
||||
* [NAQs/IAQs - Never/Infrequently Asked Questions](#naqs)
|
||||
- [Do I have any inspirations for this entry?](#inspirations)
|
||||
- [Are there any features I thought of that I wanted to implement but did not get to for some reason or another?](#features)
|
||||
- [Are there ways that one can make this game easier?](#easier)
|
||||
- [Are there ways to make it harder?](#harder)
|
||||
- [How do snakes grow in real life?](#moult)
|
||||
- [Any other interesting things about snakes?](#other)
|
||||
- [Why can you go the opposite direction and so immediately die when not cannibalising?](#opposite)
|
||||
- [Do you have any **DELICIOUS CHOCOLATE CAKE** recipes?](#chocolatecake)
|
||||
- [What are the files prog.alt.c, prog.2.c, prog-j.c and prog.alt.c ?](#alt)
|
||||
- [Do I have any inspirations for this entry?](#inspirations)
|
||||
- [Are there any features I thought of that I wanted to implement but did not get to for some reason or another?](#features)
|
||||
- [Are there ways that one can make this game easier?](#easier)
|
||||
- [Are there ways to make it harder?](#harder)
|
||||
- [How do snakes grow in real life?](#moult)
|
||||
- [Any other interesting things about snakes?](#other)
|
||||
- [Why can you go the opposite direction and so immediately die when not cannibalising?](#opposite)
|
||||
- [Do you have any **DELICIOUS CHOCOLATE CAKE** recipes?](#chocolatecake)
|
||||
- [What are the files prog.alt.c, prog.2.c, prog-j.c and prog.alt.c ?](#alt)
|
||||
|
||||
|
||||
* [Winning thoughts, dedications and thanks](#winning)
|
||||
|
||||
@@ -184,8 +184,8 @@ rest of the snake has gone through). Doing `SHED=100 SHEDS=-1`:
|
||||
|
||||
```
|
||||
ooooooooo>ooo>
|
||||
^
|
||||
>
|
||||
^
|
||||
>
|
||||
```
|
||||
|
||||
The `^` points to the part that's split from the snake and which will be
|
||||
@@ -194,8 +194,8 @@ it being `SHEDS=-3`:
|
||||
|
||||
```
|
||||
<ooo<ooooo
|
||||
^^^
|
||||
<oo
|
||||
^^^
|
||||
<oo
|
||||
```
|
||||
|
||||
If you go through the part that has split (which for some might be difficult
|
||||
@@ -258,7 +258,7 @@ adjusts the max snake size. For 10 lines and 10 columns you would see:
|
||||
terminal cols 10 (8 playable)
|
||||
|
||||
snake size: 49 (max size: 49)
|
||||
bugs: 9 (max size: 9)
|
||||
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)
|
||||
|
||||
+12
-12
@@ -24,7 +24,7 @@ for the input keys.
|
||||
* [**Photosensitive epilepsy/Stimulation overload trigger warnings**](#warning)
|
||||
* [Drawing / Practice mode](#drawing)
|
||||
* [Computer playing / Automatic mode (Photosensitive epilepsy/Stimulation overload trigger)](#auto)
|
||||
* [Variations](#auto-variations)
|
||||
* [Variations](#auto-variations)
|
||||
* [Grow-Shrink (Positive/Negative Winning) mode](#grow-shrink)
|
||||
* [Hypnotic / Sleepy mode (Photosensitive epilepsy/Stimulation overload trigger)](#hypnotic)
|
||||
* [Stimulation / Calming mode](#stim)
|
||||
@@ -32,16 +32,16 @@ for the input keys.
|
||||
|
||||
5. [Scripts](#scripts)
|
||||
|
||||
* [Colours selection](#colours)
|
||||
* [Automate the above gameplay modes](#preset)
|
||||
* [Colours selection](#colours)
|
||||
* [Automate the above gameplay modes](#preset)
|
||||
|
||||
|
||||
6. [Other game variables](#variables)
|
||||
|
||||
* [WAIT - Snake speed](#wait)
|
||||
* [EVADE - Bug evasion frequency](#evade)
|
||||
* [SIZE / MAXSIZE - Initial snake / max sizes](#sizes)
|
||||
* [GROW / SHEDS - Growth / Shedding sizes](#growth)
|
||||
* [WAIT - Snake speed](#wait)
|
||||
* [EVADE - Bug evasion frequency](#evade)
|
||||
* [SIZE / MAXSIZE - Initial snake / max sizes](#sizes)
|
||||
* [GROW / SHEDS - Growth / Shedding sizes](#growth)
|
||||
|
||||
|
||||
7. [Conclusion (and inspirational words for everyone)](#conclusions)
|
||||
@@ -562,11 +562,11 @@ diagonal movement and I also made a mistake and had to modify what I was aiming
|
||||
for. But you can consider this mode drawing or practice mode.
|
||||
|
||||
```
|
||||
oooooooooo ooooo o oo ooooo
|
||||
o o oo o oo o ooo o
|
||||
oooo o oo ooooooo oooo ooooo
|
||||
o o ooo oo o ooo o
|
||||
oooo o oo ooo oooooooo>
|
||||
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>
|
||||
```
|
||||
|
||||
|
||||
|
||||
+85
-85
@@ -17,8 +17,8 @@ already knew that so no harm there, hey?
|
||||
- [How does the snake movement work?](#movement)
|
||||
- [Drawing (manual) and computer playing (automatic) modes](#manual-automatic)
|
||||
- [Collision detection](#collision)
|
||||
* [Cannibal collision detection](#cannibalcollision)
|
||||
* [Collision detection when resizing the window of the game](#resizing)
|
||||
* [Cannibal collision detection](#cannibalcollision)
|
||||
* [Collision detection when resizing the window of the game](#resizing)
|
||||
- [Obfuscation](#obfuscation)
|
||||
- [Skinning the snake (i.e., decreasing the iocccsize)](#skinning)
|
||||
- [A few more interesting size optimisations](#size)
|
||||
@@ -216,11 +216,11 @@ in real life increases in size like that so suddenly? :)
|
||||
probably less known and either way it's not as simple as just having the code
|
||||
that it translates to. For example why have:
|
||||
|
||||
attroff(COLOR_PAIR(L));
|
||||
attroff(COLOR_PAIR(L));
|
||||
|
||||
When you can have instead:
|
||||
|
||||
attroff(m(PAIR(L)));
|
||||
attroff(m(PAIR(L)));
|
||||
|
||||
It's an extra layer of indirection. This used to be more used but when
|
||||
making it easier for users to change the colour pairs I no longer used it to
|
||||
@@ -231,12 +231,12 @@ that it translates to. For example why have:
|
||||
|
||||
- What is this block of code?
|
||||
|
||||
F(MAXSIZE)g d g = f((a)((*y-2)*(y[-2]-2)),g);
|
||||
F(GROW)N d
|
||||
F(SIZE)A d
|
||||
F(WAIT)y[-3] = (int) strtol(z,NULL,0));
|
||||
F(EVADE)W d
|
||||
/* and so on */
|
||||
F(MAXSIZE)g d g = f((a)((*y-2)*(y[-2]-2)),g);
|
||||
F(GROW)N d
|
||||
F(SIZE)A d
|
||||
F(WAIT)y[-3] = (int) strtol(z,NULL,0));
|
||||
F(EVADE)W d
|
||||
/* and so on */
|
||||
|
||||
There are several things going on here but I'll focus on the main one here and
|
||||
leave the others to their own: the `F` macro and the associated `d` macro are
|
||||
@@ -252,7 +252,7 @@ that it translates to. For example why have:
|
||||
Now it might not defeat the cpp but can you tell me what this is even with the
|
||||
cpp?
|
||||
|
||||
f((a)((*y-2)*(y[-2]-2)),g);
|
||||
f((a)((*y-2)*(y[-2]-2)),g);
|
||||
|
||||
The cpp might get it closer to what you might expect in a normal program but I
|
||||
refer to the array offsets (below also).
|
||||
@@ -266,7 +266,7 @@ much more than that (that is the `F` macro).
|
||||
|
||||
As for the Z() macro it means that I could remove `"`s; for example:
|
||||
|
||||
#define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n), Y, y[-2], X,*y,A,g, c);
|
||||
#define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n), Y, y[-2], X,*y,A,g, c);
|
||||
|
||||
Which as I have discussed elsewhere is the entire set of parameters to both
|
||||
`mvprintw()` and `printf()` plus the end of the function call (i.e. `);`.
|
||||
@@ -278,7 +278,7 @@ technique causes some beautifiers problems too.
|
||||
|
||||
- Another use of the `Z` macro is this curious line:
|
||||
|
||||
static const 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
|
||||
@@ -302,7 +302,7 @@ technique causes some beautifiers problems too.
|
||||
|
||||
Another example is using the `E()` function e.g.:
|
||||
|
||||
E(Z(YOU WIN!));
|
||||
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.
|
||||
@@ -347,12 +347,12 @@ things which reduced the number of keywords needed).
|
||||
(besides those in e.g. environmental variable processing) that's curious: I
|
||||
converted this:
|
||||
|
||||
if (!P) P = 1;
|
||||
else P = 0;
|
||||
if (!P) P = 1;
|
||||
else P = 0;
|
||||
|
||||
To this:
|
||||
|
||||
(!P && (P = 1))||(P=0);
|
||||
(!P && (P = 1))||(P=0);
|
||||
|
||||
|
||||
- Makes use of the different namespaces to have variables and labels be the
|
||||
@@ -371,13 +371,13 @@ it might be easy to miss.
|
||||
- Uses an unnamed array (compound literal) for several different game variables.
|
||||
The pointer to the first element is defined like `int *j`:
|
||||
|
||||
static int Y,X,*j = (int[8]){231,0}, *U, *V, *e, *n, Q, P,x,*y,l=4,*D;
|
||||
static int Y,X,*j = (int[8]){231,0}, *U, *V, *e, *n, Q, P,x,*y,l=4,*D;
|
||||
|
||||
Does the 231 seem familiar? It should: it's the default key delay for the
|
||||
`timeout()` call (which I will return to again). The rest are 0 default. But
|
||||
what about `j`? Is it even used? Actually in main:
|
||||
|
||||
y = j+3;
|
||||
y = j+3;
|
||||
|
||||
But aside from that `j` is not used. However...
|
||||
|
||||
@@ -386,24 +386,24 @@ this in two parts: the negative offsets and then the confusing names.
|
||||
|
||||
Can you honestly tell me that this is easy to follow?
|
||||
|
||||
if (Y < 1 || Y >= y[-2] || X < 2 || X >= *y || y[-2] >= y[-1] || *y >= 1[y])
|
||||
{
|
||||
if (*p && !(*y>=1[y]||y[-2]>=y[-1]))
|
||||
{
|
||||
if (Y<1||Y>=y[-2])
|
||||
Y = Y<1?y[-2]-1:1;
|
||||
if (X<2||X>=*y)
|
||||
X = X<2?*y-1:2;
|
||||
}
|
||||
/* ... */
|
||||
}
|
||||
if (Y < 1 || Y >= y[-2] || X < 2 || X >= *y || y[-2] >= y[-1] || *y >= 1[y])
|
||||
{
|
||||
if (*p && !(*y>=1[y]||y[-2]>=y[-1]))
|
||||
{
|
||||
if (Y<1||Y>=y[-2])
|
||||
Y = Y<1?y[-2]-1:1;
|
||||
if (X<2||X>=*y)
|
||||
X = X<2?*y-1:2;
|
||||
}
|
||||
/* ... */
|
||||
}
|
||||
|
||||
That's not the only place negative offsets occur! Observe the ternary operators
|
||||
there too.
|
||||
|
||||
I'll go back to the `F()` macro and in particular what follows one of them:
|
||||
|
||||
g d g = f((a)((*y-2)*(y[-2]-2)),g);
|
||||
g d g = f((a)((*y-2)*(y[-2]-2)),g);
|
||||
|
||||
To parse that at the very least you have to know that `y` points to `j + 3`.
|
||||
Then you have to know that `j` points to the first element of an unnamed
|
||||
@@ -414,7 +414,7 @@ this in two parts: the negative offsets and then the confusing names.
|
||||
applies to the block above of course and maybe more so). Then you have to
|
||||
think of operator precedence etc. I mean what is:
|
||||
|
||||
(*y-2) * (y[-2]-2])
|
||||
(*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`.
|
||||
@@ -425,10 +425,10 @@ this in two parts: the negative offsets and then the confusing names.
|
||||
- On the confusing names etc.: the `getmaxyx()` function gets the maximum Y, X
|
||||
dimensions. Now in the first call in `main()` I have the code and tests following:
|
||||
|
||||
getmaxyx(v, *y, y[-2]);
|
||||
--*y; --y[-2];
|
||||
if (y[-2] < 9 || *y < 9)
|
||||
return E(Z(term too small));
|
||||
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)`!
|
||||
@@ -469,7 +469,7 @@ of the brain is to assume `Y` is what is really `X` and `X` is what is really `Y
|
||||
- More confusion with variable names: If you notice the `int *U, *V` they are
|
||||
also part of the compound literal: that is they point into it:
|
||||
|
||||
U=y+2; V=U+1;
|
||||
U=y+2; V=U+1;
|
||||
|
||||
Except that these two are done in two different places: away from the
|
||||
assignment of `y` to remove them further away from the contexts they are
|
||||
@@ -485,15 +485,15 @@ also part of the compound literal: that is they point into it:
|
||||
|
||||
- There's another array that holds a variety of data.
|
||||
|
||||
static k p[5]={1,0},W=300;
|
||||
static k p[5]={1,0},W=300;
|
||||
|
||||
It holds the following information (but not necessarily in this order):
|
||||
|
||||
WALLS
|
||||
CANNIBAL
|
||||
SHED
|
||||
SHEDS
|
||||
EVADE
|
||||
WALLS
|
||||
CANNIBAL
|
||||
SHED
|
||||
SHEDS
|
||||
EVADE
|
||||
|
||||
But how will you know that just looking at the declaration? Many variables
|
||||
and they're part of collections but the many layers of indirection cause
|
||||
@@ -513,18 +513,18 @@ many other examples that I have already shown).
|
||||
|
||||
- Expanding on referring to the same thing in more than one way take a look at:
|
||||
|
||||
case KEY_LEFT:
|
||||
V[1] = l-3;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
V[l/l] = l/2;
|
||||
break;
|
||||
case KEY_UP:
|
||||
V[l-3] = l-1;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
V[l/4] = l;
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
V[1] = l-3;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
V[l/l] = l/2;
|
||||
break;
|
||||
case KEY_UP:
|
||||
V[l-3] = l-1;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
V[l/4] = l;
|
||||
break;
|
||||
|
||||
What's going on there? First of all the letter ell looks very much like the
|
||||
digit one but above there are only two references to the digit `1`; the
|
||||
@@ -551,7 +551,7 @@ many other examples that I have already shown).
|
||||
other places! But even after all of that you still need to do the
|
||||
calculations when I could simply have had:
|
||||
|
||||
V[1] = 1; V[1] = 2; ...
|
||||
V[1] = 1; V[1] = 2; ...
|
||||
|
||||
Etc.
|
||||
|
||||
@@ -585,20 +585,20 @@ check if it's > than the current?
|
||||
- More confusion with the max x/y dimensions: Going back to max x/y dimensions
|
||||
and coordinates of the snake; I showed this code before:
|
||||
|
||||
if (Y < 1 || Y >= y[-2] || X < 2 || X >= *y || y[-2] >= y[-1] || *y >= 1[y])
|
||||
{
|
||||
if (*p && !(*y>=1[y]||y[-2]>=y[-1]))
|
||||
{
|
||||
if (Y<1||Y>=y[-2])
|
||||
Y = Y<1?y[-2]-1:1;
|
||||
if (X<2||X>=*y)
|
||||
X = X<2?*y-1:2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
}
|
||||
if (Y < 1 || Y >= y[-2] || X < 2 || X >= *y || y[-2] >= y[-1] || *y >= 1[y])
|
||||
{
|
||||
if (*p && !(*y>=1[y]||y[-2]>=y[-1]))
|
||||
{
|
||||
if (Y<1||Y>=y[-2])
|
||||
Y = Y<1?y[-2]-1:1;
|
||||
if (X<2||X>=*y)
|
||||
X = X<2?*y-1:2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
}
|
||||
|
||||
I asked if you could honestly figure that out easily. But here's a bit more
|
||||
elaboration. I already talked about the negative offsets - and they should
|
||||
@@ -630,10 +630,10 @@ there's at least one negative offset.
|
||||
|
||||
- A note on the many `#define`s in my entry. You say you dislike them:
|
||||
|
||||
Doing masses of #defines to obscure the source has become 'old'. We
|
||||
tend to 'see thru' masses of #defines due to our pre-processor tests
|
||||
that we apply. Simply abusing #defines or -Dfoo=bar won't go as far
|
||||
as a program that is more well rounded in confusion.
|
||||
Doing masses of #defines to obscure the source has become 'old'. We
|
||||
tend to 'see thru' masses of #defines due to our pre-processor tests
|
||||
that we apply. Simply abusing #defines or -Dfoo=bar won't go as far
|
||||
as a program that is more well rounded in confusion.
|
||||
|
||||
As I have noted though many of these save quite a lot of bytes too. It's
|
||||
true that they might aid (but barely) in obfuscation but I think that my
|
||||
@@ -654,30 +654,30 @@ magical about the number 7 isn't there? I do not refer to primes although
|
||||
certainly one could say that primes have a magic to them. No. I'm instead
|
||||
referring to another property: bitwise AND. For example consider the following:
|
||||
|
||||
7 & 0
|
||||
7 & 1
|
||||
7 & 2
|
||||
7 & 3
|
||||
7 & 4
|
||||
7 & 5
|
||||
7 & 6
|
||||
7 & 7
|
||||
7 & 0
|
||||
7 & 1
|
||||
7 & 2
|
||||
7 & 3
|
||||
7 & 4
|
||||
7 & 5
|
||||
7 & 6
|
||||
7 & 7
|
||||
|
||||
What is the result of each operation? Quite simply it's the number itself!
|
||||
How does this relate to the `s` array though? Let me back up. Is there any
|
||||
place in the code that has the number 7 (by itself - 997 doesn't count)? A
|
||||
quick check will answer that: no. But here's a curious thing:
|
||||
|
||||
q X, Y, s[*D+2&(1<<3)-!Q]);
|
||||
q X, Y, s[*D+2&(1<<3)-!Q]);
|
||||
|
||||
We KNOW that at this place `Q` is 0 so the `!Q` has to be 1. Now `1 << 3` is 8. Therefore
|
||||
|
||||
(1 << 3) - !Q == 7
|
||||
(1 << 3) - !Q == 7
|
||||
|
||||
But what's `*D`? If the snake hasn't moved once yet it's 0; otherwise it's the number
|
||||
of the direction the snake is currently facing. Thus
|
||||
|
||||
*D&(1<<3)-!Q
|
||||
*D&(1<<3)-!Q
|
||||
|
||||
...refers to `*D`. However if I were to have that be the element it wouldn't
|
||||
work right: I wanted the semicolon in there but the space was needed to
|
||||
|
||||
+26
-26
@@ -8,13 +8,13 @@ sanity if it causes any problems) as well as colours (limitations etc.).
|
||||
<div id="toc">
|
||||
- [Capabilities support testing program](#termcaps)
|
||||
- [Setting the game dimensions](#dimensions)
|
||||
* [The LINES and COLUMNS environmental variables](#linescolumns)
|
||||
* [Terminal insanity](#insanity)
|
||||
* [Restoring the terminal](#restore)
|
||||
* [Terminal size abuse](#abuse)
|
||||
* [The LINES and COLUMNS environmental variables](#linescolumns)
|
||||
* [Terminal insanity](#insanity)
|
||||
* [Restoring the terminal](#restore)
|
||||
* [Terminal size abuse](#abuse)
|
||||
- [Terminal limitations](#termlimitations)
|
||||
- [Terminal colours](#colours)
|
||||
* [Curses background](#background)
|
||||
* [Curses background](#background)
|
||||
* [Monochrome terminals](#monochrome)
|
||||
* [Colour limitations](#colourlimitations)
|
||||
* [Disabling colour](#disablecolour)
|
||||
@@ -49,7 +49,7 @@ This compiles the program [termcaps.c](%%REPO_URL%%/2020/ferguson1/termcaps.c) a
|
||||
terminal cols 155 (153 playable)
|
||||
|
||||
snake size: 997 (max size: 5776)
|
||||
bugs: 199 (max size: 1155)
|
||||
bugs: 199 (max size: 1155)
|
||||
|
||||
at least 34 columns (currently 155) recommended for snake size 997
|
||||
at least 37 columns (currently 155) recommended for capped snake size 5776
|
||||
@@ -79,7 +79,7 @@ example:
|
||||
terminal cols 155 (153 playable)
|
||||
|
||||
snake size: 5776 (max size: 5776)
|
||||
bugs: 5771 (max size: 5771)
|
||||
bugs: 5771 (max size: 5771)
|
||||
|
||||
at least 37 columns (currently 155) recommended for snake size 5776
|
||||
at least 37 columns (currently 155) recommended for capped snake size 5776
|
||||
@@ -153,7 +153,7 @@ Say you want 55 columns:
|
||||
This will force curses to detect the max columns (X) of your terminal (for the
|
||||
game dimensions) - to be 55; it might look like this instead:
|
||||
|
||||
X:27/54 Y:20/41 S:5/997 B:0
|
||||
X:27/54 Y:20/41 S:5/997 B:0
|
||||
|
||||
But problems can arise with messing with dimensions: in my tests this held only
|
||||
to lines.
|
||||
@@ -194,10 +194,10 @@ The Linux man page says:
|
||||
```
|
||||
You might have to run the `reset` tool like:
|
||||
|
||||
<LF>reset<LF>
|
||||
<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.
|
||||
(the line-feed character is normally control-J) to get the terminal
|
||||
to work, as carriage-return may no longer work in the abnormal state.
|
||||
```
|
||||
|
||||
If you don't have the reset utility you can try:
|
||||
@@ -320,7 +320,7 @@ The manpage for `init_pair()` says this:
|
||||
|
||||
[...]
|
||||
|
||||
COLOR_PAIRS corresponds to the terminal database's max_pairs capability, (see terminfo(5)).
|
||||
COLOR_PAIRS corresponds to the terminal database's max_pairs capability, (see terminfo(5)).
|
||||
```
|
||||
|
||||
Based on the two as well as the fact that monochrome terminals (I've tried under
|
||||
@@ -332,11 +332,11 @@ confirm this I wrote the following code with the output below:
|
||||
|
||||
int main()
|
||||
{
|
||||
initscr();
|
||||
start_color();
|
||||
printw("COLORS: %d\nCOLOR_PAIRS: %d\n", COLORS, COLOR_PAIRS);
|
||||
getch();
|
||||
endwin();
|
||||
initscr();
|
||||
start_color();
|
||||
printw("COLORS: %d\nCOLOR_PAIRS: %d\n", COLORS, COLOR_PAIRS);
|
||||
getch();
|
||||
endwin();
|
||||
}
|
||||
```
|
||||
|
||||
@@ -361,17 +361,17 @@ number is out of the range? To try and figure this out I did another test:
|
||||
``` <!---c-->
|
||||
int main()
|
||||
{
|
||||
initscr();
|
||||
start_color();
|
||||
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);
|
||||
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();
|
||||
getch();
|
||||
endwin();
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -44,11 +44,11 @@ you shouldn't need it to be very wide.
|
||||
|
||||
* **RESOLUTION #1**: open the [prog.c][] and change the line
|
||||
|
||||
#define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n),Y,y[-2],X, *y, A, g, c );
|
||||
#define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n),Y,y[-2],X, *y, A, g, c );
|
||||
|
||||
To be something like:
|
||||
|
||||
#define J Z(B:%zu\n), c);
|
||||
#define J Z(B:%zu\n), c);
|
||||
|
||||
Recompile and try again. That will then show only the number of bugs eaten.
|
||||
See the [HACKING.html][] file for other data you
|
||||
@@ -76,7 +76,7 @@ e.g. when the snake is growing.
|
||||
|
||||
If you want to see this in action try:
|
||||
|
||||
SIZE=150 SHEDS=10 SHED=1 ./prog
|
||||
SIZE=150 SHEDS=10 SHED=1 ./prog
|
||||
|
||||
Once you start moving you'll see that the tail stays still for a while and
|
||||
when it does move you'll see it doesn't move for long.
|
||||
@@ -174,11 +174,11 @@ snake. See below for some tests.
|
||||
|
||||
I removed caps in a test and then:
|
||||
|
||||
GROW=1 COLUMNS=30 LINES=10 CANNIBAL=1 MAXSIZE=10000 ./prog
|
||||
GROW=1 COLUMNS=30 LINES=10 CANNIBAL=1 MAXSIZE=10000 ./prog
|
||||
|
||||
It froze at this point:
|
||||
|
||||
X:14/29 Y:5/9 S:323/10000 B:318
|
||||
X:14/29 Y:5/9 S:323/10000 B:318
|
||||
|
||||
This is because there was only one place for the bug - where the snake head
|
||||
was to be. With these parameters the limit is actually 189! This could
|
||||
@@ -188,7 +188,7 @@ snake. See below for some tests.
|
||||
|
||||
Another time I tried:
|
||||
|
||||
LINES=6 COLUMNS=6
|
||||
LINES=6 COLUMNS=6
|
||||
|
||||
And it also froze (as noted I impose a minimum of >= 10 for both LINES and
|
||||
COLUMNS).
|
||||
@@ -203,25 +203,25 @@ snake. See below for some tests.
|
||||
|
||||
For this information and more use the termcaps utility:
|
||||
|
||||
make test
|
||||
make test
|
||||
|
||||
An example:
|
||||
|
||||
terminal supports cursor movement
|
||||
terminal supports making cursor invisible
|
||||
terminal supports bold
|
||||
terminal supports colours
|
||||
terminal supports cursor movement
|
||||
terminal supports making cursor invisible
|
||||
terminal supports bold
|
||||
terminal supports colours
|
||||
|
||||
terminal rows 41 (38 playable)
|
||||
terminal cols 154 (152 playable)
|
||||
terminal rows 41 (38 playable)
|
||||
terminal cols 154 (152 playable)
|
||||
|
||||
snake size: 997 (max size: 5738)
|
||||
bugs: 199 (max size: 1147)
|
||||
snake size: 997 (max size: 5738)
|
||||
bugs: 199 (max size: 1147)
|
||||
|
||||
at least 34 columns (currently 154) recommended for snake size 997
|
||||
at least 37 columns (currently 154) recommended for capped snake size 5738
|
||||
at least 34 columns (currently 154) recommended for snake size 997
|
||||
at least 37 columns (currently 154) recommended for capped snake size 5738
|
||||
|
||||
No problems detected.
|
||||
No problems detected.
|
||||
|
||||
Why are there only 38 playable lines for 41 rows? The first row is the score
|
||||
line, the second is the top wall, the last is the bottom wall. For columns
|
||||
@@ -230,7 +230,7 @@ snake. See below for some tests.
|
||||
The calculation for max size takes place after decrementing the max y/x;
|
||||
then it's `(maxy - 2) * (maxx - 2)`; above that would be:
|
||||
|
||||
(41 - 2) * (156 - 2) == 6006
|
||||
(41 - 2) * (156 - 2) == 6006
|
||||
|
||||
If for some reason the game were to stall for this purpose you would have to
|
||||
kill the game by e.g. ctrl-c since the bug placement is stuck in a loop.
|
||||
@@ -266,7 +266,7 @@ is 0? The head is the obvious choice so once you do get to size 1 you will still
|
||||
only have the head. When you get to size 2 you'll have part of the body too.
|
||||
Try:
|
||||
|
||||
SIZE=1 GROW=1
|
||||
SIZE=1 GROW=1
|
||||
|
||||
And you will see that at one bug you'll have size two and just as if you had
|
||||
two bugs with the previous invocation.
|
||||
@@ -299,7 +299,7 @@ so that's probably why; in CentOS I did have to install it specially.
|
||||
|
||||
* **BOTTOM LINE**: try using a monochrome terminal for the game by e.g.:
|
||||
|
||||
TERM=linux-m ./prog
|
||||
TERM=linux-m ./prog
|
||||
|
||||
And then on your white background terminal the game should keep the
|
||||
background white and the foreground black. This will of course mean you have
|
||||
@@ -326,9 +326,9 @@ out if enabling brighter colours is possible.
|
||||
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. Of course you might
|
||||
also try changing the colours of the game. For that see
|
||||
[snake-colours.sh](%%REPO_URL%%/2020/ferguson1/snake-colours.sh) and
|
||||
[play.sh](%%REPO_URL%%/2020/ferguson1/play.sh).
|
||||
also try changing the colours of the game. For that see
|
||||
[snake-colours.sh](%%REPO_URL%%/2020/ferguson1/snake-colours.sh) and
|
||||
[play.sh](%%REPO_URL%%/2020/ferguson1/play.sh).
|
||||
|
||||
|
||||
<div id="movefaster">
|
||||
|
||||
@@ -107,7 +107,7 @@ This code is an [enigma](https://youtu.be/ybkkiGtJmkM). Try to decode it!
|
||||
|
||||
There is a good deal of useful documentation that is provided with this entry:
|
||||
|
||||
* [enigma.1](%%REPO_URL%%/2020/ferguson2/enigma.1) - A useful man page for this entry. To render, try:
|
||||
* [enigma.1](%%REPO_URL%%/2020/ferguson2/enigma.1) - A useful man page for this entry. To render, try:
|
||||
|
||||
|
||||
``` <!---sh-->
|
||||
@@ -160,7 +160,7 @@ I have more information on this entry like the testing procedure at
|
||||
- [IOCCC: an Enigma?](#ioccc)
|
||||
- [The 1992 Nathan Sidwell entry](#nathan)
|
||||
- [Usage](#usage)
|
||||
* [Example run](#example)
|
||||
* [Example run](#example)
|
||||
- [The recode.c configurator](#recode)
|
||||
- [A parser subtlety that could cause confusion](#parsersubtlety)
|
||||
- [On the source code layout](#layout)
|
||||
@@ -548,8 +548,8 @@ ended his life. (I later made a bug fix but I consider this inconsequential).
|
||||
As for [recode.c][] though I really love this:
|
||||
|
||||
``` <!---c-->
|
||||
/\
|
||||
/ This is *not* what you think:
|
||||
/\
|
||||
/ This is *not* what you think:
|
||||
```
|
||||
|
||||
...because it seems so wrong in C code at first glance. Also what does the
|
||||
|
||||
@@ -20,17 +20,17 @@ Y<:19:><:27:> but it's not the only example. Here the compound literal of 13
|
||||
ints:
|
||||
|
||||
``` <!---c-->
|
||||
int *z=(int[13]) { 0 } , *e, *g;
|
||||
int *z=(int[13]) { 0 } , *e, *g;
|
||||
```
|
||||
|
||||
Then in main:
|
||||
|
||||
``` <!---c-->
|
||||
e = z + 10;
|
||||
g = e + 1;
|
||||
e = z + 10;
|
||||
g = e + 1;
|
||||
|
||||
for (j=-3; j < 0; ++j)
|
||||
e<:j:> = j+3;
|
||||
for (j=-3; j < 0; ++j)
|
||||
e<:j:> = j+3;
|
||||
```
|
||||
|
||||
Which I think is more confusing: when one is iterating an array you don't
|
||||
@@ -40,31 +40,31 @@ more confusing still. There are at least two other ways that are much easier
|
||||
to read that could accomplish the same thing. It continues on:
|
||||
|
||||
``` <!---c-->
|
||||
/* ... */
|
||||
e<:i-3:> = (j < 1 ? 1 : (j > 5 ? 5 : j))-1;
|
||||
/* ... */
|
||||
e<:i-3:> = (j < 1 ? 1 : (j > 5 ? 5 : j))-1;
|
||||
```
|
||||
|
||||
* Observe these two functions:
|
||||
|
||||
``` <!---c-->
|
||||
void w(char *s, int k, int v)
|
||||
{
|
||||
for(e<:2:> = 0; s<:*P:>; ++e<:2:>)
|
||||
{
|
||||
v = s<:e<:2:>:>;
|
||||
if(v > 64 && v < 91)
|
||||
s<:e<:2:>:> = (((v - 65 + k) % 26) + 65);
|
||||
}
|
||||
}
|
||||
void Q(void)
|
||||
{
|
||||
for(*g = 0; *g < 3; ++*g)
|
||||
{
|
||||
*Y<:16+e<:1:>:>=S<:e<:e<:1:>-3:>:>;
|
||||
R<:e<:1:>:>=Y<:e<:-3+e<:1:>:>:>;
|
||||
w(R[*g],*(e+e<:1:>-6)=q(Y<:8:>,*Y<:7:>),*g);
|
||||
}
|
||||
}
|
||||
void w(char *s, int k, int v)
|
||||
{
|
||||
for(e<:2:> = 0; s<:*P:>; ++e<:2:>)
|
||||
{
|
||||
v = s<:e<:2:>:>;
|
||||
if(v > 64 && v < 91)
|
||||
s<:e<:2:>:> = (((v - 65 + k) % 26) + 65);
|
||||
}
|
||||
}
|
||||
void Q(void)
|
||||
{
|
||||
for(*g = 0; *g < 3; ++*g)
|
||||
{
|
||||
*Y<:16+e<:1:>:>=S<:e<:e<:1:>-3:>:>;
|
||||
R<:e<:1:>:>=Y<:e<:-3+e<:1:>:>:>;
|
||||
w(R[*g],*(e+e<:1:>-6)=q(Y<:8:>,*Y<:7:>),*g);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
First of all: why do I set `e[2]` to 0 and increment it for each pass in the
|
||||
@@ -97,14 +97,14 @@ and (2) I didn't want to risk changing all the offsets: thus I just made that
|
||||
address `e[1]`. Thus I also have:
|
||||
|
||||
``` <!---c-->
|
||||
for (*g = 0 ; *g < 10; ++*g)
|
||||
{
|
||||
r<:-2:> = Y<:14:><:*(e+1):>; r<:-3:> = Y<:15:><:1<:e:>:>;
|
||||
if (r<:-3:> && r<:-2:> == r<:-1:>)
|
||||
return r<:-3:>;
|
||||
if (r<:-2:> && r<:-3:> == r<:-1:>)
|
||||
return r<:-2:>;
|
||||
}
|
||||
for (*g = 0 ; *g < 10; ++*g)
|
||||
{
|
||||
r<:-2:> = Y<:14:><:*(e+1):>; r<:-3:> = Y<:15:><:1<:e:>:>;
|
||||
if (r<:-3:> && r<:-2:> == r<:-1:>)
|
||||
return r<:-3:>;
|
||||
if (r<:-2:> && r<:-3:> == r<:-1:>)
|
||||
return r<:-2:>;
|
||||
}
|
||||
```
|
||||
|
||||
This `e[1]` of course is the same as `*g` as above and as you can see has
|
||||
@@ -118,7 +118,7 @@ which I use as the two chars to compare (this is the plugboard function).
|
||||
at all. Why? In fact I call it like so:
|
||||
|
||||
``` <!---c-->
|
||||
k = Z(r<:-1:>=k);
|
||||
k = Z(r<:-1:>=k);
|
||||
```
|
||||
|
||||
The char is just used as a way to be able to call the function and assign to
|
||||
@@ -133,7 +133,7 @@ refer to the same variable in more than one way (or in some cases maybe more
|
||||
correct to say 'same location'). In the Z() function for example:
|
||||
|
||||
``` <!---c-->
|
||||
r<:-2:> = Y<:14:><:*(e+1):>; r<:-3:> = Y<:15:><:1<:e:>:>;
|
||||
r<:-2:> = Y<:14:><:*(e+1):>; r<:-3:> = Y<:15:><:1<:e:>:>;
|
||||
```
|
||||
|
||||
I refer to e[1] as both: *(e+1) and 1[e].
|
||||
@@ -154,7 +154,7 @@ index (sort of).
|
||||
reflectors in one `char [][27]`. This makes for some fun code like:
|
||||
|
||||
``` <!---c-->
|
||||
(Y<:e<:-10:>+5:><:k-'A':>) && (k = Y<:e<:-10:>+5:><:k-'A':>);
|
||||
(Y<:e<:-10:>+5:><:k-'A':>) && (k = Y<:e<:-10:>+5:><:k-'A':>);
|
||||
```
|
||||
|
||||
(Of course this also removes an if statement by joining with a &&).
|
||||
@@ -195,7 +195,7 @@ itself. But although I have quite a few cpp directives I am not using them for
|
||||
obfuscation but rather to save bytes. For examples:
|
||||
|
||||
``` <!---c-->
|
||||
%:define J(x) do(*x)=getchar(); while((*x)=='\n')
|
||||
%:define J(x) do(*x)=getchar(); while((*x)=='\n')
|
||||
```
|
||||
|
||||
Is used quite a number of times and although it could be a function that
|
||||
@@ -206,7 +206,7 @@ particular I want to bring up though because I think it's a curious one and
|
||||
it ties in to another point above:
|
||||
|
||||
``` <!---c-->
|
||||
%:define A(y) *(&Y<:7:><:1:>+(y))
|
||||
%:define A(y) *(&Y<:7:><:1:>+(y))
|
||||
```
|
||||
|
||||
What is special about this one: Above I noted how I sort of refer directly
|
||||
@@ -214,7 +214,7 @@ to the notch settings (I think it was the notch settings anyway). Now I
|
||||
could have done say
|
||||
|
||||
``` <!---c-->
|
||||
char a = Y[7][1], b = Y[7][3], c = Y[7][5];
|
||||
char a = Y[7][1], b = Y[7][3], c = Y[7][5];
|
||||
```
|
||||
|
||||
But I felt that doing instead the pointer arithmetic was worth doing.
|
||||
@@ -249,9 +249,9 @@ variables in recode.c, move them to prog.c, compile and expect it to work right.
|
||||
* Also what is this about ?
|
||||
|
||||
``` <!---c-->
|
||||
/\
|
||||
/ This is *not* what you think:
|
||||
void D(char*x){ /* ... */ }
|
||||
/\
|
||||
/ This is *not* what you think:
|
||||
void D(char*x){ /* ... */ }
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ have to if you don't wish to.
|
||||
<div id="toc">
|
||||
- [What is recode and why is it recommended?](#recode)
|
||||
- [Options](#options)
|
||||
* [Protecting against the same I/O file](#samefile)
|
||||
* [File options parser limitation](#fileoptions)
|
||||
* [`-R` option validation?](#validation)
|
||||
* [Protecting against the same I/O file](#samefile)
|
||||
* [File options parser limitation](#fileoptions)
|
||||
* [`-R` option validation?](#validation)
|
||||
- [Piping commands to recode](#pipingtorecode)
|
||||
- [Piping recode to the Enigma simulator](#pipingtoenigma)
|
||||
- [Manually test the recode program with the Enigma program](#manuallytest)
|
||||
@@ -63,11 +63,11 @@ wonderful 'challenge' for everyone.
|
||||
``` <!---sh-->
|
||||
./recode -h
|
||||
usage: ./recode [options]
|
||||
-v display selected settings
|
||||
-r pseudo-randomly select settings
|
||||
-f<input file> read file for Enigma input
|
||||
-R<string|file> init settings from settings string or file
|
||||
-o<output file> write settings to file
|
||||
-v display selected settings
|
||||
-r pseudo-randomly select settings
|
||||
-f<input file> read file for Enigma input
|
||||
-R<string|file> init settings from settings string or file
|
||||
-o<output file> write settings to file
|
||||
```
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user