home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / l / l040 / 10.ddi / CHESS.ZIP / TVPIECES.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-10-27  |  16.3 KB  |  620 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Vision Chess Demo                      }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. unit TVPieces;
  9.  
  10. interface
  11.  
  12. {$IFDEF DPMI}
  13. uses Objects, Views, Dialogs, ChessDLL, TVChsCmd, Drivers;
  14. {$ELSE}
  15. uses Objects, Views, Dialogs, ChessInf, TVChsCmd, Drivers;
  16. {$ENDIF}
  17.  
  18. type
  19.  
  20. { TGlyphButton }
  21.  
  22.   { Palette layout }
  23.   { 1 = Button background }
  24.   { 2 = Normal white piece }
  25.   { 3 = Normal black piece }
  26.   { 4 = Selected white piece }
  27.   { 5 = Selected black piece }
  28.   { 6 = Shadow }
  29.  
  30.   PGlyphButton = ^TGlyphButton;
  31.   TGlyphButton = object(TButton)
  32.     Piece: TPiece;
  33.     Color: TColor;
  34.     constructor Init(var Bounds: TRect; APiece: TPiece; AColor: TColor;
  35.       ATitle: TTitleStr; ACommand: Word; AFlags: Byte);
  36.     constructor Load(var S: TStream);
  37.     procedure Draw; virtual;
  38.     procedure DrawState(Down: Boolean);
  39.     function GetPalette: PPalette; virtual;
  40.     procedure HandleEvent(var Event: TEvent); virtual;
  41.     procedure Store(var S: TStream);
  42.   end;
  43.  
  44. { TPromoteDialog }
  45.  
  46.   { Palette layout }
  47.   { 1..32 = CGrayDialog }
  48.   { 33 = Button background }
  49.   { 34 = Normal white piece }
  50.   { 35 = Normal black piece }
  51.   { 36 = Selected white piece }
  52.   { 37 = Selected black piece }
  53.   { 38 = Shadow }
  54.  
  55.   PPromoteDialog = ^TPromoteDialog;
  56.   TPromoteDialog = object(TDialog)
  57.     constructor Init(AColor: TColor);
  58.     function GetPalette: PPalette; virtual;
  59.     procedure HandleEvent(var Event: TEvent); virtual;
  60.   end;
  61.  
  62. { TChessPiece}
  63.  
  64.   PChessPiece = ^TChessPiece;
  65.   TChessPiece = object(TView)
  66.     PieceType: TSquare;
  67.     Location: TLocation;
  68.     InJeopardy: Boolean;
  69.     constructor Init(var Bounds: TRect; APieceType: TSquare; ALocation: TLocation);
  70.     constructor Load(var S:TStream);
  71.     procedure CapturePiece;
  72.     procedure CheckJeopardy(var MoveArray: array of TMove);
  73.     procedure Draw; virtual;
  74.     function GetPromotionPiece: TPiece;
  75.     procedure HandleEvent(var Event: TEvent); virtual;
  76.     procedure MoveToSquare(ALocation: TLocation);
  77.     function PerformMove(C: TChange): Boolean;
  78.     procedure RawDraw(var B: TDrawBuffer; BufPos, Line: Integer;
  79.       var XOfs, XLen: Integer);
  80.     procedure SnapToSquare;
  81.     procedure Store(var S: TStream);
  82.   end;
  83.  
  84. const
  85.   RChessPiece: TStreamRec = (
  86.     ObjType: otChessPiece;
  87.     VmtLink: Ofs(TypeOf(TChessPiece)^);
  88.     Load:    @TChessPiece.Load;
  89.     Store:   @TChessPiece.Store);
  90.  
  91.   RGlyphButton: TStreamRec = (
  92.     ObjType: otGlyphButton;
  93.     VmtLink: Ofs(TypeOf(TGlyphButton)^);
  94.     Load:    @TGlyphButton.Load;
  95.     Store:   @TGlyphButton.Store);
  96.  
  97.   RPromoteDialog: TStreamRec = (
  98.     ObjType: otPromoteDialog;
  99.     VmtLink: Ofs(TypeOf(TPromoteDialog)^);
  100.     Load:    @TPromoteDialog.Load;
  101.     Store:   @TPromoteDialog.Store);
  102.  
  103. implementation
  104.  
  105. uses App, TVChsUtl, TVBoard;
  106.  
  107. type
  108.   TPictureType = array[0..2] of
  109.   record
  110.      x : integer;
  111.      s : string[6];
  112.   end;
  113.  
  114. const
  115.   PiecePicture: array[pKing..pPawn] of TPictureType =
  116.  
  117.         (((x : 1;   s :  '++++'),
  118.           (x : 1;   s :  '⌠ K⌠'),
  119.           (x : 1;   s :  '⌡⌡⌡⌡')),
  120.  
  121.          ((x : 1;   s :  'ΘΘΘΘ'),
  122.           (x : 1;   s :  '╞╬╬╡'),
  123.           (x : 1;   s :  '│ Q│')),
  124.  
  125.          ((x : 1;   s :  '┌╥╥┐'),
  126.           (x : 1;   s :  '│ R│'),
  127.           (x : 1;   s :  '│  │')),
  128.  
  129.          ((x : 2;   s :   '┌Ω┐'),
  130.           (x : 2;   s :   '│ │'),
  131.           (x : 2;   s :   '│B│')),
  132.  
  133.          ((x : 1;   s :  '┌──┐'),
  134.           (x : 1;   s :  '╘┐''│'),
  135.           (x : 2;   s :   '│N│')),
  136.  
  137.          ((x : 0;   s : ''     ),
  138.           (x : 3;   s :    'P' ),
  139.           (x : 2;   s :   '≡≡≡')));
  140.  
  141.  
  142. { TGlyphButton }
  143.  
  144. constructor TGlyphButton.Init(var Bounds: TRect; APiece: TPiece;
  145.   AColor: TColor; ATitle: TTitleStr; ACommand: Word; AFlags: Byte);
  146. begin
  147.   inherited Init(Bounds, ATitle, ACommand, AFlags);
  148.   Piece := APiece;
  149.   Color := AColor;
  150. end;
  151.  
  152. constructor TGlyphButton.Load(var S: TStream);
  153. begin
  154.   inherited Load(S);
  155.   S.Read(Piece, SizeOf(Piece));
  156.   S.Read(Color, SizeOf(Color));
  157. end;
  158.  
  159. procedure TGlyphButton.Draw;
  160. begin
  161.   DrawState(False);
  162. end;
  163.  
  164. procedure TGlyphButton.DrawState(Down: Boolean);
  165. var
  166.   CButton, CShadow, CPiece: Word;
  167.   Ch, SelCh: Char;
  168.   I, S, Y, T: Integer;
  169.   B: TDrawBuffer;
  170.  
  171.   procedure DrawPiece(Line: Byte);
  172.   var
  173.     L, SCOff: Integer;
  174.   begin
  175.     if Flags and bfLeftJust <> 0 then L := 1 else
  176.     begin
  177.       L := (S - Length(PiecePicture[Piece][Line].s) - 1) div 2;
  178.       if L < 1 then L := 1;
  179.     end;
  180.     MoveCStr(B[I + L + PiecePicture[Piece][Line].x - 1],
  181.       PiecePicture[Piece][Line].s, CPiece);
  182.     if ShowMarkers and not Down then
  183.     begin
  184.       if State and sfSelected <> 0 then SCOff := 0 else
  185.         if AmDefault then SCOff := 2 else SCOff := 4;
  186.       WordRec(B[0]).Lo := Byte(SpecialChars[SCOff]);
  187.       WordRec(B[S]).Lo := Byte(SpecialChars[SCOff + 1]);
  188.     end;
  189.   end;
  190.  
  191. begin
  192.   CButton := GetColor($0101);
  193.   CPiece := $0402;
  194.   SelCh := '░';
  195.   if State and sfActive <> 0 then
  196.     if State and sfSelected <> 0 then
  197.     begin
  198.       CPiece := Swap(CPiece);
  199.       SelCh := ' ';
  200.     end;
  201.   if Color = cBlack then CPiece := CPiece + $0101;
  202.   CPiece := GetColor(CPiece);
  203.   CShadow := GetColor(6);
  204.   S := Size.X - 1;
  205.   T := Size.Y div 2 - 2;
  206.   for Y := 0 to Size.Y - 2 do
  207.   begin
  208.     MoveChar(B, SelCh, Byte(CButton), Size.X);
  209.     WordRec(B[0]).Hi := CShadow;
  210.     WordRec(B[0]).Lo := Byte(' ');
  211.     if Down then
  212.     begin
  213.       WordRec(B[1]).Hi := CShadow;
  214.       WordRec(B[1]).Lo := Byte(' ');
  215.       Ch := ' ';
  216.       I := 2;
  217.     end else
  218.     begin
  219.       WordRec(B[S]).Hi := Byte(CShadow);
  220.       if ShowMarkers then Ch := ' ' else
  221.       begin
  222.         if Y = 0 then
  223.           WordRec(B[S]).Lo := Byte('▄') else
  224.           WordRec(B[S]).Lo := Byte('█');
  225.         Ch := '▀';
  226.       end;
  227.       I := 1;
  228.     end;
  229.     if (Y >= T) and (Y <= T + 2) then DrawPiece(Y - T);
  230.     if ShowMarkers and not Down then
  231.     begin
  232.       WordRec(B[1]).Lo := Byte(' ');
  233.       WordRec(B[S - 1]).Lo := Byte(' ');
  234.     end;
  235.     WriteLine(0, Y, Size.X, 1, B);
  236.   end;
  237.   MoveChar(B[0], ' ', Byte(CShadow), 2);
  238.   MoveChar(B[2], Ch, Byte(CShadow), S - 1);
  239.   WriteLine(0, Size.Y - 1, Size.X, 1, B);
  240. end;
  241.  
  242. function TGlyphButton.GetPalette: PPalette;
  243. const
  244.   P: String[Length(CGlyphButton)] = CGlyphButton;
  245. begin
  246.   GetPalette := @P;
  247. end;
  248.  
  249. procedure TGlyphButton.HandleEvent(var Event: TEvent);
  250. var
  251.   Down: Boolean;
  252.   Mouse: TPoint;
  253.   ClickRect: TRect;
  254. begin
  255.   GetExtent(ClickRect);
  256.   Inc(ClickRect.A.X);
  257.   Dec(ClickRect.B.X);
  258.   Dec(ClickRect.B.Y);
  259.   if Event.What = evMouseDown then
  260.   begin
  261.     MakeLocal(Event.Where, Mouse);
  262.     if not ClickRect.Contains(Mouse) then ClearEvent(Event)
  263.     else
  264.     begin
  265.       if Flags and bfGrabFocus <> 0 then
  266.         TView.HandleEvent(Event);
  267.       if State and sfDisabled = 0 then
  268.       begin
  269.         Inc(ClickRect.B.X);
  270.         Down := False;
  271.         repeat
  272.           MakeLocal(Event.Where, Mouse);
  273.           if Down <> ClickRect.Contains(Mouse) then
  274.           begin
  275.             Down := not Down;
  276.             DrawState(Down);
  277.           end;
  278.         until not MouseEvent(Event, evMouseMove);
  279.         if Down then
  280.         begin
  281.           Press;
  282.           DrawState(False);
  283.         end;
  284.       end;
  285.       ClearEvent(Event);
  286.     end;
  287.   end;
  288.   inherited HandleEvent(Event);
  289. end;
  290.  
  291. procedure TGlyphButton.Store(var S: TStream);
  292. begin
  293.   inherited Store(S);
  294.   S.Write(Piece, SizeOf(Piece));
  295.   S.Write(Color, SizeOf(Color));
  296. end;
  297.  
  298. { TPromoteDialog }
  299.  
  300. constructor TPromoteDialog.Init(AColor: TColor);
  301. var
  302.   R: TRect;
  303. begin
  304.   R.Assign(0, 0, 44, 7);
  305.   inherited Init(R, 'Promote Pawn');
  306.   Flags := Flags and not (wfGrow + wfClose + wfZoom);
  307.   Options := Options or ofCentered;
  308.   R.Assign(3, 2, 11, 6);
  309.   Insert(New(PGlyphButton, Init(R, pQueen, AColor, '~Q~', cmQueen,
  310.     bfNormal + bfGrabFocus)));
  311.   Inc(R.A.X, 10); Inc(R.B.X, 10);
  312.   Insert(New(PGlyphButton, Init(R, pRook, AColor, '~R~', cmRook,
  313.     bfNormal + bfGrabFocus)));
  314.   Inc(R.A.X, 10); Inc(R.B.X, 10);
  315.   Insert(New(PGlyphButton, Init(R, pBishop, AColor, '~B~', cmBishop,
  316.     bfNormal + bfGrabFocus)));
  317.   Inc(R.A.X, 10); Inc(R.B.X, 10);
  318.   Insert(New(PGlyphButton, Init(R, pKnight, AColor, '~K~', cmKnight,
  319.     bfNormal + bfGrabFocus)));
  320.   SelectNext(False);
  321. end;
  322.  
  323. function TPromoteDialog.GetPalette: PPalette;
  324. const
  325.   P: String[Length(CPromoteDialog)] = CPromoteDialog;
  326. begin
  327.   GetPalette := @P;
  328. end;
  329.  
  330. procedure TPromoteDialog.HandleEvent(var Event: TEvent);
  331. begin
  332.   case Event.What of
  333.     evCommand:
  334.       begin
  335.         case Event.Command of
  336.           cmQueen,
  337.           cmRook,
  338.           cmKnight,
  339.           cmBishop: if State and sfModal <> 0 then EndModal(Event.Command);
  340.         else
  341.           Exit;
  342.         end;
  343.         ClearEvent(Event);
  344.       end;
  345.     evKeyDown:
  346.       case Event.KeyCode of
  347.         kbEnter:
  348.           begin
  349.             Event.What := evBroadcast;
  350.             Event.Command := cmDefault;
  351.             Event.InfoPtr := nil;
  352.             PutEvent(Event);
  353.             ClearEvent(Event);
  354.           end;
  355.         kbEsc: ClearEvent(Event);
  356.       end;
  357.   end;
  358.   inherited HandleEvent(Event);
  359. end;
  360.  
  361. { TChessPiece }
  362.  
  363. constructor TChessPiece.Init(var Bounds: TRect; APieceType: TSquare; ALocation: TLocation);
  364. begin
  365.   inherited Init(Bounds);
  366.   EventMask := EventMask or (evMove + evBroadcast);
  367.   PieceType := APieceType;
  368.   Location := ALocation;
  369. end;
  370.  
  371. constructor TChessPiece.Load(var S: TStream);
  372. begin
  373.   inherited Load(S);
  374.   S.Read(PieceType, SizeOf(PieceType) + SizeOf(TLocation));
  375. end;
  376.  
  377. procedure TChessPiece.CapturePiece;
  378. begin
  379.   PChessBoard(Owner)^.RemovePiece(@Self, Location);
  380.   Free;
  381. end;
  382.  
  383. { CheckJeopardy takes the valid move list of the opponent and looks
  384.   for any move that will capture this piece. }
  385.  
  386. procedure TChessPiece.CheckJeopardy(var MoveArray: array of TMove);
  387. var
  388.   X: Integer;
  389.   OldState: Boolean;
  390. begin
  391.   OldState := InJeopardy;
  392.   InJeopardy := False;
  393.   X := 0;
  394.   while (not InJeopardy) and
  395.         (X <= High(MoveArray)) and
  396.         (MoveArray[X].Change.Piece <> pEmpty) do
  397.   begin
  398.     InJeopardy := (Word(MoveArray[X].Change.Dest) = Word(Location));
  399.     Inc(X);
  400.   end;
  401.   if OldState xor InJeopardy then  { If state has changed, redraw }
  402.     DrawView;
  403. end;
  404.  
  405. procedure TChessPiece.Draw;
  406. var
  407.   I: Integer;
  408.   B: TDrawBuffer;
  409.   R: TRect;
  410.   XOfs, XLen: Integer;
  411.   WasVisible: Boolean;
  412.  
  413.   procedure DoDraws(P: PView);
  414.   var
  415.     Bounds: TRect;
  416.   begin
  417.     while P <> nil do
  418.     begin
  419.       if P^.State and sfVisible <> 0 then
  420.       begin
  421.         P^.GetBounds(Bounds);
  422.         Bounds.Intersect(R);
  423.         if not Bounds.Empty then
  424.           P^.DrawView;
  425.       end;
  426.       P := P^.NextView;
  427.     end;
  428.   end;
  429.  
  430. begin
  431.   Owner^.Lock;
  432.   WasVisible := State and sfVisible <> 0;
  433.   State := State and not sfVisible;
  434.   GetBounds(R);
  435.   DoDraws(NextView);
  436.   if not WasVisible then
  437.   begin
  438.     Owner^.Unlock;
  439.     Exit;
  440.   end;
  441.   State := State or sfVisible;
  442.  
  443.   for I := 0 to 2 do
  444.   begin
  445.     RawDraw(B, 0, I, XOfs, XLen);
  446.     if XLen > 0 then
  447.       WriteBuf(XOfs, I, XLen, 1, B[XOfs]);
  448.   end;
  449.  
  450.   Owner^.Unlock;
  451. end;
  452.  
  453. function TChessPiece.GetPromotionPiece: TPiece;
  454. var
  455.   P: PWindow;
  456.   Result: Word;
  457. begin
  458.   if PieceType.Piece = pPawn then
  459.   begin
  460.     P := New(PPromoteDialog, Init(PieceType.Color));
  461.     Result := Application^.ExecView(Application^.ValidView(P));
  462.     GetPromotionPiece := TPiece(Result - cmQueen + Ord(pQueen));
  463.     Dispose(P, Done);
  464.   end
  465.   else GetPromotionPiece := PieceType.Piece;
  466. end;
  467.  
  468. procedure TChessPiece.HandleEvent(var Event: TEvent);
  469. var
  470.   E: TEvent;
  471.   R: TRect;
  472.   P: PChessPiece;
  473.   S: TSquare;
  474. begin
  475.   inherited HandleEvent(Event);
  476.   case Event.What of
  477.     evMouseDown:
  478.       if PChessBoard(Owner)^.CanMovePiece(PieceType.Color) then
  479.       begin
  480.         MakeFirst;
  481.         R.Assign(0, 0, Owner^.Size.X, Owner^.Size.Y);
  482.         Show;
  483.         DragView(Event, dmDragMove, R, Size, Size);
  484.         Hide;
  485.         SnapToSquare;
  486.       end;
  487.     evMove:
  488.       case Event.Command of
  489.         cmMovePiece:
  490.           with PMove(Event.InfoPtr)^ do
  491.             if (Kind in [kNormal, kEnPassant, kPawnPromote, kCastling]) and
  492.               (Word(Change.Source) = Word(Location)) then
  493.             begin
  494.               if (Kind = kPawnPromote) and (PieceType.Piece = pPawn) then
  495.                 PieceType.Piece := Change.Piece;
  496.               MoveToSquare(Change.Dest);
  497.             end
  498.             else if (PieceType.Piece = Contents) and Capture and
  499.               (Word(Change.Dest) = Word(Location)) then
  500.               CapturePiece
  501.             else if (Kind = kCastling) and (PieceType.Piece = pRook) and
  502.               (Word(RookSource) = Word(Location)) then
  503.               MoveToSquare(RookDest)
  504.             else if (Kind = kEnPassant) and (PieceType.Piece = Contents) and
  505.               Capture and (Word(EPCapture) = Word(Location)) then
  506.               CapturePiece;
  507.         cmUndoMove:
  508.           with PMove(Event.InfoPtr)^ do
  509.             if (Word(Change.Dest) = Word(Location)) then
  510.             begin
  511.               if (Kind = kPawnPromote) and (Change.Piece = PieceType.Piece) then
  512.                 PieceType.Piece := pPawn;
  513.               MoveToSquare(Change.Source);
  514.               if Capture then
  515.               begin
  516.                 S.Piece := Contents;
  517.                 if PieceType.Color = cWhite then
  518.                   S.Color := cBlack else S.Color := cWhite;
  519.                 case Kind of
  520.                   kNormal:
  521.                     begin
  522.                       SquareToLocal(Change.Dest, R.A, Owner^.Size.Y);
  523.                       R.Assign(R.A.X, R.A.Y, R.A.X + 6, R.A.Y + 3);
  524.                       P := New(PChessPiece, Init(R, S, Change.Dest));
  525.                     end;
  526.                   kEnPassant:
  527.                     begin
  528.                       SquareToLocal(EPCapture, R.A, Size.Y);
  529.                       R.Assign(R.A.X, R.A.Y, R.A.X + 6, R.A.Y + 3);
  530.                       P := New(PChessPiece, Init(R, S, EPCapture));
  531.                     end;
  532.                 end;
  533.                 PChessBoard(Owner)^.InsertPiece(P, P^.Location);
  534.               end;
  535.             end
  536.             else if (Kind = kCastling) and (PieceType.Piece = pRook) and
  537.               (Word(RookDest) = Word(Location)) then
  538.               MoveToSquare(RookSource);
  539.         cmFindPiece:
  540.           if Event.InfoWord = Word(Location) then
  541.             ClearEvent(Event);
  542.       end;
  543.     evBroadcast:
  544.       case Event.Command of
  545.         cmRegisterSave: PCollection(Event.InfoPtr)^.Insert(@Self);
  546.       end;
  547.   end;
  548. end;
  549.  
  550. procedure TChessPiece.MoveToSquare(ALocation: TLocation);
  551. var
  552.   Point: TPoint;
  553. begin
  554.   PChessBoard(Owner)^.MovePiece(@Self, Location, ALocation);
  555.   Location := ALocation;
  556.   SquareToLocal(Location, Point, Owner^.Size.Y);
  557.   MoveTo(Point.X, Point.Y);
  558. end;
  559.  
  560. function TChessPiece.PerformMove(C: TChange): Boolean;
  561. var
  562.   Result: TChessError;
  563. begin
  564.   PerformMove := True;
  565.   Result := PChessBoard(Owner)^.ValidateMove(C);
  566.   case Result of
  567.     ceOK: Message(Owner, evMove, cmSubmitMove, @C);
  568.     ceAmbiguousMove:
  569.       begin
  570.         C.Piece := GetPromotionPiece;
  571.         Message(Owner, evMove, cmSubmitMove, @C);
  572.       end;
  573.   else
  574.     PerformMove := False;
  575.   end;
  576. end;
  577.  
  578. procedure TChessPiece.RawDraw(var B: TDrawBuffer; BufPos, Line: Integer;
  579.   var XOfs, XLen: Integer);
  580. var
  581.   Color: Word;
  582. begin
  583.   if PieceType.Color = cBlack then
  584.     Color := $0404 else Color := $0505;
  585.   if InJeopardy then Color := Color + $0202;
  586.   Color := GetColor(Color);
  587.   XOfs := PiecePicture[PieceType.Piece][Line].x;
  588.   XLen := Length(PiecePicture[PieceType.Piece][Line].s);
  589.   if XLen > 0 then
  590.     MoveStr(B[BufPos + XOfs], PiecePicture[PieceType.Piece][Line].s, Color);
  591. end;
  592.  
  593. procedure TChessPiece.SnapToSquare;
  594. var
  595.   S: TLocation;
  596.   P: TPoint;
  597.   C: TChange;
  598. begin
  599.   P.X := Origin.X + (Size.X div 2);
  600.   P.Y := Origin.Y + (Size.Y div 2);
  601.   PointInSquare(P, S);
  602.   C.Piece := pEmpty;
  603.   C.Source := Location;
  604.   C.Dest := S;
  605.   if not PerformMove(C) then
  606.   begin
  607.     SquareToLocal(Location, P, Owner^.Size.Y);
  608.     MoveTo(P.X, P.Y);
  609.   end;
  610.   PChessBoard(Owner)^.DrawSurface;
  611. end;
  612.  
  613. procedure TChessPiece.Store(var S: TStream);
  614. begin
  615.   inherited Store(S);
  616.   S.Write(PieceType, SizeOf(PieceType) + SizeOf(TLocation));
  617. end;
  618.  
  619. end.
  620.