home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume14 / okbrdge2 / part03 < prev    next >
Encoding:
Internet Message Format  |  1993-01-26  |  53.7 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: v14i081:  okbridge2 - computer-mediated bridge game, Part03/14
  5. Message-ID: <3520@master.CNA.TEK.COM>
  6. Date: 7 Sep 92 21:41:15 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2036
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: mclegg@cs.UCSD.EDU (Matthew Clegg)
  12. Posting-number: Volume 14, Issue 81
  13. Archive-name: okbridge2/Part03
  14. Supersedes: okbridge: Volume 13, Issue 16-22
  15. Environment: BSD-derived Unix, NeXT, curses, sockets
  16.  
  17.  
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then unpack
  21. # it by saving it into a file and typing "sh file".  To overwrite existing
  22. # files, type "sh file -c".  You can also feed this as standard input via
  23. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  24. # will see the following message at the end:
  25. #        "End of archive 3 (of 14)."
  26. # Contents:  bridge.c
  27. # Wrapped by billr@saab on Mon Sep  7 14:33:36 1992
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'bridge.c' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'bridge.c'\"
  31. else
  32. echo shar: Extracting \"'bridge.c'\" \(51146 characters\)
  33. sed "s/^X//" >'bridge.c' <<'END_OF_FILE'
  34. X/* bridge.c
  35. X *
  36. X ! Copyright (C) 1990-1992 by Matthew Clegg.  All Rights Reserved
  37. X ! 
  38. X ! OKbridge is made available as a free service to the Internet.
  39. X ! Accordingly, the following restrictions are placed on its use:
  40. X ! 
  41. X ! 1.  OKbridge may not be modified in any way without the explicit 
  42. X !     permission of Matthew Clegg.  
  43. X ! 
  44. X ! 2.  OKbridge may not be used in any way for commercial advantage.
  45. X !     It may not be placed on for-profit networks or on for-profit
  46. X !     computer systems.  It may not be bundled as part of a package
  47. X !     or service provided by a for-profit organization.
  48. X ! 
  49. X ! If you have questions about restrictions on the use of OKbridge,
  50. X ! write to mclegg@cs.ucsd.edu.
  51. X ! 
  52. X ! DISCLAIMER:  The user of OKbridge accepts full responsibility for any
  53. X ! damage which may be caused by OKbridge.
  54. X *
  55. X * This file contains an implementation of a computer-moderated
  56. X * bridge program.  The program serves as a mediator allowing
  57. X * four people on separate systems to cooperate in a bridge game.
  58. X * The game is screen oriented and interactive, although the display
  59. X * is very simple.  The program handles the shuffling and dealing
  60. X * of the cards, and it prompts each player for input when it is
  61. X * his turn.  The lower area of the screen is a dialog box, where
  62. X * players may enter comments that will be seen by the others.
  63. X *
  64. X *
  65. X */
  66. X#define _BRIDGE_
  67. X#define random(n) ((rand()/64) % (n))
  68. X#include <sys/time.h>
  69. X#include <sys/resource.h>
  70. X#include <setjmp.h>
  71. X#include <signal.h>
  72. X#include <stdio.h>
  73. X#include <sys/types.h>
  74. X
  75. X#ifdef AIX
  76. X#include <time.h>
  77. X#endif
  78. X#include <string.h>
  79. X
  80. X#include "state.h"
  81. X#include "parser.h"
  82. X#include "display.h"
  83. X#include "input.h"
  84. X#include "terminal.h"
  85. X#include "conversation.h"
  86. X
  87. X#include "cs.h"
  88. X#include "help.h"
  89. X#include "gps.h"
  90. X#include "scoring.h"
  91. X#include "rc.h"
  92. X#include "log.h"
  93. X
  94. X#define  VISIBLE(table) 1
  95. Xextern int errno;
  96. Xextern char *sys_errlist[];
  97. Xextern char *getenv ();
  98. Xextern void srand ();
  99. Xextern int  atoi ();
  100. Xextern void exit ();
  101. X/* extern void kill (); */
  102. X
  103. X#ifdef GCC
  104. Xextern int  getpid ();
  105. Xextern time_t time ();
  106. Xextern fclose (), fflush (), printf (), fprintf (), strcasecmp (), 
  107. X  gettimeofday ();
  108. X#endif
  109. X
  110. X#ifdef DEBUG
  111. Xextern getrlimit (), setrlimit ();
  112. X#endif
  113. X
  114. X
  115. Xextern int network_port;
  116. Xextern int server_mode;
  117. Xextern int claim_in_progress;
  118. Xextern int pause_mode;
  119. X
  120. Xint server_mode_requested = 0; /* TRUE if user has requested server mode. */
  121. Xint client_mode_requested = 0; /* TRUE if user has requested client mode. */
  122. X
  123. Xint save_defaults = 1;         /* TRUE if we should save some of the 
  124. X                  flags controlling the program in a 
  125. X                  defaults file. */
  126. X
  127. Xlong startup_time;             /* The time in seconds at which the program
  128. X                  was first started. */
  129. X
  130. X#ifdef LOGFILE
  131. X  extern FILE *net_log;
  132. X#endif
  133. X
  134. Xextern char *strdup ();
  135. Xextern void Broadcast_Comment ();
  136. X
  137. Xextern char *autoload_file, *autosave_file;
  138. X
  139. XFILE *logfile = NULL;  /* The file where we log the hands that have
  140. X            . been played. */
  141. XFILE *zhang_logfile = NULL; 
  142. X                       /* The file where we log hands that are written
  143. X              in Zhang's format. */
  144. Xint table_no = -1;     /* Table number printed in Szhang format log files. */
  145. X
  146. Xhand saved_hands [4];  /* The cards as they were dealt. */
  147. Xhand saved_plays [4];  /* The cards as they were played. */
  148. Xint  leading_play [14];/* The leading player for each trick. */
  149. X
  150. Xstatic int prompt_before_hand = 1;
  151. X        /* A flag which indicates that the server should be given
  152. X           the opportunity to delay the beginning of the hand. */
  153. X
  154. Xstatic jmp_buf error_return;
  155. Xstatic jmp_buf reset_buf;
  156. X
  157. Xstatic int     abort_flag;
  158. Xstatic void randomize ()
  159. X{
  160. X  srand (time(NULL));
  161. X}
  162. X
  163. Xint bidding_code (bid_type, level, suit)
  164. X    int bid_type, level, suit;
  165. X/* Given the bidding type, as above, and the level and suit if it is
  166. X * a contract bid, returns a unique integer in the range 0-37 associated
  167. X * with the bid.  Contract bids are ordered in increasing order, so that
  168. X * 1C is the smallest and 7NT is the largest.
  169. X */
  170. X{
  171. X  switch (bid_type) {
  172. X  case BID_PASS:     return (BID_PASS);
  173. X  case BID_DOUBLE:   return (BID_DOUBLE);
  174. X  case BID_REDOUBLE: return (BID_REDOUBLE);
  175. X  case BID_SUIT:     return (5 * (level - 1) + suit + 3);
  176. X  default:       ;
  177. X  }
  178. X  return (-1);
  179. X}
  180. X
  181. Xstatic void Initiate_Skip_Mode (t)
  182. X     Table t;
  183. X{
  184. X  int i;
  185. X
  186. X  Send_skipack (t);
  187. X
  188. X  if (!server_mode) {
  189. X    t->game_mode = STARTUP_MODE;
  190. X    return;
  191. X  }
  192. X
  193. X  for (i = 0; i < 4; i++)
  194. X    if (OCCUPIED(t, i))
  195. X      t->Seats[i].skipping = 1;
  196. X
  197. X}
  198. X
  199. Xstatic int Handle_event_in_Skip_Mode (t, c)
  200. X     Table t;
  201. X     player_command c;
  202. X{
  203. X  int i;
  204. X
  205. X  switch (c->command) {
  206. X  case CMD_SKIPACK:
  207. X    t->Seats[c->player_no].skipping = 0;
  208. X    for (i = 0; i < 4; i++)
  209. X      if (OCCUPIED(t, i) && t->Seats[i].skipping)
  210. X    return (0);
  211. X    t->game_mode = STARTUP_MODE;
  212. X    return (1);
  213. X    break;
  214. X
  215. X  default:
  216. X    break;
  217. X  }
  218. X  return (0);
  219. X}
  220. X
  221. Xstatic void Initiate_Deal_Mode_if_Appropriate (t)
  222. X     Table t;
  223. X{
  224. X  int i, n;
  225. X  int ready_to_deal = 0;
  226. X
  227. X  if (!server_mode)
  228. X    return;
  229. X
  230. X  for (i = n = 0; i < 4; i++)
  231. X    if (t->Seats[i].occupied)
  232. X      n++;
  233. X
  234. X  if ((t->playing_mode == PRACTICE_PLAYING_MODE) && (n > 0))
  235. X    ready_to_deal = 1;
  236. X  else if (n == 4)
  237. X    ready_to_deal = 1;
  238. X  else 
  239. X    ready_to_deal = 0;
  240. X
  241. X  if (ready_to_deal && VISIBLE(t)) {
  242. X    if (prompt_before_hand) {
  243. X      Pause
  244. X    ( (hands_played == 0)?
  245. X     "PRESS <ESC> TO DEAL THE FIRST HAND ..." :
  246. X     "PRESS <ESC> FOR THE NEXT HAND ..."   );
  247. X
  248. X      for (i = n = 0; i < 4; i++)
  249. X    if (t->Seats[i].occupied)
  250. X      n++;
  251. X    }
  252. X
  253. X    if ((t->playing_mode == PRACTICE_PLAYING_MODE) && (n > 0))
  254. X      ready_to_deal = 1;
  255. X    else if (n == 4)
  256. X      ready_to_deal = 1;
  257. X    else 
  258. X      ready_to_deal = 0;
  259. X
  260. X    prompt_before_hand = prompt_before_hand && !ready_to_deal &&
  261. X      IS_PLAYER(local_player) && prompt_dummy;
  262. X
  263. X  } else if (!ready_to_deal)
  264. X    prompt_before_hand = IS_PLAYER(local_player) && prompt_dummy;
  265. X
  266. X  if (ready_to_deal)
  267. X    Send_deal (t);
  268. X}
  269. X
  270. Xstatic void Sequencing_Error (s)
  271. X     char *s;
  272. X{
  273. X  char buf[100];
  274. X
  275. X  sprintf (buf, "SEQUENCING ERROR: %s", s);
  276. X  Moderator_Comment (buf);
  277. X}
  278. X
  279. Xstatic void Initiate_Startup_Mode (t)
  280. X     Table t;
  281. X/* Perform setup processing when we first enter startup mode. */
  282. X{
  283. X  t->game_mode = STARTUP_MODE;
  284. X  Local_Player_Connection->spectator = 0;
  285. X  spectator_mode = 0;
  286. X  Clear_Spectators (t);
  287. X  Initiate_Deal_Mode_if_Appropriate (t);
  288. X}
  289. X
  290. Xstatic int Handle_event_in_Startup_Mode (t, b, p, c)
  291. X     Table t;
  292. X     Board *b;
  293. X     Play_record *p;
  294. X     player_command c;
  295. X/* Handles an event while we are in startup mode.  Returns 0 if the event
  296. X   causes us to remain in startup mode, and 1 if we advance to bidding mode.
  297. X*/
  298. X{
  299. X  switch (c->command) {
  300. X
  301. X  case CMD_HELLO:
  302. X  case CMD_SEAT:
  303. X  case CMD_ACK:
  304. X  case CMD_SEATPOS:
  305. X    Initiate_Deal_Mode_if_Appropriate (t);
  306. X    return (t->game_mode != STARTUP_MODE);
  307. X    break;
  308. X
  309. X  case CMD_DEAL:
  310. X    t->game_mode = DEALING_MODE;
  311. X    return (1);
  312. X    break;
  313. X
  314. X  default:
  315. X    break;
  316. X  }
  317. X  return (0);
  318. X}
  319. X
  320. Xstatic void Initiate_Deal_Mode (t)
  321. X     Table t;
  322. X/* Perform setup processing when we enter deal mode. */
  323. X{
  324. X  Board *b;
  325. X  Play_record *p;
  326. X
  327. X
  328. X  if (!server_mode) {
  329. X    t->board = NULL;
  330. X    t->play_record = NULL;
  331. X    return;
  332. X  }
  333. X
  334. X  /* If we are the server, then it is our responsibility to shuffle
  335. X     and deal the cards. */
  336. X  b = NULL;
  337. X  if (t->playing_mode == PRACTICE_PLAYING_MODE) {
  338. X    if (gps_duplicate_mode)
  339. X      GPS_Dup ("END");
  340. X    gps_duplicate_mode = 0;
  341. X  }
  342. X
  343. X  if (gps_duplicate_mode) {
  344. X    b = GPS_Get_Next_Board ();
  345. X    if ((b != NULL) && (b->scoring_mode == MP_SCORING))
  346. X      Broadcast_Comment ("WE ARE PLAYING MATCH POINT DUPLICATE BRIDGE.");
  347. X    else if (b != NULL)
  348. X      Broadcast_Comment ("WE ARE PLAYING IMP DUPLICATE BRIDGE.");
  349. X  }
  350. X  
  351. X  if (b == NULL) {
  352. X    if (gps_duplicate_mode)
  353. X      GPS_Dup ("END");
  354. X    gps_duplicate_mode = 0;
  355. X    if (Board_is_Available())
  356. X      b = Next_Unplayed_Board();
  357. X    else if (scoring_mode == RUBBER_SCORING) {
  358. X      if ((t->below_line[0] >= 100) || (t->below_line[1] >= 100)) {
  359. X    t->above_line[0] += t->below_line[0];
  360. X    t->above_line[1] += t->below_line[1];
  361. X    t->below_line[0] = t->below_line[1] = 0;
  362. X      }
  363. X      if ((t->board != NULL) && (t->board->scoring_mode == RUBBER_SCORING))
  364. X    b = Generate_Random_Rubber_Board (t->board, t->play_record);
  365. X      else
  366. X    b = Generate_Random_Rubber_Board (NULL, NULL);
  367. X    } else {
  368. X      b = Generate_Random_Match_Board (scoring_mode, t->board);
  369. X    }
  370. X  }
  371. X
  372. X  Send_board (t, b);
  373. X  for (p = b->play_records; p != NULL; p = p->next)
  374. X    Send_record (t, b, p);
  375. X
  376. X  t->play_record = Locate_play_record_by_foursome
  377. X    (b, PLAYER_NAME(t,PLAYER_NORTH), PLAYER_NAME(t, PLAYER_EAST),
  378. X     PLAYER_NAME(t,PLAYER_SOUTH),  PLAYER_NAME(t, PLAYER_WEST));
  379. X  if ((p = t->play_record) != NULL) {
  380. X    Send_userec (t, 
  381. X         p->player_names[PLAYER_NORTH], p->player_names[PLAYER_EAST], 
  382. X         p->player_names[PLAYER_SOUTH], p->player_names[PLAYER_WEST]);
  383. X  }
  384. X
  385. X  Send_score (t, t->above_line, t->below_line);
  386. X  Send_mode  (t, t->playing_mode);
  387. X  Send_begin (t);
  388. X}
  389. X
  390. Xstatic int Handle_event_in_Deal_Mode (t, b, p, c)
  391. X     Table t;
  392. X     Board *b;
  393. X     Play_record *p;
  394. X     player_command c;
  395. X/* Handles an event in deal mode.  Returns 0 if the event causes us to
  396. X   remain in deal mode, and 1 otherwise.  If we exit deal mode, then
  397. X   the board and play record to be used are stored in the corresponding
  398. X   fields of the table record t.
  399. X*/
  400. X{
  401. X  switch (c->command) {
  402. X  case CMD_BEGIN:
  403. X    t->game_mode = BIDDING_MODE;
  404. X    if (t->play_record == NULL) {
  405. X      t->play_record = Allocate_play_record 
  406. X    (PLAYER_NAME(t,PLAYER_NORTH), PLAYER_NAME(t, PLAYER_EAST),
  407. X     PLAYER_NAME(t,PLAYER_SOUTH),  PLAYER_NAME(t, PLAYER_WEST));
  408. X      Append_play_record (b, t->play_record);
  409. X    }
  410. X
  411. X    t->play_record->next_player = b->dealer;
  412. X    Compute_contract (t->board, t->play_record);
  413. X    if (t->play_record->hand_completed)
  414. X      t->game_mode = SCORING_MODE;
  415. X    else if (t->play_record->bidding_completed)
  416. X      t->game_mode = PLAYING_MODE;
  417. X    return (1);
  418. X    break;
  419. X
  420. X  case CMD_BOARD:
  421. X    t->board = c->data.board.record;
  422. X    t->play_record = NULL;
  423. X    break;
  424. X
  425. X  case CMD_MODE:
  426. X    t->playing_mode = c->data.mode;
  427. X    break;
  428. X
  429. X  case CMD_RECORD:
  430. X    p = c->data.record.play;
  431. X    if (p->bidding_completed)
  432. X      Compute_contract (t->board, p);
  433. X    if (p->hand_completed)
  434. X      Compute_MIMP_points (t->board, p);
  435. X    if (!server_mode)
  436. X      Append_play_record (t->board, c->data.record.play);
  437. X    break;
  438. X
  439. X  case CMD_SCORE:
  440. X    t->above_line[0] = c->data.score.above[0];
  441. X    t->above_line[1] = c->data.score.above[1];
  442. X    t->below_line[0] = c->data.score.below[0];
  443. X    t->below_line[1] = c->data.score.below[1];
  444. X    break;
  445. X
  446. X  case CMD_USEREC:
  447. X    t->play_record = Locate_play_record_by_foursome 
  448. X      (t->board, c->data.userec.north, c->data.userec.east,
  449. X       c->data.userec.south, c->data.userec.west);
  450. X    break;
  451. X
  452. X  default:
  453. X    return (0);
  454. X    break;
  455. X  }
  456. X  return (0);
  457. X}
  458. X
  459. Xstatic int Handle_event_in_Bidding_Mode (t, b, p, c)
  460. X     Table t;
  461. X     Board *b;
  462. X     Play_record *p;
  463. X     player_command c;
  464. X/* Handles an event while we are in bidding mode.  Returns 0 if the event
  465. X   causes us to remain in bidding mode, and 1 otherwise.  If we exit
  466. X   bidding mode, then the final contract is recorded in the play record.
  467. X   If the contract is a game contract, then the game mode is advanced to
  468. X   playing mode.  Otherwise, the mode is advanced to scoring mode.
  469. X*/
  470. X{
  471. X  int n = p->no_bids;
  472. X  int i;
  473. X  char message_buf[80];
  474. X
  475. X  if (c->command == CMD_ALERT) {
  476. X    if ((local_player == player_partner[c->player_no]) && !c->data.alert)
  477. X      return (0);
  478. X
  479. X    i = Index_of_Last_Bid (b, p, player_partner[c->player_no]);
  480. X    if (i < 0)
  481. X      Sequencing_Error ("Illegal Alert Received");
  482. X    p->alerts[i] = 1;
  483. X    return (0);
  484. X  }
  485. X
  486. X  if (c->command != CMD_BID) {
  487. X    return (0);
  488. X  } else if (c->player_no != p->next_player) {
  489. X    sprintf (message_buf, "Sequence Error: BID %s received from %s (%d).",
  490. X         bid_names[c->data.bid.level], c->player_name, c->player_no);
  491. X    Sequencing_Error (message_buf);
  492. X    return (0);
  493. X  }
  494. X
  495. X  p->bids[p->no_bids] = c->data.bid.level;
  496. X  p->alerts[p->no_bids++] = c->data.bid.alert;
  497. X  Compute_contract (b, p);
  498. X  p->next_player = player_next[p->next_player];
  499. X  if (p->no_bids < 4)
  500. X    return (0);
  501. X  else if ((p->bids[n-2] != BID_PASS) || (p->bids[n-1] != BID_PASS) ||
  502. X       (p->bids[n] != BID_PASS))
  503. X    return (0);
  504. X
  505. X  p->bidding_completed = 1;
  506. X  if (p->contract == BID_PASS) {
  507. X    t->game_mode = SCORING_MODE;
  508. X    p->hand_completed = 1;
  509. X  } else
  510. X    t->game_mode = PLAYING_MODE;
  511. X  p->next_player = player_next[p->declarer];
  512. X  return (1);
  513. X}
  514. X
  515. Xstatic void Record_Player_Names (t, b, p)
  516. X     Table t; Board *b; Play_record *p;
  517. X/* Records the names of the players at the local table into the play
  518. X   record p.  
  519. X */
  520. X{
  521. X  int i;
  522. X
  523. X  for (i = 0; i < 4; i++) {
  524. X    if (p->player_names[i] != NULL)
  525. X      free (p->player_names[i]);
  526. X    p->player_names[i] = strdup(PLAYER_NAME(t,i));
  527. X  }
  528. X}
  529. X
  530. Xstatic void Compute_Result (p)
  531. X     Play_record *p;
  532. X/* Uses the tricks[] and contract fields of the play record to compute the
  533. X   result of play.
  534. X*/
  535. X{
  536. X  p->hand_completed = 1;
  537. X  if (p->tricks[side_of(p->declarer)] >= 6 + p->contract)
  538. X    p->result = p->tricks[side_of(p->declarer)] - 6;
  539. X  else
  540. X    p->result = p->tricks[side_of(p->declarer)] - p->contract - 6;
  541. X}
  542. X
  543. Xstatic int Handle_event_in_Playing_Mode (t, b, p, c)
  544. X     Table t;
  545. X     Board *b;
  546. X     Play_record *p;
  547. X     player_command c;
  548. X/* Handles an event while we are in playing mode.  Returns 0 if the event
  549. X   causes us to remain in playing mode, and 1 otherwise.  If we exit
  550. X   playing mode, then the result of play is recorded in the play record.
  551. X*/
  552. X{
  553. X  int n, w, card;
  554. X  char buf[80];
  555. X
  556. X  if ((c->command != CMD_CLAIM) && (c->command != CMD_PLAY) &&
  557. X      (c->command != CMD_PLAYREQ))
  558. X    return (0);
  559. X
  560. X  if (c->command == CMD_CLAIM) {
  561. X    p->tricks[side_of(p->declarer)] += c->data.claim.no_tricks;
  562. X    p->tricks[1 - side_of(p->declarer)] = 
  563. X      13 - p->tricks[side_of(p->declarer)];
  564. X    Compute_Result (p);
  565. X    t->game_mode = SCORING_MODE;
  566. X    Display_Tricks_Taken ();
  567. X    return (1);
  568. X  }
  569. X
  570. X  if (c->command == CMD_PLAYREQ) {
  571. X    if (!server_mode)
  572. X      return;
  573. X    if (c->data.playreq.play_no != p->no_plays) {
  574. X      sprintf (buf, "WARNING! DUPLICATE PLAY (%s) RECEIVED FROM %s.",
  575. X           card_names[c->data.play], c->player_name);
  576. X      Broadcast_Comment (buf);
  577. X      return;
  578. X    } else {
  579. X      card = c->data.playreq.card;
  580. X      Send_play (Local_table, card);
  581. X    }
  582. X  } else
  583. X    card = c->data.playreq.card;
  584. X
  585. X  pause_mode = 0;
  586. X  p->play_list[p->no_plays++] = card;
  587. X  p->next_player = player_next[p->next_player];
  588. X  if (p->no_plays % 4 == 0) {
  589. X    n = p->no_plays - 4;
  590. X    w = Winning_card (trumpsuit_of(p->contract), p->next_player,
  591. X              p->play_list[n], p->play_list[n+1], 
  592. X              p->play_list[n+2], p->play_list[n+3]);
  593. X    p->tricks[side_of(w)] += 1;
  594. X    p->next_player = w;
  595. X    Display_Tricks_Taken ();
  596. X  }
  597. X
  598. X  if (p->no_plays == 52) {
  599. X    Compute_Result (p);
  600. X    t->game_mode = SCORING_MODE;
  601. X    return (1);
  602. X  }
  603. X
  604. X  return (0);
  605. X}
  606. X
  607. Xstatic int Honors_Point_Bonus (b, p)
  608. X     Board *b;
  609. X     Play_record *p;
  610. X/* Returns the number of bonus points awarded in a rubber contract
  611. X   for holding many honors in one hand. */
  612. X{
  613. X  int i;
  614. X  int dummy = player_partner [p->declarer];
  615. X  int trumps = trumpsuit_of (p->contract);
  616. X  int decl_honors = 0;   /* no of honors held by declarer. */
  617. X  int dummy_honors = 0;  /* no of honors held by dummy. */
  618. X
  619. X  if (trumps != SUIT_NOTRUMP) {
  620. X
  621. X    for (i = RANK_TEN; i <= RANK_ACE; i++)
  622. X      if (b->deal[card_code(trumps, i)] == p->declarer) 
  623. X    decl_honors++;
  624. X      else if (b->deal[card_code(trumps, i)] == dummy)
  625. X    dummy_honors++;
  626. X
  627. X    if ((decl_honors == 5) || (dummy_honors == 5))
  628. X      return (150);
  629. X    else if ((decl_honors == 4) || (dummy_honors == 4))
  630. X      return (100);
  631. X
  632. X  } else {
  633. X    /* In the case of a no trump contract, we count the total number of aces */
  634. X    for (i = 0; i < 4; i++)
  635. X      if (b->deal[card_code(i, RANK_ACE)] == p->declarer)
  636. X    decl_honors++;
  637. X      else if (b->deal[card_code(i, RANK_ACE)] == dummy)
  638. X    dummy_honors++;
  639. X
  640. X    if ((decl_honors == 4) || (dummy_honors == 4))
  641. X      return (150);
  642. X  }
  643. X  return (0);
  644. X  
  645. X}
  646. X
  647. Xstatic void Initiate_Scoring_Mode (t, b, p)
  648. X     Table t;
  649. X     Board *b;
  650. X     Play_record *p;
  651. X/* Initiates scoring mode for the current board.  This consists of computing
  652. X   the score for the board based upon scoring mode and result.
  653. X*/
  654. X{
  655. X  int contractor = side_of (p->declarer);
  656. X  int defender   = 1 - contractor;
  657. X  int vul        = b->vulnerable[contractor];
  658. X  int level      = level_of (p->contract);
  659. X  int trumpsuit  = trumpsuit_of (p->contract);
  660. X
  661. X  if (server_mode) {
  662. X    spectator_mode = 0;
  663. X    Clear_Spectators (t);
  664. X  }
  665. X
  666. X  if (Local_table->playing_mode != PRACTICE_PLAYING_MODE)
  667. X    hands_played += 1;
  668. X
  669. X  if (p->contract == BID_PASS)
  670. X    p->result = 0;
  671. X  else if (p->tricks[contractor] >= level + 6)
  672. X    p->result = p->tricks[contractor] - 6;
  673. X  else
  674. X    p->result = p->tricks[contractor] - level - 6;
  675. X
  676. X  p->above_line[SIDE_NS] = p->below_line[SIDE_NS] = 0;
  677. X  p->below_line[SIDE_EW] = p->below_line[SIDE_EW] = 0;
  678. X
  679. X  Compute_MIMP_points (b, p);
  680. X
  681. X  switch (b->scoring_mode) {
  682. X  case RUBBER_SCORING:
  683. X    if (p->result != 0)
  684. X      p->above_line[contractor] =  Honors_Point_Bonus (b, p);
  685. X    if (p->result > 0) {
  686. X      p->below_line[contractor] = Rubber_score_below 
  687. X    (vul, level, trumpsuit, p->doubled, p->result);
  688. X
  689. X      p->above_line[contractor] += Rubber_score_above 
  690. X    (vul, level, trumpsuit, p->doubled, p->result);
  691. X
  692. X      if (p->below_line[contractor] + b->part_score[contractor] > 100) {
  693. X    if (b->vulnerable[contractor])
  694. X      p->above_line[contractor] += b->vulnerable[defender]? 500: 700;
  695. X      }
  696. X    } else if (p->result < 0) {
  697. X      p->above_line[defender] += Rubber_score_set 
  698. X    (vul, level, trumpsuit, p->doubled, p->result);
  699. X    }
  700. X    break;
  701. X
  702. X  case DUPLICATE_SCORING:
  703. X  case IMP_SCORING:
  704. X  case MP_SCORING:
  705. X    if (p->result >= 0)
  706. X      p->below_line[contractor] = Duplicate_score_made
  707. X    (vul, level, trumpsuit, p->doubled, p->result);
  708. X    else if (p->result < 0)
  709. X      p->below_line[defender] = Duplicate_score_set
  710. X    (vul, level, trumpsuit, p->doubled, p->result);
  711. X    break;
  712. X  }
  713. X
  714. X  Compute_Intl_Matchpoints (b);
  715. X  Compute_Matchpoints (b);
  716. X
  717. X  Record_Played_Board (b);
  718. X
  719. X  if (!server_mode)
  720. X    return;
  721. X
  722. X  switch (b->scoring_mode) {
  723. X  case RUBBER_SCORING:
  724. X    t->above_line[SIDE_NS] += p->above_line[SIDE_NS];
  725. X    t->above_line[SIDE_EW] += p->above_line[SIDE_EW];
  726. X    t->below_line[SIDE_NS] += p->below_line[SIDE_NS];
  727. X    t->below_line[SIDE_EW] += p->below_line[SIDE_EW];
  728. X    break;
  729. X
  730. X  case DUPLICATE_SCORING:
  731. X    t->above_line[SIDE_NS] += t->below_line[SIDE_NS];
  732. X    t->above_line[SIDE_EW] += t->below_line[SIDE_EW];
  733. X    t->below_line[SIDE_NS] =  p->below_line[SIDE_NS];
  734. X    t->below_line[SIDE_EW] =  p->below_line[SIDE_EW];
  735. X    break;
  736. X
  737. X  case IMP_SCORING:
  738. X    t->above_line[SIDE_NS] += t->below_line[SIDE_NS];
  739. X    t->above_line[SIDE_EW] += t->below_line[SIDE_EW];
  740. X    t->below_line[SIDE_NS] =  (int) (100.0 * p->imatch_points[SIDE_NS]);
  741. X    t->below_line[SIDE_EW] =  (int) (100.0 * p->imatch_points[SIDE_EW]);
  742. X    break;
  743. X
  744. X  case MP_SCORING:
  745. X    t->above_line[SIDE_NS] += t->below_line[SIDE_NS];
  746. X    t->above_line[SIDE_EW] += t->below_line[SIDE_EW];
  747. X    t->below_line[SIDE_NS] =  (int) (100.0 * p->match_points[SIDE_NS]);
  748. X    t->below_line[SIDE_EW] =  (int) (100.0 * p->match_points[SIDE_EW]);
  749. X    break;
  750. X  }
  751. X
  752. X  Send_score (t, t->above_line, t->below_line);
  753. X  Send_end (t);
  754. X  
  755. X}
  756. X
  757. Xstatic int Handle_event_in_Scoring_Mode (t, b, p, c)
  758. X     Table t;
  759. X     Board *b;
  760. X     Play_record *p;
  761. X     player_command c;
  762. X/* Handles an event while we are in scoring mode.  Returns 0 if the
  763. X   event causes us to remain in scoring mode, and 1 otherwise.
  764. X*/
  765. X{
  766. X  switch (c->command) {
  767. X  case CMD_END:
  768. X    t->game_mode = STARTUP_MODE;
  769. X    return (1);
  770. X
  771. X  case CMD_SCORE:
  772. X    t->above_line[0] = c->data.score.above[0];
  773. X    t->above_line[1] = c->data.score.above[1];
  774. X    t->below_line[0] = c->data.score.below[0];
  775. X    t->below_line[1] = c->data.score.below[1];
  776. X    break;
  777. X
  778. X  case CMD_RECORD:
  779. X    if (!server_mode)
  780. X      Append_play_record (t->board, c->data.record.play);
  781. X    break;
  782. X
  783. X  default:
  784. X    break;
  785. X  }
  786. X  return (0);
  787. X}
  788. X
  789. Xstatic void Setup_Startup_Display ()
  790. X{
  791. X/*
  792. X  Set_Display_Mode (TALK_DISPLAY);
  793. X  Set_Input_Mode (TALK_INPUT);
  794. X*/
  795. X  Begin_timer_for_hand ();
  796. X}
  797. X
  798. Xstatic void Display_event_in_Startup_Mode 
  799. X  (t, b, p, c)
  800. X     Table t;
  801. X     Board *b;
  802. X     Play_record *p;
  803. X     player_command c;
  804. X{
  805. X  ;
  806. X}
  807. X
  808. Xstatic void Setup_Deal_Display ()
  809. X{
  810. X  ;
  811. X}
  812. X
  813. Xstatic void Display_event_in_Deal_Mode
  814. X  (t, b, p, c)
  815. X     Table t;
  816. X     Board *b;
  817. X     Play_record *p;
  818. X     player_command c;
  819. X{
  820. X  int i;
  821. X
  822. X  switch (c->command) {
  823. X
  824. X  case CMD_BEGIN:
  825. X    Local_table = t;
  826. X    Local_board = t->board;
  827. X    Local_play  = t->play_record;
  828. X
  829. X    spectator_mode = 0;
  830. X    for (i = 0; i < 4; i++)
  831. X      revealed_hands[i] = 0;
  832. X
  833. X    if (Local_play->bidding_completed) {
  834. X      Set_Display_Mode (BIDDING_DISPLAY);
  835. X      Set_Input_Mode (TALK_INPUT);
  836. X      if (!server_mode || prompt_dummy || IS_PLAYER(local_player))
  837. X    Pause ("");
  838. X    }
  839. X    break;
  840. X
  841. X  default:
  842. X    break;
  843. X  }
  844. X}
  845. X
  846. Xstatic void Prepare_for_input_during_bidding (t)
  847. X     Table t;
  848. X{
  849. X
  850. X  Board *b;
  851. X  Play_record *p;
  852. X  char buf[80];
  853. X
  854. X  b = t->board;
  855. X  p = t->play_record;
  856. X
  857. X  Display_Bidder (p->next_player);
  858. X  if (p->next_player == local_player)
  859. X    Begin_timer_for_play ();
  860. X
  861. X  if ((p->next_player == local_player) && !p->bidding_completed) {
  862. X    ring_bell ();
  863. X    if (Talking())
  864. X      Status ("PRESS <TAB> TO ENTER YOUR BID.");
  865. X  }
  866. X
  867. X  if ((t->playing_mode == PRACTICE_PLAYING_MODE) && server_mode)
  868. X    if (VACANT(t, p->next_player) && autopass_mode) {
  869. X      sprintf (buf, "%s %s BID PASS", seat_names[p->next_player],
  870. X           seat_names[p->next_player]);
  871. X      loopback_message_unformatted (Local_table, Local_Player_Connection, buf);
  872. X    }
  873. X
  874. X}
  875. X
  876. Xstatic void Setup_Bidding_Display (t, b, p)
  877. X     Table t;
  878. X     Board *b;
  879. X     Play_record *p;
  880. X/* Initializes the bidding display and global variables which are
  881. X   pertinent to the bidding.
  882. X*/
  883. X{
  884. X
  885. X  Begin_timer_for_hand ();
  886. X  Set_Display_Mode (BIDDING_DISPLAY);
  887. X  if (IS_PLAYER(local_player))
  888. X    Set_Input_Mode (BID_INPUT);
  889. X  else
  890. X    Set_Input_Mode (TALK_INPUT);
  891. X
  892. X  switch (p->no_bids % 4) {
  893. X  case 0: p->next_player = b->dealer; break;
  894. X  case 1: p->next_player = player_next[b->dealer]; break;
  895. X  case 2: p->next_player = player_partner[b->dealer]; break;
  896. X  case 3: p->next_player = player_prev[b->dealer]; break;
  897. X  }
  898. X
  899. X  pause_mode = 0;
  900. X  Prepare_for_input_during_bidding (t);
  901. X
  902. X}
  903. X
  904. Xstatic void Display_event_in_Bidding_Mode
  905. X  (t, b, p, c)
  906. X     Table t;
  907. X     Board *b;
  908. X     Play_record *p;
  909. X     player_command c;
  910. X{
  911. X  int i;
  912. X
  913. X  if (c->command == CMD_ALERT) {
  914. X    if ((local_player == player_partner[c->player_no]) && !c->data.alert)
  915. X      return;
  916. X
  917. X    i = Index_of_Last_Bid (b, p, player_partner[c->player_no]);
  918. X    if (i >= 0) {
  919. X      Display_Bid (i);
  920. X      Moderator_Comment ("ALERT!");
  921. X      ring_bell ();
  922. X    }
  923. X  } else if (c->command == CMD_BID) {
  924. X    if (c->player_no == local_player)
  925. X      End_timer_for_play ();
  926. X    Display_timer ();
  927. X    Display_Bid (p->no_bids - 1);
  928. X    Prepare_for_input_during_bidding (t);
  929. X  }
  930. X}
  931. X
  932. Xstatic void Setup_Playing_Display (t, b, p)
  933. X     Table t;
  934. X     Board *b;
  935. X     Play_record *p;
  936. X{
  937. X  int i, j, player;
  938. X
  939. X  Set_Display_Mode (PLAYING_DISPLAY);
  940. X  if (t->playing_mode == PRACTICE_PLAYING_MODE) {
  941. X    if (IS_PLAYER(local_player))
  942. X      Set_Input_Mode (PLAY_INPUT);
  943. X    else
  944. X      Set_Input_Mode (TALK_INPUT);
  945. X    for (i = 0; i < 4; i++)
  946. X      revealed_hands[i] = 1;
  947. X  } else if (IS_PLAYER(local_player) && 
  948. X         (local_player != player_partner[p->declarer]))
  949. X    Set_Input_Mode (PLAY_INPUT);
  950. X  else
  951. X    Set_Input_Mode (TALK_INPUT);
  952. X  Clear_Plays ();
  953. X
  954. X  if (IS_PLAYER(local_player))
  955. X    revealed_hands[local_player] = 1;
  956. X
  957. X  if (local_player == p->declarer)
  958. X    revealed_hands[player_partner[local_player]] = 1;
  959. X  else if (local_player == player_partner[p->declarer])
  960. X    revealed_hands[p->declarer] = 1;
  961. X
  962. X  /* If we are replaying a hand which has already been (partially) played,
  963. X     then display the plays up to this point:
  964. X  */
  965. X  player = player_next[p->declarer];
  966. X  for (i = 0; i < p->no_plays; i++) {
  967. X    if (i % 4 == 0)
  968. X      Clear_Plays ();
  969. X    Display_Play (player, p->play_list[i]);
  970. X    player = player_next[player];
  971. X    revealed_hands[player_partner[p->declarer]] = 1;
  972. X    if (i % 4 == 3) {
  973. X      for (j = 0; j < 4; j++)
  974. X    if (revealed_hands[j])
  975. X      Display_Partial_Hand (j, i);
  976. X
  977. X      if (prompt_dummy)
  978. X    Press_Return_to_Continue ("");
  979. X
  980. X      player = Winning_card(trumpsuit_of(p->contract), player,
  981. X                p->play_list[i-3], p->play_list[i-2],
  982. X                p->play_list[i-1], p->play_list[i]);
  983. X    }
  984. X  }
  985. X  p->next_player = player;
  986. X
  987. X  for (j = 0; j < 4; j++)
  988. X    if (revealed_hands[j])
  989. X      Display_Hand (j);
  990. X
  991. X  Display_Player (p->next_player);
  992. X
  993. X  if ((Next_Player (p) == local_player) || 
  994. X      (Local_table->playing_mode == PRACTICE_PLAYING_MODE))
  995. X    Compute_Default_Play ();
  996. X  else
  997. X    Clear_Default_Play ();
  998. X
  999. X  if (Next_Player (p) == local_player) {
  1000. X    Begin_timer_for_play ();
  1001. X    ring_bell ();
  1002. X    if (Talking())
  1003. X      Status ("PRESS <TAB> TO ENTER YOUR PLAY.");
  1004. X  }
  1005. X}
  1006. X
  1007. Xstatic void Display_event_in_Playing_Mode
  1008. X  (t, b, p, c, player)
  1009. X     Table t;
  1010. X     Board *b;
  1011. X     Play_record *p;
  1012. X     player_command c;
  1013. X     int player;
  1014. X{
  1015. X  int i;
  1016. X
  1017. X  if (c->command != CMD_PLAY)
  1018. X    return;
  1019. X
  1020. X  if (p->no_plays % 4 == 1)
  1021. X    Clear_Plays ();
  1022. X
  1023. X  Display_Play (player, c->data.play);
  1024. X  if (c->player_no == local_player)
  1025. X    End_timer_for_play ();
  1026. X  Display_timer ();
  1027. X
  1028. X  for (i = 0; i < 4; i++)
  1029. X    if (revealed_hands[i])
  1030. X      Display_Hand (i);
  1031. X
  1032. X  Clear_Default_Play ();
  1033. X  if ((p->no_plays % 4 == 0) && prompt_dummy) {
  1034. X    Pause ("");
  1035. X    Clear_Plays ();
  1036. X  }
  1037. X
  1038. X  if (p->no_plays == 1)
  1039. X    Display_Hand (player_partner[p->declarer]);
  1040. X
  1041. X  Display_Player (p->next_player);
  1042. X
  1043. X  if ((Next_Player (p) == local_player) || 
  1044. X      (Local_table->playing_mode == PRACTICE_PLAYING_MODE))
  1045. X    Compute_Default_Play ();
  1046. X
  1047. X  if (Next_Player (p) == local_player) {
  1048. X    Begin_timer_for_play ();
  1049. X    ring_bell ();
  1050. X    if (Talking())
  1051. X      Status ("PRESS <TAB> TO ENTER YOUR PLAY.");
  1052. X  }
  1053. X}
  1054. X
  1055. Xstatic void Setup_Scoring_Display (t, b, p)
  1056. X     Table t;
  1057. X     Board *b;
  1058. X     Play_record *p;
  1059. X{
  1060. X  char message_buf[100];
  1061. X
  1062. X  int contractor = side_of (p->declarer);
  1063. X  int honors;
  1064. X  int i, below[2], hcp;
  1065. X
  1066. X  End_timer_for_play ();
  1067. X  End_timer_for_hand ();
  1068. X  Display_timer ();
  1069. X
  1070. X  if (IS_PLAYER(local_player) && 
  1071. X      (side_of(local_player) == contractor) &&
  1072. X      (level_of (p->contract) >= 6) &&
  1073. X      (p->result > 0)) {
  1074. X    Set_Display_Mode (HELP_DISPLAY);
  1075. X    Set_Input_Mode (TALK_INPUT);
  1076. X    display_help ("slam");
  1077. X  }
  1078. X
  1079. X  if (display_mode != PLAYING_DISPLAY)
  1080. X    Set_Display_Mode (PLAYING_DISPLAY);
  1081. X  Set_Input_Mode (TALK_INPUT);
  1082. X
  1083. X  for (i = 0; i < 4; i++)
  1084. X    Display_Partial_Hand (i, 0);
  1085. X
  1086. X  switch (b->scoring_mode) {
  1087. X  case RUBBER_SCORING:
  1088. X    if (p->result == 0)
  1089. X      break;
  1090. X
  1091. X    honors = Honors_Point_Bonus (b, p);
  1092. X    if (honors == 100)
  1093. X      Moderator_Comment 
  1094. X    ("100 POINT BONUS FOR 4 HONORS IN ONE HAND");
  1095. X    else if ((honors == 150) && (trumpsuit_of(p->contract) != SUIT_NOTRUMP))
  1096. X      Moderator_Comment
  1097. X    ("150 POINT BONUS FOR ALL 5 HONORS IN ONE HAND");
  1098. X    else if (honors == 150)
  1099. X      Moderator_Comment
  1100. X    ("150 POINT BONUS FOR ALL 4 ACES IN ONE HAND");
  1101. X
  1102. X    below[0] = b->part_score[0] + p->below_line[0];
  1103. X    below[1] = b->part_score[1] + p->below_line[1];
  1104. X    if (below[contractor] >= 100) {
  1105. X      if (b->vulnerable[contractor]) {
  1106. X    if (contractor == SIDE_NS)
  1107. X      sprintf (message_buf, "%s AND %s HAVE WON THE RUBBER.",
  1108. X           PLAYER_NAME(Local_table, PLAYER_NORTH), 
  1109. X           PLAYER_NAME(Local_table, PLAYER_SOUTH));
  1110. X    else
  1111. X      sprintf (message_buf, "%s AND %s HAVE WON THE RUBBER.",
  1112. X           PLAYER_NAME(Local_table, PLAYER_EAST), 
  1113. X           PLAYER_NAME(Local_table, PLAYER_WEST));
  1114. X    Moderator_Comment (message_buf);
  1115. X      }
  1116. X    }
  1117. X    break;
  1118. X
  1119. X  case DUPLICATE_SCORING:
  1120. X  case MP_SCORING:
  1121. X  case IMP_SCORING:
  1122. X    hcp = Highcard_points (b, contractor);
  1123. X    sprintf 
  1124. X      (message_buf,
  1125. X       "HCP %d, EXPECTED SCORE: %d, ACTUAL SCORE: %d, MONO-IMPS: %5.1f",
  1126. X       hcp,
  1127. X       b->vulnerable[contractor] ?
  1128. X         MIMP_scoring_vuln[hcp]: MIMP_scoring_nonvuln[hcp],
  1129. X       (p->result >= 0)?
  1130. X         Duplicate_score_made 
  1131. X           (b->vulnerable[contractor], level_of (p->contract),
  1132. X        trumpsuit_of (p->contract), p->doubled, p->result):
  1133. X         -Duplicate_score_set
  1134. X           (b->vulnerable[contractor], level_of (p->contract),
  1135. X        trumpsuit_of (p->contract), p->doubled, p->result),
  1136. X       ((float) p->mimp_points[contractor]) * 0.5);
  1137. X    Display_Player_Comment (COMMENT_PUBLIC, "SCORE", message_buf);
  1138. X    break;
  1139. X  }
  1140. X
  1141. X  Display_Above_Line_Points ();
  1142. X  Display_Below_Line_Points ();
  1143. X  Display_Vulnerabilities ();
  1144. X}
  1145. X
  1146. Xstatic void Display_event_in_Scoring_Mode
  1147. X  (t, b, p, c)
  1148. X     Table t;
  1149. X     Board *b;
  1150. X     Play_record *p;
  1151. X     player_command c;
  1152. X{
  1153. X  switch (c->command) {
  1154. X  case CMD_SCORE:
  1155. X    Display_Above_Line_Points ();
  1156. X    Display_Below_Line_Points ();
  1157. X    break;
  1158. X
  1159. X  default:
  1160. X    break;
  1161. X  }
  1162. X}
  1163. X
  1164. Xstatic void Display_Summary_of_Hand (t, b, p)
  1165. X     Table t;
  1166. X     Board *b;
  1167. X     Play_record *p;
  1168. X{
  1169. X  FILE *fp;
  1170. X  char buf[80];
  1171. X
  1172. X  Compute_Matchpoints (b);
  1173. X  Compute_Intl_Matchpoints (b);
  1174. X
  1175. X  Clear_Plays ();
  1176. X
  1177. X  if (logfile != NULL)
  1178. X    Write_hand (logfile, b, p);
  1179. X
  1180. X  if (zhang_logfile != NULL)
  1181. X    Write_hand_compactly (zhang_logfile, t->table_no, b, p);
  1182. X
  1183. X  if (server_mode && gps_duplicate_mode) {
  1184. X    GPS_Upload_Play_Record (Local_play);
  1185. X    if (b->play_records->next == NULL)
  1186. X      Broadcast_Comment 
  1187. X    ("THIS BOARD HAS NOT BEEN PLAYED AT ANY OTHER TABLES.");
  1188. X  }
  1189. X
  1190. X  if (replay_mode && !Board_is_Available()) {
  1191. X    replay_mode = 0;
  1192. X    fp = fopen (email_filename, "w");
  1193. X    if (fp == NULL) {
  1194. X      sprintf (buf, "ERROR RE-OPENING EMAIL FILE %s: %s", email_filename,
  1195. X           sys_errlist[errno]);
  1196. X      Status (buf);
  1197. X    } else {
  1198. X      Write_Email_Duplicate_File (fp);
  1199. X      sprintf (buf, "WROTE EMAIL BOARDS TO %s.", email_filename);
  1200. X      Moderator_Comment (buf);
  1201. X      fclose (fp);
  1202. X    }
  1203. X  }
  1204. X
  1205. X  if (b->play_records->next != NULL) {
  1206. X    switch (b->scoring_mode) {
  1207. X    case RUBBER_SCORING:
  1208. X    case DUPLICATE_SCORING:
  1209. X    case MP_SCORING:
  1210. X      Sort_play_records_by_matchpoints (b);
  1211. X      break;
  1212. X    case IMP_SCORING:
  1213. X      Sort_play_records_by_imps (b);
  1214. X      break;
  1215. X    }
  1216. X
  1217. X    if (!server_mode || prompt_dummy || IS_PLAYER(local_player)) {
  1218. X      Pause ("PRESS <ESC> TO SEE THE RESULTS OF PLAY BY OTHER TABLES ...");
  1219. X      Display_First_Page_of_Scores (b);
  1220. X      while (More_Scores_to_Display()) {
  1221. X    Pause ("PRESS <ESC> TO SEE MORE RESULTS ...");
  1222. X    Display_More_Scores ();
  1223. X      }
  1224. X    }
  1225. X  }
  1226. X  
  1227. X  if (!server_mode || prompt_dummy || IS_PLAYER(local_player))
  1228. X    Pause ("PRESS <ESC> FOR THE NEXT HAND ...");
  1229. X}
  1230. X
  1231. Xstatic void main_event_loop ()
  1232. X{
  1233. X  Table t;
  1234. X  Board *b;
  1235. X  Play_record *p;
  1236. X  Message m;
  1237. X  player_command c;
  1238. X  int transition, player;
  1239. X  int prev_mode;
  1240. X
  1241. X  do {
  1242. X    Refresh_Input_Buffers ();
  1243. X    t = Wait_for_game_message ();
  1244. X    b = t->board;
  1245. X    p = t->play_record;
  1246. X    m = dequeue_message (t->game_queue);
  1247. X    c = &(m->p);
  1248. X/*    Network_Comment (m->p.command_text); */
  1249. X
  1250. X    if (c->command == CMD_SKIP) {
  1251. X      t->game_mode = SKIP_MODE;
  1252. X      pause_mode = claim_in_progress = 0;
  1253. X      transition = 1;
  1254. X    } else {
  1255. X      switch (t->game_mode) {
  1256. X      case SKIP_MODE:
  1257. X    transition = Handle_event_in_Skip_Mode (t, c);
  1258. X    break;
  1259. X
  1260. X      case STARTUP_MODE:
  1261. X    transition = Handle_event_in_Startup_Mode (t, b, p, c);
  1262. X    if (VISIBLE(t))
  1263. X      Display_event_in_Startup_Mode (t, b, p, c);
  1264. X    break;
  1265. X    
  1266. X      case DEALING_MODE:
  1267. X    transition = Handle_event_in_Deal_Mode (t, b, p, c);
  1268. X    if (VISIBLE(t))
  1269. X      Display_event_in_Deal_Mode (t, b, p, c);
  1270. X    break;
  1271. X    
  1272. X      case BIDDING_MODE:
  1273. X    transition = Handle_event_in_Bidding_Mode (t, b, p, c);
  1274. X    if (VISIBLE(c))
  1275. X      Display_event_in_Bidding_Mode (t, b, p, c);
  1276. X    if (transition && VISIBLE (c)) {
  1277. X      Clear_Default_Play ();
  1278. X      if (!server_mode || prompt_dummy || IS_PLAYER(local_player)) {
  1279. X        if (t->game_mode == PLAYING_MODE)
  1280. X          Pause ("ALL PASS -- PRESS <ESC> TO BEGIN PLAY ...");
  1281. X        else if (t->game_mode == SCORING_MODE)
  1282. X          Pause ("THROWING IN THE HAND -- PRESS <ESC> TO CONTINUE ...");
  1283. X      }
  1284. X    }
  1285. X    break;
  1286. X    
  1287. X      case PLAYING_MODE:
  1288. X    player = p->next_player;
  1289. X    transition = Handle_event_in_Playing_Mode (t, b, p, c);
  1290. X    if (VISIBLE(t))
  1291. X      Display_event_in_Playing_Mode (t, b, p, c, player);
  1292. X    break;
  1293. X    
  1294. X      case SCORING_MODE:
  1295. X    transition = Handle_event_in_Scoring_Mode (t, b, p, c);
  1296. X    if (VISIBLE(t))
  1297. X      Display_event_in_Scoring_Mode (t, b, p, c);
  1298. X    if (transition && VISIBLE(t)) {
  1299. X      prev_mode = Local_table->game_mode;
  1300. X      Local_table->game_mode = SCORING_MODE;
  1301. X      Display_Summary_of_Hand (t, b, p);
  1302. X      Local_table->game_mode = prev_mode;
  1303. X    }
  1304. X    break;
  1305. X      }
  1306. X    }
  1307. X
  1308. X    if (transition)
  1309. X      switch (t->game_mode) {
  1310. X      case SKIP_MODE:
  1311. X    Initiate_Skip_Mode (t);
  1312. X    if (VISIBLE(t)) {
  1313. X      prompt_before_hand = 1;
  1314. X      Set_Display_Mode (TALK_DISPLAY);
  1315. X      Set_Input_Mode (TALK_INPUT);
  1316. X    }
  1317. X    break;
  1318. X
  1319. X      case STARTUP_MODE:
  1320. X    Initiate_Startup_Mode (t);
  1321. X    if (VISIBLE(t))
  1322. X      Setup_Startup_Display (b, p);
  1323. X    break;
  1324. X
  1325. X      case DEALING_MODE:
  1326. X    Initiate_Deal_Mode (t);
  1327. X    if (VISIBLE(t))
  1328. X      Setup_Deal_Display (b, p);
  1329. X    break;
  1330. X
  1331. X      case BIDDING_MODE:
  1332. X    if (VISIBLE(t))
  1333. X      Setup_Bidding_Display (t, t->board, t->play_record);
  1334. X    break;
  1335. X
  1336. X      case PLAYING_MODE:
  1337. X    Record_Player_Names (t, t->board, t->play_record);
  1338. X    if (VISIBLE(t))
  1339. X      Setup_Playing_Display (t, t->board, t->play_record);
  1340. X    break;
  1341. X
  1342. X      case SCORING_MODE:
  1343. X    Initiate_Scoring_Mode (t, t->board, t->play_record);
  1344. X    if (VISIBLE(t))
  1345. X      Setup_Scoring_Display (t, t->board, t->play_record);
  1346. X    break;
  1347. X      }
  1348. X    deallocate_message (m);
  1349. X  } while (1);
  1350. X}
  1351. X
  1352. Xlong Seconds ()
  1353. X/* Returns current time in seconds. */
  1354. X{
  1355. X  struct timeval tp;
  1356. X
  1357. X  gettimeofday (&tp, NULL);
  1358. X  return (tp.tv_sec);
  1359. X}
  1360. X
  1361. Xvoid Record_playing_time ()
  1362. X{
  1363. X  long current_time = Seconds ();
  1364. X  long playing_time = current_time - startup_time;
  1365. X  GPS_Send_Playing_Time (playing_time);
  1366. X}
  1367. X
  1368. Xint Terminate_Program (termination_message)
  1369. X     char *termination_message;
  1370. X{
  1371. X  if (!abort_flag) {
  1372. X    abort_flag = 1;
  1373. X    if ((Local_table->game_mode == PLAYING_MODE) || 
  1374. X    (Local_table->game_mode == BIDDING_MODE)) {
  1375. X      if (logfile != NULL)
  1376. X    Write_hand (logfile, Local_board, Local_play);
  1377. X      if (zhang_logfile != NULL)
  1378. X    Write_hand_compactly (zhang_logfile, Local_table->table_no,
  1379. X                  Local_board, Local_play);
  1380. X    }
  1381. X    if (save_defaults)
  1382. X      Write_Initialization_File (".okdefaults");
  1383. X    Record_playing_time ();
  1384. X    if (server_mode) {
  1385. X      GPS_End_Server_Mode ();
  1386. X      server_mode = 0;
  1387. X    }
  1388. X    Refresh_Display ();
  1389. X    Send_quit (Local_table);
  1390. X    Press_Return_to_Continue (termination_message);
  1391. X  }
  1392. X  clear_screen ();
  1393. X  Reset_Terminal ();
  1394. X  exit (0);
  1395. X  return (0);
  1396. X}
  1397. X
  1398. Xint recovery_routine (parm)
  1399. X    int parm;
  1400. X{
  1401. X  Terminate_Program ("PROGRAM ABORT");
  1402. X  return (0);
  1403. X}
  1404. X
  1405. Xint Hangup_recovery_routine ()
  1406. X{
  1407. X  FILE *fp;
  1408. X
  1409. X  if (!abort_flag) {
  1410. X    abort_flag = 1;
  1411. X    if ((Local_table->game_mode == PLAYING_MODE) || 
  1412. X    (Local_table->game_mode == BIDDING_MODE)) {
  1413. X      if (logfile != NULL)
  1414. X    Write_hand (logfile, Local_board, Local_play);
  1415. X      if (zhang_logfile != NULL)
  1416. X    Write_hand_compactly (zhang_logfile, Local_table->table_no,
  1417. X                  Local_board, Local_play);
  1418. X    }
  1419. X    if (save_defaults)
  1420. X      Write_Initialization_File (".okdefaults");
  1421. X    Record_playing_time ();
  1422. X    if (server_mode) {
  1423. X      GPS_End_Server_Mode ();
  1424. X      server_mode = 0;
  1425. X    }
  1426. X    if (Local_table->board != NULL)
  1427. X      Record_Played_Board (Local_table->board);
  1428. X    fp = fopen ("okbridge.hands", "w");
  1429. X    if (fp != NULL) {
  1430. X      Write_Email_Duplicate_File (fp);
  1431. X      fclose (fp);
  1432. X    }
  1433. X    Send_quit (Local_table);
  1434. X  }
  1435. X  clear_screen ();
  1436. X  Reset_Terminal ();
  1437. X  exit (0);
  1438. X  return (0);
  1439. X}
  1440. X
  1441. Xint Quit_program ()
  1442. X{
  1443. X  Clear_Status ();
  1444. X  Continue_Comment_Display ();
  1445. X  Refresh_Display ();
  1446. X  if (Ask("ARE YOU SURE YOU WISH TO QUIT? ")) {
  1447. X    abort_flag = 1;
  1448. X    Record_playing_time ();
  1449. X    if (server_mode) {
  1450. X      GPS_End_Server_Mode ();
  1451. X      server_mode = 0;
  1452. X    }
  1453. X    if (save_defaults)
  1454. X      Write_Initialization_File (".okdefaults");
  1455. X    clear_screen ();
  1456. X    Reset_Terminal ();
  1457. X    Send_quit (Local_table);
  1458. X    exit (0);
  1459. X  }
  1460. X  return (0);
  1461. X}
  1462. X
  1463. Xint quit_error_routine ()
  1464. X{
  1465. X  if (!abort_flag) {
  1466. X    abort_flag = 1;
  1467. X#ifdef LOGFILE
  1468. X    fflush (net_log);
  1469. X#endif
  1470. X    if (server_mode) {
  1471. X      GPS_End_Server_Mode ();
  1472. X      server_mode = 0;
  1473. X    }
  1474. X    clear_screen ();
  1475. X    Reset_Terminal ();
  1476. X  }
  1477. X  kill (getpid(), SIGTRAP);
  1478. X  exit (0);
  1479. X  return (0);
  1480. X}
  1481. X
  1482. Xint socket_recovery_routine (parm)
  1483. X     int parm;
  1484. X{
  1485. X  if (!abort_flag) {
  1486. X    abort_flag = 1;
  1487. X    Record_playing_time ();
  1488. X    if (server_mode) {
  1489. X      GPS_End_Server_Mode ();
  1490. X      server_mode = 0;
  1491. X    }
  1492. X#ifdef LOGFILE
  1493. X    fflush (net_log);
  1494. X#endif
  1495. X    Moderator_Comment
  1496. X      ("NETWORK ERROR!!  YOU HAVE FOUND A BUG IN THE PROGRAM.");
  1497. X    Moderator_Comment ( "PROGRAM TERMINATING");
  1498. X    Send_quit (Local_table);
  1499. X    Pause ("");
  1500. X  }
  1501. X  clear_screen ();
  1502. X  Reset_Terminal ();
  1503. X  kill (getpid(), SIGTRAP);
  1504. X
  1505. X/*
  1506. X  access_error_routine ();
  1507. X  Terminate_Program ("THE NETWORK CONNECTIONS HAVE BEEN BROKEN!");  
  1508. X*/
  1509. X  return (0);
  1510. X}
  1511. X
  1512. Xint system_call_error_routine (parm)
  1513. X     int parm;
  1514. X{
  1515. X  if (!abort_flag) {
  1516. X    abort_flag = 1;
  1517. X#ifdef LOGFILE
  1518. X    fflush (net_log);
  1519. X#endif
  1520. X    if (server_mode) {
  1521. X      GPS_End_Server_Mode ();
  1522. X      server_mode = 0;
  1523. X    }
  1524. X    Moderator_Comment ( "INTERRUPTED SYSTEM CALL");
  1525. X  }
  1526. X  Terminate_Program ("PROGRAM TERMINATING");
  1527. X  return (0);
  1528. X}
  1529. X
  1530. Xint access_error_routine (parm)
  1531. X     int parm;
  1532. X{
  1533. X  if (!abort_flag) {
  1534. X    abort_flag = 1;
  1535. X    Record_playing_time ();
  1536. X    if (server_mode) {
  1537. X      GPS_End_Server_Mode ();
  1538. X      server_mode = 0;
  1539. X    }
  1540. X    Send_quit (Local_table);
  1541. X#ifdef LOGFILE
  1542. X    fflush (net_log);
  1543. X#endif
  1544. X    Moderator_Comment
  1545. X      ("ACCESS VIOLATION!!  YOU HAVE FOUND A BUG IN THE PROGRAM.");
  1546. X    Moderator_Comment ( "PROGRAM TERMINATING");
  1547. X/*    input_acknowledgment (-1); */
  1548. X  }
  1549. X  clear_screen ();
  1550. X  Reset_Terminal ();
  1551. X  kill (getpid(), SIGTRAP);
  1552. X  return (0);
  1553. X}
  1554. X
  1555. X
  1556. Xvoid Generate_reset (reset_type)
  1557. X     int reset_type;
  1558. X{
  1559. X  longjmp (reset_buf, reset_type);
  1560. X}
  1561. X
  1562. Xvoid Handle_reset (reset_status)
  1563. X     int reset_status;
  1564. X{
  1565. X  int seat;
  1566. X  Table t;
  1567. X  Connection c;
  1568. X
  1569. X  if (reset_status == 0)
  1570. X    return;
  1571. X
  1572. X  spectator_mode = 0;
  1573. X  for (t = Table_List; t != NULL; t = t->next) {
  1574. X    clear_all_message_queues (t);
  1575. X    t->game_mode = STARTUP_MODE;
  1576. X  }
  1577. X
  1578. X  FOREACH_CONNECTION (c)
  1579. X    c->spectator = 0;
  1580. X  for (seat = 0; seat < 4; seat++)
  1581. X    Local_table->Seats[seat].skipping = 0;
  1582. X
  1583. X  prompt_before_hand = 1;
  1584. X  claim_in_progress = 0;
  1585. X  Local_table->above_line[SIDE_NS] = Local_table->above_line[SIDE_EW] = 0;
  1586. X  Local_table->below_line[SIDE_NS] = Local_table->below_line[SIDE_EW] = 0;
  1587. X  Local_table->playing_mode = CLUB_PLAYING_MODE;
  1588. X  Reset_Status ();
  1589. X  Continue_Comment_Display ();
  1590. X  Reinitialize_Input ();
  1591. X  Set_Display_Mode (TALK_DISPLAY);
  1592. X  Set_Input_Mode (TALK_INPUT);
  1593. X
  1594. X  if (gps_duplicate_mode)
  1595. X    GPS_Dup ("END");
  1596. X  gps_duplicate_mode = 0;
  1597. X
  1598. X  switch (reset_status) {
  1599. X  case RESET_FULL:
  1600. X    Set_Display_Mode (TALK_DISPLAY);
  1601. X    Set_Input_Mode (TALK_INPUT);
  1602. X    if (server_mode)
  1603. X      FOREACH_CONNECTION (c)
  1604. X    c->state = CSTATE_CONNECTED;
  1605. X    GPS_Reset ();
  1606. X    Clear_All_Boards ();
  1607. X    if (gps_duplicate_mode)
  1608. X      GPS_Dup ("END");
  1609. X    replay_mode = 0;
  1610. X    if (client_mode) {
  1611. X      seat = local_player;
  1612. X      local_player = PLAYER_OBS;
  1613. X      Send_hello (Local_table, major_revision_level, local_player_name, seat);
  1614. X    }
  1615. X    break;
  1616. X
  1617. X  case RESET_CONNECT:
  1618. X    Close_all_connections ();
  1619. X/*    Attempt_to_connect (local_player); */
  1620. X    Attempt_to_connect (PLAYER_OBS);
  1621. X    break;
  1622. X
  1623. X  case RESET_SERVE:
  1624. X    Close_all_connections ();
  1625. X    Setup_server ();
  1626. X    hands_played = 0;
  1627. X    break;
  1628. X
  1629. X  case RESET_DISCONNECT:
  1630. X    Close_all_connections ();
  1631. X    break;
  1632. X  }
  1633. X
  1634. X}
  1635. X
  1636. Xvoid parameter_error (error_msg)
  1637. X     char *error_msg;
  1638. X{
  1639. X  printf ("Okbridge %s%s:: Error: %s\n", 
  1640. X      major_revision_level, minor_revision_level, error_msg);
  1641. X  printf ("First player starts the program on his machine with\n");
  1642. X  printf ("   okbridge [-c] [-d] [-e] [-i] [-R] <seat> <name> \n%s\n%s\n",
  1643. X      "        [-P portno] [-r replay-file] [-l load-file] [-L log-file]",
  1644. X      "        [-z# [zlog-file]]");
  1645. X  printf ("Others connect with\n");
  1646. X  printf ("   okbridge [-c] [-d] [-e] [-i] [-R] %s\n%s\n",
  1647. X      "<seat> <name> <host>","        [ ... additional parameters ... ]");
  1648. X  printf ("<seat> is one of the characters n, s, e, w\n");
  1649. X  printf ("<name> is your identifying name (ex. 'steve')\n");
  1650. X  printf ("<host> is the internet name of the first player's machine\n\n");
  1651. X  printf ("-c     is for Chicago scoring\n");
  1652. X  printf ("-d     is for Duplicate scoring\n");
  1653. X  printf ("-e     is for Email duplicate scoring\n");
  1654. X  printf ("-i     is for simulated IMP scoring\n");
  1655. X  printf ("-m     is for Modern IMP scoring\n");
  1656. X  printf ("  NOTE: Only the server can choose the scoring option.\n\n");
  1657. X  printf ("-P portno specifies the internet port number for communications\n");
  1658. X  printf ("-r replay-file specifies an email duplicate file for replay\n");
  1659. X  printf ("-l load-file specifies an email duplicate file for loading\n");
  1660. X  printf ("-L log-file specifies a logfile file saving the results of play\n");
  1661. X  printf ("-z# zlog-file specifies a table number & Zhang-format log file\n");
  1662. X  exit (1);
  1663. X}
  1664. X
  1665. Xstatic void parse_position_parameter (position_string)
  1666. X     char *position_string;
  1667. X{
  1668. X  char ch, error_buf[80];
  1669. X
  1670. X  if (strlen(position_string) == 1) {
  1671. X    ch = *position_string;
  1672. X    switch (ch) {
  1673. X    case 'n': 
  1674. X    case 'N': 
  1675. X      local_player = PLAYER_NORTH;
  1676. X      return;
  1677. X    case 'e': 
  1678. X    case 'E': 
  1679. X      local_player = PLAYER_EAST;
  1680. X      return;
  1681. X    case 's': 
  1682. X    case 'S': 
  1683. X      local_player = PLAYER_SOUTH;
  1684. X      return;
  1685. X    case 'w': 
  1686. X    case 'W': 
  1687. X      local_player = PLAYER_WEST;
  1688. X      return;
  1689. X    }
  1690. X  }
  1691. X  sprintf (error_buf, "Error -- unrecognized <seat> name: %s\n", 
  1692. X       position_string);
  1693. X  parameter_error (error_buf);
  1694. X}
  1695. X
  1696. Xtypedef  void (*signal_handler) ();
  1697. X
  1698. X#ifdef SUNOS
  1699. Xvoid Change_display_size (parm, code, scp, addr)
  1700. X     int parm, code; struct sigcontext *scp; char *addr;
  1701. X/* Computes the current dimensions of the display and updates the size of
  1702. X . the talk window appropriately.
  1703. X */
  1704. X{
  1705. X  char msg_buf[80];
  1706. X
  1707. X  Reinitialize_Terminal ();
  1708. X  Reinitialize_Display ();
  1709. X  Reinitialize_Input ();
  1710. X  Refresh_Display ();
  1711. X
  1712. X  sprintf (msg_buf, "THE CURRENT DIMENSIONS APPEAR TO BE: %d x %d\n",
  1713. X       terminal_lines, terminal_cols);
  1714. X  Display_Player_Comment (COMMENT_PRIVATE, "SIGWINCH", msg_buf);
  1715. X/*
  1716. X  restore_cursor ();
  1717. X*/
  1718. X}
  1719. X#endif SUNOS
  1720. X
  1721. X
  1722. Xvoid main (argc, argv)
  1723. X     int argc; char **argv;
  1724. X{
  1725. X        int error_value;   /* error return from setjmp/signal */
  1726. X    int argi;          /* index of current argument being processed */
  1727. X    int posi;          /* index of next positional parameter to process */
  1728. X    char *filename;    /* filename specified for log file on command line*/
  1729. X        char filename_buf[80], error_buf[80];
  1730. X        FILE *fp;          /* used only for checking the existence of files */
  1731. X    int need_to_save_context;
  1732. X    int reset_in_progress;
  1733. X    int status;
  1734. X
  1735. X    /* Various signal handlers: */
  1736. X    int recovery_routine (), Quit_program (), socket_recovery_routine (),
  1737. X        quit_error_routine (), access_error_routine (),
  1738. X        system_call_error_routine (), Hangup_recovery_routine();
  1739. X
  1740. X#define current_arg  (argv[argi])
  1741. X#define next_arg     argi++
  1742. X#define more_args    (argi < argc)
  1743. X
  1744. X#ifdef DEBUG
  1745. X#ifndef HPUX
  1746. X/* In earlier versions of the program, we have been having some problems
  1747. X   with occasional segmentation faults during the bidding.  This code
  1748. X   asks the system to create a core file if there is a segmentation fault.
  1749. X */
  1750. X    struct rlimit rlp;
  1751. X
  1752. X    getrlimit (RLIMIT_CORE, &rlp);
  1753. X    rlp.rlim_cur = rlp.rlim_max;
  1754. X    setrlimit (RLIMIT_CORE, &rlp);
  1755. X#endif
  1756. X#endif
  1757. X
  1758. X#ifdef MDEBUG
  1759. X    malloc_debug (2);
  1760. X#endif
  1761. X
  1762. X    local_player = PLAYER_OBS;
  1763. X    server_name = NULL;
  1764. X    Read_Initialization_File (".okbridgerc");
  1765. X    Read_Initialization_File (".okdefaults");
  1766. X
  1767. X    if (server_name != NULL) {
  1768. X      client_mode_requested = 1;
  1769. X      server_mode_requested = 0;
  1770. X    }
  1771. X      
  1772. X    argi = 1;
  1773. X    posi = 1;
  1774. X    while (more_args) {
  1775. X      if(*current_arg == '-') {
  1776. X        /* process a position-independent parameter. */
  1777. X        if (!strcmp(current_arg, "-d")) {
  1778. X          scoring_mode = DUPLICATE_SCORING;
  1779. X        } else if (!strcmp(current_arg, "-i")) {
  1780. X              scoring_mode = IMP_SCORING;
  1781. X        } else if (!strcmp(current_arg, "-m")) {
  1782. X              scoring_mode = MP_SCORING;
  1783. X        } else if (!strcmp(current_arg, "-R")) {
  1784. X          scoring_mode = RUBBER_SCORING;
  1785. X        } else if ((*current_arg == '-') && (*(current_arg+1) == 'p')) {
  1786. X          parse_position_parameter (current_arg+2);
  1787. X          if (posi == 1) posi++;
  1788. X        } else if (!strcmp(current_arg, "-n")) {
  1789. X          next_arg;
  1790. X          if (!more_args)
  1791. X        parameter_error 
  1792. X          ("-n parameter requires player name to follow");
  1793. X          local_player_name = strdup (current_arg);
  1794. X          if (posi == 2) posi++;
  1795. X        } else if (!strcmp(current_arg, "-s")) {
  1796. X          next_arg;
  1797. X          if (!more_args)
  1798. X        parameter_error 
  1799. X          ("-s parameter requires server name or 'ME' to follow");
  1800. X          if (!strcasecmp(current_arg, "me")) {
  1801. X        client_mode_requested = 0;
  1802. X        server_mode_requested = 1;
  1803. X          } else {
  1804. X        server_name = strdup (current_arg);
  1805. X        client_mode_requested = 1;
  1806. X        server_mode_requested = 0;
  1807. X          }
  1808. X          if (posi == 3) posi++;
  1809. X        } else if (!strcmp(current_arg, "-P")) {
  1810. X          next_arg;
  1811. X          if (!more_args)
  1812. X        parameter_error 
  1813. X            ("Error -- port number must follow -P parameter");
  1814. X          network_port = atoi (current_arg);
  1815. X          if (!network_port) {
  1816. X        sprintf (error_buf, "Error: %s\n", 
  1817. X            "-P parameter requires a positive port number");
  1818. X        parameter_error (error_buf);
  1819. X          }
  1820. X        } else if (!strcmp(current_arg, "-G")) {
  1821. X          Use_GPS = 0;
  1822. X        } else if (!strcmp(current_arg, "-b")) {
  1823. X          next_arg;
  1824. X          if (!more_args)
  1825. X        parameter_error
  1826. X          ("Error -- boards filename must follow -b parameter");
  1827. X          if ((fp = fopen(current_arg,"r")) == NULL) {
  1828. X        sprintf (error_buf, 
  1829. X             "Error -- could not open boards file %s", 
  1830. X             current_arg);
  1831. X        parameter_error (error_buf);
  1832. X          }
  1833. X          email_filename = strdup(current_arg);
  1834. X          status = Load_Email_Duplicate_File (fp);
  1835. X          if (status == -1) {
  1836. X        sprintf (error_buf, "%s is not an email duplicate file.",
  1837. X             email_filename);
  1838. X        parameter_error (error_buf);
  1839. X          } else if (status) {
  1840. X        sprintf (error_buf, "Error accessing email duplicate file %s",
  1841. X             email_filename);
  1842. X        parameter_error (error_buf);
  1843. X          }
  1844. X          fclose (fp);
  1845. X        } else if (!strcmp(current_arg, "-L")) {
  1846. X          if (logfile != NULL) fclose (logfile);
  1847. X          next_arg;
  1848. X          if (!more_args)
  1849. X        parameter_error
  1850. X          ("Error -- logfile filename must follow -L parameter");
  1851. X          if (current_arg[0] == '+') {
  1852. X        filename = current_arg + 1;
  1853. X        logfile = fopen (filename, "a");
  1854. X          } else {
  1855. X        filename = current_arg;
  1856. X        logfile = fopen (filename, "w");
  1857. X          }
  1858. X          if (logfile == NULL) {
  1859. X                sprintf (error_buf,
  1860. X             "Error -- Could not open log file %s: %s\n", 
  1861. X             filename, sys_errlist[errno]);
  1862. X        parameter_error (error_buf);
  1863. X          }
  1864. X        } else if ((current_arg[0] == '-') && (current_arg[1] == 'z')) {
  1865. X          table_no = atoi (current_arg+2);
  1866. X          if (table_no == 0) {
  1867. X        sprintf (error_buf, 
  1868. X            "Error in table number for Zhang mode: %s",
  1869. X            current_arg+2);
  1870. X        parameter_error (error_buf);
  1871. X          }
  1872. X          if ((argi < argc-1) && (argv[argi+1][0] != '-')) {
  1873. X        next_arg;
  1874. X        if (current_arg[0] == '+') {
  1875. X          filename = current_arg+1;
  1876. X          zhang_logfile = fopen (filename, "a");
  1877. X        } else {
  1878. X          filename = current_arg;
  1879. X          zhang_logfile = fopen(filename, "w");
  1880. X        }
  1881. X          } else {
  1882. X        sprintf (filename_buf, "okb_%s_rec", current_arg+2);
  1883. X        filename = filename_buf;
  1884. X        zhang_logfile = fopen (filename, "a");
  1885. X          }
  1886. X          if (zhang_logfile == NULL) {
  1887. X                sprintf (error_buf,
  1888. X             "Error -- Could not open zhang log file %s: %s", 
  1889. X            filename, sys_errlist[errno]);
  1890. X        parameter_error (error_buf);
  1891. X          }
  1892. X            } else {
  1893. X          sprintf (error_buf,
  1894. X              "Error -- unrecognized parameter: %s", current_arg);
  1895. X          parameter_error (error_buf);
  1896. X        }
  1897. X      } else {
  1898. X        /* Process a positional parameter. */
  1899. X        switch (posi) {
  1900. X        case 1: 
  1901. X          parse_position_parameter (current_arg);
  1902. X          break;
  1903. X        case 2:
  1904. X          local_player_name = strdup(current_arg);
  1905. X          break;
  1906. X        case 3:
  1907. X          server_name = strdup(current_arg);
  1908. X          server_mode_requested = 0;
  1909. X          client_mode_requested = 1;
  1910. X          break;
  1911. X        default:
  1912. X          parameter_error("Error -- too many parameters given.");
  1913. X        }
  1914. X        posi++;
  1915. X      }
  1916. X      next_arg;
  1917. X    }
  1918. X        if (local_player_name == NULL) {
  1919. X      filename = getenv("USER");
  1920. X      if (filename != NULL)
  1921. X        local_player_name = strdup (filename);
  1922. X      else
  1923. X        parameter_error
  1924. X          ("Error -- you must specify your name to play.");
  1925. X    }
  1926. X
  1927. X    if (strlen(local_player_name) > 8)
  1928. X      local_player_name[8] = '\0';
  1929. X    /* Initialize the state of the email duplicate variables: */
  1930. X
  1931. X    abort_flag = 0;
  1932. X#ifdef SIGABRT
  1933. X    signal (SIGABRT, (signal_handler) recovery_routine);
  1934. X#endif
  1935. X    signal (SIGHUP,  (signal_handler) Hangup_recovery_routine);
  1936. X    signal (SIGINT,  (signal_handler) Quit_program);
  1937. X    signal (SIGPIPE, (signal_handler) socket_recovery_routine);
  1938. X    signal (SIGURG,  (signal_handler) socket_recovery_routine);
  1939. X
  1940. X    signal (SIGQUIT, (signal_handler) quit_error_routine);
  1941. X    signal (SIGFPE,  (signal_handler) access_error_routine);
  1942. X    signal (SIGILL,  (signal_handler) access_error_routine);
  1943. X    signal (SIGBUS,  (signal_handler) access_error_routine);
  1944. X    signal (SIGSEGV, (signal_handler) access_error_routine);
  1945. X    signal (SIGSYS,  (signal_handler) system_call_error_routine);
  1946. X
  1947. X#ifdef SUNOS
  1948. X    signal (SIGWINCH, (signal_handler) Change_display_size);
  1949. X#endif SUNOS
  1950. X
  1951. X    startup_time = Seconds ();
  1952. X
  1953. X    error_value = setjmp (error_return);
  1954. X    if (error_value != 0)
  1955. X            Terminate_Program ("SIGNAL RECEIVED");
  1956. X    randomize ();
  1957. X
  1958. X    /* The order of the following initialization calls should not
  1959. X           be changed. */
  1960. X    Initialize_Network ();
  1961. X    Initialize_Terminal ();
  1962. X    Initialize_Display ();
  1963. X    Initialize_Input ();
  1964. X    initialize_help_system ();
  1965. X
  1966. X    Moderator_Comment
  1967. X      ("WELCOME TO OKBRIDGE.");
  1968. X    Moderator_Comment
  1969. X      ("COPYRIGHT (C) 1990-1992 BY MATTHEW CLEGG.  ALL RIGHTS RESERVED.");
  1970. X    Moderator_Comment
  1971. X      ("TYPE /HELP FOR INSTRUCTIONS ABOUT THIS PROGRAM");
  1972. X
  1973. X    setjmp (reset_buf);
  1974. X
  1975. X    if (Use_GPS)
  1976. X      GPS_Get_Message_of_the_Day ();
  1977. X
  1978. X#ifdef DEBUG    
  1979. X        Moderator_Comment
  1980. X      ("WARNING!! THIS VERSION OF OKBRIDGE IS UNSTABLE AND MAY CRASH!!");
  1981. X#endif
  1982. X
  1983. X/*
  1984. X    sprintf (error_buf, "%d Username = %s", strlen(User_name), User_name);
  1985. X    Moderator_Comment (error_buf);
  1986. X    sprintf (error_buf, "%d Fullname = %s", strlen(User_fullname),
  1987. X         User_fullname);
  1988. X    Moderator_Comment (error_buf);
  1989. X*/
  1990. X
  1991. X    if (server_mode_requested)
  1992. X      Setup_server ();
  1993. X    else if (client_mode_requested)
  1994. X      Attempt_to_connect (local_player);
  1995. X    else if (Use_GPS) {
  1996. X      if (!GPS_unavailable) {
  1997. X        Pause ("PRESS ESC TO SEE THE CURRENTLY PLAYING TABLES.");
  1998. X        Clear_Status ();
  1999. X        GPS_List_Tables ();
  2000. X      }
  2001. X    }
  2002. X
  2003. X    hands_played = 0;
  2004. X    need_to_save_context = 1;
  2005. X
  2006. X    Initiate_Startup_Mode (Local_table);
  2007. X    Begin_timer_for_hand ();
  2008. X
  2009. X    while (1) {
  2010. X      do {
  2011. X        reset_in_progress = setjmp (reset_buf);
  2012. X        if (reset_in_progress)
  2013. X          Handle_reset (reset_in_progress);
  2014. X      } while (reset_in_progress);
  2015. X      main_event_loop ();
  2016. X    }
  2017. X}
  2018. END_OF_FILE
  2019. if test 51146 -ne `wc -c <'bridge.c'`; then
  2020.     echo shar: \"'bridge.c'\" unpacked with wrong size!
  2021. fi
  2022. # end of 'bridge.c'
  2023. fi
  2024. echo shar: End of archive 3 \(of 14\).
  2025. cp /dev/null ark3isdone
  2026. MISSING=""
  2027. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  2028.     if test ! -f ark${I}isdone ; then
  2029.     MISSING="${MISSING} ${I}"
  2030.     fi
  2031. done
  2032. if test "${MISSING}" = "" ; then
  2033.     echo You have unpacked all 14 archives.
  2034.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2035. else
  2036.     echo You still need to unpack the following archives:
  2037.     echo "        " ${MISSING}
  2038. fi
  2039. ##  End of shell archive.
  2040. exit 0
  2041.