home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / games / strategy / mines.lha / Mines.Mod (.txt) < prev    next >
Encoding:
Oberon Text  |  1994-09-27  |  37.2 KB  |  1,222 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
  495.             XMax,YMax: INTEGER;
  496.     BEGIN
  497.         XMax:=(f.W-SeitenPlatz*2) DIV KastenPlatz;
  498.         YMax:=(f.H-ObenPlatz-UntenPlatz) DIV KastenPlatz;
  499.         IF XMax<f.d.XKastenAnz THEN RETURN FALSE;END;
  500.         IF YMax<f.d.YKastenAnz THEN RETURN FALSE;END;
  501.         RETURN TRUE;
  502.     END TestRaster;
  503.     (* check if Raster fits to frame *)
  504.     PROCEDURE CheckRaster(f: Frame): BOOLEAN;
  505.         VAR
  506.             XMax,YMax: INTEGER;
  507.             Change, Aktiv: BOOLEAN;
  508.             XAnzNeu, YAnzNeu: INTEGER;
  509.     BEGIN
  510.         Change:=FALSE;Aktiv:=TRUE;
  511.         XMax:=(f.W-SeitenPlatz*2) DIV KastenPlatz;
  512.         YMax:=(f.H-ObenPlatz-UntenPlatz) DIV KastenPlatz;
  513.         IF XMax<MinKastenAnz THEN Aktiv:=FALSE;Change:=TRUE;END;
  514.         IF YMax<MinKastenAnz THEN Aktiv:=FALSE;Change:=TRUE;END;
  515.         IF XMax<f.d.XKastenAnz THEN
  516.             XAnzNeu:=XMax;Change:=TRUE;
  517.         ELSE
  518.             XAnzNeu:=f.d.XKastenAnz;
  519.         END;
  520.         IF YMax<f.d.YKastenAnz THEN
  521.             YAnzNeu:=YMax;Change:=TRUE;
  522.         ELSE
  523.             YAnzNeu:=f.d.YKastenAnz;
  524.         END;
  525.         IF Change THEN
  526.             IF Aktiv THEN
  527.                 f.d.XKastenAnz:=XAnzNeu;f.d.YKastenAnz:=YAnzNeu;
  528.                 f.d.Aktiv:=TRUE;
  529.             ELSE
  530.                 f.d.Aktiv:=FALSE;
  531.             END;
  532.             f.d.Mode:=-1;
  533.         END;
  534.         RETURN Change;
  535.     END CheckRaster;
  536.     (* check if field fits to frame; if not, creat new field *)
  537.     PROCEDURE CalcRaster (f: Frame): BOOLEAN;
  538.         VAR pnmsg: PlotNewMsg;
  539.     BEGIN
  540.         IF CheckRaster(f) THEN
  541.             pnmsg.d:=f.d;
  542.             IF f.d.Aktiv THEN
  543.                 NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
  544.             END;
  545.             f.d.StartPlay:=FALSE;
  546.             Viewers.Broadcast(pnmsg);
  547.             RETURN TRUE;
  548.         ELSE
  549.             RETURN FALSE;
  550.         END;
  551.     END CalcRaster;
  552.     (* search boxes with no mine on it *)
  553.     PROCEDURE SearchMore(d: Data; x, y: INTEGER);
  554.         VAR
  555.             Dummy: SHORTINT;
  556.             pkmsg: PlotKastenMsg;
  557.     BEGIN
  558.         IF (x=0) OR (y=0) OR (x>d.XKastenAnz) OR (y>d.YKastenAnz) THEN RETURN;END;
  559.         Dummy:=d.Feld[x, y];
  560.         IF (Dummy<0) OR (Dummy>9) THEN RETURN;END;
  561.         DEC (d.Count);
  562.         d.Feld[x, y]:=-Dummy;
  563.         pkmsg.d:=d;
  564.         pkmsg.x:=x;pkmsg.y:=y;
  565.         Viewers.Broadcast(pkmsg);
  566.         IF Dummy=1 THEN
  567.             SearchMore(d, x+1, y);SearchMore(d, x+1, y+1);
  568.             SearchMore(d, x,y+1);SearchMore(d, x-1, y+1);
  569.             SearchMore(d, x-1, y);SearchMore(d, x-1, y-1);
  570.             SearchMore(d, x, y-1);SearchMore(d, x+1, y-1);
  571.         END;
  572.     END SearchMore;
  573.     (* new HIScore ? *)
  574.     PROCEDURE CheckHiScore(d: Data);
  575.     BEGIN
  576.         IF d.Mode>-1 THEN
  577.             IF d.Time<HiScore[d.Mode].Time THEN
  578.                 Texts.WriteString(W, "New Hi-Score !!!");Texts.WriteLn(W);
  579.                 Texts.Append(Oberon.Log, W.buf);
  580.                 HiScore[d.Mode].Time:=d.Time;
  581.                 HiScore[d.Mode].Name:=Name;
  582.                 SaveHi(FALSE);
  583.             END;
  584.         END;
  585.     END CheckHiScore;
  586.     (* all Mines found *)
  587.     PROCEDURE GotIt(f: Frame);
  588.         VAR XPos, YPos: INTEGER;
  589.     BEGIN
  590.         YPos:=f.Y+f.H-ObenPlatz+4;
  591.         XPos:=(f.W DIV 2)-9+f.X;
  592.         Display.CopyPattern(black, GotItPat, XPos+1, YPos+1, Display.paint);
  593.         f.d.Mines:=0;DrawMinesToFind(f);
  594.     END GotIt;
  595.     (* switch field *)
  596.     PROCEDURE SwitchKasten(f: Frame; XKasten, YKasten: INTEGER; Color: BOOLEAN; col: INTEGER);
  597.         VAR
  598.             timsg: TimeMsg;
  599.             pkmsg: PlotKastenMsg;
  600.             Dummy: SHORTINT;
  601.     BEGIN
  602.         IF ~f.d.Aktiv THEN RETURN; END;
  603.         Dummy:=f.d.Feld[XKasten, YKasten];
  604.         IF (Dummy>0) & (Dummy<16) THEN
  605.             pkmsg.d:=f.d;
  606.             pkmsg.x:=XKasten;pkmsg.y:=YKasten;
  607.             IF Dummy=10 THEN
  608.                 f.d.Feld[XKasten, YKasten]:=-10;
  609.                 f.d.Aktiv:=FALSE;
  610.                 SwitchAll(f, Color, col);
  611.                 Viewers.Broadcast(pkmsg);
  612.             ELSE
  613.                 IF Dummy=1 THEN
  614.                     SearchMore(f.d, XKasten, YKasten);
  615.                 ELSE
  616.                     f.d.Feld[XKasten, YKasten]:=-Dummy;
  617.                     DEC(f.d.Count);
  618.                     Viewers.Broadcast(pkmsg);
  619.                 END;
  620.                 IF f.d.Count=0 THEN
  621.                     LastTime:=Input.Time()-1;
  622.                     timsg.id:=StartTime;
  623.                     timsg.Count:=0;
  624.                     Viewers.Broadcast(timsg);
  625.                     f.d.Aktiv:=FALSE;
  626.                     f.d.Time:=(Input.Time()-f.d.Time) DIV Input.TimeUnit;
  627.                     CheckHiScore(f.d);
  628.                 END;
  629.             END;
  630.         END;
  631.     END SwitchKasten;
  632.     (* react on mouse keys *)
  633.     PROCEDURE MouseKeys*(f: Frame; XKasten, YKasten: INTEGER; Key: SET; Color: BOOLEAN; col: INTEGER);
  634.         VAR
  635.             Dummy: SHORTINT;
  636.             pkmsg: PlotKastenMsg;
  637.     BEGIN
  638.         Dummy:=f.d.Feld[XKasten, YKasten];
  639.         pkmsg.d:=f.d;
  640.         pkmsg.x:=XKasten;pkmsg.y:=YKasten;
  641.         IF Key={2} THEN
  642.             IF ~f.d.StartPlay THEN
  643.                 f.d.StartPlay:=TRUE;
  644.                 f.d.Time:=Input.Time();
  645.             END;
  646.             SwitchKasten(f, XKasten, YKasten, Color, col);
  647.         ELSIF Key={0} THEN
  648.             IF Dummy>0 THEN
  649.                 IF Dummy<16 THEN
  650.                     f.d.Feld[XKasten, YKasten]:=Dummy+16;
  651.                     f.d.Mines:=f.d.Mines-1;
  652.                 ELSE
  653.                     f.d.Feld[XKasten, YKasten]:=Dummy-16;
  654.                     f.d.Mines:=f.d.Mines+1;
  655.                 END;
  656.                 Viewers.Broadcast(pkmsg);
  657.             END;
  658.         ELSIF Key={0,2} THEN
  659.             IF Dummy<0 THEN
  660.                 IF ~f.d.StartPlay THEN
  661.                     f.d.StartPlay:=TRUE;
  662.                     f.d.Time:=Input.Time();
  663.                 END;
  664.                 SwitchKasten(f, XKasten+1, YKasten, Color, col);
  665.                 SwitchKasten(f, XKasten+1, YKasten-1, Color, col);
  666.                 SwitchKasten(f, XKasten, YKasten-1, Color, col);
  667.                 SwitchKasten(f, XKasten-1, YKasten-1, Color, col);
  668.                 SwitchKasten(f, XKasten-1, YKasten, Color, col);
  669.                 SwitchKasten(f, XKasten-1, YKasten+1, Color, col);
  670.                 SwitchKasten(f, XKasten, YKasten+1, Color, col);
  671.                 SwitchKasten(f, XKasten+1, YKasten+1, Color, col);
  672.             END;
  673.         END;
  674.     END MouseKeys;
  675.     (* get selected frame *)    
  676.     PROCEDURE GetFrame(VAR f: Display.Frame): BOOLEAN;
  677.         VAR v: Viewers.Viewer;
  678.     BEGIN
  679.         IF Oberon.Par.frame=Oberon.Par.vwr.dsc THEN
  680.             IF (Oberon.Par.frame # NIL) THEN
  681.                 f:=Oberon.Par.frame.next;
  682.                 RETURN TRUE;
  683.             END;
  684.         ELSE
  685.             v:=Oberon.MarkedViewer();
  686.             IF (v.dsc # NIL) & (v.dsc.next # NIL) THEN
  687.                 f:=v.dsc.next;
  688.                 RETURN TRUE;
  689.             END
  690.         END;
  691.         RETURN FALSE;
  692.     END GetFrame;
  693.     (* do the pause *)
  694.     PROCEDURE DoPause(f: Frame);
  695.         VAR
  696.             nfmsg: NeuesFeldMsg;
  697.             rpmsg: RePlotMsg;
  698.             pnmsg: PlotNewMsg;
  699.     BEGIN
  700.         IF f.d.Pause THEN
  701.             IF TestRaster(f) OR PauseFlag THEN
  702.                 f.d.Pause:=FALSE;
  703.                 nfmsg.d:=f.d;nfmsg.Change:=FALSE;
  704.                 Viewers.Broadcast(nfmsg);
  705.                 IF nfmsg.Change THEN
  706.                     IF f.d.Aktiv THEN
  707.                         NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
  708.                     END;
  709.                     pnmsg.d:=f.d;
  710.                     Viewers.Broadcast(pnmsg);
  711.                     f.d.StartPlay:=FALSE;
  712.                 ELSE
  713.                     rpmsg.All:=FALSE;
  714.                     rpmsg.d:=f.d;
  715.                     f.d.Time:=Input.Time()-f.d.Time;
  716.                     Viewers.Broadcast(rpmsg);
  717.                 END;
  718.             ELSE
  719.                 Texts.WriteString(W, "Frame to small for old game !");
  720.                 Texts.WriteLn(W);
  721.                 Texts.Append(Oberon.Log, W.buf);
  722.                 PauseFlag:=TRUE;
  723.             END;
  724.         ELSE
  725.             f.d.Pause:=TRUE;
  726.             f.d.Time:=Input.Time()-f.d.Time;
  727.             rpmsg.d:=f.d;rpmsg.All:=FALSE;
  728.             Viewers.Broadcast(rpmsg);
  729.         END;
  730.     END DoPause;
  731.     (* set Pause mode *)
  732.     PROCEDURE Pause*;
  733.         VAR
  734.             f, g: Display.Frame;
  735.     BEGIN
  736.         IF GetFrame(g) THEN
  737.             f:=g;
  738.             WITH f: Frame DO
  739.                 IF f.d.Aktiv THEN DoPause(f);END;
  740.             ELSE
  741.             END;
  742.         END;
  743.     END Pause;
  744.     (* do mouseaction *)
  745.     PROCEDURE DoMou(f: Frame; X, Y: INTEGER; Key, FirstKey: SET);
  746.         VAR
  747.             XKasten, YKasten: INTEGER;
  748.             XStore, YStore: INTEGER;
  749.             Dummy: SHORTINT;
  750.             pnmsg: PlotNewMsg;
  751.             nfmsg: NeuesFeldMsg;
  752.     BEGIN
  753.         IF f.d.Pause THEN RETURN; END;
  754.         XStore:=X;YStore:=Y;
  755.         X:=X-f.SeitenOffset;Y:=Y-f.UntenOffset;
  756.         IF X<0 THEN RETURN;END;
  757.         IF Y<0 THEN RETURN;END;
  758.         XKasten:=X DIV KastenPlatz +1;
  759.         YKasten:=Y DIV KastenPlatz +1;
  760.         IF (XKasten<=f.d.XKastenAnz) & (YKasten<=f.d.YKastenAnz) THEN
  761.             IF ~f.d.Aktiv THEN RETURN;END;
  762.             IF (X MOD KastenPlatz)=0 THEN RETURN;END;
  763.             IF (Y MOD KastenPlatz)=0 THEN RETURN;END;
  764.             Dummy:=f.d.Feld[XKasten, YKasten];
  765.             IF Key={1} THEN
  766.                 IF Dummy>0 THEN
  767.                     IF Dummy<16 THEN
  768.                         Oberon.RemoveMarks(f.SeitenOffset, f.UntenOffset, f.W, f.H);
  769.                         DrawCharInv(f, "?", XKasten, YKasten);
  770.                     END;
  771.                 END;
  772.             ELSE
  773.                 MouseKeys(f, XKasten, YKasten, Key, Color, Display.white);
  774.             END;
  775.             IF ~UseTimeTask THEN DrawTime(f);END;
  776.             IF f.d.Count=0 THEN
  777.                 GotIt(f);
  778.             END;
  779.         ELSE
  780.             IF (YStore>f.Y+f.H-ObenPlatz+3) & (YStore<f.Y+f.H-3) THEN
  781.                 IF (ABS(XStore-f.X-(f.W DIV 2))<10) THEN
  782.                     IF Key={2} THEN
  783.                         nfmsg.d:=f.d;
  784.                         f.d.Aktiv:=TRUE;
  785.                         Viewers.Broadcast(nfmsg);
  786.                         IF f.d.Aktiv THEN
  787.                             NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
  788.                         END;
  789.                         pnmsg.d:=f.d;
  790.                         f.d.StartPlay:=FALSE;
  791.                         Viewers.Broadcast(pnmsg);
  792.                     END;
  793.                 END;
  794.             END;
  795.         END;
  796.     END DoMou;
  797.     (* set mousecursor and call DoMouse if button is pressed *)
  798.     PROCEDURE TrackMouse*(f: Frame; X, Y: INTEGER; k: SET; Mou: PROCEDURE(f: Frame; X, Y: INTEGER; K, F: SET));
  799.         VAR
  800.             XPos, YPos: INTEGER;
  801.             NewKeys, FirstKey: SET;
  802.     BEGIN
  803.         XPos:=X;YPos:=Y;
  804.         FirstKey:=k;
  805.         REPEAT
  806.             Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, X, Y);
  807.             Input.Mouse(NewKeys, X, Y);
  808.             k:=k+NewKeys;
  809.         UNTIL NewKeys={};
  810.         IF k#{} THEN Mou(f, XPos, YPos, k, FirstKey);END;
  811.     END TrackMouse;
  812.     (* the Handler of the Miner-Frames*)
  813.     PROCEDURE Handler(f: Display.Frame; VAR m: Display.FrameMsg);
  814.         VAR
  815.             self: Frame;
  816.             dumY, dumH: INTEGER;
  817.     BEGIN
  818.         self:=f(Frame);
  819.         WITH m: Oberon.InputMsg DO
  820.             IF m.id=Oberon.track THEN TrackMouse(self, m.X, m.Y, m.keys, DoMou);END;
  821.         | m: Oberon.CopyMsg DO
  822.             m.F:=CopyMe(self);
  823.         | m: MenuViewers.ModifyMsg DO
  824.             PauseFlag:=FALSE;
  825.             IF m.H=0 THEN
  826.                 self.LastModMsg:=TRUE;
  827.                 RETURN;
  828.             END;
  829.             IF self.d.Pause OR ~self.d.Aktiv THEN      (* game is paused or not Aktiv *)
  830.                 f.Y:=m.Y;f.H:=m.H;
  831.                 ClearFrame(self, self.d.Aktiv);
  832.             ELSIF self.d.Aktiv THEN                         (* if Aktiv *)
  833.                 IF m.id=MenuViewers.extend THEN    (* extended *)
  834.                     IF self.LastModMsg THEN               (* extended from 0, CalcRaster new *)
  835.                         f.Y:=m.Y;f.H:=m.H;
  836.                         ClearFrame(self, TRUE);
  837.                         IF ~CalcRaster(self) THEN          (* if old Raster, then redraw *)
  838.                             PlotAll(self);
  839.                         END;
  840.                         IF UseTimeTask THEN StartTask();END;
  841.                     ELSE
  842.                         IF m.dY=0 THEN                        (* extended at the bootom, clear new area *)
  843.                             Oberon.RemoveMarks(self.X, m.Y, self.W, m.H-self.H);
  844.                             Display.ReplConst(Display.black, self.X, m.Y, self.W, m.H-self.H, Display.replace);
  845.                         ELSE                                       (* extended at the top, copy and clear new area *)
  846.                             Oberon.RemoveMarks(self.X, self.Y, self.W, self.H+m.dY);
  847.                             Display.CopyBlock(self.X, self.Y, self.W, self.H, self.X, self.Y+m.dY, Display.replace);
  848.                             Display.ReplConst(Display.black, self.X, m.Y, self.W, m.H-self.H, Display.replace);
  849.                             self.UntenOffset:=self.UntenOffset+m.dY;
  850.                         END;
  851.                     END;
  852.                 ELSIF m.id=MenuViewers.reduce THEN    (* reduced *)
  853.                     dumY:=f.Y;dumH:=f.H;
  854.                     f.Y:=m.Y;f.H:=m.H;
  855.                     IF TestRaster(self) THEN
  856.                         IF m.dY#0 THEN             (* if top moved, copy *)
  857.                             Oberon.RemoveMarks(self.X, m.Y, self.W, m.H-m.dY);
  858.                             Display.CopyBlock(self.X, dumY+dumH-m.H, self.W, m.H, self.X, m.Y, Display.replace);
  859.                             self.UntenOffset:=self.UntenOffset-m.dY;
  860.                         END;
  861.                     ELSE
  862.                         DoPause(self);
  863.                     END;
  864.                 END;
  865.             END;
  866.             self.LastModMsg:=FALSE;
  867.         | m: MinerMsg DO
  868.             WITH m: RePlotMsg DO
  869.                     IF m.All OR (m.d=self.d) THEN
  870.                         ClearFrame(self, self.d.Aktiv);
  871.                         IF self.d.Aktiv & ~self.d.Pause THEN
  872.                             PlotAll(self);
  873.                         END;
  874.                     END;
  875.             | m: TimeMsg DO
  876.                 IF m.id=StartTime THEN
  877.                     IF self.d.Aktiv & ~self.d.Pause & self.d.StartPlay  THEN
  878.                         DrawTime(self);
  879.                     END;
  880.                     INC(m.Count);
  881.                 END;
  882.             ELSE
  883.                 IF m.d=self.d THEN
  884.                     WITH m: PlotNewMsg DO            (* Message for new Raster *)
  885.                         IF self.d.Aktiv THEN
  886.                             IF ~CalcRaster(self) THEN     (* Raster OK for this Frame ? *)
  887.                                 ClearFrame(self, TRUE);
  888.                                 PlotAll(self);
  889.                             END;
  890.                         ELSE
  891.                             ClearFrame(self, FALSE);
  892.                         END;
  893.                     | m: PlotKastenMsg DO                (* PLot one box *)
  894.                         Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
  895.                         DrawKasten(self, m.x, m.y, Color, Display.white);
  896.                         IF self.d.Feld[m.x, m.y]>0 THEN
  897.                             DrawMinesToFind(self);
  898.                         END;
  899.                         IF ~self.d.Aktiv THEN PlotSmily(self, FALSE);END;
  900.                     | m: NeuesFeldMsg DO                (* Check if new W & H are fitting to frame *) 
  901.                         IF CheckRaster(self) THEN
  902.                             m.Change:=TRUE;
  903.                         END;
  904.                     ELSE
  905.                     END;
  906.                 END;
  907.             END;
  908.         ELSE
  909.         END;
  910.     END Handler;
  911.     (* get parameters *)
  912.     PROCEDURE GetPar*(VAR Quote, X, Y, Mode: INTEGER);
  913.         VAR
  914.             S: Texts.Scanner;
  915.             text: Texts.Text;
  916.             Dummy, StoreQuote: INTEGER;
  917.             beg, end, time: LONGINT;
  918.     BEGIN
  919.         StoreQuote:=Quote;
  920.         Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
  921.         Texts.Scan(S);
  922.         IF S.class=Texts.Char THEN
  923.             IF S.c="^" THEN
  924.                 Oberon.GetSelection(text, beg, end, time);
  925.                 IF time=-1 THEN RETURN; END;
  926.                 Texts.OpenScanner(S, text, beg);
  927.                 Texts.Scan(S);
  928.             ELSE
  929.                 RETURN;
  930.             END;
  931.         END;
  932.         IF S.class=Texts.Int THEN
  933.             IF (S.i>0) & (S.i<90) THEN;
  934.                 Quote:=SHORT(S.i);
  935.                 IF (Mode=-1) OR (X#256) THEN
  936.                     Texts.Scan(S);
  937.                     IF S.class=Texts.Int THEN;
  938.                         Dummy:=SHORT(S.i);
  939.                         Texts.Scan(S);
  940.                         IF S.class=Texts.Int THEN
  941.                             IF (Dummy<6) OR (Dummy>127) THEN
  942.                                 X:=8;
  943.                             ELSE
  944.                                 X:=Dummy;
  945.                             END;
  946.                             IF (S.i<6) OR (S.i>127) THEN
  947.                                 Y:=8;
  948.                             ELSE
  949.                                 Y:=SHORT(S.i);
  950.                             END;
  951.                         END;
  952.                     END;
  953.                 ELSE
  954.                     IF Quote#StoreQuote THEN Mode:=-1; END;
  955.                 END;
  956.             END;
  957.         END;
  958.     END GetPar;
  959.     (* set frame and parameters *)    
  960.     PROCEDURE ShortNewPar(X, Y, Quote, Mode: INTEGER);
  961.         VAR
  962.             f, g: Display.Frame;
  963.             nfmsg: NeuesFeldMsg;
  964.             pnmsg: PlotNewMsg;
  965.     BEGIN
  966.         IF GetFrame(g) THEN
  967.             f:=g;
  968.             WITH f: Frame DO
  969.                 GetPar(Quote, X, Y, Mode);
  970.                 f.d.Quote:=Quote;f.d.Mode:=Mode;
  971.                 f.d.XKastenAnz:=X;f.d.YKastenAnz:=Y;
  972.                 f.d.Aktiv:=TRUE;f.d.Pause:=FALSE;
  973.                 nfmsg.d:=f.d;
  974.                 Viewers.Broadcast(nfmsg);
  975.                 IF f.d.Aktiv THEN
  976.                     NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
  977.                 END;
  978.                 pnmsg.d:=f.d;
  979.                 f.d.StartPlay:=FALSE;
  980.                 Viewers.Broadcast(pnmsg);
  981.             ELSE
  982.             END;
  983.         END;
  984.     END ShortNewPar;
  985.     (* set new username *)
  986.     PROCEDURE SetUser*;
  987.         VAR
  988.             S: Texts.Scanner;
  989.             text: Texts.Text;
  990.             beg, end, time: LONGINT;
  991.     BEGIN
  992.         Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
  993.         Texts.Scan(S);
  994.         IF S.class=Texts.Char THEN
  995.             IF S.c="^" THEN
  996.                 Oberon.GetSelection(text, beg, end, time);
  997.                 IF time=-1 THEN RETURN; END;
  998.                 Texts.OpenScanner(S, text, beg);
  999.                 Texts.Scan(S);
  1000.             ELSE
  1001.                 RETURN;
  1002.             END;
  1003.         END;
  1004.         IF S.class=Texts.Name THEN
  1005.             COPY(S.s, Name);
  1006.         END;
  1007.         Texts.WriteString(W, "Current Username : ");
  1008.         Texts.WriteString(W, Name);
  1009.         Texts.WriteLn(W);
  1010.         Texts.Append(Oberon.Log, W.buf);    
  1011.     END SetUser;
  1012.     (* print Hi-Score *)
  1013.     PROCEDURE Score*;
  1014.         VAR 
  1015.             i: INTEGER;
  1016.             PL: Oberon.ParList;
  1017.             te: Texts.Text;
  1018.     BEGIN
  1019.         te:=TextFrames.Text("");
  1020.         Texts.WriteString(W, "Oberon-Mines Hall Of Fame !");Texts.WriteLn(W);
  1021.         Texts.WriteString(W, "________________________________________________");Texts.WriteLn(W);
  1022.         FOR i:=0 TO 2 DO
  1023.             IF i=0 THEN Texts.WriteString(W, "Beg.: ");
  1024.             ELSIF i=1 THEN Texts.WriteString(W, "Adv.: ");
  1025.             ELSE Texts.WriteString(W, "Exp.: ");END;
  1026.             Texts.WriteInt(W, HiScore[i].Time, 1);
  1027.             Texts.WriteString(W, " sec   ");
  1028.             Texts.WriteString(W, HiScore[i].Name);
  1029.             Texts.WriteLn(W);
  1030.         END;
  1031.         Texts.WriteLn(W);
  1032.         Texts.WriteString(W, "Current Username : ");
  1033.         Texts.WriteString(W, Name);
  1034.         Texts.WriteLn(W);
  1035.         Texts.Append(te, W.buf);
  1036.         Texts.Close(te, "Mines.HiScore.Text");
  1037.         te:=TextFrames.Text("");
  1038.         Texts.WriteString(W, "Mines.HiScore.Text");
  1039.         Texts.Append(te, W.buf);
  1040.         NEW(PL);PL:=Oberon.Par;
  1041.         PL.text:=te;PL.pos:=0;
  1042.         Oberon.Call("System.Open",PL,FALSE,i);            
  1043.     END Score;
  1044.     (* create new frame with new data *)
  1045.     PROCEDURE Open*;
  1046.         VAR
  1047.             x, y: INTEGER;
  1048.             f: Frame;
  1049.             v: MenuViewers.Viewer;
  1050.             tf: TextFrames.Frame;
  1051.             text: Texts.Text;
  1052.     BEGIN
  1053.         NEW(f);IF f=NIL THEN RETURN;END;
  1054.         NEW(f.d);IF f.d=NIL THEN RETURN;END;
  1055.         f.handle:=Handler;f.d.Aktiv:=TRUE;f.d.Quote:=16;
  1056.         f.LastModMsg:=TRUE;f.d.Pause:=FALSE;
  1057.         f.d.XKastenAnz:=256;f.d.YKastenAnz:=256;
  1058.         f.d.Mode:=-1;f.d.StartPlay:=FALSE;
  1059.         Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
  1060.         tf:=TextFrames.NewMenu("Mines", Menu);
  1061.         text:=TextFrames.Text("Mines.Menu.Text");
  1062.         IF text.len>5 THEN tf.text:=text;END;
  1063.         v:=MenuViewers.New(tf, f, TextFrames.menuH, x, y); 
  1064.     END Open;
  1065.     (* switch between color ans b/w mode *)
  1066.     PROCEDURE ColorMode*;
  1067.         VAR rpmsg: RePlotMsg;
  1068.     BEGIN
  1069.         Color:=~Color;
  1070.         rpmsg.All:=TRUE;
  1071.         Viewers.Broadcast(rpmsg);
  1072.         SaveHi(FALSE);
  1073.     END ColorMode;
  1074.     (* switches between task und mouse action time mode *)
  1075.     PROCEDURE TimeMode*;
  1076.     BEGIN
  1077.         UseTimeTask:=~UseTimeTask;
  1078.         SaveHi(FALSE);
  1079.     END TimeMode;
  1080.     (* start different types of the game *)
  1081.     PROCEDURE Beginner*;
  1082.     BEGIN
  1083.         ShortNewPar(8, 8, 15, 0);
  1084.     END Beginner;
  1085.     PROCEDURE Advanced*;
  1086.     BEGIN
  1087.         ShortNewPar(16, 16, 16, 1);
  1088.     END Advanced;
  1089.     PROCEDURE Expert*;
  1090.     BEGIN
  1091.         ShortNewPar(30, 16, 21, 2);
  1092.     END Expert;
  1093.     PROCEDURE Max*;
  1094.     BEGIN
  1095.         ShortNewPar(256, 256, 16, -1);
  1096.     END Max;
  1097.     PROCEDURE Start*;
  1098.     BEGIN
  1099.         ShortNewPar(8, 8, 16, -1);
  1100.     END Start;
  1101. BEGIN
  1102.     UsedFont:=Fonts.This("Syntax14.Scn.Fnt");
  1103.     Texts.OpenWriter(W);
  1104.     Texts.WriteString(W, "Oberon-Mines V1.31");
  1105.     Texts.WriteLn(W);
  1106.     Texts.WriteString(W, "(C) 1 Oct 94 by Ralf Degner");
  1107.     Texts.WriteLn(W);
  1108.     Texts.Append(Oberon.Log, W.buf);
  1109.     StartTime:=Input.Time();
  1110.     seed:=StartTime;
  1111.     TimeTaskRuns:=FALSE;
  1112.     Color:=FALSE;UseTimeTask:=TRUE;
  1113.     IF Oberon.User="" THEN
  1114.         Name:="AMIGA";
  1115.     ELSE
  1116.         COPY(Oberon.User, Name);
  1117.     END;
  1118.     Colors[0]:=Col1;Colors[1]:=Col2;Colors[2]:=Col3;Colors[3]:=Col4;
  1119.     Colors[4]:=Col5;Colors[5]:=Col6;Colors[6]:=Col7;Colors[7]:=Col8;
  1120.     LoadHi();
  1121.     IF UseTimeTask THEN
  1122.         StartTask();
  1123.     END;
  1124.     (* install patterns *)
  1125.     HappyData[1]:={5,6,7,8,9,10};
  1126.     HappyData[2]:={3,4,11,12};
  1127.     HappyData[3]:={2,13};
  1128.     HappyData[4]:={1,5,6,7,8,9,10,14};
  1129.     HappyData[5]:={1,4,11,14};
  1130.     HappyData[6]:={0,3,12,15};
  1131.     HappyData[7]:={0,7,8,15};
  1132.     HappyData[8]:={0,7,8,15};
  1133.     HappyData[9]:={0,15};
  1134.     HappyData[10]:={0,15};
  1135.     HappyData[11]:={0,15,5,6,9,10};
  1136.     HappyData[12]:={1,14,5,6,9,10};                
  1137.     HappyData[13]:={1,14};                
  1138.     HappyData[14]:={2,13};                
  1139.     HappyData[15]:={3,4,11,12};
  1140.     HappyData[16]:={5,6,7,8,9,10};
  1141.     HappyPat:=Display.NewPattern(HappyData, 16, 16);
  1142.     SadData:=HappyData;
  1143.     SadData[5]:={1,5,6,7,8,9,10,14};
  1144.     SadData[4]:={1,4,11,14};
  1145.     SadData[6]:={0,15};    
  1146.     SadPat:=Display.NewPattern(SadData, 16, 16);
  1147.     BackData[1]:={};
  1148.     BackData[2]:={5,6,7,8,9,10};
  1149.     BackData[3]:={3,4,5,6,7,8,9,10,11,12};
  1150.     BackData[4]:={2,3,4,5,6,7,8,9,10,11,12,13};
  1151.     BackData[5]:={2,3,4,5,6,7,8,9,10,11,12,13};
  1152.     BackData[6]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
  1153.     BackData[7]:={1,2,3,4,5,6,9,10,11,12,13,14};
  1154.     BackData[8]:={1,2,3,4,5,6,9,10,11,12,13,14};
  1155.     BackData[9]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
  1156.     BackData[10]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
  1157.     BackData[11]:={1,2,3,4,7,8,11,12,13,14};
  1158.     BackData[12]:={1,2,3,4,7,8,11,12,13,14};                
  1159.     BackData[13]:={2,3,4,5,6,7,8,9,10,11,12,13};                
  1160.     BackData[14]:={3,4,5,6,7,8,9,10,11,12};                
  1161.     BackData[15]:={5,6,7,8,9,10};
  1162.     BackData[16]:={};
  1163.     BackPat:=Display.NewPattern(BackData, 16, 16);
  1164.     GotItData:=HappyData;
  1165.     GotItData[12]:={1,4,5,6,7,8,9,10,11,14};
  1166.     GotItData[11]:={0,3,4,5,6,9,10,11,12,15};
  1167.     GotItData[10]:={0,2,4,5,6,9,10,11,13,15};
  1168.     GotItData[9]:={0,1,5,6,7,8,9,10,14,15};
  1169.     GotItPat:=Display.NewPattern(GotItData, 16, 16);
  1170.     PauseData:=SadData;
  1171.     PauseData[5]:={1,14};
  1172.     PauseData[4]:={1,4,5,6,7,8,9,10,11,14};
  1173.     PausePat:=Display.NewPattern(PauseData, 16, 16);
  1174.     (* Mine *)
  1175.     Data1[1]:={3,4,5,6,7,8};
  1176.     Data1[2]:={2,3,4,5,6,7,8,9};
  1177.     Data1[3]:={1,2,3,5,6,7,8,9,10};
  1178.     Data1[4]:={1,2,5,6,7,8,9,10};
  1179.     Data1[5]:={1,2,4,5,6,7,8,9,10};
  1180.     Data1[6]:={1,2,3,4,5,6,7,8,9,10};
  1181.     Data1[7]:={2,3,4,5,6,7,8,9};
  1182.     Data1[8]:={3,4,5,6,7,8};
  1183.     Data1[9]:={5,6};
  1184.     Data1[10]:={5};
  1185.     Data1[11]:={6,10};
  1186.     Data1[12]:={7,8,9};
  1187.     Pat[1]:=Display.NewPattern(Data1, 12, 12);
  1188.     (* No Mine *)
  1189.     Data2[1]:={0,11};
  1190.     Data2[2]:={1,10};
  1191.     Data2[3]:={2,9};
  1192.     Data2[4]:={3,8};
  1193.     Data2[5]:={4,7};
  1194.     Data2[6]:={5,6};
  1195.     Data2[7]:={5,6};
  1196.     Data2[8]:={4,7};
  1197.     Data2[9]:={3,8};
  1198.     Data2[10]:={2,9};
  1199.     Data2[11]:={1,10};
  1200.     Data2[12]:={0,11};
  1201.     Pat[2]:=Display.NewPattern(Data2, 12, 12);
  1202.     (* Flag *)
  1203.     Data3[1]:={};
  1204.     Data3[2]:={3};
  1205.     Data3[3]:={3};
  1206.     Data3[4]:={3};
  1207.     Data3[5]:={3};
  1208.     Data3[6]:={3};
  1209.     Data3[7]:={3,4,5};
  1210.     Data3[8]:={3,4,5,6,7};
  1211.     Data3[9]:={3,4,5,6,7,8,9};
  1212.     Data3[10]:={3,4,5,6,7};
  1213.     Data3[11]:={3,4,5};
  1214.     Data3[12]:={};
  1215.     Pat[3]:=Display.NewPattern(Data3, 12, 12);
  1216.     (* No Mine - No Color *)
  1217.     FOR Dummy:=1 TO 12 DO
  1218.         Data4[Dummy]:=Data1[Dummy]/Data2[Dummy];
  1219.     END;
  1220.     Pat[4]:=Display.NewPattern(Data4, 12, 12);
  1221. END Mines.
  1222.