Need Help with Issue with Code

I’m trying to create a switch within a function that illustrates to the player what pawns it can and can’t attack that are one square away from their currently selected pawn (excluding diagonals). If it detects that the neighboring pawn is next to one of the player’s currently selected pawns, and there is no other pawn behind it, then the neighboring pawn will flash to indicate that it’s a potential target. I haven’t programmed it yet to tell the difference between the player pawns and the enemy ones, but otherwise should still work fine. Right now, I just have the “UP” portion of it coded in, but not only is it not acting as I intended, but it’s causing some of the pawns to draw in the wrong location, which shouldn’t even be possible given that I didn’t right the switch to alter the X and Y positions of the pawns. The problematic code is under line 94, under boutscreen.

Here’s the Github

Any help would be much appreciated :grinning:

I’ve had a brief look.

So far one thing that stands out is this:

Over here you’re indexing pawnBoardLocation with X instead of Y, whereas later on you index it with Y:

But more importantly, 112 / 16 = 7, and your board is 4 x 4, so coordinate 7,3 would actually lie outside of the array. I.e. this is a buffer overflow bug.

Sure enough, changing the code to:

if (i < 4)
{
  pawnXPosition[i] = 64;
  pawnYPosition[i] = i * 16;
  pawnDirection[i] = right;
  pawnBoardLocation[i][0] = i;
} 
else
{
  pawnXPosition[i] = 112;
  pawnYPosition[i] = (i - 4) * 16;
  pawnDirection[i] = left;
  pawnBoardLocation[i - 4][3] = i;
}

Fixes the problem. (I’m presuming this is actually what you meant to write?)

I’m not entirely sure why the problem manifests in the way it does. Normally I would have thought it was due to data being overwritten, but some other symptoms lead me to believe that the compiler is actually performing some weird optimisations as a reaction to the invalid array accesses (which are classed as undefined behaviour, which means the compiler is allowed to do anything it likes, including making demons fly out of your nose!).


By the way, you might want to consider learning about structs so you only have to deal with a single array of structures instead of half a dozen different arrays. Then you could do things like paws[index].x and pawns[index].direction, and even pawns[index] = { /* all the details */ }; or pawns[a] = pawns[b];.

1 Like

So far it looks like an interesting game.

1 Like

Thank you once again :smiley: It definitely fixed the that weird undefined behavior, but it now there’s this issue where the only pawns that flash are the ones located on the second row, regardless of which pawn you’ve selected.

The soon-to-be battle system is somewhat inspired by Octopawn, which is a variation of Hexapawn. If I have enough space afterwards, I hope to make an Oregon Trail inspired overworld, where you would have to walk dozens of kilometers, fighting other trainers, resting at inns, and eventually confronting the corrupt emperor.

Just some simple concept art I have sitting on my phone of what I want to ideally create

3 Likes

Have you made any changes other than the one I specified?

With just the changes I mentioned, there doesn’t seem to be any bug like that:

Creapawn.ino.hex (35.6 KB)

(I can make a PR if you want.)

The same bug seems to be present in that one as well. If you press the A button on any of the pawns, only the ones on the second row will flash, even if the specific pawn you selected isn’t one square down from it, or it can even be the same pawn as you selected as long as its on the second row. I’m also not refering to the flash that occurs when you’re about to select a pawn, but the slightly faster flashing after pressing A on one of them. I apologize if I didn’t explain my self very well earlier. My explanations are usually always long-winded or too brief😅

I uploaded a short vid on Youtube just now that shows the bug I’m talking about

Oh, I see.

That’ll be a result of if ((pawnBoardLocation[(pawnYPosition[i] / 16) - 1][(pawnXPosition[i] - 64) / 16] < 8) & ((pawnBoardLocation[(pawnYPosition[i] / 16) - 2][(pawnXPosition[i] - 64) / 16] == 8) || (pawnYPosition[i] == 16)) & (pawnYPosition[i] > 0)).

I’m quite confused about what that condition is actually supposed to mean. I’ve pieced together enough that it’s supposed to skip drawing some of the sprites for a frame, but I’m not sure what it’s actually checking.

(I think this is also likely to have a buffer overrun bug, because if pawnYPosition[i] / 16 ever evaluates to 0, the - 1 will produce a value of -1, which will be outside the bounds of the array.)

If I had a better idea of what it’s supposed to be doing I could probably offer a solution.

If the intent is for the selected ‘pawn’ to flash, I should point out that you aren’t actually using selectedPawn here, you’re using i (which is being looped through from 0 to 7), which means that this code behaves the same regardless of which pawn is selected.


By the way, you should be using && for conditions, not &.

&& is ‘short circuited’, which means that if the left hand side is false then the right hand side won’t be evaluated, whereas & forces both sides to be evaluated, which wastes CPU time.

1 Like

I frankly completely missed the fact that I wrote ‘[i]’ in that if statement rather than ‘[selectedPawn]’. If it had been a snake staring me down, I’d be a goner :sweat_smile:

I knew about the possibility of the -1 possibly being a problem, which is why I add '|| (pawnYPosition[i] == 16)) & (pawnYPosition[i] > 0)) but I wrongfully assumed that it would loop around to another end of the array rather than just going outside of it. similar to how subtracting 1 from a variable intinialized using ‘uint8_t’ would just loop back to 255.

Also, just to make things simpler, should all following messages go to the private chat?

1 Like

If making programming mistakes was as fatal as most snake bites, there wouldn’t be any programmers in the first place, they’d have all died before any software could be written.

Bugs and mistakes are just par for the course. Making mistakes is how you learn to not repeat those mistakes (or at least how to make fewer mistakes).

That wouldn’t actually solve it. You’d have been better off doing something like:

int16_t y = (pawnYPosition[i] / 16);
int16_t x = ((pawnXPosition[i] - 64) / 16);

if ((y > 1) && pawnBoardLocation[y - 1][x] < 8 && /* et cetera*/)

Because if the y > 1 check failed the && would prevent the rest of the expression being evaluated, so the CPU would never attempt to read outside the array.

That happens in some languages, particularly ones that have a concept of ‘slices’, but not in C++.

C++ is more low level and focused on producing small and fast code, so it avoids doing extra work unless you specifically tell it to. It’s also designed to allow you to build any constructs you need rather than having them built in - that gives it flexibility at the cost of requiring a bit of extra work.

E.g. if you wanted to, you could create a custom Array class that would accept negative indices providing the behaviour you were expecting. (I’d demonstrate, but the code probably wouldn’t make much sense because it would rely on quite a lot of stuff you likely haven’t learnt about yet.)

Desktop C++ actually has a std::array class with a special at function that actually creates a program-stopping error if an index is outside the bounds of the array, so instead of having a silent bug, the program actually immediately stops and tells you what’s wrong.

That’s actually quite a different process.

A uint8_t value of 0 loops around to 255 when 1 is subtracted simply because uint8_t can only represent values from 0 (0000 0000 in binary) to 255 (1111 1111 in binary). If you used a uint16_t instead, it would loop around to 65535. That’s just a basic property of how the numbers are represented: ‘n’ binary digits can only represent 2n values

A decimal equivalent would be a ‘trip meter’ odometer:

Arrays work a bit differently. Explaining them properly would require explaining how memory addresses work, but the basic idea is that the array spans a certain amount of memory and any attempt to index beyond either end of the array, e.g. through using negative numbers or numbers that are equal to or greater than the size of the array (< 0 and >= size(array)), will just end up acessing memory outside the array.

To give a real world analogy: imagine a plate upon which you want to place some food, it has clearly defined edges and if you don’t get the food within the edges of the plate then it ends up on the worktop, or possibly even the floor. (If you want a cruder analogy, imagine a toilet…)

It’s probably better to at least keep my other suggestions to the PM in case nobody wants to hear prattle on about enums again, but I’m not always available so if you run into a bug or issue you might want to just ask it publicly and let anyone answer. Ultimately it’s up to you, I don’t mind either way.


Useless trivia: in the country I live in there are only three native snake species and only one of them is venomous. The last time anyone was killed by one was 1975. Hence I’m more likely to be trampled by cows than killed by snakes.

1 Like

Thank you, I will implement the suggested changes as soon as I get to my computer and update you on any other issues. Also apreciate the explaination on arrays as well

I’ve seen a decent amount of snakes where I live, both non-poisonous and poisonous, though I more commonly see squirrels, chipmunks, foxes, Woodchucks, rabbits, mule deers, and black bears here and there, but I have yet to see any cattle outside of the neighboring ranches where I live. So there’s just cattle wondering about around where you live?

1 Like

Technically ‘poisonous’ only means the snake would poison you if you decided to eat it. It’s ‘venomous’ that means a bite from the snake would poison you (or more accurately ‘envenomate’ you). I wouldn’t be surprised if there are poisonous snakes though.

Not wild, but wandering around fields that are easily accessible to ramblers, dog walkers and other pedestrians. On average there’s about 1 or 2 cow-related deaths per year (not counting farmers/farm hands).

I’ve never seen a wild snake (though they undoubtedly exist), but I’ve certainly met a few cows (and been licked by one).

Definitely no chipmunks, woodchucks or bears though (unless you count rugby teams).

1 Like