• Welcome to Valhalla Legends Archive.
 

Setting Bot Users - Method

Started by Mephisto, March 03, 2004, 07:23 PM

Previous topic - Next topic

Mephisto

I'm new to this whole bot development thing, and I have recently finished coding the necessary code to connect to Battle.net and receive/parse chat events.  Now I am moving on to writing the database, and I am wondering how to do this.  How do I represent a user?  I was thinking of just having the bot read from a database file and get the username and their flags.  That brings me to my next question, how should I represent flags?  I was thinking of writing a class for each flag, and in that class write each of the commands as a function.  But then I get to the point of how do I add a flag (class) to that username, and limit access to other flags (classes)?  I havn't put much thought into it, but I will be thinking of ideas as I get feedback from those who can assist in this.

Keep in mind, this is being written in C++.

effect

For someone who knows 10 or so language's Fluently this should be an easy task..
Quote from: Mangix on March 22, 2005, 03:03 AM
i am an expert Stealthbot VBScript. Recognize Bitch.

Mephisto

#2
You guys are fast.

I never said I knew 10 languages, let alone knew them fluently.

Additionally, I said in the post I havn't put much thought into it, I'm already applying some ideas.  This is just to get some feedback on experienced people in doing this, so I don't go implement a system which would be otherwise infurior to other methods which can be used.

Edit: Well, I suppose it's 10 if you count English.  But I still stand by the fact I never said I knew them fluently.

Eric

Go to the C/C++ programming forum.

Mephisto

If this was C/C++ specific, I think someone would have moved it by now.

Additionally, you don't necessarily have to know C++ to help me out with this.

Zakath

Represent a user's flags as a bitmask. When you retrieve a user's information from the database file, convert each flag into the equivalent value, then construct the bitmask out of them. Then when processing a command, simply see if they have the necessary flag by using the & operator.
Quote from: iago on February 02, 2005, 03:07 PM
Yes, you can't have everybody...contributing to the main source repository.  That would be stupid and create chaos.

Opensource projects...would be dumb.

K

#6
I like to use a std::map to map battle.net names to unique bot names, to map to user info.
something like


class BotUserInfo
{
public:
  // the name to call the user
  std::string ReferenceName;

  std::vector<std::string> AccountNames;
  std::string Email;
  std::string AIM;
 
  bool CanBan() { return (Flags & bn::BAN_MASK); }
  bool CanKick() { return (Flags & bn::KICK_MASK); }
  // etc or:
  bool GetPriv(unsigned int mask) { return (Flags & mask); }

  void SetPriv(unsigned int mask) { Flags |= mask; }
private:
  unsigned int Flags;
};


// now we can translate one of several battle.net names
// into a unique user account name
std::map<std::string, std::string>  UserLookup;

// and that account name into the user's info.
std::map<std::string, bn::BotUserInfo>  UserInfo;




MyndFyre

I'm big on extensions, so I created a simple interface (IUser) that any extension assembly (note that I'm writing in C#, so it's .NET) can provide their own implementation and then just pass that around.  I also defined an interface for a data provider such as:


public interface IDataProvider {
 IUser GetUser(string szUserName);
 IUser CreateUser(string szUserName, int dwRank);
 //etc...
 void SendBotMail(IUser sender, IUser receiver, string Message);
 IBotMaiil[] GetMessages(IUser receiver);
}


That is obviously not the entire idea, but I believe if you define well first how you want your database to behave, you'll find yourself in a much better position down the road.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Adron

#8
I tend to like having flags. If 32 flags is enough for you, use a bitmap. For maximum configurability, allow users to be given any combination of flags, and allow commands or actions to require any combination of flags.

A user could then be:

struct User {
  char name[MAX_NAME];
  unsigned flags;
};


A command could then be:


struct Command {
  char trigger[MAX_TRIGGER];
  unsigned positiveflags;
  unsigned negativeflags;
  void (*processcommand)( ... );
};



if((user.flags & cmd.positiveflags) && !(user.flags & cmd.negativeflags))
   cmd.processcommand(...);



DarkMinion

#9
First I have a struct:

struct User{
   char szMask[32];
   unsigned long dwFlags;
};


Then a list (if you want my linked list class you can have that too, just ask):


List<User *> Database;


Then I use these 3 functions to set/remove/check my flags (thanks Sky for these, btw):


bool CheckFlag(unsigned long dwMask, char bFlag)
{
   if(bFlag < 'A' || bFlag > 'Z')
      return false;
   return !!(dwMask & (1 << (bFlag - 'A')));
}

void SetFlag(unsigned long *dwMask, char bFlag)
{
   if(bFlag < 'A' || bFlag > 'Z')
      return;
   *dwMask |= (1 << (bFlag - 'A'));
}

void RemoveFlag(unsigned long *dwMask, char bFlag)
{
   if(bFlag < 'A' || bFlag > 'Z')
      return;
   *dwMask &= ~(1 << (bFlag - 'A'));
}


So say I wanted to make a new DB entry I would do something like...


User *pNew = new User;
strcpy(pNew->szMask, "testuser"); //set the user mask
pNew->dwFlags = 0;
SetFlag(pNew->dwFlags, 'A'); //set flag(s)
Database.Add(pNew);


If I wanted to modify an entry's flags, I would do something like...


//find the user
User *p;
for(int i = 0; i < Database.Count(); i++){
   p = Database.Get(i);
   if(!stricmp(szEntryToFind, p->szMask))
      break;
}
//modify
RemoveFlag(p->dwFlags, 'N'); //or whatever


If you have questions, feel free to ask...I'll post a link to my linked list class if you want it.

Kp

#10
Minor suggested improvement to DarkMinion's approach -- since you're already using new to allocate the structure, it'll take care of calling a constructor if you provide one.  As such, you could have two constructors: default, which sets name = "" and flags to 0, and one that takes a const char* and an unsigned, and saves the string + flags into the user structure before returning.  It wouldn't be any more or less efficient runtime wise afaik, but it would make for simpler user creation code. :)

[Edit: just noticed that DarkMinion's code will actually produce a user with unpredictable flags.  SetFlag is more properly AddFlag, and the flags aren't being set to a known value first.  Therefore, your only guarantee is that the resulting user will have 'A' as a flag -- he might have other flags as well.  To avoid this, explicitly set the flags variable to zero.]
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

DarkMinion

Sorry, forgot to initialize flags...thanks for reminding me Kp, fixed.