Ardumon Mockup Image


#102

The only thing I think I prefer is having the dual types just be their own thing like in my example since I didn’t want to use a 2d array. I guess it would depend on the total number of types and dual types though. If there’s 16 base types I see how your method would make more sense since there’s so many combinations it wouldn’t be practical to have 100s of enums. At the same time that would be necessary though assuming there’s only 30 monster, as at most you could only have 30 different combinations of types. Which still is a large amount. More realistically you could assume there would be at least 2 of each type for most cases which could lower that to an estimate of maybe 15-20 different type combinations.

Just as another note, you wouldn’t necessarily need the quad and quarter enums as the effective bonus is only 1, 2, or .5 which is stacked through multiplication. This is strictly cloning the mechanic though, and you have wind resisting electric so that’s clearly not your case in that example.


(Pharap) #103

Dual types don’t affect the need for a 2D array.
The 2D array comes about because you have an attacking type and a defending type.

If DualType wasn’t involved, the only difference would be that this:

uint16_t handleAttack(uint16_t baseValue, Type attackType, DualType defendingType)
{
	const Modifier mod1 = getModifier(attackType, defendingType.getType1());
	baseValue = applyModifier(baseValue, mod1);
	const Modifier mod2 = getModifier(attackType, defendingType.getType2());
	baseValue = applyModifier(baseValue, mod2);
	return baseValue;
}

Becomes this:

uint16_t handleAttack(uint16_t baseValue, Type attackType, Type defendingType)
{
	const Modifier mod = getModifier(attackType, defendingType);
	const uint16_t value = applyModifier(baseValue, mod);
	return value;
}

Your original table had a 4 in it, so I just assumed.

If there were only going to be x1, x2 and x0.5 then yes, that could be reduced.

This is before the main body of optimisation anyway, the small pool of modifiers would allow for more than one modifier per byte so that table could be crushed smaller anyway.

I just picked some random stuff for demonstration purposes.

I changed flying to wind to go closer to the classical elements rather than trying to be an outright clone.


#104

The 4 was for the water/flying dual type, since it would be 2*2, but there’s no stacking in my method so you need the 4. Yours stacks and is also probably a lot closer to the actual funtion in the 'mon games.
Also I forgot the nullifying case now that I think about it that’s just immune -> x0


(Pharap) #105

More importantly the stacking approach doesn’t use as much memory.

One of the golden rules of memory saving is “don’t pre-calculate what you can calculate on the fly”, which is sort of the antithesis to the speed rule of “pre-calculate what’s costly to calculate”.

That’s easily added:

enum class Modifier : uint8_t
{
	Same,
	None,
	Half,
	Double,
	Quarter,
	Quadruple,
};

uint16_t applyModifier(uint16_t value, Modifier modifier)
{
	switch(modifier)
	{
		case Modifier::Same: return value;
		case Modifier::None: return 0;
		case Modifier::Half: return value >> 1;
		case Modifier::Double: return value << 1;
		case Modifier::Quarter: return value >> 2;
		case Modifier::Quadruple: return value << 2;
		default: return value;
	}
}

(Gavin Atkin) #106

I wondered instead of doing skills like in pokemon, there were just three move types like rock, paper, scissors. So depending on what you do versus what they do matters as well as typing. Rock would do bonus damage if they did scissors, but paper would do reduced damage versus scissors. The names should be changed, but that basic idea I think that might be kind of cool and would take less space to implement than skills.

I also really think being able to capture every monster without losing your team would be good for extending play time. The Nuzlock idea could be kept with it still.


#107

When you think about it, type effectiveness is just a bunch of intersecting RPS triangles/ polygons. Would there still be individual types for the monsters in your idea? Or just the move types. The STAB bonus also plays a roll in modifying damage/ strategy. Perhaps only use the monster type for the STAB bonus and then use the two move types for the super effective/ resisted bonus?

Perhaps instead of a monster having a move table of x amount of moves and you can only choose 4 at a time, it would be better if they only had say up to 4 moves total, with them unlocking at certain levels. That way you would only need to store the monsters ID and level in EEPROM. I think that would be a good compromise to still keep some move variety and uniqueness between the monsters.

Say a 3 level evolution path, slug has one move. When it evolves at level 5 to snail it has 2 moves. At level 10 it evolves to iceSnail and has 3 moves. At lvl 15 it learns its 4th move.

Struct move {
  int attackPower;
  type attacktype;
  int levelRequirement;
}
move basicRock = {10, rock, 0}
move superRock = {20, rock, 15)

Also Nuzlock is a self imposed rule set so as long as you have a method of removing monsters from your party the rules could be adapted regardless of what other changes are made.


#108

I’d say it wouldn’t be a bad idea to include nuzlock. It’d make the player more engaged rather than them merely mashing the A button, and it’d give them a sense of urgency and difficulty when in a tough battle, and a high sense of acomplishment or failure, depending whether they won or lost and if they lost any good monsters in the battle. Yeah, they can implement it themselves, but what’s not to say that they won’t go back on their own rules? Those are just my two cents.

also, not to pressure you but, what are you going to name your snail Mon?


(Gavin Atkin) #109

I figured the moves effectiveness could be in addition to typing of the monsters. My only concern would be getting the battle and progression system small enough to fit on the Arduboy, but if you can pull it off that would definitely be ideal :grin:


(fred ) #110

This thread is a really good. It is like a collaborative project taking off. How would something like this be done that way? Just forking off the git hub? A lot of what I do professionally is Project Management. So just curious how it is done from a software development point of view.


#111

Nuzlock is a huge pain to play though, and it definitely requires a better understanding of the game mechanics to complete. The original nuzlock run failed at the champion battle. + the additional rulesets would be costly. The premis is you can add additional restriction through pick and choose depending on how you would like to play. I think that’s best left as self imposed rules.

I don’t really care about the name, how about IceCargo? Your suggestions are all good. My favorite name is the german name for koffing, Smogon.

This is why I suggested relying on separate files. You could split up the over world into different parts to make room for the battle engine. I don’t think progression would be too costly. The original had a couple hooks for progression. HM’s/items, gym badges, and story elements. All three of those tied in together to determine when you got hm’s and when you could use them. So its really just 1 condition to progress if you simplify it.
Stats are seeded from a base seed and then calculated on the fly using the level and and dv/ev/iv modifiers. In this case just level could be used. So progressing the monsters through levels is more about balancing that equation and basestats to feel good than designing a leveling system. All you need is a exp tracking variable, an equation to calculate the stat, and an equation to determine if they hit the level up required exp.

Also no one guessed so the crab is suppose to be a spin off of @filmote’s space invader avatar.


(Gavin Atkin) #112

@Freezingsnail the overworld really doesn’t take much space, splitting up mechanics to different sketches could save space, but at the cost of the player being tied to a computer constantly interrupting gameplay for uploading. The Arduboy is convenient to carry around and play wherever, I don’t think splitting it up would be worth it.

@fredster I don’t know if anyone has officially said if they’ll take on the role of coding it. It will certainly take a talented coder. But once coding starts a GitHub would probably be the way to go as well as something like slack for members to communicate. I might be able to assist with the overworld if development on the game starts.


#113

Good point. Most people would probably be playing casually, now that I think of about it. Yeah, it’s probably for the best self imposed.

I like the name Icecargo. It also can be called Icargo.

I never would of guessed that. :smile:


(Pharap) #114

That would probably be mandatory anyway.

Hrm, I think that might be a bit limiting.
Though Yokai Watch sort of gets away with it, but in that you don’t actually control the monster’s actions exactly and frankly I don’t like their battle mechanics as much as Pokemon.

Storing the moves in EEPROM wouldn’t be too costly, you could either store a move ID, which would probably be 1 byte since there would almost certainly be less than 255 moves, so that’s only 4 bytes per monster, or you could store an index into the monster’s move pool, and if we keep the pools small then that could be squashed into 2 or 3 bytes.

Another possibility is to have some moves essentially function the same but taking on the primary or secondary type of the monster using it, so effectively there’s only one move in memory but it ends up being several moves in practice.

I don’t think nuzlocke should be enforced.
There are plenty of people who don’t like the nuzlocke rules, it’s better to allow people who like them to choose to use them than to enforce them on people who don’t want them.
Some people only play casually and it would be better to allow them to do so.

This is a good point.
I can imagine a game where people spend several days reaching the final battle and then lose all their progress would soon be abandonned by all but the obsessives.

I agree.

It depends how organised the team is.
Sometimes projects done in free time are very haphazard.

Ideally all work is done in github branches or forks and then merged into the main code via PR, but that doesn’t always pan out, especially on smaller teams.

It would be Icecargot to match up with Escargot.
I think people would appreaciate the obviousness of the pun.

I think it would need to be a little bit more than that.
If you couldn’t somehow influence progression then everyone’s monsters would be exactly the same at the same level.
Either that or everything would be oriented on the IVs (if there were any).

I’d rather do away with IVs than EVs since there probably wouldn’t be a breeding mechanic and it would cut out the tedium of trying to get a good set of IVs.

Also remember that base stats don’t have to be saved to EEPROM, they’d probably be defined in the equivalent of the Pokedex, in progmem.

I’ll be frank, I’d have to squint to see the resemblence.

As a crab creature it makes sense, as a variation of @filmote’s space invader it’s a bit of a stretch.

It depends. If we can fit more monsters in by splitting the world up then it may be worth doing, especially if the maps were built in such a way that they last a long time.

In fact, perhaps the maps could be different zones that are playable in any order, and the level of the monsters in the field is tied either to the number of maps the player has cleared or the level of the monsters in their party.

That way people could choose which order to tackle the maps in, making it more interesting for players (kind of like a choose your own adventure thing - you choose the order you clear the maps in) and giving a bit of replayability.


While I think of it, I think we could reduce the stat pool down to just hp, strength, resistance and speed and forgo the physical/special stat split.


#115

I didn’t mean to Imply that. I was thinking of the case of having to store 30 monsters in the pc and 4 values for the moves + the level value. that would be 60-120 bytes for all the stored moves.

That was more of a joke referencing Magcargo.

I don’t think this is the worst compromise since team building is equally as important. iv/dv values are awful. They don’t really make the monsters different, just worse than ones with the max values.

As for that sprite, I didn’t want to copy the alien that much so I only really used the basic shape. The eye stalks are suppose to be the antennae ect. Like I said i’m not the best at sprites. :coffin:

All that’s missing is the special stat when comparing to gen 1. In this scope though I agree special/physical split might not be worth implementing. That’s something that would need play testing to determine though.

also,

The original thread was brutal to say the least. I’ve never gotten past the first badge personally.


(Pharap) #116

The PC would be in EEPROM.

I think Magcargo probably was supposed to be Magcargot.
Maybe they didn’t know they’d have enough space.
Depends if any G2 pokemon have a 9 character name.

Depends how many monsters there are in the end.

Being able to craft monster X into either a heavy hitter or a speedy hitter would add a layer of strategy.

I think it would be better to copy it.
If you make it too different then people won’t realise who it’s a nod to.


#117

I have an idea for monster encounters. So what if there are 3 monsters in this one area, so before you go into an encounter a random value is chosen from 0-2. This value will choose the group of monsters that will be selected with the next randomized value. Then there’s a second value that randomises from 1 to the value we just got from the first value. Then, depending on what group and the value randomize, it will select a specific monster.

Note: I’m not familiar with C++; this is merely an example.
Randomvalue1 = random (0-2)
Randomvalue2 = random (0-Randomvalue2)

Randomvalue1 (if equal to 0) {
Mon1
}
Randomvalue1 (if equal to 1) {
if (Randomvalue2 = 1) Mon1
if (Randomvalue2 = 2) Mon2
}
Randomvalue1 (if equal to 2) {
if (Randomvalue2 = 1) Mon1
if (Randomvalue2 = 2) Mon2
if (Randomvalue2 = 3) Mon3
}

And as you can see, Mon1 will be the most common of them, while Mon3 is the least common and Mon2 in the middle. You can also added more than one if statement for the same monster to increase it’s encounter rate. There are probably other ways to do it, but I just felt like I should contribute an idea.


(Pharap) #118

It’s probably easier to just have a single table and have either weights or multiple entries.

E.g. weights:

struct MonsterEncounter
{
public:
  uint8_t monsterId;
  uint8_t weight;
};

const MonsterEncounter encounterTable[] =
{
  { 1, 128 }, { 2, 64 }, { 3, 64 },
};
const uint8_t encounterTypes = 3;

uint8_t getRandomMonster(void)
{
  uint8_t r = rand() & 0xFF;
  for(uint8_t i = 0; i < encounterTypes; ++i)
  {
    auto encounter = encounterTable[i];
    if(r < encounter.weight) return encounter.monsterId;
    r -= encounter.weight;
  }
  return 0;
}

#119

I can think of a couple different ways to implement encounter rate, but I’m no sure what would be the best either. Each area could also have a level range that a rand roll could pull from for the spawned monsters level.

This is something along the lines I was thinking.


(Pharap) #120

I think weights might be cheaper than multiple entries, unless the table was compressed in progmem and then unpacked into RAM.

E.g.

struct TableEntry { uint8_t id; uint8_t amount;  };

const TableEntry table[] PROGMEM
{
  { 1, 6 }, { 2, 1 }, { 3, 1 },
};

const uint8_t unpackedTable[64];
uint8_t total = 0;

void setupTable(const TableEntry * table, uint8_t amount)
{
  total = 0;
  for(uint8_t i = 0; i < amount; ++i)
  {
    const TableEntry entry = static_cast<TableEntry>(pgm_read_word(&table[i]));
    total += entry.amount;
    for(uint8_t j = 0; j < entry.amount; ++j) unpackedTable[j] = entry.id;
  }
}

uint8_t getRandomMonster(void)
{
  uint8_t r = rand() % total;
  return unpackedTable[r];
}

#121

So something that can select one of multiple entries based opon the area the player’s in and/or other variable?