home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / dev / obero / oberon / demos / mines.mod (.txt) < prev    next >
Encoding:
Oberon Text  |  2002-10-03  |  37.2 KB  |  1,221 lines

  1. Syntax10.Scn.Fnt
  2. Syntax10b.Scn.Fnt
  3. FoldElems
  4. Syntax10.Scn.Fnt
  5. (* standard colors *)
  6. Syntax10.Scn.Fnt
  7. (* the colors of Mines for Windows *)
  8.         (*black=Display.white; red=1; yellow=10; lightgray=11; midgray=12; darkgray=14;
  9.         Col1=3; Col2=5; Col3=red; Col4=6; Col5=4; Col6=8; Col7=7; Col8=black;*)
  10. MODULE Mines; (* Oberon-Mines V1.31  (C) 1 Oct  94 by Ralf Degner *)
  11.     IMPORT
  12.         Oberon, Texts,  Display, MenuViewers, TextFrames, Input, Fonts, Viewers, SYSTEM, Files;
  13.     CONST
  14. (* the colors of Mines with Mines.Pal *)
  15.         black=Display.white; red=1; yellow=4; lightgray=12; midgray=13; darkgray=14;
  16.         Col1=3; Col2=2; Col3=red; Col4=9; Col5=7; Col6=5; Col7=6; Col8=black;
  17. (*MS-Windows Colors*)
  18.         Menu = "System.Close  System.Copy  System.Grow  Mines.Pause  Mines.Beginner  Mines.Advanced  Mines.Expert  Mines.Max  Mines.Score";
  19.         KastenBreite=16;ObenPlatz=25;
  20.         UntenPlatz=4;SeitenPlatz=4;
  21.         KastenPlatz*=KastenBreite+1;KB=KastenBreite;
  22.         MinKastenAnz=7;CharBreite=8;
  23.     TYPE
  24.         FeldPtr* = POINTER TO ARRAY OF ARRAY OF SHORTINT;
  25.         String = ARRAY 32 OF CHAR;
  26.         HiScoreType = RECORD
  27.             Name: String;
  28.             Time: LONGINT;
  29.         END;
  30.         HiScoreArrayType = ARRAY 3 OF HiScoreType;
  31.         Data* = POINTER TO DataDesc;
  32.         DataDesc* = RECORD
  33.             XKastenAnz*,YKastenAnz*: INTEGER;
  34.             Aktiv*, Pause*, StartPlay*: BOOLEAN;
  35.             Feld*: FeldPtr;
  36.             Time*, Count*, Mines*: LONGINT;
  37.             Quote*, Mode*: INTEGER;
  38.         END;
  39.         Frame* = POINTER TO FrameDesc;
  40.         FrameDesc* = RECORD(Display.FrameDesc)
  41.             SeitenOffset*, UntenOffset*: INTEGER;
  42.             LastModMsg: BOOLEAN;
  43.             d*: Data;
  44.         END;
  45.         MinerMsg = RECORD(Display.FrameMsg)
  46.             d*: Data;
  47.         END;
  48.         PlotNewMsg = RECORD(MinerMsg)
  49.         END;
  50.         PlotKastenMsg* = RECORD(MinerMsg)
  51.             x*, y*: INTEGER;
  52.         END;
  53.         NeuesFeldMsg = RECORD(MinerMsg)
  54.             Change: BOOLEAN;
  55.         END;
  56.         RePlotMsg = RECORD(MinerMsg)
  57.             All: BOOLEAN;
  58.         END;
  59.         TimeMsg = RECORD(MinerMsg)
  60.             id: LONGINT;
  61.             Count: INTEGER;
  62.         END;
  63.         UsedFont: Fonts.Font;
  64.         W: Texts.Writer;
  65.         TimeTask: Oberon.Task;
  66.         seed, StartTime, LastTime: LONGINT;
  67.         HiScore: HiScoreArrayType;
  68.         Name: String;
  69.         ScoreFile: Files.File;
  70.         ScoreRider: Files.Rider;
  71.         Color, UseTimeTask, TimeTaskRuns, PauseFlag: BOOLEAN;
  72.         Colors: ARRAY 8 OF INTEGER;
  73.         Dummy: INTEGER;
  74.         (* data for patterns *)
  75.         HappyData, SadData, BackData, GotItData, PauseData: ARRAY 17 OF SET;
  76.         HappyPat, SadPat, BackPat, GotItPat, PausePat: LONGINT;
  77.         Data1, Data2, Data3, Data4: ARRAY 13 OF SET;
  78.         Pat: ARRAY 5 OF LONGINT;
  79.     (* clear HiScore *)
  80.     PROCEDURE ClearHi;
  81.         VAR Dummy: INTEGER;
  82.     BEGIN
  83.         FOR Dummy:=0 TO 2 DO
  84.             HiScore[Dummy].Time:=999999;
  85.             HiScore[Dummy].Name:="Amiga";
  86.         END;
  87.     END ClearHi;
  88.     (* store HiScore *)
  89.     PROCEDURE SaveHi(Register: BOOLEAN);
  90.         VAR Dum: INTEGER;
  91.     BEGIN
  92.         Files.Set(ScoreRider, ScoreFile, 0);
  93.         Files.WriteBool(ScoreRider, Color);
  94.         Files.WriteBool(ScoreRider, UseTimeTask);
  95.         FOR Dum:=0 TO 2 DO
  96.             Files.WriteLInt(ScoreRider, HiScore[Dum].Time);
  97.             Files.WriteBytes(ScoreRider, HiScore[Dum].Name, 32);
  98.         END;
  99.         IF Register THEN
  100.             Files.Register(ScoreFile);
  101.         ELSE
  102.              Files.Close(ScoreFile);
  103.          END;
  104.     END SaveHi;
  105.     (* load HiScore *)
  106.     PROCEDURE LoadHi;
  107.         VAR Dum: INTEGER;
  108.     BEGIN
  109.         ClearHi();
  110.         ScoreFile:=Files.Old("Mines.Score");
  111.         IF ScoreFile=NIL THEN
  112.             ScoreFile:=Files.New("Mines.Score");
  113.             SaveHi(TRUE);
  114.         ELSE
  115.             Files.Set(ScoreRider, ScoreFile, 0);
  116.             Files.ReadBool(ScoreRider, Color);
  117.             Files.ReadBool(ScoreRider, UseTimeTask);
  118.             FOR Dum:=0 TO 2 DO
  119.                 Files.ReadLInt(ScoreRider, HiScore[Dum].Time);
  120.                 Files.ReadBytes(ScoreRider, HiScore[Dum].Name, 32);
  121.             END;
  122.         END;
  123.     END LoadHi;
  124.     (* produces random numbers *)
  125.     PROCEDURE Random(Ein: INTEGER):INTEGER;
  126.         VAR
  127.             Max, Wert: INTEGER;
  128.             Gerade: BOOLEAN;
  129.     BEGIN
  130.         IF (Ein MOD 2)=0 THEN
  131.             Max:=Ein+1;
  132.             Gerade:=TRUE;
  133.         ELSE
  134.             Max:=Ein;
  135.             Gerade:=FALSE;
  136.         END;
  137.         seed:=SYSTEM.ROT(ASH(Input.Time(), -1)+ASH(seed, -1), 13);
  138.         seed:=SYSTEM.ROT(seed, seed MOD 32);
  139.         seed:=SYSTEM.ROT(2147483647+ASH(seed, -1), 13);
  140.         seed:=SYSTEM.ROT(seed, seed DIV 01000000H);
  141.         Wert:=SHORT(seed  MOD Max);
  142.         IF Gerade THEN
  143.             IF Wert=Ein THEN
  144.                 RETURN Random(Ein);
  145.             END;
  146.         END;
  147.         RETURN Wert;
  148.     END Random;
  149.     (* stop the TimeTask *)
  150.     PROCEDURE StopTask*;
  151.     BEGIN
  152.         IF TimeTaskRuns THEN
  153.             Oberon.Remove(TimeTask);
  154.             TimeTaskRuns:=FALSE;
  155.         END;
  156.     END StopTask;
  157.     (* the task, that sends every second a TimeMsg *)
  158.     PROCEDURE TheTimeTask;
  159.         VAR timsg: TimeMsg;
  160.     BEGIN
  161.         IF Input.Time()>LastTime THEN
  162.             LastTime:=LastTime+Input.TimeUnit;
  163.             timsg.id:=StartTime;
  164.             timsg.Count:=0;
  165.             Viewers.Broadcast(timsg);
  166.             IF timsg.Count=0 THEN StopTask();END;
  167.         END;
  168.     END TheTimeTask;
  169.     (* start the TimeTask *)
  170.     PROCEDURE StartTask;
  171.     BEGIN
  172.         IF ~TimeTaskRuns THEN
  173.             NEW(TimeTask);
  174.             TimeTask.safe:=FALSE;
  175.             TimeTask.handle:=TheTimeTask;
  176.             Oberon.Install(TimeTask);
  177.             LastTime:=Input.Time();
  178.             TimeTaskRuns:=TRUE;
  179.         END;
  180.     END StartTask;
  181.     (* draw box at top of the field *)
  182.     PROCEDURE PlotSmily(f: Frame; Smile: BOOLEAN);
  183.         VAR XPos, YPos, Col: INTEGER;
  184.     BEGIN
  185.         IF f.H>ObenPlatz THEN
  186.             IF f.W>30 THEN
  187.                 YPos:=f.Y+f.H-ObenPlatz+3;
  188.                 XPos:=f.W DIV 2-10+f.X;
  189.                 IF Color THEN
  190.                     Display.ReplConst(lightgray, XPos, YPos, 20, 20, Display.replace);
  191.                     Display.ReplConst(darkgray, XPos+1, YPos, 19, 19, Display.replace);
  192.                     Display.ReplConst(midgray, XPos+1, YPos+1, 18, 18, Display.replace);
  193.                     Display.CopyPattern(yellow, BackPat, XPos+2, YPos+2, Display.paint);
  194.                     Col:=black;
  195.                 ELSE
  196.                     Display.ReplConst(Display.white, XPos, YPos, 20, 20, Display.replace);
  197.                     Display.ReplConst(Display.black, XPos+1, YPos+1, 18, 18, Display.replace);
  198.                     Col:=Display.white;
  199.                 END;
  200.                 IF f.d.Pause THEN
  201.                     Display.CopyPattern(Col, PausePat, XPos+2, YPos+2, Display.paint);
  202.                 ELSE
  203.                     IF Smile THEN                
  204.                         Display.CopyPattern(Col, HappyPat, XPos+2, YPos+2, Display.paint);
  205.                     ELSE
  206.                         Display.CopyPattern(Col, SadPat, XPos+2, YPos+2, Display.paint);
  207.                     END;
  208.                 END;
  209.             END;
  210.         END;    
  211.     END PlotSmily;
  212.     (* clear a frame *)
  213.     PROCEDURE ClearFrame(f: Frame; Smile: BOOLEAN);
  214.     BEGIN
  215.         Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
  216.         Display.ReplConst(Display.black, f.X, f.Y, f.W, f.H, Display.replace);
  217.         f.SeitenOffset:=(f.W-f.d.XKastenAnz*KastenPlatz) DIV 2 +f.X;
  218.         f.UntenOffset:=f.Y+f.H-ObenPlatz-f.d.YKastenAnz*KastenPlatz;
  219.         PlotSmily(f, Smile);
  220.     END ClearFrame;
  221.     (* copy frame with same data *)
  222.     PROCEDURE CopyMe(f: Frame): Frame;
  223.         VAR nf: Frame;
  224.     BEGIN
  225.         NEW(nf);IF nf=NIL THEN RETURN NIL;END;
  226.         nf.handle:=f.handle;
  227.         nf.d:=f.d;nf.LastModMsg:=TRUE;
  228.         RETURN nf;
  229.     END CopyMe;
  230.     (* clear a box *)
  231.     PROCEDURE ClearKasten(f: Frame; x, y: INTEGER; Color: BOOLEAN);
  232.         VAR dumx, dumy: INTEGER;
  233.     BEGIN
  234.         dumx:=f.SeitenOffset+x*KastenPlatz-KastenBreite;
  235.         dumy:=f.UntenOffset+y*KastenPlatz-KastenBreite;
  236.         IF Color THEN
  237.             Display.ReplConst(darkgray, dumx, dumy, KB, KB, Display.replace);
  238.             Display.ReplConst(lightgray, dumx+1, dumy, KB-1, KB-1, Display.replace);
  239.             Display.ReplConst(midgray, dumx+1, dumy+1, KB-2, KB-2, Display.replace);
  240.         ELSE
  241.             Display.ReplConst(Display.black, dumx, dumy, KB, KB, Display.replace);
  242.         END;
  243.     END ClearKasten;
  244.     (* draw not selected box *)
  245.     PROCEDURE BlockKasten(f: Frame; x, y: INTEGER; Color: BOOLEAN; col: INTEGER);
  246.         VAR dumx, dumy: INTEGER;
  247.     BEGIN
  248.         dumx:=f.SeitenOffset+x*KastenPlatz-KastenBreite;
  249.         dumy:=f.UntenOffset+y*KastenPlatz-KastenBreite;
  250.         IF Color THEN
  251.             Display.ReplConst(lightgray, dumx, dumy, KB, KB, Display.replace);
  252.             Display.ReplConst(darkgray, dumx+1, dumy, KB-1, KB-1, Display.replace);
  253.             Display.ReplConst(midgray, dumx+1, dumy+1, KB-2, KB-2, Display.replace);
  254.         ELSE
  255.             Display.ReplConst(Display.black, dumx, dumy, KB, KB, Display.replace);
  256.             Display.ReplConst(col, dumx+1, dumy+1, KB-2, KB-2, Display.replace);
  257.         END;
  258.     END BlockKasten;
  259.     (* draw char at box *)
  260.     PROCEDURE DrawChar(f: Frame; ch: CHAR; XKasten, YKasten: INTEGER; Color: BOOLEAN; col: INTEGER);
  261.         VAR
  262.             Pat: Display.Pattern;
  263.             dx, x, y, w, h: INTEGER;
  264.             dumx, dumy: INTEGER;
  265.     BEGIN
  266.         Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat);
  267.         ClearKasten(f, XKasten, YKasten, Color);
  268.         dumx:=f.SeitenOffset+XKasten*KastenPlatz-KastenBreite+(KB-w) DIV 2;
  269.         dumy:=f.UntenOffset+YKasten*KastenPlatz-KastenBreite+(KB-h) DIV 2;
  270.         IF Color THEN
  271.             col:=Colors[ORD(ch)-49];
  272.         END;
  273.         Display.CopyPattern(col, Pat, dumx, dumy, Display.paint);
  274.     END  DrawChar;
  275.     (* draw char at x y to display *)
  276.     PROCEDURE DrawZahl(ch:  CHAR; XPos, YPos: INTEGER);
  277.         VAR
  278.             Pat: Display.Pattern;
  279.             dx, x, y, w, h: INTEGER;
  280.     BEGIN
  281.         Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat);
  282.         IF Color THEN
  283.             h:=black;
  284.         ELSE
  285.             h:=Display.white;
  286.         END;
  287.         Display.CopyPattern(h, Pat, XPos+x, YPos+y, Display.paint);
  288.     END  DrawZahl;
  289.     (* draw LONGINT *)
  290.     PROCEDURE DrawInt(x, y: INTEGER; Zahl: LONGINT; DrawInt: BOOLEAN);
  291.         VAR Col, Anz: INTEGER;
  292.     BEGIN
  293.         Anz:=4;
  294.         IF Color THEN
  295.             Col:=midgray;
  296.         ELSE
  297.             Col:=Display.black;
  298.         END;
  299.         Display.ReplConst(Col, x, y, Anz*CharBreite+10, KastenBreite-2, Display.replace);
  300.         IF DrawInt THEN
  301.             IF Zahl<0 THEN
  302.                 DrawZahl("-", x+2, y+1);
  303.                 Zahl:=ABS(Zahl);
  304.             END;
  305.             REPEAT
  306.                 DrawZahl(CHR(Zahl MOD 10+48), x+Anz*CharBreite+1, y+2);
  307.                 Zahl:=Zahl DIV 10;
  308.                 DEC(Anz);
  309.             UNTIL (Zahl=0) OR (Anz=-1);
  310.         END;
  311.     END DrawInt;
  312.     (* draw number of Mines to find *)
  313.     PROCEDURE DrawMinesToFind(f: Frame);
  314.     BEGIN
  315.         DrawInt((f.W-119) DIV 2+f.X+2, f.Y+f.H-ObenPlatz+6, f.d.Mines, TRUE);
  316.     END DrawMinesToFind;
  317.     (* draw the time *)
  318.     PROCEDURE DrawTime(f: Frame);
  319.     BEGIN
  320.         DrawInt(f.W DIV 2+f.X+16, f.Y+f.H-ObenPlatz+6, (Input.Time()-f.d.Time) DIV Input.TimeUnit, f.d.StartPlay);
  321.     END DrawTime;
  322.     (* draw pattern, like mine *)
  323.     PROCEDURE DrawPat(f: Frame; XKasten, YKasten, No: INTEGER; Mode: BOOLEAN; Color: BOOLEAN; col: INTEGER);
  324.         VAR dumx, dumy: INTEGER;
  325.     BEGIN
  326.         IF Mode THEN
  327.             ClearKasten(f, XKasten, YKasten, Color);
  328.         ELSE
  329.             BlockKasten(f, XKasten, YKasten, Color, col);
  330.         END;
  331.         dumx:=f.SeitenOffset+XKasten*KastenPlatz-KastenBreite;
  332.         dumy:=f.UntenOffset+YKasten*KastenPlatz-KastenBreite;
  333.         IF Color THEN
  334.             IF No<3 THEN
  335.                 Display.CopyPattern(black, Pat[1], dumx+2, dumy+2, Display.paint);
  336.                 IF No=2 THEN
  337.                     Display.CopyPattern(red, Pat[2], dumx+2, dumy+2, Display.paint);
  338.                 END;
  339.             ELSE
  340.                 Display.CopyPattern(red, Pat[3], dumx+2, dumy+2, Display.paint);
  341.                 Display.ReplConst(black, dumx+5, dumy+3, 1, 10, Display.replace);
  342.             END;
  343.         ELSE
  344.             IF No=1 THEN
  345.                 IF Mode THEN
  346.                     Display.CopyPattern(col, Pat[1], dumx+2, dumy+2, Display.paint);
  347.                 ELSE
  348.                     Display.CopyPattern(Display.black, Pat[1], dumx+2, dumy+2, Display.paint);
  349.                 END;
  350.             ELSE
  351.                 IF No=2 THEN No:=4;END;
  352.                 Display.CopyPattern(Display.black, Pat[No], dumx+2, dumy+2, Display.paint);
  353.             END;
  354.         END;
  355.     END  DrawPat;
  356.     (* invert char *)
  357.     PROCEDURE DrawCharInv(f: Frame; ch:  CHAR; XKasten, YKasten: INTEGER);
  358.         VAR
  359.             Pat: Display.Pattern;
  360.             dx, x, y, w, h: INTEGER;
  361.             dumx, dumy: INTEGER;
  362.     BEGIN
  363.         Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat);
  364.         dumx:=f.SeitenOffset+XKasten*KastenPlatz-KB+(KB-w) DIV 2;
  365.         dumy:=f.UntenOffset+YKasten*KastenPlatz-KB+(KB-h) DIV 2;
  366.         Display.CopyPattern(Display.white, Pat, dumx, dumy, Display.invert);
  367.     END  DrawCharInv;
  368.     (* make new data *)
  369.     PROCEDURE NeuesFeld*(d: Data; x, y: INTEGER);
  370.         VAR
  371.             ZaehlerX, ZaehlerY: INTEGER;
  372.             dummy: LONGINT;
  373.             Bomben: SHORTINT;
  374.     BEGIN
  375.         NEW(d.Feld, x+2, y+2);
  376.         IF d.Feld=NIL THEN
  377.             d.Aktiv:=FALSE;
  378.             RETURN;
  379.         END;
  380.         FOR ZaehlerX:=0 TO x+1 DO
  381.             FOR ZaehlerY:=0 TO y+1 DO
  382.                 d.Feld[ZaehlerX, ZaehlerY]:=1;
  383.             END;
  384.         END;
  385.         dummy:=(LONG(x)*y*d.Quote) DIV 100;
  386.         d.Count:=LONG(x)*y-dummy;d.Mines:=dummy;
  387.         REPEAT
  388.             REPEAT
  389.                 ZaehlerX:=Random(x)+1;
  390.                 ZaehlerY:=Random(y)+1;
  391.             UNTIL d.Feld[ZaehlerX, ZaehlerY]=1;
  392.             d.Feld[ZaehlerX, ZaehlerY]:=10;
  393.             DEC(dummy);
  394.         UNTIL dummy=0;
  395.          FOR ZaehlerX:=1 TO x DO
  396.             FOR ZaehlerY:=1 TO y DO
  397.                 IF d.Feld[ZaehlerX, ZaehlerY]=1 THEN
  398.                     Bomben:=1;
  399.                     IF d.Feld[ZaehlerX+1, ZaehlerY]=10 THEN INC(Bomben);END;
  400.                     IF d.Feld[ZaehlerX+1, ZaehlerY+1]=10 THEN INC(Bomben);END;
  401.                     IF d.Feld[ZaehlerX, ZaehlerY+1]=10 THEN INC(Bomben);END;
  402.                     IF d.Feld[ZaehlerX-1, ZaehlerY+1]=10 THEN INC(Bomben);END;
  403.                     IF d.Feld[ZaehlerX-1, ZaehlerY]=10 THEN INC(Bomben);END;
  404.                     IF d.Feld[ZaehlerX-1, ZaehlerY-1]=10 THEN INC(Bomben);END;
  405.                     IF d.Feld[ZaehlerX, ZaehlerY-1]=10 THEN INC(Bomben);END;
  406.                     IF d.Feld[ZaehlerX+1, ZaehlerY-1]=10 THEN INC(Bomben);END;
  407.                     d.Feld[ZaehlerX, ZaehlerY]:=Bomben;
  408.                 END;
  409.             END;
  410.         END;
  411.     END NeuesFeld;
  412.     (* draw a box *)
  413.     PROCEDURE DrawKasten*(f: Frame; XZaehler, YZaehler: INTEGER; Color: BOOLEAN; col: INTEGER);
  414.         VAR dummy: SHORTINT;
  415.     BEGIN
  416.         dummy:=f.d.Feld[XZaehler, YZaehler];
  417.         IF dummy>0 THEN
  418.             IF dummy>16 THEN
  419.                 DrawPat(f, XZaehler, YZaehler, 3, FALSE, Color, col);
  420.             ELSE
  421.                 BlockKasten(f, XZaehler, YZaehler, Color, col);
  422.             END;
  423.         ELSE
  424.             IF dummy=-10 THEN
  425.                 DrawPat(f, XZaehler, YZaehler, 1, TRUE, Color, col);
  426.             ELSIF dummy=-1 THEN
  427.                 ClearKasten(f, XZaehler, YZaehler, Color);
  428.             ELSE
  429.                 DrawChar(f, CHR(47-dummy), XZaehler, YZaehler, Color, col);
  430.             END;
  431.         END;
  432.     END DrawKasten;
  433.     (* draw all *)    
  434.     PROCEDURE PlotAll(f: Frame);
  435.         VAR xdum, ydum: INTEGER;
  436.     BEGIN
  437.         xdum:=(f.W-7*KastenPlatz) DIV 2+f.X+2;
  438.         ydum:=f.Y+f.H-ObenPlatz+6;
  439.         IF Color THEN
  440.             Display.ReplConst(lightgray, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace);
  441.             Display.ReplConst(darkgray, xdum, ydum-1, 4*CharBreite+11, KastenBreite-1, Display.replace);
  442.             xdum:=f.W DIV 2+f.X+16;
  443.             Display.ReplConst(lightgray, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace);
  444.             Display.ReplConst(darkgray, xdum, ydum-1, 4*CharBreite+11, KastenBreite-1, Display.replace);
  445.         ELSE
  446.             Display.ReplConst(Display.white, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace);
  447.             xdum:=f.W DIV 2+f.X+16;
  448.             Display.ReplConst(Display.white, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace);
  449.         END;
  450.         DrawMinesToFind(f);
  451.         DrawTime(f);
  452.         ydum:=f.d.YKastenAnz*KastenPlatz+1;
  453.         xdum:=f.d.XKastenAnz*KastenPlatz+1;
  454.         IF Color THEN
  455.             Display.ReplConst(midgray, f.SeitenOffset, f.UntenOffset, xdum, ydum, Display.replace);
  456.             Display.ReplConst(lightgray, f.SeitenOffset-1, f.UntenOffset-1, 1, ydum+2, Display.replace);
  457.             Display.ReplConst(lightgray, f.SeitenOffset-1, f.UntenOffset+ydum, xdum+1, 1, Display.replace);
  458.             Display.ReplConst(darkgray, f.SeitenOffset-1, f.UntenOffset-1, xdum+2, 1, Display.replace);
  459.             Display.ReplConst(darkgray, f.SeitenOffset+xdum, f.UntenOffset-1, 1, ydum+2, Display.replace);
  460.         ELSE
  461.             Display.ReplConst(Display.white, f.SeitenOffset, f.UntenOffset, xdum, ydum, Display.replace);
  462.         END;
  463.         FOR xdum:=1 TO f.d.XKastenAnz DO
  464.             FOR ydum:=1 TO f.d.YKastenAnz DO
  465.                 DrawKasten(f, xdum, ydum, Color, Display.white);
  466.             END;
  467.         END;
  468.     END PlotAll;
  469.     (* draw all, if finding a mine *)
  470.     PROCEDURE SwitchAll(f: Frame; Color: BOOLEAN; col: INTEGER);
  471.         VAR
  472.             xdum, ydum: INTEGER;
  473.             Typ: SHORTINT;
  474.     BEGIN
  475.         Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
  476.         FOR xdum:=1 TO f.d.XKastenAnz DO
  477.             FOR ydum:=1 TO f.d.YKastenAnz DO
  478.                 Typ:=f.d.Feld[xdum, ydum];
  479.                 IF Typ>0 THEN
  480.                     IF Typ=10 THEN
  481.                         DrawPat(f, xdum, ydum, 1, FALSE, Color, col);
  482.                     ELSIF Typ<10 THEN
  483.                         f.d.Feld[xdum, ydum]:=-Typ;
  484.                         DrawKasten(f, xdum, ydum, Color, col);
  485.                     ELSIF (Typ>16) & (Typ#26) THEN
  486.                         DrawPat(f, xdum, ydum, 2, FALSE, Color, col);
  487.                     END;
  488.                 END;
  489.             END;
  490.         END;
  491.     END SwitchAll;
  492.     (* test if Raster fits to frame *)
  493.     PROCEDURE TestRaster(f: Frame): BOOLEAN;
  494.         VAR XMax,YMax: INTEGER;
  495.     BEGIN
  496.         XMax:=(f.W-SeitenPlatz*2) DIV KastenPlatz;
  497.         YMax:=(f.H-ObenPlatz-UntenPlatz) DIV KastenPlatz;
  498.         IF XMax<f.d.XKastenAnz THEN RETURN FALSE;END;
  499.         IF YMax<f.d.YKastenAnz THEN RETURN FALSE;END;
  500.         RETURN TRUE;
  501.     END TestRaster;
  502.     (* check if Raster fits to frame *)
  503.     PROCEDURE CheckRaster(f: Frame): BOOLEAN;
  504.         VAR
  505.             XMax,YMax: INTEGER;
  506.             Change, Aktiv: BOOLEAN;
  507.             XAnzNeu, YAnzNeu: INTEGER;
  508.     BEGIN
  509.         Change:=FALSE;Aktiv:=TRUE;
  510.         XMax:=(f.W-SeitenPlatz*2) DIV KastenPlatz;
  511.         YMax:=(f.H-ObenPlatz-UntenPlatz) DIV KastenPlatz;
  512.         IF XMax<MinKastenAnz THEN Aktiv:=FALSE;Change:=TRUE;END;
  513.         IF YMax<MinKastenAnz THEN Aktiv:=FALSE;Change:=TRUE;END;
  514.         IF XMax<f.d.XKastenAnz THEN
  515.             XAnzNeu:=XMax;Change:=TRUE;
  516.         ELSE
  517.             XAnzNeu:=f.d.XKastenAnz;
  518.         END;
  519.         IF YMax<f.d.YKastenAnz THEN
  520.             YAnzNeu:=YMax;Change:=TRUE;
  521.         ELSE
  522.             YAnzNeu:=f.d.YKastenAnz;
  523.         END;
  524.         IF Change THEN
  525.             IF Aktiv THEN
  526.                 f.d.XKastenAnz:=XAnzNeu;f.d.YKastenAnz:=YAnzNeu;
  527.                 f.d.Aktiv:=TRUE;
  528.             ELSE
  529.                 f.d.Aktiv:=FALSE;
  530.             END;
  531.             f.d.Mode:=-1;
  532.         END;
  533.         RETURN Change;
  534.     END CheckRaster;
  535.     (* check if field fits to frame; if not, creat new field *)
  536.     PROCEDURE CalcRaster (f: Frame): BOOLEAN;
  537.         VAR pnmsg: PlotNewMsg;
  538.     BEGIN
  539.         IF CheckRaster(f) THEN
  540.             pnmsg.d:=f.d;
  541.             IF f.d.Aktiv THEN
  542.                 NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
  543.             END;
  544.             f.d.StartPlay:=FALSE;
  545.             Viewers.Broadcast(pnmsg);
  546.             RETURN TRUE;
  547.         ELSE
  548.             RETURN FALSE;
  549.         END;
  550.     END CalcRaster;
  551.     (* search boxes with no mine on it *)
  552.     PROCEDURE SearchMore(d: Data; x, y: INTEGER);
  553.         VAR
  554.             Dummy: SHORTINT;
  555.             pkmsg: PlotKastenMsg;
  556.     BEGIN
  557.         IF (x=0) OR (y=0) OR (x>d.XKastenAnz) OR (y>d.YKastenAnz) THEN RETURN;END;
  558.         Dummy:=d.Feld[x, y];
  559.         IF (Dummy<0) OR (Dummy>9) THEN RETURN;END;
  560.         DEC (d.Count);
  561.         d.Feld[x, y]:=-Dummy;
  562.         pkmsg.d:=d;
  563.         pkmsg.x:=x;pkmsg.y:=y;
  564.         Viewers.Broadcast(pkmsg);
  565.         IF Dummy=1 THEN
  566.             SearchMore(d, x+1, y);SearchMore(d, x+1, y+1);
  567.             SearchMore(d, x,y+1);SearchMore(d, x-1, y+1);
  568.             SearchMore(d, x-1, y);SearchMore(d, x-1, y-1);
  569.             SearchMore(d, x, y-1);SearchMore(d, x+1, y-1);
  570.         END;
  571.     END SearchMore;
  572.     (* new HIScore ? *)
  573.     PROCEDURE CheckHiScore(d: Data);
  574.     BEGIN
  575.         IF d.Mode>-1 THEN
  576.             IF d.Time<HiScore[d.Mode].Time THEN
  577.                 Texts.WriteString(W, "New Hi-Score !!!");Texts.WriteLn(W);
  578.                 Texts.Append(Oberon.Log, W.buf);
  579.                 HiScore[d.Mode].Time:=d.Time;
  580.                 HiScore[d.Mode].Name:=Name;
  581.                 SaveHi(FALSE);
  582.             END;
  583.         END;
  584.     END CheckHiScore;
  585.     (* all Mines found *)
  586.     PROCEDURE GotIt(f: Frame);
  587.         VAR XPos, YPos: INTEGER;
  588.     BEGIN
  589.         YPos:=f.Y+f.H-ObenPlatz+4;
  590.         XPos:=(f.W DIV 2)-9+f.X;
  591.         Display.CopyPattern(black, GotItPat, XPos+1, YPos+1, Display.paint);
  592.         f.d.Mines:=0;DrawMinesToFind(f);
  593.     END GotIt;
  594.     (* switch field *)
  595.     PROCEDURE SwitchKasten(f: Frame; XKasten, YKasten: INTEGER; Color: BOOLEAN; col: INTEGER);
  596.         VAR
  597.             timsg: TimeMsg;
  598.             pkmsg: PlotKastenMsg;
  599.             Dummy: SHORTINT;
  600.     BEGIN
  601.         IF ~f.d.Aktiv THEN RETURN; END;
  602.         Dummy:=f.d.Feld[XKasten, YKasten];
  603.         IF (Dummy>0) & (Dummy<16) THEN
  604.             pkmsg.d:=f.d;
  605.             pkmsg.x:=XKasten;pkmsg.y:=YKasten;
  606.             IF Dummy=10 THEN
  607.                 f.d.Feld[XKasten, YKasten]:=-10;
  608.                 f.d.Aktiv:=FALSE;
  609.                 SwitchAll(f, Color, col);
  610.                 Viewers.Broadcast(pkmsg);
  611.             ELSE
  612.                 IF Dummy=1 THEN
  613.                     SearchMore(f.d, XKasten, YKasten);
  614.                 ELSE
  615.                     f.d.Feld[XKasten, YKasten]:=-Dummy;
  616.                     DEC(f.d.Count);
  617.                     Viewers.Broadcast(pkmsg);
  618.                 END;
  619.                 IF f.d.Count=0 THEN
  620.                     LastTime:=Input.Time()-1;
  621.                     timsg.id:=StartTime;
  622.                     timsg.Count:=0;
  623.                     Viewers.Broadcast(timsg);
  624.                     f.d.Aktiv:=FALSE;
  625.                     f.d.Time:=(Input.Time()-f.d.Time) DIV Input.TimeUnit;
  626.                     CheckHiScore(f.d);
  627.                 END;
  628.             END;
  629.         END;
  630.     END SwitchKasten;
  631.     (* react on mouse keys *)
  632.     PROCEDURE MouseKeys*(f: Frame; XKasten, YKasten: INTEGER; Key: SET; Color: BOOLEAN; col: INTEGER);
  633.         VAR
  634.             Dummy: SHORTINT;
  635.             pkmsg: PlotKastenMsg;
  636.     BEGIN
  637.         Dummy:=f.d.Feld[XKasten, YKasten];
  638.         pkmsg.d:=f.d;
  639.         pkmsg.x:=XKasten;pkmsg.y:=YKasten;
  640.         IF Key={2} THEN
  641.             IF ~f.d.StartPlay THEN
  642.                 f.d.StartPlay:=TRUE;
  643.                 f.d.Time:=Input.Time();
  644.             END;
  645.             SwitchKasten(f, XKasten, YKasten, Color, col);
  646.         ELSIF Key={0} THEN
  647.             IF Dummy>0 THEN
  648.                 IF Dummy<16 THEN
  649.                     f.d.Feld[XKasten, YKasten]:=Dummy+16;
  650.                     f.d.Mines:=f.d.Mines-1;
  651.                 ELSE
  652.                     f.d.Feld[XKasten, YKasten]:=Dummy-16;
  653.                     f.d.Mines:=f.d.Mines+1;
  654.                 END;
  655.                 Viewers.Broadcast(pkmsg);
  656.             END;
  657.         ELSIF Key={0,2} THEN
  658.             IF Dummy<0 THEN
  659.                 IF ~f.d.StartPlay THEN
  660.                     f.d.StartPlay:=TRUE;
  661.                     f.d.Time:=Input.Time();
  662.                 END;
  663.                 SwitchKasten(f, XKasten+1, YKasten, Color, col);
  664.                 SwitchKasten(f, XKasten+1, YKasten-1, Color, col);
  665.                 SwitchKasten(f, XKasten, YKasten-1, Color, col);
  666.                 SwitchKasten(f, XKasten-1, YKasten-1, Color, col);
  667.                 SwitchKasten(f, XKasten-1, YKasten, Color, col);
  668.                 SwitchKasten(f, XKasten-1, YKasten+1, Color, col);
  669.                 SwitchKasten(f, XKasten, YKasten+1, Color, col);
  670.                 SwitchKasten(f, XKasten+1, YKasten+1, Color, col);
  671.             END;
  672.         END;
  673.     END MouseKeys;
  674.     (* get selected frame *)    
  675.     PROCEDURE GetFrame(VAR f: Display.Frame): BOOLEAN;
  676.         VAR v: Viewers.Viewer;
  677.     BEGIN
  678.         IF Oberon.Par.frame=Oberon.Par.vwr.dsc THEN
  679.             IF (Oberon.Par.frame # NIL) THEN
  680.                 f:=Oberon.Par.frame.next;
  681.                 RETURN TRUE;
  682.             END;
  683.         ELSE
  684.             v:=Oberon.MarkedViewer();
  685.             IF (v.dsc # NIL) & (v.dsc.next # NIL) THEN
  686.                 f:=v.dsc.next;
  687.                 RETURN TRUE;
  688.             END
  689.         END;
  690.         RETURN FALSE;
  691.     END GetFrame;
  692.     (* do the pause *)
  693.     PROCEDURE DoPause(f: Frame);
  694.         VAR
  695.             nfmsg: NeuesFeldMsg;
  696.             rpmsg: RePlotMsg;
  697.             pnmsg: PlotNewMsg;
  698.     BEGIN
  699.         IF f.d.Pause THEN
  700.             IF TestRaster(f) OR PauseFlag THEN
  701.                 f.d.Pause:=FALSE;
  702.                 nfmsg.d:=f.d;nfmsg.Change:=FALSE;
  703.                 Viewers.Broadcast(nfmsg);
  704.                 IF nfmsg.Change THEN
  705.                     IF f.d.Aktiv THEN
  706.                         NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
  707.                     END;
  708.                     pnmsg.d:=f.d;
  709.                     Viewers.Broadcast(pnmsg);
  710.                     f.d.StartPlay:=FALSE;
  711.                 ELSE
  712.                     rpmsg.All:=FALSE;
  713.                     rpmsg.d:=f.d;
  714.                     f.d.Time:=Input.Time()-f.d.Time;
  715.                     Viewers.Broadcast(rpmsg);
  716.                 END;
  717.             ELSE
  718.                 Texts.WriteString(W, "Frame too small for old game !");
  719.                 Texts.WriteLn(W);
  720.                 Texts.Append(Oberon.Log, W.buf);
  721.                 PauseFlag:=TRUE;
  722.             END;
  723.         ELSE
  724.             f.d.Pause:=TRUE;
  725.             f.d.Time:=Input.Time()-f.d.Time;
  726.             rpmsg.d:=f.d;rpmsg.All:=FALSE;
  727.             Viewers.Broadcast(rpmsg);
  728.         END;
  729.     END DoPause;
  730.     (* set Pause mode *)
  731.     PROCEDURE Pause*;
  732.         VAR
  733.             f, g: Display.Frame;
  734.     BEGIN
  735.         IF GetFrame(g) THEN
  736.             f:=g;
  737.             WITH f: Frame DO
  738.                 IF f.d.Aktiv THEN DoPause(f);END;
  739.             ELSE
  740.             END;
  741.         END;
  742.     END Pause;
  743.     (* do mouseaction *)
  744.     PROCEDURE DoMou(f: Frame; X, Y: INTEGER; Key, FirstKey: SET);
  745.         VAR
  746.             XKasten, YKasten: INTEGER;
  747.             XStore, YStore: INTEGER;
  748.             Dummy: SHORTINT;
  749.             pnmsg: PlotNewMsg;
  750.             nfmsg: NeuesFeldMsg;
  751.     BEGIN
  752.         IF f.d.Pause THEN RETURN; END;
  753.         XStore:=X;YStore:=Y;
  754.         X:=X-f.SeitenOffset;Y:=Y-f.UntenOffset;
  755.         IF X<0 THEN RETURN;END;
  756.         IF Y<0 THEN RETURN;END;
  757.         XKasten:=X DIV KastenPlatz +1;
  758.         YKasten:=Y DIV KastenPlatz +1;
  759.         IF (XKasten<=f.d.XKastenAnz) & (YKasten<=f.d.YKastenAnz) THEN
  760.             IF ~f.d.Aktiv THEN RETURN;END;
  761.             IF (X MOD KastenPlatz)=0 THEN RETURN;END;
  762.             IF (Y MOD KastenPlatz)=0 THEN RETURN;END;
  763.             Dummy:=f.d.Feld[XKasten, YKasten];
  764.             IF Key={1} THEN
  765.                 IF Dummy>0 THEN
  766.                     IF Dummy<16 THEN
  767.                         Oberon.RemoveMarks(f.SeitenOffset, f.UntenOffset, f.W, f.H);
  768.                         DrawCharInv(f, "?", XKasten, YKasten);
  769.                     END;
  770.                 END;
  771.             ELSE
  772.                 MouseKeys(f, XKasten, YKasten, Key, Color, Display.white);
  773.             END;
  774.             IF ~UseTimeTask THEN DrawTime(f);END;
  775.             IF f.d.Count=0 THEN
  776.                 GotIt(f);
  777.             END;
  778.         ELSE
  779.             IF (YStore>f.Y+f.H-ObenPlatz+3) & (YStore<f.Y+f.H-3) THEN
  780.                 IF (ABS(XStore-f.X-(f.W DIV 2))<10) THEN
  781.                     IF Key={2} THEN
  782.                         nfmsg.d:=f.d;
  783.                         f.d.Aktiv:=TRUE;
  784.                         Viewers.Broadcast(nfmsg);
  785.                         IF f.d.Aktiv THEN
  786.                             NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
  787.                         END;
  788.                         pnmsg.d:=f.d;
  789.                         f.d.StartPlay:=FALSE;
  790.                         Viewers.Broadcast(pnmsg);
  791.                     END;
  792.                 END;
  793.             END;
  794.         END;
  795.     END DoMou;
  796.     (* set mousecursor and call DoMouse if button is pressed *)
  797.     PROCEDURE TrackMouse*(f: Frame; X, Y: INTEGER; k: SET; Mou: PROCEDURE(f: Frame; X, Y: INTEGER; K, F: SET));
  798.         VAR
  799.             XPos, YPos: INTEGER;
  800.             NewKeys, FirstKey: SET;
  801.     BEGIN
  802.         XPos:=X;YPos:=Y;
  803.         FirstKey:=k;
  804.         REPEAT
  805.             Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, X, Y);
  806.             Input.Mouse(NewKeys, X, Y);
  807.             k:=k+NewKeys;
  808.         UNTIL NewKeys={};
  809.         IF k#{} THEN Mou(f, XPos, YPos, k, FirstKey);END;
  810.     END TrackMouse;
  811.     (* the Handler of the Miner-Frames*)
  812.     PROCEDURE Handler(f: Display.Frame; VAR m: Display.FrameMsg);
  813.         VAR
  814.             self: Frame;
  815.             dumY, dumH: INTEGER;
  816.     BEGIN
  817.         self:=f(Frame);
  818.         WITH m: Oberon.InputMsg DO
  819.             IF m.id=Oberon.track THEN TrackMouse(self, m.X, m.Y, m.keys, DoMou);END;
  820.         | m: Oberon.CopyMsg DO
  821.             m.F:=CopyMe(self);
  822.         | m: MenuViewers.ModifyMsg DO
  823.             PauseFlag:=FALSE;
  824.             IF m.H=0 THEN
  825.                 self.LastModMsg:=TRUE;
  826.                 RETURN;
  827.             END;
  828.             IF self.d.Pause OR ~self.d.Aktiv THEN      (* game is paused or not Aktiv *)
  829.                 f.Y:=m.Y;f.H:=m.H;
  830.                 ClearFrame(self, self.d.Aktiv);
  831.             ELSIF self.d.Aktiv THEN                         (* if Aktiv *)
  832.                 IF m.id=MenuViewers.extend THEN    (* extended *)
  833.                     IF self.LastModMsg THEN               (* extended from 0, CalcRaster new *)
  834.                         f.Y:=m.Y;f.H:=m.H;
  835.                         ClearFrame(self, TRUE);
  836.                         IF ~CalcRaster(self) THEN          (* if old Raster, then redraw *)
  837.                             PlotAll(self);
  838.                         END;
  839.                         IF UseTimeTask THEN StartTask();END;
  840.                     ELSE
  841.                         IF m.dY=0 THEN                        (* extended at the bootom, clear new area *)
  842.                             Oberon.RemoveMarks(self.X, m.Y, self.W, m.H-self.H);
  843.                             Display.ReplConst(Display.black, self.X, m.Y, self.W, m.H-self.H, Display.replace);
  844.                         ELSE                                       (* extended at the top, copy and clear new area *)
  845.                             Oberon.RemoveMarks(self.X, self.Y, self.W, self.H+m.dY);
  846.                             Display.CopyBlock(self.X, self.Y, self.W, self.H, self.X, self.Y+m.dY, Display.replace);
  847.                             Display.ReplConst(Display.black, self.X, m.Y, self.W, m.H-self.H, Display.replace);
  848.                             self.UntenOffset:=self.UntenOffset+m.dY;
  849.                         END;
  850.                     END;
  851.                 ELSIF m.id=MenuViewers.reduce THEN    (* reduced *)
  852.                     dumY:=f.Y;dumH:=f.H;
  853.                     f.Y:=m.Y;f.H:=m.H;
  854.                     IF TestRaster(self) THEN
  855.                         IF m.dY#0 THEN             (* if top moved, copy *)
  856.                             Oberon.RemoveMarks(self.X, m.Y, self.W, m.H-m.dY);
  857.                             Display.CopyBlock(self.X, dumY+dumH-m.H, self.W, m.H, self.X, m.Y, Display.replace);
  858.                             self.UntenOffset:=self.UntenOffset-m.dY;
  859.                         END;
  860.                     ELSE
  861.                         DoPause(self);
  862.                     END;
  863.                 END;
  864.             END;
  865.             self.LastModMsg:=FALSE;
  866.         | m: MinerMsg DO
  867.             WITH m: RePlotMsg DO
  868.                     IF m.All OR (m.d=self.d) THEN
  869.                         ClearFrame(self, self.d.Aktiv);
  870.                         IF self.d.Aktiv & ~self.d.Pause THEN
  871.                             PlotAll(self);
  872.                         END;
  873.                     END;
  874.             | m: TimeMsg DO
  875.                 IF m.id=StartTime THEN
  876.                     IF self.d.Aktiv & ~self.d.Pause & self.d.StartPlay  THEN
  877.                         DrawTime(self);
  878.                     END;
  879.                     INC(m.Count);
  880.                 END;
  881.             ELSE
  882.                 IF m.d=self.d THEN
  883.                     WITH m: PlotNewMsg DO            (* Message for new Raster *)
  884.                         IF self.d.Aktiv THEN
  885.                             IF ~CalcRaster(self) THEN     (* Raster OK for this Frame ? *)
  886.                                 ClearFrame(self, TRUE);
  887.                                 PlotAll(self);
  888.                             END;
  889.                         ELSE
  890.                             ClearFrame(self, FALSE);
  891.                         END;
  892.                     | m: PlotKastenMsg DO                (* PLot one box *)
  893.                         Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
  894.                         DrawKasten(self, m.x, m.y, Color, Display.white);
  895.                         IF self.d.Feld[m.x, m.y]>0 THEN
  896.                             DrawMinesToFind(self);
  897.                         END;
  898.                         IF ~self.d.Aktiv THEN PlotSmily(self, FALSE);END;
  899.                     | m: NeuesFeldMsg DO                (* Check if new W & H are fitting to frame *) 
  900.                         IF CheckRaster(self) THEN
  901.                             m.Change:=TRUE;
  902.                         END;
  903.                     ELSE
  904.                     END;
  905.                 END;
  906.             END;
  907.         ELSE
  908.         END;
  909.     END Handler;
  910.     (* get parameters *)
  911.     PROCEDURE GetPar*(VAR Quote, X, Y, Mode: INTEGER);
  912.         VAR
  913.             S: Texts.Scanner;
  914.             text: Texts.Text;
  915.             Dummy, StoreQuote: INTEGER;
  916.             beg, end, time: LONGINT;
  917.     BEGIN
  918.         StoreQuote:=Quote;
  919.         Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
  920.         Texts.Scan(S);
  921.         IF S.class=Texts.Char THEN
  922.             IF S.c="^" THEN
  923.                 Oberon.GetSelection(text, beg, end, time);
  924.                 IF time=-1 THEN RETURN; END;
  925.                 Texts.OpenScanner(S, text, beg);
  926.                 Texts.Scan(S);
  927.             ELSE
  928.                 RETURN;
  929.             END;
  930.         END;
  931.         IF S.class=Texts.Int THEN
  932.             IF (S.i>0) & (S.i<90) THEN;
  933.                 Quote:=SHORT(S.i);
  934.                 IF (Mode=-1) OR (X#256) THEN
  935.                     Texts.Scan(S);
  936.                     IF S.class=Texts.Int THEN;
  937.                         Dummy:=SHORT(S.i);
  938.                         Texts.Scan(S);
  939.                         IF S.class=Texts.Int THEN
  940.                             IF (Dummy<6) OR (Dummy>127) THEN
  941.                                 X:=8;
  942.                             ELSE
  943.                                 X:=Dummy;
  944.                             END;
  945.                             IF (S.i<6) OR (S.i>127) THEN
  946.                                 Y:=8;
  947.                             ELSE
  948.                                 Y:=SHORT(S.i);
  949.                             END;
  950.                         END;
  951.                     END;
  952.                 ELSE
  953.                     IF Quote#StoreQuote THEN Mode:=-1; END;
  954.                 END;
  955.             END;
  956.         END;
  957.     END GetPar;
  958.     (* set frame and parameters *)    
  959.     PROCEDURE ShortNewPar(X, Y, Quote, Mode: INTEGER);
  960.         VAR
  961.             f, g: Display.Frame;
  962.             nfmsg: NeuesFeldMsg;
  963.             pnmsg: PlotNewMsg;
  964.     BEGIN
  965.         IF GetFrame(g) THEN
  966.             f:=g;
  967.             WITH f: Frame DO
  968.                 GetPar(Quote, X, Y, Mode);
  969.                 f.d.Quote:=Quote;f.d.Mode:=Mode;
  970.                 f.d.XKastenAnz:=X;f.d.YKastenAnz:=Y;
  971.                 f.d.Aktiv:=TRUE;f.d.Pause:=FALSE;
  972.                 nfmsg.d:=f.d;
  973.                 Viewers.Broadcast(nfmsg);
  974.                 IF f.d.Aktiv THEN
  975.                     NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
  976.                 END;
  977.                 pnmsg.d:=f.d;
  978.                 f.d.StartPlay:=FALSE;
  979.                 Viewers.Broadcast(pnmsg);
  980.             ELSE
  981.             END;
  982.         END;
  983.     END ShortNewPar;
  984.     (* set new username *)
  985.     PROCEDURE SetUser*;
  986.         VAR
  987.             S: Texts.Scanner;
  988.             text: Texts.Text;
  989.             beg, end, time: LONGINT;
  990.     BEGIN
  991.         Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
  992.         Texts.Scan(S);
  993.         IF S.class=Texts.Char THEN
  994.             IF S.c="^" THEN
  995.                 Oberon.GetSelection(text, beg, end, time);
  996.                 IF time=-1 THEN RETURN; END;
  997.                 Texts.OpenScanner(S, text, beg);
  998.                 Texts.Scan(S);
  999.             ELSE
  1000.                 RETURN;
  1001.             END;
  1002.         END;
  1003.         IF S.class=Texts.Name THEN
  1004.             COPY(S.s, Name);
  1005.         END;
  1006.         Texts.WriteString(W, "Current Username : ");
  1007.         Texts.WriteString(W, Name);
  1008.         Texts.WriteLn(W);
  1009.         Texts.Append(Oberon.Log, W.buf);    
  1010.     END SetUser;
  1011.     (* print Hi-Score *)
  1012.     PROCEDURE Score*;
  1013.         VAR 
  1014.             i: INTEGER;
  1015.             PL: Oberon.ParList;
  1016.             te: Texts.Text;
  1017.     BEGIN
  1018.         te:=TextFrames.Text("");
  1019.         Texts.WriteString(W, "Oberon-Mines Hall Of Fame !");Texts.WriteLn(W);
  1020.         Texts.WriteString(W, "________________________________________________");Texts.WriteLn(W);
  1021.         FOR i:=0 TO 2 DO
  1022.             IF i=0 THEN Texts.WriteString(W, "Beg.: ");
  1023.             ELSIF i=1 THEN Texts.WriteString(W, "Adv.: ");
  1024.             ELSE Texts.WriteString(W, "Exp.: ");END;
  1025.             Texts.WriteInt(W, HiScore[i].Time, 1);
  1026.             Texts.WriteString(W, " sec   ");
  1027.             Texts.WriteString(W, HiScore[i].Name);
  1028.             Texts.WriteLn(W);
  1029.         END;
  1030.         Texts.WriteLn(W);
  1031.         Texts.WriteString(W, "Current Username : ");
  1032.         Texts.WriteString(W, Name);
  1033.         Texts.WriteLn(W);
  1034.         Texts.Append(te, W.buf);
  1035.         Texts.Close(te, "Mines.HiScore.Text");
  1036.         te:=TextFrames.Text("");
  1037.         Texts.WriteString(W, "Mines.HiScore.Text");
  1038.         Texts.Append(te, W.buf);
  1039.         NEW(PL);PL:=Oberon.Par;
  1040.         PL.text:=te;PL.pos:=0;
  1041.         Oberon.Call("System.Open",PL,FALSE,i);            
  1042.     END Score;
  1043.     (* create new frame with new data *)
  1044.     PROCEDURE Open*;
  1045.         VAR
  1046.             x, y: INTEGER;
  1047.             f: Frame;
  1048.             v: MenuViewers.Viewer;
  1049.             tf: TextFrames.Frame;
  1050.             text: Texts.Text;
  1051.     BEGIN
  1052.         NEW(f);IF f=NIL THEN RETURN;END;
  1053.         NEW(f.d);IF f.d=NIL THEN RETURN;END;
  1054.         f.handle:=Handler;f.d.Aktiv:=TRUE;f.d.Quote:=16;
  1055.         f.LastModMsg:=TRUE;f.d.Pause:=FALSE;
  1056.         f.d.XKastenAnz:=256;f.d.YKastenAnz:=256;
  1057.         f.d.Mode:=-1;f.d.StartPlay:=FALSE;
  1058.         Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
  1059.         tf:=TextFrames.NewMenu("Mines", Menu);
  1060.         text:=TextFrames.Text("Mines.Menu.Text");
  1061.         IF text.len>5 THEN tf.text:=text;END;
  1062.         v:=MenuViewers.New(tf, f, TextFrames.menuH, x, y); 
  1063.     END Open;
  1064.     (* switch between color ans b/w mode *)
  1065.     PROCEDURE ColorMode*;
  1066.         VAR rpmsg: RePlotMsg;
  1067.     BEGIN
  1068.         Color:=~Color;
  1069.         rpmsg.All:=TRUE;
  1070.         Viewers.Broadcast(rpmsg);
  1071.         SaveHi(FALSE);
  1072.     END ColorMode;
  1073.     (* switches between task und mouse action time mode *)
  1074.     PROCEDURE TimeMode*;
  1075.     BEGIN
  1076.         UseTimeTask:=~UseTimeTask;
  1077.         SaveHi(FALSE);
  1078.     END TimeMode;
  1079.     (* start different types of the game *)
  1080.     PROCEDURE Beginner*;
  1081.     BEGIN
  1082.         ShortNewPar(8, 8, 15, 0);
  1083.     END Beginner;
  1084.     PROCEDURE Advanced*;
  1085.     BEGIN
  1086.         ShortNewPar(16, 16, 16, 1);
  1087.     END Advanced;
  1088.     PROCEDURE Expert*;
  1089.     BEGIN
  1090.         ShortNewPar(30, 16, 21, 2);
  1091.     END Expert;
  1092.     PROCEDURE Max*;
  1093.     BEGIN
  1094.         ShortNewPar(256, 256, 16, -1);
  1095.     END Max;
  1096.     PROCEDURE Start*;
  1097.     BEGIN
  1098.         ShortNewPar(8, 8, 16, -1);
  1099.     END Start;
  1100. BEGIN
  1101.     UsedFont:=Fonts.This("Syntax14.Scn.Fnt");
  1102.     Texts.OpenWriter(W);
  1103.     Texts.WriteString(W, "Oberon-Mines V1.31");
  1104.     Texts.WriteLn(W);
  1105.     Texts.WriteString(W, "(C) 1 Oct 94 by Ralf Degner");
  1106.     Texts.WriteLn(W);
  1107.     Texts.Append(Oberon.Log, W.buf);
  1108.     StartTime:=Input.Time();
  1109.     seed:=StartTime;
  1110.     TimeTaskRuns:=FALSE;
  1111.     Color:=FALSE;UseTimeTask:=TRUE;
  1112.     IF Oberon.User="" THEN
  1113.         Name:="AMIGA";
  1114.     ELSE
  1115.         COPY(Oberon.User, Name);
  1116.     END;
  1117.     Colors[0]:=Col1;Colors[1]:=Col2;Colors[2]:=Col3;Colors[3]:=Col4;
  1118.     Colors[4]:=Col5;Colors[5]:=Col6;Colors[6]:=Col7;Colors[7]:=Col8;
  1119.     LoadHi();
  1120.     IF UseTimeTask THEN
  1121.         StartTask();
  1122.     END;
  1123.     (* install patterns *)
  1124.     HappyData[1]:={5,6,7,8,9,10};
  1125.     HappyData[2]:={3,4,11,12};
  1126.     HappyData[3]:={2,13};
  1127.     HappyData[4]:={1,5,6,7,8,9,10,14};
  1128.     HappyData[5]:={1,4,11,14};
  1129.     HappyData[6]:={0,3,12,15};
  1130.     HappyData[7]:={0,7,8,15};
  1131.     HappyData[8]:={0,7,8,15};
  1132.     HappyData[9]:={0,15};
  1133.     HappyData[10]:={0,15};
  1134.     HappyData[11]:={0,15,5,6,9,10};
  1135.     HappyData[12]:={1,14,5,6,9,10};                
  1136.     HappyData[13]:={1,14};                
  1137.     HappyData[14]:={2,13};                
  1138.     HappyData[15]:={3,4,11,12};
  1139.     HappyData[16]:={5,6,7,8,9,10};
  1140.     HappyPat:=Display.NewPattern(HappyData, 16, 16);
  1141.     SadData:=HappyData;
  1142.     SadData[5]:={1,5,6,7,8,9,10,14};
  1143.     SadData[4]:={1,4,11,14};
  1144.     SadData[6]:={0,15};    
  1145.     SadPat:=Display.NewPattern(SadData, 16, 16);
  1146.     BackData[1]:={};
  1147.     BackData[2]:={5,6,7,8,9,10};
  1148.     BackData[3]:={3,4,5,6,7,8,9,10,11,12};
  1149.     BackData[4]:={2,3,4,5,6,7,8,9,10,11,12,13};
  1150.     BackData[5]:={2,3,4,5,6,7,8,9,10,11,12,13};
  1151.     BackData[6]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
  1152.     BackData[7]:={1,2,3,4,5,6,9,10,11,12,13,14};
  1153.     BackData[8]:={1,2,3,4,5,6,9,10,11,12,13,14};
  1154.     BackData[9]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
  1155.     BackData[10]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
  1156.     BackData[11]:={1,2,3,4,7,8,11,12,13,14};
  1157.     BackData[12]:={1,2,3,4,7,8,11,12,13,14};                
  1158.     BackData[13]:={2,3,4,5,6,7,8,9,10,11,12,13};                
  1159.     BackData[14]:={3,4,5,6,7,8,9,10,11,12};                
  1160.     BackData[15]:={5,6,7,8,9,10};
  1161.     BackData[16]:={};
  1162.     BackPat:=Display.NewPattern(BackData, 16, 16);
  1163.     GotItData:=HappyData;
  1164.     GotItData[12]:={1,4,5,6,7,8,9,10,11,14};
  1165.     GotItData[11]:={0,3,4,5,6,9,10,11,12,15};
  1166.     GotItData[10]:={0,2,4,5,6,9,10,11,13,15};
  1167.     GotItData[9]:={0,1,5,6,7,8,9,10,14,15};
  1168.     GotItPat:=Display.NewPattern(GotItData, 16, 16);
  1169.     PauseData:=SadData;
  1170.     PauseData[5]:={1,14};
  1171.     PauseData[4]:={1,4,5,6,7,8,9,10,11,14};
  1172.     PausePat:=Display.NewPattern(PauseData, 16, 16);
  1173.     (* Mine *)
  1174.     Data1[1]:={3,4,5,6,7,8};
  1175.     Data1[2]:={2,3,4,5,6,7,8,9};
  1176.     Data1[3]:={1,2,3,5,6,7,8,9,10};
  1177.     Data1[4]:={1,2,5,6,7,8,9,10};
  1178.     Data1[5]:={1,2,4,5,6,7,8,9,10};
  1179.     Data1[6]:={1,2,3,4,5,6,7,8,9,10};
  1180.     Data1[7]:={2,3,4,5,6,7,8,9};
  1181.     Data1[8]:={3,4,5,6,7,8};
  1182.     Data1[9]:={5,6};
  1183.     Data1[10]:={5};
  1184.     Data1[11]:={6,10};
  1185.     Data1[12]:={7,8,9};
  1186.     Pat[1]:=Display.NewPattern(Data1, 12, 12);
  1187.     (* No Mine *)
  1188.     Data2[1]:={0,11};
  1189.     Data2[2]:={1,10};
  1190.     Data2[3]:={2,9};
  1191.     Data2[4]:={3,8};
  1192.     Data2[5]:={4,7};
  1193.     Data2[6]:={5,6};
  1194.     Data2[7]:={5,6};
  1195.     Data2[8]:={4,7};
  1196.     Data2[9]:={3,8};
  1197.     Data2[10]:={2,9};
  1198.     Data2[11]:={1,10};
  1199.     Data2[12]:={0,11};
  1200.     Pat[2]:=Display.NewPattern(Data2, 12, 12);
  1201.     (* Flag *)
  1202.     Data3[1]:={};
  1203.     Data3[2]:={3};
  1204.     Data3[3]:={3};
  1205.     Data3[4]:={3};
  1206.     Data3[5]:={3};
  1207.     Data3[6]:={3};
  1208.     Data3[7]:={3,4,5};
  1209.     Data3[8]:={3,4,5,6,7};
  1210.     Data3[9]:={3,4,5,6,7,8,9};
  1211.     Data3[10]:={3,4,5,6,7};
  1212.     Data3[11]:={3,4,5};
  1213.     Data3[12]:={};
  1214.     Pat[3]:=Display.NewPattern(Data3, 12, 12);
  1215.     (* No Mine - No Color *)
  1216.     FOR Dummy:=1 TO 12 DO
  1217.         Data4[Dummy]:=Data1[Dummy]/Data2[Dummy];
  1218.     END;
  1219.     Pat[4]:=Display.NewPattern(Data4, 12, 12);
  1220. END Mines.
  1221.