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

Win7
Delphi 10.1 Starter (kostenlos) Lazarus
BeitragVerfasst: So 04.09.16 15:24 
Hallo,

ich will die dazwischenliegenden Felder eines Schachbretts in einer const Variablen unterbringen.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
array[0..63of byte=
(0,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);

Ich will von der Verbindungsline 0 und 7 dazwischen liegen die Zahlen 1, 2, 3, 4, 5, 6 usw.
oder 8 und 11 dazwischen liegen die Zahlen 9,10
oder 39 und 63 dazwischen liegen 47, 55
in einer const variable speichern

Man koennte schon ein
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
type
Tt=record 
  z:array[1..6]; 
end;

const zwischenwerte=array of array of Tt


da ich aber die Verbindungslinie z.B. 0 und 7 vertauschen kann, waere viel Speicher vergoldet.
Gibt es eine bessere Loesung?

Gerd

Moderiert von user profile iconTh69: Delphi-Tags hinzugefügt
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1577
Erhaltene Danke: 223


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: So 04.09.16 16:06 
user profile icongerd8888 hat folgendes geschrieben Zum zitierten Posting springen:
const Variablen


Ist das nicht ein Oxymoron?
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: So 04.09.16 16:41 
ausblenden Delphi-Quelltext
1:
2:
3:
4:
type
Tt=record 
  z:array[1..6of byte; 
end;


Oxymoron? Warum?
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1577
Erhaltene Danke: 223


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: So 04.09.16 16:43 
Weil eine Konstante nicht variabel sein kann bzw. eine Variable nicht konstant sein muß. In Pascal gibt es dafür zwei unterschiedliche Schlüsselwörter.


Zuletzt bearbeitet von Delphi-Laie am So 04.09.16 17:08, insgesamt 1-mal bearbeitet
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Chefentwickler
Beiträge: 20337
Erhaltene Danke: 2125

Win 10
C# (VS 2017)
BeitragVerfasst: So 04.09.16 16:47 
gerd8888 hat durch seinen Quelltext ja klar gemacht, was er meint. Daher bitte zurück zum Thema ;)

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
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: So 04.09.16 16:50 
ausblenden Delphi-Quelltext
1:
const zwischenwerte=array[0..63of array[0..63of Tt					


so muss es ganz korrekt sein.
Aber vielleicht geht es wirgendwie besser?
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1577
Erhaltene Danke: 223


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: So 04.09.16 16:55 
Ich muß es leider so deutlich schreiben, aber die Beschreibung ist wirr.

user profile icongerd8888 hat folgendes geschrieben Zum zitierten Posting springen:
Ich will von der Verbindungsline 0 und 7 dazwischen liegen die Zahlen 1, 2, 3, 4, 5, 6 usw.
oder 8 und 11 dazwischen liegen die Zahlen 9,10
oder 39 und 63 dazwischen liegen 47, 55
in einer const variable speichern


"Ich will von der Verbindungslinie 0 und 7 [, dazwischen liegen.....] in einer const variable speichern."

Tut mir leid, aber das ist kein Satz!

Auch geht m.E. die Systematik nicht hervor - welche horizontalen und welche vertikalen Linien (Zwischenwerte) werden gespeichert?

user profile icongerd8888 hat folgendes geschrieben Zum zitierten Posting springen:
da ich aber die Verbindungslinie z.B. 0 und 7 vertauschen kann, waere viel Speicher vergoldet.


Eine Verbindungslinie läßt sich nicht vertauschen, sondern immer nur (mindestens) zwei Objekte lassen sich vertauschen. Sind 0 und 7 gemeint?
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1325
Erhaltene Danke: 117

Mac OSX
TypeScript (Webstorm), Kotlin, Clojure (IDEA)
BeitragVerfasst: So 04.09.16 17:01 
Moin,

deine Fragestellung wird mir zwar nicht über die Maßen klar, aber ich glaube raten zu können, was du möchtest.

Zunächst: Unter normalen Bedingungen dürfte der Speicherplatz deines Arrays 64 * 64 * 6Byte = 24KB nicht zu einer übertriebenen Belastung deines Rechners führen. Demzufolge muss an dieser Stelle gesagt werden, dass alle folgenden Optimierung effektiv keinen Nutzen haben und nur die Lesbarkeit des Codes verschlechtern werden (siehe hierzu When is optimization not premature and therefore not evil?).

Natürlich kannst du dein Start- und Zielfeld immer aufsteigend sortieren. Dann kannst du eine Dreiecksmatrix aufbauen, die nur die Zwischenfelder von Feld X zu allen davor indizierten Feldern aufbaut. Du guckst dann in deiner Dreiecksmatrix die Zwischenfelder für das höher indizierte Feld nach und musst (falls die Reihenfolge der Felder relevant ist), den Weg ggf. reversieren. Dabei hast du dann zahlreiche teure Aktionen gemacht, mächtige 12KB RAM gespart, aber keinerlei Performance gewonnen.

In deinen Beispielen hast du nur Pfade genannt, die in Spalten oder Zeilenrichtung verlaufen. Sollen grundsätzlich auch diagonale oder sonstwie schräge Wege möglich sein?

Bis dann
Finn

Übrigens:
user profile iconDelphi-Laie hat folgendes geschrieben Zum zitierten Posting springen:
Ist das nicht ein Oxymoron?

Immerhin ist es nicht off-topic.
JoelH
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 798
Erhaltene Danke: 17

Win10
Delphi XE7/Tokyo Prof.
BeitragVerfasst: Mo 05.09.16 08:38 
user profile icongerd8888 hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
const zwischenwerte=array[0..63of array[0..63of Tt					


so muss es ganz korrekt sein.
Aber vielleicht geht es wirgendwie besser?


Ich würde sagen, die Antwort ist JA. So ist es korrekt, wenn du ganz ohne Berechnungen auskommen möchtest. Ich vermute du möchtest z.B. die Zugmöglichkeiten eines Turms aus diesem Array ermitteln.

Ich bin mir allerdings nicht sicher ob dein Code effektiv schneller ist als wenn du die Möglichkeiten jeweils in der Ausleseschleife via Addition jedes Mal neu errechnest.

_________________
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 05.09.16 09:38 
Der Turm oder (die Dame) in der oberen linken Ecke soll zur rechten oberen Ecke 0 und 7 und zur unteren linken Ecke 0 und 56.
Da der Turm nicht über Steine fliegen kann (wie der Springer) muss ich die Zwischenfelder, die jeweils auf dieser Geraden liegen prüfen.
Wenn da ein weisser oder schwarzer Stein dazwischen ist, kann der T nicht ziehen.

Wenn ich nun eine Berechnung machen würde, muesste ich so vorgehen:
1) ich muss erst von den 2 Punkten das kleinere und das groessere ermitteln
2) Ich ziehe von der groesseren Zahl die kleinere Zahl ab
3) Das Ergebnis z.B. ich habe die Punkte 0 und 7 dann 7-0=7 dann muss ich 7 mod 8 machen. Ist es ungleich 0 addiere ich jeweils von 0 immer 1 bis ich
zur 7 komme
4) z.B. bei 0 und 56 56-0=58 56 mod 8 =0 dann muss ich jeweils 8 addieren.

Wieviel das rechnen ausmacht weiss ich nicht. Aber ich muss dass dann auch für den Läufer und für die Dame machen.
Die Abfrage findet wiederholt staendig im Zugbaum statt.
Ausserdem bei der Abfrage ob der König im Schach steht, verfolge ich den T-Weg des K und brauche das wieder.

Ich könnte mir also schon vorstellen, dass sich das lohnen könnte.
JoelH
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 798
Erhaltene Danke: 17

Win10
Delphi XE7/Tokyo Prof.
BeitragVerfasst: Mo 05.09.16 09:52 
Ich empfehle dir, aus programmtechnischen Gründen von einem 8x8 Board Abstand zu nehmen und ein 10x12 Feld als Board zu nehmen. Dadurch entfallen bei der Zugerzeugung nämlich die aufwendigen Ränderprüfungen.

Zum Thema gibt es gute Wiki, ist zwar englichsprachig aber ich habe dort sehr viele Informationen erhalten bei meinem Schachprogrammprojekt.

chessprogramming.wikispaces.com/ und dort zunächst mal chessprogramming.wik...Board+Representation

Warum das Rad neu erfinden?

_________________
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 05.09.16 13:48 
JoelH, die Brettdarstellung ist mir nicht unbekannt. Man kann auch bei dem Springer ausserhalb dem Rand huepfen.
Andererseits, schreibe ich alles in einer Tabelle, wo der Springer hinzieht (er hüpft gar nicht erst über den Rand hinaus) und alle anderen Figuren auch, somit sehe ich darin keinen so grossen Sinn.
Und das einzige Problem mit T und L Zwischenfelder habe ich jetzt so geloest:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
Ttl_zwischen = record
  zwischen:array of byte;
end;

y_zahl = record
  y:array[0..63of Ttl_zwischen;
end;
zw_felder:array[0..63of y_zahl;


Ich lege das doch nicht in eine const ab, sondern erzeuge sie vor dem eigentlichen Lösevorgang.
Hat auch den Vorteil, dass ich mit dynamischen arrays nur die tatsaechlichen werte habe und evt. Blindgänger z.B. j=0 und x=0 gar kein Speicherplatz belegt.

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:
for j:=0 to 63 do begin
    for x:=0 to 63 do begin
       if x<>j then begin
         if x>j then begin
           g:=x;  //groessere Zahl
           n:=j;  //kleinere zahl
         end else begin
           n:=x;  //kleinere zahl
           g:=j;  //groessere zahl
         end;
         if (g-n)<>1 then begin
           if (g-n)<>8 then begin
             if (g-n) mod 8 <> 0 then begin
               m:=1;
               repeat
                 setlength(zw_felder[x].y[j].zwischen,m);
                 zw_felder[x].y[j].zwischen[m-1]:=(n+m);
                 inc(m);
                 if (n+m)=g then m:=101//raus
               until m>100;
             end else begin
               m:=1;
               repeat
                 setlength(zw_felder[x].y[j].zwischen,m);
                 zw_felder[x].y[j].zwischen[m-1]:=(n+(m*8));
                 inc(m);
                 if (n+(m*8))=g then m:=101;
               until m>100;
             end;
           end;
         end;
       end;
    end;
  end;

  if high(zw_felder[0].y[8].zwischen)<>-1 then
  for n:=0 to high(zw_felder[0].y[8].zwischen) do begin
    st1:=st1+' ';
    st1:=st1+inttostr(zw_felder[0].y[8].zwischen[n]);
  end;
  label1.Caption:=st1;


Warum das Rad neu erfinden? Meine Nachbarin sagt mir auch, dass es schon so viele Schachprogramme gibt, warum ich eigentlich programmiere.
Tatsächlich habe ich mir auch schon überlegt es bleiben zu lassen, weil es eh schon alles gibt.
Andererseits macht es immer wieder Spass. Den Rekord werde ich bestimmt nicht brechen... oder doch?

Gerd
JoelH
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 798
Erhaltene Danke: 17

Win10
Delphi XE7/Tokyo Prof.
BeitragVerfasst: Mo 05.09.16 14:15 
In der Tat, das dachte ich mir damals auch ;-)
Allerdings, was Boardrepräsentation/Zuggeneration angeht, da hab ich das Rad nicht wirklich neu erfunden. Ich habe lieber "unter der Haube" rum geschraubt und meine Stellungsbewertungen "optimiert".

Aber davon mal ab. Bei langschrittigen Figuren musst du sowieso testen ob es in Zuglinie eine andere Figur gibt. Und da Frage ich mich ob auslesen aus einem Array wirklich der einfachen Addition zur Laufzeit signifikant/überhaupt überlegen ist. Bei Ersterm muss das Programm eine dynamisch abgelegte Information aus dem Speicher raus suchen und laden. Bei Zweiterem werden lediglich zwei ShortInts addiert. Ich würde fast daruaf tippen, das zweiteres schneller geht.

_________________
mfg. Joel
JoelH
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 798
Erhaltene Danke: 17

Win10
Delphi XE7/Tokyo Prof.
BeitragVerfasst: Mo 05.09.16 14:59 
Habe mal schnell was gebastelt, welches das Problem jeweils abbildet.

Bei mir ist die Addition (~300 ms) dem Auslesen aus dem Array (~400 ms) überlegen.

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:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
procedure TForm1.cmd_1Click(Sender: TObject);
var
  i, n, x, t: ShortInt;
  p: Integer;
  freq: Int64;
  startTime: Int64;
  endTime: Int64;
begin
  QueryPerformanceFrequency(freq);
  QueryPerformanceCounter(startTime);

  n := 1;   // Zugrichtung ist Turmzug nach rechts

  for p := 1 to 100000000 do
  begin

    x := 0;   // Startfeld ab der gezogen wird.


    while (x < 8do
    begin
     
      t := x;              // Damit die CPU wenigstens minimal etwas zu machen hat
//      mem_1.Lines.Add(t.tostring) ;     
      inc(x, n);           // auf der Feld wird der Zugfaktor addiert
    end;
   
  end;

  QueryPerformanceCounter(endTime);

  mem_1.Lines.Add('Die Routine benötigte etwa ' + IntToStr((endTime - startTime)
    * 1000 div freq) + 'ms');

end;




procedure TForm1.cmd_2Click(Sender: TObject);
var
  i, n, x, t : ShortInt;
  p: Integer;
  freq: Int64;
  startTime: Int64;
  endTime: Int64;
  a : Array[0..630..63of Array of Shortint;
begin

  // Initialisierung des Zugfeldarray ausserhalb der Schleife,
  // da es ja bei der initialisierung des Programms einmalig erzeugt wird.
  t := 8;
  SetLength(a[0,7],t);
  for i := 0 to 7 do
    a[0,7][i] := i;      // Das Zielfeld wird in das Array geschrieben


  QueryPerformanceFrequency(freq);
  QueryPerformanceCounter(startTime);

   x := 0;
   n := 7;


  for p := 1 to 100000000 do
  begin
    for i := 0 to Length(a[x,n])-1 do
    begin
      t := a[x,n][i];   // damit was passiert, wie bei obigem Beispiel auch.
                        //  bei beiden Routinen sollte jeweils das identische zurück nach t geschrieben werden
//                        mem_1.Lines.Add(t.tostring)
    end;
  end;

  QueryPerformanceCounter(endTime);

  mem_1.Lines.Add('Die Routine benötigte etwa ' + IntToStr((endTime - startTime)
    * 1000 div freq) + 'ms');

end;

_________________
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 05.09.16 16:17 
JoelH, ich habe den Test gerade durchgefuehrt.
Auf meinem Computer ist das Ergebnis auch um ca. 100 ms unterschiedlich
Variante A: ca. 500 ms
Variante B: ca. 630 ms
(Ich habe zudem noch einen langsameren Rechner)

Ich weiss auch, was der Grund für die etwas schlechteren Werte sind:
ausblenden Delphi-Quelltext
1:
setlength()					


setlength ist der Übeltäter. Wenn man naemlich kein dynamisches array hernimmt, dann kommt man zu folgendem Ergebnis.
Hier der Code von Button2
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:
procedure TForm1.Button2Click(Sender: TObject);
var
  i, n, x, t : ShortInt;
  p: Integer;
  freq: Int64;
  startTime: Int64;
  endTime: Int64;
  a : Array[0..630..63of Array of Shortint;
  b: array[0..630..63,0..7of shortint;
begin

  // Initialisierung des Zugfeldarray ausserhalb der Schleife,
  // da es ja bei der initialisierung des Programms einmalig erzeugt wird.
  t := 8;
  //SetLength(a[0,7],t);
  for i := 0 to 7 do
    //a[0,7][i] := i;      // Das Zielfeld wird in das Array geschrieben
    b[0,7][i]:=i;

  QueryPerformanceFrequency(freq);
  QueryPerformanceCounter(startTime);

   x := 0;
   n := 7;


  for p := 1 to 100000000 do
  begin
    for i := 0 to Length(a[x,n])-1 do
    begin
      t := a[x,n][i];   // damit was passiert, wie bei obigem Beispiel auch.
                        //  bei beiden Routinen sollte jeweils das identische zurück nach t geschrieben werden
//                        mem_1.Lines.Add(t.tostring)
    end;
  end;

  QueryPerformanceCounter(endTime);

  memo1.Lines.Add('Die Routine benötigte etwa ' + IntToStr((endTime - startTime)
    * 1000 div freq) + 'ms');

end;


Variante A: 500 ms
Variante B: (obiger code) 166 ms

Sogar deutlich langsamer. Das dürfte auch der Fall sein, wenn ich es doch noch mal in const umschreibe. Das Ergebnis duerfte aehnlich sein.

Aber trotzdem will ich nochmal erwaehnen, dass wir hier von 100 Mio. Zuegen sprechen und da ist eine Abweichung von ein paar ms glaube ich wirklich nicht so schlimm.
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 05.09.16 16:27 
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:
procedure TForm1.Button2Click(Sender: TObject);
var
  i, n, x, t : ShortInt;
  p: Integer;
  freq: Int64;
  startTime: Int64;
  endTime: Int64;
  a : Array[0..630..63of Array of Shortint;
  b: array[0..630..63,0..7of shortint;
begin

  // Initialisierung des Zugfeldarray ausserhalb der Schleife,
  // da es ja bei der initialisierung des Programms einmalig erzeugt wird.
  t := 8;
  //SetLength(a[0,7],t);
  for i := 0 to 7 do
    //a[0,7][i] := i;      // Das Zielfeld wird in das Array geschrieben
    b[0,7][i]:=i;

  QueryPerformanceFrequency(freq);
  QueryPerformanceCounter(startTime);

   x := 0;
   n := 7;


  for p := 1 to 100000000 do
  begin
    for i := 0 to Length(b[x,n])-1 do
    begin
      t := b[x,n][i];   // damit was passiert, wie bei obigem Beispiel auch.
                        //  bei beiden Routinen sollte jeweils das identische zurück nach t geschrieben werden
//                        mem_1.Lines.Add(t.tostring)
    end;
  end;

  QueryPerformanceCounter(endTime);

  memo1.Lines.Add('Die Routine benötigte etwa ' + IntToStr((endTime - startTime)
    * 1000 div freq) + 'ms');

end;


so ist es richtig, vorher hatte ich t:=a[x,n][i] hergenommen.
ausserdem Length(b[x,n])-1
Dann ist es ca. gleich schnell.
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: Di 06.09.16 11:40 
Noch eine kleine Schlussbemerkung:
Die Zwischenwerte brauche ich gar nicht, da ich den T in allen Himmelsrichtungen (also eigene 4 Schachblonen habe) und wenn eine Figur da ist, breche ich die Schablone ab. Das ist mir erst im Nachhinein gekommen.
acadam71
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Di 06.09.16 17:18 
@gerd8888: Soll Dein Schachprogramm die Protokolle Winboard bzw. UCI unterstützen oder willst Du eine eigene UI entwickeln? Zur Info: Ich bastle auch gerade an einer Schach-Engine. Den Zuggenerator habe ich bereits fertig und arbeite zurzeit an der Bewertungsfunktion und der Winboard-Anbindung.
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: Di 13.09.16 11:14 
Ich will erst mal das Programm schreiben und danach mal sehen, ob sich eine UCi lohnt.
acadam71: Wie schnell ist Dein Zuggenerator. Wieviele Zuege in 1 sek schafft dein Programm.

Ich habe nun bei meinen Programm festgestellt, dass die Bitboards sogar langsamer sind:
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:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, math;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
 
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
  var
  p:cardinal;
  maske,wk:int64;
  freq: Int64;
  startTime: Int64;
  endTime: Int64;


  {function Bittest (TestZahl : int64;Bitnr: byte):boolean;
  begin
    Result := (testzahl and (Int64(1) shl bitnr)) <> 0;
  end;}



  procedure BitSet(var TestZahl : int64;Bitnr: byte);
  var bitmaske:int64;
  begin
    //TestZahl := testzahl OR (1 shl BitNr);
    bitmaske := Int64(1shl bitnr;
    testzahl:= bitmaske or testzahl;
  end;

begin
  wK:=0;
  QueryPerformanceFrequency(freq);
  QueryPerformanceCounter(startTime);
  for p:=1 to 10000000 do begin
  maske:=0;
                (* erstelle Maske *)
  bitset(maske,0); //von
  bitset(maske,3);//nach
  (* Ziehe *)
  wK:=wK xor maske;
  (* zurueck*)
  wk:=wK xor maske;
  end;

  QueryPerformanceCounter(endTime);

  memo1.Lines.Add('Die Routine benötigte etwa ' + IntToStr((endTime - startTime)
    * 1000 div freq) + 'ms');

end;

procedure TForm1.Button2Click(Sender: TObject);
var
  a:array[1..64of byte;
  p:cardinal;
  freq: Int64;
  startTime: Int64;
  endTime: Int64;
begin
  QueryPerformanceFrequency(freq);
  QueryPerformanceCounter(startTime);
  for p:=1 to 10000000 do begin
    (* ziehen *)
    a[1]:=10;
    a[2]:=0;
    (* zurueck *)
    a[2]:=0;
    a[1]:=10;
  end;

  QueryPerformanceCounter(endTime);

  memo1.Lines.Add('Die Routine benötigte etwa ' + IntToStr((endTime - startTime)
    * 1000 div freq) + 'ms');

end;

end.


mit Bitboard 145 ms
auf einem array 14 ms

Was mache ich falsch?
JoelH
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 798
Erhaltene Danke: 17

Win10
Delphi XE7/Tokyo Prof.
BeitragVerfasst: Di 13.09.16 14:52 
Na ja, das ist schon ein wenig unfair. Bei der Bitgeschichte setzt du jeweils die Maske neu, das muss nicht sein. Einmal setzen sollte reichen. Des Weiteren setzt du in der Bitvariante variabel, während du in der Arrayvariante Konstanten verwendest, das der Compiler sicher weiter optimiert.

Was die Knotenzahlen angeht. Ich kann für mein Programm ca. 1 Mio. Knoten in der Sekunde einwerfen. Dabei muss aber berücksichtigt werden, dass davon im Regelfall nur gut 50% legal (Allerdings spielt das Programm die Variante Atomic, kein reguläres Schach) sind, davon werden dann nochmal gut 50% aus sortiert durch Alpha/Beta, Hashtabellen usw.
Der Zuggenerator ist alleine sicher schneller (Hab es nie ausprobiert, wie schnell genau) , die BEwertungsfunktion ist die Bremse, so oder so.


Zusatz: Okay, hab mal die Bewertung abgekoppelt und aus der Grundstellung 10.000.000 Züge erzeugen lassen. Das hat 2925 ms gedauert. Also ca. 3418 Züge pro ms.

_________________
mfg. Joel