1 /*
2 ===========================================================================
3 blockattack - Block Attack - Rise of the Blocks
4 Copyright (C) 2005-2015 Poul Sander
5 
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see http://www.gnu.org/licenses/
18 
19 Source information and contacts persons can be found at
20 http://blockattack.net
21 ===========================================================================
22 */
23 
24 #include "puzzlehandler.hpp"
25 #include <vector>
26 #include <iostream>
27 #include "stats.h"
28 #include <physfs.h>         //Abstract file system. To use containers
29 #include "cereal/cereal.hpp"
30 #include "cereal/types/vector.hpp"
31 #include "cereal/archives/json.hpp"
32 #include "sago/SagoMisc.hpp"
33 
34 const int maxNrOfPuzzleStages = 50; //Maximum number of puzzle stages
35 
36 static std::string puzzleSavePath;
37 static std::string puzzleName;              //The filename of
38 static std::vector<bool> puzzleCleared(maxNrOfPuzzleStages); //vector that tells if puzzle cleared
39 static std::vector<int> nrOfMovesAllowed(maxNrOfPuzzleStages);  //Moves to clear
40 static int puzzleLevels[maxNrOfPuzzleStages][6][12]; //Contains board layout;
41 static int nrOfPuzzles;    //How many are there actually?
42 
PuzzleNumberOfMovesAllowed(int level)43 int PuzzleNumberOfMovesAllowed(int level) {
44 	return nrOfMovesAllowed.at(level);
45 }
46 
PuzzleGetBrick(int level,int x,int y)47 int PuzzleGetBrick(int level, int x, int y) {
48 	return puzzleLevels[level][x][y];
49 }
50 
PuzzleGetNumberOfPuzzles()51 int PuzzleGetNumberOfPuzzles() {
52 	return nrOfPuzzles;
53 }
54 
PuzzleIsCleared(int level)55 bool PuzzleIsCleared(int level) {
56 	return puzzleCleared.at(level);
57 }
58 
PuzzleGetName()59 const std::string& PuzzleGetName() {
60 	return puzzleName;
61 }
62 
PuzzleSetName(const std::string & name)63 void PuzzleSetName(const std::string& name) {
64 	puzzleName = name;
65 	puzzleSavePath = name + ".json.save";
66 }
67 
LoadClearData()68 void LoadClearData() {
69 	std::string readFileContent = sago::GetFileContent(puzzleSavePath.c_str());
70 	if (readFileContent.length() > 0) {
71 		std::stringstream ss(readFileContent);
72 		{
73 			try {
74 				cereal::JSONInputArchive archive(ss);
75 				archive(cereal::make_nvp("cleared", puzzleCleared));
76 			}
77 			catch (cereal::Exception& e) {
78 				std::cerr << "Failed to read \"" << puzzleSavePath << "\". File will be regenerated. Reason: " << e.what() << "\n";
79 				puzzleCleared.clear();
80 			}
81 		}
82 	}
83 	else {
84 		puzzleCleared.clear();
85 	}
86 	puzzleCleared.resize(nrOfPuzzles);
87 }
88 
SaveClearData()89 void SaveClearData() {
90 	std::stringstream ss;
91 	{
92 		cereal::JSONOutputArchive archive(ss);
93 		archive(cereal::make_nvp("cleared", puzzleCleared));
94 	}
95 	sago::WriteFileContent(puzzleSavePath.c_str(), ss.str());
96 }
97 
PuzzleSetClear(int Level)98 void PuzzleSetClear(int Level) {
99 	if (puzzleCleared[Level]==false) {
100 		Stats::getInstance()->addOne("puzzlesSolved");
101 	}
102 	puzzleCleared[Level] = true;
103 	SaveClearData();
104 }
105 
106 /*Loads all the puzzle levels*/
LoadPuzzleStages()107 int LoadPuzzleStages( ) {
108 	if (!PHYSFS_exists(((std::string)("puzzles/"+puzzleName)).c_str())) {
109 		std::cerr << "Warning: File not in blockattack.data: " << ("puzzles/"+puzzleName) << "\n";
110 		return -1; //file doesn't exist
111 	}
112 	std::string fileContent = sago::GetFileContent(((std::string)("puzzles/"+puzzleName)).c_str());
113 	std::stringstream inFile(fileContent);
114 
115 	inFile >> nrOfPuzzles;
116 	if (nrOfPuzzles>maxNrOfPuzzleStages) {
117 		nrOfPuzzles=maxNrOfPuzzleStages;
118 	}
119 	if (nrOfPuzzles < 0) {
120 		nrOfPuzzles = 0;
121 	}
122 	for (int k=0; k<nrOfPuzzles ; k++) {
123 		inFile >> nrOfMovesAllowed.at(k);
124 		for (int i=11; i>=0; i--)
125 			for (int j=0; j<6; j++) {
126 				inFile >> puzzleLevels[k][j][i];
127 			}
128 	}
129 	LoadClearData();
130 	return 0;
131 }
132