Syntax10.Scn.Fnt Syntax10b.Scn.Fnt FoldElems Syntax10.Scn.Fnt (* standard colors *) Syntax10.Scn.Fnt (* the colors of Mines for Windows *) (*black=Display.white; red=1; yellow=10; lightgray=11; midgray=12; darkgray=14; Col1=3; Col2=5; Col3=red; Col4=6; Col5=4; Col6=8; Col7=7; Col8=black;*) MODULE Mines; (* Oberon-Mines V1.31 (C) 1 Oct 94 by Ralf Degner *) IMPORT Oberon, Texts, Display, MenuViewers, TextFrames, Input, Fonts, Viewers, SYSTEM, Files; CONST (* the colors of Mines with Mines.Pal *) black=Display.white; red=1; yellow=4; lightgray=12; midgray=13; darkgray=14; Col1=3; Col2=2; Col3=red; Col4=9; Col5=7; Col6=5; Col7=6; Col8=black; (*MS-Windows Colors*) Menu = "System.Close System.Copy System.Grow Mines.Pause Mines.Beginner Mines.Advanced Mines.Expert Mines.Max Mines.Score"; KastenBreite=16;ObenPlatz=25; UntenPlatz=4;SeitenPlatz=4; KastenPlatz*=KastenBreite+1;KB=KastenBreite; MinKastenAnz=7;CharBreite=8; TYPE FeldPtr* = POINTER TO ARRAY OF ARRAY OF SHORTINT; String = ARRAY 32 OF CHAR; HiScoreType = RECORD Name: String; Time: LONGINT; END; HiScoreArrayType = ARRAY 3 OF HiScoreType; Data* = POINTER TO DataDesc; DataDesc* = RECORD XKastenAnz*,YKastenAnz*: INTEGER; Aktiv*, Pause*, StartPlay*: BOOLEAN; Feld*: FeldPtr; Time*, Count*, Mines*: LONGINT; Quote*, Mode*: INTEGER; END; Frame* = POINTER TO FrameDesc; FrameDesc* = RECORD(Display.FrameDesc) SeitenOffset*, UntenOffset*: INTEGER; LastModMsg: BOOLEAN; d*: Data; END; MinerMsg = RECORD(Display.FrameMsg) d*: Data; END; PlotNewMsg = RECORD(MinerMsg) END; PlotKastenMsg* = RECORD(MinerMsg) x*, y*: INTEGER; END; NeuesFeldMsg = RECORD(MinerMsg) Change: BOOLEAN; END; RePlotMsg = RECORD(MinerMsg) All: BOOLEAN; END; TimeMsg = RECORD(MinerMsg) id: LONGINT; Count: INTEGER; END; UsedFont: Fonts.Font; W: Texts.Writer; TimeTask: Oberon.Task; seed, StartTime, LastTime: LONGINT; HiScore: HiScoreArrayType; Name: String; ScoreFile: Files.File; ScoreRider: Files.Rider; Color, UseTimeTask, TimeTaskRuns, PauseFlag: BOOLEAN; Colors: ARRAY 8 OF INTEGER; Dummy: INTEGER; (* data for patterns *) HappyData, SadData, BackData, GotItData, PauseData: ARRAY 17 OF SET; HappyPat, SadPat, BackPat, GotItPat, PausePat: LONGINT; Data1, Data2, Data3, Data4: ARRAY 13 OF SET; Pat: ARRAY 5 OF LONGINT; (* clear HiScore *) PROCEDURE ClearHi; VAR Dummy: INTEGER; BEGIN FOR Dummy:=0 TO 2 DO HiScore[Dummy].Time:=999999; HiScore[Dummy].Name:="Amiga"; END; END ClearHi; (* store HiScore *) PROCEDURE SaveHi(Register: BOOLEAN); VAR Dum: INTEGER; BEGIN Files.Set(ScoreRider, ScoreFile, 0); Files.WriteBool(ScoreRider, Color); Files.WriteBool(ScoreRider, UseTimeTask); FOR Dum:=0 TO 2 DO Files.WriteLInt(ScoreRider, HiScore[Dum].Time); Files.WriteBytes(ScoreRider, HiScore[Dum].Name, 32); END; IF Register THEN Files.Register(ScoreFile); ELSE Files.Close(ScoreFile); END; END SaveHi; (* load HiScore *) PROCEDURE LoadHi; VAR Dum: INTEGER; BEGIN ClearHi(); ScoreFile:=Files.Old("Mines.Score"); IF ScoreFile=NIL THEN ScoreFile:=Files.New("Mines.Score"); SaveHi(TRUE); ELSE Files.Set(ScoreRider, ScoreFile, 0); Files.ReadBool(ScoreRider, Color); Files.ReadBool(ScoreRider, UseTimeTask); FOR Dum:=0 TO 2 DO Files.ReadLInt(ScoreRider, HiScore[Dum].Time); Files.ReadBytes(ScoreRider, HiScore[Dum].Name, 32); END; END; END LoadHi; (* produces random numbers *) PROCEDURE Random(Ein: INTEGER):INTEGER; VAR Max, Wert: INTEGER; Gerade: BOOLEAN; BEGIN IF (Ein MOD 2)=0 THEN Max:=Ein+1; Gerade:=TRUE; ELSE Max:=Ein; Gerade:=FALSE; END; seed:=SYSTEM.ROT(ASH(Input.Time(), -1)+ASH(seed, -1), 13); seed:=SYSTEM.ROT(seed, seed MOD 32); seed:=SYSTEM.ROT(2147483647+ASH(seed, -1), 13); seed:=SYSTEM.ROT(seed, seed DIV 01000000H); Wert:=SHORT(seed MOD Max); IF Gerade THEN IF Wert=Ein THEN RETURN Random(Ein); END; END; RETURN Wert; END Random; (* stop the TimeTask *) PROCEDURE StopTask*; BEGIN IF TimeTaskRuns THEN Oberon.Remove(TimeTask); TimeTaskRuns:=FALSE; END; END StopTask; (* the task, that sends every second a TimeMsg *) PROCEDURE TheTimeTask; VAR timsg: TimeMsg; BEGIN IF Input.Time()>LastTime THEN LastTime:=LastTime+Input.TimeUnit; timsg.id:=StartTime; timsg.Count:=0; Viewers.Broadcast(timsg); IF timsg.Count=0 THEN StopTask();END; END; END TheTimeTask; (* start the TimeTask *) PROCEDURE StartTask; BEGIN IF ~TimeTaskRuns THEN NEW(TimeTask); TimeTask.safe:=FALSE; TimeTask.handle:=TheTimeTask; Oberon.Install(TimeTask); LastTime:=Input.Time(); TimeTaskRuns:=TRUE; END; END StartTask; (* draw box at top of the field *) PROCEDURE PlotSmily(f: Frame; Smile: BOOLEAN); VAR XPos, YPos, Col: INTEGER; BEGIN IF f.H>ObenPlatz THEN IF f.W>30 THEN YPos:=f.Y+f.H-ObenPlatz+3; XPos:=f.W DIV 2-10+f.X; IF Color THEN Display.ReplConst(lightgray, XPos, YPos, 20, 20, Display.replace); Display.ReplConst(darkgray, XPos+1, YPos, 19, 19, Display.replace); Display.ReplConst(midgray, XPos+1, YPos+1, 18, 18, Display.replace); Display.CopyPattern(yellow, BackPat, XPos+2, YPos+2, Display.paint); Col:=black; ELSE Display.ReplConst(Display.white, XPos, YPos, 20, 20, Display.replace); Display.ReplConst(Display.black, XPos+1, YPos+1, 18, 18, Display.replace); Col:=Display.white; END; IF f.d.Pause THEN Display.CopyPattern(Col, PausePat, XPos+2, YPos+2, Display.paint); ELSE IF Smile THEN Display.CopyPattern(Col, HappyPat, XPos+2, YPos+2, Display.paint); ELSE Display.CopyPattern(Col, SadPat, XPos+2, YPos+2, Display.paint); END; END; END; END; END PlotSmily; (* clear a frame *) PROCEDURE ClearFrame(f: Frame; Smile: BOOLEAN); BEGIN Oberon.RemoveMarks(f.X, f.Y, f.W, f.H); Display.ReplConst(Display.black, f.X, f.Y, f.W, f.H, Display.replace); f.SeitenOffset:=(f.W-f.d.XKastenAnz*KastenPlatz) DIV 2 +f.X; f.UntenOffset:=f.Y+f.H-ObenPlatz-f.d.YKastenAnz*KastenPlatz; PlotSmily(f, Smile); END ClearFrame; (* copy frame with same data *) PROCEDURE CopyMe(f: Frame): Frame; VAR nf: Frame; BEGIN NEW(nf);IF nf=NIL THEN RETURN NIL;END; nf.handle:=f.handle; nf.d:=f.d;nf.LastModMsg:=TRUE; RETURN nf; END CopyMe; (* clear a box *) PROCEDURE ClearKasten(f: Frame; x, y: INTEGER; Color: BOOLEAN); VAR dumx, dumy: INTEGER; BEGIN dumx:=f.SeitenOffset+x*KastenPlatz-KastenBreite; dumy:=f.UntenOffset+y*KastenPlatz-KastenBreite; IF Color THEN Display.ReplConst(darkgray, dumx, dumy, KB, KB, Display.replace); Display.ReplConst(lightgray, dumx+1, dumy, KB-1, KB-1, Display.replace); Display.ReplConst(midgray, dumx+1, dumy+1, KB-2, KB-2, Display.replace); ELSE Display.ReplConst(Display.black, dumx, dumy, KB, KB, Display.replace); END; END ClearKasten; (* draw not selected box *) PROCEDURE BlockKasten(f: Frame; x, y: INTEGER; Color: BOOLEAN; col: INTEGER); VAR dumx, dumy: INTEGER; BEGIN dumx:=f.SeitenOffset+x*KastenPlatz-KastenBreite; dumy:=f.UntenOffset+y*KastenPlatz-KastenBreite; IF Color THEN Display.ReplConst(lightgray, dumx, dumy, KB, KB, Display.replace); Display.ReplConst(darkgray, dumx+1, dumy, KB-1, KB-1, Display.replace); Display.ReplConst(midgray, dumx+1, dumy+1, KB-2, KB-2, Display.replace); ELSE Display.ReplConst(Display.black, dumx, dumy, KB, KB, Display.replace); Display.ReplConst(col, dumx+1, dumy+1, KB-2, KB-2, Display.replace); END; END BlockKasten; (* draw char at box *) PROCEDURE DrawChar(f: Frame; ch: CHAR; XKasten, YKasten: INTEGER; Color: BOOLEAN; col: INTEGER); VAR Pat: Display.Pattern; dx, x, y, w, h: INTEGER; dumx, dumy: INTEGER; BEGIN Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat); ClearKasten(f, XKasten, YKasten, Color); dumx:=f.SeitenOffset+XKasten*KastenPlatz-KastenBreite+(KB-w) DIV 2; dumy:=f.UntenOffset+YKasten*KastenPlatz-KastenBreite+(KB-h) DIV 2; IF Color THEN col:=Colors[ORD(ch)-49]; END; Display.CopyPattern(col, Pat, dumx, dumy, Display.paint); END DrawChar; (* draw char at x y to display *) PROCEDURE DrawZahl(ch: CHAR; XPos, YPos: INTEGER); VAR Pat: Display.Pattern; dx, x, y, w, h: INTEGER; BEGIN Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat); IF Color THEN h:=black; ELSE h:=Display.white; END; Display.CopyPattern(h, Pat, XPos+x, YPos+y, Display.paint); END DrawZahl; (* draw LONGINT *) PROCEDURE DrawInt(x, y: INTEGER; Zahl: LONGINT; DrawInt: BOOLEAN); VAR Col, Anz: INTEGER; BEGIN Anz:=4; IF Color THEN Col:=midgray; ELSE Col:=Display.black; END; Display.ReplConst(Col, x, y, Anz*CharBreite+10, KastenBreite-2, Display.replace); IF DrawInt THEN IF Zahl<0 THEN DrawZahl("-", x+2, y+1); Zahl:=ABS(Zahl); END; REPEAT DrawZahl(CHR(Zahl MOD 10+48), x+Anz*CharBreite+1, y+2); Zahl:=Zahl DIV 10; DEC(Anz); UNTIL (Zahl=0) OR (Anz=-1); END; END DrawInt; (* draw number of Mines to find *) PROCEDURE DrawMinesToFind(f: Frame); BEGIN DrawInt((f.W-119) DIV 2+f.X+2, f.Y+f.H-ObenPlatz+6, f.d.Mines, TRUE); END DrawMinesToFind; (* draw the time *) PROCEDURE DrawTime(f: Frame); BEGIN 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); END DrawTime; (* draw pattern, like mine *) PROCEDURE DrawPat(f: Frame; XKasten, YKasten, No: INTEGER; Mode: BOOLEAN; Color: BOOLEAN; col: INTEGER); VAR dumx, dumy: INTEGER; BEGIN IF Mode THEN ClearKasten(f, XKasten, YKasten, Color); ELSE BlockKasten(f, XKasten, YKasten, Color, col); END; dumx:=f.SeitenOffset+XKasten*KastenPlatz-KastenBreite; dumy:=f.UntenOffset+YKasten*KastenPlatz-KastenBreite; IF Color THEN IF No<3 THEN Display.CopyPattern(black, Pat[1], dumx+2, dumy+2, Display.paint); IF No=2 THEN Display.CopyPattern(red, Pat[2], dumx+2, dumy+2, Display.paint); END; ELSE Display.CopyPattern(red, Pat[3], dumx+2, dumy+2, Display.paint); Display.ReplConst(black, dumx+5, dumy+3, 1, 10, Display.replace); END; ELSE IF No=1 THEN IF Mode THEN Display.CopyPattern(col, Pat[1], dumx+2, dumy+2, Display.paint); ELSE Display.CopyPattern(Display.black, Pat[1], dumx+2, dumy+2, Display.paint); END; ELSE IF No=2 THEN No:=4;END; Display.CopyPattern(Display.black, Pat[No], dumx+2, dumy+2, Display.paint); END; END; END DrawPat; (* invert char *) PROCEDURE DrawCharInv(f: Frame; ch: CHAR; XKasten, YKasten: INTEGER); VAR Pat: Display.Pattern; dx, x, y, w, h: INTEGER; dumx, dumy: INTEGER; BEGIN Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat); dumx:=f.SeitenOffset+XKasten*KastenPlatz-KB+(KB-w) DIV 2; dumy:=f.UntenOffset+YKasten*KastenPlatz-KB+(KB-h) DIV 2; Display.CopyPattern(Display.white, Pat, dumx, dumy, Display.invert); END DrawCharInv; (* make new data *) PROCEDURE NeuesFeld*(d: Data; x, y: INTEGER); VAR ZaehlerX, ZaehlerY: INTEGER; dummy: LONGINT; Bomben: SHORTINT; BEGIN NEW(d.Feld, x+2, y+2); IF d.Feld=NIL THEN d.Aktiv:=FALSE; RETURN; END; FOR ZaehlerX:=0 TO x+1 DO FOR ZaehlerY:=0 TO y+1 DO d.Feld[ZaehlerX, ZaehlerY]:=1; END; END; dummy:=(LONG(x)*y*d.Quote) DIV 100; d.Count:=LONG(x)*y-dummy;d.Mines:=dummy; REPEAT REPEAT ZaehlerX:=Random(x)+1; ZaehlerY:=Random(y)+1; UNTIL d.Feld[ZaehlerX, ZaehlerY]=1; d.Feld[ZaehlerX, ZaehlerY]:=10; DEC(dummy); UNTIL dummy=0; FOR ZaehlerX:=1 TO x DO FOR ZaehlerY:=1 TO y DO IF d.Feld[ZaehlerX, ZaehlerY]=1 THEN Bomben:=1; IF d.Feld[ZaehlerX+1, ZaehlerY]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX+1, ZaehlerY+1]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX, ZaehlerY+1]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX-1, ZaehlerY+1]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX-1, ZaehlerY]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX-1, ZaehlerY-1]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX, ZaehlerY-1]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX+1, ZaehlerY-1]=10 THEN INC(Bomben);END; d.Feld[ZaehlerX, ZaehlerY]:=Bomben; END; END; END; END NeuesFeld; (* draw a box *) PROCEDURE DrawKasten*(f: Frame; XZaehler, YZaehler: INTEGER; Color: BOOLEAN; col: INTEGER); VAR dummy: SHORTINT; BEGIN dummy:=f.d.Feld[XZaehler, YZaehler]; IF dummy>0 THEN IF dummy>16 THEN DrawPat(f, XZaehler, YZaehler, 3, FALSE, Color, col); ELSE BlockKasten(f, XZaehler, YZaehler, Color, col); END; ELSE IF dummy=-10 THEN DrawPat(f, XZaehler, YZaehler, 1, TRUE, Color, col); ELSIF dummy=-1 THEN ClearKasten(f, XZaehler, YZaehler, Color); ELSE DrawChar(f, CHR(47-dummy), XZaehler, YZaehler, Color, col); END; END; END DrawKasten; (* draw all *) PROCEDURE PlotAll(f: Frame); VAR xdum, ydum: INTEGER; BEGIN xdum:=(f.W-7*KastenPlatz) DIV 2+f.X+2; ydum:=f.Y+f.H-ObenPlatz+6; IF Color THEN Display.ReplConst(lightgray, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace); Display.ReplConst(darkgray, xdum, ydum-1, 4*CharBreite+11, KastenBreite-1, Display.replace); xdum:=f.W DIV 2+f.X+16; Display.ReplConst(lightgray, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace); Display.ReplConst(darkgray, xdum, ydum-1, 4*CharBreite+11, KastenBreite-1, Display.replace); ELSE Display.ReplConst(Display.white, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace); xdum:=f.W DIV 2+f.X+16; Display.ReplConst(Display.white, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace); END; DrawMinesToFind(f); DrawTime(f); ydum:=f.d.YKastenAnz*KastenPlatz+1; xdum:=f.d.XKastenAnz*KastenPlatz+1; IF Color THEN Display.ReplConst(midgray, f.SeitenOffset, f.UntenOffset, xdum, ydum, Display.replace); Display.ReplConst(lightgray, f.SeitenOffset-1, f.UntenOffset-1, 1, ydum+2, Display.replace); Display.ReplConst(lightgray, f.SeitenOffset-1, f.UntenOffset+ydum, xdum+1, 1, Display.replace); Display.ReplConst(darkgray, f.SeitenOffset-1, f.UntenOffset-1, xdum+2, 1, Display.replace); Display.ReplConst(darkgray, f.SeitenOffset+xdum, f.UntenOffset-1, 1, ydum+2, Display.replace); ELSE Display.ReplConst(Display.white, f.SeitenOffset, f.UntenOffset, xdum, ydum, Display.replace); END; FOR xdum:=1 TO f.d.XKastenAnz DO FOR ydum:=1 TO f.d.YKastenAnz DO DrawKasten(f, xdum, ydum, Color, Display.white); END; END; END PlotAll; (* draw all, if finding a mine *) PROCEDURE SwitchAll(f: Frame; Color: BOOLEAN; col: INTEGER); VAR xdum, ydum: INTEGER; Typ: SHORTINT; BEGIN Oberon.RemoveMarks(f.X, f.Y, f.W, f.H); FOR xdum:=1 TO f.d.XKastenAnz DO FOR ydum:=1 TO f.d.YKastenAnz DO Typ:=f.d.Feld[xdum, ydum]; IF Typ>0 THEN IF Typ=10 THEN DrawPat(f, xdum, ydum, 1, FALSE, Color, col); ELSIF Typ<10 THEN f.d.Feld[xdum, ydum]:=-Typ; DrawKasten(f, xdum, ydum, Color, col); ELSIF (Typ>16) & (Typ#26) THEN DrawPat(f, xdum, ydum, 2, FALSE, Color, col); END; END; END; END; END SwitchAll; (* test if Raster fits to frame *) PROCEDURE TestRaster(f: Frame): BOOLEAN; VAR XMax,YMax: INTEGER; BEGIN XMax:=(f.W-SeitenPlatz*2) DIV KastenPlatz; YMax:=(f.H-ObenPlatz-UntenPlatz) DIV KastenPlatz; IF XMaxd.XKastenAnz) OR (y>d.YKastenAnz) THEN RETURN;END; Dummy:=d.Feld[x, y]; IF (Dummy<0) OR (Dummy>9) THEN RETURN;END; DEC (d.Count); d.Feld[x, y]:=-Dummy; pkmsg.d:=d; pkmsg.x:=x;pkmsg.y:=y; Viewers.Broadcast(pkmsg); IF Dummy=1 THEN SearchMore(d, x+1, y);SearchMore(d, x+1, y+1); SearchMore(d, x,y+1);SearchMore(d, x-1, y+1); SearchMore(d, x-1, y);SearchMore(d, x-1, y-1); SearchMore(d, x, y-1);SearchMore(d, x+1, y-1); END; END SearchMore; (* new HIScore ? *) PROCEDURE CheckHiScore(d: Data); BEGIN IF d.Mode>-1 THEN IF d.Time0) & (Dummy<16) THEN pkmsg.d:=f.d; pkmsg.x:=XKasten;pkmsg.y:=YKasten; IF Dummy=10 THEN f.d.Feld[XKasten, YKasten]:=-10; f.d.Aktiv:=FALSE; SwitchAll(f, Color, col); Viewers.Broadcast(pkmsg); ELSE IF Dummy=1 THEN SearchMore(f.d, XKasten, YKasten); ELSE f.d.Feld[XKasten, YKasten]:=-Dummy; DEC(f.d.Count); Viewers.Broadcast(pkmsg); END; IF f.d.Count=0 THEN LastTime:=Input.Time()-1; timsg.id:=StartTime; timsg.Count:=0; Viewers.Broadcast(timsg); f.d.Aktiv:=FALSE; f.d.Time:=(Input.Time()-f.d.Time) DIV Input.TimeUnit; CheckHiScore(f.d); END; END; END; END SwitchKasten; (* react on mouse keys *) PROCEDURE MouseKeys*(f: Frame; XKasten, YKasten: INTEGER; Key: SET; Color: BOOLEAN; col: INTEGER); VAR Dummy: SHORTINT; pkmsg: PlotKastenMsg; BEGIN Dummy:=f.d.Feld[XKasten, YKasten]; pkmsg.d:=f.d; pkmsg.x:=XKasten;pkmsg.y:=YKasten; IF Key={2} THEN IF ~f.d.StartPlay THEN f.d.StartPlay:=TRUE; f.d.Time:=Input.Time(); END; SwitchKasten(f, XKasten, YKasten, Color, col); ELSIF Key={0} THEN IF Dummy>0 THEN IF Dummy<16 THEN f.d.Feld[XKasten, YKasten]:=Dummy+16; f.d.Mines:=f.d.Mines-1; ELSE f.d.Feld[XKasten, YKasten]:=Dummy-16; f.d.Mines:=f.d.Mines+1; END; Viewers.Broadcast(pkmsg); END; ELSIF Key={0,2} THEN IF Dummy<0 THEN IF ~f.d.StartPlay THEN f.d.StartPlay:=TRUE; f.d.Time:=Input.Time(); END; SwitchKasten(f, XKasten+1, YKasten, Color, col); SwitchKasten(f, XKasten+1, YKasten-1, Color, col); SwitchKasten(f, XKasten, YKasten-1, Color, col); SwitchKasten(f, XKasten-1, YKasten-1, Color, col); SwitchKasten(f, XKasten-1, YKasten, Color, col); SwitchKasten(f, XKasten-1, YKasten+1, Color, col); SwitchKasten(f, XKasten, YKasten+1, Color, col); SwitchKasten(f, XKasten+1, YKasten+1, Color, col); END; END; END MouseKeys; (* get selected frame *) PROCEDURE GetFrame(VAR f: Display.Frame): BOOLEAN; VAR v: Viewers.Viewer; BEGIN IF Oberon.Par.frame=Oberon.Par.vwr.dsc THEN IF (Oberon.Par.frame # NIL) THEN f:=Oberon.Par.frame.next; RETURN TRUE; END; ELSE v:=Oberon.MarkedViewer(); IF (v.dsc # NIL) & (v.dsc.next # NIL) THEN f:=v.dsc.next; RETURN TRUE; END END; RETURN FALSE; END GetFrame; (* do the pause *) PROCEDURE DoPause(f: Frame); VAR nfmsg: NeuesFeldMsg; rpmsg: RePlotMsg; pnmsg: PlotNewMsg; BEGIN IF f.d.Pause THEN IF TestRaster(f) OR PauseFlag THEN f.d.Pause:=FALSE; nfmsg.d:=f.d;nfmsg.Change:=FALSE; Viewers.Broadcast(nfmsg); IF nfmsg.Change THEN IF f.d.Aktiv THEN NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz); END; pnmsg.d:=f.d; Viewers.Broadcast(pnmsg); f.d.StartPlay:=FALSE; ELSE rpmsg.All:=FALSE; rpmsg.d:=f.d; f.d.Time:=Input.Time()-f.d.Time; Viewers.Broadcast(rpmsg); END; ELSE Texts.WriteString(W, "Frame too small for old game !"); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); PauseFlag:=TRUE; END; ELSE f.d.Pause:=TRUE; f.d.Time:=Input.Time()-f.d.Time; rpmsg.d:=f.d;rpmsg.All:=FALSE; Viewers.Broadcast(rpmsg); END; END DoPause; (* set Pause mode *) PROCEDURE Pause*; VAR f, g: Display.Frame; BEGIN IF GetFrame(g) THEN f:=g; WITH f: Frame DO IF f.d.Aktiv THEN DoPause(f);END; ELSE END; END; END Pause; (* do mouseaction *) PROCEDURE DoMou(f: Frame; X, Y: INTEGER; Key, FirstKey: SET); VAR XKasten, YKasten: INTEGER; XStore, YStore: INTEGER; Dummy: SHORTINT; pnmsg: PlotNewMsg; nfmsg: NeuesFeldMsg; BEGIN IF f.d.Pause THEN RETURN; END; XStore:=X;YStore:=Y; X:=X-f.SeitenOffset;Y:=Y-f.UntenOffset; IF X<0 THEN RETURN;END; IF Y<0 THEN RETURN;END; XKasten:=X DIV KastenPlatz +1; YKasten:=Y DIV KastenPlatz +1; IF (XKasten<=f.d.XKastenAnz) & (YKasten<=f.d.YKastenAnz) THEN IF ~f.d.Aktiv THEN RETURN;END; IF (X MOD KastenPlatz)=0 THEN RETURN;END; IF (Y MOD KastenPlatz)=0 THEN RETURN;END; Dummy:=f.d.Feld[XKasten, YKasten]; IF Key={1} THEN IF Dummy>0 THEN IF Dummy<16 THEN Oberon.RemoveMarks(f.SeitenOffset, f.UntenOffset, f.W, f.H); DrawCharInv(f, "?", XKasten, YKasten); END; END; ELSE MouseKeys(f, XKasten, YKasten, Key, Color, Display.white); END; IF ~UseTimeTask THEN DrawTime(f);END; IF f.d.Count=0 THEN GotIt(f); END; ELSE IF (YStore>f.Y+f.H-ObenPlatz+3) & (YStore0 THEN DrawMinesToFind(self); END; IF ~self.d.Aktiv THEN PlotSmily(self, FALSE);END; | m: NeuesFeldMsg DO (* Check if new W & H are fitting to frame *) IF CheckRaster(self) THEN m.Change:=TRUE; END; ELSE END; END; END; ELSE END; END Handler; (* get parameters *) PROCEDURE GetPar*(VAR Quote, X, Y, Mode: INTEGER); VAR S: Texts.Scanner; text: Texts.Text; Dummy, StoreQuote: INTEGER; beg, end, time: LONGINT; BEGIN StoreQuote:=Quote; Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); IF S.class=Texts.Char THEN IF S.c="^" THEN Oberon.GetSelection(text, beg, end, time); IF time=-1 THEN RETURN; END; Texts.OpenScanner(S, text, beg); Texts.Scan(S); ELSE RETURN; END; END; IF S.class=Texts.Int THEN IF (S.i>0) & (S.i<90) THEN; Quote:=SHORT(S.i); IF (Mode=-1) OR (X#256) THEN Texts.Scan(S); IF S.class=Texts.Int THEN; Dummy:=SHORT(S.i); Texts.Scan(S); IF S.class=Texts.Int THEN IF (Dummy<6) OR (Dummy>127) THEN X:=8; ELSE X:=Dummy; END; IF (S.i<6) OR (S.i>127) THEN Y:=8; ELSE Y:=SHORT(S.i); END; END; END; ELSE IF Quote#StoreQuote THEN Mode:=-1; END; END; END; END; END GetPar; (* set frame and parameters *) PROCEDURE ShortNewPar(X, Y, Quote, Mode: INTEGER); VAR f, g: Display.Frame; nfmsg: NeuesFeldMsg; pnmsg: PlotNewMsg; BEGIN IF GetFrame(g) THEN f:=g; WITH f: Frame DO GetPar(Quote, X, Y, Mode); f.d.Quote:=Quote;f.d.Mode:=Mode; f.d.XKastenAnz:=X;f.d.YKastenAnz:=Y; f.d.Aktiv:=TRUE;f.d.Pause:=FALSE; nfmsg.d:=f.d; Viewers.Broadcast(nfmsg); IF f.d.Aktiv THEN NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz); END; pnmsg.d:=f.d; f.d.StartPlay:=FALSE; Viewers.Broadcast(pnmsg); ELSE END; END; END ShortNewPar; (* set new username *) PROCEDURE SetUser*; VAR S: Texts.Scanner; text: Texts.Text; beg, end, time: LONGINT; BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); IF S.class=Texts.Char THEN IF S.c="^" THEN Oberon.GetSelection(text, beg, end, time); IF time=-1 THEN RETURN; END; Texts.OpenScanner(S, text, beg); Texts.Scan(S); ELSE RETURN; END; END; IF S.class=Texts.Name THEN COPY(S.s, Name); END; Texts.WriteString(W, "Current Username : "); Texts.WriteString(W, Name); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); END SetUser; (* print Hi-Score *) PROCEDURE Score*; VAR i: INTEGER; PL: Oberon.ParList; te: Texts.Text; BEGIN te:=TextFrames.Text(""); Texts.WriteString(W, "Oberon-Mines Hall Of Fame !");Texts.WriteLn(W); Texts.WriteString(W, "________________________________________________");Texts.WriteLn(W); FOR i:=0 TO 2 DO IF i=0 THEN Texts.WriteString(W, "Beg.: "); ELSIF i=1 THEN Texts.WriteString(W, "Adv.: "); ELSE Texts.WriteString(W, "Exp.: ");END; Texts.WriteInt(W, HiScore[i].Time, 1); Texts.WriteString(W, " sec "); Texts.WriteString(W, HiScore[i].Name); Texts.WriteLn(W); END; Texts.WriteLn(W); Texts.WriteString(W, "Current Username : "); Texts.WriteString(W, Name); Texts.WriteLn(W); Texts.Append(te, W.buf); Texts.Close(te, "Mines.HiScore.Text"); te:=TextFrames.Text(""); Texts.WriteString(W, "Mines.HiScore.Text"); Texts.Append(te, W.buf); NEW(PL);PL:=Oberon.Par; PL.text:=te;PL.pos:=0; Oberon.Call("System.Open",PL,FALSE,i); END Score; (* create new frame with new data *) PROCEDURE Open*; VAR x, y: INTEGER; f: Frame; v: MenuViewers.Viewer; tf: TextFrames.Frame; text: Texts.Text; BEGIN NEW(f);IF f=NIL THEN RETURN;END; NEW(f.d);IF f.d=NIL THEN RETURN;END; f.handle:=Handler;f.d.Aktiv:=TRUE;f.d.Quote:=16; f.LastModMsg:=TRUE;f.d.Pause:=FALSE; f.d.XKastenAnz:=256;f.d.YKastenAnz:=256; f.d.Mode:=-1;f.d.StartPlay:=FALSE; Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y); tf:=TextFrames.NewMenu("Mines", Menu); text:=TextFrames.Text("Mines.Menu.Text"); IF text.len>5 THEN tf.text:=text;END; v:=MenuViewers.New(tf, f, TextFrames.menuH, x, y); END Open; (* switch between color ans b/w mode *) PROCEDURE ColorMode*; VAR rpmsg: RePlotMsg; BEGIN Color:=~Color; rpmsg.All:=TRUE; Viewers.Broadcast(rpmsg); SaveHi(FALSE); END ColorMode; (* switches between task und mouse action time mode *) PROCEDURE TimeMode*; BEGIN UseTimeTask:=~UseTimeTask; SaveHi(FALSE); END TimeMode; (* start different types of the game *) PROCEDURE Beginner*; BEGIN ShortNewPar(8, 8, 15, 0); END Beginner; PROCEDURE Advanced*; BEGIN ShortNewPar(16, 16, 16, 1); END Advanced; PROCEDURE Expert*; BEGIN ShortNewPar(30, 16, 21, 2); END Expert; PROCEDURE Max*; BEGIN ShortNewPar(256, 256, 16, -1); END Max; PROCEDURE Start*; BEGIN ShortNewPar(8, 8, 16, -1); END Start; BEGIN UsedFont:=Fonts.This("Syntax14.Scn.Fnt"); Texts.OpenWriter(W); Texts.WriteString(W, "Oberon-Mines V1.31"); Texts.WriteLn(W); Texts.WriteString(W, "(C) 1 Oct 94 by Ralf Degner"); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); StartTime:=Input.Time(); seed:=StartTime; TimeTaskRuns:=FALSE; Color:=FALSE;UseTimeTask:=TRUE; IF Oberon.User="" THEN Name:="AMIGA"; ELSE COPY(Oberon.User, Name); END; Colors[0]:=Col1;Colors[1]:=Col2;Colors[2]:=Col3;Colors[3]:=Col4; Colors[4]:=Col5;Colors[5]:=Col6;Colors[6]:=Col7;Colors[7]:=Col8; LoadHi(); IF UseTimeTask THEN StartTask(); END; (* install patterns *) HappyData[1]:={5,6,7,8,9,10}; HappyData[2]:={3,4,11,12}; HappyData[3]:={2,13}; HappyData[4]:={1,5,6,7,8,9,10,14}; HappyData[5]:={1,4,11,14}; HappyData[6]:={0,3,12,15}; HappyData[7]:={0,7,8,15}; HappyData[8]:={0,7,8,15}; HappyData[9]:={0,15}; HappyData[10]:={0,15}; HappyData[11]:={0,15,5,6,9,10}; HappyData[12]:={1,14,5,6,9,10}; HappyData[13]:={1,14}; HappyData[14]:={2,13}; HappyData[15]:={3,4,11,12}; HappyData[16]:={5,6,7,8,9,10}; HappyPat:=Display.NewPattern(HappyData, 16, 16); SadData:=HappyData; SadData[5]:={1,5,6,7,8,9,10,14}; SadData[4]:={1,4,11,14}; SadData[6]:={0,15}; SadPat:=Display.NewPattern(SadData, 16, 16); BackData[1]:={}; BackData[2]:={5,6,7,8,9,10}; BackData[3]:={3,4,5,6,7,8,9,10,11,12}; BackData[4]:={2,3,4,5,6,7,8,9,10,11,12,13}; BackData[5]:={2,3,4,5,6,7,8,9,10,11,12,13}; BackData[6]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14}; BackData[7]:={1,2,3,4,5,6,9,10,11,12,13,14}; BackData[8]:={1,2,3,4,5,6,9,10,11,12,13,14}; BackData[9]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14}; BackData[10]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14}; BackData[11]:={1,2,3,4,7,8,11,12,13,14}; BackData[12]:={1,2,3,4,7,8,11,12,13,14}; BackData[13]:={2,3,4,5,6,7,8,9,10,11,12,13}; BackData[14]:={3,4,5,6,7,8,9,10,11,12}; BackData[15]:={5,6,7,8,9,10}; BackData[16]:={}; BackPat:=Display.NewPattern(BackData, 16, 16); GotItData:=HappyData; GotItData[12]:={1,4,5,6,7,8,9,10,11,14}; GotItData[11]:={0,3,4,5,6,9,10,11,12,15}; GotItData[10]:={0,2,4,5,6,9,10,11,13,15}; GotItData[9]:={0,1,5,6,7,8,9,10,14,15}; GotItPat:=Display.NewPattern(GotItData, 16, 16); PauseData:=SadData; PauseData[5]:={1,14}; PauseData[4]:={1,4,5,6,7,8,9,10,11,14}; PausePat:=Display.NewPattern(PauseData, 16, 16); (* Mine *) Data1[1]:={3,4,5,6,7,8}; Data1[2]:={2,3,4,5,6,7,8,9}; Data1[3]:={1,2,3,5,6,7,8,9,10}; Data1[4]:={1,2,5,6,7,8,9,10}; Data1[5]:={1,2,4,5,6,7,8,9,10}; Data1[6]:={1,2,3,4,5,6,7,8,9,10}; Data1[7]:={2,3,4,5,6,7,8,9}; Data1[8]:={3,4,5,6,7,8}; Data1[9]:={5,6}; Data1[10]:={5}; Data1[11]:={6,10}; Data1[12]:={7,8,9}; Pat[1]:=Display.NewPattern(Data1, 12, 12); (* No Mine *) Data2[1]:={0,11}; Data2[2]:={1,10}; Data2[3]:={2,9}; Data2[4]:={3,8}; Data2[5]:={4,7}; Data2[6]:={5,6}; Data2[7]:={5,6}; Data2[8]:={4,7}; Data2[9]:={3,8}; Data2[10]:={2,9}; Data2[11]:={1,10}; Data2[12]:={0,11}; Pat[2]:=Display.NewPattern(Data2, 12, 12); (* Flag *) Data3[1]:={}; Data3[2]:={3}; Data3[3]:={3}; Data3[4]:={3}; Data3[5]:={3}; Data3[6]:={3}; Data3[7]:={3,4,5}; Data3[8]:={3,4,5,6,7}; Data3[9]:={3,4,5,6,7,8,9}; Data3[10]:={3,4,5,6,7}; Data3[11]:={3,4,5}; Data3[12]:={}; Pat[3]:=Display.NewPattern(Data3, 12, 12); (* No Mine - No Color *) FOR Dummy:=1 TO 12 DO Data4[Dummy]:=Data1[Dummy]/Data2[Dummy]; END; Pat[4]:=Display.NewPattern(Data4, 12, 12); END Mines.