Universität Ulm, Fakultät für Mathematik und Wirtschaftswissenschaften, SAI

SS 99 || Ferienprojekt zu Allgemeine Informatik II || Puzzle Library

MODULE PuzzleIO


MODULE PuzzleIO;

   IMPORT ASCII, Graphics := TermLineGraphics, Puzzle, Read, Streams,
      Strings, Terminals, Write;

   PROCEDURE ReadMove(s: Streams.Stream; VAR move: Puzzle.Move) : BOOLEAN;
      CONST
	 rowSY = 0; colSY = 1; dashSY = 2; errorSY = 3; eofSY = 4;
      TYPE
	 Symbol = SHORTINT; (* rowSY .. eofSY *)
      VAR
	 line: ARRAY 512 OF CHAR;
	 input: Streams.Stream;
	 ch: CHAR;

	 sy: Symbol; val: SHORTINT;

      PROCEDURE NextCh;
      BEGIN
	 IF input.eof OR ~Streams.ReadByte(input, ch) THEN
	    ch := 0X;
	 END;
      END NextCh;

      PROCEDURE GetSy;
      BEGIN
	 WHILE (ch = " ") OR (ch = ASCII.tab) DO
	    NextCh;
	 END;
	 IF (ch >= "a") & (ch <= "z") THEN
	    ch := CAP(ch);
	 END;
	 IF ch = 0X THEN
	    sy := eofSY;
	 ELSIF (ch >= "A") & (ch <= CHR(Puzzle.boardsize + ORD("A"))) THEN
	    sy := rowSY; val := SHORT(ORD(ch) - ORD("A")); NextCh;
	 ELSIF (ch >= "0") & (ch <= "9") THEN
	    sy := colSY;
	    val := SHORT(ORD(ch) - ORD("0")); NextCh;
	    WHILE (ch >= "0") & (ch <= "9") DO
	       val := val * 10 + SHORT(ORD(ch) - ORD("0")); NextCh;
	    END;
	    IF val >= 1 THEN
	       DEC(val);
	    ELSE
	       sy := errorSY;
	    END;
	 ELSIF ch = "-" THEN
	    sy := dashSY; NextCh;
	 ELSE
	    sy := errorSY;
	 END;
      END GetSy;

      PROCEDURE ParsePosition(VAR x, y: SHORTINT) : BOOLEAN;
      BEGIN
	 IF sy = rowSY THEN
	    y := val; GetSy;
	    IF sy # colSY THEN RETURN FALSE END;
	    x := val; GetSy;
	 ELSIF sy = colSY THEN
	    x := val; GetSy;
	    IF sy # rowSY THEN RETURN FALSE END;
	    y := val; GetSy;
	 ELSE
	    RETURN FALSE
	 END;
	 RETURN TRUE
      END ParsePosition;

      PROCEDURE ParseMove(VAR move: Puzzle.Move) : BOOLEAN;
	 VAR
	    fromx, fromy, tox, toy: SHORTINT;
      BEGIN
	 IF ~ParsePosition(fromx, fromy) THEN RETURN FALSE END;
	 IF sy # dashSY THEN RETURN FALSE END; GetSy;
	 IF ~ParsePosition(tox, toy) THEN RETURN FALSE END;
	 Puzzle.CreateMove(move, fromx, fromy, tox, toy);
	 RETURN TRUE
      END ParseMove;

   BEGIN (* ReadMove *)
      Read.LineS(s, line);
      IF s.count = 0 THEN RETURN FALSE END;
      Strings.Open(input, line); NextCh; GetSy;
      RETURN ParseMove(move) & (sy = eofSY)
   END ReadMove;

   PROCEDURE PrintMove(s: Streams.Stream; move: Puzzle.Move);
   BEGIN
      Write.CharS(s, CHR(move.fromy + ORD("a")));
      Write.IntS(s, move.fromx + 1, 1);
      Write.CharS(s, "-");
      Write.CharS(s, CHR(move.toy + ORD("a")));
      Write.IntS(s, move.tox + 1, 1);
   END PrintMove;

   PROCEDURE PrintSituation(s: Streams.Stream; situation: Puzzle.Situation);
      VAR
	 board: Puzzle.Board;
	 row, col: INTEGER;

      PROCEDURE DrawHorizontalLine(tee: SHORTINT);
	 VAR
	    i: INTEGER;
      BEGIN
	 i := 0;
	 WHILE i < Puzzle.boardsize * 2 - 1 DO
	    IF ODD(i) THEN
	       Graphics.Draw(s, tee);
	    ELSE
	       Graphics.Draw(s, Graphics.horizontalLine);
	    END;
	    INC(i);
	 END;
      END DrawHorizontalLine;

   BEGIN (* PrintSituation *)
      Puzzle.GetBoard(situation, board);
      Graphics.Draw(s, Graphics.upperLeftCorner);
      DrawHorizontalLine(Graphics.topTee);
      Graphics.Draw(s, Graphics.upperRightCorner);
      Write.LnS(s);

      row := 0;
      WHILE row < Puzzle.boardsize DO
	 col := 0;
	 Graphics.Draw(s, Graphics.verticalLine);
	 WHILE col < Puzzle.boardsize DO
	    CASE board[row, col] OF
	    | Puzzle.empty:   Write.CharS(s, " ");
	    | Puzzle.player1: Write.CharS(s, "x");
	    | Puzzle.player2: Write.CharS(s, "o");
	    END;
	    INC(col);
	    Graphics.Draw(s, Graphics.verticalLine);
	 END;
	 Write.IntS(s, row + 1, 1);
	 Write.LnS(s);
	 INC(row);
	 IF row < Puzzle.boardsize THEN
	    Graphics.Draw(s, Graphics.leftTee);
	    DrawHorizontalLine(Graphics.cross);
	    Graphics.Draw(s, Graphics.rightTee);
	    Write.LnS(s);
	 END;
      END;

      Graphics.Draw(s, Graphics.lowerLeftCorner);
      DrawHorizontalLine(Graphics.bottomTee);
      Graphics.Draw(s, Graphics.lowerRightCorner);
      Write.LnS(s);

      Write.CharS(s, " ");
      col := 0;
      WHILE col < Puzzle.boardsize DO
	 Write.CharS(s, CHR(ORD("a") + col));
	 Write.CharS(s, " ");
	 INC(col);
      END;
      Write.LnS(s);
   END PrintSituation;

END PuzzleIO.

SS 99 || Ferienprojekt zu Allgemeine Informatik II || Puzzle Library

Andreas Borchert, 26. Juli 1999