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 appelleAI_MainRoutine.modules/ai.s::AI_MainRoutine: le dispatcher principal a 6 cas, trouve
dansab3d2-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(430 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
-
tools/LnkParser.java(modifie) : ajout du record
LnkParser.AlienDef(21 UWORDs) et de la methodegetAlienDef(int idx).
Avant on ne lisait que 4 champs (gfxType, hitPoints, height, bulType).
Maintenant on lit la structure AlienT complete (42 bytes). -
tools/LevelJsonExporter.java(modifie) :exportDefinitionsexporte
les 16 nouveaux champs par alien dansdefinitions.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)
-
core/ai/AlienBehaviour.java: enum a 6 modes, ordinal aligne sur le
byte ASMEntT_CurrentMode_bpour que la table de dispatch deAI_MainRoutine
se traduise enswitchJava direct. -
core/ai/AlienDef.java: record immutable des 21 UWORDs de AlienT.
HelpersisFlying(),attacksWithGun(),collisionRadius()(mappant la
tablediststowalldenewaliencontrol.s). -
core/ai/AlienDefLoader.java: parseur JSON regex (sans dep externe)
pour charger les 20 definitions depuisassets/levels/definitions.json.
APIload(Path),parse(String),loadFromClasspath(String). -
core/ai/AlienRuntimeState.java: etat mutable par instance d’alien,
port des champsEntT_*dedefs.iavec mapping documente. Inclut
position monde, mode courant, timers (timer1=reaction, timer2=anim,
timer3=death fade), HP, damage, control points, team number. -
core/ai/AiWorld.java: interface qui abstrait les queries au monde
(player position, LOS, control points, RNG, audio). Permet de garder
AlienAIpur et testable. L’implementation runtime sera dans la session 2.B. -
core/ai/AlienAI.java: la machine a etats. Methodeupdate(state)qui
dispatche selon le mode courant :
–doDefault(portai_ProwlRandom) : decremente timer1, test LOS,
transition vers RESPONSE quand visible et reactionTime ecoule + pas dans le noir
–doResponse(portai_Charge / ai_AttackWithGun) : anime l’attaque,
retombe en FOLLOWUP quand finie ou LOS perdue
–doFollowup(portai_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 deai_TakeDamage).
Tests (nouveau)
test/.../AlienAITest.java: 17 tests JUnit 5 qui valident toutes les
transitions de la machine a etats. Utilise unFakeWorlddeterministe avec
sequences de RNG controlees pour tester precisement les ratios 75/25 du
damage handling.
Build
-
build.gradle(modifie) : ajout dependances JUnit 5 + bloctest {. La task
useJUnitPlatform() }gradle testexecute desormais les tests IA. -
gradle.properties(modifie) : ajout action NetBeanscustom-34=test.
Limitations (a faire en phase 2.B)
- Deplacement physique :
AlienAI.moveTowards*est un placeholder lineaire
sans collision. La 2.B porteraMoveObject + Obj_DoCollisiondepuis l’ASM
pour utiliser leWallCollisionexistant. - Pathfinding : la patrouille ne suit pas le graphe de control points
(GetNextCPtdans l’ASM). Les aliens vont en ligne droite vers la cible,
ce qui est faux pour les zones reliees indirectement. - Animation 4-directionnelle :
ViewpointToDrawn’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 brancheraAlienControlSystemqui itere sur les objets
typeId=0du JSON niveau et les transforme enAlienRuntimeState. - Audio :
playPositionalSoundest un no-op. La 2.B (ou phase audio
ulterieure) brancheraAudioManagerJME. - Boss spawning :
ai_JustDiedpeut 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)