Issue with loops

I have an array of monsters, I'm attempting to append a number if they are a duplicate. In the code below, I would have Fire Wolf 1, Fire Wolf 2, but not Fire Sprite would be left alone since there is only one.

I have tested it, and the parts of it work but not the whole. I think I'm missing something stupid, thanks for the help.

#include "Monster.h"
//Monster(char* mName,bool inCombat, int initRoll,int hp, int initMod)
//.roll() updates initRoll with D20+initMod
//.engage() move to combat
//.kill() remove from combat


//----------------------------------------------------------------------------------------------
//Variables

const int TOME_LENGTH = 12;     //the length of the master tome of players and monsters


Monster tome[TOME_LENGTH] = {
  {"Thio Ki",1,25,4, false, "PC Human Wizard"},   
  {"Zenwan",1,27,2, false, "PC Halfling Rogue"},
  {"Balkas",1,33,4, false, "PC Elf Monk"},
  {"Fire Wolf",1,7,2, true, "AC=13 Flame Bite Melee +4 2d4+1 one fire"},   
  {"Fire Wolf",1,7,2, true, "AC=13 Flame Bite Melee +4 2d4+1 one fire"},   
  {"Fire Sprite",1,7,0, true, "AC=9 Melee Bite +4 2d4 one fire"},  
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},   
  {"Aiden",1,14,1, true, "AC=13 Spell Caster Melee +3 1d4"}
};


void setup() {
  Serial.begin(9600);
  Serial.println("Hello");
  multiMonster();
  for(byte i = 0; i < TOME_LENGTH; i++){
    Serial.println(tome[i].mName);
  }
}

void loop() {

}

//-------------------------------------------------------------------

void multiMonster(){
  for(byte active = 0; active < TOME_LENGTH; active++){
     byte monsterMatch[TOME_LENGTH];                                              //make a place to hold the matching indexes
     monsterMatch[0] = active;                                                    //add the current monster to monsterMatch 
     byte matchCounter = 1;                                                       //set the counter to one, this should increment everytime there is another matching name found  
     for(byte compare = 0; compare < TOME_LENGTH; compare ++){
      if(tome[active].mName == tome[compare].mName && active != compare){         //if the mName of the active monster matched the one we're comparing it to and they are not the same monster
        monsterMatch[matchCounter] = compare;                                     //add their index to the monsterMatch array
        matchCounter ++;                                                          //increment the matchCounter for the next monster (if needed)
      }
     }
    if (matchCounter > 1){                                                        //if a second monster was added to the list
      for(byte m = 0; m < matchCounter; m ++){                                    //append 1 to the first monster, 2 to the second monster, 3 to the third monster)
        char monsterBuffer[3];
        sprintf (monsterBuffer, ' %d', m);
        tome[monsterMatch[m]].mName = strcat(tome[monsterMatch[m]].mName, monsterBuffer);
        }
    }
  } 
}

if(tome[active].mName == tome[compare].mName

What type is the mName field? If it is char * or char array, that is NOT how you compare strings.

        sprintf (monsterBuffer, ' %d', m);

Single quotes are for SINGLE characters. Double quotes are for strings.

Since m can conceivably be as high as 12, your monstoerBuffer is too small. 2 digits plus a space plus a terminating NULL is NOT going to fit in a 3 element array.

mName is char* I will do some research on comparing strings.

Here is the code with your suggested updates:

#include "Monster.h"
//Monster(char* mName,bool inCombat, int initRoll,int hp, int initMod)
//.roll() updates initRoll with D20+initMod
//.engage() move to combat
//.kill() remove from combat


//----------------------------------------------------------------------------------------------
//Variables

const int TOME_LENGTH = 12;     //the length of the master tome of players and monsters


Monster tome[TOME_LENGTH] = {
  {"Thio Ki",1,25,4, false, "PC Human Wizard"},   
  {"Zenwan",1,27,2, false, "PC Halfling Rogue"},
  {"Balkas",1,33,4, false, "PC Elf Monk"},
  {"Fire Wolf",1,7,2, true, "AC=13 Flame Bite Melee +4 2d4+1 one fire"},   
  {"Fire Wolf",1,7,2, true, "AC=13 Flame Bite Melee +4 2d4+1 one fire"},   
  {"Fire Sprite",1,7,0, true, "AC=9 Melee Bite +4 2d4 one fire"},  
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},   
  {"Aiden",1,14,1, true, "AC=13 Spell Caster Melee +3 1d4"}
};


void setup() {
  Serial.begin(9600);
  Serial.println("Hello");
  multiMonster();
  for(byte i = 0; i < TOME_LENGTH; i++){
    Serial.println(tome[i].mName);
  }
}

void loop() {

}

//-------------------------------------------------------------------

void multiMonster(){
  for(byte active = 0; active < TOME_LENGTH; active++){
     byte monsterMatch[TOME_LENGTH];                                              //make a place to hold the matching indexes
     monsterMatch[0] = active;                                                    //add the current monster to monsterMatch 
     byte matchCounter = 1;                                                       //set the counter to one, this should increment everytime there is another matching name found  
     for(byte compare = 0; compare < TOME_LENGTH; compare ++){
      if(tome[active].mName == tome[compare].mName && active != compare){         //if the mName of the active monster matched the one we're comparing it to and they are not the same monster
        monsterMatch[matchCounter] = compare;                                     //add their index to the monsterMatch array
        matchCounter ++;                                                          //increment the matchCounter for the next monster (if needed)
      }
     }
    if (matchCounter > 1){                                                        //if a second monster was added to the list
      for(byte m = 0; m < matchCounter; m ++){                                    //append 1 to the first monster, 2 to the second monster, 3 to the third monster)
        char monsterBuffer[4];
        sprintf (monsterBuffer, " %d", m);
        tome[monsterMatch[m]].mName = strcat(tome[monsterMatch[m]].mName, monsterBuffer);
        }
    }
  } 
}

If mName is char* this is going to be a problem:

        tome[monsterMatch[m]].mName = strcat(tome[monsterMatch[m]].mName, monsterBuffer);

Firstly, all you need is :

        strcat(tome[monsterMatch[m]].mName, monsterBuffer);

But even then, you will write on memory you don't own. Make mName a char array with sufficient space instead.

It would be helpful if you posted the contents of monster.h.

So far, I can't see why you're using an Arduino for this. Easier to debug on the machine you're using to program the Arduino even if you do need I/O later.

wildbill:
So far, I can't see why you're using an Arduino for this. Easier to debug on the machine you're using to program the Arduino even if you do need I/O later.

The rest of my code works fine, this is just a feature I'm trying to add in with this small subset. I'm pretty new at this and hopping between Dev envrionments is a bit beyond me.

Here is the code for Monster.h:

#ifndef Monster_H
#define Monster_H

#include <Arduino.h>

class Monster{
	
	public:
		char* 	mName;
		bool	inCombat;
		byte 	initRoll;
		byte	currhp;
		
		int		hp;
		byte	initMod;
		bool	npc;
		char*	details;
		
		
		Monster(char* n, byte r,byte h, int i, bool p, char* d);
		void roll();
		void engage();
		void kill();
		void takeHit(int howHard);
	
		

};

#endif

My code runs and does the comparison and appending correctly, I'm just getting too many numbers. Here is the result of execution:

Hello
Thio Ki
Zenwan
Balkas
Fire Wolf 0 1 0 1
Fire Wolf 0 1 0 1
Fire Sprite
Son of Ignis 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
Son of Ignis 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
Son of Ignis 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
Son of Ignis 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
Son of Ignis 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
1 2 3 4 0 1 2 3 4

My code runs and does the comparison and appending correctly

Until you fix all of the problems PaulS identified for you and make mName a char array (maybe 16 bytes?), I don't think that's a true statement.

As suggested, I changed mName to char mName[20], here is my code now:

#include <CircularBuffer.h>
#include "Monster.h"

//Monster(char mName[20] ,bool inCombat, int initRoll,int hp, int initMod)
//.roll() updates initRoll with D20+initMod
//.engage() move to combat
//.kill() remove from combat

 

 

//----------------------------------------------------------------------------------------------

//Variables
const int TOME_LENGTH = 12;     //the length of the master tome of players and monsters

Monster tome[TOME_LENGTH] = {

  {"Thio Ki",1,25,4, false, "PC Human Wizard"},  
  {"Zenwan",1,27,2, false, "PC Halfling Rogue"},
  {"Balkas",1,33,4, false, "PC Elf Monk"},
  {"Fire Wolf",1,7,2, true, "AC=13 Flame Bite Melee +4 2d4+1 one fire"},  
  {"Fire Wolf",1,7,2, true, "AC=13 Flame Bite Melee +4 2d4+1 one fire"},  
  {"Fire Sprite",1,7,0, true, "AC=9 Melee Bite +4 2d4 one fire"}, 
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},
  {"Son of Ignis",1,10,1, true, "AC=11 Spell Caster Melee +3 1d4"},  
  {"Aiden",1,14,1, true, "AC=13 Spell Caster Melee +3 1d4"}
};

 

 

void setup() {

  Serial.begin(9600);
  Serial.println("Hello");
  multiMonster();
  for(byte i = 0; i < TOME_LENGTH; i++){
    Serial.println(tome[i].mName);
  }
}

 

void loop() {


}

void multiMonster(){
  for(byte active = 0; active < TOME_LENGTH; active++){
    CircularBuffer<byte,20> monsterMatch;
    monsterMatch.push(active);                         //Adds the active index to monsterMatch
    for(byte compare = 0; compare < TOME_LENGTH; compare++){
      if(strcmp(tome[active].mName, tome[compare].mName) == 0 &&  active !=  compare){
        monsterMatch.push(compare);
      }
    }
    
    byte apendCounter = 1;
    if (monsterMatch.size() > 1){
      for(byte u = 0; u < monsterMatch.size(); u++){
        char monsterBuffer[4];
        sprintf(monsterBuffer, " %d", apendCounter);
        strcat(tome[monsterMatch[u]].mName, monsterBuffer);
        apendCounter++;
      }
    }       
    //for(byte i = 0; i < monsterMatch.size(); i ++){
    //  Serial.println(tome[active].mName);
    //  Serial.println(monsterMatch[i]);
    //}
  monsterMatch.clear();

  }

}

and here is the current result:

Hello
 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12

For reference here is the revised Monster.h

#ifndef Monster_H
#define Monster_H

#include <Arduino.h>

class Monster{
	
	public:
		char 	mName[20];
		bool	inCombat;
		byte 	initRoll;
		byte	currhp;
		
		int		hp;
		byte	initMod;
		bool	npc;
		char*	details;
		
		
		Monster(char mName[20], byte r,byte h, int i, bool p, char* d);
		void roll();
		void engage();
		void kill();
		void takeHit(int howHard);
	
		

};

#endif

and the Monster.cpp

#include "Monster.h"

Monster::Monster(char mName[20], byte r,byte h, int i, bool p, char* d){
	inCombat = false;
	initRoll = r;
	hp = h;
	currhp = hp;
	initMod = i;
	npc = p;
	details = d;
	
}


void Monster::roll(){
	initRoll = random(1,21) + initMod;
}

void Monster::engage(){
	inCombat = true;
}

void Monster::kill(){
	inCombat = false;
}

void Monster::takeHit(int howHard){
	currhp -= howHard;
	if (currhp <= 0){
		kill();
	}
}

So I'm missing something else now, probably related to dealing with Char arrays.

Why does the constructor take a name (mName) that it doesn't use?

		char*	details;

You still don't understand that you REALLY need to declare an array...

I understand the memory allocation logic behind using a char array over char*. I don't understand how to implement that in my class constructor. I have attempted to do it for both the mName and the details.

#include "Monster.h"

Monster::Monster(char m[20], byte r,byte h, int i, bool p, char d[25]){
	mName[20] = m;
	inCombat = false;
	initRoll = r;
	hp = h;
	currhp = hp;
	initMod = i;
	npc = p;
	details[25] = d;
	
}


void Monster::roll(){
	initRoll = random(1,21) + initMod;
}

void Monster::engage(){
	inCombat = true;
}

void Monster::kill(){
	inCombat = false;
}

void Monster::takeHit(int howHard){
	currhp -= howHard;
	if (currhp <= 0){
		kill();
	}
}

and Monster.cpp

#ifndef Monster_H
#define Monster_H

#include <Arduino.h>

class Monster{
	
	public:
		char 	mName[20];
		bool	inCombat;
		byte 	initRoll;
		byte	currhp;
		
		int		hp;
		byte	initMod;
		bool	npc;
		char	details[25];
		
		
		Monster(char m[20], byte r,byte h, int i, bool p, char d[25]);
		void roll();
		void engage();
		void kill();
		void takeHit(int howHard);
	
		

};

#endif

If this is not correct, please include a URL of where I can learn how to do this.

If this is not correct, please include a URL of where I can learn how to do this.

Of course it is wrong. What I can not understand is why you can't understand how arrays work.

An array is a continuous block of memory. You defined an array, mName, with 20 elements. Then, you try to assign a value to the 21st position in that array, while ignoring the previous 20 elements.

		char 	mName[20];

	mName[20] = m;

That, or course, is rubbish. Even without the incorrect value in the brackets, that is NOT how you copy data from one array to another. strcmp() rules.

The assignment to details is equally wrong.

ANY C book will clear up all of your erroneous misconceptions by the end of chapter 4. GET A BOOK. Forget about online resources. If nothing else, we can beat you over the head with the book. Can't do that with a URL.

I'll work on getting a book.

I've looked at my .h and .cpp with fresh eyes, and I've implemented strcpy.

Monster.h:

#ifndef Monster_H
#define Monster_H

#include <Arduino.h>

class Monster{
	
	public:
		char	mName[20];
		bool	inCombat;
		byte 	initRoll;
		byte	currhp;
		
		int		hp;
		byte	initMod;
		bool	npc;
		char	details[25];
		
		
		Monster(char n[20], byte r,byte h, int i, bool p, char d[25]);
		void roll();
		void engage();
		void kill();
		void takeHit(int howHard);
};

#endif

Monster.cpp:

#include "Monster.h"

Monster::Monster(char n[25], byte r,byte h, int i, bool p, char d[25]){
	strcpy(n , mName);
 	inCombat = false;
	initRoll = r;
	hp = h;
	currhp = hp;
	initMod = i;
	npc = p;
	strcpy(d, details);
}


void Monster::roll(){
	initRoll = random(1,21) + initMod;
}

void Monster::engage(){
	inCombat = true;
}

void Monster::kill(){
	inCombat = false;
}

void Monster::takeHit(int howHard){
	currhp -= howHard;
	if (currhp <= 0){
		kill();
	}
}
	strcpy(n , mName);

The arguments are to where, from where.

That's the missing piece. Everything works as expected, and has been folded into the main code. Thank you.