/* B R U T A L I S l›ser hj‘lpematter og konstruktionsopgaver */ #include "time.h" #include "math.h" #include "stdio.h" #include "stdlib.h" /* letter l‘sningen af programmet hvor der direkte refereres til et felt */ #define a1 21 #define b1 22 #define c1 23 #define d1 24 #define e1 25 #define f1 26 #define g1 27 #define h1 28 #define h2 38 #define a7 81 #define a8 91 #define b8 92 #define c8 93 #define d8 94 #define e8 95 #define f8 96 #define g8 97 #define h8 98 #define equal == #define or || #define and && #define false 0 #define true 1 #define int_min -30000 #define int_max +30000 #define none 10 /* #define all_black 11 */ /* #define all_white 12 */ signed char iteration_from; /* the depth of the search; at least 1*/ signed char iteration_to; /* evt. more depths; >= iteration_from*/ signed char iteration_step; /* normally 1; eventually 2... */ /* signed char ply_mating_1; */ /* where the mating move is generated */ signed char ply_mating; /* the ply where the mating move is...*/ signed char ply_mate; /* the ply where the mate is */ /* = iteration_to..... */ signed char mating_wh_bl; /* the side that is mating the other */ signed char screen_pause; /* pauses when the limit is reached */ signed char screen_pause_limit; /* the limit */ signed char certain_piece; /* none or b/w piece */ signed char certain_piece_sq; /* on a specific square */ /*signed char certain_rowpiece; *//* none or b/w piece */ /*signed char certain_rowpiece_row;*//* the row where the piece must be */ /*signed char row_a_sq; */ /* first square on the row */ /*signed char row_h_sq; */ /* last square on the row */ signed char movemating_piece; /* none or piece (discovered check...)*/ /* castling is a king-move... */ /* promotion is a pawn-move */ signed char captured_piece; /* none, piece, empty */ signed char many_movematingpiece[99]; /* none, square */ /*signed char many_movematingpiece_all; /* which much_moving piece now... */ signed char moves_othermating_pieces[99]; /* number of moves by other */ signed char many_movematedpiece[99]; /* none, square */ /*signed char many_movematedpiece_all; /* which much_moving piece now... */ signed char moves_othermated_pieces[99]; /* number of moves by other */ int count_solutions; /* */ int max_moves; #define stop 111 /* denne bruges ogs† som stopklods i move_fr-array */ #define one_step 1 #define more_steps 7 int men_value[8] ={0, 0, 100, 300, 325, 500, 900, 20000}; signed char men_letter[9] ={'B', ' ', ' ', 'S', 'L', 'T', 'D', 'K', '\0'}; signed char king[10] ={one_step, -1, 9, 10, 11, 1, -9, -10, -11, stop }; signed char queen[10] ={more_steps, -1, 9, 10, 11, 1, -9, -10, -11, stop}; signed char rook[6] ={more_steps, -1, 10, 1, -10, stop}; signed char bishop[6] ={more_steps, 9, 11, -9, -11, stop}; signed char knight[10]={one_step, 8, 19, 21, 12, -8, -19, -21, -12, stop}; signed char *gangart; /* bruges som pointer i ovenst†ende 5 arrays */ signed char fatal_tekst[60]; /* hop ud af programmet med denne meddelelse.. */ signed char gen_moves_mode; #define move_and_attack 2 #define only_attack 1 signed char attack_w_min[h8+1]; /* mindste hvide brik der truer et felt */ signed char attack_b_min[h8+1]; /* mindste sorte brik der truer et felt */ signed char xxx[162]; /* her l‘ses den stilling, der startes med */ signed char ply, ply_1, ply_2; /* ply, ply minus en, ply minus to */ signed char wh_bl; #define white 1 #define black -1 signed char sq[120]; /* her er skakbr‘ttet som 10x12 */ signed char *sq_idx, *sq_idx2; /* disse pointere bruges p† skakbr‘ttet */ /* br‘ttes felter (sq) kan indeholde disse v‘rdier: */ #define w_p 2 /* white pawn o.s.v. */ #define w_n 3 #define w_b 4 #define w_r 5 #define w_q 6 #define w_k 7 #define b_p -2 #define b_n -3 #define b_b -4 #define b_r -5 #define b_q -6 #define b_k -7 #define sq_empty 0 #define sq_illegal 1 /* udenfor 8x8 br‘ttet */ /* >=w_p er en hvid brik; <=b_p er en sort brik */ #define prom_q_9 111 /* ved bondeforvandling indeholder til-feltet en */ #define prom_r_9 112 /* af disse v‘rdier. */ #define prom_b_9 113 /* Forvandling er til q,r,b,n, og det sker p† */ #define prom_n_9 114 /* feltet = fra-felt + 9/10/11. */ #define prom_q_10 116 /* (For sort tr‘kker man 9/10/11 fra) */ #define prom_r_10 117 #define prom_b_10 118 #define prom_n_10 119 #define prom_q_11 121 #define prom_r_11 122 #define prom_b_11 123 #define prom_n_11 124 #define max_ply 34 #define allowed 1 #define not_allowed 0 signed char w_0_0 [max_ply]; /* rokaderne (not_)allowed */ signed char w_0_0_0 [max_ply]; signed char b_0_0 [max_ply]; signed char b_0_0_0 [max_ply]; signed char e_p [max_ply]; /* indeholder not-allowed eller a6 hvis der fx lige er spillet a7a5 */ int legal_move_found [max_ply]; /* er mat fundet / afv‘rget */ signed char sq_w_k [max_ply]; /* hvor st†r white king */ signed char sq_b_k [max_ply]; /* hvor st†r black king */ signed char mobilitet [max_ply]; /* udfyldes n†r tr‘kkene er dannet */ signed char move_fr_before [max_ply]; /* indholdet af from- og to-feltet */ signed char move_to_before [max_ply]; /* inden tr‘kket blev udf›rt */ signed char move_pointer [max_ply]; /* peger p† n‘ste tr‘k */ signed char move_point; /* arbejdsindeks n†r der arbejdes i tr‘ktabellen */ #define max_moves_in_table 120 signed char move_fr [max_ply][max_moves_in_table]; signed char move_to [max_ply][max_moves_in_table]; /************** t‘lle-v‘rker ******************/ double tv_nodes, tv_pseudo_moves; int tid, gemtid; signed char make_move_status; #define normal_move 1 #define do_undo_move 0 #define kill_items 500 #define kill_depth 5 /* signed char kill_fr [kill_items][ kill_depth]; signed char kill_to [kill_items][ kill_depth]; */ henttid() /* returnerer antal hundreddele sekunder siden programstart */ { return (100*(clock())/CLK_TCK); } void press_return_to_continue() { signed char dum; printf("\n Press RETURN to continue..."); dum = getchar(); ++dum; } void beep() {printf("\a"); } void sq120_to_koordinat(signed char *ch1, signed char *ch2, signed char *ch3) /* 31 (a2) => 2(r‘kke) 1(linie) */ { *ch3=(*ch1 - 10) / 10; *ch2=*ch1 - 10 - (10 * *ch3); } void print_a1_h8(signed char *ch1) /* printer c8 hvis funktionen bliver kaldt med signed char = 93 */ {signed char ch2, ch3; sq120_to_koordinat(ch1, &ch2, &ch3); printf("%1c%1c",'a' - 1 + ch2, '0' + ch3); } void show_board() {signed char empty, x, y, piece; printf("\n white 0-0 & 0-0-0: "); if (w_0_0[ply] equal allowed) printf("+ "); else printf("- "); if (w_0_0_0[ply] equal allowed) printf("+ "); else printf("- "); printf(" black 0-0 & 0-0-0: "); if (b_0_0[ply] equal allowed) printf("+ "); else printf("- "); if (b_0_0_0[ply] equal allowed) printf("+ "); else printf("- "); printf(" e.p. : "); if (e_p[ply] equal not_allowed) printf(" no"); else print_a1_h8(&e_p[ply]); if (wh_bl equal white) printf("\n white to move "); else printf("\n black to move "); empty=' '; for (x=a8; x>=a1; x=x-10) {if (empty equal '*') empty=' '; else empty='*'; printf("\n "); for (y=x; y<=x+7; ++y) {printf(" "); if (empty equal '*') empty=' '; else empty='*'; if (sq[y] equal sq_empty) printf("%c",empty); else {if (sq[y]<=b_p) piece=(men_letter[sq[y] * -1] - 'A' + 'a'); else piece=(men_letter[sq[y] ]); if (sq[y] equal b_p) piece=men_letter[0] - 'A' + 'a'; if (sq[y] equal w_p) piece=men_letter[0]; printf("%c",piece); } } } press_return_to_continue(); } void print_char(signed char ch1) /* kan bruges til debugging */ {int genius; genius=ch1; printf("udskrift af char som et tal og karakter: %d %1c",genius, ch1); } void print_kqrbnp(signed char ch1) /* printer 'K' hvis input = 7(w_k), 'D' ved 6 o.s.v. */ {signed char poschar; poschar=ch1; if (poschar < 0) { poschar= -1 * poschar;}; printf("%1c",men_letter[poschar]); } void change_black_white() {if (wh_bl equal white) wh_bl = black; else wh_bl = white; } void unpack_promotion(signed char *to, signed char *to_9_10_11, signed char *promote_piece) {switch (*to) {case prom_q_10 : *to_9_10_11=10; *promote_piece=w_q; break; case prom_q_9 : *to_9_10_11=9 ; *promote_piece=w_q; break; case prom_q_11 : *to_9_10_11=11; *promote_piece=w_q; break; case prom_n_10 : *to_9_10_11=10; *promote_piece=w_n; break; case prom_n_9 : *to_9_10_11=9 ; *promote_piece=w_n; break; case prom_n_11 : *to_9_10_11=11; *promote_piece=w_n; break; case prom_r_10 : *to_9_10_11=10; *promote_piece=w_r; break; case prom_r_9 : *to_9_10_11=9 ; *promote_piece=w_r; break; case prom_r_11 : *to_9_10_11=11; *promote_piece=w_r; break; case prom_b_10 : *to_9_10_11=10; *promote_piece=w_b; break; case prom_b_9 : *to_9_10_11=9 ; *promote_piece=w_b; break; case prom_b_11 : *to_9_10_11=11; *promote_piece=w_b; break; } } void generate_moves_2(signed char *gangart, signed char ch1) /* input er pointer til gangart, og &sq[ch1]=pointer sq_idx */ /* dette er lidt goto-spaghetti-agtigt, men jeg synes ikke det er s† sv‘rt at l‘se. */ { signed char sc1; signed char ch2; sc1 = *gangart; /* husk at D,L & T g†r lange ture */ g_m2_10: /* ny retning */ if (*++gangart equal stop) goto g_m2_90; /* ikke flere retninger */ ch2=ch1; sq_idx2=sq_idx; g_m2_20: /* et skridt mere i den givne retning */ sq_idx2 += *gangart; ch2 += *gangart; if (*sq_idx2 equal sq_illegal) goto g_m2_10; /* udenfor br‘ttet */ if (wh_bl equal white) {attack_w_min[ch2]=w_p;} else {attack_b_min[ch2]=b_p;}; if (wh_bl equal white and *sq_idx2 >= w_p) goto g_m2_10; if (wh_bl equal black and *sq_idx2 <= b_p) goto g_m2_10; /* en brik af samme farve */ if (gen_moves_mode equal only_attack) goto g_m2_80; if (*sq_idx equal w_k and attack_b_min[ch2] equal b_p) goto g_m2_10; if (*sq_idx equal b_k and attack_w_min[ch2] equal w_p) goto g_m2_10; move_fr[ply][move_point]=ch1; move_to[ply][move_point++]=ch2; /* print_kqrbnp(*sq_idx); print_a1_h8(&ch2); printf(" "); */ g_m2_80: if (*sq_idx2 != sq_empty) goto g_m2_10; if (sc1 equal more_steps) goto g_m2_20; goto g_m2_10; g_m2_90: } void move_into_array(signed char *ch1, signed char *ch2, signed char prom) {move_fr[ply][move_point]=*ch1; if ((wh_bl equal white and *ch1h2)) move_to[ply][move_point++]=*ch2; else {move_to[ply][move_point++]=prom; /* promotion to Q, R, B, N */ move_fr[ply][move_point]=*ch1; move_to[ply][move_point++]=prom+1; move_fr[ply][move_point]=*ch1; move_to[ply][move_point++]=prom+2; move_fr[ply][move_point]=*ch1; move_to[ply][move_point++]=prom+3; } } void generate_pawn_moves(signed char ch1) { signed char ch2; if (gen_moves_mode equal move_and_attack) {ch2 = ch1 + wh_bl * 10; if (sq[ch2] equal sq_empty) {move_into_array(&ch1, &ch2, prom_q_10); if ((wh_bl equal white and ch1<=h2) or (wh_bl equal black and ch1>=a7)) {ch2 = ch1 + wh_bl * 20; if (sq[ch2] equal sq_empty) move_into_array(&ch1, &ch2, 0); } } } ch2 = ch1 + wh_bl * 9; if (wh_bl equal white) attack_w_min[ch2]=w_p; else attack_b_min[ch2]=b_p; if (gen_moves_mode equal move_and_attack) {if ((wh_bl equal white and sq[ch2]<=b_p) or (wh_bl equal black and sq[ch2]>=w_p) or (ch2 equal e_p[ply] )) move_into_array(&ch1, &ch2, prom_q_9); } ch2 = ch1 + wh_bl * 11; if (wh_bl equal white) attack_w_min[ch2]=w_p; else attack_b_min[ch2]=b_p; if (gen_moves_mode equal move_and_attack) {if ((wh_bl equal white and sq[ch2]<=b_p) or (wh_bl equal black and sq[ch2]>=w_p) or (ch2 equal e_p[ply] )) move_into_array(&ch1, &ch2, prom_q_11); } } void generate_moves() {signed char *gulerod; signed char sovs; if (wh_bl equal white) {attack_w_min[21]=w_k+1;attack_w_min[22]=w_k+1;attack_w_min[23]=w_k+1; attack_w_min[24]=w_k+1;attack_w_min[25]=w_k+1;attack_w_min[26]=w_k+1; attack_w_min[27]=w_k+1;attack_w_min[28]=w_k+1;attack_w_min[31]=w_k+1; attack_w_min[32]=w_k+1;attack_w_min[33]=w_k+1;attack_w_min[34]=w_k+1; attack_w_min[35]=w_k+1;attack_w_min[36]=w_k+1;attack_w_min[37]=w_k+1; attack_w_min[38]=w_k+1;attack_w_min[41]=w_k+1;attack_w_min[42]=w_k+1; attack_w_min[43]=w_k+1;attack_w_min[44]=w_k+1;attack_w_min[45]=w_k+1; attack_w_min[46]=w_k+1;attack_w_min[47]=w_k+1;attack_w_min[48]=w_k+1; attack_w_min[51]=w_k+1;attack_w_min[52]=w_k+1;attack_w_min[53]=w_k+1; attack_w_min[54]=w_k+1;attack_w_min[55]=w_k+1;attack_w_min[56]=w_k+1; attack_w_min[57]=w_k+1;attack_w_min[58]=w_k+1;attack_w_min[61]=w_k+1; attack_w_min[62]=w_k+1;attack_w_min[63]=w_k+1;attack_w_min[64]=w_k+1; attack_w_min[65]=w_k+1;attack_w_min[66]=w_k+1;attack_w_min[67]=w_k+1; attack_w_min[68]=w_k+1;attack_w_min[71]=w_k+1;attack_w_min[72]=w_k+1; attack_w_min[73]=w_k+1;attack_w_min[74]=w_k+1;attack_w_min[75]=w_k+1; attack_w_min[76]=w_k+1;attack_w_min[77]=w_k+1;attack_w_min[78]=w_k+1; attack_w_min[81]=w_k+1;attack_w_min[82]=w_k+1;attack_w_min[83]=w_k+1; attack_w_min[84]=w_k+1;attack_w_min[85]=w_k+1;attack_w_min[86]=w_k+1; attack_w_min[87]=w_k+1;attack_w_min[88]=w_k+1;attack_w_min[91]=w_k+1; attack_w_min[92]=w_k+1;attack_w_min[93]=w_k+1;attack_w_min[94]=w_k+1; attack_w_min[95]=w_k+1;attack_w_min[96]=w_k+1;attack_w_min[97]=w_k+1; attack_w_min[98]=w_k+1;} else {attack_b_min[21]=b_k-1;attack_b_min[22]=b_k-1;attack_b_min[23]=b_k-1; attack_b_min[24]=b_k-1;attack_b_min[25]=b_k-1;attack_b_min[26]=b_k-1; attack_b_min[27]=b_k-1;attack_b_min[28]=b_k-1;attack_b_min[31]=b_k-1; attack_b_min[32]=b_k-1;attack_b_min[33]=b_k-1;attack_b_min[34]=b_k-1; attack_b_min[35]=b_k-1;attack_b_min[36]=b_k-1;attack_b_min[37]=b_k-1; attack_b_min[38]=b_k-1;attack_b_min[41]=b_k-1;attack_b_min[42]=b_k-1; attack_b_min[43]=b_k-1;attack_b_min[44]=b_k-1;attack_b_min[45]=b_k-1; attack_b_min[46]=b_k-1;attack_b_min[47]=b_k-1;attack_b_min[48]=b_k-1; attack_b_min[51]=b_k-1;attack_b_min[52]=b_k-1;attack_b_min[53]=b_k-1; attack_b_min[54]=b_k-1;attack_b_min[55]=b_k-1;attack_b_min[56]=b_k-1; attack_b_min[57]=b_k-1;attack_b_min[58]=b_k-1;attack_b_min[61]=b_k-1; attack_b_min[62]=b_k-1;attack_b_min[63]=b_k-1;attack_b_min[64]=b_k-1; attack_b_min[65]=b_k-1;attack_b_min[66]=b_k-1;attack_b_min[67]=b_k-1; attack_b_min[68]=b_k-1;attack_b_min[71]=b_k-1;attack_b_min[72]=b_k-1; attack_b_min[73]=b_k-1;attack_b_min[74]=b_k-1;attack_b_min[75]=b_k-1; attack_b_min[76]=b_k-1;attack_b_min[77]=b_k-1;attack_b_min[78]=b_k-1; attack_b_min[81]=b_k-1;attack_b_min[82]=b_k-1;attack_b_min[83]=b_k-1; attack_b_min[84]=b_k-1;attack_b_min[85]=b_k-1;attack_b_min[86]=b_k-1; attack_b_min[87]=b_k-1;attack_b_min[88]=b_k-1;attack_b_min[91]=b_k-1; attack_b_min[92]=b_k-1;attack_b_min[93]=b_k-1;attack_b_min[94]=b_k-1; attack_b_min[95]=b_k-1;attack_b_min[96]=b_k-1;attack_b_min[97]=b_k-1; attack_b_min[98]=b_k-1;} /* kan man gemme s†dan en nulstillet tabel og bruge det gemte til efterf›lgende hurtigere nulstillinger? */ gulerod=&sq[h8]; move_point=0;sovs=a1 - 1; for (sq_idx=&sq[a1]; sq_idx<=gulerod; sq_idx++) { sovs++; if ( (wh_bl equal white and *sq_idx >= w_p) or (wh_bl equal black and *sq_idx <= b_p)) { if (*sq_idx equal w_p * wh_bl) generate_pawn_moves(sovs); else if (*sq_idx equal w_r * wh_bl) generate_moves_2(rook, sovs); else if (*sq_idx equal w_b * wh_bl) generate_moves_2(bishop, sovs); else if (*sq_idx equal w_k * wh_bl) generate_moves_2(king, sovs); else if (*sq_idx equal w_n * wh_bl) generate_moves_2(knight, sovs); else generate_moves_2(queen, sovs); }; }; if (wh_bl equal white) {if ( w_0_0[ply] equal allowed and sq[f1] equal sq_empty and sq[g1] equal sq_empty and attack_b_min[e1] equal b_k - 1 and attack_b_min[f1] equal b_k - 1 and attack_b_min[g1] equal b_k - 1) {move_fr[ply][move_point] =e1; move_to[ply][move_point++]=g1; } if ( w_0_0_0[ply] equal allowed and sq[d1] equal sq_empty and sq[c1] equal sq_empty and sq[b1] equal sq_empty and attack_b_min[e1] equal b_k - 1 and attack_b_min[d1] equal b_k - 1 and attack_b_min[c1] equal b_k - 1) {move_fr[ply][move_point] =e1; move_to[ply][move_point++]=c1; } } else {if ( b_0_0[ply] equal allowed and sq[f8] equal sq_empty and sq[g8] equal sq_empty and attack_w_min[e8] equal w_k + 1 and attack_w_min[f8] equal w_k + 1 and attack_w_min[g8] equal w_k + 1) {move_fr[ply][move_point] =e8; move_to[ply][move_point++]=g8; } if ( b_0_0_0[ply] equal allowed and sq[d8] equal sq_empty and sq[c8] equal sq_empty and sq[b8] equal sq_empty and attack_w_min[e8] equal w_k + 1 and attack_w_min[d8] equal w_k + 1 and attack_w_min[c8] equal w_k + 1) {move_fr[ply][move_point] =e8; move_to[ply][move_point++]=c8; } } } void clear_board() {signed char w1_char, w2_char, w3_char; for (w1_char=0; w1_char<120; w1_char++) { sq[w1_char]=sq_illegal; sq120_to_koordinat(&w1_char, &w2_char, &w3_char); if (w2_char>=1 and w2_char<=8 and w3_char>=1 and w3_char<=8) sq[w1_char]=sq_empty; }; } void make_move_array() { gen_moves_mode=move_and_attack; generate_moves(); /* fatal error hvis der er overflow i move array..... */ mobilitet[ply]=move_point; if (move_point > max_moves) max_moves = move_point; move_fr[ply][ move_point]=stop; move_pointer[ply]=0; } void make_only_attack() {/* tr‘kgeneratoren k›res igennem, men kun attack-arrayet dannes */ gen_moves_mode=only_attack; generate_moves(); } void make_array_ply_zero() /* indl‘ser en stilling i ////////-format med engelske brikbetegnelser */ /* (uvist hvordan en passant styres) */ {signed char w1_char, w2_char, w3_char; clear_board(); w_0_0[0]=allowed; w_0_0_0[0]=allowed; b_0_0[0]=allowed; b_0_0_0[0]=allowed; e_p[0]=not_allowed; w3_char=0;sq_w_k[0]=0;sq_b_k[0]=0; for (w1_char=a8; w1_char>=a1; w1_char=w1_char - 10) {w2_char=w1_char; if (xxx[w3_char] equal '/') w3_char++; do { if (xxx[w3_char] equal 'k') {sq[w2_char]=b_k; ++w3_char; sq_b_k[0]=w2_char; ++w2_char;} else if (xxx[w3_char] equal 'K') {sq[w2_char]=w_k; ++w3_char; sq_w_k[0]=w2_char; ++w2_char;} else if (xxx[w3_char] equal 'q') {sq[w2_char]=b_q; ++w3_char; ++w2_char;} else if (xxx[w3_char] equal 'Q') {sq[w2_char]=w_q; ++w3_char; ++w2_char;} else if (xxx[w3_char] equal 'r') {sq[w2_char]=b_r; ++w3_char; ++w2_char;} else if (xxx[w3_char] equal 'R') {sq[w2_char]=w_r; ++w3_char; ++w2_char;} else if (xxx[w3_char] equal 's') {sq[w2_char]=b_r; ++w3_char; if (w2_char equal a8) b_0_0_0[0]=not_allowed; else if (w2_char equal h8) b_0_0[0] =not_allowed; /* else {strcpy(fatal_tekst,"s-rook not on a8/h8"); goto fatal_error;} */ ++w2_char; } else if (xxx[w3_char] equal 'S') {sq[w2_char]=b_r; ++w3_char; if (w2_char equal a1) w_0_0_0[0]=not_allowed; else if (w2_char equal h1) w_0_0[0] =not_allowed; /* else {strcpy(fatal_tekst,"S-rook not on a1/h1"); goto fatal_error;} */ ++w2_char; } else if (xxx[w3_char] equal 'n') {sq[w2_char]=b_n; ++w3_char; ++w2_char;} else if (xxx[w3_char] equal 'N') {sq[w2_char]=w_n; ++w3_char; ++w2_char;} else if (xxx[w3_char] equal 'b') {sq[w2_char]=b_b; ++w3_char; ++w2_char;} else if (xxx[w3_char] equal 'B') {sq[w2_char]=w_b; ++w3_char; ++w2_char;} else if (xxx[w3_char] equal 'p') {sq[w2_char]=b_p; ++w3_char; ++w2_char;} else if (xxx[w3_char] equal 'P') {sq[w2_char]=w_p; ++w3_char; ++w2_char;} else if (xxx[w3_char]>='1' and xxx[w3_char]<='8') { --xxx[w3_char]; ++w2_char;} else if (xxx[w3_char] equal '0' or xxx[w3_char] equal '/') { ++w3_char;} /* else {strcpy(fatal_tekst,"ukendt tegn i input xxx[]"); goto fatal_error;}; */ } while (xxx[w3_char] != '/' and w3_char<81); } /* mangler: check at der er en hvid og sort konge */ if (xxx[++w3_char] equal 'b') wh_bl = black; else wh_bl = white; if (sq[a8] != b_r or sq[e8] != b_k) b_0_0_0[0] = not_allowed; if (sq[h8] != b_r or sq[e8] != b_k) b_0_0[0] = not_allowed; if (sq[a1] != w_r or sq[e1] != w_k) w_0_0_0[0] = not_allowed; if (sq[h1] != w_r or sq[e1] != w_k) w_0_0[0] = not_allowed; ply=0; ply_1=-1; ply_2=-2; change_black_white(); make_only_attack(); change_black_white(); make_move_array(); } void make_move() { signed char fr, to, fr_before, to_before, to_9_10_11, promote_piece; signed char promotion; ++ply; ++ply_1; ++ply_2; tv_nodes += + 1; many_movematingpiece[ply]=many_movematingpiece[ply_1]; moves_othermating_pieces[ply]=moves_othermating_pieces[ply_1]; many_movematedpiece[ply]=many_movematedpiece[ply_1]; moves_othermated_pieces[ply]=moves_othermated_pieces[ply_1]; w_0_0[ply]=w_0_0[ply_1];w_0_0_0[ply]=w_0_0_0[ply_1]; b_0_0[ply]=b_0_0[ply_1];b_0_0_0[ply]=b_0_0_0[ply_1]; legal_move_found[ply]=false; fr=move_fr[ply_1][ move_pointer[ply_1]]; to=move_to[ply_1][ move_pointer[ply_1]]; fr_before=sq[fr]; move_fr_before[ply_1]=fr_before; promotion=false; e_p[ply]=not_allowed; if (fr_before equal w_p * wh_bl) /* et bondetr‘k? */ {if (to<=h8) /* forvandling? nej */ {if ((to - fr) equal 20 * wh_bl) /* bondes dobbeltskridt */ e_p[ply]= fr + 10 * wh_bl; else {if ((to - fr) != 10 * wh_bl and sq[to] equal sq_empty) /* e.p. */ {sq[to - 10 * wh_bl] = sq_empty; /* bonden skal fjernes */ } } } else /* forvandling? ja */ {promotion=true; unpack_promotion(&to, &to_9_10_11, &promote_piece); to=fr + wh_bl * to_9_10_11; } }; to_before=sq[to]; move_to_before[ply_1]=to_before; if (mating_wh_bl equal wh_bl) {if (fr equal many_movematingpiece[ply]) many_movematingpiece[ply]=to; else moves_othermating_pieces[ply] -= 1; } else {if (fr equal many_movematedpiece[ply]) many_movematedpiece[ply]=to; else moves_othermated_pieces[ply] -= 1; } if (fr_before equal w_k) sq_w_k[ply]=to; else sq_w_k[ply]=sq_w_k[ply_1]; if (fr_before equal b_k) sq_b_k[ply]=to; else sq_b_k[ply]=sq_b_k[ply_1]; if (fr equal e1 or fr equal h1 or to equal h1) w_0_0[ply]=not_allowed; if (fr equal e8 or fr equal h8 or to equal h8) b_0_0[ply]=not_allowed; if (fr equal e1 or fr equal a1 or to equal a1) w_0_0_0[ply]=not_allowed; if (fr equal e8 or fr equal a8 or to equal a8) b_0_0_0[ply]=not_allowed; if (promotion equal true) sq[to]=promote_piece * wh_bl; else sq[to]=sq[fr]; sq[fr]=sq_empty; /* selve tr‘kket udf›res */ if (fr equal e1 and to equal g1 and fr_before equal w_k) {sq[h1]=sq_empty; sq[f1]=w_r;}; if (fr equal e1 and to equal c1 and fr_before equal w_k) {sq[a1]=sq_empty; sq[d1]=w_r;}; if (fr equal e8 and to equal g8 and fr_before equal b_k) {sq[h8]=sq_empty; sq[f8]=b_r;}; if (fr equal e8 and to equal c8 and fr_before equal b_k) {sq[a8]=sq_empty; sq[d8]=b_r;}; if (ply equal ply_mating and certain_piece_sq != none) {if (sq[certain_piece_sq] != certain_piece) {make_move_status=do_undo_move; goto make_move_exit;} } if (ply equal ply_mating and movemating_piece != none) {if (movemating_piece != fr_before) {make_move_status=do_undo_move; goto make_move_exit;} } if (ply equal ply_mating and captured_piece != none) {if (captured_piece != to_before) {make_move_status=do_undo_move; goto make_move_exit;} } if ((ply <= ply_mating) and (moves_othermating_pieces[ply] < 0 or moves_othermated_pieces[ply] < 0) ) {make_move_status=do_undo_move; goto make_move_exit;} make_only_attack(); change_black_white(); make_move_array(); change_black_white(); if ( (wh_bl equal white and attack_b_min[sq_w_k[ply]] equal b_p) or (wh_bl equal black and attack_w_min[sq_b_k[ply]] equal w_p) ) {make_move_status=do_undo_move; tv_pseudo_moves += 1; goto make_move_exit; } else legal_move_found[ply_1]=true; if (ply equal ply_mating) {if ( (wh_bl equal black and attack_b_min[sq_w_k[ply]] != b_p) or (wh_bl equal white and attack_w_min[sq_b_k[ply]] != w_p) ) {make_move_status=do_undo_move;} } make_move_exit: change_black_white(); } void undo_move() {signed char fr, to, to_9_10_11, promote_piece; --ply; --ply_1; --ply_2; change_black_white(); make_move_status=normal_move; /* tr‘kket f›res tilbage p† br‘ttet */ fr=move_fr[ply][ move_pointer[ply]]; sq[fr]=move_fr_before[ply]; to=move_to[ply][ move_pointer[ply]]; if (to>h8) /* ved forvandling skal to-feltet beregnes */ {unpack_promotion(&to, &to_9_10_11, &promote_piece); to=fr + wh_bl * to_9_10_11; }; sq[to]=move_to_before[ply]; if (fr equal e1 and to equal g1 and sq[fr] equal w_k) {sq[f1]=sq_empty; sq[h1]=w_r;}; if (fr equal e1 and to equal c1 and sq[fr] equal w_k) {sq[d1]=sq_empty; sq[a1]=w_r;}; if (fr equal e8 and to equal g8 and sq[fr] equal b_k) {sq[f8]=sq_empty; sq[h8]=b_r;}; if (fr equal e8 and to equal c8 and sq[fr] equal b_k) {sq[d8]=sq_empty; sq[a8]=b_r;}; if ((sq[to] equal w_p * wh_bl) and ((to - fr) != 20 * wh_bl)) {if ((to - fr) != 10 * wh_bl and sq[to] equal sq_empty) /* e.p. */ sq[to - 10 * wh_bl] = w_p * wh_bl; /* bonden inds‘ttes */ } ++move_pointer[ply]; /* peg p† det n‘ste tr‘k */ } void print_line() /* udskriver en variant */ {signed char fedtmule, fr, to, *nora, to_9_10_11, promote_piece, prom; ++count_solutions; ++screen_pause; if (screen_pause>screen_pause_limit) {screen_pause=1; press_return_to_continue(); } printf("\n"); for (fedtmule=0; fedtmuleh8) {unpack_promotion(&to, &to_9_10_11, &promote_piece); if (*nora>=w_p) to=fr + to_9_10_11; if (*nora<=b_p) to=fr - to_9_10_11; prom=men_letter[promote_piece]; } print_a1_h8(&to); printf("%c ",prom); /* if (fedtmule < (ply - 1)) printf(" "); */ } printf("#"); } void alfa_beta() { float kommatal; signed char last_ply; /* hvor dybt i ply g†r vi maksimalt ned? */ printf("\nN†r du nu trykker RETURN l›ber programmet "); printf("\nalle varianter i 3 ply igennem. "); printf("\nP† Jens' PC tager det 3,96 sec. svarende "); printf("\ntil 2425 nodes/sec. (i udgangsstillingen) "); press_return_to_continue(); gemtid=henttid(); tv_pseudo_moves=0; tv_nodes=0; last_ply=3; a: make_move(); if (ply0) goto b; tid=henttid(); printf("\nmoves searched (incl. illegal moves etc.) : %8.0f; ", tv_nodes); kommatal=(tid-gemtid); if (kommatal equal 0) kommatal=1; printf("\n %8.2f sec.", kommatal/100); printf("\n %8.0f nodes/sec.", (tv_nodes/(kommatal/100))); printf("\n max antal tr‘k : %d ",max_moves); press_return_to_continue(); move_pointer[0]=0; } void print_move() {signed char fr, to, nora, to_9_10_11, promote_piece, prom; fr=move_fr[0][ move_pointer[0]]; to=move_to[0][ move_pointer[0]]; nora = sq[fr]; if (nora <= b_p) nora = nora * -1; printf("\n"); print_kqrbnp(nora); print_a1_h8(&fr); prom=' '; if (to>h8) {unpack_promotion(&to, &to_9_10_11, &promote_piece); if (wh_bl equal white) to=fr + to_9_10_11; else to=fr - to_9_10_11; prom=men_letter[promote_piece]; } if (sq[to] equal sq_empty) printf("-"); else printf("x"); /* e.p... */ print_a1_h8(&to); printf("%c ",prom); } void find_helpmate(signed char iteration) { float kommatal; gemtid=henttid(); tv_pseudo_moves=0; tv_nodes=0; screen_pause=0; mating_wh_bl = wh_bl; if (iteration % 2 equal 0) mating_wh_bl = mating_wh_bl * -1; ply_mating =iteration; ply_mate =ply_mating + 1; /* ply_mating_1=ply_mating - 1; */ a: if (ply equal 0 and count_solutions equal 0) {print_move(); printf(" %d / %d moves so far: %8.0f",(int)move_pointer[0]+1, (int)mobilitet[0], tv_nodes); } make_move(); /* show_board(); */ if (make_move_status equal do_undo_move) goto b; if (move_fr[ply][move_pointer[ply]] equal stop) goto c; /* if ((int)tv_nodes % 10 equal 0) {printf("\npause 10 nodes %8.0f", tv_nodes); show_board(); } */ if (ply0) goto b; tid=henttid(); printf("\nmoves searched (incl. illegal moves etc.) : %8.0f; ", tv_nodes); kommatal=(tid-gemtid); if (kommatal equal 0) kommatal=1; printf("\n %8.2f sec.", kommatal/100); printf("\n %8.0f nodes/sec.", (tv_nodes/(kommatal/100))); move_pointer[0]=0; } void turnsquare(signed char *sq) {signed char r1, l1; sq120_to_koordinat(sq, &l1, &r1); *sq = (110 + (2 * l1)) - *sq; } void turn_black_white() {/* change_black_white(); */ if (movemating_piece != none) movemating_piece = movemating_piece * -1; if (captured_piece != none and captured_piece != sq_empty) captured_piece = captured_piece * -1; if (many_movematingpiece[0] != none) turnsquare(&many_movematingpiece[0]); if (many_movematedpiece[0] != none) turnsquare(&many_movematedpiece[0]); if (certain_piece_sq != none) {turnsquare(&certain_piece_sq); certain_piece = certain_piece * -1; } } void iterative_helpmate() {signed char turn=1, iteration; if (movemating_piece != none) {if (movemating_piece < 0) movemating_piece = movemating_piece * -1; if ( ((wh_bl equal white) and (iteration_from % 2 equal 0)) or ((wh_bl equal black) and (iteration_from % 2 equal 1)) ) movemating_piece = movemating_piece * -1; } if (captured_piece != none and captured_piece != sq_empty) {if (captured_piece < 0) captured_piece = captured_piece * -1; if ( ((wh_bl equal white) and (iteration_from % 2 equal 1)) or ((wh_bl equal black) and (iteration_from % 2 equal 0)) ) captured_piece = captured_piece * -1; } /* printf("\n iterative helpmate"); printf("\n iteration from : %d",(int)iteration_from); printf("\n iteration to : %d",(int)iteration_to); press_return_to_continue(); */ for (iteration=iteration_from; iteration<=iteration_to and count_solutions equal 0; iteration=iteration + iteration_step) {printf("\niteration: %d",(int)iteration); if (movemating_piece != none) printf("\nmovemating_piece %d",(int)movemating_piece); if (captured_piece != none) printf("\nmatecaptured_piece %d",(int)captured_piece); find_helpmate(iteration); if (iteration_step % 2 equal 1) {turn_black_white(); turn=turn * -1; } } printf("\n solutions found : %d ",count_solutions); count_solutions=0; if (turn equal -1) turn_black_white(); printf(" (max. number of moves found in a position : %d)",max_moves); press_return_to_continue(); } void menu_diverse() {signed char valg='0', dum; for (; valg!='X'; ) {printf("\n 1 Danish/English "); printf("%s",men_letter); printf("\n 2 Knight/Nightrider "); if (knight[0] equal one_step) printf("now: knight"); else printf("now: nightrider"); printf("\n X back to the main menu"); printf("\n\n?"); scanf("%c",&valg); valg=toupper(valg); scanf("%c",&dum); /* new-line */ if (valg equal '1') {if (men_letter[0] equal 'B') strcpy(men_letter,"P NBRQK"); else strcpy(men_letter,"B SLTDK"); } if (valg equal '2') {if (knight[0] equal one_step) {knight[0]=more_steps; men_value[w_k]=600;} else {knight[0]=one_step; men_value[w_k]=300;} make_move_array(); } } } void menu_positions() {signed char valg='0', dum; for (; valg!='X'; ) {printf("\n\n"); printf("\n 1 Show current position "); printf("\n 2 The startposition "); printf("\n 3 H#2 - 0-0 and 0-0-0. Solved in 167,41 sec. "); printf("\n 4 H#2 - 2 solutions in 1,65 sec. "); printf("\n 5 H#2 - Every move is a check; 2 sol: 190,06 sec. "); printf("\n 6 H#2 - 2 solutions. 12,41 sec. "); printf("\n 7 H#6 - set depth yourself and waite......; 3 sol. "); printf("\n 8 H#3 - all kind of promotions; 2 solutions; 131,21s."); printf("\n 9 H#2 - Nightrider (not e5....) 1 solution; 76,38 sec"); printf("\n A Type in your own position "); printf("\n X Back to the main menu "); printf("\n\n?"); scanf("%c",&valg); valg=toupper(valg); scanf("%c",&dum); /* new-line */ if (valg equal '1') show_board(); if (valg equal '2') {strcpy(xxx,"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR/w e2-e4! "); make_array_ply_zero(); show_board(); } if (valg equal '3') {strcpy(xxx,"8/8/8/8/3b1Bp1/p4k2/r7/R2NK2R/b Kf3-g2! / Bd4xa1!"); iteration_from=4;iteration_to=4; make_array_ply_zero(); show_board(); } if (valg equal '4') {strcpy(xxx,"8/8/8/8/8/1B2KN1k/8/8/b Kh3-g2! / Kh3-g4!"); iteration_from=4;iteration_to=4; make_array_ply_zero(); show_board(); } if (valg equal '5') {strcpy(xxx,"8/6N1/5K2/8/R1Nk4/6q1/B7/b7/b Qg3-d6+ / Qg3-f3+ "); iteration_from=4;iteration_to=4; make_array_ply_zero(); show_board(); } if (valg equal '6') {strcpy(xxx,"8/2KBkprN/8/8/8/8/8/8/b Tg7-g8! / f7-f6!"); iteration_from=4;iteration_to=4; make_array_ply_zero(); show_board(); } if (valg equal '7') {strcpy(xxx,"1n6/3r2p1/8/1b6/2k1q3/pp6/1pP4r/1Kn5/b 3 solutions"); make_array_ply_zero(); show_board(); } if (valg equal '8') {strcpy(xxx,"7K/8/3P3k/7b/6p1/8/3p4/8/b d2-d1B! / d2-d1R!"); iteration_from=6;iteration_to=6; make_array_ply_zero(); show_board(); } if (valg equal '9') {strcpy(xxx,"8/2n3n1/4N3/4N3/4K3/8/4p3/4k3/b Nc7-f1! "); iteration_from=4;iteration_to=4; make_array_ply_zero(); show_board(); } if (valg equal 'A') {printf("\n Type in a position - be careful!!"); printf("\n - any error may make the program crash"); printf("\n the startposition fx should be typed like this:"); printf("\n rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR/w\n?"); scanf("%s",xxx); scanf("%c",&dum); /* new-line */ make_array_ply_zero(); show_board(); } } } /* } */ void main_menu() {signed char valg='0', dum, z1, z2; int dummeint; for (; valg!='!'; ) { max_moves = 0; printf("\n\n\n\n\n B R U T A L I S ver. 1.0\n\n"); printf("\n by Jens B‘k Nielsen\n\n"); /* print_char(valg); */ printf("\n 1 Solve helpmate "); printf("\n 2 Depth including mating move - "); printf("from %d to %d (step %d)",(int)iteration_from, (int)iteration_to, (int)iteration_step); printf("\n 3 Menu: positions"); printf("\n 4 Menu: special options"); printf("\n 5 Movemating piece: "); if (movemating_piece equal none) printf("any piece"); else {dum=movemating_piece; if (dum<0) dum=dum * -1; if (dum equal 2) dum=0; printf("%c",men_letter[dum]); } printf("\n 6 Matecaptured piece: "); if (captured_piece equal none) printf("any piece"); else {if (captured_piece equal sq_empty) printf("empty square"); else {dum=captured_piece; if (dum<0) dum=dum * -1; if (dum equal 2) dum=0; printf("%c",men_letter[dum]); } } printf("\n 7 Square with a certain content: "); if (certain_piece_sq equal none) printf("none"); else {print_a1_h8(&certain_piece_sq); if (certain_piece equal sq_empty) printf(" empty square"); else { if (certain_piece <= b_p) printf(" black"); if (certain_piece >= w_p) printf(" white"); printf(" "); z1 = certain_piece; if (z1 < 0) z1 = z1 * -1; print_kqrbnp(z1); } } printf("\n 8 Mating side - many moves by piece on: "); if (many_movematingpiece[0] equal none) printf("none"); else {print_a1_h8(&many_movematingpiece[0]); printf(" (%d other move",(int)moves_othermating_pieces[0]); if (moves_othermating_pieces[0] != 1) printf("s"); printf(")"); } printf("\n 9 Mated side - many moves by piece on: "); if (many_movematedpiece[0] equal none) printf("none"); else {print_a1_h8(&many_movematedpiece[0]); printf(" (%d other move",(int)moves_othermated_pieces[0]); if (moves_othermated_pieces[0] != 1) printf("s"); printf(")"); } printf("\n ! Exit BRUTALIS\n\n"); printf("read the information in BRUTALIS.TXT -\n"); printf("2,3,4,5,6,7 is P,N,B,R,Q,K etc.\n\n?"); scanf("%c",&valg); valg=toupper(valg); if (valg != '\n') {scanf("%c",&dum);} /* new-line */ if (valg equal 'Z') alfa_beta(); if (valg equal 'T') turn_black_white(); if (valg equal '1') iterative_helpmate(); if (valg equal '2') {printf("\n first depth ? "); scanf("%d",&dummeint); iteration_from=dummeint; printf("\n last depth ? "); scanf("%d",&dummeint); iteration_to=dummeint; if (iteration_to - iteration_from > 1 and (iteration_to - iteration_from) % 2 equal 0) {printf("\n step 1 or 2 (1=change black-white mating) ? "); scanf("%d",&dummeint); iteration_step=dummeint; } } if (valg equal '3') menu_positions(); if (valg equal '4') menu_diverse(); if (valg equal '5') {printf("\n piece 2,3,4,5,6,7 or 10(any piece) ? "); scanf("%d",&dummeint); movemating_piece=dummeint; } if (valg equal '6') {printf("\n piece 0(empty square) 2,3,4,5,6,7 or 10(none) ? "); scanf("%d",&dummeint); captured_piece=dummeint; } if (valg equal '7') {a: printf("\n type in the square (a1,a2...h8). Use NO for none"); printf("\n\n?"); scanf("%s",xxx); if (xxx[2] != '\0') {beep(); printf("\n 2 characters!\n");goto a;} z1=xxx[0]; z1=tolower(z1); z2=xxx[1]; if (z1 equal 'n') certain_piece_sq = none; else {certain_piece_sq = (10 + (z2 - '1' + 1) * 10) + (z1 - 'a' + 1); printf("\n piece on a certain square - 0(empty) 2,3,4,5,6,7"); printf("\n use negative numbers for black pieces\n\n ?"); scanf("%d",&dummeint); certain_piece=dummeint; } } if (valg equal '8') {b: printf("\n type in the square (a1,a2...h8). Use NO for none"); printf("\n\n?"); scanf("%s",xxx); if (xxx[2] != '\0') {beep(); printf("\n 2 characters!\n");goto b;} z1=xxx[0]; z1=tolower(z1); z2=xxx[1]; if (z1 equal 'n') {many_movematingpiece[0] = none; moves_othermating_pieces[0]=99;} else {many_movematingpiece[0] = (10 + (z2 - '1' + 1) * 10) + (z1 - 'a' + 1); printf("\n allowed number of moves by other pieces 0,1...99\n\n ?"); scanf("%d",&dummeint); moves_othermating_pieces[0]=dummeint; } } if (valg equal '9') {c: printf("\n type in the square (a1,a2...h8). Use NO for none"); printf("\n\n?"); scanf("%s",xxx); if (xxx[2] != '\0') {beep(); printf("\n 2 characters!\n");goto c;} z1=xxx[0]; z1=tolower(z1); z2=xxx[1]; if (z1 equal 'n') {many_movematedpiece[0] = none; moves_othermated_pieces[0]=99;} else {many_movematedpiece[0] = (10 + (z2 - '1' + 1) * 10) + (z1 - 'a' + 1); printf("\n allowed number of moves by other pieces 0,1...99\n\n ?"); scanf("%d",&dummeint); moves_othermated_pieces[0]=dummeint; } } } } void main() { strcpy(men_letter,"P NBRQK"); iteration_from=3; iteration_to=3; iteration_step=1; screen_pause_limit=10; certain_piece=none; certain_piece_sq=none; /* certain_rowpiece=none; */ movemating_piece=none; captured_piece=none; /* many_movematingpiece_all=none; */ many_movematingpiece[0]=none; moves_othermating_pieces[0]=99; /* many_movematedpiece_all=none; */ many_movematedpiece[0]=none; moves_othermated_pieces[0]=99; count_solutions=0; make_move_status=normal_move; randomize(); strcpy(fatal_tekst," "); strcpy(xxx,"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR/w "); make_array_ply_zero(); main_menu(); press_return_to_continue(); }