Go to Package Interface

WITH Ada.Text_IO;
WITH Screen;
PACKAGE BODY Spider IS
------------------------------------------------------------------
--|
--|  This package provides procedures to emulate "Spider"
--|  commands. The spider is can move around
--|  the screen drawing simple patterns.
--|
--| Author: John Dalbey, Cal Poly San Luis Obispo, 1992
--| Adapted by: Michael B. Feldman, The George Washington University
--| Last Modified: July 1995
--|
------------------------------------------------------------------
 
  TYPE ScreenColors IS (Red, Blue, Green, Black);  -- available colors
 
  -- Spider's View of her Room - rows and cols both numbered 1..20
  SUBTYPE Rows IS Positive RANGE 1..20;
  SUBTYPE Cols IS Positive RANGE 1..20;
  RowsInRoom   : CONSTANT Positive := Rows'Last;
  ColsInRoom   : CONSTANT Positive := Cols'Last;
 
  -- Spider State
  Spidersym    : CONSTANT character := '*';   -- asterisk
  CurrentColumn: Cols;                        -- spider's position
  CurrentRow   : Rows;                        -- in the room.
  Heading      : Directions;                  -- spider's direction
  Ink          : ScreenColors;                -- spider's color
 
  -- Screen Description Constants: for 24 x 80 screen,
  -- 1 spider row = 1 screen row, 1 spider col = 2 screen cols
 
  RowLow       : CONSTANT Screen.Depth := 2;  -- room row bounds
  RowHigh      : CONSTANT Screen.Depth := RowLow + Rows'Last;
  ColLow       : CONSTANT Screen.Width := 21; -- lower column bound
  ColHigh      : CONSTANT Screen.Width := ColLow + 2*Cols'Last;
 
  DebugFlag    : Boolean := False;            -- Is single stepping on?
 
  -- internal procedures and functions, not in specification
  -- and therefore not available to client program
 
  PROCEDURE DrawSymbol (Which: Character) IS
  -- Pre:  Which is defined
  -- Post: Which appears in its proper position on the screen
  BEGIN
    Screen.MoveCursor (Row => (RowLow - 1) + CurrentRow,
                       Column => (ColLow - 2) + (2 * CurrentColumn));
    Ada.Text_IO.Put (Item => Which);
    Ada.Text_IO.Flush;
  END DrawSymbol;
 
  FUNCTION ColorSymbols (Color: ScreenColors) RETURN Character IS
  -- Pre:  Color is defined
  -- Post: Returns the drawing character corresponding to Color
  BEGIN
    CASE Color IS
      WHEN Red   => RETURN '+';
      WHEN Blue  => RETURN 'X';
      WHEN Green => RETURN 'O';
      WHEN Black => RETURN '.';
    END CASE;
  END ColorSymbols;
 
  FUNCTION Compass (Direction: Directions) RETURN Character IS
  -- Pre:  Direction is defined
  -- Post: Returns drawing character corresponding to Direction
  BEGIN
    CASE Direction IS
      WHEN North => RETURN '^';
      WHEN East  => RETURN '>';
      WHEN South => RETURN 'v';
      WHEN West  => RETURN '<';
    END CASE;
  END Compass;
 
  PROCEDURE DrawStatus IS
  -- Pre:  None
  -- Post: Status Box appears on the screen
  BEGIN
    Screen.MoveCursor (Row => 2, Column => 1);
    Ada.Text_IO.Put (" --- ");
    Screen.MoveCursor (Row => 3, Column => 1);
    Ada.Text_IO.Put ("|   |");
    Screen.MoveCursor (Row => 4, Column => 1);
    Ada.Text_IO.Put ("|   |");
    Screen.MoveCursor (Row => 5, Column => 1);
    Ada.Text_IO.Put (" --- ");
  END DrawStatus;
 
  PROCEDURE DrawRoom  IS
  -- Pre:  None
  -- Post: Room appears on the screen
  BEGIN
    Screen.ClearScreen;
    Screen.MoveCursor (Row => 1, Column => 1);
    -- Top Bar
    Ada.Text_IO.Put ("                   ");
    Ada.Text_IO.Put (" --------------------------------------- ");
    Ada.Text_IO.New_Line;
    FOR I in 1..20 LOOP
    Ada.Text_IO.Put ("                   ");
    Ada.Text_IO.Put ("|. . . . . . . . . . . . . . . . . . . .|");
    Ada.Text_IO.New_Line;
    END LOOP;
    Ada.Text_IO.Put ("                   ");
    Ada.Text_IO.Put (" --------------------------------------- ");
    DrawStatus;
  END DrawRoom;
 
  PROCEDURE ChgColor (NewColor : ScreenColors) IS
  -- Pre:  NewColor is defined
  -- Post: Ink is changed to NewColor and displayed in status box
  BEGIN
    Ink := NewColor;
    Screen.MoveCursor ( Row => 4, Column => 3);
    Ada.Text_IO.Put (ColorSymbols(Ink));
  END ChgColor;
 
  PROCEDURE ShowDirection IS
  -- Pre:  None
  -- Post: Heading is displayed in the status box
  BEGIN
    Screen.MoveCursor(Row => 3,Column => 3);
    Ada.Text_IO.Put (Compass(Heading));
  END ShowDirection;
 
  PROCEDURE ShowSpider IS
  -- Pre:  None
  -- Post: The spider symbol appears in its current position
  BEGIN
    DrawSymbol (SpiderSym);
  END ShowSpider;
 
  -- These procedures are in the package specification
  -- and implement the "official" spider commands
 
  PROCEDURE Start IS
  BEGIN
    DrawRoom;
    CurrentColumn := 10; -- these are in the spider's view
    CurrentRow := 11;
    Heading := North;
    Green;
    ShowSpider;
    ShowDirection;
  END Start;
 
  PROCEDURE Blue IS
  BEGIN
    ChgColor (blue);
  END Blue;
 
  PROCEDURE Green IS
  BEGIN
    ChgColor (green);
  END Green;
 
  PROCEDURE Red IS
  BEGIN
    ChgColor (red);
  END Red;
 
  PROCEDURE Black IS
  BEGIN
    ChgColor (black);
  END Black;
 
  PROCEDURE Right IS
  BEGIN
    IF Heading = Directions'Last THEN
      Heading := Directions'First;
    ELSE
      Heading := Directions'Succ (Heading);
    END IF;
    ShowDirection;
  END Right;
 
  PROCEDURE Face (WhichWay: IN Directions) IS
  BEGIN
    Heading := WhichWay;
    ShowDirection;
  END Face;
 
  FUNCTION IsFacing RETURN Directions IS
  BEGIN
    RETURN Heading;
  END IsFacing;
 
  FUNCTION AtWall RETURN Boolean IS
  BEGIN
    -- Check for out of bounds (in the spider's view)
    CASE Heading IS
      WHEN North =>
        RETURN CurrentRow <= Rows'First;
      WHEN East  =>
        RETURN CurrentColumn >= Cols'Last;
      WHEN South =>
        RETURN CurrentRow >= Rows'Last;
      WHEN West  =>
        RETURN CurrentColumn <= Cols'First;
    END CASE;
  END AtWall;
 
  PROCEDURE Step IS
  BEGIN
 
    -- leave a track where spider is standing
    DrawSymbol (ColorSymbols (Ink) );
 
    -- If out of bounds raise exception.
    IF AtWall THEN
      Screen.Beep;
      RAISE Hit_the_Wall;
    END IF;
 
    -- change the spider's location
    CASE Heading IS
      WHEN North =>
        CurrentRow := CurrentRow - 1;
      WHEN East  =>
        CurrentColumn := CurrentColumn + 1;
      WHEN South =>
        CurrentRow := CurrentRow + 1;
      WHEN West  =>
        CurrentColumn := CurrentColumn - 1;
    END CASE;
 
    -- draw the spider in her new location
    ShowSpider;
 
    -- if debug mode, wait for user to press RETURN
    IF Debugging = On THEN
      Ada.Text_IO.Skip_Line;
    ELSE
      DELAY 0.5;
    END IF;
  END Step;
 
  PROCEDURE Quit IS
  -- Quit command.
  BEGIN
    Screen.MoveCursor(Row => 23,Column => 1);
  END Quit;
 
  PROCEDURE Debug (Setting: Switch) is
  -- Toggle debugging mode
  BEGIN
    IF Setting = ON THEN
      DebugFlag := true;
      Screen.MoveCursor (Row => 10,Column => 1);
      Ada.Text_IO.Put ("-- DEBUG ON -- ");
      Ada.Text_IO.New_Line;
      Ada.Text_IO.Put ("  Press Enter");
    ELSE
      DebugFlag := false;
      Screen.MoveCursor (Row => 10,Column => 1);
      Ada.Text_IO.Put ("               ");
      Ada.Text_IO.New_Line;
      Ada.Text_IO.Put ("             ");
    END IF;
  END Debug;
 
  FUNCTION Debugging RETURN Switch IS
  BEGIN
    IF DebugFlag THEN
      RETURN On;
    ELSE
      RETURN Off;
    END IF;
  END Debugging;
 
END Spider;