Nos partenaires et nous-mêmes utilisons différentes technologies, telles que les cookies, pour personnaliser les contenus et les publicités, proposer des fonctionnalités sur les réseaux sociaux et analyser le trafic. Merci de cliquer sur le bouton ci-dessous pour donner votre accord. Vous pouvez changer d’avis et modifier vos choix à tout moment. Informations RGPD
/************************************************************************** *************************** FONCTIONS DIVERSES **************************** *************************************************************************** Ce fichier reprend diverses fonctions qui peuvent être utiles pour une IA Elles ne sont aucunement utiles seules, mais permettent de simplifier certains calculs dans des IA plus avancées. Regles générales: => Dans le cas ou une fonction prend des paramètres par adresse, cela sera mentionné dans le nom de la fonctions grace à "_adr" => les fonctions ont leurs propres sorties de debug, warning et erreurs. Les debug simples ne seront affichés que si vous mettez le booléen FUNCTIONS_DEBUG à true Voici les différents en-têtes des fonctions de ce fichier: //initialise toutes les variables nécessaires au bon fonctionnement des méthodes //de ce fichier (il est désormais inutile de l'appeller soi-même) Init_functions(); //appelable à chaque tour, cette fonction rafrachit différentes variables de calcul. //appeler cette fonction en début de tour est nécessaire pour certains algorithmes. refresh_functions(); //renvoie l'ennemi avec le moins de vie de l'équipe adverse getLowestLifeEnemy(); //retourne l'effet demandé parmi une liste d'effet //typiquement: getEffect(getChipEffect(CHIP_CURE), EFFECT_HEAL)[2]; //donnera le max de soins dela puce de soins getEffect(effects, effetVoulu); //retourne la vie totale actuelle de la team ennemie getTotalLifeAlliesTeam(); //retourne la vie totale actuelle de la team alliée getTotalLifeEnemyTeam(); //retourne la puissance d'une puce ou d'une arme utilisée sur une cible // les puces d'amélioration retournent actuellement le bonus qui sera appliqué à // la meilleure arme/puce qui correspond. Si vous comptez tirer plusieurs fois, //multipliez donc ce résultat! //ne prend pas en compte le taux d'échec //ne prend pas en compte les dégats/soins de zone, juste la puissance individuelle getPower(Cheap_Weapon, target); //retourne la moyenne des dégats d'une puce ou d'une arme getMeanDamage(weapon); //retourne la moyenne arithmétique entre 2 nombre mean(a, b); //utilise tous vos points de tour pour utiliser la puce/arme sur la cible spendTPWith(weap_chip, target); //retourne true si la puce est une puce aggressive isAggressiveChip(chip); //retourne toutes les puces aggressives équipées getAllAgressiveChip(); //retourne l'arme/puce la moins cher de la liste getCheapestCW(liste); //retourne le cout d'une puce ou d'une arme, indistinctement getCWCost(cw); //construit la meilleure combinaison d'arme possible pour toucher la cible en un nombre //de points de tour donné. buildBetterWeapons(tp, target); //retourne la case la plus proche ou on peut utiliser toutes les armes envoyées en //paramètre (en construction) function getCellToUseWeapons(weapons, target) //utilise toutes les armes envoyées en paramètre sur la cible (doublons possibles) useWeaponsOnTarget(weapons, target); //peut on utiliser l'arme cw depuis cell sur la cellule ct? canUseCWFrom(cw, cell, ct); //retourne toutes les puces qui ont l'effet concerné getChipsWithEffect(effect); //retourne le meilleur élément de tab grâce à l'évaluation par élément de fct evalueElements(tab, fct); */ //mettez cette variable à true pour afficher les messages de debug global FUNCTION_DEBUG = false; //déclaration des différentes variables: global functions_init = false; global functions_futurs_damage = []; global functions_futurs_damage_sum = 0; global functions_last_turn_life; /********************************************************************************* ********************************************************************************** FONCTIONS D INITIALISATION DES DIFFERENTES FONCIONNALITES ********************************************************************************** *********************************************************************************/ //initialise toutes les variables nécessaires au bon fonctionnement des méthodes //de ce fichier function Init_functions() { if (!functions_init) { if (FUNCTION_DEBUG) debug("*** Début de l'initialisation de <functions> ***"); functions_init = true; functions_last_turn_life = getLife(); if (FUNCTION_DEBUG) debug("*** Fin de l'initialisation de <functions> ***"); } } //appelable à chaque tour, cette fonction rafrachit différentes variables de calcul. //appeler cette fonction en début de tour est nécessaire pour certains algorithmes. function refresh_functions() { if (FUNCTION_DEBUG) debug("*** Début du rafraichissement de <functions> ***"); Init_functions(); analyse_danger(); functions_last_turn_life = getLife(); //functions_last_turn_life non utilisable en dehors du refresh donc! if (FUNCTION_DEBUG) debug("*** Fin du rafraichissement de <functions> ***"); } /********************************************************************************* ********************************************************************************** FONCTIONS UTILITAIRES BASIQUES ********************************************************************************** *********************************************************************************/ //renvoie l'ennemi avec le moins de vie de l'équipe adverse. Le booléen permet de choisir // si la fonction peut prendre les bulbes ou non function getLowestLifeEnemy(bulbes) { var enemies = getEnemies(); var res; for (var i in enemies) if (getLife(i)>0 && ((!bulbes && !isSummon(i)) || (bulbes))) res = i; for (var i in enemies) if (getLife(i)>0 && getLife(i) < getLife(res) && ((!bulbes && !isSummon(i)) || (bulbes))) res = i; return res; } //ajoute un élément en fin de tableau function arrayAppend_adr(@tab, element) { if (tab == null) { debugE("Votre tableau est null!"); return; } if (typeOf(tab) == TYPE_ARRAY) tab[count(tab)] = element; else debugE("Attention, le tableau envoyé en paramètre n'en est pas un. Vérifiez que vous l'avez bien initialisé au moyen de = []"); } //retourne l'effet demandé parmi une liste d'effet //typiquement: getEffect(getChipEffect(CHIP_CURE), EFFECT_HEAL)[2]; //donnera le max de soins dela puce de soins function getEffect(effects, wanted) { var res; for (var i in effects) { if (i[0] == wanted) res = i; } return res; } //retourne la vie totale actuelle de la team ennemie function getTotalLifeAlliesTeam() { var res = 0; for (var i in getAllies()) res = res + getLife(i); return res; } //retourne la vie totale actuelle de la team alliée function getTotalLifeEnemyTeam() { var res = 0; for (var i in getEnemies()) res = res + getLife(i); return res; } //retourne la moyenne des dégats d'une puce ou d'une arme function getMeanDamage(weapon) { if (weapon == null) return -1; if (isChip(weapon)) { return (getEffect(getChipEffects(weapon), EFFECT_DAMAGE)[2] - getEffect(getChipEffects(weapon), EFFECT_DAMAGE)[1]) / 2 + getEffect(getChipEffects(weapon), EFFECT_DAMAGE)[1]; } else return (getEffect(getWeaponEffects(weapon), EFFECT_DAMAGE)[2] - getEffect(getWeaponEffects(weapon), EFFECT_DAMAGE)[1]) /2 + getEffect(getWeaponEffects(weapon), EFFECT_DAMAGE)[1]; } //retourne la moyenne arithmétique entre 2 nombre function mean(a, b) { return (a + b)/2; } //retourne true si la puce est une puce d'attaque function isAggressiveChip(chip) { var res = false; for (var i in getChipEffects(chip)) { if (i[0] == EFFECT_DAMAGE || i[0] == EFFECT_POISON) res = true; } return res; } //retourne toutes les puces d'attaque function getAllAgressiveChip() { var res = []; var index = 0; for (var i in getChips()) { if (isAggressiveChip(i)) { res[index] = i; index ++; } } return res; } //retourne la puce/arme la moins cher function getCheapestCW(liste) { if (liste == null) { debugW("warning, la CW la moins cher d'une liste vide est null!"); return null; } var res = liste[0]; for (var i in liste) { var actualCost; if (isChip(res)) actualCost =getChipCost(res); else if (isWeapon(res)) actualCost = getWeaponCost(res); if (isChip(i) && getChipCost(i) < actualCost) res = i; else if (isWeapon(i) && getWeaponCost(i) < actualCost) res = i; } return res; } //retourne le cout d'une arme ou d'une puce function getCWCost(cw) { if (cw == null) { debugW("warning, cout demandé d'une puce qui vaut null!"); return 0; } if (isChip(cw)) return getChipCost(cw); else return getWeaponCost(cw); } //retourne true si l'élément i est dans le tableau function isInTab(i, tab) { for (var j in tab) if (j == i) return true; return false; } //retourne la case la plus proche d'une liste de cases function getNearlyCell(cells) { if (count(cells) == 0) return getCell(); var dist = getPathLength(getCell(), cells[0]); var res = 0; for (var i=0; i<count(cells); i++) { if (getPathLength(getCell(), cells[i])<=dist) { dist = getPathLength(getCell(), cells[i]); res = i; } } return cells[res]; } //retourne toutes les puces qui ont l'effet concerné function getChipsWithEffect(effect) { var res = []; var index = 0; for (var i in getChips()) { var hasEffect = false; for (var j in getChipEffects(i)) if (j[0] == effect) hasEffect = true; if (hasEffect) { res[index] = i; index++; } } return res; } //retourne le meilleur élément de tab grâce à l'évaluation par élément de fct function evalueElements(tab, fct) { if (tab == null) return null; if (count(tab) == 0) return null; var res = tab[0]; for (var i in tab) { if (fct(i) >= res) { res = i; } } return res; } /********************************************************************************* ********************************************************************************** FONCTIONS D'AIDE A LA DECISION ET D'ESTIMATION ********************************************************************************** *********************************************************************************/ //retourne la force de frappe potentielle de l'ennemi environant. Il ne s'agit que // d'une approximation basée sur l'arme actuellement équipée, la distance, la force // du/des poireau. Cette fonction stockera la liste des dégats subits (selon l'estimation) // dans le tableau functions_futurs_damage et la somme de ces dégats dans //functions_futurs_damage_sum //aucune réduction de vos armures n'est calculée, ce sont donc les dégats bruts qui //sont retournés function analyse_danger() { if (FUNCTION_DEBUG) debug("Résultat de la dernière prévoyance: " + (functions_last_turn_life- getLife() - functions_futurs_damage_sum) + " Dégats subis en plus"); var sum = 0; var damages = []; var indexD = 0; for (var i in getAliveEnemies()) { if (getWeapon(i) != null) for (var j=1; j<getTP(i); j+=getWeaponCost(getWeapon(i))) { //prerequis: lvl 37 if (getWeaponMinScope(getWeapon(i)) <= getPathLength(getCell(), getCell(i))+getMP(i)) { //sinon: //if (getWeaponMinScope(getWeapon(i)) <= getDistance(getCell(), getCell(i))+getMP(i)) { var tedamage = getMeanDamage(getWeapon(i)) * (1 + getForce(i)/100) * (1-getRelativeShield()/100) - getAbsoluteShield(); if (tedamage <0) tedamage = 0; sum += tedamage; damages[indexD] = tedamage; indexD++; } } } functions_futurs_damage_sum = sum; functions_futurs_damage = damages; if (FUNCTION_DEBUG) debug("dangé détecté: " + sum + "dégats potentiels subis au prochain tour"); return sum; } /********************************************************************************* ********************************************************************************** FONCTIONS DE CALCUL ********************************************************************************** *********************************************************************************/ //retourne la puissance d'une puce ou d'une arme utilisée sur une cible // les puces d'amélioration retournent actuellement le bonus qui sera appliqué à // la meilleure arme/puce qui correspond, multiplié par le nombre de tour de l'effet. //Si vous comptez tirer plusieurs fois, multipliez donc ce résultat! //ne prend pas en compte le taux d'échec //ne prend pas en compte les dégats/soins de zone, juste la puissance individuelle //pour les armures, la plage de dégats stoppés est basée sur l'analyse du danger //refresh_functions() est donc nécessaire au bon fonctionnement de cette évaluation function getPower(cw, target) { var effects; if (isChip(cw)) effects = getChipEffects(cw); else effects = getWeaponEffects(cw); var resultat = 0; for (var i in effects) { if (i[0] == EFFECT_DAMAGE || i[0] == EFFECT_POISON) { var temp = mean(i[1],i[2]) * (1 + getForce() / 100) * (1 - getRelativeShield(target) / 100) - getAbsoluteShield(target); temp = temp * (i[3]==0?1:i[3]); // fois le nombre de tours resultat = resultat + (temp>=0 ? temp: 0); } else if (i[0] == EFFECT_HEAL) { resultat = resultat + (1+getAgility()/100) * mean(i[1],i[2]) * i[3]; } else if (i[0] == EFFECT_ABSOLUTE_SHIELD) { var result_shield = i[1] * (1+getAgility()/100); for (var j in functions_futurs_damage) { resultat = resultat + ((functions_futurs_damage[j]-result_shield)>=0 ? result_shield:functions_futurs_damage[j]); } } else if (i[0] == EFFECT_RELATIVE_SHIELD) { var result_shield = i[1] + getAgility()/50; for (var j in functions_futurs_damage) { resultat = resultat + functions_futurs_damage[j] - (functions_futurs_damage[j]*result_shield/100); } } else if (i[0] == EFFECT_BUFF_AGILITY) { //avec CHIP_CURE codé en dur comme référence resultat = resultat + i[3] * (mean(35,43) * (1+(getAgility()+i[1])/100)- mean(35,43) * (1+(getAgility())/100)); } else if (i[0] == EFFECT_BUFF_FORCE) { resultat = resultat + i[3] * (getMeanDamage(getWeapon()) * (1+(getForce()+i[1])/100)- getMeanDamage(getWeapon()) * (1+(getForce())/100)); } } return resultat; } //retourne la puissance de l'arme/puce en fonction de son cout (basé sur getPower) // le cout est augmenté de 1 si withEquip est à true (pour les armes) function getPowerPerTP(cw, target, withEquip) { if (isChip(cw)) { if (FUNCTION_DEBUG) debug("puissance de " + getChipName(cw) + ": " + getPower(cw, target)/getChipCost(cw)); return getPower(cw, target)/getChipCost(cw); } else{ if (FUNCTION_DEBUG) debug("puissance de " + getWeaponName(cw) + ": " + getPower(cw, target)/(getWeaponCost(cw)+ (withEquip)?1:0)); return getPower(cw, target)/(getWeaponCost(cw)+ (withEquip)?1:0); } } //sans check de cible ni d'équipage, à n'utiliser que pour les puces non offensives function getPowerPerTPF(cw) { return getPowerPerTP(cw, getLeek(), false); } //utilise tous vos points de tour pour utiliser la puce/arme sur la cible function spendTPWith(weap_chip, target) { if (weap_chip == null) return; if (isChip(weap_chip)) { if (!canUseChip(weap_chip, target)) return; useChip(weap_chip, target); while(getTP() >= getChipCost(weap_chip) && canUseChip(weap_chip, target) && getChipCooldown(weap_chip) == 0) useChip(weap_chip, target); } else { if (getWeapon() != weap_chip) setWeapon(weap_chip); if (!canUseWeapon(weap_chip, target)) return; while(getTP() >= getWeaponCost(weap_chip) && canUseWeapon(weap_chip, target)) useWeapon(target); } if (getTP() >= getChipCost(CHIP_SPARK)) spendTPWith(CHIP_SPARK, target); } //construit la meilleure combinaison d'arme possible pour toucher la cible en un nombre //de points de tour donné. function buildBetterWeapons(cw, tp, target) { if (cw == null || count(cw) ==0) return []; var res = []; var index = 0; var equiped_w; var tempTP = tp; var weap_chips = cw; var bestW = getWeapon(); while (tempTP >= getCWCost(getCheapestCW(weap_chips))) { var lastWeap = bestW; for (var i in weap_chips) { if (bestW == null || getCWCost(bestW)>tempTP) bestW = i; if (getPowerPerTP(bestW, target, (lastWeap == i)) < getPowerPerTP(i, target, (lastWeap == i))) if ((getCWCost(i)+((lastWeap==i)?0:1))<=tempTP) bestW = i; } if ((getCWCost(bestW)+((lastWeap==bestW)?0:1))<=tempTP) { res[index] = bestW; tempTP = tempTP - getCWCost(bestW) ; if (lastWeap != bestW) tempTP--; index++; debug("tp restants: "+ tempTP); } else tempTP = -1; } if (FUNCTION_DEBUG) debug("la meilleure combinaison d'arme est " + res); return res; } //retourne toutes les cases ou on peut utiliser toutes les armes (puce) envoyées en //paramètre et les marque en noir sur le terrain function getCellToUseWeapons(cw, target) { var cells= []; var cellsres = []; if (count(cw) == 0) return getCell(); for (var i in cw) { if (isChip(i)) cells[count(cells)] = getCellsToUseChip(i, target); else cells[count(cells)] = getCellsToUseWeapon(i, target); } for (var i in cells[0]) { for (var j in cells) { var isIn = true; if (!isInTab(i, j)) isIn = false; if (isIn) cellsres[count(cellsres)] = i; } } for (var i in cellsres) mark(i); return getNearlyCell(cellsres); } //utilise toutes les armes envoyées en paramètre sur la cible (doublons possibles) function useWeaponsOnTarget(weapons, target) { for (var i in weapons) { if (isWeapon(i)) { if (getWeapon() != i) setWeapon(i); useWeapon(target); } else useChip(i, target); } } //peut on utiliser l'arme cw depuis cell sur la cellule ct? function canUseCWFrom(cw, cell, ct) { if (isChip(cw)) { if (isInlineChip(cw)) { if (getCellX(cell) == getCellX(ct) && getCellY(cell) == getCellY(ct)) if (getChipMinScope(cw) <= getDistance(cell, ct) && getDistance(cell, ct) <= getChipMaxScope(cw)) return true; } else if (cw != CHIP_SPARK) { if (getPathLength(cell, ct) <= getChipMaxScope(cw) && getPathLength(cell, ct) >= getChipMinScope(cw)) { //vérifier si il n'y a pas d'obstacle au moyen de la longueur du chemin: var dist = abs(getCellX(cell) - getCellX(ct)) + abs(getCellY(cell) - getCellY(ct)) + 1; if (getPathLength(cell, ct) == dist) return true; } } else {//dans le cas de chip_spark var dist = abs(getCellX(cell) - getCellX(ct)) + abs(getCellY(cell) - getCellY(ct)) + 1; if (dist <= 10) return true; } } else if (isWeapon(cw)) { if (isInlineWeapon(cw)) { if (getCellX(cell) == getCellX(ct) && getCellY(cell) == getCellY(ct)) if (getWeaponMinScope(cw) <= getDistance(cell, ct) && getDistance(cell, ct) <= getWeaponMaxScope(cw)) return true; } else { if (getPathLength(cell, ct) <= getWeaponMaxScope(cw) && getPathLength(cell, ct) >= getWeaponMinScope(cw)) { //vérifier si il n'y a pas d'obstacle au moyen de la longueur du chemin: var dist = abs(getCellX(cell) - getCellX(ct)) + abs(getCellY(cell) - getCellY(ct)) + 1; if (getPathLength(cell, ct) == dist) return true; } } } return false; } //enlève des armes envoyées en paramètre toutes les armes qu'il sera impossible d'utiliser //, c'est à dire toutes les armes qui ne pourraient toucher personne, même en se déplacant function removeUselessCW(cw, target) { var res = []; for (var i in cw) { var cells; if (isWeapon(i)) cells = getCellsToUseWeapon(i, target); else cells = getCellsToUseChip(i, target); mark(getNearlyCell(cells)); for (var j in getPath(getCell(), getNearlyCell(cells))) mark(j); if (getMP() >= getPathLength(getCell(),getNearlyCell(cells))) arrayAppend_adr(res, i); } return res;