public void DecisionContextConstructorTest() { IEnumerable <object> contextFeatures = new List <object>() { new { Features = new { day = "Monday", time = "morning", weather = "sunny" } }, }; List <PersonalizerRankableAction> actions = new List <PersonalizerRankableAction>(); actions.Add (new PersonalizerRankableAction( id: "Person", features: new List <object>() { new { videoType = "documentary", videoLength = 35, director = "CarlSagan" }, new { mostWatchedByAge = "30-35" } } )); DecisionContext decisionContext = new DecisionContext(contextFeatures, actions); Assert.AreEqual(decisionContext.ContextFeatures.Count, 1); Assert.IsTrue(decisionContext.ContextFeatures[0].Equals("{\"Features\":{\"day\":\"Monday\",\"time\":\"morning\",\"weather\":\"sunny\"}}")); Assert.AreEqual(decisionContext.Documents.Count, 1); Assert.AreEqual(decisionContext.Documents[0].ActionFeatures.Count, 2); Assert.IsTrue(decisionContext.Documents[0].ActionFeatures[0].Equals("{\"videoType\":\"documentary\",\"videoLength\":35,\"director\":\"CarlSagan\"}")); Assert.IsTrue(decisionContext.Documents[0].ActionFeatures[1].Equals("{\"mostWatchedByAge\":\"30-35\"}")); }
public SelectedAction Select(ActionSet actionSet, DecisionContext context) { var utilities = actionSet.Actions .Select(x => new SelectedAction(x, x.Score(context))) .ToList(); var utilitySum = utilities.Sum(x => x.Score); var sortedListOfActionsByProbability = utilities .Select(x => new { Probability = x.Score / utilitySum, SelectedAction = x }) .OrderByDescending(x => x.Probability) .ToList(); var runningSum = .0; var randomValue = context.RandomGenerator.Next(); foreach (var actionProbability in sortedListOfActionsByProbability) { runningSum += actionProbability.Probability; if (runningSum >= randomValue) { return(actionProbability.SelectedAction); } } return(sortedListOfActionsByProbability[0].SelectedAction); }
public override float Score(DecisionContext context) { if ((context.Target.Unit ?? context.Unit).IsEnemy(context.Unit)) { return(this.enemy_score); } return(this.ally_score); }
public override float Score(DecisionContext context) { var unit = context.Target?.Unit; if (unit == null) { return(0.0f); } return(unit.Body.IsPolymorphed ? polymorphed_score : not_polymorphed_score); }
static void Postfix(DecisionContext context) { if (IsInCombat() && context.CurrentScore > 0f && (context.Ability?.RequireFullRoundAction ?? false)) { UnitEntityData unit = context.Target.Unit ?? context.Unit; if (!unit.IsSurprising() && !unit.HasFullRoundAction()) { context.CurrentScore = 0f; } } }
public override float Score([NotNull] DecisionContext context) { var spellbook = context.Unit.Descriptor.DemandSpellbook(spellbookBlue); if (spellbook == null) { return(0f); } int maxSpellLevel = spellbook.MaxSpellLevel; if (maxSpellLevel < level || level < 1) { return(0f); } return(spellbook.GetSpontaneousSlots(level) > 0 ? 1f : 0f); }
/// <summary> /// Determines the result of the specified context. /// </summary> /// <param name="context">The context.</param> /// <returns> /// A Decision indicating the result of the query. /// </returns> public async Task<bool> CheckAsync(DecisionContext context) { // Apply Defaults context.SourceId = context.SourceId ?? defaultProvider.SourceId; // Wrap the Remote call in a Try/Catch to provide good debug information if an error occurs. try { var result = await client.GetStringAsync("Api/Decide/" + context.Id); return bool.Parse(result); } catch (Exception e) { throw new ArgumentException(string.Format("A GET for {0} returned error: {1}", "Api/Decide/" + context.Id, e.Message)); } }
public double Score(Action action, DecisionContext context) { var modificationFactor = 1.0 - 1.0 / action.Considerations.Count; var result = action.Weight; foreach (var consideration in action.Considerations) { var input = context.Get(consideration.Input).Evaluate(); var score = consideration.ResponseCurve.Evaluate(input); var makeUpValue = (1.0 - score) * modificationFactor; score += makeUpValue * score; result *= score; } return(result); }
public SelectedAction Select(ActionSet actionSet, DecisionContext context) { var maxScore = .0; Action selectedAction = null; foreach (var action in actionSet.Actions) { var score = action.Score(context); if (score >= maxScore) { maxScore = score; selectedAction = action; } } return(new SelectedAction(selectedAction, maxScore)); }
public override PlayerAction GetTurn(GetTurnContext context) { if (context.MoneyLeft / this.BigBlind <= 5) { return(PlayerAction.Raise(AllIn)); } var decisionMaker = this.factory.GetDecisionMaker(context.RoundType); var decisionContext = new DecisionContext { CommunityCards = this.CommunityCards, FirstCard = this.FirstCard, SecondCard = this.SecondCard, TurnContext = context }; return(decisionMaker.GetAction(decisionContext, this)); }
public Action Select(DecisionMaker decisionMaker, DecisionContext context) { var maxScore = .0; Action selectedAction = null; foreach (var actionSet in decisionMaker.ActionSets) { var pair = actionSet.Select(context); if (pair.Action != null && pair.Score >= maxScore) { maxScore = pair.Score; selectedAction = pair.Action; } } return(selectedAction); }
public override float Score(DecisionContext context) { var unit = context.Target?.Unit; if (unit == null) { return(min_score); } float val = (float)unit.Descriptor.Stats.BaseAttackBonus.ModifiedValue / (float)unit.Descriptor.Progression.CharacterLevel; if (val < min_bab_part) { return(min_score); } else { return(Math.Min(max_score, val)); } }
public override float Score(DecisionContext context) { var mark = context.Unit.Get <UnitPartSpiritualWeaponTargetMark>()?.buff; if (mark == null) { return(0.5f); } var summoner = context.Unit?.Get <UnitPartSummonedMonster>()?.Summoner; if (context.Target.Unit == null || summoner == null) { return(0.5f); } if (context.Target.Unit.Buffs.Enumerable.Any(b => b.Blueprint == mark && b.Context.MaybeCaster == summoner)) { return(1.0f); } else { return(0.001f); } }
private static async Task MainAsync() { // Requires Visual C++ 2015 Runtime installed // - https://www.microsoft.com/en-us/download/details.aspx?id=48145 // Requires platform to be x64 // 1. Sign in on https://ds.microsoft.com // 2. Create new app // a. Select "Custom App" // b. Supply Azure storage account // c. Empty Action Endpoint field - this disables action id based featurization // d. Empty Action Set Endpoint field // e. Set Provision FrontEnd field to "false" - avoids HTTP scoring provisioning // f. Set Vowpal Wabbit arguments to --cb_explore_adf --epsilon 0.2 -q DT -q LT // f. Click create // 3. Wait for creation and hit edit // a. Copy Client Library URL and use in the sample code below // 4. nuget install Microsoft.Research.MultiWorldTesting.ClientLibrary // a. at least version 2.0.0.6 var config = new DecisionServiceConfiguration(settingsBlobUri: "<<INSERT URL FROM STEP 3A") { ModelPollFailureCallback = ex => Console.WriteLine(ex.Message), SettingsPollFailureCallback = ex => Console.WriteLine(ex.Message) }; // you should keep this object around (e.g. static variable) as it maintains the background process // to download new models and upload logged events using (var ds = DecisionService.Create <DecisionContext>(config, typeInspector: JsonTypeInspector.Default)) { // If you add the timestamp calculating reward latencies becomes very easy on our end // In general you can use existing request ids, just be careful as they're used to seed the random // generator for exploration. // Also they're used to join rank and reward calls, so they must be unique within the experimental unit duration var eventId = EventIdUtil.AddTimestamp(Guid.NewGuid().ToString("n"), EventIdUtil.BeginningOfTime); var context = new DecisionContext { Demographics = new DemographicNamespace { Gender = "female", }, Location = new LocationNamespace { Country = "USA", City = "New York" }, Actions = new[] { new ActionDependentFeatures { Topic = new TopicNamespace { Category = "Fashion" } }, new ActionDependentFeatures { Topic = new TopicNamespace { Category = "Technology" } } } }; // get the decision var ranking = await ds.ChooseRankingAsync( uniqueKey : eventId, context : context); // report the reward if you observed desired behavior on first item in ranking // e.g. the first item returned by ChooseRankingAsync got clicked. ds.ReportReward(reward: 1f, uniqueKey: eventId); } }
public ScoreResult(float score, DecisionContext context, AIAction action) { this.score = score; this.context = context; this.action = action; }
/// <summary> /// Gets the environment with the specified alias using the context provided. /// </summary> /// <param name="alias">The globally unique alias used to represent a specific environment.</param> /// <param name="context">The context.</param> /// <returns> /// An environment specified to the provided information. /// </returns> public abstract Task<dynamic> GetAsync(string alias, DecisionContext context);
public override float Score(DecisionContext context) { float chance_to_hit_weight = Main.settings.ai_chance_to_hit_weight; float engaged_by_weight = Main.settings.ai_engaged_by_target_weight; float distance_weight = Main.settings.ai_distance_to_target_weight; UnitEntityData attacker = context.Unit; UnitEntityData target = context.Target.Unit ?? context.Unit; if (attacker == null || target == null || !target.IsEnemy(attacker) || attacker.CombatState.AIData.UnreachableUnits.Contains(target) || attacker.IsPlayerFaction) { return(min_score); } var weapon = attacker.Body?.PrimaryHand?.MaybeWeapon; if (!attacker.Body.HandsAreEnabled && attacker.Body.AdditionalLimbs.Count > 0) { weapon = attacker.Body.AdditionalLimbs[0].MaybeWeapon; } int odds = 0; if (weapon != null) { var attack_bonus = Rulebook.Trigger(new RuleCalculateAttackBonus(attacker, target, weapon, 0)).Result; var target_ac = Rulebook.Trigger(new RuleCalculateAC(attacker, target, weapon.Blueprint.AttackType)).TargetAC; odds = attack_bonus - target_ac + 10; // 0 means 50% chance to hit more is better } int certainty = 0; var unit_part_attack_scores = attacker.Ensure <UnitPartAttackScoreStorage>(); if (unit_part_attack_scores.attack_scores.ContainsKey(target)) { certainty = unit_part_attack_scores.attack_scores[target]; } else { var check_bonus = attacker.Stats.Intelligence.Bonus + attacker.Stats.Wisdom.Bonus + attacker.Descriptor.Progression.CharacterLevel; var dc = 10 + (target.Stats.CheckBluff.ModifiedValue + target.Stats.SkillStealth.ModifiedValue) / 2 + attacker.Descriptor.Progression.CharacterLevel; certainty = rng.Next(1, 20) + check_bonus - dc; certainty = Math.Max(Math.Min(10, certainty), -10); // from -10 to 10 unit_part_attack_scores.attack_scores[target] = certainty; } odds = Math.Min(Math.Max(odds, -10), 10); //from -10 to 10 float certainty_coeff = (1.0f + certainty * 0.1f) * 0.5f; //from 0 to 1 float odds_coeff = (1.0f + odds * 0.1f) * 0.5f; //1 for auto hit, 0 for auto miss float score = 1.0f - chance_to_hit_weight * (0.5f + (0.5f - odds_coeff) * certainty_coeff); var distance = Math.Max((target.Position - attacker.Position).magnitude, 5.Feet().Meters); var distance_coeff = 5.Feet().Meters / distance; //from 1 to 0; if ((weapon != null && weapon.Blueprint.IsRanged) || (context.Ability?.Blueprint != null && context.Ability.Blueprint.Range >= AbilityRange.Close && context.Ability.Blueprint.Range <= AbilityRange.Unlimited) ) { distance_coeff = 1.0f; } score *= (1.0f - distance_weight * (1.0f - distance_coeff)); //will more likely attack closer units if does not have ranged weapon var tumble_toggle = attacker.ActivatableAbilities.Enumerable.Where(a => a.Blueprint == tumble).FirstOrDefault(); if (tumble_toggle != null && !attacker.IsPlayerFaction) { tumble_toggle.IsOn = attacker.CombatState.IsEngaged && attacker.Stats.GetStat(Kingmaker.EntitySystem.Stats.StatType.SkillMobility).ModifiedValue >= 10; } var engaged_score = 1.0f - engaged_by_weight; if (attacker.CombatState.EngagedBy.Contains(target)) { engaged_score = 1.0f; } score *= engaged_score; return(Math.Max(Math.Min(score, max_score), min_score)); }
public override void SetContext(DecisionContext bestResultContext) { throw new NotImplementedException(); }
public override void SetContext(DecisionContext context) { this.context = context as PointContext; }