Update 1993/rince
Rename rince.design design.md. Format fixes in README.md.
This commit is contained in:
1 parent
08934db250
commit
155a1edae2
3 files changed
+191
-163
No files matched your search
+91
-79
@@ -1,74 +1,81 @@
|
|||||||
# Most Well Rounded
|
# Most Well Rounded
|
||||||
|
|
||||||
James Bonfield
|
James Bonfield
|
||||||
MRC Laboratory of Molecular Biology,
|
MRC Laboratory of Molecular Biology,
|
||||||
Hills Road,
|
Hills Road
|
||||||
Cambridge,
|
Cambridge
|
||||||
England
|
England
|
||||||
|
|
||||||
|
|
||||||
## To build:
|
## To build:
|
||||||
|
|
||||||
make all
|
```sh
|
||||||
|
make all
|
||||||
|
```
|
||||||
|
|
||||||
[Yusuke Endoh](/winners.html#Yusuke_Endoh) supplied a patch to get this to work
|
[Yusuke Endoh](/winners.html#Yusuke_Endoh) supplied a patch to get this to work
|
||||||
in modern systems. Thank you Yusuke!
|
in modern systems. Thank you Yusuke!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## To run:
|
## To run:
|
||||||
|
|
||||||
./rince [cabbage]
|
```sh
|
||||||
|
./rince [cabbage]
|
||||||
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
[cabbage] a CABBAGE description file (default: `rince.c`)
|
|
||||||
|
`[cabbage]` is a CABBAGE description file (default: `rince.c`)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Judges' remarks:
|
## Judges' remarks:
|
||||||
|
|
||||||
The author has provided several CABBAGE files for your amusement:
|
The author has provided several CABBAGE files for your amusement:
|
||||||
|
|
||||||
- `rince.data1` plays breakout. Keys are ',' for left, '/' for right, and '.' for 'fire the ball'.
|
- [rince.data1](rince.data1) plays
|
||||||
|
[Breakout](https://en.wikipedia.org/wiki/Breakout_(video_game). Keys are `,`
|
||||||
|
for left, `/` for right, and `.` for 'fire the ball'.
|
||||||
|
|
||||||
- `rince.data2` plays the old rince game from IOCCC 1991.
|
- [rince.data2](rince.data2) plays the old [Rince](/1991/rince/rince.c)
|
||||||
|
([README.md](/1991/rince/README.md) game from IOCCC 1991.
|
||||||
|
|
||||||
- `rince.data3` Sokoban screen 11. You are the 'o' character. You must push the
|
- [rince.data3](rince.data3) Sokoban screen 11. You are the `o` character.
|
||||||
money 'm' into the dotted region of the screen. The game is considered finished
|
You must push the money `m` into the dotted region of the screen. The game is
|
||||||
when all the `m`s are then `M`s.
|
considered finished when all the `m`s are then `M`s.
|
||||||
|
|
||||||
- `rince.data4` Sokoban screen 13. Same rules as above.
|
- [rince.data4](rince.data4) Sokoban screen 13. Same rules as above.
|
||||||
|
|
||||||
For a brief design description, see [rince.design](rince.design).
|
For a brief design description, see [design.md](design.md).
|
||||||
|
|
||||||
The `select(2)` from SunOS says:
|
The `select(2)` from SunOS says:
|
||||||
|
|
||||||
BUGS
|
```
|
||||||
|
BUGS
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
select() should probably return the time remaining from the
|
select() should probably return the time remaining from the
|
||||||
original timeout, if any, by modifying the time value in
|
original timeout, if any, by modifying the time value in
|
||||||
place. This may be implemented in future versions of the
|
place. This may be implemented in future versions of the
|
||||||
system. Thus, it is unwise to assume that the timeout
|
system. Thus, it is unwise to assume that the timeout
|
||||||
pointer will be unmodified by the select() call.
|
pointer will be unmodified by the select() call.
|
||||||
|
```
|
||||||
|
|
||||||
Systems such as Linux does return the remaining time in timeout
|
Systems such as Linux do return the remaining time in timeout
|
||||||
field (0 if no keys were pressed), but `rince` assumes that
|
field (0 if no keys were pressed), but `rince` assumes that
|
||||||
timeout remains unmodified.
|
timeout remains unmodified.
|
||||||
|
|
||||||
It has been suggested that:
|
It has been suggested that:
|
||||||
|
|
||||||
select(k,&y,0,0,&v)
|
```c
|
||||||
|
select(k,&y,0,0,&v)
|
||||||
|
```
|
||||||
|
|
||||||
should be replaced with:
|
should be replaced with:
|
||||||
|
|
||||||
select(k,&y,0,0,(v.tv_usec=1<<whatever_you_want,&v))
|
```c
|
||||||
|
select(k,&y,0,0,(v.tv_usec=1<<whatever_you_want,&v))
|
||||||
where whatever_you_want is some integer such as 17 or 19.
|
```
|
||||||
|
|
||||||
|
where `whatever_you_want` is some integer such as 17 or 19.
|
||||||
|
|
||||||
### WARNING for SunOS 4.1.x:
|
### WARNING for SunOS 4.1.x:
|
||||||
|
|
||||||
@@ -83,15 +90,16 @@ Some people may want to slow down the game by increasing the
|
|||||||
value 17 in the line:
|
value 17 in the line:
|
||||||
|
|
||||||
|
|
||||||
struct timeval v= {0,1<<17} ;
|
```c
|
||||||
|
struct timeval v= {0,1<<17} ;
|
||||||
|
```
|
||||||
|
|
||||||
to something like 18 or 19.
|
to something like 18 or 19.
|
||||||
|
|
||||||
One may also need to do a "stty sane" if you kill the program
|
One may also need to do a `stty sane` if you kill the program
|
||||||
to restore your terminal state.
|
to restore your terminal state.
|
||||||
|
|
||||||
Some people report that rince dumps core on their system.
|
Some people report that `rince` dumps core on their system.
|
||||||
|
|
||||||
On some systems that use gcc, the curses.h used by gcc (typically
|
On some systems that use gcc, the curses.h used by gcc (typically
|
||||||
`/usr/local/include/curses.h` if not `/usr/include/curses.h`) is not compatible
|
`/usr/local/include/curses.h` if not `/usr/include/curses.h`) is not compatible
|
||||||
@@ -99,27 +107,31 @@ with the curses library (typically `/lib/libcurses.a` for static libraries)
|
|||||||
used. It has been suggested that the following gcc command may help:
|
used. It has been suggested that the following gcc command may help:
|
||||||
|
|
||||||
|
|
||||||
gcc -fno-builtin -I/usr/include -o rince rince.c -lcurses -ltermcap
|
```sh
|
||||||
|
gcc -fno-builtin -I/usr/include -o rince rince.c -lcurses -ltermcap
|
||||||
|
```
|
||||||
|
|
||||||
## Selected notes from the author:
|
|
||||||
|
## Author's remarks:
|
||||||
|
|
||||||
This is a Cellular Automata Based, Beautifully Abysmal Game Environment (or
|
This is a Cellular Automata Based, Beautifully Abysmal Game Environment (or
|
||||||
CABBAGE for short). To execute the program simply type `./rince gamefile`,
|
CABBAGE for short). To execute the program simply type `./rince gamefile`,
|
||||||
where `gamefile` is a game description file. A couple are supplied for
|
where `gamefile` is a game description file. A few are supplied for your
|
||||||
your enjoyment. Alternatively, with no arguments it will default to using
|
enjoyment. Alternatively, with no arguments it will default to using it's own
|
||||||
it's own datafile (the source code in fact). This happens to be a game of
|
datafile (the source code in fact). This happens to be a game of [Space
|
||||||
space invaders. To prevent people from firing too often a very simple
|
Invaders](https://en.wikipedia.org/wiki/Space_Invaders).
|
||||||
method is employed; you must move after firing to be able to fire again.
|
To prevent people from firing too often a very simple method is employed; you
|
||||||
|
must move after firing to be able to fire again.
|
||||||
|
|
||||||
### Keys
|
### Keys
|
||||||
|
|
||||||
- Left j
|
- `j` - Left
|
||||||
- Right l
|
- `l` - Right
|
||||||
- Fire k
|
- `k` - Fire
|
||||||
|
|
||||||
This is a new breed of generic games. For instance:
|
This is a new breed of generic games. For instance:
|
||||||
|
|
||||||
|
|
||||||
Game play : Whatever you define
|
Game play : Whatever you define
|
||||||
Keys : Whatever you define
|
Keys : Whatever you define
|
||||||
Score : If you can figure out how to update it!
|
Score : If you can figure out how to update it!
|
||||||
@@ -127,46 +139,47 @@ Levels : Ahh well... it's not *totally* generic.
|
|||||||
|
|
||||||
The proper definition for usage would be: `./rince [data_filename]`
|
The proper definition for usage would be: `./rince [data_filename]`
|
||||||
|
|
||||||
Portability
|
### Portability
|
||||||
-----------
|
|
||||||
|
|
||||||
I have compiled in on the following systems:
|
I have compiled in on the following systems:
|
||||||
|
|
||||||
System OS Compiler
|
---
|
||||||
-------------------------------------------------------------------------
|
```
|
||||||
|
System OS Compiler (and flags)
|
||||||
|
DECstation 5000/240 Ultrix 4.2A c89 -std
|
||||||
|
SPARCstation 1+ SunOS 4.1 gcc -ansi -pedantic
|
||||||
|
SPARCstation 10/31 Solaris 2.1 gcc -ansi -pedantic (*)
|
||||||
|
DECAlpha 3000/500 OSF/1 V1.2 c89 -std
|
||||||
|
SGI Indigo (R4000) IRIX 4.0.5F cc -ansi
|
||||||
|
Alliant FX2800 Conentrix 3.0.0 fxc
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
DECstation 5000/240 Ultrix 4.2A c89 -std
|
\* I never said it worked! The guidelines state that you dislike programs that
|
||||||
SPARCstation 1+ SunOS 4.1 gcc -ansi -pedantic
|
won't *compile* under both BSD or SysV `Un*x`. This compiles, and indeed runs
|
||||||
SPARCstation 10/31 Solaris 2.1 gcc -ansi -pedantic (*)
|
on all the others (both BSD and SysV) correctly.
|
||||||
DECAlpha 3000/500 OSF/1 V1.2 c89 -std
|
|
||||||
SGI Indigo (R4000) IRIX 4.0.5F cc -ansi
|
|
||||||
Alliant FX2800 Conentrix 3.0.0 fxc
|
|
||||||
|
|
||||||
* I never said it worked! The guidelines state that you dislike programs that
|
|
||||||
won't *compile* under both BSD or SYS V `Un*x`. This compiles, and indeed runs
|
|
||||||
on all the others (both BSD and SYS V) correctly.
|
|
||||||
|
|
||||||
Alas, on Solaris it compiles, but mysteriously stops displaying output
|
Alas, on Solaris it compiles, but mysteriously stops displaying output
|
||||||
after a while until you quit with control C, when it all catches up again.
|
after a while until you quit with control C, when it all catches up again.
|
||||||
I think the problem may lie in either select(), or curses, (or perhaps
|
I think the problem may lie in either select(), or curses, (or perhaps
|
||||||
conflict of the two).
|
conflict of the two).
|
||||||
|
|
||||||
The use of `select()` no doubt makes it less portable to STRICT system V
|
The use of `select()` no doubt makes it less portable to STRICT SysV
|
||||||
machines. However I have tested this on several so-called system V
|
machines. However I have tested this on several so-called SysV
|
||||||
machines, and all of them support select(). In fact, the select() they
|
machines, and all of them support `select()`. In fact, the `select()` they
|
||||||
support appears to be more portable between them than their poll() call.
|
support appears to be more portable between them than their `poll()` call.
|
||||||
|
|
||||||
Obfuscation details
|
|
||||||
-------------------
|
### Obfuscation
|
||||||
|
|
||||||
I have tried to use as many different obfuscation techniques, including
|
I have tried to use as many different obfuscation techniques, including
|
||||||
some of which (such as sizeof confusion) I have not seen in any winners
|
some of which (such as `sizeof` confusion) I have not seen in any winners
|
||||||
(hmmm - perhaps there's a reason for that...) so far. Also, very poor
|
(hmmm - perhaps there's a reason for that...) so far. Also, very poor
|
||||||
structure (yes, I use goto's) has lead to apparently having an fgets() as
|
structure (yes, I use `goto`'s) has led to apparently having an `fgets()` as
|
||||||
the last line of main. Note that I have still tried to aim at least some
|
the last line of main. Note that I have still tried to aim at least some
|
||||||
efficiency (provided it makes things slightly more obfuscated of course).
|
efficiency (provided it makes things slightly more obfuscated of course).
|
||||||
One such thing is the way I dynamically allocate a 2-dimensional array
|
One such thing is the way I dynamically allocate a 2-dimensional array
|
||||||
using only ONE malloc(). Hence this program could be used as a tutorial
|
using only ONE `malloc()`. Hence this program could be used as a tutorial
|
||||||
for all those people who consistently ask this question in the C
|
for all those people who consistently ask this question in the C
|
||||||
newsgroups.
|
newsgroups.
|
||||||
|
|
||||||
@@ -181,13 +194,12 @@ of course... Sometimes I have sacrificed length for obfuscation. It is all
|
|||||||
too easy to change the arguments in main to one character identifiers, but
|
too easy to change the arguments in main to one character identifiers, but
|
||||||
in my opinion they add to obfuscation in this case by being longer.
|
in my opinion they add to obfuscation in this case by being longer.
|
||||||
|
|
||||||
Lint complains about lots of things. Firstly the use of curses immediately
|
`lint` complains about lots of things. Firstly the use of curses immediately
|
||||||
makes lint complain. The Alpha's lint gave me some positive encouragement!
|
makes `lint` complain. The Alpha's `lint` gave me some positive encouragement!
|
||||||
'precedence confusion possible: parenthesize!' :-) :-)
|
`precedence confusion possible: parenthesize!` :-) :-)
|
||||||
main() does not return correctly, because, basically, it doesn't return.
|
`main()` does not return correctly, because, basically, it doesn't return.
|
||||||
|
|
||||||
Bugs
|
### Bugs
|
||||||
----
|
|
||||||
|
|
||||||
Very little error checking is performed. I do check for not being able to
|
Very little error checking is performed. I do check for not being able to
|
||||||
open the requested filename and return 1 upon failure. However, badly
|
open the requested filename and return 1 upon failure. However, badly
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
# Implementation notes
|
||||||
|
|
||||||
|
Due to the long time this has been slowly evolving, it's hard to describe
|
||||||
|
quite whether it's been `implemented`. I think perhaps evolve is a better
|
||||||
|
term. I basic concept behind the program is to describe a game as a simple,
|
||||||
|
slightly cheaty, cellular automata system, with some of the transitions
|
||||||
|
bound to key presses.
|
||||||
|
|
||||||
|
For instance, assume you wish to make a boulder `o` roll off a hill `/`
|
||||||
|
A standard automata would have 2 rules something like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
<pre>
|
||||||
|
|
||||||
|
o.. ...
|
||||||
|
\.. --> 'o' .o. --> '.'
|
||||||
|
... .\.
|
||||||
|
|
||||||
|
</pre>
|
||||||
|
```
|
||||||
|
|
||||||
|
However, the system I devised, in order to keep things small and neat(!),
|
||||||
|
was to define a 3x3 to 3x3 map (instead of the 3x3 to 1x1 shown above).
|
||||||
|
Hence:
|
||||||
|
|
||||||
|
```
|
||||||
|
.o. ...
|
||||||
|
.\. --> .\o
|
||||||
|
... ...
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
This does of course have the odd problem with clashes. What if we want to
|
||||||
|
roll two down boulders down simultaneously towards the same square.
|
||||||
|
I perform no buffering, and so this situation is just a 'fight it out' and
|
||||||
|
let which ever transition has priority win. Such a case may produce the
|
||||||
|
following change of maps (depending on which 'roll' transition is used
|
||||||
|
first).
|
||||||
|
|
||||||
|
```
|
||||||
|
o.o ..o o..
|
||||||
|
\./ changes to \o/ or to \o/
|
||||||
|
... ... ...
|
||||||
|
```
|
||||||
|
|
||||||
|
I claim that it is possible to perform all of the 3x3 to 1x1 transitions in a
|
||||||
|
3x3 to 3x3 based system. One other feature added in is a work around for the 'no
|
||||||
|
buffering' problem. If we define a space ship (as in the [Space
|
||||||
|
Invaders](https://en.wikipedia.org/wiki/Space_Invaders) example) to fly right,
|
||||||
|
and we are 'walking through' our map from top-left to bottom-right, then it is
|
||||||
|
easy to foresee a situation where our space ship would zip right as far as
|
||||||
|
possible in only the one cycle of the automata. However, a similar
|
||||||
|
leftwards-bound space ship would only move the required one square. For this
|
||||||
|
reason I have two lists of transitions and apply them independently of each
|
||||||
|
other; first top-left to bottom right, and the second in the reverse direction.
|
||||||
|
This means that I can make any 'object' move by any amount in a single
|
||||||
|
transition.
|
||||||
|
|
||||||
|
Now comes the key important addition to make it 'game' worthy - the
|
||||||
|
addition of external control by the user. This is done by requesting that
|
||||||
|
some transitions are only valid when a certain key has been pressed.
|
||||||
|
So for example, if we (an `@` symbol) wish to move right when the `l` key
|
||||||
|
is hit we have a transition like:
|
||||||
|
|
||||||
|
## Key: l
|
||||||
|
|
||||||
|
```
|
||||||
|
* * * * * *
|
||||||
|
* @ . * . @
|
||||||
|
* * * * * *
|
||||||
|
```
|
||||||
|
|
||||||
|
Here I also use wildcards. On the match side (left) of the transition, an
|
||||||
|
asterisk will match against any character. On the update side (right), an
|
||||||
|
asterisk means 'keep whatever was here before'. So the above example
|
||||||
|
simply means to swap the `@` and `.` around when `l` is pressed. For the
|
||||||
|
purposes of space saving, this transition is shrunk to a single line.
|
||||||
|
|
||||||
|
## Key: K
|
||||||
|
|
||||||
|
```
|
||||||
|
a b c 1 2 3
|
||||||
|
d e f 4 5 6
|
||||||
|
g h i 7 8 9
|
||||||
|
```
|
||||||
|
|
||||||
|
is written as: `eabcdfghi512346789K`.
|
||||||
|
|
||||||
|
If there are no keys needed for this transition, the character `*1` should
|
||||||
|
be used instead. Now the format of the game description file is now
|
||||||
|
the following: (angle brackets denote an 'entity' to be defined).
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
<top-bot transition>*\n<bot-top transition>*\n<X size>[ \t]+<Y size>\n
|
||||||
|
<map>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `<X size>` should take into account the newline at the end of each line
|
||||||
|
of map, and hence should also be one larger than expected.
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
Implementation notes
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Due to the long time this has been slowly evolving, it's hard to describe
|
|
||||||
quite whether it's been `implemented'. I think perhaps evolve is a better
|
|
||||||
term. I basic concept behind the program is to describe a game as a simple,
|
|
||||||
slightly cheaty, cellular automata system, with some of the transitions
|
|
||||||
bound to key presses.
|
|
||||||
|
|
||||||
For instance, assume you wish to make a boulder 'o' roll off a hill '/'
|
|
||||||
A standard automata would have 2 rules something like this:
|
|
||||||
|
|
||||||
|
|
||||||
o.. ...
|
|
||||||
\.. --> `o' .o. --> `.'
|
|
||||||
... .\.
|
|
||||||
|
|
||||||
|
|
||||||
However, the system I devised, in order to keep things small and neat(!),
|
|
||||||
was to define a 3x3 to 3x3 map (instead of the 3x3 to 1x1 shown above).
|
|
||||||
Hence:
|
|
||||||
|
|
||||||
.o. ...
|
|
||||||
.\. --> .\o
|
|
||||||
... ...
|
|
||||||
|
|
||||||
This does of course have the odd problem with clashes. What if we want to
|
|
||||||
roll two down boulders down simultaneously towards the same square.
|
|
||||||
I perform no buffering, and so this situation is just a 'fight it out' and
|
|
||||||
let which ever transition has priority win. Such a case may produce the
|
|
||||||
following change of maps (depending on which 'roll' transition is used
|
|
||||||
first).
|
|
||||||
|
|
||||||
o.o ..o o..
|
|
||||||
\./ changes to \o/ or to \o/
|
|
||||||
... ... ...
|
|
||||||
|
|
||||||
I claim that it is possible to perform all of the 3x3 to 1x1 transitions
|
|
||||||
in a 3x3 to 3x3 based system. One other feature added in is a work around
|
|
||||||
for the 'no buffering' problem. if we define an space ship (as in the
|
|
||||||
space invader example) to fly right, and we are 'walking through' our map
|
|
||||||
from top-left to bottom-right, then it is easy to foresee a situation where
|
|
||||||
our space ship would zip right as far as possible in only the one cycle
|
|
||||||
of the automata. However, a similar leftwards-bound space ship would only
|
|
||||||
move the required one square. For this reason I have two lists of
|
|
||||||
transitions and apply them independently of each other; first top-left to
|
|
||||||
bottom right, and the second in the reverse direction. This means that I
|
|
||||||
can make any 'object' move by any amount in a single transition.
|
|
||||||
|
|
||||||
Now comes the key important addition to make it 'game' worthy - the
|
|
||||||
addition of external control by the user. This is done by requesting that
|
|
||||||
some transitions are only valid when a certain key has been pressed.
|
|
||||||
So for example, if we (an @ symbol) wish to move right when the 'l' key
|
|
||||||
is hit we have a transition like:
|
|
||||||
|
|
||||||
Key: l
|
|
||||||
* * * * * *
|
|
||||||
* @ . * . @
|
|
||||||
* * * * * *
|
|
||||||
|
|
||||||
Here I also use wildcards. On the match side (left) of the transition, an
|
|
||||||
asterisk will match against any character. On the update side (right), an
|
|
||||||
asterisk means 'keep whatever was here before'. So the above example
|
|
||||||
simply means to swap the '@' and '.' around when 'l' is pressed. For the
|
|
||||||
purposes of space saving, this transition is shrunk to a single line.
|
|
||||||
|
|
||||||
Key: K
|
|
||||||
a b c 1 2 3
|
|
||||||
d e f 4 5 6
|
|
||||||
g h i 7 8 9
|
|
||||||
|
|
||||||
is written as:
|
|
||||||
|
|
||||||
eabcdfghi512346789K
|
|
||||||
|
|
||||||
If there are no keys needed for this transition, the character '*' should
|
|
||||||
be used instead. Now the format of the game description file is now
|
|
||||||
the following: (angle brackets denote an 'entity' to be defined).
|
|
||||||
|
|
||||||
<top-bot transition>*\n<bot-top transition>*\n<X size>[ \t]+<Y size>\n
|
|
||||||
<map>
|
|
||||||
|
|
||||||
The <X size> should take into account the newline at the end of each line
|
|
||||||
of map, and hence should also be one larger than expected.
|
|
||||||
Reference in new issue
Block a user