Paul DuBois
unread,Feb 1, 1987, 2:00:05 AM2/1/87You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# BlobDemo/DemoStates.c
# BlobDemo/DemoSwap.c
# BlobDemo/DemoToh.c
# BlobDemo/DemoTtt.c
# BlobDemo/DemoWind.c
mkdir BlobDemo
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoStates.c
X/*
X Blob Manager Demonstration: States and Capitals module
X
X This module is an example of an extremely simple interrogative
X scenario. The original thirteen colonies of the United States must
X be matched with their capital cities. There is a single button that
X says "Give Up?" If the user clicks the button, the answer is shown,
X the button's title changes to "Resume", and the scenario is frozen
X until the button is clicked. Then the answer is cleared, the capitals
X are shuffled, and the user may start over.
X
X If the correct answers are all gotten, the button again changes to
X "Resume" and the scenario is frozen until the button is clicked.
X
X The module is unexciting; it's meant as a basic illustration, rather
X than anything useful. There are lots of bells and whistles that
X could be added.
X
X 26 July 1986 Paul DuBois
X*/
X
X
X# include "BlobDemo.h"
X# include <ControlMgr.h>
X
X
X# define nStates 13
X
X# define hState1 220
X# define hState2 110
X# define vState 16
X# define stateXOff 10
X# define stateYOff 5
X# define hCapital 85
X# define vCapital 16
X# define capXOff 225
X# define capYOff 5
X
X
Xstruct info
X{
X char *stateName;
X char *capName;
X};
X
X
X
Xstatic GrafPtr statesPort;
Xstatic BlobSetHandle donors; /* donor blobs */
Xstatic BlobSetHandle receptors; /* receptor blobs */
Xstatic ControlHandle giveUp;
Xstatic Boolean paused = false;
X
Xstatic struct info scPair[nStates] =
X{
X { "\pConnecticut", "\pHartford" },
X { "\pDelaware", "\pDover" },
X { "\pGeorgia", "\pAtlanta" },
X { "\pMaryland", "\pAnnapolis" },
X { "\pMassachusetts", "\pBoston" },
X { "\pNew Hampshire", "\pConcord" },
X { "\pNew Jersey", "\pTrenton" },
X { "\pNorth Carolina", "\pRaleigh" },
X { "\pNew York", "\pAlbany" },
X { "\pPennsylvania", "\pHarrisburg" },
X { "\pRhode Island", "\pProvidence" },
X { "\pSouth Carolina", "\pColumbia" },
X { "\pVirginia", "\pRichmond" }
X};
X
X
Xstatic Activate (active)
XBoolean active;
X{
X if (active)
X {
X SetDragRects (statesPort);
X SetBCPermissions (true, true, false, true, true);
X }
X}
X
X
Xstatic Update ()
X{
X DrawControls (statesPort);
X DrawBlobSet (receptors);
X DrawBlobSet (donors);
X}
X
X
Xstatic Mouse (pt, t, mods)
XPoint pt;
Xlong t;
Xint mods;
X{
XBlobHandle b, d;
XControlHandle ctl;
X
X if (FindControl (pt, statesPort, &ctl))
X {
X if (TrackControl (ctl, pt, nil))
X {
X if (paused) /* either all answers are correct, or we're */
X { /* showing the answer. Either way, restore */
X ThawBlobSet (receptors); /* to start state */
X ThawBlobSet (donors);
X ZUnglueGlobSet (receptors);
X ShuffleBlobSet (receptors);
X ShuffleBlobSet (donors);
X SetCTitle (giveUp, "\pGive Up?");
X ValidRect (&statesPort->portRect);
X paused = false;
X }
X else /* user gives up - show answer */
X {
X for (b = FirstBlob (receptors); b != nil; b = NextBlob (b))
X ZGlueGlob (FirstBMatch (b), b);
X FreezeBlobSet (receptors);
X FreezeBlobSet (donors);
X SetCTitle (giveUp, "\pResume");
X paused = true;
X }
X }
X }
X else
X {
X BlobClick (pt, t, donors, receptors);
X if (!paused && BlobSetQuiet (receptors)) /* answers correct? */
X {
X FreezeBlobSet (receptors);
X FreezeBlobSet (donors);
X SetCTitle (giveUp, "\pResume");
X paused = true;
X }
X }
X}
X
X
X/*
X Make blobs
X*/
X
X
XMakeBlobs ()
X{
Xint i;
XRect r, r2;
XBlobHandle b1, b2;
X
X donors = NewBlobSet ();
X receptors = NewBlobSet ();
X for (i = 0; i < nStates; ++i)
X {
X b1 = NewBlob (donors, false, 1, false, 0L);
X b2 = NewBlob (receptors, false, 0, true, 0L);
X NewBlobMatch (b1, b2); /* attach the answer */
X
X OpenBlob (); /* draw donor blob */
X SetRect (&r, 0, 0, hCapital, vCapital);
X TextBox (&scPair[i].capName[1], (long) scPair[i].capName[0], &r, 1);
X CloseRectBlob (b1, &r, &r);
X MoveBlob (b1, inFullBlob, capXOff, capYOff + (vCapital + 1) * i);
X
X OpenBlob ();
X SetRect (&r, 0, 0, hState1, vState);
X SetRect (&r2, 0, 0, hState2, vState);
X TextBox (&scPair[i].stateName[1], (long) scPair[i].stateName[0], &r2, 1);
X SetRect (&r2, 0, 0, hCapital, vCapital);
X OffsetRect (&r2, hState2 + 5, 0);
X EraseRect (&r2);
X FrameRect (&r2);
X CloseRectBlob (b2, &r2, &r);
X MoveBlob (b2, inFullBlob, stateXOff, stateYOff + (vState + 2) * i);
X }
X ShuffleBlobSet (donors);
X EnableBlobSet (receptors);
X EnableBlobSet (donors);
X}
X
X
XStatesInit ()
X{
XRect r;
X
X SkelWindow (statesPort = GetDemoWind (statesWindRes),
X Mouse, /* mouse clicks */
X nil, /* key clicks */
X Update, /* updates */
X Activate, /* activate/deactivate events */
X nil, /* close window */
X DoWClobber, /* dispose of window */
X nil, /* idle proc */
X false); /* irrelevant, since no idle proc */
X
X/*
X Make blobs. Generally have to make donors before receptors.
X*/
X MakeBlobs ();
X
X r = statesPort->portRect;
X SetRect (&r, r.left + 5, r.bottom - 25, r.left + 75, r.bottom - 5);
X giveUp = NewControl (statesPort, &r, "\pGive Up?", true, 0, 0, 0,
X pushButProc, nil);
X
X Update ();
X ValidRect (&statesPort->portRect);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoSwap.c
X/*
X Blob Manager Demonstration: Coin Swap module
X
X This has a linear board with either 5, 7 or 9 pieces. The middle
X piece is always empty, the pieces on one end are filled with black
X coins, the pieces on the other end are filled with white coins.
X The object is to swap the coins. A coin can slide into an empty
X piece next to it, or jump over a single coin to land on an empty
X piece.
X
X A menu allows the number of coins to be chosen. To win, the coins
X have to be swapped in a specific number of moves.
X
X 26 July 1986 Paul DuBois
X*/
X
X
X# include "BlobDemo.h"
X# include <MenuMgr.h>
X
X# define vMessage 10
X# define vPiece 30
X# define maxPieces 9
X# define pieceSize 24
X# define pieceGap 1
X
X
Xstatic GrafPtr swapPort;
Xstatic MenuHandle cnfgMenu;
Xstatic BlobSetHandle donors = nil;
Xstatic BlobSetHandle receptors = nil;
Xstatic int hMid;
Xstatic Str255 statusStr = "\p";
X
Xstatic int nPieces = 5;
Xstatic int nMoves = 8;
Xstatic BlobHandle piece[maxPieces];
Xstatic int moves;
Xstatic Boolean pause;
X
X
Xstatic StatusMesg (s)
XStr255 s;
X{
XRect r;
X
X SetRect (&r, hMid - 60, vMessage, hMid + 60, vMessage+16);
X TextBox (s+1, (long) s[0], &r, 1);
X StrCpy (statusStr, s);
X}
X
X
X/*
X Reset to start state. This recreates the board each time. All the
X blobs in the board require explicit matches except the middle one.
X*/
X
Xstatic Reset ()
X{
XBlobHandle b;
XRect r;
Xint i, h;
XStr255 s;
X
X InvalRect (&swapPort->portRect); /* force update when done resetting */
X pause = false;
X moves = nMoves;
X MovesLeft (moves, s);
X StatusMesg (s);
X
X if (receptors != nil) /* clobber any existing receptor set */
X {
X HideBlobSet (receptors);
X DisposeBlobSet (receptors);
X }
X receptors = NewBlobSet ();
X
X h = hMid - (nPieces * (pieceSize + pieceGap) - pieceGap) / 2;
X for (i = 0; i < nPieces; ++i)
X {
X b = NewBlob (receptors, false, 0, i != (nPieces - 1) / 2, 0L);
X piece[i] = b;
X OpenBlob ();
X SetRect (&r, h, vPiece, h + pieceSize, vPiece + pieceSize);
X EraseRect (&r);
X FrameRect (&r);
X CloseRectBlob (b, &r, &r);
X h += pieceSize + pieceGap;
X if (i < (nPieces - 1) / 2)
X {
X GlueGlob (GetBlobHandle (donors, 0), b);
X NewBlobMatch (GetBlobHandle (donors, 1), b);
X }
X else if (i > (nPieces - 1) / 2)
X {
X GlueGlob (GetBlobHandle (donors, 1), b);
X NewBlobMatch (GetBlobHandle (donors, 0), b);
X }
X }
X EnableBlobSet (receptors);
X}
X
X
Xstatic SwapPause (msg)
XStringPtr msg;
X{
X StatusMesg (msg);
X pause = true;
X}
X
X
Xstatic Mouse (pt, t, mods)
XPoint pt;
Xlong t;
Xint mods;
X{
XStr255 s;
Xregister int i;
X
X/*
X Freeze all the pieces that can't be moved, then call BlobClick.
X*/
X for (i = 0; i < nPieces; ++i)
X {
X ThawBlob (piece[i]);
X if (BGlob (piece[i]) == nil) continue;
X if (i > 0 && BGlob (piece[i-1]) == nil) continue;
X if (i > 1 && BGlob (piece[i-2]) == nil) continue;
X if (i < nPieces - 1 && BGlob (piece[i+1]) == nil) continue;
X if (i < nPieces - 2 && BGlob (piece[i+2]) == nil) continue;
X FreezeBlob (piece[i]);
X }
X if (!pause)
X {
X BlobClick (pt, t, donors, receptors);
X if (BClickResult () == bcXfer)
X {
X if (--moves == 0)
X {
X if (BlobSetQuiet (receptors))
X SwapPause ("\pYou Win");
X else
X SwapPause ("\pYou Lose");
X }
X else
X {
X MovesLeft (moves, s);
X StatusMesg (s);
X }
X }
X }
X}
X
X
X/*
X Select configuration: 4, 6, or 8 coins (2, 3, or 4 on each side).
X If the number of coins on each side is n, the number of moves
X to solve is (n+1)^2 - 1.
X*/
XDoConfiguration (item)
Xint item;
X{
X nPieces = 2 * item + 3; /* 1->5, 2->7, 3->9 pieces */
X nMoves = (item + 2) * (item + 2) - 1;
X Reset ();
X}
X
X
Xstatic Activate (active)
XBoolean active;
X{
X if (active)
X {
X SetDragRects (swapPort);
X SetBCPermissions (false, true, false, false, false); /* xfer only */
X cnfgMenu = GetMenu (swapCnfgMenuRes);
X SkelMenu (cnfgMenu, DoConfiguration, DoMClobber);
X }
X else
X SkelRmveMenu (cnfgMenu);
X}
X
X
Xstatic Update (resized)
XBoolean resized;
X{
X DrawBlobSet (receptors);
X StatusMesg (statusStr);
X}
X
X
X/*
X Make donor blobs.
X*/
X
Xstatic MakeDonors ()
X{
XBlobHandle b;
XRect r;
X
X donors = NewBlobSet ();
X b = NewBlob (donors, false, infiniteGlue, false, 0L);
X OpenBlob ();
X SetRect (&r, 0, 0, pieceSize, pieceSize);
X EraseRect (&r);
X FrameRect (&r);
X InsetRect (&r, 2, 2);
X PaintOval (&r);
X InsetRect (&r, -2, -2);
X CloseRectBlob (b, &r, &r);
X b = NewBlob (donors, false, infiniteGlue, false, 0L);
X OpenBlob ();
X PaintRect (&r);
X InsetRect (&r, 2, 2);
X EraseOval (&r);
X InsetRect (&r, -2, -2);
X CloseRectBlob (b, &r, &r);
X}
X
X
XSwapInit ()
X{
X SkelWindow (swapPort = GetDemoWind (swapWindRes),
X Mouse, /* mouse clicks */
X nil, /* key clicks */
X Update, /* updates */
X Activate, /* activate/deactivate events */
X nil, /* close window */
X DoWClobber, /* dispose of window */
X nil, /* idle proc */
X false); /* irrelevant, since no idle proc */
X
X hMid = swapPort->portRect.right / 2;
X
X MakeDonors ();
X Reset ();
X Update ();
X ValidRect (&swapPort->portRect);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoToh.c
X/*
X Blob Manager Demonstration: Tower of Hanoi
X
X 26 July 1986 Paul DuBois
X*/
X
X# include "BlobDemo.h"
X
X
X# define xBase 17 /* upper left corner of apparatus base */
X# define yBase 130
X# define baseHeight 12 /* length is computed */
X# define slotHeight 18 /* size of disk slots */
X# define slotWidth 100
X# define slotHGap 20 /* horiz. gap between slots */
X# define slotVGap 0 /* vert. gap between slots */
X# define hExtra 20 /* extra space at ends of base */
X# define nDisks 6 /* number of disks */
X# define postWidth 12 /* height is computed */
X
X
Xstatic GrafPtr tohPort;
Xstatic BlobSetHandle donors;
Xstatic BlobSetHandle receptors;
Xstatic BlobHandle tower[3][nDisks]; /* induced data structure */
X
X
X
Xstatic DrawApparatus ()
X{
Xint postHeight, baseWidth, h, v, i;
XRect r;
X
X postHeight = nDisks * (slotHeight + slotVGap) + postWidth/2;
X h = xBase + hExtra + slotWidth/2 - postWidth/2;
X SetRect (&r, h, yBase - postHeight, h + postWidth, yBase+postWidth/2);
X
X for (i = 0; i < 3; ++i)
X {
X FillRoundRect (&r, postWidth, postWidth, gray);
X FrameRoundRect (&r, postWidth, postWidth);
X OffsetRect (&r, slotWidth + slotHGap, 0);
X }
X
X baseWidth = 3 * slotWidth + 2 * slotHGap + 2 * hExtra;
X SetRect (&r, xBase, yBase, xBase + baseWidth, yBase + baseHeight);
X FillRect (&r, dkGray);
X FrameRect (&r);
X}
X
X
X/*
X If a disk was moved onto a pile, but has empty slots under it,
X drop it until it can't go any farther.
X*/
X
Xstatic DropDisk ()
X{
Xregister int i, j;
X
X for (i = 0; i < 3; ++i)
X {
X for (j = nDisks - 1; j > 0; --j) /* don't check bottom pos */
X {
X if (BGlob (tower[i][j]) != nil)
X {
X if (BGlob (tower[i][j-1]) == nil)
X TransferGlob (tower[i][j], tower[i][j-1]);
X }
X }
X }
X}
X
X
Xstatic Mouse (pt, t, mods)
XPoint pt;
Xlong t;
Xint mods;
X{
X
X BlobClick (pt, t, nil, receptors);
X DropDisk ();
X}
X
X
X/*
X The advisory functions as follows: receptor clicks are checked
X and if the click isn't in the top disk of a pile, the click is
X ignored (message advRClick). When a receptor is dragged somewhere
X else, it must be to a pile in which the disk under it is larger -
X can't drag onto a smaller disk (message advXfer).
X*/
X
Xstatic Boolean Advisory (mesg, b)
Xint mesg;
XBlobHandle b;
X{
XBlobHandle g;
Xint index, pile, piece, i;
Xstatic int srcRank;
X
X index = GetBlobIndex (b, receptors);
X pile = index / nDisks; /* 0 .. 2 */
X piece = index % nDisks; /* 0 .. nDisks-1 */
X
X switch (mesg)
X {
X case advRClick:
X {
X if (piece < nDisks - 1 && BGlob (NextBlob (b)) != nil)
X return (false);
X srcRank = GetBRefCon (BGlob (b)); /* rank of dragged piece */
X break;
X }
X case advXfer:
X {
X for (i = 0; i < piece; ++i)
X {
X if ((g = BGlob (tower[pile][i])) != nil)
X {
X if (GetBRefCon (g) > srcRank)
X return (false);
X }
X }
X break;
X }
X }
X return (true);
X}
X
X
Xstatic Update (resized)
XBoolean resized;
X{
X DrawControls (tohPort);
X DrawApparatus ();
X DrawBlobSet (receptors);
X}
X
X
Xstatic Activate (active)
XBoolean active;
X{
X if (active)
X {
X SetDragRects (tohPort);
X SetBCPermissions (false, true, false, false, false);
X SetBCAdvisory (Advisory);
X }
X else
X SetBCAdvisory (nil);
X}
X
X/*
X Call this before static MakeDonors
X*/
X
Xstatic MakeReceptors ()
X{
Xint i, j, h, v;
XBlobHandle b;
XRect r, r2, r3;
X
X receptors = NewBlobSet ();
X for (i = 0; i < 3; ++i)
X {
X for (j = 0; j < nDisks; ++j)
X {
X b = NewBlob (receptors, false, 0, false, 0L);
X tower[i][j] = b;
X OpenBlob ();
X SetRect (&r, 0, 0, slotWidth, slotHeight);
X h = slotWidth/2 - postWidth/2;
X SetRect (&r2, h, -1, h + postWidth, slotHeight+1);
X FillRect (&r2, gray); /* fill in post area */
X SetRect (&r3, 0, 0, h, slotHeight); /* erase on sides of post */
X EraseRect (&r3);
X SetRect (&r3, h + postWidth, 0, slotWidth, slotHeight);
X EraseRect (&r3);
X FrameRect (&r2);
X r2 = r;
X InsetRect (&r2, 0, 1);
X CloseRectBlob (b, &r2, &r);
X h = xBase + hExtra + i * (slotWidth + slotHGap);
X v = yBase - (j+1) * (slotHeight + slotVGap);
X MoveBlob (b, inFullBlob, h, v);
X }
X }
X}
X
X
X/*
X Make donors. These are the pieces that get moved. They're always
X attached to some receptor, and just float from one receptor to
X another. The rank of each piece is stored in the reference constant
X field. The bottom piece is 0, the top is nDisks-1.
X*/
X
Xstatic MakeDonors ()
X{
Xint i, j;
XBlobHandle b;
XRect r, r2;
X
X donors = NewBlobSet ();
X for (i = 0; i < nDisks; ++i)
X {
X b = NewBlob (donors, false, 1, false,
X (long) i); /* refCon is disk rank */
X OpenBlob ();
X SetRect (&r, 0, 0, slotWidth, slotHeight);
X j = 20 + (nDisks-i-1) * 4;
X SetRect (&r2, slotWidth/2 - j, 1, slotWidth/2 + j, slotHeight-1);
X EraseRect (&r);
X FrameRoundRect (&r2, slotHeight, slotHeight);
X CloseRectBlob (b, &r, &r);
X GlueGlob (b, tower[0][i]); /* glue to first column */
X }
X
X}
X
X
XTohInit ()
X{
X SkelWindow (tohPort = GetDemoWind (tohWindRes),
X Mouse, /* mouse clicks */
X nil, /* key clicks */
X Update, /* updates */
X Activate, /* activate/deactivate events */
X nil, /* close window */
X DoWClobber, /* dispose of window */
X nil, /* idle proc */
X false); /* irrelevant, since no idle proc */
X
X MakeReceptors ();
X MakeDonors ();
X EnableBlobSet (receptors);
X Update ();
X ValidRect (&tohPort->portRect);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoTtt.c
X/*
X Blob Manager Demonstration: Tic-Tac-Toe
X
X 25 July 1986 Paul DuBois
X*/
X
X# include "BlobDemo.h"
X# include <ControlMgr.h>
X
X
X# define barWidth 3 /* board line size */
X# define bSqSize 30 /* board square size */
X# define pSqSize 28 /* playing piece square size */
X# define yOffMesg 4
X# define yOffPiece 24 /* offset of top of pieces */
X# define xOffBoard 25
X# define yOffBoard 59
X# define xMid 73 /* xOffBoard + 1.5(bSqSize) + barWidth */
X# define yOffBut 165
X
X
Xstatic GrafPtr tttPort;
Xstatic BlobSetHandle tttReceptors; /* receptor blobs (board) */
Xstatic BlobSetHandle tttDonors; /* donor blobs (pieces) */
Xstatic BlobHandle xBlob; /* handles to each piece */
Xstatic BlobHandle oBlob;
X
Xstatic Boolean haveWin;
Xstatic Boolean wait = false;
Xstatic ControlHandle restartCtl;
Xstatic int moves;
Xstatic int firstPlayer = 0;
Xstatic Str255 statusStr;
X
X
XTttStatusMesg (s)
XStr255 s;
X{
XRect r;
X
X SetRect (&r, xMid-40, yOffMesg, xMid+40, yOffMesg+20);
X TextBox (s+1, (long) s[0], &r, 1);
X StrCpy (statusStr, s);
X}
X
X
XTttGameOver (mesg)
XStr255 mesg;
X{
X HiliteControl (restartCtl, 0);
X TttStatusMesg (mesg);
X wait = true;
X}
X
X
X
XTttSelectPlayer ()
X{
XBlobHandle b;
Xint i;
X
X i = (moves + firstPlayer) % 2; /* 0 = X, 1 = O */
X HiliteBlob (GetBlobHandle (tttDonors, i), inFullBlob, normalDraw);
X HiliteBlob (GetBlobHandle (tttDonors, 1 - i), inFullBlob, dimDraw);
X if (i)
X TttStatusMesg ("\pO's Move");
X else
X TttStatusMesg ("\pX's Move");
X/*
X Freeze board except for positions occupied by current player and
X empty positions.
X This allows pieces to be played either by playing the piece at
X the top, or by duplicating them on the board. (Can't drag onto
X another of own pieces, since replace transactions are disallowed.)
X*/
X ThawBlobSet (tttReceptors);
X for (b = FirstBlob (tttReceptors); b != nil; b = NextBlob (b))
X {
X if (BGlob (b) != nil && BGlob (b) != GetBlobHandle (tttDonors, i))
X FreezeBlob (b);
X }
X}
X
X
XTttRestart ()
X{
X HiliteControl (restartCtl, 255);
X ZUnglueGlobSet (tttReceptors);
X HiliteBlobSet (tttReceptors, inFullBlob, normalDraw);
X moves = 0;
X TttSelectPlayer ();
X wait = false;
X}
X
X
X/*
X Dim the board positions that are not part of the win. Dim them all
X on "cat's game."
X*/
X
XTttShowWinner (pos)
Xint pos;
X{
Xint i;
XBlobHandle b;
X
X for (i = 0; i < 9; ++i)
X {
X b = GetBlobHandle (tttReceptors, i);
X if ((pos % 2) == 0) /* this pos not part of win */
X HiliteBlob (b, inFullBlob, dimDraw); /* so dim it */
X pos >>= 1;
X }
X}
X
XTttTestConfig (pos, testPos)
Xint pos, testPos;
X{
Xint i;
XBlobHandle b;
X
X if ((pos & testPos) == testPos) /* have a win */
X {
X haveWin = true;
X TttShowWinner (testPos);
X }
X}
X
X
XTttTestWin (b, boardPos)
XBlobHandle b;
Xint boardPos;
X{
X if (!haveWin) /* don't bother if other player already won */
X {
X TttTestConfig (boardPos, 0x007); /* top row */
X TttTestConfig (boardPos, 0x038); /* middle row */
X TttTestConfig (boardPos, 0x1c0); /* bottom row */
X TttTestConfig (boardPos, 0x049); /* left column */
X TttTestConfig (boardPos, 0x092); /* middle column */
X TttTestConfig (boardPos, 0x124); /* right column */
X TttTestConfig (boardPos, 0x111); /* diagonal */
X TttTestConfig (boardPos, 0x054); /* diagonal */
X if (haveWin)
X {
X if (b == xBlob)
X {
X TttGameOver ("\pX Wins"); /* loser goes first next time */
X firstPlayer = 1;
X }
X else
X {
X TttGameOver ("\pO Wins");
X firstPlayer = 0;
X }
X }
X }
X}
X
X
XTttBoardPos (b)
XBlobHandle b;
X{
Xint i, mask, result;
XBlobHandle b2;
X
X result = 0;
X mask = 1;
X for (i = 0; i < 9; ++i)
X {
X b2 = GetBlobHandle (tttReceptors, i);
X if ((**b2).glob == b) /* board occupied by desired piece */
X result |= mask;
X mask <<= 1;
X }
X return (result);
X}
X
X
XTttCheckStatus ()
X{
Xint xbPos, obPos;
X
X haveWin = false;
X xbPos = TttBoardPos (xBlob);
X obPos = TttBoardPos (oBlob);
X TttTestWin (xBlob, xbPos);
X TttTestWin (oBlob, obPos);
X if (!haveWin) /* no win, but board might be full now */
X {
X if ((xbPos | obPos) == 0x1ff)
X {
X TttShowWinner (0);
X TttGameOver ("\pCat's Game");
X firstPlayer = 1 - firstPlayer; /* alternate on a draw */
X }
X }
X}
X
X
XTttMouse (pt, t, mods)
XPoint pt;
Xlong t;
Xint mods;
X{
Xint result;
XControlHandle ctl;
X
X if (FindControl (pt, tttPort, &ctl))
X {
X if (TrackControl (ctl, pt, nil))
X {
X TttRestart ();
X }
X }
X else if (!wait)
X {
X BlobClick (pt, t, tttDonors, tttReceptors);
X result = BClickResult ();
X if (result == bcGlue || result == bcDup)
X {
X ++moves;
X TttCheckStatus ();
X if (!wait) /* no win yet */
X {
X TttSelectPlayer ();
X }
X }
X }
X}
X
XTttUpdate (resized)
XBoolean resized;
X{
X DrawControls (tttPort);
X TttStatusMesg (statusStr);
X DrawGrid (3, 3, xOffBoard, yOffBoard, bSqSize, bSqSize, barWidth, barWidth);
X DrawBlobSet (tttDonors);
X DrawBlobSet (tttReceptors);
X}
X
X
XTttActivate (active)
XBoolean active;
X{
X if (active)
X {
X SetDragRects (tttPort);
X SetBCPermissions (false, false, true, false, false);
X }
X}
X
X
X/*
X Make receptor blobs
X*/
X
XTttMakeRBlob (r)
XRect *r;
X{
XBlobHandle b;
X
X b = NewBlob (tttReceptors, false, 0, false, 0L);
X OpenBlob ();
X EraseRect (r);
X InsetRect (r, 1, 1);
X FrameRect (r);
X InsetRect (r, 2, 2);
X FrameRect (r);
X InsetRect (r, -2, -2);
X CloseRectBlob (b, r, r);
X}
X
X
XTttMakeReceptors ()
X{
X tttReceptors = NewBlobSet ();
X MakeBlobGrid (3, 3, xOffBoard, yOffBoard, bSqSize, bSqSize,
X barWidth, barWidth, &TttMakeRBlob);
X}
X
X
X/*
X Make donor blobs
X*/
X
XTttMakeDBlob (b, ch, x, y)
XBlobHandle *b;
Xint ch, x, y;
X{
XRect r;
X
X *b = NewBlob (tttDonors, false, 9, false, 0L);
X OpenBlob ();
X SetRect (&r, 0, 0, pSqSize, pSqSize);
X OffsetRect (&r, x, y);
X EraseRect (&r);
X PenSize (2, 2);
X FrameRect (&r);
X PenNormal ();
X MoveTo (r.left+pSqSize/2-4, r.bottom-pSqSize/2+5);
X DrawChar ((char) ch);
X CloseRectBlob (*b, &r, &r);
X}
X
X
XTttMakeDonors ()
X{
X tttDonors = NewBlobSet ();
X TttMakeDBlob (&xBlob, 'X', xMid-pSqSize-5, yOffPiece);
X TttMakeDBlob (&oBlob, 'O', xMid+5, yOffPiece);
X}
X
X
XTttInit ()
X{
XRect r;
X
X tttPort = GetDemoWind (tttWindRes);
X SkelWindow (tttPort,
X TttMouse, /* mouse clicks */
X nil, /* key clicks */
X TttUpdate, /* updates */
X TttActivate, /* activate/deactivate events */
X nil, /* close window */
X DoWClobber, /* dispose of window */
X nil, /* idle proc */
X false); /* irrelevant, since no idle proc */
X
X TttMakeReceptors ();
X TttMakeDonors ();
X EnableBlobSet (tttReceptors);
X EnableBlobSet (tttDonors);
X SetRect (&r, xMid-45, yOffBut, xMid+45, yOffBut+20);
X restartCtl = NewControl (tttPort, &r, "\pRestart", true, 0, 0, 0,
X pushButProc, nil);
X TttRestart ();
X TttUpdate ();
X ValidRect (&tttPort->portRect);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoWind.c
X/*
X Blob Manager Demonstration: Window routines
X*/
X
X# include "BlobDemo.h"
X# include <WindowMgr.h>
X
X
X
X
X/*
X Get a window for a demo module. Pass the resource number of the
X window. Set the font to Chicago 12-point, and add the window's
X title to the Windows menu.
X*/
X
XGrafPtr GetDemoWind (resNum)
Xint resNum;
X{
XGrafPtr thePort;
X
X thePort = (GrafPtr) GetNewWindow (resNum, nil, -1L);
X SetPort (thePort);
X TextFont (0);
X TextSize (0);
X return (thePort);
X}
X
X
X/*
X Generic window handler clobber proc for TransSkel stuff
X*/
X
XDoWClobber ()
X{
XWindowPtr theWind;
X
X GetPort ((GrafPtr *) &theWind);
X CloseWindow (theWind); /* should be DisposeWindow? */
X}
X
X
X/*
X Set window's default blob dragging rects: limit rect is portRect
X of window's grafPort, slop rect is wide open rectangle.
X*/
X
XSetDragRects (thePort)
XGrafPtr thePort;
X{
XRect rSlop;
X
X SetRect (&rSlop, -30000, -30000, 30000, 30000);
X SetBDragRects (&thePort->portRect, &rSlop);
X}SHAR_EOF
exit