home *** CD-ROM | disk | FTP | other *** search
- UNIT Cards;
- (**********************)
- (**) INTERFACE (**)
- (**********************)
-
- USES crt, ListObj;
- CONST pips : array[0..12] of char = 'A23456789TJQK';
- suits : array[0..3] of char = (#3, #4, #5, #6);
- TYPE
- CardP = ^Card;
- LCardP = ^LCard;
- PileP = ^Pile;
- DeckP = ^Deck;
- LDeckP = ^LDeck;
- HandP = ^Hand;
- PlayerP = ^Player;
- direction = (up, dn, lt, rt);
- decision = (no, yes, maybe);
-
- CARD = OBJECT (Node)
- value, X, Y : Word;
- HoldAttr, TableColor,
- PipColor : Byte;
- FaceUp : Boolean;
- CONSTRUCTOR Init(iValue : Word; iTC : Byte; iFaceUp : boolean);
- CONSTRUCTOR InitXY(iValue, iX, iY : word;
- iTC : Byte; iFaceUp : boolean);
- DESTRUCTOR done; virtual;
- {--- next 4 routines locate card at (X, Y) ---}
- PROCEDURE DrawAt(vX, vY : Word); virtual;
- PROCEDURE HideAt(vX, vY : Word); virtual;
- PROCEDURE PointTo(vX, vY : Word; direc : direction); virtual;
- PROCEDURE UnPoint(vX, vY : Word; direc : direction); virtual;
- {--- next 4 routines use card's intrinsic location ---}
- PROCEDURE Display;
- PROCEDURE hide;
- PROCEDURE PointT(direc : direction);
- PROCEDURE UnPoin(direc : direction);
- FUNCTION GetRank : Byte; virtual;
- FUNCTION GetSuit : Byte; virtual;
- {--- remaining routines are static ---}
- PROCEDURE TurnUp;
- PROCEDURE TurnDown;
- PROCEDURE PutInPlace(iX, iY : Word);
- FUNCTION GetValue : Word;
- END;
-
- LCard = OBJECT (Card)
- {--- Little Card -- differs only in how it's displayed ---}
- CONSTRUCTOR Init(iValue : Word; iTC : Byte; iFaceUP : boolean);
- CONSTRUCTOR InitXY(iValue, iX, iY : word;
- iTC : Byte; iFaceUp : boolean);
- DESTRUCTOR Done; virtual;
- PROCEDURE DrawAt(vX, vY : Word); virtual;
- PROCEDURE HideAt(vX, vY : Word); virtual;
- END;
-
- Pile = OBJECT (Node)
- {--- a "smart" list of cards ---}
- X, Y, NumInPile : Word;
- FaceUp : Decision;
- Cards : List;
- CONSTRUCTOR Init(iX, iY : Word; iShow : Decision);
- DESTRUCTOR Done; virtual;
- PROCEDURE AddCard(C : CardP);
- PROCEDURE Display; virtual;
- PROCEDURE Hide; virtual;
- PROCEDURE Sort(bySuit : boolean); virtual;
- {--- remaining methods are static ---}
- PROCEDURE PlaceAt(iX, iY : Word);
- FUNCTION OnTop : CardP;
- FUNCTION OnBot : CardP;
- FUNCTION FromTop : CardP;
- FUNCTION FromBot : CardP;
- FUNCTION NextCard(C : CardP) : CardP;
- FUNCTION PrevCard(C : CardP) : CardP;
- PROCEDURE Remove(C : CardP);
- FUNCTION Empty : boolean;
- FUNCTION GetX : Word;
- FUNCTION GetY : Word;
- PROCEDURE TurnUp;
- PROCEDURE TurnDown;
- FUNCTION GetUp : decision;
- END;
-
- Hand = OBJECT (pile)
- {--- a hand is a pile with the cards spread out ---}
- pX, pY : Byte; {used in pointing to cards}
- direc : direction;
- CONSTRUCTOR Init(iX, iY : Word; iShow : decision;
- iDire : direction);
- DESTRUCTOR Done; virtual;
- PROCEDURE Display; virtual;
- PROCEDURE Hide; virtual;
- PROCEDURE PointToCard(CP : CardP; dr : direction); virtual;
- PROCEDURE UnPointCard(CP : CardP; dr : direction); virtual;
- {--- remaining method is "private" ---}
- PROCEDURE Private_Go;
- END;
-
- DECK = OBJECT (pile)
- {--- a DECK is a PILE that can shuffle ---}
- CONSTRUCTOR Init(iX, iY : Word; iTC : Byte);
- DESTRUCTOR done; virtual;
- PROCEDURE shuffle; virtual;
- PROCEDURE AddToBottom(C : CardP);
- END;
-
- LDeck = OBJECT (deck)
- {--- a LDECK is a DECK of little cards ---}
- CONSTRUCTOR Init(iX, iY : Word; iTC : Byte);
- DESTRUCTOR done; virtual;
- END;
-
- Player = OBJECT (node)
- {--- abstract -- each GAME needs a new player type ---}
- H : HandP;
- name : String;
- CONSTRUCTOR Init(iX, iY : Word; iShow : decision;
- iDire : direction; iName : String);
- DESTRUCTOR Done; virtual;
- PROCEDURE TakeCard(C : CardP); virtual;
- PROCEDURE ShowHand; virtual;
- PROCEDURE PointToMe; virtual;
- PROCEDURE UnPointMe; virtual;
- {--- remaining methods are static ---}
- FUNCTION GetName : String;
- FUNCTION OutOfCards : Boolean;
- FUNCTION NextNotSelf(L : list; X : PlayerP) : PlayerP;
- FUNCTION PrevNotSelf(L : list; X : PlayerP) : PlayerP;
- FUNCTION FirsNotSelf(L : List) : PlayerP;
- END;
-
- Game = OBJECT
- {--- abstract object -- every game will differ ---}
- D : deckP;
- TableColor : Byte;
- players : list;
- whoseturn : PlayerP;
- CONSTRUCTOR Init(iTC : byte);
- DESTRUCTOR done; virtual;
- PROCEDURE DealCards(num : word); virtual;
- PROCEDURE Display; virtual;
- {--- remaining methods are static ---}
- PROCEDURE AddPlayer(PP : PlayerP);
- END;
-
- (*-non-method routines-------*)
-
- PROCEDURE Frame(x1, y1, x2, y2 : byte; {corner coords}
- typ : byte; {type of frame}
- clr : boolean; {clear inside?}
- clrch : char); {clear with what}
-
- PROCEDURE beep;
- PROCEDURE click;
- PROCEDURE sad;
- PROCEDURE happy;
- PROCEDURE fanfare;
-
- (**********************)
- (**) IMPLEMENTATION (**)
- (**********************)
-
- (*-non-method routines-------*)
-
- PROCEDURE Frame(x1, y1, x2, y2 : byte; {corner coords}
- typ : byte; {type of frame}
- clr : boolean; {clear inside?}
- clrch : char); {clear with what}
- TYPE fchars = (ulc, top, urc, side, lrc, llc);
- CONST fc : ARRAY[0..2] OF ARRAY[fchars] OF CHAR =
- (' ', #218#196#191#179#217#192,
- #201#205#187#186#188#200);
- VAR
- ro, co : Byte;
- S : String[80];
- BEGIN
- FillChar(S, SizeOf(S), fc[typ][top]);
- S[0] := char(pred(x2-x1));
- GotoXY(x1, y1);
- Write(fc[typ][ulc], S, fc[typ][urc]);
- GotoXY(x1, y2);
- Write(fc[typ][llc], S, fc[typ][lrc]);
- FillChar(S[1], pred(SizeOf(S)), clrch);
- FOR ro := succ(y1) TO pred(y2) DO
- IF clr THEN
- BEGIN
- GotoXY(x1, ro);
- Write(fc[typ][side], S, fc[typ][side])
- END
- ELSE
- BEGIN
- GotoXY(x1, ro); Write(fc[typ][side]);
- GotoXY(x2, ro); Write(fc[typ][side]);
- END;
- END;
-
- PROCEDURE SoundDel(S, D : Word); BEGIN Sound(S); Delay(D); END;
-
- PROCEDURE beep; BEGIN SoundDel(3000, 100); nosound; END;
-
- PROCEDURE click; BEGIN SoundDel(4000, 10); NoSound; END;
-
- PROCEDURE sad;
- VAR N : Byte;
- BEGIN
- FOR N := 50 DOWNTO 1 DO SoundDel(500+20*N, 5); NoSound;
- END;
-
- PROCEDURE happy;
- VAR N : Byte;
- BEGIN
- FOR N := 1 TO 50 DO SoundDel(500+30*N, 5); NoSound;
- END;
-
- PROCEDURE fanfare;
- BEGIN
- SoundDel(523, 200); SoundDel(698, 200);
- SoundDel(880, 200); SoundDel(1047, 200);
- NoSound; Delay(200);
- SoundDel(880, 200); SoundDel(1047, 600);
- NoSound;
- END;
-
- (*-methods for CARD----------*)
-
- CONSTRUCTOR Card.Init(iValue : Word; iTC : Byte; iFaceUp : boolean);
- BEGIN
- value := iValue; TableColor := iTC;
- IF value < 26 THEN PipColor := LightRed ELSE PipColor := black;
- FaceUp := iFaceUp; X := 0; Y := 0;
- END;
-
- CONSTRUCTOR Card.InitXY(iValue, iX, iY : word;
- iTC : Byte; iFaceUp : boolean);
- BEGIN Init(iValue, iTC, iFaceUp); X := iX; Y := iY; END;
-
- DESTRUCTOR card.done; BEGIN END;
-
- PROCEDURE Card.DrawAt(vX, vY : Word);
- BEGIN
- HoldAttr := TextAttr;
- TextBackground(white);
- IF FaceUP THEN
- BEGIN
- TextColor(PipColor);
- frame(vX, vY, vX+4, vY+4, 1, true, ' ');
- {Write pips across AND down, so card values
- will be visible when spread horz. or vert.}
- GotoXY(vX+1, vY+2); Write(pips[GetRank]);
- GotoXY(vx+2, vY+1); Write(pips[GetRank]);
- GotoXY(vX+1, vY+3); Write(suits[GetSuit]);
- GotoXY(vX+3, vY+1); Write(suits[GetSuit]);
- END
- ELSE
- BEGIN
- TextBackground(blue); TextColor(lightgray);
- frame(vX, vY, vX+4, vY+4, 2, true, #176);
- END;
- TextAttr := HoldAttr;
- END;
-
- PROCEDURE Card.HideAt(vX, vY : Word);
- BEGIN
- HoldAttr := TextAttr;
- TextAttr := TableColor;
- frame(vX, vY, vX+4, vY+4, 0, true, ' ');
- TextAttr := HoldAttr;
- END;
-
- PROCEDURE Card.PointTo(vX, vY : Word; direc : direction);
- BEGIN
- HoldAttr := TextAttr;
- TextAttr := TableColor;
- CASE direc OF
- up : BEGIN; GotoXY(vX+1, vY-1); Write(#25); END;
- dn : BEGIN; GotoXY(vX+1, vY+5); Write(#24); END;
- lt : BEGIN; GotoXY(vX-1, vY+2); Write(#26); END;
- rt : BEGIN; GotoXY(vX+5, vY+2); Write(#27); END;
- END;
- TextAttr := HoldAttr;
- END;
-
- PROCEDURE Card.UnPoint(vX, vY : Word; direc : direction);
- BEGIN
- HoldAttr := TextAttr;
- TextAttr := TableColor;
- CASE direc OF
- up : BEGIN; GotoXY(vX+1, vY-1); Write(' '); END;
- dn : BEGIN; GotoXY(vX+1, vY+5); Write(' '); END;
- lt : BEGIN; GotoXY(vX-1, vY+2); Write(' '); END;
- rt : BEGIN; GotoXY(vX+5, vY+2); Write(' '); END;
- END;
- TextAttr := HoldAttr;
- END;
-
- PROCEDURE Card.Display; BEGIN DrawAt(X, Y); END;
-
- PROCEDURE Card.Hide; BEGIN HideAt(X, Y); END;
-
- PROCEDURE Card.PointT(direc : direction);
- BEGIN PointTo(X, Y, direc); END;
-
- PROCEDURE Card.Unpoin(direc : direction);
- BEGIN UnPoint(X, Y, direc); END;
-
- FUNCTION Card.GetRank : Byte; BEGIN GetRank := value MOD 13; END;
-
- FUNCTION Card.GetSuit : Byte; BEGIN GetSuit := value DIV 13; END;
-
- PROCEDURE Card.TurnUp; BEGIN FaceUp := True; END;
-
- PROCEDURE Card.TurnDown; BEGIN FaceUp := False; END;
-
- PROCEDURE Card.PutInPlace(iX, iY : Word);
- BEGIN X := iX; Y := iY; END;
-
- FUNCTION Card.GetValue : Word; BEGIN GetValue := Value; END;
-
- (*-methods for LCard---------*)
-
- CONSTRUCTOR LCard.Init(iValue : Word;
- iTC : Byte; iFaceUP : boolean);
- BEGIN Card.Init(iValue, iTC, iFaceUp); END;
-
- CONSTRUCTOR LCard.InitXY(iValue, iX, iY : word;
- iTC : Byte; iFaceUp : boolean);
- BEGIN Init(iValue, iTC, iFaceUp); X := iX; Y := iY; END;
-
- DESTRUCTOR LCard.Done; BEGIN Card.Done; END;
-
- PROCEDURE LCard.DrawAt(vX, vY : Word);
- BEGIN
- HoldAttr := TextAttr;
- TextBackground(White);
- IF FaceUp THEN
- BEGIN
- TextColor(PipColor);
- GotoXY(vX, vY); Write(' ',pips[GetRank],' ');
- GotoXY(vX, succ(vY)); Write(' ',suits[GetSuit],' ');
- END
- ELSE
- BEGIN
- TextColor(blue);
- GotoXY(vX, vY); Write(#176#176#176);
- GotoXY(vX, succ(vY)); Write(#176#176#176);
- END;
- TextAttr := HoldAttr;
- END;
-
- PROCEDURE LCard.HideAt(vX, vY : Word);
- BEGIN
- HoldAttr := TextAttr;
- TextAttr := TableColor;
- GotoXY(vX, vY); Write(' ');
- GotoXY(vX, succ(vY)); Write(' ');
- TextAttr := HoldAttr;
- END;
-
- (*-methods for PILE----------*)
-
- CONSTRUCTOR Pile.Init(iX, iY : Word; iShow : decision);
- BEGIN
- X := iX; Y := iY; Cards.Init; NumInPile := 0; FaceUp := iShow;
- END;
-
- DESTRUCTOR Pile.Done;
- BEGIN Cards.Done; END;
-
- PROCEDURE Pile.AddCard(C : CardP);
- BEGIN
- IF FaceUp = yes THEN C^.TurnUp;
- IF FaceUP = no THEN C^.TurnDown;
- Cards.Append(C); Inc(NumInPile);
- END;
-
- PROCEDURE Pile.Display;
- BEGIN IF NOT cards.Empty THEN CardP(cards.last)^.DrawAt(X, Y); END;
-
- PROCEDURE Pile.Hide;
- BEGIN IF NOT cards.Empty THEN CardP(cards.last)^.HideAt(X, Y); END;
-
- PROCEDURE Pile.Sort(bySuit : boolean);
- VAR
- N, M, T : CardP;
-
- FUNCTION greater(xM, xN : CardP) : Boolean;
- VAR Sm, Sn, Rm, Rn : Byte;
- BEGIN
- Sm := xM^.GetSuit;
- Sn := xN^.GetSuit;
- Rm := xM^.GetRank;
- Rn := xN^.GetRank;
- greater := false;
- IF BySuit THEN
- BEGIN
- IF Sm>Sn THEN greater := true
- ELSE IF (Sm = Sn) AND (Rm>Rn) THEN greater := true;
- END
- ELSE
- BEGIN
- IF Rm > Rn THEN greater := true
- ELSE IF (Rm = Rn) AND (Sm>Sn) THEN greater := true;
- END;
- END;
-
- BEGIN {immediate exchange selection sort}
- N := OnTop;
- WHILE N <> OnBot DO
- BEGIN
- M := OnBot;
- WHILE M <> N DO
- BEGIN
- IF Greater(M, N) THEN
- BEGIN
- Cards.SwapInList(M, N);
- T := M; M := N; N := T;
- END;
- M := NextCard(M);
- END;
- N := PrevCard(N);
- END;
- END;
-
- PROCEDURE Pile.PlaceAt(iX, iY : Word); BEGIN X := iX; Y := iY; END;
-
- FUNCTION Pile.OnTop : CardP; BEGIN OnTop := CardP(Cards.Last); END;
-
- FUNCTION Pile.OnBot : CardP; BEGIN OnBot := CardP(Cards.Firs); END;
-
- FUNCTION Pile.FromTop : CardP;
- BEGIN
- IF (NumInPile = 1) AND (X+Y>0) THEN
- CardP(Cards.Last)^.HideAt(X, Y);
- FromTop := CardP(Cards.Last);
- Cards.remove(Cards.Last); Dec(NumInPile);
- END;
-
- FUNCTION Pile.FromBot : CardP;
- BEGIN
- IF (NumInPile = 1) AND (X+Y>0) THEN
- CardP(Cards.Last)^.HideAt(X, Y);
- FromBot := CardP(Cards.Firs);
- Cards.Remove(Cards.Firs); Dec(NumInPile);
- END;
-
- FUNCTION Pile.GetX : Word; BEGIN GetX := X; END;
-
- FUNCTION Pile.GetY : Word; BEGIN GetY := Y; END;
-
- FUNCTION Pile.Empty : boolean; BEGIN Empty := cards.empty; END;
-
- FUNCTION Pile.NextCard(C : CardP) : CardP;
- BEGIN NextCard := CardP(cards.Next(C)); END;
-
- FUNCTION Pile.PrevCard(C : CardP) : CardP;
- BEGIN PrevCard := CardP(cards.Prev(C)); END;
-
- PROCEDURE Pile.Remove(C : CardP);
- BEGIN
- IF (NumInPile = 1) AND (X+Y>0) THEN
- CardP(Cards.Last)^.HideAt(X, Y);
- cards.remove(C); Dec(NumInPile);
- END;
-
- PROCEDURE Pile.TurnUp; BEGIN FaceUp := yes; END;
-
- PROCEDURE Pile.TurnDown; BEGIN FaceUp := no; END;
-
- FUNCTION Pile.GetUp : decision; BEGIN GetUp := FaceUp; END;
-
- (*-methods for HAND----------*)
-
- CONSTRUCTOR hand.Init(iX, iY : Word; iShow : decision;
- iDire : direction);
- BEGIN Pile.Init(iX, iY, iShow); direc := iDire; END;
-
- DESTRUCTOR Hand.Done; BEGIN Pile.done; END;
-
- PROCEDURE Hand.Private_Go;
- BEGIN
- CASE direc OF
- up : Dec(pY, 2);
- dn : Inc(pY, 2);
- lt : Dec(pX, 2);
- rt : Inc(pX, 2);
- END;
- END;
-
- PROCEDURE Hand.Display;
- VAR C : CardP;
- BEGIN
- pX := X; pY := Y; C := CardP(cards.Firs);
- WHILE C <> NIL DO
- BEGIN
- C^.DrawAt(pX, pY); Private_Go;
- C := CardP(cards.next(C));
- END;
- END;
-
- PROCEDURE Hand.Hide;
- VAR C : CardP;
- BEGIN
- pX := X; pY := Y; C := CardP(cards.Firs);
- WHILE C <> NIL DO
- BEGIN
- C^.HideAt(pX, pY); Private_Go;
- C := CardP(cards.next(C));
- END;
- END;
-
- PROCEDURE Hand.PointToCard(CP : CardP; dr : direction);
- VAR C : CardP;
- BEGIN
- pX := X; pY := Y; C := CardP(cards.Firs);
- WHILE (C<>NIL) AND (C<>CP) DO
- BEGIN
- C := CardP(cards.next(C)); Private_Go;
- END;
- IF C <> NIL THEN C^.PointTo(pX, pY, dr);
- END;
-
- PROCEDURE Hand.UnPointCard(CP : CardP; dr : direction);
- VAR C : CardP;
- BEGIN
- pX := X; pY := Y; C := CardP(cards.Firs);
- WHILE (C<>NIL) AND (C<>CP) DO
- BEGIN
- C := CardP(cards.next(C)); Private_Go;
- END;
- IF C <> NIL THEN C^.UnPoint(pX, pY, dr);
- END;
-
- (*-methods for DECK----------*)
-
- CONSTRUCTOR deck.Init(iX, iY : Word; iTC : Byte);
- VAR valu : word;
- BEGIN
- Pile.Init(iX, iY, no);
- FOR valu := 0 to 51 DO
- AddCard(New(CardP, Init(valu, iTC, false)));
- END;
-
- DESTRUCTOR Deck.done; BEGIN Pile.Done; END;
-
- PROCEDURE Deck.Shuffle;
- VAR N,M,T:CardP;
- BEGIN
- N := OnBot;
- WHILE N <> NIL DO
- BEGIN
- M := CardP(Cards.Nth(succ(random(NumInPile))));
- Cards.SwapInList(N, M);
- T := M; M := N; N := T;
- N := NextCard(N);
- END;
- END;
-
- PROCEDURE Deck.AddToBottom(C : CardP);
- BEGIN
- IF FaceUp = yes THEN C^.TurnUp;
- IF FaceUP = no THEN C^.TurnDown;
- Cards.Insert(cards.Firs, C);
- Inc(NumInPile);
- END;
-
- (*-methods for LDECK---------*)
-
- CONSTRUCTOR LDeck.Init(iX, iY : Word; iTC : Byte);
- VAR valu : Word;
- BEGIN
- Pile.Init(iX, iY, no);
- FOR valu := 0 to 51 DO
- AddCard(New(LCardP, Init(valu, iTC, false)));
- END;
-
- DESTRUCTOR LDeck.done; BEGIN Deck.Done; END;
-
- (*-methods for Player--------*)
-
- CONSTRUCTOR Player.Init(iX, iY : Word; iShow : decision;
- iDire : direction; iName : String);
- BEGIN New(H, Init(iX, iY, iShow, iDire)); name := iName; END;
-
- DESTRUCTOR Player.Done; BEGIN dispose(H, done); END;
-
- PROCEDURE Player.TakeCard(C : CardP); BEGIN H^.AddCard(C); END;
-
- FUNCTION Player.GetName : String; BEGIN GetName := name; END;
-
- {--- abstract methods ---}
- PROCEDURE Player.ShowHand; BEGIN END;
- PROCEDURE Player.PointToMe; BEGIN END;
- PROCEDURE Player.UnPointMe; BEGIN END;
-
- FUNCTION Player.OutOfCards : Boolean;
- BEGIN OutOfCards := H^.empty; END;
-
- FUNCTION Player.NextNotSelf(L : List; X : PlayerP) : PlayerP;
- VAR P : PlayerP;
- BEGIN
- P := PlayerP(L.NextCirc(X));
- IF P = @Self THEN P := PlayerP(L.NextCirc(P));
- NextNotSelf := P;
- END;
-
- FUNCTION Player.PrevNotSelf(L : List; X : PlayerP) : PlayerP;
- VAR P : PlayerP;
- BEGIN
- P := PlayerP(L.PrevCirc(X));
- IF P = @Self THEN P := PlayerP(L.PrevCirc(P));
- PrevNotSelf := P;
- END;
-
- FUNCTION Player.FirsNotSelf(L : List) : PlayerP;
- BEGIN
- IF L.Firs = @Self THEN
- FirsNotSelf := PlayerP(L.NextCirc(L.firs))
- ELSE FirsNotSelf := PlayerP(L.Firs);
- END;
-
- (*-methods for GAME----------*)
-
- CONSTRUCTOR game.Init(iTC : Byte);
- BEGIN
- Randomize;
- TableColor := iTC;
- players.Init; whoseturn := NIL;
- {each game inits its own DECK}
- END;
-
- DESTRUCTOR game.done; BEGIN Players.done; dispose(D, done); END;
-
- PROCEDURE game.AddPlayer(PP : PlayerP);
- BEGIN
- players.append(PP);
- IF players.Firs = players.last THEN
- WhoseTurn := PlayerP(players.Firs);
- END;
-
- PROCEDURE game.DealCards(num : word);
- VAR N : byte;
- P : PlayerP;
- BEGIN
- IF num = 0 THEN {deal 'til deck is gone}
- BEGIN
- P := PlayerP(players.Firs);
- WHILE NOT D^.empty DO
- BEGIN
- P^.TakeCard(D^.FromTop);
- P := PlayerP(players.NextCirc(P));
- END;
- END
- ELSE {deal "num" cards to each player}
- FOR N := 1 to num DO
- BEGIN
- P := PlayerP(players.Firs);
- WHILE P <> NIL DO
- BEGIN
- P^.TakeCard(D^.FromTop);
- P := PlayerP(players.next(P));
- END;
- END;
- END;
-
- PROCEDURE game.Display; BEGIN END;
-
- END.