(**************************************************************************)
(*                             W A R N I N G                              *)
(*                                                                        *)
(*  This Robot has NOT been designed to take advantage of the advanced    *)
(*  features of P-ROBOTS, such as, Shields, Fuel, Teams or Obstructions.  *)
(**************************************************************************)

  PROCEDURE Sniper;

    { Sniper is based on a C-Robot by Tom Poindexter }

    { Strategy: Since a scan of the entire battlefield can be done in 90 }
    { degrees from a corner, sniper can scan the field quickly. }

    { "Global" variables, that can be used by any function or procedure }
  VAR
    corner         : Integer; { current corner 0, 1, 2, or 2 }
    c1x, c1y       : Integer; { corner 1 x and y }
    c2x, c2y       : Integer; {   "    2 "  "  " }
    c3x, c3y       : Integer; {   "    3 "  "  " }
    c4x, c4y       : Integer; {   "    4 "  "  " }
    s1, s2, s3, s4 : Integer; { starting scan position for corner 1 - 4 }
    sc             : Integer; { current scan start }
    d              : Integer; { last damage check }
    closest        : Integer; { check for targets in range }
    Range          : Integer; { range to target }
    dir            : Integer; { scan direction }

    { new corner procedure to move to a different corner }
    PROCEDURE new_corner;

    VAR
      x, y           : Integer;
      Angle          : Integer;
      New            : Integer;


    BEGIN
      New := Random(4); { pick a random corner }
      IF (New = corner) THEN { but make it different than the }
        corner := (New+1) MOD 4 { current corner }
      ELSE
        corner := New;
      IF (corner = 0) THEN BEGIN { set new x,y and scan start }
        x := c1x;
        y := c1y;
        sc := s1;
      END;
      IF (corner = 1) THEN BEGIN
        x := c2x;
        y := c2y;
        sc := s2;
      END;
      IF (corner = 2) THEN BEGIN
        x := c3x;
        y := c3y;
        sc := s3;
      END;
      IF (corner = 3) THEN BEGIN
        x := c4x;
        y := c4y;
        sc := s4;
      END;

      { find the heading we need to get to the desired corner }
      Angle := Angle_To(x, y);

      { start drive train, full speed }
      drive(Angle, 100);

      { keep traveling until we are within 150 meters }
      { speed is checked in case we run into wall, other robot }
      { not terribly great, since were are doing nothing while moving }

      WHILE ((distance(loc_x, loc_y, x, y) > 150) AND (speed > 0)) DO
        ;

      { cut speed, and creep the rest of the way }

      drive(Angle, 20);
      WHILE ((distance(loc_x, loc_y, x, y) > 20) AND (speed > 0)) DO
        ;

      { stop drive, should coast in the rest of the way }
      drive(Angle, 0);
    END; { end of new_corner }


  BEGIN {Sniper Main}

    { initialize the corner info }
    { x and y location of a corner, and starting scan degree }
    c1x := 10; c1y := 10; s1 := 0;
    c2x := 10; c2y := 990; s2 := 270;
    c3x := 990; c3y := 990; s3 := 180;
    c4x := 990; c4y := 10; s4 := 90;
    closest := 9999;
    new_corner; { start at a random corner }
    d := damage; { get current damage }
    dir := sc; { starting scan direction }

    REPEAT {UNTIL DEAD OR WINNER}

      WHILE (dir < sc+90) DO BEGIN { scan through 90 degree range }
        Range := scan(dir, 5); { look at a direction }
        IF ((Range <= 700) AND (Range > 0)) THEN BEGIN
          WHILE (Range > 0) DO BEGIN { keep firing while in range }
            closest := Range; { set closest flag }
            cannon(dir, Range); { fire! }
            Range := scan(dir, 5); { check target again }
            IF (d+15 > damage) THEN { sustained several hits, }
              Range := 0; { goto new corner }
          END;
          dir := dir-10; { back up scan, in case }
        END;

        dir := dir+10; { increment scan }
        IF (d <> damage) THEN BEGIN { check for damage incurred }
          new_corner; { we're hit, move now }
          d := damage;
          dir := sc;
        END;
      END; { WHILE (dir < sc + 90) -- scan through 90 degree range }

      IF (closest = 9999) THEN BEGIN { check for any targets in range }
        new_corner; { nothing, move to new corner }
        d := damage;
        dir := sc;
      END
      ELSE BEGIN { targets in range, resume }
        dir := sc;
        closest := 9999;
      END;

    UNTIL Dead OR Winner; {REPEAT}

  END; { end of Sniper Main }
