<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged c#-ai</title>
<link>https://coderlegion.com/tag/c%23-ai</link>
<description>Powered by Question2Answer</description>
<item>
<title>Learn how FSM_API uses decoupled state machines to run a &quot;Fox and Dog&quot; AI simulation. </title>
<link>https://coderlegion.com/6261/learn-how-fsmapi-uses-decoupled-state-machines-to-run-a-fox-and-dog-ai-simulation</link>
<description>&lt;h3 id=&quot;implementing-behavior-trees-with-fsm-api-the-quick-brown-fox-and-lazy-sleeping-dog-demo&quot;&gt;Implementing Behavior Trees with FSM_API: The Quick Brown Fox and Lazy Sleeping Dog Demo&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Finite State Machines (FSMs)&lt;/strong&gt; are a foundational pattern for organizing complex logic in software, from game AI to business workflows. The &lt;strong&gt;FSM_API&lt;/strong&gt; library provides a high-performance, engine-agnostic C# solution for building and managing these systems with clarity and efficiency.&lt;/p&gt;
&lt;p&gt;This article dives into the &lt;strong&gt;Quick Brown Fox and Lazy Sleeping Dog demo&lt;/strong&gt;, an excellent, practical example found in the FSM_API public repository. It showcases how to implement simple, interacting AI agents, effectively decoupling agent data from agent behavior logic using the library's core features.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;fsm-api-core-concepts-in-the-demo&quot;&gt;FSM_API Core Concepts in the Demo&lt;/h3&gt;
&lt;p&gt;Every behavioral entity in this simulation—the Fox and the Dog—relies on three core FSM_API concepts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The State Context (&lt;code&gt;IStateContext&lt;/code&gt;):&lt;/strong&gt; This is your actual game object (the &lt;strong&gt;Fox&lt;/strong&gt; or the &lt;strong&gt;Dog&lt;/strong&gt;), holding the data (e.g., &lt;code&gt;Position&lt;/code&gt;, &lt;code&gt;Speed&lt;/code&gt;, &lt;code&gt;CollidedAgents&lt;/code&gt;) and implementing the transition methods. It must implement the &lt;code&gt;IStateContext&lt;/code&gt; interface, which requires providing a &lt;code&gt;Name&lt;/code&gt; and an &lt;code&gt;IsValid&lt;/code&gt; property.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The FSM Definition:&lt;/strong&gt; This is the reusable blueprint of states (e.g., &quot;Sleeping&quot;, &quot;Walking&quot;) and the rules for transitioning between them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The FSM Instance:&lt;/strong&gt; This is the live, active version of the blueprint, associated with a specific agent context. Both agents' FSMs are set up to run in the &lt;strong&gt;&quot;Update&quot; processing group&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-lazy-sleeping-dog-s-behavior&quot;&gt;The Lazy Sleeping Dog's Behavior&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;LazySleepingDog&lt;/code&gt; class is initialized at &lt;code&gt;Position = 3&lt;/code&gt; and starts in the &lt;strong&gt;&quot;Sleeping&quot;&lt;/strong&gt; state. Its FSM defines a classic threat response lifecycle:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;State &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;OnUpdate Action &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Transition Condition (to) &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Transition Target&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Sleeping&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Console log: &lt;em&gt;&quot;...is sleeping!&quot;&lt;/em&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;IsAwake(context)&lt;/code&gt;: &lt;code&gt;CollidedAgents.Any()&lt;/code&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Awake&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Awake&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Console log: &lt;em&gt;&quot;...is awake!&quot;&lt;/em&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ShouldChase(context)&lt;/code&gt;: &lt;code&gt;VisibleAgents.Any(s =&amp;gt; s is QuickBrownFox)&lt;/code&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Chasing&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Chasing&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;Position&lt;/code&gt; increases by &lt;code&gt;Speed&lt;/code&gt; (set to 3 on enter) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;IsMangling(context)&lt;/code&gt;: &lt;code&gt;CollidedAgents.Any(s =&amp;gt; s is QuickBrownFox)&lt;/code&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Mangling&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Mangling&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Console log: &lt;em&gt;&quot;...is Mangling the fox!&quot;&lt;/em&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;N/A &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;N/A&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Crucially, in the &lt;strong&gt;&quot;Mangling&quot;&lt;/strong&gt; state's &lt;code&gt;OnEnterMangling&lt;/code&gt; handler, the dog directly uses the FSM_API to transition the collided agent's state (the Fox) to &lt;strong&gt;&quot;Mangled&quot;&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-csharp&quot;&gt;// Inside OnEnterMangling for the dog
dog.CollidedAgents.FirstOrDefault()?.State.TransitionTo(&quot;Mangled&quot;); 
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-quick-brown-fox-s-behavior&quot;&gt;The Quick Brown Fox's Behavior&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;QuickBrownFox&lt;/code&gt; starts at &lt;code&gt;Position = 0&lt;/code&gt; and its FSM defines its attempts to flee the dog and reach a winning position:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;State &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;OnUpdate Action &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Transition Condition (to) &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Transition Target&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Walking&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;Position&lt;/code&gt; increases by &lt;code&gt;Speed&lt;/code&gt; (1) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ShouldJump(context)&lt;/code&gt;: &lt;code&gt;VisibleAgents&lt;/code&gt; within 2 units &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Jumping&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Jumping&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;Position&lt;/code&gt; increases by &lt;code&gt;Speed&lt;/code&gt; (1) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ShouldLand(context)&lt;/code&gt;: &lt;code&gt;Position&lt;/code&gt; reaches &lt;code&gt;JumpEnd&lt;/code&gt; (initial position + 2) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Walking&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Fleeing&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;Position&lt;/code&gt; increases by &lt;code&gt;Speed&lt;/code&gt; (set to 2 on enter) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;N/A &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;N/A&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Mangled&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Console log: &lt;em&gt;&quot;...is being mangled!&quot;&lt;/em&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;N/A &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;N/A&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The Fox's ultimate defensive move is the transition to &lt;strong&gt;&quot;Fleeing&quot;&lt;/strong&gt;, which is triggered by a direct collision with a &lt;code&gt;LazySleepingDog&lt;/code&gt;. However, if the Dog catches it while fleeing, the Dog forces the Fox into the terminal &lt;strong&gt;&quot;Mangled&quot;&lt;/strong&gt; state.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-simulation-loop-simpledemocontext-&quot;&gt;The Simulation Loop (&lt;code&gt;SimpleDemoContext&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;SimpleDemoContext&lt;/code&gt; acts as the game manager, controlling the flow of the entire application. It sets up the following structure:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Processing Groups:&lt;/strong&gt; It creates a &lt;strong&gt;&quot;Main&quot;&lt;/strong&gt; group for the application's FSM (&lt;code&gt;AppFSM&lt;/code&gt;) and an &lt;strong&gt;&quot;Update&quot;&lt;/strong&gt; group where the agents' FSMs run.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tick Logic:&lt;/strong&gt; The core simulation runs in &lt;code&gt;OnUpdateExecuting&lt;/code&gt;:&lt;ul&gt;
&lt;li&gt;It &lt;strong&gt;clears&lt;/strong&gt; previous frame's agent data.&lt;/li&gt;
&lt;li&gt;It performs &lt;strong&gt;Vision and Collision&lt;/strong&gt; checks based on the agents' current &lt;code&gt;Position&lt;/code&gt; and &lt;code&gt;Sight&lt;/code&gt; range, populating the &lt;code&gt;VisibleAgents&lt;/code&gt; and &lt;code&gt;CollidedAgents&lt;/code&gt; lists.&lt;/li&gt;
&lt;li&gt;It calls &lt;code&gt;FSM_API.Interaction.Update(&quot;Update&quot;)&lt;/code&gt;. This single call iterates through and updates &lt;em&gt;all&lt;/em&gt; FSM instances assigned to the &quot;Update&quot; group (the Fox and the Dog), triggering their &lt;code&gt;onUpdate&lt;/code&gt; actions and checking their transition conditions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shutdown:&lt;/strong&gt; The application's &lt;code&gt;AppFSM&lt;/code&gt; transitions to &lt;strong&gt;&quot;Shutdown&quot;&lt;/strong&gt; if a key is pressed, if the Fox reaches the &lt;code&gt;WinPosition&lt;/code&gt; (10), or if &lt;strong&gt;any agent's state is &quot;Mangled&quot;&lt;/strong&gt;. The FSM_API then manages the cleanup.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;code&gt;Program.cs&lt;/code&gt; file initiates the simulation and loops the main update call until the application context becomes invalid. This structure demonstrates how FSM_API cleanly separates an agent's &lt;strong&gt;Data&lt;/strong&gt; (&lt;code&gt;IStateContext&lt;/code&gt; properties) from its &lt;strong&gt;Behavioral Logic&lt;/strong&gt; (the FSM Definition) and relies on a central &lt;strong&gt;Simulation Tick&lt;/strong&gt; (&lt;code&gt;FSM_API.Interaction.Update()&lt;/code&gt;) to drive complex, interactive AI.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;stay-tuned-for-the-advanced-demo&quot;&gt;Stay Tuned for the Advanced Demo&lt;/h3&gt;
&lt;p&gt;This simple, 1D simulation laid the groundwork, but the next step is building a true environment!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stay tuned for a follow-up article&lt;/strong&gt; where we'll use these &lt;strong&gt;exact same agent FSMs&lt;/strong&gt; to create an &lt;strong&gt;advanced 2D environment&lt;/strong&gt; with &lt;strong&gt;multiple dogs and foxes&lt;/strong&gt; interacting simultaneously. This will highlight the true power of &lt;strong&gt;decoupled FSM definitions&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Follow us to stay informed! And for much more content, advanced articles, and discussions about our vision for the &lt;strong&gt;software for the singularity&lt;/strong&gt;, check out our:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.patreon.com/TheSingularityWorkshop&quot;&gt;&lt;strong&gt;Patreon Page&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;get-the-code&quot;&gt;Get the Code&lt;/h3&gt;
&lt;p&gt;You can explore the full implementation of this FSM-driven AI simulation and the FSM_API library structure by cloning the public repository:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/TrentBest/SimpleDemos&quot;&gt;&lt;strong&gt;https://github.com/TrentBest/SimpleDemos&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
</description>
<category>API Dev</category>
<guid isPermaLink="true">https://coderlegion.com/6261/learn-how-fsmapi-uses-decoupled-state-machines-to-run-a-fox-and-dog-ai-simulation</guid>
<pubDate>Thu, 09 Oct 2025 22:17:48 +0000</pubDate>
</item>
</channel>
</rss>