Carl Banks' Blog

Viewing single post

IOCCC Flight Simulator

Be sure to visit our Facebook Page.

The IOCCC Flight Simulator was the winning entry in the 1998 International Obfuscated C Code Contest. It is a flight simulator in under 2 kilobytes of code, complete with relatively accurate 6-degree-of-freedom dynamics, loadable wireframe scenery, and a small instrument panel.

IOCCC Flight Simulator runs on Unix-like systems with X Windows. As per contest rules, it is in the public domain.

Documentation

Introduction

You have just stepped out of the real world and into the virtual. You are now sitting in the cockpit of a Piper Cherokee airplane, heading north, flying 1000 feet above ground level.

Use the keyboard to fly the airplane. The arrow keys represent the control stick. Press the Up Arrow key to push the stick forward. Press the left arrow key to move the stick left, and so on. Press Enter to re-center the stick. Use Page Up and Page Down increase and decrease the throttle, respectively. (The rudder is automatically coordinated with the turn rate, so rudder pedals are not represented.)

On your display, you will see on the bottom left corner three instruments. The first is the airspeed indicator; it tells you how fast you're going in knots. The second is the heading indicator, or compass. 0 is north, 90 is east, 180 is south, 270 is west. The third instrument is the altimeter, which measures your height above ground level in feet.

Usage

To use, type:

cat horizon.sc pittsburgh.sc | ./banks

banks is the name of the program (a quirk of IOCCC rules, and no pun intended). horizon.sc and pittsburgh.sc are scenery files.

Features

  • Simulator models a Piper Cherokee, which is a light, single-engine, propeller-driven airplane.
  • The airplane is modeled as a six degree-of-freedom rigid body, accurately reflecting its dynamics (for normal flight conditions, at least).
  • Fly through a virtual 3-D world, while sitting at your X console.
  • Loadable scenery files.
  • Head-up display contains three instruments: a true airspeed indicator, a heading indicator (compass), and an altimeter.
  • Flight controls may be mapped to any keys at compile time by redefining the macros in the build file. Nice if your keyboard doesn't have arrow keys.
  • Time step size can be set at compile time. This is useful to reduce flicker on network X connections. (But be careful: step sizes longer than about 0.03 seconds tend to have numerical stability problems.)
  • Airplane never stalls!
  • Airplane never runs out of fuel!

Scenery

Each of the *.sc files is a scenery file. The simulator program reads in the scenery from standard input on startup. You may input more than one scenery file, as long as there are less than 1000 total lines of input.

Here is a brief description of the scenery files:

  • horizon.sc - A horizon, nothing more. You will probably always want to input this piece of scenery.
  • mountains.sc - An alternate horizon; a little more mountainous.
  • pittsburgh.sc - Scenery of downtown Pittsburgh. The downtown area is initially located to your right.
  • bb.sc - Simple obstacle course. Try to fly over the buildings and under the bridges.
  • pyramids.sc - Fly over the tombs of the ancient Pharaohs in this (fictitious) Egyptian landscape.
  • river.sc - Follow a flowing river from the sky.

A few examples of how to input scenery:

cat horizon.sc pittsburgh.sc | ./banks
cat mountains.sc bb.sc | ./banks
cat mountains.sc river.sc pyramids.sc | ./banks

You can simulate flying through a cloud bank as well:

./banks < /dev/null

You will usually want at least a horizon, though.

The format of scenery files is simple, by the way. They're just a list of 3-D coordinates, and the simulator simply draws line segments from point to point as listed in the scenery file. 0 0 0 is used to end a series of consecutive line segments. Note that in the coordinate system used, the third coordinate represents altitude in a negative sense: negative numbers are positive altitudes.

I'm sure you'll be making your own scenery files very soon!!!

Alternate Build Instructions

Several options must be passed to the compiler to make the build work. The provided build file has the appropriate options set to default values. Use this section if you want to compile with different options.

To map a key to a control, you must pass an option to the compiler in the format "-Dcontrol=key". The possible controls you can map are described in the table below:

Control  Description           Default Key
-------  --------------------- -----------
IT       Open throttle         XK_Page_Up
DT       Close throttle        XK_Page_Down
FD       Move stick forward    XK_Up
BK       Move stick back       XK_Down
LT       Move stick left       XK_Left
RT       Move stick right      XK_Right
CS       Center stick          XK_Enter

Values for the possible keys can be found in the X Windows header file <X11/keysym.h>. This file is most likely a cross-reference to another header, <X11/keysymdef.h>.

You must map all seven controls to keys at compile time, or the compilation will fail.

For example, to map Center Stick to the space-bar, the compile option would be "-DCS=XK_space".

To set the time step size, you must pass the following option to the compiler: "-Ddt=duration", where dt is literal, and where duration is the time in seconds you want the time step to be.

Two things to keep in mind when selecting a time step. Time steps that are too large (more than about 0.03) will cause numerical stability problems and should be avoided. Setting the time step to be smaller than your clock resolution will slow down the simulator, because the system pauses for more time than the simulator expects.

The best advice is to set time step size to your system timer resolution. Try a longer period if you're getting too much flicker.

Screen Shots

Here we are flying towards Downtown Pittsburgh. We can see the Point, several buildings including the USX tower, and several bridges including the Smithfield Street bridge. We see three instruments near the bottom.

http://www.aerojockey.com/images/ioccc1.gif

About the IOCCC Entry

IOCCC stands for "International Obfuscated C Code Contest." It is an quasi-annual contest to see who can write the most unreadable, unintelligible, unmanagable, but legal C program.

In the 1998 IOCCC, My flight simulator won the "Best of Show" prize. Here is the source code to the program:

#include                                     <math.h>
#include                                   <sys/time.h>
#include                                   <X11/Xlib.h>
#include                                  <X11/keysym.h>
                                          double L ,o ,P
                                         ,_=dt,T,Z,D=1,d,
                                         s[999],E,h= 8,I,
                                         J,K,w[999],M,m,O
                                        ,n[999],j=33e-3,i=
                                        1E3,r,t, u,v ,W,S=
                                        74.5,l=221,X=7.26,
                                        a,B,A=32.2,c, F,H;
                                        int N,q, C, y,p,U;
                                       Window z; char f[52]
                                    ; GC k; main(){ Display*e=
 XOpenDisplay( 0); z=RootWindow(e,0); for (XSetForeground(e,k=XCreateGC (e,z,0,0),BlackPixel(e,0))
; scanf("%lf%lf%lf",y +n,w+y, y+s)+1; y ++); XSelectInput(e,z= XCreateSimpleWindow(e,z,0,0,400,400,
0,0,WhitePixel(e,0) ),KeyPressMask); for(XMapWindow(e,z); ; T=sin(O)){ struct timeval G={ 0,dt*1e6}
; K= cos(j); N=1e4; M+= H*_; Z=D*K; F+=_*P; r=E*K; W=cos( O); m=K*W; H=K*T; O+=D*_*F/ K+d/K*E*_; B=
sin(j); a=B*T*D-E*W; XClearWindow(e,z); t=T*E+ D*B*W; j+=d*_*D-_*F*E; P=W*E*B-T*D; for (o+=(I=D*W+E
*T*B,E*d/K *B+v+B/K*F*D)*_; p<y; ){ T=p[s]+i; E=c-p[w]; D=n[p]-L; K=D*m-B*T-H*E; if(p [n]+w[ p]+p[s
]== 0|K <fabs(W=T*r-I*E +D*P) |fabs(D=t *D+Z *T-a *E)> K)N=1e4; else{ q=W/K *4E2+2e2; C= 2E2+4e2/ K
 *D; N-1E4&& XDrawLine(e ,z,k,N ,U,q,C); N=q; U=C; } ++p; } L+=_* (X*t +P*M+m*l); T=X*X+ l*l+M *M;
  XDrawString(e,z,k ,20,380,f,17); D=v/l*15; i+=(B *l-M*r -X*Z)*_; for(; XPending(e); u *=CS!=N){
                                   XEvent z; XNextEvent(e ,&z);
                                       ++*((N=XLookupKeysym
                                         (&z.xkey,0))-IT?
                                         N-LT? UP-N?& E:&
                                         J:& u: &h); --*(
                                         DN -N? N-DT ?N==
                                         RT?&u: & W:&h:&J
                                          ); } m=15*F/l;
                                          c+=(I=M/ l,l*H
                                          +I*M+a*X)*_; H
                                          =A*r+v*X-F*l+(
                                          E=.1+X*4.9/l,t
                                          =T*m/32-I*T/24
                                           )/S; K=F*M+(
                                           h* 1e4/l-(T+
                                           E*5*T*E)/3e2
                                           )/S-X*d-B*A;
                                           a=2.63 /l*d;
                                           X+=( d*l-T/S
                                            *(.19*E +a
                                            *.64+J/1e3
                                            )-M* v +A*
                                            Z)*_; l +=
                                            K *_; W=d;
                                            sprintf(f,
                                            "%5d  %3d"
                                            "%7d",p =l
                                           /1.7,(C=9E3+
                              O*57.3)%0550,(int)i); d+=T*(.45-14/l*
                             X-a*130-J* .14)*_/125e2+F*_*v; P=(T*(47
                             *I-m* 52+E*94 *D-t*.38+u*.21*E) /1e2+W*
                             179*v)/2312; select(p=0,0,0,0,&G); v-=(
                              W*F-T*(.63*m-I*.086+m*E*19-D*25-.11*u
                               )/107e2)*_; D=cos(o); E=sin(o); } }

Note that this program will not compile out-of-the-box. It requires certain compile-time parameters. The folloing script builds it on my Linux system:

#! /bin/sh
cc banks.c -o banks -DIT=XK_Page_Up -DDT=XK_Page_Down \
        -DUP=XK_Up -DDN=XK_Down -DLT=XK_Left -DRT=XK_Right \
        -DCS=XK_Return -Ddt=0.02 -lm -lX11 -L/usr/X11R6/lib

If you want to try this program, I suggest you download the 1998 IOCCC Winners Distribution.

One of the rules of the contest was that the program could not be longer than 1536 bytes (excluding spaces, tabs, newlines, semicolons, and braces). Needless to say, cramming a flight simulator into such a small file was fairly difficult. I will say that if it weren't for the wonderful property of orthogonal matrices, this flight simulator would not have been possible.

Sightings

  • The IOCCC Simulator appeared in a book, Calculated Bets by Steve Skiena.
  • Wikipedia has a listing of IOCCC Simluator in its IOCCC Entry.

Downloads

I do not distribute this program myself. If you want it, you can download the 1998 IOCCC Winners Distribution. The distribution comes with a dozen or so other winning entries, all quite interesting programs.

Note that this is a source distribution, and you will have compile it to run it. I've tested it on some versions of Linux, AIX, Irix, and Sun.

IOCCC Flight Simulator source code is in the public domain; there are no copyright restrictions on it whatsoever. However, the winners distribution has been copyrighted by the IOCCC judges. See the hint files in the distribution for details.

Tags: airplane, cb_software, flight_simulator, ioccc
Permalink: http://blog.aerojockey.com/post/iocccsim
Last Edited: 13 May 2012, 10:55 PM
No comments. - Add a comment.
Viewing single post