home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xcu16.zip / clients / xhearts / play.c < prev    next >
C/C++ Source or Header  |  1991-10-03  |  21KB  |  837 lines

  1. /*
  2.  * Copyright 1991 Cornell University
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and its
  5.  * documentation for any purpose and without fee is hereby granted, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Cornell U. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Cornell U. makes no representations about the
  11.  * suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * CORNELL UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL CORNELL UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  18.  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  * Author:  Gene W. Dykes, Program of Computer Graphics
  23.  *          580 Theory Center, Cornell University, Ithaca, NY 14853
  24.  *          (607) 255-6713   gwd@graphics.cornell.edu
  25.  */
  26.  
  27.  
  28. #include <stdio.h>
  29. #include <X11/Intrinsic.h>
  30. #include <X11/StringDefs.h>
  31. #include "hearts.h"
  32.  
  33. void determine_lead () ;
  34. static void play () ;
  35. static void score_trick () ;
  36. static void clean_table () ;
  37. void request_another_hand () ;
  38.  
  39. void
  40. trick ()
  41. {
  42. int i ;
  43. for (i=0;  i < N_PLAYERS;  i++)
  44.     play () ;
  45. score_trick () ;
  46. }
  47.  
  48. static void
  49. score_trick ()
  50. {
  51. int i, j ;
  52. char text1[20], text2[20] ;
  53.  
  54. #ifndef NO_LOGGING
  55. if (logerr) fprintf (logerr, "Current_trick : %d\n", CurrentTrick) ;
  56. if (logerr) fprintf (logerr, "Total points taken so far is %d\n",
  57. info->total_points_taken) ;
  58. #endif
  59. if (ThereArePointsInTrick || JackInThisTrick)
  60.     {
  61.     /*
  62.      * See if this is the first trick where points were dropped
  63.      * (Jack doesn't count)
  64.      */
  65.     if (ThereArePointsInTrick && !info->points_broken)
  66.     {
  67.     info->points_broken = True ;
  68.     info->points_broken_trick = snap->n_tricks_played ;
  69.     }
  70.     /*
  71.      * Update Points statistics
  72.      */
  73. #ifndef NO_LOGGING
  74. if (logerr) fprintf (logerr, "Player %d goes from %d to",
  75. TrickWinner, info->n_points_taken[TrickWinner]) ;
  76. #endif
  77.     info->n_points_taken[TrickWinner] += HeartsInThisTrick ;
  78. #ifndef NO_LOGGING
  79. if (logerr) fprintf (logerr, " %d\n", info->n_points_taken[TrickWinner]) ;
  80. #endif
  81.     if (QueenInThisTrick)
  82.     {
  83. #ifndef NO_LOGGING
  84. if (logerr) fprintf (logerr, "Player %d goes from %d to",
  85. TrickWinner, info->n_points_taken[TrickWinner]) ;
  86. #endif
  87.     info->n_points_taken[TrickWinner] += QUEEN_POINTS ;
  88. #ifndef NO_LOGGING
  89. if (logerr) fprintf (logerr, " %d\n", info->n_points_taken[TrickWinner]) ;
  90. #endif
  91.     }
  92. #ifndef NO_LOGGING
  93. if (logerr) fprintf (logerr, "\n- - - - - - - - - - -\n\n") ;
  94. #endif
  95.  
  96.     /*
  97.      * Now, show the points taken results in the player boxes
  98.      */
  99.  
  100.     if (history->jack_counts && info->jack_played && (JackWinner==TrickWinner))
  101.     {
  102.     sprintf (text1, "Points:%3d - %d",
  103.         info->n_points_taken[TrickWinner], JACK_POINTS) ;
  104.     }
  105.     else
  106.     {
  107.     sprintf (text1, "Points:%3d", info->n_points_taken[TrickWinner]) ;
  108.     }
  109.  
  110.     for (i=0;  i < N_PLAYERS;  i++)
  111.     {
  112.     if (game->player[game->ccw[i]].physiology == HumanPhysiology)
  113.         {
  114.         Arg arg ;
  115.         int dir_index = TrickWinner + i ;
  116.         if (dir_index >= N_PLAYERS)
  117.         dir_index -= N_PLAYERS ;
  118.         XtSetArg (arg, XtNlabel, text1) ;
  119.         XtSetValues (game->x.points[game->ccw[i]][dir_index], &arg, 1) ;
  120.         }
  121.     }
  122.     }
  123.  
  124.  
  125. /*
  126.  * Now, show the tricks taken results in the player boxes
  127.  */
  128.  
  129. info->n_tricks_taken[TrickWinner]++ ;
  130. sprintf (text2, "Tricks:%3d", info->n_tricks_taken[TrickWinner]) ;
  131.  
  132. for (i=0;  i < N_PLAYERS;  i++)
  133.     {
  134.     if (game->player[game->ccw[i]].physiology == HumanPhysiology)
  135.     {
  136.     Arg arg ;
  137.     int dir_index = TrickWinner + i ;
  138.     if (dir_index >= N_PLAYERS)
  139.         dir_index -= N_PLAYERS ;
  140.     XtSetArg (arg, XtNlabel, text2) ;
  141.     XtSetValues (game->x.tricks[game->ccw[i]][dir_index], &arg, 1) ;
  142.     }
  143.     }
  144.  
  145. snap->n_tricks_played++ ;
  146.  
  147. /*
  148.  * Make sure everybody gets a few seconds to see the results
  149.  */
  150.  
  151. for (j=0;  j < game->sleep_seconds;  j++)
  152.     {
  153.     for (i=0;  i < N_PLAYERS;  i++)
  154.     if (game->player[i].physiology == HumanPhysiology)
  155.         XcuWlmEvent (game->x.wlm_id[i]) ;
  156.     sleep (1) ;
  157.     }
  158.  
  159. return ;
  160. }
  161.  
  162. void
  163. determine_lead ()
  164. {
  165. int i, j ;
  166. Player *player ;
  167.  
  168. snap->n_played_to_trick = 0 ;
  169. info->n_hearts_played[CurrentTrick] = 0 ;
  170.  
  171. if (CurrentTrick == 0)
  172.     {
  173.     /*
  174.      * Search for the two of clubs and set that player to the leader
  175.      */
  176.     for (i=0;  i < N_SUITS;  i++)
  177.     {
  178.     if (strcmp (game->suit[i].name, "Clubs") != 0)
  179.         continue ;
  180.     for (j=0;  j < CARDS_PER_SUIT;  j++)
  181.         {
  182.         if (strcmp (game->suit[i].rank[j].symbol, "2") == 0)
  183.         {
  184.         int card_number = game->suit[i].rank[j].card ;
  185.         Leader = game->deck[card_number].dealt_to ;
  186.         return ;
  187.         }
  188.         }
  189.     }
  190.     }
  191. else
  192.     {
  193.     /*
  194.      * set leader to the winner of the last trick
  195.      */
  196.     Leader = LastTrickWinner ;
  197.     }
  198.  
  199. /*
  200.  * Do a check here to see if this player can claim the remaining tricks
  201.  * This is true if the worst card in each suit is higher than the highest
  202.  * cards in the suits of the opponents.
  203.  */
  204.  
  205. player = &game->player[Leader] ;
  206.  
  207. for (i=0;  i < N_SUITS;  i++)
  208.     {
  209.     int worst_card, worst_card_rank ;
  210.     if (pvt_history[Leader].n_in_suit[i] == 0)
  211.     continue ;
  212.     worst_card = pvt_history[Leader].suit[i][pvt_history[Leader].n_in_suit[i]-1] ;
  213.     worst_card_rank = info->deck[worst_card].rank ;
  214.     for (j=0;  j < N_PLAYERS;  j++)
  215.     {
  216.     int best_card, best_card_rank ;
  217.     Player *player = &game->player[j] ;
  218.     if (j == Leader)
  219.         continue ;
  220.     if (pvt_history[j].n_in_suit[i] == 0)
  221.         continue ;
  222.     best_card = pvt_history[j].suit[i][0] ;
  223.     best_card_rank = info->deck[best_card].rank ;
  224.     if (best_card_rank > worst_card_rank)
  225.         break ;
  226.     }
  227.     if (j < N_PLAYERS)
  228.     break ;
  229.     }
  230.  
  231. if (i == N_SUITS)
  232.     game->conceded = True ;
  233.  
  234. return ;
  235. }
  236.  
  237. static void
  238. play ()
  239. {
  240. int i ;
  241. int player_index = ActivePlayer ;
  242. Player *player = &game->player[player_index] ;
  243. /*
  244.  * if leader
  245.  *    if first_trick
  246.  *      call for lead of 2 of clubs,
  247.  *    else
  248.  *    prompt for lead
  249.  * else
  250.  *     prompt for play
  251.  */
  252. if (snap->n_played_to_trick == 0)
  253.     {
  254.     /* Time for a lead */
  255.     if (CurrentTrick == 0)
  256.     {
  257.     /* Since it's the first lead, we'll request lead of the 2 of clubs */
  258.     proc_message ("Please lead the two of clubs.", player_index) ;
  259.     }
  260.     else
  261.     {
  262.     proc_message ("It's your lead.", player_index) ;
  263.     }
  264.     }
  265. else
  266.     proc_message ("It's your play.", player_index) ;
  267.  
  268. player->mode = PlayMode ;
  269. if (player->physiology == HumanPhysiology)
  270.     {
  271.     for (
  272.     player->legal_play = False ;
  273.     !player->legal_play ;
  274.     wait_for_player_events ()
  275.     )
  276.     ;
  277.     }
  278. else
  279.     (*game->player[player_index].play_program)
  280.     (&pvt_history[player_index], player_index) ;
  281.  
  282. snap->n_played_to_trick++ ;
  283. player->mode = NullMode ;
  284. proc_message (" ", player_index) ;
  285. if (player->error_mode == ClearOnLegalPlay)
  286.     {
  287.     err_message (" ", player_index) ;
  288.     player->error_mode = NullClear ;
  289.     }
  290.  
  291. return ;
  292. }
  293.  
  294. void
  295. play_selected (data)
  296.     long *data ;
  297. {
  298. int i, j ;
  299. int player_index = (int) data[0] ;
  300. int suit_index = (int) data[1] ;
  301. int rank_index = (int) data[2] ;
  302. char name_string[20] ;
  303. Player *player = &game->player[player_index] ;
  304. int card_number = pvt_history[player_index].suit[suit_index][rank_index] ;
  305. int deck_suit_index = info->deck[card_number].suit ;
  306. int deck_rank_index = info->deck[card_number].rank ;
  307. int dir_index ;
  308. Arg arg ;
  309.  
  310. /*
  311.  * First, check the legality of the play
  312.  */
  313.  
  314. if (rank_index >= pvt_history[player_index].n_in_suit[suit_index])
  315.     {
  316.     err_message ("Fumble fingers!", player_index) ;
  317.     player->error_mode = ClearOnLegalPlay ;
  318.     return ;
  319.     }
  320.  
  321. if (snap->n_played_to_trick == 0)
  322.     {
  323.     /*
  324.      * It's a lead, so the following restrictions apply:
  325.      *    1) If it is the first lead, it must be the 2 of clubs
  326.      *  2) O.w., it cannot be a point card if points have not broken
  327.      *     * Unless the player has nothing but point cards
  328.      */
  329.     if (CurrentTrick == 0)
  330.     {
  331.     if (deck_suit_index != SUIT_CLUBS || deck_rank_index != RANK_TWO)
  332.         {
  333.         err_message("Read my lips! The deuce of Clubs!", Leader);
  334.         player->error_mode = ClearOnLegalPlay ;
  335.         return ;
  336.         }
  337.     }
  338.     else
  339.     {
  340.     if (!info->points_broken)
  341.         {
  342.         if (deck_suit_index == SUIT_HEARTS ||
  343.            (deck_suit_index == SUIT_SPADES &&
  344.         deck_rank_index == RANK_QUEEN))
  345.         {
  346.         /*
  347.          * Attempt to lead a point with points not broken.
  348.          * He must have only point cards for this to be legal
  349.          */
  350.         for (i=0;  i < N_SUITS;  i++)
  351.             {
  352.             for (j=0;  j < pvt_history[player_index].n_in_suit[i];  j++)
  353.             {
  354.             int held_card = pvt_history[player_index].suit[i][j] ;
  355.             if (info->deck[held_card].suit == SUIT_HEARTS)
  356.                 continue ;
  357.             if (info->deck[held_card].suit == SUIT_SPADES &&
  358.                 info->deck[held_card].rank == RANK_QUEEN)
  359.                 continue ;
  360.             err_message ("You are not allowed to lead a point yet!",
  361.                  player_index) ;
  362.             player->error_mode = ClearOnLegalPlay ;
  363.             return ;
  364.             }
  365.             }
  366.         }
  367.         }
  368.     }
  369.     /*
  370.      * If here, it was a legal lead
  371.      * Clear the table of the last trick
  372.      */
  373.     TrickWinner = player_index ;
  374.     info->trick_taking_rank = deck_rank_index ;
  375.  
  376.     clean_table () ;
  377.     }
  378. else
  379.     {
  380.     /*
  381.      * It's not a lead, so the following restrictions apply:
  382.      *    1) Must follow suit
  383.      *  2) If sloughing, there may be a rule that forbids sloughing
  384.      *     points on the first trick...
  385.      */
  386.     if (deck_suit_index != SuitLead)
  387.     {
  388.     if (pvt_history[player_index].n_in_suit[SuitLead] > 0)
  389.         {
  390.         err_message ("That's a renege! Try again.", player_index) ;
  391.         player->error_mode = ClearOnLegalPlay ;
  392.         return ;
  393.         }
  394.     if (
  395.        CurrentTrick == 0 &&
  396.        !history->points_on_first_trick &&
  397.         (
  398.         deck_suit_index == SUIT_HEARTS ||
  399.         (deck_suit_index == SUIT_SPADES && deck_rank_index == RANK_QUEEN)
  400.         )
  401.        )
  402.         {
  403.         err_message ("No point dumping on first trick! Try again.",
  404.              player_index) ;
  405.         player->error_mode = ClearOnLegalPlay ;
  406.         return ;
  407.         }
  408.     /*
  409.      * If here, it was a legal play, even though suit was not followed
  410.      */
  411.     }
  412.     else
  413.     {
  414.     /* check to see if this card may take the trick */
  415.     /* lower rank_indices are the higher ranking cards :-( */
  416.     if (deck_rank_index > info->trick_taking_rank)
  417.         {
  418.         info->trick_taking_rank = deck_rank_index ;
  419.         TrickWinner = player_index ;
  420.         }
  421.     }
  422.     }
  423.  
  424. history->trick[CurrentTrick].card[snap->n_played_to_trick] = card_number ;
  425. player->legal_play = True ;
  426.  
  427. if (deck_suit_index == SUIT_HEARTS)
  428.     {
  429.     info->n_hearts_played[CurrentTrick]++ ;
  430.     info->total_points_taken += HEART_POINTS ;
  431.     info->n_point_cards_taken++  ;
  432.     }
  433.  
  434. if (deck_suit_index == SUIT_SPADES && deck_rank_index == RANK_QUEEN)
  435.     {
  436.     info->queen_played = True ;
  437.     info->queen_played_trick = CurrentTrick ;
  438.     info->total_points_taken += QUEEN_POINTS ;
  439.     info->n_point_cards_taken++ ;
  440.     }
  441.  
  442. if (history->jack_counts &&
  443.     deck_suit_index == SUIT_DIAMONDS &&
  444.     deck_rank_index == RANK_JACK)
  445.     {
  446.     info->jack_played = True ;
  447.     info->jack_played_trick = CurrentTrick ;
  448.     info->n_point_cards_taken++ ;
  449.     }
  450.  
  451. /*
  452.  * Then, show the play on the table
  453.  */
  454.  
  455. /************
  456.  I wish I knew why this code doesn't work.
  457.  I get "Cannot access per-display info"
  458. for (i=0;  i < N_PLAYERS;  i++)
  459.     {
  460.     Arg args[2] ;
  461.     int dir_index = player_index + i ;
  462.     if (dir_index >= N_PLAYERS)
  463.     dir_index -= N_PLAYERS ;
  464.     XtSetArg (args[0], XtNforeground, game->suit[deck_suit_index].color[game->ccw[i]]) ;
  465.     XtSetArg (args[1], XtNlabel, card_string) ;
  466.     XtSetValues (game->x.plays[game->ccw[i]][dir_index], args, 2) ;
  467.     }
  468. ****************/
  469. {
  470. int dir_index = player_index ;
  471. if (game->player[dir_index].physiology == HumanPhysiology)
  472.     {
  473.     XcuWlmSetValue (game->x.wlm_id[dir_index], "XcuLabel", "south_card",
  474.     XtNforeground, game->suit[deck_suit_index].color_string) ;
  475.     XcuWlmSetValue (game->x.wlm_id[dir_index], "XcuLabel", "south_card",
  476.     XtNlabel, game->suit[deck_suit_index].rank[deck_rank_index].symbol) ;
  477.     XcuDeckRaiseWidget(game->x.south_bitmap[dir_index],
  478.                game->x.south_suit[dir_index][deck_suit_index]);
  479.     }
  480. dir_index++ ;
  481. if (dir_index == N_PLAYERS)
  482.     dir_index = 0 ;
  483. if (game->player[dir_index].physiology == HumanPhysiology)
  484.     {
  485.     XcuWlmSetValue (game->x.wlm_id[dir_index], "XcuLabel", "east_card",
  486.     XtNforeground, game->suit[deck_suit_index].color_string) ;
  487.     XcuWlmSetValue (game->x.wlm_id[dir_index], "XcuLabel", "east_card",
  488.     XtNlabel, game->suit[deck_suit_index].rank[deck_rank_index].symbol) ;
  489.     XcuDeckRaiseWidget(game->x.east_bitmap[dir_index],
  490.                game->x.east_suit[dir_index][deck_suit_index]);
  491.     }
  492. dir_index++ ;
  493. if (dir_index == N_PLAYERS)
  494.     dir_index = 0 ;
  495. if (game->player[dir_index].physiology == HumanPhysiology)
  496.     {
  497.     XcuWlmSetValue (game->x.wlm_id[dir_index], "XcuLabel", "north_card",
  498.     XtNforeground, game->suit[deck_suit_index].color_string) ;
  499.     XcuWlmSetValue (game->x.wlm_id[dir_index], "XcuLabel", "north_card",
  500.     XtNlabel, game->suit[deck_suit_index].rank[deck_rank_index].symbol) ;
  501.     XcuDeckRaiseWidget(game->x.north_bitmap[dir_index],
  502.                game->x.north_suit[dir_index][deck_suit_index]);
  503.     }
  504. dir_index++ ;
  505. if (dir_index == N_PLAYERS)
  506.     dir_index = 0 ;
  507. if (game->player[dir_index].physiology == HumanPhysiology)
  508.     {
  509.     XcuWlmSetValue (game->x.wlm_id[dir_index], "XcuLabel", "west_card",
  510.     XtNforeground, game->suit[deck_suit_index].color_string) ;
  511.     XcuWlmSetValue (game->x.wlm_id[dir_index], "XcuLabel", "west_card",
  512.     XtNlabel, game->suit[deck_suit_index].rank[deck_rank_index].symbol) ;
  513.     XcuDeckRaiseWidget(game->x.west_bitmap[dir_index],
  514.                game->x.west_suit[dir_index][deck_suit_index]);
  515.     }
  516. }
  517.  
  518. /*
  519.  * Now, remove the card from the hand
  520.  * Collapse the labels left in the row and blank out the last one
  521.  */
  522.  
  523. if (game->player[player_index].physiology == HumanPhysiology)
  524.     {
  525.     XtSetArg (arg, XtNlabel, " ") ;
  526.     XtSetValues (game->x.hands[player_index][suit_index]
  527.           [pvt_history[player_index].n_in_suit[suit_index]-1], &arg, 1) ;
  528.  
  529.     }
  530.  
  531. pvt_history[player_index].n_in_suit[suit_index]-- ;
  532. game->deck[card_number].dealt_to = N_PLAYERS ;
  533.  
  534. order_hand (player_index) ;
  535. show_deal (player_index) ;
  536. player->mode = NullMode ;
  537.  
  538. return ;
  539. }
  540.  
  541. void
  542. score_hand ()
  543. {
  544. int i, j ;
  545. char text0[20] ;
  546. char text1[20] ;
  547. char text2[20] ;
  548. char text[20] ;
  549.  
  550. /*
  551.  * First check to see if anybody claimed the rest of the tricks
  552.  */
  553.  
  554. if (game->conceded)
  555.     {
  556.     for (i=CurrentTrick;  i < N_TRICKS;  i++)
  557.     info->trick_winner[i] = Leader ;
  558.  
  559. #ifndef NO_LOGGING
  560. if (logerr) fprintf (logerr, "Player %d goes from %d to",
  561. Leader, info->n_points_taken[Leader]) ;
  562. #endif
  563.     info->n_points_taken[Leader] += (SHOOT_POINTS - info->total_points_taken) ;
  564. #ifndef NO_LOGGING
  565. if (logerr) fprintf (logerr, " %d\n", info->n_points_taken[Leader]) ;
  566. #endif
  567.  
  568.     /* Just for the heck of it, put all the goodies in this trick */
  569.     if (!info->jack_played)
  570.     {
  571.     info->jack_played = True ;
  572.     info->jack_played_trick = CurrentTrick ;
  573.     }
  574.     if (!info->queen_played)
  575.     {
  576.     info->queen_played = True ;
  577.     info->queen_played_trick = CurrentTrick ;
  578.     }
  579.  
  580.     if (history->jack_counts && info->jack_played && (JackWinner==TrickWinner))
  581.     {
  582.     sprintf (text1, "Points:%3d - %d",
  583.         info->n_points_taken[TrickWinner], JACK_POINTS) ;
  584.     }
  585.     else
  586.     {
  587.     sprintf (text1, "Points:%3d", info->n_points_taken[TrickWinner]) ;
  588.     }
  589.  
  590.     for (i=0;  i < N_PLAYERS;  i++)
  591.     {
  592.     if (game->player[game->ccw[i]].physiology == HumanPhysiology)
  593.         {
  594.         Arg arg ;
  595.         int dir_index = TrickWinner + i ;
  596.         if (dir_index >= N_PLAYERS)
  597.         dir_index -= N_PLAYERS ;
  598.         XtSetArg (arg, XtNlabel, text1) ;
  599.         XtSetValues (game->x.points[game->ccw[i]][dir_index], &arg, 1) ;
  600.         }
  601.     }
  602.     }
  603.  
  604. /*
  605.  * Next check to see if anybody shot the moon
  606.  */
  607.  
  608. for (i=0;  i < N_PLAYERS;  i++)
  609.     {
  610.     if (info->n_points_taken[i] == SHOOT_POINTS)
  611.     break ;
  612.     }
  613.  
  614. if (i < N_PLAYERS)
  615.     {
  616.     /*  A Shoot! */
  617.     char text[100] ;
  618.  
  619.     sprintf (text, "%s shot the moon!", game->player[i].name_string) ;
  620.  
  621.     if (game->player[i].physiology == HumanPhysiology)
  622.     {
  623.     XcuDeckRaiseWidget (game->x.table_deck[i], game->x.moon_decision[i]) ;
  624.  
  625.     for (
  626.         game->moon_decision = NullMoonDecision;
  627.         game->moon_decision == NullMoonDecision;
  628.         wait_for_player_events ()
  629.         /*
  630.         XcuWlmRequest (game->x.wlm_id[i])
  631.         */
  632.         ) ;
  633.     }
  634.     else
  635.     game->moon_decision = RaiseOthers ;
  636.  
  637.     for (j=0;  j < N_PLAYERS;  j++)
  638.     {
  639.     if (game->moon_decision == RaiseOthers)
  640.         info->n_points_taken[j] = SHOOT_POINTS ;
  641.     else
  642.         info->n_points_taken[j] = 0 ;
  643.     /* Announce it! */
  644.     proc_message (text, j) ;
  645.     }
  646.     if (game->moon_decision == RaiseOthers)
  647.     info->n_points_taken[i] = 0 ;
  648.     else
  649.     info->n_points_taken[i] = -SHOOT_POINTS ;
  650.     }
  651.  
  652. for (i=0;  i < N_PLAYERS;  i++)
  653.     {
  654. #ifndef NO_LOGGING
  655. if (logerr) fprintf (logerr, "Adding %d to player %d's score of %d\n",
  656. info->n_points_taken[i], i, game->player[i].score) ;
  657. #endif
  658.     game->player[i].score += info->n_points_taken[i] ;
  659.     }
  660.  
  661. if (history->jack_counts)
  662.     {
  663. #ifndef NO_LOGGING
  664. if (logerr) fprintf (logerr, "Subtracting %d from player %d's score of %d\n",
  665. JACK_POINTS, i, game->player[JackWinner].score) ;
  666. #endif
  667.     game->player[JackWinner].score -= JACK_POINTS ;
  668.     }
  669.  
  670. for (i=0;  i < N_PLAYERS;  i++)
  671.     {
  672.     Arg arg ;
  673.     sprintf (text, "Score:%4d", game->player[i].score) ;
  674.     XtSetArg (arg, XtNlabel, text) ;
  675.     for (j=0;  j < N_PLAYERS;  j++)
  676.     {
  677.     if (game->player[j].physiology == HumanPhysiology)
  678.         {
  679.         int dir_index = game->ccw[j] + i ;
  680.         if (dir_index >= N_PLAYERS)
  681.         dir_index -= N_PLAYERS ;
  682.         XtSetValues (game->x.score[j][dir_index], &arg, 1) ;
  683.         }
  684.     }
  685.     }
  686.  
  687. clean_table () ;
  688.  
  689. return ;
  690. }
  691.  
  692. static void
  693. clean_table ()
  694. {
  695. int i, j ;
  696. for (i=0;  i < N_PLAYERS;  i++)
  697.     {
  698.     if (game->player[i].physiology == ComputerPhysiology)
  699.     continue ;
  700.     for (j=0;  j < N_PLAYERS;  j++)
  701.     {
  702.     char name_string[20] ;
  703.     sprintf (name_string, "%s_card", game->seat[j]) ;
  704.     XcuWlmSetValue(game->x.wlm_id[i], "XcuLabel", name_string,
  705.                           XtNlabel," ");
  706.     }
  707.     XcuDeckRaiseWidget(game->x.south_bitmap[i], game->x.south_suit[i][N_SUITS]);
  708.     XcuDeckRaiseWidget(game->x.east_bitmap[i], game->x.east_suit[i][N_SUITS]);
  709.     XcuDeckRaiseWidget(game->x.west_bitmap[i], game->x.west_suit[i][N_SUITS]);
  710.     XcuDeckRaiseWidget(game->x.north_bitmap[i], game->x.north_suit[i][N_SUITS]);
  711.     }
  712. return ;
  713. }
  714.  
  715. Boolean
  716. hand_over ()
  717. {
  718. int i ;
  719.  
  720. if (CurrentTrick == CARDS_PER_PLAYER)
  721.     {
  722.     for (i=0;  i < N_PLAYERS;  i++)
  723.     {
  724.     game->player[i].mode = NullMode ;
  725.     proc_message ("Hand is over. No tricks left.", i) ;
  726.     }
  727.     return True ;
  728.     }
  729. else
  730. if (game->conceded)
  731.     {
  732.     for (i=0;  i < N_PLAYERS;  i++)
  733.     {
  734.     game->player[i].mode = NullMode ;
  735.     proc_message ("Hand is over. Remainder won.", i) ;
  736.     }
  737.     clear_hands (history, pvt_history, snap, info) ;
  738.     return True ;
  739.     }
  740. else
  741. if (info->n_point_cards_taken == info->n_point_cards)
  742.     {
  743.     for (i=0;  i < N_PLAYERS;  i++)
  744.     {
  745.     game->player[i].mode = NullMode ;
  746.     proc_message ("Hand is over. No points left.", i) ;
  747.     }
  748.     clear_hands () ;
  749.     return True ;
  750.     }
  751.  
  752. return False ;
  753. }
  754.  
  755. void
  756. moon_decision (card, client_data, call_data)
  757.     Widget card ;
  758.     XPointer client_data ;
  759.     XPointer call_data ;
  760. {
  761. long *data = (long *) client_data ;
  762. int decision = (int) data[0] ;
  763.  
  764. game->moon_decision = decision ;
  765. return ;
  766. }
  767.  
  768. void
  769. hand_decision (card, client_data, call_data)
  770.     Widget card ;
  771.     XPointer client_data ;
  772.     XPointer call_data ;
  773. {
  774. long *data = (long *) client_data ;
  775. int player_index = (int) data[0] ;
  776. int decision = (int) data[1] ;
  777.  
  778. game->player[player_index].hand_decision = decision ;
  779. XcuDeckRaiseWidget (game->x.table_deck[player_index],
  780.             game->x.play_tbl[player_index]) ;
  781.  
  782. return ;
  783. }
  784.  
  785. void 
  786. request_another_hand ()
  787. {
  788. int i ;
  789. /*
  790.  * Ask everybody if they want to play another hand
  791.  */
  792.  
  793. for (i=0;  i < N_PLAYERS;  i++)
  794.     {
  795.     game->player[i].hand_decision = NullHandDecision ;
  796.     if (game->player[i].physiology == HumanPhysiology)
  797.     XcuDeckRaiseWidget (game->x.table_deck[i], game->x.hand_decision[i]) ;
  798.     }
  799.  
  800. /*
  801.  * Wait for everybody to vote
  802.  */
  803.  
  804. game->hand_decision = AnotherHand ;
  805.  
  806. for (;;)
  807.     {
  808.     wait_for_player_events () ;
  809.     for (i=0;  i < N_PLAYERS;  i++)
  810.     {
  811.     if (game->player[i].physiology == ComputerPhysiology)
  812.         continue ;
  813.     if (game->player[i].hand_decision == NullHandDecision)
  814.         break ;
  815.     if (game->player[i].hand_decision == NoMore)
  816.         break ;
  817.     }
  818.     if (i == N_PLAYERS)
  819.     break ;
  820.     if (game->player[i].hand_decision == NoMore)
  821.     {
  822.     game->hand_decision = NoMore ;
  823.     break ;
  824.     }
  825.     }
  826. return ;
  827. }
  828.  
  829. int
  830. active_player ()
  831. {
  832. int position = Leader + snap->n_played_to_trick ;
  833. if (position >= N_PLAYERS)
  834.     position -= N_PLAYERS ;
  835. return position ;
  836. }
  837.