home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume14 / okbridge2 / part06 / display.c < prev   
C/C++ Source or Header  |  1993-01-27  |  34KB  |  1,287 lines

  1. /* display.c -- Display functions for OKbridge program.
  2.  *
  3.  ! Copyright (C) 1990-1992 by Matthew Clegg.  All Rights Reserved
  4.  ! 
  5.  ! OKbridge is made available as a free service to the Internet.
  6.  ! Accordingly, the following restrictions are placed on its use:
  7.  ! 
  8.  ! 1.  OKbridge may not be modified in any way without the explicit 
  9.  !     permission of Matthew Clegg.  
  10.  ! 
  11.  ! 2.  OKbridge may not be used in any way for commercial advantage.
  12.  !     It may not be placed on for-profit networks or on for-profit
  13.  !     computer systems.  It may not be bundled as part of a package
  14.  !     or service provided by a for-profit organization.
  15.  ! 
  16.  ! If you have questions about restrictions on the use of OKbridge,
  17.  ! write to mclegg@cs.ucsd.edu.
  18.  ! 
  19.  ! DISCLAIMER:  The user of OKbridge accepts full responsibility for any
  20.  ! damage which may be caused by OKbridge.
  21.  *
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <string.h>
  26.  
  27. extern char *malloc ();
  28.  
  29. #define _DISPLAY_
  30.  
  31. #include "state.h"
  32. #include "terminal.h"
  33. #include "display.h"
  34. #include "help.h"
  35. #include "input.h"
  36.  
  37. #ifdef LOGFILE
  38. extern FILE *net_log;
  39. #endif
  40.  
  41. typedef int window[4];
  42.  
  43. /* Conceptually, we think of the screen as being divided into a number
  44.    of windows, where each window describes one particular type of activity
  45.    or aspect of the game.  Therefore, we make the following definitions,
  46.    although these are only guidelines for operation of the display.
  47.  
  48. Name of
  49. Window               Ymin    Xmin    Height    Width
  50. -------             ----    ----    ----    ----            */
  51. window title          = { 1,    1,    6,    25};
  52. window top_hand      = { 2,    30,    4,    26};
  53. window scores         = { 1,    58,    6,    26};
  54. window left_hand     = { 8,    6,    6,    18};
  55. window playing_board = { 5,    27,    9,    26};
  56. window bidding_board = { 5,    1,    9,    57};
  57. window right_hand    = { 8,    56,    6,    23};
  58. window input         = { 13,    1,    6,    26};
  59. window status         = { 18,    1,    1,    79};
  60. window bottom_hand   = { 13,    30,    4,    26};
  61. window help         = { 13,    53,    6,    26};
  62. window converse         = { 19,    1,    6,    78};
  63.  
  64. #define XMIN(w)        w[1]
  65. #define YMIN(w)         w[0]
  66. #define XMAX(w)        (w[1] + w[3] - 1)
  67. #define YMAX(w)        (w[0] + w[2] - 1)
  68. #define HEIGHT(w)    w[2]
  69. #define WIDTH(w)    w[3]
  70.  
  71. static int PLAYERHAND_X [4];
  72. static int PLAYERHAND_Y [4]; 
  73. static int CARDPOS_X    [4];
  74. static int CARDPOS_Y    [4];
  75. static char *position_names [4];
  76. static int comments_suspended = 0;
  77.  
  78. static char line_buf [81];
  79. static int  status_loc;
  80.  
  81. #define COMMENT_LENGTH 78
  82.  
  83. typedef char comment_line [COMMENT_LENGTH];
  84. typedef comment_line *comment_buf;
  85.  
  86. static int full_screen_talk_start = 3;
  87.   /* The first line of the screen on which comments will be displayed,
  88.      if the full screen is used for talking.  */
  89. static int full_screen_talk_end  = 22;
  90.   /* The last line on which comments will be displayed for full screen mode. */
  91. static int full_screen_talk_size = 20;
  92.   /* The total number of lines in the full screen talk display. */
  93. static int full_screen_cursor = 0;
  94.   /* The line in the full screen buffer where the next talk message will be
  95.      displayed. */
  96.  
  97. static int playing_screen_talk_start = 20;
  98.   /* The first line of the screen on which comments will be displayed,
  99.      if we are in playing mode. */
  100. static int playing_screen_talk_end = 24;
  101.   /* last comment line for playing screen. */
  102. static int playing_screen_talk_size = 5;
  103.   /* The total number of lines in the playing screen talk display. */
  104.  
  105. static int talk_start, talk_end;
  106.   /* The current first and last lines for display of player comments. */
  107. static int talk_size;
  108.   /* talk_end - talk_start + 1. */
  109.  
  110. static comment_line *full_screen_comments = NULL, 
  111.                     *playing_screen_comments = NULL,
  112.                     *player_comments;
  113.  
  114. /* We record the list of cards played in the current trick, so that
  115.    we can redisplay them during a refresh if necessary. */
  116. static int Current_trick [4];
  117.   /* A list of plays indexed by position.  If the value is non-negative,
  118.      then it indicates the play made by the corresponding player. */
  119.  
  120. static int status_display_level = 0;
  121.   /* The number of locks which have been placed on the status display. */
  122. static char status_buf [10] [80];
  123.   /* For each lock level, a record of the status message at that level. */
  124.  
  125. Board *Board_for_display;
  126.   /* This is a pointer to the board which is being displayed in the
  127.      SCORING_DISPLAY mode. */
  128. Play_record *Current_page_of_scores = NULL;
  129.   /* The first play record which is being displayed on the current page
  130.      of scores. */
  131. Play_record *Next_page_of_scores = NULL;
  132.   /* The first play record which will be displayed on the next page 
  133.      of scores. */
  134.  
  135. char total_time_buffer [20];
  136.   /* A buffer used for displaying the total time playing the current hand. */
  137. char local_time_buffer [20];
  138.   /* A buffer used for displaying the time used by the local player. */
  139.     
  140. void Select_Talk_Mode ();
  141. void Select_Conversation_Mode ();
  142. void Display_Page_of_Scores ();
  143. void Refresh_Time_Display ();
  144.  
  145.  
  146. static void underline (ymin, xmin, length)
  147.        int ymin, xmin, length;
  148. /* Prints a line of hyphens BELOW the field beginning at (ymin,xmin),
  149.  *  of given length.
  150.  */
  151. {
  152.     int i;
  153.  
  154.     for (i = 0; i < length; i++)
  155.         line_buf[i] = '-';
  156.     line_buf[length] = '\0';
  157.     print (ymin+1, xmin, line_buf);
  158. }
  159.  
  160. static void clear_screen_area (ymin, xmin, height, width)
  161.        int ymin, xmin, height, width;
  162. {
  163.     int i;
  164.  
  165.     for (i = 0; i < width; i++) line_buf[i] = ' ';
  166.     line_buf[width] = '\0';
  167.     for (i = 0; i < height; i++) print (ymin+i, xmin, line_buf);
  168. }
  169.  
  170. static void Display_Board_Number ()
  171. {
  172.   if ((Local_board != NULL) && (Local_board->source != NULL)) {
  173.     sprintf (line_buf, "%s BOARD %d", Local_board->source,
  174.          Local_board->serial_no);
  175.     print (YMIN(title)+1,  XMIN(title),  line_buf);
  176.   } else {
  177.     sprintf (line_buf, "%d", hands_played);
  178.     print (YMIN(title)+1, XMIN(title)+6, line_buf);
  179.   }
  180.  
  181. }
  182.  
  183. static void Redraw_Scoring_Panel ()
  184. /* Redraws the scoring panel in the upper corner of the screen, which
  185.    displays the vulnerabilities, number of tricks taken, and scores.
  186. */
  187. {
  188.   /* Setup the scoreboard: */
  189.   if (local_player >= 4) {
  190.     print (YMIN(scores), XMIN(scores) + 8,   "  N-S");
  191.     print (YMIN(scores), XMIN(scores) + 16,  "  E-W");
  192.   } else if (side_of(local_player) == SIDE_NS) {
  193.     print (YMIN(scores), XMIN(scores) + 8,   "   WE");
  194.     print (YMIN(scores), XMIN(scores) + 16,  " THEY");
  195.   } else {
  196.     print (YMIN(scores), XMIN(scores) + 16,  "   WE");
  197.     print (YMIN(scores), XMIN(scores) + 8,   " THEY");
  198.   }
  199.   underline (YMIN(scores), XMIN(scores) + 8, 5);
  200.   underline (YMIN(scores), XMIN(scores) + 16, 5);
  201.   print (YMIN(scores)+2, XMIN(scores), "TRICKS");
  202.   print (YMIN(scores)+3, XMIN(scores), "VUL");
  203.   
  204.   switch (Local_board->scoring_mode) {
  205.   case RUBBER_SCORING:
  206.     print (YMIN(scores)+4, XMIN(scores), "ABOVE");
  207.     print (YMIN(scores)+5, XMIN(scores), "BELOW");
  208.     print (YMIN(title)+1,  XMIN(title),  "HAND");
  209.     break;
  210.   case DUPLICATE_SCORING:
  211.     print (YMIN(scores)+4, XMIN(scores), "TOTAL");
  212.     print (YMIN(scores)+5, XMIN(scores), "PREV");
  213.     print (YMIN(title)+1,  XMIN(title),  "BOARD");
  214.     break;
  215.   case IMP_SCORING:
  216.     print (YMIN(scores)+4, XMIN(scores), "TOTAL");
  217.     print (YMIN(scores)+5, XMIN(scores), "IMP");
  218.     print (YMIN(title)+1,  XMIN(title),  "BOARD");
  219.     break;
  220.   case MP_SCORING:
  221.     print (YMIN(scores)+4, XMIN(scores), "TOTAL");
  222.     print (YMIN(scores)+5, XMIN(scores), "MP");
  223.     print (YMIN(title)+1,  XMIN(title),  "BOARD");
  224.     break;
  225.   default:
  226.     break;
  227.   }
  228.  
  229.   Display_Tricks_Taken ();
  230.   Display_Above_Line_Points ();
  231.   Display_Below_Line_Points ();
  232.   Display_Vulnerabilities ();
  233.   Display_Board_Number ();
  234.  
  235. }
  236.  
  237. static void Redraw_Conversation_Area ()
  238. {
  239.   int i;
  240.  
  241.   /* Setup the conversational area: */
  242.   for (i = 0; i <= XMAX(converse); i++) line_buf[i] = '-';
  243.   line_buf[72] = '+';
  244.   line_buf[XMAX(converse)+1] = '\0';
  245.   print (YMIN(converse), XMIN(converse), line_buf);
  246.   for (i = talk_start; i <= talk_end; i++) {
  247.     print (i, XMIN(converse), "|");
  248.     print (i, XMAX(converse)+1, "|");
  249.   }
  250.  
  251.   /* Setup the input area: */
  252.   print (TALK_ROW, TALK_COL, "TALK");
  253.   status_loc = YMIN(status);
  254.  
  255. }
  256.  
  257. static void Redraw_Bidding_Display ()
  258. {
  259.   int i, p;
  260.   hand h;
  261.   
  262.   Display_Bidding_Board ();
  263.   if (IS_PLAYER(local_player)) {
  264.     Generate_holdings (Local_board, Local_play->play_list, 0, local_player, h);
  265.     Display_Hand_for_Bidding (local_player, h);
  266.   } else if (spectator_mode) {
  267.     Generate_holdings (Local_board, Local_play->play_list, 0, 
  268.                revealed_bidder, h);
  269.     Display_Hand_for_Bidding (revealed_bidder, h);
  270.   }
  271.  
  272.   p = Local_board->dealer;
  273.   for (i = 0; i < Local_play->no_bids; i++) {
  274.     Display_Bid (i);
  275.     p = player_next [p];
  276.   }
  277.   Display_Bidder (p);
  278.   Refresh_Time_Display ();
  279.   print (PLAY_ROW, PLAY_COL, "BID ");
  280. }
  281.  
  282. static void Redraw_Playing_Display ()
  283. {
  284.   int i;
  285.  
  286.   Display_Contract (); 
  287.   Display_Playing_Board ();
  288.  
  289.   for (i = 0; i < 4; i++)
  290.     if (revealed_hands[i]) {
  291.       if (Local_table->game_mode == PLAYING_MODE)
  292.     Display_Hand(i);
  293.       else
  294.     Display_Partial_Hand (i, 0);
  295.     }
  296.  
  297.   for (i = 0; i < 4; i++)
  298.     Display_Play (i, Current_trick[i]);
  299.  
  300.   Display_Player (Local_play->next_player);
  301.   Refresh_Time_Display ();
  302.   print (PLAY_ROW, PLAY_COL, "PLAY");
  303. }
  304.  
  305. static void Redraw_Scoring_Display ()
  306. {
  307.   Display_Page_of_Scores (Current_page_of_scores);
  308. }
  309.  
  310. void Display_Player_Position ()
  311. {
  312.   char buf[80], *position_name;
  313.   
  314.   if (IS_PLAYER(local_player))
  315.     position_name = seat_names[local_player];
  316.   else if (spectator_mode)
  317.     position_name = "SPECTATOR";
  318.   else
  319.     position_name = "OBSERVER";
  320.   
  321.   sprintf (buf, "OKBRIDGE %s%s  %s     ", 
  322.        major_revision_level, minor_revision_level, position_name);
  323.   
  324.   print (1, 1, buf);
  325.  
  326. void Refresh_Status_Display ();
  327. void Begin_full_screen_talk_mode ();
  328. void Recompute_Display_Positions ();
  329.  
  330. void Reset_Display ()
  331. /* Redraws the main features of the screen.  Used in the process
  332.  * of doing a 'refresh'.
  333.  */
  334. {
  335.   if (display_mode == MANUAL_DISPLAY)
  336.     return;
  337.  
  338.   clear_screen ();
  339.  
  340.   Recompute_Display_Positions ();
  341.  
  342.   if (display_mode == HELP_DISPLAY) {
  343.     Suspend_Comment_Display ();
  344.     status_loc = terminal_lines;
  345.     display_topics ("LIST OF HELP TOPICS");
  346.     print (terminal_lines-1, 1, "HELP");
  347.     Refresh_Status_Display ();
  348.     return;
  349.   }
  350.  
  351.   Display_Player_Position ();
  352.   Continue_Comment_Display ();
  353.   
  354.   switch (display_mode) {
  355.   case TALK_DISPLAY:
  356.     Begin_full_screen_talk_mode ();
  357.     break;
  358.   case BIDDING_DISPLAY:
  359.     Redraw_Bidding_Display ();
  360.     Redraw_Scoring_Panel ();
  361.     Redraw_Conversation_Area ();
  362.     break;
  363.   case PLAYING_DISPLAY:
  364.     Redraw_Playing_Display ();
  365.     Redraw_Scoring_Panel ();
  366.     Redraw_Conversation_Area ();
  367.     break;
  368.   case SCORING_DISPLAY:
  369.     Redraw_Scoring_Display ();
  370.     Redraw_Conversation_Area ();
  371.     break;
  372.   }
  373.  
  374.   Refresh_Player_Comments ();
  375.   Refresh_Status_Display ();
  376. }
  377.  
  378. void Recompute_Display_Positions ()
  379. /* Recomputes a number of internal constants for the display. */
  380. {
  381.   int l = local_player;
  382.   
  383.   if (l >= 4) l = PLAYER_SOUTH;
  384.   
  385.   PLAYERHAND_X [l] = XMIN(bottom_hand);
  386.   PLAYERHAND_Y [l] = YMIN(bottom_hand);
  387.   PLAYERHAND_X [player_next[l]] = XMIN(left_hand);
  388.   PLAYERHAND_Y [player_next[l]] = YMIN(left_hand);
  389.   PLAYERHAND_X [player_partner[l]] = XMIN(top_hand);
  390.   PLAYERHAND_Y [player_partner[l]] = YMIN(top_hand);
  391.   PLAYERHAND_X [player_prev[l]] = XMIN(right_hand);
  392.   PLAYERHAND_Y [player_prev[l]] = YMIN(right_hand);
  393.   
  394.   CARDPOS_Y[l] = YMAX(playing_board) - 2;
  395.   CARDPOS_X[l] = (XMAX(playing_board) + 
  396.           XMIN(playing_board))/2;
  397.   CARDPOS_Y[player_next[l]] = (YMAX(playing_board) + 
  398.                    YMIN(playing_board))/2;
  399.   CARDPOS_X[player_next[l]] = XMIN(playing_board) + 3;
  400.   CARDPOS_Y[player_partner[l]] = YMIN(playing_board) + 2;
  401.   CARDPOS_X[player_partner[l]] = (XMAX(playing_board) + 
  402.                   XMIN(playing_board))/2;
  403.   CARDPOS_Y[player_prev[l]] = (YMAX(playing_board) + 
  404.                    YMIN(playing_board))/2;
  405.   CARDPOS_X[player_prev[l]] = XMAX(playing_board) - 4;
  406.   
  407.   position_names[0] = PLAYER_NAME(Local_table, l);
  408.   position_names[1] = PLAYER_NAME(Local_table, player_next[l]);
  409.   position_names[2] = PLAYER_NAME(Local_table, player_partner[l]);
  410.   position_names[3] = PLAYER_NAME(Local_table, player_prev[l]);
  411. }
  412.  
  413. void Initialize_Display ()
  414. /* Should be called once when the program starts up. */
  415.   Initialize_Player_Comments ();
  416.   status_buf[0][0] = '\0';
  417.   display_mode = TALK_DISPLAY;
  418.   Current_trick[0] = Current_trick[1] = 
  419.     Current_trick[2] = Current_trick[3] = -1;
  420.  
  421.   Reset_Display ();
  422.   Recompute_Display_Positions ();
  423. }
  424.  
  425. void Reinitialize_Display ()
  426. {
  427.   Reinitialize_Player_Comments ();
  428.   Reset_Display ();
  429.  
  430.   Recompute_Display_Positions ();
  431. }
  432.  
  433. void Refresh_Display ()
  434. /* Resets the terminal display and redraws everything. */
  435. {
  436.   Reset_Display ();
  437. }
  438.  
  439. void Clear_Playing_Area ();
  440.  
  441. void Refresh_Player_Names ()
  442. /* Redraws the player names.  Useful in case one of the players has changed
  443.    position. */
  444. {
  445.   if ((display_mode != BIDDING_DISPLAY) && (display_mode != PLAYING_DISPLAY))
  446.     return;
  447.  
  448.   if (display_mode == BIDDING_DISPLAY) {
  449.     Clear_Bidding_Board ();
  450.     Redraw_Bidding_Display ();
  451.   } else {
  452.     Clear_Playing_Area ();
  453.     Redraw_Playing_Display ();
  454.   }
  455.  
  456. }
  457.  
  458. void Set_Display_Mode (mode)
  459.      int mode;
  460. {
  461.   if (display_mode == mode)
  462.     return;
  463.  
  464.   display_mode = mode;
  465.  
  466.   if ((mode == HELP_DISPLAY) || (mode == MANUAL_DISPLAY)) {
  467.     clear_screen ();
  468.     Suspend_Comment_Display ();
  469.     status_loc = terminal_lines;
  470.     return;
  471.   }
  472.  
  473.   if (display_mode == TALK_DISPLAY)
  474.     Select_Talk_Mode ();
  475.   else
  476.     Select_Conversation_Mode ();
  477.  
  478.   Refresh_Display ();
  479. }
  480.  
  481. void Display_Tricks_Taken ()
  482. {
  483.   sprintf (line_buf,"%5d   %5d",
  484.        Local_play->tricks[SIDE_NS], Local_play->tricks[SIDE_EW]);
  485.   print (YMIN(scores)+2,XMIN(scores)+8, line_buf);
  486. }
  487.  
  488. void Format_IMP_string (score, buf)
  489.      int score; char *buf;
  490. {
  491.   int whole, fraction;
  492.  
  493.  
  494.   if ((-95 < score) && (score < 0)) {
  495.     score = (score - 5) / 10;
  496.     sprintf (buf, " -0.%d", -score);
  497.     return;
  498.   } else if (score < 0) {
  499.     score = (score - 5) / 10;
  500.     fraction = (-score) % 10;
  501.     whole = -((-score) / 10);
  502.   } else {
  503.     score = (score + 5) / 10;
  504.     fraction = score % 10;
  505.     whole = score / 10;
  506.   }
  507.  
  508.   if (fraction == 0)
  509.     sprintf (buf, "%4d. ", whole);
  510.   else
  511.     sprintf (buf, "%4d.%d", whole, fraction);
  512. }
  513.  
  514. void Display_Above_Line_Points ()
  515. {
  516.   char ew_buf[10], ns_buf [10];
  517.  
  518.   if (Local_board->scoring_mode == IMP_SCORING) {
  519.     Format_IMP_string (Local_table->above_line[SIDE_NS], ns_buf);
  520.     Format_IMP_string (Local_table->above_line[SIDE_EW], ew_buf);
  521.     sprintf (line_buf,"%6s  %6s", ns_buf, ew_buf);
  522.   } else if (Local_board->scoring_mode == MP_SCORING) {
  523.     sprintf (line_buf, "%5.2f  %6.2f", 
  524.          ((float) Local_table->above_line[SIDE_NS]) * 0.01,
  525.          ((float) Local_table->above_line[SIDE_EW]) * 0.01);
  526.   } else
  527.     sprintf (line_buf,"%5d   %5d",
  528.          Local_table->above_line[SIDE_NS], 
  529.          Local_table->above_line[SIDE_EW]);
  530.  
  531.   print (YMIN(scores)+4,XMIN(scores)+8, line_buf);
  532. }
  533.  
  534. void Display_Below_Line_Points ()
  535. {
  536.   char ew_buf[10], ns_buf [10];
  537.  
  538.   if (Local_board->scoring_mode == IMP_SCORING) {
  539.     Format_IMP_string (Local_table->below_line[SIDE_NS], ns_buf);
  540.     Format_IMP_string (Local_table->below_line[SIDE_EW], ew_buf);
  541.     sprintf (line_buf,"%6s  %6s", ns_buf, ew_buf);
  542.   } else if (Local_board->scoring_mode == MP_SCORING) {
  543.     sprintf (line_buf, "%5.2f  %6.2f", 
  544.          ((float) Local_table->below_line[SIDE_NS]) * 0.01,
  545.          ((float) Local_table->below_line[SIDE_EW]) * 0.01);
  546.   } else
  547.     sprintf (line_buf,"%5d   %5d",
  548.          Local_table->below_line[SIDE_NS], 
  549.          Local_table->below_line[SIDE_EW]);
  550.  
  551.   print (YMIN(scores)+5,XMIN(scores)+8, line_buf);
  552. }
  553.  
  554. void Display_Vulnerabilities   ()
  555. {
  556.   char *nsv, *ewv;
  557.  
  558.   if (Local_board->vulnerable[SIDE_NS]) 
  559.     nsv = "  YES";
  560.   else
  561.     nsv = "   NO";
  562.  
  563.   if (Local_board->vulnerable[SIDE_EW]) 
  564.     ewv = "  YES";
  565.   else
  566.     ewv = "   NO";
  567.  
  568.   sprintf (line_buf, "%s   %s",nsv,ewv);
  569.   print (YMIN(scores)+3, XMIN(scores)+8, line_buf);
  570. }
  571.  
  572. void Clear_Bidding_Board ()
  573. {
  574.   int x, y, h, w;
  575.  
  576.   x = XMIN(bidding_board);
  577.   y = YMIN(bidding_board);
  578.   h = HEIGHT(bidding_board);
  579.   w = WIDTH(bidding_board);
  580.   clear_screen_area (y, x, h, w);
  581.   clear_screen_area (PLAY_ROW, 1, 1, 10);
  582.  
  583. }
  584.  
  585. void Refresh_Time_Display ()
  586. {
  587.   if ((display_mode != PLAYING_DISPLAY) && (display_mode != BIDDING_DISPLAY))
  588.     return;
  589.  
  590.   print (PLAY_ROW,   80 - strlen(total_time_buffer), total_time_buffer);
  591.   print (PLAY_ROW+1, 80 - strlen(local_time_buffer), local_time_buffer);
  592. }
  593.  
  594. void Display_Total_Time (total_buf, local_buf)
  595.      char *total_buf, *local_buf;
  596. {
  597.   sprintf (total_time_buffer, "%s", total_buf);
  598.   sprintf (local_time_buffer, "%s", local_buf);
  599.   Refresh_Time_Display ();
  600. }
  601.  
  602. void Display_Bidding_Board ()
  603. /* The bidding display is given as four columns, similar to that found
  604.    in many bridge books.  At the top of each column is printed the
  605.    corresponding input parameter string to identify the bidder. */
  606. {
  607.   char *first, *second, *third, *fourth;
  608.   
  609.   Clear_Bidding_Board ();
  610.   
  611.   first  = PLAYER_NAME(Local_table, PLAYER_NORTH);
  612.   second = PLAYER_NAME(Local_table, player_next[PLAYER_NORTH]);
  613.   third  = PLAYER_NAME(Local_table, player_partner[PLAYER_NORTH]);
  614.   fourth = PLAYER_NAME(Local_table, player_prev[PLAYER_NORTH]);
  615.   
  616.   print(YMIN(bidding_board), XMIN(bidding_board)+05, first);
  617.   print(YMIN(bidding_board), XMIN(bidding_board)+15, second);
  618.   print(YMIN(bidding_board), XMIN(bidding_board)+25, third);
  619.   print(YMIN(bidding_board), XMIN(bidding_board)+35, fourth);
  620.   
  621.   underline(YMIN(bidding_board),XMIN(bidding_board)+05,strlen(first));
  622.   underline(YMIN(bidding_board),XMIN(bidding_board)+15,strlen(second));
  623.   underline(YMIN(bidding_board),XMIN(bidding_board)+25,strlen(third));
  624.   underline(YMIN(bidding_board),XMIN(bidding_board)+35,strlen(fourth));
  625.  
  626.   Display_Board_Number ();
  627. }
  628.  
  629. static void Display_suit (y, x, cards)
  630.      int y, x; suit_type cards;
  631. /* Displays the cards in a given suit held by a player.  As input,
  632.  * cards[] is an array of 13 elements, where cards[i] is TRUE if the
  633.  * player holds the given card.  Displays the cards as a string on
  634.  * the terminal, beginning at coordinates <y,x>.
  635.  */
  636. {
  637.   int i;
  638.  
  639.   for (i = 12; i >= 0; i--)
  640.     if (cards[i])
  641.       print (y, x++, rank_names[i]);
  642. }
  643.  
  644. void Display_Hand_for_Bidding (pos, h)
  645.      int pos; hand h;
  646. {
  647.   int i, x, y;
  648.   
  649.   if (pos >= 4) return;
  650.   
  651.   y = YMIN(bidding_board);
  652.   x = XMIN(bidding_board) + 45;
  653.   clear_screen_area (y, x, HEIGHT(bidding_board), XMAX(bidding_board)-x+1);
  654.   for (i = 0; i < 6; i++)
  655.     print (y+i, x, "|");
  656.   
  657.   x+=1;
  658.   print (y, x, PLAYER_NAME(Local_table, pos));
  659.   underline (y, x, strlen(PLAYER_NAME(Local_table, pos)));
  660.   print (y+2, x, "S "); Display_suit (y+2, x+2, h+39);
  661.   print (y+3, x, "H "); Display_suit (y+3, x+2, h+26);
  662.   print (y+4, x, "D "); Display_suit (y+4, x+2, h+13);
  663.   print (y+5, x, "C "); Display_suit (y+5, x+2, h);
  664. }
  665.  
  666. void Clear_Bidder ()
  667. {
  668.   clear_screen_area (YMIN(title)+2, XMIN(title), 1, 20);
  669. }
  670.  
  671. void Display_Bidder (player)
  672.     int player;
  673. {
  674.   char bid_buf[80];
  675.  
  676.   sprintf (bid_buf, "(%c) %s's BID        ", *("NESW" + player),
  677.        PLAYER_NAME(Local_table, player));
  678.          
  679.   print (YMIN(title)+2, XMIN(title), bid_buf);
  680. }
  681.  
  682. void Display_Bid (k)
  683.      int k;
  684. /* Displays the k-th bid in the bidding list. */
  685. {
  686.   int i, x, y, bid, position, round, player;
  687.   char bid_string [10];
  688.   
  689.   round = (k / 4) + 1;
  690.   bid = Local_play->bids[k];
  691.   player = k % 4;
  692.   for (i = 0; i != Local_board->dealer; i++)
  693.     player = player_next[player];
  694.   
  695.   y = YMIN(bidding_board) + round + 1;
  696.   sprintf (line_buf, " %2d", round);
  697.   print (y, XMIN(bidding_board), line_buf);
  698.   
  699.   y++; 
  700.   for (x = Local_board->dealer; x < 4; x++)
  701.     if (x == player) y--;
  702.   
  703.   position = player;
  704.   x = XMIN(bidding_board) + 10 * position + 5;
  705.   if (bid == BID_PASS)
  706.     sprintf (bid_string, "--");
  707.   else
  708.     sprintf (bid_string, "%s", bid_names[bid]);
  709.   if (Local_play->alerts[k])
  710.     sprintf (bid_string + strlen(bid_string)," !");
  711.   
  712.   print (y, x, bid_string);
  713. }
  714.  
  715. void Display_Contract ()
  716. {
  717.   char double_buf[40], contract_buf[60];
  718.   int trump_suit = trumpsuit_of (Local_play->contract);
  719.   int contract   = level_of (Local_play->contract);
  720.  
  721.   if (Local_play->contract == BID_PASS) {
  722.     print (YMIN(title)+3, XMIN(title), "PASSED HAND");
  723.     return;
  724.   }
  725.  
  726.   clear_screen_area (YMIN(title)+2, XMIN(title), HEIGHT(title),
  727.                WIDTH(title));
  728.   if (Local_play->doubled == 2)
  729.     sprintf (double_buf,"  REDOUBLED");
  730.   else if (Local_play->doubled == 1)
  731.     sprintf (double_buf, "  DOUBLED");
  732.   else
  733.     double_buf[0] = '\0';
  734.   sprintf (contract_buf, "%1d%s (%s)%s",contract,suit_names[trump_suit],
  735.        PLAYER_NAME(Local_table, Local_play->declarer), double_buf);
  736.  
  737.   print (YMIN(title)+3, XMIN(title), contract_buf);
  738. }
  739.  
  740. void Clear_Playing_Area () 
  741. {
  742.   clear_screen_area (YMIN(playing_board), XMIN(playing_board),
  743.              HEIGHT(playing_board), WIDTH(playing_board));
  744.   clear_screen_area (YMIN(left_hand), XMIN(left_hand),
  745.              HEIGHT(left_hand), WIDTH(left_hand));
  746.   clear_screen_area (YMIN(right_hand), XMIN(right_hand),
  747.              HEIGHT(right_hand), WIDTH(right_hand));
  748.   clear_screen_area (YMIN(top_hand), XMIN(top_hand),
  749.              HEIGHT(top_hand), WIDTH(top_hand));
  750.   clear_screen_area (YMIN(bottom_hand), XMIN(bottom_hand),
  751.              HEIGHT(bottom_hand), WIDTH(bottom_hand));
  752.   clear_screen_area (YMIN(title)+3, XMIN(title), 1, WIDTH(title));
  753.   
  754. }
  755.  
  756. void Clear_Playing_Board ()
  757. {
  758.   Clear_Playing_Area ();
  759.  
  760.   Current_trick[0] = Current_trick[1] = 
  761.     Current_trick[2] = Current_trick[3] = -1;
  762. }
  763.  
  764. void Display_Playing_Board ()
  765. {
  766.   int i;
  767.   
  768.   for (i = 0; i < 4; i++)
  769.     print (PLAYERHAND_Y[i]+1, PLAYERHAND_X[i]+12 -
  770.        strlen(PLAYER_NAME(Local_table, i)), PLAYER_NAME(Local_table, i));
  771.   
  772.   for (i = 0; i < WIDTH(playing_board)-1; i++) line_buf[i] = '-';
  773.   line_buf[WIDTH(playing_board)-2] = '\0';
  774.   print (YMIN(playing_board)+1,XMIN(playing_board)+1,line_buf);
  775.   print (YMAX(playing_board)-1,XMIN(playing_board)+1,line_buf);
  776.   
  777.   for (i = YMIN(playing_board)+2; i < YMAX(playing_board)-1; i++) {
  778.     print (i, XMIN(playing_board)+1, "|");
  779.     print (i, XMAX(playing_board)-1, "|");
  780.   }
  781. }
  782.  
  783. void Display_Player (player)
  784.      int player;
  785. {
  786.   char play_buf[80];
  787.   
  788.   if (player < 0)
  789.     sprintf (play_buf, "                    ");
  790.   else if (player == player_partner[Local_play->declarer])
  791.     sprintf (play_buf, "DUMMY'S PLAY        ");
  792.   else
  793.     sprintf (play_buf, "(%c) %s's PLAY        ", 
  794.          *("NESW" + player), PLAYER_NAME(Local_table, player));
  795.   print (YMIN(title)+4, XMIN(title), play_buf);
  796. }
  797.  
  798. void Display_Play (p, card)
  799.      int p, card;
  800. {
  801.   int x, y;
  802.   
  803.   y = CARDPOS_Y [p];
  804.   x = CARDPOS_X [p];
  805.   if ((0 <= card) && (card < 52))
  806.     print (y, x, card_names[card]);
  807.   else
  808.     print (y, x, "   ");
  809.   
  810.   Current_trick [p] = card;
  811. }
  812.  
  813. void Clear_Plays  ()
  814. {
  815.   Display_Play (PLAYER_NORTH, -1);
  816.   Display_Play (PLAYER_EAST,  -1);
  817.   Display_Play (PLAYER_SOUTH, -1);
  818.   Display_Play (PLAYER_WEST,  -1);
  819. }
  820.  
  821. void Display_Partial_Hand (p, no_plays)
  822.      int p; int no_plays;
  823. {
  824.   int y, x, i;
  825.   hand h;
  826.   
  827.   if (IS_OBSERVER(p))
  828.     return;
  829.   
  830.   y = PLAYERHAND_Y [p];
  831.   x = PLAYERHAND_X [p];
  832.   for (i = 0; i < 4; i++)
  833.     print (y+i, x, "                   ");
  834.   
  835.   Generate_holdings (Local_board, Local_play->play_list, no_plays, p, h);
  836.   print (y,   x+5-8, "        ");
  837.   print (y,   x+5-strlen(PLAYER_NAME(Local_table, p)), 
  838.      PLAYER_NAME(Local_table, p));
  839.   if (p == player_partner[Local_play->declarer])
  840.     print (y+1, x+5-7, "(DUMMY)");
  841.   print (y,   x+7, "S "); Display_suit (y,   x+10, h+39);
  842.   print (y+1, x+7, "H "); Display_suit (y+1, x+10, h+26);
  843.   print (y+2, x+7, "D "); Display_suit (y+2, x+10, h+13);
  844.   print (y+3, x+7, "C "); Display_suit (y+3, x+10, h);
  845.   
  846.   revealed_hands[p] = 1;
  847. }
  848.  
  849. void Display_Hand (p)
  850.      int p;
  851. {
  852.   Display_Partial_Hand (p, Local_play->no_plays);
  853. }
  854.  
  855. void Clear_Hand (p)
  856.      int p;
  857. {
  858.   int y, x, i;
  859.   
  860.   y = PLAYERHAND_Y [p];
  861.   x = PLAYERHAND_X [p];
  862.   for (i = 0; i < 4; i++)
  863.     print (y+i, x, "                   ");
  864.   
  865.   print (y,   x+5-strlen(PLAYER_NAME(Local_table, p)), 
  866.      PLAYER_NAME(Local_table, p));
  867.   if (p == player_partner[Local_play->declarer])
  868.     print (y+1, x+5-7, "(DUMMY)");
  869.   
  870.   revealed_hands[p] = 0;
  871. }
  872.  
  873. static char *seat_letters [4] = {"N", "E", "S", "W"};
  874. static char *double_names [3] = {"", "-X", "-XX"};
  875.  
  876. static void Display_Score_Record (b, p, line)
  877.      Board *b;
  878.      Play_record *p;
  879.      int line;
  880. {
  881.   char contract_buf[10];
  882.   char buf[100];
  883.   char mark;
  884.  
  885.   if (p->contract == BID_PASS)
  886.     sprintf (contract_buf, "PASSED");
  887.   else
  888.     sprintf (contract_buf, "%s%s", bid_names[p->contract], 
  889.          double_names[p->doubled]);
  890.  
  891.   if (!strcasecmp(p->player_names[PLAYER_NORTH], local_player_name) ||
  892.       !strcasecmp(p->player_names[PLAYER_SOUTH], local_player_name))
  893.     mark = '>';
  894.   else
  895.     mark = ' ';
  896.  
  897.   sprintf (buf,
  898.        "  %c   N %-8s S %-8s %-8s %-2s %+6d %6d %6.1f %6.2f", mark,
  899.        p->player_names[PLAYER_NORTH], p->player_names[PLAYER_SOUTH],
  900.        contract_buf, seat_letters[p->declarer], p->result,
  901.        p->below_line[SIDE_NS], 
  902.        p->imatch_points[SIDE_NS],
  903.        p->match_points[SIDE_NS]);
  904.   print (line, 1, buf);
  905.  
  906.   if (!strcasecmp(p->player_names[PLAYER_EAST], local_player_name) ||
  907.       !strcasecmp(p->player_names[PLAYER_WEST], local_player_name))
  908.     mark = '>';
  909.   else
  910.     mark = ' ';
  911.  
  912.   sprintf (buf,
  913.        "  %c   E %-8s W %-8s %-8s %2s %6s %6d %6.1f %6.2f", mark,
  914.        p->player_names[PLAYER_EAST], p->player_names[PLAYER_WEST],
  915.        " ", " ", " ", p->below_line[SIDE_EW],
  916.        p->imatch_points[SIDE_EW],
  917.        p->match_points[SIDE_EW]);
  918.   print (line+1, 1, buf);
  919. }
  920.  
  921. void Display_Page_of_Scores (p)
  922.      Play_record *p;
  923. /* Displays a page of scores, starting with the play record p.  Sets the
  924.    variable Current_page_of_scores equal to p, and the variable 
  925.    Next_page_of_scores equal to the first undisplayed record.
  926. */
  927. {
  928.   char buf[100];
  929.   char *vul_string;
  930.   int line = 5;
  931.   Board *b = Board_for_display;
  932.  
  933.   clear_screen_area (1, 1, 15, 80);
  934.  
  935.   Current_page_of_scores = Next_page_of_scores = p;
  936.  
  937.   if (b->vulnerable[SIDE_NS] && b->vulnerable[SIDE_EW])
  938.     vul_string = "BOTH";
  939.   else if (b->vulnerable[SIDE_NS])
  940.     vul_string = "N-S";
  941.   else if (b->vulnerable[SIDE_EW])
  942.     vul_string = "E-W";
  943.   else
  944.     vul_string = "NONE";
  945.  
  946.   sprintf (buf, "%s BOARD %d", b->source, b->serial_no);
  947.   print (1, 78 - strlen(buf), buf);
  948.  
  949.   switch (b->scoring_mode) {
  950.   case RUBBER_SCORING:
  951.     print (1, 1, "RUBBER BRIDGE");
  952.     break;
  953.   case DUPLICATE_SCORING:
  954.     print (1, 1, "DUPLICATE BRIDGE");
  955.     break;
  956.   case MP_SCORING:
  957.     print (1, 1, "MATCH POINTS");
  958.     break;
  959.   case IMP_SCORING:
  960.     print (1, 1, "INTL MATCH POINTS");
  961.     break;
  962.   }
  963.  
  964.   sprintf (buf, "DEALER %s, VUL %s", seat_names[b->dealer], vul_string);
  965.   print (2, 1, buf);
  966.  
  967.   sprintf (buf, "%5s %21s %-8s %-2s %6s %6s %6s %6s", " ", " ",
  968.        "CONTRACT", "BY", "RESULT", "SCORE", "IMPS", "MPS");
  969.   print (4, 1, buf);
  970.  
  971.   while ((line < 15) && (Next_page_of_scores != NULL)) {
  972.     Display_Score_Record (b, Next_page_of_scores, line);
  973.     line += 3;
  974.     Next_page_of_scores = Next_page_of_scores->next;
  975.   }
  976.  
  977. }
  978.  
  979. void Display_First_Page_of_Scores (b)
  980.      Board *b;
  981. /* Initiales the scoring display and displays the first page of results from
  982.  * board b. 
  983.  */
  984. {
  985.   if ((b->play_records == NULL) || (b->play_records->next == NULL)) {
  986.     Next_page_of_scores = Current_page_of_scores = NULL;
  987.     return;
  988.   }
  989.  
  990.   Board_for_display = b;
  991.   Set_Display_Mode (SCORING_DISPLAY);
  992.   Set_Input_Mode (TALK_INPUT);
  993.  
  994.   Display_Page_of_Scores (b->play_records);
  995. }
  996.  
  997. int More_Scores_to_Display ()
  998. /* int More_Scores_to_Display (void); */
  999. /* Returns true if not all of the results have been displayed from the
  1000.  * board which is currently being displayed. 
  1001.  */
  1002. {
  1003.   return (Next_page_of_scores != NULL);
  1004. }
  1005.  
  1006. void Display_More_Scores ()
  1007. /* void Display_More_Scores (void); */
  1008. /* Displays the next page of scores for the board b. */
  1009. {
  1010.   Display_Page_of_Scores (Next_page_of_scores);
  1011. }
  1012.  
  1013.  
  1014.  
  1015. static void Save_Status_Message (message)
  1016.      char *message;
  1017. /* Saves the given message into the status display buffer at the
  1018.    current level of locking. */
  1019. {
  1020.   int i;
  1021.  
  1022.   for (i = 0; (i < WIDTH(status)) && (message[i] != '\0'); i++)
  1023.     status_buf[status_display_level][i] = message[i];
  1024.   status_buf[status_display_level][i] = '\0';
  1025. }
  1026.  
  1027. void Status (message)
  1028.      char *message;
  1029. {
  1030.   if (status_display_level > 0) {
  1031.     Moderator_Comment (message);
  1032.     return;
  1033.   }
  1034.  
  1035.   Clear_Status ();
  1036.   Save_Status_Message (message);
  1037.   Refresh_Status_Display ();
  1038. }
  1039.  
  1040. void Clear_Status ()
  1041. {
  1042.   if (status_display_level > 0)
  1043.     return;
  1044.  
  1045.   clear_screen_area (status_loc, XMIN(status), 1, WIDTH(status));
  1046.   status_buf [0][0] = '\0';
  1047. }
  1048.  
  1049. void Lock_Status (message)
  1050.      char *message;
  1051. /* Locks the status display.  This prevents the current message from being
  1052.    erased from the display.  If a new request to Status is made, that
  1053.    message is displayed as a moderator comment instead.
  1054. */
  1055. {
  1056.   status_display_level += 1;
  1057.   Save_Status_Message (message);
  1058.   Refresh_Status_Display ();
  1059. }
  1060.  
  1061. void Unlock_Status ()
  1062. /* Unlocks the status display. */
  1063. {
  1064.   if (status_display_level > 0)
  1065.     status_display_level -= 1;
  1066.   Refresh_Status_Display ();
  1067. }
  1068.  
  1069. void Reset_Status ()
  1070. /* Resets the status display. */
  1071. {
  1072.   status_display_level = 0;
  1073.   Clear_Status ();
  1074. }
  1075.  
  1076. void Refresh_Status_Display ()
  1077. {
  1078.   clear_screen_area (status_loc, XMIN(status), 1, WIDTH(status));
  1079.   print (status_loc, XMIN(status), status_buf[status_display_level]);
  1080.   set_cursor 
  1081.     (status_loc, XMIN(status) + strlen(status_buf[status_display_level]) + 1);
  1082. }
  1083.  
  1084. /* The bottom part of the screen is used for the exchange of comments
  1085.    between the players.  The following procedures are used for managing
  1086.    this part of the display. */
  1087.  
  1088.  
  1089. static void blank_out_comment (c)
  1090.      comment_line c;
  1091. {
  1092.   int i;
  1093.  
  1094.   for (i = 0; i < COMMENT_LENGTH-1; i++) c[i] = ' ';
  1095.   c[COMMENT_LENGTH-1] = '\0';
  1096. }
  1097.  
  1098. static void copy_string_to_comment (c, s)
  1099.      comment_line c; char *s;
  1100. {
  1101.   int i;
  1102.  
  1103.   blank_out_comment(c);
  1104.   i = 0;
  1105.   while ((s[i] != '\0') && (i < COMMENT_LENGTH-1)) {
  1106.     c[i] = s[i]; 
  1107.     i++; 
  1108.   }
  1109.  
  1110. }
  1111.  
  1112. static void scroll_player_comments ()
  1113. {
  1114.   int i;
  1115.  
  1116.   for (i = 0; i < playing_screen_talk_size-1; i++)
  1117.     bcopy (playing_screen_comments[i+1], playing_screen_comments[i], 
  1118.        sizeof(comment_line));
  1119.   blank_out_comment (playing_screen_comments[playing_screen_talk_size-1]);
  1120. }
  1121.  
  1122. void Select_Conversation_Mode ()
  1123. {
  1124.   talk_start = playing_screen_talk_start;
  1125.   talk_end   = playing_screen_talk_end;
  1126.   talk_size  = playing_screen_talk_size;
  1127.   player_comments = playing_screen_comments;
  1128. }
  1129.  
  1130. void Select_Talk_Mode ()
  1131. {
  1132.   talk_start = full_screen_talk_start;
  1133.   talk_end   = full_screen_talk_end;
  1134.   talk_size  = full_screen_talk_size;
  1135.   player_comments = full_screen_comments;
  1136. }
  1137.  
  1138. void Refresh_Player_Comments ()
  1139. {
  1140.   int i;
  1141.  
  1142.   if (comments_suspended)
  1143.     return;
  1144.  
  1145.   for (i = 0; i < talk_size; i++)
  1146.     print (talk_start+i, 2, player_comments[i]);
  1147. }
  1148.  
  1149. void Clear_Comment_Display ()
  1150. {
  1151.   int i;
  1152.  
  1153.   for (i = 0; i < full_screen_talk_size; i++)
  1154.     blank_out_comment (full_screen_comments + i);
  1155.   for (i = 0; i < playing_screen_talk_size; i++)
  1156.     blank_out_comment (playing_screen_comments + i);
  1157.  
  1158.   full_screen_cursor = 0;
  1159.   Refresh_Player_Comments ();
  1160. }
  1161.  
  1162. void Initialize_Player_Comments ()
  1163. {
  1164.   int i, m, n;
  1165.   
  1166.   full_screen_talk_end = terminal_lines - 3;
  1167.   playing_screen_talk_end = terminal_lines;
  1168.   
  1169.   n = full_screen_talk_end - full_screen_talk_start + 1;
  1170.   m = playing_screen_talk_end - playing_screen_talk_start + 1;
  1171.   if (n <= 0)
  1172.     n = 1;
  1173.   else if (m <= 0)
  1174.     m = 1;
  1175.   
  1176.   full_screen_comments = (comment_line *) 
  1177.     malloc (n * sizeof(comment_line));
  1178.   
  1179.   playing_screen_comments = (comment_line *)
  1180.     malloc (m * sizeof(comment_line));
  1181.   
  1182.   for (i = 0; i < n; i++)
  1183.     blank_out_comment (full_screen_comments[i]);
  1184.   for (i = 0; i < m; i++)
  1185.     blank_out_comment (playing_screen_comments[i]);
  1186.   
  1187.   full_screen_cursor = 0;
  1188.   full_screen_talk_size = n;
  1189.   playing_screen_talk_size = m;
  1190.  
  1191.   if (display_mode == TALK_DISPLAY)
  1192.     Select_Talk_Mode ();
  1193.   else
  1194.     Select_Conversation_Mode ();
  1195. }
  1196.  
  1197. void Reinitialize_Player_Comments ()
  1198. {
  1199.   Initialize_Player_Comments ();
  1200. }
  1201.  
  1202. void Display_Player_Comment (comment_level, player_name, comment)
  1203.      int comment_level; char *player_name, *comment;
  1204. {
  1205.   char message_buf [200];
  1206.   char level_id;
  1207.   
  1208.   switch (comment_level) {
  1209.   case COMMENT_PRIVATE: level_id = '-'; break;
  1210.   case COMMENT_FORMAL:  level_id = '='; break;
  1211.   case COMMENT_PUBLIC:  level_id = ':'; break;
  1212.   default:              level_id = '*';
  1213.   }
  1214.   
  1215.   sprintf (message_buf, "%s%c %s", player_name, level_id, comment);
  1216.   
  1217.   copy_string_to_comment (full_screen_comments[full_screen_cursor], 
  1218.               message_buf);
  1219.   if (full_screen_cursor < full_screen_talk_size - 1)
  1220.     full_screen_cursor++;
  1221.   else
  1222.     full_screen_cursor = 0;
  1223.   blank_out_comment (full_screen_comments[full_screen_cursor]);
  1224.  
  1225.   scroll_player_comments ();
  1226.   copy_string_to_comment 
  1227.     (playing_screen_comments[playing_screen_talk_size-1], message_buf);
  1228.  
  1229.   Refresh_Player_Comments ();
  1230. }
  1231.  
  1232. void Moderator_Comment (msg)
  1233.      char *msg;
  1234. {
  1235.   Display_Player_Comment (COMMENT_PUBLIC, "MODERATOR", msg);
  1236. }
  1237.  
  1238. void Network_Comment (msg)
  1239.      char *msg;
  1240. {
  1241.   Display_Player_Comment (COMMENT_PRIVATE, "NETWORK", msg);
  1242. }
  1243.  
  1244. void Suspend_Comment_Display ()
  1245. {
  1246.   comments_suspended = 1;
  1247. }
  1248.  
  1249. void Continue_Comment_Display ()
  1250. {
  1251.   comments_suspended = 0;
  1252. }
  1253.  
  1254.  
  1255. void Begin_full_screen_talk_mode ()
  1256. {
  1257.   int i;
  1258.  
  1259.   Select_Talk_Mode ();
  1260.   
  1261.   for (i = 0; i <= XMAX(converse); i++) line_buf[i] = '-';
  1262.   line_buf[XMAX(converse)+1] = '\0';
  1263.   print (full_screen_talk_start-1, 1, line_buf);
  1264.   line_buf[72] = '+';
  1265.   print (full_screen_talk_end+1, 1, line_buf);
  1266.   for (i = 1; i < XMAX(converse); i++) line_buf[i] = ' ';
  1267.   line_buf[0] = line_buf[XMAX(converse)] = '|';
  1268.   for (i = full_screen_talk_start; i <= full_screen_talk_end; i++)
  1269.     print (i, 1, line_buf);
  1270.   
  1271.   Refresh_Player_Comments ();
  1272.   
  1273.   /* setup the talk buffer: */
  1274.   
  1275.   print (terminal_lines-1, 1, "TALK");
  1276.   status_loc = terminal_lines;
  1277. }
  1278.  
  1279. void End_full_screen_talk_mode ()
  1280. {
  1281.   Select_Conversation_Mode ();
  1282.   status_loc = YMIN(status);
  1283.   Refresh_Display ();
  1284. }
  1285.