Subversion Repositories Kolibri OS

Rev

Rev 1805 | Rev 5822 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1805 yogev_ezra 1
#include "kosSyst.h"
2
#include "mcarray.h"
3
#include "lang.h"
4
 
5
 
6
// битмап пустого места
7
RGB bmEmpty[] = {
8
	0x201010, 0x101020, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010,
9
	0x101010, 0x102010, 0x201010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010,
10
	0x101010, 0x101010, 0x101020, 0x102010, 0x101010, 0x101010, 0x101010, 0x101010,
11
	0x101010, 0x101010, 0x101010, 0x201010, 0x101020, 0x101010, 0x101010, 0x101010,
12
	0x101010, 0x101010, 0x101010, 0x101010, 0x102010, 0x201010, 0x101010, 0x101010,
13
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101020, 0x102010, 0x101010,
14
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x201010, 0x101020,
15
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x102010
16
};
17
 
18
 
19
// битмап игрока
20
RGB bmHero[] = {
21
	0x2020E0, 0x2020E0, 0x2020E0, 0x2020E0, 0x2020E0, 0x2020E0, 0x2020E0, 0x2020C0,
22
	0x2020E0, 0x2020E0, 0x2020E0, 0x2020E0, 0x2020E0, 0x2020E0, 0x2020C0, 0x2020A0,
23
	0x2020E0, 0x2020E0, 0x2020C0, 0x2020C0, 0x2020C0, 0x2020C0, 0x2020A0, 0x2020A0,
24
	0x2020E0, 0x2020E0, 0x2020C0, 0x2020C0, 0x2020C0, 0x2020C0, 0x2020A0, 0x2020A0,
25
	0x2020E0, 0x2020E0, 0x2020C0, 0x2020C0, 0x2020C0, 0x2020C0, 0x2020A0, 0x2020A0,
26
	0x2020E0, 0x2020E0, 0x2020C0, 0x2020C0, 0x2020C0, 0x2020C0, 0x2020A0, 0x2020A0,
27
	0x2020E0, 0x2020C0, 0x2020A0, 0x2020A0, 0x2020A0, 0x2020A0, 0x2020A0, 0x2020A0,
28
	0x2020C0, 0x2020A0, 0x2020A0, 0x2020A0, 0x2020A0, 0x2020A0, 0x2020A0, 0x2020A0
29
};
30
 
31
 
32
// битмап игрока
33
RGB bmSuperHero[] = {
34
	0x5720D0, 0x5720D0, 0x5720D0, 0x5720D0, 0x5720D0, 0x5720D0, 0x5720D0, 0x5720B0,
35
	0x5720D0, 0x5720D0, 0x5720D0, 0x5720D0, 0x5720D0, 0x5720D0, 0x5720B0, 0x572090,
36
	0x5720D0, 0x5720D0, 0x5720B0, 0x5720B0, 0x5720B0, 0x5720B0, 0x572090, 0x572090,
37
	0x5720D0, 0x5720D0, 0x5720B0, 0x5720B0, 0x5720B0, 0x5720B0, 0x572090, 0x572090,
38
	0x5720D0, 0x5720D0, 0x5720B0, 0x5720B0, 0x5720B0, 0x5720B0, 0x572090, 0x572090,
39
	0x5720D0, 0x5720D0, 0x5720B0, 0x5720B0, 0x5720B0, 0x5720B0, 0x572090, 0x572090,
40
	0x5720D0, 0x5720B0, 0x572090, 0x572090, 0x572090, 0x572090, 0x572090, 0x572090,
41
	0x5720B0, 0x572090, 0x572090, 0x572090, 0x572090, 0x572090, 0x572090, 0x572090
42
};
43
 
44
 
45
// битмап гада, бегающего по заполненной местности
46
RGB bmEnemy1[] = {
47
	0xE02020, 0xE02020, 0xE02020, 0xE02020, 0xE02020, 0xE02020, 0xE02020, 0xC02020,
48
	0xE02020, 0xE02020, 0xE02020, 0xE02020, 0xE02020, 0xE02020, 0xC02020, 0xA02020,
49
	0xE02020, 0xE02020, 0xC02020, 0xC02020, 0xC02020, 0xC02020, 0xA02020, 0xA02020,
50
	0xE02020, 0xE02020, 0xC02020, 0xC02020, 0xC02020, 0xC02020, 0xA02020, 0xA02020,
51
	0xE02020, 0xE02020, 0xC02020, 0xC02020, 0xC02020, 0xC02020, 0xA02020, 0xA02020,
52
	0xE02020, 0xE02020, 0xC02020, 0xC02020, 0xC02020, 0xC02020, 0xA02020, 0xA02020,
53
	0xE02020, 0xC02020, 0xA02020, 0xA02020, 0xA02020, 0xA02020, 0xA02020, 0xA02020,
54
	0xC02020, 0xA02020, 0xA02020, 0xA02020, 0xA02020, 0xA02020, 0xA02020, 0xA02020
55
};
56
 
57
 
58
// битмап гада, бегающего по пустому месту
59
RGB bmEnemy2[] = {
60
	0xE08020, 0xE08020, 0xE08020, 0xE08020, 0xE08020, 0xE08020, 0xE08020, 0xC08020,
61
	0xE08020, 0xE08020, 0xE08020, 0xE08020, 0xE08020, 0xE08020, 0xC08020, 0xA08020,
62
	0xE08020, 0xE08020, 0xC08020, 0xC08020, 0xC08020, 0xC08020, 0xA08020, 0xA08020,
63
	0xE08020, 0xE08020, 0xC08020, 0xC08020, 0xC08020, 0xC08020, 0xA08020, 0xA08020,
64
	0xE08020, 0xE08020, 0xC08020, 0xC08020, 0xC08020, 0xC08020, 0xA08020, 0xA08020,
65
	0xE08020, 0xE08020, 0xC08020, 0xC08020, 0xC08020, 0xC08020, 0xA08020, 0xA08020,
66
	0xE08020, 0xC08020, 0xA08020, 0xA08020, 0xA08020, 0xA08020, 0xA08020, 0xA08020,
67
	0xC08020, 0xA08020, 0xA08020, 0xA08020, 0xA08020, 0xA08020, 0xA08020, 0xA08020
68
};
69
 
70
 
71
// битмап заполнения
72
RGB bmWall[] = {
73
	0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xCCCCCC,
74
	0xFFFFFF, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xAAAAAA,
75
	0xFFFFFF, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xAAAAAA,
76
	0xFFFFFF, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xAAAAAA,
77
	0xFFFFFF, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xAAAAAA,
78
	0xFFFFFF, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xAAAAAA,
79
	0xFFFFFF, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xCCCCCC, 0xAAAAAA,
80
	0xCCCCCC, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA
81
};
82
 
83
 
84
// след игрока
85
RGB bmTrack[] = {
86
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010,
87
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010,
88
	0x101010, 0x101010, 0x101010, 0x1010F0, 0x1010F0, 0x101010, 0x101010, 0x101010,
89
	0x101010, 0x101010, 0x1010F0, 0x1010F0, 0x1010F0, 0x1010F0, 0x101010, 0x101010,
90
	0x101010, 0x101010, 0x1010F0, 0x1010F0, 0x1010F0, 0x1010F0, 0x101010, 0x101010,
91
	0x101010, 0x101010, 0x101010, 0x1010F0, 0x1010F0, 0x101010, 0x101010, 0x101010,
92
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010,
93
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010
94
};
95
 
96
 
97
// след игрока
98
RGB bmSuperTrack[] = {
99
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010,
100
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010,
101
	0x101010, 0x101010, 0x101010, 0x5310D0, 0x5310D0, 0x101010, 0x101010, 0x101010,
102
	0x101010, 0x101010, 0x5310D0, 0x5310D0, 0x5310D0, 0x5310D0, 0x101010, 0x101010,
103
	0x101010, 0x101010, 0x5310D0, 0x5310D0, 0x5310D0, 0x5310D0, 0x101010, 0x101010,
104
	0x101010, 0x101010, 0x101010, 0x5310D0, 0x5310D0, 0x101010, 0x101010, 0x101010,
105
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010,
106
	0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010, 0x101010
107
};
108
 
109
 
110
// заполнение экрана для смены уровня
111
RGB bmFlip[] = {
112
	0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0,
113
	0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010,
114
	0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0,
115
	0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010,
116
	0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0,
117
	0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010,
118
	0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0,
119
	0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010, 0xF0F0F0, 0x101010
120
};
121
 
122
 
123
// бонус неуязвимости
124
RGB bmBonus1[] = {
125
	0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xCCCCCC,
126
	0xFFFFFF, 0xCCCCCC, 0xCCCCCC, 0x44AC44, 0x44AC44, 0xCCCCCC, 0xCCCCCC, 0xAAAAAA,
127
	0xFFFFFF, 0xCCCCCC, 0x44AC44, 0x44AC44, 0x44AC44, 0x44AC44, 0xCCCCCC, 0xAAAAAA,
128
	0xFFFFFF, 0x44AC44, 0x44AC44, 0x0C8C0C, 0x0C8C0C, 0x44AC44, 0x44AC44, 0xAAAAAA,
129
	0xFFFFFF, 0x44AC44, 0x44AC44, 0x0C8C0C, 0x0C8C0C, 0x44AC44, 0x44AC44, 0xAAAAAA,
130
	0xFFFFFF, 0xCCCCCC, 0x44AC44, 0x44AC44, 0x44AC44, 0x44AC44, 0xCCCCCC, 0xAAAAAA,
131
	0xFFFFFF, 0xCCCCCC, 0xCCCCCC, 0x44AC44, 0x44AC44, 0xCCCCCC, 0xCCCCCC, 0xAAAAAA,
132
	0xCCCCCC, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA
133
};
134
 
135
 
136
// бонус жизни
137
RGB bmBonus2[] = {
138
	0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xCCCCCC,
139
	0xFFFFFF, 0xCCCCCC, 0xD41414, 0xCCCCCC, 0xCCCCCC, 0xD41414, 0xCCCCCC, 0xAAAAAA,
140
	0xFFFFFF, 0xD41414, 0xD41414, 0xD41414, 0xD41414, 0xD41414, 0xD41414, 0xAAAAAA,
141
	0xFFFFFF, 0xD41414, 0xD41414, 0xD41414, 0xD41414, 0xD41414, 0xD41414, 0xAAAAAA,
142
	0xFFFFFF, 0xD41414, 0xD41414, 0xD41414, 0xD41414, 0xD41414, 0xD41414, 0xAAAAAA,
143
	0xFFFFFF, 0xCCCCCC, 0xD41414, 0xD41414, 0xD41414, 0xD41414, 0xCCCCCC, 0xAAAAAA,
144
	0xFFFFFF, 0xCCCCCC, 0xCCCCCC, 0xD41414, 0xD41414, 0xCCCCCC, 0xCCCCCC, 0xAAAAAA,
145
	0xCCCCCC, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA
146
};
147
 
148
 
149
//
150
RGB bmPMButton[] = {
151
	0xCCCCCC, 0xCCCCCC, 0x000000, 0x000000, 0xCCCCCC, 0xCCCCCC,
152
	0xCCCCCC, 0xCCCCCC, 0x000000, 0x000000, 0xCCCCCC, 0xCCCCCC,
153
	0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
154
	0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
155
	0xCCCCCC, 0xCCCCCC, 0x000000, 0x000000, 0xCCCCCC, 0xCCCCCC,
156
	0xCCCCCC, 0xCCCCCC, 0x000000, 0x000000, 0xCCCCCC, 0xCCCCCC,
157
};
158
 
159
 
160
//
161
void DrawAppWindow();
162
//
163
void DrawTop10Window();
164
//
165
void initWorldMap();
166
//
167
void drawWorldMap();
168
//
169
void clearWorldMap();
170
//
171
void drawWorldMapForFlip();
172
//
173
void drawWndTitleGo();
174
//
175
void ApplyMapDiffs( bool drawTitle = true );
176
//
177
int GetCompletePercents();
178
 
179
 
180
#define EAT_ENEMY_BONUS		100
181
 
182
#define BEFORE_START_LEVEL	100
183
#define BONUS1_LIFETIME		250
184
#define BONUS1_IND_HSIZE	6
185
 
186
#define MIN_LOOP_DELAY		1
187
#define MAX_LOOP_DELAY		20
188
#define DEFAULT_LOOP_DELAY	12
189
 
190
#define blockSize			8
191
 
192
#define ENTRY_WND_SIZE_X	400
193
#define ENTRY_WND_SIZE_Y	144
194
 
195
#define TOP10_WND_SIZE_X	176
196
#define TOP10_WND_SIZE_Y	144
197
 
198
#define MAX_X_SIZE			96
199
#define MIN_X_SIZE			48
200
#define MAX_Y_SIZE			56
201
#define MIN_Y_SIZE			28
202
 
203
#define flipMapSize			((mapSizeX * mapSizeY) / 4)
204
#define wndXOffet			1
205
#define wndYOffset			22
206
#define freeSpaceCount		((mapSizeX - 4) * (mapSizeY - 4))
207
//
208
#define	gmEmpty				0
209
#define gmHero				1
210
#define gmEnemy1			2
211
#define gmEnemy2			3
212
#define gmWall				4
213
#define gmTrack				5
214
#define gmFlip				6
215
#define gmBonus1			7
216
#define gmBonus2			8
217
#define gmSuperHero			9
218
#define gmSuperTrack		10
219
#define gmProbe				11
220
 
221
#define appStateEntry		0
222
#define appStateGo			1
223
#define appStateHideMap		2
224
#define appStateShowMap		3
225
#define appStatePause		4
226
#define appStateAfterDeath	5
227
#define appStateTop10		6
228
 
229
#define spacePerEnemy		30
230
 
231
 
232
#define BT_SIZE_X_PLUS		2
233
#define BT_SIZE_X_MINUS		3
234
#define BT_LOOP_PLUS		4
235
#define BT_LOOP_MINUS		5
236
#define BT_SIZE_Y_PLUS		6
237
#define BT_SIZE_Y_MINUS		7
238
 
239
#define TOP_TBL_SIZE		10
240
 
241
 
242
//
243
struct hiScoreHero
244
{
245
	char name[12];
246
	Dword score;
247
	//
248
	hiScoreHero()
249
	{
250
		//
251
		this->ClearName();
252
		this->score = 0;
253
	};
254
	//
255
	void ClearName()
256
	{
257
		memset( (Byte *)(this->name), '.', sizeof(this->name) );
258
	};
259
};
260
 
261
//
262
char top10FilePath[MAX_PATH];
263
hiScoreHero heroTbl[TOP_TBL_SIZE];
264
 
265
//
266
struct hiScoreFile
267
{
268
	Byte block[512];
269
	kosFileInfo fi;
270
	//
271
	hiScoreFile()
272
	{
273
		int i;
274
 
275
		//
276
		this->fi.offsetLow = this->fi.offsetHigh = 0;
277
		this->fi.dataCount = 0;
278
		this->fi.bufferPtr = this->block;
279
		this->fi.rwMode = 0;
280
		memcpy( this->fi.fileURL, top10FilePath, sizeof( top10FilePath ) );
281
		//
282
		for ( i = 0; i < ( sizeof( this->block ) / sizeof( Dword ) ); i++ )
283
		{
284
			//
285
			((Dword *)(this->block))[i] = rtlRand();
286
		}
287
	};
288
	//
289
	virtual ~hiScoreFile()
290
	{}
291
	//
292
	bool LoadFromDisk()
293
	{
294
		bool result;
295
		int i;
296
		Dword j, k;
297
		Byte *bPtr;
298
 
299
		//
300
		this->fi.rwMode = FO_READ;
301
		this->fi.dataCount = 512;
302
		result = kos_FileSystemAccess( &(this->fi) ) == 0;
303
		//
304
		if ( result )
305
		{
306
			// декодируем
307
			rtlSrand( ((Dword *)(this->block))[(sizeof(this->block) / sizeof(Dword)) - 1] );
308
			//
309
			for ( i = 0; i < (sizeof( heroTbl ) * 5); i++ )
310
			{
311
				// не трогаем последний Dword
312
				j = rtlRand() % (sizeof(this->block) - 7);
313
				k = ( rtlRand() % 31 ) + 1;
314
				//
315
				bPtr = this->block + j;
316
				//
317
				__asm{
318
					mov edx, bPtr
319
					mov ecx, k
320
					mov eax, [edx]
321
					bswap eax
322
					ror eax, cl
323
					mov [edx], eax
324
				}
325
			}
326
			//
327
			rtlSrand( kos_GetSystemClock() );
328
		}
329
		//
330
		return result;
331
	};
332
	//
333
	bool SaveToDisk()
334
	{
335
		int i;
336
		Dword *rndList;
337
		Byte *bPtr;
338
		Dword k, keyLock;
339
 
340
		//
341
		rndList = new Dword[(sizeof( heroTbl ) * 5) * 2];
342
		//
343
		keyLock = rtlRand();
344
		//
345
		for ( i = 0; i < (sizeof( heroTbl ) * 5); i++ )
346
		{
347
			//
348
			rndList[i * 2] = rtlRand() % (sizeof(this->block) - 7);
349
			rndList[(i * 2) + 1] = ( rtlRand() % 31 ) + 1;
350
		}
351
		//
352
		for ( i = (sizeof( heroTbl ) * 5) - 1; i >= 0; i-- )
353
		{
354
			//
355
			bPtr = this->block + rndList[i * 2];
356
			k = rndList[(i * 2) + 1];
357
			//
358
			__asm{
359
				mov edx, bPtr
360
				mov ecx, k
361
				mov eax, [edx]
362
				rol eax, cl
363
				bswap eax
364
				mov [edx], eax
365
			}
366
		}
367
		//
368
		delete rndList;
369
		//
370
		((Dword *)(this->block))[(sizeof(this->block) / sizeof(Dword)) - 1] = keyLock;
371
		//
372
		this->fi.rwMode = FO_WRITE;
373
		this->fi.dataCount = 512;
374
		return kos_FileSystemAccess( &( this->fi) ) == 0;
375
	};
376
};
377
 
378
///
379
hiScoreFile *top10Heroes = NULL;
380
 
381
 
382
// заголовок главного окна
383
char MainWindowTitle[] = "XONIX (C) MMVI by Rabid Rabbit";
384
#if LANG == RUS
385
char goWndTitle[] = "“а®ўҐ­м %U, § ўҐа襭® %U%%, ¦Ё§­Ґ©: %U, бзсв: %U";
386
char menuStr1[] = "1. Ќ з вм ЁЈаг";
387
char menuStr2[] = "2. ‚л室";
388
char menuStr3[] = "“Їа ў«Ґ­ЁҐ: ‘’ђ…‹Љ€ - ­ Їа ў«Ґ­ЁҐ ¤ўЁ¦Ґ­Ёп.";
389
char menuStr4[] = "SPACE - Ї г§ , ESC - ўл室 ў ¬Ґ­о.";
390
char thatsAllStr[] = "€Ја  ®Є®­зҐ­ .";
391
char worldSizeStr[] = "ђ §¬Ґа Ї®«п %U x %U н«Ґ¬Ґ­в®ў.";
392
char mainLoopDelayStr[] = "‘Є®а®бвм %U";
393
char top10str1[] = "ENTER - Ё¬п Ok.";
394
char top10str2[] = "ESC - ўл室 ў ¬Ґ­о";
395
#else
396
char goWndTitle[] = "Level %U, completed %U%%, lives: %U, scores: %U";
397
char menuStr1[] = "1. Start game";
398
char menuStr2[] = "2. Exit";
399
char menuStr3[] = "Control: ARROWS - direction of movement.";
400
char menuStr4[] = "SPACE - pause, ESC - leave to menu.";
401
char thatsAllStr[] = "Game finished.";
402
char worldSizeStr[] = "Field size %U x %U cells.";
403
char mainLoopDelayStr[] = "Speed %U";
404
char top10str1[] = "Enter - name Ok.";
405
char top10str2[] = "ESC - leave to menu";
406
#endif
407
//
408
Byte beep1[] = { 0x90, 0x33, 0 };
409
//
410
Byte *heroPtr = NULL;
411
int heroDX = 0, heroDY = 0, lastMoveDirection = 0;
412
//
413
Byte * worldMap = NULL;
414
//
415
int	wndSizeX = ENTRY_WND_SIZE_X;
416
int	wndSizeY = ENTRY_WND_SIZE_Y;
417
int mapSizeX = 64;
418
int mapSizeY = 32;
419
int loopDelay = DEFAULT_LOOP_DELAY;
420
int currentLevel = 1;
421
int appState = appStateEntry;
422
int levelFillEdge = 0;
423
int levelFillCount = 0;
424
int lifeCount = 0;
425
int flipMapCount = 0;
426
bool noBonus = false;
427
bool goToNextLevel = false;
428
bool bonus1Set = false;
429
bool bonus2Set = false;
430
int bonus1Count = 0;
431
int currentHero = gmHero;
432
int currentTrack = gmTrack;
433
Dword scoreCount = 0;
434
int enterName = -1;
435
int enterCharNdx = 0;
436
//
437
MCArray fillList;
438
 
439
//
440
struct flipMapEl
441
{
442
	Word x, y;
443
};
444
 
445
//
446
flipMapEl *flipMapPtr = NULL;
447
 
448
 
449
//
450
RGB *mapColours[] = {
451
	bmEmpty,
452
	bmHero,
453
	bmEnemy1,
454
	bmEnemy2,
455
	bmWall,
456
	bmTrack,
457
	bmFlip,
458
	bmBonus1,
459
	bmBonus2,
460
	bmSuperHero,
461
	bmSuperTrack,
462
	NULL
463
};
464
 
465
 
466
//
467
struct sMapDiff
468
{
469
	Byte *elPtr;
470
	Byte mapEl;
471
	//
472
	sMapDiff() {};
473
	//
474
	sMapDiff( Byte *sElPtr, Byte sMapEl )
475
	{
476
		this->elPtr = sElPtr;
477
		this->mapEl = sMapEl;
478
	};
479
};
480
 
481
 
482
//
483
class CMapDiff : public MCArray
484
{
485
public:
486
	virtual int Add( const sMapDiff &element )
487
	{
488
		element.elPtr[0] = element.mapEl;
489
		return MCArray::Add( element );
490
	}
491
};
492
 
493
 
494
//
495
CMapDiff mapDiffList;
496
MCArray sTrackList;
497
 
498
 
499
//
500
class CGenericEnemy
501
{
502
public:
503
	//
504
	Byte *ePtr;
505
	int dx, dy;
506
	//
507
	virtual bool Move(void) = 0;
508
};
509
 
510
class CWallEnemy : public CGenericEnemy
511
{
512
public:
513
	virtual bool Move(void);
514
};
515
 
516
class CSpaceEnemy : public CGenericEnemy
517
{
518
public:
519
	virtual bool Move(void);
520
};
521
 
522
 
523
 
524
//
525
bool CWallEnemy::Move()
526
{
527
	int ddx;
528
	Byte *nextPtr;
529
	Byte mapEl, dirMap;
530
	bool result, border;
531
 
532
	//
533
	result = false;
534
	border = false;
535
	//
536
	ddx = ( this->ePtr - worldMap ) % mapSizeX;
537
	//
538
	if ( ddx == 0 && this->dx < 0 )
539
	{
540
		border = true;
541
		this->dx = 0 - this->dx;
542
	}
543
	//
544
	if ( ddx == (mapSizeX - 1) && this->dx > 0 )
545
	{
546
		border = true;
547
		this->dx = 0 - this->dx;
548
	}
549
	//
550
	ddx = ( this->ePtr - worldMap ) / mapSizeX;
551
	//
552
	if ( ddx == 0 && this->dy < 0 )
553
	{
554
		border = true;
555
		this->dy = 0 - this->dy;
556
	}
557
	//
558
	if ( ddx == (mapSizeY - 1) && this->dy > 0 )
559
	{
560
		border = true;
561
		this->dy = 0 - this->dy;
562
	}
563
	// получим координаты места, в которое попадает объект
564
	nextPtr = this->ePtr + ( this->dx + this->dy );
565
	// получим элемент с карты
566
	mapEl = nextPtr[0];
567
	//
568
	// в зависимости от элемента
569
	switch ( mapEl )
570
	{
571
	// напоролись на игрока
572
	case gmHero:
573
		if ( sTrackList.GetCount() <= 0 )
574
		{
575
			result = true;
576
			break;
577
		}
578
 
579
	// пустое место, след игрока или гады на поле - надо отскакивать
580
	case gmSuperHero:
581
	case gmSuperTrack:
582
	case gmTrack:
583
	case gmEnemy2:
584
	case gmEmpty:
585
		//
586
		dirMap = 0;
587
		// -dx +dy
588
		mapEl = this->ePtr[this->dy - this->dx];
589
		if ( mapEl == gmEmpty
590
			|| mapEl == gmTrack
591
			|| mapEl == gmEnemy2
592
			|| mapEl == gmSuperHero
593
			|| mapEl == gmSuperTrack
594
			) dirMap |= 1;
595
		// +dy
596
		mapEl = this->ePtr[this->dy];
597
		if ( mapEl == gmEmpty
598
			|| mapEl == gmTrack
599
			|| mapEl == gmEnemy2
600
			|| mapEl == gmSuperHero
601
			|| mapEl == gmSuperTrack
602
			) dirMap |= 2;
603
		// +dx
604
		mapEl = this->ePtr[this->dx];
605
		if ( mapEl == gmEmpty
606
			|| mapEl == gmTrack
607
			|| mapEl == gmEnemy2
608
			|| mapEl == gmSuperHero
609
			|| mapEl == gmSuperTrack
610
			) dirMap |= 4;
611
		// +dx -dy
612
		mapEl = this->ePtr[this->dx - this->dy];
613
		if ( mapEl == gmEmpty
614
			|| mapEl == gmTrack
615
			|| mapEl == gmEnemy2
616
			|| mapEl == gmSuperHero
617
			|| mapEl == gmSuperTrack
618
			) dirMap |= 8;
619
		//
620
		switch ( dirMap )
621
		{
622
		case 2:
623
		case 3:
624
			this->dy = 0 - this->dy;
625
			break;
626
 
627
		case 4:
628
		case 12:
629
			this->dx = 0 - this->dx;
630
			break;
631
 
632
		default:
633
			this->dx = 0 - this->dx;
634
			this->dy = 0 - this->dy;
635
			break;
636
		}
637
		//
638
		nextPtr = this->ePtr + ( this->dx + this->dy );
639
		// получим элемент с карты
640
		mapEl = nextPtr[0];
641
		//
642
		switch ( mapEl )
643
		{
644
		//
645
		case gmHero:
646
			if ( sTrackList.GetCount() <= 0 )
647
			{
648
				result = true;
649
			}
650
 
651
		//
652
		case gmSuperHero:
653
		case gmSuperTrack:
654
		case gmTrack:
655
		case gmEmpty:
656
		case gmEnemy2:
657
			break;
658
 
659
		//
660
		default:
661
			// стираем объект
662
			mapDiffList.Add( sMapDiff( this->ePtr, gmWall ) );
663
			// переместим объект
664
			this->ePtr = nextPtr;
665
			// рисуем объект по новым координатам
666
			mapDiffList.Add( sMapDiff( this->ePtr, gmEnemy1 ) );
667
			break;
668
		}
669
		//
670
		break;
671
 
672
	// летим
673
	default:
674
		// стираем объект
675
		mapDiffList.Add( sMapDiff( this->ePtr, gmWall ) );
676
		// переместим объект
677
		this->ePtr = nextPtr;
678
		// рисуем объект по новым координатам
679
		mapDiffList.Add( sMapDiff( this->ePtr, gmEnemy1 ) );
680
		//
681
		break;
682
 
683
	}
684
	//
685
	return result;
686
}
687
 
688
//
689
bool CSpaceEnemy::Move()
690
{
691
	Byte *nextPtr;
692
	Byte mapEl, dirMap;
693
	bool result, heroTrack;
694
 
695
	//
696
	result = false;
697
	//
698
	heroTrack = ( sTrackList.GetCount() > 0 );
699
	// получим координаты места, в которое попадает объект
700
	nextPtr = this->ePtr + ( this->dx + this->dy );
701
	// получим элемент с карты
702
	mapEl = nextPtr[0];
703
	// в зависимости от элемента
704
	switch ( mapEl )
705
	{
706
	// напоролись на игрока или его след
707
	case gmTrack:
708
		result = true;
709
		break;
710
 
711
	//
712
	case gmHero:
713
		if ( heroTrack )
714
		{
715
			result = true;
716
			break;
717
		}
718
 
719
	// надо отскакивать
720
	case gmSuperHero:
721
	case gmSuperTrack:
722
	case gmBonus1:
723
	case gmBonus2:
724
	case gmEnemy1:
725
	case gmWall:
726
		//
727
		dirMap = 0;
728
		// -dx +dy
729
		mapEl = this->ePtr[this->dy - this->dx];
730
		if ( mapEl == gmWall ||
731
			mapEl == gmEnemy1 ||
732
			mapEl == gmBonus1 ||
733
			mapEl == gmBonus2 ||
734
			mapEl == gmSuperHero ||
735
			mapEl == gmSuperTrack ||
736
			( mapEl == gmHero && !heroTrack )
737
			) dirMap |= 1;
738
		// +dy
739
		mapEl = this->ePtr[this->dy];
740
		if ( mapEl == gmWall ||
741
			mapEl == gmEnemy1 ||
742
			mapEl == gmBonus1 ||
743
			mapEl == gmBonus2 ||
744
			mapEl == gmSuperHero ||
745
			mapEl == gmSuperTrack ||
746
			( mapEl == gmHero && !heroTrack )
747
			) dirMap |= 2;
748
		// +dx
749
		mapEl = this->ePtr[this->dx];
750
		if ( mapEl == gmWall ||
751
			mapEl == gmEnemy1 ||
752
			mapEl == gmBonus1 ||
753
			mapEl == gmBonus2 ||
754
			mapEl == gmSuperHero ||
755
			mapEl == gmSuperTrack ||
756
			( mapEl == gmHero && !heroTrack )
757
			) dirMap |= 4;
758
		// +dx -dy
759
		mapEl = this->ePtr[this->dx - this->dy];
760
		if ( mapEl == gmWall ||
761
			mapEl == gmEnemy1 ||
762
			mapEl == gmBonus1 ||
763
			mapEl == gmBonus2 ||
764
			mapEl == gmSuperHero ||
765
			mapEl == gmSuperTrack ||
766
			( mapEl == gmHero && !heroTrack )
767
			) dirMap |= 8;
768
		//
769
		switch ( dirMap )
770
		{
771
		case 2:
772
		case 3:
773
			this->dy = 0 - this->dy;
774
			break;
775
 
776
		case 4:
777
		case 12:
778
			this->dx = 0 - this->dx;
779
			break;
780
 
781
		default:
782
			this->dx = 0 - this->dx;
783
			this->dy = 0 - this->dy;
784
			break;
785
		}
786
		//
787
		nextPtr = this->ePtr + ( this->dx + this->dy );
788
		// получим элемент с карты
789
		mapEl = nextPtr[0];
790
		//
791
		switch ( mapEl )
792
		{
793
		//
794
		case gmTrack:
795
			result = true;
796
			break;
797
 
798
		//
799
		case gmHero:
800
			if ( heroTrack )
801
			{
802
				result = true;
803
				break;
804
			}
805
 
806
		//
807
		case gmSuperHero:
808
		case gmSuperTrack:
809
		case gmBonus1:
810
		case gmBonus2:
811
		case gmWall:
812
		case gmEnemy1:
813
			break;
814
 
815
		//
816
		default:
817
			// стираем объект
818
			mapDiffList.Add( sMapDiff( this->ePtr, gmEmpty ) );
819
			// переместим объект
820
			this->ePtr = nextPtr;
821
			// рисуем объект по новым координатам
822
			mapDiffList.Add( sMapDiff( this->ePtr, gmEnemy2 ) );
823
			break;
824
		}
825
		//
826
		break;
827
 
828
	// летим
829
	default:
830
		// стираем объект
831
		mapDiffList.Add( sMapDiff( this->ePtr, gmEmpty ) );
832
		// переместим объект
833
		this->ePtr = nextPtr;
834
		// рисуем объект по новым координатам
835
		mapDiffList.Add( sMapDiff( this->ePtr, gmEnemy2 ) );
836
		//
837
		break;
838
 
839
	}
840
	//
841
 
842
	//
843
	return result;
844
}
845
 
846
 
847
//
848
MCArray mapEnemies;
849
 
850
 
851
//
852
void xonixFree(void)
853
{
854
	clearWorldMap();
855
	if ( flipMapPtr != NULL )
856
	{
857
		delete flipMapPtr;
858
		flipMapPtr = NULL;
859
	}
860
}
861
 
862
 
863
//
864
void checkAndSetBonus2()
865
{
866
	Dword i;
867
 
868
	//
869
	if ( (!bonus2Set)
870
		&& rtlRand() < 0x40000000
871
		&& lifeCount < 3
872
		&& GetCompletePercents() > 50 )
873
	{
874
		//
875
		bonus2Set = true;
876
		//
877
		for ( i = rtlRand() % (mapSizeX * mapSizeY); worldMap[i] != gmWall; i = rtlRand() % (mapSizeX * mapSizeY) );
878
		//
879
		mapDiffList.Add( sMapDiff( worldMap + i, gmBonus2 ) );
880
	}
881
}
882
 
883
 
884
//
885
void ChangeHero()
886
{
887
	if ( bonus1Count < 1 )
888
	{
889
		currentHero = gmHero;
890
		currentTrack = gmTrack;
891
	}
892
	else
893
	{
894
		currentHero = gmSuperHero;
895
		currentTrack = gmSuperTrack;
896
	}
897
}
898
 
899
 
900
//
901
void checkAndSetBonus1()
902
{
903
	Dword i;
904
 
905
	//
906
	if ( (!bonus1Set)
907
		&& rtlRand() > 0x80000000
908
		&& lifeCount < 2
909
		&& GetCompletePercents() > 75 )
910
	{
911
		//
912
		bonus1Set = true;
913
		//
914
		for ( i = rtlRand() % (mapSizeX * mapSizeY); worldMap[i] != gmWall; i = rtlRand() % (mapSizeX * mapSizeY) );
915
		//
916
		mapDiffList.Add( sMapDiff( worldMap + i, gmBonus1 ) );
917
	}
918
}
919
 
920
 
921
//
922
void CreateFlipMap(void)
923
{
924
	Word i, j;
925
	int ndx, ndx2, k;
926
	flipMapEl el;
927
	static int lastMapSizeX = 0, lastMapSizeY = 0;
928
 
929
	//
930
	if ( lastMapSizeX != mapSizeX || lastMapSizeY != mapSizeY )
931
	{
932
		//
933
		lastMapSizeX = mapSizeX;
934
		lastMapSizeY = mapSizeY;
935
		//
936
		if ( flipMapPtr != NULL )
937
		{
938
			delete flipMapPtr;
939
			flipMapPtr = NULL;
940
		}
941
	}
942
	//
943
	if ( flipMapPtr == NULL )
944
	{
945
		flipMapPtr = new flipMapEl[flipMapSize];
946
		//
947
		ndx = 0;
948
		//
949
		for ( i = 0; i < mapSizeY; i += 2 )
950
		{
951
			for ( j = 0; j < mapSizeX; j += 2 )
952
			{
953
				//
954
				flipMapPtr[ndx].x = j;
955
				flipMapPtr[ndx].y = i;
956
				//
957
				ndx++;
958
			}
959
		}
960
	}
961
	//
962
	for ( k = 0; k < flipMapSize; k++ )
963
	{
964
		//
965
		ndx = rtlRand() % flipMapSize;
966
		ndx2 = rtlRand() % flipMapSize;
967
		//
968
		el = flipMapPtr[ndx];
969
		flipMapPtr[ndx] = flipMapPtr[ndx2];
970
		flipMapPtr[ndx2] = el;
971
	}
972
}
973
 
974
 
975
//
976
bool ProcessEndTrack()
977
{
978
	int i, j, k, m;
979
	bool noFill;
980
	Byte *mPtr, *findPtr;
981
 
982
	//
983
	j = sTrackList.GetCount();
984
	//
985
	scoreCount += j;
986
	//
987
	for ( i = 0; i < j; i++ )
988
	{
989
		//
990
		mapDiffList.Add( sMapDiff( sTrackList[i], gmWall ) );
991
	}
992
	//
993
	levelFillCount -= j;
994
	//
995
	sTrackList.Clear();
996
	//
997
	heroPtr += heroDX + heroDY;
998
	mapDiffList.Add( sMapDiff( heroPtr, currentHero ) );
999
	//
1000
	heroDX = 0;
1001
	heroDY = 0;
1002
	lastMoveDirection = 0;
1003
	// заливка
1004
	mPtr = worldMap;
1005
	//
1006
	for ( i = 0; i < mapSizeY; i++ )
1007
	{
1008
		for ( j = 0; j < mapSizeX; j++ )
1009
		{
1010
			//
1011
			if ( mPtr[0] == gmEmpty )
1012
			{
1013
				//
1014
				fillList.Clear();
1015
				//
1016
				noFill = false;
1017
				//
1018
				fillList.Add( mPtr );
1019
				//
1020
				mPtr[0] = gmProbe;
1021
				//
1022
				for ( k = 0; k < fillList.GetCount(); k++ )
1023
				{
1024
					// справа
1025
					findPtr = fillList[k] + 1;
1026
					//
1027
					switch ( findPtr[0] )
1028
					{
1029
					case gmEmpty:
1030
						fillList.Add( findPtr );
1031
						findPtr[0] = gmProbe;
1032
						break;
1033
					case gmEnemy2:
1034
						noFill = true;
1035
						break;
1036
					default:
1037
						break;
1038
					}
1039
					// слева
1040
					findPtr = fillList[k] - 1;
1041
					//
1042
					switch ( findPtr[0] )
1043
					{
1044
					case gmEmpty:
1045
						fillList.Add( findPtr );
1046
						findPtr[0] = gmProbe;
1047
						break;
1048
					case gmEnemy2:
1049
						noFill = true;
1050
						break;
1051
					default:
1052
						break;
1053
					}
1054
					// сверху
1055
					findPtr = fillList[k] - mapSizeX;
1056
					//
1057
					switch ( findPtr[0] )
1058
					{
1059
					case gmEmpty:
1060
						fillList.Add( findPtr );
1061
						findPtr[0] = gmProbe;
1062
						break;
1063
					case gmEnemy2:
1064
						noFill = true;
1065
						break;
1066
					default:
1067
						break;
1068
					}
1069
					// снизу
1070
					findPtr = fillList[k] + mapSizeX;
1071
					//
1072
					switch ( findPtr[0] )
1073
					{
1074
					case gmEmpty:
1075
						fillList.Add( findPtr );
1076
						findPtr[0] = gmProbe;
1077
						break;
1078
					case gmEnemy2:
1079
						noFill = true;
1080
						break;
1081
					default:
1082
						break;
1083
					}
1084
				}
1085
				//
1086
				if ( noFill )
1087
				{
1088
					//
1089
					fillList.Clear();
1090
				}
1091
				else
1092
				{
1093
					//
1094
					m = fillList.GetCount();
1095
					//
1096
					scoreCount += m;
1097
					//
1098
					for ( k = 0; k < m; k++ )
1099
					{
1100
						//
1101
						mapDiffList.Add( sMapDiff( fillList[k], gmWall ) );
1102
					}
1103
					//
1104
					levelFillCount -= m;
1105
				}
1106
			}
1107
			else
1108
			{
1109
				mPtr++;
1110
			}
1111
		}
1112
	}
1113
	//
1114
	mPtr = worldMap;
1115
	//
1116
	for ( i = 0; i < mapSizeY; i++ )
1117
	{
1118
		for ( j = 0; j < mapSizeX; j++ )
1119
		{
1120
			//
1121
			if ( mPtr[0] == gmProbe ) mPtr[0] = gmEmpty;
1122
			//
1123
			mPtr++;
1124
		}
1125
	}
1126
	//
1127
	checkAndSetBonus1();
1128
	checkAndSetBonus2();
1129
	//
1130
	ApplyMapDiffs();
1131
	//
1132
	return levelFillCount <= levelFillEdge;
1133
}
1134
 
1135
 
1136
//
1137
void EatEnemy( Byte *enemyPos )
1138
{
1139
	bool Eat = true;
1140
	int i, j;
1141
 
1142
	//
1143
	while ( Eat )
1144
	{
1145
		//
1146
		Eat = false;
1147
		//
1148
		j = mapEnemies.GetCount();
1149
		//
1150
		for ( i = 0; i < j; i++ )
1151
		{
1152
			//
1153
			if ( mapEnemies[i]->ePtr == enemyPos )
1154
			{
1155
				//
1156
				delete mapEnemies[i];
1157
				//
1158
				mapEnemies.RemoveAt( i );
1159
				//
1160
				Eat = true;
1161
				//
1162
				scoreCount += EAT_ENEMY_BONUS;
1163
				//
1164
				break;
1165
			}
1166
		}
1167
	}
1168
}
1169
 
1170
 
1171
//
1172
bool MoveHero()
1173
{
1174
	int ddx;
1175
	Byte *nextPtr;
1176
	Byte mapEl;
1177
	bool result;
1178
 
1179
	//
1180
	if ( heroDX == 0 && heroDY == 0 ) return false;
1181
	//
1182
	result = false;
1183
	//
1184
	nextPtr = heroPtr + ( heroDX + heroDY );
1185
	//
1186
	ddx = ( ( heroPtr - worldMap ) % mapSizeX ) - ( ( nextPtr - worldMap ) % mapSizeX );
1187
	//
1188
	if ( ddx < -1 || ddx > 1 || nextPtr < worldMap || nextPtr >= ( worldMap + ( mapSizeX * mapSizeY ) ) )
1189
	{
1190
		heroDX = 0;
1191
		heroDY = 0;
1192
		return false;
1193
	}
1194
 
1195
 
1196
	//
1197
	mapEl = nextPtr[0];
1198
	//
1199
	if ( sTrackList.GetCount() > 0 )
1200
	{
1201
		//
1202
		switch ( mapEl )
1203
		{
1204
		//
1205
		case gmEmpty:
1206
			sTrackList.Add( nextPtr );
1207
			break;
1208
		//
1209
		case gmBonus1:
1210
			bonus1Count = BONUS1_LIFETIME;
1211
			ChangeHero();
1212
			goToNextLevel = ProcessEndTrack();
1213
			return false;
1214
			break;
1215
		//
1216
		case gmBonus2:
1217
			lifeCount++;
1218
			goToNextLevel = ProcessEndTrack();
1219
			return false;
1220
			break;
1221
		//
1222
		case gmWall:
1223
			goToNextLevel = ProcessEndTrack();
1224
			return false;
1225
			break;
1226
		//
1227
		case gmEnemy1:
1228
			if ( bonus1Count > 0 )
1229
			{
1230
				//
1231
				EatEnemy( nextPtr );
1232
				//
1233
				goToNextLevel = ProcessEndTrack();
1234
				//
1235
				return false;
1236
				break;
1237
			}
1238
			else
1239
			{
1240
				//
1241
				return true;
1242
			}
1243
			break;
1244
		//
1245
		case gmEnemy2:
1246
			if ( bonus1Count > 0 )
1247
			{
1248
				//
1249
				EatEnemy( nextPtr );
1250
				sTrackList.Add( nextPtr );
1251
				break;
1252
			}
1253
			else
1254
			{
1255
				//
1256
				return true;
1257
			}
1258
			break;
1259
		//
1260
		default:
1261
			return true;
1262
			break;
1263
		}
1264
	}
1265
	else
1266
	{
1267
		//
1268
		switch ( mapEl )
1269
		{
1270
		//
1271
		case gmEmpty:
1272
			sTrackList.Add( nextPtr );
1273
			break;
1274
		//
1275
		case gmBonus1:
1276
			bonus1Count = BONUS1_LIFETIME;
1277
			break;
1278
		//
1279
		case gmBonus2:
1280
			lifeCount++;
1281
			break;
1282
		//
1283
		case gmWall:
1284
			break;
1285
		//
1286
		case gmEnemy1:
1287
			if ( bonus1Count > 0 )
1288
			{
1289
				EatEnemy( nextPtr );
1290
			}
1291
			else
1292
			{
1293
				result = true;
1294
			}
1295
			break;
1296
		//
1297
		case gmEnemy2:
1298
			if ( bonus1Count > 0 )
1299
			{
1300
				EatEnemy( nextPtr );
1301
				sTrackList.Add( nextPtr );
1302
			}
1303
			else
1304
			{
1305
				result = true;
1306
			}
1307
			break;
1308
		//
1309
		default:
1310
			result = true;
1311
			break;
1312
		}
1313
	}
1314
 
1315
	//
1316
	mapDiffList.Add( sMapDiff( heroPtr, sTrackList.GetCount() <= 1 ? gmWall : currentTrack ) );
1317
	heroPtr = nextPtr;
1318
	mapDiffList.Add( sMapDiff( heroPtr, currentHero ) );
1319
 
1320
	return result;
1321
}
1322
 
1323
 
1324
//
1325
bool MoveEnemies()
1326
{
1327
	bool result;
1328
	int i, j, ir;
1329
 
1330
	//
1331
	result = false;
1332
	ir = 0;
1333
	//
1334
	j = mapEnemies.GetCount();
1335
	//
1336
	for ( i = 0; i < j; i++ )
1337
	{
1338
		ir += ( mapEnemies[i]->Move() ? 1 : 0 );
1339
	}
1340
	//
1341
	result = ( ir != 0 );
1342
	//
1343
	return result;
1344
}
1345
 
1346
 
1347
//
1348
void ApplyMapDiffs( bool drawTitle )
1349
{
1350
	int i, j;
1351
 
1352
	//
1353
	kos_WindowRedrawStatus( 1 );
1354
	//
1355
	if ( drawTitle ) drawWndTitleGo();
1356
	//
1357
	j = mapDiffList.GetCount();
1358
	//
1359
	for ( i = 0; i < j; i++ )
1360
	{
1361
		////
1362
		//kos_DrawBar(
1363
		//	wndXOffet + ( ( ( mapDiffList[i].elPtr - worldMap ) % mapSizeX ) * blockSize ),
1364
		//	wndYOffset + ( ( ( mapDiffList[i].elPtr - worldMap ) / mapSizeX ) * blockSize ),
1365
		//	blockSize, blockSize,
1366
		//	mapColours[mapDiffList[i].mapEl]
1367
		//);
1368
		//
1369
		kos_PutImage(
1370
			mapColours[mapDiffList[i].mapEl],
1371
			blockSize,
1372
			blockSize,
1373
			wndXOffet + ( ( ( mapDiffList[i].elPtr - worldMap ) % mapSizeX ) * blockSize ),
1374
			wndYOffset + ( ( ( mapDiffList[i].elPtr - worldMap ) / mapSizeX ) * blockSize )
1375
			);
1376
	}
1377
	//
1378
	kos_WindowRedrawStatus( 2 );
1379
	//
1380
	mapDiffList.Clear();
1381
}
1382
 
1383
 
1384
//
1385
void DeadHeroProcess()
1386
{
1387
	int i, j;
1388
	Byte *mPtr = beep1;
1389
 
1390
	// beep
1391
	__asm{
1392
		mov eax, 55
1393
		mov ebx, eax
1394
		mov esi, mPtr
1395
		push eax
1396
		int 0x40
1397
		pop eax
1398
	}
1399
	//
1400
	j = sTrackList.GetCount();
1401
	//
1402
	for ( i = 0; i < j; i++ )
1403
	{
1404
		//
1405
		mapDiffList.Add( sMapDiff( sTrackList[i], gmEmpty ) );
1406
	}
1407
	//
1408
	mapDiffList.Add( sMapDiff( heroPtr, sTrackList.GetCount() > 0 ? gmEmpty : gmWall ) );
1409
	//
1410
	sTrackList.Clear();
1411
	//
1412
	heroPtr = worldMap;
1413
	//
1414
	while ( heroPtr[0] != gmWall ) heroPtr++;
1415
	//
1416
	mapDiffList.Add( sMapDiff( heroPtr, gmHero ) );
1417
	//
1418
	noBonus = true;
1419
	//
1420
	lifeCount--;
1421
	//
1422
	heroDX = 0;
1423
	heroDY = 0;
1424
	lastMoveDirection = 0;
1425
}
1426
 
1427
 
1428
//
1429
bool CheckForNextLevel()
1430
{
1431
	//
1432
	if ( goToNextLevel )
1433
	{
1434
		//
1435
		CreateFlipMap();
1436
		goToNextLevel = false;
1437
		currentLevel++;
1438
		appState = appStateHideMap;
1439
		flipMapCount = 0;
1440
		return true;
1441
	}
1442
 
1443
	//
1444
	return false;
1445
}
1446
 
1447
 
1448
//
1449
void SetGameVars()
1450
{
1451
	//
1452
	currentLevel = 1;
1453
	lifeCount = 3;
1454
	noBonus = true;
1455
	bonus1Set = false;
1456
	bonus2Set = false;
1457
	bonus1Count = 0;
1458
	goToNextLevel = false;
1459
	currentHero = gmHero;
1460
	currentTrack = gmTrack;
1461
	scoreCount = 0;
1462
	enterName = -1;
1463
	//
1464
	wndSizeX = ((mapSizeX*blockSize)+2);
1465
	wndSizeY = ((mapSizeY*blockSize)+23);
1466
	//
1467
	kos_ChangeWindow( -1, -1, wndSizeX, wndSizeY );
1468
}
1469
 
1470
//
1471
void SetEntryVars()
1472
{
1473
	//
1474
	wndSizeX = ENTRY_WND_SIZE_X;
1475
	wndSizeY = ENTRY_WND_SIZE_Y;
1476
	//
1477
	kos_ChangeWindow( -1, -1, wndSizeX, wndSizeY );
1478
	kos_SetKeyboardDataMode( KM_SCANS );
1479
}
1480
 
1481
 
1482
//
5098 clevermous 1483
void __cdecl ReleaseTop10()
1805 yogev_ezra 1484
{
1485
	//
1486
	if ( top10Heroes != NULL )
1487
	{
1488
		//
1489
		memcpy( top10Heroes->block, heroTbl, sizeof(heroTbl) );
1490
		//
1491
		top10Heroes->SaveToDisk();
1492
		//
1493
		delete top10Heroes;
1494
	}
1495
}
1496
 
1497
 
1498
//
1499
void PrepareTop10()
1500
{
1501
	//
1502
	top10Heroes = new hiScoreFile;
1503
	//
1504
	atexit( ReleaseTop10 );
1505
	//
1506
	if ( top10Heroes->LoadFromDisk() )
1507
	{
1508
		//
1509
		memcpy( heroTbl, top10Heroes->block, sizeof(heroTbl) );
1510
	}
1511
}
1512
 
1513
 
1514
//
1515
void SetUpTop10()
1516
{
1517
	int i, j;
1518
	Byte keyCode;
1519
 
1520
	//
1521
	while ( kos_CheckForEvent() == 2 ) kos_GetKey( keyCode );
1522
	//
1523
	kos_SetKeyboardDataMode( KM_CHARS );
1524
	//
1525
	kos_ChangeWindow( -1, -1, TOP10_WND_SIZE_X, TOP10_WND_SIZE_Y );
1526
	//
1527
	for ( i = 0; i < TOP_TBL_SIZE; i++ )
1528
	{
1529
		//
1530
		if ( heroTbl[i].score < scoreCount )
1531
		{
1532
			//
1533
			for ( j = TOP_TBL_SIZE - 1; j > i; j-- )
1534
			{
1535
				//
1536
				heroTbl[j] = heroTbl[j-1];
1537
			}
1538
			//
1539
			heroTbl[i].ClearName();
1540
			heroTbl[i].score = scoreCount;
1541
			//
1542
			enterName = i;
1543
			enterCharNdx = 0;
1544
			//
1545
			break;
1546
		}
1547
	}
1548
}
1549
 
1550
 
1551
//
1552
// точка входа и функция обработки сообщений
1553
//
1554
void kos_Main()
1555
{
1556
	Dword buttonID;
1557
	Byte keyCode;
1558
	Byte *bPtr;
1559
	bool workOn = true;
1560
	char *cPtr;
1561
 
1562
	// отделяем имя модуля от пути
1563
	cPtr = strrchr( kosExePath, '/' );
1564
	// проверка ;)
1565
	if ( cPtr == NULL )
1566
	{
1567
		//
1568
		rtlDebugOutString( "Invalid path to executable." );
1569
		//
1570
		return;
1571
	}
1572
	//
1573
	cPtr[1] = 0;
1574
	//
1575
	strcpy( top10FilePath, kosExePath );
1576
	//
1577
	strcpy( top10FilePath + ((cPtr - kosExePath) + 1), "xonix.t10" );
1578
 
1579
	// выполнение функций инициализации
1580
	kos_SetKeyboardDataMode( KM_SCANS );
1581
	//
1582
	PrepareTop10();
1583
 
1584
	//
1585
	while( workOn )
1586
	{
1587
		switch ( appState )
1588
		{
1589
		//
1590
		case appStateEntry:
1591
			switch ( kos_WaitForEvent() )
1592
			{
1593
			// перерисовка окна
1594
			case 1:
1595
				DrawAppWindow();
1596
				break;
1597
 
1598
			//
1599
			case 2:
1600
				kos_GetKey( keyCode );
1601
				switch ( keyCode )
1602
				{
1603
				//
1604
				case 2:
1605
					//
1606
					appState = appStateGo;
1607
					SetGameVars();
1608
					initWorldMap();
1609
					DrawAppWindow();
1610
					break;
1611
 
1612
				//
1613
				case 3:
1614
					xonixFree();
1615
					workOn = false;
1616
					break;
1617
				}
1618
				break;
1619
			//
1620
			case 3:
1621
				//
1622
				if ( ! kos_GetButtonID( buttonID ) ) break;
1623
				//
1624
				switch ( buttonID )
1625
				{
1626
				//
1627
				case BT_SIZE_X_PLUS:
1628
					mapSizeX += 2;
1629
					if ( mapSizeX > MAX_X_SIZE ) mapSizeX = MAX_X_SIZE;
1630
					break;
1631
				//
1632
				case BT_SIZE_X_MINUS:
1633
					mapSizeX -= 2;
1634
					if ( mapSizeX < MIN_X_SIZE ) mapSizeX = MIN_X_SIZE;
1635
					break;
1636
				//
1637
				case BT_SIZE_Y_PLUS:
1638
					mapSizeY += 2;
1639
					if ( mapSizeY > MAX_Y_SIZE ) mapSizeY = MAX_Y_SIZE;
1640
					break;
1641
				//
1642
				case BT_SIZE_Y_MINUS:
1643
					mapSizeY -= 2;
1644
					if ( mapSizeY < MIN_Y_SIZE ) mapSizeY = MIN_Y_SIZE;
1645
					break;
1646
				//
1647
				case BT_LOOP_MINUS:
1648
					loopDelay++;;
1649
					if ( loopDelay > MAX_LOOP_DELAY ) loopDelay = MAX_LOOP_DELAY;
1650
					break;
1651
				//
1652
				case BT_LOOP_PLUS:
1653
					loopDelay--;;
1654
					if ( loopDelay < MIN_LOOP_DELAY ) loopDelay = MIN_LOOP_DELAY;
1655
					break;
1656
				//
1657
				default:
1658
					break;
1659
				}
1660
				DrawAppWindow();
1661
				break;
1662
			//
1663
			default:
1664
				break;
1665
			}
1666
			break;
1667
		//
1668
		case appStateGo:
1669
			//
1670
			kos_Pause( loopDelay );
1671
			//
1672
			if ( bonus1Count > 0 ) bonus1Count--;
1673
			//
1674
			ChangeHero();
1675
			//
1676
			switch( kos_WaitForEvent( 1 ) )
1677
			{
1678
			//
1679
			case 0:
1680
				if ( MoveHero() )
1681
				{
1682
					//
1683
					DeadHeroProcess();
1684
				}
1685
				else
1686
				{
1687
					//
1688
					if ( CheckForNextLevel() )
1689
					{
1690
						break;
1691
					}
1692
				}
1693
				if ( MoveEnemies() )
1694
				{
1695
					// сожрали игрока
1696
					DeadHeroProcess();
1697
				}
1698
				ApplyMapDiffs();
1699
				break;
1700
			//
1701
			case 1:
1702
				DrawAppWindow();
1703
				break;
1704
 
1705
			//
1706
			case 2:
1707
				do kos_GetKey( keyCode ); while ( keyCode & 0x80 );
1708
				switch ( keyCode )
1709
				{
1710
				//
1711
				case 0x1:
1712
					SetEntryVars();
1713
					appState = appStateEntry;
1714
					clearWorldMap();
1715
					DrawAppWindow();
1716
					continue;
1717
 
1718
				//
1719
				case 0x39:
1720
					appState = appStatePause;
1721
					break;
1722
 
1723
				//
1724
				case 0x48:
1725
					heroDX = 0;
1726
					if ( lastMoveDirection == 0x50 )
1727
					{
1728
						heroDY = 0;
1729
						lastMoveDirection = 0;
1730
					}
1731
					else
1732
					{
1733
						heroDY = -mapSizeX;
1734
						lastMoveDirection = 0x48;
1735
					}
1736
					break;
1737
 
1738
				//
1739
				case 0x50:
1740
					heroDX = 0;
1741
					if ( lastMoveDirection == 0x48 )
1742
					{
1743
						heroDY = 0;
1744
						lastMoveDirection = 0;
1745
					}
1746
					else
1747
					{
1748
						heroDY = mapSizeX;
1749
						lastMoveDirection = 0x50;
1750
					}
1751
					break;
1752
 
1753
				//
1754
				case 0x4B:
1755
					heroDY = 0;
1756
					if ( lastMoveDirection == 0x4D )
1757
					{
1758
						heroDX = 0;
1759
						lastMoveDirection = 0;
1760
					}
1761
					else
1762
					{
1763
						heroDX = -1;
1764
						lastMoveDirection = 0x4B;
1765
					}
1766
					break;
1767
 
1768
				//
1769
				case 0x4D:
1770
					heroDY = 0;
1771
					if ( lastMoveDirection == 0x4B )
1772
					{
1773
						heroDX = 0;
1774
						lastMoveDirection = 0;
1775
					}
1776
					else
1777
					{
1778
						heroDX = 1;
1779
						lastMoveDirection = 0x4D;
1780
					}
1781
					break;
1782
				}
1783
				//
1784
				if ( MoveHero() )
1785
				{
1786
					//
1787
					DeadHeroProcess();
1788
				}
1789
				else
1790
				{
1791
					//
1792
					if ( CheckForNextLevel() )
1793
					{
1794
						break;
1795
					}
1796
				}
1797
				if ( MoveEnemies() )
1798
				{
1799
					// сожрали игрока
1800
					DeadHeroProcess();
1801
				}
1802
				ApplyMapDiffs();
1803
				break;
1804
 
1805
			//
1806
			default:
1807
				//
1808
				if ( MoveHero() )
1809
				{
1810
					//
1811
					DeadHeroProcess();
1812
				}
1813
				if ( MoveEnemies() )
1814
				{
1815
					// сожрали игрока
1816
					DeadHeroProcess();
1817
				}
1818
				ApplyMapDiffs();
1819
				break;
1820
			}
1821
			//
1822
			if ( lifeCount <= 0 )
1823
			{
1824
				appState = appStateAfterDeath;
1825
				DrawAppWindow();
1826
			}
1827
			//
1828
			break;
1829
 
1830
		//
1831
		case appStateAfterDeath:
1832
			switch ( kos_WaitForEvent() )
1833
			{
1834
			//
1835
			case 1:
1836
				DrawAppWindow();
1837
				break;
1838
			//
1839
			case 2:
1840
				do kos_GetKey( keyCode ); while ( keyCode & 0x80 );
1841
				if ( keyCode != 0 )
1842
				{
1843
					//
1844
					appState = appStateTop10;
1845
					SetUpTop10();
1846
					DrawAppWindow();
1847
				}
1848
				break;
1849
			//
1850
			case 3:
1851
				if ( kos_GetButtonID( buttonID ) )
1852
				{
1853
					//
1854
					if ( buttonID == 1 )
1855
					{
1856
						//
1857
						appState = appStateTop10;
1858
						SetUpTop10();
1859
						DrawAppWindow();
1860
					}
1861
				}
1862
			//
1863
			default:
1864
				break;
1865
			}
1866
			break;
1867
 
1868
		//
1869
		case appStateTop10:
1870
			switch ( kos_WaitForEvent() )
1871
			{
1872
			//
1873
			case 1:
1874
				DrawAppWindow();
1875
				break;
1876
			//
1877
			case 2:
1878
				//
1879
				kos_GetKey( keyCode );
1880
				//
1881
				if ( enterName < 0 )
1882
				{
1883
					//
1884
					if ( keyCode == 0x1b )
1885
					{
1886
						//
1887
						SetEntryVars();
1888
						clearWorldMap();
1889
						appState = appStateEntry;
1890
						DrawAppWindow();
1891
					}
1892
				}
1893
				else
1894
				{
1895
					//
1896
					switch ( keyCode )
1897
					{
1898
					//
1899
					case 13:
1900
						//
1901
						enterName = -1;
1902
						break;
1903
					//
1904
					case 8:
1905
						//
1906
						if ( enterCharNdx > 0 )
1907
						{
1908
							//
1909
							heroTbl[enterName].name[--enterCharNdx] = '.';
1910
						}
1911
						break;
1912
					//
1913
					default:
1914
						if ( keyCode >= 0x20 )
1915
						{
1916
							//
1917
							heroTbl[enterName].name[enterCharNdx++] = keyCode;
1918
							//
1919
							if ( enterCharNdx >= sizeof(heroTbl[0].name) )
1920
							{
1921
								//
1922
								enterName = -1;
1923
							}
1924
						}
1925
						break;
1926
					}
1927
					//
1928
					DrawAppWindow();
1929
				}
1930
				//
1931
				break;
1932
			//
1933
			default:
1934
				break;
1935
			}
1936
			break;
1937
 
1938
		//
1939
		case appStatePause:
1940
			switch ( kos_WaitForEvent() )
1941
			{
1942
			case 1:
1943
				DrawAppWindow();
1944
				break;
1945
 
1946
			case 2:
1947
				do kos_GetKey( keyCode ); while ( keyCode & 0x80 );
1948
				if ( keyCode != 0 )
1949
				{
1950
					//
1951
					appState = appStateGo;
1952
				}
1953
				break;
1954
 
1955
			default:
1956
				break;
1957
			}
1958
			break;
1959
 
1960
		//
1961
		case appStateHideMap:
1962
			//
1963
			switch ( kos_WaitForEvent( 1 ) )
1964
			{
1965
			case 1:
1966
				DrawAppWindow();
1967
				break;
1968
			case 2:
1969
				while ( kos_GetKey( keyCode ) );
1970
				break;
1971
			default:
1972
				bPtr = worldMap + (flipMapPtr[flipMapCount].x + (flipMapPtr[flipMapCount].y * mapSizeX));
1973
				mapDiffList.Add( sMapDiff( bPtr, gmFlip ) );
1974
				mapDiffList.Add( sMapDiff( bPtr + 1, gmFlip ) );
1975
				mapDiffList.Add( sMapDiff( bPtr + mapSizeX, gmFlip ) );
1976
				mapDiffList.Add( sMapDiff( bPtr + (mapSizeX + 1), gmFlip ) );
1977
				ApplyMapDiffs( false );
1978
				break;
1979
			}
1980
			//
1981
			flipMapCount++;
1982
			//
1983
			if ( flipMapCount >= flipMapSize )
1984
			{
1985
				flipMapCount = 0;
1986
				appState = appStateShowMap;
1987
				DrawAppWindow();
1988
			}
1989
			break;
1990
		//
1991
		case appStateShowMap:
1992
			//
1993
			switch ( kos_WaitForEvent( 1 ) )
1994
			{
1995
			case 1:
1996
				DrawAppWindow();
1997
				break;
1998
			default:
1999
				break;
2000
			}
2001
			//
2002
			flipMapCount++;
2003
			//
2004
			if ( flipMapCount >= BEFORE_START_LEVEL )
2005
			{
2006
				clearWorldMap();
2007
				flipMapCount = 0;
2008
				initWorldMap();
2009
				appState = appStateGo;
2010
				DrawAppWindow();
2011
			}
2012
			//
2013
			break;
2014
		}
2015
	}
2016
}
2017
 
2018
 
2019
//
2020
void DrawEntryScreen()
2021
{
2022
	PRINTK pr;
2023
	char line[64];
2024
 
2025
	//
2026
	kos_DefineAndDrawWindow(
2027
		100, 100,
2028
		wndSizeX, wndSizeY,
2029
		0, 0,
2030
		0, 0x2040A0,
2031
		0x2040A0
2032
		);
2033
	//
2034
	kos_WriteTextToWindow(
2035
		4, 4,
2036
		0x10, 0x42D2E2,
2037
		MainWindowTitle,
2038
		sizeof( MainWindowTitle ) - 1
2039
		);
2040
	//
2041
	kos_WriteTextToWindow(
2042
		8, 32,
2043
		0x10, 0x12FF12,
2044
		menuStr1,
2045
		sizeof( menuStr1 ) - 1
2046
		);
2047
	//
2048
	kos_WriteTextToWindow(
2049
		8, 48,
2050
		0x10, 0x12FF12,
2051
		menuStr2,
2052
		sizeof( menuStr2 ) - 1
2053
		);
2054
	//
2055
	kos_WriteTextToWindow(
2056
		8, 80,
2057
		0x10, 0xD0FF12,
2058
		menuStr3,
2059
		sizeof( menuStr3 ) - 1
2060
		);
2061
	//
2062
	kos_WriteTextToWindow(
2063
		8, 96,
2064
		0x10, 0xD0FF12,
2065
		menuStr4,
2066
		sizeof( menuStr4 ) - 1
2067
		);
2068
	// размер поля
2069
	pr.fmtline = worldSizeStr;
2070
	pr.args[0] = mapSizeX;
2071
	pr.args[1] = mapSizeY;
2072
	sprintk( line, &pr );
2073
	//
2074
	kos_WriteTextToWindow(
2075
		8, 112,
2076
		0x10, 0x12C0D0,
2077
		line,
2078
		strlen( line )
2079
		);
2080
	// кнопки X
2081
	kos_DefineButton(
2082
		ENTRY_WND_SIZE_X - 58, 112,
2083
		12, 12,
2084
		BT_SIZE_X_MINUS,
2085
		0xCCCCCC
2086
		);
2087
	//
2088
	kos_PutImage( bmPMButton + 12, 6, 2, ENTRY_WND_SIZE_X - 58 + 3, 117 );
2089
	//
2090
	kos_DefineButton(
2091
		ENTRY_WND_SIZE_X - 45, 112,
2092
		12, 12,
2093
		BT_SIZE_X_PLUS,
2094
		0xCCCCCC
2095
		);
2096
	//
2097
	kos_PutImage( bmPMButton, 6, 6, ENTRY_WND_SIZE_X - 45 + 3, 115 );
2098
	// кнопки Y
2099
	kos_DefineButton(
2100
		ENTRY_WND_SIZE_X - 29, 112,
2101
		12, 12,
2102
		BT_SIZE_Y_MINUS,
2103
		0xCCCCCC
2104
		);
2105
	//
2106
	kos_PutImage( bmPMButton + 12, 6, 2, ENTRY_WND_SIZE_X - 29 + 3, 117 );
2107
	//
2108
	kos_DefineButton(
2109
		ENTRY_WND_SIZE_X - 16, 112,
2110
		12, 12,
2111
		BT_SIZE_Y_PLUS,
2112
		0xCCCCCC
2113
		);
2114
	//
2115
	kos_PutImage( bmPMButton, 6, 6, ENTRY_WND_SIZE_X - 16 + 3, 115 );
2116
	//
2117
	//задержка в цикле выборки сообщений
2118
	pr.fmtline = mainLoopDelayStr;
2119
	pr.args[0] = MAX_LOOP_DELAY + MIN_LOOP_DELAY - loopDelay;
2120
	sprintk( line, &pr );
2121
	//
2122
	kos_WriteTextToWindow(
2123
		8, 128,
2124
		0x10, 0x12C0D0,
2125
		line,
2126
		strlen( line )
2127
		);
2128
	//
2129
	kos_DefineButton(
2130
		ENTRY_WND_SIZE_X - 29, 128,
2131
		12, 12,
2132
		BT_LOOP_MINUS,
2133
		0xCCCCCC
2134
		);
2135
	//
2136
	kos_PutImage( bmPMButton + 12, 6, 2, ENTRY_WND_SIZE_X - 29 + 3, 133 );
2137
	//
2138
	kos_DefineButton(
2139
		ENTRY_WND_SIZE_X - 16, 128,
2140
		12, 12,
2141
		BT_LOOP_PLUS,
2142
		0xCCCCCC
2143
		);
2144
	//
2145
	kos_PutImage( bmPMButton, 6, 6, ENTRY_WND_SIZE_X - 16 + 3, 131 );
2146
}
2147
 
2148
 
2149
//
2150
void DrawAppWindow()
2151
{
2152
	//
2153
	kos_WindowRedrawStatus( 1 );
2154
 
2155
	switch ( appState )
2156
	{
2157
	//
2158
	case appStateTop10:
2159
		DrawTop10Window();
2160
		break;
2161
	//
2162
	case appStateEntry:
2163
		//
2164
		DrawEntryScreen();
2165
		break;
2166
	//
2167
	case appStateGo:
2168
	case appStateShowMap:
2169
	case appStatePause:
2170
		drawWorldMap();
2171
		break;
2172
	//
2173
	case appStateAfterDeath:
2174
		//
2175
		drawWorldMap();
2176
		//
2177
		kos_DefineButton(
2178
			( wndSizeX / 2 ) - 64,
2179
			( wndSizeY / 2 ) - 16,
2180
			128, 32,
2181
			1,
2182
			0x136793
2183
			);
2184
		//
2185
		kos_WriteTextToWindow(
2186
			( wndSizeX / 2 ) - ( sizeof( thatsAllStr ) * 4 ),
2187
			( wndSizeY / 2 ) - 4,
2188
			0x10, 0xFFFFFF,
2189
			thatsAllStr,
2190
			sizeof ( thatsAllStr ) - 1
2191
			);
2192
 
2193
		//
2194
		break;
2195
	//
2196
	case appStateHideMap:
2197
		drawWorldMapForFlip();
2198
		break;
2199
	}
2200
	//
2201
	kos_WindowRedrawStatus( 2 );
2202
}
2203
 
2204
 
2205
//
2206
void initWorldMap()
2207
{
2208
	int i, j, m, allocSize;
2209
	CWallEnemy *we;
2210
	CSpaceEnemy *se;
2211
 
2212
	//
2213
	allocSize = mapSizeX * mapSizeY;
2214
	worldMap = new Byte[allocSize];
2215
	//
2216
	__asm{
2217
		mov edi, worldMap
2218
		mov ecx, allocSize
2219
		mov al, gmEmpty
2220
		rep stosb
2221
	}
2222
 
2223
 
2224
	//
2225
	levelFillEdge = ( ( currentLevel + 1 ) * spacePerEnemy ) + currentLevel;
2226
	levelFillCount = freeSpaceCount;
2227
	//
2228
	if ( ! noBonus )
2229
	{
2230
		lifeCount++;
2231
	}
2232
	//
2233
	noBonus = false;
2234
	bonus1Set = false;
2235
	bonus2Set = false;
2236
	bonus1Count = 0;
2237
	goToNextLevel = false;
2238
	currentHero = gmHero;
2239
	currentTrack = gmTrack;
2240
 
2241
	//
2242
	for ( i = 0; i < mapSizeX; i++ )
2243
	{
2244
		//
2245
		worldMap[i] = gmWall;
2246
		worldMap[mapSizeX + i] = gmWall;
2247
		//
2248
		worldMap[((mapSizeY-2)*mapSizeX) + i] = gmWall;
2249
		worldMap[((mapSizeY-1)*mapSizeX) + i] = gmWall;
2250
	}
2251
	//
2252
	for ( i = 2; i < (mapSizeY-2); i++ )
2253
	{
2254
		//
2255
		worldMap[(i*mapSizeX)] = gmWall;
2256
		worldMap[(i*mapSizeX) + 1] = gmWall;
2257
		worldMap[(i*mapSizeX) + mapSizeX - 2] = gmWall;
2258
		worldMap[(i*mapSizeX) + mapSizeX - 1] = gmWall;
2259
	}
2260
	//
2261
	heroPtr = worldMap + ( mapSizeX / 2 );
2262
	heroPtr[0] = gmHero;
2263
	heroDX = 0;
2264
	heroDY = 0;
2265
	//
2266
	for ( i = 0; i < currentLevel; i++ )
2267
	{
2268
		//
2269
		for (
2270
			j = ( rtlRand() % (mapSizeX * (mapSizeY - 2)) ) + (mapSizeX * 2);
2271
			worldMap[j] != gmWall;
2272
			j = rtlRand() % (mapSizeX * mapSizeY)
2273
			);
2274
		//
2275
		we = new CWallEnemy();
2276
		//
2277
		we->ePtr = worldMap + j;
2278
		we->dx = rtlRand() & 1 ? 1 : -1;
2279
		we->dy = rtlRand() & 1 ? mapSizeX : -mapSizeX;
2280
		//
2281
		mapEnemies.Add( we );
2282
		//
2283
		worldMap[j] = gmEnemy1;
2284
	}
2285
	//
2286
	m = currentLevel + 1;
2287
	//
2288
	for ( i = 0; i < m; i++ )
2289
	{
2290
		//
2291
		for (
2292
			j = rtlRand() % (mapSizeX * mapSizeY);
2293
			worldMap[j] != gmEmpty;
2294
			j = rtlRand() % (mapSizeX * mapSizeY)
2295
			);
2296
		//
2297
		se = new CSpaceEnemy();
2298
		//
2299
		se->ePtr = worldMap + j;
2300
		se->dx = rtlRand() & 1 ? 1 : -1;
2301
		se->dy = rtlRand() & 1 ? mapSizeX : -mapSizeX;
2302
		//
2303
		mapEnemies.Add( se );
2304
		//
2305
		worldMap[j] = gmEnemy2;
2306
	}
2307
}
2308
 
2309
 
2310
//
2311
void drawWorldMap()
2312
{
2313
	//
2314
	kos_DefineAndDrawWindow(
2315
		100, 100,
2316
		wndSizeX, wndSizeY,
2317
		0, 0,
2318
		0, 0x2040A0,
2319
		0x2040A0
2320
		);
2321
	//
2322
	drawWndTitleGo();
2323
	//
2324
	drawWorldMapForFlip();
2325
}
2326
 
2327
 
2328
//
2329
int GetCompletePercents()
2330
{
2331
	int n1, n2;
2332
 
2333
	//
2334
	n1 = freeSpaceCount - levelFillCount;
2335
	n2 = freeSpaceCount - levelFillEdge;
2336
	//
2337
	return ( n1 >= n2 ) ? 100 : ( n1 * 100 ) / n2;
2338
}
2339
 
2340
 
2341
//
2342
void drawWndTitleGo()
2343
{
2344
	PRINTK pr;
2345
	char line[64];
2346
 
2347
	//
2348
	kos_DrawBar(
2349
		1, 1,
2350
		wndSizeX - 2, 18,
2351
		0x2040A0
2352
		);
2353
 
2354
	//
2355
	pr.fmtline = goWndTitle;
2356
	pr.args[0] = currentLevel;
2357
	pr.args[1] = GetCompletePercents();
2358
	pr.args[2] = lifeCount;
2359
	pr.args[3] = scoreCount;
2360
	sprintk( line, &pr );
2361
	//
2362
	kos_WriteTextToWindow(
2363
		4, 4,
2364
		0x10, 0x42D2E2,
2365
		line,
2366
		strlen( line )
2367
		);
2368
	//
2369
	if ( bonus1Count > 0 )
2370
	{
2371
		//
2372
		kos_DrawBar(
2373
			2, 22 - BONUS1_IND_HSIZE - 1,
2374
			wndSizeX - 4, BONUS1_IND_HSIZE,
2375
			0x2040A0
2376
			);
2377
		//
2378
		kos_DrawBar(
2379
			2, 22 - BONUS1_IND_HSIZE - 1,
2380
			( bonus1Count * ( wndSizeX - 4 ) ) / BONUS1_LIFETIME, BONUS1_IND_HSIZE,
2381
			0x5720B0
2382
			);
2383
	}
2384
}
2385
 
2386
//
2387
void drawWorldMapForFlip()
2388
{
2389
	int i, j;
2390
	Byte *mPtr = worldMap;
2391
 
2392
	//
2393
	for ( i = 0; i < mapSizeY; i++ )
2394
	{
2395
		//
2396
		for ( j = 0; j < mapSizeX; j++ )
2397
		{
2398
			////
2399
			//kos_DrawBar(
2400
			//	wndXOffet + ( j * blockSize ),
2401
			//	wndYOffset + ( i * blockSize ),
2402
			//	blockSize, blockSize,
2403
			//	mapColours[*mPtr]
2404
			//);
2405
			//
2406
			kos_PutImage(
2407
				mapColours[*mPtr],
2408
				blockSize,
2409
				blockSize,
2410
				wndXOffet + ( j * blockSize ),
2411
				wndYOffset + ( i * blockSize )
2412
				);
2413
			//
2414
			mPtr++;
2415
		}
2416
	}
2417
}
2418
 
2419
 
2420
//
2421
void clearWorldMap()
2422
{
2423
	int i, j;
2424
 
2425
	//
2426
	sTrackList.Clear();
2427
	fillList.Clear();
2428
	mapDiffList.Clear();
2429
	//
2430
	j = mapEnemies.GetCount();
2431
	//
2432
	for ( i = 0; i < j; i++ )
2433
	{
2434
		//
2435
		delete mapEnemies[i];
2436
	}
2437
	//
2438
	mapEnemies.Clear();
2439
	//
2440
	if ( worldMap != NULL )
2441
	{
2442
		delete worldMap;
2443
		worldMap = NULL;
2444
	}
2445
}
2446
 
2447
 
2448
//
2449
char Top10WndTitle[] = "Top 10";
2450
 
2451
//
2452
void DrawTop10Window()
2453
{
2454
	int i;
2455
 
2456
	//
2457
	kos_DefineAndDrawWindow(
2458
		100, 100,
2459
		TOP10_WND_SIZE_X, TOP10_WND_SIZE_Y,
2460
		0, 0,
2461
		0, 0x2040A0,
2462
		0x2040A0
2463
		);
2464
	//
2465
	kos_WriteTextToWindow(
2466
		4, 4,
2467
		0x0, 0x42D2E2,
2468
		Top10WndTitle,
2469
		sizeof( Top10WndTitle ) - 1
2470
		);
2471
	//
2472
	for ( i = 0; i < TOP_TBL_SIZE; i++ )
2473
	{
2474
		//
2475
		kos_WriteTextToWindow(
2476
			6, wndYOffset + 2 + (i * 10),
2477
			0x0, enterName != i ? 0xFFFFFF : 0x00FF00,
2478
			heroTbl[i].name,
2479
			sizeof( heroTbl[0].name )
2480
			);
2481
		//
2482
		kos_DisplayNumberToWindow(
2483
			heroTbl[i].score,
2484
			8,
2485
			112, wndYOffset + 2 + (i * 10),
2486
			0xFFFF55,
2487
			nbDecimal,
2488
			false
2489
			);
2490
	}
2491
	//
2492
	kos_WriteTextToWindow(
2493
		6, wndYOffset + 6 + (i * 10),
2494
		0x10, 0x1060D0,
2495
		enterName >= 0 ? top10str1 : top10str2,
2496
		enterName >= 0 ? sizeof(top10str1) - 1 : sizeof(top10str2) - 1
2497
		);
2498
}
2499