2011

by paet the pagan-gerbil 1. January 2012 14:22

Ha, well I certainly couldn’t miss a post today, could I. Not after writing a review for 2009 and 2010, anyway. I’ve noticed that most years, I get one big thing and nothing else matters. Freddy in 2008, the house in 2009, and the car in 2010. Taking into account my daughter was born this year, what do you think I’ll be thinking about the most?

Did you enjoy this year?
Yes, a huge amount. I have a small baby again, Freddy continues to get more and more grown-up, and I’m getting more interesting challenges in work.

What did you do in 2011 that you'd never done before?
Had two car accidents... Had a daughter... bought a very flashy phone... went to a strip club... I usually spend a week writing this review, so I can remember the things that happened and add to them. No time, this is being done on the fly!

Did you keep your new year’s resolutions, and will you make more for next year?
My resolutions for this year were:

  1. Go swimming once a week
    Failed. I think I went swimming twice.
  2. Paint for forty-five minutes a week
    Kept it up for quite a while, but failed halfway through the year and never caught up lost time.
  3. Save money, overpay at least a month on the mortgage
    Done! And saved enough to pay for a trip to Cuba next year!
  4. More pictures on this blog!
    Well, when I posted, I posted pictures. But I didn’t post much.
  5. Spend no more than £5 a month on games
    Made it through half the year, but one computer game can knock out 7 months of the budget in one go. £5 is a little too low with the price of things nowadays.
  6. More games and games nights.
    Nope. I managed a few games of Warhammer, and dragged myself to Games Workshop and Cut and Thrust to try and get into it, but I just don’t plan ahead enough.
  7. Blog on A Year of Frugal Gaming once a month
    This is the one I’m most disappointed about not keeping. It’s not my blog, and feels like I’ve let other people down.

I will make more for this year, but with a great big holiday sitting in February, I need to consider what my resolutions will be, and work out what I want to do. More details to follow.

Did anyone close to you give birth?
As I mentioned many pregnancies last year, they all popped through this year. Old friends, cousins, and of course we had our baby in June.

Did anyone close to you die?
No, but a lot of my friends lost someone very, very close to them.

What countries did you visit?
None. City-wise, I went to London, Southampton and Portsmouth. I feel like I’ve been travelling less and less as I get older – never more than 110 miles from home.

What would you like to have in 2012 that you lacked in 2011?
More of my resolutions complete. I’m also eyeing up some large purchases in the house – we’re going to begin bending it towards what we want, rather than what we bought.

What date from 2011 will remain etched upon your memory, and why?
I would be very, very bad if I couldn’t remember the 15th June – the day that Izzy was born.

What was your biggest achievement of the year?
Having a daughter. She loves me.

What was your biggest failure?
Failed to keep any resolutions.

Did you suffer illness or injury?
I managed quite well through the year, only a slight hiccup in June (stress before Izzy was born dragged the immune system down) then a nasty attack of tonsillitis kept me right out of the real world for a whole week in December. Otherwise, generally managed to keep myself good.

Did you have to go to the hospital?
Check ups for the new baby, and to actually get her out (though that wasn’t the plan). Also to get Izzy’s tongue-tie cut, twice. And it might have grown back.

What was the best thing you bought?
My new phone. Although it was free on a contract. And I bought the flights to Cuba this year, but won’t actually go until February.

Whose behaviour merited celebration?
The kids, and many many other people.

Whose behaviour made you appalled and depressed?
Stanislaw Burzynski, for reasons that link will make apparent. Google (or Bing) for more, there’s lots out there. If you’re going to take advantage of cancer sufferers for financial gain, you have to accept that people will call you on it – the correct response is not to threaten legal action.

Most of our government, for more selfish reasons.

Where did most of your money go?
Mostly house stuff. A big chunk on our holiday, and it’ll totally be worth it.

What did you get really, really, really excited about?
Elizabeth! And the fact that she can digest with vomiting!

What song will always remind you of 2011?
Jessie-J, Pricetag. I heard an awesome live version in the car on my way to Portsmouth. Alongside that, I loved Swede Mason’s Masterchef Synaesthesia (Buttery Biscuit Bass). Find it on Youtube.

Compared to this time last year, are you:
i. Happier or sadder?

Happier.
ii. richer or poorer?
About the same.

What do you wish you'd done more of?
More of my resolutions. More games of Warhammer.

What do you wish you'd done less of?
Watching DVDs. We’ve burned through almost all of DS9 and Voyager this year.

How did you spend Christmas?
In Portsmouth with my parents. Then a week doing almost nothing, and finally a long car drive back to Bristol with the car absolutely filled to the brim with toys.

Where did you ring in 2011?
At home, as is normal now. I went out at midnight to chat with some neighbours, then went back to bed.

What was your favourite TV programme?
I wouldn’t say favourite, but the only new thing we watched this year was the Big Bang Theory.

Do you hate anyone now that you didn't hate this time last year?
Nope.

What was the best book you read?
I just finished reading Snuff, I thought that was awesome. I liked PG Wodehouse (Code of the Woosters) but I think that may have been last year.

What was your greatest musical discovery?
Swede Mason, Tim Minchin and Jessie-J. I don’t really follow music so that’s about it.

What did you want and get?
A daughter! I know everyone says that they don’t mind, but I’ve got one of each now.

What did you want and not get?
A daughter on my birthday. She was due the day after, but turned up 4 days late.

How did you earn your keep?
Still programming.

What was your favourite film of this year?
Didn’t see any new films. Next year, I will be watching at least The Hobbit. We must start getting to the cinema again!

What did you do on your birthday, and how old were you?
I was 27 – I was probably ill, and waiting on tenterhooks for my wife to give birth.

What one thing would have made your year immeasurably more satisfying?
I can’t think of anything other than actually completing any of my resolutions.

How would you describe your personal fashion concept in 2011?
”OK, those clothes are literally falling apart on you.” I can see 2012 as the year I need to buy a new wardrobe before my fashion concept is “it was good enough for the monkeys...”

What kept you sane?
Dark, quiet rooms when everyone is out. I can really appreciate not doing anything these days.

What political issue stirred you the most?
Mostly the phrase “we’re all in this together”, except that obviously we’re not. For example, Occupy movements and public sector strikes are seen as selfish, and not being all in this together, but the poor are getting poorer and the rich are getting richer. “All in this together” also means not chipping in and helping our European neighbours sort themselves out, when their possible collapse will deeply affect us. I don’t know what the right course of action really is, I just feel like the Prime Minister doesn’t either. All I know is that we’re not all in this together.

Aside from that, my obsession with media-watch blogs has kept me very very interested in the Leveson Inquiry. I really hope we get what we need from it.

Who was the best new person you met?
Does Izzy count?

Tell us a valuable life lesson you learned in 2011:
Keep your mouth shut.

Quote a song lyric that sums up your year:
”I’m having trouble trying to sleep...” and the rest of it, by Green Day. I think the song is called Brain Stew.

What is the best thing that you were given?
Aside from the baby?

A new job role – away from websites, and more into infrastructure things. Bigger challenges, more room for personal growth.

What is the best thing you have given someone?
I gave Freddy a sister, and my family a holiday (coming soon!)

Tags: ,

General | Journal

It's Oh So Quiet...

by paet the pagan-gerbil 19. June 2011 15:52

BIG NEWS!

On Wednesday 15th June, at 15:45, my daughter Elizabeth was born!

She is gorgeous, and looks a lot like her brother when he was new. She weighed 6lb 2oz.

It was a very strange day – our son was a (planned) home birth, and we’d looked into getting a birthing pool. Unfortunately, they are expensive to buy or hire, and we lived in a smaller house then so there wasn’t space for one. Southmead Hospital (the premier maternity ward in the area) had a pool, but it couldn’t be reliably booked – babies don’t normally conform to schedules. Add to that he was due at the end of November, and the associated problems with keeping a large body of water warm in a cheap house at that time of year. We scrapped the idea, had a lovely home birth, and completely forgot about it for Elizabeth.

259084_10150279055926085_777431084_9089077_1867059_oOn the day, we happened to be in hospital for a quick check up and assessment. They finished with ‘we can see you want a homebirth, so we’ll just get your notes ready and you can go.’ By the time they came out with all the discharge paperwork, the contractions had come on thick and fast and we weren’t sure we’d make it home in the morning traffic before the baby decided to arrive, so we asked to stay and deliver in the hospital.

At this time, all the visions that made us want a home birth came back – the beginning of Monty Python’s Meaning Of Life being among them (the machine that goes ‘ping’, etc etc). We’re practical people, and always knew that we might not get what we wanted, so we were prepared to just knuckle down and take it. However, since our notes had ‘home birth’ listed on them, the midwives made a point to check the availability of the birth suite in the hospital. A birth suite is a bit more of a home from home than the ward, with separate kitchen and bathroom facilities, living room type rooms to deliver in, and a more comfortable environment in the middle of the hospital. Like having a home birth, with the machine that goes ‘ping’ on standby down the corridor if it’s needed. After a few phone calls, they worked out it was empty but could be staffed. Result!

As we were being shown the suite, the student midwife showed us the rooms and said ‘and the room at the end has the birthing pool.’ My wife’s ears pricked up. ‘Can we have that?’ she asked.

So a completely unplanned water birth – which was a million miles from what we expected. A hospital delivery with no problems, mother and baby are doing brilliantly (if tired) and daddy and the little man are adjusting well too.

I’m back to work on Wednesday, but I’ve booked off Thursday and Friday for the next few weeks to settle in with everyone, since those are the days that Freddy is home from nursery and I can’t leave mum with both the kids on her own so soon! It’ll be a wonderful short week then!

Tags:

Journal

My thoughts on HTML5 at Microsoft TechDays 2011

by paet the pagan-gerbil 28. May 2011 08:10

I’m beginning to neglect this blog as much as the Year of Frugal Gaming that I also write for (check it out, our glorious leader Frugal Dave recently picked up a stylish blogger award! I’m thrilled to be in such company!) and I’ve written a post over there on what I’ve been up to gaming wise.

I’ve been lucky enough to go to TechDays in London again this year – I’m definitely the ‘community’ guy in our team, seeking out user groups, conferences, blogs and podcasts. I’m of the mind that you need to be plugged into all these things to know what’s available. When all you have is a hammer, everything looks like a nail, as the old saying goes, and I want to have as many different types of hammer as possible. It does come at a slightly bad time, however, as my wife is expecting to drop another baby in just over two weeks (and last night was a sleepless one of false alarms, before a 4:15 alarm in order to head to London for TechDays...) and I’m planning on staying in the capital tonight rather than travel all the way back to Bristol, and return to London again tomorrow. If I get ‘that call’ I’ll have to race for the tube station and get back in time!

Anyway, I’ve already been to the Monday event on ‘The Web’ – a discussion of HTML5, CSS3, IE9 and other sequels. I’m very impressed, but also a little melancholy. What I took away from there is that I can now create great looking sites without having an abundance of <div> elements and interlocking images to create a box with rounded corners, I can just do it in CSS. Except, for almost anything, our designers want their design to appear in every browser. This means that we can’t use the new hotness because it won’t show up in IE8 and below, which still have a considerable market share. We’re only now convincing people to let us build sites that degrade ‘gracefully’ in IE6, since it takes a disproportionate amount of time to make a site look like it should in IE6. Now we’ve got the luxury of saying “That’s a bit too hard, I’m just going to make it square.” We can’t use the same excuses for IE8, which is the default browser for Windows 7 – only a couple of years old.

On a personal site, or if we had trendier clients – the kind who care more about seeming new and cutting edge, with things floating all over the page, the sort of thing that grinds to a halt on a slow PC – there would be plenty of scope for this new technology. But as it stands, HTML5 compliance is low enough that we won’t be able to pick it up just yet.

Microsoft did put on a great show though, getting in experts on CSS and HTML from outside their own company (heck, they had a speaker from Opera – probably because Mozilla or Google turned them down!) and giving a little poke at themselves about IE6. Oh, IE6.

I’m keen to get to use HTML5, but the day job isn’t going to be the place to do that. I’m still working on an intranet app that breaks – actual functionality breaks, not just styles – if it’s not used in IE7 (compatibility mode in 8 and 9 are fine), and our external websites need to look the same across browsers. We can’t just pretend that all IE users are on version 9, that’s not realistic and won’t make customers very happy. It doesn’t matter if it degrades gracefully, the design decisions would be so different in most cases (three <div> tags with separate background images for a repeated news item to give it rounded corners, or one <div> and no images to do it all with fancy CSS3?) that it can’t look ‘correct’ without major javascript hacks which probably involve inserting all the HTML that we were going to in the first place, and still work in the newer HTML 5 browsers. The only difference is that it won’t have such pleasant markup for the developers (or the geeks who view source on websites they visit) to read.

This problem isn’t going to go away – Vista shipped with IE7, so that’s going to be supported for a fair while yet. IE6 shipped with XP, and since XP is still supported until about 2014 at last count. That means that IE6 is still officially supported by Microsoft until 2014. Vista won’t roll off until 2019 (at a guess), and Windows 7 (which contains IE8) will probably be into 2022 or so. For another five years (being optimistic), we have to assume that non-technical people (the majority of those that visit our company‘s sites) will be using the browser they installed with their operating system and never upgrading, and the majority of market share will be held by non-HTML5 compliant browsers. Hopefully, Microsoft will make more websites like www.theie6countdown.com, which tells us when we can officially ditch IE6 country by country. It won’t be long, and we can assume that anyone hitting our sites from IE6 will be Chinese and therefore unlikely to buy our products!

Tags: , ,

Journal | Programming

Learning Unit Testing XI - Difficult Terrain Is Difficult

by paet the pagan-gerbil 21. April 2011 13:15

As the title clearly states, difficult terrain is going to be hard. It will involve a replacement of the ‘get distance’ code that takes into account that strict distances are not the same as movement distances – the idea that four inches of distance may cost five, six or more inches of movement (which is what counts for running, charging, and moving in general).

Because of this difficulty, my current inability to devise a solution, and my need to get moving on other things immediately (time on this project is limited, and I would rather move on than get stuck in design hell that maybe I should have sorted out sooner) I will be abandoning the Movement phase for the infinitely more interesting Shooting phase. It actually looks slightly easier, but I’m sure that’ll be remedied when I get to the rules for weapons and skills.

Unlike movement, which started to bog down the Model class, I’m going to try and keep all shooting related code in the shooting manager. Again, having an inkling of what the skills and weapons rules are going to do later, I believe this will make things a lot easier.

The first thing written down is defining who can shoot – Any model can shoot as long as it’s armed with a missile weapon, is not in hand-to-hand combat, can see a target, didn’t run or charge and is not hiding. This seems like a sensible thing to write a checking method for, and a little raft of tests. Time for a new test class, and also (finally) a test helper.

class TestHelper
{
    public static IGameManager GetMockGameManager(IModel testModel, IObjectManager objectManager, int numberOfEnemies, int numberOfAllies)
    {
        Mock<IGameManager> mockGameManager = new Mock<IGameManager>();

        List<IModel> modelList = new List<IModel>();
        modelList.Add(testModel);

        for (int i = 0; i < numberOfAllies; i++)
        {
            modelList.Add(new Model(testModel.Player, mockGameManager.Object, objectManager));
        }
        for (int i = 0; i < numberOfEnemies; i++)
        {
            modelList.Add(new Model(testModel.Player + 1, mockGameManager.Object, objectManager));
        }
        
        mockGameManager.Setup(item => item.Models).Returns(modelList);

        return mockGameManager.Object;
    }
}
[TestClass]
public class ShootingManagerTests
{
    [TestMethod]
    public void CanShoot_ReturnsTrue_IfEverythingCorrect()
    {
        Model model = new Model(1, null, null);
        model.Weapons.Add(new MissileWeapon());
        TestHelper.GetMockGameManager(model, null, 1, 0);

        model.Location = new LocationPoint(0, 1, 0);
        model.Direction = 180;

        model.IsCharging = false;
        model.IsHiding = false;
        model.IsRunning = false;

        ShootingManager shootingTest = new ShootingManager();

        Assert.IsTrue(shootingTest.CanShoot(model));
    }
}

Right, a lot of ‘generate class’ and ‘generate stub’ later (the ctrl+. shortcut is my friend) and the library compiles again. I intend for all missile weapons (that need special functionality not covered by the basic rules) to inherit from MissileWeapon, which ought to cover the majority of things. Weapons is a list of IWeapon (implemented by MissileWeapon), Direction is just an integer describing the angle the model faces (assuming a top-down view), and ShootingManager is quite an empty class at the moment. Following TDD pretty strictly, to pass this test it becomes:

public class ShootingManager
{
    public bool CanShoot(Model model)
    {
        bool canShoot = true;
        return canShoot;
    }
}

But of course, that’s not quite right. Here’s a few more tests.

[TestMethod]
public void CanShoot_ReturnsFalse_IfRunning()
{
    Model model = new Model(1, null, null);
    model.Weapons.Add(new MissileWeapon());
    TestHelper.GetMockGameManager(model, null, 1, 0);

    model.Location = new LocationPoint(0, 1, 0);
    model.Direction = 180;

    model.IsCharging = false;
    model.IsHiding = false;
    model.IsRunning = true;

    ShootingManager shootingTest = new ShootingManager();

    Assert.IsFalse(shootingTest.CanShoot(model));
}

[TestMethod]
public void CanShoot_ReturnsFalse_IfCharging()
{
    Model model = new Model(1, null, null);
    model.Weapons.Add(new MissileWeapon());
    TestHelper.GetMockGameManager(model, null, 1, 0);

    model.Location = new LocationPoint(0, 1, 0);
    model.Direction = 180;

    model.IsCharging = true;
    model.IsHiding = false;
    model.IsRunning = false;

    ShootingManager shootingTest = new ShootingManager();

    Assert.IsFalse(shootingTest.CanShoot(model));
}

[TestMethod]
public void CanShoot_ReturnsFalse_IfHiding()
{
    Model model = new Model(1, null, null);
    model.Weapons.Add(new MissileWeapon());
    TestHelper.GetMockGameManager(model, null, 1, 0);

    model.Location = new LocationPoint(0, 1, 0);
    model.Direction = 180;

    model.IsCharging = false;
    model.IsHiding = true;
    model.IsRunning = false;

    ShootingManager shootingTest = new ShootingManager();

    Assert.IsFalse(shootingTest.CanShoot(model));
}

And what do all those lines of code need to make them pass?

public bool CanShoot(Model model)
{
    bool canShoot = true;
    if (model.IsRunning == true || model.IsHiding == true || model.IsCharging == true)
    {
        canShoot = false;
    }
    return canShoot;
}

It’s almost insulting. The next one should be a bit more of a challenge:

[TestMethod]
public void CanShoot_ReturnsFalse_IfNoMissileWeapon()
{
    Model model = new Model(1, null, null);
    TestHelper.GetMockGameManager(model, null, 1, 0);

    model.Location = new LocationPoint(0, 1, 0);
    model.Direction = 180;

    model.IsCharging = false;
    model.IsHiding = false;
    model.IsRunning = false;

    ShootingManager shootingTest = new ShootingManager();

    Assert.IsFalse(shootingTest.CanShoot(model));
}
[TestMethod]
public void CanShoot_ReturnsFalse_IfOnlyMeleeWeapons()
{
    Model model = new Model(1, null, null);
    model.Weapons.Add(new MeleeWeapon());
    TestHelper.GetMockGameManager(model, null, 1, 0);

    model.Location = new LocationPoint(0, 1, 0);
    model.Direction = 180;

    model.IsCharging = false;
    model.IsHiding = false;
    model.IsRunning = false;

    ShootingManager shootingTest = new ShootingManager();

    Assert.IsFalse(shootingTest.CanShoot(model));
}

And these are solved by:

public bool CanShoot(Model model)
{
    bool canShoot = true;
    if (model.IsRunning == true || model.IsHiding == true || model.IsCharging == true)
    {
        canShoot = false;
    }

    if (model.Weapons.Where(item => (item as MissileWeapon) != null).Count() == 0)
    {
        canShoot = false;
    }

    return canShoot;
}

Linq makes things a little bit too easy these days... The next test checks if the model can see an opponent:

[TestMethod]
public void CanShoot_ReturnsFalse_IfNoEnemyInSight()
{
    Model model = new Model(1, null, null);
    model.Weapons.Add(new MissileWeapon());
    TestHelper.GetMockGameManager(model, null, 1, 0);

    model.Location = new LocationPoint(0, 1, 0);
    model.Direction = 0;

    model.IsCharging = false;
    model.IsHiding = false;
    model.IsRunning = false;

    ShootingManager shootingTest = new ShootingManager();

    Assert.IsFalse(shootingTest.CanShoot(model));
}

As expected, it fails. The only difference to the original ‘everything is fine’ test case is the direction that the model is facing – a model can only see in a 90 degree arc to it’s front, so by turning it completely around it should be unable to see the enemy properly. The calculations on the abstract ObjectManager should reflect this, so an extra method in ObjectManager that is exposed (slightly) through Model will help out.

First off – a lot of tests break. This is because the models have been set up with null object managers, which obviously throw exceptions when the call to check them for models in sight occurs. In refactoring to get the first test (pass if all clear) passing, references and parameters were shifted from Model to IModel, things were added to IModel,and in general a bit of housekeeping took place. Here is the new ‘all clear’ test:

[TestMethod]
public void CanShoot_ReturnsTrue_IfEverythingCorrect()
{

    IModel model = new Model(0, null, null);
    IGameManager gameManager = TestHelper.GetMockGameManager(model, null, 1, 0);
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    mockObjectManager.Setup(item => item.GetModelsInSight(It.IsAny<IModel>(), gameManager.Models, 90)).Returns(gameManager.Models);
    model = new Model(1, gameManager, mockObjectManager.Object);
    model.Weapons.Add(new MissileWeapon());

    model.Location = new LocationPoint(0, 1, 0);
    model.Direction = 180;

    model.IsCharging = false;
    model.IsHiding = false;
    model.IsRunning = false;

    ShootingManager shootingTest = new ShootingManager();

    Assert.IsTrue(shootingTest.CanShoot(model));
}

With similar ‘setup’ code to the subsequent tests to get them all passing. The improved ‘new’ test:

[TestMethod]
public void CanShoot_ReturnsFalse_IfNoEnemyInSight()
{
    IModel model = new Model(0, null, null);
    IGameManager gameManager = TestHelper.GetMockGameManager(model, null, 1, 0);
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    mockObjectManager.Setup(item => item.GetModelsInSight(It.IsAny<IModel>(), gameManager.Models, 90)).Returns(new List<IModel>());
    model = new Model(1, gameManager, mockObjectManager.Object);
    model.Weapons.Add(new MissileWeapon());

    model.Location = new LocationPoint(0, 1, 0);
    model.Direction = 0;

    model.IsCharging = false;
    model.IsHiding = false;
    model.IsRunning = false;

    ShootingManager shootingTest = new ShootingManager();

    Assert.IsFalse(shootingTest.CanShoot(model));
}

And finally, the code to pass it:

public bool CanShoot(IModel model)
{
    bool canShoot = true;
    if (model.IsRunning == true || model.IsHiding == true || model.IsCharging == true)
    {
        canShoot = false;
    }

    if (model.Weapons.Where(item => (item as MissileWeapon) != null).Count() == 0)
    {
        canShoot = false;
    }

    if ((from target in model.GetModelsInSight(90)
         where target.Player != model.Player
         select target).Count() == 0)
    {
        canShoot = false;
    }

    return canShoot;
}

With one small addition to the Model class:

public List<IModel> GetModelsInSight(int angleOfSight)
{
    List<IModel> modelsInSight = new List<IModel>();
    modelsInSight = _objectManager.GetModelsInSight(this, _gameManager.Models, angleOfSight);
    return modelsInSight;
}

Finally, one more test and the ‘who can shoot’ question is completely answered. Models cannot shoot if they’re already in hand-to-hand combat. A simple boolean property (the exact circumstances of being able to set it will be complicated, but that’s a problem for later) on the Model and IModel, adding it as an explicit ‘false’ parameter in the other CanShoot tests, and it’s own test case:

[TestMethod]
public void CanShoot_ReturnsFalse_IfModelInHandToHandCombat()
{
    IModel model = new Model(0, null, null);
    IGameManager gameManager = TestHelper.GetMockGameManager(model, null, 1, 0);
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    mockObjectManager.Setup(item => item.GetModelsInSight(It.IsAny<IModel>(), gameManager.Models, 90)).Returns(gameManager.Models);
    model = new Model(1, gameManager, mockObjectManager.Object);
    model.Weapons.Add(new MissileWeapon());

    model.Location = new LocationPoint(0, 1, 0);
    model.Direction = 180;

    model.IsCharging = false;
    model.IsHiding = false;
    model.IsRunning = false;
    model.IsInHandToHandCombat = true;

    ShootingManager shootingTest = new ShootingManager();

    Assert.IsFalse(shootingTest.CanShoot(model));
}

And the complete CanShoot code to pass it:

public bool CanShoot(IModel model)
{
    bool canShoot = true;
    if (model.IsRunning == true || model.IsHiding == true || model.IsCharging == true || model.IsInHandToHandCombat == true)
    {
        canShoot = false;
    }

    if (model.Weapons.Where(item => (item as MissileWeapon) != null).Count() == 0)
    {
        canShoot = false;
    }

    if ((from target in model.GetModelsInSight(90)
         where target.Player != model.Player
         select target).Count() == 0)
    {
        canShoot = false;
    }

    return canShoot;
}

And it leaves me at a good point to finish off for this section. The next section will be the Closest Target rules, which I’ve already given some thought to – but my word count here is already over 1500, so it’s probably best to clock off!

Tags: , , ,

Programming

Book Review - Pride and Prejudice and Zombies

by paet the pagan-gerbil 4. April 2011 13:46

Product DetailsI recently finished reading Pride and Prejudice and Zombies by Seth Grahame-Smith and Jane Austen (allegedly), which I’d found brand-new and mint condition in a charity shop for £1.50. That’s definitely worth a punt!

Overall, I found it a good read. I have read the ‘original’, and even seen TV adaptations of it, but to be totally honest that was in school and I’m not even sure there was any work or essay involved in it beyond just going through the motions of reading it as a class, and/or watching the television. I can sum up my total knowledge of it before I read this book as “Many Bennett sisters want to get married, there is a mean guy name Darcy who Elizabeth hates.” Which is probably the ground-state of knowledge, like what everyone knows about Superman, Romeo and Juliet, or Macbeth.

There were parts of And Zombies that made me think they were poking fun at or paying homage to the original in a way that is opaque to outsiders but absolutely obvious to someone familiar with the work. One chapter, which was only a paragraph long, summed up a whole journey as essentially not worth writing about. Does the original book go into lavish detail of the countryside passed and the entire trip’s trivia? I know Tess of the D’Urbervilles was far over the top as a traveller’s almanac, but I honestly can’t remember enough of Pride and Prejudice to say the same.

In some places, I had to scoff and thought it was going a little over the top – Elizabeth ripping out the still beating heart of a ninja in front of a noblewoman, for instance. But it was still entertaining, and as much as the action scenes were exaggerated and a little foolish, I found that I was getting bored and restless if it went too long between them. That’s the only thing that has stopped me from trying to find a cheap/borrowed copy of the original to read, because although my interest has been raised – I want to know how close this version is to the original – the ‘zombie-less’ parts of the book were, at times, a bit of a chore.

The only major criticism I have of the book is that the zombies are mentioned often, but always using one of a small handful of period-consistent terms. When used once, these terms are an interesting look at how zombies may have been seen in that sort of world, but each one is repeated over and over again. One of the least appealing is the word ‘unmentionables’ – since they are called that often, and while some characters talk of nothing else, Mrs Bennett is the only person I can think of off the top of my head that might not have mentioned zombies at all. They are far from unmentionable, people talk about them all the time! And while Mrs Bennett rarely (if ever) talked about zombies, she talked about her daughters fighting abilities – which is itself a direct consequence of the zombie plague.

Zombie references also feel shoe-horned in many places – the best uses are more subtle, like the fact that mail is expected to be delayed, as coaches must be more heavily armed when crossing the countryside, and even then may be attacked and require a better provisioned coach to recover mail and deliver it. The turning of Miss Lucas was most interesting when it was at a distance – the frequency and quality of her letters dropping, Elizabeth wondering when (or if) the next one would arrive, or whether her disease has been discovered and what fate befell her.

Tags: ,

Books and Films

Learning Unit Testing X - Finishing Hiding

by paet the pagan-gerbil 13. March 2011 08:00

Last time, I got the tests for Charging out of the way, and got through a raft of simple checks for Hiding. This time, a few of the more complicated checks.

First off, a model can move around while hiding as long as it remains out of sight. I’m not sure how to be checking every point along the move, but I can check at the end of the movement whether it’s still out of sight.

[TestMethod]
public void Hide_ThrowsExceptionIfInSightAfterMove()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model enemyModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>() { enemyModel });

    Model testModel = new Model(2, mockGameManager.Object, mockObjectManager.Object);
    testModel.Movement = 4;
    bool exceptionThrown = false;
    mockObjectManager.Setup(item => item.GetLineOfSight(It.IsAny<IModel>(), It.IsAny<IModel>())).Returns(0);
    testModel.Hide();
    mockObjectManager.Setup(item => item.GetLineOfSight(It.IsAny<IModel>(), It.IsAny<IModel>())).Returns(1);
    Assert.IsTrue(testModel.IsHiding);
    try
    {
        testModel.MoveModel(4, 0, 0);
    }
    catch (HidingException ex)
    {
        exceptionThrown = true;
        Assert.AreEqual(enemyModel, ex.EnemyModels[0]);
    }

    Assert.IsTrue(exceptionThrown);
    Assert.IsFalse(testModel.IsHiding);
}

The best way to check this is probably to call the Hide method at the end of MoveModel – any change in the model’s visibility will be picked up. Code re-use: excellent!

if (this.IsHiding)
{
    this.Hide();
}

But I still don’t get a pass... I also need to set IsHiding to false in the Hide method, when it throws an exception. Then the test goes green.

The next test is that after an enemy model has moved, it might force a model to stop being hidden. I will keep the current action of throwing an exception – this will let the imaginary UI show that hiding has ceased.

[TestMethod]
public void Hide_StopsHidingIfInSightAfterEnemyMove()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model enemyModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>() { enemyModel });

    Model testModel = new Model(2, mockGameManager.Object, mockObjectManager.Object);
    enemyModel.Movement = 4;
    bool exceptionThrown = false;
    mockObjectManager.Setup(item => item.GetLineOfSight(It.IsAny<IModel>(), It.IsAny<IModel>())).Returns(0);
    testModel.Hide();
    mockObjectManager.Setup(item => item.GetLineOfSight(It.IsAny<IModel>(), It.IsAny<IModel>())).Returns(1);
    Assert.IsTrue(testModel.IsHiding);
    try
    {
        enemyModel.MoveModel(4, 0, 0);
    }
    catch (HidingException ex)
    {
        exceptionThrown = true;
        Assert.AreEqual(enemyModel, ex.EnemyModels[0]);
    }

    Assert.IsTrue(exceptionThrown);
    Assert.IsFalse(testModel.IsHiding);
}

The code to pass this test should be just adding the following check to the end of MoveModel (as long as Hide is added to the IModel interface).

foreach (IModel enemyModel in (from models in _gameManager.Models
                               where models.Player != this.Player
                               select models))
{
    enemyModel.Hide();
}

But this doesn’t work – not only does it not work, but it breaks other tests! Now, Charge_SetsIsChargingFlag, MoveModel_CannotMoveFurtherThanModelsMovement and NewTurn_SetsIsChargingToFalse throw exceptions and this test fails on the penultimate assert that the exception was thrown. I believe the error with this test is that the Mock GameManager I’m using is only returning the enemyModel – not the testModel. When I added the testModel to the setup, this test at least passes. The other tests all throw exceptions. This is probably due to the fact that the GameManager is not being correctly set up in each case, to return an empty List<IModel> – as a mock object, it returns null instead and the above code to check for other models fails when passed a null.

By adding in the required setup line to each of those tests, I get 31 passes again.

Finally, a model is automatically forced out of hiding if an enemy model is within it’s Initiative range of the hiding model. This one needs to be checked when the model chooses to hide, and also whenever it moves or the enemy model moves. Since all three of these cause the Hide method to be called, that should probably be where it sits. The following tests should cover off those three situations:

[TestMethod]
public void Hide_CannotHideIfEnemyInInitiativeRange()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model testModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    Model enemyModel = new Model(2, mockGameManager.Object, mockObjectManager.Object);
    mockObjectManager.Setup(item => item.GetLineOfSight(It.IsAny<IModel>(), It.IsAny<IModel>())).Returns(0);

    testModel.Location = new LocationPoint(0, 0, 0);
    enemyModel.Location = new LocationPoint(1, 0, 0);
    enemyModel.Initiative = 2;

    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>() { enemyModel, testModel });

    bool correctExceptionThrown = false;
    try
    {
        testModel.Hide();
    }
    catch (HidingException ex)
    {
        correctExceptionThrown = true;
        Assert.AreEqual(enemyModel, ex.EnemyModels[0]);
    }

    Assert.IsFalse(testModel.IsHiding);
    Assert.IsTrue(correctExceptionThrown);
}

[TestMethod]
public void MoveModel_StopHidingIfModelMovesIntoEnemyInitiativeRange()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model testModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    Model enemyModel = new Model(2, mockGameManager.Object, mockObjectManager.Object);
    mockObjectManager.Setup(item => item.GetLineOfSight(It.IsAny<IModel>(), It.IsAny<IModel>())).Returns(0);

    testModel.Location = new LocationPoint(0, 0, 0);
    enemyModel.Location = new LocationPoint(5, 0, 0);
    enemyModel.Initiative = 3;

    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>() { enemyModel, testModel });

    testModel.IsHiding = true;
    testModel.Movement = 4;

    bool correctExceptionThrown = false;
    try
    {
        testModel.MoveModel(4, 0, 0);
    }
    catch (HidingException ex)
    {
        correctExceptionThrown = true;
        Assert.AreEqual(enemyModel, ex.EnemyModels[0]);
    }

    Assert.IsFalse(testModel.IsHiding);
    Assert.IsTrue(correctExceptionThrown);
}

[TestMethod]
public void MoveModel_StopHidingIfEnemyMovesWithinInitiativeRange()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model testModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    Model enemyModel = new Model(2, mockGameManager.Object, mockObjectManager.Object);
    mockObjectManager.Setup(item => item.GetLineOfSight(It.IsAny<IModel>(), It.IsAny<IModel>())).Returns(0);

    testModel.Location = new LocationPoint(5, 0, 0);
    enemyModel.Location = new LocationPoint(0, 0, 0);
    enemyModel.Initiative = 3;

    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>() { enemyModel, testModel });

    testModel.IsHiding = true;
    enemyModel.Movement = 4;

    bool correctExceptionThrown = false;
    try
    {
        enemyModel.MoveModel(4, 0, 0);
    }
    catch (HidingException ex)
    {
        correctExceptionThrown = true;
        Assert.AreEqual(enemyModel, ex.EnemyModels[0]);
    }

    Assert.IsFalse(testModel.IsHiding);
    Assert.IsTrue(correctExceptionThrown);
}

The passing code sits in Hide, and is very pleasantly simple. Hide becomes very long:

public void Hide()
{
    if (this.IsCharging || this.IsRunning)
    {
        HidingException ex = new HidingException("Cannot hide if charged or ran this turn.");
        throw ex;
    }
    else
    {
        List<IModel> enemyModels = (from models in this._gameManager.Models
                                    where models.Player != this.Player
                                    && (this._objectManager.GetLineOfSight(models, this) > 0.6 || this.GetDistanceFrom(models.Location.X, models.Location.Y, models.Location.Z) <= models.Initiative)
                                    select models).ToList();
        if (enemyModels.Count > 0)
        {
            this.IsHiding = false;
            HidingException ex = new HidingException("Cannot hide in sight or Initiative range of enemy models.");
            ex.EnemyModels = enemyModels;
            throw ex;
        }
        else
        {
            this.IsHiding = true;
        }
    }
}

But this breaks several other tests. The reason is that some of the previously written tests are not setting locations for the enemy and test models, and the distance between them (zero) is always equal to or less than the default Initiative value (also zero). Changing the tests to give them a bit of space fixes this problem.

Since a model can remain hidden for several successive turns, it doesn’t need to reset the IsHiding flag – Hiding for all hidden models is checked whenever a model is moved, so it will be taken out of hiding when a player wishes or when it is chosen.

Next time, I move off of page 11, but I’m not sure where to yet...

Tags: , , ,

Programming

Forest Dragon Crystal

by paet the pagan-gerbil 6. March 2011 13:29

I got a game of Warhammer in this weekend – the first of the year! To inspire me to paint more, I chose to forego the Dark Elves (many of which remain unpainted) in favour of the Wood Elves (only a couple of special characters unused). The army was planned on the assumption that I’d be fighting Chaos – but there was a surprise twist with my opponent, who decided to bring his Bretonnians instead.

Still, after the initial panic attack, I realised that we had a lot of forests that could be put down and I’d just have to stay out of reach of the nasty nasty lances.

dryad2Terrain was set up pretty much as a straight line down the middle of the table, consisting of a tower, a wall, four forests (after the Wood Elf free forest was placed) and an interesting candle holder that was sat near the scenery shelves, shaped like a dragon holding a crystal. On the agreement that we first remove the candle, we decided that it would make a great centrepiece for the game, and the story went roughly along the lines of ‘Bretonnian lord wants forest dragon crystal to bling up his castle, Wood Elves don’t like people wandering around the forest’. Nothing too major.

Using the forests to funnel the lances into really obvious traps didn’t quite work – they were a bit too obvious. Slowly, over the game, I picked off all the peasants and foot troops but failed to make much of a dent on the knights – including a combined charge from Wardancers, Dryads and Glade Riders. It reinforced my belief that Wood Elves should never, ever engage to the front of a unit. And that I should probably have used the ‘Killing Blow’ dance. Also, angles of possible fleeing should be considered, as my Warhawk Riders drew a combat and automatically fled – though they would have rallied automatically too, they went through a block of peasant halberdiers and were wiped out. They could have quickly reached the other side of the battle (the one with all the knights) and helped with some rear charges to destroy a knight unit or two.

That being said, not too much of the army was destroyed – Wood Elves are very, very good at staying out of the way.

At the final tally, there were only 70 victory points between us (Wood Elves very slightly ahead) for an extremely solid draw. Hopefully we’ll have a rematch at some point, since that Bretonnian lord still wants his bling, and the Elves didn’t do enough to put him off yet – all they did was clear out the riff-raff from his army!

Tags: , , ,

Warhammer

What I Did On My Holidays

by paet the pagan-gerbil 1. March 2011 13:02

I’ve just had one of my regular el-cheapo holidays to visit family. They even bought a new bed for us to sleep on while we were there, since Fred is now in a ‘big boys’ bed.

Most of the week was spent relaxing – we drove past a beach, potty trained the little guy (mostly successful, though still in nappies when we go out or for bed) and visited many friends in the pub. I managed to get started on a new book (Pride and Prejudice and Zombies, by Jane Austen and Seth Grahame-Smith) and an old book (Monstrous Regiment, by Terry Pratchett). I barely thought about work at all.

We even squeezed in a game of Necromunda against my very first opponent and his Redemptionist gang. I took out my Delaques, and realised that the roster is over ten years old. Impressive. Jen took some Eschers. He set up a three-player scenario, where we had to get to the top of a tower before anyone else to win a prize. He and Jen got into early fighting, shooting each other off of walkways and so on. I snuck in through the other side, managing (somehow) to avoid all attacks, until my leader was caught by an executioner one-shot flamer. He caught fire, and luckily ran straight across the walkway and past two guards (one wielding a rather nasty-looking double-handed chainsaw) towards the Redemptionist base. The following turn, a Redemptionist brother reached the top of the tower, while my Delaque Juve was a level below and held up by an Escher heavy... The Redemptionists only had to wait one turn at the top to be the winners. Luckily, my leader doused the flames and ran into the Redemptionist base (undefended, they were all off picking on Eschers) and what had been a forgone conclusion shifted very suddenly – and again, as my Juve finished off the Escher. He was now at least five floors above anyone else, and only one below the top. That’s the first game of Necromunda I’ve won against that opponent – as most of his gangs have an incredibly high rating, I’m always the ‘underdog’. This scenario limited all players to four models at a time, so there was some opportunity to fight fairly there.

With the underdog bonus, and hitting the button, plus a few lucky shots on the way, that Juve managed to pick up 37 experience points (from 0!) and got instant promotion. Awesome.

Unusually for such a long stay away, I didn’t get any painting done. I almost packed some models as I left, but couldn’t get them fixed and protected for the journey in time. I decided to take it easy instead.

I did get a lead on my family tree – my aunt has done a lot of research already, with the things I had been making assumptions about previously. I think she’s gone even further back than I could, and told me that the family had originally come from France (to settle on the Isle of Wight). She’ll dig out what she can find, and I can see how it fits what I’ve discovered. Although it’s not a resolution, I’m still going to be following the family tree this year. I’ll just pick it up as and when I can.

Speaking of family trees, one of the benefits of going away was meeting the two new additions – my cousins have had babies! There are a few more expected this year, which is always fun. We’re expecting to be the last, in June. I think that the new babies are my first cousins once removed, and Freddy’s second cousins. Here’s a diagram, showing the new babies in relation to Freddy. It is restricted down to just my mum’s family, and only as far back as her parents (my grandfather, Freddy’s great-grandfather, is also the new babies great grandfather). These diagrams don’t make things in exactly the easiest format to read, but that’s something I can play around with later.

family-tree-new-babies

Tags: , ,

Journal

Learning Unit Testing IX - Moving On With Movement

by paet the pagan-gerbil 19. February 2011 08:00

Having gotten those knotty problems with world management, distances, directions, etc all out of the way I can finally move off of page 10. So what’s next? Page 11! Hooray!

It begins with a description of a charge move. A charge works like a run, at double-move rate, with the model (hopefully) ending up in contact with an enemy, or with a low wall that is also in contact with the enemy. The movement side of things should be fairly easy, but describing ‘base contact’ might be slightly more difficult.

In the real game, a model’s base is usually a circle 25mm in diameter. This is close enough to one inch to be treated as one of the arbitrary units I’m using for movement and measurement, so a model can be described as having a width of 1. If I choose the location to describe the centre-point of a model’s base, then ‘base contact’ would be a point equal to half the charger’s width plus half the target’s width, to allow for future models that may be bigger or smaller than a normal one (I’m fondly thinking of Ogryns!)

I started skirting around the issue slightly in the last post, but I need to seriously consider scenery and models as things with width and height, more than points on a virtual graph. The scenery will also need a different method of determining base contact, since it won’t often have a circular base.

It’s taking me a while to work out exactly which direction (no pun intended) to go with this. A charge sounds exactly like a regular run move, except you can (and are expected to!) get within 8” of an enemy model without stopping, and it declares that the model “Can do nothing for the rest of the turn.” To that end, I believe that only three new tests are needed, on a ‘charge’ method – one that makes sure a charging model can approach within 8” of an enemy, one that checks that an ‘isCharging’ flag is set so that the model can’t take any more actions this turn, and one that checks that that flag is removed at the beginning of a turn.

The first test – that the model doesn’t stop moving close to an enemy – is almost identical to the one that checks that it does stop moving close to an enemy, but with a different expected final position and no exception thrown.

[TestMethod]
public void Charge_CanGetWithin8InchesOfEnemy()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model enemyModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    enemyModel.Location.X = 9;
    enemyModel.Location.Y = 0;
    enemyModel.Location.Z = 0;
    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>() { enemyModel });

    Model testModel = new Model(2, mockGameManager.Object, mockObjectManager.Object);
    testModel.Movement = 4;
    testModel.Location.X = 0;
    testModel.Location.Y = 0;
    testModel.Location.Z = 0;
    bool exceptionThrown = false;
    try
    {
        mockObjectManager.Setup(item => item.GetDistanceBetween(testModel.Location, It.IsAny<float>(), It.IsAny<float>(), It.IsAny<float>())).Returns(8);
        mockObjectManager.Setup(item => item.GetPointOfIntersection(testModel.Location, It.IsAny<LocationPoint>(), enemyModel.Location, 8)).Returns(new LocationPoint(1, 0, 0));
        mockObjectManager.Setup(item => item.GetLineOfSight(testModel, enemyModel)).Returns(1);
        testModel.Charge(8, 0, 0);
    }
    catch (MovementException ex)
    {
        exceptionThrown = true;
    }

    Assert.IsFalse(exceptionThrown);
    Assert.AreEqual(8, testModel.Location.X);
    Assert.AreEqual(0, testModel.Location.Y);
    Assert.AreEqual(0, testModel.Location.Z);
}

The code to pass this test is extremely simple:

private bool _isCharging = false;

public void Charge(float positionX, float positionY, float positionZ)
{
    _isCharging = true;
    MoveModel(positionX, positionY, positionZ);
}

And a quick change to the ValidateMove method to check if the model is charging before validating the ‘within 8” of an enemy’ rule:

if (this.TotalDistanceMoved + distanceToPoint > this.Movement && _isCharging == false)

I almost feel silly for thinking it would be any harder than that, but then I was originally worrying about the base sizes, low wall restriction, etc, that is all part of ‘being in base contact’ – as far as Movement is concerned, it doesn’t matter if the models are in base contact after a charge, only that a charge was attempted. The next test, then, checks that the flag is set:

[TestMethod]
public void Charge_SetsIsChargingFlag()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model testModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    testModel.Movement = 4;
    testModel.Location.X = 0;
    testModel.Location.Y = 0;
    testModel.Location.Z = 0;

    mockObjectManager.Setup(item => item.GetDistanceBetween(testModel.Location, It.IsAny<float>(), It.IsAny<float>(), It.IsAny<float>())).Returns(8);
    testModel.Charge(8, 0, 0);
    
    Assert.IsTrue(testModel.IsCharging);
}

The code only needed to change the private _isCharging to a public IsCharging property, and again – straight into the pass. To make sure the NewTurn method resets the charging flag:

[TestMethod]
public void NewTurn_SetsIsChargingToFalse()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model testModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    testModel.Movement = 4;
    testModel.Charge(8, 0, 0);
    Assert.IsTrue(testModel.IsCharging);
    testModel.NewTurn();
    Assert.IsFalse(testModel.IsCharging);
}

Code to pass that test is just insultingly simple. At this time, I realised that the IsRunning flag might not have been set back to false at the beginning of a new turn – there’s no test for it, so I’ll add that in now.

[TestMethod]
public void NewTurn_SetsIsRunningToFalse()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>());
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model testModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    testModel.Movement = 4;
    testModel.MoveModel(8, 0, 0);
    Assert.IsTrue(testModel.IsRunning);
    testModel.NewTurn();
    Assert.IsFalse(testModel.IsRunning);
}

And as I predicted – it fails! The passing code should, again, be fairly easy to figure out. So I now have all the basics of charging, without the ‘is in base contact’ checks which will mostly be mathematical functions, and abstracted out without really implementing them (as I decided earlier).

The next challenge is Hiding, then we can move away from page 11 – much faster than getting away from page 10 was, at any rate! As I see it, the following things are necessary to check for hiding:

  • A model can choose to hide if it ends it’s turn in ‘reasonable’ cover
  • A model can move about and stay hidden, as long as it doesn’t leave the ‘reasonable’ cover.
  • A model cannot run or charge and hide in the same turn.
  • If an enemy model moves to a position it can see the hiding model, it ceases to be hidden.
  • A model ceases to be hidden if an enemy is within it’s Initiative value in inches of the model.

I will define ‘reasonable’ cover as being in at least 40% cover – this value could easily be tweaked later. I had decided while brainstorming before that line-of-sight shouldn’t return a boolean value, rather a percentage of the target that is visible. In systems that can determine only ‘visible’ and ‘not visible’, the IObjectManager would obviously return 0 and 1 and nothing in between. More subtle systems would give a range of values, meaning that cover saves (when I get to shooting) will take account of partial cover, heavy cover, etc. The first test then will check line of sight from every enemy, to make sure that it is not more than 60% visible to any of them.

[TestMethod]
public void Hide_SetsFlagIfInReasonableCover()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model enemyModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>() { enemyModel });

    Model testModel = new Model(2, mockGameManager.Object, mockObjectManager.Object);
    bool exceptionThrown = false;
    try
    {
        mockObjectManager.Setup(item => item.GetLineOfSight(It.IsAny<IModel>(), It.IsAny<IModel>())).Returns(0.5f);
        testModel.Hide();
    }
    catch (HidingException ex)
    {
        exceptionThrown = true;
    }

    Assert.IsFalse(exceptionThrown);
Assert.IsTrue(testModel.IsHiding); }

Code to pass this test:

public void Hide()
{
    List<IModel> enemyModels = (from models in this._gameManager.Models
                                where models.Player != this.Player
                                && this._objectManager.GetLineOfSight(models, this) > 0.6
                                select models).ToList();
    if (enemyModels.Count > 0)
    {
        HidingException ex = new HidingException();
        ex.EnemyModels = enemyModels;
        throw ex;
    }
    else
    {
        this.IsHiding = true;
    }
}

Using some lovely LINQy goodness! The next test:

[TestMethod]
public void Hide_ThrowsExceptionIfInSight()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    Model enemyModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>() { enemyModel });

    Model testModel = new Model(2, mockGameManager.Object, mockObjectManager.Object);
    bool exceptionThrown = false;
    try
    {
        mockObjectManager.Setup(item => item.GetLineOfSight(It.IsAny<IModel>(), It.IsAny<IModel>())).Returns(1);
        testModel.Hide();
    }
    catch (HidingException ex)
    {
        exceptionThrown = true;
        Assert.AreEqual(enemyModel, ex.EnemyModels[0]);
    }

    Assert.IsTrue(exceptionThrown);
}

Needs no modification. Maybe I went a bit too far with the code writing, since I knew what the test would be in advance? I played with the figures to make sure that the test fails when it should.

The following tests should prevent the Hiding flag staying set when running or charging:

[TestMethod]
public void Hide_RemoveHidingFlagWhenRunning()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>());

    Model testModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    testModel.IsHiding = true;
    testModel.Movement = 4;
    testModel.MoveModel(6, 0, 0);

    Assert.IsFalse(testModel.IsHiding);
}

[TestMethod]
public void Hide_RemoveHidingFlagWhenCharging()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>());

    Model testModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    testModel.IsHiding = true;
    testModel.Movement = 4;
    testModel.Charge(6, 0, 0);

    Assert.IsFalse(testModel.IsHiding);
}

The code for both these tests is simple – change MoveModel and Charge to look like:

public void MoveModel(float positionX, float positionY, float positionZ)
{
    try
    {
        ValidateMove(ref positionX, ref positionY, ref positionZ);
    }
    catch (Exception ex)
    {
        throw;
    }
    finally
    {
        this.TotalDistanceMoved += GetDistanceFrom(positionX, positionY, positionZ);
        this.Location.X = positionX;
        this.Location.Y = positionY;
        this.Location.Z = positionZ;
        if (this.TotalDistanceMoved > this.Movement)
        {
            this.IsHiding = false;
            this.IsRunning = true;
        }
    }
}

public void Charge(float positionX, float positionY, float positionZ)
{
    IsHiding = false;
    IsCharging = true;
    MoveModel(positionX, positionY, positionZ);
}

The next two tests check that a model can’t hide if it charged or ran this turn:

[TestMethod]
public void Hide_CannotHideIfRanInSameTurn()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>());

    Model testModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    testModel.IsRunning = true;
    bool correctExceptionThrown = false;
    try
    {
        testModel.Hide();
    }
    catch (HidingException ex)
    {
        correctExceptionThrown = true;
    }

    Assert.IsFalse(testModel.IsHiding);
    Assert.IsTrue(correctExceptionThrown);
}

[TestMethod]
public void Hide_CannotHideIfChargedInSameTurn()
{
    Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
    Mock<IObjectManager> mockObjectManager = new Mock<IObjectManager>();
    mockGameManager.Setup(item => item.Models).Returns(new List<IModel>());

    Model testModel = new Model(1, mockGameManager.Object, mockObjectManager.Object);
    testModel.IsCharging = true;
    bool correctExceptionThrown = false;
    try
    {
        testModel.Hide();
    }
    catch (HidingException ex)
    {
        correctExceptionThrown = true;
    }

    Assert.IsFalse(testModel.IsHiding);
    Assert.IsTrue(correctExceptionThrown);
}

I’m really liking how simple these tests are to pass at the moment. The code to solve both of those tests goes at the top of the Hide method, and is just a quick check:

if (this.IsCharging || this.IsRunning)
{
    HidingException ex = new HidingException("Cannot hide if charged or ran this turn.");
    throw ex;
}

This is getting a bit too long (I’m thinking that 2000 words, including code, should be a maximum limit on these). I’ll continue more Hiding tests next time!

Tags: , , ,

Programming

Resolutions for 2011

by paet the pagan-gerbil 12. February 2011 11:26

Wow, 2011. When did that happen? Probably sometime around the end of December, it’s usually that time of year.

With Christmas all wrapped up (ahaha), I can turn to the new year, and think about my resolutions. I was pleased with the progress last year even though I did slow down a bit in the summer. The clear lesson was to have a plan – a definite method of attack, and some measure of progress.

I’m picking some of the ‘traditional’ resolutions that I hear about every year – get fit, save money, etc. But I intend to keep at it for longer than a month, and with some hard work, longer than six months too! I’ve had a few weeks trying out what I think I can do, and I’m ready to announce these plans in full.

This year, I aim to improve myself a bit. I’ve kept myself healthy this year, but I could do better. My first resolution then: to go swimming every week. I’ve identified a local swimming pool, and we can take Freddy at the weekend. He likes swimming, and splashing, and will enjoy it. It will require some assistance (it’s the wife’s turn to drive at the weekends), but if I aim to go every week, even if I fail one week there should be enough to have raised my general fitness by the end of the year. I might keep a record of how many lengths I do, and see if it rises appreciably over the year.

I failed my resolution to paint all my Dark Elves last year. That was because there was no plan. The new plan is to do at least forty-five minutes of painting a week. I can probably get that in pieces on weekday evenings, or catch up at the weekend while Freddy has a nap. Why forty-five minutes? Because I can stick something on the DVD player (a Babylon 5 commentary, an iPlayer episode of something) and have the background noise I need when painting. Since this is a target like the ‘filing’ one last year, I can do the same as I did then and catch up if I fail one week. This should (hopefully) get the Dark Elves finished, and maybe even some of the scenery.

Last year, a number of big expenses got in the way of saving – we needed to replace the cooker, buy a car and get it insured. This all added up to quite a nasty sum, and on examination, I ended with no more in savings than I started the year with. I’ve not got a specific plan in place on how to save money, other than not to spend it, but my goals are to put away an as-yet-undetermined amount each month. My ultimate aim is to have at least increased my savings slightly, and overpaid an extra month on the mortgage. I calculated the other day that at the start of this year, there’s only around 343 months left to pay on it. If I manage to knock that down slightly – then terrific!

An easy one now – I’ve realised that I very, very rarely put pictures on here. Some of them were even only Flickr/Google Image searches, and I didn’t even do that one as often as I could/should have. I can put pictures of Fred on when I talk about him, or of models when I talk about them (the only one I have actually done!).

Finally, a triple-whammy resolution – do more of the Frugal Gaming thing. Play more, spend less, and blog about games. I will try to play a major game once a month, unless I hold a games night – of which I will attempt to organise more. I only managed a couple last year, which just wasn’t as many as I wanted. I’ll also be imposing a £5 monthly limit on games – computer games, wargames, etc. It should be reasonably easy to keep this one in control, there’s only a few things I’m interested in and I recently joined an RPG group which aims to meet weekly – and RPGs are notoriously cheap! As the final part of this one, I’ll be aiming to blog on A Year of Frugal Gaming at least once a month too. I feel I let them down a bit last year, so I’ll be trying harder to waste people’s blog-reading time with games reviews, games night tips, and any frugal gaming tips I can find.

In summary then:

  1. Go swimming once a week
  2. Paint for forty-five minutes a week
  3. Save money, overpay at least a month on the mortgage
  4. More pictures on this blog!
  5. Spend no more than £5 a month on games
  6. More games and games nights.
  7. Blog on A Year of Frugal Gaming once a month

This seems to me to be a good range of things, easy goals and milestones along the way to hit, and I should be able to get a feel for whether or not I’m getting anywhere with them.

Tags:

Journal

Powered by BlogEngine.NET 1.6.0.0
Theme by Pete Fullergreen, based on one by Mads Kristensen

Shop at Amazon.co.uk