Un générateur de coups d’Echecs en VBA

mercredi 3 août 2011
par  Matt
popularité : 6%

Générer une Collection de coups : GenerateLazyMoves(), listOfMoves, movePlayer, While


Appelons le générateur de coup du Cg1.

Calculons la description des coups aux formats San (utilisé dans un .pgn) puis descriptif.

Un générateur de coups d’Echecs en Excel VBA

Le générateur de coups automatise dans une boucle les opérations de la session précédente.

Le résultat est une liste de coups. Quand on parle de liste, en VBA il faut penser Collection.

Dans la fenêtre d’Exécution immédiate (Ctrl+G) du VBE, copier-coller et valider par ENTER :

DynamicContext

La procédure DynamicContext() crée une Collection de coups dénommée listOfMoves.

Pour l’instant elle existe (Not Nothing) mais elle est vide.

? listOfMoves.Count

[bleu marine]0[/bleu marine]

Il y a zéro coup dans la liste.

Appelons le générateur de coup pour le Cavalier avec comme paramètre listOfMoves :

boardMain.GetPiece(g1).GenerateLazyMoves listOfMoves

Un coup est [bleu marine]Lazy[/bleu marine] (paresseux) tant qu’on n’a pas vérifié si le Roi n’est plus en échec après qu’une pièce de son camp a joué ce coup. Ce n’est pas réellement une histoire de paresse, c’est plutôt que le contrôle de la résolution de l’échec du Roi est coûteux.

Un [bleu marine]Lazy[/bleu marine] coup devient légal si le Roi n’est pas en échec ou si ce coup résout l’échec. Quand un Roi est mat, cela signifie que dans la Collection des [bleu marine]Lazy[/bleu marine] coups, aucun ne permet de sauver le Roi. Il n’y a plus un seul coup légal.

Combien de coups le générateur a-t-il généré dans la Collection ?

? listOfMoves.Count

[bleu marine]2[/bleu marine]

Le générateur a trouvé deux coups de Cavalier à partir de g1.

Comme on est au tout début de la partie, le Roi Blanc ne peut pas encore être en échec. Ces deux [bleu marine]Lazy[/bleu marine] coups sont donc légaux mais pour simplifier, on ne va pas tout de suite le vérifier.

Accédons au premier coup d’indice 1 dans la collection

Set movePlayer = listOfMoves(1)

On utilise la variable movePlayer déclarée Public dans le module ModChess essentiellement pour son utilisation dans la fenêtre d’Exécution immédiate.


Notation d’un coup

Affichons ce coup : vous pouvez taper cette ligne en vous aidant de l’autocomplétion après un "."

? movePlayer.PieceMoved.Name + movePlayer.SquareFrom.Name + "-" + movePlayer.squareTo.Name

[bleu marine]Ng1-f3[/bleu marine]

A première vue, cela apparaît comme la simple concaténation de trois String. Cependant pour optimiser, on ne calcule la description d’un coup que si on veut l’afficher ou en phase de mise au point. Pour l’instant la description du coup est vide

? movePlayer.Description

Rien ne s’affiche.

movePlayer.PgnSanFormat True

La méthode PgnSanFormat() calcule la description du coup selon le format dit San utilisé dans les parties .pgn

Si le dernier paramètre de type Boolean est True, alors on résout l’ambiguïté potentielle de la case d’origine de la pièce quand deux pièces de même type appartenant au même joueur peuvent atteindre la même case. Ex : Cd2 et Cg1 pour la case d’arrivée Cf3. Dans ce cas là, la notation du coup au format San est Cg-f3 avec l’initiale de la case de départ.

? movePlayer.Description

[bleu marine]Nf3[/bleu marine]

Il n’y a pas eu d’ambiguïté dans la position de départ du Cavalier.

? movePlayer.DescrFull

[bleu marine]Ng1-f3[/bleu marine]

C’est la description complète du coup dans la notation dite descriptive qui n’a pas l’ambiguïté du format San utilisé dans les parties d’Echecs .pgn

Calculons également la notation du second coup de la liste sans résoudre d’éventuelle ambiguïté puisque dans la position de départ, il n’y en a pas.

listOfMoves(2).PgnSanFormat False

Pour des raisons de performance, on appelle PgnSanFormat() avec False comme paramètre de résolution d’ambiguïté. Car cette résolution est coûteuse. Ce n’est que lorsqu’on doit afficher un coup sur le GUI pour l’utilisateur final qu’on doit résoudre l’ambiguïté de la notation .pgn avec le dernier paramètre de PgnSanFormat() à True.

On a fait un utilitaire de debug pour afficher le contenu d’une liste de coups :

DgbMovesPrint listOfMoves

[bleu marine]Move 1 : Nf3

Move 2 : Nh3[/bleu marine]


Réinitialiser la liste de coups

Vous pouvez effacer chaque coup de la liste de coups par :

listOfMoves.Remove 1

Le 1ere item de la liste a été effacée. Puis une seconde fois :

listOfMoves.Remove 1
? listOfMoves.Count

[bleu marine]0[/bleu marine]

La liste de coups est à nouveau vide.


ClearListOfMove() et la boucle While Wend

Quand la liste de coups sera plus importante, l’effacement manuel sera trop long.

Dans la fenêtre d’Exécution immédiate, on pourra utiliser l’utilitaire :

ClearListOfMove

Les curieux pourront étudier cette courte procédure de ModChess.

Le fait d’avoir fait manuellement l’effacement des deux coups de Cavalier aidera dans la compréhension de la procédure qui fait la même chose mais dans une boucle.

En haut de la fenêtre d’Edition de ModChess, il y a deux listes déroulantes ([bleu marine]listbox[/bleu marine]) appelées : "(General)" et "(Declarations)".

Sélectionner dans la listbox "(Declarations)" à droite, la 2ème procédure ClearListOfMove().

ClearListOfMove() efface la Collection des coups d'Echecs

Après avoir testé si la Collection listOfMoves existe via If Not ... Nothing, ClearListOfMove() introduit la nouvelle structure conditionnelle :

While condition

TAB Bloc d’instructions ’ à aligner avec une TAB de plus que la marge du While.

Wend

On boucle tant que [1] la condition [bleu marine]listOfMoves.Count > 0[/bleu marine] est True, autrement tant qu’il y a des coups dans la liste. Cela signifie que le Bloc d’instructions en particulier [bleu marine]listOfMoves.Remove 1[/bleu marine] doit à un moment donné impérativement faire évoluer la condition à False sinon c’est la boucle sans fin.

On reconnaît immédiatement ce bug. Le PC utilise 100% de la CPU à tourner à fond dans la boucle. Cela fait chauffer la CPU si cela s’éternise et la souris n’est plus aussi réactive.

  • En théorie on peut arrêter l’exécution de la macro dans Excel par Ctrl+PAUSE.
  • En pratique, on peut être amené à tuer l’application Excel avec le gestionnaire des tâches de Windows (Ctrl+Shift+Esc) et on perd toutes les modifications qui n’ont pas encore été sauvées.

En phase de développement, pensez à sauvegarder avant d’exécuter des boucles While non encore au point.

Bien évidemment il n’y a pas de bug dans ClearListOfMove().

A la fin du Bloc d’instructions quand on a libéré le coup de la mémoire par :

Set moveThis = Nothing

on tombe sur l’instruction Wend qui correspond au Next à la fin du Bloc d’instructions d’un For.

On boucle en posant à nouveau la question si la condition [bleu marine]listOfMoves.Count > 0[/bleu marine] est True.

S’il reste encore des coups à effacer, on entre à nouveau dans le Bloc d’instructions pour une nouvelle itération.

Si la condition [bleu marine]listOfMoves.Count > 0[/bleu marine] devient False, on saute tout le Bloc d’instructions et on se retrouve sur l’instruction suivante, après le Wend, qui est ici :

Set listOfMoves = Nothing

On libère la liste des coups de la mémoire.


Déboguer le générateur de coups plus en détail

Dans la fenêtre projet du VBE, double-cliquez sur le module de classe Piece.

Dans la listbox des procédures de VBE, sélectionner GenerateLazyMoves()

Placez un point d’arrêt dans la 1ere instruction :

   Select Case m_typePiece

Dans la fenêtre d’Exécution immédiate, recommencez l’appel du générateur de coups :

boardMain.GetPiece(g1).GenerateLazyMoves listOfMoves

Avancez en pas à pas principal ou détaillé (F8) [2] selon le niveau d’exploration voulue.


Précédent : Le déplacement du cavalier en VBA

Suivant : Affichage des coups des Blancs en VBA


[1bleu marine]While[/bleu marine

[2bleu marine]Step Into[/bleu marine


Commentaires  Forum fermé

Brèves

Championnat jeunes 2018

dimanche 25 février 2018

A St Sernin sur Rance, Vadim Breton se qualifie pour le championnat de France jeunes. Il termine à la 4ème place des benjamins. http://echecs-occitanie.com/spip.php?article382&mode=AF

Les Jeunes qualifiés en NIII !

mercredi 14 décembre 2016

Dimanche 11 décembre 2016, aux interclubs jeunes à Leguevin, notre équipe a gagné un match et fait match nul aux deux autres.

L’équipe composée de Xavier, Vadim, Aurélie et Titouan termine 8ème et se qualifie pour la N3. A noter que Xavier et Vadim ont gagné toutes leurs parties.

Sur le Web : Site de la LMPE

Championnat jeunes

lundi 5 décembre 2016

Xavier, Vadim et Martin trois champions du Tarn et Garonne
Lire l’article

Coupe Loubatière

lundi 5 décembre 2016

Le club qualifié pour la phase régionale de la coupe Loubatière
Lire l’article

Sur le Web : Coupe Loubatière

Tournoi interne 2016-2017

lundi 5 décembre 2016

C’est reparti pour le tournoi interne : 1 partie par mois de novembre à mai
Lire l’article

Live Playchess.com

mercredi 7 septembre 2016