Format and other fixes in 2020/ferguson1
Fixed formatting in the markdown files. I did not check for typos due to the fact I wrote so much (which I'm only sorry about in the sense that it's too much to go through for almost everyone and this might make some people miss useful/interesting things. If I had 'more "time" ' maybe I could shorten it but I don't). Renamed crazy.log to crazy.log.md. Updated Makefile for the DATA variable. Corrected file names in some cases. Fixed formatting in man page. There is one other change I have in 2020/ferguson1 but it's also needed in 2020/ferguson2 so I'll do that at the same time.
This commit is contained in:
1 parent
a7e018d5e8
commit
49a6a4074d
11 files changed
+894
-732
No files matched your search
+30
-14
@@ -1,10 +1,10 @@
|
||||
In order to successfully compile this you will need a C compiler that supports
|
||||
C99+ and ncurses; note that for some platforms (e.g. Red Hat based Linux) you
|
||||
will need two different packages: the library itself but also the dev package
|
||||
that has the header files etc. If you use the Makefile obviously you need `make'
|
||||
that has the header files etc. If you use the Makefile obviously you need `make`
|
||||
too.
|
||||
|
||||
In gameplay.md I show how to easily customise the colours, set up
|
||||
In [gameplay.md](gameplay.md) I show how to easily customise the colours, set up
|
||||
different gameplay modes and various other things. The troubleshooting.md
|
||||
and terminals.md as well as bugs.md include a variety of information
|
||||
should you run into trouble.
|
||||
@@ -33,7 +33,9 @@ I imagine that it works for 32-bit systems but I do not know for sure.
|
||||
|
||||
You should be able to get the compiler with:
|
||||
|
||||
sudo xcode-select --install
|
||||
```sh
|
||||
sudo xcode-select --install
|
||||
```
|
||||
|
||||
You don't need Xcode itself and it appears that the command line tools (as above
|
||||
should install) already has ncurses so there shouldn't be anything else that
|
||||
@@ -51,10 +53,15 @@ you want to use the Makefile) to compile and link this entry. With Fedora more
|
||||
recent versions there's the `dnf` package manager but I cannot help with any of
|
||||
the GUI installers since I don't use them. Something like:
|
||||
|
||||
sudo dnf install ncurses-devel ncurses make gcc
|
||||
```sh
|
||||
sudo dnf install ncurses-devel ncurses make gcc
|
||||
```
|
||||
|
||||
Or
|
||||
# dnf install ncurses-devel ncurses make gcc
|
||||
or
|
||||
|
||||
```sh
|
||||
# dnf install ncurses-devel ncurses make gcc
|
||||
```
|
||||
|
||||
# Portability: CentOS
|
||||
|
||||
@@ -62,20 +69,29 @@ Just like Fedora you will need `gcc`, `ncurses`, `ncurses-devel` (and if you
|
||||
want to use the Makefile `make`). CentOS uses `yum` and CentOS 8 uses `dnf`.
|
||||
So:
|
||||
|
||||
sudo yum install ncurses-devel ncurses make gcc
|
||||
```sh
|
||||
sudo yum install ncurses-devel ncurses make gcc
|
||||
```
|
||||
|
||||
Or
|
||||
# yum install ncurses-devel ncurses make gcc
|
||||
or
|
||||
|
||||
Or
|
||||
sudo dnf install ncurses-devel ncurses make gcc
|
||||
```sh
|
||||
# yum install ncurses-devel ncurses make gcc
|
||||
```
|
||||
|
||||
Or
|
||||
or
|
||||
|
||||
# dnf install ncurses-devel ncurses make gcc
|
||||
```sh
|
||||
sudo dnf install ncurses-devel ncurses make gcc
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
You can also use Clang to compile.
|
||||
```sh
|
||||
# dnf install ncurses-devel ncurses make gcc
|
||||
```
|
||||
|
||||
You can also use clang to compile (which is what gcc actually is under macOS).
|
||||
|
||||
|
||||
# Compilation notes
|
||||
|
||||
+170
-138
@@ -1,4 +1,11 @@
|
||||
## Warning / caveat about this document
|
||||
# About this document
|
||||
|
||||
In this document I provide information to the herpetologist hackers to help them
|
||||
modify certain things and add features for their studying of snakes. Or if
|
||||
you prefer you can be the snake studying the herpetologist. Whichever character
|
||||
you prefer to play doesn't really matter.
|
||||
|
||||
# Warning / caveat about this document
|
||||
|
||||
WARNING: There are some things cited in this document that are no longer
|
||||
correct, might be misleading or otherwise not clear. This is both intentional
|
||||
@@ -7,21 +14,17 @@ something specific. Put another way just because the table says something
|
||||
doesn't mean it's the whole truth: no misleading comments but misleading
|
||||
document that talks about some parts of the code!
|
||||
|
||||
In this document I provide information to the herpetologist hackers to help them
|
||||
to modify certain things and add features for their studying of snakes. Or if
|
||||
you prefer you can be the snake studying the herpetologist. Whichever character
|
||||
you prefer to play doesn't really matter.
|
||||
|
||||
Please do not assume that just because something is in this file means that it's
|
||||
complete or will work without any changes. As I have changed the game over
|
||||
development stages some features have been dramatically changed and some of
|
||||
these ideas could be incompatible now or otherwise impractical. Also you might
|
||||
find in fact that some of these leave more questions than answers (e.g. some
|
||||
require making decisions for specific problems one might encounter)!
|
||||
complete or will work without any changes (see above). As I have changed the
|
||||
game over development stages some features have been dramatically changed and
|
||||
some of these ideas could be incompatible now or otherwise impractical. Also you
|
||||
might find in fact that some of these leave more questions than answers (e.g.
|
||||
some require making decisions for specific problems one might encounter)!
|
||||
|
||||
With that said here's the C sibilancy (the herpetologist programmer's and
|
||||
snake's syllabary) for all snake and herpetologist programmers alike.
|
||||
|
||||
# Modifying and adding additional features to the code
|
||||
|
||||
* Modifications
|
||||
|
||||
@@ -61,14 +64,14 @@ snake's syllabary) for all snake and herpetologist programmers alike.
|
||||
|
||||
- Max times the bug evades before game over
|
||||
|
||||
* MODIFICATIONS
|
||||
# Modifications
|
||||
|
||||
Here I include information on modifying the game in various ways depending on
|
||||
the preference of the herpetologist (or if you prefer you can be the snake
|
||||
studying the herpetologist).
|
||||
|
||||
|
||||
# Modifying the colours
|
||||
## Modifying the colours
|
||||
|
||||
As I already said I provided a script that prompts you for colours and then
|
||||
compiles the game with those colours (default if invalid input).
|
||||
@@ -82,78 +85,88 @@ and background.
|
||||
To change the colours use the snake-colours.sh or play.sh scripts. Hit enter for
|
||||
defaults if you don't want to change the colour.
|
||||
|
||||
# Background colour of the game field
|
||||
## Background colour of the game field
|
||||
|
||||
I prefer black backgrounds but this is the basic idea behind changing it. You
|
||||
initialise a pair (make it 5 so as to not interfere with the script
|
||||
customisability) and then you use the bkgd() function with the colour pair.
|
||||
Something like this:
|
||||
|
||||
init_pair(5, COLOR_BLACK, COLOR_WHITE);
|
||||
bkgd(COLOR_PAIR(5));
|
||||
```c
|
||||
init_pair(5, COLOR_BLACK, COLOR_WHITE);
|
||||
bkgd(COLOR_PAIR(5));
|
||||
```
|
||||
|
||||
I played with this after winning and I came across some problems with colours
|
||||
but that changes the background of the program anyway.
|
||||
|
||||
The standard colour identifiers are:
|
||||
|
||||
COLOR_BLACK
|
||||
COLOR_RED
|
||||
COLOR_GREEN
|
||||
COLOR_YELLOW
|
||||
COLOR_BLUE
|
||||
COLOR_MAGENTA
|
||||
COLOR_CYAN
|
||||
COLOR_WHITE
|
||||
```c
|
||||
COLOR_BLACK
|
||||
COLOR_RED
|
||||
COLOR_GREEN
|
||||
COLOR_YELLOW
|
||||
COLOR_BLUE
|
||||
COLOR_MAGENTA
|
||||
COLOR_CYAN
|
||||
COLOR_WHITE
|
||||
```
|
||||
|
||||
|
||||
See Linux Journal for more information:
|
||||
|
||||
https://www.linuxjournal.com/content/programming-color-ncurses for more details).
|
||||
See Linux Journal for more information article
|
||||
<https://www.linuxjournal.com/content/programming-color-ncurses> for more
|
||||
details.
|
||||
|
||||
|
||||
# Modifying the characters for the wall, bug and snake
|
||||
## Modifying the characters for the wall, bug and snake
|
||||
|
||||
For the wall, bug and snake body characters you can replace the following in the
|
||||
source code (include the single quotes) respectively:
|
||||
source code (**include the single quotes!**) respectively:
|
||||
|
||||
'#'
|
||||
```
|
||||
'#'
|
||||
|
||||
'*'
|
||||
'*'
|
||||
|
||||
'o'
|
||||
'o'
|
||||
```
|
||||
|
||||
# Modifying input keys
|
||||
## Modifying input keys
|
||||
|
||||
Let's say you don't want to use arrow keys or you don't have arrow keys. Instead
|
||||
you might want the keys 'l', 'r', 'u' and 'd' for the directions. Find the case
|
||||
you might want the keys `l`, `r`, `u` and `d` for the directions. Find the case
|
||||
statements:
|
||||
|
||||
KEY_LEFT
|
||||
KEY_RIGHT
|
||||
KEY_UP
|
||||
KEY_DOWN
|
||||
```c
|
||||
case KEY_LEFT:
|
||||
case KEY_RIGHT:
|
||||
case KEY_UP:
|
||||
case KEY_DOWN:
|
||||
```
|
||||
|
||||
Replace KEY_LEFT with:
|
||||
Replace `KEY_LEFT` with:
|
||||
|
||||
'l'
|
||||
```c
|
||||
'l'
|
||||
```
|
||||
|
||||
(Yes the single quotes matter)
|
||||
|
||||
And do the same thing for the other directions too. If you want more than one
|
||||
and do the same thing for the other directions too. If you want more than one
|
||||
key e.g. the arrow keys and the letters just add another case statement e.g. for
|
||||
left it might be:
|
||||
|
||||
case KEY_LEFT: case 'l':
|
||||
```c
|
||||
case KEY_LEFT: case 'l':
|
||||
```
|
||||
|
||||
Yes the single quotes matter. You can do similar for the other input keys.
|
||||
Please note that modifier keys like ctrl aren't detectable or at least I'm
|
||||
unaware of how to do so.
|
||||
|
||||
|
||||
You can do similar for the other input keys. Please note that modifier keys like
|
||||
ctrl aren't detectable or at least I'm unaware of how to do so.
|
||||
## Modifying the status/score line (table of variables/stats below)
|
||||
|
||||
|
||||
# Modifying the status/score line (table of variables/stats below)
|
||||
|
||||
* SPOILER WARNING
|
||||
### SPOILER WARNING
|
||||
|
||||
Below I give a table of some variables/expressions along with the data types and
|
||||
their respective format specifiers of the data. Originally it was a lot more
|
||||
@@ -167,11 +180,15 @@ different sets. Please also be aware that if you don't want any information you
|
||||
must set it to the below at the very least; defining it without a value is not
|
||||
enough (it amounts to the parameters to a printf call):
|
||||
|
||||
#define J " " );
|
||||
```c
|
||||
#define J " " );
|
||||
```
|
||||
|
||||
If you don't care about brief displays of 'o' at 0,0 you can just have:
|
||||
|
||||
#define J "");
|
||||
```c
|
||||
#define J "");
|
||||
```
|
||||
|
||||
That's the bare minimum. Notice also that it's been a long while since I've
|
||||
tested this part but I think this is right.
|
||||
@@ -191,7 +208,9 @@ coordinates of where the snake is plus the other things that are there (a number
|
||||
of which were added over time). Obviously this would take many bug sized bytes
|
||||
(bites) even once let alone twice! Thus I made it into a define:
|
||||
|
||||
#define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n), Y, y[-2], X,*y,A,g, c);
|
||||
```c
|
||||
#define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n), Y, y[-2], X,*y,A,g, c);
|
||||
```
|
||||
|
||||
With the table below you can show a variety of other variables/statistics.
|
||||
|
||||
@@ -199,7 +218,7 @@ There's another reason for changing this line though: depending on the terminal
|
||||
width the line could cover the top wall; this can even happen only part of the
|
||||
game because the line length is not constant: most of the variables change
|
||||
throughout the game play and as these are displayed the length of the line
|
||||
changes. Use `make test' to get an estimate (it's not perfect).
|
||||
changes. Use `make test` to get an estimate (it's not perfect).
|
||||
|
||||
This is not the fault of my entry but rather how text wraps. But this is another
|
||||
reason it's easy to change: if the terminal size is too short then you can
|
||||
@@ -215,78 +234,83 @@ For an example this would only include the size of the snake and the number of
|
||||
bugs eaten (I think I have this correct; I've made many changes to the point of
|
||||
not wanting to mess with anything that's unnecessary):
|
||||
|
||||
#define J Z(SIZE: %zu BUGS: %zu\n), A, c);
|
||||
```c
|
||||
#define J Z(SIZE: %zu BUGS: %zu\n), A, c);
|
||||
```
|
||||
|
||||
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 NOTES
|
||||
SPECIFIER
|
||||
DESCRIPTION EXPRESSION TYPE FORMAT SPECIFIER
|
||||
|
||||
Snake size A size_t %zu
|
||||
|
||||
Y coordinate Y int %d
|
||||
of snake head
|
||||
|
||||
X coordinate X int %d
|
||||
of snake head
|
||||
|
||||
Max snake size g size_t %zu
|
||||
|
||||
Bugs eaten c size_t %zu
|
||||
|
||||
Bug line (Y) *U int %d
|
||||
|
||||
Bug column (X) *V int %d
|
||||
|
||||
Snake size A size_t %zu
|
||||
|
||||
Growth size (per N size_t %zu
|
||||
bug)
|
||||
|
||||
|
||||
Snake size A size_t %zu
|
||||
|
||||
Y coordinate Y int %d
|
||||
of snake head
|
||||
|
||||
X coordinate X int %d
|
||||
of snake head
|
||||
|
||||
Max snake size g size_t %zu
|
||||
|
||||
Bugs eaten c size_t %zu
|
||||
|
||||
Bug line (Y) *U int %d
|
||||
|
||||
Bug column (X) *V int %d
|
||||
|
||||
(Initial) Snake size A size_t %zu
|
||||
|
||||
Growth size (per N size_t %zu
|
||||
bug)
|
||||
|
||||
|
||||
# Make it so the snake starts at a random location
|
||||
## Make it so the snake starts at a random location
|
||||
|
||||
Quite simply change:
|
||||
|
||||
X = H / 2; Y = *x / 2;
|
||||
```c
|
||||
X = H / 2; Y = *x / 2;
|
||||
```
|
||||
|
||||
To be something like:
|
||||
|
||||
X = R(1,H-1);
|
||||
Y = R(2,*x-1);
|
||||
```c
|
||||
X = R(1,H-1);
|
||||
Y = R(2,*x-1);
|
||||
```
|
||||
|
||||
Or whatever you might want it to be... (question to answer: will this work at
|
||||
all? You decide!)
|
||||
|
||||
|
||||
* ADDITIONS (+)
|
||||
# Additions (+)
|
||||
|
||||
Here are some things you could add (including a bit of code).
|
||||
|
||||
|
||||
# Health (and/or Lives)
|
||||
## Health (and/or Lives)
|
||||
|
||||
This was something I thought of a number of times but I opted for other features
|
||||
instead. Here are some ideas on how one might choose to implement something like
|
||||
this. Or maybe it's more like what sorts of things do you have to consider and
|
||||
answer?
|
||||
|
||||
(1) If the snake runs back into itself - thus dying - the snake would actually
|
||||
be slithering inside itself (a rather creepy thought - though they sort of do
|
||||
when they shed their skin). How then would the lives be of any value? If that
|
||||
would constitute as running into itself wouldn't it very quickly lose all lives?
|
||||
0. If the snake runs back into itself - thus dying - the snake would actually be
|
||||
slithering inside itself (a rather creepy thought - though they sort of do when
|
||||
they shed their skin). How then would the lives be of any value? If that would
|
||||
constitute as running into itself wouldn't it very quickly lose all lives?
|
||||
|
||||
I can think of a number of ways to answer this question: by defining specific
|
||||
rules (as in what would be allowed and what wouldn't be) and also by when to
|
||||
decrement the lives.
|
||||
I can think of a number of ways to answer this question: by defining
|
||||
specific rules (as in what would be allowed and what wouldn't be) and also
|
||||
by when to decrement the lives.
|
||||
|
||||
(2) If the snake hits a wall and it's not allowed to where would the snake be
|
||||
1. If the snake hits a wall and it's not allowed to where would the snake be
|
||||
placed? This is similar to (1) but maybe not as many things to consider.
|
||||
|
||||
(3) Should the snake lose its size? WHAT does having another life even MEAN?
|
||||
2. Should the snake lose its size? WHAT does having another life even MEAN?
|
||||
|
||||
(4) Do you want (you do not necessarily need) a new variable that says how many
|
||||
3. Do you want (you do not necessarily need) a new variable that says how many
|
||||
lives you want? Either way probably be good that it can be specified by the
|
||||
player.
|
||||
|
||||
@@ -305,12 +329,12 @@ some other complications.
|
||||
You could do similar for health only maybe the size of the snake decreases or
|
||||
you use the variable you would have used for lives to be health instead.
|
||||
|
||||
Vital issue to resolve: Where is the snake? And if the snake size is decreased
|
||||
Vital issue to resolve: where is the snake? And if the snake size is decreased
|
||||
will you be careful enough that you don't run into the snake where it actually
|
||||
isn't?
|
||||
|
||||
|
||||
# Saving the game
|
||||
## Saving the game
|
||||
|
||||
A few things would have to be done to do this. Maybe more than a few: some
|
||||
decisions and some code.
|
||||
@@ -329,8 +353,8 @@ the number of bugs eaten so far. Alternatively you could have the bug simply be
|
||||
placed somewhere where the snake isn't after replacing (can you replace
|
||||
something with itself?) the snake.
|
||||
|
||||
Question: Do you have to save the WALLS and other environmental variables?
|
||||
You wouldn't have to but you could: If you didn't it would mean that the player
|
||||
Question: do you have to save the WALLS and other environmental variables?
|
||||
You wouldn't have to but you could: if you didn't it would mean that the player
|
||||
could change the growth size on another run for example, or they could disable
|
||||
or enable a feature.
|
||||
|
||||
@@ -355,40 +379,43 @@ It might seem like a difficult task but it's actually not that difficult. It
|
||||
didn't take much time for me to do something like this: as far as saving and
|
||||
loading the values and even setting up ncurses: I just didn't go beyond that.
|
||||
|
||||
Tip: Don't try scr_dump()/scr_restore()/scr_init()/scr_set(). After a quick
|
||||
Tip: **DON'T TRY** `scr_dump()`/`scr_restore()`/`scr_init()`/`scr_set()`. After a quick
|
||||
test in the way I have things set up it seems to cause some problems (also
|
||||
scr_dump() quits the program).
|
||||
`scr_dump()` quits the program).
|
||||
|
||||
You would have to instead identify that restoring is requested, then read in the
|
||||
file (including the coordinates) and then populate the snake arrays, drawing it
|
||||
on screen.
|
||||
|
||||
|
||||
# Different types of walls
|
||||
## Different types of walls
|
||||
|
||||
The game has two modes with walls: if you run into it the game is over (you
|
||||
die) OR you go through it and come out on the opposite side. There certainly are
|
||||
other possibilities though. Here I give some ideas that could be implemented
|
||||
(and one I have some code for).
|
||||
|
||||
# Different types of walls: Blockades
|
||||
### Different types of walls: Blockades
|
||||
|
||||
Instead of the snake either dying or going through and out on the other side
|
||||
what if it's just that the snake is momentarily dazed and unable to move again
|
||||
until it comes round sort of like what happens with some people who pay more
|
||||
attention to their ruddy phone instead of where they're walking (even when
|
||||
crossing a busy street!).
|
||||
I did this once before as an experiment so it can work fine: let's say instead
|
||||
of the snake either dying or going through and out on the other side what if
|
||||
it's just that the snake is momentarily dazed and unable to move again until it
|
||||
comes round sort of like what happens with some people who pay more attention to
|
||||
their ruddy phone instead of where they're walking (even when crossing a busy
|
||||
street!).
|
||||
|
||||
If you look at the walls code you will see a ternary operator for both X and Y
|
||||
If you look at the walls code you will see a ternary operator for both `X` and `Y`
|
||||
coordinates. This of course is very different now but the idea remains the same:
|
||||
|
||||
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;
|
||||
}
|
||||
```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;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
You can ignore the first if if you like; I'm not going to explain that part. The
|
||||
@@ -399,9 +426,11 @@ coordinates to the correct new location.
|
||||
If however you wanted the walls to act as a barrier you could do something like
|
||||
this instead (omitting the inner if statements here):
|
||||
|
||||
X=X<1?1:*H-1;
|
||||
```c
|
||||
X=X<1?1:*H-1;
|
||||
|
||||
Y=Y<2?2:*O-1;
|
||||
Y=Y<2?2:*O-1;
|
||||
```
|
||||
|
||||
Again though that's just the idea; the code is dramatically different. The above
|
||||
incidentally is not even complete.
|
||||
@@ -421,22 +450,25 @@ other words the snake will just appear to be not moving as if the game had been
|
||||
paused.
|
||||
|
||||
|
||||
# Diagonal movement
|
||||
## Diagonal movement
|
||||
|
||||
I said this is impractical so how could it be done? Well you have to decide
|
||||
which keys would take you up and right, up and left, down and right or down and
|
||||
left. The trouble is ncurses can't detect both right and up at the same time.
|
||||
Besides that though it would only be a matter of updating both Y and X
|
||||
Besides that though it would only be a matter of updating both `Y` and `X`
|
||||
coordinates rather than just one or the other. That's easy enough to do. The
|
||||
only impractical part of this is deciding the keys and unfortunately rule 2b
|
||||
(and probably 2b) would have been broken and so have no chance of winning (now
|
||||
that I won it's too much effort and I've forgotten some of the stuff too to say
|
||||
that I won it's too much effort and I've forgotten most of the stuff too to say
|
||||
nothing of getting the format right).
|
||||
|
||||
Anyway it's just a matter of updating both X and Y. But what about going through
|
||||
walls mode? Does it matter? I'll let you figure it out!
|
||||
Anyway it's just a matter of updating both `X` and `Y`. But what about going
|
||||
through walls mode? Does it matter? I'll let you figure it out!
|
||||
|
||||
# Special abilities
|
||||
Looking back at the missing features, this is the feature I wanted more than any
|
||||
other.
|
||||
|
||||
## Special abilities
|
||||
|
||||
Could the snake jump over itself if it wanted to? How would this be implemented?
|
||||
The head would simply be moved one beyond but then you would have to keep track
|
||||
@@ -446,7 +478,7 @@ actually includes it! Then it would only be a matter of deciding what key does
|
||||
what.
|
||||
|
||||
|
||||
# Obstacles
|
||||
## Obstacles
|
||||
|
||||
Similar to walls only that it's inside the field. You would have to consider
|
||||
the behaviour of running into the obstacles: should the snake die? Should it
|
||||
@@ -457,7 +489,7 @@ character. Also to make it simpler if the walls are passable then so too would
|
||||
be the obstacles; else you would die (or if you had health/lives then those
|
||||
would apply).
|
||||
|
||||
# More than one bug
|
||||
## More than one bug
|
||||
|
||||
The main thing to consider would be the test if the snake has eaten a bug would
|
||||
have to check an array (and: how big? Where does the size come from?) as well as
|
||||
@@ -466,14 +498,14 @@ meaning that if you run into a bug spot that has more than one bug you would eat
|
||||
that many bugs).
|
||||
|
||||
|
||||
# Power-ups
|
||||
## Power-ups
|
||||
|
||||
You would need to decide what power-ups exist, what they do, how many can there
|
||||
be (and how many can the snake have at one time), what makes them show up plus
|
||||
you would have to add code to handle the power-ups.
|
||||
|
||||
|
||||
# Snakeskin shedding (becoming an obstacle)
|
||||
## Snakeskin shedding (becoming an obstacle)
|
||||
|
||||
I.e. at some point the snake would split back to some (arbitrary) size but then
|
||||
the snakeskin left would act as the snake in the sense that if the snake runs
|
||||
@@ -483,18 +515,18 @@ slithered out. But that would fill the screen very quickly of course. Maybe the
|
||||
snakeskin has some other purpose?
|
||||
|
||||
|
||||
# Snake moves faster over time
|
||||
## Snake moves faster over time
|
||||
|
||||
In the game Surround you have no control over the speed. I believe there are
|
||||
five different speed levels but the player has no control over it except the
|
||||
drawing mode. It would be possible to make it so the snake moves faster over
|
||||
time. How often and by what amount would probably vary but importantly it would
|
||||
need to not go so fast there's no controlling - or go below 0 which puts it in
|
||||
blocking mode. Probably it would be that it gets faster up to a certain per cent
|
||||
of the original speed so that it doesn't get too fast. But even that would have
|
||||
to be customisable.
|
||||
In the game [Surround](https://en.wikipedia.org/wiki/Surround_(video_game) you
|
||||
have no control over the speed. I believe there are five different speed levels
|
||||
but the player has no control over it except the drawing mode. It would be
|
||||
possible to make it so the snake moves faster over time. How often and by what
|
||||
amount would probably vary but importantly it would need to not go so fast
|
||||
there's no controlling - or go below 0 which puts it in blocking mode. Probably
|
||||
it would be that it gets faster up to a certain per cent of the original speed
|
||||
so that it doesn't get too fast. But even that would have to be customisable.
|
||||
|
||||
# Max times the bug evades before game over
|
||||
## Max times the bug evades before game over
|
||||
|
||||
Basically so that the player is on a time schedule of sorts. The same could be
|
||||
done for maximum number of movements before game over. These would both be
|
||||
|
||||
@@ -114,7 +114,7 @@ PROG= prog
|
||||
#
|
||||
OBJ= ${PROG}.o
|
||||
DATA= COMPILING.md HACKING.md bugs.html bugs.md cake.jpg cannibalism.log.md \
|
||||
chocolate-cake.html chocolate-cake.md crazy.log gameplay.html gameplay.md \
|
||||
chocolate-cake.html chocolate-cake.md crazy.log.md gameplay.html gameplay.md \
|
||||
halfwidth_vs_fullwidth.png ioccc-cake.jpg play.sh prog.2.c prog.3-j.c \
|
||||
prog.3.c snake-colours.sh snake.1 spoilers.html spoilers.md \
|
||||
termcaps.c terminals.html terminals.md troubleshooting.html troubleshooting.md
|
||||
|
||||
+65
-84
@@ -15,62 +15,67 @@ make
|
||||
|
||||
```sh
|
||||
WAIT=N WALLS=[01] EVADE=N SIZE=N MAXSIZE=N GROW=N SHEDS=N SHED=N CANNIBAL=[01] ./prog
|
||||
# Start pressing some arrow keys
|
||||
# start pressing some arrow keys
|
||||
```
|
||||
|
||||
Variables:
|
||||
where `N` is a number and `[01]` is either `1` or `0` (or more correctly zero
|
||||
and non-zero).
|
||||
|
||||
* WAIT
|
||||
### Variables:
|
||||
|
||||
* **`WAIT`**
|
||||
positive or negative integer that changes how long to wait for
|
||||
a key press prior to moving again. < 0 blocks which allows
|
||||
for complete control over movement at your own pace. Default
|
||||
231; you can move faster by holding down an arrow key.
|
||||
231; you can move faster by holding down or rapidly pressing an
|
||||
arrow key.
|
||||
|
||||
* WALLS
|
||||
whether the walls are passable or impassable (default
|
||||
passable). 0 means impassable; 1 passable.
|
||||
* **`WALLS`**
|
||||
whether the walls are passable or impassable. Default passable,
|
||||
1; 0 disables.
|
||||
|
||||
* EVADE
|
||||
* **`EVADE`**
|
||||
how many movements the Snake moves before the bug (well
|
||||
insect; see notes below about why bugs) is will move to
|
||||
another location on the field.
|
||||
insect; see notes below about why bugs) will move to
|
||||
another location in the field. Default 300; 0 disables.
|
||||
|
||||
* SIZE
|
||||
* **`SIZE`**
|
||||
initial size of the Snake. Note that it grows by one per
|
||||
move so at the default 5 it will not initially be 5
|
||||
characters long! < 0 is an immediate win.
|
||||
|
||||
* MAXSIZE
|
||||
* **`MAXSIZE`**
|
||||
the maximum size the Snake can become before the game is
|
||||
won. < 0 is the maximum size based on terminal dimensions;
|
||||
any other size will be capped based on the terminal
|
||||
dimensions to prevent problems.
|
||||
dimensions to prevent problems. Note that when **`SIZE+GROW >=
|
||||
MAXSIZE`** you win _before_ you grow to the full size!
|
||||
|
||||
* GROW
|
||||
size to grow every time you eat a bug. Negative values are
|
||||
allowed! This creates for fun gameplay modes with enough
|
||||
creativity. See [gameplay.html](gameplay.html) for some
|
||||
examples.
|
||||
* **`GROW`**
|
||||
size to grow every time you eat a bug. Default 5; negative
|
||||
values are allowed. 'Negativity' creates for fun gameplay modes with
|
||||
enough creativity. See [gameplay.md](gameplay.md) /
|
||||
[gameplay.html](gameplay.html) as well as [play.sh](play.sh) for some examples.
|
||||
|
||||
* SHED
|
||||
every SHED movements you will grow (> 0), shrink (< 0) or
|
||||
not at all (0) by the SHEDS value. Again with creativity you
|
||||
can create some fun gameplay modes.
|
||||
|
||||
NOTE: SHED and SHEDS is actually a misnomer; see notes
|
||||
* **`SHED`**
|
||||
every **`SHED`** movements you will grow (> 0), shrink (< 0) or
|
||||
stay the same length (0) by the **`SHEDS`** (below) value. Again
|
||||
with creativity you can create some fun gameplay modes. NOTE:
|
||||
the concept of shedding in this game is a misnomer; see notes
|
||||
below.
|
||||
|
||||
* SHEDS
|
||||
every SHED movements will impact what this value means: grow
|
||||
(> 0), shrink (< 0) or not at all (0). Again with creativity
|
||||
you can create some fun gameplay modes here. For instance
|
||||
you can grow upon eating a bug but shrink every SHED
|
||||
movements and it's a battle of whether you win by SIZE < 0
|
||||
or SIZE >= MAXSIZE. See play.sh for examples.
|
||||
NOTE: SHED and SHEDS is actually a misnomer; see notes
|
||||
below.
|
||||
* **`SHEDS`**
|
||||
every **`SHED`** movements will impact what this value means: grow
|
||||
(> 0), shrink (< 0) or not at all (0). Exception: if the snake
|
||||
eats a bug the counter isn't incremented. Again with creativity
|
||||
you can create some fun gameplay modes here. For instance you
|
||||
can grow upon eating a bug but shrink every **`SHED`** movements
|
||||
and then it's a battle of whether you win by **`SIZE < 0`** or
|
||||
**`SIZE >= MAXSIZE`**. See [play.sh](play.sh) for examples.
|
||||
NOTE: the concept of shedding in this game is a misnomer; see
|
||||
notes below.
|
||||
|
||||
* CANNIBAL
|
||||
* **`CANNIBAL`**
|
||||
whether you can go through the Snake or not. Default is 0
|
||||
(cannot).
|
||||
|
||||
@@ -137,52 +142,27 @@ Read ***ONLY*** if you really must give up trying to de-obfuscate!
|
||||
|
||||
Snake has two cheat modes (passable walls and self [cannibalism]), a drawing (or
|
||||
practising) mode, *can play by itself (**and win!**)*, is coloured (included
|
||||
[snake-colours.sh][] and [play.sh][] scripts compile in player-selected
|
||||
colours) and there are many other play modes (many more can be devised with the
|
||||
[snake-colours.sh][] and [play.sh][] scripts compile in player-selected colours)
|
||||
and there are many other play modes (many more can be devised with the
|
||||
imagination and the environmental variables; see [gameplay.html][] for many
|
||||
examples) and options. You can pause and there's even a built-in test unit for
|
||||
some features! The following variables change the game in the following ways
|
||||
(all can be combined):
|
||||
examples and [play.sh][] for preconfigured modes) and options. You can pause
|
||||
and there's even a built-in test unit for some features! The variables
|
||||
mentioned in the to run section at the top of this file modify the behaviour of
|
||||
Snake.
|
||||
|
||||
Here are some other features of the game:
|
||||
|
||||
* The speed of the snake: how many milliseconds to **WAIT** for input before
|
||||
moving; *default 231 milliseconds*. You can move faster by pressing a
|
||||
direction key quicker or even holding it down.
|
||||
|
||||
* If the bug (to eat) will move (**EVADE**) after user-specified number of snake
|
||||
moves (*default 300, 0 disables*).
|
||||
|
||||
* If the snake can go through **WALLS** (coming out at the opposite wall)
|
||||
(*default 1, yes*).
|
||||
|
||||
* If the snake can go through itself (**CANNIBAL**) (*default 0, no*).
|
||||
|
||||
* The initial **SIZE** of the snake (*default 5*). Note that it grows one by
|
||||
each movement so even if you start at 5 it will take some movements before
|
||||
you are the full length.
|
||||
|
||||
* The size the snake must become in order to win the game (**MAXSIZE**, *default 997*).
|
||||
|
||||
* How much to **GROW** each time a bug is eaten (*default 5*, can be negative).
|
||||
|
||||
* How many moves (**SHED**, *default 0, disabled*) before 'stretching' (grow)
|
||||
(**SHEDS**, *default 5*; can be negative). This is how snakes grow in the wild so is a
|
||||
misnomer here because snakes don't grow in the manner that the original
|
||||
Snake game was designed.
|
||||
|
||||
- Exception: if the bug is eaten the counter isn't incremented.
|
||||
|
||||
* A drawing/practising mode (**WAIT** < 0 makes `timeout()` set blocking read).
|
||||
* A drawing/practising mode (**`WAIT`** < 0 makes `timeout()` block).
|
||||
|
||||
* Computer plays the game (**WAIT=0**).
|
||||
- **EPILEPSY/STIMULATION OVERLOAD WARNING** included in the relevant
|
||||
section (this goes for a low **EVADE** value too).
|
||||
section (this goes for a low **`EVADE`** value too).
|
||||
|
||||
* Grow-Shrink mode (Positive and Negative Winning) mode (see
|
||||
[gameplay.html][] for more details).
|
||||
|
||||
* The dimensions of the game (this is actually a terminal thing but I document
|
||||
how to do this and its potential pitfalls) (**LINES** , **COLUMNS**).
|
||||
how to do this and its potential pitfalls) (**`LINES`** , **`COLUMNS`**).
|
||||
|
||||
There are no complicated command line invocations; it's just a matter of passing
|
||||
into the game descriptively named variables and I include a script that sets up
|
||||
@@ -228,7 +208,7 @@ though much of it is what's also above). To render try:
|
||||
man ./snake.1
|
||||
```
|
||||
|
||||
The [COMPILING][] file has a few portability notes and the [HACKING][] file has
|
||||
The [COMPILING.md][] file has a few portability notes and the [HACKING.md][] file has
|
||||
some information on how one might modify things, things that could be
|
||||
implemented (and how to/how not to go about some of the things) as well as some
|
||||
other information on the entry (some of which is deliberately not true - a
|
||||
@@ -308,7 +288,8 @@ everything? That's an unintentional lie; I thought it was everything but I
|
||||
implemented many new things after that. In fact I have numerous times thought I
|
||||
was done only to have added yet another feature - or two or three or more!
|
||||
|
||||
Second is the old Atari game [Surround][]. There were a few modes as I recall.
|
||||
Second is the old Atari game [Surround][] (according to Wikipedia it might even
|
||||
be the origin of Snake itself). There were a few modes as I recall.
|
||||
The object of the game was to surround your opponent so that they would run into
|
||||
you, the wall or themselves. The opponent was either the computer or another
|
||||
player.
|
||||
@@ -318,11 +299,11 @@ likewise). There was also a drawing mode where you could just move round making
|
||||
different designs though that this is in my entry is a happy coincidence
|
||||
(because `timeout()` will block when it gets a negative value). It's true that
|
||||
in my Snake it's not quite the same but it's close enough. Perhaps it can be
|
||||
made more like Surround if it grows every movement but then depending on the max
|
||||
made more like [Surround][] if it grows every movement but then depending on the max
|
||||
size of the snake the game might be over fairly quickly (I don't remember how
|
||||
it was done in Surround).
|
||||
it was done in [Surround][]).
|
||||
|
||||
In Surround each move you made you would grow in size by one. This is what
|
||||
In [Surround][] each move you made you would grow in size by one. This is what
|
||||
inspired the shedding mode. Anyway I always loved the game and it's similar to
|
||||
Snake in several ways.
|
||||
|
||||
@@ -427,7 +408,7 @@ And if you're a show-off you can try:
|
||||
- Do more than one or all of the above at the same time (the longer the snake
|
||||
becomes the more often you should do these things).
|
||||
- Eat a [great chocolate cake][]. Actually you should do that whether you're
|
||||
trying to show off or not. Sleep, bathe, eat chocolate cake, play Snake, eat
|
||||
trying to show off or not. Sleep, bath, eat chocolate cake, play Snake, eat
|
||||
chocolate cake, play Snake, sleep, ... For a great recipe see below.
|
||||
|
||||
But if that's not enough I don't know what to tell you other than suggest that
|
||||
@@ -441,7 +422,7 @@ a pun and every pun deserves to be shed).
|
||||
They grow through a process called moulting - shedding their skin (other
|
||||
creatures also moult). This takes place over some days and unlike humans snakes
|
||||
never stop growing (though growth slows down as they mature). I chose the
|
||||
variables **SHED** and **SHEDS** for simplicity and because the words are
|
||||
variables **`SHED`** and **`SHEDS`** for simplicity and because the words are
|
||||
shorter. I don't like the words because it's rather a misnomer but what I had
|
||||
chosen before was longer - STRETCH and STRETCHES.
|
||||
|
||||
@@ -461,10 +442,10 @@ when other implementations don't have it this way. There are a few reasons.
|
||||
|
||||
First is that the friend's implementation had it that way and it had been a long
|
||||
time since I had played it (if I ever did? I don't know now: I played so many
|
||||
games over the years and the game most alike it that I played is Surround, as
|
||||
games over the years and the game most alike it that I played is [Surround][], as
|
||||
below).
|
||||
|
||||
It also is the way it is in Surround.
|
||||
It also is the way it is in [Surround][].
|
||||
|
||||
It makes cannibalism mode very interesting.
|
||||
|
||||
@@ -512,13 +493,13 @@ out bad!
|
||||
I submitted three Snake versions; these are the other layouts for those few
|
||||
(more likely none) who are interested to see them.
|
||||
|
||||
The prog.2.c has more digraphs but I think no other significant differences.
|
||||
The [prog.2.c](prog.2.c) has more digraphs but I think no other significant differences.
|
||||
|
||||
The prog.3.c is in a more artistic layout (a backwards S), has at least one
|
||||
The [prog.3.c](prog.3.c) is in a more artistic layout (a backwards S), has at least one
|
||||
additional obfuscation technique (see spoilers) but it also has more digraphs
|
||||
and as the judges said they feel that digraphs are dated so that's probably why
|
||||
they chose the first layout. The prog.3-j.c version is prog.3.c with a shorter J
|
||||
define.
|
||||
they chose the first layout. The [prog.3-j.c](prog.3-j.c) version is
|
||||
[prog.3.c](prog.3.c) with a shorter `J` macro.
|
||||
|
||||
The prog.alt.c version is the one that allows for customising the bug colour and
|
||||
it's used in both [snake-colours.sh][] and [play.sh][]. It also calls `erase()`
|
||||
@@ -577,8 +558,8 @@ my entries. It's a huge honour; thank you! I also happen to **love** your
|
||||
comments as well as the award titles. And yes indeed 'most of us could use
|
||||
*[Double-layered Chocolate Fudge Cake][]*!'
|
||||
|
||||
[COMPILING]: COMPILING
|
||||
[HACKING]: HACKING
|
||||
[COMPILING.md]: COMPILING.md
|
||||
[HACKING.md]: HACKING.md
|
||||
[bugs.html]: bugs.html
|
||||
[troubleshooting.html]: troubleshooting.html
|
||||
[human snakes]: http://www.macroevolution.net/snake-human-hybrids.html
|
||||
|
||||
+62
-38
@@ -30,7 +30,9 @@ simply a fun consequence of the features I did implement.
|
||||
Let's say you want to verify that the evade mode is at the right count. How
|
||||
can you verify it without modifying the code? Try:
|
||||
|
||||
SIZE=0 SHED=1 SHEDS=1 EVADE=10 ./prog
|
||||
```sh
|
||||
SIZE=0 SHED=1 SHEDS=1 EVADE=10 ./prog
|
||||
```
|
||||
|
||||
Since you start out at size 0 and you shed every movement then when you're
|
||||
size 10 (as long as you don't eat a bug of course!) the bug should evade.
|
||||
@@ -50,7 +52,9 @@ don't at this time remember any I might have done.
|
||||
One way to show this is in full is to set the initial size and growth size to a
|
||||
high value; then try each one individually. For example:
|
||||
|
||||
SIZE=100 ./prog
|
||||
```sh
|
||||
SIZE=100 ./prog
|
||||
```
|
||||
|
||||
In this case after you make the first move the snake will keep growing and
|
||||
so the snake tail stays in the same spot until after it's the 'full size'.
|
||||
@@ -59,7 +63,7 @@ start to move too (i.e. if the tail isn't moving it is growing or else paused).
|
||||
|
||||
In several tests I set the initial size to a high value, the max to a higher
|
||||
value still and enabled cannibalism and much of the screen was full of the snake
|
||||
before it started to move. The [cannibalism.log][] has some examples of both
|
||||
before it started to move. The [cannibalism.log.md][] has some examples of both
|
||||
cannibalism and a long snake that didn't move for most of the game.
|
||||
|
||||
If however you let the snake get to the full size then eat a bug there can
|
||||
@@ -91,7 +95,7 @@ you can safely go back on yourself even without cannibalism enabled. This is
|
||||
intentional; a snake size of 0 is pointless but why should it not be playable
|
||||
anyway?
|
||||
|
||||
If SIZE < 0 you'll likely win straight away since it's unsigned and it'll wrap
|
||||
If `SIZE < 0` you'll likely win straight away since it's unsigned and it'll wrap
|
||||
back to the maximum so you will win automatically (this is the same as the
|
||||
second mode the judges suggested with `SIZE=-1 ./prog`).
|
||||
|
||||
@@ -111,20 +115,28 @@ way negative size will force a win.
|
||||
|
||||
Here's a fun output:
|
||||
|
||||
< <<<+
|
||||
```
|
||||
< <<<+
|
||||
```
|
||||
|
||||
That's from:
|
||||
|
||||
SHED=1 SHEDS=-1 ./prog
|
||||
```sh
|
||||
SHED=1 SHEDS=-1 ./prog
|
||||
```
|
||||
|
||||
And right after that you would see:
|
||||
|
||||
YOU WIN!
|
||||
X:72/156 Y:20/41 S:997/997 B:0
|
||||
```
|
||||
YOU WIN!
|
||||
X:72/156 Y:20/41 S:997/997 B:0
|
||||
```
|
||||
|
||||
Try this though:
|
||||
|
||||
SHEDS=-1 SHED=25 ./prog
|
||||
```sh
|
||||
SHEDS=-1 SHED=25 ./prog
|
||||
```
|
||||
|
||||
And you'll see that you start to be the normal size but then you leave your
|
||||
head several places until you end up getting to the max size (by way of it
|
||||
@@ -134,14 +146,18 @@ this is the basis of the grow/shrink mode of play that I talk about in the
|
||||
|
||||
Here's another thing to be aware of. Let's say you do:
|
||||
|
||||
SIZE=1 GROW=-1 ./prog
|
||||
```sh
|
||||
SIZE=1 GROW=-1 ./prog
|
||||
```
|
||||
|
||||
How many bugs will it take before you win? In fact it's two: you would see the
|
||||
head twice: the second time once you 'shrink' down to size 0; it would then be
|
||||
that if you get another bug you will be at the 'max size':
|
||||
|
||||
YOU WIN!
|
||||
X:81/156 Y:35/41 S:997/997 B:2
|
||||
```sh
|
||||
YOU WIN!
|
||||
X:81/156 Y:35/41 S:997/997 B:2
|
||||
```
|
||||
|
||||
# <a name="bitetail" href="#toc">'I was a few places behind my tail and I ran into it!'</a>
|
||||
|
||||
@@ -161,17 +177,21 @@ For instance it might look like this (the first line is as it happens, the
|
||||
second pointing to where it happens and the third being what's left after the
|
||||
rest of the snake has gone through). Doing `SHED=100 SHEDS=-1`:
|
||||
|
||||
ooooooooo>ooo>
|
||||
^
|
||||
>
|
||||
```
|
||||
ooooooooo>ooo>
|
||||
^
|
||||
>
|
||||
```
|
||||
|
||||
The ^ points to the part that's split from the snake and which will be
|
||||
The `^` points to the part that's split from the snake and which will be
|
||||
there on its own after the snake passes through it. Here's an example with
|
||||
it being `SHEDS=-3`:
|
||||
|
||||
<ooo<ooooo
|
||||
^^^
|
||||
<oo
|
||||
```
|
||||
<ooo<ooooo
|
||||
^^^
|
||||
<oo
|
||||
```
|
||||
|
||||
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
|
||||
@@ -187,14 +207,16 @@ gameplay modes.
|
||||
|
||||
# <a name="buginsnake" href="#toc">It looks like the bug is in the snake</a>
|
||||
|
||||
I show a different example in the [crazy.log][] file but what defines a coordinate
|
||||
I show a different example in the [crazy.log.md][] file but what defines a coordinate
|
||||
which the snake occupies? If the snake breaks apart then the only part
|
||||
of the screen the snake is occupying is the place which is actually moving: if
|
||||
the snake decreases in size by 3 then the three respective characters you can go
|
||||
through safely. But this also means that a bug can go there! So you might see
|
||||
something like:
|
||||
|
||||
<*oooooooo
|
||||
```
|
||||
<*oooooooo
|
||||
```
|
||||
|
||||
This is because the snake is no longer there: in fact in this run the snake was
|
||||
quite a bit lower on the screen and 25 in length.
|
||||
@@ -214,30 +236,32 @@ the game is 10 x 10. This includes the walls and score line.
|
||||
Now the default max snake size is 997 but when the terminal is too small it
|
||||
adjusts the max snake size. For 10 lines and 10 columns you would see:
|
||||
|
||||
$ make test
|
||||
terminal supports cursor movement
|
||||
terminal supports making cursor invisible
|
||||
terminal supports bold
|
||||
terminal supports colours
|
||||
```sh
|
||||
$ 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)
|
||||
terminal rows 10 (7 playable)
|
||||
terminal cols 10 (8 playable)
|
||||
|
||||
snake size: 49 (max size: 49)
|
||||
bugs: 9 (max size: 9)
|
||||
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)
|
||||
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
|
||||
1 problem detected (0 fatal).
|
||||
make: *** [test] Error 1
|
||||
```
|
||||
|
||||
First: what's the problem? It's just a warning that for the snake size of 49 the
|
||||
recommended size of columns is 28. However this is just for the score text; with
|
||||
only 10 columns it will overflow and wrap to the next line(s). But if you observe
|
||||
that 49 is the max snake size. How is this derived and why?
|
||||
|
||||
With 10 rows and columns it's calculated as 7 * 7 (i.e. it's
|
||||
With 10 rows and columns it's calculated as `7 * 7` (i.e. it's
|
||||
`(cols-3)*(rows-3)`. However the number of playable locations is in this case 56
|
||||
(`playable_rows * playable_columns`). I have played with this many
|
||||
times and I do not believe there should be a problem. If there is it's from a
|
||||
@@ -277,7 +301,7 @@ had to say on it:
|
||||
<img src="halfwidth_vs_fullwidth.png">
|
||||
|
||||
However the function `mvaddch()` takes a `chtype` which amounts to a C char
|
||||
with additional information and so the full width Ois too big for the
|
||||
with additional information and so the full width `O`is 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
|
||||
@@ -294,12 +318,12 @@ suggested it is bugging me I once again here say it's not at all bugging me
|
||||
but it is very much appreciated and it means a great deal to me. Cheers.)
|
||||
|
||||
|
||||
[crazy.log]: crazy.log
|
||||
[crazy.log.md]: crazy.log.md
|
||||
[gameplay.md]: gameplay.md
|
||||
[troubleshooting.md]: troubleshooting.md
|
||||
[troubleshooting.html]: troubleshooting.html
|
||||
[gameplay.html]: gameplay.html
|
||||
[cannibalism.log]: cannibalism.log
|
||||
[cannibalism.log.md]: cannibalism.log.md
|
||||
[https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms]: https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms
|
||||
[spoilers]: spoilers.markdown
|
||||
[screenshot of halfwidth vs fullwidth]: halfwidth_vs_fullwidth.png
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
The following are a few screen dumps of:
|
||||
|
||||
SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog
|
||||
```sh
|
||||
SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog
|
||||
```
|
||||
|
||||
As you will see it took 17 bugs to get down to below 0. Notice how I had to get
|
||||
down to 0 more than once: because I moved enough times before I got the last
|
||||
@@ -8,12 +10,15 @@ bug that I grew by 5 in size. I then however moved a bit more and ate a bug
|
||||
which brought me down to -5 therefore winning at the max size of 250. This then
|
||||
showed:
|
||||
|
||||
YOU WIN!
|
||||
X:62/89 Y:5/25 S:250/250 B:17
|
||||
```
|
||||
YOU WIN!
|
||||
X:62/89 Y:5/25 S:250/250 B:17
|
||||
```
|
||||
|
||||
Observe all the arrows on the screen; that's where a bug was that I ate and
|
||||
then I split off losing 10 in size. The first one dump I got myself already to 15:
|
||||
then I split off losing 10 in size. The first dump I'm already at 15/250:
|
||||
|
||||
```
|
||||
X:17/89 Y:15/25 S:15/250 B:13
|
||||
##########################################################################################
|
||||
# <ooooooooo o <ooooooooo* #
|
||||
@@ -40,9 +45,11 @@ X:17/89 Y:15/25 S:15/250 B:13
|
||||
# o o> #
|
||||
# oooooo #
|
||||
##########################################################################################
|
||||
```
|
||||
|
||||
But here now I'm at 0; the head is the sole left arrows:
|
||||
But here now I'm at 0; the head is marked `H` and it's moving left.
|
||||
|
||||
```
|
||||
X:19/89 Y:12/25 S:0/250 B:16
|
||||
##########################################################################################
|
||||
# <ooooooooo o <oooooooo <ooooooo #
|
||||
@@ -55,7 +62,7 @@ X:19/89 Y:12/25 S:0/250 B:16
|
||||
# <oo o o o #
|
||||
# o #
|
||||
# o o #
|
||||
# < o o #
|
||||
# H o o # <- *HEAD, LEFT*
|
||||
# o o o #
|
||||
# <ooo o oo ooooo> #
|
||||
# o o #
|
||||
@@ -69,16 +76,21 @@ X:19/89 Y:12/25 S:0/250 B:16
|
||||
# o o> #
|
||||
# oooooo #
|
||||
##########################################################################################
|
||||
```
|
||||
|
||||
I ended up moving enough times where my size went back up to 5; the head of the
|
||||
snake is in this file line 80 col 56; the bug is at line 81 col 63:
|
||||
I ended up moving enough times where my size went back up to 5.
|
||||
|
||||
Below the snake is moving right and its head is indicated by a `H` with the line
|
||||
marked at the right; the bug is marked as `B` and is also marked at the right.
|
||||
Notice how it's in the body of the snake (but see below)!
|
||||
|
||||
```
|
||||
X:55/89 Y:4/25 S:5/250 B:16
|
||||
##########################################################################################
|
||||
# <ooooooooo o <oooooooo <ooooooo #
|
||||
# o o> oo #
|
||||
# oooo> oooo #
|
||||
# o o oooooo*oo> v #
|
||||
# ooooH oooo # <- *HEAD, RIGHT*
|
||||
# o o ooooooBoo> v # <- *BUG*
|
||||
# o o oo o oo> #
|
||||
# o o o o oo #
|
||||
# o o o oooo #
|
||||
@@ -99,6 +111,7 @@ X:55/89 Y:4/25 S:5/250 B:16
|
||||
# o o> #
|
||||
# oooooo #
|
||||
##########################################################################################
|
||||
```
|
||||
|
||||
But did you see anything strange? The bug is on the fourth line below the upper wall.
|
||||
However it appears to be inside the body of the snake! But actually that's just where
|
||||
+308
-237
@@ -78,11 +78,11 @@ For troubleshooting other problems see [troubleshooting.md][]
|
||||
|
||||
# 2. <a name="input" href="#toc">Input keys</a>
|
||||
|
||||
- Left, right, up and down **arrow keys**: Move that direction.
|
||||
- Left, right, up and down **arrow keys**: move that direction.
|
||||
|
||||
- 'q' (and 'Q'): Quit the game.
|
||||
- `q` (and `Q`): quit the game.
|
||||
|
||||
- Space (`' '`): Pause/resume the game (direction keys will also resume).
|
||||
- Space: pause/resume the game (direction keys will also resume).
|
||||
Note that no other keys will resume the game; however if you press a key
|
||||
that `getch()` picks up on and the game is not paused then it will be as if
|
||||
you pressed the current direction key (assuming you already moved the snake).
|
||||
@@ -106,24 +106,26 @@ below. Note that the top line is the score/status line: the top wall is at line
|
||||
(ncurses is the opposite: Y/X). I will parenthesise the numbers below to refer
|
||||
to the number in the diagram:
|
||||
|
||||
X:24/49 Y:8/16 S:5/658 B:0
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# + #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
X:24/49 Y:8/16 S:5/658 B:0
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# + #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
|
||||
```
|
||||
|
||||
- The snake (`+`) is at (24),(8). The bug char is `*` and the wall char is
|
||||
`#`. When the snake moves the head will be an arrow facing the direction it
|
||||
@@ -149,66 +151,72 @@ to the number in the diagram:
|
||||
## <a name="playing" href="#toc">Gameplay: Playing the game</a>
|
||||
|
||||
|
||||
X:39/49 Y:8/16 S:5/658 B:0
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# oooo> #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
X:39/49 Y:8/16 S:5/658 B:0
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# oooo> #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
|
||||
I let the snake grow to its full size (with the head at (39),(8)) and I'm two
|
||||
places above the bug so let's go down:
|
||||
|
||||
X:39/49 Y:9/16 S:5/658 B:0
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# oooo #
|
||||
# v #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
X:39/49 Y:9/16 S:5/658 B:0
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# oooo #
|
||||
# v #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
|
||||
|
||||
Now you see that the snake is going down and in one move the bug will be eaten.
|
||||
Let's do that:
|
||||
|
||||
X:36/49 Y:10/16 S:10/658 B:1
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ^ o #
|
||||
# oooo #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
X:36/49 Y:10/16 S:10/658 B:1
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ^ o #
|
||||
# oooo #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
|
||||
Observe that the bug was eaten and a new bug spawned elsewhere. I went left
|
||||
three and then up one and could slither on to the bug.
|
||||
@@ -220,44 +228,48 @@ By default walls are passable (**WALLS=1**). Let's get to full size and go
|
||||
through the top wall:
|
||||
|
||||
|
||||
X:36/49 Y:15/16 S:10/658 B:1
|
||||
##################################################
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# * o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ^ #
|
||||
##################################################
|
||||
```
|
||||
X:36/49 Y:15/16 S:10/658 B:1
|
||||
##################################################
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# * o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ^ #
|
||||
##################################################
|
||||
```
|
||||
|
||||
There you can see I have grown to the full size and went through the top wall;
|
||||
the head is now at the opposite wall. Continuing:
|
||||
|
||||
X:36/49 Y:11/16 S:10/658 B:1
|
||||
##################################################
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# * o #
|
||||
# o #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ^ #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
##################################################
|
||||
```
|
||||
X:36/49 Y:11/16 S:10/658 B:1
|
||||
##################################################
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# * o #
|
||||
# o #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ^ #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
##################################################
|
||||
```
|
||||
|
||||
I might then have turned to the left and then shortly go up to get the bug. This
|
||||
goes on until you lose, quit or win the game.
|
||||
@@ -266,30 +278,32 @@ goes on until you lose, quit or win the game.
|
||||
When you specify **WALLS=0** the walls become an obstacle that end the game. It
|
||||
might look like (I set the starting size to 150 and had only just started):
|
||||
|
||||
|
||||
X:20/49 Y:2/16 S:150/658 B:0
|
||||
##################################################
|
||||
# ^ #
|
||||
# o #
|
||||
# o * #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# ooooo #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
X:20/49 Y:2/16 S:150/658 B:0
|
||||
##################################################
|
||||
# ^ #
|
||||
# o #
|
||||
# o * #
|
||||
# o #
|
||||
# o #
|
||||
# o #
|
||||
# ooooo #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
|
||||
If I continue going up I will see:
|
||||
|
||||
OUCH!
|
||||
X:20/49 Y:1/16 S:150/658 B:0
|
||||
|
||||
```
|
||||
OUCH!
|
||||
X:20/49 Y:1/16 S:150/658 B:0
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -298,95 +312,104 @@ If I continue going up I will see:
|
||||
By default cannibalism is disabled (**CANNIBAL=0**) so if you run into yourself it might look
|
||||
something like:
|
||||
|
||||
X:45/49 Y:10/16 S:10/658 B:1
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ooooo #
|
||||
# ^ o #
|
||||
# ooo #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
X:45/49 Y:10/16 S:10/658 B:1
|
||||
##################################################
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# ooooo #
|
||||
# ^ o #
|
||||
# ooo #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
##################################################
|
||||
```
|
||||
|
||||
If I were to do any movement but turn to the left I would run into myself. I'll
|
||||
go to the right two spaces:
|
||||
|
||||
OW!
|
||||
X:47/49 Y:10/16 S:10/658 B:1
|
||||
|
||||
```
|
||||
OW!
|
||||
X:47/49 Y:10/16 S:10/658 B:1
|
||||
```
|
||||
|
||||
But **CANNIBAL=1** can look very funny both in movement and still especially
|
||||
when you go through yourself several times when the snake is rather long. For
|
||||
example going through walls and the snake a few times:
|
||||
|
||||
X:4/49 Y:12/16 S:165/658 B:3
|
||||
##################################################
|
||||
#oo o ooooo o o o#
|
||||
# oooo o ooo o#
|
||||
# ooooooooooooooooooo#
|
||||
# o #
|
||||
# oooooooooo o #
|
||||
# o o o #
|
||||
# o oooo o o #
|
||||
# o o o o #
|
||||
# ooooooooooooooo #
|
||||
# o o* #
|
||||
# oo> o o #
|
||||
# o oooooooo o #
|
||||
#oooooooooooooo o oooo oooooooo#
|
||||
# o o o o o #
|
||||
##################################################
|
||||
```
|
||||
X:4/49 Y:12/16 S:165/658 B:3
|
||||
##################################################
|
||||
#oo o ooooo o o o#
|
||||
# oooo o ooo o#
|
||||
# ooooooooooooooooooo#
|
||||
# o #
|
||||
# oooooooooo o #
|
||||
# o o o #
|
||||
# o oooo o o #
|
||||
# o o o o #
|
||||
# ooooooooooooooo #
|
||||
# o o* #
|
||||
# oo> o o #
|
||||
# o oooooooo o #
|
||||
#oooooooooooooo o oooo oooooooo#
|
||||
# o o o o o #
|
||||
##################################################
|
||||
```
|
||||
|
||||
I'll go back through myself now:
|
||||
|
||||
X:6/49 Y:14/16 S:165/658 B:3
|
||||
##################################################
|
||||
#oo o ooooo o o o#
|
||||
# oooo o ooo o#
|
||||
# ooooooooooooooooooo#
|
||||
# o #
|
||||
# oooooooooo o #
|
||||
# o o o #
|
||||
# o oooo o o #
|
||||
# o o o o #
|
||||
# ooooooooooooooo #
|
||||
# o o* #
|
||||
# ooo o o #
|
||||
# oo oooooooo o #
|
||||
#ooooo>oooooooo o oooo oooooooo#
|
||||
# o o o o o #
|
||||
##################################################
|
||||
```
|
||||
X:6/49 Y:14/16 S:165/658 B:3
|
||||
##################################################
|
||||
#oo o ooooo o o o#
|
||||
# oooo o ooo o#
|
||||
# ooooooooooooooooooo#
|
||||
# o #
|
||||
# oooooooooo o #
|
||||
# o o o #
|
||||
# o oooo o o #
|
||||
# o o o o #
|
||||
# ooooooooooooooo #
|
||||
# o o* #
|
||||
# ooo o o #
|
||||
# oo oooooooo o #
|
||||
#ooooo>oooooooo o oooo oooooooo#
|
||||
# o o o o o #
|
||||
##################################################
|
||||
```
|
||||
|
||||
If you note that the head is at (6),(14) I will go one more to the right and you
|
||||
will see that the arrow has moved over:
|
||||
|
||||
X:7/49 Y:14/16 S:165/658 B:3
|
||||
##################################################
|
||||
#oo o ooooo o o o#
|
||||
# oooo o ooo o#
|
||||
# ooooooooooooooooooo#
|
||||
# o #
|
||||
# oooooooooo o #
|
||||
# o o o #
|
||||
# o oooo o o #
|
||||
# o o o o #
|
||||
# ooooooooooooooo #
|
||||
# o o* #
|
||||
# ooo o o #
|
||||
# oo oooooooo o #
|
||||
#oooooo>ooooooo o oooo oooooooo#
|
||||
# o o o o o #
|
||||
##################################################
|
||||
```
|
||||
X:7/49 Y:14/16 S:165/658 B:3
|
||||
##################################################
|
||||
#oo o ooooo o o o#
|
||||
# oooo o ooo o#
|
||||
# ooooooooooooooooooo#
|
||||
# o #
|
||||
# oooooooooo o #
|
||||
# o o o #
|
||||
# o oooo o o #
|
||||
# o o o o #
|
||||
# ooooooooooooooo #
|
||||
# o o* #
|
||||
# ooo o o #
|
||||
# oo oooooooo o #
|
||||
#oooooo>ooooooo o oooo oooooooo#
|
||||
# o o o o o #
|
||||
##################################################
|
||||
```
|
||||
|
||||
Try this: Get a reasonable length and then go back on yourself (if you're going
|
||||
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.
|
||||
@@ -398,22 +421,24 @@ The final example has the snake inside itself.
|
||||
|
||||
# <a name="shedding" href="#toc">Gameplay: Shedding (stretching)</a>
|
||||
|
||||
This feature will make you grow by the value of **SHEDS** for every **SHED**
|
||||
This feature will make you grow by the value of **`SHEDS`** for every **`SHED`**
|
||||
movements (the counter isn't incremented when you eat a bug). Basically growing
|
||||
without eating a bug (stretching would be better name here).
|
||||
|
||||
|
||||
# <a name="winning" href="#toc">Gameplay: Winning</a>
|
||||
|
||||
If you ever get to the **MAXSIZE** the game is won. You can force a win by
|
||||
If you ever get to the **`MAXSIZE`** the game is won. You can force a win by
|
||||
setting the max size to a smaller value than the size you specify (or the
|
||||
default) or setting the size to higher than the default (or < 0 which will end
|
||||
up being > the max size though I suppose there might be some value that makes it
|
||||
less than again - I'm not going to try and figure that out however). Anyway:
|
||||
|
||||
SIZE=-1 ./prog
|
||||
YOU WIN!
|
||||
X:24/49 Y:8/16 S:658/658 B:0
|
||||
```sh
|
||||
SIZE=-1 ./prog
|
||||
YOU WIN!
|
||||
X:24/49 Y:8/16 S:658/658 B:0
|
||||
```
|
||||
|
||||
Observe that the size isn't the default 997: because the screen size is too
|
||||
small for that value (see [terminals.md][]).
|
||||
@@ -422,7 +447,8 @@ 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).
|
||||
at least one cheat mode on my 16" laptop (I don't need both enabled). I don't
|
||||
think I need either for 997.
|
||||
|
||||
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
|
||||
@@ -442,7 +468,9 @@ the game is won is 199 - also a prime!
|
||||
|
||||
If you wish to quit you can hit 'q' (case-insensitive). For example:
|
||||
|
||||
X:24/49 Y:8/16 S:5/658 B:0
|
||||
```
|
||||
X:24/49 Y:8/16 S:5/658 B:0
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -462,7 +490,7 @@ the modes below.
|
||||
## <a name="warning" href="#toc">Photosensitive epilepsy/Stimulation overload trigger warnings</a>
|
||||
|
||||
If you have **photosensitive epilepsy please be careful** especially with low values
|
||||
for both **WAIT** and **EVADE**. It appears that the [number of hertz (flashes)
|
||||
for both **`WAIT`** and **`EVADE`**. It appears that the [number of hertz (flashes)
|
||||
per second triggering seizures][] is wide but depending on the variables it
|
||||
easily can be in the range.
|
||||
|
||||
@@ -479,19 +507,25 @@ If you want to draw the snake wherever you like on the screen you can do this by
|
||||
modifying the wait time (for input) to -1 (or any value < 0): then the snake
|
||||
does not move until you press a movement key. For example:
|
||||
|
||||
WAIT=-1 ./prog
|
||||
```sh
|
||||
WAIT=-1 ./prog
|
||||
```
|
||||
|
||||
|
||||
When you eat a bug the snake will grow and you can draw more. If you want to
|
||||
make it so you can go through yourself:
|
||||
|
||||
WAIT=-1 CANNIBAL=1 ./prog
|
||||
```sh
|
||||
WAIT=-1 CANNIBAL=1 ./prog
|
||||
```
|
||||
|
||||
If you don't want to start out so small (i.e. you want to be able to draw more
|
||||
quickly) you can just set the size to a bigger number (and you could do the same
|
||||
with growth and moult/shed):
|
||||
|
||||
SIZE=50 CANNIBAL=1 WAIT=-1 ./prog
|
||||
```sh
|
||||
SIZE=50 CANNIBAL=1 WAIT=-1 ./prog
|
||||
```
|
||||
|
||||
Do note that although you're a bigger size you still grow one movement at a
|
||||
time.
|
||||
@@ -499,12 +533,16 @@ time.
|
||||
Okay but then if you get too many bugs the drawing will be over. If this proves
|
||||
to be a problem simply do:
|
||||
|
||||
SIZE=100 CANNIBAL=1 WAIT=-1 GROW=0 ./prog
|
||||
```sh
|
||||
SIZE=100 CANNIBAL=1 WAIT=-1 GROW=0 ./prog
|
||||
```
|
||||
|
||||
Or something like that (maybe make the size bigger but that's up to you). You
|
||||
could also set the max size to be the highest possible by saying
|
||||
|
||||
MAXSIZE=-1
|
||||
```sh
|
||||
MAXSIZE=-1
|
||||
```
|
||||
|
||||
Which I've done in the [play.sh][] script.
|
||||
|
||||
@@ -515,11 +553,14 @@ perfect: the snake after all does not leave gaps and the game does not support
|
||||
diagonal movement and I also made a mistake and had to modify what I was aiming
|
||||
for. But you can consider this mode drawing or practice mode.
|
||||
|
||||
oooooooooo ooooo o oo ooooo
|
||||
o o oo o oo o ooo o
|
||||
oooo o oo ooooooo oooo ooooo
|
||||
o o ooo oo o ooo o
|
||||
oooo o oo ooo oooooooo>
|
||||
|
||||
|
||||
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>
|
||||
|
||||
|
||||
|
||||
## <a name="auto" href="#toc">Gameplay mode: Computer playing / Automatic mode (Photosensitive epilepsy/Stimulation overload trigger)</a>
|
||||
@@ -535,7 +576,9 @@ too.
|
||||
|
||||
If you're still here you can create this effect like:
|
||||
|
||||
WAIT=0 WALLS=1 CANNIBAL=1 ./prog
|
||||
```sh
|
||||
WAIT=0 WALLS=1 CANNIBAL=1 ./prog
|
||||
```
|
||||
|
||||
As long as the bug evades you'll find that the snake is growing because it's
|
||||
actually eating bugs; the computer is actually playing the game by itself! You
|
||||
@@ -559,14 +602,18 @@ so with fewer available it has a harder time finding a place in that one line.
|
||||
|
||||
Here's how to make the bug move every time the snake moves:
|
||||
|
||||
CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 ./prog
|
||||
```sh
|
||||
CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 ./prog
|
||||
```
|
||||
|
||||
|
||||
#### Help the computer win fairly quickly
|
||||
|
||||
If you want to see the game 'win' try something like:
|
||||
|
||||
CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 MAXSIZE=10 ./prog
|
||||
```sh
|
||||
CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 MAXSIZE=10 ./prog
|
||||
```
|
||||
|
||||
|
||||
#### Negative growth (Shrink) Automatic mode
|
||||
@@ -574,7 +621,9 @@ If you want to see the game 'win' try something like:
|
||||
Here's a fun one I just thought of (a long time after these other modes were
|
||||
thought of):
|
||||
|
||||
WAIT=0 EVADE=1 GROW=-1 SIZE=9 MAXSIZE=10 CANNIBAL=1 ./prog
|
||||
```sh
|
||||
WAIT=0 EVADE=1 GROW=-1 SIZE=9 MAXSIZE=10 CANNIBAL=1 ./prog
|
||||
```
|
||||
|
||||
What you'll see is that first the snake will get to the size of 9 - whether it
|
||||
shows to be 10 characters depends on whether or not it gets a bug before it can
|
||||
@@ -587,7 +636,9 @@ then the head again (i.e. 1 then 0 in size) and then win! This is also in the
|
||||
|
||||
Of course you can also do something like:
|
||||
|
||||
WAIT=5 WALLS=1 CANNIBAL=1 ./prog
|
||||
```sh
|
||||
WAIT=5 WALLS=1 CANNIBAL=1 ./prog
|
||||
```
|
||||
|
||||
Which although might not seem like it is significantly slower.
|
||||
|
||||
@@ -604,13 +655,17 @@ of success in catching bugs? Obviously the dimensions will affect this value.
|
||||
|
||||
How long will it take for the snake to run into itself? For instance by doing:
|
||||
|
||||
WAIT=0 ./prog
|
||||
```sh
|
||||
WAIT=0 ./prog
|
||||
```
|
||||
|
||||
On my 13" MacBook Pro at the default settings going horizontally the snake ran
|
||||
into itself at:
|
||||
On my 13" MacBook Pro (replaced later by a 16") at the default settings going
|
||||
horizontally the snake ran into itself at:
|
||||
|
||||
OW!
|
||||
X:57/156 Y:20/41 S:155/997 B:30
|
||||
```
|
||||
OW!
|
||||
X:57/156 Y:20/41 S:155/997 B:30
|
||||
```
|
||||
|
||||
What if you set the size to a high value? The lowest? There are bound to be
|
||||
other games to play with this feature!
|
||||
@@ -625,7 +680,9 @@ You have a negative shedding growth and a positive growth size: negative and
|
||||
positive winning. Depending on the parameters specified it might go one way over
|
||||
the other. Try:
|
||||
|
||||
SIZE=150 SHEDS=-5 GROW=10 SHED=50 MAXSIZE=250 ./prog
|
||||
```sh
|
||||
SIZE=150 SHEDS=-5 GROW=10 SHED=50 MAXSIZE=250 ./prog
|
||||
```
|
||||
|
||||
What this does is set the size to 150 (to make it not go down so quickly) and
|
||||
then for each bug you eat it adds 5 to the size; for every 50 moves (that you
|
||||
@@ -639,13 +696,15 @@ The parameters above were chosen after playing with the mode a bit to find a
|
||||
value that wouldn't take that much time but still would pose a challenge. One
|
||||
could reverse it so that one shrinks more than growing.
|
||||
|
||||
The [crazy.log][] file has several screen dumps with this idea.
|
||||
The [crazy.log.md][] file has several screen dumps with this idea.
|
||||
|
||||
You could also have it so that eating a bug makes you shrink and moving so many
|
||||
moves you grow. I tried this and for me it was far more fun. The [play.sh][]
|
||||
also has this mode:
|
||||
|
||||
SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog
|
||||
```sh
|
||||
SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog
|
||||
```
|
||||
|
||||
Obviously there are many other variations. The [play.sh][] script has some
|
||||
of them (the above is option 5; others are 4, 15 and 16 but only options 4 and 5
|
||||
@@ -665,7 +724,9 @@ snake moving too.
|
||||
|
||||
Anyway this might sound absurd but it can be somewhat hypnotic by doing:
|
||||
|
||||
EVADE=1 CANNIBAL=1 ./prog
|
||||
```sh
|
||||
EVADE=1 CANNIBAL=1 ./prog
|
||||
```
|
||||
|
||||
And just moving the snake about not trying to catch any bugs - just let whatever
|
||||
happens happen.
|
||||
@@ -679,7 +740,9 @@ the growth size to 0 and then just move the snake round and round eating bugs
|
||||
until you want to quit. You can enable cannibalism so that you don't have to
|
||||
worry about even running into yourself and losing:
|
||||
|
||||
GROW=0 CANNIBAL=1 ./prog
|
||||
```sh
|
||||
GROW=0 CANNIBAL=1 ./prog
|
||||
```
|
||||
|
||||
|
||||
## <a name="expansibility" href="#toc">Gameplay mode: Expansibility</a>
|
||||
@@ -708,11 +771,15 @@ this file discusses as well as allowing to easily change the colours.
|
||||
|
||||
To do this use the [snake-colours][] script like so:
|
||||
|
||||
./snake-colours
|
||||
```sh
|
||||
./snake-colours
|
||||
```
|
||||
|
||||
If you want to pass in specific variables you can do that too e.g.:
|
||||
|
||||
CANNIBAL=1 ./snake-colours
|
||||
```sh
|
||||
CANNIBAL=1 ./snake-colours
|
||||
```
|
||||
|
||||
The script will prompt you for the colour of the walls, snake head, body and the
|
||||
bug.
|
||||
@@ -729,11 +796,15 @@ you choose uses then the script will override what you pass in.
|
||||
|
||||
To use you can do something like:
|
||||
|
||||
./play.sh
|
||||
```sh
|
||||
./play.sh
|
||||
```
|
||||
|
||||
Or to make it so walls are an obstacle:
|
||||
|
||||
WALLS=0 ./play.sh
|
||||
```sh
|
||||
WALLS=0 ./play.sh
|
||||
```
|
||||
|
||||
|
||||
# 6. <a name="variables" href="#toc">Notes about some of the game variables</a>
|
||||
@@ -750,7 +821,7 @@ snake to move slower you have to increase the wait time!
|
||||
|
||||
## <a name="evade" href="#toc">EVADE: Bug evasion frequency</a>
|
||||
|
||||
For every **EVADE** snake movements the bug will try and find a new place to
|
||||
For every **`EVADE`** snake movements the bug will try and find a new place to
|
||||
occupy. It might be very close to it and I do not ensure it's a new place at
|
||||
all.
|
||||
|
||||
@@ -808,7 +879,7 @@ years ago but I know it's true now. **Believe in yourself. Always.**
|
||||
[number of hertz (flashes) per second triggering seizures]: https://www.epilepsysociety.org.uk/photosensitive-epilepsy#.Xjgpwi2ZOgQ
|
||||
[termcaps.c]: termcaps.c
|
||||
[cannibalism.log.md]: cannibalism.log.md
|
||||
[crazy.log]: crazy.log
|
||||
[crazy.log.md]: crazy.log.md
|
||||
[play.sh]: play.sh
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
|
||||
+113
-125
@@ -2,50 +2,27 @@
|
||||
.SH NAME
|
||||
snake \- Feature\-rich curses implementation of the classic 'Snake' game with many gameplay modes and options for IOCCC 2020
|
||||
.SH SYNOPSIS
|
||||
\fBsnake\fP
|
||||
\fBWAIT\fP=\fIN\fP \fBWALLS\fP=\fI[01]\fP \fBEVADE\fP=\fIN\fP \fBSIZE\fP=\fIN\fP \fBMAXSIZE\fP=\fIN\fP \fBGROW\fP=\fIN\fP \fBSHEDS\fP=\fIN\fP \fBSHED\fP=\fIN\fP \fBCANNIBAL\fP=\fI[01]\fP ./snake
|
||||
.br
|
||||
# start pressing some arrow keys
|
||||
.br
|
||||
where
|
||||
.I N
|
||||
is a number and
|
||||
.I [01]
|
||||
is either
|
||||
.I 1
|
||||
or
|
||||
.I 0
|
||||
(or more correctly zero and non-zero).
|
||||
.SH DESCRIPTION
|
||||
\fBsnake\fP has two cheat modes (passable walls/self[cannibalism]), a drawing/practising mode, \fIcan play by itself\fP (\fBand win!\fP), is coloured (included \fIsnake-colours.sh\fP and \fIplay.sh\fP scripts compile in player\-selected colours) and there are many other play modes (many more can be devised with the imagination and the environmental variables; see \fbENVIRONMENT\fP and the file \fIgameplay.md\fP for many examples) and options.
|
||||
\fBsnake\fP has two cheat modes (passable walls/self[cannibalism]), a drawing/practising mode, \fIcan play by itself\fP (\fBand win!\fP), is coloured (included \fIsnake-colours.sh\fP and \fIplay.sh\fP scripts compile in player\-selected colours) and there are many other play modes (many more can be devised with the imagination and the environmental variables; see \fBENVIRONMENT\fP and the file \fIgameplay.md\fP for many examples) and options.
|
||||
You can pause and there's even a built\-in test unit for some features!
|
||||
Some of the configurable features are:
|
||||
.PP
|
||||
Besides the environmental variables (described below) that create for a lot of gameplay modes, here are some additional features:
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP The speed of the snake (how many milliseconds to \fBWAIT\fP for input before moving; \fIdefault 231 milliseconds\fP and you can move faster by pressing the direction key quicker or or even holding it down).
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP If the bug (to eat) will move (\fBEVADE\fP) after user\-specified number of snake moves (\fIdefault 300, 0 disables\fP).
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP If the snake can go through \fBWALLS\fP (coming out at the opposite wall) (\fIdefault 1, yes\fP).
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP If the snake can go through itself (\fBCANNIBAL\fP) (\fIdefault 0, no\fP).
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP The initial \fBSIZE\fP of the snake (\fIdefault 5\fP).
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP The size the snake must become in order to win the game (\fBMAXSIZE\fP, \fIdefault 997\fP).
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP How much to \fBGROW\fP each time a bug is eaten (\fIdefault 5\fP, can be negative).
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP How many moves (\fBSHED\fP, \fIdefault 0, disabled\fP) before 'stretching' (grow) (\fBSHEDS\fP, \fIdefault 5\fP; can be negative).
|
||||
This is how snakes grow in the wild so is a misnomer here because snakes don't grow in the manner that the original Snake game was designed.
|
||||
.RS
|
||||
\fB\- Exception\fP: If the bug is eaten the counter isn't incremented.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP A drawing mode (\fBWAIT < 0\fP makes \fBtimeout()\fP set blocking read).
|
||||
\fB\-\fP A drawing mode (\fBWAIT < 0\fP makes \fBtimeout()\fP block).
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
@@ -58,10 +35,6 @@ This is how snakes grow in the wild so is a misnomer here because snakes don't g
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP The dimensions of the game (this is actually a terminal thing but I document how to do this and its potential pitfalls) (\fBLINES\fP, \fBCOLUMNS\fP).
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
\fB\-\fP Different colours and characters for the bug, snake head, snake and walls:
|
||||
.RS
|
||||
\fB\-\fP Bug is \fB*\fP (white).
|
||||
@@ -81,69 +54,89 @@ This is how snakes grow in the wild so is a misnomer here because snakes don't g
|
||||
The options are specified via the environmental variables.
|
||||
.SH ENVIRONMENT
|
||||
The following environmental variables modify the behaviour of the game:
|
||||
.TP
|
||||
.B WAIT
|
||||
positive or negative integer that changes how long to wait for a key press prior to moving again.
|
||||
< 0 blocks which allows for complete control over movement at your own pace.
|
||||
Default 231; you can move faster by holding down or rapidly pressing an arrow key.
|
||||
.TQ
|
||||
.B WALLS
|
||||
whether the walls are passable or impassable.
|
||||
Default 1, passable; 0 means impassable.
|
||||
.TQ
|
||||
.B EVADE
|
||||
how many movements the Snake makes before the bug (well insect) will move to another location in the field.
|
||||
Default 300; 0 disables.
|
||||
.TQ
|
||||
.B SIZE
|
||||
initial size of the Snake.
|
||||
Default 5.
|
||||
Note that it grows by one per move so at the default 5 it will not initially be 5 characters long!
|
||||
< 0 is an immediate win.
|
||||
.TQ
|
||||
.B MAXSIZE
|
||||
the maximum size the Snake can become before the game is won.
|
||||
< 0 is the maximum size based on terminal dimensions; any other size will be capped based on the terminal dimensions to prevent problems.
|
||||
Note that when
|
||||
.B SIZE + GROW >= MAXSIZE
|
||||
you win
|
||||
.I before
|
||||
you grow to the full size!
|
||||
.TQ
|
||||
.B GROW
|
||||
size to grow every time you eat a bug.
|
||||
Default 5; can be negative.
|
||||
"Negativity" creates for fun gameplay modes with enough creativity.
|
||||
See \fIgameplay.md\fP/\fIgameplay.html\fP for some examples.
|
||||
\fIplay.sh\fP allows you to reconfigure the colours and play different pre\-configured gameplay modes.
|
||||
.TQ
|
||||
.B SHED
|
||||
every
|
||||
.B SHED
|
||||
movements you will grow (> 0), shrink (< 0) or stay the same length (0) by the
|
||||
.B SHEDS
|
||||
(below) value.
|
||||
Default 0.
|
||||
Again with creativity you can create some fun gameplay modes.
|
||||
NOTE: the concept of shedding in this game is a misnomer.
|
||||
\fB\- Exception\fP: if the bug is eaten the counter isn't incremented.
|
||||
This is how snakes grow in the wild so is a misnomer here because snakes don't grow in the manner that the original Snake game was designed.
|
||||
.TQ
|
||||
.B SHEDS
|
||||
every
|
||||
.B SHED
|
||||
movements will impact what this value means: grow (> 0), shrink (< 0) or not at all (0).
|
||||
Default 0.
|
||||
Again with creativity you can create some fun gameplay modes here.
|
||||
For instance you can grow upon eating a bug but shrink every
|
||||
.B SHED
|
||||
movements and then it's a battle of whether you win by
|
||||
.B SIZE
|
||||
< 0
|
||||
or
|
||||
.B SIZE
|
||||
>=
|
||||
.B MAXSIZE\c
|
||||
\&.
|
||||
See
|
||||
.I play.sh
|
||||
and
|
||||
.I gameplay.html
|
||||
for examples.
|
||||
\fB\- Exception\fP: if the bug is eaten the counter isn't incremented.
|
||||
NOTE: the concept of shedding in this game is a misnomer.
|
||||
\fB\-\fP How many moves (\fBSHED\fP, \fIdefault 0, disabled\fP) before 'stretching' (grow) (\fBSHEDS\fP, \fIdefault 5\fP; can be negative).
|
||||
This is how snakes grow in the wild so is a misnomer here because snakes don't grow in the manner that the original Snake game was designed.
|
||||
.PP
|
||||
\fBGROW\fP
|
||||
.RS
|
||||
How much to grow each time a bug is eaten.
|
||||
Negative growth is a different gameplay mode.
|
||||
\fIDefault 5\fP.
|
||||
.RE
|
||||
\fBSIZE\fP
|
||||
.RS
|
||||
The initial size of the snake.
|
||||
\fIDefault 5\fP.
|
||||
.RE
|
||||
\fBMAXSIZE\fP
|
||||
.RS
|
||||
The max snake size (the size the snake must become to win).
|
||||
\fIDefault 997\fP.
|
||||
Limits are always imposed depending on the size of the terminal.
|
||||
Negative number sets to max size based on terminal size.
|
||||
.RE
|
||||
\fBWAIT\fP
|
||||
.RS
|
||||
The number of milliseconds to wait for input (how fast the snake moves).
|
||||
\fIDefault 231\fP.
|
||||
\fI0\fP has no delay: the computer will play by itself (though you can still change directions).
|
||||
\fI< 0\fP is drawing mode (makes \fIgetch()\fP block).
|
||||
.RE
|
||||
\fBEVADE\fP
|
||||
.RS
|
||||
The number of movements before the bug tries to move to a new place (evading the snake).
|
||||
\fIDefault 300\fP (0 disables).
|
||||
.RE
|
||||
\fBWALLS\fP
|
||||
.RS
|
||||
Whether the snake can go through walls.
|
||||
\fIDefault 1\fP (yes).
|
||||
.RE
|
||||
\fBCANNIBAL\fP
|
||||
.RS
|
||||
Whether the snake can go through itself.
|
||||
\fIDefault 0\fP (no).
|
||||
.RE
|
||||
\fBSHED\fP
|
||||
.RS
|
||||
How many moves before the snake 'moults' (shedding of skin to make room for growth).
|
||||
Again this isn't technically accurate in Snake.
|
||||
\fIDefault 0\fP (disabled).
|
||||
.RE
|
||||
\fBSHEDS\fP
|
||||
.RS
|
||||
The amount to grow by each time the snake sheds its skin.
|
||||
\fIDefault 5\fP.
|
||||
.RE
|
||||
.PP
|
||||
The following two modify the terminal dimensions (this is not part of the game but the terminal/curses itself):
|
||||
.PP
|
||||
\fBLINES\fP
|
||||
.RS
|
||||
The following two modify the terminal dimensions (this is not part of the game but the terminal/curses itself).
|
||||
Elsewhere I document these more and their potential pitfalls.
|
||||
.TP
|
||||
.B LINES
|
||||
The number of rows.
|
||||
Default is the maximum size of the current terminal size (\fBecho $LINES\fP will show the current value).
|
||||
Please note that this is not the number of playable rows but the entire game itself.
|
||||
.RE
|
||||
\fBCOLUMNS\fP
|
||||
.RS
|
||||
.TQ
|
||||
.B COLUMNS
|
||||
The number of columns.
|
||||
Default is the maximum size of the current terminal size (\fBecho $COLUMNS\fP will show the current value).
|
||||
Please note that this is not be the number of playable columns but the entire game itself.
|
||||
@@ -155,7 +148,7 @@ The markdown files have html counterparts; for some of these the html version is
|
||||
.RS
|
||||
Source file to the Snake game (IOCCC entry source file).
|
||||
.RE
|
||||
\fIremarks.markdown\fP
|
||||
\fIREADME.md\fP
|
||||
.RS
|
||||
Describes what the entry (game) is, what it looks like, how to play etc.
|
||||
Includes a variety of other information as well as NAQs (never asked questions that I believe could actually be asked so perhaps better would be infrequently asked questions, IAQs).
|
||||
@@ -172,16 +165,16 @@ Information to help work out any possible problems as well as show how to config
|
||||
.RS
|
||||
A troubleshooting guide focusing more on terminals.
|
||||
.RE
|
||||
\fICOMPILING\fP
|
||||
\fICOMPILING.md\fP
|
||||
.RS
|
||||
Information on Portability, C standards as well as (for the IOCCC judges) both Justifications for certain things and lints.
|
||||
.RE
|
||||
\fIHACKING\fP
|
||||
\fIHACKING.md\fP
|
||||
.RS
|
||||
Documentation on how to modify the input keys, colours, wall, bug and snake chars (to print), the status/score line and various other things.
|
||||
Includes feature ideas as well as how one might implement them.
|
||||
.RE
|
||||
\fIspoilers.markdown\fP
|
||||
\fIspoilers.md\fP
|
||||
.RS
|
||||
Technical details that give more away about how the program works (\fIHACKING\fP also does a bit of this).
|
||||
.RE
|
||||
@@ -189,7 +182,7 @@ Technical details that give more away about how the program works (\fIHACKING\fP
|
||||
.RS
|
||||
To build the terminal capabilities test utility and the Snake game itself.
|
||||
.RE
|
||||
\fIsnake-colours\fP
|
||||
\fIsnake-colours.sh\fP
|
||||
.RS
|
||||
Helper script to compile the game with player selected colours.
|
||||
.RE
|
||||
@@ -197,7 +190,7 @@ Helper script to compile the game with player selected colours.
|
||||
.RS
|
||||
List of bugs and things that might appear to be bugs that aren't, were once bugs etc.
|
||||
.RE
|
||||
\fIchocolate\-cake.markdown\fP
|
||||
\fIchocolate\-cake.md\fP
|
||||
.RS
|
||||
The judges love chocolate and who can blame them? This is something of a speciality of my mum's but it's a delicious cake that even my late stepmum (who only liked white chocolate) loved! Double\-layer chocolate fudge cake.
|
||||
.RE
|
||||
@@ -210,13 +203,13 @@ Source file to test terminal support for the used capabilities the Snake game us
|
||||
See this file to see the manual i.e. this file.
|
||||
Don't get lost in the snake pit!
|
||||
.RE
|
||||
\fIcannibalism.log\fP
|
||||
\fIcannibalism.log.md\fP
|
||||
.RS
|
||||
A screen dump of what cannibalism can look like right before winning.
|
||||
.RE
|
||||
\fIcrazy.log\fP
|
||||
\fIcrazy.log.md\fP
|
||||
.RS
|
||||
A screen dump of the positive/push - negative/shrink mode.
|
||||
Screen dumps of the positive/push - negative/shrink mode.
|
||||
.RE
|
||||
\fIplay.sh\fP
|
||||
.RS
|
||||
@@ -231,21 +224,16 @@ It also clears the screen before playing to try and maintain terminal sanity sho
|
||||
.RE
|
||||
.RE
|
||||
.SH BUGS
|
||||
.RS
|
||||
\fB\-\fP The screen keeps showing bugs!
|
||||
.RE
|
||||
.RS
|
||||
\fB-\fP There's no boss screen.
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP It was written by a human being.
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP Technically walls, snakeskin and the snake itself would \fBnot\fP be an obstacle in real life.
|
||||
\fB\-\fP the screen keeps showing bugs!
|
||||
.br
|
||||
\fB\-\fP there's no boss screen.
|
||||
.br
|
||||
\fB\-\fP it was written by a human being.
|
||||
.br
|
||||
\fB\-\fP technically walls, snakeskin and the snake itself would \fBnot\fP be an obstacle in real life.
|
||||
The shed snakeskin is not an obstacle but walls can be and so can the snake itself.
|
||||
Also snakes grow by moulting (technical term for shedding) so when the snake leaves its snakeskin behind it really ought to grow but instead it shrinks; this means negative shedding ought to have the snake grow and positive shedding have the snake - what?
|
||||
It's a misnomer: it took fewer bytes and the negative shedding is a positive consequence of unsigned arithmetic.
|
||||
.RE
|
||||
.PP
|
||||
On a more serious note see the \fBbugs.md\fP file.
|
||||
.SH EXAMPLES
|
||||
@@ -300,4 +288,4 @@ For more gameplay information and modes check \fIgameplay.md\fP; and for an inte
|
||||
Written by Cody Boone Ferguson for IOCCC 2020 (the 27th IOCCC).
|
||||
.SH SEE ALSO
|
||||
.PP
|
||||
\fB\<https://ioccc.xexyl.net/2020/snake\>\fP The 27th IOCCC 'Don't tread on me award'.
|
||||
\fB\<https://ioccc.xexyl.net/2020/snake\>\fP The 27th IOCCC 'Don't tread on me' award.
|
||||
+62
-44
@@ -38,10 +38,10 @@ already knew that so no harm there, hey?
|
||||
The gameplay I have already described but this explains the way things are
|
||||
actually done in more detail.
|
||||
|
||||
First I initialise curses; if this fails I print an error message ('curses
|
||||
error') and return 1. Next the screen size is determined and I subtract 1 from
|
||||
both x/y. If it's too small curses is ended and an error message ('screen
|
||||
too small') is printed - returning 1.
|
||||
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
|
||||
both `x`/`y`. If it's too small curses is ended and an error message (`screen
|
||||
too small`) is printed - returning 1.
|
||||
|
||||
Next the max size of the snake is determined: if `MAXSIZE` is specified then
|
||||
it's the value of that; otherwise it's the default. But in either case if it's
|
||||
@@ -49,18 +49,18 @@ too big based on the screen dimensions it's capsized. The arrays for the snake
|
||||
are this size + 1. Other environmental variables are also processed.
|
||||
|
||||
Then the arrays are allocated; if either return NULL curses is ended, an error
|
||||
message ('memory error') is printed and return 1.
|
||||
message (`memory error`) is printed and return 1.
|
||||
|
||||
If no errors have occurred I set up colours, turn on bold, set up the keypad
|
||||
etc., place the snake, the bug, draw the walls and then it waits for the first
|
||||
move (or quit of course). Technically I don't 'wait' for input as such: unless
|
||||
the wait time is negative (drawing mode) it's just a non-blocking call up to the
|
||||
WAIT milliseconds but in no event will the snake move until it is told to at
|
||||
`WAIT` milliseconds but in no event will the snake move until it is told to at
|
||||
least once (in drawing mode it will always wait).
|
||||
|
||||
In drawing mode if you pause then when you resume (hit space) the snake will
|
||||
move the last direction it had been told to move - because the direction is set
|
||||
and input was detected (the same goes for another key e.g. 'g' - just like in
|
||||
and input was detected (the same goes for another key e.g. `g` - just like in
|
||||
normal mode). But it will then wait again for input.
|
||||
|
||||
The snake function both draws the snake and updates the arrays; if the new size
|
||||
@@ -85,9 +85,9 @@ loses/quits/wins) the movement proceeds; if the game hasn't started yet it will
|
||||
jump to the top of the loop. If it's paused the same thing until it's resumed.
|
||||
The rest of the loop can be described thusly.
|
||||
|
||||
It checks the current max y/x, draws the walls, bug, gets any input from
|
||||
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
|
||||
`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).
|
||||
|
||||
@@ -99,7 +99,7 @@ it's also game over.
|
||||
|
||||
As the snake moves it will for each move grow by one up to the technical size.
|
||||
This might at times look a bit different from other times but it's a visual
|
||||
thing based on the internal data of the game and the features enabled for
|
||||
thing based on the internal state of the game and the features enabled for
|
||||
example shedding and shedding size.
|
||||
|
||||
Finally if the snake's new coordinates are on a bug a new bug is placed on the
|
||||
@@ -128,13 +128,13 @@ for bugs.
|
||||
|
||||
# <a name="manual-automatic" href="#toc">Drawing (manual) and computer playing (automatic) modes</a>
|
||||
|
||||
How do these modes work? The `timeout()` function takes a signed int: if it's <
|
||||
0 it waits indefinitely; if it's 0 it returns immediately even if there's no
|
||||
input waiting (if input is there then it's used instead); and if it's > 0 it
|
||||
How do these modes work? The `timeout()` function takes a signed int: if it's `<
|
||||
0` it waits indefinitely; if it's `0` it returns immediately even if there's no
|
||||
input waiting (if input is there then it's used instead); and if it's `> 0` it
|
||||
waits that many milliseconds. Thus a negative value allows for complete control
|
||||
over the snake's movement (speed and otherwise), a value of 0 means the snake
|
||||
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).
|
||||
milliseconds (which is how the `0` value comes into play).
|
||||
|
||||
|
||||
# <a name="collision" href="#toc">Collision detection</a>
|
||||
@@ -149,8 +149,8 @@ verifying if the snake head is at a place that's occupied by the snake, the wall
|
||||
or the bug.
|
||||
|
||||
The bug does its best to avoid landing where the snake is but given that snakes
|
||||
are very flexible and cunning who can tell what might happen? As I noted these
|
||||
bugs are not bugs! :)
|
||||
are very flexible and cunning who can tell what might happen? As I noted _these
|
||||
bugs are not bugs! :)_
|
||||
|
||||
|
||||
## <a name="cannibalcollision" href="#toc">Cannibal collision detection</a>
|
||||
@@ -351,7 +351,7 @@ converted this:
|
||||
(!P && (P = 1))||(P=0);
|
||||
|
||||
|
||||
- Makes use of the different 'namespaces' to have variables and labels be the
|
||||
- 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()).
|
||||
|
||||
@@ -361,7 +361,7 @@ two loops (a for() in the 'while()'), re-entering (as in starting over) a for()
|
||||
loop and for dealing with errors.
|
||||
|
||||
- Why do I check for `Q || P` and then goto x only to then check for `!Q && !D`
|
||||
to then goto x? Do I need to check Q at all? In fact I do but at a quick glance
|
||||
to then `goto x`? Do I need to check `Q` at all? In fact I do but at a quick glance
|
||||
it might be easy to miss.
|
||||
|
||||
- Uses an unnamed array (compound literal) for several different game variables.
|
||||
@@ -437,10 +437,10 @@ dimensions. Now in the first call in main() I have the code and tests following:
|
||||
offsets for every time I use negative offsets. But where's the fun in that?
|
||||
:)
|
||||
|
||||
BTW: Some of these are not in the table of expressions in the HACKING file.
|
||||
BTW: Some of these are not in the table of expressions in the HACKING.md 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
|
||||
Spoilers abound in that file (in addition to this file) but the HACKING.md 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!
|
||||
@@ -731,7 +731,7 @@ simply return E() and thus it's only called once. Similarly for `Q` I set it to
|
||||
top of the code and then in main() assigned like: `l = ++(int) { 3 } ;` which
|
||||
equates to 4. I think that's pretty cool!
|
||||
|
||||
- What is this? `for(I=0; A&&I<A-(A-A||A); ++I)` In fact the `A-(A-A||A)` is
|
||||
- What is this? `for(I=0; A&&I<A-(A-A||A); ++I)`. In fact the `A-(A-A||A)` is
|
||||
equivalent to `A-1`: `A` here is always > 0 so `A-A` is 0; however because `A`
|
||||
is non-zero the expression `A-A||A` is equivalent to `0 || A` and since A is
|
||||
non-zero we know that the value is `1` and thus it's `A - 1`! I quite like this
|
||||
@@ -818,25 +818,29 @@ Another thing that reduced a lot of bytes - 34 to be exact - is using the
|
||||
`mvvline()` and `mvhline()` ncurses functions rather than use three for loops to
|
||||
draw the walls.
|
||||
|
||||
Much later on I made it so that the E() function returns 1; this was a clever
|
||||
Much later on I made it so that the `E()` function returns 1; this was a clever
|
||||
way to have what I already did have - return 1 if there's an error (i.e. memory
|
||||
error or curses error or screen too small) but otherwise return 0 without having
|
||||
to have a separate int and I could get rid of two `{}` pairs as well as add
|
||||
another use for the E() function: it calls endwin() exactly once (even though
|
||||
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
|
||||
returning `E()` I am returning 1 but if the end of main() is reached 0 is
|
||||
returned. In either case curses is ended.
|
||||
|
||||
One of these optimisations saved four bytes simply by taking advantage of the
|
||||
value of a loop iterator after the loop. The loop is:
|
||||
|
||||
for (I = 0; A && I < A - 1; ++I)
|
||||
```c
|
||||
for (I = 0; A && I < A - 1; ++I)
|
||||
```
|
||||
|
||||
However after the loop I had this:
|
||||
|
||||
A > 1 && q(n[A - 1],e[A - 1], 'o');
|
||||
```c
|
||||
A > 1 && q(n[A - 1],e[A - 1], 'o');
|
||||
```
|
||||
|
||||
When I was considering moving that line to before the loop it occurred to me
|
||||
that as long as `A > 0` then `A - 1 == I` after the loop. I still had to check
|
||||
@@ -857,43 +861,54 @@ the problem.
|
||||
|
||||
First, the function that turns on colours looked like:
|
||||
|
||||
if (h) attron(m(PAIR(L)));
|
||||
else attroff(m(PAIR(L)));
|
||||
```c
|
||||
if (h) attron(m(PAIR(L)));
|
||||
else attroff(m(PAIR(L)));
|
||||
```
|
||||
|
||||
But I thought is that else actually needed? If I were to switch the order so
|
||||
that the `attroff()` is called first then I could just do an `if (h)` -
|
||||
therefore getting rid of the `else`! But then I thought why not do what I've
|
||||
done elsewhere? I had:
|
||||
|
||||
attroff(m(PAIR(L)));
|
||||
if (h) attron(m(PAIR(L)));
|
||||
```c
|
||||
attroff(m(PAIR(L)));
|
||||
if (h) attron(m(PAIR(L)));
|
||||
```
|
||||
|
||||
But I then saved an extra byte by making it:
|
||||
|
||||
attroff(m(PAIR(L)));
|
||||
h && attron(m(PAIR(L)));
|
||||
```c
|
||||
attroff(m(PAIR(L)));
|
||||
h && attron(m(PAIR(L)));
|
||||
```
|
||||
|
||||
That saved two bytes.
|
||||
|
||||
Second let's look at the B() function: there were two things I thought of that
|
||||
Second let's look at the `B()` function: there were two things I thought of that
|
||||
would save some bytes (I no longer know how many but a few at least possibly six
|
||||
or even more). I had the following code:
|
||||
|
||||
if (V && U && o) { S(N); b(1); }
|
||||
```c
|
||||
if (V && U && o) { S(N); b(1); }
|
||||
```
|
||||
|
||||
This made sure that only if the snake has caught a bug should it grow by the
|
||||
growth size and increase the bug count. But was checking for the `V` or `U`
|
||||
necessary? I gave it a look over and it occurred to me: the only time B() is
|
||||
necessary? I gave it a look over and it occurred to me: the only time `B()` is
|
||||
called with `1` (thus `o` is 1 so the if is true) was if the bug actually is
|
||||
caught. That means I could remove the `V && U &&` part of the if! Thus it became
|
||||
instead:
|
||||
|
||||
if (o) { S(N); b(1); }
|
||||
|
||||
```c
|
||||
if (o) { S(N); b(1); }
|
||||
```
|
||||
|
||||
Then this
|
||||
|
||||
!o && V && U && q U,V,' ');
|
||||
```c
|
||||
!o && V && U && q U,V,' ');
|
||||
```
|
||||
|
||||
...is to make sure to only clear the spot the bug is (or was) at if
|
||||
the bug was NOT eaten. Why not eaten? Because if it was eaten it means the
|
||||
@@ -912,7 +927,9 @@ where the snake already is. So if I had to make sure the game had started (the
|
||||
snake has moved at least once) what could I check? In fact that means the
|
||||
direction is not 0! So I could just replace it with:
|
||||
|
||||
!o && D && q *U,*V,' ');
|
||||
```c
|
||||
!o && D && q *U,*V,' ');
|
||||
```
|
||||
|
||||
That reduced the count further. But then I wondered if even that much is needed.
|
||||
The condition is that the bug has evaded which means the snake has moved already
|
||||
@@ -927,9 +944,11 @@ the score line is updated: so the empty space will be overwritten anyway. And if
|
||||
the score line is made an empty string it doesn't matter because it'll appear as
|
||||
all spaces anyway. Thus I could save another three bytes by changing it to:
|
||||
|
||||
!o && q *U,*V,' ');
|
||||
```c
|
||||
!o && q *U,*V,' ');
|
||||
```
|
||||
|
||||
Technically it would be a `" "` (see [HACKING][] file) else for N (not referring to
|
||||
Technically it would be a `" "` (see [HACKING.md][] 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
|
||||
@@ -939,8 +958,7 @@ imposition on usage (and for that matter having a 'o' at 0,0 isn't either).
|
||||
|
||||
[gameplay.md]: gameplay.md
|
||||
[gameplay.html]: gameplay.html
|
||||
[COMPILING]: COMPILING
|
||||
[HACKING]: HACKING
|
||||
[HACKING.md]: HACKING.md
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved
|
||||
|
||||
@@ -232,7 +232,7 @@ properly. Because that's what funny means in this context.
|
||||
It'd be nice if curses could detect hitting more than one arrow key at the
|
||||
same time so that diagonal directions would be possible but unfortunately it's
|
||||
not (`cat -v` confirms this). Even if I were to define four extra keys what
|
||||
would they be? And what about the head character? The HACKING file has
|
||||
would they be? And what about the head character? The [HACKING](HACKING.md) file has
|
||||
information on this.
|
||||
|
||||
I also limit the terminal size to 10 lines/columns but most likely it would
|
||||
@@ -255,7 +255,7 @@ 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).
|
||||
iocccsize; I talk about it in the [HACKING](HACKING.md) file).
|
||||
|
||||
## <a name="monochrome" href="#toc">Monochrome terminals</a>
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ it as structured as possible/easiest to find.
|
||||
|
||||
Because the score line is dynamic in length depending on the terminal size it
|
||||
can happen that the score/status wraps to the next line(s). This can be fixed by
|
||||
modifying the status line (see [HACKING][]) but you shouldn't need it to be very
|
||||
modifying the status line (see [HACKING.md][]) but you shouldn't need it to be very
|
||||
wide.
|
||||
|
||||
* RESOLUTION #0: Use a bigger screen (it doesn't take that many columns)
|
||||
@@ -59,7 +59,7 @@ wide.
|
||||
#define J Z(B:%zu\n), c);
|
||||
|
||||
Recompile and try again. That will then show only the number of bugs eaten. See
|
||||
the HACKING file for other data you can include (though there are some
|
||||
the [HACKING.md][] file for other data you can include (though there are some
|
||||
discrepancies here and there as you'll see).
|
||||
|
||||
|
||||
@@ -210,18 +210,18 @@ snake. See below for some tests.
|
||||
terminal supports bold
|
||||
terminal supports colours
|
||||
|
||||
terminal rows 42 (39 playable)
|
||||
terminal cols 157 (155 playable)
|
||||
terminal rows 41 (38 playable)
|
||||
terminal cols 154 (152 playable)
|
||||
|
||||
snake size: 997 (max size: 6006)
|
||||
bugs: 199 (max size: 1201)
|
||||
snake size: 997 (max size: 5738)
|
||||
bugs: 199 (max size: 1147)
|
||||
|
||||
at least 34 columns recommended for snake size 997 (is 157)
|
||||
at least 37 columns recommended for snake size 6006 (is 157)
|
||||
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.
|
||||
|
||||
Why are there only 39 playable lines for 42 rows? The first row is the score
|
||||
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
|
||||
you have the left and rightmost columns for the walls.
|
||||
|
||||
@@ -286,7 +286,8 @@ so that's probably why; in CentOS I did have to install it specially.
|
||||
|
||||
The `-m` suffix to terminal names means monochrome. Under Linux this
|
||||
terminal is under `/usr/share/terminfo/l/linux-m` and under macOS (Catalina
|
||||
at least) it's at `/usr/share/terminfo/6c/linux-m`.
|
||||
at least) it's at `/usr/share/terminfo/6c/linux-m` (for macOS Ventura it's
|
||||
`/usr/share/terminfo/6c/linux-m`).
|
||||
|
||||
* BOTTOM LINE: Try using a monochrome terminal for the game by e.g.:
|
||||
|
||||
@@ -295,7 +296,7 @@ so that's probably why; in CentOS I did have to install it specially.
|
||||
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).
|
||||
eat too many bytes in the entry (I cite the functions in the [HACKING.md][] file).
|
||||
|
||||
I discuss colours and terminals in much more detail in
|
||||
[terminals.md][] ([terminals.html][]).
|
||||
@@ -335,7 +336,9 @@ hit a key every time to move because it is blocking.
|
||||
|
||||
What happens if you do:
|
||||
|
||||
WALLS= ./prog
|
||||
```sh
|
||||
WALLS= ./prog
|
||||
```
|
||||
|
||||
Can you run into the wall since you didn't specify a value and the default is 1?
|
||||
No. That's not the way it works. By saying WALLS= you have told the system that
|
||||
@@ -347,43 +350,55 @@ for a number could have a better value than 0.
|
||||
If however you were to give valid input followed by invalid input the valid
|
||||
input would be parsed. For example:
|
||||
|
||||
WALLS=1test ./prog
|
||||
```sh
|
||||
WALLS=1test ./prog
|
||||
```
|
||||
|
||||
Would let you go through the walls. On the other hand
|
||||
would let you go through the walls. On the other hand
|
||||
|
||||
WALLS=test1 ./prog
|
||||
```sh
|
||||
WALLS=test1 ./prog
|
||||
```
|
||||
|
||||
Would not. Furthermore if you specify the same variable more than once it's the
|
||||
would not. Furthermore if you specify the same variable more than once it's the
|
||||
last one that counts. For example:
|
||||
|
||||
WALLS=0 WALLS=1 CANNIBAL=1 CANNIBAL=0 ./prog
|
||||
```sh
|
||||
WALLS=0 WALLS=1 CANNIBAL=1 CANNIBAL=0 ./prog
|
||||
```
|
||||
|
||||
Would allow you to go through walls but you could not cannibalise.
|
||||
would allow you to go through walls but you could not cannibalise.
|
||||
|
||||
Also note that I specify base 0 which means that you can also have it in hex and
|
||||
octal. These are all the same:
|
||||
|
||||
SIZE=0x3
|
||||
SIZE=3
|
||||
SIZE=03
|
||||
```
|
||||
SIZE=0x3
|
||||
SIZE=3
|
||||
SIZE=03
|
||||
```
|
||||
|
||||
The way the functions work is if 0x (or 0X) it's considered hex; if prefixed
|
||||
with a 0 it's octal and otherwise it's decimal. If you specify invalid data
|
||||
(even if only at the beginning of the string) the functions return 0. For
|
||||
example
|
||||
example:
|
||||
|
||||
SIZE=0
|
||||
SIZE=f
|
||||
SIZE=-
|
||||
SIZE=f1
|
||||
```
|
||||
SIZE=0
|
||||
SIZE=f
|
||||
SIZE=-
|
||||
SIZE=f1
|
||||
```
|
||||
|
||||
Are all equivalent.
|
||||
are all equivalent.
|
||||
|
||||
Observe that
|
||||
Observe that:
|
||||
|
||||
SIZE=08
|
||||
```
|
||||
SIZE=08
|
||||
```
|
||||
|
||||
Is invalid input because octal only has digits 0 - 7: the resulting size will be
|
||||
is invalid input because octal only has digits 0 - 7: the resulting size will be
|
||||
0.
|
||||
|
||||
|
||||
@@ -402,31 +417,35 @@ screen size must be at least 10 lines/columns (though in code the number will
|
||||
not be 10); if either is smaller you will get 'screen too small' and the game
|
||||
will end (yes things that haven't begun can be ended).
|
||||
|
||||
If calloc() fails to obtain the needed memory you'll see something like (here it
|
||||
If `calloc()` fails to obtain the needed memory you'll see something like (here it
|
||||
was before I added proper - to make the perfect and obvious pun - capsizing
|
||||
so that by setting the size to -1 it went to the max unsigned value):
|
||||
|
||||
$ MAXSIZE=-1 ./prog
|
||||
memory error
|
||||
X:0/157 Y:0/42 S:3/18446744073709551614 B:0
|
||||
```sh
|
||||
$ MAXSIZE=-1 ./prog
|
||||
memory error
|
||||
X:0/157 Y:0/42 S:3/18446744073709551614 B:0
|
||||
```
|
||||
|
||||
|
||||
BTW: There are two arrays that have to be **MAXSIZE** (technically + 1).
|
||||
BTW: There are two arrays that have to be **`MAXSIZE`** (technically + 1).
|
||||
|
||||
Is it possible that some value specified by the user could mess this up? I do
|
||||
not know but what I do know is that because it's unsigned it can't be negative;
|
||||
if the max size is 0 then the array size will be 1 but it won't matter because
|
||||
the snake size will be >= that max anyway. But here's a curious output:
|
||||
|
||||
SIZE=1 MAXSIZE=0 ./prog
|
||||
YOU WIN!
|
||||
X:78/156 Y:20/41 S:0/0 B:0
|
||||
```sh
|
||||
SIZE=1 MAXSIZE=0 ./prog
|
||||
YOU WIN!
|
||||
X:78/156 Y:20/41 S:0/0 B:0
|
||||
```
|
||||
|
||||
Why does it show snake size as 0 when I specified 1? It's because the max size
|
||||
is 0 and I limit the size to be no bigger than the max size.
|
||||
|
||||
|
||||
[HACKING]: HACKING
|
||||
[HACKING.md]: HACKING.md
|
||||
[prog.c]: prog.c
|
||||
[bugs.md]: bugs.md
|
||||
[terminals.md]: terminals.md
|
||||
|
||||
Reference in new issue
Block a user