Comprendre et utiliser le moteur d openESub
Le moteur d'openESub est bien séparé du reste, et il est possible de l'utiliser tout seul ou presque. Dans cet article, nous allons voir comment utiliser le moteur pour faire un simulateur (très) rudimentaire.
Cachalot (c'est le petit nom du moteur de base) est écrit en Python, comme une grande partie d'openESub, et est situé dans le répertoire /jeu/commun/cachalot de l'arborescence du jeu.
Sommaire |
Pré-requis
Pour suivre cet article, il vous faut :
- installer Python sur votre machine,
- télécharger l'arborescence contenant le moteur, pour ce faire, reportez-vous à l'article utiliser le CVS,
- plaçons-nous dans le répertoire /jeu/commun/cachalot/test où nous allons mettre notre fichier
kolga.py
(Kolga est une fille d'Aegir dans la mythologie nordique).
Code
Imports
Comme tout programme Python, il faut commencer par importer les modules.
Les modules généraux que nous allons utiliser sont :
import cmd # gère l'interface de type shell import sys # gère certains appels systèmes import os # gère les interaction avec le système d'exploitation
Pour importer les modules du moteur, nous allons devoir ajouter les chemins corrects au path :
sys.path.insert(0,os.path.abspath('../src')) sys.path.insert(0,os.path.abspath('../../../tempsReel/clients/argo/src'))
Les modules d'intérêt concernant le moteur sont :
import openRapport # gestion des comptes-rendus import openZdop # zones d'opération (parties) import openMoteur # le moteur lui-même from openConstantes import * # les constantes d'openESub
Classe et constructeur
Tout d'abord, on créé une classe qui va définir notre petit simulateur. Cette classe hérite de la classe Cmd
qui permet de construire rapidement une interface en mode texte. On met en place deux méthodes de base : une commande d'aide et une commande de sortie.
class Kolga(cmd.Cmd): """Simulateur en ligne de commande tout simple""" def help_help(self): print "Affiche la liste des commandes disposant d'une aide" def do_EOF(self, ligne): """Commande de sortie du shell : [Ctrl-D] sous Unix, [Ctrl-Z] sous Windows""" print '\n' sys.exit() def removeEmptyItem(self,list): """Supprime les items vides d'une liste de strings. Exemple : ['a',,'b'] -> ['a','b']""" return filter(None,list[:])
La dernière méthode permet de faciliter le traitement des paramètres passés à certaines commandes.
Ensuite on initialise les différentes variables. Notez qu'on choisit de passer le compte-rendu au format XML en tant que paramètre du constructeur.
# constructeur (première fonction appelée # lors de l'instanciation de la classe) def __init__(self,data): # initialise le gestionnaire de ligne de commande cmd.Cmd.__init__(self) # charge le compte-rendu XML pour extraire les données self.soums, self.torps = openRapport.LireCompteRendu(data) # définit une zone d'op standard zdop = openZdop.Zdop(0., 20000., 0., 20000.) # crée une instance du moteur self.moteur = openMoteur.Moteur(zdop) # crée un dictionnaire des sous-marins et des torpilles, # associant l'id à l'objet marin self.soumi = {} for soum in self.soums: self.soumi[soum.id] = soum self.torpi = {} for torp in self.torps: self.torpi[torp.id] = torp
On peut noter que notre classe présente les variables d'intérêt suivantes :
- moteur : une instance du moteur Cachalot,
- soumi et torpi : des dictionnaires associant un numéro d'id à un objet marin.
Lister
Notre première méthode va lister les objets présents sur la zone d'opération.
def do_liste(self,line): """Affiche la liste des objets""" # sous-marins for soum in self.soums: # affichage formaté print "(%d) Sub %s \t " % (soum.id, soum.nom), soum.contact('short') # torpilles for torp in self.torps: print "(%d) Torp \t " % (torp.id), torp.contact('short')
Compiler
Cette méthode va servir à compiler un tour.
def do_compiler(self,line): """Effectue une compilation""" # utilise le moteur faits, contacts, self.soums, self.torps = self.moteur.compiler(self.soums, self.torps) # re-crée les dictionnaires self.soumi = {} for soum in self.soums: self.soumi[soum.id] = soum self.torpi = {} for torp in self.torps: self.torpi[torp.id] = torp # affiche les évenements du tour for fait in faits: print fait
Ordres
Cette méthode va donner des ordres à un sous-marin (ami ou ennemi).
def do_ordonne(self,line): """Donne un ordre à un sous-marin : ordonne <id> <vitesse> <cap> <tir> ; avec <tir> valant 0 (pas de tir) ou 1 (tir)""" # nettoie la commande args = self.removeEmptyItem(line.split(' ')) # traduit les valeurs en entier try: id, dv, dcap, tir = map(int, args) except: print "Erreur de syntaxe"
# affiche l'aide de la commande self.do_help('ordonne') return # si le sous-marin existe if self.soumi.has_key(id): # passe les ordres self.soumi[id].ordonne(dv = dv, dcap = dcap, tir = tir) print "Ordres du sous-marin", self.soumi[id].nom, ": dv", dv, print "dcap", dcap, "tir", tir else: print "Erreur: Le sous-marin", id, "n'existe pas."
Interface
Nous allons maintenant écrire ce qui va permettre au simulateur de se lancer.
if __name__ == '__main__': # teste si argument présent if len(sys.argv) <= 1: cr = raw_input("Entrez le nom du comptes-rendu de départ > ") else: cr = sys.argv[1] # ouvre le compte-rendu XML passé en premier argument data = openRapport.OuvrirCompteRendu(cr) # message de bienvenue print 'Bienvenu sur la console de Kolga' print ' Kolga est un simulateur pour openESub (http://www.openesub.org)' print ' tapez "help" pour avoir la liste des commandes' print ' ' # on lance la console interactive shell = Kolga(data) shell.prompt = "Kolga> " shell.cmdloop()
Usage
Pour utiliser Kolga, c'est très simple :
- soit vous lancez le script avec un CR au format XML en premier argument :
python kolga.py monCR.xml
, - soit vous préférez lancer le script sans argument, auquel cas il vous faudra taper le nom du fichier lorsqu'il vous le demandera.
Kolga est présent dans l'arborescence que vous avez téléchargé au début de l'article, donc pas besoin de faire des copier/coller du code écrit ci-dessus. Il se peut que le fichier soit légèrement différent du code source de cet article, ce n'est pas grave, préférez toujours la version téléchargée via CVS. Notez que Kolga ne va pas évoluer en fonctionnalités, si vous désirez ajouter des fonctionnalités et que vous voulez en faire profitez d'autres joueurs, contactez les mainteneurs du projet, ils créeront une section pour votre simulateur.
Conclusion
Les fonctions importantes du code source d'openESub dont nous nous sommes servies sont les suivantes :
- Pour charger un CR XML :
data = openRapport.OuvrirCompteRendu( MON_FICHIER_XML ) soums, torps = openRapport.LireCompteRendu(data)
- Pour compiler un tour :
zdop = openZdop.Zdop(0., 20000., 0., 20000.) moteur = openMoteur.Moteur(zdop) faits, contacts, soums, torps = self.moteur.compiler(self.soums, self.torps)
- Pour passer des ordres à un sous-marin :
soum.ordonne(dv, dcap, tir)
Comme vous pouvez le constater, elles sont simples et intuitives... réaliser un simulateur plus graphique ne devrait donc maintenant plus vous poser de problèmes.