public void DefinePlayerZones(RobotRole role) { switch (role) { case RobotRole.Positioning: AddPreferedZone(new PointD(externalRefBoxPosition.X, externalRefBoxPosition.Y), 0.3); robotOrientation = 0; break; } }
private void UpdateRobotRole(int robotId, RobotRole role) { if (TeamMatesDisplayDictionary.ContainsKey(robotId)) { TeamMatesDisplayDictionary[robotId].SetRole(role); } else { Console.WriteLine("UpdateRobotRole : Robot non trouvé"); } }
public override void DetermineRobotRole() //A définir dans les classes héritées { switch (gameState) { case GameState.STOPPED: role = RobotRole.Stopped; break; case GameState.PLAYING: { } break; case GameState.STOPPED_GAME_POSITIONING: role = RobotRole.Positioning; break; } DefinePlayerZones(role); }
public TeamMateRoleClassifier(PointD position, RobotRole role) { this.Role = role; Position = position; }
public override void DetermineRobotRole() { /// La détermination des rôles du robot se fait robot par robot, chacun détermine son propre rôle en temps réel. /// Il n'y a pas de centralisation de la détermination dans la Base Station, ce qui permettra ultérieurement de jouer sans base station. /// /// Le Gamestate est donné par la BaseStation via la GlobalWorldMap car il intègre les commandes de la Referee Box /// /// On détermine la situation de jeu : defense / attaque / arret / placement avant remise en jeu / ... /// et on détermine le rôle du robot. /// switch (gameState) { case GameState.STOPPED: role = RobotRole.Stopped; break; case GameState.PLAYING: { /// On commence par créer une liste de TeamMateRoleClassifier qui va permettre de trier intelligemment /// /// /// On détermine le rang du joueur dans l'équipe en fonction de sa distance au ballon /// On détermine le rang du joueur dans l'équipe en fonction de sa distance au but /// /// On regarde si une des équipe a la balle /// Dictionary <int, TeamMateRoleClassifier> teamRoleClassifier = new Dictionary <int, TeamMateRoleClassifier>(); foreach (var teammate in globalWorldMap.teammateLocationList) { TeamMateRoleClassifier player = new TeamMateRoleClassifier(new PointD(teammate.Value.X, teammate.Value.Y), RobotRole.Unassigned); teamRoleClassifier.Add(teammate.Key, player); } foreach (var teammate in teamRoleClassifier) { if (teammate.Key % 10 == 0) { teamRoleClassifier[teammate.Key].Role = RobotRole.Gardien; } } if (playingSide == PlayingSide.Right) { foreach (var teammate in teamRoleClassifier) { if (teammate.Key % 10 != 0) { teamRoleClassifier[teammate.Key].Role = RobotRole.Stone; } } } else { /// On détermine le rang du joueur dans l'équipe en fonction de sa distance au ballon int rangDistanceBalle = -1; if (globalWorldMap.ballLocationList.Count > 0) { var ballPosition = new PointD(globalWorldMap.ballLocationList[0].X, globalWorldMap.ballLocationList[0].Y); for (int i = 0; i < teamRoleClassifier.Count(); i++) { ///On ajoute à la liste en premier la distance à chacun des coéquipiers teamRoleClassifier.ElementAt(i).Value.DistanceBalle = Toolbox.Distance(teamRoleClassifier.ElementAt(i).Value.Position, ballPosition); } } /// On détermine le rang du joueur dans l'équipe en fonction de sa distance au but /// Pour cela il faut d'abord définir la position du but. PointD offensiveGoalPosition; PointD defensiveGoalPosition; if (playingSide == PlayingSide.Right) { offensiveGoalPosition = new PointD(-11, 0); defensiveGoalPosition = new PointD(11, 0); } else { defensiveGoalPosition = new PointD(-11, 0); offensiveGoalPosition = new PointD(11, 0); } for (int i = 0; i < globalWorldMap.teammateLocationList.Count(); i++) { teamRoleClassifier.ElementAt(i).Value.DistanceButOffensif = Toolbox.Distance(teamRoleClassifier.ElementAt(i).Value.Position, offensiveGoalPosition); } ///On détermine à présent si l'équipe à la balle et quel joueur la possède /// var teamBallHandlingState = BallHandlingState.NoBall; int IdplayerHandlingBall = -1; foreach (var teammate in globalWorldMap.teammateBallHandlingStateList) { if (teammate.Value != BallHandlingState.NoBall) { teamBallHandlingState = teammate.Value; IdplayerHandlingBall = teammate.Key; } } /// Les indicateurs principaux nécessaire à la stratégie ont été déterminés : /// Possession de balle, distance au but de chacun des coéquipiers et /// distance à la balle de chacun des équipiers. /// Il est donc posssible de prendre des décisions stratégiques de jeu /// On commence par choisir le mode défense ou attaque selon que l'on a la balle ou pas /// if (teamBallHandlingState == BallHandlingState.NoBall) { /// L'équipe n'a pas la balle, elle se place en mode défense /// On veut deux joueurs en défense placée qui marquent les deux joueurs les plus en avant de l'équipe adverse /// On veut un joueur en contestation de balle /// On veut un joueur en défense d'interception qui coupe les lignes de passe adverses /// A présent, on filtre la liste de l'équipe de manière à trouver le joueur /// le plus proches de la balle n'étant pas le gardien var teamFiltered1 = teamRoleClassifier.Where(x => x.Value.Role == RobotRole.Unassigned).OrderBy(elt => elt.Value.DistanceBalle).ToList(); if (teamFiltered1.Count > 0) { teamRoleClassifier[teamFiltered1.ElementAt(0).Key].Role = RobotRole.DefenseurContesteur; } /// A présent, on filtre la liste de l'équipe de manière à trouver le joueur le plus proche du but à défendre /// n'étant pas gardien, ni défenseur au marquage /// Il devient contesteur de balle var teamFiltered2 = teamRoleClassifier.Where(x => (x.Value.Role == RobotRole.Unassigned)) .OrderBy(elt => elt.Value.DistanceButDefensif).ToList(); if (teamFiltered2.Count > 1) { teamRoleClassifier[teamFiltered2.ElementAt(1).Key].Role = RobotRole.DefenseurMarquage; teamRoleClassifier[teamFiltered2.ElementAt(2).Key].Role = RobotRole.DefenseurMarquage; } /// A présent, on filtre la liste de l'équipe de manière à trouver le joueur le plus proche du but à défendre /// n'étant pas gardien, ni défenseur au marquage, ni contesteur /// Il devient défenseur intercepteur var teamFiltered3 = teamRoleClassifier.Where(x => (x.Value.Role == RobotRole.Unassigned)) .OrderBy(elt => elt.Value.DistanceButDefensif).ToList(); if (teamFiltered3.Count > 0) { teamRoleClassifier[teamFiltered3.ElementAt(0).Key].Role = RobotRole.DefenseurIntercepteur; } } else { /// L'équipe a la balle, elle se place en mode attaque /// On a un joueur ayant le ballon qui est l'attaquant avec balle /// On veut deux joueurs attaquants démarqués avec lignes de passes ouvertes /// On veut un attaquant placé entre un défenseur et l'attaquant ayant la balle /// teamRoleClassifier[IdplayerHandlingBall].Role = RobotRole.AttaquantAvecBalle; var teamFiltered1 = teamRoleClassifier.Where(x => (x.Value.Role == RobotRole.Unassigned)) .OrderBy(elt => elt.Value.DistanceButOffensif).ToList(); if (teamFiltered1.Count > 1) { teamRoleClassifier[teamFiltered1.ElementAt(0).Key].Role = RobotRole.AttaquantDemarque; teamRoleClassifier[teamFiltered1.ElementAt(1).Key].Role = RobotRole.AttaquantDemarque; } /// A présent, on filtre la liste de l'équipe de manière à trouver le joueur le plus proche du but en attaque /// n'étant pas gardien, ni attaquant avec le ballon ni attaquant Démarqué /// Il devient attaquant intercepteur var teamFiltered2 = teamRoleClassifier.Where(x => (x.Value.Role == RobotRole.Unassigned)) .OrderBy(elt => elt.Value.DistanceButOffensif).ToList(); if (teamFiltered2.Count > 0) { teamRoleClassifier[teamFiltered2.ElementAt(0).Key].Role = RobotRole.AttaquantIntercepteur; } } } role = teamRoleClassifier[robotId].Role; } break; case GameState.STOPPED_GAME_POSITIONING: role = RobotRole.Positioning; break; } OnRole(robotId, role); OnBallHandlingState(robotId, BallHandlingState.NoBall); OnMessageDisplay(robotId, MessageDisplay); /// En fonction du rôle attribué, on définit les zones de préférence, les zones à éviter et les zones d'exclusion DefinePlayerZones(role); }
public void DefinePlayerZones(RobotRole role) { ///On exclut d'emblée les surface de réparation pour tous les joueurs if (role != RobotRole.Gardien) { AddForbiddenRectangle(new RectangleD(-11, -11 + 0.75 + 0.2, -3.9 / 2 - 0.2, 3.9 / 2 + 0.2)); AddForbiddenRectangle(new RectangleD(+11 - 0.75 + 0.2, +11, -3.9 / 2 - 0.2, 3.9 / 2 + 0.2)); } /// On a besoin du rang des adversaires en fonction de leur distance au but /// Pour cela il faut d'abord définir la position du but. PointD offensiveGoalPosition; PointD defensiveGoalPosition; if (playingSide == PlayingSide.Right) { offensiveGoalPosition = new PointD(-11, 0); defensiveGoalPosition = new PointD(11, 0); } else { defensiveGoalPosition = new PointD(-11, 0); offensiveGoalPosition = new PointD(11, 0); } switch (role) { case RobotRole.Gardien: /// Gestion du cas du gardien /// Exclusion de tout le terrain sauf la surface de réparation /// Ajout d'une zone préférentielle centrée sur le but /// Réglage du cap pour faire toujours face à la balle if (playingSide == PlayingSide.Right) { AddPreferredRectangle(new RectangleD(11 - 0.75, 11, -3.9 / 2, 3.9 / 2)); AddPreferedZone(new PointD(10.6, 0), 4.5, 0.2); } else { AddPreferredRectangle(new RectangleD(-11, -11 + 0.75, -3.9 / 2, 3.9 / 2)); AddPreferedZone(new PointD(-10.6, 0), 4.5, 0.2); } if (globalWorldMap.ballLocationList.Count > 0) { robotOrientation = Math.Atan2(globalWorldMap.ballLocationList[0].Y - robotCurrentLocation.Y, globalWorldMap.ballLocationList[0].X - robotCurrentLocation.X); } break; case RobotRole.Stone: AddPreferedZone(new PointD(-5, 4), 2.5); AddPreferedZone(new PointD(-5, -4), 2.5); AddPreferedZone(new PointD(5, -4), 2.5); AddPreferedZone(new PointD(5, 4), 2.5); break; case RobotRole.Positioning: AddPreferedZone(new PointD(externalRefBoxPosition.X, externalRefBoxPosition.Y), 5); robotOrientation = 0; break; case RobotRole.DefenseurContesteur: if (globalWorldMap.ballLocationList.Count > 0) { AddPreferedZone(new PointD(globalWorldMap.ballLocationList[0].X, globalWorldMap.ballLocationList[0].Y), 3, 0.5); } if (globalWorldMap.ballLocationList.Count > 0) { robotOrientation = Math.Atan2(globalWorldMap.ballLocationList[0].Y - robotCurrentLocation.Y, globalWorldMap.ballLocationList[0].X - robotCurrentLocation.X); } break; case RobotRole.DefenseurMarquage: { /// On va placer un défenseur à une distance définie de l'attaquant, sur la ligne attaquant but /// Les zones d'intérêt sont devant les deux attaquants les plus en pointe /// Il faut donc commencer par les trouver Dictionary <int, TeamMateRoleClassifier> adversaireClassifier = new Dictionary <int, TeamMateRoleClassifier>(); int i = 0; foreach (var adversaire in globalWorldMap.obstacleLocationList) { var adv = new TeamMateRoleClassifier(new PointD(adversaire.X, adversaire.Y), RobotRole.Adversaire); adv.DistanceButDefensif = Toolbox.Distance(new PointD(adversaire.X, adversaire.Y), defensiveGoalPosition); adversaireClassifier.Add(i++, adv); } /// A présent, on filtre la liste des adversaires de manière à trouver les joueurs les plus proches du but en défense /// var teamFiltered1 = adversaireClassifier.OrderBy(elt => elt.Value.DistanceButDefensif).ToList(); if (teamFiltered1.Count > 1) { if (playingSide == PlayingSide.Right) { AddPreferedZone(new PointD(teamFiltered1[0].Value.Position.X + 2, teamFiltered1[0].Value.Position.Y), 1.5); AddPreferedZone(new PointD(teamFiltered1[1].Value.Position.X + 2, teamFiltered1[1].Value.Position.Y), 1.5); } else { AddPreferedZone(new PointD(teamFiltered1[0].Value.Position.X - 2, teamFiltered1[0].Value.Position.Y), 1.5); AddPreferedZone(new PointD(teamFiltered1[1].Value.Position.X - 2, teamFiltered1[1].Value.Position.Y), 1.5); } } if (globalWorldMap.ballLocationList.Count > 0) { robotOrientation = Math.Atan2(globalWorldMap.ballLocationList[0].Y - robotCurrentLocation.Y, globalWorldMap.ballLocationList[0].X - robotCurrentLocation.X); } } break; case RobotRole.DefenseurIntercepteur: { /// On va placer un défenseur à une distance définie de l'attaquant, sur la ligne attaquant but /// Les zones d'intérêt sont devant les deux attaquants les plus en pointe /// Il faut donc commencer par les trouver Dictionary <int, TeamMateRoleClassifier> adversaireClassifier = new Dictionary <int, TeamMateRoleClassifier>(); int i = 0; foreach (var adversaire in globalWorldMap.obstacleLocationList) { var adv = new TeamMateRoleClassifier(new PointD(adversaire.X, adversaire.Y), RobotRole.Adversaire); adv.DistanceButDefensif = Toolbox.Distance(new PointD(adversaire.X, adversaire.Y), defensiveGoalPosition); adversaireClassifier.Add(i++, adv); } /// A présent, on filtre la liste des adversaires de manière à trouver les joueurs les plus proches du but en défense /// var teamFiltered1 = adversaireClassifier.OrderBy(elt => elt.Value.DistanceButDefensif).ToList(); if (teamFiltered1.Count > 1) { var adversaire1 = teamFiltered1[0].Value.Position; var adversaire2 = teamFiltered1[1].Value.Position; AddPreferredSegmentZoneList(new PointD(adversaire1.X, adversaire1.Y), new PointD(adversaire2.X, adversaire2.Y), 0.4, 0.1); AddPreferedZone(new PointD((adversaire1.X + adversaire2.X) / 2, (adversaire1.Y + adversaire2.Y) / 2), 0.4, 0.3); AddAvoidanceZone(new PointD(adversaire1.X, adversaire1.Y), 2, 0.5); //AddPreferedZone(new PointD((teamFiltered1[0].Value.Position.X + teamFiltered1[1].Value.Position.X) / 2, (teamFiltered1[0].Value.Position.Y + teamFiltered1[0].Value.Position.Y) / 2), 2.5); } if (globalWorldMap.ballLocationList.Count > 0) { robotOrientation = Math.Atan2(globalWorldMap.ballLocationList[0].Y - robotCurrentLocation.Y, globalWorldMap.ballLocationList[0].X - robotCurrentLocation.X); } } break; case RobotRole.AttaquantDemarque: /// Gestion du cas de l'attaquant démarqué /// Il doit faire en sorte que la ligne de passe entre lui et le porteur du ballon soit libre /// Pour cela il faudrait idéalement placer une zone de pénalisation conique de centre le joueur dans l'axe de chaque adversaire /// Il doit également se placer dans un position de tir possible /// Pour cela il faudrait idéalement placer une zone de pénalisation conique de centre le but dans l'axe de chaque adversaire if (playingSide == PlayingSide.Left) { AddPreferredSegmentZoneList(new PointD(7, -3), new PointD(7, 3), 3, 1); //AddPreferedZone(new PointD(8, 3), 3, 0.1); //AddPreferedZone(new PointD(8, -3), 3, 0.1); } else { //AddPreferredSegmentZoneList(new PointD(-7, -3), new PointD(-7, 3), 3, 1); //AddPreferedZone(new PointD(-8, 3), 3, 0.1); //AddPreferedZone(new PointD(-8, -3), 3, 0.1); } foreach (var adversaire in globalWorldMap.obstacleLocationList) { AddAvoidanceConicalZoneList(new PointD(robotCurrentLocation.X, robotCurrentLocation.Y), new PointD(adversaire.X, adversaire.Y), 1); } if (globalWorldMap.ballLocationList.Count > 0) { robotOrientation = Math.Atan2(globalWorldMap.ballLocationList[0].Y - robotCurrentLocation.Y, globalWorldMap.ballLocationList[0].X - robotCurrentLocation.X); } break; case RobotRole.AttaquantAvecBalle: { /// L'attaquant avec balle doit aller vers le but si il a de l'espace /// Il peut faire des passes à ses coéquipiers démarqués si il est dans une zone un peu dense /// /// On va placer un défenseur à une distance définie de l'attaquant, sur la ligne attaquant but /// Les zones d'intérêt sont devant les deux attaquants les plus en pointe /// Il faut donc commencer par les trouver Dictionary <int, TeamMateRoleClassifier> adversaireClassifier = new Dictionary <int, TeamMateRoleClassifier>(); int i = 0; foreach (var adversaire in globalWorldMap.obstacleLocationList) { var adv = new TeamMateRoleClassifier(new PointD(adversaire.X, adversaire.Y), RobotRole.Adversaire); adv.DistanceRobotConsidere = Toolbox.Distance(new PointD(adversaire.X, adversaire.Y), new PointD(robotCurrentLocation.X, robotCurrentLocation.Y)); adversaireClassifier.Add(i++, adv); } /// A présent, on filtre la liste des adversaires de manière à trouver les joueurs les plus proches du robot considéré /// var teamFiltered1 = adversaireClassifier.OrderBy(elt => elt.Value.DistanceRobotConsidere).ToList(); if (teamFiltered1.Count > 0) { var adversaireLePlusProche = teamFiltered1[0].Value.Position; if (teamFiltered1[0].Value.DistanceRobotConsidere > 2) { ///On a au moins 2m devant nous, on va vers le but ///TODO : raffiner pour ne prendre en compte que les robots entre le but et nous... AddPreferedZone(offensiveGoalPosition, 5); robotOrientation = Math.Atan2(offensiveGoalPosition.Y - robotCurrentLocation.Y, offensiveGoalPosition.X - robotCurrentLocation.X); /// Si on est suffisament proche du but, on tire if (Toolbox.Distance(new PointD(robotCurrentLocation.X, robotCurrentLocation.Y), offensiveGoalPosition) < 4) { ///On tire ! OnShootRequest(robotId, 6); } } else { ///Il y a du monde en face, on prépare une passe Dictionary <int, TeamMateRoleClassifier> teamMateClassifier = new Dictionary <int, TeamMateRoleClassifier>(); int j = 0; //foreach (var teamMateLoc in globalWorldMap.teammateLocationList) //{ // var adv = new TeamMateRoleClassifier(new PointD(adversaire.X, adversaire.Y), RobotRole.Adversaire); // adv.DistanceRobotConsidere = Toolbox.Distance(new PointD(adversaire.X, adversaire.Y), new PointD(robotCurrentLocation.X, robotCurrentLocation.Y)); // adversaireClassifier.Add(i++, adv); //} AddPreferedZone(offensiveGoalPosition, 2); } //AddPreferredSegmentZoneList(new PointD(adversaire1.X, adversaire1.Y), new PointD(adversaire2.X, adversaire2.Y), 0.4, 0.1); //AddAvoidanceZone(new PointD(adversaire1.X, adversaire1.Y), 2, 0.5); //AddPreferedZone(new PointD((teamFiltered1[0].Value.Position.X + teamFiltered1[1].Value.Position.X) / 2, (teamFiltered1[0].Value.Position.Y + teamFiltered1[0].Value.Position.Y) / 2), 2.5); } } break; } }
public PostMatchScoutingPage(ParseObject matchData) { Label pageTitle = new Label() { Text = "Post Match Info", TextColor = Color.White, BackgroundColor = Color.Black, FontSize = GlobalVariables.sizeTitle, FontAttributes = FontAttributes.Bold }; Label roleLabel = new Label() { Text = "What role did this robot generally perform?:", TextColor = Color.Black, FontSize = GlobalVariables.sizeMedium }; Picker rolePicker = new Picker(); rolePicker.Title = "Choose an Option"; for (RobotRole i = RobotRole.Shooter; i <= RobotRole.Other; i++) { rolePicker.Items.Add(i.ToString()); } ; rolePicker.SelectedIndexChanged += (sender, e) => { RobotRole role = (RobotRole)rolePicker.SelectedIndex; rolePicker.Title = role.ToString(); }; Label interferenceLabel = new Label { Text = "Did the team interfere with their alliance members?", TextColor = Color.Black, FontSize = GlobalVariables.sizeMedium, }; Picker interferencePicker = new Picker(); for (Choice type = Choice.No; type <= Choice.Yes; type++) { string stringValue = type.ToString(); interferencePicker.Items.Add(stringValue); } interferencePicker.SelectedIndexChanged += (sender, args) => { Choice type = (Choice)interferencePicker.SelectedIndex; string stringValue = type.ToString(); interferencePicker.Title = stringValue; }; Label techFoulLabel = new Label { Text = "How many tech fouls did this team commit?:", TextColor = Color.Black, FontSize = GlobalVariables.sizeMedium }; Entry techFoulEntry = new Entry { Placeholder = "0", Keyboard = Keyboard.Numeric }; Label noteLabel = new Label { Text = "Match comments/notes:", TextColor = Color.Black, FontSize = GlobalVariables.sizeMedium }; Editor noteEditor = new Editor { HeightRequest = 100, Text = "[notes]", BackgroundColor = Color.Silver }; data = matchData; Button submit = new Button { Text = "Submit", TextColor = Color.Green, BackgroundColor = Color.Black, FontSize = GlobalVariables.sizeMedium }; submit.Clicked += (object sender, EventArgs e) => { if (new CheckInternetConnectivity().InternetStatus()) { if (interferencePicker.Title == "Yes") { errorHandling("interference", true); } else { errorHandling("interference", false); } if (noteEditor.Text != "[notes]" || string.IsNullOrEmpty(noteEditor.Text) || string.IsNullOrWhiteSpace(noteEditor.Text)) { errorHandling("matchNotes", noteEditor.Text); } if (rolePicker.Title.ToString() != "Choose an Option") { errorHandling("robotRole", rolePicker.Title); } if (!string.IsNullOrEmpty(techFoulEntry.Text)) { errorHandling("techFouls", Convert.ToInt16(techFoulEntry.Text)); } else { errorHandling("techFouls", 0); } if (errorStatus == true) { errorString = errorString.Remove(errorString.Length - 2); DisplayAlert("Error:", errorString, "OK"); errorString = "The following data was unable to be saved: "; } else { // Navigation.InsertPageBefore(new PreMatchScoutingPage(), AutoMatchScoutingPage); Navigation.PushModalAsync(new PreMatchScoutingPage(matchData["scouterName"].ToString())); } } }; Label keyboardPadding = new Label(); keyboardPadding.HeightRequest = 300; StackLayout stack = new StackLayout { HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand, Children = { pageTitle, roleLabel, rolePicker, interferenceLabel, interferencePicker, techFoulLabel, techFoulEntry, noteLabel, noteEditor, submit, //keyboardPadding } }; this.Content = new ScrollView { HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand, Content = stack }; BackgroundColor = Color.Gray; }
public void SetRole(RobotRole role) { robotRole = role; }
public virtual void OnRole(int id, RobotRole role) { OnRoleEvent?.Invoke(this, new RoleArgs { RobotId = id, Role = role }); }