/// <summary> /// Initializes this rule /// </summary> /// <param name='head'>The rule's head</param> /// <param name='headAction'>Whether this rule is generated</param> /// <param name='body'>The rule's body</param> /// <param name='context'>The lexical context pushed by this rule</param> public Rule(Variable head, TreeAction headAction, RuleBody body, int context) { this.head = head; this.headAction = headAction; this.body = body; this.context = context; }
/// <summary> /// Applies the given action to all bodies in this set /// </summary> /// <param name="action">The action to apply</param> public void ApplyAction(TreeAction action) { foreach (RuleBody body in this) { body.ApplyAction(action); } }
/// <summary> /// During a reduction, inserts a virtual symbol /// </summary> /// <param name="index">The virtual symbol's index</param> /// <param name="action">The tree action applied onto the symbol</param> public void ReductionAddVirtual(int index, TreeAction action) { if (action == TreeAction.Drop) { return; // why would you do this? } int nodeId = sppf.NewNode(new TableElemRef(TableType.Virtual, index)); if (cacheNext + 1 >= cacheChildren.Length) { // the current cache is not big enough, build a bigger one Array.Resize(ref cacheChildren, cacheChildren.Length + INIT_HANDLE_SIZE); } // add the node in the cache cacheChildren[cacheNext] = new SPPFNodeRef(nodeId, 0); // setup the handle to point to the root if (handleNext == handleIndices.Length) { Array.Resize(ref handleIndices, handleIndices.Length + INIT_HANDLE_SIZE); Array.Resize(ref handleActions, handleActions.Length + INIT_HANDLE_SIZE); } handleIndices[handleNext] = cacheNext; handleActions[handleNext] = action; // copy the children handleNext++; cacheNext++; }
/// <summary> /// Applies the given action to all elements in this body /// </summary> /// <param name="action">The action to apply</param> public void ApplyAction(TreeAction action) { foreach (RuleBodyElement part in parts) { part.Action = action; } }
/// <summary> /// Adds the specified SPPF node to the cache /// </summary> /// <param name="node">The node to add to the cache</param> /// <param name="action">The tree action to apply onto the node</param> private void AddToCache(SPPFNodeNormal node, TreeAction action) { SPPFNodeVersion version = node.DefaultVersion; while (cacheNext + version.ChildrenCount + 1 >= cacheChildren.Length) { // the current cache is not big enough, build a bigger one Array.Resize(ref cacheChildren, cacheChildren.Length + INIT_HANDLE_SIZE); } // add the node in the cache cacheChildren[cacheNext] = new SPPFNodeRef(node.Identifier, 0); // setup the handle to point to the root if (handleNext == handleIndices.Length) { Array.Resize(ref handleIndices, handleIndices.Length + INIT_HANDLE_SIZE); Array.Resize(ref handleActions, handleActions.Length + INIT_HANDLE_SIZE); } handleIndices[handleNext] = cacheNext; handleActions[handleNext] = action; // copy the children if (version.ChildrenCount > 0) { Array.Copy(version.Children, 0, cacheChildren, cacheNext + 1, version.ChildrenCount); } handleNext++; cacheNext += version.ChildrenCount + 1; }
void FreeKickInit() { //FreeKick Player begin //udany begin TreeAction udanyCelnyGol = new TreeAction(0.7f, null, true, "Piękny gol zdobyty po strzale z rzutu wolnego!", GoalFreeKickPlayer); TreeAction udanyCelnyOdbijaDoPartnera = new TreeAction(0.15f, null, true, "Bramkarz broni, ale jeszcze nie koniec akcji...", ComputerShoot); TreeAction udanyCelnyOdbijaDoRywala = new TreeAction(0.25f, null, true, "Bramkarz broni! Piłka trafia do obrońców", EnemyBall); TreeAction udanyCelnyOdbijaZaLiniePrawyRozny = new TreeAction(0.5f, null, true, "Dobry rzut wolny, ale bramkarz wybil za linie. Prawy rozny", RightCorner); TreeAction udanyCelnyOdbijaZaLinieLewyRozny = new TreeAction(0.5f, null, true, "Dobry rzut wolny, ale bramkarz wybil za linie. Lewy rozny", LeftCorner); TreeAction udanyDoPartnera = new TreeAction(0.4f, null, true, "Dobre podanie z rzutu wolnego, partner przy piłce!", OurBall); TreeAction udanyCelnyOdbijaZaLinie = new TreeAction(0.6f, new TreeAction[] { udanyCelnyOdbijaZaLinieLewyRozny, udanyCelnyOdbijaZaLiniePrawyRozny }, false, ""); TreeAction udanyCelnyOdbija = new TreeAction(0.3f, new TreeAction[] { udanyCelnyOdbijaDoPartnera, udanyCelnyOdbijaDoRywala, udanyCelnyOdbijaZaLinie }, false, ""); TreeAction udanyCelny = new TreeAction(0.6f, new TreeAction[] { udanyCelnyGol, udanyCelnyOdbija }, false, ""); TreeAction udany = new TreeAction(0.6f, new TreeAction[] { udanyCelny, udanyDoPartnera }, false, ""); //udany end //nieudany begin TreeAction nieudanyBramkarzLapie = new TreeAction(0.8f, null, true, "Nieudany rzut wolny, piłka w rękach bramkarza", EnemyBall); TreeAction nieudanyDoRywala = new TreeAction(0.2f, null, true, "Nieudany rzut wolny, piłka trafia do rywali", EnemyBall); TreeAction nieudany = new TreeAction(0.4f, new TreeAction[] { nieudanyBramkarzLapie, nieudanyDoRywala }, false, ""); //nieudany end FreeKick = new TreeAction(2f, new TreeAction[] { nieudany, udany }, false, ""); //FreeKick Player end }
public TreeStateSuccessor(TreeState parent, TreeAction action, TreeState result, decimal valueOfResultingState) { ParentState = parent; ActionTaken = action; ResultingState = result; ValueOfResultingState = valueOfResultingState; }
void TackleInit() { //tackle begin //udany begin TreeAction udanyRywalWybija = new TreeAction(0.0f, null, true, "Świetny odbiór! Rywal ratuje się wybiciem na aut", Out, checkTypes.BALL_ON_SIDES, 0.05f); TreeAction udanyOdbior = new TreeAction(0.8f, null, true, "Świetny odbiór!"); TreeAction udanyFaulZwyklyBezKontuzji = new TreeAction(0.95f, null, true, "Rywal nas fauluje w walce. Nic strasznego. Wolny!", Foul); TreeAction udanyFaulZwyklyKontuzja = new TreeAction(0.05f, null, true, "Rywal nas fauluje w walce. Wygląda na kontuzję", FoulContusion); TreeAction udanyFaulNaZoltaBezKontuzji = new TreeAction(0.85f, null, true, "Rywal nas fauluje w walce. Będzie żółta kartka", FoulYellow); TreeAction udanyFaulNaZoltaKontuzja = new TreeAction(0.15f, null, true, "Rywal nas fauluje w walce. Jest żółta kartka i kontuzja", FoulContusionYellow); TreeAction udanyFaulNaCzerwonaBezKontuzji = new TreeAction(0.7f, null, true, "Rywal nas fauluje w walce. Będzie czerwona kartka!", FoulRed); TreeAction udanyFaulNaCzerwonaKontuzja = new TreeAction(0.3f, null, true, "Rywal nas fauluje w walce. Jest czerwona kartka i kontuzja", FoulContusionRed); TreeAction udanyFaulZwykly = new TreeAction(0.75f, new TreeAction[] { udanyFaulZwyklyBezKontuzji, udanyFaulZwyklyKontuzja }, false, ""); TreeAction udanyFaulNaZolta = new TreeAction(0.2f, new TreeAction[] { udanyFaulNaZoltaBezKontuzji, udanyFaulNaZoltaKontuzja }, false, ""); TreeAction udanyFaulNaCzerwona = new TreeAction(0.05f, new TreeAction[] { udanyFaulNaCzerwonaBezKontuzji, udanyFaulNaCzerwonaKontuzja }, false, ""); TreeAction udanyFaul = new TreeAction(0.2f, new TreeAction[] { udanyFaulZwykly, udanyFaulNaZolta, udanyFaulNaCzerwona }, false, "", null, checkTypes.BALL_ON_SIDES, 0.15f); TreeAction udany = new TreeAction(0.6f, new TreeAction[] { udanyRywalWybija, udanyOdbior, udanyFaul }, false, ""); //udany end //nieudany begin TreeAction nieudanyGraczWybija = new TreeAction(0.0f, null, true, "Kiepski odbiór, trzeba ratować się wybiciem na aut", Out, checkTypes.BALL_ON_SIDES, 0.05f); TreeAction nieudanyMija = new TreeAction(0.75f, null, true, "Kiepski odbiór, akcja rywali trwa", EnemyBall); TreeAction nieudanyFaulZwykly = new TreeAction(0.75f, null, true, "Kiepski odbiór, faulujemy rywala. Bez konsekwencji", PlayerFoul); TreeAction nieudanyFaulNaZolta = new TreeAction(0.2f, null, true, "Kiepski odbiór, faulujemy rywala. Żółta kartka", PlayerYellow); TreeAction nieudanyFaulNaCzerwona = new TreeAction(0.05f, null, true, "Kiepski odbiór, faulujemy rywala. Czerwona kartka", PlayerRed); TreeAction nieudanyFaul = new TreeAction(0.25f, new TreeAction[] { nieudanyFaulZwykly, nieudanyFaulNaZolta, nieudanyFaulNaCzerwona }, false, "", null, checkTypes.BALL_ON_SIDES, 0.2f); TreeAction nieudany = new TreeAction(0.4f, new TreeAction[] { nieudanyGraczWybija, nieudanyMija, nieudanyFaul }, false, ""); //nieudany end Tackle = new TreeAction(2f, new TreeAction[] { nieudany, udany }, false, ""); //Tackle end }
/// <summary> /// Performs Leaf TreeNodeType behavior. /// </summary> /// <param name="treeNode">The Leaf TreeNode.</param> internal async Task PerformLeafTypeBehavior(TreeNode treeNode) { // Check if Leaf node contains the LeafNodeSummaryAction and commit ActionInput as ActionResponse if it does. if (treeNode.Actions == null || treeNode.Actions.Count != 1) { return; } foreach (KeyValuePair <string, TreeAction> kvp in treeNode.Actions) { string treeActionKey = kvp.Key; TreeAction treeAction = kvp.Value; if (treeAction.Action != LeafNodeSummaryAction) { return; } ActionResponse actionResponse = await this.EvaluateDynamicProperty(treeAction.Input, typeof(ActionResponse)).ConfigureAwait(false); await this.CommitActionResponse(treeActionKey, actionResponse).ConfigureAwait(false); return; } }
/// <summary> /// Finalizes the reduction operation /// </summary> /// <param name="generation">The generation to reduce from</param> /// <param name="varIndex">The reduced variable index</param> /// <param name="headAction">The tree action applied in the rule's head</param> /// <returns>The identifier of the produced SPPF node</returns> public int Reduce(int generation, int varIndex, TreeAction headAction) { int label = headAction == TreeAction.ReplaceByChildren ? ReduceReplaceable(varIndex) : ReduceNormal(varIndex, headAction); AddToHistory(generation, label); return(label); }
void DribblingInit() { //dribbling begin //udany begin TreeAction udanyRywalWybija = new TreeAction(0.0f, null, true, "Świetny drybling! Rywal ratuje się wybiciem na aut", Out, checkTypes.BALL_ON_SIDES, 0.05f); TreeAction udanyPrzejscie = new TreeAction(0.8f, null, true, "Świetny drybling! Zawodnik przesuwa się wgłąb boiska", UdanyDrybling); //0.8f TreeAction udanyFaulZwyklyBezKontuzji = new TreeAction(0.95f, null, true, "Świetny drybling przerwany faulem. Nic strasznego. Wolny!", NormalnyFaul); TreeAction udanyFaulZwyklyKontuzja = new TreeAction(0.05f, null, true, "Świetny drybling przerwany faulem. Wygląda na kontuzję", FoulContusion); TreeAction udanyFaulNaZoltaBezKontuzji = new TreeAction(0.85f, null, true, "Świetny drybling przerwany faulem. Będzie żółta kartka", FoulYellow); TreeAction udanyFaulNaZoltaKontuzja = new TreeAction(0.15f, null, true, "Świetny drybling przerwany faulem. Jest żółta kartka i kontuzja", FoulContusionYellow); TreeAction udanyFaulNaCzerwonaBezKontuzji = new TreeAction(0.7f, null, true, "Świetny drybling przerwany faulem. Będzie czerwona kartka!", FoulRed); TreeAction udanyFaulNaCzerwonaKontuzja = new TreeAction(0.3f, null, true, "Świetny drybling przerwany faulem. Jest czerwona kartka i kontuzja", FoulContusionRed); TreeAction udanyFaulZwykly = new TreeAction(0.75f, new TreeAction[] { udanyFaulZwyklyBezKontuzji, udanyFaulZwyklyKontuzja }, false, ""); TreeAction udanyFaulNaZolta = new TreeAction(0.2f, new TreeAction[] { udanyFaulNaZoltaBezKontuzji, udanyFaulNaZoltaKontuzja }, false, ""); TreeAction udanyFaulNaCzerwona = new TreeAction(0.05f, new TreeAction[] { udanyFaulNaCzerwonaBezKontuzji, udanyFaulNaCzerwonaKontuzja }, false, ""); TreeAction udanyFaul = new TreeAction(0.2f, new TreeAction[] { udanyFaulZwykly, udanyFaulNaZolta, udanyFaulNaCzerwona }, false, "", null, checkTypes.BALL_ON_SIDES, 0.15f); //0.2f TreeAction udany = new TreeAction(0.6f, new TreeAction[] { udanyRywalWybija, udanyPrzejscie, udanyFaul }, false, ""); //udany end //nieudany begin TreeAction nieudanyGraczWybija = new TreeAction(0.0f, null, true, "Kiepski drybling, trzeba ratować się wybiciem na aut", Out, checkTypes.BALL_ON_SIDES, 0.05f); TreeAction nieudanyStrata = new TreeAction(0.75f, null, true, "Kiepski drybling i strata piłki", EnemyBall); TreeAction nieudanyKopaninaRywal = new TreeAction(0.5f, null, true, "Kiepski drybling, piłka po walce trafia do rywali", EnemyBall); TreeAction nieudanyKopaninaPartner = new TreeAction(0.5f, null, true, "Kiepski drybling, piłka szczęśliwie trafia po odbiciu do partnera", OurBall); TreeAction nieudanyKopanina = new TreeAction(0.25f, new TreeAction[] { nieudanyKopaninaRywal, nieudanyKopaninaPartner }, false, "", null, checkTypes.BALL_ON_SIDES, 0.2f); TreeAction nieudany = new TreeAction(0.4f, new TreeAction[] { nieudanyGraczWybija, nieudanyStrata, nieudanyKopanina }, false, ""); //nieudany end Dribbling = new TreeAction(2f, new TreeAction[] { nieudany, udany }, false, ""); //dribbling end }
void FreeKickCPUInit() { //FreeKickCPU begin //udany begin TreeAction udanyCelnyGol = new TreeAction(0.7f, null, true, "Piękny gol zdobyty po strzale z rzutu wolnego!", Goal); TreeAction udanyCelnyOdbijaDruzynaGraczGlowa = new TreeAction(0.35f, null, true, "Bramkarz odbija wolny, ale jest szansa na dobitkę głową...", Head); TreeAction udanyCelnyOdbijaDruzynaGraczNoga = new TreeAction(0.65f, null, true, "Bramkarz odbija wolny, ale jest szansa na dobitkę nogą...", PlayerFinishingShot); TreeAction udanyCelnyOdbijaDruzynaPartner = new TreeAction(1f, null, true, "Bramkarz odbija wolny, ale partnerzy dobijają!", ComputerShoot, checkTypes.PLAYER_ON_PENALTY, 0.3f); TreeAction udanyCelnyOdbijaDoRywala = new TreeAction(0.25f, null, true, "Bramkarz odbija wolny, piłka trafia pod nogi rywali", EnemyBall); TreeAction udanyCelnyOdbijaZaLiniePrawyRozny = new TreeAction(0.5f, null, true, "Dobry rzut wolny, ale bramkarz wybil za linie. Prawy rozny", RightCorner); TreeAction udanyCelnyOdbijaZaLinieLewyRozny = new TreeAction(0.5f, null, true, "Dobry rzut wolny, ale bramkarz wybil za linie. Lewy rozny", LeftCorner); TreeAction udanyDoPartneraGraczGlowa = new TreeAction(0.65f, null, true, "Podanie z wolnego do partnerów, ci wrzucają piłkę na główkę..."); TreeAction udanyDoPartneraGraczNoga = new TreeAction(0.35f, null, true, "Podanie z wolnego do partnerów, ci podają idealnie na nogę...", PlayerFinishingShot); TreeAction udanyDoPartneraStrzal = new TreeAction(1f, null, true, "Podanie z wolnego do partnera, ten oddaje strzał!", ComputerShoot, checkTypes.PLAYER_ON_PENALTY, 0.3f); TreeAction udanyCelnyOdbijaDruzynaGracz = new TreeAction(0.0f, new TreeAction[] { udanyCelnyOdbijaDruzynaGraczGlowa, udanyCelnyOdbijaDruzynaGraczNoga }, false, "", null, checkTypes.PLAYER_ON_PENALTY, 0.7f); TreeAction udanyCelnyOdbijaDruzyna = new TreeAction(0.15f, new TreeAction[] { udanyCelnyOdbijaDruzynaGracz, udanyCelnyOdbijaDruzynaPartner }, false, ""); TreeAction udanyCelnyOdbijaZaLinie = new TreeAction(0.6f, new TreeAction[] { udanyCelnyOdbijaZaLinieLewyRozny, udanyCelnyOdbijaZaLiniePrawyRozny }, false, ""); TreeAction udanyCelnyOdbija = new TreeAction(0.3f, new TreeAction[] { udanyCelnyOdbijaDruzyna, udanyCelnyOdbijaDoRywala, udanyCelnyOdbijaZaLinie }, false, ""); TreeAction udanyCelny = new TreeAction(0.6f, new TreeAction[] { udanyCelnyGol, udanyCelnyOdbija }, false, ""); TreeAction udanyDoPartneraGracz = new TreeAction(0.0f, new TreeAction[] { udanyDoPartneraGraczGlowa, udanyDoPartneraGraczNoga }, false, "", null, checkTypes.PLAYER_ON_PENALTY, 0.7f); TreeAction udanyDoPartnera = new TreeAction(0.4f, new TreeAction[] { udanyDoPartneraGracz, udanyDoPartneraStrzal }, false, ""); TreeAction udany = new TreeAction(0.6f, new TreeAction[] { udanyCelny, udanyDoPartnera }, false, ""); //udany end //nieudany begin TreeAction nieudanyBramkarzLapie = new TreeAction(0.8f, null, true, "Nieudany rzut wolny, piłka w rękach bramkarza", EnemyBall); TreeAction nieudanyDoRywala = new TreeAction(0.2f, null, true, "Nieudany rzut wolny, piłka trafia do rywali", EnemyBall); TreeAction nieudany = new TreeAction(0.4f, new TreeAction[] { nieudanyBramkarzLapie, nieudanyDoRywala }, false, ""); //nieudany end FreeKickCPU = new TreeAction(2f, new TreeAction[] { nieudany, udany }, false, ""); //FreeKickCPU end }
/// <summary> /// During a redution, pops the top symbol from the stack and gives it a tree action /// </summary> /// <param name="action">The tree action to apply to the symbol</param> public void ReductionPop(TreeAction action) { SubTree sub = stack[stackNext + popCount]; ReductionAddSub(sub, action); sub.Free(); popCount++; }
/// <summary> /// Initializes a new instance of the <see cref="DecisionTree"/> class. /// </summary> /// <param name="_decisions">_decisions.</param> /// <param name="_actions">_actions.</param> /// <param name="_callback">_callback.</param> public DecisionTree(Decision[] _decisions, TreeAction[] _actions, Action<TreeAction> _callback) { decisions = _decisions; actions = _actions; callback = _callback; doneEvent = new ManualResetEvent(true); }
void LongShootInit() { //shoot begin //celny begin TreeAction celnyGol = new TreeAction(0.55f, null, true, "Bramkarz nie wybronil, gooool!", PlayerGoal); TreeAction celnyBroniChwyta = new TreeAction(0.3f, null, true, "Strzal celny, ale bramkarz lapie pilke", EnemyBall); TreeAction celnyBroniPiastkujeDoRywala = new TreeAction(0.15f, null, true, "Strzal celny, ale bramkarz wypiastkowal do swojego", EnemyBall); TreeAction celnyBroniPiastkujeDoNas = new TreeAction(0.85f, null, true, "Strzal celny, ale bramkarz wypiastkowal do nas", OurBall); TreeAction celnyBroniOdbijaDoRywala = new TreeAction(0.4f, null, true, "Strzal celny, ale bramkarz odbil do swojego", EnemyBall); TreeAction celnyBroniOdbijaDoNas = new TreeAction(0.6f, null, true, "Strzal celny, ale bramkarz odbil do nas", OurBall); TreeAction celnyBroniZaLinieRoznyPrawy = new TreeAction(0.5f, null, true, "Strzal celny, ale bramkarz wybil za linie. Prawy rozny", RightCorner); TreeAction celnyBroniZaLinieRoznyLewy = new TreeAction(0.5f, null, true, "Strzal celny, ale bramkarz wybil za linie. Lewy rozny", LeftCorner); TreeAction celnyTrafiaRywalaZaLiniePrawyRozny = new TreeAction(0.5f, null, true, "Strzal celny, ale pilka trafia rywala i leci za linie. Prawy rozny", RightCorner); TreeAction celnyTrafiaRywalaZaLinieLewyRozny = new TreeAction(0.5f, null, true, "Strzal celny, ale pilka trafia rywala i leci za linie. Lewy rozny", LeftCorner); TreeAction celnyTrafiaRywalaOpanowuje = new TreeAction(0.15f, null, true, "Strzal celny, ale pilka trafia rywala, ktory ja opanowuje", EnemyBall); TreeAction celnyTrafiaRywalaDoNas = new TreeAction(0.15f, null, true, "Strzal celny, ale pilka trafia rywala i leci do nas", OurBall); TreeAction celnyTrafiaRywalaOdbicieDoSektorowObok = new TreeAction(0.1f, null, true, "Strzal celny, ale pilka trafia rywala i leci na jedno z otaczajacych pol", RandomAdjacementField); TreeAction celnyTrafiaNaszegoZaLinie = new TreeAction(0.6f, null, true, "Strzal celny, ale pilka trafia naszego i leci za linie", EnemyBall); TreeAction celnyTrafiaNaszegoDoRywala = new TreeAction(0.15f, null, true, "Strzal celny, ale pilka trafia naszego i leci do rywala", EnemyBall); TreeAction celnyTrafiaNaszegoOpanowuje = new TreeAction(0.15f, null, true, "Strzal celny, ale pilka trafia naszego, ktory ja opanowuje", OurBall); TreeAction celnyTrafiaNaszegoOdbicieDoSektorowObok = new TreeAction(0.1f, null, true, "Strzal celny, ale pilka trafia naszego i leci na jedno z otaczajacych pol", RandomAdjacementField); TreeAction celnyBroniPiastkuje = new TreeAction(0.1f, new TreeAction[] { celnyBroniPiastkujeDoNas, celnyBroniPiastkujeDoRywala }, false, ""); TreeAction celnyBroniOdbija = new TreeAction(0.25f, new TreeAction[] { celnyBroniOdbijaDoNas, celnyBroniOdbijaDoRywala }, false, ""); TreeAction celnyBroniZaLinie = new TreeAction(0.35f, new TreeAction[] { celnyBroniZaLinieRoznyLewy, celnyBroniZaLinieRoznyPrawy }, false, ""); TreeAction celnyTrafiaRywalaZaLinie = new TreeAction(0.6f, new TreeAction[] { celnyTrafiaRywalaZaLinieLewyRozny, celnyTrafiaRywalaZaLiniePrawyRozny }, false, ""); TreeAction celnyBroni = new TreeAction(0.25f, new TreeAction[] { celnyBroniChwyta, celnyBroniPiastkuje, celnyBroniOdbija, celnyBroniZaLinie }, false, ""); TreeAction celnyTrafiaRywala = new TreeAction(0.15f, new TreeAction[] { celnyTrafiaRywalaZaLinie, celnyTrafiaRywalaOpanowuje, celnyTrafiaRywalaDoNas, celnyTrafiaRywalaOdbicieDoSektorowObok }, false, ""); TreeAction celnyTrafiaNaszego = new TreeAction(0.05f, new TreeAction[] { celnyTrafiaNaszegoZaLinie, celnyTrafiaNaszegoDoRywala, celnyTrafiaNaszegoOpanowuje, celnyTrafiaNaszegoOdbicieDoSektorowObok }, false, ""); TreeAction celny = new TreeAction(0.5f, new TreeAction[] { celnyGol, celnyBroni, celnyTrafiaRywala, celnyTrafiaNaszego }, false, ""); //celny end //niecelny begin TreeAction nieCelnyZaLinie = new TreeAction(0.85f, null, true, "Strzal byl niecelny, pilka poleciala za linie", EnemyBall); TreeAction nieCelnySlupekDoBramki = new TreeAction(0.3f, null, true, "Strzal byl niecelny, ale pilka odbila sie od slupka do bramki", PlayerGoal); TreeAction nieCelnySlupekOdbijaDoNas = new TreeAction(0.25f, null, true, "Strzal byl niecelny, ale pilka odbila sie od slupka do nas", OurBall); TreeAction nieCelnySlupekOdbijaDoRywala = new TreeAction(0.25f, null, true, "Strzal byl niecelny, ale pilka odbila sie od slupka do rywali", EnemyBall); TreeAction nieCelnySlupekOdbijaZaLinie = new TreeAction(0.5f, null, true, "Strzal byl niecelny, pilka odbila sie od slupka i poleciala za linie", EnemyBall); TreeAction nieCelnyPoprzeczkaDoBramki = new TreeAction(0.2f, null, true, "Strzal byl niecelny, ale pilka odbila sie od poprzeczki do bramki", PlayerGoal); TreeAction nieCelnyPoprzeczkaOdbijaDoNas = new TreeAction(0.1f, null, true, "Strzal byl niecelny, ale pilka odbila sie od poprzeczki do nas", OurBall); TreeAction nieCelnyPoprzeczkaOdbijaDoRywala = new TreeAction(0.1f, null, true, "Strzal byl niecelny, ale pilka odbila sie od poprzeczki do rywali", EnemyBall); TreeAction nieCelnyPoprzeczkaOdbijaZaLinie = new TreeAction(0.8f, null, true, "Strzal byl niecelny, pilka odbila sie od poprzeczki i poleciala za linie", EnemyBall); TreeAction nieCelnySlupekOdbija = new TreeAction(0.7f, new TreeAction[] { nieCelnySlupekOdbijaDoNas, nieCelnySlupekOdbijaDoRywala, nieCelnySlupekOdbijaZaLinie }, false, ""); TreeAction nieCelnyPoprzeczkaOdbija = new TreeAction(0.8f, new TreeAction[] { nieCelnyPoprzeczkaOdbijaDoNas, nieCelnyPoprzeczkaOdbijaDoRywala, nieCelnyPoprzeczkaOdbijaZaLinie }, false, ""); TreeAction nieCelnySlupek = new TreeAction(0.1f, new TreeAction[] { nieCelnySlupekOdbija, nieCelnySlupekDoBramki }, false, ""); TreeAction nieCelnyPoprzeczka = new TreeAction(0.05f, new TreeAction[] { nieCelnyPoprzeczkaOdbija, nieCelnyPoprzeczkaDoBramki }, false, ""); TreeAction nieCelny = new TreeAction(0.5f, new TreeAction[] { nieCelnyZaLinie, nieCelnySlupek, nieCelnyPoprzeczka }, false, ""); //niecelny end longShoot = new TreeAction(2f, new TreeAction[] { nieCelny, celny }, false, ""); //shoot end }
/// <summary> /// Executes the reduction as a normal reduction /// </summary> /// <param name="varIndex">The reduced variable index</param> /// <param name="headAction">The tree action applied in the rule's head</param> /// <returns>The identifier of the produced SPPF node</returns> private int ReduceNormal(int varIndex, TreeAction headAction) { TableElemRef promotedSymbol = new TableElemRef(); SPPFNodeRef promotedReference = new SPPFNodeRef(SPPF.EPSILON, 0); int insertion = 0; for (int i = 0; i != handleNext; i++) { switch (handleActions[i]) { case TreeAction.Promote: if (promotedReference.NodeId != SPPF.EPSILON) { // not the first promotion // create a new version for the promoted node SPPFNodeNormal oldPromotedNode = sppf.GetNode(promotedReference.NodeId) as SPPFNodeNormal; SPPFNodeRef oldPromotedRef = oldPromotedNode.NewVersion(promotedSymbol, cacheChildren, insertion); // register the previously promoted reference into the cache cacheChildren[0] = oldPromotedRef; insertion = 1; } // save the new promoted node promotedReference = cacheChildren[handleIndices[i]]; SPPFNodeNormal promotedNode = sppf.GetNode(promotedReference.NodeId) as SPPFNodeNormal; SPPFNodeVersion promotedVersion = promotedNode.GetVersion(promotedReference.Version); promotedSymbol = promotedVersion.Label; // repack the children on the left if any Array.Copy(cacheChildren, handleIndices[i] + 1, cacheChildren, insertion, promotedVersion.ChildrenCount); insertion += promotedVersion.ChildrenCount; break; default: // Repack the sub-root on the left if (insertion != handleIndices[i]) { cacheChildren[insertion] = cacheChildren[handleIndices[i]]; } insertion++; break; } } TableElemRef originalLabel = new TableElemRef(TableType.Variable, varIndex); TableElemRef currentLabel = originalLabel; if (promotedReference.NodeId != SPPF.EPSILON) { // a promotion occurred currentLabel = promotedSymbol; } else if (headAction == TreeAction.ReplaceByEpsilon) { // this variable must be replaced in the final AST currentLabel = new TableElemRef(TableType.None, 0); } return(sppf.NewNode(originalLabel, currentLabel, cacheChildren, insertion)); }
/// <summary> /// During a reduction, inserts a virtual symbol /// </summary> /// <param name="index">The virtual symbol's index</param> /// <param name="action">The tree action applied onto the symbol</param> public void ReductionAddVirtual(int index, TreeAction action) { if (action == TreeAction.Drop) { return; // why would you do this? } cache.SetAt(cacheNext, new TableElemRef(TableType.Virtual, index), action); handle[handleNext++] = cacheNext++; }
protected CustomCraftTreeNode(string name, TreeAction action, TechType techType) { Name = name; Action = action; TechType = techType; // This is the actual class used for the real CraftTree CraftNode = new CraftNode(Name, Action, TechType); }
/** * Create a TreeFlag object with integer flag value and action to execute * upon match * * @param flag * int flag value * @param action * object which : the TreeAction interface */ public TreeFlag(int flag, TreeAction action) { this.setFlag(flag); this.setCategory(0); this.setBadness(0); this.setGoodness(0); this.setPostbadness(0); this.setAction(action); }
/// <summary> /// Loads a new instance of the LRProduction class from a binary representation /// </summary> /// <param name="reader">The binary reader to read from</param> public LRProduction(BinaryReader reader) { head = reader.ReadUInt16(); headAction = (TreeAction)reader.ReadByte(); reducLength = reader.ReadByte(); bytecode = new LROpCode[reader.ReadByte()]; for (int i = 0; i != bytecode.Length; i++) { bytecode[i] = new LROpCode(reader); } }
void ThrowInInit() { //ThrowInPlayer begin //udany begin TreeAction udany = new TreeAction(0.6f, null, true, "Dobra wrzutka z autu, partnerzy przy piłce", OurBall); //udany end //nieudany begin TreeAction nieudany = new TreeAction(0.4f, null, true, "Zła wrzutka z autu, piłka trafia do rywali", EnemyBall); //nieudany end ThrowIn = new TreeAction(2f, new TreeAction[] { nieudany, udany }, false, ""); //ThrowInPlayer end }
/// <summary> /// Prepares for the forthcoming reduction operations /// </summary> /// <param name="varIndex">The reduced variable index</param> /// <param name="length">The length of the reduction</param> /// <param name="action">The tree action applied onto the symbol</param> public void ReductionPrepare(int varIndex, int length, TreeAction action) { stackNext -= length; int estimation = ESTIMATION_BIAS; for (int i = 0; i != length; i++) { estimation += stack[stackNext + i].GetSize(); } cache = GetSubTree(estimation); cache.SetupRoot(new TableElemRef(TableType.Variable, varIndex), action); cacheNext = 1; handleNext = 0; popCount = 0; }
void PenaltyInit() { //penalty begin //celny begin TreeAction celnyBramkarzNieBroni = new TreeAction(0.75f, null, true, "Pewnie wykonana jedenastka!", CelnyKarny); TreeAction celnyBramkarzChwyta = new TreeAction(0.1f, null, true, "Bramkarz broni! Źle wykonany karny!", EnemyBall); TreeAction celnyBramkarzWybija = new TreeAction(0.15f, null, true, "Nie ma gola! Bramkarz wyczuł strzelającego! Rzut rożny.", OurBall); TreeAction celny = new TreeAction(0.4f, new TreeAction[] { celnyBramkarzNieBroni, celnyBramkarzChwyta, celnyBramkarzWybija }, false, ""); //celny end //niecelny begin TreeAction niecelny = new TreeAction(0.4f, null, true, "Pudło! Zmarnowany karny!", EnemyBall); //niecelny end Penalty = new TreeAction(2f, new TreeAction[] { niecelny, celny }, false, ""); //penalty end }
public override TreeAction findAction() { if (!isValid()) { return(null); } TreeAction action = null; foreach (Transform t in transform) { TreeNode c = t.GetComponent <TreeNode>(); action = c.findAction(); if (action != null) { break; } } return(action); }
void CornerCPUInit() { //cornerCPUbegin //celny begin TreeAction udanyDoGraczaGlowa = new TreeAction(0.6f, null, true, "Gracz glowkuje po dosrodkowaniu", Head); TreeAction udanyDoGraczaNoga = new TreeAction(0.4f, null, true, "Gracz strzela noga po dosrodkowaniu", PlayerFinishingShot); TreeAction udanyDoPartneraStrzal = new TreeAction(1f, null, true, "Partner strzela noga po dosrodkowaniu", ComputerShoot, checkTypes.PLAYER_ON_PENALTY, 0.6f); TreeAction udanyDoGracza = new TreeAction(0.0f, new TreeAction[] { udanyDoGraczaGlowa, udanyDoGraczaNoga }, false, "", null, checkTypes.PLAYER_ON_PENALTY, 0.4f); TreeAction udany = new TreeAction(0.4f, new TreeAction[] { udanyDoGracza, udanyDoPartneraStrzal }, false, ""); //celny end //niecelny begin TreeAction nieudany = new TreeAction(0.4f, null, true, "Przeciwnik przejmuje pilke", EnemyBall); //niecelny end cornerCPU = new TreeAction(2f, new TreeAction[] { nieudany, udany }, false, ""); //niecelny end //cornerCPUend }
void ThrowInCPUInit() { //ThrowInCPU begin // udany begin TreeAction udanyPierwszySektorDoGracza = new TreeAction(0.8f, null, true, "Gracz otrzymuje piłkę po bliskiej wrzutce z autu", OurBall); TreeAction udanyPierwszySektorDoPartnera = new TreeAction(0.2f, null, true, "Partnerzy otrzymują piłkę po bliskiej wrzutce z autu", OurBall); TreeAction udanyDrugiSektorDoGracza = new TreeAction(0.8f, null, true, "Gracz otrzymuje piłkę po długiej wrzutce z autu", OurBall); TreeAction udanyDrugiSektorDoPartnera = new TreeAction(0.2f, null, true, "Partnerzy otrzymują piłkę po długiej wrzutce z autu", OurBall); TreeAction udanyPierwszySektor = new TreeAction(0.8f, new TreeAction[] { udanyPierwszySektorDoGracza, udanyPierwszySektorDoPartnera }, false, ""); TreeAction udanyDrugiSektor = new TreeAction(0.2f, new TreeAction[] { udanyDrugiSektorDoGracza, udanyDrugiSektorDoPartnera }, false, ""); TreeAction udany = new TreeAction(0.6f, new TreeAction[] { udanyPierwszySektor, udanyDrugiSektor }, false, ""); //udany end //nieudany begin TreeAction nieudany = new TreeAction(0.4f, null, true, "Źle wykonany aut, rywal przy piłce", EnemyBall); //nieudany end ThrowInCPU = new TreeAction(2f, new TreeAction[] { nieudany, udany }, false, ""); //ThrowInCPUend }
/// <summary> /// During a reduction, insert the given sub-tree /// </summary> /// <param name="sub">The sub-tree</param> /// <param name="action">The tree action applied onto the symbol</param> private void ReductionAddSub(SubTree sub, TreeAction action) { if (sub.GetActionAt(0) == TreeAction.ReplaceByChildren) { int directChildrenCount = sub.GetChildrenCountAt(0); while (handleNext + directChildrenCount >= handle.Length) { Array.Resize(ref handle, handle.Length + INIT_HANDLE_SIZE); } // copy the children to the cache sub.CopyChildrenTo(cache, cacheNext); // setup the handle int index = 1; for (int i = 0; i != directChildrenCount; i++) { int size = sub.GetChildrenCountAt(index) + 1; handle[handleNext++] = cacheNext; cacheNext += size; index += size; } } else if (action == TreeAction.Drop) { } else { if (action != TreeAction.None) { sub.SetActionAt(0, action); } // copy the complete sub-tree to the cache if (handleNext == handle.Length) { Array.Resize(ref handle, handle.Length + INIT_HANDLE_SIZE); } sub.CopyTo(cache, cacheNext); handle[handleNext++] = cacheNext; cacheNext += sub.GetChildrenCountAt(0) + 1; } }
/// <summary> /// Adds the specified GSS label to the reduction cache with the given tree action /// </summary> /// <param name="gssLabel">The label to add to the cache</param> /// <param name="action">The tree action to apply</param> private void AddToCache(int gssLabel, TreeAction action) { if (action == TreeAction.Drop) { return; } SPPFNode node = sppf.GetNode(gssLabel); if (node.IsReplaceable) { SPPFNodeReplaceable replaceable = node as SPPFNodeReplaceable; // this is replaceable sub-tree for (int i = 0; i != replaceable.ChildrenCount; i++) { AddToCache(sppf.GetNode(replaceable.Children[i].NodeId) as SPPFNodeNormal, replaceable.Actions[i]); } } else { // this is a simple reference to an existing SPPF node AddToCache(node as SPPFNodeNormal, action); } }
/// <summary> /// Performs the processed action. /// </summary> /// <param name="action">Action.</param> public void PerformAction(TreeAction action) { if(action != null) { //Changes pathfinding strategy if necessary pathfindingStrategy = action.pathFindingMethod; //Tests to see if current state should be changed if(currentState.GetString() != action.targetState) PerformStateTransition(action.targetState); if(action.speed > -1.0f) { enemy.speed = action.speed; } //Sends animation type to animation controller anim.PerformTriggerAnimation(action.animation); //Dynamically Invokes the actions method to be performed if there is one if(action.action != null) action.action.DynamicInvoke(); } }
/// <summary> /// Makes the decision tree. /// </summary> public void MakeDecisionTree() { //Is the search timer up decisions[0] = new Decision((object[] args) => { if(searchTimer > enemy.searchingDuration) return true; else return false; }); //Is Player In Collider decisions[1] = new Decision((object[] args) => { if(enemy.enemySight.playerInCollider) return true; else return false; }); //Is player less than 10 meters away decisions[2] = new Decision((object[] args) => { if(Vector3.Distance(zombiePos, playerPos) < 10) return true; else return false; }); //Is the Player visible? decisions[3] = new Decision((object[]args) => { if(enemy.enemySight.playerInSight) return true; else return false; }); //Is the Player Audible? decisions[4] = new Decision((object[] args) => { if(enemy.enemySight.playerAudible) return true; else return false; }); actions[0] = new TreeAction() { action = () => {enemy.patrolState.GetPatrolPoint(enemy.avgPatrolInterval);}, targetState = "Patrol", pathFindingMethod = "A*", animation = "None" }; actions[1] = new TreeAction() { action = () => {enemy.patrolState.GetPatrolPoint(enemy.avgPatrolInterval);}, targetState = "Patrol", pathFindingMethod = "IterativeDeepening", animation = "None" }; actions[2] = new TreeAction() { targetState = "Chase", pathFindingMethod = "A*", animation = "None" }; actions[3] = new TreeAction() { targetState = "Alert", pathFindingMethod = "A*", animation = "None", speed = enemy.FAST_WALK, action = () => { if(zombie.TargetReached) zombie.CallForNewPath(enemy.enemySight.targetLocation.position, "A*", false ); } }; }
/// <summary> /// Makes the decision tree. /// </summary> public void MakeDecisionTree() { //Is enemy in sight? decisions[0] = new Decision((object[] args)=>{ if(enemy.enemySight.playerInSight) return true; else return false; }); //Is search timer up? decisions[1] = new Decision((object[] args) => { if(searchTimer >= enemy.searchingDuration) return true; else return false; }); //Less than 2 away from player? decisions[2] = new Decision((object[] args) => { if(Vector3.Distance(zombiePos, playerPos) < 2) return true; else return false; }); //Is the enemy in the collider? decisions[3] = new Decision((object[] args) => { if(enemy.enemySight.playerInCollider) return true; else return false; }); //Is the enemy audible? decisions[4] = new Decision((object[] args) => { if(enemy.enemySight.playerAudible) return true; else return false; }); actions[0] = new TreeAction() { pathFindingMethod = "A*", targetState = "Alert", animation = "None" }; actions[1] = new TreeAction() { action = () => {searchTimer = 0f;}, targetState = "Chase", animation = "None", pathFindingMethod = "A*" }; actions[2] = new TreeAction() { action = () => {searchTimer = 0f;}, targetState = "Chase", animation = "attack01", pathFindingMethod = "A*" }; actions[3] = new TreeAction() { action = () => { if(zombie.TargetReached) zombie.CallForNewPath(enemy.enemySight.targetLocation.position, "A*", false ); }, targetState = "Chase", animation = "None", pathFindingMethod = "A*" }; }
protected CustomCraftTreeLinkingNode(string name, TreeAction action, TechType techType) : base(name, action, techType) { }
/// <summary> /// Adds the action to queue to be performed by the AI /// </summary> /// <param name="action">Action.</param> public void AddActionToQueue(TreeAction action) { processedActions.Enqueue(action); }
/// <summary> /// Makes the decision tree. /// </summary> public void MakeDecisionTree() { //Is there an object in front of me? decisions[0] = (new Decision((object[] args) => { if(enemy.enemySight.objectInFront) return true; else return false; })); //Is the distance from enemy to player < 50 meters? decisions[1] = (new Decision((object[]args) => { if(Vector3.Distance(zombiePos, playerPos) < 50) return true; else return false; })); //Was the player last seen > 30 secs ago? decisions[2] = (new Decision((object[]args) => { if(enemy.enemySight.playerLastSeenTime > 30) return true; else return false; })); //Is the player in the collider? decisions[3] = (new Decision((object[]args) => { if(enemy.enemySight.playerInCollider) return true; else return false; })); //Is the Player visible? decisions[4] = (new Decision((object[]args) => { if(enemy.enemySight.playerInSight) return true; else return false; })); //Is the player audible? decisions[5] = (new Decision((object[]args) => { if(enemy.enemySight.playerAudible) return true; else return false; })); actions[0] = new TreeAction() { pathFindingMethod = "DynamicBiDirectional", targetState = "Patrol", animation = "attack02", speed = enemy.STAND_STILL }; actions[1] = new TreeAction() { pathFindingMethod = "DynamicBiDirectional", targetState = "Patrol", animation = "None", speed = enemy.NORMAL_WALK }; actions[2] = new TreeAction() { action = () => {GetPatrolPoint(enemy.avgPatrolInterval);}, args = {}, pathFindingMethod = "DynamicBiDirectional", targetState = "Patrol", animation = "None", speed = enemy.FAST_WALK }; actions[3] = new TreeAction() { pathFindingMethod = "DynamicBiDirectional", targetState = "Patrol", animation = "None", speed = enemy.NORMAL_WALK }; actions[4] = new TreeAction() { pathFindingMethod = "DynamicBiDirectional", targetState = "Chase", animation = "None", speed = enemy.RUNNING }; actions[5] = new TreeAction() { pathFindingMethod = "DynamicBiDirectional", targetState = "Patrol", animation = "None", speed = enemy.NORMAL_WALK }; actions[6] = new TreeAction() { action = () => { if(zombie.TargetReached) zombie.CallForNewPath(enemy.enemySight.targetLocation.position, "DynamicBiDirectional", false ); }, pathFindingMethod = "A*", targetState = "Alert", animation = "None", speed = enemy.SLOW_WALK }; }
/// <summary> /// Executes the given actionTask and commits the ActionResponse to forgeState on success. /// </summary> /// <param name="treeNodeKey">The TreeNode's key where the actions are taking place.</param> /// <param name="treeActionKey">The TreeAction's key of the action taking place.</param> /// <param name="treeAction">The TreeAction object that holds properties of the action.</param> /// <param name="actionDefinition">The object holding definitions for the action to execute.</param> /// <param name="actionTimeoutTask">The delay task tied to the action timeout.</param> /// <param name="token">The cancellation token.</param> /// <exception cref="ActionTimeoutException">If the action-level timeout was hit.</exception> /// <exception cref="OperationCanceledException">If the cancellation token was triggered.</exception> /// <returns> /// RanToCompletion if the action was completed successfully. /// Exceptions are thrown on timeout, cancellation, or retriable failures. /// </returns> internal async Task ExecuteAction( string treeNodeKey, string treeActionKey, TreeAction treeAction, ActionDefinition actionDefinition, Task actionTimeoutTask, CancellationToken token) { // Set up a linked cancellation token to trigger on timeout if ContinuationOnTimeout is set. // This ensures the runActionTask gets canceled when Forge timeout is hit. CancellationTokenSource actionCts = CancellationTokenSource.CreateLinkedTokenSource(token); token = treeAction.ContinuationOnTimeout ? actionCts.Token : token; // Evaluate the dynamic properties that are used by the actionTask. ActionContext actionContext = new ActionContext( this.Parameters.SessionId, treeNodeKey, treeActionKey, treeAction.Action, await this.EvaluateDynamicProperty(treeAction.Input, actionDefinition.InputType).ConfigureAwait(false), await this.EvaluateDynamicProperty(treeAction.Properties, null).ConfigureAwait(false), this.Parameters.UserContext, token, this.Parameters.ForgeState ); // Instantiate the BaseAction-derived ActionType class and invoke the RunAction method on it. var actionObject = Activator.CreateInstance(actionDefinition.ActionType); MethodInfo method = typeof(BaseAction).GetMethod("RunAction"); Task <ActionResponse> runActionTask = (Task <ActionResponse>)method.Invoke(actionObject, new object[] { actionContext }); // Await for the first completed task between our runActionTask and the timeout task. // This allows us to continue without awaiting the runActionTask upon timeout. var completedTask = await Task.WhenAny(runActionTask, actionTimeoutTask).ConfigureAwait(false); if (completedTask == actionTimeoutTask) { // Throw on cancellation requested if that's the reason the timeout task completed. token.ThrowIfCancellationRequested(); // If the timeout is hit and the ContinuationOnTimeout flag is set, commit a new ActionResponse // with the status set to TimeoutOnAction and return. if (treeAction.ContinuationOnTimeout) { // Trigger linked cancellation token before continuing to ensure the runActionTask gets cancelled. actionCts.Cancel(); ActionResponse timeoutResponse = new ActionResponse { Status = "TimeoutOnAction" }; await this.CommitActionResponse(treeActionKey, timeoutResponse).ConfigureAwait(false); return; } // ActionTimeout has been hit. Throw special exception to indicate this. throw new ActionTimeoutException(string.Format( "ActionTimeoutTask timed out before Action could complete. TreeNodeKey: {0}, TreeActionKey: {1}, ActionName: {2}.", treeNodeKey, treeActionKey, treeAction.Action)); } else { // Handle the completed runActionTask. if (runActionTask.Status == TaskStatus.RanToCompletion) { await this.CommitActionResponse(treeActionKey, await runActionTask).ConfigureAwait(false); } // Await the completed task to propagate any exceptions. // Exceptions are thrown here if the action hit a timeout, was cancelled, or failed. await runActionTask; } }
/// <summary> /// Executes the given action. Attempts retries according to the retry policy and timeout. /// Returns without throwing exception if the action was completed successfully. /// </summary> /// <param name="treeNodeKey">The TreeNode's key where the actions are taking place.</param> /// <param name="treeActionKey">The TreeAction's key of the action taking place.</param> /// <param name="treeAction">The TreeAction object that holds properties of the action.</param> /// <param name="actionDefinition">The object holding definitions for the action to execute.</param> /// <param name="token">The cancellation token.</param> /// <exception cref="ActionTimeoutException">If the action-level timeout was hit.</exception> /// <exception cref="OperationCanceledException">If the cancellation token was triggered.</exception> internal async Task ExecuteActionWithRetry( string treeNodeKey, string treeActionKey, TreeAction treeAction, ActionDefinition actionDefinition, CancellationToken token) { // Initialize values. Default infinite timeout. Default RetryPolicyType.None. int retryCount = 0; Exception innerException = null; Stopwatch stopwatch = new Stopwatch(); int actionTimeout = (int)await this.EvaluateDynamicProperty(treeAction.Timeout ?? -1, typeof(int)).ConfigureAwait(false); RetryPolicyType retryPolicyType = treeAction.RetryPolicy != null ? treeAction.RetryPolicy.Type : RetryPolicyType.None; TimeSpan waitTime = treeAction.RetryPolicy != null?TimeSpan.FromMilliseconds(treeAction.RetryPolicy.MinBackoffMs) : new TimeSpan(); // Kick off timers. Task actionTimeoutTask = Task.Delay(actionTimeout, token); stopwatch.Start(); // Attmpt to ExecuteAction based on RetryPolicy and Timeout. // Throw on non-retriable exceptions. while (actionTimeout == -1 || stopwatch.ElapsedMilliseconds < actionTimeout) { token.ThrowIfCancellationRequested(); try { await this.ExecuteAction(treeNodeKey, treeActionKey, treeAction, actionDefinition, actionTimeoutTask, token).ConfigureAwait(false); return; // success! } catch (OperationCanceledException) { throw; // non-retriable exception } catch (ActionTimeoutException) { throw; // non-retriable exception } catch (EvaluateDynamicPropertyException) { throw; // non-retriable exception } catch (Exception e) { // Cache exception as innerException in case we need to throw ActionTimeoutException. innerException = e; // Hit retriable exception. Retry according to RetryPolicy. // When retries are exhausted, throw ActionTimeoutException with Exception e as the innerException. switch (retryPolicyType) { case RetryPolicyType.FixedInterval: { // FixedInterval retries every MinBackoffMs until the timeout. // Ex) 200ms, 200ms, 200ms... waitTime = TimeSpan.FromMilliseconds(treeAction.RetryPolicy.MinBackoffMs); break; } case RetryPolicyType.ExponentialBackoff: { // ExponentialBackoff retries every Math.Min(MinBackoffMs * 2^(retryCount), MaxBackoffMs) until the timeout. // Ex) 100ms, 200ms, 400ms... waitTime = TimeSpan.FromMilliseconds(Math.Min(treeAction.RetryPolicy.MaxBackoffMs, waitTime.TotalMilliseconds * 2)); break; } case RetryPolicyType.None: default: { // No retries. Break out below to throw non-retriable exception. break; } } } // Break out if no retry policy set. if (retryPolicyType == RetryPolicyType.None) { // If the retries have exhausted and the ContinuationOnRetryExhaustion flag is set, commit a new ActionResponse // with the status set to RetryExhaustedOnAction and return. if (treeAction.ContinuationOnRetryExhaustion) { ActionResponse timeoutResponse = new ActionResponse { Status = "RetryExhaustedOnAction" }; await this.CommitActionResponse(treeActionKey, timeoutResponse).ConfigureAwait(false); return; } break; } // Break out early if we would hit timeout before next retry. if (actionTimeout != -1 && stopwatch.ElapsedMilliseconds + waitTime.TotalMilliseconds >= actionTimeout) { // If the timeout is hit and the ContinuationOnTimeout flag is set, commit a new ActionResponse // with the status set to TimeoutOnAction and return. if (treeAction.ContinuationOnTimeout) { ActionResponse timeoutResponse = new ActionResponse { Status = "TimeoutOnAction" }; await this.CommitActionResponse(treeActionKey, timeoutResponse).ConfigureAwait(false); return; } break; } token.ThrowIfCancellationRequested(); await Task.Delay(waitTime, token).ConfigureAwait(false); retryCount++; } // Retries are exhausted. Throw ActionTimeoutException with executeAction exception as innerException. throw new ActionTimeoutException( string.Format( "Action did not complete successfully. TreeNodeKey: {0}, TreeActionKey: {1}, ActionName: {2}, RetryCount: {3}, RetryPolicy: {4}", treeNodeKey, treeActionKey, treeAction.Action, retryCount, retryPolicyType), innerException); }
/// <summary> /// Executes the actions for the given tree node. /// Returns without throwing exception if all actions were completed successfully. /// </summary> /// <param name="treeNode">The TreeNode containing actions to execute.</param> /// <param name="treeNodeKey">The TreeNode's key where the actions are taking place.</param> /// <exception cref="TimeoutException">If the node-level timeout was hit.</exception> /// <exception cref="ActionTimeoutException">If the action-level timeout was hit.</exception> /// <exception cref="OperationCanceledException">If the cancellation token was triggered.</exception> internal async Task PerformActionTypeBehavior(TreeNode treeNode, string treeNodeKey) { List <Task> actionTasks = new List <Task>(); if (treeNode.Actions == null) { return; } // Start new parallel tasks for each action on this node. foreach (KeyValuePair <string, TreeAction> kvp in treeNode.Actions) { string treeActionKey = kvp.Key; TreeAction treeAction = kvp.Value; if (await this.GetOutputAsync(treeActionKey).ConfigureAwait(false) != null) { // Handle rehydration case. Commit LastTreeAction if it was not committed. Do not execute actions for which we have already received a response. if (await this.GetLastTreeAction().ConfigureAwait(false) == null) { await this.CommitLastTreeAction(treeActionKey).ConfigureAwait(false); } continue; } if (this.actionsMap.TryGetValue(treeAction.Action, out ActionDefinition actionDefinition)) { actionTasks.Add(this.ExecuteActionWithRetry(treeNodeKey, treeActionKey, treeAction, actionDefinition, this.walkTreeCts.Token)); } } // Wait for all parallel tasks to complete until the given timout. // If any task hits a timeout, gets cancelled, or fails, an exception will be thrown. // Note: CancelWalkTree is called at the end of every session to ensure all Actions/Tasks see the triggered cancellation token. Task nodeTimeoutTask = Task.Delay((int)await this.EvaluateDynamicProperty(treeNode.Timeout ?? -1, typeof(int)).ConfigureAwait(false), this.walkTreeCts.Token); actionTasks.Add(nodeTimeoutTask); while (actionTasks.Count > 1) { // Throw if cancellation was requested between actions completing. this.walkTreeCts.Token.ThrowIfCancellationRequested(); Task completedTask = await Task.WhenAny(actionTasks).ConfigureAwait(false); actionTasks.Remove(completedTask); if (completedTask == nodeTimeoutTask) { // Throw on cancellation requested if that's the reason the timeout task completed. this.walkTreeCts.Token.ThrowIfCancellationRequested(); // NodeTimeout was hit, throw a special exception to differentiate between timeout and cancellation. throw new TimeoutException("Hit node-level timeout in TreeNodeKey: " + treeNodeKey); } // Await the completed task to propagate any exceptions. // Exceptions are thrown here if the action hit a timeout, was cancelled, or failed. await completedTask; } }