(****************************************************

Programm  : Quevedo.mod
Zweck     : Schachendspiel Turm und König gegen König
Version   : 2.0 / 5-8-93
Autor     : Niels Knoop
Copyright : Public Domain
Sprache   : Oberon-2
Compiler  : Amiga Oberon 3.0

****************************************************)

MODULE Quevedo;

IMPORT QuevedoRoutinen,io;

VAR zuege : INTEGER;
    altpos,neupos : QuevedoRoutinen.stellung;
    zeichenkette : ARRAY 255 OF CHAR;
    abbruch : BOOLEAN;

PROCEDURE LesePosition(VAR x,y : INTEGER) : BOOLEAN;
(* Richtung (per Zahlenblock) oder Zielfeld einlesen *)
VAR eingabe : ARRAY 100 OF CHAR;
    n : INTEGER;
BEGIN
  io.ReadString(eingabe);
  IF eingabe[1] # CHR(0) THEN
    x := ORD(CAP(eingabe[0])) - 64;
    y := ORD(CAP(eingabe[1])) - 48
  ELSE
    n := ORD(eingabe[0]) - 48;
    IF (n >= 1) & (n <= 9) THEN
      x := x + (n - 1) MOD 3 - 1;
      y := y + (n - 1) DIV 3 - 1
    END
  END;
  RETURN (CAP(eingabe[0]) = "Q")
END LesePosition;


PROCEDURE SchreibePosition(x,y : INTEGER);
(* Feldkoordinaten im Klartext ausgeben *)
BEGIN
  io.Write(CHR(x + 96));
  io.Write(CHR(y + 48))
END SchreibePosition;


PROCEDURE GotoXY(x,y : INTEGER);
(* Cursor im Console-Fenster setzen *)
VAR sequenz : ARRAY 10 OF CHAR;
BEGIN
  sequenz := "\[00;00H";
  sequenz[1] := CHR((y DIV 10) MOD 10 + 48);
  sequenz[2] := CHR(y MOD 10 + 48);
  sequenz[4] := CHR((x DIV 10) MOD 10 + 48);
  sequenz[5] := CHR(x MOD 10 + 48);
  io.WriteString(sequenz);
END GotoXY;


PROCEDURE Brettmalen;
(* Schachbrett auf den Bildschirm zeichnen *)
VAR i,j,k : INTEGER;
    schwarz,weiss,leer : ARRAY 5 OF CHAR;
BEGIN
  schwarz := "\[41m";
  weiss := "\[42m";
  leer := "\[40m";
  io.WriteString("\[0m\f \r");  (* sic! *)
  FOR i := 8 TO 1 BY -1 DO
    FOR j := 1 TO 3 DO
      GotoXY(1, 25 - 3 * i + j);
      io.WriteString("   ");
      FOR k := 1 TO 8 DO
        IF (i MOD 2 = k MOD 2) THEN
          io.WriteString(schwarz);
        ELSE
          io.WriteString(weiss);
        END;
        io.WriteString("     ")
      END;
      io.WriteString(leer);
    END;
  END;
  FOR i := 8 TO 1 BY -1 DO
    GotoXY(2, 27 - 3 * i);
    io.Write(CHR(i + 48))
  END;
  FOR i := 1 TO 8 DO
    GotoXY(5 * i + 1, 27);
    io.Write(CHR(i + 64))
  END
END Brettmalen;


PROCEDURE BeschreibeFeld(x,y,farbe : INTEGER; zeichen : CHAR);
(* Angegebenes Feld auf dem Bildschirm beschreiben oder löschen *)
VAR sequenz : ARRAY 25 OF CHAR;
BEGIN
  sequenz := "\[30m\[43m \[1m \[22m \[0m";
  IF (farbe >= 0) THEN
    sequenz[2] := CHR(farbe MOD 4 + 48);
    sequenz[6] := "3";
    sequenz[12]:= zeichen
  ELSE
    sequenz[6] := CHR((x + y) MOD 2 + 49)
  END;
  GotoXY(5 * x, 27 - 3 * y);
  io.WriteString(sequenz)
END BeschreibeFeld;


BEGIN
io.Clear;
io.WriteString("   QUEVEDO 2.0 - Schachendspiel\n");
io.WriteString("    Turm und König gegen König\n");
io.WriteString("(benötigt ca. 80x30 Zeichen Platz)\n");
io.WriteString("==================================\n");
io.WriteString("Bitte die Anfangsstellung eingeben\n");
io.WriteString("(z.B. Weiß: Th8 Ka1, Schwarz: Kd5)\n\n");
LOOP
  io.WriteString("Weiß   : T");
  abbruch := LesePosition(altpos.wtx,altpos.wty);
  io.WriteString("         K");
  abbruch := LesePosition(altpos.wkx,altpos.wky);
  io.WriteString("Schwarz: K");
  abbruch := LesePosition(altpos.skx,altpos.sky);
  IF QuevedoRoutinen.LegaleStellung(altpos) THEN
    EXIT
  END;
  io.WriteString("\nSorry, illegale Stellung !\n\n")
END;
io.WriteLn;
Brettmalen;
BeschreibeFeld(altpos.wtx,altpos.wty,2,"T");
BeschreibeFeld(altpos.wkx,altpos.wky,2,"K");
BeschreibeFeld(altpos.skx,altpos.sky,1,"K");
abbruch := FALSE;
zuege := 1;
neupos := altpos;
REPEAT
  QuevedoRoutinen.WeisserZug(neupos);
  GotoXY(49,zuege + 1);
  io.WriteInt(zuege,2);
  io.WriteString(".  ");
  IF neupos.turmzug THEN
    io.Write("T");
    SchreibePosition(altpos.wtx,altpos.wty);
    io.Write("-");
    SchreibePosition(neupos.wtx,neupos.wty);
    BeschreibeFeld(altpos.wtx,altpos.wty,-1," ");
    BeschreibeFeld(neupos.wtx,neupos.wty,2,"T")
  ELSE
    io.Write("K");
    SchreibePosition(altpos.wkx,altpos.wky);
    io.Write("-");
    SchreibePosition(neupos.wkx,neupos.wky);
    BeschreibeFeld(altpos.wkx,altpos.wky,-1," ");
    BeschreibeFeld(neupos.wkx,neupos.wky,2,"K")
  END;
  IF neupos.schach THEN
    GotoXY(60,zuege + 1);
    io.Write("+")
  END;
  IF ~neupos.matt THEN
    GotoXY(62,zuege + 1);
    io.Write("K");
    SchreibePosition(altpos.skx,altpos.sky);
    io.Write("-");
    REPEAT
      neupos.skx := altpos.skx;
      neupos.sky := altpos.sky;
      GotoXY(66,zuege + 1);
      abbruch := LesePosition(neupos.skx,neupos.sky);
      GotoXY(66,zuege + 1);
      io.WriteString("\[K")
    UNTIL abbruch OR QuevedoRoutinen.LegaleStellung(neupos) &
          ((neupos.skx # altpos.skx) OR (neupos.sky # altpos.sky)) &
          (ABS(neupos.skx - altpos.skx) <= 1) &
          (ABS(neupos.sky - altpos.sky) <= 1);
    IF ~abbruch THEN
      BeschreibeFeld(altpos.skx,altpos.sky,-1," ");
      BeschreibeFeld(neupos.skx,neupos.sky,1,"K");
      GotoXY(66,zuege + 1);
      SchreibePosition(neupos.skx,neupos.sky)
    END
  ELSE
    io.Write("+")
  END;
  altpos := neupos;
  INC(zuege)
UNTIL neupos.matt OR abbruch;
GotoXY(1,28);
io.closeDelay := 250
END Quevedo.

