From 342c2043415d3ec0124f6834391c96ccbec3a1e1 Mon Sep 17 00:00:00 2001 From: julienpillis <pllsjulien@gmail.com> Date: Sun, 3 Dec 2023 10:55:44 +0100 Subject: [PATCH] =?UTF-8?q?am=C3=A9liorations=20d=C3=A9placement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agent.go | 91 +++++++++++++++++++++++++++++++++++++++--------- cmd/simu/main.go | 2 +- simu.go | 2 +- 3 files changed, 77 insertions(+), 18 deletions(-) diff --git a/agent.go b/agent.go index 29eac1c..0ab76b8 100644 --- a/agent.go +++ b/agent.go @@ -2,8 +2,9 @@ package simulation import ( //"container/heap" - //"fmt" + "fmt" "log" + "math" "math/rand" "time" ) @@ -34,6 +35,7 @@ type Agent struct { syncChan chan int decision int isOn string // Contenu de la case sur laquelle il se trouve + stuck bool } type Behavior interface { @@ -47,10 +49,36 @@ type UsagerLambda struct{} func (ul *UsagerLambda) Percept(ag *Agent, env *Environment) { // TODO: Essayer un nouveau chemin quand l'agent est bloqué + + // Perception des éléments autour de l'agent pour déterminer si bloqué + s := 0 // nombre de cases indisponibles autour de l'agent + for i := 0; i < 3; i++ { + for j := 0; j < 3; j++ { + ord := (ag.coordBasOccupation[0] - 1) + i + abs := (ag.coordBasOccupation[1] - 1) + j + + if(ord!=ag.coordBasOccupation[0] && abs !=ag.coordBasOccupation[1]){ + if ord < 0 || abs < 0 || ord > 19 || abs > 19 { + s++ + } else if env.station[ord][abs] == "X" || env.station[ord][abs] == "Q" || env.station[ord][abs] == "A" { + s++ + } + } + } + } + // Si pas de case disponible autour de lui, il est bloqué + // (ag.env.station[ag.departure[0]][ag.departure[1]] == "A" && ag.coordBasOccupation[0] == ag.departure[0] && ag.coordBasOccupation[1] == ag.departure[1]) + if s == 8 { + ag.stuck = true + fmt.Println(ag.id, ag.stuck, ag.coordBasOccupation, s) + } else { + ag.stuck = false + } } func (ul *UsagerLambda) Deliberate(ag *Agent) { - if ag.env.station[ag.departure[0]][ag.departure[1]] == "A" { + // Si l'agent est bloqué, il doit attendre qu'une case se libère autour de lui + if ag.stuck { ag.decision = Wait } else { ag.decision = Move @@ -58,11 +86,12 @@ func (ul *UsagerLambda) Deliberate(ag *Agent) { } func (ul *UsagerLambda) Act(ag *Agent, env *Environment) { - // TODO: Je crois que la construction d'un chemin s'arrête s'il y a déjà un agent sur destination. Il faudrait donc faire en sorte de s'approcher le plus possible if ag.decision == Move { + start := ag.coordBasOccupation end := ag.destination - path := findPathBFS(ag.env.station, start, end) + _, path := findClosestPointBFS(ag.env.station, start, end) + if len(path) > 0 && env.station[path[0][0]][path[0][1]] != "A" { // TODO: Pas ouf les conditions je trouve ag.env.station[ag.coordBasOccupation[0]][ag.coordBasOccupation[1]] = ag.isOn ag.isOn = ag.env.station[path[0][0]][path[0][1]] @@ -71,19 +100,18 @@ func (ul *UsagerLambda) Act(ag *Agent, env *Environment) { ag.env.station[ag.coordBasOccupation[0]][ag.coordBasOccupation[1]] = "A" } //vitesseInSeconds := int(ag.vitesse) - // Multiply the vitesse by time.Second //sleepDuration := time.Duration(vitesseInSeconds) * time.Second time.Sleep(200 * time.Millisecond) } if ag.decision == Wait { - n := rand.Intn(1) // n will be between 0 and 10 + n := rand.Intn(2) // temps d'attente aléatoire time.Sleep(time.Duration(n) * time.Second) } } func NewAgent(id string, env *Environment, syncChan chan int, vitesse int, force int, politesse bool, UpCoord Coord, DownCoord Coord, behavior Behavior, departure, destination Coord) *Agent { - return &Agent{AgentID(id), vitesse, force, politesse, UpCoord, DownCoord, departure, destination, behavior, env, syncChan, Noop, env.station[UpCoord[0]][UpCoord[1]]} + return &Agent{AgentID(id), vitesse, force, politesse, UpCoord, DownCoord, departure, destination, behavior, env, syncChan, Noop, env.station[UpCoord[0]][UpCoord[1]], false} } func (ag *Agent) ID() AgentID { @@ -165,39 +193,66 @@ func findPathBFS(matrix [20][20]string, start, end Coord) []Coord { } */ -func findPathBFS(matrix [20][20]string, start, end Coord) []Coord { +func distance(coord1, coord2 Coord) float64 { + dx := float64(coord1[0] - coord2[0]) + dy := float64(coord1[1] - coord2[1]) + return math.Sqrt(dx*dx + dy*dy) +} + +func findClosestPointBFS(matrix [20][20]string, start, end Coord) (Coord, []Coord) { queue := []Coord{start} visited := make(map[Coord]bool) parents := make(map[Coord]Coord) + closestPoint := start // Initialisez avec le point de départ + closestDistance := distance(start, end) + foundPath := false for len(queue) > 0 { current := queue[0] queue = queue[1:] + // Mettez à jour le point le plus proche si le point actuel est plus proche + currentDistance := distance(current, end) + if currentDistance < closestDistance { + closestPoint = current + closestDistance = currentDistance + } + if current == end { - // Construire le chemin à partir des parents - path := []Coord{current} - for parent, ok := parents[current]; ok; parent, ok = parents[parent] { + // Construire le chemin du point le plus proche à la destination + path := []Coord{closestPoint} + for parent, ok := parents[closestPoint]; ok; parent, ok = parents[parent] { path = append([]Coord{parent}, path...) } - return path[1:] + return closestPoint, path[1:] } visited[current] = true - neighbors := getNeighborsBFS(matrix, current) + neighbors := getNeighborsBFS(matrix, current, end) for _, neighbor := range neighbors { if !visited[neighbor] { parents[neighbor] = current queue = append(queue, neighbor) } } + + foundPath = true + } + + if foundPath { + // Retourner le chemin le plus proche même si la destination n'a pas été atteinte + path := []Coord{closestPoint} + for parent, ok := parents[closestPoint]; ok; parent, ok = parents[parent] { + path = append([]Coord{parent}, path...) + } + return closestPoint, path[1:] } - return nil // Aucun chemin trouvé + return closestPoint, nil // Aucun chemin trouvé } -func getNeighborsBFS(matrix [20][20]string, current Coord) []Coord { +func getNeighborsBFS(matrix [20][20]string, current Coord, end Coord) []Coord { neighbors := make([]Coord, 0) // Déplacements possibles : haut, bas, gauche, droite @@ -208,7 +263,11 @@ func getNeighborsBFS(matrix [20][20]string, current Coord) []Coord { // Vérifier si la nouvelle position est valide et non visitée if newRow >= 0 && newRow < len(matrix) && newCol >= 0 && newCol < len(matrix[0]) && (matrix[newRow][newCol] != "Q" && matrix[newRow][newCol] != "X") { - neighbors = append(neighbors, Coord{newRow, newCol}) + if !(matrix[newRow][newCol] == "A" && newRow != end[0] && newCol != end[1]) { + // Si la case du chemin ne comporte pas d'agent et que ce n'est pas la case d'arrivée, on peut l'ajouter + neighbors = append(neighbors, Coord{newRow, newCol}) + } + } } diff --git a/cmd/simu/main.go b/cmd/simu/main.go index ea7a7f1..c432c7d 100644 --- a/cmd/simu/main.go +++ b/cmd/simu/main.go @@ -6,7 +6,7 @@ import ( ) func main() { - s := simulation.NewSimulation(30, -1, 600*time.Second) + s := simulation.NewSimulation(20, -1, 600*time.Second) //go simulation.StartAPI(s) s.Run() } diff --git a/simu.go b/simu.go index 69b4e64..d3b8cac 100644 --- a/simu.go +++ b/simu.go @@ -88,7 +88,7 @@ func NewSimulation(agentCount int, maxStep int, maxDuration time.Duration) (simu // création de l'agent id := fmt.Sprintf("Agent #%d", i) syncChan := make(chan int) - ag := NewAgent(id, &simu.env, syncChan, 1, 0, true, Coord{0, 8 + i%2}, Coord{0, 8 + i%2}, &UsagerLambda{}, Coord{0, 8 + i%2}, Coord{12 - 4*(i%2), 18 - 15*(i%2)}) + ag := NewAgent(id, &simu.env, syncChan, 1, 0, true, Coord{0, 8 + i%2}, Coord{0, 8 + i%2}, &UsagerLambda{},Coord{0, 8 + i%2}, Coord{12 - 4*(i%2), 18 - 15*(i%2)}) //ag := NewAgent(id, &simu.env, syncChan, 1, 0, true, Coord{4,10}, Coord{4,10}, &UsagerLambda{}, Coord{4,10}, Coord{0, 0}) -- GitLab