diff --git a/puz/formats/ipuz/load_ipuz.cpp b/puz/formats/ipuz/load_ipuz.cpp index 9a54a0ad..e8452116 100644 --- a/puz/formats/ipuz/load_ipuz.cpp +++ b/puz/formats/ipuz/load_ipuz.cpp @@ -309,6 +309,10 @@ bool ipuzParser::DoLoadPuzzle(Puzzle * puz, json::Value * root) } }); } + else + { + puz->GetGrid().SetFlag(FLAG_NO_SOLUTION); + } // User grid if (doc->Contains(puzT("saved"))) diff --git a/puz/formats/jpz/load_jpz.cpp b/puz/formats/jpz/load_jpz.cpp index f991ff3c..8d7859e4 100644 --- a/puz/formats/jpz/load_jpz.cpp +++ b/puz/formats/jpz/load_jpz.cpp @@ -226,6 +226,7 @@ bool jpzParser::DoLoadPuzzle(Puzzle * puz, xml::document & doc) } // Grid cells + bool has_solution = false; xml::node cell = RequireChild(grid_node, "cell"); for (; cell; cell = cell.next_sibling("cell")) { @@ -260,7 +261,10 @@ bool jpzParser::DoLoadPuzzle(Puzzle * puz, xml::document & doc) else // type == puzT("letter") || type == puzT("clue") { square->SetMissing(false); - square->SetSolution(GetAttribute(cell, "solution")); + string_t solution = GetAttribute(cell, "solution"); + square->SetSolution(solution); + if (!solution.empty()) + has_solution = true; square->SetText(GetAttribute(cell, "solve-state")); if (type == puzT("clue")) square->SetAnnotation(true); @@ -314,6 +318,9 @@ bool jpzParser::DoLoadPuzzle(Puzzle * puz, xml::document & doc) image.child_value("encoded-image")); } } + + if (!has_solution) + grid.SetFlag(FLAG_NO_SOLUTION); } // Words diff --git a/puz/formats/jpz/save_jpz.cpp b/puz/formats/jpz/save_jpz.cpp index cb7eda70..3342fb3b 100644 --- a/puz/formats/jpz/save_jpz.cpp +++ b/puz/formats/jpz/save_jpz.cpp @@ -61,8 +61,6 @@ void SaveJpz(Puzzle * puz, const std::string & filename, void * /* dummy */) if (grid.IsScrambled()) throw ConversionError("Jpz does not support scrambled puzzles"); - if (! grid.HasSolution()) - throw ConversionError("Jpz does not support puzzles without a solution"); if (grid.GetType() == TYPE_DIAGRAMLESS) throw ConversionError("Can't save a diagramless puzzle as jpz."); @@ -88,16 +86,21 @@ void SaveJpz(Puzzle * puz, const std::string & filename, void * /* dummy */) xml::node actions = settings.append_child("actions"); actions.append_attribute("buttons-layout") = "below"; - actions.append_child("check").append_attribute("label") = "Check"; - actions.append_child("reveal-letter").append_attribute("label") = - "Reveal Letter"; - actions.append_child("reveal-word").append_attribute("label") = - "Reveal Word"; actions.append_child("revert").append_attribute("label") = "Clear All"; - actions.append_child("solution").append_attribute("label") = "Solution"; - xml::node completion = settings.append_child("completion"); - completion.append_attribute("only-if-correct") = "true"; + if (grid.HasSolution()) { + actions.append_child("check").append_attribute("label") = "Check"; + actions.append_child("reveal-letter").append_attribute("label") = + "Reveal Letter"; + actions.append_child("reveal-word").append_attribute("label") = + "Reveal Word"; + actions.append_child("solution").append_attribute("label") = "Solution"; + completion.append_attribute("only-if-correct") = "true"; + } + else { + completion.append_attribute("only-if-correct") = "false"; + } + string_t message = puz->GetMeta(puzT("completion")); if (message.empty()) { message = puzT("Congratulations, you have solved the puzzle!"); @@ -172,8 +175,9 @@ void SaveJpz(Puzzle * puz, const std::string & filename, void * /* dummy */) { if (square->IsAnnotation()) cell.append_attribute("type") = "clue"; - cell.append_attribute("solution") = - encode_utf8(square->GetSolution()).c_str(); + if (grid.HasSolution()) + cell.append_attribute("solution") = + encode_utf8(square->GetSolution()).c_str(); if (square->HasNumber()) cell.append_attribute("number") = encode_utf8(square->GetNumber()).c_str(); diff --git a/src/XGridCtrl.cpp b/src/XGridCtrl.cpp index ad70e4c8..9d385975 100644 --- a/src/XGridCtrl.cpp +++ b/src/XGridCtrl.cpp @@ -340,24 +340,24 @@ XGridCtrl::UnscrambleSolution(unsigned short key) // Helper for IsCorrect and GetStats CorrectStatus GetCorrectStatus(const puz::Grid * grid, bool correct) { - // We *can* test scrambled puzzles! Not sure why I didn't think of - // this before. (Inspired by Alex Boisvert: - // http://alexboisvert.com/software.html#check) - if (correct) + if (!grid->HasSolution()) + { + return UNCHECKABLE_PUZZLE; + } + else if (correct) { return CORRECT_PUZZLE; } else if (grid->IsScrambled()) { + // We *can* test scrambled puzzles! Not sure why I didn't think of + // this before. (Inspired by Alex Boisvert: + // http://alexboisvert.com/software.html#check) if (grid->CheckScrambledGrid()) return CORRECT_PUZZLE; else return INCORRECT_PUZZLE; } - else if (! grid->HasSolution()) - { - return UNCHECKABLE_PUZZLE; - } else { return INCORRECT_PUZZLE; @@ -403,7 +403,7 @@ XGridCtrl::GetStats(GridStats * stats) const if (square->IsBlank()) { ++stats->blank; - if (square->IsSolutionBlank()) + if (m_grid->HasSolution() && square->IsSolutionBlank()) ++stats->blank_correct; } // If the puzzle is correct so far, and without blanks (that do