void board_set_declarer (seat declarer) { board *b = CUR_BOARD; if (declarer == b->declarer) return; if (b->n_played_cards > 0) { board_statusbar (_("Cannot change declarer while cards are in play")); PROTECT_BEGIN; show_board(b, REDRAW_CONTRACT); PROTECT_END; return; } PROTECT_BEGIN; b->declarer = declarer; b->current_turn = seat_mod(declarer + 1); invalidate_dd_scores (b); show_board(b, REDRAW_CONTRACT | REDRAW_TRICKS | REDRAW_HANDS | REDRAW_NAMES | REDRAW_BOARD_LIST); PROTECT_END; }
void on_menu_file_web_activate () { board *b = CUR_BOARD; GString *url = g_string_new ("http://www.bridgebase.com/tools/handviewer.html?"); /* non-lin interface int h; g_string_append_printf (url, "d=%c", seat_lc[b->dealer]); g_string_append_printf (url, "&v=%c", vuln_lc[b->vuln[0] + 2 * b->vuln[1]]); g_string_append_printf (url, "&n=%d", b->n + 1); // TODO: real board number for (h = west; h <= south; h++) { if (*b->hand_name[h - 1]->str) g_string_append_printf (url, "&%cn=%s", seat_lc[h], b->hand_name[h - 1]->str); g_string_append_printf (url, "&%c=", seat_lc[h]); int s; for (s = club; s <= spade; s++) { g_string_append_printf (url, "%s", trump_str_char[s]); int c; for (c = s * 13 + 12; c >= (int)s * 13; c--) if (b->dealt_cards[c] == h) g_string_append_printf(url, "%c", rank_char(RANK(c))); } } if (b->n_bids) { g_string_append_printf (url, "&a="); int i; for (i = 0; i < b->n_bids; i++) g_string_append_printf (url, "%s", lin_bid (b->bidding[i])); } if (b->n_played_cards) { g_string_append_printf (url, "&p="); int i; for (i = 0; i < b->n_played_cards; i++) g_string_append_printf (url, "%s%c", trump_str_char[SUIT(b->played_cards[i])], rank_char(RANK(b->played_cards[i]))); if (b->played_cards[b->n_played_cards] = claim_rest) g_string_append_printf (url, "&c=%d", b->declarer_tricks); } */ int i; // TODO: merge with code from board_save_lin g_string_append_printf (url, "lin=pn|%s,%s,%s,%s|", b->hand_name[south-1]->str, b->hand_name[west-1]->str, b->hand_name[north-1]->str, b->hand_name[east-1]->str); g_string_append_printf (url, "st||"); g_string_append_printf (url, "md|%d%s|", seat_mod(b->dealer + 1), lin_card_string(b)); // TODO: end positions g_string_append_printf (url, "rh||"); g_string_append_printf (url, "ah|%s|", b->name->str); g_string_append_printf (url, "sv|%c|", b->vuln[0] ? (b->vuln[1] ? 'b' : 'n') : (b->vuln[1] ? 'e' : 'o')); for (i = 0; i < b->n_bids; i++) { g_string_append_printf (url, "mb|%s|", lin_bid(b->bidding[i])); if (b->alerts[i]) g_string_append_printf (url, "an|%s|", *b->alerts[i] ? b->alerts[i] : "!"); } for (i = 0; i < 52; i++) { if (i % 4 == 0) g_string_append_printf (url, "pg||"); card c = b->played_cards[i]; if (c < 0) break; if (c == claim_rest) { g_string_append_printf (url, "mc|%d|", b->declarer_tricks >= 0 ? b->declarer_tricks : 0); break; } g_string_append_printf (url, "pc|%c%c|", "CDHS"[SUIT(c)], rank_char(RANK(c))); } g_string_append_printf (url, "pg||\n"); printf ("%s\n", url->str); GError *error = NULL; gtk_show_uri (gdk_screen_get_default (), url->str, GDK_CURRENT_TIME, &error); if (error) { printf ("%s\n", error->message); g_error_free (error); } g_string_free (url, TRUE); }
static int board_parse_lin (window_board_t *win, char *line, FILE *f) { char *saveptr; char *tok; int card_nr = 0; setlocale (LC_NUMERIC, "C"); board *b = board_new (win->n_boards + 1); int board_filled = 0; board_window_append_board (win, b); /* global list of names for vugraph files */ char *name_arr[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int name_n = 0; /* IMP/MP list */ char *mp_str = NULL; char *mp_ptr = NULL; do { for (tok = sane_strtok_r(line, "|", &saveptr); tok; tok = STRTOK) { /* single hand */ if (!strcmp(tok, "pn")) { /* SWNE */ tok = STRTOK; char *nameptr; char *name = sane_strtok_r(tok, ",", &nameptr); int i = 0; do { if (i < 4) g_string_printf(b->hand_name[seat_mod (i++) - 1], "%s", name); if (name_n < 8) name_arr[name_n++] = strdup(name); } while ((name = sane_strtok_r(NULL, ",", &nameptr))); } else if (!strcmp(tok, "md")) { /* make deal */ tok = STRTOK; if (*tok == '0') { printf ("md|0| (keep deal) mode not supported\n"); continue; } if (board_filled) { /* start new board */ card_nr = 0; board_filled = 0; b = board_new (win->n_boards + 1); board_window_append_board (win, b); /* initialize player names, required for vugraph files */ int i; for (i = 0; i < 4; i++) { g_string_printf(b->hand_name[seat_mod (i) - 1], "%s", name_arr[i + (tok[0] == 'c' ? 4 : 0)]); } } char *c; seat se = south; suit su = spade; b->dealer = seat_mod(*tok - '0' - 1); for (c = tok + 1; *c; c++) { int i; if ((i = parse_suit(*c)) != -1) { su = i; } else if ((i = parse_rank_char(*c)) != -1) { if (add_card(b, se, (su * 13) + i) != 1) goto error; } else if (*c == ',') { se = seat_mod(se + 1); } else { printf("Parse error: %s", tok); goto error; } } // TODO: end positions deal_random(b); /* compute east hand */ board_filled = 1; /* consider this board finished on next qx token */ } else if (!strcmp(tok, "ah")) { /* board name */ g_string_printf(b->name, "%s", STRTOK); } else if (!strcmp(tok, "qx")) { /* board number, o1, c1, o2, ... */ tok = STRTOK; if (board_filled) { /* first token in new vugraph board */ card_nr = 0; board_filled = 0; b = board_new (win->n_boards + 1); board_window_append_board (win, b); /* initialize player names, required for vugraph files */ int i; for (i = 0; i < 4; i++) { g_string_printf(b->hand_name[seat_mod (i) - 1], "%s", name_arr[i + (tok[0] == 'c' ? 4 : 0)]); } } if (strlen (tok) >= 1) g_string_printf(b->name, "%s %s", tok[0] == 'c' ? _("Closed") : (tok[0] == 'o' ? _("Open") : _("Board")), tok + 1); /* for now assume qx|| is present in all lin files with mp|| */ if (mp_str) { // FIXME: skip leading boards that were kibitzed but not played // (01-26-08-3.lin) char *score = mp_ptr ? sane_strtok_r (NULL, ",", &mp_ptr) : sane_strtok_r (mp_str, ",", &mp_ptr); b->mp[0] = score ? round (strtod (score, NULL) * 100.0) : 0; score = sane_strtok_r (NULL, ",", &mp_ptr); b->mp[1] = score ? round (strtod (score, NULL) * 100.0) : 0; } } else if (!strcmp(tok, "sv")) { tok = STRTOK; switch (*tok) { case '0': case 'o': b->vuln[0] = 0; b->vuln[1] = 0; break; case 'n': b->vuln[0] = 1; b->vuln[1] = 0; break; case 'e': b->vuln[0] = 0; b->vuln[1] = 1; break; case 'b': b->vuln[0] = 1; b->vuln[1] = 1; break; default: printf("Unknown vulnerability: sv|%s|\n", tok); } } else if (!strcmp(tok, "mb")) { /* mb|-ppp1Cp1Hp3Np4Dp4Hppp| */ tok = STRTOK; char *bidp = tok; char *al = strchr (bidp, '!'); if (al) { *al++ = '\0'; } do { int bid = parse_bid(&bidp); if (bid == -1) { printf("Invalid bid %s/%s\n", tok, bidp); break; } board_append_bid(b, bid, 1); if (al) { board_set_alert (b, al); al = NULL; } } while (*bidp); } else if (!strcmp(tok, "an")) { tok = STRTOK; board_set_alert (b, !strcmp (tok, "!") ? "" : tok); /* filter uninteresting ! */ } else if (!strcmp(tok, "pc")) { int c = parse_card(tok = STRTOK); if (c == -1) { printf("Invalid card %s\n", tok); continue; } if (card_nr < 52) b->played_cards[card_nr++] = c; } else if (!strcmp(tok, "mc")) { tok = STRTOK; // TODO: store number of (total) claimed tricks b->played_cards[card_nr] = claim_rest; // no card_nr increment here b->declarer_tricks = atoi (tok); /* vugraph file */ } else if (!strcmp(tok, "vg")) { /* match title */ tok = STRTOK; //printf ("Match title: %s\n", tok); if (win->title) free (win->title); if (win->subtitle) free (win->subtitle); if (win->team1) free (win->team1); if (win->team2) free (win->team2); char *t_ptr; char *title = sane_strtok_r (tok, ",", &t_ptr); if (title) win->title = strdup (title); char *subtitle = sane_strtok_r (NULL, ",", &t_ptr); if (subtitle) win->subtitle = strdup (subtitle); sane_strtok_r (NULL, ",", &t_ptr); /* scoring I IMPs P MPs B board-a-match */ sane_strtok_r (NULL, ",", &t_ptr); /* first board nr */ sane_strtok_r (NULL, ",", &t_ptr); /* last board nr */ char *team1 = sane_strtok_r (NULL, ",", &t_ptr); if (team1) win->team1 = strdup (team1); sane_strtok_r (NULL, ",", &t_ptr); /* carry-over score team 1 */ char *team2 = sane_strtok_r (NULL, ",", &t_ptr); if (team2) win->team2 = strdup (team2); /* carry-over score team 2 */ } else if (!strcmp(tok, "pw")) { /* more player names */ tok = STRTOK; //printf ("Players: %s\n", tok); } else if (!strcmp(tok, "bn")) { /* board numbers */ tok = STRTOK; //printf ("Board numbers: %s\n", tok); } else if (!strcmp(tok, "rs")) { /* results */ tok = STRTOK; //printf ("Results: %s\n", tok); } else if (!strcmp(tok, "mp")) { /* MP result */ tok = STRTOK; //printf ("Scores: %s\n", tok); mp_str = strdup (tok); } else if (!strcmp(tok, "nt")) { /* comment (new text) */ tok = STRTOK; //printf ("Comment: %s\n", tok); } else if (!strcmp(tok, "at")) { /* add text */ STRTOK; } else if (!strcmp(tok, "cr") || !strcmp(tok, "cg") || !strcmp(tok, "cb")) { /* color */ STRTOK; } else if (!strcmp(tok, "hc") || !strcmp(tok, "lc") || !strcmp(tok, "hs") || !strcmp(tok, "ls")) { STRTOK; /* hilight card, suit */ } else if (!strcmp(tok, "pg")) { STRTOK; /* page break, e.g. after trick or comment */ } else if (!strcmp(tok, "rh")) { /* reset heading */ STRTOK; } else if (!strcmp(tok, "sk")) { /* set kibitzed */ STRTOK; } else if (!strcmp(tok, "st")) { /* small text */ STRTOK; } else if (!strcmp(tok, "up")) { /* undo play */ tok = STRTOK; } else if (!*tok || *tok == '\n' || *tok == '\r') { /* empty token, hopefully end of line */ } else { printf("Unknown token '%s|%s|'\n", tok, STRTOK); } } } while (fgets(line, 1023, f)); int ret = 1; int i; goto ok; error: ret = 0; ok: for (i = 0; i < name_n; i++) free (name_arr[i]); if (mp_str) free (mp_str); setlocale (LC_NUMERIC, ""); return ret; }
static int board_save_lin(window_board_t *win, char *filename) { int cur; FILE *f; if ((f = fopen (filename, "w")) == NULL) return 0; setlocale (LC_NUMERIC, "C"); if (win->title) { fprintf (f, "vg|%s,%s,%s,%d,%d,%s,,%s,|\n", win->title, win->subtitle ? win->subtitle : "", "P", // FIXME 1, win->n_boards, win->team1 ? win->team1 : "", win->team2 ? win->team2 : ""); fprintf (f, "rs|"); for (cur = 0; cur < win->n_boards; cur++) { board *b = win->boards[cur]; fprintf (f, "%s,", lin_contract (b)); if (cur != win->n_boards - 1) fprintf (f, ","); } fprintf (f, "|\n"); fprintf (f, "pw|"); for (cur = 0; cur < win->n_boards; cur++) { board *b = win->boards[cur]; fprintf (f, "%s,%s,%s,%s", b->hand_name[south-1]->str, b->hand_name[west-1]->str, b->hand_name[north-1]->str, b->hand_name[east-1]->str); if (cur != win->n_boards - 1) fprintf (f, ","); } fprintf (f, "|\n"); fprintf (f, "mp|"); for (cur = 0; cur < win->n_boards; cur++) { board *b = win->boards[cur]; if (b->mp[0] == 0 && b->mp[1] == 0) fprintf (f, "--,--"); else { if (b->mp[0]) fprintf (f, "%.2f", b->mp[0] / 100.0); fprintf (f, ","); if (b->mp[1]) fprintf (f, "%.2f", b->mp[1] / 100.0); } if (cur != win->n_boards - 1) fprintf (f, ","); } fprintf (f, "|\n"); fprintf (f, "bn|"); for (cur = 0; cur < win->n_boards; cur++) { //board *b = win->boards[cur]; fprintf (f, "%d", cur + 1); // TODO: original number? if (cur != win->n_boards - 1) fprintf (f, ","); } fprintf (f, "|\n"); fprintf (f, "pg||\n"); } for (cur = 0; cur < win->n_boards; cur++) { board *b = win->boards[cur]; int i; if (win->n_boards > 1) fprintf (f, "qx|o%d|", cur + 1); // TODO: open/closed, real board number fprintf (f, "pn|%s,%s,%s,%s|", b->hand_name[south-1]->str, b->hand_name[west-1]->str, b->hand_name[north-1]->str, b->hand_name[east-1]->str); fprintf (f, "st||"); fprintf (f, "md|%d%s|", seat_mod(b->dealer + 1), lin_card_string(b)); // TODO: end positions fprintf (f, "rh||"); fprintf (f, "ah|%s|", b->name->str); fprintf (f, "sv|%c|", b->vuln[0] ? (b->vuln[1] ? 'b' : 'n') : (b->vuln[1] ? 'e' : 'o')); for (i = 0; i < b->n_bids; i++) { fprintf (f, "mb|%s|", lin_bid(b->bidding[i])); if (b->alerts[i]) fprintf (f, "an|%s|", *b->alerts[i] ? b->alerts[i] : "!"); } for (i = 0; i < 52; i++) { if (i % 4 == 0) fprintf (f, "pg||"); card c = b->played_cards[i]; if (c < 0) break; if (c == claim_rest) { fprintf (f, "mc|%d|", b->declarer_tricks >= 0 ? b->declarer_tricks : 0); break; } fprintf (f, "pc|%c%c|", "CDHS"[SUIT(c)], rank_char(RANK(c))); } fprintf (f, "pg||\n"); } int ret = 1, e = 0; if (ferror (f)) { ret = 0; e = errno; } fclose(f); errno = e; setlocale (LC_NUMERIC, ""); return ret; }
void show_board (board *b, redraw_t redraw) { GtkWidget *w; GString *str = g_string_new(NULL); assert (b); if (redraw & REDRAW_BOARD_LIST) { board_window_rebuild_board_menu (win); window_options_board_list_populate (); } if (redraw & (REDRAW_TITLE | REDRAW_CONTRACT)) { g_string_printf(str, "Tenace - %s (%s)", b->name->str, contract_string_asc (b->level, b->trumps, b->declarer, b->doubled)); if (win->title) { g_string_append_printf (str, " - %s", win->title); if (win->subtitle) g_string_append_printf (str, " - %s", win->subtitle); if (win->team1 && win->team2) g_string_append_printf (str, _(" - %s vs. %s"), win->team1, win->team2); } else if (win->filename) { char *fname = win->filename; if (strrchr(fname, '/')) fname = strrchr(fname, '/') + 1; g_string_append_printf (str, " - %s", fname); } gtk_window_set_title(GTK_WINDOW(win->window), str->str); } if (redraw & REDRAW_CONTRACT) { w = get_widget ("label_board"); g_string_printf(str, "%s\n%s\n%s: %s\n%s: %s", b->name->str, contract_string(b->level, b->trumps, b->declarer, b->doubled), _("Dealer"), _(seat_str[b->dealer]), _("Vulnerable"), vuln_string(b)); gtk_label_set_text((GtkLabel*) w, str->str); char *dealermenu[] = { 0, "dealer_west1", "dealer_north1", "dealer_east1", "dealer_south1"}; w = get_widget (dealermenu[b->dealer]); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (w), TRUE); char *declarermenu[] = { 0, "declarer_west1", "declarer_north1", "declarer_east1", "declarer_south1"}; w = get_widget (declarermenu[b->declarer]); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (w), TRUE); char *levelmenu[] = { "level1" /* PASS */, "level1", "level2", "level3", "level4", "level5", "level6", "level7" }; w = get_widget (levelmenu[b->level]); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (w), TRUE); char *suitmenu[] = { "contract_clubs1", "contract_diamonds1", "contract_hearts1", "contract_spades1", "contract_no_trump1" }; w = get_widget (suitmenu[b->trumps]); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (w), TRUE); char *doublemenu[] = { "level_doubled0", "level_doubled1", "level_redoubled1" }; w = get_widget (doublemenu[b->doubled]); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (w), TRUE); char *vulnmenu[] = { "vuln_none", "vuln_ns", "vuln_ew", "vuln_all" }; w = get_widget (vulnmenu[2 * b->vuln[1] + b->vuln[0]]); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (w), TRUE); window_options_board_populate (); } if (redraw & REDRAW_NAMES) { w = get_widget ("label_west"); board_set_player_name (w, west, b->dealer == west, b->vuln[1], b->declarer == west, b->current_turn == west, b->hand_name[0]->str); w = get_widget ("label_north"); board_set_player_name (w, north, b->dealer == north, b->vuln[0], b->declarer == north, b->current_turn == north, b->hand_name[1]->str); w = get_widget ("label_east"); board_set_player_name (w, east, b->dealer == east, b->vuln[1], b->declarer == east, b->current_turn == east, b->hand_name[2]->str); w = get_widget ("label_south"); board_set_player_name (w, south, b->dealer == south, b->vuln[0], b->declarer == south, b->current_turn == south, b->hand_name[3]->str); window_options_board_populate (); } if (redraw & REDRAW_TRICKS) { w = get_widget ("label_tricks"); g_string_printf(str, _("NS: %d\nEW: %d"), b->tricks[0], b->tricks[1]); gtk_label_set_markup((GtkLabel*) w, str->str); } if (redraw & REDRAW_PAR) { w = get_widget ("par_label"); if (b->par_score == -1) { gtk_label_set_text (GTK_LABEL (w), ""); } else { char *par = par_label (b); gtk_label_set_markup(GTK_LABEL (w), par); free (par); } } if (redraw & REDRAW_HANDS) { int i, c; /* hands */ int next_card = b->played_cards[b->n_played_cards]; for (i = west; i <= south; i++) { for (c = 51; c >= 0; c--) { int has = i == b->cards[c]; int had = i == b->dealt_cards[c]; int color; if (seat_mask (i, win->show_hands)) color = has ? (c == next_card ? HAND_DISPLAY_HILIGHT_CARD : HAND_DISPLAY_CARD) : (had && win->show_played_cards ? HAND_DISPLAY_OLD_CARD : HAND_DISPLAY_NO_CARD); else color = HAND_DISPLAY_NO_CARD; hand_display_set_card (win->handdisp[i - 1], c, color); if (has && b->current_dd && b->current_dd->card_score[c] >= 0 && seat_mask (i, win->show_dd_scores)) hand_display_set_card_score (win->handdisp[i - 1], c, card_overtricks(b, c)); else hand_display_set_card_score (win->handdisp[i - 1], c, HAND_DISPLAY_NO_SCORE); } hand_display_set_card_score_neg (win->handdisp[i - 1], i % 2 != b->declarer % 2); hand_display_draw(GTK_WIDGET (win->handdisp[i - 1])); } /* table */ hand_display_table_reset_cards (win->table); if (b->n_played_cards) { int trick_start = b->n_played_cards - seat_mod(b->n_played_cards); for (i = trick_start; i < b->n_played_cards; i++) { card c = b->played_cards[i]; seat s = b->dealt_cards[c]; hand_display_table_set_card (win->table, i - trick_start, s, c); } } hand_display_draw(GTK_WIDGET (win->table)); line_entry_set_from_board(b); } g_string_free(str, TRUE); if (redraw & REDRAW_PLAY) window_play_update(b); if (redraw & REDRAW_BIDDING) { bidding_update (win, b, redraw & REDRAW_BIDDING_SCROLL); } }