I was playing the game (which for me is actually somewhat rare - I spend more time flicking through code than I do actually playing Arduboy games) and I spotted a bug, which I’ve since identified in the code.
When you release a mon, the code that’s supposed to shift the monsters down in the party has a bug where it tries to read outside the party array,
so instead of releasing the mon it copies some unrelated data into the array,
which gives the player a random mon.
Edit:
It’s not entirely random, it’s controllable…
If you make sure that the mon you release is the second mon in the party then you end up getting a copy of the mon you last fought.
So actually this is one of those bugs that can be abused.
If you want a particular mon, you just spam the dojo until it turns up and then release your mon.
Worse yet, that means the code is also zeroing out some unrelated data.
(I think it’s either player
or enemy
that gets zeroed out, but technically reading outside the array is ‘undefined behaviour’ so that’s not guaranteed behaviour on other computers/game systems.)
The problem is here:
It can be fixed by doing:
if ((monpals.mons[menuCursor][0] == 0) && (monpals.mons[menuCursor + 1][0] > 16) && (menuCursor <= 2))
{
// Move the monpals down, one by one
for (uint8_t i = menuCursor; i < 2; ++i)
{
// Create a local copy of the next monpal
uint8_t next0 = monpals.mons[i + 1][0];
uint8_t next1 = monpals.mons[i + 1][1];
// If the next monpal isn't empty
if(next0 != 0)
{
// The next monpal is copied into the current monpal's slot
monpals.mons[i][0] = next0;
monpals.mons[i][1] = next1;
}
// Otherwise, if the next monpal is empty
else
{
// Erase the current monpal because it's the last one
monpals.mons[i][0] = 0;
monpals.mons[i][1] = 0;
}
}
}
Hopefully that makes sense to you. If not I can explain it in more detail.
I think the best way to understand it is to work it out on paper,
following the algorithm.
There’s a few other ways to do this, some of which are easier to understand (like swapping the monpals),
but most other approaches use more resources (e.g. procecssing time).
I would have suggested this as a PR, but your code doesn’t have a licence so technically I don’t have permission to modify it.
And by the way, just since I noticed it…
The only times you have to put a semicolon after an end curcly brace are:
- When defining a
struct
,class
,enum
,enum class
orunion
- When using curly braces for initialisation
- E.g. initialising an array, or initialising an object with ‘uniform initialisation’ syntax
- Lambda expressions.
(There might be some obscure cases I’m forgetting about, but that’s all I can think of offhand.)
If there are some of those you don’t know the meaning of, don’t worry too much.
If you don’t know what they are then you’re unlikely to encounter them when writing your own code.
Conversely you do not need a semicolon for:
- Function definitions
-
for
orwhile
loops -
if
orelse
statements - Scope blocks
- Probably any other time you might need to use a curly brace