1 //------------------------------------------------------------------------------
2 // emNetwalkModel.h
3 //
4 // Copyright (C) 2010-2012,2014,2018 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20 
21 #ifndef emNetwalkModel_h
22 #define emNetwalkModel_h
23 
24 #ifndef emRecFileModel_h
25 #include <emCore/emRecFileModel.h>
26 #endif
27 
28 
29 class emNetwalkModel : public emRecFileModel, private emStructRec
30 {
31 
32 public:
33 
34 	static emRef<emNetwalkModel> Acquire(
35 		emContext & context, const emString & name, bool common=true
36 	);
37 
38 	virtual const char * GetFormatName() const;
39 
40 	int GetWidth() const;
41 	int GetHeight() const;
42 
43 	bool IsBorderless() const;
44 	bool IsNoFourWayJunctions() const;
45 	int GetComplexity() const;
46 	bool IsDigMode() const;
47 
48 	void SetAutoMark(bool autoMark, bool saveFile=true);
49 	bool IsAutoMark() const;
50 
51 	bool IsFinished() const;
52 	int GetPenaltyPoints() const;
53 
54 	int GetPiece(int x, int y) const;
55 	enum {
56 		PF_EAST   =(1<<0),
57 		PF_SOUTH  =(1<<1),
58 		PF_WEST   =(1<<2),
59 		PF_NORTH  =(1<<3),
60 		PF_SOURCE =(1<<4),
61 		PF_TARGET =(1<<5),
62 		PF_FILLED =(1<<6),
63 		PF_TOUCHED=(1<<7),
64 		PF_MARKED =(1<<8),
65 		PF_BLOCKED=(1<<9),
66 		PF_CONMASK=PF_EAST|PF_SOUTH|PF_WEST|PF_NORTH
67 	};
68 
69 	void TrySetup(
70 		int width, int height, bool borderless, bool noFourWayJunctions,
71 		int complexity, bool digMode, bool autoMark, bool saveFile=true
72 	);
73 
74 	void MarkOrUnmark(int x, int y, bool saveFile=true);
75 	void UnmarkAll(bool saveFile=true);
76 
77 	void Rotate(int x, int y, int angle, bool saveFile=true);
78 	void RotateLeft(int x, int y, bool saveFile=true);
79 	void RotateRight(int x, int y, bool saveFile=true);
80 
81 	void Scroll(int dx, int dy, bool saveFile=true);
82 
83 protected:
84 
85 	emNetwalkModel(emContext & context, const emString & name);
86 	virtual ~emNetwalkModel();
87 
88 	virtual bool TryContinueLoading();
89 
90 	virtual bool Cycle();
91 
92 private:
93 
94 	int GetPiece(int index) const;
95 	void SetPiece(int index, int piece);
96 	void XorPiece(int index, int flags);
97 	void OrPiece(int index, int flags);
98 	void AndPiece(int index, int flags);
99 
100 	int GetNeighborIndex(int index, int angle) const;
101 	bool IsConnected(int index, int angle) const;
102 	void Connect(int index, int angle);
103 
104 	void Invent();
105 	void Shuffle();
106 	void Fill();
107 	void Dig(bool reset);
108 
109 	void DoAutoMark();
110 
111 	static int RawRotate(int piece, int angle);
112 
113 	class Solver : public emUncopyable {
114 	public:
115 		Solver(emNetwalkModel * model);
116 		~Solver();
117 		bool IsUniqueSolution();
118 	private:
119 		struct Piece {
120 			int OrigDirs;
121 			int Dirs;
122 			int Placed;
123 			int Group;
124 			int NextPiece;
125 			int FrontRing;
126 			int Neighbor[4];
127 		};
128 		struct Group {
129 			int FirstPiece;
130 			int PieceCount;
131 			int OpenCount;
132 		};
133 		struct TBEntry {
134 			int * Ptr; // NULL for start-mark
135 			int Val;
136 		};
137 		bool CheckPiece(int i) const;
138 		void PlacePiece(int i);
139 		bool UpdateGroups(int i);
140 		int FindAndGetBestNext();
141 		void TBClear();
142 		void TBStart();
143 		void TBSet(int & rInt, int val);
144 		void TakeBack();
145 		int PieceCount;
146 		int GroupCount;
147 		int FrontRing;
148 		int Current;
149 		Piece * Pieces;
150 		Group * Groups;
151 		TBEntry * TBBuf, * TBTop, * TBEnd;
152 	};
153 	friend class Solver;
154 
155 	emIntRec Width;
156 	emIntRec Height;
157 	emBoolRec Borderless;
158 	emBoolRec NoFourWayJunctions;
159 	emIntRec Complexity;
160 	emBoolRec DigMode;
161 	emBoolRec AutoMark;
162 	emBoolRec Finished;
163 	emIntRec PenaltyPoints;
164 	emIntRec CurrentPiece;
165 	emTArrayRec<emIntRec> Raster;
166 
167 	emTimer AutoMarkTimer;
168 	int AutoMarkPiece;
169 	bool AutoMarkToSave;
170 
171 	static const int A2PF[4];
172 };
173 
GetWidth()174 inline int emNetwalkModel::GetWidth() const
175 {
176 	return Width;
177 }
178 
GetHeight()179 inline int emNetwalkModel::GetHeight() const
180 {
181 	return Height;
182 }
183 
IsBorderless()184 inline bool emNetwalkModel::IsBorderless() const
185 {
186 	return Borderless;
187 }
188 
IsNoFourWayJunctions()189 inline bool emNetwalkModel::IsNoFourWayJunctions() const
190 {
191 	return NoFourWayJunctions;
192 }
193 
GetComplexity()194 inline int emNetwalkModel::GetComplexity() const
195 {
196 	return Complexity;
197 }
198 
IsDigMode()199 inline bool emNetwalkModel::IsDigMode() const
200 {
201 	return DigMode;
202 }
203 
IsAutoMark()204 inline bool emNetwalkModel::IsAutoMark() const
205 {
206 	return AutoMark;
207 }
208 
IsFinished()209 inline bool emNetwalkModel::IsFinished() const
210 {
211 	return Finished;
212 }
213 
GetPenaltyPoints()214 inline int emNetwalkModel::GetPenaltyPoints() const
215 {
216 	return PenaltyPoints;
217 }
218 
RotateLeft(int x,int y,bool saveFile)219 inline void emNetwalkModel::RotateLeft(int x, int y, bool saveFile)
220 {
221 	Rotate(x,y,-1,saveFile);
222 }
223 
RotateRight(int x,int y,bool saveFile)224 inline void emNetwalkModel::RotateRight(int x, int y, bool saveFile)
225 {
226 	Rotate(x,y,1,saveFile);
227 }
228 
GetPiece(int index)229 inline int emNetwalkModel::GetPiece(int index) const
230 {
231 	return Raster[index].Get();
232 }
233 
SetPiece(int index,int piece)234 inline void emNetwalkModel::SetPiece(int index, int piece)
235 {
236 	Raster[index].Set(piece);
237 }
238 
XorPiece(int index,int flags)239 inline void emNetwalkModel::XorPiece(int index, int flags)
240 {
241 	SetPiece(index,GetPiece(index)^flags);
242 }
243 
OrPiece(int index,int flags)244 inline void emNetwalkModel::OrPiece(int index, int flags)
245 {
246 	SetPiece(index,GetPiece(index)|flags);
247 }
248 
AndPiece(int index,int flags)249 inline void emNetwalkModel::AndPiece(int index, int flags)
250 {
251 	SetPiece(index,GetPiece(index)&flags);
252 }
253 
TBClear()254 inline void emNetwalkModel::Solver::TBClear()
255 {
256 	TBTop=TBBuf;
257 }
258 
TBStart()259 inline void emNetwalkModel::Solver::TBStart()
260 {
261 	TBTop->Ptr=NULL;
262 	TBTop++;
263 }
264 
TBSet(int & rInt,int val)265 inline void emNetwalkModel::Solver::TBSet(int & rInt, int val)
266 {
267 	TBTop->Ptr=&rInt;
268 	TBTop->Val=rInt;
269 	TBTop++;
270 	rInt=val;
271 }
272 
273 
274 #endif
275