Autor Beitrag
gerd8888 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 205
Erhaltene Danke: 3

Win7
Delphi 10.1 Starter (kostenlos) Lazarus
BeitragVerfasst: Mi 14.09.16 19:00 
Jetzt habe ich die Masken in einem array gespeichert und greife direkt zu. Ist etwas schneller.
Ich habe schon mal ein Schachprogramm geschrieben mit einer brett[1..64] of shortint.
Ich habe die beiden Schachprogramme verglichen (nur mit Königen) und da ist immer noch mein altes Programm schneller.
Wahrscheinlich benoetigt die Schachabfrage viel Zeit. Hier mal die procedure

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
function Bittest (TestZahl : int64;Bitnr: byte):boolean;
//var
//  Bitmaske : int64;
begin
  {Bitmaske := 1 shl BitNr;
  result := TestZahl AND BitMaske <> 0;}

  //result := int64(1) AND BitMaske <> 0;
  //result := testzahl AND (1 shl BitNr) <> 0;
  Result := (testzahl and (Int64(1shl bitnr)) <> 0;
  //result := int64(1) shl bitnr;
end;


function sK_im_schach:boolean;
  var a,b,c,d:byte;
      h,schach:boolean;
  begin
    schach:=false;
    for a:=0 to 63 do begin
      if schach=false then
      if bittest(sk,a) then begin
        for b:=1 to 4 do begin
          if schach=false then
          if t_anz[b,a]<>0 then begin
            for c:=1 to t_anz[b,a] do begin
              (* eigener Stein im Weg *)
              h:=true;
              if bittest(st,t_wege[b,a].zahlen[c]) then begin
                h:=false;
              end;
              if h then begin
                if bittest(wk,t_wege[b,a].zahlen[c]) then begin
                  h:=false;
                end;
                if h then begin
                  if bittest(wt,t_wege[b,a].zahlen[c]) then begin
                    schach:=true;
                    h:=false;
                  end;
                end;
              end;
              if h=false then break;
            end;
          end;
        end;
      end;
    end;
    if schach then result:=true else result:=false;
  end;


Ich gehe vom König weg und schaue ob da eine Figur steht. Hier sogar nur die T-Züge. Das braucht ziemlich viel Zeit...
JoelH
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 798
Erhaltene Danke: 17

Win10
Delphi XE7/Tokyo Prof.
BeitragVerfasst: Do 15.09.16 09:14 
Hilfreich sind Variablen die auch etwas aussagen. In deiner Varianten ist der Code mühsam zu entziffern.

Sehe ich das richtig, dass du jedes mal über das gesamte Brett gehst um den König zu suchen? Das ist ja mal der absoluten Speedkiller. Wenn es ungünstig läuft benötigst du bei 10.000.000 Stellungen 640.000.000 Iterationen, von denen 630.000.000 überflüssig sind wenn du einfach eine Figurenliste mit führst, die dir zur jeweiligen Stellung die Position des Königs zurück gibt.

_________________
mfg. Joel


Zuletzt bearbeitet von JoelH am Do 15.09.16 09:16, insgesamt 1-mal bearbeitet
gerd8888 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 205
Erhaltene Danke: 3

Win7
Delphi 10.1 Starter (kostenlos) Lazarus
BeitragVerfasst: Do 15.09.16 11:04 
Das stimmt. Das habe ich übrigens noch selbst herausgefunden, dass es besser ist den weissen König und den schwarzen König einfach in ein byte abzuspeichern. Dann habe ich festgestellt, dass ich das auf das bitboard bei königen ganz verzichten kann. Nur bei Königen speichere ich das anders ab, wegen der Schachabfrage.
(Normalerweise habe ich aussagekraeftige Variablen gewaehlt. Nur bei der Schachabfrage waren es alles Schleifen und da habe ich keinen Sinn gesehen)
gerd8888 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 205
Erhaltene Danke: 3

Win7
Delphi 10.1 Starter (kostenlos) Lazarus
BeitragVerfasst: Do 15.09.16 18:11 
Habe mir heute mal das sog. magic-bitboard angesehen.
Die Grundidee ist einfach. Z.B. beim Turm in der Mitte, wird eine Maske (die schon erzeugt wurde und nur noch aufgerufen werden muss) mit der
bitboard_gesamte_steine xor maske (siehe unten)

00010000
00010000
00010000
00010000
11101111
00010000
00010000
00010000

Somit spart man sich, wenn man vom König alle Richtungen durchsucht, die Leerfeldabfrage.
Hast Du das in Deinem Atomschach auch eingebaut?
JoelH
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 798
Erhaltene Danke: 17

Win10
Delphi XE7/Tokyo Prof.
BeitragVerfasst: Fr 16.09.16 07:20 
Nein, habe ich nicht. Ich arbeite ganz oldschool mit Figurentabelle und 10*12 Board. Wie ich schon weiter oben schrieb, mein Hauptaugenmerk legte ich ganz traditionell (ganz vom eigenen Ego getrieben) auf die Stellungsbewertung und nicht auf den Zuggenerator, Oldschool eben.

Heute geht es ja fast nur noch um schnelle Zuggeneration und nur noch rudimentäre Stellungsbewertung mit Hauptaugenmerk auf die perfekte Zugsortierung um sehr gute Alpha/Beta Cuts zu bekommen. Das war aber nicht meine Motivation hinter dem Projekt. Mein Ziel war es zunächst einfach nur ein Programm zu schreiben welches mich schlagen kann. Das ging allerdings recht einfach, obwohl ich jetzt gar kein so schlechter Atomicschachler bin. Danach hab ich es eine Weile auf einem Schachserver spielen lassen, mit überraschend guten Ergebnissen. Ich schätze das Programm auf etwa 1800 Schachserver-ELO aber es hat einen Wert von knapp 2500 erreicht. Im weiteren Verlauf habe ich dann immer mehr Ideen zur Stellungsbewertung eingefügt um zu schauen ob meine Ideen auch so funktionieren wie ich mir es vorstelle oder ob ich total daneben liege.

Einige Anekdoten dazu findest du in meinem Blog zum Projekt. Da siehst du aber auch, dass ich seit mehr als einem Jahr nichts mehr daran gemacht haben.

joelh.de/atomystica/?lang=de

_________________
mfg. Joel
gerd8888 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 205
Erhaltene Danke: 3

Win7
Delphi 10.1 Starter (kostenlos) Lazarus
BeitragVerfasst: Fr 16.09.16 16:35 
JoelH, habe mir Deine Seite angesehen. Mit welchen Spielregeln spielst Du Dein Atomschach. Darf der König direkt geschlagen werden. Oder wird er nur mattgesetzt, wenn er durch eine Explosion vom Brett verschwindet. Da ich an Kunstschach interessiert bin, würde mich interessieren, ob es auch einfache Mattprobleme, wie Matt in 3 Zügen gibt.

Jetzt habe ich mich nochmal mit den magic Bitboards beschaeftigt.

00001000
00001000
00001000
11110111
00001000
00001000
00001000
00001000
(1 Maske, auf e5 steht ein wT )


00000000
00000000
00000000
00101000
00000000
00000000
00000000
00000000
(2 Ausgangsstellung)

Maske xor Ausgangstellung

00001000
00001000
00001000
11010111
00001000
00001000
00001000
00000000
(3 Attakierten Felder des Turms)

Die Felder a5 und b5 sind auch attakiert. Aber auf dem Feld c5 ist ein

Block.

Es soll nun als Ergebnis das hier herauskommen:

00001000
00001000
00001000
00010111
00001000
00001000
00001000
00000000
(4 wirklich attakierten Felder des Turms)

Jetzt ist a5 und b5 nicht blockiert.
Nun koennte man ein Lookup von Dia 3 und vielen weiteren Stellungen
erstellen. Das Problem ist nun, dass es hier sehr viele Moeglichkeiten
gibt. Verringert soll das durch ein "magic bitboard" Maske werden.
Kann mir das einer erklären, wie das funktionieren soll?
gerd8888 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 205
Erhaltene Danke: 3

Win7
Delphi 10.1 Starter (kostenlos) Lazarus
BeitragVerfasst: Fr 16.09.16 21:06 
Das Prinzip habe ich verstanden. Die magic Maske soll praktisch die untenere Maske mit Buchstaben in einer Reihenfolge bringen

00000000
0000B000
0000A000
0EDC1FG0
0000H000
0000I000
0000J000
00000000


Dann hat man wieder eine Zahl
BADECIJH

Dann wandelt es die Zahlen in einem Lookup um

Danach macht man alles rueckgaenig und hat das fertige Ergebnis.

Nur ueber eine Kleinigkeit raetsel ich noch.
Warum sind die ganz aeusseren Felder der Maske nicht besetzt.
Ich kann doch nicht automatisch einen Rückschluss machen, dass wenn e7 attackiert ist auch e8 attackiert ist, denn wenn auf e7 eine schwarze Figur steht und geschlagen wird, dann ist eben e8 nicht attackiert.

Wer hilft mir jetzt die magischen Zahlen herauszufinden. Wie funktioniert diese Art der Bitmanipulation eigentlich?
JoelH
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 798
Erhaltene Danke: 17

Win10
Delphi XE7/Tokyo Prof.
BeitragVerfasst: So 18.09.16 11:32 
user profile icongerd8888 hat folgendes geschrieben Zum zitierten Posting springen:
JoelH, habe mir Deine Seite angesehen. Mit welchen Spielregeln spielst Du Dein Atomschach. Darf der König direkt geschlagen werden. Oder wird er nur mattgesetzt, wenn er durch eine Explosion vom Brett verschwindet. Da ich an Kunstschach interessiert bin, würde mich interessieren, ob es auch einfache Mattprobleme, wie Matt in 3 Zügen gibt.

Es wird nach den Regeln gespielt die hier hinterlegt sind.

www.unix-ag.uni-kl.de/~chess/atomic/

Der König wird nicht geschlagen sondern geht ganz normal Matt oder er wird indirekt gesprengt, wenn eine eigenen Figur direkt daneben geschlagen wird. Das normale Matt ist dabei von einer einzelnen Dame herbeiführbar in der Ecke. wDb2 sKa1 ist Matt da ein König im Atomic nicht schlagen darf.

Alle anderen Regeln des normalen Schachs gelten weiterhin. Also es ist auch Patt möglich.

Hier gibt es eine tolle Seite über Atomic

www.nicklong.net/chess/atomic/ da gibt es auch eine Mattaufgaben zu finden www.nicklong.net/chess/atomic/puzzles.htm

_________________
mfg. Joel
gerd8888 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 205
Erhaltene Danke: 3

Win7
Delphi 10.1 Starter (kostenlos) Lazarus
BeitragVerfasst: Mo 19.09.16 22:51 
Ich habe mir die Atomschachrätsel angesehen. Konnte nur das letzte Problem lösen. Schade, dass es keine Lösungsbesprechung gibt.

Zurueck zu den Magic Bitboards.
Ich will jetzt die magischen Masken herausfinden:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
procedure TForm1.magische_zahlen;
var testz,t,magic,erg,i:int64;

begin
  testz:=0;
  bitset(testz,50);
  bitset(testz,43);
  bitset(testz,36);
  bitset(testz,29);
  bitset(testz,22);
  bitboard(testz);
  label1.Caption:=inttostr(low(testz))+' '+inttostr(high(testz));
  update;
  t:=testz;
  for i:= low(testz) to high(testz) do begin}
    if t*i >= low(testz) then if t*i <= high(testz) then begin
    erg:=t*i;
    if bittest(erg,59then if bittest(erg,60then if bittest(erg,61then if bittest(erg,62then
    if bittest(erg,63then begin
      bitclear(t,50);
      if not bittest(erg,59then if bittest(erg,60then if bittest(erg,61then if bittest(erg,62then
      if bittest(erg,63then begin
        bitset(t,50);
        bitclear(t,43);
        if bittest(erg,59then if not bittest(erg,60then if bittest(erg,61then if bittest(erg,62then
        if bittest(erg,63then begin
          bitset(t,43);
          bitclear(t,36);
          if bittest(erg,59then if bittest(erg,60then if not bittest(erg,61then if bittest(erg,62then
          if bittest(erg,63then begin
            bitset(t,36);
            bitclear(t,29);
            if bittest(erg,59then if bittest(erg,60then if bittest(erg,61then if not bittest(erg,62then
            if bittest(erg,63then begin
              bitset(t,29);
              bitclear(t,22);
              if bittest(erg,59then if bittest(erg,60then if bittest(erg,61then if bittest(erg,62then
              if not bittest(erg,63then begin
                //Zahl gefunden
                magic:=i;
                beep;
                break;
              end;
            end;
          end;
        end;
      end;

    end;
    end;
  end;
  beep;

  {magic:=0;
  bitset(magic,9);
  bitset(magic,17);
  bitset(magic,25);
  bitset(magic,33);
  bitset(magic,41);}


  {erg:=testz*magic;
  bitboard(erg);}

  label1.caption:=inttostr(magic);

end;


Nach 2 Stunden habe ich abgebrochen. Ich habe herausgefunden, dass es an der Multiplikation liegt:

ausblenden Delphi-Quelltext
1:
2:
3:
for i:= low(testz) to high(testz) do begin}
    if t*i >= low(testz) then if t*i <= high(testz) then begin
    erg:=t*i;


Was nun?

Gerd