Add preview of 1984-2019
The 2020 winners are hinted it, but the source code is not there,
nor are the hints. Someone could look into the HTML and
see what was commented out, but that is not a problem because
WHO won is known and the name of their AWARD is known already.
Moreover a number of the winners have talked about what their
entirs do, so the commented out spoiler text is not a bit problem.
One will find HTML commented out with:
<!-- XXX remove when 2020 is ready
2020 links here
XXX remove when 2020 is ready -->
The "XXX remove when 2020 is ready" string is found at the
start and end comment blocks. Again, soneone could read
what was commented out, but that is OK since most of that
information is known or can be known. The following files
have such HTML comment blocks in them.
./winners.html
./years-spoiler.html
./years.html
In addition, ./all/summary.txt was modified to not
include the 2020 entries for the momemt.
The 2020 winner code AND write-ups are NOT part of this set.
p.s. The all/all.tar.bz2 does not contain the 2020 source code (yet?).
This commit is contained in:
1 parent
28efc67f5d
commit
c0663537cb
1683 files changed
+220064
No files matched your search
Binary file not shown.
+197
@@ -0,0 +1,197 @@
|
||||
#!/bin/make
|
||||
# 2001 makefile
|
||||
#
|
||||
# Copyright (C) Simon Cooper, Landon Curt Noll, Peter Seebach, 2001.
|
||||
# All Rights Reserved. Permission for personal, educational or non-profit
|
||||
# use is granted provided this this copyright and notice are included in its
|
||||
# entirety and remains unaltered. All other uses must receive prior permission
|
||||
# from the contest judges.
|
||||
|
||||
SHELL= /bin/sh
|
||||
CAT= cat
|
||||
RM= rm
|
||||
SED= sed
|
||||
TRUE= true
|
||||
|
||||
# optimization
|
||||
#
|
||||
# Most compiles will safely use -O2. Some can use only -O.
|
||||
# A few compilers have broken optimizers and thus you may
|
||||
# not want anything.
|
||||
#
|
||||
#OPT=
|
||||
#OPT= -O
|
||||
OPT= -O2
|
||||
|
||||
# flags for ANSI compiles
|
||||
#
|
||||
# NOTE: Some ANSI compilers make use of -Xa to turn on ANSI mode,
|
||||
# others such as gcc may want -ansi, others (Compaq Tru64 Unix)
|
||||
# want -std1, and others may want nothing at all.
|
||||
# Adjust the CFLAGS line as needed.
|
||||
#
|
||||
# NOTE: Some compilers cannot optimize, or optimize some entries
|
||||
# incorrectly. You might want to turn on -O to see if your
|
||||
# compiler can handle them.
|
||||
#
|
||||
#
|
||||
#CFLAGS= -Xa ${OPT}
|
||||
#CFLAGS= -std1 $(OPT)
|
||||
CFLAGS= -ansi ${OPT}
|
||||
|
||||
# NOTE: On some systems, the library path does not include the location
|
||||
# of the X11 libraries. You might need to use a -L/path/to/X11/lib/dir
|
||||
# in order to compile with these libs.
|
||||
#
|
||||
X11CCFLAGS= -I/usr/X11R6/include -I/usr/X11R6/include/X11 -I/usr/include/X11
|
||||
#X11CCFLAGS=
|
||||
X11LDFLAGS= -L/usr/X11R6/lib -Wl,-R/usr/X11R6/lib
|
||||
#X11LDFLAGS=
|
||||
|
||||
# ANSI compiler
|
||||
#
|
||||
# Set CC to the name of your ANSI compiler.
|
||||
#
|
||||
# Some entries seem to need gcc. If you have gcc, set
|
||||
# both CC and MAY_NEED_GCC to gcc.
|
||||
#
|
||||
# If you do not have gcc, set CC to the name of your ANSI compiler, and
|
||||
# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just :
|
||||
# to disable such programs.
|
||||
#
|
||||
CC= cc
|
||||
MAY_NEED_GCC= gcc
|
||||
|
||||
# winners that compile under ANSI C
|
||||
#
|
||||
WINNERS= anonymous bellard bellard.otccex cheong coupard \
|
||||
ctk dgbeards herrmann1 herrmann2 jason kev ollinger rosten \
|
||||
schweikh westley williams
|
||||
ALT_NAMES= westley.orig
|
||||
DATA_FILES= anonymous_files bellard_files herrmann1_files herrmann2_files
|
||||
|
||||
|
||||
all: ${WINNERS}
|
||||
|
||||
# Most likely to amaze
|
||||
#
|
||||
anonymous: anonymous.c
|
||||
magic='${MAY_NEED_GCC} -O1'; \
|
||||
X='-DA(X)=#X'; \
|
||||
warning='-pedantic -Dprocessor'; \
|
||||
$$magic $$warning -Dmagic= $$X "-DX=A($$magic \"$$X\")" \
|
||||
-o anonymous anonymous.c
|
||||
|
||||
anonymous_files: anonymous.ten.c
|
||||
|
||||
# Best abuse of the rules
|
||||
#
|
||||
bellard: bellard.c
|
||||
${CC} -rdynamic ${CFLAGS} bellard.c -o bellard -ldl
|
||||
|
||||
bellard_files: bellard.otccex.c
|
||||
|
||||
# Best short program
|
||||
#
|
||||
cheong: cheong.c
|
||||
${CC} ${CFLAGS} cheong.c -o cheong
|
||||
|
||||
# Most obfuscated sound
|
||||
#
|
||||
coupard: coupard.c
|
||||
${CC} ${CFLAGS} -o coupard coupard.c
|
||||
|
||||
# Worst Driver
|
||||
#
|
||||
ctk: ctk.c
|
||||
${CC} ${CFLAGS} -o ctk ctk.c
|
||||
|
||||
# Worst AI
|
||||
#
|
||||
dgbeards: dgbeards.c
|
||||
${CC} ${CFLAGS} -DE=break -DF=char -DK=case -DP=int -DR=return \
|
||||
-DI=0xFFFF dgbeards.c -o dgbeards
|
||||
|
||||
# Best abuse of the C preprocessor
|
||||
#
|
||||
herrmann1: herrmann1.c herrmann1.sh
|
||||
@echo "NOTE: $@ must be built/run using the script $@.sh"
|
||||
${SHELL} ./herrmann1.sh
|
||||
|
||||
herrmann1_files: herrmann1.gcd herrmann1.sh herrmann1.times2
|
||||
|
||||
# Most eye-crossing
|
||||
#
|
||||
# This entry requires the GCC -include feature.
|
||||
#
|
||||
herrmann2: herrmann2.c
|
||||
${MAY_NEED_GCC} ${CFLAGS} herrmann2.c -o herrmann2 \
|
||||
-include /usr/include/stdlib.h -include /usr/include/stdio.h \
|
||||
-include /usr/include/time.h -include /usr/include/unistd.h
|
||||
|
||||
herrmann2_files: herrmann2.cup herrmann2.ioccc
|
||||
|
||||
# Best Of Show
|
||||
#
|
||||
jason: jason.c
|
||||
${CC} ${CFLAGS} -o jason jason.c
|
||||
|
||||
# Best Curses Game
|
||||
#
|
||||
kev: kev.c
|
||||
${CC} ${CFLAGS} -DPORT=5455 -DSPEED=50 -o kev kev.c \
|
||||
-lcurses -ltermcap \
|
||||
-Dl_="socket(il.sin_family=AF_INET,SOCK_STREAM,0)"
|
||||
|
||||
# Best primal ASCII graphics
|
||||
#
|
||||
ollinger: ollinger.c
|
||||
${CC} ${CFLAGS} ollinger.c -o ollinger
|
||||
|
||||
# Best abuse of the user
|
||||
#
|
||||
rosten: rosten.c
|
||||
${CC} ${CFLAGS} rosten.c ${X11CCFLAGS} ${X11LDFLAGS} -pedantic -lX11 \
|
||||
-o rosten
|
||||
|
||||
# Best one-liner
|
||||
#
|
||||
schweikh: schweikh.c
|
||||
${CC} ${CFLAGS} schweikh.c -o schweikh
|
||||
|
||||
# Best position-independant code
|
||||
#
|
||||
westley: westley.c
|
||||
${CC} ${CFLAGS} westley.c -o westley
|
||||
|
||||
westley.orig: westley.orig.c
|
||||
${CC} ${CFLAGS} westley.orig.c -o westley.orig
|
||||
|
||||
# Best position-independant code
|
||||
#
|
||||
williams: williams.c
|
||||
${CC} williams.c ${X11CCFLAGS} ${X11LDFLAGS} -lX11 -o williams
|
||||
|
||||
everything: ${WINNERS} ${ALT_NAMES} ${DATA_FILES}
|
||||
|
||||
love:
|
||||
@echo 'not war?'
|
||||
|
||||
haste:
|
||||
${MAKE} waste
|
||||
|
||||
waste:
|
||||
@echo 'waste'
|
||||
|
||||
clean:
|
||||
${RM} -f *.o a.out core ${WINNERS}
|
||||
|
||||
clobber: clean
|
||||
${RM} -f ${WINNERS}
|
||||
${RM} -f ${ALT_NAMES}
|
||||
|
||||
nuke: clobber
|
||||
@${TRUE}
|
||||
|
||||
install: all
|
||||
${CAT} ${WINNERS} ${ALT_NAMES} > /dev/null
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
2001 marked the "The Sixteenth International Obfuscated C Code Contest"
|
||||
|
||||
Copyright (C) Landon Curt Noll, Simon Cooper, Peter Seebach
|
||||
and Leonid A. Broukhis, 2001-2002.
|
||||
All Rights Reserved. Permission for personal, educational or non-profit
|
||||
use is granted provided this copyright and notice are included in its
|
||||
entirety and remains unaltered. All other uses must receive prior permission
|
||||
from the contest judges.
|
||||
|
||||
|
||||
Standard IOCCC stuff
|
||||
--------------------
|
||||
|
||||
The IOCCC has a web site and now has a number of international mirrors. The
|
||||
primary site can be found at,
|
||||
|
||||
http://www.ioccc.org
|
||||
|
||||
Use make to compile entries. It is possible that on non-Un*x / non-Linux
|
||||
systems the makefile needs to be changed. See the Makefile for details.
|
||||
|
||||
Look at the source and try to figure out what the programs do, and run
|
||||
them with various inputs. If you want to, look at the hints files for
|
||||
spoilers - this year we included most of the information included
|
||||
by the submitters.
|
||||
|
||||
Read over the makefile for compile/build issues. Your system may
|
||||
require certain changes (add or remove a library, add or remove a
|
||||
#define).
|
||||
|
||||
Some ANSI C compilers are not quite as good as they should be. If
|
||||
yours is lacking, you may need to compile using gcc instead of your
|
||||
local compiler.
|
||||
|
||||
|
||||
Remarks on some of the entries
|
||||
------------------------------
|
||||
|
||||
There were some outstanding entries that did not win. Unfortunately
|
||||
some very good entries lost because they:
|
||||
|
||||
+ depended too much on non-portable side effects in expressions;
|
||||
+ depended too much on a particular byte order;
|
||||
+ required the use of a special script, data file or pseudo-machine
|
||||
language that was not supplied with the entry.
|
||||
|
||||
We hope the authors of some of those entries will fix and re-submit
|
||||
them for the next IOCCC.
|
||||
|
||||
We believe you will be impressed with this year's winners. The Best of Show
|
||||
is a fine example of obfuscation. But don't ignore the other winners!
|
||||
There are games, programs that speak, ones that compile code and one that
|
||||
might run binaries you already have!
|
||||
|
||||
The Worst Abuse of the Rules is technically allowed by the rules. This year
|
||||
we awarded it again, but don't assume you can get away with using the same
|
||||
technique next time ... :-)
|
||||
|
||||
This year there were several repeat winners. This is understating the
|
||||
achievement a little - one person has won 8 times before! (Please note that
|
||||
judging is done completely anonymously).
|
||||
|
||||
|
||||
Why has it taken so long to post the winning source?
|
||||
----------------------------------------------------
|
||||
|
||||
This is somewhat my (Simon Cooper) fault. I do apologize to the IOCCC
|
||||
community for this! Judging does take quite a lot of time, and I
|
||||
over-committed myself several times this year. Without divulging too much,
|
||||
we do look at and work out what every entry does.
|
||||
|
||||
|
||||
Final Comments
|
||||
--------------
|
||||
|
||||
Please send us comments and suggestions what we have expressed above.
|
||||
Also include anything else that you would like to see in future contests.
|
||||
Send such email to:
|
||||
|
||||
questions@ioccc.org
|
||||
|
||||
If you use, distribute or publish these entries in some way, please drop
|
||||
us a line. We enjoy seeing who, where and how the contest is used.
|
||||
|
||||
You must include the words ``ioccc question'' in the subject of your EMail
|
||||
message when sending EMail to the judges.
|
||||
|
||||
If you have problems with any of the entries, AND YOU HAVE A FIX, please
|
||||
EMail the fix (patch file or the entire changed file) to the above address.
|
||||
|
||||
Watch:
|
||||
|
||||
http://www.ioccc.org/
|
||||
|
||||
for news of the next contest.
|
||||
|
||||
=-=
|
||||
@@ -0,0 +1,39 @@
|
||||
#define processor x86
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define l int*
|
||||
#define F char
|
||||
struct stat t;
|
||||
#define c return
|
||||
#define I (P+=4,*L(P-4,0))
|
||||
#define G (signed F)E(*L(P++,0))
|
||||
#define C(O,D)E (D[B+V(010)/4+O*10])
|
||||
#define U R[4]=E(V(17)-4),*(l)V(021)=
|
||||
F M [99],Q[99],b[9999],*ss,*d=b,*z;
|
||||
#define O =(n=*(l)V(021),R[4]=E(V(17)+4),n)
|
||||
#define p(a,b,c) system((sprintf(a,b,k[1]),c)),z
|
||||
#define g (y/010&7)
|
||||
#define R (B+13)
|
||||
#define x86 (F*)index\
|
||||
(ss+V(i ),0100)
|
||||
#define D(y,n,a,m,i,c )d+=sprintf( d,y,n,a,m,i,c ),(F*\
|
||||
) P
|
||||
l B,i,n,a,r,y ,
|
||||
P ;
|
||||
#define Tr(an,sl,at,or) l an##i(d,sl){ c at? an##i(d,r):or; } \
|
||||
l an(d, sl){ c \
|
||||
r=V(014 )&63,an##i(d,sl); }
|
||||
#define add(Ev,Gv) Ev(){ i=((a-=16)+C(r,4))/4,(\
|
||||
Gv?Ev() :0) ; } Ev##n(){ a=C(r,5),Ev(); }
|
||||
Tr(L,r, C(r,3)&&C(r,3)<=d?(l)(((int)B)+d+C(r,4)-C(r,3)):(((int)B)^d)>>24&&--\
|
||||
r,(l)d) Tr(Run,a,(ss=strcmp((F*)B+C((V(12)>>16),4)+C(--r,0),A(.strtab))?ss:(F\
|
||||
*)B+C(r ,4),C(r,1)-2),0) add(Sca ,V(-~i)-P+2) add(ru,strcmp(ss+V(i),A(main)))
|
||||
E(DX) { c *z? DX:DX <<030|(DX&65280)<<010|DX>>8&65280|DX>>24&0377; } l K(k){
|
||||
c L(E(k [(l)V(17)]),0); } V(v){ c E(B[v]); }
|
||||
|
||||
|
||||
main (char *ck, char **k) {
|
||||
exit(E((ck?main((z?(stat(M,&t)?P+=a+'{'?0:3:execv(M,k),a=G,i=P,y=G&255,sprintf(Q,y/'@'-3?A(*L(V(%d+%d)+%d,0)):A(R[%d]),(y&7),'\r',y/0100-1?0:G),(a+127&&a+'}'&&a+1?(a+61&&a+24&&a+025?(P=a+'H'&&a%061<=0?P:i,D(a>0?" R[%d]=E(~-E(R[%d])),\0 U R[%d],\0 R[%d] O,\0 U %d,\0R[%d]=0,"+(a&'8')*3:a <- 'c'?" %d, %c%s = R[%d], \0 %d, *R=%c%s==R[%d], \0 R[%d]=(int)%c%s,"-a%'w'%'j'*5:"%d,%d,%s=%d,",a>0?a-'h'?a-49?a&7:g:I:g,a>0?a&7:"& "[a%3%2+1],a+72?Q:A(*R),a>0|a<-99?g:I,0)):(P=i,i=a+61?a+21?E(I):G:0,D(a%' '+29+"P O,\0 U %d,P=%d,",P,P+i,0,0,0),p(d,"A'",b))):(n=g-4?g%5-1?a+127?G:I:0:(Scan(),*( x86?processor :d)=0,(int)(ss+V(i))),g%5<2?D(g%5?" %s=E(~-E(%s)), \0 U %s,"+4*g:"%s=E(E(%s)%c%d),",Q,Q,"+ - "[g],n,0):(a=G-'u'?'!':'=',D(g-4?"P=%d%c=%s?%d:%d,":"*R=E(((int(*)(l,l,l))%s)(K(1),K(2),K(3))),P O,",n,a,Q,P,P+G),p(d,"A'",b))))):(Run((z=(F*)&ck,stat(k[1],&t),B=(l)mmap(0,i=t.st_size,3,1,open(k[1],2),0))),magic((R[4]=E(B+i/4),run(),P=V(-~i),U 0)),sprintf(M,A(.%s%d),k[1],P),D("%s %s '-DX=A(%s)' -o %s '-Dmagic=",X,__FILE__,X,M,fflush(0)))),k):p(M,A(rm -f .%s*),M),*R)));
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
Most likely to amaze:
|
||||
|
||||
The author wishes to remain anonymous
|
||||
Great Britain
|
||||
|
||||
|
||||
Judges' Comments:
|
||||
|
||||
To build:
|
||||
|
||||
make anonymous
|
||||
|
||||
Try:
|
||||
|
||||
./anonymous anonymous.ten
|
||||
|
||||
Is emulation the sincerest form of flattery? This small program does
|
||||
quite a lot of bit twiddling.
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
This program is an optimizing dynamic binary translator, allowing you to
|
||||
run x86 programs on any machine (x86 or otherwise).
|
||||
|
||||
I have included a simple "10 green bottles" program, already compiled
|
||||
for the x86. The program 'ten', and its source (dull) are given as info
|
||||
files. Warning: note that the translator screws around with the binary
|
||||
you run on it, *will* corrupt the binary to some extent, and may leave
|
||||
any program you run on it unusable.
|
||||
|
||||
The build script should give an example command to run.
|
||||
|
||||
Features
|
||||
|
||||
Basic Block Cache: Rather than translating each instruction individually
|
||||
the dynamic binary translator generates a translation for an entire
|
||||
basic block of subject code. Having translated a block once, the target
|
||||
code generated will be stored for the duration that the program is
|
||||
running, so as a program runs its performance will improve, as it hits
|
||||
cached blocks. This can be clearly observed in the example program,
|
||||
'ten'.
|
||||
|
||||
Target Library Linking:
|
||||
|
||||
The program runs dynamically linked elf binaries, and when the subject
|
||||
program attempts to make a call to a standard library, the translator
|
||||
attempts to make an appropriate call to the native system libraries on
|
||||
the target machine. This involves mangling between different calling
|
||||
conventions, etc.
|
||||
|
||||
Automatic Endian Detection/Reversal:
|
||||
|
||||
There are various problems raised when attempting to run little endian
|
||||
x86 code on a big endian chip, such as a PPC. These problems are dealt
|
||||
with in a manner that is entirely transparent to the user.
|
||||
|
||||
Configuration
|
||||
|
||||
Warnings:
|
||||
|
||||
By default the build script should compile the program with a set of
|
||||
switches such that while compiling the program it generates one error
|
||||
(which I feel is useful advice). The program should generate no further
|
||||
compiler errors while it is running (yes, the program can generate
|
||||
compiler errors while it is running). If you do not wish to see this
|
||||
error, or if the program generates any further error when compiled using
|
||||
your C compiler please remove the "warning=..." line from the build
|
||||
script.
|
||||
|
||||
Optimization:
|
||||
|
||||
The build script contains a "-O1" switch for the compiler. Increasing
|
||||
the optimization level will make the program run *slower*, while
|
||||
compiling the program without any optimization will allow it to run
|
||||
*faster*.
|
||||
|
||||
Obfuscation
|
||||
|
||||
The most obvious part of the obfuscation is probably the mess of defines
|
||||
at the top. This may seem a somewhat tired old obfuscation - however
|
||||
since many of these macros are (sometimes only) used by the program once
|
||||
it has dynamically recompiled itself, they are only referenced within
|
||||
the source code from within strings - and therefore the macros cannot be
|
||||
expanded. Furthermore, some of these strings of code are not given as
|
||||
strings, but instead are wrapped up in macros that use the "#"
|
||||
preprocessor operator to turn them into strings. In the hope throwing a
|
||||
few C beautifiers the macro to generate the strings is not contained
|
||||
within the source code but instead is passed in on the command line.
|
||||
|
||||
Buried under all this, and the fact that the entire program is just a
|
||||
call to exit, there are some nice subtle little obfuscations. For
|
||||
example, you may notice that there are a couple of macros that use the
|
||||
"##" preprocessor operator to build pairs of functions. One of these
|
||||
macros is used to build to pairs of functions of which only one has
|
||||
local variables which shadow global variables; so one modifies the
|
||||
global state, and the other doesn't.
|
||||
|
||||
There is also quite a nice trick where I wave a magic wand, and a chunk
|
||||
of code which should only be run when the program is run for the first
|
||||
time (setting the PC to point at main, etc) gets turned into a
|
||||
frog^M^M^M^Mstring. The C compiler sees a string by itself in the code,
|
||||
thinks "yup, thats a valid C expression", and quietly moves on to the
|
||||
next line of code.
|
||||
|
||||
Limitations
|
||||
|
||||
Due to space limitations only a handful of instructions are supported,
|
||||
those instructions which are supported may supported in somewhat
|
||||
non-conventional ways, chunks of the architecture (e.g. flags) are just
|
||||
ignored, the elf loader does not really load the elf binary, the target
|
||||
library linking can only pass up to 3 parameters to the target library
|
||||
function, etc, etc, etc.
|
||||
|
||||
In short, please consider this a full disclaimer for any bug that may
|
||||
turn up - yes the program is unsafe, but it's pretty cool anyway.
|
||||
|
||||
Despite all this, the translator is not exclusively limited to running
|
||||
the 'ten' program. Other trivial x86 programs may run on the translator
|
||||
- and I have successfully run a wide range of HelloWorld programs,
|
||||
including one of last years IOCCC winners, 'tomx'.
|
||||
|
||||
Complete Program
|
||||
|
||||
The fact that the program makes calls to system and execv may imply that
|
||||
it is not a complete program in its own right, as it relies on other
|
||||
programs. The call to system is a call to ask gcc to recompile the
|
||||
translator with a new set of switches, and the call to execv asks for
|
||||
the newly compiled program to be executed. I would point out that
|
||||
almost every other entry to this competition also require a C compiler
|
||||
(well, the published winners at any rate, and I recognize that a few
|
||||
don't). There is little real difference between this program and one
|
||||
like last years entry 'dhyang'; both are just C programs that generate C
|
||||
code as their output.
|
||||
|
||||
Enjoy, thanks!
|
||||
@@ -0,0 +1,19 @@
|
||||
#define PLURAL(bottles) bottles==1?"bottle":"bottles"
|
||||
|
||||
void sing(int bottles) {
|
||||
printf("%d green %s, standing on the wall.\n", bottles, PLURAL(bottles));
|
||||
}
|
||||
|
||||
int main() {
|
||||
int bottles = 10;
|
||||
|
||||
while(bottles) {
|
||||
sing(bottles);
|
||||
sing(bottles);
|
||||
printf("And if one green bottle should accidently fall,\nThere'd be ");
|
||||
sing(--bottles);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+446
@@ -0,0 +1,446 @@
|
||||
#include <stdio.h>
|
||||
#define k *(int*)
|
||||
#define a if(
|
||||
#define c ad()
|
||||
#define i else
|
||||
#define p while(
|
||||
#define x *(char*)
|
||||
#define b ==
|
||||
#define V =calloc(1,99999)
|
||||
#define f ()
|
||||
#define J return
|
||||
#define l ae(
|
||||
#define n e)
|
||||
#define u d!=
|
||||
#define F int
|
||||
#define y (j)
|
||||
#define r m=
|
||||
#define t +4
|
||||
F d,z,C,h,P,K,ac,q,G,v,Q,R,D,L,W,M;
|
||||
E(n{
|
||||
x D++=e;
|
||||
}
|
||||
o f{
|
||||
a L){
|
||||
h=x L++;
|
||||
a h b 2){
|
||||
L=0;
|
||||
h=W;
|
||||
}
|
||||
}
|
||||
i h=fgetc(Q);
|
||||
}
|
||||
X f{
|
||||
J isalnum(h)|h b 95;
|
||||
}
|
||||
Y f{
|
||||
a h b 92){
|
||||
o f;
|
||||
a h b 110)h=10;
|
||||
}
|
||||
}
|
||||
c{
|
||||
F e,j,m;
|
||||
p isspace(h)|h b 35){
|
||||
a h b 35){
|
||||
o f;
|
||||
c;
|
||||
a d b 536){
|
||||
c;
|
||||
E(32);
|
||||
k d=1;
|
||||
k(d t)=D;
|
||||
}
|
||||
p h!=10){
|
||||
E(h);
|
||||
o f;
|
||||
}
|
||||
E(h);
|
||||
E(2);
|
||||
}
|
||||
o f;
|
||||
}
|
||||
C=0;
|
||||
d=h;
|
||||
a X f){
|
||||
E(32);
|
||||
M=D;
|
||||
p X f){
|
||||
E(h);
|
||||
o f;
|
||||
}
|
||||
a isdigit(d)){
|
||||
z=strtol(M,0,0);
|
||||
d=2;
|
||||
}
|
||||
i{
|
||||
x D=32;
|
||||
d=strstr(R,M-1)-R;
|
||||
x D=0;
|
||||
d=d*8+256;
|
||||
a d>536){
|
||||
d=P+d;
|
||||
a k d b 1){
|
||||
L=k(d t);
|
||||
W=h;
|
||||
o f;
|
||||
c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i{
|
||||
o f;
|
||||
a d b 39){
|
||||
d=2;
|
||||
Y f;
|
||||
z=h;
|
||||
o f;
|
||||
o f;
|
||||
}
|
||||
i a d b 47&h b 42){
|
||||
o f;
|
||||
p h){
|
||||
p h!=42)o f;
|
||||
o f;
|
||||
a h b 47)h=0;
|
||||
}
|
||||
o f;
|
||||
c;
|
||||
}
|
||||
i{
|
||||
e="++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b";
|
||||
p j=x e++){
|
||||
r x e++;
|
||||
z=0;
|
||||
p(C=x e++-98)<0)z=z*64+C+64;
|
||||
a j b d&(m b h|m b 64)){
|
||||
a m b h){
|
||||
o f;
|
||||
d=1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
l g){
|
||||
p g&&g!=-1){
|
||||
x q++=g;
|
||||
g=g>>8;
|
||||
}
|
||||
}
|
||||
A(n{
|
||||
F g;
|
||||
p n{
|
||||
g=k e;
|
||||
k e=q-e-4;
|
||||
e=g;
|
||||
}
|
||||
}
|
||||
s(g,n{
|
||||
l g);
|
||||
k q=e;
|
||||
e=q;
|
||||
q=q t;
|
||||
J e;
|
||||
}
|
||||
H(n{
|
||||
s(184,n;
|
||||
}
|
||||
B(n{
|
||||
J s(233,n;
|
||||
}
|
||||
S(j,n{
|
||||
l 1032325);
|
||||
J s(132+j,n;
|
||||
}
|
||||
Z(n{
|
||||
l 49465);
|
||||
H(0);
|
||||
l 15);
|
||||
l e+144);
|
||||
l 192);
|
||||
}
|
||||
N(j,n{
|
||||
l j+131);
|
||||
s((e<512)<<7|5,n;
|
||||
}
|
||||
T y{
|
||||
F g,e,m,aa;
|
||||
g=1;
|
||||
a d b 34){
|
||||
H(v);
|
||||
p h!=34){
|
||||
Y f;
|
||||
x v++=h;
|
||||
o f;
|
||||
}
|
||||
x v=0;
|
||||
v=v t&-4;
|
||||
o f;
|
||||
c;
|
||||
}
|
||||
i{
|
||||
aa=C;
|
||||
r z;
|
||||
e=d;
|
||||
c;
|
||||
a e b 2){
|
||||
H(m);
|
||||
}
|
||||
i a aa b 2){
|
||||
T(0);
|
||||
s(185,0);
|
||||
a e b 33)Z(m);
|
||||
i l m);
|
||||
}
|
||||
i a e b 40){
|
||||
w f;
|
||||
c;
|
||||
}
|
||||
i a e b 42){
|
||||
c;
|
||||
e=d;
|
||||
c;
|
||||
c;
|
||||
a d b 42){
|
||||
c;
|
||||
c;
|
||||
c;
|
||||
c;
|
||||
e=0;
|
||||
}
|
||||
c;
|
||||
T(0);
|
||||
a d b 61){
|
||||
c;
|
||||
l 80);
|
||||
w f;
|
||||
l 89);
|
||||
l 392+(e b 256));
|
||||
}
|
||||
i a n{
|
||||
a e b 256)l 139);
|
||||
i l 48655);
|
||||
q++;
|
||||
}
|
||||
}
|
||||
i a e b 38){
|
||||
N(10,k d);
|
||||
c;
|
||||
}
|
||||
i{
|
||||
g=k e;
|
||||
a!g)g=dlsym(0,M);
|
||||
a d b 61&j){
|
||||
c;
|
||||
w f;
|
||||
N(6,g);
|
||||
}
|
||||
i a u 40){
|
||||
N(8,g);
|
||||
a C b 11){
|
||||
N(0,g);
|
||||
l z);
|
||||
c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
a d b 40){
|
||||
a g b 1)l 80);
|
||||
r s(60545,0);
|
||||
c;
|
||||
j=0;
|
||||
p u 41){
|
||||
w f;
|
||||
s(2393225,j);
|
||||
a d b 44)c;
|
||||
j=j t;
|
||||
}
|
||||
k r j;
|
||||
c;
|
||||
a!g){
|
||||
e=e t;
|
||||
k e=s(232,k n;
|
||||
}
|
||||
i a g b 1){
|
||||
s(2397439,j);
|
||||
j=j t;
|
||||
}
|
||||
i{
|
||||
s(232,g-q-5);
|
||||
}
|
||||
a j)s(50305,j);
|
||||
}
|
||||
}
|
||||
O y{
|
||||
F e,g,m;
|
||||
a j--b 1)T(1);
|
||||
i{
|
||||
O y;
|
||||
r 0;
|
||||
p j b C){
|
||||
g=d;
|
||||
e=z;
|
||||
c;
|
||||
a j>8){
|
||||
r S(e,m);
|
||||
O y;
|
||||
}
|
||||
i{
|
||||
l 80);
|
||||
O y;
|
||||
l 89);
|
||||
a j b 4|j b 5){
|
||||
Z(n;
|
||||
}
|
||||
i{
|
||||
l n;
|
||||
a g b 37)l 146);
|
||||
}
|
||||
}
|
||||
}
|
||||
a m&&j>8){
|
||||
r S(e,m);
|
||||
H(e^1);
|
||||
B(5);
|
||||
A(m);
|
||||
H(n;
|
||||
}
|
||||
}
|
||||
}
|
||||
w f{
|
||||
O(11);
|
||||
}
|
||||
U f{
|
||||
w f;
|
||||
J S(0,0);
|
||||
}
|
||||
I y{
|
||||
F m,g,e;
|
||||
a d b 288){
|
||||
c;
|
||||
c;
|
||||
r U f;
|
||||
c;
|
||||
I y;
|
||||
a d b 312){
|
||||
c;
|
||||
g=B(0);
|
||||
A(m);
|
||||
I y;
|
||||
A(g);
|
||||
}
|
||||
i{
|
||||
A(m);
|
||||
}
|
||||
}
|
||||
i a d b 352|d b 504){
|
||||
e=d;
|
||||
c;
|
||||
c;
|
||||
a e b 352){
|
||||
g=q;
|
||||
r U f;
|
||||
}
|
||||
i{
|
||||
a u 59)w f;
|
||||
c;
|
||||
g=q;
|
||||
r 0;
|
||||
a u 59)r U f;
|
||||
c;
|
||||
a u 41){
|
||||
e=B(0);
|
||||
w f;
|
||||
B(g-q-5);
|
||||
A(n;
|
||||
g=e t;
|
||||
}
|
||||
}
|
||||
c;
|
||||
I(&m);
|
||||
B(g-q-5);
|
||||
A(m);
|
||||
}
|
||||
i a d b 123){
|
||||
c;
|
||||
ab(1);
|
||||
p u 125)I y;
|
||||
c;
|
||||
}
|
||||
i{
|
||||
a d b 448){
|
||||
c;
|
||||
a u 59)w f;
|
||||
K=B(K);
|
||||
}
|
||||
i a d b 400){
|
||||
c;
|
||||
k j=B(k j);
|
||||
}
|
||||
i a u 59)w f;
|
||||
c;
|
||||
}
|
||||
}
|
||||
ab y{
|
||||
F m;
|
||||
p d b 256|u-1&!j){
|
||||
a d b 256){
|
||||
c;
|
||||
p u 59){
|
||||
a j){
|
||||
G=G t;
|
||||
k d=-G;
|
||||
}
|
||||
i{
|
||||
k d=v;
|
||||
v=v t;
|
||||
}
|
||||
c;
|
||||
a d b 44)c;
|
||||
}
|
||||
c;
|
||||
}
|
||||
i{
|
||||
A(k(d t));
|
||||
k d=q;
|
||||
c;
|
||||
c;
|
||||
r 8;
|
||||
p u 41){
|
||||
k d=m;
|
||||
r m t;
|
||||
c;
|
||||
a d b 44)c;
|
||||
}
|
||||
c;
|
||||
K=G=0;
|
||||
l 15042901);
|
||||
r s(60545,0);
|
||||
I(0);
|
||||
A(K);
|
||||
l 50121);
|
||||
k r G;
|
||||
}
|
||||
}
|
||||
}
|
||||
main(g,n{
|
||||
Q=stdin;
|
||||
a g-->1){
|
||||
e=e t;
|
||||
Q=fopen(k e,"r");
|
||||
}
|
||||
D=strcpy(R V," int if else while break return for define main ")+48;
|
||||
v V;
|
||||
q=ac V;
|
||||
P V;
|
||||
o f;
|
||||
c;
|
||||
ab(0);
|
||||
J(*(int(*)f)k(P+592))(g,n;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
Best abuse of the rules:
|
||||
|
||||
Fabrice Bellard
|
||||
451 chemin du mas de Matour
|
||||
34790 GRABELS
|
||||
France
|
||||
|
||||
http://bellard.org
|
||||
|
||||
|
||||
Judges' Comments:
|
||||
|
||||
To build:
|
||||
|
||||
make bellard
|
||||
|
||||
Try:
|
||||
|
||||
./bellard bellard.otccex.c
|
||||
|
||||
<JUDGES_COMMENTS>
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
OTCC is an Obfuscated Tiny C Compiler for i386-linux. It generates
|
||||
FAST! i386 32 bit code (no bytecode) and it is powerful enough to
|
||||
compile itself. OTCC supports a strict subset of C. This subset is
|
||||
compilable by a standard ANSI C compiler. OTCC compiles,
|
||||
assembles, links and runs C code without the need of any other
|
||||
program.
|
||||
|
||||
You can use it by typing:
|
||||
|
||||
./bellard bellard.c [args]...
|
||||
|
||||
or by giving the C source to its standard input.
|
||||
|
||||
'args' are given to the 'main' function of bellard.c (argv[0] is
|
||||
bellard.c).
|
||||
|
||||
Examples:
|
||||
|
||||
- Sample compilation and execution:
|
||||
|
||||
./bellard bellard.otccex.c 10
|
||||
|
||||
- Self compilation:
|
||||
|
||||
./bellard bellard.c bellard.otccex.c 10
|
||||
|
||||
- Self compilation iterated...
|
||||
|
||||
./bellard bellard.c bellard.c bellard.otccex.c 10
|
||||
|
||||
An alternate syntax is to use it as a script interpreter: you can
|
||||
put '#!/usr/local/bin/otcc' at the beginning of your C source if
|
||||
you installed otcc at this place.
|
||||
|
||||
Supported C language subset (read joint example 'otccex.c' to have
|
||||
an introduction to OTCC dialect):
|
||||
|
||||
- Expressions:
|
||||
|
||||
* binary operators, by decreasing priority order: '*' '/' '%',
|
||||
'+' '-', '>>' '<<', '<' '<=' '>' '>=', '==' '!=', '&',
|
||||
'^', '|', '=', '&&', '||'.
|
||||
|
||||
* '&&' and '||' have the same semantics as C : left to right
|
||||
evaluation and early exit.
|
||||
|
||||
* Parenthesis are supported.
|
||||
|
||||
* Unary operators: '&', '*' (pointer indirection), '-'
|
||||
(negation), '+', '!', '~', post fixed '++' and '--'.
|
||||
|
||||
* Pointer indirection ('*') only works with explicit cast to
|
||||
'char *', 'int *' or 'int (*)()' (function pointer).
|
||||
|
||||
* '++', '--', and unary '&' can only be used with variable
|
||||
lvalue (left value).
|
||||
|
||||
* '=' can only be used with variable or '*' (pointer
|
||||
indirection) lvalue.
|
||||
|
||||
* Function calls are supported with standard i386 calling
|
||||
convention. Function pointers are supported with explicit
|
||||
cast. Functions can be used before being declared.
|
||||
|
||||
- Types: only signed integer ('int') variables and functions can
|
||||
be declared. Variables cannot be initialized in
|
||||
declarations. Only old K&R function declarations are parsed
|
||||
(implicit integer return value and no types on arguments).
|
||||
|
||||
- Any function or variable from the libc can be used because OTCC
|
||||
uses the libc dynamic linker to resolve undefined symbols.
|
||||
|
||||
- Instructions: blocks ('{' '}') are supported as in C. 'if' and
|
||||
'else' can be used for tests. The 'while' and 'for' C constructs
|
||||
are supported for loops. 'break' can be used to exit
|
||||
loops. 'return' is used for the return value of a function.
|
||||
|
||||
- Identifiers are parsed the same way as C. Local variables are
|
||||
handled, but there is no local name space (not a problem if
|
||||
different names are used for local and global variables).
|
||||
|
||||
- Numbers can be entered in decimal, hexadecimal ('0x' or '0X'
|
||||
prefix), or octal ('0' prefix).
|
||||
|
||||
- '#define' is supported without function like arguments. No macro
|
||||
recursion is tolerated. Other preprocessor directives are
|
||||
ignored.
|
||||
|
||||
- C Strings and C character constants are supported. Only '\n',
|
||||
'\"', '\'' and '\\' escapes are recognized.
|
||||
|
||||
- C Comments can be used (but no C++ comments).
|
||||
|
||||
- No error is displayed if an incorrect program is given.
|
||||
|
||||
- Memory: the code, data, and symbol sizes are limited to 100KB
|
||||
(it can be changed in the source code).
|
||||
|
||||
Obfuscation:
|
||||
|
||||
No special effort was needed because obfuscation is almost
|
||||
unavoidable for such a program :-) Defines must be used to
|
||||
compress the code, and integrated i386 code generator leads to non
|
||||
obvious code.
|
||||
|
||||
Portability:
|
||||
|
||||
OTCC only works on i386 linux because it generates i386 code. OTCC
|
||||
also relies on little endianness, unaligned memory accesses and
|
||||
ASCII representation of characters. It also supposes that no valid
|
||||
pointers are less than 512. If all those constraints are met, then
|
||||
OTCC could be theoretically used to "cross compile", although no
|
||||
such support is currently integrated.
|
||||
|
||||
It was successfully compiled with gcc version 2.95.2. You get some
|
||||
warnings because old K&R protos are used, some casts are implicit
|
||||
and some functions are used before being defined. OTCC uses the
|
||||
dynamic linker to resolve symbols with 'dlsym()', so '-ldl' must
|
||||
be used as library when you compile it.
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/* #!/usr/local/bin/otcc */
|
||||
/*
|
||||
* Sample OTCC C example. You can uncomment the first line and install
|
||||
* otcc in /usr/local/bin to make otcc scripts !
|
||||
*/
|
||||
|
||||
/* Any preprocessor directive except #define are ignored. We put this
|
||||
include so that a standard C compiler can compile this code too. */
|
||||
#include <stdio.h>
|
||||
|
||||
/* defines are handled, but macro arguments cannot be given. No
|
||||
recursive defines are tolerated */
|
||||
#define DEFAULT_BASE 10
|
||||
|
||||
/*
|
||||
* Only old style K&R prototypes are parsed. Only int arguments are
|
||||
* allowed (implicit types).
|
||||
*
|
||||
* By benchmarking the execution time of this function (for example
|
||||
* for fib(35)), you'll notice that OTCC is quite fast because it
|
||||
* generates native i386 machine code.
|
||||
*/
|
||||
fib(n)
|
||||
{
|
||||
if (n <= 2)
|
||||
return 1;
|
||||
else
|
||||
return fib(n-1) + fib(n-2);
|
||||
}
|
||||
|
||||
/* Identifiers are parsed the same way as C: begins with letter or
|
||||
'_', and then letters, '_' or digits */
|
||||
fact(n)
|
||||
{
|
||||
/* local variables can be declared. Only 'int' type is supported */
|
||||
int i, r;
|
||||
r = 1;
|
||||
/* 'while' and 'for' loops are supported */
|
||||
for(i=2;i<=n;i++)
|
||||
r = r * i;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Well, we could use printf, but it would be too easy */
|
||||
print_num(n, b)
|
||||
{
|
||||
int tab, p, c;
|
||||
/* Numbers can be entered in decimal, hexadecimal ('0x' prefix) and
|
||||
octal ('0' prefix) */
|
||||
/* more complex programs use malloc */
|
||||
tab = malloc(0x100);
|
||||
p = tab;
|
||||
while (1) {
|
||||
c = n % b;
|
||||
/* Character constants can be used */
|
||||
if (c >= 10)
|
||||
c = c + 'a' - 10;
|
||||
else
|
||||
c = c + '0';
|
||||
*(char *)p = c;
|
||||
p++;
|
||||
n = n / b;
|
||||
/* 'break' is supported */
|
||||
if (n == 0)
|
||||
break;
|
||||
}
|
||||
while (p != tab) {
|
||||
p--;
|
||||
printf("%c", *(char *)p);
|
||||
}
|
||||
free(tab);
|
||||
}
|
||||
|
||||
/* 'main' takes standard 'argc' and 'argv' parameters */
|
||||
main(argc, argv)
|
||||
{
|
||||
/* no local name space is supported, but local variables ARE
|
||||
supported. As long as you do not use a globally defined
|
||||
variable name as local variable (which is a bad habbit), you
|
||||
won't have any problem */
|
||||
int s, n, f, base;
|
||||
|
||||
/* && and || operator have the same semantics as C (left to right
|
||||
evaluation and early exit) */
|
||||
if (argc != 2 && argc != 3) {
|
||||
/* '*' operator is supported with explicit casting to 'int *',
|
||||
'char *' or 'int (*)()' (function pointer). Of course, 'int'
|
||||
are supposed to be used as pointers too. */
|
||||
s = *(int *)argv;
|
||||
help(s);
|
||||
return 1;
|
||||
}
|
||||
/* Any libc function can be used because OTCC uses dynamic linking */
|
||||
n = atoi(*(int *)(argv + 4));
|
||||
base = DEFAULT_BASE;
|
||||
if (argc >= 3) {
|
||||
base = atoi(*(int *)(argv + 8));
|
||||
if (base < 2 || base > 36) {
|
||||
/* external variables can be used too (here: 'stderr') */
|
||||
fprintf(stderr, "Invalid base\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
printf("fib(%d) = ", n);
|
||||
print_num(fib(n), base);
|
||||
printf("\n");
|
||||
|
||||
printf("fact(%d) = ", n);
|
||||
if (n > 12) {
|
||||
printf("Overflow");
|
||||
} else {
|
||||
/* why not using a function pointer ? */
|
||||
f = &fact;
|
||||
print_num((*(int (*)())f)(n), base);
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* functions can be used before being defined */
|
||||
help(name)
|
||||
{
|
||||
printf("usage: %s n [base]\n", name);
|
||||
printf("Compute fib(n) and fact(n) and output the result in base 'base'\n");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
int l;int main(int o,char **O,
|
||||
int I){char c,*D=O[1];if(o>0){
|
||||
for(l=0;D[l ];D[l
|
||||
++]-=10){D [l++]-=120;D[l]-=
|
||||
110;while (!main(0,O,l))D[l]
|
||||
+= 20; putchar((D[l]+1032)
|
||||
/20 ) ;}putchar(10);}else{
|
||||
c=o+ (D[I]+82)%10-(I>l/2)*
|
||||
(D[I-l+I]+72)/10-9;D[I]+=I<0?0
|
||||
:!(o=main(c/10,O,I-1))*((c+999
|
||||
)%10-(D[I]+92)%10);}return o;}
|
||||
@@ -0,0 +1,86 @@
|
||||
Best short program:
|
||||
|
||||
Raymond Cheong
|
||||
Johns Hopkins University
|
||||
USA
|
||||
|
||||
http://www.bme.jhu.edu/~rcheong/
|
||||
|
||||
|
||||
Judges' Comments:
|
||||
|
||||
To build:
|
||||
|
||||
make cheong
|
||||
|
||||
Try:
|
||||
|
||||
./cheong 1024
|
||||
./cheong 12345678901234567890
|
||||
./cheong 05305265226926441255040573044986873789
|
||||
|
||||
Be sure to give an even number of digits in the argument. Add a
|
||||
leading 0 if needed.
|
||||
|
||||
The source code is nice, compact, and self documenting
|
||||
as all good programs should be! :-)
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
Operation
|
||||
=========
|
||||
Compile normally and run with one argument, an integer with 2n digits.
|
||||
Program will return the integer part of its square root (n-digits).
|
||||
For example,
|
||||
|
||||
> gcc -o cheong cheong.c
|
||||
> cheong 1234567890
|
||||
35136
|
||||
> cheong 0200000000000000000000000000
|
||||
14142135623730
|
||||
>
|
||||
|
||||
Deviation from these instructions will cause undefined results. :-)
|
||||
|
||||
|
||||
Portability
|
||||
===========
|
||||
This program runs normally on any ANSI C compiler and is ASCII dependent.
|
||||
|
||||
Strict compiling gives just one unavoidable warning
|
||||
> gcc -ansi -Wall cheong.c
|
||||
cheong.c:3: warning: third argument of `main' should probably be `char **'
|
||||
|
||||
|
||||
Obfuscation
|
||||
===========
|
||||
The main obfuscation is the algorithm used to calculate square roots,
|
||||
sometimes known as the longhand method. The basic algorithm is itself
|
||||
obfuscated in that it only uses subtraction to calculate square roots.
|
||||
(For a detailed explanation, check Google or see Jack Crenshaw's article
|
||||
at http://www.embedded.com/98/9802fe2.htm) This program uses an even
|
||||
more obscured version which includes the following:
|
||||
- A single string is used to store two numbers of different lengths
|
||||
- Operations are done in a weird hybrid of base 10 and base 20
|
||||
- Subtraction is done addition style, i.e. 4 minus 8 equals 6 carry a -1
|
||||
- Recursive calls to main()
|
||||
|
||||
Minor obfuscations:
|
||||
- Self documenting whitespace in rectangular code block, for fun and
|
||||
glory (view with fixed-width font)
|
||||
- Integer constants adjusted to less meaningful values, just for added
|
||||
confusion
|
||||
- Hard-to-read, meaningless variable names to spite the reader
|
||||
|
||||
Challenges for the masses:
|
||||
- What are the meanings [sic, plural] of the variable o?
|
||||
- Why is (c+999)%10-(D[I]+92)%10 not equivalent to (c-D[I]+7)%10?
|
||||
- How does the program terminate?
|
||||
- Is the programmer sane? ;-)
|
||||
|
||||
|
||||
Appreciation
|
||||
============
|
||||
Thanks goes out to Bobby Rohde for numerous suggestions on how to shorten
|
||||
the program.
|
||||
@@ -0,0 +1,42 @@
|
||||
#include<unistd.h>
|
||||
#include<time.h>
|
||||
|
||||
#define k ("C9B7351A@D-/E+F?')G>H%J#=I"[(d[(i/13)*2]*91+d[(i/13)*2+1]-3220)&(\
|
||||
4096>>(i%13))?l+1:l]-59)
|
||||
#define g(n)e(n<13?n:n<20?n+1:n>20?11+n/10:13,0);e(n>12&&n<20?26:n>20&&n%10?n%\
|
||||
10:-1,2);
|
||||
#define x(n)g(localtime(&a)->tm_##n)
|
||||
|
||||
unsigned char *d="KZs2ITTwhwZYvec@JbYxOjf9-TZRGDb/el7#q(`SZ#|_neTwq\\MqJ5cVgte\
|
||||
K-ReK-(Mq8+D'6Ui0tG88vXJ-Tu{VI=d%cR]h7CumwBq\\-#{thj8fw$OEfEvLHP13_##w.OD[7Cw2\
|
||||
]<T{|[F}L;L:*+A#PwLnp{9'M3Mr|w_|unm'}$*(5]_$?O9zO{{wz4p6vP8Ipu}$BQospf=-Isnyl'\
|
||||
|g53o^c`ov-P`-x+|ZAd<e?<'b9P|LkZOf{B-8`K([srqv&gy1,:}$|s7D{yN6M#cQyKpC|*_|#xA#\
|
||||
'YfQ}$k$kr7dM#dcnWDg|PHdA#^j&q}$x@(a;k2JB]50ZKp{xRwbkTm.v\\a3fJ@V[`J#fN`s|sZeH\
|
||||
mmHX7`JKiry4sm,bUfz69{rt'k*pBq^l,ut6UVvb9N%r%l:Py3r[.Z/pBkaz2J4u{GTu)hyp#%gbS$\
|
||||
r`mzi9G|3M,r}-Dt?w)_##%fQt$k&n]e$HzFXu(|Fvt`i#$A#|ykrz+nhs'P#|pm*9[_#,5P#}$}$x\
|
||||
&s(i,HzO'&d&g?/_$P#kZ7Dn]e$J{zi8ypi|hq$_.|cLx`sy;f8GRMQM#7R5$hym*:^`sxrvtfQ|z_\
|
||||
N|ye[7dH[}#Ts\\59V@|#z}$}$y;usL)vXFiA0AukZ8H|fyKurd]|s5<|xq@Cpm,}${,e$KufO?/2M\
|
||||
t$zmM#vtfQ|zRKlEA#P&fPOwJ#pf_$?/2#@|$w}$?fLxA#^-}$cM^aA#&g#wIv?^|yY#s)Lwt'K#ON\
|
||||
yoXKYkpCl0m}D[9OGU7n([ZrL)[8eRy7uR*PJ#^5xRG>zSf>p]ZrJ_[9q?qgYe^4$r3lY$4SdsSyNv\
|
||||
J_l&w2I?q#fN*F1n|s9OGUv|w&l+pR-3Nudtyn@|Dfq#^o|s9Pt=oZCol/{VdgkLdwyn1yDed}?Dzi\
|
||||
}#Kje#d}Y${8pSt<q?qgIv|`DH?9}$O{k(LgE;|KU-tJnWOw*F@YP#|yY$b4|.50[2d}D'kaqhp;JE\
|
||||
$r&fH&'6nykYGCv>K$t?yLbwtUn[F{ncOx_.:K#nwF#f|HQs&<&bfQPE?:uJm*&\\S=*/@|We*w@$@\
|
||||
f0,*H])WL<i@^xX@)(a.>MV*p{Zqf&zH%###################u2#A#_$A#_$A#_$A#_$@tA#QI#\
|
||||
3#0&:p#?1[P*6WQ@i#C1{[;@|1}S%^r#g.d^z#M}$ziZe|kU6oZbq5$kF]4[E^nA#_.|}e$Ku^r&WA\
|
||||
#_$?/*P_$@t&gA#[;_$A#^j2#A#_*d}@v^z#8?D?D9Q`s}$5$L|u<3JC/xVz;#s^{?9$M}$x_Y,7uP\
|
||||
$",p[6789];
|
||||
|
||||
int o[]={145,1145,1745,2545,3045,4045,4345,5145,5745,6369},i=0,j=0,l=0;
|
||||
|
||||
void e(n,h){
|
||||
for(j=0;n>0;n-=!(p[j++]^9));
|
||||
for(;!n&&j[p]^9;j++)write(1,p+p[j][o],o[p[j]+1]-p[j][o]);
|
||||
for(i=0;i<h[o];i++)write(1,d+7,1);}
|
||||
|
||||
int main(){
|
||||
time_t a=time(&a);
|
||||
|
||||
for(;i<8476;j[p]=k>=0?j<*o?k-2:(p[j+1]=k<<4):0,j+=k>=0?1+(j>=*o):0,
|
||||
l=-k*(k<0),i++);e(21,4);x(hour)e(22,1);x(min)e(23,1);e(25,0);x(sec)e(24,0);
|
||||
|
||||
return;}
|
||||
@@ -0,0 +1,136 @@
|
||||
Most obfuscated sound:
|
||||
|
||||
Pierre-Philippe Coupard
|
||||
Lineo, Inc.
|
||||
ATTN : Pierre-Philippe Coupard
|
||||
390 South 400 West
|
||||
Lindon, UT 84042
|
||||
USA
|
||||
|
||||
|
||||
Judges' Comments:
|
||||
|
||||
To build:
|
||||
|
||||
make coupard
|
||||
|
||||
Try:
|
||||
|
||||
./coupard > /dev/audio
|
||||
-or-
|
||||
./coupard > /dev/sound/dsp
|
||||
|
||||
You may need to run this a few times to understand exactly what is
|
||||
being said. You might even need to look somewhere on your desktop,
|
||||
your arm or the wall for confirmation.
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
Past years' IOCCC entries do many marvellous things in small packages,
|
||||
such as console utilities, games, math, languages or even X
|
||||
applications. But they all have one thing in common (despite being hard
|
||||
to read obviously) : when they interact with the user, they only
|
||||
*display* things, i.e. they display either text or drawings.
|
||||
|
||||
So, for a change, this program titillates the sense of hearing instead
|
||||
of sight : this program is a self-contained speech synthesizer that
|
||||
tells the current time through the computer's sound card - in just under
|
||||
2 Kb of source code !
|
||||
|
||||
In the 2001 IOCCC rules and guidelines documents, there is no mention of
|
||||
what is or isn't acceptable regarding audio I/Os, but it is mentioned
|
||||
that hardware-specific and/or non-portable programs are not welcome. So,
|
||||
in order to do audio and satisfy those requirements, the format required
|
||||
by /dev/audio has been chosen : /dev/audio is a rather ancient
|
||||
fixed-format audio interface that is supported by the majority of Unices
|
||||
that can do sound, as a lowest-denominator sound I/Os interface.
|
||||
|
||||
Program usage :
|
||||
|
||||
* To listen to what the program says directly, invoke
|
||||
|
||||
./coupard > /dev/audio
|
||||
|
||||
the program then speaks out something like
|
||||
|
||||
"The time is HH hours MM minutes SS seconds"
|
||||
|
||||
in military time (24 hours). Of course, you need to have permissions
|
||||
to write to /dev/audio, have your sound card enabled, the volume up,
|
||||
the speakers connected ... :-)
|
||||
|
||||
* If you want to convert the audio output of the program into another
|
||||
audio format, you can pipe it to sox for example (sox is the
|
||||
Swiss army knife of Unix audio tools) : the command
|
||||
|
||||
./coupard | sox -c1 -r8000 -tub - -c2 -r44100 -twav test.wav
|
||||
|
||||
converts the output of the program into a 44.1KHz stereo .WAV
|
||||
file and saves it into "test.wav".
|
||||
|
||||
The output format of the program is 8KHz, unsigned 8-bit samples.
|
||||
|
||||
NOTE : the program's return code is meaningless
|
||||
|
||||
Audio quality :
|
||||
|
||||
The quality of the sound produced by the program is cross between a
|
||||
yogurt-pot-and-string telephone and a bad gramophone, i.e. the S/N
|
||||
ratio is very low and the signal's top frequency is very low as well.
|
||||
This is because the audio is stored internally at a sampling rate of
|
||||
4KHz (the Nyquist frequency is only 2KHz) with only 4-bit samples
|
||||
(adding 24db of quantization noise to an already poor signal).
|
||||
|
||||
In short, you might have to listen twice to understand what the
|
||||
program is saying. 2048 bytes including the sound generation program
|
||||
doesn't leave much room for audio quality ;-)
|
||||
|
||||
Speech generation :
|
||||
|
||||
Only 9 phonemes are used to generate the speech. Beside the limited
|
||||
number of words the program has to generate (66 words), the low sound
|
||||
quality is actually exploited to take liberties with certain
|
||||
consonants (for example, "s" and "f" sound very much the same at 4KHz,
|
||||
so they can be merged into one phoneme). Because the psychoacoustic
|
||||
context around those phonemes is just sufficient, the words can be
|
||||
interpreted correctly most of the time despite the fact that they are
|
||||
pronounced quite wrongly.
|
||||
|
||||
Internally, a table is used to generate most of the words, and
|
||||
composite words such as "thirty-five" are made up by the C code
|
||||
externally.
|
||||
|
||||
Data compression :
|
||||
|
||||
Even at 4KHz / 4 bits, the weight of all the phoneme samples and the
|
||||
word-to-phonemes table put together is over 1600 bytes, which is well
|
||||
over 2048 bytes when encoded in a C string made of printable
|
||||
characters. Therefore, a compression method was needed that's both
|
||||
efficient and with a decompressor that is implementable in the
|
||||
shortest amount of code possible. GSM compression is very good, but
|
||||
needs large psychoacoustic tables to regenerate the original
|
||||
signal. Raw FFT spectral compression is efficient too, but the
|
||||
decompression code can't be made small enough.
|
||||
|
||||
The best compression compromise was found using a simple Huffman
|
||||
compressor, and encoding the compressed data by blocks of 13 bits in
|
||||
pairs of printable ASCII characters : the raw data is compressed to
|
||||
8465 bits, and the resulting C string is therefore about 1300
|
||||
characters, which leaves just enough room for the decompressor with a
|
||||
hard-coded Huffman tree, and the code that plays the phonemes in the
|
||||
right order.
|
||||
|
||||
Note on compiler warnings and lint :
|
||||
|
||||
The program should build with gcc's -Wall -Werror and -ansi flags. If
|
||||
the -pedantic flag is used, gcc will complain about the length of the
|
||||
data string and the sign of its type, and also the fact that main()
|
||||
returns with no value. The confusion with the sign of the char type
|
||||
doesn't matter with the data string because it's composed only of
|
||||
printable characters under 127.
|
||||
|
||||
When linting the program with lclint, it complains about a huge list
|
||||
of things that, if corrected to make lint happy, would probably double
|
||||
the size of the source code.
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#define m(b)a=b;z=*a;while(*++a){y=*a;*a=z;z=y;}
|
||||
#define h(u)G=u<<3;printf("\e[%uq",l[u])
|
||||
#define c(n,s)case n:s;continue
|
||||
char x[]="((((((((((((((((((((((",w[]=
|
||||
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";char r[]={92,124,47},l[]={2,3,1
|
||||
,0};char*T[]={" |"," |","%\\|/%"," %%%",""};char d=1,p=40,o=40,k=0,*a,y,z,g=
|
||||
-1,G,X,**P=&T[4],f=0;unsigned int s=0;void u(int i){int n;printf(
|
||||
"\233;%uH\233L%c\233;%uH%c\233;%uH%s\23322;%uH@\23323;%uH \n",*x-*w,r[d],*x+*w
|
||||
,r[d],X,*P,p+=k,o);if(abs(p-x[21])>=w[21])exit(0);if(g!=G){struct itimerval t=
|
||||
{0,0,0,0};g+=((g<G)<<1)-1;t.it_interval.tv_usec=t.it_value.tv_usec=72000/((g>>
|
||||
3)+1);setitimer(0,&t,0);f&&printf("\e[10;%u]",g+24);}f&&putchar(7);s+=(9-w[21]
|
||||
)*((g>>3)+1);o=p;m(x);m(w);(n=rand())&255||--*w||++*w;if(!(**P&&P++||n&7936)){
|
||||
while(abs((X=rand()%76)-*x+2)-*w<6);++X;P=T;}(n=rand()&31)<3&&(d=n);!d&&--*x<=
|
||||
*w&&(++*x,++d)||d==2&&++*x+*w>79&&(--*x,--d);signal(i,u);}void e(){signal(14,
|
||||
SIG_IGN);printf("\e[0q\ecScore: %u\n",s);system("stty echo -cbreak");}int main
|
||||
(int C,char**V){atexit(e);(C<2||*V[1]!=113)&&(f=(C=*(int*)getenv("TERM"))==(
|
||||
int)0x756E696C||C==(int)0x6C696E75);srand(getpid());system("stty -echo cbreak"
|
||||
);h(0);u(14);for(;;)switch(getchar()){case 113:return 0;case 91:case 98:c(44,k
|
||||
=-1);case 32:case 110:c(46,k=0);case 93:case 109:c(47,k=1);c(49,h(0));c(50,h(1
|
||||
));c(51,h(2));c(52,h(3));}}
|
||||
@@ -0,0 +1,40 @@
|
||||
Worst Driver:
|
||||
|
||||
Chris King
|
||||
115 Foster Center Road
|
||||
Foster, RI, 02825
|
||||
USA
|
||||
|
||||
|
||||
Judge's Remarks:
|
||||
|
||||
To build:
|
||||
|
||||
make ctk
|
||||
|
||||
Try:
|
||||
|
||||
./ctk
|
||||
|
||||
No matter how careful you are, this guy eventually crashes. Most people
|
||||
can make at least one successful road trip without crashing.
|
||||
|
||||
This is, of course, another of the retro games.
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
This is a game based on an Apple ][ Print Shop Companion easter
|
||||
egg named 'DRIVER', in which the goal is to drive as fast as
|
||||
you can down a long twisty highway without running off the
|
||||
road. Use ',./', '[ ]', or 'bnm' to go left, straight, and
|
||||
right respectively. Use '1234' to switch gears. 'q' quits. The
|
||||
faster you go and the thinner the road is, the more points you
|
||||
get. Most of the obfuscation is in the nonsensical if statements
|
||||
among other things. It works best on the Linux console: you
|
||||
get engine sound (!) and the * Lock keyboard lights tell you
|
||||
what gear you're in (none lit=4th). The 'q' argument (no
|
||||
leading '-') will silence the sound. It won't work on a terminal
|
||||
smaller than 80x24, but it works fine with more (try it in an
|
||||
XTerm with the "Unreadable" font and the window maximized
|
||||
vertically!).
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#define A(x,y) i[a++]=(N){c,c+x,y};
|
||||
#define B(x,y) j[b++]=(N){c,c+x,y};
|
||||
#define C(j,k) for (j=0; j<k; j++){
|
||||
#define D(x) C(_,8)if(!(c+x[_]&136)){ if(p[c+x[_]]*p[c]<0)B(x[_],0)else if(!p[c+x[_]])A(x[_],0)} }
|
||||
#define J printf(
|
||||
#define O(v) _=v; while(!(c+_&136)){ x=p[c+_]*p[c]; if(x<0){B(_,0)E; } else if(x>0)E; else A(_,0)_+=v; }
|
||||
#define X(x) G(x,L)
|
||||
#define Z(x,y) memcpy(x,y,256);
|
||||
|
||||
typedef struct {
|
||||
F a,b,c;
|
||||
} N;
|
||||
|
||||
F g[]="KSLAU",
|
||||
p[256],v[]="{ ; } ; { ; ; ; { } ; { ; } { ; } { } ; { ; ; ; { ; } ; } } ; { ; ; { } ; { } } ; { ; ; { { ; ; { } } ; } ; ; { } ; { } } ; { ; ; { { ; { } } ; { ; ; { } ; { { ; ; { } ; ; ; ; { ; } { { ; ; ; { } ; { ; ; ";
|
||||
F S[]="{}; ",W[256],L[1024];
|
||||
P q[]={-14,-31,-33,-18,14,31,33,18},r[]={-1,-17,-16,-15,1,17,16,15},_,a,b,c,d,e,t=1,x,y,z;
|
||||
N i[500],j[500],*k,u;
|
||||
P f(N *V) {
|
||||
a=b=0;
|
||||
C(d,8)
|
||||
C(e,8)
|
||||
c=d<<4|e;
|
||||
if(p[c]==0||p[c]*t<0)continue;
|
||||
switch(p[c]<0?-p[c]:p[c]){
|
||||
K 80:
|
||||
if(56+t*40==(c&112)&&!p[c-32*t])
|
||||
A(t*-32,0)
|
||||
if(56+t*-40==(c&112)){
|
||||
if(!(c-17*t&136)&&p[c-17*t]*t<0){
|
||||
C(_,5)
|
||||
B(-17*t,(g[_]^_)*t)}
|
||||
}
|
||||
if(!(c-15*t&136)&&p[c-15*t]*t<0){
|
||||
C(_,5)
|
||||
B(-15*t,(g[_]^_)*t)}
|
||||
}
|
||||
C(_,5)
|
||||
A(t*-16,(g[_]^_)*t)}
|
||||
}else{
|
||||
if(!p[c-16*t])
|
||||
A(t*-16,0)
|
||||
if(!(c-(17*t)&136)&&p[c-17*t]*t<0){
|
||||
B(-17*t,0)
|
||||
}
|
||||
if(!(c-(15*t)&136)&&p[c-15*t]*t<0){
|
||||
B(-15*t,0)
|
||||
}
|
||||
}
|
||||
E;
|
||||
K 78:D(q)E;
|
||||
K 81:
|
||||
K 66:O(17)O(-17)O(15)O(-15)
|
||||
if(p[c]==66||p[c]==-66)
|
||||
E;
|
||||
K 82:O(1)O(-1)O(16)O(-16)E;
|
||||
K 75:D(r)
|
||||
} ;
|
||||
}
|
||||
}
|
||||
if ( b > 0 ) {
|
||||
C(_,b)V[_]=j[_]; }
|
||||
R b;
|
||||
} else {
|
||||
C(_,a)V[_]=i[_]; }
|
||||
R a;
|
||||
}
|
||||
}
|
||||
F *G(F *n, F *o){
|
||||
a=b=0;
|
||||
for(; n[b]; d=0){
|
||||
do{
|
||||
d*=4;
|
||||
d+=W[n[b++]];
|
||||
} while(++b<8*a+8);
|
||||
o[a++]=d;
|
||||
}
|
||||
o[a]=0;
|
||||
R o;
|
||||
}
|
||||
m(N a){ p[a.b]=a.c?a.c:p[a.a]; p[a.a]=0; }
|
||||
h(){
|
||||
J X("{ ; { { { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { { ; ; "));
|
||||
c=0; C(c,120)c%8==0&&putchar(56-c/16);
|
||||
if(p[c]<0){
|
||||
J X("} { { ; { { { ; ; ; { ; } } } ; { "),-p[c]);
|
||||
} else if(p[c]>0)
|
||||
J X("} { { ; { { { ; } } } ; { { ; { { "),p[c]);
|
||||
else
|
||||
J"| ");
|
||||
c%8==7?J X("} { { { ; ; { ; { { { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { { ; ; ")),c+=8:0;
|
||||
}
|
||||
}
|
||||
s() {
|
||||
b=0; C(a,256)
|
||||
if(v[b]==94){
|
||||
b++; C(c,v[b]-32)p[a++]=v[b+1]-120;}
|
||||
b+=2; a--;
|
||||
} else
|
||||
p[a]=v[b++]-120;
|
||||
}
|
||||
}
|
||||
P w() {
|
||||
P v=0;
|
||||
C(_,120)
|
||||
p[_]&&(p[_]*t>0&&v--,p[_]*t<0&&v++);
|
||||
}
|
||||
v+=f(i); v-=b?100:0;t=-t; v-=f(i); v+=b?100:0;t=-t;
|
||||
|
||||
R v;
|
||||
}
|
||||
P V(P n, P o) {
|
||||
P s=-I,G,H,Y;
|
||||
N M[500];
|
||||
F u[256];
|
||||
|
||||
if(!(n+o))R w()+time(NULL)%9-4;
|
||||
if(!(H=f(M)))R I;
|
||||
H<5?H==1?n++:(o<6?o++:0):0;
|
||||
Z(u,p)
|
||||
C(G,H)
|
||||
Z(p,u)
|
||||
m(M[G]);
|
||||
t=-t;
|
||||
s=(e=-V(n-1,o))>s?Y=G,e:s;
|
||||
t=-t;
|
||||
}
|
||||
e=Y;
|
||||
R s;
|
||||
}
|
||||
main(P db, F *bd[]){
|
||||
N o[500];
|
||||
F T[256];
|
||||
|
||||
C(a,256)W[a]=-1; }
|
||||
C(a,4)W[S[a]]=a; }
|
||||
G(v,v); s();
|
||||
while(1){
|
||||
h();
|
||||
b=f(o);
|
||||
scanf("%s",L);
|
||||
if(strcmp(L,"quit")==0)R 0;
|
||||
else if(strcmp(L,"g")==0){
|
||||
Z(T,p)
|
||||
J G("} } } ; } ; { } } ; { } } } } ; } } { ; { { { ; } } } ; } { { { ; ; ",L), V(db>1?atoi(bd[1]):3,0));
|
||||
Z(p,T)m(o[e]); t=-t;
|
||||
}else{
|
||||
u.a=896-16*L[1];
|
||||
u.b=896-16*L[3];
|
||||
u.a+=L[0]-97;
|
||||
u.b+=L[2]-97;
|
||||
u.c=L[4]?L[5]:0;
|
||||
C(a,b)
|
||||
if(u.a==o[a].a&&u.b==o[a].b&&u.c==o[a].c)E;
|
||||
}
|
||||
a==b?J X("} { ; } } ; { } ; { } ; } } } ; } } ; { } } ; { { ; { { } ; } } ; } } ; } ; } } { { ; ; ")):(m(u),t=-t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
Best AI:
|
||||
|
||||
Doug Beardsley
|
||||
Southern Adventist University
|
||||
359 Davis Rd. NW
|
||||
Cleveland, TN 37312
|
||||
USA
|
||||
|
||||
|
||||
Judge's Remarks:
|
||||
|
||||
To build:
|
||||
|
||||
make dgbeards
|
||||
|
||||
Try:
|
||||
|
||||
./dgbeards
|
||||
|
||||
This is probably the worst AI we've ever seen. So, then, why did
|
||||
the entry win? Because it's *trying* to lose.
|
||||
|
||||
This is also one of the first chess games we've seen.
|
||||
|
||||
Of particular interest is the author's decision that the program should
|
||||
crash if it loses. I've played chess with a lot of people like that, and
|
||||
I appreciate the realism.
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
FAQ:
|
||||
|
||||
Q: What does this program do?
|
||||
|
||||
A: It lets the user play two player or single player games of suicide
|
||||
chess. Suicide Chess (also known as Losing Chess) is a variant of normal
|
||||
chess. It is played on the same board and uses the same pieces. Here is
|
||||
a list of the differences:
|
||||
|
||||
1. The object of the game is to get to a position where you have no legal
|
||||
moves. This is usually accomplished by losing all of your pieces.
|
||||
Sometimes, the game can end when you still have some pawns on the board,
|
||||
but they are blocked and cannot move. The general rule is if a player
|
||||
has no legal moves, the game is over. The winner is the player with fewer
|
||||
pieces on the board. This is almost always the same player that had no
|
||||
moves, but not always.
|
||||
|
||||
2. In suicide chess, piece captures are compulsory. If a player can
|
||||
capture an opponent's piece, he is required to do so. If he can capture
|
||||
more than one of the opponent's pieces or can capture one piece with more
|
||||
than one of his own pieces, he can choose which capture to play.
|
||||
|
||||
3. The king is not significant. There is no concept of check and the king
|
||||
can be captured.
|
||||
|
||||
4. Because of rule 3, pawns are allowed to promote to a king.
|
||||
|
||||
5. Castling is not allowed.
|
||||
|
||||
Q: How do you use this program?
|
||||
|
||||
A: The program is fairly straightforward. When you start the program,
|
||||
it displays the opening position for a game of suicide chess and waits
|
||||
for user input. Commands are as follows:
|
||||
|
||||
quit - Quits the program
|
||||
g - Causes the computer to make a move
|
||||
|
||||
Moves are represented by the long algebraic notation for the move. For
|
||||
those not familiar with long algebraic notation, a move consists of a
|
||||
square to move from followed by a square to move to. Squares are denoted
|
||||
by a letter and a number. The letter specifies the column or file of the
|
||||
square and the number specifies the row rank. Files are named from left
|
||||
to right by the letters a-h. Rows are numbered from bottom to top with
|
||||
the numbers 1-8. A sample move from the opening position is e2e3. This
|
||||
means to move a piece from square e2 to e3. From the opening position,
|
||||
this corresponds to moving the king pawn forward one square. This is
|
||||
generally to be considered one of the best opening moves in suicide
|
||||
chess. All moves, captures and otherwise, are represented with this
|
||||
notation. A special case is pawn promotion moves. They use the same
|
||||
notation followed by an '=' and a letter representing the piece to
|
||||
promote to. The letters are R,N,B,Q,K representing rook, knight, bishop,
|
||||
queen, and king respectively. The letters must be upper case.
|
||||
|
||||
You can also specify a command line argument of a single digit to change
|
||||
the search depth of the program. If no argument is specified, it
|
||||
defaults to a depth of 3.
|
||||
|
||||
Q: Are there any limitations in your program?
|
||||
|
||||
A: Yes. The first of the limitations is that you can only play legal
|
||||
moves according to the rules of suicide chess. En passant captures are
|
||||
not recognized. They are rarely encountered in suicide chess and when
|
||||
they do happen, they usually do not change the outcome of the game. As
|
||||
mentioned above, castling is not allowed either.
|
||||
|
||||
It also does not detect the end of the game. It can see sure wins or
|
||||
losses several moves ahead, but does not announce the end of a game or
|
||||
the winner. Given the existing code it is easy to do this, but it was
|
||||
deemed unnecessary fluff.
|
||||
|
||||
Q: What is the playing strength of this program?
|
||||
|
||||
A: Playing strength is a relative term. Relative to other computer
|
||||
programs that play suicide chess, it is about the bottom. There is one
|
||||
freeware program in existence called kenny that this program can beat,
|
||||
but that is about it.
|
||||
|
||||
Suicide chess is a very tactical game. Most humans who do not have any
|
||||
experience in suicide chess will lose to this program. The Free Internet
|
||||
Chess Server (http://www.freechess.org) is a free online chess server
|
||||
that supports suicide chess. This server keeps track of ratings. The
|
||||
human ratings for suicide chess range from 1000 to about 2400. This
|
||||
program would probably be rated somewhere around 1700-1900. It is better
|
||||
than most players, but will get destroyed by experienced human opponents.
|
||||
|
||||
This program searches to a fixed depth of 3 ply. Because it does not
|
||||
search very deep, it performs very poorly in quiet strategic positions.
|
||||
In such positions, it will often just shuffle pieces around aimlessly
|
||||
until a tactical exchange presents itself.
|
||||
|
||||
A small amount of randomness has been added to make the program a more
|
||||
interesting opponent. The to avoid a call to srand(), rand() and the
|
||||
extra code for the required include files, the time() function is used as
|
||||
the source of random data. It is a slow function, and since it is
|
||||
executed inside the search loop, there is a significant performance
|
||||
decrease. To make it faster, replace the time() call with rand() and add
|
||||
the line srand(time(0)); to the beginning of main(). I used the more
|
||||
inefficient time() function to illustrate a different (and somewhat
|
||||
obfuscated?) way of generating random numbers.
|
||||
|
||||
Q: Why is this program obfuscated?
|
||||
|
||||
A: Here are several reasons:
|
||||
|
||||
First, without preprocessing, the code is not easy to read. The
|
||||
preprocessor is used to compress the code and obfuscate it. The main
|
||||
obstacle to entering this program is the source code size limit. This is
|
||||
the reason that the preprocessor was used so liberally. It is one of the
|
||||
best ways to compress C source code.
|
||||
|
||||
Second, when possible, variables in the program were made global. Their
|
||||
names are not descriptive and they are used for a variety of purposes
|
||||
throughout the program. Because of this, it is difficult to determine
|
||||
exactly what the code does even after preprocessing and beautifying the
|
||||
code.
|
||||
|
||||
Third, all function names are a single character and are obviously not
|
||||
descriptive of they're actual purpose. Again this serves the dual
|
||||
purpose of compression and obfuscation.
|
||||
|
||||
Fourth, most string variables have been encoded. This encoding serves
|
||||
to obfuscate the program as well as reduce the number of countable
|
||||
characters and get the program under the size limit of this year's IOCCC.
|
||||
There are some places where other simple encoding methods are used to
|
||||
hide the real purpose of strings. These layers of obscurity cannot be
|
||||
penetrated by just preprocessing and beautifying the program.
|
||||
|
||||
Fifth, various small obfuscations have been used in places all over the
|
||||
program. Short circuit evaluation is used as a substitute for if()
|
||||
statements in some places. The ternary operator is used. In the
|
||||
author's opinion, use of the ternary operator is almost always a strong
|
||||
argument for employee turnover.
|
||||
|
||||
Last, if you have succeeded in wading through the previous layers of
|
||||
obfuscation, you are confronted by the fact that the game that it
|
||||
implements is an obscure game. Casual inspection of the program might
|
||||
lead one to believe that it is an implementation of classic chess, but
|
||||
this is not so.
|
||||
|
||||
Q: What about the compiler warnings?
|
||||
|
||||
A: When compiled with gcc -Wall, the compiler generated the following
|
||||
warnings:
|
||||
|
||||
suggest parentheses around + or - in operand of &
|
||||
array subscript has type 'char'
|
||||
return type defaults to 'int'
|
||||
control reaches end of non-void function
|
||||
value computed is not used
|
||||
|
||||
The "value computed is not used" warning happens because I use the &&
|
||||
operator and take advantage of short circuit evaluation instead of using
|
||||
an if() statement.
|
||||
|
||||
The "suggest parentheses..." warnings are given because of expressions
|
||||
that depend on operator precedence details in the C language.
|
||||
Eliminating these warnings would reduce obfuscation.
|
||||
|
||||
The other warnings are there because it would require more code to
|
||||
eliminate them and that can't be done given the size limit.
|
||||
|
||||
Q: Why does this program crash when it loses?
|
||||
|
||||
A: What better way to admit defeat? The author thought this was
|
||||
appropriate sportsmanship for a program of this genre and can think of
|
||||
no worse job than trying to find an elusive bug in an intentionally
|
||||
obfuscated program.
|
||||
|
||||
[judge's note: This was followed by a description of the bug, and
|
||||
the comment:]
|
||||
|
||||
(Note, if this program wins, the author thinks it would be good to leave
|
||||
this information out of the remarks and encourage others to try and
|
||||
figure it out for themselves)
|
||||
|
||||
[should you be too lazy to figure it out yourself, here's the author's
|
||||
fix. I would have rot13'd it, but the punctuation would have survived.]
|
||||
|
||||
begin 644 fix.txt
|
||||
M5&AI<R!B=6<@8V%N(&)E(&9I>&5D(&EN(&$@;G5M8F5R(&]F('=A>7,L(&)U
|
||||
M="!T:&5R90II<R!A('=A>2!T:&%T(&%D9',@;VYL>2!O;F4@8GET92!T;R!T
|
||||
M:&4@<V]U<F-E(&-O9&4N("!);B!T:&4@<W1A=&5M96YT"G,]*&4]+58H;BTQ
|
||||
M+&\I*3YS/UD]1RQE.G,[(&-H86YG92!T:&4@/B!T;R!A(#X](&%N9"!T:&4@
|
||||
38G5G('=I;&P@8F4@9V]N92X*"FYG
|
||||
`
|
||||
end
|
||||
+840
@@ -0,0 +1,840 @@
|
||||
16th International Obfuscated C Code Contest Guidelines, Hints and Comments |
|
||||
|
||||
Copyright (c) Leonid A. Broukhis, Simon Cooper, Landon Curt Noll and |
|
||||
Peter Seebach, 2001. |
|
||||
|
||||
All Rights Reserved. Permission for personal, education or non-profit use is
|
||||
granted provided this this copyright and notice are included in its entirety
|
||||
and remains unaltered. All other uses must receive prior permission in
|
||||
writing from the contest judges.
|
||||
|
||||
|
||||
ABOUT THIS FILE:
|
||||
|
||||
This file is intended to help people who wish to submit entries to
|
||||
the International Obfuscated C Code Contest (IOCCC for short).
|
||||
|
||||
This is not the IOCCC rules, though it does contain comments about
|
||||
them. The guidelines should be viewed as hints and suggestions.
|
||||
Entries that violate the guidelines but remain within the rules are
|
||||
allowed. Even so, you are safer if you remain within the guidelines.
|
||||
|
||||
You should read the current IOCCC rules, prior to submitting entries.
|
||||
The rules are typically sent out with these guidelines.
|
||||
|
||||
Changes from the 2000 rules are denoted by change bars. ---> |
|
||||
Not every change is marked in this file is marked, but
|
||||
most are. :-)
|
||||
|
||||
WHAT'S NEW IN 2001: |
|
||||
|
||||
The contest runs from 01-Oct-2001 00:00 UTC to 01-Dec-2001 23:59 UTC. |
|
||||
|
||||
HINTS AND SUGGESTIONS:
|
||||
|
||||
You are encouraged to examine the winners of previous contests. See
|
||||
FOR MORE INFORMATION for details on how to get previous winners.
|
||||
|
||||
Keep in mind that rules change from year to year, so some winning entries
|
||||
may not be valid entries this year. What was unique and novel one year
|
||||
might be 'old' the next year.
|
||||
|
||||
An entry is usually examined in a number of ways. We typically apply
|
||||
a number of tests to an entry:
|
||||
|
||||
* look at the original source
|
||||
* convert ANSI tri-graphs to ASCII
|
||||
* C pre-process the source ignoring '#include' lines
|
||||
* C pre-process the source ignoring '#define' and '#include' lines
|
||||
* run it through a C beautifier
|
||||
* examine the algorithm
|
||||
* compile it (with flags to enable all warnings) |
|
||||
* execute it
|
||||
|
||||
You should consider how your entry looks in each of the above tests.
|
||||
You should ask yourself if your entry remains obscure after it has been
|
||||
'cleaned up' by the C pre-processor and a C beautifier.
|
||||
|
||||
Your entry need not pass all of the above tests. In certain
|
||||
cases, a test is not important. Entries that compete for the
|
||||
'strangest/most creative source layout' need not do as well as
|
||||
others in terms of their algorithm. On the other hand, given
|
||||
two such entries, we are more inclined to pick the entry that
|
||||
does something interesting when you run it.
|
||||
|
||||
We try to avoid limiting creativity in our rules. As such, we leave
|
||||
the contest open for creative rule interpretation. As in real life
|
||||
programming, interpreting a requirements document or a customer request
|
||||
is important. For this reason, we often award 'worst abuse of the
|
||||
rules' to an entry that illustrates this point in an ironic way.
|
||||
|
||||
We do realize that there are holes in the rules, and invite entries
|
||||
to attempt to exploit them. We will award 'worst abuse of the rules'
|
||||
and then plug the hole next year. Even so, we will attempt to use
|
||||
the smallest plug needed, if not smaller. :-)
|
||||
|
||||
Check out your program and be sure that it works. We sometimes make
|
||||
the effort to debug an entry that has a slight problem, particularly
|
||||
in or near the final round. On the other hand, we have seen some
|
||||
of the best entries fall down because they didn't work.
|
||||
|
||||
We tend to look down on a prime number printer, that claims that
|
||||
16 is a prime number. If you do have a bug, you are better off
|
||||
documenting it. Noting "this entry sometimes prints the 4th power
|
||||
of a prime by mistake" would save the above entry. And sometimes,
|
||||
a strange bug/feature can even help the entry! Of course, a correctly
|
||||
working entry is best.
|
||||
|
||||
People who are considering to just use some complex mathematical
|
||||
function or state machine to spell out something such as "hello,
|
||||
world!" may want to try and be more creative.
|
||||
|
||||
Ultra-obfuscated programs are in some cases some cases easier to
|
||||
deobfuscate than subtly-obfuscated programs. Consider using
|
||||
misleading or subtle tricks layered on top of or under an
|
||||
appropriate level of obfuscation.
|
||||
|
||||
Programs that use VTxxx/ANSI sequences that are NOT limited to a
|
||||
specific terminal brand and that can also work in a standard xterm
|
||||
are considered portable.
|
||||
|
||||
|
||||
OUR LIKES AND DISLIKES:
|
||||
|
||||
Doing masses of #defines to obscure the source has become 'old'. We
|
||||
tend to 'see thru' masses of #defines due to our pre-processor tests
|
||||
that we apply. Simply abusing #defines or -Dfoo=bar won't go as far
|
||||
as a program that is more well rounded in confusion.
|
||||
|
||||
Many ANSI C compilers dislike the following code, and so do we:
|
||||
|
||||
#define d define
|
||||
#d foo <-- don't expect this to turn into #define foo
|
||||
|
||||
When declaring local or global variables, you should declare the type:
|
||||
|
||||
int this_is_ok;
|
||||
this_is_not; <-- don't use such implicit type declarations |
|
||||
|
||||
We suggest that you compile your entry with an ANSI C compiler. If you
|
||||
must use non-ANSI C, such as K&R C, you must avoid areas that result in
|
||||
compile/link errors for ANSI C compilers. For example, using gcc
|
||||
local function declarations, such as:
|
||||
|
||||
int
|
||||
main() {
|
||||
void blah() { printf("blah\n"); }
|
||||
blah();
|
||||
}
|
||||
|
||||
are not allowed even though their existence seems tailor made for
|
||||
this contest! But for now, since they are not in wide spread use
|
||||
we cannot accept entries that use them.
|
||||
|
||||
If your entry uses functions that have a variable number of
|
||||
arguments, be careful. Systems implement va_list as a wide variety
|
||||
of ways. Because of this, a number of operations using va_list are
|
||||
not portable and must not be used:
|
||||
|
||||
* assigning a non-va_list variable to/from a va_list variable
|
||||
* casting a non-va_list variable into/from a va_list variable
|
||||
* passing a va_list variable to a function expecting a non-va_list arg
|
||||
* passing a non-va_list variable to a function expecting a va_list arg
|
||||
* performing arithmetic on va_list variables
|
||||
* using va_list as a structure or union
|
||||
|
||||
In particular, do not treat va_list variables as if they were a char **'s.
|
||||
|
||||
Avoid using <varargs.h>. Use <stdarg.h> instead.
|
||||
|
||||
If you use C preprocessor directives (#define, #if, #ifdef, ...),
|
||||
the leading '#' must be the first non-whitespace character on a line.
|
||||
While some broken C preprocessors do not allow whitespace before a
|
||||
'#', most do.
|
||||
|
||||
The exit() function returns void. On some broken systems have exit()
|
||||
return int. Your entry should assume that exit() returns a void.
|
||||
|
||||
Small programs are best when they are short, obscure and concise.
|
||||
While such programs are not as complex as other winners, they do
|
||||
serve a useful purpose. They are often the only program that people
|
||||
attempt to completely understand. For this reason, we look for
|
||||
programs that are compact, and are instructional.
|
||||
|
||||
One line programs should be short one line programs, say around 80
|
||||
bytes long. Getting close to 160 bytes is a bit too long in our opinion.
|
||||
|
||||
We tend to dislike programs that:
|
||||
|
||||
* are very hardware specific
|
||||
* are very OS version specific
|
||||
(index/strchr differences are ok, but socket/streams specific
|
||||
code is likely not to be)
|
||||
* dump core or have compiler warnings
|
||||
(it is ok only if you warn us in the 'remark' header item)
|
||||
* won't compile or run under a POSIX P1003.1/P1003.2 like systems
|
||||
* depend on a utility or application not normally found on most
|
||||
most POSIX P1003.1/P1003.2 like systems
|
||||
* abuse the build file to get around the size limit
|
||||
* obfuscate by excessive use of ANSI tri-graphs
|
||||
* are longer than they need to be
|
||||
* are similar to previous winners
|
||||
* are identical to previous losers :-)
|
||||
* are identical to future losers (Windows XP) :-) |
|
||||
|
||||
Unless you are cramped for space, or unless you are entering the
|
||||
'best one liner' category, we suggest that you format your program
|
||||
in a more creative way than simply forming excessively long lines.
|
||||
|
||||
The build file should not be used to try and get around the size
|
||||
limit. It is one thing to make use of a several -D's to help out,
|
||||
but it is quite another to use 200+ bytes of -D's in order to
|
||||
try and squeeze the source under the size limit. You should feel
|
||||
free to make use of the build file space, but you are better off
|
||||
if you show some amount of restraint.
|
||||
|
|
||||
You should try to restrict commands used on the build file to |
|
||||
POSIX-like or common Un*x-like commands. You can also compile |
|
||||
and use your own programs. If you do, try to build and execute |
|
||||
from the current directory. This restriction is not a hard and |
|
||||
absolute one. The intent is to ensure that the building if your |
|
||||
program is reasonably portable. |
|
||||
|
|
||||
Don't forget that the building of your program should be done |
|
||||
***without human intervention***. So don't do: |
|
||||
|
|
||||
cat > prog.c |
|
||||
cc prog.c -o prog |
|
||||
|
|
||||
However, you can do something cute such as making your program |
|
||||
do something dumb (or cute) when build 'automatically'. However |
|
||||
when it is run with a human involved, do something more cleaver. |
|
||||
For example, one could use the build instructions: |
|
||||
|
|
||||
cc prog.c -DNONHUMAN -o prog |
|
||||
echo "See remarks section about alternate ways to compile" |
|
||||
|
|
||||
and then include special notes in the ---remarks--- section for |
|
||||
alternate / human intervention based building. |
|
||||
|
||||
We want to get away from source that is simply a compact blob of
|
||||
characters. To help, we give a break to source that contains
|
||||
whitespace, and in certain cases ; { or } characters. While the
|
||||
number of characters excluding whitespace (tab, space, newline),
|
||||
and excluding any ; { or } followed immediately by either whitespace
|
||||
or end of file, must be <= 2048, the total size may be less than 4096 |
|
||||
bytes. This means that one may use "free of charge" up to 2048 |
|
||||
bytes of whitespace, or ; { or } followed by either whitespace
|
||||
or end of file.
|
||||
|
||||
Please do not use things like gzip to get around the size limit.
|
||||
|
||||
Given two versions of the same program, one that is a compact blob
|
||||
of code, and the other that is formatted more like a typical C
|
||||
program, we tend to favor the second version. Of course, a third
|
||||
version of the same program that is formatted in an interesting
|
||||
and/or obfuscated way, would definitely win over the first two!
|
||||
|
||||
We suggest that you avoid trying for the 'smallest self-replicating'
|
||||
source. The smallest, a zero byte entry, won in 1994.
|
||||
|
||||
We do not like writable strings. That is, we don't want stuff like:
|
||||
|
||||
char *T = "So many primes, so little time!";
|
||||
...
|
||||
T[14] = ';';
|
||||
|
||||
Please don't make use of this feature, even if your system allows it.
|
||||
However, initialized char arrays are OK to write over. This is OK: |
|
||||
|
|
||||
char b[] = "Is this Ok"; |
|
||||
b[9] = 'K'; |
|
||||
|
||||
X client entries should be as portable as possible. Entries that
|
||||
adapt to a wide collection of environments will be favored. Don't
|
||||
depend on a particular type of display. For example, don't depend
|
||||
on color or a given size. Don't require backing store.
|
||||
|
||||
X client entries should avoid using X related libraries and
|
||||
software that is not in wide spread use.
|
||||
|
||||
We don't like entries that use proprietary M*tif, Xv*ew, or OpenL*ok |
|
||||
toolkits, since not everyone has them. Use of OpenMotif is permitted |
|
||||
because it is more widely and freely available. |
|
||||
|
||||
You should avoid depending on a particular window manager.
|
||||
|
||||
X client entries should not to depend on particular items on
|
||||
.Xdefaults. If you must do so, be sure to note the required lines
|
||||
in the ---remark--- section.
|
||||
|
||||
While we recognize that UN*X is not a universal operating system, the
|
||||
contest does have a bias towards such systems. In an effort to expand
|
||||
the scope of the contest, we phrase our bias in terms of POSIX P1003.1
|
||||
and P1003.2 standards. This will allow certain non-UN*X OS users to
|
||||
submit entries. On the other hand, this is a guideline and not a rule.
|
||||
We will not reject an entry based on some POSIX technicality.
|
||||
|
||||
When dealing with OS and application environments, we suggest that you
|
||||
be reasonable with a nod towards vanilla UN*X-like systems. POSIX will
|
||||
evolve but not as much as the contest, so avoid stuff like POSIX real
|
||||
time, security, etc.
|
||||
|
||||
We like programs that:
|
||||
|
||||
* are as concise and small as they need to be
|
||||
* do something at least quasi-interesting
|
||||
* are portable
|
||||
* are unique or novel in their obfuscation style
|
||||
* MAKE USE OF A NUMBER OF DIFFERENT TYPES OF OBFUSCATION <== HINT!!
|
||||
* make us laugh and/or throw up :-) (humor helps!)
|
||||
|
||||
Some types of programs can't excel (tm) in some areas. Of course, your
|
||||
program doesn't have to excel in all areas, but doing well in several
|
||||
areas really does help.
|
||||
|
||||
You are better off explaining what your entry does in the
|
||||
---remark--- section rather than leaving it obscure for the judges
|
||||
as we might miss something and/or be too tired to notice.
|
||||
|
||||
We freely admit that interesting, creative or humorous comments in
|
||||
the ---remark--- section help your chances of winning. If you had to
|
||||
read so many twisted entries, you too would enjoy a good laugh or two.
|
||||
We think the readers of the contest winners do as well. We do read
|
||||
the ---remark--- section during the judging process, so it is worth
|
||||
your while to write a remarkable ---remark--- section.
|
||||
|
|
||||
We dislike C code with trailing control-M's (\r or \015) that results |
|
||||
in compilation failures. Some non-Un*x/non-Linux tools such as |
|
||||
MS Visual C and MS Visual C++ leave trailing control-M's on lines. |
|
||||
Users of such tools should strip off such control-M's before submitting |
|
||||
their entries. In some cases tools have a "Save As" option that will |
|
||||
prevent such trailing control-M's being added. |
|
||||
|
|
||||
We dislike entries that depend on non-portable libcurses features such |
|
||||
as halfdelay(). One should restrict libcurses to portable features |
|
||||
found on BSD and SVR4/System V curses. |
|
||||
|
|
||||
The rules disallow source that contains unescaped octets with values |
|
||||
between 128 and 255. You must use \octal or \hex escapes instead: |
|
||||
|
|
||||
/* 123456789 123456789 123456789 123456 */ |
|
||||
char *foo = "This string is 36 octets in length \263"; |
|
||||
/* This octet requires 4 octets of source ^^^^ */ |
|
||||
if (strlen(foo) == 36) printf("foo is 36 octets a final NUL\n"); |
|
||||
|
||||
Be creative!
|
||||
|
||||
|
||||
ABUSING THE RULES:
|
||||
|
||||
Legal abuse of the rules is somewhat encouraged. Legal rule abuse may
|
||||
involve, but is not limited to, doing things that are technically
|
||||
allowed by the rules and yet do not fit the spirit of what we
|
||||
intended to be submitted.
|
||||
|
||||
Legal rule abuse is encouraged to help promote creativity. Rule
|
||||
abuse entries, regardless of if they receive an award, result in
|
||||
changes to the next year's rules and guidelines.
|
||||
|
||||
Legal abuse of the rules is NOT an invitation to violate the
|
||||
rules. An entry that violates the rules in the opinion of the
|
||||
judges, WILL be disqualified. RULE ABUSE CARRIES A CERTAIN LEVEL
|
||||
OF RISK! If you have an entry that might otherwise be interesting,
|
||||
you might want to submit two versions; one that does not abuse the
|
||||
rules and one that does.
|
||||
|
||||
If you intend to abuse the rules, indicate so in the ---remark---
|
||||
section. You must try to justify why you consider your rule abuse
|
||||
to be allowed under the rules. That is, you must plead your case
|
||||
as to why your entry is valid. Humor and/or creativity help plead
|
||||
a case.
|
||||
|
||||
Abusing the entry format tends to annoy us more than amuse us.
|
||||
|
||||
We are often asked why the contest rules and guidelines seem too
|
||||
strange or contain mistakes, flaws or grammatical errors.
|
||||
One reason is that we sometimes make genuine mistakes. But in many
|
||||
cases such problems, flaws or areas of confusion are deliberate.
|
||||
Changes to rules and guidelines in response to rule abuses, are
|
||||
done in a minimal fashion. Often we will deliberately leave
|
||||
behind holes (or introduce new ones) so that future rule abuse may
|
||||
continue.
|
||||
|
||||
At the risk of stating the obvious, this contest is a parity of the
|
||||
software development process. The rules and guidelines are
|
||||
only a small part of the overall contest. Even so, one may think
|
||||
the contest rule and guideline process as a parody of the sometimes
|
||||
tragic mismatch between what a customer (or marketing) wants and
|
||||
what engineering delivers.
|
||||
|
||||
|
||||
ENTRY FORMAT:
|
||||
|
||||
In order to help us process the many entries, we must request your
|
||||
assistance by formatting your entries in a certain way. This format,
|
||||
in addition, allows us to quickly separate information about the
|
||||
author from the program itself. (see JUDGING PROCESS)
|
||||
|
||||
We have provided the program, mkentry, as an example of how to
|
||||
format entries. You should be aware of the following warning that
|
||||
is found in mkentry.c:
|
||||
|
||||
This program attempts to implement the IOCCC rules. Every
|
||||
attempt has been made to make sure that this program produces
|
||||
an entry that conforms to the contest rules. In all cases,
|
||||
where this program differs from the contest rules, the
|
||||
contest rules will be used. Be sure to check with the
|
||||
contest rules before submitting an entry.
|
||||
|
|
||||
NOTE: A copy of the mkentry program may be found at: |
|
||||
|
|
||||
http://www.ioccc.org/official/mkentry.c |
|
||||
|
||||
You are not required to use mkentry. It is convenient, however,
|
||||
as it attempts to uuencode the needed files, and attempt to check
|
||||
the entry against the size rules.
|
||||
|
||||
If you have any suggestions, comments, fixes or complaints about
|
||||
the mkentry.c program, please send EMail to the judges. (see below)
|
||||
|
||||
The following is a sample entry (the change bars are not part
|
||||
of the example, don't add them to your entry!)
|
||||
|
||||
---entry---
|
||||
rule: 2001 |
|
||||
fix: y
|
||||
title: chlejhse
|
||||
entry: 0
|
||||
date: Wed Feb 2 00:47:00 2001 |
|
||||
host: Un*x v6, pdp11/45
|
||||
2.9BSD, pdp11/70
|
||||
---remark---
|
||||
This is a not-very-obfuscated C program. It is likely not to win a
|
||||
prize, because it doesn't have what it takes to win and because the
|
||||
author plans to forget to send it in before the deadline! :-)
|
||||
---author---
|
||||
name: Landon Curt Noll
|
||||
org: IOCCC Judging Group
|
||||
addr: Toad Hall
|
||||
PO Box 170608
|
||||
San Francisco, California
|
||||
94117-0608
|
||||
USA
|
||||
Earth
|
||||
email: chongo@no_spam.fake.address
|
||||
nobody@toad.com
|
||||
url: http://www.isthe.com/chongo/index.html |
|
||||
anon: y
|
||||
---author---
|
||||
name: Leonid A. Broukhis
|
||||
org: IOCCC Judging Group
|
||||
addr: Toad Hall
|
||||
PO Box 170608
|
||||
San Francisco, California
|
||||
94117-0608
|
||||
USA
|
||||
email: leob@no_spam.fake_org
|
||||
url: http://www.mailcom.com/main.shtml
|
||||
anon: n
|
||||
---author---
|
||||
name: Simon Cooper |
|
||||
org: IOCCC Judging Group
|
||||
addr: Toad Hall
|
||||
PO Box 170608
|
||||
San Francisco, California
|
||||
94117-0608
|
||||
USA
|
||||
email: sc@no_spam.fake_edu |
|
||||
url: http://www.sfik.com |
|
||||
anon: n
|
||||
---author---
|
||||
name: Peter Seebach
|
||||
org: IOCCC Judging Group
|
||||
addr: Toad Hall
|
||||
PO Box 170608
|
||||
San Francisco, California
|
||||
94117-0608
|
||||
USA
|
||||
email: seebs@no_spam.fake_com
|
||||
url: none
|
||||
anon: y
|
||||
---info---
|
||||
begin 664 info.file
|
||||
M5&AI<R!F:6QE(&ES(&EN('1H92!P=6)L:6,@9&]M86EN+@H*:'1T<#HO+W=W
|
||||
M=RYI;V-C8RYO<F<*"E1H870@=&AA="!I<RP@:7,N"E1H870@=&AA="!I<R!N
|
||||
M;W0L"B`@("!I<R!N;W0@=&AA="!T:&%T(&YO="!I<RX*5&AA="!I<RP@=&AA
|
||||
M="!T:&%T(&ES(&YO="P@:7,A"@H)"2TM(&-H;VYG;R`Q.3<T"@I/;F4@;6EG
|
||||
M:'0@<V%Y.@H*"3(@:7,@=&AE(&=R96%T97-T(&]D9"!P<FEM92!B96-A=7-E
|
||||
M(&ET(&ES('1H92!L96%S="!E=F5N('!R:6UE+@H)4V\@;6%N>2!P<FEM97,@
|
||||
M+BXN('-O(&QI='1L92!T:6UE(0H*26X@,3DY,BP@;VYE('!E<G-O;B!T;VQD
|
||||
M('5S('1H870@=&AE>2!A8W1U86QL>2!D96-O9&5D('1H:7,@9FEL92X@($EN
|
||||
M"C$Y.3,@86YD(#$Y.30@82!F97<@;6]R92!D:60@=&AE('-A;64N("!);B`Q
|
||||
M.3DU+"!A(&YU;6)E<B!O9B!P96]P;&4@9G)O;0I%87-T97)N($5U<F]P92!T
|
||||
M;VQD('5S('1H870@=&AE>2!D96-O9&5D('1H:7,@9FEL92X@(%-E96US('1H
|
||||
M97)E(&ES(&$*<VUA;&P@=75D96-O9&4@9W)O=7`@:6X@16%S=&5R;B!%=7)O
|
||||
M<&4A("`Z+2D*"E=H>2!D;VXG="!Y;W4@=&5L;"!U<R!W:'D@>6]U(&1E8V]D
|
||||
M960@=&AI<R!F:6QE(&)Y('-E;F1I;F<@14UA:6P@=&\Z"@H)<75E<W1I;VYS
|
||||
M0&EO8V-C+F]R9PH*4&5R:&%P<R!Y;W4@;6EG:'0@<W5G9V5S="!A(&)E='1E
|
||||
M<B!E>&%M<&QE(&9I;&4@86YD('!R;V=R86T@9F]R('1H:7,*<V%M<&QE(&5N
|
||||
M=')Y/R`@268@>6]U(&1O('-E;F0@:7,@82!B971T97(@97AA;7!L92!F:6QE
|
||||
M+"!B92!W87)N960@+BXN"G1H870@:70@8V%N;F]T(&)E(&-O;G-I9&5R960@
|
||||
M87,@82!C;VYT97-T(&5N=')Y+B`@4V\@>6]U(&UI9VAT(&YO=`IW86YT('1O
|
||||
M('-E;F0@:6X@>6]U<B!B97-T('=O<FL@+BXN('-A=F4@=&AA="!F;W(@=&AE
|
||||
M(&-O;G1E<W0N("!/;B!T:&4@"F]T:&5R(&AA;F0@+BXN('EO=2!M:6=H="!W
|
||||
M86YT('1O('-E;F0@=7,@>6]U<B!M;W-T(&AU;6]R;W5S('=O<FLN("`@.BTI
|
||||
M"E5U96YC;V1E9"!C<F5D:70@=VEL;"!B92!G:79E;B!I9B!W92!P:6-K('EO
|
||||
6=7(@97AA;7!L92X*"D9I>GIB:6XA"@``
|
||||
`
|
||||
end
|
||||
---build---
|
||||
begin 664 build
|
||||
M9V-C("UA;G-I('!R;V<N8R`M3R`M1%9%4EE?4TE,3%E?1$5&24Y%("UO('!R
|
||||
#;V<*
|
||||
`
|
||||
end
|
||||
---program---
|
||||
begin 664 prog.c
|
||||
M;6%I;B@I"GL*("`@("\J"B`@("`@*B!.;W0@=F5R>2!O8F9U<V-A=&5D(&)U
|
||||
M="!T:&5N('=H870@9&ED('EO=2!E>'!E8W0@+BXN('1H:7,@:7,@:G5S=`H@
|
||||
M("`@("H@82!P;&%C96AO;&1E<B!E>&%M<&QE+@H@("`@("HO"B`@("!P<FEN
|
||||
M=&8H(E-O;65D87D@22!M:6=H="!W<FET92!A(&)E='1E<B!E>&%M<&QE+EQN
|
||||
M(BD["B`@("!P<FEN=&8H(D]N('-E8V]N9"!T:&]G=6AT("XN+B!N86@A7&XB
|
||||
M*3L*("`@('!R:6YT9B@B4V5N9"!U<R!A(&=O;V0@97AA;7!L92!B=70@8F4@
|
||||
M=V%R;F5D+"!A;GD@97AA;7!L92!Y;W5<;B(I.PH@("`@<')I;G1F*")S96YD
|
||||
M('5S('=I;&P@;F]T(&)E(&-O;G-I9&5R960@87,@86X@96YT<GD@9F]R('1H
|
||||
M92!C;VYT97-T(5QN(BD["B`@("!P<FEN=&8H(E-O('EO=2!M:6=H="!N;W0@
|
||||
M=V%N="!T;R!S96YD(&%N(&5X86UP;&4@;V8@>6]U<B!B97-T('=O<FM<;B(I
|
||||
M.PH@("`@<')I;G1F*"(N+BX@<V%V92!T:&%T(&9O<B!T:&4@8V]N=&5S="X@
|
||||
M($)U="!A(&=O;V0@:'5M;W)O=7,@<')O9R!M:6=H=%QN(BD["B`@("!P<FEN
|
||||
M=&8H(F1O("XN+B!A;F0@=V4@=VEL;"!G:79E('EO=2!U=65N8V]D960@8W)E
|
||||
M9&ET(&EN(')E='5R;BY<;B(I.PH@("`@+RH@14UA:6PZ('%U97-T:6]N<T!I
|
||||
M;V-C8RYO<F<@*B\*(VEF("%D969I;F5D*%9%4EE?4TE,3%E?1$5&24Y%*0H@
|
||||
K("`@;6%I;B@I.PHC96YD:68*("`@(&5X:70H,C,R,#D@)2`Q,C<I.PI]"@``
|
||||
`
|
||||
end
|
||||
---end---
|
||||
|
||||
Your entry's sections must be the same order as in the above example.
|
||||
|
||||
Typically the build file should assume that the source is prog.c
|
||||
and will compile into prog. If an entry wins, we will rename
|
||||
its source and binary to avoid filename collision. By tradition,
|
||||
we use the name of the entry's title, followed by an optional
|
||||
digit in case of name conflicts.
|
||||
|
||||
Please note that the title must match the following regexp:
|
||||
|
||||
^[a-zA-Z0-9_=][a-zA-Z0-9_=+-]*$
|
||||
|
||||
and must be 1 to 31 chars in length. Titles such as:
|
||||
|
||||
foo.c
|
||||
this_invalid_title_is_too_long
|
||||
/dev/null
|
||||
|
||||
are right out! :-)
|
||||
|
||||
Titles can be 31 chars long now, but please try to keep them short.
|
||||
Why 31? Because at least one of the judges likes Mersenne primes!
|
||||
|
||||
It is suggested, but not required, that the title should incorporate
|
||||
the author(s) username(s).
|
||||
|
||||
If the above entry somehow won the 'least likely to win' award,
|
||||
we would use chlejhse.c and chlejhse. |
|
||||
|
||||
If your entry depends on, or requires that your build, source
|
||||
and/or binary files be a particular name, please say so in the
|
||||
---remark--- section. If this case applies, it would be be helpful
|
||||
if you did one of the following:
|
||||
|
||||
* Tell us how to change the filename(s) in your entry.
|
||||
|
||||
* Have the build file make copies of the files. For example:
|
||||
|
||||
cc prog.c -o special_name
|
||||
|
||||
or rm -f special_src.c
|
||||
cp prog.c special_src.c
|
||||
cc special_src.c -o special_name
|
||||
|
||||
or rm -f special_build
|
||||
tail +4 build > special_build
|
||||
sh < special_build
|
||||
|
||||
* Assume that we will use the entry title. Send us a version of
|
||||
your build/program files that uses the name convention. You
|
||||
should uuencode these files in ---info--- sections.
|
||||
|
||||
If your entry needs to modify its source, info or binary files,
|
||||
please say so in the ---remark--- section. You should try to avoid
|
||||
touching your original build, source and binary files. You should
|
||||
arrange to make copies of the files you intend to modify. This
|
||||
will allow people to re-generate your entry from scratch.
|
||||
|
||||
Remember that your entry may be built without a build file. We
|
||||
typically incorporate the build lines into a Makefile. If the
|
||||
build file must exist, say so in the ---remark--- section.
|
||||
|
||||
Typically the ---build--- command will contain a "cc" command.
|
||||
It is also ok to use a "gcc" command (and gcc args). However keep
|
||||
in mind that your entry should be compilable by any standard ANSI C
|
||||
compiler and thus should not depend on a special gcc feature.
|
||||
|
||||
If your entry needs special info files, you should uuencode them
|
||||
into ---info--- sections. In the case of multiple info files,
|
||||
use multiple ---info--- sections. If no info files are needed,
|
||||
then skip the ---info--- section.
|
||||
|
||||
Info files are intended to be input, or detailed information that
|
||||
does not fit well into the ---remark--- section. For example, an
|
||||
entry that implements a compiler might want to provide some sample
|
||||
programs for the user to compile. An entry might want to include a
|
||||
lengthy design document, that might not be appropriate for a
|
||||
'hints' file.
|
||||
|
||||
Info files should be used only to supplement your entry. For
|
||||
example, info files may provide sample input or detailed
|
||||
information about your entry. Because they are supplemental,
|
||||
the entry should not require them exist.
|
||||
|
||||
In some cases, your info files might be renamed to avoid name
|
||||
conflicts. If info files should not be renamed for some reason,
|
||||
say so in the ---remark--- section.
|
||||
|
||||
Info files must uudecode into the current directory. If they
|
||||
absolutely must be renamed, or moved into a sub-directory, say
|
||||
so in the ---remark--- section.
|
||||
|
||||
When submitting multiple entries, be sure that each entry has
|
||||
a unique entry number from 0 to 7. Your first entry should
|
||||
have entry number 0.
|
||||
|
||||
With the exception of the header, all text outside of the entry
|
||||
format may be ignored. That is, don't place text outside of the
|
||||
entry and expect us to see it. (Our decoding tools are not AI
|
||||
progs!) If you need tell the judges something, put it in the
|
||||
---remark--- section, or send a EMail to:
|
||||
|
||||
questions@ioccc.org (not the address for submitting entries)
|
||||
|
|
||||
You must include the words 'ioccc question' in the subject of your |
|
||||
EMail message when sending EMail to the judges. |
|
||||
|
||||
The date should be given with respect to UTC. (Some systems refer
|
||||
to this as GMT or GMT0) The format of the date should be that as
|
||||
returned by asctime() in the C locale. An example of such a string is:
|
||||
|
||||
Wed Feb 2 00:47:00 2001
|
||||
|
||||
This format is similar to the output of the date(1) command. The
|
||||
string does not include the timezone name before the year. On many
|
||||
systems, one of the following command will produce a similar string:
|
||||
|
||||
date -u "+%a %h %d %T 20%y"
|
||||
date -u sed -e 's/... \(20[0-9][0-9]\)$/\1/'
|
||||
sh -c 'TZ=UTC date sed -e "s/... \(20[0-9][0-9]\)$/\1/"'
|
||||
sh -c 'TZ=GMT date sed -e "s/... \(20[0-9][0-9]\)$/\1/"'
|
||||
sh -c 'TZ=GMT0 date sed -e "s/... \(20[0-9][0-9]\)$/\1/"'
|
||||
|
||||
You are allowed to update/fix/revise your entry. To do so, set
|
||||
the 'fix' line in the ---entry--- section to 'y' instead of 'n'.
|
||||
Be sure that the resubmission uses the same title and entry number
|
||||
as well, as these are used to determine which entry is to be
|
||||
replaced.
|
||||
|
||||
Again, you may want to use the mkentry program may be found at: |
|
||||
|
|
||||
http://www.ioccc.org/official/mkentry.c |
|
||||
|
|
||||
to format your entry. |
|
||||
|
||||
|
|
||||
JUDGING PROCESS:
|
||||
|
||||
Entries are judged by Leonid A. Broukhis, Simon Cooper, Landon Curt Noll
|
||||
and Peter Seebach.
|
||||
|
||||
Entries are unpacked into individual directories. The EMail message
|
||||
is unpacked into individual files, each containing:
|
||||
|
||||
---entry--- section
|
||||
all ---author--- sections
|
||||
all ---info--- sections
|
||||
---build--- section
|
||||
---program--- section
|
||||
any other text, including the EMail message headers
|
||||
|
||||
Prior to judging, the 'any other text' file is scanned to be sure
|
||||
it does not contain useful information (or in case the entry was
|
||||
malformed and did not unpack correctly). Information from the
|
||||
---author--- sections and the title from the ---entry--- section
|
||||
are not read until the judging process is complete, and then only
|
||||
from entries that have won an award.
|
||||
|
||||
The above process helps keep us biased for/against any one particular
|
||||
individual. We are usually kept in the dark as much as you are
|
||||
until the final awards are given. We like the surprise of finding
|
||||
out in the end, who won and where they were from.
|
||||
|
||||
We attempt to keep all entries anonymous, unless they win an award.
|
||||
Because the main 'prize' of winning is being announced, we make all
|
||||
attempts to send non-winners into oblivion. We remove all non-winning
|
||||
files, and shred all related paper. By tradition, we do not even
|
||||
reveal the number of entries that we received. (For the curious,
|
||||
we do indicate the volume of paper consumed when presenting the IOCCC
|
||||
winners at talks)
|
||||
|
||||
After the initial announcement, we attempt to send EMail to the
|
||||
authors of the winning entries. One reason we do this is to give
|
||||
the authors a chance to comment on the way we have presented their
|
||||
entry. They are given the chance to correct mistakes and typos. We
|
||||
often accept their suggestions/comments about our remarks as well.
|
||||
This is done prior to posting the winners to the wide world.
|
||||
|
||||
Judging consists of a number of elimination rounds. During a round,
|
||||
the collection of entries are divided into two roughly equal piles;
|
||||
the pile that advances on to the next round, and the pile that does
|
||||
not. We also re-examine the entries that were eliminated in the
|
||||
previous round. Thus, an entry gets at least two readings.
|
||||
|
||||
A reading consists of a number of actions:
|
||||
|
||||
* reading the ---entry--- section
|
||||
* reading the uudecoded ---build--- section
|
||||
* reading the uudecoded ---program--- section
|
||||
* reading the uudecoded ---info--- section(s), if any
|
||||
* passing the source thru the C pre-processor
|
||||
skipping over any #include files
|
||||
* performing a number of C beautify/cleanup edits on the source
|
||||
* passing the beautified source thru the C pre-processor
|
||||
skipping over any #include files
|
||||
|
||||
In later rounds, other actions are performed:
|
||||
|
||||
* compiling/building the source
|
||||
* running the program
|
||||
* performing miscellaneous tests on the source and binary
|
||||
|
||||
Until we reduce the stack of entries down to about 25 entries, entries
|
||||
are judged on an individual basis. An entry is set aside because it
|
||||
does not, in our opinion, meet the standard established by the round.
|
||||
When the number of entries thins to about 25 entries, we begin to form
|
||||
award categories. Entries begin to compete with each other for awards.
|
||||
An entry often will compete in several categories.
|
||||
|
||||
The actual award category list will vary depending on the types of entries
|
||||
we receive. A typical category list might be:
|
||||
|
||||
* best small one line program
|
||||
* best small program
|
||||
* strangest/most creative source layout
|
||||
* most useful obfuscated program
|
||||
* best game that is obfuscated
|
||||
* most creatively obfuscated program
|
||||
* most deceptive C code
|
||||
* best X client (see OUR LIKES AND DISLIKES)
|
||||
* best abuse of ANSI C
|
||||
* worst abuse of the rules
|
||||
* (anything else so strange that it deserves an award)
|
||||
|
||||
We do not limit ourselves to this list. For example, a few entries are so
|
||||
good/bad that they are declared winners at the start of the final round.
|
||||
We will invent awards categories for them, if necessary.
|
||||
|
||||
In the final round process, we perform the difficult tasks of
|
||||
reducing the remaining entries (typically about 25) down to 8 or 10
|
||||
winners. Often we are confident that the entries that make it into
|
||||
the final round are definitely better than the ones that do not
|
||||
make it. The selection of the winners out of the final round, is
|
||||
less clear cut.
|
||||
|
||||
Sometimes a final round entry os good enough to win, but is beat out
|
||||
by a similar, but slightly better entry. For this reason, it is
|
||||
sometimes worthwhile to re-enter an improved version of an entry
|
||||
that failed to win in a previous year. This assumes, of course,
|
||||
that the entry is worth improving in the first place!
|
||||
|
||||
More often than not, we select a small entry (usually one line), a
|
||||
strange/creative layout entry, and an entry that abuses the contest
|
||||
rules in some way.
|
||||
|
||||
In the end, we traditionally pick one entry as 'best'. Sometimes such
|
||||
an entry simply far exceeds any of the other entries. More often, the
|
||||
'best' is picked because it does well in a number of categories.
|
||||
|
||||
|
||||
ANNOUNCEMENT OF WINNERS:
|
||||
|
||||
In Jan or Feb 2002 the judges will post an initial announcement of who |
|
||||
won, the name of their award, and a very brief description of the |
|
||||
winning entry on the IOCCC web site: |
|
||||
|
|
||||
http://www.ioccc.org/whowon.html |
|
||||
|
|
||||
We will also submit a brief announcement story to /.: |
|
||||
|
|
||||
http://www.slashdot.org |
|
||||
|
|
||||
that, depending on the willingness of the /. editors, may be posted |
|
||||
to their site at the same time. |
|
||||
|
|
||||
Note that initial announcement will NOT contain source. This is because |
|
||||
the winning authors are given a chance to review the judges comments, |
|
||||
and test our Makefile. This review process typically takes a few weeks. |
|
||||
|
|
||||
Sometime after the initial announcement, and once the the review by |
|
||||
the winners has been completed (perhaps Feb or Mar 2002), the winning |
|
||||
source will be posted to the IOCCC web site: |
|
||||
|
|
||||
http://www.ioccc.org/years.html |
|
||||
|
|
||||
NOTE: previous winners are available at that URL |
|
||||
|
|
||||
We will submit a story announcing the availability of the winners |
|
||||
to /. at the same time. |
|
||||
|
||||
Finally (again perhaps Feb or Mar 2002) the winning entries will be |
|
||||
posted to the following groups: |
|
||||
|
||||
comp.lang.c comp.lang.c.moderated alt.sources
|
||||
|
||||
In addition, pointers to these postings are posted to the following
|
||||
|
||||
comp.sources.misc comp.windows.x comp.programming
|
||||
misc.misc comp.std.c alt.folklore.computers
|
||||
|
||||
Often, winning entries are published in selected magazines from around
|
||||
the world. Winners have appeared in books ("The New Hackers Dictionary")
|
||||
and on T-Shirts.
|
||||
|
||||
Last, but not least, winners receive international fame and flames! :-)
|
||||
|
||||
|
||||
FOR MORE INFORMATION:
|
||||
|
||||
You may contact the judges by sending EMail to the following address:
|
||||
|
||||
questions@ioccc.org (not the address for submitting entries)
|
||||
|
||||
You must include the words 'ioccc question' in the subject of your |
|
||||
EMail message when sending EMail to the judges. |
|
||||
|
|
||||
Questions and comments about the contest are welcome. Comments about
|
||||
confusing rules and guidelines are also welcome.
|
||||
|
||||
The rules and the guidelines may (and often do) change from year to
|
||||
year. You should be sure you have the current rules and guidelines
|
||||
prior to submitting entries.
|
||||
|
||||
Check out the IOCCC Web page:
|
||||
|
||||
http://www.ioccc.org
|
||||
|
||||
It has rules, guidelines and winners of previous contests (1984 to date).
|
||||
|
||||
Leonid A. Broukhis
|
||||
Simon Cooper
|
||||
chongo (Landon Curt Noll) /\cc/\
|
||||
Peter Seebach
|
||||
@@ -0,0 +1,327 @@
|
||||
#define D define
|
||||
#define U undef
|
||||
#define n #
|
||||
|
||||
|
||||
#undef __FILE__
|
||||
n U __FILE__
|
||||
n D f __FILE__
|
||||
n D N endif
|
||||
n D p e(prg)
|
||||
n D e(x) #x
|
||||
n D q #
|
||||
n D o E #F
|
||||
n D E Q(
|
||||
n D G x,y,z)
|
||||
n D H E y,z)
|
||||
n D F ,)
|
||||
n D g o else
|
||||
n D d o D
|
||||
n D u o U
|
||||
n D w E o F D
|
||||
#ifdef prg
|
||||
|
||||
|
||||
|
||||
#ifndef tape
|
||||
n include p
|
||||
n ifndef tape
|
||||
n D tape O
|
||||
n endif
|
||||
#endif
|
||||
n D O Z(O,
|
||||
n D I Z(I,
|
||||
q D i tape
|
||||
n U O
|
||||
n U I
|
||||
n D O ,)
|
||||
n D I ,)
|
||||
q D v tape
|
||||
n U O
|
||||
n U I
|
||||
#undef tape
|
||||
n U tape
|
||||
q U tape
|
||||
#endif /* tape */
|
||||
|
||||
|
||||
q ifndef P
|
||||
q D H y ## z
|
||||
#ifdef prg
|
||||
d c 0 & 0
|
||||
d R i W v
|
||||
d B Initializing...
|
||||
d L V /* the turing */
|
||||
d M Y(O)/* state to */
|
||||
d S(x) T(O,1, start ##x)
|
||||
#else
|
||||
d c 0
|
||||
#endif
|
||||
q D P P
|
||||
q include f
|
||||
q U Q
|
||||
q D H H
|
||||
q N
|
||||
q U f
|
||||
o ifndef P
|
||||
E # D H y ## z F
|
||||
d O 3
|
||||
d I 3
|
||||
d x 3
|
||||
o if c+2
|
||||
E o F include <stdio.h>
|
||||
|
||||
|
||||
int main() {
|
||||
return 2+c|!
|
||||
printf
|
||||
(
|
||||
d y "\n"
|
||||
d z ".."
|
||||
d j " "
|
||||
d P "*"
|
||||
d k " "
|
||||
o if c
|
||||
w Y(Z) #Z
|
||||
"Un"
|
||||
"define"
|
||||
"d state "
|
||||
Y(B) y y
|
||||
"Tape:"
|
||||
o elif !c
|
||||
"Usage:"
|
||||
d M 0
|
||||
" prg=myprg.turing "
|
||||
d L ,
|
||||
d R ,
|
||||
"["
|
||||
"tape="
|
||||
"\""
|
||||
"O I O..."
|
||||
"\""
|
||||
"]"
|
||||
g
|
||||
"Final "
|
||||
"tape:"
|
||||
o N
|
||||
u O
|
||||
u I
|
||||
d O "O"
|
||||
d I "I"
|
||||
g
|
||||
d j _
|
||||
d z ...
|
||||
d k ~
|
||||
|
||||
/*StarBox*/
|
||||
/*********/
|
||||
d P *
|
||||
d y *
|
||||
E E /,*) F
|
||||
*
|
||||
* State: B
|
||||
/*********/
|
||||
|
||||
u O
|
||||
u I
|
||||
o N
|
||||
u x
|
||||
u a
|
||||
u c
|
||||
u B
|
||||
o ifdef s
|
||||
d J s
|
||||
d A l
|
||||
d B m
|
||||
d C r
|
||||
d t K
|
||||
d a L
|
||||
d b M
|
||||
d c R
|
||||
g
|
||||
d J S
|
||||
d A L
|
||||
d B M
|
||||
d C R
|
||||
d T K
|
||||
d a l
|
||||
d b m
|
||||
d c r
|
||||
o N
|
||||
y
|
||||
|
||||
|
||||
/*Triangles*/
|
||||
d V j j j j
|
||||
d W j j j j
|
||||
d X(G y j
|
||||
d Z(G j y
|
||||
d Y(x) P
|
||||
y A B C
|
||||
u X
|
||||
u Y
|
||||
u Z
|
||||
u V
|
||||
u W
|
||||
|
||||
d X(G y x
|
||||
d Z(G x y
|
||||
d V z O O
|
||||
d W O O z
|
||||
d Y(x) x
|
||||
y A B C
|
||||
u X
|
||||
u Y
|
||||
u Z
|
||||
u V
|
||||
u W
|
||||
|
||||
d V k k k k
|
||||
d W k k k k
|
||||
d X(G y k
|
||||
d Z(G k y
|
||||
d Y(x) P
|
||||
y A B C
|
||||
u X
|
||||
u Y
|
||||
u Z
|
||||
u V
|
||||
u W
|
||||
y
|
||||
u j
|
||||
u k
|
||||
u z
|
||||
u P
|
||||
u y
|
||||
u O
|
||||
/*EndOfTriang*/
|
||||
|
||||
|
||||
/* Rain */
|
||||
o ifndef I /*/*/ /*/*/
|
||||
/*/*/*/*/*/ /*/*/
|
||||
E E /*/*/*/*/*/,/) F
|
||||
d K(G /*/*/ y
|
||||
o if J(x)
|
||||
u K
|
||||
d K(G x
|
||||
w a X(J(x),A F
|
||||
u K
|
||||
d Z(G x
|
||||
d W O
|
||||
w b Y(C)
|
||||
d P C
|
||||
u Z
|
||||
o U W
|
||||
|
||||
|
||||
d Z(G z ## y
|
||||
w c C
|
||||
u Z
|
||||
g /* <- exit */
|
||||
u K
|
||||
d X(G z ## y
|
||||
|
||||
|
||||
w a A
|
||||
u X
|
||||
d X(G x
|
||||
d V O
|
||||
w b Y(A)
|
||||
d P A
|
||||
u X
|
||||
u V
|
||||
d K(G x
|
||||
w c Z(J(x),C F
|
||||
u K
|
||||
o N
|
||||
u a
|
||||
u b
|
||||
o U c
|
||||
|
||||
|
||||
d X(G J(_ ## x)
|
||||
d V J(_O)
|
||||
d Z(G J(_ ## x)
|
||||
d W J(_O)
|
||||
d Y(x) J(_ ## x)
|
||||
|
||||
|
||||
o ifdef s
|
||||
u t
|
||||
d t(G z
|
||||
d j S(x)
|
||||
d k T
|
||||
|
||||
g
|
||||
u T
|
||||
d T(G z
|
||||
d j s(x)
|
||||
d k t
|
||||
o N
|
||||
u tape
|
||||
o include p
|
||||
u tape
|
||||
d stop_O x
|
||||
d stop_I x
|
||||
w a(P) O&I&x
|
||||
|
||||
|
||||
d O 0
|
||||
d I 0
|
||||
d x 0
|
||||
w c a(P)
|
||||
u O
|
||||
u I
|
||||
u x
|
||||
d left 0
|
||||
d right 1
|
||||
w j k(P ## x)
|
||||
u P
|
||||
u left
|
||||
u right
|
||||
u stop_O
|
||||
u stop_I
|
||||
|
||||
|
||||
u Y
|
||||
o U X
|
||||
u V
|
||||
u Z
|
||||
o U W
|
||||
u A
|
||||
u B
|
||||
o U C
|
||||
u j
|
||||
u k
|
||||
w B J (.)
|
||||
u J
|
||||
u t
|
||||
o U T
|
||||
|
||||
|
||||
/*Codeblk*/
|
||||
o D P P
|
||||
o include f
|
||||
E n U Q F
|
||||
E n D H H F
|
||||
|
||||
|
||||
g
|
||||
);
|
||||
}
|
||||
w P x
|
||||
o N
|
||||
o N
|
||||
o U f
|
||||
u l
|
||||
u L
|
||||
o U m
|
||||
u M
|
||||
u r
|
||||
o U R
|
||||
u S
|
||||
u s
|
||||
o U B
|
||||
u a
|
||||
u c
|
||||
@@ -0,0 +1,46 @@
|
||||
/* Calculates the greatest common divisor of two numbers in
|
||||
unary representation. Default tape: gcd(6, 10) = 2. */
|
||||
|
||||
|
||||
|
||||
#define tape I I I I I I O I I I I I I I I I I
|
||||
|
||||
#define start_O O, right, start
|
||||
#define start_I I, left , st10
|
||||
/* st1_O may not happen */
|
||||
#define st1_I O, right, st2
|
||||
#define st2_O O, right, st11
|
||||
#define st2_I I, right, st3
|
||||
#define st3_O O, right, st4
|
||||
#define st3_I I, right, st3
|
||||
#define st4_O O, right, st4
|
||||
#define st4_I I, right, st5
|
||||
#define st5_O I, left , st6
|
||||
#define st5_I I, right, st5
|
||||
/* st6_O may not happen */
|
||||
#define st6_I O, left , st7
|
||||
#define st7_O O, right, st13
|
||||
#define st7_I I, left , st8
|
||||
#define st8_O O, left , st9
|
||||
#define st8_I I, left , st8
|
||||
#define st9_O O, left , st9
|
||||
#define st9_I I, left , st10
|
||||
#define st10_O I, right, st1
|
||||
#define st10_I I, left , st10
|
||||
#define st11_O O, right, st11
|
||||
#define st11_I O, right, st12
|
||||
#define st12_O O, right, st16
|
||||
#define st12_I I, right, st13
|
||||
#define st13_O O, right, st14
|
||||
#define st13_I I, right, st13
|
||||
#define st14_O O, left , st_next_iteration
|
||||
#define st14_I O, right, st14
|
||||
/* The state "st_next_iteration" means the the turing machine
|
||||
is about to do the next iteration of the Euklid algorithm.
|
||||
(That is, during that state, there are two numbers on the
|
||||
tape with the same gcd as the initial numbers.) */
|
||||
#define st_next_iteration_O O, left , st_next_iteration
|
||||
#define st_next_iteration_I I, left , st8
|
||||
#define st16_O O, right, stop
|
||||
#define st16_I O, right, st16
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
Best abuse of the C preprocessor:
|
||||
|
||||
Immanuel Herrmann
|
||||
University of Freiburg, Germany
|
||||
Rehlingstr. 17
|
||||
79100 Freiburg
|
||||
Germany
|
||||
|
||||
http://pcpool.mathematik.uni-freiburg.de/~immi/
|
||||
|
||||
|
||||
Judges' Comments:
|
||||
|
||||
To build:
|
||||
|
||||
Running and building are combined for this entry.
|
||||
|
||||
Try:
|
||||
./herrmann1.sh 'prg=herrmann1.times2'
|
||||
-or-
|
||||
./herrmann1.sh 'prg=herrmann1.gcd'
|
||||
|
||||
There are some clear hints in the source code as to the
|
||||
purpose of this program. Perhaps the only way to figure out what is
|
||||
going on is to look at the differences between the runs of the C
|
||||
preprocessor! Computer Science students should recognize what is going
|
||||
on.
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
Many cool things have been done with the preprocessor,
|
||||
e. g. calculation of prime numbers or the tower of Hanoi. However,
|
||||
up to now, no one proved that the preprocessor is Turing complete,
|
||||
and I wondered why. Well, the answer is simply that the
|
||||
preprocessor is _not_ Turing complete, at least not if the program
|
||||
is preprocessed only once. This is true even if the program is
|
||||
allowed to include itself. (The reason being that for a given
|
||||
program, the preprocessor has only a finite number of states, plus
|
||||
a stack consisting of the places which the file has been included
|
||||
from. This is only a push-down automaton.)
|
||||
|
||||
Well, this entry _is_ a Turing machine implemented in the
|
||||
preprocessor; so of course, it has to be preprocessed several
|
||||
times. Here are the main features:
|
||||
|
||||
- Easy to program: Write your own Turing programs in a nice
|
||||
syntax.
|
||||
|
||||
- Easy to debug: (some) errors in the Turing machine program will
|
||||
be reported nicely. (That's something which is not often seen in
|
||||
IOCCC programs.)
|
||||
|
||||
- Ultra-fast: The resulting C program will print the output in
|
||||
time O(n), where n is the length of the output. This means for
|
||||
example that you can solve NP hard problems in polynomial time!
|
||||
;-)
|
||||
|
||||
- And best of all: During the preprocessing, watch the animated
|
||||
Turing machine running over the tape and doing its work in your
|
||||
terminal!
|
||||
|
||||
|
||||
|
||||
How to use it
|
||||
=============
|
||||
|
||||
For the impatient
|
||||
-----------------
|
||||
|
||||
The info files "herrmann1.turing" and "herrmann1.gcd" are sample
|
||||
programs for the Turing machine. For example, type
|
||||
|
||||
./herrmann1.sh 'prg=herrmann1.times2'
|
||||
|
||||
and watch the animated Turing machine multiply 8 by two (in
|
||||
unary representation). Here's a screen shot during compilation:
|
||||
|
||||
/*
|
||||
*
|
||||
* State: st2.
|
||||
*
|
||||
* _ _ _ _ _ * _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
* ... O O I I I I I O I I I I I O O ...
|
||||
* ~ ~ ~ ~ ~ * ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
(As on real videos, you'll see a bit of "white noise" at the
|
||||
beginning and at the end.;-) After compilation has terminated,
|
||||
type ./prog to see the final result. The output will be
|
||||
|
||||
Final tape:
|
||||
|
||||
*
|
||||
..OOIIIIIIIIIIIIIIIIOOOO..
|
||||
*
|
||||
|
||||
(Note that the last frame of the animation is _not_ the final
|
||||
result.)
|
||||
|
||||
|
||||
In the previous example, the Turing machine started on the default
|
||||
tape of the program "times2.turing". To provide your own tape, type
|
||||
(for example)
|
||||
|
||||
./build prg=times2.turing tape="O O O I I I O O O"
|
||||
|
||||
(The O's and I's are letters, not digits.) You might prefer to
|
||||
provide only a finite portion of the tape, like I did above. In
|
||||
this case, the remainder of the tape is filled with O's. ;-)
|
||||
|
||||
If you just type
|
||||
./build
|
||||
and run the program, you'll get a usage message (and the return
|
||||
code will be 2).
|
||||
|
||||
Note: To get a really nice animation, you'll need a terminal which
|
||||
is able to scroll fast enough. (xterm is not very good. The
|
||||
kde terminal "konsole" or the text console under linux are much
|
||||
better. Simply try some out.)
|
||||
|
||||
|
||||
|
||||
Writing your own programs
|
||||
-------------------------
|
||||
|
||||
Now, let's assume you want to write a program which adds 1 to a
|
||||
number in unary representation. (That is, a row of I's is
|
||||
expected, and one more I is appended to the row.) Let's call it
|
||||
"plus1.turing". Here's what it could look like:
|
||||
|
||||
/* Search beginning of number. */
|
||||
#define start_O O, right, start
|
||||
/* Number found. Move one step to the left. */
|
||||
#define start_I I, left, st2
|
||||
/* Write a I and stop */
|
||||
#define st2_O I, left, stop
|
||||
|
||||
Some explanations:
|
||||
- The tape alphabet is always O and I.
|
||||
- The states can be anything starting with "st". "start" and
|
||||
"stop" are the start and stop states, respectively.
|
||||
- to define a state, use two lines: one for each letter on the
|
||||
tape. You may omit one of the lines if the Turing machine will
|
||||
never enter the state reading that letter. (In the example, the
|
||||
line defining st2_I has been left out.)
|
||||
- The order of the lines is irrelevant.
|
||||
- You may use c-style comments. (Would you have guessed it?)
|
||||
|
||||
Now, the program can be used with
|
||||
|
||||
./herrmann1.sh 'prg=plus1.turing' 'tape="I I I"'
|
||||
|
||||
But what happens if no tape is provided? Up to now, the Turing
|
||||
machine would start on an empty tape (that is, a tape filled with
|
||||
O's). For many programs, this doesn't make much sense (as is
|
||||
the case for "plus1.turing"). So you might want to provide a
|
||||
default tape by adding a line like
|
||||
|
||||
#define tape O O O O O I I I I
|
||||
|
||||
to your program.
|
||||
|
||||
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
When writing long programs, the most common errors are to forget
|
||||
to define a state or to misspell one. Let's assume you forgot the
|
||||
line
|
||||
|
||||
#define start_I I, left, st2
|
||||
|
||||
Remove it and type
|
||||
|
||||
./herrmann1 'prg=plus1.turing'
|
||||
|
||||
The output will be
|
||||
|
||||
Undefined state start.
|
||||
|
||||
Tape:
|
||||
|
||||
*
|
||||
..OOOOOOOOIIIIOO..
|
||||
*
|
||||
|
||||
and the return code will be 1. As you can see, the Turing machine
|
||||
moved over the O's, but when it arrived at the I (still in state
|
||||
start), the error occurred.
|
||||
|
||||
Note that other kinds of errors can cause compilation to fail.
|
||||
If this happens, the build script will write the error message of
|
||||
gcc into a file called "error" and then exit.
|
||||
|
||||
|
||||
|
||||
|
||||
What the build script does
|
||||
==========================
|
||||
|
||||
In principle, the build script simply runs the preprocessor over
|
||||
and over again, until nothing changes anymore; then, the program
|
||||
is compiled. After each preprocessing step, the script outputs the
|
||||
beginning of the program; this is where the animation takes place
|
||||
(except in the first and last few steps).
|
||||
|
||||
However, there's a technical problem to overcome: Some compilers
|
||||
(including gcc) insert a lot of white space during the
|
||||
preprocessing. This is bad for two reasons. First, the animated
|
||||
picture won't look right. And second, after some time, the file
|
||||
will grow too big for your hard disk. (The amount of white space
|
||||
grows exponentially.) So after each preprocessing, the first thing
|
||||
the build script does is remove all the unnecessary white space
|
||||
using sed.
|
||||
|
||||
(gcc would even insert #line directives if I didn't suppress
|
||||
them with the -P option.)
|
||||
|
||||
|
||||
Some more details
|
||||
-----------------
|
||||
|
||||
- The arguments passed to the build script are passed on to gcc
|
||||
with a "-D" before. I had a slight technical problem doing this
|
||||
(especially with the spaces that can appear within the tape
|
||||
argument). That made the build script a bit longer.
|
||||
|
||||
- It would be enough to pass the defines in the first
|
||||
preprocessing. The program then "remembers" them. However, it
|
||||
doesn't matter if they are passed in all preprocessings. (This
|
||||
doesn't sound very impressive, but it has required some extra
|
||||
lines of code.)
|
||||
|
||||
- During the preprocessing, intermediate files "herrmann1-1.c" and
|
||||
"herrmann1-2.c" are generated.
|
||||
|
||||
- Also, a file "error" is generated. This file is removed after
|
||||
the compilation, except if gcc produced an error; then it contains
|
||||
the error message. (I can't let gcc output all its messages
|
||||
directly, because the warnings would clobber the animation. I
|
||||
could have made the compile script output the error file in case
|
||||
of an error, but I didn't want to make it yet longer.)
|
||||
|
||||
|
||||
|
||||
|
||||
Some technical details / obfuscations
|
||||
====================================
|
||||
|
||||
- The program is compressed. In the first three preprocessing
|
||||
passes, it uncompresses itself and initializes the
|
||||
"variables". So if you want to understand how it works, the best
|
||||
thing is to preprocess it three times and then look at it
|
||||
again. (However, I wouldn't have wasted three passes if they
|
||||
weren't needed anyway to initialize the tape in certain
|
||||
cases. Find out why.)
|
||||
|
||||
- The first problem I had to solve when writing this program was
|
||||
to write a preprocessor program which outputs itself. Of course,
|
||||
each program which doesn't contain any preprocessor directives
|
||||
is such a program, but that's not what I needed. In fact, to do
|
||||
this, the program has to include itself, but even then, it's not
|
||||
easy.
|
||||
|
||||
- The next problem to solve was how to pass results of a
|
||||
calculation of one preprocessing to the next one. This is done
|
||||
by outputting #defines with the result. But there's a problem
|
||||
with this: it is impossible to output a "#define result xxx",
|
||||
where xxx depends on the previous value of result. Try it if you
|
||||
don't believe it. And find out what I did instead.
|
||||
|
||||
- What's a useful way to store information, especially the content
|
||||
of the tape? Of course, a "#define tape OOIOOIOIIIIO" contains
|
||||
the information, but then, how do you access the information?
|
||||
(For example, you won't be able to write preprocessor code which
|
||||
replaces the first O by I.) My answer looks very much like the
|
||||
way a stack would have been implemented in lambda calculus. (The
|
||||
tape is implemented as two stacks, to be exact.) And still,
|
||||
there were some technical problems to solve. Look at the program
|
||||
for more details.
|
||||
|
||||
- There are many other interesting things to look at, e.g. the way
|
||||
to access the information in the user-provided program, the way
|
||||
a non-defined state is detected, the way the picture is
|
||||
produced, etc. If you want a real challenge, try to understand
|
||||
what the line "w j k(P ## x)" does.
|
||||
|
||||
- Due to the fact that our alphabet has only 53 ;-) letters, I had
|
||||
to use many variables more than once.
|
||||
|
||||
- I couldn't refrain from doing a little bit of nasty stuff like
|
||||
|
||||
#define a 0&0
|
||||
#if !a
|
||||
|
||||
Of course, it is a bit more subtle, and even useful.
|
||||
|
||||
- The layout of the source code..., well, let's call it the
|
||||
"modern art of programming" - a mixture of program-like
|
||||
indenting and modern art. There are even some comments...
|
||||
|
||||
|
||||
|
||||
|
||||
Compatibility
|
||||
=============
|
||||
|
||||
- It works with many versions of gcc. I tested it with versions
|
||||
2.7.2.1, 2.8.1, 2.95.2, and ecgs-2.91.66. However, an old version
|
||||
of gcc produced "internal compiler errors" (obviously not my
|
||||
fault).
|
||||
|
||||
- The only warnings I get tell me that I'm undefining __FILE__ and
|
||||
that preprocessing directives are not recognized within macro
|
||||
args. My answer to this is "yes, I know this and it's all
|
||||
right". With "-Wall", I also get some warnings about "/*"
|
||||
inside comments (Well, _I_ like some well-placed "/*/*/".) as
|
||||
well as some suggestions where to place some more parentheses
|
||||
(as if I didn't know the operator precedence).
|
||||
|
||||
- Different versions of cc all produced only rubbish. Apparently,
|
||||
the preprocessors didn't really work. (I don't feel guilty
|
||||
there, either. Even with very simple programs, they produced
|
||||
mysterious output.)
|
||||
|
||||
- For Mac-Users: It works with the C compiler of Codewarrior (an
|
||||
old version). This compiler even leaves out all that unnecessary
|
||||
white space, so that no clean-up is needed. (It would be useful
|
||||
to write a kind of script which does the equivalent to the build
|
||||
script, so that one does not have to choose "preprocess" from
|
||||
the menu over and over again. I leave this as an exercise to the
|
||||
experienced Mac programmer.)
|
||||
|
||||
- In the build script, I passed the -P option to gcc to suppress
|
||||
the insertion of #line directives. If your compiler doesn't
|
||||
support this option (and does insert #line directives), you
|
||||
should change the call to sed to remove them, too: Add
|
||||
|
||||
-e "/^#line/ d"
|
||||
|
||||
to the sed parameters. Or, if your #line directives look like
|
||||
|
||||
# 15 "filename"
|
||||
|
||||
add
|
||||
|
||||
-e "/^# [0-9]/ d"
|
||||
|
||||
instead.
|
||||
|
||||
- First, I had "-ansi -pedantic" turned on, but on some systems,
|
||||
the stdio.h is not compatible to that, so I turned it back off.
|
||||
|
||||
- The build script probably needs a bash to run in. So perhaps you
|
||||
have to add "#!/bin/bash" or something like this at the
|
||||
beginning.
|
||||
|
||||
- On SunOS, I had to remove the "-q" option from diff in the build
|
||||
script.
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
name=herrmann1
|
||||
|
||||
# Make sure things are clean to start with...
|
||||
rm -f ${name} ${name}-1.c ${name}-2.c ${name}-3.c
|
||||
|
||||
defs=""
|
||||
for p in ${1+"$@"}; do
|
||||
defs="$defs \"-D$p\""
|
||||
done
|
||||
|
||||
cp ${name}.c ${name}-1.c
|
||||
touch ${name}-3.c
|
||||
|
||||
until cmp -s ${name}-1.c ${name}-3.c > /dev/null; do
|
||||
eval ${CC:-cc} -E ${name}-1.c -o ${name}-2.c -P $defs 2> error || exit
|
||||
mv -f ${name}-1.c ${name}-3.c
|
||||
sed -e 's/ */ /g' -e 's/^ //' -e '/^$/ d' -e 's:^/ \*:/*:' \
|
||||
< ${name}-2.c > ${name}-1.c
|
||||
head ${name}-1.c
|
||||
done
|
||||
|
||||
eval ${CC:-cc} ${name}-1.c -o ${name} 2> error && rm error
|
||||
|
||||
eval ./${name}
|
||||
|
||||
# Clean up intermediates...
|
||||
rm -f ${name}-1.c ${name}-2.c ${name}-3.c
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
/* Takes a number in unary representation and
|
||||
multiplies it by two
|
||||
*/
|
||||
|
||||
/* Default Tape: Multiply 8 by 2 */
|
||||
#define tape I I I I I I I I
|
||||
|
||||
|
||||
#define start_O O, right, start
|
||||
#define start_I O, left, st1
|
||||
#define st1_O I, left, st2
|
||||
#define st2_I I, left, st2
|
||||
#define st2_O I, right, st3
|
||||
#define st3_I I, right, st3
|
||||
#define st3_O O, right, st4
|
||||
#define st4_O O, left, stop
|
||||
#define st4_I O, left, st1
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
char*d,A[9876];char*d,A[9876];char*d,A[9876];char*d,A[9876];char*d,A[9876];char
|
||||
e;b;*ad,a,c; te;b;*ad,a,c; te;*ad,a,c; w,te;*ad,a, w,te;*ad,and, w,te;*ad,
|
||||
r,T; wri; ;*h; r,T; wri; ;*h; r; wri; ;*h;_, r; wri;*h;_, r; wri;*har;_, r; wri
|
||||
;on; ;l ;i(V) ;on; ;l ;i(V) ;o ;l ;mai(V) ;o ;mai(n,V) ;main (n,V)
|
||||
{-!har ; {-!har ; {har =A; {h =A;ad =A;read
|
||||
(0,&e,o||n -- +(0,&e,o||n -- +(0,&o||n ,o-- +(0,&on ,o-4,- +(0,n ,o-=94,- +(0,n
|
||||
,l=b=8,!( te-*A,l=b=8,!( te-*A,l=b,!( time-*A,l=b, time)|-*A,l= time(0)|-*A,l=
|
||||
~l),srand (l),~l),srand (l),~l),and ,!(l),~l),a ,!(A,l),~l) ,!(d=A,l),~l)
|
||||
,b))&&+((A + te,b))&&+((A + te,b))+((A -A+ te,b))+A -A+ (&te,b+A -A+(* (&te,b+A
|
||||
)=+ +95>e?(*& c)=+ +95>e?(*& c) +95>e?(*& _*c) +95>(*& _*c) +95>(*&r= _*c) +95>
|
||||
5,r+e-r +_:2-195,r+e-r +_:2-195+e-r +_:2-1<-95+e-r +_-1<-95+e-r ++?_-1<-95+e-r
|
||||
|(d==d),!n ?*d||(d==d),!n ?*d||(d==d),!n ?*d||(d==d),!n ?*d||(d==d),!n ?*d||(d=
|
||||
*( (char**)+V+ *( (char)+V+ *( (c),har)+V+ (c),har)+ (V+ (c),r)+ (V+ ( c),
|
||||
+0,*d-7 ) -r+8)+0,*d-7 -r+8)+0,*d-c:7 -r+80,*d-c:7 -r+7:80,*d-7 -r+7:80,*d++-7
|
||||
+7+! r: and%9- +7+! rand%9-85 +7+! rand%95 +7+!! rand%95 +7+ rand()%95 +7+ r
|
||||
-(r+o):(+w,_+ A-(r+o)+w,_+*( A-(r+o)+w,_+ A-(r=e+o)+w,_+ A-(r+o)+wri,_+ A-(r+o)
|
||||
+(o)+b)),!write+(o)+b,!wri,(te+(o)+b,!write+(o=_)+b,!write+(o)+b,!((write+(o)+b
|
||||
-b+*h)(1,A+b,!!-b+*h),A+b,((!!-b+*h),A+b,!!-b+((*h),A+b,!!-b+*h),A-++b,!!-b+*h)
|
||||
, a >T^l,( o-95, a >T,( o-=+95, a >T,( o-95, a)) >T,( o-95, a >T,(w? o-95, a >T
|
||||
++ &&r:b<<2+a ++ &&b<<2+a+w ++ &&b<<2+w ++ ) &&b<<2+w ++ &&b<<((2+w ++ &&
|
||||
!main(n*n,V) , !main(n,V) , !main(+-n,V) ,main(+-n,V) ) ,main(n,V) ) ,main),(n,
|
||||
l)),w= +T-->o +l)),w= +T>o +l)),w=o+ +T>o +l,w=o+ +T>o;{ +l,w=o+T>o;{ +l,w &=o+
|
||||
!a;}return _+= !a;}return _+= !a;}return _+= !a;}return _+= !a;}return _+= !a;}
|
||||
@@ -0,0 +1,38 @@
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppppqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqppppqqqppppqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppqqqqqpppqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppqqqqqpppqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqppqqqppqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppqqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppqqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppppqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppppppppppppppqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppppppppppppppppppppppppppqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqppoooooooooooooooooooooooooooooooooooppqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqpppooooooooooooonnnnnnnooooooooooooopppqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqppooooooooooooonnnnnnnnooooooooooooooppqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqppoooooooooooonnnooooooooooooooooooooppqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqppoooooooooooonnnooooooooooooooooooooppqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqppoooooooooooonnnooooooooooooooooooooppqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqppoooooooooooonnnnnnnnoooooooooooooppqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqppoooooooooooonnnnnnnooooooooooooppqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqppoooooooooooooooooooooooooooppqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqppoooooooooooooooooooooppqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppooooooooooooooopppqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppooooooopppqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppppqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppppppqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppppppqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppppqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppppppppqqqqqqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqoooooooooooooooooooqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqoooooooooooooooooooqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqoooooooooooooooooooqqqqqqqqqqqqqqqqqq
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
@@ -0,0 +1,195 @@
|
||||
Most eye-crossing:
|
||||
|
||||
Immanuel Herrmann
|
||||
University of Freiburg, Germany
|
||||
Rehlingstr. 17
|
||||
79100 Freiburg
|
||||
Germany
|
||||
|
||||
http://pcpool.mathematik.uni-freiburg.de/~immi/
|
||||
|
||||
|
||||
Judges' Comments:
|
||||
|
||||
To build:
|
||||
|
||||
make herrmann2
|
||||
|
||||
Try:
|
||||
|
||||
./herrmann2 < herrmann2.ioccc
|
||||
./herrmann2 < herrmann2.cup
|
||||
|
||||
Be careful when staring at the source code - your eyes might cross, but
|
||||
if you concentrate on your focus you will find illumination!
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
You probably know those "magic eye" 3D pictures - pictures looking
|
||||
like random noise, but when you look "through" the paper, you
|
||||
either get a three dimensional picture or a head-ache. With this
|
||||
program, you can create your own 3D pictures in ascii art. And
|
||||
yes, the program itself is such a 3D picture.
|
||||
|
||||
|
||||
How to use it
|
||||
=============
|
||||
|
||||
1. Create a file which describes the desired 3D picture. The file
|
||||
must be a block of lowercase letters the size of the desired
|
||||
picture. The letters specify the depth of the corresponding pixel:
|
||||
"a" means close to the paper, "z" means far away. The info files
|
||||
are examples. Be aware that the size of the picture is restricted
|
||||
to about 9k.
|
||||
|
||||
2. Pipe your picture into the program. The output will be your
|
||||
3D picture, constructed of random characters (with ascii code between
|
||||
32 and 126). For example, type
|
||||
|
||||
./herrmann2 < herrmann2.ioccc
|
||||
|
||||
|
||||
3. If you want to control the characters used in the output (for
|
||||
example if your picture is to consist only of digits), pass them
|
||||
as the first argument. In this case, each time the program needs a
|
||||
new random character, it will take the next one from the
|
||||
argument. When it arrives at the end of the argument, it will
|
||||
start over at the beginning. Example:
|
||||
|
||||
./herrmann2 "234 84 045 5 6765 7487 65190 84 656 254 12 43931 818 0 6542\
|
||||
341 45 567 76967 7244 606 976567 895 81898 095 68678 1843 4650547\
|
||||
565980691 389 04974" < herrmann2.ioccc
|
||||
|
||||
|
||||
Some hints to get better results
|
||||
--------------------------------
|
||||
|
||||
- Due to the way these 3D pictures work, the left part of the
|
||||
picture won't look really 3D, so don't put things too much on
|
||||
the left. The reason is that for each letter in the source file,
|
||||
a character for the right eye is printed. The 3D effect appears
|
||||
when the left eye sees the same character more to the left. This
|
||||
is of course impossible on the left border of the picture.
|
||||
|
||||
- Don't use too different depths and don't use the depths very
|
||||
close to the paper (beginning of the alphabet). This would make
|
||||
it more difficult to see the picture.
|
||||
|
||||
- When passing an argument, don't use a too short one; the
|
||||
repeating pattern which arises from the repetition of the argument
|
||||
could interfere with the repeating pattern which creates the 3D
|
||||
effect.
|
||||
|
||||
|
||||
Extra-Features
|
||||
==============
|
||||
|
||||
- The program is able to handle all common kinds of line breaks:
|
||||
Unix, Dos and Mac. To get an output with a certain kind of line
|
||||
breaks, simply use the same kind of line breaks in the input
|
||||
file.
|
||||
|
||||
- As the source code is a 3D picture itself, the easiest way to
|
||||
get it (if you lost it or if you don't have it already) is to use
|
||||
the program itself on the right picture and with the right
|
||||
argument:
|
||||
|
||||
./herrmann2 \
|
||||
'char*d,A[9876];e;b;*ad,a,c; tw,ndr,T; wri; ;*h; _,ar ;on;'\
|
||||
' ;l ;i(V)man,n {-!har ; =Aadre(0,&e,o||n -- +,o4,=9,l=b=8,'\
|
||||
'!( te-*Aim)|(0~l),srand (l),,!A,d=,b))&&+((A + te-A(&(*)=+ +95>'\
|
||||
'e?(*& c_*r=5,r+e-r +_:2-19<-+?|(d==d),!n ?*d| *( (char**)+V+), ('\
|
||||
' +0,*d-7 ) -r+8)c:7:+++7+! r: and%9- 85! ()-(r+o):(+w,_+ A*(=er'\
|
||||
'i+(o)+b)),!write,(=_((-b+*h)(1,A+b,!!((((-+, a >T^l,( o-95=+))w?'\
|
||||
'++ &&r:b<<2+a +w) ((!main(n*n,V) , +-) ),l)),w= +T-->o +o+;{ &!'\
|
||||
'a;}return _+= ' < herrmann2.ioccc
|
||||
|
||||
- If I had submitted the program last year, I would have said that
|
||||
it has exactly the maximum allowed length: 1536 characters. Now
|
||||
let's say it's a way of protesting against the inflation in
|
||||
program length.
|
||||
|
||||
- The size of the source 3D picture has been chosen carefully: as
|
||||
big as possible, but small enough to be viewed without problems
|
||||
on normal-sized terminals.
|
||||
|
||||
|
||||
Why this program should win
|
||||
===========================
|
||||
|
||||
- The layout is of a completely new kind. And it describes what
|
||||
the program does more precisely than any comment could.
|
||||
|
||||
- I don't think there has ever been an ioccc program with so
|
||||
severe layout constraints. Once the 3D picture has been fixed,
|
||||
only a sixth of the characters can be chosen freely! (457 of
|
||||
1840, to be exact.) In contrast, in palindrome programs, for
|
||||
example, half of the characters can be chosen freely.
|
||||
|
||||
- I did not cheat by using comments or -D options - something
|
||||
I've seen even some palindrome programs do. In fact, at my first
|
||||
attempt at writing the program I became convinced that it
|
||||
isn't possible without cheating. But then I found out that with
|
||||
comments or defines, it would become trivial, so I had to try
|
||||
harder...
|
||||
|
||||
- If you don't believe the constraints are hard, try to write just
|
||||
one single line which satisfies them. (To be able to make one
|
||||
function call, for example, you have to fill an entire line with
|
||||
stuff doing mostly nothing.)
|
||||
|
||||
- Just in case this is not enough: Yes, the code itself is
|
||||
obfuscated: It's (almost) only one big expression, with deep
|
||||
nesting of () and ?:, and full of unnecessary operations which
|
||||
do not really help making it readable. And it contains a lot of
|
||||
"magic numbers". (My favourite is the "7" in line 15 (each
|
||||
one). Which is the other digit I could have put there instead,
|
||||
and what other changes to the program would have been necessary?
|
||||
Without violating the constraints of course.)
|
||||
|
||||
- The fact that the main loop of the program calls "main"
|
||||
recursively is nothing new. New however is that this program
|
||||
only needs a logarithmic recursion depth! (Find out how this
|
||||
works.)
|
||||
|
||||
- When still in doubt about how to judge this program, type
|
||||
|
||||
./herrmann2 < herrmann2.cup
|
||||
|
||||
and let the result inspire you. ;-)
|
||||
|
||||
|
||||
|
||||
Requirements to the compiler / Compatibility
|
||||
============================================
|
||||
|
||||
- I fear that gcc is the only compiler for which this program
|
||||
works. Due to the severe restrictions, I was forced to use
|
||||
declarations of int variables, functions and parameters without
|
||||
specifying their type. The biggest problem was to put "int
|
||||
main(int c, char ** v){" into the program. After some time, I
|
||||
became convinced that this is impossible. Finally, at least I
|
||||
managed to squeeze "main(c, v){" into the constraints instead.
|
||||
|
||||
- Also, a lot of warnings are produced - most of them "data
|
||||
definition has no type or storage class", but also some
|
||||
"parameter names (without types) in function declaration" and
|
||||
"assignment from incompatible pointer type". I wasn't able to
|
||||
get rid of them.
|
||||
|
||||
- At least, it probably works with all sufficiently recent
|
||||
versions of gcc. I tested it with versions 2.7.2.1, 2.8.1,
|
||||
2.95.2, and ecgs-2.91.66.
|
||||
|
||||
- Of course I couldn't put "#include"-lines at the beginning of
|
||||
the program. Usually, this is not really necessary with
|
||||
gcc. However, for this program it would have been, because some
|
||||
functions appear as function pointers, and as such they are not
|
||||
generated implicitly. So the build script has to pass "-include
|
||||
..." to gcc. A problem with this is that the complete path of
|
||||
the include files has to be provided. In the build script, I
|
||||
assume that the path is /usr/include, but this can easily be
|
||||
adapted.
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllllllllllnnnnnnnnnnnllllllllllllnnnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllllllllllnnnnnnnnnllllllllllllllllnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllllnnnnnnnnnnnllllllnnnnnnllllllnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllllnnnnnnnnnnnlllllnnnnnnnnlllllnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllllnnnnnnnnnnnlllllnnnnnnnnlllllnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllllnnnnnnnnnnnlllllnnnnnnnnlllllnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllllnnnnnnnnnnnlllllnnnnnnnnlllllnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllllnnnnnnnnnnnllllllnnnnnnllllllnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllllllllllnnnnnnnnnllllllllllllllllnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnlllllllllllnnnnnnnnnnnllllllllllllnnnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnllllllllllnnnnnnnnnnllllllllllnnnnnnnnnnllllllllllnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnllllllllllllnnnnnnnnllllllllllllnnnnnnnnllllllllllllnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnllllllnnnnnnnnnnnnnnllllllnnnnnnnnnnnnnnllllllnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnnnnlllllnnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnllllllnnnnnnnnnnnnnnllllllnnnnnnnnnnnnnnllllllnnnnnnnnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnllllllllllllnnnnnnnnllllllllllllnnnnnnnnllllllllllllnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnllllllllllnnnnnnnnnnllllllllllnnnnnnnnnnllllllllllnnnnn
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __ "Y\n : ! ,.?>"
|
||||
#define D(f) ; } int f(int i) { return
|
||||
#define E(a,b,c,d,e) b##d,c,e,a
|
||||
#define e(a,b,c,d) a##b##c##d
|
||||
#define B *p++ - ' ' || !p++
|
||||
#define _(k) o(*#k - 64)
|
||||
#define G(g,l,k,o,e,d,n,c,i,b,a,f,j,m,p) \
|
||||
a#b#c#d#e#f#g#a#i#j#k#l#m#n#o e,i l##c,m##b; d g j n h(k 30:1); o p f}
|
||||
|
||||
G(E(f ( 9) -s
|
||||
? -s + 'q'
|
||||
? f( 5 ) -s &&'d' -
|
||||
s?U( 3 ) ||_(J)
|
||||
:A ( s- f( 5 ))
|
||||
:(c= 4 *
|
||||
4):
|
||||
|
||||
g(0)D(
|
||||
|
||||
V)c <= 3 *4 + 3&&c && V(X ( i) ) ;
|
||||
}
|
||||
|
||||
int , time ( 0)& , c - 15 || P
|
||||
|
||||
(1
|
||||
|
||||
):0,
|
||||
& ( !!d ( 0 )
|
||||
||(a=! _(S)) ,b= 0 )||
|
||||
a
|
||||
?d(a = 0)
|
||||
? _
|
||||
(I): w ( j =!W(j=_ (V ))) ,
|
||||
|
||||
l(_
|
||||
(Y+ s ) )
|
||||
)e
|
||||
|
||||
(
|
||||
main(){;
|
||||
;;;s , ra,
|
||||
n, d), && C ( j +R( s-j+t( i- 1) )
|
||||
)D( W)m[ c* 4| z( j ) ]
|
||||
&&_( X )E (d ( 0
|
||||
)&& R( 6)/ 6
|
||||
? c= 17|_ ( T )
|
||||
:01,||+
|
||||
, v =i & 3 ^ 2
|
||||
,+j & 3&&W ( j)||y ( 10 )D (k) --
|
||||
j ? k ( O[j]=R(15 ))
|
||||
: 1 D
|
||||
( H )o ( 7+! ! i+3 )+
|
||||
|
||||
i?
|
||||
|
||||
c=i /4 & 63,
|
||||
a= 1
|
||||
|
||||
:0)
|
||||
|
||||
D ( f )( p =M ,q ( i),*p+86)
|
||||
D ( l) * f, B?
|
||||
|
||||
B ?B ?B? B ?B ?B
|
||||
?7 :B?B ?36: 59 * 89 *5 * 2 :B?6587
|
||||
*77 :9 + 2:B ?B?B?9: 5 : 37 : B ? 5 +5:4:20:
|
||||
B?B?B?32
|
||||
|
||||
:e( 4, 3 , 1 *4 * 59 * 1 , 7):B?
|
||||
17: 34 : 19 :B ?
|
||||
8 *2 :B ?
|
||||
2:26: B?
|
||||
B?B ?B ?
|
||||
|
||||
82 *+ 576: B ?33 :22 :5 * 5:3 *4 :3:B ?B ?B? B ?6 +
|
||||
+ 17 : B?B?13:6 : 9 *2:B?15 : 7 *2 :
|
||||
|
||||
B ?
|
||||
B ?
|
||||
27:24: 31 : B?
|
||||
|
||||
|
||||
B? + 29 :,
|
||||
m [a^ 2 ] =T( 8 * 7) ;j= 3
|
||||
;
|
||||
;
|
||||
Q, ;int
|
||||
P ( int
|
||||
i )
|
||||
|
||||
{time_t(x ) =+ 0+
|
||||
time(0) ; j=E( u (i ) : i D(R )e(r ,
|
||||
a ,n ,d) ()% i+1, ( e( l , o,
|
||||
caltim , e ) (& x)) ->e( tm_h , o, u , r)
|
||||
;retur , i?_( W
|
||||
): _( U) D(Y) *p&& *p<3 * 11 ?
|
||||
( ++ p ), n j= + 34 +( j< 6
|
||||
||j>19 ),Y (i)
|
||||
: *p
|
||||
|
||||
D ( F) i == 9 ?1 :
|
||||
F( (i+ 7)% ( 7 + 3) ) +!O[ i
|
||||
]D(u) *p &&* p -32? p ++)
|
||||
D (h ) i ?*++*S=i% ( 38)- 1,
|
||||
D ( A )! n?i&&!g ( (0 ) ) ||K ( j=4| ! !i ) : N(!i )D(
|
||||
Q)++j<
|
||||
|
||||
(s ) &&Q ( t( i)^i )
|
||||
D( U )i>= 0 ?U( i- 1 )||~f (i+1 ) == ~ s
|
||||
&&H (m[c* 4 |z(i)] )
|
||||
:0;D
|
||||
|
||||
|
||||
( X) + b && b<, for (*S = M ; *
|
||||
p; ),
|
||||
|
||||
gets ( L, + 98 , stdin ) ?
|
||||
p= L, E (r( 0 ): 0 ,h( i / 38 ) : 0;D( C)!
|
||||
( m[j]+m [a= i] ) ?m[j[m]= i]=j:0;D (d) !
|
||||
b+(* O-
|
||||
c)*
|
||||
* O; D (z )
|
||||
|
||||
|
||||
-~- ~ -~i +
|
||||
v
|
||||
& 3 D(y)( putchar ) ( i)
|
||||
D ( q ) i& ,!(O[j = i]
|
||||
|| _ ( O))+a :0;
|
||||
D (w)O[ j] ==c && o
|
||||
|
||||
(( !i ++ ? ! !_ (M
|
||||
|
||||
):
|
||||
|
||||
0) +15)|| ++ j<9 &&w (
|
||||
i)D ( r )*p? *p -4?
|
||||
* p -6 ?
|
||||
y(*p <9 + 2?__[
|
||||
* p
|
||||
]: * p+ 7 +79):o( j+1) : o (26+j),&q ( -!
|
||||
* p ++ + i )D(x)i? a=x ( ( -- i)), ++ p )
|
||||
D( t ) i, | C((j=i*
|
||||
T(i-4 )) +R
|
||||
(3 ) + 4 )
|
||||
D(J) !j --E( 0 D ( K )!-!N, || i &,
|
||||
_( R ) :i* c== (O
|
||||
[ j ] ) &&n==f (j+ 6 + 5 * 4)?O
|
||||
[j]= !i * c-_ ( L) :J(i )
|
||||
D ( N ) j=9, & d(0 )? j= 6 | ! i , J(i )D
|
||||
( o)(*S = p , ++ S,p = M , r (q (i) ),-- S, p = *S))
|
||||
( (l (_ (Q )),n =s,i ^5 ) ) ;, E(j ,
|
||||
sign , v ,ed ( b ) ;;
|
||||
int c =1 ,O[9])
|
||||
;int( s
|
||||
)=
|
||||
E (n ;char, 1 ,a,6 ,o ())* Z[
|
||||
E(M [37 * 9 *3 ] ,0,L [ 99] ,3] , * *S=Z ) ;
|
||||
E (*p=+1 ,char( m)[6 , co , 4 ],ol)
|
||||
+,
|
||||
V ( v=*O = k( j= 9 )) ;
|
||||
return ! c&& - ~ ~ - -! printf
|
||||
( ( "%d \n") , F (P ( 0) +6) *50 + ! ! b*
|
||||
( +b - (int)time ( 0 )) )
|
||||
;, ( b= 60 + time ( 0)+ 60 * 4) ;, n =Y
|
||||
(u (s =Y (i) ) )
|
||||
|
||||
: (exit( 0)
|
||||
,i)D( g )x ( _(N) ^ 9)? !( a =0) : _ ( P )D (T)! i|,
|
||||
(2); s=35; Q(3);
|
||||
|
||||
s=59; Q(6);
|
||||
|
||||
|
||||
a=1;
|
||||
|
||||
|
||||
|
||||
|
||||
)
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
Best Of Show:
|
||||
|
||||
Jason Orendorff
|
||||
5 Buchanan St.
|
||||
Nashua, NH 03060
|
||||
USA
|
||||
|
||||
http://www.jorendorff.com/
|
||||
|
||||
|
||||
Judge's Remarks:
|
||||
|
||||
To build:
|
||||
|
||||
make jason
|
||||
|
||||
Try:
|
||||
|
||||
./jason
|
||||
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
|
||||
The really amazing part of this is tha it's a text adventure, and there's
|
||||
not a single word in the source that isn't a C keyword or function name,
|
||||
being used as such.
|
||||
|
||||
The interface isn't very tolerant of errors, but you can't really
|
||||
expect that from something this small.
|
||||
|
||||
Of particular interest: Go ahead, run it through the preprocessor. You
|
||||
*still* won't see the words that are used in the game.
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
TED shroyer came up with the idea that made it possible to hide all
|
||||
the text. Thanks, TED. You won. :)
|
||||
|
||||
|
||||
$ cc -o prog prog.c
|
||||
$ ./prog
|
||||
you are in a maze of twisty little passages
|
||||
caves lead: left forward back
|
||||
you see
|
||||
a lamp
|
||||
> _
|
||||
|
||||
This program is a rather nostalgic little labyrinth game. Start
|
||||
out by typing "get lamp", then use the direction words "left",
|
||||
"right", "forward", and "back" to explore the caves. Note that
|
||||
these words can refer to different passages depending on which way
|
||||
you're facing. "back" always takes you back the way you came.
|
||||
Type "quit" to quit.
|
||||
|
||||
The maze is randomly generated each time you play. The algorithm
|
||||
ensures that you start at least 6 hops away from the exit. All
|
||||
passages are two-way.
|
||||
|
||||
(There is a trick, well-known among adventure game fans, to
|
||||
keeping one's bearings in games like this. Unless you know the
|
||||
trick, it can be very difficult to find your way around. Try it
|
||||
out first; I'll give away the secret at the bottom of this
|
||||
document.)
|
||||
|
||||
The goal is to collect 8 treasures (plus the lamp) and escape into
|
||||
the sunlight - or moonlight, as the case may be. After a few
|
||||
minutes, the lamp runs out of oil, and things become perilous.
|
||||
|
||||
If you manage to escape, you score 50 points for your hide, 50
|
||||
points per item, and bonus points for speed.
|
||||
|
||||
Why I think this program is obfuscated:
|
||||
|
||||
* 70% more # symbols than the average entry.
|
||||
|
||||
* Where are all the messages? The game is downright chatty for
|
||||
only having two string literals ("%d \n" and "Y\n : ! ,.?>").
|
||||
|
||||
* There is exactly one loop in the program, a for loop, and it is
|
||||
clearly the product of a deranged mind. Running the
|
||||
preprocessor only makes it worse.
|
||||
|
||||
* Microsoft Visual C++ won't even compile this program, even
|
||||
though it is plain ANSI C (*innocent look*) and limits itself to
|
||||
the most standard and portable of the standard library
|
||||
facilities.
|
||||
|
||||
* Most of the whitespace is significant, so attempts to
|
||||
beautify it can easily lead to segmentation faults.
|
||||
|
||||
* Attempts to replace the one-character identifiers with longer,
|
||||
more meaningful names will likewise cause problems. In fact,
|
||||
simply changing all the Y's to Z's and vice versa results in
|
||||
some unexpected side effects.
|
||||
|
||||
When all warnings are enabled, some compilers express the desire
|
||||
to see a few more parentheses. I respectfully submit that there are
|
||||
plenty of parentheses in the program (370 in all.) Besides, any
|
||||
more would put me over the size limit. gcc also generates a
|
||||
warning about some calculations not being used. Having just spent
|
||||
19 hours staring at this program, sweating over every character, I
|
||||
swear gcc is wrong.
|
||||
|
||||
The program is formatted as a poem, to make it more readable.
|
||||
I find the plaintive chorus "B? B?" particularly poignant.
|
||||
Also, smiley faces are formatted flush left. (If you don't find
|
||||
the game entertaining, see if you can find
|
||||
|
||||
the fish scales Q)++j<
|
||||
the shooting star -~- ~ -~i +
|
||||
|
||||
in the source code.)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[GAME STRATEGY SPOILER: The trick, of course, is to drop items in
|
||||
empty rooms to mark them. That way you usually know if you're in a
|
||||
room you've seen before. It greatly aids mapping.]
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
#include <unistd.h>
|
||||
#include <curses.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define o0(M,W) mvprintw(W,M?M-1:M,"%s%s ",M?" ":"",_)
|
||||
#define O0(M,W) M##M=(M+=W##M)-W##M
|
||||
#define l1(M,W) M.tv_##W##sec
|
||||
#define L1(m,M,l,L,o,O) for(L=l;L--;)((char*)(m))[o]=((char*)(M))[O]
|
||||
#define I1 lL,(struct sockaddr*)&il
|
||||
#define i1 COLS
|
||||
#define j LINES
|
||||
#define L_ ((j%2)?j:j-1)
|
||||
|
||||
fd_set I;struct socka\
|
||||
ddr_in il;struct host\
|
||||
ent*LI; struct timeval
|
||||
IL,l;char L[9],_[1<<9]
|
||||
;void ___(int __
|
||||
){_[__--]=+0;if(
|
||||
++__)___(--__);_
|
||||
[__]='=';}double
|
||||
o,oo=+0,Oo=+0.2;
|
||||
long O,OO=0,oO=1
|
||||
,ii,iI,Ii,Ll,lL,
|
||||
II=sizeof(il),Il
|
||||
,ll,LL=0,i=0,li,
|
||||
lI;int main(int\
|
||||
iL,char *Li[]){\
|
||||
initscr();cbreak
|
||||
();noecho();nonl
|
||||
();___(lI=i1/4);
|
||||
_[0]='[';_[lI-1]
|
||||
=']';L1(&il,&_,\
|
||||
II,O,+O,+lI);il.
|
||||
sin_port=htons((
|
||||
unsigned long)(\
|
||||
PORT&0xffff));lL
|
||||
=l_;if(iL=!--iL)
|
||||
{il. sin_addr .\
|
||||
s_addr=0;bind(I1
|
||||
,II);listen(lL,5
|
||||
);lL=accept(I1,&
|
||||
II);}else{oO-=2;
|
||||
LI=gethostbyname
|
||||
(Li[1]);L1(&(il.
|
||||
sin_addr),(*LI).
|
||||
h_addr_list[0],\
|
||||
LI->h_length,iI,
|
||||
iI,iI);(*(&il)).
|
||||
sin_family=(&(*\
|
||||
LI))->h_addrtype
|
||||
;connect(I1,II);
|
||||
}ii=Ii=(o=i1*0.5
|
||||
)-lI/2;iI=L_-1;O
|
||||
=li=L_*0.5;while
|
||||
(_){mvaddch(+OO,
|
||||
oo,' ');o0(ii,iI
|
||||
);o0(Ii,Il-=Il);
|
||||
mvprintw(li-1,Il
|
||||
,"%d\n\n%d",i,LL
|
||||
);mvhline(li,+0,
|
||||
'-',i1);mvaddch(
|
||||
O,o,'*');move(li
|
||||
,Il);refresh();\
|
||||
timeout(+SPEED);
|
||||
gettimeofday(&IL
|
||||
,+0);Ll=getch();
|
||||
timeout(0);while
|
||||
(getch()!=ERR);\
|
||||
if(Ll=='q'&&iL)\
|
||||
write(lL,_+1,1);
|
||||
if(ii>(ll=0)&&Ll
|
||||
==','){write(lL,
|
||||
_,-(--Il));}else
|
||||
if(Ll=='.'&&ii+\
|
||||
lI<i1){write(lL,
|
||||
_+lI,++Il);}else
|
||||
if(iL||!Il)write
|
||||
(lL,_+lI-1,4-3);
|
||||
gettimeofday(&l,
|
||||
0);II=((II=l1(IL
|
||||
,)+(l1(l,u)-=l1(
|
||||
IL,u))-l1(l,)+(\
|
||||
l1(l,)-=l1(IL,))
|
||||
)<0)?1+II-l1(l,)
|
||||
+1e6+(--l1(l,)):
|
||||
II;usleep((II+=\
|
||||
l1(l,)*1e6-SPEED
|
||||
*1e3)<0?-II:+0);
|
||||
if(Ll=='q'&&!iL)
|
||||
break;FD_ZERO(&I
|
||||
);FD_SET(lL,&I);
|
||||
memset(&*&IL,ll,
|
||||
sizeof(l));if((\
|
||||
Ll=select(lL+1,&
|
||||
I,0,0,&IL)));{if
|
||||
(read(lL,&L,ll+1
|
||||
)){if(!*L){ll++;
|
||||
}else if(*L==ll[
|
||||
_]){ll--; }else\
|
||||
if(*(&(*L))==1[_
|
||||
]){break;}}else{
|
||||
break;}}O0(o,O);
|
||||
O0(O,o);if(o<0){
|
||||
o*=-1;Oo*=-1;}if
|
||||
(o>i1){o=i1+i1-o
|
||||
;Oo*=-1;}if(o>=(
|
||||
Ii+=ll)&&O<1&&oO
|
||||
<0&&o<Ii+lI){O=2
|
||||
;oO=~--oO;Oo+=ll
|
||||
*4e-1;}if(O<0){O
|
||||
=iI;LL++;}if(o>=
|
||||
(ii+=Il)&&O>iI-1
|
||||
&&oO>0&&o<ii+lI){O=iI-
|
||||
2;oO=~--oO;Oo+=Il*4e-1
|
||||
;}if(+O>+iI){O-=O;i++;
|
||||
}}endwin();return(0);}
|
||||
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
Best Curses Game:
|
||||
|
||||
Kevin Pulo
|
||||
School of Information Technologies
|
||||
Madsen Building F09
|
||||
University of Sydney, NSW, 2006
|
||||
Australia
|
||||
|
||||
http://www.kev.pulo.com.au/
|
||||
|
||||
|
||||
Judge's Remarks:
|
||||
|
||||
To build:
|
||||
|
||||
make kev
|
||||
|
||||
Try:
|
||||
|
||||
./kev
|
||||
|
||||
and then in another window,
|
||||
|
||||
./kev localhost
|
||||
|
||||
Continuing with this year's "retro game" theme, this is another old game;
|
||||
arguably, one of the oldest. Requires a functioning network, and curses.
|
||||
|
||||
The graphics aren't the impressive part; the graphics and network are.
|
||||
How many games come out at $50 and still require you to wait for a patch
|
||||
to come out before you can play multiplayer? This one works out of the
|
||||
box.
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
NETWORK P*NG!
|
||||
[=================]
|
||||
|
||||
Kevin Pulo
|
||||
kev@pulo.com.au
|
||||
|
||||
|
||||
REQUIREMENTS
|
||||
------------
|
||||
|
||||
* TCP sockets
|
||||
* curses
|
||||
* usleep
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
This program is a two-player networked version of the eighties
|
||||
arcade classic, "pong". It uses standard TCP sockets to
|
||||
communicate over the net, and ncurses for display. It supports
|
||||
variable terminal sizes (though both players must have the same
|
||||
terminal size) and game speeds. Each player has a paddle to hit
|
||||
the ball, and you get points for getting the ball past your
|
||||
opponent's paddle. It's pretty fun! :)
|
||||
|
||||
|
||||
RUNNING
|
||||
-------
|
||||
|
||||
Run the server first without any command line arguments, ie.
|
||||
|
||||
./kev
|
||||
|
||||
Then run the client with a single command line argument which is
|
||||
the name of the machine running the server, eg.
|
||||
|
||||
./kev localhost
|
||||
|
||||
Make sure that the terminals on both ends are the same size.
|
||||
Also, the TCP port number specified in the build file mustn't be
|
||||
blocked by a firewall.
|
||||
|
||||
Here's a good quick example to see it in action on your own
|
||||
machine, assuming you have Xwindows:
|
||||
|
||||
xterm -geometry 80x40 -fg green -bg black -fn 9x15bold -e ./kev &
|
||||
xterm -geometry 80x40 -fg green -bg black -fn 9x15bold -e ./kev localhost&
|
||||
|
||||
|
||||
PLAYING
|
||||
-------
|
||||
|
||||
Your paddle is the one at the bottom of the screen, your opponent
|
||||
is at the top. To move your paddle left, hold down ',' (ie. '<'
|
||||
but don't press shift). To move your paddle right, hold down '.'.
|
||||
To quit, either player may press 'q'.
|
||||
|
||||
The current score is shown on the left side of the halfway line.
|
||||
Your score is the lower number, your opponents score is the upper
|
||||
number. Your score is the number of times your opponent has
|
||||
missed the ball.
|
||||
|
||||
You can control the speed of the ball by the motion of your paddle
|
||||
when the ball hits it. If your paddle is still, then the ball
|
||||
just bounces normally off it. If your paddle is moving in the
|
||||
same direction as the ball, then the ball's speed in that
|
||||
direction will increase. If your paddle is moving in the opposite
|
||||
direction to the ball, then the ball's speed in that direction
|
||||
will decrease (or if the ball is going slowly enough, it'll turn
|
||||
around).
|
||||
|
||||
You might want to increase your keyboard repeat rate before
|
||||
playing. On the Linux console try "kbdrate -r 24.0 -d 250"
|
||||
(kbdrate might be "hidden" from normal users in /sbin, and you
|
||||
might need to be root anyway), in Xwindows try "xset r rate 250
|
||||
24" (find out your current rate first with "xset q", so that you
|
||||
can reset it later).
|
||||
|
||||
Look below in the Building section for info on how to speed up or
|
||||
slow down the game (useful if your increase or decrease the
|
||||
terminal size).
|
||||
|
||||
|
||||
BUILDING
|
||||
--------
|
||||
|
||||
Just run the Makefile as above. The "SPEED" variable in the Makefile
|
||||
controls the speed of the game (defaults to 50). This speed is
|
||||
the delay between frames in milliseconds. Thus a value of 0 will
|
||||
make the game go as fast as your network can handle, and values
|
||||
less than 50 are useful for larger terminals or more exciting
|
||||
games. The program needs bandwidth equal to 1/s bytes per second
|
||||
(where "s" is the speed value). Any latency on the network will
|
||||
be added to s - so you should probably subtract any latency from
|
||||
the value of s you want to have. Given that loopback and fast
|
||||
Ethernet LANs are both much less than 1ms of latency, you should
|
||||
only need to worry about this if you plan on playing over a slower
|
||||
link like a cable modem, DSL, or (God-forbid) dialup.
|
||||
|
||||
The TCP port to use for network communications is specified by the
|
||||
"PORT" variable in the Makefile. If the default of 5455 is
|
||||
blocked for whatever reason, you can change it to something else.
|
||||
Of course if you use a port < 1024, you'll need to be root.
|
||||
|
||||
|
||||
OBFUSCATION
|
||||
-----------
|
||||
|
||||
The program's broad structure is fairly straightforward, but
|
||||
individual tasks are rarely done in a straightforward manner. ;)
|
||||
|
||||
Identifier names have mostly been chosen to resemble paddles and
|
||||
balls, and to generally decrease readability.
|
||||
|
||||
The source has been cleverly formatted to resemble one of the
|
||||
paddles from the game, rotated 90 degrees. ;) (The "source
|
||||
paddle" has approximately the same aspect ratio as the game at 80
|
||||
columns wide, which is 1:10.)
|
||||
|
||||
Finally, the number of "non-whitespace characters" (as defined by
|
||||
the rules) in the file is exactly 2048, which I think is rather
|
||||
unexpectedly cool. :)
|
||||
|
||||
|
||||
BUGS
|
||||
----
|
||||
|
||||
There are 3 warnings when I compile with gcc 2.95.3 (-Wall -ansi
|
||||
-pedantic) on my Linux system, but all are completely harmless.
|
||||
|
||||
I don't like the curses and/or termcaps/terminfos on IRIX and
|
||||
Solaris (the only two non-Linux systems I have access to).
|
||||
Despite calling timeout(0), notimeout(win, TRUE), nodelay(win,
|
||||
TRUE) and/or keypad(win, FALSE), it still seems to force a delay
|
||||
into calls to getch() - I'm guessing at a termcap/terminfo level.
|
||||
At any rate, I can't seem to force no delay. This is a shame,
|
||||
because it basically plays havoc with the input code, particularly
|
||||
the read-ahead canceller. It still works, but not nearly as well
|
||||
(keypresses are dodgey and holding down keys doesn't always work),
|
||||
and so I _much_ prefer and recommend Linux libncurses.
|
||||
|
||||
Sometimes when 'q' is pressed in one, the other will crash out
|
||||
with "Broken pipe".
|
||||
|
||||
If the specified port can't be bound or connected to, the program
|
||||
segfaults.
|
||||
|
||||
If your terminal is too wide (we're talking gigantic here - over
|
||||
500 characters wide) then the program can segfault. It's also
|
||||
possible to crash the program a player scores over a billion
|
||||
points (1e9). Maybe you can consider that the goal... ;)
|
||||
|
||||
If you run the client and server on different architectures, both
|
||||
architectures need to have the same character systems (ie. don't
|
||||
try mixing ASCII and EBCDIC). It is independent of endianness
|
||||
though.
|
||||
|
||||
|
||||
+1301
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,21 @@
|
||||
#define n ((e[++a]-42)/9-f[d+1])?
|
||||
#define o printf("%c",c[" 01./:;|\\"]);
|
||||
|
||||
char e[]="**3<HRZcir+3@OXakt;=GOXds*\?HRZcir*7HNZ`i19JS\\p*H[m1:CJSz*>H[`mr25\
|
||||
\?Hx,P,B2Gs-KTfzRdv1SeyCR-ISeu.<Ev+9+P,z,4PfzIdvO2*HRZcir6GPis=MU*3HRZcir*HZi\
|
||||
1JS\\epy*>H[m1JSey*DH[m*3<HZiu-@P*3HZi<N]q1JS\\epy:[m1CJSeny06I[m*4\?HRZcir,\
|
||||
\?*6HRZcir1J]q2K*H[m2K*H[m2@K]qtO@M2DK]q,]q1JS\\epy[m1:JSey+[m*3<HRZcir13Gt,\
|
||||
=GVs*3<HRZcir1J]qz*HF*AH2;DK]qua0=G2:K]q]q1CJS\\pDVu1:JS*D!+3:BIOSY`egilqtxz\
|
||||
\177.0249<==>EJMUY`ejov#$59@CJOXYZbfhlnrxy&+.57=@IMR[``bcfmnq!#),@",*f;
|
||||
|
||||
int main(int j,char *k[]) {
|
||||
int a,b,c,d,g,h,i=19;
|
||||
|
||||
printf(" ");
|
||||
for(g=0[f=(char *)calloc(80+(h=atoi(1[k])),1)]=1; g<=h; g++) {
|
||||
if ((g>30)&&(f[i-2]+f[i-1]!=0)) i++;
|
||||
for(d=c=0; d<i; d++) {
|
||||
o f[d]=(e[b=c*9,b+=(c=d[f]),(((a=e[345+b]+b/19*85-33-b/40*12-b/80*4)[e]
|
||||
-42)/9-f[d+1])?n n n n n n n n 0:a:a:a:a:a:a:a:a:a]-42)%9; }
|
||||
o if (0[f]-1) printf("\n%6i ",g); else printf("\n "); }
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
Best primal ASCII graphics:
|
||||
|
||||
Nicolas Ollinger
|
||||
Ecole Normale Superieure de Lyon
|
||||
LIP, ENS Lyon
|
||||
46, allée d'Italie
|
||||
69364 Lyon Cedex 07
|
||||
France
|
||||
|
||||
http://www.ens-lyon.fr/~nollinge/
|
||||
|
||||
|
||||
Judges' Comments:
|
||||
|
||||
To build:
|
||||
|
||||
make ollinger
|
||||
|
||||
Try:
|
||||
|
||||
In a large window, say 200 chars wide and 100 high (200x100)
|
||||
with a tiny font, try:
|
||||
|
||||
./ollinger 1000 | cut -c -200
|
||||
|
||||
|
||||
Do get lost in the programs line of thought! :-)
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
What's this?
|
||||
------------
|
||||
|
||||
What do you see? On the left, you will see an enumeration of all successive
|
||||
primes from 2 to the parameter you gave to the program. On the right part,
|
||||
you can see the sieve used to find these primes. The big diagonals from
|
||||
right to left are used to erase composed numbers. When no diagonal crosses
|
||||
a number, then the left cell take value 1 and the number is prime.
|
||||
|
||||
The parallel version of this algorithm works in real time n. This C
|
||||
sequential version is slower as it works in O(n*log n). But you have some
|
||||
nice picture instead... the cost is a constant number of operation for each
|
||||
character printed on the screen.
|
||||
|
||||
|
||||
Why do you wrote it?
|
||||
--------------------
|
||||
|
||||
Let's just quote the FAQ :
|
||||
|
||||
Q: Are there types of entries that are submitted so frequently that the
|
||||
judges get tired of them?
|
||||
|
||||
A: Yes, there are types of entries that show up over and over again.
|
||||
The guidelines say:
|
||||
|
||||
We tend to dislike programs that:
|
||||
are similar to previous winners
|
||||
|
||||
We like variety. However too often we see (please look at the winning
|
||||
examples given to be aware of the level of the competition):
|
||||
|
||||
(snip)
|
||||
|
||||
generating small primes (below is the list of all
|
||||
prime related winners)
|
||||
1985/august
|
||||
1988/applin
|
||||
1994/weisberg
|
||||
1995/makarios
|
||||
1996/dalbec
|
||||
2000/bellard
|
||||
|
||||
As you can see, just a list of primes (let alone small primes)
|
||||
does not cut it anymore.
|
||||
|
||||
(snip)
|
||||
|
||||
entries that use some complex state machine/table to print
|
||||
something
|
||||
|
||||
1988/isaak
|
||||
1988/phillipps
|
||||
|
||||
Unbeaten for 12 years and counting...
|
||||
|
||||
I think this is enough motivation for trying to submit a program which uses
|
||||
some complex state machine/table to generate small primes and print them.
|
||||
|
||||
|
||||
The way it works
|
||||
----------------
|
||||
|
||||
This program simply prints the space-time diagram of some particular
|
||||
cellular automaton. The automaton is a 9-state automaton by Korec in 1998.
|
||||
It is an optimization of an old automaton for recognizing primes designed
|
||||
by Fischer in 1965.
|
||||
|
||||
The table of the automaton is encoded into the string e and consists of
|
||||
345 transitions of the kind f(left,middle,right). This encoding into e
|
||||
is obfuscated to reduce its size, restrict it to characters 32 to 127 and
|
||||
guarantee a constant time.
|
||||
|
||||
The main loop simply iterates this transition function on each cell.
|
||||
|
||||
"The rest is silence" (Hamlet, V.2)
|
||||
|
||||
Enjoy!
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifdef s
|
||||
z
|
||||
r(
|
||||
){z
|
||||
k=0,l
|
||||
=0,n,x
|
||||
XQueryPointer(i
|
||||
,XRootWindow (i,j),&m,
|
||||
&m,&o,&p,&n,&n,( ghj)&n),(o
|
||||
>=s(g)||s(o
|
||||
)<=0)&&(k=1),
|
||||
(p>=h||p<=0)&&
|
||||
(l=1),(e==1)&&(
|
||||
c=o,d=p,e=0,1)||(
|
||||
(k==0&&o-c-(z)(a+y
|
||||
(a)*.5)!=0)&&(a=o-c
|
||||
),(l^-1==-1&&p-d-(z)(
|
||||
b+y(b)*.5)!=0)&&(b=p-d),a/=f,b/=f
|
||||
,k=0,l=0);(o >=s(g)||o<=0)&&(a=-a),(
|
||||
p>=h||s(p)<=0) &&(b=-b),c=o,d=p,I(XWarpP
|
||||
,ointer)(i,None,None,0,0,s
|
||||
(g),h,(z)(a+y(a)*.5),(int)(
|
||||
b+y(b)*.5 JJ(float B;int)C,D;
|
||||
#else/*Egads! something has */
|
||||
#include<X11/Xlib.h>/*taken a*/
|
||||
#include<stdio.h>/*huge bite o-*/
|
||||
#include<stdlib.h>/*ut of the m-*/
|
||||
#include<time.h>/*ouse pointer!!!*/
|
||||
#define H(a, b) (((a)&(7<<3*(b)))>>3*(b))
|
||||
#define G(c,d) ((H(c,d)<<3*(d+1))|((H(c,d+1)<<3*d)|/*
|
||||
_XSetPointer(display, screen,GREASY|BOUNCY)*/c&~(63<<3*(d))))
|
||||
#define s(e) (G(G(G(G(G(G(e,(z)0),1),2),1),0),1))
|
||||
typedef int z;float a=0,b=0,c,d,f=1.03;z e
|
||||
=s(512),g,h,j;
|
||||
Display/**/*i;
|
||||
#define y(X)((X>0)-(X<0))
|
||||
#define x o,p; Window m;
|
||||
#define ghj unsigned int*
|
||||
#define I(aa,bb)aa##bb
|
||||
#define JJ(X)\
|
||||
));return 0;}X
|
||||
z r();int main
|
||||
(z X,char**Y){
|
||||
clock_t q=0;(X
|
||||
==2)&&(f=atof(Y[1])),((i
|
||||
=XOpenDisplay(0) )==0)&&(exit(1
|
||||
),1),j=I(Defa, ultScreen)(i),
|
||||
g=s(I(Display,
|
||||
Width)(i,j)-1)
|
||||
,h=I(DisplayH,
|
||||
eight)(i,j)-1;
|
||||
for(;;((I(clo,
|
||||
ck)()-q)*100>(
|
||||
CLOCKS_PER_SEC
|
||||
))&&(r(),q=clock()));}
|
||||
#include __FILE__
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
Best abuse of the user:
|
||||
|
||||
Edward Rosten
|
||||
Oxford University
|
||||
34 The Chilterns
|
||||
Gloucester Green
|
||||
Oxford
|
||||
OX1 2DF
|
||||
United Kingdom
|
||||
|
||||
http://users.ox.ac.uk/~scat1148
|
||||
|
||||
|
||||
Judges' Comments:
|
||||
|
||||
To build:
|
||||
|
||||
make rosten
|
||||
|
||||
Try:
|
||||
|
||||
./rosten 1.03
|
||||
./rosten 1.00
|
||||
|
||||
For some abuse, try:
|
||||
|
||||
./rosten 0.99
|
||||
|
||||
Friction can be your friend if it does not rub you (or your mouse
|
||||
cursor) in the wrong way. :-)
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
NAME
|
||||
|
||||
rosten - make the mouse act as if it has been greased
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
rosten [greasiness]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
This program is designed primarily to make your X windows interface more
|
||||
obfuscated. Try doing something mouse driven (such as using a mouse
|
||||
driven editor on this program) whilst it is running. If you're not sure
|
||||
what it does, looking at the code should give a fair idea.
|
||||
|
||||
It also has a [cat] man page if you want to install it as a `utility'.
|
||||
|
||||
|
||||
OPTIONS
|
||||
|
||||
It only takes one optional option: the greasiness factor. This is the
|
||||
number that the speed is divided by on each iteration. The default is
|
||||
1.03. A setting of 1 (no friction is fun), as is 0.99.
|
||||
|
||||
Being an X program, it recognised the DISPLAY variable.
|
||||
|
||||
|
||||
PORTABILITY
|
||||
|
||||
The program is very portable, even to non X architectures. All that is
|
||||
required is a large desk and some good grease.
|
||||
|
||||
|
||||
COMMENTS
|
||||
|
||||
It is really rather surprising that code like this should not only be
|
||||
portable, but compile with almost no warnings on most of the compilers
|
||||
tested. It's a kind of shame that none of the compilers do anything
|
||||
like this:
|
||||
|
||||
$make greasymouse
|
||||
cc greasymouse.c -o greasymouse -lX11
|
||||
greasymouse.c:30: This macro should have more text and spaces in it
|
||||
greasymouse.c:32: This is a really stupid way to perform this operation
|
||||
greasymouse.c:42: This program would look better with a newline here
|
||||
greasymouse.c:48: That's a really silly thing to do
|
||||
greasymouse.c:55: So is that
|
||||
...
|
||||
greasymouse.c:58: This program is rubbish. I'm not going to link it.
|
||||
|
||||
The code is best viewed with tabstops every 8 spaces.
|
||||
|
||||
|
||||
BUGS
|
||||
|
||||
The mouse gets stuck completely if you give it an option of less
|
||||
than 1 and leave it for too long. This is quite annoying if it
|
||||
didn't leave the terminal if was run from in focus.
|
||||
|
||||
It gets very jerky if the processor is being used. There are
|
||||
better time functions than clock() but I haven't used them.
|
||||
|
||||
It deflects slightly when it gets very slow.
|
||||
|
||||
It annoys other people if you run it on their display too
|
||||
often. Maybe I should make future versions print funny jokes to
|
||||
keep the humor fresh.
|
||||
|
||||
It's pretty ropey over a 56K modem.
|
||||
|
||||
It's even ropier over a 56K modem and tunneled through 3 ssh links.
|
||||
|
||||
|
||||
WARNINGS
|
||||
|
||||
Pages and pages and pages of things, with GCC at any rate.
|
||||
|
||||
It suggests loads of ()'s where they're not needed.
|
||||
|
||||
It reckons I have not used some of the values I have computed. I
|
||||
would never do a thing like that: I just haven't used them in
|
||||
the way it's used to.
|
||||
|
||||
The MIPS compiler suggests an == instead of an = in expressions
|
||||
such as:
|
||||
|
||||
&&(a=b)
|
||||
|
||||
but I its suggestions would break my program. It also reckons
|
||||
that r() has no prototype.
|
||||
|
||||
Giving the -pedantic option to the MIPS compiler causes it to generate
|
||||
warnings about its own header files, but not any extra ones with this
|
||||
program.
|
||||
|
||||
With all warnings enabled, the DEC compiler, oddly enough finds some
|
||||
problems with its own include files, but none with my program.
|
||||
|
||||
|
||||
ERRORS
|
||||
|
||||
The DEC compiler of this version:
|
||||
|
||||
DEC C V5.6-079 on Digital UNIX V4.0 (Rev. 878)
|
||||
|
||||
can't compile the code. It thinks that preprocessor lines can not have
|
||||
whitespace preceding the #. Moving the preprocessor directives to the
|
||||
beginning of the line wrecks the layout but makes it compile.
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
16th International Obfuscated C Code Contest Rules |
|
||||
|
||||
Copyright (c) Leonid A. Broukhis, Simon Cooper, Landon Curt Noll and |
|
||||
Peter Seebach, 2001. |
|
||||
|
||||
All Rights Reserved. Permission for personal, education or non-profit use is
|
||||
granted provided this this copyright and notice are included in its entirety
|
||||
and remains unaltered. All other uses must receive prior permission in
|
||||
writing from the contest judges.
|
||||
|
||||
Obfuscate: tr.v. -cated, -cating, -cates. 1. a. To render obscure.
|
||||
b. To darken. 2. To confuse: his emotions obfuscated his
|
||||
judgment. [LLat. obfuscare, to darken : ob(intensive) +
|
||||
Lat. fuscare, to darken < fuscus, dark.] -obfuscation n.
|
||||
obfuscatory adj.
|
||||
|
||||
|
||||
GOALS OF THE CONTEST:
|
||||
|
||||
* To write the most Obscure/Obfuscated C program under the rules below.
|
||||
* To show the importance of programming style, in an ironic way.
|
||||
* To stress C compilers with unusual code.
|
||||
* To illustrate some of the subtleties of the C language.
|
||||
* To provide a safe forum for poor C code. :-)
|
||||
|
||||
The 16th IOCCC contest window is: |
|
||||
|
||||
01-Oct-2001 00:00 UTC to 01-Dec-2001 23:59:59 UTC |
|
||||
|
||||
NOTE: Some of the changes from the 2000 rules are denoted by change bars. ---> |
|
||||
|
||||
|
||||
RULES:
|
||||
|
||||
To help us with the volume of entries, we ask that you follow these rules:
|
||||
|
||||
1) Your entry must be a complete program.
|
||||
|
||||
2) The uudecoded size of your program source must be <= 4096 bytes in |
|
||||
length. The number of characters (after uudecoding your program) |
|
||||
excluding whitespace (tab, space, newline, formfeed, return), and |
|
||||
excluding any ; { or } immediately followed by whitespace or end |
|
||||
of file, must be <= 2048.
|
||||
|
||||
3) Your entry must be submitted in the following format:
|
||||
|
|
||||
NOTE: The change bars are not part of the rules, don't add the |
|
||||
change bars to your entry! |
|
||||
|
||||
---entry---
|
||||
rule: 2001 |
|
||||
fix: y or n (n => this is a new entry, y => this replaces an older entry)
|
||||
title: title of entry (see comments below)
|
||||
entry: Entry number from 0 to 7 inclusive (your 1st entry should by 0)
|
||||
date: Date/time of submission in UTC (see comments below)
|
||||
host: Machine(s) and OS(s) under which your entry was tested
|
||||
Use tab indented lines if needed
|
||||
---remark---
|
||||
Place remarks about this entry in this section. It would be helpful if
|
||||
you were to indent your remarks with 4 spaces, though it is not a
|
||||
requirement. Also, if possible, try to avoid going beyond the 79th
|
||||
column. Blank lines are permitted.
|
||||
---author---
|
||||
name: your name
|
||||
org: School/Company/Organization
|
||||
addr: postal address
|
||||
use tab indented lines to continue
|
||||
don't forget to include the country
|
||||
email: EMail address from a well known site or registered domain.
|
||||
If you give several forms, list them on separate tab indented lines.
|
||||
url: http://your/home/page.html or say none if you don't have one
|
||||
anon: y or n (y => remain anonymous, n => OK to publish this info)
|
||||
---info---
|
||||
If your program needs an info file, place a uuencoded copy of it in
|
||||
this section. In the case of multiple info files, use multiple info
|
||||
sections. If your entry does not need a info file, skip this section.
|
||||
---build---
|
||||
Place a uuencoded copy of the command(s) used to compile/build your program
|
||||
in this section. It must uudecode into a file named 'build'. The resulting
|
||||
file must be 521 bytes or less. |
|
||||
---program---
|
||||
Place a uuencoded copy of your program in this section. It must uudecode
|
||||
into a file named is 'prog.c'. The resulting file must follow rule #2.
|
||||
---end---
|
||||
|
||||
Regarding the above format:
|
||||
|
||||
* The title must match the expression:
|
||||
|
||||
^[a-zA-Z0-9_=][a-zA-Z0-9_=+-]*$
|
||||
|
||||
and must be 1 to 31 characters in length.
|
||||
|
||||
It is suggested, but not required, that the title should
|
||||
incorporate the author(s) username(s).
|
||||
|
||||
* The date in the ---entry--- section should be given with respect
|
||||
to UTC. The format of the date should be as returned by asctime()
|
||||
using the C locale. (see guidelines for more info)
|
||||
|
||||
* You may correct/revise a previously submitted entry by sending
|
||||
it to the contest email address. Be sure to set 'fix' in the
|
||||
---entry--- section to 'y'. The corrected entry must use the same
|
||||
title and entry number as submission that is being corrected. Be
|
||||
sure that you note the re-submission in the ---remark--- as well.
|
||||
|
||||
* With the exception of the header, all text outside of the above
|
||||
format may be ignored by the judges. If you need to tell the judges
|
||||
something, put it in the ---remark--- section, or send a separate
|
||||
EMail message to the judges.
|
||||
|
||||
* Information from the ---author--- section will be published unless
|
||||
'y' was given to the respective author's 'anon' line.
|
||||
|
||||
* To credit multiple authors, include an ---author--- section for
|
||||
each author. Each should start with ---author--- line, and
|
||||
should be found between the ---entry--- and ---build--- sections.
|
||||
|
||||
* The home page URL in the ---author--- section must be fully
|
||||
qualified or must be the word `none'.
|
||||
|
||||
* The entry's remarks should include:
|
||||
- note if this entry is a re-submission of a previous entry.
|
||||
- what this program does
|
||||
- how to run the program (sample args or input)
|
||||
- special compile or execution instructions, if any
|
||||
- special filename requirements (see rule 4 and 5)
|
||||
- information about any ---info--- files
|
||||
- why you think the program is obfuscated
|
||||
- any other remarks (humorous or otherwise)
|
||||
|
||||
* Do not rot13 your entry's remarks. You may suggest that certain
|
||||
portions of your remarks be rot13ed if your entry wins an award.
|
||||
|
||||
* Info files should be used only to supplement your entry. They
|
||||
should not be required to exist.
|
||||
|
||||
* If your entry does not need an info file, skip the ---info---
|
||||
section. If your entry needs multiple info files, use multiple
|
||||
---info--- sections, one per info file. You should describe
|
||||
each info file in the ---remark--- section.
|
||||
|
||||
* Your sections must in the same order as in the above template.
|
||||
|
|
||||
* The size limits of the program source apply to the decoded version |
|
||||
of the ---program--- section. |
|
||||
|
||||
4) If your entry is selected as a winner, it will be modified as follows:
|
||||
|
||||
'build' is incorporated into a makefile, and 'build' is removed
|
||||
'prog.c' is renamed to your entry's title, followed by an optional
|
||||
digit, followed by '.c'
|
||||
your entry is compiled into a file with the name of your entry's
|
||||
title, possibly followed by a digit
|
||||
|
||||
If your entry requires that a build file exist, state so in your
|
||||
entry's remark section. The makefile will be arranged to execute a
|
||||
build shell script containing the 'build' information. The name of
|
||||
this build shell script will be your entry's title, possibly followed
|
||||
by a digit, followed by '.sh'.
|
||||
|
||||
If needed, your entry's remarks should indicate how your entry must
|
||||
be changed in order to deal with the new filenames.
|
||||
|
||||
5) The build file, the source and the resulting executable should be
|
||||
treated as read-only files. If your entry needs to modify these files,
|
||||
it should make and modify a copy of the appropriate file. If this
|
||||
occurs, state so in your entry's remarks.
|
||||
|
||||
6) The uudecoded ---program--- section must be able to be compiled
|
||||
cleanly by an ANSI C compiler, or if there are any compile errors,
|
||||
they must be documented in the ---remark--- section.
|
||||
|
||||
7) The program must be of original work. All submitted programs are |
|
||||
are thereby put in the public domain. All explicitly copyrighted |
|
||||
programs will be rejected. |
|
||||
|
||||
8) Entries must be received prior to 01-Dec-2001 23:59:59 UTC. (UTC is |
|
||||
essentially equivalent to Greenwich Mean Time) EMail your entries to:
|
||||
|
||||
entry@ioccc.org
|
||||
|
|
||||
You must include the words ``ioccc entry'' in the subject |
|
||||
of your EMail when sending in your entry! Failure to do so may |
|
||||
result in the loss of your entry! !
|
||||
|
||||
If possible, we request that you hold off on EMailing your entries
|
||||
until 01-Oct-2001 00:00 UTC. Early entries will be accepted, however. |
|
||||
We will attempt to EMail a confirmation to the sender of any entry
|
||||
received after 01-Oct-2001 00:00 UTC and before the close |
|
||||
of the contest.
|
||||
|
||||
9) Each person may submit up to 8 entries per contest year. Each entry
|
||||
must be sent in a separate EMail letter.
|
||||
|
||||
10) Entries requiring human interaction to be built are not allowed.
|
||||
|
||||
11) Programs that require special privileges (setuid, setgid, super-user,
|
||||
special owner or group) are not allowed.
|
||||
|
||||
12) Legal abuse of the rules is somewhat encouraged. An entry that, in
|
||||
the opinion of the judges, violates the rules will be disqualified.
|
||||
Entries that attempt to abuse the rules must try to justify why
|
||||
their rule abuse is legal in the ---remark--- section.
|
||||
|
|
||||
13) Your source may not contain unescaped octets with the high bit set. |
|
||||
I.e., your source may not contain octet values between 128 and 255. |
|
||||
|
|
||||
14) Any program that fails to compile because of lines with trailing |
|
||||
control-M's (\r or \015) will be rejected. |
|
||||
|
||||
|
||||
FOR MORE INFORMATION:
|
||||
|
||||
The judging will be done by Leonid A. Broukhis, Simon Cooper, Landon |
|
||||
Curt Noll and Peter Seebach. Please send questions or comments
|
||||
about the contest, to:
|
||||
|
||||
questions@ioccc.org (not the address for submitting entries)
|
||||
|
||||
You must include the words ``ioccc question'' in the subject of your |
|
||||
EMail message when sending EMail to the judges. |
|
||||
|
||||
The rules and the guidelines may (and often do) change from year to
|
||||
year. You should be sure you have the current rules and guidelines
|
||||
prior to submitting entries. To obtain them, visit the IOCCC web page:
|
||||
|
||||
http://www.ioccc.org
|
||||
|
||||
It has rules, guidelines and winners of previous contests (1984 to date).
|
||||
|
|
||||
NOTE: A copy of the mkentry program may be found at: |
|
||||
|
|
||||
http://www.ioccc.org/official/mkentry.c |
|
||||
@@ -0,0 +1 @@
|
||||
main(int c,char**v){return!m(v[1],v[2]);}m(char*s,char*t){return*t-42?*s?63==*t|*s==*t&&m(s+1,t+1):!*t:m(s,t+1)||*s&&m(s+1,t);}
|
||||
@@ -0,0 +1,73 @@
|
||||
Best one-liner:
|
||||
|
||||
Jens Schweikhardt
|
||||
Marconi Communications
|
||||
Schlartaeckerweg 3
|
||||
D-71384 Weinstadt
|
||||
Germany
|
||||
|
||||
http://www.schweikhardt.net/
|
||||
|
||||
|
||||
Judges' Comments:
|
||||
|
||||
To build:
|
||||
|
||||
make schweikh
|
||||
|
||||
Try:
|
||||
|
||||
./schweikh foo 'f??'; echo $?
|
||||
./schweikh 'best short program' '??st*o**p?*'; echo $?
|
||||
./schweikh bar 'f??'; echo $?
|
||||
|
||||
Do you get the pattern here?
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
This one-liner program is a glob pattern matcher. It understands
|
||||
the glob characters `*' meaning `zero or more characters' and
|
||||
`?' meaning exactly one character, just like your unix shell.
|
||||
|
||||
Run it with two args, the string and the glob pattern. The exit
|
||||
status is 0 (shell true) when the pattern matches, 1 otherwise.
|
||||
The glob pattern must match the whole string, so you may want to
|
||||
use * at the beginning and end of the pattern if you are looking
|
||||
for something in the middle.
|
||||
|
||||
You can use it for your shell scripting needs similar to a silent grep
|
||||
(and without stdout redirected to /dev/null):
|
||||
|
||||
if prog "${VARIABLE}" '<glob>'; then
|
||||
echo VARIABLE matches
|
||||
else
|
||||
echo no match
|
||||
fi
|
||||
|
||||
Bugs: there is no way to escape the meta characters. Dammit Jim, I'm a
|
||||
one-liner, not a regexp lib.
|
||||
|
||||
All obfuscation is obviously in the recursive m() function, an 86
|
||||
character glob pattern evaluator, returning nonzero for a match:
|
||||
* just a single complex return expression.
|
||||
* nested ternary operator ?: to save on if/else verbosity.
|
||||
* short circuiting && and || to save even more on if/else verbosity.
|
||||
* Subtraction instead of an equality operator in "*t - 42".
|
||||
* ASCII codes for '*' and '?'.
|
||||
* careful use of blanks even though this year's rules have extended
|
||||
that resource limit.
|
||||
* the source is a complete preprocessed C program. Because it communicates
|
||||
with the world out there by means of argv and the exit status, there
|
||||
is no need for stdio bloat. An asm guru could surely squeeze this
|
||||
program in less than a screenful.
|
||||
* indent(1) is probably not too helpful.
|
||||
|
||||
The recursion wonderfully and magically takes care of iteration and
|
||||
backtracking. I could tell you how it works but then I would have to
|
||||
kill^Wrequest an NDA from you :-) Run it under a debugger with several
|
||||
inputs, it will be quite helpful and instructive. Handling of '?' is
|
||||
straightforward; for '*' start out with '*foo' and 'foo*' against 'foo'.
|
||||
How does it deal with sequences of adjacent `*'? How could this be
|
||||
improved? If all else fails, recode the ?: operators with if/else and
|
||||
try again. For extra credit implement character classes like [a-z].
|
||||
@@ -0,0 +1,37 @@
|
||||
main(i)??<char c??(81??)??(81??);for(i=0;gets(*(c+i)); i++);A(i,c);J(i-1,c);??>
|
||||
/* { /KC 0000 K } */
|
||||
S(c,r,i)char*c; ??<printf("|");for(;*(c+i); i++)putchar(T(*(c+i),r));U(c,i);??>
|
||||
|
||||
char* B,*r; X(c,k)??<return isupper(c)?0:V(*(r+k),B); ??>
|
||||
J(i,c,j)char*c; ??<for(j=t(i,0) ; j+j<i; j++)L(c,j,i-j); M(i,c); ??>
|
||||
U(c,i)char*c; ??<while(i++<80)printf(" "); puts("|"); ??>
|
||||
|
||||
A(i ,c,j ,k) char *c; ??< for(j= -1; ++j<i; )for (k =j; k<i; )D(c ,j, k++); ??>
|
||||
R(c,r) char *c; ??< printf( "/%-80s|??/n" ,c); for (; r< 13; r++)S (c,r,0); ??>
|
||||
t(a,b)??<return a;??>
|
||||
|
||||
M(i,c)char c??(81??)??(81??);??<i++;while(i--)t(1,0)?puts(*(c+i)):P(*(c+i));??>
|
||||
char*d= "yyzzyzz zz z0y000 zz 00yzz00y00yzz Brian Westley zyy00yy0yy 0" ; ; ;
|
||||
#define t(a,b) t(b,a)
|
||||
|
||||
char* K;Y (c ,r) ??< int i=V ( tolower (c) ,K); return(i <0)?1 :Z(c ,r, i); ??>
|
||||
char*m= "7831734578 9547693564569528334164263z284106579 52626423135477"; ; ; ;
|
||||
P(c)char*c; ??<Q(1,0); R(c,1 ); Q(0,0); ??>
|
||||
|
||||
char* d,*m,*B; Z(c,i,k)??<return W(i, V(*(d+k), B),V(*( m+k),B) ,X(c, k)); ??>
|
||||
char*K= "gh$j|lm'pq&rv<x>z#);@_winky,.%/+*!=3-284106579 (:obfuscated??/?" ; ;
|
||||
L(c,i,j)char c??(81??)??(81??);??<G(* (c+i),*(c+j));??>
|
||||
char*r= "008y8yy8yyyyz8z8z88888z0yyz888 8888 88y00zz00z0088";
|
||||
D(c,i,j) char c??(81??)??(81??);??<E(*(c+i),*(c+j));??>
|
||||
|
||||
E(r,s)char*r,*s; ??< if(t( 0,1)&& F(r,s)<0)G(r,s); ??>
|
||||
H()??<static i=0; if (!i) ??< time(&i); srand(i); ??> return rand()-rand(); ??>
|
||||
F(r,s)char*r,*s; ??<return t(0,1)?H():strcmp(r,s); ??>
|
||||
|
||||
T(c,r) ??< return Y(c, r)?'??(' :' '; ??>
|
||||
G(r,s)char*r,*s; ??<char t??( 81??); strcpy(t,r); strcpy(r,s); strcpy(s,t); ??>
|
||||
W(r,a,b,c)??<return r==a||r==b||r==c; ??>
|
||||
|
||||
Q(t,i)??< printf(t?" ":"|"); for(; i<80; i++) printf("_"); puts(t?"_":"|"); ??>
|
||||
char*B=" yz0123456789";
|
||||
V(c,k,i) char*k; ??<for (i=0; *(k+i) &&*(k+i)!=c; i++); return *(k+i)?i:-1; ??>
|
||||
@@ -0,0 +1,155 @@
|
||||
Best position-independent code:
|
||||
|
||||
Brian Westley
|
||||
Firesign Theatre webmaster
|
||||
1906 James Ave
|
||||
St. Paul, MN 55105
|
||||
USA
|
||||
|
||||
http://www.firesigntheatre.com
|
||||
|
||||
|
||||
Judges' Comments:
|
||||
|
||||
To build:
|
||||
|
||||
make westley
|
||||
|
||||
Try:
|
||||
|
||||
./westley < westley.c > westley2.c
|
||||
cc westley2.c -ansi -o westley2
|
||||
echo 'Bozos, please deflate shoes before entering the bus!'| ./westley2
|
||||
sort -b < westley2.c > westley3.c
|
||||
cc westley3.c -ansi -o westley3
|
||||
./westley3 < westley.c | diff - westley.c
|
||||
./westley3 < westley.c | diff - westley2.c
|
||||
./westley3 < westley.c | diff - westley3.c
|
||||
|
||||
Try copying the source to a new file and changing around the
|
||||
order of the lines. Does it produce the exact same output?
|
||||
|
||||
By changing the order of the source, figure out in how many different
|
||||
ways this program can transform input to output.
|
||||
|
||||
NOTE: The entry has been modified for portability reasons. The
|
||||
original source may be found in the westley.orig.c file.
|
||||
|
||||
This assortment obfuscated lines takes position-independant code
|
||||
to a new level! :-)
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
Punch cards, or Hollerith cards, were becoming obsolete just
|
||||
as C was becoming more popular*; this is rather unfortunate,
|
||||
because C has an advantage over many other languages when it
|
||||
comes to punch cards - C programs can be written to be "drop
|
||||
proof".
|
||||
|
||||
Consider the following C program:
|
||||
|
||||
main(){a();b();c();}
|
||||
a(){printf("A");}
|
||||
b(){printf("B");}
|
||||
c(){printf("C");}
|
||||
|
||||
This program will compile and run no matter what order the
|
||||
lines are in. If you punch it on cards (one line of code per
|
||||
card, naturally) and drop them, you don't need to put them in
|
||||
any particular order**; it will always produce "ABC" as output.
|
||||
|
||||
You can also use global variables:
|
||||
|
||||
char *greet = "Hello, world!";
|
||||
char *greet; main(){puts(greet);}
|
||||
|
||||
It would be trivial to write an entire C program that is
|
||||
"drop proof" using the above techniques; surprisingly, it's
|
||||
possible to write a program that will always compile but
|
||||
behave differently depending on the line order:
|
||||
|
||||
test(a,b){return a;}
|
||||
#define test(a,b) test(b,a)
|
||||
main(){if (test(0,1)) printf("T"); else printf("F");}
|
||||
|
||||
This program will print out "T" if the #define statement
|
||||
falls between the declaration of test() and its use in
|
||||
main(), otherwise it will print out "F". Furthermore,
|
||||
you can use the same call to test() repeatedly in
|
||||
different lines to return different values:
|
||||
|
||||
#define test(x,y) test(y,x)
|
||||
main(){int i=0;a(&i);b(&i);c(&i);d(&i);printf("%d\n",i);}
|
||||
a(i)int*i;{if (test(0,1)) *i += 1;}
|
||||
b(i)int*i;{if (test(0,1)) *i += 2;}
|
||||
c(i)int*i;{if (test(0,1)) *i += 4;}
|
||||
d(i)int*i;{if (test(0,1)) *i += 8;}
|
||||
test(x,y){return x;}
|
||||
|
||||
If you enter the above program on punch cards, throw them
|
||||
up in the air, gather them up, and run it, you will get
|
||||
a number from 0 to 15 printed out. Now *that's* a random
|
||||
number generator...
|
||||
|
||||
Of course, there are drawbacks to C programming on punch
|
||||
cards; an 80-character line limit can be restricting, and
|
||||
(to be maximally portable) you need to use trigraphs for
|
||||
the characters "^[]{}\" (these aren't found on every
|
||||
keypunch, and have various encodings).
|
||||
|
||||
My C program entry does the following:
|
||||
|
||||
1) reads in lines
|
||||
2) rearranges the lines, or not
|
||||
2a) if it rearranges the lines, they are sorted or scrambled
|
||||
3) reverses the order of the lines, or not
|
||||
4) prints out the lines as either text or EBCDIC punch cards.
|
||||
|
||||
The code, as written, scrambles the input and prints it out
|
||||
as normal text, so you can simulate 'dropping' the cards.
|
||||
You can repeatedly scramble the code to get all 12 variants
|
||||
(but the scrambling isn't very random; it's just a bubble
|
||||
sort with a random number, so some variants are more common
|
||||
than others). You can also just swap the arguments in the
|
||||
calls to t() in all combinations to get all the variations.
|
||||
|
||||
If you sort the lines, you will get the version that just
|
||||
prints out the input as punch cards (you will need to display
|
||||
at least 82 columns of text, or clip the last few chars by
|
||||
piping it through "sed s/...$//"). If you use this on the
|
||||
original code, you will see that it spells out "HOLLERITH"
|
||||
when punched on cards (you can see the tall, thin letters
|
||||
spelling out "HOLLERITH" if you turn the C code sideways).
|
||||
You will also see why "/KC 0000 K" is a "Hollerith emoticon".
|
||||
Unrecognized characters are punched as a lace column.
|
||||
(You can see an ASCII simulation of the code as punch cards
|
||||
by looking at card.gif)
|
||||
|
||||
For a nice test pattern, try
|
||||
&-0123456789ABCDEFGHIJKLMNOPQR/STUVWXYZ:#@'=".<(+|!$*);,%_>?abcmnoxyz^[]{}\
|
||||
|
||||
If you want to analyze the program, sorting the lines while
|
||||
ignoring leading blanks works best (sort -b). This will
|
||||
produce the version that just reverses the line order, and
|
||||
the routines in the code are in a sensible order.
|
||||
|
||||
This program should work on EBCDIC computers. It assumes
|
||||
that the time_t ptr param to time() will work with an int
|
||||
ptr, and that "passing through" a char[][] array as a simple
|
||||
char* is ok. Your compiler MUST understand trigraphs, or it
|
||||
will miss the trigraph backslash before the double quote in
|
||||
the K string and complain about a malformed string; for GNU
|
||||
C, use -ansi or -trigraphs. Entering a line of more than 80
|
||||
characters, or more than 81 lines, will jam the card reader.
|
||||
|
||||
I've used the a[b] ==> *(a+b) trick, because this is
|
||||
actually shorter than the trigraph version of a??(b??).
|
||||
|
||||
With 28 lines of code (not counting the blank lines or the
|
||||
comment), there are technically 28! different programs, or
|
||||
304,888,344,611,713,860,501,504,000,000 different versions,
|
||||
all legal C.
|
||||
|
||||
*except in Florida voting machines
|
||||
**all cards must be face down, nine-edge first, of course.
|
||||
@@ -0,0 +1,37 @@
|
||||
main(i)??<char c??(81??)??(81??);for(i=0;gets(*(c+i)); i++);A(i,c);J(i-1,c);??>
|
||||
/* { /KC 0000 K } */
|
||||
S(c,r,i)char*c; ??<printf("|");for(;*(c+i); i++)putchar(T(*(c+i),r));U(c,i);??>
|
||||
|
||||
char* B,*r; X(c,k)??<return isupper(c)?0:V(*(r+k),B); ??>
|
||||
J(i,c,j)char*c; ??<for(j=t(i,0) ; j+j<i; j++)L(c,j,i-j); M(i,c); ??>
|
||||
U(c,i)char*c; ??<while(i++<80)printf(" "); puts("|"); ??>
|
||||
|
||||
A(i ,c,j ,k) char *c; ??< for(j= -1; ++j<i; )for (k =j; k<i; )D(c ,j, k++); ??>
|
||||
R(c,r) char *c; ??< printf( "/%-80s|??/n" ,c); for (; r< 13; r++)S (c,r,0); ??>
|
||||
t(a,b)??<return a;??>
|
||||
|
||||
M(i,c)char c??(81??)??(81??);??<i++;while(i--)t(1,0)?puts(*(c+i)):P(*(c+i));??>
|
||||
char*d= "yyzzyzz zz z0y000 zz 00yzz00y00yzz Brian Westley zyy00yy0yy 0" ; ; ;
|
||||
#define t(a,b) t(b,a)
|
||||
|
||||
char* K;Y (c ,r) ??< int i=V ( tolower (c) ,K); return(i <0)?1 :Z(c ,r, i); ??>
|
||||
char*m= "7831734578 9547693564569528334164263z284106579 52626423135477"; ; ; ;
|
||||
P(c)char*c; ??<Q(1,0); R(c,1 ); Q(0,0); ??>
|
||||
|
||||
char* d,*m,*B; Z(c,i,k)??<return W(i, V(*(d+k), B),V(*( m+k),B) ,X(c, k)); ??>
|
||||
char*K= "gh$j|lm'pq&rv<x>z#);@_winky,.%/+*!=3-284106579 (:obfuscated??/"?" ; ;
|
||||
L(c,i,j)char c??(81??)??(81??);??<G(* (c+i),*(c+j));??>
|
||||
char*r= "008y8yy8yyyyz8z8z88888z0yyz888 8888 88y00zz00z0088";
|
||||
D(c,i,j) char c??(81??)??(81??);??<E(*(c+i),*(c+j));??>
|
||||
|
||||
E(r,s)char*r,*s; ??< if(t( 0,1)&& F(r,s)<0)G(r,s); ??>
|
||||
H()??<static i=0; if (!i) ??< time(&i); srand(i); ??> return rand()-rand(); ??>
|
||||
F(r,s)char*r,*s; ??<return t(0,1)?H():strcmp(r,s); ??>
|
||||
|
||||
T(c,r) ??< return Y(c, r)?'??(' :' '; ??>
|
||||
G(r,s)char*r,*s; ??<char t??( 81??); strcpy(t,r); strcpy(r,s); strcpy(s,t); ??>
|
||||
W(r,a,b,c)??<return r==a||r==b||r==c; ??>
|
||||
|
||||
Q(t,i)??< printf(t?" ":"|"); for(; i<80; i++) printf("_"); puts(t?"_":"|"); ??>
|
||||
char*B=" yz0123456789";
|
||||
V(c,k,i) char*k; ??<for (i=0; *(k+i) &&*(k+i)!=c; i++); return *(k+i)?i:-1; ??>
|
||||
@@ -0,0 +1,73 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <unistd.h>
|
||||
typedef long O; typedef struct { O b,f,u,s,c,a,t,e,d; } C;
|
||||
Display *d; Window w; GC g; XEvent e;
|
||||
char Q[] = "Level %d Score %d", m[222];
|
||||
#define N(r) (random()%(r))
|
||||
#define U I[n++]=L[n]=l; n%=222
|
||||
#define K c=-l.u; l=I[i]; l.t=0; c+=l.u
|
||||
#define E l.e--&&!--L[l.e].d&&(L[l.e].t=3)
|
||||
#define M(a,e,i,o) a[0]=e,(a[1]=i)&&XFillPolygon(d,w,g,(void*)a,o,1,1)
|
||||
#define F return
|
||||
#define R while(
|
||||
#define Y if(l.t
|
||||
|
||||
|
||||
O p ,B,
|
||||
D,A=6,Z ,S=0,v=
|
||||
0,n=0,W=400 ,H=300,a[7]
|
||||
={ 33,99, 165, 231,297,363} ;
|
||||
XGCValues G={ 6,0 ,~0L,0,1} ; short
|
||||
T[]={ 0,300,-20,0,4 ,-20,4,10,4,-5,4,5,
|
||||
4,-20,4,20,4,-5,4,5,4, -10,4,20},b[]={ 0,0,4,
|
||||
0,-4,4,-4,-4,4,-4,4,4} ; C L[222],I[222];dC(O x){
|
||||
M(T,a[x],H,12); } Ne(C l,O s) { l.f=l.a=1; l.b=l.u=s;
|
||||
l.t=16; l.e=0; U; } nL(O t,O a,O b,O x,O y,O s,O p){ C l;
|
||||
l.d=0; l.f=s; l.t=t; y-=l.c=b; l.e=t==2?x:p; x-=l.s=a;s=(x|1)
|
||||
%2*x; t=(y|1)%2*y; l.u=(a=s>t?s: t)>>9;l.a=(x<<9)/a;l.b=(y<<9)/a;
|
||||
U; } di(C I){ O p,q,r,s,i=222;C l; B=D=0; R i--){ l=L[i]; Y>7){ p=I.s
|
||||
-l.s>>9; q=I.c-l.c>>9; r=l.t==8?l.b: l.a; s=p*p+q*q; if(s<r*r||I.t==2&&s<
|
||||
26) F S+=10; s=(20<<9)/(s|1); B+=p*s; D+=q*s; }} F 0; } hi(O x,O d){ O i=A;
|
||||
R i--&&(x<a[i]-d||x>a[i]+d)); F i; } dL(){ O c,r=0, i=222,h; C l; R i--){ l=L[i];
|
||||
Y){ r++;c=l.f; Y==3){c=l.u; l.t=0; E; }R c--){-- l.u;h=l.c>>9; Y>7){XDrawArc(d,w,g,
|
||||
(l.s>>9)-++l.a,h-l.a,l.a*2,l.a*2,0 ,90<<8); if(!l.u){ I[i].t-=8; l=I[i]; } } else Y==2)M
|
||||
(b,l.s>>9,h,6); else XDrawPoint(d ,w,g,(l.s+=l.a)>>9, h=(l.c+=l.b)>>9); Y==4&&!l.u){ Ne
|
||||
(l,20); K; } Y&&l.t<3&&(di(l)||h> H)){ if(h>H&&(c=hi( l.s>>9,25))>=0){ dC(c); a[c]=a[--
|
||||
A]; }Ne(l,30); Y==1){ E;K; } else c=l.t=0;} Y==1&&h<H -75&&!N(p*77)){ do{ nL(1,l.s,l.c,
|
||||
N(W<<9),H<<9,1,i+
|
||||
1); I[i].d++;
|
||||
}R N(3)
|
||||
|
||||
); K;
|
||||
l.u=c; c=0; } Y
|
||||
==2){ l.s+=l.a+B;
|
||||
l.a= (l.e-l.s)/((H+
|
||||
20-h)|1); l.c+=l.b+D;
|
||||
M(b,l.s>>9,l.c>>9,6); }
|
||||
} L[i]=l; } } F r; } J(){
|
||||
R A) { XFlush(d); v&&sleep(
|
||||
3); Z=++v*10; p=50-v; v%2&&hi
|
||||
((a[A]=N(W-50)+25),50)<0 &&A++;
|
||||
XClearWindow (d,w); for(B=0; B<A;
|
||||
dC(B++)); R Z|dL()){ Z&&!N(p)&&(Z--
|
||||
,nL(1+!N(p),N(W<<9), 0,N(W<<9),H<<9,1
|
||||
,0)); usleep(p*200); XCheckMaskEvent(d,
|
||||
4,&e)&&A&&--S&&nL(4,a[N(A)]<<9,H-10<<9,e.
|
||||
xbutton.x<<9,e.xbutton.y<<9,5,0);}S+=A*100;
|
||||
B=sprintf(m,Q,v,S); XDrawString(d,w
|
||||
,g,W/3,H/2,m,B); } }
|
||||
|
||||
main ()
|
||||
{
|
||||
O i=2;
|
||||
d=XOpenDisplay(0);
|
||||
w=RootWindow(d,0);
|
||||
R i--) XMapWindow(d,w=XCreateSimpleWindow(d,w,0,0,W,H,0,0,0));
|
||||
XSelectInput(d,w,4|1<<15);
|
||||
XMaskEvent(d,1<<15,&e);
|
||||
g=XCreateGC(d,w,829,&G);
|
||||
srandom(time(0));
|
||||
J();
|
||||
puts(m);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
Best Graphic Game:
|
||||
|
||||
John Williams
|
||||
941 E 25 S
|
||||
Lindon UT 84042
|
||||
USA
|
||||
|
||||
|
||||
Judge's Remarks:
|
||||
|
||||
To build:
|
||||
|
||||
make williams
|
||||
|
||||
Try:
|
||||
|
||||
./williams
|
||||
|
||||
The only way to win is not to play. No, really; you can't actually win.
|
||||
:)
|
||||
|
||||
The formatting really wants a wide screen; if you can't read it that way,
|
||||
it's the standard "three triangles around a circular" logo for nukes.
|
||||
|
||||
This is a pretty straightforward game.
|
||||
|
||||
|
||||
Selected Author's Comments:
|
||||
|
||||
What this program does:
|
||||
|
||||
It plays Missile Command, complete with MIRVs, smart bombs,
|
||||
extra cities, and scoring.
|
||||
|
||||
Command line arguments and input files are ignored.
|
||||
|
||||
To play, just point and click where you want your ABMs to explode.
|
||||
|
||||
The score is 10 points for each missile which is destroyed before
|
||||
it reaches the ground, -1 point for each ABM used, and 100 bonus
|
||||
points for each city left at the end of a level.
|
||||
|
||||
The game ends when you lose all your cities, although you will have
|
||||
to wait until the level finishes raining down to see your final score.
|
||||
|
||||
|
||||
|
||||
The main obfuscation technique is the need to compress the code to fit
|
||||
all the functionality within the size limits. I could not have included
|
||||
smart bombs without the rule excluding { } ; characters in the counts.
|
||||
All of the #defines are there to reduce code size.
|
||||
|
||||
On the other hand, I did waste a few characters in order to include
|
||||
some rather obfuscated math in the program. It uses fixed-point
|
||||
arithmetic, resulting in the overuse of bitwise shift operators.
|
||||
Another example is (x|1), which is used in a couple different ways.
|
||||
The purpose of A/(x|1) is probably obvious, but what does (x|1)%2 do?
|
||||
|
||||
Reference in new issue
Block a user