Partage
  • Partager sur Facebook
  • Partager sur Twitter

Jeu d'aventure textuel

pas à pas

    19 juin 2011 à 22:48:24

    Par contre, pour la carte, moi perso je préfère les tableaux à deux dimensions, mais c'est une question de goût ;)
    • Partager sur Facebook
    • Partager sur Twitter
      19 juin 2011 à 22:49:42

      Citation : jolfo

      Par contre, pour la carte, moi perso je préfère les tableaux à deux dimensions, mais c'est une question de goût ;)



      Là, par contre il ya une raison pour employer des tableaux 1d.
      Ca va se voir dès qu'on va utiliser des objets. ;)
      • Partager sur Facebook
      • Partager sur Twitter
      Zeste de Savoir, le site qui en a dans le citron !
        19 juin 2011 à 22:58:19

        Citation : GurneyH

        Citation : jolfo

        Par contre, pour la carte, moi perso je préfère les tableaux à deux dimensions, mais c'est une question de goût ;)



        Là, par contre il ya une raison pour employer des tableaux 1d.
        Ca va se voir dès qu'on va utiliser des objets. ;)



        J'ai hate ;)
        • Partager sur Facebook
        • Partager sur Twitter
          21 juin 2011 à 5:49:38

          Encore des déplacements!



          La dernière fois, on a vu:
          - comment représenter un case de notre carte
          - comment tester si une direction est valide
          - comment se déplacer sur la carte

          Mine de rien, on a utilisé des opérateurs du langage C qui ne vous sont pas forcément très familiers : Les opérateurs bits à bits.

          Je vais préciser un peu ce qu'on a fait.

          Vous vous souvenez que le hall d'entrée de ma carte d'exemple(case 5), a pour valeur NSEO 12, car
          -un passage à l'ouest(valeur 4)
          -un passage à l'est(valeur 8)

          pour tester les déplacements possibles à partir de cette case on a utilisé l'opérateur &(AND) de la sorte:
          if(a_NSEO[case] & dir != 0)
          Je vais essayé d'expliquer plus en détail le déroulement de ce test.

          La première chose à connaitre c'est la table de vérité de l'opérateur binaire AND:
          A B A AND B
          0 0 0
          0 1 0
          1 0 0
          1 1 1



          12 en binaire s'écrit
          1100

          Testons pour chaque direction.
          Le nord
          12 and 1
          
                     1100
          AND        0001
                     0000
          0 -> Pas de passage au nord
          
          Le sud
          12 and 2
                     1100
          AND        0010
                     0000
          0 -> Pas de passage au sud
          
          l'est
          12 and 4
                     1100
          AND        0100
                     0100
          4 -> un  passage à l'est
          
          l'ouest
          12 and 4
                     1100
          AND        1000
                     1000
          8 -> un  passage à l'ouest

          Ouf! Ca fonctionne.
          Si le test est égal à 0, il n'y a pas de passage.

          Pour être à l'aise je vous conseille de tester différentes valeur NSEO et de tester les différentes directions.

          Ouvrir les portes...



          Dans un jeu d'aventure, il est fréquent qu'on puisse ouvrir un porte fermée jusque là.

          Cela implique une modification de la valeur NSEO de la case.
          Pour arriver à nos fins, on va utiliser un autre opérateur binaire le OR(opérateur | en C)

          Table de vérité OR
          A B A OR B
          0 0 0
          1 0 1
          0 1 1
          1 1 1


          On fera
          NSEO[case] = NSEO[case] | 1 pour ouvrir le nord
          NSEO[case] = NSEO[case] | 2 pour ouvrir le sud
          NSEO[case] = NSEO[case] | 4 pour ouvrir l'est
          NSEO[case] = NSEO[case] | 8 pour ouvrir l'ouest

          Pour s'en convaincre, prenons un case avec seulement un passage au nord(1) et un passage à l'est(4).
          la valeur NSEO de la case est 5.

          On veut ouvrir un passage à l'ouest(8).
          5 en binaire -> 0101
          8 en binaire -> 1000
             
                 0101
          OR     1000
                 1101 = 13


          La nouvelle valeur NSEO de la case est 13.
          L'ouest est ouvert!

          Et les fermer.


          On peut ouvrir des passages, mais on peut aussi les fermer.
          Le passage que je viens d'emprunter s'est écroulé derrière moi... :-°

          edit du 22/06/11 suite à la remarque de QuentinC 2 plus bas.
          C'est cette fois ci l'opérateur NOT(opérateur ~ en C), qui va nous être utile.
          Cet opérateur inverse l'état d'un bit
          A NOT A
          0 1
          1 0

          Ainsi par exemple, une case possédant un passage vers chaque direction(1 + 2 + 4 + 8 = 15 -> 1111 en binaire).
          Si on veut fermer le passage à l'ouest(8 -> 1000 en binaire)
          Pour mieux voir le fonctionnement du NOT, je vais représenter la valeur binaire avec les zéros non significatifs à gauche.
          15 -> 00001111
          8 ->  00001000 en binaire.
          
          On applique le NOT sur la direction
          NOT 8 ->
          NOT 00001000, on obtient le masque:
              11110111 soit 247 en décimal.
          Reste à applique le masque à la valeur NSEO de notre case.
                15 -> 00001111    
          AND  247 -> 11110111
                      00000111
          soit 7 en décimal.

          On a bien fermé le passage à l'ouest en conservant le passage dans toutes les autres directions.

          Si on récapitule:
          Pour fermer un passage
          NSEO[case] = NSEO[case] AND (NOT dir)

          Plus subtil.


          On aurait également pu utiliser l'opérateur XOR(OU exclusif, opérateur ^ en C), et c'est ce que je faisais avant le remarque de QuentinC 2.

          Table de vérité XOR
          A B A XOR B
          0 0 0
          1 0 1
          0 1 1
          1 1 0



          On fera
          NSEO[case] = NSEO[case] ^ 1 pour fermer le nord
          NSEO[case] = NSEO[case] ^ 2 pour fermer le sud
          NSEO[case] = NSEO[case] ^ 4 pour fermer l'est
          NSEO[case] = NSEO[case] ^ 8 pour fermer l'ouest

          Encore un exemple, toujours avec notre case possédant un passage au nord(1) et un passage à l'est(4).
          La case à toujours une valeur NSEO de 5 et une représentation binaire de 0101
          On veut fermer le passage à l'est(4 -> 0100 en binaire)
          .
                   0101
          XOR      0100
                   0001


          Résultat 1. On a bien fermé le passage à l'est.

          Un problème se pose


          Si on demande à fermer un passage qui déjà fermé:
          Toujours notre case avec la valeur NSEO de 5(nord et est ouvert).
          Si j'essaye de fermer le passage à l'ouest(8), en faisant:
          NSEO[case] = 5 ^ 8
          j'obtiens l'effet inverse, et une valeur de 13 -> j'ai ouvert le passage à l'ouest!
          Je vous laisse vous en convaincre en posant l'opération binaire.

          On peut imaginer des mécanismes de va et vient subtils avec cette propriété:
          Je rentre dans une pièce par l'est, la porte se ferme derrière moi!
          Je sors de cette pièce par le nord, et je fais demi-tour, pour me rendre compte que le passage à l'est est de nouveau accessible...
          On conservera l'utilisation de l'opérateur XOR, uniquement pour ces cas particuliers.
          Je pense qu'on à fait le tour des déplacements cette fois ci.

          La prochaine fois, on s'attaque à la gestion des objets.
          • Partager sur Facebook
          • Partager sur Twitter
          Zeste de Savoir, le site qui en a dans le citron !
            21 juin 2011 à 8:34:00

            Bonjour,
            Topic intéressant. Ca fait plaisir de voir que le genre aventure textuelle n'est pas mort, j'aime bien ce genre de jeu pour se changer les idées sans pour autant s'exciter sur son clavier.
            JE vote console pour sa simplicité, son universalité et son accessibilité, et parce qu'un jeu d'aventure en SDL n'est plus un jeu textuel (on sera rapidement tenté d'ajouter des graphismes, donc on ne peut plus appeler ça jeu textuel, alors soit c'est hors sujet soit il faut changer le titre)

            Quelques remarques jusqu'ici :
            1° - En ce qui concerne la partie juste ci-dessus, je pense que présenter l'opérateur XOR pour fermer des passages est une mauvaise idée, justement parce que tenter de fermer un passage déjà fermé le rouvre. Beaucoup vont poser la question et vont avoir peut-être des bugs inexpliqués de passages qui sont ouverts alors qu'ils devraient être fermés, même si tu l'as bien précisé. En plus, ça incite à coder ça pour être certain de fermer un passage à coup sûr :
            if (nseo[case]&direction) nseo[case]^=direction;
            Ce qui n'est en soi pas faux, mais on peut élégamment se passer du if avec :
            nseo[case]&=~direction;
            Perso ça me paraît beaucoup plus logique et juste. L'opérateur XOR fait des choses plus subtiles, donc est à présenter plus tard.

            2° - Ce serait bien qu'à terme, ce topic se mue en tutoriel. Histoire qu'il soit réellement visible... quand les discussions seront terminées bien entendu.

            3° - Je suis peut-être un type tordu, mais il pourrait être intéressant dans un second temps de présenter une autre représentation possible du monde non plus sous forme de grille mais sous forme de graphe abstrait. C'est plus compliqué donc pas à aborder tout de suite, mais ça peut permettre des choses vraiment sympathiques (l'introduction efficace de la verticalité, des salles à l'intérieur d'autres salles, des passages ou cachettes secrètes, des raccourcis, voire des portes et couloirs pivotants)
            • Partager sur Facebook
            • Partager sur Twitter
              21 juin 2011 à 13:18:39

              Bonjour

              Citation : QuentinC 2


              et parce qu'un jeu d'aventure en SDL n'est plus un jeu textuel (on sera rapidement tenté d'ajouter des graphismes, donc on ne peut plus appeler ça jeu textuel, alors soit c'est hors sujet soit il faut changer le titre)



              Je pense que même si on se contente d'afficher une image de description de la scène courante, et qu'on effectue la saisie de texte en SDL, ça reste un jeu d'aventure textuel.

              Dans tous les cas je vais essayer de rester loin de l'affichage un bon moment.
              On verra en temps voulu.

              1/
              Tu as raison, utiliser l'opérateur NOT est plus logique.
              J'éditerai le post précédent dans ce sens, et on ne conservera le XOR que pour les subtilités.

              2/
              Pourquoi pas.

              3/
              Encore une fois pourquoi pas. ;)
              Même si, je pense que tous les exemples que tu proposes, sont réalisables avec une carte stockée sous forme de grille.
              Mais oui, il sera intéressant de présenter une autre structure de donnée.

              Merci pour les remarques.
              Comme je l'ai déjà dit, j'édite rapidement le post précédent.
              • Partager sur Facebook
              • Partager sur Twitter
              Zeste de Savoir, le site qui en a dans le citron !
                22 juin 2011 à 22:28:17

                Ton topic est vraiment très intéressant. C'est la première fois que je vois une résolution de problème avec les opérateurs "Bits a bits" . J 'ai bien compris le fonctionnement de et ou xor , tes explications sont claires pourtant je sais pas si je saurais les utiliser pour résoudre un autre problème.....
                J aime bien ta façon de poser les choses sans balancer abruptement des lignes et des lignes de code c'est plus facile a comprendre pour mes petits neurones.
                En attendant la suite..
                @+
                • Partager sur Facebook
                • Partager sur Twitter
                  23 juin 2011 à 5:28:49

                  Pour commencer, et pour rendre à César ce qui est à césar, je précise que toute la partie précédente est fortement inspirée d'une série d'articles rédigés par Alain Massoumipour(Poum), et publiés dans le magazine Amstrad Cent Pour Cent à la fin des années 80.
                  Les codes proposés étaient destinés au BASIC de la machine(Locomotive BASIC), qui ne possédait entre autre pas de fonctions.

                  Gestion des objets.



                  Dans un jeu d'aventure, l'interaction avec les objets peut prendre plusieurs formes.
                  On peut:
                  • prendre un objet.
                  • abandonner un objet.
                  • échanger un objet
                  • transformer certains objets

                  Quelles sont les infos nécessaires à ces actions?
                  On a besoin de savoir :
                  • Quel est le type de l'objet
                  • Dans quelle case se trouve l'objet.
                  • Si l'objet est accessible
                  • Si l'objet est en notre possession

                  J'ai choisi d'utiliser une structure pour représenter ces informations(d'autres choix sont bien sûr possibles, comme par exemple représenter toutes ces infos avec 1 seul entier.)

                  struct sObjet
                  {
                      int id;         /* Type de l'objet */ 
                      int salle;      /* Lieu de présence de l'objet */
                      int accessible; /* 0 pas accessible, 1 accessible */
                      int possession; /* 0 pas dans l'inventaire 1 dans l'inventaire */
                  };
                  


                  Pour représenter l'ensemble des objets du jeu, on va simplement utiliser un tableau de structure sObjet.

                  struct sObjet a_objets[MAX_OBJETS];
                  avec MAX_OBJETS, le nombre total d'objets présents dans le jeu.

                  Ainsi, il est très simple d'effectuer des actions comme

                  Lister les objets visibles dans une case.


                  On itère sur le tableau d'objets, et on affiche tous les objets dont le membre case est égal à la case courante.

                  Faire l'inventaire


                  On itère sur le tableau d'objets, et on affiche les objets dont le membre possession est à 1.

                  Trop facile. :-°

                  Un exemple


                  L'objet 1 dans notre jeu, est un sifflet qui a pour id 3, il se trouve dans la case 5, et est accessible.
                  Le joueur se trouvant en case 5, peut voir cet objet

                  a_objets[1].id = 3
                  a_objets[1].salle = 5
                  a_objets[1].accessible = 1
                  a_objets[1].possession = 0

                  Le joueur prend l'objet:
                  a_objets[1].possession = 1


                  Après plusieurs détours, le joueur se retrouve dans la salle 3 et décide de se séparer de l'objet:
                  a_objets[1].salle = 3
                  a_objets[1].possession = 0

                  Encore un exemple.


                  Le joueur se trouve en case 8, il voit un coffre. Au grand dam du joueur ce coffre est fermé à clef.
                  Malgré tout ce coffre contient un objet(l'objet 2), c'est une dague(id = 3), mais l'objet est:
                  • invisible pour l'instant(le joueur ne connaît pas le contenu du coffre).
                  • inaccessible puisque le joueur ne peut pas ouvrir le coffre.


                  l'objet 2 est défini ainsi
                  a_objet[2].id = 3
                  a_objet[2].salle = -1
                  a_objet[2].accessible = 0
                  a_objet[2].possession = 0


                  Le membre case est placé à une valeur négative(toute valeur ne pouvant représenter l'index d'une case de notre carte est valable) -> l'objet est invisible.

                  Le joueur continue son chemin et trouve une clé de coffre.
                  Illico, il retourne en salle 8, ouvre le coffre et peut enfin voir le contenu de ce dernier.
                  a_objets[2].salle = 8
                  a_objets[2].accessible = 1
                  a_objets[2].possession = 0


                  Le joueur peut voir l'objet, et donc le prendre.

                  C'est tout pour les objets.
                  Bien sur au moment de l'implémentation, on utilisera des enum, en lieu et places des valeurs telles que -1 pour signifier l'invisibilité temporaire d'un objet.

                  La prochaine fois, on attaque l'analyseur syntaxique(simple).

                  edit:
                  changement du membre case. :-°

                  edit du 26/06/11:
                  Ajout d'un membre id dans la structure objet.
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Zeste de Savoir, le site qui en a dans le citron !
                    23 juin 2011 à 10:20:14

                    Quelque chose à ajouter: pour les allergiques aux opérateurs bit à bit, on peut toujours s'en sortir avec une structure :
                    struct directions {
                    unsigned char nor :1;
                    unsigned char sude :1;
                    unsigned char est :1;
                    unsigned char ouest :1;
                    };
                    

                    Les opérateurs bit à bit sont bien plus intéressants à utiliser, mais si ça peut aider pour ceux qui ne comprennent pas ou qui ne veulent pas utiliser...
                    • Partager sur Facebook
                    • Partager sur Twitter
                      23 juin 2011 à 10:37:05

                      J'aurais juste une question concernant les objets: et si un même objet peut être ramassé sur plusieurs cases différentes, on procède comment? Bon, on pourrait utiliser l'opérateur | pour stocker les numéros correspondant aux différentes cases sur lesquelles l'objet peut être ramassés, mais dans ce cas, cela pose problème pour les attributs qui eux sont partagés (visible, accessible, en possesion, ...).

                      Citation : QuentinC 2


                      Quelque chose à ajouter: pour les allergiques aux opérateurs bit à bit, on peut toujours s'en sortir avec une structure :

                      struct directions {
                      unsigned char nor :1;
                      unsigned char sude :1;
                      unsigned char est :1;
                      unsigned char ouest :1;
                      };
                      




                      Les membres de structures de type champ de bits doivent être de type int, unsigned int ou _Bool. Les autres types supportés dépendent des implémentations ;)

                      Citation : Norme C99 6.7.2.1 § 4 p 101


                      A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed
                      int, unsigned int, or some other implementation-defined type.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        23 juin 2011 à 11:27:54

                        Citation : Taurre


                        et si un même objet peut être ramassé sur plusieurs cases différentes, on procède comment?


                        Un exemple, pour illustrer le problème auquel tu penses?
                        Parce que là, j'avoue, que j'ai du mal à voir comment un même objet peux être simultanément à 2 endroits.

                        Si tu parles de 2 objets similaires, style une clé et une autre clé, il s'agit de 2 objets différents mais avec la même description.
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Zeste de Savoir, le site qui en a dans le citron !
                          23 juin 2011 à 12:02:05

                          Un exemple assez parlant, c'est l'argent. Il arrive très souvent de trouver x pièces d'or dans une pièce. Cependant, on en trouve dans plusieurs pièces, au fur et à mesure de l'aventure.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            23 juin 2011 à 12:12:18

                            Citation : Taurre


                            Un exemple assez parlant, c'est l'argent. Il arrive très souvent de trouver x pièces d'or dans une pièce. Cependant, on en trouve dans plusieurs pièces, au fur et à mesure de l'aventure.


                            En effet, Le système présenté n'est pas adapté.

                            Dans la majorité des jeux d'aventure, la notion de bourse n'existe pas.
                            On va plutôt avoir un objet nommé "100 pièces d'or", qui sera échangé contre un autre objet.

                            • Partager sur Facebook
                            • Partager sur Twitter
                            Zeste de Savoir, le site qui en a dans le citron !
                              23 juin 2011 à 12:57:06

                              Citation : GurneyH


                              En effet, Le système présenté n'est pas adapté.



                              A bien y réfléchir, peut-être pas :)
                              On pourrait appliquer l'opérateur | aux champs accessible et possession. Ainsi, on obtient un code de ce type (entre parenthèse, il faudrait trouver un autre nom pour le champ case, puisque ce mot est réservé par le langage :-° ):

                              if (a_objets[case_courante].case & case_courante) {
                                 /* 
                                  * l'objet se situe sur la case 
                                  */
                                 if (a_objets[case_courante].accessible & case_courante) {
                                    /*
                                     * l'objet est accessible
                                     */
                                 }
                              }
                              


                              Le seul bémol c'est qu'on ne peut pas gérer la quantité de chaque objet avec cette méthode (enfin, je ne vois pas comment pour l'instant). Mais on peut en effet s'en sortir en créant des objets du type "50 pièces d'or". M'enfin dans ce cas, comment fait-on pour acheter une dague à 5 pièces d'or si l'on ne dispose que d'un objet "50 pièces d'or"? On utilise un système d'échange? Le joueur obtient une dague et un objet de "45 pièce d'or", mais perd son objet "50 pièces d'or"?
                              • Partager sur Facebook
                              • Partager sur Twitter
                                23 juin 2011 à 15:37:20

                                Citation : Taurre


                                Le joueur obtient une dague et un objet de "45 pièce d'or", mais perd son objet "50 pièces d'or"


                                C'est truqué. :D
                                On arrange les échanges, pour que ça corresponde aux objets présents dans le jeu.
                                Genre, on veut bien t'échanger la dague contre tes 50 pièces d'or(on oublie les promotions).
                                Après le système présenté est une base.
                                Libre à chacun d'en faire ce qu'il veut. :)

                                Heu oui, case on va trouver autre chose au moment de l'implémentation.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                Zeste de Savoir, le site qui en a dans le citron !
                                  23 juin 2011 à 15:52:04

                                  Salut, :)

                                  Juste comme ça, ça vous choque pas d'avoir une variable appelée case ?

                                  Citation : GurneyH

                                  struct sObjet
                                  {
                                      int case;       /* Lieu de présence de l'objet */
                                      int accessible; /* 0 pas accessible, 1 accessible */
                                      int possession; /* 0 pas dans l'inventaire 1 dans l'inventaire */
                                  };
                                  


                                  Voila, c'était ma remarque pour suivre ^^

                                  Edit : Désolé j'avais pas vu que Taurre avait souligné ! :euh:

                                  Sinon ça à l'air interessant ! Bonne continuation, je suivrai ! ;)
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Bla bla bla
                                    23 juin 2011 à 16:53:49

                                    Citation

                                    Les membres de structures de type champ de bits doivent être de type int, unsigned int ou _Bool. Les autres types supportés dépendent des implémentations


                                    osef, c'est pas grave, ça ne change rien à l'esprit de l'idée. Ca marche chez moi avec des unsigned char donc ça ne me serait même jamais venu à l'idée que ça puisse être interdit par la norme.

                                    Quelque chose me choque en ce qui concern les objets :
                                    struct sObjet 
                                    { 
                                        int salle;       /* Lieu de présence de l'objet */ 
                                        int accessible; /* 0 pas accessible, 1 accessible */ 
                                        int possession; /* 0 pas dans l'inventaire 1 dans l'inventaire */ 
                                    }; 
                                    

                                    Dans cette structure, tu indiques où se trouve un certain objet, mais tu ne donnes aucun moyen d'indiquer sa nature directement.
                                    * Soit tu décides que objets[18] est une clé pour ouvrir une porte dans la salle 4 et que objets[44] est une potion, mais le gros problème de cette solution c'est que ça devient rapidement le bordel si tu as plusieurs objets qui font la même chose. P.ex. est-ce que je possède une potion ? ne peut se traduire que par quelque chose de tordu comme si je possède l'objet 44 ou l'objet 32 ou l'objet 72 ou l'objet X ou l'objet Y ou l'objet Z ...... bref, vraiment pas pratique.
                                    * Soit tu ajoutes un champ dans la structure, un int suffit, pour déterminer la nature de l'objet. ET là d'un coup c'est beaucoup plus facile. Tu sais que le type 1 est une clé et le type 2 une potion, tu ne fais pas de test compliqué pour savoir si tu en possèdes une. ET en bonus, ça t'autorise à représenter les objets que tu possèdes dans ton inventaire différemment: quid d'une mini hashmap séparée, voire même un simple tableau de int pour faire simple s'il n'y a pas trop de sortes 'dobjets, avec comme clé le type d'objet et en valeur le nombre que tu en possèdes ? ça règlerait le problème de l'argent évoqué plus haut du même coup.
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      23 juin 2011 à 17:05:13

                                      Le problème je crois, c'est qu'il faut se fixer une limite.

                                      Le truc, des potions, de l'argent:
                                      Je trouve que c'est vraiment à la limite du jeu d'aventure.
                                      On est plus loin du jeu de rôle.(avec gestion de PV, par exemple).

                                      On a rarement 2 objets "faisant la exactement" la même chose dans un jeu d'aventure.

                                      Mais ok, on peut ajouter un membre à la structure(ce n'est pas plus cher).


                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      Zeste de Savoir, le site qui en a dans le citron !
                                        23 juin 2011 à 20:19:20

                                        Citation : QuentinC2


                                        osef, c'est pas grave, ça ne change rien à l'esprit de l'idée. Ca marche chez moi avec des unsigned char donc ça ne me serait même jamais venu à l'idée que ça puisse être interdit par la norme.



                                        Ce n'est pas interdit par la Norme, elle précise juste qu'une implémentation donnée ne doit supporté que les types int, unsigned int et _Bool pour un champ de bits afin d'y être conforme. Maintenant, cela ne change en effet rien à ton idée, mais il est je pense intéressant de souligner ce point sachant que tout le monde ne compile pas avec GCC ;)

                                        Citation : GurneyH


                                        C'est truqué. :D



                                        Ok, je vois :p
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          23 juin 2011 à 21:28:52

                                          Citation

                                          Le problème je crois, c'est qu'il faut se fixer une limite.

                                          Le truc, des potions, de l'argent:
                                          Je trouve que c'est vraiment à la limite du jeu d'aventure.
                                          On est plus loin du jeu de rôle.(avec gestion de PV, par exemple).


                                          Si tu avais dans l'idée de faire un jeu d'exploration pur genre fiction interactive pas trop compliqué, l'argent et les potions nous font effectivement plus dévier en direction du RPG.

                                          Cela dit, je suis sûr que beaucoup de monde ici pense en premier à un RPG style porte-monstre-trésor quand tu parles de jeu d'aventure. Du coup, les questions sur l'argent, les potions, les PV et les monstres , tu risques de les avoir quand même tôt ou tard.
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            26 juin 2011 à 18:04:56

                                            On sait maintenant se situer sur une carte, et gérer les objets de notre jeu.

                                            On continue avec

                                            l'analyse des saisies utilisateur



                                            Notre analyseur, ne va reconnaître qu'une grammaire minimale:
                                            -action
                                            -action objet
                                            où, action et objet sont des mots.

                                            Un mot pour nous, sera simplement un succession exclusive de lettres.

                                            Pour chaque action réalisable on va avoir une valeur unique.
                                            ACT_PRENDRE,
                                            ACT_FOUILLER,
                                                ...
                                            

                                            idem pour les objets
                                            OBJ_AMPOULE,
                                            OBJ_TABLE,
                                            OBJ_CHAISE,
                                                ...
                                            


                                            De même à chaque action va correspondre une série de synonyme.
                                            Ainsi, si on tape:
                                            Prendre, prend, vole, voler, derobe, derober
                                            on veut ce soit l'action ACT_PRENDRE qui soit reconnue
                                            Pour ça, on va utiliser une liste de synonyme.

                                            Chaque série de synonymes sera conclue par "*".
                                            La fin de notre liste sera conclue par "**"
                                            "PREN","VOL", "DEROB", "*",
                                             "FOUILL", "CHERCH", "*",
                                             ...,
                                            "**"
                                            

                                            La même technique sera utilisée pour les objets.

                                            Pour trouver un mot dans la liste de synonymes

                                            index = 0    
                                            On parcourt la liste : motActuel
                                                si motActuel ==  "*"
                                                    incrémenter index
                                                si motActuel == "**"
                                                    retourner -1(le mot n'est pas dans la liste)
                                                sinon
                                                    si mot == liste[motActuel]
                                                        retourner index

                                            int trouverMot(char const *syno[], char *mot)
                                            {
                                                int ret = 0;
                                                int i;
                                            
                                                for(i = 0 ;; i++)
                                                {
                                                    /* On parcourt la liste de synonymes */
                                                    if(syno[i][0] == '*')
                                                    {
                                                        /* On a atteint la fin d'une série de synonymes */
                                                        if(syno[i][1] == '*')
                                                        {
                                                            /* On a atteint la fin de la liste , le mot n'est inconnu */
                                                            return -1;
                                                        }
                                                        /* On passe à la prochaine série de synonymes */
                                                        ret++;
                                                    }
                                                    else
                                                    {
                                                        /* On teste si le mot correspond à la "racine" du zynonyme actuel */
                                                        if(strncmp(mot, syno[i], strlen(syno[i])) == 0)
                                                        {
                                                            /* On a trouvé le mot, on retourne son ID */
                                                            return ret;
                                                        }
                                                    }
                                                }
                                            }
                                            



                                            Pour lire un mot
                                            On se place au début du prochain mot
                                            Lecture du caractère courant    
                                            Tant que le caractère courant est une lettre
                                                on ajoute la lettre en majuscule à notre mot
                                                lecture du caractère courant
                                            On replace le dernier caractère lu

                                            void lireMot(char *mot, int taille)
                                            {
                                                int len = 0;
                                                int c;
                                            
                                                /* On se place au début du prochain mot */
                                                prochainMot();
                                            
                                                /* Tant qu'on lit une lettre, on est en présence d'un mot */
                                                c = getchar();
                                                while(len < taille - 1 && isalpha(c))
                                                {
                                                    /* On place la lettre en majuscule à l'emplacement courant du mot */
                                                    /* et on passe à l'emplacement suivant */
                                                    mot[len++] = toupper(c);
                                                    c = getchar();
                                                }
                                                /* On forme une chaîne valide */
                                                mot[len] = '\0';
                                            
                                                /* On replace le dernier caractère lu dans le flux */
                                                ungetc(c, stdin);
                                            }
                                            


                                            Pour lire une phrase
                                            Lecture du caractère courant
                                            Tant qu'on est pas à la fin de la phrase
                                                lire un mot
                                                si le mot est une action
                                                    si on avait pas encore d'action
                                                        actionLue = mot converti en action
                                                    sinon
                                                        retourner erreur
                                                sinon si le mot est un objet
                                                    si on avait pas encore d'objet
                                                        objetLu = motConverti en objet
                                                    sinon
                                                        retourner erreur
                                                Lecture du caractère courant

                                            int lirePhrase(int *pIdAct, int *pIdObj)
                                            {
                                                char mot[BUF_SIZE];
                                                int err = 0;
                                                int c = getchar();
                                            
                                                *pIdAct = -1;
                                                *pIdObj = -1;
                                            
                                                while(c != '\n' && !err)
                                                {
                                                    int id;
                                                    ungetc(c, stdin);
                                            
                                                    lireMot(mot, BUF_SIZE);
                                                    /* On regarde le mot est dans la liste des actions */
                                                    id = trouverMot(a_actionsSyno, mot);
                                                    if(id >= 0)
                                                    {
                                                        /* On a lu une action */
                                                        if(*pIdAct < 0)
                                                        {
                                                            /* C'est la première action rencontrée dans la phrase */
                                                            *pIdAct = id;
                                                        }
                                                        else
                                                        {
                                                            /* On a déjà rencontré une action aupravant, erreur ! */
                                                            return -1;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        /* Le mot n'est pas une action */
                                                        /* On Regarde si le mot est un objet */
                                                        id = trouverMot(a_objetsSyno, mot);
                                                        if(id >= 0)
                                                        {
                                                            /* On a lu un objet */
                                                            if(*pIdObj < 0)
                                                            {
                                                                /* C'est le premier objet rencontré dans la phrase */
                                                                *pIdObj = id;
                                                            }
                                                            else
                                                            {
                                                                /* On a déjà rencontré un objet auparavant, erreur ! */
                                                                return -1;
                                                            }
                                                        }
                                                    }
                                                    /* On lit le caractère suivant */
                                                    c = getchar();
                                                }
                                                /* action inconnue, objet inconnu */
                                                if(*pIdAct < 0 && *pIdObj < 0)
                                                    err = -1;
                                            
                                                return err;
                                            }
                                            

                                            je sais, je pourrais encore factoriser. :-°


                                            Pour lancer l'analyse on fera simplement
                                            int err = lirePhrase(&idAction, &idObjet);
                                            

                                            et idAction et idObjets seront renseignés, si tout est ok.

                                            Un petit programme de test.
                                            #include <stdio.h>
                                            #include <ctype.h>
                                            #include <string.h>
                                            
                                            #define BUF_SIZE    32
                                            
                                            typedef enum
                                            {
                                                ACT_PRENDRE,
                                                ACT_FOUILLER,
                                                ACT_EXAMINER,
                                                ACT_NORD,
                                                ACT_SUD,
                                                ACT_EST,
                                                ACT_OUEST,
                                                ACT_FIN
                                            } eAction;
                                            
                                            typedef enum
                                            {
                                                OBJ_AMPOULE,
                                                OBJ_TABLE,
                                                OBJ_CHAISE,
                                                OBJ_LIVRE,
                                                OBJ_CRAYON,
                                                OBJ_FENETRE,
                                                OBJ_PORTE,
                                                OBJ_CLE,
                                                OBJ_ORDI
                                            } eObjet;
                                            
                                            
                                            
                                            /* Descriptions */
                                            char const *a_actions[] =
                                            {
                                                "prenne",
                                                "fouille",
                                                "j'examine",
                                                "le nord",
                                                "le sud",
                                                "l'est",
                                                "l'ouest",
                                                "fin"
                                            };
                                            
                                            
                                            char const *a_actionsSyno[]=
                                            {
                                                "PREN","VOL", "DEROB", "*",
                                                "FOUILL", "CHERCH", "*",
                                                "EXAMIN", "REGARD", "OBSERV", "*",
                                                "NORD", "*",
                                                "SUD", "*",
                                                "EST", "*",
                                                "OUEST", "*",
                                                "FIN", "QUIT", "EXIT",
                                                "**"
                                            };
                                            
                                            
                                            /* Synonnymes */
                                            char const *a_objets[] =
                                            {
                                                "l'ampoule",
                                                "la table",
                                                "la chaise",
                                                "le livre",
                                                "le crayon",
                                                "la fenetre",
                                                "la porte",
                                                "la cle",
                                                "l'ordi"
                                            };
                                            
                                            
                                            
                                            
                                            char const *a_objetsSyno[] =
                                            {
                                                "AMPOULE", "LAMPE", "*",
                                                "TABLE", "BUREAU", "*",
                                                "CHAISE", "TABOURET", "SIEGE", "*",
                                                "LIVRE", "BOUQIN", "*",
                                                "CRAYON", "STYLO", "*",
                                                "FENETRE", "VITRE", "*",
                                                "PORTE", "*",
                                                "CLE", "*",
                                                "ORDI", "MICRO", "PC",
                                                "**"
                                            };
                                            
                                            
                                            void prochainMot(void)
                                            {
                                                int c;
                                                /* On lit les caractère tant qu'il ne s'agit pas d'une lettre */
                                                do
                                                {
                                                    c = getchar();
                                                }
                                                while(!isalpha(c) && c != '\n');
                                            
                                                /* On replace la dernière lettre lue dans le flux */
                                                ungetc(c, stdin);
                                            }
                                            
                                            
                                            int trouverMot(char const *syno[], char *mot)
                                            {
                                                int ret = 0;
                                                int i;
                                            
                                                for(i = 0 ;; i++)
                                                {
                                                    /* On parcourt la liste de synonymes */
                                                    if(syno[i][0] == '*')
                                                    {
                                                        /* On a atteint la fin d'une série de synonymes */
                                                        if(syno[i][1] == '*')
                                                        {
                                                            /* On a atteint la fin de la liste , le mot n'est inconnu */
                                                            return -1;
                                                        }
                                                        /* On passe à la prochaine série de synonymes */
                                                        ret++;
                                                    }
                                                    else
                                                    {
                                                        /* On teste si le mot correspond à la "racine" du zynonyme actuel */
                                                        if(strncmp(mot, syno[i], strlen(syno[i])) == 0)
                                                        {
                                                            /* On a trouvé le mot, on retourne son ID */
                                                            return ret;
                                                        }
                                                    }
                                                }
                                            }
                                            
                                            
                                            void lireMot(char *mot, int taille)
                                            {
                                                int len = 0;
                                                int c;
                                            
                                                /* On se place au début du prochain mot */
                                                prochainMot();
                                            
                                                /* Tant qu'on lit une lettre, on est en présence d'un mot */
                                                c = getchar();
                                                while(len < taille - 1 && isalpha(c))
                                                {
                                                    /* On place la lettre en majuscule à l'emplacement courant du mot */
                                                    /* et on passe à l'emplacement suivant */
                                                    mot[len++] = toupper(c);
                                                    c = getchar();
                                                }
                                                /* On forme une chaîne valide */
                                                mot[len] = '\0';
                                            
                                                /* On replace le dernier caractère lu dans le flux */
                                                ungetc(c, stdin);
                                            }
                                            
                                            
                                            
                                            /* Lit une ligne sur stdin, et renseigne les les pointeurs pIdAct et pIdObj
                                             * Si une action lue
                                             * *pIdAct = index de l'action, sinon -1
                                             * Si un objet lu
                                             * *pIdObj = index de l'objet, sinon -1
                                             * Valeur retournée:
                                             *  0 si succès
                                             * -1 si la phrase est invalide
                                             */
                                            int lirePhrase(int *pIdAct, int *pIdObj)
                                            {
                                                char mot[BUF_SIZE];
                                                int err = 0;
                                                int c = getchar();
                                            
                                                *pIdAct = -1;
                                                *pIdObj = -1;
                                            
                                                while(c != '\n' && !err)
                                                {
                                                    int id;
                                                    ungetc(c, stdin);
                                            
                                                    lireMot(mot, BUF_SIZE);
                                                    /* On regarde le mot est dans la liste des actions */
                                                    id = trouverMot(a_actionsSyno, mot);
                                                    if(id >= 0)
                                                    {
                                                        /* On a lu une action */
                                                        if(*pIdAct < 0)
                                                        {
                                                            /* C'est la première action rencontrée dans la phrase */
                                                            *pIdAct = id;
                                                        }
                                                        else
                                                        {
                                                            /* On a déjà rencontré une action aupravant, erreur ! */
                                                            return -1;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        /* Le mot n'est pas une action */
                                                        /* On Regarde si le mot est un objet */
                                                        id = trouverMot(a_objetsSyno, mot);
                                                        if(id >= 0)
                                                        {
                                                            /* On a lu un objet */
                                                            if(*pIdObj < 0)
                                                            {
                                                                /* C'est le premier objet rencontré dans la phrase */
                                                                *pIdObj = id;
                                                            }
                                                            else
                                                            {
                                                                /* On a déjà rencontré un objet auparavant, erreur ! */
                                                                return -1;
                                                            }
                                                        }
                                                    }
                                                    /* On lit le caractère suivant */
                                                    c = getchar();
                                                }
                                                /* action inconnue, objet inconnu */
                                                if(*pIdAct < 0 && *pIdObj < 0)
                                                    err = -1;
                                            
                                                return err;
                                            }
                                            
                                            
                                            
                                            int estDirection(eAction id)
                                            {
                                                return id >= ACT_NORD && id <= ACT_OUEST;
                                            }
                                            
                                            
                                            
                                            int main(void)
                                            {
                                                int idAction = -1;
                                                int idObjet = -1;
                                            
                                                while(idAction != ACT_FIN)
                                                {
                                                    int err = 0;
                                            
                                                    putchar('>');
                                                    err = lirePhrase(&idAction, &idObjet);
                                                    if(err)
                                                        puts("Rien compris ! Oo");
                                                    else
                                                    {
                                                        if(estDirection(idAction))
                                                            printf("Direction %s !\n", a_actions[idAction]);
                                                        else
                                                        {
                                                            if(idAction >= 0)
                                                            {
                                                                if(idObjet < 0)
                                                                    printf("Vous voulez que je %s quoi ?\n", a_actions[idAction]);
                                                                else
                                                                    puts("ok");
                                                            }
                                                            else
                                                                printf("Voulez que je fasse quoi de %s ?\n", a_objets[idObjet]);
                                                        }
                                                    }
                                                }
                                                return 0;
                                            }
                                            

                                            Un exemple de dialogue
                                            >nord
                                            Direction le nord !
                                            >encore au nord!
                                            Direction le nord !
                                            >maintenant au sud, svp
                                            Direction le sud !
                                            >table
                                            Voulez que je fasse quoi de la table ?
                                            >porte alors!
                                            Voulez que je fasse quoi de la porte ?
                                            >observer la table
                                            ok
                                            >fin

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            Zeste de Savoir, le site qui en a dans le citron !
                                              26 juin 2011 à 22:33:25

                                              Salut ;)
                                              Comment peux-tu savoir la direction permise dans une case, comme par exemple la case hall d'entrée (5eme case), car si elle contient la valeur 12 cela peut aussi bien être :
                                              2+10=12
                                              5+7=12
                                              6+6=12
                                              8+4=12
                                              etc....
                                              ce serait bien plus simple avec un tableau à deux dimensions, encore mieux pour l'utilisation d'objets.

                                              Autre remarque :
                                              le prefixe "obj_" et "act_" on peut s'en passer facilement, il suffit que le programme sache que le premier mot est toujours une action et le deuxieme un objet.
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                26 juin 2011 à 22:45:13

                                                On n'utilise que les valeurs
                                                1 2 4 et 8

                                                essaye de trouver 10 avec ces 4 valeurs?
                                                Combien de possibilités? ;)

                                                Pour ton autre remarque,

                                                Je préfère utiliser 2 tableaux de synonymes.

                                                Tu verras aussi que l'enum eObjet servira également pour la gestion des objet(le membre ID de la struct

                                                Citation


                                                ce serait bien plus simple avec un tableau à deux dimensions, encore mieux pour l'utilisation d'objets.


                                                non. ;)
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                Zeste de Savoir, le site qui en a dans le citron !
                                                  26 juin 2011 à 23:11:52

                                                  j'avoue que l'utilisation de 1,2,4,8 est LA méthode judicieuse pour connaître le nombre et le type des directions permises dans une case si on utilise qu'un tableau à une dimension.
                                                  Question :
                                                  Si tu mets un groupe de lettres comme NSE dans une case pour dire qu'elle a accès à Nord,Sud,Est, est-ce que c'est plus difficile à gérer ?

                                                  Ah oui et merci c'est sympa de mettre ce tuto de jeu textuel ;)
                                                  Il y a longtemps je programmais ce type de jeu en basic simple, c'était bien sympa aussi ;)
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    26 juin 2011 à 23:24:27

                                                    Non, ce n'est probablement pas plus difficile à gérer.
                                                    C'est seulement moins efficace. ;)

                                                    En gros, pour chaque case, tu vas devoir:
                                                    -stocker une chaîne,
                                                    -et rechercher la présence d'un caractère dans la chaîne.

                                                    Donc au lieu d'un char, tu auras pour chaque case de la carte(4 ou 5 si tu place le '\0', et une recherche linéaire au lieu d'un accès à l'info instantanément.

                                                    Je ne te cache pas que j'ai trouvé que c'était une manière de présenter les opérateurs binaires de manières sympa aussi.

                                                    Pour le choix du tableau 1D.
                                                    Je peux dire qu'un objet se trouve en case 12.
                                                    C'est plus chiant avec une grille 2D.
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                    Zeste de Savoir, le site qui en a dans le citron !
                                                      26 juin 2011 à 23:33:26

                                                      Citation

                                                      Je ne te cache pas que j'ai trouvé que c'était une manière de présenter les opérateurs binaires de manières sympa aussi.


                                                      heu...vi c'est juste ^^

                                                      Je préfère toujours les tableaux à deux dimensions, mais c'est une question de goût je penses, car ta méthode est efficace, juste que je ne me sens pas de dire la case 12 alors que je suis en case I,J ;)


                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        27 juin 2011 à 10:56:11

                                                        Juste un petit message pour suivre le sujet.
                                                        J'en profite au passage pour féliciter GurneyH, les questions d'architecture du projet sont super intéressante et j'attends le prochain épisode avec autant d'impatience que la prochaine saison de TBBT. ^^
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                        Zeste de Savoirbépocode minimal  — Ge0 <3
                                                          27 juin 2011 à 20:28:00

                                                          Pour les tableaux 2D, je trouve que c'est un peu bête de les utiliser quand on peut les remplacer par des tableaux 1D plus simples.

                                                          Le problème c'est que les tableaux 2D sont sujettes à des erreurs mal comprises. Exemple type :
                                                          int foo (int** tab, int row, int col) {
                                                          return 2*tab[row][col]; 
                                                          }
                                                          int main (int argc, char** argv) {
                                                          int bar[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
                                                          int n = foo(bar,1,1); // pourquoi ça marche pas ?
                                                          printf("%d",n);
                                                          return 0;
                                                          }
                                                          

                                                          Pour cette raison, je préfère les éviter. Parce que même quand on a l'habitude, ce genre d'erreur est vite arrivé et elles ne sont pas spécialement facile à repérer.

                                                          ET en ce qui concern les performances, c'est du pareil au même, l'accès implique dans les deux cas une multiplication et un déréférencement.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            2 juillet 2011 à 21:04:46

                                                            Dernière ligne droite



                                                            On a toutes les briques entre nos mains pour réaliser notre jeu.
                                                            Le tout est de mettre

                                                            Un peu d'ordre dans les briques.


                                                            Pour ce faire on va découper notre code en modules indépendants.
                                                            -constante.h qui contiendra les constantes globales du projet
                                                            -analyseur
                                                            -objets
                                                            -carte

                                                            et, en modules utilisant les précédents
                                                            -salle
                                                            -main

                                                            Je me suis fixé pour règle de ne jamais accéder aux données internes directement depuis un autre module, on passera obligatoirement par des accesseurs et mutateurs.
                                                            Cette encapsulation me permettra par exemple de changer les structures de données utilisées, par exemple, sans changer l'utilisation du module

                                                            Les modules analyseur, objet et carte ont été présentés précédemment.

                                                            C'est la fonction main, qui contient la boucle principale de notre jeu.
                                                            Cette boucle se déroule de la sorte
                                                            Tant que le jeu n'est pas fini
                                                                Si on est dans une nouvelle salle
                                                                   afficher description de la salle
                                                                afficher les directions possibles
                                                                analyse de la saisie utilisateur
                                                                si la saisie est valide
                                                                    si c'est une direction
                                                                       actualiser la position du joueur
                                                                    sinon si c'est l'action prendre
                                                                       prendre objet
                                                                    sinon si c'est l'action poser
                                                                        poser objet
                                                                    sinon si c'est l'action inventaire
                                                                        afficherInventaire
                                                                    sinon
                                                                        gestion spécifique à chaque salle
                                                                sinon
                                                                    afficher erreur


                                                            Le module salle lui s'occupe de gérer les actions spécifiques à chaque salle.
                                                            Je passe par la seule fonction publique du module gestionSalle.
                                                            Cette fonction dispatche vers la fonction adaptée selon le numéro de la salle à traiter.

                                                            Quelques remarques.
                                                            Je suis resté très très simple.
                                                            Aussi, je n'ai pas ajouté le membre id à la struct objet, comme il m'avait été conseillé.
                                                            Les données de la carte, et des objets sont en dur dans le code.
                                                            Pour un jeu plus conséquent, il faudra envisager sérieusement la lecture des données depuis un fichier.

                                                            J'ai conservé exactement pour cet essai, la même trame que le programme final illustrant la série d'articles que j'ai cité précédemment(série d'articles dans le magasine Amstrad Cent pour Cent).

                                                            Vous incarnez un agent secret, qui a pour mission de déconnecter le PC du QG ennemi.
                                                            L'aventure commence à l'entrée du QG.
                                                            :-°

                                                            Les sources sont ici
                                                            Je vous invite, à tester dans un premier temps sans regarder les sources, histoire de voir en combien de temps vous pouvez finir ce mini jeu, qui ne comporte en tout que 5 salles. ;)

                                                            N'hésitez pas, bien sur, à poser des questions, signaler des bugs, ou à émettre des critiques.

                                                            La prochaine fois, on va abandonner la console, et s'intéresser à la SDL.

                                                            edit:
                                                            Si vous regardez dans carte.c, vous verrez que pour fermer une direction j'utilise l'opérateur XOR à la place du NOT, comme je l'avais fait plus haut.
                                                            La raison est qu'avant d'appliquer le changement, je teste si le changement est logique, sinon je retourne un code d'erreur.
                                                            L'utilisation du XOR, est justifiée ici, je pense.
                                                            edit2:
                                                            Correction de l'archive.
                                                            nouvelle correction le 04/07/11
                                                            Il y avait de grosses bourdes dans le fichier objets.c :'(
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                            Zeste de Savoir, le site qui en a dans le citron !
                                                              3 juillet 2011 à 10:07:55

                                                              L'entree
                                                              Direction possibles : Ouest 
                                                              > OUEST
                                                              Couloir
                                                              Direction possibles : Est Ouest 
                                                              > FOUILLE
                                                              Il y a une porte derriere vous.


                                                              Au début je pensais que c'était de l'humour :-°

                                                              Bon alors j'avoue, j'ai du lire le code pour le terminer, parce que je ne trouvais pas cette #@*! de clé >_<
                                                              Mais sinon, c'est pas mal du tout. Il y a juste une chose que j'ai regrettée, c'est qu'il n'y a pas une aide générale. Lorsque l'on entre SOS par exemple, on a un indice sur la pièce courante (ou pas), alors que j'aurais plutôt attendu une liste des commandes possibles du style:

                                                              > HELP
                                                              PRENDRE OBJET
                                                              FOUILLE [OBJET]
                                                              DEPOSER OBJET
                                                              DEBRANCHE OBJET
                                                              ASSASSINE PERSONNE
                                                              DISCUTE PERSONNE


                                                              Citation : GurneyH


                                                              La prochaine fois, on va abandonner la console, et s'intéresser à la SDL.



                                                              J'ai hâte de voir ça :)

                                                              > FAIRE CAFE
                                                              Rien compris! Oo


                                                              C'est pourtant pas compliqué!
                                                              Désolé, j'ai pas pu m'en empêcher :-°
                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Jeu d'aventure textuel

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown