home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume13 / okbridge / part02 < prev    next >
Encoding:
Internet Message Format  |  1992-01-12  |  53.4 KB

  1. Path: uunet!zephyr.ens.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v13i017:  okbridge - computer-mediated bridge game, Part02/07
  5. Message-ID: <2276@masterCNA.TEK.COM>
  6. Date: 10 Jan 92 16:44:35 GMT
  7. Sender: news@masterCNA.TEK.COM
  8. Lines: 1708
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: mclegg@cs.UCSD.EDU (Matthew Clegg)
  12. Posting-number: Volume 13, Issue 17
  13. Archive-name: okbridge/Part02
  14. Environment: BSD-derived Unix, curses, sockets
  15.  
  16.  
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 2 (of 7)."
  25. # Contents:  MakeDistrib bridge.c helpfile.h
  26. # Wrapped by billr@saab on Fri Jan 10 08:31:28 1992
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'MakeDistrib' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'MakeDistrib'\"
  30. else
  31. echo shar: Extracting \"'MakeDistrib'\" \(578 characters\)
  32. sed "s/^X//" >'MakeDistrib' <<'END_OF_FILE'
  33. X#/bin/csh -f
  34. X#
  35. X# This shell script creates the compress okbridge tar file which
  36. X# is distributed.  Unfortunately, it seems that the "make" command
  37. X# on some systems is not smart enough to handle the work which is
  38. X# done by this file.
  39. X#
  40. Xsetenv MAJOR `grep 'major_rev.*=' globals.h | sed 's@.*"\(.*\)".*@\1@'`
  41. Xsetenv MINOR `grep 'minor_rev.*=' globals.h | sed 's@.*"\(.*\)".*@\1@'`
  42. Xsetenv OKFILENAME okbridge-$MAJOR$MINOR
  43. Xsetenv OKBDIR `pwd | sed "s@.*/\([^/]*\)@\1@"`
  44. Xcd .. 
  45. Xecho Ztar\'ing $OKBDIR into $OKFILENAME.tar.Z
  46. Xtar -cf $OKFILENAME.tar $OKBDIR
  47. Xcompress $OKFILENAME.tar
  48. END_OF_FILE
  49. if test 578 -ne `wc -c <'MakeDistrib'`; then
  50.     echo shar: \"'MakeDistrib'\" unpacked with wrong size!
  51. fi
  52. chmod +x 'MakeDistrib'
  53. # end of 'MakeDistrib'
  54. fi
  55. if test -f 'bridge.c' -a "${1}" != "-c" ; then 
  56.   echo shar: Will not clobber existing file \"'bridge.c'\"
  57. else
  58. echo shar: Extracting \"'bridge.c'\" \(49783 characters\)
  59. sed "s/^X//" >'bridge.c' <<'END_OF_FILE'
  60. X/* bridge.c
  61. X ! 
  62. X ! Copyright (C) 1990,1991 by Matthew Clegg
  63. X ! 
  64. X ! This program may be copied and distributed freely.  Please do not
  65. X ! charge money for this program or for any program derived from it.
  66. X ! If you modify this program, then include a notice stating plainly
  67. X ! that your program is derived from the okbridge program and is not
  68. X ! the same as the official okbridge program.
  69. X !
  70. X ! I welcome any suggestions for improvement to okbridge, and 
  71. X ! I would be especially happy to receive improved source code.
  72. X ! If you have comments or suggestions, or if you would like to
  73. X ! join the okbridge mailing list, then write to
  74. X !
  75. X !   mclegg@cs.ucsd.edu
  76. X !
  77. X *
  78. X * General Description:
  79. X *
  80. X * This file contains an implementation of a computer-moderated
  81. X * bridge program.  The program serves as a mediator allowing
  82. X * four people on separate systems to cooperate in a bridge game.
  83. X * The game is screen oriented and interactive, although the display
  84. X * is very simple.  The program handles the shuffling and dealing
  85. X * of the cards, and it prompts each player for input when it is
  86. X * his turn.  The lower area of the screen is a dialog box, where
  87. X * players may enter comments that will be seen by the others.
  88. X *
  89. X * Command Line:
  90. X *
  91. X *         okbridge p [name [remote-server]]
  92. X *
  93. X * Where
  94. X *
  95. X * p    is one of the characters: 'n', 's', 'e', or 'w'.  This specifies
  96. X *      which position the player wishes to have in the game.  The players
  97. X *      should agree beforehand who will take which position.  If two
  98. X *      players choose the same position, the program will not work
  99. X *      correctly.
  100. X *
  101. X * name is an optional name which will be used to identify the player.
  102. X *      If this is omitted, then the players position p will be used.
  103. X *
  104. X * remote-server
  105. X *      is the name of the remote machine where the 'server' will be
  106. X *      playing.  For the sake of establishing the network communications,
  107. X *      exactly one of the players must be a server.  The choice of the
  108. X *    server does not affect how the game plays.  If remote-server is
  109. X *      not specified, then this player will assume the role of the server.
  110. X *
  111. X * After processing the command line parameters, the program will first
  112. X * display a startup screen.  Then, it will attempt to establish the network
  113. X * connections with the other players.  After the connections have been
  114. X * established, the cards will be dealt and play will commence.
  115. X *
  116. X * The program automatically prompts for bids and plays at the appropriate
  117. X * times.  When it is not time for a player to enter a bid or play, the
  118. X * program will remain in a 'talk' mode, where the player can type messages
  119. X * that will be sent to the other players.  There are also a few special
  120. X * commands for controlling the game.  These commands are all of the
  121. X * form:
  122. X *      /command [parameters]
  123. X * For more information on the commands that are available, see the
  124. X * input.h file.
  125. X *
  126. X *
  127. X * Structure of the program:
  128. X *
  129. X * One of the chief principles in designing this game was portability.
  130. X * With this principle in mind, the game has been divided into a
  131. X * number of separate modules.  Roughly speaking, the modules in the
  132. X * game can be grouped into two parts: the bridge program and the
  133. X * operating system interface.  The bridge program consists of the
  134. X * modules DISPLAY, INPUT and BRIDGE.  These modules are rather
  135. X * complicated and represent the heart of the bridge program.
  136. X * The operating system interface consists of the modules TERMINAL
  137. X * and NETWORK.  These modules have been made as simple as possible.
  138. X * Their purpose is solely to insulate the first three modules from
  139. X * the particular operating system in use.
  140. X *
  141. X * DISPLAY.  This module contains the primitives for displaying the
  142. X * actions of the game on the screen.  This module calls only routines
  143. X * in the TERMINAL module, and does not call the operating system
  144. X * directly.  (This explains, for example, why the display is so
  145. X * rudimentary.)
  146. X *
  147. X * INPUT.  These routines are for reading the user's response from
  148. X * the terminal.  There are two sources of complexities in this module.
  149. X * One is that there is a parser which is relatively large (but not
  150. X * very sophisticated) for processing input by the player and by the
  151. X * network.  All of the actions of the program are command-driven.
  152. X * The other source of complexity is that we have to monitor both the
  153. X * keyboard and the network simultaneously at all times, and we have to
  154. X * assume that some of the input from the network will come out of order.
  155. X *
  156. X * MAIN.  This module contains the procedures which represent the
  157. X * rules of the game.
  158. X *
  159. X * TERMINAL.  This module contains entry-points for the most primitive
  160. X * I/O operations with the terminal.  We assume that the screen is
  161. X * (at least) 24 x 80, that the cursor is addressable, and that
  162. X * it is possible to check for the availability of an input character
  163. X * without actually reading it.  All of the I/O operations to the terminal
  164. X * are directed through this module.
  165. X *
  166. X * NETWORK.  This module contains the primitives for network I/O.
  167. X * Every message that is sent by a player is broadcast to the other
  168. X * three players.
  169. X *
  170. X * PS.  This is a simple module for breaking up an input string into
  171. X * a sequence of keywords.  It is used only by the parser in the INPUT
  172. X * module.
  173. X *
  174. X * HELP.  This is a module for providing on-line instructions about how
  175. X * to use the program.  The help module reads a list of topics from a
  176. X * help file.  Each topic then refers to another file containing an
  177. X * explanation of that topic.
  178. X *
  179. X *
  180. X * Future improvements:
  181. X *
  182. X * 1.  It would be nice to be able to recover from a dropped connection.
  183. X *     The network protocol assumes that the connections are stable and will
  184. X *     last for the duration of the game.  However, it has been my
  185. X *     observation that with some networks, the connections may be
  186. X *     broken occasionally.  When this happens, the okbridge program has
  187. X *     to be restarted from the beginning by all of the players.
  188. X *
  189. X * 2.  It would be nice to implement a protocol for dealing the
  190. X *     cards where each player would know only his own cards.
  191. X *
  192. X *
  193. X */
  194. X#define _BRIDGE_
  195. X#ifdef __TURBOC__
  196. X#include <alloc.h>
  197. X#include <stdlib.h>
  198. X#else
  199. X#define random(n) ((rand()/64) % (n))
  200. X#include <sys/time.h>
  201. X#include <sys/resource.h>
  202. X#endif
  203. X#include <sys/types.h>
  204. X#include <setjmp.h>
  205. X#include <signal.h>
  206. X#include <stdio.h>
  207. X#ifdef AIX
  208. X#include <time.h>
  209. X#endif
  210. X#include <string.h>
  211. X#include "globals.h"
  212. X#include "ps.h"
  213. X#include "display.h"
  214. X#include "input.h"
  215. X#include "network.h"
  216. X#include "terminal.h"
  217. X#include "help.h"
  218. X#include "code.h"
  219. X#include "email.h"
  220. X
  221. Xextern int errno;
  222. Xextern char *sys_errlist[];
  223. X
  224. Xextern int network_port;
  225. Xextern int server_mode;
  226. Xextern char *server_name;
  227. X
  228. Xextern char *autoload_file, *autosave_file;
  229. X
  230. XFILE *logfile = NULL;  /* The file where we log the hands that have
  231. X            . been played. */
  232. XFILE *zhang_logfile = NULL; 
  233. X                       /* The file where we log hands that are written
  234. X              in Zhang's format. */
  235. Xint table_no = -1;     /* Table number printed in Szhang format log files. */
  236. Xchar *month_names [] =
  237. X  { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept",
  238. X    "Oct", "Nov", "Dec"};
  239. Xhand saved_hands [4];  /* The cards as they were dealt. */
  240. Xhand saved_plays [4];  /* The cards as they were played. */
  241. Xint  leading_play [14];/* The leading player for each trick. */
  242. X
  243. Xchar *local_player_name = NULL;
  244. X    /* This variable stores the name of the local player until
  245. X       we know what his/her seat position is. */
  246. X
  247. X
  248. Xstatic jmp_buf error_return;
  249. Xstatic int     abort_flag;
  250. Xtypedef int declarations [5];
  251. Xstatic  declarations declarers [2];
  252. X
  253. X/* The following table is used for computing scores according to a
  254. X   "simulated IMP" scoring system.   Much of the code for this scoring
  255. X   system has been contributed by Ya-Xiang Yuan. */
  256. X
  257. Xstatic int IMP_scoring_table [] = {
  258. X  20, 50, 80, 120, 160, 210, 260, 310, 360, 430, 500,
  259. X  600, 750, 900, 1100, 1300, 1500, 1750, 2000, 2500, 3000,
  260. X  3500, 4000, 4500, 9999};
  261. X
  262. Xstatic int IMP_score_conversion (pt)
  263. X     int pt;
  264. X/* This procedure converts a duplicate score into a corresponding IMP
  265. X . score.  This code was contributed by Zhenjun Wu of Ohio State Univ. */
  266. X{
  267. X  int i,apt;
  268. X  static int IMP_scoring_table [] = {
  269. X    10, 40, 80, 120, 160, 210, 260, 310, 360, 420, 490,
  270. X    590, 740, 890, 1090, 1290, 1490, 1740, 1990, 2240, 2490,
  271. X    2990, 3490, 3990, 9999};
  272. X  
  273. X  if (! pt) return 0;
  274. X  apt = (pt>0)? pt:-pt ;
  275. X  for (i = 0; apt > IMP_scoring_table[i]; i++);
  276. X  return ( (pt>0)? i:-i );
  277. X}
  278. X
  279. X
  280. Xchar *strdup (s)
  281. X    char *s;
  282. X{
  283. X    char *p, *q;
  284. X
  285. X    q = p = (char *) malloc (strlen(s) + 2);
  286. X    while (*s != '\0')
  287. X        *(q++) = *(s++);
  288. X    *q = '\0';
  289. X    return (p);
  290. X};
  291. X
  292. X#ifdef NO_ISSPACE
  293. Xint isspace (ch)
  294. X     char ch;
  295. X{
  296. X  return ((ch == ' ') || (ch == '\t') || (ch == '\n'));
  297. X};
  298. X#endif
  299. X
  300. Xrandomize ()
  301. X{
  302. X        srand (time(NULL));
  303. X};
  304. X
  305. X
  306. X
  307. Xstatic char *long_suit_names [] = {"CLUB", "DIAMOND", "HEART", "SPADE",
  308. X                   "NO TRUMP"};
  309. X
  310. X
  311. Xstatic void format_suit (buffer, h, s)
  312. X     char *buffer; hand h; int s;
  313. X{
  314. X  int i;
  315. X
  316. X  for (i = 12; i >= 0; i--)
  317. X    if (h[s + i])
  318. X      *(buffer++) = *rank_names[i];
  319. X  *buffer = '\0';
  320. X};
  321. X
  322. Xstatic void log_last_hand ()
  323. X/* Writes the last hand played to the logfile, provided that the logfile
  324. X . is open.  If the logfile is not open, then does nothing.
  325. X */
  326. X{
  327. X  int i, j, down, excess, score, contractor, passes, round, lead;
  328. X  int player_no;
  329. X  Email_Score *slist;
  330. X  Email_Pair  *pair;
  331. X  char format_buffer [80];
  332. X  char *north_name, *south_name, *east_name, *west_name;
  333. X  time_t current_time;
  334. X
  335. X  if (logfile == NULL) return;
  336. X
  337. X  time (¤t_time);
  338. X  fprintf (logfile, "%s\n", ctime(¤t_time));
  339. X  fprintf (logfile, "DEALER:  %s\n", player_names[dealer]);
  340. X
  341. X  if (vulnerable[SIDE_NS] && vulnerable[SIDE_EW]) 
  342. X    fprintf (logfile, "BOTH SIDES VULNERABLE\n");
  343. X  else if (vulnerable[SIDE_NS])
  344. X    fprintf (logfile, "%s AND %s ARE VULNERABLE\n",
  345. X         player_names[PLAYER_NORTH], player_names[PLAYER_SOUTH]);
  346. X  else if (vulnerable[SIDE_EW])
  347. X    fprintf (logfile, "%s AND %s ARE VULNERABLE\n",
  348. X         player_names[PLAYER_EAST], player_names[PLAYER_WEST]);
  349. X  else
  350. X    fprintf (logfile, "NEITHER SIDE IS VULNERABLE.\n");
  351. X
  352. X  fprintf (logfile, "\nTHE DEAL:\n");
  353. X  fprintf (logfile, "\n%10s"," ");
  354. X  for (i = 0; i < 4; i++)
  355. X    fprintf (logfile, "     %-8s   ", player_names[i]);
  356. X  fprintf (logfile, "\n          ");
  357. X  for (i = 0; i < 4; i++)
  358. X    fprintf (logfile, "     --------   ");
  359. X  for (i = 3; i >= 0; i--) {
  360. X    fprintf (logfile, "\n%10sS    ", long_suit_names[i]);
  361. X    for (j = 0; j < 4; j++) {
  362. X      format_suit (format_buffer, saved_hands[j], i * 13);
  363. X      fprintf (logfile, "%-13s   ", format_buffer);
  364. X    };
  365. X  };
  366. X
  367. X  fprintf (logfile, "\n\n\nTHE BIDDING:\n");
  368. X  fprintf (logfile, "\n%10s"," ");
  369. X  for (i = 0; i < 4; i++)
  370. X    fprintf (logfile, "     %-8s   ", player_names[i]);
  371. X  fprintf (logfile, "\n          ");
  372. X  for (i = 0; i < 4; i++)
  373. X    fprintf (logfile, "     --------   ");
  374. X  fprintf (logfile, "\n%15s"," ");
  375. X  passes = -1;
  376. X  round = -1;
  377. X  i = 0;
  378. X  while (passes < 3) {
  379. X    if (i == dealer) round++;
  380. X    if (round >= 0) {
  381. X      fprintf (logfile, "%-8s%8s", bid_names[bids[i][round]]," ");
  382. X      if (bids[i][round] == BID_PASS) passes++;
  383. X      else passes = 0;
  384. X    } else
  385. X      fprintf (logfile, "%8s%8s", " ", " ");
  386. X    i = player_next [i];
  387. X    if (i == 0)
  388. X      fprintf (logfile, "\n%15s"," ");
  389. X  };
  390. X  fprintf (logfile, "\n\n%15sCONTRACT: %d %s", " ", contract, 
  391. X       long_suit_names [trump_suit]);
  392. X  if ((contract > 1) && (trump_suit != SUIT_NOTRUMP))
  393. X    fprintf (logfile, "S");
  394. X  if (redoubled)
  395. X    fprintf (logfile, " (REDOUBLED)");
  396. X  else if (doubled)
  397. X    fprintf (logfile, " (DOUBLED)");
  398. X  fprintf (logfile," BY %s\n", player_names[declarer]);
  399. X
  400. X  fprintf (logfile, "\n\n\nTHE PLAYING:\n");
  401. X  fprintf (logfile, "\n          ");
  402. X  for (i = 0; i < 13; i++)
  403. X    fprintf (logfile, "%2d  ", i+1);
  404. X  fprintf (logfile, "\n          ");
  405. X  for (i = 0; i < 4*13-2; i++) fprintf (logfile, "-");
  406. X  for (i = 0; i < 4; i++) {
  407. X    fprintf (logfile, "\n%8s  ", player_names[i]);
  408. X    for (j = 1; j < 14; j++) {
  409. X      if (saved_plays[i][j] != (char) (-1)) {
  410. X    lead = (leading_play[j] == i)? '*': ' ';
  411. X    fprintf (logfile, "%2s%c ", card_names[saved_plays[i][j]], lead);
  412. X      } else
  413. X    fprintf (logfile, "    ");
  414. X    };
  415. X  };
  416. X  fprintf (logfile, "\n\n          * INDICATES THE LEAD\n");
  417. X
  418. X  contractor = side_of(declarer);
  419. X/*
  420. X  fprintf (logfile, "\n\n\nTHE SCORES:\n\n");
  421. X  fprintf (logfile, "  TRICKS WON:  %2d\n", tricks[contractor]);
  422. X  fprintf (logfile, "  TRICKS LOST: %2d\n", tricks[1-contractor]);
  423. X  fprintf (logfile, "\n");
  424. X*/
  425. X  fprintf (logfile, "\n  BID %2d, ", contract);
  426. X  if (tricks[contractor] >= contract+6) {
  427. X    fprintf (logfile, " MADE %2d", tricks[contractor]-6);
  428. X    excess = tricks[contractor] - contract - 6;
  429. X    switch (scoring_mode) {
  430. X           case RUBBER_SCORING:
  431. X          fprintf (logfile, "\n\n  POINTS ABOVE THE LINE:  %5d\n",
  432. X               Rubber_score_above (excess));
  433. X          fprintf (logfile,     "  POINTS BELOW THE LINE:  %5d\n",
  434. X               Rubber_score_below ());
  435. X      break;
  436. X    case CHICAGO_SCORING:
  437. X            score = Chicago_score_made (excess, vulnerable[contractor]);
  438. X            if ((score < 100) && (hands_played%4 == 0))
  439. X        score += 100;
  440. X            fprintf (logfile, ", FOR A SCORE OF %5d\n", score);
  441. X      break;
  442. X    case DUPLICATE_SCORING:
  443. X    case EMAIL_SCORING:
  444. X    case IMP_SCORING:
  445. X            fprintf (logfile, ", FOR A SCORE OF %5d\n", 
  446. X                  Duplicate_score_made (excess, vulnerable[contractor]));
  447. X      break;
  448. X    }
  449. X  } else {
  450. X    down = contract + 6 - tricks[contractor];
  451. X    fprintf (logfile, " DOWN %2d, ", down);
  452. X    fprintf (logfile, " FOR A LOSS OF ");
  453. X    switch (scoring_mode) {
  454. X           case RUBBER_SCORING:
  455. X            fprintf (logfile, "%5d\n", Rubber_score_set (down));
  456. X      break;
  457. X    case CHICAGO_SCORING:
  458. X            fprintf (logfile, "%5d\n", 
  459. X           Chicago_score_set (down, vulnerable[contractor]));
  460. X      break;
  461. X    case DUPLICATE_SCORING:
  462. X    case EMAIL_SCORING:
  463. X    case IMP_SCORING:
  464. X            fprintf (logfile, "%5d\n", 
  465. X           Duplicate_score_set (down, vulnerable[contractor]));
  466. X      break;
  467. X    }
  468. X  };
  469. X
  470. X  if ((current_board != NULL) && (current_board->score_list->next != NULL)) {
  471. X    slist = current_board->score_list;
  472. X    fprintf (logfile, "\n");
  473. X    fprintf (logfile, "  %-8s %-8s %-8s %-8s %-6s %2s %6s %6s %6s %6s\n",
  474. X         "NORTH", "SOUTH", "EAST", "WEST", "BID", "BY", "RESULT",
  475. X         "SCORE", "NS-MP", "EW-MP");
  476. X    while (slist != NULL) {
  477. X      pair = email_record->player_list + slist->ns_pair;
  478. X      north_name = pair->ne;
  479. X      south_name = pair->sw;
  480. X      pair = email_record->player_list + slist->ew_pair;
  481. X      east_name = pair->ne;
  482. X      west_name = pair->sw;
  483. X      fprintf (logfile, "  %-8s %-8s %-8s %-8s ", north_name, south_name,
  484. X           east_name, west_name);
  485. X      sprintf (format_buffer, "%s", bid_names[slist->bid]);
  486. X      if (slist->doubled == BID_REDOUBLE)
  487. X    sprintf (format_buffer+strlen(format_buffer), "-XX");
  488. X      else if (slist->doubled == BID_DOUBLE)
  489. X    sprintf (format_buffer+strlen(format_buffer), "-X");
  490. X      fprintf (logfile, "%-6s %c  %+6d %6d %6.1f %6.1f\n", format_buffer, 
  491. X           *("NESW" + slist->contractor), slist->result, slist->ns_score,
  492. X           0.5 * ((float) slist->ns_match_points),
  493. X           0.5 * ((float) slist->ew_match_points));
  494. X      slist = slist->next;
  495. X    };
  496. X  };
  497. X
  498. X  fprintf (logfile, "\n\n");
  499. X  for (i = 0; i < 72; i++)
  500. X    fprintf (logfile, "=");
  501. X  fprintf (logfile, "\n%c\n", 12);
  502. X  fflush (logfile);
  503. X};
  504. X
  505. X
  506. Xstatic void zhang_log_last_hand ()
  507. X/* The following routine is S. Zhang's routine for writing the log file.
  508. X . This constitutes the heart of his "okbd" version of okbridge.
  509. X . It has been modified from the log_last_hand procedure
  510. X . by Shangyou Zhang, szhang@math.udel.edu.
  511. X */
  512. X{ 
  513. X  int i, j, down, excess, score, contractor, passes, round, lead;
  514. X  int r_round;
  515. X  char format_buffer [80];
  516. X  char *bid_zhang[4][20];
  517. X  char zhang[4];
  518. X  time_t current_time;
  519. X  struct tm *decoded_time;
  520. X
  521. X  zhang[0]='N'; zhang[1]='E';  zhang[2]='S'; zhang[3]='W';
  522. X
  523. X  if (zhang_logfile == NULL) return;
  524. X  for (i = 0; i < 4; i++){fprintf(zhang_logfile, 
  525. X         " %-8.8s ", player_names[i]);
  526. X    for (j = 3; j >= 0; j--) {
  527. X      format_suit (format_buffer, saved_hands[i], j * 13);
  528. X      fprintf (zhang_logfile, " %-13s", format_buffer);
  529. X    };    fprintf (zhang_logfile, "\n");
  530. X  };
  531. X
  532. X  contractor = side_of(declarer);
  533. X  fprintf(zhang_logfile, "%3d.(tab%3d)", current_deal_no, table_no);
  534. X
  535. X  fprintf (zhang_logfile,"   %6.6s-%c:", player_names[declarer],
  536. X              zhang[declarer]);   
  537. X  fprintf (zhang_logfile, "%d%1.1s", 
  538. X        contract, long_suit_names [trump_suit] );  
  539. X  if (redoubled)         fprintf (zhang_logfile, "XX"); 
  540. X  else if (doubled)      fprintf (zhang_logfile, "X ");  
  541. X  else                   fprintf (zhang_logfile, "  ");
  542. X
  543. X  if (tricks[contractor] >= contract+6) {
  544. X    fprintf (zhang_logfile, " -- Made %2d  |  ", 
  545. X         (contract == 0)? 0: tricks[contractor]-6);
  546. X  } else { down = contract + 6 - tricks[contractor];
  547. X    fprintf (zhang_logfile, " -- Down %2d  |  ", down);
  548. X  };
  549. X
  550. X  if (vulnerable[SIDE_NS] && vulnerable[SIDE_EW])  
  551. X                                fprintf (zhang_logfile, "Vul:BOTH |  ");
  552. X  else if (vulnerable[SIDE_NS]) fprintf (zhang_logfile, "Vul:N&S  |  ");
  553. X  else if (vulnerable[SIDE_EW]) fprintf (zhang_logfile, "Vul:E&W  |  ");
  554. X  else                          fprintf (zhang_logfile, "Vul:NONE |  ");
  555. X
  556. X
  557. X  if (tricks[contractor] >= contract+6) {
  558. X    if ( contractor == SIDE_NS )  {fprintf (zhang_logfile, " NS:  ");} 
  559. X                             else  fprintf (zhang_logfile, "*NS: -");
  560. X    excess = tricks[contractor] - contract - 6;
  561. X    if (contract == 0)
  562. X      fprintf (zhang_logfile, "0  ");
  563. X    else
  564. X      fprintf (zhang_logfile, "%d ", 
  565. X           Duplicate_score_made (excess, vulnerable[contractor]));
  566. X  } else {
  567. X    down = contract + 6 - tricks[contractor];
  568. X    if ( contractor == SIDE_NS )  {fprintf (zhang_logfile, " NS: -");} 
  569. X                             else  fprintf (zhang_logfile, "*NS:  ");
  570. X    fprintf (zhang_logfile, "%d ", 
  571. X    Duplicate_score_set (down, vulnerable[contractor]));
  572. X  };
  573. X
  574. X  for (i=0; i<4; i++) for (j=0; j<20; j++) bid_zhang[i][j]="  ";
  575. X
  576. X  passes = -1;  round = -1;  r_round=0;  i = 0;
  577. X  while (passes < 3) {
  578. X    if (i == dealer) round++;
  579. X    if (round >= 0) {
  580. X      bid_zhang[i][r_round]= bid_names[bids[i][round]];
  581. X      if (bids[i][round] == BID_PASS) passes++;
  582. X                                 else passes = 0;
  583. X    }
  584. X    i = player_next [i];  
  585. X    if ( (i==0) && passes<3 ) r_round++;
  586. X  };
  587. X
  588. X  for (i = 0; i < 4; i++) {
  589. X    fprintf(zhang_logfile,"\n%c-%-8.8s",zhang[i],player_names[i]);
  590. X    for (j = 1; j < 14; j++) {
  591. X      if (saved_plays[i][j] != (char) (-1)) {
  592. X    lead = (leading_play[j] == i)? '*': ' ';
  593. X    if ((lead ==' ')&&(i==3) ) lead='_';
  594. X    fprintf (zhang_logfile, "%2s%c", card_names[saved_plays[i][j]], lead);
  595. X      } else
  596. X    fprintf (zhang_logfile, "   ");
  597. X    }; fprintf (zhang_logfile, "|");
  598. X    for (j = 0; j <= r_round; j++) {
  599. X      fprintf (zhang_logfile, "%-2.2s ", bid_zhang[i][j]);
  600. X    };
  601. X  };
  602. X
  603. X  fprintf (zhang_logfile, "\n==========");
  604. X  for (i = 0; i < 13; i++)    fprintf (zhang_logfile, "%2d=", i+1);
  605. X  time (¤t_time);
  606. X  for (i = 0; i < 6; i++)     fprintf (zhang_logfile, "=%2d", i+1);
  607. X  decoded_time = localtime (¤t_time);    
  608. X  fprintf (zhang_logfile, " %s %2d\n%c\n", 
  609. X       month_names[decoded_time->tm_mon], decoded_time->tm_mday, 12);
  610. X  fflush (zhang_logfile);
  611. X};
  612. X
  613. Xint bidding_code (bid_type, level, suit)
  614. X    int bid_type, level, suit;
  615. X/* Given the bidding type, as above, and the level and suit if it is
  616. X * a contract bid, returns a unique integer in the range 0-37 associated
  617. X * with the bid.  Contract bids are ordered in increasing order, so that
  618. X * 1C is the smallest and 7NT is the largest.
  619. X */
  620. X{
  621. X    switch (bid_type) {
  622. X        case BID_PASS:       return (BID_PASS);
  623. X        case BID_DOUBLE:   return (BID_DOUBLE);
  624. X        case BID_REDOUBLE: return (BID_REDOUBLE);
  625. X        case BID_SUIT:     return (5 * (level - 1) + suit + 3);
  626. X        default:       ;
  627. X    };
  628. X    return (-1);
  629. X};
  630. Xint card_code (suit, rank)
  631. X    int suit, rank;
  632. X/* Given a suit and rank, returns a unique associated integer in the
  633. X * range 0-51.  The cards are arranged so that the 2 of clubs has code 0 and
  634. X * the ace of spades has code 51.
  635. X */
  636. X{
  637. X    return (13 * suit + rank);
  638. X};
  639. Xstatic generate_valid_bids (p, minimum_bid, double_ok, redouble_ok)
  640. X     int p, *minimum_bid, *double_ok, *redouble_ok;
  641. X/* Determines the valid bids for the player p, given that the list of
  642. X * bids made so far is stored in the global variable 'bids', and that
  643. X * the variables 'trump_suit', 'contract', 'declarer', 'doubled' and
  644. X * 'redoubled' reflect the current state of the bidding.  Computes
  645. X * the minimum contract bid which is acceptable, and computes boolean
  646. X * flags indicating whether it is ok to double or redouble.
  647. X */
  648. X{
  649. X    int bidding_side, declaring_side;
  650. X    bidding_side = side_of (p);
  651. X    if (contract > 0) {
  652. X        declaring_side = side_of (declarer);
  653. X        if (declaring_side != bidding_side) {
  654. X            *double_ok = !doubled;
  655. X            *redouble_ok = 0;
  656. X        } else {
  657. X            *double_ok = 0;
  658. X            if (doubled) *redouble_ok = !redoubled;
  659. X        };
  660. X    };
  661. X    if (contract == 0) {    /* no one has bid a contract yet */
  662. X        *minimum_bid = bidding_code(BID_SUIT, 1, SUIT_CLUBS);
  663. X        *double_ok = *redouble_ok = 0;
  664. X    } else
  665. X        *minimum_bid = 1 + bidding_code(BID_SUIT, contract,
  666. X                        trump_suit);
  667. X};
  668. Xstatic update_bidding_list (p, bid)
  669. X     int p, bid;
  670. X/* Enters a new bid for player p.  Assumes of course that it is p's
  671. X * turn to bid and that the bid is legal.  Updates the variables:
  672. X * trump_suit, contract, declarer, doubled, redoubled, bids, no_bids
  673. X */
  674. X{
  675. X    int round, i, side;
  676. X    round = no_bids / 4;
  677. X    bids [p][round] = bid;
  678. X    if (bid == BID_PASS) {
  679. X        ;
  680. X    } else if (bid == BID_DOUBLE) {
  681. X        doubled = 1;
  682. X    } else if (bid == BID_REDOUBLE) {
  683. X        redoubled = 1;
  684. X    } else {
  685. X        doubled = redoubled = 0;
  686. X        trump_suit = trumpsuit_of (bid);
  687. X        contract   = contract_of (bid);
  688. X        side = side_of(p);
  689. X        if (declarers[side][trump_suit] < 0)
  690. X            declarers[side][trump_suit] = p;
  691. X        declarer = declarers[side][trump_suit];
  692. X                dummy    = player_partner[declarer];
  693. X    };
  694. X    no_bids += 1;
  695. X};
  696. Xstatic generate_valid_plays (p, h)
  697. X     int p; hand h;
  698. X/* Generates a list of valid plays for player p.  The list of valid
  699. X * plays is determined by examining the global variables 'leader' and
  700. X * 'current_hand'.  The valid plays are stored as a boolean string
  701. X * in h, so that h[c] == true iff it is legal to play card c.
  702. X */
  703. X{
  704. X    int i, n, lead_suit;
  705. X    if (p == leader) {
  706. X        for (i = 0; i < 52; i++)
  707. X            h[i] = current_hand[p][i];
  708. X    } else {
  709. X        lead_suit = suit_of(plays[leader]);
  710. X        n = 0;
  711. X        for (i = 0; i < 52; i++) {
  712. X            h[i] =  current_hand[p][i] &&
  713. X                (suit_of(i) == lead_suit);
  714. X            if (h[i]) n += 1;
  715. X        };
  716. X        if (n == 0)
  717. X            for (i = 0; i < 52; i++)
  718. X                h[i] = current_hand[p][i];
  719. X    };
  720. X};
  721. Xstatic int outranks (c1, c2)
  722. X    int c1, c2;
  723. X/* Returns true if c1 outranks c2, according to the current trump_suit.
  724. X * If c1 and c2 are of different suits, neither of which is the trump_suit,
  725. X * then returns false.
  726. X */
  727. X{
  728. X    if (suit_of (c1) == suit_of (c2))
  729. X        return (rank_of(c1) > rank_of(c2));
  730. X    else
  731. X        return (suit_of (c1) == trump_suit);
  732. X};
  733. X
  734. Xstatic int play_hand ()
  735. X/* Plays one hand of bridge.  Handles the dealing, bidding, play and scoring
  736. X * of the hand.  Returns 1 if a hand is played, or 0 if all 4 players
  737. X * pass in the first round of bidding.
  738. X */
  739. X{
  740. X    /* General purpose variables: */
  741. X    int i, j, c1, c2, c3, c4;
  742. X    Email_Comment *ec;
  743. X    /* Variables used in the bidding stage: */
  744. X    int bidder, bid, no_passes, double_ok, redouble_ok,
  745. X        minimum_bid, round, highest_bid;
  746. X    /* Variables used in the playing stage: */
  747. X    int pos, card, winning_card, winning_player;
  748. X    hand legal_plays; 
  749. X    char claim_message[80];
  750. X
  751. X    /* Variables used in updating the scores: */
  752. X    int contractor, excess, down, penalty, honors_bonus,
  753. X            highcard_points, base_score;
  754. X    char *honors_bonus_string, honors_message[80];
  755. X    int email_score,  /* +/- duplicate scored recorded for email play */
  756. X            email_result; /* +tricks made, or -tricks down. */
  757. X    Email_Score *score;
  758. X
  759. X    /* Variables used for debugging: */
  760. X    int save_pos;
  761. X    tricks [SIDE_NS] = tricks [SIDE_EW] = 0;
  762. X    Display_Tricks_Taken ();
  763. X    game_mode = DEALING_MODE;
  764. X
  765. X    input_hand (current_deal);
  766. X    if (current_board != NULL)
  767. X        for (ec = current_board->pre_script; ec != NULL; ec = ec->next)
  768. X            Broadcast_Comment (ec->comment);
  769. X
  770. X    for (i = 0; i < 52; i++) {
  771. X        for (j = 0; j < 4; j++) current_hand[j][i] = 0;
  772. X        current_hand[current_deal[i]][i] = 1;
  773. X    };
  774. X    for (i = 0; i < 4; i++)
  775. X      for (j = 0; j < 52; j++){
  776. X        saved_hands[i][j] = current_hand[i][j];
  777. X        saved_plays[i][j] = -1;
  778. X      };
  779. X    no_bids = 0;
  780. X    doubled = redoubled = 0;
  781. X    bidder = dealer;
  782. X    no_passes = 0;
  783. X    contract = 0;
  784. X    trump_suit = SUIT_NOTRUMP;
  785. X    game_mode = BIDDING_MODE;
  786. X    Display_Vulnerabilities ();
  787. X    Display_Bidding_Board ();
  788. X    for (i = 0; i < 10; i++)
  789. X      for (j = 0; j < 3; j++)
  790. X        bids [j][i] = -1;
  791. X    for (i = 0; i < 5; i++)
  792. X        declarers[SIDE_NS][i] = declarers[SIDE_EW][i] = -1;
  793. X    round = 1;
  794. X    Display_Hand_for_Bidding (local_player);
  795. X    while ((no_passes < 3) || (round == 1)) {
  796. X        generate_valid_bids (bidder, &minimum_bid, &double_ok,
  797. X            &redouble_ok);
  798. X        Display_Bidder (bidder);
  799. X#ifdef LOOPBACK_MODE
  800. X        local_player = bidder;
  801. X        Display_Hand_for_Bidding (bidder);
  802. X        bid = input_bid (local_player, minimum_bid, double_ok,
  803. X                 redouble_ok);
  804. X        local_player = PLAYER_NORTH;
  805. X#else
  806. X#ifdef TWOPLAYER_MODE
  807. X        if ((bidder % 2) == (local_player % 2))
  808. X          Display_Hand_for_Bidding (bidder);
  809. X        bid = input_bid ((bidder % 2), minimum_bid, double_ok,
  810. X
  811. X                 redouble_ok);
  812. X#else
  813. X        bid = input_bid (bidder, minimum_bid, double_ok,
  814. X                 redouble_ok);
  815. X#endif
  816. X#endif
  817. X        update_bidding_list (bidder, bid);
  818. X        Display_Bid (round, bidder);
  819. X        if (bid == BID_PASS)
  820. X            no_passes++;
  821. X        else
  822. X            no_passes = 0;
  823. X        if ((bid != BID_PASS) && (bid != BID_DOUBLE) &&
  824. X            (bid != BID_REDOUBLE))
  825. X            highest_bid = bid;
  826. X        bidder = player_next[bidder];
  827. X        if (bidder == dealer) round++;
  828. X    };
  829. X    if (contract == 0) {
  830. X      Display_Status ("TOSSING IN THE HAND -- PRESS RETURN TO PROCEED");
  831. X      Record_Email_Score (current_board, ns_pair_no, ew_pair_no,
  832. X        BID_PASS, 0, PLAYER_NORTH, 0, 0);
  833. X      tricks[SIDE_NS] = 7;
  834. X      tricks[SIDE_EW] = 6;
  835. X      zhang_log_last_hand ();
  836. X      input_acknowledgment (-2);
  837. X      return (0);
  838. X    } else {
  839. X      Display_Status ("THREE PASSES -- PRESS RETURN TO BEGIN PLAY");
  840. X      input_acknowledgment (-2);
  841. X    };
  842. X    Clear_Bidding_Board ();
  843. X
  844. X    game_mode = PLAYING_MODE;
  845. X    Display_Playing_Board ();
  846. X    Display_Contract ();
  847. X
  848. X    honors_bonus = 0;
  849. X    if (trump_suit < 4) {
  850. X        j = card_code (trump_suit, RANK_TEN);
  851. X        for (i = c1 = 0; i < 5; i++)
  852. X              c1 += current_hand[declarer][i+j];
  853. X        for (i = c2 = 0; i < 5; i++)
  854. X              c2 += current_hand[dummy][i+j];
  855. X        if ((c1 == 5) || (c2 == 5)) {
  856. X            honors_bonus = 150;
  857. X            honors_bonus_string =
  858. X                  "150 POINT BONUS FOR ALL 5 HONORS IN ONE HAND";
  859. X        } else if ((c1 == 4) || (c2 == 4)) {
  860. X            honors_bonus = 100;
  861. X            honors_bonus_string =
  862. X                  "100 POINT BONUS FOR 4 HONORS IN ONE HAND";
  863. X        };
  864. X    } else {
  865. X        for (i = c1 = 0; i < 4; i++) 
  866. X            c1 += current_hand[declarer][card_code(i, RANK_ACE)];
  867. X        for (i = c2 = 0; i < 4; i++) 
  868. X            c2 += current_hand[dummy][card_code(i, RANK_ACE)];
  869. X        if ((c1 == 5) || (c2 == 5)) {
  870. X            honors_bonus = 150;
  871. X            honors_bonus_string =
  872. X                  "150 POINT BONUS FOR ALL 4 ACES IN ONE HAND";
  873. X        }
  874. X    };
  875. X    if ((scoring_mode == DUPLICATE_SCORING) || 
  876. X        (scoring_mode == EMAIL_SCORING) ||
  877. X        (scoring_mode == IMP_SCORING))
  878. X      honors_bonus = 0;
  879. X
  880. X        if (scoring_mode == IMP_SCORING) {
  881. X                for (i = c1 = 0; i < 4; i++)
  882. X                     {  c1 += current_hand[declarer][card_code(i, RANK_ACE)];
  883. X                        c1 += current_hand[dummy][card_code(i, RANK_ACE)];};
  884. X                for (i = c2 = 0; i < 4; i++) 
  885. X                     {  c2 += current_hand[declarer][card_code(i, RANK_KING)]; 
  886. X                        c2 += current_hand[dummy][card_code(i, RANK_KING)];};
  887. X                for (i = c3 = 0; i < 4; i++) 
  888. X                     {  c3 += current_hand[declarer][card_code(i, RANK_QUEEN)]; 
  889. X                        c3 += current_hand[dummy][card_code(i, RANK_QUEEN)];};
  890. X                for (i = c4 = 0; i < 4; i++) 
  891. X                     {  c4 += current_hand[declarer][card_code(i, RANK_JACK)]; 
  892. X                        c4 += current_hand[dummy][card_code(i, RANK_JACK)];};
  893. X                highcard_points = 4*c1 + 3*c2 + 2*c3 + c4;
  894. X    };
  895. X
  896. X    leader = player_next [declarer];
  897. X    for (trick = 1; trick < 14; trick++) {
  898. X            leading_play [trick] = leader;
  899. X        Display_Hand (local_player);
  900. X        if (local_player == dummy) Display_Hand (declarer);
  901. X#ifdef TWOPLAYER_MODE
  902. X        Display_Hand (player_partner[local_player]);    /* DBG */
  903. X#endif
  904. X#ifdef LOOPBACK_MODE
  905. X        for (no_plays = 0; no_plays < 4; no_plays++)
  906. X          Display_Hand (no_plays);
  907. X#endif
  908. X        no_plays = 0;
  909. X        pos = leader;
  910. X        while (no_plays < 4) {
  911. X            generate_valid_plays (pos, legal_plays);
  912. X            Display_Player (pos);
  913. X#ifdef LOOPBACK_MODE
  914. X            local_player = pos;
  915. X            Display_Hand (pos);
  916. X            card = input_play (local_player, legal_plays);
  917. X            Display_Play (pos, card);
  918. X            local_player = PLAYER_NORTH;
  919. X#else
  920. X#ifdef TWOPLAYER_MODE
  921. X            card = input_play ((pos % 2), legal_plays);
  922. X#else
  923. X            if (pos == dummy)
  924. X                card = input_play (declarer, legal_plays);
  925. X            else
  926. X                card = input_play (pos, legal_plays);
  927. X#endif
  928. X#endif
  929. X            if (card < 0) break;
  930. X
  931. X            if (no_plays == 0) {
  932. X                winning_card = card;
  933. X                winning_player = leader;
  934. X            } else if (outranks(card, winning_card)) {
  935. X                winning_card = card;
  936. X                winning_player = pos;
  937. X            };
  938. X            no_plays += 1;
  939. X            plays [pos] = card;
  940. X            current_hand[pos][card] = 0;
  941. X            saved_plays [pos][trick] = card;
  942. X            Display_Play (pos, card);
  943. X
  944. X            if (pos == local_player)
  945. X                Display_Hand (local_player);
  946. X                        if ((pos == dummy) || (trick == 1))
  947. X                Display_Hand (dummy);
  948. X            if ((local_player == dummy) && (pos == declarer))
  949. X                    Display_Hand (declarer);
  950. X
  951. X            pos = player_next[pos];
  952. X        };
  953. X        if (card < 0) {
  954. X          card = -card-1;
  955. X          tricks[side_of(declarer)] += card;
  956. X          tricks[1-side_of(declarer)] = 13 - tricks[side_of(declarer)];
  957. X          trick = 14;
  958. X          Display_Tricks_Taken();
  959. X          sprintf (claim_message,
  960. X               "DECLARER HAS CLAIMED %d MORE TRICKS", card);
  961. X          Display_Player_Comment ("MODERATOR", claim_message);
  962. X        } else {
  963. X          leader = winning_player;
  964. X          tricks[side_of(leader)] += 1;
  965. X          Display_Tricks_Taken();
  966. X          if ((local_player != dummy) || prompt_dummy)
  967. X            input_acknowledgment (-1);
  968. X        };
  969. X        Clear_Plays ();
  970. X    };
  971. X    hands_played += 1;
  972. X
  973. X    contractor = side_of(declarer);
  974. X
  975. X    switch (scoring_mode) {
  976. X      case RUBBER_SCORING:
  977. X      case CHICAGO_SCORING:
  978. X        above_line [contractor] += honors_bonus;
  979. X        break;
  980. X      case DUPLICATE_SCORING:
  981. X      case EMAIL_SCORING:
  982. X        above_line [SIDE_NS] += below_line[SIDE_NS];
  983. X        above_line [SIDE_EW] += below_line[SIDE_EW];
  984. X        below_line [SIDE_NS] = below_line[SIDE_EW] = 0;
  985. X        break;
  986. X      case IMP_SCORING:
  987. X        above_line [SIDE_NS] += below_line[SIDE_NS];
  988. X        above_line [SIDE_EW] += below_line[SIDE_EW];
  989. X        below_line [SIDE_NS] = below_line[SIDE_EW] = 0;
  990. X        sprintf (honors_message,
  991. X             "CONTRACTOR'S SIDE HAS %d HIGH CARD POINTS",
  992. X             highcard_points);
  993. X        Display_Player_Comment ("MODERATOR", honors_message);
  994. X        break;
  995. X    };
  996. X
  997. X        if (honors_bonus > 0)
  998. X            Display_Player_Comment ("MODERATOR", honors_bonus_string);
  999. X
  1000. X    if (tricks[contractor] >= contract+6) {
  1001. X        excess = tricks[contractor] - contract - 6;
  1002. X        /* We always record the hands in email structures, in case
  1003. X               the player would like to save them.  Therefore, we must
  1004. X           always compute the email score. */
  1005. X        email_score = 
  1006. X                  Duplicate_score_made (excess, vulnerable[contractor]);
  1007. X        email_result = tricks[contractor] - 6;
  1008. X
  1009. X        switch (scoring_mode) {
  1010. X          case RUBBER_SCORING:
  1011. X            below_line[contractor] += Rubber_score_below ();
  1012. X            above_line[contractor] += Rubber_score_above (excess);
  1013. X/*
  1014. X            if (vulnerable[contractor] && 
  1015. X              (below_line[contractor] >= 100)) {
  1016. X                sprintf (honors_message, "%s AND %s %s",
  1017. X                    player_names[contractor],
  1018. X                    player_names[contractor+2],
  1019. X                    "HAVE WON THE RUBBER.");
  1020. X                Display_Player_Comment ("MODERATOR",
  1021. X                    honors_message);
  1022. X            };
  1023. X*/
  1024. X            break;
  1025. X          case CHICAGO_SCORING:
  1026. X            below_line[contractor] += Chicago_score_made (excess,
  1027. X                         vulnerable[contractor]);
  1028. X            if ((below_line[contractor] < 100) &&
  1029. X                  (hands_played%4 == 0))
  1030. X                below_line[contractor] += 100;
  1031. X            if (below_line[contractor] >= 100) {
  1032. X               above_line[contractor] += below_line[contractor];
  1033. X               below_line[SIDE_NS] = below_line[SIDE_EW] = 0;
  1034. X            };
  1035. X            break;
  1036. X          case DUPLICATE_SCORING:
  1037. X          case EMAIL_SCORING:
  1038. X              below_line[contractor] = email_score;
  1039. X            break;
  1040. X          case IMP_SCORING:
  1041. X            base_score = 
  1042. X                  Duplicate_score_made (excess, 
  1043. X                        vulnerable[contractor]);
  1044. X            below_line[contractor] =
  1045. X              IMP_score_conversion (base_score);
  1046. X/*
  1047. X            for (i = 0; base_score >= IMP_scoring_table[i]; i++);
  1048. X            below_line[contractor] =
  1049. X                20 + i - highcard_points;
  1050. X*/
  1051. X            break;
  1052. X        }
  1053. X        if ((contract >= 6) && (contractor == side_of(local_player))){
  1054. X          display_help ("slam");
  1055. X          Refresh_Display ();
  1056. X        };
  1057. X    } else {
  1058. X        down = contract + 6 - tricks[contractor];
  1059. X        email_score =
  1060. X                  -Duplicate_score_set (down, vulnerable[contractor]);
  1061. X        email_result = -down;
  1062. X        switch (scoring_mode) {
  1063. X          case RUBBER_SCORING:
  1064. X            above_line [1-contractor] += Rubber_score_set (down);
  1065. X            break;
  1066. X          case CHICAGO_SCORING:
  1067. X              above_line [1-contractor] += 
  1068. X                  Chicago_score_set (down, vulnerable[contractor]);
  1069. X            break;
  1070. X          case DUPLICATE_SCORING:
  1071. X          case EMAIL_SCORING:
  1072. X              below_line [1-contractor] = - email_score;
  1073. X            break;
  1074. X          case IMP_SCORING:
  1075. X            base_score = Duplicate_score_set (down, 
  1076. X                    vulnerable[contractor]);
  1077. X            below_line[contractor] =
  1078. X              IMP_score_conversion (-base_score);
  1079. X/*
  1080. X            for (i = 0; base_score >= IMP_scoring_table[i]; i++);
  1081. X            base_score = -base_score;
  1082. X            below_line[contractor] =
  1083. X                20 - i - highcard_points;
  1084. X*/
  1085. X            break;
  1086. X        }
  1087. X    };
  1088. X                 
  1089. X    if (current_board != NULL)
  1090. X        for (ec=current_board->post_script; ec != NULL; ec = ec->next)
  1091. X            Broadcast_Comment (ec->comment);
  1092. X
  1093. X    /* Now we record the score in an email record.  If we are actually
  1094. X       playing in email mode, then we display how will each side did. */
  1095. X    i = (redoubled? BID_REDOUBLE: (doubled? BID_DOUBLE: 0));
  1096. X    if (side_of(declarer) == side_of(PLAYER_EAST)) 
  1097. X        email_score = -email_score;
  1098. X    Record_Email_Score (current_board, ns_pair_no, ew_pair_no,
  1099. X        highest_bid, i, declarer, email_result, email_score);
  1100. X    if ((scoring_mode == EMAIL_SCORING) && 
  1101. X        (local_player == PLAYER_NORTH)) {
  1102. X        Compute_Board_Match_Points (current_board);
  1103. X        score = current_board->score_list;
  1104. X        while (score->ns_pair != ns_pair_no) score = score->next;
  1105. X        if ((score->ns_match_points != 0) || 
  1106. X            (score->ew_match_points != 0)) {
  1107. X          sprintf (claim_message, "%s: %4.1f, %s: %4.1f",
  1108. X               "N-S MATCH POINTS", 
  1109. X               0.5 * ((float) score->ns_match_points),
  1110. X               "E-W MATCH POINTS", 
  1111. X               0.5 * ((float) score->ew_match_points));
  1112. X          Broadcast_Comment (claim_message);
  1113. X        };
  1114. X    };
  1115. X    log_last_hand ();
  1116. X    zhang_log_last_hand ();
  1117. X    Display_Player (-1);
  1118. X    Display_Below_Line_Points ();
  1119. X    Display_Above_Line_Points ();
  1120. X    for (i = 0; i < 4; i++)
  1121. X      for (j = 0; j < 52; j++)
  1122. X        current_hand[i][j] = saved_hands[i][j];
  1123. X    for (i = 0; i < 4; i++)
  1124. X      Display_Hand (i);
  1125. X    Display_Status 
  1126. X      ("REVIEW OF THE HAND -- PRESS RETURN ON A BLANK LINE TO PROCEED");
  1127. X    game_mode = REVIEW_MODE;
  1128. X    input_acknowledgment (-3);
  1129. X    game_mode = DEALING_MODE;
  1130. X
  1131. X    Clear_Playing_Board ();
  1132. X    return (1);
  1133. X};
  1134. Xstatic play_game ()
  1135. X{
  1136. X    int winner;
  1137. X    below_line[SIDE_NS] = below_line[SIDE_EW] = 0;
  1138. X    while ((below_line[SIDE_NS] < 100) && (below_line[SIDE_EW] < 100)) {
  1139. X            Refresh_Display ();
  1140. X        Display_Below_Line_Points ();
  1141. X        Display_Above_Line_Points ();
  1142. X        play_hand ();
  1143. X        dealer = player_next [dealer];
  1144. X    };
  1145. X
  1146. X    above_line[SIDE_NS] += below_line[SIDE_NS];
  1147. X    above_line[SIDE_EW] += below_line[SIDE_EW];
  1148. X    winner = (below_line[SIDE_NS] >= 100) ? SIDE_NS : SIDE_EW;
  1149. X    if (vulnerable[winner])
  1150. X        above_line[winner] += 500;
  1151. X    vulnerable[winner]++;
  1152. X};
  1153. Xstatic play_rubber ()
  1154. X{
  1155. X    char message_buf[80];
  1156. X
  1157. X    vulnerable[SIDE_NS] = vulnerable[SIDE_EW] = 0;
  1158. X    while ((vulnerable[SIDE_NS] < 2) && (vulnerable[SIDE_EW] < 2)) {
  1159. X        Display_Vulnerabilities ();
  1160. X        play_game ();
  1161. X    };
  1162. X    /* Add bonus points if only one side was vulnerable when the
  1163. X       rubber was won. */
  1164. X    if (vulnerable[SIDE_NS] == 0)
  1165. X        above_line[SIDE_EW] += 200;
  1166. X    else if (vulnerable[SIDE_EW] == 0)
  1167. X        above_line[SIDE_NS] += 250;
  1168. X
  1169. X    if (vulnerable[SIDE_NS] >= 2) 
  1170. X        sprintf (message_buf, "%s AND %s HAVE WON THE RUBBER.",
  1171. X            player_names[PLAYER_NORTH],
  1172. X            player_names[PLAYER_SOUTH]);
  1173. X    else
  1174. X        sprintf (message_buf, "%s AND %s HAVE WON THE RUBBER.",
  1175. X            player_names[PLAYER_EAST],
  1176. X            player_names[PLAYER_WEST]);
  1177. X    Display_Player_Comment ("MODERATOR", message_buf);
  1178. X};
  1179. X
  1180. Xstatic void play_chicago_rubber ()
  1181. X{
  1182. X  int i, hand_played;
  1183. X
  1184. X  dealer = PLAYER_NORTH;
  1185. X  for (i = 0; i < 4; i++) {
  1186. X    Refresh_Display ();
  1187. X    vulnerable[SIDE_EW] = vulnerable[SIDE_NS] = 0;
  1188. X    switch (hands_played % 4) {
  1189. X    case 0: break;
  1190. X    case 1: vulnerable[SIDE_EW] = 1; break;
  1191. X    case 2: vulnerable[SIDE_NS] = 1; break;
  1192. X    case 3: vulnerable[SIDE_EW] = vulnerable[SIDE_NS]  = 1;
  1193. X    };
  1194. X    Display_Vulnerabilities ();
  1195. X    Display_Above_Line_Points ();
  1196. X    Display_Below_Line_Points ();
  1197. X    hand_played = 0;
  1198. X    while (!hand_played) hand_played = play_hand ();
  1199. X    dealer = player_next [dealer];
  1200. X  };
  1201. X};
  1202. X
  1203. Xstatic void play_duplicate_rubber ()
  1204. X{
  1205. X  int round = 0;
  1206. X  int i, hand_played;
  1207. X
  1208. X  dealer = PLAYER_NORTH;
  1209. X  for (i = 0; i < 16; i++) {
  1210. X    Refresh_Display ();
  1211. X    vulnerable[SIDE_EW] = vulnerable[SIDE_NS] = 0;
  1212. X    switch (round) {
  1213. X    case 0: break;
  1214. X    case 1: vulnerable[SIDE_EW] = 1; break;
  1215. X    case 2: vulnerable[SIDE_NS] = 1; break;
  1216. X    case 3: vulnerable[SIDE_EW] = vulnerable[SIDE_NS]  = 1;
  1217. X    };
  1218. X    Display_Vulnerabilities ();
  1219. X    Display_Above_Line_Points ();
  1220. X    Display_Below_Line_Points ();
  1221. X    hand_played = 0;
  1222. X    while (!hand_played) hand_played = play_hand ();
  1223. X    round += 1;
  1224. X    if ((i % 4) == 3) round += 1;
  1225. X    round %= 4;
  1226. X    dealer = player_next [dealer];
  1227. X  };
  1228. X};
  1229. X
  1230. Xstatic void play_imp_rubber ()
  1231. X{
  1232. X  int round = 0;
  1233. X  int i, hand_played;
  1234. X  dealer = PLAYER_NORTH;
  1235. X  for (i = 0; i < 16; i++) {
  1236. X    Refresh_Display ();
  1237. X    vulnerable[SIDE_EW] = vulnerable[SIDE_NS] = 0;
  1238. X    switch (round) {
  1239. X    case 0: break;
  1240. X    case 1: vulnerable[SIDE_NS] = 1; break;
  1241. X    case 2: vulnerable[SIDE_EW] = 1; break;
  1242. X    case 3: vulnerable[SIDE_EW] = vulnerable[SIDE_NS]  = 1;
  1243. X    };
  1244. X    Display_Vulnerabilities ();
  1245. X    Display_Above_Line_Points ();
  1246. X    Display_Below_Line_Points ();
  1247. X    hand_played = 0;
  1248. X    while (!hand_played) hand_played = play_hand ();
  1249. X    round += 1;
  1250. X    if ((i % 4) == 3) round += 1;
  1251. X    round %= 4;
  1252. X    dealer = player_next [dealer];
  1253. X  };
  1254. X};
  1255. X
  1256. Xint recovery_routine (parm)
  1257. X    int parm;
  1258. X{
  1259. X  Terminate_Program ("PROGRAM ABORT");
  1260. X};
  1261. X
  1262. Xint Quit_program ()
  1263. X{
  1264. X  Clear_Status_Display ();
  1265. X  Continue_Comment_Display ();
  1266. X  Refresh_Display ();
  1267. X  if (input_answer("ARE YOU SURE YOU WISH TO QUIT? ")) {
  1268. X    abort_flag = 1;
  1269. X    send_player_message ("QUIT");
  1270. X    reset_network ();
  1271. X    clear_screen ();
  1272. X    Reset_Terminal ();
  1273. X    exit (0);
  1274. X  };
  1275. X};
  1276. X
  1277. Xint quit_error_routine ()
  1278. X{
  1279. X  if (!abort_flag) {
  1280. X    abort_flag = 1;
  1281. X    clear_screen ();
  1282. X    Reset_Terminal ();
  1283. X  };
  1284. X  kill (getpid(), SIGTRAP);
  1285. X};
  1286. X
  1287. Xint socket_recovery_routine (parm)
  1288. X     int parm;
  1289. X{
  1290. X  reset_network ();
  1291. X  Terminate_Program ("THE NETWORK CONNECTIONS HAVE BEEN BROKEN!");  
  1292. X};
  1293. X
  1294. Xint system_call_error_routine (parm)
  1295. X     int parm;
  1296. X{
  1297. X  if (!abort_flag) {
  1298. X    abort_flag = 1;
  1299. X    reset_network ();
  1300. X    Display_Player_Comment ("MODERATOR", "INTERRUPTED SYSTEM CALL");
  1301. X  };
  1302. X  Terminate_Program ("MODERATOR", "PROGRAM TERMINATING");
  1303. X};
  1304. X
  1305. Xint access_error_routine (parm)
  1306. X     int parm;
  1307. X{
  1308. X  if (!abort_flag) {
  1309. X    abort_flag = 1;
  1310. X    send_player_message ("QUIT");
  1311. X    reset_network ();
  1312. X    Display_Player_Comment ("MODERATOR",
  1313. X      "ACCESS VIOLATION!!  YOU HAVE FOUND A BUG IN THE PROGRAM.");
  1314. X    Display_Player_Comment ("MODERATOR", "PROGRAM TERMINATING");
  1315. X    input_acknowledgment (-1);
  1316. X  };
  1317. X  clear_screen ();
  1318. X  Reset_Terminal ();
  1319. X  kill (getpid(), SIGTRAP);
  1320. X};
  1321. X
  1322. Xint Terminate_Program (termination_message)
  1323. X     char *termination_message;
  1324. X{
  1325. X  if (!abort_flag) {
  1326. X    abort_flag = 1;
  1327. X    send_player_message ("QUIT");
  1328. X    reset_network ();
  1329. X    Refresh_Display ();
  1330. X    Display_Player_Comment ("MODERATOR", termination_message);
  1331. X    input_acknowledgment (-1);
  1332. X  };
  1333. X  clear_screen ();
  1334. X  Reset_Terminal ();
  1335. X  exit (0);
  1336. X};
  1337. X
  1338. Xparameter_error ()
  1339. X{
  1340. X  printf ("First player starts the program on his machine with\n");
  1341. X  printf ("   okbridge [-c] [-d] [-e] [-i] [-R] <seat> <name> \n%s\n%s\n",
  1342. X      "        [-p portno] [-r replay-file] [-l load-file] [-L log-file]",
  1343. X      "        [-z# [zlog-file]]");
  1344. X  printf ("Others connect with\n");
  1345. X  printf ("   okbridge [-c] [-d] [-e] [-i] [-R] %s\n%s\n",
  1346. X      "<seat> <name> <host>","        [ ... additional parameters ... ]");
  1347. X  printf ("<seat> is one of the characters n, s, e, w\n");
  1348. X  printf ("<name> is your identifying name (ex. 'steve')\n");
  1349. X  printf ("<host> is the internet name of the first player's machine\n\n");
  1350. X  printf ("-c     is for Chicago scoring\n");
  1351. X  printf ("-d     is for Duplicate scoring\n");
  1352. X  printf ("-e     is for Email duplicate scoring\n");
  1353. X  printf ("-i     is for simulated IMP scoring\n");
  1354. X  printf ("  NOTE: Only north can choose the scoring option.\n\n");
  1355. X  printf ("-p portno specifies the internet port number for communications\n");
  1356. X  printf ("-r replay-file specifies an email duplicate file for replay\n");
  1357. X  printf ("-l load-file specifies an email duplicate file for loading\n");
  1358. X  printf ("-L log-file specifies a logfile file saving the results of play\n");
  1359. X  printf ("-z# zlog-file specifies a table number & Zhang-format log file\n");
  1360. X  exit (1);
  1361. X};
  1362. X
  1363. Xstatic void parse_position_parameter (position_string)
  1364. X     char *position_string;
  1365. X{
  1366. X  char ch;
  1367. X
  1368. X  if (strlen(position_string) == 1) {
  1369. X    ch = *position_string;
  1370. X    switch (ch) {
  1371. X    case 'n': 
  1372. X    case 'N': 
  1373. X      local_player = PLAYER_NORTH;
  1374. X      return;
  1375. X    case 'e': 
  1376. X    case 'E': 
  1377. X      local_player = PLAYER_EAST;
  1378. X      return;
  1379. X    case 's': 
  1380. X    case 'S': 
  1381. X      local_player = PLAYER_SOUTH;
  1382. X      return;
  1383. X    case 'w': 
  1384. X    case 'W': 
  1385. X      local_player = PLAYER_WEST;
  1386. X      return;
  1387. X    };
  1388. X  };
  1389. X  printf ("Error -- unrecognized <seat> name: %s\n", position_string);
  1390. X  parameter_error ();
  1391. X};
  1392. X
  1393. Xtypedef  void (*signal_handler) ();
  1394. X
  1395. Xmain (argc, argv)
  1396. Xint argc; char **argv;
  1397. X{
  1398. X        int error_value;   /* error return from setjmp/signal */
  1399. X    int argi;          /* index of current argument being processed */
  1400. X    int posi;          /* index of next positional parameter to process */
  1401. X    char *filename;    /* filename specified for log file on command line*/
  1402. X        char filename_buf[80];
  1403. X        FILE *fp;          /* used only for checking the existence of files */
  1404. X
  1405. X    /* Various signal handlers: */
  1406. X    int recovery_routine (), Quit_program (), socket_recovery_routine (),
  1407. X        quit_error_routine (), access_error_routine (),
  1408. X        system_call_error_routine ();
  1409. X
  1410. X#define current_arg  (argv[argi])
  1411. X#define next_arg     argi++
  1412. X#define more_args    (argi < argc)
  1413. X
  1414. X#ifdef DEBUG
  1415. X/* In earlier versions of the program, we have been having some problems
  1416. X   with occasional segmentation faults during the bidding.  This code
  1417. X   asks the system to create a core file if there is a segmentation fault.
  1418. X */
  1419. X    struct rlimit rlp;
  1420. X
  1421. X    getrlimit (RLIMIT_CORE, &rlp);
  1422. X    rlp.rlim_cur = rlp.rlim_max;
  1423. X    setrlimit (RLIMIT_CORE, &rlp);
  1424. X#endif
  1425. X    local_player = -1;
  1426. X        scoring_mode = RUBBER_SCORING;
  1427. X    Read_Initialization_File ();
  1428. X
  1429. X    argi = 1;
  1430. X    posi = 1;
  1431. X    while (more_args) {
  1432. X      if(*current_arg == '-') {
  1433. X        /* process a position-independent parameter. */
  1434. X        if (!strcmp(current_arg, "-c")) {
  1435. X          /* Chicago scoring. */
  1436. X          scoring_mode = CHICAGO_SCORING;
  1437. X        } else if (!strcmp(current_arg, "-d")) {
  1438. X          scoring_mode = DUPLICATE_SCORING;
  1439. X        } else if (!strcmp(current_arg, "-e")) {
  1440. X          scoring_mode = EMAIL_SCORING;
  1441. X        } else if (!strcmp(current_arg, "-i")) {
  1442. X              scoring_mode = IMP_SCORING;
  1443. X        } else if (!strcmp(current_arg, "-R")) {
  1444. X          scoring_mode = RUBBER_SCORING;
  1445. X        } else if (!strcmp(current_arg, "-p")) {
  1446. X          next_arg;
  1447. X          if (!more_args) {
  1448. X        printf ("Error -- port number must follow -p parameter\n");
  1449. X        parameter_error ();
  1450. X          };
  1451. X          network_port = atoi (current_arg);
  1452. X          if (!network_port) {
  1453. X        printf ("Error: %s\n", 
  1454. X            "-p parameter requires a positive port number");
  1455. X        parameter_error ();
  1456. X          };
  1457. X        } else if (!strcmp(current_arg, "-r")) {
  1458. X          next_arg;
  1459. X          if (!more_args) {
  1460. X        printf ("Error -- replay filename must follow -r parameter\n");
  1461. X        parameter_error ();
  1462. X          };
  1463. X          if ((fp = fopen(current_arg,"r")) == NULL) {
  1464. X        printf ("Error -- could not open replay file %s", 
  1465. X            current_arg);
  1466. X        parameter_error ();
  1467. X          };
  1468. X          fclose (fp);
  1469. X          autoload_file = strdup(current_arg);
  1470. X          autosave_file = strdup(current_arg);
  1471. X          scoring_mode = EMAIL_SCORING;
  1472. X        } else if (!strcmp(current_arg, "-l")) {
  1473. X          next_arg;
  1474. X          if (!more_args) {
  1475. X        printf ("Error -- load filename must follow -l parameter\n");
  1476. X        parameter_error ();
  1477. X          };
  1478. X          if ((fp = fopen(current_arg,"r")) == NULL) {
  1479. X        printf ("Error -- could not open autoload file %s", 
  1480. X            current_arg);
  1481. X        parameter_error ();
  1482. X          };
  1483. X          fclose (fp);
  1484. X          autoload_file = strdup(current_arg);
  1485. X          scoring_mode = EMAIL_SCORING;
  1486. X        } else if (!strcmp(current_arg, "-L")) {
  1487. X          if (logfile != NULL) fclose (logfile);
  1488. X          next_arg;
  1489. X          if (!more_args) {
  1490. X        printf("Error -- logfile filename must follow -L parameter\n");
  1491. X        parameter_error ();
  1492. X          };
  1493. X          if (current_arg[0] == '+') {
  1494. X        filename = current_arg + 1;
  1495. X        logfile = fopen (filename, "a");
  1496. X          } else {
  1497. X        filename = current_arg;
  1498. X        logfile = fopen (filename, "w");
  1499. X          };
  1500. X          if (logfile == NULL) {
  1501. X                printf ("Error -- Could not open log file %s: %s\n", filename,
  1502. X             sys_errlist[errno]);
  1503. X        parameter_error ();
  1504. X          };
  1505. X        } else if ((current_arg[0] == '-') && (current_arg[1] == 'z')) {
  1506. X          table_no = atoi (current_arg+2);
  1507. X          if (table_no == 0) {
  1508. X        printf ("Error in table number for Zhang mode: %s\n",
  1509. X            current_arg+2);
  1510. X        parameter_error ();
  1511. X          };
  1512. X          if ((argi < argc-1) && (argv[argi+1][0] != '-')) {
  1513. X        next_arg;
  1514. X        if (current_arg[0] == '+') {
  1515. X          filename = current_arg+1;
  1516. X          zhang_logfile = fopen (filename, "a");
  1517. X        } else {
  1518. X          filename = current_arg;
  1519. X          zhang_logfile = fopen(filename, "w");
  1520. X        };
  1521. X          } else {
  1522. X        sprintf (filename_buf, "okb_%s_rec", current_arg+2);
  1523. X        filename = filename_buf;
  1524. X        zhang_logfile = fopen (filename, "a");
  1525. X          };
  1526. X          if (zhang_logfile == NULL) {
  1527. X                printf ("Error -- Could not open zhang log file %s: %s\n", 
  1528. X            filename, sys_errlist[errno]);
  1529. X        parameter_error ();
  1530. X          };
  1531. X            } else {
  1532. X          printf ("Error -- unrecognized parameter: %s\n", current_arg);
  1533. X          parameter_error ();
  1534. X        };
  1535. X      } else {
  1536. X        /* Process a positional parameter. */
  1537. X        switch (posi) {
  1538. X        case 1: 
  1539. X          parse_position_parameter (current_arg);
  1540. X          break;
  1541. X        case 2:
  1542. X          local_player_name = strdup(current_arg);
  1543. X          break;
  1544. X        case 3:
  1545. X          server_name = strdup(current_arg);
  1546. X          server_mode = 0;
  1547. X          break;
  1548. X        default:
  1549. X          printf ("Error -- too many parameters given.\n");
  1550. X          parameter_error ();
  1551. X        };
  1552. X        posi++;
  1553. X      };
  1554. X      next_arg;
  1555. X    };
  1556. X    if ((local_player == -1) || (local_player_name == NULL)) {
  1557. X      printf ("Error -- not enough parameters were given.\n");
  1558. X      parameter_error ();
  1559. X    };
  1560. X    if (strlen(local_player_name) > 8)
  1561. X      local_player_name[8] = '\0';
  1562. X    player_names[local_player] = local_player_name;
  1563. X#ifdef LOOPBACK_MODE
  1564. X    local_player = PLAYER_NORTH;
  1565. X#endif
  1566. X
  1567. X#ifdef TWOPLAYER_MODE
  1568. X    local_player = local_player % 2;
  1569. X#endif
  1570. X
  1571. X    game_mode           = STARTUP_MODE;
  1572. X    dealer              = PLAYER_NORTH;
  1573. X    above_line[SIDE_NS] = above_line[SIDE_EW] = 0;
  1574. X    below_line[SIDE_NS] = below_line[SIDE_EW] = 0;
  1575. X    /* Initialize the state of the email duplicate variables: */
  1576. X    total_no_deals = current_deal_no = 0;
  1577. X    replaying_mode = 0;
  1578. X    email_record = NULL;
  1579. X    current_board = NULL;
  1580. X
  1581. X    abort_flag = 0;
  1582. X#ifdef SIGABRT
  1583. X    signal (SIGABRT, (signal_handler) recovery_routine);
  1584. X#endif
  1585. X    signal (SIGINT,  (signal_handler) Quit_program);
  1586. X    signal (SIGPIPE, (signal_handler) socket_recovery_routine);
  1587. X    signal (SIGURG,  (signal_handler) socket_recovery_routine);
  1588. X
  1589. X    signal (SIGQUIT, (signal_handler) quit_error_routine);
  1590. X    signal (SIGFPE,  (signal_handler) access_error_routine);
  1591. X    signal (SIGILL,  (signal_handler) access_error_routine);
  1592. X    signal (SIGBUS,  (signal_handler) access_error_routine);
  1593. X    signal (SIGSEGV, (signal_handler) access_error_routine);
  1594. X    signal (SIGSYS,  (signal_handler) system_call_error_routine);
  1595. X
  1596. X
  1597. X    error_value = setjmp (error_return);
  1598. X    if (error_value != 0)
  1599. X            Terminate_Program ("SIGNAL RECEIVED");
  1600. X    randomize ();
  1601. X
  1602. X    /* The order of the following initialization calls should not
  1603. X           be changed. */
  1604. X    Initialize_Input_Buffers ();
  1605. X    Initialize_Terminal ();
  1606. X    initialize_help_system ();
  1607. X    Initialize_Display ();
  1608. X    initialize_network ();
  1609. X    Initialize_Input ();
  1610. X
  1611. X    Display_Player_Comment 
  1612. X      ("MODERATOR", 
  1613. X       "WELCOME TO OKBRIDGE, COPYRIGHT (C) 1990, 1991 BY MATTHEW CLEGG");
  1614. X    Display_Player_Comment ("MODERATOR",
  1615. X            "TYPE /HELP FOR INSTRUCTIONS ABOUT THIS PROGRAM");
  1616. X
  1617. X    
  1618. X/*
  1619. X    Display_Player_Comment ("MODERATOR",
  1620. X      "WARNING!! THIS VERSION OF OKBRIDGE IS UNSTABLE AND MAY CRASH!!");
  1621. X*/
  1622. X    hands_played = 0;
  1623. X    while (1) {
  1624. X        switch (scoring_mode) {
  1625. X          case RUBBER_SCORING:
  1626. X                play_rubber ();
  1627. X            break;
  1628. X          case CHICAGO_SCORING:
  1629. X                play_chicago_rubber();
  1630. X            break;
  1631. X          case DUPLICATE_SCORING:
  1632. X          case EMAIL_SCORING:
  1633. X                play_duplicate_rubber();
  1634. X            break;
  1635. X          case IMP_SCORING:
  1636. X                    play_imp_rubber();
  1637. X            break;
  1638. X        }
  1639. X    };
  1640. X
  1641. X};
  1642. END_OF_FILE
  1643. if test 49783 -ne `wc -c <'bridge.c'`; then
  1644.     echo shar: \"'bridge.c'\" unpacked with wrong size!
  1645. fi
  1646. # end of 'bridge.c'
  1647. fi
  1648. if test -f 'helpfile.h' -a "${1}" != "-c" ; then 
  1649.   echo shar: Will not clobber existing file \"'helpfile.h'\"
  1650. else
  1651. echo shar: Extracting \"'helpfile.h'\" \(55 characters\)
  1652. sed "s/^X//" >'helpfile.h' <<'END_OF_FILE'
  1653. Xchar *help_file_name="/usr/local/games/okbridge.help";
  1654. END_OF_FILE
  1655. if test 55 -ne `wc -c <'helpfile.h'`; then
  1656.     echo shar: \"'helpfile.h'\" unpacked with wrong size!
  1657. fi
  1658. # end of 'helpfile.h'
  1659. fi
  1660. echo shar: End of archive 2 \(of 7\).
  1661. cp /dev/null ark2isdone
  1662. MISSING=""
  1663. for I in 1 2 3 4 5 6 7 ; do
  1664.     if test ! -f ark${I}isdone ; then
  1665.     MISSING="${MISSING} ${I}"
  1666.     fi
  1667. done
  1668. if test "${MISSING}" = "" ; then
  1669.     echo You have unpacked all 7 archives.
  1670.     rm -f ark[1-9]isdone
  1671.     echo creating input.c from input.c.aa and input.c.ab
  1672.     cat input.c.aa input.c.ab >input.c
  1673.     rm -f input.c.aa input.c.ab
  1674. else
  1675.     echo You still need to unpack the following archives:
  1676.     echo "        " ${MISSING}
  1677. fi
  1678. ##  End of shell archive.
  1679. exit 0
  1680.