static int _generate_corners(uint8_t * cornersOut) { Perm * p = rand_perm(8); srand(time(NULL)); int i; for (i = 0; i < 8; i++) { int piece = p->map[i]; int coset = cube_perm_corner_coset(piece, i); int perm = rand() % 3; if (perm != 0) perm += 3; // perms are 0, 4, and 5 int orientation = symmetry_operation_compose(coset, perm); cornersOut[i] = piece | (orientation << 4); } while (!validate_corner_orientation(cornersOut)) { int sym = (cornersOut[7] >> 4) & 7; sym = symmetry_operation_compose(sym, 4); cornersOut[7] &= 0xf; cornersOut[7] |= (sym << 4); } int parity = perm_parity(p); perm_free(p); return parity; }
static void _generate_edges(uint8_t * edgesOut, int cornerParity) { Perm * p = rand_perm(12); if (perm_parity(p) != cornerParity) { rand_change_parity(p); } uint16_t edgeOrientations = 0; int i; for (i = 0; i < 12; i++) { int piece = p->map[i]; int s1, s2; cube_perm_edge_symmetries(piece, i, &s1, &s2); int sym = rand() % 2 == 0 ? s1 : s2; edgesOut[i] = piece | (sym << 4); if (i == 11) { if (!validate_edges(edgesOut)) { int newSym = sym == s1 ? s2 : s1; edgesOut[i] = piece | (newSym << 4); } } } perm_free(p); }
static char *new_game_desc(game_params *params, random_state *rs, char **aux, int interactive) { int gap, n, i, x; int x1, x2, p1, p2, parity; int *tiles, *used; char *ret; int retlen; n = params->w * params->h; tiles = snewn(n, int); used = snewn(n, int); for (i = 0; i < n; i++) { tiles[i] = -1; used[i] = FALSE; } gap = random_upto(rs, n); tiles[gap] = 0; used[0] = TRUE; /* * Place everything else except the last two tiles. */ for (x = 0, i = n-1; i > 2; i--) { int k = random_upto(rs, i); int j; for (j = 0; j < n; j++) if (!used[j] && (k-- == 0)) break; assert(j < n && !used[j]); used[j] = TRUE; while (tiles[x] >= 0) x++; assert(x < n); tiles[x] = j; } /* * Find the last two locations, and the last two pieces. */ while (tiles[x] >= 0) x++; assert(x < n); x1 = x; x++; while (tiles[x] >= 0) x++; assert(x < n); x2 = x; for (i = 0; i < n; i++) if (!used[i]) break; p1 = i; for (i = p1+1; i < n; i++) if (!used[i]) break; p2 = i; /* * Determine the required parity of the overall permutation. * This is the XOR of: * * - The chessboard parity ((x^y)&1) of the gap square. The * bottom right counts as even. * * - The parity of n. (The target permutation is 1,...,n-1,0 * rather than 0,...,n-1; this is a cyclic permutation of * the starting point and hence is odd iff n is even.) */ parity = ((X(params, gap) - (params->w-1)) ^ (Y(params, gap) - (params->h-1)) ^ (n+1)) & 1; /* * Try the last two tiles one way round. If that fails, swap * them. */ tiles[x1] = p1; tiles[x2] = p2; if (perm_parity(tiles, n) != parity) { tiles[x1] = p2; tiles[x2] = p1; assert(perm_parity(tiles, n) == parity); } /* * Now construct the game description, by describing the tile * array as a simple sequence of comma-separated integers. */ ret = NULL; retlen = 0; for (i = 0; i < n; i++) { char buf[80]; int k; k = sprintf(buf, "%d,", tiles[i]); ret = sresize(ret, retlen + k + 1, char); strcpy(ret + retlen, buf); retlen += k; } ret[retlen-1] = '\0'; /* delete last comma */ sfree(tiles); sfree(used); return ret; }