Je suis en train de préparer un exposé sur l'intelligence artificielle. Je travaille actuellement sur la recherche de chemin.
J'ai composé 3 codes que voici...
J'ai donc fais un 1er programme (récursif) pour atteindre le point d'arrivé, mais lors des chemins complexes (point d'arrivée rapproché, mais très difficilement accessible), le calcul est très très long.
Voici le code 1 :
Code : Tout sélectionner
Declare.b FindDirection(x,y, tx, ty)
Declare.b FindAWay(x,y, tx, ty, cpt.b, exDir.b)
RandomSeed(ElapsedMilliseconds())
#HAUT = 1
#DROITE = 2
#BAS = 4
#GAUCHE = 8
Dim Map.b(15,15)
Dim Calk.b(15,15)
For j = 0 To 14
For i = 0 To 14
Read Map(i,j)
Next i
Next j
PersoX = 1
PersoY = 1
TargetX.w = 1
TargetY.w = 1
ShowCursor_(1)
ShowCursor_(1)
ShowCursor_(1)
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse()=0
MessageRequester("Error", "Can't open DirectX 7 or later", 0)
End
EndIf
OpenScreen(320, 240, 16, "Sprite")
; - - - - - - - - - - - BOUCLE - - - - - - - - - - -
Repeat
FlipBuffers()
If IsScreenActive()
ClearScreen(0,0,0)
ReleaseMouse(0)
ExamineKeyboard(): ExamineMouse()
If MouseButton(1)
If Map(Int(MouseX()/16), Int(MouseY()/16)) = 0
TargetX = MouseX()/16
TargetY = MouseY()/16
EndIf
EndIf
Select FindDirection(PersoX, PersoY, TargetX, TargetY)
Case #HAUT
PersoY - 1
Case #DROITE
PersoX + 1
Case #BAS
PersoY + 1
Case #GAUCHE
PersoX - 1
EndSelect
StartDrawing(ScreenOutput())
For j = 0 To 14
For i = 0 To 14
If Map(i,j)
Box(i*16, j*16, 16, 16, RGB(255,255,255))
EndIf
Next i
Next j
Line(TargetX*16, TargetY*16, 16, 16, RGB(255,0,0))
Line(TargetX*16, TargetY*16 +15, 16, -16, RGB(255,0,0))
For i = 1 To 7
Circle((PersoX*16) + 8, (PersoY*16) + 8, i, RGB(255,255,0))
Next i
StopDrawing()
SetCursorPos_(MouseX(), MouseY())
Else
ReleaseMouse(1)
EndIf
Until KeyboardPushed(#PB_Key_Escape)
CloseScreen()
End
; - - - - - - - - - - - - - - - - - - - - - - - - -
DataSection
Data.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.b 1,0,0,0,0,0,0,1,0,0,0,0,0,1,1
Data.b 1,0,1,1,0,1,0,1,0,1,1,1,0,0,1
Data.b 1,0,1,1,0,1,0,0,0,1,1,1,1,0,1
Data.b 1,0,0,1,0,1,0,1,0,1,0,0,1,0,1
Data.b 1,1,0,1,0,1,0,1,0,0,0,0,0,0,1
Data.b 1,0,0,0,0,1,0,1,1,1,1,0,1,1,1
Data.b 1,1,1,1,1,1,0,1,0,0,0,0,1,0,1
Data.b 1,0,0,0,0,0,0,1,0,1,1,0,1,0,1
Data.b 1,0,1,1,0,1,1,1,0,0,1,0,1,0,1
Data.b 1,0,1,0,0,1,0,1,1,0,1,0,1,0,1
Data.b 1,0,1,0,1,1,0,1,1,0,1,0,1,0,1
Data.b 1,0,1,0,0,1,0,1,1,1,1,0,1,0,1
Data.b 1,0,0,0,0,0,0,1,0,0,0,0,0,0,1
Data.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
EndDataSection
Procedure.b FindAWay(x,y, tx, ty, cpt.b, exDir.b)
difX = (x - tx)
difY = (y - ty)
If x = tx And y = ty
ProcedureReturn(15)
ElseIf Abs(difX) + Abs(difY) > cpt
ProcedureReturn(0)
EndIf
mur = Map(x,y-1)*#HAUT + Map(x+1,y)*#DROITE + Map(x,y+1)*#BAS + Map(x-1,y)*#GAUCHE
tried.b = (exDir * 4) % 15
If Abs(difX) > Abs(difY)
; perso trop à droite : <=
If x > tx
If (mur & #GAUCHE)=0 And tried <> #GAUCHE
If FindAWay(x-1,y, tx, ty, cpt-1, #GAUCHE)
ProcedureReturn(#GAUCHE)
EndIf
EndIf
tried = #GAUCHE
;perso trop à gauche =>
Else
If (mur & #DROITE)=0 And tried <> #DROITE
If FindAWay(x+1,y, tx, ty, cpt-1, #DROITE)
ProcedureReturn(#DROITE)
EndIf
EndIf
tried = #DROITE
EndIf
Else
; perso trop haut
If y > ty
If (mur & #HAUT)=0 And tried <> #HAUT
If FindAWay(x,y-1, tx, ty, cpt-1, #HAUT)
ProcedureReturn(#HAUT)
EndIf
EndIf
tried = #HAUT
;perso trop bas ^
Else
If (mur & #BAS)=0 And tried <> #BAS
If FindAWay(x,y+1, tx, ty, cpt-1, #BAS)
ProcedureReturn(#BAS)
EndIf
EndIf
tried = #BAS
EndIf
EndIf
While (tried <> 15)
c = Pow(2, Random(3))
If (tried & c)=0
Select c
Case #HAUT
If (mur & #HAUT)=0 And tried <> #HAUT
If FindAWay(x,y-1, tx, ty, cpt-1, #HAUT)
ProcedureReturn(#HAUT)
EndIf
EndIf
Case #DROITE
If (mur & #DROITE)=0 And tried <> #DROITE
If FindAWay(x+1,y, tx, ty, cpt-1, #DROITE)
ProcedureReturn(#DROITE)
EndIf
EndIf
Case #BAS
If (mur & #BAS)=0 And tried <> #BAS
If FindAWay(x,y+1, tx, ty, cpt-1, #BAS)
ProcedureReturn(#BAS)
EndIf
EndIf
Case #GAUCHE
If (mur & #GAUCHE)=0 And tried <> #GAUCHE
If FindAWay(x-1,y, tx, ty, cpt-1, #GAUCHE)
ProcedureReturn(#GAUCHE)
EndIf
EndIf
EndSelect
tried = tried | c
EndIf
Wend
ProcedureReturn(0)
EndProcedure
Procedure.b FindDirection(x,y, tx, ty)
If (x = tx) And (y = ty)
ProcedureReturn(0)
EndIf
cpt = Abs(x - tx) + Abs(y - ty)
Repeat
r.b = FindAWay(x,y, tx,ty, cpt, 0)
cpt + 1
If cpt = 40
End
EndIf
Until r
ProcedureReturn(r)
EndProcedure
Puis j'ai refait un code similaire, sauf que c'est fois je fais 2 patates (récursion grandissante) et j'intercepte le point de collision entre ces 2 patates => point intermédiaire :
Code : Tout sélectionner
Declare.b FindDirection(x,y, tx, ty)
Declare.b FindAWay(x,y, tx, ty, cpt.b, exDir.b, marque.b, intersection.b)
RandomSeed(ElapsedMilliseconds())
#HAUT = 1
#DROITE = 2
#BAS = 4
#GAUCHE = 8
Dim Map.b(15,15)
Dim Calk.b(15,15)
Global PtInter.Point, inter.b
For j = 0 To 14
For i = 0 To 14
Read Map(i,j)
Next i
Next j
PersoX = 1
PersoY = 1
TargetX.w = 1
TargetY.w = 1
ShowCursor_(1)
ShowCursor_(1)
ShowCursor_(1)
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse()=0
MessageRequester("Error", "Can't open DirectX 7 or later", 0)
End
EndIf
OpenScreen(320, 240, 16, "Sprite")
; - - - - - - - - - - - BOUCLE - - - - - - - - - - -
Repeat
FlipBuffers()
If IsScreenActive()
ClearScreen(0,0,0)
ReleaseMouse(0)
ExamineKeyboard(): ExamineMouse()
If MouseButton(1)
If Map(Int(MouseX()/16), Int(MouseY()/16)) = 0
TargetX = MouseX()/16
TargetY = MouseY()/16
EndIf
EndIf
If Inter
dir = FindDirection(PersoX, PersoY, PtInter\x, PtInter\y)
Else
dir = FindDirection(PersoX, PersoY, TargetX, TargetY)
EndIf
Select dir
Case #HAUT
PersoY - 1
Case #DROITE
PersoX + 1
Case #BAS
PersoY + 1
Case #GAUCHE
PersoX - 1
EndSelect
If Inter
If PtInter\x = PersoX And PtInter\y = PersoY
Inter = 0
EndIf
EndIf
StartDrawing(ScreenOutput())
For j = 0 To 14
For i = 0 To 14
If Map(i,j)
Box(i*16, j*16, 16, 16, RGB(255,255,255))
EndIf
Next i
Next j
Line(TargetX*16, TargetY*16, 16, 16, RGB(255,0,0))
Line(TargetX*16, TargetY*16 +15, 16, -16, RGB(255,0,0))
If Inter
Line(PtInter\x*16, PtInter\y*16, 16, 16, RGB(0,0,255))
Line(PtInter\x*16, PtInter\y*16 +15, 16, -16, RGB(0,0,255))
EndIf
For i = 1 To 7
Circle((PersoX*16) + 8, (PersoY*16) + 8, i, RGB(255,255,0))
Next i
StopDrawing()
SetCursorPos_(MouseX(), MouseY())
Else
ReleaseMouse(1)
EndIf
Until KeyboardPushed(#PB_Key_Escape)
CloseScreen()
End
; - - - - - - - - - - - - - - - - - - - - - - - - -
DataSection
Data.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.b 1,0,0,0,0,0,0,1,0,0,0,0,0,1,1
Data.b 1,0,1,1,0,1,0,1,0,1,1,1,0,0,1
Data.b 1,0,1,1,0,1,0,0,0,1,1,1,1,0,1
Data.b 1,0,0,1,0,1,0,1,0,1,0,0,1,0,1
Data.b 1,1,0,1,0,1,0,1,0,0,0,0,0,0,1
Data.b 1,0,0,0,0,1,0,1,1,1,1,0,1,1,1
Data.b 1,1,1,1,1,1,0,1,0,0,0,0,1,0,1
Data.b 1,0,0,0,0,0,0,1,0,1,1,0,1,0,1
Data.b 1,0,1,1,0,1,1,1,0,0,1,0,1,0,1
Data.b 1,0,1,0,0,1,0,1,1,0,1,0,1,0,1
Data.b 1,0,1,0,1,1,0,1,1,0,1,0,1,0,1
Data.b 1,0,1,0,0,1,0,1,1,1,1,0,1,0,1
Data.b 1,0,0,0,0,0,0,1,0,0,0,0,0,0,1
Data.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
EndDataSection
Procedure.b FindAWay(x,y, tx, ty, cpt.b, exDir.b, marque.b, intersection.b)
difX = (x - tx)
difY = (y - ty)
If x = tx And y = ty
ProcedureReturn(15)
ElseIf Abs(difX) + Abs(difY) > cpt
ProcedureReturn(0)
EndIf
If marque
If Calk(x,y) > 0 And Calk(x,y) <> marque
If intersection
PtInter\x = x: PtInter\y = y
Inter = 1
EndIf
ProcedureReturn(15)
Else
Calk(x,y) = marque
EndIf
EndIf
mur = Map(x,y-1)*#HAUT + Map(x+1,y)*#DROITE + Map(x,y+1)*#BAS + Map(x-1,y)*#GAUCHE
tried.b = (exDir * 4) % 15
If Abs(difX) > Abs(difY)
; perso trop à droite : <=
If x > tx
If (mur & #GAUCHE)=0 And tried <> #GAUCHE
If FindAWay(x-1,y, tx, ty, cpt-1, #GAUCHE, marque, intersection)
ProcedureReturn(#GAUCHE)
EndIf
EndIf
tried = #GAUCHE
;perso trop à gauche =>
Else
If (mur & #DROITE)=0 And tried <> #DROITE
If FindAWay(x+1,y, tx, ty, cpt-1, #DROITE, marque, intersection)
ProcedureReturn(#DROITE)
EndIf
EndIf
tried = #DROITE
EndIf
Else
; perso trop haut
If y > ty
If (mur & #HAUT)=0 And tried <> #HAUT
If FindAWay(x,y-1, tx, ty, cpt-1, #HAUT, marque, intersection)
ProcedureReturn(#HAUT)
EndIf
EndIf
tried = #HAUT
;perso trop bas ^
Else
If (mur & #BAS)=0 And tried <> #BAS
If FindAWay(x,y+1, tx, ty, cpt-1, #BAS, marque, intersection)
ProcedureReturn(#BAS)
EndIf
EndIf
tried = #BAS
EndIf
EndIf
If mur | tried = 15
Calk(x,y) = -1
EndIf
While (tried <> 15)
c = Pow(2, Random(3))
If (tried & c)=0
Select c
Case #HAUT
If (mur & #HAUT)=0 And tried <> #HAUT
If FindAWay(x,y-1, tx, ty, cpt-1, #HAUT, marque, intersection)
ProcedureReturn(#HAUT)
EndIf
EndIf
Case #DROITE
If (mur & #DROITE)=0 And tried <> #DROITE
If FindAWay(x+1,y, tx, ty, cpt-1, #DROITE, marque, intersection)
ProcedureReturn(#DROITE)
EndIf
EndIf
Case #BAS
If (mur & #BAS)=0 And tried <> #BAS
If FindAWay(x,y+1, tx, ty, cpt-1, #BAS, marque, intersection)
ProcedureReturn(#BAS)
EndIf
EndIf
Case #GAUCHE
If (mur & #GAUCHE)=0 And tried <> #GAUCHE
If FindAWay(x-1,y, tx, ty, cpt-1, #GAUCHE, marque, intersection)
ProcedureReturn(#GAUCHE)
EndIf
EndIf
EndSelect
tried = tried | c
EndIf
Wend
ProcedureReturn(0)
EndProcedure
Procedure.b FindDirection(x,y, tx, ty)
If (x = tx) And (y = ty)
ProcedureReturn(0)
EndIf
For j = 0 To 15
For i = 0 To 15
If Map(i,j)
Calk(i,j) = -1
Else
Calk(i,j) = 0
EndIf
Next i
Next j
cpt = (Abs(x - tx) + Abs(y - ty) + 1)/2
Repeat
r.b = FindAWay(x,y, tx,ty, cpt, 0, 1,cpt>7)
If r
ProcedureReturn(r)
EndIf
FindAWay(tx,ty, x,y, cpt, 0, 2,0)
cpt + 2
If cpt = 40
End
EndIf
ForEver
EndProcedure
Puis j'ai fais un code avec ce que j'ai appris brievement en maths : les graphes. J'ai donc repérer les noeuds de la carte (case où il n'y a qu'un ou aucun mur sur la case à côté (non diagonale) ).
De là je répartie la carte en zone. Je repère les zones qui se touchent. Je détermine la distance entre les 2 noeuds des zones juxtaposées. Puis je détermine par quelle zone il faut passer (étapes, point "médian") pour arriver au but.
Donc tous les calculs se font à la création de la carte. Ainsi les calculs entre les déplacements sont minimes et les déplacements sont donc quasi-instantanés.
Voici donc ce dernier code (beaucoup plus complexe que les 2 précédents) :
Code : Tout sélectionner
Structure Noeud
x.w
y.w
num.w
EndStructure
Declare.b MapNotCompletelyAnalysed()
Declare GetNodes()
Declare.l CopyToMemory(*p.Noeud)
Declare BuildWay(x.w, y.w, num.w, rayon.b)
Declare MakeWays()
Declare MakeGraphe()
Declare BuildGraphe(x.w, y.w, num.w, exDir.b)
Declare GiveWayLength(x.w,y.w, tx.w,ty.w, exDir.b, rayon.b)
Declare CompleteGraphe()
Declare.b GetWay(x.w,y.w, *tx.w,*ty.w)
Declare MakeLinkingGraphe()
Declare AddToLinkingGraphe(cur.b, fin.b, deb.b, suiv.b, cpt.w)
Declare.b FindDirection(x,y, tx, ty)
Declare.b FindAWay(x,y, tx, ty, cpt.b, exDir.b)
RandomSeed(ElapsedMilliseconds())
#HAUT = 1
#DROITE = 2
#BAS = 4
#GAUCHE = 8
#SPRITE = 32
Dim Map.b(15,15)
Dim Calk.b(15,15)
Dim Link.b(15,15)
NewList Inter.l()
Global NbElts.w
For j = 0 To 14
For i = 0 To 14
Read Map(i,j)
Next i
Next j
GetNodes()
Dim Graphe.w(NbElts, NbElts)
Dim Graph2.w(NbElts, NbElts)
Dim Way.b(NbElts)
MakeGraphe()
MakeLinkingGraphe()
PersoX = 1
PersoY = 1
TargetX.w = PersoX
TargetY.w = PersoY
MiddleX.w = PersoX
MiddleY.w = PersoX
ShowCursor_(1)
ShowCursor_(1)
ShowCursor_(1)
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse()=0
MessageRequester("Error", "Can't open DirectX 7 or later", 0)
End
EndIf
OpenScreen(640, 480, 16, "Sprite")
; - - - - - - - - - - - BOUCLE - - - - - - - - - - -
Repeat
FlipBuffers()
If IsScreenActive()
ClearScreen(0,0,0)
ReleaseMouse(0)
ExamineKeyboard(): ExamineMouse()
If MouseButton(1)
If Map(Int(MouseX()/#SPRITE), Int(MouseY()/#SPRITE)) = 0
TargetX = MouseX()/#SPRITE: MiddleX = TargetX
TargetY = MouseY()/#SPRITE: MiddleY = TargetY
EndIf
EndIf
nextDir = GetWay(PersoX,PersoY, @MiddleX, @MiddleY)
Select nextDir
Case #HAUT
PersoY - 1
Case #DROITE
PersoX + 1
Case #BAS
PersoY + 1
Case #GAUCHE
PersoX - 1
EndSelect
If PersoX = MiddleX And PersoY = MiddleY
MiddleX = TargetX
MiddleY = TargetY
EndIf
StartDrawing(ScreenOutput())
For j = 0 To 14
For i = 0 To 14
If Map(i,j)
Box(i*#SPRITE, j*#SPRITE, #SPRITE, #SPRITE, RGB(255,255,255))
EndIf
;Locate(i*#SPRITE, j*#SPRITE): FrontColor(0,128,255)
;DrawText(Str(Calk(i,j)))
Next i
Next j
Line(MiddleX*#SPRITE, MiddleY*#SPRITE, #SPRITE, #SPRITE, RGB(0,0,255))
Line(MiddleX*#SPRITE, (MiddleY+1)*#SPRITE-1, #SPRITE, 0-#SPRITE, RGB(0,0,255))
Line(TargetX*#SPRITE, TargetY*#SPRITE, #SPRITE, #SPRITE, RGB(255,0,0))
Line(TargetX*#SPRITE, (TargetY+1)*#SPRITE-1, #SPRITE, 0-#SPRITE, RGB(255,0,0))
For i = 1 To 7
Circle((PersoX*#SPRITE) + #SPRITE/2, (PersoY*#SPRITE) + #SPRITE/2, i, RGB(255,255,0))
Next i
StopDrawing()
SetCursorPos_(MouseX(), MouseY())
Else
ReleaseMouse(1)
EndIf
Until KeyboardPushed(#PB_Key_Escape)
CloseScreen(): End
; - - - - - - - - - - - - - - - - - - - - - - - - -
DataSection
Data.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.b 1,0,0,0,0,0,0,1,0,0,0,0,0,1,1
Data.b 1,0,1,1,0,1,0,1,0,1,1,1,0,0,1
Data.b 1,0,1,1,0,1,0,0,0,1,1,1,1,0,1
Data.b 1,0,0,1,0,1,0,1,0,1,0,0,1,0,1
Data.b 1,1,0,1,0,1,0,1,0,0,0,0,0,0,1
Data.b 1,0,0,0,0,1,0,1,1,1,1,0,1,1,1
Data.b 1,1,1,1,1,1,0,1,0,0,0,0,1,0,1
Data.b 1,0,0,0,0,0,0,1,0,1,1,0,1,0,1
Data.b 1,0,1,1,0,1,1,1,0,0,1,0,1,0,1
Data.b 1,0,1,0,0,1,0,1,1,0,1,0,1,0,1
Data.b 1,0,1,0,1,1,0,1,1,0,1,0,1,0,1
Data.b 1,0,1,0,0,1,0,1,1,1,1,0,1,0,1
Data.b 1,0,0,0,0,0,0,1,0,0,0,0,0,0,1
Data.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
EndDataSection
Procedure.b MapNotCompletelyAnalysed()
For j = 1 To 13
For i = 1 To 13
If Calk(i,j) = 0
ProcedureReturn(1)
EndIf
Next i
Next j
EndProcedure
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Création des noeuds
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Procedure GetNodes()
*p.Noeud = AllocateMemory(6)
For j = 1 To 13
For i = 1 To 13
If Map(i,j)=0
If Map(i,j-1) + Map(i+1,j) + Map(i,j+1) + Map(i-1,j) < 2
NbElts + 1
*p\x = i
*p\y = j
*p\num = NbElts
LastElement(Inter())
AddElement(Inter())
Inter() = CopyToMemory(*p)
Calk(i,j) = NbElts
EndIf
Else
Calk(i,j) = -1
EndIf
Next i
Next j
FreeMemory(*p)
MakeWays()
EndProcedure
Procedure.l CopyToMemory(*p.Noeud)
*m.Noeud = AllocateMemory(SizeOf(*p))
If *m
CopyMemory(*p, *m, SizeOf(Noeud))
ProcedureReturn(*m)
Else
MessageRequester("Error!", "Unable to allocate memory", #PB_MessageRequester_OK)
EndIf
EndProcedure
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Création des zones
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Procedure BuildWay(x.w, y.w, num.w, rayon.b)
If Calk(x,y) = 0
Calk(x,y) = num
EndIf
If rayon = 0
ProcedureReturn
EndIf
mur = Map(x,y-1)*#HAUT + Map(x+1,y)*#DROITE + Map(x,y+1)*#BAS + Map(x-1,y)*#GAUCHE
If (mur & #GAUCHE)=0
BuildWay(x-1, y, num, rayon-1)
EndIf
If (mur & #DROITE)=0
BuildWay(x+1, y, num, rayon-1)
EndIf
If (mur & #BAS)=0
BuildWay(x, y+1, num, rayon-1)
EndIf
If (mur & #HAUT)=0
BuildWay(x, y-1, num, rayon-1)
EndIf
EndProcedure
Procedure MakeWays()
rayon = 1
*ad.Noeud
While MapNotCompletelyAnalysed()
ResetList(Inter())
While NextElement(Inter())
*ad = Inter()
BuildWay(*ad\x, *ad\y, *ad\num, rayon)
Wend
rayon + 1
Wend
EndProcedure
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Cration du graphe des zones juxtaposées
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Procedure MakeGraphe()
*ad.Noeud
ResetList(Inter())
While NextElement(Inter())
*ad = Inter()
BuildGraphe(*ad\x, *ad\y, *ad\num, 0)
Wend
CompleteGraphe()
EndProcedure
Procedure BuildGraphe(x.w, y.w, num.w, exDir.b)
If Calk(x,y) <> num
Graphe(num, Calk(x,y)) = 1
ProcedureReturn
EndIf
mur = Map(x,y-1)*#HAUT + Map(x+1,y)*#DROITE + Map(x,y+1)*#BAS + Map(x-1,y)*#GAUCHE
If (mur & #GAUCHE)=0 And exDir <> #DROITE
BuildGraphe(x-1, y, num, #GAUCHE)
EndIf
If (mur & #DROITE)=0 And exDir <> #GAUCHE
BuildGraphe(x+1, y, num, #DROITE)
EndIf
If (mur & #BAS)=0 And exDir <> #HAUT
BuildGraphe(x, y+1, num, #BAS)
EndIf
If (mur & #HAUT)=0 And exDir <> #BAS
BuildGraphe(x, y-1, num, #HAUT)
EndIf
EndProcedure
Procedure CompleteGraphe()
*m.Noeud: *n.Noeud
For i = 1 To nbElts-1
For j = i+1 To nbElts
If Graphe(i,j)
SelectElement(Inter(), i-1)
*m = Inter()
SelectElement(Inter(), j-1)
*n = Inter()
rayon = Abs(*m\x - *n\x) + Abs(*m\y - *n\y)
Repeat
t = GiveWayLength(*m\x,*m\y, *n\x,*n\y, 0, rayon)
rayon + 1
Until t
Graphe(i,j) = rayon-1
Graphe(j,i) = rayon-1
EndIf
Next j
Next i
EndProcedure
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Distance entre 2 pts
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Procedure GiveWayLength(x.w,y.w, tx.w,ty.w, exDir.b, rayon.b)
If x = tx And y = ty
ProcedureReturn(1)
ElseIf rayon = 0
ProcedureReturn(0)
EndIf
mur = Map(x,y-1)*#HAUT + Map(x+1,y)*#DROITE + Map(x,y+1)*#BAS + Map(x-1,y)*#GAUCHE
If (mur & #GAUCHE)=0 And exDir <> #DROITE
If GiveWayLength(x-1,y, tx,ty, #GAUCHE, rayon-1)
ProcedureReturn 1
EndIf
EndIf
If (mur & #DROITE)=0 And exDir <> #GAUCHE
If GiveWayLength(x+1,y, tx,ty, #DROITE, rayon-1)
ProcedureReturn 1
EndIf
EndIf
If (mur & #BAS)=0 And exDir <> #HAUT
If GiveWayLength(x,y+1, tx,ty, #BAS, rayon-1)
ProcedureReturn 1
EndIf
EndIf
If (mur & #HAUT)=0 And exDir <> #BAS
If GiveWayLength(x,y-1, tx,ty, #HAUT, rayon-1)
ProcedureReturn 1
EndIf
EndIf
EndProcedure
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Directiion du personnage
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Procedure.b GetWay(x.w,y.w, *tx.w,*ty.w)
If Calk(x,y) <> Calk(PeekW(*tx),PeekW(*ty))
If Link( Calk(PeekW(*tx),PeekW(*ty)), Calk(x,y) )
SelectElement(Inter(), Link( Calk(PeekW(*tx),PeekW(*ty)), Calk(x,y) )-1)
*n.Noeud = Inter()
PokeW(*tx, *n\x)
PokeW(*ty, *n\y)
EndIf
EndIf
ProcedureReturn( FindDirection(x,y, PeekW(*tx),PeekW(*ty)) )
EndProcedure
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Création du graphe des étapes
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Procedure AddToLinkingGraphe(cur.b, fin.b, deb.b, suiv.b, cpt.w)
If Way(cur)
ProcedureReturn(0)
EndIf
Way(cur) = 1
If Graphe(cur,fin)
; on a trouvé un chemin
If Graphe(fin,0) > cpt + Graphe(cur,fin)
Graphe(fin,0) = cpt + Graphe(cur,fin)
Link(fin, deb) = suiv
Link(deb, fin) = cur
Else
If fin = 66
Debug "Un chemin plus court existe (lg="+Str(Graphe(fin,0))+")"
EndIf
EndIf
Else
; Pas de chemin direct
For i = 1 To NbElts
If Graphe(i,cur)
AddToLinkingGraphe(i, fin, deb, suiv, cpt+Graphe(i,cur))
EndIf
Next i
EndIf
Way(cur) = 0
EndProcedure
Procedure MakeLinkingGraphe()
For j = 1 To NbElts
For i = 1 To NbElts
If Graphe(i,j)
Link(i,j) = i
EndIf
Graph2(i,j) = Graphe(i,j)
Next i
Next j
For j = 1 To NbElts
For i = 1 To NbElts
; réinitialisation des tableaux
For in = 0 To NbElts
Way(in) = 0: Graphe(in,0)=127
Next in
; recherche
If i<>j
For k = 1 To NbElts
If Graphe(i, j)
AddToLinkingGraphe(Link(i,j), j, i, j, 0)
ElseIf Graphe(k,i)
AddToLinkingGraphe(Link(k,i), j, i, k, Graphe(k,i))
EndIf
Next k
EndIf
If j<>i
Graph2(j,i)= Graphe(j,0)
Graph2(i,j)= Graphe(j,0)
EndIf
Next i
Next j
EndProcedure
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Fonctions récursives pour trouver un chemin
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Procedure.b FindAWay(x,y, tx, ty, cpt.b, exDir.b)
difX = (x - tx)
difY = (y - ty)
If x = tx And y = ty
ProcedureReturn(15)
ElseIf Abs(difX) + Abs(difY) > cpt
ProcedureReturn(0)
EndIf
mur = Map(x,y-1)*#HAUT + Map(x+1,y)*#DROITE + Map(x,y+1)*#BAS + Map(x-1,y)*#GAUCHE
tried.b = (exDir * 4) % 15
If Abs(difX) > Abs(difY)
; perso trop à droite : <=
If x > tx
If (mur & #GAUCHE)=0 And tried <> #GAUCHE
If FindAWay(x-1,y, tx, ty, cpt-1, #GAUCHE)
ProcedureReturn(#GAUCHE)
EndIf
EndIf
tried = #GAUCHE
;perso trop à gauche =>
Else
If (mur & #DROITE)=0 And tried <> #DROITE
If FindAWay(x+1,y, tx, ty, cpt-1, #DROITE)
ProcedureReturn(#DROITE)
EndIf
EndIf
tried = #DROITE
EndIf
Else
; perso trop haut
If y > ty
If (mur & #HAUT)=0 And tried <> #HAUT
If FindAWay(x,y-1, tx, ty, cpt-1, #HAUT)
ProcedureReturn(#HAUT)
EndIf
EndIf
tried = #HAUT
;perso trop bas ^
Else
If (mur & #BAS)=0 And tried <> #BAS
If FindAWay(x,y+1, tx, ty, cpt-1, #BAS)
ProcedureReturn(#BAS)
EndIf
EndIf
tried = #BAS
EndIf
EndIf
While (tried <> 15)
c = Pow(2, Random(3))
If (tried & c)=0
Select c
Case #HAUT
If (mur & #HAUT)=0 And tried <> #HAUT
If FindAWay(x,y-1, tx, ty, cpt-1, #HAUT)
ProcedureReturn(#HAUT)
EndIf
EndIf
Case #DROITE
If (mur & #DROITE)=0 And tried <> #DROITE
If FindAWay(x+1,y, tx, ty, cpt-1, #DROITE)
ProcedureReturn(#DROITE)
EndIf
EndIf
Case #BAS
If (mur & #BAS)=0 And tried <> #BAS
If FindAWay(x,y+1, tx, ty, cpt-1, #BAS)
ProcedureReturn(#BAS)
EndIf
EndIf
Case #GAUCHE
If (mur & #GAUCHE)=0 And tried <> #GAUCHE
If FindAWay(x-1,y, tx, ty, cpt-1, #GAUCHE)
ProcedureReturn(#GAUCHE)
EndIf
EndIf
EndSelect
tried = tried | c
EndIf
Wend
ProcedureReturn(0)
EndProcedure
Procedure.b FindDirection(x,y, tx, ty)
If (x = tx) And (y = ty)
ProcedureReturn(0)
EndIf
cpt = Abs(x - tx) + Abs(y - ty)
Repeat
r.b = FindAWay(x,y, tx,ty, cpt, 0)
cpt + 1
If cpt = 40
End
EndIf
Until r
ProcedureReturn(r)
EndProcedure
Si vous connaissez des sites qui expliquent bien comment faire des IA, je suis preneur.
Maintenant, je vais faire un système de WayPoints (pour des voitures)
@ ++