Aller au contenu principal

Session 113 — Phase 2.A : machine a etats IA aliens (newaliencontrol.s + AlienT)

Contexte

Demarrage du portage de l’IA des aliens depuis l’ASM original. Le moteur AB3D2
origine utilise une machine a etats a 6 modes (4 « officiels » annonces dans la
struct AlienT + 2 modes runtime non parametrables) :

Mode ASM Enum Java Role
0 DEFAULT Patrouille (prowl) entre control points
1 RESPONSE Attaque (charge ou tir)
2 FOLLOWUP Pause apres tir / approche pour attaque suivante
3 RETREAT Fuite (non implemente dans l’ASM original : ai_DoRetreat: rts)
4 TAKE_DAMAGE Animation de hit
5 DIE Animation de mort + suppression apres 25 frames

Decouvertes ASM

  • newaliencontrol.s::ItsAnAlien (l.7-78) : entry point qui charge l’AlienT depuis
    le GLF et appelle AI_MainRoutine.
  • modules/ai.s::AI_MainRoutine : le dispatcher principal a 6 cas, trouve
    dans ab3d2-tkg-original/ab3d2_source/modules/ai.s
    (n’etait pas dans /mnt/project/).
  • defs.i::STRUCTURE AlienT (l.169-191) : 21 UWORDs = 42 bytes.
  • ai_bss.s : AI_AlienWorkspace_vl (4300 longs = 300 aliens max),
    AI_AlienTeamWorkspace_vl (4
    30 longs = 30 equipes), boredom, damage.
  • newaliencontrol.s::ViewpointToDraw : sprite 4-directionnel (TOWARDS=0,
    RIGHT=1, AWAY=2, LEFT=3) calcule depuis l’angle alien vs camera.

Comportements (= index dans tables ASM)

  • DefaultBehaviour : 0=ProwlRandom, 1=ProwlRandomFlying
  • ResponseBehaviour : 0=Charge, 1=ChargeToSide, 2=AttackWithGun,
    3=ChargeFlying, 4=ChargeToSideFlying, 5=AttackWithGunFlying
  • FollowupBehaviour : 0=PauseBriefly, 1=Approach, 2=ApproachToSide,
    3=ApproachFlying, 4=ApproachToSideFlying
  • RetreatBehaviour : declared but ai_DoRetreat: rts (vide dans l’ASM)

Architecture Java (5 fichiers nouveaux + 3 modifies)

Donnees

  1. tools/LnkParser.java (modifie) : ajout du record
    LnkParser.AlienDef (21 UWORDs) et de la methode getAlienDef(int idx).
    Avant on ne lisait que 4 champs (gfxType, hitPoints, height, bulType).
    Maintenant on lit la structure AlienT complete (42 bytes).

  2. tools/LevelJsonExporter.java (modifie) : exportDefinitions exporte
    les 16 nouveaux champs par alien dans definitions.json :
    – defaultBehaviour, defaultSpeed, reactionTime
    – responseBehaviour, responseSpeed, responseTimeout
    – damageToRetreat, damageToFollowup
    – followupBehaviour, followupSpeed, followupTimeout
    – retreatBehaviour, retreatSpeed, retreatTimeout
    – girth, splatType, auxilliary

Runtime IA (nouveau package com.ab3d2.core.ai)

  1. core/ai/AlienBehaviour.java : enum a 6 modes, ordinal aligne sur le
    byte ASM EntT_CurrentMode_b pour que la table de dispatch de AI_MainRoutine
    se traduise en switch Java direct.

  2. core/ai/AlienDef.java : record immutable des 21 UWORDs de AlienT.
    Helpers isFlying(), attacksWithGun(), collisionRadius() (mappant la
    table diststowall de newaliencontrol.s).

  3. core/ai/AlienDefLoader.java : parseur JSON regex (sans dep externe)
    pour charger les 20 definitions depuis assets/levels/definitions.json.
    API load(Path), parse(String), loadFromClasspath(String).

  4. core/ai/AlienRuntimeState.java : etat mutable par instance d’alien,
    port des champs EntT_* de defs.i avec mapping documente. Inclut
    position monde, mode courant, timers (timer1=reaction, timer2=anim,
    timer3=death fade), HP, damage, control points, team number.

  5. core/ai/AiWorld.java : interface qui abstrait les queries au monde
    (player position, LOS, control points, RNG, audio). Permet de garder
    AlienAI pur et testable. L’implementation runtime sera dans la session 2.B.

  6. core/ai/AlienAI.java : la machine a etats. Methode update(state) qui
    dispatche selon le mode courant :
    doDefault (port ai_ProwlRandom) : decremente timer1, test LOS,
    transition vers RESPONSE quand visible et reactionTime ecoule + pas dans le noir
    doResponse (port ai_Charge / ai_AttackWithGun) : anime l’attaque,
    retombe en FOLLOWUP quand finie ou LOS perdue
    doFollowup (port ai_PauseBriefly / ai_Approach) : decremente timer1,
    retour en DEFAULT au timeout, ou en RESPONSE si LOS retrouvee
    doRetreat : fallback DEFAULT (ASM-fidele)
    doTakeDamage : anim hit pendant 8 frames, retour DEFAULT
    doDie : decremente timer3 (death fade), isDeadAndGone() quand 0
    applyDamage : decompte HP, transition DIE / RESPONSE (75%) / TAKE_DAMAGE (25%)
    selon GetRand & 3 (port fidele de ai_TakeDamage).

Tests (nouveau)

  1. test/.../AlienAITest.java : 17 tests JUnit 5 qui valident toutes les
    transitions de la machine a etats. Utilise un FakeWorld deterministe avec
    sequences de RNG controlees pour tester precisement les ratios 75/25 du
    damage handling.

Build

  1. build.gradle (modifie) : ajout dependances JUnit 5 + bloc test {
    useJUnitPlatform() }
    . La task gradle test execute desormais les tests IA.

  2. gradle.properties (modifie) : ajout action NetBeans custom-34=test.

Limitations (a faire en phase 2.B)

  • Deplacement physique : AlienAI.moveTowards* est un placeholder lineaire
    sans collision. La 2.B portera MoveObject + Obj_DoCollision depuis l’ASM
    pour utiliser le WallCollision existant.
  • Pathfinding : la patrouille ne suit pas le graphe de control points
    (GetNextCPt dans l’ASM). Les aliens vont en ligne droite vers la cible,
    ce qui est faux pour les zones reliees indirectement.
  • Animation 4-directionnelle : ViewpointToDraw n’est pas encore porte.
    Les sprites alien existants (alien2/ashnarg/guard/insect/priest/robotright/
    triclaw/worm) sont la et ont la bonne echelle, mais le mapping frame index
    -> direction doit etre cable dans la 2.B.
  • Spawn / integration GameAppState : aucun alien n’est instancie pour
    l’instant. La 2.B branchera AlienControlSystem qui itere sur les objets
    typeId=0 du JSON niveau et les transforme en AlienRuntimeState.
  • Audio : playPositionalSound est un no-op. La 2.B (ou phase audio
    ulterieure) branchera AudioManager JME.
  • Boss spawning : ai_JustDied peut spawner des aliens plus petits
    (splatType >= NUM_BULLET_DEFS). Pas encore implemente.
  • Team coordination : AI_AlienTeamWorkspace_vl (partage de la derniere
    position connue du joueur entre aliens d’une meme equipe) n’est pas porte.
    Chaque alien decide en solo pour le moment.

Verifications assets

Sprites bitmap : tous presents dans assets/Textures/objects/ avec les
frames attendues (echelle visuelle correcte, conforme aux height du GLF) :

Alien Frames Indices defs
alien2 19 0 (Red Alien)
ashnarg 12 4 (Ashnarg)
guard 21 2 (Guard), 5 (‘Ard Guard), 8 (Player1), 13 (Triclaw), 17 (Insect Boss)
insect 22 6 (well ard guard), 7 (Ashnarg2), 9 (Player2), 10 (Insectalien)
priest 14 11 (AlienPriest)
robotright 20 3 (Droid), 12 (BigInsect)
triclaw 18 14 (Tough Triclaw)
worm 20 (mapping a confirmer)

Vectobj boss : tous presents dans assets/Scenes/vectobj/ :
snake.j3o (alien 1 = SnakeScanner)
wasp.j3o (alien 15 = Wasp Boss)
mantis.j3o (alien 16 = Mantis Boss)
crab.j3o (alien 18 = Crab Boss)

Pour tester

./gradlew test                    # execute AlienAITest (17 tests)
./gradlew convertLevels           # regenere definitions.json avec les 16 nouveaux champs
cat assets/levels/definitions.json | grep -A 1 reactionTime  # verifier export

Fichiers nouveaux

  • core/ai/AlienBehaviour.java (enum a 6 modes)
  • core/ai/AlienDef.java (record AlienT)
  • core/ai/AlienDefLoader.java (parser definitions.json)
  • core/ai/AlienRuntimeState.java (etat runtime EntT)
  • core/ai/AiWorld.java (interface queries monde)
  • core/ai/AlienAI.java (machine a etats)
  • test/.../AlienAITest.java (17 tests JUnit)

Fichiers modifies

  • tools/LnkParser.java (record AlienDef + getAlienDef)
  • tools/LevelJsonExporter.java (export 16 nouveaux champs alien)
  • build.gradle (deps JUnit 5 + bloc test)
  • gradle.properties (action custom-34=test)

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *