1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // complex dynamic landscape creator
17 
18 #ifndef INC_C4MapCreatorS2
19 #define INC_C4MapCreatorS2
20 
21 #define C4MC_SizeRes        100         // positions in percent
22 #define C4MC_ZoomRes        100         // zoom resolution (-100 to +99)
23 
24 // string consts
25 #define C4MC_Overlay        "overlay"   // overlay node
26 #define C4MC_Point        "point"   // polygon point
27 #define C4MC_Map            "map"       // map node
28 
29 #define C4MC_DefAlgo        "solid"     // default overlay algorithm
30 
31 // error messages
32 #define C4MCErr_404             "file not found"
33 #define C4MCErr_NoGroup         "internal error: no group"
34 
35 #define C4MCErr_EOF             "unexpected end of file"
36 #define C4MCErr_NoDirGlobal     "can't use directives in local scope"
37 #define C4MCErr_UnknownDir      "unknown directive: %s"
38 #define C4MCErr_MapNoGlobal     "can't declare map in local scope"
39 #define C4MCErr_OpTypeErr       "operator type mismatch"
40 #define C4MCErr_IdtfExp         "identifier expected"
41 #define C4MCErr_UnnamedNoGlbl   "unnamed objects not allowed in global scope"
42 #define C4MCErr_BlOpenExp       "'{' expected"
43 #define C4MCErr_OpsNoGlobal     "operators not allowed in global scope"
44 #define C4MCErr_SColonOrOpExp   "';' or operator expected"
45 #define C4MCErr_Obj2Exp         "second operand expected"
46 #define C4MCErr_ReinstNoGlobal  "can't reinstanciate object '%s' in global scope"
47 #define C4MCErr_UnknownObj      "unknown object: %s"
48 #define C4MCErr_ReinstUnknown   "can't reinstanciate '%s'; object type is unknown"
49 #define C4MCErr_EqSColonBlOpenExp "'=', ';' or '{' expected"
50 #define C4MCErr_FieldConstExp   "constant for field '%s' expected"
51 #define C4MCErr_SColonExp       "';' expected"
52 #define C4MCErr_Field404        "field '%s' not found"
53 #define C4MCErr_FieldValInvalid "'%s' is not a valid value for this field"
54 #define C4MCErr_MatNotFound     "material '%s' not found"
55 #define C4MCErr_TexNotFound     "texture '%s' not found"
56 #define C4MCErr_AlgoNotFound    "algorithm '%s' not found"
57 #define C4MCErr_SFuncNotFound   "script func '%s' not found in scenario script"
58 #define C4MCErr_PointOnlyOvl    "point only allowed in overlays"
59 #define C4MCErr_NoRecTemplate   "cannot use template '%s' within itself"
60 
61 // predef
62 class C4MCCallbackArray;
63 class C4MCCallbackArrayList;
64 class C4MCNode;
65 class C4MCOverlay;
66 class C4MCPoint;
67 class C4MCMap;
68 class C4MapCreatorS2;
69 class C4MCParserErr;
70 class C4MCParser;
71 
72 struct C4MCAlgorithm
73 {
74 	char Identifier[C4MaxName];
75 	bool (*Function) (C4MCOverlay*, int32_t, int32_t);
76 };
77 
78 extern C4MCAlgorithm C4MCAlgoMap[];
79 
80 // node type enum
81 enum C4MCNodeType { MCN_Node, MCN_Overlay, MCN_Point, MCN_Map };
82 
83 // one token type
84 enum C4MCTokenType
85 {
86 	MCT_NONE,   // nothing
87 	MCT_DIR,    // directive (stored in CurrTokenIdtf)
88 	MCT_IDTF,   // identifier (stored in CurrTokenIdtf)
89 	MCT_INT,    // integer constant (stored in CurrTokenVal)
90 	MCT_EQ,     // =
91 	MCT_BLOPEN, // {
92 	MCT_BLCLOSE,// }
93 	MCT_SCOLON, // ;
94 	MCT_AND,    // &
95 	MCT_OR,     // |
96 	MCT_XOR,    // ^
97 	MCT_RANGE,  // -
98 	MCT_PERCENT,// integer constant (stored in CurrTokenVal) + %
99 	MCT_PX,     // integer constant (stored in CurrTokenVal) + px
100 	MCT_EOF     // end of file
101 };
102 
103 // a callback array
104 // contains a script func, and a map to call the func for
105 class C4MCCallbackArray
106 {
107 public:
108 	C4MCCallbackArray(C4AulFunc *pSFunc, C4MapCreatorS2 *pMapCreator); // ctor
109 	~C4MCCallbackArray();                   // dtor
110 
111 protected:
112 	C4MapCreatorS2 *pMapCreator; // map creator class to query current map of
113 	BYTE *pMap;           // bitmap whether or not to call the function for a map pixel
114 	int32_t iWdt, iHgt;       // size of the bitmap, when created
115 	C4AulFunc *pSF; // script func to be called
116 
117 	C4MCCallbackArray *pNext; // next array in linked list
118 
119 public:
120 	void EnablePixel(int32_t iX, int32_t iY); // enable pixel in map; create map if necessary
121 	void Execute(int32_t iMapZoom);       // evaluate the array
122 
123 	friend class C4MCCallbackArrayList;
124 };
125 
126 // callback array list: contains all callbacks
127 class C4MCCallbackArrayList
128 {
129 public:
C4MCCallbackArrayList()130 	C4MCCallbackArrayList() { pFirst=nullptr; } // ctor
~C4MCCallbackArrayList()131 	~C4MCCallbackArrayList() { Clear(); }    // ctor
132 
133 protected:
134 	C4MCCallbackArray *pFirst; // first array in list
135 
136 public:
137 	void Add(C4MCCallbackArray *pNewArray); // add given array to list
138 	void Clear();              // clear the list
139 	void Execute(int32_t iMapZoom);// execute all arrays
140 };
141 
142 // generic map creator tree node
143 // the code has been STL-free so far, so keep the line
144 class C4MCNode
145 {
146 public:
147 	C4MCNode *Owner, *Child0, *ChildL, *Prev, *Next; // tree structure
148 	C4MapCreatorS2 *MapCreator; // owning map creator
149 	char Name[C4MaxName]; // name, if named
150 
151 public:
152 	C4MCNode(C4MCNode *pOwner=nullptr); // constructor
153 	C4MCNode(C4MCParser* pParser, C4MCNode *pOwner, C4MCNode &rTemplate, bool fClone); // constructor using template
154 	virtual ~C4MCNode(); // destructor
155 
clone(C4MCParser * pParser,C4MCNode * pToNode)156 	virtual C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) { return new C4MCNode(pParser, pToNode, *this, true); }
157 
158 	void Clear(); // clear all child nodes
159 	void Reg2Owner(C4MCNode *pOwner); // register into list
160 
161 protected:
GlobalScope()162 	virtual bool GlobalScope() { return false; } // whether node is a global scope
SetOp(C4MCTokenType eOp)163 	virtual bool SetOp(C4MCTokenType eOp) { return false; } // set following operator
164 	C4MCNode *GetNodeByName(const char *szName); // search node by name
165 
166 	virtual bool SetField(C4MCParser *pParser, const char *szField, const char *szSVal, int32_t iVal, C4MCTokenType ValType); // set field
167 	int32_t IntPar(C4MCParser *pParser, const char *szSVal, int32_t iVal, C4MCTokenType ValType); // ensure par is int32_t
168 	const char *StrPar(C4MCParser *pParser, const char *szSVal, int32_t iVal, C4MCTokenType ValType); // ensure par is string
169 
Evaluate()170 	virtual void Evaluate() { } // called when all fields are initialized
171 	void ReEvaluate(); // evaluate everything again
172 
173 	// For Percents and Pixels
174 	class int_bool
175 	{
176 	public:
Evaluate(int32_t relative_to)177 		int32_t Evaluate(int32_t relative_to)
178 		{ if (percent) return value * relative_to / C4MC_SizeRes; else return value; }
Set(int32_t value,bool percent)179 		void Set(int32_t value, bool percent)
180 		{ this->value = value; this->percent = percent; }
181 	private:
182 		int32_t value;
183 		bool percent;
184 	};
185 public:
Type()186 	virtual C4MCNodeType Type() { return MCN_Node; } // get node type
Overlay()187 	virtual C4MCOverlay *Overlay() { return nullptr; } // return overlay, if this is one
188 	C4MCOverlay *OwnerOverlay(); // return an owner who is an overlay
189 
190 	friend class C4MCParser;
191 };
192 
193 // overlay node
194 class C4MCOverlay : public C4MCNode
195 {
196 public:
197 	C4MCOverlay(C4MCNode *pOwner=nullptr); // constructor
198 	C4MCOverlay(C4MCParser* pParser, C4MCNode *pOwner, C4MCOverlay &rTemplate, bool fClone); // construct of template
199 
clone(C4MCParser * pParser,C4MCNode * pToNode)200 	C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) override { return new C4MCOverlay(pParser, pToNode, *this, true); }
201 
202 protected:
203 	void Default(); // set default values for default presets
204 
205 public:
206 	int32_t Seed; // random seed
207 	int32_t FixedSeed; // fixed random seed set in def
208 	int32_t X,Y,Wdt,Hgt,OffX,OffY; // extends/offset
209 	int_bool RX, RY, RWdt, RHgt, ROffX, ROffY; // extends/offset relatively to owner
210 	int32_t Material; // material index
211 	bool Sub; // tunnel bg?
212 	char Texture[C4M_MaxName+1]; // texture name
213 	BYTE MatClr; // resolved mat-tex color
214 	BYTE MatClrBkg; // resolved mat-tex color
215 	C4MCTokenType Op; // following operator
216 	C4MCAlgorithm *Algorithm; // algorithm to calc whether filled or not
217 	int32_t Turbulence, Lambda, Rotate; // turbulence factors; rotation angle
218 	int_bool Alpha, Beta; // extra params
219 	int32_t ZoomX, ZoomY; // zoom factor for algorithm
220 	bool Invert, LooseBounds, Group, Mask; // extra algo behaviour
221 	C4MCCallbackArray *pEvaluateFunc;        // function called for nodes being evaluated and fulfilled
222 	C4MCCallbackArray *pDrawFunc;            // function called when this node is drawn - pass drawcolor as first param, return color to be actually used
223 
SetOp(C4MCTokenType eOp)224 	bool SetOp(C4MCTokenType eOp) override { Op=eOp; return true; } // set following operator
225 
226 	C4MCAlgorithm *GetAlgo(const char *szName);
227 
228 	bool SetField(C4MCParser *pParser, const char *szField, const char *szSVal, int32_t iVal, C4MCTokenType ValType) override; // set field
229 
230 	void Evaluate() override; // called when all fields are initialized
231 
Overlay()232 	C4MCOverlay *Overlay() override { return this; } // this is an overlay
233 	C4MCOverlay *FirstOfChain(); // go backwards in op chain until first overlay of chain
234 
235 	bool CheckMask(int32_t iX, int32_t iY); // check whether algorithms succeeds at iX/iY
236 	bool RenderPix(int32_t iX, int32_t iY, BYTE &rPix, BYTE &rPixBkg, C4MCTokenType eLastOp=MCT_NONE, bool fLastSet=false, bool fDraw=true, C4MCOverlay **ppPixelSetOverlay=nullptr); // render this pixel
237 	bool PeekPix(int32_t iX, int32_t iY); // check mask; regard operator chain
InBounds(int32_t iX,int32_t iY)238 	bool InBounds(int32_t iX, int32_t iY) { return iX>=X && iY>=Y && iX<X+Wdt && iY<Y+Hgt; } // return whether point iX/iY is inside bounds
239 
240 public:
Type()241 	C4MCNodeType Type() override { return MCN_Overlay; } // get node type
242 
243 	friend class C4MapCreatorS2;
244 	friend class C4MCParser;
245 };
246 
247 // point of polygon node
248 class C4MCPoint : public C4MCNode
249 {
250 public:
251 	C4MCPoint(C4MCNode *pOwner=nullptr); // constructor
252 	C4MCPoint(C4MCParser* pParser, C4MCNode *pOwner, C4MCPoint &rTemplate, bool fClone); // construct of template
253 
clone(C4MCParser * pParser,C4MCNode * pToNode)254 	C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) override { return new C4MCPoint(pParser, pToNode, *this, true); }
255 
256 protected:
257 	void Default(); // set default values for default presets
258 
259 public:
260 	int32_t X,Y;
261 	int_bool RX,RY;
262 
263 	void Evaluate() override; // called when all fields are initialized
264 	bool SetField(C4MCParser *pParser, const char *szField, const char *szSVal, int32_t iVal, C4MCTokenType ValType) override; // set field
265 
266 public:
Type()267 	C4MCNodeType Type() override { return MCN_Point; } // get node type
268 
269 	friend class C4MapCreatorS2;
270 	friend class C4MCParser;
271 };
272 
273 // simply an overlay that can be rendered
274 class C4MCMap : public C4MCOverlay
275 {
276 public:
277 	C4MCMap(C4MCNode *pOwner=nullptr); // constructor
278 	C4MCMap(C4MCParser* pParser, C4MCNode *pOwner, C4MCMap &rTemplate, bool fClone); // construct of template
279 
clone(C4MCParser * pParser,C4MCNode * pToNode)280 	C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) override { return new C4MCMap(pParser, pToNode, *this, true); }
281 
282 protected:
283 	void Default(); // set default values for default presets
284 
285 public:
286 	bool RenderTo(BYTE *pToBuf, BYTE *pToBufBkg, int32_t iPitch); // render to buffer
287 	void SetSize(int32_t iWdt, int32_t iHgt);
288 
289 public:
Type()290 	C4MCNodeType Type() override { return MCN_Map; } // get node type
291 
292 	friend class C4MapCreatorS2;
293 	friend class C4MCParser;
294 };
295 
296 // main map creator class
297 class C4MapCreatorS2 : public C4MCNode
298 {
299 public:
300 	C4MapCreatorS2(C4SLandscape *pLandscape, C4TextureMap *pTexMap, C4MaterialMap *pMatMap, int iPlayerCount); // constructor
301 	~C4MapCreatorS2() override; // destructor
302 
303 	void Default(); // set default data
304 	void Clear(); // clear any data
305 	bool ReadFile(const char *szFilename, C4Group *pGrp); // read defs of file
306 	bool ReadScript(const char *szScript);    // reads def directly from mem
307 
308 public:
309 	C4MCMap *GetMap(const char *szMapName); // get map by name
310 
311 public:
312 	bool Render(const char *szMapName, CSurface8*& sfcMap, CSurface8*& sfcMapBkg); // create map surface
313 	BYTE *RenderBuf(const char *szMapName, int32_t &sfcWdt, int32_t &sfcHgt); // create buffer and render it
314 
SetC4SLandscape(C4SLandscape * pLandscape)315 	void SetC4SLandscape(C4SLandscape *pLandscape) // update source for map size
316 	{ Landscape=pLandscape; }
317 
318 protected:
319 	C4SLandscape  *Landscape; // landsape presets
320 	C4TextureMap  *TexMap; // texture map
321 	C4MaterialMap *MatMap; // material map
322 	C4MCMap     DefaultMap;     // default template: landscape
323 	C4MCOverlay DefaultOverlay; // default template: overlay
324 	C4MCPoint DefaultPoint; // default template: point
325 	C4MCMap       *pCurrentMap; // map currently rendered
326 	C4MCCallbackArrayList CallbackArrays; // list of callback arrays
327 	int PlayerCount; // player count for MapPlayerExtend
328 
GlobalScope()329 	bool GlobalScope() override { return true; } // it's the global node
330 
331 public:
ExecuteCallbacks(int32_t iMapZoom)332 	void ExecuteCallbacks(int32_t iMapZoom) { CallbackArrays.Execute(iMapZoom); }
333 
334 	friend class C4MCOverlay;
335 	friend class C4MCMap;
336 	friend class C4MCParser;
337 	friend class C4MCCallbackArray;
338 };
339 
340 
341 // file parser for map creator
342 
343 // parser error
344 class C4MCParserErr
345 {
346 public:
347 	char Msg[C4MaxMessage]; // message string
348 
349 	C4MCParserErr(C4MCParser *pParser, const char *szMsg); // construct setting error msg
350 	C4MCParserErr(C4MCParser *pParser, const char *szMsg, const char *szPar); // construct setting error msg
351 	void show(); // log error
352 };
353 
354 // the parser
355 class C4MCParser
356 {
357 private:
358 	C4MapCreatorS2 *MapCreator; // map creator parsing into
359 	char *Code; // loaded code, can be nullptr if externally owned
360 	const char *BPos; // Beginning of code
361 	const char *CPos; // current parser pos in code
362 	C4MCTokenType CurrToken; // last token read
363 	char CurrTokenIdtf[C4MaxName]; // current token string
364 	int32_t CurrTokenVal; // current token value
365 	char Filename[C4MaxName]; // filename
366 
367 	bool AdvanceSpaces(); // advance to next token char; return whether EOF is reached
368 	bool GetNextToken(); // get token, store in fields and advance to next; return whether not EOF
369 	void ParseTo(C4MCNode *pToNode); // parse stuff into
370 	void ParseValue(C4MCNode *pToNode, const char *szFieldName); // Set Field
371 
372 public:
373 	C4MCParser(C4MapCreatorS2 *pMapCreator); // constructor
374 	~C4MCParser(); // destructor
375 
376 	void Clear(); // clear stuff
377 
378 	void ParseFile(const char *szFilename, C4Group *pGrp); // load and parse file
379 	void Parse(const char *szScript); // load and parse from mem
380 	void ParseMemFile(const char *szScript, const char *szFilename); // parse file previosuly loaded into mem
381 
382 	friend class C4MCParserErr;
383 };
384 
385 #endif
386