Nocebo

Duel V0.9

Jul 19th, 2012
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 19.34 KB | None | 0 0
  1. # -*- coding: utf-8 *-*
  2. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
  3. # (un peu inspiré des règles D20)
  4. # V0.9 - maj 16/08/2012
  5. # dernière modif : test_rencontre()
  6. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
  7.  
  8. import time
  9. import random
  10. import bisect # utilisé dans Rencontre_aleatoire()
  11. from math import sqrt # utilisé pour localisation_perso()
  12. import turtle  # A supprimer - Tester visuellement la localisation du perso
  13. # import pickle  # utilisé pour Perso() Item() et Rencontres_aleatoires() - A bosser
  14.  
  15.  
  16. class Perso:
  17.     "Personnages"
  18.     # Dict contenant les créatures et personnages
  19.     liste_creatures = {\
  20.         "Gerald de Rive": {"race": "Sorceleur", "hp": 45, "strength": 6, \
  21.         "dext": 5, "perception": 8,"ca": 0, "armure": 5, "arme": 'arme2', \
  22.         "niveau": 1, "xp": 0, "description": "un sorceleur", "Coord_x": 10, "Coord_y": 19}, \
  23.         # -----------
  24.         "Karadoc": {"race": "Humain", "hp": 50, "strength": 8, \
  25.         "dext": 2, "perception": 8, "ca": 0, "armure": 5, "arme": 'arme3', \
  26.         "niveau": 1, "xp": 0, "description": "un humain", "Coord_x": 28, "Coord_y": 120}, \
  27.         # -----------
  28.         "Perceval": {"race": "Humain", "hp": 50, "strength": 8, \
  29.         "dext": 2, "perception": 8, "ca": 0, "armure": 5, "arme": 'arme3', \
  30.         "niveau": 1, "xp": 0, "description": "un humain", "Coord_x": 70, "Coord_y": 15}, \
  31.         # -----------
  32.         "Orc": {"race": "Orc", "hp": 15, "strength": 4, \
  33.         "dext": 2, "perception": 8, "ca": 0, "armure": 2, "arme": 'arme2', \
  34.         "niveau": 1, "xp": 0, "description": "un Orc", "Coord_x": 50, "Coord_y": 50}, \
  35.         # -----------
  36.         "Sanglier": {"race": "Sanglier", "hp": 20, "strength": 4, \
  37.         "dext": 2, "perception": 8, "ca": 0, "armure": 2, "arme": 'arme4', \
  38.         "niveau": 1, "xp": 0, "description": "un sanglier", "Coord_x": 50, "Coord_y": 50}, \
  39.         # -----------
  40.         "Vampire": {"race": "Mort vivant", "hp": 30, "strength": 2, \
  41.         "dext": 5, "perception": 8, "ca": 0, "armure": 0, "arme": 'arme5', \
  42.         "niveau": 1, "xp": 0, "description": "un vampire", "Coord_x": 50, "Coord_y": 50}, \
  43.         # -----------
  44.         "Squelette": {"race": "Mort vivant", "hp": 15, "strength": 5, \
  45.         "dext": 1, "perception": 8, "ca": 0, "armure": 3, "arme": 'arme2', \
  46.         "niveau": 1, "xp": 0, "description": "un squelette", "Coord_x": 50, "Coord_y": 50}, \
  47.         # -----------
  48.         "Elf franchement éfféminé": {"race": "Elf", "hp": 18, "strength": 2, \
  49.         "dext": 6, "perception": 8, "ca": 0, "armure": 2, "arme": 'arme1', \
  50.         "niveau": 1, "xp": 0, "description": "un elf franchement éfféminé", "Coord_x": 50, "Coord_y": 50}, \
  51.         }
  52.  
  53.     def __init__(self, nom = "lambda", race = "humain", hp = 10, strength = 3, \
  54.     dext = 3, perception = 3, ca = 0, armure = 0, arme = "arme0", niveau = 1, xp = 0, \
  55.     description = "un humain", Coord_x = 0, Coord_y = 0):
  56.         self.nom = nom                 # Nom du personnage
  57.         self.race = race               # voir list.creatures() - A faire
  58.         self.hp = hp                   # Points de vie
  59.         self.strength = strength       # Force
  60.         self.dext = dext               # Dextérité
  61.         self.perception = perception   # Perception
  62.         self.ca = ca                   # sera calculé avec calcul_ca()
  63.         self.armure = armure           # Armure - A faire
  64.         self.arme = arme               # voir table_armes() de Item() A refaire
  65.         self.niveau = niveau           # A FAIRE
  66.         self.xp = xp                   # A FAIRE
  67.         self.description = description # utilisé lors de print divers (à voir)
  68.         self.Coord_x = Coord_x         # Coordonnées du perso - A voir pour les créatures
  69.         self.Coord_y = Coord_y         # Coordonnées du perso
  70.         # chargemment des personnages via pickle -- A FAIRE
  71.         #nom de la créature : {race,HP,Strength,Dextérité, Percéption,CA,Armure,Arme,niveau,XP,Decription, X, Y}
  72.  
  73.     def calcul_ca(self):
  74.         "Calculer la Classe d'Armure d'un personnage''"
  75.         # D20 : Permet de calculer la CA (classe d'armure)
  76.         # Sera utilisé pour déterminer quelle puissance est nécessaire pour porter un coup
  77.         # 10 + Armure + Dextérité
  78.         self.ca = 10 + self.armure + self.dext
  79.         print "%s CA : %s" % (self.nom, self.ca)
  80.  
  81.     def donne_xp(self, ennemi_niveau):
  82.         # Ajoute de l'expérience au personnage - A FAIRE
  83.         #niveau = 500 * niveau * (niveau + 1)
  84.         pass
  85.  
  86.     def niveau_sup(self):
  87.         #Fait monter le personnage d'un niveau - A FAIRE
  88.         self.table_xp = {1: 0, 2: 100, 3: 500}
  89.         pass
  90.  
  91.     def deplacement(self):
  92.         pass
  93.  
  94.     def creation_perso_rapide(self, nom):
  95.         "Créér un personnage à partir de liste_creatures()"
  96.         # on lui donne les caractéristiques de liste_creatures{}:
  97.         # - Ajuster selon le niveau du joueur -- A FAIRE
  98.         self.nom = nom
  99.         self.race = self.liste_creatures[nom]["race"]
  100.         self.hp = self.liste_creatures[nom]["hp"]
  101.         self.strength = self.liste_creatures[nom]["strength"]
  102.         self.dext = self.liste_creatures[nom]["dext"]
  103.         self.perception = self.liste_creatures[nom]["perception"]
  104.         self.ca = self.liste_creatures[nom]["ca"]
  105.         self.armure = self.liste_creatures[nom]["armure"]
  106.         self.arme = self.liste_creatures[nom]["arme"]
  107.         self.niveau = self.liste_creatures[nom]["niveau"]
  108.         self.xp = self.liste_creatures[nom]["xp"]
  109.         self.description = self.liste_creatures[nom]["description"]
  110.         self.Coord_x = self.liste_creatures[nom]["Coord_x"]
  111.         self.Coord_y = self.liste_creatures[nom]["Coord_y"]
  112.         #  A supprimer
  113.         print "%s est apparu dans le monde" % (self.liste_creatures[nom]["description"])
  114.  
  115.     def creation_perso_assistant(self):
  116.         # A voir, surement renommé et utilisé pour le changement de niveau (donc changement de caractéristiques)
  117.         pass
  118.  
  119.  
  120. class Item:
  121.     "A revoir, la logique etc"
  122.     def __init__(self):
  123.         self.table_armes = { \
  124.         'arme0': {'Nom': 'Mains nues', 'description': 'de poing', 'Poids': 0, 'Degats': 3, 'Cpt_privi': 'strength'}, \
  125.         'arme1': {'Nom': 'Dague', 'description': 'de dague', 'Poids': 500, 'Degats': 10, 'Cpt_privi': 'dext'}, \
  126.         'arme2': {'Nom': 'Rapière', 'description': 'de rapière', 'Poids': 1500, 'Degats': 20, 'Cpt_privi': 'strength'}, \
  127.         'arme3': {'Nom': 'Hache', 'description': 'de hache', 'Poids': 3000, 'Degats': 30, 'Cpt_privi': 'strength'}, \
  128.         'arme4': {'Nom': 'Défenses', 'description': 'de défenses', 'Poids': 0, 'Degats': 15, 'Cpt_privi': 'strength'}, \
  129.         'arme5': {'Nom': 'Canines', 'description': 'de canines', 'Poids': 0, 'Degats': 20, 'Cpt_privi': 'dext'} \
  130.         }
  131.  
  132.     def donne_arme(self, perso, arme_id):
  133.         "Donne une arme au personnage - A travailler"
  134.         perso.arme = self.table_armes[arme_id]
  135.  
  136.     def description_arme(self, arme_id):
  137.         "Information concernant une arme - A travailler"
  138.         print "Arme : %s" % (self.table_armes[arme_id]['Nom'])
  139.         print "description : %s" % (self.table_armes[arme_id]['description'])
  140.         print "Poids : %d %s" % (self.table_armes[arme_id]['Poids'], "Gr")
  141.         print "Dégats : 1d%d" % (self.table_armes[arme_id]['Degats'])
  142.         print "Compétance à privilégier : %s" % (self.table_armes[arme_id]['Cpt_privi'])
  143.  
  144.  
  145. class Duel:
  146.     "Duel entre deux perso"
  147.     def __init__(self):
  148.         self.initiative = False
  149.  
  150.     def calcul_init(self, perso1, perso2):  # Calcul d'initiative'
  151.         # D20 : dext + jet 1d20
  152.         jet_perso1 = perso1.dext + random.randrange(1, 20)
  153.         jet_perso2 = perso2.dext + random.randrange(1, 20)
  154.         # un peu de texte histoire de décrire (pas certain que ce soit une bonne idée de placer ça là)
  155.         print "%s : %d dext" % (perso1.nom, perso1.dext)
  156.         print "    > le jet de dés donne une initiative de %s pour %s" %\
  157.         (jet_perso1, perso1.nom)
  158.         print "%s : %d dext" % (perso2.nom, perso2.dext)
  159.         print "    > le jet de dés donne une initiative de %s pour %s" % (jet_perso2, perso2.nom)
  160.         if jet_perso1 >= jet_perso2:
  161.             print "%s attaque le premier" % perso1.nom
  162.             self.initiative = False  # on bascule le switch pour déterminé qui a l'initiative (voir stdr_fight())
  163.         else:
  164.             print "%s attaque le premier" % (perso2.nom)
  165.             self.initiative = True
  166.  
  167.     def stdr_fight(self, perso1, perso2):
  168.         "Le combat en lui même"
  169.         # Tant que l'un des personnages est en vie
  170.         while (perso1.hp > 0) and (perso2.hp > 0):
  171.             time.sleep(1)  # marque un temps de pause entre les pseudos tours
  172.             print "_____________________________________________"
  173.             # on vérifie le switch initiative pour savoir qui attaque
  174.             if self.initiative == False:
  175.                 self.attaque(perso1, perso2)
  176.                 self.initiative = True  # on bascule le switch, permet au second perso d'attaquer
  177.             else:
  178.                 self.attaque(perso2, perso1)
  179.                 self.initiative = False
  180.             if (perso1.hp <= 0):  # si l'un des perso n'a plus de points de vie
  181.                 self.victoire(perso2, perso1)  # on lance victoire()
  182.             elif (perso2.hp <= 0):
  183.                 self.victoire(perso1, perso2)
  184.  
  185.     def attaque(self, attaquant, defenseur):
  186.         "Permet de déterminé si le coup porte"
  187.         puiss_attaqu = 0  # variable qui contient la puissance de l'attaque
  188.         print "%s donne un coup %s à %s" % (attaquant.nom, attaquant.arme['description'], defenseur.nom, )
  189.         #  On calcul l'attaque via jet_attaque()
  190.         puiss_attaqu = self.jet_attaque(attaquant)
  191.         # on vérifie que la CA est dépassée par l'attaque (puiss_attaqu)
  192.         if puiss_attaqu >= defenseur.ca:
  193.             #  Puis on retire les pts de vie selon le calcul effectué par jet_degat()
  194.             defenseur.hp -= self.jet_degats(attaquant)
  195.             if defenseur.hp > 0:  # si le def est en vie
  196.                 print "    > %s perd %d points de vie. %d restants" %\
  197.                 (defenseur.nom, puiss_attaqu, defenseur.hp)
  198.             else:  # Si non, on change le message en indiquant la mort du perso
  199.                 print "    > %s perd %d points de vie et s'écroule sur le sol" % (defenseur.nom, puiss_attaqu)
  200.         else:  # dans le cas ou le coup porté manque la cible (cad si puiss_attaqu < defenseur.ca)
  201.             print "    > Le coup manque la cible. Jet d'attaque : %d |" \
  202.             " CA de la cible : %d" % (puiss_attaqu, defenseur.ca)
  203.  
  204.     def jet_attaque(self, perso):
  205.         # Calcul du jet d'attaque
  206.         # ~D20 : 1d20 + force + dextérité
  207.         return random.randrange(1, 20) + perso.strength + perso.dext
  208.  
  209.     def jet_degats(self, perso):
  210.         # Calcul du jet de dégats
  211.         # ~D20 : dégats = Degats(1,?) + Cpt_privi + Poids(poids_conv())
  212.         # ---------------------------solution temporaire au bonus Cpt_privi
  213.         perso_cpt = perso.arme['Cpt_privi']
  214.         if perso.arme['Cpt_privi'] == 'dext':
  215.             perso_cpt = perso.dext
  216.         else:
  217.             perso_cpt = perso.strength
  218.         # ---------------------------/solution temporaire au bonus  Cpt_privi
  219.         return random.randrange(1, perso.arme['Degats']) + perso_cpt +\
  220.         self.poids_conv(perso.arme['Poids'])
  221.  
  222.     def poids_conv(self, poids):
  223.         "Tableau de conversion poids-Malus/Bonus"
  224.         table_poids = {0: 0, 500: +1, 1500: -2, 3000: -4}
  225.         return table_poids[poids]
  226.  
  227.     def victoire(self, vainqueur, perdant):
  228.         "Fin du duel, distribution de l'xp et gain de niveau'"
  229.         # voir Perso.donne_xp() et Perso.niveau_sup():
  230.         print "__________________Fin du duel_________________"
  231.         # Simple message indiquant le gagnant
  232.         print "%s remporte le combat" % (vainqueur.nom)
  233.         print "%s a %d points de vie restants" % (vainqueur.nom, vainqueur.hp)
  234.  
  235.  
  236. class Rencontre_aleatoire():
  237.     "Rencontre aléatoire avec une créature choisie selon le lieu"
  238.         # On récupère les infos via pickle - A FAIRE
  239.         # -- Comment est construit le dict "lieux" : --
  240.         # Dict1 : chaque lieu est référencé de la sorte Lieu1, Lieu2 etc
  241.         # Chaque Lieu contient un dict,
  242.         #    entrée Nom = Nom du lieu
  243.         #    entrée description = La descriptionription du lieu (pas encore utilisée)
  244.         #    entrée Monstres = contient un tuple
  245.         #chaque item du tuple contient une liste elle même ayant 2 items
  246.         # item 0 = Nom de la créature, permet de renvoyer à la liste des attributs, pour le combat
  247.         # item 1 = le poids du montsre, utilisé pour calculer la prob de renctr, voir calcul_rencontre()
  248.         # "Coord_x": x, "Coord_y": y, "Rayon":10 = Localisation et taille de la zone décrite.
  249.         #... parait un peu lourd, pas mieux pour le moment
  250.     lieux = {\
  251.         "Lieu1": {"Nom": "Plaine", "description": "une plaine verdoyante", \
  252.         "Monstres": [("Sanglier", 5), ("Orc", 4), ("Elf franchement éfféminé",1)], \
  253.         "Coord_x": 0, "Coord_y": 0, "Rayon": 30},\
  254.         #-----------
  255.         "Lieu2": {"Nom": "Forêt", "description": "une forêt", "Monstres": [("Squelette", 2), ("Sanglier", 5), ("Orc", 4)], \
  256.         "Coord_x": 20, "Coord_y": 70, "Rayon": 20},\
  257.         #-----------
  258.         "Lieu3": {"Nom": "Marai", "description": "un marai humide", "Monstres": [("Squelette", 6), ("Vampire", 3)], \
  259.         "Coord_x": 75, "Coord_y": 150, "Rayon": 64},\
  260.         #-----------
  261.         "Lieu4": {"Nom": "Village en ruine", "description": "un village en ruine", "Monstres": [("Squelette", 2), ("Sanglier", 1), ("Orc", 5)], \
  262.         "Coord_x": 40, "Coord_y": 40, "Rayon": 10},\
  263.         }
  264.  
  265.     def aff_infos_lieu(self, lieu):
  266.         "affiche simplement les détails concernant le lieu, et les rencontres possibles"
  267.         # voir le problème d'encodage avec espaces/accents
  268.         print "Lieu : %s" % (lieu)
  269.         print self.lieux[lieu]["Nom"]
  270.         print self.lieux[lieu]["Monstres"]
  271.  
  272.     def calcul_rencontre(self, nom_perso, lieu, objet):
  273.         "Sélectionne un objet ou une créature aléatoirement, selon le lieu"
  274.         # "lieu" correspond à un des lieux de lieux[] dans Rencontre_aleatoire(), objet désigne soit "Monstres" (voir liste_creatures dans Perso())
  275.         # soit un type de lieu "emplacement"(voir lieux [] dans Rencontre_aleatoire() (A FAIRE... ou pas)
  276.         # nom_perso sera utilisé pour créer un ennemi de niveau équivalent (ou presque) au perso -- A FAIRE
  277.         # Permet de sortir une créature au hasard selon son poids (voir lieux[])
  278.         # afficher le poids...................self.lieux[lieu]["Monstres"][x][1]
  279.         # afficher le nom de la créature......self.lieux[lieu]["Monstres"][x][0]
  280.         # afficher tous les monstres et poids.self.lieux[lieu]["Monstres"]
  281.         self.total = 0  # contiendra le total des poids
  282.         self.liste_poids = []  # liste contenant LES totaux des poids
  283.         for i in self.lieux[lieu][objet]:  # On récupère les poids des créatures
  284.             self.total += i[1]  # on ajoute le poids sélectionné au total
  285.             self.liste_poids.append(self.total)  # on append le total en cours à la liste
  286. #---------------------------------------- v Bien meilleur méthode a étudier, OK
  287.         alea = random.random() * self.liste_poids[-1]
  288.         i = bisect.bisect_right(self.liste_poids, alea)
  289.         #print "%s rencontre %s dans %s" % (nom_perso, \
  290.         #self.lieux[lieu]["Monstres"][i][0], self.lieux[lieu]["Nom"])
  291.         return self.lieux[lieu][objet][i][0] # renvoit le monstre à créer -- Voir pour selec équipement et niveau
  292.  
  293.     def localisation_perso(self, perso):
  294.         "Permet de déterminer, selon les coordonnées du personnages, dans quelle zone il se trouve'"
  295.         for i in self.lieux:
  296.             distance = sqrt((self.lieux[i]["Coord_x"] - perso.Coord_x) ** 2 + (self.lieux[i]["Coord_y"] - perso.Coord_y) ** 2)
  297.             if distance <= self.lieux[i]["Rayon"]:
  298.                 # print self.lieux[i]["Nom"]
  299.                 return i
  300.                 break
  301.  
  302.     def test_rencontre(self, perso):
  303.         "Lance un test de rencontre, détermine si lors d'un déplacement 'le personnage fait une rencontre aléa"
  304.         lieu = self.localisation_perso(perso)
  305.         if lieu is not None:  # Si le perso se trouve dans une zone déterminée dans lieux()
  306.             if (random.randrange(1, 6)) >= 4:  # On lance test de rencontre prenant en compte les apptitudes du perso - A Faire, intervenir compétences du perso ici
  307.                 # On créé une ennemi selon le lieu dans lequel se trouve le perso
  308.                 # calcul_rencontre = chercher dans le liste des montsres du lieu
  309.                 ennemi = Perso()
  310.                 # on créé notre créature
  311.                 ennemi.creation_perso_rapide(self.calcul_rencontre("Selon niveau perso1 -- A Faire", lieu, "Monstres"))
  312.                 crea_item.donne_arme(ennemi, ennemi.arme)  # On lui donne son arme - Revoir Item()
  313.                 print "Le jet de dés donne une mauvaise rencontre pour %s" % (perso.nom)
  314.                 # Puis on calcul la CA des personnages
  315.                 perso.calcul_ca()
  316.                 ennemi.calcul_ca()
  317.                 # Puis on lance le combat
  318.                 cmb = Duel()
  319.                 cmb.calcul_init(perso, ennemi)
  320.                 cmb.stdr_fight(perso, ennemi)
  321.             else:
  322.                 print "%s a évité une mauvaise rencontre" % (perso.nom)
  323.         else:
  324.             print "%s n'a fait aucune rencontre" % (perso.nom)
  325.  
  326.     def voir_carte_zone(self):  # A supprimer,
  327.         "Affiche une réprésentation des zones et localisation perso"
  328.         for i in self.lieux:
  329.             # Turtle Zones- A SUpprimer
  330.             turtle.penup()
  331.             turtle.setpos(self.lieux[i]["Coord_x"], (self.lieux[i]["Coord_y"] - self.lieux[i]["Rayon"]))
  332.             turtle.pendown()
  333.             turtle.circle(self.lieux[i]["Rayon"])
  334.             turtle.write(self.lieux[i]["Nom"])
  335.             # / Turtle - A SUpprimer
  336.         turtle.penup()
  337.         turtle.goto(0, 0)
  338.  
  339.     def voir_pos_perso(self, perso):
  340.         "Affiche sur la carte la position du perso"
  341.         # Turtle Perso- A SUpprimer
  342.         turtle.penup()
  343.         turtle.setx(perso.Coord_x)
  344.         turtle.sety(perso.Coord_y)
  345.         turtle.pendown()
  346.         turtle.dot(4, "red")
  347.         turtle.write(perso.nom)
  348.         # / Turtle - A SUpprimer
  349.  
  350. # personnages
  351. perso1 = Perso()
  352. perso2 = Perso()
  353. perso3 = Perso()
  354.  
  355. crea_item = Item()  # Revoir tout le système d'items, pas satisfaisant
  356. aventure = Rencontre_aleatoire()
  357.  
  358. perso1.creation_perso_rapide("Gerald de Rive")  # On récupère le personnage
  359. crea_item.donne_arme(perso1, "arme2")  # On lui donne une arme - A revoir
  360.  
  361. perso2.creation_perso_rapide("Perceval")
  362. crea_item.donne_arme(perso2, "arme2")
  363.  
  364. perso3.creation_perso_rapide("Karadoc")
  365. crea_item.donne_arme(perso3, "arme3")
  366.  
  367.  
  368. aventure.voir_carte_zone()  # Visualiser la carte - A SUPPRIMER
  369.  
  370. aventure.voir_pos_perso(perso1)  # Affiche la position du perso - A SUPPRIMER
  371. aventure.voir_pos_perso(perso2)
  372. aventure.voir_pos_perso(perso3)
  373.  
  374. aventure.test_rencontre(perso1)  # On lance le test d'une rencontre aléatoire'
  375. aventure.test_rencontre(perso2)
  376. aventure.test_rencontre(perso3)
  377.  
  378. turtle.getscreen()._root.mainloop()  # A surrprimer
Advertisement
Add Comment
Please, Sign In to add comment