internal void CopyArmy() { PlanArmy army = SelectedArmy.PlanArmy; army.PlanUnits.Clear(); var armyItems = new List <PlanUnit>(); foreach (PlanUnitViewModel armyItemVM in SelectedArmy.PlanUnits) { PlanUnit armyItem = armyItemVM.PlanUnit; armyItem.Options = armyItemVM.Options.Select(option => option.Option).ToList(); army.PlanUnits.Add(armyItemVM.PlanUnit); } var copiedArmy = new PlanArmyViewModel() { PlanArmy = StaticHelper.DeepClone(army) }; Armies.Add(copiedArmy); SelectedArmy = copiedArmy; }
public async void SaveArmies() { var armies = new List <PlanArmy>(); foreach (PlanArmyViewModel armyVM in Armies) { PlanArmy army = armyVM.PlanArmy; if (army.PlanArmyId == null) { army.PlanArmyId = Guid.NewGuid(); } army.PlanUnits.Clear(); var armyUnits = new List <PlanUnit>(); foreach (PlanUnitViewModel armyUnitVM in armyVM.PlanUnits) { PlanUnit armyUnit = armyUnitVM.PlanUnit; if (armyUnit.PlanUnitId == null) { armyUnit.PlanUnitId = Guid.NewGuid(); } armyUnit.PlanArmyId = army.PlanArmyId; armyUnit.Options = armyUnitVM.Options.Select(option => option.Option).ToList(); army.PlanUnits.Add(armyUnitVM.PlanUnit); } } _armyProvider.SaveArmies(armies); }
public PlanUnitViewModel(PlanUnit planUnit) { PlanUnit = planUnit; if (planUnit.Options == null) { Options = new ObservableCollection <OptionViewModel>(); } else { Options = new ObservableCollection <OptionViewModel>(planUnit.Options.Select(option => new OptionViewModel(option))); } }
public async Task <IActionResult> GetPlanUnit([FromRoute] string idString) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } var id = new Guid(idString); PlanUnit selectedArmyUnit = _context.PlanArmyUnit.Include(e => e.Options).FirstOrDefault(armyUnit => armyUnit.PlanArmyId == id); if (selectedArmyUnit == null) { return(NotFound()); } return(Ok(selectedArmyUnit)); }
// Traza un plan para seguir más adelante // Este método contiene el algoritmo principal private void CreatePlan() { this.plan.Clear(); var worldState = WorldState.Current; #region Ordenar acciones por consecuencias abstractas Dictionary <Action, float> actionConvenience = new Dictionary <Action, float>(); Architect mostConvenientTargetArchitect = null; var maximumConvenience = -Mathf.Infinity; // Exploramos todas las acciones sin entrar en detalle, para obtener una primera aproximación acerca de // qué acciones resultarían en un estado del mundo más favorable ActionInfo abstractInfo = new ActionInfo(subjectArchitect: this); foreach (var action in Actions.GetAll()) { foreach (var targetArchitect in GameManager.Instance.architectContainer.GetComponentsInChildren <Architect>()) { if (targetArchitect.Defeated) { continue; } // Aplicamos las consecuencias sobre una copia del estado del mundo para comparar var nextWorldState = worldState.Clone(); abstractInfo.targetArchitect = targetArchitect; action.ApplyConsequences(abstractInfo, nextWorldState); var convenience = this.profile.GetConvenienceFor(nextWorldState); if (convenience > maximumConvenience) { maximumConvenience = convenience; mostConvenientTargetArchitect = targetArchitect; } } // Esta es la conveniencia más alta posible que esta acción puede ofrecer actionConvenience[action] = maximumConvenience; } List <Action> possibleActions = new List <Action>(Actions.GetAll()); #endregion #region Escoger posibles Actionables sujetos HashSet <Actionable> possibleSubjectActionables = new HashSet <Actionable>(); // Son posibles sujetos todos los ejércitos y todas las celdas bajo nuestro control possibleSubjectActionables.UnionWith(this.Nation.Armies); possibleSubjectActionables.UnionWith(this.Nation.Cells); #endregion #region Escoger posibles Actionables objetivos HashSet <Actionable> possibleTargetActionables = new HashSet <Actionable>(); // Son objetivos posibles todas las casillas adyacentes al territorio conquistado, todos los ejércitos de los rivales, // y los 16 ejércitos enemigos más cercanos possibleTargetActionables.UnionWith(this.Nation.FindAdjacentUnclaimedCellsInWorldState(worldState)); foreach (var rival in this.rivals) { possibleTargetActionables.UnionWith(rival.Nation.Armies); } var nearbyEnemies = new Army[16]; foreach (var army in this.Nation.Armies) { this.FindClosestEnemiesToCell(army.CurrentCell, nearbyEnemies); possibleTargetActionables.UnionWith(nearbyEnemies); } // En la búsqueda de posibles objetivos, es posible que se haya colado algún valor nulo. Lo eliminamos possibleTargetActionables.Remove(null); #endregion Dictionary <Action, PlanUnit> possiblePlanUnits = new Dictionary <Action, PlanUnit>(); for (var i = 0; i < possibleActions.Count; i++) { var action = possibleActions[i]; #region Encontrar combinación de sujeto y objetivo más conveniente Actionable mostConvenientSubject = null; Actionable mostConvenientTarget = null; Order mostConvenientOrder = null; var bestConvenience = -Mathf.Infinity; foreach (var subject in possibleSubjectActionables) { // Si el sujeto no puede participar en la acción, pasamos al siguiente directamente if (action.RequiredSubjectType != null && subject.GetType() != action.RequiredSubjectType) { continue; } foreach (var target in possibleTargetActionables) { // Si el objetivo no puede participar en la acción, pasamos al siguiente directamente if (action.RequiredTargetType != null && target.GetType() != action.RequiredTargetType) { continue; } // ¿Qué orden tendríamos que seguir para ejecutar esta acción, dados el sujeto y el objetivo indicados? var order = action.GetOrderForActionable(new ActionInfo( subjectArchitect: this, subject: subject, targetArchitect: target is Army ? ((Army)target).Nation.Architect : ((Cell)target).Nation?.Architect, target: target), worldState); // Es posible que el objetivo no pueda participar en la orden if (order.RequiredTargetType != null && target.GetType() != order.RequiredTargetType) { continue; } // ¿Es este el combo orden + sujeto + objetivo más conveniente que hemos encontrado harta ahora? var convenience = this.profile.GetConvenienceFor(subject, order, target, worldState); if (convenience > bestConvenience) { mostConvenientSubject = subject; mostConvenientTarget = target; mostConvenientOrder = order; bestConvenience = convenience; } } } #endregion // Si al menos hemos dado con una orden válida, generamos unidad de plan con los datos más óptimos que hemos encontrado // y actualizamos la conveniencia de la acción con los nuevos datos que tenemos if (mostConvenientOrder != null) { PlanUnit planUnitForThisAction = new PlanUnit(action, mostConvenientOrder, new OrderInfo(subject: mostConvenientSubject, target: mostConvenientTarget)); possiblePlanUnits[action] = planUnitForThisAction; actionConvenience[action] += bestConvenience; // Si no la hemos encontrado, esta acción es completamente inviable y su conveniencia es mínima } else { actionConvenience[action] = -Mathf.Infinity; } } // Ordenamos las acciones ahora que sabemos con más precisión qué conveniencia tienen possibleActions.Sort((a, b) => Mathf.RoundToInt(actionConvenience[b] - actionConvenience[a])); // Asignamos unidades de plan a cada ejército. Como las acciones están ordenadas de más a menos convenientes, // iremos asignando unidades en efectividad decreciente HashSet <Army> assignedArmies = new HashSet <Army>(); foreach (var action in possibleActions) { if (!possiblePlanUnits.ContainsKey(action)) { continue; } var planUnit = possiblePlanUnits[action]; // Si el ejército al que asignaríamos esta orden está ocioso, se la asignamos. Si no, es que ya tiene una más efectiva if (!assignedArmies.Contains(planUnit.orderInfo.subject as Army)) { plan.Add(planUnit); assignedArmies.Add(planUnit.orderInfo.subject as Army); } } }