Dec 072017
This game lets you program "computer" controlled cars that race around a track. .
File RARS03.ZIP from The Programmer’s Corner in
Category Recently Uploaded Files
This game lets you program “computer” controlled cars that race around a track. .
File Name File Size Zip Size Zip Type
CAR.EXE 128914 57761 deflated
CAR.H 4527 1772 deflated
CAR.PRJ 6650 1583 deflated
CARZ.CPP 28601 8911 deflated
CIRCLE.TRK 1058 491 deflated
CNTRL0.CPP 9282 3403 deflated
CNTRL1.CPP 5234 1932 deflated
CNTRL2.CPP 3904 1348 deflated
CNTRL3.CPP 3418 1190 deflated
CNTRL4.CPP 3999 1385 deflated
CNTRL5.CPP 6754 2408 deflated
CNTRLH.CPP 3638 1374 deflated
EGAVGA.BGI 5554 4022 deflated
GRAPHICS.CPP 17163 4882 deflated
OVAL.TRK 1058 493 deflated
RARS03.ANN 4252 1986 deflated
RARS03.DOC 8784 3699 deflated
RUNALL.BAT 154 69 deflated
SPEED.TRK 1098 512 deflated
STEFFL.TRK 1206 564 deflated
TINYOVAL.TRK 1057 494 deflated
TPCREAD.ME 199 165 deflated
TRACK.CPP 3047 1174 deflated
TRACK.H 1438 695 deflated
TRACKFIL.TRK 1222 566 deflated
V01.TRK 1116 523 deflated
V02.TRK 1142 534 deflated
V03.TRK 1222 566 deflated

Download File RARS03.ZIP Here

Contents of the RARS03.DOC file

- RARS ver. 0.3 -
by Mitchell E. Timin
([email protected])

(RARS anonymous ftp site is, /bin/ftp/rars.)

(To subscribe to the RARS mailing list send the message:
"subscribe rars-list" to "[email protected]")

After unzipping, you should have these files:

CAR.H - the Car class and various structures
TRACK.H - some const and extern statements related to the race track
TRACK.CPP - the track definition software
GRAPHICS.CPP - all of the graphics interface. (makes Borland calls)
CARZ.CPP - everything else except the control programs for the cars
CNTRL?.CPP (? means 0 - 5) - six robot driver (control) programs
CNTRLH.CPP - Human Assisted Robot Driver (requires a joystick)
CAR.EXE - built from the above with Turbo C++ ver. 3.0 for DOS
EGAVGA.BGI - borland drivers (must be in directory with car.exe to run)
RARS03.DOC - this file
RARS03.ANN - The announcement about this version, and about RARS
CAR.PRJ - Borland C++ 3.1 project file
*.TRK - nine track definition files

We used the "medium" memory model to build car.exe. We used hardware
floating point, automatic far pointers, pre-compiled headers,
debugging info included in .obj, and Borland C++ language definition.
Your might have to experiment with Borland's options. When you write
your own driver you can use C or TASM or PASCAL if you want to. A
VGA or EGA display is assumed.

The command line is:

CAR [track file] [no. of cars] [no. of laps] [real speed]

If no track file is named, TRACKFIL.TRK will be used. The .TRK
extension is optional; it will be assumed if not typed.

If you just type "CAR" you will get 6 cars racing 4 laps at
simulated realistic speed.

"CAR 7" will get you 7 cars racing 4 laps at realistic speed.

"CAR 9 12" will get you 9 cars racing 12 laps at realistic speed.

"CAR SPEED 9 12" will be the same except the track is defined by
the file SPEED.TRK.

"CAR 9 12 XXX" will get you 9 cars racing 12 laps as fast as the
computer can compute. (The last argument can be anything at all
to cause the fast speed.) With many cars and a slow computer there
will be no difference between the speeds. With few cars and a fast
computer there is a big difference.

How to choose which "drivers" drive which cars:
This is done by editing the initialization for the drivers[] array,
which is near the start of CARZ.CPP. look for this line:

con_vec (*drivers[])(situation) = { // pointers to their control programs

This line is followed by names of the control functions. You don't
have to change it, but you might or might not want cntrlh in one of
the places. (cntrlh requires a joystick, it lets you steer that
car, although the throttle is automatic. It also uses a lot of CPU
time, noticable only if the command line requests high speed.

It is possible to run more cars than there are "drivers". This
requires that some of the drivers operate more than one car. This
works surprisingly well, but since the "driver" functions use static
variables their algorithms won't perform properly. What happens is
that the 2nd car changes the 1st car's variable, and vice-versa.
Therefore, if the drivers[] array only has six different drivers,
run your races with six cars or less for best results. If you really
want to run sixteen cars, I suggest you make a driver with no static
or global variables. This driver can then fill up all of the
unfilled positions in drivers[] after using one each of your regular
robot "drivers".

Some notes on the simulation:

The car is treated like a point mass moving under a time varying
force vector. This vector is the sum of an air drag force and a
track-to-wheel force. Also, the latter is far stronger in most
situations. We compute the track-to-wheel force by first computing
the slip vector of the tire slipping against the track. The
magnitude of the force depends on the magnitude of the slip vector.
(see friction() function in CARZ.CPP) The direction of the force is
parallel to the slip vector, but in the opposite direction.
Since there is no difference between front and rear wheels, this is
equivalent to a four-wheel drive car. (or a car with only one wheel!)

F = Ma gives us the vector acceleration, which is integrated to yield
the trajectory in the form of x(t), y(t), xdot(t) and ydot(t).
The angle of the cars path at any instant is given by the velocity
vector, whose components are xdot(t) and ydot(t).

It is assumed that the driver is always able to steer so as to orient
his vehicle approximately in the direction of the velocity vector.
Furthermore, the driver can control the angle alpha, which is the
deviation between the angle that the car is pointing and the velocity
vector. This angle, the slip angle, or angle of attack in
aeronautical terminology, affects the slip vector.

The other thing that the driver controls is the speed of the bottom of
the wheel relative to the car. He makes this larger than the cars
speed to increase the speed; He makes it smaller to decelerate. We
call the vc for "Velocity Commanded". (under some conditions the
cars speed will approach vc.)

To understand vc and alpha, remember that in this model, the wheels are
always slipping, at least a little. (Think of a cinder track.) vc is the
speed of the bottom of the wheel relative to the car. (Velocity
Commanded) If the car is coasting at zero power then vc == s.v, the speed
of the car. If vc is held constant for a while the car's speed will
approach vc, unless it is cornering, in which case vc may greatly exceed
the speed. The angle "alpha" is the angle between the car's orientation
angle and its velocity vector. (like angle of attack of an aircraft)
Cornering force depends on alpha. (It is also thought of as a slip
angle.) Alpha is not directly related to the steering wheel angle, which
is not modeled here, and is assumed to rapidly oscillate about alpha to
keep the car under control, and acheive the desired alpha. There is more
about vc and alpha in CNTRL0.CPP.

The slip angle, and hence the force vector, is determined both by
alpha and vc. Furthermore, the positive direction of vc is limited
by the power available. We assume that the power available to be
delivered to the track is constant. The driver can request a vc
that would exceed the available power; in that case the simulation
(the move_car() function) changes vc in order to keep the power
within limits, and sets the power_req variable so that the driver
function can change its request on the next pass.

The main loop of the race consists of observe(), control(),
move_car(), and draw_car(). This loop is repeated at the speed
of the PC clock, about 18 times per second. (unless the user
enters the extra argument to set real_speed to 0.)

The observe() routine mostly translates the car's state from the
global x, y coordinate system into a local car-centered system with
the x-axis along the track direction. This and other information is
passed to the driver function via the "situation" structure. (see

control() gets the situation and returns alpha and vc.

move_car() uses the alpha and vc along with the current state of
the car to calculate the slip vector, the forces, and finally a
new state for the car. It also calculates the power delivered by
the wheel to the track, and if this would exceed the available power
then vc is reduced substantially to get the power to be no more than
is available. This is done in no more than three iterations, so the
reduction in vc is in coarse steps. A car that requests a very large
power output will get a small one.

draw_car() visibly moves the car to its new position and orientation.


If you want this documentation improved, e-mail me with specific
questions, or topics you want covered better.

If you want the code enhanced, e-mail me with your requests.

If you want to work on the code yourself, great! You can use the
mailing list to stay in touch with others working on the same thing.

If you want to work on porting it to another platform, great! Again,
use the mailing list so you can be part of a cooperative effort.

If you have a "driver" function that goes pretty fast, put it on the ftp
site, in the /bin/ftp/rars/robots directory. If you want to keep your
source code secret, then just send a .obj file. Another secrecy option
is to use C source code, but remove all comments, substitute random
strings for all identifiers, and remove all possible whitespace. This
will produce a very obscure, but compilable, C program.


 December 7, 2017  Add comments

Leave a Reply