void UnLoadSolutionRebus(Puzzle * puz) { for (Square * square = puz->GetGrid().First(); square != NULL; square = square->Next()) { square->SetSolutionRebus(string_t(1, char_t(square->GetPlainSolution()))); } }
// Rollback changes void UnLoadCHKD(Puzzle * puz) { for (Square * square = puz->GetGrid().First(); square != NULL; square = square->Next()) { square->RemoveFlag(FLAG_CORRECT); } }
// Rollback changes void UnLoadGEXT(Puzzle * puz) { for (Square * square = puz->GetGrid().First(); square != NULL; square = square->Next()) { square->SetFlag(FLAG_CLEAR); } }
bool LoadGEXT(Puzzle * puz, const std::string & data) { std::istringstream stream(data); istream_wrapper f(stream); std::string::const_iterator it = data.begin(); for (Square * square = puz->GetGrid().First(); square != NULL; square = square->Next()) { square->SetFlag(f.ReadChar()); } if (! f.CheckEof()) return false; return true; }
//------------------------------------------------------------------------------ // RUSR (user rebus grid) //------------------------------------------------------------------------------ bool LoadRUSR(Puzzle * puz, const std::string & data) { // RUSR is a series of strings (each nul-terminated) that represent any // user grid rebus entries. If the rebus is a symbol, it is enclosed // in '[' ']'. std::istringstream stream(data); istream_wrapper f(stream); for (Square * square = puz->GetGrid().First(); square != NULL; square = square->Next()) { std::string str = f.ReadString(); if (str.empty()) continue; square->SetText(decode_puz(str)); } if (! f.CheckEof()) return false; return true; }
bool LoadSolutionRebus(Puzzle * puz, const std::string & table, const std::string & grid) { // NB: In the grid rebus section (GRBS), the index is 1 greater than the // index in the rebus table section (RTBL). if (grid.size() != puz->GetGrid().GetWidth() * puz->GetGrid().GetHeight()) return false; // Read the rebus table (RTBL) // Format: index ':' string ';' // - Index is a number, padded to two digits with a space if needed. std::map<unsigned char, std::string> rebusTable; std::istringstream tstream(table); istream_wrapper table_stream(tstream); for (;;) { std::string key; // Read the index try { key = table_stream.ReadString(':'); } catch(std::ios::failure &) { break; } int index = atoi(key.c_str()); if (index == 0 && key != " 0") return false; // The index value in the rebus-table section is 1 less than the // index in the grid-rebus, so we need add 1 here. ++index; std::string value = table_stream.ReadString(';'); rebusTable[static_cast<unsigned char>(index)] = value; } if (! table_stream.CheckEof()) return false; // Set the grid rebus solution std::istringstream gstream(grid); istream_wrapper grid_stream(gstream); for (Square * square = puz->GetGrid().First(); square != NULL; square = square->Next()) { const unsigned char index = grid_stream.ReadChar(); if (index > 0) { // Look for this index in the rebus table std::map<unsigned char, std::string>::const_iterator it; it = rebusTable.find(index); if (it == rebusTable.end()) return false; // Don't overwrite the plain solution square->SetSolutionRebus(decode_puz(it->second)); } } if (! grid_stream.CheckEof()) return false; return true; }
void LoadPuz(Puzzle * puz, const std::string & filename, void * /* dummy */) { std::ifstream stream(filename.c_str(), std::ios::in | std::ios::binary); if (stream.fail()) throw FileError(filename); istream_wrapper f(stream); const unsigned short c_primary = f.ReadShort(); if (strcmp(f.ReadString(12).c_str(), "ACROSS&DOWN") != 0) throw FileTypeError("puz"); const unsigned short c_cib = f.ReadShort(); unsigned char c_masked[8]; f.ReadCharArray(c_masked, 8); // Version is "[major].[minor]\0" // We can read puzzles of 1.[anything] std::string versionstr = f.ReadString(4); if (versionstr[0] != '1' || ! isdigit(versionstr[2])) throw LoadError("Unknown puz version."); const unsigned short version = 10 + versionstr[2] - 0x30; f.Skip(2); // 1 unknown short const unsigned short c_grid = f.ReadShort(); f.Skip(2 * 6); // 6 noise shorts const unsigned char width = f.ReadChar(); const unsigned char height = f.ReadChar(); const unsigned short num_clues = f.ReadShort(); const unsigned short grid_type = f.ReadShort(); const unsigned short grid_flag = f.ReadShort(); puz->GetGrid().SetCksum(c_grid); puz->GetGrid().SetType(grid_type); puz->GetGrid().SetFlag(grid_flag); puz->GetGrid().SetSize(width, height); // Read user text and solution std::string solution = f.ReadString(width * height); std::string text = f.ReadString(width * height); // Set the grid's solution and text std::string::iterator sol_it = solution.begin(); std::string::iterator text_it = text.begin(); for (Square * square = puz->GetGrid().First(); square != NULL; square = square->Next()) { // Solution if (*sol_it == '.' || *sol_it == ':' && puz->IsDiagramless()) square->SetSolution(puz::Square::Black); else if (*sol_it == '-') square->SetSolution(puz::Square::Blank); else square->SetSolution(decode_puz(std::string(1, *sol_it))); ++sol_it; // Text if (square->IsBlack() && ! puz->IsDiagramless()) square->SetText(puz::Square::Black); else if (*text_it == '-' || *text_it == 0) square->SetText(puz::Square::Blank); else if (puz->IsDiagramless() && (*text_it == '.' || *text_it == ':')) { // Black squares in a diagramless puzzle. if (*text_it == '.') square->SetText(puz::Square::Black); else if (*text_it == ':') square->SetText(puz::Square::Blank); } else { square->SetText(decode_puz(std::string(1, *text_it))); if (islower(*text_it)) square->AddFlag(FLAG_PENCIL); } ++text_it; } assert(sol_it == solution.end() && text_it == text.end()); puz->NumberGrid(); // General puzzle info puz->SetTitle(decode_puz(f.ReadString())); puz->SetAuthor(decode_puz(f.ReadString())); puz->SetCopyright(decode_puz(f.ReadString())); // Clues std::vector<string_t> clues; clues.reserve(num_clues); // Save unaltered clues for the checksums std::vector<std::string> cksum_clues; cksum_clues.reserve(num_clues); for (size_t i = 0; i < num_clues; ++i) { cksum_clues.push_back(f.ReadString()); clues.push_back(escape_xml(decode_puz(cksum_clues.back()))); } puz->SetAllClues(clues); // Notes std::string notes = f.ReadString(); puz->SetNotes(escape_xml(decode_puz(notes))); puz->SetOk(true); // Try to load the extra sections (i.e. GEXT, LTIM, etc). try { LoadSections(puz, f); } catch (std::ios::failure &) { // EOF here doesn't matter. } // Don't even bother with the checksums, since we check the validity // of the puzzle anyways }
bool Scrambler::ScrambleSolution(unsigned short key_int) { bool ok = m_grid.GetWidth() > 0 && m_grid.GetHeight() > 0; ok = ok && (m_grid.m_flag & FLAG_NO_SOLUTION) == 0; assert(m_grid.First() != NULL); if (! ok) return false; if (key_int == 0) key_int = MakeKey(); assert(1000 <= key_int && key_int <= 9999); // Read the key into an array of single digits unsigned char key[4]; key[0] = int(key_int / 1000) % 10; key[1] = int(key_int / 100) % 10; key[2] = int(key_int / 10) % 10; key[3] = int(key_int / 1) % 10; std::string solution = GetSolutionDown(); unsigned short cksum = Checksummer::cksum_region(solution, 0); if (cksum == 0) return false; size_t length = solution.length(); // Don't scramble really small puzzles if(length < 12) return 0; // Do the scrambling for (int i = 0; i < 4; ++i) { std::string scramble_part; for (size_t j = 0; j < length; ++j) { char letter = solution[j] + key[j % 4]; // Make sure the letter is capital if (letter > 90) letter -= 26; // Range for capital letters assert(isupper(letter)); scramble_part.push_back(letter); } assert(scramble_part.length() == length); scramble_part = ShiftString(scramble_part, key[i]); assert(scramble_part.length() == length); scramble_part = ScrambleString(scramble_part); assert(scramble_part.length() == length); solution = scramble_part; } // Save the scrambled solution to the puzzle file std::string::iterator it = solution.begin(); for (Square * square = m_grid.First(); square != NULL; square = square->Next(DOWN)) { if (square->IsBlack()) continue; // Make sure we preserve any rebus in the solution if (! square->HasSolutionRebus()) square->SetSolution(decode_puz(std::string(1, *it))); else square->SetPlainSolution(*it); ++it; } assert(it == solution.end()); m_grid.m_flag |= FLAG_SCRAMBLED; m_grid.m_cksum = cksum; m_grid.m_key = key_int; return true; }