Capture Piece Help

Member
Posts: 102
Joined: 2005.01
Post: #1
I am writing a small desktop game played on a 4x6 game board (4 high 6 across)

each team has 4 characters moving in opposite directions the characters move one space at a time, if the enemy piece is in their way, they jump over it. I already have this all done and the edge of map stuff fixed so they dont run off into empty space. the way the game runs is by the array:

board[4][6]

when you click a square it edits the array depending on what you clicked, 0 is empty space, 1 is a character that started on the left and 2 is a character that started on the right, then it runs through them and draws them one by one. The current rules make the game extremly inbalanced in the direction of the player who goes first, to level this i want to add capturing. where if a chacacter is touching more than one enemy piece it is sent all the way to its own wall, but if you move into touching more than one enemy it isnt taken. here is the ineffective code so far:


Code:
- (void)calculateMoveForRow:(int)row column:(int)column
{
    //emtpy column testing varialbes
    int testColumnOneAhead;
    int testColumnTwoAhead;
    //variables that say where the new piece is
    int newRow;
    int newCol;
    //whose piece
    whosePiece = [self boardValueAtRow:row column:column];
    //depending on whose turn
    switch (whosePiece)    {
        case 1:
            //testing moves definitions
            testColumnOneAhead = column + 1;
            testColumnTwoAhead = column + 2;
            if (board[row][testColumnOneAhead] == 0)    {
                //can move one forward
                board[row][testColumnOneAhead] = 1;
                newRow = row;
                newCol = testColumnOneAhead;
                //clear old place
                board[row][column] = 0;
            }
            else if (board[row][testColumnTwoAhead] == 0)    {
                //jump
                //refil the new space
                board[row][testColumnTwoAhead] = 1;
                newRow = row;
                newCol = testColumnTwoAhead;
                //clear old
                board[row][column] = 0;
            }
            break;
        case 2:
            //testing moves definitions
            testColumnOneAhead = column - 1;
            testColumnTwoAhead = column - 2;
            if (board[row][testColumnOneAhead] == 0)    {
                //can move one forward
                board[row][testColumnOneAhead] = 2;
                newRow = row;
                newCol = testColumnOneAhead;
                //clear old place
                board[row][column] = 0;
            }
            else if (board[row][testColumnTwoAhead] == 0)    {
                //jump
                //refil the new space
                board[row][testColumnTwoAhead] = 2;
                newRow = row;
                newCol = testColumnTwoAhead;
                //clear old
                board[row][column] = 0;
            }
        break;
    }
    [self captureRow:newRow col:NewCol];
    [self setNeedsDisplay:YES];
    [self endCheck];
}

- (void)captureRow:(int)row col:(int)col
{
    int threat;
    switch (whosePiece)    {
        case 1:
            break;
        case 2:
            break;
    }
}

basicaly the input row and column at the very top are what row and column the player clicked.
whosePiece is whose turn it is

any help?
Quote this message in a reply
Member
Posts: 102
Joined: 2005.01
Post: #2
ok i gave up on those rules, so the new capture rules are if you form a diagonal line of tow or more characters pointing at an enemy piece the enemy piece goes back to its wall.

Code:
- (void)captureRow:(int)row col:(int)col
{
    switch (whosePiece)    {
        case 1:
            if (board[row+1][col+1] == 1 && board[row+2][col+2] == 2)    {
                //capture up 2 and right two
                board[row+2][col+2] = 0;
                board[row+2][5] = 2;
            }
            if (board[row-1][col-1] == 1 && board[row-2][col-2] == 2)    {
                //capture up 2 and right two
                board[row-2][col-2] = 0;
                board[row-2][5] = 2;
            }
            if (board[row-1][col+1] == 1 && board[row-2][col+2] == 2)    {
                //capture up 2 and right two
                board[row-2][col+2] = 0;
                board[row-2][5] = 2;
            }
            if (board[row+1][col-1] == 1 && board[row+2][col-2] == 2)    {
                //capture up 2 and right two
                board[row+2][col-2] = 0;
                board[row+2][5] = 2;
            }
            break;
        case 2:
            if (board[row+1][col+1] == 2 && board[row+2][col+2] == 1)    {
                //capture up 2 and right two
                board[row+2][col+2] = 0;
                board[row+2][0] = 1;
            }
            if (board[row-1][col-1] == 2 && board[row-2][col-2] == 1)    {
                //capture up 2 and right two
                board[row-2][col-2] = 0;
                board[row-2][0] = 1;
            }
            if (board[row-1][col+1] == 2 && board[row-2][col+2] == 1)    {
                //capture up 2 and right two
                board[row-2][col+2] = 0;
                board[row-2][0] = 1;
            }
            if (board[row+1][col-1] == 2 && board[row+2][col-2] == 1)    {
                //capture up 2 and right two
                board[row+2][col-2] = 0;
                board[row+2][0] = 1;
            }
            break;
    }



it checks invisible places off the screen that seem to contain thiings every once in a while so how should i make it so it cant check off-screen areas?
Quote this message in a reply
KiroNeem
Unregistered
 
Post: #3
To me all it seems like you need to do is either write in protection code that makes sure that you don't check something outside of the array, or you can actually extend the array on all sides so you buffer it from ever looking out of the array
Quote this message in a reply
ilovetoast
Unregistered
 
Post: #4
Have you considered using a different data structure for your game board, i.e., something analagous to the bitboards used for chess programming? A structure of that nature might help you to address the issue of illegal captures/moves.

Using bitboards in chess you could answer the question "Can the Black queen capture a White rook?", or any number of other similar inquiries by:

1) Load the bitboard for the Black queen position.
2) Use that bitboard to index the dictionary of bitboards for squares attacked by queens.
3) Logical-AND that board with the one for White rook positions. If the result is non-zero, then the Black queen could capture one/both of the White rooks.

This type of data structure might help solve your problems.... or they might just complicate the rest of your code. There's alot of good, detailed info out on the net on bitboards that you might find to be worth looking at.

toast is good
Quote this message in a reply
Member
Posts: 102
Joined: 2005.01
Post: #5
should i just google for bitboard? or is there a good place for learning that?
this is my first game... ever, so i just ransomly did stuff that seemed like a good idea, like my horribly ineffective array
Quote this message in a reply
ilovetoast
Unregistered
 
Post: #6
From my listing of sources of bitboard information:
  • Online Technical Papers of Dr. Robert Hyatt (UAB), the creator of the Crafty chess engine.
    http://www.cis.uab.edu/hyatt/pubs.html
    All of the papers are excellent background reading, but the first two on the list are probably the most appropriate for your project. The first one is Chess Program Board Representations, which gives a good overview on different data structures, including bitboards. The second one is Rotated Bitmaps, which discusses a critical theoretical advance in the generation of pseudo-legal moves from bitboards.
  • Crafty chess engine source code
    http://www.crafty-chess.com/
    In the downloads section, you will find the complete source code of many of the more recent versions of the Crafty chess engine. The program is basically entirely written in ANSI-C and will compile on a Mac (at least it does for me). Note that I have not been able to get the default books (chess term for established opening move sequences) to work correctly, however by downloading any of the user books and following the Crafty manual instruction I was able to make my own books. If you need assistance in any of these areas, I can post the specfic steps I followed. It runs as a terminal app BTW.
  • DarkThought web pages, a chess engine created by Dr. Ernst Heinz (MIT).
    http://supertech.lcs.mit.edu/~heinz/dt/
    This site has an extensive discussion of the DarkThought engine, which uses bitboards like Crafty. While it does not have much general information, it does have two interesting pages discussing its bitboard engine, including one on the implementation and one on rotated bitboards. These pages are heavily footnoted, and give the citations of the seminal offline materials published in this area.

Those three sites should give you a solid background on bitboards and their usage, and hopefully, help you to decide whether or not they could be adapted to your game. I have found them to be very fast and relatively staightforward to use (that said, rotated bitboards, particularly the 45 degree rotations, took me awhile to get my head around programatically and can be a bit tricky).

Useful terms to search on might include:
bitboard
bitmap chess
KAISSA <-- the original reasearchers in the Soviet Union who first came up with bitboards, sort of the Popov of the bitboard as it where (the Marconi of the bitboard would be the Northwestern team who independently came up with the same idea a decade or so later -- the Soviets had kept the idea to themselves as it was the height of the cold war)

Hope that helps,

toast for lunch
Quote this message in a reply
Member
Posts: 184
Joined: 2004.07
Post: #7
Seriously, if this is your first game you really should not be bothering with anything that complex.

I think the way you're doing it with arrays is fine... like Kiro said, you just need more debugging information to help you, such as asserts to make sure you're not trying to write or read memory outside of your array.

You can write wrappers for board[x][y] such as getboard(x,y) and setboard(x,y) and then inside these functions, make sure your x and y are in bounds.
Quote this message in a reply
ilovetoast
Unregistered
 
Post: #8
I agree with phydreaux that this may be more complex than you are interested in for this project. That being said, once you understand bitboards you can do away with the board array, the getters/setters, the a priori bound checks, and likely any "board" objects. In place of all that you'll have a line or two of bitwise operations and a list of predefined bitboards.

IMHO, it might come down to what this project is to you. Is it just a first go at a board game, basically a practive project? Or, is it the first version of something you hope to market/expand? Or perhaps its practice/introduction for a larger board game project you have in mind? I think how you answer those questions might help decide whether to take the time and effort to learn about bitboards. Make no mistake, bitboards are likely the "best" implementation, but using them might be analagous to going after a fly with a tank.

A wise man once said, when all you have is a hammer, everything starts to look like a nail. Wink

toast with cheese and ham
Quote this message in a reply
Member
Posts: 102
Joined: 2005.01
Post: #9
This is just a practice project, i have made a few other "board game" type things such as a coin puzzle in which each space was giving its own int variable, therre were only 5 so it wasn't too bad but this is the first with an array, so i could rewrite the same game but with different capture rules and bitboards instead.

anyway here is my accual drawing to the view from the array method.
how can i make it "effective" this was pathetic but i couldn't think of anything else


Code:
- (void)drawArray
{
    NSRect modal;
    modal.origin = NSZeroPoint;
    
    //top row for good guys
    holderImage = gTop;
    if (board[1][1] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:s fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[1][2] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:t fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[1][3] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:u fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[1][4] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:v fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[1][5] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:w fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[1][6] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:x fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    
    
    //top mid row for good guys
    holderImage = gMidTop;
    if (board[2][1] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:m fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[2][2] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:n fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[2][3] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:o fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[2][4] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:p fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[2][5] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:q fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[2][6] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:r fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    
    
    //bottom mid row for good guys
    holderImage = gMidBottom;
    if (board[3][1] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:g fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[3][2] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:h fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[3][3] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:i fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[3][4] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:j fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[3][5] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:k fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[3][6] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:l fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    
    //bottom row for good guys
    holderImage = gBottom;
    if (board[4][1] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:a fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[4][2] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:b fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[4][3] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:c fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[4][4] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:d fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[4][5] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:e fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[4][6] == 1)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:f fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    
    
    
    
    //top row for bad guys
    holderImage = eTop;
    if (board[1][1] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:s fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[1][2] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:t fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[1][3] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:u fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[1][4] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:v fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[1][5] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:w fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[1][6] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:x fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    
    
    //top mid row for bad guys
    holderImage = eMidTop;
    if (board[2][1] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:m fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[2][2] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:n fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[2][3] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:o fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[2][4] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:p fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[2][5] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:q fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[2][6] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:r fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    
    
    //bottom mid row for bad guys
    holderImage = eMidBottom;
    if (board[3][1] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:g fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[3][2] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:h fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[3][3] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:i fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[3][4] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:j fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[3][5] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:k fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[3][6] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:l fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    
    //bottom row for bad guys
    holderImage = eBottom;
    if (board[4][1] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:a fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[4][2] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:b fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[4][3] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:c fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[4][4] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:d fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[4][5] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:e fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
    if (board[4][6] == 2)    {
        modal.size = [holderImage size];
        [holderImage drawInRect:f fromRect:modal operation:NSCompositeSourceOver fraction:1];
    }
}


the main thing i learned from this is never name the squares a, b, c, d, e...... that got me confused and i had to draw a diagram.

the game has 4 "bad guys" and 4 "good guys" a diffrent graphic for each of the four rows so the fist thing it does is set my holder image to the top good graphic and find the one on the top row. then draw it in the equivilant rect in the view. then it reloads the holder image and searches a row below that. i couldnt think if a loop that would reload holder image correctly.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Display capture questions Mark Levin 4 3,600 Jan 24, 2006 12:23 PM
Last Post: Fenris