Procrastination is a friend of mine

So, instead of working on Rogue Code, I have been thinking about Don’t look back. I even started mocking the app up using Pencil Project. Here is a screen dump of the log-in page, first draft.

Log in page

I will post more screens tomorrow, if I have time. And yes, I did run today. Thank you for asking! 3 KM on the streets in the dappled evening light, weaving between cherry blossoms and  pizza delivery vans. It was a good day.

Don’t look back!

 

dontlookback

So, I ran today (2.5 KM). And, as I ran, I started thinking about a simple little game that might make me run more. You start this game a short distance away from a horde of brain hungry zombies. These zombies are walking (well, shambling) towards you. It does not matter where you go, or what you do, the zombies keep on shuffling towards you. Their pace is pretty random, and often quite slow, but it is inexorable.  If the zombies catch up with you, you die. Your only hope is to run, and keep on running. Just don’t look back.

How does the game actually work? Here is how I imagine it:

  • DLB is a web application.
  • A user creates an account, adding a few basic details (user name, email address etc.)
  • Then the user needs to configure the daily movement of the zombie pack.
  • To do this, the user types in the minimum shambling distance a zombie pack can move in one day (e.g. 1 KM) and the maximum shambling distance the pack can move in one day (e.g. 4 KM).
  • When that step is complete, the user is assigned a virtual runner who is placed 10 KM away from a virtual zombie horde. We can use a nice diagram or chart to illustrate the distance between the two parties.
  • At 12:00:01 AM the following day, the zombie horde advances towards the runner. The distance they move forward in kilometres is some random number occurring between the minimum and maximum values set during configuration. For example, with a minimum threshold of 1 KM and a maximum threshold of 4 KM, the amount the horde travels per day will be 1-4 KM.
  • When the user runs or walks in real life, they log into the web app and enter the distance they have travelled. For example, I ran 2.5 KM today, so I would log into DLB and enter 2.5 KM. My virtual runner would move forward by this amount instantaneously.
  • Every day that a runner is alive, he/she is earning points. The number of points earned per day is equal to minimum shambling distance * maximum shambling distance. For example, with a minimum threshold of 1 KM and a maximum threshold of 4 KM, I would score 4 points per day.
  • If a zombie horde ever catches up with a runner, their game is over. All points are lost.
  • Each week, a user must increase either their minimum shambling distance or maximum shambling distance by 1 KM. This makes eventual capture by the zombies very likely.
  • So, there is a ‘push your luck’ element to the game. It’s about knowing when you are about to get caught by the zombies, and ‘cashing out’ before it happens. When you cash out, you get to keep your points.

More on this idea soon.

I have facets!

So, this is an OT post and will be tagged accordingly, but I wanted to talk a little bit about running. I have, at various times in the last 10 years, flirted with the idea of becoming a runner. I have done a few Parkruns. I have entered a few middle distance road races. I even ran some of them (entering a race is much easier than actually training for it). I was briefly a member of a running club, and I ran around the streets with other crazy, dayglo people. I bought decent shoes. I tried out various headphones, playlists, routes, tracking software, watches. I did long runs, fartlek (yes, I know it is a funny word), interval training, cross training. I had physio for sore knees. I have my gait scrutinised by tooth sucking coaches. I got a little better at it, then, inevitably, I gave up.

And this is the unpleasant truth about me. I am, at heart, a dabbler. I try things on for size. I get really excited about them, I bore my friends and family with them, I read blogs and watch instructional videos, I engage. Then, at some unspecified point, I am distracted. My head is turned. And I move on.

I was thinking about this recently. I was in a church in Cracow, listening to a classical concert performed by a 5 piece ensemble. The lead violinist was superb, actually flawless. The last piece they played was ‘Winter’, by Vivaldi. The fancy name is Concerto No.4 in F-Minor RV 297. There is a really tricky bit towards the end of the third movement which is so fast, almost helter-skelter. And she nailed it! Every single note! It could not have been more precise!  And I thought about all the practice and dedication and sacrifice that she must have offered up to that moment. And I felt ashamed that I had no equal of it in my life.

I am not going to start learning the violin. I know that is beyond me. It’s not about that. I just want to nurture some sort of disciple in my life. Start something that runs to completion. Stick at something. The way I see it, my natural inclinations point me towards two things – writing code and running. Well, I write code every day at work, and I have an ongoing project in that area which helps me move forward. So, I think I should launch a running project that helps me in the same way. I came up with an idea for this on the way home from Poland. It is a very simple running game called ‘don’t look back!‘. More details to follow.  By the way, I ran 2 KM today, and it felt like progress.

 

Trapped in the amber of the moment

Rooms have traps. We have established that. All well and good. But trap-layers do not sprinkle their work around willy-nilly. A seasoned engineer would place his camouflaged pits, poison needle traps and swinging blocks close to the obvious points of interest, namely (a) the treasure and (b) the way out.

http://theadventurerstomb.blogspot.co.uk/2013/04/t-is-for-trap.html
http://theadventurerstomb.blogspot.co.uk/2013/04/t-is-for-trap.html

 

 

 

 

 

So far, when creating a room, we have allocated the trap (or traps) to random tiles.  From now on, the closer a tile is to a treasure tile or an exit tile, the more likely it is to be trapped. Here. This diagram should clear things up.

trap-probability

 

 

 

 

 

 

 

 

 

 

In the digram above, the probability of a tile being trapped is shown using colour. The treasure tile and the exit tile have a high chance of being trapped. The probability of a tile being trapped decreases the further you get away from these two ‘hot areas’.

How does this affect the trap placement algorithm? I am glad you asked. If you look at the diagram above, you will see that there are 5 different levels of trap likelihood, as follows:

trap-probability-breakdown

 

 

Now, lets attach some numbers to these 5 different levels, like so:

  • Very high: 1 in 5 tiles are trapped (i.e. probability of 0.2)
  • High: 1 in 10 tiles are trapped (i.e. probability of 0.1)
  • Medium: 1 in 20 tiles are trapped (i.e. probability of 0.05)
  • Low: 1 in 40 tiles are trapped (i.e. probability of 0.025)
  • Very Low: 1 in 80 tiles are trapped (i.e. probability of 0.0125)

How do we use these trap likelihood levels? I am glad you asked. Assume we have a room with 100 tiles. If every tile in this room has an equal chance of being trapped, we can do this:

  1. Place the 100 Tile objects in a list.
  2. Generate a random number between 0 and 99.
  3. Select the Tile object whose index matches the random number

When the tiles in the room have an unequal chance of being trapped, we must modify this slightly. We do this by rigging the lottery in favour of the higher likelihood tiles. I will write the code tomorrow, but basically this means I would clone the Tile with a very high likelihood of being trapped, giving it 16 entries in the lottery. Tiles with a high chance would get cloned 8 times, and so on. It will work out, I promise 🙂

Succint description of the game

I am trying to write a pithy description of the game for the player’s guide. This is what I have so far:

  1. Rogue Code is a programming game in which you script the behaviour of an adventurer who is raiding a dungeon.
  2. The dungeon has many rooms. These rooms contain treasure, traps and guards. The adventurer wants to steal the treasure while avoiding the guards and traps.
  3. Your adventurer progresses through the dungeon one room at a time. Each time the adventurer beats a room, the next room is unlocked.
  4. A room always has the same contents (e.g. one guard, one trap, one treasure chest) but the location of those contents changes each time the room is created.
  5. You prepare a rogue for a dungeon raid by writing code. Starting with a basic template, you will customise various aspects of the adventurer’s behaviour.
  6. Once your rogue is complete, you can release him into the first room. Thereafter, the action is turn based. In his turn, the adventurer moves, fights and steals, according to the instructions in your programming. Then the environment reacts (e.g. a trap detonates, a guard moves to attack etc.)
  7. Turn based action continues until the rogue has stolen the treasure and exited the room (thereby beating it) or he is dead.
  8. If the rogue beats the room, he is automatically released into the next room.
  9. Step 8 repeats until the rogue dies.
  10. The source code for the rogue cannot be changed after the first room (i.e. no room specific ‘tuning’).
  11. The final score for a rogue is the number of rooms he can beat before he is killed.
  12. The rogue must raid the dungeon multiple times. This mitigates the potential unfairness that randomising room contents could introduce (e.g. you might start your raid right next to an angry guard!).

Let do some theory (pt.2)

That brings us to another game rule. (3) At the start of the game, one or more guards are placed on random tiles in the room. When picking random tiles for the guards, all tiles are legal. The guard (or guards) can be placed on

  1. An edge tile
  2. A non-edge tile
  3. A tile containing the exit door
  4. A tile containing another Guard.
  5. A tile containing treasure.
  6. A tile containing a trap (the guard knows how to avoid it, so it will not trigger)
  7. A tile containing the Rogue!

Our example has just one guard. More guards could be added to increase the difficulty of the room.

Points (4) and (7) uncover an important design decision, namely, that more that one character can inhabit a given tile at a given time. Characters effectively stack. There is no limit to how many of them can be on one tile at a given time. Of course, there are consequences to this sort of proximity (i.e. combat and death). More on this later.

Let’s finish off the set up. (4) At the start of the game, one or more treasures are placed on random tiles in the room. In this context, a random tile is any tile in the room except the tile currently occupied by the Rogue (no free gifts, right?). Accordingly, the treasure must be placed after the rogue has been positioned. Our example has just one treasure tile. More complicated rooms could have lots of treasure.

Finally, we get to traps. (5) At the start of the game, one or more traps are placed on random tiles in the room. In this context, a random tile is any tile in the room except the tile currently occupied by the Rogue. His/her starting tile is assumed to be safe. Therefore, the traps must be placed after the rogue has been positioned. However, traps are more likely to be found near treasure tiles (trap allocation algorithm to follow). Therefore traps must be placed after treasure. Our example has just one trap. More complicated rooms could have multiple traps.

A summary of the room set-up algorithm:

  1. Place exit tile
  2. Place Rogue
  3. Place guard(s)
  4. Place treasure(s)
  5. Place trap(s)

 

 

 

Let’s do some theory

So before I dive in and start writing code, let’s get some theory worked out. Let’s use a simple HTML table to represent the room, with the following notation for fixtures and fittings:

  • R stands for Rogue
  • E stands for exit
  • T stands for trap
  • G stands for guard
  • X stands for trap (x marks the stop right)
 (0,0)
E
T G
X R (5,5) 

So, this is a room containing 36 tiles, set out in a 6 x 6 formation. At the start of the run, the Rogue is positioned at (4, 5). These (x, y) coordinates assume that the top left cell in the table is (0,0), and the cell at the bottom right of the table is (5,5). Game rule 1 – At the start of the game, the Rogue is placed on a random tile on the edge of a room. In the room above, there are only 20 legal start positions for the Rogue. All of the legal tiles match one of these four patterns:

  • (MIN, MIN),(MIN,MIN+1),…(MIN, MAX) (0,0),(0,1),…(0,5)
  • (MIN, MAX),(MIN+1,MAX), … (MAX, MAX) (0,5),(1,5),…(5,5)
  • (MAX,MIN+1), (MAX,MIN+2),…(MAX,MAX-1) (5,1),(5,2),…(5,4)
  • (MIN,MIN+1), (MIN,MIN+2),…(MIN,MAX-1) (0,1),(0,2),…(0,4)

Thus, for any square/rectangular room comprised of h x w tiles, there will be   (2h + 2w)-2 edge tiles which can be used for the Rogue’s start position.

A similar restriction applies to the exit. Game rule 2 – At the start of the game, the exit is positioned on a random tile on the edge of a room. An exit in the middle of a room doesn’t make sense, right?

It lives!

After a little playing around, I decided to stick with C# for the implementation. I want to do this pretty fast, and I don’t want to learn a new language as I go. I have dumped some code into a GitHub repo. It’s very basic. It creates a command line representation of a room (R = Rogue!). More to follow.

tostring

By the way, the Visual Studio extension for GitHub works very nicely. Microsoft are really playing well with others at the moment.

Just trying out Crayon

Just trying out a new code highlighter. It is called Crayon. Pretty impressive, and very easy to use. If you want to know more about the n-Queens program, check out this shizzle.

Premature complexity

Here is another trait of mine I could do without. Whenever I embark on a new project, I have a tenancy to make it really complicated, really quickly. I have a recent example of this. Last night I was sketching out the range of actions a rogue can take each turn. I immediately made it far too complicated. I had three levels of movement (sneak, walk, run) each with a different noise modifier. I had a separate ‘detect traps’ action. I was making it pretty tough for myself. In the end, I simplified things down to the following 5 actions:

  • Sneak – For one action point, a rogue can sneak one tile in any direction. This includes diagonal movement. When sneaking, a rogue has a medium chance of detecting traps.
  • Move – For one action point, a rogue can move two tiles in any direction. This includes diagonal movement. A walk action can combine directions (e.g. up and then left). When walking, a rogue has a low chance of detecting traps
  • Melee attack – For one action point, the rogue can melee attack a guard in the 8 tiles around him. Melee attacks made by the rogue have a high chance of hitting the target. A melee attack that hits will always kill the target.
  • Ranged attack – For one action point, the rogue can attack any guard within 5 tiles (in any direction). Ranged attacks made by the rogue have a variable chance of hitting the target (the further away the target, the lower the chance it will hit). A ranged attack that hits will always kill the target.
  • Steal – For one action point, the rogue can steal any treasure in the 8 tiles around him. There is no limit to the amount of treasure a rogue can carry. The reassure is assumed to be light and portable.

This should be a lot easier to implement. Some of the other stuff I thought about (‘fog of war’ type vision, effect of noise on environment etc.) can be introduced later, when I get the basic stuff working.  It’s a clear case of KISS with maybe some YAGNI thrown in for good measure.

Anyway, the next thing I am going to do is get set up for Python development. I thought it might be a good idea to use Rogue Code as an opportunity to work in another language. So I need to download the latest Python release and a good editor. I have picked PyCharm Community Edition from Jet Brains. They are the guys who make ReSharper and IntelliJ, so they should know what they are doing.