manipulating my robocode robot

I'm at a stage in my robocode implementation that I can begin to write some more observations and begin manipulating my robot. In this post I'll be:

  • creating a new observer for when there is no focus
  • issuing instructions to the robot to look for enemies
  • investigating and resolving a stackoverflow exception!
  • finally watching my robot be manipulated for the first time in my domain driven design code. At last!

The observer I'm wanting to begin with is the one that will ensure the robot looks for enemies and will effectively stop the robot being dormant. I therefore want to check if we are focused on anything and if we are not, I want to issue instructions to the robot engine. Here's the specification for this observer:

    [Subject(typeof(WeHaveNoFocusObserver))]
    public class when_there_is_no_current_focus
    {
        Establish context = () =>
        {
            manipulationState = new ManipulationState { WeAreFocusedOnSomething = false };
            manipulationStateEvent = MockRepository.GenerateStub<IEvent<ManipulationState>>();
            manipulationStateEvent.Stub(s => s.EventArgs).Return(manipulationState);
            manipulationStateObservable = Observable.Return(manipulationStateEvent);
            
            robotEngine = MockRepository.GenerateStub<ImARobotEngine>();
            robotEngine.Stub(e => e.IssueInstructionsToRobot(null))
                       .IgnoreArguments().Do(RecordInstruction);

            weHaveNoFocusObserver = new WeHaveNoFocusObserver(robotEngine);
        };

        Because of = () => weHaveNoFocusObserver.Observe(manipulationStateObservable);

        It should_subscribe_to_the_observable_and_recognise_that_we_have_no_focus = () =>
            weHaveNoFocusObserver.RecognisedThatWeHaveNoFocus.ShouldBeTrue();

        It should_issue_instructions_for_the_robot_engine_to_look_for_enemies = () =>
            ShouldHaveIssuedInstruction(x => x.LookForEnemies());

        static Action<Action<ImARobot>> RecordInstruction = i => 
                                                  instructionSentToRobotEngine = i;

        static void ShouldHaveIssuedInstruction(Action<ImARobot> expectedInstruction)
        {
            var robot = MockRepository.GenerateStub<ImARobot>();
            if (instructionSentToRobotEngine != null)
                instructionSentToRobotEngine(robot);
            robot.AssertWasCalled(expectedInstruction);
        }

        static ManipulationState manipulationState;
        protected static IEvent<ManipulationState> manipulationStateEvent;
        protected static IObservable<IEvent<ManipulationState>> manipulationStateObservable;        
        static WeHaveNoFocusObserver weHaveNoFocusObserver;
        static ImARobotEngine robotEngine;
        static Action<ImARobot> instructionSentToRobotEngine;
    }

This specification is very similar to the original start of the battle observer (if you have been following the whole series) which is now removed and replaced by this new manipulation state observer.

Essentially the specification is setting up some manipulation state which shows there is currently nothing in focus and providing this via an observable when it is told to observe.
Then, a robot engine is stubbed and it is set to record any instruction action of type Action<ImARobot> that is sent to it.

Finally I'm then taking the recorded action and manipulating a newly stubbed robot - this way I can determine what the action delegate contains and assert that it was the expected instruction of LookForEnemies().

Here's the implementation to make this pass:

    public class WeHaveNoFocusObserver : IObserveToManipulate
    {
        ImARobotEngine robotEngine;

        public WeHaveNoFocusObserver(ImARobotEngine robotEngine)
        {
            this.robotEngine = robotEngine;
        }

        public void Observe(IObservable<IEvent<ManipulationState>> situation)
        {
            situation.Where(s => s.EventArgs.WeAreFocusedOnSomething == false)
                .Subscribe(s =>
                   {
                        RecognisedThatWeHaveNoFocus = true;
                        robotEngine.IssueInstructionsToRobot(r => r.LookForEnemies());
                   });
        }

        public bool RecognisedThatWeHaveNoFocus { get; private set; }
    }

It is now looking very simple for me to add behaviour into my robocode code - the above code now subscribes to when there is no focus and looks for enemies. Here's the code for that LookForEnemies() call that was built in a previous post, and only part of the robot is shown here :

    public class SlayerRobot : Robot, ImARobot
    { 
        public void LookForEnemies()
        {
            TurnRadarRight(360);
        }

    }

This all looks great, but when I run through robocode it completely crashes on me!
A stackoverflow exception is killing the application.

After a little digging it is because I have a circular dependency in the constructor of the ManipulationStateKeeper.
When a robot engine is resolved from the IOC container, it creates a manipulation state keeper and the constructor of this is then asking the service locator to resolve a robot engine; this then creates another manipulation state keeper and so on until it crashes.

The solution is to ensure the service locator caches the resolved robot engine and to then change the ManipulationStateKeeper so that the process of passing the robot engine to the manipulation observers occurs a little later:

    public class ManipulationStateKeeper : StateKeeper<ManipulationState, IObserveToManipulate>
    {
        public ManipulationStateKeeper(IEnumerable<IObserveToManipulate> observers) : 
                                                                               base(observers)
        {
        }

        protected override ManipulationState EnsureThatStateHasBeenCreated()
        {
            return new ManipulationState();
        }

        protected override IObservable<IEvent<ManipulationState>> 
                                                EnsureThatTheObservableHasBeenCreated()
        {
            EnsureThatObserversAreGivenTheRobotEngine();

            return Observable.FromEvent<ManipulationState>(
                ev => this.StateHasUpdated += ev,
                ev => this.StateHasUpdated -= ev);
        }

        void EnsureThatObserversAreGivenTheRobotEngine()
        {
            var robotEngine = ServiceLocator.ObtainThePreviouslyRequestedRobotEngine();
            foreach (var observer in observers)
            {
                observer.UseTheRobotEngine(robotEngine);
            }
        }
    }

Now when I run my code in a battle, my robot is finally manipulated and scans for enemies!

MyRobotIsManipulated



0 comments: