Thread: Need Partners (D&D fan preferably)

  1. #1
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853

    Need Partners (D&D fan preferably)

    I was just trying to learn C++ so I started creating a D&D (4th Edition) character builder, since it is a good example to learn classes and stuff. But now I am tempted to actually make it working, meaning to be able to create a character, move and fight an encounter normally.
    I have almost finished the code needed to create a character, the board and the appropriate functions needed for the characters to act. But it is kind of bigger than I thought. So I would like to cooperate with more people to finish it. Mostly I would like the experience in working together with other programmers to accomplish the project.

    What I want exactly is for someone to create a graphic interface for the code I have.
    Then we also need code for all the powers and feats. I have a basic code how to accomplish this, but writing all of the powers and feats might take some time. But if 2-3 people are interested it wont be a big deal.

    So whoever is interested can post here

  2. #2
    Registered User
    Join Date
    Nov 2005
    Posts
    673
    I am willing to coordinate with you on this. I am a fan of D&D, am avidly learning DirectX, so just let me know I guess.

  3. #3
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Well, I need a couple of days to finish completely the code and organize it a bit in order to be readable (things came up, didn't really have much time).

    Generally, I am thinking something simple. Like a window that is divided in 3 sub-windows. One would be the screen, the other a text output and the third a text input. Like:

    -------------------------
    SCREEN | INFO
    |
    -------------------------
    OUT
    -------------------------
    IN
    -------------------------

    Currently mine is printing at the console. So the function will have to change. I ll finish the details to make sure everything will be ok and I ll post here the code with some basic explanations

  4. #4
    Registered User
    Join Date
    Nov 2005
    Posts
    673
    What is the purpose of the in/out windows?

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Sort of like this?
    Last edited by VirtualAce; 03-12-2011 at 11:41 AM.

  6. #6
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Yeah. The out box would be the "game" talking to the player. Like "missed". "Welcome". "Select your weapon". And stuff like that. Or in my version, when you want to attack for example it prompts you to choose your weapon. That information should be displayed in a OUT box.

    Of course this solution is to make it more simple, so that its window displays certain things. The inventory box maybe the only one that has multiple functions, like displaying the itesm or the stats or the powers depending on the command given. I ll probably have the first code ready in less than a day so we can work from there.

  7. #7
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Well, I believe this code should suffice to see what I have done
    Here are some explanations for the graphics:
    -There is an array of Object* pointers. This is the board. Every enemy, heroe, tree etc etc is an Object object. Every Object has a symbol which is displayed on the screen. In the graphic mode the symbol should be an image or a shape with fixed dimensions equal to one "square".
    -The repaint() function prints the board and everything on it. This has to be changed probably in the graphic mode.
    -Every cout has to replaced with code to print on the windows.
    -The command system is always choose from a list. Like "1. Standard, 2.Move, 3.Minor". You choose 1. Afterwards you choose your standard action etc etc. This can be changed with buttons. Buttons will be better generally. They will need some more code, but they might make simpler the options.
    -The command window with or w/o buttons will probably have to be enabled only when it is the players turn.
    -The movement on the map will probably be utilized with the arrow keys (no diagonal move). Instead of that it can be done by clicking on the map.

    Now, I haven't yet write code about how the feats and powers will work. So if anybody has an idea please feel free to share. What I think is this.
    First of all, the powers and feats and generally the other abilities will be objects. The character object will have std::vector s that will store them.
    The character will have an attack() function. This attack function will have default values to work as a basic attack. The power will be able to call the attack() function through a use() function which will fill accordingly the parameters. Like selecting the attack stat, the defense, extra attack, different damage etc etc. If it has a secondary attack it will call attack() twice. Now if the power doesn't make an attack or is an utility it will have to be written by scratch.
    Now, the abilities (like race traits) and feats are a bit more tricky. I can't find a general way to use them. The only thing I think will be appropriate is for each trait/feat have a keyword. So when you call attack() that can search the trait list and if the keyword is "Damage" or "AttacK" it will add those bonuses. It will actually call a use() function that will return the appropriate values if some requirements are met. Like call "Attack" and have the right weapon equipped to benefit from a Weapon Focus.
    If the trait adds a bonus to the second wind for example, as the dwarf, then it will replace the second wind (which will be simulated as a standard power) power from the list with a different one. Or something like that.
    Any ideas on that?
    Last edited by C_ntua; 10-04-2008 at 04:44 AM.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    A quick run through your code reveals a number of bad things.
    Firstly, you should hide your variables inside the class. If you don't want to bother with get/set, this may help:
    Code:
    #ifndef UtilityMember_h__
    #define UtilityMember_h__
    #include <boost/type_traits.hpp>
    #include "FriendTemplateClass.h"
    
    namespace Stuff
    {
    	template<typename T> struct ParamType
    	{
    		typedef typename boost::remove_cv
    		<
    			typename boost::remove_const
    			<
    				typename boost::remove_pointer
    				<
    					typename boost::remove_reference<T>::type
    				>::type
    			>::type
    		>::type BasicType;
    	};
    
    	template<typename T, bool IsFundamental> struct ParamPolicyInternal // IsFundamental = false
    	{
    		typedef typename boost::add_const
    		<
    			typename boost::add_reference<typename ParamType<T>::BasicType>::type
    		>
    		::type Type;
    	};
    	template<typename T> struct ParamPolicyInternal<T, true> { typedef typename ParamType<T>::BasicType Type; };
    	template<typename T> struct ParamPolicy: public ParamPolicyInternal<T, boost::is_fundamental<T>::value> { };
    
    	#define Template \
    		template \
    		< \
    			typename Type, \
    			typename Class = Dummy<Type>, \
    			typename ParamPolicy<Type>::Type (Class::* GetFunction)() = &Dummy<Type>::GetFunction, \
    			void (Class::* SetFunction)(typename ParamPolicy<Type>::Type) = &Dummy<Type>::SetFunction \
    		>
    
    	template
    	<
    		typename Type,
    		typename Class,
    		typename ParamPolicy<Type>::Type (Class::* GetFunction)(),
    		void (Class::* SetFunction)(typename ParamPolicy<Type>::Type)
    	>
    	class CUtilityMemberSpecial
    	{
    	private:
    		TYPE_FRIENDLY(Class);
    		Class* m_pClass;
    		typename ParamPolicy<Type>::Type m_Data;
    
    	public:
    		CUtilityMemberSpecial(Class* pClass): m_pClass(pClass) { }
    		CUtilityMemberSpecial(typename ParamPolicy<Type>::Type NewData, Class* pClass)
    		{
    		    Data = NewData;
    		    m_pClass = pClass;
            }
    		CUtilityMemberSpecial& operator = (typename ParamPolicy<Type>::Type NewData)
    		{
    			(m_pClass->*SetFunction)(NewData);
    			return *this;
    		}
    		operator typename ParamPolicy<Type>::Type () const
    		{
    			return (m_pClass->*GetFunction)();
    		}
    	};
    
    	template<typename Type> class CUtilityMember
    	{
    	private:
    		typename ParamPolicy<Type>::Type m_Data;
    
    	public:
    		CUtilityMember() {}
    		CUtilityMember(typename ParamPolicy<Type>::Type NewData)
    		{
    		    m_Data = NewData;
            }
    		CUtilityMember& operator = (typename ParamPolicy<Type>::Type NewData)
    		{
    			m_Data = NewData;
    			return *this;
    		}
    		operator typename ParamPolicy<Type>::Type () const
    		{
    			return m_Data;
    		}
    	};
    }
    
    #endif // UtilityMember_h__
    CUtilityMember<int> m_AttackStrength;
    Is all you have to do to hide it. Later, you can use CUtilityMemberSpecial if you want further customization. Better encapsulation. Good for the overall health of your code.

    CAccessorie is actually spelled CAccessory.
    Your BOARD should probably be boost::array (and not a pointer!). It will detect out-of-bounds for you. And is it really necrssary to make it a pointer?

    readStr should really use std::getline instead of std::cin.getline.

    Race should probably be an enum.
    I don't know if it's a good idea to name the struct and the instance of the struct by the same name (skills).

    And lastly, you have too much code and too little code that runs the game.
    Take it easy. Write the code to run the game, and add utility code to support it as you go.
    If you have to change something in your utility classes now, you may end up breaking all the code.
    And you don't even know if the current system works! Another good reason to write actual code to test if before going berserk and adding all sorts of different code to make the "system" work.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Yeah, you are absolutely right about the too much code. That is why actually I asked for some help, because I was writing the code just to learn C++, so I didn't bother writing code for it to actually be "playable", so I cannot really test it.
    So if somebody writes an interface I will be able to test it and debug it accordingly.
    And hope it won't go berserk

    I don't fully understand the hiding of my variables. But that is of course of my lack of experience with templates, so I ll need to study what you posted first I guess

    Yeah, it is not really a good idea. I will change the skills struct name.

    I ll change the array into the boost::array since I see it is better, rather than a [][].
    But, an array with what??? For example, when selecting a target I need to scan the board and find where is a valid target. Then I need to interact with that target's object. So I use a pointer. I cannot use a board with Object, since I want also to interact with objects from the derived classes of Object. There are alternatives, but I find this the simpler.

    I will change cin.getline() with std::getline()...whats the difference though?

    Well, I should have an enum for races and keywords. I have that in mind, I ll just do it in the end when I decide how much races will be playable.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by C_ntua View Post
    Yeah, you are absolutely right about the too much code. That is why actually I asked for some help, because I was writing the code just to learn C++, so I didn't bother writing code for it to actually be "playable", so I cannot really test it.
    So if somebody writes an interface I will be able to test it and debug it accordingly.
    And hope it won't go berserk
    If it's too much, perhaps start off with a console?

    I don't fully understand the hiding of my variables. But that is of course of my lack of experience with templates, so I ll need to study what you posted first I guess
    The need is because - what if you at some time decide to manually "balance" other variables if you, for example, change the defense of a character?
    Then you would need to change your code everywhere where you set the defense because one simple thing changed. Or, if you made a set function, you could change modify the function all you want, without having to change the code where you set the defense.
    It's called encapsulation, because you can write changes without breaking the code that is dependant on it.
    My get/set wrapper is a way to encapsulate without (again) changing your code.

    You really don't need to understand how it works (but it would be a good idea), only that CUtilityMember expects the type of the variable.
    So if you have

    int x;

    You can replace it with

    CUtilityMember<int> x;

    The CUtilityMemberSpecial wants the type, the class and get/set pointers. Here's how it can be done:

    CUtilityMemberSpecial<int, Character, &Character::GetDefense, &Character::SetDefense) x;

    And in the constructor, initialize it with the address of the class instance:

    Character(): x(this)

    I ll change the array into the boost::array since I see it is better, rather than a [][].
    But, an array with what??? For example, when selecting a target I need to scan the board and find where is a valid target. Then I need to interact with that target's object. So I use a pointer. I cannot use a board with Object, since I want also to interact with objects from the derived classes of Object. There are alternatives, but I find this the simpler.
    There's a problem with this.
    It's a pointer, so it requires you to allocate space for it.
    So then, how do you know which position requires CObject, which requires CObjectDerived and CObjectDerived2?
    It just won't work very well.

    So you should make an array with a CObject or CBoard or something.

    boost::array<boost::array<CObject, BOARDX+1>, BOARDX+1> BOARD;

    Remember that the board should contain all useful functions that you need for the board.
    You don't need several classes... just one.

    I will change cin.getline() with std::getline()...whats the difference though?
    std::getline reads into a std::string instead of a char. It's more C++, and you shouldn't have to worry about providing a big enough buffer.

    Well, I should have an enum for races and keywords. I have that in mind, I ll just do it in the end when I decide how much races will be playable.
    Well, fair enough I guess, but you're going to have to change your code later when you switch to an enum, and the faster you do it, the less code you have to change.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    The board of pointers won't allocate space. It will just point to the objects created. The rest will be NULL. Generally, no information is needed. Only the position, which is stored inside each Object. The board just keeps tracks of all the objects created. I could just use a vector<Object*> to do this.
    But then if I want to move a character one space north, I would have to search the whole vector to see if another object is on the specific location. Now you just have to search if board[x_pos][y_pos] != NULL. It is kind of simpler.
    Now, there are two ways for me to see if it is derived or not. One is to create every function of Character:Object as virtual to Object. The other is (which I use) to use the name of the Object in order to determine the derived class. Inanimated objects will just be Objects with names like "Tree", "Rock" etc etc. The heroes will be "Character", the enemies "Enemy" and things like that

    Well, I have functions to set stats, like setDef(), setStat(). But I guess what you are saying is more general and would be better.

    I don't understand though how what you propose will work. Like I do CUtilityMember<int> defense; Then if I want to change the defense what do I do? I understand the get/set concept, but I don't understand how this works with this specific method

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by C_ntua View Post
    The board of pointers won't allocate space. It will just point to the objects created. The rest will be NULL. Generally, no information is needed. Only the position, which is stored inside each Object. The board just keeps tracks of all the objects created. I could just use a vector<Object*> to do this.
    But then if I want to move a character one space north, I would have to search the whole vector to see if another object is on the specific location. Now you just have to search if board[x_pos][y_pos] != NULL. It is kind of simpler.
    I think I'm getting why you want pointers to this.
    But I don't know if it's a viable method.
    The problem is that you wouldn't know what type of object is stored at the location, so either you would need to know exactly what's stored, store some type information or use polymorphism.
    Btw, you could simply create a function named is_empty() and call it to check if it's empty instead of checking if a pointer is NULL.

    Now, there are two ways for me to see if it is derived or not. One is to create every function of Character:Object as virtual to Object. The other is (which I use) to use the name of the Object in order to determine the derived class. Inanimated objects will just be Objects with names like "Tree", "Rock" etc etc. The heroes will be "Character", the enemies "Enemy" and things like that
    Essentially, you mean that you "look up" the type and process the object accordingly?
    Not the best design, but a better design would probably require some more advanced knowledge.

    I don't understand though how what you propose will work. Like I do CUtilityMember<int> defense; Then if I want to change the defense what do I do? I understand the get/set concept, but I don't understand how this works with this specific method
    It's simple.

    Code:
    class Character
    {
    public:
        CUtilityMember<int> defense;
    };
    
    int main()
    {
        Character c;
        c.defense = 10; // Set
        cout << c.defense; // Get
    }
    No code changes at all. But the great part is that you can change this to another class later without breaking your code:

    Code:
    class Character
    {
        int Get() { cout << "Character::Get!"; return defense.Data; }
        void Set(int x) { cout << "Character::Set!"; defense.Data = x; }
    public:
        Character(): defense(this) { }
        CUtilityMember<int, Character, &Character::Get, &Character::Set> defense;
    };
    
    int main()
    {
        Character c;
        c.defense = 10; // Set
        cout << c.defense; // Get
    }
    Now you can customize HOW you want to do your getter and setter AND it won't break your original code (it will still compile!).
    This is the power of getter and setters.
    My class simply translates the syntax from .get() and .set(...) to .var = x and .var.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    If you want to use my small framework you really don't need to know anything about MFC. I have functions that will output to each window.

    You should, however, understand interfaces and how the objects talk to each other. In many instances you will need to derive from an interface to provide the underlying implementation of the interface. My interfaces describe the basic behavior and your code will implement that behavior as it relates to your game.

    I'll put it all into DLLs and finish the interfaces if you want to use it. Right now it is set up for implicit linking but I can set it up for explicit linking so I can alter the DLL and essentially send you a revised version and you won't have to make any code changes.

    There are far too many templates in that as it stands right now. You really don't need all of that.

    I think you would need at least the following objects:

    1. Stats class
    2. Abstract character base class
    3. Abstract game object base class (for items and such)
    4. Inventory class
    5. Map class
    6. Room class
    7. Parser class


    When you start out you should be looking at the objects in terms of their behavior and not how they implement that behavior. Also if you don't want to hardcode your stats you will need to come up with something that is flexible enough for that.

    Code:
    class IStat
    {
       public:
         virtual ~IStat() { }
         
         virtual unsigned int getValue() const = 0;
         virtual void setValue(const unsigned int value) = 0;
         virtual void incrementValue(const unsigned int increment) = 0;
         virtual void decrementValue(const unsigned int decrement) = 0;
         virtual void clearValue() = 0;
    
         virtual void setMaxValue(const unsigned int max) = 0;
         virtual unsigned int getMaxValue() const  = 0;
         
         virtual std::string getName() const = 0;
         virtual void setName(const std::string &name) = 0;
    };
    
    struct CharacterStat
    {
       std::string name;
       unsigned int value;
       unsigned int maxValue;
    };
    
    class IStatMgr
    {
       public:
         virtual ~IStatMgr() { }
    
         virtual bool addStat(const std::string &name,const CharacterStat &stat) = 0;
         virtual bool removeStat(const std::string &name) = 0;
         virtual CharacterStat &getStat() const = 0;
         virtual void getStat(const CharacterStat &stat) = 0;
         virtual void getAllStats(std::vector<CharacterStat> &stats) = 0;
         virtual void clearAllStats() = 0;
    
         virtual unsigned int getStatValue(const std::string &name) const = 0;
         virtual void setStatValue(const std::string &name,const unsigned int value) = 0;
         virtual void incrementStatValue(const std::string &name,const unsigned int increment) = 0;
         virtual void decrementStatValue(const std::string &name,const unsigned int decrement) = 0;
         virtual void clearStatValue(const std::string &name) = 0;
     };
    This is just an idea of what your stats interfaces might look like. The IStatsMgr impl class would essentially just be a container for IStat objects. Each character then would have an IStatsMgr impl or you could centralize this in a CharacterMgr constainer class.

    I think its very important to get a rudimentary design down on paper. It doesn't have to be fancy or tried and true UML but it should illustrate the relationships between objects. As well it will help you later when actually coding when you feel as if you have hit a brick wall. Remember - in design you want to look at the objects in terms of their behavior not how they actually implement that behavior. This approach will help you design your system.
    Last edited by VirtualAce; 10-04-2008 at 11:47 AM.

  14. #14
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Thanks for the ideas. I ll try to utilize them at one point. Kind of busy at the moment but I ll post here when I am ready

  15. #15
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Sorry to poke my head in here, but if you want to learn the concept behind Elysia's CUtilityMember, here's an example without the templates.

    aka setters and getters
    aka accessors
    aka encapsulation
    aka information hiding

    http://en.wikipedia.org/wiki/Information_hiding
    http://www.javaworld.com/javaworld/j...on.html?page=1

    Purpose: If you change the internals of the class, you don't want it to effect clients using that class. If you use simple variables, and later find out you need to validate, or process that variable before it's used, you have a problem. The variables are directly accessed from memory, but you need a function call. This is why you see functions such as getLength, setLength, getName, setName, getDistance, setDistance. You might want to check the name against something before allowing it, or do something else with it. In getDistance you would want to calculate the distance between some points. Instead of calling is calculateDistance, you abstract the fact it's calculated, because other classes don't need to know that - it's not important to them - they just want the return value, and call it getDistance. At the same time we can avoid the hassle of typing getDistance all the time and overload the = operator and access operator.

    main.h
    Code:
    class Latitude
    {
        private:
            int Data; // wrapped variable
    
        public:
            Latitude(); // constructor
    
        public:
            Latitude operator=(int data);
            operator int() const;
    };
    
    struct Point
    {
        Latitude Lat;
        int Lang; // instead of using a basic int variable, convert to it's own class wrapper
    };
    main.cpp
    Code:
    #include <iostream>
    
    #include "main.h"
    
    Latitude::Latitude() : Data(0)
    {
    
    }
    
    Latitude Latitude::operator =(int data)
    {
        // only allow latitudes between 0 and 255
        if(data > 0 && data < 255)
            this->Data = data;
    
        return *this;
    }
    
    Latitude::operator int() const
    {
        return this->Data;
    }
    
    int main()
    {
        Point *p = new Point();
    
        p->Lat = 500; // ignored
    
        std::cout << p->Lat << std::endl; // 0
    
        p->Lat = 200; // works
    
        std::cout << p->Lat << std::endl; // 200
    
        return 0;
    }
    The purpose of the templates is to be generic, allowing you to turn your variable into a getter/setter class any time you want.

    Note that none of this is really necessary until you run into a problem, or need to calculate one of your variables before it's used (such as distance) and don't want to both with getDistance/setDistance. Otherwise you can ignore this stuff for now, and easily add it later.
    Last edited by Dae; 10-23-2008 at 01:54 AM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. [Hardware + Software][C++ or C#] USB Fan
    By Mywk in forum C++ Programming
    Replies: 16
    Last Post: 07-04-2009, 03:12 PM
  2. What is the fan size?
    By adr in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 12-06-2007, 03:21 PM
  3. Computer Fan question
    By the dead tree in forum Tech Board
    Replies: 2
    Last Post: 12-28-2005, 04:16 PM
  4. Stress Test: Graphics/CPU intense
    By RoD in forum Tech Board
    Replies: 90
    Last Post: 01-19-2003, 01:20 PM
  5. P4 Fan problem: Urgent
    By RoD in forum Tech Board
    Replies: 5
    Last Post: 01-15-2003, 12:12 PM