!C /*----------------------------------------------------------------------+ !C | | !C | mscp.c - Marcel's Simple Chess Program | !C | | !C +----------------------------------------------------------------------+ !C | !C | Author: Marcel van Kervinck !C | Creation: 11-Jun-1998 !C | Description: Simple chess playing program !C | !C +----------------------------------------------------------------------+ !C | | !C | Copyright (C)1998-2002 Marcel van Kervinck | !C | | !C | This program is distributed under the GNU General Public License. | !C | See file COPYING or http://combinational.com/mscp/ for details. | !C | | !C +----------------------------------------------------------------------*/ ! /*----------------------------------------------------------------------+ ! | | ! | Converted to Inform by Simon Baldwin | ! | Version 1.0 - 8th August 2002 | ! | Version 1.1 - 10th September 2003 | ! | | ! +----------------------------------------------------------------------+ !C static !C char rcs_id[] = "@(#)$Id: mscp.c,v 1.12 2002/05/19 10:05:53 marcelk Exp $"; !C #include !C #include !C #include !C #include !C #include !C #include !C #include !C typedef unsigned char byte; !C #define INF 32000 #Ifndef TARGET_GLULX; Message "[MSCP requires GLULX. Sorry.]"; #Endif; #Ifdef TARGET_GLULX; Message "[MSCP]"; Constant MSCP_C_INF 32000; !C #define xisspace(c) isspace((int)(c)) !C #define xisalpha(c) isalpha((int)(c)) [ mscp_xisspace char; return (char == ' ' || char == 9); ]; ![ mscp_xisalpha char; ! return ((char >= 'a' && char <= 'z') ! || (char >= 'A' && char <= 'Z')); !]; !C /*----------------------------------------------------------------------+ !C | data structures | !C +----------------------------------------------------------------------*/ !C enum { !C A1, A2, A3, A4, A5, A6, A7, A8, !C B1, B2, B3, B4, B5, B6, B7, B8, !C C1, C2, C3, C4, C5, C6, C7, C8, !C D1, D2, D3, D4, D5, D6, D7, D8, !C E1, E2, E3, E4, E5, E6, E7, E8, !C F1, F2, F3, F4, F5, F6, F7, F8, !C G1, G2, G3, G4, G5, G6, G7, G8, !C H1, H2, H3, H4, H5, H6, H7, H8, !C CASTLE, EP !C }; Constant MSCP_C_A1 0; !Constant MSCP_C_A2 1; !Constant MSCP_C_A3 2; !Constant MSCP_C_A4 3; !Constant MSCP_C_A5 4; !Constant MSCP_C_A6 5; !Constant MSCP_C_A7 6; Constant MSCP_C_A8 7; Constant MSCP_C_B1 8; !Constant MSCP_C_B2 9; !Constant MSCP_C_B3 10; !Constant MSCP_C_B4 11; !Constant MSCP_C_B5 12; !Constant MSCP_C_B6 13; !Constant MSCP_C_B7 14; Constant MSCP_C_B8 15; Constant MSCP_C_C1 16; !Constant MSCP_C_C2 17; !Constant MSCP_C_C3 18; !Constant MSCP_C_C4 19; !Constant MSCP_C_C5 20; !Constant MSCP_C_C6 21; !Constant MSCP_C_C7 22; Constant MSCP_C_C8 23; Constant MSCP_C_D1 24; !Constant MSCP_C_D2 25; !Constant MSCP_C_D3 26; !Constant MSCP_C_D4 27; !Constant MSCP_C_D5 28; !Constant MSCP_C_D6 29; !Constant MSCP_C_D7 30; Constant MSCP_C_D8 31; Constant MSCP_C_E1 32; !Constant MSCP_C_E2 33; !Constant MSCP_C_E3 34; !Constant MSCP_C_E4 35; !Constant MSCP_C_E5 36; !Constant MSCP_C_E6 37; !Constant MSCP_C_E7 38; Constant MSCP_C_E8 39; Constant MSCP_C_F1 40; !Constant MSCP_C_F2 41; !Constant MSCP_C_F3 42; !Constant MSCP_C_F4 43; !Constant MSCP_C_F5 44; !Constant MSCP_C_F6 45; !Constant MSCP_C_F7 46; Constant MSCP_C_F8 47; Constant MSCP_C_G1 48; !Constant MSCP_C_G2 49; !Constant MSCP_C_G3 50; !Constant MSCP_C_G4 51; !Constant MSCP_C_G5 52; !Constant MSCP_C_G6 53; !Constant MSCP_C_G7 54; Constant MSCP_C_G8 55; Constant MSCP_C_H1 56; !Constant MSCP_C_H2 57; !Constant MSCP_C_H3 59; !Constant MSCP_C_H4 59; !Constant MSCP_C_H5 60; !Constant MSCP_C_H6 61; !Constant MSCP_C_H7 62; Constant MSCP_C_H8 63; Constant MSCP_C_CASTLE 64; Constant MSCP_C_EP 65; !C static byte board[66]; Array mscp_board -> 66; !C static int ply; !C #define WTM (~ply & 1) Global mscp_ply = 0; [ MSCP_WTM; return ~~(mscp_ply & 1); ]; !C #define CASTLE_WHITE_KING 1 !C #define CASTLE_WHITE_QUEEN 2 !C #define CASTLE_BLACK_KING 4 !C #define CASTLE_BLACK_QUEEN 8 Constant MSCP_C_CASTLE_WHITE_KING 1; Constant MSCP_C_CASTLE_WHITE_QUEEN 2; Constant MSCP_C_CASTLE_BLACK_KING 4; Constant MSCP_C_CASTLE_BLACK_QUEEN 8; !C static byte castle[64]; /* which piece may castle */ Array mscp_castle -> 64; !C static int computer[2]; !C static int xboard; Array mscp_computer --> 2; Global mscp_xboard_flag= 0; !C static unsigned long hash; !C static unsigned long nodes; Global mscp_hash = 0; Global mscp_nodes = 0; !C /* !C * attacks !C */ !C struct side { !C byte attack[64]; !C int king; !C byte pawns[10]; !C }; !C static struct side white, black, *friend, *enemy; Array mscp_white_attack -> 64; Global mscp_white_king = 0; Array mscp_white_pawns -> 10; Array mscp_black_attack -> 64; Global mscp_black_king = 0; Array mscp_black_pawns -> 10; Global mscp_friend_attack = 0; Global mscp_friend_king = 0; Global mscp_friend_pawns = 0; Global mscp_enemy_attack = 0; Global mscp_enemy_king = 0; Global mscp_enemy_pawns = 0; !C static unsigned short history[64*64]; Array mscp_history --> 4096; !C static signed char undo_stack[4096], *undo_sp; Array mscp_undo_stack --> 4096; Global mscp_undo_sp = 0; ! Inform note -- extra data for halfmove and last move tracking Global mscp_halfmoves = 0; Array mscp_halfmoves_list --> 1024; Array mscp_redo_list --> 1024; Global mscp_redo_lp = 0; !C static int maxdepth = 4; Global mscp_maxdepth = 3; ! Inform note - a bit snappier !C #define PRESCORE_EQUAL (10U<<9) !C #define PRESCORE_HASHMOVE (3U<<14) !C #define PRESCORE_KILLERMOVE (2U<<14) !C #define PRESCORE_COUNTERMOVE (1U<<14) Constant MSCP_C_PRESCORE_EQUAL $1400; Constant MSCP_C_PRESCORE_HASHMOVE $C000; !Constant MSCP_C_PRESCORE_KILLERMOVE $8000; !Constant MSCP_C_PRESCORE_COUNTERMOVE $4000; !C static const int prescore_piece_value[] = { !C 0, !C 0, 9<<9, 5<<9, 3<<9, 3<<9, 1<<9, !C 0, 9<<9, 5<<9, 3<<9, 3<<9, 1<<9, !C }; Array mscp_prescore_piece_value --> 0 0 $1200 $A00 $600 $600 $200 0 $1200 $A00 $600 $600 $200; !C struct move { !C short move; !C unsigned short prescore; !C }; !C static struct move move_stack[1024], *move_sp; Array mscp_move_stack_move --> 1024; Array mscp_move_stack_prescore --> 1024; Global mscp_move_sp = 0; !C static int piece_square[12][64]; !C static unsigned long zobrist[12][64]; Array mscp_piece_square --> 768; ! Inform note - precalculated, to ensure book hashes match Array mscp_zobrist --> $3AB50C2A $4431B782 $1C06DAC8 $06058ED8 $56E509FE $56F32F43 $77A4044D $31169898 $427C3C55 $6A5D128C $046CDBE2 $06D7D4B3 $43CD3747 $55E83917 $00FC4111 $3113C398 $088E4954 $35702E2F $57E82B11 $4B63962D $77188B05 $6C4F3258 $437266F5 $0BC5816B $53B39DD6 $353F7788 $59C09D07 $74856499 $618FB492 $21980F48 $06135133 $5E37EE62 $2A039441 $50FA4CF3 $60D20F0D $7EDA5023 $2EC36AE5 $1F9EF85F $7DC43530 $5C8022D1 $606DF6C8 $5364F5ED $094DC561 $50D9680C $713E154B $22E82902 $37DC5435 $621C8039 $3D265081 $1E6F6484 $233025B8 $2DFC6514 $15501BA2 $3E46339C $72E666B4 $7460EE5A $07C09267 $73CBAC2A $409434CA $4215DAE5 $28D61248 $7E4A49E9 $3F3AA0C5 $221105F1 $0B9D22B0 $795056C4 $09709C15 $40172B8A $312B91E5 $23776A9B $74F7F84D $43CEC339 $3B72F5F6 $787207F7 $066926E8 $61794CA1 $62961005 $69F5EAD3 $100BF8FE $0207F3ED $581F4DA5 $6F22B8D5 $5094E0F3 $5E3C9AD9 $5CDA4CE4 $7FEE3C5B $71BCBBFA $1DD9546C $27358DC3 $2CEE1151 $41B2F3E2 $4BA99C20 $6C491FAE $34BF100C $6BB69EE1 $2278FD06 $352BA698 $44C6606D $3BE4B761 $24C35FFF $16D37134 $13AD18A1 $492BFC1E $66B53B19 $043B1AFD $4468DA36 $3FCE3250 $7A4942E9 $5FC80DB7 $46FC9A81 $7203AF8F $4FFB0FC3 $6BC7F43A $1473431E $1B3B710F $5B7B9DC0 $10B1D72C $0BA59244 $2325B455 $00624A7A $35078FC8 $0370AEAB $5ADB5E50 $780D04C9 $1EB565B2 $172798DE $28A522B2 $7188E8F6 $5376A8B5 $133E2DE2 $57365A4C $3162604F $31A0FBDD $3FF7839F $12E25C88 $4B28EE67 $6C3BD2BD $4B88ADCE $7A4AD61F $472FCBF2 $12F6A161 $7DDCF100 $3452778E $12272678 $484E9997 $2045AD97 $3E87A50E $3B655A34 $7B052A62 $1021C707 $1991A4D7 $28DD2C5E $508BE447 $10381AA1 $535C4858 $4F91B429 $66CB188E $1FB9475B $3CFBB7A2 $31D50BF5 $1A041B62 $03A1CC46 $736A0986 $3697779C $122DBEC4 $79473F2E $34852336 $10CAC92A $715CED02 $0BCC5873 $14C2EC12 $09189C64 $2EC36DE6 $20642F06 $114B4387 $643E5CEF $3A478253 $2CBD3509 $39E4F8D1 $678B7F08 $77411B53 $5369234F $1B8D4251 $56FCE1F8 $74578D65 $20041D8F $6E30A7B4 $3C5252F0 $40C32980 $4CD9B3B7 $68A5DACB $60BF7B19 $3B2AD7EE $79C6689A $50FD94EB $383BF9D7 $698FAF18 $583086CC $59E1E84F $7E5AC8A2 $7A2A447C $6CF6678C $25085037 $44CA5DDF $41D8FEC1 $0D3D52AD $34FEE2A5 $49D1D9D1 $70334E33 $38532FD1 $5D685F3A $6F4408BE $5B9A2B03 $667E00F0 $5A6FC121 $5EF08BE9 $02719EB1 $716977B7 $4332C98C $3B4E28CB $085845D8 $5B516C2F $3E95B07F $557681F2 $574D62B3 $198B028C $7554426D $6ED53E48 $71EC21D0 $45A0191E $11D12448 $39A4FC1B $7EA36E2D $1B968D4F $39174BAF $2869EB71 $41E05C71 $70D52080 $3848ED5F $3BD814D7 $67404DF2 $2EBD7FD3 $1B130D9E $7FE30DF4 $13A94FC4 $50B3D6F1 $4EE4919B $00137F94 $001CCD96 $62FD32E8 $5D19501D $28DACFAB $3577F881 $575BF893 $571CA7B3 $1A460573 $6B0FCE7E $5ABDE91B $6A131A27 $0C1A2CD9 $0A7660C4 $61CAE939 $5095CF57 $1B5F8216 $1B558064 $0A603341 $31C4F5B9 $79E05E35 $79492815 $31E6B8E8 $2275A0F0 $5898FE3C $245B4295 $637056D8 $6455B1E8 $361329CE $241DAF1E $18D3ED18 $0172CF64 $188DAEFA $7DDAABAD $1F3D2B68 $68ECC8DD $11775AFC $32F65F59 $4CEDE632 $16A40413 $6A078701 $14308909 $7E74B839 $20EAE70B $1DE6940F $0D02741F $1C15A5E5 $513E6BCA $5916C471 $65BB0468 $591E7C05 $606059F8 $55B2DA36 $51143B2E $07397298 $4C925CDC $1D0E96CA $28CDB6AD $59942CC8 $0F082C6A $619BEADB $435801ED $46E69125 $4B433880 $2A32821A $59FB8E9A $124F4E9D $14B22ECF $3E1F22A6 $6E1BE026 $68191743 $47466519 $5E9770DD $2872EDAF $115290E8 $43A7783A $27C64A89 $4B477CC5 $4250901F $3726053C $2121C26D $2F639319 $324E669D $3932E738 $3CEA2ADE $31A47410 $23BFDFE6 $0A048760 $2F53B4C3 $2080867B $55FD05E8 $568EEE72 $41C8AAC3 $5D4309F2 $5C421EB3 $78EDA916 $3AF82160 $785743DE $2928E18B $3AEF81C9 $4231D159 $54A74C02 $336F42B9 $4D859A10 $7E45B832 $13401B62 $55C5C8CD $2C0236B9 $4556C241 $42EB5CF7 $6A247E73 $01E9E676 $23194DF5 $524D21D3 $45E7CDDB $757C08B7 $222062A3 $7C2BCCD5 $1F94F3A3 $6C076287 $58D5C479 $3A56117F $6896C6C4 $02D3A381 $14936B9A $5A7D5603 $5A9A0D5E $37E3C4CA $4A8CC670 $6038094C $7EEA8DED $590C03B3 $23C70A71 $607E9310 $15E930EE $008B647F $3F72CE20 $0A3AB76B $14DFD70C $739F5F88 $64391505 $5F932EAA $37DCCBEB $00CFCDF4 $4ADA4E96 $425D803E $088E887C $45A28947 $31E2B808 $1BA02ECE $3160E48D $503CFE4E $545BDC09 $5ACAFE23 $44F2DA66 $23E081E7 $68707717 $2F9ABC92 $57D22DA8 $27B39DA3 $01324CB2 $0D493ABB $42AED1CD $63500BEE $1C3F6932 $0713601B $090A903E $1483DB15 $5CA44A38 $2604D20C $067A2554 $3D28B11E $3A8447F0 $428EFB93 $39269208 $133D6888 $2499C296 $6AB6189F $590AA574 $49F49057 $573065AF $2A63F0E1 $075B5985 $7E522E88 $456D2382 $00364F6A $6D97B841 $03C1EB9D $30539258 $3EACE831 $49C0091C $5E963317 $56F45B84 $44A463B5 $048E2348 $0FAE4E4E $7C96EAEC $18196BDB $2CF80339 $4E9BAA3F $4DC6366A $101E910A $46C42FCA $7A1D9B11 $2DAFB7B9 $6B46EA1D $7CB44CF0 $21276086 $20320E6B $3650A350 $6811F50B $72EEDA8D $1F4E99EE $615BE850 $58F10E1F $39D642D7 $21BE4EEB $552F379B $0EEBCCCE $1AD2F009 $0E8CECA1 $4603457D $00C73574 $16865312 $4CB7CE4B $3748C546 $0A8F9305 $57FD32AD $300A28FC $6B08D107 $0FD35977 $7C969BBE $03CB16D9 $0A490281 $3F43686D $627CEC8D $778E4F7E $20051684 $2E094488 $62725454 $3FFE894A $5FE77A18 $5600EED8 $5740D304 $60DDD85C $04A7B1B3 $1D836128 $1C5F983B $4803580A $53891D75 $4EED172B $2F8C3088 $1CC6491B $1DE99A5F $5395E250 $153D1D0F $5F3ECEAD $1472F0B5 $06190590 $54BC3410 $0FFE31E6 $797DFB3D $3DF9A01B $4F7E6C66 $74FEC54F $024C018B $4BF94DDA $5C664A2D $3F8FFFBF $06DF7533 $38876ACB $4274526B $62CF10E2 $085D981C $38AD5A8E $7D143DB3 $3BDEF2EC $2A1E82A9 $39143AD9 $5F2399D5 $1A489FBF $15EFC214 $2FAEBA4C $7848EC08 $7B803EE9 $20A27257 $0900BE7E $0FDA46D0 $435F09D1 $147D9AE5 $42443AE5 $0D76B260 $6BB8C387 $2F2D0B51 $36420B09 $29E297B3 $5B557E40 $49D3CA98 $6F99E705 $610E3280 $6B15A347 $5992C13D $31CCB9BC $77B5FF2E $4D846268 $2E58C19A $450E7D3B $3A3FCFE8 $336AA638 $1EC6C0E7 $0AA28D7A $35F64A0A $3C76F233 $25171148 $0D6FA0FE $1BB28A96 $66A88C0E $43831FC9 $559BE7BF $6E8BD881 $1F3335DA $5B148B36 $21BFB4F1 $31004B86 $0A5E638C $3AD981A5 $1DCE95D2 $65CE1D47 $3EE45488 $0069CCFA $2210314C $5514860C $366CA977 $17E9DF8B $7B532AF0 $112831D1 $65DE9923 $7917FD14 $15E86A28 $4D917354 $082AB795 $2C7A9B63 $256F9765 $413C7B16 $69B502CF $6ACB9A40 $5CFC1686 $2A2AE71B $66AAB33D $50DD9E73 $05CDB97F $054D43D3 $139FD45D $622F2FBB $07E6D059 $4278871C $76EE615B $1C39DA5D $1A2F1E25 $0B641C91 $598F796E $5A6D52B1 $3F5010D8 $2181F561 $5B14C476 $306E4DB1 $19AEB84E $1DC6160E $37D20067 $3C1886D2 $6E3B63D0 $7D162539 $38E60157 $046213F0 $430AF3CF $040CBD6C $6067FF87 $4BB92983 $69547E4B $2A2FA3F3 $1DB4BC28 $44ACF554 $371E8105 $33A88B88 $7E60A836 $7BC3B20B $6CDE2FA7 $6F0AB4C7 $27E2ADC5 $12FE74F8 $7FB14F85 $51DBE641 $3BE9DF63 $7748FB4F $586B3CB7 $685F3FBA $455101DE $4951B95F $14613194 $78FDF5FF $69217667 $13E49A1D $0541F01F $2BFB85EB $0E151DDC $0C5B5DBD $426729A1 $02DE2B16 $47DEB2D2 $6DAE1DDA $422A0B77 $5656D390 $5E5BBF38 $596725ED $02EB1876 $1892EC79 $55E30889 $2C45866C $087C3329 $1202CD19 $75E72D8B $1C5F3D26 $30A79857 $4B0290B5 $156A818C $035F1950 $5876D4EA $61947C05 $5B5A5E4F $09E5C364 $4B7EDF4F $7676E241 $77005629 $3718DAC8 $40C39CBA $6A66988D $75A9878D $4D027654 $5CA6AC4B $42799F72 $3ED31776 $14A96433 $7CF15ADD $4984A340 $22F9E475 $4405CF43 $596A5A98 $5561DF04 $0C78AB67 $463CFD96 $4E2CA6E0 $557FE438 $3F604462 $49299E6F $4B60AEEF $387CF392 $135B1337 $404A89CE $5D9D545B $040D5261 $069B605B $42D2F9C0 $290ACE86 $047CD477 $1F60D2EE $0DB8175A $31051CBF $46A258BD $4C700485 $4E38DEF7 $77B6523F $62D1E37F $41AED988 $3E4B9168 $533762CB $5937281B $342A325F $3E5115BA $3D69864C $5AF00713 $44609F09 $23692AF1 $4D824660 $23DA7061 $5A0802AA $43E71513 $7818B538 $1E21AD21 $34ED60FB $4C7A19E2 $64396BA7 $75CAD458 $573B19D2 $691C56BB $438244E6 $1D797AAA $12643E04 $7323820A $202E9994 $5364D40D $009DCC41 $77CCBFB7 $233EC4D3 $6DEC0AB8 $23B3EE69 $79E941CE $40DF79E9 $0FBCD145 $354F1115 $59EA950A $37DEF1A4 $0DCA62A4 $6212040E $0CC8656F $387B60F7 $2C1B1519 $260632EE $60F9BAC2 $2B54484B $2A564A26 $071E1A81; !C #define CORE (2048) /* power of 2 */ !C static long booksize; !C /* transposition table and opening book share memory */ !C static union { !C struct tt { !C unsigned short hash; !C short move; !C short score; !C char flag; !C char depth; !C } tt[CORE]; !C struct bk { !C unsigned long hash; !C short move; !C unsigned short count; !C } bk[CORE]; !C } core; !C #define ttable core.tt !C #define book core.bk Constant MSCP_C_CORE 2048; ! Inform note - flag is 0, or +/-1, so pack into a byte by always adding 1 Array mscp_ttable_hash --> MSCP_C_CORE; Array mscp_ttable_move --> MSCP_C_CORE; Array mscp_ttable_score --> MSCP_C_CORE; Array mscp_ttable_flag -> MSCP_C_CORE; Array mscp_ttable_depth -> MSCP_C_CORE; !C /*----------------------------------------------------------------------+ !C | chess defines | !C +----------------------------------------------------------------------*/ !C enum { !C EMPTY, !C WHITE_KING, WHITE_QUEEN, WHITE_ROOK, !C WHITE_BISHOP, WHITE_KNIGHT, WHITE_PAWN, !C BLACK_KING, BLACK_QUEEN, BLACK_ROOK, !C BLACK_BISHOP, BLACK_KNIGHT, BLACK_PAWN !C }; Constant MSCP_C_EMPTY 0; Constant MSCP_C_WHITE_KING 1; Constant MSCP_C_WHITE_QUEEN 2; Constant MSCP_C_WHITE_ROOK 3; Constant MSCP_C_WHITE_BISHOP 4; Constant MSCP_C_WHITE_KNIGHT 5; Constant MSCP_C_WHITE_PAWN 6; Constant MSCP_C_BLACK_KING 7; Constant MSCP_C_BLACK_QUEEN 8; Constant MSCP_C_BLACK_ROOK 9; Constant MSCP_C_BLACK_BISHOP 10; Constant MSCP_C_BLACK_KNIGHT 11; Constant MSCP_C_BLACK_PAWN 12; !C #define PIECE_COLOR(pc) ((pc) < BLACK_KING) [ MSCP_PIECE_COLOR pc; return (pc < MSCP_C_BLACK_KING); ]; !C #define DIR_N (+1) !C #define DIR_E (+8) Constant MSCP_C_DIR_N 1; Constant MSCP_C_DIR_E 8; !C enum { FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H }; !C enum { RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8 }; Constant MSCP_C_FILE_A 0; !Constant MSCP_C_FILE_B 1; !Constant MSCP_C_FILE_C 2; !Constant MSCP_C_FILE_D 3; !Constant MSCP_C_FILE_E 4; !Constant MSCP_C_FILE_F 5; !Constant MSCP_C_FILE_G 6; Constant MSCP_C_FILE_H 7; Constant MSCP_C_RANK_1 0; Constant MSCP_C_RANK_2 1; !Constant MSCP_C_RANK_3 2; Constant MSCP_C_RANK_4 3; Constant MSCP_C_RANK_5 4; !Constant MSCP_C_RANK_6 5; Constant MSCP_C_RANK_7 6; Constant MSCP_C_RANK_8 7; !C #define RANK2CHAR(r) ('1'+(r)) [ MSCP_RANK2CHAR r; return ('1' + r); ]; !C #define CHAR2RANK(c) ((c)-'1') ![ MSCP_CHAR2RANK c; ! return (c - '1'); !]; !C #define FILE2CHAR(f) ('a'+(f)) [ MSCP_FILE2CHAR f; return ('a' + f); ]; !C #define CHAR2FILE(c) ((c)-'a') [ MSCP_CHAR2FILE c; return (c - 'a'); ]; !C #define PIECE2CHAR(p) ("-KQRBNPkqrbnp"[p]) [ MSCP_PIECE2CHAR p; switch (p) { 0: return '-'; 1: return 'K'; 2: return 'Q'; 3: return 'R'; 4: return 'B'; 5: return 'N'; 6: return 'P'; 7: return 'k'; 8: return 'q'; 9: return 'r'; 10: return 'b'; 11: return 'n'; 12: return 'p'; } return '?'; ]; !C #define F(square) ((square) >> 3) /* file */ [ MSCP_F square; return (square / 8); ]; !C #define R(square) ((square) & 7) /* rank */ [ MSCP_R square; return (square & 7); ]; !C #define SQ(f,r) (((f) << 3) | (r)) /* compose square */ [ MSCP_SQ f r; return ((f * 8) | r); ]; !C #define FLIP(square) ((sq)^7) /* flip board */ ! Inform note -- C code bug in FLIP macro definition [ MSCP_FLIP square; return ((square | 7) & ~(square & 7)); ]; !C #define MOVE(fr,to) (((fr) << 6) | (to)) /* compose move */ [ MSCP_MOVE fr _to; return ((fr * 64) | _to); ]; !C #define FR(move) (((move) & 07700) >> 6) /* from square */ [ MSCP_FR _move; return ((_move & $FC0) / 64); ]; !C #define TO(move) ((move) & 00077) /* to square */ [ MSCP_TO _move; return (_move & $3F); ]; !C #define SPECIAL 4096 Constant MSCP_C_SPECIAL 4096; !C struct cmd { !C char *name; !C void (*cmd)(char*); !C char *help; !C }; !C /* attacks */ !C #define ATKB_NORTH 0 !C #define ATKB_NORTHEAST 1 !C #define ATKB_EAST 2 !C #define ATKB_SOUTHEAST 3 !C #define ATKB_SOUTH 4 !C #define ATKB_SOUTHWEST 5 !C #define ATKB_WEST 6 !C #define ATKB_NORTHWEST 7 !C #define ATK_NORTH (1 << ATKB_NORTH) !C #define ATK_NORTHEAST (1 << ATKB_NORTHEAST) !C #define ATK_EAST (1 << ATKB_EAST) !C #define ATK_SOUTHEAST (1 << ATKB_SOUTHEAST) !C #define ATK_SOUTH (1 << ATKB_SOUTH) !C #define ATK_SOUTHWEST (1 << ATKB_SOUTHWEST) !C #define ATK_WEST (1 << ATKB_WEST) !C #define ATK_NORTHWEST (1 << ATKB_NORTHWEST) !Constant MSCP_C_ATK_NORTH $$00000001; !Constant MSCP_C_ATK_NORTHEAST $$00000010; !Constant MSCP_C_ATK_EAST $$00000100; !Constant MSCP_C_ATK_SOUTHEAST $$00001000; !Constant MSCP_C_ATK_SOUTH $$00010000; !Constant MSCP_C_ATK_SOUTHWEST $$00100000; !Constant MSCP_C_ATK_WEST $$01000000; !Constant MSCP_C_ATK_NORTHWEST $$10000000; !C #define ATK_ORTHOGONAL ( ATK_NORTH | ATK_SOUTH | \ !C ATK_WEST | ATK_EAST ) Constant MSCP_C_ATK_ORTHOGONAL $$01010101; !C #define ATK_DIAGONAL ( ATK_NORTHEAST | ATK_NORTHWEST | \ !C ATK_SOUTHEAST | ATK_SOUTHWEST ) Constant MSCP_C_ATK_DIAGONAL $$10101010; !C #define ATK_SLIDER ( ATK_ORTHOGONAL | ATK_DIAGONAL ) Constant MSCP_C_ATK_SLIDER $$11111111; !C /* logtab[] combines 3 (merged) tables, each indexable with (1< 0 0 1 0 2 0 1 9 3 8 0 (-6) 10 7 17 0 4 0 15 0 0 (-1) 0 0 0 0 (-10) 0 0 0 0 0 5 0 0 0 0 (-9) 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 (-8) 0 0 0 0 (-15) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 (-7) 0 0 0 0 (-17); !C /* which directions a king can walk to */ !C static const byte king_dirs[64] = { !C 7, 31, 31, 31, 31, 31, 31, 28, !C 199, 255, 255, 255, 255, 255, 255, 124, !C 199, 255, 255, 255, 255, 255, 255, 124, !C 199, 255, 255, 255, 255, 255, 255, 124, !C 199, 255, 255, 255, 255, 255, 255, 124, !C 199, 255, 255, 255, 255, 255, 255, 124, !C 199, 255, 255, 255, 255, 255, 255, 124, !C 193, 241, 241, 241, 241, 241, 241, 112, !C }; Array mscp_king_dirs -> 7 31 31 31 31 31 31 28 199 255 255 255 255 255 255 124 199 255 255 255 255 255 255 124 199 255 255 255 255 255 255 124 199 255 255 255 255 255 255 124 199 255 255 255 255 255 255 124 199 255 255 255 255 255 255 124 193 241 241 241 241 241 241 112; !C /* which directions a knight can jump to */ !C static const byte knight_dirs[64] = { !C 6, 14, 46, 46, 46, 46, 44, 40, !C 7, 15, 63, 63, 63, 63, 60, 56, !C 71, 207, 255, 255, 255, 255, 252, 184, !C 71, 207, 255, 255, 255, 255, 252, 184, !C 71, 207, 255, 255, 255, 255, 252, 184, !C 71, 207, 255, 255, 255, 255, 252, 184, !C 67, 195, 243, 243, 243, 243, 240, 176, !C 65, 193, 209, 209, 209, 209, 208, 144, !C }; Array mscp_knight_dirs -> 6 14 46 46 46 46 44 40 7 15 63 63 63 63 60 56 71 207 255 255 255 255 252 184 71 207 255 255 255 255 252 184 71 207 255 255 255 255 252 184 71 207 255 255 255 255 252 184 67 195 243 243 243 243 240 176 65 193 209 209 209 209 208 144; !C /*----------------------------------------------------------------------+ !C | simple random generator | !C +----------------------------------------------------------------------*/ !C static long rnd_seed = 1; !C static long rnd(void) !C { !C long r = rnd_seed; !C r = 16807 * (r % 127773L) - 2836 * (r / 127773L); !C if (r < 0) r += 0x7fffffffL; !C return rnd_seed = r; !C } ! /*----------------------------------------------------------------------+ ! | output buffering, tick callback | ! +----------------------------------------------------------------------*/ ! Output buffer, and note of size, callback, and use. Global mscp_output_buffer = 0; Global mscp_output_size = 0; Global mscp_output_callback = 0; Global mscp_output_count = 0; ! Register an output buffer. [ mscp_use_buffer buf size callback; ! See if a buffer and optional callback were given. if (buf ~= 0) { ! Keep the buffer address, and note the size passed in. mscp_output_buffer = buf; mscp_output_size = size; ! Note any output callback function, clear output so far. mscp_output_callback = callback; mscp_output_count = 0; return; } ! Output buffering turned off. mscp_output_buffer = 0; mscp_output_size = 0; mscp_output_callback = 0; mscp_output_count = 0; ]; ! Buffer an output character. [ mscp_print_char c; ! Check there is a buffer, with enough space. if (mscp_output_count >= mscp_output_size) return; ! Add the output character, and update counts. mscp_output_buffer->mscp_output_count++ = c; ! If newline and there is a callback, call it. if (c == '^' && mscp_output_callback ~= 0) { ! If callback returns true, flush buffered data. if (mscp_output_callback ! indirect (mscp_output_buffer, mscp_output_count)) { mscp_output_count = 0; ! drop current data } } ]; ! Buffer an output string. [ mscp_print_string s i; ! Ignore the call if no output buffer. if (mscp_output_count >= mscp_output_size) return; ! Print string characters. for (i = 1: i <= s->0: i++) { mscp_print_char (s->i); } ]; ! Buffer an output integer, with specific width and padding. Array mscp_number_stack -> 11; [ mscp_print_number num width zeroes ! varargs neg n i; ! Ignore the call if no output buffer. if (mscp_output_count >= mscp_output_size) return; ! Note sign, and make +ve. n = num; neg = false; if (n < 0) { neg = true; n = -n; ! incorrect if n == -MAXINT } ! Stack digits. i = 0; while (n > 0) { mscp_number_stack->i++ = n % 10 + '0'; n = n / 10; } if (i == 0) mscp_number_stack->i++ = '0'; ! Pad if required, and add sign. if (zeroes) { while (i < 10 && i < width - 1) mscp_number_stack->i++ = '0'; if (neg) mscp_number_stack->i++ = '-'; else if (i < width) mscp_number_stack->i++ = '0'; } else { if (neg) mscp_number_stack->i++ = '-'; while (i < 11 && i < width) mscp_number_stack->i++ = ' '; } ! Print number stack. i--; while (i >= 0) { mscp_print_char (mscp_number_stack->i); i--; } ]; ! Tick function, opaque argument, and unwind request flag. Global mscp_tick_function = 0; Global mscp_tick_opaque = 0; Global mscp_unwind_requested = false; ! Register a tick callback function. [ mscp_tick_register callback opaque; ! Note function and opaque. mscp_tick_function = callback; mscp_tick_opaque = opaque; ! Clear unwind flag. mscp_unwind_requested = false; ]; ! Call any registered tick function. [ mscp_tick_check retcode; ! If we have a tick function to call, call it. if (mscp_tick_function ~= 0) { retcode = mscp_tick_function (mscp_tick_opaque); ! indirect ! If tick false, set unwind flag; clear count. if (~~retcode) mscp_unwind_requested = true; } ]; !C /*----------------------------------------------------------------------+ !C | i/o functions | !C +----------------------------------------------------------------------*/ !C static void print_square(int square) !C { !C putchar(FILE2CHAR(F(square))); !C putchar(RANK2CHAR(R(square))); !C } [ mscp_print_square square; mscp_print_char (MSCP_FILE2CHAR (MSCP_F (square))); mscp_print_char (MSCP_RANK2CHAR (MSCP_R (square))); ]; !C static void print_move_long(int move) !C { !C print_square(FR(move)); !C print_square(TO(move)); !C if (move >= SPECIAL) { !C if ((board[FR(move)] == WHITE_PAWN && R(TO(move)) == RANK_8) !C || (board[FR(move)] == BLACK_PAWN && R(TO(move)) == RANK_1)) { !C putchar('='); !C putchar("QRBN"[move >> 13]); !C } !C } !C } [ mscp_print_move_long _move; mscp_print_square (MSCP_FR (_move)); mscp_print_square (MSCP_TO (_move)); if (_move >= MSCP_C_SPECIAL) { if ((mscp_board->(MSCP_FR (_move)) == MSCP_C_WHITE_PAWN && MSCP_R (MSCP_TO (_move)) == MSCP_C_RANK_8) || (mscp_board->(MSCP_FR (_move)) == MSCP_C_BLACK_PAWN && MSCP_R (MSCP_TO (_move)) == MSCP_C_RANK_1)) { mscp_print_char ('='); switch (_move / 8192) { 0: mscp_print_char ('Q'); 1: mscp_print_char ('R'); 2: mscp_print_char ('B'); 3: mscp_print_char ('N'); } } } ]; !C static void print_board(void) !C { !C int file, rank; !C for (rank=RANK_8; rank>=RANK_1; rank--) { !C printf("%d ", 1+rank); !C for (file=FILE_A; file<=FILE_H; file++) { !C putchar(' '); !C putchar(PIECE2CHAR(board[SQ(file,rank)])); !C } !C putchar('\n'); !C } !C printf(" a b c d e f g h\n%d. %s to move. %s%s%s%s ", !C 1+ply/2, WTM ? "White" : "Black", !C board[CASTLE] & CASTLE_WHITE_KING ? "K" : "", !C board[CASTLE] & CASTLE_WHITE_QUEEN ? "Q" : "", !C board[CASTLE] & CASTLE_BLACK_KING ? "k" : "", !C board[CASTLE] & CASTLE_BLACK_QUEEN ? "q" : "" !C ); !C if (board[EP]) print_square(board[EP]); !C putchar('\n'); !C } Array mscp_print_board_abc string " a b c d e f g h^"; Array mscp_print_board_wtm string "White to move. "; Array mscp_print_board_btm string "Black to move. "; [ mscp_print_board file rank castle; for (rank = MSCP_C_RANK_8: rank >= MSCP_C_RANK_1: rank--) { mscp_print_number (1 + rank); mscp_print_char (' '); for (file=MSCP_C_FILE_A: file<=MSCP_C_FILE_H: file++) { mscp_print_char (' '); mscp_print_char (MSCP_PIECE2CHAR (mscp_board->(MSCP_SQ (file,rank)))); } mscp_print_char ('^'); } mscp_print_string (mscp_print_board_abc); mscp_print_number (1 + mscp_ply / 2); mscp_print_char ('.'); mscp_print_char (' '); if (MSCP_WTM ()) mscp_print_string (mscp_print_board_wtm); else mscp_print_string (mscp_print_board_btm); castle = mscp_board->MSCP_C_CASTLE; if (castle & MSCP_C_CASTLE_WHITE_KING) mscp_print_char ('K'); if (castle & MSCP_C_CASTLE_WHITE_QUEEN) mscp_print_char ('Q'); if (castle & MSCP_C_CASTLE_BLACK_KING) mscp_print_char ('k'); if (castle & MSCP_C_CASTLE_BLACK_QUEEN) mscp_print_char ('q'); mscp_print_char (' '); if (mscp_board->MSCP_C_EP) mscp_print_square (mscp_board->MSCP_C_EP); mscp_print_char ('^'); ]; !C static int readline(char *line, int size, FILE *fp) !C { !C int c; !C int pos = 0; !C for (;;) { !C errno = 0; !C c = fgetc(fp); !C if (c == EOF) { !C if (!errno) return -1; !C printf("error: %s\n", strerror(errno)); !C errno = 0; !C continue; !C } !C if (c == '\n') { !C break; !C } !C if (pos < size-1) { !C line[pos++] = c; !C } !C } !C line[pos] = 0; !C return pos; !C } !C /*----------------------------------------------------------------------+ !C | position | !C +----------------------------------------------------------------------*/ !C static void setup_board(char *fen) !C { !C int file=FILE_A, rank=RANK_8; !C while (xisspace(*fen)) fen++; !C memset(board, 0, sizeof(board)); !C while (rank>RANK_1 || file<=FILE_H) { !C int piece = EMPTY; !C int count = 1; !C switch (*fen) { !C case 'K': piece = WHITE_KING; break; !C case 'Q': piece = WHITE_QUEEN; break; !C case 'R': piece = WHITE_ROOK; break; !C case 'B': piece = WHITE_BISHOP; break; !C case 'N': piece = WHITE_KNIGHT; break; !C case 'P': piece = WHITE_PAWN; break; !C case 'k': piece = BLACK_KING; break; !C case 'r': piece = BLACK_ROOK; break; !C case 'q': piece = BLACK_QUEEN; break; !C case 'b': piece = BLACK_BISHOP; break; !C case 'n': piece = BLACK_KNIGHT; break; !C case 'p': piece = BLACK_PAWN; break; !C case '/': rank -= 1; file = FILE_A; fen++; continue; !C case '1': case '2': case '3': case '4': !C case '5': case '6': case '7': case '8': !C count = *fen - '0'; !C break; !C default: !C puts("fen error\n"); !C return; !C } !C do { !C board[SQ(file,rank)] = piece; !C file ++; !C } while (--count); !C fen++; !C } !C ply = fen[1] == 'b'; !C fen += 2; !C while (*fen) { !C switch (*fen) { !C case 'K': board[CASTLE] |= CASTLE_WHITE_KING; break; !C case 'Q': board[CASTLE] |= CASTLE_WHITE_QUEEN; break; !C case 'k': board[CASTLE] |= CASTLE_BLACK_KING; break; !C case 'q': board[CASTLE] |= CASTLE_BLACK_QUEEN; break; !C case 'a': case 'b': case 'c': case 'd': !C case 'e': case 'f': case 'g': case 'h': !C board[EP] = SQ(CHAR2FILE(*fen),WTM?RANK_4:RANK_5); !C break; !C default: !C break; !C } !C fen++; !C } !C move_sp = move_stack; !C undo_sp = undo_stack; !C print_board(); !C } Array mscp_setup_board_fenerr string "fen error^"; Array mscp_setup_temp -> 66; [ mscp_setup_board fen file rank i j piece count hm mnum; #Ifdef MSCP_DEBUG; print "[MSCP> setup_board ", fen, "]^"; #Endif; file = MSCP_C_FILE_A; rank = MSCP_C_RANK_8; for (j = 0: j < 66: j++) ! Inform note - read FEN into mscp_setup_temp->j = 0; ! a temporary array first i = 1; while (i <= fen->0 && mscp_xisspace (fen->i)) i++; while (i <= fen->0 && (rank > MSCP_C_RANK_1 || file <= MSCP_C_FILE_H)) { piece = MSCP_C_EMPTY; count = 1; switch (fen->i) { 'K': piece = MSCP_C_WHITE_KING; 'Q': piece = MSCP_C_WHITE_QUEEN; 'R': piece = MSCP_C_WHITE_ROOK; 'B': piece = MSCP_C_WHITE_BISHOP; 'N': piece = MSCP_C_WHITE_KNIGHT; 'P': piece = MSCP_C_WHITE_PAWN; 'k': piece = MSCP_C_BLACK_KING; 'r': piece = MSCP_C_BLACK_ROOK; 'q': piece = MSCP_C_BLACK_QUEEN; 'b': piece = MSCP_C_BLACK_BISHOP; 'n': piece = MSCP_C_BLACK_KNIGHT; 'p': piece = MSCP_C_BLACK_PAWN; '/': rank--; file = MSCP_C_FILE_A; i++; if (rank < 0) { mscp_print_string (mscp_setup_board_fenerr); return false; } continue; '1', '2', '3', '4', '5', '6', '7', '8': count = fen->i - '0'; default: mscp_print_string (mscp_setup_board_fenerr); return false; } while (count > 0 && file <= MSCP_C_FILE_H) { mscp_setup_temp->(MSCP_SQ (file,rank)) = piece; file++; count--; } i++; } if (i + 1 > fen->0) { mscp_print_string (mscp_setup_board_fenerr); return false; } ! Inform note - move board data to real board on valid FEN for (j = 0: j < 66: j++) mscp_board->j = mscp_setup_temp->j; mscp_ply = (fen->(i + 1) == 'b'); i = i + 2; while (i <= fen->0 && mscp_xisspace (fen->i)) i++; while (i <= fen->0 && ~~(mscp_xisspace (fen->i))) { switch (fen->i) { 'K': mscp_board->MSCP_C_CASTLE = mscp_board->MSCP_C_CASTLE | MSCP_C_CASTLE_WHITE_KING; 'Q': mscp_board->MSCP_C_CASTLE = mscp_board->MSCP_C_CASTLE | MSCP_C_CASTLE_WHITE_QUEEN; 'k': mscp_board->MSCP_C_CASTLE = mscp_board->MSCP_C_CASTLE | MSCP_C_CASTLE_BLACK_KING; 'q': mscp_board->MSCP_C_CASTLE = mscp_board->MSCP_C_CASTLE | MSCP_C_CASTLE_BLACK_QUEEN; } i++; } while (i <= fen->0 && mscp_xisspace (fen->i)) i++; while (i <= fen->0 && ~~(mscp_xisspace (fen->i))) { switch (fen->i) { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h': ! Inform note -- C MSCP has a bug here: RANK_5 should ! be used for active white, RANK4 for active black; ! the bug's corrected here if (MSCP_WTM ()) mscp_board->MSCP_C_EP = MSCP_SQ (MSCP_CHAR2FILE (fen->i), MSCP_C_RANK_5); else mscp_board->MSCP_C_EP = MSCP_SQ (MSCP_CHAR2FILE (fen->i), MSCP_C_RANK_4); } i++; } hm = 0; while (i <= fen->0 && mscp_xisspace (fen->i)) i++; while (i <= fen->0 && fen->i >= '0' && fen->0 && fen->i <= '9' ) { hm = hm * 10 + fen->i - '0'; i++; } mscp_halfmoves = hm; mnum = 0; while (i <= fen->0 && mscp_xisspace (fen->i)) i++; while (i <= fen->0 && fen->i >= '0' && fen->0 && fen->i <= '9' ) { mnum = mnum * 10 + fen->i - '0'; i++; } if (mnum > 0) mscp_ply = mscp_ply + 2 * mnum - 2; mscp_move_sp = 0; mscp_undo_sp = 0; mscp_redo_lp = 0; mscp_print_board (); return true; ]; !C /*----------------------------------------------------------------------+ !C | transposition tables | !C +----------------------------------------------------------------------*/ !C static void compute_hash(void) !C { !C int sq; !C hash = 0; !C for(sq=0; sq<64; sq++) { !C if (board[sq] != EMPTY) { !C hash ^= zobrist[board[sq]-1][sq]; !C } !C } !C hash ^= WTM; !C } [ mscp_compute_hash sq z wtm; #Ifdef MSCP_DEBUG; print "[MSCP> compute_hash]^"; #Endif; mscp_hash = 0; for (sq = 0: sq < 64: sq++) { if (mscp_board->sq ~= MSCP_C_EMPTY) { z = mscp_zobrist-->((mscp_board->sq - 1) * 64 + sq); mscp_hash = (mscp_hash | z) & ~(mscp_hash & z); } } wtm = MSCP_WTM (); mscp_hash = (mscp_hash | wtm) & ~(mscp_hash & wtm); ]; !C /*----------------------------------------------------------------------+ !C | attack tables | !C +----------------------------------------------------------------------*/ !C static void atk_slide(int sq, byte dirs, struct side *s) !C { !C byte dir = 0; !C int to; !C dirs &= king_dirs[sq]; !C do { !C dir -= dirs; !C dir &= dirs; !C to = sq; !C do { !C to += logtab[LOG_STEP+dir]; !C s->attack[to] += 1; !C if (board[to] != EMPTY) break; !C } while (dir & king_dirs[to]); !C } while (dirs -= dir); !C } [ mscp_atk_slide sq dirs side_attack dir _to; #Ifdef MSCP_DEBUG; print "[MSCP> atk_slide ", sq, ", ", dirs, ", ", side_attack, "]^"; #Endif; dir = 0; dirs = dirs & mscp_king_dirs->sq; do { dir = dir - dirs; dir = dir & dirs; _to = sq; do { _to = _to + mscp_logtab-->(MSCP_C_LOG_STEP + dir); side_attack->_to = side_attack->_to + 1; if (mscp_board->_to ~= MSCP_C_EMPTY) break; } until (~~(dir & mscp_king_dirs->_to)); dirs = dirs - dir; } until (dirs == 0); ]; !C static void compute_attacks (void) !C { !C int sq, to, pc; !C byte dir, dirs; !C memset(&white, 0, sizeof(white)); !C memset(&black, 0, sizeof(black)); !C if ((hash = WTM)) { !C friend = &white; !C enemy = &black; !C } else { !C friend = &black; !C enemy = &white; !C } !C for (sq=0; sq<64; sq++) { !C pc = board[sq]; !C if (pc == EMPTY) { !C continue; !C } !C hash ^= zobrist[pc-1][sq]; !C switch (pc) { !C case WHITE_KING: !C { !C byte dir = 0, dirs; !C white.king = sq; !C dirs = king_dirs[sq]; !C do { !C dir -= dirs; !C dir &= dirs; !C to = sq + logtab[LOG_STEP+dir]; !C white.attack[to] += 1; !C } while (dirs -= dir); !C break; !C } !C case BLACK_KING: !C { !C byte dir = 0, dirs; !C black.king = sq; !C dirs = king_dirs[sq]; !C do { !C dir -= dirs; !C dir &= dirs; !C to = sq + logtab[LOG_STEP+dir]; !C black.attack[to] += 1; !C } while (dirs -= dir); !C break; !C } !C case WHITE_QUEEN: !C atk_slide(sq, ATK_SLIDER, &white); !C break; !C case BLACK_QUEEN: !C atk_slide(sq, ATK_SLIDER, &black); !C break; !C case WHITE_ROOK: !C atk_slide(sq, ATK_ORTHOGONAL, &white); !C break; !C case BLACK_ROOK: !C atk_slide(sq, ATK_ORTHOGONAL, &black); !C break; !C case WHITE_BISHOP: !C atk_slide(sq, ATK_DIAGONAL, &white); !C break; !C case BLACK_BISHOP: !C atk_slide(sq, ATK_DIAGONAL, &black); !C break; !C case WHITE_KNIGHT: !C dir = 0; !C dirs = knight_dirs[sq]; !C do { !C dir -= dirs; !C dir &= dirs; !C to = sq + logtab[LOG_JUMP+dir]; !C white.attack[to] += 1; !C } while (dirs -= dir); !C break; !C case BLACK_KNIGHT: !C dir = 0; !C dirs = knight_dirs[sq]; !C do { !C dir -= dirs; !C dir &= dirs; !C to = sq + logtab[LOG_JUMP+dir]; !C black.attack[to] += 1; !C } while (dirs -= dir); !C break; !C case WHITE_PAWN: !C white.pawns[1+F(sq)] += 1; !C if (F(sq) != FILE_H) { !C white.attack[sq + DIR_N + DIR_E] += 1; !C } !C if (F(sq) != FILE_A) { !C white.attack[sq + DIR_N - DIR_E] += 1; !C } !C break; !C case BLACK_PAWN: !C black.pawns[1+F(sq)] += 1; !C if (F(sq) != FILE_H) { !C black.attack[sq - DIR_N + DIR_E] += 1; !C } !C if (F(sq) != FILE_A) { !C black.attack[sq - DIR_N - DIR_E] += 1; !C } !C break; !C } !C } !C } [ mscp_compute_attacks sq _to pc dir dirs i z wtm file; #Ifdef MSCP_DEBUG; print "[MSCP> compute_attacks]^"; #Endif; for (i = 0: i < 64: i++) { mscp_white_attack->i = 0; mscp_black_attack->i = 0; } mscp_white_king = 0; mscp_black_king = 0; for (i = 0: i < 10: i++) { mscp_white_pawns->i = 0; mscp_black_pawns->i = 0; } mscp_hash = MSCP_WTM (); if (mscp_hash) { mscp_friend_attack = mscp_white_attack; mscp_friend_pawns = mscp_white_pawns; mscp_enemy_attack = mscp_black_attack; mscp_enemy_pawns = mscp_black_pawns; wtm = true; ! Inform note - used later } else { mscp_friend_attack = mscp_black_attack; mscp_friend_pawns = mscp_black_pawns; mscp_enemy_attack = mscp_white_attack; mscp_enemy_pawns = mscp_white_pawns; wtm = false; ! Inform note - used later } mscp_enemy_king = 0; mscp_friend_king = 0; for (sq = 0: sq < 64: sq++) { pc = mscp_board->sq; if (pc == MSCP_C_EMPTY) { continue; } z = mscp_zobrist-->((pc - 1) * 64 + sq); mscp_hash = (mscp_hash | z) & ~(mscp_hash & z); switch (pc) { MSCP_C_WHITE_KING: dir = 0; mscp_white_king = sq; if (wtm) mscp_friend_king = sq; ! Inform note - else mscp_enemy_king = sq; ! set kings dirs = mscp_king_dirs->sq; do { dir = dir - dirs; dir = dir & dirs; _to = sq + mscp_logtab--> (MSCP_C_LOG_STEP + dir); mscp_white_attack->_to = mscp_white_attack->_to + 1; dirs = dirs - dir; } until (dirs == 0); MSCP_C_BLACK_KING: dir = 0; mscp_black_king = sq; if (~~wtm) mscp_friend_king = sq; ! Inform note - else mscp_enemy_king = sq; ! set kings dirs = mscp_king_dirs->sq; do { dir = dir - dirs; dir = dir & dirs; _to = sq + mscp_logtab--> (MSCP_C_LOG_STEP + dir); mscp_black_attack->_to = mscp_black_attack->_to + 1; dirs = dirs - dir; } until (dirs == 0); MSCP_C_WHITE_QUEEN: mscp_atk_slide (sq, MSCP_C_ATK_SLIDER, mscp_white_attack); MSCP_C_BLACK_QUEEN: mscp_atk_slide (sq, MSCP_C_ATK_SLIDER, mscp_black_attack); MSCP_C_WHITE_ROOK: mscp_atk_slide (sq, MSCP_C_ATK_ORTHOGONAL, mscp_white_attack); MSCP_C_BLACK_ROOK: mscp_atk_slide (sq, MSCP_C_ATK_ORTHOGONAL, mscp_black_attack); MSCP_C_WHITE_BISHOP: mscp_atk_slide (sq, MSCP_C_ATK_DIAGONAL, mscp_white_attack); MSCP_C_BLACK_BISHOP: mscp_atk_slide (sq, MSCP_C_ATK_DIAGONAL, mscp_black_attack); MSCP_C_WHITE_KNIGHT: dir = 0; dirs = mscp_knight_dirs->sq; do { dir = dir - dirs; dir = dir & dirs; _to = sq + mscp_logtab--> (MSCP_C_LOG_JUMP + dir); mscp_white_attack->_to = mscp_white_attack->_to + 1; dirs = dirs - dir; } until (dirs == 0); MSCP_C_BLACK_KNIGHT: dir = 0; dirs = mscp_knight_dirs->sq; do { dir = dir - dirs; dir = dir & dirs; _to = sq + mscp_logtab--> (MSCP_C_LOG_JUMP + dir); mscp_black_attack->_to = mscp_black_attack->_to + 1; dirs = dirs - dir; } until (dirs == 0); MSCP_C_WHITE_PAWN: file = MSCP_F (sq); i = 1 + file; mscp_white_pawns->i = mscp_white_pawns->i + 1; if (file ~= MSCP_C_FILE_H) { i = sq + MSCP_C_DIR_N + MSCP_C_DIR_E; mscp_white_attack->i = mscp_white_attack->i + 1; } if (file ~= MSCP_C_FILE_A) { i = sq + MSCP_C_DIR_N - MSCP_C_DIR_E; mscp_white_attack->i = mscp_white_attack->i + 1; } MSCP_C_BLACK_PAWN: file = MSCP_F (sq); i = 1 + file; mscp_black_pawns->i = mscp_black_pawns->i + 1; if (file ~= MSCP_C_FILE_H) { i = sq - MSCP_C_DIR_N + MSCP_C_DIR_E; mscp_black_attack->i = mscp_black_attack->i + 1; } if (file ~= MSCP_C_FILE_A) { i = sq - MSCP_C_DIR_N - MSCP_C_DIR_E; mscp_black_attack->i = mscp_black_attack->i + 1; } } } ]; !C /*----------------------------------------------------------------------+ !C | make/unmake move | !C +----------------------------------------------------------------------*/ !C static void make_move(int move) !C { !C int fr; !C int to; !C int sq; !C *undo_sp++ = -1; /* sentinel */ !C if (board[EP]) { /* whipe ep info */ !C *undo_sp++ = board[EP]; !C *undo_sp++ = EP; !C board[EP] = 0; !C } !C to = TO(move); !C fr = FR(move); !C if (move & SPECIAL) { /* first deal with specials */ !C switch (R(fr)) { !C case RANK_8: /* black castles */ !C undo_sp--; !C ply--; !C if (to == G8) { !C make_move(MOVE(H8,F8)); !C } else { !C make_move(MOVE(A8,D8)); !C } !C break; !C case RANK_7: /* toggle ep flag */ !C if (board[fr] == BLACK_PAWN) { !C *undo_sp++ = 0; !C *undo_sp++ = EP; !C board[EP] = to; !C } else { /* white promotes */ !C *undo_sp++ = board[fr]; !C *undo_sp++ = fr; !C board[fr] = WHITE_QUEEN + (move>>13); !C } !C break; !C case RANK_5: /* white captures ep */ !C case RANK_4: /* black captures ep */ !C sq = SQ(F(to),R(fr)); !C *undo_sp++ = board[sq]; !C *undo_sp++ = sq; !C board[sq] = EMPTY; !C break; !C case RANK_2: /* toggle ep flag */ !C if (board[fr] == WHITE_PAWN) { !C *undo_sp++ = 0; !C *undo_sp++ = EP; !C board[EP] = to; !C } else { /* black promotes */ !C *undo_sp++ = board[fr]; !C *undo_sp++ = fr; !C board[fr] = BLACK_QUEEN + (move>>13); !C } !C break; !C case RANK_1: /* white castles */ !C undo_sp--; !C ply--; !C if (to == G1) { !C make_move(MOVE(H1,F1)); !C } else { !C make_move(MOVE(A1,D1)); !C } !C break; !C default: !C break; !C } !C } !C *undo_sp++ = board[to]; !C *undo_sp++ = to; !C *undo_sp++ = board[fr]; !C *undo_sp++ = fr; !C board[to] = board[fr]; !C board[fr] = EMPTY; !C if (board[CASTLE] & (castle[fr] | castle[to])) { !C *undo_sp++ = board[CASTLE]; !C *undo_sp++ = CASTLE; !C board[CASTLE] &= ~(castle[fr] | castle[to]); !C } !C ply++; !C } [ mscp_make_move _move fr _to sq; #Ifdef MSCP_DEBUG; print "[MSCP> make_move ", _move, "]^"; #Endif; mscp_undo_stack-->(mscp_undo_sp++) = -1;! sentinel if (mscp_board->MSCP_C_EP) { ! wipe ep info mscp_undo_stack-->(mscp_undo_sp++) = mscp_board->MSCP_C_EP; mscp_undo_stack-->(mscp_undo_sp++) = MSCP_C_EP; mscp_board->MSCP_C_EP = 0; } _to = MSCP_TO (_move); fr = MSCP_FR (_move); if (_move & MSCP_C_SPECIAL) { ! first deal with specials switch (MSCP_R (fr)) { MSCP_C_RANK_8: ! black castles mscp_unmake_move (); ! Inform note -- MSCP 2.0-like ! bug fix if (_to == MSCP_C_G8) { mscp_make_move (MSCP_MOVE (MSCP_C_H8, MSCP_C_F8)); } else { mscp_make_move (MSCP_MOVE (MSCP_C_A8, MSCP_C_D8)); } MSCP_C_RANK_7: ! toggle ep flag if (mscp_board->fr == MSCP_C_BLACK_PAWN) { mscp_undo_stack-->(mscp_undo_sp++) = 0; mscp_undo_stack-->(mscp_undo_sp++) = MSCP_C_EP; mscp_board->MSCP_C_EP = _to; } else { ! white promotes mscp_undo_stack-->(mscp_undo_sp++) = mscp_board->fr; mscp_undo_stack-->(mscp_undo_sp++) = fr; mscp_board->fr = MSCP_C_WHITE_QUEEN + (_move / 8192); } MSCP_C_RANK_5, ! white captures ep MSCP_C_RANK_4: ! black captures ep sq = MSCP_SQ (MSCP_F (_to), MSCP_R (fr)); mscp_undo_stack-->(mscp_undo_sp++) = mscp_board->sq; mscp_undo_stack-->(mscp_undo_sp++) = sq; mscp_board->sq = MSCP_C_EMPTY; MSCP_C_RANK_2: ! toggle ep flag if (mscp_board->fr == MSCP_C_WHITE_PAWN) { mscp_undo_stack-->(mscp_undo_sp++) = 0; mscp_undo_stack-->(mscp_undo_sp++) = MSCP_C_EP; mscp_board->MSCP_C_EP = _to; } else { ! black promotes mscp_undo_stack-->(mscp_undo_sp++) = mscp_board->fr; mscp_undo_stack-->(mscp_undo_sp++) = fr; mscp_board->fr = MSCP_C_BLACK_QUEEN + (_move / 8192); } MSCP_C_RANK_1: ! white castles mscp_unmake_move (); ! Inform note -- MSCP 2.0-like ! bug fix if (_to == MSCP_C_G1) { mscp_make_move (MSCP_MOVE (MSCP_C_H1, MSCP_C_F1)); } else { mscp_make_move (MSCP_MOVE (MSCP_C_A1, MSCP_C_D1)); } } } mscp_undo_stack-->(mscp_undo_sp++) = mscp_board->_to; mscp_undo_stack-->(mscp_undo_sp++) = _to; mscp_undo_stack-->(mscp_undo_sp++) = mscp_board->fr; mscp_undo_stack-->(mscp_undo_sp++) = fr; mscp_board->_to = mscp_board->fr; mscp_board->fr = MSCP_C_EMPTY; if (mscp_board->MSCP_C_CASTLE & (mscp_castle->fr | mscp_castle->_to)) { mscp_undo_stack-->(mscp_undo_sp++) = mscp_board->MSCP_C_CASTLE; mscp_undo_stack-->(mscp_undo_sp++) = MSCP_C_CASTLE; mscp_board->MSCP_C_CASTLE = mscp_board->MSCP_C_CASTLE & ~(mscp_castle->fr | mscp_castle->_to); } mscp_ply++; ]; !C static void unmake_move(void) !C { !C int sq; !C for (;;) { !C sq = *--undo_sp; !C if (sq < 0) break; /* sentinel */ !C board[sq] = *--undo_sp; !C } !C ply--; !C } [ mscp_unmake_move sq; #Ifdef MSCP_DEBUG; print "[MSCP> unmake_move]^"; #Endif; while (true) { sq = mscp_undo_stack-->(--mscp_undo_sp); if (sq < 0) break; ! sentinel mscp_board->sq = mscp_undo_stack-->(--mscp_undo_sp); } mscp_ply--; ]; !C /*----------------------------------------------------------------------+ !C | move generator | !C +----------------------------------------------------------------------*/ !C static unsigned short caps; /* @@@ */ Global mscp_caps = 0; !C static int push_move(int fr, int to) !C { !C unsigned short prescore = PRESCORE_EQUAL; !C int move; !C /* !C * what do we capture !C */ !C if (board[to] != EMPTY) { !C prescore += (1<<9) + prescore_piece_value[board[to]]; !C } !C /* !C * is to-square safe? !C */ !C if (WTM) { !C if (black.attack[to] != 0) { /* defended */ !C prescore -= prescore_piece_value[board[fr]]; !C } !C } else { !C if (white.attack[to] != 0) { /* defended */ !C prescore -= prescore_piece_value[board[fr]]; !C } !C } !C if (prescore >= caps) { !C move = MOVE(fr, to); !C move_sp->move = move; !C move_sp->prescore = prescore | history[move]; !C move_sp++; !C return 1; !C } !C return 0; !C } [ mscp_push_move fr _to prescore _move; #Ifdef MSCP_DEBUG; print "[MSCP> push_move ", fr, ", ", _to, "]^"; #Endif; prescore = MSCP_C_PRESCORE_EQUAL; ! ! what do we capture ! if (mscp_board->_to ~= MSCP_C_EMPTY) { prescore = prescore + 512 + mscp_prescore_piece_value-->(mscp_board->_to); } ! ! is to-square safe? ! if (MSCP_WTM ()) { if (mscp_black_attack->_to ~= 0) { ! defended prescore = prescore - mscp_prescore_piece_value-->(mscp_board->fr); } } else { if (mscp_white_attack->_to ~= 0) { ! defended prescore = prescore - mscp_prescore_piece_value-->(mscp_board->fr); } } if (prescore >= mscp_caps) { _move = MSCP_MOVE (fr, _to); mscp_move_stack_move-->mscp_move_sp = _move; mscp_move_stack_prescore-->mscp_move_sp = prescore | mscp_history-->_move; mscp_move_sp++; return 1; } return 0; ]; !C static void push_special_move(int fr, int to) !C { !C int move; !C move = MOVE(fr, to); !C move_sp->prescore = PRESCORE_EQUAL | history[move]; !C move_sp->move = move | SPECIAL; !C move_sp++; !C } [ mscp_push_special_move fr _to _move; #Ifdef MSCP_DEBUG; print "[MSCP> push_special_move ", fr, ", ", _to, "]^"; #Endif; _move = MSCP_MOVE (fr, _to); mscp_move_stack_prescore-->mscp_move_sp = MSCP_C_PRESCORE_EQUAL | mscp_history-->_move; mscp_move_stack_move-->mscp_move_sp = _move | MSCP_C_SPECIAL; mscp_move_sp++; ]; !C static void push_pawn_move(int fr, int to) !C { !C if ((R(to) == RANK_8) || (R(to) == RANK_1)) { !C push_special_move(fr, to); /* queen promotion */ !C push_special_move(fr, to); /* rook promotion */ !C move_sp[-1].move += 1<<13; !C push_special_move(fr, to); /* bishop promotion */ !C move_sp[-1].move += 2<<13; !C push_special_move(fr, to); /* knight promotion */ !C move_sp[-1].move += 3<<13; !C } else { !C push_move(fr, to); !C } !C } [ mscp_push_pawn_move fr _to; #Ifdef MSCP_DEBUG; print "[MSCP> push_pawn_move ", fr, ", ", _to, "]^"; #Endif; if ((MSCP_R (_to) == MSCP_C_RANK_8) || (MSCP_R (_to) == MSCP_C_RANK_1)) { mscp_push_special_move (fr, _to); ! queen promotion mscp_push_special_move (fr, _to); ! rook promotion mscp_move_stack_move-->(mscp_move_sp - 1) = mscp_move_stack_move-->(mscp_move_sp - 1) + $2000; mscp_push_special_move (fr, _to); ! bishop promotion mscp_move_stack_move-->(mscp_move_sp - 1) = mscp_move_stack_move-->(mscp_move_sp - 1) + $4000; mscp_push_special_move (fr, _to); ! knight promotion mscp_move_stack_move-->(mscp_move_sp - 1) = mscp_move_stack_move-->(mscp_move_sp - 1) + $6000; } else { mscp_push_move (fr, _to); } ]; !C static void gen_slides(int fr, byte dirs) !C { !C int vector; !C int to; !C byte dir = 0; !C !C dirs &= king_dirs[fr]; !C do { !C dir -= dirs; !C dir &= dirs; !C vector = logtab[LOG_STEP+dir]; !C to = fr; !C do { !C to += vector; !C if (board[to] != EMPTY) { !C if (PIECE_COLOR(board[to]) != WTM) { !C push_move(fr, to); !C } !C break; !C } !C push_move(fr, to); !C } while (dir & king_dirs[to]); !C } while (dirs -= dir); !C } [ mscp_gen_slides fr dirs vector _to dir wtm; #Ifdef MSCP_DEBUG; print "[MSCP> gen_slides ", fr, ", ", dirs, "]^"; #Endif; wtm = MSCP_WTM (); dirs = dirs & mscp_king_dirs->fr; do { dir = dir - dirs; dir = dir & dirs; vector = mscp_logtab-->(MSCP_C_LOG_STEP + dir); _to = fr; do { _to = _to + vector; if (mscp_board->_to ~= MSCP_C_EMPTY) { if (MSCP_PIECE_COLOR (mscp_board->_to) ~= wtm) { mscp_push_move (fr, _to); } break; } mscp_push_move (fr, _to); } until (~~(dir & mscp_king_dirs->_to)); dirs = dirs - dir; } until (dirs == 0); ]; !C static int compare_move(const void *ap, const void *bp) !C { !C const struct move *a = ap; !C const struct move *b = bp; !C if (a->prescore < b->prescore) return -1; !C if (a->prescore > b->prescore) return 1; !C return a->move - b->move; /* this makes qsort deterministic */ !C } !C static int test_illegal(int move) !C { !C make_move(move); !C compute_attacks(); !C unmake_move(); !C return friend->attack[enemy->king] != 0; !C } [ mscp_test_illegal _move; #Ifdef MSCP_DEBUG; print "[MSCP> test_illegal ", _move, "]^"; #Endif; mscp_make_move (_move); mscp_compute_attacks (); mscp_unmake_move (); return (mscp_friend_attack->mscp_enemy_king ~= 0); ]; !C static void generate_moves(unsigned treshold) !C { !C int fr, to; !C int pc; !C byte dir, dirs; !C caps = treshold; !C for (fr=0; fr<64; fr++) { !C pc = board[fr]; !C if (!pc || PIECE_COLOR(pc) != WTM) { !C continue; !C } !C /* !C * generate moves for this piece !C */ !C switch (pc) { !C case WHITE_KING: !C case BLACK_KING: !C dir = 0; !C dirs = king_dirs[fr]; !C do { !C dir -= dirs; !C dir &= dirs; !C to = fr+logtab[LOG_STEP+dir]; !C if (board[to] != EMPTY !C && PIECE_COLOR(board[to]) == WTM) { !C continue; !C } !C push_move(fr, to); !C } while (dirs -= dir); !C break; !C case WHITE_QUEEN: !C case BLACK_QUEEN: !C gen_slides (fr, ATK_SLIDER); !C break; !C case WHITE_ROOK: !C case BLACK_ROOK: !C gen_slides (fr, ATK_ORTHOGONAL); !C break; !C case WHITE_BISHOP: !C case BLACK_BISHOP: !C gen_slides (fr, ATK_DIAGONAL); !C break; !C case WHITE_KNIGHT: !C case BLACK_KNIGHT: !C dir = 0; !C dirs = knight_dirs[fr]; !C do { !C dir -= dirs; !C dir &= dirs; !C to = fr+logtab[LOG_JUMP+dir]; !C if (board[to] != EMPTY !C && PIECE_COLOR(board[to]) == WTM) { !C continue; !C } !C push_move(fr, to); !C } while (dirs -= dir); !C break; !C case WHITE_PAWN: !C if (F(fr) != FILE_H) { !C to = fr + DIR_N + DIR_E; !C if (board[to] >= BLACK_KING) { !C push_pawn_move(fr, to); !C } !C } !C if (F(fr) != FILE_A) { !C to = fr + DIR_N - DIR_E; !C if (board[to] >= BLACK_KING) { !C push_pawn_move(fr, to); !C } !C } !C to = fr + DIR_N; !C if (board[to] != EMPTY) { !C break; !C } !C push_pawn_move(fr, to); !C if (R(fr) == RANK_2) { !C to += DIR_N; !C if (board[to] == EMPTY) { !C if (push_move(fr, to)) !C if (black.attack[to-DIR_N]) { !C move_sp[-1].move |= SPECIAL; !C } !C } !C } !C break; !C case BLACK_PAWN: !C if (F(fr) != FILE_H) { !C to = fr - DIR_N + DIR_E; !C if (board[to] && board[to] < BLACK_KING) { !C push_pawn_move(fr, to); !C } !C } !C if (F(fr) != FILE_A) { !C to = fr - DIR_N - DIR_E; !C if (board[to] && board[to] < BLACK_KING) { !C push_pawn_move(fr, to); !C } !C } !C to = fr - DIR_N; !C if (board[to] != EMPTY) { !C break; !C } !C push_pawn_move(fr, to); !C if (R(fr) == RANK_7) { !C to -= DIR_N; !C if (board[to] == EMPTY) { !C if (push_move(fr, to)) !C if (white.attack[to+DIR_N]) { !C move_sp[-1].move |= SPECIAL; !C } !C } !C } !C break; !C } !C } !C /* !C * generate castling moves !C */ !C if (board[CASTLE] && !enemy->attack[friend->king]) { !C if ((board[CASTLE] & CASTLE_WHITE_KING) && !C !board[F1] && !board[G1] && !C !enemy->attack[F1]) !C { !C push_special_move(E1, G1); !C } !C if ((board[CASTLE] & CASTLE_WHITE_QUEEN) && !C !board[D1] && !board[C1] && !board[B1] && !C !enemy->attack[D1]) !C { !C push_special_move(E1, C1); !C } !C if ((board[CASTLE] & CASTLE_BLACK_KING) && !C !board[F8] && !board[G8] && !C !enemy->attack[F8]) !C { !C push_special_move(E8, G8); !C } !C if ((board[CASTLE] & CASTLE_BLACK_QUEEN) && !C !board[D8] && !board[C8] && !board[B8] && !C !enemy->attack[D8]) !C { !C push_special_move(E8, C8); !C } !C } !C /* !C * generate en-passant captures !C */ !C if (board[EP]) { !C int ep = board[EP]; !C if (WTM) { !C if (F(ep) != FILE_A && board[ep-DIR_E] == WHITE_PAWN) { !C if (push_move(ep-DIR_E, ep+DIR_N)) !C move_sp[-1].move |= SPECIAL; !C } !C if (F(ep) != FILE_H && board[ep+DIR_E] == WHITE_PAWN) { !C if (push_move(ep+DIR_E, ep+DIR_N)) !C move_sp[-1].move |= SPECIAL; !C } !C } else { !C if (F(ep) != FILE_A && board[ep-DIR_E] == BLACK_PAWN) { !C if (push_move(ep-DIR_E, ep-DIR_N)) !C move_sp[-1].move |= SPECIAL; !C } !C if (F(ep) != FILE_H && board[ep+DIR_E] == BLACK_PAWN) { !C if (push_move(ep+DIR_E, ep-DIR_N)) !C move_sp[-1].move |= SPECIAL; !C } !C } !C } !C } [ mscp_generate_moves threshold fr _to pc dir dirs ep i wtm file castle; #Ifdef MSCP_DEBUG; print "[MSCP> generate_moves ", threshold, "]^"; #Endif; mscp_caps = threshold; wtm = MSCP_WTM (); for (fr = 0: fr < 64: fr++) { pc = mscp_board->fr; if (pc == 0 || MSCP_PIECE_COLOR (pc) ~= wtm) { continue; } ! ! generate moves for this piece ! switch (pc) { MSCP_C_WHITE_KING, MSCP_C_BLACK_KING: dir = 0; dirs = mscp_king_dirs->fr; do { dir = dir - dirs; dir = dir & dirs; _to = fr +mscp_logtab-->(MSCP_C_LOG_STEP + dir); if (mscp_board->_to ~= MSCP_C_EMPTY && MSCP_PIECE_COLOR (mscp_board->_to) == wtm) { dirs = dirs - dir; continue; } mscp_push_move (fr, _to); dirs = dirs - dir; } until (dirs == 0); MSCP_C_WHITE_QUEEN, MSCP_C_BLACK_QUEEN: mscp_gen_slides (fr, MSCP_C_ATK_SLIDER); MSCP_C_WHITE_ROOK, MSCP_C_BLACK_ROOK: mscp_gen_slides (fr, MSCP_C_ATK_ORTHOGONAL); MSCP_C_WHITE_BISHOP, MSCP_C_BLACK_BISHOP: mscp_gen_slides (fr, MSCP_C_ATK_DIAGONAL); MSCP_C_WHITE_KNIGHT, MSCP_C_BLACK_KNIGHT: dir = 0; dirs = mscp_knight_dirs->fr; do { dir = dir - dirs; dir = dir & dirs; _to = fr +mscp_logtab-->(MSCP_C_LOG_JUMP + dir); if (mscp_board->_to ~= MSCP_C_EMPTY && MSCP_PIECE_COLOR (mscp_board->_to) == wtm) { dirs = dirs - dir; continue; } mscp_push_move (fr, _to); dirs = dirs - dir; } until (dirs == 0); MSCP_C_WHITE_PAWN: file = MSCP_F (fr); if (file ~= MSCP_C_FILE_H) { _to = fr + MSCP_C_DIR_N + MSCP_C_DIR_E; if (mscp_board->_to >= MSCP_C_BLACK_KING) { mscp_push_pawn_move (fr, _to); } } if (file ~= MSCP_C_FILE_A) { _to = fr + MSCP_C_DIR_N - MSCP_C_DIR_E; if (mscp_board->_to >= MSCP_C_BLACK_KING) { mscp_push_pawn_move (fr, _to); } } _to = fr + MSCP_C_DIR_N; if (mscp_board->_to ~= MSCP_C_EMPTY) { break; } mscp_push_pawn_move (fr, _to); if (MSCP_R (fr) == MSCP_C_RANK_2) { _to = _to + MSCP_C_DIR_N; if (mscp_board->_to == MSCP_C_EMPTY) { if (mscp_push_move (fr, _to)) { if (mscp_black_attack-> (_to - MSCP_C_DIR_N)) { i = mscp_move_sp - 1; mscp_move_stack_move-->i = mscp_move_stack_move-->i | MSCP_C_SPECIAL; } } } } MSCP_C_BLACK_PAWN: file = MSCP_F (fr); if (file ~= MSCP_C_FILE_H) { _to = fr - MSCP_C_DIR_N + MSCP_C_DIR_E; if (mscp_board->_to && mscp_board->_to < MSCP_C_BLACK_KING) { mscp_push_pawn_move (fr, _to); } } if (file ~= MSCP_C_FILE_A) { _to = fr - MSCP_C_DIR_N - MSCP_C_DIR_E; if (mscp_board->_to && mscp_board->_to < MSCP_C_BLACK_KING) { mscp_push_pawn_move (fr, _to); } } _to = fr - MSCP_C_DIR_N; if (mscp_board->_to ~= MSCP_C_EMPTY) { break; } mscp_push_pawn_move (fr, _to); if (MSCP_R (fr) == MSCP_C_RANK_7) { _to = _to - MSCP_C_DIR_N; if (mscp_board->_to == MSCP_C_EMPTY) { if (mscp_push_move (fr, _to)) { if (mscp_white_attack-> (_to + MSCP_C_DIR_N)) { i = mscp_move_sp - 1; mscp_move_stack_move-->i = mscp_move_stack_move-->i | MSCP_C_SPECIAL; } } } } } } ! ! generate castling moves ! castle = mscp_board->MSCP_C_CASTLE; if (castle && (~~(mscp_enemy_attack->mscp_friend_king))) { if ((castle & MSCP_C_CASTLE_WHITE_KING) && (~~(mscp_board->MSCP_C_F1)) && (~~(mscp_board->MSCP_C_G1)) && (~~(mscp_enemy_attack->MSCP_C_F1))) { mscp_push_special_move (MSCP_C_E1, MSCP_C_G1); } if ((castle & MSCP_C_CASTLE_WHITE_QUEEN) && (~~(mscp_board->MSCP_C_D1)) && (~~(mscp_board->MSCP_C_C1)) && (~~(mscp_board->MSCP_C_B1)) && (~~(mscp_enemy_attack->MSCP_C_D1))) { mscp_push_special_move (MSCP_C_E1, MSCP_C_C1); } if ((castle & MSCP_C_CASTLE_BLACK_KING) && (~~(mscp_board->MSCP_C_F8)) && (~~(mscp_board->MSCP_C_G8)) && (~~(mscp_enemy_attack->MSCP_C_F8))) { mscp_push_special_move (MSCP_C_E8, MSCP_C_G8); } if ((castle & MSCP_C_CASTLE_BLACK_QUEEN) && (~~(mscp_board->MSCP_C_D8)) && (~~(mscp_board->MSCP_C_C8)) && (~~(mscp_board->MSCP_C_B8)) && (~~(mscp_enemy_attack->MSCP_C_D8))) { mscp_push_special_move (MSCP_C_E8, MSCP_C_C8); } } ! ! generate en-passant captures ! if (mscp_board->MSCP_C_EP) { ep = mscp_board->MSCP_C_EP; if (wtm) { file = MSCP_F (ep); if (file ~= MSCP_C_FILE_A && mscp_board->(ep - MSCP_C_DIR_E) == MSCP_C_WHITE_PAWN) { if (mscp_push_move (ep - MSCP_C_DIR_E, ep + MSCP_C_DIR_N)) { i = mscp_move_sp - 1; mscp_move_stack_move-->i = mscp_move_stack_move-->i | MSCP_C_SPECIAL; } } if (file ~= MSCP_C_FILE_H && mscp_board->(ep + MSCP_C_DIR_E) == MSCP_C_WHITE_PAWN) { if (mscp_push_move (ep + MSCP_C_DIR_E, ep + MSCP_C_DIR_N)) { i = mscp_move_sp - 1; mscp_move_stack_move-->i = mscp_move_stack_move-->i | MSCP_C_SPECIAL; } } } else { file = MSCP_F (ep); if (file ~= MSCP_C_FILE_A && mscp_board->(ep - MSCP_C_DIR_E) == MSCP_C_BLACK_PAWN) { if (mscp_push_move (ep - MSCP_C_DIR_E, ep - MSCP_C_DIR_N)) { i = mscp_move_sp - 1; mscp_move_stack_move-->i = mscp_move_stack_move-->i | MSCP_C_SPECIAL; } } if (file ~= MSCP_C_FILE_H && mscp_board->(ep + MSCP_C_DIR_E) == MSCP_C_BLACK_PAWN) { if (mscp_push_move (ep + MSCP_C_DIR_E, ep - MSCP_C_DIR_N)) { i = mscp_move_sp - 1; mscp_move_stack_move-->i = mscp_move_stack_move-->i | MSCP_C_SPECIAL; } } } } ]; !C static void print_move_san(int move) !C { !C int fr, to; !C int filex = 0, rankx = 0; !C struct move *moves; !C fr = FR(move); !C to = TO(move); !C if ((move==(MOVE(E1,C1)|SPECIAL)) || (move==(MOVE(E8,C8)|SPECIAL))) { !C fputs("O-O-O", stdout); !C goto check; !C } !C if ((move==(MOVE(E1,G1)|SPECIAL)) || (move==(MOVE(E8,G8)|SPECIAL))) { !C fputs("O-O", stdout); !C goto check; !C } !C if ((board[fr]==WHITE_PAWN) || (board[fr] == BLACK_PAWN)) { !C /* !C * pawn moves are a bit special !C */ !C if (F(fr) != F(to)) { !C printf("%cx", FILE2CHAR(F(fr))); !C } !C print_square (to); !C /* !C * promote to piece (=Q, =R, =B, =N) !C */ !C if (move > 4095 !C && (R(to)==RANK_1 || R(to)==RANK_8)) { !C putchar('='); !C putchar("QRBN"[move>>13]); !C } !C goto check; !C } !C /* !C * piece identifier (K, Q, R, B, N) !C */ !C putchar(toupper(PIECE2CHAR(board[fr]))); !C /* !C * disambiguate: consider moves of identical pieces to the same square !C */ !C moves = move_sp; !C generate_moves(0); !C while (move_sp > moves) { !C move_sp --; !C if (to != TO(move_sp->move) /* same destination */ !C || move == move_sp->move /* different move */ !C || board[fr] != board[FR(move_sp->move)] /* same piece */ !C || test_illegal(move_sp->move)) { !C continue; !C } !C rankx |= (R(fr) == R(FR(move_sp->move))) + 1; !C filex |= F(fr) == F(FR(move_sp->move)); !C } !C if (rankx != filex) putchar(FILE2CHAR(F(fr))); !C if (filex) putchar(RANK2CHAR(R(fr))); !C /* !C * capture sign !C */ !C if (board[to] != EMPTY) putchar('x'); !C /* !C * to-square !C */ !C print_square(to); !C /* !C * check ('+') or checkmate ('#') !C */ !C check: !C make_move(move); !C compute_attacks(); !C if (enemy->attack[friend->king]) { /* in check, is mate? */ !C int sign = '#'; !C moves = move_sp; !C generate_moves(0); !C while (move_sp > moves) { !C move_sp --; !C if (!test_illegal(move_sp->move)) { !C sign = '+'; !C move_sp = moves; /* break */ !C } !C } !C putchar(sign); !C } !C unmake_move(); !C } [ mscp_buffer_char_san c buf cp; cp = buf->0 + 1; buf->cp = c; buf->0 = cp; ]; [ mscp_buffer_move_san_check _move buf moves sign; ! ! check ('+') or checkmate ('#') ! mscp_make_move (_move); mscp_compute_attacks (); if (mscp_enemy_attack->mscp_friend_king) { ! in check, is mate? sign = '#'; moves = mscp_move_sp; mscp_generate_moves (0); while (mscp_move_sp > moves) { mscp_move_sp--; if (~~(mscp_test_illegal (mscp_move_stack_move-->mscp_move_sp))) { sign = '+'; mscp_move_sp = moves; ! break } } mscp_buffer_char_san (sign, buf); } mscp_unmake_move (); ]; [ mscp_buffer_move_san _move buf fr _to filex rankx moves; buf->0 = 0; filex = 0; rankx = 0; fr = MSCP_FR (_move); _to = MSCP_TO (_move); if ((_move == (MSCP_MOVE (MSCP_C_E1, MSCP_C_C1) | MSCP_C_SPECIAL)) || (_move == (MSCP_MOVE (MSCP_C_E8, MSCP_C_C8) | MSCP_C_SPECIAL))) { mscp_buffer_char_san ('O', buf);mscp_buffer_char_san ('-', buf); mscp_buffer_char_san ('O', buf);mscp_buffer_char_san ('-', buf); mscp_buffer_char_san ('O', buf); mscp_buffer_move_san_check (_move, buf); return; } if ((_move == (MSCP_MOVE (MSCP_C_E1, MSCP_C_G1) | MSCP_C_SPECIAL)) || (_move == (MSCP_MOVE (MSCP_C_E8, MSCP_C_G8) | MSCP_C_SPECIAL))) { mscp_buffer_char_san ('O', buf);mscp_buffer_char_san ('-', buf); mscp_buffer_char_san ('O', buf); mscp_buffer_move_san_check (_move, buf); return; } if ((mscp_board->fr == MSCP_C_WHITE_PAWN) || (mscp_board->fr == MSCP_C_BLACK_PAWN)) { ! ! pawn moves are a bit special ! if (MSCP_F (fr) ~= MSCP_F (_to)) { mscp_buffer_char_san (MSCP_FILE2CHAR (MSCP_F (fr)), buf); mscp_buffer_char_san ('x', buf); } mscp_buffer_char_san (MSCP_FILE2CHAR (MSCP_F (_to)), buf); mscp_buffer_char_san (MSCP_RANK2CHAR (MSCP_R (_to)), buf); ! ! promote to piece (=Q, =R, =B, =N) ! if (_move > 4095 && (MSCP_R (_to)==MSCP_C_RANK_1 || MSCP_R (_to)==MSCP_C_RANK_8)) { mscp_buffer_char_san ('=', buf); switch (_move / 8192) { 0: mscp_buffer_char_san ('Q', buf); 1: mscp_buffer_char_san ('R', buf); 2: mscp_buffer_char_san ('B', buf); 3: mscp_buffer_char_san ('N', buf); default: mscp_buffer_char_san ('?', buf);! not expected } } mscp_buffer_move_san_check (_move, buf); return; } ! ! piece identifier (K, Q, R, B, N) ! switch (MSCP_PIECE2CHAR (mscp_board->fr)) { 'K', 'k': mscp_buffer_char_san ('K', buf); 'Q', 'q': mscp_buffer_char_san ('Q', buf); 'R', 'r': mscp_buffer_char_san ('R', buf); 'B', 'b': mscp_buffer_char_san ('B', buf); 'N', 'n': mscp_buffer_char_san ('N', buf); 'P', 'p': mscp_buffer_char_san ('P', buf); ! not expected default: mscp_buffer_char_san ('-', buf); ! not expected } ! ! disambiguate: consider moves of identical pieces to the same square ! moves = mscp_move_sp; mscp_generate_moves (0); while (mscp_move_sp > moves) { mscp_move_sp--; if (_to ~= MSCP_TO (mscp_move_stack_move-->mscp_move_sp) ! same destination || _move == mscp_move_stack_move-->mscp_move_sp ! different move || mscp_board->fr ~= mscp_board-> (MSCP_FR (mscp_move_stack_move-->mscp_move_sp)) ! same piece || mscp_test_illegal (mscp_move_stack_move-->mscp_move_sp)) { continue; } rankx = rankx | ((MSCP_R (fr) == MSCP_R (MSCP_FR (mscp_move_stack_move-->mscp_move_sp))) + 1); filex = filex | (MSCP_F (fr) == MSCP_F (MSCP_FR (mscp_move_stack_move-->mscp_move_sp))); } if (rankx ~= filex) mscp_buffer_char_san (MSCP_FILE2CHAR (MSCP_F (fr)), buf); if (filex) mscp_buffer_char_san (MSCP_RANK2CHAR (MSCP_R (fr)), buf); ! ! capture sign ! if (mscp_board->_to ~= MSCP_C_EMPTY) mscp_buffer_char_san ('x', buf); ! ! to-square ! mscp_buffer_char_san (MSCP_FILE2CHAR (MSCP_F (_to)), buf); mscp_buffer_char_san (MSCP_RANK2CHAR (MSCP_R (_to)), buf); ! ! check ('+') or checkmate ('#') ! mscp_buffer_move_san_check (_move, buf); ]; Array mscp_san_buffer -> 11; [ mscp_print_move_san _move; #Ifdef MSCP_DEBUG; print "[MSCP> print_move_san ", _move, "]^"; #Endif; mscp_buffer_move_san (_move, mscp_san_buffer); mscp_print_string (mscp_san_buffer); ]; !C /*----------------------------------------------------------------------+ !C | move parser | !C +----------------------------------------------------------------------*/ !C static int parse_move(char *line, int *num) !C { !C int move, matches; !C int n = 0; !C struct move *m; !C char *piece = NULL; !C char *fr_file = NULL; !C char *fr_rank = NULL; !C char *to_file = NULL; !C char *to_rank = NULL; !C char *prom_piece = NULL; !C char *s; !C while (xisspace(line[n])) /* skip white space */ !C n++; !C if (!strncmp(line+n, "o-o-o", 5) !C || !strncmp(line+n, "O-O-O", 5) !C || !strncmp(line+n, "0-0-0", 5)) { !C piece = "K"; fr_file = "e"; to_file = "c"; !C n+=5; !C } !C else if (!strncmp(line+n, "o-o", 3) !C || !strncmp(line+n, "O-O", 3) !C || !strncmp(line+n, "0-0", 3)) { !C piece = "K"; fr_file = "e"; to_file = "g"; !C n+=3; !C } !C else { !C s = strchr("KQRBNP", line[n]); !C if (s && *s) { !C piece = s; !C n++; !C } !C /* first square */ !C s = strchr("abcdefgh", line[n]); !C if (s && *s) { !C to_file = s; !C n++; !C } !C s = strchr("12345678", line[n]); !C if (s && *s) { !C to_rank = s; !C n++; !C } !C if (line[n] == '-' || line[n] == 'x') { !C n++; !C } !C s = strchr("abcdefgh", line[n]); !C if (s && *s) { !C fr_file = to_file; !C fr_rank = to_rank; !C to_file = s; !C to_rank = NULL; !C n++; !C } !C s = strchr("12345678", line[n]); !C if (s && *s) { !C to_rank = s; !C n++; !C } !C if (line[n] == '=') { !C n++; !C } !C s = strchr("QRBNqrbn", line[n]); !C if (s && *s) { !C prom_piece = s; !C n++; !C } !C } !C while (line[n] == '+' || line[n] == '#' !C || line[n] == '!' || line[n] == '?') { !C n++; !C } !C *num = n; !C if (!piece && !fr_file && !fr_rank !C && !to_file && !to_rank && !prom_piece) !C return 0; !C move = 0; !C matches = 0; !C m = move_sp; !C compute_attacks(); !C generate_moves(0); !C while (move_sp > m) { !C int fr, to; !C move_sp --; !C fr = FR(move_sp->move); !C to = TO(move_sp->move); !C /* does this move match? */ !C if ((piece && *piece != toupper(PIECE2CHAR(board[fr]))) !C || (to_file && *to_file != FILE2CHAR(F(to))) !C || (to_rank && *to_rank != RANK2CHAR(R(to))) !C || (fr_file && *fr_file != FILE2CHAR(F(fr))) !C || (fr_rank && *fr_rank != RANK2CHAR(R(fr))) !C || (prom_piece && !C (toupper(*prom_piece) != "QRBN"[(move_sp->move)>>13]))) !C { !C continue; !C } !C /* if so, is it legal? */ !C if (test_illegal(move_sp->move)) { !C continue; !C } !C /* probably.. */ !C /* do we already have a match? */ !C if (move) { !C int old_is_p, new_is_p; !C if (piece) { !C puts("ambiguous!"); print_board(); puts(line); !C move_sp = m; !C return 0; !C } !C /* if this move is a pawn move and the previously !C found isn't, we accept it */ !C old_is_p = (board[FR(move)]==WHITE_PAWN) || !C (board[FR(move)]==BLACK_PAWN); !C new_is_p = (board[fr]==WHITE_PAWN) || !C (board[fr]==BLACK_PAWN); !C if (new_is_p && !old_is_p) { !C move = move_sp->move; !C matches = 1; !C } else if (old_is_p && !new_is_p) { !C } else if (!old_is_p && !new_is_p) { !C matches ++; !C } else if (old_is_p && new_is_p) { !C puts("ambiguous!"); print_board(); puts(line); !C move_sp = m; !C return 0; !C } !C } else { !C move = move_sp->move; !C matches = 1; !C } !C } !C if (matches <= 1) !C return move; !C puts("ambiguous!"); print_board(); puts(line); !C return 0; !C } Array mscp_parse_move_ambiguous string "ambiguous!^"; [ mscp_parse_move line _move matches n m piece fr_rank fr_file to_rank to_file prom_piece fr _to uc_piece uc_prom_piece move_prom_piece old_is_p new_is_p; #Ifdef MSCP_DEBUG; print "[MSCP> parse_move ", line, "]^"; #Endif; piece = 0; fr_rank = 0; fr_file = 0; to_rank = 0; to_file = 0; prom_piece = 0; n = 1; while (n <= line->0 && mscp_xisspace (line->n)) ! skip white space n++; if (line->0 - n >= 4 && line->(n + 1) == '-' && line->(n + 3) == '-' && ((line->n == 'o' && line->(n + 2) == 'o' && line->(n + 4) == 'o') || (line->n == 'O' && line->(n + 2) == 'O' && line->(n + 4) == 'O') || (line->n == '0' && line->(n + 2) == '0' && line->(n + 4) == '0'))) { piece = 'K'; fr_file = 'e'; to_file = 'c'; n = n + 5; } else if (line->0 - n >= 2 && line->(n + 1) == '-' && ((line->n == 'o' && line->(n + 2) == 'o') || (line->n == 'O' && line->(n + 2) == 'O') || (line->n == '0' && line->(n + 2) == '0'))) { piece = 'K'; fr_file = 'e'; to_file = 'g'; n = n + 3; } else { if (n <= line->0) { switch (line->n) { 'K', 'Q', 'R', 'B', 'N', 'P': piece = line->n; n++; } } ! first square if (n <= line->0) { switch (line->n) { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h': to_file = line->n; n++; } } if (n <= line->0) { switch (line->n) { '1', '2', '3', '4', '5', '6', '7', '8': to_rank = line->n; n++; } } if (n <= line->0) { if (line->n == '-' || line->n == 'x') { n++; } } ! second square if (n <= line->0) { switch (line->n) { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h': fr_file = to_file; fr_rank = to_rank; to_file = line->n; to_rank = 0; n++; } } if (n <= line->0) { switch (line->n) { '1', '2', '3', '4', '5', '6', '7', '8': to_rank = line->n; n++; } } ! promotion if (n <= line->0) { if (line->n == '=') { n++; } } if (n <= line->0) { switch (line->n) { 'Q', 'R', 'B', 'N', 'q', 'r', 'b', 'n': prom_piece = line->n; n++; } } } while (n <= line->0 && (line->n == '+' || line->n == '#' || line->n == '!' || line->n == '?')) { n++; } if (piece == 0 && fr_file == 0 && fr_rank == 0 && to_file == 0 && to_rank == 0 && prom_piece == 0) return 0; _move = 0; matches = 0; m = mscp_move_sp; mscp_compute_attacks (); mscp_generate_moves (0); while (mscp_move_sp > m) { mscp_move_sp--; fr = MSCP_FR (mscp_move_stack_move-->mscp_move_sp); _to = MSCP_TO (mscp_move_stack_move-->mscp_move_sp); ! does this move match? if (piece ~= 0) { switch (MSCP_PIECE2CHAR (mscp_board->fr)) { 'K', 'k': uc_piece = 'K'; 'Q', 'q': uc_piece = 'Q'; 'R', 'r': uc_piece = 'R'; 'B', 'b': uc_piece = 'B'; 'N', 'n': uc_piece = 'N'; 'P', 'p': uc_piece = 'P'; default: uc_piece = '-'; ! not expected } if (piece ~= uc_piece) { continue; } } if ((to_file ~= 0 && to_file ~= MSCP_FILE2CHAR (MSCP_F (_to))) || (to_rank ~= 0 && to_rank ~= MSCP_RANK2CHAR (MSCP_R (_to))) || (fr_file ~= 0 && fr_file ~= MSCP_FILE2CHAR (MSCP_F (fr))) || (fr_rank ~= 0 && fr_rank ~= MSCP_RANK2CHAR (MSCP_R (fr)))) { continue; } if (prom_piece ~= 0) { switch (prom_piece) { 'Q', 'q': uc_prom_piece = 'Q'; 'R', 'r': uc_prom_piece = 'R'; 'B', 'b': uc_prom_piece = 'B'; 'N', 'n': uc_prom_piece = 'N'; default: uc_prom_piece = 0; } switch (mscp_move_stack_move-->mscp_move_sp / 8192) { 0: move_prom_piece = 'Q'; 1: move_prom_piece = 'R'; 2: move_prom_piece = 'B'; 3: move_prom_piece = 'N'; default: move_prom_piece = '-';! not expected } if (uc_prom_piece ~= move_prom_piece) { continue; } } ! if so, is it legal? if (mscp_test_illegal (mscp_move_stack_move-->mscp_move_sp)) { continue; } ! probably... ! do we already have a match? if (_move ~= 0) { if (piece ~= 0) { mscp_print_string (mscp_parse_move_ambiguous); mscp_print_board (); mscp_print_string (line); mscp_print_char ('^'); mscp_move_sp = m; return 0; } ! if this move is a pawn move and the previously ! found isn't, we accept it old_is_p = ((mscp_board->(MSCP_FR (_move)) == MSCP_C_WHITE_PAWN) || (mscp_board->(MSCP_FR (_move)) == MSCP_C_BLACK_PAWN)); new_is_p = ((mscp_board->fr == MSCP_C_WHITE_PAWN) || (mscp_board->fr == MSCP_C_BLACK_PAWN)); if (new_is_p && (~~old_is_p)) { _move = mscp_move_stack_move-->mscp_move_sp; matches = 1; } else if ((~~old_is_p) && (~~new_is_p)) { matches ++; } else if (old_is_p && new_is_p) { mscp_print_string (mscp_parse_move_ambiguous); mscp_print_board (); mscp_print_string (line); mscp_print_char ('^'); mscp_move_sp = m; return 0; } } else { _move = mscp_move_stack_move-->mscp_move_sp; matches = 1; } } if (matches <= 1) return _move; mscp_print_string (mscp_parse_move_ambiguous); mscp_print_board (); mscp_print_string (line); mscp_print_char ('^'); return 0; ]; !C /*----------------------------------------------------------------------+ !C | opening book | !C +----------------------------------------------------------------------*/ ! pre-built book data Constant MSCP_C_BOOKSIZE 2036; Array mscp_book_data_hash --> $00062CCD $0021A4F4 $004A47A8 $004A47A8 $004BC191 $005314B3 $005314B3 $005314B3 $006DAD6D $006DAD6D $006DAD6D $006DAD6D $006F6E55 $00C63E5E $00D322BB $0111D46C $0111D46C $01120601 $016CC5B8 $016CC5B8 $01704C99 $01704C99 $01704C99 $0175B337 $0175B337 $01B3BBE2 $01E25FEA $0210FBAF $02BA7EC0 $0380DD47 $0387F1E4 $03AB67CB $03B9F83C $03B9F83C $03D1CBB5 $03F5E809 $03F60F23 $03F82297 $03F82297 $03F82297 $03FC1608 $04050660 $04050660 $04050660 $04050660 $04050660 $04050660 $041F4F75 $041F4F75 $04203EEA $04215060 $04215060 $04215060 $045FDFA9 $045FDFA9 $045FDFA9 $046FD85A $04A81A2D $04C056F3 $04CB08CA $04CB08CA $04CB08CA $04E409AB $0501F8B3 $0504635E $052CF14B $057FE16C $057FE16C $05B90597 $05D6E93E $05DBFE74 $05FAFB05 $05FCA604 $0610824A $063B55CB $063F9704 $06674858 $066AD0CF $066AD0CF $06A876F9 $06A876F9 $06A876F9 $06AEE78E $06B92BCA $06B92BCA $06D780DD $06EC0112 $06EC0112 $0701671D $072B0F42 $073435BC $0737C038 $0737C038 $07577C72 $076C63C3 $0770D4E0 $0770D4E0 $07797FDC $07797FDC $079C1A25 $07C288E3 $07C288E3 $07C288E3 $07D033DA $07DB60EA $07E87DB2 $07F4236E $07F4236E $07F4236E $08269386 $084EACCF $084EACCF $084EACCF $08CF8AC0 $08DB0535 $08E5233C $08E5233C $08FB2C20 $08FB2C20 $095EB04F $095EB04F $0970C8C8 $0970C8C8 $0979B832 $0979B832 $09A67D9F $09A67D9F $09B69BA6 $09CD44D2 $09D3B7D4 $09D3B7D4 $09D3B7D4 $09E39490 $09E39490 $09E39490 $09E39490 $09E39490 $09E39490 $09EE4EAD $09F3163A $09F63BE2 $09F63BE2 $09FA1813 $09FA1813 $0A11650E $0A3C1B0A $0A3C1B0A $0A3C1B0A $0A3EC7FE $0A636D18 $0A636D18 $0A81A306 $0AD29AD2 $0AEC9C70 $0AEC9C70 $0AEC9C70 $0B419DA3 $0B428648 $0B4662FD $0B4F436E $0B763F39 $0B763F39 $0B763F39 $0B7A910A $0B88C7BB $0B88C7BB $0B88C7BB $0BB0C9E7 $0BB0C9E7 $0BB0C9E7 $0BB0C9E7 $0BB0C9E7 $0BB0C9E7 $0BDB9A83 $0BDB9A83 $0BDB9A83 $0BE64CD7 $0BEF9DBA $0C06A289 $0C06A289 $0C09769A $0CBBC23D $0CBE75E6 $0CBE75E6 $0CC2AD3F $0CC52C91 $0CD6905D $0CE80968 $0CE80968 $0CE80968 $0CE80968 $0CE80968 $0CE80968 $0CE96150 $0CE96150 $0D2578E8 $0D2CBD9B $0D797CEE $0D81AD05 $0D81AD05 $0DA6EE30 $0DCB5142 $0DCD46A7 $0E1D719C $0E1DEB1F $0E4D4395 $0E4D4395 $0E573B1C $0E613DD4 $0E687964 $0E687964 $0E7003D8 $0E7003D8 $0ED60444 $0F0B9D72 $0F0B9D72 $0F2A2D45 $0F2A2D45 $0F623C7A $0F623C7A $0F9BE2F3 $0F9BE2F3 $0F9BE2F3 $0F9BE2F3 $0FB3318E $0FD09A9E $0FD09A9E $0FD09A9E $0FD09A9E $0FD12D3C $102DA7E1 $103D44B6 $103D44B6 $1066645E $107D789E $109D4A44 $109D4A44 $109D4A44 $109D4A44 $10A379AF $10AB7E54 $10B8803B $10F420EB $11195C37 $112CF768 $11907CE9 $11A15D62 $11AD213A $11B47221 $11B47221 $11B47221 $11B47221 $11BEACAB $11C259D5 $11C6522A $11D2B539 $11DB4CAF $11DB4CAF $11F45254 $1203D03A $12125372 $122E83C3 $123C2B15 $123C2B15 $124DCBA7 $125B0BB2 $12778179 $12778179 $12778179 $129F7409 $129F7409 $129F7409 $12B26221 $1305D740 $130B24E5 $130B24E5 $1339975C $133CA2A7 $1364F538 $137B97BD $1398AAAE $13ACCED2 $13ACCED2 $13C3219E $13C3219E $13C3219E $13C3219E $13C3219E $13C3219E $13C6E212 $13EBB347 $142B4FA7 $143516D6 $14436129 $1445BD2B $1445BD2B $14600ACC $149B8E13 $14C3AB78 $14CA23E5 $14CC0E3D $14DB71CD $14DB71CD $14DEDEBF $14DEDEBF $151D2953 $152FC3BB $1547BF47 $1547BF47 $154845EE $154D9DB2 $15B2BE83 $15CCAF20 $15D120FD $15D120FD $15F2457C $15F2457C $160EEB68 $1631EBD3 $163BB340 $163BB340 $1647AF2B $164889BB $164E26C1 $16598C24 $16B68B58 $16D45056 $16EBCDE8 $170BAA4B $1720D4F3 $1720D4F3 $1720D4F3 $1720D4F3 $1722CCEF $1722CCEF $172AC7F8 $172AC7F8 $173C74B9 $176439D3 $1785ED72 $178BFA0A $17A03665 $17A60F97 $17A60F97 $17D04F5E $1801EA05 $181BF112 $181D7E81 $182FB40A $183CD9B0 $1843363D $1843363D $187A4458 $1886FDE0 $1886FDE0 $18877B2E $188A9277 $188A9277 $189F9C1E $18A717C4 $1919442E $1921D19D $1923281D $193631B7 $19709E1D $197260F5 $19A55478 $19A8B096 $19BBC9DA $19CD33EA $19CD33EA $19E180AB $19F687F7 $19FB7B49 $1A108EA9 $1A17286D $1A519553 $1A6FA129 $1A9A6C67 $1ABED871 $1ABED871 $1ABED871 $1ABED871 $1ABED871 $1ACB879A $1AD42137 $1AD42137 $1AD42137 $1AD42137 $1AE6F3EE $1AF0F388 $1B4CCABB $1B650ACF $1B84C876 $1B88D939 $1B95CB35 $1B95CB35 $1BA0580C $1BD4FC5F $1BD4FC5F $1BE056DF $1BE535B4 $1BE535B4 $1C17FADD $1C17FADD $1C1BE486 $1C1CB582 $1C1CB582 $1C1CB582 $1C1CB582 $1C1CB582 $1C1F00C1 $1C2C37D0 $1C2C37D0 $1C2C37D0 $1C2C37D0 $1C2C37D0 $1C46DDC2 $1C46DDC2 $1C46DDC2 $1C52B819 $1C52B819 $1C5BD813 $1C5BD813 $1C63E733 $1C63E733 $1C63E733 $1C63E733 $1C6D16D5 $1C970C2E $1CACB152 $1CB8E0B3 $1CB8E0B3 $1CB8E0B3 $1CC2046B $1CD598DE $1CE07C33 $1D076EC9 $1D076EC9 $1D076EC9 $1D0C8994 $1D20C5CA $1D261752 $1D261752 $1D5B9B22 $1D741CD3 $1D7CFD4D $1D812CF1 $1D812CF1 $1D812CF1 $1DA354BA $1DBFB716 $1DD63BBA $1DDDF3CA $1DF2160D $1E1938B6 $1E1938B6 $1E1D685E $1E610F34 $1E69DE94 $1E758339 $1E758339 $1E81FD96 $1E81FD96 $1E9ECE4A $1E9ECE4A $1E9ECE4A $1E9ECE4A $1E9ECE4A $1E9ECE4A $1E9ECE4A $1E9ECE4A $1ED778A6 $1EF2C76A $1EF2C76A $1EF2C76A $1EF2C76A $1F059C22 $1F0B956A $1F100CA8 $1F100CA8 $1F6A2BEF $1F748E17 $1F884A96 $1F89D721 $1F89D721 $1F97FFD7 $1F9A5932 $1FB54589 $1FBC5752 $1FE3E201 $2061DD5F $207D9187 $207D9187 $208B4359 $208E1E86 $208E1E86 $2097C614 $2097C614 $2097C614 $20C3C85F $20D3D6AB $20D3D6AB $20DCAC75 $20DCAC75 $20DCAC75 $20DF3999 $210F15BF $21365BC7 $213F7992 $217D8A39 $217D8A39 $217D8A39 $217D8A39 $217F6C6A $2191D1FB $2191D1FB $219249E0 $219249E0 $219249E0 $219F6A3E $219F6A3E $21AD0663 $21AD0663 $220A1921 $220A1921 $221567E2 $221A6FB6 $222BDE3C $222BDE3C $2264D749 $226AB28E $227CFE24 $227CFE24 $227CFE24 $227CFE24 $228D9648 $2296E93A $22BF095F $22BF095F $22C9919D $22C9919D $22E92153 $23050C7C $23105A36 $23105A36 $234DA589 $235FA60E $23D1C3DF $23D721BF $23D7403A $240FA52C $2420F1B4 $2423F825 $243695B2 $245C2C7C $2464D228 $24878FEB $2498545D $2498545D $2498545D $24A79617 $24A79617 $24A79617 $24B3B9E9 $24B3B9E9 $24D0676F $24FD82F2 $24FF589B $2502EAB0 $251F066B $251F066B $251F066B $251F066B $252024B6 $252024B6 $2537604C $256D12E5 $2571E0EB $25750C77 $257545CE $257545CE $25823660 $258535BC $258B3055 $2591F5CC $2591F5CC $2596408B $25BBA02A $25CCC188 $25DA5FA0 $25DA5FA0 $25DA5FA0 $25DA5FA0 $25DF4A28 $25DF4A28 $25DF4A28 $260977D3 $2619ACF8 $262D209A $267472F0 $2676C4F5 $2676C4F5 $267B42A2 $26A25590 $26C9B03F $26C9B03F $26F41E7A $26F85887 $274A727D $274A727D $274D59D3 $27711179 $277FD74D $27E53B4A $27EBF947 $27FCB303 $2809FB9C $2809FB9C $2809FB9C $2809FB9C $280E057A $28238322 $28366788 $28366788 $283A10C2 $28ED132D $29331093 $29331093 $29455BDD $294F4B65 $294F4B65 $294F4B65 $294F4B65 $2956B4AD $295FD04F $29731C90 $298065C5 $29D7B29F $29D7B29F $2A1C7B51 $2A234CE1 $2A23E252 $2A37A837 $2A37A837 $2A3CA0FE $2A4FE45A $2A574B17 $2A676853 $2A676853 $2A84F806 $2A84F806 $2A84F806 $2A84F806 $2AC167E0 $2AC167E0 $2B153E6A $2B153E6A $2B153E6A $2B19D84C $2B49345A $2B4F9FD5 $2B9C60D5 $2B9E994A $2BA99542 $2BB63A5F $2BCD001F $2BDCCE26 $2BFF66C0 $2C0551DD $2C0E2868 $2C6092D0 $2C65F5F4 $2CD89739 $2CFF4004 $2CFF4004 $2D1306A8 $2D1306A8 $2D161320 $2D161320 $2D2E84F5 $2D2E84F5 $2D3B4D04 $2D4E6B86 $2D5FF609 $2D5FF609 $2D7CB165 $2D7CB165 $2DA1A85F $2DA1A85F $2DA21B59 $2DAA7018 $2DDA9555 $2DDA9555 $2DDA9555 $2DDA9555 $2DDA9555 $2DDA9555 $2DDA9555 $2DDE17B4 $2DECDF3E $2E050B27 $2E050B27 $2E1C260E $2E4E026A $2E534349 $2E763EAD $2E763EAD $2E7A1BF6 $2E871BF3 $2E8F7DE4 $2E957103 $2EA60438 $2EA60438 $2EA60438 $2EC7319E $2EC7319E $2ECFE2CC $2ECFE2CC $2ECFE2CC $2ECFE2CC $2ECFE2CC $2ECFE2CC $2ECFE2CC $2EDD7D3B $2EE75261 $2EF016EA $2EF99515 $2EF99515 $2EF99515 $2EF99515 $2EF99515 $2EF99515 $2F790038 $2F8D2213 $2FAA9CB6 $2FAA9CB6 $2FB18FA1 $2FB39BCD $2FB39BCD $2FBE84D5 $2FBEA0B7 $301DC933 $304981A8 $3049C977 $304A60F1 $304A60F1 $30500DA2 $30706B1C $3077FE19 $3077FE19 $3077FE19 $3077FE19 $3077FE19 $3077FE19 $3077FE19 $3077FE19 $30B84D9C $30C609D3 $30D96522 $30E97546 $30E97546 $30E97546 $30F5880B $30F80F71 $30FEFB8F $31047F64 $31119181 $31119181 $3154C1A5 $31622B26 $318873B3 $31A45AE6 $31A45AE6 $31A45AE6 $31C3BB21 $31DCEB0E $3200ADA6 $3214802A $3214802A $3214802A $3214802A $32227FDF $32255E59 $3228E9F5 $322DC33C $322DC33C $32408A9C $325C83DC $3267CDFC $328B8436 $32A2CBED $32A2CBED $32B28F99 $32B28F99 $32B8C09C $32B8C09C $32D6CD41 $332B688E $332B688E $33493A8E $3349D772 $3378F6F9 $3378F6F9 $3378F6F9 $33899B31 $33899B31 $339A9EDD $339A9EDD $33A29E03 $33A29E03 $33E3E849 $33F20170 $33F20170 $33F20170 $33F20170 $3430CFF3 $3433CDFA $3433CDFA $346D71FB $346D71FB $346F5EDE $3475BCDD $34809D07 $34C45123 $34CF0D94 $34D436A2 $34EF57C2 $34EF57C2 $352ED614 $35352CCD $353701FD $353701FD $353701FD $353701FD $353701FD $353701FD $3548C6BF $3548C6BF $354B4141 $358FA3F3 $35B73426 $35B73426 $35B73426 $35D1F320 $35D1F320 $35D1F320 $35DEA89A $360B451D $363337B0 $3635ED04 $367CD33E $369275FA $36A097DF $36B2258D $36B2258D $36C53E89 $36C5925C $36CCAA44 $36D090C3 $36DD9240 $36DD9240 $36DD9240 $36DD9240 $36EA2360 $36F0C011 $3702098A $37023130 $37473F8F $374816BC $3754A4D7 $3754A4D7 $375852D8 $37594D8E $37594D8E $37594D8E $37594D8E $37594D8E $37A23BC7 $37ACCC43 $37AE9462 $37B8050F $37B8050F $37C0BC80 $37E2EF10 $37E2EF10 $37EB118D $37EB118D $380E79FE $384A3D74 $3850E1A5 $3866EBB0 $38971CED $38971CED $38AA5CA0 $38AA5CA0 $38AA5CA0 $38AA5CA0 $38D8DB5E $38E1B1BD $38FE8051 $38FE8051 $3909FAD2 $390A07F6 $390AD820 $390AD820 $390DD146 $390DD146 $390DD146 $390F127E $390F127E $390F127E $390F127E $393AEC82 $39439845 $39440A1D $3944B812 $3944B812 $3944B812 $39A8EAC2 $39E585E0 $39E585E0 $39ED94E3 $3A583645 $3A5ED4A9 $3A5ED4A9 $3A5ED4A9 $3A7EA9AA $3A82A108 $3A936E2A $3AA1EF1C $3ACCE126 $3ACCE126 $3AF29D7D $3B144D44 $3B288C6A $3B2CE972 $3B38D22E $3B3B7B67 $3B4F849F $3B8A7454 $3B94234D $3BEB41F2 $3C131445 $3C1EAE8E $3C24A36A $3C2F4A4C $3C31B94A $3C31B94A $3C31B94A $3C3B9DDD $3C64165A $3CA5A11D $3CA8DC59 $3CC05190 $3CCC8454 $3CE13230 $3CE13230 $3CE353B3 $3CE99538 $3D337CAD $3D67B973 $3DA8BC1E $3DA9B7D9 $3DA9B7D9 $3DA9B7D9 $3DA9B7D9 $3DC552B8 $3DC552B8 $3DE21DB5 $3DE21DB5 $3DF061BE $3E08AADB $3E0BDC74 $3E0BDC74 $3E0BDC74 $3E0BDC74 $3E0BDC74 $3E2FAC78 $3E4D3904 $3E4D3904 $3E506AA3 $3E506AA3 $3E5C8C85 $3E5C8C85 $3E5C8C85 $3E698537 $3E698537 $3E6A4481 $3E6A4481 $3E9CA8FA $3E9FBA8E $3EB28CC9 $3F199A7C $3F1EF387 $3F1EF387 $3F1EF387 $3F2A825A $3F3E5F2A $3FAA3985 $3FAA3985 $3FC26560 $3FEE655C $3FF74AE8 $402A0BBF $403853C7 $403946F5 $40667CF3 $40B6BE00 $40CD0663 $40CF5CF8 $40CF5CF8 $40D33E1F $40E3439B $40E3439B $40E3439B $41089B56 $412A22FD $41305673 $41305673 $4130ACC5 $4140DBB8 $414E7BC4 $414E7BC4 $415BD4B6 $415BD4B6 $415DDD54 $4160AB86 $41683A81 $41736A65 $4178EAFB $417E5880 $417E5880 $417E5880 $417E5880 $4199DA66 $4199FFF3 $419DC8D5 $41A715D2 $41CDAA28 $41D142EE $41D45766 $41F35F1B $41F35F1B $41FB40CC $4243DEFE $4243DEFE $4243DEFE $4259C966 $42A98654 $42A98654 $42A98654 $42DFC209 $43141F70 $4316D36A $431D26B3 $431D26B3 $4326CD87 $433188C7 $4337619A $434A73DD $435DA1AB $435DA1AB $436C0DA1 $439C6633 $43A8EDD4 $43C12ED8 $43CE416E $43DBD06D $43DD291F $43DD291F $43EA2517 $43EA2517 $440B8BD9 $44120910 $44448E04 $4445E63C $4445E63C $4445E63C $4445E63C $44531DFA $446E49AC $446E4C3B $446F426B $446F426B $446F426B $44859FEC $44924E53 $44924E53 $44AB4DDD $44AB4DDD $44BA56E5 $44BCF051 $44C2A305 $44C2A305 $44C2A305 $44D4A80B $44D7F54F $44FF72AA $450BB528 $450BB528 $450BB528 $4526580F $452C4251 $45364FA2 $45634094 $457932D6 $458C41D0 $45939A9F $45B9E9E3 $45D53C20 $45E4202C $45E90C39 $45FE9FDD $460F23F3 $460F23F3 $46238D87 $46238D87 $466581B6 $467BEB10 $46A8B9AB $46AAC282 $46AF060A $46BA2540 $46BA2540 $46BA2540 $46BA2540 $46BA2540 $46BA2540 $46BA2540 $46E043E3 $46E5B46D $46E5B46D $46E5B46D $46E5B46D $47142E25 $47142E25 $4726AD45 $4726AD45 $4790E716 $47972D60 $47972D60 $47A41ED4 $47B1489E $47C1A7EA $47F4C0D5 $482C7F9B $4830AECE $4830AECE $4830AECE $484303EE $488F3F9C $488F3F9C $489066D6 $489A76B6 $48C08D0D $48C08D0D $48C08D0D $48C8F30C $48C8F30C $48FA6C1B $48FE2986 $491334C7 $492987E0 $4932ACA2 $4932ACA2 $4932ACA2 $493E3A6C $493F8786 $493F8786 $4965CEF7 $4965CEF7 $497715A9 $49A5447B $49C5BBF0 $49D0A14E $49D0A14E $49D0A14E $49D1F9B5 $49D1F9B5 $49D3495E $49DCE3CA $49E2D83C $49F4DB65 $4A10661A $4A1C60CA $4A89C4FF $4A8B7E9D $4A8B7E9D $4AA4198F $4AB1A604 $4AB705AB $4AB705AB $4AC5D1B9 $4AC67757 $4AE92B8C $4B28DB39 $4B480F20 $4B51F95C $4B55CDC3 $4B5DD3C1 $4B5DD3C1 $4B9A0E6D $4BEF664F $4BEF664F $4BFF3013 $4C01BA02 $4C299A3B $4C299A3B $4C299A3B $4C490B03 $4C4C1297 $4C66E79E $4C66E79E $4C6B2699 $4C88E595 $4CCFB2B6 $4CF2C994 $4CFD31D6 $4D14B1A7 $4D381FD3 $4D381FD3 $4D6394E3 $4D6394E3 $4D6394E3 $4D6394E3 $4D6AB2B2 $4D778C98 $4D7B37B4 $4DB6FE6F $4DBBC0AD $4DD80768 $4E0599AD $4E0599AD $4E11A00C $4E14C49E $4E3ADF9E $4E47CABC $4E53AC5E $4E88C51F $4E88C51F $4E8A8106 $4E96BA9F $4E96BA9F $4EAEAA70 $4EC73F9B $4EDCDA83 $4F241559 $4F27E801 $4F4592E6 $4F49F8FA $4F6A9334 $4F9A2F6C $4FAA893A $4FAF26DE $4FC62474 $4FCEE9BE $4FD29592 $4FD29592 $4FD29592 $4FFA9326 $4FFA9326 $4FFA9326 $4FFA9326 $4FFCEDBC $5023A363 $5026145D $50316DF5 $5071212E $50898462 $508D139E $508D139E $508D139E $508D139E $509EE2F7 $50AB6DE2 $50D7AB0C $50E2231C $51088AC6 $511A3D39 $5138CA1B $514F623F $51605596 $51605596 $5160DCBE $51679979 $517A2A7B $51A635B5 $51A635B5 $51A635B5 $51B2C295 $51B7C2CA $51CC012C $51D8ACB1 $51D8ACB1 $51D8ACB1 $51D8ACB1 $51DBF708 $51E47D57 $5204429A $5210CA01 $521F6D5D $521F6D5D $521F6D5D $5223DC51 $524FBBE7 $525D5AC0 $525D88C1 $525D88C1 $527B363C $52BAC739 $52BAC739 $52BAC739 $52F0AE84 $52F0AE84 $530640F6 $530E19E5 $530E19E5 $530FCC98 $532BEF24 $534DB98B $534DB98B $535DD07D $535DD07D $53669FFA $537A9348 $539667A8 $53A8F1A7 $53A8F1A7 $53A8F1A7 $53A8F1A7 $53AADE82 $5419E9C1 $5419E9C1 $5419E9C1 $5419E9C1 $54276FF9 $54276FF9 $5435AE09 $5436CDB5 $544FAE58 $5478778A $5478778A $5478778A $5481D884 $5481D884 $5481D884 $5485EDD9 $54879C2D $5498087C $5498087C $5498087C $5498087C $5498087C $549BD3F5 $54B2EF95 $54B60BD2 $54B60BD2 $54B60BD2 $54BF0001 $54BFA0EE $54C1ABEB $54D6ECB1 $54D6ECB1 $54DB014D $54FF574D $5505F959 $5518A629 $551C4ADC $55323612 $553D9413 $55412C02 $554BF7AA $554BF7AA $55701C9E $55701C9E $558D2A9E $558FC8E1 $55985C2E $55A166C0 $55F765F0 $55FBF73B $5611C496 $562C13C4 $5633211E $5633211E $5633FFA5 $564EE601 $564F7AE8 $566CE997 $567671D4 $567671D4 $567671D4 $5689FB5D $5689FB5D $5689FB5D $5689FB5D $568B4D58 $56907229 $56CFFDF8 $56F348B7 $56FB2D66 $56FB2D66 $56FB2D66 $57288999 $57288999 $57288999 $57288999 $57288999 $572A2443 $57367A9F $57367A9F $57367A9F $575D43D2 $57697A3D $57CF2EEA $57D96143 $57DC20CC $57DF6030 $5831F6DC $5832C46C $5834563D $584BF6D2 $5851E56E $585D6E2E $586D24F3 $586D96FC $589A6C14 $58C95820 $58D00963 $58F87B69 $59067F9F $590B0282 $590DB0F9 $590DB0F9 $5923D1A6 $59689C8B $59727407 $597B732F $597F5A6D $59832236 $59991BF7 $59991BF7 $59A1F04F $59B76434 $59C3D730 $59E12902 $59E232E9 $59E232E9 $5A0C078D $5A1F94F9 $5A303687 $5A303687 $5A303687 $5A303687 $5A4B39C3 $5A4B39C3 $5A503A3D $5A5107FD $5AAE3F6E $5ADA6E2D $5ADA6E2D $5ADA6E2D $5B4905F7 $5B6377C8 $5BAAE89A $5BB45733 $5BB95693 $5BD36782 $5BD36782 $5BFDB37F $5BFDEDF8 $5C1DA1D5 $5C28050F $5C3284D5 $5C7A9BA9 $5C8520B2 $5C8DF3E0 $5C937FE4 $5C97B5F9 $5C98F704 $5C98F704 $5D0A28AC $5D0A28AC $5D0A28AC $5D11C193 $5D11C193 $5D33F9BE $5D4AE8E2 $5D4CB22D $5D7CCFA9 $5D7CCFA9 $5DA0C9A1 $5DA20A4E $5DAB155E $5DCB4E9B $5E1B8B2E $5E86B9D8 $5E9344B8 $5E9344B8 $5EA64133 $5EDD394C $5EEF77B4 $5F3700B2 $5F392F28 $5F4085EC $5F419F1F $5F45E5DE $5F577348 $5F687815 $5F7264B9 $5F7DA00A $5F7DA00A $5F7DA00A $5FA19C2B $6002CAE9 $6002CAE9 $600BA4E7 $60132D58 $60158E13 $6020C579 $6058B840 $60649CD5 $606F0FEA $6097FF96 $6097FF96 $6097FF96 $609C5158 $60A414C8 $60A414C8 $60A8ABAD $60A9F934 $60A9F934 $60A9F934 $60AE6C31 $60E0FE82 $60F0E239 $61252BD9 $6144F038 $61923CB2 $6193F7D2 $6197696C $61BD5C0A $61CE2C2B $61DEF3C4 $61E2A431 $61E5CDCA $61E5CDCA $61FA319B $61FBE75F $6229A31E $624D13BA $6256C042 $629F2817 $62F9DFB5 $6313DF42 $6320A569 $632C065D $632C065D $632C065D $6339DDBA $634499F0 $634EE807 $6366E706 $6366E706 $63712172 $63712172 $6396D290 $6396D290 $6396D290 $63973183 $63A6F1D4 $63B8D13E $63B8D13E $63B8D13E $63B8D13E $63C235E6 $63C235E6 $63C235E6 $63D52070 $63F41B4D $6401255D $6409A330 $6424EB40 $6433417F $6482C195 $6482C195 $64A7A9C9 $64AE18DC $64C9AA4D $64D4700F $64E8BEC4 $651B9096 $6531C4B3 $6547C926 $654D812B $654D812B $654E0BCF $6569330B $6569330B $65929A96 $65929A96 $65929A96 $6595466C $65A68726 $65A68726 $65A68726 $65BBFC74 $65BEE9FC $65BEE9FC $65BEE9FC $65C50E10 $65D15E31 $65D4A19F $65E2DFB5 $6618BCEC $663422BD $6660347D $6670926F $6670926F $668C6405 $66BBF857 $66C694D7 $66E1B126 $671EBBAD $671EBBAD $671EBBAD $671EBBAD $671EBBAD $671EBBAD $6759303F $6759303F $6759303F $67874AA3 $678AA3FA $678AA3FA $678AA3FA $67950201 $679938A2 $679938A2 $67BB5196 $67DDF347 $67F139BB $67F139BB $68111D2D $6823F1D2 $6823F1D2 $68491BC0 $68491BC0 $68491BC0 $68491BC0 $68491BC0 $68491BC0 $68491BC0 $68491BC0 $68491BC0 $6872D6CD $68943A59 $68A7B021 $68A7B021 $68CC320B $68D5089C $68EF3FF0 $68EF3FF0 $6932856A $695C9C7F $69746DBA $69A2FAEB $69D3D66B $6A12E60B $6A3433D9 $6A4DAC3F $6A694FF2 $6A697C4A $6A799566 $6A8BCC1C $6A8BCC1C $6A930363 $6A930363 $6ABFFEE3 $6AF72AEC $6AF86EAF $6B19892F $6B21440A $6B2FA611 $6B350BE0 $6B70E00E $6B79DA9F $6B79DA9F $6B83DE5B $6B93AE9D $6B93AE9D $6B93AE9D $6BB07F0C $6BC10DF0 $6BC10DF0 $6BCC3FB0 $6BCC3FB0 $6BCC3FB0 $6BCC3FB0 $6BE6BC1C $6C050312 $6C050312 $6C0BA652 $6C1E56BD $6C35BB09 $6C35BB09 $6C35BB09 $6C379215 $6C379215 $6C379215 $6C379215 $6C3F4147 $6C3F4147 $6C3F4147 $6C8D1EE0 $6C8D1EE0 $6CDFE3A3 $6CDFE3A3 $6CED77F2 $6CEFBE67 $6CEFBE67 $6CEFBE67 $6CEFBE67 $6CEFBE67 $6CEFBE67 $6CFF23CF $6D3C1A98 $6D3C1A98 $6D3C1A98 $6D3C5139 $6D70C127 $6D7E53F4 $6D89D1FF $6D89D1FF $6D9A8F18 $6D9A8F18 $6DB1462A $6DB1462A $6DB1462A $6DB204C3 $6DB204C3 $6DCD6AB7 $6DD685A2 $6E15DEEB $6E2D69BB $6E38FA5E $6E4E7B5C $6E4E7B5C $6E8CC054 $6E8CC054 $6E8E6D8E $6EB443AC $6EB443AC $6ED5DB59 $6ED6ADF6 $6EE4D204 $6F03189E $6F0D08BF $6F0D08BF $6F0E43AD $6F0E43AD $6F11DB4F $6F3D753B $6F46EF7A $6F46EF7A $6F67A857 $6F76E889 $6F76E889 $6F76E889 $6F76E889 $6F76E889 $6F8019A4 $6FB84A53 $6FC0C722 $6FC0C722 $7004F51B $702EFF20 $702EFF20 $703D456D $7049C139 $706CAF2F $70A396AA $70A396AA $70A396AA $70A396AA $70A396AA $70A396AA $70A396AA $70A396AA $70D0AB13 $711BD4F7 $713A8C73 $7145BD96 $71504208 $71703255 $71A7E8A2 $71C56D2F $71D11292 $71D11292 $71D5F42A $71D5F42A $71EC9140 $71EC9140 $71EC9140 $71F44BCA $72047E49 $723E817E $723E817E $723E817E $7253FE67 $725ABB14 $725ABB14 $725ABB14 $725ABB14 $72CFF733 $72CFF733 $72D41E0C $72DEBB28 $72DEBB28 $72F33BFD $72F33BFD $72F5D911 $73094717 $73094717 $7318DAD6 $7352AC73 $735B1095 $73953D7A $739CD6D8 $73B2E589 $73B54B8A $73BAB2EF $73BC9814 $73C3B314 $73E838E5 $73E838E5 $73E838E5 $73F58643 $7434E3DB $74354F8C $743C58EC $743C58EC $74465370 $74465370 $74465370 $74616B00 $7462CCF8 $74832C26 $748369E1 $748369E1 $748369E1 $749C561E $749C561E $749C561E $749C561E $749C561E $74C79EB3 $74D12140 $74DBAB0E $74E8929F $7504588D $7504588D $754254BC $7544CAB4 $7544CAB4 $7565A707 $75666169 $7573A791 $75C49AF5 $75C4A356 $75F8B91F $75F9294F $75FA3986 $75FA3986 $761F1AC9 $763147AE $7653B382 $765E81C2 $765E81C2 $768927E6 $76B6AA2B $76D38659 $76D38659 $76E3A51D $76FD85F7 $76FD85F7 $770C9752 $77350703 $77350703 $773DB74B $773DB74B $774E9D42 $778BFD1E $77AC74DD $77B23EDC $77F11004 $77F47DD5 $783D84ED $7844E1F4 $78B3FDFD $78B5FE01 $78D7FCB1 $78DA114D $78DA114D $78DA114D $78DA114D $78DA114D $78E78FA5 $78E78FA5 $790527BB $790B63A1 $7926BEE0 $7946E398 $7946E398 $795304A5 $7984E900 $7984E900 $7984E900 $7998DEF7 $79A4EFE8 $79B0CF39 $79B0CF39 $79BC7ED5 $79FE807C $7A006CE4 $7A266B62 $7A3DF3AD $7A5AFF2B $7A5AFF2B $7A802C68 $7AAD42F2 $7AB96F7E $7AC27C7C $7AC324A2 $7ADBCFF9 $7ADBCFF9 $7ADBCFF9 $7AF7D09A $7AFDE57F $7B247465 $7B247465 $7B285FB3 $7B3B4B9A $7B45E555 $7B45E555 $7B5FEE24 $7BB9E708 $7BBF7CD0 $7BCB3947 $7BCB3947 $7BCB3947 $7BCB3947 $7BD1369A $7BD519AD $7BDB1AFB $7BDB1AFB $7BE43826 $7BE43826 $7BE43826 $7BEB98A9 $7BEB98A9 $7BEB98A9 $7C165EF8 $7C1BB0F2 $7C3D9297 $7C3E5CA4 $7C43BF96 $7C4ED0EB $7C813B2C $7CA1F1D3 $7CA6B184 $7CA6B184 $7CA6B184 $7CB188CA $7CBC5666 $7CD02F45 $7CD02F45 $7CD02F45 $7CD1FA38 $7CDB56F0 $7CDB56F0 $7CF99D21 $7CF99D21 $7D012AC5 $7D04CFBC $7D05706C $7D5D4FEB $7D7C1C74 $7D833940 $7D833940 $7D9DCDB9 $7DA7C545 $7DE6AE15 $7DF2FD3B $7DF4DEEF $7E037A16 $7E05C1A8 $7E05C1A8 $7E11E5E1 $7E11E5E1 $7E11E5E1 $7E330AD7 $7E51753D $7E51753D $7E707D14 $7E707D14 $7E707D14 $7EB63AC5 $7EB63AC5 $7EB63AC5 $7EBF2D7B $7EBF2D7B $7EBFE5F8 $7F061D40 $7F22E145 $7F22E145 $7F30540D $7F50F752 $7F50F752 $7F5CF62B $7F6977AD $7F6977AD $7F6D9CE0 $7F6D9CE0 $7F6D9CE0 $7F6D9CE0 $7F75A6A6 $7F793A1F $7F7DB8FE $7F86B474 $7FD31336 $7FD31336 $7FD31336 $7FF4A2DA $7FF94B83; ! Inform note - book data packed, count in high 16 bits, move in low 16 bits Array mscp_book_data_pack --> $00010212 $0006079D $00010A13 $00011453 $000307DC $00050BD4 $00010BE6 $00040DED $00200212 $00160219 $000208DC $000508E4 $000203DE $0001179C $00010712 $0002055B $00030BCB $00011830 $00010621 $00010A20 $00030212 $0028065B $00060A0C $00010594 $00070BF6 $00010C72 $0003066A $00010B5C $002500CA $00010252 $0001065B $000106D4 $003E0303 $00060315 $00010DED $00010DED $000303DE $00020A1A $00010C21 $00010C2A $0001079D $00020185 $000103D5 $000A0594 $00010723 $00010BE6 $00070DED $00010315 $00011830 $0001042B $00030434 $0001060A $00060862 $00020212 $0002065B $00060AA4 $0001079D $000119F7 $000104DC $000E0212 $00060C2A $00010C72 $0003095C $000103D5 $00010BE6 $00010DB5 $000106D4 $000208DC $00010A9B $00010212 $00050212 $00010042 $0003031E $00010452 $0001079C $000106DC $00020452 $000104DC $00020C2A $00020594 $000209A5 $00090DED $0003079D $00010A1A $00010C2A $0001051B $00010594 $000105CE $00020DED $000107DC $00020595 $000106DC $00010C2A $00080BF6 $00010A6B $00010A21 $00050A6A $00010595 $00030BF6 $00021830 $00010595 $000109A4 $000519F7 $00040594 $00010BE7 $00010C2A $00010594 $00010595 $00010DED $000109A4 $00010212 $00040C2A $00010C72 $000107CD $0001091B $00010422 $00011830 $000106D2 $0001079C $0003079C $000119F7 $000205CE $00010BE6 $000103D5 $0001079C $000204CA $00011830 $00010DED $00010C2A $00260212 $00190C2A $000A0C72 $00010212 $00010434 $00010453 $00010863 $00020C2A $00040C72 $00010862 $00010AE4 $000404CC $00020C2A $00020A13 $00011810 $000200CA $0001065A $0003065B $00180E7A $00010252 $0001065B $00010863 $000102E6 $00010DB5 $0001038D $0001079C $00010DB5 $0002065A $000205CE $00010595 $000104DC $0001065B $00020863 $00010C2A $00060B63 $00020452 $00010A13 $00040A9B $0002038D $00020594 $0006079C $0002079D $000709A5 $00060DB5 $00010212 $00010219 $00010419 $00010C21 $00010452 $00020594 $000219F7 $00020185 $000107D6 $00010A6A $00030A6B $000219F7 $000105DE $00010AE4 $000B0212 $00070452 $0002065B $00010A6B $00010C21 $00BC0C2A $00010595 $000119F7 $000106CA $00081863 $00010115 $000105F3 $000109A5 $00011830 $00010DED $00010BE6 $00030A20 $00010554 $000105DE $00010DED $0001065B $000108DC $000303D5 $000203DE $00010212 $0016065B $00020C2A $00070A21 $00010E7A $00020219 $00010493 $00020C2A $00030E7B $0003079C $0001079D $000109A5 $00020DED $00010594 $00020212 $00030453 $0002065A $0019065B $00020F9A $00010422 $00020212 $00020C72 $000103DE $0001079C $0001038D $00080594 $000207DE $00040DE6 $00010A6B $0001055C $00020C72 $00010D7E $0008038C $000104DC $00010C72 $0002095C $0001070D $00040212 $0006065B $00550A0C $000A0A13 $00010202 $000103D5 $00010633 $00010594 $0001065B $00011830 $00010A1A $00010C2A $00010BAD $00010863 $0016079C $001B0BF6 $00010BE6 $00010A9B $000104DC $00010862 $00020C2A $0001079C $000109A4 $00010DB5 $00020AE4 $0001065B $000102D4 $000119F7 $00010BF6 $00010595 $000103D5 $000206CC $000D0619 $0001065B $00010920 $003D079C $0002079D $000709A5 $000A0BAC $00030DB5 $009C0DED $00010619 $0002079D $00010A21 $0001055C $000300CA $000405DE $00030FBD $00060BE7 $00010A31 $000805E5 $0007079D $004C0212 $00010452 $0001065B $00010185 $000107CD $000103D5 $00021830 $00020D22 $00010D2B $0001051B $00010212 $000219F7 $00020D19 $00010A6B $00010C2A $000109A4 $00010DED $000108DC $00010BF6 $000506CC $000406D5 $00010B5C $00010042 $00011863 $000106CA $00010452 $00020452 $0001079D $000105E5 $00010042 $000108DC $001008E4 $00010C21 $0001079D $000119F7 $00010422 $00011830 $00010EFC $00050BF6 $000604A3 $00010BF6 $00030BF6 $00030A1A $00010C21 $00010BF6 $0002065B $00020DED $000105DE $0001079C $0001042B $00070185 $00060BE6 $00010C2A $0001079D $00010BE7 $00010212 $00070212 $00020C72 $00011810 $00020452 $00010A21 $00010B73 $00010621 $00030A1A $00010B23 $00080B5C $00010795 $00010452 $00040212 $0001079C $00010DED $00010212 $00021830 $00010544 $0001091B $00030594 $000108E4 $00010DED $000208D4 $00040212 $0001024A $00020452 $0002065A $0025065B $000119F7 $00010305 $0001030D $00010862 $00010A6A $00010BF6 $00010422 $0001049B $00020795 $00010BCB $0001038C $000108D4 $00010BE6 $00010566 $0001071B $00010BE6 $000103DE $0003079C $000209A4 $0001079C $000109A4 $000219F7 $0001038C $000103DE $000207CD $000107D6 $00020BE6 $000119F7 $00060212 $0002065B $00010A13 $00060A6B $00740C2A $00020422 $000106DC $00051830 $00020862 $00020C2A $00010042 $00010043 $000100D5 $00020452 $0001065B $00021830 $00010A21 $00020DED $00010A0C $000D0212 $00030434 $00030C72 $00010BAD $000205DE $00010633 $000103D5 $000203DE $000305DE $00010C2A $00020C2A $00010619 $00010A6B $000404A3 $00040395 $00010453 $000108D4 $00010BD4 $00010BE6 $000204A3 $00080712 $000109A5 $000103D5 $00020452 $0004042B $00060434 $0001065B $00010795 $0001064A $00010452 $00011830 $0001038D $000203D5 $00010042 $00010434 $0001060A $00080611 $000C0862 $00020A6A $00020C2A $00010C72 $00010453 $00020219 $00020422 $00030452 $00010621 $00010C2A $00010212 $000105DE $00010DB5 $000204DC $00010C2A $00010BE6 $0016079D $000F19F7 $00010DED $0006065B $00010C72 $00010219 $00011830 $00010C2A $00010BF6 $00020DED $0003065B $00010434 $00040C2A $000107FB $00010BD4 $00010DED $0008079C $0001061B $00010A9B $00020422 $00020A21 $00020C72 $0001079D $00020DED $000102D2 $00010668 $000203DE $000107D6 $000109A5 $000119A4 $00020302 $00010D26 $00010E7B $000103DE $000209A5 $000319A4 $00010422 $00010C2A $0001079C $00010DED $00010BF6 $00010DED $000103D5 $00010BE6 $000108DC $000108E4 $00010A1A $00010A1A $00020212 $00020452 $0053065B $00060A0C $000103D5 $00010BE6 $00010C2A $00010C72 $0003075C $00010BE6 $0002065B $00020594 $00010A1A $00010A6B $000206E4 $000103D5 $0001051B $000105DE $00040DED $000103DE $00020C2A $00010185 $00010DED $00010BD4 $000108E4 $000105C5 $00010185 $00010594 $00040DED $000103D5 $00010BDD $00010BE6 $0001065B $00010C2A $000203D5 $00020704 $00010A0C $00010A9B $0006038C $000509A5 $00010DB5 $000119A4 $000103DE $000809A5 $00020C2A $00011830 $00010A1A $00010A32 $00010594 $0002079C $00010B5C $00010C72 $00010594 $0002079D $00050BF6 $00010B63 $00020DED $00010A21 $00090212 $000104DC $00010611 $00010862 $00010212 $000306DC $00010C72 $0001079C $00010C2A $000108DC $00010408 $00030042 $00010C2A $000103D5 $00010A1A $000202C4 $000502D2 $00060795 $0002038C $0002038D $0001079D $000109A5 $000207C4 $0001065B $000204CA $0002065B $00010C21 $00010185 $000103D5 $0001051B $00020DED $00030B5E $00010862 $000107D6 $000219F7 $00010DB5 $000109A4 $00020212 $00010419 $000104A3 $00010212 $00010452 $00010C2A $00011E7B $00010AA0 $00020434 $00020C2A $000119F7 $00010453 $00020863 $00010212 $000107E6 $00020A31 $00020594 $0001079C $000109A5 $0001014C $0001065B $00010212 $0001065B $00010621 $0001065A $0001065B $00351830 $0001095C $00010B5C $00040434 $000204DC $000A0C2A $00010BCB $00010A6A $0001079C $00010D3B $000209A5 $00010BE6 $000119F7 $00010291 $000103D5 $00010212 $00010C2A $000C0212 $00010B63 $000103D5 $0001065B $000109A5 $000119A4 $00010C21 $00020C2A $0001065B $00010C2A $00010A6B $00010C2A $00010219 $00010A6B $00010595 $000119F7 $0001065B $00010C2A $00010043 $00010A21 $000108ED $000103DE $00060544 $0005054F $000505CE $000205E5 $00020B5E $00020BE7 $00020FBD $000105CE $00010A1A $00010594 $0001079C $000106D4 $000104A3 $0025038C $000107D6 $00040DE6 $0001079D $000105DE $00010252 $0001065B $000303D5 $0001079D $000107D6 $0001079D $000107D6 $00440185 $0002055B $00030BAC $00020BD4 $00020DB5 $00010DE6 $00060DED $000103D5 $000104A3 $000508F2 $00020422 $00130434 $00080A13 $00030A21 $00010A6B $00020C72 $00010595 $00010BD4 $000209AD $00020DAD $000109A5 $00060434 $000308E4 $00011830 $000319F7 $00011830 $000219F7 $00010B73 $00020A13 $00020C2A $00020185 $00010CF6 $000103D5 $00040594 $000B079C $0001079D $000209A5 $00010BAC $00020DB5 $00130DED $00011830 $00010A31 $00030594 $0002024B $00020452 $0001065A $000108E4 $00010453 $000104DC $00010A21 $00010212 $00010C2A $00020422 $0001059D $000208E4 $00010434 $00030453 $00020C72 $000208DC $00010212 $00010C2A $00010212 $0002065B $00010C2A $00010C72 $00010291 $00020BE6 $000206D4 $00010434 $00010C2A $00020A1A $000104DC $0001124B $00010C2A $00010434 $0001049C $000207DC $0002095C $0001065B $00010A13 $00030452 $000103DE $00010BE6 $000209A5 $0002095C $00010453 $00020A31 $00010C2A $000E06DC $00020C2A $000107E6 $00010DED $00010422 $00010C21 $00080252 $00010A13 $00010A6B $00010C2A $00020C72 $00010A1A $0001051B $000107CD $000206CA $00020A6B $00010185 $00020A21 $00020185 $00010AB4 $0001065B $00010C2A $00020212 $0001065A $00020C2A $00071810 $00020422 $00020A13 $00060A21 $00030A6B $00020C72 $00090C73 $00010043 $00010668 $00020C2A $000308DC $00100212 $00010A1A $00010A6A $000108F4 $00020A13 $00020C2A $0001065B $0002011F $00010219 $00020B5E $000106D5 $00010BF6 $00010042 $0003065A $0037065B $00010925 $00010594 $000104DC $000108D2 $00010A6B $00010C21 $00020C2A $00020C72 $000109A5 $00010BF6 $00010B63 $00010A9B $0001065B $00010764 $00020C2A $00020C72 $00010D2A $00050A21 $00080A6A $00010A6B $00010C21 $00070C2A $00040185 $0001071B $0001051B $000106CA $000106EA $00100212 $0002042B $00040453 $000203D5 $000319F7 $00030BF6 $00010212 $000103D5 $000302D2 $00020212 $000908E4 $0003038C $0002079D $00080B63 $00280BE6 $00010E20 $00010544 $0001091D $00010A6B $0001091B $00010C2A $0001024B $00010419 $000503DE $000505EC $00040DED $00070212 $00080219 $000608DC $000408E4 $0001050D $0001079D $00010BD4 $00010595 $0003079D $00030BF6 $0001075B $00160212 $000606CC $00010185 $00020C2A $000205F3 $00010764 $00020DB5 $0002065B $000108DC $000105CE $00010A31 $00010862 $00020C72 $000109A5 $000105EC $00010BDD $00010315 $00010C2A $00010C2A $0001049B $00010621 $0001091B $00010A1A $0002029B $00050B35 $000206CA $0003165B $00010212 $000B065B $00010C2A $000109A1 $0001024A $000206CC $00020BF6 $0001065B $00020C2A $00010BCB $00010BE6 $00010303 $00021830 $00010795 $00080723 $00010594 $00070212 $000104DC $00010862 $000C0C2A $0001004A $0001060A $00010BF6 $00010DED $000800CA $00010DED $0001079D $000107CD $000109A5 $00020DB5 $00010DED $000107E6 $0001050B $0001050D $00020A31 $00030C2A $000105C5 $000205CE $00010BCB $000103D5 $000119F7 $0002065B $00040A0C $000103DE $0001064A $000405EC $00010A21 $000205DE $000207CD $000409A5 $00090B5C $0002165B $000104A1 $00020A6B $00010594 $00010434 $00010C2A $00010DB5 $00010595 $000106DC $00010964 $00020A6B $00010395 $000104DC $0001060A $00040A9B $000103D5 $00010DB5 $00030DED $00010212 $00010452 $00050453 $00010A1A $00010C2A $00011830 $000109A5 $00010DED $000105CE $00010DB5 $00020764 $00010DED $000103D5 $00010434 $000105DE $000A038D $00040594 $000E079C $00030BCB $00010723 $00010452 $0001091B $00010C73 $000103D5 $00010219 $00010C2A $00180863 $00030C2A $000119F7 $00040595 $00020713 $000409A5 $000103D5 $000109A4 $000209A5 $00040DED $00010758 $00010594 $00010B5E $008B0453 $00110C2A $0001049B $000109A4 $000107D6 $00010BD4 $00010594 $000219F7 $00010BF6 $00021830 $00020212 $00030293 $0001049B $0001079C $000209A5 $000219A4 $0001038C $00010BE6 $000108DC $004C0DED $00010C2A $003103D5 $005D079D $002F09A5 $00020DB5 $00020862 $00010DED $00010994 $00010010 $00010862 $00010C2A $00010DED $0002055B $000419F7 $000108E4 $00040C2A $00020BE7 $00010DB5 $00020452 $00020A1A $00020A6B $00010594 $000303D5 $0001055C $000100D5 $00020621 $00250A20 $00020AE2 $00010C2A $0001095C $000204DC $00010BE6 $000108DD $00010DED $00010DB5 $000102D2 $00010FF7 $000104DC $00010452 $00070723 $00010DB5 $000104DC $000208DC $0001079C $0002051B $0002055B $000109EF $000107D6 $00020043 $00040422 $000A0434 $00030A13 $00060A21 $00050A6B $00020C72 $000208E4 $00050185 $0006079D $000707D6 $00040DED $00020619 $00010A13 $00010619 $000106CA $00010D2D $0001079C $000109A4 $00020452 $00020594 $00010BE7 $00020DED $00010A9B $00010CF4 $00010E30 $00020E7B $00010863 $000203DE $00020BE6 $000105CE $00010B73 $000C079D $000209A5 $000219A4 $0001065B $00010C72 $00010DB5 $00010453 $000108E4 $00010A31 $00020185 $000203D5 $00040FBD $000109A5 $00010BF6 $00010DED $004E051B $00040DED $0001038C $00010A1A $00010BDD $00010212 $00010621 $0004065B $000209A5 $000119A4 $00010713 $00010291 $0002095C $00010621 $00010C2A $000205DE $000119A4 $00010B63 $00010B73 $000106DC $000108E4 $00020595 $000E0DB5 $00020BE6 $00010A1A $000107C4 $000203D5 $00010BF6 $00010C2A $000119F7 $00010422 $000206DC $0001065A $0001055B $00010B23 $00010043 $00270A9B $00020723 $00010BCB $00020BE6 $00020212 $00010C72 $00010594 $00050DED $000102D2 $00011830 $000203D5 $0002094A $00010349 $00010DED $00010453 $00060863 $00020185 $000205DE $000107CD $000D09A5 $00010723 $00010C2A $000103DE $00010862 $00010AA4 $00010A9B $00350453 $00080C2A $000109A4 $00010DED $00010B73 $00010A6B $00010008 $00010212 $0001065B $00010D2D $00010C21 $00010C2A $00010B5C $00020DED $00010595 $000105F3 $000108E4 $000109A5 $00010212 $000107DB $0001051B $00010DED $000105CE $000109AF $000109AF $00010185 $000103C5 $000105F3 $0003042B $00010434 $000904DC $00090C2A $00020A13 $00010BE6 $000304DC $00010594 $000519F7 $00010BCB $00010212 $0001065A $0001065B $00010AB4 $000119F7 $0001065A $000103D5 $0001095C $0001075C $00010DB5 $00020185 $00010794 $0015079D $000219F7 $00010C2A $000209AD $00010212 $00040212 $00010453 $00050A1A $00020DED $000105CE $00010DED $00070422 $00010A13 $00010A21 $00010C72 $0006079D $0001079D $00010219 $0001165B $00020185 $000203D5 $00020BE6 $0001065B $00030FBD $000308DC $0005065B $00010C2A $0002095C $00010422 $00030A13 $00030C2A $00020185 $000103D5 $00010FBD $000303D5 $0009079D $00010434 $00010A20 $00020C2A $00010EFC $00010595 $000109A5 $00060B5E $00010A13 $00010A6B $00020422 $00020A21 $00010A6B $00020C72 $00010FBD $00020042 $00010212 $00010862 $00050C72 $000105F3 $0001091B $0001079C $00010434 $00010212 $00020083 $00030633 $00020C2A $006803D5 $0002079D $000A0DED $00010D7E $00010BE7 $0001042B $00010434 $000204DC $0004060A $00020862 $0002079D $00010C2A $00010212 $00010A31 $00010C2A $00010219 $00060BF6 $00011830 $00010453 $00030863 $000608E4 $00020DED $00050DED $000106EA $0001051B $0001061D $000108DC $0001051B $00020434 $00050453 $0001049B $00010C2A $000203D5 $00010663 $00020619 $000119F7 $000306CA $00010544 $00010419 $0001051B $0001038D $00010594 $0001031D $0001065B $000109A5 $000109AF $00010434 $000A0453 $00040862 $00020594 $0001079C $0001079D $000419F7 $000119F7 $0001024A $00010185 $000103D5 $00010212 $0002065B $00010C2A $00100594 $0002079D $000309A4 $004809A5 $00390DB5 $00020A31 $000103D5 $000109A5 $00010DED $000309A5 $0001095C $00250A9B $000205F3 $000105DE $0002064A $00010554 $00021830 $0001091B $00010C2A $0001079C $000108ED $00010BF6 $00020594 $000106E1 $00010A1A $00010BE6 $00020B5C $00021830 $000105DE $0001079C $00010DED $000102C4 $00010434 $00010C2A $00010212 $00010C2A $0001031E $00010185 $000103D5 $0001091B $0001079C $00020A9B $00020291 $0001030B $000205CE $000106E4 $000408E4 $000103D5 $00140595 $000B0713 $001509A5 $000105EC $000105F3 $00010452 $0001079D $00010DED $00010185 $00040713 $000409A5 $00010A31 $000106D4 $0001065B $00010C21 $00010794 $00010452 $00010A20 $00020212 $00011830 $000109A5 $0001065B $0001079D $00010595 $00010452 $000106CA $0001065A $000107ED $0001079D $00010DB5 $00020212 $00010422 $00020453 $0001079C $00010BCB $0002091B $00010212 $00010A9B $000103D5 $000209A5 $00010419 $00040B5C $003D079C $00010566 $000205DE $00020726 $00010452 $00010A20 $0001079D $00010212 $00011830 $00010A20 $00010764 $0002061A $00030863 $000208E4 $00010B7C $00010A1A $000203D5 $00030212 $00010453 $00020C2A $00010434 $000203D5 $000107CD $0001079D $00020A13 $00010619 $00010219 $000103D5 $000109A5 $0001079C $00010863 $00010C2A $00010C72 $00050252 $000408DC $00050C2A $0002049C $00080453 $0008065B $00030C72 $00010DED $00010A31 $00011830 $000305F3 $00010BF6 $00011830 $00010BF6 $00010A13 $0002062A $00030219 $00020594 $000109A5 $00030422 $000104CA $000209AF $00010C72 $00011453 $000106DC $00010452 $000109A5 $0001075C $00010DB5 $00010FBD $000103D5 $00010BD4 $00040DED $000119F7 $0001065A $0001042B $000109A5 $00010DB5 $00030452 $00010C2A $00020594 $0005079C $00030BCB $00010BDD $00040DED $00040594 $00070595 $00010BCB $00080BE6 $00010212 $0001165B $00041830 $00020B5C $00010042 $00010B5C $00011810 $000206CA $00010DBD $00010185 $00010BE6 $00010AE4 $0001079D $0019079C $000119F7 $000407D6 $00010594 $00010303 $000119F7 $00010434 $000106D4 $0001051B $00040DB5 $00130DED $00010043 $00040219 $00010AB4 $00020DED $00010115 $0001051B $000105DE $000105F3 $00020185 $000203D5 $0002079D $00010452 $000109A4 $00010A13 $00061810 $0006092A $00010452 $00060291 $00010A0C $00010C2A $00010A31 $0004051B $0002070D $0001079D $000207CD $000107D6 $000D09A5 $00050DB5 $00100DED $000219A4 $0003038D $00040594 $000419F7 $00010DED $000203D5 $0001079D $00040DED $00010BE6 $000207DC $00010DED $00010713 $00010452 $0001051B $000109A5 $00010619 $000203DE $000809A4 $000203D5 $00D20594 $00200595 $0003079C $0017079D $008309A4 $003A09A5 $00060DB5 $000B0DED $00010C2A $00010DED $000106D4 $00010A0C $00010594 $00010356 $0001065A $0004065B $0001079D $00021830 $00010212 $00010C2A $000408ED $00010DED $000109A5 $000107D6 $0001091B $0027051B $00010DB5 $00020212 $00010C2A $00030042 $00010419 $00010DB5 $000108DC $00010AF4 $0006055C $0001055C $0001079C $0001049B $00011830 $0001038C $00010BE6 $000119D7 $000106D5 $00030A21 $00030C72 $000109A5 $00020A21 $00010E7A $00200185 $001703D5 $000F09A5 $000A0DB5 $0001070D $0002079C $0007079D $00011810 $00010DED $00020862 $00030863 $00060C2A $000107D6 $00010BD4 $00010DB5 $00020DED $0001079D $00010B63 $00010BD4 $00010BCB $00010BE6 $00020043 $00010863 $00080663 $00060594 $00040595 $000909A4 $000509A5 $00040DB5 $000D0DED $00020A31 $00320212 $00040C2A $00040C72 $000108DC $000107D6 $00010BD4 $00010453 $00010C72 $000105DE $000107CD $00030453 $0005065B $00030C72 $00010422 $00010A1A $00010DB5 $0001079D $00020BE6 $00010212 $000105F3 $00010713 $00010BE6 $00010453 $0001065B $00010DED $00010BCB $00030DED $00010212 $00010C2A $00010422 $00011830 $0002061B $004C0A9B $00020422 $000106DC $00010453 $000209A5 $0001091B $00010B63 $00020863 $00090452 $0001065A $0001065B $00010E7A $00031043 $00020C2A $00020964 $00010042 $00010419 $00010DB5 $000103D5 $000109A5 $0001095C $000106D5 $000106D4 $00010422 $00010434 $00010A13 $00010A21 $00010A6A $00060A6B $00030C2A $00010C72 $0002079C $00010452 $00050A1A $000119F7 $00010DAD $00010594 $0025051B $00010422 $00010A1A $00010A21 $000203DE $000107DE $000105F3 $000107DD $00020BAD $0002071D $00010A31 $00010A1A $00010C21 $00010C2A $00010212 $000103D5 $000103DE $00010594 $000109A4 $000103D5 $00010DED $000106D5 $00010619 $00010A13 $00050C2A $00021453 $00020DED $00020212 $00020312 $0002051B $0001055C $00010291 $000103D5 $000105CE $00010A6B $0001079C $00010BE6 $00010BE6 $00010042 $000603D5 $0002079D $000309A5 $00020564 $00010DED $00020595 $00070042 $00010419 $00010212 $00010603 $00040862 $000203D5 $00011FBC $000302D2 $00010115 $000407D6 $00010B5E $0001038D $00030594 $00010595 $000209A5 $00020DB5 $00010A21 $00010A20 $00020594 $000108F4 $000109A5 $000A0DED $00010863 $000105E5 $00020BE6 $00020A13 $00010DE6 $00010619 $00010595 $00030713 $000105F3 $00020824 $00010863 $00010C2A $000105DE $00010C2A $000109A5 $00020212 $00010C72 $000104DC $00010212 $0009079C $001C0BCB $0001079C $00030713 $00010BE6 $00020B5E $000103D5 $0001091B $00040422 $00010434 $00010DED $00020AA4 $00010862 $00010219 $00010C2A $00010219 $00010621 $00010D3B $00020219 $0001099D $000208DC $00290453 $00EF065B $01DC0863 $00290C2A $00030C72 $0001079D $00010DB4 $000119F7 $0001065B $000203D5 $000107D6 $00010FBD $00020594 $00010595 $0001071B $000109A5 $00010544 $00010C2A $00010043 $00150452 $000203DE $0001061B $0008065B $000119F7 $00020BE6 $0006079D $00380DED $000105CE $0007091B $00020DED $00010DED $001519F7 $000103D5 $000209A5 $00020DB5 $0001065B $00020DED $0001051B $000109A5 $000103DE $00060594 $00010185 $0001079D $000303D5 $00010A1A $000207D6 $00020594 $00020595 $00030BE6 $00070DED $000107C4 $00010DB5 $0001062A $00070A6B $00030212 $00010C2A $00010C72 $0001079C $0004092B $00010BD4 $00011830 $00010E7A $00020862 $00010506 $00010452 $00020302 $00010D3B $000103D5 $00010594 $000109A4 $00010DED $0001079D $000109B4 $000A0185 $000F03D5 $000C0DED $00010212 $00010594 $00010DED $00010422 $00010A1A $00010BE6 $00010FBD $000806E4 $00010668 $00010DED $00040FBD $000119F7 $0002095C $00010BE6 $000503DE $0001065B $0001065A $00010A0C $0004079D $00010BCB $00020212 $0001065A $00031830 $00030252 $00010453 $0001065B $0002079D $000209A5 $00010DB5 $00010008 $00010422 $00010A0C $0001051B $000207CD $00010212 $00010595 $00020BE6 $00010FBD $000103D5 $00010313 $00011830 $00010920 $00010A6B $00021830 $000203D5 $00020723 $00130BCB $00090DED $00010A6B $0005065B $00010A1A $00020A21 $00010212 $0007065B $00011453 $000719F7 $000203D5; !C static int compare_bk(const void *ap, const void *bp) !C { !C const struct bk *a = ap; !C const struct bk *b = bp; !C if (a->hash < b->hash) return -1; !C if (a->hash > b->hash) return 1; !C return (int)a->move - (int)b->move; !C } !C static void compact_book(void) !C { !C long b = 0, c = 0; !C qsort(book, booksize, sizeof(*book), compare_bk); !C while (b= 0) { !C s = line; !C for (;;) { !C move = parse_move(s, &num); !C if (!move) break; !C s += num; !C if (booksize < CORE) { !C compute_hash(); !C book[booksize].hash = hash; !C book[booksize].move = move; !C book[booksize].count = 1; !C booksize++; !C if (booksize >= CORE) compact_book(); !C } !C make_move(move); !C } !C while (ply>0) unmake_move(); /* wrong */ !C } !C fclose(fp); !C compact_book(); !C } !C static int book_move(void) !C { !C int move = 0, sum = 0; !C long x = 0, y, m; !C char *seperator = "book:"; !C if (!booksize) return 0; !C y = booksize; !C compute_hash(); !C while (y-x > 1) { /* inv: book.hash[x] <= hash < book.hash[y] */ !C m = (x + y) / 2; !C if (hash < book[m].hash) { y=m; } else { x=m; } !C } !C while (book[x].hash == hash) { !C printf("%s (%d)", seperator, book[x].count); !C seperator = ","; !C print_move_san(book[x].move); !C compute_hash(); !C sum += book[x].count; !C if (rnd()%sum < book[x].count) { !C move = book[x].move; !C } !C if (!x--) break; !C } !C putchar('\n'); !C return move; !C } Array mscp_book_move_book string "book:"; [ mscp_book_move _move sum x y m first bcount bmove; #Ifdef MSCP_DEBUG; print "[MSCP> book_move]^"; #Endif; _move = 0; sum = 0; x = 0; first = true; y = MSCP_C_BOOKSIZE; mscp_compute_hash (); while (y - x > 1) { ! inv: book.hash[x] <= hash < book.hash[y] m = (x + y) / 2; if (mscp_hash < mscp_book_data_hash-->m) { y = m; } else { x = m; } } while (x > 0 && mscp_book_data_hash-->x == mscp_hash) { bcount = mscp_book_data_pack-->x / 65536; ! Inform note - bmove = mscp_book_data_pack-->x & $FFFF; ! unpack data if (first) { mscp_print_string (mscp_book_move_book); first = false; } else mscp_print_char (','); mscp_print_char (' '); mscp_print_char ('('); mscp_print_number (bcount); mscp_print_char (')'); mscp_print_move_san (bmove); mscp_compute_hash (); sum = sum + bcount; if (random (sum) - 1 < bcount) { _move = bmove; } x--; } mscp_print_char ('^'); return _move; ]; !C /*----------------------------------------------------------------------+ !C | evaluator | !C +----------------------------------------------------------------------*/ !C static int center[64] = { !C 0, 2, 3, 4, 4, 3, 2, 0, !C 2, 3, 4, 5, 5, 4, 3, 2, !C 3, 4, 5, 7, 7, 5, 4, 3, !C 4, 5, 7, 10, 10, 7, 5, 4, !C 4, 5, 7, 10, 10, 7, 5, 4, !C 3, 4, 5, 7, 7, 5, 4, 3, !C 2, 3, 4, 5, 5, 4, 3, 2, !C 0, 2, 3, 4, 4, 3, 2, 0, !C }; Array mscp_center -> 0 2 3 4 4 3 2 0 2 3 4 5 5 4 3 2 3 4 5 7 7 5 4 3 4 5 7 10 10 7 5 4 4 5 7 10 10 7 5 4 3 4 5 7 7 5 4 3 2 3 4 5 5 4 3 2 0 2 3 4 4 3 2 0; !C static int pawn_advance[64] = { !C 0, 0, 2, 3, 5, 30, 50, 0, !C 0, 0, 2, 3, 5, 30, 50, 0, !C 0, 0, 2, 3, 5, 30, 50, 0, !C 0, -5, 2, 8, 8, 30, 50, 0, !C 0, -5, 2, 8, 8, 30, 50, 0, !C 0, 0, 2, 3, 5, 30, 50, 0, !C 0, 0, 2, 3, 5, 30, 50, 0, !C 0, 0, 2, 3, 5, 30, 50, 0, !C }; Array mscp_pawn_advance --> 0 0 2 3 5 30 50 0 0 0 2 3 5 30 50 0 0 0 2 3 5 30 50 0 0 (-5) 2 8 8 30 50 0 0 (-5) 2 8 8 30 50 0 0 0 2 3 5 30 50 0 0 0 2 3 5 30 50 0 0 0 2 3 5 30 50 0; !C #define DIFF(a,b) ((a)>(b) ? (a)-(b) : (b)-(a)) !C #define TAXI(a,b) (DIFF(F(a),F(b)) + DIFF((a),(b))) [ MSCP_DIFF a b; if (a > b) return (a - b); else return (b - a); ]; [ MSCP_TAXI a b; return (MSCP_DIFF (MSCP_F (a), MSCP_F (b)) + MSCP_DIFF (a, b)); ]; !C static void compute_piece_square_tables(void) !C { !C int pc, sq; !C int score = 0; !C int file; !C compute_attacks(); /* so we know where the king and pawns are */ !C for (sq=0; sq<64; sq++) { !C file = 1+F(sq); !C for (pc=1; pc<13; pc++) { !C switch (pc) { !C case WHITE_KNIGHT: !C score = 300; !C score += center[sq]; !C score -= TAXI(black.king, sq); !C break; !C case BLACK_KNIGHT: !C score = -300; !C score -= center[sq]; !C score += TAXI(white.king, sq); !C break; !C case WHITE_BISHOP: !C score = +300; !C break; !C case BLACK_BISHOP: !C score = -300; !C break; !C case WHITE_ROOK: !C score = +500; !C score += DIFF(F(black.king), F(sq)); !C break; !C case BLACK_ROOK: !C score = -500; !C score -= DIFF(F(white.king), F(sq)); !C break; !C case WHITE_QUEEN: !C score = +900; !C score += center[sq]; !C break; !C case BLACK_QUEEN: !C score = -900; !C score -= center[sq]; !C break; !C case WHITE_KING: !C score = +400; !C score += center[sq]; !C break; !C case BLACK_KING: !C score = -400; !C score -= center[sq]; !C break; !C case WHITE_PAWN: !C score = +100; !C score += pawn_advance[sq]; !C if (!black.pawns[file]) { !C score += pawn_advance[sq]; !C } !C break; !C case BLACK_PAWN: !C score = -100; !C score -= pawn_advance[FLIP(sq)]; !C if (!white.pawns[file]) { !C score -= pawn_advance[FLIP(sq)]; !C } !C break; !C } !C piece_square[pc-1][sq] = score; !C } !C } !C piece_square[WHITE_KING-1][G1] += 100; !C piece_square[BLACK_KING-1][G8] -= 100; !C } [ mscp_compute_piece_square_tables pc sq _score file i; #Ifdef MSCP_DEBUG; print "[MSCP> compute_piece_square_tables]^"; #Endif; _score = 0; mscp_compute_attacks (); ! so we know where the king & pawns are for (sq = 0: sq < 64: sq++) { file = 1 + MSCP_F (sq); for (pc = 1: pc < 13: pc++) { switch (pc) { MSCP_C_WHITE_KNIGHT: _score = ( 300); _score = _score + mscp_center->sq; _score = _score - MSCP_TAXI (mscp_black_king, sq); MSCP_C_BLACK_KNIGHT: _score = (-300); _score = _score - mscp_center->sq; _score = _score + MSCP_TAXI (mscp_white_king, sq); MSCP_C_WHITE_BISHOP: _score = ( 300); MSCP_C_BLACK_BISHOP: _score = (-300); MSCP_C_WHITE_ROOK: _score = ( 500); _score = _score + MSCP_DIFF (MSCP_F (mscp_black_king), MSCP_F (sq)); MSCP_C_BLACK_ROOK: _score = (-500); _score = _score - MSCP_DIFF (MSCP_F (mscp_white_king), MSCP_F (sq)); MSCP_C_WHITE_QUEEN: _score = ( 900); _score = _score + mscp_center->sq; MSCP_C_BLACK_QUEEN: _score = (-900); _score = _score - mscp_center->sq; MSCP_C_WHITE_KING: _score = ( 400); _score = _score + mscp_center->sq; MSCP_C_BLACK_KING: _score = (-400); _score = _score - mscp_center->sq; MSCP_C_WHITE_PAWN: _score = ( 100); _score = _score + mscp_pawn_advance-->sq; if (mscp_black_pawns->file == 0) { _score = _score + mscp_pawn_advance-->sq; } MSCP_C_BLACK_PAWN: _score = (-100); _score = _score - mscp_pawn_advance--> (MSCP_FLIP (sq)); if (mscp_white_pawns->file == 0) { _score = _score - mscp_pawn_advance--> (MSCP_FLIP (sq)); } } mscp_piece_square-->((pc - 1) * 64 + sq) = _score; } } i = (MSCP_C_WHITE_KING - 1) * 64 + MSCP_C_G1; mscp_piece_square-->i = mscp_piece_square-->i + 100; i = (MSCP_C_BLACK_KING - 1) * 64 + MSCP_C_G8; mscp_piece_square-->i = mscp_piece_square-->i - 100; ]; !C static int white_control[64] = { !C 1, 1, 1, 1, 2, 2, 2, 2, !C 1, 1, 1, 1, 2, 2, 2, 2, !C 1, 1, 2, 2, 3, 3, 2, 2, !C 1, 1, 2, 5, 6, 3, 2, 2, !C 1, 1, 2, 5, 6, 3, 2, 2, !C 1, 1, 2, 2, 3, 3, 2, 2, !C 1, 1, 1, 1, 2, 2, 2, 2, !C 1, 1, 1, 1, 2, 2, 2, 2, !C }; Array mscp_white_control -> 1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2 1 1 2 2 3 3 2 2 1 1 2 5 6 3 2 2 1 1 2 5 6 3 2 2 1 1 2 2 3 3 2 2 1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2; !C static int evaluate(void) !C { !C int sq; !C int score = 0; !C int white_has, black_has; !C /* !C * stage 1: material+piece_square tables !C */ !C for (sq=0; sq<64; sq++) { !C int file; !C if (board[sq] == EMPTY) continue; !C score += piece_square[board[sq]-1][sq]; !C file = F(sq)+1; !C switch (board[sq]) { !C case WHITE_PAWN: !C { !C int missing; !C if (white.pawns[file] > 1) { !C score -= 15; !C } !C missing = !white.pawns[file-1] + !white.pawns[file+1] + !C !black.pawns[file]; !C score -= missing * missing * 5; !C break; !C } !C case BLACK_PAWN: !C { !C int missing; !C if (black.pawns[file] > 1) { !C score -= 15; !C } !C missing = !black.pawns[file-1] + !black.pawns[file+1] + !C !white.pawns[file]; !C score += missing * missing * 5; !C break; !C } !C case WHITE_ROOK: !C if (!white.pawns[file]) { !C score += 10; !C if (!black.pawns[file]) { !C score += 10; !C } !C } !C break; !C case BLACK_ROOK: !C if (!black.pawns[file]) { !C score -= 10; !C if (!white.pawns[file]) { !C score -= 10; !C } !C } !C break; !C default: !C break; !C } !C } !C /* !C * stage 2: board control !C */ !C white_has = 0; !C black_has = 0; !C for (sq=0; sq<64; sq++) { !C if (white.attack[sq] > black.attack[sq]) { !C white_has += white_control[sq]; !C } !C if (white.attack[sq] < black.attack[sq]) { !C black_has += white_control[FLIP(sq)]; !C } !C } !C score += (white_has - black_has); !C return WTM ? score : -score; !C } [ mscp_evaluate sq _score white_has black_has file missing; #Ifdef MSCP_DEBUG; print "[MSCP> evaluate]^"; #Endif; _score = 0; ! ! stage 1: material+piece_square tables ! for (sq = 0: sq < 64: sq++) { if (mscp_board->sq == MSCP_C_EMPTY) continue; _score = _score + mscp_piece_square-->((mscp_board->sq - 1) * 64 + sq); file = MSCP_F (sq) + 1; switch (mscp_board->sq) { MSCP_C_WHITE_PAWN: if (mscp_white_pawns->file > 1) { _score = _score - 15; } missing = (mscp_white_pawns->(file - 1) == 0) + (mscp_white_pawns->(file + 1) == 0) + (mscp_black_pawns->file == 0); _score = _score - (missing * missing * 5); MSCP_C_BLACK_PAWN: if (mscp_black_pawns->file > 1) { _score = _score - 15; } missing = (mscp_black_pawns->(file - 1) == 0) + (mscp_black_pawns->(file + 1) == 0) + (mscp_white_pawns->file == 0); _score = _score + (missing * missing * 5); MSCP_C_WHITE_ROOK: if (mscp_white_pawns->file == 0) { _score = _score + 10; if (mscp_black_pawns->file == 0) { _score = _score + 10; } } MSCP_C_BLACK_ROOK: if (mscp_black_pawns->file == 0) { _score = _score - 10; if (mscp_white_pawns->file == 0) { _score = _score - 10; } } } } ! ! stage 2: board control ! white_has = 0; black_has = 0; for (sq = 0: sq < 64: sq++) { if (mscp_white_attack->sq > mscp_black_attack->sq) { white_has = white_has + mscp_white_control->sq; } if (mscp_white_attack->sq < mscp_black_attack->sq) { black_has = black_has + mscp_white_control->(MSCP_FLIP (sq)); } } _score = _score + (white_has - black_has); ! ! Inform note - keepalive call, makes a callback to caller code ! for Glk tick and keeping the display current; we cycle here around ! a couple of hundred times each second. ! #Ifndef MSCP_NO_TICK_CHECK; mscp_tick_check (); #Endif; if (MSCP_WTM ()) return _score; else return -(_score); ]; ! /*----------------------------------------------------------------------+ ! | sort | ! +----------------------------------------------------------------------*/ [ mscp_moves_swap x y temp; if (x == y) return; ! swap both move and prescore temp = mscp_move_stack_move-->x; mscp_move_stack_move-->x = mscp_move_stack_move-->y; mscp_move_stack_move-->y = temp; temp = mscp_move_stack_prescore-->x; mscp_move_stack_prescore-->x = mscp_move_stack_prescore-->y; mscp_move_stack_prescore-->y = temp; ]; [ mscp_compare_moves x y; if (mscp_move_stack_prescore-->x < mscp_move_stack_prescore-->y) return -1; if (mscp_move_stack_prescore-->x > mscp_move_stack_prescore-->y) return 1; return mscp_move_stack_move-->x - mscp_move_stack_move-->y; ! this makes sort deterministic ]; [ mscp_qsort_moves lo hi i j p; if (lo >= hi) return; ! quicksort if more than 5 elements, otherwise bubble sort if (hi - lo > 5) { i = lo; for (p = lo - 1: i < hi: i++) { if (mscp_compare_moves (i, hi) < 0) { mscp_moves_swap (i, ++p); } } mscp_qsort_moves (lo, p); for (i = p + 1: i <= hi: i++) { if (mscp_compare_moves (i, hi) <= 0) { mscp_moves_swap (i, ++p); } } mscp_qsort_moves (p + 1, hi); } else { for (i = hi: i > lo: i--) { for (j = lo: j < i: j++) { if (mscp_compare_moves (i, j) < 0) mscp_moves_swap (i, j); } } } ]; !C /*----------------------------------------------------------------------+ !C | search | !C +----------------------------------------------------------------------*/ !C static int qsearch(int alpha, int beta) !C { !C int best_score; !C int score; !C struct move *moves; !C nodes++; !C best_score = evaluate(); !C if (best_score >= beta) { !C return best_score; !C } !C moves = move_sp; !C generate_moves(PRESCORE_EQUAL + (1<<9)); !C qsort(moves, move_sp - moves, sizeof(*moves), compare_move); !C while (move_sp > moves) { !C int move; !C move_sp --; !C move = move_sp->move; !C make_move(move); !C compute_attacks(); !C if (friend->attack[enemy->king]) { !C unmake_move(); !C continue; !C } !C score = - qsearch(-beta, -alpha); !C unmake_move(); !C if (score <= best_score) { !C continue; !C } !C best_score = score; !C if (score <= alpha) { !C continue; !C } !C alpha = score; !C if (score < beta) { !C continue; !C } !C move_sp = moves; /* fail high: skip remaining moves */ !C } !C return best_score; !C } [ mscp_qsearch alpha beta best_score _score moves _move; #Ifdef MSCP_DEBUG; print "[MSCP> qsearch ", alpha, ", ", beta, "]^"; #Endif; mscp_nodes++; best_score = mscp_evaluate (); if (best_score >= beta) { return best_score; } #Ifndef MSCP_NO_UNWIND; if (mscp_unwind_requested) ! Inform special return best_score; ! Inform special #Endif; moves = mscp_move_sp; mscp_generate_moves (MSCP_C_PRESCORE_EQUAL + 512); mscp_qsort_moves (moves, mscp_move_sp - 1); while (mscp_move_sp > moves) { mscp_move_sp--; _move = mscp_move_stack_move-->mscp_move_sp; mscp_make_move (_move); mscp_compute_attacks (); if (mscp_friend_attack->mscp_enemy_king) { mscp_unmake_move (); continue; } _score = -(mscp_qsearch (-beta, -alpha)); mscp_unmake_move (); #Ifndef MSCP_NO_UNWIND; if (mscp_unwind_requested) { ! Inform special mscp_move_sp = moves; ! Inform special break; ! Inform special } ! Inform special #Endif; if (_score <= best_score) { continue; } best_score = _score; if (_score <= alpha) { continue; } alpha = _score; if (_score < beta) { continue; } mscp_move_sp = moves; ! fail high: skip remaining moves } return best_score; ]; !C static int search(int depth, int alpha, int beta) !C { !C int best_score = -INF; !C int best_move = 0; !C int score; !C struct move *moves; !C int incheck = 0; !C struct tt *tt; !C unsigned long h; !C int oldalpha, oldbeta; !C oldalpha = alpha; !C oldbeta = beta; !C nodes++; !C /* !C * test for draw by repetition !C */ !C h = hash; !C /* !C * check transposition table !C */ !C tt = &ttable[((h>>16) & (CORE-1))]; !C if (tt->hash == (h & 0xffffU)) { !C if (tt->depth >= depth) { !C if (tt->flag >= 0) alpha = tt->score; !C if (tt->flag <= 0) beta = tt->score; !C if (alpha >= beta) return tt->score; !C } !C best_move = tt->move & 07777; !C } !C history[best_move] |= PRESCORE_HASHMOVE; !C incheck = enemy->attack[friend->king]; !C /* !C * generate moves !C */ !C moves = move_sp; !C generate_moves(0); !C history[best_move] &= 0x3fff; !C best_move = 0; !C qsort(moves, move_sp - moves, sizeof(*moves), compare_move); !C /* !C * loop over all moves !C */ !C while (move_sp > moves) { !C int newdepth; !C int move; !C move_sp --; !C move = move_sp->move; !C make_move(move); !C compute_attacks(); !C if (friend->attack[enemy->king]) { !C unmake_move(); !C continue; !C } !C newdepth = incheck ? depth : depth-1; !C if (newdepth <= 0) { !C score = -qsearch(-beta, -alpha); !C } else { !C score = -search(newdepth, -beta, -alpha); !C } !C if (score < -29000) score++; !C unmake_move(); !C if (score <= best_score) { !C continue; !C } !C best_score = score; !C best_move = move; !C if (score <= alpha) { !C continue; !C } !C alpha = score; !C if (score < beta) { !C continue; !C } !C move_sp = moves; /* fail high: skip remaining moves */ !C } !C if (best_score == -INF) { /* deal with mate and stalemate */ !C if (incheck) { !C best_score = -30000; !C } else !C best_score = 0; !C } !C history[best_move & 07777] += depth*depth; !C if (history[best_move & 07777] > 511) { !C int m; !C for (m=0; m>= 4; !C } !C } !C tt->hash = h & 0xffffU; !C tt->move = best_move; !C tt->score = best_score; !C tt->depth = depth; !C tt->flag = (oldalpha < best_score) - (best_score < oldbeta); !C return best_score; !C } [ mscp_search depth alpha beta best_score best_move _score moves incheck tt h oldalpha oldbeta newdepth _move i m count; #Ifdef MSCP_DEBUG; print "[MSCP> search ", depth, ", ", alpha, ", ", beta, "]^"; #Endif; best_score = -MSCP_C_INF; best_move = 0; incheck = 0; oldalpha = alpha; oldbeta = beta; mscp_nodes++; ! ! test for draw by repetition ! h = mscp_hash; ! ! check transposition table ! tt = (h / 65536) & (MSCP_C_CORE - 1); ! ! Inform note - check the full hash code in tables ! if (mscp_ttable_hash-->tt == h) { if (mscp_ttable_depth->tt >= depth) { if (mscp_ttable_flag->tt - 1 >= 0) ! Inform note - alpha = mscp_ttable_score-->tt; ! here we sub- if (mscp_ttable_flag->tt - 1 <= 0) ! tract the 1 beta = mscp_ttable_score-->tt; ! added to flag if (alpha >= beta) return mscp_ttable_score-->tt; } best_move = mscp_ttable_move-->tt & $FFF; } mscp_history-->best_move = mscp_history-->best_move | MSCP_C_PRESCORE_HASHMOVE; incheck = mscp_enemy_attack->mscp_friend_king; ! ! generate moves ! moves = mscp_move_sp; mscp_generate_moves (0); mscp_history-->best_move = mscp_history-->best_move & $3FFF; best_move = 0; mscp_qsort_moves (moves, mscp_move_sp - 1); ! ! loop over all moves ! count = 0; while (mscp_move_sp > moves) { mscp_move_sp--; _move = mscp_move_stack_move-->mscp_move_sp; mscp_make_move (_move); mscp_compute_attacks (); if (mscp_friend_attack->mscp_enemy_king) { mscp_unmake_move (); continue; } if (incheck) newdepth = depth; else newdepth = depth - 1; if (newdepth <= 0) { _score = -(mscp_qsearch (-beta, -alpha)); } else { _score = -(mscp_search (newdepth, -beta, -alpha)); } if (_score < -29000) _score++; mscp_unmake_move (); #Ifndef MSCP_NO_UNWIND; if (mscp_unwind_requested) { ! Inform special mscp_move_sp = moves; ! Inform special break; ! Inform special } ! Inform special #Endif; if (_score <= best_score) { continue; } best_score = _score; best_move = _move; if (_score <= alpha) { continue; } alpha = _score; if (_score < beta) { continue; } mscp_move_sp = moves; ! fail high: skip remaining moves } if (best_score == -MSCP_C_INF) {! deal with mate and stalemate if (incheck) { best_score = -30000; } else best_score = 0; } #Ifndef MSCP_NO_UNWIND; if (mscp_unwind_requested) ! Inform special return best_score; ! Inform special #Endif; i = best_move & $FFF; mscp_history-->i = mscp_history-->i + (depth * depth); if (mscp_history-->i > 511) { for (m = 0: m < MSCP_C_SPECIAL: m++) { mscp_history-->m = mscp_history-->m / 16; } } ! ! Inform note - put the full hash code in tables, since there is space ! mscp_ttable_hash-->tt = h; mscp_ttable_move-->tt = best_move; mscp_ttable_score-->tt = best_score; mscp_ttable_depth->tt = depth; mscp_ttable_flag->tt = (oldalpha < best_score) ! Inform note - - (best_score < oldbeta) + 1; ! save flag + 1 return best_score; ]; !C static unsigned short squeeze(unsigned long n) /* reduces long int to short */ !C { !C const unsigned long mask = ~0U<<11; !C unsigned short s; !C for (s=0; n&mask; n>>=1, s-=mask) !C /* SKIP */; !C return s | n; !C } !C static int root_search(int maxdepth) !C { !C int depth; !C int score, best_score; !C int move = 0; !C int alpha, beta; !C unsigned long node; !C struct move *m; !C nodes = 0; !C compute_piece_square_tables(); !C generate_moves(0); !C qsort(move_stack, move_sp-move_stack, sizeof(struct move), compare_move); !C alpha = -INF; !C beta = +INF; !C puts(" nodes ply score move"); !C for (depth = 1; depth <= maxdepth; depth++) { !C m = move_stack; !C best_score = -32768; !C node = nodes; !C while (m < move_sp) { !C make_move(m->move); !C compute_attacks(); !C if (friend->attack[enemy->king] != 0) { /* illegal? */ !C unmake_move(); !C *m = *--move_sp; /* drop this move */ !C continue; !C } !C if (depth-1 > 0) { !C score = -search(depth-1, -beta, -alpha); !C } else { !C score = -qsearch(-beta, -alpha); !C } !C unmake_move(); !C if (score>=beta || (score<=alpha && m==move_stack)) { !C alpha = -INF; beta = +INF; !C continue; /* re-search this move */ !C } !C m->prescore = ~squeeze(nodes-node); !C node = nodes; !C if (score > best_score) { !C best_score = score; !C alpha = score; !C beta = score + 1; !C move = m->move; !C *move_sp = *move_stack; /* swap */ !C *move_stack = *m; !C *m = *move_sp; !C } !C m++; /* continue with next move */ !C } !C printf(" %5lu %3d %+1.2f ", nodes, depth, best_score / 100.0); !C print_move_san(move_stack->move); !C puts(""); !C if (move_sp-move_stack <= 1) { !C break; /* just one move to play */ !C } !C /* sort remaining moves in descending order of subtree size */ !C qsort(move_stack+1, move_sp-move_stack-1, sizeof(*m), compare_move); !C alpha = best_score - 33; !C beta = best_score + 33; !C } !C move_sp = move_stack; !C return move; !C } Array mscp_root_search_hdr string " nodes ply score move^"; [ mscp_root_search maxdepth depth _score best_score _move alpha beta node m temp; #Ifdef MSCP_DEBUG; print "[MSCP> root_search ", maxdepth, "]^"; #Endif; _move = 0; mscp_nodes = 0; mscp_compute_piece_square_tables (); mscp_generate_moves (0); mscp_qsort_moves (0, mscp_move_sp - 1); alpha = -MSCP_C_INF; beta = MSCP_C_INF; mscp_print_string (mscp_root_search_hdr); for (depth = 1: depth <= maxdepth: depth++) { m = 0; best_score = -32768; node = mscp_nodes; while (m < mscp_move_sp) { mscp_make_move (mscp_move_stack_move-->m); mscp_compute_attacks (); if (mscp_friend_attack->mscp_enemy_king ~= 0) { ! illegal? mscp_unmake_move (); mscp_moves_swap (m, --mscp_move_sp); ! drop this move continue; } if (depth - 1 > 0) { _score = -(mscp_search (depth - 1, -beta, -alpha)); } else { _score = -(mscp_qsearch (-beta, -alpha)); } mscp_unmake_move (); if (_score >= beta || (_score <= alpha && m == 0)) { alpha = -MSCP_C_INF; beta = MSCP_C_INF; continue; ! re-search this move } ! ! Inform note - the following line sets a -ve prescore ! for sorting; this is intentional. The original ! mscp "squeezes" a long into an unsigned short, then ! inverts the bits to get a larger-is-better value. ! Here, we just use the raw -ve value, and still ! larger-is-better since the smallest -ve is sorted. ! mscp_move_stack_prescore-->m = node - mscp_nodes; node = mscp_nodes; if (_score > best_score) { best_score = _score; alpha = _score; beta = _score + 1; _move = mscp_move_stack_move-->m; mscp_moves_swap (m, 0); ! swap m to top } m++; ! continue with next move #Ifndef MSCP_NO_UNWIND; if (mscp_unwind_requested && _move ~= 0)! Inform special break; ! Inform special #Endif; } mscp_print_char (' '); mscp_print_number (mscp_nodes, 5); mscp_print_char (' '); mscp_print_number (depth, 3); mscp_print_char (' '); temp = best_score; if (temp >= 0) mscp_print_char ('+'); else { mscp_print_char ('-'); temp = -(temp); } mscp_print_number (temp / 100); mscp_print_char ('.'); mscp_print_number (temp % 100, 2, true); mscp_print_char (' '); mscp_print_move_san (mscp_move_stack_move-->0); mscp_print_char ('^'); if (mscp_move_sp <= 1) { break; ! just one move to play } #Ifndef MSCP_NO_UNWIND; if (mscp_unwind_requested) ! Inform special break; ! Inform special #Endif; ! sort remaining moves in descending order of subtree size mscp_qsort_moves (1, mscp_move_sp - 1); alpha = best_score - 33; beta = best_score + 33; } mscp_move_sp = 0; return _move; ]; !C /*----------------------------------------------------------------------+ !C | commands | !C +----------------------------------------------------------------------*/ ! Inform note -- extra information kept on the last moves made Global mscp_last_white_move = 0; Array mscp_last_white_san -> 11; Global mscp_last_black_move = 0; Array mscp_last_black_san -> 11; [ mscp_note_move _move fr _to; if (MSCP_WTM ()) { mscp_last_white_move = _move; mscp_buffer_move_san (_move, mscp_last_white_san); } else { mscp_last_black_move = _move; mscp_buffer_move_san (_move, mscp_last_black_san); } fr = MSCP_FR (_move); _to = MSCP_TO (_move); if (mscp_board->fr == MSCP_C_WHITE_PAWN || mscp_board->fr == MSCP_C_BLACK_PAWN || mscp_board->_to) mscp_halfmoves = 0; else mscp_halfmoves++; ]; !C static void cmd_bd(char *dummy) !C { !C print_board(); !C } [ mscp_cmd_bd; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_bd]^"; #Endif; mscp_print_board (); return true; ]; !C static void cmd_book(char *dummy) !C { !C int move; !C printf("%ld moves in book\n", booksize); !C move = book_move(); !C if (move) { !C print_move_san(move); !C puts(" selected"); !C } !C } Array mscp_cmd_book_moves string " moves in book^"; Array mscp_cmd_book_selected string " selected^"; [ mscp_cmd_book _move; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_book]^"; #Endif; mscp_print_number (MSCP_C_BOOKSIZE); mscp_print_string (mscp_cmd_book_moves); _move = mscp_book_move (); if (_move) { mscp_print_move_san (_move); mscp_print_string (mscp_cmd_book_selected); } return true; ]; !C static void cmd_list_moves(char *dummy) !C { !C struct move *m; !C int nmoves = 0; !C puts("moves are:"); !C compute_attacks(); !C m = move_sp; !C generate_moves(0); !C qsort(m, move_sp - m, sizeof(*m), compare_move); !C while (move_sp > m) { !C --move_sp; !C if (test_illegal(move_sp->move)) continue; !C print_move_san(move_sp->move); !C putchar('\n'); !C nmoves ++; !C } !C printf("%d move%s\n", nmoves, nmoves==1 ? "" : "s"); !C } Array mscp_cmd_list_moves_are string "moves are:^"; Array mscp_cmd_list_moves_move string " move"; [ mscp_cmd_list_moves m nmoves; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_list_moves]^"; #Endif; nmoves = 0; mscp_print_string (mscp_cmd_list_moves_are); mscp_compute_attacks (); m = mscp_move_sp; mscp_generate_moves (0); mscp_qsort_moves (m, mscp_move_sp - 1); while (mscp_move_sp > m) { --mscp_move_sp; if (mscp_test_illegal (mscp_move_stack_move-->mscp_move_sp)) { continue; } mscp_print_move_san (mscp_move_stack_move-->mscp_move_sp); mscp_print_char ('^'); nmoves++; } mscp_print_number (nmoves); mscp_print_string (mscp_cmd_list_moves_move); if (nmoves ~= 1) mscp_print_char ('s'); mscp_print_char ('^'); return true; ]; !C static void cmd_default(char *s) !C { !C int move, dummy; !C move = parse_move(s, &dummy); !C if (move) { !C make_move(move); !C print_board(); !C } else { !C puts("no such move or command"); !C } !C } Array mscp_cmd_default_nsm string "no such move or command^"; [ mscp_cmd_default s _move; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_default]^"; #Endif; _move = mscp_parse_move (s); if (_move) { mscp_halfmoves_list-->mscp_redo_lp = mscp_halfmoves; mscp_redo_list-->mscp_redo_lp++ = _move; mscp_note_move (_move); mscp_make_move (_move); mscp_print_board (); return true; } else { mscp_print_string (mscp_cmd_default_nsm); return false; } ]; !C static void cmd_undo(char *dummy) !C { !C if (undo_sp > undo_stack) { !C unmake_move(); !C computer[0] = 0; !C computer[1] = 0; !C } else { !C puts("cannot undo move"); !C } !C } Array mscp_cmd_undo_cant string "cannot undo move^"; [ mscp_cmd_undo; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_undo]^"; #Endif; if (mscp_undo_sp > 0) { mscp_unmake_move (); mscp_computer-->0 = 0; mscp_computer-->1 = 0; if (MSCP_WTM ()) { mscp_last_white_move = 0; mscp_last_white_san->0 = 0; } else { mscp_last_black_move = 0; mscp_last_black_san->0 = 0; } mscp_redo_lp--; mscp_halfmoves = mscp_halfmoves_list-->mscp_redo_lp; ! Inform note -- undo and redo the last two moves to keep ! the last move indicators current if (mscp_redo_lp >= 2) { mscp_unmake_move (); mscp_redo_lp--; mscp_unmake_move (); mscp_redo_lp--; mscp_halfmoves = mscp_halfmoves_list-->mscp_redo_lp; mscp_note_move (mscp_redo_list-->mscp_redo_lp); mscp_make_move (mscp_redo_list-->mscp_redo_lp++); mscp_note_move (mscp_redo_list-->mscp_redo_lp); mscp_make_move (mscp_redo_list-->mscp_redo_lp++); } return true; } else { mscp_print_string (mscp_cmd_undo_cant); return false; } ]; !C static void cmd_both(char *dummy) !C { !C computer[0] = 1; !C computer[1] = 1; !C } [ mscp_cmd_both; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_both]^"; #Endif; mscp_computer-->0 = 1; mscp_computer-->1 = 1; return true; ]; !C static void cmd_white(char *dummy) !C { !C computer[0] = 0; !C computer[1] = 1; !C ply = 0; !C } [ mscp_cmd_white; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_white]^"; #Endif; ! ! Inform note -- this looks wrong, however, it's this way to match ! xboard expectations, and changing it causes strange things to ! happen ! mscp_computer-->0 = 0; mscp_computer-->1 = 1; mscp_ply = 0; return true; ]; !C static void cmd_black(char *dummy) !C { !C computer[0] = 1; !C computer[1] = 0; !C ply = 1; !C } [ mscp_cmd_black; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_black]^"; #Endif; ! Inform note -- see mscp_cmd_white() comments above mscp_computer-->0 = 1; mscp_computer-->1 = 0; mscp_ply = 1; return true; ]; !C static void cmd_force(char *dummy) !C { !C computer[0] = 0; !C computer[1] = 0; !C } [ mscp_cmd_force; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_force]^"; #Endif; mscp_computer-->0 = 0; mscp_computer-->1 = 0; return true; ]; !C static void cmd_go(char *dummy) !C { !C computer[!WTM] = 1; !C computer[WTM] = 0; !C } [ mscp_cmd_go; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_go]^"; #Endif; mscp_computer-->(~~(MSCP_WTM ())) = 1; mscp_computer-->( MSCP_WTM () ) = 0; return true; ]; !C static void cmd_test(char *s) !C { !C int d = maxdepth; !C sscanf(s, "%*s%d", &d); !C root_search(d); !C } [ mscp_cmd_test d; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_test]^"; #Endif; mscp_root_search (d); return true; ]; !C static void cmd_set_depth(char *s) !C { !C if (1==sscanf(s, "%*s%d", &maxdepth)) { !C if (maxdepth < 1) maxdepth = 1; !C if (maxdepth > 8) maxdepth = 8; !C } !C printf("maximum search depth is %d plies\n", maxdepth); !C } Array mscp_cmd_set_depth_max string "maximum search depth is "; [ mscp_cmd_set_depth d retcode; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_set_depth]^"; #Endif; if (d < 1) { mscp_maxdepth = 1; retcode = false; } else if (d > 8) { mscp_maxdepth = 8; retcode = false; } else { mscp_maxdepth = d; retcode = true; } mscp_print_string (mscp_cmd_set_depth_max); mscp_print_number (mscp_maxdepth); mscp_print_char (' '); mscp_print_char ('p'); mscp_print_char ('l'); if (mscp_maxdepth ~= 1) { mscp_print_char ('i'); mscp_print_char ('e'); mscp_print_char ('s'); } else mscp_print_char ('y'); mscp_print_char ('^'); return retcode; ]; !C static void cmd_new(char *dummy) !C { !C setup_board("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -"); !C computer[0] = 0; !C computer[1] = 1; !C } Array mscp_initial_fen string "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; [ mscp_cmd_new i retcode; i = 0; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_new]^"; #Endif; retcode = mscp_setup_board (mscp_initial_fen); #Ifndef MSCP_NO_AGGRESSIVE; for (i = 0: i < MSCP_C_CORE: i++) { mscp_ttable_hash-->i = 0; mscp_ttable_move-->i = 0; mscp_ttable_score-->i = 0; mscp_ttable_flag->i = 0; mscp_ttable_depth->i = 0; } for (i = 0: i < 4096: i++) { mscp_history-->i = 0; } #Endif; mscp_computer-->0 = 0; mscp_computer-->1 = 1; mscp_last_white_move = 0; mscp_last_white_san->0 = 0; mscp_last_black_move = 0; mscp_last_black_san->0 = 0; return retcode; ]; !C static void cmd_xboard(char *dummy) !C { !C xboard = 1; !C } !C static void cmd_reset(char *dummy) !C { !C memset(&core, 0, sizeof(core)); !C memset(history, 0, sizeof(history)); !C booksize = 0; !C maxdepth = 4; !C } [ mscp_cmd_reset i; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_reset]^"; #Endif; for (i = 0: i < MSCP_C_CORE: i++) { mscp_ttable_hash-->i = 0; mscp_ttable_move-->i = 0; mscp_ttable_score-->i = 0; mscp_ttable_flag->i = 0; mscp_ttable_depth->i = 0; } for (i = 0: i < 4096: i++) { mscp_history-->i = 0; } mscp_maxdepth = 3; ! Inform note - a bit snappier return true; ]; !C static void cmd_fen(char *s) !C { !C while (xisalpha(*s)) s++; !C setup_board(s); !C } [ mscp_cmd_fen s i retcode; i = 0; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_fen]^"; #Endif; retcode = mscp_setup_board (s); #Ifndef MSCP_NO_AGGRESSIVE; for (i = 0: i < MSCP_C_CORE: i++) { mscp_ttable_hash-->i = 0; mscp_ttable_move-->i = 0; mscp_ttable_score-->i = 0; mscp_ttable_flag->i = 0; mscp_ttable_depth->i = 0; } for (i = 0: i < 4096: i++) { mscp_history-->i = 0; } #Endif; mscp_last_white_move = 0; mscp_last_white_san->0 = 0; mscp_last_black_move = 0; mscp_last_black_san->0 = 0; return retcode; ]; !C static void cmd_quit(char *dummy) !C { !C exit(0); !C } !C struct cmd mscp_commands[]; /* forward declaration */ !C static void cmd_help(char *dummy) !C { !C struct cmd *c; !C puts("commands are:"); !C c = mscp_commands; !C do { !C printf("%-8s - %s\n", c->name ? c->name : "", c->help); !C } while (c++->name != NULL); !C } Array mscp_cmd_about_1 string "^This is MSCP 1.2 (Marcel's Simple Chess Program)^^"; Array mscp_cmd_about_2 string "Copyright (C)1998-2002 Marcel van Kervinck^"; Array mscp_cmd_about_3 string "This program is distributed under the GNU General Public License.^"; Array mscp_cmd_about_4 string "See file COPYING or http://combinational.com/mscp/ for details.^^"; Array mscp_cmd_about_5 string "Inform version by Simon Baldwin^"; Array mscp_cmd_about_6 string "Inform MSCP comes with ABSOLUTELY NO WARRANTY.^"; Array mscp_cmd_about_7 string "See http://www.ifarchive.org/if-archive/games/source/inform/^^"; [ mscp_cmd_about; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_about]^"; #Endif; mscp_print_string (mscp_cmd_about_1); mscp_print_string (mscp_cmd_about_2); mscp_print_string (mscp_cmd_about_3); mscp_print_string (mscp_cmd_about_4); mscp_print_string (mscp_cmd_about_5); mscp_print_string (mscp_cmd_about_6); mscp_print_string (mscp_cmd_about_7); return true; ]; [ mscp_cmd_status i rank file pc castle m nmoves _move; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_status]^"; #Endif; ! ! print depth, ply, acive color, moves, halfmoves, and last moves ! mscp_print_number (mscp_maxdepth); mscp_print_char (' '); mscp_print_number (1 + mscp_ply / 2); mscp_print_char (' '); if (MSCP_WTM ()) mscp_print_char ('w'); else mscp_print_char ('b'); mscp_print_char (' '); if (mscp_computer-->0) mscp_print_char ('w');else mscp_print_char ('-'); if (mscp_computer-->1) mscp_print_char ('b');else mscp_print_char ('-'); mscp_print_char (' '); mscp_compute_attacks (); m = mscp_move_sp; mscp_generate_moves (0); mscp_qsort_moves (m, mscp_move_sp - 1); while (mscp_move_sp > m) { --mscp_move_sp; if (~~(mscp_test_illegal (mscp_move_stack_move-->mscp_move_sp))) nmoves++; } mscp_print_number (nmoves); mscp_print_char (' '); mscp_print_number (mscp_halfmoves); mscp_print_char (' '); if (mscp_last_white_move) mscp_print_move_long (mscp_last_white_move); else mscp_print_char ('-'); mscp_print_char (' '); if (mscp_last_white_san->0) mscp_print_string (mscp_last_white_san); else mscp_print_char ('-'); mscp_print_char (' '); if (mscp_last_black_move) mscp_print_move_long (mscp_last_black_move); else mscp_print_char ('-'); mscp_print_char (' '); if (mscp_last_black_san->0) mscp_print_string (mscp_last_black_san); else mscp_print_char ('-'); mscp_print_char ('^'); ! ! print the board FEN description ! i = 0; for (rank = MSCP_C_RANK_8: rank >= MSCP_C_RANK_1: rank--) { if (rank < MSCP_C_RANK_8) { if (i > 0) { mscp_print_char (i + '0'); i = 0; } mscp_print_char ('/'); } for (file=MSCP_C_FILE_A: file<=MSCP_C_FILE_H: file++) { pc = MSCP_PIECE2CHAR (mscp_board->(MSCP_SQ (file,rank))); if (pc ~= '-') { if (i > 0) { mscp_print_char (i + '0'); i = 0; } mscp_print_char (pc); } else { i++; } } } if (i > 0) { mscp_print_char (i + '0'); } mscp_print_char (' '); ! ! print remaining FEN information -- active color, available castling, ! en passant square, halfmoves, and ply ! if (MSCP_WTM ()) mscp_print_char ('w'); else mscp_print_char ('b'); mscp_print_char (' '); castle = mscp_board->MSCP_C_CASTLE; if (castle & MSCP_C_CASTLE_WHITE_KING) mscp_print_char ('K'); if (castle & MSCP_C_CASTLE_WHITE_QUEEN) mscp_print_char ('Q'); if (castle & MSCP_C_CASTLE_BLACK_KING) mscp_print_char ('k'); if (castle & MSCP_C_CASTLE_BLACK_QUEEN) mscp_print_char ('q'); if (~~castle) mscp_print_char ('-'); mscp_print_char (' '); if (mscp_redo_lp > 0) { mscp_unmake_move (); mscp_redo_lp--; _move = mscp_redo_list-->mscp_redo_lp; if (mscp_board->(MSCP_FR (_move)) == MSCP_C_WHITE_PAWN && MSCP_R (MSCP_FR (_move)) == MSCP_C_RANK_2 && MSCP_R (MSCP_TO (_move)) == MSCP_C_RANK_4) { mscp_print_char (MSCP_FILE2CHAR (MSCP_F (MSCP_FR (_move)))); mscp_print_char ('3'); } else if (mscp_board->(MSCP_FR (_move)) == MSCP_C_BLACK_PAWN && MSCP_R (MSCP_FR (_move)) == MSCP_C_RANK_7 && MSCP_R (MSCP_TO (_move)) == MSCP_C_RANK_5) { mscp_print_char (MSCP_FILE2CHAR (MSCP_F (MSCP_FR (_move)))); mscp_print_char ('6'); } else mscp_print_char ('-'); mscp_make_move (mscp_redo_list-->mscp_redo_lp++); } else mscp_print_char ('-'); mscp_print_char (' '); mscp_print_number (mscp_halfmoves); ! Halfmoves since pawn/capture mscp_print_char (' '); mscp_print_number (1 + mscp_ply / 2); mscp_print_char ('^'); return true; ]; [ mscp_cmd_history lp bl; #Ifdef MSCP_DEBUG; print "[MSCP> cmd_history]^"; #Endif; ! ! undo all moves, back to the game start or FEN setup ! lp = mscp_redo_lp; while (lp > 0) { mscp_unmake_move (); lp--; } ! ! remake each move, and print its SAN ! bl = ~~(MSCP_WTM ()); while (lp < mscp_redo_lp) { #Ifndef MSCP_NO_TICK_CHECK; mscp_tick_check (); #Endif; #Ifndef MSCP_NO_UNWIND; if (mscp_unwind_requested) { while (lp < mscp_redo_lp) mscp_make_move (mscp_redo_list-->lp++); return true; } #Endif; if (lp > 0) { if ((lp + bl) % 8 == 0) mscp_print_char ('^'); else mscp_print_char (' '); } if (lp == 0 && ~~(MSCP_WTM ())) { mscp_print_number (1 + mscp_ply / 2); mscp_print_char ('.'); mscp_print_char ('.'); mscp_print_char ('.'); mscp_print_char (' '); } else if (MSCP_WTM ()) { mscp_print_number (1 + mscp_ply / 2); mscp_print_char ('.'); mscp_print_char (' '); } mscp_print_move_san (mscp_redo_list-->lp); mscp_make_move (mscp_redo_list-->lp++); } if (lp > 0) mscp_print_char ('^'); return true; ]; !C struct cmd mscp_commands[] = { !C { "help", cmd_help, "show this list of commands" }, !C { "bd", cmd_bd, "display board" }, !C { "ls", cmd_list_moves, "list moves" }, !C { "new", cmd_new, "new game" }, !C { "go", cmd_go, "computer starts playing" }, !C { "test", cmd_test, "search (depth)" }, !C { "quit", cmd_quit, "leave chess program" }, !C { "sd", cmd_set_depth, "set maximum search depth (plies)" }, !C { "both", cmd_both, "computer plays both sides" }, !C { "force", cmd_force, "computer plays neither side" }, !C { "white", cmd_white, "set computer to play white" }, !C { "black", cmd_black, "set computer to play black" }, !C { "book", cmd_book, "lookup current position in book" }, !C { "undo", cmd_undo, "undo move" }, !C { "reset", cmd_reset, "reset internal tables" }, !C { "quit", cmd_quit, "leave chess program" }, !C { "xboard", cmd_xboard, "switch to xboard mode" }, !C { "fen", cmd_fen, "setup new position" }, !C { NULL, cmd_default, "enter moves in algebraic notation" }, !C }; Global mscp_initialized = false; [ mscp_ensure_initialized; if (~~mscp_initialized) { #Ifdef MSCP_DEBUG; print "[MSCP> initialize]^"; #Endif; mscp_castle->MSCP_C_A1 = MSCP_C_CASTLE_WHITE_QUEEN; mscp_castle->MSCP_C_E1 = MSCP_C_CASTLE_WHITE_KING | MSCP_C_CASTLE_WHITE_QUEEN; mscp_castle->MSCP_C_H1 = MSCP_C_CASTLE_WHITE_KING; mscp_castle->MSCP_C_A8 = MSCP_C_CASTLE_BLACK_QUEEN; mscp_castle->MSCP_C_E8 = MSCP_C_CASTLE_BLACK_KING | MSCP_C_CASTLE_BLACK_QUEEN; mscp_castle->MSCP_C_H8 = MSCP_C_CASTLE_BLACK_KING; mscp_initialized = true; return mscp_cmd_new (); } return false; ]; ! /*----------------------------------------------------------------------+ ! | programming interface | ! +----------------------------------------------------------------------*/ ! execute call function codes Constant MSCP_EXEC_INITIALIZE 0; Constant MSCP_EXEC_DISPLAY_BOARD 1; Constant MSCP_EXEC_LIST_MOVES 2; Constant MSCP_EXEC_NEW_GAME 3; Constant MSCP_EXEC_GO 4; Constant MSCP_EXEC_SEARCH 5; Constant MSCP_EXEC_SET_DEPTH 6; Constant MSCP_EXEC_BOTH 7; Constant MSCP_EXEC_FORCE 8; Constant MSCP_EXEC_WHITE 9; Constant MSCP_EXEC_BLACK 10; Constant MSCP_EXEC_BOOK 12; Constant MSCP_EXEC_UNDO 13; Constant MSCP_EXEC_RESET 14; Constant MSCP_EXEC_SETUP_FEN 15; Constant MSCP_EXEC_MOVE 16; Constant MSCP_EXEC_ABOUT 17; Constant MSCP_EXEC_STATUS 18; Constant MSCP_EXEC_HISTORY 19; Array mscp_execute_game_over string "game over^"; ! main programming interface function [ mscp_execute cmd a1 a2 a3 a4 a5 a6 ! varargs i retcode _move; i = 0; #Ifdef MSCP_DEBUG; print "[MSCP> execute ", cmd, ", ", a1, ", ", a2, ", ", a3, ", ", a4, ", ", a5, ", ", a6, "]^"; #Endif; switch (cmd) { MSCP_EXEC_INITIALIZE: mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_ensure_initialized (); MSCP_EXEC_DISPLAY_BOARD: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_bd (); MSCP_EXEC_LIST_MOVES: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_list_moves (); MSCP_EXEC_NEW_GAME: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_new (); MSCP_EXEC_GO: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_go (); MSCP_EXEC_SEARCH: mscp_ensure_initialized (); mscp_use_buffer (a2, a3, a4); mscp_tick_register (a5, a6); retcode = mscp_cmd_test (a1); MSCP_EXEC_SET_DEPTH: mscp_ensure_initialized (); mscp_use_buffer (a2, a3, a4); mscp_tick_register (a5, a6); retcode = mscp_cmd_set_depth (a1); MSCP_EXEC_BOTH: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_both (); MSCP_EXEC_FORCE: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_force (); MSCP_EXEC_WHITE: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_white (); MSCP_EXEC_BLACK: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_black (); MSCP_EXEC_BOOK: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_book (); MSCP_EXEC_UNDO: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_undo (); MSCP_EXEC_RESET: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_reset (); MSCP_EXEC_SETUP_FEN: mscp_ensure_initialized (); mscp_use_buffer (a2, a3, a4); mscp_tick_register (a5, a6); retcode = mscp_cmd_fen (a1); MSCP_EXEC_MOVE: mscp_ensure_initialized (); mscp_use_buffer (a2, a3, a4); mscp_tick_register (a5, a6); retcode = mscp_cmd_default (a1); MSCP_EXEC_ABOUT: mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_about (); MSCP_EXEC_STATUS: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_status (); MSCP_EXEC_HISTORY: mscp_ensure_initialized (); mscp_use_buffer (a1, a2, a3); mscp_tick_register (a4, a5); retcode = mscp_cmd_history (); default: return -1; } if (retcode) { while (mscp_computer-->(~~(MSCP_WTM ()))) { _move = mscp_book_move (); if (~~_move) { #Ifdef MSCP_NO_AGGRESSIVE; for (i = 0: i < MSCP_C_CORE: i++) { mscp_ttable_hash-->i = 0; mscp_ttable_move-->i = 0; mscp_ttable_score-->i = 0; mscp_ttable_flag->i = 0; mscp_ttable_depth->i = 0; } for (i = 0: i < 4096: i++) { mscp_history-->i = 0; } #Endif; _move = mscp_root_search (mscp_maxdepth); } if ((~~_move) || mscp_halfmoves >= 50) { mscp_print_string (mscp_execute_game_over); mscp_computer-->0 = 0; mscp_computer-->1 = 0; break; } mscp_print_number (1 + mscp_ply / 2); mscp_print_char ('.'); mscp_print_char (' '); mscp_print_char ('.'); mscp_print_char ('.'); mscp_print_char ('.'); mscp_print_char (' '); mscp_print_move_long (_move); mscp_print_char ('^'); mscp_halfmoves_list-->mscp_redo_lp = mscp_halfmoves; mscp_redo_list-->mscp_redo_lp++ = _move; mscp_note_move (_move); mscp_make_move (_move); mscp_print_board (); } } mscp_use_buffer (0, 0, 0); mscp_tick_register (0, 0); return retcode; ]; !C /*----------------------------------------------------------------------+ !C | main | !C +----------------------------------------------------------------------*/ !C static void catch_sigint(int s) !C { !C signal(s, catch_sigint); !C } !C static char msg[] = !C "\n" !C "This is MSCP 1.2 (Marcel's Simple Chess Program)\n" !C "\n" !C "Copyright (C)1998-2002 Marcel van Kervinck\n" !C "This program is distributed under the GNU General Public License.\n" !C "(See file COPYING or http://combinational.com/mscp/ for details.)\n" !C "\n" !C "Type 'help' for a list of commands\n"; !C int main(void) !C { !C int i; !C int cmd; !C char line[128]; !C char name[128]; !C int move; !C (void)rcs_id; !C puts(msg); !C signal(SIGINT, catch_sigint); !C for (i=0; i ", stdout); !C fflush(stdout); !C } !C if (readline(line, sizeof(line), stdin) < 0) { !C break; !C } !C if (1 != sscanf(line, "%s", name)) continue; !C for (cmd=0; mscp_commands[cmd].name != NULL; cmd++) { !C if (0==strcmp(mscp_commands[cmd].name, name)) { !C break; !C } !C } !C mscp_commands[cmd].cmd(line); !C while (computer[!WTM]) { !C move = book_move(); !C if (!move) { !C booksize = 0; !C memset(&core, 0, sizeof(core)); !C memset(history, 0, sizeof(history)); !C move = root_search(maxdepth); !C } !C if (!move) { !C puts("game over"); !C computer[0] = computer[1] = 0; !C break; !C } !C printf("%d. ... ", 1+ply/2); !C print_move_long(move); !C putc('\n', stdout); !C fflush(stdout); !C make_move(move); !C print_board(); !C } !C } !C return 0; !C } ! /*----------------------------------------------------------------------+ ! | xboard interface | ! +----------------------------------------------------------------------*/ ! command strings to exec codes mapping table Array mscp_xboard_cmd_help string "help"; Array mscp_xboard_cmd_bd string "bd"; Array mscp_xboard_cmd_ls string "ls"; Array mscp_xboard_cmd_new string "new"; Array mscp_xboard_cmd_go string "go"; Array mscp_xboard_cmd_test string "test"; Array mscp_xboard_cmd_quit string "quit"; Array mscp_xboard_cmd_sd string "sd"; Array mscp_xboard_cmd_both string "both"; Array mscp_xboard_cmd_force string "force"; Array mscp_xboard_cmd_white string "white"; Array mscp_xboard_cmd_black string "black"; Array mscp_xboard_cmd_book string "book"; Array mscp_xboard_cmd_undo string "undo"; Array mscp_xboard_cmd_reset string "reset"; Array mscp_xboard_cmd_xboard string "xboard"; Array mscp_xboard_cmd_fen string "fen"; Array mscp_xboard_cmd_about string "about"; Array mscp_xboard_cmd_status string "status"; Array mscp_xboard_cmd_history string "history"; Array mscp_xboard_table table [; mscp_xboard_cmd_help (-1); mscp_xboard_cmd_bd MSCP_EXEC_DISPLAY_BOARD; mscp_xboard_cmd_ls MSCP_EXEC_LIST_MOVES; mscp_xboard_cmd_new MSCP_EXEC_NEW_GAME; mscp_xboard_cmd_go MSCP_EXEC_GO; mscp_xboard_cmd_test MSCP_EXEC_SEARCH; mscp_xboard_cmd_quit (-2); mscp_xboard_cmd_sd MSCP_EXEC_SET_DEPTH; mscp_xboard_cmd_both MSCP_EXEC_BOTH; mscp_xboard_cmd_force MSCP_EXEC_FORCE; mscp_xboard_cmd_white MSCP_EXEC_WHITE; mscp_xboard_cmd_black MSCP_EXEC_BLACK; mscp_xboard_cmd_book MSCP_EXEC_BOOK; mscp_xboard_cmd_undo MSCP_EXEC_UNDO; mscp_xboard_cmd_reset MSCP_EXEC_RESET; mscp_xboard_cmd_xboard (-3); mscp_xboard_cmd_fen MSCP_EXEC_SETUP_FEN; mscp_xboard_cmd_about MSCP_EXEC_ABOUT; mscp_xboard_cmd_status MSCP_EXEC_STATUS; mscp_xboard_cmd_history MSCP_EXEC_HISTORY; 0 MSCP_EXEC_MOVE; ! always last ]; ! lookup command code from xboard input line [ mscp_lookup_xboard_command line entry i j str cmd k; i = 1; while (i <= line->0 && mscp_xisspace (line->i)) i++; for (entry = 1: entry <= mscp_xboard_table-->0: entry = entry + 2) { str = mscp_xboard_table-->entry; cmd = mscp_xboard_table-->(entry + 1); if (str == 0) { ! found end? return cmd; } j = i; k = 1; while (j <= line->0 && k <= str->0 && line->j == str->k) { j++; k++; } if (k > str->0 && (j > line->0 || mscp_xisspace (line->j))) { return cmd; } } return MSCP_EXEC_MOVE; ! table error -- no sentinel ]; ! xboard output buffer Array mscp_xboard_buffer -> 256; ! print xboard output buffer callback [ mscp_xboard_callback buffer length i; ! print up to, but exclude, "^" at end of buffer for (i = 0: i < length - 1: i++) print (char) buffer->i; print "^"; ! add newline return true; ]; ! find xboard line number argument [ mscp_xboard_get_num_arg line i d; i = 1; while (i <= line->0 && mscp_xisspace (line->i)) i++; while (i <= line->0 && ~~(mscp_xisspace (line->i))) i++; while (i <= line->0 && mscp_xisspace (line->i)) i++; d = -1; while (i <= line->0) { if (line->i < '0' || line->i > '9') { break; } if (d == -1) d = 0; d = d * 10 + line->i - '0'; i++; } return d; ]; ! xboard string argument buffer Array mscp_xboard_str_arg_buf -> 256; ! find xboard line string argument [ mscp_xboard_get_str_arg line i j; i = 1; while (i <= line->0 && mscp_xisspace (line->i)) i++; while (i <= line->0 && ~~(mscp_xisspace (line->i))) i++; while (i <= line->0 && mscp_xisspace (line->i)) i++; j = 1; while (i <= line->0) { mscp_xboard_str_arg_buf->j++ = line->i++; } mscp_xboard_str_arg_buf->0 = j - 1; return mscp_xboard_str_arg_buf; ]; ! xboard interface initialization flag Global mscp_xboard_initialized = false; ! main xboard interface function [ mscp_xboard line callback opaque ! varargs cmd retcode numarg strarg; #Ifdef MSCP_DEBUG; print "[MSCP> xboard ", line, ", ", callback, ", ", opaque, "]^"; #Endif; if (line == 0 || line->0 == 0) { ! null/empty input line if (~~mscp_xboard_initialized) { ! first call? mscp_execute (MSCP_EXEC_ABOUT, mscp_xboard_buffer, 256, mscp_xboard_callback, callback, opaque); print "Type 'help' for a list of commands^^"; mscp_execute (MSCP_EXEC_INITIALIZE, mscp_xboard_buffer, 256, mscp_xboard_callback, callback, opaque); mscp_xboard_initialized = true; } if (~~mscp_xboard_flag) print "inform-mscp> "; return true; } cmd = mscp_lookup_xboard_command (line); switch (cmd) { MSCP_EXEC_DISPLAY_BOARD, MSCP_EXEC_LIST_MOVES, MSCP_EXEC_NEW_GAME, MSCP_EXEC_GO, MSCP_EXEC_BOTH, MSCP_EXEC_FORCE, MSCP_EXEC_WHITE, MSCP_EXEC_BLACK, MSCP_EXEC_BOOK, MSCP_EXEC_UNDO, MSCP_EXEC_RESET, MSCP_EXEC_ABOUT, MSCP_EXEC_STATUS, MSCP_EXEC_HISTORY: ! no arg calls retcode = mscp_execute (cmd, mscp_xboard_buffer, 256, mscp_xboard_callback, callback, opaque); MSCP_EXEC_SEARCH, MSCP_EXEC_SET_DEPTH: ! number arg calls numarg = mscp_xboard_get_num_arg (line); if (numarg == -1) numarg = mscp_maxdepth; retcode = mscp_execute (cmd, numarg, mscp_xboard_buffer, 256, mscp_xboard_callback, callback, opaque); MSCP_EXEC_SETUP_FEN: ! string arg call strarg = mscp_xboard_get_str_arg (line); retcode = mscp_execute (cmd, strarg, mscp_xboard_buffer, 256, mscp_xboard_callback, callback, opaque); MSCP_EXEC_MOVE: ! line is arg call retcode = mscp_execute (cmd, line, mscp_xboard_buffer, 256, mscp_xboard_callback, callback, opaque); -1: ! help special print "commands are:^"; print "help - show this list of commands^"; print "bd - display board^"; print "ls - list moves^"; print "new - new game^"; print "go - computer starts playing^"; print "test - search (depth)^"; print "quit - leave chess program^"; print "sd - set maximum search depth (plies)^"; print "both - computer plays both sides^"; print "force - computer plays neither side^"; print "white - set computer to play white^"; print "black - set computer to play black^"; print "book - lookup current position in book^"; print "undo - undo move^"; print "reset - reset internal tables^"; print "xboard - switch to xboard mode^"; print "fen - setup new position^"; print "about - print credits, complies with GPL^"; print "status - one-line summary of last moves and board^"; print "history - list all game moves made, in PGN format^"; print " - enter moves in algebraic notation^"; retcode = true; -2: ! quit special return -1; ! no new prompt -3: ! prompt off special mscp_xboard_flag = 1; retcode = true; } if (~~mscp_xboard_flag) print "inform-mscp> "; return retcode; ]; !C /*----------------------------------------------------------------------+ !C | | !C +----------------------------------------------------------------------*/ #Endif;