quad.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. PROGRAM Quad;
  2. {A demo which loads some graphics etc. Nice. Don't forget to distribute
  3. quaddata.inc!
  4. The sources for this game was found on a site that claims to only have
  5. PD stuff with the below header(which was only reindented), and the webmaster
  6. said that everything he published was sent to him with that purpose. We tried
  7. to contact the authors mentioned below via mail over internet, but that
  8. failed. If there is somebody that claims authorship of these programs,
  9. please mail [email protected], and the sources will be removed from our
  10. websites.
  11. ------------------------------------------------------------------------
  12. ORIGINAL Header:
  13. Programmed by: Justin Pierce
  14. Graphics by: Whitney Pierce
  15. Inspired by: Jos Dickman''s triple memory!
  16. -----
  17. Old version requires egavga.bgi. FPC doesn't require BGI's (VGA and VESA
  18. support are built in the Graph, others are ignored).}
  19. Uses Crt,Dos,Graph,
  20. GameUnit; {Supplied with FPC demoes package. Wrapper for
  21. mousesupport (via msmouse or api), and contains
  22. highscore routines}
  23. Const nox = 10;
  24. noy = 8;
  25. card_border = red;
  26. PicBufferSize = 64000; {Buffersize for deRLE'ed picture data}
  27. ComprBufferSize = 20000; {Buffer for diskread- RLE'ed data}
  28. PicsFilename = 'quaddata.dat'; {Name of picturesfile}
  29. ScoreFileName = 'quad.scr';
  30. Type
  31. pByte = ^Byte; {BufferTypes}
  32. Card = Record
  33. exposed: boolean;
  34. pic: byte;
  35. End;
  36. {Assigns an enumeration to each picture}
  37. PictureEnum= (zero,one,two,three,four,five,six,seven,eight,nine,colon,
  38. back,score,exit_b,score_b,chunk,p1,p2,p3,p4,p5,p6,p7,p8,
  39. p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20);
  40. {A pictures definition;
  41. x and y dimensions and offset in PicData buffer}
  42. Picture = packed Record
  43. start: longint;
  44. x,y: byte;
  45. End;
  46. {All pictures. This array, and the data in PicData is all pic info.}
  47. PictureArray= ARRAY[zero..p20] OF Picture;
  48. selected = Record
  49. x,y: byte;
  50. pic: byte;
  51. End;
  52. time_record = Record
  53. o_hr,o_min,o_sec,o_sec100: word;
  54. hr,min,sec,sec100: word;
  55. a_sec,a_min: word;
  56. End;
  57. Var b : array[1..nox,1..noy] Of card;
  58. Pics : PictureArray;
  59. PicData : PByte;
  60. s : array[1..4] Of selected;
  61. os : byte;
  62. turns : integer;
  63. off,ok,exit1: boolean;
  64. opened : byte;
  65. bgidirec : string;
  66. time : time_record;
  67. Procedure fatal(fcall:String);
  68. Begin
  69. textmode(CO80);
  70. clrscr;
  71. Writeln('A fatal error has occured');
  72. Writeln('Error: ',fcall);
  73. Writeln;
  74. Write('Hit enter to halt program--');
  75. readln;
  76. halt;
  77. End;
  78. Procedure ginit640x480x16(direc:String);
  79. Var grd,grmode,errcode: integer;
  80. Begin
  81. closegraph;
  82. grd := 9;{ detect;}
  83. grmode := 2;{ m800x600x16;}
  84. initgraph(grd,grmode,direc);
  85. { ErrCode := GraphResult;
  86. If ErrCode <> grOk Then fatal(
  87. 'PROC[GINIT640X480X16]- CANNOT INITIALIZE 640x480x16 GRAPHICS MODE'
  88. );}
  89. setgraphmode(2);
  90. End;
  91. Procedure clean_board;
  92. Var x,y: byte;
  93. Begin
  94. y := 1;
  95. Repeat
  96. x := 1;
  97. Repeat
  98. b[x,y].pic := 0;
  99. b[x,y].exposed := false;
  100. inc(x);
  101. Until x>nox;
  102. inc(y);
  103. Until y>noy
  104. End;
  105. Procedure showpic(xp,yp:integer; tp:pictureenum);
  106. Var x,y,x1,y1: byte;
  107. tx: integer;
  108. Begin
  109. x := pics[tp].x; {mb[tp.start];}
  110. y := pics[tp].y; {mb[tp.start+1];}
  111. y1 := 1;
  112. tx := 0;
  113. Repeat
  114. x1 := 1;
  115. Repeat
  116. putpixel(xp+(x1-1),yp+(y1-1),picdata[pics[tp].start-1+tx]);
  117. inc(x1);
  118. inc(tx);
  119. Until x1>x;
  120. inc(y1);
  121. Until y1>y;
  122. End;
  123. Procedure NumberOutput(X,Y,Number:LONGINT;RightY:BOOLEAN);
  124. Var num: string;
  125. plc: byte;
  126. Begin
  127. str(number,num);
  128. If length(num)=1 Then
  129. insert('0',num,0);
  130. IF RightY THEN
  131. dec (x,length(num)*11);
  132. plc := 1;
  133. Repeat
  134. IF (Num[plc]>CHR(47)) AND (Num[plc]<CHR(58)) THEN
  135. showpic(((plc-1)*11)+X,Y,pictureenum(ORD(Zero)+ORD(Num[plc])-48));
  136. inc(plc);
  137. Until plc>length(num);
  138. End;
  139. Procedure update_secs;
  140. Begin
  141. showpic(605,453,colon);
  142. NumberOutput(615,453,time.a_sec,FALSE);
  143. End;
  144. Procedure showturn(x,y:integer);
  145. Begin
  146. hidemouse;
  147. If (x=0) And (y=0) Then
  148. NumberOutput(4,453,Turns,FALSE)
  149. ELSE
  150. NumberOutput(x,y,Turns,FALSE);
  151. showmouse;
  152. End;
  153. Procedure get_original_time;
  154. Begin
  155. With time Do
  156. Begin
  157. a_sec := 0;
  158. a_min := 0;
  159. gettime(o_hr,o_min,o_sec,o_sec100);
  160. gettime(hr,min,sec,sec100);
  161. End;
  162. End;
  163. Procedure update_time(ForcedUpdate:BOOLEAN);
  164. Begin
  165. With time Do
  166. Begin
  167. gettime(hr,min,sec,sec100);
  168. If sec<>o_sec Then
  169. Begin
  170. inc(a_sec);
  171. If a_sec<=60 Then update_secs;
  172. End;
  173. If a_sec>60 Then
  174. Begin
  175. a_sec := 0;
  176. inc(a_min);
  177. ForcedUpdate:=TRUE;
  178. End;
  179. IF ForcedUpdate THEN
  180. BEGIN
  181. Update_secs;
  182. showpic(606,453,colon);
  183. NumberOutput(606,453,time.a_min,TRUE);
  184. END;
  185. o_hr := hr;
  186. o_min := min;
  187. o_sec := sec;
  188. o_sec100 := sec;
  189. End;
  190. End;
  191. Procedure makecard(x,y:byte);
  192. Var xp,yp: integer;
  193. Begin
  194. hidemouse;
  195. xp := ((x-1)*63);
  196. yp := ((y-1)*56);
  197. setcolor(card_border);
  198. setfillstyle(1,0);
  199. bar(xp+1,yp+1,xp+62,yp+55);
  200. rectangle(xp,yp,xp+63,yp+56);
  201. If b[x,y].exposed=false Then
  202. Begin
  203. showpic(xp+1,yp+1,back);
  204. End;
  205. showmouse;
  206. If b[x,y].exposed=true Then
  207. Begin
  208. hidemouse;
  209. showpic(xp+7,yp+4,pictureenum(ORD(b[x,y].pic)+ORD(p1)-1));
  210. showmouse;
  211. End;
  212. End;
  213. Function used(pic:byte): byte;
  214. Var cx,cy,u: byte;
  215. Begin
  216. used := 0;
  217. u := 0;
  218. cy := 1;
  219. Repeat
  220. cx := 1;
  221. Repeat
  222. If b[cx,cy].pic=pic Then inc(u);
  223. inc(cx);
  224. Until cx>nox;
  225. inc(cy);
  226. Until cy>noy;
  227. used := u;
  228. End;
  229. Procedure set_board;
  230. CONST Outstr=#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+
  231. #219+#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+#219+
  232. #219+#219+#219+#219;
  233. Var cx,cy,pic: byte;
  234. Begin
  235. setcolor(0);
  236. outtextxy(0,470,OutStr);
  237. setcolor(green);
  238. outtextxy(0,470,'Dealing board, please wait...');
  239. Delay(1000);
  240. cy := 1;
  241. Repeat
  242. cx := 1;
  243. Repeat
  244. Repeat
  245. pic := random(20)+1;
  246. Until used(pic)<4;
  247. b[cx,cy].pic := pic;
  248. makecard(cx,cy);
  249. inc(cx);
  250. Until cx>nox;
  251. inc(cy);
  252. Until cy>noy;
  253. setcolor(0);
  254. outtextxy(0,470,OutStr);
  255. End;
  256. Procedure fire_works;
  257. Const
  258. nof = 30;
  259. Type
  260. fires = Record
  261. x,y: Longint;
  262. direct: longint;
  263. speed: Longint;
  264. explode: boolean;
  265. color: byte;
  266. oex: longint;
  267. End;
  268. Var fire: array[1..nof] Of fires;
  269. Procedure clean_fires;
  270. Var c: longint;
  271. Begin
  272. c := 1;
  273. Repeat
  274. fire[c].direct := random(2)+1;
  275. fire[c].color := random(15)+1;
  276. fire[c].x := random(639);
  277. fire[c].y := 479;
  278. fire[c].explode := false;
  279. fire[c].speed := random(20)+15;
  280. fire[c].oex := 1;
  281. inc(c);
  282. Until c>nof;
  283. End;
  284. Procedure inact;
  285. Var c: longint;
  286. Begin
  287. c := 1;
  288. Repeat
  289. If fire[c].explode=false Then
  290. Begin
  291. setcolor(fire[c].color);
  292. circle(fire[c].x,fire[c].y,1);
  293. End;
  294. If (fire[c].explode=true) And (fire[c].oex<10) Then
  295. Begin
  296. setcolor(fire[c].color);
  297. circle(fire[c].x,fire[c].y,fire[c].oex);
  298. setcolor(random(15)+1);
  299. circle(fire[c].x,fire[c].y,fire[c].oex-1);
  300. End;
  301. inc(c);
  302. Until c>nof;
  303. delay(75);
  304. gotoxy(1,1);
  305. c := 1;
  306. Repeat
  307. setcolor(0);
  308. circle(fire[c].x,fire[c].y,1);
  309. If (fire[c].explode=true) And (fire[c].oex<10) Then
  310. Begin
  311. circle(fire[c].x,fire[c].y,fire[c].oex);
  312. circle(fire[c].x,fire[c].y,fire[c].oex-1);
  313. inc(fire[c].oex);
  314. End;
  315. If fire[c].explode=false Then
  316. Begin
  317. dec(fire[c].speed,1);
  318. dec(fire[c].y,fire[c].speed);
  319. If fire[c].direct=1 Then inc(fire[c].x,2);
  320. If fire[c].direct=2 Then dec(fire[c].x,2);
  321. If fire[c].speed<=(-1*LONGINT(random(11))) Then
  322. fire[c].explode := true;
  323. End;
  324. inc(c);
  325. Until c>nof;
  326. c := 1;
  327. End;
  328. Function exploded: boolean;
  329. Var c: longint;
  330. m: boolean;
  331. Begin
  332. c := 1;
  333. m := true;
  334. Repeat
  335. If fire[c].oex<6 Then m := false;
  336. inc(c);
  337. Until (c>nof);
  338. exploded := m;
  339. End;
  340. Begin
  341. cleardevice;
  342. Repeat
  343. clean_fires;
  344. Repeat
  345. inact;
  346. Until (exploded=true) Or (keypressed);
  347. Until keypressed;
  348. End;
  349. Procedure win;
  350. Var m,s: string;
  351. I,J : LONGINT;
  352. Begin
  353. hidemouse;
  354. fire_works;
  355. cleardevice;
  356. closegraph;
  357. textmode(co80+font8x8);
  358. clrscr;
  359. I:=SlipInScore(Turns);
  360. GotoXY(1,23);
  361. Writeln('Game Over, turns needed = ',Turns);
  362. FOR J:=9 TO 22 DO
  363. BEGIN
  364. GotoXY(20,J);
  365. Write(' ':38);
  366. END;
  367. IF I<>0 THEN
  368. BEGIN
  369. ShowHighScore;
  370. InputStr(S,20,21-I,10,FALSE,AlfaBeta);
  371. IF Length(S)<12 THEN
  372. BEGIN
  373. str(time.a_min,m);
  374. S:=S+'['+m+':';
  375. str(time.a_sec,m);
  376. S:=S+'m'+']';
  377. END;
  378. HighScore[I-1].Name:=S;
  379. END;
  380. ShowHighScore;
  381. ginit640x480x16(bgidirec);
  382. off := false;
  383. clean_board;
  384. set_board;
  385. turns := 0;
  386. showpic(0,450,score);
  387. showpic(80,450,score_b);
  388. showpic(150,450,exit_b);
  389. showpic(569,450,score);
  390. showturn(0,0);
  391. exit1 := false;
  392. get_original_time;
  393. update_time(True);
  394. SetMousePosition(0,0);
  395. showmouse;
  396. End;
  397. Procedure show_scores;
  398. Var x,y,c: byte;
  399. Begin
  400. hidemouse;
  401. y := 1;
  402. Repeat
  403. x := 1;
  404. showpic(x+135,(y-1)*21,score);
  405. showpic(x,(y-1)*21,score);
  406. showpic(x+204,(y-1)*21,score);
  407. Repeat
  408. showpic(((x-1)*10)+3,(y-1)*21,chunk);
  409. inc(x);
  410. Until x>20;
  411. inc(y);
  412. Until y>10;
  413. c := 0;
  414. Repeat
  415. If HighScore[c].name<>'' Then
  416. Begin
  417. setcolor(white);
  418. outtextxy(4,7+(c*21),HighScore[c].name);
  419. turns := HighScore[c].Score;
  420. showturn(211,3+(c*21));
  421. End;
  422. inc(c);
  423. Until c>9;
  424. turns := 0;
  425. gotoxy(1,1);
  426. readln;
  427. off := false;
  428. clean_board;
  429. set_board;
  430. turns := 0;
  431. showpic(0,450,score);
  432. showpic(80,450,score_b);
  433. showpic(150,450,exit_b);
  434. showpic(569,450,score);
  435. showturn(0,0);
  436. exit1 := false;
  437. get_original_time;
  438. update_time(True);
  439. SetMousePosition(0,0);
  440. showmouse;
  441. End;
  442. Procedure interpret;
  443. Var mpx,mpy: byte;
  444. ms_mx,ms_my,ms_but : LONGINT;
  445. Begin
  446. GetMouseState(ms_mx,ms_my,ms_but);
  447. ms_mx:=ms_mx shr 1;;
  448. If ms_but=0 Then off := false;
  449. If ((ms_but AND 1)=1) And (off=false) Then
  450. Begin
  451. off := true;
  452. mpx := ms_mx*2 Div 63;
  453. mpy := (ms_my) Div 56;
  454. If (ms_mx*2>=80) And (ms_mx*2<=129) And (ms_my>=450) And (ms_my<=466)
  455. And (ok=true) Then show_scores;
  456. If (ms_mx*2>=150) And (ms_mx*2<=199) And (ms_my>=450) And (ms_my<=466)
  457. Then
  458. Begin
  459. exit1 := true;
  460. End;
  461. inc(mpx);
  462. inc(mpy);
  463. If (b[mpx,mpy].exposed=false) And (mpx>=1) And (mpy>=1) And (mpx<=10) And (mpy<=8)
  464. Then
  465. Begin
  466. setfillstyle(1,0);
  467. bar(80,450,130,466);
  468. ok := false;
  469. b[mpx,mpy].exposed := true;
  470. makecard(mpx,mpy);
  471. inc(os);
  472. s[os].x := mpx;
  473. s[os].y := mpy;
  474. s[os].pic := b[mpx,mpy].pic;
  475. End;
  476. End;
  477. If os=4 Then
  478. Begin
  479. inc(turns);
  480. showturn(0,0);
  481. os := 0;
  482. delay(700);
  483. inc(opened);
  484. If Not((s[1].pic=s[2].pic) And (s[1].pic=s[3].pic) And (s[1].pic=s[4].pic)) Then
  485. Begin
  486. dec(opened);
  487. b[s[1].x,s[1].y].exposed := false;
  488. b[s[2].x,s[2].y].exposed := false;
  489. b[s[3].x,s[3].y].exposed := false;
  490. b[s[4].x,s[4].y].exposed := false;
  491. makecard(s[1].x,s[1].y);
  492. makecard(s[2].x,s[2].y);
  493. makecard(s[3].x,s[3].y);
  494. makecard(s[4].x,s[4].y);
  495. End;
  496. If opened=20 Then win;
  497. End;
  498. If NOT ok Then
  499. update_time(FALSE);
  500. End;
  501. Procedure load_pics(PicBuf:PByte);
  502. {loads picture structures from disc}
  503. VAR F : File;
  504. Buf1Ind,
  505. I,J,K : LONGINT;
  506. TData : PByte;
  507. Begin
  508. GetMem(TData,ComprBufferSize); { allocate buffer}
  509. Assign(F,Picsfilename); { Open file}
  510. {$I-}
  511. Reset(F,1);
  512. {$I+}
  513. If ioresult<>0 Then
  514. BEGIN
  515. TextMode(CO80);
  516. Writeln('Fatal error, couldn''t find graphics data file quaddata.dat');
  517. HALT;
  518. END;
  519. {Read the array with picture information; (X,Y dimensions and offset in
  520. binary data)}
  521. BlockRead(F,pics,SIZEOF(Picture)*(ORD(p20)-ORD(zero)+1),I);
  522. {Read some slackspace which shouldn't be in the file ;-)}
  523. blockread(F,TData[0],6,Buf1ind);
  524. {Read the real, RLE'ed graphics data}
  525. BlockRead(F,TData[0],ComprBufferSize,Buf1Ind);
  526. Close(F);
  527. {Expand the RLE data. Of each byte, the high nibble is the count-1, low
  528. nibble is the value}
  529. I:=0; J:=0;
  530. REPEAT
  531. K:=(TData[I] SHR 4) +1;
  532. FillChar(PicBuf[J],K,TData [I] AND 15);
  533. INC(J,K);
  534. INC(I);
  535. UNTIL I>=Buf1Ind;
  536. {Release the temporary buffer (the compressed data isn't necesary anymore)}
  537. Freemem(TData,ComprBufferSize);
  538. End;
  539. Procedure clean;
  540. VAR I : LONGINT;
  541. Begin
  542. Randomize; {Initialize random generator}
  543. Negative:=TRUE; {Higher highscore is worse}
  544. HighX:=20; HighY:=9; {coordinates for highscores}
  545. GetMem(PicData,PicBufferSize); {Allocate room for pictures}
  546. load_pics(PicData); {Load picture data from file}
  547. FOR I:=0 TO 9 DO {Create default scores}
  548. HighScore[I].Score:=-100*I; {Negative, because then the
  549. "highest" score is best}
  550. LoadHighScore(ScoreFileName); {Try to load highscore file}
  551. closegraph;
  552. bgidirec := 'd:\prog\bp\bgi';
  553. ginit640x480x16(bgidirec);
  554. setcolor(card_border);
  555. ok := true;
  556. opened := 0;
  557. os := 0;
  558. s[1].x := 0;
  559. s[2].x := 0;
  560. s[3].x := 0;
  561. off := false;
  562. clean_board;
  563. set_board;
  564. turns := 0;
  565. showpic(0,450,score); showpic(80,450,score_b);
  566. showpic(150,450,exit_b); showpic(569,450,score);
  567. showturn(0,0);
  568. exit1 := false;
  569. SetMousePosition(0,0);
  570. get_original_time;
  571. update_time(True);
  572. showmouse;
  573. End;
  574. Begin
  575. clean;
  576. Repeat
  577. interpret;
  578. Until exit1=true;
  579. closegraph;
  580. textmode(co80);
  581. Freemem(PicData,PicBufferSize);
  582. clrscr;
  583. SaveHighScore;
  584. Writeln('Thanks for playing Quadruple Memory');
  585. Writeln('Feel free to distribute this software.');
  586. Writeln;
  587. Writeln('Programmed by: Justin Pierce');
  588. Writeln('Graphics by: Whitney Pierce');
  589. Writeln('Inspired by: Jos Dickman''s triple memory!');
  590. Writeln('FPC conversion and cleanup by Marco van de Voort');
  591. Writeln;
  592. End.