4 * X version by kirk johnson october 1990
5 * Amiga version by Loren J. Rittle Sun Feb 24 06:17:30 1991
6 * Aris, this ones for you...
7 * ...when do I get my pizza :-)
9 * It only took 4-5 hours to port from X, I did it on a dare!
10 * No Copyright N© 1991 Loren J. Rittle. No rights reserved.
11 * Some code generated via PowerWindows 2.5.
12 * I also used their PD event shell as a starting point.
14 * Original UseNet post header:
15 * Path: news.larc.nasa.gov!elroy.jpl.nasa.gov!usc!cs.utexas.edu!sun-barr!newstop!exodus!kanchenjunga.LCS.MIT.EDU
16 * From: tuna@kanchenjunga.LCS.MIT.EDU (Kirk 'UhOh' Johnson)
17 * Newsgroups: comp.sources.x
18 * Subject: v11i083: mosaic, Part01/01
19 * Message-ID: <8101@exodus.Eng.Sun.COM>
20 * Date: 17 Feb 91 19:12:47 GMT
21 * Sender: news@exodus.Eng.Sun.COM
23 * Approved: argv@sun.com
25 * Submitted-by: tuna@kanchenjunga.LCS.MIT.EDU (Kirk 'UhOh' Johnson)
26 * Posting-number: Volume 11, Issue 83
27 * Archive-name: mosaic/part01
29 * Thanks to Kirk for releasing such a nice simple game program with source...
30 * Hard Drive Installable and Multitasks, thus better than any psygnosis game...
33 #include <aros/oldprograms.h>
34 #include <exec/types.h>
36 #include <exec/memory.h>
37 #include <libraries/dos.h>
38 #include <intuition/intuition.h>
39 #include <graphics/gfxmacros.h>
46 struct IntuitionBase
*IntuitionBase
= NULL
;
47 struct GfxBase
*GfxBase
= NULL
;
49 SHORT BorderVectors1
[] =
58 struct Border Border1
=
67 struct IntuiText IText1
=
76 struct Gadget Gadget1
=
93 struct IntuiText IText2
=
102 struct NewWindow NewWindowStructure1
=
107 MOUSEBUTTONS
+ MOUSEMOVE
+ GADGETUP
+ CLOSEWINDOW
+ RAWKEY
,
108 WINDOWDRAG
+ WINDOWDEPTH
+ REPORTMOUSE
+ WINDOWCLOSE
+ ACTIVATE
+ NOCAREREFRESH
,
111 "Mosaic, Amiga Version by Loren J. Rittle\0Sun Feb 24 04:36:18 1991",
119 struct NewWindow NewWindowStructure2
=
125 WINDOWDRAG
+ WINDOWDEPTH
+ NOCAREREFRESH
,
136 char *ScoreFile
= "mosaic.scores";
138 Word tile
[NTiles
]; /* the board */
139 Word piece
[NPieces
]; /* the "deck" of pieces */
140 Word nextpiece
; /* index into the deck */
142 Word size
[NTiles
]; /* score data structures */
145 Word tscore
[3]; /* total score */
146 Word pscore
[3]; /* last piece score */
147 Word remain
[3]; /* tiles remaining */
149 static char buf
[256];
151 NameAndScore highscore
[NHighScores
];
159 BPTR SpeakFH
= BNULL
;
161 struct Window
*wG
= NULL
;
162 struct RastPort
*rpG
;
164 struct Window
*wS
= NULL
;
165 struct RastPort
*rpS
;
167 #define BoundVarVal(var, min, max) \
171 else if ((var) > (max)) \
176 {0x1111, 0x4444, 0x1111, 0x4444, 0x1111, 0x4444, 0x1111, 0x4444};
179 {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
181 int main (int argc
, char **argv
)
189 struct IntuiMessage
*message
;
191 IntuitionBase
= (struct IntuitionBase
*)OpenLibrary ("intuition.library", 0);
192 GfxBase
= (struct GfxBase
*)OpenLibrary ("graphics.library", 0);
193 if (!IntuitionBase
|| !GfxBase
)
194 fatal ("Can't open Intuition and/or Graphics Library.");
196 wG
= OpenWindow (&NewWindowStructure1
);
198 fatal ("Can't open a window.");
201 wS
= OpenWindow (&NewWindowStructure2
);
203 fatal ("Can't open a window.");
207 /* struct Process* proc = (struct Process *)FindTask(0L); */
208 /* APTR temp = proc->pr_WindowPtr; */
210 /* proc->pr_WindowPtr = (APTR)-1L; */
211 SpeakFH
= Open ("speak:", MODE_NEWFILE
);
212 /* proc->pr_WindowPtr = temp; */
216 PrintIText (rpG
, &IText2
, 0, 0);
224 SetAfPt (rpG
, (void *) backfill
, 3);
225 RectFill (rpG
, 20, 14, 24 * 14 + 20, 24 * 7 + 14);
228 for (x
= 0; x
< 25; x
++)
230 Move (rpG
, x
* 14 + 20, 14);
231 Draw (rpG
, x
* 14 + 20, 24 * 7 + 14);
234 for (y
= 0; y
< 25; y
++)
236 Move (rpG
, 20, y
* 7 + 14);
237 Draw (rpG
, 24 * 14 + 20, y
* 7 + 14);
242 WaitPort (wG
->UserPort
);
243 while ((message
= (struct IntuiMessage
*) GetMsg (wG
->UserPort
)) != NULL
)
245 code
= message
->Code
;
246 object
= message
->IAddress
;
247 class = message
->Class
;
248 MouseX
= message
->MouseX
;
249 MouseY
= message
->MouseY
;
250 ReplyMsg ((struct Message
*) message
);
251 if (class == CLOSEWINDOW
)
254 * This is very kludgy, don't follow this example of how to read
255 * keys... This is a quick hack to allow the 'a' for auto play
256 * feature to work. Try it, you may hate it! Because, the
257 * AutoPlay() function is not too smart. LJR
259 if ((class == RAWKEY
) && (code
== 32))
261 /* Here again, quick hack to support open/closing of
262 * score window via 's'. LJR
264 if ((class == RAWKEY
) && (code
== 33))
268 wS
= OpenWindow (&NewWindowStructure2
);
270 fatal ("Can't open a window.");
280 if (class == MOUSEMOVE
)
281 MoveBox (MouseX
, MouseY
);
282 if (class == MOUSEBUTTONS
) {
285 if ((highlitXonDown
== highlitX
) &&
286 (highlitYonDown
== highlitY
))
288 if ((nextpiece
< NPieces
) &&
289 (DropPiece (highlitY
, highlitX
, piece
[nextpiece
])))
294 if (nextpiece
== NPieces
)
302 Write (SpeakFH
, "No Way!", 7);
304 /* DisplayBeep (NULL) */;
308 Write (SpeakFH
, "Un-do!", 7);
310 /* DisplayBeep (NULL) */;
314 highlitXonDown
= highlitX
;
315 highlitYonDown
= highlitY
;
318 if ((class == GADGETUP
) || (class == GADGETDOWN
))
319 if (object
== (void *) &Gadget1
)
327 MoveBox (int MouseX
, int MouseY
)
330 int newX
= (MouseX
- 27) / 14;
331 int newY
= (MouseY
- 17) / 7;
333 BoundVarVal (newX
, 0, 22);
334 BoundVarVal (newY
, 0, 22);
336 if ((newX
== highlitX
) && (newY
== highlitY
))
340 for (x
= highlitX
; x
< highlitX
+ 3; x
++)
342 Move (rpG
, x
* 14 + 20, highlitY
* 7 + 14);
343 Draw (rpG
, x
* 14 + 20, highlitY
* 7 + 14 + 14);
346 for (y
= highlitY
; y
< highlitY
+ 3; y
++)
348 Move (rpG
, highlitX
* 14 + 20, y
* 7 + 14);
349 Draw (rpG
, highlitX
* 14 + 20 + 28, y
* 7 + 14);
352 SetAfPt (rpG
, (void *) backfill
, 3);
354 if (!tile
[highlitY
* BoardSize
+ highlitX
])
355 RectFill (rpG
, highlitX
* 14 + 21, highlitY
* 7 + 15, (highlitX
+1) * 14 + 19, (highlitY
+1) * 7 + 13);
356 if (!tile
[highlitY
* BoardSize
+ highlitX
+ 1])
357 RectFill (rpG
, (highlitX
+1) * 14 + 21, highlitY
* 7 + 15, (highlitX
+2) * 14 + 19, (highlitY
+1) * 7 + 13);
358 if (!tile
[(highlitY
+ 1) * BoardSize
+ highlitX
])
359 RectFill (rpG
, highlitX
* 14 + 21, (highlitY
+1) * 7 + 15, (highlitX
+1) * 14 + 19, (highlitY
+2) * 7 + 13);
360 if (!tile
[(highlitY
+ 1) * BoardSize
+ highlitX
+ 1])
361 RectFill (rpG
, (highlitX
+1) * 14 + 21, (highlitY
+1) * 7 + 15, (highlitX
+2) * 14 + 19, (highlitY
+2) * 7 + 13);
363 if (nextpiece
== NPieces
)
365 highlitX
= highlitY
= 0;
372 for (x
= highlitX
; x
< highlitX
+ 3; x
++)
374 Move (rpG
, x
* 14 + 20, highlitY
* 7 + 14);
375 Draw (rpG
, x
* 14 + 20, highlitY
* 7 + 14 + 14);
378 for (y
= highlitY
; y
< highlitY
+ 3; y
++)
380 Move (rpG
, highlitX
* 14 + 20, y
* 7 + 14);
381 Draw (rpG
, highlitX
* 14 + 20 + 28, y
* 7 + 14);
384 SetAfPt (rpG
, (void *) solid
, 3);
385 if (!tile
[highlitY
* BoardSize
+ highlitX
])
387 SetAPen (rpG
, piece
[nextpiece
] & 0x0003);
388 RectFill (rpG
, highlitX
* 14 + 21, highlitY
* 7 + 15, (highlitX
+1) * 14 + 19, (highlitY
+1) * 7 + 13);
390 if (!tile
[highlitY
* BoardSize
+ highlitX
+ 1])
392 SetAPen (rpG
, (piece
[nextpiece
] & 0x000C)>>2);
393 RectFill (rpG
, (highlitX
+1) * 14 + 21, highlitY
* 7 + 15, (highlitX
+2) * 14 + 19, (highlitY
+1) * 7 + 13);
395 if (!tile
[(highlitY
+ 1) * BoardSize
+ highlitX
])
397 SetAPen (rpG
, (piece
[nextpiece
] & 0x0030)>>4);
398 RectFill (rpG
, highlitX
* 14 + 21, (highlitY
+1) * 7 + 15, (highlitX
+1) * 14 + 19, (highlitY
+2) * 7 + 13);
400 if (!tile
[(highlitY
+ 1) * BoardSize
+ highlitX
+ 1])
402 SetAPen (rpG
, (piece
[nextpiece
] & 0x00C0)>>6);
403 RectFill (rpG
, (highlitX
+1) * 14 + 21, (highlitY
+1) * 7 + 15, (highlitX
+2) * 14 + 19, (highlitY
+2) * 7 + 13);
417 CloseLibrary ((struct Library
*)GfxBase
);
418 if (IntuitionBase
!= NULL
)
419 CloseLibrary ((struct Library
*)IntuitionBase
);
427 fprintf (stderr
, "%s: warning! %s\n", AppName
, msg
);
435 fprintf (stderr
, "%s: %s\n", AppName
, msg
);
440 ReadHighScores (void)
445 s
= fopen (ScoreFile
, "r");
448 warning ("unable to open score file; creating new one");
450 for (i
= 0; i
< NHighScores
; i
++)
452 strcpy (highscore
[i
].uname
, ".");
453 highscore
[i
].score
= -1;
460 for (i
= 0; i
< NHighScores
; i
++)
463 if (sscanf (buf
, "%s %d",
464 highscore
[i
].uname
, &highscore
[i
].score
) != 2)
465 fatal ("incomplete score file read");
473 WriteHighScores (void)
478 s
= fopen (ScoreFile
, "w");
480 fatal ("unable to open score file");
482 for (i
= 0; i
< NHighScores
; i
++)
483 fprintf (s
, "%s %d\n", highscore
[i
].uname
, highscore
[i
].score
);
489 CheckHighScore (void)
495 uname
= NULL
/* getenv ("USERNAME") */;
497 uname
= "Unknown_Puzzle_Solver";
498 score
= tscore
[0] + tscore
[1] + tscore
[2];
501 * note that we don't actually try to do any locking of the high score
502 * file during this critical section ...
507 for (i
= 0; i
< NHighScores
; i
++)
508 if (strcmp (highscore
[i
].uname
, uname
) == 0)
511 if (i
== NHighScores
)
514 if (score
> highscore
[i
].score
)
516 while ((i
> 0) && (score
> highscore
[i
- 1].score
))
518 strcpy (highscore
[i
].uname
, highscore
[i
- 1].uname
);
519 highscore
[i
].score
= highscore
[i
- 1].score
;
522 strcpy (highscore
[i
].uname
, uname
);
523 highscore
[i
].score
= score
;
529 Write (SpeakFH
, "Congratulations!", 16);
530 Write (SpeakFH
, "You got a hi score.", 19);
533 /* DisplayBeep (NULL) */;
543 while (nextpiece
< NPieces
)
547 r
= rand () % (BoardSize
- 1);
548 c
= rand () % (BoardSize
- 1);
550 while (!DropPiece (r
, c
, piece
[nextpiece
]));
555 if (nextpiece
== NPieces
)
564 UpdateAndScore (int r
, int c
, Word score
[])
568 i
= r
* BoardSize
+ c
;
570 PossiblyMerge (i
, i
+ 1);
571 PossiblyMerge (i
+ BoardSize
, i
+ BoardSize
+ 1);
573 PossiblyMerge (i
, i
+ BoardSize
);
574 PossiblyMerge (i
+ 1, i
+ BoardSize
+ 1);
578 PossiblyMerge (i
, i
- 1);
579 PossiblyMerge (i
+ BoardSize
, i
+ BoardSize
- 1);
583 PossiblyMerge (i
, i
- BoardSize
);
584 PossiblyMerge (i
+ 1, i
- BoardSize
+ 1);
586 if (c
<= (BoardSize
- 3))
588 PossiblyMerge (i
+ 1, i
+ 2);
589 PossiblyMerge (i
+ BoardSize
+ 1, i
+ BoardSize
+ 2);
591 if (r
<= (BoardSize
- 3))
593 PossiblyMerge (i
+ BoardSize
, i
+ (2 * BoardSize
));
594 PossiblyMerge (i
+ BoardSize
+ 1, i
+ (2 * BoardSize
) + 1);
596 /* compute the new score */
597 for (i
= 0; i
< 3; i
++)
599 for (i
= 0; i
< NTiles
; i
++)
600 if ((tile
[i
] != 0) && (parent
[i
] == i
))
601 score
[tile
[i
] - 1] += size
[i
] * size
[i
];
605 PossiblyMerge (int i
, int j
)
611 /* tiles are not the same color */
612 if (tile
[i
] != tile
[j
])
617 while (parent
[irep
] != irep
)
620 /* compress path from i to irep */
622 while (parent
[scan
] != scan
)
630 while (parent
[jrep
] != jrep
)
633 /* compress path from j to jrep */
635 while (parent
[scan
] != scan
)
641 /* tiles are already in the same set */
646 if (size
[irep
] > size
[jrep
])
649 size
[irep
] += size
[jrep
];
654 size
[jrep
] += size
[irep
];
659 DropPiece (int r
, int c
, Word p
)
665 idx
= r
* BoardSize
+ c
;
667 /* check for illegal move */
668 if ((tile
[idx
] != 0) ||
669 (tile
[idx
+ 1] != 0) ||
670 (tile
[idx
+ BoardSize
] != 0) ||
671 (tile
[idx
+ BoardSize
+ 1] != 0))
674 /* place the piece */
677 remain
[type
- 1] -= 1;
681 tile
[idx
+ 1] = type
;
682 remain
[type
- 1] -= 1;
686 tile
[idx
+ BoardSize
] = type
;
687 remain
[type
- 1] -= 1;
691 tile
[idx
+ BoardSize
+ 1] = p
& 0x03;
692 remain
[type
- 1] -= 1;
694 /* update the score */
695 UpdateAndScore (r
, c
, nscore
);
696 for (idx
= 0; idx
< 3; idx
++)
698 pscore
[idx
] = nscore
[idx
] - tscore
[idx
];
699 tscore
[idx
] = nscore
[idx
];
719 srand ((int) time (NULL
));
721 /* clear the board */
722 for (i
= 0; i
< NTiles
; i
++)
727 for (i
= 1; i
<= 3; i
++)
728 for (j
= 1; j
<= 3; j
++)
729 for (k
= 1; k
<= 3; k
++)
730 for (l
= 1; l
<= 3; l
++)
731 piece
[idx
++] = (i
<< 6) | (j
<< 4) | (k
<< 2) | (l
<< 0);
734 for (i
= 0; i
< 1000; i
++)
736 idx
= rand () % NPieces
;
738 piece
[idx
] = piece
[0];
743 /* clear score data structures */
744 for (i
= 0; i
< NTiles
; i
++)
750 for (i
= 0; i
< 3; i
++)
754 remain
[i
] = (NPieces
* 4) / 3;
760 drawTile (int r
, int c
)
767 SetAfPt (rpG
, (void *) solid
, 3);
768 SetAPen (rpG
, tile
[r
* BoardSize
+ c
]);
769 RectFill (rpG
, x
+ 1, y
+ 1, x
+ 13, y
+ 6);
773 drawHighScores (void)
778 for (i
= 0; i
< NHighScores
; i
++)
779 if (highscore
[i
].score
> 0)
781 sprintf (buf
, "%-24s %5d", highscore
[i
].uname
, highscore
[i
].score
);
782 Move (rpG
, 50, 30 + i
* 14);
783 Text (rpG
, buf
, strlen (buf
));
790 int p
= (nextpiece
< NPieces
) ? piece
[nextpiece
] : 0;
791 int x
= 26 * 14 + 20;
794 SetAfPt (rpG
, (void *) solid
, 3);
795 SetAPen (rpG
, p
& 0x03);
796 RectFill (rpG
, x
+ 1, y
+ 1, x
+ 13, y
+ 6);
798 SetAPen (rpG
, p
& 0x03);
799 RectFill (rpG
, x
+ 15, y
+ 1, x
+ 27, y
+ 6);
801 SetAPen (rpG
, p
& 0x03);
802 RectFill (rpG
, x
+ 1, y
+ 8, x
+ 13, y
+ 13);
804 SetAPen (rpG
, p
& 0x03);
805 RectFill (rpG
, x
+ 15, y
+ 8, x
+ 27, y
+ 13);
818 Text (rpS
, "to play:", 8);
821 for (i
= 0; i
< 3; i
++)
824 sprintf (buf
, "%5d ", remain
[i
]);
825 Text (rpS
, buf
, strlen (buf
));
830 Text (rpS
, "total:", 6);
834 for (i
= 0; i
< 3; i
++)
838 sprintf (buf
, "%5d ", tscore
[i
]);
839 Text (rpS
, buf
, strlen (buf
));
843 sprintf (buf
, "%5d", total
);
845 Text (rpS
, buf
, strlen (buf
));
848 Text (rpS
, "piece:", 6);
852 for (i
= 0; i
< 3; i
++)
856 sprintf (buf
, "%5d ", pscore
[i
]);
857 Text (rpS
, buf
, strlen (buf
));
861 sprintf (buf
, "%5d", total
);
863 Text (rpS
, buf
, strlen (buf
));