diff --git a/cmd/simu/main.go b/cmd/simu/main.go index f963e03be40af2a537924923ad7f76bad953b94a..9c17dbaeda87fa72e40546a19735b10ffc6b5cd1 100644 --- a/cmd/simu/main.go +++ b/cmd/simu/main.go @@ -6,7 +6,7 @@ import ( ) func main() { - s := simulation.NewSimulation(10, -1, 600*time.Second) + s := simulation.NewSimulation(20, -1, 600*time.Second) //go simulation.StartAPI(s) s.Run() } diff --git a/internal/algorithms/astar.go b/internal/algorithms/astar.go index 8b7ad9435a783d0932d36ec7173a9b78bc567068..d1fc5062c3e54db8733201f9de67c1036b26b6e1 100644 --- a/internal/algorithms/astar.go +++ b/internal/algorithms/astar.go @@ -2,12 +2,12 @@ package algorithms import ( "container/heap" + "math/rand" ) /* * Utilisation de l'algorithme A* pour les déplacements * //TODO: Peut-être gérer un passage par référence et non par copie - * //TODO: faire des points de repère */ type Node struct { row, col, cost, heuristic, width, height, orientation int @@ -167,7 +167,9 @@ func getNeighbors(matrix [20][20]string, current, end Node, forbiddenCell Node, func Heuristic(row, col int, end Node) int { // Heuristique simple : distance de Manhattan - return abs(row-end.row) + abs(col-end.col) + // On introduit de l'aléatoire pour ajouter de la diversité dans la construction des chemins + // On évite d'avoir tout le temps le même chemin pour un même point de départ et d'arrivé + return abs(row-end.row) + abs(col-end.col) + rand.Intn(3) } func abs(x int) int { diff --git a/internal/simulation/agent.go b/internal/simulation/agent.go index a9af413195bb30620b1b8d6dad33f642508dcf03..686c830361e8c99d27f3e51a7bb35678ac685ceb 100644 --- a/internal/simulation/agent.go +++ b/internal/simulation/agent.go @@ -6,11 +6,9 @@ package simulation * // TODO: Gérer les moments où les agents font du quasi-sur place car ils ne peuvent plus bouger * // TODO: Il arrive encore que certains agents soient bloqués, mais c'est quand il n'y a aucun mouvement possible. * // Il faudrait faire en sorte que les agents bougent et laisse passer les autres - * // TODO: vérifier map playground, destination en (0,0) (normalement résolu si ajout de panneaux et zones) */ import ( - //"fmt" //"fmt" "log" "math/rand" @@ -28,6 +26,7 @@ const ( Mark Wait Move + Disapear ) type Coord [2]int @@ -88,6 +87,10 @@ func (ag *Agent) Start() { ag.behavior.Deliberate(ag) ag.behavior.Act(ag) ag.syncChan <- step + if ag.decision == Disapear{ + ag.env.RemoveAgent(*ag) + return + } } }() } @@ -120,7 +123,7 @@ func IsMovementSafe(path []alg.Node, agt *Agent, env *Environment) (bool, int) { if !(borneInfCol < 0 || borneInfRow < 0 || borneSupRow > 20 || borneSupCol > 20) { for i := borneInfRow; i < borneSupRow; i++ { for j := borneInfCol; j < borneSupCol; j++ { - if !(j >= infCol && j < supCol && i >= infRow && i < supRow) && (env.station[i][j] != "B" && env.station[i][j] != "_") { + if !(j >= infCol && j < supCol && i >= infRow && i < supRow) && (env.station[i][j] != "B" && env.station[i][j] != "_" && env.station[i][j] != "W" && env.station[i][j] != "S") { // Si on n'est pas sur une case atteignable, en dehors de la zone qu'occupe l'agent avant déplacement, on est bloqué safe = false } @@ -205,8 +208,6 @@ func (ag *Agent) isStuck() bool { func (ag *Agent) MoveAgent() { - // ============ Initialisation des noeuds de départ ====================== - // ================== Tentative de calcul du chemin ======================= if len(ag.path) == 0 { start, end := ag.generatePathExtremities() @@ -217,16 +218,18 @@ func (ag *Agent) MoveAgent() { // ================== Etude de faisabilité ======================= if IsAgentBlocking(ag.path, ag, ag.env) { // TODO:voir comment gérer les situations de blocage - start, end := ag.generatePathExtremities() + //start, end := ag.generatePathExtremities() // Si un agent bloque notre déplacement, on attend un temps aléatoire, et reconstruit un chemin en évitant la position time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond) - path := alg.FindPath(ag.env.station, start, end, ag.path[0], false) + //path := alg.FindPath(ag.env.station, start, end, ag.path[0], false) time.Sleep(time.Second) - ag.path = path + //ag.path = path + return } + // ================== Déplacement si aucun problème ======================= safe, or := IsMovementSafe(ag.path, ag, ag.env) if safe { - removeAgent(&ag.env.station, ag) + RemoveAgent(&ag.env.station, ag) rotateAgent(ag, or) //ag.env.station[ag.coordBasOccupation[0]][ag.coordBasOccupation[1]] = ag.isOn ag.position[0] = ag.path[0].Row() @@ -253,7 +256,7 @@ func (ag *Agent) generatePathExtremities() (alg.Node, alg.Node) { return start, end } -func removeAgent(matrix *[20][20]string, agt *Agent) { +func RemoveAgent(matrix *[20][20]string, agt *Agent) { // Supprime l'agent de la matrice // Calcul des bornes de position de l'agent diff --git a/internal/simulation/env.go b/internal/simulation/env.go index 55ca9ccec59613c9ab9f227d7946424fbc3ea3d4..9ecf0fb640bbe1ca95ed42286e342e95b21af82b 100644 --- a/internal/simulation/env.go +++ b/internal/simulation/env.go @@ -26,6 +26,18 @@ func (env *Environment) AddAgent(agt Agent) { env.agentCount++ } +func (env *Environment) RemoveAgent(agt Agent) { + for i := 0; i < len(env.station); i++ { + if env.ags[i].id == agt.id{ + // Utiliser la syntaxe de découpage pour supprimer l'élément + env.ags = append(env.ags[:i], env.ags[i+1:]...) + // Sortir de la boucle après avoir trouvé et supprimé l'élément + break + } + } + env.agentCount-- +} + func (env *Environment) Do(a Action, c Coord) (err error) { env.Lock() defer env.Unlock() diff --git a/internal/simulation/simu.go b/internal/simulation/simu.go index b0e50637551c5cec93a2edc76118dd150909b94f..04ae4b4603024f070608dc3604242dc982c74c4f 100644 --- a/internal/simulation/simu.go +++ b/internal/simulation/simu.go @@ -151,7 +151,13 @@ func NewSimulation(agentCount int, maxStep int, maxDuration time.Duration) (simu //ag := NewAgent(id, &simu.env, syncChan, time.Duration(time.Second), 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, 1000, 0, true, &UsagerLambda{}, Coord{3, 4}, Coord{18, 12}, 2, 1) - ag := NewAgent(id, &simu.env, syncChan, 1000, 0, true, &UsagerLambda{}, Coord{18, 4}, Coord{1, 8}, 1, 1) + ag := &Agent{} + if i%2==0{ + ag = NewAgent(id, &simu.env, syncChan, 1000, 0, true, &UsagerLambda{}, Coord{18, 4}, Coord{0, 8}, 2, 1) + }else{ + ag = NewAgent(id, &simu.env, syncChan, 1000, 0, true, &UsagerLambda{}, Coord{1, 8}, Coord{8, 5}, 1, 1) + } + //ag := NewAgent(id, &simu.env, syncChan, 1000, 0, true, &UsagerLambda{}, Coord{1, 17}, Coord{0, 0}, 2, 1) // ajout de l'agent à la simulation diff --git a/internal/simulation/usagerLambda.go b/internal/simulation/usagerLambda.go index 843be3742b32ab72bbfaef92a5696af2d4cb08ec..abe11892a9c5fab8b36093dd823940647a0f06e6 100644 --- a/internal/simulation/usagerLambda.go +++ b/internal/simulation/usagerLambda.go @@ -1,6 +1,7 @@ package simulation import ( + "fmt" "math/rand" "time" ) @@ -17,7 +18,10 @@ func (ul *UsagerLambda) Percept(ag *Agent) { } func (ul *UsagerLambda) Deliberate(ag *Agent) { - if ag.stuck { + if ag.position == ag.destination && (ag.isOn[ag.position] == "W" || ag.isOn[ag.position] == "S") { + fmt.Println(ag.id, "disapear") + ag.decision = Disapear + } else if ag.stuck { ag.decision = Wait } else { ag.decision = Move @@ -30,6 +34,8 @@ func (ul *UsagerLambda) Act(ag *Agent) { } else if ag.decision == Wait { n := rand.Intn(2) // temps d'attente aléatoire time.Sleep(time.Duration(n) * time.Second) + } else if ag.decision == Disapear { + RemoveAgent(&ag.env.station, ag) } }