Révélation
Jeudi 10 janvier 2008Attention ! je vais parler d’informatique
Ca fait un petit moment que j’étudie le langage Haskell pendant mes heures perdues. Ca fait aussi un moment que j’ai dans mes cartons le projet de programmer un générateur de personnages pour Shadowrun 4. Alors forcément, j’ai fini par faire le pont entre les deux activités.
Coder un générateur de personnages n’est pas chose facile - tout du moins en coder un qui soit complet et propre. Parce que la création de personnages, c’est des tonnes de petites règles à la con dans tous les sens, qui s’influencent les unes les autres. Et au final, c’est un enfer.
Pendant longtemps je suis resté bloqué à la phase de conception, avec quelques essais peu concluants ici et là. Mais cette semaine, les choses ont changé. D’un coup, j’ai réalisé que pendant tout ce temps, mes tentatives de conception étaient franchement influencées par mon expérience de la programmation orientée objet. Que si je voulais m’en sortir, il fallait que je vois les choses sous un jour différent.
Jusqu’alors, je voyais les choses sous cet angle :
- j’ai un énorme type de données très compliqué qui représente le personnage,
- il est accompagné d’un ensemble de fonctions permettant de le modifier,
- il y a un ensemble de règles qui testent la validité du personnage.
Là où je me prennais la tête, c’était sur l’interaction avec l’utilisateur : l’utilisateur peut décider de prendre un avantage qui va modifer le personnage, puis de retirer cet avantage. Devrait-on alors définir une fonction qui applique les modifications et une seconde qui applique les modifications inverses ?
Cette semaine, j’ai changé de point de vue. Je me suis rendu compte que c’était ma vision du processus de création d’un personnage qui était biaisée.
Au final, créer un personnage, c’est partir d’une base commune et faire une série de choix qui vont modifier cette base jusqu’à arriver au résultat final. Plutôt que de se focaliser sur le personnage en lui même, il faut se focaliser sur le processus de création, c’est à dire l’enchainement de modifications appliquées à la base.
Et là, tout devient plus simple : chaque choix de l’utilisateur doit s’exprimer sous la forme d’une fonction Personnage -> Personnage, qu’on enchainera pour obtenir le résultat final. Si l’utilisateur décide finalement de ne pas prendre tel avantage, rien de plus simple : on retire la fonction correspondante de la liste de modifications, on réapplique les modifications suivantes et on a le personnage corrigé.