home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / pascal / P_ROBOTS.ZIP / P-ROBT21.ZOO / p-robots.doc < prev    next >
Encoding:
Text File  |  1989-10-30  |  106.9 KB  |  2,736 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.                                      P-ROBOTS 
  9.  
  10.  
  11.                           A Game For PASCAL Programmers
  12.  
  13.  
  14.                            Version 2.0 -- December 1989
  15.  
  16.  
  17.                                         By
  18.  
  19.  
  20.                                   David Malmberg
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.                                   Distributed by
  35.                                     Softworks
  36.                                  43064 Via Moraga
  37.                         Mission San Jose, California 94539
  38.                                   (415) 659-0533
  39.  
  40.  
  41.                                     _______ 
  42.                                ____|__     |               (tm)
  43.                             --|       |    |------------------- 
  44.                               |   ____|__  |  Association of 
  45.                               |  |       |_|  Shareware 
  46.                               |__|   o   |    Professionals 
  47.                             -----|   |   |--------------------- 
  48.                                  |___|___|    MEMBER
  49.  
  50.  
  51.  
  52.  
  53.                        Copyrighted 1989 -- All Rights Reserved
  54.                                   By David Malmberg
  55.  
  56. JUST WHAT IS P-ROBOTS?
  57.  
  58.  
  59.    P-ROBOTS ("pee-robots") is a game based on computer programming in PASCAL. 
  60.    The objective of the game is to design and program a "robot" that can
  61.    triumph over similar robots designed and programmed by others in a
  62.    real-time battle of wits and flying missiles.  You control your robot by
  63.    writing a procedure in PASCAL to specify your robot's behavior and strategy
  64.    in its efforts to vanquish up to three other robots in a battle to the
  65.    death.  A variety of pre-defined P-ROBOTS PASCAL functions and procedures
  66.    allow your robot to track its position on the battlefield, monitor its
  67.    health or damage condition, and calculate the distance and angle to
  68.    opponents from its current battlefield position.  Each robot is equipped
  69.    with a cannon to fire missiles, and a motorized drive mechanism to either
  70.    close in for the kill of a hapless opponent or flee from a fierce foe.
  71.  
  72.    P-ROBOTS is an excellent way for the novice programmer to sharpen his/her
  73.    PASCAL skills and have fun at the same time.  However, P-ROBOTS does
  74.    assumes that the robot designer/programmer already knows the fundamentals
  75.    of programming in PASCAL.
  76.  
  77.    For the experienced programmer, P-ROBOTS offers a chance to see just how
  78.    well you program in a programming environment where "bad" code can lead to
  79.    graphic and ignoble defeat and "brilliant" code can bring triumph and
  80.    glory.
  81.  
  82.    In addition to being enjoyed in thousands of homes, P-ROBOTS has been
  83.    successfully used in a number of classroom settings -- from high school
  84.    PASCAL programming classes to graduate level courses in Artificial
  85.    Intelligence.  "The competitive environment that P-ROBOTS creates has
  86.    really sparked my students' desire to learn.  Our weekly robot contests are
  87.    great fun and enjoyed by all -- including me", said one high school PASCAL
  88.    teacher.  Another teacher has challenged his PASCAL students by offering a
  89.    unique reward: any student that can design and program a robot that can
  90.    beat the teacher's robot consistently does not have to take the final exam.
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.                                         i
  112.  
  113. TABLE OF CONTENTS
  114.  
  115.  
  116.    JUST WHAT IS P-ROBOTS?  . . . . . . . . . . . . . . . . . . . . . . .  i
  117.    TABLE OF CONTENTS . . . . . . . . . . . . . . . . . . . . . . . . . . ii
  118.    P-ROBOTS REGISTRATION/ORDER FORM  . . . . . . . . . . . . . . . . . .iii
  119.    LICENSE TERMS (Shareware Rules) . . . . . . . . . . . . . . . . . . . iv
  120.    DISTRIBUTION OF P-ROBOTS BY DISK VENDORS  . . . . . . . . . . . . . .  v
  121.    P-ROBOTS PRODUCT/TECHNICAL SUPPORT  . . . . . . . . . . . . . . . . . vi
  122.    ACKNOWLEDGEMENTS  . . . . . . . . . . . . . . . . . . . . . . . . . .vii
  123.    INTRODUCTION  . . . . . . . . . . . . . . . . . . . . . . . . . . . .  1
  124.    HARDWARE AND SOFTWARE REQUIREMENTS  . . . . . . . . . . . . . . . . .  1
  125.    FILES ON THE DISK . . . . . . . . . . . . . . . . . . . . . . . . . .  1
  126.    GETTING STARTED . . . . . . . . . . . . . . . . . . . . . . . . . . .  2
  127.    INVOKING A CONTEST  . . . . . . . . . . . . . . . . . . . . . . . . .  3
  128.    CONTROLLING YOUR ROBOT'S MOVEMENT . . . . . . . . . . . . . . . . . .  4
  129.    ATTACKING OTHER ROBOTS  . . . . . . . . . . . . . . . . . . . . . . .  5
  130.    OTHER SPECIAL P-ROBOTS FUNCTIONS AND PROCEDURES . . . . . . . . . . .  7
  131.         TIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  7
  132.         DISTANCE . . . . . . . . . . . . . . . . . . . . . . . . . . . .  7
  133.         ANGLE_TO . . . . . . . . . . . . . . . . . . . . . . . . . . . .  8
  134.         RANDOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  8
  135.         TRIG FUNCTIONS . . . . . . . . . . . . . . . . . . . . . . . . .  8
  136.    INFLICTING DAMAGE . . . . . . . . . . . . . . . . . . . . . . . . . .  9
  137.    PUTTING IT ALL TOGETHER . . . . . . . . . . . . . . . . . . . . . . .  9
  138.    ROBOT PROGRAMMING RULES . . . . . . . . . . . . . . . . . . . . . . . 12
  139.    ADVANCED P-ROBOT FEATURES . . . . . . . . . . . . . . . . . . . . . . 13
  140.         CONTROLLING THE ANIMATION SPEED  . . . . . . . . . . . . . . . . 13
  141.         PROTECTIVE SHIELDS . . . . . . . . . . . . . . . . . . . . . . . 13
  142.         FUEL CONSTRAINTS . . . . . . . . . . . . . . . . . . . . . . . . 14
  143.         RUNNING OUT OF FUEL  . . . . . . . . . . . . . . . . . . . . . . 15
  144.         AN EXAMPLE USING A SHIELD AND FUEL . . . . . . . . . . . . . . . 15
  145.         ROBOT TEAMS  . . . . . . . . . . . . . . . . . . . . . . . . . . 18
  146.         AN EXAMPLE OF A ROBOT TEAM . . . . . . . . . . . . . . . . . . . 19
  147.         OBSTRUCTIONS ON THE BATTLEFIELD  . . . . . . . . . . . . . . . . 22
  148.         AN EXAMPLE DEALING WITH OBSTRUCTIONS . . . . . . . . . . . . . . 22
  149.         INTELLIGENCE OPTIONS . . . . . . . . . . . . . . . . . . . . . . 26
  150.    APPENDIX I: COMPILER ERRORS . . . . . . . . . . . . . . . . . . . . . 27
  151.    APPENDIX II: RUN-TIME ERRORS  . . . . . . . . . . . . . . . . . . . . 29
  152.    APPENDIX III: COMMON PROBLEMS . . . . . . . . . . . . . . . . . . . . 31
  153.    APPENDIX IV: THE P-ROBOTS PASCAL LANGUAGE . . . . . . . . . . . . . . 32
  154.    APPENDIX V: A BLATANT "PLUG" FOR ANOTHER SOFTWORKS PRODUCT  . . . . . 35
  155.    APPENDIX VI: ABOUT THE AUTHOR . . . . . . . . . . . . . . . . . . . . 39
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.                                         ii
  170.  
  171. P-ROBOTS REGISTRATION/ORDER FORM
  172.  
  173.  
  174.    Remit to:  Softworks
  175.               43064 Via Moraga
  176.               Mission San Jose, California  94539
  177.  
  178.    You can also order by phone using your Mastercard or VISA by dialing (415)
  179.    659-0533, 12:00 noon to 9:00 p.m., PST ONLY, Monday to Friday.
  180.  
  181.    P-ROBOTS Registration ..............................@ $ 25.00 ea $ ______
  182.  
  183.         Registration entitles you to the following:
  184.  
  185.         (1) Notice of all future P-ROBOTS upgrades.
  186.         (2) Latest version of the program, with a collection of the
  187.               most recent and best robots, and a printed manual.
  188.         (3) Turbo or Quick Pascal source code for P-ROBOTS.
  189.         (4) Turbo or Quick Pascal source code for the multi-tasking PASCAL
  190.               compiler used as the basis for developing P-ROBOTS.
  191.         (5) Telephone support from 7:00 to 9:00 PST (M-F).
  192.         (6) A warm glow from having supported at least one of the many
  193.               Shareware products you probably use.
  194.         (7) The P-ROBOTS author's eternal gratitude.
  195.  
  196.    Orders are normally shipped by US mail at no additional charge.
  197.  
  198.        For UPS shipment, please add $4.00...............@ $ 4.00 ea $ ______
  199.  
  200.        For shipments outside the United States, add.....@ $ 5.00 ea $ ______
  201.  
  202.                                                          Subtotal   $ ______
  203.  
  204.        (California residents please add 7 1/4% sales tax)     Tax   $ ______
  205.  
  206.                                                             TOTAL   $ ______
  207.  
  208.    Payment by:    ( ) Check    ( ) MasterCard    ( ) VISA    ( ) Cash
  209.  
  210.         Name: _______________________________________________________________
  211.  
  212.      Address: _______________________________________________________________
  213.  
  214.             : _______________________________________________________________
  215.  
  216.        State: ______________________________ Zip:____________________________
  217.  
  218.    Day Phone: ____________________________ Eve: _____________________________
  219.  
  220.       Card #: _________________________________ Exp. Date: __________________
  221.  
  222.    Signature of cardholder: _________________________________________________
  223.  
  224.    Disk Version Desired:    _____ IBM 5 1/4   _____ IBM 3 1/2
  225.  
  226.  
  227.                                        iii
  228.  
  229. LICENSE TERMS (Shareware Rules)
  230.  
  231.    P-ROBOTS is NOT public domain or free software, but is being distributed as
  232.    "Shareware".  This means that if you are a regular user of P-ROBOTS, you
  233.    should pay for your copy and become a registered user.  Only from the
  234.    income from your registration fees can the author continue to provide
  235.    product support, make enhancements to P-ROBOTS, and stay in business.
  236.  
  237.    Non-registered users of this software are granted a limited license to make
  238.    an evaluation copy for trial use on a private non-commercial basis, for the
  239.    express purpose of determining whether P-ROBOTS is suitable for their
  240.    needs.  At the end of this trial period, the user should either register
  241.    his/her copy of P-ROBOTS or discontinue using it.
  242.  
  243.    Registered users of P-ROBOTS may use P-ROBOTS on any computer, provided
  244.    that P-ROBOTS is used on only one computer at a time, and that the copy is
  245.    not routinely used on that computer by other people.  If other people use
  246.    the copy of P-ROBOTS routinely, they should become registered users
  247.    themselves.
  248.  
  249.    Registered P-ROBOTS users may make archival and working copies of the
  250.    P-ROBOTS program disk to back up their software and protect their
  251.    investment.  They may also make evaluation copies of P-ROBOTS for trial use
  252.    by non-registered users, subject to the terms outlined above.
  253.  
  254.    Operators of electronic bulletin boards (Sysops) are encouraged to post
  255.    P-ROBOTS and related ROBOT game files for downloading by their users.  
  256.  
  257.    This license to use P-ROBOTS does NOT include the right to distribute or
  258.    sell P-ROBOTS.  Distribution terms are detailed below.
  259.  
  260.    P-ROBOTS may be uploaded to and downloaded from commercial systems such as
  261.    CompuServe, GENIE, and BIX, so long as the only charge paid by the
  262.    subscriber is for on-line time and there is no charge for the program. 
  263.    Those copying, sharing, and/or electronically transmitting the program are
  264.    required not to delete or modify the copyright notice and restrictive
  265.    notices from the program or documentation; anyone doing so will be treated
  266.    as a contributory copyright violator.
  267.  
  268.    The P-ROBOTS documentation may not be modified by users. The program may
  269.    not be separated from the documentation when distributed.  Printed or
  270.    "Xeroxed" copies of the P-ROBOTS documentation (i.e., this manual) may not
  271.    be distributed or sold without the written permission of Softworks.
  272.  
  273.    NOTE:  This program is produced by a member of the Association of Shareware
  274.    Professionals (ASP).  ASP wants to make sure that the shareware principle
  275.    works for you.  If you are unable to resolve a shareware-related problem
  276.    with an ASP member by contacting the member directly, ASP may be able to
  277.    help.  The ASP Ombudsman can help you resolve a dispute with an ASP member,
  278.    but does not provide technical support for members' products.  Please write
  279.    to the ASP Ombudsman at P.O. Box 5786, Bellevue, WA 98006 or send a
  280.    CompuServe message via EasyPlex to ASP Ombudsman 70007,3536.
  281.  
  282.  
  283.  
  284.  
  285.                                         iv
  286.  
  287. DISTRIBUTION OF P-ROBOTS BY DISK VENDORS
  288.  
  289.  
  290.    Distributors of "public domain" or user-supported software libraries must
  291.    obtain written permission to distribute copies of P-ROBOTS and related
  292.    robot game files.  No one may use P-ROBOTS as a promotion for any
  293.    commercial venture or as an enticement for the user to pay for any program,
  294.    product, or service unless they have received the express written
  295.    permission of the program's author.
  296.  
  297.    In order to distribute P-ROBOTS, a dealer or disk vendor must comply with
  298.    the following conditions:
  299.  
  300.      (1)  You must obtain written permission from Softworks to distribute
  301.           P-ROBOTS.  If you receive no reply, write again: our silence does
  302.           NOT constitute permission, and you may not distribute "pending"
  303.           receipt of permission.
  304.  
  305.      (2)  A fee of not more than $7 may be charged for each disk sold. 
  306.           P-ROBOTS may not be included on any disk sold for more than $7,
  307.           including CD-ROM or optical disks, without express written
  308.           permission from Softworks.
  309.  
  310.      (3)  Vendors may not modify or delete ANY files on the disk.  Vendors may
  311.           add a "GO" program, and/or a reasonable number of small text files
  312.           designed to assist or provide a service to the user, but these added
  313.           files must be easily identifiable and end-users must be allowed to
  314.           delete the added files.
  315.  
  316.      (4)  Vendors must make a reasonable effort to distribute only the most
  317.           recent versions of P-ROBOTS.  All vendors who have requested and
  318.           received written permission to distribute P-ROBOTS will be notified
  319.           of updates as they are released.
  320.  
  321.      (5)  All disk vendors must comply with any and all vendor guidelines or
  322.           vendor requirements set forth by the Association of Shareware
  323.           Professionals (ASP); for more information about ASP, contact its
  324.           chairman, Jim Button, at Buttonware in Seattle.  Violation of any
  325.           ASP guideline or requirement automatically revokes permission to
  326.           distribute P-ROBOTS.
  327.  
  328.    Until formal requirements are adopted by the ASP, you must comply with the
  329.    following guidelines: Vendors must make an attempt to educate users on the
  330.    nature of Shareware.  Catalogs, advertisements, order forms, and all disks
  331.    sold should contain ASP-approved or recommended wording describing the
  332.    nature of shareware, and should explicitly state that no part of disk sale
  333.    revenues are paid to the programs' authors.  When vendor catalogs or
  334.    advertisements carry both Shareware and PD programs, the Shareware programs
  335.    must be differentiated from the public domain programs in some way (in the
  336.    description, with an asterisk, by listing the registration fee, etc.). 
  337.  
  338.  
  339.  
  340.  
  341.  
  342.  
  343.                                         v
  344.  
  345. P-ROBOTS PRODUCT/TECHNICAL SUPPORT
  346.  
  347.  
  348.    Softworks will make every reasonable effort to fix P-ROBOTS bugs, and help
  349.    registered users by answering technical and other P-ROBOTS related
  350.    questions.  This Product/Technical support for P-ROBOTS is available to
  351.    registered users (only) in several forms:
  352.  
  353.      (1)  By leaving a message in the 'Softworks' forum on BIX (the BYTE
  354.           Information Exchange).
  355.  
  356.      (2)  By telephone to David Malmberg at Softworks, Monday through Friday
  357.           from 7:00 PM to 9:00 PM (Pacific Coast Time) at (415) 659-0533. 
  358.           Please respect these hours!
  359.  
  360.      (3)  By CompuServe E-Mail to David Malmberg, CompuServe ID 73435,1277.
  361.  
  362.      (4)  By letter to:
  363.  
  364.                Softworks
  365.                43064 Via Moraga
  366.                Mission San Jose, California
  367.                                    94539
  368.  
  369.    If you send disks or listings that you wish returned, be sure to enclosed a
  370.    self-addressed, stamped envelope (SASE) with sufficient postage.  If you do
  371.    not enclose a SASE, your material will not be returned.
  372.  
  373.    Regardless of the method you use to solicit P-ROBOTS support, if you are
  374.    having a problem and you can not get P-ROBOTS to do what you think it
  375.    should do, please provide background information on the following:
  376.  
  377.      (1)  The version of P-ROBOTS you are using.
  378.  
  379.      (2)  The computer system you are using.
  380.  
  381.      (3)  Your system's configuration, i.e., amount of RAM, number and type of
  382.           disk drives, the type of monitor you are using.
  383.  
  384.      (4)  Any memory resident programs you have installed at the same time you
  385.           are using P-ROBOTS and a "rough idea" of what they do and how much
  386.           memory they take.
  387.  
  388.      (5)  Your problem, i.e., what is happening vs. what you think should be
  389.           happening. 
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.                                         vi
  402.  
  403. ACKNOWLEDGEMENTS
  404.  
  405.  
  406.    P-ROBOTS owes a great deal to many people and to several previous programs.
  407.  
  408.    The P-Code PASCAL compiler that was used in P-ROBOTS has a long history. 
  409.    It was originally developed and published in 1976 by Nicklaus Wirth, the
  410.    "father" of PASCAL.  In 1982, M. Ben-Ari developed and published a book
  411.    describing how to make the compiler capable of multi-tasking.  Over the
  412.    years, this compiler has been converted to many, many different computers
  413.    and to many different dialects of PASCAL.  In 1986, Charles Schoening
  414.    converted the compiler to Turbo Pascal version 2.0 on the IBM and released
  415.    his version to the public domain.  I have enhanced and converted the
  416.    compiler to the most recent releases of Turbo Pascal (versions 4.0, 5.0 and
  417.    5.5 for the IBM and compatibles), as well as, to Microsoft's QuickPascal. 
  418.    This version was then adapted to be the compiler "engine" for P-ROBOTS.
  419.  
  420.    The inspiration for P-ROBOTS and the initial design of the program came
  421.    from a similar program called C-ROBOTS by Tom Poindexter, which was first
  422.    published in 1985.  As might be expected from the name, C-ROBOTS allows the
  423.    programmer to design and program his/her robots in the C language, rather
  424.    than PASCAL.  If you are interested in C-ROBOTS, Tom is selling it as
  425.    Shareware for a $20 registration fee.  The registration fee entitles you to
  426.    the latest version of the program, a large collection of excellent robots,
  427.    and the source code for the C-ROBOTS (written in C -- of course).  C-ROBOTS
  428.    can be ordered from Tom at the following address:
  429.  
  430.           Tom Poindexter
  431.           6864 Amherst Court
  432.           Highlands Ranch, CO
  433.                          80126
  434.  
  435.    C-ROBOTS can NOT be ordered from Softworks; it must be ordered from Tom
  436.    directly at the above address. 
  437.  
  438.    In addition, I would especially like to thank Professor B.J. Gleason of
  439.    Upsala College and his students.  Version 2.0 of P- ROBOTS benefited
  440.    greatly from their suggestions.  Professor Gleason and his students also
  441.    donated some truly awesome Robots that are included on the current P-ROBOTS
  442.    disk.
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.                                        vii
  457.  
  458. INTRODUCTION
  459.  
  460.  
  461.    P-ROBOTS ("pee-robots") is a game based on computer programming in PASCAL. 
  462.    The objective of the game is to design and program a "robot" that can
  463.    triumph over similar robots designed and programmed by others in a
  464.    real-time battle of wits and flying missiles.  You control your robot by
  465.    writing a procedure in PASCAL to specify your robot's behavior and strategy
  466.    in its efforts to vanquish up to three other robots in a battle to the
  467.    death.  A variety of pre-defined P-ROBOTS PASCAL functions and procedures
  468.    allow your robot to track its position on the battlefield, monitor its
  469.    health or damage condition, and calculate the distance and angle to
  470.    opponents from its current battlefield position.  Each robot is equipped
  471.    with a cannon to fire missiles, and a motorized drive mechanism to either
  472.    close in for the kill of a hapless opponent or flee from a fierce foe.
  473.  
  474.    P-ROBOTS is an excellent way for the novice programmer to sharpen his/her
  475.    PASCAL skills and have fun at the same time.  However, P-ROBOTS does
  476.    assumes that the robot designer/programmer already knows the fundamentals
  477.    of programming in PASCAL.
  478.  
  479.    For the experienced programmer, P-ROBOTS offers a chance to see just how
  480.    well you program in a programming environment where "bad" code can lead to
  481.    graphic and ignoble defeat and "brilliant" code can bring triumph and
  482.    glory.
  483.  
  484.    In addition to being enjoyed in thousands of homes, P-ROBOTS has been
  485.    successfully used in a number of classroom settings -- from high school
  486.    PASCAL programming classes to graduate level courses in Artificial
  487.    Intelligence.  "The competitive environment that P-ROBOTS creates has
  488.    really sparked my students' desire to learn.  Our weekly robot contests are
  489.    great fun and enjoyed by all -- including me", said one high school PASCAL
  490.    teacher.  Another teacher has challenged his PASCAL students by offering a
  491.    unique reward: any student that can design and program a robot that can
  492.    beat the teacher's robot consistently does not have to take the final exam.
  493.  
  494.  
  495. HARDWARE AND SOFTWARE REQUIREMENTS
  496.  
  497.    If you intend to run P-ROBOTS on an IBM or compatible computer, you will
  498.    need at least 384K of memory and DOS 2.1 or later.  Either a color or
  499.    monochrome monitor may be used.  If you are using a color monitor, P-ROBOTS
  500.    will automatically detect it and use different colors for each robot.  If
  501.    you are using a monochrome monitor, P-ROBOTS will display your robots
  502.    accordingly.
  503.  
  504.  
  505. FILES ON THE DISK
  506.  
  507.    You should have the following files on your P-ROBOTS disk:
  508.  
  509.           P-ROBOTS.EXE   The is the main program that is executed whenever you
  510.                          hold  a P-ROBOTS contest.
  511.  
  512.  
  513.  
  514.                                         1
  515.  
  516.           P-ROBOTS.DOC   This file contains the documentation for P-ROBOTS. 
  517.                          It is a text file and can be printed by giving the
  518.                          command at the DOS prompt: TYPE P-ROBOTS.DOC > PRN
  519.  
  520.           PR-DEMO.BAT    This is a file that gives a demonstration of a
  521.                          typical P-ROBOTS contest between three robots.
  522.  
  523.           ????????.PR    These are other PASCAL source code files for other
  524.                          robots.  All P-ROBOTS robots MUST have .PR file
  525.                          extensions.  Without this .PR extension, P-ROBOTS
  526.                          will not compile the robot and enter it in any robot
  527.                          contests.
  528.  
  529.  
  530. GETTING STARTED
  531.  
  532.    To see a typical P-ROBOTS contest, just execute the batch file PR-DEMO. 
  533.    What you will see will be the PASCAL source code for three robots being
  534.    read from the disk and compiled by P-ROBOTS.  After being compiled
  535.    successfully (without any errors), you will then see a battle between these
  536.    three robots.  The battle will last between one and four minutes and you
  537.    will be able to see the individual robots move around the battlefield, fire
  538.    their missiles and get hit when the missiles explode too near them on the
  539.    screen.  The screen and the battlefield will look something like the
  540.    following:
  541.  
  542.  
  543.           (x=0,y=999)                        (x=999,y=999)
  544.  
  545.               +------------------------------------+ 1  CHASER 
  546.               |                                    |  D% 015   Sc 218
  547.               |                               1    |  Sp 000   Hd 090
  548.               |                          \^/       |  X= 902   Y= 890
  549.            ^  |     (missile exploding) <-#->      | ------------------
  550.            |  |                          /v\       | 2  M66
  551.               |                                    |  D% 050   Sc 275
  552.            Y  |              +        (missiles    |  Sp 100   Hd 180
  553.               |                     +   flying)    |  X=  89   Y= 534
  554.            a  |                                    | ------------------
  555.            x  |   2                                | 3  NINJA
  556.            i  |                                    |  D% 000   Sc 045
  557.            s  |                                    |  Sp 000   Hd 000
  558.               |                 3                  |  X= 423   Y= 350
  559.               |                /                   | ------------------
  560.               |          (robots)                  |
  561.               |                                    |
  562.               |                                    |
  563.               |                                    |
  564.               |                                    |
  565.               |                                    | CPU 
  566.               +------------------------------------+ Cycles:     34512
  567.  
  568.           (x=0,y=0)           X axis -->     (x=999,y=0)
  569.  
  570.  
  571.  
  572.  
  573.                                         2
  574.  
  575.    The battlefield is 1000 meters by 1000 meters with the coordinates 0,0 in
  576.    the lower left hand corner of the screen.  The border of the battlefield
  577.    has a "fence" or "wall" around it which will cause the robots damage if
  578.    they run into it.  Hitting a border of the battlefield will also cause your
  579.    robot to come crashing to a halt.  On the battlefield, each robot is
  580.    represented by a number from 1 to 4.  (There can be at most four robots in
  581.    any one contest.)  Flying missiles will be represented on the screen by +
  582.    symbols, and explosions by a flurry of lines and corners -- as can be seen
  583.    above.
  584.  
  585.    Beside the battlefield are several "status" areas where information about
  586.    each robot is displayed.  The number that precedes the robot's name is its
  587.    symbol on the screen.  For example, the number 2 represents the robot M66
  588.    in the above display.  The "D%" field shows the percentage of damage that
  589.    the robot has incurred so far.  When the damage percentage gets to 100% the
  590.    robot dies.  The "Sc" field shows the direction in degrees (from 0 to 359)
  591.    that the robot's scanner is currently pointed.  The scanner is used to
  592.    detect the presence of enemy robots and to aim missiles at them.  The "Sp"
  593.    field show the robot's current speed.  A speed of zero means the robot is
  594.    standing still and the maximum speed is 100.  The "Hd" field show the
  595.    robot's current heading, i.e., the direction it is moving.  Like the
  596.    scanner field, the heading is shown in degrees from 0 to 359.  The "X=" and
  597.    "Y=" fields show the robot's current X and Y coordinates on the
  598.    battlefield, respectively.  The  X-axis runs from 0 on the left to 999 on
  599.    the right side of the battlefield.  The Y-axis runs from 0 at the bottom on
  600.    the screen to 999 at the top.
  601.  
  602.    All angles/directions in P-ROBOTS are calculated in degrees from 0 to 359
  603.    using the traditional compass directions you undoubted learned in Geometry. 
  604.    Due east is zero degrees, north is 90 degrees, etc.:
  605.  
  606.               135    90   45
  607.                   \  |  /
  608.                    \ | /
  609.              180 --- x --- 0
  610.                    / | \ 
  611.                   /  |  \ 
  612.               225   270   315
  613.  
  614.  
  615. INVOKING A CONTEST
  616.  
  617.    Sooner or later, you are going to get tired just watching the DEMO match
  618.    and will want to see contests between other robots - perhaps, even your own
  619.    robot creations.  There are two types of contests: single games or matches. 
  620.    In single game mode, the game is played with animated "graphics" where the
  621.    progress of the battle can be watched on the screen.  Match play is when
  622.    you want to run a series of contests (maybe as many as 100) between the
  623.    same group of robots to see what the winning percentages are for each
  624.    contestant.  Match play does not display the actual battles, but just shows
  625.    the summary of wins and loses as each individual game is played.  Match
  626.    play is ideal for playing overnight.
  627.  
  628.    If you want to stop a P-ROBOTS game (either single game or match), just hit
  629.    Control-Break.
  630.  
  631.  
  632.                                         3
  633.  
  634.    To run a single game, just give a command at the DOS prompt like:
  635.  
  636.              P-ROBOTS Robot1 Robot2 .. Robot3
  637.  
  638.    For example, to run a single game between the robots: NINJA, HOTSHOT, WIMP
  639.    and BLASTER you would enter the command:
  640.  
  641.              P-ROBOTS NINJA HOTSHOT WIMP BLASTER
  642.  
  643.    Or to run a single game between HOTSHOT and WIMP you would enter the
  644.    command:
  645.  
  646.              P-ROBOTS HOTSHOT WIMP
  647.  
  648.    It is also possible to test your robot against a "default" robot, named
  649.    TARGET, that is built into the P-ROBOTS program.  TARGET just sits in the
  650.    center of the battlefield waiting to get shot at.  However, TARGET does
  651.    shoot back -- so be warned that beating TARGET is not totally a trivial
  652.    exercise.  TARGET is an excellent opponent for testing new robots.  For
  653.    example, to test a robot named FRED against TARGET, just give the command:
  654.  
  655.              P-ROBOTS FRED
  656.  
  657.    To invoke a series of contest, i.e., match play, append a "/MNNN" behind
  658.    the  normal single play command, where NNN represents the number of games
  659.    you wish to play in the match.  For example, "/M50" would cause 50 games to
  660.    be played in the match and "/M100" would cause 100 games to be played.  
  661.    HOTSHOT, WIMP and BLASTER you would enter the command:
  662.  
  663.              P-ROBOTS NINJA HOTSHOT WIMP BLASTER /M20
  664.  
  665.    Or to run a series of 10 games between HOTSHOT and WIMP you would enter the
  666.    command:
  667.  
  668.              P-ROBOTS HOTSHOT WIMP /M10
  669.  
  670.    IMPORTANT NOTE: The actual files on the disk containing the source code for
  671.    the various robots MUST have a .PR file extension.  However, when the game
  672.    is invoked, the use of this extension is optional.
  673.  
  674.  
  675. CONTROLLING YOUR ROBOT'S MOVEMENT
  676.  
  677.    To move your robot in P-ROBOTS you must use the special procedure "Drive"
  678.    that is built into the P-ROBOTS version of the PASCAL language.  The Drive
  679.    procedure would be used in your program as:
  680.  
  681.              Drive (degree,speed);
  682.  
  683.    This would cause your robot to move in the direction specified by "degree"
  684.    and at the speed indicated by the second parameter, "speed".  The direction
  685.    will be forced by the Drive procedure to be between 0 and 359 (i.e., degree
  686.    := degree MOD 360;) and the speed will be restricted to between 0 and the
  687.    maximum of 100.  Calling the Drive procedure with a speed of zero, will
  688.    cause your robot to stop.
  689.  
  690.  
  691.                                         4
  692.  
  693.    For example:
  694.  
  695.              Drive(90,100);  (* drive north at top speed *)
  696.              Drive(heading,0); (* slow down and stop *)
  697.  
  698.    In an attempt to simulate some degree of reality, a robot's speed does not
  699.    change instantly, but rather has to go through periods of acceleration and
  700.    deceleration.  For example, to stop a robot traveling at a maximum speed of
  701.    100 will take between 100 and 200 meters.  Conversely, to get up to a speed
  702.    of 100 from a standing stop will also take between 100 and 200 meters.
  703.  
  704.    Also, your robot will not be able to "turn on a dime".  You must be moving
  705.    at a speed of 50 or less to change directions.  Attempting to turn while
  706.    going over 50 will cause your robot's drive motor to "over heat" and your
  707.    robot will just coast to a stop on its current heading.
  708.  
  709.    To monitor the status of your movement on the battlefield, the P-ROBOTS
  710.    version of PASCAL has several special built-in functions.
  711.  
  712.    The built-in "Speed" function returns the current speed of your robot (from
  713.    0 to 100).  Remember that the value returned by Speed may not always be the
  714.    same as the last parameter used in the last call to Drive, because of
  715.    acceleration and deceleration.
  716.  
  717.    An example of how the Speed function might be used is as follows:
  718.  
  719.         Drive(270,100);        (* start driving, due south *)
  720.          ; ; ;                 (* other instructions *)
  721.         IF Speed = 0           (* check if stopped, i.e., current speed = 0 *)
  722.             THEN Drive(90,20); (* Probably, ran into the south border *)
  723.                                (* Go north at speed of 20 *) 
  724.  
  725.    The built-in "Loc_X" and "Loc_Y" functions return your robots X and Y
  726.    coordinates on the battlefield, respectively.  The following shows how
  727.    these functions might be used:
  728.  
  729.        Drive (45,50);  (* start driving in north-easterly direction *)
  730.        WHILE (Loc_X < 900) AND (Loc_Y < 900) DO Drive(45,50); 
  731.             (* i.e., just keep driving until we are close to a border *)
  732.        Drive (45,0);   (* slow down and stop *)
  733.  
  734.  
  735. ATTACKING OTHER ROBOTS
  736.  
  737.    The main offensive weapons available to your robot are its scanner and its
  738.    cannon.  Both of these weapons are controlled by using special built-in
  739.    capabilities of the P-ROBOTS PASCAL language.
  740.  
  741.    The scanner is an "electronic eye" that enables your robot to look for
  742.    enemy robots in any chosen direction from 0 to 359 degrees.  The scanner
  743.    has a maximum resolution of +/- 10 degrees.  This allows your robot to
  744.    quickly scan the battlefield at a low resolution, then use finer resolution
  745.    to pinpoint a foe's precise position.  The scanner would be accessed by a
  746.    reference to the "Scan" function, as follows:
  747.  
  748.              Scan(degree,resolution)  
  749.  
  750.                                         5
  751.  
  752.    This function invokes the robot's scanner, at the specified degree and
  753.    resolution.  This function returns an integer value of 0 if no enemy robots
  754.    are within the scan range or a integer value (greater than 0) representing
  755.    the distance to the nearest robot in the scan area.  The value passed as
  756.    the parameter "degree" will be forced to be in the range 0 to 359. 
  757.    Likewise, the "resolution" will be forced to be in the range of +/- 10
  758.    degrees.
  759.  
  760.    Some examples:
  761.  
  762.        Enemy := Scan(180,10); (* scans the area from 170 to 190 degrees *)
  763.        Dist_To_Foe := Scan(180,2); (* scans from 178 to 182 degrees *)
  764.        Target_Range := Scan(90,0); (* scan 90 degrees, with no variance *)
  765.  
  766.    Once an enemy robot is found with the scanner, you would use your robot's
  767.    cannon to fire a missile at the enemy.  This is done by using P-ROBOTS
  768.    special "Cannon" procedure:
  769.  
  770.              Cannon(degree,range);
  771.  
  772.    This will fire a missile in the direction specified by the parameter
  773.    "degree" and for a distance specified by the value of "range".  Your
  774.    robot's cannon has a maximum range of 700 meters.  There are an unlimited
  775.    number of missiles -- so you need not worry about running out.  However, it
  776.    will take some time to reload between firing missiles; so that, the number
  777.    of missiles in the air at any one time to limited to two.  The cannon is
  778.    mounted on an independent turret, and therefore can fire in any direction,
  779.    regardless of the robot's current movement direction.
  780.  
  781.    For example, the following "chunk" of code will cause your robot to
  782.    constantly scan for enemies and blast away at them as long as they are in
  783.    sight.  When they are no longer in sight (or in range), the scanner will
  784.    move to the next 20 degree segment of the circle:
  785.  
  786.        Angle := 0; (* initialize to east *)
  787.        REPEAT
  788.          Enemy_Range := Scan(Angle,10); (* Get range to target -- if any *)   
  789.       
  790.          WHILE (Enemy_Range > 40) AND (Enemy_Range <= 700) DO
  791.            BEGIN (* Enemy in sight and in range *)
  792.              Cannon(Angle,Enemy_Range); (* Blast it! *) 
  793.              Enemy_Range := Scan(Angle,10); (* Still there? *)
  794.            END;
  795.            Angle := Angle + 20; (* move search to next segment *)
  796.         UNTIL Dead or Winner;
  797.  
  798.    The "Dead" and the "Winner" in the UNTIL statement are special pre-defined
  799.    Boolean functions in P-ROBOTS.  Dead will have a value of FALSE while your
  800.    robot is still alive (i.e., its damage is less than 100%) and TRUE when it
  801.    finally dies.  Similarly, Winner will be TRUE if your robot is the last
  802.    survivor of the battle and FALSE otherwise.
  803.  
  804.  
  805.  
  806.  
  807.  
  808.                                         6
  809.  
  810.    If your robot utilized the basic "Sitting Duck" strategy given above, its
  811.    opponents would undoubtedly make short work of it.  To make the strategy a
  812.    little smarter, we need some way to determine if we are under attack. 
  813.    Fortunately (and not surprisingly), P-ROBOTS has another special function
  814.    that can assist us -- the "Damage" function.  Whenever you use this
  815.    function in your code, it will return an integer value of your robot's
  816.    current damage percentage.  If this value changes, then we know the robot
  817.    is under attack and it probably should run for safety.
  818.  
  819.    As an example, let's see how the Damage function could be used to make the
  820.    above code a little smarter:
  821.  
  822.         Old_Damage := Damage; (* Get initial value of damage *)   
  823.         Angle := 0; (* initialize to east *)
  824.         REPEAT      
  825.           Enemy_Range := Scan(Angle,10); (* Get range to target -- if any *)
  826.           WHILE (Enemy_Range > 40) AND (Enemy_Range <= 700) DO 
  827.             BEGIN (* Enemy in sight and in range *)
  828.               Cannon(Angle,Enemy_Range); (* Blast it! *)
  829.               Enemy_Range := Scan(Angle,10); (* Still there? *)        
  830.             END;
  831.           Angle := Angle + 20; (* move search to next segment *)
  832.           IF Damage > Old_Damage THEN
  833.             BEGIN (* Under attack *)
  834.               Old_Damage := Damage; (* Get latest Damage value *)
  835.               Move; (* Get out of here!! *)
  836.             END;
  837.         UNTIL Dead or Winner;
  838.  
  839.    The "Move" reference above would call a separate procedure that would move
  840.    the robot to another position on the battlefield where it will hopefully be
  841.    safer.  This procedure will be given a little latter as another example.
  842.  
  843.  
  844. OTHER SPECIAL P-ROBOTS FUNCTIONS AND PROCEDURES
  845.  
  846.  
  847. TIME
  848.  
  849.    The built-in Time function returns the current time as measures by the
  850.    P-ROBOTS' CPU cycles.  By using this function, you should be able to
  851.    calculate the speed of your enemies.  The value returned by this function
  852.    is restricted to being in the range 0 to 32767 and when it gets to 32767 it
  853.    starts again at zero.  An example of how you might get this value is as
  854.    follows:
  855.  
  856.              Start_Time := Time;
  857.  
  858.  
  859. DISTANCE
  860.  
  861.    Since your robot will frequently find it useful to be able to calculate
  862.    distances from one point on the battlefield to another, P-ROBOTS provides a
  863.    built-in function to do it:
  864.  
  865.              Distance(X1,Y1,X2,Y2)
  866.  
  867.                                         7
  868.  
  869.    would return the integer distance from the point X1,Y1 to the point X2,Y2.
  870.  
  871.  
  872. ANGLE_TO
  873.  
  874.    The Angle_To function will return the angle to a point on the battlefield
  875.    from your robot's current position.  The value returned will be an integer
  876.    in degrees from 0 to 359.  As an example of how both the Distance and
  877.    Angle_To functions might be used, consider the following procedure that
  878.    will move your robot to the point X,Y on the battlefield:
  879.  
  880.         PROCEDURE GoTo(X, Y : Integer);(* Go to location X,Y *)
  881.           VAR
  882.             Heading  : Integer;
  883.         BEGIN       (* Find the heading we need to get to the desired spot. *)
  884.           Heading := Angle_To(X, Y);
  885.  
  886.           (* Keep traveling at top speed until we are within 150 meters. *)
  887.           WHILE (Distance(Loc_X, Loc_Y, X, Y) > 150) DO Drive(Heading, 100);
  888.  
  889.           (* Cut speed, and creep the rest of the way. *)
  890.           WHILE (Distance(Loc_X, Loc_Y, X, Y) > 20) DO Drive(Heading, 20);
  891.  
  892.           (* Stop driving, should coast to a stop. *)
  893.           Drive(Heading, 0); (* I.E., Stop *)
  894.         END; (* GoTo(X,Y) *)
  895.  
  896.  
  897. RANDOM
  898.  
  899.    The function Random(limit) returns a random integer between 0 and limit. 
  900.    As an example, the following procedure will cause your robot to move to a
  901.    random spot on the battlefield:
  902.  
  903.        PROCEDURE Move; (* Move to a random spot on the playing field. *)
  904.          VAR
  905.            x, y       : Integer;
  906.        BEGIN
  907.          x := Random(900) + 50;
  908.          y := Random(900) + 50;
  909.          GoTo(x, y);
  910.        END; (* Move *)
  911.  
  912.    Notice that the Move procedure makes use of the GoTo(X,Y) procedure
  913.    developed in the previous example.
  914.  
  915.  
  916. TRIG FUNCTIONS
  917.  
  918.    P-ROBOTS has several standard Trig functions that will be of value to a
  919.    clever robot, specifically:
  920.  
  921.              Sin(degree)
  922.  
  923.  
  924.  
  925.                                         8
  926.  
  927.    will return the real value of the Sin of an angle of degree where degree is
  928.    an integer from 0 to 359.
  929.  
  930.              Cos(degree)
  931.  
  932.    will return the real value of the Cos of an angle of degree where degree is
  933.    an integer from 0 to 359.
  934.  
  935.              ArcTan(ratio)
  936.  
  937.    will the angle in integer degrees that has a Tan of ratio.
  938.  
  939.  
  940. INFLICTING DAMAGE
  941.  
  942.    Your robot can be damaged by only two things: collisions and missiles.  The
  943.    level of damage is given by the following table:
  944.  
  945.      2%  --    A collision with another robot (both robots in a collision
  946.                receive damage) or one of the battlefield walls.  A collision
  947.                also causes the robot to stop cold, i.e., its speed is reduced
  948.                instantly to 0.
  949.  
  950.      3%  --    A missile explodes within a 40 meter radius.
  951.  
  952.      5%  --    A missile explodes within a 20 meter radius.
  953.  
  954.      10% --    A missile explodes within a 5 meter radius.
  955.  
  956.    Damage is inflicted on ALL robots within these distances.  That means that
  957.    if one of your own missiles explodes within 40 meters of your robot, it
  958.    causes damage.  Using sloppy programming logic, it is possible for your
  959.    robot to commit suicide by firing missiles too close to itself.  For
  960.    example, your robot would not last long with this code:
  961.  
  962.              Drive(Angle,100);
  963.              WHILE (Loc_X < 999) DO Cannon(Angle,Scan(Angle,10));
  964.  
  965.    Damage is cumulative, and cannot be repaired.  However, a robot does not
  966.    loose any mobility, fire potential, etc. at high damage levels.  In other
  967.    words, a robot at 99% damage performs equally as well as a robot with no
  968.    damage.  However, when the damage level gets to 100% your robot is dead and
  969.    it is out of the current competition.
  970.  
  971.  
  972. PUTTING IT ALL TOGETHER
  973.  
  974.    Here is a complete sample robot named HotShot:
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.                                         9
  985.  
  986.       PROCEDURE HotShot;
  987.       (* Author: David Malmberg
  988.  
  989.       Strategy:  Stay in one place.  Find a foe.  Take a shot.
  990.       Keep improving aim and shooting until foe is lost from sights.
  991.       Then move sights (scanning) to adjacent target area.  If hit, 
  992.       then move to another random position on playing field.  If the
  993.       Robot scans two complete circles (720 degrees) without finding
  994.       a foe in shooting range, move to another spot on the field.
  995.       (This will avoid "stand-offs" where opponents stay just out of
  996.       range of one another.)
  997.  
  998.       This Robot should be VERY effective against foes which are
  999.       stopped or are moving slowly.  It will be less effective
  1000.       against Robots traveling at high speeds.   *)
  1001.  
  1002.       VAR (* HotShot "Global" variables *)
  1003.         Angle,       (* Scanning angle *)
  1004.         Last_Damage, (* Robot's last damage value *)
  1005.         Range,       (* Range/Distance to foe *)
  1006.         Sweep,       (* "Sweep count" when = 36, have scanned 720 degrees *)
  1007.         Delta        (* Scanning arc *)
  1008.                     : Integer;
  1009.  
  1010.        PROCEDURE GoTo(X, Y : Integer);
  1011.           (* Go to location X,Y on playing field. *)
  1012.         VAR
  1013.           Heading  : Integer;
  1014.        BEGIN       (* Find the heading we need to get to the desired spot. *)
  1015.           Heading := Angle_To(X, Y);
  1016.  
  1017.          (* Keep traveling at top speed until we are within 150 meters. *)
  1018.          WHILE (Distance(Loc_X, Loc_Y, X, Y) > 150) DO Drive(Heading, 100);
  1019.  
  1020.          (* Cut speed, and creep the rest of the way. *)
  1021.          WHILE (Distance(Loc_X, Loc_Y, X, Y) > 20) DO Drive(Heading, 20);
  1022.  
  1023.          (* Stop driving, should coast to a stop. *)
  1024.          Drive(Heading, 0); (* I.E., Stop *)
  1025.        END; (* GoTo(X,Y) *)
  1026.  
  1027.        FUNCTION Hurt  : Boolean;
  1028.         (* Checks if Robot has incurred any new damage. *)
  1029.         VAR
  1030.           Curr_Damage  : Integer;
  1031.           Answer       : Boolean;
  1032.        BEGIN
  1033.           Curr_Damage := Damage;
  1034.           Answer := (Curr_Damage > Last_Damage);
  1035.           Last_Damage := Curr_Damage;
  1036.           Hurt := Answer;
  1037.        END; (* Hurt *)
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.                                         10
  1044.  
  1045.        PROCEDURE Move;
  1046.         (* Move to a random spot on the playing field. *)
  1047.         VAR
  1048.           x, y       : Integer; 
  1049.        BEGIN
  1050.           Sweep := 0; (* Reset Sweep counter to zero. *)
  1051.           x := Random(900) + 50;
  1052.           y := Random(900) + 50;
  1053.           GoTo(x, y);
  1054.        END; (* Move *)
  1055.  
  1056.        PROCEDURE Aim( VAR Ang : Integer; VAR Arc : Integer);
  1057.         (* Improve aim by doing a binary search of the target area.
  1058.            I.E., divide the target area in two equal pieces and redefine
  1059.            the target area to be the piece where the foe is found.
  1060.            If the foe is not found, expand the search area to the
  1061.            maximum arc of plus or minus 10 degrees. *)
  1062.        BEGIN
  1063.           (* Divide search area in two. *) 
  1064.           Arc := Arc DIV 2;
  1065.           (* Check piece "below" target angle. *)
  1066.           IF Scan(Ang - Arc, Arc) <> 0
  1067.             (* If foe found, redefine target angle. *)
  1068.             THEN Ang := Ang - Arc
  1069.             (* If not found, then check piece "above" target angle. *)
  1070.             ELSE IF Scan(Ang + Arc, Arc) <> 0
  1071.                    (* If foe found, redefine target angle. *)
  1072.                    THEN Ang := Ang + Arc
  1073.                    ELSE Arc := 10;
  1074.           (* If foe not found in either piece, expand search arc to +/- 10 *)
  1075.        END; (* Aim *)
  1076.  
  1077.       BEGIN (* HotShot Main *)
  1078.         (* Start scanning for foes in center of field. *)
  1079.         Angle := Angle_To(500, 500);
  1080.         Sweep := 0; (* Initialize Sweep counter to zero. *)
  1081.         REPEAT (* Until Dead or Winner *)  
  1082.           Delta := 10; (* Start with widest scanning arc. *)
  1083.           Range := Scan(Angle, Delta);
  1084.           WHILE (Range > 40) AND (Range < 701) DO
  1085.             (* Must be far enough away to avoid self-damage. *)
  1086.             BEGIN
  1087.               Sweep := 0; (* Found foe, so reset Sweep to zero *)
  1088.               Aim(Angle, Delta); (* Improve aim. *)
  1089.               Cannon(Angle, Range); (* Fire!! *)
  1090.               Range := Scan(Angle, Delta); (* Is foe still in sights? *)
  1091.             END;
  1092.           Angle := Angle + 20; (* Look in adjacent target area. *)
  1093.           Sweep := Sweep + 1;
  1094.           IF Hurt OR (Sweep = 36) THEN Move;
  1095.           (* If hit or have scanned two full circles, move elsewhere. *)
  1096.         UNTIL Dead OR Winner;
  1097.       END; (* HotShot Main *)
  1098.  
  1099.  
  1100.  
  1101.  
  1102.                                         11
  1103.  
  1104. ROBOT PROGRAMMING RULES
  1105.  
  1106.    There are several things in the above example the you should think of as
  1107.    rules that your robots should ALWAYS observe.
  1108.  
  1109.      1.   Your robot should be in a "self-contained" PROCEDURE with the
  1110.           following basic structure:
  1111.  
  1112.                    PROCEDURE RoboName;
  1113.  
  1114.                      {"Global" Variables}
  1115.  
  1116.                      FUNCTION A;
  1117.                         ....
  1118.                      PROCEDURE B;
  1119.                         ....
  1120.                      FUNCTION Z;
  1121.  
  1122.                    BEGIN {RoboName Main}
  1123.                         ....
  1124.                    END; {RoboName Main}
  1125.  
  1126.           Failure to follow this basic structure will cause the P-ROBOTS
  1127.           program and your robot to both meet a fiery death.
  1128.  
  1129.      2.   A robot should have its PROCEDURE named exactly the same name as the
  1130.           file with the code for the robot (except for the .PR extension). 
  1131.           I.E., the HotShot robot procedure should be in a  file named
  1132.           HOTSHOT.PR.  Again, failure to follow this rule will cause your
  1133.           robot program to crash.
  1134.  
  1135.      3.   In the "main" routine for your robot, you need to have some kind of
  1136.           "infinite" loop that is repeat endlessly.  In the sample robot,
  1137.           HOTSHOT, this loop is the REPEAT ... UNTIL structure:
  1138.  
  1139.                   REPEAT (* Until Dead or Winner *)
  1140.                     ....
  1141.                   UNTIL Dead OR Winner;
  1142.  
  1143.           Another "infinite" loop that would works equally well is:
  1144.  
  1145.                   WHILE (NOT Dead) AND (NOT Winner) DO
  1146.                     BEGIN 
  1147.                       ....
  1148.                     END;
  1149.  
  1150.      4.   Your robot source code should be very well documented with comments.
  1151.  
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.                                         12
  1162.  
  1163. ADVANCED P-ROBOT FEATURES
  1164.  
  1165.    All of the robot programming ground rules and robot-specific language
  1166.    presented up to this point correspond to features found in C-ROBOTS by Tom
  1167.    Poindexter -- which was the inspiration for P-ROBOTS.  After P-ROBOTS had
  1168.    been released for several months, users had made a number of suggestions
  1169.    for improvements and new features.  In version 2.0 (first released in
  1170.    December 1989), I tried to incorporate the best suggestions.  Specifically,
  1171.    version 2.0 adds the following improvements and new features:
  1172.  
  1173.           *  Animation Speed Options
  1174.           *  Protective Shields
  1175.           *  Fuel Constraints
  1176.           *  Robot Teams
  1177.           *  Obstructions on the Battlefield
  1178.           *  Intelligence Options
  1179.  
  1180.    NOTE: All of these new features are optional.  Your old version 1.0 robots
  1181.    can still be used just as they have always been used.
  1182.  
  1183.  
  1184. CONTROLLING THE ANIMATION SPEED
  1185.  
  1186.    Since not all computers operate at the same speed, it is very desireable to
  1187.    be able to control the animation speed of the robot contest.  This can be
  1188.    done by using another command line parameter, the "/SN" parameter, where N
  1189.    can be either 1, 2, 3 or 4.  A value of 1 corresponds to the slowest
  1190.    animation speed and 4 is the fastest.  The normal default setting is 4 or
  1191.    the fastest speed.  A value of 4 will normally look fine on an 8086 or
  1192.    80286 computer.  If you are using a 386 machine, you will probably want to
  1193.    use one of the slower animation speeds.  For example, to run a single game
  1194.    between the robots: NINJA, HOTSHOT, WIMP and BLASTER at a moderately slow
  1195.    animation speed (i.e., a speed of 2) you would enter the command:
  1196.  
  1197.              P-ROBOTS NINJA HOTSHOT WIMP BLASTER /S2
  1198.  
  1199.    If you are playing a series of contests (i.e., match play), you should not
  1200.    slow down the speed since these games are not displayed/animated anyway.
  1201.  
  1202.  
  1203. PROTECTIVE SHIELDS
  1204.  
  1205.    In version 2.0 of P-ROBOTS, your robot can use a protective shield by using
  1206.    the command "RaiseShield".  When your robot's shield is up, your robot will
  1207.    not incur any damage from collisions or cannon explosions.  The shield may
  1208.    be lowered by using the command "LowerShield".  The status of your robot's
  1209.    shield can be determined by using the built-in Boolean function,
  1210.    "ShieldRaised" which will return a value of TRUE or FALSE based on your
  1211.    robot's shield condition.  For example, you might want to use the following
  1212.    statement in a robot program:
  1213.  
  1214.              IF NOT ShieldRaised THEN RaiseShield;
  1215.  
  1216.    Of course, there must be a "catch" to using your Shield -- or there would
  1217.    not be any real challenge to a robot contest.  The catch is that your
  1218.    Shield MUST use scarce fuel resources as explained in the next section.
  1219.  
  1220.                                         13
  1221.  
  1222.    NOTE: Unlike the Starship Enterprise, your robot has only one Shield (i.e.,
  1223.    singular) not multiple Shields (plural).  If you use "Shields" (plural) in
  1224.    your robot programs, you will get a compiler error for an "UNKNOWN
  1225.    IDENTIFIER".
  1226.  
  1227.  
  1228. FUEL CONSTRAINTS
  1229.  
  1230.    Many people have commented that P-ROBOTS (and C-ROBOTS before it) seemed to
  1231.    favor robots that used "brute force" rather than "raw cunning" -- i.e., all
  1232.    other things being equal, robots that fired often seem to beat robots that
  1233.    fired accurately.  In an effort to create a little more level playing field
  1234.    for smart robots, I added fuel constraints to version 2.0.  Under these
  1235.    constraints, robots that fire indiscriminately will waste valuable fuel and
  1236.    will ultimately run out of fuel and find themselves defenseless and at the
  1237.    mercy of their wiser and more fuel efficient opponents.
  1238.  
  1239.    When having a robot battle that has fuel constraints, each robot begins the
  1240.    contest with 1000 "jiggers" of fuel.  Then during the contest, fuel is used
  1241.    up at the following rates:
  1242.  
  1243.           *  Firing a missile takes 3 jiggers
  1244.           *  Traveling 100 meters takes 5 jigger
  1245.           *  Having a shield up for 200 CPU cycles takes 1 jigger
  1246.  
  1247.    In addition, if your robot's Shield is up, whenever your robot would have
  1248.    incurred damage from a missile or a collision, it uses twice the number of
  1249.    jiggers of fuel to absorb the damage as it would have incurred in damage had
  1250.    its Shield been down.  For example, when your robot's Shield is up,
  1251.    absorbing a direct missile hit uses 20 jiggers of fuel; absorbing the
  1252.    impact of a collision with another robot uses 4 jiggers of fuel, etc.  So,
  1253.    it is prudent for your robot to take care to avoid missiles and collisions
  1254.    even if its Shield is raised.
  1255.  
  1256.    The number of jiggers of each robot's fuel is displayed continuously next
  1257.    to the robot's name on the screen.  This value may be accessed from within a
  1258.    robot program by using the built-in function "Fuel". For example, you might
  1259.    want to use the following logic in a robot program to begin a special
  1260.    "End-Game" strategy when your fuel gets low:
  1261.  
  1262.              IF Fuel < 200 THEN End_Game;
  1263.  
  1264.    There are several other built-in P-ROBOTS functions that may be useful when
  1265.    you have fuel constraints.  Specifically, "LimitedFuel" will return a TRUE
  1266.    or FALSE based upon whether the contest your robot is playing in has fuel
  1267.    constraints or not.  The built-in function "Meters" is like an Odometer on
  1268.    a car -- only it returns the number of meters your robot has traveled since
  1269.    the beginning of the contest.  For example, you might wish to use the
  1270.    following command in your robot's program to invoke your "End-Game"
  1271.    strategy:
  1272.  
  1273.              IF LimitedFuel 
  1274.                 THEN IF (Meters > 20000) OR (Fuel < 200) THEN End_Game;
  1275.  
  1276.  
  1277.                                         14
  1278.  
  1279.    To have a robot contest with fuel constraints, you must use a "/F" command
  1280.    line parameter when you invoke your contest.  For example, to run a single
  1281.    game between the robots: NINJA, WIMP and BLASTER with fuel constraints, you
  1282.    would enter the following command at the DOS prompt:
  1283.  
  1284.              P-ROBOTS NINJA WIMP BLASTER /F
  1285.  
  1286.    If you wish to have a series of 50 matches with fuel constraints between
  1287.    the same group of robots, you would add a "/M50" parameter to the command
  1288.    as follows:
  1289.  
  1290.              P-ROBOTS NINJA WIMP BLASTER /F /M50
  1291.  
  1292.  
  1293. RUNNING OUT OF FUEL
  1294.  
  1295.    When you robot runs out of fuel it does everything you might expect: it
  1296.    stops cold and can no longer move; it can no longer fire its cannon; and it
  1297.    can no longer maintain a raised shield.  In other words, it is totally and
  1298.    absolutely defenseless.  Other robots which still have fuel will make quick
  1299.    work of any robot that is unfortunate enough to become a "sitting duck" by
  1300.    running out of fuel.  If all of the robots in the game run out of fuel, the
  1301.    game is over and the robot with the least damage (i.e., the strongest of
  1302.    the survivors) is declared the winner.
  1303.  
  1304.  
  1305. AN EXAMPLE USING A SHIELD AND FUEL
  1306.  
  1307.    Here is an example of how the previous example robot, HOTSHOT, might be
  1308.    modified to use its Shield and consider Fuel constraints:
  1309.  
  1310.  
  1311.      PROCEDURE HotShot2;
  1312.      {
  1313.       Author: David Malmberg
  1314.  
  1315.       Strategy:  Stay in one place.  Find a foe.  Take a shot.
  1316.       Keep improving aim and shooting until foe is lost from sights.
  1317.       Then move sights (scanning) to adjacent target area.
  1318.       If the Robot scans a complete circle (360 degrees) without
  1319.       finding a foe in shooting range, move to another spot on the
  1320.       field.  (This will avoid "stand-offs" where opponents stay
  1321.       just out of range of one another.)  RaiseShield when standing
  1322.       still and lower them when moving.
  1323.  
  1324.       When damage gets to 70 (or more) or fuel (if using fuel) gets
  1325.       below 200 adopt an "End-Game" strategy of moving to the lower
  1326.       left corner, lower shield, and continue to scan and shoot in
  1327.       the corner's 90 degree range.
  1328.  
  1329.       This Robot should be VERY effective against foes which
  1330.       are stopped or are moving slowly.  It will be less effective
  1331.       against Robots traveling at high speeds.
  1332.  
  1333.  
  1334.                                         15
  1335.       This Robot has been designed to utilize Fuel (if it is available)
  1336.       to power its Shield.  However, it has NOT been designed to deal
  1337.       effectively with Obstructions.
  1338.      }
  1339.  
  1340.      VAR { HotShot2 "Global" variables }
  1341.        Angle, { Scanning angle }
  1342.        Range, { Range/Distance to foe }
  1343.        Sweep, { "Sweep count" -- when = 18, Robot has scanned 360 degrees }
  1344.        Delta          : Integer; { Scanning arc }
  1345.  
  1346.        PROCEDURE GOTO(x, y : Integer);
  1347.          { Go to location X,Y on playing field. }
  1348.        VAR Heading    : Integer;
  1349.        BEGIN
  1350.          { Find the heading we need to get to the desired spot. }
  1351.          Heading := Angle_To(x, y);
  1352.  
  1353.          { Keep traveling at top speed until we are within 150 meters }
  1354.          WHILE (distance(loc_x, loc_y, x, y) > 150) DO drive(Heading, 100);
  1355.  
  1356.          { Cut speed, and creep the rest of the way. }
  1357.          WHILE (distance(loc_x, loc_y, x, y) > 20) DO drive(Heading, 20);
  1358.  
  1359.          { Stop driving, should coast to a stop. }
  1360.          drive(Heading, 0); {I.E., Stop}
  1361.        END; {GoTo(X,Y)}
  1362.  
  1363.        PROCEDURE Move;
  1364.          { Move to a random spot on the playing field. }
  1365.        VAR x, y       : Integer;
  1366.        BEGIN
  1367.          Sweep := 0; { Reset Sweep counter to zero. }
  1368.          x := Random(900)+50;
  1369.          y := Random(900)+50;
  1370.          GOTO(x, y);
  1371.        END; {Move}
  1372.  
  1373.        PROCEDURE Aim( VAR Ang : Integer; VAR Arc : Integer);
  1374.         (* Improve aim by doing a binary search of the target area.
  1375.            I.E., divide the target area in two equal pieces and redefine
  1376.            the target area to be the piece where the foe is found.
  1377.            If the foe is not found, expand the search area to the
  1378.            maximum arc of plus or minus 10 degrees. *)
  1379.        BEGIN
  1380.           (* Divide search area in two. *) 
  1381.           Arc := Arc DIV 2;
  1382.           (* Check piece "below" target angle. *)
  1383.           IF Scan(Ang - Arc, Arc) <> 0
  1384.             (* If foe found, redefine target angle. *)
  1385.             THEN Ang := Ang - Arc
  1386.             (* If not found, then check piece "above" target angle. *)
  1387.             ELSE IF Scan(Ang + Arc, Arc) <> 0
  1388.                    (* If foe found, redefine target angle. *)
  1389.                    THEN Ang := Ang + Arc
  1390.                    ELSE Arc := 10;
  1391.           (* If foe not found in either piece, expand search arc to +/- 10 *)
  1392.        END; (* Aim *)
  1393.                                         16
  1394.  
  1395.      PROCEDURE End_Game;
  1396.      { Special strategy for "End Game" }
  1397.      BEGIN {End_Game}
  1398.        GoTo(0,0); {Lower Left Corner}
  1399.        Angle := 10; {Sweep arc from 0 to 90 degrees only}
  1400.        REPEAT
  1401.          Delta := 10; { Start with widest scanning arc. }
  1402.          Range := scan(Angle, Delta);
  1403.          WHILE (Range > 40) AND (Range < 700) DO
  1404.            { Must be far enough away to avoid self-damage. }
  1405.            BEGIN
  1406.              Aim(Angle, Delta); { Improve aim. }
  1407.              cannon(Angle, Range); { Fire!! }
  1408.              Range := scan(Angle, Delta); { Is foe still in sights? }
  1409.            END;
  1410.          Angle := Angle+20; { Look in adjacent target area. }
  1411.          IF Angle > 90 THEN Angle := 10;
  1412.        UNTIL Dead OR Winner;
  1413.      END; {End_Game}
  1414.  
  1415.      BEGIN {HotShot2 Main}
  1416.        RaiseShield;
  1417.        Angle := 0;
  1418.        GoTo(500, 500); { Move to center of field. }
  1419.        Sweep := 0; { Initialize Sweep counter to zero. }
  1420.        REPEAT { Until Dead or Winner }
  1421.          Delta := 10; { Start with widest scanning arc. }
  1422.          Range := scan(Angle, Delta);
  1423.          WHILE (Range > 40) AND (Range < 700) DO
  1424.            { Must be far enough away to avoid self-damage. }
  1425.            BEGIN
  1426.              Sweep := 0; { Found foe, so reset Sweep to zero }
  1427.              Aim(Angle, Delta); { Improve aim. }
  1428.              cannon(Angle, Range); { Fire!! }
  1429.              Range := scan(Angle, Delta); { Is foe still in sights? }
  1430.            END;
  1431.          Angle := Angle+20; { Look in adjacent target area. }
  1432.          Sweep := Sweep+1;
  1433.          IF Sweep >= 18 THEN
  1434.            BEGIN { If robot has scanned a full circle, move elsewhere. }
  1435.              LowerShield; {Don't need shield (as much) when moving}
  1436.              Move;
  1437.            END;
  1438.          RaiseShield; {Standing still so use shield}
  1439.          {"End" game strategy}
  1440.          IF (Fuel < 200) OR (Damage > 70) THEN End_Game;
  1441.        UNTIL Dead OR Winner;
  1442.      END; {HotShot2 Main}
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449.  
  1450.  
  1451.  
  1452.                                         17
  1453.  
  1454. ROBOT TEAMS
  1455.  
  1456.    One of the most intriguing suggestions that I received from version 1.0
  1457.    users of P-ROBOTS was the idea of allowing two robots to act as members of
  1458.    the same team and to communicate with each other during the course of the
  1459.    battle.  This option has been added to version 2.0.
  1460.  
  1461.    NOTE: For consistency and better understanding, if your robot is a member
  1462.    of a two robot team, the other team member is referred to as your robot's
  1463.    "Ally".  Similarly, within your Ally's robot program, your robot would be
  1464.    referred to as its Ally.
  1465.  
  1466.    Robot teams may use the following special built-in P-ROBOTS functions:
  1467.  
  1468.           AllyLoc_X -- returns the current X coordinate of your Ally
  1469.  
  1470.           AllyLoc_Y -- returns the current Y coordinate of your Ally
  1471.  
  1472.           AllyDamage -- returns your Ally's current Damage level
  1473.  
  1474.           AllySpeed -- returns your Ally's current Speed
  1475.  
  1476.           AllyHeading -- returns your Ally's current Heading
  1477.  
  1478.           AllyMeters -- returns your Ally's current Meters
  1479.  
  1480.           AllyFuel -- returns your Ally's current Fuel level
  1481.  
  1482.           AllyShieldRaised -- returns TRUE or FALSE depending upon whether
  1483.           your Ally's shield is raised or not
  1484.  
  1485.           AllyDead -- returns TRUE or FALSE depending upon whether your Ally
  1486.           is Dead or not
  1487.  
  1488.           AllyAlive -- returns TRUE or FALSE depending upon whether your Ally
  1489.           is Alive or not
  1490.  
  1491.    In addition to using these built-in functions to learn about your Ally's
  1492.    status, it is also possible in version 2.0 for robots to exchange
  1493.    information by access the "global" array COMM[1..20].  All robots may
  1494.    access this array and both retrieve and store values to any of its 20
  1495.    elements.  Be warned however, that stuffing "garbage" into COMM's elements
  1496.    to sabotage the communication between opposing team members is NOT
  1497.    considered to be fair play!!
  1498.  
  1499.    One other piece of information is necessary in order for two robots to work
  1500.    together effectively as a team -- there must be some way to tell if a robot
  1501.    is friend or foe.  The way this is done is to define a special function
  1502.    called "ObjectScanned" which is reset whenever your robot scans the
  1503.    battlefield.  The value returned by ObjectScanned will be one of four
  1504.    specially defined values/constants:  Nothing, Ally, Enemy or Obstruction. 
  1505.    For example, to make sure that you only fire your cannon at enemy robots
  1506.    when you are part of a team, you might want to use statements like the
  1507.    following:
  1508.  
  1509.  
  1510.  
  1511.                                         18
  1512.  
  1513.           Dist := Scan(Angle, Delta);
  1514.           IF ObjectScanned = Enemy THEN Cannon(Angle, Dist); {Blast 'Em!!}
  1515.  
  1516.    To tell the P-ROBOTS compiler that you have an Ally and are part of a team,
  1517.    you need to include a statement within your robot's program that looks
  1518.    like:
  1519.  
  1520.           TeamAlly = "TagTeam2";
  1521.  
  1522.    This statement tells the P-ROBOTS compiler that your Ally is named
  1523.    "TagTeam2".  To work correctly, the robot "TagTeam2" must have a similar
  1524.    statement within its program that identifies your robot's name as its Ally.
  1525.  
  1526.  
  1527. AN EXAMPLE OF A ROBOT TEAM
  1528.  
  1529.    Here is an example of one member of a robot team.  Notice, that this robot
  1530.    and its Ally (named "TagTeam2") communicate by passing information through
  1531.    COMM[10] and COMM[11].
  1532.  
  1533.  
  1534.      PROCEDURE TagTeam1;
  1535.  
  1536.      TeamAlly = "TagTeam2";  (* This statement MUST be included for teams!! *)
  1537.  
  1538.      {
  1539.       Author: David Malmberg
  1540.  
  1541.       Strategy: Go to a random corner, raise shield, and blast away at any
  1542.                 robot in range.  Improve aim after every successful scan.
  1543.                 If the robot scans 20 times unsuccessfully, move to another   
  1544.                 random corner.  Lower shields when moving; raise them when    
  1545.                 stopped.
  1546.  
  1547.                 This robot can act individually or as part of a team with     
  1548.                 another robot that follows an identical strategy, i.e.,       
  1549.                 TagTeam2.  If operating as a team, the two robots communicate 
  1550.                 their corners to each other by setting COMM[10] to TagTeam1's 
  1551.                 corner and COMM[11] to TagTeam2's corner.  They try to always 
  1552.                 pick different random corners.  Operating from different      
  1553.                 corners, the two robots should be able to cover most of the   
  1554.                 battlefield very well.
  1555.  
  1556.                 WARNING: This Robot has NOT been designed to deal with
  1557.                 Obstructions effectively.  However, it has been designed to   
  1558.                 use its Shield (if possible). 
  1559.      }
  1560.  
  1561.      CONST
  1562.        NW_Corner = 1;
  1563.        NE_Corner = 2;
  1564.        SW_Corner = 3;
  1565.        SE_Corner = 4;
  1566.  
  1567.  
  1568.  
  1569.  
  1570.                                         19
  1571.  
  1572.      VAR { TagTeam1 "Global" variables }
  1573.        CornerX : ARRAY[1..4] OF Integer; {X coordinate of Corners}
  1574.        CornerY : ARRAY[1..4] OF Integer; {Y coordinate of Corners}
  1575.        StartAngle : ARRAY[1..4] OF Integer; {Starting scan angles for Corners}
  1576.        Corner, { Current Corner }
  1577.        Times,  { Number of times robot has scanned without success for enemy }
  1578.        Angle,  { Scanning angle }
  1579.        Delta,  { Scanning angle width }
  1580.        Range   { Range/Distance to foe }  : Integer;
  1581.  
  1582.        PROCEDURE Initialize;
  1583.        { Set up Corner data }
  1584.        BEGIN
  1585.          CornerX[NW_Corner] := 10;
  1586.          CornerY[NW_Corner] := 990;
  1587.          StartAngle[NW_Corner] := 270;
  1588.  
  1589.          CornerX[NE_Corner] := 990;
  1590.          CornerY[NE_Corner] := 990;
  1591.          StartAngle[NE_Corner] := 180;
  1592.  
  1593.          CornerX[SW_Corner] := 10;
  1594.          CornerY[SW_Corner] := 10;
  1595.          StartAngle[SW_Corner] := 0;
  1596.  
  1597.          CornerX[SE_Corner] := 990;
  1598.          CornerY[SE_Corner] := 10;
  1599.          StartAngle[SE_Corner] := 90;
  1600.        END; {Initialize}
  1601.  
  1602.        PROCEDURE GOTO(x, y : Integer);
  1603.          { Go to location X,Y on playing field. }
  1604.        VAR Heading    : Integer;
  1605.        BEGIN
  1606.          LowerShield; {Moving target is hard to hit - so lower shield}
  1607.  
  1608.          { Find the heading we need to get to the desired spot. }
  1609.          Heading := Angle_To(x, y);
  1610.  
  1611.          { Keep traveling at top speed until we are within 150 meters }
  1612.          WHILE (distance(loc_x, loc_y, x, y) > 150) DO Drive(Heading, 100);
  1613.  
  1614.          { Cut speed, and creep the rest of the way. }
  1615.          WHILE (distance(loc_x, loc_y, x, y) > 20) DO Drive(Heading, 20);
  1616.  
  1617.          { Stop driving, should coast to a stop. }
  1618.          Drive(Heading, 0); {I.E., Stop}
  1619.  
  1620.          RaiseShield; {Still target is easy to hit - so raise shield}
  1621.        END; {GoTo(X,Y)}
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628.  
  1629.                                         20
  1630.  
  1631.        PROCEDURE Aim( VAR Ang : Integer; VAR Arc : Integer);
  1632.         (* Improve aim by doing a binary search of the target area.
  1633.            I.E., divide the target area in two equal pieces and redefine
  1634.            the target area to be the piece where the foe is found.
  1635.            If the foe is not found, expand the search area to the
  1636.            maximum arc of plus or minus 10 degrees. *)
  1637.        BEGIN
  1638.           Arc := Arc DIV 2; (* Divide search area in two. *) 
  1639.           (* Check piece "below" target angle. *)
  1640.           IF Scan(Ang - Arc, Arc) <> 0
  1641.             (* If foe found, redefine target angle. *)
  1642.             THEN Ang := Ang - Arc
  1643.             (* If not found, then check piece "above" target angle. *)
  1644.             ELSE IF Scan(Ang + Arc, Arc) <> 0
  1645.                    (* If foe found, redefine target angle. *)
  1646.                    THEN Ang := Ang + Arc
  1647.                    ELSE Arc := 10;
  1648.           (* If foe not found in either piece, expand search arc to +/- 10 *)
  1649.        END; (* Aim *)
  1650.  
  1651.      PROCEDURE Do_Corner;
  1652.      { Scan and shoot from corner }
  1653.      BEGIN {Do_Corner}
  1654.        Times := 0; {Count of unsuccessful scans}
  1655.        Angle := StartAngle[Corner] + 10; {Starting angle for scanning}
  1656.        REPEAT
  1657.          Delta := 10; { Start with widest scanning arc. }
  1658.          Range := scan(Angle, Delta);
  1659.          WHILE (Range > 40) AND (Range < 700) DO
  1660.            { Must be far enough away to avoid self-damage. }
  1661.            BEGIN
  1662.              Aim(Angle, Delta); { Improve aim. }
  1663.              IF ObjectScanned = Enemy THEN cannon(Angle, Range); { Fire!! }
  1664.              Range := scan(Angle, Delta); { Is foe still in sights? }
  1665.            END;
  1666.          Angle := Angle + 20; { Look in adjacent target area. }
  1667.          IF (Angle > (StartAngle[Corner] + 90))
  1668.            THEN Angle := StartAngle[Corner] + 10;
  1669.          Times := Times + 1;
  1670.        UNTIL Times > 20; { Leave after 20 unsuccessful scans }
  1671.      END; {Do_Corner}
  1672.  
  1673.      BEGIN {TagTeam1 Main}
  1674.        Initialize;
  1675.        COMM[11] := 0; {Set Ally's corner (if any) to zero}
  1676.        COMM[10] := 0; {Communicate my corner to Ally}
  1677.        REPEAT
  1678.          REPEAT
  1679.            Corner := Random(3) + 1; {Pick a corner}
  1680.          UNTIL Corner <> COMM[11]; {Need different corner than Ally}
  1681.          COMM[10] := Corner; {Communicate my corner to Ally (if any)}
  1682.          GoTo(CornerX[Corner], CornerY[Corner]);
  1683.          { Move to selected corner. }
  1684.          Do_Corner;
  1685.        UNTIL Dead OR Winner;
  1686.      END; {TagTeam1 Main}
  1687.  
  1688.                                         21
  1689.  
  1690. OBSTRUCTIONS ON THE BATTLEFIELD
  1691.  
  1692.    Another new feature added in version 2.0 of P-ROBOTS is the possibility
  1693.    of randomly placed Obstructions on the battlefield.  This option is
  1694.    selected by using the "/ON" command line parameter, where N can be 1, 2 or
  1695.    3 -- corresponding to 1, 2 or 3 Obstructions.  Each Obstruction will be a
  1696.    randomly sized and placed rectangle.
  1697.  
  1698.    Be warned however, that using Obstructions in your battles will
  1699.    s..l..o..w.. down the speed of the battle considerably.  The logic required
  1700.    for P-ROBOTS to deal with Obstructions is fairly extensive and very
  1701.    computationally intense.  So the more Obstructions your battle has, the
  1702.    slower it will run.
  1703.  
  1704.    If your robot runs into one of these Obstructions, it will be stopped cold
  1705.    and incur Damage (if its Shield is down) -- just as if it ran into one of
  1706.    the battlefield walls.  A scanner will not be able to see beyond an
  1707.    Obstruction; nor will it be possible to shoot a missile past an
  1708.    Obstruction.  Therefore, it will be possible for a robot to "hide" from
  1709.    enemy scanners and missile by "hugging" the walls of an Obstruction.  More
  1710.    often than not, a scanner will only "see" the Obstruction and not the
  1711.    robot.
  1712.  
  1713.    Obstructions add a whole new dimension to the possible problems and
  1714.    opportunities that a robot may face!!
  1715.  
  1716.    Your robot will be able to determine where the Obstructions are by scanning
  1717.    and then checking the value returned by the function "ObjectScanned".  For
  1718.    example, you might use the following Boolean function to determine if the
  1719.    direction your robot is traveling (denoted below by the variable "Heading")
  1720.    is clear of Obstructions for the next 100 meters:
  1721.  
  1722.           FUNCTION ClearAhead : Boolean;
  1723.           BEGIN
  1724.             ClearAhead := (Scan(Heading,2) > 100)
  1725.                            OR (ObjectScanned <> Obstruction);
  1726.           END; {ClearAhead}
  1727.  
  1728.  
  1729. AN EXAMPLE DEALING WITH OBSTRUCTIONS
  1730.  
  1731.    Below is our old friend, HOTSHOT, adapted to deal with the problem of
  1732.    Obstructions by using logic to move around them.  Notice, that we can no
  1733.    longer use the same routine we have been using to go to a point X, Y on the
  1734.    battlefield -- because that point might be inside an Obstruction -- in
  1735.    which case our robot would commit suicide by repeatedly "banging its head"
  1736.    against the wall of the Obstruction.  To see how this problem is overcome,
  1737.    see the Procedure "Ramble" in the listing.
  1738.  
  1739.  
  1740.  
  1741.  
  1742.  
  1743.  
  1744.  
  1745.                                         22
  1746.  
  1747.      PROCEDURE HotShot3; 
  1748.      { 
  1749.       Author: David Malmberg 
  1750.     
  1751.       Strategy:  Stay in one place.  Find a foe.  Take a shot. 
  1752.       Keep improving aim and shooting until foe is lost from sights. 
  1753.       Then move sights (scanning) to adjacent target area. 
  1754.       If the Robot scans a complete circle (360 degrees) without 
  1755.       finding a foe in shooting range, move to another spot on the 
  1756.       field.  (This will avoid "stand-offs" where opponents stay 
  1757.       just out of range of one another.)  RaiseShield (if available)
  1758.       when standing still and lower them when moving. 
  1759.     
  1760.       When damage gets to 70 (or more) or fuel (if using fuel) gets 
  1761.       below 200 adopt an "End-Game" strategy of moving to the lower 
  1762.       left corner, lower shield, and continue to scan and shoot in 
  1763.       the corner's 90 degree range. 
  1764.     
  1765.       This Robot should be VERY effective against foes which 
  1766.       are stopped or are moving slowly.  It will be less effective 
  1767.       against Robots traveling at high speeds. 
  1768.     
  1769.       This Robot has been designed to utilize Fuel (if it is available) 
  1770.       to power its Shield.  It has also been designed to deal with 
  1771.       Obstructions (if any) by moving around them. 
  1772.      } 
  1773.     
  1774.     
  1775.      VAR { HotShot3 "Global" variables } 
  1776.        Angle, { Scanning angle } 
  1777.        Range, { Range/Distance to foe } 
  1778.        Sweep, { "Sweep count" -- when = 18, Robot has scanned 360 degrees } 
  1779.        Delta          : Integer; { Scanning arc } 
  1780.     
  1781.        PROCEDURE GOTO(X, Y : Integer); 
  1782.          { Go to location X,Y on playing field. } 
  1783.        VAR Heading    : Integer; 
  1784.        BEGIN 
  1785.        { WARNING:  If the point X,Y is inside an Obstruction then } 
  1786.        { executing this routine will cause the Robot to commit } 
  1787.        { suicide by repeatedly running into the wall of the Obstruction. } 
  1788.     
  1789.          { Find the heading we need to get to the desired spot. } 
  1790.          Heading := Angle_To(x, y); 
  1791.     
  1792.          { Keep traveling at top speed until we are within 150 meters } 
  1793.          WHILE (distance(loc_x, loc_y, x, y) > 150) DO drive(Heading, 100); 
  1794.     
  1795.          { Cut speed, and creep the rest of the way. } 
  1796.          WHILE (distance(loc_x, loc_y, x, y) > 20) DO drive(Heading, 20); 
  1797.     
  1798.          { Stop driving, should coast to a stop. } 
  1799.          drive(Heading, 0); {I.E., Stop} 
  1800.        END; {GoTo(X,Y)} 
  1801.     
  1802.  
  1803.                                         23
  1804.  
  1805.        PROCEDURE Ramble(X, Y : Integer); 
  1806.          { Move to X, Y (if possible) on the playing field } 
  1807.          { by avoiding Obstructions - if any.              } 
  1808.        VAR Heading, Tries, Dist : Integer; 
  1809.        BEGIN 
  1810.          Tries := 0; 
  1811.          Heading := Angle_To(X, Y); 
  1812.          Drive(Heading, 50); {Start off toward X,Y} 
  1813.          Dist := Scan(Heading, 5); 
  1814.          REPEAT 
  1815.            IF ObjectScanned = Obstruction 
  1816.              THEN BEGIN 
  1817.                REPEAT 
  1818.                  Heading := Heading + 10; 
  1819.                  Dist := Scan(Heading, 5); 
  1820.                UNTIL ObjectScanned <> Obstruction; 
  1821.                Drive(Heading, 50); {Minimum speed to turn freely} 
  1822.              END; 
  1823.            Heading := Angle_To(X, Y); 
  1824.            Dist := Scan(Heading, 5); 
  1825.            Tries := Tries + 1; 
  1826.          UNTIL (ObjectScanned <> Obstruction) OR (Tries > 20); 
  1827.          IF (ObjectScanned <> Obstruction) THEN GOTO(X,Y); 
  1828.        END; {Ramble} 
  1829.     
  1830.        PROCEDURE Move; 
  1831.          { Move to a random spot on the playing field. } 
  1832.        VAR x, y       : Integer; 
  1833.        BEGIN 
  1834.          Sweep := 0; { Reset Sweep counter to zero. } 
  1835.          x := Random(900)+50; 
  1836.          y := Random(900)+50; 
  1837.          Ramble(x, y); 
  1838.        END; {Move} 
  1839.     
  1840.        PROCEDURE Aim(VAR Ang : Integer; VAR Arc : Integer); 
  1841.        { 
  1842.         Improve aim by doing a binary search of the target area. 
  1843.         I.E., divide the target area in two equal pieces and redefine 
  1844.         the target area to be the piece where the foe is found. 
  1845.         If the foe is not found, expand the search area to the 
  1846.         maximum arc of plus or minus 10 degrees. 
  1847.        } 
  1848.        BEGIN 
  1849.          IF ObjectScanned = Enemy 
  1850.            THEN BEGIN 
  1851.              Arc := Arc DIV 2; { Divide search area in two. } 
  1852.              IF scan(Ang-Arc, Arc) <> 0 { Check piece "below" target angle. } 
  1853.                THEN Ang := Ang-Arc { If foe found, redefine target angle. } 
  1854.                ELSE IF scan(Ang+Arc, Arc) <> 0 { Check piece "above" Ang. } 
  1855.                 THEN Ang := Ang+Arc { If foe found, redefine target angle. } 
  1856.                 ELSE Arc := 10; 
  1857.            { Foe not found in either piece, expand search area to max arc. }
  1858.            END 
  1859.            ELSE Arc := 10; 
  1860.        END; {Aim} 
  1861.  
  1862.                                         24
  1863.  
  1864.        PROCEDURE End_Game; 
  1865.        { Special strategy for the "End Game" }
  1866.        BEGIN {End_Game} 
  1867.          Ramble(0,0); {Lower Left Corner} 
  1868.          Angle := 10; {Sweep arc from 0 to 90 degrees only} 
  1869.          REPEAT 
  1870.            Delta := 10; { Start with widest scanning arc. } 
  1871.            Range := scan(Angle, Delta); 
  1872.            WHILE (Range > 40) AND (Range < 700) AND (ObjectScanned = Enemy) 
  1873.              DO { Must be far enough away to avoid self-damage. } 
  1874.                BEGIN 
  1875.                  Aim(Angle, Delta); { Improve aim. } 
  1876.                  IF ObjectScanned = Enemy 
  1877.                    THEN cannon(Angle, Range); { Fire!! } 
  1878.                  Range := scan(Angle, Delta); { Is foe still in sights? } 
  1879.                END; 
  1880.            Angle := Angle+20; { Look in adjacent target area. } 
  1881.            IF Angle > 90 THEN Angle := 10; 
  1882.          UNTIL Dead OR Winner; 
  1883.        END; {End_Game} 
  1884.     
  1885.        BEGIN {HotShot3 Main} 
  1886.          RaiseShield; 
  1887.          Angle := 0; 
  1888.          Ramble(500, 500); { Move to center of field -- if possible. } 
  1889.          Sweep := 0; { Initialize Sweep counter to zero. } 
  1890.          REPEAT { Until Dead or Winner } 
  1891.            Delta := 10; { Start with widest scanning arc. } 
  1892.            Range := scan(Angle, Delta); 
  1893.            WHILE (Range > 40) AND (Range < 700) AND (ObjectScanned = Enemy) 
  1894.              DO { Must be far enough away to avoid self-damage. } 
  1895.                BEGIN 
  1896.                  Sweep := 0; { Found foe, so reset Sweep to zero } 
  1897.                  Aim(Angle, Delta); { Improve aim. } 
  1898.                  IF ObjectScanned = Enemy 
  1899.                    THEN cannon(Angle, Range); { Fire!! } 
  1900.                  Range := scan(Angle, Delta); { Is foe still in sights? } 
  1901.                END; 
  1902.            Angle := Angle+20; { Look in adjacent target area. } 
  1903.            Sweep := Sweep+1; 
  1904.            IF Sweep = 18 THEN 
  1905.              BEGIN { If robot has scanned a full circle, move elsewhere. } 
  1906.                LowerShield; {Don't need shield (as much) when moving} 
  1907.                Move; 
  1908.              END; 
  1909.            RaiseShield; {Standing still so use shield} 
  1910.            {"End" game strategy} 
  1911.            IF (Fuel < 200) OR (Damage > 70) THEN End_Game; 
  1912.          UNTIL Dead OR Winner; 
  1913.        END; {HotShot3 Main} 
  1914.     
  1915.  
  1916.  
  1917.  
  1918.  
  1919.  
  1920.                                         25
  1921.  
  1922. INTELLIGENCE OPTIONS
  1923.  
  1924.    The final new feature added in version 2.0 of P-ROBOTS is the possibility
  1925.    of varying the intelligence of your robots' "on-board" computers.  This
  1926.    option is selected by using the "/IN" command line parameter, where N can
  1927.    be 1, 2, 3 up to 10.  What this option really does is vary the number of
  1928.    instructions your robots' "on-board" computers can execute in any given
  1929.    amount of "time" during the game.  For example, with the lowest
  1930.    intelligence setting (i.e., a value of 1), your robots' "on-board" computer
  1931.    might execute 10 instructions during the time it travels 10 meters; while
  1932.    at the highest intelligence setting (of 10), 100 instructions might be
  1933.    executed during the same 10 meter travel period.  Obviously, at higher
  1934.    intelligence settings your robot will be able to perform more calculations
  1935.    and make more effective use of complex strategies and algorithms.
  1936.  
  1937.    For example, to run a single game between the robots: NINJA, WIMP and
  1938.    BLASTER with an intelligence setting of 5 (i.e., very smart robots), you
  1939.    would enter the following command at the DOS prompt:
  1940.  
  1941.           P-ROBOTS NINJA WIMP BLASTER /I5
  1942.  
  1943.    If you wish to have a series of 50 matches with the same intelligence
  1944.    setting between the same group of robots, you would add a "/M50" parameter
  1945.    to the command as follows:
  1946.  
  1947.           P-ROBOTS NINJA WIMP BLASTER /I5 /M50
  1948.  
  1949.    The default intelligence setting is 1 -- the lowest value and the standard
  1950.    setting used in version 1.0 of P-ROBOTS.  You should not think of this
  1951.    lowest setting as having "dumb" or "stupid" robots.  Robots operating at an
  1952.    intelligence level of 1 are still quite smart.  To use an analogy from
  1953.    personal computing, you might think of an intelligence setting of 1 as
  1954.    having each robot in the game equipped with an Intel 8088 microprocessor,
  1955.    running at 4.77 megahertz -- i.e., the same speed and processor used in the
  1956.    original IBM PC back in 1981.  By comparison, using an intelligence setting
  1957.    of 10 is like putting a 33 megahertz 80386 in your robot.
  1958.  
  1959.    Be warned however -- there is a price to be paid for increased robot
  1960.    intelligence -- it slows down the apparent speed of the game.  At higher
  1961.    intelligence settings, the computer you will be running P-ROBOTS on will
  1962.    have to execute more instructions (on your robot's behalf) while the robot
  1963.    travels 10 meters, and the game will appear to take longer for your robot
  1964.    to travel that same 10 meters.  This may or may not be a problem for you
  1965.    depending upon the speed of the computer you are using to play P-ROBOTS.
  1966.  
  1967.    There is one other potential problem with using various intelligence
  1968.    settings in P- ROBOTS.  This is the problem of inconsistent performance of
  1969.    your robots.  For example, you may have a robot that beats everything in
  1970.    sight at higher intelligence levels and gets beat by everything in sight at
  1971.    lower levels -- or vice versa.  Unfortunately, you can not have it both
  1972.    ways.  My advice to you is to select an intelligence level that plays at an
  1973.    acceptable display/animation speed on your computer and stick to it.
  1974.  
  1975.  
  1976.  
  1977.  
  1978.                                         26
  1979.  
  1980. APPENDIX I: COMPILER ERRORS
  1981.  
  1982.    The PASCAL compiler in P-ROBOTS will report any syntax or logic errors that
  1983.    it encounters during the compilation process.  Then the program will
  1984.    terminate without playing the game.  A listing of the robot(s) source code
  1985.    with the errors marked in the source will then be found in a file named
  1986.    LISTING.TXT on the disk/directory where P-ROBOTS is being run.  Because
  1987.    P-ROBOTS is going to write to the disk, you must NOT have a "write-protect"
  1988.    tab on the disk or you will get a fatal error whenever you try to run the
  1989.    program.  This file should be printed out and studied and your corrections
  1990.    made to your robot source files.  Do NOT make your corrections on the
  1991.    LISTING.TXT file!  The compiler only compiles robot files (i.e., files with
  1992.    a ".PR" extension).
  1993.  
  1994.    If your robot(s) source code did not have any errors (that the compiler
  1995.    could detect) there will not be a LISTING.TXT file created and the P-ROBOTS
  1996.    program will execute normally and the contest between the various robots
  1997.    will be played.
  1998.  
  1999.    The compiler will report the following errors by number:
  2000.  
  2001.           0.   UNDEFINED IDENTIFIER
  2002.           1.   MULTIPLE DEFINITION OF THIS IDENTIFIER
  2003.           2.   EXPECTED AN IDENTIFIER
  2004.           3.   PROGRAM MUST BEGIN WITH "PROGRAM"
  2005.           4.   EXPECTED CLOSING PARENTHESIS ")"
  2006.           5.   EXPECTED A COLON ":"
  2007.           6.   INCORRECTLY USED SYMBOL 
  2008.           7.   EXPECTED IDENTIFIER OR THE SYMBOL "VAR"
  2009.           8.   EXPECTED THE SYMBOL "OF"
  2010.           9.   EXPECTED AN OPENING PARENTHESIS "(" 
  2011.           10.  EXPECTED IDENTIFIER, "ARRAY" OR "RECORD"
  2012.           11.  EXPECTED AN OPENING BRACKET "["
  2013.           12.  EXPECTED A CLOSING BRACKET "]"
  2014.           13.  EXPECTED ".." WITHOUT INTERVENING BLANKS
  2015.           14.  EXPECTED A SEMICOLON ";"
  2016.           15.  BAD RESULT TYPE FOR A FUNCTION
  2017.           16.  EXPECTED AN EQUAL SIGN "="
  2018.           17.  EXPECTED BOOLEAN EXPRESSION
  2019.           18.  CONTROL VARIABLE OF THE WRONG TYPE
  2020.           19.  MUST BE MATCHING TYPES
  2021.           20.  "OUTPUT" IS REQUIRED IN PROGRAM HEADING
  2022.           21.  THE NUMBER IS TOO LARGE
  2023.           22.  EXPECT PERIOD ".", CHECK BEGIN-END PAIRS
  2024.           23.  BAD TYPE FOR A CASE STATEMENT
  2025.           24.  ILLEGAL CHARACTER
  2026.           25.  ILLEGAL CONSTANT OR CONSTANT IDENTIFIER
  2027.           26.  ILLEGAL ARRAY SUBSCRIPT (CHECK TYPE)
  2028.           27.  ILLEGAL BOUNDS FOR AN ARRAY INDEX
  2029.           28.  INDEXED VARIABLE MUST BE AN ARRAY
  2030.           29.  EXPECTED A TYPE IDENTIFIER
  2031.           30.  UNDEFINED TYPE
  2032.           31.  VAR WITH FIELD SELECTOR MUST BE RECORD
  2033.           32.  EXPECTED TYPE "BOOLEAN"
  2034.           33.  ILLEGAL TYPE FOR ARITHMETIC EXPRESSION
  2035.  
  2036.                                         27
  2037.  
  2038.           34.  EXPECTED INTEGER FOR "DIV" OR "MOD"
  2039.           35.  INCOMPATIBLE TYPES FOR COMPARISON
  2040.           36.  PARAMETER TYPES DO NOT MATCH
  2041.           37.  EXPECTED A VARIABLE
  2042.           38.  A STRING MUST HAVE ONE OR MORE CHAR
  2043.           39.  NUMBER OF PARAMETERS DO NOT MATCH
  2044.           40.  INVALID "TeamAlly" NAME FORMAT
  2045.           41.  ILLEGAL PARAMETERS TO "WRITE"
  2046.           42.  PARAMETER MUST BE OF TYPE "REAL"
  2047.           43.  PARAMETER MUST BE OF TYPE "INTEGER"
  2048.           44.  EXPECTED VARIABLE OR CONSTANT
  2049.           45.  EXPECTED A VARIABLE OR PROCEDURE
  2050.           46.  TYPES MUST MATCH IN AN ASSIGNMENT
  2051.           47.  CASE LABEL NOT SAME TYPE AS CASE CLAUSE
  2052.           48.  ARGUMENT TO STD. FUNCTION OF WRONG TYPE
  2053.           49.  THE PROGRAM REQUIRES TOO MUCH STORAGE
  2054.           50.  ILLEGAL SYMBOL FOR A CONSTANT
  2055.           51.  EXPECTED BECOMES ":="
  2056.           52.  EXPECTED "THEN"
  2057.           53.  EXPECTED "UNTIL"
  2058.           54.  EXPECTED "DO"
  2059.           55.  EXPECTED "TO" OR "DOWNTO"
  2060.           56.  EXPECTED "BEGIN"
  2061.           57.  EXPECTED "END"
  2062.           58.  EXPECTED ID, CONST, "NOT" OR "("
  2063.           59.  "INPUT"  IS REQUIRED IN PROGRAM HEADING
  2064.           60.  ILLEGAL (CONTROL) CHARACTER PRESENT IN SOURCE 
  2065.  
  2066.    Not all of the above error messages will be used in P-ROBOTS because the
  2067.    compiler has been modified to not allow certain kinds of PASCAL statements. 
  2068.    For example, since P-ROBOTS does not allow READs and WRITEs you will not
  2069.    get the above error messages that are normally associated with READ and
  2070.    WRITE.  If you attempt to READ or WRITE in a P-ROBOTS program you will get
  2071.    an error message number zero -- "UNDEFINED IDENTIFIER".
  2072.  
  2073.    Also, remember not to use PASCAL "reserved" words as variable or procedure
  2074.    names.  I.E., variables named BEGIN, ARRAY, DO, FOR, etc. will cause
  2075.    strange error messages.
  2076.  
  2077.    On very rare occasions, you may get another kind of compiler error if the
  2078.    robots' source code you are currently trying to compile is so "verbose"
  2079.    that it causes the one of the compiler's tables to overflow.  When this
  2080.    happens, you will be given an error message which identifies which specific
  2081.    table has been over flowed.  The limits for these tables are as follows:
  2082.  
  2083.         400    Identifiers (Variables, Constants, Procedures and Functions)
  2084.          40    Procedures or Functions
  2085.          40    Real Constants   
  2086.          60    Arrays
  2087.           7    Levels of "Nested" Procedures or Functions
  2088.        5000    "Compiled" P-Code instructions
  2089.  
  2090.    These limits apply to the total number of identifiers (etc.) for all of the
  2091.    robots you have in the current contest.
  2092.  
  2093.  
  2094.                                         28
  2095.  
  2096. APPENDIX II: RUN-TIME ERRORS
  2097.  
  2098.  
  2099.    When using P-ROBOTS it is possible to get two kinds of run-time errors. 
  2100.    The first kind (and probably the most frequent) is an error that occurs
  2101.    within the P-ROBOTS program itself when you try to do something that the 
  2102.    P-Code compiler within P-ROBOTS objects to -- like trying to divide by
  2103.    zero.  The second kind of run-time error is generated by Turbo Pascal. 
  2104.    These errors are due to situations like not having enough memory or disk
  2105.    space to run the P-ROBOTS program.  Each of these types of errors will be
  2106.    discussed below.
  2107.  
  2108.  
  2109. P-ROBOTS RUN-TIME ERRORS
  2110.  
  2111.    It is possible that the P-ROBOTS compiler will detect an error during the
  2112.    game.  These are known as "run-time" errors and they will cause the game to
  2113.    terminate and an error message to be printed.  The following kinds of
  2114.    run-time errors will be caught and reported:
  2115.  
  2116.      1.   DIVIDE BY 0
  2117.  
  2118.           For example, if Delta_X had a value of zero in the following program
  2119.           statement, you would get a "DIVIDE BY 0" error:
  2120.  
  2121.                   Target_Angle := ArcTan(Delta_Y/Delta_X);
  2122.  
  2123.      2.   UNDEFINED CASE
  2124.  
  2125.           For example, if the variable X had a value of 12 below you would get
  2126.           an "UNDEFINED CASE" error:
  2127.  
  2128.                   CASE X OF
  2129.                      1 : .....
  2130.                      2 : .....
  2131.                      3 : .....
  2132.                          .
  2133.                          .
  2134.                     10 : .....
  2135.                   END; {CASE}
  2136.  
  2137.      3.   INVALID INDEX
  2138.  
  2139.           For example, a reference to the tenth element of an array (i.e.,
  2140.           Spot[10]) that was only defined to have the elements one through
  2141.           five (i.e., Spot : ARRAY[1..5] OF INTEGER;) would cause an "INVALID
  2142.           INDEX" error.
  2143.  
  2144.  
  2145.  
  2146.  
  2147.  
  2148.  
  2149.  
  2150.  
  2151.  
  2152.                                         29
  2153.  
  2154.      4.   STORAGE OVERFLOW
  2155.  
  2156.           You would only get a "STORAGE OVERFLOW" error if one (or more) of
  2157.           your robots in the current contest was making too many recursive
  2158.           calls to the same procedure or function or was evaluating a large
  2159.           number of very, very complex assignment statements so that the
  2160.           robot's "stack" space was exceeded.  If you get this error, check
  2161.           your overall robot logic -- there must be a better way!
  2162.  
  2163.  
  2164. TURBO PASCAL RUN-TIME ERRORS
  2165.  
  2166.    Here are the run-time errors that might be generated by Turbo Pascal:
  2167.  
  2168.      101  "Disk Write Error" -- You would get this error (probably) because
  2169.           you do not have enough room on your disk to contain the complete
  2170.           LISTING.TXT file (i.e., the error listing) and your disk became
  2171.           full.
  2172.  
  2173.      203  "Heap Overflow Error" -- You probably don't have enough free memory. 
  2174.           P-ROBOTS needs at least 384K of free memory (i.e, after counting all
  2175.           of the memory residents programs).
  2176.  
  2177.  
  2178.  
  2179.  
  2180.  
  2181.  
  2182.  
  2183.  
  2184.  
  2185.  
  2186.  
  2187.  
  2188.  
  2189.  
  2190.  
  2191.  
  2192.  
  2193.  
  2194.  
  2195.  
  2196.  
  2197.  
  2198.  
  2199.  
  2200.  
  2201.  
  2202.  
  2203.  
  2204.  
  2205.  
  2206.  
  2207.  
  2208.  
  2209.  
  2210.  
  2211.                                         30
  2212.  
  2213. APPENDIX III: COMMON PROBLEMS
  2214.  
  2215.  
  2216.    If P-ROBOTS is not doing what you think it should do, check for these
  2217.    common problems:
  2218.  
  2219.      1.   Leaving a "write-protect" tab on the game disk will cause a fatal
  2220.           crash.  There needs to be a way for the LISTING.TXT file (i.e., the
  2221.           error listing) to be written on the disk.  Also, make sure you have
  2222.           enough disk space to contain the LISTING.TXT file.  20K of available
  2223.           disk space should be plenty of room.
  2224.  
  2225.      2.   Your robot must be a self-contained PASCAL PROCEDURE with the same
  2226.           name as the file (but without the .PR extension).
  2227.  
  2228.      3.   Your robot must have an "infinite" loop in the "main" routine.
  2229.  
  2230.      4.   Don't commit robot "suicide" by firing your cannon for a range of
  2231.           zero.  For example:
  2232.  
  2233.                   Drive(Angle,100);
  2234.                   WHILE (Loc_X < 999) DO Cannon(Angle,Scan(Angle,10));
  2235.  
  2236.           will cause your robot to commit suicide.
  2237.  
  2238.      5.   You need to have at least 384K of free memory in order to run 
  2239.           P-ROBOTS.  If you don't have enough memory, you will get a Turbo
  2240.           Pascal run-time error number 203.
  2241.  
  2242.  
  2243.  
  2244.  
  2245.  
  2246.  
  2247.  
  2248.  
  2249.  
  2250.  
  2251.  
  2252.  
  2253.  
  2254.  
  2255.  
  2256.  
  2257.  
  2258.  
  2259.  
  2260.  
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267.  
  2268.  
  2269.                                         31
  2270.  
  2271. APPENDIX IV: THE P-ROBOTS PASCAL LANGUAGE
  2272.  
  2273.  
  2274. "NORMAL" PASCAL
  2275.  
  2276.    P-ROBOTS allows a relatively rich subset of the "normal" PASCAL language.
  2277.  
  2278.    Predefined types include REAL, INTEGER, and BOOLEAN.  CONSTants, RECORDs
  2279.    and user-defined TYPEs are allowed.  ARRAYs are allowed.
  2280.  
  2281.    Comments may be added to a program by enclosing text with braces { }, or 
  2282.    (* *) pairs.
  2283.  
  2284.    Variable and other identifier names may have up to 10 significant
  2285.    characters.
  2286.  
  2287.    Arithmetic operators include: +, -, *, /, DIV and MOD.  Comparison
  2288.    operators include: >, <, <>, =, <=, and >=.  Boolean operators include:
  2289.    AND, OR, and NOT.
  2290.  
  2291.    Control statements/structures include:  CASE, FOR-TO-DO, FOR-DOWNTO-DO,
  2292.    IF-THEN, IF-THEN-ELSE, REPEAT-UNTIL, and WHILE-DO.
  2293.  
  2294.    Functions and Procedures may or may not have parameters.  If a Function or
  2295.    a Procedure has parameters, these parameters may be passed by value or by
  2296.    reference (i.e., a VAR parameter).  Procedures and Functions may be
  2297.    "nested" to a maximum of seven levels.  Recursion is allowed.
  2298.  
  2299.    Pre-defined Functions include: TRUE, FALSE, ABS, SQR, ODD, SUCC, PRED,
  2300.    ROUND, TRUNC, SIN, COS, EXP, LN, SQRT, ARCTAN, and RANDOM.  All of these
  2301.    Functions have the same interpretation in P-ROBOTS as in standard PASCAL,
  2302.    except for the various Trig functions which use degrees in P-ROBOTS, rather
  2303.    than radians.
  2304.  
  2305.    The following are NOT allowed in P-ROBOTS and will generate error messages: 
  2306.    CHAR, STRING, enumerated types, subranges, pointers, variant records,
  2307.    PACKED, sets, IN, files, input, output, GET, PUT, READ, WRITE, WITH, LABEL,
  2308.    GOTO.
  2309.  
  2310.  
  2311. UNIQUE P-ROBOTS PASCAL PROCEDURES AND FUNCTIONS
  2312.  
  2313.    Alive -- returns a TRUE or FALSE depending upon whether your robot is alive
  2314.    or not.
  2315.  
  2316.    Ally -- a pre-defined P-ROBOTS "constant" which is one of the values
  2317.    returned by the "ObjectScanned" function.
  2318.  
  2319.    AllyAlive -- returns TRUE or FALSE depending upon whether your Ally is
  2320.    Alive or not.
  2321.  
  2322.    AllyDamage -- returns your Ally's current Damage level.
  2323.  
  2324.    AllyDead -- returns TRUE or FALSE depending upon whether your Ally is Dead
  2325.    or not.
  2326.  
  2327.                                         32
  2328.  
  2329.    AllyFuel -- returns your Ally's current Fuel level.
  2330.  
  2331.    AllyHeading -- returns your Ally's current Heading.
  2332.  
  2333.    AllyLoc_X -- returns the current X coordinate of your Ally.
  2334.  
  2335.    AllyLoc_Y -- returns the current Y coordinate of your Ally.
  2336.  
  2337.    AllyMeters -- returns your Ally's current Meters.
  2338.  
  2339.    AllyShieldRaised -- returns TRUE or FALSE depending upon whether your
  2340.    Ally's shield is raised or not.
  2341.  
  2342.    AllySpeed -- returns your Ally's current Speed.
  2343.  
  2344.    Angle_To(X, Y) -- return to angle in degrees form your robot's current
  2345.    position to the point X, Y on the battlefield.
  2346.  
  2347.    Cannon(degree, range); -- fires a missile at an angle of "degree" and for a
  2348.    distance of "range".
  2349.  
  2350.    Damage -- returns the value of your robot's current damage level.
  2351.  
  2352.    Dead -- returns a TRUE or FALSE depending upon whether your robot is dead
  2353.    or not.
  2354.  
  2355.    Distance(X1, Y1, X2, Y2) -- returns the distance in meters from the point
  2356.    X1, Y1 on the battle field to the point X2, Y2.
  2357.  
  2358.    Drive(degree, speed); -- causes your robot to move in the direction given
  2359.    by "degree" at a specified "speed".
  2360.  
  2361.    Enemy -- a pre-defined P-ROBOTS "constant" which is one of the values
  2362.    returned by the "ObjectScanned" function.
  2363.  
  2364.    Fuel -- returns the current value of your robot's fuel level in "jiggers".
  2365.  
  2366.    LimitedFuel -- returns TRUE or FALSE depending upon whether your current
  2367.    battle has fuel constraints or not.
  2368.  
  2369.    LowerShield; -- causes your robot's shield to be lowered.
  2370.  
  2371.    Meters -- returns the cumulative number of meters that your robot has
  2372.    traveled during the current battle.
  2373.  
  2374.    Nothing -- a pre-defined P-ROBOTS "constant" which is one of the values
  2375.    returned by the "ObjectScanned" function.
  2376.  
  2377.    ObjectScanned -- returns the type of object that was found by the most
  2378.    recent "Scan" call (if any).  The result returned can have the "constant"
  2379.    values: Nothing, Ally, Enemy or Obstruction.
  2380.  
  2381.    Obstruction -- a pre-defined P-ROBOTS "constant" which is one of the values
  2382.    returned by the "ObjectScanned" function.
  2383.  
  2384.  
  2385.                                         33
  2386.  
  2387.    RaiseShield; -- causes your robot's shield to be raised.
  2388.  
  2389.    Random(limit) -- returns a random integer in the range of zero to "limit".
  2390.  
  2391.    Scan(degree, resolution) -- returns the distance in meters to any other
  2392.    robot or obstruction that is within the "viewing" arc/angle of "degree" +/-
  2393.    "resolution".  If nothing is scanned then the function "Scan" returns a
  2394.    value of zero.
  2395.  
  2396.    ShieldRaised -- returns TRUE or FALSE depending upon whether your robot's
  2397.    shield is up or down.
  2398.  
  2399.    Time -- returns the current CPU cycle count.  This function can be used to
  2400.    time various events, speeds, etc., within your robot program.
  2401.  
  2402.  
  2403.  
  2404.  
  2405.  
  2406.  
  2407.  
  2408.  
  2409.  
  2410.  
  2411.  
  2412.  
  2413.  
  2414.  
  2415.  
  2416.  
  2417.  
  2418.  
  2419.  
  2420.  
  2421.  
  2422.  
  2423.  
  2424.  
  2425.  
  2426.  
  2427.  
  2428.  
  2429.  
  2430.  
  2431.  
  2432.  
  2433.  
  2434.  
  2435.  
  2436.  
  2437.  
  2438.  
  2439.  
  2440.  
  2441.  
  2442.  
  2443.  
  2444.                                         34
  2445.  
  2446. APPENDIX V: A BLATANT "PLUG" FOR ANOTHER SOFTWORKS PRODUCT
  2447.  
  2448.    The Adventure Game Toolkit is designed to allow you to create and play your
  2449.    own text adventure games.  Once created, your adventure games can be shared
  2450.    with and enjoyed by others -- even if they do not have a copy of the
  2451.    Adventure Game Toolkit themselves.
  2452.  
  2453.    The Adventure Game Toolkit (AGT) began life as a program by Mark Welch
  2454.    called the Generic Adventure Game System (GAGS).  Using GAGS it was
  2455.    possible for the non-programmer to develop complete adventure games using a
  2456.    fixed (but relatively large) vocabulary of action verbs.  David Malmberg
  2457.    took GAGS and made a number of enhancements including the ability to
  2458.    customize the vocabulary and to program complex conditional tests and a
  2459.    rich assortment of actions and messages using a special metalanguage
  2460.    (designed specifically for writing adventure games).  The current Adventure
  2461.    Game Toolkit combines the best features of both approaches to enable the
  2462.    user to create two distinct levels of adventure games:
  2463.  
  2464.      (1)  Standard Level games that require no programming experience
  2465.           (honestly!), only a fertile imagination.  These Standard Level games
  2466.           follow the original GAGS format and only require that the user
  2467.           generate the game using a word processor or text editor to describe
  2468.           the various locations, objects and results of actions that
  2469.           collectively make up the game.
  2470.  
  2471.      (2)  Professional Level games that also make use of the special adventure
  2472.           game metalanguage to create games as complex and rich as the game
  2473.           designer's imagination and prose style will allow.  These games
  2474.           should be technically comparable with the published text adventure
  2475.           games from firms like Infocom.
  2476.  
  2477.  
  2478. FEATURES OF THE ADVENTURE GAME TOOLKIT
  2479.  
  2480.    AGT has a number of features that make it a very comprehensive adventure
  2481.    product.  These features make AGT more powerful, more professional and
  2482.    easier to use than any previously available text adventure game development
  2483.    system.  Some of these key features are: 
  2484.  
  2485.      POWERFUL
  2486.  
  2487.           *    Big, complex games with up to 200 locations, 100 inanimate
  2488.                objects (e.g., treasures, swords, lakes, trees, books, etc.)
  2489.                and 100 animate objects (e.g., people, animals or creatures).
  2490.  
  2491.           *    Large standard vocabulary with potential to define many more
  2492.                words unique to a specific adventure.  Typical games can have a
  2493.                vocabulary of 500 words or more.
  2494.  
  2495.  
  2496.  
  2497.  
  2498.  
  2499.  
  2500.  
  2501.                                         35
  2502.  
  2503.           *    Sophisticated parser that can understand (1) complex input
  2504.                commands including pronouns (IT, HIM, HER, THEM, MY and ITS),
  2505.                and (2) compound commands separated by AND or THEN or
  2506.                punctuation symbols, and (3) commands addressed to characters
  2507.                within the game.  Here are a few examples of commands AGT can
  2508.                handle with ease:
  2509.  
  2510.                       GET THE FLASH LIGHT AND THEN SWITCH IT ON
  2511.                       DROP THE FOOD, THE KEY AND THE BOTTLE THEN UNLOCK
  2512.                         THE DOOR WITH THE BRASS KEY AND THEN LEAVE
  2513.                       PUT ON THE CLOAK, THEN EXAMINE IT; READ ITS LABEL
  2514.                       PLACE THE GREEN ROCK AND THE SMALL PEBBLE BEHIND THE
  2515.                         TREE 
  2516.                       ENTER THE HOUSE; GET ALL; EXIT; SOUTH; SOUTH THEN DOWN
  2517.                       SULU, SET A COURSE FOR ALPHA 14
  2518.                       SCOTTY, BEAM DOWN A TRICORDER AND THE QWERTY MODULE
  2519.  
  2520.           *    Special, English-like metalanguage (especially developed for
  2521.                writing Adventure games) that gives the game designer total
  2522.                control and flexibility in the development of his/her games.
  2523.  
  2524.           *    Source code available to Registered Users.  Over 12,000 lines
  2525.                of Turbo Pascal 4.0/5.0/5.5 that may be customized to fit the
  2526.                game designer's unique needs. 
  2527.  
  2528.      PROFESSIONAL
  2529.  
  2530.           *    "Look and feel" of Infocom adventure games with similar screen
  2531.                layout and standard vocabulary and routines.
  2532.  
  2533.           *    Automatic screen adaptation to use either a color or a
  2534.                monochrome monitor.  Color combinations may be specified by the
  2535.                game designer or by the player during the game.
  2536.  
  2537.           *    Predefined function and cursor keys to input frequently used
  2538.                commands and move directions.
  2539.  
  2540.           *    SCRIPT and UNSCRIPT commands to echo game output to printer.
  2541.  
  2542.      EASY-TO-USE
  2543.  
  2544.           *    Large library of completed games that can be enjoyed simply as
  2545.                great entertainment or used as a platform by the game designer
  2546.                to build upon and/or learn from.
  2547.  
  2548.           *    Professionally written documentation totalling about 200 pages. 
  2549.                Has numerous examples that unveil the "secrets" of great
  2550.                adventure writers.
  2551.  
  2552.  
  2553.  
  2554.  
  2555.  
  2556.  
  2557.  
  2558.  
  2559.  
  2560.                                         36
  2561.  
  2562. HOW TO GET A COPY OF THE ADVENTURE GAME TOOLKIT
  2563.  
  2564.    The Adventure Game Toolkit (AGT) is distributed as "Shareware".  Copies can
  2565.    be found on many electronic bulletin boards and time-sharing services
  2566.    including Genie, CompuServe and  BIX.  AGT is also available by mail
  2567.    directly from the authors at:
  2568.  
  2569.           Softworks
  2570.           43064 Via Moraga
  2571.           Mission San Jose, California  94539
  2572.  
  2573.    You can also order by phone using your Mastercard or VISA to (415)
  2574.    659-0533, 9:00 AM to 8:00 PM, PST ONLY.  The price list for various
  2575.    versions/options of AGT is as follows: 
  2576.  
  2577.    1.  AGT Registration .............................. @ $ 20.00 ea $ ______
  2578.      includes: (1) Notice of all future AGT upgrades, new AGT Adventures
  2579.      and related AGT products.  (2) Latest version of the program, sample
  2580.      Adventure game source files (CAVE, CRUSADE, UNDERGRD, ALICE and 
  2581.      others), and summary documentation on disk.  Over one megabyte of
  2582.      program and data files -- ARCed on two disks.  Normally, these disks
  2583.      will not be sent until the next AGT upgrade.  If you wish these 
  2584.      disks sent immediately, please indicate so in your letter or call.
  2585.      (3) Telephone support from 7:00 to 9:00 PST (M-F).  (4) A warm glow
  2586.      from having supported at least one of the many Shareware products you
  2587.      probably use.  (5) The AGT authors' eternal gratitude. 
  2588.  
  2589.    2.  Above with printed AGT manual ................ @ $ 35.00 ea  $ ______
  2590.      includes: Above items plus printed manual about 200 pages long with
  2591.      numerous detailed examples on how to use the Adventure Game Toolkit
  2592.      to create very professional and very clever Adventure games.  The
  2593.      printed AGT manual has approximately twice the amount of information
  2594.      as contained in the summary disk documentation. 
  2595.  
  2596.    3.  Printed AGT manual (Only) .................... @ $ 20.00 ea  $ ______
  2597.  
  2598.    4.  UPGRADE to the newest AGT version (Only) ..... @ $ 12.00 ea  $ ______
  2599.      includes: Latest version of the program, sample Adventure game source
  2600.      files (CAVE, CRUSADE, UNDERGRD, ALICE and others), and summary
  2601.      documentation on disk.  Over one megabyte of program and data files
  2602.      -- ARCed on two disks. 
  2603.  
  2604.    5.  AGT Turbo Pascal 4.0/5.0 source code ......... @ $ 50.00 ea  $ ______
  2605.      includes: Turbo Pascal 4.0/5.0/5.5 source code for AGT's COMPILE
  2606.      and RUN programs.  Over 12,000 lines of Turbo Pascal source code.
  2607.      YOU MUST BE    A REGISTERED AGT USER TO ORDER THE SOURCE CODE! 
  2608.  
  2609.    Orders are normally shipped by US mail at no additional charge.
  2610.           For UPS shipment, please add $4.00..........@ $ 4.00 ea   $ ______
  2611.           For shipments outside the United States, add  $ 8.00 ea   $ ______
  2612.                                                           Subtotal  $ ______
  2613.           (California residents please add 7 1/4% sales tax)   Tax  $ ______
  2614.  
  2615.                                                              TOTAL  $ ______
  2616.  
  2617.  
  2618.                                         37
  2619.  
  2620.     Payment by:    ( ) Check    ( ) MasterCard    ( ) VISA    ( ) Cash
  2621.  
  2622.     Be sure to specify the computer/disk version desired:
  2623.  
  2624.         _____ Macintosh   _____ Atari ST   _____ IBM 5 1/4   _____ IBM 3 1/2
  2625.  
  2626.  
  2627.  
  2628.         Name: _______________________________________________________________
  2629.  
  2630.      Address: _______________________________________________________________
  2631.  
  2632.             : _______________________________________________________________
  2633.  
  2634.        State: ______________________________ Zip:____________________________
  2635.  
  2636.    Day Phone: ____________________________ Eve: _____________________________
  2637.  
  2638.       Card #: _________________________________ Exp. Date: __________________
  2639.  
  2640.    Signature of cardholder: _________________________________________________
  2641.  
  2642.  
  2643.  
  2644.  
  2645.  
  2646.  
  2647.  
  2648.  
  2649.  
  2650.  
  2651.  
  2652.  
  2653.  
  2654.  
  2655.  
  2656.  
  2657.  
  2658.  
  2659.  
  2660.  
  2661.  
  2662.  
  2663.  
  2664.  
  2665.  
  2666.  
  2667.  
  2668.  
  2669.  
  2670.  
  2671.  
  2672.  
  2673.  
  2674.  
  2675.  
  2676.  
  2677.                                         38
  2678.  
  2679. APPENDIX VI: ABOUT THE AUTHOR
  2680.  
  2681.  
  2682.    David Malmberg has been active in the world of personal computer since
  2683.    1977.  He is the author or co-author of six published software products.
  2684.  
  2685.    His most successful products were the Turtle Graphics series published by
  2686.    HESware.  These two programs have sold over 80,000 copies world-wide, been
  2687.    translated into Spanish, and won two Consumer Electronic Software Showcase
  2688.    awards as some of the best software of 1983.  These programs have been
  2689.    widely used in schools to teach computer literacy to children and other
  2690.    computer novices.
  2691.  
  2692.    His most recent software product was the Adventure Game Toolkit written
  2693.    with Mark Welch.  The Adventure Game Toolkit is also available from
  2694.    Softworks.
  2695.  
  2696.    Dave has also published numerous articles and programs in various computer
  2697.    magazines.  He has been a Contributing Editor of both COMPUTE!'s HOME &
  2698.    EDUCATIONAL COMPUTING and MICRO magazines.  He was one of the principal
  2699.    authors of COMPUTE!'s FIRST BOOK OF VIC, the best selling computer book of
  2700.    1983.  He has written regular columns on educational uses of computers and
  2701.    on LOGO for COMMODORE and POWER/PLAY magazines.  
  2702.  
  2703.  
  2704.  
  2705.  
  2706.  
  2707.  
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.  
  2714.  
  2715.  
  2716.  
  2717.  
  2718.  
  2719.  
  2720.  
  2721.  
  2722.  
  2723.  
  2724.  
  2725.  
  2726.  
  2727.  
  2728.  
  2729.  
  2730.  
  2731.  
  2732.  
  2733.  
  2734.                                         39
  2735.  
  2736.