From c2fbdf929c99aa0e01c48fb583c44e87fb4a2219 Mon Sep 17 00:00:00 2001 From: Yogev Ezra Date: Sun, 30 Jan 2011 10:48:08 +0000 Subject: [PATCH] Added sources of the following games: bnc, checkers, fara, FindNumbers, gomoku, reversi, rforces, sq_game, sudoku, whowtbam, xonix. git-svn-id: svn://kolibrios.org@1805 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../games/FindNumbers/trunk/FindNumbers.c-- | 157 ++ programs/games/FindNumbers/trunk/kolibri.h-- | 168 ++ programs/games/bnc/trunk/bk100.png | Bin 0 -> 1201 bytes programs/games/bnc/trunk/bk5.PNG | Bin 0 -> 2642 bytes programs/games/bnc/trunk/bnc.asm | 22 + programs/games/bnc/trunk/bnc.txt | 53 + programs/games/bnc/trunk/bnc4.PNG | Bin 0 -> 1685 bytes programs/games/bnc/trunk/bnc6.PNG | Bin 0 -> 1743 bytes programs/games/bnc/trunk/code.inc | 205 ++ programs/games/bnc/trunk/data.inc | 35 + programs/games/bnc/trunk/draw.inc | 595 ++++ programs/games/bnc/trunk/lang.inc | 1 + programs/games/bnc/trunk/macros.inc | 270 ++ programs/games/bnc/trunk/macs.inc | 86 + programs/games/bnc/trunk/main.inc | 74 + programs/games/checkers/trunk/board.h | 1410 ++++++++++ programs/games/checkers/trunk/buttons.h | 355 +++ programs/games/checkers/trunk/checkers.cpp | 1420 ++++++++++ programs/games/checkers/trunk/compile.txt | 21 + programs/games/checkers/trunk/cpp2asm.bat | 3 + programs/games/checkers/trunk/dos-draw.h | 381 +++ programs/games/checkers/trunk/dosmouse.h | 172 ++ programs/games/checkers/trunk/egavga.bgi | Bin 0 -> 5554 bytes programs/games/checkers/trunk/gnu-draw.h | 295 ++ programs/games/checkers/trunk/gr-draw.h | 121 + programs/games/checkers/trunk/hash.h | 185 ++ programs/games/checkers/trunk/history.h | 402 +++ .../games/checkers/trunk/include/me_func.inc | 1135 ++++++++ .../games/checkers/trunk/include/me_heap.h | 90 + .../games/checkers/trunk/include/me_heap.inc | 284 ++ .../games/checkers/trunk/include/me_lib.h | 16 + .../games/checkers/trunk/include/me_lib.inc | 118 + .../games/checkers/trunk/include/me_start.inc | 90 + .../games/checkers/trunk/include/memheap.h | 626 +++++ .../games/checkers/trunk/include/menuet.h | 536 ++++ .../games/checkers/trunk/include/stdarg.h | 13 + .../checkers/trunk/include/write_macro.inc | 49 + programs/games/checkers/trunk/keysym.h | 2047 ++++++++++++++ programs/games/checkers/trunk/makefile | 4 + programs/games/checkers/trunk/me_make.inc | 10 + programs/games/checkers/trunk/mt-draw.h | 79 + programs/games/checkers/trunk/player.h | 888 ++++++ programs/games/checkers/trunk/position.h | 882 ++++++ programs/games/checkers/trunk/qsort.c | 331 +++ programs/games/checkers/trunk/sysproc.h | 27 + programs/games/checkers/trunk/t2fasm.exe | Bin 0 -> 5120 bytes programs/games/checkers/trunk/tmplayer.h | 729 +++++ programs/games/checkers/trunk/win-chk.rc | 106 + programs/games/checkers/trunk/win-chk.res | Bin 0 -> 1964 bytes programs/games/checkers/trunk/win-draw.h | 530 ++++ programs/games/checkers/trunk/winabout.rh | 3 + programs/games/fara/trunk/KosFile.cpp | 131 + programs/games/fara/trunk/KosFile.h | 26 + programs/games/fara/trunk/MCSMEMM.H | 28 + programs/games/fara/trunk/Release/pe2kos.exe | Bin 0 -> 13312 bytes programs/games/fara/trunk/bmp2src.exe | Bin 0 -> 36864 bytes programs/games/fara/trunk/bmp2src/bmp2src.dsp | 103 + programs/games/fara/trunk/bmp2src/bmp2src.dsw | 29 + .../games/fara/trunk/bmp2src/lzmapack.lib | Bin 0 -> 36152 bytes programs/games/fara/trunk/bmp2src/main.cpp | 166 ++ programs/games/fara/trunk/build_gfx.bat | 3 + programs/games/fara/trunk/crc32.cpp | 64 + programs/games/fara/trunk/crc32.h | 18 + programs/games/fara/trunk/face.bmp | Bin 0 -> 115256 bytes programs/games/fara/trunk/face.jpg | Bin 0 -> 8985 bytes programs/games/fara/trunk/fara.sln | 19 + programs/games/fara/trunk/fara.vcproj | 290 ++ programs/games/fara/trunk/gameWnd.cpp | 1585 +++++++++++ programs/games/fara/trunk/gameWnd.h | 29 + programs/games/fara/trunk/gfxdef.cpp | 285 ++ programs/games/fara/trunk/gfxdef.h | 101 + programs/games/fara/trunk/gmplace.bmp | Bin 0 -> 615550 bytes programs/games/fara/trunk/gmplace.jpg | Bin 0 -> 38689 bytes programs/games/fara/trunk/grobfar.txt | 31 + programs/games/fara/trunk/kosSyst.cpp | 870 ++++++ programs/games/fara/trunk/kosSyst.h | 197 ++ programs/games/fara/trunk/lang.h | 3 + programs/games/fara/trunk/lzma_unpack.asm | 393 +++ programs/games/fara/trunk/lzma_unpack.obj | Bin 0 -> 1208 bytes programs/games/fara/trunk/main.cpp | 80 + programs/games/fara/trunk/mainWnd.cpp | 211 ++ programs/games/fara/trunk/mainWnd.h | 13 + programs/games/fara/trunk/mainfish.bmp | Bin 0 -> 76314 bytes programs/games/fara/trunk/mcarray.h | 181 ++ programs/games/fara/trunk/mcsmemm.cpp | 298 ++ programs/games/fara/trunk/numbers.bmp | Bin 0 -> 7256 bytes programs/games/fara/trunk/top10wnd.cpp | 361 +++ programs/games/fara/trunk/top10wnd.h | 14 + programs/games/gomoku/trunk/gomoku.asm | 735 +++++ programs/games/reversi/trunk/Makefile | 3 + programs/games/reversi/trunk/reversi.c | 619 ++++ programs/games/rforces/trunk/KosFile.h | 26 + programs/games/rforces/trunk/cmp.bat | 4 + programs/games/rforces/trunk/forces_1.1.cpp | 402 +++ programs/games/rforces/trunk/kosFile.cpp | 131 + programs/games/rforces/trunk/kosSyst.cpp | 970 +++++++ programs/games/rforces/trunk/kosSyst.h | 220 ++ programs/games/rforces/trunk/mcsmemm.cpp | 329 +++ programs/games/rforces/trunk/mcsmemm.h | 28 + programs/games/rforces/trunk/mymath.h | 95 + programs/games/rforces/trunk/objects.h | 466 +++ programs/games/rforces/trunk/pe2kos.exe | Bin 0 -> 13312 bytes programs/games/rforces/trunk/properties.h | 46 + programs/games/rforces/trunk/rforces.cpp | 379 +++ programs/games/rforces/trunk/rforces.h | 19 + programs/games/sq_game/trunk/MACROS.INC | 269 ++ programs/games/sq_game/trunk/SQ_GAME.ASM | 246 ++ programs/games/sq_game/trunk/build_en.bat | 4 + programs/games/sq_game/trunk/build_ru.bat | 4 + programs/games/sudoku/trunk/SudokuSolve.pas | 423 +++ programs/games/sudoku/trunk/editbox_ex.mac | 194 ++ programs/games/sudoku/trunk/sudoku.asm | 1162 ++++++++ programs/games/sudoku/trunk/sudoku.fnt | Bin 0 -> 144 bytes programs/games/whowtbam/trunk/wwtbam.cpp | 1283 +++++++++ programs/games/xonix/trunk/MCSMEMM.H | 28 + programs/games/xonix/trunk/Release/pe2kos.exe | Bin 0 -> 13312 bytes programs/games/xonix/trunk/fatest.sln | 19 + programs/games/xonix/trunk/fatest.vcproj | 246 ++ programs/games/xonix/trunk/kosSyst.cpp | 829 ++++++ programs/games/xonix/trunk/kosSyst.h | 201 ++ programs/games/xonix/trunk/lang.h | 3 + programs/games/xonix/trunk/logo.bmp | Bin 0 -> 196662 bytes programs/games/xonix/trunk/main.cpp | 2500 +++++++++++++++++ programs/games/xonix/trunk/mcarray.h | 167 ++ programs/games/xonix/trunk/mcsmemm.cpp | 329 +++ programs/games/xonix/trunk/resource.h | 15 + 126 files changed, 32947 insertions(+) create mode 100644 programs/games/FindNumbers/trunk/FindNumbers.c-- create mode 100644 programs/games/FindNumbers/trunk/kolibri.h-- create mode 100644 programs/games/bnc/trunk/bk100.png create mode 100644 programs/games/bnc/trunk/bk5.PNG create mode 100644 programs/games/bnc/trunk/bnc.asm create mode 100644 programs/games/bnc/trunk/bnc.txt create mode 100644 programs/games/bnc/trunk/bnc4.PNG create mode 100644 programs/games/bnc/trunk/bnc6.PNG create mode 100644 programs/games/bnc/trunk/code.inc create mode 100644 programs/games/bnc/trunk/data.inc create mode 100644 programs/games/bnc/trunk/draw.inc create mode 100644 programs/games/bnc/trunk/lang.inc create mode 100644 programs/games/bnc/trunk/macros.inc create mode 100644 programs/games/bnc/trunk/macs.inc create mode 100644 programs/games/bnc/trunk/main.inc create mode 100644 programs/games/checkers/trunk/board.h create mode 100644 programs/games/checkers/trunk/buttons.h create mode 100644 programs/games/checkers/trunk/checkers.cpp create mode 100644 programs/games/checkers/trunk/compile.txt create mode 100644 programs/games/checkers/trunk/cpp2asm.bat create mode 100644 programs/games/checkers/trunk/dos-draw.h create mode 100644 programs/games/checkers/trunk/dosmouse.h create mode 100644 programs/games/checkers/trunk/egavga.bgi create mode 100644 programs/games/checkers/trunk/gnu-draw.h create mode 100644 programs/games/checkers/trunk/gr-draw.h create mode 100644 programs/games/checkers/trunk/hash.h create mode 100644 programs/games/checkers/trunk/history.h create mode 100644 programs/games/checkers/trunk/include/me_func.inc create mode 100644 programs/games/checkers/trunk/include/me_heap.h create mode 100644 programs/games/checkers/trunk/include/me_heap.inc create mode 100644 programs/games/checkers/trunk/include/me_lib.h create mode 100644 programs/games/checkers/trunk/include/me_lib.inc create mode 100644 programs/games/checkers/trunk/include/me_start.inc create mode 100644 programs/games/checkers/trunk/include/memheap.h create mode 100644 programs/games/checkers/trunk/include/menuet.h create mode 100644 programs/games/checkers/trunk/include/stdarg.h create mode 100644 programs/games/checkers/trunk/include/write_macro.inc create mode 100644 programs/games/checkers/trunk/keysym.h create mode 100644 programs/games/checkers/trunk/makefile create mode 100644 programs/games/checkers/trunk/me_make.inc create mode 100644 programs/games/checkers/trunk/mt-draw.h create mode 100644 programs/games/checkers/trunk/player.h create mode 100644 programs/games/checkers/trunk/position.h create mode 100644 programs/games/checkers/trunk/qsort.c create mode 100644 programs/games/checkers/trunk/sysproc.h create mode 100644 programs/games/checkers/trunk/t2fasm.exe create mode 100644 programs/games/checkers/trunk/tmplayer.h create mode 100644 programs/games/checkers/trunk/win-chk.rc create mode 100644 programs/games/checkers/trunk/win-chk.res create mode 100644 programs/games/checkers/trunk/win-draw.h create mode 100644 programs/games/checkers/trunk/winabout.rh create mode 100644 programs/games/fara/trunk/KosFile.cpp create mode 100644 programs/games/fara/trunk/KosFile.h create mode 100644 programs/games/fara/trunk/MCSMEMM.H create mode 100644 programs/games/fara/trunk/Release/pe2kos.exe create mode 100644 programs/games/fara/trunk/bmp2src.exe create mode 100644 programs/games/fara/trunk/bmp2src/bmp2src.dsp create mode 100644 programs/games/fara/trunk/bmp2src/bmp2src.dsw create mode 100644 programs/games/fara/trunk/bmp2src/lzmapack.lib create mode 100644 programs/games/fara/trunk/bmp2src/main.cpp create mode 100644 programs/games/fara/trunk/build_gfx.bat create mode 100644 programs/games/fara/trunk/crc32.cpp create mode 100644 programs/games/fara/trunk/crc32.h create mode 100644 programs/games/fara/trunk/face.bmp create mode 100644 programs/games/fara/trunk/face.jpg create mode 100644 programs/games/fara/trunk/fara.sln create mode 100644 programs/games/fara/trunk/fara.vcproj create mode 100644 programs/games/fara/trunk/gameWnd.cpp create mode 100644 programs/games/fara/trunk/gameWnd.h create mode 100644 programs/games/fara/trunk/gfxdef.cpp create mode 100644 programs/games/fara/trunk/gfxdef.h create mode 100644 programs/games/fara/trunk/gmplace.bmp create mode 100644 programs/games/fara/trunk/gmplace.jpg create mode 100644 programs/games/fara/trunk/grobfar.txt create mode 100644 programs/games/fara/trunk/kosSyst.cpp create mode 100644 programs/games/fara/trunk/kosSyst.h create mode 100644 programs/games/fara/trunk/lang.h create mode 100644 programs/games/fara/trunk/lzma_unpack.asm create mode 100644 programs/games/fara/trunk/lzma_unpack.obj create mode 100644 programs/games/fara/trunk/main.cpp create mode 100644 programs/games/fara/trunk/mainWnd.cpp create mode 100644 programs/games/fara/trunk/mainWnd.h create mode 100644 programs/games/fara/trunk/mainfish.bmp create mode 100644 programs/games/fara/trunk/mcarray.h create mode 100644 programs/games/fara/trunk/mcsmemm.cpp create mode 100644 programs/games/fara/trunk/numbers.bmp create mode 100644 programs/games/fara/trunk/top10wnd.cpp create mode 100644 programs/games/fara/trunk/top10wnd.h create mode 100644 programs/games/gomoku/trunk/gomoku.asm create mode 100644 programs/games/reversi/trunk/Makefile create mode 100644 programs/games/reversi/trunk/reversi.c create mode 100644 programs/games/rforces/trunk/KosFile.h create mode 100644 programs/games/rforces/trunk/cmp.bat create mode 100644 programs/games/rforces/trunk/forces_1.1.cpp create mode 100644 programs/games/rforces/trunk/kosFile.cpp create mode 100644 programs/games/rforces/trunk/kosSyst.cpp create mode 100644 programs/games/rforces/trunk/kosSyst.h create mode 100644 programs/games/rforces/trunk/mcsmemm.cpp create mode 100644 programs/games/rforces/trunk/mcsmemm.h create mode 100644 programs/games/rforces/trunk/mymath.h create mode 100644 programs/games/rforces/trunk/objects.h create mode 100644 programs/games/rforces/trunk/pe2kos.exe create mode 100644 programs/games/rforces/trunk/properties.h create mode 100644 programs/games/rforces/trunk/rforces.cpp create mode 100644 programs/games/rforces/trunk/rforces.h create mode 100644 programs/games/sq_game/trunk/MACROS.INC create mode 100644 programs/games/sq_game/trunk/SQ_GAME.ASM create mode 100644 programs/games/sq_game/trunk/build_en.bat create mode 100644 programs/games/sq_game/trunk/build_ru.bat create mode 100644 programs/games/sudoku/trunk/SudokuSolve.pas create mode 100644 programs/games/sudoku/trunk/editbox_ex.mac create mode 100644 programs/games/sudoku/trunk/sudoku.asm create mode 100644 programs/games/sudoku/trunk/sudoku.fnt create mode 100644 programs/games/whowtbam/trunk/wwtbam.cpp create mode 100644 programs/games/xonix/trunk/MCSMEMM.H create mode 100644 programs/games/xonix/trunk/Release/pe2kos.exe create mode 100644 programs/games/xonix/trunk/fatest.sln create mode 100644 programs/games/xonix/trunk/fatest.vcproj create mode 100644 programs/games/xonix/trunk/kosSyst.cpp create mode 100644 programs/games/xonix/trunk/kosSyst.h create mode 100644 programs/games/xonix/trunk/lang.h create mode 100644 programs/games/xonix/trunk/logo.bmp create mode 100644 programs/games/xonix/trunk/main.cpp create mode 100644 programs/games/xonix/trunk/mcarray.h create mode 100644 programs/games/xonix/trunk/mcsmemm.cpp create mode 100644 programs/games/xonix/trunk/resource.h diff --git a/programs/games/FindNumbers/trunk/FindNumbers.c-- b/programs/games/FindNumbers/trunk/FindNumbers.c-- new file mode 100644 index 0000000000..a44cf1cb24 --- /dev/null +++ b/programs/games/FindNumbers/trunk/FindNumbers.c-- @@ -0,0 +1,157 @@ +//(C) Artemonische, 2010 + +#pragma option meos +//#include "..\lib\kolibri.h--" //Ї®¤Є«оз Ґ¬ ЎЁЎ«Ё®вҐЄг б KolibriOS API +#include "kolibri.h--" + +int find=10; +struct + { + int x; + int y; + int button_id; + int mark; + int text; + }box[81]; + +void main() +{ + int button,tempi,tempj; + randomize(); + initialization(); + draw_window(); + draw_buttons(); + loop() + { + switch(WaitEvent()) + { + CASE evButton: + button=GetButtonID(); + IF (button==1) + { + ExitProcess(); + } + IF (button==582) + { + find=10; + initialization(); + draw_window(); + draw_buttons(); + } + if (button>500) && (button<582) && (box[button-500].text == find) + { + box[button-500].mark=2; + find++; + if (find==91) + { + draw_window(); + } + else + { + DeleteButton(button); + tempi=box[button-500].y*30-30; + tempj=30*box[button-500].x-16; + DrawBar(tempi,tempj,30,30,0xDCFFDC); + DrawBar(70,289,16,8,0xDCFFDC); + DrawBar(252,289,16,8,0xDCFFDC); + WriteNumber(70,289,0x80,0,find); + WriteNumber(252,289,0x80,0,90-find+1); + } + } + BREAK; + CASE evKey: //Ґб«Ё Їа®Ё§®и«® ­ ¦ вЁҐ Є« ўЁиЁ ­  Є« ўЁ вгॠ+ IF (GetKey()==051) + { + find=10; + initialization(); + draw_window(); + draw_buttons(); + } + BREAK; + CASE evReDraw: + draw_window(); + draw_buttons(); + BREAK; + } + } + ExitProcess(); +} + +void draw_window() +{ + WindowRedrawStatus(1); //­ з «® ЇҐаҐаЁб®ўЄЁ ®Є­  + DefineAndDrawWindow(300,176,280,340,0x34,0xDCFFDC,0,0,"FindNumbers v1.1"); //аЁб㥬 ®Є­® + DrawBar(0,13,271,1,0x0CFF0C); //«Ё­Ёп ᢥаег + DrawBar(0,285,271,1,0x0CFF0C); + DrawBar(0,299,271,1,0x0CFF0C); //«Ё­Ёп б­Ё§г + if (find<=90) + { + WriteText(4,4,0x80,0x000000,"‘®ЎҐаЁвҐ ўбҐ зЁб«  ®в 10 ¤® 90 Ї® Ї®ап¤Єг..."); + WriteText(4,289,0x80,0x000000,"€йҐ¬ зЁб«®: "); + WriteText(162,289,0x80,0x000000,"Ћбв «®бм ­ ©вЁ: "); + WriteNumber(70,289,0x80,0,find); + WriteNumber(252,289,0x80,0,90-find+1); + DrawFlatButton(155,300,115,14,582,0xAFFFAF,"‡ ­®ў® (F2)"); + WriteText(4,304,0x80,0x000000,"Made by Artemonische,2010"); + } + IF (find==91) + { + WriteText(70,100,0x80,0x000000,"‚л ­ и«Ё ўбҐ зЁб« ! :)"); + DrawFlatButton(100,110,70,20,582,0xE4DFE1,"‡ ­®ў® (F2)"); + } + WindowRedrawStatus(2); //Є®­Ґж ЇҐаҐаЁб®ўЄЁ ®Є­  +} + +void draw_buttons() +{ +int i,tempi,tempj; + for (i=1;i<=81;i++) + { + IF (box[i].mark==1) + { + tempi=box[i].y*30-30; + tempj=30*box[i].x-16; + DefineButton(tempi,tempj,29,29,box[i].button_id,0xAFFFAF); + WriteNumber(tempi+11,tempj+11,0x80,0,box[i].text); + } + } +} + +void initialization() +{ +int i,j,t; +t=0; + FOR (i=1;i<=9;i++) + { + FOR (j=1;j<=9;j++) + { + t++; + box[t].x=j; + box[t].y=i; + box[t].mark=1; + box[t].button_id=500+t; + box[t].text=Generate(t); + } + } +} + +int Generate(int xx) +{ + int temp,k,p; + p=2; + WHILE (p==2) + { + temp=random(81)+10; + p=1; + FOR (k=1; k> 8; +} + +inline fastcall word GetButtonID(){ + EAX = 17; + $int 0x40 + EAX = EAX >> 8; +} + +inline fastcall dword strlen(dword EDI){ + EAX=0; + ECX=-1; + $REPNE $SCASB + EAX-=2+ECX; +} + +byte WindowRePaint=0; +inline fastcall void WindowRedrawStatus(dword EBX) +{ + EAX = 12; // function 12:tell os about windowdraw + $int 0x40 + IF (EBX==1) WindowRePaint=1; ELSE WindowRePaint=0; +} + +void DefineAndDrawWindow(dword x,y,sizeX,sizeY,byte mainAreaType,dword mainAreaColour,byte headerType,dword headerColour,EDI) +{ + EBX = x << 16 + sizeX; + ECX = y << 16 + sizeY; + EDX = mainAreaType << 24 | mainAreaColour; + ESI = headerType << 24 | headerColour; + $xor eax,eax + $int 0x40 +} + + +void WriteText(dword x,y,byte fontType, dword color, EDX, ESI) +{ + EAX = 4; + EBX = x<<16+y; + ECX = fontType<<24+color; + $int 0x40; +} + +void WriteNumber(dword x,y,byte fontType, ESI, ECX) +{ +EAX = 47; +EBX = 2<<16; +EDX = x<<16+y; +ESI = fontType<<24+ESI; +$int 0x40; +} + + + +void DrawBar(dword x,y,w,h,EDX) +{ + EAX = 13; + EBX = x<<16+w; + ECX = y<<16+h; + $int 0x40 +} + +void DefineButton(dword x,y,w,h,EDX,ESI) +{ + EAX = 8; + EBX = x<<16+w; + ECX = y<<16+h; + $int 0x40 +} + +inline fastcall void DeleteButton(dword EDX) +{ + EAX = 8; + EDX += BT_DEL; + $int 0x40; +} + +void DrawFlatButton(dword x,y,width,height,id,color,text) +{ + DrawRegion_3D(x,y,width,height,0x94AECE,0x94AECE); + DrawRegion_3D(x+1,y+1,width-2,height-2,0xFFFFFF,0xC7C7C7); + DrawBar(x+2,y+2,width-3,height-3,color); //§ «ЁўЄ  + IF (id<>0) DefineButton(x,y,width,height,id+BT_HIDE,0xEFEBEF); //Є­®ЇЄ  + WriteText(-strlen(text)*6+width/2+x+1,height/2-3+y,0x80,0,text,0); +} + + +dword generator; // random number generator - для генерации случайных чисел + +:int random(int max) +// get pseudo-random number - получить псевдослучайное число +{ + $rdtsc // eax & edx + $xor eax,edx + $not eax + + EBX = generator; + $ror ebx,3 + $xor ebx,0xdeadbeef + EBX += EAX; + generator = EBX; + + EAX += EBX; + EAX = EAX % max; + return EAX; +} + +:randomize() +// initialize random number generator - инициализировать генератор случайных чисел +{ + asm + { + mov eax,3 + int 0x40 + ror eax,16 + } + generator = EAX; +} + +inline fastcall ExitProcess(){ + EAX = -1; // close this program + $int 0x40 +} + +void DrawRegion_3D(dword x,y,width,height,color1,color2) +{ + DrawBar(x,y,width+1,1,color1); + DrawBar(x,y+1,1,height-1,color1); + DrawBar(x+width,y+1,1,height,color2); + DrawBar(x,y+height,width,1,color2); +} \ No newline at end of file diff --git a/programs/games/bnc/trunk/bk100.png b/programs/games/bnc/trunk/bk100.png new file mode 100644 index 0000000000000000000000000000000000000000..dc317c26e014ad60c1f18e6467c09422b136029b GIT binary patch literal 1201 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 literal 0 HcmV?d00001 diff --git a/programs/games/bnc/trunk/bnc.asm b/programs/games/bnc/trunk/bnc.asm new file mode 100644 index 0000000000..1aa4909a0e --- /dev/null +++ b/programs/games/bnc/trunk/bnc.asm @@ -0,0 +1,22 @@ +;************************************************ +;* Bulls-and-Cows */ Kolibri OS /* +;************************* 25/10/2007 ********* +include 'main.inc' ; main.inc +include 'data.inc' ; data.inc +include 'code.inc' ; code.inc +include 'macs.inc' ; macs.inc +include 'macros.inc' ; standard macro definitions - mcall & all-all-all + + BeginProgram + call clears + call rndseed + call rnew + + main_loop + + CODE_SECTION + + DATA_SECTION + + EndProgram + diff --git a/programs/games/bnc/trunk/bnc.txt b/programs/games/bnc/trunk/bnc.txt new file mode 100644 index 0000000000..7cfb2c3be6 --- /dev/null +++ b/programs/games/bnc/trunk/bnc.txt @@ -0,0 +1,53 @@ +Bulls-and-Cows v0.01 --- bnc.bin --- http://kolibrios.org + +Logical game. You must guess secret 4-digit number (Non-repeated). +Input your move by keys from '0' to '9', edit it by 'BackSpace', +and place into game by 'Enter'. + +'Bull' stands for the digit is in right place. +'Cow' means it is present, but is placed wrong. +Program gives you total info from which you may deduce next move. +Your aim is - 4 bulls. 9 moves is more then enought. + + (* Быки и Коровы *) + + Эта игра распространена мало, хотя я знаю ее с детства. +Считается логической, так как нужно немного подумать ;)) +Обычно игра ведется двумя людьми на листках бумаги... + + Каждый загадывает четырех-значное число, используя цифры +от 0 до 9, цифра в числе должна встречаться не более одного раза. +Числа сохраняются в тайне друг от друга, затем каждый +пытается угадать число оппонента за кратчайшее число ходов. + + Ход: комбинируется число и называется вслух, противник записывает +его под своим числом и сравнивает - если цифры из хода стоят на тех же +местах, что и в загаданном - это считается быком, каждая цифра дает 1 быка. +Если цифра в числе есть, но стоит на другом месте - это корова. +Все цифры проверяются, общее количество быков и коров записывается и +сообщается тому, кто сделал ход. Тот тоже их записывает и на основе +этой информации потом делает дальнейшие ходы. + + Ходы делаются по очереди. Кто первым получит в ответ 4 быка - выиграл. +Это означает, что число полностью угадано. + + Эта программа работает следующим образом: она загадывает четырехзначное +число и ждет ввода пользователя. Используя цифровые кнопки на клавиатуре +1234567890 игрок вводит четыре цифры и заканчивает ввод нажатием ENTER. +В случае неправильного ввода можно удалить знак кнопкой BackSpace. +Программа обрабатывает введенное число, сравнивает со своим и выдает +значения быков и коров. Игрок ни с кем не соревнуется (программа не +угадывает число игрока), а лишь развивает свои мозги... +В этом вся суть игры - пошевелить мозгами. + + + На картинках bnc4.png, bnc6.png - примеры сыгранных партий... + + bk100.png - статистика выигрышей за 100 партий. +Видно, что в среднем за 5-6 ходов выиграть можно. А именно - 95% +вероятность победы при правильной (логичной) игре. За 7 ходов - 100% +График составлен с помощью алгоритма, реализующего отсутствующую здесь +часть, где программа отгадывает число противника. +В общем случае можно считать, что если Вы не выиграли за 7 ходов, то +100% проиграли. + diff --git a/programs/games/bnc/trunk/bnc4.PNG b/programs/games/bnc/trunk/bnc4.PNG new file mode 100644 index 0000000000000000000000000000000000000000..0f81d0e2a674f0e4c5bc259dd581ba1720b6837a GIT binary patch literal 1685 zcmZvbc{~%28^_foH=#tyksKxDN;63ja)*$k+)8fS6f=lSpXygskznT?f+0Iwu32M33MnW@q3gNZ#Lo*QtW zbAAP{I5+?tHWv2A2kW6jhYlY;3;+N)IXRCUIl{%ob@b>_ZfeT7er=_H% z&YU?TEiEl0BO@y-D<>y+_Uu`CdHHka&M7D;C@Lx{DJdx{E1y4q{=$U|Dk>@$FJ4qt zRaH|{Q&(5Nbm@|YhK8o5rk0kLwzjs8j?U%Fmvwb@uUxqT1OoN+^gtkxzP|p|t5*#S z46a?fW@u=5{rdGAH*Odi85tWJ-@JL##KgqZ)YQz(?AEPY=H})W78aJ4mR43)*4EZG zHa51lwzqHJwzIRdx3_n2aJX~lj-#WalarIPv-91%cU@duTwPt=+}zyV-S6GIcmMu< z4-XGdPfsr|FK=&eA0HoIUtd2zKYxG!2M-=ReE2XRAmGuXM}dKXK|w*m!NDORA)%q6 zVPRq6;o%Vx5nwPF0)arG(8$Qh$B!RBdGaJGDk?fU8U};K#Kgei@YvYcxVX5dPoKue z$0sBtAP|Ve#Kfeeq~zq}XV0Fcq@+B5{`|#@7pbYKX=!OMU%pIFPtVB6$jr>l%F4>l z&d$ln$<58p%gcN9>Q#PzenCM&VPPQ>i7YBADlRTADJdx}Eq(p^by-y1M%M`i6#v#>U2`rl$Ar-+%b<;p4}T&CSg% zEiEV%3XMi%FqqcXRxB3V*4EbE-j2iJ@OXSjN5`j6pE^4`KY#w*)z#JA-QCmE)7#tI z*Vp&u%a^ZTzxMa{fBW`rU|?WyaByg7Xn1(|`}glZe*73285tcN{rU4Jfj}Sji%UyO%gf6v zD=Vw3t7~g(>+9jmv$lj{7jyB5*;s>{1Tuvwy&`<$#@E@a94 zceA}jh1pZi9mnPS(ML6F5om1|BrL{(!Zy zBB7V7-LSM@vA!xPG}d23hYnVY7i%8ESJc?=k=1e>*|UQSEG`v9(!6K$1 zk|wWrbPF;8WIj-2&oj>!=dRmVF6Wa%qO^zXLNC)8ne$7? zpvDz;pO;Q2%xkfd6h+M+a8o9|K33q2KdHhHp(3NTTy< zho2|Zc^9)8EMaJnR5l(bRw8ag8#g^Re3hEaq?c1Ps<8Yks`0J;>h90=$=hSwjvBa3 zl*6<&nz)*UCb|tpP!_lJhay>nV$-845U&+_*@E5z9lFU|+Nz&g*yh)VuoRaf7D=0M z4S+?nX#7wH#>$O9dd1VN>D3IiS0_0e~a+gi(22o={n<4 zI3k7RRLeF{%ITD|N+VDolOg&;K>L78jxEFcNJBO7#1?j3X*=+9^MoOVtBl2LCA4nXE}F_h$3ifSDaoom1c`I)g0(4a$CkS!NcixzLL@fb>8AOI!MH R@c*_OLRvnGGAQd#^gkQ#YQO*h literal 0 HcmV?d00001 diff --git a/programs/games/bnc/trunk/bnc6.PNG b/programs/games/bnc/trunk/bnc6.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a63ca6f1ca8178286a5bdff9477899e14352b8f3 GIT binary patch literal 1743 zcmaJ=c{mdQ8+S#{LM4jHEk$L{+#^PghJ;X#Ia-k;R~xA$*WAjrFwL1`YjWgB$e9ew zotbNM-!}B^d%oxUp6`$E`Tls{-~0RLeSh!u*2=<|mrI0;iHV69Y+?vuUt* za$`6HSedMD+ZZt@Gcz*_3kxeND;pczi4!N-+1WWbI8L5C$;rvd#l^+V&CSEZ!^_Ld z$H#Z-)Tz^_PxJHh3kV1Z3JRV%bLQ;Xv**s86A}_SfBw9%u&{`T$b}0RE?&GSDk>@_ zCI$ci#KpxgUAiP8At5O#DJ3N(EiEl0BO@y-D<>x>FE4-j@?`}Dg)3LCT)lc#QBhGz zN$J|PYuB$|zj5P+va&J|2vku~QB_q{Q&Uq{SJ%+c(A3ntdGn^0mX@}*wvLXDuCA`0 zo}RwGzJY-O2m~@TG&C|Yx^?T8v9Ym_2nK^ae*E~!lPA8uzJ7jwPoF;Z_xBG7 z2nY-e3*(m{H*em=#KgRP`!+T!-o&~`S}F}1%-u$Xf(R0sOaOz zj~EQ5xVX5aq@=X8w5+VGyu7@kqT!GBQFW5`X{xJvur% zHa0dsK0YxqF*!LoH8nLoJ^km;pP88%5{WcBJ4+^$=jP_-=jRs|78Vy5mzI_&6bh9} zU0z;ZSy@?KU0qvSTVG$_*x1p;mL?VZzgggR(d$F2&OC^ z;%eoUIzUw{AfmG6z#BA6+KRL~TB@BIjqcH1Y2Cv(Bz{+1#Cue5j4RkeuGg&AYvaGD z!tOird?rHBj({8+i(LrIm8SKv3J&`Q7#w8Mu6|Z;R*{rPvE6jm=-eEHE%bSdk}%>9 zo6!Xv88Oomwub!P2}--0S-I{0mZ>$vb~+>bs?c2P2E?A7le`cCG7gaX+L&^tlA*%9 zeo7AHX+YC}T{`l4XT?dX{gaLCO@ap^6QBvouB zb;0DwGZdMrK`v|Y)!r$8Qy1E?Mlh2HZ<&dcmSX#!wV-J zmmXP@q2@(orhS3|dFo+)nnjU*{T`?cR3FU;jRbZdUp`vQJ8HQXh+S)F5+3wQ+;vzA zl@rTn<&Y{0apI>Bxe%A}B0C%=*-P$)H~?Ihj^AGjCOrC2UB+w#Bf9Z&K^d-D5kwRh zN@LavG0s4+WPf-ss&rA@n{MMU3QyA2rdVZJCT4%qi54U5g*+T3t8>ZUW0AI@=SVx=o}=s)AOsZhA(unaI9nq;A3|2=ck8>++~t zooNJ3<=>m!VH@71ovKaFJi4mQ^O|maeUIF z&7wW6>@-fW(LoY*%l@E&I$wa;4r5P=KDJ54YgI3II$;(LtY^(wAsEy)hG_MF?sPI{ Sdz`6_#?51``c!65YUdv;fPD7= literal 0 HcmV?d00001 diff --git a/programs/games/bnc/trunk/code.inc b/programs/games/bnc/trunk/code.inc new file mode 100644 index 0000000000..87664802a3 --- /dev/null +++ b/programs/games/bnc/trunk/code.inc @@ -0,0 +1,205 @@ +macro CODE_SECTION + +{ +;+-----------------------------------+ Uses:eax,ebx,edx +;|-------Random Number Generator-----|---------------------------| +;+-----------------------------------+ + rndseed: ; + mov eax,26 ; func 26 subfunc 9 + mov ebx,9 ; + int 0x40 ; + mov dword[seed],eax ; system time from boot + random9: ; RND=[0..9] + mov eax,3 ; + int 0x40 ; get current time + shr eax,16 ; seconds in al + add eax,dword[seed] ; + imul eax,0x15a4e35 ; random formula rv=rv*0x15a4e35+1 + inc eax ; return (rv&0x7FFFFFFF)%N + mov dword[seed],eax ; + and eax,0x07FFFFFFF ; + mov ebx,10 ; N=10 + xor edx,edx ; + div bx ; eax/ebx= int[result]+rest + add dl,'0' ; DL='0'..'9' - rest + ret ; +;================================================= + rnew: ; New Random Secret Number + xor esi,esi ;---------------------------- + LoopBegin lb1,0 ; + rn: call random9 ; DL=RND('0'..'9') + xor edi,edi ; + lb2: cmp byte[nA+edi],dl ; + je rn ; + inc edi ; + cmp edi,4 ; 4 digit + jne lb2 ; + mov byte[nA+esi],dl ;nA - secret number without double digits + inc esi ;nA - 4 bytes of non-repeated digits '0'..'9' + LoopEnd lb1,4 ; + ret ; +;------------------------------------- + numStr: inc dword[turn] ; turn++ + mov ebx,dword[turn] ; + push ebx ; + pop ecx ; ebx=ecx=turn + add cl,'0' ; + add ch,':' ; + dec ebx ; -1 + shl ebx,4 ; *16 + mov word[tStr+ebx],cx; begin string by turn number +':' + ret +;------------------------------------- + paint_list: + LoopBegin lbList,0 + mov ebx,ecx + shl ebx,4 ; *16 + mov edx,tStr + add edx,ebx + add ebx,25*65536 ;x + add ebx,45 ;y + mov eax,4 ;func 4 + mov ecx,cTxt ;color + mov esi,16 ;line length + int 0x40 + LoopEnd lbList,9 ; + ret +;-INPUT------------------------------------ KEYBOARD INPUT ----------- + input: ;ah - key code + mov byte[char],ah ;char<-ah + cmp ah,13 ;13- enter + jne @f + jmp _enter + @@: + cmp ah,8 ;8 - del backSpace <=| + jne @f + jmp _back + @@: + + cmp ah,'0' ; '0'..'9' + jae @f + ret + @@: cmp ah,'9' + jbe @f + ret ; if not - return subroutine + @@: +;------------------------pressed:0123456789----------- + cmp byte[posn],4 + je @f ;full line - do nothing + call ptrStr ;esi - pointer at tStr + xor eax,eax + add al,byte[posn] + add esi,eax ;+posn + mov al,byte[char] + mov byte[esi+3],al ;esi+3 = place 4 digits + inc byte[posn] ;next digit + @@: ret +;------------------------ + _enter: + cmp byte[posn],4 ; Enter Turn + je @f + ret + @@: + call check ; check input for difference + cmp eax,0 + je @f + ret + @@: + call bcalculate ; calc b+c + call numStr ; 'N:' next string number + mov byte[posn],0 ; new line + ret +;------------------------ + _back: cmp byte[posn],0 ; empty input - do nothing + je @f + dec byte[posn] + call ptrStr ;esi = pointer at tStr + xor eax,eax + add al,byte[posn] ; byte of esi +posn + add esi,eax ;+posn + mov byte[esi+3],' ' + @@: ret +;===========================================--end - input - + ptrStr: ; esi=tStr+turn*16 + mov esi,dword[turn] + shl esi,4 + add esi,tStr + ret +;------------------------ + clears: mov ecx,160 + clr1: mov byte[tStr+ecx],0;' ' + loop clr1 + mov byte[tStr],0;' ' + mov byte[posn],0 + mov dword[turn],0 + ret +;-------------------------CHECK---Input--[1234]------- + check: ; check for similar digits (equal) + call ptrStr ; esi ...pointer + ;mov esi,dword[turn] + ;shl esi,4 + ;add esi,tStr + xor eax,eax + xor edi,edi ; edi - counter 0..3 + xor ecx,ecx + lb4ch: mov dl,byte[esi+ecx+3] + cmp byte[esi+edi+3],dl + jne @f + inc eax ; =equivalent +1 + @@: + inc edi ; + cmp edi,4 ; cycle ,4 digits + jne lb4ch ; + xor edi,edi ; edi - counter 0..3 + + inc ecx + cmp ecx,4 + jne lb4ch + + sub eax,4 ; must be 4, if more - doubles present + ret + + bcalculate: ;------------------; calc b:+c: + call ptrStr ; esi ... + add esi,3 + ;inc esi + ;inc esi ;+3 + ;inc esi ; ...- pointer to Line + LoopBegin lbBu1,0 ;bull count cycle ecx=0..3 + mov bl,byte[nA+ecx] + mov dl,byte[esi+ecx] + cmp bl,dl + jne @f + inc byte[nBul] + @@: + LoopEnd lbBu1,4 + + mov ax,'B:' ; output Bulls + mov word[esi+6],ax + mov al,byte[nBul] + add al,'0' + mov byte[esi+8],al + + LoopBegin lbCo2,0 ;Cows count cycle ecx=0..3 + mov dl,byte[esi+ecx] + xor edi,edi ; cycle edi=0..3 + lb3: mov bl,byte[nA+edi] + cmp bl,dl + jne @f + inc byte[nCow] ;Cows+Bulls + @@: inc edi ; + cmp edi,4 ; + jne lb3 ; + LoopEnd lbCo2,4 ;endcycle ecx + + mov ax,'C:' ; output Cows + mov word[esi+10],ax + mov al,byte[nCow] + sub al,byte[nBul] + add al,'0' + mov byte[esi+12],al + mov dword[nBul],0 ;nCow=posn=char=0 + ret +;-------------------------------------- +} + diff --git a/programs/games/bnc/trunk/data.inc b/programs/games/bnc/trunk/data.inc new file mode 100644 index 0000000000..6190181f32 --- /dev/null +++ b/programs/games/bnc/trunk/data.inc @@ -0,0 +1,35 @@ +;#************************** +;#* BNC-DATA * +;#************************** 25/10/2007 +macro DATA_SECTION +{ +;----------------------------------------------------------------------------- + header: db 'Bulls-and-Cows v0.01 ' + new: db 'New' +;--------------------------------- + nBul: db 0 + nCow: db 0 +;--------------------------------- + posn: db 0 ;position 0-4 : 4 - finish -enter + char: db 0 + ; + nA: dd 0 + turn: dd 0 + seed: dd 0 + ; + tStr: ; table of Strings = 10*(16) bytes +;------------------------------------------- + rb 160 + ;-- '0123456789ABCDEF'--- + ;-- 1: 1234 B:4 C:0 --- + ;db ' ';1 + ;db ' ';2 + ;db ' ';3 + ;db ' ';4 + ;db ' ';5 + ;db ' ';6 + ;db ' ';7 + ;db ' ';8 + ;db ' ';9 + +} diff --git a/programs/games/bnc/trunk/draw.inc b/programs/games/bnc/trunk/draw.inc new file mode 100644 index 0000000000..744c90a995 --- /dev/null +++ b/programs/games/bnc/trunk/draw.inc @@ -0,0 +1,595 @@ + +DrawLine: + + mov eax,38 + mov ebx,[Line.x1] + mov ecx,[Line.y1] + mov edx,[Line.color] + shl ebx,16 + shl ecx,16 + add ebx,[Line.x2] + add ecx,[Line.y2] + mcall + + ret + +DrawPixel: + + xor eax,eax + inc al + mov ebx,[Pixel.x] + mov ecx,[Pixel.y] + mov edx,[Pixel.color] + mcall + + ret + +RectangleContour: + + mov eax,38 + mov ebx,[Rectangle.x] + mov ecx,[Rectangle.y] + mov edx,[Rectangle.color] + mov esi,ebx + mov edi,ecx + shl ebx,16 + shl ecx,16 + add ebx,esi + add ecx,edi + add ebx,[Rectangle.width] + mcall + + mov eax,38 + mov ebx,[Rectangle.x] + mov ecx,[Rectangle.y] + mov edx,[Rectangle.color] + add ecx,[Rectangle.height] + mov esi,ebx + mov edi,ecx + shl ebx,16 + shl ecx,16 + add ebx,esi + add ecx,edi + add ebx,[Rectangle.width] + mcall + + mov eax,38 + mov ebx,[Rectangle.x] + mov ecx,[Rectangle.y] + mov edx,[Rectangle.color] + mov esi,ebx + mov edi,ecx + shl ebx,16 + shl ecx,16 + add ebx,esi + add ecx,edi + add ecx,[Rectangle.height] + mcall + + mov eax,38 + mov ebx,[Rectangle.x] + mov ecx,[Rectangle.y] + mov edx,[Rectangle.color] + add ebx,[Rectangle.width] + mov esi,ebx + mov edi,ecx + shl ebx,16 + shl ecx,16 + add ebx,esi + add ecx,edi + add ecx,[Rectangle.height] + mcall + + ret + +;eax -first color +;ebx- second color +;OUT +;eax - averege color +calculate_average_color: + + and eax,0xffffff + and ebx,0xffffff + + mov [b_min],al + mov [b_max],bl + shr eax,8 + shr ebx,8 + mov [g_min],al + mov [g_max],bl + shr eax,8 + shr ebx,8 + mov [r_min],al + mov [r_max],bl + + xor eax,eax + xor ebx,ebx + mov al,[r_max] + mov bl,[r_min] + add eax,ebx + shr eax,1 + mov [r],al + + xor eax,eax + xor ebx,ebx + mov al,[g_max] + mov bl,[g_min] + add eax,ebx + shr eax,1 + mov [g],al + + xor eax,eax + xor ebx,ebx + mov al,[b_max] + mov bl,[b_min] + add eax,ebx + shr eax,1 + mov [b],al + + xor eax,eax + mov al,[r] + shl eax,8 + mov al,[g] + shl eax,8 + mov al,[b] + + ret + +;eax -color +;ebx- sub value +;OUT +;eax - sabved color +calculate_sabved_color: + + and eax,0xffffff + + mov [b],al + shr eax,8 + mov [g],al + shr eax,8 + mov [r],al + + sub [r],bl + sub [g],bl + sub [b],bl + + xor eax,eax + mov al,[r] + shl eax,8 + mov al,[g] + shl eax,8 + mov al,[b] + + ret + +DrawString: + + mov ebx,[Button.text] + call GetLengthString + mov esi,eax + + mov eax,4 + mov ebx,[Font.x] + shl ebx,16 + add ebx,[Font.y] + mov ecx,[Button.textcolor] + mov edx,[Button.text] + mcall + + ret + +;eax -first color +;ebx- second color +;ecx- x coordinat of rectangle +;edx- y coordinat of rectangle +;esi- rectangle size x +;edi- rectangle size y + +rectangle_gradient_right: + + mov [line_coordinat_x],ecx + mov [line_coordinat_y],edx + mov [line_size_x],esi + mov [line_size_y],edi + + mov ecx,esi + mov edx,dword pointer + call gradient + + mov ecx,[line_coordinat_y] + shl ecx,16 + add ecx,[line_coordinat_y] + add ecx,[line_size_y] + + mov eax,[line_size_x] + add [line_coordinat_x],eax + + mov esi,dword pointer + mov edi,[line_size_x] + + next_vertical_line_draw_right: + + mov eax,38 + mov ebx,[line_coordinat_x] + shl ebx,16 + add ebx,[line_coordinat_x] + mov edx,[esi] + and edx,0xffffff + mcall + + add esi,3 + sub [line_coordinat_x],1 + + dec edi + jnz next_vertical_line_draw_right + + ret + +;eax -first color +;ebx- second color +;ecx- x coordinat of rectangle +;edx- y coordinat of rectangle +;esi- rectangle size x +;edi- rectangle size y + +rectangle_gradient_left: + + mov [line_coordinat_x],ecx + mov [line_coordinat_y],edx + mov [line_size_x],esi + mov [line_size_y],edi + + mov ecx,esi + mov edx,dword pointer + call gradient + + mov ecx,[line_coordinat_y] + shl ecx,16 + add ecx,[line_coordinat_y] + add ecx,[line_size_y] + + mov esi,dword pointer + mov edi,[line_size_x] + + next_vertical_line_draw_left: + + mov eax,38 + mov ebx,[line_coordinat_x] + shl ebx,16 + add ebx,[line_coordinat_x] + mov edx,[esi] + and edx,0xffffff + mcall + + add esi,3 + add [line_coordinat_x],1 + + dec edi + jnz next_vertical_line_draw_left + + ret + +;eax -first color +;ebx- second color +;ecx- x coordinat of rectangle +;edx- y coordinat of rectangle +;esi- rectangle size x +;edi- rectangle size y + +rectangle_gradient_up: + + mov [line_coordinat_x],ecx + mov [line_coordinat_y],edx + mov [line_size_x],esi + mov [line_size_y],edi + + mov ecx,edi + mov edx,dword pointer + call gradient + + mov ebx,[line_coordinat_x] + shl ebx,16 + add ebx,[line_coordinat_x] + add ebx,[line_size_x] + + mov eax,[line_size_y] + add [line_coordinat_y],eax + + mov esi,dword pointer + mov edi,[line_size_y] + + next_horizontal_line_draw_up: + + mov eax,38 + mov ecx,[line_coordinat_y] + shl ecx,16 + add ecx,[line_coordinat_y] + mov edx,[esi] + and edx,0xffffff + mcall + + add esi,3 + sub [line_coordinat_y],1 + + dec edi + jnz next_horizontal_line_draw_up + + ret + +;eax -first color +;ebx- second color +;ecx- x coordinat of rectangle +;edx- y coordinat of rectangle +;esi- rectangle size x +;edi- rectangle size y + +rectangle_gradient_down: + + mov [line_coordinat_x],ecx + mov [line_coordinat_y],edx + mov [line_size_x],esi + mov [line_size_y],edi + + mov ecx,edi + mov edx,dword pointer + call gradient + + mov ebx,[line_coordinat_x] + shl ebx,16 + add ebx,[line_coordinat_x] + add ebx,[line_size_x] + + mov esi,dword pointer + mov edi,[line_size_y] + + next_horizontal_line_draw_down: + + mov eax,38 + mov ecx,[line_coordinat_y] + shl ecx,16 + add ecx,[line_coordinat_y] + mov edx,[esi] + and edx,0xffffff + mcall + + add esi,3 + add [line_coordinat_y],1 + + dec edi + jnz next_horizontal_line_draw_down + + ret + +;eax -first color +;ebx- second color +;ecx- length of line +;edx- pointer to memory for colors of gradient + +gradient: + + mov [length],ecx + + and eax,0xffffff + and eax,0xffffff + + mov [b_min],al + mov [b_max],bl + shr eax,8 + shr ebx,8 + mov [g_min],al + mov [g_max],bl + shr eax,8 + shr ebx,8 + mov [r_min],al + mov [r_max],bl + + mov eax,[length] + dec eax + mov [v],eax + fild [v] + + xor eax,eax + mov al,[r_max] + sub al,[r_min] + mov [v],eax + fild [v] + fdiv st0,st1 + fstp [step_r] + + xor eax,eax + mov al,[g_max] + sub al,[g_min] + mov [v],eax + fild [v] + fdiv st0,st1 + fstp [step_g] + + xor eax,eax + mov al,[b_max] + sub al,[b_min] + mov [v],eax + fild [v] + fdiv st0,st1 + fstp [step_b] + + fstp [v] + + xor eax,eax + mov al,[r_min] + mov [r],al + mov [v],eax + fild [v] + fstp [r_f] + + xor eax,eax + mov al,[g_min] + mov [g],al + mov [v],eax + fild [v] + fstp [g_f] + + xor eax,eax + mov al,[b_min] + mov [b],al + mov [v],eax + fild [v] + fstp [b_f] + + next_gradient_color_save: + + xor ebx,ebx + xor eax,eax + mov al,[r] + mov bl,al + shl eax,8 + mov al,[g] + shl eax,8 + mov al,[b] + + mov [edx],ax + mov [edx+2],bl + + fld [step_r] + fld [r_f] + fadd st0,st1 + fst [r_f] + fistp [v] + xor eax,eax + mov eax,[v] + mov [r],al + fstp [v] + + fld [step_g] + fld [g_f] + fadd st0,st1 + fst [g_f] + fistp [v] + xor eax,eax + mov eax,[v] + mov [g],al + fstp [v] + + fld [step_b] + fld [b_f] + fadd st0,st1 + fst [b_f] + fistp [v] + xor eax,eax + mov eax,[v] + mov [b],al + fstp [v] + + add edx,3 + + dec ecx + jnz next_gradient_color_save + + ret + +;IN +;NON +;OUT +;variable [skin_height] + +get_skin_height: + + pushad + + mov eax,48 + mov ebx,4 + int 0x40 + + mov [skin_height],eax + popad + + ret +;eax - x +;ebx - y +;ecx - size x +;edx - size y +;esi - pointer to memory for rectangle +SaveFonForRectangle: + + mov [Rectangle.x],eax + mov [Rectangle.y],ebx + mov [Rectangle.width],ecx + mov [Rectangle.height],edx + mov [PointerToMem],esi + + ;get bytes per string + mov eax,61 + mov ebx,2 + mcall + mov [BitsPerPixel],eax + + mov eax,61 + mov ebx,3 + mcall + mov [BytesPerString],eax + + + ;get window coordinats + mov eax,9 + mov ebx,dword IPC_table + or ecx,-1 + mcall + + mov eax,dword[IPC_table+34] + mov ebx,dword[IPC_table+38] + ;mov ecx,dword[IPC_table+42] + ;mov edx,dword[IPC_table+46] + ;mov [WindowCoordinatX],eax + ;mov [WindowCoordinatY],ebx + ;mov [WindowSizeX],ecx + ;mov [WindowSizeY],edx + + add eax,[Rectangle.x] + add ebx,[Rectangle.y] + + imul ebx,[BytesPerString] + mov esi,[Rectangle.width] + + cmp [BitsPerPixel],24 + jne no_24 + + lea eax,[eax+eax*2] + lea esi,[esi+esi*2] + mov edi,3 + jmp exit_bits_per_pixel + no_24: + + shl eax,2 + shl esi,2 + mov edi,4 + exit_bits_per_pixel: + + add eax,ebx + + mov ebx,[BytesPerString] + sub ebx,esi + mov [offset],ebx + + mov esi,[PointerToMem] + mov edx,[Rectangle.height] + next_string_pixels_save: + + mov ecx,[Rectangle.width] + next_pixel_save: + + mov ebx,[gs:eax] + and ebx,0xffffff + mov [esi],bx + shr ebx,16 + mov [esi+2],bl + + add esi,3 + add eax,edi + dec ecx + jnz next_pixel_save + + add eax,[offset] + dec edx + jnz next_string_pixels_save + + exit_: + ret diff --git a/programs/games/bnc/trunk/lang.inc b/programs/games/bnc/trunk/lang.inc new file mode 100644 index 0000000000..30c0149bd9 --- /dev/null +++ b/programs/games/bnc/trunk/lang.inc @@ -0,0 +1 @@ +lang fix ru \ No newline at end of file diff --git a/programs/games/bnc/trunk/macros.inc b/programs/games/bnc/trunk/macros.inc new file mode 100644 index 0000000000..50d2745750 --- /dev/null +++ b/programs/games/bnc/trunk/macros.inc @@ -0,0 +1,270 @@ +; new application structure +macro meos_app_start + { + use32 + org 0x0 + + db 'MENUET01' + dd 0x01 + dd __start + dd __end + dd __memory + dd __stack + + if used __params & ~defined __params + dd __params + else + dd 0x0 + end if + + dd 0x0 + } +MEOS_APP_START fix meos_app_start + +macro code + { + __start: + } +CODE fix code + +macro data + { + __data: + } +DATA fix data + +macro udata + { + if used __params & ~defined __params + __params: + db 0 + __end: + rb 255 + else + __end: + end if + __udata: + } +UDATA fix udata + +macro meos_app_end + { + align 32 + rb 2048 + __stack: + __memory: + __end: + } +MEOS_APP_END fix meos_app_end + + +; macro for defining multiline text data +struc mstr [sstring] + { + forward + local ssize + virtual at 0 + db sstring + ssize = $ + end virtual + dd ssize + db sstring + common + dd -1 + } + + +; strings +macro sz name,[data] { ; from MFAR [mike.dld] + common + if used name + label name + end if + forward + if used name + db data + end if + common + if used name + .size = $-name + end if +} + +macro lsz name,[lng,data] { ; from MFAR [mike.dld] + common + if used name + label name + end if + forward + if (used name)&(lang eq lng) + db data + end if + common + if used name + .size = $-name + end if +} + + + +; easy system call macro +macro mpack dest, hsrc, lsrc +{ + if (hsrc eqtype 0) & (lsrc eqtype 0) + mov dest, (hsrc) shl 16 + lsrc + else + if (hsrc eqtype 0) & (~lsrc eqtype 0) + mov dest, (hsrc) shl 16 + add dest, lsrc + else + mov dest, hsrc + shl dest, 16 + add dest, lsrc + end if + end if +} + +macro __mov reg,a,b { ; mike.dld + if (~a eq)&(~b eq) + mpack reg,a,b + else if (~a eq)&(b eq) + mov reg,a + end if +} + +macro mcall a,b,c,d,e,f { ; mike.dld + __mov eax,a + __mov ebx,b + __mov ecx,c + __mov edx,d + __mov esi,e + __mov edi,f + int 0x40 +} + + + +; optimize the code for size +__regs fix + +macro add arg1,arg2 + { + if (arg2 eqtype 0) + if (arg2) = 1 + inc arg1 + else + add arg1,arg2 + end if + else + add arg1,arg2 + end if + } + +macro sub arg1,arg2 + { + if (arg2 eqtype 0) + if (arg2) = 1 + dec arg1 + else + sub arg1,arg2 + end if + else + sub arg1,arg2 + end if + } + +macro mov arg1,arg2 + { + if (arg1 in __regs) & ((arg2 eqtype 0) | (arg2 eqtype '0')) + if (arg2) = 0 + xor arg1,arg1 + else if (arg2) = 1 + xor arg1,arg1 + inc arg1 + else if (arg2) = -1 + or arg1,-1 + else if (arg2) > -128 & (arg2) < 128 + push arg2 + pop arg1 + else + mov arg1,arg2 + end if + else + mov arg1,arg2 + end if + } + + +macro struct name + { + virtual at 0 + name name + sizeof.#name = $ - name + end virtual + } + +; structures used in MeOS +struc process_information + { + .cpu_usage dd ? ; +0 + .window_stack_position dw ? ; +4 + .window_stack_value dw ? ; +6 + .not_used1 dw ? ; +8 + .process_name rb 12 ; +10 + .memory_start dd ? ; +22 + .used_memory dd ? ; +26 + .PID dd ? ; +30 + .x_start dd ? ; +34 + .y_start dd ? ; +38 + .x_size dd ? ; +42 + .y_size dd ? ; +46 + .slot_state dw ? ; +50 + dw ? ; +52 - reserved + .client_left dd ? ; +54 + .client_top dd ? ; +58 + .client_width dd ? ; +62 + .client_height dd ? ; +66 + .wnd_state db ? ; +70 + rb (1024-71) + } +struct process_information + +struc system_colors + { + .frame dd ? + .grab dd ? + .grab_button dd ? + .grab_button_text dd ? + .grab_text dd ? + .work dd ? + .work_button dd ? + .work_button_text dd ? + .work_text dd ? + .work_graph dd ? + } +struct system_colors + + +; constants + +; events +EV_IDLE = 0 +EV_TIMER = 0 +EV_REDRAW = 1 +EV_KEY = 2 +EV_BUTTON = 3 +EV_EXIT = 4 +EV_BACKGROUND = 5 +EV_MOUSE = 6 +EV_IPC = 7 +EV_STACK = 8 + +; event mask bits for function 40 +EVM_REDRAW = 1b +EVM_KEY = 10b +EVM_BUTTON = 100b +EVM_EXIT = 1000b +EVM_BACKGROUND = 10000b +EVM_MOUSE = 100000b +EVM_IPC = 1000000b +EVM_STACK = 10000000b \ No newline at end of file diff --git a/programs/games/bnc/trunk/macs.inc b/programs/games/bnc/trunk/macs.inc new file mode 100644 index 0000000000..15e087071c --- /dev/null +++ b/programs/games/bnc/trunk/macs.inc @@ -0,0 +1,86 @@ +;************************************ +;******** ЊЂЉђЋ‘› ******************* +;************************************ +; Constants= colors +;-----------------------梥в:0xRRGGBB +cBLACK = 0x000000 ; зҐа­л© +cRED = 0xFF0000 ; Єа б­л© +cYELLOW = 0xFFFF00 ; ¦Ґ«вл© +cGREEN = 0x00FF00 ; §Ґ«Ґ­л© +cNAVY = 0x0000FF ; бЁ­Ё© +cMAGENTA = 0xFF00FF ; ¬ «Ё­®ўл© +cBLUE = 0x00FFFF ; Ј®«гЎ®© +cWHITE = 0xFFFFFF ; ЎҐ«л© +cBROWN = 0x554433 ; Є®аЁз­Ґўл© +cB equ cBLACK +cW equ cWHITE + +macro BeginProgram + { + use32 + org 0x0 + + db 'MENUET01' + dd 0x01 + dd __start + dd __end + dd __memory ; 0x10000 + dd __stack ; 0x10000 + dd 0x0 ; dd __params + dd 0x0 + __start: + } + +macro EndProgram + { + align 32 + rb 256 ;512 + __end: + __stack: + __memory: + } + + +macro LoopBegin lab,begi +{ + push ecx ; ECX->STACK store old + mov ecx,begi + lab: + push ecx ; ECX->STACK counter store +} + +macro LoopEnd lab,endi +{ + pop ecx ;ECX<-STACK counter restore + inc ecx + cmp ecx,endi + jne lab + pop ecx ;ECX<-STACK restore old +} + +macro SetEventMask mmm +{ + mov eax,40 + mov ebx,mmm + int 0x40 +} + +macro redraw_begin +{ + mov eax,12 + mov ebx,1 + int 0x40 +} + +macro redraw_end +{ + mov eax,12 + mov ebx,2 + int 0x40 +} + +macro EventIs eee,lll +{ + cmp eax,eee + je lll +} diff --git a/programs/games/bnc/trunk/main.inc b/programs/games/bnc/trunk/main.inc new file mode 100644 index 0000000000..82c9839a8e --- /dev/null +++ b/programs/games/bnc/trunk/main.inc @@ -0,0 +1,74 @@ +;#*************** +;#* BNC.MAIN() +;#*************** +cTxt equ 0x10000000 +cTxtW equ 0x10FFFFFF + +macro main_loop +{ +draw_window: + redraw_begin +;------------------------------ + ;--- MainWindow + mcall 0,100*65536+250,100*65536+250,0x02FFFFFF ,0x808899AA ,0xFFAAcc + ;--- MainWindow TitleBar + mcall 4,8*65536+8,0x00224422,header,20 + ;--- Button - Close MainWindow + mcall 8,230*65536+12, 5*65536+12, 100 ,0xFF6611 + ;--- Button - "New" ... + mcall 8,190*65536+50,25*65536+15, 200 ,0xAA66CC + mcall 4,205*65536+30,cTxtW,new,3 + ;--- Button - "Turn" ... + ;mcall 8,190*65536+50,50*65536+15, 150 ,0x116611 +;-----------------------------1234-secret-number---show + ; mcall 4, 50*65536+30,cTxt ,nA,4 +;-----------------------------9-lines- + call paint_list + redraw_end +;============================= + event_wait: + mcall 23,100 +;------------------------------------------------------------------------------- +; event in eax - and what will happen +;------------------------------------------------------------------------------- + EventIs EV_REDRAW,draw_window ; redraw window + EventIs EV_KEY,key ; pressed key + EventIs EV_BUTTON,button ; one clicks button + jmp event_wait ; returns at point of waiting for +;------------------------------------------------------------------------------- +; Events handler +;------------------------------------------------------------------------------- +key: ; + mov eax,2 ; key code in ah. + int 0x40 ; + cmp ah,27 ; ESC? + je close ; exit on ESC + + call input ; input 0-9,Enter,<_BackSpace + + jmp draw_window ; event_wait ; +button: ; + mov eax,17 ; button ID in ah + int 0x40 ; +;------------------------------------------------------------------------------- +; Buttons handler +;------------------------------------------------------------------------------- + cmp ah,100 ; id=100("Close window")? + jne noclose ; + close: ; + mov eax,-1 ; CLOSE all + int 0x40 ; + noclose: ; + cmp ah,150 ; id=150 "Turn" + je @F + call rnew ; id=200 "New" ->nA + + call clears + jmp draw_window ;event_wait + + @@: + call paint_list + jmp event_wait +; +} + diff --git a/programs/games/checkers/trunk/board.h b/programs/games/checkers/trunk/board.h new file mode 100644 index 0000000000..59f3edfb28 --- /dev/null +++ b/programs/games/checkers/trunk/board.h @@ -0,0 +1,1410 @@ +#ifndef _HEADER_BOARD_H +#define _HEADER_BOARD_H + +#ifndef __MENUET__ +#include +#include +#include +#include +#include +#include +#endif +#include "position.h" +#include "history.h" +#include "gr-draw.h" + +int ssf = 0; + +struct TIntPoint +{ + TIntPoint() {} + TIntPoint(int x, int y) : x(x), y(y) {} + TIntPoint(const TIntPoint &p) : x(p.x), y(p.y) {} + + TIntPoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; return *this;} + + int x, y; +}; + +struct TRealPoint +{ + TRealPoint() {} + TRealPoint(double x, double y) : x(x), y(y) {} + TRealPoint(const TRealPoint &p) : x(p.x), y(p.y) {} + TRealPoint(const TIntPoint &p) : x(p.x), y(p.y) {} + + TRealPoint &operator=(const TRealPoint &p) {x = p.x; y = p.y; return *this;} + TRealPoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; return *this;} + + TIntPoint Round() {return TIntPoint((int)floor(x+0.5), (int)floor(y+0.5));} + + double x, y; +}; + +struct TProjectivePoint +{ + TProjectivePoint() {} + TProjectivePoint(const TProjectivePoint &p) : x(p.x), y(p.y), z(p.z) {} + TProjectivePoint(double x, double y, double z = 1) : x(x), y(y), z(z) {} + TProjectivePoint(const TIntPoint &p, double z = 1) : x(p.x), y(p.y), z(z) {} + TProjectivePoint(const TRealPoint &p, double z = 1) : x(p.x), y(p.y), z(z) {} + + int IsCorrect() const {return fabs(x) > Eps || fabs(y) > Eps || fabs(z) > Eps;} + int IsFinite() const; + TRealPoint rpnt() const; + int rpnt(TRealPoint &p) const; + TIntPoint pnt() const; + int pnt(TIntPoint &p) const; + + TProjectivePoint &operator=(const TProjectivePoint &p); + TProjectivePoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; z = 1; return *this;} + TProjectivePoint &operator=(const TRealPoint &p) {x = p.x; y = p.y; z = 1; return *this;} + TProjectivePoint &operator*=(int n) {x *= n; y *= n; z *= n; return *this;} + friend TProjectivePoint operator*(const TProjectivePoint &p, int n) + {return TProjectivePoint(p.x * n, p.y * n, p.z * n);} + friend TProjectivePoint operator*(int n, const TProjectivePoint &p) + {return TProjectivePoint(n * p.x, n * p.y, n * p.z);} + TProjectivePoint &operator*=(double n) {x *= n; y *= n; z *= n; return *this;} + friend TProjectivePoint operator*(const TProjectivePoint &p, double n) + {return TProjectivePoint(p.x * n, p.y * n, p.z * n);} + friend TProjectivePoint operator*(double n, const TProjectivePoint &p) + {return TProjectivePoint(n * p.x, n * p.y, n * p.z);} + + double px() const {return x/z;} + double py() const {return y/z;} + + double x, y, z; + + static const double Eps, FR; +}; + +const double TProjectivePoint::Eps = 1e-12; +const double TProjectivePoint::FR = 1e+4; + +inline int TProjectivePoint::IsFinite() const +{ + double fz = fabs(z); + return fz > Eps && fabs(x) < fz * FR && fabs(y) < fz * FR; +} + +TRealPoint TProjectivePoint::rpnt() const +{ + if (!IsFinite()) return TRealPoint(0, 0); + else return TRealPoint(x/z, y/z); +} + +inline int TProjectivePoint::rpnt(TRealPoint &p) const +{ + if (!IsFinite()) {p.x = 0; p.y = 0; return 0;} + else {p.x = x/z; p.y = y/z; return 1;} +} + +inline TIntPoint TProjectivePoint::pnt() const +{ + if (!IsFinite()) return TIntPoint(INT_MIN, INT_MIN); + else return TIntPoint((int)floor(x/z + 0.5), (int)floor(y/z + 0.5)); +} + +inline int TProjectivePoint::pnt(TIntPoint &p) const +{ + if (!IsFinite()) {p.x = INT_MIN; p.y = INT_MIN; return 0;} + else + { + p.x = (int)floor(x/z + 0.5); + p.y = (int)floor(y/z + 0.5); + return 1; + } +} + +TProjectivePoint &TProjectivePoint::operator=(const TProjectivePoint &p) +{ + x = p.x; y = p.y; z = p.z; + return *this; +} + + +class TProjectiveMap +{ +public: + TProjectiveMap() {} + TProjectiveMap(int n) {p[0].x = p[1].y = p[2].z = n; + p[0].y = p[0].z = p[1].x = p[1].z = p[2].x = p[2].y = 0;} + TProjectiveMap(const TProjectiveMap &map) + {p[0] = map.p[0]; p[1] = map.p[1]; p[2] = map.p[2];} + TProjectiveMap(const TProjectivePoint pnt[]) + {p[0] = pnt[0]; p[1] = pnt[1]; p[2] = pnt[2];} + TProjectiveMap(const TProjectivePoint &p0, const TProjectivePoint &p1, + const TProjectivePoint &p2) {p[0] = p0; p[1] = p1; p[2] = p2;} + + TProjectiveMap &operator=(const TProjectiveMap &map) + {p[0] = map.p[0]; p[1] = map.p[1]; p[2] = map.p[2]; return *this;} + TProjectiveMap &operator=(const TProjectivePoint pnt[]) + {p[0] = pnt[0]; p[1] = pnt[1]; p[2] = pnt[2]; return *this;} + TProjectiveMap &operator=(int n) {p[0].x = p[1].y = p[2].z = n; + p[0].y = p[0].z = p[1].x = p[1].z = p[2].x = p[2].y = 0; return *this;} + + TProjectivePoint operator()(const TProjectivePoint &point) const; + friend TProjectiveMap operator*(const TProjectiveMap &a, const TProjectiveMap &b); + TProjectiveMap &operator*=(const TProjectiveMap &b); + TProjectiveMap &operator*=(int n) {p[0] *= n; p[1] *= n; p[2] *= n; return *this;} + friend TProjectiveMap operator*(const TProjectiveMap &a, int n) + {return TProjectiveMap(a.p[0] * n, a.p[1] * n, a.p[2] * n);} + friend TProjectiveMap operator*(int n, const TProjectiveMap &b) + {return TProjectiveMap(n * b.p[0], n * b.p[1], n * b.p[2]);} + TProjectiveMap Reversed() const; + TProjectiveMap &Reverse() {return (*this) = Reversed();} + friend TProjectiveMap operator/(const TProjectiveMap &a, const TProjectiveMap &b) + {return a * b.Reversed();} + TProjectiveMap &operator/=(const TProjectiveMap &b) {return (*this) *= b.Reversed();} + TProjectiveMap &operator/=(int n) {if (!n) (*this) = 0; return *this;} + TProjectivePoint Reversed(const TProjectivePoint &point) const; + + TProjectivePoint operator()(double x, double y, double z = 1) const + {return (*this)(TProjectivePoint(x, y, z));} + TProjectivePoint Reversed(double x, double y, double z = 1) const + {return Reversed(TProjectivePoint(x, y, z));} + + TProjectiveMap &Set4(const TProjectivePoint &a0, const TProjectivePoint &a1, + const TProjectivePoint &a2, const TProjectivePoint &a3); + TProjectiveMap &Set4(const TProjectivePoint a[]) {return Set4(a[0], a[1], a[2], a[3]);} + TProjectiveMap &Set4to4(const TProjectivePoint a[], const TProjectivePoint b[]) + {return Set4(b) /= TProjectiveMap().Set4(a);} + TProjectiveMap &Set4to4(const TProjectivePoint &a0, const TProjectivePoint &a1, + const TProjectivePoint &a2, const TProjectivePoint &a3, + const TProjectivePoint b[]) + {return Set4(b) /= TProjectiveMap().Set4(a0, a1, a2, a3);} + TProjectiveMap &Set4to4(const TProjectivePoint a[], + const TProjectivePoint &b0, const TProjectivePoint &b1, + const TProjectivePoint &b2, const TProjectivePoint &b3) + {return Set4(b0, b1, b2, b2) /= TProjectiveMap().Set4(a);} + TProjectiveMap &Set4to4(const TProjectivePoint &a0, const TProjectivePoint &a1, + const TProjectivePoint &a2, const TProjectivePoint &a3, + const TProjectivePoint &b0, const TProjectivePoint &b1, + const TProjectivePoint &b2, const TProjectivePoint &b3) + {return Set4(b0, b1, b2, b2) /= TProjectiveMap().Set4(a0, a1, a2, a3);} + +public: + TProjectivePoint p[3]; +}; + +TProjectivePoint TProjectiveMap::operator()(const TProjectivePoint &point) const +{ + return TProjectivePoint(p[0].x * point.x + p[1].x * point.y + p[2].x * point.z, + p[0].y * point.x + p[1].y * point.y + p[2].y * point.z, + p[0].z * point.x + p[1].z * point.y + p[2].z * point.z); +} + +TProjectiveMap operator*(const TProjectiveMap &a, const TProjectiveMap &b) +{ + return TProjectiveMap(a(b.p[0]), a(b.p[1]), a(b.p[2])); +} + +TProjectiveMap &TProjectiveMap::operator*=(const TProjectiveMap &b) +{ + TProjectivePoint p0 = (*this)(b.p[0]), p1 = (*this)(b.p[1]), p2 = (*this)(b.p[2]); + p[0] = p0; p[1] = p1; p[2] = p2; + return *this; +} + +TProjectiveMap TProjectiveMap::Reversed() const +{ + return TProjectiveMap(TProjectivePoint(p[1].y * p[2].z - p[2].y * p[1].z, + p[2].y * p[0].z - p[0].y * p[2].z, p[0].y * p[1].z - p[1].y * p[0].z), + TProjectivePoint(p[1].z * p[2].x - p[2].z * p[1].x, + p[2].z * p[0].x - p[0].z * p[2].x, p[0].z * p[1].x - p[1].z * p[0].x), + TProjectivePoint(p[1].x * p[2].y - p[2].x * p[1].y, + p[2].x * p[0].y - p[0].x * p[2].y, p[0].x * p[1].y - p[1].x * p[0].y)); +} + +TProjectivePoint TProjectiveMap::Reversed(const TProjectivePoint &point) const +{ + return TProjectivePoint((p[1].y * p[2].z - p[2].y * p[1].z) * point.x + + (p[1].z * p[2].x - p[2].z * p[1].x) * point.y + + (p[1].x * p[2].y - p[2].x * p[1].y) * point.z, + (p[2].y * p[0].z - p[0].y * p[2].z) * point.x + + (p[2].z * p[0].x - p[0].z * p[2].x) * point.y + + (p[2].x * p[0].y - p[0].x * p[2].y) * point.z, + (p[0].y * p[1].z - p[1].y * p[0].z) * point.x + + (p[0].z * p[1].x - p[1].z * p[0].x) * point.y + + (p[0].x * p[1].y - p[1].x * p[0].y) * point.z); +} + +TProjectiveMap &TProjectiveMap::Set4(const TProjectivePoint &a0, + const TProjectivePoint &a1, const TProjectivePoint &a2, const TProjectivePoint &a3) +{ + p[0] = a0; p[1] = a1; p[2] = a2; + TProjectivePoint K = Reversed(a3); + p[0] *= K.x; p[1] *= K.y; p[2] *= K.z; + return *this; +} + + +TRealPoint r_circle_pnt[13]; +TRealPoint r_star_pnt[13]; +const double r_star_large = 1.2, r_star_small = 0.8; +const double r_ch_lines[] = {0.8, 0.7, 0.6, 0.5}; + +void InitBoardData() +{ + int i, len; + double a, r; + len = NELEM(r_circle_pnt) - 1; + for (i = 0; i < len; i++) + { + a = 2 * i * M_PI / len; + r_circle_pnt[i].x = cos(a); + r_circle_pnt[i].y = sin(a); + } + r_circle_pnt[len] = r_circle_pnt[0]; + len = sizeof(r_star_pnt) / sizeof(r_star_pnt[0]) - 1; + for (i = 0; i < len; i++) + { + a = 2 * i * M_PI / len; + r = (i % 2) ? r_star_small : r_star_large; + r_star_pnt[i].x = cos(a) * r; + r_star_pnt[i].y = sin(a) * r; + } + r_star_pnt[len] = r_star_pnt[0]; +} + +class TChBoard; + +class TSomeDraw +{ +public: + TSomeDraw() {} + + virtual void Draw(TGraphDraw *drw, int w, int h) = 0; + virtual void DrawB(TGraphDraw *drw, TChBoard &brd); + virtual TIntPoint GetDSize(int w, int h) {return TIntPoint(INT_MIN, INT_MIN);} +}; + +class TChBoard +{ +public: + TChBoard(int id = 0); + + TProjectiveMap Get4PMap() const; + int GetW() const {return width;} + int GetH() const {return height;} + void ClearWH() {width = -1; height = -1;} + void Resize(int w, int h); + void Resize(TIntPoint size) {Resize(size.x, size.y);} + + TIntPoint PlToWin(double x, double y) const; + TIntPoint PlToWin(TRealPoint rp) const {return PlToWin(rp.x, rp.y);} + TRealPoint WinToPl(int x, int y) const; + TRealPoint WinToPl(TIntPoint p) const {return WinToPl(p.x, p.y);} + + void NewGame(); + int CanPlayerMove() const {return !IsPlayView && !game_end && !player[MainPos.wmove];} + + void Draw(TGraphDraw *drw); + int ResizeDraw(TGraphDraw *drw, int w, int h); + int CheckResize(TGraphDraw *drw); + int HaveCheckResize() const {return check_resize;} + void SetCheckResize(int cr) {check_resize = cr;} + int MouseClick(TGraphDraw *drw, int x, int y); + void UnMove(TGraphDraw *drw); + + int CMove(TGraphDraw *drw, int x, int y); + int AutoMove(TGraphDraw *drw, int nmove = 0, int draw_check = 1); + + enum PKey {PNull, PEnter, PLeft, PRight, PUp, PDown}; + PKey GetKeySide(PKey key); + int PKeyEvent(TGraphDraw *drw, PKey key = PEnter); +protected: + enum TextLineType {TLT_Main, TLT_Move, TLT_Wait, TLT_GameEnd, TLT_WrongMove, + TLT_PlDidntMove, TLT_PlWrongMove, TLT_WrongColor, + TLT_WfCell, TLT_WnfCell, TLT_WMustEat, TLT_WMustEatMore, + TLT_WNoMove, TLT_WChBack, TLT_WNotDm, TLT_WOnlyDiag, + TLT_WEatYour, TLT_WMoreOne, TLT_WNotDmE, TLT_WMustEatMoreD, + TLT_WTurnBack}; + void GetTextLine(char str[]) const; + void DrawTextLine(TGraphDraw *drw) const; + void LineB(TGraphDraw *drw, double x1, double y1, double x2, double y2) const; + void DrawCh(TGraphDraw *drw, double x0, double y0, const TRealPoint pnt[], int npnt, + int L = NELEM(r_ch_lines)) const; + void DrawIL(TGraphDraw *drw, double x0, double y0, int L) const; + void MoveErase(); + void CurPointClear(TGraphDraw *drw) const; + void RenewMPos() {if (MainPlay.GetPos(MainPos, CurMoveN) < 0) MainPos.Init();} + void PrintLMove(); + void SetNoMove(TGraphDraw *drw = 0, int force = 1); + TextLineType GetTLTfromA(int s) const; + void ChangeTLT(TGraphDraw *drw, TextLineType t); + TextLineType GetSimpleTLT() const; +public: + void ResetTextLine(TGraphDraw *drw); + TChPlayer *GetPlayer(int k) const {return player[k];} + void SetPlayer(int k, TChPlayer *pl) {player[k] = pl;} + int GetBottomColor() const {return BottomColor;} + void SetBottomColor(int c) {BottomColor = c & 1;} +public: + enum {textlineh = 14, min_brd = 120, max_delt = 20, min_brdsize = 70}; + int GetTextLineY() const; + TSomeDraw *GetSomeDraw() const {return some_draw;} + void SetSomeDraw(TSomeDraw *drw) {some_draw = drw;} + TIntPoint GetMinWSize() const {return min_wsize;} + void SetMinWSize(TIntPoint mws) {min_wsize = mws; Resize(width, height);} + void SetMinWSize(int w, int h) {SetMinWSize(TIntPoint(w, h));} + void DrawTimer(TGraphDraw *drw, double t, int wh = 0) const; + int GetNumMove() const {return MainPlay.GetN() - 1;} + int GetCurMoveN() const {return CurMoveN;} + int SetCurMoveN(int n, TGraphDraw *drw = 0); + int SetPlay(const PlayWrite &play); + PlayWrite GetPlay() const {return MainPlay;} + int GetPViewStatus() const {return IsPlayView;} + void SetPViewStatus(int pv) {IsPlayView = pv;} + void GoToCurMove(); + int GetGameEnd() const {return game_end;} + void EraseHistory() {hist_inited = 0;} + int ReinitHistory(); +protected: + double dw_delt, dw_cell; + int width, height; + TProjectiveMap PoleMap; + Position MainPos; + int BottomColor; + unsigned char TheMove[NUM_CELL]; + unsigned char Eaten[NUM_CELL]; + unsigned char BecameD; + TIntPoint CurPoint; + int game_end; + int check_resize; + TIntPoint delta_size; + TextLineType text_line_type; + PlayWrite MainPlay; + TChPlayer *player[2]; + TSomeDraw *some_draw; + TIntPoint min_wsize; + int CurMoveN, IsPlayView; + THistory history; + int hist_inited; +}; + +inline void TSomeDraw::DrawB(TGraphDraw *drw, TChBoard &brd) +{ + Draw(drw, brd.GetW(), brd.GetH()); +} + +void TChBoard::MoveErase() +{ + TheMove[0] = 0; + Eaten[0] = 0; + BecameD = 0; +} + +TChBoard::TChBoard(int id) : history(id) +{ + InitBoardData(); + player[0] = player[1] = 0; + dw_delt = 0.3; + dw_cell = 1; + BottomColor = 0; + check_resize = 0; + delta_size.x = 0; delta_size.y = 0; + some_draw = 0; + min_wsize.x = 80; min_wsize.y = 80; + ClearWH(); + Resize(400, 400); + NewGame(); +} + +TProjectiveMap TChBoard::Get4PMap() const +{ + return TProjectiveMap().Set4(TRealPoint(-dw_delt, -dw_delt), + TRealPoint(NW_CELL*dw_cell + dw_delt, -dw_delt), + TRealPoint(NW_CELL*dw_cell + dw_delt, NW_CELL*dw_cell + dw_delt), + TRealPoint(-dw_delt, NW_CELL*dw_cell + dw_delt)); +} + +void TChBoard::Resize(int w, int h) +{ + width = w; height = h; + if (width < min_wsize.x) width = min_wsize.x; + if (height < min_wsize.y) height = min_wsize.y; + for (;;) + { + if (some_draw) + { + TIntPoint dsz = some_draw->GetDSize(width, height); + if (dsz.x >= 0 && dsz.y >= 0) delta_size = dsz; + } + int change = 0; + if (width < delta_size.x + min_brdsize) + { + width = delta_size.x + min_brdsize; + change++; + } + if (height < delta_size.y + min_brdsize + textlineh) + { + height = delta_size.y + min_brdsize + textlineh; + change++; + } + if (!some_draw || !change) break; + } + double sx = max_delt, dx = width - 2*sx - delta_size.x; + double sy = max_delt, dy = height - 2*sy - delta_size.y - textlineh; + if (dy < min_brd) + { + double d = (min_brd - dy) / 2; + if (d > sy) d = sy; + sy -= d; dy += 2*d; + } + if (dx < min_brd) + { + double d = (min_brd - dx) / 2; + if (d > sx) d = sx; + sx -= d; dx += 2*d; + } + if (dy > dx) {sy += (dy - dx) / 2; dy = dx;} + double tx = (dx - dy * dy / dx) / 3; + PoleMap.Set4(TRealPoint(sx, sy + dy - 70*ssf), TRealPoint(sx + dx, sy + dy), + TRealPoint(sx + dx - tx, sy), TRealPoint(sx + tx, sy + 40*ssf)); + PoleMap /= Get4PMap(); +} + +TIntPoint TChBoard::PlToWin(double x, double y) const +{ + if (BottomColor == 1) y = NW_CELL*dw_cell - y; + else x = NW_CELL*dw_cell - x; + /**/if (ssf) y += 0.6 * sin(x);/**/ + return PoleMap(x, y).pnt(); +} + +TRealPoint TChBoard::WinToPl(int x, int y) const +{ + TRealPoint rpnt; + if (PoleMap.Reversed(x, y).rpnt(rpnt)) + { + /**/if (ssf) rpnt.y -= 0.6 * sin(rpnt.x);/**/ + if (BottomColor == 1) rpnt.y = NW_CELL*dw_cell - rpnt.y; + else rpnt.x = NW_CELL*dw_cell - rpnt.x; + return rpnt; + } + else return TRealPoint(-dw_cell - dw_delt, -dw_cell - dw_delt); +} + +void TChBoard::NewGame() +{ + int k; + MoveErase(); + MainPos.Init(); + MainPlay.Clear(); + for (k = 0; k < NW_CELL * 3 / 2; k++) MainPos.SH[k] = 1; + for (k = 0; k < NW_CELL * 3 / 2; k++) MainPos.SH[NUM_CELL - k - 1] = 2; + MainPlay.Add(0, MainPos); + CurMoveN = 0; + text_line_type = TLT_Main; + game_end = 0; + CurPoint.x = -1; CurPoint.y = -1; + IsPlayView = 0; + printf("\nCheckers: New game.\n"); + EraseHistory(); +} + +int TChBoard::GetTextLineY() const +{ + int y = height - (max_delt + textlineh + delta_size.y); + int i, j; + for (i = 0; i <= 1; i++) for (j = 0; j <= 1; j++) + { + TRealPoint corner; + corner.x = (2*i - 1) * dw_delt + i * NW_CELL * dw_cell; + corner.y = (2*j - 1) * dw_delt + j * NW_CELL * dw_cell; + TIntPoint wcr = PlToWin(corner); + if (wcr.x != INT_MIN && wcr.y != INT_MIN) + { + if (y < wcr.y) y = wcr.y; + } + } + y -= textlineh; + if (y > height - delta_size.y - 2*textlineh) + { + y = height - delta_size.y - 2*textlineh; + } + return (y + height - delta_size.y) / 2; +} + +#ifdef BUILD_RUS +#define aCheckersGame "€Ја  ў и иЄЁ." +#define aRedMoves "Ља б­лҐ 室пв." +#define aBlueMoves "‘Ё­ЁҐ 室пв." +#define aWait "Џ®¤®¦¤ЁвҐ." +#define aRedWins "Ља б­лҐ ўлЁЈа «Ё." +#define aBlueWins "‘Ё­ЁҐ ўлЁЈа «Ё." +#define aDraw "ЌЁзмп." +#define aRed "Ља б­лҐ " +#define aBlue "‘Ё­ЁҐ " +#define aMadeWrongMove "ᤥ« «Ё ­ҐЇа ўЁ«м­л© 室." +#define aNoMove "­Ґ ᬮЈ«Ё ᤥ« вм 室." +#define aEndGame "Љ®­Ґж ЁЈал." +#define aYouWin " (‚л ўлЁЈа «Ё)" +#define aYouLose " (‚л Їа®ЁЈа «Ё)" +#define aRedWin " (Ља б­лҐ ўлЁЈа «Ё)" +#define aBlueWin " (‘Ё­ЁҐ ўлЁЈа «Ё)" +#define aWrongMove "ЌҐўҐа­л© 室." +#define aNotYourChecker "ќв® ­Ґ ў и  и иЄ ." +#define aFreeCell "ќв  Є«ҐвЄ  Їгбв п." +#define aNotFreeCell " иЄЁ ¬®Јгв 室Ёвм в®«мЄ® ­  бў®Ў®¤­лҐ Є«ҐвЄЁ." +#define aMustEat "‚л ¤®«¦­л ў§пвм и иЄг." +#define aMustEatMore "‚л ¤®«¦­л ў§пвм Ґйс и иЄг." +#define aCheckerNoMove "“ нв®© и иЄЁ ­Ґв 室®ў." +#define aNoBack " иЄЁ ­Ґ 室пв ­ § ¤." +#define aNotDamka "ќв® ­Ґ ¤ ¬Є ." +#define aOnlyDiag " иЄЁ 室пв в®«мЄ® Ї® ¤Ё Ј®­ «Ё." +#define aEatYour " иЄЁ ­Ґ ¬®Јгв Ґбвм бў®Ёе." +#define aMoreOne "‚л ­Ґ ¬®¦ҐвҐ ў§пвм Ў®«ҐҐ ®¤­®© и иЄЁ §  а §." +#define aNoTurnBack " иЄЁ ­Ґ ¬®Јгв а §ў®а зЁў вмбп ­ § ¤ ЇаЁ ў§пвЁЁ." +#else +#define aCheckersGame "The checkers game." +#define aRedMoves "Red moves." +#define aBlueMoves "Blue moves." +#define aWait "Please wait." +#define aRedWins "Red wins." +#define aBlueWins "Blue wins." +#define aDraw "Draw." +#define aRed "Red " +#define aBlue "Blue " +#define aMadeWrongMove "make a wrong move." +#define aNoMove "could not make a move." +#define aEndGame "End of the game." +#define aYouWin " (You win)" +#define aYouLose " (You lose)" +#define aRedWin " (Red win)" +#define aBlueWin " (Blue win)" +#define aWrongMove "Wrong move." +#define aNotYourChecker "It isn't your checker." +#define aFreeCell "The cell is free." +#define aNotFreeCell "Checkers may be moved only on a free cell." +#define aMustEat "You must eat a checker." +#define aMustEatMore "You must eat more checkers." +#define aCheckerNoMove "The checker have no moves." +#define aNoBack "Checkers may not be moved back." +#define aNotDamka "It is not a damka." +#define aOnlyDiag "Checkers may be moved only along diagonal." +#define aEatYour "You may not eat your checkers." +#define aMoreOne "You may not eat more than one checker at a time." +#define aNoTurnBack "Checkers may not turn back when eating." +#endif + +void TChBoard::GetTextLine(char str[]) const +{ + str[0] = 0; + int g = (game_end - 1) % 2, h = 0; + switch(text_line_type) + { + case TLT_Main: + strcpy(str, aCheckersGame); + break; + case TLT_Move: + if (MainPos.wmove == 0) + { + strcpy(str, aRedMoves); + } + else strcpy(str, aBlueMoves); + break; + case TLT_Wait: + strcpy(str, aWait); + break; + case TLT_GameEnd: + case TLT_PlDidntMove: + case TLT_PlWrongMove: + if (!game_end) break; + if (text_line_type == TLT_GameEnd) + { + if (game_end == 1) strcpy(str, aRedWins); + else if (game_end == 2) strcpy(str, aBlueWins); + else if (game_end == 5) strcpy(str, aDraw); + } + if (!str[0]) + { + if (game_end >= 1 && game_end <= 4) + { + if (g == 0) strcpy(str, aRed); + else strcpy(str, aBlue); + if (text_line_type == TLT_PlWrongMove) + { + strcat(str, aMadeWrongMove); + } + else strcat(str, aNoMove); + h = 1; + } + else strcpy(str, aEndGame); + } + if (game_end >= 1 && game_end <= 4) + { + if (!IsPlayView && player[1-g] && !player[g]) + { + strcat(str, aYouWin); + } + else if (!IsPlayView && player[g] && !player[1-g]) + { + strcat(str, aYouLose); + } + else if (h && g == 0) strcat(str, aRedWin); + else if (h && g == 1) strcat(str, aBlueWin); + } + break; + case TLT_WrongMove: + strcpy(str, aWrongMove); + break; + case TLT_WrongColor: + strcpy(str, aNotYourChecker); + break; + case TLT_WfCell: + strcpy(str, aFreeCell); + break; + case TLT_WnfCell: + strcpy(str, aNotFreeCell); + break; + case TLT_WMustEat: + strcpy(str, aMustEat); + break; + case TLT_WMustEatMore: + case TLT_WMustEatMoreD: + strcpy(str, aMustEatMore); + break; + case TLT_WNoMove: + strcpy(str, aCheckerNoMove); + break; + case TLT_WChBack: + strcpy(str, aNoBack); + break; + case TLT_WNotDm: + case TLT_WNotDmE: + strcpy(str, aNotDamka); + break; + case TLT_WOnlyDiag: + strcpy(str, aOnlyDiag); + break; + case TLT_WEatYour: + strcpy(str, aEatYour); + break; + case TLT_WMoreOne: + strcpy(str, aMoreOne); + break; + case TLT_WTurnBack: + strcpy(str, aNoTurnBack); + break; + } +} + +void TChBoard::DrawTextLine(TGraphDraw *drw) const +{ + if (!drw || !drw->IsDraw()) return; + char str[100]; + GetTextLine(str); + if (str[0]) drw->DrawText(10, GetTextLineY(), str); +} + +void TChBoard::ResetTextLine(TGraphDraw *drw) +{ + if (!game_end && text_line_type != TLT_Move) ChangeTLT(drw, TLT_Move); +} + +void TChBoard::LineB(TGraphDraw *drw, double x1, double y1, double x2, double y2) const +{ + if (!drw || !drw->IsDraw()) return; + TIntPoint p1 = PlToWin(x1, y1), p2 = PlToWin(x2, y2); + if (p1.x != INT_MIN && p1.y != INT_MIN && p2.x != INT_MIN && p2.y != INT_MIN) + { + drw->DrawLine(p1.x, p1.y, p2.x, p2.y); + } +} + +void TChBoard::DrawCh(TGraphDraw *drw, double x0, double y0, const TRealPoint pnt[], int npnt, int L) const +{ + if (!drw || !drw->IsDraw()) return; + int i, j; + for (j = 0; j < L; j++) + { + for (i = 0; i < npnt - 1; i++) + { + LineB(drw, x0 + pnt[i].x * dw_cell * r_ch_lines[j] / 2, + y0 + pnt[i].y * dw_cell * r_ch_lines[j] / 2, + x0 + pnt[i+1].x * dw_cell * r_ch_lines[j] / 2, + y0 + pnt[i+1].y * dw_cell * r_ch_lines[j] / 2); + } + } +} + +void TChBoard::DrawIL(TGraphDraw *drw, double x0, double y0, int L) const +{ + if (!drw || !drw->IsDraw()) return; + int i, j; + if (L == 0 || L == 1) + { + const int numDST[2] = {2, 4}; + const double DST[2][4] = {{0.96, 0.88}, {0.8, 0.76, 0.72, 0.68}}; + const int MULT[4][4] = {{-1, -1, -1, 1}, {-1, 1, 1, 1}, + {-1, -1, 1, -1}, {1, -1, 1, 1}}; + for (i = 0; i < numDST[L]; i++) for (j = 0; j < 4; j++) + { + LineB(drw, x0 + dw_cell * DST[L][i] * MULT[j][0] / 2, + y0 + dw_cell * DST[L][i] * MULT[j][1] / 2, + x0 + dw_cell * DST[L][i] * MULT[j][2] / 2, + y0 + dw_cell * DST[L][i] * MULT[j][3] / 2); + } + } + else if (L == 2) + { + const double DP[] = {0.85, 0.90, 0.95}; + const int numDP = NELEM(DP); + for (i = 0; i < numDP; i++) for (j = -1; j <= 1; j += 2) + { + LineB(drw, x0 - j * dw_cell * DP[i] / 2, + y0 - dw_cell * DP[numDP - i - 1] / 2, + x0 + j * dw_cell * DP[numDP - i - 1] / 2, + y0 + dw_cell * DP[i] / 2); + } + } +} + +void TChBoard::Draw(TGraphDraw *drw) +{ + if (!drw || !drw->IsDraw()) return; + if (CheckResize(drw)) drw->DrawClear(); + int i, j, k, kn; + unsigned long black = drw->GetBlackColor(); + unsigned long red = drw->CreateColor(65535u, 0, 0); + unsigned long green = drw->CreateColor(0, 49151u, 0); + unsigned long blue = drw->CreateColor(0, 0, 65535u); + drw->SetColor(black); + for (i = -1; i <= NW_CELL + 1; i++) for (j = -1; j <= NW_CELL; j++) + { + if (i < 0 || i > NW_CELL || j >= 0 && j < NW_CELL) + { + double mval = dw_cell * NW_CELL + dw_delt; + double x, y0, y1; + if (i < 0) x = -dw_delt; + else if (i > NW_CELL) x = mval; + else x = i * dw_cell; + if (j < 0) y0 = -dw_delt; + else if (j > NW_CELL) y0 = mval; + else y0 = j * dw_cell; + if ((j+1) < 0) y1 = -dw_delt; + else if ((j+1) > NW_CELL) y1 = mval; + else y1 = (j+1) * dw_cell; + LineB(drw, x, y0, x, y1); + } + } + for (i = -1; i <= NW_CELL; i++) for (j = -1; j <= NW_CELL + 1; j++) + { + if (j < 0 || j > NW_CELL || i >= 0 && i < NW_CELL) + { + double mval = dw_cell * NW_CELL + dw_delt; + double x0, x1, y; + if (i < 0) x0 = -dw_delt; + else if (i > NW_CELL) x0 = mval; + else x0 = i * dw_cell; + if ((i+1) < 0) x1 = -dw_delt; + else if ((i+1) > NW_CELL) x1 = mval; + else x1 = (i+1) * dw_cell; + if (j < 0) y = -dw_delt; + else if (j > NW_CELL) y = mval; + else y = j * dw_cell; + LineB(drw, x0, y, x1, y); + } + } + for (i = -1; i <= 1; i += 2) + { + drw->SetColor((i < 0) ? red : blue); + for (j = -1; j <= 1; j += 2) + { + double c = dw_cell * NW_CELL / 2; + double d = (dw_cell/2 > dw_delt) ? dw_delt : dw_cell/2; + LineB(drw, c + j * (c + 0.5*d), c + i * (c - 0.5*d), + c + j * (c + 0.5*d), c + i * (c - 3.5*d)); + LineB(drw, c + j * (c + 0.5*d), c + i * (c - 3.5*d), + c + j * (c + 0.2*d), c + i * (c - 2.5*d)); + LineB(drw, c + j * (c + 0.5*d), c + i * (c - 3.5*d), + c + j * (c + 0.8*d), c + i * (c - 2.5*d)); + LineB(drw, c + j * (c + 0.2*d), c + i * (c - 2.5*d), + c + j * (c + 0.8*d), c + i * (c - 2.5*d)); + } + } + for (i = 0; i < NW_CELL; i++) for (j = 0; j < NW_CELL; j++) + { + if (!PoleCpos(i, j)) + { + drw->SetColor(black); + LineB(drw, (i+0.33) * dw_cell, j * dw_cell, (i+0.33) * dw_cell, (j+1) * dw_cell); + LineB(drw, (i+0.67) * dw_cell, j * dw_cell, (i+0.67) * dw_cell, (j+1) * dw_cell); + LineB(drw, i * dw_cell, (j+0.33) * dw_cell, (i+1) * dw_cell, (j+0.33) * dw_cell); + LineB(drw, i * dw_cell, (j+0.67) * dw_cell, (i+1) * dw_cell, (j+0.67) * dw_cell); + LineB(drw, i * dw_cell, j * dw_cell, (i+1) * dw_cell, (j+1) * dw_cell); + LineB(drw, (i+1) * dw_cell, j * dw_cell, i * dw_cell, (j+1) * dw_cell); + } + else + { + k = PoleToNum(i, j); + kn = MainPos.SH[k]; + if (TheMove[0] > 0 && k == TheMove[1]) + { + if (kn == 1 || kn == 2) kn = 5; + else if (kn == 3 || kn == 4) kn = 6; + } + if (TheMove[0] > 0 && k == TheMove[TheMove[0]]) + { + kn = MainPos.SH[TheMove[1]]; + if (kn <= 2 && BecameD) kn += 2; + } + if (kn == 1) + { + drw->SetColor(red); + DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, + r_circle_pnt, NELEM(r_circle_pnt)); + } + else if (kn == 2) + { + drw->SetColor(blue); + DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, + r_circle_pnt, NELEM(r_circle_pnt)); + } + else if (kn == 3) + { + drw->SetColor(red); + DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, + r_star_pnt, NELEM(r_star_pnt)); + } + else if (kn == 4) + { + drw->SetColor(blue); + DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, + r_star_pnt, NELEM(r_star_pnt)); + } + else if (kn == 5) + { + drw->SetColor(green); + DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, + r_circle_pnt, NELEM(r_circle_pnt), 2); + } + else if (kn == 6) + { + drw->SetColor(green); + DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, + r_circle_pnt, NELEM(r_circle_pnt), 2); + } + } + } + for (k = 1; k <= Eaten[0]; k++) + { + if (TheMove[0] <= 0 || Eaten[k] != TheMove[TheMove[0]]) + { + NumToPole(Eaten[k], i, j); + kn = MainPos.SH[Eaten[k]]; + if (kn) + { + if (kn == 1 || kn == 3) drw->SetColor(blue); + else if (kn == 2 || kn == 4) drw->SetColor(red); + DrawIL(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, 2); + } + } + } + if (TheMove[0] > 0) + { + NumToPole(TheMove[TheMove[0]], i, j); + drw->SetColor(green); + DrawIL(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, 1); + } + if (CurPoint.x >= 0 && CurPoint.y >= 0) + { + drw->SetColor(green); + DrawIL(drw, (CurPoint.x+0.5)*dw_cell, (CurPoint.y+0.5)*dw_cell, 0); + } + drw->SetColor(black); + DrawTextLine(drw); + if (some_draw) some_draw->DrawB(drw, *this); + drw->FreeColor(red); + drw->FreeColor(green); + drw->FreeColor(blue); +} + +int TChBoard::ResizeDraw(TGraphDraw *drw, int w, int h) +{ + int w0 = width, h0 = height; + Resize(w, h); + if (drw && drw->IsDraw() && (width != w0 || height != h0)) + { + drw->DrawClear(); + Draw(drw); + return 1; + } + else return 0; +} + +int TChBoard::CheckResize(TGraphDraw *drw) +{ + if (!drw || !check_resize) return 0; + int w, h; + drw->GetSize(w, h); + if (w < 0 || h < 0) return 0; + int w0 = width, h0 = height; + Resize(w, h); + return width != w0 || height != h0; +} + +void TChBoard::CurPointClear(TGraphDraw *drw) const +{ + if (!drw || !drw->IsDraw()) return; + drw->SetColor(drw->GetWhiteColor()); + DrawIL(drw, (CurPoint.x+0.5)*dw_cell, (CurPoint.y+0.5)*dw_cell, 0); +} + +int TChBoard::MouseClick(TGraphDraw *drw, int x, int y) +{ + TRealPoint rpnt = WinToPl(x, y); + if (rpnt.x < -dw_delt || rpnt.y < -dw_delt || + rpnt.x > NW_CELL*dw_cell + dw_delt || + rpnt.y > NW_CELL*dw_cell + dw_delt) return -1; + if (CurPoint.x >= 0 && CurPoint.y >= 0) + { + CurPointClear(drw); + CurPoint.x = -1; CurPoint.y = -1; + Draw(drw); + } + ResetTextLine(drw); + if (AutoMove(drw)) return 3; + if (!CanPlayerMove()) return 0; + int i = (int)floor(rpnt.x / dw_cell), j = (int)floor(rpnt.y / dw_cell); + if (i < 0 || j < 0 || i >= NW_CELL || j >= NW_CELL) return 0; + if (!PoleCpos(i, j)) return 1; + return 2 + CMove(drw, i, j); +} + +TChBoard::PKey TChBoard::GetKeySide(PKey key) +{ + if (key != PLeft && key != PRight && key != PUp && key != PDown) return key; + TIntPoint a0 = PlToWin(4*dw_cell, 0); + TIntPoint a1 = PlToWin(4*dw_cell, 8*dw_cell); + TIntPoint b0 = PlToWin(0, 4*dw_cell); + TIntPoint b1 = PlToWin(8*dw_cell, 4*dw_cell); + double ax = a0.x - a1.x, ay = a0.y - a1.y; + double bx = b0.x - b1.x, by = b0.y - b1.y; + double t; + if (a0.x == INT_MIN || a0.y == INT_MIN || a1.x == INT_MIN || + a1.y == INT_MIN || fabs(ax) < 0.5 && fabs(ay) < 0.5) + { + ax = 0, ay = 1; + } + if (b0.x == INT_MIN || b0.y == INT_MIN || b1.x == INT_MIN || + b1.y == INT_MIN || fabs(bx) < 0.5 && fabs(by) < 0.5) + { + bx = 1, by = 0; + } + t = fabs(ax) + fabs(ay); ax /= t; ay /= t; + t = fabs(bx) + fabs(by); bx /= t; by /= t; + if (fabs(ax) <= fabs(bx)) + { + if (key == PLeft) return (bx > 0) ? PRight : PLeft; + if (key == PRight) return (bx > 0) ? PLeft : PRight; + if (key == PUp) return (ay > 0) ? PDown : PUp; + if (key == PDown) return (ay > 0) ? PUp : PDown; + } + else + { + if (key == PLeft) return (ax > 0) ? PDown : PUp; + if (key == PRight) return (ax > 0) ? PUp : PDown; + if (key == PUp) return (by > 0) ? PRight : PLeft; + if (key == PDown) return (by > 0) ? PLeft : PRight; + } + return PNull; +} + +int TChBoard::PKeyEvent(TGraphDraw *drw, PKey key) +{ + ResetTextLine(drw); + if (AutoMove(drw)) return 3; + if (!CanPlayerMove()) return 0; + key = GetKeySide(key); + if (CurPoint.x < 0 || CurPoint.y < 0 || + CurPoint.x >= NW_CELL || CurPoint.y >= NW_CELL) + { + CurPoint.x = NW_CELL / 2; + CurPoint.y = NW_CELL / 2; + Draw(drw); + return 1; + } + if (key == PEnter) return 2 + CMove(drw, CurPoint.x, CurPoint.y); + if (drw && drw->IsDraw() && CheckResize(drw)) + { + drw->DrawClear(); + Draw(drw); + } + if (key == PLeft) + { + if (CurPoint.x == 0) return 0; + CurPointClear(drw); + CurPoint.x--; + Draw(drw); + return 1; + } + else if (key == PRight) + { + if (CurPoint.x == NW_CELL - 1) return 0; + CurPointClear(drw); + CurPoint.x++; + Draw(drw); + return 1; + } + else if (key == PUp) + { + if (CurPoint.y == 0) return 0; + CurPointClear(drw); + CurPoint.y--; + Draw(drw); + return 1; + } + else if (key == PDown) + { + if (CurPoint.y == NW_CELL - 1) return 0; + CurPointClear(drw); + CurPoint.y++; + Draw(drw); + return 1; + } + else return 0; +} + +void TChBoard::UnMove(TGraphDraw *drw) +{ + MoveErase(); + if (drw && drw->IsDraw()) + { + drw->DrawClear(); + Draw(drw); + } +} + +TChBoard::TextLineType TChBoard::GetTLTfromA(int s) const +{ + if (s >= 0) return TLT_Main; + switch(s) + { + case Position::AWColor: return TLT_WrongColor; + case Position::AfCell: return TLT_WfCell; + case Position::AnfCell: return TLT_WnfCell; + case Position::AMustEat: return TLT_WMustEat; + case Position::AMustEatMore: return TLT_WMustEatMore; + case Position::AMustEatMoreD: return TLT_WMustEatMoreD; + case Position::ANoMove: return TLT_WNoMove; + case Position::AChBack: return TLT_WChBack; + case Position::ANotDm: return TLT_WNotDm; + case Position::ANotDmE: return TLT_WNotDmE; + case Position::AOnlyDiag: return TLT_WOnlyDiag; + case Position::AEatYour: return TLT_WEatYour; + case Position::AMoreOne: return TLT_WMoreOne; + case Position::ATurnBack: return TLT_WTurnBack; + default: return TLT_WrongMove; + } +} + +void TChBoard::ChangeTLT(TGraphDraw *drw, TextLineType t) +{ + if (text_line_type == t) return; + if (drw && drw->IsDraw()) + { + drw->SetColor(drw->GetWhiteColor()); + DrawTextLine(drw); + } + text_line_type = t; + if (drw && drw->IsDraw()) + { + drw->SetColor(drw->GetBlackColor()); + DrawTextLine(drw); + } +} + +TChBoard::TextLineType TChBoard::GetSimpleTLT() const +{ + if (game_end && CurMoveN >= MainPlay.GetN() - 1) return TLT_GameEnd; + else return TLT_Move; +} + +inline int TChBoard::ReinitHistory() +{ + if (history.Play(MainPlay)) {hist_inited = 1; return 1;} + else {hist_inited = 0; return 0;} +} + +void TChBoard::PrintLMove() +{ + PlayWrite::PMv pmv; + if (MainPlay.GetMoveL(pmv.mv) >= 0) + { + MainPlay.GetPosL(pmv.pos, 1); + char *s = new char[pmv.pos.GetLenMvEx(pmv.mv, 11)]; + if (s) + { + pmv.pos.WriteMvEx(pmv.mv, s, 11); + printf("Checkers: %s%s\n", (pmv.pos.wmove == 1) ? "..." : "", s); + delete[] s; + } + if (!hist_inited) ReinitHistory(); + else history.Move(pmv.pos, pmv.mv, MainPlay.GetN() - 1); + } +} + +int TChBoard::CMove(TGraphDraw *drw, int x, int y) +{ + if (AutoMove(drw)) return 1; + if (!CanPlayerMove()) return 0; + if (!game_end && text_line_type != TLT_Move) ChangeTLT(drw, TLT_Move); + int k = PoleToNum(x, y), s; + if (TheMove[0] > 0) + { + if (!PoleCpos(x, y) || k == TheMove[TheMove[0]]) {UnMove(drw); return 1;} + int e = 1; + s = MainPos.AMove(TheMove, k, e); + if (s < 0) + { + ChangeTLT(drw, GetTLTfromA(s)); + return 0; + } + if (s < NUM_CELL) Eaten[++Eaten[0]] = (unsigned char)s; + TheMove[++TheMove[0]] = (unsigned char)k; + BecameD = BecameD || MainPos.BecameD(k, MainPos.SH[TheMove[1]]); + if (e == 0) + { + if (MainPlay.Add(TheMove) != 0) + { + ChangeTLT(drw, TLT_WrongMove); + return 0; + } + CurMoveN = MainPlay.GetN() - 1; + MoveErase(); + RenewMPos(); + PrintLMove(); + if (AutoMove(drw)) return 1; + } + if (drw && drw->IsDraw()) + { + drw->DrawClear(); + Draw(drw); + } + return 1; + } + else + { + if (!PoleCpos(x, y)) return 0; + s = MainPos.AChCell(k); + if (s != 1) + { + ChangeTLT(drw, GetTLTfromA(s)); + return 0; + } + TheMove[0] = 1; + TheMove[1] = (unsigned char)k; + Draw(drw); + return 1; + } +} + +void TChBoard::SetNoMove(TGraphDraw *drw, int force) +{ + if (!force && CurPoint.x < 0 && CurPoint.y < 0 && TheMove[0] == 0 && Eaten[0] == 0) + { + return; + } + CurPoint.x = -1; CurPoint.y = -1; + MoveErase(); + if (drw && drw->IsDraw()) + { + drw->DrawClear(); + Draw(drw); + } +} + +int TChBoard::AutoMove(TGraphDraw *drw, int nmove, int draw_check) +{ + if (game_end || IsPlayView) {SetNoMove(drw, 0); return 0;} + if (CurMoveN < MainPlay.GetN() - 1) + { + CurMoveN = MainPlay.GetN() - 1; + RenewMPos(); + SetNoMove(drw); + return 2; + } + if (!MainPos.AllCanEat() && !MainPos.AllCanMove()) + { + game_end = 2 - MainPos.wmove; + ChangeTLT(drw, TLT_GameEnd); + if (!player[game_end - 1]) printf("Checkers: You win.\n"); + else printf("Checkers: You lose.\n"); + SetNoMove(drw); + return 3; + } + else if (draw_check > 0 && MainPlay.IsDraw()) + { + game_end = 5; + ChangeTLT(drw, TLT_GameEnd); + printf("Checkers: Draw.\n"); + SetNoMove(drw); + return 3; + } + if (!player[MainPos.wmove]) return 0; + TIntPoint CurP0 = CurPoint; + if (CurPoint.x >= 0 && CurPoint.y >= 0) + { + if (drw) CurPointClear(drw); + CurPoint.x = -1; CurPoint.y = -1; + } + MoveErase(); + int k; + for (k = 0; player[MainPos.wmove] && (k < nmove || nmove == 0); k++) + { + TChPlayer::PMv pmv; + pmv.pos = MainPos; + Position::SetNullMv(pmv.mv); + MainPlay.GetMoveL(pmv.mv); + text_line_type = TLT_Move; + if (!player[MainPos.wmove]->Move(pmv)) + { + text_line_type = TLT_PlDidntMove; + game_end = 4 - MainPos.wmove; + break; + } + if (MainPlay.Add(pmv.mv) != 0) + { + text_line_type = TLT_PlWrongMove; + game_end = 4 - MainPos.wmove; + break; + } + CurMoveN = MainPlay.GetN() - 1; + MoveErase(); + RenewMPos(); + PrintLMove(); + if (!MainPos.AllCanEat() && !MainPos.AllCanMove()) + { + game_end = 2 - MainPos.wmove; + text_line_type = TLT_GameEnd; + if (!player[game_end - 1]) printf("Checkers: You win.\n"); + else printf("Checkers: You lose.\n"); + break; + } + else if (draw_check >= 0 && MainPlay.IsDraw()) + { + game_end = 5; + text_line_type = TLT_GameEnd; + printf("Checkers: Draw.\n"); + break; + } + } + if (!game_end) + { + text_line_type = TLT_Move; + CurPoint = CurP0; + } + if (drw && drw->IsDraw()) + { + drw->DrawClear(); + Draw(drw); + } + return 1; +} + +void TChBoard::DrawTimer(TGraphDraw *drw, double t, int wh) const +{ + if (!drw || !drw->IsDraw()) return; + if (wh) drw->SetColor(drw->GetWhiteColor()); + else drw->SetColor(drw->GetBlackColor()); + double r1 = dw_delt * 0.4, r2 = dw_delt * 0.45; + double x = t * dw_cell * NW_CELL, y = -dw_delt / 2; + if (MainPos.wmove == 1) + { + x = dw_cell * NW_CELL - x; + y = dw_cell * NW_CELL - y; + } + LineB(drw, x - r1, y - r2, x + r2, y + r1); + LineB(drw, x - r2, y - r1, x + r1, y + r2); + LineB(drw, x - r1, y + r2, x + r2, y - r1); + LineB(drw, x - r2, y + r1, x + r1, y - r2); + if (wh) + { + int i, j, jj; + drw->SetColor(drw->GetBlackColor()); + for (i = -1; i <= NW_CELL; i++) + { + double mval = dw_cell * NW_CELL + dw_delt; + double x0, x1, y; + if (i < 0) x0 = -dw_delt; + else if (i > NW_CELL) x0 = mval; + else x0 = i * dw_cell; + if ((i+1) < 0) x1 = -dw_delt; + else if ((i+1) > NW_CELL) x1 = mval; + else x1 = (i+1) * dw_cell; + if (fabs(x0 - x) < dw_delt || fabs(x1 - x) < dw_delt) + { + for (jj = 0; jj <= 1; jj++) + { + if (MainPos.wmove == 1) j = NW_CELL + jj; + else j = -jj; + if (j < 0 || j > NW_CELL || i >= 0 && i < NW_CELL) + { + if (j < 0) y = -dw_delt; + else if (j > NW_CELL) y = mval; + else y = j * dw_cell; + LineB(drw, x0, y, x1, y); + } + } + } + } + } +} + +int TChBoard::SetCurMoveN(int n, TGraphDraw *drw) +{ + int nmove = MainPlay.GetN() - 1; + if (n > nmove) n = nmove; + if (n < 0) n = 0; + if (CurMoveN != n) + { + CurMoveN = n; + RenewMPos(); + if (n < nmove) + { + MoveErase(); + CurPoint.x = -1; CurPoint.y = -1; + } + text_line_type = GetSimpleTLT(); + if (drw && drw->IsDraw()) + { + drw->DrawClear(); + Draw(drw); + } + return 1; + } + else return 0; +} + +int TChBoard::SetPlay(const PlayWrite &play) +{ + if (play.GetN() <= 0) return 0; + MainPlay = play; + MoveErase(); + CurPoint.x = -1; CurPoint.y = -1; + CurMoveN = INT_MIN; + SetCurMoveN(play.GetN()); + if (!MainPos.AllCanEat() && !MainPos.AllCanMove()) game_end = 2 - MainPos.wmove; + else if (MainPlay.IsDraw()) game_end = 5; + else game_end = 0; + text_line_type = GetSimpleTLT(); + IsPlayView = 1; + EraseHistory(); + return 1; +} + +void TChBoard::GoToCurMove() +{ + if (!MainPos.AllCanEat() && !MainPos.AllCanMove() || + MainPlay.IsDraw(CurMoveN + 1)) return; + MainPlay.ClearFrom(CurMoveN + 1); + MoveErase(); + game_end = 0; + text_line_type = GetSimpleTLT(); + IsPlayView = 0; +} + +#endif //_HEADER_BOARD_H diff --git a/programs/games/checkers/trunk/buttons.h b/programs/games/checkers/trunk/buttons.h new file mode 100644 index 0000000000..ac0dbba432 --- /dev/null +++ b/programs/games/checkers/trunk/buttons.h @@ -0,0 +1,355 @@ +#ifndef _HEADER_BUTTONS_H +#define _HEADER_BUTTONS_H + +#ifndef __MENUET__ +#include +#include +#include +#endif +#include "gr-draw.h" + +struct TXButton +{ + TXButton(int n = -1, int w = 100, int h = 20) : num(n), w(w), h(h), drw(1) {} + TXButton(const TXButton &b) : w(b.w), h(b.h) {} + + TXButton &operator=(const TXButton &b) {w = b.w; h = b.h; num = b.num; return *this;} + + virtual void Draw(TGraphDraw *drw, int x0, int y0, + unsigned long dcolor, unsigned long lcolor, unsigned long tcolor, int ins = 0); + virtual int ButtonPnt(int xp, int yp, int &n, int kind = 0); + + int num, w, h, drw; +}; + +void TXButton::Draw(TGraphDraw *drw, int x0, int y0, + unsigned long dcolor, unsigned long /*lcolor*/, + unsigned long /*tcolor*/, int /*ins*/) +{ + if (!drw || !drw->IsDraw()) return; + drw->SetColor(dcolor); + drw->DrawLine(x0, y0, x0 + w, y0); + drw->DrawLine(x0, y0, x0, y0 + h); + drw->DrawLine(x0 + w, y0, x0 + w, y0 + h); + drw->DrawLine(x0, y0 + h, x0 + w, y0 + h); +} + +int TXButton::ButtonPnt(int xp, int yp, int &n, int /*kind*/) +{ + n = num; + return (xp >= 0 && yp >= 0 && xp <= w && yp <= h) ? 1 : INT_MIN; +} + + +struct TextButton : public TXButton +{ + enum {thick_def = 3}; + + TextButton(int n = -1, int w = 100, int h = 20, char *text = 0, int thick = thick_def) + : TXButton(n, w, h), text(text), thick(thick) {CheckDefW();} + TextButton(const TXButton &b, char *text = 0, int thick = thick_def) + : TXButton(b), text(text), thick(thick) {CheckDefW();} + TextButton(const TextButton &b) : TXButton(b), text(b.text), thick(b.thick) {} + + TextButton &operator=(const TextButton &b); + + virtual void Draw(TGraphDraw *drw, int x0, int y0, + unsigned long dcolor, unsigned long lcolor, unsigned long tcolor, int ins = 0); + void CheckDefW(); + + int thick; + char *text; +}; + +inline TextButton &TextButton::operator=(const TextButton &b) +{ + text = b.text; + TXButton::operator=(b); + return *this; +} + +void TextButton::Draw(TGraphDraw *drw, int x0, int y0, + unsigned long dcolor, unsigned long lcolor, unsigned long tcolor, int ins) +{ + if (!drw || !drw->IsDraw()) return; + int i; + if (thick <= -1 && thick >= -5) + { + drw->SetColor(dcolor); + for (i = 0; i < -thick; i++) + { + drw->DrawLine(x0 + i, y0 + i, x0 + w - i, y0 + i); + drw->DrawLine(x0 + i, y0 + i, x0 + i, y0 + h - i); + drw->DrawLine(x0 + w - i, y0 + i, x0 + w - i, y0 + h - i); + drw->DrawLine(x0 + i, y0 + h - i, x0 + w - i, y0 + h - i); + } + } + else if (thick > 0) + { + for (i = 0; i < thick; i++) + { + drw->SetColor(ins ? dcolor : lcolor); + drw->DrawLine(x0 + i, y0 + i, x0 + w - i, y0 + i); + drw->DrawLine(x0 + i, y0 + i, x0 + i, y0 + h - i); + drw->SetColor(ins ? lcolor : dcolor); + drw->DrawLine(x0 + w - i, y0 + i, x0 + w - i, y0 + h - i); + drw->DrawLine(x0 + i, y0 + h - i, x0 + w - i, y0 + h - i); + } + } + else TXButton::Draw(drw, x0, y0, dcolor, lcolor, tcolor, ins); + if (text) + { + drw->SetColor(tcolor); + drw->DrawText(x0 + 7, y0 + (h - drw->GetTextH(text)) / 2, text); + } +} + +inline void TextButton::CheckDefW() +{ + if (w < 0 && text) w = 15 + strlen(text) * 8; +} + +class TXButtonArray +{ +public: + TXButtonArray(int d = 10) : button(0), nbutton(0), mbutton(0), + delt(d), ins(-1), k_ins(0) {} + ~TXButtonArray() {Clear();} + + void Clear(); + void Add(TXButton *bt); + void Add(int n = -1, int w = 100, int h = 20, char *str = 0, + int thick = TextButton::thick_def); + TXButton *operator[](int i) {return button[i];} + int GetNButton() const {return nbutton;} + int GetInsert() const {return ins;} + TXButton *GetButton(int n); + + int GetDelt() const {return delt;} + void SetDelt(int d) {delt = d;} + + int GetParam(int w, int p) const; + int GetNumStr(int w) const {return GetParam(w, 0);} + int GetHeight(int w) const {return GetParam(w, 1);} + int GetFWidth() const; + + void Draw(TGraphDraw *drw, int x0, int y0, int w); + void Draw(TGraphDraw *drw, int x0, int y0, int w, + unsigned long dcolor, unsigned long lcolor, unsigned long tcolor, int insd = 1); + int ButtonPnt(int xp, int yp, int w, int &n, int kind = 0); +protected: + void Extend(int n = -1); + + TXButton **button; + int nbutton, mbutton; + int delt; + int ins, k_ins; +}; + +void TXButtonArray::Clear() +{ + int i; + if (button) + { + for (i = 0; i < nbutton; i++) if (button[i]) delete button[i]; + delete[] button; + } + button = 0; nbutton = 0; mbutton = 0; +} + +void TXButtonArray::Extend(int n) +{ + if (n < 0) n = nbutton + 1; + if (mbutton < n) + { + typedef TXButton *TXButtonPnt; + TXButton **b_old = button; + int m_old = mbutton; + mbutton = n * 2; + button = new TXButtonPnt[mbutton]; + for (int i = 0; i < mbutton; i++) button[i] = 0; + if (b_old) + { + for (int i = 0; i < m_old; i++) button[i] = b_old[i]; + delete[] b_old; + } + } +} + +void TXButtonArray::Add(TXButton *bt) +{ + Extend(); + if (button[nbutton]) delete[] button[nbutton]; + button[nbutton] = bt; + nbutton++; +} + +void TXButtonArray::Add(int n, int w, int h, char *str, int thick) +{ + if (thick < 0 && !str) Add(new TXButton(n, w, h)); + else Add(new TextButton(n, w, h, str, thick)); +} + +TXButton *TXButtonArray::GetButton(int n) +{ + int i; + for (i = 0; i < nbutton; i++) + { + if (button[i] && button[i]->num == n) return button[i]; + } + return 0; +} + +int TXButtonArray::GetFWidth() const +{ + int i, x = 0; + for (i = 0; i < nbutton; i++) + { + if (button[i] && button[i]->drw > 0) x += button[i]->w + delt; + } + if (x != 0) x -= delt; + return x; +} + +int TXButtonArray::GetParam(int w, int p) const +{ + int i, k = 0; + int x = 0, y = 0, ym = 0; + for (i = 0; i < nbutton; i++) if (button[i] && button[i]->drw > 0) + { + int xx = x + button[i]->w + delt; + if (x != 0 && xx > w + delt) + { + k++; y += ym + delt; ym = 0; + x = 0; xx = x + button[i]->w + delt; + } + x = xx; + if (ym < button[i]->h) ym = button[i]->h; + } + if (x != 0) {k++; y += ym;} + else if (y != 0) y -= delt; + if (p == 0) return k; + else if (p == 1) return y; + else return -1; +} + +void TXButtonArray::Draw(TGraphDraw *drw, int x0, int y0, int w) +{ + const unsigned short power_gray = 49152U; + unsigned long black = drw->GetBlackColor(); + unsigned long grey = drw->CreateColor(power_gray, power_gray, power_gray); + Draw(drw, x0, y0, w, black, grey, black, 1); + drw->FreeColor(grey); +} + +void TXButtonArray::Draw(TGraphDraw *drw, int x0, int y0, int w, + unsigned long dcolor, unsigned long lcolor, unsigned long tcolor, int insd) +{ + int i; + int x = 0, y = 0, ym = 0; + if (!insd && ins >= 0) k_ins = 2; + for (i = 0; i < nbutton; i++) if (button[i] && button[i]->drw > 0) + { + int xx = x + button[i]->w + delt; + if (x != 0 && xx > w + delt) + { + y += ym + delt; ym = 0; + x = 0; xx = x + button[i]->w + delt; + } + button[i]->Draw(drw, x0 + x, y0 + y, + dcolor, lcolor, tcolor, k_ins == 1 && ins == i); + x = xx; + if (ym < button[i]->h) ym = button[i]->h; + } +} + +int TXButtonArray::ButtonPnt(int xp, int yp, int w, int &n, int kind) +{ + int i; + int x = 0, y = 0, ym = 0; + if (ins < 0 && (kind == 2 || kind == 3)) return INT_MIN; + for (i = 0; i < nbutton; i++) if (button[i] && button[i]->drw > 0) + { + int xx = x + button[i]->w + delt; + if (x != 0 && xx > w + delt) + { + y += ym + delt; ym = 0; + x = 0; xx = x + button[i]->w + delt; + } + if (ins < 0 || i == ins) + { + int wh = button[i]->ButtonPnt(xp - x, yp - y, n, kind); + if (n == -1) n = i; + if (i == ins) + { + if (kind == 1) return wh; + else if (kind == 2) + { + if (wh == INT_MIN || n < 0) + { + if (k_ins != 2) {k_ins = 2; n = -10; return 1000;} + } + else if (k_ins != 1) {k_ins = 1; return 1000;} + return wh; + } + else if (kind == 3) + { + if (wh == INT_MIN) + { + n = -10; + if (k_ins == 1) wh = 1000; + } + k_ins = 0; ins = -1; + return wh; + } + else return wh; + } + else if (wh != INT_MIN) + { + if (kind == 1) {ins = i; k_ins = 1; return wh;} + else if (kind == 2 || kind == 3) return INT_MIN; + else return wh; + } + } + x = xx; + if (ym < button[i]->h) ym = button[i]->h; + } + n = -10; + return INT_MIN; +} + +struct TMultiButton : public TXButton +{ + TMultiButton(int n = -1, int w = 100, int h = 20, int d = 2) + : TXButton(n, w, h), a(d) {} + + virtual void Draw(TGraphDraw *drw, int x0, int y0, unsigned long dcolor, + unsigned long lcolor, unsigned long tcolor, int ins = 0); + virtual int ButtonPnt(int xp, int yp, int &n, int kind = 0); + + void SetDefW(); + + TXButtonArray a; +}; + +void TMultiButton::Draw(TGraphDraw *drw, int x0, int y0, unsigned long dcolor, + unsigned long lcolor, unsigned long tcolor, int ins) +{ + a.Draw(drw, x0, y0, w, dcolor, lcolor, tcolor, ins); +} + +int TMultiButton::ButtonPnt(int xp, int yp, int &n, int kind) +{ + if (a.GetInsert() < 0 && (xp < 0 || yp < 0 || xp > w || yp > h)) return INT_MIN; + return a.ButtonPnt(xp, yp, w, n, kind); +} + +void TMultiButton::SetDefW() +{ + w = a.GetFWidth(); + if (w < 0) w = 0; + h = a.GetHeight(w); +} + +#endif //_HEADER_BUTTONS_H + diff --git a/programs/games/checkers/trunk/checkers.cpp b/programs/games/checkers/trunk/checkers.cpp new file mode 100644 index 0000000000..a197773d6d --- /dev/null +++ b/programs/games/checkers/trunk/checkers.cpp @@ -0,0 +1,1420 @@ +#define BUILD_RUS +#ifndef __MENUET__ +#include +#include +#include +#include +#include +#else +#include +#include +using namespace Menuet; +#define strlen StrLen +#define strcpy StrCopy +#define memcpy MemCopy +#include +const unsigned dectab[] = { 1000000000, 100000000, 10000000, 1000000, 100000, + 10000, 1000, 100, 10, 0 }; +int sprintf( char *Str, char* Format, ... ) +{ + int i, fmtlinesize, j, k, flag; + unsigned head, tail; + char c; + va_list arglist; + // + va_start(arglist, Format); + + // + fmtlinesize = strlen( Format ); + // + if( fmtlinesize == 0 ) return 0; + + // + for( i = 0, j = 0; i < fmtlinesize; i++ ) + { + // + c = Format[i]; + // + if( c != '%' ) + { + Str[j++] = c; + continue; + } + // + i++; + // + if( i >= fmtlinesize ) break; + + // + flag = 0; + // + c = Format[i]; + if (c == 'l') c = Format[++i]; + // + switch( c ) + { + // + case '%': + Str[j++] = c; + break; + // ЃЃЌ„ џђЏЌ‰• + case 's': + char* str; + str = va_arg(arglist, char*); + for( k = 0; ( c = str[k] ) != 0; k++ ) + { + Str[j++] = c; + } + break; + // ЃЃЌ„ џ•‹ЃЌЉћ + case 'c': + Str[j++] = va_arg(arglist, int) & 0xFF; + break; + // ЃЃЌ„ „ЃЌ€ЊЌ–Ќ џЉЌЃћ Ѓ „…џљђ•‚ЊЌ‹ Ѓ•„… + case 'u': + case 'd': + head = va_arg(arglist, unsigned); + for( k = 0; dectab[k] != 0; k++ ) + { + tail = head % dectab[k]; + head /= dectab[k]; + c = head + '0'; + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + // + head = tail; + } + // + c = head + '0'; + Str[j++] = c; + break; + default: + break; + } + } + // + Str[j] = 0; + return j; +} +int isdigit(int c) +{ + return (c>='0' && c<='9'); +} +int atoi(const char* string) +{ + int res=0; + int sign=0; + const char* ptr; + for (ptr=string; *ptr && *ptr<=' ';ptr++); + if (*ptr=='-') {sign=1;++ptr;} + while (*ptr >= '0' && *ptr <= '9') + { + res = res*10 + *ptr++ - '0'; + } + if (sign) res = -res; + return res; +} +int islower(int c) +{ + return (c>='a' && c<='z'); +} +int abs(int n) +{ + return (n<0)?-n:n; +} +int memcmp(const void* buf1, const void* buf2, unsigned count) +{ + const char* ptr1 = (const char*)buf1; + const char* ptr2 = (const char*)buf2; + unsigned i=0; + while (i' +#define XK_minus '-' +#define XK_equal '=' +#define XK_underscore '_' +#define XK_plus '+' +#define XK_Delete 0xB6 +#define XK_F8 0x39 +#define XK_l 'l' +#define XK_L 'L' +#define XK_F2 0x33 +#define XK_s 's' +#define XK_S 'S' +#define XK_slash '/' +#define XK_question '?' +#define XK_n 'n' +#define XK_N 'N' +#define XK_t 't' +#define XK_T 'T' +#define XK_r 'r' +#define XK_R 'R' +#define XK_b 'b' +#define XK_B 'B' +#define XK_f 'f' +#define XK_F 'F' +#define assert(a) /* nothing */ +#include "qsort.c" +#endif +#include "gr-draw.h" +#include "board.h" +#include "player.h" +#include "buttons.h" +#include "sysproc.h" + +char *strskipref(char *s1, char *s2) +{ + int L = strlen(s2); + if (strncmp(s1, s2, L) == 0) return s1 + L; + else return 0; +} + +class TPlayArray +{ +public: + TPlayArray(int d = 10) : play(0), nplay(0), mplay(0) {} + ~TPlayArray() {Clear();} + + void Clear(); + void Add(const PlayWrite &pl); + PlayWrite &operator[](int i) {return play[i];} + int GetNPlay() const {return nplay;} +#ifndef __MENUET__ + int OpenFile(const char *name, int kind); + int MsgOpenFile(const char *name, int kind); + int SaveFile(const char *name, int num, int kind); + int MsgSaveFile(const char *name, int num, int kind); +#endif + void Del(int n); +protected: + void Extend(int n = -1); + + PlayWrite *play; + int nplay, mplay; +protected: +#ifndef __MENUET__ + static const char *const search[]; + static int AnalizeKind(FILE *f, const int w[], const char *smb = 0); + static int ReadFileTo(FILE *f, char c); + static int ReadFileTo(FILE *f, const char *c); + static int ReadTheText(FILE *f, const char *s); +#endif +}; + +#ifndef __MENUET__ +const char *const TPlayArray::search[] = + {"checkers-", "play:", "text", "bin_1.0\n", "history_", "1.0", "1.1"}; +#endif + +void TPlayArray::Clear() +{ + if (play) delete[] play; + play = 0; nplay = 0; mplay = 0; +} + +void TPlayArray::Extend(int n) +{ + if (n < 0) n = nplay + 1; + if (mplay < n) + { + PlayWrite *p_old = play; + int m_old = mplay; + mplay = n * 2; + play = new PlayWrite[mplay]; + if (p_old) + { + for (int i = 0; i < m_old; i++) play[i] = p_old[i]; + delete[] p_old; + } + } +} + +void TPlayArray::Add(const PlayWrite &pl) +{ + Extend(); + play[nplay] = pl; + nplay++; +} + +#ifndef __MENUET__ +int TPlayArray::AnalizeKind(FILE *f, const int w[], const char *smb) +{ + int i, L, was1 = 1; + unsigned char ch; + int fnd[NELEM(search)]; + for (i = 0; i < NELEM(search); i++) fnd[i] = 1; + for (L = 0; was1; L++) + { + was1 = 0; + if (fread(&ch, 1, 1, f) != 1) return (L == 0) ? -2 : -1; + for (i = 0; w[i] >= 0; i++) if (fnd[i]) + { + if (tolower(ch) != tolower(search[w[i]][L])) fnd[i] = 0; + else + { + was1 = 1; + if (search[w[i]][L+1] == 0) + { + if (smb && smb[0] && fread(&ch, 1, 1, f) == 1) + { + ungetc(ch, f); + if (strchr(smb, tolower(ch)) || isalpha(ch) && strchr(smb, toupper(ch))) + { + break; + } + } + return i; + } + } + } + } + return -10 - L; +} + +int TPlayArray::ReadFileTo(FILE *f, char c) +{ + char ch; + do + { + if (fread(&ch, 1, 1, f) != 1) return 0; + } + while(ch != c); + return 1; +} + +int TPlayArray::ReadFileTo(FILE *f, const char *c) +{ + char ch; + do + { + if (fread(&ch, 1, 1, f) != 1) return 0; + } + while(!strchr(c, ch)); + return 1; +} + +int TPlayArray::ReadTheText(FILE *f, const char *s) +{ + char ch; + while (*s) + { + if (fread(&ch, 1, 1, f) != 1 || ch != *s) return 0; + s++; + } + return 1; +} + +int TPlayArray::OpenFile(const char *name, int kind) +{ + int k_fnd = 0; + FILE *f = fopen(name, "rb"); + if (!f) return -1; + if (kind == -1) + { + const int w[] = {0, -1}; + int r = AnalizeKind(f, w); + if (r >= 0) {kind = w[r]; k_fnd = 1;} + else if (r == -11) {kind = 3; k_fnd = 3;} + else {fclose(f); return (kind == -2) ? -2 : -10;} + } + if (kind == 0) + { + if (k_fnd < 1 && !ReadFileTo(f, '-')) {fclose(f); return -10;} + k_fnd = 1; + const int w[] = {1, 4, -1}; + int r = AnalizeKind(f, w); + if (r >= 0) {kind = w[r]; k_fnd = 2;} + else {fclose(f); return -10;} + } + if (kind == 1) + { + if (k_fnd < 2 && !ReadFileTo(f, ':')) {fclose(f); return -10;} + k_fnd = 2; + const int w[] = {2, 3, -1}; + int r = AnalizeKind(f, w); + if (r >= 0) {kind = w[r]; k_fnd = 3;} + else {fclose(f); return -10;} + } + if (kind == 4) + { + if (k_fnd < 2 && !ReadFileTo(f, '_')) {fclose(f); return -10;} + k_fnd = 2; + const int w[] = {5, 6, -1}; + int r = AnalizeKind(f, w, ".1234567890"); + if (r >= 0) {kind = w[r]; k_fnd = 3;} + else {fclose(f); return -10;} + } + if (kind == 5) {kind = 3; k_fnd = 0;} + if (kind == 6) + { + if (!ReadFileTo(f, "\n\r")) {fclose(f); return -4;} + k_fnd = 3; + PlayWrite *pl = 0; + int np = THistory::HRead(f, pl); + if (np > 0 && pl) + { + int i; + Extend(nplay + np); + for (i = 0; i < np; i++) + { + if (pl[i].GetN() >= 3) play[nplay++] = pl[i]; + } + } + if (pl) delete[] pl; + fclose(f); + return 1; + } + if (kind == 2) + { + printf("kind = 2\n"); + unsigned char ch; + do + { + if (fread(&ch, 1, 1, f) != 1) {fclose(f); return -10;} + } + while(!isspace(ch)); + PlayWrite pl; + char word[101]; + int i, kind = 0; + for (;;) + { + do + { + if (fread(&ch, 1, 1, f) != 1) break; + } + while(ch == 0 || isspace(ch)); + if (feof(f)) strcpy(word, "[end]"); + else + { + i = 0; + while(ch != 0 && !isspace(ch)) + { + if (i < 100) word[i++] = ch; + if (fread(&ch, 1, 1, f) != 1) break; + } + word[i] = 0; + } + if (word[0] != '[') + { + if (kind == 1) + { + if (word[0] != '#' && word[0] != '$' && word[0] != '%') + { + Position pos; + pos.Read(word, 1); + pl.Clear(); + pl.Add(0, pos); + kind = 2; + } + } + else if (kind == 2) + { + if (word[0] != '#' && word[0] != '$' && word[0] != '%') + { + for (i = 0; word[i] && word[i] != '.' && word[i] != ','; i++) + { + if (!isdigit((unsigned char)word[i])) {i = -1; break;} + } + if (i == -1) + { + PlayWrite::PMv pmv; + if (pl.GetPosL(pmv.pos) < 0) kind = 3; + else if (!pmv.pos.ReadMv(pmv.mv, word, 1)) kind = 3; + else if (pl.Add(pmv.mv) != 0) kind = 3; + } + } + } + } + else + { + if (kind == 2 || kind == 3) + { + if (pl.GetN() > 0) Add(pl); + pl.Clear(); + } + kind = 0; + for (i = 0; word[i]; i++) + { + word[i] = (char)tolower((unsigned char)word[i]); + } + if (strskipref(word, "[end]")) break; + else if (strskipref(word, "[play_v1.1]")) kind = 1; + } + } + fclose(f); + return 1; + } + if (kind == 3) + { + char ch[LEN_WPOS]; + if (k_fnd < 3 && !ReadFileTo(f, '\n')) {fclose(f); return -10;} + k_fnd = 3; + do + { + PlayWrite pl; + for (;;) + { + int i; + for (i = 0; i < LEN_WPOS; i++) + { + if (fread(ch + i, 1, 1, f) != 1 || ch[i] < 0) break; + } + if (i < LEN_WPOS) break; + PlayWrite::PMv pmv0, pmv1; + pmv1.pos.Read(ch); + pmv1.pos.Reverse(); + if (pl.GetPMvL(pmv0) >= 0) + { + TComputerPlayer::Z z; + z.FindAllMoves(pmv0); + int r; + for (r = 0; r < z.narr; r++) + { + if (memcmp(z.array[r].pos.SH, pmv1.pos.SH, sizeof(pmv1.pos.SH)) == 0) + { + pmv1 = z.array[r]; + break; + } + } + if (r < z.narr) pl.Add(pmv1); + else {fclose(f); return -3;} + } + else pl.Add(0, pmv1.pos); + } + if (pl.GetN() > 0) Add(pl); + } + while(!feof(f)); + fclose(f); + return 1; + } + fclose(f); + return -10; +} + +int TPlayArray::MsgOpenFile(const char *name, int kind) +{ + int n0 = nplay, no_games = 0; + int r = OpenFile(name, kind); + if (r <= 0) + { + if (r == -1) + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ЌҐ ¬®Јг ®вЄалвм д ©« \"%s\".\n", name); +#else + printf("\nCheckers: Can't open the file \"%s\".\n", name); +#endif + return 0; + } + else if (r == -2) + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ” ©« \"%s\" Їгбв.\n", name); +#else + printf("\nCheckers: The file \"%s\" is empty.\n", name); +#endif + return 0; + } + else if (r == -3) + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ” ©« \"%s\" ®иЁЎ®з­л©.\n", name); +#else + printf("\nCheckers: Invalid file \"%s\".\n", name); +#endif + return 0; + } + else if (r == -4) no_games = 1; + else if (r == -10) + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ” ©« \"%s\" Ё¬ҐҐв ­ҐўҐа­л© вЁЇ.\n", name); +#else + printf("\nCheckers: The file \"%s\" has wrong type.\n", name); +#endif + return 0; + } + else + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ЋиЁЎЄ  ®вЄалвЁп д ©«  \"%s\".\n", name); +#else + printf("\nCheckers: Error openning the file \"%s\".\n", name); +#endif + return 0; + } + } + if (!no_games && nplay > n0) return 1; + else + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ” ©« \"%s\" ­Ґ ᮤҐа¦Ёв ЁЈа.\n", name); +#else + printf("\nCheckers: File \"%s\" don't contains games.\n", name); +#endif + return 0; + } +} + +int TPlayArray::SaveFile(const char *name, int num, int kind) +{ + FILE *f = 0; + if (kind == 0 || kind == 1 || kind == 2) + { + f = fopen(name, "wt"); + if (!f) return -1; + fprintf(f, "checkers-play:text\n"); + int i0 = num, i; + if (num < 0) {i0 = 0; num = nplay-1;} + for (i = i0; i <= num; i++) if (play[i].GetN() > 0) + { + PlayWrite::PMv pmv; + if (play[i].GetPos(pmv.pos, 0) < 0) return -9; + char *str = new char[10 + NUM_CELL]; + if (!str) return -5; + pmv.pos.Write(str, 1); + fprintf(f, "\n[Play_v1.1]#%d %s\n", i - i0 + 1, str); + delete[] str; + int j; + for (j = 1; j < play[i].GetN(); j++) + { + if (play[i].GetPos(pmv.pos, j - 1) < 0) return -9; + if (play[i].GetMove(pmv.mv, j) < 0) return -9; + str = new char[pmv.pos.GetLenMvEx(pmv.mv, 11)]; + if (!str) return -5; + pmv.pos.WriteMvEx(pmv.mv, str, 11); + if (j % 2 == 1) + { + int nbytes = fprintf(f, "%d. ", (j + 1) / 2); + while(nbytes++ < 5) fprintf(f, " "); + } + fprintf(f, "%s", str); + if (j % 2 == 0 || j == play[i].GetN() - 1) fprintf(f, "\n"); + else fprintf(f, " ,\t"); + delete[] str; + } + } + fclose(f); + return 1; + } + else if (kind == -1 || kind == 3) + { + f = fopen(name, "wb"); + if (!f) return -1; + if (kind == 3) fprintf(f, "checkers-play:bin_1.0\n"); + int i = num; + if (num < 0) {i = 0; num = nplay-1;} + for (; i <= num; i++) + { + char ch[LEN_WPOS]; + Position pos; + play[i].GetPosL(pos); + if (!pos.AllCanEat() && !pos.AllCanMove()) + { + ch[0] = (pos.wmove == 0) ? char(-3) : char(-1); + } + else ch[0] = char(-2); + fwrite(ch, 1, 1, f); + int j; + for (j = 0; j < play[i].GetN(); j++) + { + Position pos; + play[i].GetPos(pos, j); + pos.Reverse(); + pos.Write(ch); + fwrite(ch, LEN_WPOS, 1, f); + } + } + fclose(f); + return 1; + } + if (f) fclose(f); + return -10; +} + +int TPlayArray::MsgSaveFile(const char *name, int num, int kind) +{ + int r = SaveFile(name, num, kind); + if (r <= 0) + { + if (r == -1) + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ЌҐ ¬®Јг ®вЄалвм д ©« \"%s\" ­  § ЇЁбм.\n", name); +#else + printf("\nCheckers: Can't open the file \"%s\" to write.\n", name); +#endif + } + else if (r == -5) + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ЌҐ ¤®бв в®з­® Ї ¬пвЁ ¤«п б®еа ­Ґ­Ёп д ©«  \"%s\".\n", name); +#else + printf("\nCheckers: Not enough memory to save the file \"%s\".\n", name); +#endif + } + else if (r == -10) + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ” ©« \"%s\" Ё¬ҐҐв ­ҐўҐа­л© вЁЇ.\n", name); +#else + printf("\nCheckers: The file \"%s\" has wrong type.\n", name); +#endif + } + else + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ЋиЁЎЄ  б®еа ­Ґ­Ёп д ©«  \"%s\".\n", name); +#else + printf("\nCheckers: Error saving the file \"%s\".\n", name); +#endif + } + return 0; + } + else + { +#ifdef BUILD_RUS + printf("\n иЄЁ: ” ©« \"%s\" б®еа ­с­.\n", name); +#else + printf("\nCheckers: File \"%s\" saved.\n", name); +#endif + return 1; + } +} +#endif + +void TPlayArray::Del(int n) +{ + if (!play || n < 0 || n >= nplay) return; + else if (nplay <= 1) {Clear(); return;} + int i; + for (i = n; i < nplay - 1; i++) play[i] = play[i+1]; + play[nplay - 1].Clear(); + nplay--; +} + + +void SetPlayerString(char *str, int c, TChPlayer *p) +{ + strcpy(str, c ? "blue: " : "red: "); + if (!p) strcat(str, "input"); + else strcat(str, "computer"); +} + +class TMainDraw : public TSomeDraw +{ +public: + TMainDraw() : undo_redo(0), ur_type(-1), cur_play(0), + def_savefile("save.che"), def_savekind(2) {InitButton();} + + virtual void Draw(TGraphDraw *drw, int w, int h) + { + int d = button.GetDelt(); + int hh = button.GetHeight(w - 2*d); + if (hh != 0) hh += d; + drw->SetColor(drw->GetBlackColor()); + button.Draw(drw, d, h - hh, w - 2*d); + } + + virtual void DrawB(TGraphDraw *drw, TChBoard &board) + { + int urt = (board.GetCurMoveN() <= 0) + + 2*(board.GetCurMoveN() >= board.GetNumMove()); + if (ur_type != urt) SetButtonKind(board); + Draw(drw, board.GetW(), board.GetH()); + } + + virtual TIntPoint GetDSize(int w, int h) + { + int d = button.GetDelt(); + int hh = button.GetHeight(w - 2*d); + if (hh != 0) hh += d; + return TIntPoint(0, hh); + } + + virtual int ButtonPnt(int xp, int yp, int w, int h, int &n, int k = 0) + { + int d = button.GetDelt(); + int hh = button.GetHeight(w - 2*d); + if (hh != 0) hh += d; + return button.ButtonPnt(xp - d, yp - (h - hh), w - 2*d, n, k); + } + + void InitButton(); + void SetButtonKind(const TChBoard &board); + void PressUR(int n, TChBoard &board, TGraphDraw *drw); + void PressLS(int n, TChBoard &board, TGraphDraw *drw); + void CurPlayNorm() + { + if (cur_play < 0 || cur_play >= play.GetNPlay()) cur_play = 0; + } + + TXButtonArray button; + TMultiButton *undo_redo, *play_list; + char player_str[2][50], play_num[2][10]; + TPlayArray play; + int cur_play; + char *def_savefile; + int def_savekind; +protected: + int ur_type; +}; + +void TMainDraw::InitButton() +{ + button.Add(1, 80, 22, "new game"); + button.Add(6, 60, 22, "list"); + button.Add(7, 60, 22, "delete"); + play_list = new TMultiButton(20); + play_list->a.Add(26, 20, 22, "1"); + play_list->a.Add(21, 20, 22, "-"); + play_list->a.Add(23, 37, 22, play_num[0], -2); + play_list->a.Add(22, 20, 22, "+"); + play_list->a.Add(27, 37, 22, play_num[1]); + play_list->SetDefW(); + button.Add(play_list); + button.Add(24, 50, 22, "clear"); +#ifndef __MENUET__ + button.Add(25, 50, 22, "save"); +#endif + button.Add(2, 120, 22, player_str[0]); + button.Add(3, 120, 22, player_str[1]); + button.Add(4, 110, 22, "rotate board"); + undo_redo = new TMultiButton(10); + undo_redo->a.Add(11, 27, 22, "<<"); + undo_redo->a.Add(12, 20, 22, "<"); + undo_redo->a.Add(15, 20, 22, "^"); + undo_redo->a.Add(13, 20, 22, ">"); + undo_redo->a.Add(14, 27, 22, ">>"); + undo_redo->SetDefW(); + button.Add(undo_redo); + button.Add(5, 60, 22, "exit"); +} + +void TMainDraw::SetButtonKind(const TChBoard &board) +{ + int thick; + TextButton *txb; + TXButton *bt1; + ur_type = 0; + SetPlayerString(player_str[0], 0, board.GetPlayer(0)); + SetPlayerString(player_str[1], 1, board.GetPlayer(1)); + int is_drw = !board.GetPViewStatus(); + bt1 = button.GetButton(2); + if (bt1) bt1->drw = is_drw; + bt1 = button.GetButton(3); + if (bt1) bt1->drw = is_drw; + if (board.GetCurMoveN() <= 0) {ur_type++; thick = 0;} + else thick = 3; +// txb = dynamic_cast(undo_redo->a.GetButton(11)); +// if (txb) txb->thick = thick; +// txb = dynamic_cast(undo_redo->a.GetButton(12)); +// if (txb) txb->thick = thick; +// we can use simple static cast + ((TextButton*)(undo_redo->a.GetButton(11)))->thick = thick; + ((TextButton*)(undo_redo->a.GetButton(12)))->thick = thick; + if (board.GetCurMoveN() >= board.GetNumMove()) {ur_type += 2; thick = 0;} + else thick = 3; +// txb = dynamic_cast(undo_redo->a.GetButton(13)); +// if (txb) txb->thick = thick; +// txb = dynamic_cast(undo_redo->a.GetButton(14)); +// if (txb) txb->thick = thick; + ((TextButton*)(undo_redo->a.GetButton(13)))->thick = thick; + ((TextButton*)(undo_redo->a.GetButton(14)))->thick = thick; + if (board.GetCurMoveN() < board.GetNumMove() || + (board.GetPViewStatus() && board.GetGameEnd() <= 0)) + { + thick = 3; + } + else thick = 0; +// txb = dynamic_cast(undo_redo->a.GetButton(15)); +// if (txb) txb->thick = thick; + ((TextButton*)(undo_redo->a.GetButton(15)))->thick = thick; + if (play.GetNPlay() == 0) is_drw = 1; + bt1 = button.GetButton(6); + if (bt1) bt1->drw = is_drw; + bt1 = button.GetButton(7); + if (bt1) bt1->drw = !is_drw; +#ifndef __MENUET__ + bt1 = button.GetButton(25); + if (bt1) bt1->drw = !is_drw; +#endif + is_drw = board.GetPViewStatus() && play.GetNPlay() > 1; + bt1 = button.GetButton(20); + if (bt1) bt1->drw = is_drw; + bt1 = button.GetButton(24); + if (bt1) bt1->drw = is_drw; + if (is_drw) + { + play_num[0][0] = 0; play_num[1][0] = 0; + if (cur_play >= 0) sprintf(play_num[0], "%d", cur_play + 1); + sprintf(play_num[1], "%d", play.GetNPlay()); + thick = (cur_play <= 0) ? 0 : 3; +#define dynamic_cast static_cast + txb = dynamic_cast(play_list->a.GetButton(21)); + if (txb) txb->thick = thick; + txb = dynamic_cast(play_list->a.GetButton(26)); + if (txb) txb->thick = thick; + thick = (cur_play >= play.GetNPlay() - 1) ? 0 : 3; + txb = dynamic_cast(play_list->a.GetButton(22)); + if (txb) txb->thick = thick; + txb = dynamic_cast(play_list->a.GetButton(27)); + if (txb) txb->thick = thick; +#undef dynamic_cast + } +} + +void TMainDraw::PressUR(int n, TChBoard &board, TGraphDraw *drw) +{ + int mv; + if (n == 11) mv = 0; + else if (n == 12) mv = board.GetCurMoveN() - 1; + else if (n == 13) mv = board.GetCurMoveN() + 1; + else mv = board.GetNumMove(); + if (board.SetCurMoveN(mv)) + { + SetButtonKind(board); + if (drw && drw->IsDraw()) + { + drw->DrawClear(); + board.Draw(drw); + } + } + else Draw(drw, board.GetW(), board.GetH()); +} + +void TMainDraw::PressLS(int n, TChBoard &board, TGraphDraw *drw) +{ + int need_redraw = 0; + if (n == 6) + { + if (!board.GetPViewStatus() || play.GetNPlay() == 0) + { + PlayWrite cur_pw = board.GetPlay(); + if (cur_pw.GetN() > 2 || play.GetNPlay() == 0) play.Add(board.GetPlay()); + cur_play = play.GetNPlay() - 1; + board.SetPlay(play[cur_play]); + need_redraw = 1; + } + } + else if (n == 7) + { + if (board.GetPViewStatus() && play.GetNPlay() != 0) + { + play.Del(cur_play); + if (play.GetNPlay() >= 1) + { + if (cur_play >= play.GetNPlay()) cur_play--; + board.SetPlay(play[cur_play]); + } + need_redraw = 1; + } + } + else if (n == 21) + { + if (cur_play > 0) {board.SetPlay(play[--cur_play]); need_redraw = 1;} + } + else if (n == 22) + { + if (cur_play < play.GetNPlay() - 1) + { + board.SetPlay(play[++cur_play]); need_redraw = 1; + } + } + else if (n == 26) + { + if (cur_play > 0) + { + cur_play = 0; + board.SetPlay(play[cur_play]); need_redraw = 1; + } + } + else if (n == 27) + { + if (cur_play < play.GetNPlay() - 1) + { + cur_play = play.GetNPlay() - 1; + board.SetPlay(play[cur_play]); need_redraw = 1; + } + } + else if (n == 24) {play.Clear(); cur_play = 0; need_redraw = 1;} +#ifndef __MENUET__ + else if (n == 25) + { + if (play.GetNPlay() > 0) play.MsgSaveFile(def_savefile, -1, def_savekind); + } + else if (n == 28) + { + if (play.GetNPlay() > 0) play.MsgSaveFile(def_savefile, cur_play, def_savekind); + } +#endif + if (need_redraw) + { + SetButtonKind(board); + if (drw && drw->IsDraw()) + { + drw->DrawClear(); + board.Draw(drw); + } + } + else Draw(drw, board.GetW(), board.GetH()); +} + +struct TTimerDraw +{ + TTimerDraw(TChBoard *brd, TGraphDraw *drw) : brd(brd), drw(drw) {} + + TChBoard *brd; + clock_t st, ut, dt; + double x0; + TGraphDraw *drw; + + static void draw(void *v, int k = 0); +}; + +void TTimerDraw::draw(void *v, int k) +{ + TTimerDraw &d = *(TTimerDraw*)v; + clock_t t = clock(); + if (k == 0 && t - d.ut < CLOCKS_PER_SEC * 0.01) return; + if (k > 0) + { + d.st = t; + if (!d.drw || !d.drw->IsDraw()) return; + d.drw->DrawClear(); + d.brd->Draw(d.drw); + d.dt = t; + } + else if (!d.drw || !d.drw->IsDraw()) return; + double xold = d.x0; + if (k >= 0) + { + d.x0 = (1 - cos(2.0 * (t - d.st) / CLOCKS_PER_SEC)) / 2; + d.brd->DrawTimer(d.drw, d.x0, 0); + d.ut = t; + if (k == 0 && t - d.dt > CLOCKS_PER_SEC * 0.5) + { + d.brd->Draw(d.drw); + d.dt = t; + } + } + if (k <= 0) d.brd->DrawTimer(d.drw, xold, 1); +} + + +struct TMainData +{ + TChBoard board; + TComputerPlayer player; + TMainDraw main_draw; + + TMainData(int id = 0); + void InitDef(); + static int EventFunction(const TGraphDraw::event &ev); + void NewGame(TGraphDraw *drw); + void RotateBoard(TGraphDraw *drw); + void PlayerPress(int np, TGraphDraw *drw); + void GoToCurMove(TGraphDraw *drw); +}; + +TMainData::TMainData(int id) : board(id) +{ + board.SetCheckResize(1); + board.SetPlayer(1, &player); + board.SetBottomColor(0); + board.SetSomeDraw(&main_draw); + board.SetMinWSize(90, 140); +} + +void TMainData::InitDef() +{ + if (main_draw.play.GetNPlay() > 0) + { + main_draw.CurPlayNorm(); + board.SetPlay(main_draw.play[main_draw.cur_play]); + } + main_draw.SetButtonKind(board); +} + +void TMainData::NewGame(TGraphDraw *drw) +{ + board.NewGame(); + main_draw.SetButtonKind(board); + if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);} +} + +void TMainData::RotateBoard(TGraphDraw *drw) +{ + board.SetBottomColor(3 - board.GetBottomColor()); + if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);} +} + +void TMainData::PlayerPress(int np, TGraphDraw *drw) +{ + if (np != 0 && np != 1) return; + if (board.GetPlayer(np)) board.SetPlayer(np, 0); + else board.SetPlayer(np, &player); + if (board.GetPlayer(0) && !board.GetPlayer(1)) + { + board.SetBottomColor(1); + } + if (board.GetPlayer(1) && !board.GetPlayer(0)) + { + board.SetBottomColor(0); + } + main_draw.SetButtonKind(board); + if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);} +} + +void TMainData::GoToCurMove(TGraphDraw *drw) +{ + board.GoToCurMove(); + main_draw.SetButtonKind(board); + if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);} +} + +int TMainData::EventFunction(const TGraphDraw::event &ev) +{ + if (!ev.any.drw->data) return -100; + TMainData &data = *(TMainData*)ev.any.drw->data; + int nbutton, ret = 0; + switch(ev.type) + { + case TGraphDraw::event::button_down: + if (ev.button.n != 1) break; + ev.button.drw->OpenDraw(); + if (data.main_draw.ButtonPnt(ev.button.x, ev.button.y, + data.board.GetW(), data.board.GetH(), nbutton, 1) > 0) + { + data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH()); + ret |= TGraphDraw::ret_setcapture; + } + else data.board.MouseClick(ev.button.drw, ev.button.x, ev.button.y); + ev.button.drw->CloseDraw(); + break; + case TGraphDraw::event::mouse_move: + if (ev.button.n >= 0 && ev.button.n != 1) break; + ev.button.drw->OpenDraw(); + if (data.main_draw.ButtonPnt(ev.button.x, ev.button.y, + data.board.GetW(), data.board.GetH(), nbutton, 2) >= 1000) + { + data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH()); + } + ev.button.drw->CloseDraw(); + break; + case TGraphDraw::event::button_up: + if (ev.button.n != 1) break; + ev.button.drw->OpenDraw(); + if (data.main_draw.ButtonPnt(ev.button.x, ev.button.y, + data.board.GetW(), data.board.GetH(), nbutton, 3) > 0) + { + switch(nbutton) + { + case 1: + data.NewGame(ev.button.drw); + break; + case 2: + case 3: + data.PlayerPress(nbutton - 2, ev.button.drw); + break; + case 4: + data.RotateBoard(ev.button.drw); + break; + case 5: + data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH()); + ev.button.drw->Quit(); + break; + case 11: + case 12: + case 13: + case 14: + data.main_draw.PressUR(nbutton, data.board, ev.button.drw); + break; + case 15: + data.GoToCurMove(ev.button.drw); + break; + case 6: + case 7: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + data.main_draw.PressLS(nbutton, data.board, ev.button.drw); + break; + default: + data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH()); + break; + } + } + ev.button.drw->CloseDraw(); + break; + case TGraphDraw::event::draw: + ev.button.drw->OpenDraw(); + data.board.Draw(ev.button.drw); + ev.button.drw->CloseDraw(); + break; + case TGraphDraw::event::key_down: + ev.button.drw->OpenDraw(); + if (ev.key.k == XK_Left) data.board.PKeyEvent(ev.button.drw, TChBoard::PLeft); + else if (ev.key.k == XK_Right) data.board.PKeyEvent(ev.button.drw, TChBoard::PRight); + else if (ev.key.k == XK_Up) data.board.PKeyEvent(ev.button.drw, TChBoard::PUp); + else if (ev.key.k == XK_Down) data.board.PKeyEvent(ev.button.drw, TChBoard::PDown); + else if (ev.key.k == XK_Return || ev.key.k == XK_space) + { + data.board.PKeyEvent(ev.button.drw, TChBoard::PEnter); + } + else if (ev.key.k == XK_Escape) ev.button.drw->Quit(); + else if (ev.key.k == XK_less) data.main_draw.PressUR(11, data.board, ev.button.drw); + else if (ev.key.k == XK_comma) data.main_draw.PressUR(12, data.board, ev.button.drw); + else if (ev.key.k == XK_period) data.main_draw.PressUR(13, data.board, ev.button.drw); + else if (ev.key.k == XK_greater) data.main_draw.PressUR(14, data.board, ev.button.drw); + else if (ev.key.k == XK_minus) data.main_draw.PressLS(21, data.board, ev.button.drw); + else if (ev.key.k == XK_equal) data.main_draw.PressLS(22, data.board, ev.button.drw); + else if (ev.key.k == XK_underscore) data.main_draw.PressLS(26, data.board, ev.button.drw); + else if (ev.key.k == XK_plus) data.main_draw.PressLS(27, data.board, ev.button.drw); + else if (ev.key.k == XK_Delete) data.main_draw.PressLS(7, data.board, ev.button.drw); + else if (ev.key.k == XK_F8) data.main_draw.PressLS(24, data.board, ev.button.drw); + else if (ev.key.k == XK_l || ev.key.k == XK_L) data.main_draw.PressLS(6, data.board, ev.button.drw); +#ifndef __MENUET__ + else if (ev.key.k == XK_F2) data.main_draw.PressLS(25, data.board, ev.button.drw); +#endif + else if (ev.key.k == XK_s || ev.key.k == XK_S) data.main_draw.PressLS(28, data.board, ev.button.drw); + else if (ev.key.k == XK_slash || ev.key.k == XK_question) data.GoToCurMove(ev.button.drw); + else if (ev.key.k == XK_n || ev.key.k == XK_N) data.NewGame(ev.button.drw); + else if (ev.key.k == XK_t || ev.key.k == XK_T) data.RotateBoard(ev.button.drw); + else if (ev.key.k == XK_r || ev.key.k == XK_R) data.PlayerPress(0, ev.button.drw); + else if (ev.key.k == XK_b || ev.key.k == XK_B) data.PlayerPress(1, ev.button.drw); + else if (ev.key.k == XK_f || ev.key.k == XK_F) + { + int w, h; + ev.button.drw->GetSize(w, h); + ev.button.drw->CloseDraw(); + if (DuplicateProcess() == 0) + { + ev.button.drw->ResReinit(w, h); + data.board.EraseHistory(); + } + } + ev.button.drw->CloseDraw(); + break; + case TGraphDraw::event::close: + ret = 1; + break; + } + return ret; +} + +#ifndef __MENUET__ +int main(int argc, char **argv) +{ + randomize(); + THistory::InitHFile(argv[0]); + TMainData data(-1); + if (argv && argc >= 2) + { + int i, kx = 1; + for (i = 1; i < argc; i++) + { + if (kx == 1 && argv[i][0] == '-') + { + if (strcmp(argv[i], "--") == 0) kx = 0; + else if (strcmp(argv[i], "-ssf") == 0) ssf = 1; + else if (strncmp(argv[i], "-save", 5) == 0) + { + int j = 5; + if (argv[i][j]) + { + if (argv[i][j] != '=' || !argv[i][j+1]) + { + data.main_draw.def_savekind = atoi(argv[i] + j); + while (argv[i][j] && argv[i][j] != '=') j++; + if (argv[i][j] != '=' || !argv[i][j+1]) continue; + } + data.main_draw.def_savefile = argv[i] + j + 1; + } + } + else printf("Checkers: Invalid key %s\n", argv[i]); + } + else if (kx == 0 || kx == 1) + { + data.main_draw.play.MsgOpenFile(argv[i], -1); + } + } + } + data.InitDef(); + TMainGraphDraw graph( +#ifdef BUILD_RUS + " иЄЁ" +#else + "Checkers" +#endif + ); + TTimerDraw timer_draw(&data.board, &graph); + data.player.draw = TTimerDraw::draw; data.player.data = &timer_draw; + graph.evfunc = TMainData::EventFunction; graph.data = &data; + graph.SetAboutInfo(1); + graph.Run(TGraphDraw::button_down_mask | TGraphDraw::button_up_mask | + TGraphDraw::key_down_mask | TGraphDraw::mouse_drag_mask, + 450 + 100 * ssf, 528); + return 0; +} +#else + +TMainData* mdata; +TMainGraphDraw* graph; + +bool MenuetOnStart(TStartData &me_start, TThreadData) +{ + mdata = new TMainData(-1); + graph = new TMainGraphDraw; + randomize(); + mdata->InitDef(); + static TTimerDraw timer_draw(&mdata->board, graph); + mdata->player.draw = TTimerDraw::draw; mdata->player.data = &timer_draw; + graph->data = mdata; + me_start.WinData.Title = +#ifdef BUILD_RUS + " иЄЁ" +#else + "Checkers" +#endif + ; + me_start.Width = 450 + 100*ssf; + me_start.Height = 528; + return true; +} +bool MenuetOnClose(TThreadData) +{ + delete mdata; + delete graph; + return true; +} +int MenuetOnIdle(TThreadData) +{return -1;} +void MenuetOnSize(int window_rect[], TThreadData) +{mdata->board.Resize(window_rect[2]-window_rect[0], window_rect[3]-window_rect[1]);} +void MenuetOnKeyPress(TThreadData) +{ + TGraphDraw::event ev; + ev.type = TGraphDraw::event::key_down; + ev.any.drw = graph; + ev.key.k = GetKey(); + mdata->EventFunction(ev); +} +void MenuetOnDraw(void) +{ + TGraphDraw::event ev; + ev.type = TGraphDraw::event::draw; + ev.any.drw = graph; + mdata->EventFunction(ev); +} +void MenuetOnMouse(TThreadData) +{ + short x,y; + GetMousePosition(x,y); + int m = GetMouseButton() & 1; + static int mprev = 0; + if (m == mprev) + return; + mprev = m; + TGraphDraw::event ev; + ev.type = m ? TGraphDraw::event::button_down : TGraphDraw::event::button_up; + ev.any.drw = graph; + ev.button.n = 1; + ev.button.x = x; + ev.button.y = y; + mdata->EventFunction(ev); +} +#endif diff --git a/programs/games/checkers/trunk/compile.txt b/programs/games/checkers/trunk/compile.txt new file mode 100644 index 0000000000..43175c8c18 --- /dev/null +++ b/programs/games/checkers/trunk/compile.txt @@ -0,0 +1,21 @@ +1. Компиляция под Колибри. +Для компиляции необходим Borland C++ (из всего пакета нужен только компилятор +командной строки), а также FASM версии не более 1.64. +cpp2asm.bat компилирует С++-исходник в TASM-исходник, + а потом превращает его в FASM-исходник. +После этого, возможно, понадобится перенести в f_checkers.asm строки с equ + в начало файла. +Компиляция бинарника - как обычно, fasm f_checkers.asm checkers. + +2. Компиляция под Linux. +Просто скажите make. По крайней мере в одной Linux-системе это работает. +В других могут понадобиться некоторые изменения. +В исходниках русские буквы записаны в кодировке DOS (cp866). Так что для +вразумительных сообщений либо закомментируйте первую строку в checkers.cpp +("#define BUILD_RUS"), либо прогоните все *.cpp и *.h файлы через dos2unix. + +3. Компиляция под DOS/Windows. +Для компиляции необходим пакет Borland C++ for DOS/Windows соответственно. +Компиляция стандартна для Borland C++, в проект должен входить основной файл +checkers.cpp и для Windows также файл ресурсов win-chk.rc; +для DOS должен быть прилинкован egavga.bgi. diff --git a/programs/games/checkers/trunk/cpp2asm.bat b/programs/games/checkers/trunk/cpp2asm.bat new file mode 100644 index 0000000000..279fe4a332 --- /dev/null +++ b/programs/games/checkers/trunk/cpp2asm.bat @@ -0,0 +1,3 @@ +bcc32 -S -v- -R- -6 -a4 -O2 -Og -Oi -Ov -OS -k- -x- -D__MENUET__ -Iinclude checkers.cpp +echo include "me_make.inc" > f_checkers.asm +t2fasm < checkers.asm >> f_checkers.asm \ No newline at end of file diff --git a/programs/games/checkers/trunk/dos-draw.h b/programs/games/checkers/trunk/dos-draw.h new file mode 100644 index 0000000000..b1d530f51b --- /dev/null +++ b/programs/games/checkers/trunk/dos-draw.h @@ -0,0 +1,381 @@ +#include "gr-draw.h" + +#ifndef _DOS_GRAPHIC_DRAW_H +#define _DOS_GRAPHIC_DRAW_H + +#include "dosmouse.h" +#include "keysym.h" +#include +#include +#include +#include + +class TDosGraphDraw : public TGraphDraw +{ +public: + TDosGraphDraw(const char *s = 0); + ~TDosGraphDraw() {} +public: + static unsigned long GetKeySym(unsigned int key); +protected: + unsigned long bgcolor; + int quit; + TCursorVisible cursor; +public: + unsigned long GetBlackColor() {return 0;} + unsigned long GetWhiteColor() {return 15;} + unsigned long CreateColor(unsigned short red, + unsigned short green, unsigned short blue); + void FreeColor(unsigned long c) {} + unsigned long GetBgColor() {return bgcolor;} + void SetBgColor(unsigned long c) {bgcolor = c;} + + int GetStatus() {return (graphresult() == grOk) ? 1 : 0;} + int Init() {return 0;} + int Run(int evmask = 0, int w = INT_MIN, int h = INT_MIN); + + void GetSize(int &w, int &h); + int OpenDraw(); + int IsDraw() {return graphresult() == grOk && cursor.IsHidden();} + void CloseDraw() {cursor.Show();} + + int SetColor(unsigned long c); + int DrawLine(int x0, int y0, int x1, int y1); + int DrawText(int x0, int y0, char *text); + int DrawClear(); + int GetTextH(const char *s) {return 8;} + int GetTextW(const char *s) {return 8 * sizeof(s);} + void Quit(int q = 1) {quit = (q > 0) ? q : 0;} +}; + +unsigned long TDosGraphDraw::GetKeySym(unsigned int key) +{ + switch(key) + { + case 331: return XK_Left; + case 333: return XK_Right; + case 328: return XK_Up; + case 336: return XK_Down; + case 13: return XK_Return; + case 32: return XK_space; + case 27: return XK_Escape; + case 44: return XK_comma; + case 46: return XK_period; + case 60: return XK_comma; + case 62: return XK_period; + case 45: return XK_minus; + case 61: return XK_equal; + case 95: return XK_underscore; + case 43: return XK_plus; + case 339: return XK_Delete; + case 47: return XK_slash; + case 63: return XK_question; + case 315: return XK_F1; + case 316: return XK_F2; + case 317: return XK_F3; + case 318: return XK_F4; + case 319: return XK_F5; + case 320: return XK_F6; + case 321: return XK_F7; + case 322: return XK_F8; + case 323: return XK_F9; + case 324: return XK_F10; + case 389: return XK_F11; + case 390: return XK_F12; + case 97: return XK_a; + case 98: return XK_b; + case 99: return XK_c; + case 100: return XK_d; + case 101: return XK_e; + case 102: return XK_f; + case 103: return XK_g; + case 104: return XK_h; + case 105: return XK_i; + case 106: return XK_j; + case 107: return XK_k; + case 108: return XK_l; + case 109: return XK_m; + case 110: return XK_n; + case 111: return XK_o; + case 112: return XK_p; + case 113: return XK_q; + case 114: return XK_r; + case 115: return XK_s; + case 116: return XK_t; + case 117: return XK_u; + case 118: return XK_v; + case 119: return XK_w; + case 120: return XK_x; + case 121: return XK_y; + case 122: return XK_z; + case 65: return XK_A; + case 66: return XK_B; + case 67: return XK_C; + case 68: return XK_D; + case 69: return XK_E; + case 70: return XK_F; + case 71: return XK_G; + case 72: return XK_H; + case 73: return XK_I; + case 74: return XK_J; + case 75: return XK_K; + case 76: return XK_L; + case 77: return XK_M; + case 78: return XK_N; + case 79: return XK_O; + case 80: return XK_P; + case 81: return XK_Q; + case 82: return XK_R; + case 83: return XK_S; + case 84: return XK_T; + case 85: return XK_U; + case 86: return XK_V; + case 87: return XK_W; + case 88: return XK_X; + case 89: return XK_Y; + case 90: return XK_Z; + default: return XK_VoidSymbol; + } +} + +TDosGraphDraw::TDosGraphDraw(const char *s) : TGraphDraw(s) +{ + bgcolor = GetWhiteColor(); +} + +unsigned long TDosGraphDraw::CreateColor(unsigned short red, + unsigned short green, unsigned short blue) +{ + const unsigned short PD = 12288U, PM = 36863U, PL = 65535U; + const unsigned short COLOR[16][3] = + {{0U, 0U, 0U}, {0U, 0U, PM}, {0U, PM, 0U}, {0U, PM, PM}, + {PM, 0U, 0U}, {PM, 0U, PM}, {PM, PM, 0U}, {PM, PM, PM}, + {PD, PD, PD}, {PD, PD, PL}, {PD, PL, PD}, {PD, PL, PL}, + {PL, PD, PD}, {PL, PD, PL}, {PL, PL, PD}, {PL, PL, PL}}; + int b[3]; + if (red > green) + { + if (green > blue) {b[0] = 4; b[1] = 2; b[2] = 1;} + else if (red > blue) {b[0] = 4; b[1] = 1; b[2] = 2;} + else {b[0] = 1; b[1] = 4; b[2] = 2;} + } + else + { + if (red > blue) {b[0] = 2; b[1] = 4; b[2] = 1;} + else if (green > blue) {b[0] = 2; b[1] = 1; b[2] = 4;} + else {b[0] = 1; b[1] = 2; b[2] = 4;} + } + int i, j, c, c0 = 0; + long d, d0 = LONG_MAX; + for (j = 0; j <= 8; j += 8) for (i = 0, c = j; i <= 3; c |= b[i++]) + { + d = labs((long)red - COLOR[c][0]) + labs((long)green - COLOR[c][1]) + + labs((long)blue - COLOR[c][2]); + if (d0 >= d) {d0 = d; c0 = c;} + } + return c0; +} + +void TDosGraphDraw::GetSize(int &w, int &h) +{ + if (graphresult() == grOk) + { + w = getmaxx() + 1; h = getmaxy() + 1; + } + else TGraphDraw::GetSize(w, h); +} + +int TDosGraphDraw::OpenDraw() +{ + if (graphresult() == grOk) + { + cursor.Hide(); + return 1; + } + else return 0; +} + +int TDosGraphDraw::SetColor(unsigned long c) +{ + if (!IsDraw()) return 0; + else {setcolor((int)c); return 1;} +} + +int TDosGraphDraw::DrawLine(int x0, int y0, int x1, int y1) +{ + if (!IsDraw()) return 0; + else {line(x0, y0, x1, y1); return 1;} +} + +int TDosGraphDraw::DrawText(int x0, int y0, char *text) +{ + if (!IsDraw()) return 0; + else {outtextxy(x0, y0, text); return 1;} +} + +int TDosGraphDraw::DrawClear() +{ + if (!IsDraw()) return 0; + setbkcolor((int)bgcolor); setcolor((int)bgcolor); + bar(0, 0, getmaxx(), getmaxy()); + setbkcolor(0); + return 1; +} + +int TDosGraphDraw::Run(int evmask, int /*w*/, int /*h*/) +{ + if (!evfunc) return -2; + int wasgraph = graphresult(); + if (!wasgraph) + { + int gdriver = DETECT, gmode, errorcode; + initgraph(&gdriver, &gmode, ""); + if ((errorcode = graphresult()) != grOk) + { + printf("Graphics error: %s\n", grapherrormsg(errorcode)); + return -1; + } + } + event ev; + int ch = INT_MIN, stpr = 0; + int old_mx = -1000, old_my = -1000; + clock_t old_mtime = clock(); + int show_cur = TCursorVisible::C.IsShowed(); + freopen("NUL", "wt", stdout); + quit = 0; + while (quit == 0) + { + if (stpr == 0) + { + ev.type = event::start; + ev.any.drw = this; + evfunc(ev); + CloseDraw(); + stpr = 1; + } + else if (stpr == 1) + { + ev.type = event::draw; + ev.any.drw = this; + evfunc(ev); + CloseDraw(); + stpr = 2; + } + else if (ch >= 0 && (evmask & key_down_mask)) + { + ev.type = event::key_up; + ev.key.drw = this; + ev.key.k = ch; + evfunc(ev); + CloseDraw(); + ch = INT_MIN; + } + else if (kbhit()) + { + if (MouseStatus && TCursorVisible::C.IsShowed() && + (unsigned long)(clock() - old_mtime) > 5 * CLK_TCK) + { + TCursorVisible::C.Hide(); + old_mtime = clock(); + } + int ch = (unsigned char)getch(); + if (!ch && kbhit()) ch = 0x100 | (unsigned char)getch(); + if (evmask & key_down_mask) + { + ev.type = event::key_down; + ev.key.drw = this; + ev.key.k = GetKeySym(ch); + evfunc(ev); + CloseDraw(); + } + } + else if (MouseStatus && (evmask & (button_down_mask | + button_up_mask | mouse_move_mask | mouse_drag_mask))) + { + int k, x, y, z; + for (k = 0; k < MouseStatus; k++) + { + z = GetButtonDown(k, x, y); + if (z) + { + TCursorVisible::C.Show(); + old_mx = x; old_my = y; + old_mtime = clock(); + if (evmask & button_down_mask) + { + ev.type = event::button_down; + ev.button.drw = this; + ev.button.x = x; ev.button.y = y; + ev.button.n = k + 1; + evfunc(ev); + CloseDraw(); + } + old_mtime = clock(); + k = -1; break; + } + z = GetButtonUp(k, x, y); + if (z) + { + TCursorVisible::C.Show(); + old_mx = x; old_my = y; + old_mtime = clock(); + if (evmask & button_up_mask) + { + ev.type = event::button_up; + ev.button.drw = this; + ev.button.x = x; ev.button.y = y; + ev.button.n = k + 1; + evfunc(ev); + CloseDraw(); + } + k = -1; break; + } + } + if (k >= 0) + { + z = PosCursor(x, y); + if (x != old_mx || y != old_my) + { + TCursorVisible::C.Show(); + old_mx = x; old_my = y; + old_mtime = clock(); + if (evmask & (mouse_move_mask | mouse_drag_mask)) + { + for (k = 0; k < MouseStatus; k++) + { + if (z & (1 << k)) break; + } + if (evmask & ((k == MouseStatus) ? mouse_move_mask : mouse_drag_mask)) + { + ev.type = event::mouse_move; + ev.button.drw = this; + ev.button.x = x; ev.button.y = y; + ev.button.n = (k >= MouseStatus) ? 0 : (k + 1); + evfunc(ev); + CloseDraw(); + } + } + } + else if (TCursorVisible::C.IsShowed() && + (unsigned long)(clock() - old_mtime) > 30 * CLK_TCK) + { + TCursorVisible::C.Hide(); + old_mtime = clock(); + } + } + } + if (quit == 1) + { + ev.type = event::close; + ev.any.drw = this; + Quit(evfunc(ev)); + CloseDraw(); + } + } + TCursorVisible::C.Set(show_cur); + if (!wasgraph) closegraph(); + freopen("CON", "wt", stdout); + return quit; +} + +#endif //_DOS_GRAPHIC_DRAW_H diff --git a/programs/games/checkers/trunk/dosmouse.h b/programs/games/checkers/trunk/dosmouse.h new file mode 100644 index 0000000000..4627429e00 --- /dev/null +++ b/programs/games/checkers/trunk/dosmouse.h @@ -0,0 +1,172 @@ +#ifndef _INCLUDE_DOS_MOUSE +#define _INCLUDE_DOS_MOUSE + +#include + +inline int GetMouseStatus() +{ + int a, b; + _AX = 0; + geninterrupt(0x33); + a = _AX; b = _BX; + if (!a) return 0; + else return b; +} + +class TCursorVisible +{ +public: + TCursorVisible(int s = 1) : visible(1) {if (!s) Hide();} + ~TCursorVisible() {Show();} + + int IsShowed() const {return visible;} + int IsHidden() const {return !visible;} + int Show() + { + if (!visible) {_AX = 1; geninterrupt(0x33); visible = 1; return 1;} + else return 0; + } + int Hide() + { + if (visible) {_AX = 2; geninterrupt(0x33); visible = 0; return 1;} + else return 0; + } + int Set(int v) {return v ? Show() : Hide();} +private: + int visible; +public: + class T_C + { + public: + ~T_C() {Hide();} + + int IsShowed() const {return visible;} + int IsHidden() const {return !visible;} + int Show() + { + if (!visible) {_AX = 1; geninterrupt(0x33); visible = 1; return 1;} + else return 0; + } + int Hide() + { + if (visible) {_AX = 2; geninterrupt(0x33); visible = 0; return 1;} + else return 0; + } + int Set(int v) {return v ? Show() : Hide();} + private: + T_C() : visible(0) {} + friend class TCursorVisible; + + int visible; + }; + + static T_C C; +}; + +extern int MouseStatus; + +inline void SetShowCursor(int show) +{ + if (MouseStatus) + { + _AX = show ? 1 : 2; + geninterrupt(0x33); + } +} + +inline void ShowCursor() +{ + if (MouseStatus) + { + _AX = 1; + geninterrupt(0x33); + } +} + +inline void HideCursor() +{ + if (MouseStatus) + { + _AX = 2; + geninterrupt(0x33); + } +} + +inline int PosCursor(int &x, int &y) +{ + if (MouseStatus) + { + int xx, yy, r; + _AX = 3; + geninterrupt(0x33); + xx = _CX; yy = _DX; + r = _BX; + x = xx; y = yy; + return r; + } + else return 0; +} + +inline int SetPosCursor(int x, int y) +{ + if (MouseStatus) + { + _AX = 4; _CX = x; _DX = y; + geninterrupt(0x33); + return _BX; + } + else return 0; +} + +inline int GetButtonDown(int n, int &x, int &y) +{ + if (MouseStatus) + { + int xx, yy, r; + _AX = 5; _BX = n; + geninterrupt(0x33); + xx = _CX; yy = _DX; + r = _BX; + x = xx; y = yy; + return r; + } + else return 0; +} + +inline int GetButtonUp(int n, int &x, int &y) +{ + if (MouseStatus) + { + int xx, yy, r; + _AX = 6; _BX = n; + geninterrupt(0x33); + xx = _CX; yy = _DX; + r = _BX; + x = xx; y = yy; + return r; + } + else return 0; +} + +inline void BoundCursorX(int x1, int x2) +{ + if (MouseStatus) + { + _AX = 7; _CX = x1; _DX = x2; + geninterrupt(0x33); + } +} + +inline void BoundCursorY(int y1, int y2) +{ + if (MouseStatus) + { + _AX = 8; _CX = y1; _DX = y2; + geninterrupt(0x33); + } +} + +int MouseStatus = GetMouseStatus(); +TCursorVisible::T_C TCursorVisible::C; + +#endif //_INCLUDE_DOS_MOUSE diff --git a/programs/games/checkers/trunk/egavga.bgi b/programs/games/checkers/trunk/egavga.bgi new file mode 100644 index 0000000000000000000000000000000000000000..800163160dcf3473e5e18a35738a1385ffc999c7 GIT binary patch literal 5554 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 literal 0 HcmV?d00001 diff --git a/programs/games/checkers/trunk/gnu-draw.h b/programs/games/checkers/trunk/gnu-draw.h new file mode 100644 index 0000000000..5ef95207a9 --- /dev/null +++ b/programs/games/checkers/trunk/gnu-draw.h @@ -0,0 +1,295 @@ +#include "gr-draw.h" +#include +#include +#include +#include +#include + +#ifndef _GNU_GRAPHIC_DRAW_H +#define _GNU_GRAPHIC_DRAW_H + +class TGnuGraphDraw : public TGraphDraw +{ +public: + TGnuGraphDraw(const char *s = 0); + ~TGnuGraphDraw(); + + static unsigned long GetKeySym(unsigned int key) {return key;} + + unsigned long GetBlackColor(); + unsigned long GetWhiteColor(); + unsigned long CreateColor(unsigned short red, + unsigned short green, unsigned short blue); + void FreeColor(unsigned long c); + unsigned int GetBgColor() const {return bgcolor;} + void SetBgColor(unsigned long c) {bgcolor = c;} + + int GetStatus() {return disp ? (win ? 1 : 0) : (-1);} + int Init() {return disp ? 0 : -1;} + int Run(int evmask = 0, int w = INT_MIN, int h = INT_MIN); + + void GetSize(int &w, int &h); + int OpenDraw(); + int IsDraw() {return disp && win && prGC;} + void CloseDraw() {if (prGC) {XFreeGC(disp, prGC); prGC = 0;}} + + int SetColor(unsigned long c); + int DrawLine(int x0, int y0, int x1, int y1); + int DrawText(int x0, int y0, char *text); + int DrawClear(); + int GetTextH(const char *s) {return 10;} + int GetTextW(const char *s) {return 6 * strlen(s);} + void Quit(int q = 1) {quit = (q > 0) ? q : 0;} + void ResReinit(int w = INT_MIN, int h = INT_MIN); +protected: + void InitDisplay(); + void InitWindow(int w = INT_MIN, int h = INT_MIN); +protected: + int quit; + unsigned long bgcolor; + Display *disp; + Window win; + int ScrNum; + GC prGC; + Mask xmask; +}; + +TGnuGraphDraw::TGnuGraphDraw(const char *s /*= 0*/) : TGraphDraw(s), prGC(0) +{ + xmask = 0; + InitDisplay(); +} + +TGnuGraphDraw::~TGnuGraphDraw() +{ + CloseDraw(); + if (disp) XCloseDisplay(disp); +} + +void TGnuGraphDraw::InitDisplay() +{ + disp = XOpenDisplay(NULL); + if (disp) ScrNum = DefaultScreen(disp); + else + { + int L = 100; + if (title) L += strlen(title); + char *str = new char[L]; + if (str) + { + strcpy(str, "\n"); + if (title && title[0]) {strcat(str, title); strcat(str, ": ");} + strcat(str, "Can't connect to X Server.\n"); + printf("%s", str); + } + } + bgcolor = GetWhiteColor(); +} + +unsigned long TGnuGraphDraw::GetBlackColor() +{ + if (disp) return BlackPixel(disp, ScrNum); + else return TGraphDraw::GetBlackColor(); +} + +unsigned long TGnuGraphDraw::GetWhiteColor() +{ + if (disp) return WhitePixel(disp, ScrNum); + else return TGraphDraw::GetWhiteColor(); +} + +unsigned long TGnuGraphDraw::CreateColor(unsigned short red, + unsigned short green, unsigned short blue) +{ + if (disp) + { + XColor color; + color.red = red; color.green = green; color.blue = blue; + if (XAllocColor(disp, DefaultColormap(disp, ScrNum), &color)) + { + return color.pixel; + } + else return BlackPixel(disp, ScrNum); + } + else return TGraphDraw::CreateColor(red, green, blue); +} + +void TGnuGraphDraw::FreeColor(unsigned long c) +{ + if (disp && c != BlackPixel(disp, ScrNum)) + { + XFreeColors(disp, DefaultColormap(disp, ScrNum), &c, 1, 0); + } +} + +void TGnuGraphDraw::GetSize(int &w, int &h) +{ + if (disp) + { + int x, y; + Window w_ret; + unsigned int br, dr, width = 0, height = 0; + XGetGeometry(disp, win, &w_ret, &x, &y, &width, &height, &br, &dr); + w = width; h = height; + } + else TGraphDraw::GetSize(w, h); +} + +int TGnuGraphDraw::OpenDraw() +{ + if (!disp && !win) return 0; + if (!prGC) prGC = XCreateGC(disp, win, 0, NULL); + return 1; +} + +int TGnuGraphDraw::SetColor(unsigned long c) +{ + if (!disp || !prGC) return 0; + XSetForeground(disp, prGC, c); + return 1; +} + +int TGnuGraphDraw::DrawLine(int x0, int y0, int x1, int y1) +{ + if (!disp || !prGC) return 0; + XDrawLine(disp, win, prGC, x0, y0, x1, y1); + return 1; +} + +int TGnuGraphDraw::DrawText(int x0, int y0, char *text) +{ + if (!disp || !prGC) return 0; + XDrawString(disp, win, prGC, x0, y0 + GetTextH(text), text, strlen(text)); + return 1; +} + +int TGnuGraphDraw::DrawClear() +{ + if (!disp || !prGC) return 0; + XClearWindow(disp, win); + return 1; +} + +void TGnuGraphDraw::InitWindow(int w, int h) +{ + if (w <= 0 || h <= 0) TGraphDraw::GetSize(w, h); + win = XCreateSimpleWindow(disp, RootWindow(disp, ScrNum), + 100, 100, w, h, 2, BlackPixel(disp, ScrNum), GetBgColor()); + XSelectInput(disp, win, xmask); + XMapWindow(disp, win); +} + +void TGnuGraphDraw::ResReinit(int w, int h) +{ + if (disp) {free(disp); disp = 0;} + InitDisplay(); + if (!disp) exit(1); + else if (win) InitWindow(w, h); +} + +int TGnuGraphDraw::Run(int evmask, int w, int h) +{ + if (!disp) return -1; + if (!evfunc) return -2; + xmask = ExposureMask; + if (evmask & button_down_mask) xmask |= ButtonPressMask; + if (evmask & button_up_mask) xmask |= ButtonReleaseMask; + if (evmask & key_down_mask) xmask |= KeyPressMask; + if (evmask & key_up_mask) xmask |= KeyReleaseMask; + if (evmask & mouse_move_mask) xmask |= PointerMotionMask; + if (evmask & mouse_drag_mask) + { + xmask |= ButtonMotionMask | Button1MotionMask | Button2MotionMask | + Button3MotionMask | Button4MotionMask | Button5MotionMask; + } + InitWindow(w, h); + XEvent xevent; + KeySym sym; + char str[50]; + event ev; + int stpr = 0; + quit = 0; + while (quit == 0) + { + if (stpr == 0) + { + ev.type = event::start; + ev.any.drw = this; + evfunc(ev); + CloseDraw(); + stpr = 1; + } + else + { + XNextEvent(disp, &xevent); + switch(xevent.type) + { + case Expose: + if (xevent.xexpose.count != 0) break; + ev.type = event::draw; + ev.any.drw = this; + evfunc(ev); + CloseDraw(); + break; + case ButtonPress: + ev.type = event::button_down; + ev.button.drw = this; + ev.button.x = xevent.xbutton.x; + ev.button.y = xevent.xbutton.y; + ev.button.n = xevent.xbutton.button; + evfunc(ev); + CloseDraw(); + break; + case ButtonRelease: + ev.type = event::button_up; + ev.button.drw = this; + ev.button.x = xevent.xbutton.x; + ev.button.y = xevent.xbutton.y; + ev.button.n = xevent.xbutton.button; + evfunc(ev); + CloseDraw(); + break; + case MotionNotify: + ev.type = event::mouse_move; + ev.button.drw = this; + ev.button.x = xevent.xbutton.x; + ev.button.y = xevent.xbutton.y; + ev.button.n = xevent.xbutton.button; + evfunc(ev); + CloseDraw(); + break; + case KeyPress: + memset(str, 0, 20); + XLookupString(&xevent.xkey, str, 20, &sym, 0); + ev.type = event::key_down; + ev.key.drw = this; + ev.key.k = (unsigned long)sym; + evfunc(ev); + CloseDraw(); + break; + case KeyRelease: + memset(str, 0, 20); + XLookupString(&xevent.xkey, str, 20, &sym, 0); + ev.type = event::key_up; + ev.key.drw = this; + ev.key.k = (unsigned long)sym; + evfunc(ev); + CloseDraw(); + break; + } + } + if (quit == 1) + { + ev.type = event::close; + ev.any.drw = this; + Quit(evfunc(ev)); + CloseDraw(); + } + } + CloseDraw(); + XDestroyWindow(disp, win); + win = 0; + return quit; +} + +#endif //_GNU_GRAPHIC_DRAW_H diff --git a/programs/games/checkers/trunk/gr-draw.h b/programs/games/checkers/trunk/gr-draw.h new file mode 100644 index 0000000000..4d86003f94 --- /dev/null +++ b/programs/games/checkers/trunk/gr-draw.h @@ -0,0 +1,121 @@ +#ifndef _GRAPHIC_DRAW_H +#define _GRAPHIC_DRAW_H + +#ifndef __MENUET__ +#include +#include + +#ifdef _Windows +# include +#endif +#else +#define LONG_MIN (-2147483647L-1) /* minimum signed long value */ +#define INT_MIN LONG_MIN +#endif + +class TGraphDraw +{ +public: + union event + { + enum evtype {noevent = 0, draw, button_down, button_up, + mouse_move, key_down, key_up, start, close} type; + + struct evany + { + evtype type; + TGraphDraw *drw; + } any; + + struct evbutton : public evany + { + int x, y, n; + } button; + + struct evkey : public evany + { + unsigned long k; + } key; + }; + + enum {button_down_mask = 0x1, button_up_mask = 0x2, key_down_mask = 0x4, + key_up_mask = 0x8, mouse_move_mask = 0x10, mouse_drag_mask = 0x20}; + + enum {ret_setcapture = 0x10}; +public: + TGraphDraw(const char *s = 0) : title(0), about_info(0), + evfunc(0), id(0), data(0) {CopyTitle(s);} + ~TGraphDraw() {FreeTitle();} + + virtual unsigned long GetBlackColor() {return 0;} + virtual unsigned long GetWhiteColor() {return 0xFFFFFFL;} + virtual unsigned long CreateColor(unsigned short red, + unsigned short green, unsigned short blue); + virtual void FreeColor(unsigned long c) {} + virtual unsigned long GetBgColor() {return GetWhiteColor();} + virtual void SetBgColor(unsigned long c) {} + + virtual void SetTitle(const char *s) {CopyTitle(s);} + const char *GetTitle() const {return title;} + + virtual int GetStatus() {return 0;} //1 - can draw, 0 - can't draw, <0 - error + virtual int Init() {return 0;} + virtual void UnInit() {} + virtual int Run(int evmask = 0, int w = INT_MIN, int h = INT_MIN) {return -100;} + + virtual void GetSize(int &w, int &h) {w = 200; h = 200;} + virtual int OpenDraw() {return 0;} + virtual int IsDraw() {return 0;} + virtual void CloseDraw() {} + + virtual int SetColor(unsigned long c) {return 0;} + virtual int DrawLine(int x0, int y0, int x1, int y1) {return 0;} + virtual int DrawText(int x0, int y0, char *text) {return 0;} + virtual int DrawClear() {return 0;} + virtual int GetTextH(const char *s) {return 16;} + virtual int GetTextW(const char *s) {return 8 * strlen(s);} + virtual void Quit(int q = 1) {} + virtual void ResReinit(int w = INT_MIN, int h = INT_MIN) {} + virtual int GetAboutInfo() {return about_info;} + virtual void SetAboutInfo(int inf) {about_info = inf;} +protected: + void FreeTitle() {if (title) {delete[] title; title = 0;}} + void CopyTitle(const char *s); + char *title; + int about_info; +public: + int (*evfunc)(const event &ev); + int id; + void *data; +}; + +unsigned long TGraphDraw::CreateColor(unsigned short red, + unsigned short green, unsigned short blue) +{ + return (unsigned long)(red >> 8) + ((unsigned long)(green >> 8) << 8) + + ((unsigned long)(blue >> 8) << 16); +} + +void TGraphDraw::CopyTitle(const char *s) +{ + FreeTitle(); + if (s) {title = new char[strlen(s) + 1]; strcpy(title, s);} +} + +#if defined __GNUC__ +# include "gnu-draw.h" + typedef TGnuGraphDraw TMainGraphDraw; +#elif defined __MENUET__ +# include "mt-draw.h" + typedef TKlbrGraphDraw TMainGraphDraw; +#elif defined _Windows +# include "win-draw.h" + typedef TWinGraphDraw TMainGraphDraw; +#elif defined __MSDOS__ +# include "dos-draw.h" + typedef TDosGraphDraw TMainGraphDraw; +#else + typedef TGraphDraw TMainGraphDraw; +#endif + +#endif //_GRAPHIC_DRAW_H diff --git a/programs/games/checkers/trunk/hash.h b/programs/games/checkers/trunk/hash.h new file mode 100644 index 0000000000..376bd2319e --- /dev/null +++ b/programs/games/checkers/trunk/hash.h @@ -0,0 +1,185 @@ +#if !defined(HASH_TABLE_H) +#define HASH_TABLE_H + +template +class THashTable +{ +public: + THashTable(int _m = -1) {MemInit(_m);} + ~THashTable() {null();} + + int hash1(const TypeString &x) const {return func1(x);} + int hash2(const TypeString &x) const {return 2*func2(x) + 1;} + + void null(); + int IsNull() const {return M >= 0;} + int NumElem() const {return n;} + int MaxNumElem() const {return stack_size;} + int GetM() const {return M;} + int TableSize() const {return 1 << M;} + + void resize(int _m); + void push(const T &x); + T *find(const TypeString &x); + void pop(); + + T &last() {return stack[n-1];} + const T &last() const {return stack[n-1];} + T &first() {return stack[0];} + const T &first() const {return stack[0];} + T &operator[](int i) {return stack[i];} + const T &operator[](int i) const {return stack[i];} + T *operator()() {return stack;} + const T *operator()() const {return stack;} +protected: + void _push(const T &x); + int _find_pointer(const T *p) const; + int _find(const TypeString &x) const; + void MemInit(int _m); +protected: + int M; + int stack_size; + int n; + T **table; + T *stack; +protected: + HashFunction func1, func2; +}; + +template +void THashTable::null() +{ + if (table) delete[] table; + if (stack) delete[] stack; + M = -1; + table = 0; + stack = 0; + stack_size = 0; + n = 0; + func1.init(-1); + func2.init(-1); +} + +template +void THashTable::resize(int _m) +{ + delete[] table; + T *stp = stack; + int np = n; + MemInit(_m); + for (int i = 0; i < np && n < stack_size; i++) _push(stp[i]); + if (stp) delete[] stp; +} + +template +inline void THashTable::push(const T &x) +{ + if (n == stack_size) resize(M + 1); + _push(x); +} + +template +inline T *THashTable::find(const TypeString &x) +{ + int i = _find(x); + if (i >= 0) return table[i]; + else return 0; +} + +template +inline void THashTable::pop() +{ + if (n > 0) + { + n--; + int i = _find_pointer(stack + n); + if (i >= 0) table[i] = NULL; + } +} + +template +void THashTable::_push(const T &x) +{ + int h1 = hash1(x); + int h2 = hash2(x); + int i = h1; + stack[n] = x; + do + { + if (table[i] == NULL) + { + table[i] = stack + n; + break; + } + i = (i + h2) & ((1 << M) - 1); + } + while (i != h1); + n++; +} + +template +int THashTable::_find_pointer(const T *p) const +{ + if (n > 0) + { + int h1 = hash1(*p); + int h2 = hash2(*p); + int i = h1; + do + { + if (table[i] == NULL) break; + if (table[i] == p) return i; + i = (i + h2) & ((1 << M) - 1); + } + while (i != h1); + } + return -1; +} + +template +int THashTable::_find(const TypeString &x) const +{ + if (n > 0) + { + int h1 = hash1(x); + int h2 = hash2(x); + int i = h1; + do + { + if (table[i] == NULL) break; + if ((*table[i]) == x) return i; + i = (i + h2) & ((1 << M) - 1); + } + while (i != h1); + } + return -1; +} + +template +void THashTable::MemInit(int _m) +{ + M = _m; + if (M < 0) + { + M = -1; + stack_size = 0; + table = 0; + stack = 0; + n = 0; + func1.init(-1); + func2.init(-1); + } + else + { + if (M < 3) M = 3; + stack_size = (1 << M) / 3; + table = new T*[1 << M]; + for (int i = 0; i < (1 << M); i++) table[i] = NULL; + stack = new T[stack_size]; + n = 0; + func1.init(M); + func2.init(M-1); + } +} + +#endif // HASH_TABLE_H diff --git a/programs/games/checkers/trunk/history.h b/programs/games/checkers/trunk/history.h new file mode 100644 index 0000000000..5ba1f7199d --- /dev/null +++ b/programs/games/checkers/trunk/history.h @@ -0,0 +1,402 @@ +#ifndef _HEADER_HISTORY_H +#define _HEADER_HISTORY_H + +#ifndef __MENUET__ +#include +#include +#include +#include +#endif +#include "position.h" +#include "hash.h" +#include "sysproc.h" + +class THistory +{ +#ifndef __MENUET__ +public: + static char FileName[1024]; +#endif +public: + THistory(int id = 0) {if (id >= 0) Hid = NHid++; else Hid = id;} + + int GetId() const {return Hid;} + static int GetNId() {return NHid;} + + int Start(const Position &pos) const; + int Move(const Position &pos, const unsigned char mv[], int nmove) const; + int Play(const PlayWrite &play) const; + +#ifndef __MENUET__ + static int InitHFile(char *dname = 0); + static int HRead(FILE *f, PlayWrite *&play); +protected: + int Print(const char *str) const; +#endif + + int Hid; + + static int NHid; +protected: + struct TStr + { + TStr(const char *ss = 0) : s(0) {(*this) = ss;} + TStr(const TStr &ss) : s(0) {(*this) = ss.s;} + ~TStr() {(*this) = 0;} + + TStr &operator=(const char *ss); + TStr &operator=(const TStr &ss) {return (*this) = ss.s;} + + operator char*() {return s;} + operator const char*() const {return s;} + char &operator*() {return *s;} + const char &operator*() const {return *s;} + char &operator[](int i) {return s[i];} + const char &operator[](int i) const {return s[i];} + void Extend(int n); + + friend int operator==(const TStr &s1, const TStr &s2) + {return strcmp(s1, s2) == 0;} + friend int operator==(const char *s1, const TStr &s2) + {return strcmp(s1, s2) == 0;} + friend int operator==(const TStr &s1, const char *s2) + {return strcmp(s1, s2) == 0;} + friend int operator!=(const TStr &s1, const TStr &s2) + {return strcmp(s1, s2) != 0;} + friend int operator!=(const char *s1, const TStr &s2) + {return strcmp(s1, s2) != 0;} + friend int operator!=(const TStr &s1, const char *s2) + {return strcmp(s1, s2) != 0;} + friend int operator>=(const TStr &s1, const TStr &s2) + {return strcmp(s1, s2) >= 0;} + friend int operator>=(const char *s1, const TStr &s2) + {return strcmp(s1, s2) >= 0;} + friend int operator>=(const TStr &s1, const char *s2) + {return strcmp(s1, s2) >= 0;} + friend int operator<=(const TStr &s1, const TStr &s2) + {return strcmp(s1, s2) <= 0;} + friend int operator<=(const char *s1, const TStr &s2) + {return strcmp(s1, s2) <= 0;} + friend int operator<=(const TStr &s1, const char *s2) + {return strcmp(s1, s2) <= 0;} + friend int operator>(const TStr &s1, const TStr &s2) + {return strcmp(s1, s2) > 0;} + friend int operator>(const char *s1, const TStr &s2) + {return strcmp(s1, s2) > 0;} + friend int operator>(const TStr &s1, const char *s2) + {return strcmp(s1, s2) > 0;} + friend int operator<(const TStr &s1, const TStr &s2) + {return strcmp(s1, s2) < 0;} + friend int operator<(const char *s1, const TStr &s2) + {return strcmp(s1, s2) < 0;} + friend int operator<(const TStr &s1, const char *s2) + {return strcmp(s1, s2) < 0;} + + char *s; + }; + + class THash + { + public: + void init(int _m); + int operator()(const TStr &str) const; + protected: + int m; + int K[16]; + }; + + struct TTableItem + { + TTableItem(const char *s = 0, int k = 0) : str(s), k(k) {} + TTableItem(const TStr &s, int k = 0) : str(s), k(k) {} + TTableItem(const TTableItem &t) : str(t.str), k(t.k) {} + + operator TStr&() {return str;} + operator const TStr&() const {return str;} + + TStr str; + int k; + }; +}; + +#ifndef __MENUET__ +char THistory::FileName[1024] = "history.che"; +#endif +int THistory::NHid = 0; + +#ifndef __MENUET__ +int THistory::Print(const char *str) const +{ + char *line = new char[30 + strlen(str)]; + if (!line) return 0; + unsigned long pr_id = GetProcessId(); + if (Hid == -1) sprintf(line, "%lu %s\n", pr_id, str); + else if (Hid < 0) sprintf(line, "%lu%c %s\n", pr_id, (char)Hid, str); + else sprintf(line, "%lu:%d %s\n", pr_id, Hid, str); + FILE *f = fopen(FileName, "at"); + if (!f) + { + clock_t cc = clock(); + do {f = fopen(FileName, "at");} + while(!f && (clock() - cc) <= 0.05 * CLOCKS_PER_SEC); + } + if (!f) {delete[] line; return 0;} + fputs(line, f); + fclose(f); + delete[] line; + return 1; +} +#endif + +int THistory::Start(const Position &pos) const +{ + char str[20 + NUM_CELL] = "Start "; + if (!pos.Write(str + strlen(str), 1)) return 0; +#ifndef __MENUET__ + if (!Print(str)) return 0; +#endif + return 1; +} + +int THistory::Move(const Position &pos, const unsigned char mv[], int nmove) const +{ + char *str = new char[15 + pos.GetLenMvEx(mv, 11)]; + if (!str) return 0; + sprintf(str, "%d.%s ", (nmove + 1) / 2, (nmove % 2 == 0) ? ".." : ""); + pos.WriteMvEx(mv, str + strlen(str), 11); +#ifndef __MENUET__ + if (!Print(str)) {delete[] str; return 0;} +#endif + delete[] str; + return 1; +} + +int THistory::Play(const PlayWrite &play) const +{ + if (play.GetN() <= 0) return 0; + Position pos; + if (play.GetPos(pos, 0) < 0) return 0; + if (!Start(pos)) return 0; + int i; + unsigned char mv[NUM_CELL]; + for (i = 1; i < play.GetN(); i++) + { + if (play.GetPos(pos, i - 1) < 0) return 0; + if (play.GetMove(mv, i) < 0) return 0; + if (!Move(pos, mv, i)) return 0; + } + return 1; +} + +#ifndef __MENUET__ +int THistory::InitHFile(char *dname) +{ + if (dname && dname[0]) + { + char fnm[1024]; + strcpy(fnm, dname); + int i; + for (i = strlen(fnm) - 1; i >= 0; i--) + { + if (fnm[i] == DIR_SEPARATOR) break; + } + if (i >= 0) + { + strcpy(fnm + i + 1, FileName); + strcpy(FileName, fnm); + } + } + int e = 1; + FILE *f = fopen(FileName, "rt"); + if (f) {e = feof(f); fclose(f);} + if (!e) return 0; + f = fopen(FileName, "wt"); + if (!f) return -1; + fputs("checkers-history_1.1\n", f); + fclose(f); + return 1; +} +#endif + +THistory::TStr &THistory::TStr::operator=(const char *ss) +{ + if (s) delete[] s; + if (ss) + { + s = new char[strlen(ss) + 1]; + strcpy(s, ss); + } + else s = 0; + return *this; +} + +void THistory::TStr::Extend(int n) +{ + if (n <= 0) {(*this) = 0; return;} + char *ss = s; + s = new char[n+1]; + if (ss) + { + strncpy(s, ss, n); + s[n] = 0; + delete[] ss; + } + else s[0] = 0; +} + +void THistory::THash::init(int _m) +{ + m = _m; + for (int i = 0; i < 16; i++) + { + K[i] = (2*random(32767) + 1) & ((1 << m) - 1); + } +} + +int THistory::THash::operator()(const TStr &str) const +{ + int i, r = 0; + const char *s = str; + for (i = 0; *s; i = (i+1) & 15) r += *(s++) * K[i]; + r &= (1 << m) - 1; + return r; +} + +#ifndef __MENUET__ +int THistory::HRead(FILE *f, PlayWrite *&play) +{ + const int MAX_INP_WORD = 100; + int nplay = 0, mplay = 10; + play = new PlayWrite[mplay]; + THashTable table; + TStr word; + char inp_word[MAX_INP_WORD + 1]; + int r, maxword = 0; + unsigned char ch; + int i, k = 0, kind = 0, wasspace = 1, nmove = 0; + for (;;) + { + r = (fread(&ch, 1, 1, f) == 1); + if (!r || isspace(ch)) + { + if (!wasspace) + { + if (kind == 0) kind = 1; + else if (kind == 2) + { + for (i = 0; inp_word[i]; i++) + { + inp_word[i] = (char)tolower((unsigned char)inp_word[i]); + } + if (strcmp(inp_word, "start") == 0) kind = 5; + else kind = -1; + inp_word[0] = 0; k = 0; + } + else if (kind == 3) + { + nmove *= 2; + if (k <= 1) nmove--; + inp_word[0] = 0; + k = 0; kind = 4; + } + else if (kind == 4) + { + TTableItem *n_pl = table.find(word); + if (!n_pl) kind = -1; + else if (nmove < 1 || nmove > play[n_pl->k].GetN()) kind = -1; + else + { + PlayWrite::PMv pmv; + if (play[n_pl->k].GetPos(pmv.pos, nmove - 1) < 0) kind = -1; + else if (!pmv.pos.ReadMv(pmv.mv, inp_word, 1)) kind = -1; + else + { + play[n_pl->k].ClearFrom(nmove); + if (play[n_pl->k].Add(pmv.mv) != 0) kind = -1; + else {k = n_pl->k; kind = 11;} + } + } + } + else if (kind == 5) + { + Position pos; + pos.Read(inp_word, 1); + if (pos.IsNull()) kind = -1; + else + { + TTableItem *n_pl = table.find(word); + if (!n_pl) + { + table.push(TTableItem(word, nplay)); + n_pl = table.find(word); + } + if (!n_pl) kind = -1; + else + { + if (nplay >= mplay) + { + PlayWrite *play0 = play; + int mplay0 = mplay; + mplay = 2*nplay + 3; + play = new PlayWrite[mplay]; + if (play0) + { + for (i = 0; i < mplay0; i++) play[i] = play0[i]; + delete[] play0; + } + } + n_pl->k = nplay++; + play[n_pl->k].Add(0, pos); + k = n_pl->k; kind = 12; + } + } + } + } + if (!r || ch == '\n' || ch == '\r') + { + k = 0; + kind = 0; + if (!r) break; + } + wasspace = 1; + } + else + { + if (kind == 0) + { + if (k >= maxword) word.Extend(2*k + 3); + word[k++] = ch; + word[k] = 0; + } + else if (kind == 1) + { + if (isdigit(ch)) {nmove = ch - '0'; k = 0; kind = 3;} + else + { + inp_word[0] = ch; + inp_word[1] = 0; + k = 1; kind = 2; + } + } + else if (kind == 2 || kind == 4 || kind == 5) + { + if (k < MAX_INP_WORD) + { + inp_word[k++] = ch; + inp_word[k] = 0; + } + } + else if (kind == 3) + { + if (k == 0 && isdigit(ch)) nmove = 10 * nmove + ch - '0'; + else if (ch == '.') k++; + else kind = -1; + } + wasspace = 0; + } + } + return nplay; +} +#endif + +#endif //_HEADER_HISTORY_H diff --git a/programs/games/checkers/trunk/include/me_func.inc b/programs/games/checkers/trunk/include/me_func.inc new file mode 100644 index 0000000000..f0fab935ce --- /dev/null +++ b/programs/games/checkers/trunk/include/me_func.inc @@ -0,0 +1,1135 @@ +;const int +MENUET_BORDER_SIZE = 4; +;const int +MENUET_HEADER_SIZE = 20; + +;const int +MENUET_THREAD_DATA_USER = 0; // Thread data begin from the user dword +;const int +MENUET_THREAD_DATA_ST_BEGIN = 1; // Stack beginning follows after the user dword +;const int +MENUET_THREAD_DATA_NEXT = 2; +;const int +MENUET_THREAD_DATA_PID = 3; +;const int +MENUET_THREAD_DATA_FLAG = 4; +;const int +MENUET_THREAD_DATA_X = 5; +;const int +MENUET_THREAD_DATA_Y = 6; +;const int +MENUET_THREAD_DATA_C_WINDOW = 7; +;const int +MENUET_THREAD_DATA_C_HEADER = 8; +;const int +MENUET_THREAD_DATA_C_BORDER = 9; +;const int +MENUET_THREAD_DATA_C_TITLE = 10; +;const int +MENUET_THREAD_DATA_TITLE = 11; +;const int +MENUET_THREAD_DATA_PICTURE = 12; +;const int +MENUET_THREAD_DATA_SZ_PICT = 13; +;const int +MENUET_THREAD_DATA_LAST_SX = 14; +;const int +MENUET_THREAD_DATA_LAST_SY = 15; +;const int +MENUET_THREAD_DATA_LEN = 16; + +;const int +MENUET_MUTEX_MAX_TIME_WAIT = 20; + +;const int +MENUET_FILE_BLOCK_SIZE = 512; + +;const int +MENUET_FILE_MEMORY_OS_NEED = 4096; + +;/*** + +macro segment name +{ + segment name + if name eq _init_ | name eq _INIT_ +Menuet_SegmentInit: + else if name eq _exit_ | name eq _EXIT_ +Menuet_SegmentExit: + end if +} + +macro endseg name +{ + if name eq _init_ | name eq _INIT_ +Menuet_SegmentInitEnd: + else if name eq _exit_ | name eq _EXIT_ +Menuet_SegmentExitEnd: + end if + endseg name +} + +macro Menuet_Put_MovEaxVal_Ret address,val +{ + mov byte [address],0xB8 + mov dword [address+4],0xC089C300 + mov dword [address+1],val +} + +define @Menuet@Main$qv +nextdef MenuetEntryPoint + and esp,not 3 + sub esp,1024 + mov eax,9 + mov ebx,esp + mov ecx,-1 + int 0x40 + mov ebx,[esp+26] + mov edx,[esp+30] + lea eax,[ebx-0x20] + add esp,1024 + cmp esp,eax + cmova esp,eax + and esp,not 3 + xor eax,eax + cld + mov edi,@Menuet@_ThreadTable + mov ecx,256 + rep stos dword [edi] + mov esi,@Menuet@GetPid$qv + mov edi,@Menuet@_ThreadSavedBegProc + movs dword [edi],[esi] + movs dword [edi],[esi] + mov esi,@Menuet@GetThreadData$qv + movs dword [edi],[esi] + movs dword [edi],[esi] + Menuet_Put_MovEaxVal_Ret @Menuet@GetPid$qv,edx +if defined MenuetHeapInit + mov ecx,esp + push ebx + push ecx + push U_END + call MenuetHeapInit ; Initialize a dynamic heap and create new memory in its begin. + pop ecx ; Parameters: begin of a new heap, end of data to create in + mov [esp+4],eax ; the begin of a heap. Return address of the created data. + mov dword [esp],0 +else + xor eax,eax + push eax + push eax +end if + call @Menuet@ThreadMain$qpvt1 +nextdef Menuet_ThreadFinish + add esp,8 +if defined MenuetHeapFreeAndThreadFinish + test eax,eax + jz Menuet_ThreadFinish_end + push dword @Menuet@_ExitProcessNow + push eax + call MenuetHeapFreeAndThreadFinish ; Free the given memory and finish the thread, +end if ; should exit process if second argument points to not zero. +Menuet_ThreadFinish_end: + or eax,-1 + int 0x40 +enddef + +define @Menuet@ThreadMain$qpvt1 + xchg ebx,[esp+4] + xchg ebp,[esp+8] + push esi + push edi + sub esp,MENUET_THREAD_DATA_LEN*4 + mov [esp],ebx + mov [esp+4],ebp + mov eax,40 + mov ebx,0x27 + int 0x40 + mov ebx,esp + cmp byte [@Menuet@_ThreadSavedBegProc],0x90 + jz Menuet_main_else_first_check + Menuet_Put_MovEaxVal_Ret @Menuet@GetThreadData$qv,esp +if defined Menuet_SegmentInit & defined Menuet_SegmentInitEnd + push Menuet_SegmentInitEnd + push Menuet_SegmentInit + jmp Menuet_main_after_first_check +end if +Menuet_main_else_first_check: + xor eax,eax + push eax + push eax +Menuet_main_after_first_check: + push ebx + call @@Menuet@_CallStart$qppvpvt2 + add esp,12 + test al,al + jnz Menuet_main_test_close_first + jmp Menuet_main_end +Menuet_main_close_first: + btr dword [esp+MENUET_THREAD_DATA_FLAG*4],31 + push esp + call @@MenuetOnClose$qppv + pop ecx + test al,al + jnz Menuet_main_end +Menuet_main_test_close_first: + cmp dword [esp+MENUET_THREAD_DATA_FLAG*4],0 + jl Menuet_main_close_first +; push esp +; push dword 1 +; call @Menuet@Redraw$qippv +; add esp,8 +Menuet_main_paint_msg: + or dword [esp+MENUET_THREAD_DATA_FLAG*4],3 + sub esp,1024 + mov eax,9 + mov ebx,esp + mov ecx,-1 + int 0x40 + mov eax,[esp+34] + mov ebx,[esp+38] + mov ecx,[esp+42] + mov edx,[esp+46] + add esp,1024 + cmp ecx,[esp+MENUET_THREAD_DATA_LAST_SX*4] + jnz Menuet_main_size + cmp edx,[esp+MENUET_THREAD_DATA_LAST_SY*4] + jz Menuet_main_paint +Menuet_main_size: + mov [esp+MENUET_THREAD_DATA_LAST_SX*4],ecx + mov [esp+MENUET_THREAD_DATA_LAST_SY*4],edx + push edx + push ecx + push ebx + push eax + lea ecx,[esp+16] + mov edx,esp + push ecx + push edx + call @@MenuetOnSize$qpippv + add esp,24 + test dword [esp+MENUET_THREAD_DATA_FLAG*4],3 + jz Menuet_main_cycle +Menuet_main_paint: + cmp dword [esp+MENUET_THREAD_DATA_FLAG*4],0 + jl Menuet_main_close + push esp + push dword 0 + call @Menuet@Redraw$qippv + add esp,8 +Menuet_main_cycle: + mov eax,11 +Menuet_main_message: + cmp dword [esp+MENUET_THREAD_DATA_FLAG*4],0 + jl Menuet_main_close + int 0x40 + test eax,eax + jnz Menuet_main_on_message + cmp dword [esp+MENUET_THREAD_DATA_FLAG*4],0 + jne Menuet_main_paint + push esp + call @@MenuetOnIdle$qppv + pop ecx + test eax,eax + jz Menuet_main_cycle + jl Menuet_main_wait_message + mov ebx,eax + mov eax,23 + jmp Menuet_main_message +Menuet_main_wait_message: + mov eax,10 + jmp Menuet_main_message +Menuet_main_key_press: + push esp + call @@MenuetOnKeyPress$qppv + pop ecx + jmp Menuet_main_cycle +Menuet_main_mouse: + push esp + call @@MenuetOnMouse$qppv + pop ecx + jmp Menuet_main_cycle +Menuet_main_on_message: + dec eax + jz Menuet_main_paint_msg + dec eax + jz Menuet_main_key_press + cmp eax,4 + jz Menuet_main_mouse + dec eax + jnz Menuet_main_cycle +Menuet_main_button: + mov eax,17 + int 0x40 + test al,al + jnz Menuet_main_cycle +Menuet_main_close: + btr dword [esp+MENUET_THREAD_DATA_FLAG*4],31 + push esp + call @@MenuetOnClose$qppv + pop ecx + test al,al + jz Menuet_main_button +Menuet_main_end: + mov ebx,esp + lock dec dword [@Menuet@_ThreadNumber] +if defined Menuet_SegmentExit & defined Menuet_SegmentExitEnd + jnz Menuet_main_else_last_check + push Menuet_SegmentExitEnd + push Menuet_SegmentExit + jmp Menuet_main_after_last_check +end if +Menuet_main_else_last_check: + xor eax,eax + push eax + push eax +Menuet_main_after_last_check: + push ebx + call @@Menuet@_RemoveThreadData$qppvpvt2 + add esp,12 + lock inc dword [@Menuet@_ThreadScanCount+4] + mov ebx,1 + jmp Menuet_main_end_wait +Menuet_main_end_wait_loop: + mov eax,5 + int 0x40 + shl ebx,1 + cmp ebx,MENUET_MUTEX_MAX_TIME_WAIT + jna Menuet_main_end_wait + mov ebx,MENUET_MUTEX_MAX_TIME_WAIT +Menuet_main_end_wait: + cmp dword [@Menuet@_ExitProcessNow],0 + jnz @Menuet@ExitProcess$qv + cmp dword [@Menuet@_ThreadScanCount],0 + jnz Menuet_main_end_wait_loop + lock dec dword [@Menuet@_ThreadScanCount+4] + mov ebp,[esp+4] + mov ebx,[esp] + add esp,MENUET_THREAD_DATA_LEN*4 + mov eax,ebp + pop edi + pop esi + xchg ebp,[esp+8] + xchg ebx,[esp+4] + ret +enddef + +macro call func +{ + if func eq __chkstk + sub esp,eax + else + call func + end if +} + +define @Menuet@Redraw$qippv + push ebp + mov ebp,[esp+12] + mov edx,[ebp+MENUET_THREAD_DATA_FLAG*4] + cmp dword [esp+8],0 + jl Menuet_redraw_only_inv + jz Menuet_redraw_no_frame + or dl,2 +Menuet_redraw_no_frame: + bt edx,30 + jnc Menuet_redraw_begin + or dl,1 + mov [ebp+MENUET_THREAD_DATA_FLAG*4],edx + jmp Menuet_redraw_end +Menuet_redraw_only_inv: + test dl,3 + jnz Menuet_redraw_no_frame +Menuet_redraw_end: + pop ebp + ret +Menuet_redraw_begin: + push ebx + push esi + push edi + and dword [ebp+MENUET_THREAD_DATA_FLAG*4],0xFFFFFFFC + mov eax,12 + mov ebx,1 + int 0x40 + test dl,2 + jz Menuet_redraw_picture + push 48 + pop eax + push 4 + pop ebx + int 0x40 + mov ebx,[ebp+MENUET_THREAD_DATA_X*4] + add ebx,2*5-1 + mov ecx,[ebp+MENUET_THREAD_DATA_Y*4] + add cx,ax + add ecx,5-1 + mov edx,[ebp+MENUET_THREAD_DATA_C_WINDOW*4] +; mov esi,[ebp+MENUET_THREAD_DATA_C_HEADER*4] +; mov edi,[ebp+MENUET_THREAD_DATA_C_BORDER*4] + mov edi,[ebp+MENUET_THREAD_DATA_TITLE*4] + xor eax,eax + int 0x40 +; mov edx,[ebp+MENUET_THREAD_DATA_TITLE*4] +; test edx,edx +; jz Menuet_redraw_picture +; mov edi,edx +; mov ecx,0xFFFFFFFF +; xor al,al +; cld +; repnz scas byte [edi] +; not ecx +; mov esi,ecx +; dec esi +; jz Menuet_redraw_picture +; mov eax,4 +; mov ebx,0x00070007 +; mov ecx,[ebp+MENUET_THREAD_DATA_C_TITLE*4] +; int 0x40 +Menuet_redraw_picture: +; mov esi,[ebp+MENUET_THREAD_DATA_PICTURE*4] +; test esi,esi +; jz Menuet_redraw_end_draw +; mov ecx,[ebp+MENUET_THREAD_DATA_SZ_PICT*4] +; jecxz Menuet_redraw_end_draw +; mov al,byte [ebp+MENUET_THREAD_DATA_C_WINDOW*4+3] +; and al,15 +; mov edx,MENUET_BORDER_SIZE*65536+MENUET_HEADER_SIZE +; cmp al,3 +; jnz Menuet_redraw_no_skin +; mov eax,48 +; mov ebx,4 +; int 0x40 +; mov dx,ax +;Menuet_redraw_no_skin: +; mov eax,7 +; mov ebx,esi +; int 0x40 + call @@MenuetOnDraw$qv +Menuet_redraw_end_draw: + mov eax,12 + mov ebx,2 + int 0x40 + pop edi + pop esi + pop ebx + pop ebp + ret +enddef + +define @Menuet@MoveWindow$qxpxi + push ebx + push esi + mov eax,[esp+12] + mov ebx,[eax] + mov ecx,[eax+4] + mov edx,[eax+8] + mov esi,[eax+12] + mov eax,67 + int 0x40 + pop esi + pop ebx + ret +enddef + +define @Menuet@Abort$qv + push dword [@Menuet@DebugPrefix] + call @Menuet@DebugPutString$qpxc + mov dword [esp],Menuet_abort_string + call @Menuet@DebugPutString$qpxc + pop ecx +nextdef @Menuet@ExitProcess$qv + lock bts dword [@Menuet@_ExitProcessNow],0 + jc Menuet_exit_process_wait + sub esp,1024 + mov eax,9 + mov ebx,esp + mov ecx,-1 + int 0x40 + mov esi,eax + mov edi,[esp+30] +Menuet_exit_process_loop: + mov eax,9 + mov ebx,esp + mov ecx,esi + int 0x40 + mov eax,[esp+30] + cmp eax,edi + jz Menuet_exit_process_continue + mov ebx,eax + or bl,15 + inc ebx + jz Menuet_exit_process_continue + mov ebx,eax + call Menuet_HashInt + movzx eax,al + mov eax,dword [@Menuet@_ThreadTable+eax*4] + jmp Menuet_exit_process_test +Menuet_exit_process_next: + mov eax,dword [eax+MENUET_THREAD_DATA_NEXT*4] +Menuet_exit_process_test: + test eax,eax + jz Menuet_exit_process_continue + cmp ebx,[eax+MENUET_THREAD_DATA_PID*4] + jnz Menuet_exit_process_next + mov eax,18 + mov ebx,2 + mov ecx,esi + int 0x40 +Menuet_exit_process_continue: + dec esi + jnl Menuet_exit_process_loop + add esp,1024 + mov dword [@Menuet@_ExitProcessNow],-1 +if defined EMULATOR + int3 + call 0x76543210 +end if +Menuet_exit_process_end: + mov dword [@Menuet@_ThreadMutex],0 + or eax,-1 + int 0x40 +Menuet_exit_process_wait: + mov eax,5 + mov ebx,1 +Menuet_exit_process_wait_loop: + cmp dword [@Menuet@_ExitProcessNow],0 + jl Menuet_exit_process_end + int 0x40 + shl ebx,1 + cmp ebx,MENUET_MUTEX_MAX_TIME_WAIT + jna Menuet_exit_process_wait_loop + mov ebx,MENUET_MUTEX_MAX_TIME_WAIT + jmp Menuet_exit_process_wait_loop +enddef + +define @Menuet@ExitThread$qppv,@Menuet@ThreadMain$qpvt1 + mov esp,[esp+4] + jmp Menuet_main_end +enddef + +define @Menuet@ReturnMessageLoop$qppv,@Menuet@ThreadMain$qpvt1 + mov esp,[esp+4] + bt dword [esp+MENUET_THREAD_DATA_FLAG*4],30 + jc Menuet_main_end + jmp Menuet_main_cycle +enddef + +define @Menuet@Delay$qui + push ebx + mov eax,5 + mov ebx,[esp+8] + int 0x40 + pop ebx + ret +enddef + +define @Menuet@Clock$qv + push ebx + mov eax,26 + mov ebx,9 + int 0x40 + pop ebx + ret +enddef + +define @Menuet@GetPackedTime$qv + mov eax,3 + int 0x40 + ret +enddef + +define @Menuet@GetTime$qpi + mov eax,3 + int 0x40 + mov edx,[esp+4] + movzx ecx,al + shr ecx,4 + and al,0x0F + imul ecx,10 + add cl,al + mov dword [edx+8],ecx + mov cl,ah + shr ecx,4 + and ah,0x0F + imul ecx,10 + add cl,ah + mov dword [edx+4],ecx + bswap eax + mov cl,ah + shr ecx,4 + and ah,0x0F + imul ecx,10 + add cl,ah + mov dword [edx],ecx + ret +enddef + +define @Menuet@GetPackedDate$qv + mov eax,29 + int 0x40 + ret +enddef + +define @Menuet@GetDate$qpi + mov eax,29 + int 0x40 + mov edx,[esp+4] + movzx ecx,al + shr ecx,4 + and al,0x0F + imul ecx,10 + add cl,al + mov dword [edx+4],ecx + mov cl,ah + shr ecx,4 + and ah,0x0F + imul ecx,10 + add cl,ah + mov dword [edx],ecx + bswap eax + mov cl,ah + shr ecx,4 + and ah,0x0F + imul ecx,10 + add cl,ah + mov dword [edx+8],ecx + ret +enddef + +define @Menuet@ReadCommonColors$qpui + push ebx + mov eax,48 + mov ebx,3 + mov ecx,[esp+8] + mov edx,40 + int 0x40 + pop ebx + ret +enddef + +define @Menuet@GetProcessInfo$qpuipct1t1piui + push ebx + push esi + push edi + sub esp,1024 + mov eax,9 + mov ebx,esp + mov ecx,[1024+12+24+esp] + int 0x40 + xor edi,edi + or edi,[1024+12+4+esp] + jz Menuet_get_proc_info_no_usecpu + mov ecx,[esp] + mov [edi],ecx + xor edi,edi +Menuet_get_proc_info_no_usecpu: + or edi,[1024+12+8+esp] + jz Menuet_get_proc_info_no_name + lea esi,[esp+10] + cld + movs dword [edi],[esi] + movs dword [edi],[esi] + movs dword [edi],[esi] + mov byte [edi],0 + xor edi,edi +Menuet_get_proc_info_no_name: + or edi,[1024+12+12+esp] + jz Menuet_get_proc_info_no_mem + mov ecx,[esp+26] + mov [edi],ecx + xor edi,edi +Menuet_get_proc_info_no_mem: + or edi,[1024+12+16+esp] + jz Menuet_get_proc_info_no_pid + mov ecx,[esp+30] + mov [edi],ecx + xor edi,edi +Menuet_get_proc_info_no_pid: + or edi,[1024+12+20+esp] + jz Menuet_get_proc_info_no_rect + lea esi,[esp+34] + cld + movs dword [edi],[esi] + movs dword [edi],[esi] + movs dword [edi],[esi] + movs dword [edi],[esi] + xor edi,edi +Menuet_get_proc_info_no_rect: + add esp,1024 + pop edi + pop esi + pop ebx + ret +enddef + +define @Menuet@GetPid$qv + push ebx + sub esp,1024 + mov eax,9 + mov ebx,esp + mov ecx,-1 + int 0x40 + mov eax,[esp+30] + add esp,1024 + pop ebx + ret +enddef + +define @Menuet@GetPid$qppv + mov ecx,[esp+4] + mov eax,[ecx+MENUET_THREAD_DATA_PID*4] + ret +enddef + +define @Menuet@_HashByte$qui +nextdef @Menuet@_HashWord$qui +nextdef @Menuet@_HashDword$qui + mov eax,[esp+4] +nextdef Menuet_HashInt + mul dword [Menuet_hash_int_val0] + xor eax,edx + bswap eax + mul dword [Menuet_hash_int_val1] + shrd eax,edx,14 + bswap eax + lea eax,[eax+4*eax] + ror eax,9 + ret +Menuet_hash_int_val0: + dd 0xA82F94C5 +Menuet_hash_int_val1: + dd 0x9193780B +enddef + +define @Menuet@GetThreadData$qv + call @Menuet@GetPid$qv + push eax + call @Menuet@GetThreadData$qui + pop ecx + ret +enddef + +define @Menuet@GetThreadData$qui + mov eax,[esp+4] + call Menuet_HashInt + movzx eax,al + cmp dword [@Menuet@_ThreadScanCount+4],0 + jnz Menuet_get_thread_data_wait +Menuet_get_thread_data_nowait: + lock inc dword [@Menuet@_ThreadScanCount] + mov eax,dword [@Menuet@_ThreadTable+eax*4] + mov ecx,[esp+4] + jmp Menuet_get_thread_data_test +Menuet_get_thread_data_loop: + mov eax,dword [eax+MENUET_THREAD_DATA_NEXT*4] +Menuet_get_thread_data_test: + test eax,eax + jz Menuet_get_thread_data_end + cmp ecx,[eax+MENUET_THREAD_DATA_PID*4] + jnz Menuet_get_thread_data_loop +Menuet_get_thread_data_end: + lock dec dword [@Menuet@_ThreadScanCount] + ret +Menuet_get_thread_data_wait: + push eax + push ebx + mov eax,5 + mov ebx,1 +Menuet_get_thread_data_wait_loop: + int 0x40 + cmp dword [@Menuet@_ThreadScanCount+4],0 + jz Menuet_get_thread_data_wait_end + shl ebx,1 + cmp ebx,MENUET_MUTEX_MAX_TIME_WAIT + jna Menuet_get_thread_data_wait_loop + mov ebx,MENUET_MUTEX_MAX_TIME_WAIT + jmp Menuet_get_thread_data_wait_loop +Menuet_get_thread_data_wait_end: + pop ebx + pop eax + jmp Menuet_get_thread_data_nowait +enddef + +define @Menuet@_GetSkinHeader$qv + push ebx + mov eax,48 + mov ebx,4 + int 0x40 + pop ebx + ret +enddef + +define @Menuet@GetScreenSize$qrust1 + mov eax,14 + int 0x40 + mov ecx,[esp+8] + mov word [ecx],ax + mov ecx,[esp+4] + shr eax,16 + mov word [ecx],ax + ret +enddef + +define Menuet_MutexLockNoWait + pop eax + xor al,al + ret +enddef + +define Menuet_MutexLockWait + push ebx + mov eax,5 + xor ebx,ebx +Menuet_lock_wait_cycle: + int 0x40 + shl byte [ecx],1 + jz Menuet_lock_wait_cycle + pop ebx + mov al,1 + ret +enddef + +define Menuet_MutexLockWaitTime + cmp dword [esp+12],0 + jng Menuet_MutexLockWait + push ebx + push edx + mov edx,[esp+20] + mov eax,26 + mov ebx,9 + int 0x40 + add edx,eax +Menuet_lock_wait_time_cycle: + mov eax,5 + xor ebx,ebx + int 0x40 + shl byte [ecx],1 + jnz Menuet_lock_wait_time_ret_true + mov eax,26 + mov ebx,9 + int 0x40 + cmp eax,edx + js Menuet_lock_wait_time_cycle + pop edx + pop ebx + pop eax + xor al,al + ret +Menuet_lock_wait_time_ret_true: + pop edx + pop ebx + mov al,1 + ret +enddef + +define Menuet_MutexLock + shl byte [ecx],1 + jnz Menuet_lock_first + call eax +Menuet_lock_first: + mov al,1 + ret +enddef + +define @Menuet@TryLock$qp13Menuet@TMutex + mov eax,Menuet_MutexLockNoWait + mov ecx,[esp+4] + jmp Menuet_MutexLock +enddef + +define @Menuet@Lock$qp13Menuet@TMutex + mov eax,Menuet_MutexLockWait + mov ecx,[esp+4] + jmp Menuet_MutexLock +enddef + +define @Menuet@LockTime$qp13Menuet@TMutexi + mov eax,Menuet_MutexLockWaitTime + mov ecx,[esp+4] + jmp Menuet_MutexLock +enddef + +define @Menuet@UnLock$qp13Menuet@TMutex + mov ecx,[esp+4] + shr byte [ecx],1 + jz Menuet_unlock_pause + ret +Menuet_unlock_pause: + mov byte [ecx],0x40 + push ebx + mov eax,5 + xor ebx,ebx + int 0x40 + pop ebx + ret +enddef + +define Menuet_MutexLockRec + shl byte [ecx],1 + jng Menuet_lock_first + cmp dword [ecx+4],edx + jz Menuet_lock_rec_self + call eax +Menuet_lock_rec_first: + mov al,1 + mov dword [ecx+4],edx + ret +Menuet_lock_rec_self: + mov al,1 + add dword [ecx],0x100 + jc Menuet_lock_rec_overflow + ret +Menuet_lock_rec_overflow: + push dword [@Menuet@DebugPrefix] + call @Menuet@DebugPutString$qpxc + mov dword [esp],Menuet_try_lock_rec_overflow_string + call @Menuet@DebugPutString$qpxc + pop ecx + jmp @Menuet@Abort$qv +enddef + +define @Menuet@TryLock$qp16Menuet@TRecMutexui + mov eax,Menuet_MutexLockNoWait + mov ecx,[esp+4] + mov edx,[esp+8] + jmp Menuet_MutexLockRec +enddef + +define @Menuet@Lock$qp16Menuet@TRecMutexui + mov eax,Menuet_MutexLockWait + mov ecx,[esp+4] + mov edx,[esp+8] + jmp Menuet_MutexLockRec +enddef + +define @Menuet@LockTime$qp16Menuet@TRecMutexiui + mov eax,Menuet_MutexLockWaitTime + mov ecx,[esp+4] + mov edx,[esp+12] + jmp Menuet_MutexLockRec +enddef + +define @Menuet@UnLock$qp16Menuet@TRecMutexui + mov ecx,[esp+4] + mov edx,[esp+8] + cmp dword [ecx+4],edx + jnz Menuet_unlock_rec_notlocked + sub dword [ecx],0x100 + jnc Menuet_unlock_rec_end + add dword [ecx],0x100 + shl byte [ecx],1 + shr byte [ecx],2 + jng Menuet_unlock_rec_pause +Menuet_unlock_rec_end: + ret +Menuet_unlock_rec_pause: + mov byte [ecx],0x20 + push ebx + mov eax,5 + xor ebx,ebx + int 0x40 + pop ebx + ret +Menuet_unlock_rec_notlocked: + push dword [@Menuet@DebugPrefix] + call @Menuet@DebugPutString$qpxc + mov dword [esp],Menuet_unlock_rec_notlocked_string + call @Menuet@DebugPutString$qpxc + pop ecx + jmp @Menuet@Abort$qv +enddef + +define @Menuet@DebugPutChar$qc + mov cl,byte [esp+4] + cmp cl,13 + jz Menuet_debug_put_char_ret + push ebx + cmp cl,10 + jz Menuet_debug_put_char_enter +Menuet_debug_put_char_after_cmp: + mov eax,63 + mov ebx,1 + int 0x40 + pop ebx +Menuet_debug_put_char_ret: + ret +Menuet_debug_put_char_enter: + mov cl,13 + mov eax,63 + mov ebx,1 + int 0x40 + mov cl,10 + jmp Menuet_debug_put_char_after_cmp +enddef + +define @Menuet@DebugPutString$qpxc + push esi + push dword 0 + mov esi,dword [esp+12] + jmp Menuet_debug_put_string_test +Menuet_debug_put_string_loop: + mov dword [esp],eax + call @Menuet@DebugPutChar$qc + inc esi +Menuet_debug_put_string_test: + xor eax,eax + or al,[esi] + test al,al + jnz Menuet_debug_put_string_loop + pop ecx + pop esi + ret +enddef + +define @Menuet@GetKey$qv + mov eax,2 + int 0x40 + test al,al + jnz Menuet_get_key_eof + movzx eax,ah + ret +Menuet_get_key_eof: + mov eax,-1 + ret +enddef + +define @Menuet@GetMouseButton$qv + push ebx + mov eax,37 + mov ebx,2 + int 0x40 + pop ebx + ret +enddef + +define @Menuet@GetMousePosition$qrst1o + push ebx + mov eax,37 + xor ebx,ebx + cmp byte [esp+16],0 + jnz Menuet_get_mouse_pos_absolute + inc ebx +Menuet_get_mouse_pos_absolute: + int 0x40 + mov ecx,[esp+12] + mov word [ecx],ax + mov ecx,[esp+8] + shr eax,16 + mov word [ecx],ax + pop ebx + ret +enddef + +define @Menuet@WasThreadCreated$qv + cmp byte [@Menuet@_ThreadSavedBegProc],0x90 + setz al + ret +enddef + +define @Menuet@CreateThread$qpvuit1 + push ebx + mov edx,[esp+16] + mov ebx,[esp+12] + test edx,edx + jnz Menuet_create_thread_after_new +if defined MenuetHeapAlloc + cmp ebx,4096 + jnb Menuet_create_thread_alloc + mov ebx,STACKSIZE +Menuet_create_thread_alloc: + push ebx + call MenuetHeapAlloc ; Create new dynamic memory of the given size + pop ecx + test eax,eax + jnz Menuet_create_thread_mem_created +end if + or eax,-1 + jmp Menuet_create_thread_end +Menuet_create_thread_mem_created: + lea edx,[eax+ebx] +Menuet_create_thread_after_new: + neg ebx + jz Menuet_create_thread_test_first + add ebx,edx +Menuet_create_thread_test_first: + cmp byte [@Menuet@_ThreadSavedBegProc],0x90 + jnz Menuet_create_thread_init +Menuet_create_thread_fill_stack: + lock inc dword [@Menuet@_ThreadNumber] + and edx,not 3 + sub edx,12 + mov ecx,[esp+8] + mov dword [edx+8],ebx + mov dword [edx+4],ecx + mov dword [edx],Menuet_ThreadFinish + mov eax,51 + mov ebx,1 + mov ecx,@Menuet@ThreadMain$qpvt1 + int 0x40 + mov ebx,eax + or bl,15 + inc ebx + jnz Menuet_create_thread_end + lock dec dword [@Menuet@_ThreadNumber] +if defined MenuetHeapFree + or ebx,[edx+8] + jz Menuet_create_thread_end + push ebx + call MenuetHeapFree ; Delete the given dynamic memory + pop ecx +end if +Menuet_create_thread_end: + pop ebx + ret +Menuet_create_thread_init: + push esi + push edi + cld + mov esi,@Menuet@_ThreadSavedBegProc + mov edi,@Menuet@GetPid$qv + movs dword [edi],[esi] + movs dword [edi],[esi] + mov edi,@Menuet@GetThreadData$qv + movs dword [edi],[esi] + movs dword [edi],[esi] + mov eax,0x90909090 + mov edi,@Menuet@_ThreadSavedBegProc + stos dword [edi] + stos dword [edi] + stos dword [edi] + stos dword [edi] + pop edi + pop esi + jmp Menuet_create_thread_fill_stack +enddef + +define @Menuet@_FileAccess$qpv + push ebx + mov eax,58 + mov ebx,[esp+8] + int 0x40 + mov ecx,[esp+8] + mov [ecx],ebx + pop ebx + cmp eax,5 + jz Menuet_file_access_ret_zero + ret +Menuet_file_access_ret_zero: + xor eax,eax + ret +enddef + +__pure_error_: + jmp $ + +define Menuet_abort_string + db 'Abnormal program termination.',10,0 +newdef Menuet_try_lock_rec_overflow_string + db 'Recursive mutex lock count overflow.',10,0 +newdef Menuet_unlock_rec_notlocked_string + db 'Recursive mutex unlock error.',10,0 +enddef + +include "me_lib.inc" + +;/**/ + diff --git a/programs/games/checkers/trunk/include/me_heap.h b/programs/games/checkers/trunk/include/me_heap.h new file mode 100644 index 0000000000..5954d8edfc --- /dev/null +++ b/programs/games/checkers/trunk/include/me_heap.h @@ -0,0 +1,90 @@ +#ifndef __MENUET_HEAP_H_INCLUDED_ +#define __MENUET_HEAP_H_INCLUDED_ + +#include +#include + +// Menuet memory heap interface. + +namespace Menuet // All menuet functions, types and data are nested in the (Menuet) namespace. +{ + void *Alloc(unsigned int size); + void *ReAlloc(void *mem, unsigned int size); + void Free(void *mem); +} + +#ifdef __MENUET__ + +namespace Menuet +{ + +// Global variables + + MemoryHeap::TFreeSpace _MenuetFreeSpace; + MemoryHeap::TMemBlock _MenuetMemBlock; + TMutex _MemHeapMutex = MENUET_MUTEX_INIT; + +// Functions + + void *_HeapInit(void *begin, void *use_end, void *end) + { + MemoryHeap::InitFreeSpace(_MenuetFreeSpace); + _MenuetMemBlock = MemoryHeap::CreateBlock(begin, end, _MenuetFreeSpace); + unsigned int use_beg = (unsigned int)MemoryHeap::BlockBegin(_MenuetMemBlock) + + MemoryHeap::BlockAddSize - MemoryHeap::BlockEndSize; + unsigned int use_size = (unsigned int)use_end; + if (use_size <= use_beg) return 0; + else use_size -= use_beg; + return MemoryHeap::Alloc(_MenuetFreeSpace, use_size); + } + + bool _SetUseMemory(unsigned int use_mem); + + int _RecalculateUseMemory(unsigned int use_mem); + + void *Alloc(unsigned int size) + { + if (!size) return 0; + Lock(&_MemHeapMutex); + void *res = MemoryHeap::Alloc(_MenuetFreeSpace, size); + if (!res) + { + unsigned use_mem = (unsigned int)MemoryHeap::BlockEndFor(_MenuetMemBlock, size); + if (_SetUseMemory(_RecalculateUseMemory(use_mem))) + { + res = MemoryHeap::Alloc(_MenuetFreeSpace, size); + } + } + UnLock(&_MemHeapMutex); + return res; + } + + void *ReAlloc(void *mem, unsigned int size) + { + Lock(&_MemHeapMutex); + void *res = MemoryHeap::ReAlloc(_MenuetFreeSpace, mem, size); + if (!res && size) + { + unsigned use_mem = (unsigned int)MemoryHeap::BlockEndFor(_MenuetMemBlock, size); + if (_SetUseMemory(_RecalculateUseMemory(use_mem))) + { + res = MemoryHeap::ReAlloc(_MenuetFreeSpace, mem, size); + } + } + UnLock(&_MemHeapMutex); + return res; + } + + void Free(void *mem) + { + Lock(&_MemHeapMutex); + MemoryHeap::Free(_MenuetFreeSpace, mem); + UnLock(&_MemHeapMutex); + } + + void _FreeAndThreadFinish(void *mem, int *exit_proc_now); +} + +#endif // def __MENUET__ + +#endif // ndef __MENUET_HEAP_H_INCLUDED_ diff --git a/programs/games/checkers/trunk/include/me_heap.inc b/programs/games/checkers/trunk/include/me_heap.inc new file mode 100644 index 0000000000..6a32667508 --- /dev/null +++ b/programs/games/checkers/trunk/include/me_heap.inc @@ -0,0 +1,284 @@ +;/*** + +MenuetHeapInit = @@Menuet@_HeapInit$qpvt1t1 + +MenuetHeapAlloc = @@Menuet@Alloc$qui + +MenuetHeapReAlloc = @@Menuet@ReAlloc$qpvui + +MenuetHeapFree = @@Menuet@Free$qpv + +MenuetHeapFreeAndThreadFinish = @Menuet@_FreeAndThreadFinish$qpvpi + +define @Menuet@_SetUseMemory$qui + push ebx + mov eax,64 + mov ebx,1 + mov ecx,[esp+8] + int 0x40 + pop ebx + test eax,eax + jnz Menuet_set_use_memory_nomem + push ecx + push dword [@Menuet@_MenuetMemBlock] + call @@MemoryHeap@ResizeBlock$q20MemoryHeap@TMemBlockpv + add esp,8 + mov al,1 + ret +Menuet_set_use_memory_nomem: + xor al,al + ret +enddef + +define @Menuet@_RecalculateUseMemory$qui + mov eax,dword [esp+4] + mov ecx,(U_END + 3) and not 3 + cmp eax,ecx + jna Menuet_recalculate_use_memory_min + push ebx + sub eax,ecx + mov ebx,6 + mul ebx + dec ebx + div ebx + add eax,((U_END + 3) and not 3) + 3 + and eax,not 3 + pop ebx + ret +Menuet_recalculate_use_memory_min: + mov eax,ecx + ret +enddef + +define @Menuet@_FreeAndThreadFinish$qpvpi + mov ebx,1 + mov ecx,[esp+8] + jmp Menuet_heap_free_tf_wait +Menuet_heap_free_tf_wait_loop: + mov eax,5 + int 0x40 + shl ebx,1 + cmp ebx,MENUET_MUTEX_MAX_TIME_WAIT + jna Menuet_heap_free_tf_wait + mov ebx,MENUET_MUTEX_MAX_TIME_WAIT +Menuet_heap_free_tf_wait: + cmp dword [ecx],0 + jnz @Menuet@ExitProcess$qv + lock bts dword [@Menuet@_MemHeapMutex],0 + jc Menuet_heap_free_tf_wait_loop + push dword [esp+4] + push @Menuet@_MenuetFreeSpace + call @@MemoryHeap@Free$qr21MemoryHeap@TFreeSpacepv + add esp,8 + mov byte [@Menuet@_MemHeapMutex],0x40 + or eax,-1 + int 0x40 +enddef + +macro call func +{ + if func eq @MemoryHeap@_FirstNotZeroBit$qui + bsf eax,[esp] + else if func eq @MemoryHeap@_CopyMemItemArray$quiuiui + xchg edi,[esp] + xchg esi,[esp+4] + mov ecx,[esp+8] + cld + sub ecx,esi + shr ecx,2 + rep movs dword [edi],[esi] + xchg edi,[esp] + xchg esi,[esp+4] + else + call func + end if +} + +@$bnwa$qui = @@Menuet@Alloc$qui +@$bnew$qui = @@Menuet@Alloc$qui + +@$bdla$qpv = @@Menuet@Free$qpv +@$bdele$qpv = @@Menuet@Free$qpv + +define @_vector_new_ldtc_$qpvuiuiuit1uit1 +.var_2C = -0Ch +.var_28 = -8 +.var_24 = -4 +.arg_0 = 8 +.arg_4 = 0Ch +.arg_8 = 10h +.arg_C = 14h +.arg_10 = 18h + push ebp + mov ebp, esp + add esp, -0Ch + push ebx + push esi + push edi + mov edi, [ebp+.arg_10] + mov esi, [ebp+.arg_C] + cmp dword [ebp+.arg_0], 0 + jnz .loc_10070 + mov edx, [ebp+.arg_4] + imul edx, [ebp+.arg_8] + test esi, 10h + jz @f + add edx, 4 +@@: + push edx + call @$bnwa$qui + pop ecx + mov [ebp+.arg_0], eax + test eax, eax + jz .ret + mov dword [ebp+.var_2C], 1 + jmp @f +.loc_10070: + and dword [ebp+.var_2C], 0 +@@: + test esi, 10h + jz @f + mov edx, [ebp+.arg_0] + mov ecx, [ebp+.arg_8] + mov [edx], ecx + add dword [ebp+.arg_0], 4 +@@: + mov eax, [ebp+.arg_0] + test edi, edi + jz .ret + mov ecx, [ebp+.arg_8] + mov [ebp+.var_28], ecx + mov ebx, eax + jmp .loc_100EF +.loc_100B0: + mov eax, esi + and eax, 7 + dec eax + jz .loc_100CB + dec eax + jz .loc_100D1 + dec eax + jz .loc_100D6 + dec eax + dec eax + jz .loc_100DC + jmp $ +.loc_100CB: + push ebx + call edi + pop ecx + jmp .loc_100EC +.loc_100D1: +.loc_100DC: + push ebx + call edi + jmp .loc_100EC +.loc_100D6: + mov eax, ebx + call edi +.loc_100EC: + add ebx, [ebp+.arg_4] +.loc_100EF: + dec dword [ebp+.var_28] + jns .loc_100B0 + mov eax, [ebp+.arg_0] +.ret: + pop edi + pop esi + pop ebx + mov esp, ebp + pop ebp + ret +enddef + +define @_vector_delete_ldtc_$qpvuiuiuit1 +.arg_0 = 8 +.arg_4 = 0Ch +.arg_8 = 10h +.arg_C = 14h +.arg_10 = 18h + push ebp + mov ebp, esp + push ebx + push esi + push edi + mov edi, [ebp+.arg_C] + mov esi, edi + and esi, 10h + and edi, 8 + cmp dword [ebp+.arg_0], 0 + jz .ret + test esi, esi + jz @f + mov ecx, [ebp+.arg_0] + mov eax, [ecx-4] + mov [ebp+.arg_8], eax +@@: + mov ebx, [ebp+.arg_8] + dec ebx + imul ebx, [ebp+.arg_4] + add ebx, [ebp+.arg_0] + jmp .loc_100D3 +.loc_1008B: + mov eax, [ebp+.arg_C] + and eax, 7 + dec eax + jz .loc_1009E + dec eax + jz .loc_100A9 + dec eax + jz .loc_100B1 + dec eax + dec eax + jz .loc_100BD + jmp $ +.loc_1009E: + push 2 + push ebx + call dword [ebp+.arg_10] + add esp, 8 + jmp .loc_100D0 +.loc_100A9: + push 2 + push ebx + call dword [ebp+.arg_10] + jmp .loc_100D0 +.loc_100B1: + mov edx, 2 + mov eax, ebx + call dword [ebp+.arg_10] + jmp .loc_100D0 +.loc_100BD: + push 2 + push ebx + call dword [ebp+.arg_10] +.loc_100D0: + sub ebx, [ebp+.arg_4] +.loc_100D3: + dec dword [ebp+.arg_8] + jns .loc_1008B + test esi, esi + jz @f + sub dword [ebp+.arg_0], 4 +@@: + test edi, edi + jz @f + push dword [ebp+.arg_0] + call @$bdla$qpv + pop ecx + jmp .ret +@@: + mov eax, [ebp+.arg_0] + jmp .reteax +.ret: + xor eax, eax +.reteax: + pop edi + pop esi + pop ebx + mov esp, ebp + pop ebp + ret +enddef + +;/**/ diff --git a/programs/games/checkers/trunk/include/me_lib.h b/programs/games/checkers/trunk/include/me_lib.h new file mode 100644 index 0000000000..48cebb6c7b --- /dev/null +++ b/programs/games/checkers/trunk/include/me_lib.h @@ -0,0 +1,16 @@ +#ifndef __MENUET_LIB_H_INCLUDED_ +#define __MENUET_LIB_H_INCLUDED_ + +// Menuet interface. + +namespace Menuet // All menuet functions, types and data are nested in the (Menuet) namespace. +{ + unsigned int StrLen(const char *str); + char *StrCopy(char *dest, const char *src); + void *MemCopy(void *dest, const void *src, unsigned int n); + void *MemSet(void *s, char c, unsigned int n); + + double Floor(double x); +} + +#endif // __MENUET_LIB_H_INCLUDED_ diff --git a/programs/games/checkers/trunk/include/me_lib.inc b/programs/games/checkers/trunk/include/me_lib.inc new file mode 100644 index 0000000000..7be9ab3fac --- /dev/null +++ b/programs/games/checkers/trunk/include/me_lib.inc @@ -0,0 +1,118 @@ +define @Menuet@StrLen$qpxc + push edi + cld + mov edi,[esp+8] + mov ecx,-1 + xor al,al + repnz scas byte [edi] + not ecx + lea eax,[ecx-1] + pop edi + ret +enddef + +define @Menuet@StrCopy$qpcpxc + push esi + push edi + cld + mov edi,[esp+16] + mov ecx,-1 + mov esi,edi + xor al,al + repnz scas byte [edi] + not ecx + mov edi,[esp+12] + mov edx,ecx + mov eax,edi + shr ecx,2 + rep movs dword [edi],[esi] + mov ecx,edx + and ecx,3 + rep movs byte [edi],[esi] + pop edi + pop esi + ret +enddef + +define @Menuet@MemCopy$qpvpxvui + push esi + push edi + cld + mov edi,[esp+12] + mov eax,edi + mov ecx,[esp+20] + mov esi,[esp+16] + mov edx,ecx + shr ecx,2 + rep movs dword [edi],[esi] + mov ecx,edx + and ecx,3 + rep movs byte [edi],[esi] + pop edi + pop esi + ret +enddef + +define @Menuet@MemSet$qpvcui + push edi + cld + mov edi,[esp+8] + mov al,[esp+12] + mov ah,al + mov dx,ax + shl eax,16 + mov ax,dx + mov ecx,[esp+16] + mov edx,ecx + shr ecx,2 + rep stos dword [edi] + mov ecx,edx + and ecx,3 + rep stos byte [edi] + pop edi + mov eax,[esp+4] + ret +enddef + +define __ftol + sub esp,12 + wait + fstcw word [esp+8] + wait + mov al,[esp+9] + or byte [esp+9],0x0c + fldcw word [esp+8] + fistp qword [esp] + mov [esp+9],al + fldcw word [esp+8] + mov eax,[esp] + mov edx,[esp+4] + add esp,12 + ret +enddef + +define @Menuet@Floor$qd + fld qword [esp+4] + mov ax,[esp+10] + shl ax,1 + cmp ax,0x8680 + ja Menuet_floor_end + mov ch,4 + sub esp,2 + wait + fstcw word [esp] + mov ax,0xf3ff + wait + mov dx,[esp] + and ax,dx + or ah,ch + mov [esp],ax + fldcw word [esp] + frndint + mov [esp],dx + fldcw word [esp] + add esp,2 +Menuet_floor_end: + ret +enddef + diff --git a/programs/games/checkers/trunk/include/me_start.inc b/programs/games/checkers/trunk/include/me_start.inc new file mode 100644 index 0000000000..36e1bcf24b --- /dev/null +++ b/programs/games/checkers/trunk/include/me_start.inc @@ -0,0 +1,90 @@ +use32 +org 0x0 + db 'MENUET01' + dd 0x1 + dd MenuetEntryPoint + dd I_END + dd U_END+STACKSIZE+HEAPSIZE + dd U_END+STACKSIZE + dd 0x0,0x0 + +ptr equ +offset equ +short equ +tbyte equ tword + +PTR equ +OFFSET equ +SHORT equ +TBYTE equ TWORD + +macro movsb a,b +{ + if a eq & b eq + movsb + else + movsx a,b + end if +} + +macro movsw a,b +{ + if a eq & b eq + movsw + else + movsx a,b + end if +} + +macro segment name {} + +macro endseg name {} + +macro usedef [link] +{ + common + if ~link eq + virtual at 0 + forward + dd link + common + end virtual + end if +} + +macro define x,[link] +{ + common + if x eq + else if used x + x: + usedef link +} + +macro enddef [link] +{ + common + usedef link + end if +} + +macro newdef x,[link] +{ + common + end if + if x eq + else if used x + x: + usedef link +} + +macro nextdef x,[link] +{ + common + usedef x + end if + if x eq + else if used x + x: + usedef link +} diff --git a/programs/games/checkers/trunk/include/memheap.h b/programs/games/checkers/trunk/include/memheap.h new file mode 100644 index 0000000000..bf8aa101fc --- /dev/null +++ b/programs/games/checkers/trunk/include/memheap.h @@ -0,0 +1,626 @@ +#ifndef __MEMORY_HEAP_RBTREE_H_INCLUDED_ +#define __MEMORY_HEAP_RBTREE_H_INCLUDED_ + +namespace MemoryHeap +{ + typedef unsigned int TMemItem; + + enum {NumTreeSmall = 8 * sizeof(TMemItem)}; + +// Memory heap interface. + + struct TFreeSpace + { + TMemItem Small[NumTreeSmall], Min, SmallMask; + }; + + struct TMemBlock + { + TMemItem *Begin; + }; + + bool BlockValid(const TMemBlock &block); // Is the given memory block valid? + void *BlockBegin(const TMemBlock &block); // Return the beginning address of the block. + void *BlockEnd(const TMemBlock &block); // Return the ending address of the block. + TFreeSpace &BlockFreeSpace(const TMemBlock &block); // Return the free space of the block. + + void InitFreeSpace(TFreeSpace &fs); // Initialize the free space. + TMemBlock NullBlock(); // Return null invalid block. + TMemBlock CreateBlock(void *begin, void *end, TFreeSpace &fs); + // Create a memory block with the given begin and end and add free space of it to (fs), + //_ give (BlockAddSize) bytes of the block for it's data. + //_ (Program can alloc (end - begin - BlockAddSize) bytes after it, + //_ that must be not less than (MemMinSize) ). + TMemBlock CreateBlock(void *begin, void *end); + // Create a memory block with the given begin and end and new free space for it, + //_ give (BlockAddSizeFS) bytes of the block for it's data. + //_ (Program can alloc (end - begin - BlockAddSizeFS) bytes after it, + //_ that must be not less than (MemMinSize) ). + void ResizeBlock(TMemBlock block, void *new_end); // Resize the memory block to the given new end. + void RemoveBlock(TMemBlock block); // Remove the given memory block. + + void *BlockEndFor(TMemBlock block, unsigned int size); + // Return the new end of the block needed for (ResizeBlock) to alloc the given size of memory. + unsigned int BlockSize(TMemBlock block); // Return the size of the given block. + unsigned int MemSize(void *mem); // Return the size of the allocced memory. + + void *Alloc(TFreeSpace &fs, unsigned int size); + // Alloc a memory in the given free space, give (MemAddSize) bytes for it's data. + void *ReAlloc(TFreeSpace &fs, unsigned int size, void *mem); + // ReAlloc the given memory, it must lie in the block with the given free space. + void Free(TFreeSpace &fs, void *mem); + // Free the given memory, it must lie in the block with the given free space. + +// Macro definitions. + +#define MEMORY_HEAP_ALIGN_DOWN(s) (MemoryHeap::TMemItem(s) & ~(MemoryHeap::MemAlign - 1)) +#define MEMORY_HEAP_ALIGN_UP(s) ((MemoryHeap::TMemItem(s) + (MemoryHeap::MemAlign - 1)) & ~(MemoryHeap::MemAlign - 1)) +#define MEMORY_HEAP_ITEM(s,k) ( ((MemoryHeap::TMemItem*)(s))[(k)] ) +#define MEMORY_HEAP_NEXT(s) (MEMORY_HEAP_ITEM((s),-1)) +#define MEMORY_HEAP_PREV(s) (MEMORY_HEAP_ITEM((s),-2)) +#define MEMORY_HEAP_FREE(s) (MEMORY_HEAP_ITEM((s),-1) & 1) + +// Constants. + + enum {MemAlign = sizeof(TMemItem)}; + enum {MemAddSize = MEMORY_HEAP_ALIGN_UP(2 * sizeof(TMemItem))}; + enum {BlockEndSize = MemAddSize}; + enum {BlockAddSize = MEMORY_HEAP_ALIGN_UP(4 * sizeof(TMemItem)) + BlockEndSize}; + enum {BlockAddSizeFS = BlockAddSize + BlockEndSize + MEMORY_HEAP_ALIGN_UP(sizeof(TFreeSpace))}; + enum {MemMinSize = MEMORY_HEAP_ALIGN_UP(2 * sizeof(TMemItem))}; + +// Inline functions. + + inline bool BlockValid(const TMemBlock &block) {return block.Begin != 0;} + + inline void *BlockBegin(const TMemBlock &block) {return (void*)block.Begin;} + + inline void *BlockEnd(const TMemBlock &block) {return block.Begin ? (void*)block.Begin[1] : 0;} + + inline TFreeSpace &BlockFreeSpace(const TMemBlock &block) {return *(TFreeSpace*)block.Begin[0];} + + inline TMemBlock NullBlock() {TMemBlock block; block.Begin = 0; return block;} + + inline void *BlockEndFor(TMemBlock block, unsigned int size) + { + TMemItem last = (TMemItem)block.Begin[1]; + TMemItem prevlast = MEMORY_HEAP_PREV(last); + return (void*)( (MEMORY_HEAP_FREE(prevlast) ? prevlast : last) + MemAddSize + + ((size <= MemMinSize) ? MemMinSize : MEMORY_HEAP_ALIGN_UP(size)) ); + } + + inline unsigned int BlockSize(TMemBlock block) + { + if (!block.Begin) return 0; + return (unsigned int)(block.Begin[1] - (TMemItem)block.Begin); + } + + inline unsigned int MemSize(void *mem) + { + if (!mem) return 0; + TMemItem c = (TMemItem)mem; + return MEMORY_HEAP_NEXT(c) - c - MemAddSize; + } + +// Free space item functions. + + TMemItem _FirstNotZeroBit(TMemItem i) + { + TMemItem r = 0; + while ((i >>= 1) != 0) r++; + return r; + } + + void _RBTreeRotate(TMemItem parent, TMemItem item, int side) + { + TMemItem temp = MEMORY_HEAP_ITEM(parent,0); + MEMORY_HEAP_ITEM(item,0) = temp; + if (temp) + { + if (MEMORY_HEAP_ITEM(temp,2) == parent) + { + MEMORY_HEAP_ITEM(temp,2) = item; + } + else MEMORY_HEAP_ITEM(temp,3) = item; + } + temp = MEMORY_HEAP_ITEM(item,side^1); + if (temp) MEMORY_HEAP_ITEM(temp,0) = parent; + MEMORY_HEAP_ITEM(parent,side) = temp; + MEMORY_HEAP_ITEM(parent,0) = item; + MEMORY_HEAP_ITEM(item,side^1) = parent; + temp = MEMORY_HEAP_ITEM(parent,1); + MEMORY_HEAP_ITEM(parent,1) = MEMORY_HEAP_ITEM(item,1); + MEMORY_HEAP_ITEM(item,1) = temp; + } + + void InitFreeSpace(TFreeSpace &fs) + { + TMemItem i; + for (i = 0; i <= NumTreeSmall; i++) fs.Small[i] = 0; + fs.Min = 0; fs.SmallMask = 0; + } + + void _FreeAdd(TFreeSpace &fs, TMemItem item) + { + TMemItem size = MEMORY_HEAP_NEXT(item) - item; + if (size < MemAddSize + MemMinSize + MemAlign * NumTreeSmall) + { + TMemItem s = (size - (MemAddSize + MemMinSize)) / MemAlign; + TMemItem &addto = fs.Small[s]; + MEMORY_HEAP_ITEM(item,1) = (TMemItem)(&addto); + MEMORY_HEAP_ITEM(item,0) = (TMemItem)addto; + if (addto) MEMORY_HEAP_ITEM(addto,1) = item; + addto = item; + fs.SmallMask |= TMemItem(1) << s; + return; + } + TMemItem addto = fs.Min, parent, temp; + MEMORY_HEAP_ITEM(item,2) = 0; + MEMORY_HEAP_ITEM(item,3) = 0; + if (!addto) + { + MEMORY_HEAP_ITEM(item,0) = 0; + MEMORY_HEAP_ITEM(item,1) = 1; + fs.Min = item; + return; + } + MEMORY_HEAP_ITEM(item,1) = 0; + TMemItem side = 2; + if (MEMORY_HEAP_NEXT(addto) - addto >= size) fs.Min = item; + else + { + for (;;) + { + parent = MEMORY_HEAP_ITEM(addto,0); + if (!parent) break; + if (MEMORY_HEAP_NEXT(parent) - parent < size) addto = parent; + else break; + } + for (;;) + { + if (MEMORY_HEAP_NEXT(addto) - addto < size) + { + temp = MEMORY_HEAP_ITEM(addto,3); + if (!temp) {side = 3; break;} + addto = temp; + } + else + { + temp = MEMORY_HEAP_ITEM(addto,2); + if (!temp) break; + addto = temp; + } + } + } + MEMORY_HEAP_ITEM(item,0) = addto; + MEMORY_HEAP_ITEM(addto,side) = item; + for (;;) + { + if (MEMORY_HEAP_ITEM(addto,1) != 0) return; + parent = MEMORY_HEAP_ITEM(addto,0); + temp = MEMORY_HEAP_ITEM(parent,2); + if (temp == addto) + { + temp = MEMORY_HEAP_ITEM(parent,3); + side = 2; + } + else side = 3; + if (!temp || MEMORY_HEAP_ITEM(temp,1) != 0) break; + MEMORY_HEAP_ITEM(addto,1) = 1; + MEMORY_HEAP_ITEM(temp,1) = 1; + item = parent; + addto = MEMORY_HEAP_ITEM(item,0); + if (!addto) return; + MEMORY_HEAP_ITEM(item,1) = 0; + } + if (MEMORY_HEAP_ITEM(addto,side) != item) + { + temp = MEMORY_HEAP_ITEM(item,side); + if (temp) MEMORY_HEAP_ITEM(temp,0) = addto; + MEMORY_HEAP_ITEM(addto,side^1) = temp; + MEMORY_HEAP_ITEM(addto,0) = item; + MEMORY_HEAP_ITEM(item,side) = addto; + MEMORY_HEAP_ITEM(item,0) = parent; + MEMORY_HEAP_ITEM(parent,side) = item; + } + else item = addto; + _RBTreeRotate(parent, item, side); + } + + void _FreeDel(TFreeSpace &fs, TMemItem item) + { + TMemItem size = MEMORY_HEAP_NEXT(item) - item; + if (size < MemAddSize + MemMinSize + MemAlign * NumTreeSmall) + { + TMemItem prev = MEMORY_HEAP_ITEM(item,1); + TMemItem next = MEMORY_HEAP_ITEM(item,0); + MEMORY_HEAP_ITEM(prev,0) = next; + if (next) MEMORY_HEAP_ITEM(next,1) = prev; + else + { + TMemItem s = (size - (MemAddSize + MemMinSize)) / MemAlign; + if (!fs.Small[s]) fs.SmallMask &= ~(TMemItem(1) << s); + } + return; + } + TMemItem parent, temp, second, add; + TMemItem side = 2; + temp = MEMORY_HEAP_ITEM(item,3); + if (temp) + { + for (;;) + { + second = temp; + temp = MEMORY_HEAP_ITEM(temp,2); + if (!temp) break; + } + if (fs.Min == item) fs.Min = second; + add = MEMORY_HEAP_ITEM(second,3); + parent = MEMORY_HEAP_ITEM(second,0); + if (parent == item) {parent = second; side = 3;} + else + { + temp = MEMORY_HEAP_ITEM(item,3); + MEMORY_HEAP_ITEM(second,3) = temp; + MEMORY_HEAP_ITEM(temp,0) = second; + } + temp = MEMORY_HEAP_ITEM(item,2); + MEMORY_HEAP_ITEM(second,2) = temp; + if (temp) MEMORY_HEAP_ITEM(temp,0) = second; + temp = MEMORY_HEAP_ITEM(item,0); + MEMORY_HEAP_ITEM(second,0) = temp; + if (temp) + { + if (MEMORY_HEAP_ITEM(temp,2) == item) + { + MEMORY_HEAP_ITEM(temp,2) = second; + } + else MEMORY_HEAP_ITEM(temp,3) = second; + } + MEMORY_HEAP_ITEM(parent,side) = add; + if (add) MEMORY_HEAP_ITEM(add,0) = parent; + bool color = MEMORY_HEAP_ITEM(second,1); + MEMORY_HEAP_ITEM(second,1) = MEMORY_HEAP_ITEM(item,1); + if (!color) return; + } + else + { + if (fs.Min == item) fs.Min = MEMORY_HEAP_ITEM(item,0); + add = MEMORY_HEAP_ITEM(item,2); + parent = MEMORY_HEAP_ITEM(item,0); + if (add) MEMORY_HEAP_ITEM(add,0) = parent; + if (parent) + { + if (MEMORY_HEAP_ITEM(parent,2) == item) + { + MEMORY_HEAP_ITEM(parent,2) = add; + } + else + { + MEMORY_HEAP_ITEM(parent,3) = add; + side = 3; + } + } + else + { + if (add) MEMORY_HEAP_ITEM(add,1) = 1; + return; + } + if (!MEMORY_HEAP_ITEM(item,1)) return; + } + if (add && !MEMORY_HEAP_ITEM(add,1)) + { + MEMORY_HEAP_ITEM(add,1) = 1; + return; + } + for (;;) + { + second = MEMORY_HEAP_ITEM(parent,side^1); + if (!MEMORY_HEAP_ITEM(second,1)) + { + _RBTreeRotate(parent, second, side^1); + second = MEMORY_HEAP_ITEM(parent,side^1); + } + temp = MEMORY_HEAP_ITEM(second,side^1); + if (temp && !MEMORY_HEAP_ITEM(temp,1)) + { + MEMORY_HEAP_ITEM(temp,1) = 1; + break; + } + temp = MEMORY_HEAP_ITEM(second,side); + if (temp && !MEMORY_HEAP_ITEM(temp,1)) + { + _RBTreeRotate(second, temp, side); + MEMORY_HEAP_ITEM(second,1) = 1; + second = temp; + break; + } + MEMORY_HEAP_ITEM(second,1) = 0; + if (!MEMORY_HEAP_ITEM(parent,1)) + { + MEMORY_HEAP_ITEM(parent,1) = 1; + return; + } + second = parent; + parent = MEMORY_HEAP_ITEM(second,0); + if (!parent) return; + if (MEMORY_HEAP_ITEM(parent,2) == second) side = 2; + else side = 3; + } + _RBTreeRotate(parent, second, side^1); + } + + TMemItem _FreeFindAfter(TMemItem item, TMemItem size) + { + if (!item) return 0; + TMemItem paritem, s; + if (MEMORY_HEAP_NEXT(item) - item >= size) return item; + for (;;) + { + paritem = MEMORY_HEAP_ITEM(item,0); + if (!paritem) break; + s = MEMORY_HEAP_NEXT(paritem) - paritem; + if (s == size) return paritem; + if (s < size) item = paritem; + else break; + } + MEMORY_HEAP_ITEM(item,3); + for (;;) + { + if (!item) return paritem; + s = MEMORY_HEAP_NEXT(item) - item; + if (s == size) return item; + if (s < size) item = MEMORY_HEAP_ITEM(item,3); + else + { + paritem = item; + item = MEMORY_HEAP_ITEM(item,2); + } + } + } + + TMemItem _FreeFind(TFreeSpace &fs, TMemItem size) + { + TMemItem item, nextitem, s; + if (size < MemAddSize + MemMinSize + MemAlign * NumTreeSmall) + { + TMemItem m, t; + s = (size - (MemAddSize + MemMinSize)) / MemAlign; + item = fs.Small[s]; + if (item) return item; + if (size < MemAlign * NumTreeSmall) + { + t = size / MemAlign; + m = fs.SmallMask >> t; + if (m) return fs.Small[t + _FirstNotZeroBit(m)]; + else if (fs.Min) return fs.Min; + } + else + { + item = _FreeFindAfter(fs.Min, size + 1 + MemAddSize + MemMinSize); + if (item) return item; + } + m = fs.SmallMask >> s; + if (m) return fs.Small[s + _FirstNotZeroBit(m)]; + else return fs.Min; + } + item = _FreeFindAfter(fs.Min, ++size); + if (!item) return 0; + s = MEMORY_HEAP_NEXT(item) - item; + if (s == size) return item; + size += MemAddSize + MemMinSize; + if (s >= size) return item; + nextitem = _FreeFindAfter(item, size); + return nextitem ? nextitem : item; + } + +// Block functions. + + inline void _CreateBlockEnd(TMemBlock &block, TFreeSpace &fs, TMemItem c, TMemItem e) + { + block.Begin[0] = (TMemItem)(&fs); + if (e - c < TMemItem(MemAddSize + MemMinSize)) + { + MEMORY_HEAP_NEXT(c) = 0; + block.Begin[1] = c; + } + else + { + MEMORY_HEAP_NEXT(c) = e + 1; + _FreeAdd(fs, c); + MEMORY_HEAP_PREV(e) = c; + MEMORY_HEAP_NEXT(e) = 0; + block.Begin[1] = e; + } + } + + TMemBlock CreateBlock(void *begin, void *end, TFreeSpace &fs) + { + TMemBlock block = {0}; + TMemItem b = MEMORY_HEAP_ALIGN_UP(begin); + TMemItem e = MEMORY_HEAP_ALIGN_DOWN(end); + if (e <= b || e - b < TMemItem(BlockAddSize - MemAddSize)) return block; + block.Begin = (TMemItem*)b; + b += MEMORY_HEAP_ALIGN_UP(4 * sizeof(TMemItem)); + MEMORY_HEAP_PREV(b) = 0; + _CreateBlockEnd(block, fs, b, e); + return block; + } + + TMemBlock CreateBlock(void *begin, void *end) + { + TMemBlock block = {0}; + TMemItem b = MEMORY_HEAP_ALIGN_UP(begin); + TMemItem e = MEMORY_HEAP_ALIGN_DOWN(end); + if (e <= b || e - b < TMemItem(BlockAddSizeFS - MemAddSize)) return block; + block.Begin = (TMemItem*)b; + b += MEMORY_HEAP_ALIGN_UP(4 * sizeof(TMemItem)); + TMemItem c = b + MemAddSize + MEMORY_HEAP_ALIGN_UP(sizeof(TFreeSpace)); + MEMORY_HEAP_PREV(b) = 0; + MEMORY_HEAP_NEXT(b) = c; + MEMORY_HEAP_PREV(c) = b; + InitFreeSpace(*(TFreeSpace*)b); + _CreateBlockEnd(block, *(TFreeSpace*)b, c, e); + return block; + } + + void ResizeBlock(TMemBlock block, void *new_end) + { + if (!BlockValid(block)) return; + TMemItem e = MEMORY_HEAP_ALIGN_DOWN(new_end); + TMemItem c = block.Begin[1]; + TFreeSpace &fs = *(TFreeSpace*)block.Begin[0]; + do + { + if (c == e) return; + else if (c > e) + { + while ((c = MEMORY_HEAP_PREV(c)) > e) + { + if (MEMORY_HEAP_FREE(c)) _FreeDel(fs, c); + } + if (!c) {block.Begin = 0; return;} + if (MEMORY_HEAP_FREE(c)) + { + _FreeDel(fs, c); + if (e - c < TMemItem(MemAddSize + MemMinSize)) e = c; + else + { + MEMORY_HEAP_NEXT(c) = e + 1; + _FreeAdd(*(TFreeSpace*)block.Begin[0], c); + break; + } + } + else if (e - c >= TMemItem(MemAddSize + MemMinSize)) + { + MEMORY_HEAP_NEXT(c) = e; break; + } + MEMORY_HEAP_NEXT(c) = 0; + block.Begin[1] = c; + if (c == e) return; + } + TMemItem pc = MEMORY_HEAP_PREV(c); + if (pc && MEMORY_HEAP_FREE(pc)) _FreeDel(fs, c = pc); + else if (e - c < TMemItem(MemAddSize + MemMinSize)) return; + MEMORY_HEAP_NEXT(c) = e + 1; + _FreeAdd(fs, c); + } while(false); + MEMORY_HEAP_PREV(e) = c; + MEMORY_HEAP_NEXT(e) = 0; + block.Begin[1] = e; + } + + void RemoveBlock(TMemBlock block) + { + if (!BlockValid(block)) return; + TMemItem e = block.Begin[1]; + TFreeSpace &fs = *(TFreeSpace*)block.Begin[0]; + while ((e = MEMORY_HEAP_PREV(e)) != 0) + { + if (MEMORY_HEAP_FREE(e)) _FreeDel(fs, e); + } + block.Begin = 0; + } + +// Free space functions. + + void _CopyMemItemArray(TMemItem dest, TMemItem src, TMemItem end) + { + TMemItem k = (end - src) / sizeof(TMemItem); + TMemItem *d = (TMemItem*)dest; + TMemItem *s = (TMemItem*)src; + while (k--) *(d++) = *(s++); + } + + void *Alloc(TFreeSpace &fs, unsigned int size) + { + if (!size) return 0; + TMemItem s = MEMORY_HEAP_ALIGN_UP(size) + MemAddSize; + if (s < MemAddSize + MemMinSize) s = MemAddSize + MemMinSize; + TMemItem c = _FreeFind(fs, s); + if (!c) return 0; + _FreeDel(fs, c); + TMemItem nc = --MEMORY_HEAP_NEXT(c); + TMemItem mc = c + s; + if (nc - (MemAddSize + MemMinSize) >= mc) + { + MEMORY_HEAP_NEXT(c) = mc; + MEMORY_HEAP_PREV(mc) = c; + MEMORY_HEAP_NEXT(mc) = nc + 1; + MEMORY_HEAP_PREV(nc) = mc; + _FreeAdd(fs, mc); + } + return (void*)c; + } + + void *ReAlloc(TFreeSpace &fs, void *mem, unsigned int size) + { + if (!mem) return Alloc(fs, size); + if (!size) {Free(fs, mem); return 0;} + TMemItem s = MEMORY_HEAP_ALIGN_UP(size) + MemAddSize; + TMemItem c = (TMemItem)mem; + TMemItem mc = MEMORY_HEAP_NEXT(c); + TMemItem nc = MEMORY_HEAP_NEXT(mc); + if (--nc & 1) nc = mc; + if (s < MemAddSize + MemMinSize) s = MemAddSize + MemMinSize; + if (nc - c < s) + { + mem = Alloc(fs, size); + if (mem) + { + _CopyMemItemArray((TMemItem)mem, c, mc - MemAddSize); + Free(fs, (void*)c); + return mem; + } + else + { + TMemItem pc = MEMORY_HEAP_PREV(c); + if (pc && MEMORY_HEAP_FREE(pc) && nc - pc >= s) + { + _FreeDel(fs, pc); + _CopyMemItemArray(pc, c, mc - MemAddSize); + c = pc; + } + else return 0; + } + } + if (mc < nc) _FreeDel(fs, mc); + mc = c + s; + if (nc - (MemAddSize + MemMinSize) >= mc) + { + MEMORY_HEAP_NEXT(c) = mc; + MEMORY_HEAP_PREV(mc) = c; + MEMORY_HEAP_NEXT(mc) = nc + 1; + MEMORY_HEAP_PREV(nc) = mc; + _FreeAdd(fs, mc); + } + else + { + MEMORY_HEAP_NEXT(c) = nc; + MEMORY_HEAP_PREV(nc) = c; + } + return (void*)c; + } + + int free_a = 0; + + void Free(TFreeSpace &fs, void *mem) + { + TMemItem c = (TMemItem)mem; + if (!c) return; + TMemItem pc = MEMORY_HEAP_PREV(c); + TMemItem mc = MEMORY_HEAP_NEXT(c); + TMemItem nc = MEMORY_HEAP_NEXT(mc); + if (--nc & 1) nc = mc; + else _FreeDel(fs, mc); + if (free_a == 1) return; + if (pc && MEMORY_HEAP_FREE(pc)) _FreeDel(fs, c = pc); + MEMORY_HEAP_NEXT(c) = nc + 1; + MEMORY_HEAP_PREV(nc) = c; + if (free_a == 2) return; + _FreeAdd(fs, c); + } +} + +#endif // ndef __MEMORY_HEAP_RBTREE_H_INCLUDED_ + diff --git a/programs/games/checkers/trunk/include/menuet.h b/programs/games/checkers/trunk/include/menuet.h new file mode 100644 index 0000000000..74e0bff50f --- /dev/null +++ b/programs/games/checkers/trunk/include/menuet.h @@ -0,0 +1,536 @@ +#ifndef __MENUET_H_INCLUDED_ +#define __MENUET_H_INCLUDED_ + +#include + +// Menuet interface. + +namespace Menuet // All menuet functions, types and data are nested in the (Menuet) namespace. +{ + const char *DebugPrefix = "User program: "; + + struct TWindowData // Data for drawing a window. + { + unsigned short WindowType, HeaderType; + unsigned long WindowColor, HeaderColor, BorderColor, TitleColor; + const char *Title; + }; + + struct TStartData // This structure is used only for MenuetOnStart function. + { + unsigned short Left, Width, Top, Height; // Initial window rectangle. + TWindowData WinData; + }; + + typedef void **TThreadData; // Thread data are the fast identifier of thread, contains user dword in + //_ the zero element and stack beginning (or zero if it is unknown) in the first element. + //_ The stack will be deleted from dynamic memory at the finish of the thread if stack beginning is not zero. + + struct TMutex; // Simple mutex can be locked only once at a time. +#define MENUET_MUTEX_INIT {} // Simple mutex initializer, cat be redefined in a realization of the library + + struct TRecMutex; // Recursive mutex can be locked many times by a single thread at a time. +#define MENUET_REC_MUTEX_INIT {} // Recursive mutex initializer, cat be redefined in a realization of the library + + // Some functions have two forms: the fast form with (thread_data) parameter and the form without it. + // Note: pass only thread data of current thread as (thread_data) parameter to these functions. + + void Main(); // Main function is called at program startup. + void* ThreadMain(void *user = 0, void *stack_begin = 0); + // Called at thread startup, (user) is placed in thread data as a user dword, + //_ (stack_begin) is placed in thread data as a stack beginning. + //_ Return new value of stack beginning that can be changed in the thread data. + void GetWindowData(TWindowData &win_data); // Write current window data to (win_data). + void GetWindowData(TWindowData &win_data, TThreadData thread_data); + void SetWindowData(const TWindowData &win_data); // Replace current window data by (win_data). + void SetWindowData(const TWindowData &win_data, TThreadData thread_data); + void CloseWindow(); // Close current window when returning to message loop. + void CloseWindow(TThreadData thread_data); + void Redraw(int frame = 0); // Redraw current window immediately, if (frame) is positive redraw the frame too, + void Redraw(int frame, TThreadData thread_data); //_ if (frame) is negative redraw only invalideted window. + void Invalidate(int frame = 0); // Redraw current window when no message will be is the queue, + void Invalidate(int frame, TThreadData thread_data); //_ if (frame) is positive redraw the frame too, + //_ if (frame) is negative do nothing. + void MoveWindow(const int window_rect[/* 4 */]); // Move and resize current window. + + void Abort(); // Abnormally terminate a program. + void ExitProcess(); // Exit from the process, don't call any destructors of global varyables + void ExitThread(); // Exit from the current thread + void ExitThread(TThreadData thread_data); + void ReturnMessageLoop(); // Return to the message loop of the thread. Exit from the thread + void ReturnMessageLoop(TThreadData thread_data); //_ if it is called from (MenuetOnStart). + + void Delay(unsigned int time); // Delay the execution of the program during (time) hundredth seconds. + unsigned int Clock(); // Return the time from starting of the system to this moment in hundredth of seconds. + int GetPackedTime(); // Return the current time of day in binary-decimal format 0x00SSMMHH. + void GetTime(int t[/* 3 */]); // Write the current time to (t): t[0] = second, t[1] = minute, t[2] = hour. + int GetPackedDate(); // Return the current date in binary-decimal format 0x00YYDDMM. + void GetDate(int d[/* 3 */]); // Write the current date to (d): d[0] = day, d[1] = month, d[2] = year. + void GetTimeDate(int t[/* 6 */]); // Write the current time and date to (t): t[0] = second, + //_ t[1] = minute, t[2] = hour, t[3] = day, t[4] = month, t[5] = year. + void ReadCommonColors(unsigned int colors[/* 10 */]); // Writes standart window colors to (colors). + unsigned int GetProcessInfo(unsigned int *use_cpu, char process_name[/* 13 */], unsigned int *use_memory, + unsigned int *pid, int window_rect[/* 4 */], unsigned int pid_for = -1); + // Write (pid_for) process information to variables parameters points, return + //_ the number of processes. (pid_for) equal to (-1) means current process. + unsigned int GetPid(); // Return the current thread identifier (pid). + unsigned int GetPid(TThreadData thread_data); + TThreadData GetThreadData(); // Return the thread data of the current thread. + TThreadData GetThreadData(unsigned int pid); // Return the thread data of the thread with the given pid. + + void* GetPicture(unsigned short &width, unsigned short &height); + void* GetPicture(unsigned short &width, unsigned short &height, TThreadData thread_data); + // Return the picture on the window and write its width and height to (width) and (height). + void SetPicture(void *picture, unsigned short width, unsigned short height); + void SetPicture(void *picture, unsigned short width, unsigned short height, TThreadData thread_data); + // Replace the picture on the window by the given picture with the given width and height. + void GetBorderHeader(unsigned short &border_size, unsigned short &header_size); + void GetBorderHeader(unsigned short &border_size, unsigned short &header_size, TThreadData thread_data); + // Write the border thickness to (border_size) and header height to (header_size). + void GetClientSize(unsigned short &width, unsigned short &height); + void GetClientSize(unsigned short &width, unsigned short &height, TThreadData thread_data); + // Write the client area width and height to (width) and (height) parameters. + void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height); + void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height, TThreadData thread_data); + // Write the client area size of window with the width (win_width) + //_ and height (win_height) to (width) and (height) parameters. + void GetScreenSize(unsigned short &width, unsigned short &height); + // Write the screen width and height to (width) and (height) parameters. + + void InitMutex(TMutex *mutex); // Initialize the simple mutex. + void InitRecMutex(TRecMutex *mutex); // Initialize the recursive mutex. + bool TryLock(TMutex *mutex); // Try to lock the mutex without waitting, return true if lock. + bool TryLock(TRecMutex *mutex); + bool TryLock(TRecMutex *mutex, TThreadData thread_data); + bool TryLock(TRecMutex *mutex, unsigned int pid); + void Lock(TMutex *mutex); // Lock mutex and wait for it if this necessary. + void Lock(TRecMutex *mutex); + void Lock(TRecMutex *mutex, TThreadData thread_data); + void Lock(TRecMutex *mutex, unsigned int pid); + bool LockTime(TMutex *mutex, int time); + bool LockTime(TRecMutex *mutex, int time); // Lock mutex and wait for it during (time) hundredth seconds. + bool LockTime(TRecMutex *mutex, int time, TThreadData thread_data); + bool LockTime(TRecMutex *mutex, int time, unsigned int pid); + void UnLock(TMutex *mutex); // Unlock mutex + void UnLock(TRecMutex *mutex); + void UnLock(TRecMutex *mutex, TThreadData thread_data); + void UnLock(TRecMutex *mutex, unsigned int pid); + + void DebugPutChar(char c); // Put the character to the debug board. + void DebugPutString(const char *s); // Put the string to the debug board. + int GetKey(); // Return key pressed by user or -1 if no key was pressed. + int GetMouseButton(); // Return buttons pressed: 0 - no buttons, 1 - left button, 2 - right button, 3 - both buttons. + void GetMousePosition(short &x, short &y, bool absolute = false); + // Write mouse position to (x) and (y): absolute if (absolute) is true and relative the window otherwise. + void GetMousePosPicture(short &x, short &y); + + int GetThreadNumber(); // Return the number of threads currently executing. + bool WasThreadCreated(); // Return true if there was created at least one thread except the main thred. + unsigned int CreateThread(void *user = 0, unsigned int stack_size = 0, void *stack_end = 0); + // Create a new thread with the user dword (user) and stack pointer (stack_end). + //_ If (stack_end) is zero, create stack in dynamic memory of size (stack_size) or + //_ the same size as the main thread if (stack_size) less that 4096. Set the beginning + //_ of the stack if (stack_end) is zero or (stack_size) is not zero, in this case stack + //_ will be deleted automaticaly from dynamic memory at the finish of the thread. +} + +// Function, defined outside. + +bool MenuetOnStart(Menuet::TStartData &me_start, Menuet::TThreadData thread_data); + // Window will be created iff return value is true. +bool MenuetOnClose(Menuet::TThreadData thread_data); // Window will be closed iff return value is true. +int MenuetOnIdle(Menuet::TThreadData thread_data); // Return the time to wait next message. +void MenuetOnSize(int window_rect[/* 4 */], Menuet::TThreadData thread_data); // When the window is resized. +void MenuetOnKeyPress(Menuet::TThreadData thread_data); // When user press a key. +void MenuetOnMouse(Menuet::TThreadData thread_data); // When user move a mouse. + +#ifdef __MENUET__ + +namespace Menuet +{ +// Structures. + + struct TMutex // Simple mutex can be locked only once at a time. + { + unsigned int mut; + }; +#undef MENUET_MUTEX_INIT +#define MENUET_MUTEX_INIT {0x40} // Simple mutex initializer, cat be redefined in a realization of the library + + struct TRecMutex // Recursive mutex can be locked many times by a single thread at a time. + { + unsigned int mut, pid; + }; +#undef MENUET_REC_MUTEX_INIT +#define MENUET_REC_MUTEX_INIT {0x20,-1} // Recursive mutex initializer, cat be redefined in a realization of the library + +// Global variables. + + volatile TThreadData _ThreadTable[256]; + volatile unsigned int _ThreadScanCount[2] = {0, 0}; + volatile int _ThreadNumber = 1; + volatile int _ExitProcessNow = 0; + TMutex _ThreadMutex = MENUET_MUTEX_INIT; + unsigned int _ThreadSavedBegProc[4]; + +// Inline functions. + + inline void GetWindowData(TWindowData &win_data) {GetWindowData(win_data, GetThreadData());} + + inline void SetWindowData(const TWindowData &win_data) {SetWindowData(win_data, GetThreadData());} + + inline void CloseWindow() {CloseWindow(GetThreadData());} + + inline void Redraw(int frame) {Redraw(frame, GetThreadData());} + + inline void Invalidate(int frame) {Invalidate(frame, GetThreadData());} + + inline void* GetPicture(unsigned short &width, unsigned short &height) + { + return GetPicture(width, height, GetThreadData()); + } + + inline void SetPicture(void *picture, unsigned short width, unsigned short height) + { + SetPicture(picture, width, height, GetThreadData()); + } + + inline void GetBorderHeader(unsigned short &border_size, unsigned short &header_size) + { + GetBorderHeader(border_size, header_size, GetThreadData()); + } + + inline void GetClientSize(unsigned short &width, unsigned short &height) + { + unsigned int pid; + int rect[4]; + GetProcessInfo(0, 0, 0, &pid, rect); + GetClientSize(width, height, rect[2], rect[3], GetThreadData(pid)); + } + + inline void GetClientSize(unsigned short &width, unsigned short &height, TThreadData thread_data) + { + int rect[4]; + GetProcessInfo(0, 0, 0, 0, rect); + GetClientSize(width, height, rect[2], rect[3], thread_data); + } + + inline void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height) + { + GetClientSize(width, height, win_width, win_height, GetThreadData()); + } + + inline void GetTimeDate(int t[/* 6 */]) {GetTime(t); GetDate(t + 3);} + + inline void InitMutex(TMutex *mutex) {mutex->mut = 0;} + + inline void InitRecMutex(TRecMutex *mutex) {mutex->mut = 0; mutex->pid = -1;} + + inline bool TryLock(TRecMutex *mutex) {return TryLock(mutex, GetPid());} + + inline bool TryLock(TRecMutex *mutex, TThreadData thread_data) {return TryLock(mutex, GetPid(thread_data));} + + inline void Lock(TRecMutex *mutex) {Lock(mutex, GetPid());} + + inline void Lock(TRecMutex *mutex, TThreadData thread_data) {Lock(mutex, GetPid(thread_data));} + + inline bool LockTime(TRecMutex *mutex, int time) {return LockTime(mutex, time, GetPid());} + + inline bool LockTime(TRecMutex *mutex, int time, TThreadData thread_data) + {return LockTime(mutex, time, GetPid(thread_data));} + + inline void UnLock(TRecMutex *mutex) {UnLock(mutex, GetPid());} + + inline void UnLock(TRecMutex *mutex, TThreadData thread_data) {UnLock(mutex, GetPid(thread_data));} + + inline int GetThreadNumber() {return _ThreadNumber;} + +// Constants from fasm. + +#include + +// Functions. + + unsigned char _HashByte(unsigned int value); + unsigned short _HashWord(unsigned int value); + unsigned int _HashDword(unsigned int value); + + void _GetStartData(TStartData &start_data, TThreadData thread_data) + { + start_data.Left = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_X] >> 16); + start_data.Width = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_X]); + start_data.Top = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_Y] >> 16); + start_data.Height = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_Y]); + GetWindowData(start_data.WinData, thread_data); + } + + void _SetStartData(const TStartData &start_data, TThreadData thread_data) + { + (unsigned long&)thread_data[MENUET_THREAD_DATA_X] = + ((unsigned int)start_data.Left << 16) | start_data.Width; + (unsigned long&)thread_data[MENUET_THREAD_DATA_Y] = + ((unsigned int)start_data.Top << 16) | start_data.Height; + SetWindowData(start_data.WinData, thread_data); + } + + void _ApplyCommonColors(TWindowData &win_data) + { + unsigned int colors[10]; + ReadCommonColors(colors); + win_data.WindowColor = colors[5]; + win_data.HeaderColor = colors[1]; + win_data.BorderColor = colors[0]; + win_data.TitleColor = colors[4]; + } + + void _SetValueFunctionPriority(void *beg, int n) + { + int k, i; + unsigned char num[256]; + for (i = 0; i < 256; i++) num[i] = 0; + for (k = 0; k < n; k++) + { + i = ((unsigned char*)beg + 6*k)[1]; + ((unsigned char*)beg + 6*k)[0] = num[i]; + if (num[i] != 255) num[i]++; + } + } + + void _CallFunctionPriority(void *beg, void *end, bool reverse = false) + { + struct _Local + { + static int cmp(void *beg, int i, int j) + { + unsigned char *x = (unsigned char*)beg + 6*i; + unsigned char *y = (unsigned char*)beg + 6*j; + if (*(unsigned short*)x < *(unsigned short*)y) return -1; + if (*(unsigned short*)x > *(unsigned short*)y) return 1; + return 0; + } + + static void swap(void *beg, int i, int j) + { + unsigned char *x = (unsigned char*)beg + 6*i; + unsigned char *y = (unsigned char*)beg + 6*j; + short s; + int t; + s = *(short*)x; *(short*)x = *(short*)y; *(short*)y = s; + x += 2; y += 2; + t = *(int*)x; *(int*)x = *(int*)y; *(int*)y = t; + } + + static void call(void *beg, int i) + { + unsigned char *x = (unsigned char*)beg + 6*i; + (*(void(**)())(x+2))(); + } + }; + + if (!beg || !end || end <= beg) return; + int i, j, k, m, n; + n = ((unsigned char*)end - (unsigned char*)beg) / 6; + if (n <= 0) return; + _SetValueFunctionPriority(beg, n); + m = n; k = n; + while (m > 1) + { + if (k > 0) k--; + else _Local::swap(beg, 0, --m); + j = k; + for (;;) + { + i = j; + if (2*i + 1 >= m) break; + if (_Local::cmp(beg, 2*i + 1, j) > 0) j = 2*i + 1; + if (2*i + 2 < m && _Local::cmp(beg, 2*i + 2, j) > 0) j = 2*i + 2; + if (i == j) break; + _Local::swap(beg, i, j); + } + } + if (!reverse) + { + for (k = 0; k < n; k++) _Local::call(beg, k); + } + else + { + for (k = n-1; k >= 0; k--) _Local::call(beg, k); + } + } + + bool _CallStart(TThreadData thread_data, void *init = 0, void *init_end = 0) + { + struct _TThreadDataTemplate + { + unsigned int data[12]; + }; + static const _TThreadDataTemplate _ThreadDataTemplate = + {{3, 0x00320100, 0x00320100, 0x33FFFFFF, 0x806060FF, 0x00000000, 0x00FFFF40, 0, 0, 0, -1, -1}}; + + unsigned int pid = GetPid(); + volatile TThreadData *thread_table_item; + Lock(&_ThreadMutex); + if (_ExitProcessNow) ExitProcess(); + thread_table_item = &_ThreadTable[_HashByte(pid)]; + thread_data[MENUET_THREAD_DATA_NEXT] = (void*)*thread_table_item; + (unsigned int&)thread_data[MENUET_THREAD_DATA_PID] = pid; + *(_TThreadDataTemplate*)(thread_data + MENUET_THREAD_DATA_FLAG) = _ThreadDataTemplate; + *thread_table_item = thread_data; + UnLock(&_ThreadMutex); + if (_ExitProcessNow) ExitProcess(); + _CallFunctionPriority(init, init_end, false); + TStartData start_data; + _GetStartData(start_data, thread_data); +// _ApplyCommonColors(start_data.WinData); + (unsigned int&)thread_data[MENUET_THREAD_DATA_FLAG] |= 0x40000000; + thread_data[MENUET_THREAD_DATA_TITLE] = (void*)(&start_data); + if (!MenuetOnStart(start_data, thread_data)) return false; + (unsigned int&)thread_data[MENUET_THREAD_DATA_FLAG] &= ~0x40000000; + _SetStartData(start_data, thread_data); + return true; + } + + void _RemoveThreadData(TThreadData thread_data, void *exit = 0, void *exit_end = 0) + { + _CallFunctionPriority(exit, exit_end, true); + volatile TThreadData *thread_table_item; + Lock(&_ThreadMutex); + if (_ExitProcessNow) ExitProcess(); + thread_table_item = &_ThreadTable[_HashByte(GetPid(thread_data))]; + while (*thread_table_item) + { + if (*thread_table_item == thread_data) + { + *thread_table_item = (TThreadData)thread_data[MENUET_THREAD_DATA_NEXT]; + break; + } + thread_table_item = (TThreadData*)(*thread_table_item + MENUET_THREAD_DATA_NEXT); + } + UnLock(&_ThreadMutex); + if (_ExitProcessNow) ExitProcess(); + } + + void GetWindowData(TWindowData &win_data, TThreadData thread_data) + { + if ((unsigned int)thread_data[MENUET_THREAD_DATA_FLAG] & 0x40000000) + { + win_data = ((TStartData*)thread_data[MENUET_THREAD_DATA_TITLE])->WinData; + return; + } + win_data.WindowType = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_C_WINDOW] >> 24); + win_data.HeaderType = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_C_HEADER] >> 24); + win_data.WindowColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_WINDOW] & 0xFFFFFF; + win_data.HeaderColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_HEADER] & 0xFFFFFF; + win_data.BorderColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_BORDER] & 0xFFFFFF; + win_data.TitleColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_TITLE] & 0xFFFFFF; + win_data.Title = (char*)thread_data[MENUET_THREAD_DATA_TITLE]; + } + + void SetWindowData(const TWindowData &win_data, TThreadData thread_data) + { + if ((unsigned int)thread_data[MENUET_THREAD_DATA_FLAG] & 0x40000000) + { + ((TStartData*)thread_data[MENUET_THREAD_DATA_TITLE])->WinData = win_data; + return; + } + (unsigned int&)thread_data[MENUET_THREAD_DATA_C_WINDOW] = + ((unsigned int)win_data.WindowType << 24) | (win_data.WindowColor & 0xFFFFFF); + (unsigned int&)thread_data[MENUET_THREAD_DATA_C_HEADER] = + ((unsigned int)win_data.HeaderType << 24) | (win_data.HeaderColor & 0xFFFFFF); + (unsigned int&)thread_data[MENUET_THREAD_DATA_C_BORDER] = win_data.BorderColor & 0xFFFFFF; + (unsigned int&)thread_data[MENUET_THREAD_DATA_C_TITLE] = win_data.TitleColor & 0xFFFFFF; + thread_data[MENUET_THREAD_DATA_TITLE] = (void*)win_data.Title; + Invalidate(1, thread_data); + } + + void CloseWindow(TThreadData thread_data) + { + (unsigned int&)thread_data[MENUET_THREAD_DATA_FLAG] |= 0x80000000; + } + + void Invalidate(int frame, TThreadData thread_data) + { + if (frame < 0) return; + (unsigned int&)thread_data[MENUET_THREAD_DATA_FLAG] |= (frame ? 3 : 1); + } + + void* GetPicture(unsigned short &width, unsigned short &height, TThreadData thread_data) + { + width = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_SZ_PICT] >> 16); + height = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_SZ_PICT]); + return (void*)thread_data[MENUET_THREAD_DATA_PICTURE]; + } + + void SetPicture(void *picture, unsigned short width, unsigned short height, TThreadData thread_data) + { + thread_data[MENUET_THREAD_DATA_PICTURE] = (void*)picture; + (unsigned int&)thread_data[MENUET_THREAD_DATA_SZ_PICT] = + (width == 0 || height == 0) ? 0 : (((unsigned int)width << 16) | height); + Invalidate(0, thread_data); + } + + int _GetSkinHeader(); + + void GetBorderHeader(unsigned short &border_size, unsigned short &header_size, TThreadData thread_data) + { + int win_type = ((unsigned int)thread_data[MENUET_THREAD_DATA_FLAG] & 0x40000000) ? + ((TStartData*)thread_data[MENUET_THREAD_DATA_TITLE])->WinData.WindowType : + ((unsigned int)thread_data[MENUET_THREAD_DATA_C_WINDOW] >> 24); + border_size = MENUET_BORDER_SIZE; + header_size = short(((win_type & 15) == 3) ? _GetSkinHeader() : MENUET_HEADER_SIZE); + } + + void GetClientSize(unsigned short &width, unsigned short &height, + int win_width, int win_height, TThreadData thread_data) + { + const int MAX_SIZE = 32767; + unsigned short border_size, header_size; + GetBorderHeader(border_size, header_size, thread_data); + win_width -= 2 * border_size; + win_height -= border_size + header_size; + if (win_width < 0) win_width = 0; + else if (win_width > MAX_SIZE) win_width = MAX_SIZE; + if (win_height < 0) win_height = 0; + else if (win_height > MAX_SIZE) win_height = MAX_SIZE; + width = (unsigned short)win_width; + height = (unsigned short)win_height; + } + + void GetMousePosPicture(short &x, short &y) + { + unsigned short dx, dy; + GetMousePosition(x, y); + GetBorderHeader(dx, dy); + x -= dx; y -= dy; + } +} + +#else // def __MENUET__ + +namespace Menuet +{ + struct TMutex + { + unsigned int mut; + + TMutex(); + ~TMutex(); + }; +#undef MENUET_MUTEX_INIT +#define MENUET_MUTEX_INIT TMutex() + + struct TRecMutex + { + unsigned int mut; + + TRecMutex(); + ~TRecMutex(); + }; +#undef MENUET_REC_MUTEX_INIT +#define MENUET_REC_MUTEX_INIT TRecMutex() +} + +#endif // else: def __MENUET__ + +#endif // ndef __MENUET_H_INCLUDED_ + diff --git a/programs/games/checkers/trunk/include/stdarg.h b/programs/games/checkers/trunk/include/stdarg.h new file mode 100644 index 0000000000..7abd7592eb --- /dev/null +++ b/programs/games/checkers/trunk/include/stdarg.h @@ -0,0 +1,13 @@ +#ifndef __STDARG_H +#define __STDARG_H + +typedef void *va_list; + +#define __size(x) ((sizeof(x)+sizeof(int)-1) & ~(sizeof(int)-1)) + +#define va_start(ap, parmN) ((void)((ap) = (va_list)((char *)(&parmN)+__size(parmN)))) +#define va_arg(ap, type) (*(type *)(((*(char **)&(ap))+=__size(type))-(__size(type)))) +#define va_end(ap) ((void)0) + + +#endif /* __STDARG_H */ diff --git a/programs/games/checkers/trunk/include/write_macro.inc b/programs/games/checkers/trunk/include/write_macro.inc new file mode 100644 index 0000000000..3015f65896 --- /dev/null +++ b/programs/games/checkers/trunk/include/write_macro.inc @@ -0,0 +1,49 @@ +macro writestr [arg] +{ + common + + local straddr + local strend + pushad + push straddr + push strend + jmp @Menuet@DebugPutString$qpxc + straddr db arg,0 + strend: + pop eax + popad +} + +macro writeint arg +{ + push dword arg + xchg eax,[esp] + pushad + push eax + call @DebugPutNumber$qi + pop eax + popad + pop eax +} + +macro write [arg] +{ + forward + + if arg eq + else if arg eq endline + writestr 10 + else if arg eqtype '' + writestr arg + else + writeint arg + end if +} + +macro writeln [arg] +{ + common + + write arg,endline +} + diff --git a/programs/games/checkers/trunk/keysym.h b/programs/games/checkers/trunk/keysym.h new file mode 100644 index 0000000000..f120d49556 --- /dev/null +++ b/programs/games/checkers/trunk/keysym.h @@ -0,0 +1,2047 @@ +#ifndef _INCLUDE_KEY_SYM_H +#define _INCLUDE_KEY_SYM_H + +/* $Xorg: keysym.h,v 1.4 2001/02/09 02:03:23 xorgcvs Exp $ */ + +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/include/keysym.h,v 1.4 2001/12/14 19:53:26 dawes Exp $ */ + +/* default keysyms */ +#define XK_MISCELLANY +#define XK_XKB_KEYS +#define XK_LATIN1 +#define XK_LATIN2 +#define XK_LATIN3 +#define XK_LATIN4 +#define XK_LATIN8 +#define XK_LATIN9 +#define XK_CAUCASUS +#define XK_GREEK +#define XK_KATAKANA +#define XK_ARABIC +#define XK_CYRILLIC +#define XK_HEBREW +#define XK_THAI +#define XK_KOREAN +#define XK_ARMENIAN +#define XK_GEORGIAN +#define XK_VIETNAMESE +#define XK_CURRENCY + + + +/* keysym definitions */ + +#define XK_VoidSymbol 0xFFFFFF /* void symbol */ + +#ifdef XK_MISCELLANY +/* + * TTY Functions, cleverly chosen to map to ascii, for convenience of + * programming, but could have been arbitrary (at the cost of lookup + * tables in client code. + */ + +#define XK_BackSpace 0xFF08 /* back space, back char */ +#define XK_Tab 0xFF09 +#define XK_Linefeed 0xFF0A /* Linefeed, LF */ +#define XK_Clear 0xFF0B +#define XK_Return 0xFF0D /* Return, enter */ +#define XK_Pause 0xFF13 /* Pause, hold */ +#define XK_Scroll_Lock 0xFF14 +#define XK_Sys_Req 0xFF15 +#define XK_Escape 0xFF1B +#define XK_Delete 0xFFFF /* Delete, rubout */ + + + +/* International & multi-key character composition */ + +#define XK_Multi_key 0xFF20 /* Multi-key character compose */ +#define XK_Codeinput 0xFF37 +#define XK_SingleCandidate 0xFF3C +#define XK_MultipleCandidate 0xFF3D +#define XK_PreviousCandidate 0xFF3E + +/* Japanese keyboard support */ + +#define XK_Kanji 0xFF21 /* Kanji, Kanji convert */ +#define XK_Muhenkan 0xFF22 /* Cancel Conversion */ +#define XK_Henkan_Mode 0xFF23 /* Start/Stop Conversion */ +#define XK_Henkan 0xFF23 /* Alias for Henkan_Mode */ +#define XK_Romaji 0xFF24 /* to Romaji */ +#define XK_Hiragana 0xFF25 /* to Hiragana */ +#define XK_Katakana 0xFF26 /* to Katakana */ +#define XK_Hiragana_Katakana 0xFF27 /* Hiragana/Katakana toggle */ +#define XK_Zenkaku 0xFF28 /* to Zenkaku */ +#define XK_Hankaku 0xFF29 /* to Hankaku */ +#define XK_Zenkaku_Hankaku 0xFF2A /* Zenkaku/Hankaku toggle */ +#define XK_Touroku 0xFF2B /* Add to Dictionary */ +#define XK_Massyo 0xFF2C /* Delete from Dictionary */ +#define XK_Kana_Lock 0xFF2D /* Kana Lock */ +#define XK_Kana_Shift 0xFF2E /* Kana Shift */ +#define XK_Eisu_Shift 0xFF2F /* Alphanumeric Shift */ +#define XK_Eisu_toggle 0xFF30 /* Alphanumeric toggle */ +#define XK_Kanji_Bangou 0xFF37 /* Codeinput */ +#define XK_Zen_Koho 0xFF3D /* Multiple/All Candidate(s) */ +#define XK_Mae_Koho 0xFF3E /* Previous Candidate */ + +/* 0xFF31 thru 0xFF3F are under XK_KOREAN */ + +/* Cursor control & motion */ + +#define XK_Home 0xFF50 +#define XK_Left 0xFF51 /* Move left, left arrow */ +#define XK_Up 0xFF52 /* Move up, up arrow */ +#define XK_Right 0xFF53 /* Move right, right arrow */ +#define XK_Down 0xFF54 /* Move down, down arrow */ +#define XK_Prior 0xFF55 /* Prior, previous */ +#define XK_Page_Up 0xFF55 +#define XK_Next 0xFF56 /* Next */ +#define XK_Page_Down 0xFF56 +#define XK_End 0xFF57 /* EOL */ +#define XK_Begin 0xFF58 /* BOL */ + + +/* Misc Functions */ + +#define XK_Select 0xFF60 /* Select, mark */ +#define XK_Print 0xFF61 +#define XK_Execute 0xFF62 /* Execute, run, do */ +#define XK_Insert 0xFF63 /* Insert, insert here */ +#define XK_Undo 0xFF65 /* Undo, oops */ +#define XK_Redo 0xFF66 /* redo, again */ +#define XK_Menu 0xFF67 +#define XK_Find 0xFF68 /* Find, search */ +#define XK_Cancel 0xFF69 /* Cancel, stop, abort, exit */ +#define XK_Help 0xFF6A /* Help */ +#define XK_Break 0xFF6B +#define XK_Mode_switch 0xFF7E /* Character set switch */ +#define XK_script_switch 0xFF7E /* Alias for mode_switch */ +#define XK_Num_Lock 0xFF7F + +/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */ + +#define XK_KP_Space 0xFF80 /* space */ +#define XK_KP_Tab 0xFF89 +#define XK_KP_Enter 0xFF8D /* enter */ +#define XK_KP_F1 0xFF91 /* PF1, KP_A, ... */ +#define XK_KP_F2 0xFF92 +#define XK_KP_F3 0xFF93 +#define XK_KP_F4 0xFF94 +#define XK_KP_Home 0xFF95 +#define XK_KP_Left 0xFF96 +#define XK_KP_Up 0xFF97 +#define XK_KP_Right 0xFF98 +#define XK_KP_Down 0xFF99 +#define XK_KP_Prior 0xFF9A +#define XK_KP_Page_Up 0xFF9A +#define XK_KP_Next 0xFF9B +#define XK_KP_Page_Down 0xFF9B +#define XK_KP_End 0xFF9C +#define XK_KP_Begin 0xFF9D +#define XK_KP_Insert 0xFF9E +#define XK_KP_Delete 0xFF9F +#define XK_KP_Equal 0xFFBD /* equals */ +#define XK_KP_Multiply 0xFFAA +#define XK_KP_Add 0xFFAB +#define XK_KP_Separator 0xFFAC /* separator, often comma */ +#define XK_KP_Subtract 0xFFAD +#define XK_KP_Decimal 0xFFAE +#define XK_KP_Divide 0xFFAF + +#define XK_KP_0 0xFFB0 +#define XK_KP_1 0xFFB1 +#define XK_KP_2 0xFFB2 +#define XK_KP_3 0xFFB3 +#define XK_KP_4 0xFFB4 +#define XK_KP_5 0xFFB5 +#define XK_KP_6 0xFFB6 +#define XK_KP_7 0xFFB7 +#define XK_KP_8 0xFFB8 +#define XK_KP_9 0xFFB9 + + + +/* + * Auxilliary Functions; note the duplicate definitions for left and right + * function keys; Sun keyboards and a few other manufactures have such + * function key groups on the left and/or right sides of the keyboard. + * We've not found a keyboard with more than 35 function keys total. + */ + +#define XK_F1 0xFFBE +#define XK_F2 0xFFBF +#define XK_F3 0xFFC0 +#define XK_F4 0xFFC1 +#define XK_F5 0xFFC2 +#define XK_F6 0xFFC3 +#define XK_F7 0xFFC4 +#define XK_F8 0xFFC5 +#define XK_F9 0xFFC6 +#define XK_F10 0xFFC7 +#define XK_F11 0xFFC8 +#define XK_L1 0xFFC8 +#define XK_F12 0xFFC9 +#define XK_L2 0xFFC9 +#define XK_F13 0xFFCA +#define XK_L3 0xFFCA +#define XK_F14 0xFFCB +#define XK_L4 0xFFCB +#define XK_F15 0xFFCC +#define XK_L5 0xFFCC +#define XK_F16 0xFFCD +#define XK_L6 0xFFCD +#define XK_F17 0xFFCE +#define XK_L7 0xFFCE +#define XK_F18 0xFFCF +#define XK_L8 0xFFCF +#define XK_F19 0xFFD0 +#define XK_L9 0xFFD0 +#define XK_F20 0xFFD1 +#define XK_L10 0xFFD1 +#define XK_F21 0xFFD2 +#define XK_R1 0xFFD2 +#define XK_F22 0xFFD3 +#define XK_R2 0xFFD3 +#define XK_F23 0xFFD4 +#define XK_R3 0xFFD4 +#define XK_F24 0xFFD5 +#define XK_R4 0xFFD5 +#define XK_F25 0xFFD6 +#define XK_R5 0xFFD6 +#define XK_F26 0xFFD7 +#define XK_R6 0xFFD7 +#define XK_F27 0xFFD8 +#define XK_R7 0xFFD8 +#define XK_F28 0xFFD9 +#define XK_R8 0xFFD9 +#define XK_F29 0xFFDA +#define XK_R9 0xFFDA +#define XK_F30 0xFFDB +#define XK_R10 0xFFDB +#define XK_F31 0xFFDC +#define XK_R11 0xFFDC +#define XK_F32 0xFFDD +#define XK_R12 0xFFDD +#define XK_F33 0xFFDE +#define XK_R13 0xFFDE +#define XK_F34 0xFFDF +#define XK_R14 0xFFDF +#define XK_F35 0xFFE0 +#define XK_R15 0xFFE0 + +/* Modifiers */ + +#define XK_Shift_L 0xFFE1 /* Left shift */ +#define XK_Shift_R 0xFFE2 /* Right shift */ +#define XK_Control_L 0xFFE3 /* Left control */ +#define XK_Control_R 0xFFE4 /* Right control */ +#define XK_Caps_Lock 0xFFE5 /* Caps lock */ +#define XK_Shift_Lock 0xFFE6 /* Shift lock */ + +#define XK_Meta_L 0xFFE7 /* Left meta */ +#define XK_Meta_R 0xFFE8 /* Right meta */ +#define XK_Alt_L 0xFFE9 /* Left alt */ +#define XK_Alt_R 0xFFEA /* Right alt */ +#define XK_Super_L 0xFFEB /* Left super */ +#define XK_Super_R 0xFFEC /* Right super */ +#define XK_Hyper_L 0xFFED /* Left hyper */ +#define XK_Hyper_R 0xFFEE /* Right hyper */ +#endif /* XK_MISCELLANY */ + +/* + * ISO 9995 Function and Modifier Keys + * Byte 3 = 0xFE + */ + +#ifdef XK_XKB_KEYS +#define XK_ISO_Lock 0xFE01 +#define XK_ISO_Level2_Latch 0xFE02 +#define XK_ISO_Level3_Shift 0xFE03 +#define XK_ISO_Level3_Latch 0xFE04 +#define XK_ISO_Level3_Lock 0xFE05 +#define XK_ISO_Group_Shift 0xFF7E /* Alias for mode_switch */ +#define XK_ISO_Group_Latch 0xFE06 +#define XK_ISO_Group_Lock 0xFE07 +#define XK_ISO_Next_Group 0xFE08 +#define XK_ISO_Next_Group_Lock 0xFE09 +#define XK_ISO_Prev_Group 0xFE0A +#define XK_ISO_Prev_Group_Lock 0xFE0B +#define XK_ISO_First_Group 0xFE0C +#define XK_ISO_First_Group_Lock 0xFE0D +#define XK_ISO_Last_Group 0xFE0E +#define XK_ISO_Last_Group_Lock 0xFE0F + +#define XK_ISO_Left_Tab 0xFE20 +#define XK_ISO_Move_Line_Up 0xFE21 +#define XK_ISO_Move_Line_Down 0xFE22 +#define XK_ISO_Partial_Line_Up 0xFE23 +#define XK_ISO_Partial_Line_Down 0xFE24 +#define XK_ISO_Partial_Space_Left 0xFE25 +#define XK_ISO_Partial_Space_Right 0xFE26 +#define XK_ISO_Set_Margin_Left 0xFE27 +#define XK_ISO_Set_Margin_Right 0xFE28 +#define XK_ISO_Release_Margin_Left 0xFE29 +#define XK_ISO_Release_Margin_Right 0xFE2A +#define XK_ISO_Release_Both_Margins 0xFE2B +#define XK_ISO_Fast_Cursor_Left 0xFE2C +#define XK_ISO_Fast_Cursor_Right 0xFE2D +#define XK_ISO_Fast_Cursor_Up 0xFE2E +#define XK_ISO_Fast_Cursor_Down 0xFE2F +#define XK_ISO_Continuous_Underline 0xFE30 +#define XK_ISO_Discontinuous_Underline 0xFE31 +#define XK_ISO_Emphasize 0xFE32 +#define XK_ISO_Center_Object 0xFE33 +#define XK_ISO_Enter 0xFE34 + +#define XK_dead_grave 0xFE50 +#define XK_dead_acute 0xFE51 +#define XK_dead_circumflex 0xFE52 +#define XK_dead_tilde 0xFE53 +#define XK_dead_macron 0xFE54 +#define XK_dead_breve 0xFE55 +#define XK_dead_abovedot 0xFE56 +#define XK_dead_diaeresis 0xFE57 +#define XK_dead_abovering 0xFE58 +#define XK_dead_doubleacute 0xFE59 +#define XK_dead_caron 0xFE5A +#define XK_dead_cedilla 0xFE5B +#define XK_dead_ogonek 0xFE5C +#define XK_dead_iota 0xFE5D +#define XK_dead_voiced_sound 0xFE5E +#define XK_dead_semivoiced_sound 0xFE5F +#define XK_dead_belowdot 0xFE60 +#define XK_dead_hook 0xFE61 +#define XK_dead_horn 0xFE62 + +#define XK_First_Virtual_Screen 0xFED0 +#define XK_Prev_Virtual_Screen 0xFED1 +#define XK_Next_Virtual_Screen 0xFED2 +#define XK_Last_Virtual_Screen 0xFED4 +#define XK_Terminate_Server 0xFED5 + +#define XK_AccessX_Enable 0xFE70 +#define XK_AccessX_Feedback_Enable 0xFE71 +#define XK_RepeatKeys_Enable 0xFE72 +#define XK_SlowKeys_Enable 0xFE73 +#define XK_BounceKeys_Enable 0xFE74 +#define XK_StickyKeys_Enable 0xFE75 +#define XK_MouseKeys_Enable 0xFE76 +#define XK_MouseKeys_Accel_Enable 0xFE77 +#define XK_Overlay1_Enable 0xFE78 +#define XK_Overlay2_Enable 0xFE79 +#define XK_AudibleBell_Enable 0xFE7A + +#define XK_Pointer_Left 0xFEE0 +#define XK_Pointer_Right 0xFEE1 +#define XK_Pointer_Up 0xFEE2 +#define XK_Pointer_Down 0xFEE3 +#define XK_Pointer_UpLeft 0xFEE4 +#define XK_Pointer_UpRight 0xFEE5 +#define XK_Pointer_DownLeft 0xFEE6 +#define XK_Pointer_DownRight 0xFEE7 +#define XK_Pointer_Button_Dflt 0xFEE8 +#define XK_Pointer_Button1 0xFEE9 +#define XK_Pointer_Button2 0xFEEA +#define XK_Pointer_Button3 0xFEEB +#define XK_Pointer_Button4 0xFEEC +#define XK_Pointer_Button5 0xFEED +#define XK_Pointer_DblClick_Dflt 0xFEEE +#define XK_Pointer_DblClick1 0xFEEF +#define XK_Pointer_DblClick2 0xFEF0 +#define XK_Pointer_DblClick3 0xFEF1 +#define XK_Pointer_DblClick4 0xFEF2 +#define XK_Pointer_DblClick5 0xFEF3 +#define XK_Pointer_Drag_Dflt 0xFEF4 +#define XK_Pointer_Drag1 0xFEF5 +#define XK_Pointer_Drag2 0xFEF6 +#define XK_Pointer_Drag3 0xFEF7 +#define XK_Pointer_Drag4 0xFEF8 +#define XK_Pointer_Drag5 0xFEFD + +#define XK_Pointer_EnableKeys 0xFEF9 +#define XK_Pointer_Accelerate 0xFEFA +#define XK_Pointer_DfltBtnNext 0xFEFB +#define XK_Pointer_DfltBtnPrev 0xFEFC + +#endif + +/* + * 3270 Terminal Keys + * Byte 3 = 0xFD + */ + +#ifdef XK_3270 +#define XK_3270_Duplicate 0xFD01 +#define XK_3270_FieldMark 0xFD02 +#define XK_3270_Right2 0xFD03 +#define XK_3270_Left2 0xFD04 +#define XK_3270_BackTab 0xFD05 +#define XK_3270_EraseEOF 0xFD06 +#define XK_3270_EraseInput 0xFD07 +#define XK_3270_Reset 0xFD08 +#define XK_3270_Quit 0xFD09 +#define XK_3270_PA1 0xFD0A +#define XK_3270_PA2 0xFD0B +#define XK_3270_PA3 0xFD0C +#define XK_3270_Test 0xFD0D +#define XK_3270_Attn 0xFD0E +#define XK_3270_CursorBlink 0xFD0F +#define XK_3270_AltCursor 0xFD10 +#define XK_3270_KeyClick 0xFD11 +#define XK_3270_Jump 0xFD12 +#define XK_3270_Ident 0xFD13 +#define XK_3270_Rule 0xFD14 +#define XK_3270_Copy 0xFD15 +#define XK_3270_Play 0xFD16 +#define XK_3270_Setup 0xFD17 +#define XK_3270_Record 0xFD18 +#define XK_3270_ChangeScreen 0xFD19 +#define XK_3270_DeleteWord 0xFD1A +#define XK_3270_ExSelect 0xFD1B +#define XK_3270_CursorSelect 0xFD1C +#define XK_3270_PrintScreen 0xFD1D +#define XK_3270_Enter 0xFD1E +#endif + +/* + * Latin 1 + * Byte 3 = 0 + */ +#ifdef XK_LATIN1 +#define XK_space 0x020 +#define XK_exclam 0x021 +#define XK_quotedbl 0x022 +#define XK_numbersign 0x023 +#define XK_dollar 0x024 +#define XK_percent 0x025 +#define XK_ampersand 0x026 +#define XK_apostrophe 0x027 +#define XK_quoteright 0x027 /* deprecated */ +#define XK_parenleft 0x028 +#define XK_parenright 0x029 +#define XK_asterisk 0x02a +#define XK_plus 0x02b +#define XK_comma 0x02c +#define XK_minus 0x02d +#define XK_period 0x02e +#define XK_slash 0x02f +#define XK_0 0x030 +#define XK_1 0x031 +#define XK_2 0x032 +#define XK_3 0x033 +#define XK_4 0x034 +#define XK_5 0x035 +#define XK_6 0x036 +#define XK_7 0x037 +#define XK_8 0x038 +#define XK_9 0x039 +#define XK_colon 0x03a +#define XK_semicolon 0x03b +#define XK_less 0x03c +#define XK_equal 0x03d +#define XK_greater 0x03e +#define XK_question 0x03f +#define XK_at 0x040 +#define XK_A 0x041 +#define XK_B 0x042 +#define XK_C 0x043 +#define XK_D 0x044 +#define XK_E 0x045 +#define XK_F 0x046 +#define XK_G 0x047 +#define XK_H 0x048 +#define XK_I 0x049 +#define XK_J 0x04a +#define XK_K 0x04b +#define XK_L 0x04c +#define XK_M 0x04d +#define XK_N 0x04e +#define XK_O 0x04f +#define XK_P 0x050 +#define XK_Q 0x051 +#define XK_R 0x052 +#define XK_S 0x053 +#define XK_T 0x054 +#define XK_U 0x055 +#define XK_V 0x056 +#define XK_W 0x057 +#define XK_X 0x058 +#define XK_Y 0x059 +#define XK_Z 0x05a +#define XK_bracketleft 0x05b +#define XK_backslash 0x05c +#define XK_bracketright 0x05d +#define XK_asciicircum 0x05e +#define XK_underscore 0x05f +#define XK_grave 0x060 +#define XK_quoteleft 0x060 /* deprecated */ +#define XK_a 0x061 +#define XK_b 0x062 +#define XK_c 0x063 +#define XK_d 0x064 +#define XK_e 0x065 +#define XK_f 0x066 +#define XK_g 0x067 +#define XK_h 0x068 +#define XK_i 0x069 +#define XK_j 0x06a +#define XK_k 0x06b +#define XK_l 0x06c +#define XK_m 0x06d +#define XK_n 0x06e +#define XK_o 0x06f +#define XK_p 0x070 +#define XK_q 0x071 +#define XK_r 0x072 +#define XK_s 0x073 +#define XK_t 0x074 +#define XK_u 0x075 +#define XK_v 0x076 +#define XK_w 0x077 +#define XK_x 0x078 +#define XK_y 0x079 +#define XK_z 0x07a +#define XK_braceleft 0x07b +#define XK_bar 0x07c +#define XK_braceright 0x07d +#define XK_asciitilde 0x07e + +#define XK_nobreakspace 0x0a0 +#define XK_exclamdown 0x0a1 +#define XK_cent 0x0a2 +#define XK_sterling 0x0a3 +#define XK_currency 0x0a4 +#define XK_yen 0x0a5 +#define XK_brokenbar 0x0a6 +#define XK_section 0x0a7 +#define XK_diaeresis 0x0a8 +#define XK_copyright 0x0a9 +#define XK_ordfeminine 0x0aa +#define XK_guillemotleft 0x0ab /* left angle quotation mark */ +#define XK_notsign 0x0ac +#define XK_hyphen 0x0ad +#define XK_registered 0x0ae +#define XK_macron 0x0af +#define XK_degree 0x0b0 +#define XK_plusminus 0x0b1 +#define XK_twosuperior 0x0b2 +#define XK_threesuperior 0x0b3 +#define XK_acute 0x0b4 +#define XK_mu 0x0b5 +#define XK_paragraph 0x0b6 +#define XK_periodcentered 0x0b7 +#define XK_cedilla 0x0b8 +#define XK_onesuperior 0x0b9 +#define XK_masculine 0x0ba +#define XK_guillemotright 0x0bb /* right angle quotation mark */ +#define XK_onequarter 0x0bc +#define XK_onehalf 0x0bd +#define XK_threequarters 0x0be +#define XK_questiondown 0x0bf +#define XK_Agrave 0x0c0 +#define XK_Aacute 0x0c1 +#define XK_Acircumflex 0x0c2 +#define XK_Atilde 0x0c3 +#define XK_Adiaeresis 0x0c4 +#define XK_Aring 0x0c5 +#define XK_AE 0x0c6 +#define XK_Ccedilla 0x0c7 +#define XK_Egrave 0x0c8 +#define XK_Eacute 0x0c9 +#define XK_Ecircumflex 0x0ca +#define XK_Ediaeresis 0x0cb +#define XK_Igrave 0x0cc +#define XK_Iacute 0x0cd +#define XK_Icircumflex 0x0ce +#define XK_Idiaeresis 0x0cf +#define XK_ETH 0x0d0 +#define XK_Eth 0x0d0 /* deprecated */ +#define XK_Ntilde 0x0d1 +#define XK_Ograve 0x0d2 +#define XK_Oacute 0x0d3 +#define XK_Ocircumflex 0x0d4 +#define XK_Otilde 0x0d5 +#define XK_Odiaeresis 0x0d6 +#define XK_multiply 0x0d7 +#define XK_Ooblique 0x0d8 +#define XK_Oslash XK_Ooblique +#define XK_Ugrave 0x0d9 +#define XK_Uacute 0x0da +#define XK_Ucircumflex 0x0db +#define XK_Udiaeresis 0x0dc +#define XK_Yacute 0x0dd +#define XK_THORN 0x0de +#define XK_Thorn 0x0de /* deprecated */ +#define XK_ssharp 0x0df +#define XK_agrave 0x0e0 +#define XK_aacute 0x0e1 +#define XK_acircumflex 0x0e2 +#define XK_atilde 0x0e3 +#define XK_adiaeresis 0x0e4 +#define XK_aring 0x0e5 +#define XK_ae 0x0e6 +#define XK_ccedilla 0x0e7 +#define XK_egrave 0x0e8 +#define XK_eacute 0x0e9 +#define XK_ecircumflex 0x0ea +#define XK_ediaeresis 0x0eb +#define XK_igrave 0x0ec +#define XK_iacute 0x0ed +#define XK_icircumflex 0x0ee +#define XK_idiaeresis 0x0ef +#define XK_eth 0x0f0 +#define XK_ntilde 0x0f1 +#define XK_ograve 0x0f2 +#define XK_oacute 0x0f3 +#define XK_ocircumflex 0x0f4 +#define XK_otilde 0x0f5 +#define XK_odiaeresis 0x0f6 +#define XK_division 0x0f7 +#define XK_oslash 0x0f8 +#define XK_ooblique XK_oslash +#define XK_ugrave 0x0f9 +#define XK_uacute 0x0fa +#define XK_ucircumflex 0x0fb +#define XK_udiaeresis 0x0fc +#define XK_yacute 0x0fd +#define XK_thorn 0x0fe +#define XK_ydiaeresis 0x0ff +#endif /* XK_LATIN1 */ + +/* + * Latin 2 + * Byte 3 = 1 + */ + +#ifdef XK_LATIN2 +#define XK_Aogonek 0x1a1 +#define XK_breve 0x1a2 +#define XK_Lstroke 0x1a3 +#define XK_Lcaron 0x1a5 +#define XK_Sacute 0x1a6 +#define XK_Scaron 0x1a9 +#define XK_Scedilla 0x1aa +#define XK_Tcaron 0x1ab +#define XK_Zacute 0x1ac +#define XK_Zcaron 0x1ae +#define XK_Zabovedot 0x1af +#define XK_aogonek 0x1b1 +#define XK_ogonek 0x1b2 +#define XK_lstroke 0x1b3 +#define XK_lcaron 0x1b5 +#define XK_sacute 0x1b6 +#define XK_caron 0x1b7 +#define XK_scaron 0x1b9 +#define XK_scedilla 0x1ba +#define XK_tcaron 0x1bb +#define XK_zacute 0x1bc +#define XK_doubleacute 0x1bd +#define XK_zcaron 0x1be +#define XK_zabovedot 0x1bf +#define XK_Racute 0x1c0 +#define XK_Abreve 0x1c3 +#define XK_Lacute 0x1c5 +#define XK_Cacute 0x1c6 +#define XK_Ccaron 0x1c8 +#define XK_Eogonek 0x1ca +#define XK_Ecaron 0x1cc +#define XK_Dcaron 0x1cf +#define XK_Dstroke 0x1d0 +#define XK_Nacute 0x1d1 +#define XK_Ncaron 0x1d2 +#define XK_Odoubleacute 0x1d5 +#define XK_Rcaron 0x1d8 +#define XK_Uring 0x1d9 +#define XK_Udoubleacute 0x1db +#define XK_Tcedilla 0x1de +#define XK_racute 0x1e0 +#define XK_abreve 0x1e3 +#define XK_lacute 0x1e5 +#define XK_cacute 0x1e6 +#define XK_ccaron 0x1e8 +#define XK_eogonek 0x1ea +#define XK_ecaron 0x1ec +#define XK_dcaron 0x1ef +#define XK_dstroke 0x1f0 +#define XK_nacute 0x1f1 +#define XK_ncaron 0x1f2 +#define XK_odoubleacute 0x1f5 +#define XK_udoubleacute 0x1fb +#define XK_rcaron 0x1f8 +#define XK_uring 0x1f9 +#define XK_tcedilla 0x1fe +#define XK_abovedot 0x1ff +#endif /* XK_LATIN2 */ + +/* + * Latin 3 + * Byte 3 = 2 + */ + +#ifdef XK_LATIN3 +#define XK_Hstroke 0x2a1 +#define XK_Hcircumflex 0x2a6 +#define XK_Iabovedot 0x2a9 +#define XK_Gbreve 0x2ab +#define XK_Jcircumflex 0x2ac +#define XK_hstroke 0x2b1 +#define XK_hcircumflex 0x2b6 +#define XK_idotless 0x2b9 +#define XK_gbreve 0x2bb +#define XK_jcircumflex 0x2bc +#define XK_Cabovedot 0x2c5 +#define XK_Ccircumflex 0x2c6 +#define XK_Gabovedot 0x2d5 +#define XK_Gcircumflex 0x2d8 +#define XK_Ubreve 0x2dd +#define XK_Scircumflex 0x2de +#define XK_cabovedot 0x2e5 +#define XK_ccircumflex 0x2e6 +#define XK_gabovedot 0x2f5 +#define XK_gcircumflex 0x2f8 +#define XK_ubreve 0x2fd +#define XK_scircumflex 0x2fe +#endif /* XK_LATIN3 */ + + +/* + * Latin 4 + * Byte 3 = 3 + */ + +#ifdef XK_LATIN4 +#define XK_kra 0x3a2 +#define XK_kappa 0x3a2 /* deprecated */ +#define XK_Rcedilla 0x3a3 +#define XK_Itilde 0x3a5 +#define XK_Lcedilla 0x3a6 +#define XK_Emacron 0x3aa +#define XK_Gcedilla 0x3ab +#define XK_Tslash 0x3ac +#define XK_rcedilla 0x3b3 +#define XK_itilde 0x3b5 +#define XK_lcedilla 0x3b6 +#define XK_emacron 0x3ba +#define XK_gcedilla 0x3bb +#define XK_tslash 0x3bc +#define XK_ENG 0x3bd +#define XK_eng 0x3bf +#define XK_Amacron 0x3c0 +#define XK_Iogonek 0x3c7 +#define XK_Eabovedot 0x3cc +#define XK_Imacron 0x3cf +#define XK_Ncedilla 0x3d1 +#define XK_Omacron 0x3d2 +#define XK_Kcedilla 0x3d3 +#define XK_Uogonek 0x3d9 +#define XK_Utilde 0x3dd +#define XK_Umacron 0x3de +#define XK_amacron 0x3e0 +#define XK_iogonek 0x3e7 +#define XK_eabovedot 0x3ec +#define XK_imacron 0x3ef +#define XK_ncedilla 0x3f1 +#define XK_omacron 0x3f2 +#define XK_kcedilla 0x3f3 +#define XK_uogonek 0x3f9 +#define XK_utilde 0x3fd +#define XK_umacron 0x3fe +#endif /* XK_LATIN4 */ + +/* + * Latin-8 + * Byte 3 = 18 + */ +#ifdef XK_LATIN8 +#define XK_Babovedot 0x12a1 +#define XK_babovedot 0x12a2 +#define XK_Dabovedot 0x12a6 +#define XK_Wgrave 0x12a8 +#define XK_Wacute 0x12aa +#define XK_dabovedot 0x12ab +#define XK_Ygrave 0x12ac +#define XK_Fabovedot 0x12b0 +#define XK_fabovedot 0x12b1 +#define XK_Mabovedot 0x12b4 +#define XK_mabovedot 0x12b5 +#define XK_Pabovedot 0x12b7 +#define XK_wgrave 0x12b8 +#define XK_pabovedot 0x12b9 +#define XK_wacute 0x12ba +#define XK_Sabovedot 0x12bb +#define XK_ygrave 0x12bc +#define XK_Wdiaeresis 0x12bd +#define XK_wdiaeresis 0x12be +#define XK_sabovedot 0x12bf +#define XK_Wcircumflex 0x12d0 +#define XK_Tabovedot 0x12d7 +#define XK_Ycircumflex 0x12de +#define XK_wcircumflex 0x12f0 +#define XK_tabovedot 0x12f7 +#define XK_ycircumflex 0x12fe +#endif /* XK_LATIN8 */ + +/* + * Latin-9 (a.k.a. Latin-0) + * Byte 3 = 19 + */ + +#ifdef XK_LATIN9 +#define XK_OE 0x13bc +#define XK_oe 0x13bd +#define XK_Ydiaeresis 0x13be +#endif /* XK_LATIN9 */ + +/* + * Katakana + * Byte 3 = 4 + */ + +#ifdef XK_KATAKANA +#define XK_overline 0x47e +#define XK_kana_fullstop 0x4a1 +#define XK_kana_openingbracket 0x4a2 +#define XK_kana_closingbracket 0x4a3 +#define XK_kana_comma 0x4a4 +#define XK_kana_conjunctive 0x4a5 +#define XK_kana_middledot 0x4a5 /* deprecated */ +#define XK_kana_WO 0x4a6 +#define XK_kana_a 0x4a7 +#define XK_kana_i 0x4a8 +#define XK_kana_u 0x4a9 +#define XK_kana_e 0x4aa +#define XK_kana_o 0x4ab +#define XK_kana_ya 0x4ac +#define XK_kana_yu 0x4ad +#define XK_kana_yo 0x4ae +#define XK_kana_tsu 0x4af +#define XK_kana_tu 0x4af /* deprecated */ +#define XK_prolongedsound 0x4b0 +#define XK_kana_A 0x4b1 +#define XK_kana_I 0x4b2 +#define XK_kana_U 0x4b3 +#define XK_kana_E 0x4b4 +#define XK_kana_O 0x4b5 +#define XK_kana_KA 0x4b6 +#define XK_kana_KI 0x4b7 +#define XK_kana_KU 0x4b8 +#define XK_kana_KE 0x4b9 +#define XK_kana_KO 0x4ba +#define XK_kana_SA 0x4bb +#define XK_kana_SHI 0x4bc +#define XK_kana_SU 0x4bd +#define XK_kana_SE 0x4be +#define XK_kana_SO 0x4bf +#define XK_kana_TA 0x4c0 +#define XK_kana_CHI 0x4c1 +#define XK_kana_TI 0x4c1 /* deprecated */ +#define XK_kana_TSU 0x4c2 +#define XK_kana_TU 0x4c2 /* deprecated */ +#define XK_kana_TE 0x4c3 +#define XK_kana_TO 0x4c4 +#define XK_kana_NA 0x4c5 +#define XK_kana_NI 0x4c6 +#define XK_kana_NU 0x4c7 +#define XK_kana_NE 0x4c8 +#define XK_kana_NO 0x4c9 +#define XK_kana_HA 0x4ca +#define XK_kana_HI 0x4cb +#define XK_kana_FU 0x4cc +#define XK_kana_HU 0x4cc /* deprecated */ +#define XK_kana_HE 0x4cd +#define XK_kana_HO 0x4ce +#define XK_kana_MA 0x4cf +#define XK_kana_MI 0x4d0 +#define XK_kana_MU 0x4d1 +#define XK_kana_ME 0x4d2 +#define XK_kana_MO 0x4d3 +#define XK_kana_YA 0x4d4 +#define XK_kana_YU 0x4d5 +#define XK_kana_YO 0x4d6 +#define XK_kana_RA 0x4d7 +#define XK_kana_RI 0x4d8 +#define XK_kana_RU 0x4d9 +#define XK_kana_RE 0x4da +#define XK_kana_RO 0x4db +#define XK_kana_WA 0x4dc +#define XK_kana_N 0x4dd +#define XK_voicedsound 0x4de +#define XK_semivoicedsound 0x4df +#define XK_kana_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_KATAKANA */ + +/* + * Arabic + * Byte 3 = 5 + */ + +#ifdef XK_ARABIC +#define XK_Farsi_0 0x590 +#define XK_Farsi_1 0x591 +#define XK_Farsi_2 0x592 +#define XK_Farsi_3 0x593 +#define XK_Farsi_4 0x594 +#define XK_Farsi_5 0x595 +#define XK_Farsi_6 0x596 +#define XK_Farsi_7 0x597 +#define XK_Farsi_8 0x598 +#define XK_Farsi_9 0x599 +#define XK_Arabic_percent 0x5a5 +#define XK_Arabic_superscript_alef 0x5a6 +#define XK_Arabic_tteh 0x5a7 +#define XK_Arabic_peh 0x5a8 +#define XK_Arabic_tcheh 0x5a9 +#define XK_Arabic_ddal 0x5aa +#define XK_Arabic_rreh 0x5ab +#define XK_Arabic_comma 0x5ac +#define XK_Arabic_fullstop 0x5ae +#define XK_Arabic_0 0x5b0 +#define XK_Arabic_1 0x5b1 +#define XK_Arabic_2 0x5b2 +#define XK_Arabic_3 0x5b3 +#define XK_Arabic_4 0x5b4 +#define XK_Arabic_5 0x5b5 +#define XK_Arabic_6 0x5b6 +#define XK_Arabic_7 0x5b7 +#define XK_Arabic_8 0x5b8 +#define XK_Arabic_9 0x5b9 +#define XK_Arabic_semicolon 0x5bb +#define XK_Arabic_question_mark 0x5bf +#define XK_Arabic_hamza 0x5c1 +#define XK_Arabic_maddaonalef 0x5c2 +#define XK_Arabic_hamzaonalef 0x5c3 +#define XK_Arabic_hamzaonwaw 0x5c4 +#define XK_Arabic_hamzaunderalef 0x5c5 +#define XK_Arabic_hamzaonyeh 0x5c6 +#define XK_Arabic_alef 0x5c7 +#define XK_Arabic_beh 0x5c8 +#define XK_Arabic_tehmarbuta 0x5c9 +#define XK_Arabic_teh 0x5ca +#define XK_Arabic_theh 0x5cb +#define XK_Arabic_jeem 0x5cc +#define XK_Arabic_hah 0x5cd +#define XK_Arabic_khah 0x5ce +#define XK_Arabic_dal 0x5cf +#define XK_Arabic_thal 0x5d0 +#define XK_Arabic_ra 0x5d1 +#define XK_Arabic_zain 0x5d2 +#define XK_Arabic_seen 0x5d3 +#define XK_Arabic_sheen 0x5d4 +#define XK_Arabic_sad 0x5d5 +#define XK_Arabic_dad 0x5d6 +#define XK_Arabic_tah 0x5d7 +#define XK_Arabic_zah 0x5d8 +#define XK_Arabic_ain 0x5d9 +#define XK_Arabic_ghain 0x5da +#define XK_Arabic_tatweel 0x5e0 +#define XK_Arabic_feh 0x5e1 +#define XK_Arabic_qaf 0x5e2 +#define XK_Arabic_kaf 0x5e3 +#define XK_Arabic_lam 0x5e4 +#define XK_Arabic_meem 0x5e5 +#define XK_Arabic_noon 0x5e6 +#define XK_Arabic_ha 0x5e7 +#define XK_Arabic_heh 0x5e7 /* deprecated */ +#define XK_Arabic_waw 0x5e8 +#define XK_Arabic_alefmaksura 0x5e9 +#define XK_Arabic_yeh 0x5ea +#define XK_Arabic_fathatan 0x5eb +#define XK_Arabic_dammatan 0x5ec +#define XK_Arabic_kasratan 0x5ed +#define XK_Arabic_fatha 0x5ee +#define XK_Arabic_damma 0x5ef +#define XK_Arabic_kasra 0x5f0 +#define XK_Arabic_shadda 0x5f1 +#define XK_Arabic_sukun 0x5f2 +#define XK_Arabic_madda_above 0x5f3 +#define XK_Arabic_hamza_above 0x5f4 +#define XK_Arabic_hamza_below 0x5f5 +#define XK_Arabic_jeh 0x5f6 +#define XK_Arabic_veh 0x5f7 +#define XK_Arabic_keheh 0x5f8 +#define XK_Arabic_gaf 0x5f9 +#define XK_Arabic_noon_ghunna 0x5fa +#define XK_Arabic_heh_doachashmee 0x5fb +#define XK_Farsi_yeh 0x5fc +#define XK_Arabic_farsi_yeh XK_Farsi_yeh +#define XK_Arabic_yeh_baree 0x5fd +#define XK_Arabic_heh_goal 0x5fe +#define XK_Arabic_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_ARABIC */ + +/* + * Cyrillic + * Byte 3 = 6 + */ +#ifdef XK_CYRILLIC +#define XK_Cyrillic_GHE_bar 0x680 +#define XK_Cyrillic_ghe_bar 0x690 +#define XK_Cyrillic_ZHE_descender 0x681 +#define XK_Cyrillic_zhe_descender 0x691 +#define XK_Cyrillic_KA_descender 0x682 +#define XK_Cyrillic_ka_descender 0x692 +#define XK_Cyrillic_KA_vertstroke 0x683 +#define XK_Cyrillic_ka_vertstroke 0x693 +#define XK_Cyrillic_EN_descender 0x684 +#define XK_Cyrillic_en_descender 0x694 +#define XK_Cyrillic_U_straight 0x685 +#define XK_Cyrillic_u_straight 0x695 +#define XK_Cyrillic_U_straight_bar 0x686 +#define XK_Cyrillic_u_straight_bar 0x696 +#define XK_Cyrillic_HA_descender 0x687 +#define XK_Cyrillic_ha_descender 0x697 +#define XK_Cyrillic_CHE_descender 0x688 +#define XK_Cyrillic_che_descender 0x698 +#define XK_Cyrillic_CHE_vertstroke 0x689 +#define XK_Cyrillic_che_vertstroke 0x699 +#define XK_Cyrillic_SHHA 0x68a +#define XK_Cyrillic_shha 0x69a + +#define XK_Cyrillic_SCHWA 0x68c +#define XK_Cyrillic_schwa 0x69c +#define XK_Cyrillic_I_macron 0x68d +#define XK_Cyrillic_i_macron 0x69d +#define XK_Cyrillic_O_bar 0x68e +#define XK_Cyrillic_o_bar 0x69e +#define XK_Cyrillic_U_macron 0x68f +#define XK_Cyrillic_u_macron 0x69f + +#define XK_Serbian_dje 0x6a1 +#define XK_Macedonia_gje 0x6a2 +#define XK_Cyrillic_io 0x6a3 +#define XK_Ukrainian_ie 0x6a4 +#define XK_Ukranian_je 0x6a4 /* deprecated */ +#define XK_Macedonia_dse 0x6a5 +#define XK_Ukrainian_i 0x6a6 +#define XK_Ukranian_i 0x6a6 /* deprecated */ +#define XK_Ukrainian_yi 0x6a7 +#define XK_Ukranian_yi 0x6a7 /* deprecated */ +#define XK_Cyrillic_je 0x6a8 +#define XK_Serbian_je 0x6a8 /* deprecated */ +#define XK_Cyrillic_lje 0x6a9 +#define XK_Serbian_lje 0x6a9 /* deprecated */ +#define XK_Cyrillic_nje 0x6aa +#define XK_Serbian_nje 0x6aa /* deprecated */ +#define XK_Serbian_tshe 0x6ab +#define XK_Macedonia_kje 0x6ac +#define XK_Ukrainian_ghe_with_upturn 0x6ad +#define XK_Byelorussian_shortu 0x6ae +#define XK_Cyrillic_dzhe 0x6af +#define XK_Serbian_dze 0x6af /* deprecated */ +#define XK_numerosign 0x6b0 +#define XK_Serbian_DJE 0x6b1 +#define XK_Macedonia_GJE 0x6b2 +#define XK_Cyrillic_IO 0x6b3 +#define XK_Ukrainian_IE 0x6b4 +#define XK_Ukranian_JE 0x6b4 /* deprecated */ +#define XK_Macedonia_DSE 0x6b5 +#define XK_Ukrainian_I 0x6b6 +#define XK_Ukranian_I 0x6b6 /* deprecated */ +#define XK_Ukrainian_YI 0x6b7 +#define XK_Ukranian_YI 0x6b7 /* deprecated */ +#define XK_Cyrillic_JE 0x6b8 +#define XK_Serbian_JE 0x6b8 /* deprecated */ +#define XK_Cyrillic_LJE 0x6b9 +#define XK_Serbian_LJE 0x6b9 /* deprecated */ +#define XK_Cyrillic_NJE 0x6ba +#define XK_Serbian_NJE 0x6ba /* deprecated */ +#define XK_Serbian_TSHE 0x6bb +#define XK_Macedonia_KJE 0x6bc +#define XK_Ukrainian_GHE_WITH_UPTURN 0x6bd +#define XK_Byelorussian_SHORTU 0x6be +#define XK_Cyrillic_DZHE 0x6bf +#define XK_Serbian_DZE 0x6bf /* deprecated */ +#define XK_Cyrillic_yu 0x6c0 +#define XK_Cyrillic_a 0x6c1 +#define XK_Cyrillic_be 0x6c2 +#define XK_Cyrillic_tse 0x6c3 +#define XK_Cyrillic_de 0x6c4 +#define XK_Cyrillic_ie 0x6c5 +#define XK_Cyrillic_ef 0x6c6 +#define XK_Cyrillic_ghe 0x6c7 +#define XK_Cyrillic_ha 0x6c8 +#define XK_Cyrillic_i 0x6c9 +#define XK_Cyrillic_shorti 0x6ca +#define XK_Cyrillic_ka 0x6cb +#define XK_Cyrillic_el 0x6cc +#define XK_Cyrillic_em 0x6cd +#define XK_Cyrillic_en 0x6ce +#define XK_Cyrillic_o 0x6cf +#define XK_Cyrillic_pe 0x6d0 +#define XK_Cyrillic_ya 0x6d1 +#define XK_Cyrillic_er 0x6d2 +#define XK_Cyrillic_es 0x6d3 +#define XK_Cyrillic_te 0x6d4 +#define XK_Cyrillic_u 0x6d5 +#define XK_Cyrillic_zhe 0x6d6 +#define XK_Cyrillic_ve 0x6d7 +#define XK_Cyrillic_softsign 0x6d8 +#define XK_Cyrillic_yeru 0x6d9 +#define XK_Cyrillic_ze 0x6da +#define XK_Cyrillic_sha 0x6db +#define XK_Cyrillic_e 0x6dc +#define XK_Cyrillic_shcha 0x6dd +#define XK_Cyrillic_che 0x6de +#define XK_Cyrillic_hardsign 0x6df +#define XK_Cyrillic_YU 0x6e0 +#define XK_Cyrillic_A 0x6e1 +#define XK_Cyrillic_BE 0x6e2 +#define XK_Cyrillic_TSE 0x6e3 +#define XK_Cyrillic_DE 0x6e4 +#define XK_Cyrillic_IE 0x6e5 +#define XK_Cyrillic_EF 0x6e6 +#define XK_Cyrillic_GHE 0x6e7 +#define XK_Cyrillic_HA 0x6e8 +#define XK_Cyrillic_I 0x6e9 +#define XK_Cyrillic_SHORTI 0x6ea +#define XK_Cyrillic_KA 0x6eb +#define XK_Cyrillic_EL 0x6ec +#define XK_Cyrillic_EM 0x6ed +#define XK_Cyrillic_EN 0x6ee +#define XK_Cyrillic_O 0x6ef +#define XK_Cyrillic_PE 0x6f0 +#define XK_Cyrillic_YA 0x6f1 +#define XK_Cyrillic_ER 0x6f2 +#define XK_Cyrillic_ES 0x6f3 +#define XK_Cyrillic_TE 0x6f4 +#define XK_Cyrillic_U 0x6f5 +#define XK_Cyrillic_ZHE 0x6f6 +#define XK_Cyrillic_VE 0x6f7 +#define XK_Cyrillic_SOFTSIGN 0x6f8 +#define XK_Cyrillic_YERU 0x6f9 +#define XK_Cyrillic_ZE 0x6fa +#define XK_Cyrillic_SHA 0x6fb +#define XK_Cyrillic_E 0x6fc +#define XK_Cyrillic_SHCHA 0x6fd +#define XK_Cyrillic_CHE 0x6fe +#define XK_Cyrillic_HARDSIGN 0x6ff +#endif /* XK_CYRILLIC */ + +/* + * Greek + * Byte 3 = 7 + */ + +#ifdef XK_GREEK +#define XK_Greek_ALPHAaccent 0x7a1 +#define XK_Greek_EPSILONaccent 0x7a2 +#define XK_Greek_ETAaccent 0x7a3 +#define XK_Greek_IOTAaccent 0x7a4 +#define XK_Greek_IOTAdieresis 0x7a5 +#define XK_Greek_IOTAdiaeresis XK_Greek_IOTAdieresis /* old typo */ +#define XK_Greek_OMICRONaccent 0x7a7 +#define XK_Greek_UPSILONaccent 0x7a8 +#define XK_Greek_UPSILONdieresis 0x7a9 +#define XK_Greek_OMEGAaccent 0x7ab +#define XK_Greek_accentdieresis 0x7ae +#define XK_Greek_horizbar 0x7af +#define XK_Greek_alphaaccent 0x7b1 +#define XK_Greek_epsilonaccent 0x7b2 +#define XK_Greek_etaaccent 0x7b3 +#define XK_Greek_iotaaccent 0x7b4 +#define XK_Greek_iotadieresis 0x7b5 +#define XK_Greek_iotaaccentdieresis 0x7b6 +#define XK_Greek_omicronaccent 0x7b7 +#define XK_Greek_upsilonaccent 0x7b8 +#define XK_Greek_upsilondieresis 0x7b9 +#define XK_Greek_upsilonaccentdieresis 0x7ba +#define XK_Greek_omegaaccent 0x7bb +#define XK_Greek_ALPHA 0x7c1 +#define XK_Greek_BETA 0x7c2 +#define XK_Greek_GAMMA 0x7c3 +#define XK_Greek_DELTA 0x7c4 +#define XK_Greek_EPSILON 0x7c5 +#define XK_Greek_ZETA 0x7c6 +#define XK_Greek_ETA 0x7c7 +#define XK_Greek_THETA 0x7c8 +#define XK_Greek_IOTA 0x7c9 +#define XK_Greek_KAPPA 0x7ca +#define XK_Greek_LAMDA 0x7cb +#define XK_Greek_LAMBDA 0x7cb +#define XK_Greek_MU 0x7cc +#define XK_Greek_NU 0x7cd +#define XK_Greek_XI 0x7ce +#define XK_Greek_OMICRON 0x7cf +#define XK_Greek_PI 0x7d0 +#define XK_Greek_RHO 0x7d1 +#define XK_Greek_SIGMA 0x7d2 +#define XK_Greek_TAU 0x7d4 +#define XK_Greek_UPSILON 0x7d5 +#define XK_Greek_PHI 0x7d6 +#define XK_Greek_CHI 0x7d7 +#define XK_Greek_PSI 0x7d8 +#define XK_Greek_OMEGA 0x7d9 +#define XK_Greek_alpha 0x7e1 +#define XK_Greek_beta 0x7e2 +#define XK_Greek_gamma 0x7e3 +#define XK_Greek_delta 0x7e4 +#define XK_Greek_epsilon 0x7e5 +#define XK_Greek_zeta 0x7e6 +#define XK_Greek_eta 0x7e7 +#define XK_Greek_theta 0x7e8 +#define XK_Greek_iota 0x7e9 +#define XK_Greek_kappa 0x7ea +#define XK_Greek_lamda 0x7eb +#define XK_Greek_lambda 0x7eb +#define XK_Greek_mu 0x7ec +#define XK_Greek_nu 0x7ed +#define XK_Greek_xi 0x7ee +#define XK_Greek_omicron 0x7ef +#define XK_Greek_pi 0x7f0 +#define XK_Greek_rho 0x7f1 +#define XK_Greek_sigma 0x7f2 +#define XK_Greek_finalsmallsigma 0x7f3 +#define XK_Greek_tau 0x7f4 +#define XK_Greek_upsilon 0x7f5 +#define XK_Greek_phi 0x7f6 +#define XK_Greek_chi 0x7f7 +#define XK_Greek_psi 0x7f8 +#define XK_Greek_omega 0x7f9 +#define XK_Greek_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_GREEK */ + +/* + * Technical + * Byte 3 = 8 + */ + +#ifdef XK_TECHNICAL +#define XK_leftradical 0x8a1 +#define XK_topleftradical 0x8a2 +#define XK_horizconnector 0x8a3 +#define XK_topintegral 0x8a4 +#define XK_botintegral 0x8a5 +#define XK_vertconnector 0x8a6 +#define XK_topleftsqbracket 0x8a7 +#define XK_botleftsqbracket 0x8a8 +#define XK_toprightsqbracket 0x8a9 +#define XK_botrightsqbracket 0x8aa +#define XK_topleftparens 0x8ab +#define XK_botleftparens 0x8ac +#define XK_toprightparens 0x8ad +#define XK_botrightparens 0x8ae +#define XK_leftmiddlecurlybrace 0x8af +#define XK_rightmiddlecurlybrace 0x8b0 +#define XK_topleftsummation 0x8b1 +#define XK_botleftsummation 0x8b2 +#define XK_topvertsummationconnector 0x8b3 +#define XK_botvertsummationconnector 0x8b4 +#define XK_toprightsummation 0x8b5 +#define XK_botrightsummation 0x8b6 +#define XK_rightmiddlesummation 0x8b7 +#define XK_lessthanequal 0x8bc +#define XK_notequal 0x8bd +#define XK_greaterthanequal 0x8be +#define XK_integral 0x8bf +#define XK_therefore 0x8c0 +#define XK_variation 0x8c1 +#define XK_infinity 0x8c2 +#define XK_nabla 0x8c5 +#define XK_approximate 0x8c8 +#define XK_similarequal 0x8c9 +#define XK_ifonlyif 0x8cd +#define XK_implies 0x8ce +#define XK_identical 0x8cf +#define XK_radical 0x8d6 +#define XK_includedin 0x8da +#define XK_includes 0x8db +#define XK_intersection 0x8dc +#define XK_union 0x8dd +#define XK_logicaland 0x8de +#define XK_logicalor 0x8df +#define XK_partialderivative 0x8ef +#define XK_function 0x8f6 +#define XK_leftarrow 0x8fb +#define XK_uparrow 0x8fc +#define XK_rightarrow 0x8fd +#define XK_downarrow 0x8fe +#endif /* XK_TECHNICAL */ + +/* + * Special + * Byte 3 = 9 + */ + +#ifdef XK_SPECIAL +#define XK_blank 0x9df +#define XK_soliddiamond 0x9e0 +#define XK_checkerboard 0x9e1 +#define XK_ht 0x9e2 +#define XK_ff 0x9e3 +#define XK_cr 0x9e4 +#define XK_lf 0x9e5 +#define XK_nl 0x9e8 +#define XK_vt 0x9e9 +#define XK_lowrightcorner 0x9ea +#define XK_uprightcorner 0x9eb +#define XK_upleftcorner 0x9ec +#define XK_lowleftcorner 0x9ed +#define XK_crossinglines 0x9ee +#define XK_horizlinescan1 0x9ef +#define XK_horizlinescan3 0x9f0 +#define XK_horizlinescan5 0x9f1 +#define XK_horizlinescan7 0x9f2 +#define XK_horizlinescan9 0x9f3 +#define XK_leftt 0x9f4 +#define XK_rightt 0x9f5 +#define XK_bott 0x9f6 +#define XK_topt 0x9f7 +#define XK_vertbar 0x9f8 +#endif /* XK_SPECIAL */ + +/* + * Publishing + * Byte 3 = a + */ + +#ifdef XK_PUBLISHING +#define XK_emspace 0xaa1 +#define XK_enspace 0xaa2 +#define XK_em3space 0xaa3 +#define XK_em4space 0xaa4 +#define XK_digitspace 0xaa5 +#define XK_punctspace 0xaa6 +#define XK_thinspace 0xaa7 +#define XK_hairspace 0xaa8 +#define XK_emdash 0xaa9 +#define XK_endash 0xaaa +#define XK_signifblank 0xaac +#define XK_ellipsis 0xaae +#define XK_doubbaselinedot 0xaaf +#define XK_onethird 0xab0 +#define XK_twothirds 0xab1 +#define XK_onefifth 0xab2 +#define XK_twofifths 0xab3 +#define XK_threefifths 0xab4 +#define XK_fourfifths 0xab5 +#define XK_onesixth 0xab6 +#define XK_fivesixths 0xab7 +#define XK_careof 0xab8 +#define XK_figdash 0xabb +#define XK_leftanglebracket 0xabc +#define XK_decimalpoint 0xabd +#define XK_rightanglebracket 0xabe +#define XK_marker 0xabf +#define XK_oneeighth 0xac3 +#define XK_threeeighths 0xac4 +#define XK_fiveeighths 0xac5 +#define XK_seveneighths 0xac6 +#define XK_trademark 0xac9 +#define XK_signaturemark 0xaca +#define XK_trademarkincircle 0xacb +#define XK_leftopentriangle 0xacc +#define XK_rightopentriangle 0xacd +#define XK_emopencircle 0xace +#define XK_emopenrectangle 0xacf +#define XK_leftsinglequotemark 0xad0 +#define XK_rightsinglequotemark 0xad1 +#define XK_leftdoublequotemark 0xad2 +#define XK_rightdoublequotemark 0xad3 +#define XK_prescription 0xad4 +#define XK_minutes 0xad6 +#define XK_seconds 0xad7 +#define XK_latincross 0xad9 +#define XK_hexagram 0xada +#define XK_filledrectbullet 0xadb +#define XK_filledlefttribullet 0xadc +#define XK_filledrighttribullet 0xadd +#define XK_emfilledcircle 0xade +#define XK_emfilledrect 0xadf +#define XK_enopencircbullet 0xae0 +#define XK_enopensquarebullet 0xae1 +#define XK_openrectbullet 0xae2 +#define XK_opentribulletup 0xae3 +#define XK_opentribulletdown 0xae4 +#define XK_openstar 0xae5 +#define XK_enfilledcircbullet 0xae6 +#define XK_enfilledsqbullet 0xae7 +#define XK_filledtribulletup 0xae8 +#define XK_filledtribulletdown 0xae9 +#define XK_leftpointer 0xaea +#define XK_rightpointer 0xaeb +#define XK_club 0xaec +#define XK_diamond 0xaed +#define XK_heart 0xaee +#define XK_maltesecross 0xaf0 +#define XK_dagger 0xaf1 +#define XK_doubledagger 0xaf2 +#define XK_checkmark 0xaf3 +#define XK_ballotcross 0xaf4 +#define XK_musicalsharp 0xaf5 +#define XK_musicalflat 0xaf6 +#define XK_malesymbol 0xaf7 +#define XK_femalesymbol 0xaf8 +#define XK_telephone 0xaf9 +#define XK_telephonerecorder 0xafa +#define XK_phonographcopyright 0xafb +#define XK_caret 0xafc +#define XK_singlelowquotemark 0xafd +#define XK_doublelowquotemark 0xafe +#define XK_cursor 0xaff +#endif /* XK_PUBLISHING */ + +/* + * APL + * Byte 3 = b + */ + +#ifdef XK_APL +#define XK_leftcaret 0xba3 +#define XK_rightcaret 0xba6 +#define XK_downcaret 0xba8 +#define XK_upcaret 0xba9 +#define XK_overbar 0xbc0 +#define XK_downtack 0xbc2 +#define XK_upshoe 0xbc3 +#define XK_downstile 0xbc4 +#define XK_underbar 0xbc6 +#define XK_jot 0xbca +#define XK_quad 0xbcc +#define XK_uptack 0xbce +#define XK_circle 0xbcf +#define XK_upstile 0xbd3 +#define XK_downshoe 0xbd6 +#define XK_rightshoe 0xbd8 +#define XK_leftshoe 0xbda +#define XK_lefttack 0xbdc +#define XK_righttack 0xbfc +#endif /* XK_APL */ + +/* + * Hebrew + * Byte 3 = c + */ + +#ifdef XK_HEBREW +#define XK_hebrew_doublelowline 0xcdf +#define XK_hebrew_aleph 0xce0 +#define XK_hebrew_bet 0xce1 +#define XK_hebrew_beth 0xce1 /* deprecated */ +#define XK_hebrew_gimel 0xce2 +#define XK_hebrew_gimmel 0xce2 /* deprecated */ +#define XK_hebrew_dalet 0xce3 +#define XK_hebrew_daleth 0xce3 /* deprecated */ +#define XK_hebrew_he 0xce4 +#define XK_hebrew_waw 0xce5 +#define XK_hebrew_zain 0xce6 +#define XK_hebrew_zayin 0xce6 /* deprecated */ +#define XK_hebrew_chet 0xce7 +#define XK_hebrew_het 0xce7 /* deprecated */ +#define XK_hebrew_tet 0xce8 +#define XK_hebrew_teth 0xce8 /* deprecated */ +#define XK_hebrew_yod 0xce9 +#define XK_hebrew_finalkaph 0xcea +#define XK_hebrew_kaph 0xceb +#define XK_hebrew_lamed 0xcec +#define XK_hebrew_finalmem 0xced +#define XK_hebrew_mem 0xcee +#define XK_hebrew_finalnun 0xcef +#define XK_hebrew_nun 0xcf0 +#define XK_hebrew_samech 0xcf1 +#define XK_hebrew_samekh 0xcf1 /* deprecated */ +#define XK_hebrew_ayin 0xcf2 +#define XK_hebrew_finalpe 0xcf3 +#define XK_hebrew_pe 0xcf4 +#define XK_hebrew_finalzade 0xcf5 +#define XK_hebrew_finalzadi 0xcf5 /* deprecated */ +#define XK_hebrew_zade 0xcf6 +#define XK_hebrew_zadi 0xcf6 /* deprecated */ +#define XK_hebrew_qoph 0xcf7 +#define XK_hebrew_kuf 0xcf7 /* deprecated */ +#define XK_hebrew_resh 0xcf8 +#define XK_hebrew_shin 0xcf9 +#define XK_hebrew_taw 0xcfa +#define XK_hebrew_taf 0xcfa /* deprecated */ +#define XK_Hebrew_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_HEBREW */ + +/* + * Thai + * Byte 3 = d + */ + +#ifdef XK_THAI +#define XK_Thai_kokai 0xda1 +#define XK_Thai_khokhai 0xda2 +#define XK_Thai_khokhuat 0xda3 +#define XK_Thai_khokhwai 0xda4 +#define XK_Thai_khokhon 0xda5 +#define XK_Thai_khorakhang 0xda6 +#define XK_Thai_ngongu 0xda7 +#define XK_Thai_chochan 0xda8 +#define XK_Thai_choching 0xda9 +#define XK_Thai_chochang 0xdaa +#define XK_Thai_soso 0xdab +#define XK_Thai_chochoe 0xdac +#define XK_Thai_yoying 0xdad +#define XK_Thai_dochada 0xdae +#define XK_Thai_topatak 0xdaf +#define XK_Thai_thothan 0xdb0 +#define XK_Thai_thonangmontho 0xdb1 +#define XK_Thai_thophuthao 0xdb2 +#define XK_Thai_nonen 0xdb3 +#define XK_Thai_dodek 0xdb4 +#define XK_Thai_totao 0xdb5 +#define XK_Thai_thothung 0xdb6 +#define XK_Thai_thothahan 0xdb7 +#define XK_Thai_thothong 0xdb8 +#define XK_Thai_nonu 0xdb9 +#define XK_Thai_bobaimai 0xdba +#define XK_Thai_popla 0xdbb +#define XK_Thai_phophung 0xdbc +#define XK_Thai_fofa 0xdbd +#define XK_Thai_phophan 0xdbe +#define XK_Thai_fofan 0xdbf +#define XK_Thai_phosamphao 0xdc0 +#define XK_Thai_moma 0xdc1 +#define XK_Thai_yoyak 0xdc2 +#define XK_Thai_rorua 0xdc3 +#define XK_Thai_ru 0xdc4 +#define XK_Thai_loling 0xdc5 +#define XK_Thai_lu 0xdc6 +#define XK_Thai_wowaen 0xdc7 +#define XK_Thai_sosala 0xdc8 +#define XK_Thai_sorusi 0xdc9 +#define XK_Thai_sosua 0xdca +#define XK_Thai_hohip 0xdcb +#define XK_Thai_lochula 0xdcc +#define XK_Thai_oang 0xdcd +#define XK_Thai_honokhuk 0xdce +#define XK_Thai_paiyannoi 0xdcf +#define XK_Thai_saraa 0xdd0 +#define XK_Thai_maihanakat 0xdd1 +#define XK_Thai_saraaa 0xdd2 +#define XK_Thai_saraam 0xdd3 +#define XK_Thai_sarai 0xdd4 +#define XK_Thai_saraii 0xdd5 +#define XK_Thai_saraue 0xdd6 +#define XK_Thai_sarauee 0xdd7 +#define XK_Thai_sarau 0xdd8 +#define XK_Thai_sarauu 0xdd9 +#define XK_Thai_phinthu 0xdda +#define XK_Thai_maihanakat_maitho 0xdde +#define XK_Thai_baht 0xddf +#define XK_Thai_sarae 0xde0 +#define XK_Thai_saraae 0xde1 +#define XK_Thai_sarao 0xde2 +#define XK_Thai_saraaimaimuan 0xde3 +#define XK_Thai_saraaimaimalai 0xde4 +#define XK_Thai_lakkhangyao 0xde5 +#define XK_Thai_maiyamok 0xde6 +#define XK_Thai_maitaikhu 0xde7 +#define XK_Thai_maiek 0xde8 +#define XK_Thai_maitho 0xde9 +#define XK_Thai_maitri 0xdea +#define XK_Thai_maichattawa 0xdeb +#define XK_Thai_thanthakhat 0xdec +#define XK_Thai_nikhahit 0xded +#define XK_Thai_leksun 0xdf0 +#define XK_Thai_leknung 0xdf1 +#define XK_Thai_leksong 0xdf2 +#define XK_Thai_leksam 0xdf3 +#define XK_Thai_leksi 0xdf4 +#define XK_Thai_lekha 0xdf5 +#define XK_Thai_lekhok 0xdf6 +#define XK_Thai_lekchet 0xdf7 +#define XK_Thai_lekpaet 0xdf8 +#define XK_Thai_lekkao 0xdf9 +#endif /* XK_THAI */ + +/* + * Korean + * Byte 3 = e + */ + +#ifdef XK_KOREAN + +#define XK_Hangul 0xff31 /* Hangul start/stop(toggle) */ +#define XK_Hangul_Start 0xff32 /* Hangul start */ +#define XK_Hangul_End 0xff33 /* Hangul end, English start */ +#define XK_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */ +#define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */ +#define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */ +#define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */ +#define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */ +#define XK_Hangul_Banja 0xff39 /* Banja mode */ +#define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */ +#define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */ +#define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */ +#define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */ +#define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */ +#define XK_Hangul_Special 0xff3f /* Special symbols */ +#define XK_Hangul_switch 0xFF7E /* Alias for mode_switch */ + +/* Hangul Consonant Characters */ +#define XK_Hangul_Kiyeog 0xea1 +#define XK_Hangul_SsangKiyeog 0xea2 +#define XK_Hangul_KiyeogSios 0xea3 +#define XK_Hangul_Nieun 0xea4 +#define XK_Hangul_NieunJieuj 0xea5 +#define XK_Hangul_NieunHieuh 0xea6 +#define XK_Hangul_Dikeud 0xea7 +#define XK_Hangul_SsangDikeud 0xea8 +#define XK_Hangul_Rieul 0xea9 +#define XK_Hangul_RieulKiyeog 0xeaa +#define XK_Hangul_RieulMieum 0xeab +#define XK_Hangul_RieulPieub 0xeac +#define XK_Hangul_RieulSios 0xead +#define XK_Hangul_RieulTieut 0xeae +#define XK_Hangul_RieulPhieuf 0xeaf +#define XK_Hangul_RieulHieuh 0xeb0 +#define XK_Hangul_Mieum 0xeb1 +#define XK_Hangul_Pieub 0xeb2 +#define XK_Hangul_SsangPieub 0xeb3 +#define XK_Hangul_PieubSios 0xeb4 +#define XK_Hangul_Sios 0xeb5 +#define XK_Hangul_SsangSios 0xeb6 +#define XK_Hangul_Ieung 0xeb7 +#define XK_Hangul_Jieuj 0xeb8 +#define XK_Hangul_SsangJieuj 0xeb9 +#define XK_Hangul_Cieuc 0xeba +#define XK_Hangul_Khieuq 0xebb +#define XK_Hangul_Tieut 0xebc +#define XK_Hangul_Phieuf 0xebd +#define XK_Hangul_Hieuh 0xebe + +/* Hangul Vowel Characters */ +#define XK_Hangul_A 0xebf +#define XK_Hangul_AE 0xec0 +#define XK_Hangul_YA 0xec1 +#define XK_Hangul_YAE 0xec2 +#define XK_Hangul_EO 0xec3 +#define XK_Hangul_E 0xec4 +#define XK_Hangul_YEO 0xec5 +#define XK_Hangul_YE 0xec6 +#define XK_Hangul_O 0xec7 +#define XK_Hangul_WA 0xec8 +#define XK_Hangul_WAE 0xec9 +#define XK_Hangul_OE 0xeca +#define XK_Hangul_YO 0xecb +#define XK_Hangul_U 0xecc +#define XK_Hangul_WEO 0xecd +#define XK_Hangul_WE 0xece +#define XK_Hangul_WI 0xecf +#define XK_Hangul_YU 0xed0 +#define XK_Hangul_EU 0xed1 +#define XK_Hangul_YI 0xed2 +#define XK_Hangul_I 0xed3 + +/* Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_Kiyeog 0xed4 +#define XK_Hangul_J_SsangKiyeog 0xed5 +#define XK_Hangul_J_KiyeogSios 0xed6 +#define XK_Hangul_J_Nieun 0xed7 +#define XK_Hangul_J_NieunJieuj 0xed8 +#define XK_Hangul_J_NieunHieuh 0xed9 +#define XK_Hangul_J_Dikeud 0xeda +#define XK_Hangul_J_Rieul 0xedb +#define XK_Hangul_J_RieulKiyeog 0xedc +#define XK_Hangul_J_RieulMieum 0xedd +#define XK_Hangul_J_RieulPieub 0xede +#define XK_Hangul_J_RieulSios 0xedf +#define XK_Hangul_J_RieulTieut 0xee0 +#define XK_Hangul_J_RieulPhieuf 0xee1 +#define XK_Hangul_J_RieulHieuh 0xee2 +#define XK_Hangul_J_Mieum 0xee3 +#define XK_Hangul_J_Pieub 0xee4 +#define XK_Hangul_J_PieubSios 0xee5 +#define XK_Hangul_J_Sios 0xee6 +#define XK_Hangul_J_SsangSios 0xee7 +#define XK_Hangul_J_Ieung 0xee8 +#define XK_Hangul_J_Jieuj 0xee9 +#define XK_Hangul_J_Cieuc 0xeea +#define XK_Hangul_J_Khieuq 0xeeb +#define XK_Hangul_J_Tieut 0xeec +#define XK_Hangul_J_Phieuf 0xeed +#define XK_Hangul_J_Hieuh 0xeee + +/* Ancient Hangul Consonant Characters */ +#define XK_Hangul_RieulYeorinHieuh 0xeef +#define XK_Hangul_SunkyeongeumMieum 0xef0 +#define XK_Hangul_SunkyeongeumPieub 0xef1 +#define XK_Hangul_PanSios 0xef2 +#define XK_Hangul_KkogjiDalrinIeung 0xef3 +#define XK_Hangul_SunkyeongeumPhieuf 0xef4 +#define XK_Hangul_YeorinHieuh 0xef5 + +/* Ancient Hangul Vowel Characters */ +#define XK_Hangul_AraeA 0xef6 +#define XK_Hangul_AraeAE 0xef7 + +/* Ancient Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_PanSios 0xef8 +#define XK_Hangul_J_KkogjiDalrinIeung 0xef9 +#define XK_Hangul_J_YeorinHieuh 0xefa + +/* Korean currency symbol */ +#define XK_Korean_Won 0xeff + +#endif /* XK_KOREAN */ + +/* + * Armenian + * Byte 3 = 0x14 + */ + +#ifdef XK_ARMENIAN +#define XK_Armenian_eternity 0x14a1 +#define XK_Armenian_ligature_ew 0x14a2 +#define XK_Armenian_full_stop 0x14a3 +#define XK_Armenian_verjaket 0x14a3 +#define XK_Armenian_parenright 0x14a4 +#define XK_Armenian_parenleft 0x14a5 +#define XK_Armenian_guillemotright 0x14a6 +#define XK_Armenian_guillemotleft 0x14a7 +#define XK_Armenian_em_dash 0x14a8 +#define XK_Armenian_dot 0x14a9 +#define XK_Armenian_mijaket 0x14a9 +#define XK_Armenian_separation_mark 0x14aa +#define XK_Armenian_but 0x14aa +#define XK_Armenian_comma 0x14ab +#define XK_Armenian_en_dash 0x14ac +#define XK_Armenian_hyphen 0x14ad +#define XK_Armenian_yentamna 0x14ad +#define XK_Armenian_ellipsis 0x14ae +#define XK_Armenian_exclam 0x14af +#define XK_Armenian_amanak 0x14af +#define XK_Armenian_accent 0x14b0 +#define XK_Armenian_shesht 0x14b0 +#define XK_Armenian_question 0x14b1 +#define XK_Armenian_paruyk 0x14b1 +#define XK_Armenian_AYB 0x14b2 +#define XK_Armenian_ayb 0x14b3 +#define XK_Armenian_BEN 0x14b4 +#define XK_Armenian_ben 0x14b5 +#define XK_Armenian_GIM 0x14b6 +#define XK_Armenian_gim 0x14b7 +#define XK_Armenian_DA 0x14b8 +#define XK_Armenian_da 0x14b9 +#define XK_Armenian_YECH 0x14ba +#define XK_Armenian_yech 0x14bb +#define XK_Armenian_ZA 0x14bc +#define XK_Armenian_za 0x14bd +#define XK_Armenian_E 0x14be +#define XK_Armenian_e 0x14bf +#define XK_Armenian_AT 0x14c0 +#define XK_Armenian_at 0x14c1 +#define XK_Armenian_TO 0x14c2 +#define XK_Armenian_to 0x14c3 +#define XK_Armenian_ZHE 0x14c4 +#define XK_Armenian_zhe 0x14c5 +#define XK_Armenian_INI 0x14c6 +#define XK_Armenian_ini 0x14c7 +#define XK_Armenian_LYUN 0x14c8 +#define XK_Armenian_lyun 0x14c9 +#define XK_Armenian_KHE 0x14ca +#define XK_Armenian_khe 0x14cb +#define XK_Armenian_TSA 0x14cc +#define XK_Armenian_tsa 0x14cd +#define XK_Armenian_KEN 0x14ce +#define XK_Armenian_ken 0x14cf +#define XK_Armenian_HO 0x14d0 +#define XK_Armenian_ho 0x14d1 +#define XK_Armenian_DZA 0x14d2 +#define XK_Armenian_dza 0x14d3 +#define XK_Armenian_GHAT 0x14d4 +#define XK_Armenian_ghat 0x14d5 +#define XK_Armenian_TCHE 0x14d6 +#define XK_Armenian_tche 0x14d7 +#define XK_Armenian_MEN 0x14d8 +#define XK_Armenian_men 0x14d9 +#define XK_Armenian_HI 0x14da +#define XK_Armenian_hi 0x14db +#define XK_Armenian_NU 0x14dc +#define XK_Armenian_nu 0x14dd +#define XK_Armenian_SHA 0x14de +#define XK_Armenian_sha 0x14df +#define XK_Armenian_VO 0x14e0 +#define XK_Armenian_vo 0x14e1 +#define XK_Armenian_CHA 0x14e2 +#define XK_Armenian_cha 0x14e3 +#define XK_Armenian_PE 0x14e4 +#define XK_Armenian_pe 0x14e5 +#define XK_Armenian_JE 0x14e6 +#define XK_Armenian_je 0x14e7 +#define XK_Armenian_RA 0x14e8 +#define XK_Armenian_ra 0x14e9 +#define XK_Armenian_SE 0x14ea +#define XK_Armenian_se 0x14eb +#define XK_Armenian_VEV 0x14ec +#define XK_Armenian_vev 0x14ed +#define XK_Armenian_TYUN 0x14ee +#define XK_Armenian_tyun 0x14ef +#define XK_Armenian_RE 0x14f0 +#define XK_Armenian_re 0x14f1 +#define XK_Armenian_TSO 0x14f2 +#define XK_Armenian_tso 0x14f3 +#define XK_Armenian_VYUN 0x14f4 +#define XK_Armenian_vyun 0x14f5 +#define XK_Armenian_PYUR 0x14f6 +#define XK_Armenian_pyur 0x14f7 +#define XK_Armenian_KE 0x14f8 +#define XK_Armenian_ke 0x14f9 +#define XK_Armenian_O 0x14fa +#define XK_Armenian_o 0x14fb +#define XK_Armenian_FE 0x14fc +#define XK_Armenian_fe 0x14fd +#define XK_Armenian_apostrophe 0x14fe +#define XK_Armenian_section_sign 0x14ff +#endif /* XK_ARMENIAN */ + +/* + * Georgian + * Byte 3 = 0x15 + */ + +#ifdef XK_GEORGIAN +#define XK_Georgian_an 0x15d0 +#define XK_Georgian_ban 0x15d1 +#define XK_Georgian_gan 0x15d2 +#define XK_Georgian_don 0x15d3 +#define XK_Georgian_en 0x15d4 +#define XK_Georgian_vin 0x15d5 +#define XK_Georgian_zen 0x15d6 +#define XK_Georgian_tan 0x15d7 +#define XK_Georgian_in 0x15d8 +#define XK_Georgian_kan 0x15d9 +#define XK_Georgian_las 0x15da +#define XK_Georgian_man 0x15db +#define XK_Georgian_nar 0x15dc +#define XK_Georgian_on 0x15dd +#define XK_Georgian_par 0x15de +#define XK_Georgian_zhar 0x15df +#define XK_Georgian_rae 0x15e0 +#define XK_Georgian_san 0x15e1 +#define XK_Georgian_tar 0x15e2 +#define XK_Georgian_un 0x15e3 +#define XK_Georgian_phar 0x15e4 +#define XK_Georgian_khar 0x15e5 +#define XK_Georgian_ghan 0x15e6 +#define XK_Georgian_qar 0x15e7 +#define XK_Georgian_shin 0x15e8 +#define XK_Georgian_chin 0x15e9 +#define XK_Georgian_can 0x15ea +#define XK_Georgian_jil 0x15eb +#define XK_Georgian_cil 0x15ec +#define XK_Georgian_char 0x15ed +#define XK_Georgian_xan 0x15ee +#define XK_Georgian_jhan 0x15ef +#define XK_Georgian_hae 0x15f0 +#define XK_Georgian_he 0x15f1 +#define XK_Georgian_hie 0x15f2 +#define XK_Georgian_we 0x15f3 +#define XK_Georgian_har 0x15f4 +#define XK_Georgian_hoe 0x15f5 +#define XK_Georgian_fi 0x15f6 +#endif /* XK_GEORGIAN */ + +/* + * Azeri (and other Turkic or Caucasian languages of ex-USSR) + * Byte 3 = 0x16 + */ + +#ifdef XK_CAUCASUS +/* latin */ +#define XK_Ccedillaabovedot 0x16a2 +#define XK_Xabovedot 0x16a3 +#define XK_Qabovedot 0x16a5 +#define XK_Ibreve 0x16a6 +#define XK_IE 0x16a7 +#define XK_UO 0x16a8 +#define XK_Zstroke 0x16a9 +#define XK_Gcaron 0x16aa +#define XK_Obarred 0x16af +#define XK_ccedillaabovedot 0x16b2 +#define XK_xabovedot 0x16b3 +#define XK_Ocaron 0x16b4 +#define XK_qabovedot 0x16b5 +#define XK_ibreve 0x16b6 +#define XK_ie 0x16b7 +#define XK_uo 0x16b8 +#define XK_zstroke 0x16b9 +#define XK_gcaron 0x16ba +#define XK_ocaron 0x16bd +#define XK_obarred 0x16bf +#define XK_SCHWA 0x16c6 +#define XK_schwa 0x16f6 +/* those are not really Caucasus, but I put them here for now */ +/* For Inupiak */ +#define XK_Lbelowdot 0x16d1 +#define XK_Lstrokebelowdot 0x16d2 +#define XK_lbelowdot 0x16e1 +#define XK_lstrokebelowdot 0x16e2 +/* For Guarani */ +#define XK_Gtilde 0x16d3 +#define XK_gtilde 0x16e3 +#endif /* XK_CAUCASUS */ + +/* + * Vietnamese + * Byte 3 = 0x1e + */ + +#ifdef XK_VIETNAMESE +#define XK_Abelowdot 0x1ea0 +#define XK_abelowdot 0x1ea1 +#define XK_Ahook 0x1ea2 +#define XK_ahook 0x1ea3 +#define XK_Acircumflexacute 0x1ea4 +#define XK_acircumflexacute 0x1ea5 +#define XK_Acircumflexgrave 0x1ea6 +#define XK_acircumflexgrave 0x1ea7 +#define XK_Acircumflexhook 0x1ea8 +#define XK_acircumflexhook 0x1ea9 +#define XK_Acircumflextilde 0x1eaa +#define XK_acircumflextilde 0x1eab +#define XK_Acircumflexbelowdot 0x1eac +#define XK_acircumflexbelowdot 0x1ead +#define XK_Abreveacute 0x1eae +#define XK_abreveacute 0x1eaf +#define XK_Abrevegrave 0x1eb0 +#define XK_abrevegrave 0x1eb1 +#define XK_Abrevehook 0x1eb2 +#define XK_abrevehook 0x1eb3 +#define XK_Abrevetilde 0x1eb4 +#define XK_abrevetilde 0x1eb5 +#define XK_Abrevebelowdot 0x1eb6 +#define XK_abrevebelowdot 0x1eb7 +#define XK_Ebelowdot 0x1eb8 +#define XK_ebelowdot 0x1eb9 +#define XK_Ehook 0x1eba +#define XK_ehook 0x1ebb +#define XK_Etilde 0x1ebc +#define XK_etilde 0x1ebd +#define XK_Ecircumflexacute 0x1ebe +#define XK_ecircumflexacute 0x1ebf +#define XK_Ecircumflexgrave 0x1ec0 +#define XK_ecircumflexgrave 0x1ec1 +#define XK_Ecircumflexhook 0x1ec2 +#define XK_ecircumflexhook 0x1ec3 +#define XK_Ecircumflextilde 0x1ec4 +#define XK_ecircumflextilde 0x1ec5 +#define XK_Ecircumflexbelowdot 0x1ec6 +#define XK_ecircumflexbelowdot 0x1ec7 +#define XK_Ihook 0x1ec8 +#define XK_ihook 0x1ec9 +#define XK_Ibelowdot 0x1eca +#define XK_ibelowdot 0x1ecb +#define XK_Obelowdot 0x1ecc +#define XK_obelowdot 0x1ecd +#define XK_Ohook 0x1ece +#define XK_ohook 0x1ecf +#define XK_Ocircumflexacute 0x1ed0 +#define XK_ocircumflexacute 0x1ed1 +#define XK_Ocircumflexgrave 0x1ed2 +#define XK_ocircumflexgrave 0x1ed3 +#define XK_Ocircumflexhook 0x1ed4 +#define XK_ocircumflexhook 0x1ed5 +#define XK_Ocircumflextilde 0x1ed6 +#define XK_ocircumflextilde 0x1ed7 +#define XK_Ocircumflexbelowdot 0x1ed8 +#define XK_ocircumflexbelowdot 0x1ed9 +#define XK_Ohornacute 0x1eda +#define XK_ohornacute 0x1edb +#define XK_Ohorngrave 0x1edc +#define XK_ohorngrave 0x1edd +#define XK_Ohornhook 0x1ede +#define XK_ohornhook 0x1edf +#define XK_Ohorntilde 0x1ee0 +#define XK_ohorntilde 0x1ee1 +#define XK_Ohornbelowdot 0x1ee2 +#define XK_ohornbelowdot 0x1ee3 +#define XK_Ubelowdot 0x1ee4 +#define XK_ubelowdot 0x1ee5 +#define XK_Uhook 0x1ee6 +#define XK_uhook 0x1ee7 +#define XK_Uhornacute 0x1ee8 +#define XK_uhornacute 0x1ee9 +#define XK_Uhorngrave 0x1eea +#define XK_uhorngrave 0x1eeb +#define XK_Uhornhook 0x1eec +#define XK_uhornhook 0x1eed +#define XK_Uhorntilde 0x1eee +#define XK_uhorntilde 0x1eef +#define XK_Uhornbelowdot 0x1ef0 +#define XK_uhornbelowdot 0x1ef1 +#define XK_Ybelowdot 0x1ef4 +#define XK_ybelowdot 0x1ef5 +#define XK_Yhook 0x1ef6 +#define XK_yhook 0x1ef7 +#define XK_Ytilde 0x1ef8 +#define XK_ytilde 0x1ef9 +#define XK_Ohorn 0x1efa /* U+01a0 */ +#define XK_ohorn 0x1efb /* U+01a1 */ +#define XK_Uhorn 0x1efc /* U+01af */ +#define XK_uhorn 0x1efd /* U+01b0 */ + +#define XK_combining_tilde 0x1e9f /* U+0303 */ +#define XK_combining_grave 0x1ef2 /* U+0300 */ +#define XK_combining_acute 0x1ef3 /* U+0301 */ +#define XK_combining_hook 0x1efe /* U+0309 */ +#define XK_combining_belowdot 0x1eff /* U+0323 */ +#endif /* XK_VIETNAMESE */ + +#ifdef XK_CURRENCY +#define XK_EcuSign 0x20a0 +#define XK_ColonSign 0x20a1 +#define XK_CruzeiroSign 0x20a2 +#define XK_FFrancSign 0x20a3 +#define XK_LiraSign 0x20a4 +#define XK_MillSign 0x20a5 +#define XK_NairaSign 0x20a6 +#define XK_PesetaSign 0x20a7 +#define XK_RupeeSign 0x20a8 +#define XK_WonSign 0x20a9 +#define XK_NewSheqelSign 0x20aa +#define XK_DongSign 0x20ab +#define XK_EuroSign 0x20ac +#endif + + +#endif //_INCLUDE_KEY_SYM_H diff --git a/programs/games/checkers/trunk/makefile b/programs/games/checkers/trunk/makefile new file mode 100644 index 0000000000..045c71ebd6 --- /dev/null +++ b/programs/games/checkers/trunk/makefile @@ -0,0 +1,4 @@ +checkers : checkers.o + g++ -L/usr/X11R6/lib -lX11 -o checkers checkers.o +checkers.o : checkers.cpp board.h position.h player.h tmplayer.h buttons.h history.h hash.h gr-draw.h gnu-draw.h sysproc.h + g++ -c checkers.cpp diff --git a/programs/games/checkers/trunk/me_make.inc b/programs/games/checkers/trunk/me_make.inc new file mode 100644 index 0000000000..173c2eb927 --- /dev/null +++ b/programs/games/checkers/trunk/me_make.inc @@ -0,0 +1,10 @@ +;//NAME// checkers.cpp +;//COMPILER// bcc32 -S -v- -R- -6 -a4 -O2 -Og -Oi -Ov -OS -k- -D__MENUET__ -Iinclude +;//UTIL_PATH// . + +STACKSIZE equ 102400 +HEAPSIZE equ 102400 + +include "include\me_start.inc" +include "include\me_func.inc" +include "include\me_heap.inc" diff --git a/programs/games/checkers/trunk/mt-draw.h b/programs/games/checkers/trunk/mt-draw.h new file mode 100644 index 0000000000..3adce2b73a --- /dev/null +++ b/programs/games/checkers/trunk/mt-draw.h @@ -0,0 +1,79 @@ +unsigned long cur_color; +class TKlbrGraphDraw : public TGraphDraw +{ +public: + virtual int SetColor(unsigned long c) {cur_color=c;return 1;} + virtual int DrawLine(int x0, int y0, int x1, int y1); + virtual int DrawText(int x0, int y0, char* text); + virtual int IsDraw(void) {return 1;} + virtual int DrawClear(); + virtual unsigned long CreateColor(unsigned short red, + unsigned short green, unsigned short blue); + virtual void GetSize(int &w, int &h); + virtual int GetTextH(const char *s) {return 10;} + virtual int GetTextW(const char *s) {return 6 * strlen(s);} + virtual void Quit(int q = 1) {CloseWindow();} +}; +int TKlbrGraphDraw::DrawLine(int x0, int y0, int x1, int y1) +{ + asm mov ebx, x0 + asm shl ebx, 16 + asm add ebx, x1 + asm mov ecx, y0 + asm shl ecx, 16 + asm add ecx, y1 + asm mov edx, [cur_color] + asm push 38 + asm pop eax + asm int 40h + return 1; +} +int TKlbrGraphDraw::DrawText(int x0, int y0, char* text) +{ + asm mov ebx, x0 + asm shl ebx, 16 + asm add ebx, y0 + asm mov ecx, [cur_color] + asm or ecx, 0xC0000000 + asm mov edx, text + asm mov edi, 0xFFFFFF + asm push 4 + asm pop eax + asm int 40h + return 1; +} +int TKlbrGraphDraw::DrawClear(void) +{ + int w,h; + GetSize(w,h); + asm mov ebx, w + asm mov ecx, h + asm mov edx, 0xFFFFFF + asm push 13 + asm pop eax + asm int 40h + return 1; +} +unsigned long TKlbrGraphDraw::CreateColor(unsigned short red, + unsigned short green, unsigned short blue) +{ + return (unsigned long)(blue >> 8) + ((unsigned long)(green >> 8) << 8) + + ((unsigned long)(red >> 8) << 16); +} +void TKlbrGraphDraw::GetSize(int &w, int &h) +{ + int width, height; + asm sub esp, 1024 + asm mov ebx, esp + asm or ecx, -1 + asm push 9 + asm pop eax + asm int 40h + asm mov eax, [esp+62] + asm mov width, eax + asm mov eax, [esp+66] + asm mov height, eax + asm add esp, 1024 + w = width; + h = height; +} diff --git a/programs/games/checkers/trunk/player.h b/programs/games/checkers/trunk/player.h new file mode 100644 index 0000000000..8eff1ce459 --- /dev/null +++ b/programs/games/checkers/trunk/player.h @@ -0,0 +1,888 @@ +#ifndef _HEADER_PLAYER_H +#define _HEADER_PLAYER_H + +#include "position.h" +#include "sysproc.h" +#ifndef __MENUET__ +#include +#include +#include +#endif + +template +class TBaseCompPlayer : public TChPlayer +{ +public: + static const int PKind; + static const tvalue win_val; +public: + TBaseCompPlayer() : draw(0), data(0) {} + + virtual int PlayerID() {return PKind;} + virtual int Move(PMv &pmv); + + struct PMvv : public PMv + { + tvalue val; + }; + + struct Z + { + Z(int marr = 400) : narr(0), marr(marr) {array = new PMvv[marr];} + ~Z() {Clear();} + + void Clear() {if (array) {delete[] array; array = 0;} marr = 0; narr = 0;} + void AddPos(int n); + void AddPos() {AddPos(narr + 1);} + int FindAllMoves(PMv pmv, int onlyeat = 0); + void FindSideEats(PMv &pmv, int k, int sx, int sy); + + static int ComparePMv(const void *v1, const void *v2); + void Sort(int n0, int n1); + + int marr, narr; + PMvv *array; + }; + + static tvalue GetLossValue(const Position &pos); + virtual tvalue GetValue(const Position &pos, int num = 0); + tvalue GetFullValue(const Position &pos, int num = 0); + tvalue FindBMove(Z &z, int num, PMvv *pmv, int zn = -1, + tvalue a = -2 * win_val, tvalue b = 2 * win_val); +public: + void (*draw)(void*, int = 0); + void *data; +}; + +template +const int TBaseCompPlayer::PKind = 0x2000; + +template +const tvalue TBaseCompPlayer::win_val = (tvalue)10000000L; + +template +void TBaseCompPlayer::Z::AddPos(int n) +{ + if (marr < n) + { + int m0 = marr; + PMvv *arr0 = array; + marr = 2*n + 10; + array = new PMvv[marr]; + if (arr0) + { + int i; + for (i = 0; i < m0; i++) array[i] = arr0[i]; + delete[] arr0; + } + } +} + +template +void TBaseCompPlayer::Z::FindSideEats(PMv &pmv, int k, int sx, int sy) +{ + int x, y; + NumToPole(k, x, y); + if (pmv.pos.SH[k] == pmv.pos.wmove + 1) + { + int xx = x + 2*sx, yy = y + 2*sy; + if (xx >= 0 && xx < NW_CELL && yy >= 0 && yy < NW_CELL) + { + int kk = PoleToNum(xx, yy); + if (pmv.pos.SH[kk] == 0) + { + int k1 = PoleToNum(x + sx, y + sy); + char nk1 = pmv.pos.SH[k1]; + if (nk1 == 2 - pmv.pos.wmove || nk1 == 4 - pmv.pos.wmove) + { + char SH_k1 = pmv.pos.SH[k1]; + pmv.pos.Del(k1); pmv.pos.Move(k, kk); + if (pmv.pos.wmove == 0 && yy == NW_CELL - 1 || + pmv.pos.wmove == 1 && yy == 0) pmv.pos.SH[kk] += (char)2; + pmv.mv[++pmv.mv[0]] = (char)kk; + int nold = narr; + FindSideEats(pmv, kk, sx, sy); + FindSideEats(pmv, kk, sy, -sx); + FindSideEats(pmv, kk, -sy, sx); + if (narr == nold) + { + AddPos(); + (PMv&)array[narr] = pmv; + array[narr].pos.wmove = !pmv.pos.wmove; + narr++; + } + pmv.mv[0]--; + pmv.pos.SH[k1] = SH_k1; pmv.pos.Del(kk); + pmv.pos.SH[k] = char(pmv.pos.wmove + 1); + } + } + } + } + else if (pmv.pos.SH[k] == pmv.pos.wmove + 3) + { + int i, i0, i1; + if (sx < 0) i0 = x; + else i0 = NW_CELL - x - 1; + if (sy < 0) i1 = y; + else i1 = NW_CELL - y - 1; + if (i0 > i1) i0 = i1; + if (i0 >= 2) + { + pmv.pos.Del(k); + pmv.mv[0]++; + i1 = -1; + int kk, kk1; + char SH_kk1; + int nold = narr; + for (i = 1; i <= i0; i++) + { + kk = PoleToNum(x + i*sx, y + i*sy); + char chh = pmv.pos.SH[kk]; + if (chh) + { + if (i1 >= 0 || (chh != 2 - pmv.pos.wmove && chh != 4 - pmv.pos.wmove)) break; + else + { + i1 = i; kk1 = kk; + SH_kk1 = chh; + pmv.pos.Del(kk1); + } + } + else if (i1 >= 0) + { + pmv.pos.SH[kk] = char(pmv.pos.wmove + 3); + pmv.mv[pmv.mv[0]] = (char)kk; + if (i == i1+1) FindSideEats(pmv, kk, sx, sy); + FindSideEats(pmv, kk, sy, -sx); + FindSideEats(pmv, kk, -sy, sx); + pmv.pos.Del(kk); + } + } + if (narr == nold && i1 >= 0) + { + while (--i > i1) + { + kk = PoleToNum(x + i*sx, y + i*sy); + AddPos(); + (PMv&)array[narr] = pmv; + array[narr].pos.SH[kk] = char(pmv.pos.wmove + 3); + array[narr].mv[pmv.mv[0]] = (char)kk; + array[narr].pos.wmove = !pmv.pos.wmove; + narr++; + } + } + pmv.mv[0]--; + pmv.pos.SH[k] = char(pmv.pos.wmove + 3); + if (i1 >= 0) pmv.pos.SH[kk1] = SH_kk1; + } + } +} + +template +int TBaseCompPlayer::Z::FindAllMoves(PMv pmv, int onlyeat) +{ + int k, nold = narr, was_eat = 1; + pmv.mv[0] = 1; + for (k = 0; k < NUM_CELL; k++) + { + if (pmv.pos.SH[k] == pmv.pos.wmove + 1 || pmv.pos.SH[k] == pmv.pos.wmove + 3) + { + pmv.mv[1] = (char)k; + FindSideEats(pmv, k, 1, 1); + FindSideEats(pmv, k, 1, -1); + FindSideEats(pmv, k, -1, 1); + FindSideEats(pmv, k, -1, -1); + } + } + if (narr == nold) + { + was_eat = 0; + if (!onlyeat) + { + pmv.mv[0] = 2; + for (k = 0; k < NUM_CELL; k++) + { + if (pmv.pos.SH[k] == pmv.pos.wmove + 1) + { + pmv.mv[1] = (char)k; + int x, x0, x1, y; + NumToPole(k, x0, y); + if (pmv.pos.wmove == 1) y--; else y++; + if (y >= 0 && y < NW_CELL) + { + int kk; + x1 = (x0--) + 1; + for (x = x0; x <= x1; x += 2) if (x >= 0 && x < NW_CELL) + { + kk = PoleToNum(x, y); + if (pmv.pos.SH[kk] == 0) + { + AddPos(); + (PMv&)array[narr] = pmv; + array[narr].pos.Del(k); + if (pmv.pos.wmove == 0 && y == NW_CELL - 1 || + pmv.pos.wmove == 1 && y == 0) + { + array[narr].pos.Add(kk, char(pmv.pos.wmove + 3)); + } + else array[narr].pos.Add(kk, char(pmv.pos.wmove + 1)); + array[narr].mv[2] = (char)kk; + array[narr].pos.wmove = !pmv.pos.wmove; + narr++; + } + } + } + } + else if (pmv.pos.SH[k] == pmv.pos.wmove + 3) + { + pmv.mv[1] = (char)k; + int x, y, sx, sy; + NumToPole(k, x, y); + for (sx = -1; sx <= 1; sx += 2) if (x + sx >= 0 && x + sx < NW_CELL) + { + for (sy = -1; sy <= 1; sy += 2) if (y + sy >= 0 && y + sy < NW_CELL) + { + int i, i0, i1; + if (sx < 0) i0 = x; + else i0 = NW_CELL - x - 1; + if (sy < 0) i1 = y; + else i1 = NW_CELL - y - 1; + if (i0 > i1) i0 = i1; + for (i = 1; i <= i0; i++) + { + int kk = PoleToNum(x + i*sx, y + i*sy); + if (pmv.pos.SH[kk]) break; + AddPos(); + (PMv&)array[narr] = pmv; + array[narr].pos.Move(k, kk); + array[narr].mv[2] = (char)kk; + array[narr].pos.wmove = !pmv.pos.wmove; + narr++; + } + } + } + } + } + } + } + pmv.mv[0] = 0; + return was_eat; +} + +template +int TBaseCompPlayer::Z::ComparePMv(const void *v1, const void *v2) +{ + PMvv *pmv1 = (PMvv*)v1, *pmv2 = (PMvv*)v2; + if (pmv1->val < pmv2->val) return -1; + else if (pmv1->val > pmv2->val) return 1; + else return 0; +} + +template +void TBaseCompPlayer::Z::Sort(int n0, int n1) +{ + qsort(array + n0, n1 - n0, sizeof(PMvv), ComparePMv); +} + + +template +tvalue TBaseCompPlayer::GetLossValue(const Position &pos) +{ + tvalue val = -win_val - 1000021L; + for (int i = 0; i < NUM_CELL; i++) + { + if (pos.SH[i] == 1 + pos.wmove) val -= 10000L; + else if (pos.SH[i] == 2 - pos.wmove) val -= 100L; + else if (pos.SH[i] == 3 + pos.wmove) val -= 80000L; + else if (pos.SH[i] == 4 - pos.wmove) val -= 100L; + } + return val; +} + +template +tvalue TBaseCompPlayer::GetValue(const Position &pos, int num) +{ + tvalue val = 0; + if (num == 0) + { + int NumDM0 = 0, NumDM1 = 0; + for (int i = 0; i < NUM_CELL; i++) + { + short PreimSHPos[32] = {243, 243, 243, 245, + 240, 240, 240, 240, + 244, 244, 244, 244, + 245, 248, 248, 245, + 249, 250, 250, 248, + 256, 260, 260, 256, + 280, 280, 280, 260, + 280, 280, 280, 280}; + if (pos.SH[i] == 1 + pos.wmove) + { + val += PreimSHPos[pos.wmove ? (NUM_CELL - 1 - i) : i]; + } + else if (pos.SH[i] == 2 - pos.wmove) + { + val -= PreimSHPos[pos.wmove ? i : (NUM_CELL - 1 - i)]; + } + else if (pos.SH[i] == 3 + pos.wmove) NumDM1++; + else if (pos.SH[i] == 4 - pos.wmove) NumDM0++; + } + if (NumDM1 > 0) + { + val += 560; NumDM1--; + if (NumDM1 > 0) + { + val += 432; NumDM1--; + val += NumDM1 * 384; + } + } + if (NumDM0 > 0) + { + val -= 560; NumDM0--; + if (NumDM0 > 0) + { + val -= 432; NumDM0--; + val -= NumDM0 * 384; + } + } + } + if (num == 1) + { + char NSH1 = 0, NSH0 = 0, NDM1 = 0, NDM0 = 0; + int i; + for (i = 0; i < 32; i++) + { + if (pos.SH[i] == 1 + pos.wmove) NSH1++; + else if (pos.SH[i] == 2 - pos.wmove) NSH0++; + else if (pos.SH[i] == 3 + pos.wmove) NDM1++; + else if (pos.SH[i] == 4 - pos.wmove) NDM0++; + } + if (NDM1 > 0 && NDM0 > 0 && NSH1 + NSH0 < 3) + { + unsigned char HwoBD = 0; + char Sh0BD = 1, Sh1BD = 1; + for (i = 0; i < 8; i++) + { + char ShBD = pos.SH[PoleToNum(i, 7 - i)]; + if (ShBD == 1 + pos.wmove) Sh1BD++; + else if (ShBD == 2 - pos.wmove) Sh0BD++; + else if (ShBD == 3 + pos.wmove) HwoBD |= 2; + else if (ShBD == 4 - pos.wmove) HwoBD |= 1; + } + if (HwoBD == 2) val += 128 / Sh0BD; + if (HwoBD == 1) val -= 128 / Sh1BD; + if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 1) + { + char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}}; + char Add = 0; + for (i = 0; i < 4; i++) + { + Add |= char((pos.SH[Best4P[i][0]] == 3 + pos.wmove) * 3 + + (pos.SH[Best4P[i][1]] == 3 + pos.wmove)); + } + if (Add >= 4) val += 32; + else if (Add == 3) val += 24; + else if (Add >= 1) val += 16; + } + else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 2) + { + char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}}; + char Add = 0; + for (i = 0; i < 4; i++) + { + Add |= char((pos.SH[Best4P[i][0]] == 4 - pos.wmove) * 3 + + (pos.SH[Best4P[i][1]] == 4 - pos.wmove)); + } + if (Add >= 4) val -= 32; + else if (Add == 3) val -= 24; + else if (Add >= 1) val -= 16; + } + } + else + { + for (i = 0; i < NUM_CELL; i++) + { + char Color = char(pos.SH[i] - 1); + if (Color == 0 || Color == 1) + { + char qi = Color ? char(NUM_CELL - 1 - i) : char(i); + char Zn = Color ? char(-1) : char(1); + char PreZ = (Color == pos.wmove) ? char(1) : char(-1); + if (pos.SH[i + Zn * 8] != 2 - Color) + { + if (qi / 4 == 2) + { + char IsFree = 0; + if (pos.SH[i - Zn * 4] == 2 - Color) IsFree += (char)2; + else if (qi != 8) + { + if (pos.SH[i - Zn ] == 2 - Color || + pos.SH[i - Zn * 9] == 2 - Color) IsFree += (char)2; + else if (Color != pos.wmove) + if (pos.SH[i - Zn * 5] == 2 - Color) IsFree++; + } + if (qi == 11) IsFree += (char)2; + else if (pos.SH[i + Zn ] == 2 - Color || + pos.SH[i - Zn * 3] == 2 - Color || + pos.SH[i - Zn * 7] == 2 - Color) IsFree += (char)2; + else if (Color != pos.wmove && qi != 10) + { + if (pos.SH[i - Zn * 2] == 2 - Color) IsFree++; + } + if (IsFree < 3) val += PreZ * 176 / (1 + NDM0 + NDM1); + else if (qi == 9 || qi == 10) + { + val += PreZ * 128 / (1 + NDM0 + NDM1); + } + } + else if (qi / 4 == 3) + { + char IsFree = 0; + if (pos.SH[i - Zn * 12] == 2 - Color) + { + if (Color == pos.wmove) IsFree += (char)11; + else IsFree += (char)12; + } + else if (pos.SH[i - Zn * 4] == 2 - Color) IsFree += (char)11; + else if (qi == 15) IsFree += (char)5; + else if (pos.SH[i - Zn * 7] == 2 - Color) IsFree += (char)9; + else if (pos.SH[i + Zn] == 2 - Color) IsFree += (char)8; + else if (pos.SH[i - Zn * 11] == 2 - Color) + { + if (Color == pos.wmove) IsFree += (char)5; + else IsFree += (char)7; + } + else if (pos.SH[i - Zn * 3] == 2 - Color) IsFree += (char)5; + else if (qi != 14) + { + if (pos.SH[i - Zn * 6] == 2 - Color) IsFree += (char)3; + else if (Color != pos.wmove) + { + if (pos.SH[i - Zn * 10] == 2 - Color) IsFree++; + } + } + if (qi == 12) IsFree += (char)7; + else if (pos.SH[i - Zn * 13] == 2 - Color) + { + if (Color == pos.wmove) IsFree += (char)11; + else IsFree += (char)12; + } + else if (pos.SH[i - Zn * 5] == 2 - Color) IsFree += (char)11; + else if (pos.SH[i - Zn * 9] == 2 - Color) IsFree += (char)9; + else if (pos.SH[i - Zn] == 2 - Color) IsFree += (char)8; + else if (qi != 13) + { + if (pos.SH[i - Zn * 14] == 2 - Color) + { + if (Color == pos.wmove) IsFree += (char)5; + else IsFree += (char)7; + } + else if (pos.SH[i - Zn * 6] == 2 - Color) IsFree += (char)5; + else if (pos.SH[i - Zn * 10] == 2 - Color) IsFree += (char)3; + else if (Color != pos.wmove && qi != 14) + { + if (pos.SH[i - Zn * 15] == 2 - Color) IsFree++; + } + } + if (IsFree < ((Color == pos.wmove) ? 14 : 12)) + { + val += PreZ * 160 / (1 + NDM0 + NDM1); + } + } + } + } + } + } + } + if (num == 2) + { + char NSH1 = 0, NSH0 = 0, NDM1 = 0, NDM0 = 0; + for (int i = 0; i < NUM_CELL; i++) + { + if (pos.SH[i] == 1 + pos.wmove) NSH1++; + else if (pos.SH[i] == 2 - pos.wmove) NSH0++; + else if (pos.SH[i] == 3 + pos.wmove) NDM1++; + else if (pos.SH[i] == 4 - pos.wmove) NDM0++; + } + if (NDM1 > 0 && NDM0 > 0 && NSH1 == 0 && NSH0 == 0) + { + short PrP = 0; + char Cpos3 = -1; + if (NDM1 == 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0) Cpos3 = 1; + else if (NDM1 == 1 && NDM0 == 3 && NSH1 == 0 && NSH0 == 0) Cpos3 = 0; + if (Cpos3 >= 0) + { + for (int Osm = 0; Osm <= 1; Osm++) for (int Csm = 0; Csm <= 1; Csm++) + { + char PosSH[7][3] = {{13, 17, 18}, {6, 17, 18}, {9, 21, 22}, + {17, 18, 19}, {9, 10, 15}, {11, 14, 18}, {2, 14, 18}}; + for (char PosNi = 0; PosNi < 7; PosNi++) + { + bool IsPosR = 1; + for (char ShNi = 0; ShNi < 3; ShNi++) + { + char DNomSh = (Csm == 1) ? char(31 - PosSH[PosNi][ShNi]) + : char(PosSH[PosNi][ShNi]); + if (Osm == 1) + { + int x, y; + NumToPole(DNomSh, x, y); + DNomSh = (char)PoleToNum(y, x); + } + if (pos.SH[DNomSh] != 3 + (Cpos3 == pos.wmove)) IsPosR = 0; + } + if (IsPosR) + { + if (PosNi == 3) + { + if (Cpos3 == 1) + { + if (pos.SH[(Csm == 1) ? 29 : 2] != + 4 - (Cpos3 == pos.wmove) && pos.SH[(Csm == 1) ? 11 : 20] != + 4 - (Cpos3 == pos.wmove)) PrP = 216; + } + else + { + bool PrPZ = 1; + for (int i = 0; i < 6; i++) + if (pos.SH[PoleToNum((Csm == 1) ? (i + 2) : i, + (Csm == 1) ? (7 - i) : (5 - i))] == + 4 - (Cpos3 == pos.wmove)) PrPZ = 0; + if (PrPZ) PrP = -216; + } + } + else if (PosNi == 4) + { + if (Cpos3 == 1) + { + if (pos.SH[ 0] != 4 - (Cpos3 == pos.wmove) && + pos.SH[ 4] != 4 - (Cpos3 == pos.wmove) && + pos.SH[27] != 4 - (Cpos3 == pos.wmove) && + pos.SH[31] != 4 - (Cpos3 == pos.wmove)) + { + PrP = 216; + } + } + else + { + if (pos.SH[(Csm == Osm) ? 4 : 0] != 4 - (Cpos3 == pos.wmove) && + pos.SH[(Csm == Osm) ? 8 : 5] != 4 - (Cpos3 == pos.wmove) && + pos.SH[(Csm == Osm) ? 26 : 23] != 4 - (Cpos3 == pos.wmove) && + pos.SH[(Csm == Osm) ? 31 : 27] != 4 - (Cpos3 == pos.wmove)) + { + PrP = -216; + } + } + } + else if (PosNi == 5) + { + char DNomSh = (Cpos3 == 1) ? ((Osm == 1) ? (char)16 : (char)6) + : ((Osm == 1) ? (char)20 : (char)2); + if (Csm == 1) DNomSh = char(31 - DNomSh); + if (pos.SH[DNomSh] == 4 - (Cpos3 == pos.wmove)) + { + PrP = (Cpos3 == 1) ? short(160) : short(-160); + } + } + else if (PosNi == 6) + { + if (Cpos3 == 1) + { + if (pos.SH[ 1] == 4 - (Cpos3 == pos.wmove) || + pos.SH[12] == 4 - (Cpos3 == pos.wmove) || + pos.SH[19] == 4 - (Cpos3 == pos.wmove) || + pos.SH[30] == 4 - (Cpos3 == pos.wmove)) + { + PrP = 168; + } + } + else + { + if (pos.SH[(Csm == 1) ? 15 : 6] == 4 - (Cpos3 == pos.wmove) || + pos.SH[(Csm == 1) ? 25 : 16] == 4 - (Cpos3 == pos.wmove)) + { + PrP = -168; + } + } + } + else PrP = short(((Cpos3 == 1) ? 1 : -1) * ((PosNi == 0) ? 200 : 208)); + } + } + } + } + if (PrP == 0) + { + unsigned char HwoBD = 0; + char NShSBD = 0; + for (int i = 0; i < 8; i++) + { + char ShBD = pos.SH[PoleToNum(i, 7 - i)]; + if (ShBD == 3 + pos.wmove) {HwoBD |= 2; NShSBD++;} + else if (ShBD == 4 - pos.wmove) {HwoBD |= 1; NShSBD++;} + } + if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 2) + { + if (NShSBD >= 1) val -= NShSBD - 1; + if (pos.SH[ 3] == 3 + pos.wmove) val--; + if (pos.SH[28] == 3 + pos.wmove) val--; + char Drg1 = 0, DrgPS = 0; + bool Drg1p = 0; + for (int i = 0; i < 7; i++) + { + char Sh7D = pos.SH[PoleToNum(i, i + 1)]; + if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 1;} + else if (Sh7D == 4 - pos.wmove) Drg1p = 1; + Sh7D = pos.SH[PoleToNum(i + 1, i)]; + if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 2;} + else if (Sh7D == 4 - pos.wmove) Drg1p = 1; + } + if (pos.SH[0] == 3 + pos.wmove || pos.SH[4] == 3 + pos.wmove || + pos.SH[27] == 3 + pos.wmove || pos.SH[31] == 3 + pos.wmove) + {if (Drg1p) val += 4; else val -= 1;} + if ((pos.SH[14] == 3 + pos.wmove) == (pos.SH[17] == 3 + pos.wmove)) + {if (Drg1 == 1) val += 2;} + else + { + if (Drg1 >= 2) + { + if (Drg1 > 2) val -= 1; + if (DrgPS == 3) val += 4; + if (Drg1p) val += 4; else val += 16; + if (!Drg1p && DrgPS) + { + Drg1 = 0; Drg1p = 0; DrgPS = 0; + for (int i = 0; i < 6; i++) + { + char Sh7D = pos.SH[PoleToNum(i, 5 - i)]; + if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 1;} + else if (Sh7D == 4 - pos.wmove) Drg1p = 1; + Sh7D = pos.SH[PoleToNum(i + 2, 7 - i)]; + if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 2;} + else if (Sh7D == 4 - pos.wmove) Drg1p = 1; + } + if (pos.SH[2] == 3 + pos.wmove || pos.SH[11] == 3 + pos.wmove || + pos.SH[20] == 3 + pos.wmove || pos.SH[29] == 3 + pos.wmove) + val += 4; + if ((pos.SH[14] == 3 + pos.wmove) + ? (pos.SH[13] == 3 + pos.wmove || pos.SH[22] == 3 + pos.wmove) + : (pos.SH[ 9] == 3 + pos.wmove || pos.SH[18] == 3 + pos.wmove)) + { + if (Drg1 >= 2) + { + if (DrgPS == 3) val += 4; + if (Drg1p) val += 4; else val += 16; + } + else if (Drg1 == 1) val += 1; + } + else if (Drg1 == 1) val += 2; + } + } + } + } + else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 1) + { + if (NShSBD >= 1) val += NShSBD - 1; + if (pos.SH[ 3] == 4 - pos.wmove) val++; + if (pos.SH[28] == 4 - pos.wmove) val++; + char Drg1 = 0, DrgPS = 0; + bool Drg1p = 0; + for (int i = 0; i < 7; i++) + { + char Sh7D = pos.SH[PoleToNum(i, i + 1)]; + if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 1;} + else if (Sh7D == 3 + pos.wmove) Drg1p = 1; + Sh7D = pos.SH[PoleToNum(i + 1, i)]; + if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 2;} + else if (Sh7D == 3 + pos.wmove) Drg1p = 1; + } + if (pos.SH[0] == 4 - pos.wmove || pos.SH[4] == 4 - pos.wmove || + pos.SH[27] == 4 - pos.wmove || pos.SH[31] == 4 - pos.wmove) + {if (Drg1p) val -= 4; else val += 1;} + if ((pos.SH[14] == 4 - pos.wmove) == (pos.SH[17] == 4 - pos.wmove)) + {if (Drg1 == 1) val -= 2;} + else + { + if (Drg1 >= 2) + { + if (Drg1 > 2) val += 1; + if (DrgPS == 3) val -= 4; + if (Drg1p) val -= 4; else val -= 16; + if (!Drg1p && DrgPS) + { + Drg1 = 0; Drg1p = 0; DrgPS = 0; + for (int i = 0; i < 6; i++) + { + char Sh7D = pos.SH[PoleToNum(i, 5 - i)]; + if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 1;} + else if (Sh7D == 3 + pos.wmove) Drg1p = 1; + Sh7D = pos.SH[PoleToNum(i + 2, 7 - i)]; + if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 2;} + else if (Sh7D == 3 + pos.wmove) Drg1p = 1; + } + if (pos.SH[2] == 4 - pos.wmove || pos.SH[11] == 4 - pos.wmove || + pos.SH[20] == 4 - pos.wmove || pos.SH[29] == 4 - pos.wmove) + { + val -= 4; + } + if ((pos.SH[14] == 4 - pos.wmove) + ? (pos.SH[13] == 4 - pos.wmove || pos.SH[22] == 4 - pos.wmove) + : (pos.SH[ 9] == 4 - pos.wmove || pos.SH[18] == 4 - pos.wmove)) + { + if (Drg1 >= 2) + { + if (DrgPS == 3) val -= 4; + if (Drg1p) val -= 4; else val -= 16; + } + else if (Drg1 == 1) val -= 1; + } + else if (Drg1 == 1) val -= 2; + } + } + } + } + else if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 1) + { + char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}}; + char Add = 0; + for (int i = 0; i < 4; i++) + { + Add |= char((pos.SH[Best4P[i][0]] == 3 + pos.wmove) * 3 + + (pos.SH[Best4P[i][1]] == 3 + pos.wmove)); + } + if (Add >= 4) val += 3; + else if (Add == 3) val += 2; + else if (Add >= 1) val += 1; + } + else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 2) + { + char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}}; + char Add = 0; + for (int i = 0; i < 4; i++) + { + Add |= char((pos.SH[Best4P[i][0]] == 4 - pos.wmove) * 3 + + (pos.SH[Best4P[i][1]] == 4 - pos.wmove)); + } + if (Add >= 4) val -= 3; + else if (Add == 3) val -= 2; + else if (Add >= 1) val -= 1; + } + } + else val += PrP; + } + } + return val; +} + +template +tvalue TBaseCompPlayer::GetFullValue(const Position &pos, int num) +{ + if (!pos.AllCanMove() && !pos.AllCanEat()) return GetLossValue(pos); + else return GetValue(pos, num); +} + +template +tvalue TBaseCompPlayer::FindBMove(Z &z, int num, + PMvv *pmv, int zn, tvalue a, tvalue b) +{ + assert(b > a); + assert(num >= 0); + if (num >= 3 && draw) draw(data); + int nlast = z.narr; + if (zn < 0) {z.AddPos(); z.array[zn = z.narr++] = *pmv;} + if (pmv) pmv->mv[0] = 0; + int n0 = z.narr; + int was_eat = z.FindAllMoves(z.array[zn], num <= 0); + int n1 = z.narr; + tvalue val; + if (n1 == n0) + { + assert(!z.array[zn].pos.AllCanEat()); + assert(num == 0 || !z.array[zn].pos.AllCanMove()); + if (num > 0 || !z.array[zn].pos.AllCanMove()) val = GetLossValue(z.array[zn].pos); + else val = GetValue(z.array[zn].pos, 0); + } + else if (pmv && n1 == n0 + 1 && nlast < n0) + { + *pmv = z.array[n0]; + if (!z.array[n0].pos.AllCanMove() && !z.array[n0].pos.AllCanMove()) + { + val = -1 - GetLossValue(z.array[n0].pos); + } + else + { + val = -GetValue(z.array[n0].pos, 0); + n1 = -1; + } + } + else + { + int k, opt; + if (num >= 2) + { + if (pmv && n1 > n0 + 1) + { + for (k = 0; k < 2*(n1 - n0); k++) + { + int i0 = n0 + random(n1 - n0), i1 = n0 + random(n1 - n0 - 1); + if (i1 >= i0) i1++; + PMvv t_pmv = z.array[i0]; + z.array[i0] = z.array[i1]; + z.array[i1] = t_pmv; + } + } + for (k = n0; k < n1; k++) z.array[k].val = GetFullValue(z.array[k].pos); + z.Sort(n0, n1); + } + tvalue cc = 2 * win_val; + tvalue dval = was_eat ? 0 : GetValue(z.array[zn].pos, num); + tvalue aa = -b, bb = -a; + if (aa < -win_val) aa--; + else if (aa > win_val) aa++; + else aa += dval; + if (bb < -win_val) bb--; + else if (bb > win_val) bb++; + else bb += dval; + for (k = n0; k < n1 && bb > aa; k++) + { + tvalue vk; + vk = FindBMove(z, num-1+was_eat, 0, k, aa, bb); + if (vk < cc) + { + opt = k; cc = vk; + if (bb > cc) bb = cc; + } + } + if (cc < -win_val) cc++; + else if (cc > win_val) cc--; + else cc -= dval; + val = -cc; + assert(opt >= n0 && opt < n1); + if (pmv) *pmv = z.array[opt]; + } + z.array[zn].val = val; + z.narr = nlast; + if (pmv) + { + if (n1 >= 0) printf("Checkers: value = %ld\n", val); + else printf("Checkers: value = ?\n"); + } + return val; +} + +template +int TBaseCompPlayer::Move(PMv &pmv) +{ + Z z; + PMvv zpmv; + (PMv&)zpmv = pmv; + if (draw) draw(data, 1); + FindBMove(z, 6, &zpmv); + if (draw) draw(data, -1); + if (zpmv.mv[0] == 0) return 0; + pmv = zpmv; + return 1; +} + +typedef TBaseCompPlayer TComputerPlayer; + +#endif //_HEADER_PLAYER_H diff --git a/programs/games/checkers/trunk/position.h b/programs/games/checkers/trunk/position.h new file mode 100644 index 0000000000..30599a773f --- /dev/null +++ b/programs/games/checkers/trunk/position.h @@ -0,0 +1,882 @@ +#ifndef _HEADER_POSITION_H +#define _HEADER_POSITION_H + +#ifndef __MENUET__ +#include +#include +#include +#include +#endif + +#define NELEM(a) (sizeof(a) / sizeof((a)[0])) + +const int NW_CELL = 8; + +const int NUM_CELL = NW_CELL * NW_CELL / 2; +const int LEN_WPOS = (NUM_CELL + 2) / 3; + +inline int PoleCpos(int i, int j) +{ + return (i + j) % 2 != 0; +} + +inline int PoleToNum(int i, int j) +{ + return j * (NW_CELL / 2) + i/2; +} + +inline void NumToPole(int k, int &i, int &j) +{ + j = k / (NW_CELL / 2); + i = k % (NW_CELL / 2); + i *= 2; + if (j % 2 == 0) i++; +} + +class Position +{ +public: + char SH[NUM_CELL]; + char wmove; + + Position() {Init();} + Position(const Position &p); + Position& operator=(const Position &p); + + void Init(); + int IsNull() const; + void Add(int np, char sh) {SH[np] = sh;} + void Del(int np) {SH[np] = 0;} + void Move(int np0, int np1) {if (np0 != np1) {SH[np1] = SH[np0]; SH[np0] = 0;}} + static int BecameD(int np, char ch); + + enum {AWrong = -1, AWColor = -2, AfCell = -3, AnfCell = -4, + AMustEatMore = -5, AMustEat = -6, ANoMove = -7, AChBack = -8, + ANotDm = -9, AOnlyDiag = -10, AEatYour = -11, AMoreOne = -12, + ANotDmE = -13, AMustEatMoreD = -14, ATurnBack = -15}; + + int ScanSide(int x, int y, int sx, int sy, int sh_k = -1) const; + int CanEat(int k, int psx = 0, int psy = 0, int sh_k = -1) const; + int CanMove(int k) const; + int AChCell(int k); + int AMove(const unsigned char MV[], int k = -1, int &mkmove = *(int*)0); + int AllCanEat(int w = -1) const; + int AllCanMove(int w = -1) const; + + char *Write(char WP[], int how = 0) const; + Position &Read(const char WP[], int how = 0); + static char *WriteMv(const unsigned char mv[], char WP[], int how = 0); + int WriteMvEx(const unsigned char mv[], char WP[], int how = 0) const; + static unsigned char *ReadMv(unsigned char mv[], const char WP[], int how = 0); + static int GetLenMv(const unsigned char mv[], int how = 0); + int GetLenMvEx(const unsigned char mv[], int how = 0) const; + static int GetLenMwr(const char WP[], int how = 0); + static void SetNullMv(unsigned char mv[]) {mv[0] = 0;} + void Reverse(); +}; + +Position::Position(const Position &p) : wmove(p.wmove) +{ + for(int i = 0; i < NUM_CELL; i++) SH[i] = p.SH[i]; +} + +Position& Position::operator=(const Position &p) +{ + wmove = p.wmove; + for(int i = 0; i < NUM_CELL; i++) SH[i] = p.SH[i]; + return *this; +} + +void Position::Init() +{ + wmove = 0; + for (int i = 0; i < NUM_CELL; i++) SH[i] = 0; +} + +int Position::IsNull() const +{ + for (int i = 0; i < NUM_CELL; i++) if (SH[i] != 0) return 0; + return 1; +} + +inline int Position::BecameD(int np, char ch) +{ + int x, y; + NumToPole(np, x, y); + return ch == 1 && y == NW_CELL - 1 || ch == 2 && y == 0; +} + +char *Position::Write(char WP[], int how) const +{ + if (how == 0) + { + int i = 0, j; + for (j = 0; i < NUM_CELL; j++) + { + WP[j] = SH[i++]; + if (i < NUM_CELL) {WP[j] *= (char)5; WP[j] += SH[i++];} + if (i < NUM_CELL) {WP[j] *= (char)5; WP[j] += SH[i++];} + if (i >= NUM_CELL) {WP[j] *= (char)2; WP[j] += wmove;} + WP[j]++; + } + } + else if (how == 1) + { + int i; + for (i = NUM_CELL - 1; i >= 0; i--) + { + if (SH[i] < 0 || SH[i] >= 5) return 0; + } + for (i = 0; i < NUM_CELL; i++) + { + const char SYMBOL[5] = {'0', 'R', 'B', 'X', 'Z'}; + WP[i] = SYMBOL[SH[NUM_CELL - 1 - i]]; + } + WP[NUM_CELL] = ':'; + WP[NUM_CELL + 1] = (wmove == 0) ? 'r' : 'b'; + WP[NUM_CELL + 2] = 0; + } + return WP; +} + +Position &Position::Read(const char WP[], int how) +{ + if (how == 0) + { + int i = 0, j, ii; + for (j = 0; i < NUM_CELL; j++) + { + unsigned int cwp = WP[j] - 1; + if (i >= NUM_CELL - 3) + { + wmove = char(cwp % 2); + cwp /= 2; + ii = NUM_CELL - 1; + } + else ii = i + 2; + while(ii >= i) {SH[ii--] = char(cwp % 5); cwp /= 5;} + i += 3; + } + } + else if (how == 1) + { + int i; + wmove = 0; + for (i = 0; i < NUM_CELL; i++) + { + switch(WP[i]) + { + case '0': + case '-': case '.': + case 'F': case 'f': + SH[NUM_CELL - 1 - i] = 0; + break; + case '1': + case 'A': case 'a': + case 'R': case 'r': + SH[NUM_CELL - 1 - i] = 1; + break; + case '2': + case 'B': case 'b': + case 'S': case 's': + SH[NUM_CELL - 1 - i] = 2; + break; + case '3': + case 'W': case 'w': + case 'X': case 'x': + SH[NUM_CELL - 1 - i] = 3; + break; + case '4': + case 'Y': case 'y': + case 'Z': case 'z': + SH[NUM_CELL - 1 - i] = 4; + break; + default: + Init(); + return *this; + } + } + if (WP[NUM_CELL] == ':') + { + char c = WP[NUM_CELL + 1]; + if (c == 'B' || c == 'b' || c == 'S' || c == 's' || + c == 'Y' || c == 'y' || c == 'Z' || c == 'z') + { + wmove = 1; + } + } + } + return *this; +} + +char *Position::WriteMv(const unsigned char mv[], char WP[], int how) +{ + int i, nmv = 0; + if (mv) nmv = mv[0]; + if (how == 0) + { + WP[0] = char(nmv + 1); + for (i = 1; i <= nmv; i++) WP[i] = char(mv[i] + 1); + } + else if (how == 1) + { + int j = 0; + for (i = 1; i <= nmv; i++) + { + int x, y; + NumToPole(mv[i], x, y); + WP[j++] = char('a' + NW_CELL - 1 - x); + int r = sprintf(WP + j, "%d", 1 + y); + if (r > 0) j += r; + if (i != nmv) WP[j++] = '-'; + } + WP[j] = 0; + } + return WP; +} + +unsigned char *Position::ReadMv(unsigned char mv[], const char WP[], int how) +{ + int i; + if (how == 0) + { + mv[0] = char(WP[0] - 1); + for (i = 1; i <= mv[0]; i++) mv[i] = char(WP[i] - 1); + } + else if (how == 1) + { + int j = 0, x = -1, y = -1; + mv[0] = 0; + for (;;) + { + if (isdigit(WP[j])) + { + y = atoi(WP + j) - 1; + while (isdigit(WP[j])) j++; + } + else if (islower(WP[j])) x = NW_CELL - 1 - (WP[j++] - 'a'); + else + { + if (x >= 0 && y >= 0 && x < NW_CELL && y < NW_CELL) + { + mv[++mv[0]] = (char)PoleToNum(x, y); + } + else if (y >= 0 && y < NUM_CELL) mv[++mv[0]] = (char)(NUM_CELL - 1 - y); + x = -1; y = -1; + if (WP[j] == '-' || WP[j] == '*' || WP[j] == ':') j++; + else break; + } + if (x >= 0 && y >= 0 && x < NW_CELL && y < NW_CELL) + { + mv[++mv[0]] = (char)PoleToNum(x, y); + x = -1; y = -1; + } + } + } + return mv; +} + +int Position::GetLenMv(const unsigned char mv[], int how) +{ + if (how == 0) return mv ? (1 + mv[0]) : 1; + else if (how == 1) + { + int i, j = 0; + if (!mv) return 1; + for (i = 1; i <= mv[0]; i++) + { + int x, y; + NumToPole(mv[i], x, y); + j++; y++; + while(y > 0) {j++; y /= 10;} + if (i != mv[0]) j++; + } + return ++j; + } + else return 0; +} + +int Position::GetLenMwr(const char WP[], int how) +{ + if (how == 0) return (unsigned char)WP[0]; + else if (how == 1) + { + int j; + for (j = 0; WP[j] == '-' || WP[j] == '*' || + WP[j] == ':' || isdigit(j) || islower(j); j++); + return j + 1; + } + else return 0; +} + +inline int Position::GetLenMvEx(const unsigned char mv[], int how) const +{ + return WriteMvEx(mv, 0, how); +} + +int Position::WriteMvEx(const unsigned char mv[], char WP[], int how) const +{ + if (how == 11) + { + Position pos = *this; + int p, L = 0, was_d = 0; + for (p = 1; p <= mv[0]; p++) + { + if (!was_d && pos.SH[mv[p]] > 2) + { + if (WP) WP[L] = '*'; + L++; + was_d = 1; + } + int x0, y0, x1, y1; + NumToPole(mv[p], x0, y0); + if (WP) + { + WP[L++] = char('a' + NW_CELL - 1 - x0); + int r = sprintf(WP + L, "%d", 1 + y0); + if (r > 0) L += r; + } + else + { + L++; + int g = y0 + 1; + while(g > 0) {L++; g /= 10;} + } + if (p >= mv[0]) break; + NumToPole(mv[p+1], x1, y1); + int mi = abs(x1 - x0), i, eat = -1; + if (mi > 0 && mi == abs(y1 - y0)) + { + int sx = (x1 > x0) ? 1 : -1; + int sy = (y1 > y0) ? 1 : -1; + for (i = 1; i < mi; i++) + { + int r = PoleToNum(x0 + i * sx, y0 + i * sy); + if (pos.SH[r] != 0) + { + eat = r; + pos.Del(r); + } + } + } + if (WP) WP[L] = (eat >= 0) ? ':' : '-'; + L++; + if (pos.SH[mv[p]] == 1 && y1 == NW_CELL - 1) pos.SH[mv[p]] = 3; + else if (pos.SH[mv[p]] == 2 && y1 == 0) pos.SH[mv[p]] = 4; + pos.Move(mv[p], mv[p+1]); + } + if (WP) WP[L] = 0; + L++; + return L; + } + else + { + if (WP) WriteMv(mv, WP, how); + return GetLenMv(mv, how); + } +} + +int Position::ScanSide(int x, int y, int sx, int sy, int sh_k) const +{ + if (sh_k < 0) sh_k = SH[PoleToNum(x, y)]; + if (sh_k < 1 || sh_k > 4) return -2; + if (sh_k >= 2) sh_k -= 2; + int i, i0, i1, f = 0, g = 0; + if (sx < 0) i0 = x; + else i0 = NW_CELL - x - 1; + if (sy < 0) i1 = y; + else i1 = NW_CELL - y - 1; + if (i0 > i1) i0 = i1; + for (i = 1; i <= i0; i++) + { + char nk = SH[PoleToNum(x + i*sx, y + i*sy)]; + if (nk) + { + if (f || (nk != 3 - sh_k && nk != 5 - sh_k)) return g; + else f = 1; + } + else if (f) return (i == 2) ? 4 : (2 + g); + else if (i == 1) g = 1; + } + return g; +} + +int Position::CanEat(int k, int psx, int psy, int sh_k) const +{ + int x, y, sx, sy; + if (sh_k < 0) sh_k = SH[k]; + if (sh_k < 1 || sh_k > 6) return 0; + NumToPole(k, x, y); + if (sh_k > 4) + { + int i, i0, i1, f = 0; + if (-psx < 0) i0 = x; + else i0 = NW_CELL - x - 1; + if (-psy < 0) i1 = y; + else i1 = NW_CELL - y - 1; + if (i0 > i1) i0 = i1; + for (i = 1; i <= i0; i++) + { + int nk = SH[PoleToNum(x - i*psx, y - i*psy)]; + if (nk) + { + if (f || (nk != 7 - sh_k && nk != 9 - sh_k)) break; + else f = 1; + } + else + { + if (f) return 1; + if (ScanSide(x - i*psx, y - i*psy, psy, -psx, sh_k-2) >= 2) return 1; + if (ScanSide(x - i*psx, y - i*psy, -psy, psx, sh_k-2) >= 2) return 1; + } + } + } + else for (sx = -1; sx <= 1; sx += 2) if (x + 2*sx >= 0 && x + 2*sx < NW_CELL) + { + for (sy = -1; sy <= 1; sy += 2) + { + if ((sx != psx || sy != psy) && y + 2*sy >= 0 && y + 2*sy < NW_CELL) + { + if (sh_k <= 2) + { + if (SH[PoleToNum(x + 2*sx, y + 2*sy)] == 0) + { + int nk = SH[PoleToNum(x + sx, y + sy)]; + if (nk == 3 - sh_k || nk == 5 - sh_k) return 1; + } + } + else if (ScanSide(x, y, sx, sy, sh_k) >= 2) return 1; + } + } + } + return 0; +} + +int Position::CanMove(int k) const +{ + int x, y, xx, yy, y1, y2; + NumToPole(k, x, y); + if (SH[k] == 1) y1 = y2 = y + 1; + else if (SH[k] == 2) y1 = y2 = y - 1; + else if (SH[k] != 3 && SH[k] != 4) return 0; + else {y1 = y - 1; y2 = y + 1;} + for (yy = y1; yy <= y2; yy += 2) if (yy >= 0 && yy < NW_CELL) + { + for (xx = x - 1; xx <= x + 1; xx += 2) if (xx >= 0 && xx < NW_CELL) + { + if (SH[PoleToNum(xx, yy)] == 0) return 1; + } + } + return 0; +} + +int Position::AChCell(int k) +{ + if (k < 0 || k >= NUM_CELL) return AWrong; + if (SH[k] == 0) return AfCell; + if (SH[k] != 1 + wmove && SH[k] != 3 + wmove) return AWColor; + if (CanEat(k)) return 1; + if (AllCanEat()) return AMustEat; + if (CanMove(k)) return 1; + return ANoMove; +} + +int Position::AMove(const unsigned char MV[], int k, int &mkmove) +{ + if (k >= NUM_CELL) return AWrong; + if (MV[0] <= 0) + { + if (k < 0) return NUM_CELL; + int s = AChCell(k); + if (s < 0) return s; + else return NUM_CELL; + } + if (MV[0] == 1 && k < 0) + { + int s = AChCell(MV[1]); + if (s < 0) return s; + else return NUM_CELL; + } + if (SH[MV[1]] == 0) return AfCell; + if (SH[MV[1]] != 1 + wmove && SH[MV[1]] != 3 + wmove) return AWColor; + int i, mi, p, MV_L, MV_N = MV[0], eat = -1, r; + int psx = 0, psy = 0; + if (k >= 0) MV_N++; + Position pos = *this; + for (p = 1; p < MV_N; p++) + { + int x0, y0, x1, y1, i_eat; + if (p < MV[0]) MV_L = MV[p+1]; + else if (k < 0) break; + else MV_L = k; + if (pos.SH[MV_L] != 0) return AnfCell; + NumToPole(MV[p], x0, y0); + NumToPole(MV_L, x1, y1); + mi = abs(x1 - x0); + if (mi <= 0 || mi != abs(y1 - y0)) return AOnlyDiag; + int sx = (x1 > x0) ? 1 : -1; + int sy = (y1 > y0) ? 1 : -1; + if (sx == psx && sy == psy) return ATurnBack; + psx = -sx; psy = -sy; + eat = -1; i_eat = -1; + for (i = 1; i < mi; i++) + { + r = PoleToNum(x0 + i * sx, y0 + i * sy); + if (pos.SH[r] != 0) + { + if (eat >= 0) return AMoreOne; + if (pos.SH[r] != 2 - wmove && pos.SH[r] != 4 - wmove) return AEatYour; + eat = r; i_eat = i; + pos.Del(r); + } + } + if (eat >= 0) + { + if (pos.SH[MV[p]] <= 2 && mi != 2) return ANotDmE; + } + else + { + if (MV_N > 2) return AMustEatMore; + if (pos.SH[MV[p]] <= 2) + { + if (mi != 1) return ANotDm; + if (wmove == 0 && y1 < y0 || wmove == 1 && y1 > y0) return AChBack; + } + if (AllCanEat()) return AMustEat; + } + if (i_eat >= 0 && pos.SH[MV[p]] > 2) + { + if (!pos.CanEat(MV_L, psx, psy, pos.SH[MV[p]])) + { + if (pos.CanEat(PoleToNum(x0 + i_eat*sx, y0 + i_eat*sy), + psx, psy, pos.SH[MV[p]] + 2)) + { + return AMustEatMoreD; + } + } + } + if (wmove == 0 && y1 == NW_CELL - 1) pos.SH[MV[p]] = 3; + else if (wmove == 1 && y1 == 0) pos.SH[MV[p]] = 4; + pos.Move(MV[p], MV_L); + } + if (&mkmove) + { + int end = MV_N > 1 && (eat < 0 || !pos.CanEat(MV_L, psx, psy)); + if (mkmove == 1 && end) + { + *this = pos; + wmove = !wmove; + } + if (end) mkmove = 0; + else + { + if (MV_N > 1 && eat >= 0) mkmove = AMustEatMore; + else mkmove = AWrong; + } + } + if (k < 0 || eat < 0) eat = NUM_CELL; + return eat; +} + +int Position::AllCanEat(int w) const +{ + int k; + if (w < 0) w = wmove; + for (k = 0; k < NUM_CELL; k++) + { + if ((SH[k] == w+1 || SH[k] == w+3) && CanEat(k)) return 1; + } + return 0; +} + +int Position::AllCanMove(int w) const +{ + int k; + if (w < 0) w = wmove; + for (k = 0; k < NUM_CELL; k++) + { + if ((SH[k] == w+1 || SH[k] == w+3) && CanMove(k)) return 1; + } + return 0; +} + +void Position::Reverse() +{ + int i; + for (i = 0; i <= (NUM_CELL-1) / 2; i++) + { + int sh1 = SH[i], sh2 = SH[NUM_CELL - 1 - i]; + if (sh1 == 1) sh1 = 2; + else if (sh1 == 2) sh1 = 1; + else if (sh1 == 3) sh1 = 4; + else if (sh1 == 4) sh1 = 3; + if (sh2 == 1) sh2 = 2; + else if (sh2 == 2) sh2 = 1; + else if (sh2 == 3) sh2 = 4; + else if (sh2 == 4) sh2 = 3; + SH[i] = (char)sh2; SH[NUM_CELL - 1 - i] = (char)sh1; + } + wmove = !wmove; +} + + +class PlayWrite +{ +public: + PlayWrite() : play(0), mplay(0), nplay(0), start(0), mstart(0), nstart(0) {} + PlayWrite(const PlayWrite &pl) : play(0), mplay(0), nplay(0), + start(0), mstart(0), nstart(0) {(*this) = pl;} + ~PlayWrite() {Clear();} + + void Clear(); + PlayWrite &operator=(const PlayWrite &pl); + int GetN() const {return nstart - 1;} + int GetLen() const {return nplay - sizeof(int);} + + struct PMv + { + Position pos; + unsigned char mv[NUM_CELL]; + }; + + void Add(const unsigned char move[], const Position &pos); + void Add(const PMv &pmv) {Add(pmv.mv, pmv.pos);} + int Add(const unsigned char move[]); + int GetMove(unsigned char move[], int k) const; + int GetPos(Position &pos, int k) const; + int GetPMv(PMv &pmv, int k) const; + int GetMoveL(unsigned char move[], int k = 0) const + {return GetMove(move, nstart - 2 - k);} + int GetPosL(Position &pos, int k = 0) const {return GetPos(pos, nstart - 2 - k);} + int GetPMvL(PMv &pmv, int k = 0) const {return GetPMv(pmv, nstart - 2 - k);} + int ClearFrom(int k = 0); + int IsDraw(int nmove = -1); +protected: + void IncPlay(int k); + void IncStart(int k); + void IncStart() {IncStart(nstart + 1);} + void AddStart() {IncStart(); start[nstart++] = nplay;} + void Split(); + void SplitClear(); +protected: + char *play; + int *start; + int mplay, nplay, mstart, nstart; +}; + +void PlayWrite::Clear() +{ + if (play) + { + if ((*(int*)play) > 0) (*(int*)play)--; + else delete[] play; + } + play = 0; mplay = 0; nplay = 0; + if (start) + { + if (start[0] > 0) start[0]--; + else delete[] start; + } + start = 0; mstart = 0; nstart = 0; +} + +void PlayWrite::Split() +{ + if (play && (*(int*)play) > 0) + { + (*(int*)play)--; + char *play0 = play; + mplay = nplay; + play = new char[mplay]; + memcpy(play, play0, nplay * sizeof(play[0])); + (*(int*)play) = 0; + } + if (start && start[0] > 0) + { + start[0]--; + int *start0 = start; + mstart = nstart; + start = new int[mstart]; + memcpy(start, start0, nstart * sizeof(start[0])); + start[0] = 0; + } +} + +void PlayWrite::SplitClear() +{ + if (play && (*(int*)play) > 0) + { + (*(int*)play)--; + play = 0; + nplay = 0; mplay = 0; + } + if (start && start[0] > 0) + { + start[0]--; + start = 0; + nstart = 0; mstart = 0; + } +} + +PlayWrite &PlayWrite::operator=(const PlayWrite &pl) +{ + if (&pl != this) + { + play = pl.play; + (*(int*)play)++; + nplay = pl.nplay; mplay = pl.mplay; + start = pl.start; + start[0]++; + nstart = pl.nstart; mstart = pl.mstart; + } + return *this; +} + +void PlayWrite::IncPlay(int k) +{ + if (mplay < k) + { + int m0 = mplay; + char *play0 = play; + mplay = 2*k + 10; + play = new char[mplay]; + memcpy(play, play0, m0 * sizeof(play[0])); + (*(int*)play) = 0; + if (play0) + { + if ((*(int*)play0) > 0) (*(int*)play0)--; + else delete[] play0; + } + } +} + +void PlayWrite::IncStart(int k) +{ + if (mstart < k) + { + int m0 = mstart; + int *start0 = start; + mstart = 2*k + 10; + start = new int[mstart]; + memcpy(start, start0, m0 * sizeof(start[0])); + start[0] = 0; + if (start0) + { + if (start0[0] > 0) start0[0]--; + else delete[] start0; + } + } +} + +void PlayWrite::Add(const unsigned char move[], const Position &pos) +{ + Split(); + int k = Position::GetLenMv(move); + if (nstart < 1) nstart = 1; + if (nplay < sizeof(int)) nplay = sizeof(int); + AddStart(); + IncPlay(nplay + k + LEN_WPOS); + Position::WriteMv(move, play + nplay, 0); + nplay += k; + pos.Write(play + nplay, 0); + nplay += LEN_WPOS; +} + +int PlayWrite::Add(const unsigned char move[]) +{ + if (nstart <= 1) return 1; + Position pos; + GetPosL(pos); + int mkmove = 1; + int res = pos.AMove(move, -1, mkmove); + if (res < 0) return res; + else if (mkmove != 0) return mkmove; + Add(move, pos); + return 0; +} + +int PlayWrite::GetMove(unsigned char move[], int k) const +{ + if (!play || !start) return -1; + k++; + if (k <= 0 || k >= nstart) return -1; + Position::ReadMv(move, play + start[k], 0); + return Position::GetLenMv(move); +} + +int PlayWrite::GetPos(Position &pos, int k) const +{ + if (!play || !start) return -1; + k++; + if (k <= 0 || k >= nstart) return -1; + int mlen = Position::GetLenMwr(play + start[k], 0); + pos.Read(play + start[k] + mlen, 0); + return LEN_WPOS; +} + +int PlayWrite::GetPMv(PMv &pmv, int k) const +{ + if (!play || !start) return -1; + k++; + if (k <= 0 || k >= nstart) return -1; + Position::ReadMv(pmv.mv, play + start[k], 0); + int mlen = Position::GetLenMv(pmv.mv); + pmv.pos.Read(play + start[k] + mlen, 0); + return mlen + LEN_WPOS; +} + +int PlayWrite::ClearFrom(int k) +{ + if (!play || !start) return 0; + k++; + if (k >= nstart) return 0; + if (k <= 1) {Clear(); return 2;} + nplay = start[k]; + nstart = k; + return 1; +} + +int PlayWrite::IsDraw(int nmove) +{ + nmove++; + if (nmove <= 0 || nmove > nstart) nmove = nstart; + if (!start || nmove <= 3) return 0; + int i, j, k, draw = 0; + for (i = 1; i < nmove; i++) + { + k = 1; + char *p1 = play + start[i] + Position::GetLenMwr(play + start[i], 0); + for (j = 1; j < i; j++) + { + char *p2 = play + start[j] + Position::GetLenMwr(play + start[j], 0); + if (memcmp(p1, p2, LEN_WPOS) == 0) k++; + } + if (k >= 3) {draw = 1; break;} + } + return draw; +} + + +class TChPlayer +{ +public: + TChPlayer() {} + + typedef struct PlayWrite::PMv PMv; + + virtual int PlayerID() {return 0;} + virtual int Move(PMv &pmv) = 0; + + int Move(Position &pos, char mv[]); +}; + +int TChPlayer::Move(Position &pos, char mv[]) +{ + PMv pmv; + pmv.pos = pos; memcpy(pmv.mv, mv, sizeof(pmv.mv)); + int res = Move(pmv); + pos = pmv.pos; memcpy(mv, pmv.mv, sizeof(pmv.mv)); + return res; +} + +#endif //_HEADER_POSITION_H diff --git a/programs/games/checkers/trunk/qsort.c b/programs/games/checkers/trunk/qsort.c new file mode 100644 index 0000000000..6edc89a627 --- /dev/null +++ b/programs/games/checkers/trunk/qsort.c @@ -0,0 +1,331 @@ +static void shortsort(char *lo, char *hi, unsigned width, + int (*comp)(const void *, const void *)); + +static void swap(char *p, char *q, unsigned width); + +/* this parameter defines the cutoff between using quick sort and + insertion sort for arrays; arrays with lengths shorter or equal to the + below value use insertion sort */ + +#define CUTOFF 8 /* testing shows that this is good value */ + +#define STKSIZ (8*sizeof(void*) - 2) + +/*** +*qsort(base, num, wid, comp) - quicksort function for sorting arrays +* +*Purpose: +* quicksort the array of elements +* side effects: sorts in place +* maximum array size is number of elements times size of elements, +* but is limited by the virtual address space of the processor +* +*Entry: +* char *base = pointer to base of array +* unsigned num = number of elements in the array +* unsigned width = width in bytes of each array element +* int (*comp)() = pointer to function returning analog of strcmp for +* strings, but supplied by user for comparing the array elements. +* it accepts 2 pointers to elements. +* Returns neg if 1<2, 0 if 1=2, pos if 1>2. +* +*Exit: +* returns void +* +*******************************************************************************/ + +void qsort ( + void *base, + unsigned num, + unsigned width, + int (*comp)(const void *, const void *) + ) +{ + /* Note: the number of stack entries required is no more than + 1 + log2(num), so 30 is sufficient for any array */ + char *lo, *hi; /* ends of sub-array currently sorting */ + char *mid; /* points to middle of subarray */ + char *loguy, *higuy; /* traveling pointers for partition step */ + unsigned size; /* size of the sub-array */ + char *lostk[STKSIZ], *histk[STKSIZ]; + int stkptr; /* stack for saving sub-array to be processed */ + + if (num < 2) + return; /* nothing to do */ + + stkptr = 0; /* initialize stack */ + + lo = (char *)base; + hi = (char *)base + width * (num-1); /* initialize limits */ + + /* this entry point is for pseudo-recursion calling: setting + lo and hi and jumping to here is like recursion, but stkptr is + preserved, locals aren't, so we preserve stuff on the stack */ +recurse: + + size = (hi - lo) / width + 1; /* number of el's to sort */ + + /* below a certain size, it is faster to use a O(n^2) sorting method */ + if (size <= CUTOFF) { + shortsort(lo, hi, width, comp); + } + else { + /* First we pick a partitioning element. The efficiency of the + algorithm demands that we find one that is approximately the median + of the values, but also that we select one fast. We choose the + median of the first, middle, and last elements, to avoid bad + performance in the face of already sorted data, or data that is made + up of multiple sorted runs appended together. Testing shows that a + median-of-three algorithm provides better performance than simply + picking the middle element for the latter case. */ + + mid = lo + (size / 2) * width; /* find middle element */ + + /* Sort the first, middle, last elements into order */ + if (comp(lo, mid) > 0) { + swap(lo, mid, width); + } + if (comp(lo, hi) > 0) { + swap(lo, hi, width); + } + if (comp(mid, hi) > 0) { + swap(mid, hi, width); + } + + /* We now wish to partition the array into three pieces, one consisting + of elements <= partition element, one of elements equal to the + partition element, and one of elements > than it. This is done + below; comments indicate conditions established at every step. */ + + loguy = lo; + higuy = hi; + + /* Note that higuy decreases and loguy increases on every iteration, + so loop must terminate. */ + for (;;) { + /* lo <= loguy < hi, lo < higuy <= hi, + A[i] <= A[mid] for lo <= i <= loguy, + A[i] > A[mid] for higuy <= i < hi, + A[hi] >= A[mid] */ + + /* The doubled loop is to avoid calling comp(mid,mid), since some + existing comparison funcs don't work when passed the same + value for both pointers. */ + + if (mid > loguy) { + do { + loguy += width; + } while (loguy < mid && comp(loguy, mid) <= 0); + } + if (mid <= loguy) { + do { + loguy += width; + } while (loguy <= hi && comp(loguy, mid) <= 0); + } + + /* lo < loguy <= hi+1, A[i] <= A[mid] for lo <= i < loguy, + either loguy > hi or A[loguy] > A[mid] */ + + do { + higuy -= width; + } while (higuy > mid && comp(higuy, mid) > 0); + + /* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi, + either higuy == lo or A[higuy] <= A[mid] */ + + if (higuy < loguy) + break; + + /* if loguy > hi or higuy == lo, then we would have exited, so + A[loguy] > A[mid], A[higuy] <= A[mid], + loguy <= hi, higuy > lo */ + + swap(loguy, higuy, width); + + /* If the partition element was moved, follow it. Only need + to check for mid == higuy, since before the swap, + A[loguy] > A[mid] implies loguy != mid. */ + + if (mid == higuy) + mid = loguy; + + /* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition at top + of loop is re-established */ + } + + /* A[i] <= A[mid] for lo <= i < loguy, + A[i] > A[mid] for higuy < i < hi, + A[hi] >= A[mid] + higuy < loguy + implying: + higuy == loguy-1 + or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid] */ + + /* Find adjacent elements equal to the partition element. The + doubled loop is to avoid calling comp(mid,mid), since some + existing comparison funcs don't work when passed the same value + for both pointers. */ + + higuy += width; + if (mid < higuy) { + do { + higuy -= width; + } while (higuy > mid && comp(higuy, mid) == 0); + } + if (mid >= higuy) { + do { + higuy -= width; + } while (higuy > lo && comp(higuy, mid) == 0); + } + + /* OK, now we have the following: + higuy < loguy + lo <= higuy <= hi + A[i] <= A[mid] for lo <= i <= higuy + A[i] == A[mid] for higuy < i < loguy + A[i] > A[mid] for loguy <= i < hi + A[hi] >= A[mid] */ + + /* We've finished the partition, now we want to sort the subarrays + [lo, higuy] and [loguy, hi]. + We do the smaller one first to minimize stack usage. + We only sort arrays of length 2 or more.*/ + + if ( higuy - lo >= hi - loguy ) { + if (lo < higuy) { + lostk[stkptr] = lo; + histk[stkptr] = higuy; + ++stkptr; + } /* save big recursion for later */ + + if (loguy < hi) { + lo = loguy; + goto recurse; /* do small recursion */ + } + } + else { + if (loguy < hi) { + lostk[stkptr] = loguy; + histk[stkptr] = hi; + ++stkptr; /* save big recursion for later */ + } + + if (lo < higuy) { + hi = higuy; + goto recurse; /* do small recursion */ + } + } + } + + /* We have sorted the array, except for any pending sorts on the stack. + Check if there are any, and do them. */ + + --stkptr; + if (stkptr >= 0) { + lo = lostk[stkptr]; + hi = histk[stkptr]; + goto recurse; /* pop subarray from stack */ + } + else + return; /* all subarrays done */ +} + + +/*** +*shortsort(hi, lo, width, comp) - insertion sort for sorting short arrays +*shortsort_s(hi, lo, width, comp, context) - insertion sort for sorting short arrays +* +*Purpose: +* sorts the sub-array of elements between lo and hi (inclusive) +* side effects: sorts in place +* assumes that lo < hi +* +*Entry: +* char *lo = pointer to low element to sort +* char *hi = pointer to high element to sort +* unsigned width = width in bytes of each array element +* int (*comp)() = pointer to function returning analog of strcmp for +* strings, but supplied by user for comparing the array elements. +* it accepts 2 pointers to elements, together with a pointer to a context +* (if present). Returns neg if 1<2, 0 if 1=2, pos if 1>2. +* void *context - pointer to the context in which the function is +* called. This context is passed to the comparison function. +* +*Exit: +* returns void +* +*Exceptions: +* +*******************************************************************************/ + +static void shortsort ( + char *lo, + char *hi, + unsigned width, + int (*comp)(const void *, const void *) + ) +{ + char *p, *max; + + /* Note: in assertions below, i and j are alway inside original bound of + array to sort. */ + + while (hi > lo) { + /* A[i] <= A[j] for i <= j, j > hi */ + max = lo; + for (p = lo+width; p <= hi; p += width) { + /* A[i] <= A[max] for lo <= i < p */ + if (comp(p, max) > 0) { + max = p; + } + /* A[i] <= A[max] for lo <= i <= p */ + } + + /* A[i] <= A[max] for lo <= i <= hi */ + + swap(max, hi, width); + + /* A[i] <= A[hi] for i <= hi, so A[i] <= A[j] for i <= j, j >= hi */ + + hi -= width; + + /* A[i] <= A[j] for i <= j, j > hi, loop top condition established */ + } + /* A[i] <= A[j] for i <= j, j > lo, which implies A[i] <= A[j] for i < j, + so array is sorted */ +} + +/*** +*swap(a, b, width) - swap two elements +* +*Purpose: +* swaps the two array elements of size width +* +*Entry: +* char *a, *b = pointer to two elements to swap +* unsigned width = width in bytes of each array element +* +*Exit: +* returns void +* +*Exceptions: +* +*******************************************************************************/ + +static void swap ( + char *a, + char *b, + unsigned width + ) +{ + char tmp; + + if ( a != b ) + /* Do the swap one character at a time to avoid potential alignment + problems. */ + while ( width-- ) { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } +} diff --git a/programs/games/checkers/trunk/sysproc.h b/programs/games/checkers/trunk/sysproc.h new file mode 100644 index 0000000000..caba2c2d71 --- /dev/null +++ b/programs/games/checkers/trunk/sysproc.h @@ -0,0 +1,27 @@ +#ifndef _HEADER_SYSTEM_PROCESS_H +#define _HEADER_SYSTEM_PROCESS_H + +#ifndef __MENUET__ +#include +#include +#endif + +#if defined __GNUC__ +# include +# define DIR_SEPARATOR ('/') + inline long GetProcessId() {return (long)getpid();} + inline long DuplicateProcess() {return (long)fork();} + inline int random(int m) {return ((unsigned long)rand()) % m;} + inline void randomize() {srand(time(0));} +#elif defined __TURBOC__ && !defined __MENUET__ +# include +# define DIR_SEPARATOR ('\\') + inline long GetProcessId() {return (long)getpid();} + inline long DuplicateProcess() {return -1;} +#else +# define DIR_SEPARATOR ('\\') + inline long GetProcessId() {return 0;} + inline long DuplicateProcess() {return -1;} +#endif + +#endif //_HEADER_SYSTEM_PROCESS_H diff --git a/programs/games/checkers/trunk/t2fasm.exe b/programs/games/checkers/trunk/t2fasm.exe new file mode 100644 index 0000000000000000000000000000000000000000..cad968b59c30c9d87435fff16b56329525f91022 GIT binary patch literal 5120 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 bnlMlBH5?oqp3I2>_W;0R%X_=O|7-r=B|{F| literal 0 HcmV?d00001 diff --git a/programs/games/checkers/trunk/tmplayer.h b/programs/games/checkers/trunk/tmplayer.h new file mode 100644 index 0000000000..f797a53baf --- /dev/null +++ b/programs/games/checkers/trunk/tmplayer.h @@ -0,0 +1,729 @@ +#ifndef _HEADER_TMP_PLAYER_H +#define _HEADER_TMP_PLAYER_H + +#include "player.h" + +class CompPosition : public Position +{ +public: + bool Move; + + CompPosition() : Position() {Move = 1;} + CompPosition(CompPosition &p, bool IsChange = 0) : Position(p) + {Move = p.Move + IsChange;} + CompPosition& operator=(CompPosition &p) + {for(int i = 0; i < 32; i++) SH[i] = p.SH[i]; Move = p.Move; return *this;} + CompPosition& Init(Position &p, bool MoveColor = 1) + {for(int i = 0; i < 32; i++) SH[i] = p.SH[i]; Move = MoveColor; return *this;} +}; + +namespace ComputerMove +{ +#define BCM_START -256 +#define BCM_ISM1 -257 + + class BestMove; + bool MoveEat(BestMove* BM); + bool MovePr(BestMove* BM); + + class BestMove + { + public: + BestMove (CompPosition &Pos1, BestMove *par = 0) + {Pos = Pos1; Parent = par; NMax = 0;} + + void StartMove() + { + if (Parent->NomP == BCM_ISM1) return; + if (Parent->NomP == BCM_START) NomP = 258; else NomP = Parent->NomP; + if (!MoveEat(this)) + { + bool IsNP256 = 0, IsNP258 = 0; + if (NomP == 258) IsNP258 = 1; + if (NomP == 256) + { + IsNP256 = 1; int NSH1 = 0; int NSH0 = 0; + for (int i = 0; i < 32; i++) + { + if (Pos.SH[i] == 1 + Pos.Move) NSH1 += 1; + else if (Pos.SH[i] == 2 - Pos.Move) NSH0 += 1; + else if (Pos.SH[i] == 3 + Pos.Move) NSH1 += 6; + else if (Pos.SH[i] == 4 - Pos.Move) NSH0 += 6; + } + int NSH = NSH0 * NSH1; + if (NSH > 100) NomP = 0; else if (NSH > 30) NomP = 1; + else if (NSH > 5) NomP = 2; else NomP = 3; + } + else if (NomP == 0) NomP = BCM_ISM1; else NomP--; + if (!MovePr(this)) + { + NextPreim = -16777472; + for (int i = 0; i < 32; i++) + { + if (Pos.SH[i] == 1 + Pos.Move) NextPreim -= 512; + else if (Pos.SH[i] == 2 - Pos.Move) NextPreim -= 32; + else if (Pos.SH[i] == 3 + Pos.Move) NextPreim -= 4096; + else if (Pos.SH[i] == 4 - Pos.Move) NextPreim -= 32; + } + } + else if (NomP == BCM_ISM1) + { + char NomDM0 = 0, NomDM1 = 0; + NextPreim = 0; + for (int i = 0; i < 32; i++) + { + short PreimSHPos[32] = {243, 243, 243, 245, + 240, 240, 240, 240, + 244, 244, 244, 244, + 245, 248, 248, 245, + 249, 250, 250, 248, + 256, 260, 260, 256, + 280, 280, 280, 260, + 280, 280, 280, 280}; + if (Pos.SH[i] == 1 + Pos.Move) + NextPreim += PreimSHPos[Pos.Move ? (31 - i) : i]; + else if (Pos.SH[i] == 2 - Pos.Move) + NextPreim -= PreimSHPos[Pos.Move ? i : (31 - i)]; + else if (Pos.SH[i] == 3 + Pos.Move) NomDM1++; + else if (Pos.SH[i] == 4 - Pos.Move) NomDM0++; + } + if (NomDM1 > 0) + { + NextPreim += 560; NomDM1--; + if (NomDM1 > 0) + { + NextPreim += 432; NomDM1--; + NextPreim += long(NomDM1) * 384; + } + } + if (NomDM0 > 0) + { + NextPreim -= 560; NomDM0--; + if (NomDM0 > 0) + { + NextPreim -= 432; NomDM0--; + NextPreim -= long(NomDM0) * 384; + } + } + } + else if (IsNP256 && NextPreim < 16777216 && NextPreim > -16777216) + { + char NSH1 = 0, NSH0 = 0, NDM1 = 0, NDM0 = 0; + for (int i = 0; i < 32; i++) + { + if (Pos.SH[i] == 1 + Pos.Move) NSH1++; + else if (Pos.SH[i] == 2 - Pos.Move) NSH0++; + else if (Pos.SH[i] == 3 + Pos.Move) NDM1++; + else if (Pos.SH[i] == 4 - Pos.Move) NDM0++; + } + if (NDM1 > 0 && NDM0 > 0 && NSH1 + NSH0 < 3) + { + unsigned char HwoBD = 0; char Sh0BD = 1, Sh1BD = 1; + for (int i = 0; i < 8; i++) + { + char ShBD = Pos.SH[PoleToNum(i, 7 - i)]; + if (ShBD == 1 + Pos.Move) Sh1BD++; + else if (ShBD == 2 - Pos.Move) Sh0BD++; + else if (ShBD == 3 + Pos.Move) HwoBD |= 2; + else if (ShBD == 4 - Pos.Move) HwoBD |= 1; + } + if (HwoBD == 2) NextPreim += 128 / Sh0BD; + if (HwoBD == 1) NextPreim -= 128 / Sh1BD; + if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 1) + { + char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}}; + char Add = 0; + for (int i = 0; i < 4; i++) Add |= + (char(Pos.SH[Best4P[i][0]] == 3 + Pos.Move) * 3 + + char(Pos.SH[Best4P[i][1]] == 3 + Pos.Move)); + if (Add >= 4) NextPreim += 32; else if (Add == 3) NextPreim += 24; + else if (Add >= 1) NextPreim += 16; + } + else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 2) + { + char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}}; + char Add = 0; + for (int i = 0; i < 4; i++) Add |= + (char(Pos.SH[Best4P[i][0]] == 4 - Pos.Move) * 3 + + char(Pos.SH[Best4P[i][1]] == 4 - Pos.Move)); + if (Add >= 4) NextPreim -= 32; else if (Add == 3) NextPreim -= 24; + else if (Add >= 1) NextPreim -= 16; + } + } + else + { + for (int i = 0; i < 32; i++) + { + char Color = Pos.SH[i] - 1; + if (Color == 0 || Color == 1) + { + char qi = Color ? (31 - i) : i; + char Zn = Color ? -1 : 1; + char PreZ = (Color == Pos.Move) ? 1 : -1; + if (Pos.SH[i + Zn * 8] != 2 - Color) + { + if (qi / 4 == 2) + { + char IsFree = 0; + if (Pos.SH[i - Zn * 4] == 2 - Color) IsFree += 2; + else if (qi != 8) + { + if (Pos.SH[i - Zn ] == 2 - Color || + Pos.SH[i - Zn * 9] == 2 - Color) IsFree += 2; + else if (Color != Pos.Move) + if (Pos.SH[i - Zn * 5] == 2 - Color) IsFree++; + } + if (qi == 11) IsFree += 2; + else if (Pos.SH[i + Zn ] == 2 - Color || + Pos.SH[i - Zn * 3] == 2 - Color || + Pos.SH[i - Zn * 7] == 2 - Color) IsFree += 2; + else if (Color != Pos.Move && qi != 10) + if (Pos.SH[i - Zn * 2] == 2 - Color) IsFree++; + if (IsFree < 3) NextPreim += PreZ * 176 / (1 + NDM0 + NDM1); + else if (qi == 9 || qi == 10) NextPreim += + PreZ * 128 / (1 + NDM0 + NDM1); + } + else if (qi / 4 == 3) + { + char IsFree = 0; + if (Pos.SH[i - Zn * 12] == 2 - Color) + {if (Color == Pos.Move) IsFree += 11; else IsFree += 12;} + else if (Pos.SH[i - Zn * 4] == 2 - Color) IsFree += 11; + else if (qi == 15) IsFree += 5; + else if (Pos.SH[i - Zn * 7] == 2 - Color) IsFree += 9; + else if (Pos.SH[i + Zn] == 2 - Color) IsFree += 8; + else if (Pos.SH[i - Zn * 11] == 2 - Color) + {if (Color == Pos.Move) IsFree += 5; else IsFree += 7;} + else if (Pos.SH[i - Zn * 3] == 2 - Color) IsFree += 5; + else if (qi != 14) + { + if (Pos.SH[i - Zn * 6] == 2 - Color) IsFree += 3; + else if (Color != Pos.Move) + if (Pos.SH[i - Zn * 10] == 2 - Color) IsFree++; + } + if (qi == 12) IsFree += 7; + else if (Pos.SH[i - Zn * 13] == 2 - Color) + {if (Color == Pos.Move) IsFree += 11; else IsFree += 12;} + else if (Pos.SH[i - Zn * 5] == 2 - Color) IsFree += 11; + else if (Pos.SH[i - Zn * 9] == 2 - Color) IsFree += 9; + else if (Pos.SH[i - Zn] == 2 - Color) IsFree += 8; + else if (qi != 13) + { + if (Pos.SH[i - Zn * 14] == 2 - Color) + {if (Color == Pos.Move) IsFree += 5; else IsFree += 7;} + else if (Pos.SH[i - Zn * 6] == 2 - Color) IsFree += 5; + else if (Pos.SH[i - Zn * 10] == 2 - Color) IsFree += 3; + else if (Color != Pos.Move && qi != 14) + if (Pos.SH[i - Zn * 15] == 2 - Color) IsFree++; + } + if (IsFree < ((Color == Pos.Move) ? 14 : 12)) + NextPreim += PreZ * 160 / (1 + NDM0 + NDM1); + } + } + } + } + } + } + else if (IsNP258 && NextPreim < 16777216 && NextPreim > -16777216) + { + char NSH1 = 0, NSH0 = 0, NDM1 = 0, NDM0 = 0; + for (int i = 0; i < 32; i++) + { + if (Pos.SH[i] == 1 + Pos.Move) NSH1++; + else if (Pos.SH[i] == 2 - Pos.Move) NSH0++; + else if (Pos.SH[i] == 3 + Pos.Move) NDM1++; + else if (Pos.SH[i] == 4 - Pos.Move) NDM0++; + } + if (NDM1 > 0 && NDM0 > 0 && NSH1 == 0 && NSH0 == 0) + { + short PrP = 0; char Cpos3 = -1; + if (NDM1 == 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0) Cpos3 = 1; + else if (NDM1 == 1 && NDM0 == 3 && NSH1 == 0 && NSH0 == 0) Cpos3 = 0; + if (Cpos3 >= 0) + { + for (char Osm = 0; Osm <= 1; Osm++) for (char Csm = 0; Csm <= 1; Csm++) + { + char PosSH[7][3] = {{13, 17, 18}, {6, 17, 18}, {9, 21, 22}, + {17, 18, 19}, {9, 10, 15}, {11, 14, 18}, {2, 14, 18}}; + for (char PosNi = 0; PosNi < 7; PosNi++) + { + bool IsPosR = 1; + for (char ShNi = 0; ShNi < 3; ShNi++) + { + char DNomSh = (Csm == 1) ? (31 - PosSH[PosNi][ShNi]) + : PosSH[PosNi][ShNi]; + if (Osm == 1) {int x, y; NumToPole(DNomSh, x, y); + DNomSh = PoleToNum(y, x);} + if (Pos.SH[DNomSh] != 3 + (Cpos3 == Pos.Move)) IsPosR = 0; + } + if (IsPosR) + { + if (PosNi == 3) + { + if (Cpos3 == 1) {if (Pos.SH[(Csm == 1) ? 29 : 2] != + 4 - (Cpos3 == Pos.Move) && Pos.SH[(Csm == 1) ? 11 : 20] + != 4 - (Cpos3 == Pos.Move)) PrP = 216;} + else + { + bool PrPZ = 1; + for (int i = 0; i < 6; i++) + if (Pos.SH[PoleToNum((Csm == 1) ? (i + 2) : i, + (Csm == 1) ? (7 - i) : (5 - i))] == + 4 - (Cpos3 == Pos.Move)) PrPZ = 0; + if (PrPZ) PrP = -216; + } + } + else if (PosNi == 4) + { + if (Cpos3 == 1) + {if (Pos.SH[ 0] != 4 - (Cpos3 == Pos.Move) + && Pos.SH[ 4] != 4 - (Cpos3 == Pos.Move) + && Pos.SH[27] != 4 - (Cpos3 == Pos.Move) + && Pos.SH[31] != 4 - (Cpos3 == Pos.Move)) PrP = 216;} + else {if (Pos.SH[(Csm == Osm) ? 4 : 0] != 4 - (Cpos3 == Pos.Move) + && Pos.SH[(Csm == Osm) ? 8 : 5] != 4 - (Cpos3 == Pos.Move) + && Pos.SH[(Csm == Osm) ? 26 : 23] != 4 - (Cpos3 == Pos.Move) + && Pos.SH[(Csm == Osm) ? 31 : 27] != 4 - (Cpos3 == Pos.Move)) + PrP = -216;} + } + else if (PosNi == 5) + { + char DNomSh = (Cpos3 == 1) ? ((Osm == 1) ? 16 : 6) + : ((Osm == 1) ? 20 : 2); + if (Csm == 1) DNomSh = 31 - DNomSh; + if (Pos.SH[DNomSh] == 4 - (Cpos3 == Pos.Move)) + PrP = (Cpos3 == 1) ? 160 : -160; + } + else if (PosNi == 6) + { + if (Cpos3 == 1) + {if (Pos.SH[ 1] == 4 - (Cpos3 == Pos.Move) + || Pos.SH[12] == 4 - (Cpos3 == Pos.Move) + || Pos.SH[19] == 4 - (Cpos3 == Pos.Move) + || Pos.SH[30] == 4 - (Cpos3 == Pos.Move)) PrP = 168;} + else + {if (Pos.SH[(Csm == 1) ? 15 : 6] == 4 - (Cpos3 == Pos.Move) + || Pos.SH[(Csm == 1) ? 25 : 16] == 4 - (Cpos3 == Pos.Move)) + PrP = -168;} + } + else PrP = ((Cpos3 == 1) ? 1 : -1) * ((PosNi == 0) ? 200 : 208); + } + } + } + } + if (PrP == 0) + { + unsigned char HwoBD = 0; char NShSBD = 0; + for (int i = 0; i < 8; i++) + { + char ShBD = Pos.SH[PoleToNum(i, 7 - i)]; + if (ShBD == 3 + Pos.Move) {HwoBD |= 2; NShSBD++;} + else if (ShBD == 4 - Pos.Move) {HwoBD |= 1; NShSBD++;} + } + if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 2) + { + if (NShSBD >= 1) NextPreim -= NShSBD - 1; + if (Pos.SH[ 3] == 3 + Pos.Move) NextPreim--; + if (Pos.SH[28] == 3 + Pos.Move) NextPreim--; + char Drg1 = 0; bool Drg1p = 0; char DrgPS = 0; + for (int i = 0; i < 7; i++) + { + char Sh7D = Pos.SH[PoleToNum(i, i + 1)]; + if (Sh7D == 3 + Pos.Move) {Drg1++; DrgPS |= 1;} + else if (Sh7D == 4 - Pos.Move) Drg1p = 1; + Sh7D = Pos.SH[PoleToNum(i + 1, i)]; + if (Sh7D == 3 + Pos.Move) {Drg1++; DrgPS |= 2;} + else if (Sh7D == 4 - Pos.Move) Drg1p = 1; + } + if (Pos.SH[0] == 3 + Pos.Move || Pos.SH[4] == 3 + Pos.Move || + Pos.SH[27] == 3 + Pos.Move || Pos.SH[31] == 3 + Pos.Move) + {if (Drg1p) NextPreim += 4; else NextPreim -= 1;} + if ((Pos.SH[14] == 3 + Pos.Move) == (Pos.SH[17] == 3 + Pos.Move)) + {if (Drg1 == 1) NextPreim += 2;} + else + { + if (Drg1 >= 2) + { + if (Drg1 > 2) NextPreim -= 1; + if (DrgPS == 3) NextPreim += 4; + if (Drg1p) NextPreim += 4; else NextPreim += 16; + if (!Drg1p && DrgPS) + { + Drg1 = 0; Drg1p = 0; DrgPS = 0; + for (int i = 0; i < 6; i++) + { + char Sh7D = Pos.SH[PoleToNum(i, 5 - i)]; + if (Sh7D == 3 + Pos.Move) {Drg1++; DrgPS |= 1;} + else if (Sh7D == 4 - Pos.Move) Drg1p = 1; + Sh7D = Pos.SH[PoleToNum(i + 2, 7 - i)]; + if (Sh7D == 3 + Pos.Move) {Drg1++; DrgPS |= 2;} + else if (Sh7D == 4 - Pos.Move) Drg1p = 1; + } + if (Pos.SH[2] == 3 + Pos.Move || Pos.SH[11] == 3 + Pos.Move || + Pos.SH[20] == 3 + Pos.Move || Pos.SH[29] == 3 + Pos.Move) + NextPreim += 4; + if ((Pos.SH[14] == 3 + Pos.Move) + ? (Pos.SH[13] == 3 + Pos.Move || Pos.SH[22] == 3 + Pos.Move) + : (Pos.SH[ 9] == 3 + Pos.Move || Pos.SH[18] == 3 + Pos.Move)) + { + if (Drg1 >= 2) + { + if (DrgPS == 3) NextPreim += 4; + if (Drg1p) NextPreim += 4; else NextPreim += 16; + } + else if (Drg1 == 1) NextPreim += 1; + } + else if (Drg1 == 1) NextPreim += 2; + } + } + } + } + else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 1) + { + if (NShSBD >= 1) NextPreim += NShSBD - 1; + if (Pos.SH[ 3] == 4 - Pos.Move) NextPreim++; + if (Pos.SH[28] == 4 - Pos.Move) NextPreim++; + char Drg1 = 0; bool Drg1p = 0; char DrgPS = 0; + for (int i = 0; i < 7; i++) + { + char Sh7D = Pos.SH[PoleToNum(i, i + 1)]; + if (Sh7D == 4 - Pos.Move) {Drg1++; DrgPS |= 1;} + else if (Sh7D == 3 + Pos.Move) Drg1p = 1; + Sh7D = Pos.SH[PoleToNum(i + 1, i)]; + if (Sh7D == 4 - Pos.Move) {Drg1++; DrgPS |= 2;} + else if (Sh7D == 3 + Pos.Move) Drg1p = 1; + } + if (Pos.SH[0] == 4 - Pos.Move || Pos.SH[4] == 4 - Pos.Move || + Pos.SH[27] == 4 - Pos.Move || Pos.SH[31] == 4 - Pos.Move) + {if (Drg1p) NextPreim -= 4; else NextPreim += 1;} + if ((Pos.SH[14] == 4 - Pos.Move) == (Pos.SH[17] == 4 - Pos.Move)) + {if (Drg1 == 1) NextPreim -= 2;} + else + { + if (Drg1 >= 2) + { + if (Drg1 > 2) NextPreim += 1; + if (DrgPS == 3) NextPreim -= 4; + if (Drg1p) NextPreim -= 4; else NextPreim -= 16; + if (!Drg1p && DrgPS) + { + Drg1 = 0; Drg1p = 0; DrgPS = 0; + for (int i = 0; i < 6; i++) + { + char Sh7D = Pos.SH[PoleToNum(i, 5 - i)]; + if (Sh7D == 4 - Pos.Move) {Drg1++; DrgPS |= 1;} + else if (Sh7D == 3 + Pos.Move) Drg1p = 1; + Sh7D = Pos.SH[PoleToNum(i + 2, 7 - i)]; + if (Sh7D == 4 - Pos.Move) {Drg1++; DrgPS |= 2;} + else if (Sh7D == 3 + Pos.Move) Drg1p = 1; + } + if (Pos.SH[2] == 4 - Pos.Move || Pos.SH[11] == 4 - Pos.Move || + Pos.SH[20] == 4 - Pos.Move || Pos.SH[29] == 4 - Pos.Move) + NextPreim -= 4; + if ((Pos.SH[14] == 4 - Pos.Move) + ? (Pos.SH[13] == 4 - Pos.Move || Pos.SH[22] == 4 - Pos.Move) + : (Pos.SH[ 9] == 4 - Pos.Move || Pos.SH[18] == 4 - Pos.Move)) + { + if (Drg1 >= 2) + { + if (DrgPS == 3) NextPreim -= 4; + if (Drg1p) NextPreim -= 4; else NextPreim -= 16; + } + else if (Drg1 == 1) NextPreim -= 1; + } + else if (Drg1 == 1) NextPreim -= 2; + } + } + } + } + else if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 1) + { + char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}}; + char Add = 0; + for (int i = 0; i < 4; i++) Add |= + (char(Pos.SH[Best4P[i][0]] == 3 + Pos.Move) * 3 + + char(Pos.SH[Best4P[i][1]] == 3 + Pos.Move)); + if (Add >= 4) NextPreim += 3; else if (Add == 3) NextPreim += 2; + else if (Add >= 1) NextPreim += 1; + } + else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 2) + { + char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}}; + char Add = 0; + for (int i = 0; i < 4; i++) Add |= + (char(Pos.SH[Best4P[i][0]] == 4 - Pos.Move) * 3 + + char(Pos.SH[Best4P[i][1]] == 4 - Pos.Move)); + if (Add >= 4) NextPreim -= 3; else if (Add == 3) NextPreim -= 2; + else if (Add >= 1) NextPreim -= 1; + } + } + else NextPreim += PrP; + } + } + } + Parent->TakeMove(Pos, -NextPreim); + } + + void TakeMove(CompPosition &Pos1, long Preim) + { + if (Preim >= 16777216) Preim--; else if (Preim <= -16777216) Preim++; + bool b = (NMax == 0 || Preim > NextPreim); if (NMax == 0) NMax = 1; + if (!b && Preim == NextPreim) {b = (random(NMax + 1) == 0); NMax++;} + if (b) {if (NomP == BCM_START) *NextPos = Pos1; NextPreim = Preim;} + } + + CompPosition Pos; int NomP; BestMove *Parent; + + CompPosition *NextPos; char NMax; long NextPreim; + }; + + class MoveEatParam + { + public: + char Home; + char Eaten[15]; char NomEat; + BestMove* BM; + + MoveEatParam(){} + + char RealPlase(char N) + { + char RP; + if (N == Home) RP = 0; else RP = BM->Pos.SH[N]; + for (int i = 0; i < NomEat; i++) if (N == Eaten[i]) RP = 0; + return RP; + } + }; + + void EatContinue(MoveEatParam& MEP, bool IsDMC, char Start, char Kurs) + { + bool IsCanEat = 0; + int x, y; NumToPole(Start, x, y); + if (y == 7 - MEP.BM->Pos.Move * 7) IsDMC = 1; + if (IsDMC) + { + int KursY = Kurs / abs(Kurs); int KursX = Kurs - KursY * 2; + for (int i = x, j = y; + i >= 0 && j >= 0 && i < 8 && j < 8; + i += KursX, j += KursY) + { + int Shash = MEP.RealPlase(PoleToNum(i, j)); + if (Shash == 2 - MEP.BM->Pos.Move || Shash == 4 - MEP.BM->Pos.Move) + { + if (i + KursX >= 0 && j + KursY >= 0 && i + KursX < 8 && j + KursY < 8) + if (MEP.RealPlase(PoleToNum(i + KursX, j + KursY)) == 0) + { + IsCanEat = 1; + MEP.Eaten[MEP.NomEat++] = PoleToNum(i, j); + EatContinue(MEP, 1, PoleToNum(i + KursX, j + KursY), + KursX + 2 * KursY); + MEP.NomEat--; + } + break; + } + else if (Shash == 1 + MEP.BM->Pos.Move || Shash == 3 + MEP.BM->Pos.Move) break; + else for (int Rotate = -1; Rotate <= 1; Rotate += 2) + for (int i1 = i + KursY * Rotate, j1 = j - KursX * Rotate; + i1 >= 0 && j1 >= 0 && i1 < 8 && j1 < 8; + i1 += KursY * Rotate, j1 -= KursX * Rotate) + { + int Shash = MEP.RealPlase(PoleToNum(i1, j1)); + if (Shash == 2 - MEP.BM->Pos.Move || Shash == 4 - MEP.BM->Pos.Move) + { + if (i1 + KursY * Rotate >= 0 && j1 - KursX * Rotate >= 0 && + i1 + KursY * Rotate < 8 && j1 - KursX * Rotate < 8) + if (MEP.RealPlase(PoleToNum(i1 + KursY * Rotate, j1 - KursX * Rotate)) == 0) + { + IsCanEat = 1; + MEP.Eaten[MEP.NomEat++] = PoleToNum(i1, j1); + EatContinue(MEP, 1, PoleToNum(i1 + KursY * Rotate, + j1 - KursX * Rotate), + KursY * Rotate - 2 * KursX * Rotate); + MEP.NomEat--; + } + break; + } + else if (Shash == 1 + MEP.BM->Pos.Move || Shash == 3 + MEP.BM->Pos.Move) break; + } + } + if (!IsCanEat) + { + for (int ii = x, jj = y; ii >= 0 && jj >= 0 && + ii < 8 && jj < 8; ii += KursX, jj += KursY) + { + if (MEP.RealPlase(PoleToNum(ii, jj)) != 0) break; + BestMove BMove(MEP.BM->Pos, MEP.BM); BMove.Pos.SH[MEP.Home] = 0; + for (int i = 0; i < MEP.NomEat; i++) {BMove.Pos.SH[MEP.Eaten[i]] = 0;} + BMove.Pos.SH[PoleToNum(ii, jj)] = 3 + MEP.BM->Pos.Move; + BMove.Pos.Move = !BMove.Pos.Move; + BMove.StartMove(); + } + } + } + else + { + for (int i = -1; i <= 1; i += 2) for (int j = -1; j <= 1; j += 2) + if (i + 2 * j != -Kurs) if (x + 2 * i >= 0 + && y + 2 * j >= 0 && x + 2*i < 8 && y + 2 * j < 8) + { + char FESH = PoleToNum(x + i, y + j); char FESHrp = MEP.RealPlase(FESH); + char FMSH = PoleToNum(x + 2 * i, y + 2 * j); + if ((FESHrp == 2 - MEP.BM->Pos.Move || FESHrp == 4 - MEP.BM->Pos.Move) + && MEP.RealPlase(FMSH) == 0) + { + IsCanEat = 1; + MEP.Eaten[MEP.NomEat++] = FESH; + EatContinue(MEP, 0, FMSH, i + 2 * j); + MEP.NomEat--; + } + } + if (!IsCanEat) + { + BestMove BMove(MEP.BM->Pos, MEP.BM); BMove.Pos.SH[MEP.Home] = 0; + for (int i = 0; i < MEP.NomEat; i++) {BMove.Pos.SH[MEP.Eaten[i]] = 0;} + BMove.Pos.SH[Start] = 1 + MEP.BM->Pos.Move; + BMove.Pos.Move = !BMove.Pos.Move; + BMove.StartMove(); + } + } + } + + bool MoveEat(BestMove* BM) + { + bool IsCanEat = 0; + MoveEatParam MEP; MEP.BM = BM; + for (MEP.Home = 0; MEP.Home < 32; MEP.Home++) + { + if (BM->Pos.SH[MEP.Home] == 1 + BM->Pos.Move) + { + int x, y; NumToPole(MEP.Home, x, y); + for (int i = -1; i <= 1; i += 2) for (int j = -1; j <= 1; j += 2) + if (x + 2*i >= 0 && y + 2*j >= 0 && x + 2*i < 8 && y + 2*j < 8) + { + int FESH = PoleToNum(x + i, y + j); + int FMSH = PoleToNum(x + 2 * i, y + 2 * j); + if ((BM->Pos.SH[FESH] == 2 - BM->Pos.Move || BM->Pos.SH[FESH] == 4 - BM->Pos.Move) + && BM->Pos.SH[FMSH] == 0) + { + IsCanEat = 1; + MEP.NomEat = 1; MEP.Eaten[0] = FESH; + EatContinue(MEP, 0, FMSH, i + 2 * j); + } + } + } + else if (BM->Pos.SH[MEP.Home] == 3 + BM->Pos.Move) + { + int x, y; NumToPole(MEP.Home, x, y); + for (int i = -1; i <= 1; i += 2) for (int j = -1; j <= 1; j += 2) + for (int a = x + i, b = y + j; + a >= 0 && b >= 0 && a < 8 && b < 8; + a += i, b += j) + { + char Shash = PoleToNum(a, b); + char Shash1 = PoleToNum(a + i, b + j); + if (BM->Pos.SH[Shash] == 2 - BM->Pos.Move || BM->Pos.SH[Shash] == 4 - BM->Pos.Move) + { + if (a + i >= 0 && b + j >= 0 && a + i < 8 && b + j < 8) + if (BM->Pos.SH[Shash1] == 0) + { + IsCanEat = 1; + MEP.NomEat = 1; MEP.Eaten[0] = Shash; + EatContinue(MEP, 1, Shash1, i + 2 * j); + } + break; + } + else if (BM->Pos.SH[Shash] == 1 + BM->Pos.Move || BM->Pos.SH[Shash] == 3 + BM->Pos.Move) break; + } + } + } + return IsCanEat; + } + + bool MovePr(BestMove* BM) + { + bool IsCanMove = 0; + for (int N = 0; N < 32; N++) + { + if (BM->Pos.SH[N] == 1 + BM->Pos.Move) + { + int x, y; NumToPole(N, x, y); + int j = 1 - 2 * BM->Pos.Move; + for (int i = -1; i <= 1; i += 2) + if (x + i >= 0 && y + j >= 0 && x + i < 8 && y + j < 8) + { + int FMSH = PoleToNum(x + i, y + j); + if (BM->Pos.SH[FMSH] == 0) + { + IsCanMove = 1; + BestMove BMove(BM->Pos, BM); BMove.Pos.SH[N] = 0; + BMove.Pos.SH[FMSH] = 1 + BM->Pos.Move + 2 * + (y + j == 7 - BM->Pos.Move * 7); + BMove.Pos.Move = !BMove.Pos.Move; + BMove.StartMove(); + } + } + } + else if (BM->Pos.SH[N] == 3 + BM->Pos.Move) + { + int x, y; NumToPole(N, x, y); + for (int i = -1; i <= 1; i += 2) for (int j = -1; j <= 1; j += 2) + for (int a = x + i, b = y + j; + a >= 0 && b >= 0 && a < 8 && b < 8; + a += i, b += j) + { + if (BM->Pos.SH[PoleToNum(a, b)] != 0) break; + IsCanMove = 1; + BestMove BMove(BM->Pos, BM); BMove.Pos.SH[N] = 0; + BMove.Pos.SH[PoleToNum(a, b)] = 3 + BM->Pos.Move; + BMove.Pos.Move = !BMove.Pos.Move; + BMove.StartMove(); + } + } + } + return IsCanMove; + } + + int StartMove(Position& Pos, bool CompColor) + { + CompPosition Pos1; Pos1.Init(Pos, CompColor); + BestMove MainMove(Pos1); MainMove.NomP = BCM_START; + MainMove.NextPos = &Pos1; + if (!MoveEat(&MainMove)) if (!MovePr(&MainMove)) return 1; + Pos = Pos1; MainMove.Pos = Pos1; + MainMove.NomP = BCM_ISM1; + if (!MoveEat(&MainMove)) if (!MovePr(&MainMove)) return -1; + return 0; + } + +#undef BCM_ISM1 +#undef BCM_START +} + + +class TemporaryPlayer : public TChPlayer +{ +public: + TemporaryPlayer() {} + + virtual int Move(PMv &pmv); +}; + +int TemporaryPlayer::Move(PMv &pmv) +{ + TComputerPlayer::Z z; + z.FindAllMoves(pmv); + if (z.narr <= 0) return 0; + int r, s = ComputerMove::StartMove(pmv.pos, pmv.pos.wmove); + if (s > 0) return 0; + for (r = 0; r < z.narr; r++) + { + if (memcmp(z.array[r].pos.SH, pmv.pos.SH, sizeof(pmv.pos.SH)) == 0) + { + pmv = z.array[r]; + return 1; + } + } + return 0; +} + +#endif //_HEADER_TMP_PLAYER_H diff --git a/programs/games/checkers/trunk/win-chk.rc b/programs/games/checkers/trunk/win-chk.rc new file mode 100644 index 0000000000..43b8b332ba --- /dev/null +++ b/programs/games/checkers/trunk/win-chk.rc @@ -0,0 +1,106 @@ +#define IDC_DEBUG 22003 +#define IDC_COPYRIGHT 22002 +#define IDC_VERSION 22001 +#include +#include "winabout.rh" + + +WinDrawIcon ICON +{ +'00 00 01 00 01 00 20 20 10 00 00 00 00 00 E8 02' +'00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00' +'00 00 01 00 04 00 00 00 00 00 80 02 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 80 00 00 80 00 00 00 80 80 00 80 00' +'00 00 80 00 80 00 80 80 00 00 C0 C0 C0 00 80 80' +'80 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00' +'00 00 FF 00 FF 00 FF FF 00 00 FF FF FF 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 11 11 11 11 11 11 00 00 00 00 00 00 00' +'00 19 11 11 11 11 11 11 11 10 11 00 00 00 00 00' +'19 11 19 11 11 11 11 11 01 11 01 01 00 00 00 19' +'11 91 91 11 11 11 11 11 11 01 10 10 11 00 01 91' +'91 11 19 11 11 11 11 11 11 11 01 11 00 00 01 91' +'19 91 91 11 11 11 11 11 11 01 10 10 11 00 99 19' +'91 19 11 99 99 99 99 99 99 10 11 00 00 00 99 11' +'91 99 99 99 99 99 99 99 99 99 99 11 10 00 99 19' +'99 99 99 11 11 11 11 11 11 99 99 99 91 00 91 99' +'99 11 11 11 11 11 11 11 11 11 11 99 99 00 99 99' +'11 91 11 99 99 99 99 99 99 11 19 11 99 90 19 91' +'99 19 99 91 11 11 11 11 19 99 91 99 19 91 19 91' +'91 99 99 19 19 99 99 91 91 99 99 19 19 91 19 91' +'91 99 99 19 19 99 99 91 91 99 99 19 19 91 19 91' +'99 19 99 91 11 11 11 11 19 99 91 99 19 91 01 99' +'11 91 11 99 99 99 99 99 99 11 19 11 99 10 00 19' +'99 11 11 11 11 11 11 11 11 11 11 99 91 00 00 01' +'11 99 99 11 11 11 11 11 11 99 99 11 10 00 00 00' +'00 11 11 99 99 99 99 99 99 11 11 00 00 00 00 00' +'00 00 00 11 11 11 11 11 11 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' +'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' +'FF FF FF FF FF FF FF C0 03 FF FC 00 00 3F F0 00' +'00 0F C0 00 00 03 80 00 00 01 80 00 00 01 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' +'00 00 80 00 00 01 C0 00 00 03 E0 00 00 07 FC 00' +'00 3F FF C0 03 FF FF FF FF FF FF FF FF FF FF FF' +'FF FF FF FF FF FF FF FF FF FF FF FF FF FF' +} + + +1 VERSIONINFO +FILEVERSION 1, 0, 1, 0 +PRODUCTVERSION 1, 0, 1, 0 +FILEFLAGSMASK 0 +FILEFLAGS VS_FFI_FILEFLAGSMASK +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileDescription", "Checkers for Windows\000" + VALUE "FileVersion", "1.01\000" + VALUE "InternalName", "Checkers\000" + VALUE "LegalCopyright", "Copyright © 2003. Rumyantsev Andrey.\000" + VALUE "OriginalFilename", "WinCheckers.exe\000" + VALUE "ProductName", "Checkers\000" + VALUE "ProductVersion", "1.01\000" + } + + } + + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x0409, 0x04e4 + } + +} + +IDD_ABOUT1 DIALOG 41, 33, 204, 65 +EXSTYLE WS_EX_DLGMODALFRAME +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About Checkers" +FONT 8, "MS Sans Serif" +{ + CONTROL "Version", IDC_VERSION, "STATIC", SS_CENTER | SS_NOPREFIX | WS_CHILD | WS_VISIBLE | WS_GROUP, 28, 14, 174, 8 + CONTROL "C H E C K E R S", -1, "STATIC", SS_CENTER | SS_NOPREFIX | WS_CHILD | WS_VISIBLE | WS_GROUP, 28, 4, 174, 8 + CONTROL "", IDC_COPYRIGHT, "STATIC", SS_CENTER | SS_NOPREFIX | WS_CHILD | WS_VISIBLE | WS_GROUP, 28, 27, 174, 17 + CONTROL "", IDC_DEBUG, "STATIC", SS_RIGHT | SS_NOPREFIX | WS_CHILD | WS_VISIBLE | WS_GROUP, 136, 55, 66, 8 + CONTROL "WinDrawIcon", -1, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 8, 8, 21, 20 + CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 76, 46, 40, 14 +} + + + diff --git a/programs/games/checkers/trunk/win-chk.res b/programs/games/checkers/trunk/win-chk.res new file mode 100644 index 0000000000000000000000000000000000000000..84c657dca179faa51800db176170ec8e2118252e GIT binary patch literal 1964 zcmchXJx^3o5Qg6ii-HC2O`y2Z;+klJ7GyyZqm3df(SShsED0haQ5Uj+NVig1ddvL@ zCd7YWvZaMT!onCkzgpwvQf+T9uSED2ft4!{?)P+AvbEPLe(VM;K|^t0mpjl!}_wsN0WenzNTe zrZ+5%KyjRRonf66=$kJhr@CXW@OXueHP?o;kY(CCRS zUZ%)znX25T0t=e2znjryd!nZI72I@6mvuoOus0di19IJkAwK3MyLF!~h#5W>+u7H( z!MA1dQXMn4o>#Bls$1U|()57t@n2vw=B8cF*;%h2z!&p!G2gjy$C{|`XIbYAHiLf- zzfeCMzEkO-&izW)$h=!WGrCUkh)6fTe)ZAs#^+zZ=qkHM-B!um_YVIS&VG{bX@Fb; LJStRk!c*xFC$3ba literal 0 HcmV?d00001 diff --git a/programs/games/checkers/trunk/win-draw.h b/programs/games/checkers/trunk/win-draw.h new file mode 100644 index 0000000000..af9cd06688 --- /dev/null +++ b/programs/games/checkers/trunk/win-draw.h @@ -0,0 +1,530 @@ +#ifndef _Windows +# error Can't include this file without windows +#endif + +#include "gr-draw.h" + +#ifndef _WIN_GRAPHIC_DRAW_H +#define _WIN_GRAPHIC_DRAW_H + +#include "winabout.h" +#include "keysym.h" +#include +#include +#include +#include +#include +#include +#include + +#define main OwlMain + +class TWinGraphDraw : public TGraphDraw +{ +public: + TWinGraphDraw(const char *s = 0); + ~TWinGraphDraw(); +public: + static const int CM_ABOUT; + static unsigned long GetKeySym(unsigned int key); +protected: + class TDrwWindow : public TWindow + { + public: + TDrwWindow(TWinGraphDraw *drw) : TWindow(), win_draw(drw) + { + Init((TWindow*)NULL, 0, 0); + } + + TColor GetBkgndColor() const {return BkgndColor;} + protected: + void SetupWindow(); + bool CanClose(); + void Paint(TDC &dc, bool erase, TRect &rect); + void EvSize(uint sizeType, TSize &size) {Invalidate();} + void EvLButtonDblClk(uint modKeys, TPoint& point) {EvLButtonDown(modKeys, point);} + void EvLButtonDown(uint modKeys, TPoint& point); + void EvLButtonUp(uint modKeys, TPoint& point); + void EvRButtonDblClk(uint modKeys, TPoint& point) {EvRButtonDown(modKeys, point);} + void EvRButtonDown(uint modKeys, TPoint& point); + void EvRButtonUp(uint modKeys, TPoint& point); + void EvMButtonDblClk(uint modKeys, TPoint& point) {EvMButtonDown(modKeys, point);} + void EvMButtonDown(uint modKeys, TPoint& point); + void EvMButtonUp(uint modKeys, TPoint& point); + void EvMouseMove(uint modKeys, TPoint& point); + void EvKeyDown(uint key, uint repeatCount, uint flags); + void EvKeyUp(uint key, uint repeatCount, uint flags); + public: + TWinGraphDraw *win_draw; + + DECLARE_RESPONSE_TABLE(TDrwWindow); + }; + + class TDrwFrameWindow : public TFrameWindow + { + public: + TDrwFrameWindow(TWindow *parent, TDrwWindow *client); + protected: + virtual void SetupWindow(); + void EvSysCommand(uint cmdType, TPoint& point); + public: + TWinGraphDraw *win_draw; + + DECLARE_RESPONSE_TABLE(TDrwFrameWindow); + }; + + class TDrwApplication : public TApplication + { + public: + TDrwApplication(TWinGraphDraw *drw, int w = 0, int h = 0) + : def_w(w), def_h(h), win_draw(drw) {} + + void InitMainWindow() + { + win_draw->win = new TDrwWindow(win_draw); + SetMainWindow(new TDrwFrameWindow(0, win_draw->win)); + GetMainWindow()->SetIcon(this, "WinDrawIcon"); + GetMainWindow()->SetIconSm(this, "WinDrawIcon"); + if (def_w > 0 && def_h > 0) + { + GetMainWindow()->Attr.W = def_w + 2*GetSystemMetrics(SM_CXFRAME); + GetMainWindow()->Attr.H = def_h + + GetSystemMetrics(SM_CYCAPTION) + 2*GetSystemMetrics(SM_CYFRAME); + } + } + public: + int def_w, def_h; + TWinGraphDraw *win_draw; + }; + + friend class TDrwWindow; + friend class TDrwApplication; +protected: + TDrwApplication app; + TDrwWindow *win; + TDC *dc; + int kind_dc; + TColor bgcolor; + int evmask, quit; +public: + unsigned long GetBgColor(); + void SetBgColor(unsigned long c); + void SetTitle(const char *s); + + int GetStatus() {return win ? 1 : 0;} + int Init() {return 0;} + int Run(int evmask = 0, int w = INT_MIN, int h = INT_MIN); + + void GetSize(int &w, int &h); + int OpenDraw(); + int IsDraw() {return win && dc;} + void CloseDraw(); + + int SetColor(unsigned long c); + int DrawLine(int x0, int y0, int x1, int y1); + int DrawText(int x0, int y0, char *text); + int DrawClear(); + int GetTextH(const char *s); + int GetTextW(const char *s); + void Quit(int q = 1); +}; + +const int TWinGraphDraw::CM_ABOUT = 7128; + +unsigned long TWinGraphDraw::GetKeySym(uint key) +{ + switch(key) + { + case 37: return XK_Left; + case 39: return XK_Right; + case 38: return XK_Up; + case 40: return XK_Down; + case 13: return XK_Return; + case 32: return XK_space; + case 27: return XK_Escape; + case 188: return XK_comma; + case 190: return XK_period; + case 189: return XK_minus; + case 187: return XK_equal; + case 46: return XK_Delete; + case 191: return XK_slash; + case 112: return XK_F1; + case 113: return XK_F2; + case 114: return XK_F3; + case 115: return XK_F4; + case 116: return XK_F5; + case 117: return XK_F6; + case 118: return XK_F7; + case 119: return XK_F8; + case 120: return XK_F9; + case 121: return XK_F10; + case 122: return XK_F11; + case 123: return XK_F12; + case 65: return XK_a; + case 66: return XK_b; + case 67: return XK_c; + case 68: return XK_d; + case 69: return XK_e; + case 70: return XK_f; + case 71: return XK_g; + case 72: return XK_h; + case 73: return XK_i; + case 74: return XK_j; + case 75: return XK_k; + case 76: return XK_l; + case 77: return XK_m; + case 78: return XK_n; + case 79: return XK_o; + case 80: return XK_p; + case 81: return XK_q; + case 82: return XK_r; + case 83: return XK_s; + case 84: return XK_t; + case 85: return XK_u; + case 86: return XK_v; + case 87: return XK_w; + case 88: return XK_x; + case 89: return XK_y; + case 90: return XK_z; + default: return XK_VoidSymbol; + } +} + +TWinGraphDraw::TWinGraphDraw(const char *s) + : TGraphDraw(s), app(this), dc(0), kind_dc(0) +{ + bgcolor = GetWhiteColor(); +} + +TWinGraphDraw::~TWinGraphDraw() +{ + CloseDraw(); + dc = 0; kind_dc = 0; win = 0; +} + +unsigned long TWinGraphDraw::GetBgColor() +{ + if (win) bgcolor = win->GetBkgndColor(); + return bgcolor.GetValue(); +} + +void TWinGraphDraw::SetBgColor(unsigned long c) +{ + bgcolor.SetValue(c); + if (win) win->SetBkgndColor(bgcolor); +} + +void TWinGraphDraw::SetTitle(const char *s) +{ + TGraphDraw::SetTitle(s); + if (win) win->SetCaption(s); +} + +int TWinGraphDraw::Run(int evmask, int w, int h) +{ + if (!evfunc) return -2; + this->evmask = evmask; + app.def_w = w; app.def_h = h; + quit = 0; + app.Run(); + return quit; +} + +void TWinGraphDraw::GetSize(int &w, int &h) +{ + if (win) + { + TRect rect; + win->GetWindowRect(rect); + w = rect.Width(); h = rect.Height(); + } + else TGraphDraw::GetSize(w, h); +} + +int TWinGraphDraw::OpenDraw() +{ + if (!win) return 0; + if (!dc) {dc = new TWindowDC(*win); kind_dc = 1;} + return 1; +} + +void TWinGraphDraw::CloseDraw() +{ + if (dc && kind_dc == 1) delete dc; + if (kind_dc <= 2) {dc = 0; kind_dc = 0;} +} + +int TWinGraphDraw::SetColor(unsigned long c) +{ + if (!win || !dc) return 0; + TColor color(c); + dc->SelectObject((TPen)color); + dc->SetTextColor(color); + return 1; +} + +int TWinGraphDraw::DrawLine(int x0, int y0, int x1, int y1) +{ + if (!win || !dc) return 0; + dc->MoveTo(x0, y0); + dc->LineTo(x1, y1); + return 1; +} + +int TWinGraphDraw::DrawText(int x0, int y0, char *text) +{ + if (!win || !dc) return 0; + dc->TextOut(x0, y0, text); + return 1; +} + +int TWinGraphDraw::DrawClear() +{ + if (!win || !dc) return 0; + dc->FillRect(TRect(TPoint(0, 0), win->GetWindowRect().Size()), bgcolor); + return 1; +} + +int TWinGraphDraw::GetTextH(const char *s) +{ + if (win) + { + TFont fnt = win->GetWindowFont(); + return fnt.GetHeight(); + } + else return TGraphDraw::GetTextH(s); +} + +int TWinGraphDraw::GetTextW(const char *s) +{ + if (win) + { + TFont fnt = win->GetWindowFont(); + return fnt.GetMaxWidth() * strlen(s); + } + else return TGraphDraw::GetTextW(s); +} + +void TWinGraphDraw::Quit(int q) +{ + quit = q; + if (quit <= 0) quit = 0; + else if (win) win->PostMessage(WM_CLOSE); +} + +DEFINE_RESPONSE_TABLE1(TWinGraphDraw::TDrwFrameWindow, TFrameWindow) + EV_WM_SYSCOMMAND, +END_RESPONSE_TABLE; + +TWinGraphDraw::TDrwFrameWindow::TDrwFrameWindow(TWindow *parent, TDrwWindow *client) + : TFrameWindow(parent, client->win_draw->GetTitle(), client) +{ + win_draw = client->win_draw; +} + +void TWinGraphDraw::TDrwFrameWindow::SetupWindow() +{ + TFrameWindow::SetupWindow(); + if (win_draw->GetAboutInfo() > 0) + { + TMenu menu = GetSystemMenu(false); + menu.AppendMenu(MF_SEPARATOR); + menu.AppendMenu(MF_STRING, CM_ABOUT, "&About"); + } +} + +void TWinGraphDraw::TDrwFrameWindow::EvSysCommand(uint cmdType, TPoint& point) +{ + if (cmdType == CM_ABOUT) + { + char dia_name[50] = "IDD_ABOUT"; + int dia_num = win_draw->GetAboutInfo(); + if (dia_num > 0) + { + itoa(dia_num, dia_name + strlen(dia_name), 10); + TAboutDialog(this, dia_name).Execute(); + } + } + else TFrameWindow::EvSysCommand(cmdType, point); +} + +DEFINE_RESPONSE_TABLE1(TWinGraphDraw::TDrwWindow, TWindow) + EV_WM_MOUSEMOVE, + EV_WM_LBUTTONDBLCLK, + EV_WM_LBUTTONDOWN, + EV_WM_LBUTTONUP, + EV_WM_RBUTTONDBLCLK, + EV_WM_RBUTTONDOWN, + EV_WM_RBUTTONUP, + EV_WM_MBUTTONDBLCLK, + EV_WM_MBUTTONDOWN, + EV_WM_MBUTTONUP, + EV_WM_SIZE, + EV_WM_KEYDOWN, + EV_WM_KEYUP, +END_RESPONSE_TABLE; + +void TWinGraphDraw::TDrwWindow::SetupWindow() +{ + TWindow::SetupWindow(); + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0) return; + event ev; + ev.type = event::start; + ev.any.drw = win_draw; + win_draw->evfunc(ev); + win_draw->CloseDraw(); +} + +bool TWinGraphDraw::TDrwWindow::CanClose() +{ + if (!win_draw || !win_draw->evfunc || win_draw->quit > 1) return true; + event ev; + ev.type = event::close; + ev.any.drw = win_draw; + win_draw->quit = win_draw->evfunc(ev); + if (win_draw->quit <= 0) win_draw->quit = 0; + win_draw->CloseDraw(); + return win_draw->quit != 0; +} + +void TWinGraphDraw::TDrwWindow::Paint(TDC &dc, bool, TRect&) +{ + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0) return; + win_draw->CloseDraw(); + win_draw->dc = &dc; win_draw->kind_dc = 2; + event ev; + ev.type = event::draw; + ev.any.drw = win_draw; + win_draw->evfunc(ev); + win_draw->CloseDraw(); +} + +void TWinGraphDraw::TDrwWindow::EvLButtonDown(uint /*modKeys*/, TPoint& point) +{ + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0 || + !(win_draw->evmask & button_down_mask)) return; + event ev; + ev.type = event::button_down; + ev.button.drw = win_draw; + ev.button.n = 1; + ev.button.x = point.x; + ev.button.y = point.y; + int r = win_draw->evfunc(ev); + if (r >= 0 && (r & ret_setcapture)) SetCapture(); + win_draw->CloseDraw(); +} + +void TWinGraphDraw::TDrwWindow::EvLButtonUp(uint /*modKeys*/, TPoint& point) +{ + ReleaseCapture(); + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0 || + !(win_draw->evmask & button_up_mask)) return; + event ev; + ev.type = event::button_up; + ev.button.drw = win_draw; + ev.button.n = 1; + ev.button.x = point.x; + ev.button.y = point.y; + win_draw->evfunc(ev); + win_draw->CloseDraw(); +} + +void TWinGraphDraw::TDrwWindow::EvRButtonDown(uint /*modKeys*/, TPoint& point) +{ + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0 || + !(win_draw->evmask & button_down_mask)) return; + event ev; + ev.type = event::button_down; + ev.button.drw = win_draw; + ev.button.n = 2; + ev.button.x = point.x; + ev.button.y = point.y; + int r = win_draw->evfunc(ev); + if (r >= 0 && (r & ret_setcapture)) SetCapture(); + win_draw->CloseDraw(); +} + +void TWinGraphDraw::TDrwWindow::EvRButtonUp(uint /*modKeys*/, TPoint& point) +{ + ReleaseCapture(); + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0 || + !(win_draw->evmask & button_up_mask)) return; + event ev; + ev.type = event::button_up; + ev.button.drw = win_draw; + ev.button.n = 2; + ev.button.x = point.x; + ev.button.y = point.y; + win_draw->evfunc(ev); + win_draw->CloseDraw(); +} + +void TWinGraphDraw::TDrwWindow::EvMButtonDown(uint /*modKeys*/, TPoint& point) +{ + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0 || + !(win_draw->evmask & button_down_mask)) return; + event ev; + ev.type = event::button_down; + ev.button.drw = win_draw; + ev.button.n = 3; + ev.button.x = point.x; + ev.button.y = point.y; + int r = win_draw->evfunc(ev); + if (r >= 0 && (r & ret_setcapture)) SetCapture(); + win_draw->CloseDraw(); +} + +void TWinGraphDraw::TDrwWindow::EvMButtonUp(uint /*modKeys*/, TPoint& point) +{ + ReleaseCapture(); + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0 || + !(win_draw->evmask & button_up_mask)) return; + event ev; + ev.type = event::button_up; + ev.button.drw = win_draw; + ev.button.n = 3; + ev.button.x = point.x; + ev.button.y = point.y; + win_draw->evfunc(ev); + win_draw->CloseDraw(); +} + +void TWinGraphDraw::TDrwWindow::EvMouseMove(uint /*modKeys*/, TPoint& point) +{ + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0 || + !(win_draw->evmask & (mouse_move_mask | mouse_drag_mask))) return; + event ev; + ev.type = event::mouse_move; + ev.button.drw = win_draw; + ev.button.n = -1; + ev.button.x = point.x; + ev.button.y = point.y; + win_draw->evfunc(ev); + win_draw->CloseDraw(); +} + +void TWinGraphDraw::TDrwWindow::EvKeyDown(uint key, uint /*repeatCount*/, uint /*flags*/) +{ + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0 || + !(win_draw->evmask & key_down_mask)) return; + event ev; + ev.type = event::key_down; + ev.key.drw = win_draw; + ev.key.k = GetKeySym(key); + win_draw->evfunc(ev); + win_draw->CloseDraw(); +} + +void TWinGraphDraw::TDrwWindow::EvKeyUp(uint key, uint /*repeatCount*/, uint /*flags*/) +{ + if (!win_draw || !win_draw->evfunc || win_draw->quit > 0 || + !(win_draw->evmask & key_up_mask)) return; + event ev; + ev.type = event::key_up; + ev.key.drw = win_draw; + ev.key.k = GetKeySym(key); + win_draw->evfunc(ev); + win_draw->CloseDraw(); +} + +#endif //_WIN_GRAPHIC_DRAW_H diff --git a/programs/games/checkers/trunk/winabout.rh b/programs/games/checkers/trunk/winabout.rh new file mode 100644 index 0000000000..306b2a8703 --- /dev/null +++ b/programs/games/checkers/trunk/winabout.rh @@ -0,0 +1,3 @@ +#define IDC_DEBUG 22003 +#define IDC_COPYRIGHT 22002 +#define IDC_VERSION 22001 diff --git a/programs/games/fara/trunk/KosFile.cpp b/programs/games/fara/trunk/KosFile.cpp new file mode 100644 index 0000000000..fe29fa73d0 --- /dev/null +++ b/programs/games/fara/trunk/KosFile.cpp @@ -0,0 +1,131 @@ +#include "kosSyst.h" +#include "kosfile.h" + + +CKosFile::CKosFile(char *fileName) +{ + // + this->fileInfo.bufferPtr = new Byte[FILE_BUFFER_SIZE]; + // + this->filePointer = 0; + this->bufferPointer = 0; + this->validBuffer = false; + // + strcpy( this->fileInfo.fileURL, fileName ); +} + + +CKosFile::~CKosFile(void) +{ + // + delete this->fileInfo.bufferPtr; +} + + +void CKosFile::ValidateBuffer() +{ + // + if ( this->validBuffer ) + { + // + if ( this->filePointer < this->bufferPointer + || this->filePointer >= (this->bufferPointer + FILE_BUFFER_SIZE) ) + { + // + this->validBuffer = false; + } + } +} + + +void CKosFile::UpdateBuffer(void) +{ + // + if ( ! this->validBuffer ) + { + // + this->fileInfo.OffsetLow = this->filePointer / OS_BLOCK_SIZE; + this->fileInfo.OffsetHigh = 0; + // + this->bufferPointer = this->fileInfo.OffsetLow * OS_BLOCK_SIZE; + // + this->fileInfo.dataCount = FILE_BUFFER_BLOCKS; + // + this->fileInfo.rwMode = 0; + // + Dword rr = kos_FileSystemAccess( &(this->fileInfo) ); + this->validBuffer = ( rr == 0 ) || ( rr == 6 ); + } +} + + +int CKosFile::Seek(int seekFrom, int seekStep) +{ + // + switch ( seekFrom ) + { + // + case SEEK_SET: + // + this->filePointer = seekStep; + break; + // + case SEEK_CUR: + // + this->filePointer += seekStep; + break; + } + // + this->ValidateBuffer(); + // + return this->filePointer; +} + + +int CKosFile::Read(Byte *targetPtr, int readCount) +{ + int bufferLeast, result; + + // + result = 0; + // + do + { + // + this->UpdateBuffer(); + // + if ( ! this->validBuffer ) return result; + // + bufferLeast = FILE_BUFFER_SIZE - (this->filePointer - this->bufferPointer); + // + if ( bufferLeast > readCount ) bufferLeast = readCount; + // + if ( bufferLeast ) + { + // + memcpy( + targetPtr, + this->fileInfo.bufferPtr + (this->filePointer - this->bufferPointer), + bufferLeast + ); + // + targetPtr += bufferLeast; + readCount -= bufferLeast; + this->filePointer += bufferLeast; + // + result += bufferLeast; + } + // + this->ValidateBuffer(); + } + while ( readCount > 0 ); + // + return result; +} + + +int CKosFile::Write(Byte *sourcePtr, int writeCount) +{ + return 0; +} + diff --git a/programs/games/fara/trunk/KosFile.h b/programs/games/fara/trunk/KosFile.h new file mode 100644 index 0000000000..5f7c18e9bc --- /dev/null +++ b/programs/games/fara/trunk/KosFile.h @@ -0,0 +1,26 @@ +#pragma once + +#define SEEK_SET 0 +#define SEEK_CUR 1 + +#define FILE_BUFFER_SIZE 512 +#define OS_BLOCK_SIZE 1 +#define FILE_BUFFER_BLOCKS (FILE_BUFFER_SIZE / OS_BLOCK_SIZE) + + +class CKosFile +{ +public: + CKosFile(char *fileName); + virtual ~CKosFile(void); + virtual int Read(Byte *targetPtr, int readCount); + virtual int Write(Byte *sourcePtr, int writeCount); + virtual int Seek(int seekFrom, int seekStep); +protected: + int filePointer; + int bufferPointer; + bool validBuffer; + kosFileInfo fileInfo; + virtual void ValidateBuffer(void); + virtual void UpdateBuffer(void); +}; diff --git a/programs/games/fara/trunk/MCSMEMM.H b/programs/games/fara/trunk/MCSMEMM.H new file mode 100644 index 0000000000..42d61eaadb --- /dev/null +++ b/programs/games/fara/trunk/MCSMEMM.H @@ -0,0 +1,28 @@ +// + +struct MemBlock +{ + Dword Size; + Dword Addr; + MemBlock *Next; + MemBlock *Previous; +}; + + +#define INITIALQUEUESIZE (32 * 4) + +#define FALSE 0 +#define TRUE -1 + +#define MB_FREE 0 +#define MB_USER 1 + +#define SIZE_ALIGN 4 + + + +Byte *allocmem( Dword reqsize ); +Dword freemem( void *vaddress ); + + + diff --git a/programs/games/fara/trunk/Release/pe2kos.exe b/programs/games/fara/trunk/Release/pe2kos.exe new file mode 100644 index 0000000000000000000000000000000000000000..139e746398e5b696be39dded15b36d3de38b324e GIT binary patch literal 13312 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 N@csXx|93O+zW{zRzq9}V literal 0 HcmV?d00001 diff --git a/programs/games/fara/trunk/bmp2src.exe b/programs/games/fara/trunk/bmp2src.exe new file mode 100644 index 0000000000000000000000000000000000000000..984adf2174394b88aeddb59e84a141dc5e4f4a1d GIT binary patch literal 36864 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 I(*H#GH|$nG+yDRo literal 0 HcmV?d00001 diff --git a/programs/games/fara/trunk/bmp2src/bmp2src.dsp b/programs/games/fara/trunk/bmp2src/bmp2src.dsp new file mode 100644 index 0000000000..3b3ad354ac --- /dev/null +++ b/programs/games/fara/trunk/bmp2src/bmp2src.dsp @@ -0,0 +1,103 @@ +# Microsoft Developer Studio Project File - Name="bmp2src" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=bmp2src - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "bmp2src.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "bmp2src.mak" CFG="bmp2src - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "bmp2src - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "bmp2src - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "bmp2src - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib lzmapack.lib /nologo /subsystem:console /machine:I386 /opt:nowin98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "bmp2src - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib lzmapack.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "bmp2src - Win32 Release" +# Name "bmp2src - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\main.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/programs/games/fara/trunk/bmp2src/bmp2src.dsw b/programs/games/fara/trunk/bmp2src/bmp2src.dsw new file mode 100644 index 0000000000..04bd5dd271 --- /dev/null +++ b/programs/games/fara/trunk/bmp2src/bmp2src.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "bmp2src"=.\bmp2src.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/programs/games/fara/trunk/bmp2src/lzmapack.lib b/programs/games/fara/trunk/bmp2src/lzmapack.lib new file mode 100644 index 0000000000000000000000000000000000000000..f24c03846e322bc91b3df0404c799133f2272a54 GIT binary patch literal 36152 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 Ka`POk^!gtf$WcrH literal 0 HcmV?d00001 diff --git a/programs/games/fara/trunk/bmp2src/main.cpp b/programs/games/fara/trunk/bmp2src/main.cpp new file mode 100644 index 0000000000..90047be385 --- /dev/null +++ b/programs/games/fara/trunk/bmp2src/main.cpp @@ -0,0 +1,166 @@ +#include +#include + +extern "C" __stdcall lzma_set_dict_size(unsigned logdictsize); +extern "C" __stdcall lzma_compress( + const void* source, + void* destination, + unsigned length, + void* workmem); + +typedef struct +{ + short int sizeX; + short int sizeY; + int compressedSize; + int physicalOffset; + int uncompressedSize; +} SCompBmpHeader; + +int main(int argc, char* argv[]) +{ + if (argc < 3) + { + printf("Usage: bmp2src ...\n"); + return 1; + } + FILE* fo = fopen(argv[1], "wb"); + if (!fo) + { + printf("Cannot create destination file\n"); + return 2; + } + int n=0; + SCompBmpHeader* hea = (SCompBmpHeader*)malloc((argc-2)*sizeof(SCompBmpHeader)); + void** ptrs = (void**)malloc((argc-2)*4); + lzma_set_dict_size(20); + void* workmem = (void*)malloc(0x509000 + (1<<20)*19/2); + for (int i=2;i= 0xE0 && buf[1] <= 0xEF) + { + fseek(fi,buf[2]*256 + buf[3] - 2,SEEK_CUR); + continue; + } + unsigned len = buf[2]*256 + buf[3] + 2; + fseek(fi,-4,SEEK_CUR); + fread(ptr,1,len,fi); + if (buf[1]>=0xC0 && buf[1]<=0xCF && buf[1]!=0xC4 && buf[1]!=0xC8 && buf[1]!=0xCC) + { + // found SOFn marker + hea[i-2].sizeX = (unsigned char)ptr[4+3]*256 + (unsigned char)ptr[4+4]; + hea[i-2].sizeY = (unsigned char)ptr[4+1]*256 + (unsigned char)ptr[4+2]; + bOk = true; + } + ptr += len; + if (buf[1] == 0xDA) + { + // SOS marker + len = insize - ftell(fi); + fread(ptr,1,len,fi); + ptr += len; + break; + } + } + if (!bOk) {printf(" invalid\n");free(ptr);continue;} + hea[i-2].compressedSize = ptr - (unsigned char*)output; + hea[i-2].uncompressedSize = hea[i-2].compressedSize - 1; + hea[i-2].physicalOffset = (i==2) ? 0 : + hea[i-3].physicalOffset+hea[i-3].compressedSize; + ptrs[i-2] = output; + ++n; + printf(" OK\n"); + continue; + } + if (buf[0x1C] != 24) + { + printf("Input file %s is not 24-bit BMP\n",argv[i]); + fclose(fi); + continue; + } + int width = *(int*)(buf+0x12); + int linesize = (width*3+3)&~3; + int height = *(int*)(buf+0x16); + void* input = malloc(width*height*3); + void* packed = malloc(9*width*height*3/8 + 0x80); + for (int p=0;p= uncompressedSize) + { + compressedSize = uncompressedSize; + free(packed); + ptrs[i-2] = input; + } + else + { + ptrs[i-2] = packed; + free(input); + } + printf(" %d -> %d\n",uncompressedSize, compressedSize); + hea[i-2].compressedSize = compressedSize; + ++n; + } + for (i=0;i= 0x8320; i-- ) + { + mask = i; + for ( j=0; j<8; j++ ) + { + k = mask; + mask >>= 1; + if ( k & 1 ) + { + mask ^= 0xEDB88320; + } + this->table[i & 0xFF] = mask; + } + } +} + + +Dword CCRC32::InitCRC32() +{ + return 0xFFFFFFFF; +} + + +Dword CCRC32::FinalizeCRC32(Dword d) +{ + return ~d; +} + + +void CCRC32::DoCRC32(Byte *buffer, Dword length, Dword *CRC32value) +{ + Dword result, i; + Byte mask; + + result = *CRC32value; + + for ( i=0; i>= 8 ) ^ this->table[mask]; + } + *CRC32value = result; +} + + +Dword CCRC32::GetCRC32(Byte *buffer, Dword length) +{ + Dword result; + + result = 0xFFFFFFFF; + + this->DoCRC32( buffer, length, &result ); + + return ~result; +} diff --git a/programs/games/fara/trunk/crc32.h b/programs/games/fara/trunk/crc32.h new file mode 100644 index 0000000000..2aceabb227 --- /dev/null +++ b/programs/games/fara/trunk/crc32.h @@ -0,0 +1,18 @@ +#if !defined(AFX_CRC32_H__1F375B73_5C72_4711_B464_7212EFC14AAE__INCLUDED_) +#define AFX_CRC32_H__1F375B73_5C72_4711_B464_7212EFC14AAE__INCLUDED_ + +class CCRC32 +{ +private: + Dword table[256]; + + +public: + Dword GetCRC32( Byte *buffer, Dword length ); + void DoCRC32( Byte *buffer, Dword length, Dword *CRC32value ); + Dword FinalizeCRC32( Dword ); + Dword InitCRC32(); + CCRC32(); +}; + +#endif // !defined(AFX_CRC32_H__1F375B73_5C72_4711_B464_7212EFC14AAE__INCLUDED_) diff --git a/programs/games/fara/trunk/face.bmp b/programs/games/fara/trunk/face.bmp new file mode 100644 index 0000000000000000000000000000000000000000..34ff774115c983dfb9a080d1dbbc697e5cde91d7 GIT binary patch literal 115256 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/programs/games/fara/trunk/gameWnd.cpp b/programs/games/fara/trunk/gameWnd.cpp new file mode 100644 index 0000000000..833dab8997 --- /dev/null +++ b/programs/games/fara/trunk/gameWnd.cpp @@ -0,0 +1,1585 @@ +// + +#include "kosSyst.h" +#include "KosFile.h" +#include "gfxdef.h" +#include "gameWnd.h" +#include "mcarray.h" +#include "lang.h" + +// +#define EMPTY_PLACE 0 + +#define LEVEL_PROGRESS_LEFT (132+1) +#define LEVEL_PROGRESS_TOP (388+21) +#define LEVEL_PROGRESS_HEIGHT 4 +#define LEVEL_PROGRESS_WIDTH 329 +#define LEVEL_PROGRESS_COLOUR 0xDF2933 + +#define BONUS_SOMEBLOCK_TOP (120+21) +#define BONUS_SOMEBLOCK_LEFT (46+1) +#define BONUS_FREEBLOCK_TOP (163+21) +#define BONUS_FREEBLOCK_LEFT (9+1) +#define BONUS_DIAGBLOCK_TOP (213+21) +#define BONUS_DIAGBLOCK_LEFT (48+1) +#define BONUS_PROGRESS_HEIGHT 37 +#define BONUS_PROGRESS_WIDTH 4 + +#define LEVEL_SCORE_BASE 50 + +// +CKosBitmap gameFace; +CKosBitmap gameBlocks; +CKosBitmap gameNumbers; +CKosBitmap gameBlocksZ[4]; +// +CFishka *fishki[blocksNum]; + +// +char *gameWndTitle; +#if LANG == RUS +char gameWndTitle1[] = "” а ®­ ¦¤св ⥡п :)"; +char gameWndTitle2[] = "Ќг ў®в..."; +char gameOverText[] = "„ «миҐ ¤®а®ЈЁ ­Ґв!"; +#else +char gameWndTitle1[] = "Pharaoh waits for you :)"; +char gameWndTitle2[] = "Well..."; +char gameOverText[] = "No further way!"; +#endif +// +Word gcx, gcy; +// +#define mapSize 8 +// +// +#define blocksLeft (134+2) +#define blocksTop (43+22) +// +#define blockTypesNum 10 +// +Byte gameMap[mapSize * mapSize]; +// уровень +int gameLevel; +// +int maxGameLevel; +int startGameLevel; +// счёт +Dword playerScore; +// счётчик добавленных блоков +int insertedBlocksCount; +// количество блоков для перехода на следующий уровень +int levelBlocksLimit; +// номер выделенного блока +int selectedBlock; +// прибавление шага для индикатора прохождения уровня * 1024 +int levelProgressStep; +// занчение индикатора прохождения уровня +int levelProgressCount; +// блоки для удаления +struct sRemoveBlock +{ + short int ndx; + short int value; + sRemoveBlock() + { + this->ndx = 0; + this->value = 0; + }; + sRemoveBlock( int pNdx, int pValue ) + { + this->ndx = pNdx; + this->value = pValue; + }; +}; +bool operator == ( const sRemoveBlock &b1, const sRemoveBlock &b2 ) +{ + return b1.ndx == b2.ndx; +}; +MCArray toRemoveList; +// падающие блоки +MCArray toFallList; +// +bool mouseButtonDisabled; +// +bool freezeBonuses = false; +// +int bonusSomeBlockProgressStep; +int bonusSomeBlockProgressCount; +// +int bonusFreeBlockProgressStep; +int bonusFreeBlockProgressCount; +// +int bonusDiagBlockProgressStep; +int bonusDiagBlockProgressCount; + + + +#define SELECTED_BLOCK_NONE -1 + +// бонус включен +int bonusSomeBlock; +// счётчик блоков для бонуса +int bonusSomeBlockCount; +// количество блоков, которое надо убрать, чтобы получить бонус +int bonusSomeBlockEdge; +#define BONUS_SOMEBLOCK_SELECTED -2 +// +bool bonusFreeBlock; +int bonusFreeBlockCount; +int bonusFreeBlockEdge; +#define BONUS_FREEBLOCK_SELECTED -3 +// +int bonusDiagBlock; +int bonusDiagBlockCount; +int bonusDiagBlockEdge; +#define BONUS_DIAGBLOCK_SELECTED -4 +// +void drawScore(); +// отобразить блоки бонусов +void drawBonuses(); +// +void drawLevelNum(); +// +void fadeOutBlocks(); +// +void fallDownBlocks(); + + +void ClearGameMeters() +{ + // индикатор прохождение уровня + kos_DrawBar( + LEVEL_PROGRESS_LEFT, + LEVEL_PROGRESS_TOP, + LEVEL_PROGRESS_WIDTH, + LEVEL_PROGRESS_HEIGHT, + 0 + ); + // индикаторы бонусов + // some + kos_DrawBar( + 33+1, + 118+21, + BONUS_PROGRESS_WIDTH, + BONUS_PROGRESS_HEIGHT, + 0 + ); + // free + kos_DrawBar( + 58+1, + 166+21, + BONUS_PROGRESS_WIDTH, + BONUS_PROGRESS_HEIGHT, + 0 + ); + // diag + kos_DrawBar( + 37+1, + 213+21, + BONUS_PROGRESS_WIDTH, + BONUS_PROGRESS_HEIGHT, + 0 + ); +} + + +// +void drawGameMeters() +{ + // + ClearGameMeters(); + // индикатор прохождение уровня + kos_DrawBar( + LEVEL_PROGRESS_LEFT, + LEVEL_PROGRESS_TOP, + levelProgressCount, + LEVEL_PROGRESS_HEIGHT, + LEVEL_PROGRESS_COLOUR + ); + // + if ( bonusSomeBlockProgressCount > 0 ) + // some + kos_DrawBar( + 33+1, + 118+21+BONUS_PROGRESS_HEIGHT-bonusSomeBlockProgressCount, + BONUS_PROGRESS_WIDTH, + bonusSomeBlockProgressCount, + LEVEL_PROGRESS_COLOUR + ); + // + if ( bonusFreeBlockProgressCount > 0 ) + // free + kos_DrawBar( + 58+1, + 166+21+BONUS_PROGRESS_HEIGHT-bonusFreeBlockProgressCount, + BONUS_PROGRESS_WIDTH, + bonusFreeBlockProgressCount, + LEVEL_PROGRESS_COLOUR + ); + // + if ( bonusDiagBlockProgressCount > 0 ) + // diag + kos_DrawBar( + 37+1, + 213+21+BONUS_PROGRESS_HEIGHT-bonusDiagBlockProgressCount, + BONUS_PROGRESS_WIDTH, + bonusDiagBlockProgressCount, + LEVEL_PROGRESS_COLOUR + ); +} + + +//////////////////////////////////////////////////////////////////////////////// +void SetLevelVariables() +{ + selectedBlock = -1; + levelBlocksLimit = ( gameLevel > 5 ) ? LEVEL_SCORE_BASE * ( gameLevel + 1 ) : LEVEL_SCORE_BASE * ( 11 - gameLevel ); + insertedBlocksCount = 0; + // + levelProgressCount = 0; + levelProgressStep = ( LEVEL_PROGRESS_WIDTH * 1024 ) / levelBlocksLimit; + // + bonusSomeBlockEdge = levelBlocksLimit / 4; + bonusFreeBlockEdge = levelBlocksLimit / 3; + bonusDiagBlockEdge = levelBlocksLimit / 2; + // + bonusSomeBlockProgressStep = ( BONUS_PROGRESS_HEIGHT * 1024 ) / bonusSomeBlockEdge; + bonusSomeBlockProgressCount = ( ( ( bonusSomeBlockCount > bonusSomeBlockEdge ) ? bonusSomeBlockEdge : bonusSomeBlockCount ) * bonusSomeBlockProgressStep ) / 1024; + // + bonusFreeBlockProgressStep = ( BONUS_PROGRESS_HEIGHT * 1024 ) / bonusFreeBlockEdge; + bonusFreeBlockProgressCount = ( ( ( bonusFreeBlockCount > bonusFreeBlockEdge ) ? bonusFreeBlockEdge : bonusFreeBlockCount ) * bonusFreeBlockProgressStep ) / 1024; + // + bonusDiagBlockProgressStep = ( BONUS_PROGRESS_HEIGHT * 1024 ) / bonusDiagBlockEdge; + bonusDiagBlockProgressCount = ( ( ( bonusDiagBlockCount > bonusDiagBlockEdge ) ? bonusDiagBlockEdge : bonusDiagBlockCount ) * bonusDiagBlockProgressStep ) / 1024; +} + + +// +int GetScoreByBlocks( int blocksCount ) +{ + int limit, update, i, j, acc; + + // + if ( blocksCount < 3 ) return 0; + // + limit = 20 * blocksNum * gameLevel; + // + update = gameLevel; + acc = 1; + // + j = blocksCount - 3; + // + for ( i = 0; i < j; i++ ) + { + // + acc *= gameLevel + 1; + // + if ( ( update + acc ) > limit ) return limit; + } + // + return update + acc; +} + + + +// +int insertNewBlocks() +{ + int i, j, k, ndx, result, btn; + + // + toFallList.Clear(); + // + result = 0; + // + btn = gameLevel > 5 ? blockTypesNum : 5 + gameLevel; + // + ndx = ( mapSize * mapSize ) - mapSize; + // + for ( i = 0; i < mapSize; i++ ) + { + for ( j = 0; j < mapSize; j++ ) + { + // + k = ndx + i - ( j * mapSize ); + // + if ( gameMap[k] == EMPTY_PLACE ) + { + // + for ( ; j < (mapSize-1); j++ ) + { + // + gameMap[k] = gameMap[k-mapSize]; + toFallList.AddExclusive( k ); + k -= mapSize; + } + // + gameMap[i] = ( rtlRand() % btn ) + 1; + toFallList.AddExclusive( i ); + // + result++; + // + break; + } + } + } + // + insertedBlocksCount += result; + // + return result; +} + + +// поиск цепочек блоков для удаления, удаление блоков +// возвращает приращение счёта игрока +int findBlockLines() +{ + int x, y, ndx; + int removeCount = 0; + + // очистим список для записи результатов + toRemoveList.Clear(); + // + for ( y = 0; y < mapSize; y++ ) + { + // + for ( x = 0; x < mapSize; x++ ) + { + // + ndx = x + ( y * mapSize ); + // + if ( gameMap[ndx] == EMPTY_PLACE ) continue; + // проверяем горизонтальную цепочку + if ( x < (mapSize - 2) ) + { + // + if ( + ( gameMap[ndx] == gameMap[ndx+1] && gameMap[ndx] == gameMap[ndx+2] ) + || ( BONUS_FREE_BLOCK == gameMap[ndx] && gameMap[ndx+1] == gameMap[ndx+2] ) + || ( gameMap[ndx] == gameMap[ndx+1] && BONUS_FREE_BLOCK == gameMap[ndx+2] ) + || ( gameMap[ndx] == gameMap[ndx+2] && BONUS_FREE_BLOCK == gameMap[ndx+1] ) + ) + { + // нашли цепочку, запомним + toRemoveList.AddExclusive( sRemoveBlock( ndx, gameMap[ndx] ) ); + toRemoveList.AddExclusive( sRemoveBlock( ndx+1, gameMap[ndx+1] ) ); + toRemoveList.AddExclusive( sRemoveBlock( ndx+2, gameMap[ndx+2] ) ); + } + } + // проверяем вертикальную цепочку + if ( y < (mapSize - 2) ) + { + // + if ( + ( gameMap[ndx] == gameMap[ndx+mapSize] && gameMap[ndx] == gameMap[ndx+mapSize+mapSize] ) + || ( BONUS_FREE_BLOCK == gameMap[ndx] && gameMap[ndx+mapSize] == gameMap[ndx+mapSize+mapSize] ) + || ( gameMap[ndx] == gameMap[ndx+mapSize] && BONUS_FREE_BLOCK == gameMap[ndx+mapSize+mapSize] ) + || ( gameMap[ndx] == gameMap[ndx+mapSize+mapSize] && BONUS_FREE_BLOCK == gameMap[ndx+mapSize] ) + ) + { + // нашли цепочку, запомним + toRemoveList.AddExclusive( sRemoveBlock( ndx, gameMap[ndx] ) ); + toRemoveList.AddExclusive( sRemoveBlock( ndx+mapSize, gameMap[ndx+mapSize] ) ); + toRemoveList.AddExclusive( sRemoveBlock( ndx+mapSize+mapSize, gameMap[ndx+mapSize+mapSize] ) ); + } + } + } + } + // + return toRemoveList.GetCount(); +} + + +// проверка на невозможность собрать какую-нибудь линию +bool checkGameOut() +{ + int x, y, ndx; + + // + ndx = 0; + // + for ( y = 0; y < mapSize; y++ ) + { + // + for ( x = 0; x < mapSize; x++ ) + { + // проверяем горизонтальные цепочки из двух символов + if ( x < (mapSize - 1) ) + { + // + if ( gameMap[ndx] == gameMap[ndx+1] ) + { + // нашли цепочку из двух блоков + // проверка бонусов + if ( bonusSomeBlock == gameMap[ndx] ) return false; + if ( bonusFreeBlock ) return false; + // проверка обычных перестановок + if ( y > 0 ) + { + // + if ( x > 0 ) + { + // + if ( gameMap[ndx-mapSize-1] == gameMap[ndx] ) return false; + } + // + if ( x < (mapSize - 2) ) + { + // + if ( gameMap[ndx-mapSize+2] == gameMap[ndx] ) return false; + } + } + // + if ( x > 1 ) + { + // + if ( gameMap[ndx-2] == gameMap[ndx] ) return false; + } + // + if ( x < (mapSize - 3) ) + { + // + if ( gameMap[ndx+3] == gameMap[ndx] ) return false; + } + // + if ( y < (mapSize - 1) ) + { + // + if ( x > 0 ) + { + // + if ( gameMap[ndx+mapSize-1] == gameMap[ndx] ) return false; + } + // + if ( x < (mapSize - 2) ) + { + // + if ( gameMap[ndx+mapSize+2] == gameMap[ndx] ) return false; + } + } + // проверка диагональных перестановок + if ( bonusDiagBlock > 0 ) + { + // + if ( y > 0 ) + { + // + if ( x > 1 ) + { + // + if ( gameMap[ndx-mapSize-2] == gameMap[ndx] ) return false; + } + // + if ( gameMap[ndx-mapSize] == gameMap[ndx] ) return false; + // + if ( x < (mapSize - 2) ) + { + // + if ( gameMap[ndx-mapSize+1] == gameMap[ndx] ) return false; + } + // + if ( x < (mapSize - 3) ) + { + // + if ( gameMap[ndx-mapSize+3] == gameMap[ndx] ) return false; + } + } + // + if ( y < (mapSize - 1) ) + { + // + if ( x > 1 ) + { + // + if ( gameMap[ndx+mapSize-2] == gameMap[ndx] ) return false; + } + // + if ( gameMap[ndx+mapSize] == gameMap[ndx] ) return false; + // + if ( x < (mapSize - 2) ) + { + // + if ( gameMap[ndx+mapSize+1] == gameMap[ndx] ) return false; + } + // + if ( x < (mapSize - 3) ) + { + // + if ( gameMap[ndx+mapSize+3] == gameMap[ndx] ) return false; + } + } + } // закончена проверка диагональных перестановок + } + } + // проверяем горизонтальные цепочки из двух блоков с промежутком + if ( x < (mapSize - 2) ) + { + // + if ( gameMap[ndx] == gameMap[ndx+2] ) + { + // нашли два блока с промежутком + // проверка бонусов + if ( bonusSomeBlock == gameMap[ndx] ) return false; + if ( bonusFreeBlock ) return false; + // + if ( y > 0 ) + { + // + if ( gameMap[ndx-mapSize+1] == gameMap[ndx] ) return false; + } + // + if ( y < (mapSize-1) ) + { + // + if ( gameMap[ndx+mapSize+1] == gameMap[ndx] ) return false; + } + // проверка диагональных перестановок + if ( bonusDiagBlock > 0 ) + { + // + if ( y > 0 ) + { + // + if ( gameMap[ndx-mapSize] == gameMap[ndx] ) return false; + // + if ( gameMap[ndx-mapSize+2] == gameMap[ndx] ) return false; + } + // + if ( y < (mapSize-1) ) + { + // + if ( gameMap[ndx+mapSize] == gameMap[ndx] ) return false; + // + if ( gameMap[ndx+mapSize+2] == gameMap[ndx] ) return false; + } + } + } + } + // проверяем вертикальные цепочки из двух символов + if ( y < (mapSize - 1) ) + { + // + if ( gameMap[ndx] == gameMap[ndx+mapSize] ) + { + // нашли цепочку из двух блоков + // проверка бонусов + if ( bonusSomeBlock == gameMap[ndx] ) return false; + if ( bonusFreeBlock ) return false; + // + if ( x > 0 ) + { + // + if ( y > 0 ) + { + // + if ( gameMap[ndx-1-mapSize] == gameMap[ndx] ) return false; + } + // + if ( y < (mapSize - 2) ) + { + // + if ( gameMap[ndx-1+(2*mapSize)] == gameMap[ndx] ) return false; + } + } + // + if ( y > 1 ) + { + // + if ( gameMap[ndx-(2*mapSize)] == gameMap[ndx] ) return false; + } + // + if ( y < (mapSize - 3) ) + { + // + if ( gameMap[ndx+(3*mapSize)] == gameMap[ndx] ) return false; + } + // + if ( x < (mapSize - 1) ) + { + // + if ( y > 0 ) + { + // + if ( gameMap[ndx+1-mapSize] == gameMap[ndx] ) return false; + } + // + if ( y < (mapSize - 2) ) + { + // + if ( gameMap[ndx+1+(2*mapSize)] == gameMap[ndx] ) return false; + } + } + // проверка диагональных перестановок + if ( bonusDiagBlock > 0 ) + { + // + if ( x > 0 ) + { + // + if ( y > 1 ) + { + // + if ( gameMap[ndx-1-(2*mapSize)] == gameMap[ndx] ) return false; + } + // + if ( gameMap[ndx-1] == gameMap[ndx] ) return false; + // + if ( y < (mapSize - 2) ) + { + // + if ( gameMap[ndx-1+mapSize] == gameMap[ndx] ) return false; + } + // + if ( y < (mapSize - 3) ) + { + // + if ( gameMap[ndx-1+(3*mapSize)] == gameMap[ndx] ) return false; + } + } + // + if ( x < (mapSize - 1) ) + { + // + if ( y > 1 ) + { + // + if ( gameMap[ndx+1-(2*mapSize)] == gameMap[ndx] ) return false; + } + // + if ( gameMap[ndx+1] == gameMap[ndx] ) return false; + // + if ( y < (mapSize - 2) ) + { + // + if ( gameMap[ndx+1+mapSize] == gameMap[ndx] ) return false; + } + // + if ( y < (mapSize - 3) ) + { + // + if ( gameMap[ndx+1+(3*mapSize)] == gameMap[ndx] ) return false; + } + } + } // закончена проверка диагональных перестановок + } + } + // проверяем вертикальные цепочки из двух блоков с промежутком + if ( y < (mapSize - 2) ) + { + // + if ( gameMap[ndx] == gameMap[ndx+(2*mapSize)] ) + { + // нашли два блока с промежутком + // проверка бонусов + if ( bonusSomeBlock == gameMap[ndx] ) return false; + if ( bonusFreeBlock ) return false; + // + if ( x > 0 ) + { + // + if ( gameMap[ndx-1+mapSize] == gameMap[ndx] ) return false; + } + // + if ( x < (mapSize-1) ) + { + // + if ( gameMap[ndx+1+mapSize] == gameMap[ndx] ) return false; + } + // проверка диагональных перестановок + if ( bonusDiagBlock > 0 ) + { + // + if ( x > 0 ) + { + // + if ( gameMap[ndx-1] == gameMap[ndx] ) return false; + // + if ( gameMap[ndx-1+(2*mapSize)] == gameMap[ndx] ) return false; + } + // + if ( x < (mapSize-1) ) + { + // + if ( gameMap[ndx+1] == gameMap[ndx] ) return false; + // + if ( gameMap[ndx+1+(2*mapSize)] == gameMap[ndx] ) return false; + } + } + } + } + // + ndx++; + } + } + // + gameWndTitle = gameWndTitle2; + // + return true; +} + + +// +bool exterminateLines() +{ + int deletedBlocks, btn, i, j; + bool needRedrawBonus = false; + + // + btn = gameLevel > 5 ? blockTypesNum : 5 + gameLevel; + // + playerScore += GetScoreByBlocks( deletedBlocks = findBlockLines() ); + // + if ( ! freezeBonuses ) + { + // + if ( gameLevel >= 2 && bonusSomeBlock <= 0 ) bonusSomeBlockCount += deletedBlocks; + if ( gameLevel >= 3 && !bonusFreeBlock ) bonusFreeBlockCount += deletedBlocks; + if ( gameLevel >= 4 && bonusDiagBlock <= 0 ) bonusDiagBlockCount += deletedBlocks; + // первый бонус + if ( + ( bonusSomeBlockCount >= bonusSomeBlockEdge || ( gameLevel >= 2 && deletedBlocks >= 4 ) ) + && bonusSomeBlock <= 0 + ) + { + bonusSomeBlock = ( rtlRand() % btn ) + 1; + needRedrawBonus = true; + if ( bonusSomeBlockCount >= bonusSomeBlockEdge ) bonusSomeBlockCount = 0; + } + if ( bonusSomeBlockCount >= bonusSomeBlockEdge ) bonusSomeBlockCount = 0; + // второй бонус + if ( bonusFreeBlockCount >= bonusFreeBlockEdge || ( gameLevel >=3 && deletedBlocks >= 5 ) ) + { + bonusFreeBlock = true; + needRedrawBonus = true; + if ( bonusFreeBlockCount >= bonusFreeBlockEdge ) bonusFreeBlockCount = 0; + } + if ( bonusFreeBlockCount >= bonusFreeBlockEdge ) bonusFreeBlockCount = 0; + // третий бонус + if ( bonusDiagBlockCount >= bonusDiagBlockEdge || ( gameLevel >= 4 && deletedBlocks >= 6 ) ) + { + bonusDiagBlock = 3; + needRedrawBonus = true; + if ( bonusDiagBlockCount >= bonusDiagBlockEdge ) bonusDiagBlockCount = 0; + } + if ( bonusDiagBlockCount >= bonusDiagBlockEdge ) bonusDiagBlockCount = 0; + // + bonusSomeBlockProgressCount = ( ( ( bonusSomeBlockCount > bonusSomeBlockEdge ) ? bonusSomeBlockEdge : bonusSomeBlockCount ) * bonusSomeBlockProgressStep ) / 1024; + // + bonusFreeBlockProgressCount = ( ( ( bonusFreeBlockCount > bonusFreeBlockEdge ) ? bonusFreeBlockEdge : bonusFreeBlockCount ) * bonusFreeBlockProgressStep ) / 1024; + // + bonusDiagBlockProgressCount = ( ( ( bonusDiagBlockCount > bonusDiagBlockEdge ) ? bonusDiagBlockEdge : bonusDiagBlockCount ) * bonusDiagBlockProgressStep ) / 1024; + // + if ( needRedrawBonus ) drawBonuses(); + } + // + j = toRemoveList.GetCount(); + // + for ( i = 0; i < j; i++ ) + { + gameMap[toRemoveList[i].ndx] = EMPTY_PLACE; + } + // + return toRemoveList.GetCount() > 0; +} + + +// заполнение игрового поля случайной комбинацией блоков +void initGameMap() +{ + int i, localScore, localInserted, btn; + + // + btn = gameLevel > 5 ? blockTypesNum : 5 + gameLevel; + // + for ( i = 0; i < (mapSize * mapSize); i++ ) + { + gameMap[i] = ( rtlRand() % btn ) + 1; + } + // + localScore = playerScore; + localInserted = insertedBlocksCount; + // + freezeBonuses = true; + // + while ( exterminateLines() ) + { + while ( insertNewBlocks() > 0 ); + } + // + freezeBonuses = false; + // + playerScore = localScore; + insertedBlocksCount = localInserted; +} + + +// отобразить блоки бонусов +void drawBonuses() +{ + // + kos_PutImage( + selectedBlock != BONUS_SOMEBLOCK_SELECTED ? + fishki[bonusSomeBlock]->GetBits() : + fishki[bonusSomeBlock]->GetHighlightedBits(), + blockSize, blockSize, + BONUS_SOMEBLOCK_LEFT, BONUS_SOMEBLOCK_TOP + ); + // + kos_PutImage( + bonusFreeBlock ? + ( + selectedBlock != BONUS_FREEBLOCK_SELECTED ? + fishki[BONUS_FREE_BLOCK]->GetBits() : + fishki[BONUS_FREE_BLOCK]->GetHighlightedBits() + ) : + fishki[0]->GetBits(), + blockSize, blockSize, + BONUS_FREEBLOCK_LEFT, BONUS_FREEBLOCK_TOP + ); + // + kos_PutImage( + bonusDiagBlock > 0 ? + fishki[bonusDiagBlock+BONUS_DIAG_BLOCK-1]->GetBits() : + fishki[0]->GetBits(), + blockSize, blockSize, + BONUS_DIAGBLOCK_LEFT, BONUS_DIAGBLOCK_TOP + ); +} + + +// отобразить игровое поле +void drawGameMap() +{ + int i, j, ndx; + + // + for ( i = 0; i < mapSize; i++ ) + { + // + for ( j = 0; j < mapSize; j++ ) + { + // + ndx = (i*mapSize) + j; + // + kos_PutImage( + ndx != selectedBlock ? + fishki[gameMap[ndx]]->GetBits() : + fishki[gameMap[ndx]]->GetHighlightedBits(), + blockSize, blockSize, + (j * blockSize) + blocksLeft, + (i * blockSize) + blocksTop + ); + } + } +} + + +// координаты курсора "мыши" +int mX, mY; + +// проверка на нажатие левой кнопки "мыши" +bool mouseLButtonDown() +{ + static bool isDown = false; + Dword buttons; + + // + kos_GetMouseState( buttons, mX, mY ); + // + if ( mouseButtonDisabled ) return false; + // + if ( ( buttons & 1 ) ) + { + if ( isDown ) + return false; + else + { + isDown = true; + return true; + } + } + else + { + if ( isDown ) + { + isDown = false; + } + return false; + } +} + +// +void flipTwoBlocks( int ndx1, int ndx2 ) +{ + Word blX, blY, selX, selY; + Byte fishCode; + + // + blX = ( ndx1 % mapSize ) * blockSize + blocksLeft; + blY = ( ndx1 / mapSize ) * blockSize + blocksTop; + selX = ( ndx2 % mapSize ) * blockSize + blocksLeft; + selY = ( ndx2 / mapSize ) * blockSize + blocksTop; + // переставим блоки местами + fishCode = gameMap[ndx1]; + gameMap[ndx1] = gameMap[ndx2]; + gameMap[ndx2] = fishCode; + // изображение блока + kos_PutImage( + fishki[gameMap[ndx1]]->GetBits(), + blockSize, blockSize, + blX, + blY + ); + // изображение блока + kos_PutImage( + fishki[gameMap[ndx2]]->GetBits(), + blockSize, blockSize, + selX, + selY + ); +} + + +// игровой процесс +int GameLoop() +{ + int result, ndx, blX, blY, selX, selY, ddX, ddY, nSel; + Byte keyCode, mCode; + bool needDecBonus; + Dword buttonID; + + // + gameWndTitle = gameWndTitle1; + gameFace.GetSize( gcx, gcy ); + gameLevel = startGameLevel; + playerScore = 0; + bonusSomeBlock = 0; + bonusFreeBlock = false; + bonusDiagBlock = 0; + bonusSomeBlockCount = 0; + bonusFreeBlockCount = 0; + bonusDiagBlockCount = 0; + bonusSomeBlockProgressCount = 0; + bonusFreeBlockProgressCount = 0; + bonusDiagBlockProgressCount = 0; + SetLevelVariables(); + mouseButtonDisabled = false; + initGameMap(); + // + kos_ChangeWindow( -1, -1, gcx + 1, gcy + 21 ); + // + for ( result = GM_NONE; result == GM_NONE; ) + { + switch( kos_WaitForEvent() ) + { + // надо полностью перерисовать окно + case 1: + DrawGameWindow(); + break; + + // клавиатура + case 2: + if ( kos_GetKey( keyCode ) ) + { + // + switch ( keyCode ) + { + case 0x1B: + result = GM_ABORT; + break; + + default: + break; + } + } + break; + + // кнопки + case 3: + if ( kos_GetButtonID( buttonID ) ) + { + switch ( buttonID ) + { + case 0xA: + result = GM_ABORT; + break; + + default: + break; + } + } + + // событие от мыши + case 6: + // нажатие левой кнопки? + if ( mouseLButtonDown() ) + { + // считаем координаты относително игрового поля + blX = mX - blocksLeft; + blY = mY - blocksTop; + // попало в игровое поле? + if ( blX >= 0 && blX < (mapSize * blockSize) + && blY >= 0 && blY < (mapSize * blockSize) ) + { + // получаем координаты в блоках + blX /= blockSize; + blY /= blockSize; + // получаем номер блока на карте + ndx = blX + ( blY * mapSize ); + // ещё одна проверка, чтобы не вылезти за пределы карты + if ( ndx >= 0 && ndx < (mapSize * mapSize) ) + { + // начинаем перерисовку + kos_WindowRedrawStatus( WRS_BEGIN ); + // если не было выбранного блока + if ( selectedBlock == SELECTED_BLOCK_NONE ) + { + // запомним выделенный блок + selectedBlock = ndx; + // отметим блок на игровом поле + kos_PutImage( + fishki[gameMap[selectedBlock]]->GetHighlightedBits(), + blockSize, blockSize, + ( selectedBlock % mapSize ) * blockSize + blocksLeft, + ( selectedBlock / mapSize ) * blockSize + blocksTop + ); + } + else // помеченный блок уже есть + { + if ( selectedBlock >= 0 ) + { + // координаты помеченного блока + selX = selectedBlock % mapSize; + selY = selectedBlock / mapSize; + // был выбран другой блок? + if ( ndx != selectedBlock ) + { + // считаем разность координат двух блоков + ddX = selX - blX; + ddY = selY - blY; + needDecBonus = ( bonusDiagBlock > 0 && abs(ddX) == 1 && abs(ddY) == 1 ); + // если это соседний блок + if ( + ( abs(ddX) == 1 && ddY == 0 ) + || ( abs(ddY) == 1 && ddX == 0 ) + || needDecBonus + ) + { + // переставим блоки местами + flipTwoBlocks( ndx, selectedBlock ); + // + kos_Pause( 16 ); + // + if ( findBlockLines() > 0 ) + { + // + if ( needDecBonus ) + { + // + --bonusDiagBlock; + // + drawBonuses(); + } + // снимаем пометку с блока + selectedBlock = SELECTED_BLOCK_NONE; + // + while ( exterminateLines() ) + { + // + fadeOutBlocks(); + // + //drawGameMap(); + //drawScore(); + // + //kos_Pause( 25 ); + // + while ( insertNewBlocks() > 0 ) + { + // + fallDownBlocks(); + // + //drawGameMap(); + //kos_Pause( 30 ); + } + } + // + drawScore(); + // + levelProgressCount = ( ( ( insertedBlocksCount > levelBlocksLimit ) ? levelBlocksLimit : insertedBlocksCount ) * levelProgressStep ) / 1024; + // + drawGameMeters(); + // + if ( insertedBlocksCount > levelBlocksLimit ) + { + kos_Pause( 50 ); + gameLevel++; + SetLevelVariables(); + // + //initGameMap(); + // + //DrawGameWindow(); + // + drawGameMeters(); + drawLevelNum(); + } + else + // + if ( mouseButtonDisabled = checkGameOut() ) + { + // + DrawGameWindow(); + } + } + else + { + // не получается линии, блоки ставим на место + flipTwoBlocks( ndx, selectedBlock ); + // снимаем пометку с блока + selectedBlock = SELECTED_BLOCK_NONE; + } + } + else // выбран несоседний блок + { + // перестим маркер + kos_PutImage( + fishki[gameMap[selectedBlock]]->GetBits(), + blockSize, blockSize, + selX * blockSize + blocksLeft, + selY * blockSize + blocksTop + ); + // пометим выбранный блок + selectedBlock = ndx; + // на игровом поле + kos_PutImage( + fishki[gameMap[selectedBlock]]->GetHighlightedBits(), + blockSize, blockSize, + blX * blockSize + blocksLeft, + blY * blockSize + blocksTop + ); + } + } + else // выбран тот же блок + { + // снимаем пометку + kos_PutImage( + fishki[gameMap[selectedBlock]]->GetBits(), + blockSize, blockSize, + selX * blockSize + blocksLeft, + selY * blockSize + blocksTop + ); + // + selectedBlock = SELECTED_BLOCK_NONE; + } + } + else + // ткнули в блок при выбранном бонусе + { + // + mCode = gameMap[ndx]; + // + switch ( selectedBlock ) + { + case BONUS_SOMEBLOCK_SELECTED: + gameMap[ndx] = bonusSomeBlock; + break; + + case BONUS_FREEBLOCK_SELECTED: + gameMap[ndx] = BONUS_FREE_BLOCK; + break; + + default: + break; + } + // + if ( findBlockLines() > 0 ) + { + // убираем использованный бонус + switch ( selectedBlock ) + { + case BONUS_SOMEBLOCK_SELECTED: + bonusSomeBlock = 0; + break; + + case BONUS_FREEBLOCK_SELECTED: + bonusFreeBlock = false; + break; + + default: + break; + } + // на экране тоже + drawBonuses(); + drawGameMap(); + kos_Pause( 16 ); + // убираем блоки + // снимаем пометку с блока + selectedBlock = SELECTED_BLOCK_NONE; + // + while ( exterminateLines() ) + { + // + fadeOutBlocks(); + // + //drawGameMap(); + //drawScore(); + // + //kos_Pause( 25 ); + // + while ( insertNewBlocks() > 0 ) + { + // + fallDownBlocks(); + // + //drawGameMap(); + //kos_Pause( 30 ); + } + } + // + drawScore(); + // + levelProgressCount = ( ( ( insertedBlocksCount > levelBlocksLimit ) ? levelBlocksLimit : insertedBlocksCount ) * levelProgressStep ) / 1024; + // + drawGameMeters(); + // + if ( insertedBlocksCount > levelBlocksLimit ) + { + kos_Pause( 50 ); + gameLevel++; + SetLevelVariables(); + // + //initGameMap(); + // + //DrawGameWindow(); + // + drawGameMeters(); + drawLevelNum(); + } + else + // + mouseButtonDisabled = checkGameOut(); + } + else + // бонус здесь неприменим + { + // вернём взад + gameMap[ndx] = mCode; + // пометим блок + selectedBlock = ndx; + // на игровом поле + kos_PutImage( + fishki[gameMap[selectedBlock]]->GetHighlightedBits(), + blockSize, blockSize, + blX * blockSize + blocksLeft, + blY * blockSize + blocksTop + ); + // уберём пометку с бонуса + drawBonuses(); + } + } + } + // определим кнопку + kos_DefineButton( + 444+1, 2+21, + 54, 20, + 0x6000000A, + 0 + ); + // завершаем перерисовку + kos_WindowRedrawStatus( WRS_END ); + } + } + else + // проверим попадание в бонусы + { + nSel = 0; + // + if ( mX >= BONUS_SOMEBLOCK_LEFT && (mX - BONUS_SOMEBLOCK_LEFT) <= blockSize + && mY >= BONUS_SOMEBLOCK_TOP && (mY - BONUS_SOMEBLOCK_TOP ) <= blockSize ) + { + // + nSel = BONUS_SOMEBLOCK_SELECTED; + } + // + if ( mX >= BONUS_FREEBLOCK_LEFT && (mX - BONUS_FREEBLOCK_LEFT) <= blockSize + && mY >= BONUS_FREEBLOCK_TOP && (mY - BONUS_FREEBLOCK_TOP ) <= blockSize ) + { + // + nSel = BONUS_FREEBLOCK_SELECTED; + } + // + if ( mX >= BONUS_DIAGBLOCK_LEFT && (mX - BONUS_DIAGBLOCK_LEFT) <= blockSize + && mY >= BONUS_DIAGBLOCK_TOP && (mY - BONUS_DIAGBLOCK_TOP ) <= blockSize ) + { + // + nSel = BONUS_DIAGBLOCK_SELECTED; + } + // + if ( nSel != 0 ) + { + // + if ( selectedBlock > 0 ) + { + // снимаем пометку + kos_PutImage( + fishki[gameMap[selectedBlock]]->GetBits(), + blockSize, blockSize, + (selectedBlock % mapSize) * blockSize + blocksLeft, + (selectedBlock / mapSize) * blockSize + blocksTop + ); + } + // + if ( selectedBlock != nSel ) + selectedBlock = nSel; + else + selectedBlock = SELECTED_BLOCK_NONE; + // + drawBonuses(); + } + } + + } + // + break; + + default: + break; + } + } + // отменим кнопку + kos_DefineButton( + 0, 0, + 0, 0, + 0x8000000A, + 0 + ); + // + if ( gameLevel > maxGameLevel ) maxGameLevel = gameLevel; + // + return result; +} + +// +void drawLevelNum() +{ + Word startX; + + // + if ( gameLevel > 9 ) + { + // + startX = LEVEL_LEFT; + // + kos_PutImage( + gameNumbers.GetBits() + ( ( gameLevel / 10 ) * NUM_WIDTH * NUM_HEIGHT ), + NUM_WIDTH, NUM_HEIGHT, + startX, LEVEL_TOP + ); + // + startX += NUM_WIDTH; + } + else + { + // + startX = LEVEL_LEFT + ( (LEVEL_WIDTH - NUM_WIDTH) / 2 ); + } + // + kos_PutImage( + gameNumbers.GetBits() + ( ( gameLevel % 10 ) * NUM_WIDTH * NUM_HEIGHT ), + NUM_WIDTH, NUM_HEIGHT, + startX, LEVEL_TOP + ); +} + +// +void drawScore() +{ + Word startX; + int i, j; + char strNum[8]; + + // число в текстовом виде + sprintf( strNum, "%U", playerScore ); + // + j = strlen( strNum ); + // + startX = SCORE_LEFT + ( ( SCORE_WIDTH - ( NUM_WIDTH * j ) ) / 2 ); + // + for ( i = 0; i < j; i++ ) + { + // + kos_PutImage( + gameNumbers.GetBits() + ( ( strNum[i] - '0' ) * NUM_WIDTH * NUM_HEIGHT ), + NUM_WIDTH, NUM_HEIGHT, + startX, SCORE_TOP + ); + // + startX += NUM_WIDTH; + } +} + + +// +void DrawGameWindow() +{ + // + kos_WindowRedrawStatus( WRS_BEGIN ); + // окно + kos_DefineAndDrawWindow( + WNDLEFT, WNDTOP, + gcx + 1, gcy + 21, + 0, 0x0, + 0, WNDHEADCOLOUR, + WNDHEADCOLOUR + ); + // заголовок окна + kos_WriteTextToWindow( + 4, 7, + 0x10, WNDTITLECOLOUR, + gameWndTitle, strlen(gameWndTitle) + ); + // + gameFace.Draw( 1, 21 ); + drawGameMap(); + drawGameMeters(); + drawBonuses(); + // номер уровня + drawLevelNum(); + drawScore(); + // + if ( mouseButtonDisabled ) + { + // + kos_DrawBar( + ( gcx + 1 - 160 ) / 2, ( gcy + 21 - 32 ) / 2, + 160, 32, + 0x2383B3 + ); + // + kos_WriteTextToWindow( + ( gcx + 1 - sizeof( gameOverText ) * 6 ) / 2, ( gcy + 21 - 9 ) / 2, + 0x0, 0xF7F7F7, + gameOverText, + sizeof( gameOverText ) + ); + } + // определим кнопку + kos_DefineButton( + 444+1, 2+21, + 54, 20, + 0x6000000A, + 0 + ); + // + kos_WindowRedrawStatus( WRS_END ); +} + + +// +void fadeOutBlocks() +{ + int i, j, k, ndx, x, y; + + // + j = toRemoveList.GetCount(); + // + for ( k = 0; k < 4; k++ ) + { + // + __asm{ + push eax + push ebx + mov eax, 18 + mov ebx, 14 + int 0x40 + pop eax + pop ebx + } + // + for ( i = 0; i < j; i++ ) + { + // + ndx = toRemoveList[i].ndx; + y = ndx / mapSize; + x = ndx % mapSize; + // + kos_PutImage( + gameBlocksZ[k].GetBits() + ( (toRemoveList[i].value - 1) * blockSize * blockSize ), + blockSize, blockSize, + (x * blockSize) + blocksLeft, + (y * blockSize) + blocksTop + ); + } + // + kos_Pause( 3 ); + } + //clear + for ( i = 0; i < j; i++ ) + { + // + ndx = toRemoveList[i].ndx; + y = ndx / mapSize; + x = ndx % mapSize; + // + kos_DrawBar( + (x * blockSize) + blocksLeft, + (y * blockSize) + blocksTop, + blockSize, blockSize, 0 + ); + } + // + kos_Pause( 16 ); +} + + +// +void fallDownBlocks() +{ + int i, j, k, ndx, x, y, height, offset; + + // + j = toFallList.GetCount(); + // + for ( k = 1; k <= blockSize; k += 2 ) + { + // + __asm{ + push eax + push ebx + mov eax, 18 + mov ebx, 14 + int 0x40 + pop eax + pop ebx + } + // + for ( i = 0; i < j; i++ ) + { + // + ndx = toFallList[i]; + // + y = ( ( ( ndx / mapSize ) - 1 ) * blockSize ) + k; + if ( y < 0 ) + { + y = 0; + height = k; + offset = blockSize - k; + } + else + { + offset = 0; + height = blockSize; + } + // + x = ( ndx % mapSize ) * blockSize; + // + kos_PutImage( + fishki[gameMap[ndx]]->GetBits() + ( offset * blockSize ), + blockSize, height, + x + blocksLeft, + y + blocksTop + ); + } + // + kos_Pause( 1 ); + } +} diff --git a/programs/games/fara/trunk/gameWnd.h b/programs/games/fara/trunk/gameWnd.h new file mode 100644 index 0000000000..b82f9b0ef0 --- /dev/null +++ b/programs/games/fara/trunk/gameWnd.h @@ -0,0 +1,29 @@ +// gameWnd.h + +extern CKosBitmap gameFace; +extern CKosBitmap gameBlocks; +extern CKosBitmap gameNumbers; +extern CKosBitmap gameBlocksZ[4]; +extern CFishka *fishki[blocksNum]; +extern Dword playerScore; + +#define GM_NONE 0 +#define GM_TOP10 1 +#define GM_ABORT 2 + +#define NUM_WIDTH 12 +#define NUM_HEIGHT 20 + +#define SCORE_LEFT (9+2) +#define SCORE_TOP (57+22) +#define SCORE_WIDTH 72 + +#define LEVEL_LEFT (66+2) +#define LEVEL_TOP (89+22) +#define LEVEL_WIDTH 24 + +// +void DrawGameWindow(); +// +int GameLoop(); + diff --git a/programs/games/fara/trunk/gfxdef.cpp b/programs/games/fara/trunk/gfxdef.cpp new file mode 100644 index 0000000000..16a48f271a --- /dev/null +++ b/programs/games/fara/trunk/gfxdef.cpp @@ -0,0 +1,285 @@ +#include "kosSyst.h" +#include "KosFile.h" +#include "gfxdef.h" +#include "crc32.h" + +extern "C" void __stdcall lzma_decompress( + const void* source, + void* destination, + unsigned dest_length); + +struct export_item +{ + const char* name; + const void* func; +}; + +typedef void* (__stdcall *img_decode_t)(const void* data, unsigned len, void* parameters); +typedef void (__stdcall *img_to_rgb2_t)(const void* image, void* destination); +typedef void (__stdcall *img_destroy_t)(void* image); +typedef void (__stdcall *img_lib_init_t)(void); // really fastcall with 4 args, but called from asm code + +img_lib_init_t img_lib_init = NULL; +img_decode_t img_decode = NULL; +img_to_rgb2_t img_to_rgb2 = NULL; +img_destroy_t img_destroy = NULL; + +export_item* libini_exports = NULL; +static const char libini_name[] = "/sys/lib/libimg.obj"; + +extern "C" int strcmp(const char* str1, const char* str2); +#pragma intrinsic(strcmp) + +void jpeg_decompress( + const void* source, + unsigned source_length, + void* destination, + unsigned dest_length) +{ + if (!libini_exports) + { + __asm + { + mov eax, 68 + mov ebx, 19 + mov ecx, offset libini_name + int 40h + mov [libini_exports], eax + } + if (!libini_exports) + { + rtlDebugOutString("Cannot load libimg.obj"); + kos_ExitApp(); + } + for (export_item* p = libini_exports; p->name; p++) + { + if (!strcmp(p->name,"lib_init")) + img_lib_init = (img_lib_init_t)p->func; + else if (!strcmp(p->name,"img_decode")) + img_decode = (img_decode_t)p->func; + else if (!strcmp(p->name,"img_to_rgb2")) + img_to_rgb2 = (img_to_rgb2_t)p->func; + else if (!strcmp(p->name,"img_destroy")) + img_destroy = (img_destroy_t)p->func; + } + if (!img_lib_init || !img_decode || !img_to_rgb2 || !img_destroy) + { + rtlDebugOutString("Required exports were not found in libimg.obj"); + kos_ExitApp(); + } + __asm + { + mov eax, offset kos_malloc + mov ebx, offset kos_free + mov ecx, offset kos_realloc + call img_lib_init + } + } + void* image = img_decode(source, source_length, NULL); + if (!image) + { + rtlDebugOutString("JPEG error"); + kos_ExitApp(); + } + img_to_rgb2(image, destination); + img_destroy(image); +} + +////// CKosBitmap + +CKosBitmap::CKosBitmap() +{ + this->bmpID = -1; + this->buffer = NULL; + this->sizeX = 0; + this->sizeY = 0; +} + + +CKosBitmap::~CKosBitmap() +{ + if ( this->buffer != NULL ) delete this->buffer; +} + + +// § Јаг§Є  Ё§ б¦ в®Ј® д ©«  +bool CKosBitmap::LoadFromArch( SCompBmpHeader *bmpArchDesc, CKosFile *fromFile, int ID ) +{ + Byte *tmpBuff; + + // + if ( this->buffer != NULL ) + { + delete this->buffer; + this->buffer = NULL; + } + // + this->buffer = new RGB[bmpArchDesc->sizeX * bmpArchDesc->sizeY]; + // + tmpBuff = new Byte[bmpArchDesc->compressedSize]; + // + fromFile->Seek( SEEK_SET, bmpArchDesc->physicalOffset ); + if ( fromFile->Read( tmpBuff, bmpArchDesc->compressedSize ) == bmpArchDesc->compressedSize ) + { + // + if ( bmpArchDesc->compressedSize == bmpArchDesc->uncompressedSize+1) + { + // JPEG image + jpeg_decompress( tmpBuff, bmpArchDesc->compressedSize, + this->buffer, bmpArchDesc->sizeX * bmpArchDesc->sizeY * 3); + } + else if ( bmpArchDesc->compressedSize != bmpArchDesc->uncompressedSize ) + { + // LZMA-packed BMP + lzma_decompress( tmpBuff, this->buffer, bmpArchDesc->uncompressedSize); + } + else + { + // + memcpy( (Byte *)(this->buffer), tmpBuff, bmpArchDesc->compressedSize ); + } + // + this->sizeX = bmpArchDesc->sizeX; + this->sizeY = bmpArchDesc->sizeY; + this->bmpID = ID; + } + // + delete tmpBuff; + // + return true; +} + + +// ўлўҐбвЁ ў ®Є­® Є авЁ­Єг +void CKosBitmap::Draw( Word x, Word y ) +{ + // + if ( this->buffer != NULL ) + // + kos_PutImage( this->buffer, this->sizeX, this->sizeY, x, y ); +} + + +// Ї®«гзЁвм гЄ § вҐ«м ­  ®Ў« бвм ¤ ­­ле +RGB * CKosBitmap::GetBits() +{ + return this->buffer; +} + + +// Ї®«гзЁвм а §¬Ґа Є авЁ­ЄЁ +void CKosBitmap::GetSize( Word &cx, Word &cy ) +{ + cx = this->sizeX; + cy = this->sizeY; +} + +// ᮧ¤ вм Є авЁ­Єг Ё§ Ў®«м襩 +void CKosBitmap::Scale(Word size, RGB *mainBits) +{ + buffer = new RGB[(sizeX=blockSize)*(sizeY=blockSize*11)]; + memset((Byte*)buffer,0,3*blockSize*blockSize*11); + RGB* tmpBuf = new RGB[blockSize*size]; + for (int k=0;k<11;k++) + { + int delta = (blockSize - size)/2; + int i,j; + int a; + int d1 = blockSize/size; + int d2 = (blockSize-d1*(size))*256/size; + // бЈ« ¦Ёў ­ЁҐ Ї® Ј®аЁ§®­в «Ё + RGB* ptrBuf = tmpBuf; + for (j=0;jb = srcBits->b + (srcBits[1].b-srcBits[0].b)*a/256; + ptrBuf->g = srcBits->g + (srcBits[1].g-srcBits[0].g)*a/256; + ptrBuf->r = srcBits->r + (srcBits[1].r-srcBits[0].r)*a/256; + ptrBuf++; + srcBits += d1; + a += d2; + if (a >= 256) + { + a -= 256; + srcBits++; + } + } + } + // бЈ« ¦Ёў ­ЁҐ Ї® ўҐавЁЄ «Ё + for (j=0;jb = srcBits->b + (srcBits[size].b-srcBits[0].b)*a/256; + ptrBuf->g = srcBits->g + (srcBits[size].g-srcBits[0].g)*a/256; + ptrBuf->r = srcBits->r + (srcBits[size].r-srcBits[0].r)*a/256; + ptrBuf += blockSize; + srcBits += d1*size; + a += d2; + if (a >= 256) + { + a -= 256; + srcBits += size; + } + } + } + } + delete tmpBuf; +} + + +////////////////////// CFishka /////////////////////// + +CFishka::CFishka( CKosBitmap *fromBmp, int yOffset, RGB insColour ) +{ + int i, c; + + // + this->bits = fromBmp->GetBits() + (yOffset * blockSize); + this->transColour = insColour; + // + this->highLighted = new RGB[blockSize * blockSize]; + // + for ( i = 0; i < (blockSize * blockSize); i++ ) + { + // + this->highLighted[i] = this->bits[i]; + // + if ( this->highLighted[i] != this->transColour ) + { + c = ( this->highLighted[i].b * 185 ) / 100; + this->highLighted[i].b = (c > 255) ? 255 : c; + c = ( this->highLighted[i].g * 185 ) / 100; + this->highLighted[i].g = (c > 255) ? 255 : c; + c = ( this->highLighted[i].r * 185 ) / 100; + this->highLighted[i].r = (c > 255) ? 255 : c; + } + } +} + +// +CFishka::~CFishka() +{ + // + delete this->highLighted; +} + + +// +RGB * CFishka::GetBits() +{ + return this->bits; +} + +// +RGB * CFishka::GetHighlightedBits() +{ + return this->highLighted; +} + diff --git a/programs/games/fara/trunk/gfxdef.h b/programs/games/fara/trunk/gfxdef.h new file mode 100644 index 0000000000..06aea424ab --- /dev/null +++ b/programs/games/fara/trunk/gfxdef.h @@ -0,0 +1,101 @@ +// gfxdef.h + +#define MAIN_FACE_NDX 0 +#define GAME_FACE_NDX 1 +#define BUTTONS_NDX 2 +#define NUMBERS_NDX 3 + +#define BONUS_FREE_BLOCK 11 +#define BONUS_DIAG_BLOCK 12 + +#define WNDLEFT 64 +#define WNDTOP 64 +#define WNDHEADCOLOUR 0xD4C233 +#define WNDTITLECOLOUR 0x47151C + +// +#define blockSize 41 +#define blocksNum 15 + +extern int maxGameLevel; +extern int startGameLevel; + +#define START_LEVEL 1 + +//// +//struct CPoint +//{ +// int x, y; +// // +// CPoint() +// { +// this->x = 0; +// this->y = 0; +// }; +// // +// CPoint( int iX, int iY ) +// { +// this->x = iX; +// this->y = iY; +// }; +// // +// CPoint( CPoint &pt ) +// { +// this->x = pt.x; +// this->y = pt.y; +// }; +//}; + + +// описание сжатого битмапа в файле +struct SCompBmpHeader +{ + short int sizeX; + short int sizeY; + int compressedSize; + int physicalOffset; + int uncompressedSize; +}; + + +// сласс битмапа для использования в программе +class CKosBitmap +{ +protected: + int bmpID; + RGB *buffer; + Word sizeX; + Word sizeY; +public: + CKosBitmap(); + ~CKosBitmap(); + // загрузка из сжатого файла + bool LoadFromArch( SCompBmpHeader *bmpArchDesc, CKosFile *fromFile, int ID ); + // вывести в окно картинку + void Draw( Word x, Word y ); + // получить указатель на область данных + RGB *GetBits(); + // получить размер картинки + void GetSize( Word &cx, Word &cy ); + // создать картинку по картинке большего размера + void Scale(Word size, RGB* mainBits); +}; + + +// класс фишки игрового поля +class CFishka +{ +protected: + // + RGB *bits; + // + RGB transColour; + // + RGB *highLighted; +public: + CFishka( CKosBitmap *fromBmp, int yOffset, RGB insColour ); + virtual ~CFishka(); + virtual RGB * GetBits(void); + virtual RGB * GetHighlightedBits(void); +}; + diff --git a/programs/games/fara/trunk/gmplace.bmp b/programs/games/fara/trunk/gmplace.bmp new file mode 100644 index 0000000000000000000000000000000000000000..be7ea65b433df585ade828f2757dceb01a22b868 GIT binary patch literal 615550 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%0DpHzHwEf;Me>0SS_V@myXaAcD{PA(g^EyyLDF=Eu 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
  • J^|sf~kl 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

    {Vdh~KGsttn$Vuh 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 z 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 <$&`qw8;q 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 I5niYN*>cH!+5i9m literal 0 HcmV?d00001 diff --git a/programs/games/fara/trunk/grobfar.txt b/programs/games/fara/trunk/grobfar.txt new file mode 100644 index 0000000000..7dc44c8500 --- /dev/null +++ b/programs/games/fara/trunk/grobfar.txt @@ -0,0 +1,31 @@ + ГРОБНИЦА ФАРАОНА + + +Смысл игры состоит в том, чтобы, перемещая иероглифы на входе в очередную комнату гробницы фараона (8Х8), открыть проход. + +Вы можете менять местами два иероглифа расположенных рядом по вертикали или горизонтали в случае, если при такой перестановке образуется комбинация из трех или более одинаковых картинок в ряд. Такие ряды тут же исчезают, а свободное место заполняется иероглифами "осыпавшимися" сверху. Недостающие иероглифы генерируются случайным образом. + +За исчезающие иероглифы начисляются очки. За комбинацию из иероглифов даются очки по формуле L+(L+1)^(N-3), но не более 20*L*N, где N - число иероглифов в комбинации, а L - номер уровня. + +Для того, чтобы перейти с одного уровня на другой, необходимо убрать определённое число иероглифов (на каждом уровне разное). Снизу от панели с иероглифами расположена полоска, отмечающая сколько пройдено и сколько осталось иероглифов. + +1-й уровень - 500 +2-й уровень - 450 +3-й уровень - 400 +4-й уровень - 350 +5-й уровень - 300 +6-й и далее - 50*(L+1) + + +На первом уровне комбинации составляются из 6 видов иероглифов. С каждым новым уровнем в комбинациях начинает участвовать один новый иероглиф, но всего не более 10 (т.е. начиная с 5-го уровня и далее в игре будет 10 разных иероглифов, не учитывая специальных). + +Начиная со 2-го уровня за каждую комбинацию из 4-х и более иероглифов, а также за прохождение каждой четверти уровня игрок получает "свободный" иероглиф - это обычный иероглиф (сгенерированный случайным образом), который хранится у игрока "в кармане" и при необходимости может быть вставлен игроком на любое место, заменив тем самым расположенный там иероглиф. + +Начиная с 3-го уровня за каждую комбинацию из 5-ти и более иероглифов, а также за прохождение каждой трети уровня игрок получает "универсальный ключ" , подходящий к любой комбинации иероглифов и к нескольким разным комбинациям одновременно. + +Начиная с 4-го уровня за каждую комбинацию из 6-ти и более иероглифов, а также за прохождение половины уровня игрок получает "искривитель пространства" , позволяющий, при его применении, сделать 3 хода (не обязательно подряд) по диагонали. + +У игрока не может быть одновременно более 1 дополнительного иероглифа каждого типа (1 простой, 1 джокер и 1 искривитель). + +Игра заканчивается, если игрок не может составить ни одной комбинации имеющимися у него в распоряжении иероглифами. + diff --git a/programs/games/fara/trunk/kosSyst.cpp b/programs/games/fara/trunk/kosSyst.cpp new file mode 100644 index 0000000000..3f388ddb18 --- /dev/null +++ b/programs/games/fara/trunk/kosSyst.cpp @@ -0,0 +1,870 @@ +#include "kosSyst.h" +#include + +#define atexitBufferSize 32 + + +char pureCallMessage[] = "PURE function call!"; + +char *kosExePath = NULL; + +// +void (__cdecl *atExitList[atexitBufferSize])(); +int atExitFnNum = 0; +// +int __cdecl atexit( void (__cdecl *func )( void )) +{ + // + if ( atExitFnNum < atexitBufferSize ) + { + // + atExitList[atExitFnNum++] = func; + return 0; + } + else + { + return 1; + } +} + + +// +Dword RandomSeed = 1; +// +void rtlSrand( Dword seed ) +{ + RandomSeed = seed; +} +// +Dword rtlRand( void ) +{ + //маска 0x80000776 + + Dword dwi, i; + + for ( i = 0; i < 32; i++ ) + { + + dwi = RandomSeed & 0x80000776; + + __asm{ + mov eax, dwi + mov edx, eax + bswap eax + xor eax, edx + xor al, ah + setpo al + movzx eax, al + mov dwi, eax + } + + RandomSeed = ( RandomSeed << 1 ) | ( dwi & 1 ); + } + + return RandomSeed; +} + +// +void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ) +{ + __asm{ + mov edi, dst + mov eax, dst + mov esi, src + mov ecx, bytesCount + rep movsb + } +} + +// +void memset( Byte *dst, Byte filler, Dword count ) +{ + // + __asm{ + mov edi, dst + mov al, filler + mov ecx, count + rep stosb + } +} + +// +Dword rtlInterlockedExchange( Dword *target, Dword value ) +{ +// Dword result; + + // + __asm{ + mov eax, value + mov ebx, target + xchg eax, [ebx] +// mov result, eax + } + // +// return result; +} + + +////////////////////////////////////////////////////////////////////// +// +// копирование строки +// + +char * __cdecl strcpy( char *target, const char *source ) +{ + char *result = target; + + while( target[0] = source[0] ) + { + target++; + source++; + } + + return result; +} + + +////////////////////////////////////////////////////////////////////// +// +// реверсивный поиск символа +// + +char * __cdecl strrchr( const char * string, int c ) +{ + char *cPtr; + + // + for ( cPtr = (char *)string + strlen( string ); cPtr >= string; cPtr-- ) + { + // + if ( *cPtr == c ) return cPtr; + } + // + return NULL; +} + + +////////////////////////////////////////////////////////////////////// +// +// определение длины строки +// + +int __cdecl strlen( const char *line ) +{ + int i; + + for( i=0; line[i] != 0; i++ ); + return i; +} + + + +////////////////////////////////////////////////////////////////////// +// +// перевод шестнадцатиричного числа в символ +// + +unsigned int num2hex( unsigned int num ) +{ + if( num < 10 ) + return num + '0'; + return num - 10 + 'A'; +} + + +////////////////////////////////////////////////////////////////////// +// +// вывод строки на печать +// + +Dword dectab[] = { 1000000000, 100000000, 10000000, 1000000, 100000, + 10000, 1000, 100, 10, 0 }; + +// +void sprintf( char *Str, char* Format, ... ) +{ + int i, fmtlinesize, j, k, flag; + Dword head, tail; + char c; + va_list arglist; + // + va_start(arglist, Format); + + // + fmtlinesize = strlen( Format ); + // + if( fmtlinesize == 0 ) return; + + // + for( i = 0, j = 0; i < fmtlinesize; i++ ) + { + // + c = Format[i]; + // + if( c != '%' ) + { + Str[j++] = c; + continue; + } + // + i++; + // + if( i >= fmtlinesize ) break; + + // + flag = 0; + // + c = Format[i]; + // + switch( c ) + { + // + case '%': + Str[j++] = c; + break; + // вывод строки + case 'S': + Byte* str; + str = va_arg(arglist, Byte*); + for( k = 0; ( c = str[k] ) != 0; k++ ) + { + Str[j++] = c; + } + break; + // вывод байта + case 'B': + k = va_arg(arglist, int) & 0xFF; + Str[j++] = num2hex( ( k >> 4 ) & 0xF ); + Str[j++] = num2hex( k & 0xF ); + break; + // вывод символа + case 'C': + Str[j++] = va_arg(arglist, int) & 0xFF; + break; + // вывод двойного слова в шестнадцатиричном виде + case 'X': + Dword val; + val = va_arg(arglist, Dword); + for( k = 7; k >= 0; k-- ) + { + // + c = num2hex ( ( val >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + if( flag == 0 ) Str[j++] = '0'; + break; + // вывод двойного слова в десятичном виде + case 'U': + head = va_arg(arglist, Dword); + tail = 0; + for( k = 0; dectab[k] != 0; k++ ) + { + tail = head % dectab[k]; + head /= dectab[k]; + c = head + '0'; + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + // + head = tail; + } + // + c = head + '0'; + Str[j++] = c; + break; + // вывод 64-битного слова в шестнадцатиричном виде + case 'Q': + unsigned int low_dword, high_dword; + low_dword = va_arg(arglist, unsigned int); + high_dword = va_arg(arglist, unsigned int); + for( k = 7; k >= 0; k-- ) + { + // + c = num2hex ( ( ( high_dword + 1) >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + for( k=7; k >= 0; k-- ) + { + // + c = num2hex ( ( low_dword >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + if( flag == 0 ) Str[j++] = '0'; + // + break; + // + default: + break; + } + } + // + Str[j] = 0; +} + + +// функция -1 завершения процесса +void kos_ExitApp() +{ + int i; + + // + for ( i = atExitFnNum - 1; i >= 0; i-- ) + { + // + atExitList[i](); + } + // + __asm{ + mov eax, -1 + int 0x40 + } +} + + +// функция 0 +void kos_DefineAndDrawWindow( + Word x, Word y, + Word sizeX, Word sizeY, + Byte mainAreaType, + Dword mainAreaColour, + Byte headerType, + Dword headerColour, + Dword borderColour + ) +{ + Dword arg1, arg2, arg3, arg4; + + // + arg1 = ( x << 16 ) + sizeX; + arg2 = ( y << 16 ) + sizeY; + arg3 = ( mainAreaType << 24 ) | mainAreaColour; + arg4 = ( headerType << 24 ) | headerColour; + // + __asm{ + mov eax, 0 + mov ebx, arg1 + mov ecx, arg2 + mov edx, arg3 + mov esi, arg4 + mov edi, borderColour + int 0x40 + } +} + + +// функция 1 поставить точку +void kos_PutPixel( Dword x, Dword y, Dword colour ) +{ + // + __asm{ + mov eax, 1 + mov ebx, x + mov ecx, y + mov edx, colour + int 0x40 + } +} + + +// функция 2 получить код нажатой клавиши +bool kos_GetKey( Byte &keyCode ) +{ + Dword result; + + // + __asm{ + mov eax, 2 + int 0x40 + mov result, eax + } + // + keyCode = result >> 8; + // + return ( result & 0xFF ) == 0; +} + + +// функция 3 получить время +Dword kos_GetSystemClock() +{ +// Dword result; + + // + __asm{ + mov eax, 3 + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 4 +void kos_WriteTextToWindow( + Word x, + Word y, + Byte fontType, + Dword textColour, + char *textPtr, + Dword textLen + ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | y; + arg2 = ( fontType << 24 ) | textColour; + // + __asm{ + mov eax, 4 + mov ebx, arg1 + mov ecx, arg2 + mov edx, textPtr + mov esi, textLen + int 0x40 + } +} + + +// функция 5 пауза, в сотых долях секунды +void kos_Pause( Dword value ) +{ + // + __asm{ + mov eax, 5 + mov ebx, value + int 0x40 + } +} + + +// функция 7 нарисовать изображение +void kos_PutImage( RGB * imagePtr, Word sizeX, Word sizeY, Word x, Word y ) +{ + Dword arg1, arg2; + + // + arg1 = ( sizeX << 16 ) | sizeY; + arg2 = ( x << 16 ) | y; + // + __asm{ + mov eax, 7 + mov ebx, imagePtr + mov ecx, arg1 + mov edx, arg2 + int 0x40 + } +} + + + +// функция 8 определить кнопку +void kos_DefineButton( Word x, Word y, Word sizeX, Word sizeY, Dword buttonID, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | sizeX; + arg2 = ( y << 16 ) | sizeY; + // + __asm{ + mov eax, 8 + mov ebx, arg1 + mov ecx, arg2 + mov edx, buttonID + mov esi, colour + int 0x40 + } +} + + +// функция 9 - информация о процессе +Dword kos_ProcessInfo( sProcessInfo *targetPtr, Dword processID ) +{ +// Dword result; + + // + __asm{ + mov eax, 9 + mov ebx, targetPtr + mov ecx, processID + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 10 +Dword kos_WaitForEvent() +{ +// Dword result; + + __asm{ + mov eax, 10 + int 0x40 +// mov result, eax + } + +// return result; +} + + +// функция 11 +Dword kos_CheckForEvent() +{ +// Dword result; + + __asm{ + mov eax, 11 + int 0x40 +// mov result, eax + } + +// return result; +} + + +// функция 12 +void kos_WindowRedrawStatus( Dword status ) +{ + __asm{ + mov eax, 12 + mov ebx, status + int 0x40 + } +} + + +// функция 13 нарисовать полосу +void kos_DrawBar( Word x, Word y, Word sizeX, Word sizeY, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | sizeX; + arg2 = ( y << 16 ) | sizeY; + // + __asm{ + mov eax, 13 + mov ebx, arg1 + mov ecx, arg2 + mov edx, colour + int 0x40 + } +} + + +// функция 17 +bool kos_GetButtonID( Dword &buttonID ) +{ + Dword result; + + // + __asm{ + mov eax, 17 + int 0x40 + mov result, eax + } + // + buttonID = result >> 8; + // + return (result & 0xFF) == 0; +} + + +// функция 23 +Dword kos_WaitForEvent( Dword timeOut ) +{ +// Dword result; + + __asm{ + mov eax, 23 + mov ebx, timeOut + int 0x40 +// mov result, eax + } + +// return result; +} + + +// получение информации о состоянии "мыши" функция 37 +void kos_GetMouseState( Dword & buttons, int & cursorX, int & cursorY ) +{ + Dword mB; + Word curX; + Word curY; + sProcessInfo sPI; + + // + __asm{ + mov eax, 37 + mov ebx, 0 + int 0x40 + mov curY, ax + shr eax, 16 + mov curX, ax + mov eax, 37 + mov ebx, 2 + int 0x40 + mov mB, eax + } + // + kos_ProcessInfo( &sPI ); + // + buttons = mB; + cursorX = curX - sPI.processInfo.x_start; + cursorY = curY - sPI.processInfo.y_start; +} + + +// функция 40 установить маску событий +void kos_SetMaskForEvents( Dword mask ) +{ + // + __asm{ + mov eax, 40 + mov ebx, mask + int 0x40 + } +} + + +// функция 47 вывести в окно приложения число +void kos_DisplayNumberToWindow( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + eNumberBase nBase, + bool valueIsPointer + ) +{ + Dword arg1, arg2; + + // + arg1 = ( valueIsPointer ? 1 : 0 ) | + ( ((Byte)nBase) << 8 ) | + ( ( digitsNum & 0x1F ) << 16 ); + arg2 = ( x << 16 ) | y; + // + __asm{ + mov eax, 47 + mov ebx, arg1 + mov ecx, value + mov edx, arg2 + mov esi, colour + int 0x40 + } +} + + +// функция 70 доступ к файловой системе +Dword kos_FileSystemAccess( kosFileInfo *fileInfo ) +{ +// Dword result; + + // + __asm{ + mov eax, 70 + mov ebx, fileInfo + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 63 вывод символя в окно отладки +void kos_DebugOutChar( char ccc ) +{ + // + __asm{ + mov eax, 63 + mov ebx, 1 + mov cl, ccc + int 0x40 + } +} + + +// функция 66 режим получения данных от клавиатуры +void kos_SetKeyboardDataMode( Dword mode ) +{ + // + __asm{ + mov eax, 66 + mov ebx, 1 + mov ecx, mode + int 0x40 + } +} + + +// вывод строки в окно отладки +void rtlDebugOutString( char *str ) +{ + // + for ( ; str[0] != 0; str++ ) + { + kos_DebugOutChar( str[0] ); + } + // + kos_DebugOutChar( 13 ); + kos_DebugOutChar( 10 ); +} + + +// выделение-освобождение-перераспределение блоков памяти +__declspec(naked) void* __stdcall kos_malloc(Dword size) +{ + __asm + { + push ebx + push ecx + mov ecx, [esp+12] + mov eax, 68 + mov ebx, 12 + int 0x40 + pop ecx + pop ebx + ret 4 + } +} +__declspec(naked) void __stdcall kos_free(void* mptr) +{ + __asm + { + push ebx + push ecx + mov ecx, [esp+12] + mov eax, 68 + mov ebx, 13 + int 0x40 + pop ecx + pop ebx + ret 4 + } +} +__declspec(naked) void* __stdcall kos_realloc(void* mptr, Dword size) +{ + __asm + { + push ebx + push ecx + push edx + mov eax, 68 + mov ebx, 20 + mov ecx, [esp+20] + mov edx, [esp+16] + int 0x40 + pop edx + pop ecx + pop ebx + ret 8 + } +} + +// функция 67 изменить параметры окна, параметр == -1 не меняется +void kos_ChangeWindow( Dword x, Dword y, Dword sizeX, Dword sizeY ) +{ + // + __asm{ + mov eax, 67 + mov ebx, x + mov ecx, y + mov edx, sizeX + mov esi, sizeY + int 0x40 + } +} + + + +// вызов абстрактного метода +int __cdecl _purecall() +{ + rtlDebugOutString( pureCallMessage ); + kos_ExitApp(); + return 0; +} + + +// вызов статических инициализаторов +// заодно инициализация генератора случайных чисел +#pragma section(".CRT$XCA",long,read,write) +#pragma section(".CRT$XCZ",long,read,write) +typedef void (__cdecl *_PVFV)(void); +__declspec(allocate(".CRT$XCA")) _PVFV __xc_a[1] = { NULL }; +__declspec(allocate(".CRT$XCZ")) _PVFV __xc_z[1] = { NULL }; +// +#pragma comment(linker, "/merge:.CRT=.rdata") +// +void crtStartUp() +{ + // инициализируем кучу + __asm + { + mov eax, 68 + mov ebx, 11 + int 40h + } + // вызываем инициализаторы по списку, NULL'ы игнорируем + for ( _PVFV *pbegin = __xc_a; pbegin < __xc_z; pbegin++ ) + { + // + if ( *pbegin != NULL ) + (**pbegin)(); + } + // инициализируем генератор случайных чисел + rtlSrand( kos_GetSystemClock() ); + // путь к файлу процесса + kosExePath = *((char **)0x20); + // вызов главной функции приложения + kos_Main(); + // выход + kos_ExitApp(); +} + + diff --git a/programs/games/fara/trunk/kosSyst.h b/programs/games/fara/trunk/kosSyst.h new file mode 100644 index 0000000000..7c8323dcdb --- /dev/null +++ b/programs/games/fara/trunk/kosSyst.h @@ -0,0 +1,197 @@ +typedef unsigned __int32 Dword; +typedef unsigned __int16 Word; +typedef unsigned __int8 Byte; +typedef unsigned __int32 size_t; + +#define NULL 0 + +#define MAX_PATH 256 + +#define FO_READ 0 +#define FO_WRITE 2 + +#define EM_WINDOW_REDRAW 1 +#define EM_KEY_PRESS 2 +#define EM_BUTTON_CLICK 4 +#define EM_APP_CLOSE 8 +#define EM_DRAW_BACKGROUND 16 +#define EM_MOUSE_EVENT 32 +#define EM_IPC 64 +#define EM_NETWORK 256 + +#define KM_CHARS 0 +#define KM_SCANS 1 + +#define WRS_BEGIN 1 +#define WRS_END 2 + +#define PROCESS_ID_SELF -1 + +#define abs(a) (a<0?0-a:a) + + +struct kosFileInfo +{ + Dword rwMode; + Dword OffsetLow; + Dword OffsetHigh; + Dword dataCount; + Byte *bufferPtr; + char fileURL[MAX_PATH]; +}; + + +struct RGB +{ + Byte b; + Byte g; + Byte r; + // + RGB() {}; + // + RGB( Dword value ) + { + r = value >> 16; + g = value >> 8; + b = value; + }; + // + bool operator != ( RGB &another ) + { + return this->b != another.b || this->g != another.g || this->r != another.r; + }; + // + bool operator == ( RGB &another ) + { + return this->b == another.b && this->g == another.g && this->r == another.r; + }; +}; + + +union sProcessInfo +{ + Byte rawData[1024]; + struct + { + Dword cpu_usage; + Word window_stack_position; + Word window_stack_value; + Word reserved1; + char process_name[12]; + Dword memory_start; + Dword used_memory; + Dword PID; + Dword x_start; + Dword y_start; + Dword x_size; + Dword y_size; + Word slot_state; + } processInfo; +}; + +// +extern char *kosExePath; + +// +void crtStartUp(); +// +int __cdecl _purecall(); +// +int __cdecl atexit( void (__cdecl *func )( void )); +// +void rtlSrand( Dword seed ); +Dword rtlRand( void ); +// +char * __cdecl strcpy( char *target, const char *source ); +int __cdecl strlen( const char *line ); +char * __cdecl strrchr( const char * string, int c ); +// +void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ); +// +void memset( Byte *dst, Byte filler, Dword count ); +// +void sprintf( char *Str, char* Format, ... ); +// +Dword rtlInterlockedExchange( Dword *target, Dword value ); +// функция -1 завершения процесса +void kos_ExitApp(); +// функция 0 +void kos_DefineAndDrawWindow( + Word x, Word y, + Word sizeX, Word sizeY, + Byte mainAreaType, Dword mainAreaColour, + Byte headerType, Dword headerColour, + Dword borderColour + ); +// функция 1 поставить точку +void kos_PutPixel( Dword x, Dword y, Dword colour ); +// функция 2 получить код нажатой клавиши +bool kos_GetKey( Byte &keyCode ); +// функция 3 получить время +Dword kos_GetSystemClock(); +// функция 4 +void kos_WriteTextToWindow( + Word x, Word y, + Byte fontType, + Dword textColour, + char *textPtr, + Dword textLen + ); +// функция 7 нарисовать изображение +void kos_PutImage( RGB * imagePtr, Word sizeX, Word sizeY, Word x, Word y ); +// функция 8 определить кнопку +void kos_DefineButton( Word x, Word y, Word sizeX, Word sizeY, Dword buttonID, Dword colour ); +// функция 5 пауза, в сотых долях секунды +void kos_Pause( Dword value ); +// функция 9 - информация о процессе +Dword kos_ProcessInfo( sProcessInfo *targetPtr, Dword processID = PROCESS_ID_SELF ); +// функция 10 +Dword kos_WaitForEvent(); +// функция 11 +Dword kos_CheckForEvent(); +// функция 12 +void kos_WindowRedrawStatus( Dword status ); +// функция 13 нарисовать полосу +void kos_DrawBar( Word x, Word y, Word sizeX, Word sizeY, Dword colour ); +// функция 17 +bool kos_GetButtonID( Dword &buttonID ); +// функция 23 +Dword kos_WaitForEvent( Dword timeOut ); +// +enum eNumberBase +{ + nbDecimal = 0, + nbHex, + nbBin +}; +// получение информации о состоянии "мыши" функция 37 +void kos_GetMouseState( Dword & buttons, int & cursorX, int & cursorY ); +// функция 40 установить маску событий +void kos_SetMaskForEvents( Dword mask ); +// функция 47 вывести в окно приложения число +void kos_DisplayNumberToWindow( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + eNumberBase nBase = nbDecimal, + bool valueIsPointer = false + ); +// функция 58 доступ к файловой системе +Dword kos_FileSystemAccess( kosFileInfo *fileInfo ); +// функция 63 +void kos_DebugOutChar( char ccc ); +// +void rtlDebugOutString( char *str ); +// функция 64 изменить параметры окна, параметр == -1 не меняется +void kos_ChangeWindow( Dword x, Dword y, Dword sizeX, Dword sizeY ); +// 68.12/13/20 +void* __stdcall kos_malloc(Dword size); +void __stdcall kos_free(void* mptr); +void* __stdcall kos_realloc(void* mptr, Dword size); +// функция 66 режим получения данных от клавиатуры +void kos_SetKeyboardDataMode( Dword mode ); + +// +void kos_Main(); diff --git a/programs/games/fara/trunk/lang.h b/programs/games/fara/trunk/lang.h new file mode 100644 index 0000000000..ef15793f1a --- /dev/null +++ b/programs/games/fara/trunk/lang.h @@ -0,0 +1,3 @@ +#define RUS 1 +#define ENG 2 +#define LANG RUS \ No newline at end of file diff --git a/programs/games/fara/trunk/lzma_unpack.asm b/programs/games/fara/trunk/lzma_unpack.asm new file mode 100644 index 0000000000..e0ec3e102e --- /dev/null +++ b/programs/games/fara/trunk/lzma_unpack.asm @@ -0,0 +1,393 @@ +; Exports only one function: +; void __stdcall lzma_decompress( +; const void* source, +; void* destination, +; unsigned dest_length); + + format COFF + +section '.text' code + +pb equ 2 ; pos state bits +lp equ 0 ; literal pos state bits +lc equ 3 ; literal context bits +posStateMask equ ((1 shl pb)-1) +literalPosMask equ ((1 shl lp)-1) + +kNumPosBitsMax = 4 +kNumPosStatesMax = (1 shl kNumPosBitsMax) + +kLenNumLowBits = 3 +kLenNumLowSymbols = (1 shl kLenNumLowBits) +kLenNumMidBits = 3 +kLenNumMidSymbols = (1 shl kLenNumMidBits) +kLenNumHighBits = 8 +kLenNumHighSymbols = (1 shl kLenNumHighBits) + +LenChoice = 0 +LenChoice2 = 1 +LenLow = 2 +LenMid = (LenLow + (kNumPosStatesMax shl kLenNumLowBits)) +LenHigh = (LenMid + (kNumPosStatesMax shl kLenNumMidBits)) +kNumLenProbs = (LenHigh + kLenNumHighSymbols) + +kNumStates = 12 +kNumLitStates = 7 +kStartPosModelIndex = 4 +kEndPosModelIndex = 14 +kNumFullDistances = (1 shl (kEndPosModelIndex/2)) +kNumPosSlotBits = 6 +kNumLenToPosStates = 4 +kNumAlignBits = 4 +kAlignTableSize = (1 shl kNumAlignBits) +kMatchMinLen = 2 + +IsMatch = 0 +IsRep = 0xC0 ; (IsMatch + (kNumStates shl kNumPosBitsMax)) +IsRepG0 = 0xCC ; (IsRep + kNumStates) +IsRepG1 = 0xD8 ; (IsRepG0 + kNumStates) +IsRepG2 = 0xE4 ; (IsRepG1 + kNumStates) +IsRep0Long = 0xF0 ; (IsRepG2 + kNumStates) +PosSlot = 0x1B0 ; (IsRep0Long + (kNumStates shl kNumPosBitsMax)) +SpecPos = 0x2B0 ; (PosSlot + (kNumLenToPosStates shl kNumPosSlotBits)) +Align_ = 0x322 ; (SpecPos + kNumFullDistances - kEndPosModelIndex) +Lencoder = 0x332 ; (Align_ + kAlignTableSize) +RepLencoder = 0x534 ; (Lencoder + kNumLenProbs) +Literal = 0x736 ; (RepLencoder + kNumLenProbs) + +LZMA_BASE_SIZE = 1846 ; must be ==Literal +LZMA_LIT_SIZE = 768 + +kNumTopBits = 24 +kTopValue = (1 shl kNumTopBits) + +kNumBitModelTotalBits = 11 +kBitModelTotal = (1 shl kNumBitModelTotalBits) +kNumMoveBits = 5 + +RangeDecoderBitDecode: +; in: eax->prob +; out: CF=bit + push edx + mov edx, [range] + shr edx, kNumBitModelTotalBits + imul edx, [eax] + cmp [code_], edx + jae .ae + mov [range], edx + mov edx, kBitModelTotal + sub edx, [eax] + shr edx, kNumMoveBits + add [eax], edx +.n: + pushfd + call update_decoder + popfd + pop edx + ret +.ae: + sub [range], edx + sub [code_], edx + mov edx, [eax] + shr edx, kNumMoveBits + sub [eax], edx + stc + jmp .n + +update_decoder: + cmp byte [range+3], 0 ;cmp dword [range], kTopValue + jnz @f ;jae @f + shl dword [range], 8 + shl dword [code_], 8 + push eax + mov eax, [inptr] + mov al, [eax] + inc dword [inptr] + mov byte [code_], al + pop eax +@@: ret + +LzmaLenDecode: +; in: eax->prob, edx=posState +; out: ecx=len + +; LenChoice==0 +; add eax, LenChoice*4 + call RangeDecoderBitDecode + jnc .0 + add eax, (LenChoice2-LenChoice)*4 + call RangeDecoderBitDecode + jc @f + mov cl, kLenNumMidBits + shl edx, cl + lea eax, [eax + (LenMid-LenChoice2)*4 + edx*4] + call RangeDecoderBitTreeDecode + add ecx, kLenNumLowSymbols + ret +@@: + add eax, (LenHigh-LenChoice2)*4 + mov cl, kLenNumHighBits + call RangeDecoderBitTreeDecode + add ecx, kLenNumLowSymbols + kLenNumMidSymbols + ret +.0: + mov cl, kLenNumLowBits + shl edx, cl + lea eax, [eax + LenLow*4 + edx*4] +RangeDecoderBitTreeDecode: +; in: eax->probs,ecx=numLevels +; out: ecx=length; destroys edx + push edi + xor edx, edx + inc edx + mov edi, edx + xchg eax, edi +@@: + push eax + lea eax, [edi+edx*4] + call RangeDecoderBitDecode + pop eax + adc dl, dl + add al, al + loop @b + sub dl, al + pop edi + mov ecx, edx + ret + +; void __stdcall lzma_decompress( +; const void* source, +; void* destination, +; unsigned dest_length); +lzma_decompress equ _lzma_decompress@12 +public lzma_decompress +lzma_decompress: + push esi edi ebx ebp + mov esi, [esp+4*4+4] ; source + xor ebp, ebp + mov edi, code_ + inc esi + lodsd + bswap eax + stosd + xor eax, eax + dec eax + stosd + stosd + stosd + stosd + xchg eax, esi + stosd + mov ecx, Literal + (LZMA_LIT_SIZE shl (lc+lp)) + mov eax, kBitModelTotal/2 + mov edi, p + rep stosd + mov edi, [esp+4*4+8] ; destination + mov ebx, edi + add ebx, [esp+4*4+12] ; dest_length +.main_loop: + cmp edi, ebx + jae .main_loop_done + mov edx, edi + and edx, posStateMask + push eax ; al = previous byte + mov eax, ebp + shl eax, kNumPosBitsMax+2 + lea eax, [p + IsMatch*4 + eax + edx*4] + call RangeDecoderBitDecode + pop eax + jc .1 + movzx eax, al +if literalPosMask + mov ah, dl + and ah, literalPosMask +end if + shr eax, 8-lc + imul eax, LZMA_LIT_SIZE*4 + add eax, p+Literal*4 + mov cl, 1 + cmp ebp, kNumLitStates + jb .literal + mov dl, [edi + esi] +.lx0: + add dl, dl + setc ch + push eax + lea eax, [eax+ecx*4+0x100*4] + call RangeDecoderBitDecode + pop eax + adc cl, cl + jc .lx1 + xor ch, cl + test ch, 1 + mov ch, 0 + jz .lx0 +.literal: +@@: + push eax + lea eax, [eax+ecx*4] + call RangeDecoderBitDecode + pop eax + adc cl, cl + jnc @b +.lx1: + mov eax, ebp + cmp al, 4 + jb @f + cmp al, 10 + mov al, 3 + jb @f + mov al, 6 +@@: sub ebp, eax + xchg eax, ecx +.stosb_main_loop: + stosb + jmp .main_loop +.1: + lea eax, [p + IsRep*4 + ebp*4] + call RangeDecoderBitDecode + jnc .10 + add eax, (IsRepG0 - IsRep)*4 ;lea eax, [p + IsRepG0*4 + ebp*4] + call RangeDecoderBitDecode + jc .111 + mov eax, ebp + shl eax, kNumPosBitsMax+2 + lea eax, [p + IsRep0Long*4 + eax + edx*4] + call RangeDecoderBitDecode + jc .1101 + cmp ebp, 7 + sbb ebp, ebp + lea ebp, [ebp+ebp+11] + mov al, [edi + esi] + jmp .stosb_main_loop +.111: + add eax, (IsRepG1 - IsRepG0) * 4 ;lea eax, [p + IsRepG1*4 + ebp*4] + call RangeDecoderBitDecode + xchg esi, [rep1] + jnc @f + add eax, (IsRepG2 - IsRepG1) * 4 ;lea eax, [p + IsRepG2*4 + ebp*4] + call RangeDecoderBitDecode + xchg esi, [rep2] + jnc @f + xchg esi, [rep3] +@@: +.1101: + mov eax, p + RepLencoder*4 + call LzmaLenDecode + push 8 + jmp .rmu +.10: + xchg esi, [rep1] + xchg esi, [rep2] + mov [rep3], esi + mov eax, p + Lencoder*4 + call LzmaLenDecode + push kNumLenToPosStates-1 + pop eax + cmp eax, ecx + jb @f + mov eax, ecx +@@: + push ecx + push kNumPosSlotBits + pop ecx + shl eax, cl + shl eax, 2 + add eax, p+PosSlot*4 + call RangeDecoderBitTreeDecode + mov esi, ecx + cmp ecx, kStartPosModelIndex + jb .l6 + push ecx + xor eax, eax + inc eax + shr ecx, 1 + adc al, al + dec ecx + shl eax, cl + mov esi, eax + pop edx + cmp edx, kEndPosModelIndex + jae .l5 + sub eax, edx + shl eax, 2 + add eax, p + (SpecPos - 1)*4 + jmp .l59 +.l5: + sub ecx, kNumAlignBits +; call RangeDecoderDecodeDirectBits +;RangeDecoderDecodeDirectBits: + xor eax, eax +.l: + shr dword [range], 1 + add eax, eax + mov edx, [code_] + sub edx, [range] + jb @f + mov [code_], edx + inc eax +@@: + call update_decoder + loop .l +; ret + mov cl, kNumAlignBits + shl eax, cl + add esi, eax + mov eax, p+Align_*4 +.l59: +; call RangeDecoderReverseBitTreeDecode_addesi +;_RangeDecoderReverseBitTreeDecode_addesi: +; in: eax->probs,ecx=numLevels +; out: esi+=length; destroys edx + push edi ecx + xor edx, edx + inc edx + xor edi, edi +@@: + push eax + lea eax, [eax+edx*4] + call RangeDecoderBitDecode + lahf + adc edx, edx + sahf + rcr edi, 1 + pop eax + loop @b + pop ecx + rol edi, cl + add esi, edi + pop edi +; ret +.l6: + pop ecx + not esi + push 7 +.rmu: + cmp ebp, 7 + pop ebp + jb @f + inc ebp + inc ebp + inc ebp +@@: +.repmovsb: + inc ecx + push esi + add esi, edi + rep movsb + lodsb + pop esi + jmp .stosb_main_loop +.main_loop_done: + pop ebp ebx edi esi + ret 12 + +section '.bss' data +p rd LZMA_BASE_SIZE + (LZMA_LIT_SIZE shl (lc+lp)) +code_ dd ? +range dd ? +rep1 dd ? +rep2 dd ? +rep3 dd ? +inptr dd ? +previousByte db ? diff --git a/programs/games/fara/trunk/lzma_unpack.obj b/programs/games/fara/trunk/lzma_unpack.obj new file mode 100644 index 0000000000000000000000000000000000000000..ef8c1f1626ffa0f0576450d83aecb371a029bd04 GIT binary patch literal 1208 zcmYk6TSyd97{|}-&aQ(>yTO`TLS+hVrnsh=V4$I4)Pr`>)zU5VLYsD(F^CXSM$~ax zupacK3tgTvNr}WFaK=qDDA8R|A`ej9mHogF3x>w*gr$!Ux`)XNiIqh7L#eG1U?96wvoj4obwi?|?_I=+uXp_cWg+<3sIO^g|miYma>R`8Fq{|}b zb;0Q9dcJonLj4HB4nRz_(B-I)i;|YLr{ZEVW(?v}1|exl^l9@Yta$ZM4^iO{tB`{) zHT1~})}50P)T5h%B6}HeC4}G6W=cnH!_A?5XHzQ)jk}57_=b;6e)ngHd4}q|P--jg z2%3eT63%3KE;F=8%WHb{=Aj#p<{F)BH`!i%8AL+4C@14;Ab$J*LS*7RPE4tgGepi z@L3|!S~Es?jWkkV*B5)didUnP_26p)pEN2ivOHg4k+a7AM){D(D-D;3OB;l6^B57n z3`J-zRrIqKc|4IE14eeJ=OjTrGkl1ouCnmxN+95y?qxk*X1Ko* zaNgbMzB4{!^?fV$yk=Hy#eXO4A<%j$ug%TP%`RkC7al$?^D9tO=}BAJV7U74fDJ@? zWPoRoA}OU%+D9pmQUN6^B^#w`N;Q-wDgC0f8IlI`?xEC7=>er-N)wbmQu<8kH>G7t za2>4W&{K+~beNKr(rHRnlrB(eq_qB4fpqXa*WVu?Q@=3WKR|ESde)#QAY09~+B3F_ R%Ci@1FY%RvkY!0h{{WwkU>E=Z literal 0 HcmV?d00001 diff --git a/programs/games/fara/trunk/main.cpp b/programs/games/fara/trunk/main.cpp new file mode 100644 index 0000000000..c50b3dad36 --- /dev/null +++ b/programs/games/fara/trunk/main.cpp @@ -0,0 +1,80 @@ +#include "kosSyst.h" +#include "kosFile.h" +#include "gfxdef.h" +#include "mainWnd.h" +#include "gameWnd.h" +#include "top10wnd.h" + + + + +void kos_Main() +{ + int hdrNum, i; + SCompBmpHeader *hdrList; + char *cPtr; + + // отделяем имя модуля от пути + cPtr = strrchr( kosExePath, '/' ); + // проверка ;) +/* if ( cPtr == NULL ) + { + // + rtlDebugOutString( "Invalid path to executable." ); + // + return; + }*/ + // + cPtr[1] = 0; + // + strcpy( top10FilePath, kosExePath ); + // + strcpy( top10FilePath + ((cPtr - kosExePath) + 1), "fara.t10" ); + // + PrepareTop10(); + // прикрутим имя файла с графикой + strcpy( cPtr + 1, "fara.gfx" ); + // загружаем картинки из файла + CKosFile gfxRes( kosExePath ); + + // читаем количество картинок в файле + if ( gfxRes.Read( (Byte *)&hdrNum, sizeof(hdrNum) ) != sizeof(hdrNum) ) return; + // место под заголовки + hdrList = new SCompBmpHeader[hdrNum]; + // считываем заголовки картинок + gfxRes.Read( (Byte *)hdrList, sizeof(SCompBmpHeader) * hdrNum ); + // распаковываем картинки + mainWndFace.LoadFromArch( &(hdrList[MAIN_FACE_NDX]), &gfxRes, MAIN_FACE_NDX ); + gameFace.LoadFromArch( &(hdrList[GAME_FACE_NDX]), &gfxRes, GAME_FACE_NDX ); + gameBlocks.LoadFromArch( &(hdrList[BUTTONS_NDX]), &gfxRes, BUTTONS_NDX ); + gameNumbers.LoadFromArch( &(hdrList[NUMBERS_NDX]), &gfxRes, NUMBERS_NDX ); + // масштабируем иероглифы к меньшим размерам + for ( i = 0; i < 4; i++ ) + gameBlocksZ[i].Scale(32-i*8,gameBlocks.GetBits()); + // + delete hdrList; + // инициализируем блоки + for ( i = 0; i < blocksNum; i++ ) + { + // + fishki[i] = new CFishka( &gameBlocks, i * blockSize, RGB(0x0) ); + } + // + maxGameLevel = START_LEVEL; + // добавляем маску для событий мыши + kos_SetMaskForEvents( 0x27 ); + // + while ( MainWndLoop() == MW_START_GAME ) + { + GameLoop(); + Top10Loop(); + } + // + for ( i = 0; i < blocksNum; i++ ) + { + delete fishki[i]; + } + // + delete hdrList; +} + diff --git a/programs/games/fara/trunk/mainWnd.cpp b/programs/games/fara/trunk/mainWnd.cpp new file mode 100644 index 0000000000..3999cad071 --- /dev/null +++ b/programs/games/fara/trunk/mainWnd.cpp @@ -0,0 +1,211 @@ +#include "kosSyst.h" +#include "KosFile.h" +#include "gfxdef.h" +#include "mainWnd.h" +#include "lang.h" + + +// +RGB bmPMButton[] = { + 0xCCCCCC, 0xCCCCCC, 0x000000, 0x000000, 0xCCCCCC, 0xCCCCCC, + 0xCCCCCC, 0xCCCCCC, 0x000000, 0x000000, 0xCCCCCC, 0xCCCCCC, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0xCCCCCC, 0xCCCCCC, 0x000000, 0x000000, 0xCCCCCC, 0xCCCCCC, + 0xCCCCCC, 0xCCCCCC, 0x000000, 0x000000, 0xCCCCCC, 0xCCCCCC, +}; + + +// +#if LANG == RUS +char mainWndTitle[] = "PHARAON's CRYPT"; +char mainWndCopyright[] = "(C) MMVI by Rabid Rabbit"; +char mainWndMenuStart[] = "1. Ќ з вм ЁЈаг"; +char mainWndMenuExit[] = "2. ‚л室"; +char mainWndMenuLevel[] = "Ќ з «м­л© га®ўҐ­м - %U"; +#else +char mainWndTitle[] = "PHARAON's CRYPT"; +char mainWndCopyright[] = "(C) MMVI by Rabid Rabbit"; +char mainWndMenuStart[] = "1. Start game"; +char mainWndMenuExit[] = "2. Exit"; +char mainWndMenuLevel[] = "Starting level - %U"; +#endif +// +CKosBitmap mainWndFace; +// +Word mcx, mcy; + +#define BT_SIZE_X_MINUS 4 +#define BT_SIZE_X_PLUS 5 + +// +int MainWndLoop() +{ + Byte keyCode; + Dword buttonID; + int result; + static bool firstTime = true; + + // + startGameLevel = maxGameLevel; + // + if ( firstTime ) + { + // + mainWndFace.GetSize( mcx, mcy ); + // + firstTime = false; + // + DrawMainWindow(); + } + // + kos_ChangeWindow( -1, -1, mcx + 1, mcy + 21 ); + // + for ( result = MW_NONE; result == MW_NONE; ) + { + switch( kos_WaitForEvent() ) + { + case 1: + DrawMainWindow(); + break; + + case 2: + if ( kos_GetKey( keyCode ) ) + { + // + switch ( keyCode ) + { + case '1': + result = MW_START_GAME; + break; + + case '2': + result = MW_EXIT_APP; + break; + + default: + break; + } + } + break; + + case 3: + if ( kos_GetButtonID( buttonID ) ) + { + // + switch ( buttonID ) + { + // + case BT_SIZE_X_MINUS: + if ( --startGameLevel < 1 ) + startGameLevel = 1; + else + DrawMainWindow(); + break; + + // + case BT_SIZE_X_PLUS: + if ( ++startGameLevel > maxGameLevel ) + startGameLevel = maxGameLevel; + else + DrawMainWindow(); + break; + + // + default: + break; + } + } + + default: + break; + } + } + // кнопки + kos_DefineButton( + 0, 0, + 0, 0, + BT_SIZE_X_MINUS + 0x80000000, + 0 + ); + // + kos_DefineButton( + 0, 0, + 0, 0, + BT_SIZE_X_PLUS + 0x80000000, + 0 + ); + // + return result; +} + + +// полная отрисовка главного окна программы (1) +void DrawMainWindow() +{ + char line[64]; + + // + kos_WindowRedrawStatus( WRS_BEGIN ); + // окно + kos_DefineAndDrawWindow( + WNDLEFT, WNDTOP, + mcx + 1, mcy + 21, + 0, 0x0, + 0, WNDHEADCOLOUR, + WNDHEADCOLOUR + ); + // заголовок окна + kos_WriteTextToWindow( + 4, 7, + 0x10, WNDTITLECOLOUR, + mainWndTitle, sizeof(mainWndTitle)-1 + ); + // + mainWndFace.Draw( 1, 21 ); + // первая строка + kos_WriteTextToWindow( + 8, 32, + 0, 0x0, + mainWndMenuStart, sizeof(mainWndMenuStart)-1 + ); + // вторая строка + kos_WriteTextToWindow( + 8, 48, + 0, 0x0, + mainWndMenuExit, sizeof(mainWndMenuExit)-1 + ); + // третья строка + sprintf( line, mainWndMenuLevel, startGameLevel); + kos_WriteTextToWindow( + 8, 64, + 0, 0x0, + line, strlen( line ) + ); + // кнопки + kos_DefineButton( + mcx - 29, 64, + 12, 12, + BT_SIZE_X_MINUS, + 0xCCCCCC + ); + // + kos_PutImage( bmPMButton + 12, 6, 2, mcx - 29 + 3, 69 ); + // + kos_DefineButton( + mcx - 16, 64, + 12, 12, + BT_SIZE_X_PLUS, + 0xCCCCCC + ); + // + kos_PutImage( bmPMButton, 6, 6, mcx - 16 + 3, 67 ); + // копирайт + kos_WriteTextToWindow( + 8, mcy - 16 + 21, + 0, 0x000066, + mainWndCopyright, sizeof(mainWndCopyright)-1 + ); + // + kos_WindowRedrawStatus( WRS_END ); +} diff --git a/programs/games/fara/trunk/mainWnd.h b/programs/games/fara/trunk/mainWnd.h new file mode 100644 index 0000000000..13978fc431 --- /dev/null +++ b/programs/games/fara/trunk/mainWnd.h @@ -0,0 +1,13 @@ +// mainWnd.h + +#define MW_NONE 0 +#define MW_EXIT_APP 1 +#define MW_START_GAME 2 + + +// +int MainWndLoop(); +// полная отрисовка главного окна программы (1) +void DrawMainWindow(); +// +extern CKosBitmap mainWndFace; diff --git a/programs/games/fara/trunk/mainfish.bmp b/programs/games/fara/trunk/mainfish.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4b52b4df0719bdde46ae9b43d446561621e4439e GIT binary patch literal 76314 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 literal 0 HcmV?d00001 diff --git a/programs/games/fara/trunk/mcarray.h b/programs/games/fara/trunk/mcarray.h new file mode 100644 index 0000000000..f0d06814e1 --- /dev/null +++ b/programs/games/fara/trunk/mcarray.h @@ -0,0 +1,181 @@ +#define AR_CHUNK_SIZE 64 + +// +template +class MCArray +{ +protected: + TYPE * _dataPtr; + int _elementsCount; + int _capacity; + +public: + MCArray(); + virtual ~MCArray(); + virtual int Add( const TYPE &element ); + virtual int AddExclusive( const TYPE &element ); + virtual TYPE & GetAt( int Ndx ); + virtual TYPE & operator [] ( int Ndx ); + virtual int Find( int startNdx, const TYPE & element ); + virtual int RemoveAt( int Ndx ); + virtual void Clear(void); + virtual int GetCount(void); +}; + +// + + +// +template +MCArray::MCArray() +{ + // устанавливаем переменные + this->_dataPtr = NULL; + this->_capacity = 0; + this->_elementsCount = 0; +} + + +// +template +MCArray::~MCArray() +{ + // + this->_capacity = 0; + this->_elementsCount = 0; + // + if ( this->_dataPtr != NULL ) + { + delete this->_dataPtr; + } +} + + +// +template +int MCArray::AddExclusive( const TYPE &element ) +{ + // + if ( this->Find( 0, element ) < 0 ) + return this->Add( element ); + else + return -1; +} + + +// +template +int MCArray::Add( const TYPE &element ) +{ + TYPE * dPtr; + + // есть ли место? + if ( this->_elementsCount >= this->_capacity ) + { + // занимаем ещё памяти + dPtr = new TYPE [this->_capacity + AR_CHUNK_SIZE]; + // проверка + if ( dPtr == NULL ) + { + // + return -1; + } + + if ( this->_capacity > 0 ) + { + // скопируем существующие данные на новое место + memcpy( dPtr, this->_dataPtr, sizeof(TYPE) * this->_capacity ); + // удалим старую копию данных + delete this->_dataPtr; + } + // скорректируем размер + this->_capacity += AR_CHUNK_SIZE; + // скорректируем указатель на данные + this->_dataPtr = dPtr; + } + + // копируем элемент в массив + this->_dataPtr[this->_elementsCount] = element; + //memcpy( this->_dataPtr + this->_elementsCount, &element, sizeof(TYPE) ); + + // увеличиваем счётчик элементов + return ++this->_elementsCount; +} + + +// +template +TYPE & MCArray::GetAt( int Ndx ) +{ + //assert( Ndx >= 0 && Ndx < this->_elementsCount ); + return this->_dataPtr[Ndx]; +} + + +// +template +TYPE & MCArray::operator [] ( int Ndx ) +{ + return this->GetAt( Ndx ); +} + + +// +template +int MCArray::Find( int startNdx, const TYPE & element ) +{ + int i; + + if ( startNdx < 0 || startNdx >= this->_elementsCount ) + { + return -1; + } + + for ( i = startNdx; i < this->_elementsCount; i++ ) + { + if ( element == this->_dataPtr[i] ) + { + return i; + } + } + + return -1; +} + + +// +template +int MCArray::RemoveAt( int Ndx ) +{ + int mn; + + if ( Ndx < 0 || Ndx >= this->_elementsCount ) + { + return 0; + } + + mn = this->_elementsCount - Ndx; + + if ( mn != 1 ) + { + memcpy( this->_dataPtr + Ndx, this->_dataPtr + Ndx + 1, sizeof(TYPE) * ( mn - 1 ) ); + } + + this->_elementsCount--; + return 1; +} + + +// +template +void MCArray::Clear() +{ + this->_elementsCount = 0; +} + +// +template +int MCArray::GetCount() +{ + return this->_elementsCount; +} diff --git a/programs/games/fara/trunk/mcsmemm.cpp b/programs/games/fara/trunk/mcsmemm.cpp new file mode 100644 index 0000000000..cfc0c4adcc --- /dev/null +++ b/programs/games/fara/trunk/mcsmemm.cpp @@ -0,0 +1,298 @@ +// memman.cpp : Defines the entry point for the console application. +// + +#include "kosSyst.h" +#include "mcsmemm.h" + + +void * __cdecl operator new ( size_t count, size_t element_size ) +{ + return allocmem( (Dword)(count * element_size) ); +} + +void * __cdecl operator new [] ( size_t amount ) +{ + return allocmem( (Dword)amount ); +} + +void * __cdecl operator new ( size_t amount ) +{ + return allocmem( (Dword)amount ); +} + +void __cdecl operator delete ( void *pointer ) +{ + if ( pointer != NULL ) freemem( pointer ); +} + +void __cdecl operator delete [] ( void *pointer ) +{ + if ( pointer != NULL ) freemem( pointer ); +} + + +// +Dword mmMutex = FALSE; +MemBlock *rootfree = NULL; +MemBlock *rootuser = NULL; +bool mmInitialized = false; +Byte *mmHeapTop = NULL; + + +// +Byte *allocmem( Dword reqsize ) +{ + MemBlock *BlockForCheck; + MemBlock *LastKnownGood; + Dword tail; + Byte *address; + + //подровняем размер + if( ( tail = reqsize % SIZE_ALIGN ) != 0 ) + { + reqsize += SIZE_ALIGN - tail; + } + + LastKnownGood = NULL; + + // ждём освобождения мьютекса + while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) + { + // + kos_Pause( 1 ); + } + + //ищем подходящий свободный блок + if( rootfree != NULL ) + { + for ( BlockForCheck = rootfree; ; BlockForCheck = BlockForCheck->Next ) + { + if ( BlockForCheck->Size >= reqsize ) + { + //нашли + if ( LastKnownGood != NULL ) + { + if ( LastKnownGood->Size >= BlockForCheck->Size ) + LastKnownGood = BlockForCheck; + } + else + LastKnownGood = BlockForCheck; + if ( LastKnownGood->Size == reqsize ) + break; + } + if ( BlockForCheck->Next == NULL ) + break; + } + } + + if ( LastKnownGood != NULL ) + { + //проверим найденный блок на возможность деления + tail = LastKnownGood->Size - reqsize; + if ( tail >= ( sizeof(MemBlock) + SIZE_ALIGN ) ) + { + //будем разбивать + BlockForCheck = (MemBlock *)( ( (Byte *)LastKnownGood ) + tail ); + BlockForCheck->Size = reqsize; + //вставим занятый блок в начало списка занатых блоков + if( rootuser != NULL ) + { + BlockForCheck->Next = rootuser; + rootuser->Previous = BlockForCheck; + BlockForCheck->Previous = NULL; + rootuser = BlockForCheck; + } + else + { + rootuser = BlockForCheck; + BlockForCheck->Next = NULL; + BlockForCheck->Previous = NULL; + } + + //изменим размер оставшейся части + LastKnownGood->Size = tail - sizeof(MemBlock); + address = ( (Byte *)BlockForCheck ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + else + { + //перемести блок из очереди свободных в начало очереди занятых + //сначала выкинем его из очереди свободных + if ( LastKnownGood->Previous != NULL ) + { + LastKnownGood->Previous->Next = LastKnownGood->Next; + } + else + { + //блок стоит в начале очереди + rootfree = LastKnownGood->Next; + } + if( LastKnownGood->Next != NULL ) + { + LastKnownGood->Next->Previous = LastKnownGood->Previous; + } + //теперь вставим его в очередь занятых + if( rootuser != NULL ) + { + LastKnownGood->Next = rootuser; + rootuser->Previous = LastKnownGood; + LastKnownGood->Previous = NULL; + rootuser = LastKnownGood; + } + else + { + rootuser = LastKnownGood; + LastKnownGood->Next = NULL; + LastKnownGood->Previous = NULL; + } + // + address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + } + else + { + // надо получить ещё блок памяти + LastKnownGood = (MemBlock *)kos_malloc( + (reqsize > 0x10000 - sizeof(MemBlock)) ? (reqsize + sizeof(MemBlock)) : 0x10000); + if (LastKnownGood != NULL) + { + LastKnownGood->Size = reqsize; + // теперь вставим его в очередь занятых + LastKnownGood->Next = rootuser; + LastKnownGood->Previous = NULL; + if (rootuser != NULL) + rootuser->Previous = LastKnownGood; + rootuser = LastKnownGood; + // а также добавим хвост свежевыделенного большого блока в список свободных + if (reqsize < 0x10000 - sizeof(MemBlock)) + { + MemBlock* free = (MemBlock*)((Byte*)LastKnownGood + sizeof(MemBlock) + reqsize); + free->Next = rootfree; + free->Previous = NULL; + if (rootfree != NULL) + rootfree->Previous = free; + rootfree = free; + } + address = (Byte*)LastKnownGood + sizeof(MemBlock); + // отпустим мьютекс + rtlInterlockedExchange(&mmMutex, FALSE); + + return address; + } + } + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + // + rtlDebugOutString( "allocmem failed." ); + kos_ExitApp(); + // + return NULL; +} + +// +Dword freemem( void *vaddress ) +{ + Dword result; + + Byte *checknext, *address = (Byte *)vaddress; + + // ждём освобождения мьютекса + while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) + { + // + kos_Pause( 1 ); + } + + MemBlock *released = (MemBlock *)( address - sizeof(MemBlock) ); + + result = released->Size; + + //убираем блок из списка занятых + if ( released->Previous != NULL ) + { + released->Previous->Next = released->Next; + } + else + { + rootuser = released->Next; + } + if ( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //закинем теперь этот блок в список свободных + released->Next = rootfree; + released->Previous = NULL; + rootfree = released; + if ( released->Next != NULL ) + { + released->Next->Previous = released; + } + + //теперь поищем смежные свободные блоки + checknext = (Byte *)(rootfree) + ( rootfree->Size + sizeof(MemBlock) ); + // + for ( released = rootfree->Next; released != NULL; released = released->Next ) + { + if ( checknext == (Byte *)released ) + { + //собираем блоки вместе + //сначала выкинем из очереди свободных + released->Previous->Next = released->Next; + if( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //теперь увеличим размер корневого блока + rootfree->Size += released->Size + sizeof(MemBlock); + break; + } + } + //если надо, поищем блоки перед текщим. + checknext = (Byte *)(rootfree); + // + if ( released == NULL ) + { + for ( released = rootfree->Next; released != NULL; released = released->Next ) + { + if ( checknext == (Byte *)released + ( released->Size + sizeof(MemBlock) ) ) + { + //собираем блоки вместе + //увеличим размер блока + released->Size += rootfree->Size + sizeof(MemBlock); + //теперь выкинем из очереди свободных + released->Previous->Next = released->Next; + if ( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //и закинем его в начало очереди вместо присоединённого блока из корня списка + if ( rootfree->Next != NULL ) + { + rootfree->Next->Previous = released; + } + released->Next = rootfree->Next; + released->Previous = NULL; + rootfree = released; + break; + } + } + } + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return result; +} + diff --git a/programs/games/fara/trunk/numbers.bmp b/programs/games/fara/trunk/numbers.bmp new file mode 100644 index 0000000000000000000000000000000000000000..85b2c549266c64c717eda856cf8d37039c20794d GIT binary patch literal 7256 zcmds*hgTFw9LGs8iWH?-5WAw-&_q#U!HA*~6&t8T{g;whqoRTZ6coXT6}yNO3vvf{ za&SkJDj*!lffVzdoxQo;*}Yp{-phNCd)&R5+0XoDcE7XV-wYdL;-|R@pH=u>fUh^c z`S^b47KmT^@%M6bBj5kvbGY&w{tj9O_nZ3nl=iBQK$+jngZoTh^)5Ms=mT&PD192a~^#1zp%clH}h@8)axz90!tP2VeIc?#OKmBND@O%zg zzDWUEUPTyjKF*nDO=jhzPs{E#(3mt%e0jfgxV6t)!AM&USq2Z72KE}h#^`KY-*#=t z>sa%=HSAHdltKA`sUOS^UH6tZU6HRkxT_<#DheuyP6T}-dpNi+D*8@+k082rT}~Us zQiwhfYwVLg1S06Y#zk3mv=O4mmk&q*S{@3s>|W!-TOV1R19CxWJ49c2OB@R=U?3K~ zM1LVD;z(Oijy3e|D7I}Sg0>5y^Y;#BufRa`4X-*@KWhzp$S(}y1_qfMtjKO&dZ(U^ zMID1xSt0aJ{er*6`#NZbtH>T8#X|2kgxsv9<%8yd{bl`oN@Qa#&u&JXkW4WS$bDsf zyGweu7j|Fm6j?uC_y9o>%mlk%H_HHZcjw-Z9P)6Yf96z$Ek-}T-dd~Ds*I;tn z*Ff}aUUaV4>Srx06bplAp0;3NaE)9Q_O2=xhb@256ndK%lw)AsOSG9rF!M9T1;#~S z)x}vuV&-Mkur6>FI0mcI!s4vDc{gfiq*l^uoUw10&c-pQBF>Cd3vG`ze%-0JMZfFX znBTGPMcc~9uy^7r!H9EJ!svRU-+lqJ_66*{dD;EOMYrna-l%4ba+DF&g1jI8qy?g@ zinZ-scT_NUo-Bt#(CPMtf$lqXw&=HAkwnlon$uzL!RZjxabGdT zw&*uqfWd?bd0(0W=p1NHSI&oPA@-i9u>sri8YzIJ39c_!#YPT}q3s563|RNw2Bd&F z*Q=+dm?vH^aiM56^iIQqo3(SURZUGcPfSv0R67pO#>jl@+UN8|CMg@bOXmr_i0*k* zcapM^`h(NS%Rc#{xPD@EJaDh>iz8^{#wDhizLNZDXm$_~k_oekYn%oCEzSTB;+b3da>GeyYFkF&2i zUJ8mu6|&Y5B^bw^EaBz}_ZFDysmT=(RABTR!>U2aGSMLx z$pYlm*0hA|_iAUQRRtwi1SFY!5)5Nck~na9AqzM%1+oB`35jJsrwwCIFs6--LJOQ& zXoOg+DAORT(|*YuE2RrelFkiX;COI97d!H^HbKJ3#g`=N%24}bHeF}`u{m6UPqFMm+{hu1l z=wmu}O~z#$-*ZOKQzeL_oC6f6YWkivdj7?~!jzwLy$TGx9gH#p*8=}{7Dq~g8Fj2! z+M+DOQbrw>G1LkeISy8ELeDdT?Fe>Z4uI{PF?cAfiAErd;M+cD#GJ(Gk6E_ev{o$Cf#(potP2o5X>n3}!bnL;%TkK%|C~^}RU}T?WKZd(_6kujwuW|v< zOS7(32c?)bF)$O7NGfqn!rq~~hmZnXlOBq-p~|}-DP}jW3W$w(IKuN0OvCZN7g-kx z1JjUQVigGkdx!b3E3`mNLl}rwiM?Y(m})_q@PqlBDjj`XPfSC?P!jfzO{3pAqZeUR zUUqJvVP3^KUHXQ4oG5XJ8_-p1zxVl>H8a!1-4~KR6c^RBKVspM^)mG zW1WyD#wQp(PlAzIw{$Gwn4rNh-bEb7{QnAM|3LG;eW`Qzh@GCNurNd`P+&OI@w-9A zOF?slEV7)Tg316|kznLZr+QB38Gds`B1stdzh<1E6mpbsJs)xe(3%ha5fqT9_P+(m sd@u^mbo|~x4uJ7bEW?ISHYEjvtHhm-Yq%3II1kzEsYQ?t@$W1D0EG#WClearName(); + this->score = 0; + }; + // + void ClearName() + { + memset( (Byte *)(this->name), '.', sizeof(this->name) ); + }; +}; + +// +hiScoreHero heroTbl[TOP_TBL_SIZE]; + +// +struct hiScoreFile +{ + Byte block[512]; + kosFileInfo fi; + // + hiScoreFile() + { + int i; + + // + this->fi.OffsetLow = this->fi.OffsetHigh = 0; + this->fi.dataCount = 0; + this->fi.bufferPtr = this->block; + this->fi.rwMode = 0; + memcpy( this->fi.fileURL, top10FilePath, strlen( top10FilePath ) + 1); + // + for ( i = 0; i < ( sizeof( this->block ) / sizeof( Dword ) ); i++ ) + { + // + ((Dword *)(this->block))[i] = rtlRand(); + } + }; + // + virtual ~hiScoreFile() + {} + // + bool LoadFromDisk() + { + bool result; + int i; + Dword j, k; + Byte *bPtr; + + // + this->fi.rwMode = FO_READ; + this->fi.OffsetLow = this->fi.OffsetHigh = 0; + this->fi.dataCount = 512; + result = kos_FileSystemAccess( &(this->fi) ) == 0; + // + if ( result ) + { + // декодируем + rtlSrand( ((Dword *)(this->block))[(sizeof(this->block) / sizeof(Dword)) - 1] ); + // + for ( i = 0; i < (sizeof( heroTbl ) * 5); i++ ) + { + // не трогаем последний Dword + j = rtlRand() % (sizeof(this->block) - 7); + k = ( rtlRand() % 31 ) + 1; + // + bPtr = this->block + j; + // + __asm{ + mov edx, bPtr + mov ecx, k + mov eax, [edx] + bswap eax + ror eax, cl + mov [edx], eax + } + } + // + rtlSrand( kos_GetSystemClock() ); + } + // + return result; + }; + // + bool SaveToDisk() + { + int i; + Dword *rndList; + Byte *bPtr; + Dword k, keyLock; + + // + rndList = new Dword[(sizeof( heroTbl ) * 5) * 2]; + // + keyLock = rtlRand(); + // + for ( i = 0; i < (sizeof( heroTbl ) * 5); i++ ) + { + // + rndList[i * 2] = rtlRand() % (sizeof(this->block) - 7); + rndList[(i * 2) + 1] = ( rtlRand() % 31 ) + 1; + } + // + for ( i = (sizeof( heroTbl ) * 5) - 1; i >= 0; i-- ) + { + // + bPtr = this->block + rndList[i * 2]; + k = rndList[(i * 2) + 1]; + // + __asm{ + mov edx, bPtr + mov ecx, k + mov eax, [edx] + rol eax, cl + bswap eax + mov [edx], eax + } + } + // + delete rndList; + // + ((Dword *)(this->block))[(sizeof(this->block) / sizeof(Dword)) - 1] = keyLock; + // + this->fi.rwMode = FO_WRITE; + this->fi.dataCount = 512; + return kos_FileSystemAccess( &( this->fi) ) == 0; + }; +}; + + +/// +hiScoreFile *top10Heroes = NULL; + +// +#if LANG == RUS +char Top10WndTitle[] = "Top 10"; +char top10str1[] = "ENTER - Ё¬п Ok."; +char top10str2[] = "ESC - ўл室 ў ¬Ґ­о"; +#else +char Top10WndTitle[] = "Top 10"; +char top10str1[] = "Enter - name Ok."; +char top10str2[] = "Esc - leave to menu"; +#endif +int enterName = -1; +int enterCharNdx = 0; + + +// +void ReleaseTop10() +{ + // + if ( top10Heroes != NULL ) + { + // + memcpy( top10Heroes->block, heroTbl, sizeof(heroTbl) ); + // + top10Heroes->SaveToDisk(); + // + delete top10Heroes; + } +} + + +// +void PrepareTop10() +{ + // + top10Heroes = new hiScoreFile; + // + atexit( ReleaseTop10 ); + // + if ( top10Heroes->LoadFromDisk() ) + { + // + memcpy( heroTbl, top10Heroes->block, sizeof(heroTbl) ); + } +} + + +// +void SetUpTop10() +{ + int i, j; + Byte keyCode; + + // + while ( kos_CheckForEvent() == 2 ) kos_GetKey( keyCode ); + // + kos_SetKeyboardDataMode( KM_CHARS ); + // + kos_ChangeWindow( -1, -1, TOP10_WND_SIZE_X, TOP10_WND_SIZE_Y ); + // + for ( i = 0; i < TOP_TBL_SIZE; i++ ) + { + // + if ( heroTbl[i].score < playerScore ) + { + // + for ( j = TOP_TBL_SIZE - 1; j > i; j-- ) + { + // + heroTbl[j] = heroTbl[j-1]; + } + // + heroTbl[i].ClearName(); + heroTbl[i].score = playerScore; + // + enterName = i; + enterCharNdx = 0; + // + break; + } + } +} + + +// +void DrawTop10Window() +{ + int i; + + // + kos_DefineAndDrawWindow( + 100, 100, + TOP10_WND_SIZE_X, TOP10_WND_SIZE_Y, + 0, 0, + 0, 0x2040A0, + 0x2040A0 + ); + // + kos_WriteTextToWindow( + 4, 4, + 0x0, 0x42D2E2, + Top10WndTitle, + sizeof( Top10WndTitle ) - 1 + ); + // + for ( i = 0; i < TOP_TBL_SIZE; i++ ) + { + // + kos_WriteTextToWindow( + 6, 21 + 2 + (i * 10), + 0x0, enterName != i ? 0xFFFFFF : 0x00FF00, + heroTbl[i].name, + sizeof( heroTbl[0].name ) + ); + // + kos_DisplayNumberToWindow( + heroTbl[i].score, + 8, + 112, 21 + 2 + (i * 10), + 0xFFFF55, + nbDecimal, + false + ); + } + // + kos_WriteTextToWindow( + 6, 21 + 6 + (i * 10), + 0x10, 0x1060D0, + enterName >= 0 ? top10str1 : top10str2, + enterName >= 0 ? sizeof(top10str1) - 1 : sizeof(top10str2) - 1 + ); +} + + +// игровой процесс +void Top10Loop() +{ + Byte keyCode; + + // + SetUpTop10(); + // + while ( true ) + { + switch ( kos_WaitForEvent() ) + { + // + case 1: + DrawTop10Window(); + break; + // + case 2: + // + kos_GetKey( keyCode ); + // + if ( enterName < 0 ) + { + // + if ( keyCode == 0x1b ) + { + // + return; + } + } + else + { + // + switch ( keyCode ) + { + // + case 13: + // + enterName = -1; + break; + // + case 8: + // + if ( enterCharNdx > 0 ) + { + // + heroTbl[enterName].name[--enterCharNdx] = '.'; + } + break; + // + default: + if ( keyCode >= 0x20 ) + { + // + heroTbl[enterName].name[enterCharNdx++] = keyCode; + // + if ( enterCharNdx >= sizeof(heroTbl[0].name) ) + { + // + enterName = -1; + } + } + break; + } + // + DrawTop10Window(); + } + // + break; + // + default: + break; + } + } +} \ No newline at end of file diff --git a/programs/games/fara/trunk/top10wnd.h b/programs/games/fara/trunk/top10wnd.h new file mode 100644 index 0000000000..a09ddaafa2 --- /dev/null +++ b/programs/games/fara/trunk/top10wnd.h @@ -0,0 +1,14 @@ +// top10wnd.h + +#define TOP_TBL_SIZE 10 +#define TOP10_WND_SIZE_X 176 +#define TOP10_WND_SIZE_Y 144 + +extern char top10FilePath[MAX_PATH]; +// игровой процесс +void Top10Loop(); +// +void PrepareTop10(); + + + diff --git a/programs/games/gomoku/trunk/gomoku.asm b/programs/games/gomoku/trunk/gomoku.asm new file mode 100644 index 0000000000..6d4f774392 --- /dev/null +++ b/programs/games/gomoku/trunk/gomoku.asm @@ -0,0 +1,735 @@ +;http://sources.ru/pascal/gamestxt/go-moku.zip + +N equ 19 ; Size of the board + +use32 + org 0x0 + db 'MENUET01' + dd 0x1 + dd START + dd I_END + dd (I_END+200+13*N*N) and not 3 + dd (I_END+200+13*N*N) and not 3 + dd 0x0,0x0 + +include 'macros.inc' +include 'lang.inc' + +AttackFactor dw 1 ; Importance of attack (1..16) + +START: + + mcall 40,100111b + mcall 40,100111b + mcall 3 + mov [rsx1],ax + shr eax,16 + mov [rsx2],ax + +redraw_all: + mcall 12,1 + mcall 48,4 + xchg eax,ecx + add ecx,100*65536+(16*N+26) + mcall 0,100*65536+(16*N+12),,0x34FFFFFF,,title + mcall 38,2*65536+(16*N),20*65536+20,0x00a0a0a0;000000 + mov edi,N + @@: add ecx,16*65536+16 + mcall + dec edi + jnz @b + push cx + mov ecx,20*65536 + pop cx + mcall ,1*65536+1 + mov edi,N + @@: add ebx,16*65536+16 + mcall + dec edi + jnz @b + + mcall 8,3*65536+40,3*65536+12,2,0xFFFFFF + mcall ,50*65536+40,,3, + mcall 4,7*65536+5,0x80000000,txt_buttons + mcall 12,2 + + +draw_pole: +; mcall 48,4 +; xchg eax,ecx +; add ecx,100*65536+(16*N+26) +; mcall 0,100*65536+(16*N+12),,0x74FFFFFF,,title + + mov esi,Board + mov edi,N*N-N + mov ebp,N + mov ebx,(1+5)*65536+(21+5-1) + call print_board + bt [flags],0 + jnc @f + mcall 4,100*65536+6,0x800000ff,txt_go +@@: bt [flags],3 + jnc @f + mcall 4,100*65536+6,0x800000ff,txt_tie + jmp still +@@: + bt [flags],2 + jnc still + ret +still: + mcall 10 + + dec al + jz redraw_all + dec al + jz key + dec al + jz button + sub al,3 + jz mouse + jmp still + +key: + mcall 2 + btr [flags],2 + cmp ah,97 + jne @f +.auto: bts [flags],2 + jmp mouse.auto +@@: cmp ah,110 + je button.new_game + jmp still + +button: + mcall 17 + cmp ah,1 + jne @f + mcall -1 +@@: cmp ah,2 + jne key.auto +.new_game: + mov [TotalLines],2 * 2 * (N * (N - 4) + (N - 4) * (N - 4)) + mov [WinningLine],0x0 + mov [X],(N + 1)/2 + mov [Y],(N + 1)/2 + mov [flags],0 + mov edi,Board + mov ecx,(13*N*N/4)+1 + xor eax,eax + cld +@@: stosd + loop @b + jmp redraw_all + +print_board: + cmp byte [esi],0 ;пусто + je .null + cmp byte [esi],1 ;X + je .one + cmp byte [esi],2 ;O + je .two + bts [flags],4 + cmp byte [esi],3 ;Х выиграл + je .one + jmp .two ;0 выиграл + +.end: + inc esi + dec ebp + jnz print_board + test edi,edi + jz @f + sub edi,N + mov ebp,N + add ebx,-N*16*65536+16 + jmp print_board +@@: ret + +.one: + mov ecx,0xd04ba010 + bt [flags],4 + jnc @f + mov ecx,0xd0ff0000 + btr [flags],4 +@@: push edi + mcall 4,,,txt_x,,0xffffff + pop edi +.null: + add ebx,16*65536;+16 + jmp .end +.two: + mov ecx,0xd000459a + bt [flags],4 + jnc @f + mov ecx,0xd0ff0000 + btr [flags],4 +@@: push edi + mcall 4,,,txt_o,,0xffffff + pop edi + jmp .null + + +draw_one_symbol: + movzx eax,[X] + mov ebx,16 + mul ebx + shl eax,16 + add eax,(1+5)*65536; + mov ax,[Y] + mov ecx,16 + mul cx + add ax,(21+5-1) + xchg eax,ebx + + movzx eax,[Y] + push ebx + mov ebx,N + mul bx + mov bx,[X] + add ax,bx + pop ebx + mov esi,Board + add esi,eax + mov edi,0 + mov ebp,1 + call print_board +ret + + +mouse: + bt [flags],5 + jc still + mcall 37,2 + test eax,eax + jz still + mcall 37,1 + mov dx,ax + shr eax,16 + cmp dx,20 + jbe still + cmp dx,(16*N+20) + jge still + cmp ax,1 + jbe still + cmp ax,(16*N) + jge still + + bt [flags],0 + jc still + bt [flags],3 + jc still + sub ax,1 + push dx + xor edx,edx + mov cx,16 + div cx + pop dx + mov [X],ax + push ax + sub dx,20 + mov ax,dx + xor dx,dx + div cx + mov [Y],ax + xor dx,dx + mov cx,N + mul cx + pop dx + add ax,dx + cmp ax,N*N + jge still + mov esi,Board + + cmp byte [esi+eax],0 + jne still + +.auto: bt [flags],0 + jc .end + bt [flags],3 + jc .end + + btr [flags],1 ;0 - 室 ¤Ґ« Ґв ЁЈа®Є + bt [flags],2 + jnc @f + call FindMove +@@: call MakeMove + call draw_one_symbol + bt [flags],0 + jc .end + + bts [flags],1 ;1 - 室 ¤Ґ« Ґв cpu + call FindMove + call MakeMove + call draw_one_symbol +.end: bt [flags],0 + jnc @f + call BlinkRow + btr [flags],2 +@@:; mcall 12,1 + bt [flags],3 + jc @f + bt [flags],2 + jnc @f + call draw_pole + jmp .auto +@@: jmp draw_pole + + + + +winline: dw 1,0, 1,1, 1,-1, 0,1 ;X,Y +BlinkRow: + movzx ecx,[WinningLine] + mov eax,[winline+(ecx-1)*4] + push ax ;Dx + shr eax,16 + push ax ;Dy + movzx eax,[Y] + mov si,N + mul si + add ax,[X] + mov cl,[Board+eax] +@@: movzx eax,[Y] + add ax,[esp] + mov [Y],ax + test eax,eax + jz .ret + cmp eax,N-1 + jg .ret + movzx ebx,[X] + add bx,[esp+2] + mov [X],bx + test ebx,ebx + jz .ret + cmp ebx,N-1 + jg .ret + mov si,N + mul si + add ax,bx + cmp byte [Board+eax],cl + je @b + +.ret: mov edi,5 + mov esi,N +@@: movzx eax,[Y] + sub ax,[esp] + mov [Y],ax + mul si + movzx ebx,[X] + sub bx,[esp+2] + mov [X],bx + add ax,bx + cmp byte [Board+eax],cl + jne .1 + add byte [Board+eax],2 +.1: dec edi + jnz @b + add esp,4 +ret + + + +Max dw ? + +FindMove: + mov [Max],0 + mov [X],((N+1) / 2) + mov [Y],((N+1) / 2) + movzx eax,[Y] + mov ah,N + mul ah + add ax,[X] + cmp byte [Board+eax],0 + jne @f + mov [Max],4 +@@: xor ecx,ecx +.loop: + cmp byte [Board+ecx],0 + jne .check_loop + movzx eax, word [Value+ecx*2] + bt [flags],1 + jc @f + movzx eax, word [Value+(N*N+ecx)*2] + @@: + mov ebx,16 + add bx,[AttackFactor] + mul bx + shr eax,4 ;div 16 + mov bx,[Value+2*(N*N+ecx)] + bt [flags],1 + jc @f + mov bx,[Value+2*(ecx)] + @@: + add bx,ax + mov eax,4 + call random + add bx,ax + cmp bx,[Max] + jbe .check_loop + mov [Max],bx + xor edx,edx + mov eax,ecx + mov ebx,N + div ebx + mov [X],dx + mov [Y],ax +.check_loop: + inc ecx + cmp ecx,N*N + jb .loop +ret + + +MakeMove: + xor eax,eax + mov esi,N + +.1: movzx ecx,[X] ;ecx=X1, eax=K, edx=Y1 + inc cl + movzx edx,[Y] + inc dl + sub cl,al + xor edi,edi + test ecx,ecx + jz .1_ + cmp ecx,N-4 + jg .1_ + dec cl + dec dl + push eax edx + mov eax,edx + mul esi + add eax,ecx + call .Add + bt [flags],0 + jnc .11 + cmp [WinningLine],0x0 + jne .11 + mov [WinningLine],1 + .11: mov eax,[esp];edx + mul esi + add eax,ecx + push eax + mov eax,[esp+4];edx + mul esi + add eax,edi + add eax,ecx + mov ebx,eax + pop eax + call .Update + inc edi + cmp edi,4 + jbe .11 + pop edx eax +.1_: inc eax + cmp eax,4 + jbe .1 + + xor eax,eax + +.2: movzx ecx,[X] + inc cl + movzx edx,[Y] + inc dl + xor edi,edi + sub cl,al + sub dl,al + test ecx,ecx + jz .2_ + cmp ecx,N-4 + jg .2_ + test edx,edx + jz .2_ + cmp edx,N-4 + jg .2_ + dec cl + dec dl + push eax edx + mov eax,edx + mul esi + add eax,ecx + add eax,1*N*N + call .Add + bt [flags],0 + jnc .21 + cmp [WinningLine],0x0 + jne .21 + mov [WinningLine],2 + .21: mov eax,[esp];edx + mul esi + add eax,ecx + add eax,1*N*N + push eax + mov eax,[esp+4];edx + add eax,edi + mul esi + add eax,edi + add eax,ecx + mov ebx,eax + pop eax + call .Update + inc edi + cmp edi,4 + jbe .21 + pop edx eax +.2_: inc eax + cmp eax,4 + jbe .2 + + xor eax,eax + +.3: movzx ecx,[X] + inc cl + movzx edx,[Y] + inc dl + xor edi,edi + add cl,al + sub dl,al + cmp ecx,5 + jb .3_ + cmp ecx,N + jg .3_ + test edx,edx + jz .3_ + cmp edx,N-4 + jg .3_ + dec cl + dec dl + push eax edx + mov eax,edx + mul esi + add eax,ecx + add eax,3*N*N + call .Add + bt [flags],0 + jnc .31 + cmp [WinningLine],0 + jne .31 + mov [WinningLine],3 + .31: mov eax,[esp];edx + mul esi + add eax,ecx + add eax,3*N*N + push eax + mov eax,[esp+4];edx + add eax,edi + mul esi + add eax,ecx + sub eax,edi + mov ebx,eax + pop eax + call .Update + inc edi + cmp edi,4 + jbe .31 + pop edx eax +.3_: inc eax + cmp eax,4 + jbe .3 + + xor eax,eax + +.4: movzx ecx,[X] + inc cl + movzx edx,[Y] + inc dl + xor edi,edi + sub dl,al + test edx,edx + jz .4_ + cmp edx,N-4 + jg .4_ + dec cl + dec dl + push eax edx + mov eax,edx + mul esi + add eax,ecx + add eax,2*N*N + call .Add + bt [flags],0 + jnc .41 + cmp [WinningLine],0 + jne .41 + mov [WinningLine],4 + .41: mov eax,[esp];edx + mul esi + add eax,ecx + add eax,2*N*N + push eax + mov eax,[esp+4];edx + add eax,edi + mul esi + add eax,ecx + mov ebx,eax + pop eax + call .Update + inc edi + cmp edi,4 + jbe .41 + pop edx eax +.4_: inc eax + cmp eax,4 + jbe .4 + + movzx eax,[Y] + mul esi + add ax,[X] + bt [flags],1 + jc @f + mov byte [Board+eax],1 + jmp .end +@@: + mov byte [Board+eax],2 +.end: cmp [TotalLines],0 + jne @f + bts [flags],3 +@@: +ret + +.Add: + bt [flags],1 + jnc .Add_player + inc byte [Line+eax] + cmp byte [Line+eax],1 + jne @f + dec [TotalLines] +@@: cmp byte [Line+eax],5 + jb @f + bts [flags],0 ;ЁЈа  ®Є®­зҐ­  +@@: +ret +.Add_player: + inc byte [Line+eax+4*N*N] + cmp byte [Line+eax+4*N*N],1 + jne @f + dec [TotalLines] +@@: cmp byte [Line+eax+4*N*N],5 + jb @f + bts [flags],0 ;ЁЈа  ®Є®­зҐ­  +@@: +ret + +.Update: +;eax ЇҐаўл© Ї а ¬Ґва, ebx ўв®а®© + push edi + bt [flags],1 + jnc .Update_player + cmp byte [Line+eax+4*N*N],0 + jne .else_cpu + push eax + movzx edi, byte [Line+eax] + mov ax, word [edi*2+2+Weight] + sub ax, word [edi*2+Weight] + add [Value+ebx*2],ax + pop eax + jmp .Update_end + .else_cpu: + cmp byte [Line+eax],1 + jne .Update_end + push eax + movzx edi, byte [Line+eax+4*N*N] + mov ax, word [edi*2+2+Weight] + sub [Value+ebx*2+N*N*2],ax + pop eax + jmp .Update_end +.Update_player: + cmp byte [Line+eax],0 + jne .else_player + push eax + movzx edi, byte [Line+eax+4*N*N] + mov ax, word [edi*2+2+Weight] + mov di, word [edi*2+Weight] + sub ax,di + add [Value+ebx*2+2*N*N],ax + pop eax + jmp .Update_end + .else_player: + cmp byte [Line+eax+4*N*N],1 + jne .Update_end + push eax + movzx edi, byte [Line+eax] + mov ax, word [edi*2+2+Weight] + sub [Value+ebx*2],ax + pop eax +.Update_end: + pop edi +ret + + +align 4 +rsx1 dw ?;0x4321 +rsx2 dw ?;0x1234 +random: ; Ё§ ASCL + push ecx ebx edi edx + mov cx,ax + mov ax,[rsx1] + mov bx,[rsx2] + mov si,ax + mov di,bx + mov dl,ah + mov ah,al + mov al,bh + mov bh,bl + xor bl,bl + rcr dl,1 + rcr ax,1 + rcr bx,1 + add bx,di + adc ax,si + add bx,0x62e9 + adc ax,0x3619 + mov [rsx1],bx + mov [rsx2],ax + xor dx,dx + cmp ax,0 + je nodiv + cmp cx,0 + je nodiv + div cx +nodiv: + mov ax,dx + pop edx edi ebx ecx + and eax,0000ffffh +ret + + + +txt_x db 'X',0 +txt_o db 'O',0 +if lang eq ru +title db 'ѓ®¬®Єг',0 +txt_buttons db 'Ќ®ў п Ђўв®',0 +txt_go db '€Ја  ®Є®­зҐ­ ',0 +txt_tie db 'ЌҐв 室®ў',0 +else +title db 'Gomoku',0 +txt_go db 'Game over',0 +txt_tie db 'Tie game',0 +txt_buttons db 'New Auto',0 +endf + + +Weight dw 0,0,4,20,100,500,0 + + +WinningLine db 0 +TotalLines dw 0 + +X dw 0 +Y dw 0 + +flags rw 1 +;ЎЁв 0: ЁЈа  ®Є®­зҐ­  +;1: 0-室 ЁЈа®Є , 1-жЇг +;2: autoplay +;3: е®¤л ЁбзҐаЇ ­л +;4: ў print_board - ўл¤Ґ«Ґ­ЁҐ Єа б­л¬ 梥⮬ 5-вЁ ў ап¤ Є«Ґв®Є + +I_END: +align 16 +Board rb N*N +Value rw N*N*2 ;ЇҐаў п Ї®«®ўЁ­  - ¤«п Є®¬Ї , ўв®а п - ¤«п ЁЈа®Є  +Line rb 4*N*N*2 + + diff --git a/programs/games/reversi/trunk/Makefile b/programs/games/reversi/trunk/Makefile new file mode 100644 index 0000000000..6bf4de36ab --- /dev/null +++ b/programs/games/reversi/trunk/Makefile @@ -0,0 +1,3 @@ +OUTFILE = reversi +OBJS = reversi.o +include $(MENUETDEV)/makefiles/Makefile_for_program diff --git a/programs/games/reversi/trunk/reversi.c b/programs/games/reversi/trunk/reversi.c new file mode 100644 index 0000000000..967b03d726 --- /dev/null +++ b/programs/games/reversi/trunk/reversi.c @@ -0,0 +1,619 @@ +// +// KReversi.java +// The Othello Game, based on the algorithm of Muffy Barkocy +// (muffy@fish.com). +// +// The strategy is very very simple. The best move for the computer +// is the move that flip more pieces (preferring boards line and +// corners) and give less pieces to move to the opponent. +// +// Author: Alex "Kazuma" Garbagnati (kazuma@energy.it) +// Date: 20 Jan 96 +// L.R.: 26 Jan 96 +// Note: +// + + + +#include +#include +#include +#include +#include +#include + +typedef unsigned int u32; + +int YSHIFT= 33; + +int ENGLISH = 0; // +int ITALIAN = 1; // Languages +int EXTERNAL = 2; // + +#define BLACK 0x000000; // +#define BLACK_S 0x333333; // +#define WHITE 0xffffff; // Colors +#define WHITE_S 0xaaaaaa; // + + +int NOMOVE = 0; // +int REALMOVE = 1; // Type of move +int PSEUDOMOVE = 2; // + +int Empty = 0; // +int User = 1; // Board's owners +int Computer = 2; // + +#define true 1 +#define false 0 + +int UserMove = true; +int GameOver = false; +int CopyWinOn = false; +int StillInitiated = false; // This solve a little + // problem on reinit. + +int TheBoard[8][8]; // Board +int Score[8][8]; +int OpponentScore[8][8]; + + + + // + // DrawBoard + // (paint the Othello Board, a 8X8 green square table) + // + // Input: graphic (Graphics) + // Output: none + // Notes: + // + void DrawBoard() { + int i; + for(i=0;i<=8;i++) + { + __asm__ __volatile__("int $0x40"::"a"(38),"b"(320),"c"(YSHIFT+(YSHIFT+(40*i))*65536+40*i),"d"(0x555555)); + __menuet__line((40*i),YSHIFT,(40*i),353,0x555555); // horizontal + + } + + } + // End of DrawBoard + + + // + // DrawPiece + // (paint a piece, black or white, I'm using an 8x8 array, so + // from the input values for rows and cols must be + // subtracted 1) + // + // Input: who (int), + // column (int), + // row (int) + // Output: none + // Notes: + // + void DrawPiece(int Who, int Col, int Row) { + int pCol = (40*(Col-1)+1); + int pRow = YSHIFT+(40*(Row-1)+1); + u32 pColor,pShadow; + + if (Who == User) { + pColor = BLACK; + pShadow = BLACK_S; + } else { + pColor = WHITE; + pShadow = WHITE_S; + } + TheBoard[Col-1][Row-1] = Who; + + __menuet__bar(pCol+9,pRow+9,19,19,pColor); + } + // End of DrawPiece + + + // + // MsgWhoMove + // (paint the message informing who's move) + // + // Input: is user ? (int) + // Output: none + // Notes: + // + void MsgWhoMove(int UM) { + } + // End of MsgWhoMove + + + // + // FlipRow + // (calculate number of pieces are flipped by a move + // and return it. Eventually do the complete or pseudo + // move) + // + // Input: who (int) + // which board (int[][]) + // position col, row (int) + // direction col, row (int) + // make move ? (int) + // + int FlipRow(int Who, int WhichBoard[8][8] , int C, int R, + int CInc, int RInc, int MakeMove) { + int NewCol; + int NewRow; + int Opponent = User + Computer - Who; + int CNT = 0; + + NewCol = C - 1; + NewRow = R - 1; + while (true) { + if (((NewCol+CInc) < 0) || ((NewCol+CInc) > 7) || + ((NewRow+RInc) < 0) || ((NewRow+RInc) > 7)) { + return 0; + } + if (WhichBoard[NewCol+CInc][NewRow+RInc] == Opponent) { + CNT++; + NewCol += CInc; + NewRow += RInc; + } else if (WhichBoard[NewCol+CInc][NewRow+RInc] == Empty) { + return 0; + } else { + break; + } + } + if (MakeMove != NOMOVE) { + C--; + R--; + int v; + for(v=0; v<=CNT; v++) { + if (MakeMove == REALMOVE) { + DrawPiece(Who, C+1, R+1); + } else { + WhichBoard[C][R] = Who; + } + C += CInc; + R += RInc; + } + } + return CNT; + } + // End of FlipRow + + + // + // IsLegalMove + // (verify that the move is legal) + // + // Input: who (int) + // board (int[][]) + // position col, row (int) + // Output: is legal ? (int) + // Notes: + // + int IsLegalMove(int Who, int WhichBoard[8][8] , int C, int R) { + if (WhichBoard[C-1][R-1] != Empty) { + return false; + } + int CInc,RInc; + for (CInc=-1; CInc<2; CInc++) { + for (RInc=-1; RInc<2; RInc++) { + if (FlipRow(Who, WhichBoard, C, R, CInc, RInc, NOMOVE) > 0) { + return true; + } + } + } + return false; + } + // End of IsLegalMove + + + // + // MakeMove + // (make the move) + // + // Input: who (int) + // position col, row (int) + // Output: false=EndGame, true=next player (int) + // Notes: + // + int MakeMove(int Who, int C, int R) { + int CInc,RInc; + for (CInc=-1; CInc<2; CInc++) { + for (RInc=-1; RInc<2; RInc++) { + FlipRow(Who, TheBoard, C, R, CInc, RInc, REALMOVE); + } + } + if (IsBoardComplete() || + ((!ThereAreMoves(Computer, TheBoard)) && (!ThereAreMoves(User, TheBoard)))) { + return false; + } + int Opponent = (User + Computer) - Who; + if (ThereAreMoves(Opponent, TheBoard)) { + UserMove = !UserMove; + } + return true; + } + // End of MakeMove + + + // + // EndGame + // (shows the winning message) + // + // Input: none + // Output: none + // Notes: + // + void EndGame() { + int CompPieces = 0; + int UserPieces = 0; + char *WinMsg_W = "Computer Won"; + char *WinMsg_L = "User Won"; + char *WinMsg_T = "???"; + char *TheMsg; + + int StrWidth; + + int c,r; + for (c=0; c<8; c++) { + for (r=0; r<8; r++) { + if (TheBoard[c][r] == Computer) { + CompPieces++; + } else { + UserPieces++; + } + } + } + if (CompPieces > UserPieces) { + TheMsg = WinMsg_W; + } else if (UserPieces > CompPieces) { + TheMsg = WinMsg_L; + } else { + TheMsg = WinMsg_T; + } + + __menuet__write_text(100,8,0xff0000,TheMsg,strlen(TheMsg)); + + } + // End of EndGame + + + // + // IsBoardComplete + // (checks if the board is complete) + // + // Input: none + // Output: the board is complete ? (int) + // Notes: + // + int IsBoardComplete() { + int i,j; + for (i=0; i<8; i++) { + for (j=0; j<8; j++) { + if (TheBoard[i][j] == Empty) { + return false; + } + } + } + return true; + } + // End of IsBoardComplete + + + // + // ThereAreMoves + // (checks if there are more valid moves for the + // player) + // + // Input: player (int) + // board (int[][]) + // Output: there are moves ? (int) + // Notes: + // + int ThereAreMoves(int Who, int WhichBoard[8][8] ) { + int i,j; + for (i=1; i<=8; i++) { + for (j=1; j<=8; j++) { + if (IsLegalMove(Who, WhichBoard, i, j)) { + return true; + } + } + } + return false; + } + // End of ThereAreMoves + + + // + // CalcOpponentScore + // (calculate the totalScore of opponent after + // a move) + // + // Input: position x, y (int) + // Output: score (int) + // Notes: + // + int CalcOpponentScore(int CP, int RP) { + int OpScore = 0; + int tempBoard[8][8]; // = new int[8][8]; + int c,r; + for (c=0; c<8; c++) { + for (r=0; r<8; r++) { + tempBoard[c][r] = TheBoard[c][r]; + } + } + int CInc,RInc; + for (CInc=-1; CInc<2; CInc++) { + for (RInc=-1; RInc<2; RInc++) { + FlipRow(Computer, tempBoard, CP+1, RP+1, CInc, RInc, PSEUDOMOVE); + } + } + if (ThereAreMoves(User, tempBoard)) { + int C,R; + for (C=0; C<8; C++) { + for (R=0; R<8; R++) { + OpScore += RankMove(User, tempBoard, C, R); + } + } + } + return OpScore; + } + // End of CalcOpponentScore() + + + // + // RankMoves + // (rank all moves for the computer) + // + // Input: none + // Output: none + // Notes: + // + void RankMoves() { + int C,R; + for (C=0; C<8; C++) { + for (R=0; R<8; R++) { + Score[C][R] = RankMove(Computer, TheBoard, C, R); + if (Score[C][R] != 0) { + OpponentScore[C][R] = CalcOpponentScore(C, R); + } else { + OpponentScore[C][R] = 0; + } + } + } + } + // End of RankMoves + + + // + // RankMove + // (rank a move for a player on a board) + // + // Input: who moves (int) + // on which board (int[][]) + // position col, row (int) + // Output: flipped pieces (int) + // Notes: best are corner, then border lines, + // worst are line near to border lines + // + int RankMove(int Who, int WhichBoard[8][8], int Col, int Row) { + int CNT = 0; + int MV = 0; + + if (WhichBoard[Col][Row] != Empty) { + return 0; + } + int CInc,RInc; + for (CInc=-1; CInc<2; CInc++) { + for (RInc=-1; RInc<2; RInc++) { + MV = FlipRow(Who, WhichBoard, Col+1, Row+1, CInc, RInc, NOMOVE); + CNT += MV; + } + } + if (CNT > 0) { + if (((Col == 0) || (Col == 7)) || + ((Row == 0) || (Row == 7))) { + CNT = 63; + } + if (((Col == 0) || (Col == 7)) && + ((Row == 0) || (Row == 7))) { + CNT = 64; + } + if ((((Col == 0) || (Col == 7)) && (Row == 1) || (Row == 6)) && + (((Col == 1) || (Col == 6)) && (Row == 0) || (Row == 7)) && + (((Col == 1) || (Col == 6)) && (Row == 1) || (Row == 6))) { + CNT = 1; + } + } + return CNT; + } + // End of RankMove + + + // + // BestMove + // (calculate and execute the best move) + // + // Input: none + // Output: value, col & row (int[3]) + // Notes: + // + void BestMove (int retval[3]) { + + retval[0] = -998; // move value; + retval[1] = 0; // column + retval[2] = 0; // row + + RankMoves(); + int C,R; + for (C=0; C<8; C++) { + for (R=0; R<8; R++) { + if ((Score[C][R] == 0) && (OpponentScore[C][R] == 0)) { + Score[C][R] = -999; + } else if (Score[C][R] != 64) { + Score[C][R] = Score[C][R] - OpponentScore[C][R]; + } + } + } + for (C=0; C<8; C++) { + for (R=0; R<8; R++) { + if (Score[C][R] > retval[0]) { + retval[1] = C; + retval[2] = R; + retval[0] = Score[C][R]; + } + } + } + retval[1]++; + retval[2]++; +// return retval; + } + // End of BestMove + + + + + // + // paint + // + void paint() { +// MsgWhoMove(UserMove); + if (!CopyWinOn) { + int i,j; + for (i=0; i<8; i++) { + for (j=0; j<8; j++) { + if (TheBoard[i][j] != Empty) { + DrawPiece(TheBoard[i][j], i+1, j+1); + } + } + } +// } else { +// ShowAbout(); + } + } + // End of paint + + + // + // init + // + void init() { + // This is the right size of the applet 321x387 +// resize(321,387); + // I set twice the language. That's because if anybody + // forget a string in an external language file, are + // used english strings. + if (!StillInitiated) { + StillInitiated = true; + } + int i,j; + for (i=0; i<8; i++) { + for (j=0; j<8; j++) { + TheBoard[i][j] = 0; + } + } + TheBoard[3][3] = User; + TheBoard[3][4] = Computer; + TheBoard[4][3] = Computer; + TheBoard[4][4] = User; + UserMove = true; +// MsgWhoMove(true); + // repaint(); + } + // End of init + + + + + +void paint_win(void) +{ + __menuet__window_redraw(1); + __menuet__define_window(100,100,330,400,0x33777777,0,"Reversi"); + __menuet__make_button(2,2,40,20,3,0xe0e0e0); + __menuet__write_text(8,8,0x333333,"New",3); + __menuet__window_redraw(2); +} + +void app_main(void) +{ + int i; + u32 mouse_coord; + u32 mouse_butn; + int X,Y; + + int TheCol, TheRow; + int BMove[3]; + int BX, BY; + int retval = false; + + + __menuet__set_bitfield_for_wanted_events(EVENT_REDRAW + EVENT_KEY + EVENT_BUTTON + EVENT_MOUSE_CHANGE); + paint_win(); + DrawBoard(); + init(); + paint(); + + for(;;) + { + i=__menuet__wait_for_event(); + switch(i) + { + case 1: + paint_win(); + DrawBoard(); + paint(); + continue; + case 2: + __menuet__getkey(); + continue; + case 3: + if(__menuet__get_button_id()==1) { + __menuet__sys_exit();} + else + paint_win(); + init(); + DrawBoard(); + paint(); + continue; + case 4: + continue; + case 5: + continue; + case 6: + __asm__ __volatile__("int $0x40":"=a"(mouse_butn):"0"(37),"b"(2)); + __asm__ __volatile__("int $0x40":"=a"(mouse_coord):"0"(37),"b"(1)); + X = mouse_coord >> 16; + Y = mouse_coord & 0xffff; + + // Process a normal click in the board + BX = X; + BY = Y - YSHIFT; + + + if ((BY >= 0) && (BY <= 321) && + (mouse_butn !=0) && (UserMove)) { + TheCol = (int)((BX/40)+1); + TheRow = (int)((BY/40)+1); + + if (IsLegalMove(User, TheBoard, TheCol, TheRow)) { + retval = MakeMove(User, TheCol, TheRow); + while (retval && (!UserMove)) { + //MsgWhoMove(UserMove); + BestMove(BMove); + + retval = MakeMove(Computer, BMove[1], BMove[2]); + //MsgWhoMove(UserMove); + } + if (!retval) { + EndGame(); + } + } + paint(); + } + continue; + + + } + } +} + diff --git a/programs/games/rforces/trunk/KosFile.h b/programs/games/rforces/trunk/KosFile.h new file mode 100644 index 0000000000..5f7c18e9bc --- /dev/null +++ b/programs/games/rforces/trunk/KosFile.h @@ -0,0 +1,26 @@ +#pragma once + +#define SEEK_SET 0 +#define SEEK_CUR 1 + +#define FILE_BUFFER_SIZE 512 +#define OS_BLOCK_SIZE 1 +#define FILE_BUFFER_BLOCKS (FILE_BUFFER_SIZE / OS_BLOCK_SIZE) + + +class CKosFile +{ +public: + CKosFile(char *fileName); + virtual ~CKosFile(void); + virtual int Read(Byte *targetPtr, int readCount); + virtual int Write(Byte *sourcePtr, int writeCount); + virtual int Seek(int seekFrom, int seekStep); +protected: + int filePointer; + int bufferPointer; + bool validBuffer; + kosFileInfo fileInfo; + virtual void ValidateBuffer(void); + virtual void UpdateBuffer(void); +}; diff --git a/programs/games/rforces/trunk/cmp.bat b/programs/games/rforces/trunk/cmp.bat new file mode 100644 index 0000000000..59b663e8a2 --- /dev/null +++ b/programs/games/rforces/trunk/cmp.bat @@ -0,0 +1,4 @@ +"C:\Program Files\Microsoft Visual Studio 8\VC\bin\cl" /c /O2 /nologo /GS- /GR- /fp:fast rforces.cpp kosFile.cpp kosSyst.cpp mcsmemm.cpp +"C:\Program Files\Microsoft Visual Studio 8\VC\bin\link" /nologo /manifest:no /entry:crtStartUp /subsystem:native /base:0 /fixed /align:16 /nodefaultlib rforces.obj kosFile.obj kosSyst.obj mcsmemm.obj +pe2kos rforces.exe rforces +pause \ No newline at end of file diff --git a/programs/games/rforces/trunk/forces_1.1.cpp b/programs/games/rforces/trunk/forces_1.1.cpp new file mode 100644 index 0000000000..06a589cc1d --- /dev/null +++ b/programs/games/rforces/trunk/forces_1.1.cpp @@ -0,0 +1,402 @@ +/* Rocket Forces + * Filename: rforces.cpp + * Version 0.1 + * Copyright (c) Serial 2007 + */ + + +#include + +#include "kosSyst.h" +#include "kosFile.h" +#include "mymath.h" +#include "properties.h" +#include "objects.h" +#include "rforces.h" + + +const char header[] = GAME_NAME; +cCursor *cursor; +cGun *gun = new cGun; +cCross **crosses = new cCross*[R_COUNT]; +cRocket **rockets = new cRocket*[R_COUNT]; +cBomb **bombs = new cBomb*[B_COUNT]; +cExplode **explodes = new cExplode*[R_COUNT + B_COUNT]; +cBuilding *house = new cBuilding(); +Dword *cur_handle; +int score = 0, health = 100; + +struct MouseState +{ + int x, y, lbclick; + Dword buttons; +} ms; + + +void kos_Main() +{ + Dword frame_start, frame_end; + OnStart(); + Menu(); + for (;;) + { + frame_start = kos_GetTime(); + switch (kos_CheckForEvent()) + { + case 1: + DrawWindow(); + break; + case 2: // key pressed, read it and ignore + Byte keyCode; + kos_GetKey(keyCode); + if (keyCode == 27) + { + OnExit(); + } + break; + case 3: // button pressed; we have only one button, close + OnExit(); + break; + case 6: // событие от мыши (нажатие на кнопку мыши или перемещение; сбрасывается при прочтении) + OnMouseMove(); + if (ms.lbclick == 1) + { + OnLMBClick(); + } + break; + default: + OnMouseMove(); + break; + } + DrawBombs(); + DrawRocketsAndCrosses(); + DrawExplodes(); + frame_end = kos_GetTime(); + if (frame_end - frame_start < FRAME_TIME) + { + kos_Pause(FRAME_TIME - (frame_end - frame_start)); + } + if (health <= 0) + { + OnExit(); + } + } +} + +void DrawWindow() +{ + kos_WindowRedrawStatus(1); + kos_DefineAndDrawWindow(10, 40, WINDOW_WIDTH + 8, WINDOW_HEIGHT + 25, 0x33, BG_COLOR, 0, 0, (Dword)header); + kos_WindowRedrawStatus(2); + + kos_WindowRedrawStatus(1); /// DEL!!!!11 + + OnMouseMove(); + + // Draw buildings + for (int i = 20; i < 5 * 50; i += 50) + { + house->Draw(i, 467, H_COLOR); + } + for (int i = 8 * 50; i < 13 * 50; i += 50) + { + house->Draw(i, 467, H_COLOR); + } + +} + +void DrawBombs() +{ + for (int i = 0; i < B_COUNT; i++) + { + if (bombs[i]->IsEnabled() == 0) + { + int rnd; + rnd = rtlRand() % B_POSSIBILITY; + if (rnd == 1) + { + rnd = 10 + rtlRand() % 620; + bombs[i]->Enable(rnd, 0, 4, 9, rnd + 2, 0); + } + } + else + { + if (bombs[i]->cy > gun->cy + 5) + { + health -= 5; + if (explodes[R_COUNT + i]->IsEnabled() == 1) + { + explodes[R_COUNT + i]->Disable(BG_COLOR); + } + explodes[R_COUNT + i]->Enable(bombs[i]->cx, bombs[i]->cy); + bombs[i]->Disable(BG_COLOR); + } + else + { + bombs[i]->cy += B_SPEED; + bombs[i]->DrawAngle(bombs[i]->cx, 639, B_COLOR); + } + } + } +} + +void DrawRocketsAndCrosses() +{ + double a; + for (int i = 0; i < R_COUNT; i++) + { + if (crosses[i]->IsEnabled() == 1) + { + if (sqrt(((long int) (crosses[i]->x - rockets[i]->cx) * (crosses[i]->x - rockets[i]->cx)) + ((long int) (crosses[i]->y - rockets[i]->cy) * (crosses[i]->y - rockets[i]->cy))) < 5) + { + if (explodes[i]->IsEnabled() == 1) + { + explodes[i]->Disable(BG_COLOR); + } + explodes[i]->Enable(crosses[i]->x, crosses[i]->y); + crosses[i]->Disable(BG_COLOR); + rockets[i]->Disable(BG_COLOR); + } + else + { + crosses[i]->Draw(CROSS_COLOR); + if (rockets[i]->cx - crosses[i]->x == 0) + { + a = M_PI / 2; + } + else + { + a = atan((double)(rockets[i]->cy - crosses[i]->y) / (double)(rockets[i]->cx - crosses[i]->x)); + if (rockets[i]->cx - crosses[i]->x < 0) a += M_PI; + } + rockets[i]->cx = round_int(rockets[i]->cx - R_SPEED * cos(a)); + rockets[i]->cy = round_int(rockets[i]->cy - R_SPEED * sin(a)); + rockets[i]->DrawAngle(crosses[i]->x, crosses[i]->y, R_COLOR); + } + } + } +} + +void DrawExplodes() +{ + for (int i = 0; i < R_COUNT + B_COUNT; i++) + { + if (explodes[i]->IsEnabled() == 1) + { + explodes[i]->DrawNext(EXP_COLOR); + for (int j = 0; j < B_COUNT; j++) + { + if ( bombs[j]->IsEnabled() == 1 && + bombs[j]->cx > explodes[i]->cx - explodes[i]->step - 1 && bombs[j]->cx < explodes[i]->cx + explodes[i]->step + 1 && + bombs[j]->cy + 5 > explodes[i]->cy - explodes[i]->step - 1 && bombs[j]->cy + 5 < explodes[i]->cy + explodes[i]->step + 1 + ) + { + score += B_COUNT + 2; + if (explodes[R_COUNT + j]->IsEnabled() == 1) + { + explodes[R_COUNT + j]->Disable(BG_COLOR); + } + explodes[R_COUNT + j]->Enable(bombs[j]->cx, bombs[j]->cy); + bombs[j]->Disable(BG_COLOR); + } + } + } + } +} + +void OnMouseMove() +{ + Dword old_buttons = ms.buttons; + kos_GetMouseWindowXY(ms.x, ms.y); + kos_GetMouseButtonsState(ms.buttons); + if ((old_buttons & 0x00000001) == 0 && (ms.buttons & 0x00000001) == 1) + { + ms.lbclick = 1; + } + else + { + ms.lbclick = 0; + } + + + kos_WriteTextToWindow(8, 10, 0, TEXT_COLOR, "Population: %", 16); + kos_DisplayNumberToWindowBg(health, 3, 79, 10, TEXT_COLOR, BG_COLOR, nbDecimal, false); + kos_WriteTextToWindow(8, 22, 0, TEXT_COLOR, "Score:", 6); + kos_DisplayNumberToWindowBg(score, 4, 49, 22, TEXT_COLOR, BG_COLOR, nbDecimal, false); + + if (ms.x >= 0 && ms.x < WINDOW_WIDTH && ms.y >= 0 && ms.y < WINDOW_HEIGHT) + { + gun->DrawAngle(ms.x, ms.y, G_COLOR); + } + + if (HARDWARE_CURSOR == 0) + { + cursor->Draw(ms.x, ms.y, CUR_COLOR); + } + + /*if (DEBUG == 1) + { + kos_DisplayNumberToWindowBg(ms.x, 3, WINDOW_WIDTH - 30, 10, TEXT_COLOR, BG_COLOR, nbDecimal, false); + kos_DisplayNumberToWindowBg(ms.y, 3, WINDOW_WIDTH - 30, 22, TEXT_COLOR, BG_COLOR, nbDecimal, false); + kos_DisplayNumberToWindowBg(ms.buttons, 1, WINDOW_WIDTH - 30, 34, TEXT_COLOR, BG_COLOR, nbDecimal, false); + }*/ + +} + +void OnLMBClick() +{ + if (ms.y < gun->cy - 10) + { + double a; + int j = -1; + for (int i = 0; i < R_COUNT; i++) + { + if (crosses[i]->IsEnabled() == 0) + { + if (j >= -1) j = i; + } + else if (ms.x > crosses[i]->x - 10 && ms.x < crosses[i]->x + 10 && ms.y > crosses[i]->y - 10 && ms.y < crosses[i]->y + 10) + { + j = -2; + break; + } + } + if (j >= 0) + { + if (score > 0) score -= 1; + crosses[j]->Enable(ms.x, ms.y); + if (gun->cx - ms.x == 0) + { + a = M_PI/2; + } + else + { + a = atan((double)gun->cy - ms.y / (double) gun->cx - ms.x); + if (gun->cx - ms.x < 0) a += M_PI; + } + rockets[j]->Enable(round_int(gun->cx - 15 * cos(a)) - 2, round_int(gun->cy - 15 * sin(a)) - 5, 3, 6, round_int(gun->cx - 15 * cos(a)), round_int(gun->cy - 15 * sin(a))); + } + } +} + +void OnRMBClick() +{ +} + +void ChangeCursor() +{ + Dword *cur = new Dword[1024]; + for (int i = 0; i < 1024; i++) + { + cur[i] = 0x00000000; + } + if (HARDWARE_CURSOR == 1) + { + Dword cur_color = 0xFF000000 | CUR_COLOR; + cur[0 * 32 + 5] = cur_color; + cur[1 * 32 + 5] = cur_color; + cur[2 * 32 + 5] = cur_color; + cur[2 * 32 + 3] = cur_color; + cur[2 * 32 + 4] = cur_color; + cur[2 * 32 + 6] = cur_color; + cur[3 * 32 + 2] = cur_color; + cur[4 * 32 + 2] = cur_color; + cur[5 * 32 + 2] = cur_color; + cur[5 * 32 + 1] = cur_color; + cur[5 * 32 + 0] = cur_color; + + cur[5 * 32 + 5] = cur_color; + + cur[8 * 32 + 4] = cur_color; + cur[8 * 32 + 5] = cur_color; + cur[8 * 32 + 6] = cur_color; + cur[8 * 32 + 7] = cur_color; + cur[9 * 32 + 5] = cur_color; + cur[10 * 32 + 5] = cur_color; + cur[7 * 32 + 8] = cur_color; + cur[6 * 32 + 8] = cur_color; + cur[5 * 32 + 8] = cur_color; + cur[5 * 32 + 9] = cur_color; + cur[5 * 32 + 10] = cur_color; + } + cur_handle = kos_LoadMouseCursor(cur, 0x05050002); + delete[] cur; + kos_SetMouseCursor(cur_handle); +} + +void Menu() +{ + NewGame(); +} + +void NewGame() +{ + gun->DrawAngle((WINDOW_WIDTH / 2) - 5, WINDOW_HEIGHT - 20, G_COLOR); +} + +void OnStart() +{ + if (HARDWARE_CURSOR == 0) + { + cursor = new cCursor(); + } + ChangeCursor(); + + gun->Enable((WINDOW_WIDTH / 2) - 10, WINDOW_HEIGHT - 30, 10, 20, (WINDOW_WIDTH / 2) - 5, WINDOW_HEIGHT - 20); + + for (int i = 0; i < R_COUNT; i++) + { + crosses[i] = new cCross(); + rockets[i] = new cRocket(); + } + for (int i = 0; i < B_COUNT; i++) + { + bombs[i] = new cBomb(); + } + for (int i = 0; i < R_COUNT + B_COUNT; i++) + { + explodes[i] = new cExplode(); + } + + rtlSrand(kos_GetTime()); + + DrawWindow(); + kos_SetMaskForEvents(39); +} + +void OnExit() +{ + kos_WriteTextToWindow(WINDOW_WIDTH / 2 - 35, WINDOW_HEIGHT / 2 - 10, 0, TEXT_COLOR, "Game Over", 9); + + //while(kos_WaitForEvent() != 2); + kos_Pause(200); + + /*kos_DeleteMouseCursor(cur_handle); + + for (int i = 0; i < R_COUNT; i++) + { + delete crosses[i]; + delete rockets[i]; + } + for (int i = 0; i < B_COUNT; i++) + { + delete bombs[i]; + } + for (int i = 0; i < R_COUNT + B_COUNT; i++) + { + delete explodes[i]; + } + delete[] crosses; + delete[] rockets; + delete[] bombs; + delete[] explodes; + + delete gun; + delete house; + if (HARDWARE_CURSOR == 0) + { + delete cursor; + }*/ + + kos_ExitApp(); +} diff --git a/programs/games/rforces/trunk/kosFile.cpp b/programs/games/rforces/trunk/kosFile.cpp new file mode 100644 index 0000000000..1bf8c33fcd --- /dev/null +++ b/programs/games/rforces/trunk/kosFile.cpp @@ -0,0 +1,131 @@ +#include "kosSyst.h" +#include "kosfile.h" + + +CKosFile::CKosFile(char *fileName) +{ + // + this->fileInfo.bufferPtr = new Byte[FILE_BUFFER_SIZE]; + // + this->filePointer = 0; + this->bufferPointer = 0; + this->validBuffer = false; + // + strcpy( this->fileInfo.fileURL, fileName ); +} + + +CKosFile::~CKosFile(void) +{ + // + delete this->fileInfo.bufferPtr; +} + + +void CKosFile::ValidateBuffer() +{ + // + if ( this->validBuffer ) + { + // + if ( this->filePointer < this->bufferPointer + || this->filePointer >= (this->bufferPointer + FILE_BUFFER_SIZE) ) + { + // + this->validBuffer = false; + } + } +} + + +void CKosFile::UpdateBuffer(void) +{ + // + if ( ! this->validBuffer ) + { + // + this->fileInfo.OffsetLow = this->filePointer / OS_BLOCK_SIZE; + this->fileInfo.OffsetHigh = 0; + // + this->bufferPointer = this->fileInfo.OffsetLow * OS_BLOCK_SIZE; + // + this->fileInfo.dataCount = FILE_BUFFER_BLOCKS; + // + this->fileInfo.rwMode = 0; + // + Dword rr = kos_FileSystemAccess( &(this->fileInfo) ); + this->validBuffer = ( rr == 0 ); + } +} + + +int CKosFile::Seek(int seekFrom, int seekStep) +{ + // + switch ( seekFrom ) + { + // + case SEEK_SET: + // + this->filePointer = seekStep; + break; + // + case SEEK_CUR: + // + this->filePointer += seekStep; + break; + } + // + this->ValidateBuffer(); + // + return this->filePointer; +} + + +int CKosFile::Read(Byte *targetPtr, int readCount) +{ + int bufferLeast, result; + + // + result = 0; + // + do + { + // + this->UpdateBuffer(); + // + if ( ! this->validBuffer ) return result; + // + bufferLeast = FILE_BUFFER_SIZE - (this->filePointer - this->bufferPointer); + // + if ( bufferLeast > readCount ) bufferLeast = readCount; + // + if ( bufferLeast ) + { + // + memcpy( + targetPtr, + this->fileInfo.bufferPtr + (this->filePointer - this->bufferPointer), + bufferLeast + ); + // + targetPtr += bufferLeast; + readCount -= bufferLeast; + this->filePointer += bufferLeast; + // + result += bufferLeast; + } + // + this->ValidateBuffer(); + } + while ( readCount > 0 ); + // + return result; +} + + +int CKosFile::Write(Byte *sourcePtr, int writeCount) +{ + return 0; +} + diff --git a/programs/games/rforces/trunk/kosSyst.cpp b/programs/games/rforces/trunk/kosSyst.cpp new file mode 100644 index 0000000000..7f32412691 --- /dev/null +++ b/programs/games/rforces/trunk/kosSyst.cpp @@ -0,0 +1,970 @@ +#include "kosSyst.h" +#include + +#define atexitBufferSize 32 + + +char pureCallMessage[] = "PURE function call!"; + +char *kosExePath = NULL; + +// +void (__cdecl *atExitList[atexitBufferSize])(); +int atExitFnNum = 0; +// +int __cdecl atexit( void (__cdecl *func )( void )) +{ + // + if ( atExitFnNum < atexitBufferSize ) + { + // + atExitList[atExitFnNum++] = func; + return 0; + } + else + { + return 1; + } +} + + +// +Dword RandomSeed = 1; +// +void rtlSrand( Dword seed ) +{ + RandomSeed = seed; +} +// +Dword rtlRand( void ) +{ + //маска 0x80000776 + + Dword dwi, i; + + for ( i = 0; i < 32; i++ ) + { + + dwi = RandomSeed & 0x80000776; + + __asm{ + mov eax, dwi + mov edx, eax + bswap eax + xor eax, edx + xor al, ah + setpo al + movzx eax, al + mov dwi, eax + } + + RandomSeed = ( RandomSeed << 1 ) | ( dwi & 1 ); + } + + return RandomSeed; +} + +// +void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ) +{ + __asm{ + mov edi, dst + mov eax, dst + mov esi, src + mov ecx, bytesCount + rep movsb + } +} + +// +void memset( Byte *dst, Byte filler, Dword count ) +{ + // + __asm{ + mov edi, dst + mov al, filler + mov ecx, count + rep stosb + } +} + +// +Dword rtlInterlockedExchange( Dword *target, Dword value ) +{ +// Dword result; + + // + __asm{ + mov eax, value + mov ebx, target + xchg eax, [ebx] +// mov result, eax + } + // +// return result; +} + + +////////////////////////////////////////////////////////////////////// +// +// копирование строки +// + +char * __cdecl strcpy( char *target, const char *source ) +{ + char *result = target; + + while( target[0] = source[0] ) + { + target++; + source++; + } + + return result; +} + + +////////////////////////////////////////////////////////////////////// +// +// реверсивный поиск символа +// + +char * __cdecl strrchr( const char * string, int c ) +{ + char *cPtr; + + // + for ( cPtr = (char *)string + strlen( string ); cPtr >= string; cPtr-- ) + { + // + if ( *cPtr == c ) return cPtr; + } + // + return NULL; +} + + +////////////////////////////////////////////////////////////////////// +// +// определение длины строки +// + +int __cdecl strlen( const char *line ) +{ + int i; + + for( i=0; line[i] != 0; i++ ); + return i; +} + + + +////////////////////////////////////////////////////////////////////// +// +// перевод шестнадцатиричного числа в символ +// + +unsigned int num2hex( unsigned int num ) +{ + if( num < 10 ) + return num + '0'; + return num - 10 + 'A'; +} + + +////////////////////////////////////////////////////////////////////// +// +// вывод строки на печать +// + +Dword dectab[] = { 1000000000, 100000000, 10000000, 1000000, 100000, + 10000, 1000, 100, 10, 0 }; + +// +void sprintf( char *Str, char* Format, ... ) +{ + int i, fmtlinesize, j, k, flag; + Dword head, tail; + char c; + va_list arglist; + // + va_start(arglist, Format); + + // + fmtlinesize = strlen( Format ); + // + if( fmtlinesize == 0 ) return; + + // + for( i = 0, j = 0; i < fmtlinesize; i++ ) + { + // + c = Format[i]; + // + if( c != '%' ) + { + Str[j++] = c; + continue; + } + // + i++; + // + if( i >= fmtlinesize ) break; + + // + flag = 0; + // + c = Format[i]; + // + switch( c ) + { + // + case '%': + Str[j++] = c; + break; + // вывод строки + case 'S': + Byte* str; + str = va_arg(arglist, Byte*); + for( k = 0; ( c = str[k] ) != 0; k++ ) + { + Str[j++] = c; + } + break; + // вывод байта + case 'B': + k = va_arg(arglist, int) & 0xFF; + Str[j++] = num2hex( ( k >> 4 ) & 0xF ); + Str[j++] = num2hex( k & 0xF ); + break; + // вывод символа + case 'C': + Str[j++] = va_arg(arglist, int) & 0xFF; + break; + // вывод двойного слова в шестнадцатиричном виде + case 'X': + Dword val; + val = va_arg(arglist, Dword); + for( k = 7; k >= 0; k-- ) + { + // + c = num2hex ( ( val >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + if( flag == 0 ) Str[j++] = '0'; + break; + // вывод двойного слова в десятичном виде + case 'U': + head = va_arg(arglist, Dword); + tail = 0; + for( k = 0; dectab[k] != 0; k++ ) + { + tail = head % dectab[k]; + head /= dectab[k]; + c = head + '0'; + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + // + head = tail; + } + // + c = head + '0'; + Str[j++] = c; + break; + // вывод 64-битного слова в шестнадцатиричном виде + case 'Q': + unsigned int low_dword, high_dword; + low_dword = va_arg(arglist, unsigned int); + high_dword = va_arg(arglist, unsigned int); + for( k = 7; k >= 0; k-- ) + { + // + c = num2hex ( ( ( high_dword + 1) >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + for( k=7; k >= 0; k-- ) + { + // + c = num2hex ( ( low_dword >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + if( flag == 0 ) Str[j++] = '0'; + // + break; + // + default: + break; + } + } + // + Str[j] = 0; +} + + +// функция -1 завершения процесса +void kos_ExitApp() +{ + int i; + + // + for ( i = atExitFnNum - 1; i >= 0; i-- ) + { + // + atExitList[i](); + } + // + __asm{ + mov eax, -1 + int 0x40 + } +} + + +// функция 0 +void kos_DefineAndDrawWindow( + Word x, Word y, + Word sizeX, Word sizeY, + Byte mainAreaType, + Dword mainAreaColour, + Byte headerType, + Dword headerColour, + Dword borderColour + ) +{ + Dword arg1, arg2, arg3, arg4; + + // + arg1 = ( x << 16 ) + sizeX; + arg2 = ( y << 16 ) + sizeY; + arg3 = ( mainAreaType << 24 ) | mainAreaColour; + arg4 = ( headerType << 24 ) | headerColour; + // + __asm{ + mov eax, 0 + mov ebx, arg1 + mov ecx, arg2 + mov edx, arg3 + mov esi, arg4 + mov edi, borderColour + int 0x40 + } +} + + +// функция 1 поставить точку +void kos_PutPixel( Dword x, Dword y, Dword colour ) +{ + // + __asm{ + mov eax, 1 + mov ebx, x + mov ecx, y + mov edx, colour + int 0x40 + } +} + + +// функция 2 получить код нажатой клавиши +bool kos_GetKey( Byte &keyCode ) +{ + Dword result; + + // + __asm{ + mov eax, 2 + int 0x40 + mov result, eax + } + // + keyCode = result >> 8; + // + return ( result & 0xFF ) == 0; +} + + +// функция 3 получить время +Dword kos_GetSystemClock() +{ +// Dword result; + + // + __asm{ + mov eax, 3 + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 4 +void kos_WriteTextToWindow( + Word x, + Word y, + Byte fontType, + Dword textColour, + char *textPtr, + Dword textLen + ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | y; + arg2 = ( fontType << 24 ) | textColour; + // + __asm{ + mov eax, 4 + mov ebx, arg1 + mov ecx, arg2 + mov edx, textPtr + mov esi, textLen + int 0x40 + } +} + + +// функция 5 пауза, в сотых долях секунды +void kos_Pause( Dword value ) +{ + // + __asm{ + mov eax, 5 + mov ebx, value + int 0x40 + } +} + + +// функция 7 нарисовать изображение +void kos_PutImage( RGB * imagePtr, Word sizeX, Word sizeY, Word x, Word y ) +{ + Dword arg1, arg2; + + // + arg1 = ( sizeX << 16 ) | sizeY; + arg2 = ( x << 16 ) | y; + // + __asm{ + mov eax, 7 + mov ebx, imagePtr + mov ecx, arg1 + mov edx, arg2 + int 0x40 + } +} + + + +// функция 8 определить кнопку +void kos_DefineButton( Word x, Word y, Word sizeX, Word sizeY, Dword buttonID, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | sizeX; + arg2 = ( y << 16 ) | sizeY; + // + __asm{ + mov eax, 8 + mov ebx, arg1 + mov ecx, arg2 + mov edx, buttonID + mov esi, colour + int 0x40 + } +} + + +// функция 9 - информация о процессе +Dword kos_ProcessInfo( sProcessInfo *targetPtr, Dword processID ) +{ +// Dword result; + + // + __asm{ + mov eax, 9 + mov ebx, targetPtr + mov ecx, processID + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 10 +Dword kos_WaitForEvent() +{ +// Dword result; + + __asm{ + mov eax, 10 + int 0x40 +// mov result, eax + } + +// return result; +} + + +// функция 11 +Dword kos_CheckForEvent() +{ +// Dword result; + + __asm{ + mov eax, 11 + int 0x40 +// mov result, eax + } + +// return result; +} + + +// функция 12 +void kos_WindowRedrawStatus( Dword status ) +{ + __asm{ + mov eax, 12 + mov ebx, status + int 0x40 + } +} + + +// функция 13 нарисовать полосу +void kos_DrawBar( Word x, Word y, Word sizeX, Word sizeY, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | sizeX; + arg2 = ( y << 16 ) | sizeY; + // + __asm{ + mov eax, 13 + mov ebx, arg1 + mov ecx, arg2 + mov edx, colour + int 0x40 + } +} + + +// функция 17 +bool kos_GetButtonID( Dword &buttonID ) +{ + Dword result; + + // + __asm{ + mov eax, 17 + int 0x40 + mov result, eax + } + // + buttonID = result >> 8; + // + return (result & 0xFF) == 0; +} + + +// функция 23 +Dword kos_WaitForEvent( Dword timeOut ) +{ +// Dword result; + + __asm{ + mov eax, 23 + mov ebx, timeOut + int 0x40 +// mov result, eax + } + +// return result; +} + +// функция 26.9 получить значение счётчика времени +Dword kos_GetTime() +{ + __asm{ + mov eax, 26 + mov ebx, 9 + int 0x40 + } +} + +// функция 37 получение информации о состоянии "мыши" +void kos_GetMouseState( Dword & buttons, int & cursorX, int & cursorY ) +{ + Dword mB; + Word curX; + Word curY; + sProcessInfo sPI; + + // + __asm{ + mov eax, 37 + mov ebx, 0 + int 0x40 + mov curY, ax + shr eax, 16 + mov curX, ax + mov eax, 37 + mov ebx, 2 + int 0x40 + mov mB, eax + } + // + kos_ProcessInfo( &sPI ); + // + buttons = mB; + cursorX = curX - sPI.processInfo.x_start; + cursorY = curY - sPI.processInfo.y_start; +} + +// функция 37.1 получение координат "мыши" относительно окна +void kos_GetMouseWindowXY( int & cursorX, int & cursorY ) +{ + Word curX; + Word curY; + + __asm{ + mov eax, 37 + mov ebx, 1 + int 0x40 + + mov ebx, eax + shr eax, 16 + and ebx, 0xffff + + mov curX, ax + mov curY, bx + } + + cursorX = curX; + cursorY = curY; +} + +// функция 37.2 получение информации о нажатых кнопки "мыши" +void kos_GetMouseButtonsState( Dword & buttons ) +{ + Dword mB; + + __asm{ + mov eax, 37 + mov ebx, 2 + int 0x40 + mov mB, eax + } + + buttons = mB; +} + +// функция 37.4 загрузка курсора "мыши" +Dword * kos_LoadMouseCursor( Dword * cursor, Dword loadstate ) +{ + //Dword handle; + __asm{ + mov eax, 37 + mov ebx, 4 + mov edx, loadstate + mov ecx, cursor + int 0x40 + //mov handle, eax + } + //return handle; +} + +// функция 37.5 установка курсора "мыши" +Dword * kos_SetMouseCursor( Dword * handle ) +{ + //Dword handle; + __asm{ + mov eax, 37 + mov ebx, 5 + mov ecx, handle + int 0x40 + //mov handle, eax + } + //return handle; +} + +// функция 37.6 удаление курсора "мыши" +void kos_DeleteMouseCursor( Dword * handle ) +{ + __asm{ + mov eax, 37 + mov ebx, 6 + mov ecx, handle + int 0x40 + } +} + +// функция 38 нарисовать полосу +void kos_DrawLine( Word x1, Word y1, Word x2, Word y2, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x1 << 16 ) | x2; + arg2 = ( y1 << 16 ) | y2; + // + __asm{ + mov eax, 38 + mov ebx, arg1 + mov ecx, arg2 + mov edx, colour + int 0x40 + } +} + + +// функция 40 установить маску событий +void kos_SetMaskForEvents( Dword mask ) +{ + // + __asm{ + mov eax, 40 + mov ebx, mask + int 0x40 + } +} + + +// функция 47 вывести в окно приложения число +void kos_DisplayNumberToWindow( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + eNumberBase nBase, + bool valueIsPointer + ) +{ + Dword arg1, arg2; + + // + arg1 = ( valueIsPointer ? 1 : 0 ) | + ( ((Byte)nBase) << 8 ) | + ( ( digitsNum & 0x1F ) << 16 ); + arg2 = ( x << 16 ) | y; + // + __asm{ + mov eax, 47 + mov ebx, arg1 + mov ecx, value + mov edx, arg2 + mov esi, colour + int 0x40 + } +} + +// функция 47 вывести в окно приложения число c фоном +void kos_DisplayNumberToWindowBg( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + Dword bgcolour, + eNumberBase nBase, + bool valueIsPointer + ) +{ + Dword arg1, arg2; + + // + arg1 = ( valueIsPointer ? 1 : 0 ) | + ( ((Byte)nBase) << 8 ) | + ( ( digitsNum & 0x1F ) << 16 ); + arg2 = ( x << 16 ) | y; + // + __asm{ + mov eax, 47 + mov ebx, arg1 + mov ecx, value + mov edx, arg2 + mov esi, colour + or esi, 0x40000000 + mov edi, bgcolour + int 0x40 + } +} + + +// функция 70 доступ к файловой системе +Dword kos_FileSystemAccess( kosFileInfo *fileInfo ) +{ +// Dword result; + + // + __asm{ + mov eax, 70 + mov ebx, fileInfo + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 63 вывод символя в окно отладки +void kos_DebugOutChar( char ccc ) +{ + // + __asm{ + mov eax, 63 + mov ebx, 1 + mov cl, ccc + int 0x40 + } +} + + +// функция 66 режим получения данных от клавиатуры +void kos_SetKeyboardDataMode( Dword mode ) +{ + // + __asm{ + mov eax, 66 + mov ebx, 1 + mov ecx, mode + int 0x40 + } +} + + +// вывод строки в окно отладки +void rtlDebugOutString( char *str ) +{ + // + for ( ; str[0] != 0; str++ ) + { + kos_DebugOutChar( str[0] ); + } + // + kos_DebugOutChar( 13 ); + kos_DebugOutChar( 10 ); +} + + +// функция 64 изменение количества памяти, выделенной для программы +bool kos_ApplicationMemoryResize( Dword targetSize ) +{ + Dword result; + + // + __asm{ + mov eax, 64 + mov ebx, 1 + mov ecx, targetSize + int 0x40 + mov result, eax + } + // + return result == 0; +} + + +// функция 67 изменить параметры окна, параметр == -1 не меняется +void kos_ChangeWindow( Dword x, Dword y, Dword sizeX, Dword sizeY ) +{ + // + __asm{ + mov eax, 67 + mov ebx, x + mov ecx, y + mov edx, sizeX + mov esi, sizeY + int 0x40 + } +} + + + +// вызов абстрактного метода +int __cdecl _purecall() +{ + rtlDebugOutString( pureCallMessage ); + kos_ExitApp(); + return 0; +} + + +// вызов статических инициализаторов +// заодно инициализация генератора случайных чисел +//#pragma section(".CRT$XCA",long,read,write) +//#pragma section(".CRT$XCZ",long,read,write) +#pragma data_seg(".CRT$XCA") +#pragma data_seg(".CRT$XCZ") +typedef void (__cdecl *_PVFV)(void); +__declspec(allocate(".CRT$XCA")) _PVFV __xc_a[1] = { NULL }; +__declspec(allocate(".CRT$XCZ")) _PVFV __xc_z[1] = { NULL }; +// +#pragma comment(linker, "/merge:.CRT=.rdata") +// +void crtStartUp() +{ + // вызываем инициализаторы по списку, NULL'ы игнорируем + for ( _PVFV *pbegin = __xc_a; pbegin < __xc_z; pbegin++ ) + { + // + if ( *pbegin != NULL ) + (**pbegin)(); + } + // инициализируем генератор случайных чисел + rtlSrand( kos_GetSystemClock() ); + // путь к файлу процесса + kosExePath = *((char **)0x20); + // вызов главной функции приложения + kos_Main(); + // выход + kos_ExitApp(); +} + + diff --git a/programs/games/rforces/trunk/kosSyst.h b/programs/games/rforces/trunk/kosSyst.h new file mode 100644 index 0000000000..a69c4b8bc5 --- /dev/null +++ b/programs/games/rforces/trunk/kosSyst.h @@ -0,0 +1,220 @@ +typedef unsigned __int32 Dword; +typedef unsigned __int16 Word; +typedef unsigned __int8 Byte; +//typedef unsigned __int32 size_t; + +#define NULL 0 + +#define MAX_PATH 256 + +#define FO_READ 0 +#define FO_WRITE 2 + +#define EM_WINDOW_REDRAW 1 +#define EM_KEY_PRESS 2 +#define EM_BUTTON_CLICK 4 +#define EM_APP_CLOSE 8 +#define EM_DRAW_BACKGROUND 16 +#define EM_MOUSE_EVENT 32 +#define EM_IPC 64 +#define EM_NETWORK 256 + +#define KM_CHARS 0 +#define KM_SCANS 1 + +#define WRS_BEGIN 1 +#define WRS_END 2 + +#define PROCESS_ID_SELF -1 + +#define abs(a) (a<0?0-a:a) + + +struct kosFileInfo +{ + Dword rwMode; + Dword OffsetLow; + Dword OffsetHigh; + Dword dataCount; + Byte *bufferPtr; + char fileURL[MAX_PATH]; +}; + + +struct RGB +{ + Byte b; + Byte g; + Byte r; + // + RGB() {}; + // + RGB( Dword value ) + { + r = value >> 16; + g = value >> 8; + b = value; + }; + // + bool operator != ( RGB &another ) + { + return this->b != another.b || this->g != another.g || this->r != another.r; + }; + // + bool operator == ( RGB &another ) + { + return this->b == another.b && this->g == another.g && this->r == another.r; + }; +}; + + +union sProcessInfo +{ + Byte rawData[1024]; + struct + { + Dword cpu_usage; + Word window_stack_position; + Word window_stack_value; + Word reserved1; + char process_name[12]; + Dword memory_start; + Dword used_memory; + Dword PID; + Dword x_start; + Dword y_start; + Dword x_size; + Dword y_size; + Word slot_state; + } processInfo; +}; + +// +extern char *kosExePath; + +// +void crtStartUp(); +// +int __cdecl _purecall(); +// +int __cdecl atexit( void (__cdecl *func )( void )); +// +void rtlSrand( Dword seed ); +Dword rtlRand( void ); +// +char * __cdecl strcpy( char *target, const char *source ); +int __cdecl strlen( const char *line ); +char * __cdecl strrchr( const char * string, int c ); +// +void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ); +// +void memset( Byte *dst, Byte filler, Dword count ); +// +void sprintf( char *Str, char* Format, ... ); +// +Dword rtlInterlockedExchange( Dword *target, Dword value ); +// функция -1 завершения процесса +void kos_ExitApp(); +// функция 0 +void kos_DefineAndDrawWindow( + Word x, Word y, + Word sizeX, Word sizeY, + Byte mainAreaType, Dword mainAreaColour, + Byte headerType, Dword headerColour, + Dword borderColour + ); +// функция 1 поставить точку +void kos_PutPixel( Dword x, Dword y, Dword colour ); +// функция 2 получить код нажатой клавиши +bool kos_GetKey( Byte &keyCode ); +// функция 3 получить время +Dword kos_GetSystemClock(); +// функция 4 +void kos_WriteTextToWindow( + Word x, Word y, + Byte fontType, + Dword textColour, + char *textPtr, + Dword textLen + ); +// функция 7 нарисовать изображение +void kos_PutImage( RGB * imagePtr, Word sizeX, Word sizeY, Word x, Word y ); +// функция 8 определить кнопку +void kos_DefineButton( Word x, Word y, Word sizeX, Word sizeY, Dword buttonID, Dword colour ); +// функция 5 пауза, в сотых долях секунды +void kos_Pause( Dword value ); +// функция 9 информация о процессе +Dword kos_ProcessInfo( sProcessInfo *targetPtr, Dword processID = PROCESS_ID_SELF ); +// функция 10 +Dword kos_WaitForEvent(); +// функция 11 +Dword kos_CheckForEvent(); +// функция 12 +void kos_WindowRedrawStatus( Dword status ); +// функция 13 нарисовать прямоугольник +void kos_DrawBar( Word x, Word y, Word sizeX, Word sizeY, Dword colour ); +// функция 17 +bool kos_GetButtonID( Dword &buttonID ); +// функция 23 +Dword kos_WaitForEvent( Dword timeOut ); +// функция 26.9 получить значение счётчика времени +Dword kos_GetTime(); +// +enum eNumberBase +{ + nbDecimal = 0, + nbHex, + nbBin +}; +// функция 37 получение информации о состоянии "мыши" +void kos_GetMouseState( Dword & buttons, int & cursorX, int & cursorY ); +// функция 37.1 получение координат "мыши" относительно окна +void kos_GetMouseWindowXY( int & cursorX, int & cursorY ); +// функция 37.2 получение информации о нажатых кнопки "мыши" +void kos_GetMouseButtonsState( Dword & buttons ); +// функция 37.4 загрузка курсора "мыши" +Dword * kos_LoadMouseCursor( Dword * cursor, Dword loadstate ); +// функция 37.5 установка курсора "мыши" +Dword * kos_SetMouseCursor( Dword * handle ); +// функция 37.6 удаление курсора "мыши" +void kos_DeleteMouseCursor( Dword * handle ); +// функция 38 нарисовать полосу +void kos_DrawLine( Word x1, Word y1, Word x2, Word y2, Dword colour ); +// функция 40 установить маску событий +void kos_SetMaskForEvents( Dword mask ); +// функция 47 вывести в окно приложения число +void kos_DisplayNumberToWindow( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + eNumberBase nBase = nbDecimal, + bool valueIsPointer = false + ); +// функция 47 вывести в окно приложения число c фоном +void kos_DisplayNumberToWindowBg( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + Dword bgcolour, + eNumberBase nBase = nbDecimal, + bool valueIsPointer = false + ); +// функция 58 доступ к файловой системе +Dword kos_FileSystemAccess( kosFileInfo *fileInfo ); +// функция 63 +void kos_DebugOutChar( char ccc ); +// +void rtlDebugOutString( char *str ); +// функция 64 изменить параметры окна, параметр == -1 не меняется +void kos_ChangeWindow( Dword x, Dword y, Dword sizeX, Dword sizeY ); +// функция 67 изменение количества памяти, выделенной для программы +bool kos_ApplicationMemoryResize( Dword targetSize ); +// функция 66 режим получения данных от клавиатуры +void kos_SetKeyboardDataMode( Dword mode ); + +// +void kos_Main(); diff --git a/programs/games/rforces/trunk/mcsmemm.cpp b/programs/games/rforces/trunk/mcsmemm.cpp new file mode 100644 index 0000000000..20feab80f6 --- /dev/null +++ b/programs/games/rforces/trunk/mcsmemm.cpp @@ -0,0 +1,329 @@ +// memman.cpp : Defines the entry point for the console application. +// + +#include "kosSyst.h" +#include "mcsmemm.h" + + +void * __cdecl operator new ( size_t count, size_t element_size ) +{ + return allocmem( (Dword)(count * element_size) ); +} + +void * __cdecl operator new [] ( size_t amount ) +{ + return allocmem( (Dword)amount ); +} + +void * __cdecl operator new ( size_t amount ) +{ + return allocmem( (Dword)amount ); +} + +void __cdecl operator delete ( void *pointer ) +{ + if ( pointer != NULL ) freemem( pointer ); +} + +void __cdecl operator delete [] ( void *pointer ) +{ + if ( pointer != NULL ) freemem( pointer ); +} + + +// +Dword mmMutex = FALSE; +MemBlock *rootfree = NULL; +MemBlock *rootuser = NULL; +bool mmInitialized = false; +Byte *mmHeapTop = NULL; + + +// +Byte * AllocMemFromSystem( Dword reqSize ) +{ + Byte *result; + sProcessInfo pInfo; + + // + if ( mmInitialized ) + { + result = mmHeapTop; + } + else + { + // + kos_ProcessInfo( &pInfo ); + // + result = (Byte *)(pInfo.processInfo.used_memory + 1); + // + mmInitialized = true; + } + // + if ( ! kos_ApplicationMemoryResize( ((Dword)result) + reqSize ) ) + { + result = NULL; + } + // + mmHeapTop = result + reqSize; + // + return result; +} + + +// +Byte *allocmem( Dword reqsize ) +{ + MemBlock *BlockForCheck; + MemBlock *LastKnownGood; + Dword tail; + Byte *address; + + //подровняем размер + if( ( tail = reqsize % SIZE_ALIGN ) != 0 ) + { + reqsize += SIZE_ALIGN - tail; + } + + LastKnownGood = NULL; + + // ждём освобождения мьютекса + while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) + { + // + kos_Pause( 1 ); + } + + //ищем подходящий свободный блок + if( rootfree != NULL ) + { + for ( BlockForCheck = rootfree; ; BlockForCheck = BlockForCheck->Next ) + { + if ( BlockForCheck->Size >= reqsize ) + { + //нашли + if ( LastKnownGood != NULL ) + { + if ( LastKnownGood->Size >= BlockForCheck->Size ) + LastKnownGood = BlockForCheck; + } + else + LastKnownGood = BlockForCheck; + if ( LastKnownGood->Size == reqsize ) + break; + } + if ( BlockForCheck->Next == NULL ) + break; + } + } + + if ( LastKnownGood != NULL ) + { + //проверим найденный блок на возможность деления + tail = LastKnownGood->Size - reqsize; + if ( tail >= ( sizeof(MemBlock) + SIZE_ALIGN ) ) + { + //будем разбивать + BlockForCheck = (MemBlock *)( ( (Byte *)LastKnownGood ) + tail ); + BlockForCheck->Size = reqsize; + //вставим занятый блок в начало списка занатых блоков + if( rootuser != NULL ) + { + BlockForCheck->Next = rootuser; + rootuser->Previous = BlockForCheck; + BlockForCheck->Previous = NULL; + rootuser = BlockForCheck; + } + else + { + rootuser = BlockForCheck; + BlockForCheck->Next = NULL; + BlockForCheck->Previous = NULL; + } + + //изменим размер оставшейся части + LastKnownGood->Size = tail - sizeof(MemBlock); + address = ( (Byte *)BlockForCheck ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + else + { + //перемести блок из очереди свободных в начало очереди занятых + //сначала выкинем его из очереди свободных + if ( LastKnownGood->Previous != NULL ) + { + LastKnownGood->Previous->Next = LastKnownGood->Next; + } + else + { + //блок стоит в начале очереди + rootfree = LastKnownGood->Next; + } + if( LastKnownGood->Next != NULL ) + { + LastKnownGood->Next->Previous = LastKnownGood->Previous; + } + //теперь вставим его в очередь занятых + if( rootuser != NULL ) + { + LastKnownGood->Next = rootuser; + rootuser->Previous = LastKnownGood; + LastKnownGood->Previous = NULL; + rootuser = LastKnownGood; + } + else + { + rootuser = LastKnownGood; + LastKnownGood->Next = NULL; + LastKnownGood->Previous = NULL; + } + // + address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + } + else + { + //надо получить ещё кусочек памяти + LastKnownGood = (MemBlock *)AllocMemFromSystem( reqsize + sizeof(MemBlock) ); + // + if( LastKnownGood != NULL ) + { + LastKnownGood->Size = reqsize; + //теперь вставим его в очередь занятых + if( rootuser != NULL ) + { + LastKnownGood->Next = rootuser; + rootuser->Previous = LastKnownGood; + LastKnownGood->Previous = NULL; + rootuser = LastKnownGood; + } + else + { + rootuser = LastKnownGood; + LastKnownGood->Next = NULL; + LastKnownGood->Previous = NULL; + } + address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + } + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + // + rtlDebugOutString( "allocmem failed." ); + kos_ExitApp(); + // + return NULL; +} + +// +Dword freemem( void *vaddress ) +{ + Dword result; + + Byte *checknext, *address = (Byte *)vaddress; + + // ждём освобождения мьютекса + while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) + { + // + kos_Pause( 1 ); + } + + MemBlock *released = (MemBlock *)( address - sizeof(MemBlock) ); + + result = released->Size; + + //убираем блок из списка занятых + if ( released->Previous != NULL ) + { + released->Previous->Next = released->Next; + } + else + { + rootuser = released->Next; + } + if ( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //закинем теперь этот блок в список свободных + released->Next = rootfree; + released->Previous = NULL; + rootfree = released; + if ( released->Next != NULL ) + { + released->Next->Previous = released; + } + + //теперь поищем смежные свободные блоки + checknext = (Byte *)(rootfree) + ( rootfree->Size + sizeof(MemBlock) ); + // + for ( released = rootfree->Next; released != NULL; released = released->Next ) + { + if ( checknext == (Byte *)released ) + { + //собираем блоки вместе + //сначала выкинем из очереди свободных + released->Previous->Next = released->Next; + if( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //теперь увеличим размер корневого блока + rootfree->Size += released->Size + sizeof(MemBlock); + break; + } + } + //если надо, поищем блоки перед текщим. + checknext = (Byte *)(rootfree); + // + if ( released == NULL ) + { + for ( released = rootfree->Next; released != NULL; released = released->Next ) + { + if ( checknext == (Byte *)released + ( released->Size + sizeof(MemBlock) ) ) + { + //собираем блоки вместе + //увеличим размер блока + released->Size += rootfree->Size + sizeof(MemBlock); + //теперь выкинем из очереди свободных + released->Previous->Next = released->Next; + if ( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //и закинем его в начало очереди вместо присоединённого блока из корня списка + if ( rootfree->Next != NULL ) + { + rootfree->Next->Previous = released; + } + released->Next = rootfree->Next; + released->Previous = NULL; + rootfree = released; + break; + } + } + } + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return result; +} + diff --git a/programs/games/rforces/trunk/mcsmemm.h b/programs/games/rforces/trunk/mcsmemm.h new file mode 100644 index 0000000000..42d61eaadb --- /dev/null +++ b/programs/games/rforces/trunk/mcsmemm.h @@ -0,0 +1,28 @@ +// + +struct MemBlock +{ + Dword Size; + Dword Addr; + MemBlock *Next; + MemBlock *Previous; +}; + + +#define INITIALQUEUESIZE (32 * 4) + +#define FALSE 0 +#define TRUE -1 + +#define MB_FREE 0 +#define MB_USER 1 + +#define SIZE_ALIGN 4 + + + +Byte *allocmem( Dword reqsize ); +Dword freemem( void *vaddress ); + + + diff --git a/programs/games/rforces/trunk/mymath.h b/programs/games/rforces/trunk/mymath.h new file mode 100644 index 0000000000..6d911d875c --- /dev/null +++ b/programs/games/rforces/trunk/mymath.h @@ -0,0 +1,95 @@ +/* Rocket Forces + * Filename: mymath.h + * Version 0.1 + * Copyright (c) Serial 2007 + */ + + +extern "C" int _fltused = 0; + +#define M_PI 3.14159265358979323846 + +inline double sin(double x) +{ + __asm fld x + __asm fsin +} + +inline double cos(double x) +{ + __asm fld x + __asm fcos +} + +inline double sqrt(double x) +{ + __asm fld x + __asm fsqrt +} + +inline double acos(double x) +{ + __asm fld x + __asm fld st(0) + __asm fmul st,st(1) + __asm fld1 + __asm fsubrp st(1),st(0) + __asm fsqrt + __asm fxch st(1) + __asm fpatan +} + +inline double atan(double x) +{ + double res = acos(1 / sqrt(1 + x * x)); + if (x < 0) + { + res *= -1; + } + return res; +} + +inline int round_int(double x) +{ + int i; + static const float round_to_nearest = 0.5f; + __asm + { + fld x + fadd st, st(0) + fadd round_to_nearest + fistp i + sar i, 1 + } + return i; +} + +inline int floor_int(double x) +{ + int i; + static const float round_toward_m_i = -0.5f; + __asm + { + fld x + fadd st, st (0) + fadd round_toward_m_i + fistp i + sar i, 1 + } + return i; +} + +inline int ceil_int(double x) +{ + int i; + static const float round_toward_p_i = -0.5f; + __asm + { + fld x + fadd st, st (0) + fsubr round_toward_p_i + fistp i + sar i, 1 + } + return (-i); +} diff --git a/programs/games/rforces/trunk/objects.h b/programs/games/rforces/trunk/objects.h new file mode 100644 index 0000000000..c9c36a3c71 --- /dev/null +++ b/programs/games/rforces/trunk/objects.h @@ -0,0 +1,466 @@ +/* Rocket Forces + * Filename: objects.h + * Version 0.1 + * Copyright (c) Serial 2007 + */ + + +void ppx(int x, int y, int color); +void pline(int x1, int y1, int x2, int y2, int color); +void draw4(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int color); + + +class cBuilding +{ +public: + void Draw(int x, int y, int color) + { + draw4(x, y, x+10, y-5, x+20, y, x, y, color); + draw4(x, y, x+20, y, x+20, y+11, x, y+11, color); + draw4(x+3, y+3, x+8, y+3, x+8, y+8, x+3, y+8, color); + draw4(x+15, y+3, x+20, y+3, x+20, y+11, x+15, y+11, color); + } +}; + +class cCursor +{ +public: + cCursor() + { + cx = -1; + cy = -1; + } + void Delete(int color) + { + ppx(cx, cy, color); + + ppx(cx-3, cy, color); + ppx(cx-4, cy, color); + ppx(cx-5, cy, color); + ppx(cx, cy-3, color); + ppx(cx, cy-4, color); + ppx(cx, cy-5, color); + ppx(cx-1, cy-3, color); + ppx(cx-2, cy-3, color); + ppx(cx-3, cy-3, color); + ppx(cx-3, cy-2, color); + ppx(cx-3, cy-1, color); + ppx(cx+1, cy-3, color); + + ppx(cx+3, cy, color); + ppx(cx+4, cy, color); + ppx(cx+5, cy, color); + ppx(cx, cy+3, color); + ppx(cx, cy+4, color); + ppx(cx, cy+5, color); + ppx(cx+1, cy+3, color); + ppx(cx+2, cy+3, color); + ppx(cx+3, cy+3, color); + ppx(cx+3, cy+2, color); + ppx(cx+3, cy+1, color); + ppx(cx+1, cy-3, color); + ppx(cx-1, cy+3, color); + } + void Draw(int x, int y, int color) + { + if (cx!=x || cy!=y) + { + Delete(BG_COLOR); + cx = x; + cy = y; + ppx(cx, cy, color); + + ppx(cx-3, cy, color); + ppx(cx-4, cy, color); + ppx(cx-5, cy, color); + ppx(cx, cy-3, color); + ppx(cx, cy-4, color); + ppx(cx, cy-5, color); + ppx(cx-1, cy-3, color); + ppx(cx-2, cy-3, color); + //ppx(cx-3, cy-3, color); + ppx(cx-3, cy-2, color); + ppx(cx-3, cy-1, color); + ppx(cx+1, cy-3, color); + + ppx(cx+3, cy, color); + ppx(cx+4, cy, color); + ppx(cx+5, cy, color); + ppx(cx, cy+3, color); + ppx(cx, cy+4, color); + ppx(cx, cy+5, color); + ppx(cx+1, cy+3, color); + ppx(cx+2, cy+3, color); + //ppx(cx+3, cy+3, color); + ppx(cx+3, cy+2, color); + ppx(cx+3, cy+1, color); + ppx(cx+1, cy-3, color); + ppx(cx-1, cy+3, color); + } + } +private: + int cx, cy; +}; + +class cExplode +{ +public: + cExplode() + { + cx = -1; + cy = -1; + } + void Enable(int cx, int cy) + { + step = 1; + cExplode::cx = cx; + cExplode::cy = cy; + } + int IsEnabled(void) + { + if (cx==-1 && cy==-1) + { + return 0; + } + else + { + return 1; + } + } + void Draw(int r, int color) + { + int d=3-2*r, x=-1, y=r; + while (x++=EXP_RAD) + { + Disable(BG_COLOR); + } + else + { + Draw(step, BG_COLOR); + Draw(++step, color); + } + } + void Disable(int color) + { + Draw(step, color); + cx = -1; + cy = -1; + } + int cx, cy; + int step; +}; + +class cRocket +{ +public: + cRocket() + { + cx = -1; + cy = -1; + } + void Enable(int x, int y, int width, int height, int cx, int cy) + { + coord[0][0] = x; + coord[0][1] = y; + coord[1][0] = x+width; + coord[1][1] = y; + coord[2][0] = x+width; + coord[2][1] = y+height; + coord[3][0] = x; + coord[3][1] = y+height; + cRocket::cx = cx; + cRocket::cy = cy; + for (int j=0; j<4; j++) + { + dist[j] = sqrt((double)((coord[j][0]-cx)*(coord[j][0]-cx)+(coord[j][1]-cy)*(coord[j][1]-cy))); + fi[j] = acos((coord[j][0]-cx)/dist[j]); + if (coord[j][1]0; i--) + { + fire[i][0] = fire[i-1][0]; + fire[i][1] = fire[i-1][1]; + } + fire[0][0] = cx; + fire[0][1] = cy; + for (int i=1; i<4; i++) + { + if (fire[i][0]!=-1 || fire[i][1]!=-1) ppx(fire[i][0], fire[i][1], SMOKE_COLOR); + } + } + void Disable(int color) + { + for (int i=0; i<4; i++) + { + ppx(fire[i][0], fire[i][1], color); + fire[i][0] = 0; + fire[i][1] = 0; + } + Draw(color); + cx = -1; + cy = -1; + } + int cx, cy; + protected: + int coord[4][2]; + double dist[4]; + double fi[4]; + int fire[4][2]; +}; + +class cBomb: public cRocket +{ +public: + void Draw(int color) + { + draw4(coord[0][0], coord[0][1], coord[1][0], coord[1][1], coord[2][0], coord[2][1], coord[3][0], coord[3][1], color); + ppx(cx-1, coord[2][1]+1, color); + ppx(cx, coord[2][1]+1, color); + ppx(cx+1, coord[2][1]+1, color); + for (int i=1; i<4; i++) + { + if (fire[i][0]!=-1 || fire[i][1]!=-1) + { + if (i==1) + { + ppx(fire[i][0]-1, fire[i][1], BG_COLOR); + ppx(fire[i][0]+1, fire[i][1], BG_COLOR); + } + else + { + ppx(fire[i][0], fire[i][1], BG_COLOR); + } + } + } + } + void DrawAngle(int mx, int my, int color) + { + // Delete old rectangle + Draw(BG_COLOR); + + // Draw new rectangle + for (int j=0; j<4; j++) + { + coord[j][1] += B_SPEED; + } + draw4(coord[0][0], coord[0][1], coord[1][0], coord[1][1], coord[2][0], coord[2][1], coord[3][0], coord[3][1], color); + ppx(cx-1, coord[2][1]+1, color); + ppx(cx, coord[2][1]+1, color); + ppx(cx+1, coord[2][1]+1, color); + for (int i=3; i>0; i--) + { + fire[i][0] = fire[i-1][0]; + fire[i][1] = fire[i-1][1]; + } + fire[0][0] = cx; + fire[0][1] = cy; + for (int i=1; i<4; i++) + { + if (fire[i][0]!=-1 || fire[i][1]!=-1) + { + if (i==1) + { + ppx(fire[i][0]-1, fire[i][1], SMOKE_COLOR); + ppx(fire[i][0]+1, fire[i][1], SMOKE_COLOR); + } + else + { + ppx(fire[i][0], fire[i][1], SMOKE_COLOR); + } + } + } + } + void Disable(int color) + { + for (int i=0; i<4; i++) + { + ppx(fire[i][0], fire[i][1], color); + fire[i][0] = 0; + fire[i][1] = 0; + } + Draw(color); + cx = -1; + cy = -1; + } +}; + +class cGun: public cRocket +{ +public: + void Enable(int x, int y, int width, int height, int cx, int cy) + { + old_mx = -1; + old_my = -1; + coord[0][0] = x; + coord[0][1] = y; + coord[1][0] = x+width; + coord[1][1] = y; + coord[2][0] = x+width; + coord[2][1] = y+height; + coord[3][0] = x; + coord[3][1] = y+height; + cRocket::cx = cx; + cRocket::cy = cy; + for (int j=0; j<4; j++) + { + dist[j] = sqrt((double)((coord[j][0]-cx)*(coord[j][0]-cx)+(coord[j][1]-cy)*(coord[j][1]-cy))); + fi[j] = acos((coord[j][0]-cx)/dist[j]); + if (coord[j][1]= 0 && x < WINDOW_WIDTH && y >= 0 && y < WINDOW_HEIGHT) kos_PutPixel(x, y, color); +} + +void pline(int x1, int y1, int x2, int y2, int color) +{ + kos_DrawLine(x1, y1, x2, y2, color); +} + + +void draw4(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int color) +{ + pline(x1, y1, x2, y2, color); + pline(x2, y2, x3, y3, color); + pline(x3, y3, x4, y4, color); + pline(x4, y4, x1, y1, color); +} diff --git a/programs/games/rforces/trunk/pe2kos.exe b/programs/games/rforces/trunk/pe2kos.exe new file mode 100644 index 0000000000000000000000000000000000000000..bef0e7ce2dc89dcc6c3a8675f0b1892a10205e2f GIT binary patch literal 13312 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 + +#include "kosSyst.h" +#include "kosFile.h" +#include "mymath.h" +#include "properties.h" +#include "objects.h" +#include "rforces.h" + + +const char header[] = GAME_NAME; +cCursor *cursor; +cGun *gun = new cGun; +cCross **crosses = new cCross*[R_COUNT]; +cRocket **rockets = new cRocket*[R_COUNT]; +cBomb **bombs = new cBomb*[B_COUNT]; +cExplode **explodes = new cExplode*[R_COUNT + B_COUNT]; +cBuilding *house = new cBuilding(); +Dword *cur_handle; +int score, health; + +struct MouseState +{ + int x, y, lbclick; + Dword buttons; +} ms; + + +void kos_Main() +{ + Dword frame_start, frame_end; + OnStart(); + Menu(); + for (;;) + { + frame_start = kos_GetTime(); + switch (kos_CheckForEvent()) + { + case 1: + DrawWindow(); + break; + case 2: // key pressed, read it and ignore + Byte keyCode; + kos_GetKey(keyCode); + if (keyCode == 27) + { + OnExit(); + } + if (keyCode == 51) + { + OnStart(); + } + break; + case 3: // button pressed; we have only one button, close + OnExit(); + break; + case 6: // событие от мыши (нажатие на кнопку мыши или перемещение; сбрасывается при прочтении) + OnMouseMove(); + if (ms.lbclick == 1) + { + OnLMBClick(); + } + break; + default: + OnMouseMove(); + break; + } + DrawBombs(); + DrawRocketsAndCrosses(); + DrawExplodes(); + frame_end = kos_GetTime(); + if (frame_end - frame_start < FRAME_TIME) + { + kos_Pause(FRAME_TIME - (frame_end - frame_start)); + } + if (health <= 0) + { + OnExit(); + } + } +} + +void DrawWindow() +{ + kos_WindowRedrawStatus(1); + kos_DefineAndDrawWindow(10, 40, WINDOW_WIDTH + 8, WINDOW_HEIGHT + 25, 0x33, BG_COLOR, 0, 0, (Dword)header); + kos_WindowRedrawStatus(2); + + OnMouseMove(); + + // Draw buildings + for (int i = 20; i < 5 * 50; i += 50) + { + house->Draw(i, 467, H_COLOR); + } + for (int i = 8 * 50; i < 13 * 50; i += 50) + { + house->Draw(i, 467, H_COLOR); + } + +} + +void DrawBombs() +{ + for (int i = 0; i < B_COUNT; i++) + { + if (bombs[i]->IsEnabled() == 0) + { + int rnd; + rnd = rtlRand() % B_POSSIBILITY; + if (rnd == 1) + { + rnd = 10 + rtlRand() % 620; + bombs[i]->Enable(rnd, 0, 4, 9, rnd + 2, 0); + } + } + else + { + if (bombs[i]->cy > gun->cy + 5) + { + health -= 5; + if (explodes[R_COUNT + i]->IsEnabled() == 1) + { + explodes[R_COUNT + i]->Disable(BG_COLOR); + } + explodes[R_COUNT + i]->Enable(bombs[i]->cx, bombs[i]->cy); + bombs[i]->Disable(BG_COLOR); + } + else + { + bombs[i]->cy += B_SPEED; + bombs[i]->DrawAngle(bombs[i]->cx, 639, B_COLOR); + } + } + } +} + +void DrawRocketsAndCrosses() +{ + double a; + for (int i = 0; i < R_COUNT; i++) + { + if (crosses[i]->IsEnabled() == 1) + { + if (sqrt(((long int) (crosses[i]->x - rockets[i]->cx) * (crosses[i]->x - rockets[i]->cx)) + ((long int) (crosses[i]->y - rockets[i]->cy) * (crosses[i]->y - rockets[i]->cy))) < 5) + { + if (explodes[i]->IsEnabled() == 1) + { + explodes[i]->Disable(BG_COLOR); + } + explodes[i]->Enable(crosses[i]->x, crosses[i]->y); + crosses[i]->Disable(BG_COLOR); + rockets[i]->Disable(BG_COLOR); + } + else + { + crosses[i]->Draw(CROSS_COLOR); + if (rockets[i]->cx - crosses[i]->x == 0) + { + a = M_PI / 2; + } + else + { + a = atan((double)(rockets[i]->cy - crosses[i]->y) / (double)(rockets[i]->cx - crosses[i]->x)); + if (rockets[i]->cx - crosses[i]->x < 0) a += M_PI; + } + rockets[i]->cx = round_int(rockets[i]->cx - R_SPEED * cos(a)); + rockets[i]->cy = round_int(rockets[i]->cy - R_SPEED * sin(a)); + rockets[i]->DrawAngle(crosses[i]->x, crosses[i]->y, R_COLOR); + } + } + } +} + +void DrawExplodes() +{ + for (int i = 0; i < R_COUNT + B_COUNT; i++) + { + if (explodes[i]->IsEnabled() == 1) + { + explodes[i]->DrawNext(EXP_COLOR); + for (int j = 0; j < B_COUNT; j++) + { + if ( bombs[j]->IsEnabled() == 1 && + bombs[j]->cx > explodes[i]->cx - explodes[i]->step - 1 && bombs[j]->cx < explodes[i]->cx + explodes[i]->step + 1 && + bombs[j]->cy + 5 > explodes[i]->cy - explodes[i]->step - 1 && bombs[j]->cy + 5 < explodes[i]->cy + explodes[i]->step + 1 + ) + { + score += B_COUNT + 2; + if (explodes[R_COUNT + j]->IsEnabled() == 1) + { + explodes[R_COUNT + j]->Disable(BG_COLOR); + } + explodes[R_COUNT + j]->Enable(bombs[j]->cx, bombs[j]->cy); + bombs[j]->Disable(BG_COLOR); + } + } + } + } +} + +void OnMouseMove() +{ + Dword old_buttons = ms.buttons; + kos_GetMouseWindowXY(ms.x, ms.y); + kos_GetMouseButtonsState(ms.buttons); + if ((old_buttons & 0x00000001) == 0 && (ms.buttons & 0x00000001) == 1) + { + ms.lbclick = 1; + } + else + { + ms.lbclick = 0; + } + + + kos_WriteTextToWindow(8, 10, 0, TEXT_COLOR, "Population: %", 16); + kos_DisplayNumberToWindowBg(health, 3, 79, 10, TEXT_COLOR, BG_COLOR, nbDecimal, false); + kos_WriteTextToWindow(8, 22, 0, TEXT_COLOR, "Score:", 6); + kos_DisplayNumberToWindowBg(score, 4, 49, 22, TEXT_COLOR, BG_COLOR, nbDecimal, false); + + if (ms.x >= 0 && ms.x < WINDOW_WIDTH && ms.y >= 0 && ms.y < WINDOW_HEIGHT) + { + gun->DrawAngle(ms.x, ms.y, G_COLOR); + } + + if (HARDWARE_CURSOR == 0) + { + cursor->Draw(ms.x, ms.y, CUR_COLOR); + } + + /*if (DEBUG == 1) + { + kos_DisplayNumberToWindowBg(ms.x, 3, WINDOW_WIDTH - 30, 10, TEXT_COLOR, BG_COLOR, nbDecimal, false); + kos_DisplayNumberToWindowBg(ms.y, 3, WINDOW_WIDTH - 30, 22, TEXT_COLOR, BG_COLOR, nbDecimal, false); + kos_DisplayNumberToWindowBg(ms.buttons, 1, WINDOW_WIDTH - 30, 34, TEXT_COLOR, BG_COLOR, nbDecimal, false); + }*/ + +} + +void OnLMBClick() +{ + if (ms.y < gun->cy - 10) + { + double a; + int j = -1; + for (int i = 0; i < R_COUNT; i++) + { + if (crosses[i]->IsEnabled() == 0) + { + if (j >= -1) j = i; + } + else if (ms.x > crosses[i]->x - 10 && ms.x < crosses[i]->x + 10 && ms.y > crosses[i]->y - 10 && ms.y < crosses[i]->y + 10) + { + j = -2; + break; + } + } + if (j >= 0) + { + if (score > 0) score -= 1; + crosses[j]->Enable(ms.x, ms.y); + if (gun->cx - ms.x == 0) + { + a = M_PI/2; + } + else + { + a = atan((double)gun->cy - ms.y / (double) gun->cx - ms.x); + if (gun->cx - ms.x < 0) a += M_PI; + } + rockets[j]->Enable(round_int(gun->cx - 15 * cos(a)) - 2, round_int(gun->cy - 15 * sin(a)) - 5, 3, 6, round_int(gun->cx - 15 * cos(a)), round_int(gun->cy - 15 * sin(a))); + } + } +} + +void OnRMBClick() +{ +} + +void ChangeCursor() +{ + Dword *cur = new Dword[1024]; + for (int i = 0; i < 1024; i++) + { + cur[i] = 0x00000000; + } + if (HARDWARE_CURSOR == 1) + { + Dword cur_color = 0xFF000000 | CUR_COLOR; + cur[0 * 32 + 5] = cur_color; + cur[1 * 32 + 5] = cur_color; + cur[2 * 32 + 5] = cur_color; + cur[2 * 32 + 3] = cur_color; + cur[2 * 32 + 4] = cur_color; + cur[2 * 32 + 6] = cur_color; + cur[3 * 32 + 2] = cur_color; + cur[4 * 32 + 2] = cur_color; + cur[5 * 32 + 2] = cur_color; + cur[5 * 32 + 1] = cur_color; + cur[5 * 32 + 0] = cur_color; + + cur[5 * 32 + 5] = cur_color; + + cur[8 * 32 + 4] = cur_color; + cur[8 * 32 + 5] = cur_color; + cur[8 * 32 + 6] = cur_color; + cur[8 * 32 + 7] = cur_color; + cur[9 * 32 + 5] = cur_color; + cur[10 * 32 + 5] = cur_color; + cur[7 * 32 + 8] = cur_color; + cur[6 * 32 + 8] = cur_color; + cur[5 * 32 + 8] = cur_color; + cur[5 * 32 + 9] = cur_color; + cur[5 * 32 + 10] = cur_color; + } + cur_handle = kos_LoadMouseCursor(cur, 0x05050002); + delete[] cur; + kos_SetMouseCursor(cur_handle); +} + +void Menu() +{ + NewGame(); +} + +void NewGame() +{ + gun->DrawAngle((WINDOW_WIDTH / 2) - 5, WINDOW_HEIGHT - 20, G_COLOR); +} + +void OnStart() +{ + if (HARDWARE_CURSOR == 0) + { + cursor = new cCursor(); + } + ChangeCursor(); + + gun->Enable((WINDOW_WIDTH / 2) - 10, WINDOW_HEIGHT - 30, 10, 20, (WINDOW_WIDTH / 2) - 5, WINDOW_HEIGHT - 20); + + for (int i = 0; i < R_COUNT; i++) + { + crosses[i] = new cCross(); + rockets[i] = new cRocket(); + } + for (int i = 0; i < B_COUNT; i++) + { + bombs[i] = new cBomb(); + } + for (int i = 0; i < R_COUNT + B_COUNT; i++) + { + explodes[i] = new cExplode(); + } + + health = 100; + score = 0; + + rtlSrand(kos_GetTime()); + + DrawWindow(); + kos_SetMaskForEvents(39); +} + +void OnExit() +{ + kos_WriteTextToWindow(WINDOW_WIDTH / 2 - 35, WINDOW_HEIGHT / 2 - 10, 0, TEXT_COLOR, "Game Over", 9); + + kos_Pause(200); + + kos_ExitApp(); +} diff --git a/programs/games/rforces/trunk/rforces.h b/programs/games/rforces/trunk/rforces.h new file mode 100644 index 0000000000..6c9f60d5da --- /dev/null +++ b/programs/games/rforces/trunk/rforces.h @@ -0,0 +1,19 @@ +/* Rocket Forces + * Filename: rforces.h + * Version 0.1 + * Copyright (c) Serial 2007 + */ + + +void DrawWindow(); +void DrawBombs(); +void DrawRocketsAndCrosses(); +void DrawExplodes(); +void OnMouseMove(); +void OnLMBClick(); +void OnRMBClick(); +void ChangeCursor(); +void Menu(); +void NewGame(); +void OnStart(); +void OnExit(); diff --git a/programs/games/sq_game/trunk/MACROS.INC b/programs/games/sq_game/trunk/MACROS.INC new file mode 100644 index 0000000000..14185dbfce --- /dev/null +++ b/programs/games/sq_game/trunk/MACROS.INC @@ -0,0 +1,269 @@ +; new application structure +macro meos_app_start + { + use32 + org 0x0 + + db 'MENUET01' + dd 0x01 + dd __start + dd __end + dd __memory + dd __stack + + if used __params & ~defined __params + dd __params + else + dd 0x0 + end if + + dd 0x0 + } +MEOS_APP_START fix meos_app_start + +macro code + { + __start: + } +CODE fix code + +macro data + { + __data: + } +DATA fix data + +macro udata + { + if used __params & ~defined __params + __params: + db 0 + __end: + rb 255 + else + __end: + end if + __udata: + } +UDATA fix udata + +macro meos_app_end + { + align 32 + rb 2048 + __stack: + __memory: + } +MEOS_APP_END fix meos_app_end + + +; macro for defining multiline text data +struc mstr [sstring] + { + forward + local ssize + virtual at 0 + db sstring + ssize = $ + end virtual + dd ssize + db sstring + common + dd -1 + } + + +; strings +macro sz name,[data] { ; from MFAR [mike.dld] + common + if used name + label name + end if + forward + if used name + db data + end if + common + if used name + .size = $-name + end if +} + +macro lsz name,[lng,data] { ; from MFAR [mike.dld] + common + if used name + label name + end if + forward + if (used name)&(lang eq lng) + db data + end if + common + if used name + .size = $-name + end if +} + + + +; easy system call macro +macro mpack dest, hsrc, lsrc +{ + if (hsrc eqtype 0) & (lsrc eqtype 0) + mov dest, (hsrc) shl 16 + lsrc + else + if (hsrc eqtype 0) & (~lsrc eqtype 0) + mov dest, (hsrc) shl 16 + add dest, lsrc + else + mov dest, hsrc + shl dest, 16 + add dest, lsrc + end if + end if +} + +macro __mov reg,a,b { ; mike.dld + if (~a eq)&(~b eq) + mpack reg,a,b + else if (~a eq)&(b eq) + mov reg,a + end if +} + +macro mcall a,b,c,d,e,f { ; mike.dld + __mov eax,a + __mov ebx,b + __mov ecx,c + __mov edx,d + __mov esi,e + __mov edi,f + int 0x40 +} + + + +; optimize the code for size +__regs fix + +macro add arg1,arg2 + { + if (arg2 eqtype 0) + if (arg2) = 1 + inc arg1 + else + add arg1,arg2 + end if + else + add arg1,arg2 + end if + } + +macro sub arg1,arg2 + { + if (arg2 eqtype 0) + if (arg2) = 1 + dec arg1 + else + sub arg1,arg2 + end if + else + sub arg1,arg2 + end if + } + +macro mov arg1,arg2 + { + if (arg1 in __regs) & ((arg2 eqtype 0) | (arg2 eqtype '0')) + if (arg2) = 0 + xor arg1,arg1 + else if (arg2) = 1 + xor arg1,arg1 + inc arg1 + else if (arg2) = -1 + or arg1,-1 + else if (arg2) > -128 & (arg2) < 128 + push arg2 + pop arg1 + else + mov arg1,arg2 + end if + else + mov arg1,arg2 + end if + } + + +macro struct name + { + virtual at 0 + name name + sizeof.#name = $ - name + end virtual + } + +; structures used in MeOS +struc process_information + { + .cpu_usage dd ? ; +0 + .window_stack_position dw ? ; +4 + .window_stack_value dw ? ; +6 + .not_used1 dw ? ; +8 + .process_name rb 12 ; +10 + .memory_start dd ? ; +22 + .used_memory dd ? ; +26 + .PID dd ? ; +30 + .x_start dd ? ; +34 + .y_start dd ? ; +38 + .x_size dd ? ; +42 + .y_size dd ? ; +46 + .slot_state dw ? ; +50 + dw ? ; +52 - reserved + .client_left dd ? ; +54 + .client_top dd ? ; +58 + .client_width dd ? ; +62 + .client_height dd ? ; +66 + .wnd_state db ? ; +70 + rb (1024-71) + } +struct process_information + +struc system_colors + { + .frame dd ? + .grab dd ? + .grab_button dd ? + .grab_button_text dd ? + .grab_text dd ? + .work dd ? + .work_button dd ? + .work_button_text dd ? + .work_text dd ? + .work_graph dd ? + } +struct system_colors + + +; constants + +; events +EV_IDLE = 0 +EV_TIMER = 0 +EV_REDRAW = 1 +EV_KEY = 2 +EV_BUTTON = 3 +EV_EXIT = 4 +EV_BACKGROUND = 5 +EV_MOUSE = 6 +EV_IPC = 7 +EV_STACK = 8 + +; event mask bits for function 40 +EVM_REDRAW = 1b +EVM_KEY = 10b +EVM_BUTTON = 100b +EVM_EXIT = 1000b +EVM_BACKGROUND = 10000b +EVM_MOUSE = 100000b +EVM_IPC = 1000000b +EVM_STACK = 10000000b \ No newline at end of file diff --git a/programs/games/sq_game/trunk/SQ_GAME.ASM b/programs/games/sq_game/trunk/SQ_GAME.ASM new file mode 100644 index 0000000000..790a555e27 --- /dev/null +++ b/programs/games/sq_game/trunk/SQ_GAME.ASM @@ -0,0 +1,246 @@ +; SQ_game for MenuetOS +; Author: Alexei Ershov aka ealex +; E-mail: e-al[at]yandex[dot]ru +; Fidonet: 2:469/335.38 +; slightly optimized by diamond +; english translation by diamond (two strings in end of source) + + + BtnSize equ 32 ; а §¬Ґа Є­®ЇЄЁ + BtnSpace equ 10 ; Їа®¬Ґ¦гв®Є ¬Ґ¦¤г Є­®ЇЄ ¬Ё + NofBtn equ 4 ; а §¬Ґа Ї®«п (3-15) + Color1 equ 0xcc0000 + Color2 equ 0x00cc00 + + FieldSize = (BtnSize+BtnSpace)*NofBtn + BtnSpace*3 + center = FieldSize / 2 + + + use32 ; ўЄ«озЁвм 32-ЎЁв­л© ०Ё¬  бᥬЎ«Ґа  + org 0x0 ;  ¤аҐб жЁп б ­г«п + + db 'MENUET01' ; 8-Ў ©в­л© Ё¤Ґ­вЁдЁЄ в®а MenuetOS + dd 0x01 ; ўҐабЁп § Ј®«®ўЄ  (ўбҐЈ¤  1) + dd START ;  ¤аҐб ЇҐаў®© Є®¬ ­¤л + dd I_END ; а §¬Ґа Їа®Ја ¬¬л + dd 0x1000 ; Є®«ЁзҐбвў® Ї ¬пвЁ + dd 0x1000 ;  ¤аҐб ўҐаиЁ­л бвнЄ  + dd 0x0 ;  ¤аҐб ЎгдҐа  ¤«п Ї а ¬Ґва®ў (­Ґ ЁбЇ®«м§гҐвбп) + dd 0x0 ; § аҐ§ҐаўЁа®ў ­® + +include 'lang.inc' +include 'MACROS.INC' ; ¬ Єа®бл ®Ў«ҐЈз ов ¦Ё§­м  бᥬЎ«ҐайЁЄ®ў! + + +START: + call Game_Init +red: + call Draw_Window + +still: + mcall 10 ; дг­ЄжЁп 10 - ¦¤ вм б®ЎлвЁп + dec eax + jz red + dec eax + jnz button + + key: ; ­ ¦ в  Є« ўЁи  ­  Є« ўЁ вгॠ+ mov al, 2 + int 0x40 + jmp still +;--------------------------------------------------------------------- + +button: + mov al, 17 ; 17 - Ї®«гзЁвм Ё¤Ґ­вЁдЁЄ в®а ­ ¦ в®© Є­®ЇЄЁ + int 0x40 + cmp ah, 1 ; Ґб«Ё ­ ¦ в  Є­®ЇЄ  б ­®¬Ґа®¬ 1, ўл室Ё¬ + je .exit + + cmp ah, 2 ; Ґб«Ё ­ ¦ в  Є­®ЇЄ  2, ­ зЁ­ Ґ¬ ­®ўго ЁЈаг + je START + + ; Ќ ¦  Є­®ЇЄ  ­  Ї®«Ґ + inc dword [moves] ; 㢥«ЁзЁў Ґ¬ зЁб«® 室®ў + + shr eax, 8 ; ў eax Ё¤Ґ­вЁдЁЄ в®а ­ ¦ в®© Є­®ЇЄЁ + + mov dh, NofBtn + div dh ; al = ax(­®¬Ґа Є­®ЇЄЁ) / NofBtn + ; ah = ®бв в®Є (б¬. аЁбг­®Є) + mov ebx, eax ; б®еа ­Ё¬ з бв­®Ґ Ё ®бв в®Є ў ebx + + ; al\ah 0 1 2 3 + ; +-+ +-+ +-+ +-+ + ; 1 |4| |5| |6| |7| + ; +-+ +-+ +-+ +-+ + + ; +-+ +-+ +-+ +-+ + ; 2 |8| |9| |10 |11 + ; +-+ +-+ +-+ +-+ + + ; +-+ +-+ +-+ +-+ + ; 3 |12 |13 |14 |15 + ; +-+ +-+ +-+ +-+ + + ; +-+ +-+ +-+ +-+ + ; 4 |16 |17 |18 |19 + ; +-+ +-+ +-+ +-+ + +; ЊҐ­пҐ¬ 梥в бв®«ЎЁЄ  + shr eax, 8 ; eax = ah + mov edi, field + add edi, eax ; edi гЄ §ўлҐв ­  ЇҐаўго Є­®ЇЄг Ё ЁбЄ®¬®¬ бв«ЎжҐ + mov ecx, NofBtn +@@: + not byte[edi] ; ¬Ґ­пҐ¬ 梥⠢® ўбҐ¬ бв®«ЎЁЄҐ + dec ecx + add edi, NofBtn + test ecx, ecx + jnz @r + +; ЊҐ­пҐ¬ 梥в бва®ЄЁ + mov eax, ebx ; ў®ббв ­ ў«Ёў Ґ¬ eax + dec eax + mov dl, NofBtn + mul dl ; ax = al * NofBtn + mov edi, field + add edi, eax ; edi гЄ §ўлҐв ­  ЇҐаўго Є­®ЇЄг ў ЁбЄ®¬®© бва®ЄҐ + mov ecx, NofBtn +@@: + not byte [edi] ; ¬Ґ­пҐ¬ 梥⠢® ўбҐ© бва®ЄҐ + dec ecx + inc edi + test ecx, ecx + jnz @r +; –ўҐв ­ ¦ в®© Є­®ЇЄЁ ¬Ґ­п«бп 2 а §  (Є®Ј¤  ®Ўа Ў влў «Ё бва®Єг Ё бв®«ЎҐж), +; в.Ґ. ®бв «бп ЇҐаў®­ з «­л¬ +; ЊҐ­пҐ¬ 梥⠭ ¦ в®© Є­®ЇЄЁ + shr ebx, 8 ; ebx = ®бв в®Є (ah ­  аЁбг­ЄҐ) + not byte [field+eax+ebx] + jmp red + + + + .exit: + mcall -1 ; Ё­ зҐ Є®­Ґж Їа®Ја ¬¬л + + +;---------------------------------------------------------------------------- +; Draw_Window +;---------------------------------------------------------------------------- +Draw_Window: + + mcall 12, 1 + mcall 0, 200*65536+FieldSize,\ + 200*65536+FieldSize+20+20+20,\ + 0x03AABBCC, 0x805080D0, 0x005080D0 + mcall 4, 8*65536+8, 0x10DDEEFF, header, header_e - header + + mcall 8, BtnSpace*2*65536 + 83,\ + (FieldSize+BtnSpace+20)*65536+ 15, 2 + mcall 4, (BtnSpace*2+3)*65536+(BtnSize+BtnSpace)*NofBtn+BtnSpace*4+20+4,\ + 0x10DDEEFF, strNew, strNew_e - strNew + mcall 4, (center - 25) * 65536 + 30, 0, strMovs, strMovs_e - strMovs + mcall 47, 4*65536+1, moves, (center + 2 ) * 65536 + 30, 0 + + + + mov ecx, (20+20+BtnSpace-BtnSize)*65536+BtnSize + mov edx, NofBtn ; Ё¤Ґ­вЁдЁЄ в®а ЇҐаў®© Є­®ЇЄЁ ­  Ї®«Ґ + ; б¬ аЁбг­®Є + +buttons: ; аЁб㥬 Є­®Ї®зЄЁ + mov eax, edx + mov dh, NofBtn + div dh ; al = ax / dh, ah - ®бв в®Є + mov dh, 0 + test ah, ah ; Ґб«Ё ah = 0, ­ зЁ­ Ґ¬ ­®ўл© ап¤ + jnz @f + add ecx, (BtnSize+BtnSpace)*65536 + mov ebx, BtnSpace*2*65536+BtnSize +@@: + mov esi, Color1 ; Ў ©в Ї®  ¤аҐбг + cmp byte [field-NofBtn+edx], 0 ; field-NofBtn+­®¬Ґа_Є­®ЇЄЁ + jz @f ; Ј®ў®аЁв ® ҐҐ 梥⥠+ mov esi, Color2 +@@: + mcall 8, + add ebx, (BtnSize+BtnSpace)*65536 + inc edx ; ЇҐаҐе®¤Ё¬ Є б«Ґ¤го饩 Є­®ЇЄҐ + cmp edx, NofBtn*(NofBtn+1) + jb buttons + + mcall 12, 2 ; дг­ЄжЁп 12: б®®ЎйЁвм Ћ‘ ®Ў ®ваЁб®ўЄҐ ®Є­  + +ret + +;---------------------------------------------------------------------------- +; Game_Init +;---------------------------------------------------------------------------- +Game_Init: + and [moves], 0 ; ®Ў­г«Ё¬ Є®«ЁзҐбвў® 室®ў + + call random ; ў eax б«гз ©­®Ґ зЁб«® + mov ecx, NofBtn * NofBtn ; ў ecx Є®«-ў® Є­®Ї®Є ­  Ї®«Ґ + mov bh, 0 ; ¤«п Є ¦¤®© Є­®ЇЄЁ Ўг¤Ґ¬ Ўа вм + ; 1 ЎЁв Ё§ eax, bh - бЄ®«мЄ® +button_init: ; ЎЁв 㦥 ЁбЇ®«м§®ў «Ё + shr eax, 1 ; ¬« ¤иЁ© ЎЁв Ї®Ї ¤ Ґв ў д« Ј CF + ; ў § ўЁбЁ¬®бвЁ ®в ҐЈ® §­ зҐ­Ёп + ; ў bl § ЇЁблў Ґвбп -1 Ё«Ё 0 + sbb bl, bl + mov [field + ecx - 1], bl + + inc bh + cmp bh, 32 ; Ґб«Ё ЁбЇ®«м§®ў ­л ўбҐ 32 ЎЁв  Ё§ eax + jb @f ; ­ ® Ї®«гзЁвм ­®ў®Ґ б«гз ©­®Ґ зЁб«® + call random + mov bh, 0 +@@: + loop button_init + +ret + +;---------------------------------------------------------------------------- +; random - ў§пв  Ё§ вҐваЁб  +;---------------------------------------------------------------------------- +random: mov eax,[generator] + add eax,-43ab45b5h + ror eax,1 + xor eax,32c4324fh + ror eax,1 + mov [generator],eax + ; --- IVAN --- + mov eax,26 + mov ebx,9 + int 0x40 + xor eax,0xdeadbeef + add eax,[generator] + ; --- IVAN --- + ret + +;============================================================================ + +field db NofBtn * NofBtn dup(0) +moves dd 0 +generator dd 0 + +if lang eq ru +header db 'Game' +header_e: +strMovs db '•Ћ„' ; '•Ћ„' +strMovs_e: +strNew db 'Ќ®ў п ЁЈа ' ; 'Ќ®ў п ЁЈа ' +strNew_e: +else +header db 'Game' +header_e: +strMovs db 'MOVE' +strMovs_e: +strNew db ' New game' +strNew_e: +end if + + + +I_END: ; ¬ҐвЄ  Є®­ж  Їа®Ја ¬¬л diff --git a/programs/games/sq_game/trunk/build_en.bat b/programs/games/sq_game/trunk/build_en.bat new file mode 100644 index 0000000000..146614a2d3 --- /dev/null +++ b/programs/games/sq_game/trunk/build_en.bat @@ -0,0 +1,4 @@ +@echo lang fix en >lang.inc +@fasm sq_game.asm sq_game +@erase lang.inc +@pause \ No newline at end of file diff --git a/programs/games/sq_game/trunk/build_ru.bat b/programs/games/sq_game/trunk/build_ru.bat new file mode 100644 index 0000000000..e634b5f805 --- /dev/null +++ b/programs/games/sq_game/trunk/build_ru.bat @@ -0,0 +1,4 @@ +@echo lang fix ru >lang.inc +@fasm sq_game.asm sq_game +@erase lang.inc +@pause \ No newline at end of file diff --git a/programs/games/sudoku/trunk/SudokuSolve.pas b/programs/games/sudoku/trunk/SudokuSolve.pas new file mode 100644 index 0000000000..692496e2d3 --- /dev/null +++ b/programs/games/sudoku/trunk/SudokuSolve.pas @@ -0,0 +1,423 @@ +;unit SudokuSolve; + +;interface + +;type +; TSudokuBoard=array[0..8,0..8] of byte;//тип поле для игры + +; function CheckSudoku(var Map: TSudokuBoard): boolean; +; //возвращает true если поле составлено правильно + +; function Solve(var Map: TSudokuBoard): integer; +; //решает Судоку +; //Result = 1; - решение найдено +; //Result = -1; - тупиклвая комбинация + +; procedure CopyArray(var Dst: TSudokuBoard;Src: TSudokuBoard); + +;implementation + +;type +; TSudokuPt=record //тип точка с минимальным числом кандидатов +; mini,minj,variances: byte; +; end; + +;var +; TempMap: TSudokuBoard;//поля +; Pt: TSudokuPt; //точка +; i,j: byte; //счетчики + + + +align 4 +CheckSudoku: +pushad +;function CheckSudoku(var Map: TSudokuBoard): boolean; ;карта в esi! +;var +; i,j,x,y: byte; +; Zap: set of byte; +;begin + +;//проверяем столбцы +; for i:=0 to 8 do +; begin +; Zap:=[]; +; for j:=0 to 8 do +; if Map[i,j]<>0 then +; if Map[i,j] in Zap then +; begin +; Result:=false; +; Exit; +; end else +; Zap:=Zap+[Map[i,j]]; +; end; + xor ecx,ecx + xor eax,eax + xor edx,edx + mov bx,0x0909 +.1: mov al, byte [esi+ecx] + test al,al + jz @f + btc dx,ax + jc .ret_false + @@: + add cl,9 + dec bl + jnz .1 +; test [flags],1 shl 15 +; jz @f +; cmp edx,1022 ;1111111110b +; jne .ret_false +;@@: + bt [flags],15 + jnc @f + cmp dx,1022 ;1111111110 + jne .ret_false +@@: + sub cl,9*9-1 + xor edx,edx + mov bl,9 + dec bh + jnz .1 + + +;//проверяем строки +; for j:=0 to 8 do +; begin +; Zap:=[]; +; for i:=0 to 8 do +; if Map[i,j]<>0 then +; if Map[i,j] in Zap then +; begin +; Result:=false; +; Exit; +; end else +; Zap:=Zap+[Map[i,j]] +; end; + + xor ecx,ecx + xor eax,eax + xor edx,edx + mov bx,0x0909 +.2: mov al, byte [esi+ecx] + test al,al + jz @f + btc dx,ax + jc .ret_false + @@: + inc ecx + dec bl + jnz .2 + bt [flags],15 + jnc @f + cmp dx,1022 ;1111111110 + jne .ret_false +@@: + xor edx,edx + mov bl,9 + dec bh + jnz .2 + +;//проверяем сектора +;for i:=0 to 2 do +; for j:=0 to 2 do +; begin +; zap:=[]; +; for x:=0 to 2 do +; for y:=0 to 2 do +; if map[i*3+y,j*3+x]<>0 then +; if map[i*3+y,j*3+x] in Zap then +; begin +; Result:=false; +; exit; +; end else +; Zap:=zap+[map[i*3+y,j*3+x]]; +; end; +;Result:=true; +;end; + mov ecx,0x0303 ;ij + xor eax,eax + xor edx,edx + mov ebx,0x0303 ;xy + +.3: movzx eax,ch + dec al + lea eax,[eax*2+eax] + add al,bl ;i*3+y + dec al + mov edi,eax + movzx eax,cl + dec al + lea eax,[eax*2+eax] + add al,bh ;j*3+x + dec al + xchg eax,edi + mov ah,9 + mul ah + add eax,edi ;i*3+y,j*3+x + mov al,[esi+eax] + test al,al + jz @f + btc dx,ax + jc .ret_false + @@: + dec bl + jnz .3 + mov bl,3 + dec bh + jnz .3 + bt [flags],15 + jnc @f + cmp dx,1022 ;1111111110 + jne .ret_false +@@: + mov bx,0x0303 + xor edx,edx + dec cl + jnz .3 + mov cl,3 + dec ch + jnz .3 +popad +clc +ret +.ret_false: +popad +stc +ret + +_iRet dw ? + +Pt: +.mini db ? +.minj db ? +.variances db ? + +bFree db ? +nVariances db ? +nMinVariances db ? + +align 4 +FindMinPoint: + pushad + mov [bFree],0 + mov [nMinVariances],10 + mov cx,0x0909 ;ij +.1: movzx eax,ch + mov ah,9 + dec al + mul ah + add al,cl + dec al + cmp byte [esi+eax],0 + je @f +.11: dec cl + jnz .1 + mov cl,9 + dec ch + jnz .1 + jmp .3 + +@@: mov [nVariances],0 + mov [bFree],1 + mov ebx,1 +.2: mov [esi+eax],bl + call CheckSudoku + jc @f + inc [nVariances] +@@: inc ebx + cmp ebx,9 + jbe .2 + + mov byte [esi+eax],0 + mov dl,[nVariances] + cmp dl,0 + je .11 + cmp dl,[nMinVariances] + jnb .11 + mov [Pt.mini],ch + mov [Pt.minj],cl + mov [Pt.variances],dl + mov [nMinVariances],dl + jmp .11 + +.3: cmp [bFree],1 + jne @f + cmp [nMinVariances],10 + jge @f + mov [_iRet],1 + popad + ret +@@: cmp [bFree],1 + jne @f + mov [_iRet],-1 + popad + ret +@@: mov [_iRet],0 + popad +ret + + +; //ищет точку с минимальным числом кандидатов и записивает результат в MinPt +; //Result = -1; - нашли, куда можно поставить цифру +; //Result = 1; - свободное место есть на поле, но поставить никуда нельзя +; //Result = 0; - нет свободного места +;function FindMinPoint(var MinPt: TSudokuPt;var Map: TSudokuBoard): integer; +;var +;nVariances,nMinVariances,variance: byte; +;bFree: boolean; +;begin +;bFree:= false; +;nMinVariances:=10; +;for i:=0 to 8 do +; for j:=0 to 8 do +; begin +; if Map[i,j]<>0 then continue; +; nVariances := 0; +; bFree := true; +; for variance:=1 to 9 do +; begin +; map[i,j]:=variance; +; if CheckSudoku(Map) then inc(nVariances); +; end; +; Map[i,j]:=0; +; if nVariances=0 then continue; +; if nVariances < nMinVariances then +; begin +; MinPt.mini:=i; +; MInPt.minj:=j; +; MinPt.variances:=nVariances; +; nMinVariances := nVariances; +; end; +; end; +;if (bFree) and (nMinVariances<10) then // нашли, куда можно поставить цифру +; begin +; Result:=1; +; Exit; +; end; +;if bFree then // свободное место есть на поле, но поставить никуда нельзя +; begin +; Result:=-1; +; exit; +; end; +;result:=0; // нет свободного места +;end; + + + +;procedure CopyArray(var Dst: TSudokuBoard;Src: TSudokuBoard); +;begin +;for i:=0 to 8 do +; for j:=0 to 8 do +; Dst[i,j]:=Src[i,j]; +;end; + +CopyArray: + push ecx eax + xor ecx,ecx +@@: mov al,[esi+ecx] + mov [edi+ecx],al + inc ecx + cmp ecx,9*9 + jb @b + pop eax ecx +ret + + + +align 4 +Solve: + pushad +if DEBUG +dbg_dec esp +dbg_dec ecx +mcall 5,1 +endf + call FindMinPoint + cmp [_iRet],0 + jne @f + mov [_iRet],1 + popad + ret + @@: + cmp [_iRet],-1 + jne @f + popad + ret +@@: + push esi edi + mov edi,TempMap + call CopyArray + pop edi esi + mov ecx,1 + movzx eax, byte [Pt.mini] + dec al + mov ah,9 + mul ah + add al,byte [Pt.minj] + dec al +.1: mov byte [esi+eax],cl + call CheckSudoku + jnc @f +.2: inc ecx + cmp ecx,9 + jbe .1 +; jmp .1 +@@: call Solve + cmp [_iRet],-1 + jne @f + push esi edi + mov edi,TempMap + xchg esi,edi + call CopyArray + pop edi esi + popad + ret +@@: cmp [_iRet],1 + jne .3 + popad + ret +.3: mov [_iRet],0 + popad +ret + +;function Solve(var Map: TSudokuBoard): integer; +;var +; variance: byte; +; iRet: integer; +;begin +;// ищем клетку с наименьшим числом кандидатов: +;iRet:=FindMinPoint(Pt,Map); +;if (iRet = 0) then +; begin +; result:=1;// решение найдено +; exit; +; end else +;if (iRet = -1) then // тупиковая комбинация +; begin +; result:=-1; +; exit; +; end; + +;CopyArray(TempMap,Map); // сохраняем то, что есть +;for variance:=1 to 9 do +;begin +; Map[pt.mini,pt.minj]:=variance; // пытаемся ставить на найденную клетку цифры от 1 до 9 +; if not CheckSudoku(Map) then continue; // такую цифру поставить нельзя. Берём следующую. +; iRet:=Solve(Map); // запускаем функцию рекурсивно +; if iRet=-1 then // тупиковая комбинация +; begin +; CopyArray(Map,tempmap); // восстанавливаем массив и берём следующую цифру на то же место +; continue; +; end; +;if iRet=1 then // решение найдено +; begin +; Result:=1; +; exit; +; end; +;end; +;Result:=0; +;end; + +;end. + diff --git a/programs/games/sudoku/trunk/editbox_ex.mac b/programs/games/sudoku/trunk/editbox_ex.mac new file mode 100644 index 0000000000..938904c57c --- /dev/null +++ b/programs/games/sudoku/trunk/editbox_ex.mac @@ -0,0 +1,194 @@ + +ch_struc_size=36 +ed_struc_size=76 +ch_flag_en=10b + +ch_left equ [edi] ;Є®®а¤Ё­ в  ­ з «  аЁб®ў ­Ёп Ї® е +ch_top equ [edi+2] ;Є®®а¤Ё­ в  ­ з «  аЁб®ў ­Ёп Ї® г +ch_text_margin equ [edi+4] ;=4 а ббв®п­ЁҐ ®в Їаאַ㣮«м­ЁЄ  祪 Ў®Єб  ¤® ­ ¤ЇЁбЁ +ch_size equ [edi+8] ;12 а §¬Ґа Єў ¤а в  祪 Ў®Єб  +ch_color equ [edi+12] ;梥⠢­гваЁ checkbox +ch_border_color equ [edi+16] ; or [edi+4] ;梥в а ¬ЄЁ checkbox ҐҐ ¬®¦­® § ¤ вм б ¬®бв®п⥫쭮 +ch_text_color equ [edi+20];[edi+4] ;梥в ⥪бв  +ch_text_ptr equ [edi+24] ;гЄ § вҐ«м ­  ­ з «® ⥪бв®ў®© бва®ЄЁ +ch_text_length equ [edi+28] +ch_flags equ [edi+32] ;д« ЈЁ + +ed_width equ [edi] ;иЁаЁ­  Є®¬Ї®­Ґ­в  +ed_left equ [edi+4] ;Ї®«®¦Ґ­ЁҐ Ї® ®бЁ е +ed_top equ [edi+8] ;Ї®«®¦Ґ­ЁҐ Ї® ®бЁ г +ed_color equ [edi+12] ;梥в д®­  Є®¬Ї®­Ґ­в  +shift_color equ [edi+16] ;=0x6a9480 ¤«п ЇаЁ¬Ґа  ў®§мҐ¬ ¦Ґ«Ґ­л© 梥⠡®Єб  +ed_focus_border_color equ [edi+20] ;梥в а ¬ЄЁ Є®¬Ї®­Ґ­в  +ed_blur_border_color equ [edi+24] ;梥⠭Ґ  ЄвЁў­®Ј® Є®¬Ї®­Ґ­в  +ed_text_color equ [edi+28] ;梥в ⥪бв  +ed_max equ [edi+32] ;Є®«-ў® бЁ¬ў®«®ў Є®в®алҐ ¬®¦­® ¬ ЄбЁ¬ «м­® ўўҐбвЁ +ed_text equ [edi+36] ;гЄ § вҐ«м ­  ЎгдҐа +ed_mouse_variable equ [edi+40] ; гЄ § вҐ«м ­  ЇҐаҐ¬Ґ­­го ¤«п Ў®Єб /ЈагЇЇл +ed_flags equ [edi+44] ;д« ЈЁ +bp_flags equ [ebp+44] ;ў ­ҐЄ®в®але Їа®жҐ¤га е edi ЁбЇ®«м§гҐвбп, ў§ ¬Ґ­ гЄ § вҐ«м еа ­Ёвмбп ў ebp +ed_size equ [edi+48] ;Є®«-ў® бЁ¬ў®«®ў +bp_size equ [ebp+48] ;Є®«-ў® бЁ¬ўЇ®«®ў, ¤«п  ¤аҐб жЁЁ ЁбЇ«м§гҐвбп ebpЎ edi § ­пв +ed_pos equ [edi+52] ;Ї®§ЁжЁп Єгаб®а  +ed_offset equ [edi+56] ;ᬥ饭ЁҐ +cl_curs_x equ [edi+60] ;ЇаҐ¤л¤г饥 Є®®а¤Ё­ в  Єгаб®а  Ї® е +cl_curs_y equ [edi+64] ;ЇаҐ¤л¤г饥 Є®®а¤Ё­ в  Єгаб®а  Ї® г +ed_shift_pos equ [edi+68] ;Ї®«®¦Ґ­ЁҐ Єгаб®а  +ed_shift_pos_old equ [edi+72] ;бв а®Ґ Ї®«®¦Ґ­ЁҐ Єгаб®а  + +ed_struc_size=76 +struc edit_box width,left,top,color,shift_color,focus_border_color,\ + blur_border_color,text_color,max,text,mouse_variable,flags,size,pos +{ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;Bit mask from editbox +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +ed_figure_only= 1000000000000000b ;®¤­Ё бЁ¬ў®«л +ed_always_focus= 100000000000000b +ed_focus= 10b ;д®Єгб ЇаЁ«®¦Ґ­Ёп +ed_shift_on= 1000b ;Ґб«Ё ­Ґ гбв ­®ў«Ґ­ -§­ зЁв ўЇҐаўлҐ ­ ¦ в shift,Ґб«Ё Ўл« гбв ­®ў«Ґ­, §­ зЁв ¬л 㦥 зв® - в® ¤Ґ« «Ё 㤥নў п shift +ed_shift_on_off=1111111111110111b +ed_shift= 100b ;ўЄ«оз Ґвбп ЇаЁ ­ ¦ вЁЁ ­  shift в.Ґ. Ґб«Ё ­ ¦Ё¬ о +ed_shift_off= 1111111111111011b +ed_shift_bac= 10000b ;ЎЁв ¤«п ®зЁбвЄЁ ўл¤Ґ«Ґ­®Ј® shift в.Ґ. ЇаЁ гбв ­®ўЄҐ Ј®ў®аЁв зв® Ґбвм ўл¤Ґ«Ґ­ЁҐ +ed_shift_bac_cl=1111111111101111b ;®зЁбвЄ  ЇаЁ г¤ «Ґ­ЁЁ ўл¤Ґ«Ґ­Ёп +ed_shift_cl= 1111111111100011b +ed_shift_mcl= 1111111111111011b +ed_left_fl= 100000b +ed_right_fl= 1111111111011111b +ed_offset_fl= 1000000b +ed_offset_cl= 1111111110111111b +ed_insert= 10000000b +ed_insert_cl= 1111111101111111b +ed_mouse_on = 100000000b +ed_mous_adn_b= 100011000b +ed_mouse_on_off=1111111011111111b +ed_height=14 ; ўлб®в  + +.width dd width +.left dd left +.top dd top +.color dd color +.shift_color dd shift_color +.focus_border_color dd focus_border_color +.blur_border_color dd blur_border_color +.text_color dd text_color +.max dd max +.text dd text +.mouse_variable dd mouse_variable +.flags dd flags+0 +.size dd size+0 +.pos dd pos+0 +.offset dd 0 +.cl_curs_x dd 0 +.cl_curs_y dd 0 +.shift dd 0 +.shift_old dd 0 +} +macro edit_boxes_set_sys_color start,end,color_table +{ + mov edi,start + mov ecx,((end-start)/ed_struc_size) + mov esi,color_table +@@: + mov eax,dword [esi+36] + mov ebx,dword [esi+20] + push dword eax + pop dword ed_focus_border_color + shr bh,1 + shr bl,1 + shr ah,1 + shr al,1 + add ah,bh + add al,bl + ror eax,16 + ror ebx,16 + shr bl,1 + shr al,1 + add al,bl + ror eax,16 + mov dword ed_blur_border_color,eax + mov dword shift_color,eax + add edi,ed_struc_size + loop @b +} +macro get_sys_colors col_buf +{ + ;mov eax,48 + push 48 + pop eax + ;mov ebx,3 + push 3 + pop ebx + ;mov ecx,col_buf + push col_buf + pop ecx + ;mov edx,40 + push 40 + pop edx + mcall +} +macro check_boxes_set_sys_color start,end,color_table +{ +ch_left equ [edi] ;Є®®а¤Ё­ в  ­ з «  аЁб®ў ­Ёп Ї® е +ch_top equ [edi+2] ;Є®®а¤Ё­ в  ­ з «  аЁб®ў ­Ёп Ї® г +ch_text_margin equ [edi+4] ;=4 а ббв®п­ЁҐ ®в Їаאַ㣮«м­ЁЄ  祪 Ў®Єб  ¤® ­ ¤ЇЁбЁ +ch_size equ [edi+8] ;12 а §¬Ґа Єў ¤а в  祪 Ў®Єб  +ch_color equ [edi+12] ;梥⠢­гваЁ checkbox +ch_border_color equ [edi+16] ; or [edi+4] ;梥в а ¬ЄЁ checkbox ҐҐ ¬®¦­® § ¤ вм б ¬®бв®п⥫쭮 +ch_text_color equ [edi+20];[edi+4] ;梥в ⥪бв  +ch_text_ptr equ [edi+24] ;гЄ § вҐ«м ­  ­ з «® ⥪бв®ў®© бва®ЄЁ +ch_text_length equ [edi+28] +ch_flags equ [edi+32] ;д« ЈЁ + + +;ch_left equ [edi] ;Є®®а¤Ё­ в  ­ з «  аЁб®ў ­Ёп Ї® е +;ch_top equ [edi+2] ;Є®®а¤Ё­ в  ­ з «  аЁб®ў ­Ёп Ї® г +;ch_color equ [edi+4] ;梥⠢­гваЁ checkbox +;ch_border_color equ [edi+8] ;梥в а ¬ЄЁ checkbox +;ch_text_color equ [edi+12] ;梥в ⥪бв  +;ch_text_ptr equ [edi+16] ;гЄ § вҐ«м ­  ­ з «® ⥪бв®ў®© бва®ЄЁ +;ch_text_length equ [edi+20] ;¤«Ё­  ­ ¤ЇЁбЁ (2^64 в Є®© ¤«Ё­л ¬®¦Ґв Ўлвм ⥪бв) +;ch_flags equ [edi+24] ;д« ЈЁ + + mov edi,start + mov ecx,((end-start)/ch_struc_size) + mov esi,color_table +@@: + push dword [esi+32] + pop dword ch_text_color + push dword [esi+36] + pop dword ch_border_color + add edi,ch_struc_size + loop @b +} +struc check_box left,top,ch_text_margin,ch_size,color,border_color,text_color,text,ch_text_length,flags +{ ;бвагЄвга  Ї а ¬Ґва®ў ¤«п 祪 Ў®Єб  +ch_flag_en=10b +.left: dw left ;+0 ;Ї®«®¦Ґ­ЁҐ Ї® е +.top: dw top ;Ї®«®¦Ґ­ЁҐ Ї® г +.ch_text_margin: dd ch_text_margin ;а ббв®п­ЁҐ ®в Їаאַ㣮«м­ЁЄ  祪 Ў®Єб  ¤® ­ ¤ЇЁбЁ +.ch_size: dd ch_size ;а §¬Ґа Єў ¤а в  祪 Ў®Єб , ¤«п ЇаЁ¬Ґа  12 +.color: dd color ;梥⠢­гвਠ祪Ў®Єб  +.border_color: dd border_color ;梥в а ¬ЄЁ +.text_color: dd text_color ;梥⠭ ¤ЇЁбЁ +.text: dd text ; ¤аҐб ў Є®¤Ґ Їа®Ја ¬¬л Ј¤Ґ а бЇ®«®¦Ґ­ ⥪бв +.ch_text_length: dd ch_text_length ;¤«Ё­­  бва®ЄЁ б бЁ¬ў®« ¬Ё +.flags: dd flags+0 ; д« ЈЁ +} +struc option_box point_gr,left,top,op_text_margin,op_size,color,border_color,text_color,text,op_text_length,flags +{ ;бвагЄвга  Ї а ¬Ґва®ў ¤«п 祪 Ў®Єб  +op_flag_en=10b +.option_group: dd point_gr +.left: dw left ;+0 ;Ї®«®¦Ґ­ЁҐ Ї® е +.top: dw top ;Ї®«®¦Ґ­ЁҐ Ї® г +.ch_text_margin: dd op_text_margin ;а ббв®п­ЁҐ ®в Їаאַ㣮«м­ЁЄ  祪 Ў®Єб  ¤® ­ ¤ЇЁбЁ +.ch_size: dd op_size ;а §¬Ґа Єў ¤а в  祪 Ў®Єб , ¤«п ЇаЁ¬Ґа  12 +.color: dd color ;梥⠢­гвਠ祪Ў®Єб  +.border_color: dd border_color ;梥в а ¬ЄЁ +.text_color: dd text_color ;梥⠭ ¤ЇЁбЁ +.text: dd text ; ¤аҐб ў Є®¤Ґ Їа®Ја ¬¬л Ј¤Ґ а бЇ®«®¦Ґ­ ⥪бв +.ch_text_length: dd op_text_length ;¤«Ё­­  бва®ЄЁ б бЁ¬ў®« ¬Ё +.flags: dd flags+0 ; д« ЈЁ +} + diff --git a/programs/games/sudoku/trunk/sudoku.asm b/programs/games/sudoku/trunk/sudoku.asm new file mode 100644 index 0000000000..879644948d --- /dev/null +++ b/programs/games/sudoku/trunk/sudoku.asm @@ -0,0 +1,1162 @@ +; 4.11.2009 staper@inbox.ru + +; 2.06.2010 fixed a little bug in check + +;based on http://sources.codenet.ru/download/1599/Sudoku.html + +; ‚ Їа ў®¬ ­Ё¦­Ґ¬ гЈ«г а бЇ®« Ј Ґвбп бҐа п Є­®ЇЄ , +;ЇаЁ ­ ¦ вЁо ­  Є®в®аго ®Є­® 㢥«ЁзЁў Ґвбп ў а §¬ҐаҐ. + +; Џа®Ја ¬¬  Їа®ўҐапҐв бва®Єг Ї а ¬Ґва®ў; Їа®бв® ЇҐаҐ¤ ©вҐ +;Їгвм Є д ©«г б § ¤ зҐ©. + +; ‘®зҐв ­Ёп Є« ўЁи: +; n - бЈҐ­ҐаЁа®ў вм в Ў«Ёжг +; c - Їа®ўҐаЁвм аҐиҐ­ЁҐ +; Їа®ЎҐ« - Ї®Є § вм аҐиҐ­ЁҐ +; +- - Ё§¬Ґ­Ёвм га®ўҐ­м б«®¦­®бвЁ +; t - ЇаЁ®бв ­®ўЁвм/§ ЇгбвЁвм ᥪ㭤®¬Ґа +; i - ўўҐбвЁ бў®© ЇаЁ¬Ґа +; r - аҐиЁвм +; l - § Јаг§Ёвм § ¤ зг Ё§ д ©«  +; s - б®еа ­Ёвм § ¤ зг ў д ©« +; a - б®еа ­Ёвм аҐиҐ­ЁҐ ў д ©« + +use32 +org 0x0 + db 'MENUET01' + dd 0x1, START, I_END, (D_END+10000) and not 3, (D_END+10000) and not 3, buf_cmd_lin, cur_dir_path + +Difficult db 0 ;б«®¦­®бвм [0..9] +Difficult_array db 80,75,68,59,50,45,40,36,32,25 + +;–ўҐв : +Bckgrd_clr equ 0xffffff ;д®­ +Brdr_line_clr equ 0x780000 ;«Ё­ЁЁ Ї® Ја ­Ёж ¬ +Inter_line_clr equ 0xb0b0b0 ;ў­гв७­ЁҐ «Ё­ЁЁ +Square_clr equ 0xdddddd ;梥⠪габ®а  +Fix_nmb_clr equ 0x335533;0 ;бв вЁз­®Ґ §­ зҐ­ЁҐ +Chg_nmb_clr equ 0;x008d8d ;ЇҐаҐ¬Ґ­­®Ґ §­ зҐ­ЁҐ +Text_clr equ 0x000000 ;⥪бв +Message_clr equ 0x0000ff ;б®®ЎйҐ­Ёп + +DEBUG equ 0 + +macro dbg_dec num +{pushad +newline +debug_print_dec num +popad +} + +include 'macros.inc' +;include 'debug.inc' +include 'editbox_ex.mac' +include 'lang.inc' +include 'SudokuSolve.pas' + + +START: + mcall 40,7 + mcall 3 + mov [rsx1],ax + ror eax,16 + mov [rsx2],ax + rol eax,7 + mov [rsx3],ax + rol eax,7 + mov [rsx4],ax + +; call LOAD_LIB ;loading Box_Lib library + +; This is the part of the macros for load any library/libraries by +LOAD_LIB: + mcall 68,19,system_path ; load of sys directory + test eax,eax + jnz .end_steep + + bts [flags],7 +; ret + jmp .end + +.end_steep: + +; initialize import + mov edx, eax + mov esi,myimport +.import_loop: + lodsd + test eax, eax + jz .import_done + push edx +.import_find: + mov ebx, [ds:edx] + test ebx, ebx + jz .exit ;import_not_found + push eax +.lp: + mov cl, [ds:eax] + cmp cl, [ds:ebx] + jnz .import_find_next + test cl, cl + jz .import_found + inc eax + inc ebx + jmp .lp +.import_find_next: + pop eax + add edx, 8 + jmp .import_find +.import_found: + pop eax + mov eax, [ds:edx+4] + mov [esi-4], eax + pop edx + jmp .import_loop +.exit: + add esp,4 + + bts [flags],7 +;ret + jmp .end + +.import_done: + btr [flags],7 + +;®ЇаҐ¤Ґ«пҐ¬ ¤«Ё­г бва®ЄЁ б Ї а ¬Ґва ¬Ё + mov esi,buf_cmd_lin + xor eax,eax +@@: cmp byte [esi+eax],0 + je @f + inc eax + jmp @b +@@: mov dword [edit1.size],eax + mov dword [edit1.pos],eax +;ret +.end: + + bt [flags],7 + jc @f + mcall 68,11 + cmp dword [edit1.pos],0 + je @f + call load_sudoku + jnc redraw_all +@@: jmp key.new_game + + +redraw_all: + mcall 12,1 + mcall 48,4 + add eax,100*65536+(24*9+67) + mov ecx,eax + mcall 0,100*65536+(24*9+12),,(0x34000000+Bckgrd_clr),,title + mcall 38,1*65536+(24*9+1),21*65536+21,Brdr_line_clr + mov edx,Inter_line_clr + mov edi,3 + mov esi,3 + @@: add ecx,24*65536+24 + mcall + dec esi + jnz @b + mov esi,3 + push edx + mcall ,,,Brdr_line_clr + pop edx + dec edi + jnz @b + mcall ,1*65536+1,22*65536+236,Inter_line_clr;0xe7e6a0 + mov edx,Inter_line_clr + mov edi,3 + mov esi,3 + push edx + mcall ,,,Brdr_line_clr + pop edx + + @@: add ebx,24*65536+24 + mcall + dec esi + jnz @b + mov esi,3 + push edx + mcall ,,,Brdr_line_clr + pop edx + dec edi + jnz @b + + mcall 8,<208,8>,<257,8>,2,0xbbbbbb + mcall 4,<5,5>,(0x80000000+Text_clr),txt.new + mcall ,<105,5>,,txt.dif + mcall ,<5,258>,,txt.space + mcall ,<5,246>,,txt.check + mcall ,<129,246>,,txt.time + mcall ,<5,285>,,txt.own_map + mcall ,<5,296>,,txt.solve + mcall ,<90,296>,,txt.load + mcall ,<5,306>,,txt.save + mcall ,<90,306>,,txt.save_solve + + bts [flags],5 + call Timer.0 + call show_level + + push dword Map;esi; mov esi,Map + mcall 12,2 +draw_pole: + if DEBUG + call SysMsgBoardNum ;show esp + endf + + movzx eax,[Y] + dec al + mov ebx,9 + mul bl + mov bl,[X] + add al,bl + pop esi ; mov esi,Map + push eax ;Єгаб®азЁЄ + mov edi,81-9 + mov ebp,9 + mov ebx,1*65536+21 + mov ecx,21*65536+41 + call out_numbers + pop eax + bt [flags],2 + jc key.0 + +still: + mcall 23,10 + test eax,eax + jz Timer + + dec al + jz redraw_all + dec al + jz key + dec al + jnz still +;button: + mcall 17 + cmp ah,1 + jne @f + mcall -1 +@@: cmp ah,2 + jne still + btc [flags],9 + mcall 48,4 + add eax,(24*9+67) + mov esi,eax + bt [flags],9 + jnc @f + add esi,40 +@@: mcall 67,100,100,(24*9+12), + jmp still +key: + mcall 2 + cmp ah,32 ;Їа®ЎҐ« +jne @f + btc [flags],3 + jc .todraw + push dword SolveMap + jmp draw_pole + .todraw: + push dword Map + jmp draw_pole +@@: + bt [flags],3 + jnc @f + bts [flags],2 + push eax + push dword Map + jmp draw_pole +.0: pop eax + btr [flags],2 + btr [flags],3 +@@: cmp ah,108 ;l + jne @f + bt [flags],7 + jc still + bt [flags],6 + jc still + bts [flags],8 + call window_load_save + jmp still +@@: cmp ah,115 ;s + jne @f + btr [flags],10 +.sresh: bt [flags],7 + jc still + bt [flags],6 + jc still + btr [flags],8 + call window_load_save + jmp still +@@: cmp ah,97 ;a + jne @f + bts [flags],10 + jmp .sresh +@@: cmp ah,116 ;t + jne @f + btc [flags],1 + jnc still + mcall 26,9 + sub eax,[Ticks_new] + push eax + mov eax,[Ticks] + mov ebx,100 + mul ebx + pop ecx + sub ecx,eax + add [Ticks_new],ecx + jmp still + +@@: cmp ah,105 ;i + jne @f + xor ecx,ecx + .105_0: + mov byte [SolveMap+ecx],0 + mov byte [Map+ecx],0 + inc ecx + cmp ecx,9*9 + jb .105_0 + jmp .todraw + +@@: cmp ah,114 ;r + jne .43 + xor ecx,ecx + .114_0: + mov al,[Map+ecx] + cmp al,9 + jbe @f + sub al,10 + @@: + mov [SolveMap+ecx],al + inc ecx + cmp ecx,9*9 + jb .114_0 + mov esi,SolveMap + call Solve + cmp [_iRet],1 + jne @f + mov edx,txt.check_yes + call Show_message + jmp still + @@: ;­Ґв аҐиҐ­Ё© + xor ecx,ecx + @@: + mov byte [SolveMap+ecx],0 + inc ecx + cmp ecx,9*9 + jb @b + mov edx,txt.nosolve + call Show_message + jmp still + +.43: cmp ah,43 ;+ + jne .45 + cmp [Difficult],9 + je still + inc [Difficult] + call show_level + jmp still +.45: ;- + cmp ah,45 + jne .99 + cmp [Difficult],0 + je still + dec [Difficult] + call show_level + jmp still + +.99: ;Check + cmp ah,99 + jne .39 + bts [flags],15 + xor ecx,ecx + mov edx,txt.check_no +; @@: mov al,byte [Map+ecx] +; cmp byte [SolveMap+ecx],al +; jne @f +; inc ecx +; cmp ecx,9*9 +; jb @b + @@: mov al,byte [Map+ecx] ;ЇҐаҐ­®бЁ¬ §­ зҐ­Ёп ў® ўаҐ¬Ґ­­л© ¬ ббЁў + cmp al,9 + jbe .991 + sub al,10 + .991: + mov [TempMap+ecx],al + inc ecx + cmp ecx,9*9 + jb @b + mov esi,TempMap + call CheckSudoku + jc @f + mov edx,txt.check_yes + @@: btr [flags],15 + call Show_message + jmp .todraw + +.39: cmp ah,0x39 + ja .110 + cmp ah,0x30 + jb still + sub ah,0x30 + mov cl,ah + + movzx eax,[Y] + dec al + mov ebx,9 + mul bl + mov bl,[X] + dec bl + add al,bl + mov esi,Map + cmp byte [esi+eax],9 + jg still + mov [esi+eax],cl + jmp .onedraw + +.110: cmp ah,110 ;n + jne .176 +.new_game: + call GeneratePlayBoard + mov [Ticks],0 + mcall 26,9 + mov [Ticks_new],eax + jmp redraw_all + +.176: cmp ah,176 ;Єгаб®ал + jne .177 + call draw_one_symbol + dec [X] + cmp [X],1 + jge @f + mov [X],9 +@@: jmp .onedraw +.177: cmp ah,177 + jne .178 + call draw_one_symbol + inc [Y] + cmp [Y],9 + jbe @f + mov [Y],1 +@@: jmp .onedraw +.178: cmp ah,178 + jne .179 + call draw_one_symbol + dec [Y] + cmp [Y],1 + jge @f + mov [Y],9 +@@: jmp .onedraw +.179: cmp ah,179 + jne still + call draw_one_symbol + inc [X] + cmp [X],9 + jbe @f + mov [X],1 +@@: +.onedraw: + bts [flags],4 + call draw_one_symbol + jmp still ;.todraw + +show_level: + movzx ecx,[Difficult] + mcall 47,0x10000,,<205,5>,(0x50000000+Text_clr),Bckgrd_clr +ret + +Show_message: + mcall 4,<5,269>,(0xd0000000+Message_clr),,,Bckgrd_clr +ret + +Timer: + bt [flags],1 + jc still + mcall 26,9 + sub eax,[Ticks_new] + mov ebx,100 + xor edx,edx + div ebx + cmp eax,[Ticks] + je still + mov [Ticks],eax +.1: mov ebx,60 + xor edx,edx + div ebx + push eax + mov ecx,edx + mcall 47,0x00020000,,<206,246>,(0x40000000+Text_clr),Bckgrd_clr + pop ecx + mov edx,189*65536+246 + mcall + bt [flags],5 + jnc @f + btr [flags],5 + ret +@@: jmp still +.0: mov eax,[Ticks] + jmp .1 + +draw_one_symbol: + movzx eax,[X] + mov ebx,24*65536+24 + mul ebx + xchg eax,ebx + add ebx,(1*65536+21-24*65536+24) + movzx eax,[Y] + mov ecx,24*65536+24 + mul ecx + xchg eax,ecx + add ecx,(21*65536+41-24*65536+24) + movzx eax,[Y] + dec al + push ebx + mov ebx,9 + mul bl + mov bl,[X] + add al,bl + dec al + pop ebx + mov esi,Map + add esi,eax + push dword 0 ;­Ґ Єгаб®а + bt [flags],4 + jnc @f + mov dword [esp],1 ;Єгаб®а + btr [flags],4 +@@: mov edi,0 + mov ebp,1 + call out_numbers + pop eax +ret + + +out_numbers: + push ebx ecx esi + shr ebx,16 + inc bx + shl ebx,16 + add ebx,23 + shr ecx,16 + inc cx + shl ecx,16 + add ecx,23 + mov edx,Bckgrd_clr + push ebp + dec dword [esp+4*5] + jnz @f + mov edx,Square_clr +@@: mcall 13 + pop ebp + pop esi + + cmp byte [esi],0 + je .null + cmp byte [esi],9 + jbe .changeable_number + cmp byte [esi],19 + jbe .fixed_number + jmp .null +.end: + inc esi + dec ebp + jnz out_numbers + test edi,edi + jz @f + sub edi,9 + mov ebp,9 + add ebx,-9*24*65536-9*24 + add ecx,24*65536+24 + jmp out_numbers + @@: +ret + +.fixed_number: + push esi + shr ebx,16 + shr ecx,16 + mov dx,bx + shl edx,16 + mov dx,cx + add edx,8*65536+4 + movzx ebx,byte [esi] + sub ebx,10 + dec ebx + shl ebx,4 + add ebx,FONT + mov ecx,8*65536+16 + push esi ebp edi + mov edi,Pltr.fx + cmp dword [esp+4*7],0 + jne @f + mov edi,Pltr.fxk +@@: mov esi,1 + mov ebp,0 + mcall 65 + pop edi ebp esi +.1: pop esi ecx ebx + add ebx,24*65536+24 + jmp .end + +.null: + pop ecx ebx + add ebx,24*65536+24 + jmp .end +.changeable_number: + push esi + shr ebx,16 + shr ecx,16 + mov dx,bx + shl edx,16 + mov dx,cx + add edx,8*65536+4 + movzx ebx,byte [esi] + dec ebx + shl ebx,4 + add ebx,FONT + mov ecx,8*65536+16 + push esi ebp edi + mov edi,Pltr.ch + cmp dword [esp+4*7],0 + jne @f + mov edi,Pltr.chk +@@: mov esi,1 + mov ebp,0 + mcall 65 + pop edi ebp esi + jmp .1 + + + +GeneratePlayBoard: +;i db 0 +;j db 0 +;RandI db 0 +;RandJ db 0 +;iRet db 0 +;//ЈҐ­ҐаЁа㥬 аҐиҐ­­го ¬ ваЁжг +;m: +;for i:=0 to 8 do +; for j:=0 to 8 do +; begin +; Map[i,j]:=0; +; SolveMap[i,j]:=0; +; RealMap[i,j]:=0; +; end; + mov edi,Map + mov esi,SolveMap + mov edx,RealMap + xor ecx,ecx + @@: + mov byte [edi+ecx],0 + mov byte [esi+ecx],0 + mov byte [edx+ecx],0 + inc ecx + cmp ecx,9*9 + jb @b + +;//бв ўЁ¬ а ­¤®¬­® ­ҐбЄ®«мЄ® зЁбҐ« ­  Ї®«Ґ +;for i:=1 to 21 do +; begin +; RandI:=random(9); +; RandJ:=random(9); +; if SolveMap[RandI,RandJ]=0 then +; begin +; SolveMap[RandI,RandJ]:=random(9)+1; +; if not CheckSudoku(SolveMap) then +; begin +; SolveMap[RandI,RandJ]:=0; +; Continue; +; end; +; end else Continue; +; end; + + mov ecx,21 +.1: mov eax,9 + call random + mov ebx,eax + mov eax,9 + call random + mov ah,9 + mul ah + add eax,ebx ;RandI,RandJ + cmp byte [esi+eax],0 + jne .loop + mov ebx,eax + mov eax,9 + call random + mov byte [esi+ebx],al + call CheckSudoku + jnc .loop + mov byte [esi+ebx],0 + .loop: + loop .1 + + +;//аҐи Ґ¬ ‘㤮Єг +;iRet:=Solve(SolveMap); +;if iRet<>1 then goto m; +;i:=1; + + mov esi,SolveMap + call Solve + cmp [_iRet],1 + jne GeneratePlayBoard + + movzx ecx,[Difficult] + movzx ecx,byte [Difficult_array+ecx] + +;case Difficult of +;1: +; while i<=42 do +; begin +; RandI:=random(9); +; RandJ:=random(9); +; if RealMap[RandI,RandJ]<>0 then Continue else +; RealMap[RandI,RandJ]:=SolveMap[RandI,RandJ]; +; inc(i); +; end; +;2: +; while i<=32 do +; begin +; RandI:=random(9); +; RandJ:=random(9); +; if RealMap[RandI,RandJ]<>0 then Continue else +; RealMap[RandI,RandJ]:=SolveMap[RandI,RandJ]; +; inc(i); +; end; +;3: +; while i<=25 do +; begin +; RandI:=random(9); +; RandJ:=random(9); +; if RealMap[RandI,RandJ]<>0 then Continue else +; RealMap[RandI,RandJ]:=SolveMap[RandI,RandJ]; +; inc(i); +; end; +;end; + +.2: + mov eax,9 + call random + mov ebx,eax + mov eax,9 + call random + mov ah,9 + mul ah + cmp al,81 + jb @f + dec al + @@: + add eax,ebx ;RandI,RandJ + cmp byte [RealMap+eax],0 + jne .loop2 + add byte [SolveMap+eax],10 + mov bl,[SolveMap+eax] + mov byte [RealMap+eax],bl + .loop2: + loop .2 + +;for i:=0 to 8 do +; for j:=0 to 8 do +; Map[i,j]:=RealMap[i,j]; +;end; + + xor ecx,ecx +@@: mov al,[RealMap+ecx] + mov [Map+ecx],al + inc ecx + cmp ecx,9*9 + jb @b +ret + + + + +align 4 +rsx1 dw ?;0x4321 +rsx2 dw ?;0x1234 +rsx3 dw ?;0x62e9 +rsx4 dw ?;0x3619 +random: ; Ё§ ASCL + push ecx ebx esi edx + mov cx,ax + mov ax,[rsx1] + mov bx,[rsx2] + mov si,ax + mov di,bx + mov dl,ah + mov ah,al + mov al,bh + mov bh,bl + xor bl,bl + rcr dl,1 + rcr ax,1 + rcr bx,1 + add bx,di + adc ax,si + add bx,[rsx3] + adc ax,[rsx4] + sub [rsx3],di + adc [rsx4],si + mov [rsx1],bx + mov [rsx2],ax + xor dx,dx + cmp ax,0 + je nodiv + cmp cx,0 + je nodiv + div cx +nodiv: + mov ax,dx + pop edx esi ebx ecx + and eax,0000ffffh +ret + + + +if DEBUG +SysMsgBoardNum: ;warning: destroys eax,ebx,ecx,esi + mov ebx,esp + mov ecx,8 + mov esi,(number_to_out+1) +.1: + mov eax,ebx + and eax,0xF + add al,'0' + cmp al,(10+'0') + jb @f + add al,('A'-'0'-10) +@@: + mov [esi+ecx],al + shr ebx,4 + loop .1 + dec esi + mcall 71,1,number_to_out +ret + +number_to_out db '0x00000000',13,10,0 +endf + + + +window_load_save: + popad + mcall 51,1,.thread,(threat_stack+32*4) + pushad + ret +.thread: + bts [flags],6 +.red: + mcall 12,1 + mov edi,txt.load + bt [flags],8 + jc @f + mov edi,txt.save + bt [flags],10 + jnc @f + mov edi,txt.save_solve +@@: mcall 0,50*65536+300,0x70*65536+60,(0x34000000+Bckgrd_clr),, + mcall 8,<245,43>,<2,14>,100,0xaaaaaa + mcall 4,<252,5>,(0x80000000+Text_clr),txt.enter + push dword edit1 + call [edit_box_draw] + mcall 12,2 +.still: + mcall 10 + dec al + jz .red + dec al + jz .key + dec al + jz .button + jmp .still +.button: + mcall 17,1 + cmp ah,1 + jne @f + .end: btr [flags],6 + mcall -1 + @@: cmp ah,100 + jne .still + bt [flags],8 + jc .ld + .sv: call save_sudoku + jnc .end + jmp .err + .ld: call load_sudoku + jnc .end + .err: mcall 4,<5,19>,(0x80000000+Text_clr),txt.error + jmp .still + + +.key: + mcall 2 + cmp ah,13 + jne @f + bt [flags],8 + jc .ld + jmp .sv + @@: cmp ah,27 + je .end + push dword edit1 + call [edit_box_key] + jmp .still + + +save_sudoku: + mov [_size],9*(9+2) + mcall 68,12,[_size] + test eax,eax + jnz @f + stc + ret + +@@: mov [_buffer],eax + mov edx,Map + bt [flags],10 + jnc @f + mov edx,SolveMap +@@: mov esi,eax;[_buffer] + mov ecx,[_size] + xor edi,edi + dec edi + mov ebx,9 +.1: test ecx,ecx + jz .end + test ebx,ebx + jz .2 + inc edi + dec ebx + mov al,[edx+edi] + test al,al + jnz @f + mov byte [esi+edi],0x23 + loop .1 + jmp .end +@@: cmp al,9 + jbe @f + sub al,10 +@@: add al,48 + mov byte [esi+edi],al + loop .1 + jmp .end +.2: mov ebx,9 + mov byte [esi+edi+1],13 + mov byte [esi+edi+2],10 + add esi,2 + sub ecx,2 + jmp .1 + + +.end: mov [func_70.func_n],2 + push [_size] + pop [func_70.param3] + push [_buffer] + pop [func_70.param4] + mov [func_70.name],buf_cmd_lin + mcall 70,func_70 + cmp al,0 ;б®еа ­с­ г¤ з­®? + je @f + mcall 68,13,[_buffer] + stc + ret +@@: mcall 68,13,[_buffer] + clc +ret + +load_sudoku: + mov [func_70.func_n],5 + mov [func_70.param3],0 + mov [func_70.param4],bufferfinfo + mov [func_70.name],buf_cmd_lin + mcall 70,func_70 + test al,al ;д ©« ­ ©¤Ґ­? + jz @f + stc + ret + @@: mov eax, dword [bufferfinfo+32] ;Є®ЇЁа㥬 а §¬Ґа д ©«  + cmp eax,81 + jge @f + stc + ret +@@: cmp eax,100 + jb @f + stc + ret + +_size dd 0 +_buffer dd 0 + +@@: mov [_size],eax + mcall 68,12,[_size] + test eax,eax + jnz @f + stc + ret ;®иЁЎЄ  ­  ўл¤Ґ«Ґ­ЁҐ Ў«®Є  + @@: + mov [_buffer],eax + mov [func_70.func_n],0 + mov [func_70.name],buf_cmd_lin + push dword [_size] + pop dword [func_70.param3] + push dword [_buffer] + pop dword [func_70.param4] + mcall 70,func_70 + test eax,eax + jz @f + stc + ret ;®иЁЎЄ  з⥭Ёп +@@: + + mov edx,Map + mov esi,[_buffer] + mov ecx,[_size] + xor edi,edi + dec edi +.1: test ecx,ecx + jz .end + inc edi + mov al,[esi+edi] + cmp al,0x23 + jne @f + mov byte [edx+edi],0 + loop .1 + jmp .end +@@: cmp al,13 + jne @f + add esi,2 + dec edi + sub ecx,2 + jmp .1 +@@: sub al,48 + mov byte [edx+edi],al + loop .1 +.end: mcall 68,13,[_buffer] + + xor ecx,ecx +@@: mov byte [SolveMap+ecx],0 + inc ecx + cmp ecx,9*9 + jb @b + + mov [Ticks],0 + mcall 26,9 + mov [Ticks_new],eax + + clc +ret + + + + +align 4 +myimport: +edit_box_draw dd aEdit_box_draw +edit_box_key dd aEdit_box_key +edit_box_mouse dd aEdit_box_mouse +version_ed dd aVersion_ed + dd 0 + dd 0 +aEdit_box_draw db 'edit_box',0 +aEdit_box_key db 'edit_box_key',0 +aEdit_box_mouse db 'edit_box_mouse',0 +aVersion_ed db 'version_ed',0 + +edit1 edit_box 240,2,2,Bckgrd_clr,0x6a9480,0,0xAABBCC,0,4096,buf_cmd_lin,ed_focus,2,0,0 + +func_70: + .func_n dd ? + .param1 dd 0 + .param2 dd 0 + .param3 dd ? + .param4 dd ? + .rezerv db 0 + .name dd ? + +if lang eq ru +title db '‘㤮Єг',0 +txt: +.dif db "‘«®¦­®бвм (+/-):",0 +.new db 'Ќ®ў п (N)',0 +.space db 'ђҐиҐ­ЁҐ (Џа®ЎҐ«)',0 +.check db 'Џа®ўҐаЁвм (C)',0 +.check_yes db 'ђҐиҐ­ЁҐ ­ ©¤Ґ­®',0 +.check_no = .nosolve +.time db "‚६п (T) :",0 +.own_map db '‚ўҐбвЁ бў®о ‘г¤®Єг ¤«п аҐиҐ­Ёп (I)',0 +.nosolve db 'ЌҐ аҐиҐ­® ',0 +.solve db 'ђҐиЁвм (R)',0 +.save db '‘®еа ­Ёвм (S)',0 +.save_solve db '‘®еа ­Ёвм аҐиҐ­ЁҐ (A)',0 +.error db 'ЋиЁЎЄ ',0 +.load db '‡ Јаг§Ёвм (L)',0 +.enter db 'Enter',0 +else +title db 'Sudoku',0 +txt: +.dif db "Difficult (+/-)",0 +.new db 'New (N)',0 +.space db 'Solution (Space)',0 +.check db 'Check (C)',0 +.check_yes db 'Right ',0 +.check_no db 'Not right ',0 +.time db " Time (T) :",0 +.own_map db 'Input your own Sudoku (I)',0 +.nosolve db 'It is not solved',0 +.solve db 'Solve (R)',0 +.save db 'Save (S)',0 +.save_solve db 'Save solution (A)',0 +.error db 'Error';,0 +.load db 'Load (L)',0 +.enter db 'Enter',0 +endf + +system_path db '/sys/lib/' +boxlib_name db 'box_lib.obj',0 + +X db 1 +Y db 1 + +Pltr: +.ch dd Bckgrd_clr,Chg_nmb_clr +.chk dd Square_clr,Chg_nmb_clr +.fx dd Bckgrd_clr,Fix_nmb_clr +.fxk dd Square_clr,Fix_nmb_clr + +align 4 +FONT file "SUDOKU.FNT" +;Џ «Ёвал: + + +I_END: +align 16 +Map rb 9*9 +SolveMap rb 9*9 +RealMap rb 9*9 +TempMap rb 9*9 + +cur_dir_path rb 4096 +buf_cmd_lin rb 4096 +bufferfinfo rb 40 +Ticks_new rd 1 ;dd 0 +Ticks rd 1 ;dd 0 +flags rw 1 +threat_stack rd 32 ;: times 32 dd 0 + +D_END: +;ЎЁв 0: б¬. ЇҐаҐ¤ draw_pole +;1: 1-в ©¬Ґа ўЄ«озс­ +;2: ў draw_pole Ё key +;3: 1-Ї®Є § вм аҐис­­го Є авг +;4: in draw_one_symbol +;5: in Timer +;6: 1 ­  нЄа ­Ґ ®Є­® ‘®еа ­Ґ­Ёп/‡ Јаг§ЄЁ +;7: box_lib is not loaded +;8: 0 - б®еа ­Ёвм 1 - § Јаг§Ёвм +;9: 1 - 㢥«ЁзЁвм ўлб®вг ®Є­  +;10: 1 - б®еа ­Ёвм аҐиҐ­ЁҐ +;15 1 - Їа®ўҐаЄ  ЇаЁ ­ ¦ вЁЁ Є« ўЁиЁ ‘ (¤«п CheckSudoku) \ No newline at end of file diff --git a/programs/games/sudoku/trunk/sudoku.fnt b/programs/games/sudoku/trunk/sudoku.fnt new file mode 100644 index 0000000000000000000000000000000000000000..cfce09f81c53f24fe2bdc7c4ba7533746824a50d GIT binary patch literal 144 zcmZQzkg%wTkN|@^1`wz@*2cyoVUTd(*gr7;ACPCk!^YNjtOm?y;gPY)IrEQ)her+~ sf8fA@KWqqjn=~N*7zjYr|2qbh1R4kgVD&X%DTF+jUk6lkrUEDr0IYN>rvLx| literal 0 HcmV?d00001 diff --git a/programs/games/whowtbam/trunk/wwtbam.cpp b/programs/games/whowtbam/trunk/wwtbam.cpp new file mode 100644 index 0000000000..8bca2619f8 --- /dev/null +++ b/programs/games/whowtbam/trunk/wwtbam.cpp @@ -0,0 +1,1283 @@ +// Исходник игры "Кто хочет быть миллионером?" для Колибри ОС +// by Андрей Михайлович (Dron2004) + +#include +#include + +char sVersion[] = "‚ҐабЁп 0.1"; + +int status=0; + +bool needcleanup = false; //Символ того, что игра была начата... Необходимо для высвобождения памяти +int questioncount = 0; //Число вопросов +int currentquestion = 0; //Номер текущего вопроса (1, 2, ..., 15) + +int askedquestions[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +char friendsAdvice[1]={' '}; + +char summs[][16]={"0","100","200","300","500","1000","2000","4000","8000","16000","32000","64000","125000","250000","500000","1000000"}; +char * question; +char * answerA; +char * answerB; +char * answerC; +char * answerD; +Byte correctanswer=0x00; + +int questionlength=0; +int answerAlength=0; +int answerBlength=0; +int answerClength=0; +int answerDlength=0; + +bool na50available = true; +bool callfriendavailable = true; +bool zalavailable = true; + +int zalA=0; +int zalB=0; +int zalC=0; +int zalD=0; + + + +bool drawA = true; +bool drawB = true; +bool drawC = true; +bool drawD = true; + + + + +char * tempquestion; +char * tempanswerA; +char * tempanswerB; +char * tempanswerC; +char * tempanswerD; +Byte tempcorrectanswer=0x00; +int tempquestionlength=0; +int tempanswerAlength=0; +int tempanswerBlength=0; +int tempanswerClength=0; +int tempanswerDlength=0; + + + + +const char header[]="Љв® е®зҐв Ўлвм ¬Ё««Ё®­Ґа®¬ ¤«п Kolibri OS"; +void app_halt(); + +char * filepathname; //Определяем путь и имя файла с базой вопросов +void getFilePathName(){ + int lastslashindex=0; + char ourfilename[]="appdata.dat"; + int tmpcnt=0; + + for (tmpcnt=0;tmpcnt0){ + basefile.Read (inputbyte,1); + if (inputbyte[0]==0x10){ + skipsleft--; + } + inputbyte[0]=0x00; + } + + //Проверим сложность + basefile.Read (inputbyte,1); + + // Нам нужно, чтобы сложность задаваемого вопроса соответствовала номеру задаваемого + // в игре вопроса (на какую сумму мы играем; вопрос на 1000000 должен быть посложнее, + // чем вопрос на 100 рублей :-))) + + if (inputbyte[0]==0x05) //Лёкгий вопрос + { + if (currentquestion > 5){ //Лёгкие вопросы - вопросы от 1 до 5 + goto regenerate; //Если это уже 6 вопрос и более - ищем другой вопрос + } + } + if (inputbyte[0]==0x06) //Средний вопрос + { + if ((currentquestion < 6)||(currentquestion > 10)){ //Средние вопросы - вопросы от 6 до 10 + goto regenerate; + } + } + if (inputbyte[0]==0x07) //Сложный вопрос + { + if (currentquestion < 11){ //Средние вопросы - вопросы от 11 до 15 + goto regenerate; + } + } + + + for (int counter=0; counter 0){ + basefile2.Read (inputbyte,1); + if (inputbyte[0]==0x10){ + skipsleft--; + } + inputbyte[0]=0x00; + } + + basefile2.Read (inputbyte,1); // Это - сложность вопроса. Мы её уже проверили. + + //Читаем вопрос + int currentbyte=0; + while (inputbyte[0]!=0x01){ + basefile2.Read (inputbyte,1); + if (inputbyte[0]!=0x01){tempquestion[currentbyte]=inputbyte[0];} + currentbyte++; + } + tempquestion[currentbyte]='\n'; + + //Читаем ответ A + currentbyte=0; + while (inputbyte[0]!=0x02){ + basefile2.Read (inputbyte,1); + if (inputbyte[0]!=0x02){tempanswerA[currentbyte]=inputbyte[0];} + currentbyte++; + } + tempanswerA[currentbyte]='\n'; + + //Читаем ответ B + currentbyte=0; + while (inputbyte[0]!=0x03){ + basefile2.Read (inputbyte,1); + if (inputbyte[0]!=0x03){tempanswerB[currentbyte]=inputbyte[0];} + currentbyte++; + } + tempanswerB[currentbyte]='\n'; + + //Читаем ответ C + currentbyte=0; + while (inputbyte[0]!=0x04){ + basefile2.Read (inputbyte,1); + if (inputbyte[0]!=0x04){tempanswerC[currentbyte]=inputbyte[0];} + currentbyte++; + } + tempanswerC[currentbyte]='\n'; + + //Читаем ответ D + currentbyte=0; + while (inputbyte[0]!=0x08){ + basefile2.Read (inputbyte,1); + if (inputbyte[0]!=0x08){tempanswerD[currentbyte]=inputbyte[0];} + currentbyte++; + } + tempanswerD[currentbyte]='\n'; + + basefile2.Read (inputbyte,1); // Это-правильный ответ + tempcorrectanswer=inputbyte[0]; + // ВСЁ!!!!!! ГОТОВО!!!! УРА! + + //Считали. Теперь надо перетасовать вопросы. + questionlength = 0; + answerAlength = 0; + answerBlength = 0; + answerClength = 0; + answerDlength = 0; + //Сам вопрос остаётся без изменения + questionlength=tempquestionlength; + question = new char[questionlength]; + for (int cd=0; cd - ­ з вм ЁЈаг", 0); + kos_WriteTextToWindow (10,85,0x80,0x770000, " - ўл室", 0); + + kos_WriteTextToWindow (10,150,0x80,0x000000, "(C) 2008 Ђ­¤аҐ© ЊЁе ©«®ўЁз aka Dron2004", 0); + //kos_DisplayNumberToWindow (questioncount,3,40,60,0x000000, nbDecimal, false); + } + if (status==1){ //Игра + + kos_DrawBar(0,0,610,174,0xEEEEFF); + + kos_WriteTextToWindow (10,10,0x0,0x000000, question, questionlength-1); + + if (drawA==true){ + kos_WriteTextToWindow (10,40,0x80,0x000000, "A. ", 0); + kos_WriteTextToWindow (30,40,0x0,0x000000, answerA, answerAlength-1); + } + if (drawB==true){ + kos_WriteTextToWindow (10,60,0x80,0x000000, "B. ", 0); + kos_WriteTextToWindow (30,60,0x0,0x000000, answerB, answerBlength-1); + } + if (drawC==true){ + kos_WriteTextToWindow (10,80,0x80,0x000000, "C. ", 0); + kos_WriteTextToWindow (30,80,0x0,0x000000, answerC, answerClength-1); + } + if (drawD==true){ + kos_WriteTextToWindow (10,100,0x80,0x000000, "D. ", 0); + kos_WriteTextToWindow (30,100,0x0,0x000000, answerD, answerDlength-1); + } + if (na50available==true){kos_WriteTextToWindow (30,150,0x80,0x000000, "<7> 50 ­  50", 0);} + if (callfriendavailable==true){kos_WriteTextToWindow (150,150,0x80,0x000000, "<8> ‡ў®­®Є ¤агЈг", 0);} + if (zalavailable==true){kos_WriteTextToWindow (280,150,0x80,0x000000, "<9> Џ®¤бЄ §Є  § « ", 0);} + + if((na50available==false)&&(callfriendavailable==false)&&(zalavailable==false)) {kos_WriteTextToWindow (30,150,0x80,0x000000, " - § Ўа вм ¤Ґ­мЈЁ Ё г©вЁ", 0);} + + kos_WriteTextToWindow (430,130,0x80,0x000000, "‚®Їа®б ­ ", 0); + kos_WriteTextToWindow (500,130,0x80,0x000000, summs[currentquestion], 0); + + kos_WriteTextToWindow (430,150,0x80,0x000000, "“ ў б", 0); + kos_WriteTextToWindow (500,150,0x80,0x000000, summs[currentquestion-1], 0); + + + + } + if (status==2){ //Окно "Это - правильный ответ" + kos_DrawBar(0,0,610,174,0xDDFFDD); + kos_WriteTextToWindow (10,10,0x80,0x000000, "„ , нв® Їа ўЁ«м­л© ®вўҐв!", 0); + + kos_WriteTextToWindow (10,150,0x80,0x000000, " - Їа®¤®«¦Ёвм", 0); + } + if (status==3){ //Вы выиграли миллион, однако ж!!! + kos_DrawBar(0,0,610,174,0x00FF00); + kos_WriteTextToWindow (10,10,0x80,0x000000, "‚л ўлЁЈа «Ё ¬Ё««Ё®­!!!", 0); + kos_WriteTextToWindow (10,150,0x80,0x000000, " - ўл室", 0); + } + if (status==4){ //Звонок другу + kos_DrawBar(0,0,610,174,0xAAFFFF); + kos_WriteTextToWindow (10,10,0x80,0x000000, "„агЈ б®ўҐвгҐв ў ¬ ®вўҐв", 0); + kos_WriteTextToWindow (165,10,0x80,0x000000, friendsAdvice, 0); + kos_WriteTextToWindow (10,150,0x80,0x000000, " - Їа®¤®«¦Ёвм", 0); + } + if (status==5){ //Подсказка зала + kos_DrawBar(0,0,610,174,0xAAFFFF); + kos_WriteTextToWindow (10,10,0x80,0x000000, "Њ­Ґ­ЁҐ  г¤Ёв®аЁЁ а бЇаҐ¤Ґ«Ё«®бм в Є:", 0); + if (drawA==true){ + kos_WriteTextToWindow (10,30,0x80,0x000000, "ЋвўҐв A: ", 0); + kos_DisplayNumberToWindow(zalA,3,60,30,0x000000,nbDecimal,0); + kos_WriteTextToWindow (80,30,0x80,0x000000, "%", 0); + } + if (drawB==true){ + kos_WriteTextToWindow (10,45,0x80,0x000000, "ЋвўҐв B: ", 0); + kos_DisplayNumberToWindow(zalB,3,60,45,0x000000,nbDecimal,0); + kos_WriteTextToWindow (80,45,0x80,0x000000, "%", 0); + } + if (drawC==true){ + kos_WriteTextToWindow (10,60,0x80,0x000000, "ЋвўҐв C: ", 0); + kos_DisplayNumberToWindow(zalC,3,60,60,0x000000,nbDecimal,0); + kos_WriteTextToWindow (80,60,0x80,0x000000, "%", 0); + } + if (drawD==true){ + kos_WriteTextToWindow (10,75,0x80,0x000000, "ЋвўҐв D: ", 0); + kos_DisplayNumberToWindow(zalD,3,60,75,0x000000,nbDecimal,0); + kos_WriteTextToWindow (80,75,0x80,0x000000, "%", 0); + } + + + + + + kos_WriteTextToWindow (10,150,0x80,0x000000, " - Їа®¤®«¦Ёвм", 0); + } + + if (status==6){ //Вы забрали деньги ;-) + kos_DrawBar(0,0,610,174,0xBBFFBB); + kos_WriteTextToWindow (10,10,0x80,0x000000, "‚л § Ўа «Ё ¤Ґ­мЈЁ Ё ги«Ё. ‚ и ўлЁЈали б®бв ўЁ«:", 0); + kos_WriteTextToWindow (10,20,0x80,0x000000, summs[currentquestion-1], 0); + kos_WriteTextToWindow (10,150,0x80,0x000000, " - ўл室", 0); + } + if (status==-1){ //Вы ошиблись :-( + kos_DrawBar(0,0,610,174,0xFF8888); + kos_WriteTextToWindow (10,10,0x80,0x000000, "Љ ᮦ «Ґ­Ёо, ўл ®иЁЎ«Ёбм... Џа ўЁ«м­л© ®вўҐв -", 0); + + switch (correctanswer){ + case 0x01: + kos_WriteTextToWindow (10,25,0x80,0x000000, "A. ", 0); + kos_WriteTextToWindow (30,25,0x0,0x000000, answerA, answerAlength-1); + break; + case 0x02: + kos_WriteTextToWindow (10,25,0x80,0x000000, "B. ", 0); + kos_WriteTextToWindow (30,25,0x0,0x000000, answerB, answerBlength-1); + break; + case 0x03: + kos_WriteTextToWindow (10,25,0x80,0x000000, "C. ", 0); + kos_WriteTextToWindow (30,25,0x0,0x000000, answerC, answerClength-1); + break; + case 0x04: + kos_WriteTextToWindow (10,25,0x80,0x000000, "D. ", 0); + kos_WriteTextToWindow (30,25,0x0,0x000000, answerD, answerDlength-1); + break; + } + kos_WriteTextToWindow (10,50,0x80,0x000000, "‚ १г«мв вҐ ўл ўлЁЈа «Ё:", 0); + + if (currentquestion<6) {kos_WriteTextToWindow (220,50,0x80,0x000000,summs[0], 0);} + if ((currentquestion>5)&&(currentquestion<11)) {kos_WriteTextToWindow (220,50,0x80,0x000000,summs[5], 0);} + if (currentquestion>10) {kos_WriteTextToWindow (220,50,0x80,0x000000,summs[10], 0);} + + + + + kos_WriteTextToWindow (10,150,0x80,0x000000, " - ўл室", 0); + } + + kos_WindowRedrawStatus(2); + +} + + + +void call_friend(){ + int tmpcodee; + + recode5: + tmpcodee =(rtlRand()%10)+1; + int tmpbyte; + + if (currentquestion < 6 ){ + if (tmpcodee>3){ //Друг знает + if (correctanswer==0x01) {friendsAdvice[0]='A';} + if (correctanswer==0x02) {friendsAdvice[0]='B';} + if (correctanswer==0x03) {friendsAdvice[0]='C';} + if (correctanswer==0x04) {friendsAdvice[0]='D';} + } + else //Друг говорит наугад + { + + int tmpbyte2=0; + recode51: + int tmpcodee2=(rtlRand()%4)+1; + + switch(tmpcodee2){ + case 1: + friendsAdvice[0]='A'; + break; + case 2: + friendsAdvice[0]='B'; + break; + case 3: + friendsAdvice[0]='C'; + break; + case 4: + friendsAdvice[0]='D'; + break; + } + } + + } + + if ((currentquestion > 5) && (currentquestion<11)){ + if (tmpcodee>5){ //Друг знает + if (correctanswer==0x01) {friendsAdvice[0]='A';} + if (correctanswer==0x02) {friendsAdvice[0]='B';} + if (correctanswer==0x03) {friendsAdvice[0]='C';} + if (correctanswer==0x04) {friendsAdvice[0]='D';} + } + else //Друг говорит наугад + { + + int tmpbyte2=0; + recode52: + int tmpcodee2=(rtlRand()%4)+1; + switch(tmpcodee2){ + case 1: + friendsAdvice[0]='A'; + break; + case 2: + friendsAdvice[0]='B'; + break; + case 3: + friendsAdvice[0]='C'; + break; + case 4: + friendsAdvice[0]='D'; + break; + } + } + + } + + if (currentquestion > 10){ + if (tmpcodee>7){ //Друг знает + if (correctanswer==0x01) {friendsAdvice[0]='A';} + if (correctanswer==0x02) {friendsAdvice[0]='B';} + if (correctanswer==0x03) {friendsAdvice[0]='C';} + if (correctanswer==0x04) {friendsAdvice[0]='D';} + } + else //Друг говорит наугад + { + + int tmpbyte2=0; + recode53: + int tmpcodee2=(rtlRand()%4)+1; + + switch(tmpcodee2){ + case 1: + friendsAdvice[0]='A'; + break; + case 2: + friendsAdvice[0]='B'; + break; + case 3: + friendsAdvice[0]='C'; + break; + case 4: + friendsAdvice[0]='D'; + break; + } + } + + if ((friendsAdvice[0]=='A')&&(drawA==false)){goto recode5;} + if ((friendsAdvice[0]=='B')&&(drawB==false)){goto recode5;} + if ((friendsAdvice[0]=='C')&&(drawC==false)){goto recode5;} + if ((friendsAdvice[0]=='D')&&(drawD==false)){goto recode5;} + } + + + + + + +} + +void call_zal(){ //Подсказка зала + int maxpercent=0; + for (int tmpc=0; tmpc<(16-currentquestion);tmpc=tmpc+2){ + maxpercent=(rtlRand()%101); + if (maxpercent>50) {break;} + } + + if ((drawA==true)&&(drawB==true)&&(drawC==true)&&(drawD==true)){ + switch (correctanswer){ + case 0x01: + zalA=maxpercent; + zalB=(rtlRand()%(101-zalA)); + zalC=(rtlRand()%(101-zalA-zalB)); + zalD=100-zalA-zalB-zalC; + break; + + case 0x02: + zalB=maxpercent; + zalA=(rtlRand()%(101-zalB)); + zalC=(rtlRand()%(101-zalA-zalB)); + zalD=100-zalA-zalB-zalC; + break; + + case 0x03: + zalC=maxpercent; + zalB=(rtlRand()%(101-zalC)); + zalA=(rtlRand()%(101-zalC-zalB)); + zalD=100-zalA-zalB-zalC; + break; + + case 0x04: + zalD=maxpercent; + zalB=(rtlRand()%(101-zalD)); + zalC=(rtlRand()%(101-zalD-zalB)); + zalA=100-zalD-zalB-zalC; + break; + } + } + else + { + if ((drawA==true)&&(drawB==true)){ + if (correctanswer==0x01){ + zalA=maxpercent; + zalB=100-zalA; + } + else + { + zalB=maxpercent; + zalA=100-zalB; + } + } + if ((drawA==true)&&(drawC==true)){ + if (correctanswer==0x01){ + zalA=maxpercent; + zalC=100-zalA; + } + else + { + zalC=maxpercent; + zalA=100-zalC; + } + } + if ((drawA==true)&&(drawD==true)){ + if (correctanswer==0x01){ + zalA=maxpercent; + zalD=100-zalA; + } + else + { + zalD=maxpercent; + zalA=100-zalD; + } + } + + if ((drawB==true)&&(drawC==true)){ + if (correctanswer==0x02){ + zalB=maxpercent; + zalC=100-zalB; + } + else + { + zalC=maxpercent; + zalB=100-zalC; + } + } + if ((drawB==true)&&(drawD==true)){ + if (correctanswer==0x02){ + zalB=maxpercent; + zalD=100-zalB; + } + else + { + zalD=maxpercent; + zalB=100-zalD; + } + } + + if ((drawC==true)&&(drawD==true)){ + if (correctanswer==0x03){ + zalC=maxpercent; + zalD=100-zalC; + } + else + { + zalD=maxpercent; + zalC=100-zalD; + } + } + + } +} + +void kos_Main(){ + rtlSrand(kos_GetSystemClock() / 10000); + getFilePathName(); + prepareFileData(); + draw_window(); + while (true){ + + switch (kos_WaitForEvent()){ + case 1: + draw_window(); + break; + case 2: + Byte keyCode; + kos_GetKey(keyCode); + + if (status==0){ //Меню + if (keyCode==27){ + app_halt(); + } + if (keyCode==13){ + currentquestion=1; + status=1; + loadquestion(); + ////// ПОМЕНЯТЬ МЕСТАМИ!!!!!!! ///////// + draw_window(); + + } + } + if (status==1){ //Игра + + if (keyCode==8){ + status=6; + draw_window(); + } + + if (drawA==true){ + if ((keyCode==49)||(keyCode==97)||(keyCode==65)){ + if (correctanswer==0x01){ + status=2; + } + else + { + status=-1; + } + drawA = true; + drawB = true; + drawC = true; + drawD = true; + + draw_window(); + } + } + + if (drawB==true){ + if ((keyCode==50)||(keyCode==98)||(keyCode==66)){ + if (correctanswer==0x02){ + status=2; + } + else + { + status=-1; + } + drawA = true; + drawB = true; + drawC = true; + drawD = true; + + draw_window(); + } + } + if (drawC==true){ + if ((keyCode==51)||(keyCode==99)||(keyCode==67)){ + if (correctanswer==0x03){ + status=2; + } + else + { + status=-1; + } + drawA = true; + drawB = true; + drawC = true; + drawD = true; + + draw_window(); + } + } + if (drawD==true){ + if ((keyCode==52)||(keyCode==100)||(keyCode==68)){ + if (correctanswer==0x04){ + status=2; + } + else + { + status=-1; + } + drawA = true; + drawB = true; + drawC = true; + drawD = true; + + draw_window(); + } + } + + if (callfriendavailable==true){ //Реализация подсказки "Звонок другу" + if (keyCode==56){ + callfriendavailable=false; + status=4; + call_friend(); + draw_window(); + } + } + + if (zalavailable==true){ //Реализация подсказки зала + if (keyCode==57){ + zalavailable=false; + status=5; + call_zal(); + draw_window(); + } + } + + if (na50available==true){ //Реализация подсказки "50 на 50" + if (keyCode==55){ + + if (correctanswer==0x01){ + drawA=true; + + int tmpcodee; + + recode1: + tmpcodee =(rtlRand()%3)+1; + + int tmpbyte; + + switch(tmpcodee){ + case 1: + drawB=true; + drawC=false; + drawD=false; + break; + case 2: + drawB=false; + drawC=true; + drawD=false; + case 3: + drawB=false; + drawC=false; + drawD=true; + + } + } + if (correctanswer==0x02){ + drawB=true; + + int tmpcodee; + + recode2: + tmpcodee =(rtlRand()%3)+1; + + int tmpbyte; + + + switch(tmpcodee){ + case 1: + drawA=true; + drawC=false; + drawD=false; + break; + case 2: + drawA=false; + drawC=true; + drawD=false; + case 3: + drawA=false; + drawC=false; + drawD=true; + + } + } + if (correctanswer==0x03){ + drawC=true; + + int tmpcodee; + + recode3: + tmpcodee =(rtlRand()%3)+1; + int tmpbyte; + + + switch(tmpcodee){ + case 1: + drawB=true; + drawA=false; + drawD=false; + break; + case 2: + drawB=false; + drawA=true; + drawD=false; + case 3: + drawB=false; + drawA=false; + drawD=true; + + } + } + if (correctanswer==0x04){ + drawA=true; + + int tmpcodee; + + recode4: + tmpcodee =(rtlRand()%3)+1; + + int tmpbyte; + + + switch(tmpcodee){ + case 1: + drawB=true; + drawC=false; + drawA=false; + break; + case 2: + drawB=false; + drawC=true; + drawA=false; + case 3: + drawB=false; + drawC=false; + drawA=true; + + } + } + na50available=false; + draw_window(); + + } + } + + } + if (status==2){ //Окно "Это - правильный ответ!" + if (keyCode==13){ + if (currentquestion<15){ + currentquestion++; + status=1; + loadquestion(); + draw_window(); + } + else + { + status=3; + draw_window(); + } + + } + } + if (status==3){ //Вы выиграли миллион + if (keyCode==27){ + app_halt(); + } + } + if (status==4){ //Совет друга + if (keyCode==13){ + status=1; + draw_window(); + } + } + if (status==5){ //Подсказка зала + if (keyCode==13){ + status=1; + draw_window(); + } + } + if (status==6){ //Вы забрали деньги ;-) + if (keyCode==27){ + app_halt(); + } + } + if (status==-1){ //Вы ошиблись :-( + if (keyCode==27){ + app_halt(); + } + } + + //kos_DrawBar(38,118,50,130,0xBBBBBB); + //kos_DisplayNumberToWindow (keyCode,3,40,120,0x000000, nbDecimal, false); + + + break; + case 3: + app_halt(); + break; + } + + } +} + + +void app_halt(){ + delete filepathname; + + if (needcleanup==true){ + delete question; + delete answerA; + delete answerB; + delete answerC; + delete answerD; + } + kos_ExitApp(); +} diff --git a/programs/games/xonix/trunk/MCSMEMM.H b/programs/games/xonix/trunk/MCSMEMM.H new file mode 100644 index 0000000000..42d61eaadb --- /dev/null +++ b/programs/games/xonix/trunk/MCSMEMM.H @@ -0,0 +1,28 @@ +// + +struct MemBlock +{ + Dword Size; + Dword Addr; + MemBlock *Next; + MemBlock *Previous; +}; + + +#define INITIALQUEUESIZE (32 * 4) + +#define FALSE 0 +#define TRUE -1 + +#define MB_FREE 0 +#define MB_USER 1 + +#define SIZE_ALIGN 4 + + + +Byte *allocmem( Dword reqsize ); +Dword freemem( void *vaddress ); + + + diff --git a/programs/games/xonix/trunk/Release/pe2kos.exe b/programs/games/xonix/trunk/Release/pe2kos.exe new file mode 100644 index 0000000000000000000000000000000000000000..bef0e7ce2dc89dcc6c3a8675f0b1892a10205e2f GIT binary patch literal 13312 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/programs/games/xonix/trunk/kosSyst.cpp b/programs/games/xonix/trunk/kosSyst.cpp new file mode 100644 index 0000000000..af685c0927 --- /dev/null +++ b/programs/games/xonix/trunk/kosSyst.cpp @@ -0,0 +1,829 @@ +#include "kosSyst.h" + +#define atexitBufferSize 32 + + +char pureCallMessage[] = "PURE function call!"; + +char *kosExePath = NULL; + +// +void (__cdecl *atExitList[atexitBufferSize])(); +int atExitFnNum = 0; +// +int __cdecl atexit( void (__cdecl *func )( void )) +{ + // + if ( atExitFnNum < atexitBufferSize ) + { + // + atExitList[atExitFnNum++] = func; + return 0; + } + else + { + return 1; + } +} + + +// +Dword RandomSeed = 1; +// +void rtlSrand( Dword seed ) +{ + RandomSeed = seed; +} +// +Dword rtlRand( void ) +{ + //маска 0x80000776 + + Dword dwi, i; + + for ( i = 0; i < 32; i++ ) + { + + dwi = RandomSeed & 0x80000776; + + __asm{ + mov eax, dwi + mov edx, eax + bswap eax + xor eax, edx + xor al, ah + setpo al + movzx eax, al + mov dwi, eax + } + + RandomSeed = ( RandomSeed << 1 ) | ( dwi & 1 ); + } + + return RandomSeed; +} + +// +void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ) +{ + __asm{ + mov edi, dst + mov eax, dst + mov esi, src + mov ecx, bytesCount + rep movsb + } +} + +// +void memset( Byte *dst, Byte filler, Dword count ) +{ + // + __asm{ + mov edi, dst + mov al, filler + mov ecx, count + rep stosb + } +} + +// +Dword rtlInterlockedExchange( Dword *target, Dword value ) +{ +// Dword result; + + // + __asm{ + mov eax, value + mov ebx, target + xchg eax, [ebx] +// mov result, eax + } + // +// return result; +} + + +////////////////////////////////////////////////////////////////////// +// +// копирование строки +// + +char * __cdecl strcpy( char *target, const char *source ) +{ + char *result = target; + + while( target[0] = source[0] ) + { + target++; + source++; + } + + return result; +} + + +////////////////////////////////////////////////////////////////////// +// +// реверсивный поиск символа +// + +char * __cdecl strrchr( const char * string, int c ) +{ + char *cPtr; + + // + for ( cPtr = (char *)string + strlen( string ); cPtr >= string; cPtr-- ) + { + // + if ( *cPtr == c ) return cPtr; + } + // + return NULL; +} + + +////////////////////////////////////////////////////////////////////// +// +// определение длины строки +// + +int __cdecl strlen( const char *line ) +{ + int i; + + for( i=0; line[i] != 0; i++ ); + return i; +} + + + +////////////////////////////////////////////////////////////////////// +// +// перевод шестнадцатиричного числа в символ +// + +unsigned int num2hex( unsigned int num ) +{ + if( num < 10 ) + return num + '0'; + return num - 10 + 'A'; +} + + +////////////////////////////////////////////////////////////////////// +// +// вывод строки на печать +// + +Dword dectab[] = { 1000000000, 100000000, 10000000, 1000000, 100000, + 10000, 1000, 100, 10, 0 }; + +// +void sprintk( char *Str, PRINTK *arg ) +{ + int i, fmtlinesize, j, ac, k, flag; + Dword head, tail; + char c; + + // + ac = 0; + + // + fmtlinesize = strlen( arg->fmtline ); + // + if( fmtlinesize == 0 ) return; + + // + for( i = 0, j = 0; i < fmtlinesize; i++ ) + { + // + c = arg->fmtline[i]; + // + if( c != '%' ) + { + Str[j++] = c; + continue; + } + // + i++; + // + if( i >= fmtlinesize ) break; + + // + flag = 0; + // + c = arg->fmtline[i]; + // + switch( c ) + { + // + case '%': + Str[j++] = c; + break; + // вывод строки + case 'S': + for( k = 0; ( c = ((Byte *)arg->args[ac])[k] ) != 0; k++ ) + { + Str[j++] = c; + } + ac++; + break; + // вывод байта + case 'B': + k = (int)(arg->args[ac]) & 0xFF; + Str[j++] = num2hex( ( k >> 4 ) & 0xF ); + Str[j++] = num2hex( k & 0xF ); + ac++; + break; + // вывод символа + case 'C': + Str[j++] = (int)(arg->args[ac]) & 0xFF; + ac++; + break; + // вывод двойного слова в шестнадцатиричном виде + case 'X': + for( k = 7; k >= 0; k-- ) + { + // + c = num2hex ( ( (Dword)(arg->args[ac]) >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + if( flag == 0 ) Str[j++] = '0'; + ac++; + break; + // вывод двойного слова в десятичном виде + case 'U': + head = (Dword)(arg->args[ac]); + tail = 0; + for( k = 0; dectab[k] != 0; k++ ) + { + tail = head % dectab[k]; + head /= dectab[k]; + c = head + '0'; + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + // + head = tail; + } + // + c = head + '0'; + Str[j++] = c; + ac++; + break; + // вывод 64-битного слова в шестнадцатиричном виде + case 'Q': + for( k = 7; k >= 0; k-- ) + { + // + c = num2hex ( ( *((unsigned int *)(arg->args[ac]) + 1) >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + for( k=7; k >= 0; k-- ) + { + // + c = num2hex ( ( *((unsigned int *)(arg->args[ac])) >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + if( flag == 0 ) Str[j++] = '0'; + // + ac++; + break; + // + default: + break; + } + } + // + Str[j] = 0; +} + + +// функция -1 завершения процесса +void kos_ExitApp() +{ + int i; + + // + for ( i = atExitFnNum - 1; i >= 0; i-- ) + { + // + atExitList[i](); + } + // + __asm{ + mov eax, -1 + int 0x40 + } +} + + +// функция 0 +void kos_DefineAndDrawWindow( + Word x, Word y, + Word sizeX, Word sizeY, + Byte mainAreaType, + Dword mainAreaColour, + Byte headerType, + Dword headerColour, + Dword borderColour + ) +{ + Dword arg1, arg2, arg3, arg4; + + // + arg1 = ( x << 16 ) + sizeX; + arg2 = ( y << 16 ) + sizeY; + arg3 = ( mainAreaType << 24 ) | mainAreaColour; + arg4 = ( headerType << 24 ) | headerColour; + // + __asm{ + mov eax, 0 + mov ebx, arg1 + mov ecx, arg2 + mov edx, arg3 + mov esi, arg4 + mov edi, borderColour + int 0x40 + } +} + + +// функция 1 поставить точку +void kos_PutPixel( Dword x, Dword y, Dword colour ) +{ + // + __asm{ + mov eax, 1 + mov ebx, x + mov ecx, y + mov edx, colour + int 0x40 + } +} + + +// функция 2 получить код нажатой клавиши +bool kos_GetKey( Byte &keyCode ) +{ + Dword result; + + // + __asm{ + mov eax, 2 + int 0x40 + mov result, eax + } + // + keyCode = result >> 8; + // + return ( result & 0xFF ) == 0; +} + + +// функция 3 получить время +Dword kos_GetSystemClock() +{ +// Dword result; + + // + __asm{ + mov eax, 3 + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 4 +void kos_WriteTextToWindow( + Word x, + Word y, + Byte fontType, + Dword textColour, + char *textPtr, + Dword textLen + ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | y; + arg2 = ( fontType << 24 ) | textColour; + // + __asm{ + mov eax, 4 + mov ebx, arg1 + mov ecx, arg2 + mov edx, textPtr + mov esi, textLen + int 0x40 + } +} + + +// функция 5 пауза, в сотых долях секунды +void kos_Pause( Dword value ) +{ + // + __asm{ + mov eax, 5 + mov ebx, value + int 0x40 + } +} + + +// функция 7 нарисовать изображение +void kos_PutImage( RGB * imagePtr, Word sizeX, Word sizeY, Word x, Word y ) +{ + Dword arg1, arg2; + + // + arg1 = ( sizeX << 16 ) | sizeY; + arg2 = ( x << 16 ) | y; + // + __asm{ + mov eax, 7 + mov ebx, imagePtr + mov ecx, arg1 + mov edx, arg2 + int 0x40 + } +} + + + +// функция 8 определить кнопку +void kos_DefineButton( Word x, Word y, Word sizeX, Word sizeY, Dword buttonID, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | sizeX; + arg2 = ( y << 16 ) | sizeY; + // + __asm{ + mov eax, 8 + mov ebx, arg1 + mov ecx, arg2 + mov edx, buttonID + mov esi, colour + int 0x40 + } +} + + +// функция 9 - информация о процессе +Dword kos_ProcessInfo( sProcessInfo *targetPtr, Dword processID ) +{ +// Dword result; + + // + __asm{ + mov eax, 9 + mov ebx, targetPtr + mov ecx, processID + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 10 +Dword kos_WaitForEvent() +{ +// Dword result; + + __asm{ + mov eax, 10 + int 0x40 +// mov result, eax + } + +// return result; +} + + +// функция 11 +Dword kos_CheckForEvent() +{ +// Dword result; + + __asm{ + mov eax, 11 + int 0x40 +// mov result, eax + } + +// return result; +} + + +// функция 12 +void kos_WindowRedrawStatus( Dword status ) +{ + __asm{ + mov eax, 12 + mov ebx, status + int 0x40 + } +} + + +// функция 13 нарисовать полосу +void kos_DrawBar( Word x, Word y, Word sizeX, Word sizeY, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | sizeX; + arg2 = ( y << 16 ) | sizeY; + // + __asm{ + mov eax, 13 + mov ebx, arg1 + mov ecx, arg2 + mov edx, colour + int 0x40 + } +} + + +// функция 17 +bool kos_GetButtonID( Dword &buttonID ) +{ + Dword result; + + // + __asm{ + mov eax, 17 + int 0x40 + mov result, eax + } + // + buttonID = result >> 8; + // + return (result & 0xFF) == 0; +} + + +// функция 23 +Dword kos_WaitForEvent( Dword timeOut ) +{ +// Dword result; + + __asm{ + mov eax, 23 + mov ebx, timeOut + int 0x40 +// mov result, eax + } + +// return result; +} + + +// получение информации о состоянии "мыши" функция 37 +void kos_GetMouseState( Dword & buttons, int & cursorX, int & cursorY ) +{ + Dword mB; + Word curX; + Word curY; + sProcessInfo sPI; + + // + __asm{ + mov eax, 37 + mov ebx, 0 + int 0x40 + mov curY, ax + shr eax, 16 + mov curX, ax + mov eax, 37 + mov ebx, 2 + int 0x40 + mov mB, eax + } + // + kos_ProcessInfo( &sPI ); + // + buttons = mB; + cursorX = curX - sPI.processInfo.x_start; + cursorY = curY - sPI.processInfo.y_start; +} + + +// функция 40 установить маску событий +void kos_SetMaskForEvents( Dword mask ) +{ + // + __asm{ + mov eax, 40 + mov ebx, mask + int 0x40 + } +} + + +// функция 47 вывести в окно приложения число +void kos_DisplayNumberToWindow( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + eNumberBase nBase, + bool valueIsPointer + ) +{ + Dword arg1, arg2; + + // + arg1 = ( valueIsPointer ? 1 : 0 ) | + ( ((Byte)nBase) << 8 ) | + ( ( digitsNum & 0x1F ) << 16 ); + arg2 = ( x << 16 ) | y; + // + __asm{ + mov eax, 47 + mov ebx, arg1 + mov ecx, value + mov edx, arg2 + mov esi, colour + int 0x40 + } +} + + +// функция 70 доступ к файловой системе +Dword kos_FileSystemAccess( kosFileInfo *fileInfo ) +{ +// Dword result; + + // + __asm{ + mov eax, 70 + mov ebx, fileInfo + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 63 вывод символя в окно отладки +void kos_DebugOutChar( char ccc ) +{ + // + __asm{ + mov eax, 63 + mov ebx, 1 + mov cl, ccc + int 0x40 + } +} + + +// функция 66 режим получения данных от клавиатуры +void kos_SetKeyboardDataMode( Dword mode ) +{ + // + __asm{ + mov eax, 66 + mov ebx, 1 + mov ecx, mode + int 0x40 + } +} + + +// вывод строки в окно отладки +void rtlDebugOutString( char *str ) +{ + // + for ( ; str[0] != 0; str++ ) + { + kos_DebugOutChar( str[0] ); + } + // + kos_DebugOutChar( 13 ); + kos_DebugOutChar( 10 ); +} + + +// функция 64 изменение количества памяти, выделенной для программы +bool kos_ApplicationMemoryResize( Dword targetSize ) +{ + Dword result; + + // + __asm{ + mov eax, 64 + mov ebx, 1 + mov ecx, targetSize + int 0x40 + mov result, eax + } + // + return result == 0; +} + + +// функция 67 изменить параметры окна, параметр == -1 не меняется +void kos_ChangeWindow( Dword x, Dword y, Dword sizeX, Dword sizeY ) +{ + // + __asm{ + mov eax, 67 + mov ebx, x + mov ecx, y + mov edx, sizeX + mov esi, sizeY + int 0x40 + } +} + + + +// вызов абстрактного метода +int __cdecl _purecall() +{ + rtlDebugOutString( pureCallMessage ); + kos_ExitApp(); + return 0; +} + + +// вызов статических инициализаторов +// заодно инициализация генератора случайных чисел +#pragma section(".CRT$XCA",long,read,write) +#pragma section(".CRT$XCZ",long,read,write) +typedef void (__cdecl *_PVFV)(void); +__declspec(allocate(".CRT$XCA")) _PVFV __xc_a[1] = { NULL }; +__declspec(allocate(".CRT$XCZ")) _PVFV __xc_z[1] = { NULL }; +// +#pragma comment(linker, "/merge:.CRT=.rdata") +// +void crtStartUp() +{ + // вызываем инициализаторы по списку, NULL'ы игнорируем + for ( _PVFV *pbegin = __xc_a; pbegin < __xc_z; pbegin++ ) + { + // + if ( *pbegin != NULL ) + (**pbegin)(); + } + // инициализируем генератор случайных чисел + rtlSrand( kos_GetSystemClock() ); + // путь к файлу процесса + kosExePath = *((char **)0x20); + // вызов главной функции приложения + kos_Main(); + // выход + kos_ExitApp(); +} + + diff --git a/programs/games/xonix/trunk/kosSyst.h b/programs/games/xonix/trunk/kosSyst.h new file mode 100644 index 0000000000..aed509e253 --- /dev/null +++ b/programs/games/xonix/trunk/kosSyst.h @@ -0,0 +1,201 @@ +typedef unsigned __int32 Dword; +typedef unsigned __int16 Word; +typedef unsigned __int8 Byte; +typedef unsigned __int32 size_t; + +#define NULL 0 + +#define MAX_PATH 256 + +#define FO_READ 0 +#define FO_WRITE 2 + +#define EM_WINDOW_REDRAW 1 +#define EM_KEY_PRESS 2 +#define EM_BUTTON_CLICK 4 +#define EM_APP_CLOSE 8 +#define EM_DRAW_BACKGROUND 16 +#define EM_MOUSE_EVENT 32 +#define EM_IPC 64 +#define EM_NETWORK 256 + +#define KM_CHARS 0 +#define KM_SCANS 1 + +#define WRS_BEGIN 1 +#define WRS_END 2 + +#define PROCESS_ID_SELF -1 + +#define abs(a) (a<0?0-a:a) + + +struct kosFileInfo +{ + Dword rwMode; + Dword offsetLow; + Dword offsetHigh; + Dword dataCount; + Byte *bufferPtr; + char fileURL[MAX_PATH]; +}; + + +struct RGB +{ + Byte b; + Byte g; + Byte r; + // + RGB() {}; + // + RGB( Dword value ) + { + r = value >> 16; + g = value >> 8; + b = value; + }; + // + bool operator != ( RGB &another ) + { + return this->b != another.b || this->g != another.g || this->r != another.r; + }; + // + bool operator == ( RGB &another ) + { + return this->b == another.b && this->g == another.g && this->r == another.r; + }; +}; + + +union sProcessInfo +{ + Byte rawData[1024]; + struct + { + Dword cpu_usage; + Word window_stack_position; + Word window_stack_value; + Word reserved1; + char process_name[12]; + Dword memory_start; + Dword used_memory; + Dword PID; + Dword x_start; + Dword y_start; + Dword x_size; + Dword y_size; + Word slot_state; + } processInfo; +}; + +struct PRINTK +{ + char *fmtline; + Dword args[11]; +}; + +// +extern char *kosExePath; + +// +void crtStartUp(); +// +int __cdecl _purecall(); +// +int __cdecl atexit( void (__cdecl *func )( void )); +// +void rtlSrand( Dword seed ); +Dword rtlRand( void ); +// +char * __cdecl strcpy( char *target, const char *source ); +int __cdecl strlen( const char *line ); +char * __cdecl strrchr( const char * string, int c ); +// +void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ); +// +void memset( Byte *dst, Byte filler, Dword count ); +// +void sprintk( char *Str, PRINTK *arg ); +// +Dword rtlInterlockedExchange( Dword *target, Dword value ); +// функция -1 завершения процесса +void kos_ExitApp(); +// функция 0 +void kos_DefineAndDrawWindow( + Word x, Word y, + Word sizeX, Word sizeY, + Byte mainAreaType, Dword mainAreaColour, + Byte headerType, Dword headerColour, + Dword borderColour + ); +// функция 1 поставить точку +void kos_PutPixel( Dword x, Dword y, Dword colour ); +// функция 2 получить код нажатой клавиши +bool kos_GetKey( Byte &keyCode ); +// функция 3 получить время +Dword kos_GetSystemClock(); +// функция 4 +void kos_WriteTextToWindow( + Word x, Word y, + Byte fontType, + Dword textColour, + char *textPtr, + Dword textLen + ); +// функция 7 нарисовать изображение +void kos_PutImage( RGB * imagePtr, Word sizeX, Word sizeY, Word x, Word y ); +// функция 8 определить кнопку +void kos_DefineButton( Word x, Word y, Word sizeX, Word sizeY, Dword buttonID, Dword colour ); +// функция 5 пауза, в сотых долях секунды +void kos_Pause( Dword value ); +// функция 9 - информация о процессе +Dword kos_ProcessInfo( sProcessInfo *targetPtr, Dword processID = PROCESS_ID_SELF ); +// функция 10 +Dword kos_WaitForEvent(); +// функция 11 +Dword kos_CheckForEvent(); +// функция 12 +void kos_WindowRedrawStatus( Dword status ); +// функция 13 нарисовать полосу +void kos_DrawBar( Word x, Word y, Word sizeX, Word sizeY, Dword colour ); +// функция 17 +bool kos_GetButtonID( Dword &buttonID ); +// функция 23 +Dword kos_WaitForEvent( Dword timeOut ); +// +enum eNumberBase +{ + nbDecimal = 0, + nbHex, + nbBin +}; +// получение информации о состоянии "мыши" функция 37 +void kos_GetMouseState( Dword & buttons, int & cursorX, int & cursorY ); +// функция 40 установить маску событий +void kos_SetMaskForEvents( Dword mask ); +// функция 47 вывести в окно приложения число +void kos_DisplayNumberToWindow( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + eNumberBase nBase = nbDecimal, + bool valueIsPointer = false + ); +// функция 58 доступ к файловой системе +Dword kos_FileSystemAccess( kosFileInfo *fileInfo ); +// функция 63 +void kos_DebugOutChar( char ccc ); +// +void rtlDebugOutString( char *str ); +// функция 64 изменить параметры окна, параметр == -1 не меняется +void kos_ChangeWindow( Dword x, Dword y, Dword sizeX, Dword sizeY ); +// функция 67 изменение количества памяти, выделенной для программы +bool kos_ApplicationMemoryResize( Dword targetSize ); +// функция 66 режим получения данных от клавиатуры +void kos_SetKeyboardDataMode( Dword mode ); + +// +void kos_Main(); diff --git a/programs/games/xonix/trunk/lang.h b/programs/games/xonix/trunk/lang.h new file mode 100644 index 0000000000..ef15793f1a --- /dev/null +++ b/programs/games/xonix/trunk/lang.h @@ -0,0 +1,3 @@ +#define RUS 1 +#define ENG 2 +#define LANG RUS \ No newline at end of file diff --git a/programs/games/xonix/trunk/logo.bmp b/programs/games/xonix/trunk/logo.bmp new file mode 100644 index 0000000000000000000000000000000000000000..be7959501cc7ecfaa837bc5cd28a1236e3dfdf59 GIT binary patch literal 196662 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 Y^#ihYft=SHMdClearName(); + this->score = 0; + }; + // + void ClearName() + { + memset( (Byte *)(this->name), '.', sizeof(this->name) ); + }; +}; + +// +char top10FilePath[MAX_PATH]; +hiScoreHero heroTbl[TOP_TBL_SIZE]; + +// +struct hiScoreFile +{ + Byte block[512]; + kosFileInfo fi; + // + hiScoreFile() + { + int i; + + // + this->fi.offsetLow = this->fi.offsetHigh = 0; + this->fi.dataCount = 0; + this->fi.bufferPtr = this->block; + this->fi.rwMode = 0; + memcpy( this->fi.fileURL, top10FilePath, sizeof( top10FilePath ) ); + // + for ( i = 0; i < ( sizeof( this->block ) / sizeof( Dword ) ); i++ ) + { + // + ((Dword *)(this->block))[i] = rtlRand(); + } + }; + // + virtual ~hiScoreFile() + {} + // + bool LoadFromDisk() + { + bool result; + int i; + Dword j, k; + Byte *bPtr; + + // + this->fi.rwMode = FO_READ; + this->fi.dataCount = 512; + result = kos_FileSystemAccess( &(this->fi) ) == 0; + // + if ( result ) + { + // декодируем + rtlSrand( ((Dword *)(this->block))[(sizeof(this->block) / sizeof(Dword)) - 1] ); + // + for ( i = 0; i < (sizeof( heroTbl ) * 5); i++ ) + { + // не трогаем последний Dword + j = rtlRand() % (sizeof(this->block) - 7); + k = ( rtlRand() % 31 ) + 1; + // + bPtr = this->block + j; + // + __asm{ + mov edx, bPtr + mov ecx, k + mov eax, [edx] + bswap eax + ror eax, cl + mov [edx], eax + } + } + // + rtlSrand( kos_GetSystemClock() ); + } + // + return result; + }; + // + bool SaveToDisk() + { + int i; + Dword *rndList; + Byte *bPtr; + Dword k, keyLock; + + // + rndList = new Dword[(sizeof( heroTbl ) * 5) * 2]; + // + keyLock = rtlRand(); + // + for ( i = 0; i < (sizeof( heroTbl ) * 5); i++ ) + { + // + rndList[i * 2] = rtlRand() % (sizeof(this->block) - 7); + rndList[(i * 2) + 1] = ( rtlRand() % 31 ) + 1; + } + // + for ( i = (sizeof( heroTbl ) * 5) - 1; i >= 0; i-- ) + { + // + bPtr = this->block + rndList[i * 2]; + k = rndList[(i * 2) + 1]; + // + __asm{ + mov edx, bPtr + mov ecx, k + mov eax, [edx] + rol eax, cl + bswap eax + mov [edx], eax + } + } + // + delete rndList; + // + ((Dword *)(this->block))[(sizeof(this->block) / sizeof(Dword)) - 1] = keyLock; + // + this->fi.rwMode = FO_WRITE; + this->fi.dataCount = 512; + return kos_FileSystemAccess( &( this->fi) ) == 0; + }; +}; + +/// +hiScoreFile *top10Heroes = NULL; + + +// заголовок главного окна +char MainWindowTitle[] = "XONIX (C) MMVI by Rabid Rabbit"; +#if LANG == RUS +char goWndTitle[] = "“а®ўҐ­м %U, § ўҐа襭® %U%%, ¦Ё§­Ґ©: %U, бзсв: %U"; +char menuStr1[] = "1. Ќ з вм ЁЈаг"; +char menuStr2[] = "2. ‚л室"; +char menuStr3[] = "“Їа ў«Ґ­ЁҐ: ‘’ђ…‹Љ€ - ­ Їа ў«Ґ­ЁҐ ¤ўЁ¦Ґ­Ёп."; +char menuStr4[] = "SPACE - Ї г§ , ESC - ўл室 ў ¬Ґ­о."; +char thatsAllStr[] = "€Ја  ®Є®­зҐ­ ."; +char worldSizeStr[] = "ђ §¬Ґа Ї®«п %U x %U н«Ґ¬Ґ­в®ў."; +char mainLoopDelayStr[] = "‘Є®а®бвм %U"; +char top10str1[] = "ENTER - Ё¬п Ok."; +char top10str2[] = "ESC - ўл室 ў ¬Ґ­о"; +#else +char goWndTitle[] = "Level %U, completed %U%%, lives: %U, scores: %U"; +char menuStr1[] = "1. Start game"; +char menuStr2[] = "2. Exit"; +char menuStr3[] = "Control: ARROWS - direction of movement."; +char menuStr4[] = "SPACE - pause, ESC - leave to menu."; +char thatsAllStr[] = "Game finished."; +char worldSizeStr[] = "Field size %U x %U cells."; +char mainLoopDelayStr[] = "Speed %U"; +char top10str1[] = "Enter - name Ok."; +char top10str2[] = "ESC - leave to menu"; +#endif +// +Byte beep1[] = { 0x90, 0x33, 0 }; +// +Byte *heroPtr = NULL; +int heroDX = 0, heroDY = 0, lastMoveDirection = 0; +// +Byte * worldMap = NULL; +// +int wndSizeX = ENTRY_WND_SIZE_X; +int wndSizeY = ENTRY_WND_SIZE_Y; +int mapSizeX = 64; +int mapSizeY = 32; +int loopDelay = DEFAULT_LOOP_DELAY; +int currentLevel = 1; +int appState = appStateEntry; +int levelFillEdge = 0; +int levelFillCount = 0; +int lifeCount = 0; +int flipMapCount = 0; +bool noBonus = false; +bool goToNextLevel = false; +bool bonus1Set = false; +bool bonus2Set = false; +int bonus1Count = 0; +int currentHero = gmHero; +int currentTrack = gmTrack; +Dword scoreCount = 0; +int enterName = -1; +int enterCharNdx = 0; +// +MCArray fillList; + +// +struct flipMapEl +{ + Word x, y; +}; + +// +flipMapEl *flipMapPtr = NULL; + + +// +RGB *mapColours[] = { + bmEmpty, + bmHero, + bmEnemy1, + bmEnemy2, + bmWall, + bmTrack, + bmFlip, + bmBonus1, + bmBonus2, + bmSuperHero, + bmSuperTrack, + NULL +}; + + +// +struct sMapDiff +{ + Byte *elPtr; + Byte mapEl; + // + sMapDiff() {}; + // + sMapDiff( Byte *sElPtr, Byte sMapEl ) + { + this->elPtr = sElPtr; + this->mapEl = sMapEl; + }; +}; + + +// +class CMapDiff : public MCArray +{ +public: + virtual int Add( const sMapDiff &element ) + { + element.elPtr[0] = element.mapEl; + return MCArray::Add( element ); + } +}; + + +// +CMapDiff mapDiffList; +MCArray sTrackList; + + +// +class CGenericEnemy +{ +public: + // + Byte *ePtr; + int dx, dy; + // + virtual bool Move(void) = 0; +}; + +class CWallEnemy : public CGenericEnemy +{ +public: + virtual bool Move(void); +}; + +class CSpaceEnemy : public CGenericEnemy +{ +public: + virtual bool Move(void); +}; + + + +// +bool CWallEnemy::Move() +{ + int ddx; + Byte *nextPtr; + Byte mapEl, dirMap; + bool result, border; + + // + result = false; + border = false; + // + ddx = ( this->ePtr - worldMap ) % mapSizeX; + // + if ( ddx == 0 && this->dx < 0 ) + { + border = true; + this->dx = 0 - this->dx; + } + // + if ( ddx == (mapSizeX - 1) && this->dx > 0 ) + { + border = true; + this->dx = 0 - this->dx; + } + // + ddx = ( this->ePtr - worldMap ) / mapSizeX; + // + if ( ddx == 0 && this->dy < 0 ) + { + border = true; + this->dy = 0 - this->dy; + } + // + if ( ddx == (mapSizeY - 1) && this->dy > 0 ) + { + border = true; + this->dy = 0 - this->dy; + } + // получим координаты места, в которое попадает объект + nextPtr = this->ePtr + ( this->dx + this->dy ); + // получим элемент с карты + mapEl = nextPtr[0]; + // + // в зависимости от элемента + switch ( mapEl ) + { + // напоролись на игрока + case gmHero: + if ( sTrackList.GetCount() <= 0 ) + { + result = true; + break; + } + + // пустое место, след игрока или гады на поле - надо отскакивать + case gmSuperHero: + case gmSuperTrack: + case gmTrack: + case gmEnemy2: + case gmEmpty: + // + dirMap = 0; + // -dx +dy + mapEl = this->ePtr[this->dy - this->dx]; + if ( mapEl == gmEmpty + || mapEl == gmTrack + || mapEl == gmEnemy2 + || mapEl == gmSuperHero + || mapEl == gmSuperTrack + ) dirMap |= 1; + // +dy + mapEl = this->ePtr[this->dy]; + if ( mapEl == gmEmpty + || mapEl == gmTrack + || mapEl == gmEnemy2 + || mapEl == gmSuperHero + || mapEl == gmSuperTrack + ) dirMap |= 2; + // +dx + mapEl = this->ePtr[this->dx]; + if ( mapEl == gmEmpty + || mapEl == gmTrack + || mapEl == gmEnemy2 + || mapEl == gmSuperHero + || mapEl == gmSuperTrack + ) dirMap |= 4; + // +dx -dy + mapEl = this->ePtr[this->dx - this->dy]; + if ( mapEl == gmEmpty + || mapEl == gmTrack + || mapEl == gmEnemy2 + || mapEl == gmSuperHero + || mapEl == gmSuperTrack + ) dirMap |= 8; + // + switch ( dirMap ) + { + case 2: + case 3: + this->dy = 0 - this->dy; + break; + + case 4: + case 12: + this->dx = 0 - this->dx; + break; + + default: + this->dx = 0 - this->dx; + this->dy = 0 - this->dy; + break; + } + // + nextPtr = this->ePtr + ( this->dx + this->dy ); + // получим элемент с карты + mapEl = nextPtr[0]; + // + switch ( mapEl ) + { + // + case gmHero: + if ( sTrackList.GetCount() <= 0 ) + { + result = true; + } + + // + case gmSuperHero: + case gmSuperTrack: + case gmTrack: + case gmEmpty: + case gmEnemy2: + break; + + // + default: + // стираем объект + mapDiffList.Add( sMapDiff( this->ePtr, gmWall ) ); + // переместим объект + this->ePtr = nextPtr; + // рисуем объект по новым координатам + mapDiffList.Add( sMapDiff( this->ePtr, gmEnemy1 ) ); + break; + } + // + break; + + // летим + default: + // стираем объект + mapDiffList.Add( sMapDiff( this->ePtr, gmWall ) ); + // переместим объект + this->ePtr = nextPtr; + // рисуем объект по новым координатам + mapDiffList.Add( sMapDiff( this->ePtr, gmEnemy1 ) ); + // + break; + + } + // + return result; +} + +// +bool CSpaceEnemy::Move() +{ + Byte *nextPtr; + Byte mapEl, dirMap; + bool result, heroTrack; + + // + result = false; + // + heroTrack = ( sTrackList.GetCount() > 0 ); + // получим координаты места, в которое попадает объект + nextPtr = this->ePtr + ( this->dx + this->dy ); + // получим элемент с карты + mapEl = nextPtr[0]; + // в зависимости от элемента + switch ( mapEl ) + { + // напоролись на игрока или его след + case gmTrack: + result = true; + break; + + // + case gmHero: + if ( heroTrack ) + { + result = true; + break; + } + + // надо отскакивать + case gmSuperHero: + case gmSuperTrack: + case gmBonus1: + case gmBonus2: + case gmEnemy1: + case gmWall: + // + dirMap = 0; + // -dx +dy + mapEl = this->ePtr[this->dy - this->dx]; + if ( mapEl == gmWall || + mapEl == gmEnemy1 || + mapEl == gmBonus1 || + mapEl == gmBonus2 || + mapEl == gmSuperHero || + mapEl == gmSuperTrack || + ( mapEl == gmHero && !heroTrack ) + ) dirMap |= 1; + // +dy + mapEl = this->ePtr[this->dy]; + if ( mapEl == gmWall || + mapEl == gmEnemy1 || + mapEl == gmBonus1 || + mapEl == gmBonus2 || + mapEl == gmSuperHero || + mapEl == gmSuperTrack || + ( mapEl == gmHero && !heroTrack ) + ) dirMap |= 2; + // +dx + mapEl = this->ePtr[this->dx]; + if ( mapEl == gmWall || + mapEl == gmEnemy1 || + mapEl == gmBonus1 || + mapEl == gmBonus2 || + mapEl == gmSuperHero || + mapEl == gmSuperTrack || + ( mapEl == gmHero && !heroTrack ) + ) dirMap |= 4; + // +dx -dy + mapEl = this->ePtr[this->dx - this->dy]; + if ( mapEl == gmWall || + mapEl == gmEnemy1 || + mapEl == gmBonus1 || + mapEl == gmBonus2 || + mapEl == gmSuperHero || + mapEl == gmSuperTrack || + ( mapEl == gmHero && !heroTrack ) + ) dirMap |= 8; + // + switch ( dirMap ) + { + case 2: + case 3: + this->dy = 0 - this->dy; + break; + + case 4: + case 12: + this->dx = 0 - this->dx; + break; + + default: + this->dx = 0 - this->dx; + this->dy = 0 - this->dy; + break; + } + // + nextPtr = this->ePtr + ( this->dx + this->dy ); + // получим элемент с карты + mapEl = nextPtr[0]; + // + switch ( mapEl ) + { + // + case gmTrack: + result = true; + break; + + // + case gmHero: + if ( heroTrack ) + { + result = true; + break; + } + + // + case gmSuperHero: + case gmSuperTrack: + case gmBonus1: + case gmBonus2: + case gmWall: + case gmEnemy1: + break; + + // + default: + // стираем объект + mapDiffList.Add( sMapDiff( this->ePtr, gmEmpty ) ); + // переместим объект + this->ePtr = nextPtr; + // рисуем объект по новым координатам + mapDiffList.Add( sMapDiff( this->ePtr, gmEnemy2 ) ); + break; + } + // + break; + + // летим + default: + // стираем объект + mapDiffList.Add( sMapDiff( this->ePtr, gmEmpty ) ); + // переместим объект + this->ePtr = nextPtr; + // рисуем объект по новым координатам + mapDiffList.Add( sMapDiff( this->ePtr, gmEnemy2 ) ); + // + break; + + } + // + + // + return result; +} + + +// +MCArray mapEnemies; + + +// +void xonixFree(void) +{ + clearWorldMap(); + if ( flipMapPtr != NULL ) + { + delete flipMapPtr; + flipMapPtr = NULL; + } +} + + +// +void checkAndSetBonus2() +{ + Dword i; + + // + if ( (!bonus2Set) + && rtlRand() < 0x40000000 + && lifeCount < 3 + && GetCompletePercents() > 50 ) + { + // + bonus2Set = true; + // + for ( i = rtlRand() % (mapSizeX * mapSizeY); worldMap[i] != gmWall; i = rtlRand() % (mapSizeX * mapSizeY) ); + // + mapDiffList.Add( sMapDiff( worldMap + i, gmBonus2 ) ); + } +} + + +// +void ChangeHero() +{ + if ( bonus1Count < 1 ) + { + currentHero = gmHero; + currentTrack = gmTrack; + } + else + { + currentHero = gmSuperHero; + currentTrack = gmSuperTrack; + } +} + + +// +void checkAndSetBonus1() +{ + Dword i; + + // + if ( (!bonus1Set) + && rtlRand() > 0x80000000 + && lifeCount < 2 + && GetCompletePercents() > 75 ) + { + // + bonus1Set = true; + // + for ( i = rtlRand() % (mapSizeX * mapSizeY); worldMap[i] != gmWall; i = rtlRand() % (mapSizeX * mapSizeY) ); + // + mapDiffList.Add( sMapDiff( worldMap + i, gmBonus1 ) ); + } +} + + +// +void CreateFlipMap(void) +{ + Word i, j; + int ndx, ndx2, k; + flipMapEl el; + static int lastMapSizeX = 0, lastMapSizeY = 0; + + // + if ( lastMapSizeX != mapSizeX || lastMapSizeY != mapSizeY ) + { + // + lastMapSizeX = mapSizeX; + lastMapSizeY = mapSizeY; + // + if ( flipMapPtr != NULL ) + { + delete flipMapPtr; + flipMapPtr = NULL; + } + } + // + if ( flipMapPtr == NULL ) + { + flipMapPtr = new flipMapEl[flipMapSize]; + // + ndx = 0; + // + for ( i = 0; i < mapSizeY; i += 2 ) + { + for ( j = 0; j < mapSizeX; j += 2 ) + { + // + flipMapPtr[ndx].x = j; + flipMapPtr[ndx].y = i; + // + ndx++; + } + } + } + // + for ( k = 0; k < flipMapSize; k++ ) + { + // + ndx = rtlRand() % flipMapSize; + ndx2 = rtlRand() % flipMapSize; + // + el = flipMapPtr[ndx]; + flipMapPtr[ndx] = flipMapPtr[ndx2]; + flipMapPtr[ndx2] = el; + } +} + + +// +bool ProcessEndTrack() +{ + int i, j, k, m; + bool noFill; + Byte *mPtr, *findPtr; + + // + j = sTrackList.GetCount(); + // + scoreCount += j; + // + for ( i = 0; i < j; i++ ) + { + // + mapDiffList.Add( sMapDiff( sTrackList[i], gmWall ) ); + } + // + levelFillCount -= j; + // + sTrackList.Clear(); + // + heroPtr += heroDX + heroDY; + mapDiffList.Add( sMapDiff( heroPtr, currentHero ) ); + // + heroDX = 0; + heroDY = 0; + lastMoveDirection = 0; + // заливка + mPtr = worldMap; + // + for ( i = 0; i < mapSizeY; i++ ) + { + for ( j = 0; j < mapSizeX; j++ ) + { + // + if ( mPtr[0] == gmEmpty ) + { + // + fillList.Clear(); + // + noFill = false; + // + fillList.Add( mPtr ); + // + mPtr[0] = gmProbe; + // + for ( k = 0; k < fillList.GetCount(); k++ ) + { + // справа + findPtr = fillList[k] + 1; + // + switch ( findPtr[0] ) + { + case gmEmpty: + fillList.Add( findPtr ); + findPtr[0] = gmProbe; + break; + case gmEnemy2: + noFill = true; + break; + default: + break; + } + // слева + findPtr = fillList[k] - 1; + // + switch ( findPtr[0] ) + { + case gmEmpty: + fillList.Add( findPtr ); + findPtr[0] = gmProbe; + break; + case gmEnemy2: + noFill = true; + break; + default: + break; + } + // сверху + findPtr = fillList[k] - mapSizeX; + // + switch ( findPtr[0] ) + { + case gmEmpty: + fillList.Add( findPtr ); + findPtr[0] = gmProbe; + break; + case gmEnemy2: + noFill = true; + break; + default: + break; + } + // снизу + findPtr = fillList[k] + mapSizeX; + // + switch ( findPtr[0] ) + { + case gmEmpty: + fillList.Add( findPtr ); + findPtr[0] = gmProbe; + break; + case gmEnemy2: + noFill = true; + break; + default: + break; + } + } + // + if ( noFill ) + { + // + fillList.Clear(); + } + else + { + // + m = fillList.GetCount(); + // + scoreCount += m; + // + for ( k = 0; k < m; k++ ) + { + // + mapDiffList.Add( sMapDiff( fillList[k], gmWall ) ); + } + // + levelFillCount -= m; + } + } + else + { + mPtr++; + } + } + } + // + mPtr = worldMap; + // + for ( i = 0; i < mapSizeY; i++ ) + { + for ( j = 0; j < mapSizeX; j++ ) + { + // + if ( mPtr[0] == gmProbe ) mPtr[0] = gmEmpty; + // + mPtr++; + } + } + // + checkAndSetBonus1(); + checkAndSetBonus2(); + // + ApplyMapDiffs(); + // + return levelFillCount <= levelFillEdge; +} + + +// +void EatEnemy( Byte *enemyPos ) +{ + bool Eat = true; + int i, j; + + // + while ( Eat ) + { + // + Eat = false; + // + j = mapEnemies.GetCount(); + // + for ( i = 0; i < j; i++ ) + { + // + if ( mapEnemies[i]->ePtr == enemyPos ) + { + // + delete mapEnemies[i]; + // + mapEnemies.RemoveAt( i ); + // + Eat = true; + // + scoreCount += EAT_ENEMY_BONUS; + // + break; + } + } + } +} + + +// +bool MoveHero() +{ + int ddx; + Byte *nextPtr; + Byte mapEl; + bool result; + + // + if ( heroDX == 0 && heroDY == 0 ) return false; + // + result = false; + // + nextPtr = heroPtr + ( heroDX + heroDY ); + // + ddx = ( ( heroPtr - worldMap ) % mapSizeX ) - ( ( nextPtr - worldMap ) % mapSizeX ); + // + if ( ddx < -1 || ddx > 1 || nextPtr < worldMap || nextPtr >= ( worldMap + ( mapSizeX * mapSizeY ) ) ) + { + heroDX = 0; + heroDY = 0; + return false; + } + + + // + mapEl = nextPtr[0]; + // + if ( sTrackList.GetCount() > 0 ) + { + // + switch ( mapEl ) + { + // + case gmEmpty: + sTrackList.Add( nextPtr ); + break; + // + case gmBonus1: + bonus1Count = BONUS1_LIFETIME; + ChangeHero(); + goToNextLevel = ProcessEndTrack(); + return false; + break; + // + case gmBonus2: + lifeCount++; + goToNextLevel = ProcessEndTrack(); + return false; + break; + // + case gmWall: + goToNextLevel = ProcessEndTrack(); + return false; + break; + // + case gmEnemy1: + if ( bonus1Count > 0 ) + { + // + EatEnemy( nextPtr ); + // + goToNextLevel = ProcessEndTrack(); + // + return false; + break; + } + else + { + // + return true; + } + break; + // + case gmEnemy2: + if ( bonus1Count > 0 ) + { + // + EatEnemy( nextPtr ); + sTrackList.Add( nextPtr ); + break; + } + else + { + // + return true; + } + break; + // + default: + return true; + break; + } + } + else + { + // + switch ( mapEl ) + { + // + case gmEmpty: + sTrackList.Add( nextPtr ); + break; + // + case gmBonus1: + bonus1Count = BONUS1_LIFETIME; + break; + // + case gmBonus2: + lifeCount++; + break; + // + case gmWall: + break; + // + case gmEnemy1: + if ( bonus1Count > 0 ) + { + EatEnemy( nextPtr ); + } + else + { + result = true; + } + break; + // + case gmEnemy2: + if ( bonus1Count > 0 ) + { + EatEnemy( nextPtr ); + sTrackList.Add( nextPtr ); + } + else + { + result = true; + } + break; + // + default: + result = true; + break; + } + } + + // + mapDiffList.Add( sMapDiff( heroPtr, sTrackList.GetCount() <= 1 ? gmWall : currentTrack ) ); + heroPtr = nextPtr; + mapDiffList.Add( sMapDiff( heroPtr, currentHero ) ); + + return result; +} + + +// +bool MoveEnemies() +{ + bool result; + int i, j, ir; + + // + result = false; + ir = 0; + // + j = mapEnemies.GetCount(); + // + for ( i = 0; i < j; i++ ) + { + ir += ( mapEnemies[i]->Move() ? 1 : 0 ); + } + // + result = ( ir != 0 ); + // + return result; +} + + +// +void ApplyMapDiffs( bool drawTitle ) +{ + int i, j; + + // + kos_WindowRedrawStatus( 1 ); + // + if ( drawTitle ) drawWndTitleGo(); + // + j = mapDiffList.GetCount(); + // + for ( i = 0; i < j; i++ ) + { + //// + //kos_DrawBar( + // wndXOffet + ( ( ( mapDiffList[i].elPtr - worldMap ) % mapSizeX ) * blockSize ), + // wndYOffset + ( ( ( mapDiffList[i].elPtr - worldMap ) / mapSizeX ) * blockSize ), + // blockSize, blockSize, + // mapColours[mapDiffList[i].mapEl] + //); + // + kos_PutImage( + mapColours[mapDiffList[i].mapEl], + blockSize, + blockSize, + wndXOffet + ( ( ( mapDiffList[i].elPtr - worldMap ) % mapSizeX ) * blockSize ), + wndYOffset + ( ( ( mapDiffList[i].elPtr - worldMap ) / mapSizeX ) * blockSize ) + ); + } + // + kos_WindowRedrawStatus( 2 ); + // + mapDiffList.Clear(); +} + + +// +void DeadHeroProcess() +{ + int i, j; + Byte *mPtr = beep1; + + // beep + __asm{ + mov eax, 55 + mov ebx, eax + mov esi, mPtr + push eax + int 0x40 + pop eax + } + // + j = sTrackList.GetCount(); + // + for ( i = 0; i < j; i++ ) + { + // + mapDiffList.Add( sMapDiff( sTrackList[i], gmEmpty ) ); + } + // + mapDiffList.Add( sMapDiff( heroPtr, sTrackList.GetCount() > 0 ? gmEmpty : gmWall ) ); + // + sTrackList.Clear(); + // + heroPtr = worldMap; + // + while ( heroPtr[0] != gmWall ) heroPtr++; + // + mapDiffList.Add( sMapDiff( heroPtr, gmHero ) ); + // + noBonus = true; + // + lifeCount--; + // + heroDX = 0; + heroDY = 0; + lastMoveDirection = 0; +} + + +// +bool CheckForNextLevel() +{ + // + if ( goToNextLevel ) + { + // + CreateFlipMap(); + goToNextLevel = false; + currentLevel++; + appState = appStateHideMap; + flipMapCount = 0; + return true; + } + + // + return false; +} + + +// +void SetGameVars() +{ + // + currentLevel = 1; + lifeCount = 3; + noBonus = true; + bonus1Set = false; + bonus2Set = false; + bonus1Count = 0; + goToNextLevel = false; + currentHero = gmHero; + currentTrack = gmTrack; + scoreCount = 0; + enterName = -1; + // + wndSizeX = ((mapSizeX*blockSize)+2); + wndSizeY = ((mapSizeY*blockSize)+23); + // + kos_ChangeWindow( -1, -1, wndSizeX, wndSizeY ); +} + +// +void SetEntryVars() +{ + // + wndSizeX = ENTRY_WND_SIZE_X; + wndSizeY = ENTRY_WND_SIZE_Y; + // + kos_ChangeWindow( -1, -1, wndSizeX, wndSizeY ); + kos_SetKeyboardDataMode( KM_SCANS ); +} + + +// +void ReleaseTop10() +{ + // + if ( top10Heroes != NULL ) + { + // + memcpy( top10Heroes->block, heroTbl, sizeof(heroTbl) ); + // + top10Heroes->SaveToDisk(); + // + delete top10Heroes; + } +} + + +// +void PrepareTop10() +{ + // + top10Heroes = new hiScoreFile; + // + atexit( ReleaseTop10 ); + // + if ( top10Heroes->LoadFromDisk() ) + { + // + memcpy( heroTbl, top10Heroes->block, sizeof(heroTbl) ); + } +} + + +// +void SetUpTop10() +{ + int i, j; + Byte keyCode; + + // + while ( kos_CheckForEvent() == 2 ) kos_GetKey( keyCode ); + // + kos_SetKeyboardDataMode( KM_CHARS ); + // + kos_ChangeWindow( -1, -1, TOP10_WND_SIZE_X, TOP10_WND_SIZE_Y ); + // + for ( i = 0; i < TOP_TBL_SIZE; i++ ) + { + // + if ( heroTbl[i].score < scoreCount ) + { + // + for ( j = TOP_TBL_SIZE - 1; j > i; j-- ) + { + // + heroTbl[j] = heroTbl[j-1]; + } + // + heroTbl[i].ClearName(); + heroTbl[i].score = scoreCount; + // + enterName = i; + enterCharNdx = 0; + // + break; + } + } +} + + +// +// точка входа и функция обработки сообщений +// +void kos_Main() +{ + Dword buttonID; + Byte keyCode; + Byte *bPtr; + bool workOn = true; + char *cPtr; + + // отделяем имя модуля от пути + cPtr = strrchr( kosExePath, '/' ); + // проверка ;) + if ( cPtr == NULL ) + { + // + rtlDebugOutString( "Invalid path to executable." ); + // + return; + } + // + cPtr[1] = 0; + // + strcpy( top10FilePath, kosExePath ); + // + strcpy( top10FilePath + ((cPtr - kosExePath) + 1), "xonix.t10" ); + + // выполнение функций инициализации + kos_SetKeyboardDataMode( KM_SCANS ); + // + PrepareTop10(); + + // + while( workOn ) + { + switch ( appState ) + { + // + case appStateEntry: + switch ( kos_WaitForEvent() ) + { + // перерисовка окна + case 1: + DrawAppWindow(); + break; + + // + case 2: + kos_GetKey( keyCode ); + switch ( keyCode ) + { + // + case 2: + // + appState = appStateGo; + SetGameVars(); + initWorldMap(); + DrawAppWindow(); + break; + + // + case 3: + xonixFree(); + workOn = false; + break; + } + break; + // + case 3: + // + if ( ! kos_GetButtonID( buttonID ) ) break; + // + switch ( buttonID ) + { + // + case BT_SIZE_X_PLUS: + mapSizeX += 2; + if ( mapSizeX > MAX_X_SIZE ) mapSizeX = MAX_X_SIZE; + break; + // + case BT_SIZE_X_MINUS: + mapSizeX -= 2; + if ( mapSizeX < MIN_X_SIZE ) mapSizeX = MIN_X_SIZE; + break; + // + case BT_SIZE_Y_PLUS: + mapSizeY += 2; + if ( mapSizeY > MAX_Y_SIZE ) mapSizeY = MAX_Y_SIZE; + break; + // + case BT_SIZE_Y_MINUS: + mapSizeY -= 2; + if ( mapSizeY < MIN_Y_SIZE ) mapSizeY = MIN_Y_SIZE; + break; + // + case BT_LOOP_MINUS: + loopDelay++;; + if ( loopDelay > MAX_LOOP_DELAY ) loopDelay = MAX_LOOP_DELAY; + break; + // + case BT_LOOP_PLUS: + loopDelay--;; + if ( loopDelay < MIN_LOOP_DELAY ) loopDelay = MIN_LOOP_DELAY; + break; + // + default: + break; + } + DrawAppWindow(); + break; + // + default: + break; + } + break; + // + case appStateGo: + // + kos_Pause( loopDelay ); + // + if ( bonus1Count > 0 ) bonus1Count--; + // + ChangeHero(); + // + switch( kos_WaitForEvent( 1 ) ) + { + // + case 0: + if ( MoveHero() ) + { + // + DeadHeroProcess(); + } + else + { + // + if ( CheckForNextLevel() ) + { + break; + } + } + if ( MoveEnemies() ) + { + // сожрали игрока + DeadHeroProcess(); + } + ApplyMapDiffs(); + break; + // + case 1: + DrawAppWindow(); + break; + + // + case 2: + do kos_GetKey( keyCode ); while ( keyCode & 0x80 ); + switch ( keyCode ) + { + // + case 0x1: + SetEntryVars(); + appState = appStateEntry; + clearWorldMap(); + DrawAppWindow(); + continue; + + // + case 0x39: + appState = appStatePause; + break; + + // + case 0x48: + heroDX = 0; + if ( lastMoveDirection == 0x50 ) + { + heroDY = 0; + lastMoveDirection = 0; + } + else + { + heroDY = -mapSizeX; + lastMoveDirection = 0x48; + } + break; + + // + case 0x50: + heroDX = 0; + if ( lastMoveDirection == 0x48 ) + { + heroDY = 0; + lastMoveDirection = 0; + } + else + { + heroDY = mapSizeX; + lastMoveDirection = 0x50; + } + break; + + // + case 0x4B: + heroDY = 0; + if ( lastMoveDirection == 0x4D ) + { + heroDX = 0; + lastMoveDirection = 0; + } + else + { + heroDX = -1; + lastMoveDirection = 0x4B; + } + break; + + // + case 0x4D: + heroDY = 0; + if ( lastMoveDirection == 0x4B ) + { + heroDX = 0; + lastMoveDirection = 0; + } + else + { + heroDX = 1; + lastMoveDirection = 0x4D; + } + break; + } + // + if ( MoveHero() ) + { + // + DeadHeroProcess(); + } + else + { + // + if ( CheckForNextLevel() ) + { + break; + } + } + if ( MoveEnemies() ) + { + // сожрали игрока + DeadHeroProcess(); + } + ApplyMapDiffs(); + break; + + // + default: + // + if ( MoveHero() ) + { + // + DeadHeroProcess(); + } + if ( MoveEnemies() ) + { + // сожрали игрока + DeadHeroProcess(); + } + ApplyMapDiffs(); + break; + } + // + if ( lifeCount <= 0 ) + { + appState = appStateAfterDeath; + DrawAppWindow(); + } + // + break; + + // + case appStateAfterDeath: + switch ( kos_WaitForEvent() ) + { + // + case 1: + DrawAppWindow(); + break; + // + case 2: + do kos_GetKey( keyCode ); while ( keyCode & 0x80 ); + if ( keyCode != 0 ) + { + // + appState = appStateTop10; + SetUpTop10(); + DrawAppWindow(); + } + break; + // + case 3: + if ( kos_GetButtonID( buttonID ) ) + { + // + if ( buttonID == 1 ) + { + // + appState = appStateTop10; + SetUpTop10(); + DrawAppWindow(); + } + } + // + default: + break; + } + break; + + // + case appStateTop10: + switch ( kos_WaitForEvent() ) + { + // + case 1: + DrawAppWindow(); + break; + // + case 2: + // + kos_GetKey( keyCode ); + // + if ( enterName < 0 ) + { + // + if ( keyCode == 0x1b ) + { + // + SetEntryVars(); + clearWorldMap(); + appState = appStateEntry; + DrawAppWindow(); + } + } + else + { + // + switch ( keyCode ) + { + // + case 13: + // + enterName = -1; + break; + // + case 8: + // + if ( enterCharNdx > 0 ) + { + // + heroTbl[enterName].name[--enterCharNdx] = '.'; + } + break; + // + default: + if ( keyCode >= 0x20 ) + { + // + heroTbl[enterName].name[enterCharNdx++] = keyCode; + // + if ( enterCharNdx >= sizeof(heroTbl[0].name) ) + { + // + enterName = -1; + } + } + break; + } + // + DrawAppWindow(); + } + // + break; + // + default: + break; + } + break; + + // + case appStatePause: + switch ( kos_WaitForEvent() ) + { + case 1: + DrawAppWindow(); + break; + + case 2: + do kos_GetKey( keyCode ); while ( keyCode & 0x80 ); + if ( keyCode != 0 ) + { + // + appState = appStateGo; + } + break; + + default: + break; + } + break; + + // + case appStateHideMap: + // + switch ( kos_WaitForEvent( 1 ) ) + { + case 1: + DrawAppWindow(); + break; + case 2: + while ( kos_GetKey( keyCode ) ); + break; + default: + bPtr = worldMap + (flipMapPtr[flipMapCount].x + (flipMapPtr[flipMapCount].y * mapSizeX)); + mapDiffList.Add( sMapDiff( bPtr, gmFlip ) ); + mapDiffList.Add( sMapDiff( bPtr + 1, gmFlip ) ); + mapDiffList.Add( sMapDiff( bPtr + mapSizeX, gmFlip ) ); + mapDiffList.Add( sMapDiff( bPtr + (mapSizeX + 1), gmFlip ) ); + ApplyMapDiffs( false ); + break; + } + // + flipMapCount++; + // + if ( flipMapCount >= flipMapSize ) + { + flipMapCount = 0; + appState = appStateShowMap; + DrawAppWindow(); + } + break; + // + case appStateShowMap: + // + switch ( kos_WaitForEvent( 1 ) ) + { + case 1: + DrawAppWindow(); + break; + default: + break; + } + // + flipMapCount++; + // + if ( flipMapCount >= BEFORE_START_LEVEL ) + { + clearWorldMap(); + flipMapCount = 0; + initWorldMap(); + appState = appStateGo; + DrawAppWindow(); + } + // + break; + } + } +} + + +// +void DrawEntryScreen() +{ + PRINTK pr; + char line[64]; + + // + kos_DefineAndDrawWindow( + 100, 100, + wndSizeX, wndSizeY, + 0, 0, + 0, 0x2040A0, + 0x2040A0 + ); + // + kos_WriteTextToWindow( + 4, 4, + 0x10, 0x42D2E2, + MainWindowTitle, + sizeof( MainWindowTitle ) - 1 + ); + // + kos_WriteTextToWindow( + 8, 32, + 0x10, 0x12FF12, + menuStr1, + sizeof( menuStr1 ) - 1 + ); + // + kos_WriteTextToWindow( + 8, 48, + 0x10, 0x12FF12, + menuStr2, + sizeof( menuStr2 ) - 1 + ); + // + kos_WriteTextToWindow( + 8, 80, + 0x10, 0xD0FF12, + menuStr3, + sizeof( menuStr3 ) - 1 + ); + // + kos_WriteTextToWindow( + 8, 96, + 0x10, 0xD0FF12, + menuStr4, + sizeof( menuStr4 ) - 1 + ); + // размер поля + pr.fmtline = worldSizeStr; + pr.args[0] = mapSizeX; + pr.args[1] = mapSizeY; + sprintk( line, &pr ); + // + kos_WriteTextToWindow( + 8, 112, + 0x10, 0x12C0D0, + line, + strlen( line ) + ); + // кнопки X + kos_DefineButton( + ENTRY_WND_SIZE_X - 58, 112, + 12, 12, + BT_SIZE_X_MINUS, + 0xCCCCCC + ); + // + kos_PutImage( bmPMButton + 12, 6, 2, ENTRY_WND_SIZE_X - 58 + 3, 117 ); + // + kos_DefineButton( + ENTRY_WND_SIZE_X - 45, 112, + 12, 12, + BT_SIZE_X_PLUS, + 0xCCCCCC + ); + // + kos_PutImage( bmPMButton, 6, 6, ENTRY_WND_SIZE_X - 45 + 3, 115 ); + // кнопки Y + kos_DefineButton( + ENTRY_WND_SIZE_X - 29, 112, + 12, 12, + BT_SIZE_Y_MINUS, + 0xCCCCCC + ); + // + kos_PutImage( bmPMButton + 12, 6, 2, ENTRY_WND_SIZE_X - 29 + 3, 117 ); + // + kos_DefineButton( + ENTRY_WND_SIZE_X - 16, 112, + 12, 12, + BT_SIZE_Y_PLUS, + 0xCCCCCC + ); + // + kos_PutImage( bmPMButton, 6, 6, ENTRY_WND_SIZE_X - 16 + 3, 115 ); + // + //задержка в цикле выборки сообщений + pr.fmtline = mainLoopDelayStr; + pr.args[0] = MAX_LOOP_DELAY + MIN_LOOP_DELAY - loopDelay; + sprintk( line, &pr ); + // + kos_WriteTextToWindow( + 8, 128, + 0x10, 0x12C0D0, + line, + strlen( line ) + ); + // + kos_DefineButton( + ENTRY_WND_SIZE_X - 29, 128, + 12, 12, + BT_LOOP_MINUS, + 0xCCCCCC + ); + // + kos_PutImage( bmPMButton + 12, 6, 2, ENTRY_WND_SIZE_X - 29 + 3, 133 ); + // + kos_DefineButton( + ENTRY_WND_SIZE_X - 16, 128, + 12, 12, + BT_LOOP_PLUS, + 0xCCCCCC + ); + // + kos_PutImage( bmPMButton, 6, 6, ENTRY_WND_SIZE_X - 16 + 3, 131 ); +} + + +// +void DrawAppWindow() +{ + // + kos_WindowRedrawStatus( 1 ); + + switch ( appState ) + { + // + case appStateTop10: + DrawTop10Window(); + break; + // + case appStateEntry: + // + DrawEntryScreen(); + break; + // + case appStateGo: + case appStateShowMap: + case appStatePause: + drawWorldMap(); + break; + // + case appStateAfterDeath: + // + drawWorldMap(); + // + kos_DefineButton( + ( wndSizeX / 2 ) - 64, + ( wndSizeY / 2 ) - 16, + 128, 32, + 1, + 0x136793 + ); + // + kos_WriteTextToWindow( + ( wndSizeX / 2 ) - ( sizeof( thatsAllStr ) * 4 ), + ( wndSizeY / 2 ) - 4, + 0x10, 0xFFFFFF, + thatsAllStr, + sizeof ( thatsAllStr ) - 1 + ); + + // + break; + // + case appStateHideMap: + drawWorldMapForFlip(); + break; + } + // + kos_WindowRedrawStatus( 2 ); +} + + +// +void initWorldMap() +{ + int i, j, m, allocSize; + CWallEnemy *we; + CSpaceEnemy *se; + + // + allocSize = mapSizeX * mapSizeY; + worldMap = new Byte[allocSize]; + // + __asm{ + mov edi, worldMap + mov ecx, allocSize + mov al, gmEmpty + rep stosb + } + + + // + levelFillEdge = ( ( currentLevel + 1 ) * spacePerEnemy ) + currentLevel; + levelFillCount = freeSpaceCount; + // + if ( ! noBonus ) + { + lifeCount++; + } + // + noBonus = false; + bonus1Set = false; + bonus2Set = false; + bonus1Count = 0; + goToNextLevel = false; + currentHero = gmHero; + currentTrack = gmTrack; + + // + for ( i = 0; i < mapSizeX; i++ ) + { + // + worldMap[i] = gmWall; + worldMap[mapSizeX + i] = gmWall; + // + worldMap[((mapSizeY-2)*mapSizeX) + i] = gmWall; + worldMap[((mapSizeY-1)*mapSizeX) + i] = gmWall; + } + // + for ( i = 2; i < (mapSizeY-2); i++ ) + { + // + worldMap[(i*mapSizeX)] = gmWall; + worldMap[(i*mapSizeX) + 1] = gmWall; + worldMap[(i*mapSizeX) + mapSizeX - 2] = gmWall; + worldMap[(i*mapSizeX) + mapSizeX - 1] = gmWall; + } + // + heroPtr = worldMap + ( mapSizeX / 2 ); + heroPtr[0] = gmHero; + heroDX = 0; + heroDY = 0; + // + for ( i = 0; i < currentLevel; i++ ) + { + // + for ( + j = ( rtlRand() % (mapSizeX * (mapSizeY - 2)) ) + (mapSizeX * 2); + worldMap[j] != gmWall; + j = rtlRand() % (mapSizeX * mapSizeY) + ); + // + we = new CWallEnemy(); + // + we->ePtr = worldMap + j; + we->dx = rtlRand() & 1 ? 1 : -1; + we->dy = rtlRand() & 1 ? mapSizeX : -mapSizeX; + // + mapEnemies.Add( we ); + // + worldMap[j] = gmEnemy1; + } + // + m = currentLevel + 1; + // + for ( i = 0; i < m; i++ ) + { + // + for ( + j = rtlRand() % (mapSizeX * mapSizeY); + worldMap[j] != gmEmpty; + j = rtlRand() % (mapSizeX * mapSizeY) + ); + // + se = new CSpaceEnemy(); + // + se->ePtr = worldMap + j; + se->dx = rtlRand() & 1 ? 1 : -1; + se->dy = rtlRand() & 1 ? mapSizeX : -mapSizeX; + // + mapEnemies.Add( se ); + // + worldMap[j] = gmEnemy2; + } +} + + +// +void drawWorldMap() +{ + // + kos_DefineAndDrawWindow( + 100, 100, + wndSizeX, wndSizeY, + 0, 0, + 0, 0x2040A0, + 0x2040A0 + ); + // + drawWndTitleGo(); + // + drawWorldMapForFlip(); +} + + +// +int GetCompletePercents() +{ + int n1, n2; + + // + n1 = freeSpaceCount - levelFillCount; + n2 = freeSpaceCount - levelFillEdge; + // + return ( n1 >= n2 ) ? 100 : ( n1 * 100 ) / n2; +} + + +// +void drawWndTitleGo() +{ + PRINTK pr; + char line[64]; + + // + kos_DrawBar( + 1, 1, + wndSizeX - 2, 18, + 0x2040A0 + ); + + // + pr.fmtline = goWndTitle; + pr.args[0] = currentLevel; + pr.args[1] = GetCompletePercents(); + pr.args[2] = lifeCount; + pr.args[3] = scoreCount; + sprintk( line, &pr ); + // + kos_WriteTextToWindow( + 4, 4, + 0x10, 0x42D2E2, + line, + strlen( line ) + ); + // + if ( bonus1Count > 0 ) + { + // + kos_DrawBar( + 2, 22 - BONUS1_IND_HSIZE - 1, + wndSizeX - 4, BONUS1_IND_HSIZE, + 0x2040A0 + ); + // + kos_DrawBar( + 2, 22 - BONUS1_IND_HSIZE - 1, + ( bonus1Count * ( wndSizeX - 4 ) ) / BONUS1_LIFETIME, BONUS1_IND_HSIZE, + 0x5720B0 + ); + } +} + +// +void drawWorldMapForFlip() +{ + int i, j; + Byte *mPtr = worldMap; + + // + for ( i = 0; i < mapSizeY; i++ ) + { + // + for ( j = 0; j < mapSizeX; j++ ) + { + //// + //kos_DrawBar( + // wndXOffet + ( j * blockSize ), + // wndYOffset + ( i * blockSize ), + // blockSize, blockSize, + // mapColours[*mPtr] + //); + // + kos_PutImage( + mapColours[*mPtr], + blockSize, + blockSize, + wndXOffet + ( j * blockSize ), + wndYOffset + ( i * blockSize ) + ); + // + mPtr++; + } + } +} + + +// +void clearWorldMap() +{ + int i, j; + + // + sTrackList.Clear(); + fillList.Clear(); + mapDiffList.Clear(); + // + j = mapEnemies.GetCount(); + // + for ( i = 0; i < j; i++ ) + { + // + delete mapEnemies[i]; + } + // + mapEnemies.Clear(); + // + if ( worldMap != NULL ) + { + delete worldMap; + worldMap = NULL; + } +} + + +// +char Top10WndTitle[] = "Top 10"; + +// +void DrawTop10Window() +{ + int i; + + // + kos_DefineAndDrawWindow( + 100, 100, + TOP10_WND_SIZE_X, TOP10_WND_SIZE_Y, + 0, 0, + 0, 0x2040A0, + 0x2040A0 + ); + // + kos_WriteTextToWindow( + 4, 4, + 0x0, 0x42D2E2, + Top10WndTitle, + sizeof( Top10WndTitle ) - 1 + ); + // + for ( i = 0; i < TOP_TBL_SIZE; i++ ) + { + // + kos_WriteTextToWindow( + 6, wndYOffset + 2 + (i * 10), + 0x0, enterName != i ? 0xFFFFFF : 0x00FF00, + heroTbl[i].name, + sizeof( heroTbl[0].name ) + ); + // + kos_DisplayNumberToWindow( + heroTbl[i].score, + 8, + 112, wndYOffset + 2 + (i * 10), + 0xFFFF55, + nbDecimal, + false + ); + } + // + kos_WriteTextToWindow( + 6, wndYOffset + 6 + (i * 10), + 0x10, 0x1060D0, + enterName >= 0 ? top10str1 : top10str2, + enterName >= 0 ? sizeof(top10str1) - 1 : sizeof(top10str2) - 1 + ); +} + + diff --git a/programs/games/xonix/trunk/mcarray.h b/programs/games/xonix/trunk/mcarray.h new file mode 100644 index 0000000000..48e338ec05 --- /dev/null +++ b/programs/games/xonix/trunk/mcarray.h @@ -0,0 +1,167 @@ +#define AR_CHUNK_SIZE 64 + +// +template +class MCArray +{ +protected: + TYPE * _dataPtr; + int _elementsCount; + int _capacity; + +public: + MCArray(); + ~MCArray(); + virtual int Add( const TYPE &element ); + TYPE & GetAt( int Ndx ); + TYPE & operator [] ( int Ndx ); + int Find( int startNdx, TYPE & element ); + int RemoveAt( int Ndx ); + void Clear(void); + int GetCount(void); +}; + +// + + +// +template +MCArray::MCArray() +{ + // устанавливаем переменные + this->_dataPtr = NULL; + this->_capacity = 0; + this->_elementsCount = 0; +} + + +// +template +MCArray::~MCArray() +{ + // + this->_capacity = 0; + this->_elementsCount = 0; + // + if ( this->_dataPtr != NULL ) + { + delete this->_dataPtr; + } +} + + +// +template +int MCArray::Add( const TYPE &element ) +{ + TYPE * dPtr; + + // есть ли место? + if ( this->_elementsCount >= this->_capacity ) + { + // занимаем ещё памяти + dPtr = new TYPE [this->_capacity + AR_CHUNK_SIZE]; + // проверка + if ( dPtr == NULL ) + { + // + return -1; + } + + if ( this->_capacity > 0 ) + { + // скопируем существующие данные на новое место + memcpy( dPtr, this->_dataPtr, sizeof(TYPE) * this->_capacity ); + // удалим старую копию данных + delete this->_dataPtr; + } + // скорректируем размер + this->_capacity += AR_CHUNK_SIZE; + // скорректируем указатель на данные + this->_dataPtr = dPtr; + } + + // копируем элемент в массив + memcpy( this->_dataPtr + this->_elementsCount, &element, sizeof(TYPE) ); + + // увеличиваем счётчик элементов + return ++this->_elementsCount; +} + + +// +template +TYPE & MCArray::GetAt( int Ndx ) +{ + //assert( Ndx >= 0 && Ndx < this->_elementsCount ); + return this->_dataPtr[Ndx]; +} + + +// +template +TYPE & MCArray::operator [] ( int Ndx ) +{ + return this->GetAt( Ndx ); +} + + +// +template +int MCArray::Find( int startNdx, TYPE & element ) +{ + int i; + + if ( startNdx < 0 || startNdx >= this->_elementsCount ) + { + return -1; + } + + for ( i = startNdx; i < this->_elementsCount; i++ ) + { + if ( element == this->_dataPtr[i] ) + { + return i; + } + } + + return -1; +} + + +// +template +int MCArray::RemoveAt( int Ndx ) +{ + int mn; + + if ( Ndx < 0 || Ndx >= this->_elementsCount ) + { + return 0; + } + + mn = this->_elementsCount - Ndx; + + if ( mn != 1 ) + { + memcpy( this->_dataPtr + Ndx, this->_dataPtr + Ndx + 1, sizeof(TYPE) * ( mn - 1 ) ); + } + + this->_elementsCount--; + return 1; +} + + +// +template +void MCArray::Clear() +{ + this->_elementsCount = 0; +} + +// +template +int MCArray::GetCount() +{ + return this->_elementsCount; +} diff --git a/programs/games/xonix/trunk/mcsmemm.cpp b/programs/games/xonix/trunk/mcsmemm.cpp new file mode 100644 index 0000000000..20feab80f6 --- /dev/null +++ b/programs/games/xonix/trunk/mcsmemm.cpp @@ -0,0 +1,329 @@ +// memman.cpp : Defines the entry point for the console application. +// + +#include "kosSyst.h" +#include "mcsmemm.h" + + +void * __cdecl operator new ( size_t count, size_t element_size ) +{ + return allocmem( (Dword)(count * element_size) ); +} + +void * __cdecl operator new [] ( size_t amount ) +{ + return allocmem( (Dword)amount ); +} + +void * __cdecl operator new ( size_t amount ) +{ + return allocmem( (Dword)amount ); +} + +void __cdecl operator delete ( void *pointer ) +{ + if ( pointer != NULL ) freemem( pointer ); +} + +void __cdecl operator delete [] ( void *pointer ) +{ + if ( pointer != NULL ) freemem( pointer ); +} + + +// +Dword mmMutex = FALSE; +MemBlock *rootfree = NULL; +MemBlock *rootuser = NULL; +bool mmInitialized = false; +Byte *mmHeapTop = NULL; + + +// +Byte * AllocMemFromSystem( Dword reqSize ) +{ + Byte *result; + sProcessInfo pInfo; + + // + if ( mmInitialized ) + { + result = mmHeapTop; + } + else + { + // + kos_ProcessInfo( &pInfo ); + // + result = (Byte *)(pInfo.processInfo.used_memory + 1); + // + mmInitialized = true; + } + // + if ( ! kos_ApplicationMemoryResize( ((Dword)result) + reqSize ) ) + { + result = NULL; + } + // + mmHeapTop = result + reqSize; + // + return result; +} + + +// +Byte *allocmem( Dword reqsize ) +{ + MemBlock *BlockForCheck; + MemBlock *LastKnownGood; + Dword tail; + Byte *address; + + //подровняем размер + if( ( tail = reqsize % SIZE_ALIGN ) != 0 ) + { + reqsize += SIZE_ALIGN - tail; + } + + LastKnownGood = NULL; + + // ждём освобождения мьютекса + while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) + { + // + kos_Pause( 1 ); + } + + //ищем подходящий свободный блок + if( rootfree != NULL ) + { + for ( BlockForCheck = rootfree; ; BlockForCheck = BlockForCheck->Next ) + { + if ( BlockForCheck->Size >= reqsize ) + { + //нашли + if ( LastKnownGood != NULL ) + { + if ( LastKnownGood->Size >= BlockForCheck->Size ) + LastKnownGood = BlockForCheck; + } + else + LastKnownGood = BlockForCheck; + if ( LastKnownGood->Size == reqsize ) + break; + } + if ( BlockForCheck->Next == NULL ) + break; + } + } + + if ( LastKnownGood != NULL ) + { + //проверим найденный блок на возможность деления + tail = LastKnownGood->Size - reqsize; + if ( tail >= ( sizeof(MemBlock) + SIZE_ALIGN ) ) + { + //будем разбивать + BlockForCheck = (MemBlock *)( ( (Byte *)LastKnownGood ) + tail ); + BlockForCheck->Size = reqsize; + //вставим занятый блок в начало списка занатых блоков + if( rootuser != NULL ) + { + BlockForCheck->Next = rootuser; + rootuser->Previous = BlockForCheck; + BlockForCheck->Previous = NULL; + rootuser = BlockForCheck; + } + else + { + rootuser = BlockForCheck; + BlockForCheck->Next = NULL; + BlockForCheck->Previous = NULL; + } + + //изменим размер оставшейся части + LastKnownGood->Size = tail - sizeof(MemBlock); + address = ( (Byte *)BlockForCheck ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + else + { + //перемести блок из очереди свободных в начало очереди занятых + //сначала выкинем его из очереди свободных + if ( LastKnownGood->Previous != NULL ) + { + LastKnownGood->Previous->Next = LastKnownGood->Next; + } + else + { + //блок стоит в начале очереди + rootfree = LastKnownGood->Next; + } + if( LastKnownGood->Next != NULL ) + { + LastKnownGood->Next->Previous = LastKnownGood->Previous; + } + //теперь вставим его в очередь занятых + if( rootuser != NULL ) + { + LastKnownGood->Next = rootuser; + rootuser->Previous = LastKnownGood; + LastKnownGood->Previous = NULL; + rootuser = LastKnownGood; + } + else + { + rootuser = LastKnownGood; + LastKnownGood->Next = NULL; + LastKnownGood->Previous = NULL; + } + // + address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + } + else + { + //надо получить ещё кусочек памяти + LastKnownGood = (MemBlock *)AllocMemFromSystem( reqsize + sizeof(MemBlock) ); + // + if( LastKnownGood != NULL ) + { + LastKnownGood->Size = reqsize; + //теперь вставим его в очередь занятых + if( rootuser != NULL ) + { + LastKnownGood->Next = rootuser; + rootuser->Previous = LastKnownGood; + LastKnownGood->Previous = NULL; + rootuser = LastKnownGood; + } + else + { + rootuser = LastKnownGood; + LastKnownGood->Next = NULL; + LastKnownGood->Previous = NULL; + } + address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + } + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + // + rtlDebugOutString( "allocmem failed." ); + kos_ExitApp(); + // + return NULL; +} + +// +Dword freemem( void *vaddress ) +{ + Dword result; + + Byte *checknext, *address = (Byte *)vaddress; + + // ждём освобождения мьютекса + while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) + { + // + kos_Pause( 1 ); + } + + MemBlock *released = (MemBlock *)( address - sizeof(MemBlock) ); + + result = released->Size; + + //убираем блок из списка занятых + if ( released->Previous != NULL ) + { + released->Previous->Next = released->Next; + } + else + { + rootuser = released->Next; + } + if ( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //закинем теперь этот блок в список свободных + released->Next = rootfree; + released->Previous = NULL; + rootfree = released; + if ( released->Next != NULL ) + { + released->Next->Previous = released; + } + + //теперь поищем смежные свободные блоки + checknext = (Byte *)(rootfree) + ( rootfree->Size + sizeof(MemBlock) ); + // + for ( released = rootfree->Next; released != NULL; released = released->Next ) + { + if ( checknext == (Byte *)released ) + { + //собираем блоки вместе + //сначала выкинем из очереди свободных + released->Previous->Next = released->Next; + if( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //теперь увеличим размер корневого блока + rootfree->Size += released->Size + sizeof(MemBlock); + break; + } + } + //если надо, поищем блоки перед текщим. + checknext = (Byte *)(rootfree); + // + if ( released == NULL ) + { + for ( released = rootfree->Next; released != NULL; released = released->Next ) + { + if ( checknext == (Byte *)released + ( released->Size + sizeof(MemBlock) ) ) + { + //собираем блоки вместе + //увеличим размер блока + released->Size += rootfree->Size + sizeof(MemBlock); + //теперь выкинем из очереди свободных + released->Previous->Next = released->Next; + if ( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //и закинем его в начало очереди вместо присоединённого блока из корня списка + if ( rootfree->Next != NULL ) + { + rootfree->Next->Previous = released; + } + released->Next = rootfree->Next; + released->Previous = NULL; + rootfree = released; + break; + } + } + } + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return result; +} + diff --git a/programs/games/xonix/trunk/resource.h b/programs/games/xonix/trunk/resource.h new file mode 100644 index 0000000000..fff35ca30a --- /dev/null +++ b/programs/games/xonix/trunk/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by fatest.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif