home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume14 / okbrdge2 / part04 < prev    next >
Encoding:
Internet Message Format  |  1993-01-26  |  54.3 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: v14i082:  okbridge2 - computer-mediated bridge game, Part04/14
  5. Message-ID: <3521@master.CNA.TEK.COM>
  6. Date: 7 Sep 92 21:41:24 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2016
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: mclegg@cs.UCSD.EDU (Matthew Clegg)
  12. Posting-number: Volume 14, Issue 82
  13. Archive-name: okbridge2/Part04
  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 4 (of 14)."
  26. # Contents:  commands.c rc.h
  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 'commands.c' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'commands.c'\"
  31. else
  32. echo shar: Extracting \"'commands.c'\" \(44917 characters\)
  33. sed "s/^X//" >'commands.c' <<'END_OF_FILE'
  34. X/* commands.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 module implements the commands which are available through the
  56. X * input processor.
  57. X *
  58. X */
  59. X
  60. X#include <stdio.h>
  61. X#include <string.h>
  62. X#include <sys/time.h>
  63. X
  64. X#include "types.h"
  65. X#include "parser.h"
  66. X#include "state.h"
  67. X#include "terminal.h"
  68. X#include "display.h"
  69. X#include "input.h"
  70. X#include "gps.h"
  71. X#include "help.h"
  72. X#include "conversation.h"
  73. X
  74. X/* extern fclose (), strcasecmp (), gettimeofday (); */
  75. X
  76. Xextern int errno;
  77. Xextern char *sys_errlist[];
  78. Xextern char *strdup();
  79. Xextern void free ();
  80. X
  81. Xextern int  pause_mode;
  82. X
  83. Xextern void Assign_seat ();
  84. Xextern void Broadcast_seat_assignment ();
  85. Xextern void Generate_reset ();
  86. Xextern void Broadcast_Comment ();
  87. Xextern void Quit_program ();
  88. X
  89. X/* The following structures define the set of commands which are available
  90. X   to the local player.
  91. X */
  92. X
  93. X
  94. Xenum
  95. X{
  96. X  INPUT_ERROR = 0,
  97. X
  98. X  INPUT_ALERT,
  99. X  INPUT_ASSIGN,
  100. X  INPUT_AUTOPASS,
  101. X  INPUT_BELL,
  102. X  INPUT_CC,
  103. X
  104. X  INPUT_CCDEF,                                                        /* JAS */
  105. X  INPUT_CLAIM,
  106. X  INPUT_CLS,
  107. X  INPUT_CONNECT,
  108. X  INPUT_DEFAULT,
  109. X
  110. X  INPUT_DISCONNECT,
  111. X  INPUT_DL,
  112. X  INPUT_DOWNLOAD,
  113. X  INPUT_DUP,
  114. X  INPUT_EAST,
  115. X
  116. X  INPUT_EMAIL,
  117. X  INPUT_FORMAL,
  118. X  INPUT_FULLNAME,
  119. X  INPUT_HELP,
  120. X  INPUT_JOIN,
  121. X
  122. X  INPUT_LHB,
  123. X  INPUT_LHO,
  124. X  INPUT_LOAD,
  125. X  INPUT_LOG,
  126. X  INPUT_MESSAGE,
  127. X
  128. X  INPUT_NAME,
  129. X  INPUT_NORTH,
  130. X  INPUT_OBS,
  131. X  INPUT_OBSERVE,
  132. X  INPUT_OPP,
  133. X
  134. X  INPUT_PAUSE,
  135. X  INPUT_PERISH,
  136. X  INPUT_PING,
  137. X  INPUT_PLAYERS,
  138. X  INPUT_PRACTICE,
  139. X
  140. X  INPUT_PROMPT,
  141. X  INPUT_PUBLISH,
  142. X  INPUT_QUIT,
  143. X  INPUT_REPLAY,
  144. X  INPUT_RESET,
  145. X
  146. X  INPUT_RESULTS,
  147. X  INPUT_REVEAL,
  148. X  INPUT_REVIEW,
  149. X  INPUT_RHB,
  150. X  INPUT_RHO,
  151. X
  152. X  INPUT_SAVE,
  153. X  INPUT_SCORE,
  154. X  INPUT_SCOREBOARD,
  155. X  INPUT_SEAT,
  156. X  INPUT_SERVE,
  157. X
  158. X  INPUT_SETCC,
  159. X  INPUT_SKIP,
  160. X  INPUT_SOUTH,
  161. X  INPUT_SPEC,
  162. X  INPUT_TABLE,
  163. X
  164. X  INPUT_TABLES,
  165. X  INPUT_TIMER,
  166. X  INPUT_WAKEUP,
  167. X  INPUT_WEST,
  168. X  INPUT_WHO,
  169. X
  170. X  INPUT_WHOIS,
  171. X  INPUT_ZLOG,
  172. X
  173. X  INPUT_MAX
  174. X    };
  175. X
  176. Xstatic void 
  177. X  Parse_alert_input (), 
  178. X  Parse_assign_input (), 
  179. X  Parse_autopass_input (),
  180. X  Parse_bell_input (), 
  181. X  Parse_cc_input (),
  182. X
  183. X  Parse_ccdef_input (),                                              /* JAS */
  184. X  Parse_claim_input (),
  185. X  Parse_cls_input (),
  186. X  Parse_connect_input (),
  187. X  Parse_default_input(), 
  188. X
  189. X  Parse_disconnect_input (), 
  190. X  Parse_download_input (),
  191. X  Parse_dup_input (),
  192. X  Parse_east_input (), 
  193. X  Parse_email_input (),
  194. X
  195. X  Parse_formal_input (),
  196. X  Parse_fullname_input (),
  197. X  Parse_help_input (), 
  198. X  Parse_join_input (),
  199. X
  200. X  Parse_lho_input (), 
  201. X  Parse_load_input (), 
  202. X  Parse_log_input (),  
  203. X  Parse_message_input (),
  204. X  Parse_name_input (), 
  205. X
  206. X  Parse_north_input (), 
  207. X  Parse_observe_input (),
  208. X  Parse_opp_input (),
  209. X  Parse_pause_input (),
  210. X
  211. X  Parse_perish_input (),
  212. X  Parse_ping_input (), 
  213. X  Parse_players_input (),
  214. X  Parse_practice_input (),
  215. X  Parse_prompt_input (),
  216. X
  217. X  Parse_publish_input (),
  218. X  Parse_quit_input (), 
  219. X  Parse_replay_input (), 
  220. X  Parse_reset_input (), 
  221. X  Parse_results_input (),
  222. X
  223. X  Parse_reveal_input (), 
  224. X  Parse_review_input(), 
  225. X  Parse_rho_input (), 
  226. X  Parse_save_input (), 
  227. X  Parse_score_input (), 
  228. X
  229. X  Parse_scoreboard_input(),
  230. X  Parse_seat_input (), 
  231. X  Parse_serve_input (),
  232. X  Parse_setcc_input (), 
  233. X  Parse_skip_input (),
  234. X
  235. X  Parse_south_input (), 
  236. X  Parse_table_input (),
  237. X  Parse_tables_input (),
  238. X  Parse_timer_input (),
  239. X  Parse_wakeup_input (), 
  240. X
  241. X  Parse_west_input (),
  242. X  Parse_who_input (), 
  243. X  Parse_whois_input (), 
  244. X  Parse_zlog_input ();
  245. X
  246. Xstatic Command_Descriptor Input_Commands [] = {
  247. X  {"ALERT",  C_EMPTY, Parse_alert_input},
  248. X  {"ASSIGN", {{F_NAME, "<player-name>"}, A_SEAT, NOP}, Parse_assign_input},
  249. X  {"AUTOPASS", C_STATE, Parse_autopass_input},
  250. X  {"BELL",   C_STATE, Parse_bell_input},
  251. X  {"CC",     C_PARAM(F_KEYWORD|F_OPTIONAL, "NS|EW|MY|BOTH"), Parse_cc_input},
  252. X
  253. X  {"CCDEF", C_PARAM(F_STRING | F_OPTIONAL, "<cc-def>"), Parse_ccdef_input},
  254. X  {"CLAIM",  C_PARAM(F_INT | F_OPTIONAL, "<no-tricks>"), Parse_claim_input},
  255. X  {"CLS",    C_EMPTY, Parse_cls_input},
  256. X  {"CONNECT",{{F_FILENAME | F_OPTIONAL, "<server-name>"},
  257. X          {F_INT | F_OPTIONAL, "<port-number>"}, NOP}, 
  258. X     Parse_connect_input},
  259. X  {"DEFAULT", C_STATE, Parse_default_input},
  260. X
  261. X  {"DISCONNECT", C_PARAM(F_NAME, "<player-name>"), Parse_disconnect_input},
  262. X  {"DL",     C_PARAM(F_FILENAME | F_OPTIONAL, "<email-file>"), 
  263. X     Parse_download_input},
  264. X  {"DOWNLOAD",C_PARAM(F_FILENAME | F_OPTIONAL, "<email-file>"), 
  265. X     Parse_download_input},
  266. X  {"DUP",     {{F_KEYWORD | F_OPTIONAL, "MP|IMP|END"}, NOP, NOP}, 
  267. X     Parse_dup_input},
  268. X  {"EAST",   C_EMPTY, Parse_east_input},
  269. X
  270. X  {"EMAIL",  C_PARAM (F_STRING, "<email-address>"), Parse_email_input},
  271. X  {"FORMAL", C_STATE, Parse_formal_input},
  272. X  {"FULLNAME", C_PARAM (F_STRING, "<full-name>"), Parse_fullname_input},
  273. X  {"HELP",   C_PARAM(F_NAME | F_OPTIONAL, "<help-topic-name>"), 
  274. X     Parse_help_input},
  275. X  {"JOIN",   C_PARAM(F_NAME | F_OPTIONAL, "<name-of-server>"), 
  276. X     Parse_join_input},
  277. X
  278. X  {"LHB",    C_PARAM(F_STRING, "<message>"), Parse_rho_input},
  279. X  {"LHO",    C_PARAM(F_STRING, "<message>"), Parse_lho_input},
  280. X  {"LOAD",   C_PARAM(F_FILENAME, "<board-file>"), Parse_load_input},
  281. X  {"LOG",    C_PARAM(F_FILENAME | F_OPTIONAL, "<logfile>"), Parse_log_input},
  282. X  {"MESSAGE",C_PARAM(F_STRING | F_OPTIONAL, "<GPS-message>"), 
  283. X     Parse_message_input},
  284. X
  285. X  {"NAME",   C_PARAM(F_NAME, "<player-name>"), Parse_name_input},
  286. X  {"NORTH",  C_EMPTY, Parse_north_input},
  287. X  {"OBS",    C_EMPTY, Parse_observe_input},
  288. X  {"OBSERVE",C_EMPTY, Parse_observe_input},
  289. X  {"OPP",    C_PARAM(F_STRING, "<message>"), Parse_opp_input},
  290. X
  291. X  {"PAUSE",  C_EMPTY, Parse_pause_input},
  292. X  {"PERISH", C_EMPTY, Parse_perish_input},
  293. X  {"PING",   C_EMPTY, Parse_ping_input},
  294. X  {"PLAYERS",C_PARAM(F_NAME | F_OPTIONAL, "<name-of-server>"), 
  295. X     Parse_players_input},
  296. X  {"PRACTICE", C_STATE, Parse_practice_input},
  297. X  {"PROMPT", C_STATE, Parse_prompt_input},
  298. X
  299. X  {"PUBLISH",C_EMPTY, Parse_publish_input},
  300. X  {"QUIT",   C_EMPTY, Parse_quit_input},
  301. X  {"REPLAY", C_PARAM(F_FILENAME, "<board-file>"), Parse_replay_input},
  302. X  {"RESET",  C_EMPTY, Parse_reset_input},
  303. X  {"RESULTS", C_PARAM(F_FILENAME | F_OPTIONAL, "<results-file-name>"), 
  304. X     Parse_results_input},
  305. X
  306. X  {"REVEAL", C_PARAM(F_NAME | F_OPTIONAL, "<player-name>"),
  307. X     Parse_reveal_input},
  308. X  {"REVIEW", C_EMPTY, Parse_review_input},
  309. X  {"RHB",    C_PARAM(F_STRING, "<message>"), Parse_lho_input},
  310. X  {"RHO",    C_PARAM(F_STRING, "<message>"), Parse_rho_input},
  311. X  {"SAVE",   C_PARAM(F_FILENAME | F_OPTIONAL, "<board-file>"), 
  312. X     Parse_save_input},
  313. X
  314. X  {"SCORE",  C_PARAM(F_KEYWORD, PARSER_SCORE), Parse_score_input},
  315. X  {"SCOREBOARD", C_EMPTY, Parse_scoreboard_input},
  316. X  {"SEAT",   C_SEAT, Parse_seat_input},
  317. X  {"SERVE",  C_PARAM(F_INT | F_OPTIONAL, "<port-number>"), Parse_serve_input},
  318. X  {"SETCC",  C_PARAM(F_STRING | F_OPTIONAL, "<convention-card>"), 
  319. X     Parse_setcc_input},
  320. X
  321. X  {"SKIP",   C_PARAM(F_INT | F_OPTIONAL, "<skip-count>"), Parse_skip_input},
  322. X  {"SOUTH",  C_EMPTY, Parse_south_input},
  323. X  {"SPEC",   C_PARAM(F_NAME | F_OPTIONAL, "<player-name>"),
  324. X     Parse_reveal_input},
  325. X  {"TABLE",  C_PARAM(F_INT, "<table-number>"), Parse_table_input},
  326. X  {"TABLES", C_EMPTY, Parse_tables_input},
  327. X
  328. X  {"TIMER",  C_STATE, Parse_timer_input},
  329. X  {"WAKEUP", C_PARAM(F_NAME | F_OPTIONAL, "<player-name> | ALL"), 
  330. X     Parse_wakeup_input},
  331. X  {"WEST",   C_EMPTY, Parse_west_input},
  332. X  {"WHO",    C_EMPTY, Parse_who_input},
  333. X  {"WHOIS",  C_PARAM(F_NAME | F_OPTIONAL, "<player-name>"), Parse_whois_input},
  334. X
  335. X  {"ZLOG",   C_PARAM(F_FILENAME | F_OPTIONAL, "<logfile>"), Parse_zlog_input},
  336. X  END_PARSE_TABLE
  337. X};
  338. X
  339. Xchar *autoload_file = NULL;     /* The name of the file from which we
  340. X                   will initially try to load a sequence
  341. X                   of boards, if we are north in email mode. */
  342. Xchar *autosave_file = NULL;     /* The name of the file to which we will
  343. X                   automatically save the boards that we
  344. X                   have played. */
  345. X
  346. Xint claim_in_progress = 0;      /* TRUE if we are currently processing a
  347. X                   claim request.  This blocks us from making
  348. X                   another claim. */
  349. X
  350. Xextern FILE *logfile;
  351. Xextern FILE *zhang_logfile;
  352. X
  353. Xextern char *email_error_message;
  354. Xextern int server_mode;
  355. X
  356. Xextern char *Get_CC_Value();                                          /* JAS */
  357. Xextern int Define_CC();                                               /* JAS */
  358. Xextern void Display_All_CCs();                                        /* JAS */
  359. X
  360. Xextern int No_connections ();
  361. X
  362. Xextern int timer_is_on;
  363. Xextern struct timeval ping_start;
  364. X
  365. Xstatic char msg_buf[100];         /* A buffer for error messages. */
  366. X
  367. Xstatic void load_email_file (filename)
  368. X     char *filename;
  369. X/* Attempts to read a sequence of deals from the email duplicate file
  370. X . with name filename.
  371. X */
  372. X{
  373. X  FILE *f = fopen (filename, "r");
  374. X  int status;
  375. X
  376. X  if (f == NULL) {
  377. X    sprintf (msg_buf, "COULD NOT OPEN FILE %s: %s", filename, 
  378. X         sys_errlist[errno]);
  379. X    Status (msg_buf);
  380. X    return;
  381. X  }
  382. X
  383. X  Clear_All_Boards ();
  384. X  if (gps_duplicate_mode)
  385. X    GPS_Dup ("END");
  386. X  gps_duplicate_mode = 0;
  387. X  status = Load_Email_Duplicate_File (f);
  388. X  fclose (f);
  389. X  if (status == 1) {
  390. X    sprintf (msg_buf, "%s IS NOT AN EMAIL DUPLICATE FILE.", filename);
  391. X    Status (msg_buf);
  392. X    replay_mode = 0;
  393. X  } else if (status) {
  394. X    sprintf (msg_buf, "ERROR READING %s.", filename);
  395. X    Status (msg_buf);
  396. X    replay_mode = 0;
  397. X  } else {
  398. X    Send_skip (Local_table);
  399. X    sprintf (msg_buf, "LOADED EMAIL BOARDS FROM %s.", filename);
  400. X    Moderator_Comment (msg_buf);
  401. X    email_filename = strdup (filename);
  402. X  }
  403. X
  404. X}
  405. X
  406. Xstatic void save_email_file (filename)
  407. X     char *filename;
  408. X{
  409. X  FILE *f = fopen (filename, "w");
  410. X
  411. X  if (f == NULL) {
  412. X    sprintf (msg_buf, "COULD NOT OPEN FILE %s: %s", filename, 
  413. X         sys_errlist[errno]);
  414. X    Status (msg_buf);
  415. X    return;
  416. X  }
  417. X
  418. X  Write_Email_Duplicate_File (f);
  419. X  fclose (f);
  420. X
  421. X  sprintf (msg_buf, "SAVED EMAIL BOARDS TO %s.", filename);
  422. X  Moderator_Comment (msg_buf);
  423. X}
  424. X
  425. Xvoid Review_Bidding ()
  426. X/* Generates a review of the bidding. */
  427. X{
  428. X  int mode = Local_table->game_mode;
  429. X  int current_input_mode = input_mode;
  430. X  int current_display_mode = display_mode;
  431. X
  432. X  if (FORMAL(Local_table))
  433. X    Status ("THE BIDDING CANNOT BE REVIEW DURING FORMAL PLAY.");
  434. X  else if ((mode == PLAYING_MODE) || (mode == SCORING_MODE)) {
  435. X    Set_Display_Mode (BIDDING_DISPLAY);
  436. X    Set_Input_Mode (TALK_INPUT);
  437. X    Pause ("PRESS <ESC> TO RETURN TO PLAY ...");
  438. X    Set_Display_Mode (current_display_mode);
  439. X    Set_Input_Mode (current_input_mode);
  440. X  } else 
  441. X    Status ("THE BIDDING CANNOT BE REVIEWED NOW.");
  442. X  
  443. X  Refresh_Input_Buffers ();
  444. X}
  445. X
  446. Xstatic int Partner_has_bid (t, b, p, player)
  447. X     Table t;
  448. X     Board *b;
  449. X     Play_record *p;
  450. X     int player;
  451. X/* Returns true if the partner of p has bid. */
  452. X{
  453. X  int partner = player_partner[player];
  454. X  int i, bidder;
  455. X
  456. X  if (p->no_bids > 3)
  457. X    return (1);
  458. X
  459. X  bidder = b->dealer;
  460. X  for (i = 0; i < p->no_bids; i++)
  461. X    if (bidder == partner)
  462. X      return (1);
  463. X    else
  464. X      bidder = player_next [bidder];
  465. X
  466. X  return (0);
  467. X}
  468. X
  469. Xstatic void Parse_alert_input ()
  470. X/* ALERT
  471. X . Sends an alert message showing that partner's most recent bid is unusual.
  472. X */
  473. X{
  474. X  if (IS_OBSERVER(local_player))
  475. X    Status ("OBSERVERS MAY NOT USE THE ALERT COMMAND.");
  476. X  else if (Local_table->game_mode != BIDDING_MODE)
  477. X    Status ("YOU MAY ONLY ALERT DURING BIDDING MODE.");
  478. X  else if (!Partner_has_bid (Local_table,Local_board,Local_play,local_player))
  479. X    Status ("YOUR PARTNER HAS NOT BID YET.");
  480. X  else
  481. X    Send_alert (Local_table, !FORMAL(Local_table));
  482. X
  483. X}
  484. X
  485. Xstatic void Parse_assign_input (player, seat)
  486. X     char *player; int *seat;
  487. X{
  488. X  Connection c;
  489. X
  490. X  if (!server_mode) {
  491. X    Status ("ONLY THE SERVER CAN USE THE /ASSIGN COMMAND.");
  492. X    return;
  493. X  }
  494. X
  495. X  FOREACH_PLAYER(c, Local_table) {
  496. X    if (!strcasecmp(player, c->player_name))
  497. X      break;
  498. X  }
  499. X
  500. X  if (c == NULL) {
  501. X    sprintf (msg_buf, "THERE IS NO PLAYER NAMED %s", player);
  502. X    Status (msg_buf);
  503. X    return;
  504. X  }
  505. X
  506. X  if (IS_PLAYER(*seat) && OCCUPIED(Local_table, *seat)) {
  507. X    sprintf (msg_buf, "THE %s SEAT IS ALREADY OCCUPIED.", seat_names[*seat]);
  508. X    Status (msg_buf);
  509. X    return;
  510. X  }
  511. X
  512. X  sprintf (msg_buf, "%s %s SEATREQ %s", seat_names[c->seat], c->player_name,
  513. X       seat_names[*seat]);
  514. X  loopback_message_unformatted (c->table, c, msg_buf);
  515. X}
  516. X
  517. Xstatic void Parse_autopass_input (a)
  518. X     int *a;
  519. X/* AUTOPASS [ON|OFF]
  520. X . The AUTOPASS command controls whether or not the moderator will 
  521. X . automatically provide "PASS" bids for absent players during practice mode.
  522. X */
  523. X{
  524. X  if (client_mode) {
  525. X    Status ("ONLY THE SERVER MAY SPECIFY THE AUTOPASS MODE.");
  526. X    return;
  527. X  }
  528. X
  529. X  if (a != NULL) autopass_mode = *a;
  530. X  sprintf (msg_buf, "AUTOPASS MODE IS NOW %s.", autopass_mode? "ON": "OFF");
  531. X  Moderator_Comment (msg_buf);
  532. X}
  533. X
  534. Xstatic void Parse_bell_input (b)
  535. X     int *b;
  536. X/* BELL [ON|OFF]
  537. X . The BELL command updates the state of the bell and/or displays its
  538. X . current state.  
  539. X */
  540. X{
  541. X  if (b != NULL) bell_is_on = *b;
  542. X  sprintf (msg_buf, "THE BELL IS NOW %s.", bell_is_on? "ON": "OFF");
  543. X  Moderator_Comment (msg_buf);
  544. X  ring_bell ();
  545. X}
  546. X
  547. X
  548. Xstatic void Parse_cc_input (whose)
  549. X     int *whose;
  550. X{
  551. X  int they;
  552. X
  553. X  if (whose == NULL) {
  554. X    if (local_player < 4) {
  555. X      they = side_of(player_next[local_player]);
  556. X      if (conventions[they] == NULL)
  557. X    Status ("THEY HAVE NOT SPECIFIED THEIR CONVENTION CARD YET.");
  558. X      else
  559. X    Status (conventions[they]);
  560. X    } else {
  561. X      if ((conventions[0] == NULL) && (conventions[1] == NULL))
  562. X    Status
  563. X      ("NEITHER SIDE HAS SPECIFIED A CONVENTION CARD YET.");
  564. X      else {
  565. X    if (conventions[0] != NULL)
  566. X      Display_Player_Comment (COMMENT_PUBLIC, "N-S", conventions[0]);
  567. X    if (conventions[1] != NULL)
  568. X      Display_Player_Comment (COMMENT_PUBLIC, "E-W", conventions[1]);
  569. X      }
  570. X    }
  571. X  } else {
  572. X    if (*whose < 2) {
  573. X      if (conventions[*whose] == NULL) {
  574. X    sprintf (msg_buf, "%s %s", *whose? "E-W": "N-S",
  575. X         "HAVE NOT SPECIFIED THEIR CONVENTION CARD YET.");
  576. X    Status (msg_buf);
  577. X      } else
  578. X    Status (conventions[*whose]);
  579. X    } else if (*whose == 2) {
  580. X      if (local_cc == NULL)
  581. X    Status ("YOU HAVE NOT SPECIFIED YOUR CONVENTION CARD YET.");
  582. X      else
  583. X    Status (local_cc);
  584. X    } else {
  585. X      if ((conventions[0] == NULL) && (conventions[1] == NULL))
  586. X    Status
  587. X      ("NEITHER SIDE HAS SPECIFIED A CONVENTION CARD YET.");
  588. X      else {
  589. X    if (conventions[0] != NULL)
  590. X      Display_Player_Comment (COMMENT_PUBLIC, "N-S", conventions[0]);
  591. X    if (conventions[1] != NULL)
  592. X      Display_Player_Comment (COMMENT_PUBLIC, "E-W", conventions[1]);
  593. X      }
  594. X    }
  595. X  }
  596. X
  597. X}
  598. X
  599. X
  600. Xstatic void Parse_ccdef_input(cc)                                 /* JAS */
  601. X     char *cc;
  602. X{
  603. X  if (!cc)
  604. X  {
  605. X    Display_All_CCs(Moderator_Comment);
  606. X  }
  607. X  else
  608. X  {
  609. X    if (Define_CC(cc, Status))
  610. X    {
  611. X      /* returns 1 on error */
  612. X      sprintf (msg_buf, "ERROR DEFINING CC: %s", cc);
  613. X      Status (msg_buf);
  614. X    }
  615. X  }
  616. X}
  617. X
  618. Xstatic int  Claim_responses_received_event ()
  619. X{
  620. X  return (claim_responses == 2);
  621. X}
  622. X
  623. Xstatic void Parse_claim_input (n)
  624. X     int *n;
  625. X/* CLAIM [n]
  626. X . The CLAIM command is used by declarer to finish the hand early,
  627. X . claiming an additional number of tricks.  If n is omitted, then
  628. X . all remaining tricks are claimed.
  629. X */
  630. X{
  631. X  int tricks_claimed;
  632. X  int tricks_played = Local_play->tricks[0] + Local_play->tricks[1];
  633. X
  634. X  if (Local_table->game_mode != PLAYING_MODE) {
  635. X    Status ("YOU MAY ONLY CLAIM DURING THE PLAY OF THE HAND.");
  636. X    return;
  637. X  } else if ((Local_table->playing_mode != PRACTICE_PLAYING_MODE) &&
  638. X         (Local_play->declarer != local_player)) {
  639. X    Status ("ONLY THE DECLARER MAY MAKE A CLAIM.");
  640. X    return;
  641. X  } else if (claim_in_progress) {
  642. X    Status ("A CLAIM IS ALREADY IN PROGRESS.  YOU MUST WAIT TO CLAIM AGAIN.");
  643. X    return;
  644. X  }
  645. X
  646. X  if (n == NULL)
  647. X    tricks_claimed = 13 - tricks_played;
  648. X  else if (*n >= 0)
  649. X    tricks_claimed = *n;
  650. X  else
  651. X    tricks_claimed = 13 - tricks_played + *n;
  652. X
  653. X  if ((tricks_claimed < 0) || (tricks_claimed + tricks_played > 13)) {
  654. X    sprintf (msg_buf, "ILLEGAL CLAIM -- YOU MAY CLAIM UP TO %d TRICKS.",
  655. X         13 - tricks_played);
  656. X    Status (msg_buf);
  657. X    return;
  658. X  }
  659. X
  660. X  if (Local_table->playing_mode == PRACTICE_PLAYING_MODE) {
  661. X    Send_claim (Local_table, tricks_claimed);
  662. X    return;
  663. X  }
  664. X
  665. X  claim_in_progress = 1;
  666. X  Send_claimreq (Local_table, tricks_claimed);
  667. X  Status ("WAITING FOR A REPLY TO YOUR CLAIM ...");
  668. X  Clear_Focus_Buffer ();
  669. X  Set_Input_Mode (TALK_INPUT);
  670. X
  671. X  Refresh_Input_Buffers ();
  672. X  Wait_for_event_at_game_level (Claim_responses_received_event);
  673. X
  674. X  Set_Input_Mode (PLAY_INPUT);
  675. X
  676. X  if (claim_accepted) {
  677. X    Clear_Status ();
  678. X    Send_claim (Local_table, tricks_claimed);
  679. X  }
  680. X
  681. X  claim_in_progress = 0;
  682. X}
  683. X
  684. Xstatic void Parse_cls_input ()
  685. X{
  686. X  Clear_Comment_Display ();
  687. X}
  688. X
  689. Xstatic void Parse_connect_input (s, p)
  690. X     char *s; int *p;
  691. X/* CONNECT [server] [ip]
  692. X . The CONNECT command is used by a client to establish a connection
  693. X . with a server. 
  694. X */
  695. X{
  696. X
  697. X  if ((s == NULL) && (server_name == NULL)) {
  698. X    Status ("YOU MUST SPECIFY THE SERVER TO WHICH TO CONNECT.");
  699. X    return;
  700. X  }
  701. X
  702. X  if (server_mode && (No_connections(Local_table) > 1)) {
  703. X    Moderator_Comment 
  704. X      ("WARNING! THIS WILL DISCONNECT THE PLAYERS AT THIS TABLE!");
  705. X    if (!Ask("ARE YOU SURE YOU WISH TO DO THIS? "))
  706. X    return;
  707. X  } else if (client_mode && (Local_table->game_mode != STARTUP_MODE) &&
  708. X         IS_PLAYER(local_player)) {
  709. X    Moderator_Comment
  710. X      ("WARNING! THIS WILL DISCONNECT YOU FROM THIS TABLE!");
  711. X    if (!Ask("ARE YOU SURE YOU WISH TO DO THIS? "))
  712. X      return;
  713. X  }
  714. X
  715. X  if (client_mode)
  716. X    Send_quit (Local_table);
  717. X
  718. X  if (p != NULL)
  719. X    network_port = *p;
  720. X  else
  721. X    network_port = DEFAULT_PORT;
  722. X
  723. X  if (s != NULL)
  724. X    server_name = strdup (s);
  725. X
  726. X  Generate_reset (RESET_CONNECT);
  727. X}
  728. X
  729. X/*
  730. Xstatic void Parse_deal_input (d)
  731. X     int *d;
  732. X.* DEAL [n]
  733. X . If we are the server in email duplicate mode, then deals n hands
  734. X . for play.  If n is negative, then deals continuously, i.e., until
  735. X . the program is terminated or a reset is given.  If n is zero, then
  736. X . deals 16 hands.
  737. X *.
  738. X{
  739. X  if (total_no_deals < 0)
  740. X    Moderator_Comment ("ENTERING CONTINUOUS DEAL MODE.");
  741. X  else {
  742. X    sprintf (msg_buf, "BEGINNING A SEQUENCE OF %d DEALS.", total_no_deals);
  743. X    Moderator_Comment (msg_buf);
  744. X  }
  745. X  replaying_mode = 0;
  746. X  current_board = NULL;
  747. X}
  748. X*/
  749. X
  750. Xstatic void Parse_default_input (d)
  751. X     int *d;
  752. X/* DEFAULT [ON|OFF]
  753. X . The DEFAULT command controls whether or not default inputs will be
  754. X . automatically provided for the user.  
  755. X */
  756. X{
  757. X  if (d != NULL) default_plays = *d;
  758. X  sprintf (msg_buf, "DEFAULT MODE IS NOW %s", default_plays? "ON": "OFF");
  759. X  Moderator_Comment (msg_buf);
  760. X}
  761. X
  762. Xstatic void Parse_download_input (d)
  763. X     char *d;
  764. X/* DOWNLOAD [<email-filename>]
  765. X . Downloads an email duplicate file from the GPS or requests a list of
  766. X . the available email duplicate files.
  767. X */
  768. X{
  769. X  if (d == NULL)
  770. X    GPS_Directory ();
  771. X  else
  772. X    GPS_Download (d);
  773. X}
  774. X
  775. Xstatic void Parse_dup_input (mode)
  776. X     int *mode;
  777. X/* DUP [MP|IMP|END]
  778. X . Initiates or terminates GPS duplicate mode.
  779. X */
  780. X{
  781. X  if (!server_mode) {
  782. X    Status ("ONLY THE SERVER MAY REQUEST GPS DUPLICATE MODE.");
  783. X    return;
  784. X  }
  785. X
  786. X  if ((mode != NULL) && (*mode == 2)) {
  787. X    if (gps_duplicate_mode) {
  788. X      GPS_Dup ("END");
  789. X      gps_duplicate_mode = 0;
  790. X      if ((Local_table->game_mode == BIDDING_MODE) ||
  791. X      (Local_table->game_mode == PLAYING_MODE))
  792. X    Send_skip (Local_table);
  793. X    }
  794. X    return;
  795. X  }
  796. X
  797. X  Local_table->playing_mode = CLUB_PLAYING_MODE;
  798. X  if ((mode == NULL) || (*mode == 1))
  799. X    GPS_Dup ("IMP");
  800. X  else
  801. X    GPS_Dup ("MP");
  802. X  gps_duplicate_mode = 1;
  803. X
  804. X  Local_table->above_line[SIDE_NS] = Local_table->above_line[SIDE_EW] = 0;
  805. X  Local_table->below_line[SIDE_NS] = Local_table->below_line[SIDE_EW] = 0;
  806. X
  807. X  if ((Local_table->game_mode != STARTUP_MODE) &&
  808. X      (Local_table->game_mode != SCORING_MODE))
  809. X    Send_skip (Local_table);
  810. X}
  811. X     
  812. Xstatic void Parse_disconnect_input (player)
  813. X     char *player;
  814. X{
  815. X  Connection p;
  816. X
  817. X  if (!server_mode) {
  818. X    Status ("THE DISCONNECT COMMAND CAN ONLY BE USED BY THE SERVER.");
  819. X    return;
  820. X  }
  821. X
  822. X  if (!strcasecmp(player, "NORTH"))
  823. X    p = Local_table->Seats[PLAYER_NORTH].connection;
  824. X  else if (!strcasecmp(player, "EAST"))
  825. X    p = Local_table->Seats[PLAYER_EAST].connection;
  826. X  else if (!strcasecmp(player, "SOUTH"))
  827. X    p = Local_table->Seats[PLAYER_SOUTH].connection;
  828. X  else if (!strcasecmp(player, "WEST"))
  829. X    p = Local_table->Seats[PLAYER_WEST].connection;
  830. X  else {
  831. X    FOREACH_CONNECTION (p)
  832. X      if (!strcasecmp(player, p->player_name))
  833. X    break;
  834. X    if (p == NULL) {
  835. X      sprintf (msg_buf, "THERE IS NO PLAYER NAMED %s", player);
  836. X      Status (msg_buf);
  837. X      return;
  838. X    }
  839. X  }
  840. X
  841. X  if (p == NULL) {
  842. X    sprintf (msg_buf, "THE %s SEAT IS NOT CURRENTLY OCCUPIED.", player);
  843. X    Status (msg_buf);
  844. X    return;
  845. X  }
  846. X
  847. X  if (p->local) {
  848. X    Status ("YOU CANNOT DISCONNECT YOURSELF!");
  849. X    return;
  850. X  }
  851. X
  852. X  sprintf (msg_buf, "THE CONNECTION WITH %s HAS BEEN CLOSED.",p->player_name);
  853. X  close_connection (p);
  854. X  Broadcast_Comment (msg_buf);
  855. X}
  856. X
  857. Xstatic void Parse_email_input (a)
  858. X     char *a;
  859. X/* EMAIL <email-address>
  860. X * Specifies the local player's email address.
  861. X */
  862. X{
  863. X  if (local_player_email != NULL)
  864. X    free (local_player_email);
  865. X
  866. X  local_player_email = strdup (a);
  867. X  sprintf (msg_buf, "YOUR EMAIL ADDRESS IS NOW %s.", a);
  868. X  Status (msg_buf);
  869. X  Send_email (Local_table, local_player_email);
  870. X}
  871. X
  872. Xstatic void Set_playing_mode (m)
  873. X     int m;
  874. X/* If m is -1, then displays the current playing mode.  Otherwise,
  875. X * if we are the server, then sets the current playing mode to *m.
  876. X */
  877. X{
  878. X  Clear_Focus_Buffer ();
  879. X
  880. X  if ((m == -1) || (m == Local_table->playing_mode)) {
  881. X    switch (Local_table->playing_mode) {
  882. X    case CLUB_PLAYING_MODE:
  883. X      Status ("WE ARE PLAYING CLUB STYLE BRIDGE.");
  884. X      return;
  885. X    case PRACTICE_PLAYING_MODE:
  886. X      Status ("WE ARE PLAYING PRACTICE HANDS.");
  887. X      return;
  888. X    case FORMAL_PLAYING_MODE:
  889. X      Status ("WE ARE PLAYING FORMAL BRIDGE.");
  890. X      return;
  891. X    }
  892. X  }
  893. X
  894. X  if (client_mode) {
  895. X    Status ("ONLY THE SERVER MAY CHANGE THE PLAYING MODE.");
  896. X    return;
  897. X  }
  898. X
  899. X  if ((Local_table->game_mode == BIDDING_MODE) || 
  900. X      (Local_table->game_mode == PLAYING_MODE))
  901. X    if (!Ask("THIS WILL END THE CURRENT HAND.  DO YOU WISH TO DO THIS? "))
  902. X      return;
  903. X
  904. X  Local_table->playing_mode = m;
  905. X  Send_skip (Local_table);
  906. X}
  907. X
  908. Xstatic void Parse_formal_input (f)
  909. X     int *f;
  910. X/* FORMAL [ON|OFF]
  911. X . The formal command controls whether talk messages are sent to all of
  912. X . the other players or just to the opponents.
  913. X */
  914. X{
  915. X  if (f == NULL)
  916. X    Set_playing_mode (FORMAL_PLAYING_MODE);
  917. X  else
  918. X    Set_playing_mode (*f? FORMAL_PLAYING_MODE: CLUB_PLAYING_MODE);
  919. X}
  920. X
  921. Xstatic void Parse_fullname_input (f)
  922. X     char *f;
  923. X/* FULLNAME <player-full-name>
  924. X * Specifies the player's full name. 
  925. X */
  926. X{
  927. X  if (local_player_full_name != NULL)
  928. X    free (local_player_full_name);
  929. X
  930. X  local_player_full_name = strdup (f);
  931. X  sprintf (User_fullname, "%s", f);
  932. X  Status ("YOUR FULL NAME HAS BEEN SET.");
  933. X  Send_fullname (Local_table, User_fullname);
  934. X}
  935. X
  936. Xstatic int Exit_help_mode_event ()
  937. X{
  938. X  return (!pause_mode);
  939. X}
  940. X
  941. Xstatic void Parse_help_input (t)
  942. X     char *t;
  943. X/* HELP [<help-topic-name>]
  944. X . Gives help on the named topic, or a general description of the program
  945. X . if no topic is specified.
  946. X */
  947. X{
  948. X  int input_save = input_mode;
  949. X  int display_save = display_mode;
  950. X
  951. X  Clear_Focus_Buffer ();
  952. X  Set_Display_Mode (HELP_DISPLAY);
  953. X  Set_Input_Mode (TALK_INPUT);
  954. X  if (t != NULL)
  955. X    display_help (t);
  956. X  else {
  957. X    Lock_Status ("TYPE THE NAME OF A TOPIC OR PRESS <ESC> TO EXIT HELP.");
  958. X    browse_help ("");
  959. X    Refresh_Input_Buffers ();
  960. X    pause_mode = 1;
  961. X    Wait_for_event_at_game_level (Exit_help_mode_event);
  962. X    Unlock_Status ();
  963. X  }
  964. X  Set_Display_Mode (display_save);
  965. X  Set_Input_Mode (input_save);
  966. X
  967. X}
  968. X
  969. Xstatic void Parse_join_input (s)
  970. X     char *s;
  971. X/* JOIN [<server-name>]
  972. X . Joins the table being served by the named person.  If the server-name
  973. X . is omitted, then joins the most recently opened table.
  974. X */
  975. X{
  976. X  char server_ip_buf[60];
  977. X  int server_port, status;
  978. X
  979. X  status = GPS_Get_Server_IP (s, server_ip_buf, &server_port);
  980. X  if (status) {
  981. X    if (s == NULL)
  982. X      Status ("THERE ARE NO TABLES CURRENTLY BEING SERVED.");
  983. X    else
  984. X      Status ("NO TABLE IS BEING HOSTED BY THAT PERSON.");
  985. X    return;
  986. X  }
  987. X
  988. X  if (server_mode && (No_connections(Local_table) > 1)) {
  989. X    Moderator_Comment 
  990. X      ("WARNING! THIS WILL DISCONNECT THE PLAYERS AT THIS TABLE!");
  991. X    if (!Ask("ARE YOU SURE YOU WISH TO DO THIS? "))
  992. X    return;
  993. X  } else if (client_mode && (Local_table->game_mode != STARTUP_MODE) &&
  994. X         IS_PLAYER(local_player)) {
  995. X    Moderator_Comment
  996. X      ("WARNING! THIS WILL DISCONNECT YOU FROM THIS TABLE!");
  997. X    if (!Ask("ARE YOU SURE YOU WISH TO DO THIS? "))
  998. X      return;
  999. X  }
  1000. X
  1001. X  if (client_mode)
  1002. X    Send_quit (Local_table);
  1003. X
  1004. X  network_port = server_port;
  1005. X  server_name = strdup (server_ip_buf);
  1006. X
  1007. X  Generate_reset (RESET_CONNECT);
  1008. X}
  1009. X
  1010. Xstatic void Parse_lho_input (m)
  1011. X     char *m;
  1012. X/* LHO <message>
  1013. X . Sends a message to the left-hand opponent.
  1014. X */
  1015. X{
  1016. X  if (IS_OBSERVER(local_player))
  1017. X    Status ("PRIVATE MESSAGES CANNOT BE SENT BY AN OBSERVER.");
  1018. X  else {
  1019. X    Display_Player_Comment (COMMENT_PRIVATE, local_player_name, m);
  1020. X    Send_talk (Local_table, TALK_RCPT_LHO, m);
  1021. X  }
  1022. X}
  1023. X
  1024. Xstatic void Parse_load_input (f)
  1025. X     char *f;
  1026. X/* LOAD <filename>
  1027. X . The LOAD command is used by the server to LOAD a sequence of email
  1028. X . boards from a file.  
  1029. X */
  1030. X{
  1031. X  if (client_mode) {
  1032. X    Status ("CLIENTS CANNOT LOAD EMAIL BOARDS.");
  1033. X    return;
  1034. X  }
  1035. X
  1036. X  if (gps_duplicate_mode)
  1037. X    GPS_Dup ("END");
  1038. X  replay_mode = gps_duplicate_mode = 0;
  1039. X  load_email_file (f);
  1040. X}
  1041. X
  1042. Xstatic void Parse_log_input (f)
  1043. X     char *f;
  1044. X/* LOG <filename>
  1045. X . The LOG command opens a file to which the results of play will be
  1046. X . recorded, or it closes a currently open logfile if no filename is
  1047. X . specified.  
  1048. X */
  1049. X{
  1050. X  char *filename;
  1051. X
  1052. X  if (f == NULL) {
  1053. X    if (logfile == NULL)
  1054. X      Moderator_Comment ("THERE IS NO OPEN LOGFILE.");
  1055. X    else {
  1056. X      fclose (logfile);
  1057. X      logfile = NULL;
  1058. X      Moderator_Comment ("THE LOG FILE HAS BEEN CLOSED.");
  1059. X    }
  1060. X    return;
  1061. X  } else {
  1062. X    if (logfile != NULL) fclose (logfile);
  1063. X    if (f[0] == '+') {
  1064. X      filename = f + 1;
  1065. X      logfile = fopen (filename, "a");
  1066. X    } else {
  1067. X      filename = f;
  1068. X      logfile = fopen (filename, "w");
  1069. X    }
  1070. X    if (logfile == NULL) {
  1071. X      sprintf (msg_buf, "%s ERROR OPENING %s",
  1072. X           sys_errlist[errno], filename);
  1073. X      Moderator_Comment (msg_buf);
  1074. X    } else {
  1075. X      sprintf (msg_buf, "NOW LOGGING TO %s", filename);
  1076. X      Moderator_Comment (msg_buf);
  1077. X    }
  1078. X  }
  1079. X}
  1080. X
  1081. Xstatic void Parse_message_input (m)
  1082. X     char *m;
  1083. X/* MESSAGE [<GPS-message>]
  1084. X *  If we are in server mode, sends a message to the GPS which will be
  1085. X *  displayed with our table announcement.
  1086. X */
  1087. X{
  1088. X  if (!server_mode) {
  1089. X    Status 
  1090. X      ("YOU CANNOT SEND A GPS MESSAGE UNLESS YOU ARE IN SERVER MODE.");
  1091. X    return;
  1092. X  }
  1093. X
  1094. X  if (GPS_unavailable || !Use_GPS) {
  1095. X    Status
  1096. X      ("THE GLOBAL PLAYER SERVICE IS CURRENTLY UNAVAILABLE.");
  1097. X    return;
  1098. X  }
  1099. X
  1100. X  GPS_Advertise_Message (m);
  1101. X}
  1102. X
  1103. Xstatic void Parse_name_input (m)
  1104. X     char *m;
  1105. X/* NAME <new-name>
  1106. X *   changes the name of the local player to <new-name>
  1107. X */
  1108. X{
  1109. X  char *s;
  1110. X
  1111. X  if (spectator_mode) {
  1112. X    Status ("YOU CANNOT CHANGE YOUR NAME DURING SPECTATOR MODE.");
  1113. X    return;
  1114. X  }
  1115. X
  1116. X  s = strdup (m);
  1117. X  if (strlen(s) > 8) s[8] = '\0';
  1118. X
  1119. X  Clear_Focus_Buffer ();
  1120. X  Send_name (Local_table, s);
  1121. X  GPS_Change_Name (local_player_name, s);
  1122. X  local_player_name = s;
  1123. X  sprintf (Local_Player_Connection->player_name, "%s", s);
  1124. X
  1125. X/*
  1126. X  if (IS_PLAYER(local_player)) {
  1127. X    sprintf (PLAYER_NAME(Local_table, local_player), "%s", s);
  1128. X  } else {
  1129. X    sprintf (msg_buf, "YOUR NEW NAME IS %s", local_player_name);
  1130. X    Moderator_Comment (msg_buf);
  1131. X  }
  1132. X*/
  1133. X}
  1134. X
  1135. Xstatic void Parse_opp_input (m)
  1136. X     char *m;
  1137. X/* OPP <message>
  1138. X . Sends a message to (both of) the opponents.
  1139. X */
  1140. X{
  1141. X  if (IS_OBSERVER(local_player))
  1142. X    Status ("PRIVATE MESSAGES CANNOT BE SENT BY AN OBSERVER.");
  1143. X  else {
  1144. X/*    Display_Player_Comment (COMMENT_FORMAL, local_player_name, m); */
  1145. X    Send_talk (Local_table, TALK_RCPT_OPPS, m);
  1146. X  }
  1147. X}
  1148. X
  1149. Xstatic void Parse_pause_input ()
  1150. X/* PAUSE
  1151. X . Returns to full screen talk mode if we are not already there.
  1152. X */
  1153. X{
  1154. X  int d = display_mode;
  1155. X  int i = input_mode;
  1156. X  
  1157. X  Clear_Focus_Buffer ();
  1158. X  if (display_mode != TALK_DISPLAY) {
  1159. X    Set_Display_Mode (TALK_DISPLAY);
  1160. X    Set_Input_Mode (TALK_INPUT);
  1161. X    Pause ("");
  1162. X    Set_Display_Mode (d);
  1163. X    Set_Input_Mode (i);
  1164. X  }
  1165. X  Clear_Status ();
  1166. X}
  1167. X
  1168. Xstatic void Parse_perish_input ()
  1169. X/* PERISH
  1170. X . Discontinues use of the GPS.  If we are a server, we will delete
  1171. X . our table from the database.
  1172. X */
  1173. X{
  1174. X  if (server_mode)
  1175. X    GPS_End_Server_Mode ();
  1176. X
  1177. X  Use_GPS = 0;
  1178. X}
  1179. X
  1180. Xstatic void Parse_ping_input ()
  1181. X/* PING
  1182. X . Sends a message to each of the other players, which is automatically
  1183. X . echoed.  The time delay until the echo's are received is reported.
  1184. X */
  1185. X{
  1186. X  gettimeofday (&ping_start, NULL);
  1187. X  Send_ping (Local_table);
  1188. X}
  1189. X
  1190. Xstatic void Parse_players_input (s)
  1191. X     char *s;
  1192. X/* PLAYERS <table-name>
  1193. X . Lists the players at the given table.
  1194. X */
  1195. X{
  1196. X  Clear_Focus_Buffer ();
  1197. X  GPS_List_Players (s);
  1198. X}
  1199. X
  1200. Xstatic void Parse_practice_input (p)
  1201. X     int *p;
  1202. X/* PRACTICE [ON|OFF]
  1203. X . Practice mode is used for partnerships to practice bidding and planning
  1204. X . play.
  1205. X */
  1206. X{
  1207. X  if (p == NULL)
  1208. X    Set_playing_mode (PRACTICE_PLAYING_MODE);
  1209. X  else
  1210. X    Set_playing_mode (*p? PRACTICE_PLAYING_MODE: CLUB_PLAYING_MODE);
  1211. X}
  1212. X
  1213. Xstatic void Parse_prompt_input (p)
  1214. X     int *p;
  1215. X/* PROMPT [ON|OFF]
  1216. X . Changes or displays whether the dummy is always prompted after each
  1217. X . trick has been played.
  1218. X */
  1219. X{
  1220. X  if (p != NULL) prompt_dummy = *p;
  1221. X  sprintf (msg_buf,  "THE DUMMY %s BE PROMPTED AFTER EACH TRICK",
  1222. X       prompt_dummy? "WILL": "WILL NOT");
  1223. X  Moderator_Comment (msg_buf);
  1224. X}
  1225. X
  1226. Xstatic void Parse_publish_input ()
  1227. X/* PUBLISH
  1228. X . Resumes use of the GPS.  If we are a server, publishes our table
  1229. X . in the global GPS database.
  1230. X */
  1231. X{
  1232. X  Use_GPS = 1;
  1233. X  GPS_unavailable = 0;
  1234. X
  1235. X  if (server_mode)
  1236. X    GPS_Broadcast_Server ();
  1237. X}
  1238. X
  1239. Xstatic void Parse_quit_input ()
  1240. X/* QUIT
  1241. X . Terminates the program.
  1242. X */
  1243. X{
  1244. X  Quit_program ();
  1245. X}
  1246. X
  1247. Xstatic void Parse_replay_input (f)
  1248. X     char *f;
  1249. X/* REPLAY <filename>
  1250. X . Loads a sequence of email boards from the file f.  After they have been
  1251. X . played, writes the results back to f.
  1252. X */
  1253. X{
  1254. X  if (client_mode) {
  1255. X    Status ("CLIENTS CANNOT LOAD EMAIL BOARDS.");
  1256. X    return;
  1257. X  }
  1258. X
  1259. X  replay_mode = 1;
  1260. X  if (gps_duplicate_mode)
  1261. X    GPS_Dup ("END");
  1262. X  gps_duplicate_mode = 0;
  1263. X  load_email_file (f);
  1264. X}
  1265. X
  1266. Xstatic void Parse_reset_input ()
  1267. X/* RESET
  1268. X . Resets the state of the program.
  1269. X */
  1270. X{
  1271. X  Connection c;
  1272. X  Table t;
  1273. X
  1274. X  if (client_mode) {
  1275. X    Status ("CLIENTS MAY NOT USE THE /RESET COMMAND.");
  1276. X    return;
  1277. X  }
  1278. X
  1279. X  for (t = Table_List; t != NULL; t = t->next)
  1280. X    Send_reset (t);
  1281. X
  1282. X  FOREACH_CONNECTION (c)
  1283. X    if (!c->local)
  1284. X      Assign_seat (c->table, c, PLAYER_OBS);
  1285. X
  1286. X}
  1287. X
  1288. Xstatic void Parse_results_input (results_file)
  1289. X     char *results_file;
  1290. X{
  1291. X  FILE *rf;
  1292. X  Cipher c;
  1293. X  Board *results_list, *b;
  1294. X  int current_display_mode = display_mode;
  1295. X  int current_input_mode = input_mode;
  1296. X
  1297. X  if (results_file != NULL) {
  1298. X    rf = fopen (results_file, "w");
  1299. X    if (rf == NULL) {
  1300. X      sprintf (msg_buf, "ERROR OPENING RESULTS FILE %s: %s", results_file,
  1301. X           sys_errlist[errno]);
  1302. X      Status (msg_buf);
  1303. X      return;
  1304. X    }
  1305. X  } else
  1306. X    rf = NULL;
  1307. X
  1308. X  Clear_Focus_Buffer ();
  1309. X  Status ("DOWNLOADING RESULTS OF PLAY FROM GPS ...");
  1310. X  restore_cursor ();
  1311. X  results_list = GPS_Download_Results (local_player_name);
  1312. X  Clear_Status ();
  1313. X
  1314. X  if (results_list == NULL) {
  1315. X    Status ("NO RESULTS ARE AVAILABLE FOR YOU.");
  1316. X    if (rf != NULL)
  1317. X      fclose (rf);
  1318. X    return;
  1319. X  }
  1320. X
  1321. X  if (rf != NULL) {
  1322. X    sprintf (msg_buf, "WRITING RESULTS OF DUPLICATE PLAY TO %s ...", 
  1323. X         results_file);
  1324. X    Moderator_Comment (msg_buf);
  1325. X
  1326. X    Write_Email_Header (rf);
  1327. X    Create_Cipher_Descriptor (rf, &c);
  1328. X    Write_Cipher_Descriptor (rf, &c);
  1329. X
  1330. X    for (b = results_list; b != NULL; b = b->next)
  1331. X      Write_Email_Board (rf, &c, b);
  1332. X
  1333. X    fclose (rf);
  1334. X
  1335. X    if (!Ask("DO YOU WISH TO SEE A DISPLAY OF THE RESULTS? ")) {
  1336. X      Erase_board_list (&results_list);
  1337. X      return;
  1338. X    }
  1339. X  }
  1340. X
  1341. X  for (b = results_list; b != NULL; b = b->next) {
  1342. X    if ((b->play_records != NULL) && (b->play_records->next != NULL)) {
  1343. X      Display_First_Page_of_Scores (b);
  1344. X      Pause ("PRESS <ESC> TO SEE THE NEXT PAGE OF RESULTS ...");
  1345. X      while (More_Scores_to_Display ()) {
  1346. X    Display_More_Scores ();
  1347. X    Pause ("PRESS <ESC> TO SEE THE NEXT PAGE OF RESULTS ...");
  1348. X      }
  1349. X    }
  1350. X  }
  1351. X
  1352. X  Erase_board_list (&results_list);
  1353. X  Set_Display_Mode (current_display_mode);
  1354. X  Set_Input_Mode (current_input_mode);
  1355. X}
  1356. X
  1357. Xstatic void Reveal_hand (position)
  1358. X     int position;
  1359. X/* Reveals to the observer the contents of the hand held by 'position' */
  1360. X{
  1361. X  hand h;
  1362. X
  1363. X  if (!spectator_mode) {
  1364. X    spectator_mode = 1;
  1365. X    Send_spec (Local_table);
  1366. X    if (!PRACTICE(Local_table))
  1367. X      Status ("YOU MAY ONLY TALK TO OTHER SPECTATORS NOW.");
  1368. X    Display_Player_Position ();
  1369. X  }
  1370. X    
  1371. X  revealed_bidder = position;
  1372. X  revealed_hands[position] = 1;
  1373. X  
  1374. X  if (Local_table->game_mode == PLAYING_MODE)
  1375. X    Display_Hand (position);
  1376. X  else if (Local_table->game_mode == BIDDING_MODE) {
  1377. X    Generate_holdings (Local_board, Local_play->play_list, 0, position, h);
  1378. X    Display_Hand_for_Bidding (position, h);
  1379. X  }
  1380. X
  1381. X}
  1382. X
  1383. Xstatic void Parse_reveal_input (player)
  1384. X     char *player;
  1385. X{
  1386. X  int i, known;
  1387. X  int game_mode = Local_table->game_mode;
  1388. X
  1389. X  if (IS_PLAYER(local_player)) {
  1390. X    if (game_mode != PLAYING_MODE) {
  1391. X      Status ("YOU MAY NOT ENTER SPECTATOR MODE IF YOU ARE PLAYING.");
  1392. X      return;
  1393. X    } else if (local_player != player_partner[Local_play->declarer]) {
  1394. X      Status 
  1395. X    ("ONLY THE OBSERVER AND THE DUMMY MAY SEE OTHER PLAYER'S HANDS!");
  1396. X      return;
  1397. X    }
  1398. X  }
  1399. X
  1400. X  if ((game_mode != BIDDING_MODE) && (game_mode != PLAYING_MODE)) {
  1401. X    Status ("YOU WILL NOT BE ABLE TO SEE ANYTHING UNTIL NEXT HAND.");
  1402. X    return;
  1403. X  }
  1404. X
  1405. X  if (FORMAL(Local_table)) {
  1406. X    Status ("YOU MAY NOT SEE THE PLAYER'S HANDS DURING FORMAL PLAY.");
  1407. X    return;
  1408. X  }
  1409. X
  1410. X  if (player == NULL) {
  1411. X    Reveal_hand (PLAYER_WEST);
  1412. X    Reveal_hand (PLAYER_SOUTH);
  1413. X    Reveal_hand (PLAYER_EAST);
  1414. X    Reveal_hand (PLAYER_NORTH);
  1415. X  } else if (!strcasecmp(player, "NORTH") || !strcasecmp(player, "N"))
  1416. X    Reveal_hand (PLAYER_NORTH);
  1417. X  else if (!strcasecmp(player, "EAST") || !strcasecmp(player, "E"))
  1418. X    Reveal_hand (PLAYER_EAST);
  1419. X  else if (!strcasecmp(player, "SOUTH") || !strcasecmp(player, "S"))
  1420. X    Reveal_hand (PLAYER_SOUTH);
  1421. X  else if (!strcasecmp(player, "WEST") || !strcasecmp(player, "W"))
  1422. X    Reveal_hand (PLAYER_WEST);
  1423. X  else if (!strcasecmp(player, "NE") || !strcasecmp(player, "EN")) {
  1424. X    Reveal_hand (PLAYER_EAST);
  1425. X    Reveal_hand (PLAYER_NORTH);
  1426. X  } else if (!strcasecmp(player, "NS") || !strcasecmp(player, "SN")) {
  1427. X    Reveal_hand (PLAYER_SOUTH);
  1428. X    Reveal_hand (PLAYER_NORTH);
  1429. X  } else if (!strcasecmp(player, "NW") || !strcasecmp(player, "WN")) {
  1430. X    Reveal_hand (PLAYER_WEST);
  1431. X    Reveal_hand (PLAYER_NORTH);
  1432. X  } else if (!strcasecmp(player, "SE") || !strcasecmp(player, "ES")) {
  1433. X    Reveal_hand (PLAYER_SOUTH);
  1434. X    Reveal_hand (PLAYER_EAST);
  1435. X  } else if (!strcasecmp(player, "SW") || !strcasecmp(player, "WS")) {
  1436. X    Reveal_hand (PLAYER_WEST);
  1437. X    Reveal_hand (PLAYER_SOUTH);
  1438. X  } else if (!strcasecmp(player, "EW") || !strcasecmp(player, "WE")) {
  1439. X    Reveal_hand (PLAYER_WEST);
  1440. X    Reveal_hand (PLAYER_EAST);
  1441. X  } else {
  1442. X    known = 0;
  1443. X    for (i = 0; i < 4; i++)
  1444. X      if (OCCUPIED(Local_table, i) && 
  1445. X      !strcasecmp(player, PLAYER_NAME(Local_table, i))) {
  1446. X    Reveal_hand (i);
  1447. X    known = 1;
  1448. X      }
  1449. X    if (!known) {
  1450. X      sprintf (msg_buf, "THERE IS NO PLAYER NAMED %s", player);
  1451. X      Status (msg_buf);
  1452. X      return;
  1453. X    }
  1454. X  }
  1455. X
  1456. X}
  1457. X
  1458. Xstatic void Parse_review_input ()
  1459. X{
  1460. X  Clear_Focus_Buffer ();
  1461. X  Review_Bidding ();
  1462. X}
  1463. X
  1464. Xstatic void Parse_rho_input (m)
  1465. X     char *m;
  1466. X/* RHO <message>
  1467. X . Sends a message to the right-hand opponent.
  1468. X */
  1469. X{
  1470. X  if (IS_OBSERVER(local_player))
  1471. X    Status ("PRIVATE MESSAGES CANNOT BE SENT BY AN OBSERVER.");
  1472. X  else {
  1473. X    Display_Player_Comment (COMMENT_PRIVATE, local_player_name, m);
  1474. X    Send_talk (Local_table, TALK_RCPT_RHO, m);
  1475. X  }
  1476. X}
  1477. X     
  1478. Xstatic void Parse_save_input (f)
  1479. X     char *f;
  1480. X/* SAVE <filename>
  1481. X . Saves the sequence of boards that have been played to the file f.
  1482. X */
  1483. X{
  1484. X  if ((f == NULL) && (email_filename == NULL)) {
  1485. X    Status ("YOU MUST SPECIFY THE NAME OF THE EMAIL SAVE FILE.");
  1486. X    return;
  1487. X  } else if (f == NULL)
  1488. X    save_email_file (email_filename);
  1489. X  else
  1490. X    save_email_file (f);
  1491. X}
  1492. X
  1493. Xstatic void Parse_score_input (s)
  1494. X     int *s;
  1495. X/* SCORE RUBBER|DUPLICATE|IMP|MP|CLEAR
  1496. X . Chooses a scoring mode.  Can be used by the server.
  1497. X */
  1498. X{
  1499. X  if (client_mode) {
  1500. X    Status ("ONLY THE SERVER MAY CHANGE THE SCORING MODE.");
  1501. X    return;
  1502. X  }
  1503. X
  1504. X  if ((*s == scoring_mode) && !gps_duplicate_mode) return;
  1505. X
  1506. X  if (*s != CLEAR_SCORING) {
  1507. X    scoring_mode = *s;
  1508. X    if (gps_duplicate_mode) {
  1509. X      GPS_Dup ("END");
  1510. X      gps_duplicate_mode = 0;
  1511. X    }
  1512. X  }
  1513. X
  1514. X  Local_table->above_line[SIDE_NS] = Local_table->above_line[SIDE_EW] = 0;
  1515. X  Local_table->below_line[SIDE_NS] = Local_table->below_line[SIDE_EW] = 0;
  1516. X  switch (scoring_mode) {
  1517. X  case RUBBER_SCORING:
  1518. X    Moderator_Comment ("WE ARE PLAYING RUBBER BRIDGE.");
  1519. X    break;
  1520. X  case DUPLICATE_SCORING:
  1521. X    Moderator_Comment ("WE ARE PLAYING DUPLICATE BRIDGE.");
  1522. X    break;
  1523. X  case IMP_SCORING:
  1524. X    Moderator_Comment ("WE ARE PLAYING IMP BRIDGE.");
  1525. X    break;
  1526. X  case MP_SCORING:
  1527. X    Moderator_Comment ("WE ARE PLAYING MATCH POINT BRIDGE.");
  1528. X    break;
  1529. X  case CLEAR_SCORING:
  1530. X    Moderator_Comment ("THE SCORES HAVE BEEN CLEARED.");
  1531. X    break;
  1532. X  }
  1533. X  if ((Local_table->game_mode != STARTUP_MODE) &&
  1534. X      (Local_table->game_mode != SCORING_MODE))
  1535. X    Send_skip (Local_table);
  1536. X
  1537. X}
  1538. X
  1539. Xstatic void Parse_scoreboard_input ()
  1540. X/* SCOREBOARD
  1541. X . Displays the GPS scoreboard.
  1542. X */
  1543. X{
  1544. X  Clear_Focus_Buffer ();
  1545. X  GPS_Display_Scoreboard ();
  1546. X}
  1547. X
  1548. Xstatic void Parse_seat_input (s)
  1549. X     int *s;
  1550. X/* SEAT NORTH|EAST|SOUTH|WEST|OBS
  1551. X . Requests the given seat for the local player.
  1552. X */
  1553. X{
  1554. X/*  CHECK_ENABLED (INPUT_SEAT); */
  1555. X
  1556. X  if (spectator_mode) {
  1557. X    Status ("YOU CANNOT CHANGE YOUR SEAT IN SPECTATOR MODE.");
  1558. X    return;
  1559. X  }
  1560. X
  1561. X  Send_seatreq (Local_table, *s);
  1562. X}
  1563. X
  1564. Xstatic void Parse_east_input ()
  1565. X{
  1566. X  int i = PLAYER_EAST;
  1567. X
  1568. X  Parse_seat_input (&i);
  1569. X}
  1570. X
  1571. Xstatic void Parse_north_input ()
  1572. X{
  1573. X  int i = PLAYER_NORTH;
  1574. X
  1575. X  Parse_seat_input (&i);
  1576. X}
  1577. X
  1578. Xstatic void Parse_observe_input ()
  1579. X{
  1580. X  int i = PLAYER_OBS;
  1581. X
  1582. X  Parse_seat_input (&i);
  1583. X}
  1584. X
  1585. Xstatic void Parse_south_input ()
  1586. X{
  1587. X  int i = PLAYER_SOUTH;
  1588. X
  1589. X  Parse_seat_input (&i);
  1590. X}
  1591. X
  1592. Xstatic void Parse_west_input ()
  1593. X{
  1594. X  int i = PLAYER_WEST;
  1595. X
  1596. X  Parse_seat_input (&i);
  1597. X}
  1598. X
  1599. Xstatic void Parse_serve_input (p)
  1600. X     int *p;
  1601. X/* SERVE [<port-number>]
  1602. X . Enters Server mode.
  1603. X */
  1604. X{
  1605. X  if (client_mode && (Local_table->game_mode != STARTUP_MODE) &&
  1606. X      IS_PLAYER(local_player)) {
  1607. X    Moderator_Comment
  1608. X      ("WARNING! THIS WILL DISCONNECT YOU FROM THIS TABLE!");
  1609. X    if (!Ask("ARE YOU SURE YOU WISH TO DO THIS? "))
  1610. X      return;
  1611. X  } else if (server_mode) {
  1612. X    Status ("YOU ARE ALREADY SERVING A TABLE.");
  1613. X    GPS_Broadcast_Server ();
  1614. X    return;
  1615. X  }
  1616. X
  1617. X  if (p != NULL)
  1618. X    network_port = *p;
  1619. X  else
  1620. X    network_port = DEFAULT_PORT;
  1621. X
  1622. X  if (client_mode)
  1623. X    Send_quit (Local_table);
  1624. X
  1625. X  Generate_reset (RESET_SERVE);
  1626. X}
  1627. X
  1628. Xstatic void Parse_setcc_input (cc)
  1629. X     char *cc;
  1630. X{
  1631. X  /*
  1632. X    JAS -- should we be "free"ing the old local_cc?
  1633. X    */
  1634. X  if (cc != NULL)
  1635. X    local_cc = strdup (Get_CC_Value(cc));                             /* JAS */
  1636. X
  1637. X  if ((local_player < 4) && (local_cc != NULL)) {
  1638. X    Send_cc (Local_table, local_cc);
  1639. X    conventions[side_of(local_player)] = strdup(local_cc);
  1640. X    sprintf (msg_buf, "%s: %s", (side_of(local_player) == SIDE_NS)? 
  1641. X         "N-S": "E-W", local_cc);
  1642. X  } else if (local_cc == NULL)
  1643. X    Status ("YOUR CONVENTION CARD IS EMPTY.");
  1644. X}
  1645. X
  1646. Xstatic void Parse_skip_input (n)
  1647. X     int *n;
  1648. X/* SKIP [n]
  1649. X . Ends the current hand prematurely, and skips the next n-1 hands.
  1650. X */
  1651. X{
  1652. X  int i;
  1653. X  Board *b;
  1654. X
  1655. X  if ((n != NULL) && !server_mode) {
  1656. X    Status ("ONLY THE SERVER MAY SPECIFY A SKIP COUNT.");
  1657. X    return;
  1658. X  } else if (IS_OBSERVER(local_player)) {
  1659. X    Status ("OBSERVERS MAY NOT USE THE /SKIP COMMAND.");
  1660. X    return;
  1661. X  }
  1662. X
  1663. X  Send_skip (Local_table);
  1664. X
  1665. X  if (n != NULL) {
  1666. X    sprintf (msg_buf, "SKIPPED %d HANDS.", *n);
  1667. X    for (i = 1; i < *n; i++) {
  1668. X      b = Next_Unplayed_Board ();
  1669. X      if (b == NULL) {
  1670. X    sprintf (msg_buf, "ALL UNPLAYED BOARDS HAVE BEEN SKIPPED.");
  1671. X    break;
  1672. X      }
  1673. X      Record_Played_Board (b);
  1674. X    }
  1675. X    Moderator_Comment (msg_buf);
  1676. X  }
  1677. X
  1678. X}
  1679. X
  1680. Xstatic void Parse_table_input (table_no)
  1681. X     int *table_no;
  1682. X/* TABLE table-no
  1683. X . Requests to switch to the given table.
  1684. X */
  1685. X{
  1686. X  Send_tablereq (Local_table, *table_no);
  1687. X}
  1688. X
  1689. Xstatic void Parse_tables_input ()
  1690. X/* TABLES
  1691. X . Lists the tables which are currently playing.
  1692. X */
  1693. X{
  1694. X  Clear_Focus_Buffer ();
  1695. X  GPS_List_Tables ();
  1696. X}
  1697. X
  1698. Xstatic void Parse_timer_input (tm)
  1699. X     int *tm;
  1700. X{
  1701. X  timer_is_on = (tm == NULL)? timer_is_on: *tm;
  1702. X  sprintf (msg_buf, "THE TIMER IS %s.", timer_is_on? "ON": "OFF");
  1703. X  if (timer_is_on)
  1704. X    Display_timer ();
  1705. X  else
  1706. X    Display_Total_Time ("", "");
  1707. X  Status (msg_buf);
  1708. X}
  1709. X
  1710. Xvoid Wakeup_player (player)
  1711. X     char *player;
  1712. X{
  1713. X
  1714. X  if (IS_OBSERVER(local_player) && !server_mode) {
  1715. X    Status ("THE WAKEUP COMMAND CANNOT BE USED BY AN OBSERVER.");
  1716. X    return;
  1717. X  }
  1718. X
  1719. X  if (FORMAL(Local_table))
  1720. X    player = "ALL";
  1721. X  else if (player == NULL) {
  1722. X    if (!OCCUPIED(Local_table, player_partner[local_player])) {
  1723. X      Status ("YOU HAVE NO PARTNER TO WAKE UP!");
  1724. X      return;
  1725. X    }
  1726. X    player = PLAYER_NAME(Local_table, player_partner[local_player]);
  1727. X  }
  1728. X  
  1729. X  Send_wakeup (Local_table, player);
  1730. X  sprintf (msg_buf, "SENDING WAKEUP SIGNAL TO %s ...", player);
  1731. X  Status (msg_buf);
  1732. X
  1733. X}
  1734. X
  1735. Xstatic void Parse_wakeup_input (player)
  1736. X     char *player;
  1737. X{
  1738. X  Wakeup_player (player); 
  1739. X}
  1740. X
  1741. Xstatic void Parse_who_input ()
  1742. X/* WHO
  1743. X . Generates a short listing of the players who are currently connected.
  1744. X */
  1745. X{
  1746. X  Send_who (Local_table);
  1747. X}
  1748. X
  1749. Xstatic void Parse_whois_input (p)
  1750. X     char *p;
  1751. X/* WHOIS [<player-name>]
  1752. X . Asks for the identity of the given player.  If we are sitting at the
  1753. X . table, then omitting <player-name> causes both of the opponents to
  1754. X . be identified.
  1755. X */
  1756. X{
  1757. X  int opp1, opp2;
  1758. X  Connection c;
  1759. X
  1760. X  if ((p == NULL) && (local_player >= 4)) {
  1761. X    Send_whois (Local_table, "*ALL*");
  1762. X/*    Status ("ERROR: YOU MUST SPECIFY THE NAME OF A PLAYER"); */
  1763. X  } else if (p == NULL) {
  1764. X    opp1 = side_of(player_next[local_player]);
  1765. X    opp2 = player_partner[opp1];
  1766. X    if (OCCUPIED(Local_table, opp1))
  1767. X      Send_whois (Local_table, PLAYER_NAME(Local_table, opp1));
  1768. X    if (OCCUPIED(Local_table, opp2))
  1769. X      Send_whois (Local_table, PLAYER_NAME(Local_table, opp2));
  1770. X  } else
  1771. X    Send_whois (Local_table, p);
  1772. X}
  1773. X
  1774. Xstatic void Parse_zlog_input (f)
  1775. X     char *f;
  1776. X/* ZLOG <filename>
  1777. X . The ZLOG command opens or closes a file for recording the play in
  1778. X . Zhang's format. 
  1779. X */
  1780. X{
  1781. X  char *filename;
  1782. X
  1783. X  if (f == NULL) {
  1784. X    if (zhang_logfile == NULL)
  1785. X      Moderator_Comment ("THERE IS NO OPEN ZLOGFILE.");
  1786. X    else {
  1787. X      fclose (zhang_logfile);
  1788. X      zhang_logfile = NULL;
  1789. X      Moderator_Comment ("THE ZLOGFILE HAS BEEN CLOSED.");
  1790. X    }
  1791. X    return;
  1792. X  } else {
  1793. X    if (zhang_logfile != NULL) fclose (zhang_logfile);
  1794. X    if (f[0] == '+') {
  1795. X      filename = f + 1;
  1796. X      zhang_logfile = fopen (filename, "a");
  1797. X    } else {
  1798. X      filename = f;
  1799. X      zhang_logfile = fopen (filename, "w");
  1800. X    }
  1801. X    if (zhang_logfile == NULL) {
  1802. X      sprintf (msg_buf, "%s ERROR OPENING %s",
  1803. X           sys_errlist[errno], filename);
  1804. X      Moderator_Comment (msg_buf);
  1805. X    } else {
  1806. X      sprintf (msg_buf, "NOW ZLOGGING TO %s", filename);
  1807. X      Moderator_Comment (msg_buf);
  1808. X    }
  1809. X  }
  1810. X}
  1811. X
  1812. Xint Parse_Server_Command (command_buf)
  1813. X     char *command_buf;
  1814. X/* On entry, command_buf should contain a special request to the server
  1815. X   made by a client.  Parses the command and executes it.  Returns 0 if
  1816. X   the command was parsed correctly, and 1 if an error occurs.  In the
  1817. X   latter case, the error message is placed in the Parser_Error_Buf.
  1818. X*/
  1819. X{
  1820. X  return (Parse_Command (Input_Commands, INPUT_MAX-1, command_buf));
  1821. X}
  1822. X
  1823. Xvoid Parse_Input_Command (command_buf)
  1824. X     char *command_buf;
  1825. X/* Parses the command contained in the buffer command_buf and executes
  1826. X   the corresponding command.  If an error occurs, then displays an
  1827. X   appropriate message in the status line. 
  1828. X*/
  1829. X{
  1830. X  if (Parse_Command(Input_Commands, INPUT_MAX-1, command_buf+1))
  1831. X    Status (Parser_Error_Buf);
  1832. X}
  1833. END_OF_FILE
  1834. if test 44917 -ne `wc -c <'commands.c'`; then
  1835.     echo shar: \"'commands.c'\" unpacked with wrong size!
  1836. fi
  1837. # end of 'commands.c'
  1838. fi
  1839. if test -f 'rc.h' -a "${1}" != "-c" ; then 
  1840.   echo shar: Will not clobber existing file \"'rc.h'\"
  1841. else
  1842. echo shar: Extracting \"'rc.h'\" \(6555 characters\)
  1843. sed "s/^X//" >'rc.h' <<'END_OF_FILE'
  1844. X/* rc.h -- Routines for reading/writing okbridge initialization files.
  1845. X *
  1846. X ! Copyright (C) 1990-1992 by Matthew Clegg.  All Rights Reserved
  1847. X ! 
  1848. X ! OKbridge is made available as a free service to the Internet.
  1849. X ! Accordingly, the following restrictions are placed on its use:
  1850. X ! 
  1851. X ! 1.  OKbridge may not be modified in any way without the explicit 
  1852. X !     permission of Matthew Clegg.  
  1853. X ! 
  1854. X ! 2.  OKbridge may not be used in any way for commercial advantage.
  1855. X !     It may not be placed on for-profit networks or on for-profit
  1856. X !     computer systems.  It may not be bundled as part of a package
  1857. X !     or service provided by a for-profit organization.
  1858. X ! 
  1859. X ! If you have questions about restrictions on the use of OKbridge,
  1860. X ! write to mclegg@cs.ucsd.edu.
  1861. X ! 
  1862. X ! DISCLAIMER:  The user of OKbridge accepts full responsibility for any
  1863. X ! damage which may be caused by OKbridge.
  1864. X *
  1865. X */
  1866. X
  1867. X/*
  1868. X * This module contains procedures for reading the okbridge startup
  1869. X * files.  Each line in this file is either a comment line
  1870. X * or a (field, value) pair.  Comment lines begin with the pound sign
  1871. X * '#' character.  Field, value pairs are of the format
  1872. X *    <Field-name>    <value>
  1873. X *
  1874. X * The fields which are currently recognized are as follows:
  1875. X *
  1876. X * AUTOSAVE     ON | OFF
  1877. X *     Specifies that we will save the options specified by the user
  1878. X *    during play of the program to the file .okdefaults after the
  1879. X *    program terminates.
  1880. X *
  1881. X * BELL        ON | OFF
  1882. X *    When requesting input (a bid or a play), the terminal's
  1883. X *    bell is rung by default.  However, this can be disabled
  1884. X *    by specifying 'BELL OFF'.  This has the same effect as the
  1885. X *    '/BELL OFF' command.
  1886. X *
  1887. X * CC           <convention-card>
  1888. X *      This is a one line description of the conventions which you
  1889. X *      like to use. 
  1890. X *
  1891. X **** The following command added by jsegal 5-14-92.
  1892. X * CCDEF       <ccname> <convention-card>
  1893. X *      This command will define a named CC.  It must be before
  1894. X *      the CC line of the startup if that line specifies a named CC.
  1895. X *
  1896. X * DEFAULT      ON | OFF
  1897. X *      This controls whether or not default inputs will be provided for
  1898. X *      bids, plays and questions.
  1899. X *
  1900. X * EMAIL        <email-address>
  1901. X *      This should be your email address.  It is currently used only for
  1902. X *      identification purposes.
  1903. X *
  1904. X * ESCKEY       <decimal-key-code>
  1905. X *      Specifies the key which will be recognized when the program
  1906. X *      presents the message "PRESS <ESC> TO CONTINUE."  This should
  1907. X *      be a decimal number representing the key code.  For example,
  1908. X *      the <RETURN> key has code 13, and the ESC key (the default)
  1909. X *      has code 27.
  1910. X *
  1911. X * FULLNAME     <your-full-name>
  1912. X *      This field is used only for identification purposes, and should
  1913. X *      contain your full name as you would wish it to be displayed to others.
  1914. X *
  1915. X * GPS           ON | OFF
  1916. X *    Controls whether or not we will contact the Global Player Service
  1917. X *       automatically when the program starts up.
  1918. X *
  1919. X * GPS_IP    <ip-name-or-number-of-GPS> [<GPS-port>]
  1920. X *    Specifies the Internet name or number of the GPS
  1921. X *
  1922. X * HELPFILE    <directory-name>
  1923. X *    This field specifies the directory to be used for reading
  1924. X *    the okbridge help files.
  1925. X *
  1926. X * LOAD         <email-duplicate-filename>
  1927. X *      This field is only valid if the position is north and the
  1928. X *      scoring mode is email duplicate.  In this case, okbridge will
  1929. X *      automatically read a set of email duplicate boards from the
  1930. X *      named file.
  1931. X *
  1932. X * LOG        <filename>
  1933. X *    If this statement is present in the startup file, then
  1934. X *    the hands will automatically be logged to the given filename.
  1935. X *      If the first character of <filename> is '+', then logs the
  1936. X *      hands to the end of the file rather than erasing the old file.
  1937. X *
  1938. X * MY_IP        <local-IP-number>
  1939. X *      This field specifies the IP number of the local player.
  1940. X *      Usually, okbridge can determine the IP number correctly
  1941. X *      a call to gethostbyname(), but on some systems, this will
  1942. X *      not give correct results.
  1943. X *
  1944. X * NAME        <local-player-name>
  1945. X *    This field specifies the name that will be used to identify
  1946. X *    the local player to the other players.
  1947. X *
  1948. X * PORT        <positive-integer>
  1949. X *    This field specifies the internet port number that will be
  1950. X *    used for communications with the server.
  1951. X *
  1952. X * PROMPT     NO | YES
  1953. X *    The value of this field is only relevant in hands where the
  1954. X *    local player is the dummy.  In this case, the dummy is
  1955. X *    ordinarily prompted to press RETURN at the end of each trick.
  1956. X *    This allows the dummy to see the cards that are played as they
  1957. X *    are played.  However, if 'PROMPT NO' is specified, then the
  1958. X *    dummy will not be prompted.
  1959. X *
  1960. X * REPLAY       <email-duplicate-filename>
  1961. X *      This field is only valid if the position is north and the
  1962. X *      scoring mode is email duplicate.  In this case, a set of
  1963. X *      boards will automatically be read from the named file.
  1964. X *      After they have been played, the results will automatically
  1965. X *      be written back to the file from which the boards were read.
  1966. X *
  1967. X * SCORING    RUBBER | CHICAGO | DUPLICATE | EMAIL | IMP
  1968. X *    This field is only relevant if the local player is north.
  1969. X *    In this case, the SCORING field determines the type of scoring
  1970. X *    that will be used by default in the game.
  1971. X *
  1972. X * SEAT     NORTH | EAST | SOUTH | WEST
  1973. X *    This field specifies the local player's position.
  1974. X *
  1975. X * SERVER    ME | <internet-name-or-number>
  1976. X *    If the value of this field is 'ME', then the local player
  1977. X *    will assume the role of server.  If the value of this field
  1978. X *    is anything else, then it is interpreted as an internet name
  1979. X *    or number of the machine where the server is running.
  1980. X *
  1981. X * TIMER        ON | OFF
  1982. X *      This controls whether or not the timer will automatically
  1983. X *      be displayed showing the amount of time spent by the local
  1984. X *      player and by all players on the current hand.
  1985. X *
  1986. X * TIMEZONE     <timezone-string>
  1987. X *      This is a string which specifies the name of the time zone of
  1988. X *      the local player.  Usually, this can be determined from looking
  1989. X *      at the tm_zone field of the structure returned by the localtime()
  1990. X *      system call, but some systems do not have this field.
  1991. X *
  1992. X * ZLOG         <filename>
  1993. X *      This command is similar to the LOG command, in that it opens
  1994. X *      a file for recording play, but the format of the file is 
  1995. X *      different.
  1996. X */
  1997. X
  1998. Xvoid Read_Initialization_File ();
  1999. X/* Reads an initialization file.  If the file cannot be found, then does
  2000. X   nothing. */
  2001. X
  2002. Xvoid Write_Initialization_File ();
  2003. X/* Writes the current program settings to the given file. */
  2004. END_OF_FILE
  2005. if test 6555 -ne `wc -c <'rc.h'`; then
  2006.     echo shar: \"'rc.h'\" unpacked with wrong size!
  2007. fi
  2008. # end of 'rc.h'
  2009. fi
  2010. echo shar: End of archive 4 \(of 14\).
  2011. cp /dev/null ark4isdone
  2012. MISSING=""
  2013. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  2014.     if test ! -f ark${I}isdone ; then
  2015.     MISSING="${MISSING} ${I}"
  2016.     fi
  2017. done
  2018. if test "${MISSING}" = "" ; then
  2019.     echo You have unpacked all 14 archives.
  2020.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2021. else
  2022.     echo You still need to unpack the following archives:
  2023.     echo "        " ${MISSING}
  2024. fi
  2025. ##  End of shell archive.
  2026. exit 0
  2027.