home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume13
/
okbridge
/
part05
/
display.c
next >
Wrap
C/C++ Source or Header
|
1992-01-12
|
17KB
|
653 lines
/* display.c -- Display functions for netbridge program.
!
! Copyright (C) 1990,1991 by Matthew Clegg
!
! This program may be copied and distributed freely. Please do not
! charge money for this program or for any program derived from it.
! If you modify this program, then include a notice stating plainly
! that your program is derived from the okbridge program and is not
! the same as the official okbridge program.
!
! I welcome any suggestions for improvement to okbridge, and
! I would be especially happy to receive improved source code.
! If you have comments or suggestions, or if you would like to
! join the okbridge mailing list, then write to
!
! mclegg@cs.ucsd.edu
!
*/
#include <stdio.h>
#include <string.h>
#include "globals.h"
#include "terminal.h"
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, 59, 6, 26};
window left_hand = { 8, 6, 6, 18};
window playing_board = { 5, 27, 9, 26};
window bidding_board = { 5, 1, 9, 58};
window right_hand = { 8, 56, 6, 23};
window input = { 13, 1, 6, 26};
window status = { 18, 1, 1, 78};
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 char status_message_buf[81];
static 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 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);
};
Reset_Display ()
/* Redraws the main features of the screen. Used in the process
* of doing a 'refresh'.
*/
{
int i;
char program_name[20];
sprintf (program_name, "OKBRIDGE %s%s", major_revision_level,
minor_revision_level);
clear_screen ();
/* Display the title of the program: */
print (YMIN(title), XMIN(title), program_name);
/* print (YMIN(title)+1, XMIN(title), "MTC JUNE 90"); */
/* Setup the scoreboard: */
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 (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 CHICAGO_SCORING:
print (YMIN(scores)+4, XMIN(scores), "TOTAL");
print (YMIN(scores)+5, XMIN(scores), "PART");
print (YMIN(title)+1, XMIN(title), "HAND");
break;
case DUPLICATE_SCORING:
case EMAIL_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;
};
sprintf (program_name, "%d", current_deal_no);
print (YMIN(title)+1, XMIN(title)+6, program_name);
/* Setup the input area: */
print (TALK_ROW, TALK_COL, "TALK");
/* Setup the conversational area: */
for (i = 0; i <= XMAX(converse); i++) line_buf[i] = '-';
line_buf[XMAX(converse)+1] = '\0';
print (YMIN(converse), XMIN(converse), line_buf);
for (i = YMIN(converse)+1; i <= YMAX(converse); i++) {
print (i, XMIN(converse), "|");
print (i, XMAX(converse)+1, "|");
};
};
Initialize_Display ()
/* Should be called once when the program starts up. */
{
/* Initialize_Terminal (); */
Reset_Display ();
PLAYERHAND_X [local_player] = XMIN(bottom_hand);
PLAYERHAND_Y [local_player] = YMIN(bottom_hand);
PLAYERHAND_X [player_next[local_player]] = XMIN(left_hand);
PLAYERHAND_Y [player_next[local_player]] = YMIN(left_hand);
PLAYERHAND_X [player_partner[local_player]] = XMIN(top_hand);
PLAYERHAND_Y [player_partner[local_player]] = YMIN(top_hand);
PLAYERHAND_X [player_prev[local_player]] = XMIN(right_hand);
PLAYERHAND_Y [player_prev[local_player]] = YMIN(right_hand);
CARDPOS_Y[local_player] = YMAX(playing_board) - 2;
CARDPOS_X[local_player] = (XMAX(playing_board) +
XMIN(playing_board))/2;
CARDPOS_Y[player_next[local_player]] = (YMAX(playing_board) +
YMIN(playing_board))/2;
CARDPOS_X[player_next[local_player]] = XMIN(playing_board) + 3;
CARDPOS_Y[player_partner[local_player]] = YMIN(playing_board) + 2;
CARDPOS_X[player_partner[local_player]] = (XMAX(playing_board) +
XMIN(playing_board))/2;
CARDPOS_Y[player_prev[local_player]] = (YMAX(playing_board) +
YMIN(playing_board))/2;
CARDPOS_X[player_prev[local_player]] = XMAX(playing_board) - 4;
position_names[0] = player_names [local_player];
position_names[1] = player_names [player_next[local_player]];
position_names[2] = player_names [player_partner[local_player]];
position_names[3] = player_names [player_prev[local_player]];
status_message_buf[0] = '\0';
};
Refresh_Display ()
/* Resets the terminal display and redraws everything. */
{
int i, j, p;
Reset_Display ();
Display_Tricks_Taken ();
Display_Above_Line_Points ();
Display_Below_Line_Points ();
Display_Vulnerabilities ();
Refresh_Player_Comments ();
if (game_mode == STARTUP_MODE) {
;
} else if (game_mode == BIDDING_MODE) {
Display_Bidding_Board ();
Display_Hand_for_Bidding (local_player);
p = dealer;
for (i = 0; i < no_bids; i++) {
Display_Bid (i/4 + 1, p);
p = player_next [p];
};
Display_Bidder (p);
print (PLAY_ROW, PLAY_COL, "BID ");
} else if (game_mode == PLAYING_MODE) {
Display_Contract ();
Display_Playing_Board ();
Display_Hand (local_player);
if ((trick > 1) || (no_plays > 0))
Display_Hand (dummy);
if (local_player == dummy)
Display_Hand (declarer);
#ifdef LOOPBACK_MODE
Display_Hand (player_next[local_player]); /* DBG */
Display_Hand (player_partner[local_player]); /* DBG */
Display_Hand (player_prev[local_player]); /* DBG */
#endif
#ifdef TWOPLAYER_MODE
Display_Hand (player_partner[local_player]);
#endif
p = leader;
for (i = 0; i < no_plays; i++) {
Display_Play (p, plays[p]);
p = player_next[p];
};
Display_Player (p);
print (PLAY_ROW, PLAY_COL, "PLAY");
} else if (game_mode == REVIEW_MODE) {
Display_Contract ();
Display_Playing_Board ();
Display_Player (-1);
Display_Below_Line_Points ();
Display_Above_Line_Points ();
for (i = 0; i < 4; i++)
Display_Hand (i);
/*
Display_Status
("REVIEW OF THE HAND -- PRESS RETURN ON A BLANK LINE TO PROCEED");
*/
};
Refresh_Status_Display ();
};
Display_Tricks_Taken ()
{
sprintf (line_buf,"%5d %5d",tricks[SIDE_NS], tricks[SIDE_EW]);
print (YMIN(scores)+2,XMIN(scores)+8, line_buf);
};
Display_Above_Line_Points ()
{
sprintf (line_buf,"%5d %5d",above_line[SIDE_NS],
above_line[SIDE_EW]);
print (YMIN(scores)+4,XMIN(scores)+8, line_buf);
};
Display_Below_Line_Points ()
{
sprintf (line_buf,"%5d %5d",below_line[SIDE_NS],
below_line[SIDE_EW]);
print (YMIN(scores)+5,XMIN(scores)+8, line_buf);
};
Display_Vulnerabilities ()
{
char *nsv, *ewv;
if (vulnerable[SIDE_NS]) nsv = " YES";
else nsv = " NO";
if (vulnerable[SIDE_EW]) ewv = " YES";
else ewv = " NO";
sprintf (line_buf, "%s %s",nsv,ewv);
print (YMIN(scores)+3, XMIN(scores)+8, line_buf);
};
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);
};
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. */
{
int i;
char *first, *second, *third, *fourth, board_no_buf[10];
Clear_Bidding_Board ();
first = player_names [PLAYER_NORTH];
second = player_names [player_next[PLAYER_NORTH]];
third = player_names [player_partner[PLAYER_NORTH]];
fourth = player_names [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));
sprintf (board_no_buf, "%d", current_deal_no);
print (YMIN(title)+1, XMIN(title)+6, board_no_buf);
};
static 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]);
};
Display_Hand_for_Bidding (pos)
int pos;
{
int i, x, y;
suit_type h;
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_names[pos]);
underline (y, x, strlen(player_names[pos]));
h = current_hand[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);
};
Display_Bidder (player)
int player;
{
char bid_buf[80];
sprintf (bid_buf, "%s's BID ", player_names[player]);
print (YMIN(title)+2, XMIN(title), bid_buf);
};
Display_Bid (round, player)
int round, player;
{
int x, y, bid, position;
char *bid_string;
y = YMIN(bidding_board) + round + 1;
sprintf (line_buf, " %2d", round);
print (y, XMIN(bidding_board), line_buf);
/*
if (player == dealer) position = 0;
else if (player == player_next[dealer]) position = 1;
else if (player == player_partner[dealer]) position = 2;
else position = 3;
*/
y++;
for (x = dealer; x < 4; x++)
if (x == player) y--;
position = player;
x = XMIN(bidding_board) + 10 * position + 5;
bid = bids[player][round-1];
if (bid == BID_PASS)
bid_string = "--";
else
bid_string = bid_names[bid];
print (y, x, bid_string);
};
Display_Contract ()
{
char double_buf[40], contract_buf[60];
clear_screen_area (YMIN(title)+2, XMIN(title), HEIGHT(title),
WIDTH(title));
if (redoubled)
sprintf (double_buf," REDOUBLED");
else if (doubled)
sprintf (double_buf, " DOUBLED");
else
double_buf[0] = '\0';
sprintf (contract_buf, "%1d%s (%s)%s",contract,suit_names[trump_suit],
player_names[declarer], double_buf);
print (YMIN(title)+3, XMIN(title), contract_buf);
}
Clear_Playing_Board ()
{
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));
};
Display_Playing_Board ()
{
int i;
/* Clear_Playing_Board (); */
for (i = 0; i < 4; i++)
print (PLAYERHAND_Y[i]+1, PLAYERHAND_X[i]+12 -
strlen(player_names[i]), player_names[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, "|");
};
};
Display_Player (player)
int player;
{
char play_buf[80];
if (player < 0)
sprintf (play_buf, " ");
else if (player == dummy)
sprintf (play_buf, "DUMMY'S PLAY ");
else
sprintf (play_buf, "%s's PLAY ",
player_names[player]);
print (YMIN(title)+4, XMIN(title), play_buf);
};
Display_Play (p, card)
int p, card;
{
int x, y, position;
y = CARDPOS_Y [p];
x = CARDPOS_X [p];
if ((0 <= card) && (card < 52))
print (y, x, card_names[card]);
else
print (y, x, " ");
};
Clear_Plays ()
{
Display_Play (PLAYER_NORTH, -1);
Display_Play (PLAYER_EAST, -1);
Display_Play (PLAYER_SOUTH, -1);
Display_Play (PLAYER_WEST, -1);
};
Display_Hand (p)
int p;
{
int y, x, i;
suit_type h;
y = PLAYERHAND_Y [p];
x = PLAYERHAND_X [p];
for (i = 0; i < 4; i++)
print (y+i, x, " ");
h = current_hand[p];
print (y, x+5-strlen(player_names[p]), player_names[p]);
if (p == dummy)
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);
};
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_names[p]), player_names[p]);
if (p == dummy)
print (y+1, x+5-7, "(DUMMY)");
};
Display_Status (message)
char *message;
{
Clear_Status_Display ();
print (YMIN(status), XMIN(status), message);
sprintf (status_message_buf, "%s", message);
set_cursor (YMIN(status), XMIN(status) + strlen(message) + 1);
};
Clear_Status_Display ()
{
clear_screen_area (YMIN(status), XMIN(status), 1, WIDTH(status));
status_message_buf [0] = '\0';
};
Refresh_Status_Display ()
{
clear_screen_area (YMIN(status), XMIN(status), 1, WIDTH(status));
print (YMIN(status), XMIN(status), status_message_buf);
set_cursor (YMIN(status),
XMIN(status) + strlen(status_message_buf) + 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. */
#define COMMENT_LENGTH 78
#define COMMENT_BUF_SIZE 5
typedef char comment_line [COMMENT_LENGTH];
typedef comment_line comment_buf [COMMENT_BUF_SIZE];
static comment_buf player_comments;
static 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 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 scroll_player_comments ()
{
int i, j;
for (i = 0; i < COMMENT_BUF_SIZE - 1; i++)
for (j = 0; j < COMMENT_LENGTH; j++) {
player_comments[i][j] =
player_comments[i+1][j];
};
};
Refresh_Player_Comments ()
{
int i, x, y;
if (comments_suspended)
return;
x = XMIN(converse) + 1;
y = YMIN(converse) + 1;
for (i = 0; i < COMMENT_BUF_SIZE; i++)
print (y+i, x, player_comments[i]);
};
Initialize_Player_Comments ()
{
int i;
for (i = 0; i < COMMENT_BUF_SIZE; i++)
blank_out_comment (player_comments[i]);
Refresh_Player_Comments ();
};
Display_Player_Comment (player_name, comment)
char *player_name, *comment;
{
char message_buf [80];
sprintf (message_buf, "%s: %s", player_name, comment);
scroll_player_comments ();
copy_string_to_comment (player_comments[COMMENT_BUF_SIZE-1],
message_buf);
Refresh_Player_Comments ();
};
void Suspend_Comment_Display ()
{
comments_suspended = 1;
};
void Continue_Comment_Display ()
{
comments_suspended = 0;
};