home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume14 / okbrdge2 / part06 < prev    next >
Encoding:
Internet Message Format  |  1993-01-26  |  53.5 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: v14i084:  okbridge2 - computer-mediated bridge game, Part06/14
  5. Message-ID: <3523@master.CNA.TEK.COM>
  6. Date: 7 Sep 92 21:41:46 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 1942
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: mclegg@cs.UCSD.EDU (Matthew Clegg)
  12. Posting-number: Volume 14, Issue 84
  13. Archive-name: okbridge2/Part06
  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 6 (of 14)."
  26. # Contents:  cs.c display.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 'cs.c' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'cs.c'\"
  31. else
  32. echo shar: Extracting \"'cs.c'\" \(16640 characters\)
  33. sed "s/^X//" >'cs.c' <<'END_OF_FILE'
  34. X/* cs.c -- client/server routines
  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 */
  56. X
  57. X#include <stdio.h>
  58. X#include <string.h>
  59. X
  60. X#include "socket.h"
  61. X#include "network.h"
  62. X#include "state.h"
  63. X#include "gps.h"
  64. X#include "cs.h"
  65. X
  66. X#ifdef LOGFILE
  67. Xextern FILE *net_log;
  68. X#endif
  69. X
  70. X#ifdef GCC
  71. Xextern strcasecmp ();
  72. Xextern fprintf ();
  73. Xextern fflush ();
  74. X#endif
  75. X
  76. Xextern char Parser_Error_Buf [];
  77. X
  78. Xextern void Generate_reset ();
  79. Xextern void Network_Comment ();
  80. X
  81. Xvoid Clear_Spectators (t)
  82. X     Table t;
  83. X/* Clears the spectator mode flag for each of the players at the table t. */
  84. X{
  85. X  Connection c;
  86. X
  87. X  FOREACH_PLAYER (c, t) 
  88. X    c->spectator = 0;
  89. X  spectator_mode = 0;
  90. X
  91. X}
  92. X
  93. Xvoid Vacate_seat (t, s)
  94. X     Table t; int s;
  95. X/* Clears the seat s in the table t. */
  96. X{
  97. X  if (IS_PLAYER(s)) {
  98. X    t->Seats[s].connection = NULL;
  99. X    sprintf (t->Seats[s].player_name, "%s", seat_names[s]);
  100. X    t->Seats[s].occupied = 0;
  101. X  }
  102. X
  103. X}
  104. X
  105. Xvoid Assign_seat (t, c, seat)
  106. X     Table t; Connection c; int seat;
  107. X/* void Assign_seat (Table t, Connection c, int seat) */
  108. X/* Assigns the given seat to the player with connection c. */
  109. X{
  110. X  Vacate_seat (t, c->seat);
  111. X
  112. X  c->seat = seat;
  113. X  if (IS_PLAYER(seat)) {
  114. X    t->Seats[seat].connection = c;
  115. X    sprintf (PLAYER_NAME(t, seat), "%s", c->player_name);
  116. X    t->Seats[seat].occupied = 1;
  117. X  }
  118. X}
  119. X
  120. Xint Request_Seat (c, requested)
  121. X     Connection c; int requested;
  122. X/* int Request_Seat (Connection c, int requested) */
  123. X/* Requests the given seat for the player with connection c.
  124. X . If the request can be granted, then assigns the player to the seat,
  125. X . sends an acknowledgment message to the requesting player, and returns 
  126. X . the seat index of the seat assigned.  If it cannot be granted, then sends 
  127. X . an error message to the requesting player and returns -1.
  128. X */
  129. X{
  130. X  int i;
  131. X  char message_buf [100];
  132. X  Table t = c->table;
  133. X
  134. X  if (VACANT(t,requested)) {
  135. X    Send_seat (c->table, c->seat, requested, c->player_name);
  136. X    Assign_seat (c->table, c, requested);
  137. X    sprintf (message_buf, "SEATPOS %s", seat_names[requested]);
  138. X    send_private_message (c, message_buf);
  139. X    return (requested);
  140. X  } else {
  141. X    /* Construct a SEATERR message indicating which seats are free: */
  142. X    sprintf (message_buf, "SEATERR");
  143. X    for (i = 0; i < 4; i++)
  144. X      if (!t->Seats[i].occupied)
  145. X    sprintf (message_buf+strlen(message_buf), " %s", seat_names[i]);
  146. X    send_private_message (c, message_buf);
  147. X    return (-1);
  148. X  }
  149. X}
  150. X
  151. Xstatic void Respond_to_who_message (who_msg)
  152. X     Message who_msg;
  153. X{
  154. X  char msg_buf[100], message[120];
  155. X  int i;
  156. X  Connection c;
  157. X  Table t = who_msg->source->table;
  158. X
  159. X  msg_buf[0] = '\0';
  160. X  for (i = 0; i < 4; i++)
  161. X    if (OCCUPIED(t,i))
  162. X      sprintf (msg_buf+strlen(msg_buf),"%s(%c) %s",
  163. X           (strlen(msg_buf) > 0)? ", ": "",
  164. X           *("NESW" + i), PLAYER_NAME(t, i));
  165. X  if (strlen(msg_buf) > 0) {
  166. X    sprintf (message, "COMMENT %s", msg_buf);
  167. X    send_private_message (who_msg->source, message);
  168. X  }
  169. X
  170. X  msg_buf[0] = '\0';
  171. X  FOREACH_PLAYER (c, t) {
  172. X    if (IS_OBSERVER(c->seat) && !c->spectator) {
  173. X      sprintf (msg_buf+strlen(msg_buf), "%s%s",
  174. X           (strlen(msg_buf) > 0)? ", ": " ", c->player_name);
  175. X    }
  176. X    if (strlen (msg_buf) > 50) {
  177. X      sprintf (message, "COMMENT OBSERVERS: %s", msg_buf);
  178. X      send_private_message (who_msg->source, message);
  179. X      msg_buf[0] = '\0';
  180. X    }
  181. X  }
  182. X  if (strlen(msg_buf) > 0) {
  183. X    sprintf (message, "COMMENT OBSERVERS: %s", msg_buf);
  184. X    send_private_message (who_msg->source, message);
  185. X  }
  186. X
  187. X  msg_buf[0] = '\0';
  188. X  FOREACH_PLAYER (c, t) {
  189. X    if (c->spectator) {
  190. X      sprintf (msg_buf+strlen(msg_buf), "%s%s",
  191. X           (strlen(msg_buf) > 0)? ", ": " ", c->player_name);
  192. X    }
  193. X    if (strlen (msg_buf) > 50) {
  194. X      sprintf (message, "COMMENT SPECTATORS: %s", msg_buf);
  195. X      send_private_message (who_msg->source, message);
  196. X      msg_buf[0] = '\0';
  197. X    }
  198. X  }
  199. X  if (strlen(msg_buf) > 0) {
  200. X    sprintf (message, "COMMENT SPECTATORS: %s", msg_buf);
  201. X    send_private_message (who_msg->source, message);
  202. X  }
  203. X}
  204. X
  205. Xstatic void Transmit_State_Information (t, c)
  206. X     Table t;
  207. X     Connection c;
  208. X/* If a board is currently being played at the table t, then transmits
  209. X * the state information for that board. 
  210. X */
  211. X{
  212. X  char buf1[100], buf2[100], buf3[100];
  213. X  Play_record *p;
  214. X  Connection d;
  215. X
  216. X  sprintf (buf1, "TABLE %d", t->table_no);
  217. X  send_private_message (c, buf1);
  218. X
  219. X  FOREACH_PLAYER (d, t) {
  220. X    if (d != c) {
  221. X      sprintf (buf1, "ACK %s %s", d->player_name,
  222. X           IS_PLAYER(d->seat)? seat_names[d->seat]: "");
  223. X      send_private_message (c, buf1);
  224. X    }
  225. X  } 
  226. X
  227. X  if (IS_PLAYER(c->seat)) {
  228. X    sprintf (buf1, "SEATPOS %s", seat_names[c->seat]);
  229. X    send_private_message (c, buf1);
  230. X  }
  231. X
  232. X  c->state = CSTATE_PLAYING;
  233. X  if (t->game_mode == STARTUP_MODE)
  234. X    return;
  235. X
  236. X  send_private_message (c, "DEAL");
  237. X
  238. X  if (t->board == NULL)
  239. X    return;
  240. X
  241. X  sprintf (buf1, "BOARD %s %d", t->board->source, t->board->serial_no);
  242. X  send_private_message (c, buf1);
  243. X
  244. X  Encode_board (t->board, buf1, buf2);
  245. X  server_send_unformatted (c, buf1);
  246. X  server_send_unformatted (c, buf2);
  247. X
  248. X  for (p = t->board->play_records; p != NULL; p = p->next) {
  249. X    sprintf (buf1, "RECORD %s %d", t->board->source, t->board->serial_no);
  250. X    send_private_message (c, buf1);
  251. X    Encode_play_record (p, buf1, buf2, buf3);
  252. X    server_send_unformatted (c, buf1);
  253. X    server_send_unformatted (c, buf2);
  254. X    server_send_unformatted (c, buf3);
  255. X  }
  256. X
  257. X  if ((p = t->play_record) != NULL) {
  258. X    sprintf (buf1, "USEREC %s %s %s %s", 
  259. X         p->player_names[PLAYER_NORTH], p->player_names[PLAYER_EAST],
  260. X         p->player_names[PLAYER_SOUTH], p->player_names[PLAYER_WEST]);
  261. X    send_private_message (c, buf1);
  262. X  }
  263. X
  264. X  sprintf (buf1, "SCORE %d %d %d %d",
  265. X       t->above_line[SIDE_NS], t->above_line[SIDE_EW],
  266. X       t->below_line[SIDE_NS], t->below_line[SIDE_EW]);
  267. X  send_private_message (c, buf1);
  268. X  
  269. X  switch (t->playing_mode) {
  270. X  case CLUB_PLAYING_MODE:
  271. X    send_private_message (c, "MODE CLUB");
  272. X    break;
  273. X  case FORMAL_PLAYING_MODE:
  274. X    send_private_message (c, "MODE FORMAL");
  275. X    break;
  276. X  case PRACTICE_PLAYING_MODE:
  277. X    send_private_message (c, "MODE PRACTICE");
  278. X    break;
  279. X  }
  280. X
  281. X  send_private_message (c, "BEGIN");
  282. X
  283. X  if (t->game_mode != SCORING_MODE)
  284. X    return;
  285. X
  286. X  send_private_message (c, "END");
  287. X}
  288. X
  289. Xstatic void Who_Response (who_msg, c, response)
  290. X     Message who_msg;
  291. X     Connection c;
  292. X     char *response;
  293. X{
  294. X  char buf[100];
  295. X
  296. X  sprintf (buf, "WHORESP %s %s", c->player_name, response);
  297. X  send_private_message (who_msg->source, buf);
  298. X}
  299. X
  300. Xstatic void Respond_to_Whois_Message (msg)
  301. X     Message msg;
  302. X{
  303. X  Connection c;
  304. X  char buf[80];
  305. X
  306. X  if (!strcmp(msg->p.data.whois.name, "*ALL*")) {
  307. X    FOREACH_PLAYER (c, msg->source->table) {
  308. X      if (strlen(c->fullname))
  309. X    Who_Response (msg, c, c->fullname);
  310. X      if (strlen(c->email))
  311. X    Who_Response (msg, c, c->email);
  312. X    }
  313. X    return;
  314. X  }
  315. X
  316. X  FOREACH_CONNECTION (c)
  317. X    if (!strcasecmp(msg->p.data.whois.name, c->player_name))
  318. X      break;
  319. X
  320. X  if (c == NULL) {
  321. X    sprintf (buf, "WHORESP %s %s", msg->p.data.whois.name,
  322. X         "THERE IS NO PLAYER WITH THIS NAME.");
  323. X    send_private_message (msg->source, buf);
  324. X  } else if ((strlen(c->fullname) == 0) && (strlen(c->email) == 0))
  325. X    Who_Response (msg, c, "NO INFORMATION AVAILABLE.");
  326. X  else {
  327. X    if (strlen(c->fullname))
  328. X      Who_Response (msg, c, c->fullname);
  329. X    if (strlen(c->email))
  330. X      Who_Response (msg, c, c->email);
  331. X  }
  332. X}
  333. X
  334. Xvoid Handle_Protocol_Message_for_Server (msg)
  335. X     Message msg;
  336. X/* Processes the message m.  If the message is a protocol message, then
  337. X   takes appropriate action based on the message.  Appends the message
  338. X   to the appropriate conversation queue if further action is warranted.
  339. X*/
  340. X{
  341. X  char message_buf [100];
  342. X  int s;
  343. X  int  propagate;
  344. X    /* A boolean flag which in the server mode indicates that the message
  345. X       received should automatically be propagated to all other players. */
  346. X  int pass_upwards;
  347. X    /* A boolean flag which indicates that the message should be put
  348. X       onto the conversation queue to be processed at the next level. */
  349. X  Table t = msg->source->table;
  350. X  Table tp;
  351. X
  352. X  propagate = !msg->private;
  353. X  pass_upwards = 1;
  354. X
  355. X  switch (msg->p.command) {
  356. X  case CMD_ERROR  :
  357. X    if (msg->source->state == CSTATE_CONNECTED) {
  358. X      sprintf (message_buf, "NORTH SEATERR OKBRIDGE %s: %s",
  359. X           major_revision_level, "I DON'T RECOGNIZE YOU -- GO AWAY!");
  360. X      fd_writeln (msg->source->channel, message_buf);
  361. X      close_connection (msg->source);
  362. X    } else {
  363. X/*
  364. X      sprintf (message_buf, "ERROR!! %s", msg->p.data.error.message);
  365. X      send_private_message (msg->source, message_buf);
  366. X*/
  367. X#ifdef LOGFILE
  368. X      fprintf (net_log, "** %s\n", msg->p.command_text);
  369. X      fprintf (net_log, "** %s\n", message_buf);
  370. X      fflush (net_log);
  371. X#endif
  372. X    }
  373. X    propagate = pass_upwards = 0;
  374. X    break;
  375. X
  376. X  case CMD_EMAIL:
  377. X    propagate = 0;
  378. X    if (msg->source->local)
  379. X      sprintf (Local_Player_Connection->email, "%s", msg->p.data.email.addr);
  380. X    else
  381. X      sprintf (msg->source->email, "%s", msg->p.data.email.addr);
  382. X    break;
  383. X
  384. X  case CMD_FULLNAME:
  385. X    propagate = 0;
  386. X    if (msg->source->local)
  387. X      sprintf (Local_Player_Connection->fullname, "%s", 
  388. X           msg->p.data.fullname.name);
  389. X    else
  390. X      sprintf (msg->source->fullname, "%s", msg->p.data.fullname.name);
  391. X    GPS_Broadcast_Server_Silently ();
  392. X    break;
  393. X
  394. X  case CMD_HELLO  :
  395. X    if (strcmp(major_revision_level, msg->p.data.hello.version)) {
  396. X      if (strcmp(msg->p.data.hello.version, "1.6")) {
  397. X    sprintf (message_buf, "CONNERR %s %s %s",
  398. X         "INCOMPATIBLE VERSIONS OF OKBRIDGE --",
  399. X         "SERVER IS USING VERSION", major_revision_level);
  400. X    send_private_message (msg->source, message_buf);
  401. X    close_connection (msg->source);
  402. X      } else {
  403. X    sprintf (message_buf, "OKBRIDGE ERROR !! OKBRIDGE %s%s: %s",
  404. X         major_revision_level, minor_revision_level,
  405. X         "I DON'T RECOGNIZE YOU -- GO AWAY!");
  406. X    server_send_unformatted (msg->source, message_buf);
  407. X    write (msg->source->channel, "\0", 1);
  408. X    close_connection (msg->source);
  409. X      }
  410. X      propagate = 0;
  411. X    } else {
  412. X      sprintf (msg->source->player_name, "%s", msg->p.player_name);
  413. X      msg->source->state = CSTATE_PLAYING;
  414. X      if (OCCUPIED(t, msg->p.data.hello.seat_req)) {
  415. X    msg->p.data.hello.seat_req = PLAYER_OBS;
  416. X    sprintf (msg->p.command_text, "%s HELLO %s %s OBS",
  417. X         msg->p.player_name, major_revision_level,
  418. X         msg->p.player_name);
  419. X      }
  420. X      Assign_seat (t, msg->source, msg->p.data.hello.seat_req);
  421. X      Transmit_State_Information (t, msg->source);
  422. X/*    GPS_Broadcast_Server_Silently (); */
  423. X      propagate = 1;
  424. X    }
  425. X    break;
  426. X
  427. X  case CMD_NAME:
  428. X    sprintf (msg->source->player_name, "%s", msg->p.data.name.new_name);
  429. X    break;
  430. X
  431. X  case CMD_QUIT   :
  432. X    if (!msg->source->local) {
  433. X      Vacate_seat (msg->source->table, msg->p.player_no);
  434. X      close_connection (msg->source);
  435. X    }
  436. X    GPS_Broadcast_Server_Silently ();
  437. X    break;
  438. X
  439. X  case CMD_PLAYREQ:
  440. X    propagate = 0;
  441. X    break;
  442. X
  443. X  case CMD_REGISTRY:
  444. X    propagate = 0;
  445. X    strcpy (msg->source->registry, msg->p.data.registry.id);
  446. X    break;
  447. X
  448. X  case CMD_SEATERR:
  449. X    propagate = 0;
  450. X    break;
  451. X
  452. X  case CMD_SEATPOS:
  453. X    propagate = 0;
  454. X    break;
  455. X
  456. X  case CMD_SEATREQ:
  457. X    propagate = 0;
  458. X    Request_Seat (msg->source, msg->p.data.seatreq);
  459. X    break;
  460. X
  461. X  case CMD_SERVEREQ:
  462. X    propagate = 0;
  463. X    if (Parse_Server_Command (msg->p.data.servereq.command)) {
  464. X      sprintf (message_buf, "COMMENT %s", Parser_Error_Buf);
  465. X      send_private_message (msg->source, message_buf);
  466. X    } else
  467. X      send_private_message (msg->source, 
  468. X                "COMMENT SERVER REQUEST ACKNOWLEDGED.");
  469. X    break;
  470. X
  471. X  case CMD_TABLE:
  472. X    propagate = 0;
  473. X    for (tp = Table_List; tp != NULL; tp = tp->next)
  474. X      if (tp->table_no == msg->p.data.tablereq)
  475. X    break;
  476. X
  477. X    if (tp != NULL)
  478. X      Local_table = tp;
  479. X    break;
  480. X
  481. X  case CMD_TABLEREQ:
  482. X    propagate = 0;
  483. X    for (tp = Table_List; tp != NULL; tp = tp->next)
  484. X      if (tp->table_no == msg->p.data.tablereq)
  485. X    break;
  486. X
  487. X    if (tp == NULL) {
  488. X      sprintf (message_buf, "COMMENT THERE IS NO TABLE NUMBER %d.",
  489. X           msg->p.data.tablereq);
  490. X      send_private_message (msg->source, message_buf);
  491. X    } else if (tp->table_no == t->table_no) {
  492. X      sprintf (message_buf, "COMMENT YOU ARE ALREADY AT TABLE %d.",
  493. X           msg->p.data.tablereq);
  494. X      send_private_message (msg->source, message_buf);
  495. X    } else {
  496. X      Assign_seat (msg->source->table, msg->source, PLAYER_OBS);
  497. X      Switch_Table (msg->source, tp);
  498. X      Transmit_State_Information (tp, msg->source);
  499. X      Send_seat (tp, PLAYER_OBS, PLAYER_OBS, msg->p.player_name);
  500. X    }
  501. X    break;
  502. X
  503. X  case CMD_WHO:
  504. X    Respond_to_who_message (msg);
  505. X    propagate = pass_upwards = 0;
  506. X    break;
  507. X
  508. X  case CMD_WHOIS:
  509. X    propagate = pass_upwards = 0;
  510. X    Respond_to_Whois_Message (msg);
  511. X    break;
  512. X
  513. X  default:
  514. X    break;
  515. X  }
  516. X
  517. X  if (propagate) {
  518. X    if (msg->loopback)
  519. X      Relay_message (msg->source->table, msg->source, msg->p.command,
  520. X             msg->p.command_text);
  521. X    else {
  522. X      sprintf (message_buf, "%s %s", 
  523. X           seat_names[msg->p.player_no],   msg->p.command_text);
  524. X      Relay_message (msg->source->table, msg->source, msg->p.command, 
  525. X             message_buf);
  526. X    }
  527. X    if (msg->p.command == CMD_BOARD)
  528. X      Relay_board (t, msg->source, msg->p.data.board.record);
  529. X    else if (msg->p.command == CMD_RECORD)
  530. X      Relay_play_record (t, msg->source, msg->p.data.record.play);
  531. X  }
  532. X
  533. X  if (pass_upwards)
  534. X    enqueue_message (t->conversation_queue, msg);
  535. X  else
  536. X    deallocate_message (msg);
  537. X
  538. X}
  539. X
  540. Xvoid Handle_Protocol_Message_for_Client (msg)
  541. X     Message msg;
  542. X/* Performs the corresponding action as Handle_Protocol_Message_for_Server */
  543. X{
  544. X  int pass_upwards = 1;
  545. X    /* A boolean flag which indicates that the message should be put
  546. X       onto the conversation queue to be processed at the next level. */
  547. X  char message_buf[80];
  548. X
  549. X  Table t = Local_table;
  550. X
  551. X  switch (msg->p.command) {
  552. X  case CMD_ERROR:
  553. X    sprintf (message_buf, "ERROR!! %s", msg->p.data.error.message);
  554. X    Network_Comment (message_buf);
  555. X    Network_Comment (msg->p.command_text);
  556. X#ifdef LOGFILE
  557. X    fprintf (net_log, "** %s\n", msg->p.command_text);
  558. X    fprintf (net_log, "** %s\n", message_buf);
  559. X    fflush (net_log);
  560. X#endif
  561. X    break;
  562. X
  563. X  case CMD_ACK:
  564. X    if (IS_PLAYER(msg->p.data.ack.position)) {
  565. X      sprintf (PLAYER_NAME(t, msg->p.data.ack.position), "%s", 
  566. X           msg->p.data.ack.player_name);
  567. X      t->Seats[msg->p.data.ack.position].occupied = 1;
  568. X    }
  569. X    break;
  570. X
  571. X  case CMD_HELLO:
  572. X    if (IS_PLAYER(msg->p.data.hello.seat_req)) {
  573. X      sprintf (PLAYER_NAME(t, msg->p.data.hello.seat_req), "%s", 
  574. X           msg->p.data.hello.player_name);
  575. X      t->Seats[msg->p.data.hello.seat_req].occupied = 1;
  576. X    }
  577. X    break;
  578. X
  579. X  case CMD_QUIT   :
  580. X    Vacate_seat (t, msg->p.player_no);
  581. X    break;
  582. X
  583. X  case CMD_SEAT   :
  584. X    if (msg->p.data.seat.old_pos != local_player)
  585. X      Vacate_seat (t, msg->p.data.seat.old_pos);
  586. X    if (IS_PLAYER(msg->p.data.seat.new_pos)) { 
  587. X      sprintf (PLAYER_NAME(t, msg->p.data.seat.new_pos), "%s", 
  588. X           msg->p.data.seat.player_name);
  589. X      t->Seats[msg->p.data.seat.new_pos].occupied = 1;
  590. X    }
  591. X    break;
  592. X    
  593. X  case CMD_SEATREQ:
  594. X    if (!client_mode)
  595. X      Request_Seat (msg->source, msg->p.data.seatreq);
  596. X    break;
  597. X
  598. X  case CMD_TABLE:
  599. X    t->table_no = msg->p.data.table;
  600. X    Vacate_seat (t, PLAYER_NORTH);
  601. X    Vacate_seat (t, PLAYER_EAST);
  602. X    Vacate_seat (t, PLAYER_SOUTH);
  603. X    Vacate_seat (t, PLAYER_WEST);
  604. X    break;
  605. X
  606. X  case CMD_WHO:
  607. X    if (!client_mode)
  608. X      Respond_to_who_message (msg);
  609. X    pass_upwards = 0;
  610. X    break;
  611. X
  612. X  case CMD_WHOIS:
  613. X    if (!client_mode) {
  614. X      if (local_player_full_name != NULL)
  615. X    sprintf (Local_Player_Connection->fullname, "%s", 
  616. X         local_player_full_name);
  617. X      if (local_player_email != NULL)
  618. X    sprintf (Local_Player_Connection->email, "%s", local_player_email);
  619. X      Respond_to_Whois_Message (msg);
  620. X    }
  621. X    pass_upwards = 0;
  622. X    break;
  623. X
  624. X  default:
  625. X    break;
  626. X  }
  627. X
  628. X  if (pass_upwards)
  629. X    enqueue_message (t->conversation_queue, msg);
  630. X  else
  631. X    deallocate_message (msg);
  632. X}
  633. END_OF_FILE
  634. if test 16640 -ne `wc -c <'cs.c'`; then
  635.     echo shar: \"'cs.c'\" unpacked with wrong size!
  636. fi
  637. # end of 'cs.c'
  638. fi
  639. if test -f 'display.c' -a "${1}" != "-c" ; then 
  640.   echo shar: Will not clobber existing file \"'display.c'\"
  641. else
  642. echo shar: Extracting \"'display.c'\" \(34086 characters\)
  643. sed "s/^X//" >'display.c' <<'END_OF_FILE'
  644. X/* display.c -- Display functions for OKbridge program.
  645. X *
  646. X ! Copyright (C) 1990-1992 by Matthew Clegg.  All Rights Reserved
  647. X ! 
  648. X ! OKbridge is made available as a free service to the Internet.
  649. X ! Accordingly, the following restrictions are placed on its use:
  650. X ! 
  651. X ! 1.  OKbridge may not be modified in any way without the explicit 
  652. X !     permission of Matthew Clegg.  
  653. X ! 
  654. X ! 2.  OKbridge may not be used in any way for commercial advantage.
  655. X !     It may not be placed on for-profit networks or on for-profit
  656. X !     computer systems.  It may not be bundled as part of a package
  657. X !     or service provided by a for-profit organization.
  658. X ! 
  659. X ! If you have questions about restrictions on the use of OKbridge,
  660. X ! write to mclegg@cs.ucsd.edu.
  661. X ! 
  662. X ! DISCLAIMER:  The user of OKbridge accepts full responsibility for any
  663. X ! damage which may be caused by OKbridge.
  664. X *
  665. X */
  666. X#include <stdio.h>
  667. X#include <string.h>
  668. X
  669. Xextern char *malloc ();
  670. X
  671. X#define _DISPLAY_
  672. X#include "state.h"
  673. X#include "terminal.h"
  674. X#include "display.h"
  675. X#include "help.h"
  676. X#include "input.h"
  677. X
  678. X#ifdef LOGFILE
  679. Xextern FILE *net_log;
  680. X#endif
  681. X
  682. Xtypedef int window[4];
  683. X/* Conceptually, we think of the screen as being divided into a number
  684. X   of windows, where each window describes one particular type of activity
  685. X   or aspect of the game.  Therefore, we make the following definitions,
  686. X   although these are only guidelines for operation of the display.
  687. XName of
  688. XWindow               Ymin    Xmin    Height    Width
  689. X-------             ----    ----    ----    ----            */
  690. Xwindow title          = { 1,    1,    6,    25};
  691. Xwindow top_hand      = { 2,    30,    4,    26};
  692. Xwindow scores         = { 1,    58,    6,    26};
  693. Xwindow left_hand     = { 8,    6,    6,    18};
  694. Xwindow playing_board = { 5,    27,    9,    26};
  695. Xwindow bidding_board = { 5,    1,    9,    57};
  696. Xwindow right_hand    = { 8,    56,    6,    23};
  697. Xwindow input         = { 13,    1,    6,    26};
  698. Xwindow status         = { 18,    1,    1,    79};
  699. Xwindow bottom_hand   = { 13,    30,    4,    26};
  700. Xwindow help         = { 13,    53,    6,    26};
  701. Xwindow converse         = { 19,    1,    6,    78};
  702. X#define XMIN(w)        w[1]
  703. X#define YMIN(w)         w[0]
  704. X#define XMAX(w)        (w[1] + w[3] - 1)
  705. X#define YMAX(w)        (w[0] + w[2] - 1)
  706. X#define HEIGHT(w)    w[2]
  707. X#define WIDTH(w)    w[3]
  708. X
  709. Xstatic int PLAYERHAND_X [4];
  710. Xstatic int PLAYERHAND_Y [4]; 
  711. Xstatic int CARDPOS_X    [4];
  712. Xstatic int CARDPOS_Y    [4];
  713. Xstatic char *position_names [4];
  714. Xstatic int comments_suspended = 0;
  715. Xstatic char line_buf [81];
  716. Xstatic int  status_loc;
  717. X
  718. X#define COMMENT_LENGTH 78
  719. X
  720. Xtypedef char comment_line [COMMENT_LENGTH];
  721. Xtypedef comment_line *comment_buf;
  722. X
  723. Xstatic int full_screen_talk_start = 3;
  724. X  /* The first line of the screen on which comments will be displayed,
  725. X     if the full screen is used for talking.  */
  726. Xstatic int full_screen_talk_end  = 22;
  727. X  /* The last line on which comments will be displayed for full screen mode. */
  728. Xstatic int full_screen_talk_size = 20;
  729. X  /* The total number of lines in the full screen talk display. */
  730. Xstatic int full_screen_cursor = 0;
  731. X  /* The line in the full screen buffer where the next talk message will be
  732. X     displayed. */
  733. X
  734. Xstatic int playing_screen_talk_start = 20;
  735. X  /* The first line of the screen on which comments will be displayed,
  736. X     if we are in playing mode. */
  737. Xstatic int playing_screen_talk_end = 24;
  738. X  /* last comment line for playing screen. */
  739. Xstatic int playing_screen_talk_size = 5;
  740. X  /* The total number of lines in the playing screen talk display. */
  741. X
  742. Xstatic int talk_start, talk_end;
  743. X  /* The current first and last lines for display of player comments. */
  744. Xstatic int talk_size;
  745. X  /* talk_end - talk_start + 1. */
  746. X
  747. Xstatic comment_line *full_screen_comments = NULL, 
  748. X                    *playing_screen_comments = NULL,
  749. X                    *player_comments;
  750. X
  751. X/* We record the list of cards played in the current trick, so that
  752. X   we can redisplay them during a refresh if necessary. */
  753. Xstatic int Current_trick [4];
  754. X  /* A list of plays indexed by position.  If the value is non-negative,
  755. X     then it indicates the play made by the corresponding player. */
  756. X
  757. Xstatic int status_display_level = 0;
  758. X  /* The number of locks which have been placed on the status display. */
  759. Xstatic char status_buf [10] [80];
  760. X  /* For each lock level, a record of the status message at that level. */
  761. X
  762. XBoard *Board_for_display;
  763. X  /* This is a pointer to the board which is being displayed in the
  764. X     SCORING_DISPLAY mode. */
  765. XPlay_record *Current_page_of_scores = NULL;
  766. X  /* The first play record which is being displayed on the current page
  767. X     of scores. */
  768. XPlay_record *Next_page_of_scores = NULL;
  769. X  /* The first play record which will be displayed on the next page 
  770. X     of scores. */
  771. X
  772. Xchar total_time_buffer [20];
  773. X  /* A buffer used for displaying the total time playing the current hand. */
  774. Xchar local_time_buffer [20];
  775. X  /* A buffer used for displaying the time used by the local player. */
  776. X    
  777. Xvoid Select_Talk_Mode ();
  778. Xvoid Select_Conversation_Mode ();
  779. Xvoid Display_Page_of_Scores ();
  780. Xvoid Refresh_Time_Display ();
  781. X
  782. X
  783. Xstatic void underline (ymin, xmin, length)
  784. X       int ymin, xmin, length;
  785. X/* Prints a line of hyphens BELOW the field beginning at (ymin,xmin),
  786. X *  of given length.
  787. X */
  788. X{
  789. X    int i;
  790. X    for (i = 0; i < length; i++)
  791. X        line_buf[i] = '-';
  792. X    line_buf[length] = '\0';
  793. X    print (ymin+1, xmin, line_buf);
  794. X}
  795. Xstatic void clear_screen_area (ymin, xmin, height, width)
  796. X       int ymin, xmin, height, width;
  797. X{
  798. X    int i;
  799. X    for (i = 0; i < width; i++) line_buf[i] = ' ';
  800. X    line_buf[width] = '\0';
  801. X    for (i = 0; i < height; i++) print (ymin+i, xmin, line_buf);
  802. X}
  803. X
  804. Xstatic void Display_Board_Number ()
  805. X{
  806. X  if ((Local_board != NULL) && (Local_board->source != NULL)) {
  807. X    sprintf (line_buf, "%s BOARD %d", Local_board->source,
  808. X         Local_board->serial_no);
  809. X    print (YMIN(title)+1,  XMIN(title),  line_buf);
  810. X  } else {
  811. X    sprintf (line_buf, "%d", hands_played);
  812. X    print (YMIN(title)+1, XMIN(title)+6, line_buf);
  813. X  }
  814. X
  815. X}
  816. X
  817. Xstatic void Redraw_Scoring_Panel ()
  818. X/* Redraws the scoring panel in the upper corner of the screen, which
  819. X   displays the vulnerabilities, number of tricks taken, and scores.
  820. X*/
  821. X{
  822. X  /* Setup the scoreboard: */
  823. X  if (local_player >= 4) {
  824. X    print (YMIN(scores), XMIN(scores) + 8,   "  N-S");
  825. X    print (YMIN(scores), XMIN(scores) + 16,  "  E-W");
  826. X  } else if (side_of(local_player) == SIDE_NS) {
  827. X    print (YMIN(scores), XMIN(scores) + 8,   "   WE");
  828. X    print (YMIN(scores), XMIN(scores) + 16,  " THEY");
  829. X  } else {
  830. X    print (YMIN(scores), XMIN(scores) + 16,  "   WE");
  831. X    print (YMIN(scores), XMIN(scores) + 8,   " THEY");
  832. X  }
  833. X  underline (YMIN(scores), XMIN(scores) + 8, 5);
  834. X  underline (YMIN(scores), XMIN(scores) + 16, 5);
  835. X  print (YMIN(scores)+2, XMIN(scores), "TRICKS");
  836. X  print (YMIN(scores)+3, XMIN(scores), "VUL");
  837. X  
  838. X  switch (Local_board->scoring_mode) {
  839. X  case RUBBER_SCORING:
  840. X    print (YMIN(scores)+4, XMIN(scores), "ABOVE");
  841. X    print (YMIN(scores)+5, XMIN(scores), "BELOW");
  842. X    print (YMIN(title)+1,  XMIN(title),  "HAND");
  843. X    break;
  844. X  case DUPLICATE_SCORING:
  845. X    print (YMIN(scores)+4, XMIN(scores), "TOTAL");
  846. X    print (YMIN(scores)+5, XMIN(scores), "PREV");
  847. X    print (YMIN(title)+1,  XMIN(title),  "BOARD");
  848. X    break;
  849. X  case IMP_SCORING:
  850. X    print (YMIN(scores)+4, XMIN(scores), "TOTAL");
  851. X    print (YMIN(scores)+5, XMIN(scores), "IMP");
  852. X    print (YMIN(title)+1,  XMIN(title),  "BOARD");
  853. X    break;
  854. X  case MP_SCORING:
  855. X    print (YMIN(scores)+4, XMIN(scores), "TOTAL");
  856. X    print (YMIN(scores)+5, XMIN(scores), "MP");
  857. X    print (YMIN(title)+1,  XMIN(title),  "BOARD");
  858. X    break;
  859. X  default:
  860. X    break;
  861. X  }
  862. X
  863. X  Display_Tricks_Taken ();
  864. X  Display_Above_Line_Points ();
  865. X  Display_Below_Line_Points ();
  866. X  Display_Vulnerabilities ();
  867. X  Display_Board_Number ();
  868. X
  869. X}
  870. X
  871. Xstatic void Redraw_Conversation_Area ()
  872. X{
  873. X  int i;
  874. X
  875. X  /* Setup the conversational area: */
  876. X  for (i = 0; i <= XMAX(converse); i++) line_buf[i] = '-';
  877. X  line_buf[72] = '+';
  878. X  line_buf[XMAX(converse)+1] = '\0';
  879. X  print (YMIN(converse), XMIN(converse), line_buf);
  880. X  for (i = talk_start; i <= talk_end; i++) {
  881. X    print (i, XMIN(converse), "|");
  882. X    print (i, XMAX(converse)+1, "|");
  883. X  }
  884. X
  885. X  /* Setup the input area: */
  886. X  print (TALK_ROW, TALK_COL, "TALK");
  887. X  status_loc = YMIN(status);
  888. X
  889. X}
  890. X
  891. Xstatic void Redraw_Bidding_Display ()
  892. X{
  893. X  int i, p;
  894. X  hand h;
  895. X  
  896. X  Display_Bidding_Board ();
  897. X  if (IS_PLAYER(local_player)) {
  898. X    Generate_holdings (Local_board, Local_play->play_list, 0, local_player, h);
  899. X    Display_Hand_for_Bidding (local_player, h);
  900. X  } else if (spectator_mode) {
  901. X    Generate_holdings (Local_board, Local_play->play_list, 0, 
  902. X               revealed_bidder, h);
  903. X    Display_Hand_for_Bidding (revealed_bidder, h);
  904. X  }
  905. X
  906. X  p = Local_board->dealer;
  907. X  for (i = 0; i < Local_play->no_bids; i++) {
  908. X    Display_Bid (i);
  909. X    p = player_next [p];
  910. X  }
  911. X  Display_Bidder (p);
  912. X  Refresh_Time_Display ();
  913. X  print (PLAY_ROW, PLAY_COL, "BID ");
  914. X}
  915. X
  916. Xstatic void Redraw_Playing_Display ()
  917. X{
  918. X  int i;
  919. X
  920. X  Display_Contract (); 
  921. X  Display_Playing_Board ();
  922. X
  923. X  for (i = 0; i < 4; i++)
  924. X    if (revealed_hands[i]) {
  925. X      if (Local_table->game_mode == PLAYING_MODE)
  926. X    Display_Hand(i);
  927. X      else
  928. X    Display_Partial_Hand (i, 0);
  929. X    }
  930. X
  931. X  for (i = 0; i < 4; i++)
  932. X    Display_Play (i, Current_trick[i]);
  933. X
  934. X  Display_Player (Local_play->next_player);
  935. X  Refresh_Time_Display ();
  936. X  print (PLAY_ROW, PLAY_COL, "PLAY");
  937. X}
  938. X
  939. Xstatic void Redraw_Scoring_Display ()
  940. X{
  941. X  Display_Page_of_Scores (Current_page_of_scores);
  942. X}
  943. X
  944. Xvoid Display_Player_Position ()
  945. X{
  946. X  char buf[80], *position_name;
  947. X  
  948. X  if (IS_PLAYER(local_player))
  949. X    position_name = seat_names[local_player];
  950. X  else if (spectator_mode)
  951. X    position_name = "SPECTATOR";
  952. X  else
  953. X    position_name = "OBSERVER";
  954. X  
  955. X  sprintf (buf, "OKBRIDGE %s%s  %s     ", 
  956. X       major_revision_level, minor_revision_level, position_name);
  957. X  
  958. X  print (1, 1, buf);
  959. X} 
  960. X
  961. Xvoid Refresh_Status_Display ();
  962. Xvoid Begin_full_screen_talk_mode ();
  963. Xvoid Recompute_Display_Positions ();
  964. Xvoid Reset_Display ()
  965. X/* Redraws the main features of the screen.  Used in the process
  966. X * of doing a 'refresh'.
  967. X */
  968. X{
  969. X  if (display_mode == MANUAL_DISPLAY)
  970. X    return;
  971. X
  972. X  clear_screen ();
  973. X
  974. X  Recompute_Display_Positions ();
  975. X
  976. X  if (display_mode == HELP_DISPLAY) {
  977. X    Suspend_Comment_Display ();
  978. X    status_loc = terminal_lines;
  979. X    display_topics ("LIST OF HELP TOPICS");
  980. X    print (terminal_lines-1, 1, "HELP");
  981. X    Refresh_Status_Display ();
  982. X    return;
  983. X  }
  984. X
  985. X  Display_Player_Position ();
  986. X  Continue_Comment_Display ();
  987. X  
  988. X  switch (display_mode) {
  989. X  case TALK_DISPLAY:
  990. X    Begin_full_screen_talk_mode ();
  991. X    break;
  992. X  case BIDDING_DISPLAY:
  993. X    Redraw_Bidding_Display ();
  994. X    Redraw_Scoring_Panel ();
  995. X    Redraw_Conversation_Area ();
  996. X    break;
  997. X  case PLAYING_DISPLAY:
  998. X    Redraw_Playing_Display ();
  999. X    Redraw_Scoring_Panel ();
  1000. X    Redraw_Conversation_Area ();
  1001. X    break;
  1002. X  case SCORING_DISPLAY:
  1003. X    Redraw_Scoring_Display ();
  1004. X    Redraw_Conversation_Area ();
  1005. X    break;
  1006. X  }
  1007. X
  1008. X  Refresh_Player_Comments ();
  1009. X  Refresh_Status_Display ();
  1010. X}
  1011. X
  1012. Xvoid Recompute_Display_Positions ()
  1013. X/* Recomputes a number of internal constants for the display. */
  1014. X{
  1015. X  int l = local_player;
  1016. X  
  1017. X  if (l >= 4) l = PLAYER_SOUTH;
  1018. X  
  1019. X  PLAYERHAND_X [l] = XMIN(bottom_hand);
  1020. X  PLAYERHAND_Y [l] = YMIN(bottom_hand);
  1021. X  PLAYERHAND_X [player_next[l]] = XMIN(left_hand);
  1022. X  PLAYERHAND_Y [player_next[l]] = YMIN(left_hand);
  1023. X  PLAYERHAND_X [player_partner[l]] = XMIN(top_hand);
  1024. X  PLAYERHAND_Y [player_partner[l]] = YMIN(top_hand);
  1025. X  PLAYERHAND_X [player_prev[l]] = XMIN(right_hand);
  1026. X  PLAYERHAND_Y [player_prev[l]] = YMIN(right_hand);
  1027. X  
  1028. X  CARDPOS_Y[l] = YMAX(playing_board) - 2;
  1029. X  CARDPOS_X[l] = (XMAX(playing_board) + 
  1030. X          XMIN(playing_board))/2;
  1031. X  CARDPOS_Y[player_next[l]] = (YMAX(playing_board) + 
  1032. X                   YMIN(playing_board))/2;
  1033. X  CARDPOS_X[player_next[l]] = XMIN(playing_board) + 3;
  1034. X  CARDPOS_Y[player_partner[l]] = YMIN(playing_board) + 2;
  1035. X  CARDPOS_X[player_partner[l]] = (XMAX(playing_board) + 
  1036. X                  XMIN(playing_board))/2;
  1037. X  CARDPOS_Y[player_prev[l]] = (YMAX(playing_board) + 
  1038. X                   YMIN(playing_board))/2;
  1039. X  CARDPOS_X[player_prev[l]] = XMAX(playing_board) - 4;
  1040. X  
  1041. X  position_names[0] = PLAYER_NAME(Local_table, l);
  1042. X  position_names[1] = PLAYER_NAME(Local_table, player_next[l]);
  1043. X  position_names[2] = PLAYER_NAME(Local_table, player_partner[l]);
  1044. X  position_names[3] = PLAYER_NAME(Local_table, player_prev[l]);
  1045. X}
  1046. X
  1047. Xvoid Initialize_Display ()
  1048. X/* Should be called once when the program starts up. */
  1049. X{ 
  1050. X  Initialize_Player_Comments ();
  1051. X  status_buf[0][0] = '\0';
  1052. X  display_mode = TALK_DISPLAY;
  1053. X  Current_trick[0] = Current_trick[1] = 
  1054. X    Current_trick[2] = Current_trick[3] = -1;
  1055. X
  1056. X  Reset_Display ();
  1057. X  Recompute_Display_Positions ();
  1058. X}
  1059. X
  1060. Xvoid Reinitialize_Display ()
  1061. X{
  1062. X  Reinitialize_Player_Comments ();
  1063. X  Reset_Display ();
  1064. X
  1065. X  Recompute_Display_Positions ();
  1066. X}
  1067. X
  1068. Xvoid Refresh_Display ()
  1069. X/* Resets the terminal display and redraws everything. */
  1070. X{
  1071. X  Reset_Display ();
  1072. X}
  1073. X
  1074. Xvoid Clear_Playing_Area ();
  1075. X
  1076. Xvoid Refresh_Player_Names ()
  1077. X/* Redraws the player names.  Useful in case one of the players has changed
  1078. X   position. */
  1079. X{
  1080. X  if ((display_mode != BIDDING_DISPLAY) && (display_mode != PLAYING_DISPLAY))
  1081. X    return;
  1082. X
  1083. X  if (display_mode == BIDDING_DISPLAY) {
  1084. X    Clear_Bidding_Board ();
  1085. X    Redraw_Bidding_Display ();
  1086. X  } else {
  1087. X    Clear_Playing_Area ();
  1088. X    Redraw_Playing_Display ();
  1089. X  }
  1090. X
  1091. X}
  1092. X
  1093. Xvoid Set_Display_Mode (mode)
  1094. X     int mode;
  1095. X{
  1096. X  if (display_mode == mode)
  1097. X    return;
  1098. X
  1099. X  display_mode = mode;
  1100. X
  1101. X  if ((mode == HELP_DISPLAY) || (mode == MANUAL_DISPLAY)) {
  1102. X    clear_screen ();
  1103. X    Suspend_Comment_Display ();
  1104. X    status_loc = terminal_lines;
  1105. X    return;
  1106. X  }
  1107. X
  1108. X  if (display_mode == TALK_DISPLAY)
  1109. X    Select_Talk_Mode ();
  1110. X  else
  1111. X    Select_Conversation_Mode ();
  1112. X
  1113. X  Refresh_Display ();
  1114. X}
  1115. Xvoid Display_Tricks_Taken ()
  1116. X{
  1117. X  sprintf (line_buf,"%5d   %5d",
  1118. X       Local_play->tricks[SIDE_NS], Local_play->tricks[SIDE_EW]);
  1119. X  print (YMIN(scores)+2,XMIN(scores)+8, line_buf);
  1120. X}
  1121. X
  1122. Xvoid Format_IMP_string (score, buf)
  1123. X     int score; char *buf;
  1124. X{
  1125. X  int whole, fraction;
  1126. X
  1127. X
  1128. X  if ((-95 < score) && (score < 0)) {
  1129. X    score = (score - 5) / 10;
  1130. X    sprintf (buf, " -0.%d", -score);
  1131. X    return;
  1132. X  } else if (score < 0) {
  1133. X    score = (score - 5) / 10;
  1134. X    fraction = (-score) % 10;
  1135. X    whole = -((-score) / 10);
  1136. X  } else {
  1137. X    score = (score + 5) / 10;
  1138. X    fraction = score % 10;
  1139. X    whole = score / 10;
  1140. X  }
  1141. X
  1142. X  if (fraction == 0)
  1143. X    sprintf (buf, "%4d. ", whole);
  1144. X  else
  1145. X    sprintf (buf, "%4d.%d", whole, fraction);
  1146. X}
  1147. Xvoid Display_Above_Line_Points ()
  1148. X{
  1149. X  char ew_buf[10], ns_buf [10];
  1150. X
  1151. X  if (Local_board->scoring_mode == IMP_SCORING) {
  1152. X    Format_IMP_string (Local_table->above_line[SIDE_NS], ns_buf);
  1153. X    Format_IMP_string (Local_table->above_line[SIDE_EW], ew_buf);
  1154. X    sprintf (line_buf,"%6s  %6s", ns_buf, ew_buf);
  1155. X  } else if (Local_board->scoring_mode == MP_SCORING) {
  1156. X    sprintf (line_buf, "%5.2f  %6.2f", 
  1157. X         ((float) Local_table->above_line[SIDE_NS]) * 0.01,
  1158. X         ((float) Local_table->above_line[SIDE_EW]) * 0.01);
  1159. X  } else
  1160. X    sprintf (line_buf,"%5d   %5d",
  1161. X         Local_table->above_line[SIDE_NS], 
  1162. X         Local_table->above_line[SIDE_EW]);
  1163. X
  1164. X  print (YMIN(scores)+4,XMIN(scores)+8, line_buf);
  1165. X}
  1166. Xvoid Display_Below_Line_Points ()
  1167. X{
  1168. X  char ew_buf[10], ns_buf [10];
  1169. X
  1170. X  if (Local_board->scoring_mode == IMP_SCORING) {
  1171. X    Format_IMP_string (Local_table->below_line[SIDE_NS], ns_buf);
  1172. X    Format_IMP_string (Local_table->below_line[SIDE_EW], ew_buf);
  1173. X    sprintf (line_buf,"%6s  %6s", ns_buf, ew_buf);
  1174. X  } else if (Local_board->scoring_mode == MP_SCORING) {
  1175. X    sprintf (line_buf, "%5.2f  %6.2f", 
  1176. X         ((float) Local_table->below_line[SIDE_NS]) * 0.01,
  1177. X         ((float) Local_table->below_line[SIDE_EW]) * 0.01);
  1178. X  } else
  1179. X    sprintf (line_buf,"%5d   %5d",
  1180. X         Local_table->below_line[SIDE_NS], 
  1181. X         Local_table->below_line[SIDE_EW]);
  1182. X
  1183. X  print (YMIN(scores)+5,XMIN(scores)+8, line_buf);
  1184. X}
  1185. Xvoid Display_Vulnerabilities   ()
  1186. X{
  1187. X  char *nsv, *ewv;
  1188. X  if (Local_board->vulnerable[SIDE_NS]) 
  1189. X    nsv = "  YES";
  1190. X  else
  1191. X    nsv = "   NO";
  1192. X
  1193. X  if (Local_board->vulnerable[SIDE_EW]) 
  1194. X    ewv = "  YES";
  1195. X  else
  1196. X    ewv = "   NO";
  1197. X
  1198. X  sprintf (line_buf, "%s   %s",nsv,ewv);
  1199. X  print (YMIN(scores)+3, XMIN(scores)+8, line_buf);
  1200. X}
  1201. Xvoid Clear_Bidding_Board ()
  1202. X{
  1203. X  int x, y, h, w;
  1204. X
  1205. X  x = XMIN(bidding_board);
  1206. X  y = YMIN(bidding_board);
  1207. X  h = HEIGHT(bidding_board);
  1208. X  w = WIDTH(bidding_board);
  1209. X  clear_screen_area (y, x, h, w);
  1210. X  clear_screen_area (PLAY_ROW, 1, 1, 10);
  1211. X}
  1212. X
  1213. Xvoid Refresh_Time_Display ()
  1214. X{
  1215. X  if ((display_mode != PLAYING_DISPLAY) && (display_mode != BIDDING_DISPLAY))
  1216. X    return;
  1217. X
  1218. X  print (PLAY_ROW,   80 - strlen(total_time_buffer), total_time_buffer);
  1219. X  print (PLAY_ROW+1, 80 - strlen(local_time_buffer), local_time_buffer);
  1220. X}
  1221. X
  1222. Xvoid Display_Total_Time (total_buf, local_buf)
  1223. X     char *total_buf, *local_buf;
  1224. X{
  1225. X  sprintf (total_time_buffer, "%s", total_buf);
  1226. X  sprintf (local_time_buffer, "%s", local_buf);
  1227. X  Refresh_Time_Display ();
  1228. X}
  1229. X
  1230. Xvoid Display_Bidding_Board ()
  1231. X/* The bidding display is given as four columns, similar to that found
  1232. X   in many bridge books.  At the top of each column is printed the
  1233. X   corresponding input parameter string to identify the bidder. */
  1234. X{
  1235. X  char *first, *second, *third, *fourth;
  1236. X  
  1237. X  Clear_Bidding_Board ();
  1238. X  
  1239. X  first  = PLAYER_NAME(Local_table, PLAYER_NORTH);
  1240. X  second = PLAYER_NAME(Local_table, player_next[PLAYER_NORTH]);
  1241. X  third  = PLAYER_NAME(Local_table, player_partner[PLAYER_NORTH]);
  1242. X  fourth = PLAYER_NAME(Local_table, player_prev[PLAYER_NORTH]);
  1243. X  
  1244. X  print(YMIN(bidding_board), XMIN(bidding_board)+05, first);
  1245. X  print(YMIN(bidding_board), XMIN(bidding_board)+15, second);
  1246. X  print(YMIN(bidding_board), XMIN(bidding_board)+25, third);
  1247. X  print(YMIN(bidding_board), XMIN(bidding_board)+35, fourth);
  1248. X  
  1249. X  underline(YMIN(bidding_board),XMIN(bidding_board)+05,strlen(first));
  1250. X  underline(YMIN(bidding_board),XMIN(bidding_board)+15,strlen(second));
  1251. X  underline(YMIN(bidding_board),XMIN(bidding_board)+25,strlen(third));
  1252. X  underline(YMIN(bidding_board),XMIN(bidding_board)+35,strlen(fourth));
  1253. X
  1254. X  Display_Board_Number ();
  1255. X}
  1256. Xstatic void Display_suit (y, x, cards)
  1257. X     int y, x; suit_type cards;
  1258. X/* Displays the cards in a given suit held by a player.  As input,
  1259. X * cards[] is an array of 13 elements, where cards[i] is TRUE if the
  1260. X * player holds the given card.  Displays the cards as a string on
  1261. X * the terminal, beginning at coordinates <y,x>.
  1262. X */
  1263. X{
  1264. X  int i;
  1265. X  for (i = 12; i >= 0; i--)
  1266. X    if (cards[i])
  1267. X      print (y, x++, rank_names[i]);
  1268. X}
  1269. Xvoid Display_Hand_for_Bidding (pos, h)
  1270. X     int pos; hand h;
  1271. X{
  1272. X  int i, x, y;
  1273. X  
  1274. X  if (pos >= 4) return;
  1275. X  
  1276. X  y = YMIN(bidding_board);
  1277. X  x = XMIN(bidding_board) + 45;
  1278. X  clear_screen_area (y, x, HEIGHT(bidding_board), XMAX(bidding_board)-x+1);
  1279. X  for (i = 0; i < 6; i++)
  1280. X    print (y+i, x, "|");
  1281. X  
  1282. X  x+=1;
  1283. X  print (y, x, PLAYER_NAME(Local_table, pos));
  1284. X  underline (y, x, strlen(PLAYER_NAME(Local_table, pos)));
  1285. X  print (y+2, x, "S "); Display_suit (y+2, x+2, h+39);
  1286. X  print (y+3, x, "H "); Display_suit (y+3, x+2, h+26);
  1287. X  print (y+4, x, "D "); Display_suit (y+4, x+2, h+13);
  1288. X  print (y+5, x, "C "); Display_suit (y+5, x+2, h);
  1289. X}
  1290. X
  1291. Xvoid Clear_Bidder ()
  1292. X{
  1293. X  clear_screen_area (YMIN(title)+2, XMIN(title), 1, 20);
  1294. X}
  1295. Xvoid Display_Bidder (player)
  1296. X    int player;
  1297. X{
  1298. X  char bid_buf[80];
  1299. X  sprintf (bid_buf, "(%c) %s's BID        ", *("NESW" + player),
  1300. X       PLAYER_NAME(Local_table, player));
  1301. X         
  1302. X  print (YMIN(title)+2, XMIN(title), bid_buf);
  1303. X}
  1304. Xvoid Display_Bid (k)
  1305. X     int k;
  1306. X/* Displays the k-th bid in the bidding list. */
  1307. X{
  1308. X  int i, x, y, bid, position, round, player;
  1309. X  char bid_string [10];
  1310. X  
  1311. X  round = (k / 4) + 1;
  1312. X  bid = Local_play->bids[k];
  1313. X  player = k % 4;
  1314. X  for (i = 0; i != Local_board->dealer; i++)
  1315. X    player = player_next[player];
  1316. X  
  1317. X  y = YMIN(bidding_board) + round + 1;
  1318. X  sprintf (line_buf, " %2d", round);
  1319. X  print (y, XMIN(bidding_board), line_buf);
  1320. X  
  1321. X  y++; 
  1322. X  for (x = Local_board->dealer; x < 4; x++)
  1323. X    if (x == player) y--;
  1324. X  
  1325. X  position = player;
  1326. X  x = XMIN(bidding_board) + 10 * position + 5;
  1327. X  if (bid == BID_PASS)
  1328. X    sprintf (bid_string, "--");
  1329. X  else
  1330. X    sprintf (bid_string, "%s", bid_names[bid]);
  1331. X  if (Local_play->alerts[k])
  1332. X    sprintf (bid_string + strlen(bid_string)," !");
  1333. X  
  1334. X  print (y, x, bid_string);
  1335. X}
  1336. Xvoid Display_Contract ()
  1337. X{
  1338. X  char double_buf[40], contract_buf[60];
  1339. X  int trump_suit = trumpsuit_of (Local_play->contract);
  1340. X  int contract   = level_of (Local_play->contract);
  1341. X  if (Local_play->contract == BID_PASS) {
  1342. X    print (YMIN(title)+3, XMIN(title), "PASSED HAND");
  1343. X    return;
  1344. X  }
  1345. X
  1346. X  clear_screen_area (YMIN(title)+2, XMIN(title), HEIGHT(title),
  1347. X               WIDTH(title));
  1348. X  if (Local_play->doubled == 2)
  1349. X    sprintf (double_buf,"  REDOUBLED");
  1350. X  else if (Local_play->doubled == 1)
  1351. X    sprintf (double_buf, "  DOUBLED");
  1352. X  else
  1353. X    double_buf[0] = '\0';
  1354. X  sprintf (contract_buf, "%1d%s (%s)%s",contract,suit_names[trump_suit],
  1355. X       PLAYER_NAME(Local_table, Local_play->declarer), double_buf);
  1356. X  print (YMIN(title)+3, XMIN(title), contract_buf);
  1357. X}
  1358. X
  1359. Xvoid Clear_Playing_Area () 
  1360. X{
  1361. X  clear_screen_area (YMIN(playing_board), XMIN(playing_board),
  1362. X             HEIGHT(playing_board), WIDTH(playing_board));
  1363. X  clear_screen_area (YMIN(left_hand), XMIN(left_hand),
  1364. X             HEIGHT(left_hand), WIDTH(left_hand));
  1365. X  clear_screen_area (YMIN(right_hand), XMIN(right_hand),
  1366. X             HEIGHT(right_hand), WIDTH(right_hand));
  1367. X  clear_screen_area (YMIN(top_hand), XMIN(top_hand),
  1368. X             HEIGHT(top_hand), WIDTH(top_hand));
  1369. X  clear_screen_area (YMIN(bottom_hand), XMIN(bottom_hand),
  1370. X             HEIGHT(bottom_hand), WIDTH(bottom_hand));
  1371. X  clear_screen_area (YMIN(title)+3, XMIN(title), 1, WIDTH(title));
  1372. X  
  1373. X}
  1374. X
  1375. Xvoid Clear_Playing_Board ()
  1376. X{
  1377. X  Clear_Playing_Area ();
  1378. X
  1379. X  Current_trick[0] = Current_trick[1] = 
  1380. X    Current_trick[2] = Current_trick[3] = -1;
  1381. X}
  1382. Xvoid Display_Playing_Board ()
  1383. X{
  1384. X  int i;
  1385. X  
  1386. X  for (i = 0; i < 4; i++)
  1387. X    print (PLAYERHAND_Y[i]+1, PLAYERHAND_X[i]+12 -
  1388. X       strlen(PLAYER_NAME(Local_table, i)), PLAYER_NAME(Local_table, i));
  1389. X  
  1390. X  for (i = 0; i < WIDTH(playing_board)-1; i++) line_buf[i] = '-';
  1391. X  line_buf[WIDTH(playing_board)-2] = '\0';
  1392. X  print (YMIN(playing_board)+1,XMIN(playing_board)+1,line_buf);
  1393. X  print (YMAX(playing_board)-1,XMIN(playing_board)+1,line_buf);
  1394. X  
  1395. X  for (i = YMIN(playing_board)+2; i < YMAX(playing_board)-1; i++) {
  1396. X    print (i, XMIN(playing_board)+1, "|");
  1397. X    print (i, XMAX(playing_board)-1, "|");
  1398. X  }
  1399. X}
  1400. Xvoid Display_Player (player)
  1401. X     int player;
  1402. X{
  1403. X  char play_buf[80];
  1404. X  
  1405. X  if (player < 0)
  1406. X    sprintf (play_buf, "                    ");
  1407. X  else if (player == player_partner[Local_play->declarer])
  1408. X    sprintf (play_buf, "DUMMY'S PLAY        ");
  1409. X  else
  1410. X    sprintf (play_buf, "(%c) %s's PLAY        ", 
  1411. X         *("NESW" + player), PLAYER_NAME(Local_table, player));
  1412. X  print (YMIN(title)+4, XMIN(title), play_buf);
  1413. X}
  1414. Xvoid Display_Play (p, card)
  1415. X     int p, card;
  1416. X{
  1417. X  int x, y;
  1418. X  
  1419. X  y = CARDPOS_Y [p];
  1420. X  x = CARDPOS_X [p];
  1421. X  if ((0 <= card) && (card < 52))
  1422. X    print (y, x, card_names[card]);
  1423. X  else
  1424. X    print (y, x, "   ");
  1425. X  
  1426. X  Current_trick [p] = card;
  1427. X}
  1428. Xvoid Clear_Plays  ()
  1429. X{
  1430. X  Display_Play (PLAYER_NORTH, -1);
  1431. X  Display_Play (PLAYER_EAST,  -1);
  1432. X  Display_Play (PLAYER_SOUTH, -1);
  1433. X  Display_Play (PLAYER_WEST,  -1);
  1434. X}
  1435. X
  1436. Xvoid Display_Partial_Hand (p, no_plays)
  1437. X     int p; int no_plays;
  1438. X{
  1439. X  int y, x, i;
  1440. X  hand h;
  1441. X  
  1442. X  if (IS_OBSERVER(p))
  1443. X    return;
  1444. X  
  1445. X  y = PLAYERHAND_Y [p];
  1446. X  x = PLAYERHAND_X [p];
  1447. X  for (i = 0; i < 4; i++)
  1448. X    print (y+i, x, "                   ");
  1449. X  
  1450. X  Generate_holdings (Local_board, Local_play->play_list, no_plays, p, h);
  1451. X  print (y,   x+5-8, "        ");
  1452. X  print (y,   x+5-strlen(PLAYER_NAME(Local_table, p)), 
  1453. X     PLAYER_NAME(Local_table, p));
  1454. X  if (p == player_partner[Local_play->declarer])
  1455. X    print (y+1, x+5-7, "(DUMMY)");
  1456. X  print (y,   x+7, "S "); Display_suit (y,   x+10, h+39);
  1457. X  print (y+1, x+7, "H "); Display_suit (y+1, x+10, h+26);
  1458. X  print (y+2, x+7, "D "); Display_suit (y+2, x+10, h+13);
  1459. X  print (y+3, x+7, "C "); Display_suit (y+3, x+10, h);
  1460. X  
  1461. X  revealed_hands[p] = 1;
  1462. X}
  1463. X
  1464. Xvoid Display_Hand (p)
  1465. X     int p;
  1466. X{
  1467. X  Display_Partial_Hand (p, Local_play->no_plays);
  1468. X}
  1469. X
  1470. Xvoid Clear_Hand (p)
  1471. X     int p;
  1472. X{
  1473. X  int y, x, i;
  1474. X  
  1475. X  y = PLAYERHAND_Y [p];
  1476. X  x = PLAYERHAND_X [p];
  1477. X  for (i = 0; i < 4; i++)
  1478. X    print (y+i, x, "                   ");
  1479. X  
  1480. X  print (y,   x+5-strlen(PLAYER_NAME(Local_table, p)), 
  1481. X     PLAYER_NAME(Local_table, p));
  1482. X  if (p == player_partner[Local_play->declarer])
  1483. X    print (y+1, x+5-7, "(DUMMY)");
  1484. X  
  1485. X  revealed_hands[p] = 0;
  1486. X}
  1487. X
  1488. Xstatic char *seat_letters [4] = {"N", "E", "S", "W"};
  1489. Xstatic char *double_names [3] = {"", "-X", "-XX"};
  1490. X
  1491. Xstatic void Display_Score_Record (b, p, line)
  1492. X     Board *b;
  1493. X     Play_record *p;
  1494. X     int line;
  1495. X{
  1496. X  char contract_buf[10];
  1497. X  char buf[100];
  1498. X  char mark;
  1499. X
  1500. X  if (p->contract == BID_PASS)
  1501. X    sprintf (contract_buf, "PASSED");
  1502. X  else
  1503. X    sprintf (contract_buf, "%s%s", bid_names[p->contract], 
  1504. X         double_names[p->doubled]);
  1505. X
  1506. X  if (!strcasecmp(p->player_names[PLAYER_NORTH], local_player_name) ||
  1507. X      !strcasecmp(p->player_names[PLAYER_SOUTH], local_player_name))
  1508. X    mark = '>';
  1509. X  else
  1510. X    mark = ' ';
  1511. X
  1512. X  sprintf (buf,
  1513. X       "  %c   N %-8s S %-8s %-8s %-2s %+6d %6d %6.1f %6.2f", mark,
  1514. X       p->player_names[PLAYER_NORTH], p->player_names[PLAYER_SOUTH],
  1515. X       contract_buf, seat_letters[p->declarer], p->result,
  1516. X       p->below_line[SIDE_NS], 
  1517. X       p->imatch_points[SIDE_NS],
  1518. X       p->match_points[SIDE_NS]);
  1519. X  print (line, 1, buf);
  1520. X
  1521. X  if (!strcasecmp(p->player_names[PLAYER_EAST], local_player_name) ||
  1522. X      !strcasecmp(p->player_names[PLAYER_WEST], local_player_name))
  1523. X    mark = '>';
  1524. X  else
  1525. X    mark = ' ';
  1526. X
  1527. X  sprintf (buf,
  1528. X       "  %c   E %-8s W %-8s %-8s %2s %6s %6d %6.1f %6.2f", mark,
  1529. X       p->player_names[PLAYER_EAST], p->player_names[PLAYER_WEST],
  1530. X       " ", " ", " ", p->below_line[SIDE_EW],
  1531. X       p->imatch_points[SIDE_EW],
  1532. X       p->match_points[SIDE_EW]);
  1533. X  print (line+1, 1, buf);
  1534. X}
  1535. X
  1536. Xvoid Display_Page_of_Scores (p)
  1537. X     Play_record *p;
  1538. X/* Displays a page of scores, starting with the play record p.  Sets the
  1539. X   variable Current_page_of_scores equal to p, and the variable 
  1540. X   Next_page_of_scores equal to the first undisplayed record.
  1541. X*/
  1542. X{
  1543. X  char buf[100];
  1544. X  char *vul_string;
  1545. X  int line = 5;
  1546. X  Board *b = Board_for_display;
  1547. X
  1548. X  clear_screen_area (1, 1, 15, 80);
  1549. X
  1550. X  Current_page_of_scores = Next_page_of_scores = p;
  1551. X
  1552. X  if (b->vulnerable[SIDE_NS] && b->vulnerable[SIDE_EW])
  1553. X    vul_string = "BOTH";
  1554. X  else if (b->vulnerable[SIDE_NS])
  1555. X    vul_string = "N-S";
  1556. X  else if (b->vulnerable[SIDE_EW])
  1557. X    vul_string = "E-W";
  1558. X  else
  1559. X    vul_string = "NONE";
  1560. X
  1561. X  sprintf (buf, "%s BOARD %d", b->source, b->serial_no);
  1562. X  print (1, 78 - strlen(buf), buf);
  1563. X
  1564. X  switch (b->scoring_mode) {
  1565. X  case RUBBER_SCORING:
  1566. X    print (1, 1, "RUBBER BRIDGE");
  1567. X    break;
  1568. X  case DUPLICATE_SCORING:
  1569. X    print (1, 1, "DUPLICATE BRIDGE");
  1570. X    break;
  1571. X  case MP_SCORING:
  1572. X    print (1, 1, "MATCH POINTS");
  1573. X    break;
  1574. X  case IMP_SCORING:
  1575. X    print (1, 1, "INTL MATCH POINTS");
  1576. X    break;
  1577. X  }
  1578. X
  1579. X  sprintf (buf, "DEALER %s, VUL %s", seat_names[b->dealer], vul_string);
  1580. X  print (2, 1, buf);
  1581. X
  1582. X  sprintf (buf, "%5s %21s %-8s %-2s %6s %6s %6s %6s", " ", " ",
  1583. X       "CONTRACT", "BY", "RESULT", "SCORE", "IMPS", "MPS");
  1584. X  print (4, 1, buf);
  1585. X
  1586. X  while ((line < 15) && (Next_page_of_scores != NULL)) {
  1587. X    Display_Score_Record (b, Next_page_of_scores, line);
  1588. X    line += 3;
  1589. X    Next_page_of_scores = Next_page_of_scores->next;
  1590. X  }
  1591. X
  1592. X}
  1593. X
  1594. Xvoid Display_First_Page_of_Scores (b)
  1595. X     Board *b;
  1596. X/* Initiales the scoring display and displays the first page of results from
  1597. X * board b. 
  1598. X */
  1599. X{
  1600. X  if ((b->play_records == NULL) || (b->play_records->next == NULL)) {
  1601. X    Next_page_of_scores = Current_page_of_scores = NULL;
  1602. X    return;
  1603. X  }
  1604. X
  1605. X  Board_for_display = b;
  1606. X  Set_Display_Mode (SCORING_DISPLAY);
  1607. X  Set_Input_Mode (TALK_INPUT);
  1608. X
  1609. X  Display_Page_of_Scores (b->play_records);
  1610. X}
  1611. X
  1612. Xint More_Scores_to_Display ()
  1613. X/* int More_Scores_to_Display (void); */
  1614. X/* Returns true if not all of the results have been displayed from the
  1615. X * board which is currently being displayed. 
  1616. X */
  1617. X{
  1618. X  return (Next_page_of_scores != NULL);
  1619. X}
  1620. X
  1621. Xvoid Display_More_Scores ()
  1622. X/* void Display_More_Scores (void); */
  1623. X/* Displays the next page of scores for the board b. */
  1624. X{
  1625. X  Display_Page_of_Scores (Next_page_of_scores);
  1626. X}
  1627. X
  1628. X
  1629. X
  1630. Xstatic void Save_Status_Message (message)
  1631. X     char *message;
  1632. X/* Saves the given message into the status display buffer at the
  1633. X   current level of locking. */
  1634. X{
  1635. X  int i;
  1636. X
  1637. X  for (i = 0; (i < WIDTH(status)) && (message[i] != '\0'); i++)
  1638. X    status_buf[status_display_level][i] = message[i];
  1639. X  status_buf[status_display_level][i] = '\0';
  1640. X}
  1641. X
  1642. Xvoid Status (message)
  1643. X     char *message;
  1644. X{
  1645. X  if (status_display_level > 0) {
  1646. X    Moderator_Comment (message);
  1647. X    return;
  1648. X  }
  1649. X
  1650. X  Clear_Status ();
  1651. X  Save_Status_Message (message);
  1652. X  Refresh_Status_Display ();
  1653. X}
  1654. Xvoid Clear_Status ()
  1655. X{
  1656. X  if (status_display_level > 0)
  1657. X    return;
  1658. X
  1659. X  clear_screen_area (status_loc, XMIN(status), 1, WIDTH(status));
  1660. X  status_buf [0][0] = '\0';
  1661. X}
  1662. X
  1663. Xvoid Lock_Status (message)
  1664. X     char *message;
  1665. X/* Locks the status display.  This prevents the current message from being
  1666. X   erased from the display.  If a new request to Status is made, that
  1667. X   message is displayed as a moderator comment instead.
  1668. X*/
  1669. X{
  1670. X  status_display_level += 1;
  1671. X  Save_Status_Message (message);
  1672. X  Refresh_Status_Display ();
  1673. X}
  1674. X
  1675. Xvoid Unlock_Status ()
  1676. X/* Unlocks the status display. */
  1677. X{
  1678. X  if (status_display_level > 0)
  1679. X    status_display_level -= 1;
  1680. X  Refresh_Status_Display ();
  1681. X}
  1682. X
  1683. Xvoid Reset_Status ()
  1684. X/* Resets the status display. */
  1685. X{
  1686. X  status_display_level = 0;
  1687. X  Clear_Status ();
  1688. X}
  1689. X
  1690. Xvoid Refresh_Status_Display ()
  1691. X{
  1692. X  clear_screen_area (status_loc, XMIN(status), 1, WIDTH(status));
  1693. X  print (status_loc, XMIN(status), status_buf[status_display_level]);
  1694. X  set_cursor 
  1695. X    (status_loc, XMIN(status) + strlen(status_buf[status_display_level]) + 1);
  1696. X}
  1697. X
  1698. X/* The bottom part of the screen is used for the exchange of comments
  1699. X   between the players.  The following procedures are used for managing
  1700. X   this part of the display. */
  1701. Xstatic void blank_out_comment (c)
  1702. X     comment_line c;
  1703. X{
  1704. X  int i;
  1705. X  for (i = 0; i < COMMENT_LENGTH-1; i++) c[i] = ' ';
  1706. X  c[COMMENT_LENGTH-1] = '\0';
  1707. X}
  1708. Xstatic void copy_string_to_comment (c, s)
  1709. X     comment_line c; char *s;
  1710. X{
  1711. X  int i;
  1712. X  blank_out_comment(c);
  1713. X  i = 0;
  1714. X  while ((s[i] != '\0') && (i < COMMENT_LENGTH-1)) {
  1715. X    c[i] = s[i]; 
  1716. X    i++; 
  1717. X  }
  1718. X}
  1719. Xstatic void scroll_player_comments ()
  1720. X{
  1721. X  int i;
  1722. X
  1723. X  for (i = 0; i < playing_screen_talk_size-1; i++)
  1724. X    bcopy (playing_screen_comments[i+1], playing_screen_comments[i], 
  1725. X       sizeof(comment_line));
  1726. X  blank_out_comment (playing_screen_comments[playing_screen_talk_size-1]);
  1727. X}
  1728. X
  1729. Xvoid Select_Conversation_Mode ()
  1730. X{
  1731. X  talk_start = playing_screen_talk_start;
  1732. X  talk_end   = playing_screen_talk_end;
  1733. X  talk_size  = playing_screen_talk_size;
  1734. X  player_comments = playing_screen_comments;
  1735. X}
  1736. X
  1737. Xvoid Select_Talk_Mode ()
  1738. X{
  1739. X  talk_start = full_screen_talk_start;
  1740. X  talk_end   = full_screen_talk_end;
  1741. X  talk_size  = full_screen_talk_size;
  1742. X  player_comments = full_screen_comments;
  1743. X}
  1744. X
  1745. Xvoid Refresh_Player_Comments ()
  1746. X{
  1747. X  int i;
  1748. X
  1749. X  if (comments_suspended)
  1750. X    return;
  1751. X
  1752. X  for (i = 0; i < talk_size; i++)
  1753. X    print (talk_start+i, 2, player_comments[i]);
  1754. X}
  1755. X
  1756. Xvoid Clear_Comment_Display ()
  1757. X{
  1758. X  int i;
  1759. X
  1760. X  for (i = 0; i < full_screen_talk_size; i++)
  1761. X    blank_out_comment (full_screen_comments + i);
  1762. X  for (i = 0; i < playing_screen_talk_size; i++)
  1763. X    blank_out_comment (playing_screen_comments + i);
  1764. X
  1765. X  full_screen_cursor = 0;
  1766. X  Refresh_Player_Comments ();
  1767. X}
  1768. Xvoid Initialize_Player_Comments ()
  1769. X{
  1770. X  int i, m, n;
  1771. X  
  1772. X  full_screen_talk_end = terminal_lines - 3;
  1773. X  playing_screen_talk_end = terminal_lines;
  1774. X  
  1775. X  n = full_screen_talk_end - full_screen_talk_start + 1;
  1776. X  m = playing_screen_talk_end - playing_screen_talk_start + 1;
  1777. X  if (n <= 0)
  1778. X    n = 1;
  1779. X  else if (m <= 0)
  1780. X    m = 1;
  1781. X  
  1782. X  full_screen_comments = (comment_line *) 
  1783. X    malloc (n * sizeof(comment_line));
  1784. X  
  1785. X  playing_screen_comments = (comment_line *)
  1786. X    malloc (m * sizeof(comment_line));
  1787. X  
  1788. X  for (i = 0; i < n; i++)
  1789. X    blank_out_comment (full_screen_comments[i]);
  1790. X  for (i = 0; i < m; i++)
  1791. X    blank_out_comment (playing_screen_comments[i]);
  1792. X  
  1793. X  full_screen_cursor = 0;
  1794. X  full_screen_talk_size = n;
  1795. X  playing_screen_talk_size = m;
  1796. X
  1797. X  if (display_mode == TALK_DISPLAY)
  1798. X    Select_Talk_Mode ();
  1799. X  else
  1800. X    Select_Conversation_Mode ();
  1801. X}
  1802. X
  1803. Xvoid Reinitialize_Player_Comments ()
  1804. X{
  1805. X  Initialize_Player_Comments ();
  1806. X}
  1807. X
  1808. Xvoid Display_Player_Comment (comment_level, player_name, comment)
  1809. X     int comment_level; char *player_name, *comment;
  1810. X{
  1811. X  char message_buf [200];
  1812. X  char level_id;
  1813. X  
  1814. X  switch (comment_level) {
  1815. X  case COMMENT_PRIVATE: level_id = '-'; break;
  1816. X  case COMMENT_FORMAL:  level_id = '='; break;
  1817. X  case COMMENT_PUBLIC:  level_id = ':'; break;
  1818. X  default:              level_id = '*';
  1819. X  }
  1820. X  
  1821. X  sprintf (message_buf, "%s%c %s", player_name, level_id, comment);
  1822. X  
  1823. X  copy_string_to_comment (full_screen_comments[full_screen_cursor], 
  1824. X              message_buf);
  1825. X  if (full_screen_cursor < full_screen_talk_size - 1)
  1826. X    full_screen_cursor++;
  1827. X  else
  1828. X    full_screen_cursor = 0;
  1829. X  blank_out_comment (full_screen_comments[full_screen_cursor]);
  1830. X
  1831. X  scroll_player_comments ();
  1832. X  copy_string_to_comment 
  1833. X    (playing_screen_comments[playing_screen_talk_size-1], message_buf);
  1834. X
  1835. X  Refresh_Player_Comments ();
  1836. X}
  1837. X
  1838. Xvoid Moderator_Comment (msg)
  1839. X     char *msg;
  1840. X{
  1841. X  Display_Player_Comment (COMMENT_PUBLIC, "MODERATOR", msg);
  1842. X}
  1843. X
  1844. Xvoid Network_Comment (msg)
  1845. X     char *msg;
  1846. X{
  1847. X  Display_Player_Comment (COMMENT_PRIVATE, "NETWORK", msg);
  1848. X}
  1849. X
  1850. Xvoid Suspend_Comment_Display ()
  1851. X{
  1852. X  comments_suspended = 1;
  1853. X}
  1854. X
  1855. Xvoid Continue_Comment_Display ()
  1856. X{
  1857. X  comments_suspended = 0;
  1858. X}
  1859. X
  1860. Xvoid Begin_full_screen_talk_mode ()
  1861. X{
  1862. X  int i;
  1863. X
  1864. X  Select_Talk_Mode ();
  1865. X  
  1866. X  for (i = 0; i <= XMAX(converse); i++) line_buf[i] = '-';
  1867. X  line_buf[XMAX(converse)+1] = '\0';
  1868. X  print (full_screen_talk_start-1, 1, line_buf);
  1869. X  line_buf[72] = '+';
  1870. X  print (full_screen_talk_end+1, 1, line_buf);
  1871. X  for (i = 1; i < XMAX(converse); i++) line_buf[i] = ' ';
  1872. X  line_buf[0] = line_buf[XMAX(converse)] = '|';
  1873. X  for (i = full_screen_talk_start; i <= full_screen_talk_end; i++)
  1874. X    print (i, 1, line_buf);
  1875. X  
  1876. X  Refresh_Player_Comments ();
  1877. X  
  1878. X  /* setup the talk buffer: */
  1879. X  
  1880. X  print (terminal_lines-1, 1, "TALK");
  1881. X  status_loc = terminal_lines;
  1882. X}
  1883. X
  1884. Xvoid End_full_screen_talk_mode ()
  1885. X{
  1886. X  Select_Conversation_Mode ();
  1887. X  status_loc = YMIN(status);
  1888. X  Refresh_Display ();
  1889. X}
  1890. END_OF_FILE
  1891. if test 34086 -ne `wc -c <'display.c'`; then
  1892.     echo shar: \"'display.c'\" unpacked with wrong size!
  1893. fi
  1894. # end of 'display.c'
  1895. fi
  1896. echo shar: End of archive 6 \(of 14\).
  1897. cp /dev/null ark6isdone
  1898. MISSING=""
  1899. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1900.     if test ! -f ark${I}isdone ; then
  1901.     MISSING="${MISSING} ${I}"
  1902.     fi
  1903. done
  1904. if test "${MISSING}" = "" ; then
  1905.     echo You have unpacked all 14 archives.
  1906.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1907. else
  1908.     echo You still need to unpack the following archives:
  1909.     echo "        " ${MISSING}
  1910. fi
  1911. ##  End of shell archive.
  1912. exit 0
  1913.