home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume14
/
okbridge2
/
part06
/
display.c
< prev
Wrap
C/C++ Source or Header
|
1993-01-27
|
34KB
|
1,287 lines
/* display.c -- Display functions for OKbridge program.
*
! Copyright (C) 1990-1992 by Matthew Clegg. All Rights Reserved
!
! OKbridge is made available as a free service to the Internet.
! Accordingly, the following restrictions are placed on its use:
!
! 1. OKbridge may not be modified in any way without the explicit
! permission of Matthew Clegg.
!
! 2. OKbridge may not be used in any way for commercial advantage.
! It may not be placed on for-profit networks or on for-profit
! computer systems. It may not be bundled as part of a package
! or service provided by a for-profit organization.
!
! If you have questions about restrictions on the use of OKbridge,
! write to mclegg@cs.ucsd.edu.
!
! DISCLAIMER: The user of OKbridge accepts full responsibility for any
! damage which may be caused by OKbridge.
*
*/
#include <stdio.h>
#include <string.h>
extern char *malloc ();
#define _DISPLAY_
#include "state.h"
#include "terminal.h"
#include "display.h"
#include "help.h"
#include "input.h"
#ifdef LOGFILE
extern FILE *net_log;
#endif
typedef int window[4];
/* Conceptually, we think of the screen as being divided into a number
of windows, where each window describes one particular type of activity
or aspect of the game. Therefore, we make the following definitions,
although these are only guidelines for operation of the display.
Name of
Window Ymin Xmin Height Width
------- ---- ---- ---- ---- */
window title = { 1, 1, 6, 25};
window top_hand = { 2, 30, 4, 26};
window scores = { 1, 58, 6, 26};
window left_hand = { 8, 6, 6, 18};
window playing_board = { 5, 27, 9, 26};
window bidding_board = { 5, 1, 9, 57};
window right_hand = { 8, 56, 6, 23};
window input = { 13, 1, 6, 26};
window status = { 18, 1, 1, 79};
window bottom_hand = { 13, 30, 4, 26};
window help = { 13, 53, 6, 26};
window converse = { 19, 1, 6, 78};
#define XMIN(w) w[1]
#define YMIN(w) w[0]
#define XMAX(w) (w[1] + w[3] - 1)
#define YMAX(w) (w[0] + w[2] - 1)
#define HEIGHT(w) w[2]
#define WIDTH(w) w[3]
static int PLAYERHAND_X [4];
static int PLAYERHAND_Y [4];
static int CARDPOS_X [4];
static int CARDPOS_Y [4];
static char *position_names [4];
static int comments_suspended = 0;
static char line_buf [81];
static int status_loc;
#define COMMENT_LENGTH 78
typedef char comment_line [COMMENT_LENGTH];
typedef comment_line *comment_buf;
static int full_screen_talk_start = 3;
/* The first line of the screen on which comments will be displayed,
if the full screen is used for talking. */
static int full_screen_talk_end = 22;
/* The last line on which comments will be displayed for full screen mode. */
static int full_screen_talk_size = 20;
/* The total number of lines in the full screen talk display. */
static int full_screen_cursor = 0;
/* The line in the full screen buffer where the next talk message will be
displayed. */
static int playing_screen_talk_start = 20;
/* The first line of the screen on which comments will be displayed,
if we are in playing mode. */
static int playing_screen_talk_end = 24;
/* last comment line for playing screen. */
static int playing_screen_talk_size = 5;
/* The total number of lines in the playing screen talk display. */
static int talk_start, talk_end;
/* The current first and last lines for display of player comments. */
static int talk_size;
/* talk_end - talk_start + 1. */
static comment_line *full_screen_comments = NULL,
*playing_screen_comments = NULL,
*player_comments;
/* We record the list of cards played in the current trick, so that
we can redisplay them during a refresh if necessary. */
static int Current_trick [4];
/* A list of plays indexed by position. If the value is non-negative,
then it indicates the play made by the corresponding player. */
static int status_display_level = 0;
/* The number of locks which have been placed on the status display. */
static char status_buf [10] [80];
/* For each lock level, a record of the status message at that level. */
Board *Board_for_display;
/* This is a pointer to the board which is being displayed in the
SCORING_DISPLAY mode. */
Play_record *Current_page_of_scores = NULL;
/* The first play record which is being displayed on the current page
of scores. */
Play_record *Next_page_of_scores = NULL;
/* The first play record which will be displayed on the next page
of scores. */
char total_time_buffer [20];
/* A buffer used for displaying the total time playing the current hand. */
char local_time_buffer [20];
/* A buffer used for displaying the time used by the local player. */
void Select_Talk_Mode ();
void Select_Conversation_Mode ();
void Display_Page_of_Scores ();
void Refresh_Time_Display ();
static void underline (ymin, xmin, length)
int ymin, xmin, length;
/* Prints a line of hyphens BELOW the field beginning at (ymin,xmin),
* of given length.
*/
{
int i;
for (i = 0; i < length; i++)
line_buf[i] = '-';
line_buf[length] = '\0';
print (ymin+1, xmin, line_buf);
}
static void clear_screen_area (ymin, xmin, height, width)
int ymin, xmin, height, width;
{
int i;
for (i = 0; i < width; i++) line_buf[i] = ' ';
line_buf[width] = '\0';
for (i = 0; i < height; i++) print (ymin+i, xmin, line_buf);
}
static void Display_Board_Number ()
{
if ((Local_board != NULL) && (Local_board->source != NULL)) {
sprintf (line_buf, "%s BOARD %d", Local_board->source,
Local_board->serial_no);
print (YMIN(title)+1, XMIN(title), line_buf);
} else {
sprintf (line_buf, "%d", hands_played);
print (YMIN(title)+1, XMIN(title)+6, line_buf);
}
}
static void Redraw_Scoring_Panel ()
/* Redraws the scoring panel in the upper corner of the screen, which
displays the vulnerabilities, number of tricks taken, and scores.
*/
{
/* Setup the scoreboard: */
if (local_player >= 4) {
print (YMIN(scores), XMIN(scores) + 8, " N-S");
print (YMIN(scores), XMIN(scores) + 16, " E-W");
} else if (side_of(local_player) == SIDE_NS) {
print (YMIN(scores), XMIN(scores) + 8, " WE");
print (YMIN(scores), XMIN(scores) + 16, " THEY");
} else {
print (YMIN(scores), XMIN(scores) + 16, " WE");
print (YMIN(scores), XMIN(scores) + 8, " THEY");
}
underline (YMIN(scores), XMIN(scores) + 8, 5);
underline (YMIN(scores), XMIN(scores) + 16, 5);
print (YMIN(scores)+2, XMIN(scores), "TRICKS");
print (YMIN(scores)+3, XMIN(scores), "VUL");
switch (Local_board->scoring_mode) {
case RUBBER_SCORING:
print (YMIN(scores)+4, XMIN(scores), "ABOVE");
print (YMIN(scores)+5, XMIN(scores), "BELOW");
print (YMIN(title)+1, XMIN(title), "HAND");
break;
case DUPLICATE_SCORING:
print (YMIN(scores)+4, XMIN(scores), "TOTAL");
print (YMIN(scores)+5, XMIN(scores), "PREV");
print (YMIN(title)+1, XMIN(title), "BOARD");
break;
case IMP_SCORING:
print (YMIN(scores)+4, XMIN(scores), "TOTAL");
print (YMIN(scores)+5, XMIN(scores), "IMP");
print (YMIN(title)+1, XMIN(title), "BOARD");
break;
case MP_SCORING:
print (YMIN(scores)+4, XMIN(scores), "TOTAL");
print (YMIN(scores)+5, XMIN(scores), "MP");
print (YMIN(title)+1, XMIN(title), "BOARD");
break;
default:
break;
}
Display_Tricks_Taken ();
Display_Above_Line_Points ();
Display_Below_Line_Points ();
Display_Vulnerabilities ();
Display_Board_Number ();
}
static void Redraw_Conversation_Area ()
{
int i;
/* Setup the conversational area: */
for (i = 0; i <= XMAX(converse); i++) line_buf[i] = '-';
line_buf[72] = '+';
line_buf[XMAX(converse)+1] = '\0';
print (YMIN(converse), XMIN(converse), line_buf);
for (i = talk_start; i <= talk_end; i++) {
print (i, XMIN(converse), "|");
print (i, XMAX(converse)+1, "|");
}
/* Setup the input area: */
print (TALK_ROW, TALK_COL, "TALK");
status_loc = YMIN(status);
}
static void Redraw_Bidding_Display ()
{
int i, p;
hand h;
Display_Bidding_Board ();
if (IS_PLAYER(local_player)) {
Generate_holdings (Local_board, Local_play->play_list, 0, local_player, h);
Display_Hand_for_Bidding (local_player, h);
} else if (spectator_mode) {
Generate_holdings (Local_board, Local_play->play_list, 0,
revealed_bidder, h);
Display_Hand_for_Bidding (revealed_bidder, h);
}
p = Local_board->dealer;
for (i = 0; i < Local_play->no_bids; i++) {
Display_Bid (i);
p = player_next [p];
}
Display_Bidder (p);
Refresh_Time_Display ();
print (PLAY_ROW, PLAY_COL, "BID ");
}
static void Redraw_Playing_Display ()
{
int i;
Display_Contract ();
Display_Playing_Board ();
for (i = 0; i < 4; i++)
if (revealed_hands[i]) {
if (Local_table->game_mode == PLAYING_MODE)
Display_Hand(i);
else
Display_Partial_Hand (i, 0);
}
for (i = 0; i < 4; i++)
Display_Play (i, Current_trick[i]);
Display_Player (Local_play->next_player);
Refresh_Time_Display ();
print (PLAY_ROW, PLAY_COL, "PLAY");
}
static void Redraw_Scoring_Display ()
{
Display_Page_of_Scores (Current_page_of_scores);
}
void Display_Player_Position ()
{
char buf[80], *position_name;
if (IS_PLAYER(local_player))
position_name = seat_names[local_player];
else if (spectator_mode)
position_name = "SPECTATOR";
else
position_name = "OBSERVER";
sprintf (buf, "OKBRIDGE %s%s %s ",
major_revision_level, minor_revision_level, position_name);
print (1, 1, buf);
}
void Refresh_Status_Display ();
void Begin_full_screen_talk_mode ();
void Recompute_Display_Positions ();
void Reset_Display ()
/* Redraws the main features of the screen. Used in the process
* of doing a 'refresh'.
*/
{
if (display_mode == MANUAL_DISPLAY)
return;
clear_screen ();
Recompute_Display_Positions ();
if (display_mode == HELP_DISPLAY) {
Suspend_Comment_Display ();
status_loc = terminal_lines;
display_topics ("LIST OF HELP TOPICS");
print (terminal_lines-1, 1, "HELP");
Refresh_Status_Display ();
return;
}
Display_Player_Position ();
Continue_Comment_Display ();
switch (display_mode) {
case TALK_DISPLAY:
Begin_full_screen_talk_mode ();
break;
case BIDDING_DISPLAY:
Redraw_Bidding_Display ();
Redraw_Scoring_Panel ();
Redraw_Conversation_Area ();
break;
case PLAYING_DISPLAY:
Redraw_Playing_Display ();
Redraw_Scoring_Panel ();
Redraw_Conversation_Area ();
break;
case SCORING_DISPLAY:
Redraw_Scoring_Display ();
Redraw_Conversation_Area ();
break;
}
Refresh_Player_Comments ();
Refresh_Status_Display ();
}
void Recompute_Display_Positions ()
/* Recomputes a number of internal constants for the display. */
{
int l = local_player;
if (l >= 4) l = PLAYER_SOUTH;
PLAYERHAND_X [l] = XMIN(bottom_hand);
PLAYERHAND_Y [l] = YMIN(bottom_hand);
PLAYERHAND_X [player_next[l]] = XMIN(left_hand);
PLAYERHAND_Y [player_next[l]] = YMIN(left_hand);
PLAYERHAND_X [player_partner[l]] = XMIN(top_hand);
PLAYERHAND_Y [player_partner[l]] = YMIN(top_hand);
PLAYERHAND_X [player_prev[l]] = XMIN(right_hand);
PLAYERHAND_Y [player_prev[l]] = YMIN(right_hand);
CARDPOS_Y[l] = YMAX(playing_board) - 2;
CARDPOS_X[l] = (XMAX(playing_board) +
XMIN(playing_board))/2;
CARDPOS_Y[player_next[l]] = (YMAX(playing_board) +
YMIN(playing_board))/2;
CARDPOS_X[player_next[l]] = XMIN(playing_board) + 3;
CARDPOS_Y[player_partner[l]] = YMIN(playing_board) + 2;
CARDPOS_X[player_partner[l]] = (XMAX(playing_board) +
XMIN(playing_board))/2;
CARDPOS_Y[player_prev[l]] = (YMAX(playing_board) +
YMIN(playing_board))/2;
CARDPOS_X[player_prev[l]] = XMAX(playing_board) - 4;
position_names[0] = PLAYER_NAME(Local_table, l);
position_names[1] = PLAYER_NAME(Local_table, player_next[l]);
position_names[2] = PLAYER_NAME(Local_table, player_partner[l]);
position_names[3] = PLAYER_NAME(Local_table, player_prev[l]);
}
void Initialize_Display ()
/* Should be called once when the program starts up. */
{
Initialize_Player_Comments ();
status_buf[0][0] = '\0';
display_mode = TALK_DISPLAY;
Current_trick[0] = Current_trick[1] =
Current_trick[2] = Current_trick[3] = -1;
Reset_Display ();
Recompute_Display_Positions ();
}
void Reinitialize_Display ()
{
Reinitialize_Player_Comments ();
Reset_Display ();
Recompute_Display_Positions ();
}
void Refresh_Display ()
/* Resets the terminal display and redraws everything. */
{
Reset_Display ();
}
void Clear_Playing_Area ();
void Refresh_Player_Names ()
/* Redraws the player names. Useful in case one of the players has changed
position. */
{
if ((display_mode != BIDDING_DISPLAY) && (display_mode != PLAYING_DISPLAY))
return;
if (display_mode == BIDDING_DISPLAY) {
Clear_Bidding_Board ();
Redraw_Bidding_Display ();
} else {
Clear_Playing_Area ();
Redraw_Playing_Display ();
}
}
void Set_Display_Mode (mode)
int mode;
{
if (display_mode == mode)
return;
display_mode = mode;
if ((mode == HELP_DISPLAY) || (mode == MANUAL_DISPLAY)) {
clear_screen ();
Suspend_Comment_Display ();
status_loc = terminal_lines;
return;
}
if (display_mode == TALK_DISPLAY)
Select_Talk_Mode ();
else
Select_Conversation_Mode ();
Refresh_Display ();
}
void Display_Tricks_Taken ()
{
sprintf (line_buf,"%5d %5d",
Local_play->tricks[SIDE_NS], Local_play->tricks[SIDE_EW]);
print (YMIN(scores)+2,XMIN(scores)+8, line_buf);
}
void Format_IMP_string (score, buf)
int score; char *buf;
{
int whole, fraction;
if ((-95 < score) && (score < 0)) {
score = (score - 5) / 10;
sprintf (buf, " -0.%d", -score);
return;
} else if (score < 0) {
score = (score - 5) / 10;
fraction = (-score) % 10;
whole = -((-score) / 10);
} else {
score = (score + 5) / 10;
fraction = score % 10;
whole = score / 10;
}
if (fraction == 0)
sprintf (buf, "%4d. ", whole);
else
sprintf (buf, "%4d.%d", whole, fraction);
}
void Display_Above_Line_Points ()
{
char ew_buf[10], ns_buf [10];
if (Local_board->scoring_mode == IMP_SCORING) {
Format_IMP_string (Local_table->above_line[SIDE_NS], ns_buf);
Format_IMP_string (Local_table->above_line[SIDE_EW], ew_buf);
sprintf (line_buf,"%6s %6s", ns_buf, ew_buf);
} else if (Local_board->scoring_mode == MP_SCORING) {
sprintf (line_buf, "%5.2f %6.2f",
((float) Local_table->above_line[SIDE_NS]) * 0.01,
((float) Local_table->above_line[SIDE_EW]) * 0.01);
} else
sprintf (line_buf,"%5d %5d",
Local_table->above_line[SIDE_NS],
Local_table->above_line[SIDE_EW]);
print (YMIN(scores)+4,XMIN(scores)+8, line_buf);
}
void Display_Below_Line_Points ()
{
char ew_buf[10], ns_buf [10];
if (Local_board->scoring_mode == IMP_SCORING) {
Format_IMP_string (Local_table->below_line[SIDE_NS], ns_buf);
Format_IMP_string (Local_table->below_line[SIDE_EW], ew_buf);
sprintf (line_buf,"%6s %6s", ns_buf, ew_buf);
} else if (Local_board->scoring_mode == MP_SCORING) {
sprintf (line_buf, "%5.2f %6.2f",
((float) Local_table->below_line[SIDE_NS]) * 0.01,
((float) Local_table->below_line[SIDE_EW]) * 0.01);
} else
sprintf (line_buf,"%5d %5d",
Local_table->below_line[SIDE_NS],
Local_table->below_line[SIDE_EW]);
print (YMIN(scores)+5,XMIN(scores)+8, line_buf);
}
void Display_Vulnerabilities ()
{
char *nsv, *ewv;
if (Local_board->vulnerable[SIDE_NS])
nsv = " YES";
else
nsv = " NO";
if (Local_board->vulnerable[SIDE_EW])
ewv = " YES";
else
ewv = " NO";
sprintf (line_buf, "%s %s",nsv,ewv);
print (YMIN(scores)+3, XMIN(scores)+8, line_buf);
}
void Clear_Bidding_Board ()
{
int x, y, h, w;
x = XMIN(bidding_board);
y = YMIN(bidding_board);
h = HEIGHT(bidding_board);
w = WIDTH(bidding_board);
clear_screen_area (y, x, h, w);
clear_screen_area (PLAY_ROW, 1, 1, 10);
}
void Refresh_Time_Display ()
{
if ((display_mode != PLAYING_DISPLAY) && (display_mode != BIDDING_DISPLAY))
return;
print (PLAY_ROW, 80 - strlen(total_time_buffer), total_time_buffer);
print (PLAY_ROW+1, 80 - strlen(local_time_buffer), local_time_buffer);
}
void Display_Total_Time (total_buf, local_buf)
char *total_buf, *local_buf;
{
sprintf (total_time_buffer, "%s", total_buf);
sprintf (local_time_buffer, "%s", local_buf);
Refresh_Time_Display ();
}
void Display_Bidding_Board ()
/* The bidding display is given as four columns, similar to that found
in many bridge books. At the top of each column is printed the
corresponding input parameter string to identify the bidder. */
{
char *first, *second, *third, *fourth;
Clear_Bidding_Board ();
first = PLAYER_NAME(Local_table, PLAYER_NORTH);
second = PLAYER_NAME(Local_table, player_next[PLAYER_NORTH]);
third = PLAYER_NAME(Local_table, player_partner[PLAYER_NORTH]);
fourth = PLAYER_NAME(Local_table, player_prev[PLAYER_NORTH]);
print(YMIN(bidding_board), XMIN(bidding_board)+05, first);
print(YMIN(bidding_board), XMIN(bidding_board)+15, second);
print(YMIN(bidding_board), XMIN(bidding_board)+25, third);
print(YMIN(bidding_board), XMIN(bidding_board)+35, fourth);
underline(YMIN(bidding_board),XMIN(bidding_board)+05,strlen(first));
underline(YMIN(bidding_board),XMIN(bidding_board)+15,strlen(second));
underline(YMIN(bidding_board),XMIN(bidding_board)+25,strlen(third));
underline(YMIN(bidding_board),XMIN(bidding_board)+35,strlen(fourth));
Display_Board_Number ();
}
static void Display_suit (y, x, cards)
int y, x; suit_type cards;
/* Displays the cards in a given suit held by a player. As input,
* cards[] is an array of 13 elements, where cards[i] is TRUE if the
* player holds the given card. Displays the cards as a string on
* the terminal, beginning at coordinates <y,x>.
*/
{
int i;
for (i = 12; i >= 0; i--)
if (cards[i])
print (y, x++, rank_names[i]);
}
void Display_Hand_for_Bidding (pos, h)
int pos; hand h;
{
int i, x, y;
if (pos >= 4) return;
y = YMIN(bidding_board);
x = XMIN(bidding_board) + 45;
clear_screen_area (y, x, HEIGHT(bidding_board), XMAX(bidding_board)-x+1);
for (i = 0; i < 6; i++)
print (y+i, x, "|");
x+=1;
print (y, x, PLAYER_NAME(Local_table, pos));
underline (y, x, strlen(PLAYER_NAME(Local_table, pos)));
print (y+2, x, "S "); Display_suit (y+2, x+2, h+39);
print (y+3, x, "H "); Display_suit (y+3, x+2, h+26);
print (y+4, x, "D "); Display_suit (y+4, x+2, h+13);
print (y+5, x, "C "); Display_suit (y+5, x+2, h);
}
void Clear_Bidder ()
{
clear_screen_area (YMIN(title)+2, XMIN(title), 1, 20);
}
void Display_Bidder (player)
int player;
{
char bid_buf[80];
sprintf (bid_buf, "(%c) %s's BID ", *("NESW" + player),
PLAYER_NAME(Local_table, player));
print (YMIN(title)+2, XMIN(title), bid_buf);
}
void Display_Bid (k)
int k;
/* Displays the k-th bid in the bidding list. */
{
int i, x, y, bid, position, round, player;
char bid_string [10];
round = (k / 4) + 1;
bid = Local_play->bids[k];
player = k % 4;
for (i = 0; i != Local_board->dealer; i++)
player = player_next[player];
y = YMIN(bidding_board) + round + 1;
sprintf (line_buf, " %2d", round);
print (y, XMIN(bidding_board), line_buf);
y++;
for (x = Local_board->dealer; x < 4; x++)
if (x == player) y--;
position = player;
x = XMIN(bidding_board) + 10 * position + 5;
if (bid == BID_PASS)
sprintf (bid_string, "--");
else
sprintf (bid_string, "%s", bid_names[bid]);
if (Local_play->alerts[k])
sprintf (bid_string + strlen(bid_string)," !");
print (y, x, bid_string);
}
void Display_Contract ()
{
char double_buf[40], contract_buf[60];
int trump_suit = trumpsuit_of (Local_play->contract);
int contract = level_of (Local_play->contract);
if (Local_play->contract == BID_PASS) {
print (YMIN(title)+3, XMIN(title), "PASSED HAND");
return;
}
clear_screen_area (YMIN(title)+2, XMIN(title), HEIGHT(title),
WIDTH(title));
if (Local_play->doubled == 2)
sprintf (double_buf," REDOUBLED");
else if (Local_play->doubled == 1)
sprintf (double_buf, " DOUBLED");
else
double_buf[0] = '\0';
sprintf (contract_buf, "%1d%s (%s)%s",contract,suit_names[trump_suit],
PLAYER_NAME(Local_table, Local_play->declarer), double_buf);
print (YMIN(title)+3, XMIN(title), contract_buf);
}
void Clear_Playing_Area ()
{
clear_screen_area (YMIN(playing_board), XMIN(playing_board),
HEIGHT(playing_board), WIDTH(playing_board));
clear_screen_area (YMIN(left_hand), XMIN(left_hand),
HEIGHT(left_hand), WIDTH(left_hand));
clear_screen_area (YMIN(right_hand), XMIN(right_hand),
HEIGHT(right_hand), WIDTH(right_hand));
clear_screen_area (YMIN(top_hand), XMIN(top_hand),
HEIGHT(top_hand), WIDTH(top_hand));
clear_screen_area (YMIN(bottom_hand), XMIN(bottom_hand),
HEIGHT(bottom_hand), WIDTH(bottom_hand));
clear_screen_area (YMIN(title)+3, XMIN(title), 1, WIDTH(title));
}
void Clear_Playing_Board ()
{
Clear_Playing_Area ();
Current_trick[0] = Current_trick[1] =
Current_trick[2] = Current_trick[3] = -1;
}
void Display_Playing_Board ()
{
int i;
for (i = 0; i < 4; i++)
print (PLAYERHAND_Y[i]+1, PLAYERHAND_X[i]+12 -
strlen(PLAYER_NAME(Local_table, i)), PLAYER_NAME(Local_table, i));
for (i = 0; i < WIDTH(playing_board)-1; i++) line_buf[i] = '-';
line_buf[WIDTH(playing_board)-2] = '\0';
print (YMIN(playing_board)+1,XMIN(playing_board)+1,line_buf);
print (YMAX(playing_board)-1,XMIN(playing_board)+1,line_buf);
for (i = YMIN(playing_board)+2; i < YMAX(playing_board)-1; i++) {
print (i, XMIN(playing_board)+1, "|");
print (i, XMAX(playing_board)-1, "|");
}
}
void Display_Player (player)
int player;
{
char play_buf[80];
if (player < 0)
sprintf (play_buf, " ");
else if (player == player_partner[Local_play->declarer])
sprintf (play_buf, "DUMMY'S PLAY ");
else
sprintf (play_buf, "(%c) %s's PLAY ",
*("NESW" + player), PLAYER_NAME(Local_table, player));
print (YMIN(title)+4, XMIN(title), play_buf);
}
void Display_Play (p, card)
int p, card;
{
int x, y;
y = CARDPOS_Y [p];
x = CARDPOS_X [p];
if ((0 <= card) && (card < 52))
print (y, x, card_names[card]);
else
print (y, x, " ");
Current_trick [p] = card;
}
void Clear_Plays ()
{
Display_Play (PLAYER_NORTH, -1);
Display_Play (PLAYER_EAST, -1);
Display_Play (PLAYER_SOUTH, -1);
Display_Play (PLAYER_WEST, -1);
}
void Display_Partial_Hand (p, no_plays)
int p; int no_plays;
{
int y, x, i;
hand h;
if (IS_OBSERVER(p))
return;
y = PLAYERHAND_Y [p];
x = PLAYERHAND_X [p];
for (i = 0; i < 4; i++)
print (y+i, x, " ");
Generate_holdings (Local_board, Local_play->play_list, no_plays, p, h);
print (y, x+5-8, " ");
print (y, x+5-strlen(PLAYER_NAME(Local_table, p)),
PLAYER_NAME(Local_table, p));
if (p == player_partner[Local_play->declarer])
print (y+1, x+5-7, "(DUMMY)");
print (y, x+7, "S "); Display_suit (y, x+10, h+39);
print (y+1, x+7, "H "); Display_suit (y+1, x+10, h+26);
print (y+2, x+7, "D "); Display_suit (y+2, x+10, h+13);
print (y+3, x+7, "C "); Display_suit (y+3, x+10, h);
revealed_hands[p] = 1;
}
void Display_Hand (p)
int p;
{
Display_Partial_Hand (p, Local_play->no_plays);
}
void Clear_Hand (p)
int p;
{
int y, x, i;
y = PLAYERHAND_Y [p];
x = PLAYERHAND_X [p];
for (i = 0; i < 4; i++)
print (y+i, x, " ");
print (y, x+5-strlen(PLAYER_NAME(Local_table, p)),
PLAYER_NAME(Local_table, p));
if (p == player_partner[Local_play->declarer])
print (y+1, x+5-7, "(DUMMY)");
revealed_hands[p] = 0;
}
static char *seat_letters [4] = {"N", "E", "S", "W"};
static char *double_names [3] = {"", "-X", "-XX"};
static void Display_Score_Record (b, p, line)
Board *b;
Play_record *p;
int line;
{
char contract_buf[10];
char buf[100];
char mark;
if (p->contract == BID_PASS)
sprintf (contract_buf, "PASSED");
else
sprintf (contract_buf, "%s%s", bid_names[p->contract],
double_names[p->doubled]);
if (!strcasecmp(p->player_names[PLAYER_NORTH], local_player_name) ||
!strcasecmp(p->player_names[PLAYER_SOUTH], local_player_name))
mark = '>';
else
mark = ' ';
sprintf (buf,
" %c N %-8s S %-8s %-8s %-2s %+6d %6d %6.1f %6.2f", mark,
p->player_names[PLAYER_NORTH], p->player_names[PLAYER_SOUTH],
contract_buf, seat_letters[p->declarer], p->result,
p->below_line[SIDE_NS],
p->imatch_points[SIDE_NS],
p->match_points[SIDE_NS]);
print (line, 1, buf);
if (!strcasecmp(p->player_names[PLAYER_EAST], local_player_name) ||
!strcasecmp(p->player_names[PLAYER_WEST], local_player_name))
mark = '>';
else
mark = ' ';
sprintf (buf,
" %c E %-8s W %-8s %-8s %2s %6s %6d %6.1f %6.2f", mark,
p->player_names[PLAYER_EAST], p->player_names[PLAYER_WEST],
" ", " ", " ", p->below_line[SIDE_EW],
p->imatch_points[SIDE_EW],
p->match_points[SIDE_EW]);
print (line+1, 1, buf);
}
void Display_Page_of_Scores (p)
Play_record *p;
/* Displays a page of scores, starting with the play record p. Sets the
variable Current_page_of_scores equal to p, and the variable
Next_page_of_scores equal to the first undisplayed record.
*/
{
char buf[100];
char *vul_string;
int line = 5;
Board *b = Board_for_display;
clear_screen_area (1, 1, 15, 80);
Current_page_of_scores = Next_page_of_scores = p;
if (b->vulnerable[SIDE_NS] && b->vulnerable[SIDE_EW])
vul_string = "BOTH";
else if (b->vulnerable[SIDE_NS])
vul_string = "N-S";
else if (b->vulnerable[SIDE_EW])
vul_string = "E-W";
else
vul_string = "NONE";
sprintf (buf, "%s BOARD %d", b->source, b->serial_no);
print (1, 78 - strlen(buf), buf);
switch (b->scoring_mode) {
case RUBBER_SCORING:
print (1, 1, "RUBBER BRIDGE");
break;
case DUPLICATE_SCORING:
print (1, 1, "DUPLICATE BRIDGE");
break;
case MP_SCORING:
print (1, 1, "MATCH POINTS");
break;
case IMP_SCORING:
print (1, 1, "INTL MATCH POINTS");
break;
}
sprintf (buf, "DEALER %s, VUL %s", seat_names[b->dealer], vul_string);
print (2, 1, buf);
sprintf (buf, "%5s %21s %-8s %-2s %6s %6s %6s %6s", " ", " ",
"CONTRACT", "BY", "RESULT", "SCORE", "IMPS", "MPS");
print (4, 1, buf);
while ((line < 15) && (Next_page_of_scores != NULL)) {
Display_Score_Record (b, Next_page_of_scores, line);
line += 3;
Next_page_of_scores = Next_page_of_scores->next;
}
}
void Display_First_Page_of_Scores (b)
Board *b;
/* Initiales the scoring display and displays the first page of results from
* board b.
*/
{
if ((b->play_records == NULL) || (b->play_records->next == NULL)) {
Next_page_of_scores = Current_page_of_scores = NULL;
return;
}
Board_for_display = b;
Set_Display_Mode (SCORING_DISPLAY);
Set_Input_Mode (TALK_INPUT);
Display_Page_of_Scores (b->play_records);
}
int More_Scores_to_Display ()
/* int More_Scores_to_Display (void); */
/* Returns true if not all of the results have been displayed from the
* board which is currently being displayed.
*/
{
return (Next_page_of_scores != NULL);
}
void Display_More_Scores ()
/* void Display_More_Scores (void); */
/* Displays the next page of scores for the board b. */
{
Display_Page_of_Scores (Next_page_of_scores);
}
static void Save_Status_Message (message)
char *message;
/* Saves the given message into the status display buffer at the
current level of locking. */
{
int i;
for (i = 0; (i < WIDTH(status)) && (message[i] != '\0'); i++)
status_buf[status_display_level][i] = message[i];
status_buf[status_display_level][i] = '\0';
}
void Status (message)
char *message;
{
if (status_display_level > 0) {
Moderator_Comment (message);
return;
}
Clear_Status ();
Save_Status_Message (message);
Refresh_Status_Display ();
}
void Clear_Status ()
{
if (status_display_level > 0)
return;
clear_screen_area (status_loc, XMIN(status), 1, WIDTH(status));
status_buf [0][0] = '\0';
}
void Lock_Status (message)
char *message;
/* Locks the status display. This prevents the current message from being
erased from the display. If a new request to Status is made, that
message is displayed as a moderator comment instead.
*/
{
status_display_level += 1;
Save_Status_Message (message);
Refresh_Status_Display ();
}
void Unlock_Status ()
/* Unlocks the status display. */
{
if (status_display_level > 0)
status_display_level -= 1;
Refresh_Status_Display ();
}
void Reset_Status ()
/* Resets the status display. */
{
status_display_level = 0;
Clear_Status ();
}
void Refresh_Status_Display ()
{
clear_screen_area (status_loc, XMIN(status), 1, WIDTH(status));
print (status_loc, XMIN(status), status_buf[status_display_level]);
set_cursor
(status_loc, XMIN(status) + strlen(status_buf[status_display_level]) + 1);
}
/* The bottom part of the screen is used for the exchange of comments
between the players. The following procedures are used for managing
this part of the display. */
static void blank_out_comment (c)
comment_line c;
{
int i;
for (i = 0; i < COMMENT_LENGTH-1; i++) c[i] = ' ';
c[COMMENT_LENGTH-1] = '\0';
}
static void copy_string_to_comment (c, s)
comment_line c; char *s;
{
int i;
blank_out_comment(c);
i = 0;
while ((s[i] != '\0') && (i < COMMENT_LENGTH-1)) {
c[i] = s[i];
i++;
}
}
static void scroll_player_comments ()
{
int i;
for (i = 0; i < playing_screen_talk_size-1; i++)
bcopy (playing_screen_comments[i+1], playing_screen_comments[i],
sizeof(comment_line));
blank_out_comment (playing_screen_comments[playing_screen_talk_size-1]);
}
void Select_Conversation_Mode ()
{
talk_start = playing_screen_talk_start;
talk_end = playing_screen_talk_end;
talk_size = playing_screen_talk_size;
player_comments = playing_screen_comments;
}
void Select_Talk_Mode ()
{
talk_start = full_screen_talk_start;
talk_end = full_screen_talk_end;
talk_size = full_screen_talk_size;
player_comments = full_screen_comments;
}
void Refresh_Player_Comments ()
{
int i;
if (comments_suspended)
return;
for (i = 0; i < talk_size; i++)
print (talk_start+i, 2, player_comments[i]);
}
void Clear_Comment_Display ()
{
int i;
for (i = 0; i < full_screen_talk_size; i++)
blank_out_comment (full_screen_comments + i);
for (i = 0; i < playing_screen_talk_size; i++)
blank_out_comment (playing_screen_comments + i);
full_screen_cursor = 0;
Refresh_Player_Comments ();
}
void Initialize_Player_Comments ()
{
int i, m, n;
full_screen_talk_end = terminal_lines - 3;
playing_screen_talk_end = terminal_lines;
n = full_screen_talk_end - full_screen_talk_start + 1;
m = playing_screen_talk_end - playing_screen_talk_start + 1;
if (n <= 0)
n = 1;
else if (m <= 0)
m = 1;
full_screen_comments = (comment_line *)
malloc (n * sizeof(comment_line));
playing_screen_comments = (comment_line *)
malloc (m * sizeof(comment_line));
for (i = 0; i < n; i++)
blank_out_comment (full_screen_comments[i]);
for (i = 0; i < m; i++)
blank_out_comment (playing_screen_comments[i]);
full_screen_cursor = 0;
full_screen_talk_size = n;
playing_screen_talk_size = m;
if (display_mode == TALK_DISPLAY)
Select_Talk_Mode ();
else
Select_Conversation_Mode ();
}
void Reinitialize_Player_Comments ()
{
Initialize_Player_Comments ();
}
void Display_Player_Comment (comment_level, player_name, comment)
int comment_level; char *player_name, *comment;
{
char message_buf [200];
char level_id;
switch (comment_level) {
case COMMENT_PRIVATE: level_id = '-'; break;
case COMMENT_FORMAL: level_id = '='; break;
case COMMENT_PUBLIC: level_id = ':'; break;
default: level_id = '*';
}
sprintf (message_buf, "%s%c %s", player_name, level_id, comment);
copy_string_to_comment (full_screen_comments[full_screen_cursor],
message_buf);
if (full_screen_cursor < full_screen_talk_size - 1)
full_screen_cursor++;
else
full_screen_cursor = 0;
blank_out_comment (full_screen_comments[full_screen_cursor]);
scroll_player_comments ();
copy_string_to_comment
(playing_screen_comments[playing_screen_talk_size-1], message_buf);
Refresh_Player_Comments ();
}
void Moderator_Comment (msg)
char *msg;
{
Display_Player_Comment (COMMENT_PUBLIC, "MODERATOR", msg);
}
void Network_Comment (msg)
char *msg;
{
Display_Player_Comment (COMMENT_PRIVATE, "NETWORK", msg);
}
void Suspend_Comment_Display ()
{
comments_suspended = 1;
}
void Continue_Comment_Display ()
{
comments_suspended = 0;
}
void Begin_full_screen_talk_mode ()
{
int i;
Select_Talk_Mode ();
for (i = 0; i <= XMAX(converse); i++) line_buf[i] = '-';
line_buf[XMAX(converse)+1] = '\0';
print (full_screen_talk_start-1, 1, line_buf);
line_buf[72] = '+';
print (full_screen_talk_end+1, 1, line_buf);
for (i = 1; i < XMAX(converse); i++) line_buf[i] = ' ';
line_buf[0] = line_buf[XMAX(converse)] = '|';
for (i = full_screen_talk_start; i <= full_screen_talk_end; i++)
print (i, 1, line_buf);
Refresh_Player_Comments ();
/* setup the talk buffer: */
print (terminal_lines-1, 1, "TALK");
status_loc = terminal_lines;
}
void End_full_screen_talk_mode ()
{
Select_Conversation_Mode ();
status_loc = YMIN(status);
Refresh_Display ();
}