home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!spool.mu.edu!uwm.edu!ogicse!zephyr.ens.tek.com!master!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v13i019: okbridge - computer-mediated bridge game, Part04/07
- Message-ID: <2278@masterCNA.TEK.COM>
- Date: 10 Jan 92 16:44:51 GMT
- Article-I.D.: masterCN.2278
- Sender: news@masterCNA.TEK.COM
- Lines: 1153
- Approved: billr@saab.CNA.TEK.COM
-
- Submitted-by: mclegg@cs.UCSD.EDU (Matthew Clegg)
- Posting-number: Volume 13, Issue 19
- Archive-name: okbridge/Part04
- Environment: BSD-derived Unix, curses, sockets
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 4 (of 7)."
- # Contents: input.c.ab
- # Wrapped by billr@saab on Fri Jan 10 08:31:28 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'input.c.ab' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'input.c.ab'\"
- else
- echo shar: Extracting \"'input.c.ab'\" \(31325 characters\)
- sed "s/^X//" >'input.c.ab' <<'END_OF_FILE'
- Xstatic int Reserved_message (message)
- X char *message;
- X/* Compares the given message to the list of card and bid names. If a
- X match is found, then returns true. Otherwise, returns false.
- X*/
- X{
- X char compare_buff[100], *ch;
- X int i;
- X
- X if (!strlen(message))
- X return (1);
- X
- X strcpy (compare_buff, message);
- X ch = compare_buff;
- X for (ch = compare_buff; *ch != '\0'; ch++)
- X *ch = toupper(*ch);
- X
- X for (i=0; i < 52; i++)
- X if (!strcmp(card_names[i], compare_buff))
- X return (1);
- X
- X for (i=0; i < 38; i++)
- X if (!strcmp(bid_names[i], compare_buff))
- X return (1);
- X
- X return (0);
- X
- X};
- X
- Xstatic load_email_file (filename)
- X char *filename;
- X/* Attempts to read a sequence of deals from the email duplicate file
- X . with name filename.
- X */
- X{
- X char msg_buf [80];
- X
- X total_no_deals = current_deal_no = 0;
- X current_board = NULL;
- X if (email_record != NULL)
- X Free_Email_Duplicate_Struct (email_record);
- X email_record = NULL;
- X current_deal_no =
- X Read_Email_Duplicate_File (filename, &email_record);
- X if (current_deal_no) {
- X if (email_record != NULL)
- X Free_Email_Duplicate_Struct
- X (email_record);
- X email_record = NULL;
- X if (current_deal_no > 0) {
- X sprintf (msg_buf, "%s %d: %s", "FORMAT ERROR NEAR LINE",
- X codefile_line_no, email_error_message);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X } else {
- X sprintf (msg_buf, "%s %s: %s", "ERROR IN READING", filename,
- X sys_errlist[errno]);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X };
- X email_record = New_Email_Duplicate_Struct ();
- X current_deal_no = 0;
- X replaying_mode = 0;
- X } else {
- X total_no_deals = email_record->nboards;
- X current_board = email_record->board_list;
- X replaying_mode = 1;
- X sprintf (msg_buf, "LOADED %d BOARDS FROM %s.",
- X total_no_deals, filename);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X };
- X ns_pair_no = Add_Email_Pair (email_record,
- X player_names[PLAYER_NORTH],
- X player_names[PLAYER_SOUTH]);
- X ew_pair_no = Add_Email_Pair (email_record,
- X player_names[PLAYER_EAST],
- X player_names[PLAYER_WEST]);
- X};
- X
- Xstatic void save_email_file (filename)
- X char *filename;
- X{
- X int error_flag;
- X char msg_buf[80];
- X
- X error_flag = Write_Email_Duplicate_File (filename, 1, email_record);
- X if (error_flag) {
- X sprintf (msg_buf, "%s %s: %s", "ERROR IN WRITING", filename,
- X sys_errlist[errno]);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X } else {
- X sprintf (msg_buf, "WROTE %d %s %s.",
- X email_record->nboards, "ENCODED BOARDS TO", filename);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X sprintf (msg_buf, "%s.plain", filename);
- X error_flag = Write_Email_Duplicate_File (msg_buf, 0, email_record);
- X sprintf (filename,"%s", msg_buf);
- X if (error_flag) {
- X sprintf (msg_buf, "%s %s: %s",
- X "ERROR IN WRITING", filename, sys_errlist[errno]);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X error_flag = 0;
- X } else {
- X sprintf (msg_buf, "WROTE %d %s %s.",
- X email_record->nboards, "UNENCODED BOARDS TO", filename);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X };
- X };
- X};
- X
- Xstatic process_player_command (pc)
- X player_command pc;
- X/* Determines whether the player command pc should be handled internally
- X . by the input module, or whether it should be passed upwards. If it will
- X . be handled internally, then performs the appropriate action. If it will
- X . be passed upwards, then places it in an appropriate queue to be handled
- X . later.
- X */
- X{
- X char msg_buf[100], *word, *filename;
- X int mils; /* milliseconds elapsed between ping and echo */
- X int error_flag;
- X struct timeval ping_end;
- X
- X if ((pc->player_no == local_player) && disabled(pc->command)) {
- X Display_Status ("THIS COMMAND CANNOT BE USED NOW");
- X return;
- X };
- X/*
- X if ((pc->command != CMD_HELLO) && !players_here[pc->player_no])
- X return;
- X*/
- X
- X switch (pc->command) {
- X case CMD_ERROR:
- X break; /* do nothing for erroneous commands. */
- X case CMD_VULN:
- X enqueue_command (pc);
- X break;
- X case CMD_RDEAL:
- X enqueue_command (pc);
- X if ((pc->player_no != local_player) &&
- X (game_mode != DEALING_MODE)) {
- X Display_Player_Comment ("MODERATOR",
- X "THE CARDS HAVE NOW BEEN DEALT.");
- X };
- X break;
- X case CMD_BID:
- X enqueue_command (pc);
- X break;
- X case CMD_PLAY:
- X enqueue_command (pc);
- X break;
- X case CMD_FINISH:
- X enqueue_command (pc);
- X break;
- X case CMD_HELLO:
- X if (players_here[pc->player_no]) {
- X sprintf (msg_buf,
- X "THERE ARE TWO PEOPLE CLAIMING THE SEAT OF %s",
- X local_player_names [pc->player_no]);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X send_message_talk (msg_buf);
- X Terminate_Program ("PROGRAM TERMINATING");
- X };
- X if (pc->player_no == local_player) {
- X /* The following statement should never
- X * be executed: */
- X break;
- X } else {
- X send_message_ack ();
- X player_names[pc->player_no] =
- X strdup(pc->data.version_name +
- X VERSION_LENGTH);
- X if (strlen(player_names[pc->player_no]) > 8)
- X player_names[pc->player_no][8] = '\0';
- X error_flag = verify_compatibility
- X (pc->player_no, pc->data.version_name);
- X if (!error_flag) {
- X sprintf (msg_buf,
- X "%s HAS JOINED THE GAME AS %s",
- X player_names[pc->player_no],
- X local_player_names[pc->player_no]);
- X Display_Player_Comment ("MODERATOR",
- X msg_buf);
- X if (ring_my_bell) ring_bell ();
- X players_here [pc->player_no] = 1;
- X }
- X };
- X#ifdef TWOPLAYER_MODE
- X players_here [player_partner[pc->player_no]] = 1;
- X#endif
- X break;
- X case CMD_ACK:
- X verify_compatibility (pc->player_no,
- X pc->data.version_name);
- X player_names[pc->player_no] =
- X strdup(pc->data.version_name+VERSION_LENGTH);
- X if (strlen(player_names[pc->player_no]) > 8)
- X player_names[pc->player_no][8] = '\0';
- X if (pc->player_no == local_player)
- X send_message_ack ();
- X/*
- X else if (game_mode != STARTUP_MODE) {
- X sprintf (msg_buf,
- X "ACKNOWLEDGMENT RECEIVED FROM %s",
- X player_names[pc->player_no]);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X }
- X*/
- X else if (!players_here[pc->player_no]) {
- X sprintf (msg_buf,
- X "%s HAS JOINED THE GAME AS %s",
- X player_names[pc->player_no],
- X local_player_names[pc->player_no]);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X };
- X players_here [pc->player_no] = 1;
- X#ifdef TWOPLAYER_MODE
- X players_here [player_partner[pc->player_no]] = 1;
- X#endif
- X break;
- X case CMD_TALK:
- X if (pc->player_no == local_player) {
- X if (Reserved_message (pc->data.message))
- X break;
- X send_message_talk (pc->data.message);
- X };
- X Display_Player_Comment (player_names[pc->player_no],
- X pc->data.message);
- X players_here [pc->player_no] = 1;
- X break;
- X case CMD_COMMENT:
- X Display_Player_Comment ("MODERATOR", pc->data.message);
- X break;
- X case CMD_QUIT:
- X if (pc->player_no == local_player)
- X Quit_program ();
- X else {
- X sprintf (msg_buf, "%s HAS QUIT.",
- X player_names[pc->player_no]);
- X Display_Player_Comment ("MODERATOR",
- X msg_buf);
- X if (game_mode == STARTUP_MODE)
- X players_here[pc->player_no] = 0;
- X Close_Network_Connection
- X (local_player_names[pc->player_no]);
- X };
- X/* soft_abort (); */
- X break;
- X case CMD_HELP:
- X display_help (pc->data.topic);
- X Refresh_Display ();
- X break;
- X case CMD_BELL:
- X if (pc->data.bell == 0) ring_my_bell = 0;
- X if (pc->data.bell == 1) ring_my_bell = 1;
- X if (ring_my_bell) word = "ON";
- X else word = "OFF";
- X sprintf (msg_buf, "THE BELL IS NOW %s", word);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X if (ring_my_bell) ring_bell ();
- X break;
- X case CMD_DEFAULT:
- X if (pc->data.defaalt == 0) default_plays = 0;
- X if (pc->data.defaalt == 1) default_plays = 1;
- X if (default_plays) word = "ON";
- X else word = "OFF";
- X sprintf (msg_buf, "DEFAULT INPUT MODE IS NOW %s",
- X word);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X break;
- X case CMD_REVIEW:
- X Review_Bidding ();
- X break;
- X case CMD_PROMPT:
- X if (pc->data.prompt == 0) prompt_dummy = 0;
- X if (pc->data.prompt == 1) prompt_dummy = 1;
- X if (prompt_dummy) word = "WILL";
- X else word = "WILL NOT";
- X sprintf (msg_buf,
- X "THE DUMMY %s BE PROMPTED AFTER EACH TRICK",
- X word);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X break;
- X case CMD_PING:
- X if (pc->player_no == local_player) {
- X gettimeofday (&ping_start, NULL);
- X send_message_ping ();
- X } else
- X send_message_echo (pc->player_no);
- X break;
- X case CMD_ECHO:
- X players_here[pc->player_no] = 1;
- X if (pc->data.ping_source == local_player) {
- X gettimeofday (&ping_end, NULL);
- X mils = (ping_end.tv_sec - ping_start.tv_sec)
- X * 1000;
- X mils += ping_end.tv_usec / 1000;
- X mils -= ping_start.tv_usec / 1000;
- X sprintf (msg_buf,
- X "ECHO RECEIVED FROM %-10s IN %7.2f SECONDS",
- X player_names[pc->player_no],
- X ((float) mils) * 0.001);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X };
- X break;
- X case CMD_CLAIM:
- X if (pc->player_no == local_player)
- X process_claim_offer (pc->data.tricks);
- X else if (local_player != dummy)
- X process_claim_response (pc->data.tricks);
- X break;
- X case CMD_RESP:
- X claim_responses++;
- X if (!pc->data.response) {
- X/*
- X sprintf (msg_buf,
- X "THE CLAIM OFFER WAS DECLINED BY %s",
- X player_names[pc->player_no]);
- X*/
- X if (!claim_rejected) {
- X sprintf (msg_buf,
- X "THE CLAIM OFFER WAS DECLINED.");
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X };
- X claim_rejected = 1;
- X };
- X break;
- X case CMD_SCORE:
- X scoring_mode_known = 1;
- X scoring_mode = pc->data.scoring;
- X switch (scoring_mode) {
- X case RUBBER_SCORING:
- X Display_Player_Comment ("MODERATOR",
- X "WE ARE PLAYING RUBBER BRIDGE.");
- X break;
- X case CHICAGO_SCORING:
- X Display_Player_Comment ("MODERATOR",
- X "WE ARE PLAYING CHICAGO BRIDGE.");
- X break;
- X case DUPLICATE_SCORING:
- X Display_Player_Comment ("MODERATOR",
- X "WE ARE PLAYING DUPLICATE BRIDGE.");
- X break;
- X case EMAIL_SCORING:
- X Display_Player_Comment ("MODERATOR",
- X "WE ARE PLAYING EMAIL DUPLICATE BRIDGE.");
- X break;
- X case IMP_SCORING:
- X Display_Player_Comment ("MODERATOR",
- X "WE ARE PLAYING IMP BRIDGE.");
- X break;
- X };
- X break;
- X case CMD_LOG:
- X if (pc->data.filename[0] == '\0') {
- X if (logfile == NULL)
- X Display_Player_Comment ("MODERATOR",
- X "THERE IS NO OPEN LOGFILE.");
- X else {
- X fclose (logfile);
- X logfile = NULL;
- X Display_Player_Comment ("MODERATOR",
- X "THE LOG FILE HAS BEEN CLOSED.");
- X };
- X } else {
- X if (logfile != NULL) fclose (logfile);
- X if (pc->data.filename[0] == '+') {
- X filename = pc->data.filename + 1;
- X logfile = fopen (filename, "a");
- X } else {
- X filename = pc->data.filename;
- X logfile = fopen (filename, "w");
- X };
- X if (logfile == NULL) {
- X sprintf (msg_buf, "%s ERROR OPENING %s",
- X sys_errlist[errno], filename);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X } else {
- X sprintf (msg_buf, "NOW LOGGING TO %s",
- X filename);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X };
- X };
- X break;
- X case CMD_DEAL:
- X total_no_deals = pc->data.nhands;
- X current_deal_no = 0;
- X if (email_record != NULL)
- X Free_Email_Duplicate_Struct (email_record);
- X email_record = New_Email_Duplicate_Struct ();
- X ns_pair_no = Add_Email_Pair (email_record,
- X player_names[PLAYER_NORTH],
- X player_names[PLAYER_SOUTH]);
- X ew_pair_no = Add_Email_Pair (email_record,
- X player_names[PLAYER_EAST],
- X player_names[PLAYER_WEST]);
- X if (total_no_deals < 0)
- X Display_Player_Comment ("MODERATOR",
- X "ENTERING CONTINUOUS DEAL MODE.");
- X else {
- X sprintf (msg_buf, "%s %d DEALS.",
- X "BEGINNING A SEQUENCE OF",
- X total_no_deals);
- X Display_Player_Comment ("MODERATOR", msg_buf);
- X };
- X replaying_mode = 0;
- X current_board = NULL;
- X break;
- X case CMD_LOAD:
- X load_email_file (pc->data.filename);
- X break;
- X case CMD_SAVE:
- X save_email_file (pc->data.filename);
- X break;
- X case CMD_REPLAY:
- X load_email_file (pc->data.filename);
- X if (replaying_mode)
- X autosave_file = strdup (pc->data.filename);
- X break;
- X default:
- X sprintf (msg_buf, "PLAYER %d, CODE %d\n",
- X pc->player_no, pc->command);
- X Display_Player_Comment ("INTERNAL ERROR!", msg_buf);
- X };
- X};
- X
- Xstatic player_input (rmt_player, ib, default_command)
- X int rmt_player; input_buffer ib; char *default_command;
- X/* This procedure monitors the network and the keyboard simultaneously,
- X . waiting for a command to arrive. The local player is free to type at the
- X . keyboard, placing characters into the buffer ib. When he presses
- X . enter, a command is issued. By default, the command which is issued
- X . is obtained by concatenating the player's input to the string given
- X . in default command. However, if the player's command begins with a
- X . slash '/', then it is interpreted directly as the command. The exit
- X . condition for this procedure is determined by the input value of player.
- X . If player = -1, then the procedure exits as soon as any kind of message
- X . is received. If player is in the range 0..3, then the procedure exits
- X . only when a play is received from the corresponding player. No other
- X . values for player are valid.
- X */
- X{
- X struct player_command_struct pcs;
- X char command_buf[100];
- X int polling;
- X
- X
- X/* Clear_Status_Display(); */
- X print (ib->row, 1, default_command);
- X update_input_buffer (ib, '\0');
- X if (rmt_player < 0)
- X polling = 1;
- X else if (rmt_player < 4)
- X polling = !command_available(rmt_player);
- X polling = 1;
- X while (polling) {
- X if (message_available()) {
- X receive_player_command (&pcs);
- X if (pcs.player_no >= 0) {
- X process_player_command (&pcs);
- X polling = 0;
- X };
- X };
- X if (char_avail()) {
- X if (update_input_buffer(ib, input_char())) {
- X Clear_Status_Display ();
- X pcs.player_no = local_player;
- X if (ib->buf[0] == '/')
- X ps_copy (command_string, ib->buf+1);
- X else {
- X sprintf (command_buf, "%s %s",
- X default_command, ib->buf);
- X ps_copy (command_string, command_buf);
- X };
- X clear_input_buffer (ib);
- X parse_player_command (command_string, &pcs);
- X if (pcs.command == CMD_ERROR)
- X Display_Status (parsing_errmsg);
- X else {
- X process_player_command (&pcs);
- X polling = 0;
- X };
- X update_input_buffer (ib, '\0');
- X };
- X };
- X if ((3 >= rmt_player) && (rmt_player >= 0))
- X polling = !command_available(rmt_player);
- X };
- X
- X};
- X
- Xstatic input_remote_play (rmt_player, play, pc)
- X int rmt_player; long play; player_command pc;
- X/* As input, receives the index of a remote player as rmt_player and
- X . a bit string of allowable plays as play. Waits for the specified
- X . player to make one of the plays listed in the bit string play.
- X . If we receive any other type of play, then an error message is
- X . generated. Otherwise, creates the play into the structure pc.
- X */
- X{
- X char error_message [100];
- X int waiting;
- X
- X waiting = 1;
- X while (waiting) {
- X if (QUEUE_EMPTY(rmt_player))
- X player_input (rmt_player, talk_buffer, "TALK ");
- X dequeue_command (rmt_player, pc);
- X if (pc != NULL) {
- X if (pc->command & play)
- X waiting = 0;
- X else {
- X sprintf (error_message,
- X "EXPECTING PLAY %ld FROM %d; RECEIVED PLAY %ld",
- X play, rmt_player, pc->command);
- X Display_Player_Comment ("NETWORK ERROR",
- X error_message);
- X };
- X };
- X };
- X};
- X
- XInitialize_Input_Buffers ()
- X/* Establishes and initializes the buffers that are used for reading
- X . input from the terminal.
- X */
- X{
- X talk_buffer=(input_buffer) malloc (sizeof(struct input_buffer_struct));
- X play_buffer=(input_buffer) malloc (sizeof(struct input_buffer_struct));
- X ask_buffer =(input_buffer) malloc (sizeof(struct input_buffer_struct));
- X
- X talk_buffer->row = TALK_ROW;
- X talk_buffer->col = TALK_COL + 6;
- X talk_buffer->length = TALK_LENGTH - 6;
- X talk_buffer->pos = 0;
- X talk_buffer->buf[0] = '\0';
- X
- X play_buffer->row = PLAY_ROW;
- X play_buffer->col = PLAY_COL + 6;
- X play_buffer->length = PLAY_LENGTH - 6;
- X play_buffer->pos = 0;
- X play_buffer->buf[0] = '\0';
- X
- X ask_buffer->row = TALK_ROW + 1;
- X ask_buffer->col = 0;
- X ask_buffer->length = 5;
- X ask_buffer->pos = 0;
- X ask_buffer->buf[0] = '\0';
- X
- X email_record = NULL;
- X};
- X
- XInitialize_Input ()
- X/* Initializes the higher-level state of the network connections,
- X . including doing the initial handshaking with the other players.
- X */
- X{
- X int i, wait;
- X char msg_buf[80];
- X
- X initialize_command_queue();
- X
- X command_string = ps_alloc (127);
- X command_disabled = 0;
- X disable(CMD_RDEAL);
- X disable(CMD_BID);
- X disable(CMD_PLAY);
- X disable(CMD_FINISH);
- X disable(CMD_HELLO);
- X disable(CMD_ACK);
- X disable(CMD_ECHO);
- X disable(CMD_RESP);
- X disable(CMD_SCORE);
- X disable(CMD_CLAIM);
- X disable(CMD_DEAL);
- X disable(CMD_LOAD);
- X enable(CMD_SAVE);
- X
- X#ifdef LOOPBACK_MODE
- X for (i = 0; i < 4; i++) players_here[i] = 1; /* DBG */
- X wait = 0;
- X#else
- X for (i = 0; i < 4; i++) players_here[i] = 0;
- X players_here[local_player] = 1;
- X wait = 1;
- X#ifdef TWOPLAYER_MODE
- X players_here[player_partner[local_player]] = 1;
- X#endif
- X#endif
- X
- X /* First, wait for the other players to arrive: */
- X send_message_hello ();
- X while (wait) {
- X player_input (-1, talk_buffer, "TALK ");
- X wait = 0;
- X for (i = 0; i < 4; i++)
- X if (!players_here[i]) wait = 1;
- X };
- X
- X /* Now we reach an agreement about which scoring convention
- X will be used. In this implementation, north makes the decision
- X and the others follow this decision. */
- X if (local_player == PLAYER_NORTH)
- X send_message_score ();
- X else {
- X while (!scoring_mode_known)
- X player_input (-1, talk_buffer, "TALK ");
- X };
- X
- X /* Now that we have all of this information we can initialize the
- X email duplicate structures. Even though we may not be playing
- X email duplicate, we still record all of the hands in case one
- X of the players would like to save them.
- X */
- X email_record = New_Email_Duplicate_Struct ();
- X current_board = NULL;
- X ns_pair_no = Add_Email_Pair (email_record,
- X player_names[PLAYER_NORTH],
- X player_names[PLAYER_SOUTH]);
- X ew_pair_no = Add_Email_Pair (email_record,
- X player_names[PLAYER_EAST],
- X player_names[PLAYER_WEST]);
- X current_deal_no = total_no_deals = 0;
- X};
- X
- Xstatic shuffle_the_deck (cards)
- X deal cards;
- X/* Using the algorithm suggested by Douglas Foxvog. Thanks, Doug! */
- X{
- X int i, t, c;
- X deal shuffle;
- X
- X for (i = 0; i < 52; i++)
- X shuffle [i] = i;
- X for (i = 0; i < 51; i++) {
- X c = random (52 - i);
- X t = shuffle[i+c];
- X shuffle[i+c] = shuffle[i];
- X shuffle[i] = t;
- X };
- X for (i = 0; i < 52; i++)
- X cards[shuffle[i]] = (i % 4);
- X
- X};
- X
- Xstatic void Print_Continue_Message (saved_already)
- X int saved_already;
- X{
- X if ((total_no_deals == 0) && !replaying_mode) {
- X Display_Player_Comment ("MODERATOR",
- X "TO BEGIN PLAY, TYPE /DEAL [nhands] OR /LOAD filename.");
- X } else {
- X Display_Player_Comment ("MODERATOR",
- X "ALL BOARDS HAVE NOW BEEN PLAYED.");
- X if (!saved_already)
- X Display_Player_Comment ("MODERATOR",
- X "TYPE /SAVE filename TO SAVE THE RESULTS,");
- X Display_Player_Comment ("MODERATOR",
- X "THEN /DEAL [nhands] OR /LOAD filename TO CONTINUE PLAY.");
- X };
- X};
- X
- Xstatic int Email_Deal_Available ()
- X{
- X if (replaying_mode)
- X return (current_board != NULL);
- X else
- X return (current_deal_no != total_no_deals);
- X};
- X
- Xinput_hand (current_deal)
- X deal current_deal;
- X/* If this player is the dealer, then shuffles the deck and deals the
- X cards to everyone. Otherwise, waits for the dealer to tell what
- X the new shuffle is. Stores the new deal in current_deal.
- X*/
- X{
- X struct player_command_struct pcs;
- X int i, saved;
- X char message_buf[80];
- X
- X#ifdef LOOPBACK_MODE
- X int dealer;
- X dealer = local_player;
- X#endif
- X#ifdef TWOPLAYER_MODE
- X dealer = dealer % 2;
- X#endif
- X
- X if (current_board != NULL)
- X current_board = current_board -> next;
- X if ((scoring_mode == EMAIL_SCORING) && (local_player == PLAYER_NORTH)){
- X if (!Email_Deal_Available()) {
- X saved = 0;
- X if (autoload_file != NULL) {
- X load_email_file (autoload_file);
- X autoload_file = NULL;
- X if (!replaying_mode)
- X autosave_file = NULL;
- X } else if (autosave_file != NULL) {
- X save_email_file (autosave_file);
- X autosave_file = NULL;
- X saved = 1;
- X };
- X enable (CMD_DEAL);
- X enable (CMD_LOAD);
- X enable (CMD_REPLAY);
- X if (!Email_Deal_Available())
- X Print_Continue_Message (saved);
- X while (!Email_Deal_Available ())
- X player_input (-1, talk_buffer, "TALK ");
- X disable (CMD_DEAL);
- X disable (CMD_LOAD);
- X disable (CMD_REPLAY);
- X };
- X if (replaying_mode) {
- X for (i = 0; i < 52; i++)
- X current_deal[i] = current_board->deal[i];
- X vulnerable[SIDE_NS] = current_board->ns_vulnerable;
- X vulnerable[SIDE_EW] = current_board->ew_vulnerable;
- X dealer = current_board->dealer;
- X } else {
- X shuffle_the_deck (current_deal);
- X current_board = Add_Email_Board (email_record,
- X current_deal);
- X current_board->ns_vulnerable = vulnerable[SIDE_NS];
- X current_board->ew_vulnerable = vulnerable[SIDE_EW];
- X current_board->dealer = dealer;
- X };
- X send_message_vuln (dealer, vulnerable[SIDE_NS],
- X vulnerable[SIDE_EW]);
- X send_message_rdeal (current_deal);
- X } else if (scoring_mode == EMAIL_SCORING) {
- X Display_Status ("WAITING FOR DEAL ... ");
- X input_remote_play (PLAYER_NORTH, CMD_VULN, &pcs);
- X vulnerable[SIDE_NS] =
- X (pcs.data.vulnerable >> SIDE_NS) & 1;
- X vulnerable[SIDE_EW] =
- X (pcs.data.vulnerable >> SIDE_EW) & 1;
- X dealer = pcs.data.vulnerable >> 2;
- X input_remote_play (PLAYER_NORTH, CMD_RDEAL, &pcs);
- X for (i = 0; i < 52; i++)
- X current_deal[i] = pcs.data.deal[i];
- X Clear_Status_Display ();
- X } else if (dealer == local_player) {
- X shuffle_the_deck (current_deal);
- X send_message_rdeal (current_deal);
- X } else {
- X Display_Status ("WAITING FOR DEAL ... ");
- X input_remote_play (dealer, CMD_RDEAL, &pcs);
- X for (i = 0; i < 52; i++)
- X current_deal[i] = pcs.data.deal[i];
- X Clear_Status_Display ();
- X };
- X if (current_board == NULL) {
- X current_board = Add_Email_Board (email_record, current_deal);
- X current_board->ns_vulnerable = vulnerable[SIDE_NS];
- X current_board->ew_vulnerable = vulnerable[SIDE_EW];
- X current_board->dealer = dealer;
- X };
- X current_deal_no += 1;
- X
- X};
- X
- Xstatic display_valid_bids (minimum_bid, double_ok, redouble_ok)
- X int minimum_bid, double_ok, redouble_ok;
- X{
- X char double_string[40], bid_string[80];
- X
- X if (double_ok)
- X sprintf (double_string, "; DOUBLE IS OK");
- X else if (redouble_ok)
- X sprintf (double_string, "; REDOUBLE IS OK");
- X else
- X double_string[0] = '\0';
- X
- X sprintf (bid_string, "ERROR -- MINIMUM BID IS %s%s",
- X bid_names[minimum_bid], double_string);
- X Display_Status (bid_string);
- X};
- X
- Xstatic display_valid_plays (current_hand)
- X hand current_hand;
- X{
- X char card_string [60], card_message[80];
- X int i, j, c;
- X
- X c = 0;
- X for (i = 0; i < 52; i++) {
- X if (current_hand[i]) {
- X for (j = 0; card_names[i][j] != '\0'; j++)
- X card_string[c++] = card_names[i][j];
- X card_string[c++] = ' ';
- X };
- X };
- X card_string[c++] = '\0';
- X sprintf (card_message,"ERROR -- VALID PLAYS ARE %s", card_string);
- X Display_Status (card_message);
- X};
- X
- Xstatic int legal_bid (bid, minimum, double_ok, redouble_ok)
- X int bid, double_ok, redouble_ok;
- X{
- X if (bid < 0)
- X return (0);
- X else if (bid == BID_PASS)
- X return (1);
- X else if (bid == BID_DOUBLE)
- X return (double_ok);
- X else if (bid == BID_REDOUBLE)
- X return (redouble_ok);
- X else
- X return (minimum <= bid);
- X};
- X
- Xint input_bid (rmt_player, minimum_bid, double_ok, redouble_ok)
- X int rmt_player, minimum_bid, double_ok, redouble_ok;
- X/* Waits for the indicated player to make a bid. If the player is the
- X * one sitting at this terminal, then prompts for the play from the screen.
- X * Otherwise, waits for the play to come from the network. Returns the
- X * index of the card played. The input parameter minimum gives the index
- X * of the minimum acceptable contract bid. The parameters double_ok and
- X * redouble_ok are boolean flags which indicate respectively if it is ok
- X * to bid double or redouble.
- X */
- X{
- X int no_bid, bid;
- X struct player_command_struct pcs;
- X
- X if (rmt_player == local_player) {
- X no_bid = 1;
- X enable (CMD_BID);
- X if (ring_my_bell) ring_bell ();
- X play_buffer->length = TALK_LENGTH - 6;
- X default_input = "PASS";
- X while (no_bid) {
- X player_input (local_player, play_buffer, "BID ");
- X dequeue_command (local_player, &pcs);
- X if (pcs.command != CMD_BID)
- X bid = -1;
- X else
- X bid = pcs.data.bid;
- X no_bid = !legal_bid(bid, minimum_bid, double_ok,
- X redouble_ok);
- X if (no_bid)
- X display_valid_bids (minimum_bid, double_ok,
- X redouble_ok);
- X };
- X play_buffer->length = PLAY_LENGTH - 6;
- X send_message_bid (bid);
- X disable (CMD_BID);
- X default_input = NULL;
- X } else {
- X input_remote_play (rmt_player, CMD_BID, &pcs);
- X bid = pcs.data.bid;
- X };
- X return (bid);
- X};
- X
- Xstatic int minimum_card (ch)
- X hand ch;
- X/* Returns the card of least rank held in the hand ch. */
- X{
- X int suit_order[4], suit, mc, i, j;
- X
- X for (i = j = 0; i < 4; i++)
- X if (i != trump_suit)
- X suit_order [j++] = i;
- X if (trump_suit < 4)
- X suit_order [3] = trump_suit;
- X
- X for (i = 0; i < 4; i++) {
- X suit = suit_order [i];
- X for (j = 0; j < 13; j++) {
- X mc = suit * 13 + j;
- X if (ch[mc]) return (mc);
- X };
- X };
- X return (-1);
- X};
- X
- Xstatic int no_cards (ch)
- X hand ch;
- X{
- X int i, n;
- X
- X for (i = n = 0; i < 52; i++)
- X if (ch[i]) n++;
- X return (n);
- X};
- X
- Xstatic set_default_suit (ch)
- X hand ch;
- X/* Examines the cards in the hand ch. If all of the cards are from a single
- X suit, then sets default_suit to that suit. Otherwise, sets default_suit
- X to -1.
- X*/
- X{
- X int i, d;
- X
- X d = default_suit = -1;
- X for (i = 0; i < 52; i++)
- X if (ch[i]) {
- X if (d == -1)
- X d = suit_of (i);
- X else if (d != suit_of(i))
- X return;
- X };
- X default_suit = d;
- X
- X};
- X
- Xint input_play (rmt_player, current_hand)
- X int rmt_player; hand current_hand;
- X/* Waits for the indicated player to play a card. If that player is the
- X * one sitting at the terminal, then prompts from the screen for the play.
- X * In this case, current_hand gives a list of the valid cards which may
- X * be played. If the indicated player is a remote player, then waits for
- X * the play to arrive through the network. If the return value is
- X * nonnegative, then it is the index of card played. If the return value
- X * is -k-1, then k specifies the number of additional tricks claimed
- X * by the contracting team.
- X */
- X{
- X int no_play, play;
- X struct player_command_struct pcs;
- X char *dp;
- X char temp_buffer[60];
- X
- X if (local_player == rmt_player) {
- X no_play = 1;
- X enable (CMD_PLAY);
- X if (local_player == declarer) enable (CMD_CLAIM);
- X if (ring_my_bell) ring_bell ();
- X default_input = card_names[minimum_card(current_hand)];
- X if (default_plays && (no_cards(current_hand) == 1)) {
- X for (dp = default_input; *dp != '\0'; dp++)
- X play_buffer->buf[play_buffer->pos++] = *dp;
- X play_buffer->buf[play_buffer->pos] = '\0';
- X play_buffer->defaulted = 1;
- X };
- X set_default_suit (current_hand);
- X while (no_play) {
- X player_input (local_player, play_buffer, "PLAY ");
- X dequeue_command (local_player, &pcs);
- X if (pcs.command == CMD_FINISH) {
- X play = -pcs.data.tricks - 1;
- X no_play = 0;
- X } else if (pcs.command == CMD_PLAY) {
- X play = pcs.data.card;
- X no_play = !current_hand[play];
- X if (!no_play)
- X send_message_play (play);
- X };
- X if (no_play)
- X display_valid_plays (current_hand);
- X };
- X default_input = NULL;
- X disable (CMD_PLAY);
- X disable (CMD_CLAIM);
- X } else {
- X input_remote_play (rmt_player, CMD_PLAY | CMD_FINISH, &pcs);
- X if (pcs.command == CMD_FINISH)
- X play = -pcs.data.tricks - 1;
- X else
- X play = pcs.data.card;
- X };
- X return (play);
- X};
- X
- Xinput_acknowledgment (line)
- X int line;
- X/* Displays the message "PRESS RETURN TO CONTINUE" on the given screen line,
- X * unless:
- X * line == -1, in which case the message is displayed on the
- X * status line, or
- X * line == -2, in which case no message is displayed,
- X * line == -3, in which case no message is displayed, and the
- X * program enters TALK mode, exiting when a RETURN is pressed
- X * on a blank line.
- X * Then waits for the user to press, RETURN.
- X */
- X{
- X int ch;
- X struct player_command_struct pcs;
- X
- X if (line == -1) {
- X Clear_Status_Display ();
- X Display_Status ("PRESS RETURN TO CONTINUE");
- X } else if (line >= 0) {
- X print (line, 1, "PRESS RETURN TO CONTINUE");
- X set_cursor (line, 1 + strlen("PRESS RETURN TO CONTINUE"));
- X };
- X
- X if (ring_my_bell) ring_bell ();
- X waiting_for_acknowledgment = 1;
- X while (waiting_for_acknowledgment) {
- X if (line == -3)
- X player_input (-1, talk_buffer, "TALK ");
- X else {
- X if (message_available()) {
- X receive_player_command (&pcs);
- X if (pcs.player_no >= 0)
- X process_player_command (&pcs);
- X };
- X if (char_avail()) {
- X ch = input_char ();
- X waiting_for_acknowledgment = (ch != '\012')
- X && (ch != '\015');
- X if (ch == '\022')
- X Refresh_Display ();
- X };
- X };
- X };
- X if (line != -3)
- X while (char_avail()) input_char ();
- X Clear_Status_Display ();
- X
- X};
- X
- Xinput_answer (question)
- X char *question;
- X/* Displays the question on the status line and waits for the
- X * local player to press 'y' or 'n'. Returns 1 if 'y' was entered
- X * and 0 if 'n' was entered.
- X */
- X{
- X int polling, ch;
- X struct player_command_struct pcs;
- X
- X waiting_for_acknowledgment = 0;
- X Display_Status (question);
- X ask_buffer->col = strlen(question) + 2;
- X clear_input_buffer (ask_buffer);
- X default_input = "NO";
- X if (ring_my_bell) ring_bell ();
- X for (polling = 1; polling;) {
- X if (message_available()) {
- X receive_player_command (&pcs);
- X if (pcs.player_no >= 0)
- X process_player_command (&pcs);
- X };
- X if (char_avail())
- X if(update_input_buffer (ask_buffer, input_char())) {
- X ch = ask_buffer->buf[0];
- X polling = ((ch != 'y') && (ch != 'Y')
- X && (ch != 'n') && (ch != 'N'));
- X clear_input_buffer (ask_buffer);
- X };
- X };
- X default_input = NULL;
- X Clear_Status_Display ();
- X update_input_buffer (talk_buffer, '\0');
- X return ((ch == 'y') || (ch == 'Y'));
- X
- X};
- X
- Xprocess_claim_offer (t)
- X int t;
- X{
- X char error_buf[80];
- X struct player_command_struct pcs;
- X
- X if ((t + trick) > 14) {
- X sprintf (error_buf, "THERE ARE ONLY %d TRICKS WHICH CAN BE CLAIMED",
- X 14 - trick);
- X Display_Status (error_buf);
- X return;
- X };
- X
- X claim_responses = 0;
- X claim_rejected = 0;
- X send_message_claim (t);
- X Display_Status ("WAITING FOR A RESPONSE TO YOUR OFFER...");
- X
- X disable (CMD_CLAIM);
- X while (claim_responses < 2)
- X player_input (-1, talk_buffer, "TALK ");
- X enable (CMD_CLAIM);
- X
- X Clear_Status_Display ();
- X
- X if (!claim_rejected) {
- X send_message_finish (t);
- X pcs.command = CMD_FINISH;
- X pcs.player_no = local_player;
- X pcs.data.tricks = t;
- X enqueue_command (&pcs);
- X };
- X};
- X
- Xprocess_claim_response (t)
- X int t;
- X{
- X int response;
- X char question_buffer [80];
- X
- X Display_Hand (declarer);
- X sprintf (question_buffer, "DECLARER CLAIMS %d TRICKS. DO YOU ACCEPT [YN]?",
- X t);
- X response = input_answer (question_buffer);
- X Clear_Hand (declarer);
- X update_input_buffer (talk_buffer, '\0');
- X send_message_respond (response);
- X};
- END_OF_FILE
- if test 31325 -ne `wc -c <'input.c.ab'`; then
- echo shar: \"'input.c.ab'\" unpacked with wrong size!
- fi
- # end of 'input.c.ab'
- fi
- echo shar: End of archive 4 \(of 7\).
- cp /dev/null ark4isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 7 archives.
- rm -f ark[1-9]isdone
- echo creating input.c from input.c.aa and input.c.ab
- cat input.c.aa input.c.ab >input.c
- rm -f input.c.aa input.c.ab
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-