def trouver_navires(visible, personnage, portee, precision, exceptions=None): """Cherche les navires autour du personnage.""" exceptions = exceptions or {} navire = personnage.salle.navire etendue = navire.etendue altitude = etendue.altitude nav_direction = navire.direction.direction pos_coords = personnage.salle.coords.tuple() x, y, z = pos_coords position = Vector(x, y, altitude) navires = [n for n in importeur.navigation.navires.values() if \ n.etendue and mag(n.position.x, n.position.y, altitude, position.x, position.y, altitude) - \ n.get_max_distance_au_centre() <= portee] for t_navire in navires: # On détermine la salle la plus proche t_salles = [s for s in t_navire.salles.values() if \ s.coords.z == 0 and s.coords.valide] for t_salle in t_salles: # Calcul de la distance entre salle et t_salle t_coords = t_salle.coords.tuple() t_x, t_y, t_z = t_coords distance = mag(x, y, 0, t_x, t_y, 0) v_point = Vector(t_x, t_y, altitude) v_dist = v_point - position direction = get_direction(v_dist) r_direction = (direction - nav_direction) % 360 # On détermine l'angle minimum fonction de la précision angle = norme_angle(round(r_direction / precision) * precision) if distance <= portee: visible.entrer_point(angle, v_dist, t_navire, nav_direction, precision, exceptions=exceptions)
def testMag01(self): z = (v.mag(self.x), v.mag(self.y), v.mag(self.z)) e = (1.0, ) * 3 self.assertSequenceEqual(e, z) del e del z
def intersect(ls1, ls2, Debug=False): p = ls1.start() q = ls2.start() r = ls1.dvec() s = ls2.dvec() numu = vector.cross((q - p), r) den = vector.cross(r, s) if Debug: print('p:', p) print('q:', q) print('r:', r) print('s:', s) print('(q-p)xr = ', numu) print('rxs = ', den) psect = vector.vector([None] * p.size()) intersected = False if vector.mag(den) < 1e-10: if vector.mag(numu) < 1e-10: # Colinear pass else: # Parallel and non-intersecting pass else: numt = vector.cross((q - p), s) t = numt / den u = numu / den if Debug: print('t:', t) print('u:', u) if (u >= 0 and u <= 1) and (t >= 0 and t <= 1): pintt = p + r * t pintu = q + s * u if Debug: print('p+rxt =', pintt) print('q+sxu =', pintu) if vector.mag(pintt - pintu) < 1e-10: psect = pintt intersected = True else: # Two lines are not parallel but do not intersected pass return intersected, psect
def update(self, delta, view): super(Boss, self).update(delta) if self.rect.colliderect(view): if not self.active: self.active = True self.sound_announce.play() if self.idle > 0: self.idle -= delta else: if self.whirl: v = (self.target.centerx - self.rect.centerx, self.target.centery - self.rect.centery) mag = vector.mag(v) if mag < 300 * delta: self.rect.center = self.target.center self.whirl = False self.target = None self.idle = self.__whirlsecs self.charging = False else: v = vector.muls(vector.divs(v, vector.mag(v)), 300 * delta) self.move(v) else: if self.charging: self.move((0, self.__charge_speed * delta)) self.rect.bottom = min(self.rect.bottom, view.bottom) if self.rect.bottom == view.bottom: self.charging = False self.set_animation(self.sprite_swim, 4) elif self.target: v = (self.target.centerx - self.rect.centerx, self.target.centery - self.rect.centery) mag = vector.mag(v) if mag < self.__speed * delta: self.rect.center = self.target.center self.set_animation(self.sprite_swim, 4) self.target = None else: v = vector.muls(vector.divs(v, vector.mag(v)), self.__speed * delta) self.move(v) else: if random.random() < self.__charge_chance: self.charging = True self.set_animation(self.sprite_charge, 4) self.sound_charge.play() else: self.target = pygame.Rect((self.rect.left + random.randint(-self.__range, self.__range), self.rect.top + random.randint(-self.__range, self.__range)), (137, 274)) self.target.left = max(self.target.left, 144) self.target.right = min(self.target.right, 768 - 144) self.target.top = max(self.target.top, view.top) self.target.bottom = min(self.target.bottom, view.top + (864 * 0.75))
def update(self, delta, view): """Updates Location""" super(Guppy, self).update(delta) # Move based on School if self.whirl: v = (self.target.centerx - self.rect.centerx, self.target.centery - self.rect.centery) mag = vector.mag(v) if mag < 300 * delta: self.rect.center = self.target.center else: v = vector.muls(vector.divs(v, vector.mag(v)), 300 * delta) self.move(v) else: self.rect.center = vector.add(self.rect.center, vector.muls(self.velocity, delta))
def drag(self): drag = vector.normalize(self.vel) drag *= -1 speed = vector.mag(self.vel) drag = vector.withMag(drag, env.DRAG_FORCE * speed * speed) self.applyForce(drag)
def distance_au_centre(self, salle): """Retourne la distance de salle au centre de la perturbation""" x1 = salle.coords.x x2 = self.centre.x y1 = salle.coords.y y2 = self.centre.y return ceil(mag(x1, y1, 0, x2, y2, 0))
def valider(self, personnage, dic_masques): """Validation du masque""" Masque.valider(self, personnage, dic_masques) nom = self.a_interpreter salle = personnage.salle x, y, z = salle.coords.tuple() etendue = salle.etendue if not etendue: raise ErreurValidation( "Il n'y a pas de navires suffisamment proches.") navires = list(importeur.navigation.navires.values()) navires = [n for n in navires if n.etendue is etendue and \ contient(n.desc_survol, nom)] navires = [n for n in navires if mag(n.position.x, n.position.y, n.position.z, x, y, z) < 15] if not navires: raise ErreurValidation( "Ce navire est introuvable.") navire = navires[0] self.nom_navire = navire.nom self.navire = navire return True
def separation(self, list): mean = (0.0, 0.0) for i in list: dist = vector.mag(vector.sub(self.rect.center, i.rect.center)) if dist > 0 and dist < self.__separation_limit: mean = vector.add(mean, vector.divs(vector.sub(self.rect.center, i.rect.center), dist)) return vector.divs(mean, len(list))
def enemies_on_range(self): on_range = [] for enemy in self.terrain.enemy_group: distance_vector = vector.distance(enemy.origin, self.origin) mag = vector.mag(distance_vector) if mag < self.range + enemy.radius: on_range.append(enemy) return on_range
def onseg(self, p, Debug=False): ltot = self.mag() lps = vector.mag(p - self.vs) lep = vector.mag(self.ve - p) diff = ltot - (lps + lep) if Debug: print('Total length: ', ltot) print('s-p length: ', lps) print('p-t length: ', lep) print('diff : ', diff) if vector.mag(diff) < 1e-10: return True else: return False
def getarea(self): sumA = 0.0 for i in range(0, self.totalSize()-2): v1 = self.pts[i+1] - self.pts[0] v2 = self.pts[i+2] - self.pts[0] sumA += 0.5*vector.mag(vector.cross(v1, v2)) return sumA
def choisir_matelots(self, exception=None): """Retourne le matelot le plus apte à accomplir la volonté.""" navire = self.navire adverse = self.adverse matelots = navire.equipage.get_matelots_au_poste("sabreur", endurance_min=30, exception=exception) graph = self.navire.graph sabreurs = [] # Détermine la salle la plus proche distance = None choisie = None for salle in navire.salles.values(): t_mag = mag(salle.coords.x, salle.coords.y, 0, adverse.position.x, adverse.position.y, 0) if distance is None or t_mag < distance: distance = t_mag choisie = salle # Maintenant, détermine la salle de l'adversaire la plus proche distance = None adv_choisie = None for salle in adverse.salles.values(): t_mag = mag(salle.coords.x, salle.coords.y, 0, choisie.coords.x, choisie.coords.y, 0) if distance is None or t_mag < distance: distance = t_mag adv_choisie = salle # Enfin, cherche la salle de transition des sabreurs for matelot in matelots: origine = matelot.salle.mnemonic destination = choisie.mnemonic if origine == destination: sabreurs.append((matelot, [], adv_choisie)) else: chemin = graph.get((origine, destination)) if chemin: sabreurs.append((matelot, chemin, adv_choisie)) return sabreurs
def choisir_matelots(self, exception=None): """Retourne le matelot le plus apte à accomplir la volonté.""" navire = self.navire adverse = self.adverse matelots = navire.equipage.get_matelots_au_poste( "sabreur", endurance_min=30, exception=exception) graph = self.navire.graph sabreurs = [] # Détermine la salle la plus proche distance = None choisie = None for salle in navire.salles.values(): t_mag = mag(salle.coords.x, salle.coords.y, 0, adverse.position.x, adverse.position.y, 0) if distance is None or t_mag < distance: distance = t_mag choisie = salle # Maintenant, détermine la salle de l'adversaire la plus proche distance = None adv_choisie = None for salle in adverse.salles.values(): t_mag = mag(salle.coords.x, salle.coords.y, 0, choisie.coords.x, choisie.coords.y, 0) if distance is None or t_mag < distance: distance = t_mag adv_choisie = salle # Enfin, cherche la salle de transition des sabreurs for matelot in matelots: origine = matelot.salle.mnemonic destination = choisie.mnemonic if origine == destination: sabreurs.append((matelot, [], adv_choisie)) else: chemin = graph.get((origine, destination)) if chemin: sabreurs.append((matelot, chemin, adv_choisie)) return sabreurs
def rate(self, list): mean = (0, 0) for i in list: mean = vector.add(mean, i.velocity) mean = vector.divs(mean, len(list)) meandist = vector.mag(mean) if meandist > self.__force_max: mean = vector.muls(vector.divs(mean, meandist), self.__force_max) return mean
def steer(self, v): diff = vector.sub(v, self.rect.center) dist = vector.mag(diff) if dist > 0: diff = vector.divs(diff, dist) damp = 64.0 if dist < damp: diff = vector.muls(diff, self.__velocity_max * (dist / damp)) else: diff = vector.muls(diff, self.__velocity_max) vec = vector.sub(diff, self.velocity) vecdist = vector.mag(vec) if vecdist > self.__force_max: vec = vector.muls(vector.divs(vec, vecdist), self.__force_max) else: vec = (0, 0) return vec
def slope(self, pos, ref_planet): total = [0, 0] # Tracks the total acceleration on the planet for planet in self.planet_list: if (ref_planet != planet): # Uses Newton's Law of Universial Gravitation to find the component of acceleration caused by each other planet in the system total = vector.add( total, vector.scalarMult( vector.sub(planet.nextpos, pos), (planet.mass / pow(vector.mag(vector.sub(planet.nextpos, pos)), 3)))) return (vector.scalarMult(total, G))
def update(self, delta, view): super(Fish, self).update(delta) # Only drift if on screen #if self.rect.colliderect(view): # self.rect.top += self.__drift_speed * delta #if whirlpool hits do not allow fish to target salmon if self.target == None: self.move((0, self.__drift_speed * delta)) else: if not self.whirl: self.move((self.__velocity[0] * delta, self.__velocity[1] * delta )) else: v = (self.target.centerx - self.rect.centerx, self.target.centery - self.rect.centery) mag = vector.mag(v) if mag < 300 * delta: self.rect.center = self.target.center else: v = vector.muls(vector.divs(v, vector.mag(v)), 300 * delta) self.move(v)
def main(): vec_1 = [random(), random(), random()] vec_2 = [random(), random(), random()] vec_3 = [random(), random(), random()] #creates 3 random numerical lists print("v_1 = {0}, |v_1| = {1}".format(vec_1, v.mag(vec_1))) print("\nv_2 = {0}, |v_2| = {1}".format(vec_2, v.mag(vec_2))) print("\nv_3 = {0}, |v_3| = {1}".format(vec_3, v.mag(vec_3))) #prints our vectors and their norms print("\nv_1 + v_2 = {0}".format(v.vec_sum(vec_1, vec_2))) print("\nv_1 . v_2 = {0}".format(v.vec_dot(vec_1, vec_2))) print("\nv_1 x v_2 = {0}".format(v.vec_cross(vec_1, vec_2))) #prints out the sum, inner, and cross products respectively of v_1 and v_2 print("\n\n---Testing Identities---\n\n") print("First Identity:") print("v_1 x v_2 = {0}".format(v.vec_cross(vec_1, vec_2))) print("\n-v_2 x v_1 = {0}".format( v.vec_diff([0, 0, 0], v.vec_cross(vec_2, vec_1)))) #prints out identities print("\n\nSecond Identity:") print("v_1 x (v_2 + v_3) = {0}".format( v.vec_cross(vec_1, v.vec_sum(vec_2, vec_3)))) print("\n(v_1 x v_2) + (v_1 x v_3) = {0}".format( v.vec_sum(v.vec_cross(vec_1, vec_2), v.vec_cross(vec_1, vec_3)))) #prints out identities print("\nThird Identity:") print("v_1 x (v_2 x v_3) = {0}".format( v.vec_cross(vec_1, v.vec_cross(vec_2, vec_3)))) print("\n(v_1 . v_3)v_2 - (v_1 . v_2)v_3 = {0}".format( v.vec_diff(v.vec_mult(vec_2, v.vec_dot(vec_1, vec_3)), v.vec_mult(vec_3, v.vec_dot(vec_1, vec_2)))))
def update(self, delta, view): super(Catfish, self).update(delta) if self.rect.colliderect(view): if self.whirl: v = (self.target.centerx - self.rect.centerx, self.target.centery - self.rect.centery) mag = vector.mag(v) if mag < 300 * delta: self.rect.center = self.target.center else: v = vector.muls(vector.divs(v, vector.mag(v)), 300 * delta) self.move(v) else: if self.bound.colliderect(self.target): if self.rect.centerx < self.target.centerx: self.move((self.__chase_speed * delta, 0)) self.rect.centerx = min(self.rect.centerx, self.target.centerx) self.rect.right = min(self.rect.right, self.bound.right) elif self.rect.centerx > self.target.centerx: self.move((-self.__chase_speed * delta, 0)) self.rect.centerx = max(self.rect.centerx, self.target.centerx) self.rect.left = max(self.rect.left, self.bound.left) self.move(vector.muls(self.__velocity, delta))
def iselem(v, vl): chk = 1e-20 if isinstance(vl, list): for e in vl: chk = vector.mag(v - e) if chk<1e-10: return True else: dv = v-vl chk = np.sqrt(dv*dv) if chk<1e-10: return True return False
def envoyer_orbe(self, auteur, destinataire, orbe, message, ajout=""): """Envoie et brouille le message en fonction de la distance.""" s_auteur = auteur.salle s_destinataire = getattr(destinataire, "salle", destinataire) if s_auteur.coords.valide and s_destinataire.coords.valide: distance = mag(s_auteur.coords.x, s_auteur.coords.y, s_auteur.coords.z, s_destinataire.coords.x, s_destinataire.coords.y, s_destinataire.coords.z) else: distance = 20 # En fonction de la distance, essaye de prélever de la mana mana = int(round(distance / 2)) if mana < 10: mana = 10 elif mana > 100: mana = 100 try: auteur.stats.mana -= mana except DepassementStat: # Brouille le message taux = distance / 400 if taux < 0.02: taux = 0.02 elif taux > 0.3: taux = 0.3 for i, car in enumerate(message): if random() < taux: message = message[:i] + "?" + message[i + 1:] # Enfin, on fait attendre le message en fonction de la distance temps = distance / 100 if temps < 1: temps = 1 importeur.communication.enregistrer_conversation( "|jn|orbe|ff|", destinataire, auteur, message) message = "|jn|[Orbe {}] dit {}: {}|ff|".format( orbe.nom_orbe, ajout, message) importeur.diffact.ajouter_action("orbe_{}".format(str(id(message))), temps, destinataire.envoyer, message)
def envoyer_orbe(self, auteur, destinataire, orbe, message, ajout=""): """Envoie et brouille le message en fonction de la distance.""" s_auteur = auteur.salle s_destinataire = getattr(destinataire, "salle", destinataire) if s_auteur.coords.valide and s_destinataire.coords.valide: distance = mag(s_auteur.coords.x, s_auteur.coords.y, s_auteur.coords.z, s_destinataire.coords.x, s_destinataire.coords.y, s_destinataire.coords.z) else: distance = 20 # En fonction de la distance, essaye de prélever de la mana mana = int(round(distance / 2)) if mana < 10: mana = 10 elif mana > 100: mana = 100 try: auteur.stats.mana -= mana except DepassementStat: # Brouille le message taux = distance / 400 if taux < 0.02: taux = 0.02 elif taux > 0.3: taux = 0.3 for i, car in enumerate(message): if random() < taux: message = message[:i] + "?" + message[i + 1:] # Enfin, on fait attendre le message en fonction de la distance temps = distance / 100 if temps < 1: temps = 1 importeur.communication.enregistrer_conversation("|jn|orbe|ff|", destinataire, auteur, message) message = "|jn|[Orbe {}] dit {}: {}|ff|".format(orbe.nom_orbe, ajout, message) importeur.diffact.ajouter_action("orbe_{}".format(str(id(message))), temps, destinataire.envoyer, message)
def get_etendues_proches(self, x, y, distance, exceptions=None): """Retourne les étendues liées à self suffisamment proches. Les apramètres à préciser sont : x -- l'âxe X du point de départ y -- l'âxe Y du point de départ distance -- la distance maximale du point de départ Les liens sont parcourus pour trouver les étendues proches. Si des étendues sont trouvées, la même recherche est effectuée récursivement dessus. """ exceptions = exceptions or set() exceptions.add(self) etendues = [self] for (bx, by), etendue in self.liens.items(): if mag(x, y, 0, bx, by, 0) <= distance: if etendue not in exceptions: etendues += etendue.get_etendues_proches( x, y, distance, exceptions) return etendues
def _check_inside(self, ps, pe): ldet = lineseg.lineseg(ps, pe) nsects = 0 psects = [] for l in self.ls: isectd, psect = lineseg.intersect(ldet, l) if isectd: append = False if len(psects)>0: for pchk in psects: chk = vector.mag(pchk - psect) if chk > 1e-10: append = True else: append = True if append: nsects += 1 psects.append(psect) return nsects
def executer(self): """Exécute l'ordre : essaye d'aborder.""" navire = self.navire matelot = self.matelot personnage = matelot.personnage salle = personnage.salle d_salle = self.salle navire = d_salle.navire if d_salle is personnage.salle: yield SignalInutile("le matelot a déjà abordé") if mag(salle.coords.x, salle.coords.y, 0, d_salle.coords.x, d_salle.coords.y, 0) > 2: yield SignalAbandonne("Ce navire est trop loin, capitaine !", True) matelot.armer() personnage.salle = d_salle personnage << "Vous sautez dans {}.".format( navire.desc_survol) personnage << salle.regarder(personnage) d_salle.envoyer("{{}} arrive en sautant depuis {}.".format( salle.titre.lower()), personnage) salle.envoyer("{{}} saute dans {}.".format( navire.nom), personnage) importeur.hook["personnage:deplacer"].executer( personnage, d_salle, None, 0) # On appelle les pnj.arrive des PNJs de la salle for perso in d_salle.personnages: if perso is not personnage and hasattr(perso, "script") and \ perso.peut_voir(personnage): importeur.hook["pnj:arrive"].executer(perso, personnage) yield SignalTermine()
def get_points_proches(self, x, y, distance, liens=True): """Retourne les points proches de la position indiquée. Paramètres à préciser : x -- la coordonnée X de la position y -- la coordonnée Y de la position distance -- la distance maximum des points recherchés liens -- recherche récursive dans les étendues liées """ proches = {} altitude = self.altitude etendues = [self] if liens: etendues = self.get_etendues_proches(x, y, distance) for etendue in etendues: points = etendue.obstacles.copy() points.update(etendue.cotes) for (bx, by), point in points.items(): if mag(x, y, altitude, bx, by, altitude) <= distance: proches[(bx, by)] = point return proches
def testMag01(self): z = (v.mag(self.x), v.mag(self.y), v.mag(self.z)) e = (1.0, ) * 3 [self.assertEqual(zk, ek) for zk, ek in zip(z, e)]
def mag(self): return vector.mag(self.dvec())
def apply_speed(self): movement = vector.times(self.speed, self.direction) new_pos = vector.plus(self.pos, movement) self.set_position(new_pos) self.distance_travelled += vector.mag(movement)
def intersectedArea(self, g, Debug=False): if not self.intersect(g): return -1 #--- search the pivot point ist = 0 poly = [] for i in range(0, self.size()): if g.inside(self.pts[i]): poly.append(self.pts[ist]) ist = i break lseg = lineseg.lineseg(self.pts[i], self.pts[i+1]) isectd, psect, iseg = g.intersect(lseg) if isectd: poly.append(psect) ist = i break #--- Walk along boundary of intersected area # cag : cell as geometry cag = geometry(self.points(False)) # Loop over the cell sides for i in range(ist+1, self.size()+1): p = self.pts[i] # f: a side of this cell f = lineseg.lineseg(self.pts[i-1], self.pts[i]) # Check if the side f intersect with given geometry g # isectd: boolean if g and f intersected or not # psect : intersected point # iseg : index of intersected segment of g isectd, psect, iseg = g.intersect(f) if isectd: # Check if psect has been added to poly already if not iselem(psect, poly): poly.append(psect) # Walk along the geometry g to find another intersect point of # this cell and g. The geometry points inbetween the two # intersected points are added to the poly for i in range(iseg+1, g.size()): pchk = g.pts[i] if cag.inside(pchk) and \ not iselem(pchk, poly): poly.append(pchk) if g.inside(p) and not iselem(p, poly): poly.append(p) if Debug: print('\nPoints in this poly:') for l in poly: print(l) # Estimate the area if len(poly) == 3: v1 = poly[1] - poly[0] v2 = poly[2] - poly[1] return 0.5*vector.mag(vector.cross(v1, v2)) else: sumA = 0.0 for i in range(0, len(poly)-2): v1 = poly[i+1] - poly[0] v2 = poly[i+2] - poly[0] sumA += 0.5*vector.mag(vector.cross(v1, v2)) return sumA
def distance(salle): x, y, z = salle.coords.tuple() return mag(x, y, z, o_x, o_y, o_z)
import vector from random import random as random vec_1 = [random(),random(),random()] vec_2 = [random(),random(),random()] vec_3 = [random(),random(),random()] print("v_1 = {0}, |v_1| = {1}".format(vec_1, vector.mag(vec_1))) print("v_2 = {0}, |v_2| = {1}".format(vec_2, vector.mag(vec_2))) print("v_3 = {0}, |v_3| = {1}".format(vec_3, vector.mag(vec_3))) print("\nv_1 + v_2 = {0}".format(vector.vec_sum(vec_1, vec_2))) print("\nv_1 . v_2 = {0}".format(vector.vec_dot(vec_1, vec_2))) print("\nv_1 x v_2 = {0}".format(vector.vec_cross(vec_1, vec_2))) print("\n\n---Testing Identities---\n\n")
def aim(self, enemy): distance_vector = vector.distance(enemy.origin, self.origin) mag = vector.mag(distance_vector) unit_vector = vector.times(1 / mag, distance_vector) return vector.times(self.bullet_speed, unit_vector)