Subversion Repositories Kolibri OS

Rev

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