Propagation de feu et relation de proximité

J’aimerais implémenter un système de feu qui pourrait se propager à des objets « proches ».

J’étais partie pour créer une relation de proximité, qui amalgamerait à la fois le containment, le support, éventuellement l’incorporation. Idéalement, je la voyais comme une relation d’équivalence (c’est surtout la symétrie et la transitivité qui m’intéressent, donc si A et B sont sur C qui est dans D et que E est aussi dans D, qu’ils soient tous considérés comme proches les uns des autres).
Mais j’ai un peu du mal avec les relations. Si j’écris Bordering relates things to each other in groups. j’ai une relation d’équivalence, mais je ne sais pas comment définir qui est proche de quoi. Et si j’adapte l’exemple du contact de la documentation (§13.12) :
Bordering relates a thing (called X) to a thing (called Y) when X is part of Y or Y is part of X or X contains Y or Y contains X or X supports Y or Y supports X.
C’est a priori plus transitif, et je ne sais pas non plus comment ajouter la transitivité. Si les endroits comptent là-dedans, je vais aussi être embêtée.

Est-ce que c’est juste une mauvaise idée de gérer ça avec une relation ? L’exemple 192 Frizz gère la propagation de l’eau avec un rulebook qui gère au cas par cas toutes les situations différentes, ce que je voulais éviter.

Surprenamment moins évident que ce que j’ai pensé de prime abord !

Absolument pas testé, il se peut que je me plante quelque part, mais ça donne une idée.

[Renommé parce que je n’aime pas utiliser un suffixe en -ing comme pour les actions.]
Contact relates a thing (called X) to a thing (called Y) when X is the holder of Y or Y is the holder of X.
The verb to border means the contact relation.

Transitive contact relates a thing (called X) to a thing (called Y) when X borders Y or a thing that borders X transborders Y.
The verb to transborder means the transitive contact relation.

J’ai un peu peur qu’une boucle infinie se cache dans la récursion.

Je soupçonne que ça boucle sur tous les objets du jeu et donc que ça n’est pas très efficace. Si on sait que le contact ne peut se faire que par l’arbre des objets, alors on peut faire plus efficace en ne bouclant que sur les enfants et parents ou en trouvant l’ancêtre commun.

Désolé, je n’ai pas le courage de faire mieux pour le moment.

Pas de problème, merci d’avoir répondu !
Moi aussi je pensais que ça serait simple au début.

Alors je devais être vraiment fatigué parce que la réponse est super simple.

La transitivité, au fond, c’est juste d’avoir un chemin dans le graphe de la relation de contact, non ? Et il y a des algorithmes pour éviter le genre de boucle infinies que j’ai décrit, comme Dijkstra. Et c’est une des forces d’Inform de fournir ça avec les relations (section « Indirect relations » de la doc).

Donc il aurait suffit de faire ça pour le transitive contact :

Transitive contact relates a thing (called X) to a thing (called Y) when X is Y [pour la symétrie] or the next step via the contact relation from X to Y is not nothing.
The verb to transborder means the transitive contact relation.

Mais on obtient ça parce qu’on ne peut pas chercher de chemin avec les relations calculées.

Run-time problem P30: Attempt to find route or count steps through an implicit relation.

Reste plus qu’à implanten Dijkstra soi-même… :frowning_face: Mais j’ai testé ma réponse précédente (à laquelle il manque d’ailleurs la symétrie) et elle semble fonctionner donc tout est bon en fait ?

(Par « symétrie », je voulais bien sûr dire « réflexivité ». Oups.)

Désolée, je n’ai pas bossé sur le projet pendant un moment.

J’ai testé la solution 1, elle ne cause pas d’erreur à la compilation, mais quand je demande, lorsque j’examine un objet say "[list of things that transborder the noun]". et que je teste en examinant un objet, j’obtiens Glulxe fatal error: Stack overflow in function call. à la place de la liste. J’avais testé en rajoutant des bouts pour la symétrie, puis juste avec ta définition telle quelle.

Je vais décrire ce que j’avais envisagé pour la propagation du feu, au cas où ça donne des idées. En gros, chaque objet à un niveau de flammabilité, plus il est élevé, plus c’est facile de l’enflammer (0 = ne brulera pas du tout, 5 = très facile à enflammer), les objets inflammables peuvent être dans différents états : intact, en flammes et brûlé. Je voudrais qu’on puisse tenter d’allumer des objets avec, par exemple, un briquet. Si l’objet est intact et son niveau de flammabilité est suffisamment élevé, il s’enflamme, et je pensais lancer une scène à partir de là. Tant qu’on est dans la scène, à chaque tour, on boucle sur les objets intacts « proches », et ceux dont le niveau de flammabilité est inférieur ou égal à (celui du truc en flammes le moins inflammable + 1) deviennent eux aussi en flammes. Idéalement, après un certain nombre de tours qui dépend du niveau de flammabilité (les trucs plus inflammables brûlent moins longtemps), les objets disparaissent et/ou deviennent brûlés. Si plus rien dans la zone n’est en flammes, la scène prend fin.

Ce qui m’intéressait dans la relation, c’était donc d’avoir des groupes d’objets sur lesquels je peux boucler. En soit, je vois trois grandes zones de proximité (la cheminée, la table et le lit) où les trucs pourraient brûler, ainsi que les possessions du joueur qu’on ne pourrait pas allumer, et puis le reste, je ne sais pas encore si je veux bloquer l’allumage ou juste permettre d’enflammer des trucs sans propagation.

Étant donné que je connais à l’avance les « zones » dans lesquelles je veux qu’il y aie propagation, est-ce que c’est plus simple de gérer ça à la main, en donnant des attributs aux objets au départ en fonction de là où ils sont, puis en modifiant ces attributs quand on les déplace ? Est-ce que c’est plus simple de forcer à ce que tous les trucs déplacés « à la main » soient des enfants directs des trois gros objets qui définissent mes zones (donc si je mets le tabouret dans la cheminée, puis que j’essaye de mettre un truc sur le tabouret, je demande à Inform de le mettre dans la cheminée directement), histoire de n’avoir que des enfants directs ? Est-ce qu’il y a une autre approche plus simple à laquelle je ne pense pas ?

C’est exactement ce à quoi je faisais allusion par « j’ai un peu peur qu’une boucle infinie se cache dans la récursion ». (Trop de récursion remplit la pile.)

Mais si j’ai bien compris ce que tu veux faire, je vois pas trop où est la transitivité ? Si A est en feu, et A touche B et B touche C : au tour suivant, le feu sera propagé à B par contact avec A, mais est-ce que C le sera aussi directement ou il faut attendre le tour suivant ? Si non, alors ça me semble facile ?

À chaque tour, pour chaque objet en feu, parcourir les objets intacts qui le touchent et si leur inflammabilité est assez haute, les mettre dans une liste. Ensuite, mettre tous les objets dans la liste en feu. à la fin, parcourir tous les objets en feu pour incrémenter leur compteur et les faire disparaître, etc.

On utilise une liste intermédiaire pour ne pas gêner la boucle extérieure. Si on veut la transitivité, c’est plus compliqué, il faut marquer les objets pour ne pas les parcourir 2 fois et d’autres trucs.

C’est à cause des niveaux de flammabilité que j’ai besoin de la transitivité.

Mettons que dans la cheminée (0), j’ai une buche (2) et un bout de papier (3), sur la buche, j’ai des brindilles (3) et un allume-feu (4). Avec le briquet, je peux allumer l’allume-feu. Au tour suivant, je voudrais que les flammes se propagent au papier et aux brindilles (4->3), et à la buche seulement au tour d’après (3->2) (puis plus rien, vu que la cheminée est ininflammable).

C’est pour ça que ça m’intéressait d’avoir des groupes, parce que je pensais que ça serait facile, mais avec le recul, pas trop. C’est peut-être plus simple de juste s’arranger pour qu’il n’y aie pas d’empilements complexes.