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
|
||||
|
||||
James Bonfield
|
||||
MRC Laboratory of Molecular Biology,
|
||||
Hills Road,
|
||||
Cambridge,
|
||||
England
|
||||
James Bonfield
|
||||
MRC Laboratory of Molecular Biology,
|
||||
Hills Road
|
||||
Cambridge
|
||||
England
|
||||
|
||||
|
||||
## To build:
|
||||
|
||||
make all
|
||||
```sh
|
||||
make all
|
||||
```
|
||||
|
||||
[Yusuke Endoh](/winners.html#Yusuke_Endoh) supplied a patch to get this to work
|
||||
in modern systems. Thank you Yusuke!
|
||||
|
||||
|
||||
|
||||
## To run:
|
||||
|
||||
./rince [cabbage]
|
||||
```sh
|
||||
./rince [cabbage]
|
||||
```
|
||||
|
||||
where:
|
||||
[cabbage] a CABBAGE description file (default: `rince.c`)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
`[cabbage]` is a CABBAGE description file (default: `rince.c`)
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
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
|
||||
money 'm' into the dotted region of the screen. The game is considered finished
|
||||
when all the `m`s are then `M`s.
|
||||
- [rince.data3](rince.data3) Sokoban screen 11. You are the `o` character.
|
||||
You must push the money `m` into the dotted region of the screen. The game is
|
||||
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:
|
||||
|
||||
BUGS
|
||||
```
|
||||
BUGS
|
||||
|
||||
...
|
||||
...
|
||||
|
||||
select() should probably return the time remaining from the
|
||||
original timeout, if any, by modifying the time value in
|
||||
place. This may be implemented in future versions of the
|
||||
system. Thus, it is unwise to assume that the timeout
|
||||
pointer will be unmodified by the select() call.
|
||||
select() should probably return the time remaining from the
|
||||
original timeout, if any, by modifying the time value in
|
||||
place. This may be implemented in future versions of the
|
||||
system. Thus, it is unwise to assume that the timeout
|
||||
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
|
||||
timeout remains unmodified.
|
||||
|
||||
It has been suggested that:
|
||||
|
||||
select(k,&y,0,0,&v)
|
||||
|
||||
```c
|
||||
select(k,&y,0,0,&v)
|
||||
```
|
||||
|
||||
should be replaced with:
|
||||
|
||||
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.
|
||||
```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.
|
||||
|
||||
### 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:
|
||||
|
||||
|
||||
struct timeval v= {0,1<<17} ;
|
||||
|
||||
```c
|
||||
struct timeval v= {0,1<<17} ;
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
`/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:
|
||||
|
||||
|
||||
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
|
||||
CABBAGE for short). To execute the program simply type `./rince gamefile`,
|
||||
where `gamefile` is a game description file. A couple are supplied for
|
||||
your enjoyment. Alternatively, with no arguments it will default to using
|
||||
it's own datafile (the source code in fact). This happens to be a game of
|
||||
space invaders. To prevent people from firing too often a very simple
|
||||
method is employed; you must move after firing to be able to fire again.
|
||||
where `gamefile` is a game description file. A few are supplied for your
|
||||
enjoyment. Alternatively, with no arguments it will default to using it's own
|
||||
datafile (the source code in fact). This happens to be a game of [Space
|
||||
Invaders](https://en.wikipedia.org/wiki/Space_Invaders).
|
||||
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
|
||||
|
||||
- Left j
|
||||
- Right l
|
||||
- Fire k
|
||||
- `j` - Left
|
||||
- `l` - Right
|
||||
- `k` - Fire
|
||||
|
||||
This is a new breed of generic games. For instance:
|
||||
|
||||
|
||||
Game play : Whatever you define
|
||||
Keys : Whatever you define
|
||||
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]`
|
||||
|
||||
Portability
|
||||
-----------
|
||||
### Portability
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
* 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.
|
||||
\* I never said it worked! The guidelines state that you dislike programs that
|
||||
won't *compile* under both BSD or SysV `Un*x`. This compiles, and indeed runs
|
||||
on all the others (both BSD and SysV) correctly.
|
||||
|
||||
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.
|
||||
I think the problem may lie in either select(), or curses, (or perhaps
|
||||
conflict of the two).
|
||||
|
||||
The use of `select()` no doubt makes it less portable to STRICT system V
|
||||
machines. However I have tested this on several so-called system V
|
||||
machines, and all of them support select(). In fact, the select() they
|
||||
support appears to be more portable between them than their poll() call.
|
||||
The use of `select()` no doubt makes it less portable to STRICT SysV
|
||||
machines. However I have tested this on several so-called SysV
|
||||
machines, and all of them support `select()`. In fact, the `select()` they
|
||||
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
|
||||
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
|
||||
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
|
||||
efficiency (provided it makes things slightly more obfuscated of course).
|
||||
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
|
||||
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
|
||||
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
|
||||
makes lint complain. The Alpha's lint gave me some positive encouragement!
|
||||
'precedence confusion possible: parenthesize!' :-) :-)
|
||||
main() does not return correctly, because, basically, it doesn't return.
|
||||
`lint` complains about lots of things. Firstly the use of curses immediately
|
||||
makes `lint` complain. The Alpha's `lint` gave me some positive encouragement!
|
||||
`precedence confusion possible: parenthesize!` :-) :-)
|
||||
`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
|
||||
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