home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!zephyr.ens.tek.com!master!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v13i017: okbridge - computer-mediated bridge game, Part02/07
- Message-ID: <2276@masterCNA.TEK.COM>
- Date: 10 Jan 92 16:44:35 GMT
- Sender: news@masterCNA.TEK.COM
- Lines: 1708
- Approved: billr@saab.CNA.TEK.COM
-
- Submitted-by: mclegg@cs.UCSD.EDU (Matthew Clegg)
- Posting-number: Volume 13, Issue 17
- Archive-name: okbridge/Part02
- Environment: BSD-derived Unix, curses, sockets
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 7)."
- # Contents: MakeDistrib bridge.c helpfile.h
- # Wrapped by billr@saab on Fri Jan 10 08:31:28 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'MakeDistrib' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MakeDistrib'\"
- else
- echo shar: Extracting \"'MakeDistrib'\" \(578 characters\)
- sed "s/^X//" >'MakeDistrib' <<'END_OF_FILE'
- X#/bin/csh -f
- X#
- X# This shell script creates the compress okbridge tar file which
- X# is distributed. Unfortunately, it seems that the "make" command
- X# on some systems is not smart enough to handle the work which is
- X# done by this file.
- X#
- Xsetenv MAJOR `grep 'major_rev.*=' globals.h | sed 's@.*"\(.*\)".*@\1@'`
- Xsetenv MINOR `grep 'minor_rev.*=' globals.h | sed 's@.*"\(.*\)".*@\1@'`
- Xsetenv OKFILENAME okbridge-$MAJOR$MINOR
- Xsetenv OKBDIR `pwd | sed "s@.*/\([^/]*\)@\1@"`
- Xcd ..
- Xecho Ztar\'ing $OKBDIR into $OKFILENAME.tar.Z
- Xtar -cf $OKFILENAME.tar $OKBDIR
- Xcompress $OKFILENAME.tar
- END_OF_FILE
- if test 578 -ne `wc -c <'MakeDistrib'`; then
- echo shar: \"'MakeDistrib'\" unpacked with wrong size!
- fi
- chmod +x 'MakeDistrib'
- # end of 'MakeDistrib'
- fi
- if test -f 'bridge.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bridge.c'\"
- else
- echo shar: Extracting \"'bridge.c'\" \(49783 characters\)
- sed "s/^X//" >'bridge.c' <<'END_OF_FILE'
- X/* bridge.c
- X !
- X ! Copyright (C) 1990,1991 by Matthew Clegg
- X !
- X ! This program may be copied and distributed freely. Please do not
- X ! charge money for this program or for any program derived from it.
- X ! If you modify this program, then include a notice stating plainly
- X ! that your program is derived from the okbridge program and is not
- X ! the same as the official okbridge program.
- X !
- X ! I welcome any suggestions for improvement to okbridge, and
- X ! I would be especially happy to receive improved source code.
- X ! If you have comments or suggestions, or if you would like to
- X ! join the okbridge mailing list, then write to
- X !
- X ! mclegg@cs.ucsd.edu
- X !
- X *
- X * General Description:
- X *
- X * This file contains an implementation of a computer-moderated
- X * bridge program. The program serves as a mediator allowing
- X * four people on separate systems to cooperate in a bridge game.
- X * The game is screen oriented and interactive, although the display
- X * is very simple. The program handles the shuffling and dealing
- X * of the cards, and it prompts each player for input when it is
- X * his turn. The lower area of the screen is a dialog box, where
- X * players may enter comments that will be seen by the others.
- X *
- X * Command Line:
- X *
- X * okbridge p [name [remote-server]]
- X *
- X * Where
- X *
- X * p is one of the characters: 'n', 's', 'e', or 'w'. This specifies
- X * which position the player wishes to have in the game. The players
- X * should agree beforehand who will take which position. If two
- X * players choose the same position, the program will not work
- X * correctly.
- X *
- X * name is an optional name which will be used to identify the player.
- X * If this is omitted, then the players position p will be used.
- X *
- X * remote-server
- X * is the name of the remote machine where the 'server' will be
- X * playing. For the sake of establishing the network communications,
- X * exactly one of the players must be a server. The choice of the
- X * server does not affect how the game plays. If remote-server is
- X * not specified, then this player will assume the role of the server.
- X *
- X * After processing the command line parameters, the program will first
- X * display a startup screen. Then, it will attempt to establish the network
- X * connections with the other players. After the connections have been
- X * established, the cards will be dealt and play will commence.
- X *
- X * The program automatically prompts for bids and plays at the appropriate
- X * times. When it is not time for a player to enter a bid or play, the
- X * program will remain in a 'talk' mode, where the player can type messages
- X * that will be sent to the other players. There are also a few special
- X * commands for controlling the game. These commands are all of the
- X * form:
- X * /command [parameters]
- X * For more information on the commands that are available, see the
- X * input.h file.
- X *
- X *
- X * Structure of the program:
- X *
- X * One of the chief principles in designing this game was portability.
- X * With this principle in mind, the game has been divided into a
- X * number of separate modules. Roughly speaking, the modules in the
- X * game can be grouped into two parts: the bridge program and the
- X * operating system interface. The bridge program consists of the
- X * modules DISPLAY, INPUT and BRIDGE. These modules are rather
- X * complicated and represent the heart of the bridge program.
- X * The operating system interface consists of the modules TERMINAL
- X * and NETWORK. These modules have been made as simple as possible.
- X * Their purpose is solely to insulate the first three modules from
- X * the particular operating system in use.
- X *
- X * DISPLAY. This module contains the primitives for displaying the
- X * actions of the game on the screen. This module calls only routines
- X * in the TERMINAL module, and does not call the operating system
- X * directly. (This explains, for example, why the display is so
- X * rudimentary.)
- X *
- X * INPUT. These routines are for reading the user's response from
- X * the terminal. There are two sources of complexities in this module.
- X * One is that there is a parser which is relatively large (but not
- X * very sophisticated) for processing input by the player and by the
- X * network. All of the actions of the program are command-driven.
- X * The other source of complexity is that we have to monitor both the
- X * keyboard and the network simultaneously at all times, and we have to
- X * assume that some of the input from the network will come out of order.
- X *
- X * MAIN. This module contains the procedures which represent the
- X * rules of the game.
- X *
- X * TERMINAL. This module contains entry-points for the most primitive
- X * I/O operations with the terminal. We assume that the screen is
- X * (at least) 24 x 80, that the cursor is addressable, and that
- X * it is possible to check for the availability of an input character
- X * without actually reading it. All of the I/O operations to the terminal
- X * are directed through this module.
- X *
- X * NETWORK. This module contains the primitives for network I/O.
- X * Every message that is sent by a player is broadcast to the other
- X * three players.
- X *
- X * PS. This is a simple module for breaking up an input string into
- X * a sequence of keywords. It is used only by the parser in the INPUT
- X * module.
- X *
- X * HELP. This is a module for providing on-line instructions about how
- X * to use the program. The help module reads a list of topics from a
- X * help file. Each topic then refers to another file containing an
- X * explanation of that topic.
- X *
- X *
- X * Future improvements:
- X *
- X * 1. It would be nice to be able to recover from a dropped connection.
- X * The network protocol assumes that the connections are stable and will
- X * last for the duration of the game. However, it has been my
- X * observation that with some networks, the connections may be
- X * broken occasionally. When this happens, the okbridge program has
- X * to be restarted from the beginning by all of the players.
- X *
- X * 2. It would be nice to implement a protocol for dealing the
- X * cards where each player would know only his own cards.
- X *
- X *
- X */
- X
- X#define _BRIDGE_
- X
- X#ifdef __TURBOC__
- X#include <alloc.h>
- X#include <stdlib.h>
- X#else
- X#define random(n) ((rand()/64) % (n))
- X#include <sys/time.h>
- X#include <sys/resource.h>
- X#endif
- X
- X#include <sys/types.h>
- X#include <setjmp.h>
- X#include <signal.h>
- X#include <stdio.h>
- X#ifdef AIX
- X#include <time.h>
- X#endif
- X#include <string.h>
- X
- X#include "globals.h"
- X#include "ps.h"
- X#include "display.h"
- X#include "input.h"
- X#include "network.h"
- X#include "terminal.h"
- X#include "help.h"
- X#include "code.h"
- X#include "email.h"
- X
- Xextern int errno;
- Xextern char *sys_errlist[];
- X
- Xextern int network_port;
- Xextern int server_mode;
- Xextern char *server_name;
- X
- Xextern char *autoload_file, *autosave_file;
- X
- XFILE *logfile = NULL; /* The file where we log the hands that have
- X . been played. */
- XFILE *zhang_logfile = NULL;
- X /* The file where we log hands that are written
- X in Zhang's format. */
- Xint table_no = -1; /* Table number printed in Szhang format log files. */
- Xchar *month_names [] =
- X { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept",
- X "Oct", "Nov", "Dec"};
- Xhand saved_hands [4]; /* The cards as they were dealt. */
- Xhand saved_plays [4]; /* The cards as they were played. */
- Xint leading_play [14];/* The leading player for each trick. */
- X
- Xchar *local_player_name = NULL;
- X /* This variable stores the name of the local player until
- X we know what his/her seat position is. */
- X
- X
- Xstatic jmp_buf error_return;
- Xstatic int abort_flag;
- X
- Xtypedef int declarations [5];
- Xstatic declarations declarers [2];
- X
- X/* The following table is used for computing scores according to a
- X "simulated IMP" scoring system. Much of the code for this scoring
- X system has been contributed by Ya-Xiang Yuan. */
- X
- Xstatic int IMP_scoring_table [] = {
- X 20, 50, 80, 120, 160, 210, 260, 310, 360, 430, 500,
- X 600, 750, 900, 1100, 1300, 1500, 1750, 2000, 2500, 3000,
- X 3500, 4000, 4500, 9999};
- X
- Xstatic int IMP_score_conversion (pt)
- X int pt;
- X/* This procedure converts a duplicate score into a corresponding IMP
- X . score. This code was contributed by Zhenjun Wu of Ohio State Univ. */
- X{
- X int i,apt;
- X static int IMP_scoring_table [] = {
- X 10, 40, 80, 120, 160, 210, 260, 310, 360, 420, 490,
- X 590, 740, 890, 1090, 1290, 1490, 1740, 1990, 2240, 2490,
- X 2990, 3490, 3990, 9999};
- X
- X if (! pt) return 0;
- X apt = (pt>0)? pt:-pt ;
- X for (i = 0; apt > IMP_scoring_table[i]; i++);
- X return ( (pt>0)? i:-i );
- X}
- X
- X
- Xchar *strdup (s)
- X char *s;
- X{
- X char *p, *q;
- X
- X q = p = (char *) malloc (strlen(s) + 2);
- X while (*s != '\0')
- X *(q++) = *(s++);
- X *q = '\0';
- X return (p);
- X};
- X
- X#ifdef NO_ISSPACE
- Xint isspace (ch)
- X char ch;
- X{
- X return ((ch == ' ') || (ch == '\t') || (ch == '\n'));
- X};
- X#endif
- X
- Xrandomize ()
- X{
- X srand (time(NULL));
- X};
- X
- X
- X
- Xstatic char *long_suit_names [] = {"CLUB", "DIAMOND", "HEART", "SPADE",
- X "NO TRUMP"};
- X
- X
- Xstatic void format_suit (buffer, h, s)
- X char *buffer; hand h; int s;
- X{
- X int i;
- X
- X for (i = 12; i >= 0; i--)
- X if (h[s + i])
- X *(buffer++) = *rank_names[i];
- X *buffer = '\0';
- X};
- X
- Xstatic void log_last_hand ()
- X/* Writes the last hand played to the logfile, provided that the logfile
- X . is open. If the logfile is not open, then does nothing.
- X */
- X{
- X int i, j, down, excess, score, contractor, passes, round, lead;
- X int player_no;
- X Email_Score *slist;
- X Email_Pair *pair;
- X char format_buffer [80];
- X char *north_name, *south_name, *east_name, *west_name;
- X time_t current_time;
- X
- X if (logfile == NULL) return;
- X
- X time (¤t_time);
- X fprintf (logfile, "%s\n", ctime(¤t_time));
- X fprintf (logfile, "DEALER: %s\n", player_names[dealer]);
- X
- X if (vulnerable[SIDE_NS] && vulnerable[SIDE_EW])
- X fprintf (logfile, "BOTH SIDES VULNERABLE\n");
- X else if (vulnerable[SIDE_NS])
- X fprintf (logfile, "%s AND %s ARE VULNERABLE\n",
- X player_names[PLAYER_NORTH], player_names[PLAYER_SOUTH]);
- X else if (vulnerable[SIDE_EW])
- X fprintf (logfile, "%s AND %s ARE VULNERABLE\n",
- X player_names[PLAYER_EAST], player_names[PLAYER_WEST]);
- X else
- X fprintf (logfile, "NEITHER SIDE IS VULNERABLE.\n");
- X
- X fprintf (logfile, "\nTHE DEAL:\n");
- X fprintf (logfile, "\n%10s"," ");
- X for (i = 0; i < 4; i++)
- X fprintf (logfile, " %-8s ", player_names[i]);
- X fprintf (logfile, "\n ");
- X for (i = 0; i < 4; i++)
- X fprintf (logfile, " -------- ");
- X for (i = 3; i >= 0; i--) {
- X fprintf (logfile, "\n%10sS ", long_suit_names[i]);
- X for (j = 0; j < 4; j++) {
- X format_suit (format_buffer, saved_hands[j], i * 13);
- X fprintf (logfile, "%-13s ", format_buffer);
- X };
- X };
- X
- X fprintf (logfile, "\n\n\nTHE BIDDING:\n");
- X fprintf (logfile, "\n%10s"," ");
- X for (i = 0; i < 4; i++)
- X fprintf (logfile, " %-8s ", player_names[i]);
- X fprintf (logfile, "\n ");
- X for (i = 0; i < 4; i++)
- X fprintf (logfile, " -------- ");
- X fprintf (logfile, "\n%15s"," ");
- X passes = -1;
- X round = -1;
- X i = 0;
- X while (passes < 3) {
- X if (i == dealer) round++;
- X if (round >= 0) {
- X fprintf (logfile, "%-8s%8s", bid_names[bids[i][round]]," ");
- X if (bids[i][round] == BID_PASS) passes++;
- X else passes = 0;
- X } else
- X fprintf (logfile, "%8s%8s", " ", " ");
- X i = player_next [i];
- X if (i == 0)
- X fprintf (logfile, "\n%15s"," ");
- X };
- X fprintf (logfile, "\n\n%15sCONTRACT: %d %s", " ", contract,
- X long_suit_names [trump_suit]);
- X if ((contract > 1) && (trump_suit != SUIT_NOTRUMP))
- X fprintf (logfile, "S");
- X if (redoubled)
- X fprintf (logfile, " (REDOUBLED)");
- X else if (doubled)
- X fprintf (logfile, " (DOUBLED)");
- X fprintf (logfile," BY %s\n", player_names[declarer]);
- X
- X fprintf (logfile, "\n\n\nTHE PLAYING:\n");
- X fprintf (logfile, "\n ");
- X for (i = 0; i < 13; i++)
- X fprintf (logfile, "%2d ", i+1);
- X fprintf (logfile, "\n ");
- X for (i = 0; i < 4*13-2; i++) fprintf (logfile, "-");
- X for (i = 0; i < 4; i++) {
- X fprintf (logfile, "\n%8s ", player_names[i]);
- X for (j = 1; j < 14; j++) {
- X if (saved_plays[i][j] != (char) (-1)) {
- X lead = (leading_play[j] == i)? '*': ' ';
- X fprintf (logfile, "%2s%c ", card_names[saved_plays[i][j]], lead);
- X } else
- X fprintf (logfile, " ");
- X };
- X };
- X fprintf (logfile, "\n\n * INDICATES THE LEAD\n");
- X
- X contractor = side_of(declarer);
- X/*
- X fprintf (logfile, "\n\n\nTHE SCORES:\n\n");
- X fprintf (logfile, " TRICKS WON: %2d\n", tricks[contractor]);
- X fprintf (logfile, " TRICKS LOST: %2d\n", tricks[1-contractor]);
- X fprintf (logfile, "\n");
- X*/
- X fprintf (logfile, "\n BID %2d, ", contract);
- X if (tricks[contractor] >= contract+6) {
- X fprintf (logfile, " MADE %2d", tricks[contractor]-6);
- X excess = tricks[contractor] - contract - 6;
- X switch (scoring_mode) {
- X case RUBBER_SCORING:
- X fprintf (logfile, "\n\n POINTS ABOVE THE LINE: %5d\n",
- X Rubber_score_above (excess));
- X fprintf (logfile, " POINTS BELOW THE LINE: %5d\n",
- X Rubber_score_below ());
- X break;
- X case CHICAGO_SCORING:
- X score = Chicago_score_made (excess, vulnerable[contractor]);
- X if ((score < 100) && (hands_played%4 == 0))
- X score += 100;
- X fprintf (logfile, ", FOR A SCORE OF %5d\n", score);
- X break;
- X case DUPLICATE_SCORING:
- X case EMAIL_SCORING:
- X case IMP_SCORING:
- X fprintf (logfile, ", FOR A SCORE OF %5d\n",
- X Duplicate_score_made (excess, vulnerable[contractor]));
- X break;
- X }
- X } else {
- X down = contract + 6 - tricks[contractor];
- X fprintf (logfile, " DOWN %2d, ", down);
- X fprintf (logfile, " FOR A LOSS OF ");
- X switch (scoring_mode) {
- X case RUBBER_SCORING:
- X fprintf (logfile, "%5d\n", Rubber_score_set (down));
- X break;
- X case CHICAGO_SCORING:
- X fprintf (logfile, "%5d\n",
- X Chicago_score_set (down, vulnerable[contractor]));
- X break;
- X case DUPLICATE_SCORING:
- X case EMAIL_SCORING:
- X case IMP_SCORING:
- X fprintf (logfile, "%5d\n",
- X Duplicate_score_set (down, vulnerable[contractor]));
- X break;
- X }
- X };
- X
- X if ((current_board != NULL) && (current_board->score_list->next != NULL)) {
- X slist = current_board->score_list;
- X fprintf (logfile, "\n");
- X fprintf (logfile, " %-8s %-8s %-8s %-8s %-6s %2s %6s %6s %6s %6s\n",
- X "NORTH", "SOUTH", "EAST", "WEST", "BID", "BY", "RESULT",
- X "SCORE", "NS-MP", "EW-MP");
- X while (slist != NULL) {
- X pair = email_record->player_list + slist->ns_pair;
- X north_name = pair->ne;
- X south_name = pair->sw;
- X pair = email_record->player_list + slist->ew_pair;
- X east_name = pair->ne;
- X west_name = pair->sw;
- X fprintf (logfile, " %-8s %-8s %-8s %-8s ", north_name, south_name,
- X east_name, west_name);
- X sprintf (format_buffer, "%s", bid_names[slist->bid]);
- X if (slist->doubled == BID_REDOUBLE)
- X sprintf (format_buffer+strlen(format_buffer), "-XX");
- X else if (slist->doubled == BID_DOUBLE)
- X sprintf (format_buffer+strlen(format_buffer), "-X");
- X fprintf (logfile, "%-6s %c %+6d %6d %6.1f %6.1f\n", format_buffer,
- X *("NESW" + slist->contractor), slist->result, slist->ns_score,
- X 0.5 * ((float) slist->ns_match_points),
- X 0.5 * ((float) slist->ew_match_points));
- X slist = slist->next;
- X };
- X };
- X
- X fprintf (logfile, "\n\n");
- X for (i = 0; i < 72; i++)
- X fprintf (logfile, "=");
- X fprintf (logfile, "\n%c\n", 12);
- X fflush (logfile);
- X};
- X
- X
- Xstatic void zhang_log_last_hand ()
- X/* The following routine is S. Zhang's routine for writing the log file.
- X . This constitutes the heart of his "okbd" version of okbridge.
- X . It has been modified from the log_last_hand procedure
- X . by Shangyou Zhang, szhang@math.udel.edu.
- X */
- X{
- X int i, j, down, excess, score, contractor, passes, round, lead;
- X int r_round;
- X char format_buffer [80];
- X char *bid_zhang[4][20];
- X char zhang[4];
- X time_t current_time;
- X struct tm *decoded_time;
- X
- X zhang[0]='N'; zhang[1]='E'; zhang[2]='S'; zhang[3]='W';
- X
- X if (zhang_logfile == NULL) return;
- X for (i = 0; i < 4; i++){fprintf(zhang_logfile,
- X " %-8.8s ", player_names[i]);
- X for (j = 3; j >= 0; j--) {
- X format_suit (format_buffer, saved_hands[i], j * 13);
- X fprintf (zhang_logfile, " %-13s", format_buffer);
- X }; fprintf (zhang_logfile, "\n");
- X };
- X
- X contractor = side_of(declarer);
- X fprintf(zhang_logfile, "%3d.(tab%3d)", current_deal_no, table_no);
- X
- X fprintf (zhang_logfile," %6.6s-%c:", player_names[declarer],
- X zhang[declarer]);
- X fprintf (zhang_logfile, "%d%1.1s",
- X contract, long_suit_names [trump_suit] );
- X if (redoubled) fprintf (zhang_logfile, "XX");
- X else if (doubled) fprintf (zhang_logfile, "X ");
- X else fprintf (zhang_logfile, " ");
- X
- X if (tricks[contractor] >= contract+6) {
- X fprintf (zhang_logfile, " -- Made %2d | ",
- X (contract == 0)? 0: tricks[contractor]-6);
- X } else { down = contract + 6 - tricks[contractor];
- X fprintf (zhang_logfile, " -- Down %2d | ", down);
- X };
- X
- X if (vulnerable[SIDE_NS] && vulnerable[SIDE_EW])
- X fprintf (zhang_logfile, "Vul:BOTH | ");
- X else if (vulnerable[SIDE_NS]) fprintf (zhang_logfile, "Vul:N&S | ");
- X else if (vulnerable[SIDE_EW]) fprintf (zhang_logfile, "Vul:E&W | ");
- X else fprintf (zhang_logfile, "Vul:NONE | ");
- X
- X
- X if (tricks[contractor] >= contract+6) {
- X if ( contractor == SIDE_NS ) {fprintf (zhang_logfile, " NS: ");}
- X else fprintf (zhang_logfile, "*NS: -");
- X excess = tricks[contractor] - contract - 6;
- X if (contract == 0)
- X fprintf (zhang_logfile, "0 ");
- X else
- X fprintf (zhang_logfile, "%d ",
- X Duplicate_score_made (excess, vulnerable[contractor]));
- X } else {
- X down = contract + 6 - tricks[contractor];
- X if ( contractor == SIDE_NS ) {fprintf (zhang_logfile, " NS: -");}
- X else fprintf (zhang_logfile, "*NS: ");
- X fprintf (zhang_logfile, "%d ",
- X Duplicate_score_set (down, vulnerable[contractor]));
- X };
- X
- X for (i=0; i<4; i++) for (j=0; j<20; j++) bid_zhang[i][j]=" ";
- X
- X passes = -1; round = -1; r_round=0; i = 0;
- X while (passes < 3) {
- X if (i == dealer) round++;
- X if (round >= 0) {
- X bid_zhang[i][r_round]= bid_names[bids[i][round]];
- X if (bids[i][round] == BID_PASS) passes++;
- X else passes = 0;
- X }
- X i = player_next [i];
- X if ( (i==0) && passes<3 ) r_round++;
- X };
- X
- X for (i = 0; i < 4; i++) {
- X fprintf(zhang_logfile,"\n%c-%-8.8s",zhang[i],player_names[i]);
- X for (j = 1; j < 14; j++) {
- X if (saved_plays[i][j] != (char) (-1)) {
- X lead = (leading_play[j] == i)? '*': ' ';
- X if ((lead ==' ')&&(i==3) ) lead='_';
- X fprintf (zhang_logfile, "%2s%c", card_names[saved_plays[i][j]], lead);
- X } else
- X fprintf (zhang_logfile, " ");
- X }; fprintf (zhang_logfile, "|");
- X for (j = 0; j <= r_round; j++) {
- X fprintf (zhang_logfile, "%-2.2s ", bid_zhang[i][j]);
- X };
- X };
- X
- X fprintf (zhang_logfile, "\n==========");
- X for (i = 0; i < 13; i++) fprintf (zhang_logfile, "%2d=", i+1);
- X time (¤t_time);
- X for (i = 0; i < 6; i++) fprintf (zhang_logfile, "=%2d", i+1);
- X decoded_time = localtime (¤t_time);
- X fprintf (zhang_logfile, " %s %2d\n%c\n",
- X month_names[decoded_time->tm_mon], decoded_time->tm_mday, 12);
- X fflush (zhang_logfile);
- X};
- X
- Xint bidding_code (bid_type, level, suit)
- X int bid_type, level, suit;
- X/* Given the bidding type, as above, and the level and suit if it is
- X * a contract bid, returns a unique integer in the range 0-37 associated
- X * with the bid. Contract bids are ordered in increasing order, so that
- X * 1C is the smallest and 7NT is the largest.
- X */
- X{
- X switch (bid_type) {
- X case BID_PASS: return (BID_PASS);
- X case BID_DOUBLE: return (BID_DOUBLE);
- X case BID_REDOUBLE: return (BID_REDOUBLE);
- X case BID_SUIT: return (5 * (level - 1) + suit + 3);
- X default: ;
- X };
- X return (-1);
- X};
- X
- Xint card_code (suit, rank)
- X int suit, rank;
- X/* Given a suit and rank, returns a unique associated integer in the
- X * range 0-51. The cards are arranged so that the 2 of clubs has code 0 and
- X * the ace of spades has code 51.
- X */
- X{
- X return (13 * suit + rank);
- X};
- X
- Xstatic generate_valid_bids (p, minimum_bid, double_ok, redouble_ok)
- X int p, *minimum_bid, *double_ok, *redouble_ok;
- X/* Determines the valid bids for the player p, given that the list of
- X * bids made so far is stored in the global variable 'bids', and that
- X * the variables 'trump_suit', 'contract', 'declarer', 'doubled' and
- X * 'redoubled' reflect the current state of the bidding. Computes
- X * the minimum contract bid which is acceptable, and computes boolean
- X * flags indicating whether it is ok to double or redouble.
- X */
- X{
- X int bidding_side, declaring_side;
- X
- X bidding_side = side_of (p);
- X if (contract > 0) {
- X declaring_side = side_of (declarer);
- X if (declaring_side != bidding_side) {
- X *double_ok = !doubled;
- X *redouble_ok = 0;
- X } else {
- X *double_ok = 0;
- X if (doubled) *redouble_ok = !redoubled;
- X };
- X };
- X if (contract == 0) { /* no one has bid a contract yet */
- X *minimum_bid = bidding_code(BID_SUIT, 1, SUIT_CLUBS);
- X *double_ok = *redouble_ok = 0;
- X } else
- X *minimum_bid = 1 + bidding_code(BID_SUIT, contract,
- X trump_suit);
- X};
- X
- Xstatic update_bidding_list (p, bid)
- X int p, bid;
- X/* Enters a new bid for player p. Assumes of course that it is p's
- X * turn to bid and that the bid is legal. Updates the variables:
- X * trump_suit, contract, declarer, doubled, redoubled, bids, no_bids
- X */
- X{
- X int round, i, side;
- X
- X round = no_bids / 4;
- X bids [p][round] = bid;
- X if (bid == BID_PASS) {
- X ;
- X } else if (bid == BID_DOUBLE) {
- X doubled = 1;
- X } else if (bid == BID_REDOUBLE) {
- X redoubled = 1;
- X } else {
- X doubled = redoubled = 0;
- X trump_suit = trumpsuit_of (bid);
- X contract = contract_of (bid);
- X side = side_of(p);
- X if (declarers[side][trump_suit] < 0)
- X declarers[side][trump_suit] = p;
- X declarer = declarers[side][trump_suit];
- X dummy = player_partner[declarer];
- X };
- X no_bids += 1;
- X};
- X
- X
- Xstatic generate_valid_plays (p, h)
- X int p; hand h;
- X/* Generates a list of valid plays for player p. The list of valid
- X * plays is determined by examining the global variables 'leader' and
- X * 'current_hand'. The valid plays are stored as a boolean string
- X * in h, so that h[c] == true iff it is legal to play card c.
- X */
- X{
- X int i, n, lead_suit;
- X
- X if (p == leader) {
- X for (i = 0; i < 52; i++)
- X h[i] = current_hand[p][i];
- X } else {
- X lead_suit = suit_of(plays[leader]);
- X n = 0;
- X for (i = 0; i < 52; i++) {
- X h[i] = current_hand[p][i] &&
- X (suit_of(i) == lead_suit);
- X if (h[i]) n += 1;
- X };
- X if (n == 0)
- X for (i = 0; i < 52; i++)
- X h[i] = current_hand[p][i];
- X };
- X};
- X
- Xstatic int outranks (c1, c2)
- X int c1, c2;
- X/* Returns true if c1 outranks c2, according to the current trump_suit.
- X * If c1 and c2 are of different suits, neither of which is the trump_suit,
- X * then returns false.
- X */
- X{
- X if (suit_of (c1) == suit_of (c2))
- X return (rank_of(c1) > rank_of(c2));
- X else
- X return (suit_of (c1) == trump_suit);
- X};
- X
- X
- Xstatic int play_hand ()
- X/* Plays one hand of bridge. Handles the dealing, bidding, play and scoring
- X * of the hand. Returns 1 if a hand is played, or 0 if all 4 players
- X * pass in the first round of bidding.
- X */
- X{
- X /* General purpose variables: */
- X int i, j, c1, c2, c3, c4;
- X Email_Comment *ec;
- X
- X /* Variables used in the bidding stage: */
- X int bidder, bid, no_passes, double_ok, redouble_ok,
- X minimum_bid, round, highest_bid;
- X
- X /* Variables used in the playing stage: */
- X int pos, card, winning_card, winning_player;
- X hand legal_plays;
- X char claim_message[80];
- X
- X /* Variables used in updating the scores: */
- X int contractor, excess, down, penalty, honors_bonus,
- X highcard_points, base_score;
- X char *honors_bonus_string, honors_message[80];
- X int email_score, /* +/- duplicate scored recorded for email play */
- X email_result; /* +tricks made, or -tricks down. */
- X Email_Score *score;
- X
- X /* Variables used for debugging: */
- X int save_pos;
- X
- X tricks [SIDE_NS] = tricks [SIDE_EW] = 0;
- X Display_Tricks_Taken ();
- X
- X game_mode = DEALING_MODE;
- X
- X input_hand (current_deal);
- X if (current_board != NULL)
- X for (ec = current_board->pre_script; ec != NULL; ec = ec->next)
- X Broadcast_Comment (ec->comment);
- X
- X for (i = 0; i < 52; i++) {
- X for (j = 0; j < 4; j++) current_hand[j][i] = 0;
- X current_hand[current_deal[i]][i] = 1;
- X };
- X for (i = 0; i < 4; i++)
- X for (j = 0; j < 52; j++){
- X saved_hands[i][j] = current_hand[i][j];
- X saved_plays[i][j] = -1;
- X };
- X
- X no_bids = 0;
- X doubled = redoubled = 0;
- X bidder = dealer;
- X no_passes = 0;
- X contract = 0;
- X trump_suit = SUIT_NOTRUMP;
- X
- X game_mode = BIDDING_MODE;
- X Display_Vulnerabilities ();
- X Display_Bidding_Board ();
- X for (i = 0; i < 10; i++)
- X for (j = 0; j < 3; j++)
- X bids [j][i] = -1;
- X for (i = 0; i < 5; i++)
- X declarers[SIDE_NS][i] = declarers[SIDE_EW][i] = -1;
- X round = 1;
- X
- X Display_Hand_for_Bidding (local_player);
- X
- X while ((no_passes < 3) || (round == 1)) {
- X generate_valid_bids (bidder, &minimum_bid, &double_ok,
- X &redouble_ok);
- X Display_Bidder (bidder);
- X#ifdef LOOPBACK_MODE
- X local_player = bidder;
- X Display_Hand_for_Bidding (bidder);
- X bid = input_bid (local_player, minimum_bid, double_ok,
- X redouble_ok);
- X local_player = PLAYER_NORTH;
- X#else
- X#ifdef TWOPLAYER_MODE
- X if ((bidder % 2) == (local_player % 2))
- X Display_Hand_for_Bidding (bidder);
- X bid = input_bid ((bidder % 2), minimum_bid, double_ok,
- X
- X redouble_ok);
- X#else
- X bid = input_bid (bidder, minimum_bid, double_ok,
- X redouble_ok);
- X#endif
- X#endif
- X update_bidding_list (bidder, bid);
- X Display_Bid (round, bidder);
- X if (bid == BID_PASS)
- X no_passes++;
- X else
- X no_passes = 0;
- X if ((bid != BID_PASS) && (bid != BID_DOUBLE) &&
- X (bid != BID_REDOUBLE))
- X highest_bid = bid;
- X bidder = player_next[bidder];
- X if (bidder == dealer) round++;
- X };
- X if (contract == 0) {
- X Display_Status ("TOSSING IN THE HAND -- PRESS RETURN TO PROCEED");
- X Record_Email_Score (current_board, ns_pair_no, ew_pair_no,
- X BID_PASS, 0, PLAYER_NORTH, 0, 0);
- X tricks[SIDE_NS] = 7;
- X tricks[SIDE_EW] = 6;
- X zhang_log_last_hand ();
- X input_acknowledgment (-2);
- X return (0);
- X } else {
- X Display_Status ("THREE PASSES -- PRESS RETURN TO BEGIN PLAY");
- X input_acknowledgment (-2);
- X };
- X Clear_Bidding_Board ();
- X
- X game_mode = PLAYING_MODE;
- X Display_Playing_Board ();
- X Display_Contract ();
- X
- X honors_bonus = 0;
- X if (trump_suit < 4) {
- X j = card_code (trump_suit, RANK_TEN);
- X for (i = c1 = 0; i < 5; i++)
- X c1 += current_hand[declarer][i+j];
- X for (i = c2 = 0; i < 5; i++)
- X c2 += current_hand[dummy][i+j];
- X if ((c1 == 5) || (c2 == 5)) {
- X honors_bonus = 150;
- X honors_bonus_string =
- X "150 POINT BONUS FOR ALL 5 HONORS IN ONE HAND";
- X } else if ((c1 == 4) || (c2 == 4)) {
- X honors_bonus = 100;
- X honors_bonus_string =
- X "100 POINT BONUS FOR 4 HONORS IN ONE HAND";
- X };
- X } else {
- X for (i = c1 = 0; i < 4; i++)
- X c1 += current_hand[declarer][card_code(i, RANK_ACE)];
- X for (i = c2 = 0; i < 4; i++)
- X c2 += current_hand[dummy][card_code(i, RANK_ACE)];
- X if ((c1 == 5) || (c2 == 5)) {
- X honors_bonus = 150;
- X honors_bonus_string =
- X "150 POINT BONUS FOR ALL 4 ACES IN ONE HAND";
- X }
- X };
- X if ((scoring_mode == DUPLICATE_SCORING) ||
- X (scoring_mode == EMAIL_SCORING) ||
- X (scoring_mode == IMP_SCORING))
- X honors_bonus = 0;
- X
- X if (scoring_mode == IMP_SCORING) {
- X for (i = c1 = 0; i < 4; i++)
- X { c1 += current_hand[declarer][card_code(i, RANK_ACE)];
- X c1 += current_hand[dummy][card_code(i, RANK_ACE)];};
- X for (i = c2 = 0; i < 4; i++)
- X { c2 += current_hand[declarer][card_code(i, RANK_KING)];
- X c2 += current_hand[dummy][card_code(i, RANK_KING)];};
- X for (i = c3 = 0; i < 4; i++)
- X { c3 += current_hand[declarer][card_code(i, RANK_QUEEN)];
- X c3 += current_hand[dummy][card_code(i, RANK_QUEEN)];};
- X for (i = c4 = 0; i < 4; i++)
- X { c4 += current_hand[declarer][card_code(i, RANK_JACK)];
- X c4 += current_hand[dummy][card_code(i, RANK_JACK)];};
- X highcard_points = 4*c1 + 3*c2 + 2*c3 + c4;
- X };
- X
- X leader = player_next [declarer];
- X for (trick = 1; trick < 14; trick++) {
- X leading_play [trick] = leader;
- X Display_Hand (local_player);
- X if (local_player == dummy) Display_Hand (declarer);
- X
- X#ifdef TWOPLAYER_MODE
- X Display_Hand (player_partner[local_player]); /* DBG */
- X#endif
- X#ifdef LOOPBACK_MODE
- X for (no_plays = 0; no_plays < 4; no_plays++)
- X Display_Hand (no_plays);
- X#endif
- X
- X no_plays = 0;
- X pos = leader;
- X while (no_plays < 4) {
- X generate_valid_plays (pos, legal_plays);
- X Display_Player (pos);
- X#ifdef LOOPBACK_MODE
- X local_player = pos;
- X Display_Hand (pos);
- X card = input_play (local_player, legal_plays);
- X Display_Play (pos, card);
- X local_player = PLAYER_NORTH;
- X#else
- X#ifdef TWOPLAYER_MODE
- X card = input_play ((pos % 2), legal_plays);
- X#else
- X if (pos == dummy)
- X card = input_play (declarer, legal_plays);
- X else
- X card = input_play (pos, legal_plays);
- X#endif
- X#endif
- X if (card < 0) break;
- X
- X if (no_plays == 0) {
- X winning_card = card;
- X winning_player = leader;
- X } else if (outranks(card, winning_card)) {
- X winning_card = card;
- X winning_player = pos;
- X };
- X no_plays += 1;
- X plays [pos] = card;
- X current_hand[pos][card] = 0;
- X saved_plays [pos][trick] = card;
- X Display_Play (pos, card);
- X
- X if (pos == local_player)
- X Display_Hand (local_player);
- X if ((pos == dummy) || (trick == 1))
- X Display_Hand (dummy);
- X if ((local_player == dummy) && (pos == declarer))
- X Display_Hand (declarer);
- X
- X pos = player_next[pos];
- X };
- X if (card < 0) {
- X card = -card-1;
- X tricks[side_of(declarer)] += card;
- X tricks[1-side_of(declarer)] = 13 - tricks[side_of(declarer)];
- X trick = 14;
- X Display_Tricks_Taken();
- X sprintf (claim_message,
- X "DECLARER HAS CLAIMED %d MORE TRICKS", card);
- X Display_Player_Comment ("MODERATOR", claim_message);
- X } else {
- X leader = winning_player;
- X tricks[side_of(leader)] += 1;
- X Display_Tricks_Taken();
- X if ((local_player != dummy) || prompt_dummy)
- X input_acknowledgment (-1);
- X };
- X Clear_Plays ();
- X };
- X hands_played += 1;
- X
- X contractor = side_of(declarer);
- X
- X switch (scoring_mode) {
- X case RUBBER_SCORING:
- X case CHICAGO_SCORING:
- X above_line [contractor] += honors_bonus;
- X break;
- X case DUPLICATE_SCORING:
- X case EMAIL_SCORING:
- X above_line [SIDE_NS] += below_line[SIDE_NS];
- X above_line [SIDE_EW] += below_line[SIDE_EW];
- X below_line [SIDE_NS] = below_line[SIDE_EW] = 0;
- X break;
- X case IMP_SCORING:
- X above_line [SIDE_NS] += below_line[SIDE_NS];
- X above_line [SIDE_EW] += below_line[SIDE_EW];
- X below_line [SIDE_NS] = below_line[SIDE_EW] = 0;
- X sprintf (honors_message,
- X "CONTRACTOR'S SIDE HAS %d HIGH CARD POINTS",
- X highcard_points);
- X Display_Player_Comment ("MODERATOR", honors_message);
- X break;
- X };
- X
- X if (honors_bonus > 0)
- X Display_Player_Comment ("MODERATOR", honors_bonus_string);
- X
- X if (tricks[contractor] >= contract+6) {
- X excess = tricks[contractor] - contract - 6;
- X /* We always record the hands in email structures, in case
- X the player would like to save them. Therefore, we must
- X always compute the email score. */
- X email_score =
- X Duplicate_score_made (excess, vulnerable[contractor]);
- X email_result = tricks[contractor] - 6;
- X
- X switch (scoring_mode) {
- X case RUBBER_SCORING:
- X below_line[contractor] += Rubber_score_below ();
- X above_line[contractor] += Rubber_score_above (excess);
- X/*
- X if (vulnerable[contractor] &&
- X (below_line[contractor] >= 100)) {
- X sprintf (honors_message, "%s AND %s %s",
- X player_names[contractor],
- X player_names[contractor+2],
- X "HAVE WON THE RUBBER.");
- X Display_Player_Comment ("MODERATOR",
- X honors_message);
- X };
- X*/
- X break;
- X case CHICAGO_SCORING:
- X below_line[contractor] += Chicago_score_made (excess,
- X vulnerable[contractor]);
- X if ((below_line[contractor] < 100) &&
- X (hands_played%4 == 0))
- X below_line[contractor] += 100;
- X if (below_line[contractor] >= 100) {
- X above_line[contractor] += below_line[contractor];
- X below_line[SIDE_NS] = below_line[SIDE_EW] = 0;
- X };
- X break;
- X case DUPLICATE_SCORING:
- X case EMAIL_SCORING:
- X below_line[contractor] = email_score;
- X break;
- X case IMP_SCORING:
- X base_score =
- X Duplicate_score_made (excess,
- X vulnerable[contractor]);
- X below_line[contractor] =
- X IMP_score_conversion (base_score);
- X/*
- X for (i = 0; base_score >= IMP_scoring_table[i]; i++);
- X below_line[contractor] =
- X 20 + i - highcard_points;
- X*/
- X break;
- X }
- X if ((contract >= 6) && (contractor == side_of(local_player))){
- X display_help ("slam");
- X Refresh_Display ();
- X };
- X } else {
- X down = contract + 6 - tricks[contractor];
- X email_score =
- X -Duplicate_score_set (down, vulnerable[contractor]);
- X email_result = -down;
- X switch (scoring_mode) {
- X case RUBBER_SCORING:
- X above_line [1-contractor] += Rubber_score_set (down);
- X break;
- X case CHICAGO_SCORING:
- X above_line [1-contractor] +=
- X Chicago_score_set (down, vulnerable[contractor]);
- X break;
- X case DUPLICATE_SCORING:
- X case EMAIL_SCORING:
- X below_line [1-contractor] = - email_score;
- X break;
- X case IMP_SCORING:
- X base_score = Duplicate_score_set (down,
- X vulnerable[contractor]);
- X below_line[contractor] =
- X IMP_score_conversion (-base_score);
- X/*
- X for (i = 0; base_score >= IMP_scoring_table[i]; i++);
- X base_score = -base_score;
- X below_line[contractor] =
- X 20 - i - highcard_points;
- X*/
- X break;
- X }
- X };
- X
- X if (current_board != NULL)
- X for (ec=current_board->post_script; ec != NULL; ec = ec->next)
- X Broadcast_Comment (ec->comment);
- X
- X /* Now we record the score in an email record. If we are actually
- X playing in email mode, then we display how will each side did. */
- X i = (redoubled? BID_REDOUBLE: (doubled? BID_DOUBLE: 0));
- X if (side_of(declarer) == side_of(PLAYER_EAST))
- X email_score = -email_score;
- X Record_Email_Score (current_board, ns_pair_no, ew_pair_no,
- X highest_bid, i, declarer, email_result, email_score);
- X if ((scoring_mode == EMAIL_SCORING) &&
- X (local_player == PLAYER_NORTH)) {
- X Compute_Board_Match_Points (current_board);
- X score = current_board->score_list;
- X while (score->ns_pair != ns_pair_no) score = score->next;
- X if ((score->ns_match_points != 0) ||
- X (score->ew_match_points != 0)) {
- X sprintf (claim_message, "%s: %4.1f, %s: %4.1f",
- X "N-S MATCH POINTS",
- X 0.5 * ((float) score->ns_match_points),
- X "E-W MATCH POINTS",
- X 0.5 * ((float) score->ew_match_points));
- X Broadcast_Comment (claim_message);
- X };
- X };
- X log_last_hand ();
- X zhang_log_last_hand ();
- X Display_Player (-1);
- X Display_Below_Line_Points ();
- X Display_Above_Line_Points ();
- X for (i = 0; i < 4; i++)
- X for (j = 0; j < 52; j++)
- X current_hand[i][j] = saved_hands[i][j];
- X for (i = 0; i < 4; i++)
- X Display_Hand (i);
- X Display_Status
- X ("REVIEW OF THE HAND -- PRESS RETURN ON A BLANK LINE TO PROCEED");
- X game_mode = REVIEW_MODE;
- X input_acknowledgment (-3);
- X game_mode = DEALING_MODE;
- X
- X Clear_Playing_Board ();
- X return (1);
- X};
- X
- X
- Xstatic play_game ()
- X{
- X int winner;
- X
- X below_line[SIDE_NS] = below_line[SIDE_EW] = 0;
- X
- X while ((below_line[SIDE_NS] < 100) && (below_line[SIDE_EW] < 100)) {
- X Refresh_Display ();
- X Display_Below_Line_Points ();
- X Display_Above_Line_Points ();
- X play_hand ();
- X dealer = player_next [dealer];
- X };
- X
- X above_line[SIDE_NS] += below_line[SIDE_NS];
- X above_line[SIDE_EW] += below_line[SIDE_EW];
- X winner = (below_line[SIDE_NS] >= 100) ? SIDE_NS : SIDE_EW;
- X if (vulnerable[winner])
- X above_line[winner] += 500;
- X vulnerable[winner]++;
- X};
- X
- Xstatic play_rubber ()
- X{
- X char message_buf[80];
- X
- X vulnerable[SIDE_NS] = vulnerable[SIDE_EW] = 0;
- X
- X while ((vulnerable[SIDE_NS] < 2) && (vulnerable[SIDE_EW] < 2)) {
- X Display_Vulnerabilities ();
- X play_game ();
- X };
- X
- X /* Add bonus points if only one side was vulnerable when the
- X rubber was won. */
- X if (vulnerable[SIDE_NS] == 0)
- X above_line[SIDE_EW] += 200;
- X else if (vulnerable[SIDE_EW] == 0)
- X above_line[SIDE_NS] += 250;
- X
- X if (vulnerable[SIDE_NS] >= 2)
- X sprintf (message_buf, "%s AND %s HAVE WON THE RUBBER.",
- X player_names[PLAYER_NORTH],
- X player_names[PLAYER_SOUTH]);
- X else
- X sprintf (message_buf, "%s AND %s HAVE WON THE RUBBER.",
- X player_names[PLAYER_EAST],
- X player_names[PLAYER_WEST]);
- X Display_Player_Comment ("MODERATOR", message_buf);
- X};
- X
- Xstatic void play_chicago_rubber ()
- X{
- X int i, hand_played;
- X
- X dealer = PLAYER_NORTH;
- X for (i = 0; i < 4; i++) {
- X Refresh_Display ();
- X vulnerable[SIDE_EW] = vulnerable[SIDE_NS] = 0;
- X switch (hands_played % 4) {
- X case 0: break;
- X case 1: vulnerable[SIDE_EW] = 1; break;
- X case 2: vulnerable[SIDE_NS] = 1; break;
- X case 3: vulnerable[SIDE_EW] = vulnerable[SIDE_NS] = 1;
- X };
- X Display_Vulnerabilities ();
- X Display_Above_Line_Points ();
- X Display_Below_Line_Points ();
- X hand_played = 0;
- X while (!hand_played) hand_played = play_hand ();
- X dealer = player_next [dealer];
- X };
- X};
- X
- Xstatic void play_duplicate_rubber ()
- X{
- X int round = 0;
- X int i, hand_played;
- X
- X dealer = PLAYER_NORTH;
- X for (i = 0; i < 16; i++) {
- X Refresh_Display ();
- X vulnerable[SIDE_EW] = vulnerable[SIDE_NS] = 0;
- X switch (round) {
- X case 0: break;
- X case 1: vulnerable[SIDE_EW] = 1; break;
- X case 2: vulnerable[SIDE_NS] = 1; break;
- X case 3: vulnerable[SIDE_EW] = vulnerable[SIDE_NS] = 1;
- X };
- X Display_Vulnerabilities ();
- X Display_Above_Line_Points ();
- X Display_Below_Line_Points ();
- X hand_played = 0;
- X while (!hand_played) hand_played = play_hand ();
- X round += 1;
- X if ((i % 4) == 3) round += 1;
- X round %= 4;
- X dealer = player_next [dealer];
- X };
- X};
- X
- Xstatic void play_imp_rubber ()
- X{
- X int round = 0;
- X int i, hand_played;
- X
- X dealer = PLAYER_NORTH;
- X for (i = 0; i < 16; i++) {
- X Refresh_Display ();
- X vulnerable[SIDE_EW] = vulnerable[SIDE_NS] = 0;
- X switch (round) {
- X case 0: break;
- X case 1: vulnerable[SIDE_NS] = 1; break;
- X case 2: vulnerable[SIDE_EW] = 1; break;
- X case 3: vulnerable[SIDE_EW] = vulnerable[SIDE_NS] = 1;
- X };
- X Display_Vulnerabilities ();
- X Display_Above_Line_Points ();
- X Display_Below_Line_Points ();
- X hand_played = 0;
- X while (!hand_played) hand_played = play_hand ();
- X round += 1;
- X if ((i % 4) == 3) round += 1;
- X round %= 4;
- X dealer = player_next [dealer];
- X };
- X};
- X
- Xint recovery_routine (parm)
- X int parm;
- X{
- X Terminate_Program ("PROGRAM ABORT");
- X};
- X
- Xint Quit_program ()
- X{
- X Clear_Status_Display ();
- X Continue_Comment_Display ();
- X Refresh_Display ();
- X if (input_answer("ARE YOU SURE YOU WISH TO QUIT? ")) {
- X abort_flag = 1;
- X send_player_message ("QUIT");
- X reset_network ();
- X clear_screen ();
- X Reset_Terminal ();
- X exit (0);
- X };
- X};
- X
- Xint quit_error_routine ()
- X{
- X if (!abort_flag) {
- X abort_flag = 1;
- X clear_screen ();
- X Reset_Terminal ();
- X };
- X kill (getpid(), SIGTRAP);
- X};
- X
- Xint socket_recovery_routine (parm)
- X int parm;
- X{
- X reset_network ();
- X Terminate_Program ("THE NETWORK CONNECTIONS HAVE BEEN BROKEN!");
- X};
- X
- Xint system_call_error_routine (parm)
- X int parm;
- X{
- X if (!abort_flag) {
- X abort_flag = 1;
- X reset_network ();
- X Display_Player_Comment ("MODERATOR", "INTERRUPTED SYSTEM CALL");
- X };
- X Terminate_Program ("MODERATOR", "PROGRAM TERMINATING");
- X};
- X
- Xint access_error_routine (parm)
- X int parm;
- X{
- X if (!abort_flag) {
- X abort_flag = 1;
- X send_player_message ("QUIT");
- X reset_network ();
- X Display_Player_Comment ("MODERATOR",
- X "ACCESS VIOLATION!! YOU HAVE FOUND A BUG IN THE PROGRAM.");
- X Display_Player_Comment ("MODERATOR", "PROGRAM TERMINATING");
- X input_acknowledgment (-1);
- X };
- X clear_screen ();
- X Reset_Terminal ();
- X kill (getpid(), SIGTRAP);
- X};
- X
- Xint Terminate_Program (termination_message)
- X char *termination_message;
- X{
- X if (!abort_flag) {
- X abort_flag = 1;
- X send_player_message ("QUIT");
- X reset_network ();
- X Refresh_Display ();
- X Display_Player_Comment ("MODERATOR", termination_message);
- X input_acknowledgment (-1);
- X };
- X clear_screen ();
- X Reset_Terminal ();
- X exit (0);
- X};
- X
- Xparameter_error ()
- X{
- X printf ("First player starts the program on his machine with\n");
- X printf (" okbridge [-c] [-d] [-e] [-i] [-R] <seat> <name> \n%s\n%s\n",
- X " [-p portno] [-r replay-file] [-l load-file] [-L log-file]",
- X " [-z# [zlog-file]]");
- X printf ("Others connect with\n");
- X printf (" okbridge [-c] [-d] [-e] [-i] [-R] %s\n%s\n",
- X "<seat> <name> <host>"," [ ... additional parameters ... ]");
- X printf ("<seat> is one of the characters n, s, e, w\n");
- X printf ("<name> is your identifying name (ex. 'steve')\n");
- X printf ("<host> is the internet name of the first player's machine\n\n");
- X printf ("-c is for Chicago scoring\n");
- X printf ("-d is for Duplicate scoring\n");
- X printf ("-e is for Email duplicate scoring\n");
- X printf ("-i is for simulated IMP scoring\n");
- X printf (" NOTE: Only north can choose the scoring option.\n\n");
- X printf ("-p portno specifies the internet port number for communications\n");
- X printf ("-r replay-file specifies an email duplicate file for replay\n");
- X printf ("-l load-file specifies an email duplicate file for loading\n");
- X printf ("-L log-file specifies a logfile file saving the results of play\n");
- X printf ("-z# zlog-file specifies a table number & Zhang-format log file\n");
- X exit (1);
- X};
- X
- Xstatic void parse_position_parameter (position_string)
- X char *position_string;
- X{
- X char ch;
- X
- X if (strlen(position_string) == 1) {
- X ch = *position_string;
- X switch (ch) {
- X case 'n':
- X case 'N':
- X local_player = PLAYER_NORTH;
- X return;
- X case 'e':
- X case 'E':
- X local_player = PLAYER_EAST;
- X return;
- X case 's':
- X case 'S':
- X local_player = PLAYER_SOUTH;
- X return;
- X case 'w':
- X case 'W':
- X local_player = PLAYER_WEST;
- X return;
- X };
- X };
- X printf ("Error -- unrecognized <seat> name: %s\n", position_string);
- X parameter_error ();
- X};
- X
- Xtypedef void (*signal_handler) ();
- X
- Xmain (argc, argv)
- Xint argc; char **argv;
- X{
- X int error_value; /* error return from setjmp/signal */
- X int argi; /* index of current argument being processed */
- X int posi; /* index of next positional parameter to process */
- X char *filename; /* filename specified for log file on command line*/
- X char filename_buf[80];
- X FILE *fp; /* used only for checking the existence of files */
- X
- X /* Various signal handlers: */
- X int recovery_routine (), Quit_program (), socket_recovery_routine (),
- X quit_error_routine (), access_error_routine (),
- X system_call_error_routine ();
- X
- X#define current_arg (argv[argi])
- X#define next_arg argi++
- X#define more_args (argi < argc)
- X
- X#ifdef DEBUG
- X/* In earlier versions of the program, we have been having some problems
- X with occasional segmentation faults during the bidding. This code
- X asks the system to create a core file if there is a segmentation fault.
- X */
- X struct rlimit rlp;
- X
- X getrlimit (RLIMIT_CORE, &rlp);
- X rlp.rlim_cur = rlp.rlim_max;
- X setrlimit (RLIMIT_CORE, &rlp);
- X#endif
- X local_player = -1;
- X scoring_mode = RUBBER_SCORING;
- X Read_Initialization_File ();
- X
- X argi = 1;
- X posi = 1;
- X while (more_args) {
- X if(*current_arg == '-') {
- X /* process a position-independent parameter. */
- X if (!strcmp(current_arg, "-c")) {
- X /* Chicago scoring. */
- X scoring_mode = CHICAGO_SCORING;
- X } else if (!strcmp(current_arg, "-d")) {
- X scoring_mode = DUPLICATE_SCORING;
- X } else if (!strcmp(current_arg, "-e")) {
- X scoring_mode = EMAIL_SCORING;
- X } else if (!strcmp(current_arg, "-i")) {
- X scoring_mode = IMP_SCORING;
- X } else if (!strcmp(current_arg, "-R")) {
- X scoring_mode = RUBBER_SCORING;
- X } else if (!strcmp(current_arg, "-p")) {
- X next_arg;
- X if (!more_args) {
- X printf ("Error -- port number must follow -p parameter\n");
- X parameter_error ();
- X };
- X network_port = atoi (current_arg);
- X if (!network_port) {
- X printf ("Error: %s\n",
- X "-p parameter requires a positive port number");
- X parameter_error ();
- X };
- X } else if (!strcmp(current_arg, "-r")) {
- X next_arg;
- X if (!more_args) {
- X printf ("Error -- replay filename must follow -r parameter\n");
- X parameter_error ();
- X };
- X if ((fp = fopen(current_arg,"r")) == NULL) {
- X printf ("Error -- could not open replay file %s",
- X current_arg);
- X parameter_error ();
- X };
- X fclose (fp);
- X autoload_file = strdup(current_arg);
- X autosave_file = strdup(current_arg);
- X scoring_mode = EMAIL_SCORING;
- X } else if (!strcmp(current_arg, "-l")) {
- X next_arg;
- X if (!more_args) {
- X printf ("Error -- load filename must follow -l parameter\n");
- X parameter_error ();
- X };
- X if ((fp = fopen(current_arg,"r")) == NULL) {
- X printf ("Error -- could not open autoload file %s",
- X current_arg);
- X parameter_error ();
- X };
- X fclose (fp);
- X autoload_file = strdup(current_arg);
- X scoring_mode = EMAIL_SCORING;
- X } else if (!strcmp(current_arg, "-L")) {
- X if (logfile != NULL) fclose (logfile);
- X next_arg;
- X if (!more_args) {
- X printf("Error -- logfile filename must follow -L parameter\n");
- X parameter_error ();
- X };
- X if (current_arg[0] == '+') {
- X filename = current_arg + 1;
- X logfile = fopen (filename, "a");
- X } else {
- X filename = current_arg;
- X logfile = fopen (filename, "w");
- X };
- X if (logfile == NULL) {
- X printf ("Error -- Could not open log file %s: %s\n", filename,
- X sys_errlist[errno]);
- X parameter_error ();
- X };
- X } else if ((current_arg[0] == '-') && (current_arg[1] == 'z')) {
- X table_no = atoi (current_arg+2);
- X if (table_no == 0) {
- X printf ("Error in table number for Zhang mode: %s\n",
- X current_arg+2);
- X parameter_error ();
- X };
- X if ((argi < argc-1) && (argv[argi+1][0] != '-')) {
- X next_arg;
- X if (current_arg[0] == '+') {
- X filename = current_arg+1;
- X zhang_logfile = fopen (filename, "a");
- X } else {
- X filename = current_arg;
- X zhang_logfile = fopen(filename, "w");
- X };
- X } else {
- X sprintf (filename_buf, "okb_%s_rec", current_arg+2);
- X filename = filename_buf;
- X zhang_logfile = fopen (filename, "a");
- X };
- X if (zhang_logfile == NULL) {
- X printf ("Error -- Could not open zhang log file %s: %s\n",
- X filename, sys_errlist[errno]);
- X parameter_error ();
- X };
- X } else {
- X printf ("Error -- unrecognized parameter: %s\n", current_arg);
- X parameter_error ();
- X };
- X } else {
- X /* Process a positional parameter. */
- X switch (posi) {
- X case 1:
- X parse_position_parameter (current_arg);
- X break;
- X case 2:
- X local_player_name = strdup(current_arg);
- X break;
- X case 3:
- X server_name = strdup(current_arg);
- X server_mode = 0;
- X break;
- X default:
- X printf ("Error -- too many parameters given.\n");
- X parameter_error ();
- X };
- X posi++;
- X };
- X next_arg;
- X };
- X if ((local_player == -1) || (local_player_name == NULL)) {
- X printf ("Error -- not enough parameters were given.\n");
- X parameter_error ();
- X };
- X if (strlen(local_player_name) > 8)
- X local_player_name[8] = '\0';
- X player_names[local_player] = local_player_name;
- X
- X#ifdef LOOPBACK_MODE
- X local_player = PLAYER_NORTH;
- X#endif
- X
- X#ifdef TWOPLAYER_MODE
- X local_player = local_player % 2;
- X#endif
- X
- X
- X game_mode = STARTUP_MODE;
- X dealer = PLAYER_NORTH;
- X above_line[SIDE_NS] = above_line[SIDE_EW] = 0;
- X below_line[SIDE_NS] = below_line[SIDE_EW] = 0;
- X
- X /* Initialize the state of the email duplicate variables: */
- X total_no_deals = current_deal_no = 0;
- X replaying_mode = 0;
- X email_record = NULL;
- X current_board = NULL;
- X
- X abort_flag = 0;
- X#ifdef SIGABRT
- X signal (SIGABRT, (signal_handler) recovery_routine);
- X#endif
- X signal (SIGINT, (signal_handler) Quit_program);
- X signal (SIGPIPE, (signal_handler) socket_recovery_routine);
- X signal (SIGURG, (signal_handler) socket_recovery_routine);
- X
- X signal (SIGQUIT, (signal_handler) quit_error_routine);
- X signal (SIGFPE, (signal_handler) access_error_routine);
- X signal (SIGILL, (signal_handler) access_error_routine);
- X signal (SIGBUS, (signal_handler) access_error_routine);
- X signal (SIGSEGV, (signal_handler) access_error_routine);
- X signal (SIGSYS, (signal_handler) system_call_error_routine);
- X
- X
- X error_value = setjmp (error_return);
- X if (error_value != 0)
- X Terminate_Program ("SIGNAL RECEIVED");
- X
- X randomize ();
- X
- X /* The order of the following initialization calls should not
- X be changed. */
- X Initialize_Input_Buffers ();
- X Initialize_Terminal ();
- X initialize_help_system ();
- X Initialize_Display ();
- X initialize_network ();
- X Initialize_Input ();
- X
- X Display_Player_Comment
- X ("MODERATOR",
- X "WELCOME TO OKBRIDGE, COPYRIGHT (C) 1990, 1991 BY MATTHEW CLEGG");
- X Display_Player_Comment ("MODERATOR",
- X "TYPE /HELP FOR INSTRUCTIONS ABOUT THIS PROGRAM");
- X
- X
- X/*
- X Display_Player_Comment ("MODERATOR",
- X "WARNING!! THIS VERSION OF OKBRIDGE IS UNSTABLE AND MAY CRASH!!");
- X*/
- X
- X hands_played = 0;
- X while (1) {
- X switch (scoring_mode) {
- X case RUBBER_SCORING:
- X play_rubber ();
- X break;
- X case CHICAGO_SCORING:
- X play_chicago_rubber();
- X break;
- X case DUPLICATE_SCORING:
- X case EMAIL_SCORING:
- X play_duplicate_rubber();
- X break;
- X case IMP_SCORING:
- X play_imp_rubber();
- X break;
- X }
- X };
- X
- X};
- X
- END_OF_FILE
- if test 49783 -ne `wc -c <'bridge.c'`; then
- echo shar: \"'bridge.c'\" unpacked with wrong size!
- fi
- # end of 'bridge.c'
- fi
- if test -f 'helpfile.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'helpfile.h'\"
- else
- echo shar: Extracting \"'helpfile.h'\" \(55 characters\)
- sed "s/^X//" >'helpfile.h' <<'END_OF_FILE'
- Xchar *help_file_name="/usr/local/games/okbridge.help";
- END_OF_FILE
- if test 55 -ne `wc -c <'helpfile.h'`; then
- echo shar: \"'helpfile.h'\" unpacked with wrong size!
- fi
- # end of 'helpfile.h'
- fi
- echo shar: End of archive 2 \(of 7\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 7 archives.
- rm -f ark[1-9]isdone
- echo creating input.c from input.c.aa and input.c.ab
- cat input.c.aa input.c.ab >input.c
- rm -f input.c.aa input.c.ab
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-