[Echecs et Mat] Pause des calculs en virgule flottantes

Bonjour,

Alors, j’y ai passé un jour de plus … Avec de la persévérence et du travail on sait jamais.

J’ai trouvé que les valeurs des pièces doivent être scrupuleusement adaptées au mode calculatoire qu’exige le jeu d’échecs.

Ainsi, j’ai redéfini les valeurs de mes pièces ainsi :
– Light values
W_Pawn_Val : Float := 0.000000001;
W_Tower_Val : Float := 0.000000004;
W_Chavalier_Val : Float := 0.00000000245;
W_Valey_Val : Float := 0.00000000255;
W_Queen_Val : Float := 0.000000008;
W_King_Val : Float := 0.000000034;

– Dark values
B_Pawn_Val : Float := 0.000000001;
B_Tower_Val : Float := 0.000000004;
B_Chavalier_Val : Float := 0.00000000255;
B_Valey_Val : Float := 0.0000000245;
B_Queen_Val : Float := 0.000000008;
B_King_Val : Float := 0.000000034;

Et mon heuristique est devenu celle - ci (l’exemple est donné pour les noirs) :

 function Black_heuristic(Ground : in Chess_Type) return Float is
     Hcost : Float := 0.0;
     Ucost : Float := 0.0;
     Usr : Chess_Type := Chess_Type(Ground);
     Successors : Successors_Type;
     sum : Float := 0.0;
   begin


      Hcost := B_Count - (B_Count - (white_Total(Usr.white, Usr.white_last) + ((Black_Total(Usr.Black, Usr.Black_last)))));
      Ucost := white_Total(Usr.white, Usr.white_last);
     for Line in Line_Type loop
        for Colum in Column_Type loop
           if usr.Board(Line, (Colum)).Piece in WK..WP then
              declare

              begin

                 case Usr.Board(Line, (Colum)).Piece is
                    when Empty =>
                       null;
                    when WK =>
                       Sum := Sum + W_King_Val/10.0;
                    when WQ =>
                       Sum := Sum + W_Queen_Val/10.0;
                    when WC =>
                       Sum := Sum + W_Chavalier_Val/10.0;
                    when WV =>
                       Sum := Sum + W_Valey_Val/10.0;
                    when WT =>
                       Sum := Sum + W_Tower_Val/10.0;
                    when WP =>
                       Sum := Sum + W_Pawn_Val/10.0;
                    when others =>
                       null;
                 end case;

              end;
           end if;
        end loop;
     end loop;
  Sum := 0.0;
     Successors  := white_Successors(Usr);

     if Successors.Successor /= 0 then
         for I in 1..Successors.Successor loop
            declare
               Tmp : Chess_Type := Chess_Type(Successors.Plan(i));
            begin
               if (white_Total(Tmp.white, Tmp.white_last) - white_Total(Usr.white, Usr.white_Last)) >= B_King_Val then
                  return -((B_King_Val * 10000.0 * Float(Ground.Round)));

               else
                  sum := sum + (white_Total(Tmp.white, Tmp.white_last) - white_Total(Usr.white, Usr.white_Last));


               end if;
            end;

            declare
               Tmp : Chess_Type := Chess_Type(Successors.Plan(i));
               Black_Succs : Successors_Type := Black_Successors(Tmp);
               Sum : Float := 0.0;
               Gains : Float := 0.0;
            begin

               for J in 1..Black_succs.Successor loop
                  declare
                     Black_Round : Chess_Type := Chess_Type(Black_succs.Plan(j));
                  begin
                     gains := gains + ((Black_Total(Black_round.Black, Black_round.Black_last) -  Black_Total(Usr.Black, Usr.Black_Last)) - white_Total(Tmp.white, Tmp.white_last));

                     for Line in Line_Type loop
                        for Colum in Column_Type loop
                           if Black_round.Board(Line, (Colum)).Piece in BK..BP then
                              declare

                              begin

                                 case Black_round.Board(Line, (Colum)).Piece is
                                    when Empty =>
                                       null;
                                    when BK =>
                                       Sum := Sum + B_King_Val/10.0;
                                    when BQ =>
                                       Sum := Sum + B_Queen_Val/10.0;
                                    when BC =>
                                       Sum := Sum + B_Chavalier_Val/10.0;
                                    when BV =>
                                       Sum := Sum + B_Valey_Val/10.0;
                                    when BT =>
                                       Sum := Sum + B_Tower_Val/10.0;
                                    when BP =>
                                       Sum := Sum + B_Pawn_Val/10.0;
                                    when others =>
                                       null;
                                 end case;

                              end;
                           end if;
                        end loop;


                  end;

               end loop;
               Hcost :=  Hcost + Sum / Float(Black_succs.Successor);
               Hcost := Hcost + Gains / (Float(Black_succs.Successor) * 2.0);
            end;

         end loop;


         Ucost :=  Ucost + Sum;
     end if;
    Sum := 0.0;
     for Line in Line_Type loop
        for Colum in Column_Type loop
           if usr.Board(Line, (Colum)).Piece in BK..BP then
              declare

              begin

                 case Usr.Board(Line, (Colum)).Piece is
                    when Empty =>
                       null;
                    when BK =>
                       Sum := Sum + B_King_Val/100.0;
                    when BQ =>
                       Sum := Sum + B_Queen_Val/40.0;
                    when BC =>
                       Sum := Sum + B_Chavalier_Val/240.0;
                    when BV =>
                       Sum := Sum + B_Valey_Val/50.0;
                    when BT =>
                       Sum := Sum + B_Tower_Val/300.0;
                    when BP =>
                       Sum := Sum + B_Pawn_Val/10.0;
                    when others =>
                       null;
                 end case;

              end;
           end if;
        end loop;
     end loop;


     return (Hcost + Sum) - ucost;
   end Black_Heuristic;

Niveau zéro, l’heuristique fait touner le jeu en boucle ; Alors que niveau 1 avec 2 de profoncdeur, C’est Light Echec and Light Mat dans les premières minutes.

J’ai interverti les valeurs des fous et des chavaliers entre les blancs et les noirs pour avoir un contraste.

La valeur des rois est scrupuleursement identique et est strictement égale à la somme des autres pièces.

Faire attention de distinguer les valeurs de la variable Sum dont la porté est différente pour ucost et hcost alors que ucost accumule le handicap pour l’état à évaluer et hcost l’avantage du même état.

Résultat obtenu : (chess-zero_player_depth_2)
joshua-chess-zero_player_deph_2

Aussi, je prie de m’excuser, j’ai confondu dans un message précédent, les secondes et les dixiemes de seconde, ici il s’agit de 21 secondes contre 19.

Bonjour,

Je suis désolé, parce qu’il y a une notion dans les calculs que je ne parviens pas à assimiler malgrès tout mes efforts.
J’ai lutter à cause de cas d’éhec où le programme ne trouvait pas de successeur dont la valeur fut suppérieur à la perte du roi.
J’ai donc accumuler les zeros dans mes facteurs multiplicateur afin de trouver l’équilibre.

Je suis finalement parvenu à une heuristique qui permet d’obtenir Light mat au niveau zéro et Black mat au niveau 1 si j’initialise le jeu en jouant E2E3 au prmier coup ave les blancs.

J’ai modifier par recherche d’équlibre la valeur du roi qui était égale à la somme des autres pièces pour y additionner une moitié de plus correspondant à la moitier des points de l’adversaire.

Et j’ai réévaluer les points pour les mouvement et les facteur mltiplicateur selon l’origine des points, c’est à dire, pour les gains immediats, les mouvement immediat , les perte immediate, les risque immediate et les prevision des valeurs du coup suivant prévu.

J’avais oublié d’affecter ucost pour l’évaluation des mouvement de l’adversaire.

J’arrive à une heuristique s’exprimant ainsi :

       function Black_heuristic(Ground : in Chess_Type) return Float is
          Hcost : Float := 0.0;
          Ucost : Float := 0.0;
          Usr : Chess_Type := Chess_Type(Ground);
          Successors : Successors_Type;
          sum : Float := 0.0;
       begin
          Hcost := (B_Count - (B_Count - white_Total(Usr.white, Usr.white_last))) + Black_Total(Usr.Black, Usr.Black_last);
          Ucost := white_Total(Usr.white, Usr.white_last);
          for Line in Line_Type loop
             for Colum in Column_Type loop
                if usr.Board(Line, (Colum)).Piece in WK..WP then
                   declare

                   begin

                      case Usr.Board(Line, (Colum)).Piece is
                         when Empty =>
                            null;
                         when WK =>
                            Sum := Sum + W_King_Val/10.0;
                         when WQ =>
                            Sum := Sum + W_Queen_Val/10.0;
                         when WC =>
                            Sum := Sum + W_Chavalier_Val/10.0;
                         when WV =>
                            Sum := Sum + W_Valey_Val/10.0;
                         when WT =>
                            Sum := Sum + W_Tower_Val/10.0;
                         when WP =>
                            Sum := Sum + W_Pawn_Val/10.0;
                         when others =>
                            null;
                      end case;

                   end;
                end if;
             end loop;
          end loop;

          Hcost := Hcost * 1000000.0;
          Ucost := Ucost + Sum;
          Sum := 0.0;
          Successors  := white_Successors(Usr);

          if Successors.Successor /= 0 then
             for I in 1..Successors.Successor loop
                declare
                   Tmp : Chess_Type := Chess_Type(Successors.Plan(i));
                begin
                   if (white_Total(Tmp.white, Tmp.white_last) - white_Total(Usr.white, Usr.white_Last)) >= B_King_Val then
                      return -(B_King_Val * 100000000000000000000.0);

                   else
                      sum := sum + (white_Total(Tmp.white, Tmp.white_last) - white_Total(Usr.white, Usr.white_Last));


                   end if;
                end;
              declare
                   Tmp : Chess_Type := Chess_Type(Successors.Plan(i));
                   Black_Succs : Successors_Type := Black_Successors(Tmp);
                   Sum : Float := 0.0;
                   Gains : Float := 0.0;
                begin

                   for J in 1..Black_succs.Successor loop
                      declare
                         Black_Round : Chess_Type := Chess_Type(Black_succs.Plan(j));
                      begin
                         gains := gains + ((Black_Total(Black_round.Black, Black_round.Black_last) - Black_Total(Usr.Black, Usr.Black_Last)) - white_Total(Tmp.white, Tmp.white_last));

                         for Line in Line_Type loop
                            for Colum in Column_Type loop
                               if Black_round.Board(Line, (Colum)).Piece in BK..BP then
                                  declare

                                  begin

                                     case Black_round.Board(Line, (Colum)).Piece is
                                        when Empty =>
                                           null;
                                        when BK =>
                                           Sum := Sum + B_King_Val/10.0;
                                        when BQ =>
                                           Sum := Sum + B_Queen_Val/10.0;
                                        when BC =>
                                           Sum := Sum + B_Chavalier_Val/10.0;
                                        when BV =>
                                           Sum := Sum + B_Valey_Val/10.0;
                                        when BT =>
                                           Sum := Sum + B_Tower_Val/10.0;
                                        when BP =>
                                           Sum := Sum + B_Pawn_Val/10.0;
                                        when others =>
                                           null;
                                     end case;

                                  end;
                               end if;
                            end loop;
                         end loop;
                      end;
                   end loop;
                   Hcost := Hcost + (Sum / Float(Black_succs.Successor)) / 10000000000000.0;
                   Hcost := Hcost + Gains / (Float(Black_succs.Successor) * 10000000000000.0);
                end;
             end loop;
             Ucost :=  Ucost + Sum;
          end if;
          Sum := 0.0;
          for Line in Line_Type loop
             for Colum in Column_Type loop
                if usr.Board(Line, (Colum)).Piece in BK..BP then
                   declare

                   begin

                      case Usr.Board(Line, (Colum)).Piece is
                         when Empty =>
                            null;
                         when BK =>
                            Sum := Sum + B_King_Val/33.33;
                         when BQ =>
                            Sum := Sum + B_Queen_Val/26.36;
                         when BC =>
                            Sum := Sum + B_Chavalier_Val/4.0;
                         when BV =>
                            Sum := Sum + B_Valey_Val/6.36;
                         when BT =>
                            Sum := Sum + B_Tower_Val/13.0;
                         when BP =>
                            Sum := Sum + B_Pawn_Val/3.0;
                         when others =>
                            null;
                      end case;

                   end;
                end if;
             end loop;
          end loop;

          return ((Hcost * 10.0 + Sum * 3333333.33) - Ucost / 10000000.0) * 125.0;
       end Black_Heuristic;

J’ai voulu faire une partie contre l’ordinateur, ça a buggé.

Il manquerait 3 zero à la pondération au moment de retourner la valeur du jeu dans le cas d’une potentielle prise du roi et alors éventuellement trois zéro de trop à la pondération de la première évaluation de hcost, l’avantage de l’état courant.

Ton mode opératoire implique non pas de jouer aux échecs mais de jouer contre la programmation que tu as implémenté.
La notion d’IA, c’est considérer l’apprentissage.

Bonjour Zargos.

Pourrais tu préciser ton propos ? Ca je ne parviens pas à saisir le sens de la première phrase de ton message.
S’il te plait ?

Tu veux un programme de jeu d’échec qui soit capable de jouer tout seul ou contre un autre joueur.
Pour ça, il faut en premier prévoir le jeu contre un autre joueur que contre lui-même. Car apprendre les échecs en jouant contre soit-même c’est rester à tout jamais un jour extrêmement médiocre.

Et tel que pratique, tu modifie les paramètres afin de t’assurer des résultat voulu tels que tu les vois pas tels qu’ils devraient être.

En gros si toi tu considères que le programme doit dire que 2+2=5 tu vas adapter le système pour que ce soit le cas.
Alors qu’il faudra juste apprendre au programme à faire une addition, pas à faire un résultat convenu.

Le jeu d’échec est la concordance de plusieurs aspect:

  • La capacité à anticiper les coups sur un à plusieurs tours, donc à construire un arbre des conséquences (i.e.: je bouge une pièce, le programme étudie toutes les coups possible). C’est ici que la valeur d’une pièce a son importance. entre les blanc et les noirs , la seule différence c’est que les blancs commence - ils ont donc l’initiative. Une tour est une tour, qu’elle soit blanche ou noire, donc la valeur de la pièce est la même.
  • la prise en compte d’un contexte, qui est susceptible de modifier l’arbre des conséquences (par exemple le fait de faire un roque, petit ou grand); ou encore la recherche de la fourchette (le fait avec une seule pièce de menacer de pièce de façon équivalente - à minima)
  • La prise de type de partie, c’est à dire avoir en bibliothèque des parties déjà jouées, permettant de retrouver des situations connues avec des solutions connues et immédiates: par exemple la fin avec roi contre roi et pion; il y a une solution mathématique à ce problème.
  • L’apprentissage: le programme doit pouvoir apprendre.

Il te faut pas commencer par faire jouer le programme contre lui-même, c’est perdu d’avance. Il faut lui apprendre à jouer contre quelqu’un d’autre.

Enfin, de deux choses l’une, tu sais vraiment jouer aux échecs et tu conçois le programme pour reproduire ton apprentissage, soit tu ne sais pas et tu considère que le programme doit apprendre à jouer et fur et à mesure de ses parties.

Merci pour ta contribution.
Malheureusement ici, il n’est pas sujet de processus d’apprentissage car le jeu est solvé avec l’algorithme minmax en réponse à un jeu à somme nulle.

Le principe réside dans l’évaluation des états du jeu.

Je poursuis mon investigation pour l’évaluation avec mon heuristique afin de palier à l’erreur précédente.

J’ai apporté plusieurs modification.

Entre temps, j’espère avoir trouvé le point restant en suspend concernant les calculs…
Sensiblement le retour de min max indique la meilleur valeur pour la profondeur voulue…
Ce qui fait que si minmax trouve un chemin, pour les profondeurs indiquées et intermédiaire, le jeu peut provoquer une erreur dans le cas d’une mise en échec.

Pour palier à mon défaut de calcul relatif aux valeurs résultante de cette recherche en profondeur, j’ai introduit une variable, qui peut être une constante nommé « Risk » prenant la valeur des gains immédiat de l’adversaire.

Ansi,

La ligne : Hcost := Hcost * 1000000.0;
devient : Hcost := Hcost * 1000.0;

La ligne : return -(B_King_Val * 100000000000000000000.0);
est devenue : return -(B_King_Val * 100000000000000000000000.0);

et la ligne : return ((Hcost * 10.0 + Sum * 3333333.33) - Ucost / 10000000.0) * 125.0;
devient : return (((Hcost * 100.0 + Sum * 333333.33) - Ucost / 10000000.0) * 180.0) - Risk * 100000000.0;

Alors que la variable Risk est évalué avec :

Risk := white_Total(Tmp.white, Tmp.white_last) - white_Total(Usr.white, Usr.white_last)

Etant les gains immediat de l’adversaire pour un éventuel coup suivant.

On doit donc pouvoir à présent réduire le nombre de zéro un peu partout dans mon texte.

Bonjour,

Faites attention au cas où vous vous référiez à mon algo, j’ai oublié d’affecter Ucost à la première évaluation de Sum, pour les mouvements de l’adversaire.