Thread: A basic optimization request...

  1. #1
    Registered User
    Join Date
    May 2010
    Location
    Australia
    Posts
    10

    Smile A basic optimization request...

    Hey, I'm still moderatly new to C++, I've played with it for several months only.

    I'm trying to write some c++ code to record chess pieces in memory, and I will be using a 64-bit model, I did some reading, and it became apparent that I could represent the 64 squares of a chess board in a 64 bit register, such that one register could hold the location of all white pawns, or another all black queens.

    I liked this, it fit in well with the way I pictured my 64-bit processor working.

    I wrote a simple file, it is basically just to hold the data, I'll extend it later, but I have some questions, mostly about memory management and optimization.

    First - I'll list my code...

    BoardData.h
    Code:
    class BoardData
    {
    	struct BitBoard
    	{
    		unsigned long long WhitePawns;
    		unsigned long long WhiteKnights;
    		unsigned long long WhiteBishops;
    		unsigned long long WhiteRooks;
    		unsigned long long WhiteQueens;
    		unsigned long long WhiteKing;
    		unsigned long long WhitePieces;
    		unsigned long long BlackPawns;
    		unsigned long long BlackKnights;
    		unsigned long long BlackBishops;
    		unsigned long long BlackRooks;
    		unsigned long long BlackQueens;
    		unsigned long long BlackKing;
    		unsigned long long BlackPieces;
    		unsigned char CastlingFlags;
    		/* The CastlingFlags are four bits 0-3 that contain true/false information about the availability of castling.
    		 * bit 0 = White King Side Rook (White Short Castle)
    		 * bit 1 = White Queen Side Rook (White Long Castle)
    		 * bit 2 = Black King Side Rook (Black Short Castle)
    		 * bit 3 = Black Queen Side Rook (Black Long Castle)
    		 */
    		unsigned char EnPassantPhantomPawn;
    		/* A value stored in bits 0-6 represents a square of the board (0-63) assuming that 0 is the White Queen Side
    		 * Rook, going left to right and then down the board.
    		 * bit 7 is a true/false flag indicating the pressence of the en'Passant Phantom Pawn, if this bit is false,
    		 * bits 0-6 are unused.
    		 */
    	};
    public:
    	BoardData() { Clear(); };
    	~BoardData() { Destroy(); }
    	void Clear();
    	void Destroy();
    	void* GetHandle();
    private:
    	BitBoard thisInstance;
    };
    and BoardData.cpp
    Code:
    #include "BoardData.h"
    
    void BoardData::Clear()
    {
    	thisInstance.WhitePawns=thisInstance.BlackPawns=0ULL;
    	thisInstance.WhiteKnights=thisInstance.BlackKnights=0ULL;
    	thisInstance.WhiteBishops=thisInstance.BlackBishops=0ULL;
    	thisInstance.WhiteRooks=thisInstance.BlackRooks=0ULL;
    	thisInstance.WhiteQueens=thisInstance.BlackQueens=0ULL;
    	thisInstance.WhiteKing=thisInstance.BlackKing=0ULL;
    	thisInstance.WhitePieces=thisInstance.BlackPieces=0ULL;
    	thisInstance.CastlingFlags=15;
    	thisInstance.EnPassantPhantomPawn=0;
    	return;
    }
    void BoardData::Destroy()
    {
    	delete GetHandle();
    	return;
    }
    void* BoardData::GetHandle()
    {
    	return &thisInstance;
    }
    My hope is that this code can go into memory with a minimum of fuss, while I do not plan to be caching a lot of these structures, I would imagine that during the recursion process I do take a few board thumbnails as I go.

    My model is speed priority, memory secondary. As I just said, memory is still of a high profile concern.

    What would be better, calling this as a static library, a dynamic dll or just inserting it as a class in my main program? I'll elaborate on a few things, load time is unimportant as a speed consideration, speed is only required for improving iterations.

    Can anyone just looking at the above perhaps suggest a better way of handling this data?

    Finally, (and slightly off-topic) I'm using Visual Studio 2008 Professional, I made a 64bit profile for the code, I'm sure there is an easy way to remove the default Win32 profile, (guess I'm being slightly dumb asking here, as I will solve this before I get a reply) how do I remove that reference to the Win32 profile...

    P.S: Perhaps I lack confidence, but I'm going to ask anyway, does anyone see any apparent faults with my code? I've been more mucking around with C#, and void* and delete commands are not something I've delved into much.

    EDIT: I'd like to add that for storing the board I intend to use 32 bytes to hold the physical component + a byte for castle flags, and a byte for the en'Passant Phantom Pawn, this storage will be used in transposition tables. The above description is purely for accelerated processing, an expanded form.
    Another query I have with the void*, will I be able to access the data in the struct using that void*, like say I wanted to extract the flags for castling, would I need to redeclare the struct in the main code block?
    For example, say I went with the idea of making this a DLL, my guess is that I would need to make the struct extern (as well as all the public functions I suppose...)
    2nd Edit: I've totally rearranged my code into a factory, looking back at the above now that I've ventured on a little I see my whole approach was possibly way out of whack.
    With that struct, when it comes to delete, do I just use delete to destory it, or should I use the array variant of delete?
    Last edited by feeder74; 05-04-2010 at 12:33 AM.

  2. #2
    Registered User
    Join Date
    May 2010
    Location
    Australia
    Posts
    10
    Ok, well, the factory has rewritten the above, but I'm doing something wrong...

    I'll list my code and explain, hopefully someone will help...

    BoardFactory.h
    Code:
    class BoardFactory
    {
    	struct BitBoard
    	{
    		unsigned long long WhitePawns;
    		unsigned long long WhiteKnights;
    		unsigned long long WhiteBishops;
    		unsigned long long WhiteRooks;
    		unsigned long long WhiteQueens;
    		unsigned long long WhiteKing;
    		unsigned long long WhitePieces;
    		unsigned long long BlackPawns;
    		unsigned long long BlackKnights;
    		unsigned long long BlackBishops;
    		unsigned long long BlackRooks;
    		unsigned long long BlackQueens;
    		unsigned long long BlackKing;
    		unsigned long long BlackPieces;
    		unsigned char CastlingFlags;
    		/* The CastlingFlags are four bits 0-3 that contain true/false information about the availability of castling.
    		 * bit 0 = White King Side Rook (White Short Castle)
    		 * bit 1 = White Queen Side Rook (White Long Castle)
    		 * bit 2 = Black King Side Rook (Black Short Castle)
    		 * bit 3 = Black Queen Side Rook (Black Long Castle)
    		 */
    		unsigned char EnPassantPhantomPawn;
    		/* A value stored in bits 0-6 represents a square of the board (0-63) assuming that 0 is the White Queen Side
    		 * Rook, going left to right and then down the board.
    		 * bit 7 is a true/false flag indicating the pressence of the en'Passant Phantom Pawn, if this bit is false,
    		 * bits 0-6 are unused.
    		 */
    	};
    public:
    	BoardFactory() { Clear(); };
    	~BoardFactory() { Destroy(); };
    	void Clear();
    	void Destroy();
    	void* MakeNewBoard();
    	bool Create();
    	bool DestroyBoard(BoardFactory::BitBoard* Board);
    	bool MakeDefaultSetup (BoardFactory::BitBoard* Board);
    	unsigned long long GetSquareBit(unsigned char Square);
    	unsigned long long GetInvertedSquareBit(unsigned char Square);
    	unsigned long long GetBitBoard(BoardFactory::BitBoard* Board, unsigned char PieceType);
    	unsigned char GetCastlingFlags(BoardFactory::BitBoard* Board);
    	unsigned char GetPhantomPawnInfo(BoardFactory::BitBoard* Board);
    };
    BoardFactory.cpp
    Code:
    #include "BoardFactory.h"
    void BoardFactory::Clear()
    {
    	return;
    }
    void BoardFactory::Destroy()
    {
    	return;
    }
    void* BoardFactory::MakeNewBoard()
    {
    	BoardFactory::BitBoard* data=new BoardFactory::BitBoard();
    	return &data;
    }
    bool BoardFactory::Create()
    {
    	return true;
    }
    bool BoardFactory::DestroyBoard(BoardFactory::BitBoard* Board)
    {
    	delete Board;
    	return true;
    }
    bool BoardFactory::MakeDefaultSetup(BoardFactory::BitBoard* Board)
    {
    	Board->WhitePawns=65280ULL;
    	Board->WhiteKnights=66ULL;
    	Board->WhiteBishops=36ULL;
    	Board->WhiteRooks=129ULL;
    	Board->WhiteQueens=16ULL;
    	Board->WhiteKing=8ULL;
    	Board->WhitePieces=65535ULL;
    	Board->BlackPawns=71776119061217280ULL;
    	Board->BlackKnights=4755801206503243776ULL;
    	Board->BlackBishops=2594073385365405696ULL;
    	Board->BlackRooks=9295429630892703744ULL;
    	Board->BlackQueens=1152921504606846976ULL;
    	Board->BlackKing=576460752303423488ULL;
    	Board->BlackPieces=18446462598732840960ULL;
    	Board->CastlingFlags=15;
    	Board->EnPassantPhantomPawn=0;
    	return true;
    }
    unsigned long long BoardFactory::GetSquareBit(unsigned char Square)
    {
    	if (Square>63) return 0ULL;
    	return 1ULL<<Square;
    }
    unsigned long long BoardFactory::GetInvertedSquareBit(unsigned char Square)
    {
    	if (Square>63) return 18446744073709551615ULL;
    	return 18446744073709551615ULL-(1ULL<<Square);
    }
    unsigned long long BoardFactory::GetBitBoard(BoardFactory::BitBoard *Board, unsigned char PieceType)
    {
    	switch (PieceType)
    	{
    	case 0:
    		return Board->WhitePawns;
    	case 1:
    		return Board->WhiteKnights;
    	case 2:
    		return Board->WhiteBishops;
    	case 3:
    		return Board->WhiteRooks;
    	case 4:
    		return Board->WhiteQueens;
    	case 5:
    		return Board->WhiteKing;
    	case 6:
    		return Board->WhitePieces;
    	case 7:
    		return Board->BlackPawns;
    	case 8:
    		return Board->BlackKnights;
    	case 9:
    		return Board->BlackBishops;
    	case 10:
    		return Board->BlackRooks;
    	case 11:
    		return Board->BlackQueens;
    	case 12:
    		return Board->BlackKing;
    	case 13:
    		return Board->BlackPieces;
    	default:
    		return 0ULL;
    	}
    }
    unsigned char BoardFactory::GetCastlingFlags(BoardFactory::BitBoard *Board)
    {
    	return Board->CastlingFlags;
    }
    unsigned char BoardFactory::GetPhantomPawnInfo(BoardFactory::BitBoard *Board)
    {
    	return Board->EnPassantPhantomPawn;
    }
    This all looks good, except....
    Code:
    void* BoardFactory::MakeNewBoard()
    {
    	BoardFactory::BitBoard* data=new BoardFactory::BitBoard();
    	return &data;
    }
    The variable data is a temporary variable, and the data will be wiped by trash collector just after the pointer is returned.
    Is there a way that I can use <vector> or something to just be able to keep adding these boards to the heap? Anything I should know about trash?

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Hold your horses, here.
    First off, why do you need this "insane" optimization in the first place? Unless speed is really necessary, I would recommend clarify of code before obfuscation.
    Secondly, you have no need to much around with new and delete. Just place this struct inside your class and you're done. It will be destroyed automatically.
    I would also recommend you read up a little about dynamic memory allocation if you intend to use it, since you aren't grasping the concepts correctly.
    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.

  4. #4
    Registered User
    Join Date
    May 2010
    Location
    Australia
    Posts
    10
    Quote Originally Posted by Elysia View Post
    Hold your horses, here.
    First off, why do you need this "insane" optimization in the first place? Unless speed is really necessary, I would recommend clarify of code before obfuscation.
    I do feel speed on this process is neeeded, at the current point in time I really have no idea how often this routine will be called, but I'm kinda thinking it will be intensive...
    Quote Originally Posted by Elysia View Post
    Secondly, you have no need to much around with new and delete. Just place this struct inside your class and you're done. It will be destroyed automatically.
    Thank you for your answer, I've been having a few mental hurdles when it comes to this stuff, since I've been under the impression you need to destroy everything with C++
    Quote Originally Posted by Elysia View Post
    I would also recommend you read up a little about dynamic memory allocation if you intend to use it, since you aren't grasping the concepts correctly.
    Just trying my luck, any recomended reading perhaps?

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by feeder74 View Post
    I do feel speed on this process is neeeded, at the current point in time I really have no idea how often this routine will be called, but I'm kinda thinking it will be intensive...
    This is called premature optimization and is a bad thing.
    Write the routine first without the extreme need for speed and if it turns out later that your program is slow, profile it, and find out where the performance hit is. Then fix that.
    Otherwise you are shooting yourself in the foot and making things more difficult for yourself.

    Thank you for your answer, I've been having a few mental hurdles when it comes to this stuff, since I've been under the impression you need to destroy everything with C++
    Well, put it this way:
    In C++, there are two storage area: the heap and the stack. When you use the new operator, things are placed on the heap. Everything that is placed on the heap is never destroyed automatically and have to be destroyed manually. This is where delete comes in.
    For everything else, it's placed on the stack. Everything on the stack is cleaned up automatically, so you don't have to do anything. This also brings up the concept of RIIA. When an object of the stack goes out of scope, its destructor is called, and from there you can do some interesting stuff, like freeing a pointer. That would guarantee that when the object is destroyed, it would free that pointer. And you don't have to worry about destroying that object since it will automatically be destroyed at the end of the function.

    Just trying my luck, any recomended reading perhaps?
    I've always liked Accelerated C++. You could try that.
    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.

  6. #6
    Registered User
    Join Date
    Mar 2010
    Posts
    68
    I too would agree with the above posters. There is a programming convention that says do not optimize your code before you have written it out. First, write your code out expressing your idea as much as possible. Afterwords, look for places to optimize. The reason is because what you are doing right now, may not the correct way you want to optimize this program and you may end up wasting your time.

  7. #7
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Allocating things dynamically is generally considered a rather slow operation. Also, since different board representations may end up being far apart in memory, accessing those may also be slower. That in addition to working with dynamic allocations being more complicated.

    So you should first start out with normal stack objects and if it turns out to be problematic (e.g overflows the stack if you create tons of those in recursion/make enormous arrays of those), then you can put lots of them in dynamic memory (e.g in a std::vector).
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Elysia View Post
    Hold your horses, here.
    First off, why do you need this "insane" optimization in the first place? Unless speed is really necessary, I would recommend clarify of code before obfuscation.
    Bitboards are standard in chess systems. If somebody is confused by it, that person should not be programming chess. I'd go so far as to say that if you're not using bitboards, you'll be laughed out of town. There are so many advantages to using bitboards that I don't even know where to start.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by brewbuck View Post
    Bitboards are standard in chess systems.
    That's not what I was referring to, though. I was referring to the fact that the OP seems to have an intention of trying to over-optimize code where there may be little need. When "super" optimizing code, it often becomes more obscure and difficult to read and analyze.
    I merely pointed out that that should be avoided.
    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.

  10. #10
    Registered User
    Join Date
    May 2010
    Location
    Australia
    Posts
    10
    Thx Elysia, I'll keep it in mind, I have a fair bit of time with this, and am spending most of it loosely researching when I'm not buisy with other things, right now, I'm in the process of trying to make a simple BoardDevice, the evolved version of the above code, I'm not intending to stepping away from this class till it is something I can be proud of though, so move list generation can wait a while longer.
    I have further questions though, like if I have multiple instances of a class made into objects (like via MyClass * MyObject=new MyClass() ), will I have multiple instances of the code and the data in memory? If so, should I try to seperate my data Classes from my Code as I strive to perfect this BoardDevice class?
    The code for the *.cpp portion is now starting to look like this... (jfyi)
    Code:
    /* BoardDevice.cpp
     * V0.1.0 Written by Daniel Jeremiah O'Neill.
     * This version compleated at 3:20AM GMT+10 Wednesday 5th May 2010.
     * Functions as a chess board with any legal chess pieces on it, does no error
     * checking, any configuration is possible, multiple kings per side, more than
     * 8 pawns, etc... Allows a variety of manipulative functions, as well as
     * a usefull generate hash function, by which a board may be stored or 
     * identified.
     */
    #include "BoardDevice.h"
    /* BoardDevice::Clear()
     * Places the board in a state of null. There are no pieces on the board in this
     * state, the castling flags are set to false, that is, castling is turned off,
     * and the en'Passant pawn is set to cleared - no en'Passant phantom.
     * Further more, it wipes the board hash data clean, setting all values there
     * to null as well.
     */
    void BoardDevice::Clear()
    {
    	BoardDevice::WhitePawns=BoardDevice::BlackPawns=0ULL;
    	BoardDevice::WhiteKnights=BoardDevice::BlackKnights=0ULL;
    	BoardDevice::WhiteBishops=BoardDevice::BlackBishops=0ULL;
    	BoardDevice::WhiteRooks=BoardDevice::BlackRooks=0ULL;
    	BoardDevice::WhiteQueens=BoardDevice::BlackQueens=0ULL;
    	BoardDevice::WhiteKing=BoardDevice::BlackKing=0ULL;
    	BoardDevice::WhitePieces=BoardDevice::BlackPieces=0ULL;
    	BoardDevice::EnPassantPhantomPawn=BoardDevice::CastlingFlags=0;
    	for (int i=0;i<34;i++) BoardDevice::BoardHash[i]=0;
    }
    /* BoardDevice::Destroy()
     * For the destruction of this class only! Destroys the only array in memory,
     * that is the board hash data.
     */
    void BoardDevice::Destroy()
    {
    	delete[] &BoardHash;
    }
    /* BoardDevice::Reset()
     * Resets the board and places it into a new game configuration. 8 pawns are
     * places along the rank that is one square in from the current colors side,
     * rooks are placed in all corners, knights next to them, bishops next to
     * knights, a king on the right, and a queen on the left of the two vacant
     * squares that remain. The castling flags are set to 1111, all true, that
     * is, all castle moves, short and long for both colors, are enabled, the
     * en'Passant phantom pawn is set to cleared - no en'Passant phnatom.
     * When this is done, Reset() returns a true value in the bool.
     */
    bool BoardDevice::Reset()
    {
    	BoardDevice::WhitePawns=65280ULL;
    	BoardDevice::WhiteKnights=66ULL;
    	BoardDevice::WhiteBishops=36ULL;
    	BoardDevice::WhiteRooks=129ULL;
    	BoardDevice::WhiteQueens=16ULL;
    	BoardDevice::WhiteKing=8ULL;
    	BoardDevice::WhitePieces=65535ULL;
    	BoardDevice::BlackPawns=71776119061217280ULL;
    	BoardDevice::BlackKnights=4755801206503243776ULL;
    	BoardDevice::BlackBishops=2594073385365405696ULL;
    	BoardDevice::BlackRooks=9295429630892703744ULL;
    	BoardDevice::BlackQueens=1152921504606846976ULL;
    	BoardDevice::BlackKing=576460752303423488ULL;
    	BoardDevice::BlackPieces=18446462598732840960ULL;
    	BoardDevice::CastlingFlags=15;
    	BoardDevice::EnPassantPhantomPawn=0;
    	return true;
    }
    /* BoardDevice::TestPiece(unsigned char Square, unsigned char PieceType)
     * Tests square 'Square' to see if piece 'PieceType' is present, returns
     * true if it is, or false, indicating it is not, false may also indicate
     * that the input values are out of range, Square must be between 0 and
     * 63, while PieceType is shown on the table below.
     * +--------+--------------------------------------------------------------+
     * | Value  |  Piece Type                                                  |
     * +--------+--------------------------------------------------------------+
     * |      0 | White Pawn                                                   |
     * |      1 | White Knight                                                 |
     * |      2 | White Bishop                                                 |
     * |      3 | White Rook                                                   |
     * |      4 | White Queen                                                  |
     * |      5 | White King                                                   |
     * |      6 | White Piece                                                  |
     * |      7 | Black Pawn                                                   |
     * |      8 | Black Knight                                                 |
     * |      9 | Black Bishop                                                 |
     * |     10 | Black Rook                                                   |
     * |     11 | Black Queen                                                  |
     * |     12 | Black King                                                   |
     * |     13 | Black Piece                                                  |
     * +--------+--------------------------------------------------------------+
     */
    bool BoardDevice::TestPiece(unsigned char Square, unsigned char PieceType)
    {
    	switch(PieceType)
    	{
    	case 0:
    		if ((BoardDevice::WhitePawns&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 1:
    		if ((BoardDevice::WhiteKnights&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 2:
    		if ((BoardDevice::WhiteBishops&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 3:
    		if ((BoardDevice::WhiteRooks&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 4:
    		if ((BoardDevice::WhiteQueens&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 5:
    		if ((BoardDevice::WhiteKing&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 6:
    		if ((BoardDevice::WhitePieces&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 7:
    		if ((BoardDevice::BlackPawns&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 8:
    		if ((BoardDevice::BlackKnights&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 9:
    		if ((BoardDevice::BlackBishops&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 10:
    		if ((BoardDevice::BlackRooks&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 11:
    		if ((BoardDevice::BlackQueens&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 12:
    		if ((BoardDevice::BlackKing&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	case 13:
    		if ((BoardDevice::BlackPieces&BoardDevice::GetSquareBit(Square))!=0)
    			return true;
    		else
    			return false;
    	default:
    		return false;
    	}
    }
    /* BoardDevice::RemovePiece(unsigned char Square, unsigned char PieceType)
     * Removes a valid piece from the board, the piece must exist to be removed,
     * if it does not, RemovePiece(unsigned char Square, unsigned char PieceType)
     * returns a false value, indicating an error. After checking the input
     * variables for faults, the function attempts to alter data, after which it
     * returns true - success.
     * Square is a value between 0 and 63, any value outside this range will
     * cause the function to return false.
     * PieceType can be any of the values listed on the table below, any other
     * value will return false, indicating an error, no piece will be removed.
     * +--------+--------------------------------------------------------------+
     * | Value  |  Piece Type                                                  |
     * +--------+--------------------------------------------------------------+
     * |      0 | White Pawn                                                   |
     * |      1 | White Knight                                                 |
     * |      2 | White Bishop                                                 |
     * |      3 | White Rook                                                   |
     * |      4 | White Queen                                                  |
     * |      5 | White King                                                   |
     * |      6 | White Piece (Unused, trying to use this value will cause the |
     * |        | function to return false, indicating an error, no piece will |
     * |        | be removed.                                                  |
     * |      7 | Black Pawn                                                   |
     * |      8 | Black Knight                                                 |
     * |      9 | Black Bishop                                                 |
     * |     10 | Black Rook                                                   |
     * |     11 | Black Queen                                                  |
     * |     12 | Black King                                                   |
     * |     13 | Black Piece (Unused, trying to use this value will cause the |
     * |        | function to return false, indicating an error, no piece will |
     * |        | be removed.                                                  |
     * +--------+--------------------------------------------------------------+
     */
    bool BoardDevice::RemovePiece(unsigned char Square, unsigned char PieceType)
    {
    	if (Square>63) return false;
    	switch (PieceType)
    	{
    	case 0:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::WhitePawns&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 1:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::WhiteKnights&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 2:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::WhiteBishops&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 3:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::WhiteRooks&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 4:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::WhiteQueens&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 5:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::WhiteKing&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 7:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::BlackPawns&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 8:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::BlackKnights&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 9:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::BlackBishops&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 10:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::BlackRooks&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 11:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::BlackQueens&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	case 12:
    		if (!BoardDevice::TestPiece(Square, PieceType)) return false;
    		BoardDevice::BlackKing&=BoardDevice::GetInvertedSquareBit(Square);
    		BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
    		break;
    	default:
    		return false;
    	}
    	return true;
    }
    /* BoardDevice::PlacePiece(unsigned char Square, unsigned char PieceType)
     * Places a valid piece on the board, the square must be empty for the piece
     * to be placed, if it is not, PlacePiece(unsigned char Square, unsigned
     * char PieceType) returns a false value, indicating an error. After 
     * checking input values for faults, the function attempts to alter data,
     * adter which it reutrns true - success.
     * Square is a value between 0 and 63, any value outside this range will
     * cause the function to return false.
     * PieceType can be any of the values listed on the table below, any other
     * value will return false, indicating an error, no piece will be removed.
     * +--------+--------------------------------------------------------------+
     * | Value  |  Piece Type                                                  |
     * +--------+--------------------------------------------------------------+
     * |      0 | White Pawn                                                   |
     * |      1 | White Knight                                                 |
     * |      2 | White Bishop                                                 |
     * |      3 | White Rook                                                   |
     * |      4 | White Queen                                                  |
     * |      5 | White King                                                   |
     * |      6 | White Piece (Unused, trying to use this value will cause the |
     * |        | function to return false, indicating an error, no piece will |
     * |        | be removed.                                                  |
     * |      7 | Black Pawn                                                   |
     * |      8 | Black Knight                                                 |
     * |      9 | Black Bishop                                                 |
     * |     10 | Black Rook                                                   |
     * |     11 | Black Queen                                                  |
     * |     12 | Black King                                                   |
     * |     13 | Black Piece (Unused, trying to use this value will cause the |
     * |        | function to return false, indicating an error, no piece will |
     * |        | be removed.                                                  |
     * +--------+--------------------------------------------------------------+
     */
    bool BoardDevice::PlacePiece(unsigned char Square, unsigned char PieceType)
    {
    	if (Square>64) return false;
    	switch (PieceType)
    	{
    	case 0:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::WhitePawns|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 1:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::WhiteKnights|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 2:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::WhiteBishops|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 3:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::WhiteRooks|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 4:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::WhiteQueens|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 5:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::WhiteKing|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 7:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::BlackPawns|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 8:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::BlackKnights|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 9:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::BlackBishops|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 10:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::BlackRooks|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 11:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::BlackQueens|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	case 12:
    		if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
    		BoardDevice::BlackKing|=BoardDevice::GetSquareBit(Square);
    		BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
    		break;
    	default:
    		return false;
    	}
    	return true;
    }
    /* BoardDevice::GetCastlingFlags()
     * Returns a value between 0000 and 1111, these flags in order from left to
     * right indicate the following castle moves are available if the flag is 1.
     * Black Long(Queen Side) Castle
     * Black Short(King Side) Castle
     * White Long(Queen Side) Castle
     * White Short(King Side) Castle
     */
    unsigned char BoardDevice::GetCastlingFlags()
    {
    	return BoardDevice::CastlingFlags;
    }
    /* BoardDevice::GetPhantomPawnInfo()
     * Returns a value of 0 in bit 7 if no en'Passant phantom pawn is present,
     * otherwise, if bit 7 is set to 1, bits 0-6 contain a value between 0 and
     * 63 indicating the square upon which it is preent. Optionally, and
     * uneeded, bit 8 may be set to 1 if the pawn is black, and 0 if the pawn
     * is white.
     */
    unsigned char BoardDevice::GetPhantomPawnInfo()
    {
    	return BoardDevice::EnPassantPhantomPawn;
    }
    /* BoardDevice::GetSquareBit(unsigned char Square)
     * Accepts a value between 0 and 63 indicating a sqaure on the chess board,
     * returns a value of 2 to the power of Square, or 0 on error.
     */
    unsigned long long BoardDevice::GetSquareBit(unsigned char Square)
    {
    	if (Square>63) return 0ULL;
    	return 1ULL<<Square;
    }
    /* BoardDevice::GetInvertedSquareBit(unsigned char Square)
     * Accepts a value between 0 and 63 indicating a sqaure on the chess board,
     * similar to GetSquareBit(unsigned char Square) this function returns a
     * a value where the flag is turned off, and all other flags are on.
     */
    unsigned long long BoardDevice::GetInvertedSquareBit(unsigned char Square)
    {
    	if (Square>63) return 18446744073709551615ULL;
    	return 18446744073709551615ULL-(1ULL<<Square);
    }
    /* BoardDevice::GetBitBoard(unsigned char PieceType)
     * This function returns a value of zero if the PieceType is out of range,
     * otherwise, it returns the associated BitBoard as shown on the table
     * below. The BitBoard contains a 0 flag when the square does not contain
     * a piece of the asociated type, and a 1 flag when it does.
     * +--------+--------------------------------------------------------------+
     * | Value  |  Piece Type                                                  |
     * +--------+--------------------------------------------------------------+
     * |      0 | White Pawn                                                   |
     * |      1 | White Knight                                                 |
     * |      2 | White Bishop                                                 |
     * |      3 | White Rook                                                   |
     * |      4 | White Queen                                                  |
     * |      5 | White King                                                   |
     * |      6 | White Piece                                                  |
     * |      7 | Black Pawn                                                   |
     * |      8 | Black Knight                                                 |
     * |      9 | Black Bishop                                                 |
     * |     10 | Black Rook                                                   |
     * |     11 | Black Queen                                                  |
     * |     12 | Black King                                                   |
     * |     13 | Black Piece                                                  |
     * +--------+--------------------------------------------------------------+
     */
    unsigned long long BoardDevice::GetBitBoard(unsigned char PieceType)
    {
    	switch (PieceType)
    	{
    	case 0:
    		return BoardDevice::WhitePawns;
    	case 1:
    		return BoardDevice::WhiteKnights;
    	case 2:
    		return BoardDevice::WhiteBishops;
    	case 3:
    		return BoardDevice::WhiteRooks;
    	case 4:
    		return BoardDevice::WhiteQueens;
    	case 5:
    		return BoardDevice::WhiteKing;
    	case 6:
    		return BoardDevice::WhitePieces;
    	case 7:
    		return BoardDevice::BlackPawns;
    	case 8:
    		return BoardDevice::BlackKnights;
    	case 9:
    		return BoardDevice::BlackBishops;
    	case 10:
    		return BoardDevice::BlackRooks;
    	case 11:
    		return BoardDevice::BlackQueens;
    	case 12:
    		return BoardDevice::BlackKing;
    	case 13:
    		return BoardDevice::BlackPieces;
    	default:
    		return 0ULL;
    	}
    }
    /* BoardDevice::GetBoardHash()
     * Returns a 34 byte hash indicating the current state of the board.
     * This hash functions as an ID for the current board state, only one
     * such value can exist per board configuration.
     */
    unsigned char* BoardDevice::GetBoardHash()
    {
    	for (unsigned char i=0;i<64;i++) BoardDevice::BoardHash[i]=0;
    	for (unsigned char i=0;i<32;i++)
    	{
    		if (BoardDevice::TestPiece(i*2,0)) BoardDevice::BoardHash[i]|=1;
    		if (BoardDevice::TestPiece(i*2+1,0)) BoardDevice::BoardHash[i]|=16;
    		if (BoardDevice::TestPiece(i*2,1)) BoardDevice::BoardHash[i]|=2;
    		if (BoardDevice::TestPiece(i*2+1,1)) BoardDevice::BoardHash[i]|=32;
    		if (BoardDevice::TestPiece(i*2,2)) BoardDevice::BoardHash[i]|=3;
    		if (BoardDevice::TestPiece(i*2+1,2)) BoardDevice::BoardHash[i]|=48;
    		if (BoardDevice::TestPiece(i*2,3)) BoardDevice::BoardHash[i]|=4;
    		if (BoardDevice::TestPiece(i*2+1,3)) BoardDevice::BoardHash[i]|=64;
    		if (BoardDevice::TestPiece(i*2,4)) BoardDevice::BoardHash[i]|=5;
    		if (BoardDevice::TestPiece(i*2+1,4)) BoardDevice::BoardHash[i]|=80;
    		if (BoardDevice::TestPiece(i*2,5)) BoardDevice::BoardHash[i]|=6;
    		if (BoardDevice::TestPiece(i*2+1,5)) BoardDevice::BoardHash[i]|=96;
    		if (BoardDevice::TestPiece(i*2,7)) BoardDevice::BoardHash[i]|=8;
    		if (BoardDevice::TestPiece(i*2+1,7)) BoardDevice::BoardHash[i]|=128;
    		if (BoardDevice::TestPiece(i*2,8)) BoardDevice::BoardHash[i]|=9;
    		if (BoardDevice::TestPiece(i*2+1,8)) BoardDevice::BoardHash[i]|=144;
    		if (BoardDevice::TestPiece(i*2,9)) BoardDevice::BoardHash[i]|=10;
    		if (BoardDevice::TestPiece(i*2+1,9)) BoardDevice::BoardHash[i]|=160;
    		if (BoardDevice::TestPiece(i*2,10)) BoardDevice::BoardHash[i]|=11;
    		if (BoardDevice::TestPiece(i*2+1,10)) BoardDevice::BoardHash[i]|=176;
    		if (BoardDevice::TestPiece(i*2,11)) BoardDevice::BoardHash[i]|=12;
    		if (BoardDevice::TestPiece(i*2+1,11)) BoardDevice::BoardHash[i]|=192;
    		if (BoardDevice::TestPiece(i*2,12)) BoardDevice::BoardHash[i]|=13;
    		if (BoardDevice::TestPiece(i*2+1,12)) BoardDevice::BoardHash[i]|=208;
    	}
    	BoardHash[32]=BoardDevice::GetCastlingFlags();
    	BoardHash[33]=BoardDevice::GetPhantomPawnInfo();
    	return BoardHash;
    }
    /* ToDo: Add a function that allows a Board to be setup from a hash value.
     */
    EDIT:I know its not perfect, like the testpiece() function could have break; instead of elses, with a final return false at the end, but I'm still working on this
    Last edited by feeder74; 05-04-2010 at 11:59 AM.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code is separate from data; thus if you make multiple copies of A which contains code, the code will not be duplicated. However, all the data that is associated with A naturally gets duplicated because that data contained in the class A is specific to a specific instance only.
    Also, try to avoid the new operator.
    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.

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Elysia View Post
    That's not what I was referring to, though. I was referring to the fact that the OP seems to have an intention of trying to over-optimize code where there may be little need.
    You're questioning the need to optimize a chess AI?

    You do realize that speed is so important in chess that it took a computer with 30 CPUs and 480 special-purpose chess processors to beat Gary Kasparov, right?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Like I said, write code first, optimize later.
    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.

  14. #14
    Registered User
    Join Date
    May 2010
    Location
    Australia
    Posts
    10
    Quote Originally Posted by Elysia View Post
    Also, try to avoid the new operator.
    I learnt assembly code years ago - back before the protected mode revolution, when I came back to programming I was lost, a friend put me onto C#, and you can't use that language without the new command, I got a gut load of C# and the hidden implementations of many aspects of .NET, and when I got a better understanding of all the changes that computer programming has gone through - I immediately embarked on learning C++, I admit it though, my passion is programming in Assembly, free from protected mode, possibly even interfacing with devices through the use of int xxh and the like. My intentions are to take a course in basic electronics, and advance my education to a point where I can start actually designing my own chipsets with unique psuedo-codes, one project (long term, but I'm working on it now) is to make a dedicated computer that serves the sole purpose of playing chess(purely as a hobby).

  15. #15
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Elysia View Post
    Like I said, write code first, optimize later.
    Translation: write something unacceptable, then throw it all away and do it right. Might as well skip that pointless first step.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Function call from another .c module
    By Ali.B in forum C Programming
    Replies: 14
    Last Post: 08-03-2009, 11:45 AM
  2. Can you check what is wrong with this code
    By Ron in forum C++ Programming
    Replies: 4
    Last Post: 08-01-2008, 10:59 PM
  3. [ANN] New script engine (Basic sintax)
    By MKTMK in forum C++ Programming
    Replies: 1
    Last Post: 11-01-2005, 10:28 AM
  4. what are your thoughts on visual basic?
    By orion- in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 09-22-2005, 04:28 AM