Created
November 8, 2015 04:30
-
-
Save danvk/0e298b7bbb80f5fceaf1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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