Principe

Vous l’aurez certainement remarqué; certaines entités (puces/batiments) du projet Yota sont controlées par le moteur du jeu de manière autonome. Cette intelligence artificielle fonctionne à base de scripts, codés dans un langage propre au jeu et dédié à cet usage.

Syntaxe

  • Section/procédure (#) :

Symbolise un nom de section. Une section est un bloc d’expression pouvant être executé et réferencé par ce nom.

SECTION #Section
  [expressions]
   ... 
END
Execute(#Section)
  • Variable locale ($)

Les variables permettent de stocker localement (voir sémantique) des valeurs dans le contexte du script.

Echo($v)
Set($v,123)
IF
  $v>0
THEN
...
END
  • Fonction (@) et procédure ([aucun prefixe])

Appels aux fonctions natives du langage. Lorsque le nom de la fonction est prefixé, la valeur de retour est stockée dans la pile d’appel et peut être récupérée. Liste non-exhaustive des fonctions natives :

Stop, Execute, Echo, Set, SetVolatile, Store, Restore, Now, GetVolatile, MyPR, MyPE, GetRandomReachablePos, GetPos, MyPEMax, NearestEnemyPlayer, HaveWeaponReady, AvailWeapon, MoveToPlayer, Attack, MoveToPoint, IsBot

Echo("toto")
 
Attack($id)
 
Set($variable,@Now())
 
IF
  @MyPR() > 75
THEN
  Echo("j'ai pas peur")
END
 

Sémantique

La sémantique de ce langage se veut simple, de manière à inciter les joueurs les plus motivés à participer à l’amélioration et au développement des scripts. C’est un langage de type procédural, avec les spécificités suivantes :

  • Tout le code dans des sections, ormis les constantes (DEFINE)
    • Il est possible d’implementer autant de sections que nécéssaire

... [ en cours de rédaction ]

  • Pas de boucle (for,while,do, etc ...) pour plusieurs raisons :
    • Le point d’entrée du script est executé à intervalles réguliers
    • Les scripts ne doivent pas consommer trop de temps processeur
    • La recursivité permet (dans certaines mesures) le developpement d’algorithmes suffisament complexes pour une prise de décision de l’entité contrôlée.
  • Branchements conditionnels pondérés. Ceux-ci permettent l’inclusion de facteurs aléatoires de manière simple, claire, et securisée (difficile à faire bugger :p).

Voici la syntaxe des branchements conditionnels :

IF
   [condition]
THEN
   WEIGHT [poids p1]
      [expression a1]
   WEIGHT [poids p2]
      [expression a2]
   ...
ELSE
   WEIGHT [poids q1]
      [expression b1]
   WEIGHT [poids q2]
      [expression b2]
   ...
END

Si la condition est remplie, la probabilité que l’expression (ou bloc d’expression) a1 soit executée sera : prob.a1 = p1/Σ(p,1 à n)

Ainsi, si la somme des poids vaut 100, les poids corresponderont au pourcentage de chance d’execution pour chaque bloc d’expression correspondant.

Si le mot-clef WEIGHT est omis, le bloc d’expressions suivant aura 100% de chance de s’executer si la condition est vraie.

  • Differents types de variables :
  • Variables locales (notées $nom_de_la_variable)
    • Durée de vie d’une execution du script
    • Accès en lecture/ecriture aisés :
  Set($variable,123)
  Set($variable,$variable+2)
  Echo($variable) 
  Set($variable,@fonction())
  Echo($variable)
  • Variables persistantes (identifiées par une chaine de caractères “nom_de_la_variable”)
    • Durée de vie illimitée
    • Accès en lecture/ecriture via ces 2 méthodes :
  Store("variable",1)
 
 ...
 
  Restore($tmp,"variable")
  Echo($tmp)
  • Variables volatiles (identifiées par un ID numérique, l’utilisation du mot clef DEFINE est conseillé)
    • Durée de vie semi-illimité (en cas de rédemarrage du serveur, les valeurs sont perdues)
    • Accès en lecture/ecriture via 2 méthodes :
//definition de l'ID de la variable
DEFINE VARIABLE 1
 
  SetVolatile(VARIABLE,123)
  
... 
 
  $tmp = @GetVolatile(VARIABLE)
  Echo($tmp)

L’utilité de ce type de variable par rapport aux variables persistentes se justifie uniquement en terme de performances. En effet les variables persistantes sont stockées dans la base de données, tandis que les variables volatiles sont stockées en mémoire. Cependant, leur caractère volatile impose certaines contraintes; l’entité controlée ne doit pas “se bloquer” (c’est à dire être dans un état transitoire qui la placerait dans l’incapacité de poursuivre sa logique de fonctionnement) en cas de coupures du serveur, plus ou moins frequentes et nécessaires lors de mises à jour. Typiquement, ces variables peuvent être utilisées pour :

  • se souvenir de l’ennemi qu’on est en train d’attaquer
  • se souvenir d’un point de patrouille choisit au hasard (parce qu’on a que ça à faire)

... Notez que dans ces 2 cas, un redemarrage du serveur (et donc une reinitialisation de ces variables) n’engendrera pas forcement un comportement stupide ou illogique de l’entité.

  • Differents types de données pour les variables :
  • Variables Chaînes : “bla”
  • Variables Numériques : 12345
  • Variables Points : [12.15]

Fonctions natives

Set(var,val) // renvoie 1
Store(name,var) // renvoie 1 (ou 0 si problème interne)
Restore(var,name) // renvoie 1 si la variable a été restaurée, sinon 0
 
GetVolatile(vid) // renvoie la variable ou 0 si elle n'existe pas
SetVolatile(vid,val) // renvoie 1
 
Stop() // renvoie 1
Execute(section) // renvoie 1 ou 0 si la section n'existe pas ou si la recursion est trop grande (profondeur 50)
Echo(str) // renvoie 1
 
 
Attack(eid,wid,target) // renvoie :
// -1 si erreur interne
// 0 si l'entité n'existe pas
// -2 ou -6 si hors de portée (arme ou vision)
// -3 si les PE sont insuffisants
// -4 si l'arme n'est pas prète
// -5 si l'arme n'existe pas ou n'est plus en possession
// -7 si les PR de la cible sont déjà au max (pour une réparation)
// -8 si inconscient
// -9 si paralysé
// 1 si l'attaque a detruit la cible
// 2 si l'attaque n'a pas detruit la cible
 
 
AttackPos(pos,wid) // renvoie les memes codes d'erreur que Attack, mais toujours 1 pour succès
 
MoveToPlayer(eid) // renvoie :
 
// -6 si hangar (celui qui essaie de bouger)
// -5 si en surcharge
// -4 si innaccessible
// -8 si inconscient
// -9 si paralysé
 
// sinon, le nombre de déplacements nécessaire pour aller à destination
 
MoveToPoint(pos) // memes codes d'erreur que MoveToPlayer
 
 
Now() // renvoie le timestamp unix courant
Rand(min,max) // renvoie un entier aléatoire entre min et max
 
IsBot(eid) // renvoie 1 si l'entité eid est une puce
GetPos() // renvoie la position actuelle
GetPosX() 
GetPosY()
 
GetRandomReachablePos() // renvoie une position aléatoire sur la map accessible, -1 si aucune trouvée
 
MyPR() // renvoie les PR courants
MyPRMax() 
 
MyPE() // renvoie les milli PE courants
MyPEMax()
 
MyID() // renvoie l'id de l'entité courante
 
NearestEnemy() // renvoie l'id de l'ennemi le plus proche, avec comme ordre de priorité : batiment offensif, puce, batiment
 
NearestEnemyPlayer() 
NearestEnemyBuilding()
 
AvailWeapon(eid) // renvoie l'id de la meilleure arme utilisable sur l'ennemi passé en parametre (eid peut etre -1)
HaveWeaponReady() // renvoie 1 si une arme est dispo, sinon 0
 
SelfDestruction() // renvoie 1 si ok, -1 si erreur interne

Exemples de scripts d'IA

Tourelle de défense

//-------------------------------------------------------------------------------------------
//                                                                              
//	yota ia script v1            
//                       
//  script pour tourelle de defense                                                                   
//-------------------------------------------------------------------------------------------
DEFINE VOLATILE_LAST_ACT 1
DEFINE VOLATILE_WAIT 2
 
 
SECTION #Root
	Echo("#Root")
	Set($wait_val,@GetVolatile(VOLATILE_WAIT))
	Set($last_act,@GetVolatile(VOLATILE_LAST_ACT))
	Set($act_since,(@Now()-$last_act))
	
	IF
		$act_since<$wait_val
	THEN
		Stop()	
	END
	
	Execute(#Combat)
END
 
SECTION #OnPlayerMove
	IF 
		1
	THEN
		WEIGHT 50
			SetVolatile(VOLATILE_WAIT,30)
			Execute(#Root)
		WEIGHT 50
			Echo("pas vu")
			Stop()
	END
END
 
SECTION #OnPlayerAttack
 
END
//--------------------------------------------------------------\
//	#Wait : Comportement d'attente                          |
//                                                              |
//--------------------------------------------------------------/
SECTION #Wait
	//Echo("#Wait")
	//2 Minutes d'attente
	SetVolatile(VOLATILE_LAST_ACT,@Now())
	SetVolatile(VOLATILE_WAIT,120)
	Stop()
END
 
SECTION #Combat
	Echo("#Combat")
	Set($nearest_enemy,@NearestEnemy())
	IF
		!$nearest_enemy
	THEN
		Echo("pas d'ennemi proche")
		Execute(#Wait)
		Stop()
	END
	
	Set($availweapon,@AvailWeapon($nearest_enemy))
	
	IF 
		$availweapon
	THEN
		Execute(#Attack)
		Stop()
	END
END
 
SECTION #Attack
	Echo("#Attack")
	IF
		@IsBot($nearest_enemy)
	THEN
		WEIGHT 60
			//	1 == pas de ciblage
			Set($target,1)
		WEIGHT 10
			//	2 == tete
			Set($target,2)
		WEIGHT 30
			//	3 == prop
			Set($target,3)
	END
	
	Attack($nearest_enemy,$availweapon,$target)
	
	//ajout d'un delai d'attente aléatoire
	IF
		1
	THEN
		WEIGHT 30
			SetVolatile(VOLATILE_WAIT,30)
		WEIGHT 30
			SetVolatile(VOLATILE_WAIT,45)
		WEIGHT 30
			SetVolatile(VOLATILE_WAIT,60)
	END
	
	SetVolatile(VOLATILE_LAST_ACT,@Now())
END
 

Bot

//-------------------------------------------------------------------------------------------\
//                                                                                           |
//	yota ia script v1             - Bot2 -                                               |
//                                                                                           |
//  Données persistantes :	 context    => [int] action courante                         | 
//                           target_pos => [point] point de patrouille courant               |                        
//                           current_target => [pid] cible courante                          |  
//                                                                                           |
//  Données volatiles :	 	 VOLATILE_LAST_ACT   => [int] derniere action effectuée      |  
//                                                                                           |
//-------------------------------------------------------------------------------------------/
DEFINE CONTEXT_NONE 0
DEFINE CONTEXT_PATROL 1
DEFINE CONTEXT_COMBAT 2
DEFINE CONTEXT_FLEE 3
 
DEFINE VOLATILE_LAST_ACT 1
//--------------------------------------------------------------\
//	#Root : Point d'entrée du script                        |
//                                                              |
//--------------------------------------------------------------/
SECTION #Root
	//Echo("#Root")
	//Si la derniere action effectuée est trop récente, on attend.
	Set($last_act,@GetVolatile(VOLATILE_LAST_ACT))
	Set($act_since,(@Now()-$last_act))
	IF
		$act_since<10
	THEN
		Stop()	
	END
	
	Execute(#ReevaluateContext)
END
 
//--------------------------------------------------------------\
//	#ReevaluateContext : Réévalue l'état et donc le         |
//                           comportement à adopter.            |
//--------------------------------------------------------------/
SECTION #ReevaluateContext
	Echo("#ReevaluateContext")
	
	//Rappel de l'action en cours
	Restore($context,"context")
	
	Set($lowpr,@MyPR() < 20)
	Set($lowpe,@MyPE() < 10000)
	
	IF 
		($context==CONTEXT_FLEE) || $lowpr
	THEN
		WEIGHT 50
			Execute(#Flee)
			Stop()
		WEIGHT 50
			Execute(#Combat)
			Stop()
	END
	
	IF 
		$lowpe
	THEN
		Execute(#Wait)
		Stop()
	END
	
	Execute(#Combat)
END
 
//--------------------------------------------------------------\
//	#OnPlayerMove : Trigger sur déplacement d'un joueur à   |
//                      portée.                                 |
//--------------------------------------------------------------/
SECTION #OnPlayerMove
	Echo("#OnPlayerMove")
	Execute(#Root)
END
 
//--------------------------------------------------------------\
//	#Flee : Comportement de fuite                           |
//                                                              |
//--------------------------------------------------------------/
SECTION #Flee
	Echo("#Flee")
	Restore($target_pos,"target_pos")
	IF
		!$target_pos
	THEN
		Echo($target_pos)
		Set($target_pos,@GetRandomReachablePos())
		Store("target_pos",$target_pos)
	END
	
	IF 
		$target_pos==@GetPos()
	THEN
		Store("target_pos",0)
		Execute(#Flee)
		Stop()
	END
	
	IF 
		1
	THEN
		WEIGHT 70
			MoveToPoint($target_pos)
		WEIGHT 10
			//Changement de direction aléatoirement
			Set($target_pos,@GetRandomReachablePos())
			Store("target_pos",$target_pos)
			MoveToPoint($target_pos)
		WEIGHT 20
			//Arret de la fuite
			Store("context",CONTEXT_NONE)
	END
	
	SetVolatile(VOLATILE_LAST_ACT,@Now())
	Stop()
END
 
//--------------------------------------------------------------\
//	#Wait : Comportement d'attente (energie faible)         |
//                                                              |
//--------------------------------------------------------------/
SECTION #Wait
	Echo("#Wait")
	//1 Minute d'attente
	SetVolatile(VOLATILE_LAST_ACT,@Now()+60)
	Stop()
END
 
//--------------------------------------------------------------\
//	#Patrol : Effectue un déplacement aléatoire sur la  	|
//					carte.                  |
//--------------------------------------------------------------/
SECTION #Patrol
	Echo("#Patrol")
	
	//En dessous d'un seuil, on considère qu'on a pas assez d'énergie pour patrouiller
	//( et garder de quoi attaquer au cas ou)
	IF 
		@MyPE() < (@MyPEMax()-10000)
	THEN
		Execute(#Wait)
		Stop()
	END
 
	//Nouveau point de patrouille si besoin
	Restore($target_pos,"target_pos")
	IF
		!$target_pos
	THEN
		Set($target_pos,@GetRandomReachablePos())
		Store("target_pos",$target_pos)
	END
	
	//Déplacement si on n'est pas encore à destination
	IF 
		$target_pos==@GetPos()
	THEN
		//RAZ du point de patrouille && réévaluation de l'état
		Store("target_pos",0)
		Store("context",CONTEXT_NONE)
		Stop()
	END
	
	
	Set($move_ret,@MoveToPoint($target_pos))
	IF
		$move_ret<0
	THEN
		Echo("Impossible de bouger ... patrouille")
		Store("target_pos",0)
		Store("context",CONTEXT_NONE)
		Stop()
	END
	
	Store("context",CONTEXT_PATROL)
	Stop()
END
 
 
//--------------------------------------------------------------\
//	#FindTarget : 	Renvoie un ennemi à portée, ou le       |
//                      précedent s'il n'est pas mort.          |
//--------------------------------------------------------------/
SECTION #FindTarget
	Echo("#FindTarget")
	Restore($nearest_enemy,"current_target")
	IF 
		!$nearest_enemy
	THEN
		Set($nearest_enemy,@NearestEnemyPlayer())
	END
END
 
//--------------------------------------------------------------\
//	#Combat : Cherche une cible à portée en ce déplacant    |
//                si besoin (via #Patrol si aucune n'est        |
//                visible), puis attaque.                       |
//--------------------------------------------------------------/
SECTION #Combat
	Echo("#Combat")
		
	//Aucune arme prete => fuite ou attente
	IF
		!@HaveWeaponReady()
	THEN
		WEIGHT 50
			Execute(#Flee)
			Stop()
		WEIGHT 50
			Execute(#Wait)
			Stop()	
	END
	
	//Recherche de cible, ou récupération d'une cible existante
	Execute(#FindTarget)
	Echo($nearest_enemy)
	
	//Rien à portée, patrouille
	IF
		!$nearest_enemy
	THEN
		Execute(#Patrol)
		Stop()
	END
	
	//Un ennemi est à portée, on est réellement en combat ...
	// sauvegarde de l'ennemi courant.
	Store("context",CONTEXT_COMBAT)
	Store("current_target",$nearest_enemy)
	
	Set($availweapon,@AvailWeapon($nearest_enemy))
	IF 
		$availweapon
	THEN
		Execute(#Attack)
		Stop()
	END
	
	//Aucune arme dispo pour la distance actuelle; on se rapproche.
	Set($move_ret,@MoveToPlayer($nearest_enemy))
	IF
		$move_ret<0
	THEN
		Store("current_target",0)
		Store("target_pos",0)
		Store("context",CONTEXT_NONE)
		Stop()
	END
	SetVolatile(VOLATILE_LAST_ACT,@Now())
	Stop()
END
 
//--------------------------------------------------------------\
//	#Attack : Effectue l'attaque sur $nearest_enemy avec    |
//                l'arme $availweapon                           |
//                                                              |
//--------------------------------------------------------------/
SECTION #Attack
	Echo("#Attack")
	
	//Choix du ciblage
	IF
		1
	THEN
		WEIGHT 60
			//	1 == pas de ciblage
			Set($target,1)
		WEIGHT 10
			//	2 == tete
			Set($target,2)
		WEIGHT 30
			//	3 == prop
			Set($target,3)
	END
	
	Set($attack_ret,@Attack($nearest_enemy,$availweapon,$target))
	Echo($attack_ret)
	IF 
		($attack_ret==1) || ($attack_ret==-2)
	THEN
		// Si @Attack a renvoyé 1, c'est que l'ennemi est mort, reinitialisation des données persistantes.
		// -2 => hors de portée (hangar)
		Store("current_target",0)
		Store("context",CONTEXT_NONE)
	END
	SetVolatile(VOLATILE_LAST_ACT,@Now())
END
 

Bot poseur de mine

//-------------------------------------------------------------------------------------------\
//                                                                                           |
//	yota ia script v1             - Bot2 -                                               |
//                                                                                           |
//  Données persistantes :	 context    => [int] action courante                         | 
//                           target_pos => [point] point de patrouille courant               |                        
//                           current_target => [pid] cible courante                          |  
//                                                                                           |
//  Données volatiles :	 	 VOLATILE_LAST_ACT   => [int] derniere action effectuée      |  
//                                                                                           |
//-------------------------------------------------------------------------------------------/
DEFINE CONTEXT_NONE 0
DEFINE CONTEXT_PATROL 1
DEFINE CONTEXT_COMBAT 2
DEFINE CONTEXT_FLEE 3
 
DEFINE VOLATILE_LAST_ACT 1
DEFINE VOLATILE_WAITING 2
//--------------------------------------------------------------\
//	#Root : Point d'entrée du script                        |
//                                                              |
//--------------------------------------------------------------/
SECTION #Root
	Echo("#Root")
	//Si la derniere action effectuée est trop récente, on attend.
	Set($waiting,@GetVolatile(VOLATILE_WAITING))
	IF
		$waiting
	THEN
		Set($delay,60)
	ELSE
		Set($delay,10)
	END
	
 
	Set($last_act,@GetVolatile(VOLATILE_LAST_ACT))
	Set($act_since,(@Now()-$last_act))
	IF
		$act_since<$delay
	THEN
		Echo("Waiting")
		Stop()	
	END
	
	Execute(#ReevaluateContext)
 
END
 
//--------------------------------------------------------------\
//	#ReevaluateContext : Réévalue l'état et donc le         |
//                           comportement à adopter.            |
//--------------------------------------------------------------/
SECTION #ReevaluateContext
	Echo("#ReevaluateContext")
	
	//Rappel de l'action en cours
	Restore($context,"context")
	
	Set($lowpr,@MyPR() < 20)
	Set($lowpe,@MyPE() < 10000)
	
	IF 
		($context==CONTEXT_FLEE) || $lowpr
	THEN
		WEIGHT 100
			Execute(#Flee)
			Stop()
	END
	
	IF 
		$lowpe
	THEN
		Execute(#Wait)
		Stop()
	END
	
	Execute(#Patrol)
END
 
//--------------------------------------------------------------\
//	#OnPlayerMove : Trigger sur déplacement d'un joueur à   |
//                      portée.                                 |
//--------------------------------------------------------------/
SECTION #OnPlayerMove
	Echo("#OnPlayerMove")
	SetVolatile(VOLATILE_WAITING,0)
	Execute(#Root)
END
 
//--------------------------------------------------------------\
//	#OnPlayerDrop : Trigger sur un objet posé   |
//                      à portée.                                 |
//--------------------------------------------------------------/
SECTION #OnPlayerDrop
	Echo("#OnPlayerMove")
	TryLoot()
	Execute(#Flee)
END
//--------------------------------------------------------------\
//	#OnPlayerAttack : Trigger sur déplacement d'un joueur à   |
//                      portée.                                 |
//--------------------------------------------------------------/
SECTION #OnPlayerAttack
	Echo("#OnPlayerMove")
	SetVolatile(VOLATILE_WAITING,0)
	IF
		1
	THEN
		WEIGHT 5
			Execute(#Drop)
		WEIGHT 95
			Execute(#Flee)
	END
END
//--------------------------------------------------------------\
//	#Flee : Comportement de fuite                           |
//                                                              |
//--------------------------------------------------------------/
SECTION #Flee
	Echo("#Flee")
	Restore($target_pos,"target_pos")
	IF
		!$target_pos
	THEN
		Echo($target_pos)
		Set($target_pos,@GetRandomReachablePos())
		Store("target_pos",$target_pos)
	END
	
	IF 
		$target_pos==@GetPos()
	THEN
		Store("target_pos",0)
		Execute(#Flee)
		Stop()
	END
	
	IF
		1
	THEN
		WEIGHT 80
		WEIGHT 20
			Execute(#Drop)
	END
	
	IF 
		1
	THEN
		WEIGHT 70
			MoveToPoint($target_pos)
		WEIGHT 10
			//Changement de direction aléatoirement
			Set($target_pos,@GetRandomReachablePos())
			Store("target_pos",$target_pos)
			MoveToPoint($target_pos)
		WEIGHT 20
			//Arret de la fuite
			Store("context",CONTEXT_NONE)
	END
	
	SetVolatile(VOLATILE_LAST_ACT,@Now())
	Stop()
END
 
//--------------------------------------------------------------\
//	#Wait : Comportement d'attente (energie faible)         |
//                                                              |
//--------------------------------------------------------------/
SECTION #Wait
	Echo("#Wait")
	SetVolatile(VOLATILE_WAITING,1)
	//1 Minute d'attente
	//SetVolatile(VOLATILE_LAST_ACT,@Now()+60)
	IF
                1
        THEN
		WEIGHT 99
               		Stop()
		WEIGHT 1
			Echo("WaitLoot")
                     	TryLoot()
        END
	Stop()
END
 
//--------------------------------------------------------------\
//	#Patrol : Effectue un déplacement aléatoire sur la  	|
//					carte.                  |
//--------------------------------------------------------------/
SECTION #Patrol
	Echo("#Patrol")
	
	//En dessous d'un seuil, on considère qu'on a pas assez d'énergie pour patrouiller
	//( et garder de quoi attaquer au cas ou)
	IF 
		@MyPE() < (@MyPEMax()-(@MyPEMax()/2))
	THEN
		Execute(#Wait)
		Stop()
	END
 
	//Nouveau point de patrouille si besoin
	Restore($target_pos,"target_pos")
	IF
		!$target_pos
	THEN
		Set($target_pos,@GetRandomReachablePos())
		Store("target_pos",$target_pos)
	END
	
	//Déplacement si on n'est pas encore à destination
	IF 
		$target_pos==@GetPos()
	THEN
		//RAZ du point de patrouille && réévaluation de l'état
		Store("target_pos",0)
		Store("context",CONTEXT_NONE)
		Stop()
	END
	
	IF
		1
	THEN
		WEIGHT 10
			Execute(#Drop)
			Stop()
		WEIGHT 90
			Set($move_ret,@MoveToPoint($target_pos))
	END
	
	
	
	IF
		$move_ret<0
	THEN
		Echo("Impossible de bouger ... patrol")
		Store("target_pos",0)
		Store("context",CONTEXT_NONE)
		Stop()
	END
	
	Store("context",CONTEXT_PATROL)
	Stop()
END
 
 
//--------------------------------------------------------------\
//	#Drop : 	Tente de poser une mine                 |
//--------------------------------------------------------------/
SECTION #Drop
	Echo("#Drop")
	
	Set($target_pos,@GetRandomReachablePos())
	Store("target_pos",$target_pos)
	
	Set($drop_ret,@DropMine())
	
	IF
		$drop_ret==1
	THEN
		InvokeObject(6,17,2)
	END
	
	Set($move_ret,@MoveToPoint($target_pos))
	IF
		$move_ret<0
	THEN
		Echo("Impossible de bouger ... patrol")
		Store("target_pos",0)
		Store("context",CONTEXT_NONE)
		Stop()
	END
	
	Store("context",CONTEXT_PATROL)
	Stop()
END
 

Bot combat

//-------------------------------------------------------------------------------------------\
//                                                                                           |
//	yota ia script v2             - Bot2 -                                               |
//                                                                                           |
//  Données persistantes :	 context    => [int] action courante                         | 
//                           target_pos => [point] point de patrouille courant               |                        
//                           current_target => [pid] cible courante                          |  
//                                                                                           |
//  Données volatiles :	 	 VOLATILE_LAST_ACT   => [int] derniere action effectuée      |  
//                                                                                           |
//-------------------------------------------------------------------------------------------/
DEFINE CONTEXT_NONE 0
DEFINE CONTEXT_PATROL 1
DEFINE CONTEXT_COMBAT 2
DEFINE CONTEXT_FLEE 3
DEFINE CONTEXT_FINDGENE 4
 
DEFINE VOLATILE_LAST_ACT 1
DEFINE VOLATILE_WAITING 2
//--------------------------------------------------------------\
//	#Root : Point d'entrée du script                        |
//                                                              |
//--------------------------------------------------------------/
SECTION #Root
	Echo("#Root")
	//Si la derniere action effectuée est trop récente, on attend.
	Set($waiting,@GetVolatile(VOLATILE_WAITING))
	IF
		$waiting
	THEN
		Set($delay,60)
	ELSE
		Set($delay,10)
	END
	
	Set($last_act,@GetVolatile(VOLATILE_LAST_ACT))
	Set($act_since,(@Now()-$last_act))
	IF
		$act_since<$delay
	THEN
		Echo("Waiting")
		Stop()	
	END
	
	Execute(#ReevaluateContext)
END
 
//--------------------------------------------------------------\
//	#ReevaluateContext : Réévalue l'état et donc le         |
//                           comportement à adopter.            |
//--------------------------------------------------------------/
SECTION #ReevaluateContext
	Echo("#ReevaluateContext")
	
	//Rappel de l'action en cours
	Restore($context,"context")
	
	Set($lowpr,@MyPR() < 20)
	Set($lowpe,@MyPE() < 50000)
	
	IF 
		($context==CONTEXT_FLEE) || $lowpr
	THEN
		WEIGHT 50
			Execute(#Flee)
			Stop()
		WEIGHT 50
			Execute(#Combat)
			Stop()
	END
	
//	IF 
//		$lowpe || ($context==CONTEXT_FINDGENE)
//	THEN
//		Execute(#FindGenerator)
//		Stop()
//	END
	
	Execute(#Combat)
END
 
//--------------------------------------------------------------\
//	#OnPlayerMove : Trigger sur déplacement d'un joueur à   |
//                      portée.                                 |
//--------------------------------------------------------------/
SECTION #OnPlayerMove
	Echo("#OnPlayerMove")
	SetVolatile(VOLATILE_WAITING,0)
	Execute(#Root)
END
//--------------------------------------------------------------\
//	#OnPlayerDrop : Trigger sur un objet posé   |
//                      à portée.                                 |
//--------------------------------------------------------------/
SECTION #OnPlayerDrop
	IF
		1
	THEN
		WEIGHT 80
			TryLoot()
			Stop()
		WEIGHT 20
			Stop()
	END
END
//--------------------------------------------------------------\
//	#OnPlayerAttack : Trigger sur déplacement d'un joueur à   |
//                      portée.                                 |
//--------------------------------------------------------------/
SECTION #OnPlayerAttack
	Echo("#OnPlayerMove")
	SetVolatile(VOLATILE_WAITING,0)
	Execute(#Root)
END
//--------------------------------------------------------------\
//	#Flee : Comportement de fuite                           |
//                                                              |
//--------------------------------------------------------------/
SECTION #Flee
	Echo("#Flee")
	Restore($target_pos,"target_pos")
	IF
		!$target_pos
	THEN
		Echo($target_pos)
		Set($target_pos,@GetRandomReachablePos())
		Store("target_pos",$target_pos)
	END
	
	IF 
		$target_pos==@GetPos()
	THEN
		Store("target_pos",0)
		Execute(#Flee)
		Stop()
	END
	
	IF
		@MyPE() < 50000
	THEN
		WEIGHT 70
			Store("context",CONTEXT_NONE)
			Stop()
		WEIGHT 30
			Execute(#Wait)
			Stop()
	END
	
	IF 
		1
	THEN
		WEIGHT 70
			MoveToPoint($target_pos)
		WEIGHT 10
			//Changement de direction aléatoirement
			Set($target_pos,@GetRandomReachablePos())
			Store("target_pos",$target_pos)
			MoveToPoint($target_pos)
		WEIGHT 20
			//Arret de la fuite
			Store("context",CONTEXT_NONE)
	END
	
	SetVolatile(VOLATILE_LAST_ACT,@Now())
	Stop()
END
 
//--------------------------------------------------------------\
//	#Wait : Comportement d'attente (energie faible)         |
//                                                              |
//--------------------------------------------------------------/
SECTION #Wait
	Echo("#Wait")
	SetVolatile(VOLATILE_WAITING,1)
	//1 Minute d'attente
	//SetVolatile(VOLATILE_LAST_ACT,@Now()+60)
	Stop()
END
 
 
SECTION #FindGenerator
	Restore($target_pos,"target_pos")
        IF
                !$target_pos
        THEN
                Set($target_pos,@GetNearestReachableGenPos())
                Store("target_pos",$target_pos)
        END
	//Déplacement si on n'est pas encore à destination
        IF
                $target_pos==@GetPos()
        THEN
                //RAZ du point de patrouille && réévaluation de l'état
                Store("target_pos",0)
		Store("context",CONTEXT_NONE)
		Execute(#Wait)
		Stop()
        END
 
        Set($move_ret,@MoveToPoint($target_pos))
        IF
                $move_ret<0
        THEN
                Echo("Impossible de bouger ... FindGenerator")
                Store("target_pos",0)
                Store("context",CONTEXT_NONE)
                Stop()
        END
	Store("context",CONTEXT_FINDGENE)
END
//--------------------------------------------------------------\
//	#Patrol : Effectue un déplacement aléatoire sur la  	|
//					carte.                  |
//--------------------------------------------------------------/
SECTION #Patrol
	Echo("#Patrol")
	
	//En dessous d'un seuil, on considère qu'on a pas assez d'énergie pour patrouiller
	//( et garder de quoi attaquer au cas ou)
	IF 
		@MyPE() < (@MyPEMax()-10000)
	THEN
		Execute(#Wait)
		Stop()
	END
	
	IF
                @MyPE() < (@MyPEMax()/3)
        THEN
                Execute(#FindGenerator)
                Stop()
        END
 
 
	//Nouveau point de patrouille si besoin
	Restore($target_pos,"target_pos")
	IF
		!$target_pos
	THEN
		Set($target_pos,@GetRandomReachablePos())
		Store("target_pos",$target_pos)
	END
	
	//Déplacement si on n'est pas encore à destination
	IF 
		$target_pos==@GetPos()
	THEN
		//RAZ du point de patrouille && réévaluation de l'état
		Store("target_pos",0)
		Store("context",CONTEXT_NONE)
		Stop()
	END
	
	
	Set($move_ret,@MoveToPoint($target_pos))
	IF
		$move_ret<0
	THEN
		Echo("Impossible de bouger ... patrol")
		Store("target_pos",0)
		Store("context",CONTEXT_NONE)
		Stop()
	END
	
	Store("context",CONTEXT_PATROL)
	Stop()
END
 
 
//--------------------------------------------------------------\
//	#FindTarget : 	Renvoie un ennemi à portée, ou le           |
//                      précedent s'il n'est pas mort.          |
//--------------------------------------------------------------/
SECTION #FindTarget
	Echo("#FindTarget")
	Restore($nearest_enemy,"current_target")
	IF 
		!$nearest_enemy
	THEN
		Set($nearest_enemy,@NearestEnemyPlayer())
	END
END
 
//--------------------------------------------------------------\
//	#Combat : Cherche une cible à portée en ce déplacant        |
//                si besoin (via #Patrol si aucune n'est        |
//                visible), puis attaque.                       |
//--------------------------------------------------------------/
SECTION #Combat
	Echo("#Combat")
		
	IF 
		@MyPE() < 15000
	THEN
		Echo("Low PE => Wait")
		Execute(#Wait)
		Stop()
	END
	
	//TryLoot()
	
	//Aucune arme prete => fuite ou attente
	IF
		!@HaveWeaponReady()
	THEN
		WEIGHT 30
			//TryLoot()
			Echo("No weapon => Flee")
			Execute(#Flee)
			Stop()
		WEIGHT 30
			//TryLoot()
			Echo("No weapon => Wait")
			Execute(#Wait)
			Stop()
		WEIGHT 30
			Echo("No weapon => Reload")
			ReloadSomething()
			Stop()
	END
	
	//Recherche de cible, ou récupération d'une cible existante
	Execute(#FindTarget)
	Echo($nearest_enemy)
	
	//Rien à portée, patrouille
	IF
		!$nearest_enemy
	THEN
		Execute(#Patrol)
		Stop()
	END
	
	//Un ennemi est à portée, on est réellement en combat ...
	// sauvegarde de l'ennemi courant.
	Store("context",CONTEXT_COMBAT)
	Store("current_target",$nearest_enemy)
	
	Set($availweapon,@AvailWeapon($nearest_enemy))
	IF 
		$availweapon
	THEN
		Execute(#Attack)
		Stop()
	END
	
	//Aucune arme dispo pour la distance actuelle; on se rapproche.
	Set($move_ret,@MoveToPlayer($nearest_enemy))
	IF
		$move_ret<0
	THEN
		Echo("cant move to target, reeval ... combat")
		Store("current_target",0)
		Store("target_pos",0)
		Store("context",CONTEXT_NONE)
		Stop()
	END
	SetVolatile(VOLATILE_LAST_ACT,@Now())
	Stop()
END
 
//--------------------------------------------------------------\
//	#Attack : Effectue l'attaque sur $nearest_enemy avec    |
//                l'arme $availweapon                           |
//                                                              |
//--------------------------------------------------------------/
SECTION #Attack
	Echo("#Attack")
	
	//Choix du ciblage
	IF
		1
	THEN
		WEIGHT 60
			//	1 == pas de ciblage
			Set($target,1)
		WEIGHT 10
			//	2 == tete
			Set($target,2)
		WEIGHT 30
			//	3 == prop
			Set($target,3)
	END
	
	Set($attack_ret,@Attack($nearest_enemy,$availweapon,$target))
	Echo($attack_ret)
	IF 
		($attack_ret==1) || ($attack_ret==-2)
	THEN
		// Si @Attack a renvoyé 1, c'est que l'ennemi est mort, reinitialisation des données persistantes.
		// -2 => hors de portée (hangar)
		Store("current_target",0)
		Store("context",CONTEXT_NONE)
		TryLoot()
	END
	SetVolatile(VOLATILE_LAST_ACT,@Now())
	SetVolatile(VOLATILE_WAITING,0)
END
 

autres/ia.txt · Dernière modification: 2009/02/12 20:34 par flo