home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / tcp / Networking / TCP / Server / AmiSlate / SlateRexx / chess.rexx < prev    next >
OS/2 REXX Batch file  |  1995-03-24  |  39KB  |  1,261 lines

  1. /* Chess for AmiSlate v1.0! */
  2.  
  3. /* Constants for use with AmiSlate's ARexx interface */
  4. AMode.DOT      =  0 
  5. AMode.PEN      =  1 
  6. AMode.LINE     =  2 
  7. AMode.CIRCLE   =  3 
  8. AMode.SQUARE   =  4 
  9. AMode.POLY     =  5 
  10. AMode.FLOOD    =  6 
  11. AMode.DTEXT    =  7 
  12.  
  13. AMessage.TIMEOUT     = 1    /* No events occurred in specified time period */
  14. AMessage.MESSAGE     = 2    /* Message recieved from remote Amiga */
  15. AMessage.MOUSEDOWN   = 4    /* Left mouse button press in drawing area */
  16. AMessage.MOUSEUP     = 8    /* Left mouse button release in drawing area */
  17. AMessage.RESIZE      = 16    /* Window was resized--time to redraw screen? */ 
  18. AMessage.QUIT        = 32    /* AmiSlate is shutting down */
  19. AMessage.CONNECT     = 64    /* Connection established */
  20. AMessage.DISCONNECT  = 128    /* Connection broken */
  21. AMessage.TOOLSELECT  = 256    /* Tool Selected */
  22. AMessage.COLORSELECT = 512    /* Palette Color selected */
  23. AMessage.KEYPRESS    = 1024    /* Key pressed */
  24.  
  25. ACTIVE  = 1
  26. PASSIVE = 0
  27.  
  28. /* Chess specific constants */
  29. GlobData.HILITEPEN = 2
  30. GlobData.SQUAREPEN1 = 3        /* It would probably be better to get these */
  31. GlobData.SQUAREPEN2 = 4        /* dynamically, wouldn't it? */
  32. GlobData.SIDE1PEN   = 2
  33. GlobData.SIDE2PEN   = 1
  34. GlobData.moverr = "No error"
  35.  
  36. piece.BLANK  = 0
  37. piece.PAWN   = 1
  38. piece.ROOK   = 2
  39. piece.KNIGHT = 4
  40. piece.BISHOP = 8
  41. piece.QUEEN  = 16
  42. piece.KING   = 32
  43.  
  44. /* Defaults */
  45. BInitialSquareSet = 0
  46.  
  47. /* Get our host's name--always given as first argument when run from Amislate */
  48. parse arg CommandPort ActiveString
  49.  
  50. if (length(CommandPort) == 0) then do
  51.     say ""
  52.     say "Usage:  rx chess.rexx <REXXPORTNAME>"
  53.     say "        (REXXPORTNAME is usually AMISLATE)"
  54.     say ""
  55.     say "Or run from the Rexx menu within AmiSlate."
  56.     say ""
  57.     exit 0
  58.     end
  59.     
  60. /* Send all commands to this host */
  61. address (CommandPort) 
  62. options results
  63.  
  64. /* Reserves pixels for a future toolbar -- currently, none */
  65. GlobData.ToolBarHeight = 0
  66.  
  67. /* Check to see which tool is selected, whether we are connected */
  68. GlobData.BFlood = 0
  69. GetStateAttrs stem stateattrs.
  70.  
  71. if (stateattrs.mode > 1) then GlobData.BFlood = 1
  72.  
  73. /* Parse command line argument to see if we've been activated by 
  74.    a remote request or a local user */
  75. check = upper(left(ActiveString,3))
  76. if (upper(left(ActiveString,3)) ~= 'RE') then 
  77.     do
  78.         GlobData.BActive = 1
  79.     end
  80.     else
  81.     do    
  82.         GlobData.BActive = 0
  83.     end
  84.  
  85. /* See if we're connected */
  86. GetRemoteStateAttrs stem rstateattrs.
  87.  
  88. if (rstateattrs.mode > -1) then 
  89.     do
  90.         GlobData.BConnectMode = 1
  91.     end
  92.     else
  93.     do
  94.         GlobData.BConnectMode = 0
  95.     end
  96.     
  97. 'lock on'            /* keep user from drawing */
  98. 'lockpalette on'        /* match colors, if possible */
  99.  
  100. success = InitChessArray()
  101.  
  102. /* Initiator goes first */
  103. GlobData.turn = ACTIVE
  104.  
  105.  
  106. /* Handshaking for two-computer game */
  107. if (GlobData.BConnectMode = 1) then 
  108. do
  109.     if (GlobData.BActive == 1) then 
  110.     do
  111.         SetWindowTitle '"'||"Requesting game from remote user"||'"' 
  112.     RemoteRexxCommand '"'||"Would you like to play chess?"||'"' "slaterexx:chess.rexx"
  113.     
  114.         waitevent stem handshake. MESSAGE
  115.         if (handshake.message == 0) then 
  116.         do
  117.             SetWindowTitle '"'||"Chess Game Refused"||'"'
  118.             exit
  119.         end
  120.     success = DrawChessBoard()
  121.     SetRemoteWindowTitle '"'||"Their turn (White)"||'"'
  122.     end
  123.     else
  124.     do
  125.         /* Examine window to get dimensions */
  126.     GetWindowAttrs stem winattrs.
  127.        GlobData.BoardWidth = winattrs.width  - 58
  128.        GlobData.BoardHeight= winattrs.height - 53 - GlobData.ToolBarHeight
  129.     end
  130. end
  131. else 
  132. do
  133.     success = DrawChessBoard()
  134. end        
  135.  
  136. /* If we're in line mode, tell the remote client */
  137. if (GlobData.BActive == 1) then sendmessage "*****"||GlobData.BFlood
  138.  
  139.  
  140.  
  141. success = UpdateStatus()
  142. do while(1)
  143.     waitevent stem event. RESIZE MOUSEDOWN MOUSEUP TOOLSELECT MESSAGE DISCONNECT
  144.  
  145.     if (event.type == AMessage.DISCONNECT) then GlobData.BConnectMode = 0
  146.     if (event.type == AMessage.QUIT) then exit
  147.     if (event.type == AMessage.RESIZE) then do
  148.         if ((GlobData.BActive == 1)|(GlobData.BConnectMode == 0)) then do
  149.            success = DrawChessBoard()
  150.         end
  151.         else do
  152.            /* Just examine window to get new dimensions */
  153.            GetWindowAttrs stem winattrs.
  154.            GlobData.BoardWidth = winattrs.width  - 58
  155.            GlobData.BoardHeight= winattrs.height - 53 - GlobData.ToolBarHeight
  156.         end
  157.              success = UpdateStatus()
  158.     end
  159.  
  160.     if (event.type == AMessage.MESSAGE) then do
  161.         success = ParseMove(event.message)
  162.         if (success == 1) then do
  163.              GlobData.turn = GlobData.BActive
  164.              success = UpdateStatus()
  165.              end
  166.         end
  167.         
  168.     if ((event.type = AMessage.TOOLSELECT)&(GlobData.BActive == 1)) then do
  169.         BOldFlood = GlobData.BFlood
  170.         if (event.code1 < 1) then GlobData.BFlood = 0
  171.         if (event.code1 >= 1) then GlobData.BFlood = 1
  172.         if ((event.code1 = 7)|(GlobData.BFlood ~= BOldFlood)) then do
  173.             success = DrawChessBoard()
  174.             sendmessage "*****"||GlobData.BFlood
  175.             end
  176.         end
  177.  
  178.     if (((event.type = AMessage.MOUSEDOWN)|((event.type = AMessage.MOUSEUP)&(BInitialSquareSet = 1)))&((GlobData.turn = GlobData.BActive)|(GlobData.BConnectMode = 0))) then do
  179.         xtemp = event.x
  180.         SelectChessSquareX = -1
  181.         do while (xtemp > 0)
  182.             xtemp = xtemp - trunc(GlobData.BoardWidth / 8)
  183.             SelectChessSquareX = SelectChessSquareX + 1
  184.             end
  185.         ytemp = event.y
  186.         SelectChessSquareY = -1
  187.         do while (ytemp > GlobData.ToolBarHeight)
  188.             ytemp = ytemp - trunc(GlobData.BoardHeight / 8)
  189.             SelectChessSquareY = SelectChessSquareY + 1
  190.             end
  191.  
  192.         ThisSquare = ChessBoard.SelectChessSquareX.SelectChessSquareY        
  193.         if (((GlobData.turn == ACTIVE)&(ThisSquare > 0))|((GlobData.turn == PASSIVE)&(ThisSquare < 0))|(BInitialSquareSet == 1)) then do
  194.    
  195.                /* HiLite selected square */
  196.             success = SelectChessSquare(SelectChessSquareX, SelectChessSquareY, GlobData.HILITEPEN)
  197.     
  198.              if (BInitialSquareSet = 0) then do
  199.                 BInitialSquareSet = 1
  200.                 SelectedSquareX = SelectChessSquareX
  201.                 SelectedSquareY = SelectChessSquareY
  202.                 end
  203.             else do
  204.                 /* De-HiLite old square */
  205.                 sqc = SquareColor(SelectedSquareX, SelectedSquareY)
  206.                 success = SelectChessSquare(SelectedSquareX, SelectedSquareY, sqc)
  207.             
  208.                 /* De-HiLite this square--move done! */    
  209.                 sqc = SquareColor(SelectChessSquareX, SelectChessSquareY)
  210.                 success = SelectChessSquare(SelectChessSquareX,SelectChessSquareY, sqc)
  211.     
  212.                 BInitialSquareSet = 0
  213.  
  214.             GlobData.moverr = "No error"
  215.  
  216.             moveResult = MovePiece(SelectedSquareX, SelectedSquareY, SelectChessSquareX, SelectChessSquareY)
  217.             if (moveResult > 0) then do
  218.                     szSendString = "1" || selectedSquareX || SelectedSquareY || SelectChessSquareX || SelectChessSquareY || moveResult
  219.                     sendmessage szSendString
  220.                     if (GlobData.turn == 1) then do
  221.                         GlobData.turn = 0
  222.                         end
  223.                     else do
  224.                         GlobData.turn = 1
  225.                         end
  226.                     success = UpdateStatus()
  227.                     end
  228.                 else do
  229.                     SetWindowTitle '"'||"Error: "|| GlobData.moverr || '"'
  230.                     DisplayBeep
  231.                     end
  232.                 end
  233.             end
  234.         end
  235.     end
  236. exit
  237.  
  238.  
  239.  
  240. /* --------------------------------------------------------------- */
  241. /* procedure MovePiece                           */
  242. /* --------------------------------------------------------------- */
  243. MovePiece: procedure expose ChessBoard. piece. PiecePosX. PiecePosY. GlobData.
  244.     parse arg OldX, OldY, X, Y
  245.     
  246.     if (CheckMove(OldX, OldY, X, Y, 1) == 0) then do
  247.         return 0    
  248.         end
  249.         
  250.     /* Special case for castling--king moves to earlier square */
  251.     if (abs(ChessBoard.OldX.OldY) == Piece.King) then do
  252.         if ((OldX == 3)&(X == 0)) then X = 1
  253.         if ((OldX == 3)&(X == 7)) then X = 6
  254.         end
  255.                 
  256.     if (UpdatePiecePos(OldX, OldY, X, Y) == 0) then do
  257.         EasyRequest Chess_Error "555:UPP_failed" Okay
  258.         return 0
  259.         end    
  260.     
  261.     /* Was there a death here?  If so, remove dying piece */
  262.     if (ChessBoard.X.Y ~= Piece.BLANK) then do
  263.         VictimPiece = GetPiecePos(X, Y)
  264.         if (VictimPiece > 0) then do
  265.             PiecePosX.1.VictimPiece = 9999
  266.             PiecePosY.1.VictimPiece = 9999
  267.             end
  268.         else do
  269.             VictimPiece = abs(VictimPiece)
  270.             PiecePosX.2.VictimPiece = 9999
  271.             PiecePosY.2.VictimPiece = 9999
  272.             end
  273.         end
  274.  
  275.     returnresult = 1
  276.     
  277.     /* Check for pawn promotion */
  278.     if (((Y == 7)&(ChessBoard.OldX.OldY == Piece.PAWN))|((Y == 0)&(ChessBoard.OldX.OldY == -Piece.PAWN))) then do
  279.             if (ChessBoard.OldX.OldY = Piece.PAWN) then do
  280.                 tSide = 1
  281.                 end
  282.             else do
  283.                 tSide = -1
  284.             end
  285.             
  286.             EasyRequest '"'||"Your pawn is getting a promotion!"||'"' '"'||"What do you want to promote your pawn to?"||'"' "Queen|Rook|Bishop|Knight"
  287.         if (rc == 0) then ChessBoard.OldX.OldY = tSide * Piece.Knight
  288.         if (rc == 1) then ChessBoard.OldX.OldY = tSide * Piece.Queen
  289.         if (rc == 2) then ChessBoard.OldX.OldY = tSide * Piece.Rook
  290.         if (rc == 3) then ChessBoard.OldX.OldY = tSide * Piece.Bishop
  291.         returnresult = rc + 2    /* For transmission */
  292.     end
  293.     
  294.     ChessBoard.X.Y = ChessBoard.OldX.OldY              /* Then put the piece in the new spot! */
  295.     ChessBoard.OldX.OldY = Piece.BLANK
  296.     
  297.     success=DrawPiece(OldX, OldY, ChessBoard.OldX.OldY, GlobData.BFlood)
  298.     success=DrawPiece(X, Y, ChessBoard.X.Y, GlobData.BFlood)
  299.                     
  300.     return returnresult
  301.  
  302.  
  303. /* --------------------------------------------------------------- */
  304. /* procedure MoveCreatesCheck                           */
  305. /*                                   */
  306. /* This procedure will determine if the move (OldX,OldY)->(X,Y)    */
  307. /* will get the piece at CheckX, CheckY into danger (i.e. check    */
  308. /* for a king, etc. ) without affecting the board              */
  309. /* --------------------------------------------------------------- */
  310. MoveCreatesCheck: procedure expose ChessBoard. piece. PiecePosX. PiecePosY. 
  311.     parse arg OldX, OldY, X, Y, CheckX, CheckY
  312.     
  313.     if (ChessBoard.OldX.OldY == Piece.BLANK) then do
  314.         EasyRequest Chess_Error "MoveCreatesCheck:_Bad_Attacker!" Okay
  315.         return 1
  316.         end
  317.     
  318.     AttackerPiece = ChessBoard.OldX.OldY
  319.     AttackerID = GetPiecePos(OldX, OldY)
  320.     if (AttackerID == 0) then do
  321.         EasyRequest Chess_Error "MoveCreatesCheck:_Anonymous_Attacker!" Okay
  322.         return 1
  323.         end
  324.     if (AttackerID < 0) then do
  325.         AttackerID = abs(AttackerID)
  326.         nAttackerSide = 2
  327.         end
  328.     else do
  329.         nAttackerSide = 1
  330.         end
  331.             
  332.     TargetPiece = ChessBoard.X.Y
  333.     TargetID    = 0            /* Default = unset/error */    
  334.     if (TargetPiece ~= Piece.BLANK) then do
  335.     TargetID = GetPiecePos(X,Y)
  336.     if (TargetID == 0) then do
  337.         EasyRequest Chess_Error "MoveCreatesCheck:_Anonymous_defender!" Okay
  338.         return 1
  339.         end
  340.     if (TargetID < 0) then do
  341.         TargetID = abs(TargetID)
  342.         nTargetSide = 2
  343.         end
  344.     else do
  345.         nTargetSide = 1
  346.         end
  347.     PiecePosX.nTargetSide.TargetID = 9999
  348.     PiecePosY.nTargetSide.TargetID = 9999
  349.     end
  350.  
  351.     /* Move the attacker, on both arrays */
  352.         PiecePosX.nAttackerSide.AttackerID = X
  353.         PiecePosY.nAttackerSide.AttackerID = Y
  354.     ChessBoard.X.Y = AttackerPiece              /* Then put the piece in the new spot! */
  355.  
  356.     /* Erase the attacker from his old position */
  357.     ChessBoard.OldX.OldY = Piece.BLANK
  358.  
  359.     /* Now see if we have a check situation */
  360.     returnFlag = IsInCheck(CheckX,CheckY)
  361.     
  362.     /* Clean up from our little sim -- move piece back and replace victim */
  363.     ChessBoard.OldX.OldY = AttackerPiece
  364.     PiecePosX.nAttackerSide.AttackerID = OldX
  365.     PiecePosY.nAttackerSide.AttackerID = OldY
  366.     
  367.     ChessBoard.X.Y = TargetPiece
  368.     if (TargetID ~= 0) then do
  369.         PiecePosX.nTargetSide.TargetID = X
  370.         PiecePosY.nTargetSide.TargetID = Y
  371.         end
  372.     
  373.     return ReturnFlag
  374.     
  375.  
  376.     
  377. /* --------------------------------------------------------------- */
  378. /* procedure UpdatePiecePos                               */
  379. /* --------------------------------------------------------------- */
  380. UpdatePiecePos: procedure expose ChessBoard. PiecePosX. PiecePosY.
  381.     parse arg OldX, OldY, X, Y
  382.     
  383.     ThisPiece = GetPiecePos(OldX, OldY)
  384.     
  385.     if (ThisPiece == 0) then do
  386.         EasyRequest Chess_Error "UpdatePiecePos:update_empty_square?_huh?" Okay
  387.         return 0
  388.         end
  389.         
  390.     if (ThisPiece > 0) then do
  391.         PiecePosX.1.ThisPiece = X
  392.         PiecePosY.1.ThisPiece = Y
  393.         return 1
  394.         end
  395.     else do
  396.         ThisPiece = abs(ThisPiece)
  397.         PiecePosX.2.ThisPiece = X
  398.         PiecePosY.2.ThisPiece = Y
  399.         return 1
  400.         end
  401.     
  402.     EasyRequest Chess_Error "UpdatePiecePos_error-not_found" Okay
  403.     return 0
  404.  
  405.  
  406.  
  407.  
  408. /* --------------------------------------------------------------- */
  409. /* procedure GetPiecePos                              */
  410. /*                                   */
  411. /* Given a set of co-ordinates, this function returns the PiecePos */
  412. /* index/ID of the piece there.  Positive values is for Side1 (top */
  413. /* and negative values are for side2 (bottom).  0 = blank/error.   */
  414. /* --------------------------------------------------------------- */
  415. GetPiecePos: procedure expose PiecePosX. PiecePosY. ChessBoard.
  416.     parse arg X, Y
  417.     
  418.     if ((ChessBoard.X.Y == 0)|(X < 0)|(X > 7)|(Y < 0)|(Y > 7)) then return 0
  419.         
  420.     if (ChessBoard.X.Y > 0) then do
  421.         pi = 1
  422.         do while (pi < 17)
  423.             if ((PiecePosX.1.pi == X)&(PiecePosY.1.pi == Y)) then do
  424.                 return pi
  425.                 end
  426.             pi = pi + 1
  427.             end
  428.         end
  429.     else do
  430.         pi = 1
  431.         do while (pi < 17)
  432.             if ((PiecePosX.2.pi == X)&(PiecePosY.2.pi == Y)) then do
  433.                 return -pi
  434.                 end
  435.             pi = pi + 1
  436.             end
  437.         end
  438.     return 0
  439.  
  440.  
  441. /* --------------------------------------------------------------- */
  442. /* procedure InternalMove                          */
  443. /*                                   */
  444. /* Updates all necessary piece movement vars in memory only        */
  445. /*                                   */
  446. /* --------------------------------------------------------------- */
  447. InternalMove: procedure expose ChessBoard. piece. PiecePosX. PiecePosY.
  448.     parse arg XFrom, YFrom, XTo, YTo
  449.  
  450.     if (UpdatePiecePos(XFrom, YFrom, XTo, YTo) == 0) then do
  451.         EasyRequest Chess_Error "997:UPP_failed" Okay
  452.         return 0
  453.         end    
  454.     ChessBoard.XTo.YTo = ChessBoard.XFrom.YFrom
  455.     ChessBoard.XFrom.YFrom = Piece.BLANK
  456.     return 1
  457.  
  458.  
  459.  
  460. /* --------------------------------------------------------------- */
  461. /* procedure CastleOkay                          */
  462. /*                                   */
  463. /* returns 1 if the castling move is okay, else zero                */
  464. /*                                   */
  465. /* --------------------------------------------------------------- */
  466. CastleOkay: procedure expose ChessBoard. piece. PiecePosX. PiecePosY. GlobData.
  467.     parse arg XFrom, YFrom, XTo, YTo
  468.  
  469.     GlobData.moverr = "Can't castle from there"
  470.  
  471.     /* Only can castle from King's starting position */
  472.     if (XFrom != 3) then do
  473.         GlobData.moverr = "Can't castle after king has moved"
  474.         return 0
  475.         end
  476.         
  477.     if (YFrom != YTo) then return 0
  478.         
  479.     /* First thing: determine what side we're on */
  480.     if (ChessBoard.XFrom.YFrom < 0) then do
  481.         SideToCheck = 2
  482.         if (YFrom != 7) then return 0
  483.         end
  484.     else do
  485.         SideToCheck = 1
  486.         if (YFrom != 0) then return 0
  487.         end
  488.         
  489.     /* can't castle if king has already moved */
  490.     if (ChessBoard.KingMoved.SideToCheck == 1) then do
  491.         GlobData.moverr = "Can't castle after king has moved"
  492.         return 0
  493.         end
  494.     
  495.     LeftOrRight = 0            /* Default = error */
  496.     if (XTo == 0) then do
  497.         LeftOrRight = 1        /* Left */
  498.         NewRookX = 2
  499.         NewKingX = 1
  500.         /* Can't castle if rook has moved */
  501.         if (ChessBoard.LeftRookMoved.SideToCheck == 1) then do
  502.             GlobData.moverr = "Can't castle after rook has moved"
  503.             return 0
  504.             end
  505.         end
  506.     if (XTo == 7) then do
  507.         LeftOrRight = 2     /* Right */
  508.         NewRookX = 5
  509.         NewKingX = 6
  510.         /* Can't castle if rook has moved */
  511.         if (ChessBoard.RightRookMoved.SideToCheck == 1) then do
  512.             GlobData.moverr = "Can't castle after rook has moved"
  513.             return 0
  514.             end
  515.         end        
  516.     if (LeftOrRight == 0) then do
  517.         GlobData.moverr = "You should never see this error"
  518.         return 0    /* This should never happen */
  519.         end    
  520.     
  521.     /* Make sure all spaces between king and rook are clear */
  522.     if (GlideOK(XFrom,YFrom,XTo,YTo) == 0) then do
  523.         GlobData.moverr = "There are pieces between king and rook"
  524.         return 0
  525.         end
  526.         
  527.     /* Can't castle out of check */
  528.     if (IsInCheck(XFrom,YFrom) == 1) then do
  529.         GlobData.moverr = "Can't castle out of check"
  530.         return 0
  531.         end
  532.     
  533.     /* Move rook to new position, in my head anyway */
  534.     if (InternalMove(XTo, YTo, newRookX, YTo) == 0) then return 0
  535.     
  536.     /* Move king to new position, in my head anyway */
  537.     if (InternalMove(XFrom, YFrom, newKingX, YFrom) == 0) then return 0
  538.  
  539.     /* See if this causes check */
  540.     if (IsInCheck(newKingX,YFrom) == 1) then do
  541.         /* oops, would be a move into check.  No can do! */
  542.         /* So move everything back! */
  543.  
  544.         /* Move rook back to old position, in my head anyway */
  545.         if (InternalMove(newRookX, YTo, XTo, YTo) == 0) then return 0
  546.         
  547.         /* Move king back to old position, in my head anyway */
  548.         if (InternalMove(newKingX, YFrom, XFrom, YFrom) == 0) then return 0
  549.  
  550.         GlobData.moverr = "Can't castle into check"
  551.         
  552.         /* and fail */
  553.         return 0
  554.         end
  555.         
  556.     /* If we're here, then the castle is acceptable.  Put the king
  557.        back for now--it'll be moved by the normal turn--but we'll 
  558.        move the rook ourselves! */
  559.     
  560.     /* Move king back to old position, in my head anyway */
  561.     if (InternalMove(newKingX, YFrom, XFrom, YFrom) == 0) then return 0
  562.     
  563.     /* Display and transmit the rook's move */
  564.     
  565.     /* Erase old rook */
  566.     success = DrawPiece(XTo, YTo, ChessBoard.XTo.YTo, GlobData.BFlood)
  567.     
  568.     /* Draw new rook */
  569.     success = DrawPiece(newRookX, YTo, ChessBoard.newRookX.YTo, GlobData.BFlood)
  570.     
  571.     /* Transmit move -- 2 means don't lose turn yet */
  572.     szSendString = "2" || XTo || YTo || newRookX || YTo || "0"
  573.         sendmessage szSendString
  574.  
  575.     return 1
  576.     
  577.  
  578. /* --------------------------------------------------------------- */
  579. /* procedure CheckMove                          */
  580. /* --------------------------------------------------------------- */
  581. CheckMove: procedure expose ChessBoard. piece. PiecePosX. PiecePosY. GlobData.
  582.     parse arg XFrom, YFrom, XTo, YTo, BCheckForCheck
  583.     
  584.     /* A move off of the board is illegal */
  585.     if ((XTo < 0)|(XTo > 7)|(YTo < 0)|(YTo > 7)) then do
  586.         GlobData.moverr = "Can't move off of board"
  587.         return 0
  588.         end
  589.         
  590.     /* A move from off of the board is illegal */
  591.     if ((XFrom < 0)|(XFrom > 7)|(YFrom < 0)|(YFrom > 7)) then do
  592.         GlobData.moverr = "Can't move from off of board"
  593.         return 0
  594.         end
  595.         
  596.     /* Blanks can't move */
  597.     if (ChessBoard.XFrom.YFrom == Piece.BLANK) then do
  598.         GlobData.moverr = "Can't move a blank square"
  599.         return 0
  600.         end
  601.  
  602.     
  603.     /* A move to the same spot we're on is illegal */
  604.     if ((XFrom == XTo)&(YFrom == YTo)) then do
  605.         GlobData.moverr = "Can't move onto yourself"
  606.         return 0
  607.         end
  608.  
  609.     /* A move onto one of your own pieces is illegal */
  610.     if ((ChessBoard.XTo.YTo * ChessBoard.XFrom.YFrom) > 0) then do
  611.         /* except when you're castling */
  612.         if (((ChessBoard.XTo.YTo == Piece.Rook)&(ChessBoard.XFrom.YFrom == Piece.King))|((ChessBoard.XTo.YTo == -Piece.Rook)&(ChessBoard.XFrom.YFrom == -Piece.King))) then do
  613.              /* nothing right now, we'll check for castling later */
  614.              end 
  615.         else do
  616.              GlobData.moverr = "Can't attack your own piece"
  617.              return 0
  618.              end
  619.     end
  620.     
  621.     /* Rules for the PAWN */    
  622.     if (abs(ChessBoard.XFrom.YFrom) == Piece.PAWN) then do
  623.         GlobData.moverr = "Bad pawn move"
  624.         if (ChessBoard.XFrom.YFrom < 0) then do
  625.             PawnMoveDir = -1 
  626.             end
  627.             else PawnMoveDir = 1
  628.         if ((XTo == XFrom)&(ChessBoard.XTo.YTo ~= Piece.BLANK)) then do
  629.             GlobData.moverr = "Pawn can't attack forward"
  630.              return 0
  631.              end
  632.         if ((XTo == XFrom)&(abs(YFrom - YTo) == 2)) then do
  633.             /* First move for a pawn can be two spaces, if both spaces are blank */
  634.             Ytemp = YFrom+PawnMoveDir
  635.             if ((ChessBoard.XFrom.Ytemp) ~= Piece.BLANK) then return 0
  636.             if ((YFrom == 1)&(PawnMoveDir ~= 1)) then return 0
  637.             if ((YFrom == 6)&(PawnMoveDir ~= -1)) then return 0
  638.             if ((YFrom ~= 1)&(YFrom ~= 6)) then return 0
  639.             end
  640.         else do
  641.             if (YTo ~= (YFrom + PawnMoveDir)) then return 0
  642.             if (abs(XFrom - XTo) > 1) then return 0
  643.             if ((abs(XFrom - XTo) == 1)&(ChessBoard.XTo.YTo == Piece.BLANK)) then return 0    
  644.             end
  645.         end 
  646.     
  647.     /* Rules for the ROOK */
  648.     if (abs(ChessBoard.XFrom.YFrom) == Piece.ROOK) then do
  649.         if ((XFrom ~= XTo)&(YFrom ~= YTo)) then do
  650.             GlobData.moverr = "Rook must move horizontally or vertically"
  651.             return 0
  652.             end
  653.         if (GlideOK(XFrom,YFrom,XTo,YTo) == 0) then do
  654.             GlobData.moverr = "Move is blocked"
  655.             return 0
  656.             end
  657.         end
  658.         
  659.     /* Rules for the KNIGHT */
  660.     if (abs(ChessBoard.XFrom.YFrom) == Piece.KNIGHT) then do
  661.         GlobData.moverr = "Bad knight move"
  662.         if (((abs(XFrom - XTo) ~= 2)|(abs(YFrom - YTo) ~= 1))&((abs(XFrom - XTo) ~= 1)|(abs(YFrom - YTo) ~= 2))) then return 0
  663.         end
  664.         
  665.     /* Rules for the BISHOP */
  666.     if (abs(ChessBoard.XFrom.YFrom) == Piece.BISHOP) then do
  667.         if (abs(XFrom - XTo) ~= abs(YFrom - YTo)) then do
  668.             GlobData.moverr = "Bishop must move diagonally"
  669.             return 0
  670.             end
  671.         if (GlideOK(XFrom,YFrom,XTo,YTo) == 0) then do
  672.             GlobData.moverr = "Move is blocked"
  673.             return 0
  674.             end
  675.         end
  676.  
  677.     /* Rules for the QUEEN */
  678.     if (abs(ChessBoard.XFrom.YFrom) == Piece.QUEEN) then do
  679.         if ((abs(XFrom - XTo) ~= abs(YFrom - YTo))&((XFrom ~= XTo)&(YFrom ~= YTo))) then do
  680.             GlobData.moverr = "Queen must move in a straight line"
  681.             return 0
  682.             end
  683.         if (GlideOK(XFrom,YFrom,XTo,YTo) == 0) then do
  684.             GlobData.moverr = "Move is blocked"
  685.             return 0
  686.             end
  687.         end
  688.  
  689.     /* Rules for the KING */
  690.     if (abs(ChessBoard.XFrom.YFrom) == Piece.KING) then do
  691.         if (((ChessBoard.XTo.YTo == Piece.ROOK)&(ChessBoard.XFrom.YFrom == Piece.KING))|((ChessBoard.XTo.YTo == -Piece.ROOK)&(ChessBoard.XFrom.YFrom == -Piece.KING)))
  692.            then do
  693.                 if (CastleOkay(XFrom,YFrom,XTo,YTo) == 0) then return 0
  694.                 end
  695.            else do
  696.             if ((abs(XTo - XFrom) > 1)|(abs(YTo - YFrom) > 1)) then do
  697.                 GlobData.moverr = "King can only move 1 square"
  698.                 return 0
  699.                 end
  700.            end
  701.     end
  702.     
  703.     if (BCheckForCheck == 0) then return 1
  704.     
  705.     /* Get king's co-ordinates */
  706.     if (Chessboard.XFrom.YFrom > 0) then do
  707.         KingPosX = PiecePosX.1.1
  708.         KingPosY = PiecePosY.1.1        
  709.         end
  710.     else do
  711.         KingPosX = PiecePosX.2.1
  712.         KingPosY = PiecePosY.2.1
  713.         end
  714.  
  715.     /* If king is moving, check were he WILL be, not where he IS */
  716.     if (abs(ChessBoard.XFrom.YFrom) == Piece.KING) then do
  717.         KingPosX = XTo
  718.         KingPosY = YTo
  719.         end
  720.         
  721.     if (MoveCreatesCheck(XFrom, YFrom, XTo, YTo, KingPosX, KingPosY) == 1) then do
  722.         if (abs(ChessBoard.XFrom.YFrom) == Piece.KING) then do
  723.                 GlobData.moverr = "Move would put you in check"
  724.             end
  725.             else do
  726.                 GlobData.moverr = "Move does not remove you from check"
  727.             end
  728.         return 0
  729.         end
  730.             
  731.     /* If we passed all these tests, we're ok */        
  732.  
  733.     /* If it's a rook or a king, set the appropriate moved flag */
  734.     if (ChessBoard.XFrom.YFrom == Piece.King) then ChessBoard.KingMoved.1 = 1
  735.     if (ChessBoard.XFrom.YFrom == -Piece.King) then ChessBoard.KingMoved.2 = 1
  736.     
  737.     if (ChessBoard.XFrom.YFrom == Piece.Rook) then do
  738.         if ((XFrom == 0)&(YFrom == 0)) then ChessBoard.LeftRookMoved.1 = 1
  739.         if ((XFrom == 7)&(YFrom == 0)) then ChessBoard.RightRookMoved.1 = 1
  740.         end
  741.     if (ChessBoard.XFrom.YFrom == -Piece.Rook) then do
  742.         if ((XFrom == 0)&(YFrom == 7)) then ChessBoard.LeftRookMoved.2 = 1
  743.         if ((XFrom == 7)&(YFrom == 7)) then ChessBoard.RightRookMoved.2 = 1
  744.         end
  745.                     
  746.     return 1
  747.     
  748.     
  749.     
  750. /* --------------------------------------------------------------- */
  751. /* procedure GlideOK                              */
  752. /* --------------------------------------------------------------- */
  753. GlideOK:    procedure expose ChessBoard. piece.
  754.     parse arg XFrom, YFrom, XTo, YTo
  755.     
  756.     xd = 0
  757.     yd = 0
  758.         
  759.     if ((XTo - XFrom) > 0) then xd = 1
  760.     if ((XTo - XFrom) < 0) then xd = -1
  761.     if ((YTo - YFrom) > 0) then yd = 1
  762.     if ((YTo - YFrom) < 0) then yd = -1
  763.  
  764.     x = XFrom + xd    /* Start scanning after where piece already is */
  765.     y = YFrom + yd
  766.     
  767.     xgoal = XTo 
  768.     ygoal = YTo 
  769.     
  770.     do while ((x ~= xgoal)|(y ~= ygoal))
  771.         if (ChessBoard.x.y ~= Piece.BLANK) then return 0
  772.         if ((x<0)|(y<0)|(x>7)|(y>7)) then do
  773.             EasyRequest Chess_Error "Glide_error!" Okay
  774.             return 0
  775.             end
  776.         x = x + xd
  777.         y = y + yd
  778.         end
  779.         
  780.     return 1
  781.     
  782.  
  783. /* --------------------------------------------------------------- */
  784. /* procedure IsInCheck                           */
  785. /*                                    */
  786. /* returns 1 if the given square is in danger, otherwise 0         */
  787. /* --------------------------------------------------------------- */
  788. IsInCheck: procedure expose ChessBoard. PiecePosX. PiecePosY. piece.
  789.     parse arg X, Y
  790.         
  791.     
  792.     if (ChessBoard.X.Y == 0) then do
  793.         EasyRequest Chess_Error "IsInCheck_:_Square_is_empty!" Okay
  794.         return 0
  795.         end
  796.         
  797.     if (ChessBoard.X.Y > 0) then SideToCheck = 2
  798.     if (ChessBoard.X.Y < 0) then SideToCheck = 1
  799.     
  800.     pi = 1
  801.     do while (pi < 17)
  802.         if (CheckMove(PiecePosX.SideToCheck.pi,PiecePosY.SideToCheck.pi,X,Y,0) == 1) then return 1
  803.         pi = pi + 1
  804.     end
  805.     return 0
  806.  
  807.  
  808.  
  809. /* --------------------------------------------------------------- */
  810. /* procedure                                */
  811. /* --------------------------------------------------------------- */
  812. InitChessArray: procedure expose ChessBoard. piece. PiecePosX. PiecePosY.
  813.  
  814.    /* Set special castling info for both sides */
  815.    ChessBoard.KingMoved.1 = 0
  816.    ChessBoard.KingMoved.2 = 0
  817.    ChessBoard.LeftRookMoved.1  = 0
  818.    ChessBoard.RightRookMoved.1 = 0
  819.    ChessBoard.LeftRookMoved.2  = 0
  820.    ChessBoard.RightRookMoved.2 = 0
  821.    
  822.    /* Set Kings */
  823.    ChessBoard.3.0 = Piece.KING
  824.    ChessBoard.3.7 = -Piece.KING
  825.  
  826.    /* Set king position markers */
  827.    PiecePosX.1.1 = 3
  828.    PiecePosY.1.1 = 0
  829.    PiecePosX.2.1 = 3
  830.    PiecePosY.2.1 = 7
  831.  
  832.    /* Set Queens */
  833.    ChessBoard.4.0 = Piece.QUEEN
  834.    ChessBoard.4.7 = -Piece.QUEEN
  835.  
  836.    /* Set queen position markers */
  837.    PiecePosX.1.2 = 4
  838.    PiecePosY.1.2 = 0
  839.    PiecePosX.2.2 = 4
  840.    PiecePosY.2.2 = 7
  841.  
  842.    /* Set rooks */
  843.    ChessBoard.0.0 = Piece.ROOK
  844.    ChessBoard.7.0 = Piece.ROOK
  845.    ChessBoard.0.7 = -Piece.ROOK
  846.    ChessBoard.7.7 = -Piece.ROOK
  847.  
  848.    /* Set rook position markers */
  849.    PiecePosX.1.3 = 0
  850.    PiecePosY.1.3 = 0
  851.    PiecePosX.1.4 = 7
  852.    PiecePosY.1.4 = 0
  853.    
  854.    PiecePosX.2.3 = 0
  855.    PiecePosY.2.3 = 7
  856.    PiecePosX.2.4 = 7
  857.    PiecePosY.2.4 = 7
  858.    
  859.    /* Set knights */
  860.    ChessBoard.1.0 = Piece.KNIGHT
  861.    ChessBoard.6.0 = Piece.KNIGHT
  862.    ChessBoard.1.7 = -Piece.KNIGHT
  863.    ChessBoard.6.7 = -Piece.KNIGHT
  864.  
  865.    /* Set knight position markers */
  866.    PiecePosX.1.5 = 1
  867.    PiecePosY.1.5 = 0
  868.    PiecePosX.1.6 = 6
  869.    PiecePosY.1.6 = 0
  870.    
  871.    PiecePosX.2.5 = 1
  872.    PiecePosY.2.5 = 7
  873.    PiecePosX.2.6 = 6
  874.    PiecePosY.2.6 = 7
  875.  
  876.    /* Set bishops */
  877.    ChessBoard.2.0 = Piece.BISHOP
  878.    ChessBoard.5.0 = Piece.BISHOP
  879.    ChessBoard.2.7 = -Piece.BISHOP
  880.    ChessBoard.5.7 = -Piece.BISHOP
  881.  
  882.    /* Set bishop position markers */
  883.    PiecePosX.1.7 = 2
  884.    PiecePosY.1.7 = 0
  885.    PiecePosX.1.8 = 5
  886.    PiecePosY.1.8 = 0
  887.    
  888.    PiecePosX.2.7 = 2
  889.    PiecePosY.2.7 = 7
  890.    PiecePosX.2.8 = 5
  891.    PiecePosY.2.8 = 7   
  892.  
  893.    /* Set rows of pawns */
  894.    jx = 0
  895.    do while (jx < 8)
  896.        ChessBoard.jx.1 = Piece.PAWN
  897.        ppTemp = jx + 9
  898.        PiecePosX.1.ppTemp = jx
  899.        PiecePosY.1.ppTemp = 1
  900.     jx = jx + 1
  901.        end
  902.    
  903.    jx = 0
  904.    do while (jx < 8)
  905.     ChessBoard.jx.6 = -1        /* - means bottom team */
  906.        ppTemp = jx + 9
  907.        PiecePosX.2.ppTemp = jx
  908.        PiecePosY.2.ppTemp = 6
  909.     jx = jx + 1
  910.     end
  911.   
  912.    /* Center of board is all blanks */
  913.    jy = 2
  914.    do while (jy < 6)
  915.     jx = 0
  916.     do while (jx < 8)
  917.         ChessBoard.jx.jy = Piece.BLANK
  918.         jx = jx + 1
  919.     end
  920.     jy = jy + 1
  921.    end
  922.  
  923.    return 1
  924.  
  925.  
  926.  
  927. /* --------------------------------------------------------------- */
  928. /* procedure DrawChessBoard                       */
  929. /* --------------------------------------------------------------- */
  930. DrawChessBoard: procedure expose ChessBoard. GlobData. piece.
  931.  
  932.    /* Say what we're doing */
  933.    SetWindowTitle '"'||"Drawing Chess Board, Please Wait"||'"'
  934.    SetRemoteWindowTitle '"'||"Drawing Chess Board, Please Wait"||'"'
  935.  
  936.    /* Examine window to get dimensions */
  937.    GetWindowAttrs stem winattrs.
  938.    GlobData.BoardWidth = winattrs.width  - 58
  939.    GlobData.BoardHeight= winattrs.height - 53 - GlobData.ToolBarHeight
  940.  
  941.    /* Clear Screen */
  942.    clear
  943.    jy = 0
  944.    do while (jy < 8)
  945.     jx = 0
  946.     do while (jx < 8)
  947.         success = DrawPiece(jx, jy, ChessBoard.jx.jy, GlobData.BFlood)
  948.         jx = jx + 1
  949.     end
  950.     jy = jy + 1
  951.    end
  952.  
  953.    return 1
  954.     
  955. /* --------------------------------------------------------------- */
  956. /* procedure SquareColor                                              */
  957. /*                                                                      */
  958. /* Given the X,Y co-ordinates (0-7,0-7) of a chess square, return  */
  959. /* its pen color.                                                    */
  960. /* --------------------------------------------------------------- */
  961. SquareColor: procedure expose GlobData.
  962.     parse arg XX, YY
  963.  
  964. if ((XX+ YY)/2) = trunc((XX + YY)/2) then
  965.     return GlobData.SQUAREPEN1
  966. else
  967.     return GlobData.SQUAREPEN2 
  968.  
  969.  
  970. /* --------------------------------------------------------------- */
  971. /* procedure SelectChessSquare                       */
  972. /* --------------------------------------------------------------- */
  973. SelectChessSquare: procedure expose GlobData.
  974.     parse arg ChessSquareSelectX, ChessSquareSelectY, PenToSelectWith
  975.  
  976.    xleft   = trunc(GlobData.BoardWidth / 8) * ChessSquareSelectX
  977.    ytop    = (trunc(GlobData.BoardHeight / 8) * ChessSquareSelectY) + GlobData.ToolBarHeight
  978.    xright  = xleft + trunc(GlobData.BoardWidth / 8)
  979.    ybottom = ytop + trunc(GlobData.BoardHeight / 8)
  980.  
  981.    setfpen PenToSelectWith
  982.    square xleft ytop (xright-1) (ybottom-1)
  983.    return 1
  984.  
  985.  
  986. /* --------------------------------------------------------------- */
  987. /* procedure ParseMove                           */
  988. /* --------------------------------------------------------------- */
  989. ParseMove: procedure expose ChessBoard. piece. PiecePosX. PiecePosY. GlobData.
  990.     parse arg MoveString
  991.     
  992.    /* parses a move of the form MABCD0 , where 
  993.        M = checkcode, A = X1, B = Y1, C = X2, D = Y2.  No checking needs to
  994.        be done on the move, as that will all have been done before allowing
  995.        it to be sent */   
  996.     
  997.    leftpart = left(MoveString,3)
  998.    rightpart = right(MoveString,3)
  999.  
  1000.    checkcode = left(leftpart,1)
  1001.    promcode = right(rightpart,1)
  1002.  
  1003.    /* Special case:  If the message is of the form *****N, then N is
  1004.       the new value for BFlood */
  1005.    if (checkcode == '*') then do
  1006.        GlobData.BFlood = promcode
  1007.        return 2    /* means stick around for another move */
  1008.        end
  1009.        
  1010.    /* If its my turn, then he don't get to move! */
  1011.    if (GlobData.turn == GlobData.BActive) then return 0
  1012.  
  1013.    leftpart = right(leftpart,2)
  1014.    rightpart = left(rightpart,2)
  1015.    
  1016.    mx1 = left(leftpart,1)
  1017.    my1 = right(leftpart,1)
  1018.    mx2 = left(rightpart,1)
  1019.    my2 = right(rightpart,1)
  1020.    
  1021.    if (UpdatePiecePos(mx1, my1, mx2, my2) == 0) then do
  1022.        EasyRequeset Chess_Error "555:_UPP_failed" Okay
  1023.        return 0
  1024.        end    
  1025.  
  1026.    /* Was there a death here?  If so, remove dying piece */
  1027.    if (ChessBoard.mx2.my2 ~= Piece.BLANK) then do
  1028.        VictimPiece = GetPiecePos(mx2, my2)
  1029.     if (VictimPiece > 0) then do
  1030.         PiecePosX.1.VictimPiece = 9999
  1031.         PiecePosY.1.VictimPiece = 9999
  1032.         end
  1033.     else do
  1034.         VictimPiece = abs(VictimPiece)
  1035.         PiecePosX.2.VictimPiece = 9999
  1036.         PiecePosY.2.VictimPiece = 9999
  1037.         end
  1038.     end
  1039.     
  1040.    /* See if there was a pawn promotion on this move */
  1041.    if (promcode > 1) then do
  1042.        /* Get side code */
  1043.     if (ChessBoard.mx1.my1 > 0) then do
  1044.         tSide = 1
  1045.         end
  1046.     else do
  1047.         tSide = -1
  1048.         end
  1049.        if (promcode == 2) then ChessBoard.mx1.my1 = Piece.KNIGHT * tSide
  1050.        if (promcode == 3) then ChessBoard.mx1.my1 = Piece.QUEEN  * tSide
  1051.        if (promcode == 4) then ChessBoard.mx1.my1 = Piece.ROOK   * tSide
  1052.        if (promcode == 5) then ChessBoard.mx1.my1 = Piece.BISHOP * tSide
  1053.        say "promotion to "promcode
  1054.        end
  1055.        
  1056.    ChessBoard.mx2.my2 = ChessBoard.mx1.my1  /* Then put the piece in the new spot! */
  1057.    ChessBoard.mx1.my1 = Piece.BLANK
  1058.    
  1059.    return checkcode
  1060.    
  1061.  
  1062.  
  1063.  
  1064. /* --------------------------------------------------------------- */
  1065. /* procedure UpdateStatus                                             */
  1066. /* --------------------------------------------------------------- */
  1067. UpdateStatus: procedure expose GlobData. ACTIVE PASSIVE
  1068.     
  1069.     /* Say whose turn it is */
  1070.     if (GlobData.turn ~= GlobData.BActive) then LocalOrRemote = "It's Their turn" 
  1071.     if ((GlobData.BConnectMode == 0)|(GlobData.turn == GlobData.BActive)) then LocalOrRemote = "It's Your turn"
  1072.  
  1073.     if (GlobData.turn == ACTIVE) then do
  1074.         LocalOrRemote = '"' || LocalOrRemote || " (White)" || '"'
  1075.         end
  1076.         else do
  1077.         LocalOrRemote = '"' || LocalOrRemote || " (Black)" || '"'
  1078.         end
  1079.             
  1080.     SetWindowTitle LocalOrRemote
  1081.     return 1
  1082.     
  1083.  
  1084.  
  1085. /* --------------------------------------------------------------- */
  1086. /* procedure DrawPiece                                              */
  1087. /* --------------------------------------------------------------- */
  1088. DrawPiece: procedure expose GlobData. piece.
  1089.     parse arg X, Y, PieceCode, BFlood
  1090.     
  1091.     /* Decode PieceCode */
  1092.     PieceColor = GlobData.SIDE1PEN
  1093.     
  1094.     if (PieceCode < 0) then do
  1095.         PieceCode = abs(PieceCode)
  1096.         PieceColor = GlobData.SIDE2PEN
  1097.         end
  1098.     
  1099.     /* Get co-ords of our square */
  1100.     xleft   = trunc(GlobData.BoardWidth / 8) * X
  1101.     ytop    = (trunc(GlobData.BoardHeight / 8) * Y) + GlobData.ToolBarHeight
  1102.     xd      = trunc(GlobData.BoardWidth / 8) - 1
  1103.     yd      = trunc(GlobData.BoardHeight/ 8) - 1
  1104.     xright  = xleft + xd
  1105.     ybottom = ytop + yd
  1106.     xcenter = (xleft + trunc(xd/2)) 
  1107.     ycenter = (ytop + trunc(yd/2)) 
  1108.     
  1109.     /* First thing we need to do is erase the square */
  1110.     sqc = SquareColor(X, Y)
  1111.     setfpen sqc
  1112.     square xleft ytop xright ybottom fill
  1113.  
  1114.     /* If we're doing a filled mode draw, then outline in the other team's color */
  1115.     if (BFlood > 0) then do
  1116.             if (PieceColor == GlobData.SIDE1PEN) then do
  1117.                 OutlineColor = GlobData.SIDE2PEN
  1118.                 end 
  1119.             else do
  1120.                 OutlineColor = GlobData.SIDE1PEN
  1121.                 end
  1122.             end
  1123.             else do
  1124.                 OutlineColor = PieceColor
  1125.             end             
  1126.  
  1127.     /* Set color to appropriate side */
  1128.     setfpen OutlineColor
  1129.         
  1130.     if (PieceCode == piece.PAWN) then do
  1131.         penreset
  1132.         pen (xleft+trunc(xd*.56))  (ytop+trunc(yd*.47))
  1133.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.8))
  1134.         pen (xleft+trunc(xd*.65))  (ytop+trunc(yd*.9))
  1135.         pen (xleft+trunc(xd*.35))  (ytop+trunc(yd*.9))
  1136.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.8))
  1137.         pen (xleft+trunc(xd*.44))  (ytop+trunc(yd*.47))
  1138.         if BFlood > 0 then do
  1139.                 setfpen PieceColor
  1140.                 circle (xleft+trunc(xd*.5)) (ytop+trunc(yd*.38)) (trunc(xd*.16)) (trunc(yd*.16)) fill
  1141.                     setfpen OutlineColor
  1142.                     end
  1143.         circle (xleft+trunc(xd*.5)) (ytop+trunc(yd*.38)) (trunc(xd*.16)) (trunc(yd*.16))
  1144.  
  1145.             if BFlood > 0 then do
  1146.                 setfpen PieceColor
  1147.                     flood xcenter (ytop + trunc(yd * .8))
  1148.                     end
  1149.     end
  1150.     else if (PieceCode == piece.ROOK) then do
  1151.         penreset
  1152.         pen (xleft+trunc(xd*.3))   (ytop+trunc(yd*.2))
  1153.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.2))
  1154.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.3))
  1155.         pen (xleft+trunc(xd*.45))  (ytop+trunc(yd*.3))
  1156.         pen (xleft+trunc(xd*.45))  (ytop+trunc(yd*.2))
  1157.         pen (xleft+trunc(xd*.55))  (ytop+trunc(yd*.2))
  1158.         pen (xleft+trunc(xd*.55))  (ytop+trunc(yd*.3))
  1159.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.3))
  1160.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.2))
  1161.         pen (xleft+trunc(xd*.7))   (ytop+trunc(yd*.2))
  1162.         pen (xleft+trunc(xd*.7))   (ytop+trunc(yd*.3))
  1163.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.4))
  1164.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.7))
  1165.         pen (xleft+trunc(xd*.75))  (ytop+trunc(yd*.9))
  1166.         pen (xleft+trunc(xd*.25))  (ytop+trunc(yd*.9))
  1167.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.7))
  1168.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.4))
  1169.         pen (xleft+trunc(xd*.3))   (ytop+trunc(yd*.3))
  1170.         pen (xleft+trunc(xd*.3))   (ytop+trunc(yd*.2))
  1171.             setfpen PieceColor
  1172.         if BFlood > 0 then flood (xleft+trunc(xd*.5)) (ytop + trunc(yd*.5))
  1173.     end 
  1174.     else if (PieceCode == piece.KNIGHT) then do
  1175.         penreset 
  1176.         pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.2))
  1177.             pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.10))
  1178.             pen (xleft+trunc(xd*.33)) (ytop+trunc(yd*.19))
  1179.         pen (xleft+trunc(xd*.6))  (ytop+trunc(yd*.2))
  1180.         pen (xleft+trunc(xd*.7))  (ytop+trunc(yd*.4))
  1181.         pen (xleft+trunc(xd*.65)) (ytop+trunc(yd*.45))
  1182.         pen (xleft+trunc(xd*.5))  (ytop+trunc(yd*.4))
  1183.         pen (xleft+trunc(xd*.5))  (ytop+trunc(yd*.5))
  1184.         pen (xleft+trunc(xd*.6))  (ytop+trunc(yd*.6))
  1185.         pen (xleft+trunc(xd*.75)) (ytop+trunc(yd*.9))
  1186.         pen (xleft+trunc(xd*.25)) (ytop+trunc(yd*.9))
  1187.         pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.8))
  1188.         pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.7))
  1189.         pen (xleft+trunc(xd*.2))  (ytop+trunc(yd*.4))
  1190.         pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.2))
  1191.             setfpen PieceColor
  1192.         if BFlood > 0 then flood (xleft+trunc(xd*.5)) (ytop+trunc(yd*.75))
  1193.         setfpen OutlineColor
  1194.         circle (xleft+trunc(xd*.55)) (ytop+trunc(yd*.3)) trunc(xd/20) trunc(yd/20) fill
  1195.     end
  1196.     else if (PieceCode == piece.BISHOP) then do
  1197.         penreset
  1198.         pen (xleft+trunc(xd*.48))  (ytop+trunc(yd*.2))
  1199.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.3))
  1200.         pen (xleft+trunc(xd*.45))  (ytop+trunc(yd*.4))
  1201.         pen (xleft+trunc(xd*.35))  (ytop+trunc(yd*.7))
  1202.         pen (xleft+trunc(xd*.35))  (ytop+trunc(yd*.9))
  1203.         pen (xleft+trunc(xd*.65))  (ytop+trunc(yd*.9))
  1204.         pen (xleft+trunc(xd*.65))  (ytop+trunc(yd*.7))
  1205.         pen (xleft+trunc(xd*.55))  (ytop+trunc(yd*.4))
  1206.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.3))
  1207.         pen (xleft+trunc(xd*.52))  (ytop+trunc(yd*.2))
  1208.         if BFlood > 0 then do
  1209.             setfpen PieceColor
  1210.             circle (xleft+trunc(xd*.5)) (ytop+trunc(yd*.2)) trunc(xd*.08) trunc(yd*.08) fill
  1211.             setfpen OutlineColor
  1212.             end
  1213.         circle (xleft+trunc(xd*.5)) (ytop+trunc(yd*.2)) trunc(xd*.08) trunc(yd*.08)
  1214.             if BFlood > 0 then do
  1215.                 setfpen PieceColor
  1216.                flood (xleft+trunc(xd*.5)) (ytop+trunc(yd*.8))
  1217.                 end
  1218.     end
  1219.     else if (PieceCode == piece.QUEEN) then do
  1220.         penreset
  1221.         pen (xleft+trunc(xd*.4)) (ytop+trunc(yd*.1))
  1222.         pen (xleft+trunc(xd*.6)) (ytop+trunc(yd*.1))
  1223.         pen (xleft+trunc(xd*.7)) (ytop+trunc(yd*.15))
  1224.         pen (xleft+trunc(xd*.6)) (ytop+trunc(yd*.3))
  1225.         pen (xleft+trunc(xd*.6)) (ytop+trunc(yd*.7))
  1226.         pen (xleft+trunc(xd*.8)) (ytop+trunc(yd*.9))
  1227.         pen (xleft+trunc(xd*.2)) (ytop+trunc(yd*.9))
  1228.         pen (xleft+trunc(xd*.4)) (ytop+trunc(yd*.7))
  1229.         pen (xleft+trunc(xd*.4)) (ytop+trunc(yd*.3))
  1230.         pen (xleft+trunc(xd*.3)) (ytop+trunc(yd*.15))
  1231.         pen (xleft+trunc(xd*.4)) (ytop+trunc(yd*.1))
  1232.             setfpen PieceColor
  1233.         if BFlood > 0 then flood (xleft+trunc(xd*.5)) (ytop + trunc(yd*.75))
  1234.     end
  1235.     else if (PieceCode == piece.KING) then do
  1236.         penreset
  1237.         pen (xleft+trunc(xd*.47)) (ytop+trunc(yd*.1))
  1238.         pen (xleft+trunc(xd*.53)) (ytop+trunc(yd*.1))
  1239.         pen (xleft+trunc(xd*.53)) (ytop+trunc(yd*.2))
  1240.         pen (xleft+trunc(xd*.57)) (ytop+trunc(yd*.2))
  1241.         pen (xleft+trunc(xd*.57)) (ytop+trunc(yd*.3))
  1242.         pen (xleft+trunc(xd*.53)) (ytop+trunc(yd*.3))
  1243.         pen (xleft+trunc(xd*.53)) (ytop+trunc(yd*.4))
  1244.         pen (xleft+trunc(xd*.6))  (ytop+trunc(yd*.5))
  1245.         pen (xleft+trunc(xd*.55)) (ytop+trunc(yd*.6))
  1246.         pen (xleft+trunc(xd*.6))  (ytop+trunc(yd*.8))
  1247.         pen (xleft+trunc(xd*.7))  (ytop+trunc(yd*.9))
  1248.         pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.9))
  1249.         pen (xleft+trunc(xd*.4))  (ytop+trunc(yd*.8))
  1250.         pen (xleft+trunc(xd*.45)) (ytop+trunc(yd*.6))
  1251.         pen (xleft+trunc(xd*.4))  (ytop+trunc(yd*.5))
  1252.         pen (xleft+trunc(xd*.47)) (ytop+trunc(yd*.4))
  1253.         pen (xleft+trunc(xd*.47)) (ytop+trunc(yd*.3))
  1254.         pen (xleft+trunc(xd*.43)) (ytop+trunc(yd*.3))
  1255.         pen (xleft+trunc(xd*.43)) (ytop+trunc(yd*.2))
  1256.         pen (xleft+trunc(xd*.47)) (ytop+trunc(yd*.2))
  1257.         pen (xleft+trunc(xd*.47)) (ytop+trunc(yd*.1))
  1258.             setfpen PieceColor
  1259.         if BFlood > 0 then flood (xleft+trunc(xd*.5)) (ytop+trunc(yd*.7))
  1260.     end
  1261.     return 1