A hero can attack diagonally if they use a certain weapon (eg long sword, staff).  This is simple – it’s just plus or minus one X, plus or minus one Y.  But we also need to account for walls and blocks – which can obstruct a diagonal melee attack.

Walls
Let’s start with walls.  Four sides are relevant when attacking diagonally.  In the case of attacking south-west, the relevant sides are – west, south, west then south, south then west.  Let’s consider the south-west attack visually:

To abstract this concept of “relevant walls” so it applies to each of the four possible diagonal attacks, we can say – xDir, yDir, xDir then yDir, yDir then xDir.  For south-west, the xDir is west and the yDir is south.  Each of these four sides has two possibilities – either the side is a wall or it isn’t.  That’s 2^4 = 16 possible scenarios.  Since that’s a small number, let’s visualize each of them for a south-west attack:

For the sake of discussion, I labeled each with a bit mask (the order is lsb-to-msb xDir, yDir, yDir-then-xDir, xDir-then-yDir).  Since HeroQuest walls are based on pre-defined rooms, some of these never happen on the standard HeroQuest board.  Expansions quests allow rooms to change, but even then I don’t think we ever see any of the one-bit scenarios (0001, 0010, 0100, 1000).  In any case, each of these 16 scenarios can be marked as 1 or 0 (valid or not valid):

 0000: 1 0001: 1 0010: 1 0011: 0 0100: 1 0101: 0 0110: 1 0111: 0 1000: 1 1001: 1 1010: 0 1011: 0 1100: 0 1101: 0 1110: 0 1111: 0

Just for fun, consider the following pattern in the bits.  If there’s zero or one bits, then it’s valid.  If there’s three or four bits, then it’s invalid.  So that just leaves us with the two bit scenarios – (0011, 0101, 1010, 1100) are invalid, (0110, 1001) are valid.

Blocks
What about blocks?  In addition to walls on square sides, we can also have objects that block an entire square.  Blocks by themselves are simple for the case of one-square diagonal attacks.  Here’s a visualization:

If we only had blocks (no walls), then the only invalid attacks are 1xxx (target square is blocked) and 01×1 (diagonal line of sight with two corners).  1xxx never happens in HeroQuest because monsters can not occupy walls.  0111 can’t happen either; the Earth spell Pass through Rock allows a Hero to walk through walls, but the Hero can’t end his/her movement on a wall (or else the hero is trapped forever).  So if we only had blocks (no walls), then the only invalid attack to check for is 0101.

Walls and Blocks
However, we don’t only have blocks – we have both blocks and walls.  If I made a bit mask for the relevant combinations of 4 sides * 4 squares, we’d have 8 bits, which is 256 possible scenarios.  An array with 256 entries is not a lot to store in a lookup table.

An alternate way to look at the problem is this – we can map each relevant block to two relevant walls.  0001 block maps to 1001 walls.  0010 block maps to 0011 walls.  0100 block maps to 0110 walls.  1000 block maps to 1100 walls.  For example, block 1000 + wall 0010 => wall 1110 => invalid.

So far we’ve talked about south-west and about an abstract diagonal attack (with xDir, yDir).  Here’s a visualization of the four possible diagonal attacks.

Diagonal through two falling block traps
0101 blocks is an interesting case – attacking through two diagonal blocks.  It seems obvious that movement should be blocked by 0101 blocks (though in HeroQuest, only orthogonal movements are allowed anyway), but what about attacks?  Depending on the type of block and the type of attack, it might make some intuitive sense to allow the attack.  For example, what if the blockers are a falling block trap (which looks like a hill of rocks) and the attack is a crossbow?  It’s an interesting corner case.  My current opinion is that for simple and consistent rules, it should block the attack.  The HeroQuest falling block trap tile looks like this:

Diagonal Attack HeroQuest Rules
The Instruction Booklet (both American and European) specifically shows example scenarios of diagonal attacks.  This clarifies that diagonal attack through a door is valid and diagonal attack through two heroes is valid.  This is different than our 0101 block scenario because it’s heroes not blocks.  So blocks block differently than (heroes, monsters, furniture) in the 0101 scenario.

Line of Sight
What I’ve discussed in this post is one-square diagonal attacks (or movements, though none of the figures in HeroQuest move diagonally).  This is a special case of a broader problem – it’s line of sight with a distance of one square (horizontal or diagonal).  HeroQuest also has ranged weapons and spells, but I’ll come to that in a later post.

Video
For now, I’ll close with screenshots and a video showing off valid/invalid detection of diagonal attacks.

Some additional features shown in this video are…  Action -> Attack -> sub-menu to select weapon.  This menu references the hero’s weapon(s), and each Hero can have multiple weapons (such as a longsword to attack diagonally).  Damaging a monster adds skulls.  If a monster’s body goes below zero, then the monster dies.  Mouse-over highlights a valid move or attack, left mouse down selects it (you can still move/attack orthogonally with arrow keys).  Orthographic birds eye view.