In fact I didn’t even look at my old code (though disbelievers may be forgiven).
Please PM me with any bug reports. 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
* Cribbage hand-counting, without warrantee.
* Copyleft (C) 2011 Septimus G. Stevens, VII
*
* Since all you high-level guys will have
* built-in combination generators,
* I'll kluge a 'general-purpose' one of my own,
* brutish but adequate here.
*/
static char Cntbit[] = {
#define BB1(x) x, x+1, x+1, x+2
#define BB2(x) BB1(x), BB1(x+1), BB1(x+1), BB1(x+2)
#define BB3(x) BB2(x), BB2(x+1), BB2(x+1), BB2(x+2)
BB3(0), BB3(1), BB3(1), BB3(2),
};
#define Bitcnt(x) (Cntbit[(x) & 0xff] + Cntbit[(x) >> 8])
/* Loop thru K-combinations of n */
#define For_combos(c,k,n) \
for (c = 0; c < 1<<n; c++) if (Cntbit[c] == k)
static char Elem1[] = {
#define EROW(x) x, 0, 1, 0, 2, 0, 1, 0
#define ERO2(x) EROW(x), EROW(3), EROW(4), EROW(3)
ERO2(-9), ERO2(5), EROW(6), EROW(5),
ERO2(7), ERO2(5), EROW(6), EROW(5),
};
#define E1(x) (Elem1[(x) & 0xff] >= 0 \
? Elem1[(x) & 0xff] : 8 + Elem1[(x) >> 8])
#define E2(x) E1((x) & (x) - 1)
#define E3(x) E2((x) & (x) - 1)
#define E4(x) E3((x) & (x) - 1)
#define E5(x) E4((x) & (x) - 1)
/* General card manipulations */
char Cardnames[] = "A23456789TJQK";
char Suitnames[] = "SHDC";
#define ch2ix(s, c) (strchr(s, c) - (s))
#define CN2CI(s) (ch2ix(Cardnames, s[0]) \
+ 13 * ch2ix(Suitnames, s[1]))
#define CI2R(i) ((i) % 13)
#define CI2S(i) ((i) / 13)
#define R2K(r) ((r) < 9 ? (r)+1 : 10)
int Hand[6], Nhand[5];
#define NI2R(i) CI2R(Nhand*)
#define NI2S(i) CI2S(Nhand*)
#define N2K(i) R2K(NI2R(i))
#define NI2M(i) (1 << NI2R(i))
/* Count the cribbage hand Nhand */
int gscore(void)
{
int combo, i, s1, ss, msk, thisc, totc, score;
/* We can save a line of code by doing Runs first */
#define ISRUN(m) ! ((m) & (m) + (1 << E1(m)))
/* Runs of five */
msk = NI2M(0) | NI2M(1) | NI2M(2) | NI2M(3) | NI2M(4);
score = (Bitcnt(msk) == 5 && ISRUN(msk)) ? 5 : 0;
/* Runs of four */
if (! score) For_combos(combo, 4, 5) {
msk = NI2M(E1(combo)) | NI2M(E2(combo))
| NI2M(E3(combo)) | NI2M(E4(combo));
if (Bitcnt(msk) == 4 && ISRUN(msk)) score += 4;
}
/* Runs of three */
if (! score) For_combos(combo, 3, 5) {
msk = NI2M(E1(combo)) | NI2M(E2(combo)) | NI2M(E3(combo));
if (Bitcnt(msk) == 3 && ISRUN(msk)) score += 3;
}
/* Flush and Nobs */
s1 = NI2S(0);
ss = NI2S(4);
for (i = 0; i < 4; i++) {
if (NI2R(i) == 10 && NI2S(i) == ss)
score += 1;
if (NI2S(i) != s1)
s1 = 9;
}
if (s1 < 9)
score += 4 + (s1 == ss);
/* Pairs */
For_combos(combo, 2, 5)
if (NI2R(E1(combo)) == NI2R(E2(combo)))
score += 2;
/* Fifteens, brutish */
totc = N2K(0) + N2K(1) + N2K(2) + N2K(3) + N2K(4);
if (totc == 15) score += 2;
For_combos(combo, 2, 5) {
thisc = N2K(E1(combo)) + N2K(E2(combo));
if (thisc == 15) score += 2;
if (thisc == totc - 15) score += 2;
}
For_combos(combo, 1, 5)
if (N2K(E1(combo)) == totc - 15) score += 2;
if (1) return score;
printf("The score of ");
for (i = 0; i < 5; i++)
printf("%c%c ",
Cardnames[NI2R(i)],
Suitnames[NI2S(i)]);
printf(" is %d
", score);
return score;
}
double mscore(int j1, int j2)
{
int i, k, m;
double totscore = 0;
for (i = k = 0; i < 6; i++)
if (i != j1 && i != j2)
Nhand[k++] = Hand*;
for (k = 0; k < 52; k++) {
Nhand[4] = k;
for (m = 0; m < 6; m++)
if (Hand[m] == k) break;
if (m == 6)
totscore += gscore();
}
return totscore / 46.0;
}
int main(int argc, char **argv)
{
int i, combo, j1, j2, bj1, bj2;
double tscore, bestsco = -1;
if (argc != 7) exit(1);
for (i = 0; i < 6; i++)
Hand* = CN2CI(argv[i + 1]);
For_combos(combo, 2, 6) {
j1 = E1(combo);
j2 = E2(combo);
tscore = mscore(j1, j2);
if (tscore > bestsco)
bestsco = tscore, bj1 = j1, bj2 = j2;
}
printf("From hand ");
for (i = 0; i < 6; i++)
printf("%c%c ",
Cardnames[CI2R(Hand*)],
Suitnames[CI2S(Hand*)]);
printf(", the best discards are ");
printf("%c%c ",
Cardnames[CI2R(Hand[bj1])],
Suitnames[CI2S(Hand[bj1])]);
printf("%c%c
",
Cardnames[CI2R(Hand[bj2])],
Suitnames[CI2S(Hand[bj2])]);
}