Filewatcher File Search
FTP Search
  
Directory 
  
Content Search 
   
pkg://tclrobots-1.0.tar.gz:53994/tclrobots.man  downloads

.TH TclRobots 6 "8/11/94" "" "Tcl/Tk"
.ce 4
\s+2TclRobots\s-2
.sp
Copyright 1994 Tom Poindexter
.br
tpoind@advtech.uswest.com
.br
tpoindex@nyx.cs.du.edu
.na
.PP
.SH "WHAT IS TCLROBOTS?"
.PP
TclRobots is a programming game, not unlike 'Core War'.  
To play TclRobots, you
must write a Tcl program that controls a robot.  The robot's mission is to
survive a battle with other robots.  Two, three, or four robots compete 
during a battle, each running different programs (or possibly the
same program in different robots.)  Each robot is 
equipped with a scanner, cannon, drive mechanism.  
A single match continues until one robot is left running.  A 
tournament can be run with any number of robot programs, each robot playing
every other in a round-robin fashion, one-on-one.  A battle 
simulator is available to help debug robot programs.
.PP
The TclRobots program provides a physical environment, imposing certain
game parameters to which all robots must adhere.  TclRobots also provides
a view on a battle, and a controlling user interface.
.PP
TclRobots is strongly influenced by my 1985 game, CROBOTS.  CROBOTS is based on writing 
robot control programs in C, and the entire environment is tightly 
coupled into a single program that contains a small C compiler, virtual 
stack-based CPU, multi-tasking scheduler, and execution environment.  
TclRobots instead is loosely coupled, utilizing separate Tcl wish interpreters 
for each robot.  Communication between a robot and the TclRobots program is 
accomplished with Tk's 
.I send 
command.
.PP
.PP
TclRobots requirements:  a wish interpreter built from Tcl 7.3 and Tk 3.6.
.PP
TclRobots uses the Tk "send" command - if your X server is insecure
(xhost access list not empty), you will need a wish compiled with the 
"-DNO_TK_SECURITY" flag.  Better yet, use "xauth" instead of "xhost."
.PP
Availability:
.br
TclRobots (and Tcl/Tk, if you don't already have it) are available at
the following locations:
.PP
ftp://harbor.ecn.purdue.edu/pub/tcl/code/tclrobots-1.0.tar.gz
.br
ftp://ftp.cs.berkeley.edu/ucb/tcl/tcl7.3.tar.Z
.br
ftp://ftp.cs.berkeley.edu/ucb/tcl/tk3.6.tar.Z
.PP
.SH "INSTALLATION AND DEMO"
.PP
.IP -
Edit the Makefile.  All that is needed it the path of your wish executable,
and the directory where you would like TclRobots installed. See
the comments at the top of the Makefile.  `make' to install.
.IP -
run `tclrobots' from the directory where you unpacked the distribution.
.IP -
Double-Click on the `samples' directory in the Files listbox.
.IP -
Click on `Select All'
.IP -
Click on `Run Battle'
.PP
.SH SYNOPSIS
.B tclrobots
[ [ -t timelimit ]  [ -o results-file ]   files... ]
.PP
.B Tclrobots
without any command line arguments starts TclRobots in interactive mode.
The user interface (described below) is used to select files, start battles,
tournaments, or the simulator.
.PP
If command line arguments are specified, 
.B tclrobots
starts in tournament mode using the specified files.  Options:
.PP
.HP
.B "-t  timelimit "
sets the number of minutes to run each match in a tournament.  Timelimit
should be specified as an integer number of minutes.  If -t is omitted,
matches run a maximum of 10 minutes each.
.HP
.B "-o  results-file "
specifies the file name in which to record tournament results.  
If -o is omitted, the file name "results.out" is used.
.PP
.SH "THE ROBOT"
.PP
All robots in TclRobots are constructed equally.  What differentiates the 
robots' behavior is the control program that you write.  The robot has the 
ability to move, look for, and shoot at, other robots.  
.PP
Robots use a compass system based on 0 to 359 degrees, with 0 pointing
due east, 90 due north, 180 due west, and 270 due south.  
.PP
The robot's drive mechanism can be controlled to move the robot in a
particular direction, at some speed.  Direction is expressed as an
integer degree heading 0 - 359, and speed is 0 to 100 percent.  The motor is
inefficient above 35% speed, and begins to overheat.  When a heat 
index of 200 is reached, the motor cannot be operated over 35% 
until cooling allows the heat index 
to drop back to 0.  While the robot is very agile and
stable, safeguards are built into the interface to prevent the robot
from tipping over while trying to turn at too fast a rate for any given
speed.   
.PP
The following table represents maximum speeds at which a delta course change
can be made:
.PP
.TS
c n.
Degrees of	Maximum
course change	Speed
_
25 or less	100%
25 - 50	50%
50 - 75	30%
75 or greater	20%
.TE
.PP
If a course change is attempted at a speed above the maximum for the change,
the drive is disengaged (speed set to 0) on the present course.
The drive mechanism also allows the robot to turn faster at slower speeds.
.PP
.TS
c n.
Speed	Rate of turn
	per second	
_
25% or less	90
25 - 50%	60
50 - 75%	40
75% or more	30
.TE
.PP
At 100% speed, the robot travels at 20 meters per second.
Robots are also subject to acceleration and deaccelearation, a linear
constant of 20% speed per second.
.PP
Each robot is equipped with a scanning device, which can be pointed 
independently of the current drive heading of the robot.  A scan can be
initiated in any direction, 0-359 degrees.  The scanner has
a variable resolution capability, detecting other robots within a maximum of
+/- 10 degrees from the scan direction.  If a scan finds a robot, the distance
to the opposing robot is reported.  
However, if a resolution greater than 0 is used, the scanner's result
may be reported inaccurately.  
In this case, the distance reported may be off by as much as
10 meters for each degree of resolution (up to 100 meters in error for a
+/- 10 degree resolution scan.)  A high resolution scan 
(0 specified for resolution) will always return accurate results. 
.PP
If two or more robots are in the
scan's resolution, the closest opponent is reported.  It's also possible to 
distinguish various opposing robots, as the scanner has a rudimentary 
digital signal processor, and each robot has a arbitrary signature.
A robot program can also be alerted when it is the subject of a scan by
another robot.  The signature of the scanning robot can be determined, but
not it's heading or distance.
.PP
A cannon is the robot's offensive weapon, firing a shell at opposing robots.
The cannon has a maximum range of 700 meters, and can be aimed independently
of robot heading.
Damage to all surrounding robots is assessed as follows:
.PP
.TS
c c
c c
n n.
Meters from	% Damage
explosion	incurred
_
10	10%
20	5%
40	2%
.TE
.PP
While the robot has an large (unlimited) cache of shells available, it 
can only reload fast enough to have one shell in the air at
maximum range at any one time (approximately 4 seconds).
Cannon shells are grouped four to a clip;  after a clip is exhausted, 
it is ejected and a new clip loaded in place.  The effect is that
on every fourth shell, the reload time is tripled (12 seconds.)
The cannon fires its shells in a high arc; a shell will not impact
into another robot that might be in the line of flight.
Shells travel at 200 meters per second toward the target.
.PP
Various feedback registers in the robot can be accessed by the control 
program, reporting the current amount of damage, x and y battlefield 
location, current speed, and an internal clock tick.
.PP
Robots incur damage expressed as a percent value.  When 100% damage is
reached, the robot is "dead", and ceases to function.  However, damage
has no effect on operational ability.  A robot with 99% damage 
operates as well as one with no damage.
.PP
.SH "THE BATTLEFIELD"
.PP
The battlefield in TclRobots is a 1,000 by 1,000 meter 
square area.  Walls surround the
battlefield, and robots running into a wall will suffer 5% damage.
The coordinate system is based on increasing x and y axis values from the
southwest corner (bottom left is 0,0).  999,999 is the 
extreme northeast (upper right).
.PP
Upon start up, robots are placed in random quadrants.
.PP
.SH "THE ROBOT TCL LANGUAGE"
.PP
Robot control programs are written in the Tcl language.  The following
Tcl commands are available:
.PP
.TS
l l l.
after	if	rename
append	incr	return
array	join	scan
break	lappend	set
case	lindex	source
catch	linsert	split
concat	list	string
continue	llength	switch
error	lrange	time
eval	lreplace	trace
exit	lsearch	unset
expr	lsort	update
file	pid	uplevel
for	proc	upvar
foreach	rand	while
format	regexp	
global	regsub	
.TE
.PP
Note that the
.I after
and 
.I update
commands from Tk are available.  
See the Tcl and Tk man pages for information on these commands.
.PP
.SH "THE ROBOT HARDWARE INTERFACES"
.PP
The following Tcl commands are the interface to the robot's hardware (syscalls.)
Each interface command takes a minimum of 100 milliseconds to complete (except
the scanner command, which requires 200 milliseconds.)
Commands that take arguments will return -1 if any argument is 
out of valid ranges.  For degrees, valid values are 0-359; for
speed, 0-100, for resolution, 0-10, for cannon range, 0-700.
.PP
.TP
.B scanner \fIdegree resolution\fR
.br
The scanner command invokes the robot's scanner.
.I Degree 
must be in the range 0-359.  Scanner returns 0 if nothing
found, or an integer greater than zero indicating the distance to
an opponent.
.I Resolution
controls how wide in degrees the scan can detect 
opponents from the absolute scanning
direction, and must be in the range 0-10.
A robot that has
been destroyed is not reported by the scanner.
.TP
.B dsp
.br
The dsp command returns a list of two integers, the first element is 
the digital signature of the last robot 
found using the scanner.  The second element is the 
percent of damage the scanned robot has accumulated, 0-99 percent.
Each robot in a battle has a distinct signature.  If nothing was found
during the last scan (scanner command returned 0), then the dsp command
will return "0 0".
.TP
.B alert \fIproc-name\fR
.br
The alert command names a procedure to be called when the robot is
being scanned by another robot.  When the robot detects it 
has been scanned, the
.I proc-name
procedure is called with one argument, the dsp signature of the
robot that performed the scan.  If proc-name is null (""), then the
alert feature is disabled.
.TP
.B cannon \fIdegree range\fR
.br
The cannon commands fires a shell in the direction specified by 
.I degree, 
for the distance 
.I range.  
Cannon returns 1 if a shell was fired;
if the cannon is reloading, 0 is returned.
.TP
.B damage
.br
The damage command reports the current percent of damage suffered by the
robot, 0-99.  At 100% damage, the robot is "dead", and as such, 
the control program is no longer running.
.TP
.B drive \fIdegree speed\fR
.br
The drive command starts the robot's drive mechanism.
.I Degree 
must be in
the range 0-359.
.I Speed 
must be in the range 0-100.  Any change in course
that falls outside the "Degrees of course change" 
table (see "The Robot", above)
will cause the robot's
speed to be set to 0 along the current course.  A speed of 0
causes the robot to coast to a stop.  The drive command
returns the speed set.  If the drive is currently overheated, the maximum
speed during overheating (35%) will be set.
.TP
.B speed
.br 
The speed command reports the current speed of the robot, 0-100.  
Speed may return
more or less than what was last set with the drive command because of
acceleration/deaccelearation, drive overheating, or collision into a wall.  
.TP
.B heat
.br
The heat command returns a list of two integers, the first element is the
overheating flag, 1 if the maximum heat value was attained, otherwise 0.
The second element is the current heat index, 0-200.
.TP
.B loc_x
.br
The loc_x command returns the current x axis location of the robot, 0-999
meters.
.TP
.B loc_y
.br
The loc_y command returns the current y axis location of the robot, 0-999
meters.
.TP
.B tick
.br
The tick command returns the current robot clock tick,
which has a 500 millisecond
resolution.  The clock is set to 0 upon robot startup.
.PP
.PP
Convenience commands
.PP
The following Tcl commands are available to the robot control program.  As such, 
they execute immediately without the 100 millisecond interface time.
.TP
.B dputs \fIargs\fR
.br
The dputs command prints a message on the robot's status window.
Dputs accepts any number of arguments.
.TP
.B rand \fImax\fR
.br
The rand command is a simple random number generator, based on Knuth's
algorithm.  The rand command returns an integer between 0 and (
.I max 
- 1),
where max is in the range 1 to 65535.
The seed value is randomly set; if a particular seed value is desired,
the global variable 
.I _lastvalue 
may be set to a value between 0-65535.
.PP
.PP
.SH "WRITING ROBOT CONTROL PROGRAMS"
.PP
Several internal variables and procedures are loaded into a robot before
loading the robot control program.  Reserved variables and commands begin
with and underscore "_" or dot ".".  Do not use variables or procedures in
robot control program that begin with either symbol.
.PP
Robot control programs may set variables or define procedures as required.
Robot control programs should never exit, as they will not be restarted
by TclRobots.  Thus, the main processing should be enclosed in an endless
loop, e.g. "while 1 { ... }"
.PP
Most standard Tcl commands are available to robot control programs.  Notable
Tcl commands that are missing: all file I/O (
.I "gets, puts, open, close," 
etc.),
.I "exec, info,"
standard Tcl library procs (
.I "auto_load, unknown, tkerror "
etc.)
.PP
In addition, most standard Tk commands are also missing.  Tk commands that
are available are
.I after 
and 
.I update.  
Each syscall implicitly performs the 
.I update 
command, or the programmer can execute it any time to ensure that commands
scheduled with 
.I after
are run.
.PP
Any "unknown" procedure, or "tkerror" situation is reported in the robot's
status window, and the robot program will terminate.
.PP
Robot control programs may also examine (but not set) the global variable
.I _debug
to cause debugging code to be executed during battle simulation.  
.I _debug
is set to 1 if running in the simulator, 0 otherwise.
(see "The Simulator" below.)
.PP 
If the 
.I alert
command is used, the procedure it specifies should exist, and take one
argument, e.g.
.PP
.RS
proc I_Was_Scanned {who} {
.br
  dputs $who scanned me!
.br
}
.br
alert I_Was_Scanned
.RE
.PP
Any valid filename can be used for a robot control
program; a suffix of
.B .tr
is recommended to indicate a TclRobots file.
.PP
.SH "THE TCLROBOTS USER INTERFACE"
.PP
TclRobots has a user interface to start battles, run the simulator, commence
a tournament, and view battles in progress.  Upon startup, TclRobots displays
a bar of five buttons, and two listboxes.  The buttons are:
.IP -
Run Battle - runs a battle with selected robots
.IP -
Simulator.. - starts the simulator dialog
.IP -
Tournament.. - starts the tournament controller
.IP -
About.. - a small about box with TclRobots version number
.IP -
Quit - immediately exits TclRobots
.PP
The two listboxes are a file section box (left side), and a 
list of selected robot files (right side).
.PP
The file section box presents a list of directories and files in the current
directory.  Double-clicking on a directory changes to that directory.  
Double-clicking on a file chooses that file to be run in a battle, simulator, 
or tournament.  A file filter entry is presented at the top of the file 
selection box and may be used to filter the selection by entering a pattern
and pressing "Filter".  At the bottom of the file selection list is a
file selection.  Entering a file and pressing "Select" will enter that file
in the "Robot Files Selected" list.  The button labeled "Select All" will
select all files in the file selection box to the Robot Files Selected list.
.PP
Robot files should be selected before pressing "Run Battle", "Simulator..", or
"Tournament..".  To run a single battle, select two to four robot files from
the file selection list.  A single file may be selected more than once; 
separate robots will be loaded with the same file.  If the "Simulator.."
button is pressed, the first file in the Robot Files Selected list will be
used for the Simulator.  If the "Tournament.." button is pressed, all files
in the Robot Files Selected list will be run in a tournament fashion. 
In a tournament, duplicate files will be removed from the list.
.PP
The Robot Files Selected listbox has two buttons, "Remove", and "Remove All".
Selecting a file by single clicking and pressing the Remove button will
remove that file from the list.  The Remove All button will remove all files
from the Robot Files Selected list.
.PP
Robot files selected are not verified;  if a file other than a
TclRobots robot control program is selected, results are unpredictable.
.PP
.PP
When "Run Battle" is pressed, TclRobots will spawn a new wish interpreter,
position it to the right of the main window, and load it with a selected
robot control program.  After all robot wish interpreters are spawned, the
file selection frame is replaced with a view on the battlefield and the
battle will commence.  Each robot is assigned a specific color, and is
represented on the battlefield by a unique arrow shape of that color.
When a robot
issues the 
.I scanner
command, the scan is represented by a dotted line
emanating from the robot.  Shells fired by a robot are represented by
a small black dot.  The robot's current damage status is shown 
below the robot's file name, just above the battlefield.
.PP
During a battle, the "Run Battle" button is replaced, by "Halt".  If pressed,
the current battle is halted, and the spawned robot interpreters exit.
The "Halt" button is then replaced with "Reset", which removes the 
battlefield, and presents the file selection frame.
.PP
Individual wish interpreters for the robots contain a listbox and scrollbar,
which hold output from the "dputs" command.
.PP
.PP
.SH "THE SIMULATOR"
.PP
The "Simulator.." button starts the simulator, using the first entry in 
the Robot Files Selected list.  A simulator control window appears, and a
target robot is placed in the middle of the battlefield (500,500).
.PP
The Simulator allows a robot program to be examined during robot execution,
revealing important information about the robot.  A robot control program can
be set to stop on each "syscall" (any of the robot hardware interface 
commands.)  While the robot program is paused, the simulator can query or
set global variables in the robot control program.
.PP
The Simulator has its control buttons at the top of the Simulator window.
A checkbutton "Step syscalls" toggles the single step action of the
robot control program.  The button "Single Step" will also set the Step
Syscalls checkbutton, or allow the robot control program to run to the
next syscall if already in Step Syscalls.  The button "5% Hit" 
simulates the robot incurring damage. 
The button "Scan" simulates the robot being scanned by the target.  The
target's dsp signature is "1".
The button "Close" will remove the
simulator and the spawned robot wish interpreter, and return to the file
selection listbox frame.
.PP
When the "Step Syscalls" button is in the "off" state, the robot
executes its code in real time.  During "Single Step", execution is
paused at the next syscall and one motion time cycle is executed.  
Thus, time
is not accurately represented.  The behavior of a robot that is single
stepped may be exaggerated, especially while the robot is in motion.
.PP
As the robot is simulated, the robot's X and Y location, current heat
index, speed, heading, and damage are updated.  If the simulator is in
the Step Syscalls state, these attributes may also be set by entering a
new value.  Parameter fields only accept numeric entries in the range
that is acceptable for any particular parameter.
The "Heat" entry turns red (inverse on monochrome displays)
when the robot's motor is the in overheated state.
.PP
The last syscall executed by the robot is shown, along with the
arguments to the call (if any).  The return value from the
syscall is shown in parentheses.  The current clock tick is also displayed,
but cannot be altered.
.PP
At the bottom of the simulator, global variables in the robot may be
examined or set.  Entering a variable name in the "Variable" entry
and pressing enter or the "Examine" button will display the variable's
value.  Entering a new value in the "Value" entry and pressing enter or
the "Set" button will set the variable.
.PP
.PP
.SH "TOURNAMENT CONTROLLER"
.PP
The "Tournament.." button starts the Tournament Controller window.  When
the "Start Tournament" button is pressed, files
in the Robot Files Selected window are first scanned for uniqueness,
ignoring any duplicate filenames.  A tournament is run on the remaining 
files in a round-robin fashion, each robot battling every other, one-on-one.
.PP
A time limit is imposed on each battle.  The default is 10 minutes
per battle, and may be set in the "Maximum minutes per match" entry.
Optionally, tournament results may be saved into a file by specifying
a valid file name in the "Optional results file" entry.
.PP
Results of each individual match are displayed in the "Results" listbox.
.PP
Each battle is scored.  A robot winning a match receives three points.  A
tie match (both robots still running after the 
time limit expires) results in
one point each.  At the end of the tournament, robots are ranked according
to total points.
.PP
During each match, the main window operates as in "Run Battle" mode; 
"Halt may be used to stop a tournament in progress.  The Tournament 
Controller's window will display the time remaining in the current 
match.
.PP
.PP
.SH INTERNALS
.PP
TclRobots implements a small "physics" package (proc update_robots) 
to control robot and missile (cannon shells) movement.  The proc is
scheduled to run every 500 milliseconds during a battle.
.PP
Each robot in a battle executes in a separate wish interpreter.  When 
a new robot is started, a series of setup and interface code is first
sent (using "send") to the new intepreter.  A "source" command is also
sent to load an individual robot control program.  The interface
code that is sent causes each robot to relay its interface calls back 
to TclRobots using the "send" command.
.PP
Most commands set parameters in an array that TclRobots maintains.  The
"update_robots" proc carries out the requests.  "Scanner" is an exception,
in that the scan is computed and values returned.  Commands that return
status information merely return relevant portions of the robot array.
.PP
Cheating?
.br
Since each robot communicates to TclRobots via the 
.I send 
command, it 
exposes TclRobots to unauthorized access to its internals.  Thus, a crafty
robot programmer may be tempted to use 
.I send 
to look at or set the
state of other robots.  The setup code is modified for each robot,
renaming the 
.I send 
command to a randomly generated name.  The Tcl 
.I info
command is deleted, so that the new send command name is not
readily apparent.  However, this method is not totally foolproof.
.PP
Just consider it to be "unsportsman-like" to attempt such usage of send.
.PP
.PP
.SH ACKNOWLEDGMENTS
.PP 
I've used a few pieces of code in TclRobots that I didn't write, and
acknowledge those people:
.PP
.IP
  John Ousterhout - mkDialog, from the "widget" demo included with Tk
.br
  Mark Eichin - rand, from a comp.lang.tcl posting
.br
  Bill Burdick - every, from a comp.lang.tcl posting
.sp
  I also used the file selection box procs from my "wisql" and "wosql"
  programs distributed with Sybtcl and Oratcl.
.PP
I'd also like to recognize John Ousterhout again, for creating Tcl/Tk
and making it available to the world.  Tcl/Tk is such a flexible language -
I was able to graft in the simulator and tournament controller as 
after thoughts, without changing much existing code. 
.PP 
.PP
.SH NOTES
.PP
If you are unfamiliar with 'Core war', it is a programming game based on 
two assembly language programs running in one address space of a virtual 
computer.  Programs try to cause the other to terminate, leaving the winning
program as the only one left running.
.PP
From the rec.games.corewar Frequently Asked Questions (Stefan Strack):
.RS
.PP
Core War was first described in the "Core War Guidelines" of March,
1984 by D. G. Jones and A. K. Dewdney of the Department of Computer
Science at The University of Western Ontario (Canada).  Dewdney wrote
several "Computer Recreations" articles in "Scientific American" which
discussed Core War, starting with the May 1984 article.
.RE
.PP
My CROBOTS game was released in 1985 as PC MSDOS "Shareware".  It is still
available from various FTP archives, including:
.PP
ftp://oak.oakland.edu/pub/msdos/c/crobots.zip
.PP
CROBOTS was released in binary form only, and a source license was
available for payment of the shareware fee.  Working on TclRobots
has again sparked my interest in such games, 
and I'm tempted to update CROBOTS.  
Any such release (no promises when that might be) will include source.
.PP
If TclRobots complains that you are using "xhost" style security, you
should either use "xauth" style security, or recompile your wish 
interpreter, uncommenting the Tk Makefile
line:
.PP
#SECURITY_FLAGS = -DTK_NO_SECURITY
.PP
Information on setting up "xauth" is available at:
.PP
ftp://harbor.ecn.purdue.edu/pub/tcl/docs/Xauthority.gz
.PP
.SH BUGS
.PP
TclRobots is inherently simplistic in its treatment of physics.  Part of the
goal is to run a challenging game while still executing and updating the
battlefield in a reasonable time period.  I developed TclRobots on a 486-50mhz
pc running Linux, and can easily run a four robot battle (five wish
interpreters running.)
.PP
I've fixed the size of the main window, largely for ease of plotting the
robots and missiles in the canvas.  Currently the canvas is 500x500 pixels,
so reducing the battlefield arena to canvas locations is a simple divide by
two.  My intent was to save as much processing during the update cycle.
.PP
The time limit in Tournament mode is not actual wall clock time, but 
rather a calculation that assumes the 500 millisecond tick rate of the
physics package is accurate.  The time that "update_robots" takes to
run on each tick is cumulative in distorting tournament time.
.PP
The user interface was not designed.  Instead, it evolved from functionality.
It could probably stand improvement.
.PP
No doubt that some programmers will carefully examine the "physics" package
and exploit its weaknesses.  At least it available for all to see.  Some of
the ideas I put in TclRobots that was missing from CROBOTS is the "motor
heating", which should eliminate robots running a full speed for an 
extended period of time.  Also, the cannon is limited on its ability for
rapid fire by introducing the notion of a "clip", with longer reloading times.
.PP
.SH AUTHOR
.PP
Tom Poindexter, Denver, Colorado.  Version 1.0 released August, 1994.
.PP
Any suggestions for improvement can be sent to me at either address listed
at the top of this document.
.PP
Results 1 - 1
Help - FTP Sites List - Software Dir.
Searching half a billion files worldwide
© 1997-2009 MARUHN Internet Solutions