#include enum color {RD, PU, YL, BL, OR, GR, PI}; char *names[] = {"RD", "PU", "YL", "BL", "OR", "GR", "PI"}; color sq[135] = { PI, RD, PU, YL, BL, OR, GR, RD, PU, PI, YL, BL, OR, GR, RD, PU, YL, BL, PI, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, PI, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, PI, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PI, PU, YL, BL, OR, GR, RD, PU, PI, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU, YL, BL, OR, GR, RD, PU}; int tr[135][18]; // a one character description for each square char *sn = "S P L C P G ts t g s p Q s F"; int main(int argc, char **argv) { int exact = 0; if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e') { // avoid strcmp exact = 1; printf("Version that requires landing exactly on last purple square\n"); } else printf("Official version - you can advance past end purple square\n"); int i,j,k,l; // set the matrix to all 0 for(i=0; i<135; i++) for(j=0; j<18; j++) tr[i][j] = 0; // first rules - picking a single color moves to next square of same color // a doouble moves you to second square of that color for(i=0; i<135; i++) { // if you are on square i for(j=0; j<6; j++) { // and you get color j for (k=i+1; k<135 && sq[k] != color(j); k++) ; if (!exact) tr[i][j] = k < 135 ? k : 134; // if too far, go to last square else tr[i][j] = k < 135 ? k : i; // if too far, stay put // now find the second square of the same color for (l=k+1; l<135 && sq[l] != color(j); l++) ; if (!exact) tr[i][6+j] = l < 135 ? l : 134; // if too far, go to last else // just go as far as you can. tr[i][6+j] = l < 135 ? l : (k < 135 ? k : i); } } // picture cards move you right to that square for(i=0; i<135; i++) { tr[i][12] = 9; // Lord Licorice tr[i][13] = 18; // Candy cane tr[i][14] = 43; // Gumdrop mountain tr[i][15] = 75; // Grandma Nut tr[i][16] = 96; // Princess Lolly tr[i][17] = 104; // Queen Frostine } // Now the passes. 5->59, 34->47 for(i=0; i<135; i++) { for(j=0; j<12; j++) { if (tr[i][j] == 5) tr[i][j] = 59; if (tr[i][j] == 34) tr[i][j] = 47; } } // The stuck squares for(j=0;j<18; j++) { if (j != int(YL) && j-6 != int(YL)) // on square 48, only YL or DYL will work tr[48][j] = 48; if (j != int(BL) && j-6 != int(BL)) // square 86 sticks till BL or DBL tr[86][j] = 86; if (j != int(RD) && j-6 != int(RD)) //square 121 sticks until red tr[121][j] = 121; tr[134][j] = 134; // stay in the last square forever. } // print the transition matrix printf("Matrix describing the result of each card starting from each square:\n"); printf(" SQ CLR RD PU YL BL OR GR DRD DPU DYL DBL DOR DGR LoL CyC GuM GrN PrL QnF\n"); for(i=0; i<135; i++) { printf("%3d %2s:", i, names[int(sq[i])]); for(j=0; j<18; j++) printf("%4d", tr[i][j]); printf("\n"); } printf("\n"); // now the prob of getting each card. Assume 66 cards total; 8 each single colors // 2 each double colors, 1 each picture double prc[18]; for(j=0; j<6; j++) { prc[j] = 8.0/66.0; prc[6+j] = 2.0/66.0; prc[12+j] = 1.0/66.0; } // initial probability double pr[135]; for(i=0; i<135; i++) pr[i] = 0.0; pr[0] = 1.0; double winft = 0.0; // total odds of winning if you go first double winst = 0.0; // total odds if you go second. double avg[4] = {0.0,0.0,0.0,0.0}; // average game length for(k=0; pr[134] < 0.9999; k++) { // take turns until 99.9 chance of finishing printf("after turn %d: P=path, L=Lord Licorice, G=Gumdrop, t=target of path,\n",k); printf(" s=stuck, g=grandma, p=Princess Lolly, Q=Queen Frostine, F=finished\n"); for(i=0; i<135; i++) { char num[10]; sprintf(num, "%8.5f", pr[i]); if (i != 0) // skip labelling first since it can be 1.00000 num[1] = sn[i]; printf("%s", num); if ((i % 9) == 8) printf("\n"); } printf("\n"); double newpr[135]; for(i=0; i<135; i++) newpr[i] = 0.0; for(i=0; i<135; i++) { for(j=0; j<18; j++) { int ta = tr[i][j]; // target square newpr[ta] += pr[i]*prc[j]; // odds we land there } } // Do some specific calculatioms for the two person case double thist = newpr[134] - pr[134]; // odds of winning on this turn, if you go first = you win AND opponent takes at least as long double winf = thist*(1.0-pr[134]); winft += winf; // odds of winning if you go second (just double checking) double wins = thist*(1.0-newpr[134]); winst += wins; printf("odds that you win on this turn going first %7.5f, going second %7.5f\n", winf, wins); // Now do the calculations for the 1-4 player case double a = 1.0 - newpr[134]; // odds a single player not finished double p = 1.0 - pr[134]; // odds a single player not finished last turn double tt[4]; // odds of ending this turn tt[0] = p - a; tt[1] = p*p - a*a; tt[2] = p*p*p - a*a*a; tt[3] = p*p*p*p - a*a*a*a; printf("Odds finishing this turn with 1,2,3,4 players %7.5f %7.5f %7.5f %7.5f\n", tt[0], tt[1], tt[2], tt[3]); for(i=0; i<4; i++) avg[i] += tt[i]*(k+1); printf("Odds game is finished with 1,2,3,4 players %7.5f %7.5f %7.5f %7.5f\n", 1.0-a, 1.0-a*a, 1.0-a*a*a, 1.0-a*a*a*a); for(i=0; i<135; i++) pr[i] = newpr[i]; } printf("\nAverage game length with 1,2,3,4 players %7.5f %7.5f %7.5f %7.5f\n", avg[0], avg[1], avg[2], avg[3]); printf("Total odds first=%7.5f, second = %7.5f, ratio %f\n", winft, winst, winft/winst); return 0; }