Je veux construire un analyseur de règles générique pour les systèmes RPG de style stylo et papier. Une règle peut impliquer généralement 1 à N entités 1 à N rôles d'un dé et calculer des valeurs en fonction de plusieurs attributs d'une entité.
Par exemple:
Le joueur a STR 18, son arme actuellement équipée lui donne un bonus de +1 STR mais un malus de DEX -1. Il attaque une entité monstre et la logique du jeu est maintenant requise pour exécuter un ensemble de règles ou d'actions:
Le joueur lance les dés, s'il obtient par exemple 8 ou plus (la valeur d'attaque de base dont il a besoin pour passer est l'un de ses attributs de base!) Son attaque est réussie. Le monstre lance ensuite les dés pour calculer si l'attaque passe par son armure. Si oui, les dégâts sont subis sinon l'attaque a été bloquée.
En plus des règles mathématiques simples peuvent également avoir des contraintes comme s'appliquer uniquement à une certaine classe d'utilisateurs (guerrier vs assistant par exemple) ou tout autre attribut. Donc, cela ne se limite pas aux opérations mathématiques.
Si vous connaissez des systèmes RPG comme Dungeon and Dragons, vous saurez ce que je fais.
Mon problème est maintenant que je ne sais pas comment construire exactement cela de la meilleure façon possible. Je veux que les gens puissent mettre en place n'importe quel type de règle et ensuite faire simplement une action comme sélectionner un joueur et un monstre et exécuter une action (un ensemble de règles comme une attaque).
Je demande moins d'aide pour le côté base de données, mais plutôt pour trouver une structure et un analyseur afin de garder mes règles flexibles. La langue de choix pour cela est d'ailleurs PHP.
Modifier I:
Permettez-moi d'affiner mon objectif: je veux créer une interface conviviale (qui ne nécessite pas que quelqu'un apprenne un langage de programmation) pour construire des règles de jeu plus ou moins complexes. La raison simple: une utilisation personnelle pour ne pas avoir besoin de se souvenir de toutes les règles tout le temps, nous ne jouons tout simplement pas souvent et c'est un bouchon pour les rechercher à chaque fois. Aussi: Cela ressemble à une tâche amusante à faire et à apprendre. :)
Ce que j'ai essayé jusqu'à présent: penser à un concept au lieu de perdre du temps à construire une mauvaise architecture. Jusqu'à présent, j'ai l'idée de permettre à un utilisateur de créer autant d'attributs qu'il le souhaite, puis d'attribuer autant d'attributs qu'il le souhaite à tout type d'entité. Une entité peut être un joueur, un monstre, un objet, n'importe quoi. Désormais, lors du calcul de quelque chose, les données sont mises à la disposition de l'analyseur de règles afin que l'analyseur de règles puisse faire des choses comme si Player.base_attack + dice (1x6)> Monster.armor_check puis Monster.health - 1; La question ici est de savoir comment créer cet analyseur.
Edit II:
Voici un exemple de valeur assez basique mais pour le calculer correctement, il y a beaucoup de choses et de variables différentes à prendre en compte:
Bonus d'attaque de base (durée) Votre bonus d'attaque de base (communément appelé BAB par la communauté d20) est un bonus de jet d'attaque dérivé de la classe et du niveau du personnage. Les bonus d'attaque de base augmentent à différents taux pour différentes classes de personnages. Un personnage gagne une deuxième attaque par round lorsque son bonus d'attaque de base atteint +6, un troisième avec un bonus d'attaque de base de +11 ou plus, et un quatrième avec un bonus d'attaque de base de +16 ou plus. Bonus d'attaque de base gagnés dans différentes classes, comme pour un personnage multiclasse, pile. Le bonus d'attaque de base d'un personnage n'accorde plus d'attaque après avoir atteint +16, ne peut pas être inférieur à +0 et n'augmente pas en raison des niveaux de classe une fois que le niveau du personnage atteint le 20e. Un bonus d'attaque de base minimum est requis pour certains exploits.
Vous pouvez le lire ici http://www.dandwiki.com/wiki/Base_Attack_Bonus_(Term) y compris les liens vers les classes et les exploits qui ont à nouveau leurs propres règles pour calculer les valeurs requises pour l'attaque de base.
J'ai commencé à penser que le garder aussi générique que possible rendrait également assez difficile d'obtenir un bon analyseur de règles.
Func
s qui initialise l'état du programme en fonction des arguments comme clés du dictionnaire. Surpris, je n'avais jamais trouvé ce post de Yegge auparavant, très cool, merci de l'avoir signalé.Réponses:
Ce que vous demandez est essentiellement un langage spécifique au domaine - un petit langage de programmation à des fins étroites, dans ce cas, définissant les règles RPG P&P. Concevoir une langue n'est en principe pas difficile, mais il y a une quantité considérable de connaissances initiales que vous devez acquérir pour être productif. Malheureusement, il n'y a pas de référence centrale pour ce genre de choses - vous devez le récupérer par le biais d'essais, d'erreurs et de nombreuses recherches.
Tout d'abord, trouvez un ensemble d'opérations primitives grâce auxquelles d'autres opérations peuvent être implémentées. Par exemple:
Obtenez ou définissez une propriété du joueur, d'un PNJ ou d'un monstre
Obtenez le résultat d'un jet de dé
Évaluer les expressions arithmétiques
Évaluer les expressions conditionnelles
Effectuer une ramification conditionnelle
Concevez une syntaxe qui exprime vos primitives. Comment représenterez-vous les nombres? À quoi ressemble une déclaration? Les instructions se terminent-elles par un point-virgule? Terminé à la nouvelle ligne? Existe-t-il une structure en blocs? Comment allez-vous l'indiquer: à travers des symboles ou une indentation? Y a-t-il des variables? Qu'est-ce qui constitue un nom de variable légal? Les variables sont-elles mutables? Comment allez-vous accéder aux propriétés des objets? Les objets sont-ils de première classe? Pouvez-vous les créer vous-même?
Écrivez un analyseur qui transforme votre programme en une arborescence de syntaxe abstraite (AST). En savoir plus sur l'analyse des instructions avec un analyseur de descente récursif. Découvrez comment analyser des expressions arithmétiques avec une descente récursive est ennuyeux, et un analyseur de priorité d'opérateur de haut en bas (analyseur Pratt) peut vous faciliter la vie et raccourcir votre code.
Écrivez un interprète qui évalue votre AST. Il peut simplement lire chaque nœud de l'arbre et faire ce qu'il dit:
a = b
devientnew Assignment("a", "b")
devientvars["a"] = vars["b"];
. Si cela vous facilite la vie, convertissez l'AST sous une forme plus simple avant l'évaluation.Je recommande de concevoir la chose la plus simple qui fonctionnera et restera lisible. Voici un exemple de ce à quoi pourrait ressembler une langue. Votre conception différera nécessairement en fonction de vos besoins et préférences spécifiques.
Vous pouvez également apprendre à intégrer un langage de script existant tel que Python ou Lua dans votre application et l'utiliser. L'inconvénient de l'utilisation d'un langage à usage général pour une tâche spécifique au domaine est que l'abstraction est fuyante: toutes les fonctionnalités et les accrochages du langage sont toujours présents. L'avantage est que vous n'avez pas à le mettre en œuvre vous-même - et c'est un avantage important. Considère-le.
la source
Je commencerais par déterminer les différentes "phases" de chaque action.
Par exemple, une phase de combat peut impliquer:
Chacune de ces méthodes aurait accès à certains objets assez génériques, tels que le
Player
et leMonster
, et effectuerait des vérifications assez génériques que d'autres entités peuvent utiliser pour modifier les valeurs.Par exemple, vous pourriez avoir quelque chose qui ressemble à ceci inclus dans votre
GetPlayerCombatStats()
méthode:Cela vous permet d'ajouter facilement n'importe quelle entité avec des règles spécifiques, telles qu'une classe de joueur, un monstre ou une pièce d'équipement.
Comme autre exemple, supposons que vous vouliez une épée de tout tuer sauf Squid , ce qui vous donne +4 contre tout, sauf si cette chose a des tentacules, auquel cas vous devez laisser tomber votre épée et obtenir un -10 au combat.
Votre classe d'équipement pour cette épée pourrait avoir un
GetCombatStats
qui ressemble à ceci:Cela vous permet de modifier facilement les valeurs de combat sans avoir besoin de connaître le reste de la logique de combat, et cela vous permet d'ajouter facilement de nouvelles pièces à l'application parce que les détails et la logique d'implémentation de votre équipement (ou de n'importe quelle entité) ne sont que doivent exister dans la classe d'entité elle-même.
Les éléments clés à déterminer sont à quels points les valeurs peuvent-elles changer et quels éléments influencent ces valeurs. Une fois que vous les avez, la création de vos composants individuels devrait être facile :)
la source
Player
,Monster
,Dice
, etc.), et la mise en place quelque chose qui permet aux utilisateurs de pièces d'entités glisser / déposer dans une zone « équation », remplissant les paramètres de l'entité (comme le remplissageplayer.base_attack
) et spécifiez des opérateurs simples sur la façon dont les pièces s'emboîtent. J'ai en fait publié quelque chose sur mon blog qui analyse une équation mathématique que vous pourriez utiliser.Je jetterais un coup d'œil à maptool en particulier au framework 4e éd . C'est le meilleur système que j'ai vu pour configurer ce dont vous parlez. Malheureusement, le meilleur est encore horriblement cruel. Leur système "macro" a ... disons ... évolué avec le temps.
Quant à un "analyseur de règles", je m'en tiendrai au langage de programmation avec lequel vous êtes à l'aise, même si c'est PHP. Il n'y aura aucun moyen de contourner toutes les règles de votre système.
Maintenant, si vous voulez que vos utilisateurs puissent écrire LEUR PROPRE ensemble de règles, alors vous envisagez d'implémenter votre propre langage de script. Les utilisateurs écrivent leurs propres actions de haut niveau, votre php interprète cela en quelque chose qui affecte réellement les valeurs de la base de données, puis il jette un tas d'erreurs car c'est un système horriblement cru qui a été mis en place au fil des ans. Vraiment, la réponse de Jon Purdy est juste sur le ballon.
la source
Je pense que vous devez être en mesure de penser de manière abstraite à ce qui va se passer dans votre espace problématique, de trouver une sorte de modèle, puis de baser votre DSL sur cela.
Par exemple, vous pourriez avoir l'entité entités, l'action et l'événement au niveau supérieur. Les jets de dé sont des événements qui se produisent à la suite d'actions. Les actions auraient des conditions qui déterminent si elles sont disponibles dans une situation donnée et un "script" des choses qui se produisent lorsque l'action est entreprise. Des choses plus complexes seraient la capacité de définir une séquence de phases où différentes actions peuvent se produire.
Une fois que vous avez une sorte de modèle conceptuel (et je vous suggère de l'écrire et / ou de dessiner des diagrammes pour le représenter), vous pouvez commencer à examiner différents moyens de le mettre en œuvre.
Une voie consiste à définir ce qu'on appelle un DSL externe où vous définissez votre syntaxe et utilisez un outil tel que antlr pour l'analyser et appeler votre logique. Une autre voie consiste à utiliser les fonctionnalités présentes dans un langage de programmation pour définir votre DSL. Des langues telles que Groovy et Ruby sont particulièrement bonnes dans cet espace.
Un piège que vous devez éviter est de mélanger votre logique d'affichage avec votre modèle de jeu implémenté. Je voterais pour que l'affichage lise votre modèle et s'affiche correctement plutôt que de mélanger votre code d'affichage mélangé avec votre modèle.
la source