program shakkipeli; uses Sysutils,bigdecimalmath; //For the first four moves of chess alone, there are 318,979,564,000 possible moves // There are 400 distinct chess positions after two moves const maxtaso=3; type nappula = (a1,b1,c1,d1,e1,f1,g1,h1,a2,b2,c2,d2,e2,f2,g2,h2,a7,b7,c7,d7,e7,f7,g7,h7,a8,b8,c8,d8,e8,f8,g8,h8,tyhja); ind=1..8; pelilauta = array[ind,ind] of nappula; siirrot=^siirto; //kerätään mahdolliset siirrot siirto=record mistarivi: ind; mistasara: ind; mihinrivi: ind; mihinsara: ind; nap:nappula; seuraava: siirrot; edel: siirrot; end; laudat=^pelilautatietue; //pino kunkin haaran eri pelitilanteille ja mahdollisille siirroille siinä pelitilanteessa. //Koko pelipuuta ei rakenneta. pelilautatietue=record lautatilanne: pelilauta; lautatilanteensiirrot: siirrot; aiempi: laudat; seuraava: laudat; end; var lauta,seuraavalauta,apulauta: laudat; //pidetään yllä laudan pelitilannetta seuraavasiirto,valkmahdollisetsiirrot,mustmahdollisetsiirrot,edellinen,apusiirrot: siirrot; i,j: ind; siirtojenlukumaara: BigDecimal; siirtotaso:integer; str:string; function nappulaonvalkoinen(r,s:ind):boolean; //onko koordinaateissa r s sijaitseva nappula valkoinen? begin if lauta^.lautatilanne[r,s] in [a1,b1,c1,d1,e1,f1,g1,h1,a2,b2,c2,d2,e2,f2,g2,h2] then nappulaonvalkoinen:=true else nappulaonvalkoinen:=false; end; function nappulaonmusta(r,s:ind):boolean; //Onko koordinaateissa r,s sijaitseva nappula musta? begin if lauta^.lautatilanne[r,s] in [a8,b8,c8,d8,e8,f8,g8,h8,a7,b7,c7,d7,e7,f7,g7,h7] then nappulaonmusta:=true else nappulaonmusta:=false; end; procedure valklisaasiirto(r,s,rivi,sarake:ind); begin siirtojenlukumaara:=siirtojenlukumaara+1; //writeln(lauta^.lautatilanne[r,s],rivi,sarake); seuraavasiirto:=new(siirrot); seuraavasiirto^.mihinrivi:=rivi; seuraavasiirto^.mihinsara:=sarake; seuraavasiirto^.mistarivi:=r; seuraavasiirto^.mistasara:=s; seuraavasiirto^.nap:=lauta^.lautatilanne[r,s]; if valkmahdollisetsiirrot = nil then begin // Lista on tyhjä, lisätään uusi alkio suoraan valkmahdollisetsiirrot := seuraavasiirto; end else begin // Etsitään listan loppu edellinen := valkmahdollisetsiirrot; while edellinen^.seuraava <> nil do edellinen := edellinen^.seuraava; // Lisätään uusi alkio listan loppuun edellinen^.seuraava := seuraavasiirto; end; end; procedure mustlisaasiirto(r,s,rivi,sarake:ind); begin siirtojenlukumaara:=siirtojenlukumaara+1; //writeln(lauta^.lautatilanne[r,s],rivi,sarake); seuraavasiirto:=new(siirrot); seuraavasiirto^.mihinrivi:=rivi; seuraavasiirto^.mihinsara:=sarake; seuraavasiirto^.mistarivi:=r; seuraavasiirto^.mistasara:=s; seuraavasiirto^.nap:=lauta^.lautatilanne[r,s]; if mustmahdollisetsiirrot = nil then begin // Lista on tyhjä, lisätään uusi alkio suoraan mustmahdollisetsiirrot := seuraavasiirto; end else begin // Etsitään listan loppu edellinen := mustmahdollisetsiirrot; while edellinen^.seuraava <> nil do edellinen := edellinen^.seuraava; // Lisätään uusi alkio listan loppuun edellinen^.seuraava := seuraavasiirto; end; end; procedure valksotilasiir(r,s:ind); //Tutkitaan valkoisen sotilaan siirrot begin if (r<=7) then begin if lauta^.lautatilanne[r-1,s]=tyhja then // valkoinen sotilas pystyy siirtymään yhden begin valklisaasiirto(r,s,r-1,s); end; if (r=7) and (lauta^.lautatilanne[r-2,s]=tyhja) and (lauta^.lautatilanne[r-1,s]=tyhja) then //vsotilas pystyy siirtymään kaksi eteenpäin begin valklisaasiirto(r,s,r-2,s); end; if s>1 then //pystyykö vsotilas syömään vasemmalta? if nappulaonmusta(r-1,s-1) then begin valklisaasiirto(r,s,r-1,s-1); end; if s<8 then //pystyykö vsotilas syömään oikealta? if nappulaonmusta(r-1,s+1) then begin valklisaasiirto(r,s,r-1,s+1); end; end; end; procedure mustsotilasiir(r,s:ind); //Tutkitaan musta sotilaan siirrot begin if (r<=7) then begin if lauta^.lautatilanne[r+1,s]=tyhja then // musta sotilas pystyy siirtymään yhden begin mustlisaasiirto(r,s,r+1,s); end; if (r=2) and (lauta^.lautatilanne[r+2,s]=tyhja) and (lauta^.lautatilanne[r+1,s]=tyhja) then //vsotilas pystyy siirtymään kaksi eteenpäin begin mustlisaasiirto(r,s,r+2,s); end; if s>1 then //pystyykö musta sotilas syömään vasemmalta? if nappulaonvalkoinen(r+1,s-1) then begin mustlisaasiirto(r,s,r+1,s-1); end; if s<8 then //pystyykö musta sotilas syömään oikealta? if nappulaonvalkoinen(r+1,s+1) then begin mustlisaasiirto(r,s,r+1,s+1); end; end; end; procedure valkratsusiir(r,s:ind); //tutkitaan valkean ratsun siirrot begin if (r>2) and (s>1) and ((lauta^.lautatilanne[r-2,s-1]=tyhja) or nappulaonmusta(r-2,s-1)) then begin valklisaasiirto(r,s,r-2,s-1); end; if (r>2) and (s<8) and ((lauta^.lautatilanne[r-2,s+1]=tyhja) or nappulaonmusta(r-2,s+1)) then begin valklisaasiirto(r,s,r-2,s+1); end; if (r>1) and (s<7) and ((lauta^.lautatilanne[r-1,s+2]=tyhja) or nappulaonmusta(r-1,s+2)) then begin valklisaasiirto(r,s,r-1,s+2); end; if (r<8) and (s<7) and ((lauta^.lautatilanne[r+1,s+2]=tyhja) or nappulaonmusta(r+1,s+2)) then begin valklisaasiirto(r,s,r+1,s+2); end; if (r<7) and (s<8) and ((lauta^.lautatilanne[r+2,s+1]=tyhja) or nappulaonmusta(r+2,s+1)) then begin valklisaasiirto(r,s,r+2,s+1); end; if (r<7) and (s>1) and ((lauta^.lautatilanne[r+2,s-1]=tyhja) or nappulaonmusta(r+2,s-1)) then begin valklisaasiirto(r,s,r+2,s-1); end; if (r<8) and (s>2) and ((lauta^.lautatilanne[r+1,s-2]=tyhja) or nappulaonmusta(r+1,s-2)) then begin valklisaasiirto(r,s,r+1,s-2); end; if (r<8) and (s>2) and ((lauta^.lautatilanne[r+1,s-2]=tyhja) or nappulaonmusta(r+1,s-2)) then begin valklisaasiirto(r,s,r+1,s-2); end; end; procedure mustratsusiir(r,s:ind); //tutkitaan valkean ratsun siirrot begin if (r>2) and (s>1) and ((lauta^.lautatilanne[r-2,s-1]=tyhja) or nappulaonvalkoinen(r-2,s-1)) then begin mustlisaasiirto(r,s,r-2,s-1); end; if (r>2) and (s<8) and ((lauta^.lautatilanne[r-2,s+1]=tyhja) or nappulaonvalkoinen(r-2,s+1)) then begin mustlisaasiirto(r,s,r-2,s+1); end; if (r>1) and (s<7) and ((lauta^.lautatilanne[r-1,s+2]=tyhja) or nappulaonvalkoinen(r-1,s+2)) then begin mustlisaasiirto(r,s,r-1,s+2); end; if (r<8) and (s<7) and ((lauta^.lautatilanne[r+1,s+2]=tyhja) or nappulaonvalkoinen(r+1,s+2)) then begin mustlisaasiirto(r,s,r+1,s+2); end; if (r<7) and (s<8) and ((lauta^.lautatilanne[r+2,s+1]=tyhja) or nappulaonvalkoinen(r+2,s+1)) then begin mustlisaasiirto(r,s,r+2,s+1); end; if (r<7) and (s>1) and ((lauta^.lautatilanne[r+2,s-1]=tyhja) or nappulaonvalkoinen(r+2,s-1)) then begin mustlisaasiirto(r,s,r+2,s-1); end; if (r<8) and (s>2) and ((lauta^.lautatilanne[r+1,s-2]=tyhja) or nappulaonvalkoinen(r+1,s-2)) then begin mustlisaasiirto(r,s,r+1,s-2); end; if (r<8) and (s>2) and ((lauta^.lautatilanne[r+1,s-2]=tyhja) or nappulaonvalkoinen(r+1,s-2)) then begin mustlisaasiirto(r,s,r+1,s-2); end; end; procedure valkoinentornisyo(r,s:ind); //tutkitaan valkean tornin mahdolliset syönnit var rr,ss:integer; begin rr:=-1; if (r>1) then begin while (lauta^.lautatilanne[r+rr,s]=tyhja) do begin r:=r-1; end; if nappulaonmusta(r-1,s) then valklisaasiirto(r,s,r-1,s); end; rr:=1; if (r<8) then begin while (lauta^.lautatilanne[r+rr,s]=tyhja) do begin r:=r+1; end; if nappulaonmusta(r+1,s) then valklisaasiirto(r,s,r+1,s); end; ss:=1; if (s<8) then begin while (lauta^.lautatilanne[r,s+ss]=tyhja) do begin s:=s+1; end; if nappulaonmusta(r,s+1) then valklisaasiirto(r,s,r,s+1); end; ss:=-1; if (s>1) then begin while (lauta^.lautatilanne[r,s+ss]=tyhja) do begin s:=s-1; end; if nappulaonmusta(r,s-1) then valklisaasiirto(r,s,r,s-1); end; end; procedure valktornisiir(r,s:ind); var rr,ss: integer; begin valkoinentornisyo(r,s); //ensin tutkitaan pääseekö valkoinen torni syömään rr:=-1; if (r>1) then begin while (lauta^.lautatilanne[r+rr,s]=tyhja) do begin valklisaasiirto(r,s,r+rr,s); r:=r-1; end; end; rr:=1; if (r<8) then begin while (lauta^.lautatilanne[r+rr,s]=tyhja) do begin valklisaasiirto(r,s,r+rr,s); r:=r-1; end; end; ss:=1; if (s<8) then begin while (lauta^.lautatilanne[r,s+ss]=tyhja) do begin valklisaasiirto(r,s,r,s+ss); s:=s+1; end; end; ss:=-1; if (s>1) then begin while (lauta^.lautatilanne[r,s+ss]=tyhja) do begin valklisaasiirto(r,s,r,s+ss); s:=s-1; end; end; end; procedure mustatornisyo(r,s:ind); //tutkitaan mustan tornin mahdolliset syönnit var rr,ss:integer; begin rr:=-1; if (r>1) then begin while (lauta^.lautatilanne[r+rr,s]=tyhja) do begin r:=r-1; end; if nappulaonvalkoinen(r-1,s) then mustlisaasiirto(r,s,r-1,s); end; rr:=1; if (r<8) then begin while (lauta^.lautatilanne[r+rr,s]=tyhja) do begin r:=r+1; end; if nappulaonvalkoinen(r+1,s) then mustlisaasiirto(r,s,r+1,s); end; ss:=1; if (s<8) then begin while (lauta^.lautatilanne[r,s+ss]=tyhja) do begin s:=s+1; end; if nappulaonvalkoinen(r,s+1) then mustlisaasiirto(r,s,r,s+1); end; ss:=-1; if (s>1) then begin while (lauta^.lautatilanne[r,s+ss]=tyhja) do begin s:=s-1; end; if nappulaonvalkoinen(r,s-1) then mustlisaasiirto(r,s,r,s-1); end; end; procedure musttornisiir(r,s:ind); var rr,ss: integer; begin mustatornisyo(r,s); //ensin tutkitaan pääseekö valkoinen torni syömään rr:=-1; if (r>1) then begin while (lauta^.lautatilanne[r+rr,s]=tyhja) do begin mustlisaasiirto(r,s,r+rr,s); r:=r-1; end; end; rr:=1; if (r<8) then begin while (lauta^.lautatilanne[r+rr,s]=tyhja) do begin mustlisaasiirto(r,s,r+rr,s); r:=r-1; end; end; ss:=1; if (s<8) then begin while (lauta^.lautatilanne[r,s+ss]=tyhja) do begin mustlisaasiirto(r,s,r,s+ss); s:=s+1; end; end; ss:=-1; if (s>1) then begin while (lauta^.lautatilanne[r,s+ss]=tyhja) do begin mustlisaasiirto(r,s,r,s+ss); s:=s-1; end; end; end; procedure valklahettisiir(r,s:ind); //tutkitaan lähetin mahdolliset siirrot var rr,ss:integer; begin rr:=-1; ss:=-1; if (r>1) and (s>1) then while (lauta^.lautatilanne[r+rr,s+ss]=tyhja) do begin valklisaasiirto(r,s,r+rr,s+ss); r:=r-1; s:=s-1; end; rr:=-1; ss:=1; if (r>1) and (s<8) then while (lauta^.lautatilanne[r+rr,s+ss]=tyhja) do begin valklisaasiirto(r,s,r+rr,s+ss); r:=r-1; s:=s+1; end; rr:=1; ss:=1; if (r<8) and (s<8) then while (lauta^.lautatilanne[r+rr,s+ss]=tyhja) do begin valklisaasiirto(r,s,r+rr,s+ss); r:=r+1; s:=s+1; end; rr:=1; ss:=-1; if (r<8) and (s>1) then while (lauta^.lautatilanne[r+rr,s+ss]=tyhja) do begin valklisaasiirto(r,s,r+rr,s+ss); r:=r+1; s:=s-1; end; end; procedure mustlahettisiir(r,s:ind); //tutkitaan mustan lähetin mahdolliset siirrot var rr,ss:integer; begin rr:=-1; ss:=-1; if (r>1) and (s>1) then while (lauta^.lautatilanne[r+rr,s+ss]=tyhja) do begin mustlisaasiirto(r,s,r+rr,s+ss); r:=r-1; s:=s-1; end; rr:=-1; ss:=1; if (r>1) and (s<8) then while (lauta^.lautatilanne[r+rr,s+ss]=tyhja) do begin mustlisaasiirto(r,s,r+rr,s+ss); r:=r-1; s:=s+1; end; rr:=1; ss:=1; if (r<8) and (s<8) then while (lauta^.lautatilanne[r+rr,s+ss]=tyhja) do begin mustlisaasiirto(r,s,r+rr,s+ss); r:=r+1; s:=s+1; end; rr:=1; ss:=-1; if (r<8) and (s>1) then while (lauta^.lautatilanne[r+rr,s+ss]=tyhja) do begin mustlisaasiirto(r,s,r+rr,s+ss); r:=r+1; s:=s-1; end; end; procedure valkkuningatarsiir(r,s:ind); // tutkitaan kuningattaren kaikki mahdolliset siirrot begin valklahettisiir(r,s); valktornisiir(r,s); end; procedure mustkuningatarsiir(r,s:ind); // tutkitaan kuningattaren kaikki mahdolliset siirrot begin mustlahettisiir(r,s); musttornisiir(r,s); end; procedure valkkuningasiir(r,s:ind); //tutkitaan kuninkaan mahdolliset siirrot var i,j: -1..1; begin for i:=-1 to 1 do for j:=-1 to 1 do begin if (not (i=0) and (j=0)) and (r+i<=8) and (r+i>=1) and (r+j>=1) and (r+j<=8) then if (lauta^.lautatilanne[r+i,s+j]=tyhja) then valklisaasiirto(r,s,r+i,s+j); end; end; procedure mustkuningasiir(r,s:ind); //tutkitaan kuninkaan mahdolliset siirrot var i,j: -1..1; begin for i:=-1 to 1 do for j:=-1 to 1 do begin if (not (i=0) and (j=0)) and (r+i<=8) and (r+i>=1) and (r+j>=1) and (r+j<=8) then if (lauta^.lautatilanne[r+i,s+j]=tyhja) then mustlisaasiirto(r,s,r+i,s+j); end; end; procedure tulostamahdollisetsiirrot; var apuri: siirrot; begin apuri:=valkmahdollisetsiirrot; while apuri^.seuraava<>nil do begin begin writeln(apuri^.mistarivi, apuri^.mistasara, apuri^.mihinrivi,apuri^.mihinsara,apuri^.nap); apuri:=apuri^.seuraava; end; end; end; procedure lisaauupelilautatietue; begin seuraavalauta:=new(laudat); seuraavalauta^.aiempi:=lauta; seuraavalauta^.seuraava:=NIL; seuraavalauta^.lautatilanne:=lauta^.lautatilanne; seuraavalauta^.lautatilanteensiirrot:=valkmahdollisetsiirrot; if lauta^.seuraava=nil then lauta^.seuraava:=seuraavalauta else begin apulauta:=lauta; while apulauta^.seuraava<>NIL do apulauta:=apulauta^.seuraava; apulauta^.seuraava:=seuraavalauta; end; end; procedure valkoinensiirtaa; var r,s: ind; kopio: pelilauta; begin if mustmahdollisetsiirrot=NIL then begin for r:=1 to 8 do for s:=1 to 8 do begin if lauta^.lautatilanne[r,s]=a1 then valktornisiir(r,s); if lauta^.lautatilanne[r,s]=b1 then valkratsusiir(r,s); if lauta^.lautatilanne[r,s]=c1 then valklahettisiir(r,s); if lauta^.lautatilanne[r,s]=d1 then valkkuningatarsiir(r,s); if lauta^.lautatilanne[r,s]=e1 then valkkuningasiir(r,s); if lauta^.lautatilanne[r,s]=f1 then valklahettisiir(r,s); if lauta^.lautatilanne[r,s]=g1 then valkratsusiir(r,s); if lauta^.lautatilanne[r,s]=h1 then valktornisiir(r,s); if lauta^.lautatilanne[r,s] in [a2, b2, c2, d2, e2, f2, g2, h2] then valksotilasiir(r,s); end; end else begin apusiirrot:=mustmahdollisetsiirrot; while apusiirrot^.seuraava<>NIL do begin writeln('valkoinensiirtaa'); for r:=1 to 8 do for s:=1 to 8 do begin if lauta^.lautatilanne[r,s]=a1 then valktornisiir(r,s); if lauta^.lautatilanne[r,s]=b1 then valkratsusiir(r,s); if lauta^.lautatilanne[r,s]=c1 then valklahettisiir(r,s); if lauta^.lautatilanne[r,s]=d1 then valkkuningatarsiir(r,s); if lauta^.lautatilanne[r,s]=e1 then valkkuningasiir(r,s); if lauta^.lautatilanne[r,s]=f1 then valklahettisiir(r,s); if lauta^.lautatilanne[r,s]=g1 then valkratsusiir(r,s); if lauta^.lautatilanne[r,s]=h1 then valktornisiir(r,s); if lauta^.lautatilanne[r,s] in [a2, b2, c2, d2, e2, f2, g2, h2] then valksotilasiir(r,s); end; end; apusiirrot:=apusiirrot^.seuraava; end; tulostamahdollisetsiirrot; lisaauupelilautatietue; end; procedure mustasiirtaa; var r,s: ind; laskuri: Integer; begin laskuri:=0; apusiirrot:=valkmahdollisetsiirrot; while apusiirrot^.seuraava<>NIL do begin writeln('mustasiirtaa', ' ',laskuri); laskuri:=laskuri+1; for r:=1 to 8 do for s:=1 to 8 do begin if lauta^.lautatilanne[r,s]=a8 then musttornisiir(r,s); if lauta^.lautatilanne[r,s]=b8 then mustratsusiir(r,s); if lauta^.lautatilanne[r,s]=c8 then mustlahettisiir(r,s); if lauta^.lautatilanne[r,s]=d8 then mustkuningatarsiir(r,s); if lauta^.lautatilanne[r,s]=e8 then mustkuningasiir(r,s); if lauta^.lautatilanne[r,s]=f8 then mustlahettisiir(r,s); if lauta^.lautatilanne[r,s]=g8 then mustratsusiir(r,s); if lauta^.lautatilanne[r,s]=h8 then musttornisiir(r,s); if lauta^.lautatilanne[r,s] in [a7, b7, c7, d7, e7, f7, g7, h7] then mustsotilasiir(r,s); end; apusiirrot:=apusiirrot^.seuraava; end; end; procedure tuhoasolmut; begin end; begin //pääohjelma lauta:=new(laudat); lauta^.aiempi:=NIL; lauta^.seuraava:=NIL; for i:=3 to 6 do for j:=1 to 8 do lauta^.lautatilanne[i,j]:=tyhja; lauta^.lautatilanne[8,1]:=a1; lauta^.lautatilanne[8,2]:=b1; lauta^.lautatilanne[8,3]:=c1; lauta^.lautatilanne[8,4]:=d1; lauta^.lautatilanne[8,5]:=e1; lauta^.lautatilanne[8,6]:=f1; lauta^.lautatilanne[8,7]:=g1; lauta^.lautatilanne[8,8]:=h1; lauta^.lautatilanne[7,1]:=a2; lauta^.lautatilanne[7,2]:=b2; lauta^.lautatilanne[7,3]:=c2; lauta^.lautatilanne[7,4]:=d2; lauta^.lautatilanne[7,5]:=e2; lauta^.lautatilanne[7,6]:=f2; lauta^.lautatilanne[7,7]:=g2; lauta^.lautatilanne[7,8]:=h2; lauta^.lautatilanne[1,1]:=a8; lauta^.lautatilanne[1,2]:=b8; lauta^.lautatilanne[1,3]:=c8; lauta^.lautatilanne[1,4]:=d8; lauta^.lautatilanne[1,5]:=e8; lauta^.lautatilanne[1,6]:=f8; lauta^.lautatilanne[1,7]:=g8; lauta^.lautatilanne[1,8]:=h8; lauta^.lautatilanne[2,1]:=a7; lauta^.lautatilanne[2,2]:=b7; lauta^.lautatilanne[2,3]:=c7; lauta^.lautatilanne[2,4]:=d7; lauta^.lautatilanne[2,5]:=e7; lauta^.lautatilanne[2,6]:=f7; lauta^.lautatilanne[2,7]:=g7; lauta^.lautatilanne[2,8]:=h7; valkmahdollisetsiirrot:=NIL; mustmahdollisetsiirrot:=NIL; siirtojenlukumaara:=0; siirtotaso:=0; while (siirtotaso