Skip to content

Instantly share code, notes, and snippets.

@danvk
Created November 8, 2015 04:30
Show Gist options
  • Save danvk/0e298b7bbb80f5fceaf1 to your computer and use it in GitHub Desktop.
Save danvk/0e298b7bbb80f5fceaf1 to your computer and use it in GitHub Desktop.
/**
* Usage:
* ./next-plays DEAL_PBN <C|D|H|S|N> <N|S|E|W> play1 play2 ...
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "../include/dll.h"
#include "../src/PBN.h"
const char* USAGE = "./next-plays DEAL_PBN <C|D|H|S|N> <N|S|E|W> play1 play2 ...";
#define SPADES 0
#define HEARTS 1
#define DIAMONDS 2
#define CLUBS 3
#define NOTRUMP 4
#define NORTH 0
#define EAST 1
#define SOUTH 2
#define WEST 3
struct Play {
int suit; // SPADES, HEARTS, DIAMONDS, CLUBS
int rank; // 2-14
};
int NEXT_PLAYER[] = {EAST, SOUTH, WEST, NORTH};
void bad_trump(const char* trump) {
fprintf(stderr, "Invalid trump: '%s' (expected N, S, H, D, C)\n", trump);
exit(1);
}
int parse_trump(const char* trump) {
if (strlen(trump) != 1) {
bad_trump(trump);
}
char c = toupper(trump[0]);
if (c == 'N') return NOTRUMP;
if (c == 'S') return SPADES;
if (c == 'H') return HEARTS;
if (c == 'D') return DIAMONDS;
if (c == 'C') return CLUBS;
bad_trump(trump);
return 0; // unreachable
}
void bad_player(const char* player) {
fprintf(stderr, "Invalid player: '%s' (expected N, S, E, W)\n", player);
exit(1);
}
int parse_player(const char* player) {
if (strlen(player) != 1) {
bad_player(player);
}
char c = toupper(player[0]);
if (c == 'N') return NORTH;
if (c == 'S') return SOUTH;
if (c == 'E') return EAST;
if (c == 'W') return WEST;
bad_player(player);
return 0; // unreachable
}
void bad_play(const char* play) {
fprintf(stderr, "Invalid play: '%s' (expected, e.g. 2D, 9C, TH, AS)\n", play);
exit(1);
}
Play parse_play(const char* play) {
if (strlen(play) != 2) {
bad_play(play);
}
Play p;
switch (toupper(play[0])) {
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
p.rank = play[0] - '0';
break;
case 'T': p.rank = 10; break;
case 'J': p.rank = 11; break;
case 'Q': p.rank = 12; break;
case 'K': p.rank = 13; break;
case 'A': p.rank = 14; break;
default:
bad_play(play);
}
switch (toupper(play[1])) {
case 'H': p.suit = HEARTS; break;
case 'S': p.suit = HEARTS; break;
case 'D': p.suit = DIAMONDS; break;
case 'C': p.suit = CLUBS; break;
default:
bad_play(play);
}
return p;
}
unsigned short int dbitMapRank[16] =
{
0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020,
0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000
};
unsigned char dcardRank[16] =
{
'x', 'x', '2', '3', '4', '5', '6', '7',
'8', '9', 'T', 'J', 'Q', 'K', 'A', '-'
};
unsigned char dcardSuit[5] = { 'S', 'H', 'D', 'C', 'N' };
unsigned char dcardHand[4] = { 'N', 'E', 'S', 'W' };
void equals_to_string(int equals, char * res) {
int p = 0;
int m = equals >> 2;
for (int i = 15; i >= 2; i--)
{
if (m & static_cast<int>(dbitMapRank[i]))
res[p++] = static_cast<char>(dcardRank[i]);
}
res[p] = 0;
}
void PrintFut(const futureTricks& fut) {
int n = 0;
printf("[");
for (int i = 0; i < fut.cards; i++) {
char res[15] = "";
printf("%s\n {\"suit\": \"%c\", \"rank\": \"%c\", \"score\": %d}",
n++ ? "," : "",
dcardSuit[ fut.suit[i] ],
dcardRank[ fut.rank[i] ],
fut.score[i]);
equals_to_string(fut.equals[i], res);
int len = static_cast<int>(strlen(res));
for (int j = 0; j < len; j++) {
char rank = res[j];
printf("%s\n {\"suit\": \"%c\", \"rank\": \"%c\", \"score\": %d}",
n++ ? "," : "",
dcardSuit[ fut.suit[i] ],
rank,
fut.score[i]);
}
}
printf("\n]\n");
}
int main(int argc, char** argv) {
if (argc < 4) {
fprintf(stderr, "Not enough arguments. Usage:\n\n %s\n", USAGE);
return 1;
}
char *deal_pbn = argv[1],
*suit_str = argv[2],
*declarer_str = argv[3];
int declarer = parse_player(declarer_str);
int player = NEXT_PLAYER[declarer];
deal dl;
dl.trump = parse_trump(suit_str);
dl.first = player;
int res = ConvertFromPBN(deal_pbn, dl.remainCards);
if (res != RETURN_NO_FAULT) {
char error[80];
ErrorMessage(res, error);
fprintf(stderr, "ConvertFromPBN failed: %d %s\n", res, error);
return 1;
}
// previously-played cards on this trick
dl.currentTrickSuit[0] = 0;
dl.currentTrickRank[0] = 0;
dl.currentTrickSuit[1] = 0;
dl.currentTrickRank[1] = 0;
dl.currentTrickSuit[2] = 0;
dl.currentTrickRank[2] = 0;
Play plays[52];
int num_plays = argc - 4;
for (int i = 0; i < num_plays; i++) {
plays[i] = parse_play(argv[i + 4]);
}
for (int i = 0; i < num_plays; i++) {
const Play& p = plays[i];
unsigned int cards_in_suit = dl.remainCards[player][p.suit];
unsigned int card = 1 << p.rank;
if ((cards_in_suit & card) == 0) {
fprintf(stderr, "Player %d cannot play %s\n", player, argv[i + 4]);
exit(1);
}
dl.remainCards[player][p.suit] -= card;
dl.currentTrickSuit[i] = p.suit;
dl.currentTrickRank[i] = p.rank;
player = NEXT_PLAYER[player];
}
// ... apply the plays to the PBN
// strcpy(dlPBN.remainCards, deal_pbn);
int target = -1;
int solutions = 3;
int mode = 0;
SetMaxThreads(0);
printf("dl.first: %d\n", dl.first);
printf("dl.trump: %d\n", dl.trump);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
printf("dl.remainCards[%d][%d]: 0x%x\n", i, j, dl.remainCards[i][j]);
}
}
for (int i = 0; i < 3; i++) {
printf("dl.currentTrickSuit[%d]: %d\n", i, dl.currentTrickSuit[i]);
printf("dl.currentTrickRank[%d]: %d\n", i, dl.currentTrickRank[i]);
}
futureTricks fut;
res = SolveBoard(dl, target, solutions, mode, &fut, 0);
if (res != RETURN_NO_FAULT) {
char error[80];
ErrorMessage(res, error);
fprintf(stderr, "SolveBoard failed: %d %s\n", res, error);
return 1;
}
// PrintPBNHand
PrintFut(fut);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment