home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!zephyr.ens.tek.com!master!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v14i088: okbridge2 - computer-mediated bridge game, Part10/14
- Message-ID: <3527@master.CNA.TEK.COM>
- Date: 7 Sep 92 21:42:37 GMT
- Sender: news@master.CNA.TEK.COM
- Lines: 1806
- Approved: billr@saab.CNA.TEK.COM
-
- Submitted-by: mclegg@cs.UCSD.EDU (Matthew Clegg)
- Posting-number: Volume 14, Issue 88
- Archive-name: okbridge2/Part10
- Supersedes: okbridge: Volume 13, Issue 16-22
- Environment: BSD-derived Unix, NeXT, 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 10 (of 14)."
- # Contents: WhatsNew conversation.c log.c oktally.c
- # Wrapped by billr@saab on Mon Sep 7 14:33:38 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'WhatsNew' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'WhatsNew'\"
- else
- echo shar: Extracting \"'WhatsNew'\" \(2491 characters\)
- sed "s/^X//" >'WhatsNew' <<'END_OF_FILE'
- XWhat's New in Okbridge version 1.7
- X------ --- -- -------- ------- ---
- X
- X1. GPS Duplicate Play
- X
- XThe GPS now supports duplicate play. The /DUP command can be used
- Xto download duplicate boards from the GPS. After each board is played,
- Xthe results of play by other tables are displayed. The /RESULTS
- Xcommand can be used to find out how well other tables have done at
- Xboards you have already played.
- X
- X
- X2. Improved Scoring Modes
- X
- XOKbridge 1.7 now contains only four scoring modes: Rubber, Duplicate,
- XIMP and MP. The Rubber and Duplicate modes are the same as before.
- XThe IMP mode scores Mono-IMP points for boards which have only been
- Xplayed by one table and scores true IMP points for boards which have
- Xbeen played by multiple tables. Similarly, the MP mode scores
- Xsimulated match points for boards which have only been played by
- Xone table and true match points for boards which have been played
- Xby multiple tables.
- X
- XAll players now see the same scores, regardless of when they join.
- X
- X
- X3. A Two-player Practice Mode has been added.
- X
- XFollowing a suggestion of Alan Truscott, a "practice" mode has been
- Xadded whereby two (or more) players may practice bidding together.
- XOKbridge supplies PASS bids for absent players, and after the bidding
- Xis completed, the hand has is displayed so that the partnership may
- Xdiscuss the bidding and plan the play.
- X
- X
- X4. User Interface Improvements
- X
- XSwitching between bidding/playing and talking is now completely
- Xunder user control. OKbridge never switches into bidding/playing
- Xmode on its own. Instead the <TAB> key is used to switch between
- Xbidding/playing and talking.
- X
- XMost of those annoying "PRESS RETURN TO CONTINUE" messages have
- Xbeen replaced by "PRESS ESC TO CONTINUE" messages. This will
- Xsubstantially reduce the chance that pressing return will have
- Xan unintended effect.
- X
- X
- X5. Increased Fault Tolerance
- X
- XIf your connection to the server is temporarily lost, it is possible
- Xto rejoin the game and continue playing from exactly where you left off.
- XIt is possible to save a board which has been partially played and to
- Xresume playing it at a later date. Observers can take over in the
- Xmiddle of a hand.
- X
- X
- X6. Defaults can be saved and restored
- X
- XMany of the program's settings, such as the player name, email address,
- Xbell and prompt toggles, etc., are now saved automatically to the
- Xfile ".okdefaults" when the program terminates. This file is then
- Xread at startup time, restoring the prior settings.
- X
- X
- X6. Spectators can now talk to each other.
- X
- END_OF_FILE
- if test 2491 -ne `wc -c <'WhatsNew'`; then
- echo shar: \"'WhatsNew'\" unpacked with wrong size!
- fi
- # end of 'WhatsNew'
- fi
- if test -f 'conversation.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'conversation.c'\"
- else
- echo shar: Extracting \"'conversation.c'\" \(14993 characters\)
- sed "s/^X//" >'conversation.c' <<'END_OF_FILE'
- X/* conversation.c -- processor for conversation level messages.
- X *
- X ! Copyright (C) 1990-1992 by Matthew Clegg. All Rights Reserved
- X !
- X ! OKbridge is made available as a free service to the Internet.
- X ! Accordingly, the following restrictions are placed on its use:
- X !
- X ! 1. OKbridge may not be modified in any way without the explicit
- X ! permission of Matthew Clegg.
- X !
- X ! 2. OKbridge may not be used in any way for commercial advantage.
- X ! It may not be placed on for-profit networks or on for-profit
- X ! computer systems. It may not be bundled as part of a package
- X ! or service provided by a for-profit organization.
- X !
- X ! If you have questions about restrictions on the use of OKbridge,
- X ! write to mclegg@cs.ucsd.edu.
- X !
- X ! DISCLAIMER: The user of OKbridge accepts full responsibility for any
- X ! damage which may be caused by OKbridge.
- X *
- X * This module is responsible for processing messages at the conversation
- X * level of the okbridge protocol.
- X */
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <sys/time.h>
- X
- X#include "network.h"
- X#include "state.h"
- X#include "display.h"
- X#include "terminal.h"
- X#include "cs.h"
- X#include "input.h"
- X#include "conversation.h"
- X
- X#ifdef GCC
- Xextern gettimeofday (), strcasecmp ();
- Xextern fprintf ();
- X#endif
- X
- Xextern int pause_mode;
- X
- Xextern char *strdup ();
- Xextern void free ();
- X
- Xextern void Generate_reset ();
- X
- X
- Xchar msg_buf[100]; /* A buffer used for formatting messages that will
- X be displayed or sent to other players. */
- X
- Xstruct timeval ping_start; /* time at which last ping command
- X was issued. */
- X
- X#ifdef LOGFILE
- Xextern FILE *net_log;
- X#endif
- X
- Xstatic void Respond_to_Echo (msg)
- X Message msg;
- X/* Responds to an echo message. */
- X{
- X int mils; /* milliseconds elapsed between ping and echo */
- X struct timeval ping_end;
- X
- X if (!strcmp(msg->p.data.echo.ping_source, local_player_name)) {
- 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, "ECHO RECEIVED FROM (%c) %-10s IN %7.2f SECONDS",
- X *("NESWO" + msg->p.player_no), msg->p.player_name,
- X ((float) mils) * 0.001);
- X Moderator_Comment (msg_buf);
- X }
- X}
- X
- Xvoid Handle_Conversation_Message (msg)
- X Message msg;
- X/* Processes the message m. If the message is a protocol message, then
- X takes appropriate action based on the message. Appends the message
- X to the appropriate conversation queue if further action is warranted.
- X*/
- X{
- X char message_buf [100];
- X int i, s;
- X int pass_upwards;
- X /* A boolean flag indicating that the message should be passed upwards
- X to the game queue. */
- X Table t = msg->source->table;
- X
- X pass_upwards = 1;
- X switch (msg->p.command) {
- X case CMD_ERROR :
- X sprintf (message_buf, "ERROR IN MESSAGE FROM %s (%s):",
- X msg->source->player_name,
- X (msg->source->seat < 4)? seat_names[msg->source->seat]:
- X "OBSERVER");
- X Network_Comment (message_buf);
- X Network_Comment (msg->p.data.error.message);
- X Network_Comment (msg->p.command_text);
- X pass_upwards = 0;
- X break;
- X
- X case CMD_ACK:
- X sprintf (message_buf, "%s HAS JOINED THE GAME AS %s.",
- X msg->p.data.ack.player_name,
- X (msg->p.data.ack.position == PLAYER_OBS)? "AN OBSERVER":
- X seat_names[msg->p.data.ack.position]);
- X Network_Comment (message_buf);
- X break;
- X
- X case CMD_CC:
- X if (conventions[side_of(msg->p.player_no)] != NULL)
- X free (conventions[side_of(msg->p.player_no)]);
- X conventions[side_of(msg->p.player_no)] = strdup(msg->p.data.cc);
- X Display_Player_Comment
- X (COMMENT_PUBLIC, side_of(msg->p.player_no)? "E-W CC": "N-S CC",
- X msg->p.data.cc);
- X break;
- X
- X case CMD_CLAIMREQ:
- X if (IS_PLAYER(local_player) &&
- X (side_of(local_player) != side_of(Local_play->declarer))) {
- X Set_Display_Mode (PLAYING_DISPLAY);
- X Display_Hand (Local_play->declarer);
- X Display_Hand (player_partner[local_player]);
- X Display_Hand (player_partner[Local_play->declarer]);
- X sprintf (message_buf,
- X "DECLARER CLAIMS %d TRICKS. DO YOU ACCEPT? ",
- X msg->p.data.claimreq.no_tricks);
- X Send_claimresp (Local_table, Ask(message_buf));
- X Clear_Hand (Local_play->declarer);
- X Clear_Hand (player_partner[local_player]);
- X } else {
- X sprintf (message_buf, "DECLARER IS CLAIMING %d TRICKS ...",
- X msg->p.data.claimreq.no_tricks);
- X Moderator_Comment (message_buf);
- X }
- X claim_responses = 0;
- X claim_accepted = 1;
- X break;
- X
- X case CMD_CLAIMRESP:
- X claim_responses += 1;
- X claim_accepted = claim_accepted && msg->p.data.claimresp;
- X if ((claim_responses == 2) && !claim_accepted)
- X Status ("THE CLAIM OFFER HAS BEEN DECLINED.");
- X break;
- X
- X case CMD_COMMENT:
- X Moderator_Comment (msg->p.data.comment);
- X break;
- X
- X case CMD_ECHO:
- X Respond_to_Echo (msg);
- X break;
- X
- X case CMD_HELLO :
- X if (strcmp(major_revision_level, msg->p.data.hello.version)) {
- X sprintf (message_buf, "%s HAS ATTEMPTED TO CONNECT USING VERSION %s",
- X msg->p.data.hello.player_name, msg->p.data.hello.version);
- X Network_Comment (message_buf);
- X } else {
- X if (IS_OBSERVER(msg->p.data.hello.seat_req))
- X sprintf (message_buf, "%s HAS JOINED THE GAME.",
- X msg->p.data.hello.player_name);
- X else {
- X sprintf (message_buf, "%s HAS JOINED THE GAME AS %s.",
- X msg->p.data.hello.player_name,
- X seat_names[msg->p.data.hello.seat_req]);
- X sprintf (PLAYER_NAME(t, msg->p.data.hello.seat_req), "%s",
- X msg->p.data.hello.player_name);
- X Refresh_Player_Names ();
- X }
- X Network_Comment (message_buf);
- X ring_bell ();
- X }
- X break;
- X
- X case CMD_MODE:
- X if (msg->p.data.mode != t->playing_mode) {
- X switch (msg->p.data.mode) {
- X case CLUB_PLAYING_MODE:
- X Moderator_Comment ("WE ARE PLAYING CLUB STYLE BRIDGE.");
- X break;
- X case PRACTICE_PLAYING_MODE:
- X Moderator_Comment ("WE ARE PLAYING PRACTICE BRIDGE.");
- X break;
- X case FORMAL_PLAYING_MODE:
- X Moderator_Comment ("WE ARE PLAYING FORMAL BRIDGE.");
- X break;
- X }
- X }
- X break;
- X
- X case CMD_NAME:
- X sprintf (message_buf, "%s IS NOW NAMED %s.", msg->p.player_name,
- X msg->p.data.name.new_name);
- X Network_Comment (message_buf);
- X if (IS_PLAYER(msg->p.player_no)) {
- X sprintf (PLAYER_NAME(t, msg->p.player_no), "%s",
- X msg->p.data.name.new_name);
- X Refresh_Player_Names ();
- X }
- X break;
- X
- X case CMD_QUIT:
- X sprintf (message_buf, "%s HAS QUIT.", msg->p.player_name);
- X Network_Comment (message_buf);
- X if (IS_PLAYER(msg->p.player_no)) {
- X Refresh_Player_Names ();
- X Refresh_Input_Buffers ();
- X }
- X pass_upwards = 0;
- X break;
- X
- X case CMD_PING:
- X if (!msg->loopback)
- X Send_echo (msg->source->table, msg->p.player_name);
- X break;
- X
- X case CMD_RESET:
- X Moderator_Comment ("RESET RECEIVED!");
- X Generate_reset (RESET_FULL);
- X break;
- X
- X case CMD_SKIP:
- X Moderator_Comment ("SKIPPING TO NEXT HAND ... ");
- X pause_mode = 0;
- X break;
- X
- X case CMD_SEAT:
- X if (strcasecmp(msg->p.data.seat.player_name, local_player_name)) {
- X s = msg->p.data.seat.new_pos;
- X sprintf (message_buf, "%s IS SITTING AS %s.",
- X msg->p.data.seat.player_name,
- X IS_PLAYER(s)? seat_names[s]: "AN OBSERVER");
- X Network_Comment (message_buf);
- X if (IS_PLAYER(msg->p.data.seat.new_pos) ||
- X IS_PLAYER(msg->p.data.seat.old_pos)) {
- X Refresh_Player_Names ();
- X Refresh_Input_Buffers ();
- X }
- X } else
- X Display_Player_Position ();
- X break;
- X
- X case CMD_SEATERR:
- X Network_Comment ("THE SEAT WHICH YOU REQUESTED IS OCCUPIED.");
- X if (msg->p.data.seaterr.free_seats[0] >= 4)
- X Network_Comment ("THERE ARE NO FREE SEATS CURRENTLY.");
- X else {
- X sprintf (message_buf, "THE CURRENTLY FREE SEATS ARE:");
- X for (i = 0; i < 3; i++)
- X if (msg->p.data.seaterr.free_seats[i] < 4)
- X sprintf (message_buf + strlen(message_buf), " %s,",
- X seat_names[msg->p.data.seaterr.free_seats[i]]);
- X message_buf[strlen(message_buf)-1] = '.';
- X Network_Comment (message_buf);
- X }
- X break;
- X
- X case CMD_SEATPOS:
- X Assign_seat (Local_table, Local_Player_Connection, msg->p.data.seatpos);
- X local_player = msg->p.data.seatpos;
- X if (Local_table->game_mode == BIDDING_MODE) {
- X if (IS_OBSERVER(msg->p.data.seatpos))
- X Set_Input_Mode (TALK_INPUT);
- X else
- X Set_Input_Mode (BID_INPUT);
- X Refresh_Player_Names ();
- X Refresh_Input_Buffers ();
- X } else if (Local_table->game_mode == PLAYING_MODE) {
- X if (PRACTICE(Local_table) && IS_PLAYER(msg->p.data.seatpos))
- X Set_Input_Mode (PLAY_INPUT);
- X else if (IS_OBSERVER(msg->p.data.seatpos) ||
- X (msg->p.data.seatpos == player_partner[Local_play->declarer]))
- X Set_Input_Mode (TALK_INPUT);
- X else
- X Set_Input_Mode (PLAY_INPUT);
- X Refresh_Player_Names ();
- X Refresh_Input_Buffers ();
- X if (IS_PLAYER(local_player))
- X Display_Hand (local_player);
- X }
- X Display_Player_Position ();
- X sprintf (message_buf, "YOU ARE NOW SITTING AS %s.",
- X IS_PLAYER(local_player)? seat_names[local_player]:
- X "AN OBSERVER");
- X Network_Comment (message_buf);
- X break;
- X
- X case CMD_SPEC:
- X sprintf (message_buf, "%s HAS ENTERED SPECTATOR MODE.",
- X msg->p.player_name);
- X Moderator_Comment (message_buf);
- X msg->source->spectator = 1;
- X break;
- X
- X case CMD_TABLE:
- X if (t->table_no == msg->p.data.table) {
- X sprintf (message_buf, "YOU HAVE JOINED TABLE %d.", t->table_no);
- X Moderator_Comment (message_buf);
- X } else {
- X sprintf (message_buf, "ERROR IN ASSIGNMENT TO TABLE %d",
- X msg->p.data.table);
- X Moderator_Comment (message_buf);
- X }
- X break;
- X
- X case CMD_TALK:
- X switch (msg->p.data.talk.recipients) {
- X case TALK_RCPT_LHO:
- X if (player_next[msg->p.player_no] == local_player)
- X Display_Player_Comment
- X (COMMENT_PRIVATE, msg->p.player_name, msg->p.data.talk.message);
- X break;
- X case TALK_RCPT_RHO:
- X if (player_prev[msg->p.player_no] == local_player)
- X Display_Player_Comment
- X (COMMENT_PRIVATE, msg->p.player_name, msg->p.data.talk.message);
- X break;
- X case TALK_RCPT_OPPS:
- X if (player_partner[msg->p.player_no] != local_player)
- X Display_Player_Comment
- X (COMMENT_FORMAL, msg->p.player_name, msg->p.data.talk.message);
- X break;
- X case TALK_RCPT_SPEC:
- X if (spectator_mode)
- X Display_Player_Comment
- X (COMMENT_FORMAL, msg->p.player_name, msg->p.data.talk.message);
- X break;
- X case TALK_RCPT_ALL:
- X default:
- X Display_Player_Comment
- X (COMMENT_PUBLIC, msg->p.player_name, msg->p.data.talk.message);
- X break;
- X }
- X break;
- X
- X case CMD_WAKEUP:
- X if (!strcasecmp(msg->p.data.wakeup.recipient, "ALL")) {
- X Display_Player_Comment (COMMENT_PUBLIC, msg->p.player_name, "WAKE UP!");
- X ring_bell ();
- X } else if (!strcasecmp(msg->p.data.wakeup.recipient, local_player_name)) {
- X Display_Player_Comment (COMMENT_PRIVATE, msg->p.player_name, "WAKE UP!");
- X ring_bell ();
- X }
- X break;
- X
- X case CMD_WHORESP:
- X sprintf (message_buf, "WHOIS %s", msg->p.data.whoresp.recipient);
- X Display_Player_Comment (COMMENT_PUBLIC, message_buf,
- X msg->p.data.whoresp.message);
- X break;
- X
- X default:
- X break;
- X }
- X
- X if (pass_upwards)
- X enqueue_message(t->game_queue, msg);
- X else
- X deallocate_message (msg);
- X}
- X
- Xstatic int Handle_Protocol_Messages ()
- X/* Handles all messages which are on protocol queues. If any messages
- X were found, returns TRUE.
- X*/
- X{
- X Table t;
- X Message m;
- X int message_found = 0;
- X
- X for (t = Table_List; t != NULL; t = t->next) {
- X while (message_available(t->protocol_queue)) {
- X m = dequeue_message (t->protocol_queue);
- X message_found = 1;
- X if (server_mode)
- X Handle_Protocol_Message_for_Server (m);
- X else
- X Handle_Protocol_Message_for_Client (m);
- X }
- X }
- X
- X return (message_found);
- X}
- X
- Xstatic int Handle_Conversation_Messages ()
- X/* Handles all messages which are on conversation queues. If any messages
- X were found, returns TRUE.
- X*/
- X{
- X Table t;
- X Message m;
- X int message_found = 0;
- X
- X for (t = Table_List; t != NULL; t = t->next) {
- X while (message_available(t->conversation_queue)) {
- X message_found = 1;
- X m = dequeue_message (t->conversation_queue);
- X Handle_Conversation_Message (m);
- X }
- X }
- X
- X return (message_found);
- X}
- X
- Xvoid Wait_for_event_at_conversation_level (e)
- X event_signal e;
- X/* Receives incoming messages at all tables. Handles keyboard characters
- X * and messages which arrive on the protocol queues. Each time a keyboard
- X * character is received or a new message is processed, the event_signal
- X * routine is called. If it returns true, then the procedure exits.
- X */
- X{
- X do {
- X Handle_Protocol_Messages ();
- X if ((*e)()) return;
- X restore_cursor ();
- X Wait_for_network_event ();
- X if ((*e)()) return;
- X Accept_Keyboard_Characters ();
- X } while (1);
- X
- X}
- X
- Xvoid Wait_for_event_at_game_level (e)
- X event_signal e;
- X/* Receives incoming messages at all tables. Handles keyboard characters
- X * and messages which arrive on the protocol and conversation queues. Each
- X * time a keyboard character is received or a new message is processed, the
- X * event_signal e routine is called. If it returns true, then the procedure
- X * exits.
- X */
- X{
- X int protocol_message_handled,
- X conversation_message_handled;
- X
- X do {
- X do {
- X protocol_message_handled = Handle_Protocol_Messages ();
- X conversation_message_handled = Handle_Conversation_Messages ();
- X } while (protocol_message_handled || conversation_message_handled);
- X
- X if ((*e)()) return;
- X restore_cursor ();
- X Wait_for_network_event ();
- X if ((*e)()) return;
- X Accept_Keyboard_Characters ();
- X } while (1);
- X}
- X
- XTable Wait_for_conversation_message ()
- X/* Receives incoming message at all tables. Handles keyboard characters
- X * and messages which arrive on the protocol queues. When a message is
- X * placed onto the conversation queue of a table, returns a pointer to
- X * the table. */
- X{
- X Table t;
- X
- X do {
- X Handle_Protocol_Messages ();
- X for (t = Table_List; t != NULL; t = t->next)
- X if (message_available(t->conversation_queue))
- X return (t);
- X restore_cursor ();
- X Wait_for_network_event ();
- X Accept_Keyboard_Characters ();
- X } while (1);
- X}
- X
- XTable Wait_for_game_message ()
- X/* Receives incoming messages at all tables. Handles keyboard characters
- X * and messages which arrive on the protocol and game queues. When a message
- X * is placed onto the game queue of a table, returns a pointer to the table.
- X */
- X{
- X Table t;
- X int protocol_message_handled,
- X conversation_message_handled;
- X
- X do {
- X do {
- X protocol_message_handled = Handle_Protocol_Messages ();
- X conversation_message_handled = Handle_Conversation_Messages ();
- X } while (protocol_message_handled || conversation_message_handled);
- X
- X for (t = Table_List; t != NULL; t = t->next)
- X if (message_available(t->game_queue))
- X return (t);
- X
- X restore_cursor ();
- X Wait_for_network_event ();
- X Accept_Keyboard_Characters ();
- X } while (1);
- X}
- END_OF_FILE
- if test 14993 -ne `wc -c <'conversation.c'`; then
- echo shar: \"'conversation.c'\" unpacked with wrong size!
- fi
- # end of 'conversation.c'
- fi
- if test -f 'log.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'log.c'\"
- else
- echo shar: Extracting \"'log.c'\" \(17424 characters\)
- sed "s/^X//" >'log.c' <<'END_OF_FILE'
- X/* log.c -- module for recording boards to log files.
- X *
- X ! Copyright (C) 1990-1992 by Matthew Clegg. All Rights Reserved
- X !
- X ! OKbridge is made available as a free service to the Internet.
- X ! Accordingly, the following restrictions are placed on its use:
- X !
- X ! 1. OKbridge may not be modified in any way without the explicit
- X ! permission of Matthew Clegg.
- X !
- X ! 2. OKbridge may not be used in any way for commercial advantage.
- X ! It may not be placed on for-profit networks or on for-profit
- X ! computer systems. It may not be bundled as part of a package
- X ! or service provided by a for-profit organization.
- X !
- X ! If you have questions about restrictions on the use of OKbridge,
- X ! write to mclegg@cs.ucsd.edu.
- X !
- X ! DISCLAIMER: The user of OKbridge accepts full responsibility for any
- X ! damage which may be caused by OKbridge.
- X *
- X */
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#ifdef AIX
- X#include <time.h>
- X#endif
- X
- X#include "types.h"
- X#include "boards.h"
- X#include "scoring.h"
- X#include "log.h"
- X
- X#ifdef GCC
- Xextern time_t time ();
- Xextern fprintf ();
- Xextern fflush ();
- X#endif
- X
- Xextern void *qsort ();
- X
- X
- Xtypedef int (* play_comparator) ();
- Xtypedef int sorted_play_array [4][13];
- X
- Xstatic Play_record *Play_record_buffer [1000];
- X
- Xstatic void format_suit (buffer, h, p, s)
- X/* Searches the hand h for cards held by the player p in the suit s.
- X For each such card found, places an ascii character representing its
- X rank into the buffer.
- X*/
- X char *buffer; hand h; int p, s;
- X{
- X int i;
- X
- X for (i = 12; i >= 0; i--)
- X if (h[card_code(s, i)] == p)
- X *(buffer++) = *rank_names[i];
- X *buffer = '\0';
- X}
- X
- Xstatic void Sort_cards_by_trick
- X (trumps, leader, plays, no_plays, s, leaders)
- X int trumps;
- X int leader;
- X card_type *plays;
- X int no_plays;
- X sorted_play_array s;
- X int *leaders;
- X/* Sorts the set of plays for a hand by trick and player. */
- X{
- X int player = leader;
- X int trick_no = 0;
- X int i, j;
- X
- X for (i = 0; i < 4; i++)
- X for (j = 0; j < 13; j++)
- X s[i][j] = -1;
- X
- X leaders[0] = leader;
- X for (i = 0; i < no_plays; i++) {
- X s[player][trick_no] = plays[i];
- X player = player_next[player];
- X if (i % 4 == 3) {
- X player =
- X Winning_card (trumps, player,
- X s[player][trick_no],
- X s[player_next[player]][trick_no],
- X s[player_partner[player]][trick_no],
- X s[player_prev[player]][trick_no]);
- X if (trick_no < 12)
- X leaders[++trick_no] = player;
- X }
- X }
- X}
- X
- Xvoid Write_hand (logfile, b, p)
- X FILE *logfile;
- X Board *b;
- X Play_record *p;
- X/* Writes the board b with play record p to the file f in an expanded
- X * format which is similar to that found in bridge books.
- X */
- X{
- X int i, j;
- X char buf1[80], buf2[80];
- X time_t current_time;
- X
- X /* We always make the declarer appear as south: */
- X int vsouth = p->declarer;
- X int vwest = player_next[p->declarer];
- X int vnorth = player_partner[p->declarer];
- X int veast = player_prev[p->declarer];
- X
- X char *north_name = p->player_names[vnorth],
- X *west_name = p->player_names[vwest],
- X *south_name = p->player_names[vsouth],
- X *east_name = p->player_names[veast],
- X *player_names[4];
- X
- X sorted_play_array sorted_plays;
- X /* The list of cards each played by each player, indexed by trick no. */
- X int leader[13];
- X /* For each trick, the index of the player who was on lead. */
- X int lead, follow;
- X /* Boolean flags indicating if the current player is on lead. */
- X int round;
- X /* The current round of bidding. */
- X int bidder, player;
- X
- X player_names[PLAYER_NORTH] = north_name;
- X player_names[PLAYER_EAST] = east_name;
- X player_names[PLAYER_WEST] = west_name;
- X player_names[PLAYER_SOUTH] = south_name;
- X
- X if (logfile == NULL) return;
- X
- X time (¤t_time);
- X fprintf (logfile, "%s%s Board %d\n\n", ctime(¤t_time),
- X b->source, b->serial_no);
- X fprintf (logfile, "%s Dealer\n", p->player_names[b->dealer]);
- X if (b->vulnerable[side_of(vsouth)] && b->vulnerable[side_of(veast)])
- X fprintf (logfile, "All vul\n");
- X else if (b->vulnerable[side_of(vsouth)])
- X fprintf (logfile, "N-S vul\n");
- X else if (b->vulnerable[side_of(veast)])
- X fprintf (logfile, "E-W vul\n");
- X else
- X fprintf (logfile, "None vul\n");
- X
- X fprintf (logfile, "\n");
- X fprintf (logfile, "%15s North (%s)\n", " ", north_name);
- X format_suit (buf1, b->deal, vnorth, SUIT_SPADES);
- X fprintf (logfile, "%15s S %s\n", " ", buf1);
- X format_suit (buf1, b->deal, vnorth, SUIT_HEARTS);
- X fprintf (logfile, "%15s H %s\n", " ", buf1);
- X format_suit (buf1, b->deal, vnorth, SUIT_DIAMONDS);
- X fprintf (logfile, "%15s D %s\n", " ", buf1);
- X format_suit (buf1, b->deal, vnorth, SUIT_CLUBS);
- X fprintf (logfile, "%15s C %s\n", " ", buf1);
- X
- X sprintf (buf1, "West (%s)", west_name);
- X fprintf (logfile, "%-15s %15s East (%s)\n", buf1, " ", east_name);
- X format_suit (buf1, b->deal, vwest, SUIT_SPADES);
- X format_suit (buf2, b->deal, veast, SUIT_SPADES);
- X fprintf (logfile, "S %-13s %15s S %s\n", buf1, " ", buf2);
- X format_suit (buf1, b->deal, vwest, SUIT_HEARTS);
- X format_suit (buf2, b->deal, veast, SUIT_HEARTS);
- X fprintf (logfile, "H %-13s %15s H %s\n", buf1, " ", buf2);
- X format_suit (buf1, b->deal, vwest, SUIT_DIAMONDS);
- X format_suit (buf2, b->deal, veast, SUIT_DIAMONDS);
- X fprintf (logfile, "D %-13s %15s D %s\n", buf1, " ", buf2);
- X format_suit (buf1, b->deal, vwest, SUIT_CLUBS);
- X format_suit (buf2, b->deal, veast, SUIT_CLUBS);
- X fprintf (logfile, "C %-13s %15s C %s\n", buf1, " ", buf2);
- X
- X fprintf (logfile, "\n");
- X fprintf (logfile, "%15s South (%s)\n", " ", south_name);
- X format_suit (buf1, b->deal, vsouth, SUIT_SPADES);
- X fprintf (logfile, "%15s S %s\n", " ", buf1);
- X format_suit (buf1, b->deal, vsouth, SUIT_HEARTS);
- X fprintf (logfile, "%15s H %s\n", " ", buf1);
- X format_suit (buf1, b->deal, vsouth, SUIT_DIAMONDS);
- X fprintf (logfile, "%15s D %s\n", " ", buf1);
- X format_suit (buf1, b->deal, vsouth, SUIT_CLUBS);
- X fprintf (logfile, "%15s C %s\n", " ", buf1);
- X
- X fprintf (logfile, "\n");
- X if (p->hand_completed && p->contract == 0)
- X fprintf (logfile, " All Passed.\n");
- X else if (p->hand_completed) {
- X fprintf (logfile, "\n%5s %-8s %-8s %-8s %-8s\n", " ",
- X "West", "North", "East", "South");
- X fprintf (logfile, "%5s %-8s %-8s %-8s %-8s\n", " ",
- X west_name, north_name, east_name, south_name);
- X fprintf (logfile, "\n%5s ", " ");
- X round = -1;
- X bidder = vwest;
- X for (i = 0; i < p->no_bids - 2;) {
- X if (bidder == b->dealer) round++;
- X if (round < 0)
- X fprintf (logfile, "%-8s ", "--");
- X else if (i >= p->no_bids - 3) {
- X fprintf (logfile, "(all pass)");
- X i++;
- X } else{
- X sprintf (buf1, "%s%c",
- X (p->bids[i] == BID_PASS)? "pass": bid_names[p->bids[i]],
- X p->alerts[i]? '*': ' ');
- X fprintf (logfile, "%-8s ", buf1);
- X i++;
- X }
- X bidder = player_next[bidder];
- X if (bidder == vwest)
- X fprintf (logfile, "\n%5s ", " ");
- X }
- X if (bidder != vwest)
- X fprintf (logfile, "\n");
- X
- X if (p->no_plays > 0)
- X fprintf (logfile, "\n%5s Opening Lead: %s\n\n", " ",
- X card_names[(int) (p->play_list[0])]);
- X }
- X
- X if (p->hand_completed && (p->no_plays > 0)) {
- X Sort_cards_by_trick (trumpsuit_of(p->contract), player_next[p->declarer],
- X p->play_list, p->no_plays, sorted_plays, leader);
- X
- X fprintf (logfile, "\n ");
- X for (i = 0; i < 13; i++)
- X fprintf (logfile, "%2d ", i+1);
- X fprintf (logfile, "\n ");
- X for (i = 0; i < 4*13-2; i++) fprintf (logfile, "-");
- X player = vwest;
- X for (i = 0; i < 4; i++) {
- X fprintf (logfile, "\n%8s ", p->player_names[player]);
- X for (j = 0; j < 13; j++) {
- X if (sorted_plays[player][j] != -1) {
- X lead = (leader[j] == player)? '>': ' ';
- X if ((j < 12) && (leader[j+1] == player))
- X follow = '-';
- X else
- X follow = ' ';
- X fprintf (logfile, "%c%2s%c", lead,
- X card_names[sorted_plays[player][j]], follow);
- X } else
- X fprintf (logfile, " ");
- X }
- X player = player_next [player];
- X }
- X fprintf (logfile, "\n\n > indicates the lead\n\n");
- X }
- X
- X if (p->hand_completed) {
- X fprintf (logfile, "\nResult: %+d\n\n", p->result);
- X switch (b->scoring_mode) {
- X case RUBBER_SCORING:
- X fprintf (logfile, "%-10s %8s %8s\n", " ", "N-S", "E-W");
- X fprintf (logfile, "%-10s %8s %8s\n", " ", "------", "------");
- X fprintf (logfile, "%-10s %8d %8d\n", "Above",
- X p->above_line[side_of(vsouth)], p->above_line[side_of(veast)]);
- X fprintf (logfile, "%-10s %8s %8s\n", " ", "------", "------");
- X fprintf (logfile, "%-10s %8d %8d\n", "Part Score",
- X b->part_score[side_of(vsouth)], b->part_score[side_of(veast)]);
- X fprintf (logfile, "%-10s %8d %8d\n", "Below",
- X p->below_line[side_of(vsouth)], p->below_line[side_of(veast)]);
- X fprintf (logfile, "\n");
- X break;
- X
- X case DUPLICATE_SCORING:
- X case MP_SCORING:
- X Sort_play_records_by_matchpoints (b);
- X Write_summary_of_play (logfile, b);
- X break;
- X
- X case IMP_SCORING:
- X Sort_play_records_by_imps (b);
- X Write_summary_of_play (logfile, b);
- X break;
- X }
- X }
- X
- X fprintf (logfile, "\n\n");
- X for (i = 0; i < 72; i++)
- X fprintf (logfile, "=");
- X fprintf (logfile, "\n%c\n", 12);
- X fflush (logfile);
- X}
- X
- X
- Xvoid Write_hand_compactly (zhang_logfile, table_no, b, p)
- X FILE *zhang_logfile;
- X int table_no;
- X Board *b;
- X Play_record *p;
- X/* Writes the board b with play record p to the file f in a brief format
- X * which was introduced by S. Zhang.
- X */
- X{
- X int i, j;
- X char format_buffer [80];
- X char *bid_zhang[4][20];
- X char zhang[4];
- X time_t current_time;
- X struct tm *decoded_time;
- X sorted_play_array sorted_plays;
- X int leading_play [13];
- X int contractor = side_of (p->declarer);
- X int trump_suit = trumpsuit_of (p->contract);
- X int down, excess, round, lead, bidder;
- X int contract = level_of (p->contract);
- X
- X zhang[0]='N'; zhang[1]='E'; zhang[2]='S'; zhang[3]='W';
- X
- X if (zhang_logfile == NULL) return;
- X for (i = 0; i < 4; i++){fprintf(zhang_logfile,
- X " %-8.8s ", p->player_names[i]);
- X for (j = 3; j >= 0; j--) {
- X format_suit (format_buffer, b->deal, i, j);
- X fprintf (zhang_logfile, " %-13s", format_buffer);
- X } fprintf (zhang_logfile, "\n");
- X }
- X
- X fprintf(zhang_logfile, "%3d.(tab%3d)", b->serial_no, table_no);
- X
- X fprintf (zhang_logfile," %6.6s-%c:", p->player_names[p->declarer],
- X zhang[p->declarer]);
- X fprintf (zhang_logfile, "%d%1.1s",
- X contract, long_suit_names [trump_suit] );
- X
- X if (p->doubled == 2)
- X fprintf (zhang_logfile, "XX");
- X else if (p->doubled)
- X fprintf (zhang_logfile, "X ");
- X else
- X fprintf (zhang_logfile, " ");
- X
- X if (p->tricks[contractor] >= contract+6) {
- X fprintf (zhang_logfile, " -- Made %2d | ",
- X (contract == 0)? 0: p->tricks[contractor]-6);
- X } else { down = contract + 6 - p->tricks[contractor];
- X fprintf (zhang_logfile, " -- Down %2d | ", down);
- X }
- X
- X if (b->vulnerable[SIDE_NS] && b->vulnerable[SIDE_EW])
- X fprintf (zhang_logfile, "Vul:BOTH | ");
- X else if (b->vulnerable[SIDE_NS]) fprintf (zhang_logfile, "Vul:N&S | ");
- X else if (b->vulnerable[SIDE_EW]) fprintf (zhang_logfile, "Vul:E&W | ");
- X else fprintf (zhang_logfile, "Vul:NONE | ");
- X
- X
- X if (p->tricks[contractor] >= contract+6) {
- X if ( contractor == SIDE_NS ) {fprintf (zhang_logfile, " NS: ");}
- X else fprintf (zhang_logfile, "*NS: -");
- X excess = p->tricks[contractor] - contract - 6;
- X if (contract == 0)
- X fprintf (zhang_logfile, "0 ");
- X else
- X fprintf (zhang_logfile, "%d ",
- X Duplicate_score_made
- X (b->vulnerable[contractor], level_of(p->contract),
- X trumpsuit_of(p->contract), p->doubled, p->result));
- X } else {
- X down = contract + 6 - p->tricks[contractor];
- X if ( contractor == SIDE_NS ) {fprintf (zhang_logfile, " NS: -");}
- X else fprintf (zhang_logfile, "*NS: ");
- X fprintf (zhang_logfile, "%d ",
- X Duplicate_score_set
- X (b->vulnerable[contractor], level_of(p->contract),
- X trumpsuit_of(p->contract), p->doubled, p->result));
- X }
- X
- X for (i=0; i<4; i++) for (j=0; j<20; j++) bid_zhang[i][j]=" ";
- X
- X bidder = b->dealer;
- X round = 0;
- X for (i = 0; i < p->no_bids; i++) {
- X bid_zhang[bidder][round] = bid_names[p->bids[i]];
- X bidder = player_next[bidder];
- X if (bidder == PLAYER_NORTH) round++;
- X }
- X
- X Sort_cards_by_trick (trumpsuit_of(p->contract), player_next[p->declarer],
- X p->play_list, p->no_plays, sorted_plays, leading_play);
- X for (i = 0; i < 4; i++) {
- X fprintf(zhang_logfile,"\n%c-%-8.8s",zhang[i],p->player_names[i]);
- X for (j = 0; j < 13; j++) {
- X if (sorted_plays[i][j] != -1) {
- X lead = (leading_play[j] == i)? '*': ' ';
- X if ((lead ==' ')&&(i==3) ) lead='_';
- X fprintf (zhang_logfile, "%2s%c", card_names[sorted_plays[i][j]], lead);
- X } else
- X fprintf (zhang_logfile, " ");
- X } fprintf (zhang_logfile, "|");
- X for (j = 0; j <= p->no_bids/4; j++) {
- X fprintf (zhang_logfile, "%-2.2s ", bid_zhang[i][j]);
- X }
- X }
- X
- X fprintf (zhang_logfile, "\n==========");
- X for (i = 0; i < 13; i++) fprintf (zhang_logfile, "%2d=", i+1);
- X time (¤t_time);
- X for (i = 0; i < 6; i++) fprintf (zhang_logfile, "=%2d", i+1);
- X decoded_time = localtime (¤t_time);
- X fprintf (zhang_logfile, " %s %2d\n%c\n",
- X month_names[decoded_time->tm_mon], decoded_time->tm_mday, 12);
- X fflush (zhang_logfile);
- X}
- X
- Xvoid sprint_summary_header (buf)
- X char *buf;
- X{
- X sprintf (buf, "%-11s %3s %3s %-4s %-21s %-8s %2s %3s %-5s %5s %4s",
- X "Board", "No", "Dlr", "Vul", "Players", "Contract",
- X "By", "Res", "Score", "IMPs", "MPs");
- X}
- X
- Xstatic char *seat_letters [4] = {"N", "E", "S", "W"};
- Xstatic char *double_names [3] = {"", "-X", "-XX"};
- X
- Xvoid sprint_summary_record (buf1, buf2, b, p)
- X char *buf1;
- X char *buf2;
- X Board *b;
- X Play_record *p;
- X{
- X char *vul_string;
- X char contract_buf[10];
- X
- X if (b->vulnerable[SIDE_NS] && b->vulnerable[SIDE_EW])
- X vul_string = "both";
- X else if (b->vulnerable[SIDE_NS])
- X vul_string = "N-S";
- X else if (b->vulnerable[SIDE_EW])
- X vul_string = "E-W";
- X else
- X vul_string = "none";
- X
- X if (p->contract == BID_PASS)
- X sprintf (contract_buf, "Passed");
- X else
- X sprintf (contract_buf, "%s%s", bid_names[p->contract],
- X double_names[p->doubled]);
- X
- X sprintf (buf1,
- X "%-11s %3d %-3s %-4s N %-8s S %-8s %-8s %-2s %+3d %5d %5.1f %4.2f",
- X b->source, b->serial_no, seat_letters[b->dealer], vul_string,
- X p->player_names[PLAYER_NORTH], p->player_names[PLAYER_SOUTH],
- X contract_buf, seat_letters[p->declarer], p->result,
- X p->below_line[SIDE_NS],
- X p->imatch_points[SIDE_NS],
- X p->match_points[SIDE_NS]);
- X
- X sprintf (buf2,
- X "%-11s %3s %3s %-4s E %-8s W %-8s %-8s %2s %3s %5d %5.1f %4.2f",
- X " ", " ", " ", " ",
- X p->player_names[PLAYER_EAST], p->player_names[PLAYER_WEST],
- X " ", " ", " ", p->below_line[SIDE_EW],
- X p->imatch_points[SIDE_EW],
- X p->match_points[SIDE_EW]);
- X
- X}
- X
- Xvoid Write_summary_of_play (f, b)
- X FILE *f;
- X Board *b;
- X/* For each play record associated to the board b, writes a single line
- X * summary describing the result of play.
- X */
- X{
- X char buf1 [100], buf2[100];
- X Play_record *p;
- X
- X sprint_summary_header (buf1);
- X fprintf (f, "%s\n", buf1);
- X
- X for (p = b->play_records; p != NULL; p = p->next) {
- X sprint_summary_record (buf1, buf2, b, p);
- X fprintf (f, "%s\n", buf1);
- X fprintf (f, "%s\n", buf2);
- X }
- X fprintf (f, "\n");
- X}
- X
- Xstatic void Sort_play_records (b, pc)
- X Board *b;
- X play_comparator pc;
- X{
- X int i, n = 0;
- X Play_record *p;
- X
- X if ((b->play_records == NULL) || (b->play_records->next == NULL))
- X return;
- X
- X for (p = b->play_records; p != NULL; p = p->next)
- X Play_record_buffer[n++] = p;
- X
- X qsort (Play_record_buffer, n, sizeof(Play_record *), pc);
- X
- X p = b->play_records = Play_record_buffer[0];
- X for (i = 1; i < n; i++)
- X p = (p->next = Play_record_buffer[i]);
- X p->next = NULL;
- X}
- X
- Xstatic int match_point_comparator (q1, q2)
- X Play_record **q1;
- X Play_record **q2;
- X{
- X float d1, d2;
- X Play_record *p1 = *q1;
- X Play_record *p2 = *q2;
- X
- X if (!p1->hand_completed && !p2->hand_completed)
- X return (0);
- X else if (!p2->hand_completed)
- X return (-1);
- X else if (!p1->hand_completed)
- X return (1);
- X
- X d1 = p1->match_points[SIDE_NS] - p1->match_points[SIDE_EW];
- X d2 = p2->match_points[SIDE_NS] - p2->match_points[SIDE_EW];
- X if (d2 < d1)
- X return (-1);
- X else if (d1 < d2)
- X return (1);
- X else
- X return (0);
- X}
- X
- X
- Xvoid Sort_play_records_by_matchpoints (b)
- X Board *b;
- X/* Sorts the set of play records for the board b according to the match
- X * point scores.
- X */
- X{
- X Sort_play_records (b, match_point_comparator);
- X}
- X
- Xstatic int imp_comparator (q1, q2)
- X Play_record **q1;
- X Play_record **q2;
- X{
- X float d1, d2;
- X Play_record *p1 = *q1;
- X Play_record *p2 = *q2;
- X
- X if (!p1->hand_completed && !p2->hand_completed)
- X return (0);
- X else if (!p2->hand_completed)
- X return (-1);
- X else if (!p1->hand_completed)
- X return (1);
- X
- X d1 = p1->imatch_points[SIDE_NS] - p1->imatch_points[SIDE_EW];
- X d2 = p2->imatch_points[SIDE_NS] - p2->imatch_points[SIDE_EW];
- X if (d2 < d1)
- X return (-1);
- X else if (d1 < d2)
- X return (1);
- X else
- X return (0);
- X}
- X
- Xvoid Sort_play_records_by_imps (b)
- X Board *b;
- X/* Sorts the set of play records for the board b according to the
- X * imp scores.
- X */
- X{
- X Sort_play_records (b, imp_comparator);
- X}
- X
- END_OF_FILE
- if test 17424 -ne `wc -c <'log.c'`; then
- echo shar: \"'log.c'\" unpacked with wrong size!
- fi
- # end of 'log.c'
- fi
- if test -f 'oktally.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'oktally.c'\"
- else
- echo shar: Extracting \"'oktally.c'\" \(16133 characters\)
- sed "s/^X//" >'oktally.c' <<'END_OF_FILE'
- X/* oktally.c
- X *
- X ! Copyright (C) 1990-1992 by Matthew Clegg. All Rights Reserved
- X !
- X ! OKbridge is made available as a free service to the Internet.
- X ! Accordingly, the following restrictions are placed on its use:
- X !
- X ! 1. OKbridge may not be modified in any way without the explicit
- X ! permission of Matthew Clegg.
- X !
- X ! 2. OKbridge may not be used in any way for commercial advantage.
- X ! It may not be placed on for-profit networks or on for-profit
- X ! computer systems. It may not be bundled as part of a package
- X ! or service provided by a for-profit organization.
- X !
- X ! If you have questions about restrictions on the use of OKbridge,
- X ! write to mclegg@cs.ucsd.edu.
- X !
- X ! DISCLAIMER: The user of OKbridge accepts full responsibility for any
- X ! damage which may be caused by OKbridge.
- X *
- X * This program merges email duplicate files, totaling the match
- X * points for corresponding pairs in each file, generating an output
- X * describing the results for each board.
- X *
- X * Usage:
- X *
- X * tally [-c] [-i] [-l] [-m] [-p player_name] [-sn] [-t[b]] [-z]
- X * file_1 file_2 ... file_n
- X *
- X * Reads each of file_1, file_2, ..., file_n. Merges the boards
- X * from these files and totals the match points for each pair.
- X * Writes the merged set of boards to standard output.
- X *
- X * Parameters:
- X *
- X * -c
- X * Coded output. Writes an encoded email duplicate file as output.
- X *
- X * -i
- X * IMP scoring. Sorts the output play records by IMPs. The default is
- X * to sort by match points.
- X *
- X * -l
- X * Long output. Writes each board in a format which is similar to
- X * that used for presentation in bridge books and magazines.
- X *
- X * -m
- X * Merge. Does a selective merge. Boards appearing in the second files
- X * which do not appear in the file are ignored.
- X *
- X * -p player_name
- X * specifies that only boards which have been played by the specified
- X * player should be considered.
- X *
- X * -sn
- X * Skip count. Specifies a skip count. The first n boards read into
- X * memory are ignored.
- X *
- X * -t
- X * Totals. Computes the totals for each player and prints out the
- X * list of totals, sorted either by match points or IMPs. If -tb
- X * is specified, then a two-column output is generated, the first
- X * column given the match point score totals and the second giving
- X * the match point score totals.
- X *
- X * -z
- X * Zhang format. Writes each board out in a compact format which was
- X * first introduced by Shangyou Zhang.
- X */
- X
- X#include <stdio.h>
- X#include <string.h>
- X
- X#define _BRIDGE_
- X
- X#include "types.h"
- X#include "boards.h"
- X#include "log.h"
- X
- X#ifdef GCC
- Xextern fprintf (), fclose ();
- X#endif
- X
- Xextern int errno;
- Xextern char *sys_errlist [];
- Xextern char *malloc ();
- Xextern void exit ();
- Xextern int atoi ();
- Xextern char *strdup ();
- X
- Xchar **filename;
- X /* The list of files from which we are to read email duplicate hands. */
- X
- Xint no_files;
- X /* The number of entries in the filename array. */
- X
- Xint coded_format;
- X /* A boolean variable which is true if the output should be written
- X in coded format. */
- X
- Xchar *player_name_of_interest = NULL;
- X /* If non-NULL, then we only consider boards which have been played by
- X the given player. */
- X
- X#define OUTPUT_SUMMARY 0
- X#define OUTPUT_EMAIL 1
- X#define OUTPUT_LOG 2
- X#define OUTPUT_ZLOG 3
- X#define OUTPUT_TOTALS 4
- X
- Xint output_mode = OUTPUT_SUMMARY;
- X /* Defines the output mode which will be used:
- X SUMMARY: Default. For each board, prints out a listing of how
- X each table bid the board and the score which was made.
- X EMAIL: Writes the set boards out in email duplicate format.
- X LOG: Writes each board and play record out in a detailed format
- X which shows the bidding and the playing.
- X ZLOG: Writes the boards out in a compact format developed by
- X Shangyou Zhang.
- X TOTALS: Writes the total score for each player.
- X */
- X
- Xint sort_by_matchpoints = 1;
- X /* A boolean flag which if true indicates that we will sort the play
- X records by matchpoints. Otherwise, we will sort them by IMPs. */
- X
- Xint two_column_output = 0;
- X /* If true, indicates that the output will consist of two columns
- X of score totals. */
- X
- Xint merge_only = 0;
- X /* Indicates that boards read from the second and succeeding files will
- X be merged into those already read. */
- X
- X/* The following structure is used for maintaining the array of player
- X scores.
- X*/
- Xtypedef struct Player_score_struct {
- X char *player_name;
- X float score; /* In MP or IMP scoring, the total of the individual
- X scores received by the player. */
- X float total_score; /* In MP scoring, the total number of match points
- X received by the player. */
- X float total_possible; /* In MP scoring, the total number of match points
- X which were available to the player. */
- X int total_boards; /* The total number of boards played by this player.*/
- X} Player_score;
- X
- X
- X
- Xvoid Abort (m)
- X char *m;
- X{
- X fprintf (stderr, "tally: %s\n", m);
- X exit (1);
- X}
- X
- Xstatic void Read_File (filename)
- X char *filename;
- X{
- X FILE *fp;
- X int status;
- X char error_buf[80];
- X
- X if (strcmp(filename, "-")) {
- X fp = fopen (filename, "r");
- X if (fp == NULL) {
- X sprintf (error_buf, "Error opening file %s: %s", filename,
- X sys_errlist[errno]);
- X Abort (error_buf);
- X }
- X } else
- X fp = stdin;
- X
- X status = Load_Email_Duplicate_File (fp);
- X if (status == 1) {
- X sprintf (error_buf, "%s is not an email duplicate file", filename);
- X Abort (error_buf);
- X } else if (status == -1) {
- X sprintf (error_buf, "Error reading file %s", filename);
- X Abort (error_buf);
- X }
- X
- X if (strcmp(filename, "-"))
- X fclose (fp);
- X}
- X
- Xstatic void Merge_File (filename)
- X char *filename;
- X{
- X FILE *fp;
- X int status;
- X char error_buf[80];
- X
- X if (strcmp(filename, "-")) {
- X fp = fopen (filename, "r");
- X if (fp == NULL) {
- X sprintf (error_buf, "Error opening file %s: %s", filename,
- X sys_errlist[errno]);
- X Abort (error_buf);
- X }
- X } else
- X fp = stdin;
- X
- X status = Merge_Email_Duplicate_File (fp, Unplayed_boards);
- X if (status == 1) {
- X sprintf (error_buf, "%s is not an email duplicate file", filename);
- X Abort (error_buf);
- X } else if (status == -1) {
- X sprintf (error_buf, "Error reading file %s", filename);
- X Abort (error_buf);
- X }
- X
- X if (strcmp(filename, "-"))
- X fclose (fp);
- X}
- X
- Xint Count_Total_Players (blist)
- X Board *blist;
- X{
- X Play_record *p;
- X int n;
- X
- X n = 0;
- X for (; blist != NULL; blist = blist->next)
- X for (p = blist->play_records; p != NULL; p = p->next)
- X n += 4;
- X
- X return (n);
- X}
- X
- Xint Compare_Score_List_Entries (p, q)
- X Player_score *p, *q;
- X{
- X if (p->score == q->score)
- X return (strcasecmp(p->player_name, q->player_name));
- X else if (p->score > q->score)
- X return (-1);
- X else
- X return (1);
- X}
- X
- Xint Compare_Score_List_Names (p, q)
- X Player_score *p, *q;
- X{
- X return(strcasecmp(p->player_name, q->player_name));
- X}
- X
- Xint Sort_and_Merge_Scores (scores, entries)
- X Player_score *scores; int entries;
- X{
- X int i, n;
- X
- X if (entries == 0)
- X return (0);
- X
- X qsort (scores, entries, sizeof(Player_score), Compare_Score_List_Names);
- X
- X n = 0;
- X for (i = 1; i < entries; i++)
- X if (strcasecmp(scores[n].player_name, scores[i].player_name)) {
- X n += 1;
- X bcopy (scores+i, scores+n, sizeof(Player_score));
- X } else {
- X scores[n].score += scores[i].score;
- X scores[n].total_score += scores[i].total_score;
- X scores[n].total_possible += scores[i].total_possible;
- X scores[n].total_boards += scores[i].total_boards;
- X }
- X
- X qsort (scores, n+1, sizeof(Player_score), Compare_Score_List_Entries);
- X return (n+1);
- X}
- X
- Xstatic int Tables_Played (b)
- X Board *b;
- X/* Returns the number of tables which have played the board b. */
- X{
- X int i = 0;
- X Play_record *p;
- X
- X for (p = b->play_records; p != NULL; p = p->next)
- X if (p->hand_completed) i++;
- X
- X return (i);
- X}
- X
- Xvoid Create_Matchpoint_List (blist, scores, no_scores)
- X Board *blist; Player_score **scores; int *no_scores;
- X{
- X int i, ns;
- X int no_players = Count_Total_Players (blist);
- X Player_score *score_list;
- X Board *b;
- X Play_record *p;
- X
- X score_list = *scores = (Player_score *)
- X malloc (no_players * sizeof(Player_score));
- X
- X ns = 0;
- X for (b = blist; b != NULL; b = b->next)
- X if ((b->scoring_mode == MP_SCORING) && (Tables_Played(b) >= 4))
- X for (p = b->play_records; p != NULL; p = p->next)
- X for (i = 0; i < 4; i++) {
- X score_list[ns].player_name = p->player_names[i];
- X score_list[ns].score = p->match_points[side_of(i)];
- X score_list[ns].total_possible = (float) (Tables_Played(b) - 1);
- X score_list[ns].total_score =
- X p->match_points[side_of(i)] * score_list[ns].total_possible;
- X score_list[ns].total_boards = 1;
- X ns += 1;
- X }
- X
- X *no_scores = Sort_and_Merge_Scores (score_list, ns);
- X}
- X
- Xvoid Create_IMP_List (blist, scores, no_scores)
- X Board *blist; Player_score **scores; int *no_scores;
- X{
- X int i, ns;
- X int no_players = Count_Total_Players (blist);
- X Player_score *score_list;
- X Board *b;
- X Play_record *p;
- X
- X score_list = *scores = (Player_score *)
- X malloc (no_players * sizeof(Player_score));
- X
- X ns = 0;
- X for (b = blist; b != NULL; b = b->next)
- X if ((b->scoring_mode == IMP_SCORING) && (Tables_Played(b) >= 4))
- X for (p = b->play_records; p != NULL; p = p->next)
- X for (i = 0; i < 4; i++) {
- X score_list[ns].player_name = p->player_names[i];
- X score_list[ns].score = p->imatch_points[side_of(i)];
- X score_list[ns].total_score = score_list[ns].score;
- X score_list[ns].total_possible = 0.0;
- X score_list[ns].total_boards = 1;
- X ns += 1;
- X }
- X
- X *no_scores = Sort_and_Merge_Scores (score_list, ns);
- X}
- X
- Xvoid Write_Match_Point_Totals (blist)
- X Board *blist;
- X{
- X Player_score *matchpoint_list;
- X int no_matchpoint_scores;
- X int i;
- X
- X Create_Matchpoint_List (blist, &matchpoint_list, &no_matchpoint_scores);
- X
- X printf ("%4s %-10s %12s %8s %8s\n", " ", "Name", "Match Points", "Percent",
- X "Boards");
- X
- X for (i = 0; i < no_matchpoint_scores; i++)
- X printf ("%4d %-10s %12.2f %8.1f %8d\n",
- X i+1,
- X matchpoint_list[i].player_name,
- X matchpoint_list[i].score,
- X 100.0 * matchpoint_list[i].total_score /
- X matchpoint_list[i].total_possible,
- X matchpoint_list[i].total_boards
- X );
- X}
- X
- Xvoid Write_IMP_Totals (blist)
- X Board *blist;
- X{
- X Player_score *IMP_list;
- X int no_imp_scores;
- X int i;
- X
- X Create_IMP_List (blist, &IMP_list, &no_imp_scores);
- X
- X printf ("%4s %-10s %8s %8s %8s\n",
- X " ", "Name", "IMPs", "Average", "Boards");
- X
- X for (i = 0; i < no_imp_scores; i++)
- X printf ("%4d %-10s %8.1f %8.1f %8d\n",
- X i+1,
- X IMP_list[i].player_name,
- X IMP_list[i].score,
- X IMP_list[i].total_score / ((float) IMP_list[i].total_boards),
- X IMP_list[i].total_boards);
- X}
- X
- Xvoid Write_Totals_in_Two_Columns (blist)
- X Board *blist;
- X{
- X Player_score *matchpoint_list, *IMP_list;
- X int no_matchpoint_scores, no_imp_scores, max_scores;
- X int i;
- X
- X Create_Matchpoint_List (blist, &matchpoint_list, &no_matchpoint_scores);
- X Create_IMP_List (blist, &IMP_list, &no_imp_scores);
- X
- X printf ("%4s %-10s %12s %4s %5s %-10s %12s %4s\n",
- X " ", "Name", "Match Points", "Pct", " ", "Name", "IMPs", "Avg");
- X
- X if (no_matchpoint_scores > no_imp_scores)
- X max_scores = no_matchpoint_scores;
- X else
- X max_scores = no_imp_scores;
- X
- X for (i = 0; i < max_scores; i++)
- X if ((i < no_matchpoint_scores) && (i < no_imp_scores))
- X printf ("%4d %-10s %12.2f %4d %5s %-10s %12.1f %4.1f\n",
- X i+1,
- X matchpoint_list[i].player_name,
- X matchpoint_list[i].score,
- X (int) (100.0 * matchpoint_list[i].total_score /
- X matchpoint_list[i].total_possible + 0.5),
- X " ",
- X IMP_list[i].player_name,
- X IMP_list[i].score,
- X IMP_list[i].total_score / ((float) IMP_list[i].total_boards)
- X );
- X
- X else if (i < no_matchpoint_scores)
- X printf ("%4d %-10s %12.2f %4d\n",
- X i+1,
- X matchpoint_list[i].player_name,
- X matchpoint_list[i].score,
- X (int) (100.0 * matchpoint_list[i].total_score /
- X matchpoint_list[i].total_possible + 0.5));
- X else
- X printf ("%4d %-10s %12s %10s %-10s %12.1f %4.1f\n",
- X i+1, " ", " ", " ",
- X IMP_list[i].player_name,
- X IMP_list[i].score,
- X IMP_list[i].total_score / ((float) IMP_list[i].total_boards)
- X );
- X
- X}
- X
- Xint Has_Played (b, n)
- X Board *b; char *n;
- X/* Returns true if the board b has been played by n. */
- X{
- X Play_record *p;
- X int i;
- X
- X for (p = b->play_records; p != NULL; p = p->next)
- X for (i = 0; i < 4; i++)
- X if (!strcasecmp(p->player_names[i], n))
- X return (1);
- X
- X return (0);
- X}
- X
- Xvoid main (argc, argv)
- X int argc; char *argv[];
- X{
- X int i, skip_count;
- X char error_buf [80];
- X Board *b;
- X Play_record *p;
- X Board *output_list, *output_list_tail;
- X
- X no_files = 0;
- X skip_count = 0;
- X filename = (char **) malloc ((argc - 1) * sizeof(char *));
- X for (i = 1; i < argc; i++) {
- X if (*argv[i] == '-') {
- X if(argv[i][1] == '\0')
- X filename[no_files++] = argv[i];
- X else if (argv[i][1] == 's') {
- X skip_count = atoi (argv[i]+2);
- X if (skip_count == 0) {
- X sprintf (error_buf, "Error in skip count: %s", argv[i]+2);
- X Abort (error_buf);
- X }
- X } else if (!strcmp(argv[i], "-c"))
- X output_mode = OUTPUT_EMAIL;
- X else if (!strcmp(argv[i], "-i"))
- X sort_by_matchpoints = 0;
- X else if (!strcmp(argv[i], "-l"))
- X output_mode = OUTPUT_LOG;
- X else if (!strcmp(argv[i], "-m"))
- X merge_only = 1;
- X else if (!strcmp(argv[i], "-p")) {
- X if (++i == argc)
- X Abort ("Player name must follow -p parameter");
- X player_name_of_interest = strdup(argv[i]);
- X } else if (!strcmp(argv[i], "-t"))
- X output_mode = OUTPUT_TOTALS;
- X else if (!strcmp(argv[i], "-tb")) {
- X output_mode = OUTPUT_TOTALS;
- X two_column_output = 1;
- X } else if (!strcmp(argv[i], "-z"))
- X output_mode = OUTPUT_ZLOG;
- X else if (!strcmp(argv[i], "-S"))
- X output_mode = OUTPUT_SUMMARY;
- X else
- X Abort ("Error in parameters");
- X } else
- X filename[no_files++] = argv[i];
- X }
- X
- X if (no_files < 1)
- X Abort ("At least one email file name must be given.");
- X
- X Read_File (filename[0]);
- X
- X for (i = 1; i < no_files; i++) {
- X if (merge_only)
- X Merge_File (filename[i]);
- X else
- X Read_File (filename[i]);
- X }
- X
- X for (i = 0; i < skip_count; i++)
- X b = Next_Unplayed_Board ();
- X
- X if (Unplayed_boards != NULL) {
- X output_list = output_list_tail = Unplayed_boards;
- X Unplayed_boards = output_list->next;
- X } else
- X output_list = output_list_tail = NULL;
- X
- X while (Unplayed_boards != NULL) {
- X if ((player_name_of_interest == NULL) ||
- X Has_Played (Unplayed_boards, player_name_of_interest)) {
- X output_list_tail->next = Unplayed_boards;
- X output_list_tail = output_list_tail->next;
- X }
- X Unplayed_boards = Unplayed_boards->next;
- X }
- X if (output_list != NULL)
- X output_list_tail->next = NULL;
- X else
- X Abort ("There are no boards on the output list.");
- X
- X for (b = output_list; b != NULL; b = b->next) {
- X for (p = b->play_records; p != NULL; p = p->next) {
- X Compute_contract (b, p);
- X Compute_MIMP_points (b, p);
- X }
- X Compute_Matchpoints (b);
- X Compute_Intl_Matchpoints (b);
- X if (sort_by_matchpoints)
- X Sort_play_records_by_matchpoints (b);
- X else
- X Sort_play_records_by_imps (b);
- X }
- X
- X switch (output_mode) {
- X case OUTPUT_SUMMARY:
- X for (b = output_list; b != NULL; b = b->next)
- X if (b->play_records != NULL)
- X Write_summary_of_play (stdout, b);
- X break;
- X
- X case OUTPUT_EMAIL:
- X Played_boards = output_list;
- X Write_Email_Duplicate_File (stdout);
- X break;
- X
- X case OUTPUT_LOG:
- X for (b = output_list; b != NULL; b = b->next)
- X for (p = b->play_records; p != NULL; p = p->next)
- X Write_hand (stdout, b, p);
- X break;
- X
- X case OUTPUT_ZLOG:
- X for (b = output_list; b != NULL; b = b->next)
- X for (p = b->play_records; p != NULL; p = p->next)
- X Write_hand_compactly (stdout, 1, b, p);
- X break;
- X
- X case OUTPUT_TOTALS:
- X if (two_column_output)
- X Write_Totals_in_Two_Columns (output_list);
- X else if (sort_by_matchpoints)
- X Write_Match_Point_Totals (output_list);
- X else
- X Write_IMP_Totals (output_list);
- X }
- X}
- END_OF_FILE
- if test 16133 -ne `wc -c <'oktally.c'`; then
- echo shar: \"'oktally.c'\" unpacked with wrong size!
- fi
- # end of 'oktally.c'
- fi
- echo shar: End of archive 10 \(of 14\).
- cp /dev/null ark10isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 14 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-