git repos / blockattack-game

blame: source/code/puzzlehandler.cpp

normal view · raw

1899da11 sago007 2015-12-30 19:04 1
/*
1899da11 sago007 2015-12-30 19:04 2
===========================================================================
1899da11 sago007 2015-12-30 19:04 3
blockattack - Block Attack - Rise of the Blocks
1899da11 sago007 2015-12-30 19:04 4
Copyright (C) 2005-2015 Poul Sander
1899da11 sago007 2015-12-30 19:04 5
1899da11 sago007 2015-12-30 19:04 6
This program is free software: you can redistribute it and/or modify
1899da11 sago007 2015-12-30 19:04 7
it under the terms of the GNU General Public License as published by
1899da11 sago007 2015-12-30 19:04 8
the Free Software Foundation, either version 2 of the License, or
1899da11 sago007 2015-12-30 19:04 9
(at your option) any later version.
1899da11 sago007 2015-12-30 19:04 10
1899da11 sago007 2015-12-30 19:04 11
This program is distributed in the hope that it will be useful,
1899da11 sago007 2015-12-30 19:04 12
but WITHOUT ANY WARRANTY; without even the implied warranty of
1899da11 sago007 2015-12-30 19:04 13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1899da11 sago007 2015-12-30 19:04 14
GNU General Public License for more details.
1899da11 sago007 2015-12-30 19:04 15
1899da11 sago007 2015-12-30 19:04 16
You should have received a copy of the GNU General Public License
1899da11 sago007 2015-12-30 19:04 17
along with this program.  If not, see http://www.gnu.org/licenses/
1899da11 sago007 2015-12-30 19:04 18
1899da11 sago007 2015-12-30 19:04 19
Source information and contacts persons can be found at
1899da11 sago007 2015-12-30 19:04 20
http://blockattack.net
1899da11 sago007 2015-12-30 19:04 21
===========================================================================
1899da11 sago007 2015-12-30 19:04 22
*/
1899da11 sago007 2015-12-30 19:04 23
055218be sago007 2015-08-22 18:44 24
#include "puzzlehandler.hpp"
9f711750 Poul Sander 2024-05-12 12:35 25
#include "nlohmann/json.hpp"
055218be sago007 2015-08-22 18:44 26
#include <vector>
055218be sago007 2015-08-22 18:44 27
#include <iostream>
9f711750 Poul Sander 2024-05-12 12:35 28
#include <sstream>
055218be sago007 2015-08-22 18:44 29
#include "stats.h"
055218be sago007 2015-08-22 18:44 30
#include <physfs.h>         //Abstract file system. To use containers
5cdbc29b Poul Sander 2025-05-30 20:06 31
#include <fmt/core.h>
63acc19f sago007 2016-02-15 17:48 32
#include "sago/SagoMisc.hpp"
055218be sago007 2015-08-22 18:44 33
9f711750 Poul Sander 2024-05-12 12:35 34
using json = nlohmann::json;
9f711750 Poul Sander 2024-05-12 12:35 35
63acc19f sago007 2016-02-15 17:48 36
const int maxNrOfPuzzleStages = 50; //Maximum number of puzzle stages
63acc19f sago007 2016-02-15 17:48 37
055218be sago007 2015-08-22 18:44 38
static std::string puzzleSavePath;
055218be sago007 2015-08-22 18:44 39
static std::string puzzleName;              //The filename of
055218be sago007 2015-08-22 18:44 40
static std::vector<bool> puzzleCleared(maxNrOfPuzzleStages); //vector that tells if puzzle cleared
055218be sago007 2015-08-22 18:44 41
static std::vector<int> nrOfMovesAllowed(maxNrOfPuzzleStages);  //Moves to clear
055218be sago007 2015-08-22 18:44 42
static int puzzleLevels[maxNrOfPuzzleStages][6][12]; //Contains board layout;
055218be sago007 2015-08-22 18:44 43
static int nrOfPuzzles;    //How many are there actually?
055218be sago007 2015-08-22 18:44 44
52352a94 Poul Sander 2025-06-03 19:04 45
int PuzzleNumberOfMovesAllowed(size_t level) {
52352a94 Poul Sander 2025-06-03 19:04 46
	if (level >= nrOfMovesAllowed.size()) {
298835a8 Poul Sander 2025-05-31 20:49 47
		return -1;
298835a8 Poul Sander 2025-05-31 20:49 48
	}
055218be sago007 2015-08-22 18:44 49
	return nrOfMovesAllowed.at(level);
055218be sago007 2015-08-22 18:44 50
}
055218be sago007 2015-08-22 18:44 51
520e8c44 Poul Sander 2025-06-29 18:16 52
void PuzzleNumberOfMovesAllowedSet(size_t level, int numbler_of_moves) {
520e8c44 Poul Sander 2025-06-29 18:16 53
	if (level >= nrOfMovesAllowed.size()) {
520e8c44 Poul Sander 2025-06-29 18:16 54
		return;
520e8c44 Poul Sander 2025-06-29 18:16 55
	}
520e8c44 Poul Sander 2025-06-29 18:16 56
	nrOfMovesAllowed[level] = numbler_of_moves;
520e8c44 Poul Sander 2025-06-29 18:16 57
}
520e8c44 Poul Sander 2025-06-29 18:16 58
52352a94 Poul Sander 2025-06-03 19:04 59
int PuzzleGetBrick(size_t level, int x, int y) {
52352a94 Poul Sander 2025-06-03 19:04 60
	if (level >= maxNrOfPuzzleStages || x >= 6 || y >= 12 || x < 0 || y < 0) {
83b95511 Poul Sander 2025-05-30 19:54 61
		return -1;
83b95511 Poul Sander 2025-05-30 19:54 62
	}
055218be sago007 2015-08-22 18:44 63
	return puzzleLevels[level][x][y];
055218be sago007 2015-08-22 18:44 64
}
055218be sago007 2015-08-22 18:44 65
b8a4e6f1 Poul Sander 2025-06-21 10:31 66
void PuzzleSetBrick(size_t level, int x, int y, int brick) {
b8a4e6f1 Poul Sander 2025-06-21 10:31 67
	if (level >= maxNrOfPuzzleStages || x >= 6 || y >= 12 || x < 0 || y < 0) {
b8a4e6f1 Poul Sander 2025-06-21 10:31 68
		return;
b8a4e6f1 Poul Sander 2025-06-21 10:31 69
	}
b8a4e6f1 Poul Sander 2025-06-21 10:31 70
	if (brick >= 7) {
b8a4e6f1 Poul Sander 2025-06-21 10:31 71
		return;
b8a4e6f1 Poul Sander 2025-06-21 10:31 72
	}
b8a4e6f1 Poul Sander 2025-06-21 10:31 73
	puzzleLevels[level][x][y] = brick;
b8a4e6f1 Poul Sander 2025-06-21 10:31 74
}
b8a4e6f1 Poul Sander 2025-06-21 10:31 75
055218be sago007 2015-08-22 18:44 76
int PuzzleGetNumberOfPuzzles() {
055218be sago007 2015-08-22 18:44 77
	return nrOfPuzzles;
055218be sago007 2015-08-22 18:44 78
}
055218be sago007 2015-08-22 18:44 79
52352a94 Poul Sander 2025-06-03 19:04 80
bool PuzzleIsCleared(size_t level) {
055218be sago007 2015-08-22 18:44 81
	return puzzleCleared.at(level);
055218be sago007 2015-08-22 18:44 82
}
055218be sago007 2015-08-22 18:44 83
055218be sago007 2015-08-22 18:44 84
const std::string& PuzzleGetName() {
055218be sago007 2015-08-22 18:44 85
	return puzzleName;
055218be sago007 2015-08-22 18:44 86
}
055218be sago007 2015-08-22 18:44 87
055218be sago007 2015-08-22 18:44 88
void PuzzleSetName(const std::string& name) {
055218be sago007 2015-08-22 18:44 89
	puzzleName = name;
63acc19f sago007 2016-02-15 17:48 90
	puzzleSavePath = name + ".json.save";
63acc19f sago007 2016-02-15 17:48 91
}
63acc19f sago007 2016-02-15 17:48 92
63acc19f sago007 2016-02-15 17:48 93
void LoadClearData() {
63acc19f sago007 2016-02-15 17:48 94
	std::string readFileContent = sago::GetFileContent(puzzleSavePath.c_str());
5cdbc29b Poul Sander 2025-05-30 20:06 95
	if (readFileContent.length()) {
9f711750 Poul Sander 2024-05-12 12:35 96
		json j = json::parse(readFileContent);
9f711750 Poul Sander 2024-05-12 12:35 97
		try {
9f711750 Poul Sander 2024-05-12 12:35 98
			j.at("cleared").get_to(puzzleCleared);
1de972a7 Poul Sander 2025-11-11 20:23 99
		}
1de972a7 Poul Sander 2025-11-11 20:23 100
		catch (json::exception& e) {
9f711750 Poul Sander 2024-05-12 12:35 101
			std::cerr << "Failed to read \"" << puzzleSavePath << "\". File will be regenerated. Reason: " << e.what() << "\n";
9f711750 Poul Sander 2024-05-12 12:35 102
			puzzleCleared.clear();
63acc19f sago007 2016-02-15 17:48 103
		}
63acc19f sago007 2016-02-15 17:48 104
	}
63acc19f sago007 2016-02-15 17:48 105
	else {
63acc19f sago007 2016-02-15 17:48 106
		puzzleCleared.clear();
63acc19f sago007 2016-02-15 17:48 107
	}
63acc19f sago007 2016-02-15 17:48 108
	puzzleCleared.resize(nrOfPuzzles);
63acc19f sago007 2016-02-15 17:48 109
}
63acc19f sago007 2016-02-15 17:48 110
63acc19f sago007 2016-02-15 17:48 111
void SaveClearData() {
9f711750 Poul Sander 2024-05-12 12:35 112
	json j = json{ { "cleared", puzzleCleared } };
5cdbc29b Poul Sander 2025-05-30 20:06 113
	const std::string s = j.dump(4);
9f711750 Poul Sander 2024-05-12 12:35 114
	sago::WriteFileContent(puzzleSavePath.c_str(), s);
055218be sago007 2015-08-22 18:44 115
}
055218be sago007 2015-08-22 18:44 116
52352a94 Poul Sander 2025-06-03 19:04 117
void PuzzleSetClear(size_t Level) {
ecef5838 sago007 2015-11-24 20:01 118
	if (puzzleCleared[Level]==false) {
055218be sago007 2015-08-22 18:44 119
		Stats::getInstance()->addOne("puzzlesSolved");
acd79baf sago007 2015-11-22 19:37 120
	}
055218be sago007 2015-08-22 18:44 121
	puzzleCleared[Level] = true;
63acc19f sago007 2016-02-15 17:48 122
	SaveClearData();
055218be sago007 2015-08-22 18:44 123
}
055218be sago007 2015-08-22 18:44 124
055218be sago007 2015-08-22 18:44 125
/*Loads all the puzzle levels*/
ecef5838 sago007 2015-11-24 20:01 126
int LoadPuzzleStages( ) {
5cdbc29b Poul Sander 2025-05-30 20:06 127
	const std::string filename = fmt::format("puzzles/{}",puzzleName);
5cdbc29b Poul Sander 2025-05-30 20:06 128
	if (!PHYSFS_exists(filename.c_str())) {
5cdbc29b Poul Sander 2025-05-30 20:06 129
		std::cerr << "Warning: File not in blockattack.data: " << filename << "\n";
055218be sago007 2015-08-22 18:44 130
		return -1; //file doesn't exist
055218be sago007 2015-08-22 18:44 131
	}
5cdbc29b Poul Sander 2025-05-30 20:06 132
	const std::string fileContent = sago::GetFileContent(filename.c_str());
f1091f34 sago007 2016-03-25 20:56 133
	std::stringstream inFile(fileContent);
055218be sago007 2015-08-22 18:44 134
055218be sago007 2015-08-22 18:44 135
	inFile >> nrOfPuzzles;
acd79baf sago007 2015-11-22 19:37 136
	if (nrOfPuzzles>maxNrOfPuzzleStages) {
055218be sago007 2015-08-22 18:44 137
		nrOfPuzzles=maxNrOfPuzzleStages;
acd79baf sago007 2015-11-22 19:37 138
	}
c35c2b10 sago007 2016-03-31 18:49 139
	if (nrOfPuzzles < 0) {
c35c2b10 sago007 2016-03-31 18:49 140
		nrOfPuzzles = 0;
c35c2b10 sago007 2016-03-31 18:49 141
	}
c35c2b10 sago007 2016-03-31 18:49 142
	for (int k=0; k<nrOfPuzzles ; k++) {
c35c2b10 sago007 2016-03-31 18:49 143
		inFile >> nrOfMovesAllowed.at(k);
055218be sago007 2015-08-22 18:44 144
		for (int i=11; i>=0; i--)
ecef5838 sago007 2015-11-24 20:01 145
			for (int j=0; j<6; j++) {
055218be sago007 2015-08-22 18:44 146
				inFile >> puzzleLevels[k][j][i];
055218be sago007 2015-08-22 18:44 147
			}
055218be sago007 2015-08-22 18:44 148
	}
63acc19f sago007 2016-02-15 17:48 149
	LoadClearData();
055218be sago007 2015-08-22 18:44 150
	return 0;
63acc19f sago007 2016-02-15 17:48 151
}
dcdbd31f Poul Sander 2025-04-04 18:45 152
dcdbd31f Poul Sander 2025-04-04 18:45 153
int SavePuzzleStages() {
5cdbc29b Poul Sander 2025-05-30 20:06 154
	if (puzzleName.empty()) {
dcdbd31f Poul Sander 2025-04-04 18:45 155
		std::cerr << "Error: No puzzle name set. Cannot save.\n";
dcdbd31f Poul Sander 2025-04-04 18:45 156
		return -1;
dcdbd31f Poul Sander 2025-04-04 18:45 157
	}
dcdbd31f Poul Sander 2025-04-04 18:45 158
	std::string fileContent = std::to_string(nrOfPuzzles) + "\n";
dcdbd31f Poul Sander 2025-04-04 18:45 159
	for (int k=0; k<nrOfPuzzles ; k++) {
dcdbd31f Poul Sander 2025-04-04 18:45 160
		fileContent += std::to_string(nrOfMovesAllowed.at(k)) + "\n";
dcdbd31f Poul Sander 2025-04-04 18:45 161
		for (int i=11; i>=0; i--)
dcdbd31f Poul Sander 2025-04-04 18:45 162
			for (int j=0; j<6; j++) {
dcdbd31f Poul Sander 2025-04-04 18:45 163
				fileContent += std::to_string(puzzleLevels[k][j][i]) + " ";
dcdbd31f Poul Sander 2025-04-04 18:45 164
			}
dcdbd31f Poul Sander 2025-04-04 18:45 165
		fileContent += "\n";
dcdbd31f Poul Sander 2025-04-04 18:45 166
	}
dcdbd31f Poul Sander 2025-04-04 18:45 167
	sago::WriteFileContent(((std::string)("puzzles/"+puzzleName)).c_str(), fileContent);
dcdbd31f Poul Sander 2025-04-04 18:45 168
	return 0;
0305b768 Poul Sander 2025-07-17 14:08 169
}
0305b768 Poul Sander 2025-07-17 14:08 170
0305b768 Poul Sander 2025-07-17 14:08 171
void EditorRemovePuzzle(size_t level) {
0305b768 Poul Sander 2025-07-17 14:08 172
	if (level >= nrOfPuzzles) {
0305b768 Poul Sander 2025-07-17 14:08 173
		return;
0305b768 Poul Sander 2025-07-17 14:08 174
	}
0305b768 Poul Sander 2025-07-17 14:08 175
	//Shift all puzzles up.
0305b768 Poul Sander 2025-07-17 14:08 176
	memmove(puzzleLevels[level], puzzleLevels[level+1], sizeof(puzzleLevels[0])*(nrOfPuzzles-level-1));
0305b768 Poul Sander 2025-07-17 14:08 177
	nrOfPuzzles--;
0305b768 Poul Sander 2025-07-17 14:08 178
}
0305b768 Poul Sander 2025-07-17 14:08 179
0305b768 Poul Sander 2025-07-17 14:08 180
void EditorAddPuzzle(size_t level) {
e48b9d40 Poul Sander 2025-10-07 20:08 181
	if (nrOfPuzzles >= maxNrOfPuzzleStages) {
0305b768 Poul Sander 2025-07-17 14:08 182
		return;
0305b768 Poul Sander 2025-07-17 14:08 183
	}
1de972a7 Poul Sander 2025-11-11 20:23 184
	if (level >= maxNrOfPuzzleStages) {
e48b9d40 Poul Sander 2025-10-07 20:08 185
		level = 0;
e48b9d40 Poul Sander 2025-10-07 20:08 186
	}
e48b9d40 Poul Sander 2025-10-07 20:08 187
	memmove( puzzleLevels[level+1], puzzleLevels[level], sizeof(puzzleLevels[0])*(maxNrOfPuzzleStages-level-1) );
0305b768 Poul Sander 2025-07-17 14:08 188
	nrOfPuzzles++;
0305b768 Poul Sander 2025-07-17 14:08 189
	for (size_t i = 0; i < 6; i++) {
0305b768 Poul Sander 2025-07-17 14:08 190
		for (size_t j =0; j < 12; j++) {
0305b768 Poul Sander 2025-07-17 14:08 191
			puzzleLevels[level][i][j] = -1;
0305b768 Poul Sander 2025-07-17 14:08 192
		}
0305b768 Poul Sander 2025-07-17 14:08 193
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 194
}
4ebb3d36 Poul Sander 2025-10-05 11:55 195
4ebb3d36 Poul Sander 2025-10-05 11:55 196
void EditorResizePuzzleNumber(size_t number_of_puzzles) {
4ebb3d36 Poul Sander 2025-10-05 11:55 197
	if (number_of_puzzles > 50) {
4ebb3d36 Poul Sander 2025-10-05 11:55 198
		number_of_puzzles = 50;
4ebb3d36 Poul Sander 2025-10-05 11:55 199
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 200
	nrOfPuzzles = number_of_puzzles;
4ebb3d36 Poul Sander 2025-10-05 11:55 201
}
1970-01-01 00:00 202