PROGRAM Quad; {A demo which loads some graphics etc. Nice. Don't forget to distribute quaddata.inc! The sources for this game was found on a site that claims to only have PD stuff with the below header(which was only reindented), and the webmaster said that everything he published was sent to him with that purpose. We tried to contact the authors mentioned below via mail over internet, but that failed. If there is somebody that claims authorship of these programs, please mail marco@freepascal.org, and the sources will be removed from our websites. ------------------------------------------------------------------------ ORIGINAL Header: Programmed by: Justin Pierce Graphics by: Whitney Pierce Inspired by: Jos Dickman''s triple memory! ----- Old version requires egavga.bgi. FPC doesn't require BGI's (VGA and VESA support are built in the Graph, others are ignored).} Uses Crt,Dos,Graph, GameUnit; {Supplied with FPC demoes package. Wrapper for mousesupport (via msmouse or api), and contains highscore routines} Const nox = 10; noy = 8; card_border = red; PicBufferSize = 64000; {Buffersize for deRLE'ed picture data} ComprBufferSize = 20000; {Buffer for diskread- RLE'ed data} PicsFilename = 'quaddata.dat'; {Name of picturesfile} ScoreFileName = 'quad.scr'; Type pByte = ^Byte; {BufferTypes} Card = Record exposed: boolean; pic: byte; End; {Assigns an enumeration to each picture} PictureEnum= (zero,one,two,three,four,five,six,seven,eight,nine,colon, back,score,exit_b,score_b,chunk,p1,p2,p3,p4,p5,p6,p7,p8, p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20); {A pictures definition; x and y dimensions and offset in PicData buffer} Picture = packed Record start: longint; x,y: byte; End; {All pictures. This array, and the data in PicData is all pic info.} PictureArray= ARRAY[zero..p20] OF Picture; selected = Record x,y: byte; pic: byte; End; time_record = Record o_hr,o_min,o_sec,o_sec100: word; hr,min,sec,sec100: word; a_sec,a_min: word; End; Var b : array[1..nox,1..noy] Of card; Pics : PictureArray; PicData : PByte; s : array[1..4] Of selected; os : byte; turns : integer; off,ok,exit1: boolean; opened : byte; bgidirec : string; time : time_record; { Procedure fatal(fcall:String); Begin textmode(CO80); clrscr; Writeln('A fatal error has occured'); Writeln('Error: ',fcall); Writeln; Write('Hit enter to halt program--'); readln; halt; End; } Procedure ginit640x480x16(direc:String); Var grd,grmode: integer; Begin closegraph; grd := 9;{ detect;} grmode := 2;{ m800x600x16;} initgraph(grd,grmode,direc); setgraphmode(2); End; Procedure clean_board; Var x,y: byte; Begin y := 1; Repeat x := 1; Repeat b[x,y].pic := 0; b[x,y].exposed := false; inc(x); Until x>nox; inc(y); Until y>noy End; Procedure showpic(xp,yp:integer; tp:pictureenum); Var x,y,x1,y1: byte; tx: integer; Begin x := pics[tp].x; {mb[tp.start];} y := pics[tp].y; {mb[tp.start+1];} y1 := 1; tx := 0; Repeat x1 := 1; Repeat putpixel(xp+(x1-1),yp+(y1-1),picdata[pics[tp].start-1+tx]); inc(x1); inc(tx); Until x1>x; inc(y1); Until y1>y; End; Procedure NumberOutput(X,Y,Number:LONGINT;RightY:BOOLEAN); Var num: string; plc: byte; Begin str(number,num); If length(num)=1 Then insert('0',num,0); IF RightY THEN dec (x,length(num)*11); plc := 1; Repeat IF (Num[plc]>CHR(47)) AND (Num[plc]length(num); End; Procedure update_secs; Begin showpic(605,453,colon); NumberOutput(615,453,time.a_sec,FALSE); End; Procedure showturn(x,y:integer); Begin hidemouse; If (x=0) And (y=0) Then NumberOutput(4,453,Turns,FALSE) ELSE NumberOutput(x,y,Turns,FALSE); showmouse; End; Procedure get_original_time; Begin With time Do Begin a_sec := 0; a_min := 0; gettime(o_hr,o_min,o_sec,o_sec100); gettime(hr,min,sec,sec100); End; End; Procedure update_time(ForcedUpdate:BOOLEAN); Begin With time Do Begin gettime(hr,min,sec,sec100); If sec<>o_sec Then Begin inc(a_sec); If a_sec<=60 Then update_secs; End; If a_sec>60 Then Begin a_sec := 0; inc(a_min); ForcedUpdate:=TRUE; End; IF ForcedUpdate THEN BEGIN Update_secs; showpic(606,453,colon); NumberOutput(606,453,time.a_min,TRUE); END; o_hr := hr; o_min := min; o_sec := sec; o_sec100 := sec; End; End; Procedure makecard(x,y:byte); Var xp,yp: integer; Begin hidemouse; xp := ((x-1)*63); yp := ((y-1)*56); setcolor(card_border); setfillstyle(1,0); bar(xp+1,yp+1,xp+62,yp+55); rectangle(xp,yp,xp+63,yp+56); If b[x,y].exposed=false Then Begin showpic(xp+1,yp+1,back); End; showmouse; If b[x,y].exposed=true Then Begin hidemouse; showpic(xp+7,yp+4,pictureenum(ORD(b[x,y].pic)+ORD(p1)-1)); showmouse; End; End; Function used(pic:byte): byte; Var cx,cy,u: byte; Begin used := 0; u := 0; cy := 1; Repeat cx := 1; Repeat If b[cx,cy].pic=pic Then inc(u); inc(cx); Until cx>nox; inc(cy); Until cy>noy; used := u; End; Procedure set_board; CONST Outstr=#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+ #219+#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+ #219+#219+#219+#219; Var cx,cy,pic: byte; Begin setcolor(0); outtextxy(0,470,OutStr); setcolor(green); outtextxy(0,470,'Dealing board, please wait...'); Delay(1000); cy := 1; Repeat cx := 1; Repeat Repeat pic := random(20)+1; Until used(pic)<4; b[cx,cy].pic := pic; makecard(cx,cy); inc(cx); Until cx>nox; inc(cy); Until cy>noy; setcolor(0); outtextxy(0,470,OutStr); End; Procedure fire_works; Const nof = 30; Type fires = Record x,y: Longint; direct: longint; speed: Longint; explode: boolean; color: byte; oex: longint; End; Var fire: array[1..nof] Of fires; Procedure clean_fires; Var c: longint; Begin c := 1; Repeat fire[c].direct := random(2)+1; fire[c].color := random(15)+1; fire[c].x := random(639); fire[c].y := 479; fire[c].explode := false; fire[c].speed := random(20)+15; fire[c].oex := 1; inc(c); Until c>nof; End; Procedure inact; Var c: longint; Begin c := 1; Repeat If fire[c].explode=false Then Begin setcolor(fire[c].color); circle(fire[c].x,fire[c].y,1); End; If (fire[c].explode=true) And (fire[c].oex<10) Then Begin setcolor(fire[c].color); circle(fire[c].x,fire[c].y,fire[c].oex); setcolor(random(15)+1); circle(fire[c].x,fire[c].y,fire[c].oex-1); End; inc(c); Until c>nof; delay(75); gotoxy(1,1); c := 1; Repeat setcolor(0); circle(fire[c].x,fire[c].y,1); If (fire[c].explode=true) And (fire[c].oex<10) Then Begin circle(fire[c].x,fire[c].y,fire[c].oex); circle(fire[c].x,fire[c].y,fire[c].oex-1); inc(fire[c].oex); End; If fire[c].explode=false Then Begin dec(fire[c].speed,1); dec(fire[c].y,fire[c].speed); If fire[c].direct=1 Then inc(fire[c].x,2); If fire[c].direct=2 Then dec(fire[c].x,2); If fire[c].speed<=(-1*LONGINT(random(11))) Then fire[c].explode := true; End; inc(c); Until c>nof; c := 1; End; Function exploded: boolean; Var c: longint; m: boolean; Begin c := 1; m := true; Repeat If fire[c].oex<6 Then m := false; inc(c); Until (c>nof); exploded := m; End; Begin cleardevice; Repeat clean_fires; Repeat inact; Until (exploded=true) Or (keypressed); Until keypressed; End; Procedure win; Var m,s: string; I,J : LONGINT; Begin hidemouse; fire_works; cleardevice; closegraph; textmode(co80+font8x8); clrscr; I:=SlipInScore(Turns); GotoXY(1,23); Writeln('Game Over, turns needed = ',Turns); FOR J:=9 TO 22 DO BEGIN GotoXY(20,J); Write(' ':38); END; IF I<>0 THEN BEGIN ShowHighScore; {$IFDEF USEGRAPHICS} GrInputStr(S,20,21-I,16,12,10,FALSE,AlfaBeta); {$ELSE} InputStr(S,20,21-I,10,FALSE,AlfaBeta); {$ENDIF} IF Length(S)<12 THEN BEGIN str(time.a_min,m); S:=S+'['+m+':'; str(time.a_sec,m); S:=S+'m'+']'; END; HighScore[I-1].Name:=S; END; ShowHighScore; ginit640x480x16(bgidirec); off := false; clean_board; set_board; turns := 0; showpic(0,450,score); showpic(80,450,score_b); showpic(150,450,exit_b); showpic(569,450,score); showturn(0,0); exit1 := false; get_original_time; update_time(True); SetMousePosition(0,0); showmouse; End; Procedure show_scores; Var x,y,c: byte; Begin hidemouse; y := 1; Repeat x := 1; showpic(x+135,(y-1)*21,score); showpic(x,(y-1)*21,score); showpic(x+204,(y-1)*21,score); Repeat showpic(((x-1)*10)+3,(y-1)*21,chunk); inc(x); Until x>20; inc(y); Until y>10; c := 0; Repeat If HighScore[c].name<>'' Then Begin setcolor(white); outtextxy(4,7+(c*21),HighScore[c].name); turns := HighScore[c].Score; showturn(211,3+(c*21)); End; inc(c); Until c>9; turns := 0; gotoxy(1,1); readln; off := false; clean_board; set_board; turns := 0; showpic(0,450,score); showpic(80,450,score_b); showpic(150,450,exit_b); showpic(569,450,score); showturn(0,0); exit1 := false; get_original_time; update_time(True); SetMousePosition(0,0); showmouse; End; Procedure interpret; Var mpx,mpy: byte; ms_mx,ms_my,ms_but : LONGINT; Begin GetMouseState(ms_mx,ms_my,ms_but); ms_mx:=ms_mx shr 1;; If ms_but=0 Then off := false; If ((ms_but AND 1)=1) And (off=false) Then Begin off := true; mpx := ms_mx*2 Div 63; mpy := (ms_my) Div 56; If (ms_mx*2>=80) And (ms_mx*2<=129) And (ms_my>=450) And (ms_my<=466) And (ok=true) Then show_scores; If (ms_mx*2>=150) And (ms_mx*2<=199) And (ms_my>=450) And (ms_my<=466) Then Begin exit1 := true; End; inc(mpx); inc(mpy); If (b[mpx,mpy].exposed=false) And (mpx>=1) And (mpy>=1) And (mpx<=10) And (mpy<=8) Then Begin setfillstyle(1,0); bar(80,450,130,466); ok := false; b[mpx,mpy].exposed := true; makecard(mpx,mpy); inc(os); s[os].x := mpx; s[os].y := mpy; s[os].pic := b[mpx,mpy].pic; End; End; If os=4 Then Begin inc(turns); showturn(0,0); os := 0; delay(700); inc(opened); If Not((s[1].pic=s[2].pic) And (s[1].pic=s[3].pic) And (s[1].pic=s[4].pic)) Then Begin dec(opened); b[s[1].x,s[1].y].exposed := false; b[s[2].x,s[2].y].exposed := false; b[s[3].x,s[3].y].exposed := false; b[s[4].x,s[4].y].exposed := false; makecard(s[1].x,s[1].y); makecard(s[2].x,s[2].y); makecard(s[3].x,s[3].y); makecard(s[4].x,s[4].y); End; If opened=20 Then win; End; If NOT ok Then update_time(FALSE); End; Procedure load_pics(PicBuf:PByte); {loads picture structures from disc} VAR F : File; Buf1Ind, I,J,K : LONGINT; TData : PByte; Begin GetMem(TData,ComprBufferSize); { allocate buffer} Assign(F,Picsfilename); { Open file} {$I-} Reset(F,1); {$I+} If ioresult<>0 Then BEGIN TextMode(CO80); Writeln('Fatal error, couldn''t find graphics data file quaddata.dat'); HALT; END; {Read the array with picture information; (X,Y dimensions and offset in binary data)} BlockRead(F,pics,SIZEOF(Picture)*(ORD(p20)-ORD(zero)+1),I); {Read some slackspace which shouldn't be in the file ;-)} blockread(F,TData[0],6,Buf1ind); {Read the real, RLE'ed graphics data} BlockRead(F,TData[0],ComprBufferSize,Buf1Ind); Close(F); {Expand the RLE data. Of each byte, the high nibble is the count-1, low nibble is the value} I:=0; J:=0; REPEAT K:=(TData[I] SHR 4) +1; FillChar(PicBuf[J],K,TData [I] AND 15); INC(J,K); INC(I); UNTIL I>=Buf1Ind; {Release the temporary buffer (the compressed data isn't necesary anymore)} Freemem(TData,ComprBufferSize); End; Procedure clean; VAR I : LONGINT; Begin Randomize; {Initialize random generator} Negative:=TRUE; {Higher highscore is worse} HighX:=20; HighY:=9; {coordinates for highscores} GetMem(PicData,PicBufferSize); {Allocate room for pictures} load_pics(PicData); {Load picture data from file} FOR I:=0 TO 9 DO {Create default scores} HighScore[I].Score:=-100*I; {Negative, because then the "highest" score is best} LoadHighScore(ScoreFileName); {Try to load highscore file} closegraph; bgidirec := 'd:\prog\bp\bgi'; ginit640x480x16(bgidirec); setcolor(card_border); ok := true; opened := 0; os := 0; s[1].x := 0; s[2].x := 0; s[3].x := 0; off := false; clean_board; set_board; turns := 0; showpic(0,450,score); showpic(80,450,score_b); showpic(150,450,exit_b); showpic(569,450,score); showturn(0,0); exit1 := false; SetMousePosition(0,0); get_original_time; update_time(True); showmouse; End; Begin clean; Repeat interpret; Until exit1=true; closegraph; textmode(co80); Freemem(PicData,PicBufferSize); clrscr; SaveHighScore; Writeln('Thanks for playing Quadruple Memory'); Writeln('Feel free to distribute this software.'); Writeln; Writeln('Programmed by: Justin Pierce'); Writeln('Graphics by: Whitney Pierce'); Writeln('Inspired by: Jos Dickman''s triple memory!'); Writeln('FPC conversion and cleanup by Marco van de Voort'); Writeln; End. $Log$ Revision 1.1 2001-05-03 21:39:33 peter * moved to own module Revision 1.2 2000/07/13 11:33:08 michael + removed logs }