A faire : généalogie du projet…
Cette section est dans la continuité de mon article de vulgarisation sur les distances, en particulier le cas p = 2.
Contrairement à et surtout qui se prêtent bien aux grilles, est certes plus naturelle mais posera problème pour une implémentation dans un jeu comme Nova.
Nous avons un vaisseau situé au centre d'une case et nous voulons afficher toutes les cases à portée de saut, c'est à dire situées à une certaine distance du centre de la case (prenons 6 pour le moment). La question revient plus ou moins à décider si on va arrondir au supérieur ou à l'inférieur. Par exemple, en jouant avec ce site vous vous apercevrez que l'auteur a choisi d'arrondir au supérieur :
Pour être franc, esthétiquement ce choix me choque : ce n'est pas très rond. Formalisons donc un peu le problème pour comprendre ce qu'il se passe. Nous traçons le cercle de centre et de rayon (la distance de saut, exprimée en nombre de cases). Nous pouvons donc définir le disque des points à l'intérieur du cercle :
Le problème est bien sûr que nous devons penser en terme de cases et non de points du plan. Nous allons donc assimiler une case à son centre, et nous dirons que la case sera affichée si le point à coordonnées entières vérifie . Dit autrement, une case sera affichée si le centre de la case est dans le disque .
Avec cette définition, on s'aperçoit immédiatement que sur les bords nord, sud, est et ouest du cercle il ne devrait y avoir qu'une case d'affichée, contrairement au dessin précédent où nous voyons cinq cases pour . En effet le centre de la case à l'est est pile dans le disque, mais les centres des cases au dessus et en dessous ne devraient pas y être, puisque et . En regardant un peu le code source, on s'aperçoit que c'est parce que ce n'est pas qui a été pris comme rayon du cercle, mais . C'est pour cela que j'ai parlé d'arrondi au supérieur. En fait, nous aurions dû plutôt avoir ceci :
À ce stade, force est de constater que la solution mathématiquement juste est encore plus hideuse que l'autre, surtout les cases toutes seules au nord, au sud, à l'est et à l'ouest. Comme dans Nova nous nous intéresserons à de petites () valeurs de saut, nous pouvons envisager d'utiliser plutôt la condition , où est petit et à régler au jugé. Avec nous retrouvons la solution mathématiquement juste, et avec nous retrouvons la solution du site susnommé. Il ne reste qu'à prendre une valeur satisfaisante sur le plan esthétique…
Après réflexion, je suis en fait parti sur au lieu de , car quand devient grand l'erreur devient négligeable au carré au lieu de juste négligeable. Il ne reste qu'à fixer de façon à ce que le dessin soit satisfaisant pour les premières valeurs. Après test est suffisant. J'obtiens donc la condition qui est assez simple à calculer. De plus, cela m'a aidé à faire des tests, vu que est quand même plus à l'aise avec les entiers.
Voici le code que j'ai utilisé pour générer ces images :
\PassOptionsToPackage{dvipsnames}{xcolor} \documentclass[tikz]{standalone} \usepackage{lmodern} \usepackage[T1]{fontenc} \usepackage[french]{babel} \usepackage[utf8]{inputenc} \usepackage{contour} \usepackage{tikz} \usepackage{multido} \usepackage{ifthen} \usepackage[nomessages]{fp} \newcommand{\maxSaut}{10} \begin{document} \multido{\iSaut=1+1}{\maxSaut}{ \FPeval{\iSautCarre}{clip(\iSaut*\iSaut+1)} \FPeval{\zone}{clip(2*\iSaut+1)} \begin{tikzpicture}[scale=1.0] \fill[black] (-\iSaut-1,-\iSaut-1) rectangle (\iSaut+2,\iSaut+2) ; \multido{\i=-\iSaut+1}{\zone}{ \multido{\ii=-\iSaut+1}{\zone}{ \FPeval{\normeCarre}{clip(\i*\i+\ii*\ii)} \ifthenelse{\normeCarre<\iSautCarre \OR \normeCarre=\iSautCarre}{ \fill[Green] (\i,\ii) -- (\i,\ii+1) -- (\i+1,\ii+1) -- (\i+1,\ii) -- cycle; }{} } } \fill[blue] (0,0) -- (0,1) -- (1,1) -- (1,0) -- cycle; \draw[white] (-\iSaut-1,-\iSaut-1) grid (\iSaut+2,\iSaut+2) ; \draw[blue, ultra thick] (0.5,0.5) circle (\iSaut) ; \end{tikzpicture} } \end{document}
Quelques précisions :
Pour l'algorithme lui-même, exprimé en C par exemple, ça donnerait quelque chose de la forme :
void afficherPortee(int xVaisseau, int yVaisseau, int portee) { for (xCase = xVaisseau-portee ; xCase <= xVaisseau+portee ; xCase++) for (yCase = yVaisseau-portee ; yCase <= yVaisseau+portee ; yCase++) if ((xCase-xVaisseau)*(xCase-xVaisseau) + (yCase-yVaisseau)*(yCase-yVaisseau) <= portee*portee + 1) afficher(xCase,yCase); }
où la fonction « afficher » dépend de l'interface choisie.
Cette section est pour l'instant seulement une prise de notes.
note : quand je parle de planète je devrais en fait parler de système, vu qu'on a décidé qu'un système formait un tout (logique car oje souhaite me focaliser sur la vue galactique et que les planètes d'un même système partageaient de facto leur stocke de ressources). En particulier, il n'est plus possible à plusieurs joueurs de coloniser le même point (enfin, modulo l'emploi des corporations…).
Lien avec l'article sur les sauts hyperspatiaux.
+ faire dessin avec les portées différentes.
Idée : consommation de combustible = distance parcourue * temps gagné, de façon à avoir une tension entre la consommation de minerai et la vitesse (on peut aller très loin pour peu si on n'est pas pressé, ou au contraire brûler beaucoup de ressources pour se déplacer rapidement). Je parle ici de la consommation d'un vaisseau, la consommation d'une flotte étant obtenue tout simplement en sommant la consommation des vaisseaux. Si la consommation est homogène, cela revient à multiplier par le nombre de vaisseaux.
Par exemple, on peut parcourir 4 cases une par une. Dans ce cas on fait 4 étapes en consommant 1 unité de combustible [1]. On pourrait aussi décider de faire des sauts de 2 cases, auquel cas on consommerait 2 combustibles pour la distance, multipliés par 2 parce qu'on fait deux fois moins d'étapes. Et en faisant un seul saut on consomme 4*4 = 16 unités de minerai.
Au final, pour chaque saut : consommation = distance au carré. La formule est simple et a même du sens d'un point de vue physique (par exemple les champs gravitationnels sont « au carré », préciser ?).
A faire : montrer que si on parcourt une distance donnée en deux sauts alors on a intérêt à arrêter le premier saut à mi-distance.
Ainsi, la portée de saut est (Unity a bien une fonction racine), et si on veut pouvoir revenir en arrière ou plus généralement faire deux sauts consécutifs de . On a donc naturellement une portée maximale de saut, dépendant de la capacité maximale des transporteurs (en supposant qu'on peut panacher le transport de ressources, et qu'il n'y ait pas par exemple des emplacements dédiés au minerai ou au combustible).
Cette dernière remarque est un bon exemple de fausse bonne idée de conception. Un autre exemple de fausse bonne idée est un stock de ressources universel, utilisable par toutes les planètes (c'est le cas de l'hôtel des vente par exemple) [2]. En effet, on veut que les gens aient à transporter leurs ressources car :
Le cas des cargos (transporteurs automatisés et continus formant un cycle entre planètes). Il est possible de transporter des ressources via des flottes (qui ont par exemple un peu de combustible et des pièces détachées / minerai) ou via des cargos. Il faut que les cargo soient rentables pour éviter que les joueurs utilisent exclusivement des flottes, ce qui inciterait à la micro-gestion, ce qui est rébarbatif. Ainsi, une fois construits et activés, les cargos ont un coût continu en combustible correspondant à une flotte avançant case par case (le coût minimal donc), et dont la taille de cargaison correspond à ce qui se fait de mieux pour les flottes. L'avantage est que contrairement aux flottes qui ne larguent leur cargaison qu'une fois arrivées, les cargos distillent leur cargaison de façon continue. Ainsi, sur une période de temps correspondant à la durée du voyage les quantités transportées seront les mêmes, mais les cargos font une sorte d'avance aux joueurs. Je ne pense pas que ce soit craqué, et on peut de toute façon jouer sur les temps de construction pour équilibrer, surtout connaissant la portée maximale de saut.
Le faut que les cargos consomment du combustible et déplacent des ressources d'un système de production à un système de consommation de façon continue (quantité par seconde) permet facilement de prévoir les changements d'état d'un système (stock de ressource vide ou fin de construction) et donc économise du temps de calcul sur le serveur. Enfin, j'impose qu'une voie commerciale établie par des cargos forme un cycle, par exemple entre deux systèmes (aller et retour des ressources [4]) ou trois systèmes (comme le commerce triangulaire), pour des raisons de logique (les vaisseaux doivent revenir pour recommencer le voyage) mais aussi de gameplay (notamment envoyer des ressources des systèmes riches vers les pauvres, ou plus généralement créer des cycles intéressants dans son domaine entre systèmes spécialisés).
[1] L'unité est une valeur universelle appliquée à toutes les ressources, qui désigne la quantité de ressource en question que l'on peut entasser dans un container (lien dataGueule ?) standard de la Fédération. Ainsi, bien que les astri'll [5] aient obtenus les unités de mesures lors du congrès de ? et les humains les règles monétaires (les menehatim ayant obtenu le méridien galactique), ces derniers ont de facto gagné une unité de mesure informelle dans le domaine commercial.
[2] Seuls les crédits et la recherche rentrent dans cette catégorie, vu qu'ils sont dématérialisés, contrairement aux ressources qui sont extraites ou transformées localement, ou au savoir-faire qui est porté par la population.
[3] L'intérêt de l'exploration est renouvelé dès qu'une nouvelle ressource est découverte par la technologie, puisqu'il faut alors actualiser les cartes. C'est le rôle des prospecteurs, par opposition aux explorateurs purs qui eux vont cartographier les étoiles et les trous de ver, et visiter les ruines des Anciens.
[4] Cela incite à ce qu'il y ait des ressources allant des systèmes pauvres vers les systèmes riches, par exemple le minerai ou le combustible, mais aussi qu'il y ait des ressources allant des systèmes riches vers les systèmes pauvres, comme des produits manufacturés ou des soldats (cynisme !).
[5] le 'll désigne une instanciation, ainsi “astri” évoquera l'individu astri en général, alors que “astri'll” désignera un certain nombre d'individus. En français c'est un peu la différence entre un article défini et indéfini. Concept un peu platonicien, non ? La mathématique est platonicienne ?