/* the scrambling functions use this impossibly unfortunate representation for the board. We calculate it here. NULL on error */ unsigned char* formatted_solution(struct puzzle_t* puz) { if (puz == NULL) return NULL; int w = puz_width_get(puz); int h = puz_height_get(puz); int board_sz = w*h; unsigned char* sol = puz_solution_get(puz); int i,size = 0; for(i=0; i < board_sz; i++) { if(sol[i] != '.') size++; } unsigned char* out = calloc(size+1, sizeof(unsigned char)); int j,index = 0; for(i=0; i < w; i++) { for(j=0; j < h; j++) { if (sol[j*h + i] != '.') { out[index] = sol[j*h + i]; index++; } } } out[size] = 0; return out; }
/** * puz_extras_set - set the puzzle's extras grid * * @puz: a pointer to the struct puzzle_t to write to (required) * @val: a pointer to the string to st the value to (required) * * returns NULL on error, else a pointer to the struct's copy of the string */ unsigned char * puz_extras_set(struct puzzle_t *puz, unsigned char *val) { if(NULL == puz || NULL == val) return NULL; free(puz->gext); int size = puz_width_get(puz) * puz_height_get(puz); puz->gext = calloc(size+1, sizeof (unsigned char)); memcpy(puz->gext, val, size); puz->gext[size] = 0; return puz->gext; }
/** * puz_clear_rusr - clear out a puzzle's rusr memory * * @puz: a pointer to the struct puzzle_t to clear rusr from (required) * * This function clears out the rusr memory. Specifically, it frees * all rusr table entries, the rusrstorage, and sets the number of * rtbl entries to 0. * * Note that any pointers you have to rusr entries will become invalid * after calling this function. * * Returns -1 on error, 0 on success. */ int puz_clear_rusr(struct puzzle_t *puz) { int i; if (NULL == puz || NULL == puz->rusr) return -1; int bd_sz = puz_width_get(puz) * puz_height_get(puz); for(i = 0; i < bd_sz; i++) free(puz->rusr[i]); free(puz->rusr); puz->rusr = NULL; puz->rusr_sz = 0; puz->rusr_cksum = 0; puz->calc_rusr_cksum = 0; return 0; }
int unformat_unlocked_sol(struct puzzle_t* puz, unsigned char* formatted) { if (puz == NULL || formatted == NULL) return -1; int w = puz_width_get(puz); int h = puz_height_get(puz); unsigned char* sol = puz_solution_get(puz); int i,j; int index = 0; // XXX this could fail if we calculated something poorly (but shouldn't) for(i=0; i < w; i++) { for(j=0; j < h; j++) { if (sol[j*h + i] != '.') { sol[j*h + i] = formatted[index]; index++; } } } return 0; }
/** * puz_size - calculate the size of a puzzle as a PUZ file * * @puz: a pointer to the struct puzzle_t to size * * This function is used to calculate the size of the PUZ file for a * given puzzle. * * Return value: -1 on error, a positive (non-zero) integer size on * success. */ int puz_size(struct puzzle_t *puz) { int i, sz; if(!puz) return -1; int board_size = puz_width_get(puz) * puz_height_get(puz); sz = 0x34; // header sz += board_size; sz += board_size; sz += Sstrlen(puz_title_get(puz)) + 1; // title sz += Sstrlen(puz_author_get(puz)) + 1; // author sz += Sstrlen(puz_copyright_get(puz)) + 1; // copyright for(i = 0; i < puz_clue_count_get(puz); i++) { sz += Sstrlen(puz_clue_get(puz, i)) + 1; } if(puz->notes_sz) sz += puz->notes_sz; sz += 1; // NULL terminated if (puz_has_rebus(puz)) { sz += 4; // GRBS sz += 2; // board size sz += 2; // checksum sz += board_size; // rebus grid sz += 1; // NULL sz += 4; // RTBL sz += 2; // size sz += 2; // checksum for (i = 0; i < puz_rebus_count_get(puz); i++) { sz += Sstrlen(puz_rtbl_get(puz, i)) + 1; } sz += 1; // NULL } if (puz_has_timer(puz)) { sz += 4; //LTIM sz += 4; // size and checksum sz += Sstrlen(puz->ltim); //timer string sz += 1; // NULL } if (puz_has_extras(puz)) { sz += 4; // GEXT sz += 2; // size sz += 2; // checksum sz += board_size; // extras grid sz += 1; // NULL } if (puz_has_rusr(puz)) { sz += 4; // RUSR sz += 2; // size sz += 2; // checksum sz += puz->rusr_sz; //data sz++; // NULL } return sz; }
/* ************************************************************************ Main **** */ int main(int argc, char *argv[]) { int fd; void *base; struct stat buf; int i, sz; struct puzzle_t p; char *destfile = NULL; if(argc < 2) { printf("Usage: %s <file.puz>\n", argv[0]); return 0; } if(argc == 3) { destfile = argv[2]; printf("Will regurgitate into %s as binary after reading\n", argv[2]); } i = stat(argv[1], &buf); if(i != 0) { perror("stat:"); return -1; } sz = buf.st_size; if(!(fd = open(argv[1], O_RDONLY))) { perror("open:"); return -1; } if(!(base = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0))) { perror("mmap"); return -1; } if(NULL == puz_load(&p, PUZ_FILE_UNKNOWN, base, sz)) { printf("There was an error loading the puzzle file. See above for details\n"); return -1; } puz_cksums_calc(&p); i = puz_cksums_check(&p); if(i != 00) { printf("*** Error: %d errors in checksums.\n", i); return -1; } const char* separator = "myuniquelibpuzseparator"; printf("%s", separator); printf("%s", puz_title_get(&p)); printf("%s", separator); printf("%s", puz_author_get(&p)); printf("%s", separator); printf("%s", puz_notes_get(&p)); printf("%s", separator); printf("%d", puz_width_get(&p)); printf("%s", separator); printf("%d", puz_height_get(&p)); printf("%s", separator); printf("%s", puz_grid_get(&p)); printf("%s", separator); printf("%s", puz_solution_get(&p)); int numClues = puz_clue_count_get(&p); int clueNum = 0; for (; clueNum < numClues; clueNum++) { printf("%s", separator); printf("%s", puz_clue_get(&p, clueNum)); } return 0; }