home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / games / tbridge.zip / PLAY.BR < prev    next >
Text File  |  1986-06-01  |  41KB  |  1,296 lines

  1. {  ╔══════════════════════════════════════════════════════╗
  2.    ║            PLAY.BR  Module of BRIDGE.PAS             ║                                                      ║
  3.    ║                                                      ║
  4.    ║                Last modified 10/29/85                ║
  5.    ║                                                      ║
  6.    ║   Plays the cards for the computer or gets plays     ║
  7.    ║   from the player and updates playing information.   ║
  8.    ╚══════════════════════════════════════════════════════╝
  9.  }
  10. function findHigh(Hand: HandType;   s: SuitType): CardNoType;
  11. { Find Highest Card }
  12. var
  13.   High: CardNoType;
  14. begin
  15.   High := 0;
  16.   while (Sdist[Hand,High].Suit <> s) or
  17.            Sdist[Hand,High].Played do
  18.     High :=  High+1;
  19.   findHigh :=  High;
  20. end; { findHigh }
  21.  
  22. function findLow(Hand: HandType;   s: SuitType): CardNoType;
  23. { Find Lowest Card }
  24. var
  25.   Low: CardNoType;
  26. begin
  27.   Low :=  12;
  28.   while (Sdist[Hand, Low].Suit <> s) or
  29.          Sdist[Hand, Low].Played do
  30.     Low :=  Low-1;
  31.   findLow := Low;
  32. end; { findLow }
  33.  
  34. type
  35.   ExpandValueType  =  -1..15;
  36.  
  37. function Highest(hand4: integer;   s: SuitType): ExpandValueType;
  38. { Return Value of Highest Card }
  39. var
  40.   Hand: HandType;
  41. begin
  42.   Hand := hand4 and 3;
  43.   if Sdata[Hand].l[s] = 0 then
  44.     Highest := -1
  45.   else
  46.     Highest := Sdist[Hand,findHigh(Hand,s)].Value;
  47. end; { Highest }
  48.  
  49. function Lowest(hand4: integer;   s: SuitType): ExpandValueType;
  50. { Return Value of Lowest Card }
  51. var
  52.   Hand : HandType;
  53. begin
  54.   Hand := hand4 and 3;
  55.   if Sdata[Hand].l[s] = 0 then
  56.     Lowest := Ace + 1
  57.   else
  58.     Lowest := Sdist[Hand,findLow(Hand,s)].Value;
  59. end; { Lowest }
  60.  
  61. function Highmax(hand4: integer;   s: SuitType;
  62.                  MaxVal: ExpandValueType): ExpandValueType;
  63. { Return Value of the Highest Card, which is
  64.   lower or equal to MaxVal }
  65. var
  66.   Hand: HandType;
  67.   No:   CardNoType;
  68. begin
  69.   Hand:=hand4 and 3;
  70.   Highmax:=-1;
  71.   for No:=0 to 12 do
  72.     if not Sdist[Hand,No].Played then
  73.       if (Sdist[Hand,No].Suit=s) then
  74.         if (Sdist[Hand,No].Value<=MaxVal) then
  75.         begin
  76.           Highmax:=Sdist[Hand,No].Value;
  77.           Exit;
  78.         end;
  79. end; { Highmax }
  80.  
  81. procedure PlayCard(Hand: HandType;   No: CardNoType);
  82. { Plays the Card and updates Game, Sdist, Sdata, Sim and TrickNo }
  83. begin
  84.   with Sdist[Hand,No],Sim do
  85.   begin
  86.     Played := true;
  87.     with Sdata[Hand] do
  88.       l[Suit] := l[Suit]-1;
  89.     Game[Round].Hand := Hand;
  90.     Game[Round].No := No;
  91.     if Round and 3 = 0 then
  92.     begin
  93.       LeadSuit := Suit;      { Lead }
  94.       BestCard := Sdist[Hand,No];
  95.       BestHand := Hand;
  96.     end
  97.     else
  98.       if (Suit =  BestCard.Suit) and (Value > BestCard.Value) or
  99.          (Suit <> BestCard.Suit) and (Suit = Contract.Trump) then
  100.       begin
  101.         BestCard := Sdist[Hand,No];  { Best Card }
  102.         BestHand := Hand;
  103.       end;
  104.       Round := Round+1;
  105.       if Round and 3 = 0 then
  106.       begin
  107.         if not odd(BestHand+Dummy) then
  108.           WonTricks := WonTricks+1;
  109.         LeadHand := BestHand;   TrickNo := TrickNo+1;
  110.       end;
  111.       PlayingHand := (LeadHand+Round) and 3;
  112.   end; { with }
  113. end; { PlayCard }
  114.  
  115. procedure ResetTrick;
  116. { Reestablishes the situation in Sim, Sdist, Sdata and TrickNo
  117.   one trick earlier (inverts 4 calls of PlayCard) }
  118. var
  119.   Cnt: 0..3;
  120. begin
  121.   with Sim do
  122.   begin
  123.     if not odd(LeadHand+Dummy) then
  124.       WonTricks := WonTricks-1;
  125.     for Cnt := 3 downto 0 do
  126.     begin
  127.       Round := Round-1;
  128.       with Game[Round],Sdist[Hand,No] do
  129.       begin
  130.         Played := false;
  131.         with Sdata[Hand] do l[Suit] := l[Suit]+1;
  132.       end;
  133.     end;
  134.     with Game[Round] do
  135.     begin
  136.       LeadHand := Hand;
  137.       PlayingHand := LeadHand;
  138.       LeadSuit := Sdist[Hand,No].Suit;
  139.     end;
  140.     TrickNo := TrickNo-1;
  141.   end;
  142. end; { ResetTrick }
  143.  
  144. procedure TestSuit(PlayingHand: HandType;   s: SuitType;
  145.                    var TopTricks: integer;
  146.                    var winning:  boolean);
  147. { TopTricks is the Number of TopTricks in the Suit for PlayingHand.
  148.   winning is true if All cards in the Suit are winners }
  149. var
  150.   MaxVal      : ExpandValueType;      { Highest Card }
  151.   HighHand    : HandType;             { Hand with Highest Card }
  152.   OpponentVal : ExpandValueType;      { Opponents Highest Card }
  153.   Highval     : array[HandType] of    { Table of Highest cards }
  154.                   ExpandValueType;
  155.   h           : HandType;
  156.   i           : CardNoType;
  157.   Len         : LengthType;
  158.  
  159. begin
  160.   CheckKBD;
  161.   TopTricks := 0;
  162.   winning := false;
  163.   MaxVal := -1;
  164.   for h := North to West do
  165.   begin
  166.     Highval[h] := Highest(h,s);   { Find Highest Card }
  167.     if MaxVal <  Highval[h] then
  168.     begin
  169.       MaxVal := Highval[h];
  170.       HighHand := h;
  171.     end;
  172.   end;
  173.  
  174.   if MaxVal >= 0 then
  175.     if not odd(HighHand+PlayingHand) then
  176.     begin
  177.       { Find opponents Highest Card }
  178.       OpponentVal := Max(Highval[(HighHand+1) and 3],
  179.                        Highval[(HighHand-1) and 3]);
  180.       for i := 0 to 12 do with Sdist[HighHand,i] do { Count TopTricks }
  181.         if not Played and (Suit = s) and (Value > OpponentVal) then
  182.           TopTricks := TopTricks+1;
  183.       for i := 0 to 12 do
  184.         with Sdist[(HighHand+2) and 3,i] do
  185.          if not Played and (Suit = s) and (Value > OpponentVal) then
  186.            TopTricks := TopTricks+1;
  187.       Len := Max(Sdata[HighHand].l[s], Sdata[(HighHand+2) and 3].l[s]);
  188.       TopTricks := Min(TopTricks,Len);
  189.       { The Suit is winning if PlayingHand can take All Tricks
  190.         from Top }
  191.       winning := TopTricks >= Max(Sdata[(HighHand+1) and 3].l[s],
  192.                               Sdata[(HighHand-1) and 3].l[s]);
  193.       if winning then TopTricks := Len;
  194.     end;
  195. end; { TestSuit }
  196.  
  197. function TopTrick(PlayingHand: HandType;   s: SuitType): integer;
  198. { Returns the Number of TopTricks for the side.
  199.   A negative Number means that the opponents has TopTricks.
  200.   The Number is calculated by using TestSuit }
  201. var
  202.   Top     : integer;
  203.   winning : boolean;
  204. begin
  205.   TestSuit(PlayingHand,s,Top,winning);
  206.   if Top = 0 then
  207.   begin
  208.     TestSuit((PlayingHand+1) and 3,s,Top,winning);
  209.     Top := -Top;
  210.   end;
  211.   TopTrick := Top;
  212. end; { TopTrick }
  213.  
  214. { Contains the different lead Suits used in the search }
  215. var
  216.   Count : array[0..13] of record
  217.                             { Sorted table of Suits }
  218.                             Suits : array[1..4] of SuitType;
  219.                             { Evaluation of Suits }
  220.                             Evaluation : array[SuitType] of integer;
  221.                             { Counter for Suit table }
  222.                             Cnt :        0..4;
  223.                           end;
  224.  
  225. type
  226.   ExpandCardNoType  =  -1..12;
  227.  
  228. function SelectLead: ExpandCardNoType;
  229. { Selects a lead in the position.
  230.   The function will return a new suggestion for a lead
  231.   every time it is called (-1 means No more suggestions).
  232.   The function uses the record Count[TrickNo]
  233.   (suggestion Number Cnt is in the Suit Suits[Cnt])
  234.   All calculations are performed in the Sim record }
  235.  
  236. function SelectSuit(Number: integer): SuitType;
  237. { Selects the Suit in which the lead should be Played.
  238.   Number is the suggestion Number.
  239.   The Suits and the evaluations are placed in Count[TrickNo].
  240.   All calculations are performed in the Sim records }
  241.  
  242. procedure SortSuits;
  243. { Sort Suits in Count }
  244. var
  245.   t1,t2 :  1..4;
  246.   Suit  :  SuitType;
  247. begin
  248.   with Count[TrickNo] do
  249.   for t1 := 1 to 3 do for t2 := t1+1 to 4 do
  250.     if Evaluation[Suits[t1]] < Evaluation[Suits[t2]] then
  251.     begin
  252.       Suit     := Suits[t2];
  253.       Suits[t2] := Suits[t1];
  254.       Suits[t1] := Suit;
  255.     end;
  256. end; { SortSuits }
  257.  
  258. function DeclarerLeadEvalu(s: SuitType): integer;
  259. { Evaluate the Suit as lead from declarer or Dummy }
  260. var
  261.   Evalu    : integer;
  262.   Short    : HandType;
  263.   ShortLen : LengthType;
  264.   Val      : integer;
  265. begin
  266.   CheckKBD;
  267.   with Sim,Sdata[PlayingHand],Contract do
  268.   begin
  269.     Evalu := 0;
  270.     if s = Trump then
  271.     begin
  272.       { Draw Trump until the opponents have No more }
  273.       if (Sdata[(PlayingHand+1) and 3].l[Trump] > 0) or
  274.          (Sdata[(PlayingHand-1) and 3].l[Trump] > 0) then
  275.          Evalu := 200;
  276.     end
  277.     else
  278.       if Trump <> NT then
  279.       begin
  280.         { Try to establish a Ruff trick }
  281.         Short := (PlayingHand + 2) and 3;
  282.         if Sdata[Short].l[s] > l[s] then
  283.           Short := PlayingHand;
  284.         ShortLen := Sdata[Short].l[s];
  285.         Val := Sdata[(Short+2) and 3].l[s]-2*ShortLen;
  286.         if (Val > 0) and (Sdata[Short].l[Trump] > 0) then
  287.         begin
  288.           with Sdata[(Short+1) and 3] do
  289.             if (l[s] <= ShortLen) and (l[Trump] > 0) then
  290.               Val := 0;
  291.           with Sdata[(Short-1) and 3] do
  292.             if (l[s] <= ShortLen) and (l[Trump] > 0) then
  293.               Val := 0;
  294.             if Val > 0 then
  295.               Evalu := 200+Val;
  296.         end;
  297.       end; { if }
  298.       DeclarerLeadEvalu := Evalu;
  299.   end;
  300. end; { DeclarerLeadEvalu }
  301.  
  302. function OpponentLeadEvalu(s: SuitType): integer;
  303. { Evaluate the Suit as lead from Opponent to declarer }
  304. var
  305.   Evalu     : integer;
  306.   RuffRisk  : boolean;
  307.   TopTricks : integer;
  308.   winning   : boolean;
  309. begin
  310.   CheckKBD;
  311.   with Sim,Sdata[PlayingHand],Contract do
  312.   begin
  313.     Evalu := 0;
  314.     RuffRisk := false;
  315.     if (Trump <> NT) and (s <> Trump) then
  316.     begin
  317.       { Check if declarer or Dummy can Ruff Suit }
  318.       with Sdata[(PlayingHand+1) and 3] do
  319.         if (l[s] = 0) and (l[Trump] > 0) then
  320.           RuffRisk := true;
  321.       with Sdata[(PlayingHand-1) and 3] do
  322.         if (l[s] = 0) and (l[Trump] > 0) then
  323.           RuffRisk := true;
  324.     end;
  325.     if not RuffRisk then
  326.     begin
  327.       TestSuit(PlayingHand,s,TopTricks,winning);
  328.       if TopTricks > 0 then
  329.       begin
  330.         Evalu := 200+TopTricks;  { Take TopTricks }
  331.         if winning then
  332.           Evalu := Evalu+4;
  333.       end
  334.       else
  335.         if Trump <> NT then
  336.         begin
  337.           { Try to establish a Ruff trick }
  338.           with Sdata[PlayingHand] do
  339.             if (l[s] <= 1) and (l[Trump] > 0) then
  340.               Evalu := 200;
  341.           with Sdata[(PlayingHand+2) and 3] do
  342.             if (l[s] <= 1) and (l[Trump] > 0) then
  343.               Evalu := 200;
  344.         end;
  345.     end;
  346.     OpponentLeadEvalu := Evalu;
  347.   end; { with }
  348.   CheckKBD;
  349. end; { OpponentLeadEvalu }
  350.  
  351. function SuitEvalu(s: SuitType): integer;
  352. { Evaluate the strength of the Suit }
  353. var
  354.   Evalu     : integer;
  355.   TopTricks : integer;
  356.   winning   : boolean;
  357.   m,n       : integer;
  358. begin
  359.   CheckKBD;
  360.   with Sim,Sdata[PlayingHand],Contract do
  361.   begin
  362.     if s = Trump then
  363.       Evalu := 100           { Play Trump }
  364.     else
  365.     begin
  366.       m := Sdata[North].l[s]+Sdata[South].l[s];   { Play best Suit }
  367.       n := Sdata[East ].l[s]+Sdata[West ].l[s];
  368.       if not odd(PlayingHand) then
  369.         Evalu := 96+m-2*n
  370.       else
  371.         Evalu := 96+n-2*m;
  372.       if not odd(PlayingHand+Dummy) then
  373.       begin
  374.         Evalu := Evalu+24;
  375.         TestSuit(PlayingHand,s,TopTricks,winning);
  376.         if TopTricks > 0 then
  377.         begin
  378.           Evalu := 128+TopTricks;      { Take TopTricks }
  379.           if winning then
  380.             Evalu := Evalu+4;
  381.         end;
  382.       end;
  383.     end;
  384.     SuitEvalu := Evalu;
  385.   end;
  386. end; { SuitEvalu }
  387.  
  388. var
  389.   Lastlead : TrumpType;    { The Suit which was  last lead by the side }
  390.   LastNo   : integer;      { The trick Number of last lead by the side }
  391.   s        : SuitType;
  392.   Evalu    : integer;
  393.   i        : integer;
  394. label 10;
  395. begin
  396.   CheckKBD;
  397.   with Sim,Sdata[PlayingHand],Count[TrickNo] do
  398.   begin
  399.     { When the procedure is called for the first suggestion,
  400.       All Suits are evaluated, sorted and stored in the record
  401.       Count[TrickNo]. Suggestion Number Number is then simply
  402.       the Suit Suits[Number] }
  403.     if Number = 1 then
  404.     begin
  405.       { Find Suit of last lead by this side }
  406.       Lastlead := NT;
  407.       for i := FirstNo to TrickNo-1 do with Game[i*4] do
  408.         if not odd(PlayingHand+Hand) then
  409.         begin
  410.           Lastlead := Sdist[Hand,No].Suit;
  411.           LastNo  := i;
  412.         end;
  413.       for s := Club to Spade do
  414.       begin
  415.         if l[s] = 0 then                      { Evaluate each Suit }
  416.           Evalu := -1000
  417.         else
  418.         begin
  419.           if not odd(PlayingHand+Dummy) then  { Most important rules }
  420.             Evalu := DeclarerLeadEvalu(s)
  421.           else
  422.             Evalu := OpponentLeadEvalu(s);
  423.           if s = Lastlead then  { Continue playing same Suit as in last lead }
  424.             Evalu := Max(Evalu+40,Count[LastNo].Evaluation[Lastlead]);
  425.           if Evalu = 0 then     { Second most important rules }
  426.             Evalu := SuitEvalu(s);
  427.         end;
  428.         Evaluation[s] := Evalu;
  429.         Suits[Ord(s)+1] := s;
  430.       end;
  431.       SortSuits;                  { Sort Suits }
  432.     end;
  433.     SelectSuit := Suits[Number];  { Return suggested Suit }
  434.   end { with };
  435.   CheckKBD;
  436. end; { SelectSuit }
  437.  
  438. function SuitTreatment(CardSuit: SuitType): CardNoType;
  439. { Decides which Card in CardSuit should be Played }
  440. var
  441.   Low        : boolean;  { program plays Lowest Card in CardSuit }
  442.   Highval,                          { Players  Highest Card }
  443.   PartnerVal : ExpandValueType;     { Partners Highest Card }
  444. begin
  445.   CheckKBD;
  446.   with Sim,Sdata[PlayingHand] do
  447.   begin
  448.     Low := true;                    { Play Low normally }
  449.     if l[CardSuit] > 1 then
  450.     begin
  451.       { Play High if both opponents have singletons }
  452.       if (Sdata[(PlayingHand+1) and 3].l[CardSuit] <= 1) and
  453.          (Sdata[(PlayingHand-1) and 3].l[CardSuit] <= 1) then
  454.         Low := false
  455.       else
  456.       begin
  457.         Highval := Highest(PlayingHand  ,CardSuit);
  458.         PartnerVal := Highest(PlayingHand+2,CardSuit);
  459.         if PartnerVal < Highval then
  460.         begin
  461.           { Play High if Partner cannot take trick }
  462.           if (Highmax(PlayingHand+1,CardSuit,Highval) > PartnerVal) or
  463.              (Highmax(PlayingHand-1,CardSuit,Highval) > PartnerVal) then
  464.             Low := false;
  465.         end
  466.         else
  467.           { Play High to make a finesse }
  468.           if (Sdata[(PlayingHand+2) and 3].l[CardSuit] >= 2) and
  469.              (Sdata[(PlayingHand+1) and 3].l[CardSuit] >= 3) then
  470.             if Highest(PlayingHand+1,CardSuit) = PartnerVal-1 then
  471.               if Highest(PlayingHand-1,CardSuit) > Highval then
  472.                 Low := false;
  473.         if not Low then
  474.         begin
  475.           { Play Low if the Opponent has Highest Card singleton }
  476.           if Sdata[(PlayingHand+1) and 3].l[CardSuit] = 1 then
  477.             if Highest(PlayingHand+1,CardSuit) > Highval then
  478.               Low := true;
  479.           if Sdata[(PlayingHand-1) and 3].l[CardSuit] = 1 then
  480.             if Highest(PlayingHand-1,CardSuit) > Highval then
  481.               Low := true;
  482.         end;  { if }
  483.       end; { else }
  484.     end; { if }
  485.     if Low then
  486.       SuitTreatment := findLow(PlayingHand,CardSuit)
  487.     else
  488.       SuitTreatment := findHigh(PlayingHand,CardSuit);
  489.   end { with };
  490.   CheckKBD;
  491. end; { SuitTreatment }
  492.  
  493. var
  494.   CardSuit: SuitType;
  495. begin { SelectLead }
  496.   with Count[TrickNo] do
  497.   { Decide if any more suggestions should be made, and
  498.     calculate eventually next suggestion }
  499.   if Cnt >= 2 then
  500.     SelectLead := -1
  501.   else
  502.   begin
  503.     Cnt := Cnt+1;
  504.     CardSuit := SelectSuit(Cnt);
  505.     if (Cnt > 1) and (Evaluation[Suits[1]]-
  506.         Evaluation[CardSuit] >= BranchValue) then
  507.       SelectLead := -1
  508.     else
  509.       SelectLead := SuitTreatment(CardSuit);
  510.   end;
  511. end; { SelectLead }
  512.  
  513. function DiscardCard: CardNoType;
  514. { Find the Card with Lowest Value }
  515. var
  516.   CardSuit   : SuitType;    { Chosen Suit }
  517.   Minval,                   { Minimal Card Value }
  518.   Evalu      : integer;     { Card Value }
  519.   Hold       : boolean;     { Hold opponents Suit }
  520.   Highval,
  521.   LowVal,
  522.   OpponentVal,
  523.   Val        : ExpandValueType;
  524.   s          : SuitType;
  525.   Hand       : HandType;
  526.   top0,top1  : integer;
  527.   TopTricks  : integer;
  528.   winning    : boolean;
  529.   OwnVal,
  530.   OppVal,
  531.   v          : integer;
  532.  
  533. function Trickval(Top: integer): integer;
  534. { Calculate Value of TopTricks.
  535.   OwnVal is Value of a Player trick.
  536.   OppVal is Value of an Opponent trick }
  537. begin
  538.    if Top >= 0 then
  539.      Trickval := Top*OwnVal
  540.    else
  541.      Trickval := Top*OppVal;
  542. end; { Trickval }
  543.  
  544. begin
  545.   CheckKBD;
  546.   with Sim,Sdata[PlayingHand],Contract do
  547.   begin
  548.     Minval := MaxInt;
  549.     for s := Club to Spade do
  550.       if l[s] > 0 then
  551.       begin
  552.         if s = Trump then   { Evaluate the importance of each of the Suits }
  553.           Evalu := 500      { do not discard Trump }
  554.         else
  555.         begin
  556.           LowVal := Lowest(PlayingHand,s);  { do not discard High Card }
  557.           if LowVal > 10 then
  558.             Evalu := 8+LowVal
  559.           else
  560.           begin
  561.             { Penalty for leaving High Card unprotected.
  562.               Otherwise Hold the longest Suit }
  563.             Highval := Highest(PlayingHand,s);
  564.             if (Highval > 10) and (Highval <> Ace) and
  565.                (l[s] <= Ace+1-Highval) then
  566.               Evalu := Highval
  567.             else
  568.               Evalu := l[s];
  569.             if odd(PlayingHand+Dummy) then { if Player have No more trumps,
  570.                                              then discard longest Suit }
  571.             if Trump <> NT then
  572.               if l[Trump] = 0 then
  573.                 Evalu := -l[s];
  574.           end;
  575.           Hold := false;  { Hold opponents Suit unless the Player has
  576.                             trumps or Partner leads next trick }
  577.           if odd(PlayingHand+Dummy) or (Trump = NT) then
  578.           begin
  579.             Hold := odd(PlayingHand+BestHand);
  580.             with BestCard do
  581.               if Suit = LeadSuit then
  582.                 Val := Value
  583.               else
  584.                 Val := Ace+1;
  585.             Hand := (PlayingHand+1) and 3;
  586.             while Hand <> LeadHand do
  587.             begin
  588.               OpponentVal := Highest(Hand,LeadSuit);
  589.               if (OpponentVal < 0) and (Trump <> NT) then
  590.                 if Sdata[Hand].l[Trump] > 0 then
  591.                   OpponentVal := Ace+1;
  592.               if Val <= OpponentVal then
  593.               begin
  594.                 Val := OpponentVal;
  595.                 Hold := odd(PlayingHand+Hand);
  596.               end;
  597.               Hand := (Hand+1) and 3;
  598.             end;
  599.           end;
  600.           top1 := TopTrick(PlayingHand,s);
  601.           { TOP1 is the present Number of TopTricks for side.
  602.             TOP0 is the Number of TopTricks if PlayingHand
  603.             discards a Card in the Suit }
  604.           with Sdist[PlayingHand,findHigh(PlayingHand,s)],
  605.                Sdata[PlayingHand] do
  606.           begin
  607.             Played := true;
  608.             l[s] := l[s]-1;
  609.             top0 := TopTrick(PlayingHand,s);
  610.             Played := false;   l[s] := l[s]+1;
  611.           end;
  612.           OwnVal := 40; { Evaluate the importance of the lost TopTricks }
  613.           OppVal := 20;
  614.           if (Trump <> NT) and
  615.              ((top1 > 0)  =  odd(PlayingHand+Dummy)) then
  616.             if (abs(top1) > Sdata[(Dummy+1) and 3].l[s]) or
  617.                (abs(top1) > Sdata[(Dummy-1) and 3].l[s]) then
  618.               OppVal := 8;
  619.           if Hold then
  620.           begin
  621.             v := OppVal;
  622.             OppVal := OwnVal;
  623.             OwnVal := v;
  624.           end;
  625.           Evalu := Evalu+(Trickval(top1)-Trickval(top0));
  626.         end;
  627.         if Evalu < Minval then
  628.         begin
  629.           Minval := Evalu;
  630.           CardSuit := s;
  631.       end;
  632.     end { for Suit };
  633.     DiscardCard := findLow(PlayingHand,CardSuit);
  634.     { Discard Lowest Card in the chosen Suit }
  635.   end { with };
  636.   CheckKBD;
  637. end { DiscardCard };
  638.  
  639. function SelectCard: CardNoType;
  640. { Selects a Card in the position.
  641.   The procedure does not handle leads in the search
  642.   (this is Done by SelectLead).
  643.   The procedure can only be called once, and gives thus
  644.   only one suggestion (in contrary to SelectLead).
  645.   All calculations are performed in the Sim records }
  646.  
  647. function FollowSuit: CardNoType;
  648. { Follow Suit and play a Card in the lead Suit }
  649. var   
  650.   Low         : boolean;    { program plays Lowest Card in CardSuit }
  651.   findLower   : boolean;    { program plays Lowest Card,
  652.                               which is higher than OpponentVal }
  653.   OpponentVal,              { Opponents Highest Card }
  654.   Highval,              { Players Highest Card }
  655.   PartnerVal  : ExpandValueType;   { Partners Highest Card }
  656.   TopTricks   : integer;
  657.   winning     : boolean;
  658.   No          : CardNoType;
  659. begin
  660.   CheckKBD;
  661.   with Sim,Sdata[PlayingHand] do
  662.   begin
  663.     Low := true;
  664.     if (BestCard.Suit = LeadSuit) and (l[LeadSuit] > 1) then
  665.     begin
  666.       Highval := Highest(PlayingHand,LeadSuit);
  667.       if BestCard.Value <= Highval then
  668.         { It is possible to play the Highest Card }
  669.         case Round and 3+1 of
  670.           2 : begin   { 2nd Hand }
  671.                 { Play Low  if Partner can take trick, else
  672.                   play High if it will get the trick, else
  673.                   play High if it will press the Opponent, else
  674.                   play Low  in 2nd Hand }
  675.                 OpponentVal := Max(Highest(PlayingHand+1,LeadSuit),
  676.                                    BestCard.Value);
  677.                 PartnerVal := Highest(PlayingHand+2,LeadSuit);
  678.                 Low := (PartnerVal > OpponentVal)
  679.                        or (OpponentVal > Highval)
  680.                          and ((PartnerVal > BestCard.Value) or
  681.                              (Sdata[(PlayingHand+1) and 3].l[LeadSuit] = 1));
  682.                 findLower := (Round <= Rel.Round+2)
  683.                              and (Highval > OpponentVal);
  684.               end;
  685.           3: begin   { 3rd Hand }
  686.                { Play Low  if Partner is sure to win trick }
  687.                OpponentVal := Highest(PlayingHand+1,LeadSuit);
  688.                Low := not odd(BestHand+PlayingHand) and
  689.                           (OpponentVal < BestCard.Value);
  690.                if not Low then
  691.                begin
  692.                  findLower := true;    { Play High in 3rd Hand }
  693.                  OpponentVal := Highmax(PlayingHand+1,LeadSuit,Highval);
  694.                  if OpponentVal < BestCard.Value then
  695.                    if odd(BestHand+PlayingHand) then
  696.                      OpponentVal := BestCard.Value
  697.                    else
  698.                      Low := true;
  699.                end;
  700.              end;
  701.           4: begin   { 4th Hand }
  702.                      { Get trick unless Partner has it }
  703.                if odd(BestHand+PlayingHand) then
  704.                begin
  705.                  Low := false;
  706.                  findLower := true;
  707.                  OpponentVal := BestCard.Value;
  708.                end;
  709.              end;
  710.         end { case };
  711.     end; { if }
  712.     if Low then
  713.       FollowSuit := findLow(PlayingHand, LeadSuit)
  714.     else
  715.     begin
  716.       FollowSuit := findHigh(PlayingHand, LeadSuit);
  717.       if findLower then
  718.         for No := 0 to 12 do
  719.           with Sdist[PlayingHand,No] do
  720.             if not Played and
  721.               (Suit = LeadSuit) and (Value > OpponentVal) then
  722.               FollowSuit := No;
  723.     end;
  724.   end { with };
  725.   CheckKBD;
  726. end { FollowSuit };
  727.  
  728.  
  729. function SelectRuff: ExpandCardNoType;
  730. { Check whether and with which trumph
  731.   the trick should be ruffed }
  732. var
  733.   Ruff        : boolean;  { Ruff the trick }
  734.   Low         : boolean;  { program plays Lowest Card in CardSuit }
  735.   findLower   : boolean;  { program plays Lowest Card,
  736.                             which is higher than OpponentVal }
  737.   OpponentVal : ExpandValueType;    { Opponents Highest Trump }
  738.   No          : CardNoType;
  739. begin
  740.   with Sim,Sdata[PlayingHand],Contract do
  741.   begin
  742.     if Trump = NT then
  743.       Ruff := false
  744.     else
  745.       Ruff := (Sdata[PlayingHand].l[Trump] > 0)
  746.               and ((BestCard.Suit <> Trump) or
  747.                    (Highest(PlayingHand,Trump) > BestCard.Value));
  748.       if Ruff then
  749.       begin
  750.         { Ruff if it gets the trick }
  751.         case Round and 3+1 of
  752.           2 : Ruff := Highest(PlayingHand+2,LeadSuit)  <=
  753.                      Max(Highest(PlayingHand+1,LeadSuit),BestCard.Value);
  754.           3 : Ruff := odd(PlayingHand+BestHand) or
  755.                       (BestCard.Suit = LeadSuit) and
  756.                       (Highest(PlayingHand+1,LeadSuit) > BestCard.Value);
  757.           4 : Ruff := odd(PlayingHand+BestHand);
  758.         end { case };
  759.         if Ruff then
  760.         begin
  761.           Low := true;
  762.           with BestCard do
  763.             if Suit = Trump then
  764.               if Highest(PlayingHand,Trump) > Value then
  765.               begin
  766.                 Low := false;
  767.                 findLower := true;
  768.                 OpponentVal := Value;
  769.               end
  770.               else
  771.                 Ruff := false;
  772.         end;
  773.       end;
  774.       if not Ruff then
  775.         SelectRuff := -1
  776.       else
  777.         if Low then
  778.           SelectRuff := findLow(PlayingHand,Trump)
  779.         else
  780.         begin
  781.           SelectRuff := findHigh(PlayingHand,Trump);
  782.           if findLower then
  783.             for No := 0 to 12 do
  784.               with Sdist[PlayingHand,No] do
  785.                 if not Played and (Suit = Trump)
  786.                    and (Value > OpponentVal) then
  787.                   SelectRuff := No;
  788.         end;
  789.   end { with };
  790. end { SelecTrump };
  791.  
  792.  
  793. var
  794.   CardNo: ExpandCardNoType;
  795. begin { SelectCard }
  796.   with Sim,Sdata[PlayingHand] do
  797.     if Round and 3 = 0 then
  798.     begin
  799.          { Find lead by calling SelectLead
  800.            (must not be used in the search) }
  801.       Count[TrickNo].Cnt := 0;   FirstNo := TrickNo;
  802.       SelectCard := SelectLead;
  803.     end
  804.     else
  805.     begin
  806.       if l[LeadSuit] > 0 then
  807.       { Follow Suit and play a Card in the lead Suit }
  808.         SelectCard := FollowSuit
  809.       else
  810.       begin
  811.         CardNo := SelectRuff;  { Void Suit, Ruff the trick or Discard a Card }
  812.         if CardNo >= 0 then
  813.           SelectCard := CardNo
  814.         else
  815.           SelectCard := DiscardCard;
  816.       end;
  817.     end;
  818. end { SelectCard };
  819.  
  820. procedure Analyse(var Result: integer);
  821. { Performs the analysis of the given position (in the Sim records).
  822.   When the analysis is finished the Number of won Tricks
  823.   for the declarer is placed in Result }
  824. var
  825.   MaxVal : array[-1..13] of integer;   { Alfa-Beta values }
  826.   CardNo : ExpandCardNoType;           { Counters }
  827.   Back   : -1..13;
  828.   i      : IndexType;
  829.   h      : 1..3;
  830.  
  831. label Call,Loop;
  832. begin
  833.   CheckKBD;
  834.   with Sim do
  835.   begin
  836.     if Round and 3 <> 0 then        { Finish this trick }
  837.       for h := Round and 3 to 3 do
  838.         PlayCard(PlayingHand,SelectCard);
  839.     FirstNo := TrickNo;
  840.     Call:                           { Initialize MaxVal[TrickNo] }
  841.     if odd(PlayingHand+Dummy) then
  842.       MaxVal[TrickNo] := -WonTricks+TrickNo-14
  843.     else
  844.       MaxVal[TrickNo] :=  WonTricks+1;
  845.     if TrickNo = FirstNo then
  846.       MaxVal[FirstNo-1] := TrickNo-13-MaxVal[FirstNo]
  847.     else
  848.     begin
  849.       Back := TrickNo;
  850.       repeat
  851.         Back := Back-1
  852.       until (MaxVal[TrickNo] > 0)  =  (MaxVal[Back] > 0);
  853.       if MaxVal[TrickNo] <  MaxVal[Back] then
  854.         MaxVal[TrickNo] := MaxVal[Back];
  855.     end;
  856.     Count[TrickNo].Cnt := 0;        { Initiate SelectLead }
  857.   Loop: { Test cut-off }
  858.     Back := TrickNo;
  859.     repeat
  860.       Back := Back-1
  861.     until (MaxVal[TrickNo] > 0) <> (MaxVal[Back] > 0);
  862.     if MaxVal[TrickNo]+MaxVal[Back] >= 0 then
  863.     begin
  864.       Back := Back+1;         { Take Back All Tricks lead by the Player }
  865.       MaxVal[Back] := MaxVal[TrickNo];
  866.       while TrickNo > Back do ResetTrick;
  867.     end
  868.     else
  869.     begin
  870.       CardNo := SelectLead;   { Find next lead }
  871.       if CardNo >= 0 then
  872.       begin
  873.         PlayCard(PlayingHand,CardNo);  { Play the whole trick }
  874.         for h := 1 to 3 do
  875.           PlayCard(PlayingHand,SelectCard);
  876.         goto Call;
  877.       end;
  878.     end;
  879.  
  880.     if TrickNo > FirstNo then
  881.     begin
  882.       ResetTrick;             { Backup MaxVal-Value }
  883.       if (MaxVal[TrickNo] > 0)  =  (MaxVal[TrickNo+1] > 0) then
  884.         MaxVal[TrickNo] :=  MaxVal[TrickNo+1]
  885.       else
  886.         MaxVal[TrickNo] := -MaxVal[TrickNo+1];
  887.       goto Loop;
  888.     end;
  889.   end; { with }
  890.   CheckKBD;
  891.   Result := abs(MaxVal[TrickNo])-1; { Save Result and reestablish situation }
  892.   for i := Sim.Round-1 downto Rel.Round do
  893.     with Game[i],Sdist[Hand,No],Sdata[Hand] do
  894.     begin
  895.       Played := false;
  896.       l[Suit] := l[Suit]+1;
  897.     end;
  898.   Sim := Rel;
  899.   TrickNo := Rel.Round div 4;
  900.   CheckKBD;
  901. end; { Analyse }
  902.  
  903. procedure FindCard(var BestChoice: CardNoType;
  904.                    var Redeal, Auto, Hint : boolean);
  905. { Finds a Card to play. The Rel records contains the actual
  906.   situation.
  907.   TrickNo, Game, Contract, BLIND and Info are alse updated.
  908.   The Number of the chosen Card is returned in BestChoice.
  909.   if the Hand is controlled by the human,
  910.   the Card is Read from input }
  911. var
  912.   Comp    : boolean;               { Computer controls Hand }
  913.   All     : boolean;               { All cards can be Played }
  914.  
  915.   Cardstat: array[CardNoType] of   { Statistics about cards }
  916.                  record
  917.                    Try:  boolean;  { Card should be tried }
  918.                    Stat: integer;  { Statistical Evaluation }
  919.                  end;
  920.  
  921. function CountTry: LengthType;
  922. { Counts the Number of cards which should be tried }
  923. var
  924.   Count : LengthType;
  925.   No    : CardNoType;
  926. begin
  927.   Redeal := False;
  928.   Count := 0;
  929.   for No := 0 to 12 do
  930.     if Cardstat[No].Try then
  931.       Count := Count+1;
  932.   CountTry := Count;
  933. end; { CountTry }
  934.  
  935. procedure InitSearch;
  936. { Copies Rel in Sim, and finds the cards, which shall be analysed }
  937.  
  938. procedure SelectTry;
  939. { Selects the cards which should be analysed }
  940. var
  941.   LastCard : array[SuitType] of ValueType;
  942.   { Strength of last chosen Card in the Suit }
  943.   h        : HandType;
  944.   i        : CardNoType;
  945. begin
  946.   with Rel,Rdata[PlayingHand],Contract do
  947.   begin
  948.     for i := 12 downto 0 do
  949.       with Rdist[PlayingHand,i],Cardstat[i] do
  950.         if Try then
  951.         begin
  952.           { Always Try Lowest Card in a Suit }
  953.           if Value <> Lowest(PlayingHand,Suit) then
  954.           begin
  955.             { Never Try two different equally strong cards }
  956.             Try := false;
  957.             if Value > LastCard[Suit]+1 then
  958.               for h := North to West do
  959.                 if Highmax(h,Suit,Value-1) > LastCard[Suit] then
  960.                   Try := true;
  961.             if not Try then if PlayingHand <> LeadHand then
  962.               if (Suit = BestCard.Suit) and
  963.                  (LastCard[Suit] < BestCard.Value) then
  964.                 Try := true;
  965.             if not Try then
  966.               LastCard[Suit] := Value;
  967.             if Try then
  968.             begin
  969.               if PlayingHand = LeadHand then
  970.                 Try := Value > 8   { Try to lead All High cards }
  971.               else
  972.                 if (Suit = BestCard.Suit) or (Suit = Trump) then
  973.                 begin
  974.                   { Try cards which gets the trick }
  975.                   if Suit = BestCard.Suit then
  976.                     Try := Value > BestCard.Value
  977.                   else
  978.                     Try := Suit = Trump;
  979.                     { in 4th Hand Try only Lowest Card, which gets the trick }
  980.                   if Try then
  981.                     if (Value <= 8) or (PlayingHand = (LeadHand+3) and 3) then
  982.                       if not ((Suit = BestCard.Suit) and
  983.                               (LastCard[Suit] < BestCard.Value)) then
  984.                         Try := false;
  985.                 end
  986.                 else
  987.                   Try := false;
  988.             end; { if }
  989.           end;
  990.           if Try then
  991.             LastCard[Suit] := Value;
  992.         end;
  993.   end; { with }
  994. end; { SelectTry }
  995.  
  996. var
  997.   i :    CardNoType;
  998. begin { InitSearch }
  999.   Sim := Rel;
  1000.   with Rel,Rdata[PlayingHand] do
  1001.   begin
  1002.     if PlayingHand <> Dummy then    { Check if Computer controls the Hand }
  1003.     begin
  1004.       Comp := Computer[PlayingHand];
  1005.       if Comp and not Auto then
  1006.         PlayMessage(PlayingHand, Hint);
  1007.     end
  1008.     else
  1009.     begin
  1010.       Comp := Computer[(Dummy+2) and 3];
  1011.       if Comp and not Auto then
  1012.         PlayMessage(Dummy, Hint);
  1013.     end;
  1014.     CheckKBD;
  1015.     if PlayingHand = LeadHand then  { Check if All cards can be Played }
  1016.       All := true
  1017.     else
  1018.       All := l[LeadSuit] = 0;
  1019.     for i := 0 to 12 do             { Check which cards can be Played }
  1020.       with Rdist[PlayingHand,i],Cardstat[i] do
  1021.       begin
  1022.         Stat := 0;
  1023.         Try := not Played and (All or (Suit = LeadSuit));
  1024.       end;
  1025.     if Comp then
  1026.       if CountTry > 1 then
  1027.         SelectTry;                  { Select the cards to be analysed further }
  1028.     CheckKBD;
  1029.   end; { with }
  1030. end; { InitSearch }
  1031.  
  1032. var
  1033.   DealNo    : integer;            { Deal counter }
  1034.   Result    : integer;            { Result of analysis }
  1035.   StatEvalu : integer;            { Evaluation of Result }
  1036.   MaxStat   : integer;            { Maximal statistical Evaluation }
  1037.   TryNo     : CardNoType;
  1038.   Choice    : ExpandCardNoType;
  1039.   MinValue  : ValueType;
  1040.   Suit      : SuitType;
  1041.  
  1042. label 10,20;
  1043. begin { findCard }
  1044.   CheckKBD;
  1045.   InitSearch;
  1046.   with Sim do
  1047.     if CountTry = 1 then
  1048.     begin
  1049.       for TryNo := 0 to 12 do   { Find the only Card }
  1050.         if Cardstat[TryNo].Try then
  1051.           BestChoice := TryNo;
  1052.     end
  1053.     else
  1054.       if Comp then
  1055.       begin
  1056.         GotoCardPos(PlayingHand);  { Find Card for Computer }
  1057.         DealNo := 0;               { Heuristic Evaluation   }
  1058.         if Heurisfac <> 0 then
  1059.           while ((DealNo < MaxDeals) and not Cheat
  1060.                 or (DealNo < 1)) and (CountTry > 1) do
  1061.         begin
  1062.           DealNo := DealNo + 1;
  1063.           Sdist := Rdist;
  1064.           Sdata := Rdata;
  1065.           if not Cheat then
  1066.           begin
  1067.             DealCards;
  1068.             ChangeCards;
  1069.           end;
  1070.           SortCards;
  1071.           with Sdist[PlayingHand,SelectCard] do
  1072.             for TryNo := 0 to 12 do
  1073.               with Cardstat[TryNo] do
  1074.                 if Try and (Sdist[PlayingHand,TryNo].Suit = Suit) and
  1075.                   (Sdist[PlayingHand,TryNo].Value <= Value) then
  1076.                 begin
  1077.                   Stat := Stat + Heurisfac;
  1078.                   goto 10;
  1079.                 end;
  1080.         10:
  1081.           CheckKBD;
  1082.       end; { if }
  1083.       DealNo := 0;   { Search }
  1084.       if SearchFac <> 0 then
  1085.         while ((DealNo < MaxDeals) and not Cheat or (DealNo < 1))
  1086.               and (CountTry > 1) do
  1087.         begin
  1088.           DealNo := DealNo+1;
  1089.           Sdist := Rdist;
  1090.           Sdata := Rdata;
  1091.           if not Cheat then
  1092.           begin
  1093.             DealCards;
  1094.             ChangeCards;
  1095.           end;
  1096.           SortCards;
  1097.           for TryNo := 0 to 12 do
  1098.             if Cardstat[TryNo].Try then
  1099.             begin
  1100.               PlayCard(PlayingHand, TryNo);  { Analyse Card }
  1101.               Analyse(Result);
  1102.               StatEvalu := Result-(6+Contract.Level); { Calculate Evaluation }
  1103.               if StatEvalu < 0 then
  1104.                 StatEvalu := StatEvalu-2;
  1105.               if odd(PlayingHand + Dummy) then
  1106.                 StatEvalu := -StatEvalu;
  1107.               with Cardstat[TryNo] do
  1108.                 Stat := Stat + StatEvalu * SearchFac;
  1109.             end; { if }
  1110.         end; { while }
  1111.         MaxStat := -MaxInt;                 { Find best Choice }
  1112.         for TryNo := 12 downto 0 do
  1113.           with Cardstat[TryNo] do if Try then
  1114.             if Stat > MaxStat then
  1115.             begin
  1116.               BestChoice := TryNo;
  1117.               MaxStat := Stat;
  1118.             end;
  1119.       end
  1120.       else
  1121.       begin
  1122.         repeat            { Read Card from keyboard }
  1123.           PlayMenu;
  1124.           Choice := -1;
  1125.           Answer(PlayingHand, Command, false, Redeal);
  1126.                { The third paramater indicates that we are not Bidding }
  1127.           if Redeal then
  1128.             Exit;
  1129.           if (Command = 'O') then
  1130.           begin
  1131.             Command := '';
  1132.             Auto := true;
  1133.             Exit;
  1134.           end;
  1135.           if (Command = 'H') then
  1136.           begin
  1137.             Command := '';
  1138.             Hint := true;
  1139.             Exit;
  1140.           end;
  1141.           if (Command = '') and All then
  1142.             Choice := DiscardCard
  1143.           else
  1144.             for TryNo := 0 to 12 do
  1145.               with Rdist[PlayingHand,TryNo],Cardstat[TryNo] do
  1146.                 if Try then
  1147.                   if (Command = ValueName[Value] + TrumpName[Suit][1]) or
  1148.                      ((Command  =  ValueName[Value]) or
  1149.                      (Command  =  '') and not All) then
  1150.                     Choice := TryNo;
  1151.           if Choice < 0 then
  1152.             Error(' INVALID PLAY ');
  1153.         until Choice >= 0;
  1154.         BestChoice := Choice;
  1155.       end;
  1156. end; { findCard }
  1157.  
  1158. procedure MakeCard(BestChoice: CardNoType; AutoSet : boolean);
  1159. { Play the Card in the real situation, and Update the Rel records }
  1160. var
  1161.   PlayHand : HandType;   { PlayingHand }
  1162.   Card     : CardType;   { Played Card }
  1163. begin
  1164.   CheckKBD;
  1165.   Sim   := Rel;              { Copy the Rel records }
  1166.   Sdist := Rdist;
  1167.   Sdata := Rdata;
  1168.   PlayHand := Sim.PlayingHand;
  1169.   Card := Sdist[PlayHand,BestChoice];
  1170.   with Sim,Card,Info[PlayHand] do
  1171.   begin
  1172.     if Minl[Suit] > 0 then  { Updata Info }
  1173.       Minl[Suit] := Minl[Suit]-1;
  1174.     if (Round and 3 <> 0) and (Suit <> LeadSuit) then
  1175.       Minl[LeadSuit] := -1;
  1176.     CheckKBD;
  1177.     PlayCard(PlayHand,BestChoice);  { Play the Card }
  1178.     CheckKBD;
  1179.     Rel := Sim;                     { Restore the Rel records }
  1180.     Rdist := Sdist;
  1181.     Rdata := Sdata;
  1182.     if Round = 1 then               { Setup screen }
  1183.     begin
  1184.       ClearIt;  { ClearTable and bid window }
  1185.       PrintPlayScreen;
  1186.     end;
  1187.     PrintSuit(PlayHand,Card.Suit);  { Print the Card and the new situation }
  1188.     PrintCard(PlayHand,Card);
  1189.     if Round and 3 = 0 then
  1190.     begin
  1191.       PrintwonTricks;
  1192.       if AutoSet then
  1193.         Delay(LongDelay)
  1194.       else
  1195.         ClearTblMsg;
  1196.       ClearTable;
  1197.     end;
  1198.   end;
  1199. end; { MakeCard }
  1200.  
  1201. procedure PlayCards(var BestChoice : CardNoType;
  1202.                         var Redeal : boolean);
  1203. { finds the cards to plays and plays them for each of
  1204.   the thirteen tricks or until the user cancels the game }
  1205. var
  1206.   SavedHands : PlayerHand;
  1207.   HandsSaved, Auto, Hint, HintPlayed : boolean;
  1208.  
  1209. procedure SetAuto;
  1210. { puts play into auto mode }
  1211.  
  1212. procedure SetHands;
  1213. { Set hands for autoplay }
  1214. var
  1215.   CurHand : HandType;
  1216. begin
  1217.   for CurHand := North to West do
  1218.   begin
  1219.     SavedHands[CurHand] := Computer[CurHand];
  1220.     Computer[CurHand] := true;
  1221.   end;
  1222. end; { SetHands }
  1223.  
  1224. begin  { SetAuto }
  1225.   HandsSaved := true;
  1226.   Command := '';
  1227.   SetHands;
  1228.   PrintScreen(Dummy);   {  Show all hands for AutoPlay  }
  1229.   PrintContract;
  1230.   PrintWonTricks;
  1231.   ClearMenu;
  1232.   Message('  AutoPlay  ');
  1233.   FindCard(BestChoice, Redeal, Auto, Hint);
  1234. end; { SetAuto }
  1235.  
  1236. procedure ResetHands;
  1237. { Restore the hands that the user plays }
  1238. var
  1239.   CurHand : HandType;
  1240. begin
  1241.   for CurHand := North to West do
  1242.   begin
  1243.     Computer[CurHand] := SavedHands[CurHand];
  1244.   end;
  1245. end; { ResetHands }
  1246.  
  1247. procedure SetHint;
  1248. begin
  1249.   with Rel do
  1250.   begin
  1251.     if (PlayingHand = Dummy) then
  1252.     begin
  1253.       Computer[(PlayingHand + 2) and 3] := true;
  1254.       Hint := true;
  1255.       FindCard(BestChoice, Redeal, Auto, Hint);
  1256.       ShowHint(Rel.PlayingHand,
  1257.                Rdist[PlayingHand, BestChoice], HintPlayed);
  1258.       Computer[(PlayingHand + 2) and 3] := false;
  1259.     end
  1260.     else
  1261.     begin
  1262.       Computer[PlayingHand] := true;
  1263.       Hint := true;
  1264.       FindCard(BestChoice, Redeal, Auto, Hint);
  1265.       ShowHint(Rel.PlayingHand,
  1266.                Rdist[PlayingHand, BestChoice], HintPlayed);
  1267.       Computer[PlayingHand] := false;
  1268.     end;
  1269.   end; { with }
  1270. end; { SetHint }
  1271.  
  1272. begin
  1273.   Auto := false;
  1274.   HandsSaved := false;
  1275.   repeat
  1276.     Hint := false;
  1277.     HintPlayed := false;
  1278.     FindCard(BestChoice, Redeal, Auto, Hint);
  1279.     if Redeal then
  1280.     begin
  1281.       GameNo := GameNo - 1;
  1282.       Exit;
  1283.     end;
  1284.     if Hint then
  1285.       SetHint
  1286.     else
  1287.       if Auto and not HandsSaved then
  1288.         SetAuto;
  1289.     if (not Hint) or HintPlayed then
  1290.       MakeCard(BestChoice, HandsSaved);
  1291.   until TrickNo = 13;
  1292.   if HandsSaved then       { AutoPlay over reset the hands }
  1293.     ResetHands;
  1294. end; { PlayCards }
  1295.  
  1296. { end PLAY.BR }