1 /*
2 This file is part of "Avanor, the Land of Mystery" roguelike game
3 Home page: http://www.avanor.com/
4 Copyright (C) 2000-2003 Vadim Gaidukevich
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <stdlib.h>
24 #include "global.h"
25 #include "string.h"
26 
27 unsigned long total_cr  = 0;
28 unsigned long total_it  = 0;
29 unsigned long cr_kiled  = 0;
30 unsigned long cr_died   = 0;
31 
32 
33 const char* color_convert_table[] =
34 {
35 	"\x1F\x00", "\x1F\x01", "\x1F\x02", "\x1F\x03",
36 	"\x1F\x04", "\x1F\x05", "\x1F\x06", "\x1F\x07",
37 	"\x1F\x08", "\x1F\x09", "\x1F\x0A", "\x1F\x0B",
38 	"\x1F\x0C", "\x1F\x0D", "\x1F\x0E", "\x1F\x0F",
39 };
40 
41 int __animation_flag = 100;
42 
43 #ifndef XWIN32
44 char * vscreen;
45 #endif
46 
47 long   size_x = 80;
48 long   size_y = 25;
49 
50 int cursor_pos_x = 0;
51 int cursor_pos_y = 0;
52 int current_attr = 7;
53 
54 #ifdef XWIN32
55 	#include <windows.h>
56 	HANDLE                     hStdout;
57 	HANDLE                     hStdin;
58 	CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
59     CONSOLE_CURSOR_INFO        ccInfo;
60 	CHAR_INFO                 *vscreenw;
61 #endif
62 
vInit()63 void vInit()
64 {
65 #ifdef XLINUX
66 	mkdir(vMakePath(HOME_DIR, ""), 0755);
67 #endif
68 
69 #ifdef XDOS
70 	text_info ti;
71 	gettextinfo(&ti);
72 	size_x = ti.screenwidth;
73 	size_y = ti.screenheight;
74 #endif
75 
76 #ifdef XWIN32
77 	hStdin  = GetStdHandle(STD_INPUT_HANDLE);
78 	hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
79 
80     GetConsoleCursorInfo(hStdout, &ccInfo);
81 
82 	GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
83 	size_x = csbiInfo.srWindow.Right - csbiInfo.srWindow.Left + 1;
84 	size_y = csbiInfo.srWindow.Bottom - csbiInfo.srWindow.Top + 1;
85 
86 	if(size_x != csbiInfo.dwSize.X || size_y != csbiInfo.dwSize.Y)
87 	{
88 		COORD coord = { (short)size_x, (short)size_y };
89 		if(!SetConsoleScreenBufferSize(hStdout, coord))
90 			assert(false);
91 	}
92 
93 	vscreenw = new CHAR_INFO[size_x * size_y];
94 
95 #endif //XWIN32
96 
97 #ifdef XLINUX
98 	initscr();
99 	cbreak();
100 	noecho();
101 	nonl();
102 	raw();
103 	start_color();
104 
105 	init_pair(0,             COLOR_BLACK,   COLOR_BLACK);
106 	init_pair(xBLUE,         COLOR_BLUE,    COLOR_BLACK);
107 	init_pair(xGREEN,        COLOR_GREEN,   COLOR_BLACK);
108 	init_pair(xRED,          COLOR_RED,     COLOR_BLACK);
109 	init_pair(xMAGENTA,      COLOR_MAGENTA, COLOR_BLACK);
110 	init_pair(xCYAN,         COLOR_CYAN,    COLOR_BLACK);
111 	init_pair(xBROWN,        COLOR_YELLOW,  COLOR_BLACK);
112 	init_pair(xLIGHTGRAY,    COLOR_WHITE,   COLOR_BLACK);
113 
114 	init_pair(xLIGHTBLUE,    COLOR_BLUE,    COLOR_BLACK);
115 	init_pair(xLIGHTGREEN,   COLOR_GREEN ,  COLOR_BLACK);
116 	init_pair(xLIGHTRED,     COLOR_RED,     COLOR_BLACK);
117 	init_pair(xLIGHTMAGENTA, COLOR_MAGENTA, COLOR_BLACK);
118 	init_pair(xLIGHTCYAN,    COLOR_CYAN,    COLOR_BLACK);
119 	init_pair(xYELLOW,       COLOR_YELLOW,  COLOR_BLACK);
120 	init_pair(xWHITE,        COLOR_WHITE,   COLOR_BLACK);
121 
122 	size_x = COLS;
123 	size_y = LINES;
124 
125 #endif //XLINUX
126 
127 #ifndef XWIN32
128 	vscreen = new char[size_x * size_y * 2];
129 #endif
130 
131 	vClrScr();
132 }
133 
vClrScr()134 void vClrScr()
135 {
136 #ifdef XWIN32
137 	CHAR_INFO blank_char = { ' ', 7 };
138 	int screenbuf_size = size_x * size_y;
139 	for (int i = 0; i < screenbuf_size; i++)
140 		vscreenw[i] = blank_char;
141 #else
142 	for (int i = 0; i < size_x * size_y * 2; i += 2)
143 	{
144 		vscreen[i] = 32;
145 		vscreen[i + 1] = 7;
146 	}
147 #endif
148 }
149 
vFinit()150 void vFinit()
151 {
152 #ifdef XWIN32
153 	SetConsoleScreenBufferSize(hStdout, csbiInfo.dwSize);
154 	SetConsoleWindowInfo(hStdout, true, &csbiInfo.srWindow);
155     SetConsoleCursorInfo(hStdout, &ccInfo);
156     delete[] vscreenw;
157 #endif
158 #ifdef XLINUX
159 	endwin();
160 #endif
161 #ifndef XWIN32
162 	delete[] vscreen;
163 #endif
164 }
165 
vRefresh()166 void vRefresh()
167 {
168 #ifdef XWIN32
169 	COORD      buffer_size = { (short)size_x, (short)size_y };
170 	COORD      buffer_coord = { 0, 0 };
171 	SMALL_RECT write_region = { 0, 0, size_x - 1, size_y - 1 };
172 
173 	WriteConsoleOutput(hStdout, vscreenw, buffer_size, buffer_coord, &write_region);
174 #endif
175 #ifdef XDOS
176 	puttext(1, 1, size_x, size_y, vscreen);
177 #endif
178 #ifdef XLINUX
179 	move(0, 0);
180 	for (int i = 0; i < size_x * size_y; i++)
181 	{
182 //    attrset(vscreen[i * 1]);
183 		char ch2 = vscreen[i * 2 + 1];
184 		char ch1 = vscreen[i * 2];
185 		if (ch1 < ' ') ch1 = ' ';
186 		if (ch2 > 7)
187 			addch(ch1 | (ch2 << 8) | A_BOLD);
188 		else
189 			addch(ch1 | (ch2 << 8));
190 
191 	}
192 
193 	refresh();
194 #endif
195 }
196 
vPutCh(int x,int y,char ch,int attr)197 void vPutCh(int x, int y, char ch, int attr)
198 {
199 	assert(x >= 0 && y >= 0 && x <= size_x && y <= size_y);
200 #ifdef XWIN32
201 	CHAR_INFO tmp = { ch, attr };
202 	vscreenw[x + y * size_x] = tmp;
203 #else
204 	vscreen[x * 2 + y * size_x * 2] = ch;
205 	vscreen[x * 2 + y * size_x * 2 + 1] = attr;
206 #endif
207 };
208 
vTestCh(int x,int y)209 char vTestCh(int x, int y)
210 {
211 #ifdef XWIN32
212 	return vscreenw[x + y * size_x].Char.AsciiChar;
213 #else
214 	return vscreen[x * 2 + y * size_x * 2];
215 #endif
216 }
217 
vPutCh(int x,int y,char ch)218 void vPutCh(int x, int y, char ch)
219 {
220 #ifdef XWIN32
221 	vscreenw[x + y * size_x].Char.AsciiChar = ch;
222 #else
223 	vscreen[x * 2 + y * size_x * 2] = ch;
224 #endif
225 };
226 
vGotoXY(int x,int y)227 void vGotoXY(int x, int y)
228 {
229 	cursor_pos_x = x;
230 	cursor_pos_y = y;
231 }
232 
vGetCursorPos(int * x,int * y)233 void vGetCursorPos(int * x, int * y)
234 {
235 	*x = cursor_pos_x;
236 	*y = cursor_pos_y;
237 }
238 
vGetS(char * s,int buffer_size)239 int vGetS(char * s, int buffer_size)
240 {
241 	int cx;
242 	int cy;
243 	vGetCursorPos(&cx, &cy);
244 	int buffer_pos = 0;
245 	char ch;
246 	strcpy(s, "");
247 	do
248 	{
249 		vXGotoXY(cx + strlen(s), cy);
250 		ch = vGetch();
251 
252 		s[buffer_pos] = ch;
253 		if (ch == 13 || ch == 27 )
254 		{
255 			s[buffer_pos] = 0;
256 			if (ch == 13)
257 				return 1;
258 			else
259 				return 0;
260 		}
261 		if (ch == 8 && buffer_pos > 0)
262 		{
263 			s[buffer_pos - 1] = ' ';
264 			s[buffer_pos] = 0;
265 			vGotoXY(cx, cy);
266 			vPutS(s);
267 			buffer_pos--;
268 		} else
269 			if (ch != 8)
270 				buffer_pos++;
271 		s[buffer_pos] = 0;
272 		vGotoXY(cx, cy);
273 		vPutS(s);
274 		vRefresh();
275 	} while (buffer_pos < buffer_size - 1);
276 
277 	return 1;
278 }
279 
vDelay(int n)280 void vDelay(int n)
281 {
282 #ifdef XWIN32
283 
284 #endif
285 #ifdef XDOS
286 	delay(n);
287 #endif
288 
289 }
290 
vKbhit()291 int vKbhit()
292 {
293 #ifdef XLINUX
294 	timeout(0);
295 	int ch = getch();
296 	timeout(-1);
297 	if (ch == ERR) return 0;
298 	ungetch(ch);
299 	return 1;
300 #else
301 	return kbhit();
302 #endif
303 }
304 
vGetch()305 int vGetch()
306 {
307 #ifdef XLINUX
308 	int ch = getch();
309 	if (ch != 27) return ch;
310 
311    	timeout(0);
312    	ch = getch();
313    	timeout(-1);
314 
315    	if (ch == ERR) return KEY_ESC;
316    	if (ch != '[') { ungetch(ch); return KEY_ESC; }
317 
318    	switch (getch())
319    	{
320    		case 'A': return KEY_UP;
321    		case 'B': return KEY_DOWN;
322    		case 'C': return KEY_RIGHT;
323    		case 'D': return KEY_LEFT;
324    		case 'G': return KEY_CENTER;
325    		case '1': return getch() == '~' ? KEY_HOME : KEY_UNKNOWN;
326    		case '4': return getch() == '~' ? KEY_END : KEY_UNKNOWN;
327    		case '5': return getch() == '~' ? KEY_PGUP : KEY_UNKNOWN;
328    		case '6': return getch() == '~' ? KEY_PGDOWN : KEY_UNKNOWN;
329    	}
330    	return KEY_UNKNOWN;
331 #else
332 	int ch = getch();
333 	if (ch == 0 || ch == 224) ch = KEY_EXTENDED_CODE | getch();
334 	return ch;
335 #endif
336 }
337 
vXGetch(char * ch_buf)338 int vXGetch(char * ch_buf)
339 {
340 	int slen = strlen(ch_buf);
341 	while (1)
342 	{
343 		int ch = vGetch();
344 		for (int i = 0; i < slen; i++)
345 		{
346 			if (ch == ch_buf[i])
347 				return ch;
348 		}
349 		if (ch == KEY_ESC)
350 			return 0;
351 	}
352 }
353 
vXGotoXY(int x,int y)354 void vXGotoXY(int x, int y)
355 {
356 	cursor_pos_x = x;
357 	cursor_pos_y = y;
358 
359 #ifdef XWIN32
360 	CONSOLE_CURSOR_INFO ConsoleCursorInfo = ccInfo;
361 	ConsoleCursorInfo.bVisible = TRUE;
362 	SetConsoleCursorInfo(hStdout, &ConsoleCursorInfo);
363 
364 	COORD coord;
365 	coord.X = x;
366 	coord.Y = y;
367 	SetConsoleCursorPosition(hStdout, coord);
368 #endif
369 
370 #ifdef XDOS
371 	_setcursortype(_NORMALCURSOR);
372 	gotoxy(x + 1, y + 1);
373 #endif
374 
375 #ifdef XLINUX
376 	move(y, x);
377 #endif
378 
379 }
380 
vHideCursor()381 void vHideCursor()
382 {
383 #ifdef XWIN32
384 //	CONSOLE_CURSOR_INFO ConsoleCursorInfo = ccInfo;
385 //	ConsoleCursorInfo.bVisible = FALSE;
386 //	SetConsoleCursorInfo(hStdout, &ConsoleCursorInfo);
387 #endif
388 
389 #ifdef XDOS
390 	_setcursortype(_NOCURSOR);
391 #endif
392 
393 #ifdef XLINUX
394 	vXGotoXY(size_x, size_y);
395 #endif
396 }
397 
vSetAttr(int color)398 void vSetAttr(int color)
399 {
400 	current_attr = color;
401 }
402 
vClrEol()403 void vClrEol()
404 {
405 	while (cursor_pos_x < size_x)
406 	{
407 		vPutCh(cursor_pos_x, cursor_pos_y, ' ');
408 		cursor_pos_x++;
409 	}
410 }
411 
412 // (31, x) - change attr
413 //
vPutS(const char * s)414 void vPutS(const char * s)
415 {
416 	if(cursor_pos_y >= size_y) cursor_pos_x = cursor_pos_y = 0;
417 
418 	while(true)
419 	{
420 		char ch = *s++;
421 		switch(ch)
422 		{
423 			case 0 :
424 				return;
425 			case 31 :
426 				vSetAttr(*s++); break;
427 			case 13 :
428 			case '\n' :
429 				cursor_pos_x = 0;
430 				if(++cursor_pos_y >= size_y) cursor_pos_y = 0;
431 				break;
432 			default :
433 			{
434 				if(cursor_pos_x >= size_x)
435 				{
436 					cursor_pos_x = 0;
437 					if(++cursor_pos_y >= size_y) cursor_pos_y = 0;
438 				}
439 				vPutCh(cursor_pos_x++, cursor_pos_y, ch, current_attr);
440 			}
441 		}
442 	}
443 }
444 
vFPutS(FILE * f,const char * s)445 void vFPutS(FILE * f, const char * s)
446 {
447 	int pos = 0;
448 	while (s[pos])
449 	{
450 		if (s[pos] == 31)
451 		{
452 			pos +=2;
453 			continue;
454 		}
455 		fprintf(f, "%c", s[pos]);
456 		pos++;
457 	}
458 }
459 
460 static unsigned long randx;
461 
vRandSeed(unsigned long seed)462 void vRandSeed(unsigned long seed)
463 {
464 	randx = seed;
465 }
466 
467 #define X_RAND_A   0x000343FDUL
468 #define X_RAND_B   0x00269EC3UL
469 #define X_RAND_MAX 0x7FFFFFFFUL
470 
vRand()471 long vRand()
472 {
473 	randx = randx * X_RAND_A + X_RAND_B;
474 	unsigned long randhigh = randx & 0x7FFF0000;
475 	randx = randx * X_RAND_A + X_RAND_B;
476 	unsigned long randlow = randx >> 16;
477 	return randhigh | randlow;
478 }
479 
vRand(unsigned long n)480 long vRand(unsigned long n)
481 {
482 	assert(n > 0);
483 	if (n > 0x8000)
484 	{
485 		assert(n <= X_RAND_MAX + 1);
486 		randx = randx * X_RAND_A + X_RAND_B;
487 		unsigned long randhigh = randx & 0x7FFF0000;
488 		randx = randx * X_RAND_A + X_RAND_B;
489 		unsigned long randlow = randx >> 16;
490 		return (randhigh | randlow) % n;
491 	}
492 	else
493 	{
494 		randx = randx * X_RAND_A + X_RAND_B;
495 		return (randx >> 16) % n;
496 	}
497 }
498 
V_BUFFER()499 V_BUFFER::V_BUFFER()
500 {
501 #ifdef XWIN32
502 	buffer = new char[size_x * size_y * sizeof(CHAR_INFO)];
503 #else
504 	buffer = new char[size_x * size_y * 2];
505 #endif
506 }
507 
~V_BUFFER()508 V_BUFFER::~V_BUFFER()
509 {
510 	delete [] buffer;
511 }
512 
vStore(V_BUFFER * buf)513 void vStore(V_BUFFER * buf)
514 {
515 #ifdef XWIN32
516 	memcpy(buf->buffer, vscreenw, size_x * size_y * sizeof(CHAR_INFO));
517 #else
518 	memcpy(buf->buffer, vscreen, size_x * size_y * 2);
519 #endif
520 }
521 
vRestore(V_BUFFER * buf)522 void vRestore(V_BUFFER * buf)
523 {
524 #ifdef XWIN32
525 	memcpy(vscreenw, buf->buffer, size_x * size_y * sizeof(CHAR_INFO));
526 #else
527 	memcpy(vscreen, buf->buffer, size_x * size_y * 2);
528 #endif
529 }
530 
531 static char path_buffer[1024];
532 
vMakePath(char * prefix,char * filename)533 char *vMakePath(char *prefix, char *filename)
534 {
535 #ifdef XLINUX
536 	if (prefix[0] == '~')
537 	{
538 		sprintf(path_buffer, "%s%s%s", getenv("HOME"), prefix + 1, filename);
539 	}
540 	else
541 #endif
542 	{
543 		sprintf(path_buffer, "%s%s", prefix, filename);
544 	}
545 	return path_buffer;
546 }
547