IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

Application.ProcessMessages pas aussi efficace qu'on pourrait croire [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut Application.ProcessMessages pas aussi efficace qu'on pourrait croire
    et bien sûr, je suis à la poursuite/à la recherche d'une idée/d'une astuce/d'un truc pour contourner ce que je m'en vais vous conter ci-dessous, qui n'est pas piqué des vers !

    Bonsoir à tous !

    Or donc, toujours dans les méandres des jeux d'échecs, je voulais faire rejouer une partie au programme sur lequel je travaille, et qui fonctionne bien, sauf avec ce problème.

    Au départ l'organisation de mon programme est simple : je lance le moteur qui va me servir de partenaire, je clique deux fois sur le plateau, ça génère une string genre "e2e4" qui est envoyée au moteur par le biais de l'événement OnChange d'un TLabeledEdit.
    Et le moteur va renvoyer son coup grâce à une chaîne identique dans un autre TLabeledEdit, récupéré aussi dans son OnChange.

    Tous ces échanges sont envoyés au système d'affichage qui fait se déplacer les pièces sur le plateau et c'est très joli et voilà le monsieur il est content.

    Jusqu'à tout à l'heure où j'avais une longue série de coups représentant une partie que je voulais revoir.
    Je me suis dit "Fastoche ! En 5 minutes c'est torché" et trois heures plus tard j'y suis encore et me voilà à poster ma bouteille à la mer...

    Ça ne devait pas être une bonne idée, car dès le départ ça partait mal (chez moi c'est un signe) : je me souvenais que pour saisir quelque chose on peut utiliser InputQuery mais ayant oublié la syntaxe, j'ai donc tapé quelque chose genre s := InputQuery, ai mis le curseur en plein milieu du mot, ai fait F1 et paf !, dans le décor, ou plutôt, complètement à côté de la plaque. Essayez, vous verrez bien...

    Suis alors parti à la pêche aux infos sur le web, et non sans mal j'ai écrit ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    procedure TForm1.btnLoadGameClick(Sender: TObject);
    var
      s: string;
      i: integer;
      sl:TStringList;
    begin
      sl:=TStringList.Create;
      s := InputBox('Partie à rejouer', 'Entrez les coups :', 'Ici...'); // copier/coller de la liste des coups blanc noir blanc noir etc.
      // dans http://wiki.lazarus.freepascal.org/Dialog_Examples/fr on peut lire
      // "Une chaîne de caractère par défaut, peut être rentrée optionnellement."
      // résultat, une chaîne de caractère par défaut doit être rentrée. !!!
      // J'adore les options obligatoires, grrrrrr !
      // même topo avec l'infobulle qui s'affiche : erronée... Bref...
    
      Split(' ', s, sl); // pour découper la chaine en coups genre e2e4
      for i := 0 to sl.Count-1 do begin
        if (i mod 2) = 0 then begin // blancs
          ledReceivedFromPlateau.Text := sl[i]; // le coup des blancs
          Application.ProcessMessages; // la respiration qui devrait rendre la main, mais...
          memoblancs.Lines.Add(sl[i]); // bien loggé
          Sleep(2000); // pour avoir le temps de voir
        end else begin // noirs
          memonoirs.Lines.Add(sl[i]); // bien loggé, mais depuis la chaîne passée, pas le retour du moteur
        end;
      end;
      sl.Free;
    end;
    (désolé, j'ai essayé code=ceci, code=cela, pas moyen d'avoir un peu de couleur dans ce bout de code...)

    J'en suis là : la ligne ledReceivedFromPlateau.Text := sl[i]; est la même que celle que j'utilise quand je clique pour de vrai à la souris sur le plateau : ledReceivedFromPlateau.Text := ClickOnPlateau; ClickOnPlateau est une string qui va contenir le coup joué, genre comme ci-dessus, e2e4.

    Si je clique avec la souris, comme raconté plus haut, le moteur reçoit la string, la traite et renvoie sa réponse ; si j'exécute la boucle sur la string passée dans l'InputBox, je ne vois rien revenir du moteur...
    Ce fonctionnement donne l'impression que je ne sors pas de la procédure btnLoadGameClick (enfin, c'est p'têt pas les bons mots mais je ne vois pas comment le dire autrement) et pourtant les memos de log sont correctement remplis.
    Pour moi, il n'y a aucune raison pour que ça ne fonctionne pas...

    Une dernière précision : si je passe dans l'InputBox une chaîne de 1 coup (e2e4), tout fonctionne bien, ie le coup est reçu par le moteur qui répond. Mais bien sûr dans ce cas-là on est sorti de la boucle et donc de la procédure.

    Une idée, les copains ?
    Ah oui, j'ai les CThreads activés dans le .lpr, et j'ai blindé les routines du moteur d'Application.ProcessMessages sans que ça change ce comportement étrange...

    Un dernier mot : je poste dans la section Lazarus mais c'est peut-être lié au fait que le moteur (écrit par glegat dans l'autre post et adapté par votre serviteur) est au départ une unité Free Pascal. J'ai peut-être oublié un uses ou un autre truc qui n'empêcherait ni la compilation ni l'exécution basique, mais je ne vois vraiment pas quoi.

    Merci de m'avoir lu (oui, c'était long) et merci pour vos pistes
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  2. #2
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 954
    Points : 9 284
    Points
    9 284
    Par défaut
    hello J.P T,
    je ne sais pas si c'est moi qui ne comprend rien à ton code, mais pourquoi ne fais-tu pas le même traitement pour les blancs et les noirs ? Et quand tu rentres une chaîne c'est toujours un coup des blancs en premier ? d'autre part le Split que tu utilises vient de quelle classe ? avec un TStringList tu peux utiliser la propriété délimiter. Voici ce que cela donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    procedure TfrmCandC.Button1Click(Sender: TObject);
    var
      s: string;
      i: integer;
      sl:TStringList;
    begin
      sl:=TStringList.Create;
      s := InputBox('Partie à rejouer', 'Entrez les coups :', 'Ici...'); // copier/coller de la liste des coups blanc noir blanc noir etc.
      // dans http://wiki.lazarus.freepascal.org/Dialog_Examples/fr on peut lire
      // "Une chaîne de caractère par défaut, peut être rentrée optionnellement."
      // résultat, une chaîne de caractère par défaut doit être rentrée. !!!
      // J'adore les options obligatoires, grrrrrr !
      // même topo avec l'infobulle qui s'affiche : erronée... Bref...
      sl.Delimiter := ' ';
      sl.DelimitedText := s;
    //  Split(' ', s, sl); // pour découper la chaine en coups genre e2e4
      for i := 0 to sl.Count-1 do begin
        if (i mod 2) = 0 then begin // blancs
          memoblancs.Lines.Add(sl[i]); // bien loggé
        end else begin // noirs
          memonoirs.Lines.Add(sl[i]); // bien loggé, mais depuis la chaîne passée, pas le retour du moteur
        end;
            ledReceiveFromPlateau.Text := sl[i]; // le coup  en cours
            Application.ProcessMessages; // la respiration qui devrait rendre la main, mais...
            Sleep(2000); // pour avoir le temps de voir
      end;
      sl.Free;
    Ami calmant, J.P (pas T)
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  3. #3
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 301
    Points
    11 301
    Billets dans le blog
    6
    Par défaut
    Si le LabeledEditOnChange pointe vers une procédure CalculeCoupDesNoirs, essaie de le mettre à nil avant de changer le Text puis de déclencher CalculeCoupDesNoirs et remettre le OnChange pour voir si ça valide la séquence. Dans ce cas, ça montrerait que le souci est lié au déclenchement du OnChange pendant le ProcessMessages, à expertiser... Pour ma part, en replay, je coderais plutôt les appels en dur, sans faire appel au LabeledEdit ni à son OnChange.
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  4. #4
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Salut J.P,

    et merci de ton retour.

    Citation Envoyé par jurassic pork Voir le message
    hello J.P T,
    je ne sais pas si c'est moi qui ne comprend rien à ton code, mais pourquoi ne fais-tu pas le même traitement pour les blancs et les noirs ?
    Parce que je veux simuler une partie où le joueur humain clique sur des cases pendant que le moteur attend la string représentant le coup joué puis à réception calcule sa réponse et la renvoie.
    Les attentes se basent sur l'événement OnChange des TLabeledEdit, remplis l'un par la procédure de concaténation des clics représentant le départ et l'arrivée du coup humain, et l'autre par une string préparée par le moteur.

    Et au final, je voulais juste ne pas être obligé de recliquer tous les coups blancs juste pour regarder le moteur noir jouer à son tour. D'où l'idée de la boucle pour envoyer les coups blancs dans la propriété .Text du TLabeledEdit concerné, comme s'ils avaient été cliqués.

    Citation Envoyé par jurassic pork Voir le message
    Et quand tu rentres une chaîne c'est toujours un coup des blancs en premier ?
    Pas nécessairement, mais pour cette partie c'est ainsi. En gros, la chaîne que j'ai notée commence comme ça : e2e4 g7g5 g1f3 e7e6 f1c4 b8c6...

    Citation Envoyé par jurassic pork Voir le message
    d'autre part le Split que tu utilises vient de quelle classe ? avec un TStringList tu peux utiliser la propriété délimiter.
    Bah, j'avais dû oublier cette propriété et du coup j'ai fouillé le web et trouvé quelque chose qui fait pareil :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    procedure Split(const Delimiter: Char; Input: string; const Strings: TStrings);
    begin // usage : Split(' ', string_à_splitter, stringlist_de_destination_des_bouts);
       Assert(Assigned(Strings)) ;
       Strings.Clear;
       Strings.Delimiter := Delimiter;
       Strings.DelimitedText := Input;
    end;
    (ah tiens, la couleur est revenue ! Quand je dis qu'il y a des mystères en informatique... Mais Gilles ne me croit pas, lol !)

    Citation Envoyé par jurassic pork Voir le message
    Voici ce que cela donne :
    Merci de t'être décarcassé mais je ne le teste pas car ça ne répond pas au cahier des charges qui est de m'éviter de recliquer tous les coups blancs de la partie tout en laissant le moteur répondre aux coups qu'il reçoit.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  5. #5
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Salut, Yves

    Content de voir que mes préoccupations t'interpellent également
    Citation Envoyé par tourlourou Voir le message
    Si le LabeledEditOnChange pointe vers une procédure CalculeCoupDesNoirs, essaie de le mettre à nil avant de changer le Text puis de déclencher CalculeCoupDesNoirs et remettre le OnChange pour voir si ça valide la séquence. Dans ce cas, ça montrerait que le souci est lié au déclenchement du OnChange pendant le ProcessMessages, à expertiser... Pour ma part, en replay, je coderais plutôt les appels en dur, sans faire appel au LabeledEdit ni à son OnChange.
    Pas sûr de t'avoir bien compris dans ce qui précède.

    Alors voilà ma proc sur le OnChange du TLabeledEdit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TForm1.ledReceivedFromPlateauChange(Sender: TObject);
    begin
      if ledReceivedFromPlateau.Text <> '' then
        if Length(ledReceivedFromPlateau.Text) = 4 then begin // = e2e4 par ex.
          GestionCoup(ledReceivedFromPlateau.Text, True); // proc pour le déplacement des pièces
          if ckbEngineRunning.Checked then // lié à l'état du moteur
            kempelen4lazarus.sinput := ledReceivedFromPlateau.Text; // vers moteur
          ledReceivedFromPlateau.Text := '';
        end;
    end;
    Un mot d'explication : kempelen4lazarus est le programme de Gérard adapté à ma sauce, sinput est une bête string déclarée globalement pour être accessible, et je la surveille ainsi (épuré pour alléger) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      procedure SaisitCoupHumain;
      begin
        log(' A vous de jouer...  ');
        // readln(coupsaisi); // version d'origine en mode console, remplacée par
        repeat sleep(10); Application.ProcessMessages; until sinput <> '';
        log('Entrée = ' + sinput);
        coupsaisi := sinput; 
        sinput := '';
        {mise en minuscule du coupsaisi}
        StrPcopy(@a,coupsaisi);
        coupsaisi := StrLower(@a);
      end;
    Ce bout de code est appelé ainsi depuis la boucle principale de jeu, et coupsaisi sera analysé plus loin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
          // choix est initialisé au lancement du prog
          if choix = 1 then begin // blancs
            if trait = 1 then SaisitCoupHumain else KempelenJoue;
          end;
          if choix = 2 then begin // noirs
            if trait = 1 then KempelenJoue else SaisitCoupHumain;
          end;
    Non, ce qui est fou, c'est que ça fonctionne si je tiens la souris et qu'au bout du compte la string résultante se retrouve dans kempelen4lazarus.sinput et que ça ne fonctionne plus si cette même variable est remplie automatiquement par ma boucle de lecture de partie enregistrée.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  6. #6
    Rédacteur/Modérateur
    Avatar de M.Dlb
    Inscrit en
    Avril 2002
    Messages
    2 464
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 464
    Points : 4 311
    Points
    4 311
    Par défaut
    Il doit manquer un évènement qui fait déclencher le "OnChange". De manière générale c'est difficile d'automatiser des interfaces graphiques, à moins de simuler des évènement souris ou clavier eux-mêmes... Et encore c'est pas gagné......
    Pour ce genre de choses, le mieux c'est de prendre un fichier texte en entrée et modifier le programme pour qu'il rejoue ce fichier texte.

    En général, il vaut mieux décorréler l'interface graphique du traitement réel de la donnée... Facile à dire mais parfois difficile à faire
    M.Dlb - Modérateur z/OS - Rédacteur et Modérateur Pascal

  7. #7
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Bonjour,

    et merci pour ton entrée :
    Citation Envoyé par M.Dlb Voir le message
    Il doit manquer un évènement qui fait déclencher le "OnChange". De manière générale c'est difficile d'automatiser des interfaces graphiques, à moins de simuler des évènement souris ou clavier eux-mêmes... Et encore c'est pas gagné......
    Et pourtant ça doit être le cas puisque j'attends que l'utilisateur humain (moi ) ait cliqué deux fois pour concaténer ces deux strings (représentant les positions de départ et d'arrivée) en une seule qui est passée par instruction dans la propriété .Text du TLabeledEdit, et que ça fonctionne dans ce cas-là.
    Et si une autre instruction modifie elle aussi cette propriété .Text ça ne fonctionne plus ...

    Citation Envoyé par M.Dlb Voir le message
    Pour ce genre de choses, le mieux c'est de prendre un fichier texte en entrée et modifier le programme pour qu'il rejoue ce fichier texte.
    Vu les difficultés auxquelles je fais face, je pense que le jeu n'en vaut pas la chandelle.

    Citation Envoyé par M.Dlb Voir le message
    En général, il vaut mieux décorréler l'interface graphique du traitement réel de la donnée... Facile à dire mais parfois difficile à faire
    Il me semble bien que c'est le cas...

    Enfin, pour résumer et synthétiser, j'en suis là (je le regroupe comme ça pour une visualisation sympathique, mais il s'agit bien de 2 procs différentes, hyper allégées pour aller à l'essentiel) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure TForm1.ledReceivedFromPlateauChange(Sender: TObject); // dans l'ihm
    begin
      kempelen4lazarus.sinput := ledReceivedFromPlateau.Text; // vers moteur
    memo1.Lines.Add('ihm '+kempelen4lazarus.sinput); // log OK
     
    procedure SaisitCoupHumain; // dans kempelen4lazarus
    begin
      log(' A vous de jouer...  ');
      // readln(coupsaisi);
      repeat sleep(10); Application.ProcessMessages; until sinput <> '';
    Form1.memo1.Lines.Add('kkk '+sinput); // jamais vu
    On est dans le même programme, là, c'est juste deux unités différentes...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  8. #8
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 420
    Points : 5 819
    Points
    5 819
    Par défaut
    salut

    pour eviter ce genre de soucis et afin de maitriser tes evenement tu peut passer comme ceci


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var
      LonChange : TNotifyEvent;
    ...
    Begin
      ...
          LonChange :=  ledReceivedFromPlateau.onChange ;
          ledReceivedFromPlateau.onChange := Nil; // tu desactive 
          ledReceivedFromPlateau.Text := trim(sl[i]); // le coup des blancs
          ledReceivedFromPlateau.onChange := LonChange;  // tu reactive
          ledReceivedFromPlateauChange(Self); // Tu force l'evenement onchange 
      ...
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  9. #9
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Salut, anapurna

    Aussitôt écrit aussitôt testé mais pas mieux...

    C'est peut-être une spécificité Linux, mon souci ?

    Merci pour la piste,
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  10. #10
    Membre chevronné

    Homme Profil pro
    au repos
    Inscrit en
    Février 2014
    Messages
    429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : au repos

    Informations forums :
    Inscription : Février 2014
    Messages : 429
    Points : 1 884
    Points
    1 884
    Par défaut
    Bonjour Jipété,

    Je ne suis pas certain d'avoir bien compris le mécanisme avec le moteur, aussi j'espère que je ne vais pas dire des idioties.

    Comme déjà souligné, je suis persuadé que le problème vient des événements OnChange.
    Il y a d'ailleurs quelque chose qui me "chipote" dans ton code de la procedure ledReceivedFromPlateauChange :
    à la dernière ligne tu réinitialises à '' ledReceivedFromPlateau.Text... ce qui provoque un deuxième appel à l'événement OnChange. Je ne sais pas si ça change quelque chose à ton problème, mais est-il impossible de croire que cela pertube un application.processmessages ? D'autant que ton Sleep est placé avant cette instruction.

    Si je peux me permettre...
    Pourquoi joues-tu avec des événements OnChange ? Il me semble qu'il y facilement moyen de s'en passer.
    1) "l'humain" joue son coup soit par 2 clics, soit par remplissage d'un TEdit (sans événement OnChange). Dans ce cas, c'est la frappe Enter qui valide son coup.
    2) Dès ce moment tu rend disable le plateau et le TEdit, et tu lances un TTimer qui va périodiquement scruter la réponse du moteur.
    3) Cette réponse peut se voir dans un simple Label et bien sûr graphiquement sur le plateau.
    4) Dès la réponse, tu rends de nouveau accessible le plateau et le TEdit, tu coupes le timer, et ainsi de suite...

    En ce qui concerne le fait de rejouer une partie :
    Comme tu le fais dans une boucle, tu ne permets aucune modification, donc il me semble que c'est du pur graphique, je ne vois pas en quoi le moteur et les LabelEdit devraient intervenir.
    Mais, ne serait-il pas intéressant de permettre au joueur de re-partir du coup 14 qu'il estime avoir mal joué et de voir l'impact d'un changement ?
    Cela demande un peu de code (réinitialisation du moteur avec la nouvelle séquence...), mais cela ne devrait pas être insurmontable.
    Je le répète, je ne sais pas comment fonctionne ce moteur. Serait-ce possible ?

    Cordialement
    Thierry

  11. #11
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Salut Thierry,
    Citation Envoyé par ThWilliam Voir le message
    [...]
    Je le répète, je ne sais pas comment fonctionne ce moteur. Serait-ce possible ?

    Cordialement
    Thierry
    Je ne sais pas encore ; je vais réfléchir à tout ça.

    Dans l'attente, j'ai ramené le problème à sa plus simple expression, histoire d'essayer de comprendre, donc une fiche, deux boutons, un checkbox, un memo et un tlabelededit et en avant dans un nouveau projet :

    D'abord, ce n'est pas une histoire d'unité car tout tient dans la même et le canard est bien vivant, damned ! (Et il est aussi vivant avec mon vieux Delphi7 lancé dans une VM Win2000.)

    Soit une procédure d'attente toute simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure TForm1.StartLoop;
    begin
      while ckbLoop.Checked do begin // Checkbox pour boucler
        if sinput <> '' then begin // si le "panier" est plein
          memo1.Lines.Add(sinput); // traitement des denrées
          sinput := ''; // raz du "panier" pour prochaine livraison
        end;
        Application.ProcessMessages;
        sleep(10);
      end;
    end;
    On pourrait croire, en lisant ce qui précède comme un scénario de série, que dès que la donnée est arrivée elle est traitée, mais que nenni !

    Et ça se voit très bien en pas-à-pas, grâce à l'autre procédure qui "charge la mule" avec les données :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure TForm1.ledReceivedFromPlateauChange(Sender: TObject);
    begin
      if length(ledReceivedFromPlateau.Text) = 4 then begin // si les commissions sont prêtes
        sinput:=ledReceivedFromPlateau.Text; // on remplit le "panier"
        sleep(500); // on attend un peu qu'il soit récupéré
        Application.ProcessMessages;
        // on peut penser que c'est bon (relisez l'autre code ci-dessus), on vérifie quand même 
        if sinput = '' then // si le "panier" est vide alors remise à zéro sinon
          ledReceivedFromPlateau.Text := ''; // impossible de renvoyer la même chose
      end;
    end;
    500 millisecondes pour 4 malheureux caractères c'est une enclume pour écraser une mouche ou sortir la Ferrari pour aller au tabac du coin, on est bien d'accord.

    Mais malgré cette débauche de moyens, avec un point d'arrêt sur la ligne suivant App.PM et la souris sur sinput, on se rend compte que sinput n'est pas vide alors que ça fait 499,999 millisecondes que ça doit être fait.
    Y a des choses qui me dépassent...

    Va falloir trouver le moyen de faire de la vraie programmation événementielle, peut-être avec un thread...

    Merci de m'avoir lu / soutenu et de m'avoir suggéré des trucs.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  12. #12
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 954
    Points : 9 284
    Points
    9 284
    Par défaut
    hello,
    au lieu de faire une boucle infernale d'attente pourquoi n'utilises-tu pas un timer comme ceci par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    procedure TForm1.ledReceivedFromPlateauChange(Sender: TObject);
    begin
      if length(ledReceivedFromPlateau.Text) = 4 then begin // si les commissions sont prêtes
        sinput:=ledReceivedFromPlateau.Text; // on remplit le "panier"
        sleep(40); // on attend un peu qu'il soit récupéré
        Application.ProcessMessages;
        // on peut penser que c'est bon (relisez l'autre code ci-dessus), on vérifie quand même
        if sinput = '' then // si le "panier" est vide alors remise à zéro sinon
          ledReceivedFromPlateau.Text := ''; // impossible de renvoyer la même chose
      end;
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
           if sinput <> '' then begin // si le "panier" est plein
            memo1.Lines.Add(sinput); // traitement des denrées
            sinput := ''; // raz du "panier" pour prochaine livraison
          end;
    end;
    L' intervalle du timer est réglé sur 20 .

    Ami calmant, J.P
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  13. #13
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Yop !
    Citation Envoyé par jurassic pork Voir le message
    hello,
    au lieu de faire une boucle infernale d'attente pourquoi n'utilises-tu pas un timer comme ceci par exemple : [...]
    Pourquoi ? Mais parce que je n'y ai pas pensé, tout simplement !

    Et je n'y ai pas pensé parce qu'au départ je suis parti du prog de glegat complètement séquentiel (à part la boucle de jeu) dans lequel j'ai juste remplacé les readln de saisie des coups entrés par l'utilisateur par mes boucles repeat...until sinput <> '' dont j'ai déjà parlé, et que j'ai suivi cette logique, bêtement...

    Bon, ton truc fontionne tip-top , on verra demain comment mélanger tout ça.

    En ce qui me concerne, j'ai trouvé comment faire fonctionner ça avec les threads, ça va bien aussi, sauf que ça me met un cpu à 100%
    (bon, tous les exemples du dossier examples/multithreading me mettent un cœur à 100%, pas glop)

    Bye,
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  14. #14
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Bonjour à tous,

    le proverbe japonais du jour :
    le bon commentaire du matin évite les bugs de la journée


    Regardez :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure TForm1.ledReceivedFromPlateauChange(Sender: TObject);
    begin
      if length(ledReceivedFromPlateau.Text) = 4 then begin
        sinput:=ledReceivedFromPlateau.Text;
        sleep(40); // obligatoire sinon texte pas effacé malgré App.PM
        Application.ProcessMessages; // App.PM ici --> texte effacé
        if sinput = '' then
          ledReceivedFromPlateau.Text := '';
    //    Application.ProcessMessages; // App.PM ici ou rien --> texte pas effacé ! ! ! !
      end;
    end;
    À partir de là, tout fonctionne du feu de Dieu, j'arrive même à me passer du timer de J.P, et tout va bien.

    Allez, un ch'tit , même si intellectuellement je ne suis pas satisfait et que je suspecte un sac de nœuds dans la méthode OnChange, genre le contrôle "Edit" de l'objet est "tenu" par je ne sais trop quoi et libéré par le App.PM et donc, si cette libération arrive après la demande d'effacement, ben c'est pas fait.
    Enfin, j'en sais trop rien mais ça ressemble à ça, en termes de comportement.

    Merci de supporter mes prises de tête

    Bonne journée,
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  15. #15
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 420
    Points : 5 819
    Points
    5 819
    Par défaut
    salut
    je ne suis pas partisant des timer ... trop rigide est dans certaine ne sont pas du tout adapté

    pourquoi ne pas utiliser les messages comme déclencheur ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    const
       WM_RECEIVEVT = WM_USER +1000;
       WM_SENDEVT   = WM_USER +1001;
     
    ...
     
      Protected
         procedure WMRECEIVEVT (var Message: TMessage); message WM_RECEIVEVT;
         procedure WMSENDEVT (var Message: TMessage); message WM_SENDEVT;
      ...
    pour déclencher les événements tu peut faire ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      PostMessage(Handle,WM_SENDEVT,0,0);
     
      PostMessage(Handle,WM_RECEIVEVT,0,0);
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  16. #16
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Citation Envoyé par anapurna Voir le message
    pourquoi ne pas utiliser les messages comme déclencheur ?
    Parce que je ne voulais pas rajouter de la complexité à un bordel inextricable...

    Je viens de décocher "résolu" car si ça fonctionne avec la petite maquette, ça ne veut plus rien savoir dans la vraie vie...

    Je reste persuadé qu'il y a un mic-mac avec le OnChange du TLabeledEdit, va falloir abandonner cette idée et trouver une autre solution.

    Imaginez un peu. D'un côté j'ai ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TForm1.ledSendToEngineChange(Sender: TObject);
    begin
      if ckbEngineRunning.Checked and (Length(ledSendToEngine.Text) = 4) // je vois bien écrit e2e4
        then btnSendClick(Sender);
    end;
     
    procedure TForm1.btnSendClick(Sender: TObject);
    begin
        sinput := ledSendToEngine.Text // là je suis censé mettre e2e4 dans sinput, et simuler le clic, d'accord ?
    end;
    et de l'autre côté, ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      log(' A vous de jouer...  '); // ça je peux le lire dans le mémo de log, au démarrage
      repeat sleep(10); Application.ProcessMessages; until sinput <> ''; // attente utilisateur, on est d'accord ?
      log('Entrée = ' + sinput); // et ça non, jamais vu !
    Et si pendant que "ça" attend je clique sur le bouton Send, je vois passer des choses fausses (genre sinput mis à jour avec de mauvaises données -- les données des coups blancs extraits de la liste, truc de ouf !) mais je ne vois jamais écrit dans le mémo de log "Entrée = valeur_passée"...

    Je baisse les bras, ça m'épuise...
    Car encore une fois, tout ce bazar fonctionne très bien quand je tiens la souris et que j'oublie l'idée d'envoyer à la place une simple liste de coups

    [EDIT une heure + tard] D'abord je barre une ligne, j'ai incriminé à tort les TLabeledEdit qui n'y sont pour rien, les pauvres : remplacés par des strings, c'est la même pagaille à partir de la boucle de lecture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
        if (i mod 2) = 0 then
        begin // blancs
          sinput := sl[i]; // coups envoyés au moteur, le 1er = e2e4
          memoblancs.Lines.Add('b1 '+sinput);
          memoblancs.Lines.Add('b2 '+sl[i]);
          sleep(500);
          Application.ProcessMessages;
          memoblancs.Lines.Add('b3 '+sinput);
          { dans le memoblancs :
      b1 e2e4
      b2 e2e4
      b3 e2e4 --> sinput toujours remplie après 500 msec...
      donc la partie réception ("l'autre côté") n'est jamais exécutée dans cette boucle...
          }
          // attente réponse des noirs
          repeat sleep(10); Application.ProcessMessages; until sRetourMoteur <> '';
          memonoirs.Lines.Add('n '+sRetourMoteur); // désespérément vide...
        end;
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  17. #17
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 420
    Points : 5 819
    Points
    5 819
    Par défaut
    Salut

    effectivement je pense qu'il se mélange les pinceaux
    pour ma part je l'aurais conditionné a l'appui sur la touche retour
    dans le keydown
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      if (Key=VK_RETURN) then 
      begin
         DO_MY_PROCESS
         Key := 0;
      end
    de plus je pense vraiment que tu devrais t'orienter vers les message puisque tu attend un retour du serveur et tu ne connais pas a l'avance son temps de réponse
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  18. #18
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Bon, j'en ai raz la casquette et si je poste ce n'est pas pour espérer une solution, il n'y en a pas, c'est pour vous montrer ce que je vis avec cette histoire.

    Dans le petit bout de copie d'écran ci-dessous, vous pouvez apercevoir une instruction qui remet ma chaîne "sinput" à vide, sauf que l'infobulle en mode pas-à-pas montre que ce n'est pas fait... Comment débugger dans ces conditions ?

    Nom : sinput_1.jpg
Affichages : 693
Taille : 11,4 Ko

    Alors j'ai rajouté une ligne App.PM qui arrange les choses ici (l'infobulle m'indique alors '') mais les déglingue ailleurs, dans la procédure qui attend des données grâce à ce "sinput", justement, et ces données ont été transmises au dessus de la ligne sleep(100); et malgré cette valeur démente, ben "sinput" est vide dans l'autre procédure, je le vois au résultat dans un mémo :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        log( ' Votre choix ? : ');
        //	readln(choix); // origine
        repeat sleep(10); Application.ProcessMessages; until sinput <> '';
        log('Touche = ' + sinput); // jamais vu si App.PM

    C'est abominable comme tout se mord la queue et interfère et va finir par me rendre fou...

    Alors, jouer avec les événements, un timer (ce matin moi tout seul avec les threads -- oui, en maquette ça fonctionne) ou que sais-je ne va que rajouter de la complexité au brouillard indébogable, vous avez vu la copie d'écran.

    J'abandonne...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  19. #19
    Membre chevronné

    Homme Profil pro
    au repos
    Inscrit en
    Février 2014
    Messages
    429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : au repos

    Informations forums :
    Inscription : Février 2014
    Messages : 429
    Points : 1 884
    Points
    1 884
    Par défaut
    Salut Jipété.

    J'abandonne...
    ça, je n'aime pas voir !

    A force de poster des codes différents, je ne m'y retrouve plus !
    Pour simplifier : dans une partie normale, l'humain joue, tu connais donc la valeur à assigner à sinput. Pourquoi, bon sang, as-tu besoin d'une procedure qui boucle tous les 10ms pour voir si cette valeur est <> '' ? Alors qu'il suffit de passer au moteur la variable et de lui dire ce qu'il doit faire : réfléchir sur la réponse à trouver ou jouer un coup imposé (cas d'une séquence au-départ d'un stringlist).

    Dans ton code ci-dessus, tu as 2 fonctions Sleep qui s'entrecroisent dans le même thread, donc il devient très difficile de savoir ce qu'en fait l'OS. Je parie sur ceci :
    La procedure qui boucle avec sleep(10) rend à un moment la main (app.pm) à une procedure qui initialises sinput, puis fait un sleep(100): résultat, la boucle n'est plus exécutée pendant 100 ms, et quand elle reçoit à nouveau la main, sinput entre-temps a été réinitialisé à "" !

    Cordialement
    Thierry

    PS: si tu ne veux plus te préoccuper de cette discussion,dis-le clairement.

  20. #20
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Salut Thierry,

    Citation Envoyé par ThWilliam Voir le message
    Citation Envoyé par Jipété
    J'abandonne...
    ça, je n'aime pas voir !
    Hé bien tu vas être satisfait et tu vas rire, j'en enfin solutionné ce sac de nœuds (et c'était vraiment le cas).

    Je m'en suis sorti en passant par un... thread, et oui ! Un thead qui simule l'humain (boucle sur la liste des coups à jouer avec attente de la réponse du moteur).
    Écrit comme ça, ça a l'air tout simple, je ne vous raconte pas les circonvolutions à coups de booléens bien placés et de surveillance du changement d'état de variables...
    Une usine à gaz mâtinée de plat de spaghettis, mais bon, ça fonctionne et j'ai pu rejouer une partie en regardant les pièces bouger toutes seules sur le plateau.
    Ça fait bien plaisir


    Techniquement, le problème était qu'une procédure ne rend pas la main tant qu'elle n'a pas terminé, et qu'à force d'écrire des choses genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    intA := 1;
    boolB := True;
    sString := 'texte';
    on a tendance à penser que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    StartWaitLoopFromMoteur(True);
    StartWaitLoopVersMoteur(True);
    vont se comporter de la même manière, mais non : tant que la première n'a pas terminé, la seconde n'est pas lancée.
    Et pareil pour les événements OnChange des T(Labeled)Edit, qui fonctionnent très bien, au final, et que j'ai incriminés à tort : c'était moi qui ne savait pas les utiliser.

    D'où le thread et sa manière si particulière de dialoguer avec les objets de l'ihm, à coups de Synchronize.

    Mais bon, je peux enfin cliquer sur

    Citation Envoyé par ThWilliam Voir le message
    Pour simplifier : dans une partie normale, l'humain joue, tu connais donc la valeur à assigner à sinput. Pourquoi, bon sang, as-tu besoin d'une procedure qui boucle tous les 10ms pour voir si cette valeur est <> '' ?
    Parce que le moteur fonctionne en mode texte et qu'il attend donc le coup humain avec une instruction readln ; mais l'humain peut mettre du temps à répondre (téléphone, pipi, café, etc.), readln s'en fiche, ça tourne en boucle...
    Pour remplacer ça je n'ai rien trouvé de mieux que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        log(' A vous de jouer...  '); // origine
        // readln(coupsaisi); // origine
        repeat sleep(10); Application.ProcessMessages; until sinput <> '';
        log('Entrée = ' + sinput);
        coupsaisi := sinput; sinput := '';
    Ce qui était dément, c'était de mettre la souris en pas-à-pas sur le 2e sinput et de voir que c'était vide alors que sinput ne l'était pas puisque c'était rempli... dans une procédure OnChange... Les procs qui se mordaient la queue, ne rendaient pas la main, toussa toussa...

    Citation Envoyé par ThWilliam Voir le message
    Alors qu'il suffit de passer au moteur la variable et de lui dire ce qu'il doit faire : réfléchir sur la réponse à trouver ou jouer un coup imposé (cas d'une séquence au départ d'un stringlist).
    Tu vois, toi aussi tu te fais des nœuds dans la tête, à force : pour rejouer une partie, ce qui m'intéressait c'était de m'éviter de cliquer en suivant les coups dans une liste et regarder le moteur répondre. Et comme il partait d'une bibliothèque, fatalement ses coups seraient les mêmes que la première fois.
    Quel intérêt ? Pouvoir surveiller des variables, genre sur une partie de 10 coups, modifier tel coup au 8e coup par exemple et voir comment ça se comporte, bref, pouvoir avoir un comportement prévisible.

    Bon, allez, tournons la page, je vais faire une petite partie ça me détendra, , et ensuite je bascule sur mon autre projet, que j'ai un peu négligé ces derniers temps
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Exécuter une application externe pas à pas
    Par leyo666 dans le forum Langages de programmation
    Réponses: 5
    Dernier message: 07/04/2007, 18h41
  2. [Application MDI] Pas de barre de menus
    Par grid93 dans le forum Delphi
    Réponses: 3
    Dernier message: 25/02/2007, 10h20
  3. Application.ProcessMessages dans une table
    Par sondo dans le forum Bases de données
    Réponses: 11
    Dernier message: 04/02/2007, 14h16
  4. Blocage même avec Application.ProcessMessages
    Par Sub0 dans le forum Delphi
    Réponses: 7
    Dernier message: 31/01/2007, 05h13
  5. problème avec Application->ProcessMessages()
    Par petitours dans le forum C++Builder
    Réponses: 4
    Dernier message: 15/08/2005, 10h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo