#include<dos.h>
#include<time.h>
#include<stdio.h>
#include<conio.h>
char N[65][8][8]; //Casilla de origen, direccion, alcance=Casilla destino
char H[8][65][8]; //Tipo de pieza, casilla, direccion=Alcance
int A[33],C[33],T[33]; //Tipo,casilla y bando (0vacia,1PB,2PN,3C,4A,5T,6D,7R)
int G[9],C1[9],C2[9],C3[9];
int K[65],P[65],e[8][8],p[6][576];
int main()
{
_AX=0x13;
geninterrupt(0x10);
time_t ti;
char E,far*Q[65],far*q=(char far*)0xA0000000;
char pieza[][6][22]={"00000000000000000000","00000000200020000000","00000000000000000000","00000000000000000000","00000022000022000000","00000000022000000000",
"00000000000000000000","00000000220220000000","00022222222222200000","00000000000000000000","00000222200222200000","00000000022000000000",
"00000000222200000000","00000000222220000000","00002222222222220000","00022200222200222000","02200222200222200220","00000002222220000000",
"00000002222220000000","00000002222222000000","00000222111111222000","00022200222200222000","22220022000022002222","00000002222220000000",
"00000002222220000000","00000022222212200000","00000002222222122200","00022200222200222000","22220002000020002222","02222200022000222220",
"00000002222220000000","00000222222221220000","00002022222222212220","00022222222222222000","02200002200220000220","22111220022002211122",
"00000000222200000000","00002222112222122000","00002022222222212220","00022222222222222000","00220002200220002200","21222122211222122212",
"00000002222220000000","00002222122222122000","00022122222222221220","00000211111111200000","00022002200220022000","21222212211221222212",
"00000022222222000000","00022222222222122000","00222212112222221220","00000222222222200000","00022202222220222000","22122221222212222122",
"00000022222222000000","00222222222222122200","02221221221222221220","00000222222222200000","00022222222222222000","02212222122122221220",
"00000022222222000000","02222222222222212200","22212222121222221220","00000222222222200000","00022222222222222000","00221222222222212200",
"00000002222220000000","22122222222222212200","02221221221222221220","00000222222222200000","00022222222222222000","00022222222222222000",
"00000022222222000000","21122222221222212200","00222212112222221220","00000222222222200000","00021111111111112000","00021111111111112000",
"00000222222222200000","02222220012222212200","00022122222222222220","00000222222222200000","00222222222222222200","00222222222222222200",
"00000222222222200000","00022000222222212220","00002022222222200220","00000222222222200000","02222222222222222220","02222222222222222220",
"00002222222222220000","00000000222222221220","00000002222222000220","00000222222222200000","00222222222222222200","00222222222222222200",
"00002222222222220000","00000002222222221220","00000000222220000020","00002111111111120000","00021111111111112000","00021111111111112000",
"00002222222222220000","00000002222222221220","00000022222222200000","00022222222222222000","00022222222222222000","00022222222222222000",
"00002222222222220000","00000022222222221220","00002222222222222000","00222222222222222200","00222222222222222200","00222222222222222200",
"00000000000000000000","00000022222222222220","00022222200002222200","00222222222222222200","00222222222222222200","00222222222222222200",
"00000000000000000000","00000000000000000000","00222220000000000000","00000000000000000000","00000000000000000000","00000000000000000000"};
char figura[][5][13]={"0000001010000","0011111111000","0111011101110","0001110111000","0000001000000",
"0000011110000","0001000000100","0101110111010","1101110111011","0000011100000",
"0000100001000","0000111110010","0100000000010","1100100010011","0111001001110",
"0001000010100","0001000001001","0111111111110","0100100010010","1000101010001",
"0010010001010","0010000000101","0001000001000","0100110110010","1010010100101",
"0010000001010","0101010000101","0001000001000","0110110110110","1001001001001",
"0100000001001","1000101000101","0001000001000","0101001001010","1000100010001",
"1000011000101","0101010000101","0001000001000","0100000000010","0100010100010",
"0111101000101","0010000000101","0001000001000","0010000000100","0010000000100",
"0000010000101","0001000001011","0001111111000","0011111111100","0011111111100",
"0000100000101","0000100010001","0010000000100","0100000000010","0100000000010",
"0001000000101","0001000111000","0100000000010","1000000000001","1000000000001",
"0001111111111","0011111000000","0111111111110","1111111111111","1111111111111"};
int posicion[][3][8]={-5,-3,-4,-6,-7,-4,-3,-5, 00,00,00,00,00,00,05,00, 00,00,00,00,00,00,00,00,
-2,-2,-2,-2,-2,-2,-2,-2, 00,00,07,00,00,00,00,00, 05,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,00, 00,00,00,00,-7,01,01,00,
00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,00, 00,00,00,-2,-2,-2,00,00,
00,00,00,00,00,00,00,00, 00,00,00,00,00,-2,00,00, 00,00,00,04,00,01,00,00,
00,00,00,00,00,00,00,00, 00,00,00,00,00,00,-2,00, 00,07,00,01,00,01,00,00,
01,01,01,01,01,01,01,01, 00,06,00,00,00,03,-7,00, 00,00,00,00,00,00,00,00,
05,03,04,06,07,04,03,05, 00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,00};
int B[65],BB[8]={0,1,0,-1,-2,0,2,0}; //Promocion y al paso
int S[201][4],J[201][9],JJ[9][9]; //Control de jugadas
int m[201][6],mm[2][2][9][6]; //Secuencia de mate
int aa[9],dd[9],hh[9]; //Rutina principal
int pc1[9],pc2[9],pc3[9]; //Piezas
int pr[3],R[]={0,5,61}; //Casilla rey de inicio
int P1[]={0,1,33}; //Blancas de 1 a P2[1]
int P2[]={0,0,32}; //Negras de P1[2] a 32
int f[65]={1},F[][3]={0,15,0,0,0,15,0,15,0}; //Fondo, perfil
int i[576],I[]={195,227,284,316}; //Tabulacion
int X[13][4]={1155,1219,1219,1276};
int L[]={-1,1,-1,1,-1,1,-1,1,-1};
int LL[]={400,0,400,0,400,0,400,0,400};
int ix[]={-1,0,1,1,1,0,-1,-1,1,2,2,1,-1,-2,-2,-1};
int iy[]={1,1,1,0,-1,-1,-1,0,2,1,-1,-2,-2,-1,1,2};
int D[]={0,2,0,0,0,1,0,0}; //Peon al frente
int d1[]={0,0,4,0,0,1,0,0};
int d2[]={0,2,6,7,6,7,7,7};
int d3[]={0,1,1,1,2,2,1,1};
int Z[]={0,0,0,1,2,3,4,5};
int c=64,h=1,t=1,tt=2,M=3;
int a,b,d,j,n,v,w,z,x,y,c1,c2,V,W;
for(v=576;v--;i[v]=320*y+v%24)
if((y=v/24)>1&&y<22&&(x=v%24)>1&&x<22)
for(w=6;w--;) p[w][v]=pieza[y-2][w][x-2]-48;
for(a=8;--a;)
for(d=d1[a];d<=d2[a];d+=d3[a])
if(a>6) e[7][d]=2;
else if(a>3) e[a][d]=8;
else if(a<3&&!D[d]) e[3-a][d]=2;
for(v=0;v<8;v++)
for(w=8;w--;B[c--]=BB[v])
if((a=posicion[v][1][w])>0){ //Eleccion de posicion[][?][]
A[++P2[1]]=a;
P[C[P2[1]]=c]=P2[1];
T[P2[1]]=1;
if(a>6) pr[1]=P2[1];
}
else if(a<0){
A[--P1[2]]=-a;
P[C[P1[2]]=c]=P1[2];
T[P1[2]]=2;
if(-a>6) pr[2]=P1[2];
}
do{
y=c++/8;
x=c-8*y;
Q[c]=q+7680*(7-y)+24*x+936;
f[c]=4-f[c-1];
if(x<2) f[c]=4-f[c];
if(a=A[P[c]]) F[T[P[c]]][0]=f[c];
for(v=576;v--;)
*(Q[c]+i[v])=a?F[T[P[c]]][p[Z[a]][v]]:f[c];
for(d=8;d--;h=1){
if((v=x+ix[d+8])>0&&v<9&&(w=y+iy[d+8])>-1&&w<8)
N[c][d][H[3][c][d]--]=v+8*w;
while((v=x+ix[d]*h)>0&&v<9&&(w=y+iy[d]*h)>-1&&w<8)
N[c][d][h++]=v+8*w;
for(a=--h?8:1;--a;)
if(a>6) H[a][c][d]=R[T[P[c]]]==c&&(d==3||d==7)?2:1;
else if(a>3&&e[a][d]) H[a][c][d]=h;
else if(a<3) if(e[3-a][d]) H[a][c][d]=1;
else if(D[d]==3-a)
H[a][c][d]=B[c]==3-a?2:1;
}
}while(c<64);
printf("%c[2;26fBlancas Negras",27);
for(v=13;v--;)
for(d=4;d--;y=x){
if(v) X[v][d]=5120*v+I[d]+960;
x=X[v][d];
if(v>11||d>2) continue;
for(w=y-x+1;w--;)
*(q+x+w)=*(q+x+w+5120)=7;
for(w=16;w--;)
*(q+x+320*w)=*(q+y+320*w)=7;
}
Inicio:
ti=time(NULL);
for(j=v=0;v<M;v++)
for(w=0;w++<M-v;) JJ[w][v+w]=LL[w];
pc1[n=1]=P1[t]; //Primera pieza
Origen:
C1[n]=C[pc1[n]]; //Casilla de la pieza
if(!C1[n]) goto Siguiente;
K[C1[n]]++; //Simulacion de origen
P[C1[n]]=0;
aa[n]=A[pc1[n]]; //Tipo de pieza
dd[n]=d1[aa[n]]; //Direccion inicial
Alcance:
hh[n]=H[aa[n]][C1[n]][dd[n]]; //Alcance total
if(!hh[n]) goto Direccion;
G[n]=aa[n]!=3; //Alcance inicial (0 para el caballo)
Destino:
C2[n]=N[C1[n]][dd[n]][G[n]]; //Casilla destino
pc2[n]=P[C2[n]]; //Pieza en destino
if(T[pc2[n]]==t) goto Direccion; //Mismo bando
if(aa[n]<3) //Peon
if(D[dd[n]]==T[pc2[n]]){
if(pc2[n]||B[C1[n]]+t) goto Direccion;
if(aa[n-1]>2||G[n-1]<2) goto Direccion;
if(2*C2[n]!=C1[n-1]+C2[n-1]) goto Direccion;
C3[n]--; //Simular captura
pc3[n]=P[C2[n-1]];
C[pc3[n]]=P[C2[n-1]]=0;
}
else if(B[C1[n]]==t) A[pc1[n]]=6; //Promocion
if(aa[n]>6&&G[n]>1) //Enroque
if(K[R[t]]>1||pc2[n]) goto Direccion;
else{
c=R[t]; //Casilla del rey en origen
for(d=0;d<8;d++)
if(T[x=P[N[c][d][0]]]==tt&&A[x]==3) d=8;
else for(h=0;h++<H[6][c][d];)
if(x=P[N[c][d][h]]) if(T[x]==tt&&h<e[A[x]][d]) h=d=8; //Jaque
else break;
if(d=d>8) goto Direccion;
if(c<C2[n]) if(K[c+3]||P[c+3]!=pr[t]-3*L[t]) goto Direccion;
else C3[n]=c+3; //Enroque corto
if(c>C2[n]) if(K[c-4]+P[c-3]||P[c-4]!=pr[t]+4*L[t]) goto Direccion;
else C3[n]=c-4;
pc3[n]=P[C3[n]]; //Simulacion de enroque
C[pc3[n]]=(c+C2[n])/2;
P[C3[n]]=0;
P[(c+C2[n])/2]=pc3[n];
}
Simulacion:
C[pc1[n]]=C2[n]; //Pieza a destino
C[pc2[n]]=0;
P[C2[n]]=pc1[n];
c=C[pr[t]]; //Casilla del rey
for(d=0;d<8;d++)
if(T[x=P[N[c][d][0]]]==tt&&A[x]==3) d=8;
else for(h=0;h++<H[6][c][d];)
if(x=P[N[c][d][h]]) if(T[x]==tt&&h<e[A[x]][d]) h=d=8; //Jaque
else break;
if(d<9&&n<M){ //Nivel siguiente
t=3-(tt=t);
pc1[++n]=P1[t];
goto Origen;
}
Restaurar:
C[pc2[n]]=C2[n];
P[C2[n]]=pc2[n];
if(C3[n]<0){ //Al paso
C[pc3[n]]=C2[n-1];
P[C2[n-1]]=pc3[n];
C3[n]++;
}
if(C3[n]){ //Enroque
C[pc3[n]]=C3[n];
P[C3[n]]=pc3[n];
P[(R[t]+C2[n])/2]=C3[n]=0;
}
if(d=d>8) hh[n]-=aa[n]>6; //No permite enroque
else{
JJ[1][n]+=2; //Jugadas posibles
if(n==1){
S[++j][0]=A[pc1[1]]>aa[1]?A[pc1[1]]:0;
S[j][1]=C1[1];
S[j][2]=C2[1];
S[j][3]=M-1;
for(v=0;++v<M;)
if(JJ[v][v+1]>1) J[j][v]=JJ[v][v+1]/2;
else{
J[j][v]=JJ[v][v+1]-1;
J[j][v+1]=200-J[j][v];
S[j][3]=v+(L[v]==L[M]);
for(w=v-1;w--;)
m[j][w]=mm[J[j][v]+1][0][v+1][w];
break;
}
}
else for(v=0;v++<M-n;){ //Minimax
x=JJ[v+1][n+v]-JJ[v][n+v];
if(L[v]!=(x>0)-(x<0)) continue;
JJ[v+1][n+v]=JJ[v][n+v]; //Confirma secuencia
if(v==3&&n<4) for(y=2;y--;)
for(w=n+1;w--;)
mm[y][0][n+3][w]=mm[y][1][n+3][w];
}
}
for(v=n;v<M;v++) //Reinicio de contadores
for(w=0;w++<M-v;) JJ[w][v+w]=LL[w];
if(A[pc1[n]]>aa[n]) if(--A[pc1[n]]>2) goto Simulacion;
else A[pc1[n]]=t; //Subpromocion
if(!pc2[n]&&G[n]++<hh[n]) goto Destino;
Direccion:
dd[n]+=d3[aa[n]];
if(dd[n]<=d2[aa[n]]) goto Alcance;
K[C1[n]]--; //Restaura origen
C[pc1[n]]=C1[n];
P[C1[n]]=pc1[n];
Siguiente:
if(pc1[n]++<P2[t]) goto Origen; //Pieza siguiente
if(!JJ[1][n]){
c=C[pr[t]]; //Casilla del rey
for(d=0;d<8;d++)
if(T[x=P[N[c][d][0]]]==tt&&A[x]==3) d=8; //Jaque del caballo
else for(h=0;h++<H[6][c][d];)
if(x=P[N[c][d][h]]) if(T[x]==tt&&h<e[A[x]][d]) h=d=8;
else break;
y=JJ[1][n]=d=d<9;
for(v=0;v<n-2;v++) //Secuencia de mate o ahogado
if(aa[v+2]!=B[C1[v+2]]) mm[y][n>4][n][v]=100*aa[v+2]+C2[v+2];
else mm[y][n>4][n][v]=-100*A[pc1[v+2]]-C2[v+2];
}
if(--n){
t=3-(tt=t);
goto Restaurar;
}
for(v=11-M;v--;)
for(d=3;d--;)
for(b=X[v+M+2][d]+1,V=15;V--;)
for(b-=320,W=d==1?55:31;W--;) *(q+b+W)=0;
h=4+2*M;
for(v=10-M;v--;)
if(v<j){ //Ordenar maximos o minimos
for(x=y=0;y++<j;)
if(S[y][3])
if(!x) x=y;
else if(L[M]==((V=J[x][S[x][3]])<(W=J[y][S[y][3]]))-(V>W)) x=y;
else if(V==W&&S[x][3]>S[y][3]) x=y;
y=J[x][S[x][3]++];
gotoxy(26+(t+M)%2*11,h+=2);
if(y>0&&y<200) printf("%3u",y);
else if(y==0||y==200) printf("1/2");
else if(y==LL[S[x][3]-t]/2-L[S[x][3]-t]) printf("1-0");
else printf("0-1");
printf("%c[%u;32f%c%c",27,h,97+(S[x][2]-1)%8,49+(S[x][2]-1)/8);
S[x][3]=0;
b=552+2560*h;
if(a=S[x][0]) b+=34;
else a=A[P[S[x][1]]];
if(z=Z[a]) for(V=13;V--;b-=320)
for(W=13;W--;)
*(q+b+W)=F[0][figura[V][z-1][W]-48];
}
printf("%c[%u;26fN=%u",27,4+2*M,M);
printf("%c[%u;30f%5.f%c",27,4+2*M,difftime(time(NULL)+1,ti),34);
c1=c2=R[t]; //Casilla del rey en origen
while(kbhit()) getch();
Cursor:
if(c2){
for(y=M;y--;)
for(d=3;d--;)
for(b=X[y+2][d]+1,V=15;V--;)
for(b-=320,W=d==1?55:31;W--;) *(q+b+W)=0;
gotoxy(15+11*t,4);
if(j) printf("%3u",j);
else if(JJ[1][1]) printf("1/2");
else if(t<2) printf("0-1");
else printf("1-0");
}
c=c1; //Casilla de origen
c2=x=0;
for(v=576;v--;)
if(*(Q[c]+i[v])==f[c]) *(Q[c]+i[v])=6+t;
while(!(E=getch()));
if(E==27&&!j) return 0;
if(E!=13){
if(E==77&&c1<64) c1++;
if(E==75&&c1>1) c1--;
if(E==72&&c1<57) c1+=8;
if(E==80&&c1>8) c1-=8;
for(v=576;v--;)
if(*(Q[c]+i[v])==6+t) *(Q[c]+i[v])=f[c];
y=M+(E=='+'&&M<8)-(E=='-'&&M>2);
if(y==M) goto Cursor;
M=y;
goto Inicio;
}
Eleccion:
if((x+=E!=75)>j||(x-=E==75)<1) if(!c2) goto Cursor;
else x=x<1?j:1;
if(S[x][1]!=c1) goto Eleccion;
c2=S[x][2];
printf("%c[4;32f%c%c",27,97+(c2-1)%8,49+(c2-1)/8);
b=10792;
if(a=S[x][0]) b+=34;
else a=A[P[c1]];
if(z=Z[a]) for(V=13;V--;b-=320)
for(W=13;W--;)
*(q+b+W)=F[0][figura[V][z-1][W]-48];
F[t][0]=9-t;
for(v=576;v--;)
*(Q[c2]+i[v])=F[t][p[z][v]];
for(a=y=0;++y<M;){
gotoxy(37-(y+t)%2*11,h=4+2*y);
for(d=3;d--;)
for(b=X[h/2][d]+1,V=15;V--;)
for(b-=320,W=d==1?55:31;W--;) *(q+b+W)=0;
if(!a) if(J[x][y]>0) printf("%3u",J[x][y]);
else if(!J[x][a=y]) printf("1/2");
else if((y+t)%2) printf("0-1");
else printf("1-0");
}
while(--a>0){
b=586+2560*(h=4+2*a);
y=m[x][a-1];
if(y>0) b-=34;
else y=-y;
printf("%c[%u;32f%c%c",27,h,97+(y%100-1)%8,49+(y%100-1)/8);
if(z=Z[y/100]) for(V=13;V--;b-=320)
for(W=13;W--;)
*(q+b+W)=F[0][figura[V][z-1][W]-48];
}
while(!(E=getch()));
if(a=A[P[c2]]) F[T[P[c2]]][0]=f[c2]; //Pieza a capturar
for(v=576;v--;)
*(Q[c2]+i[v])=a?F[T[P[c2]]][p[Z[a]][v]]:f[c2];
if(E==27) goto Cursor;
if(E!=13) goto Eleccion;
if(S[x][0]) A[P[c1]]=S[x][0]; //Promocion
aa[0]=A[P[c1]]; //Posibilitar al paso
G[0]=L[t]*(c2-c1)/8;
if(!a&&aa[0]<3&&(c1-c2)%8){
c=C2[0];
P[c]=A[P[c]]=C[P[c]]=0;
for(v=576;v--;)
*(Q[c]+i[v])=f[c];
}
C1[0]=c1; //Casilla origen
C2[0]=c2; //Casilla destino
K[c1]=K[c2]=1; //Casilla usada
do{
C[P[c1]]=c2;
C[P[c2]]=0;
P[c2]=P[c1];
P[c1]=c=0;
for(v=576;v--;)
*(Q[c1]+i[v])=f[c1];
a=A[P[c2]]; //Pieza
F[t][0]=f[c2];
for(v=576;v--;)
*(Q[c2]+i[v])=F[t][p[Z[a]][v]];
if(a>6) if(c2-c1==2) c=c2+1;
else if(c1-c2==2) c=c2-2;
c2=(c1+c2)/2;
}while(c1=c);
t=3-(tt=t);
goto Inicio;
}