universal function for pawns.

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Emu*
Posts: 689
Joined: Mon Apr 28, 2008 9:47 am UTC
Location: Cardiff, UK
Contact:

Re: universal function for pawns.

Postby Emu* » Mon Oct 11, 2010 8:25 pm UTC

headprogrammingczar wrote:This isn't entirely on the topic, but your code doesn't handle En Passant.


Lol. I used that rule once, and got a rather pointy queen thrown at me.
Cosmologicon wrote:Emu* implemented a naive east-first strategy and ran it for an hour, producing results that rivaled many sophisticated strategies, visiting 614 cells. For this, Emu* is awarded Best Deterministic Algorithm!

User avatar
Zabaron
Posts: 113
Joined: Wed Jun 04, 2008 3:33 am UTC
Location: Georgia

Re: universal function for pawns.

Postby Zabaron » Mon Oct 11, 2010 8:28 pm UTC

the mishanator wrote:and i get this compile error: error: ‘class Piece’ has no member named ‘move’

That's because the Piece class doesn't have a move() function. What you want here is to make an empty move() function in your Piece class, and to override it in the subclasses. This behavior can be achieved with the 'virtual' keyword, i.e.

Code: Select all

class Piece {
...
public:
     virtual void move(/*some args here*/);
     ...
}


Then if you put a move() function with the same signature (that is, the same name, return type, and arguments) in the Pawn class, it will be called instead of Piece::move(), even if you call it through a Piece*.

Now that I've typed all of this, I realize you may not have learned about dynamic memory allocation yet, which this solution relies on. If you haven't covered the 'new' and 'delete' operators yet, then ignore this post.

-Zabaron
I love deadlines. I love that wooshing sound they make as they fly by. -Douglas Adams

bieber
Posts: 223
Joined: Thu Mar 13, 2008 12:13 am UTC

Re: universal function for pawns.

Postby bieber » Mon Oct 11, 2010 10:27 pm UTC

Oh, woops. Definitely leave out the "void"

User avatar
Emu*
Posts: 689
Joined: Mon Apr 28, 2008 9:47 am UTC
Location: Cardiff, UK
Contact:

Re: universal function for pawns.

Postby Emu* » Mon Oct 11, 2010 11:11 pm UTC

Java would probably be a better language to learn OO concepts in, then apply them to C++ later...
Cosmologicon wrote:Emu* implemented a naive east-first strategy and ran it for an hour, producing results that rivaled many sophisticated strategies, visiting 614 cells. For this, Emu* is awarded Best Deterministic Algorithm!

squareroot
Posts: 548
Joined: Tue Jan 12, 2010 1:04 am UTC
Contact:

Re: universal function for pawns.

Postby squareroot » Mon Oct 11, 2010 11:19 pm UTC

Jplus wrote:Actually, in a truly OO design it would be even better to give Pieces no knowledge at all about their position... because, afterall, the board is already keeping track of their positions. Same story for whether positions are occupied or not (if you do it like this, every piece will be keeping a private registry of which positions are occupied; not efficient and also error-prone!).


I'm not sure, but I would say the most OO design would be giving each piece knowledge of it's location; it would have bool move(int x,int y). The board would keep a list of all pieces. Of course, that's silly and inefficient, so we would almost certainly want to deviate from pure OOP and do what you suggested.
<signature content="" style="tag:html;" overused meta />
Good fucking job Will Yu, you found me - __ -

masher
Posts: 821
Joined: Tue Oct 23, 2007 11:07 pm UTC
Location: Melbourne, Australia

Re: universal function for pawns.

Postby masher » Tue Oct 12, 2010 1:03 am UTC

Jplus wrote:Actually, in a truly OO design it would be even better to give Pieces no knowledge at all about their position... because, afterall, the board is already keeping track of their positions. Same story for whether positions are occupied or not (if you do it like this, every piece will be keeping a private registry of which positions are occupied; not efficient and also error-prone!).


How then do we figure out how we can move a piece?

I'm just giving this a bash for fun (I'm just (trying) to make the pawns work for now)

My ChessBoard knows where all the ChessPieces are.
Each ChessPiece doesn't know where it is.

ChessBoard has a method:

Code: Select all

   public boolean move(int startRow, int startCol, int endRow, int endCol){
      return this.getPiece(startRow, startCol).move(endRow, endCol);
   }

which selects the ChessPiece at the start position and tells it to move to the end position.

How can I then check if it is a legal move for the ChessPiece? Currently, each ChessPiece (ie ChessPawn extends ChessPiece, ChessRook extends ChessPiece...) has its own implementation of the move method, but I'm buggered if I can figure out how to check back to the ChessBoard to ensure that I'm not moving through other ChessPieces, how to tell if the move is legal....

I originally started with each piece knowing where it is, but I'm trying your way of doing things, just to exercise my mind... I can do it when each ChessPiece knows where it is, but not this way...

bieber
Posts: 223
Joined: Thu Mar 13, 2008 12:13 am UTC

Re: universal function for pawns.

Postby bieber » Tue Oct 12, 2010 1:25 am UTC

masher wrote:
Jplus wrote:Actually, in a truly OO design it would be even better to give Pieces no knowledge at all about their position... because, afterall, the board is already keeping track of their positions. Same story for whether positions are occupied or not (if you do it like this, every piece will be keeping a private registry of which positions are occupied; not efficient and also error-prone!).


How then do we figure out how we can move a piece?

I'm just giving this a bash for fun (I'm just (trying) to make the pawns work for now)

My ChessBoard knows where all the ChessPieces are.
Each ChessPiece doesn't know where it is.

ChessBoard has a method:

Code: Select all

   public boolean move(int startRow, int startCol, int endRow, int endCol){
      return this.getPiece(startRow, startCol).move(endRow, endCol);
   }

which selects the ChessPiece at the start position and tells it to move to the end position.

How can I then check if it is a legal move for the ChessPiece? Currently, each ChessPiece (ie ChessPawn extends ChessPiece, ChessRook extends ChessPiece...) has its own implementation of the move method, but I'm buggered if I can figure out how to check back to the ChessBoard to ensure that I'm not moving through other ChessPieces, how to tell if the move is legal....

I originally started with each piece knowing where it is, but I'm trying your way of doing things, just to exercise my mind... I can do it when each ChessPiece knows where it is, but not this way...


Give the chess board this method

Code: Select all

bool move(Piece& startPos, int dx, int dy, bool checkPath = true); //dx and dy are relative coordinates, checkPath tells it whether to check for other pieces in the way

...and then the chess pieces' move methods can look like this

Code: Select all

virtual bool Rook::move(int dx, int dy)
{
    //Assuming each Piece is initialized with a reference to the board as parent
    return (dx == 0 || dy == 0) && parent.move(*this, dx, dy, false);
}

the mishanator
Posts: 209
Joined: Mon May 31, 2010 6:49 pm UTC

Re: universal function for pawns.

Postby the mishanator » Tue Oct 12, 2010 5:49 am UTC

i split it up like this:

Code: Select all

class Piece {
protected:
   int position[2];
   bool side;
   bool state;
   int occupied[8][8];
public:
   Piece();
   int getPositionX();
   int getPositionY();
   void kill();
   bool isAlive();
   int getOccupied(int x, int y);
   bool getSide();
};

class Pawn: public Piece {
public:
   Pawn(bool Side, int x, int y);
   void move(bool first, bool kill, int x, int y);
};
is this an okay thing to do?

Axidos
Posts: 167
Joined: Tue Jan 20, 2009 12:02 pm UTC
Location: trapped in a profile factory please send help

Re: universal function for pawns.

Postby Axidos » Tue Oct 12, 2010 7:10 am UTC

the mishanator wrote:i split it up like this:

Code: Select all

class Piece {
protected:
   int position[2];
   bool side;
   bool state;
   int occupied[8][8];
public:
   Piece();
   int getPositionX();
   int getPositionY();
   void kill();
   bool isAlive();
   int getOccupied(int x, int y);
   bool getSide();
};

class Pawn: public Piece {
public:
   Pawn(bool Side, int x, int y);
   void move(bool first, bool kill, int x, int y);
};
is this an okay thing to do?

occupied looks like a chess board that stores whether a spot on the board is occupied.

Given that there are 16 pieces, you are essentially duplicating the same data 16 times so each piece knows what's out there. The issue with data duplication is not wasted space so much as keeping all the data synchronised. Every piece essentially keeps track of the board now, and if any two pieces don't completely agree (e.g. one thinks this space is occupied, another doesn't) you're going to have bugs that are a pain to track down.

Basically, that's a pretty awful approach.

Create a board class and let it handle the board. The pieces don't need to know very much about the board at all.

the mishanator
Posts: 209
Joined: Mon May 31, 2010 6:49 pm UTC

Re: universal function for pawns.

Postby the mishanator » Tue Oct 12, 2010 7:15 am UTC

i dont think you see why i need that there. the thing is pieces that move more than one tile at a time need to loop through every tile to check if there is something there, the loops are in their move methods.

Axidos
Posts: 167
Joined: Tue Jan 20, 2009 12:02 pm UTC
Location: trapped in a profile factory please send help

Re: universal function for pawns.

Postby Axidos » Tue Oct 12, 2010 8:02 am UTC

Then I'd suggest these modifications:
1. Create a Board class which keeps track of all the spaces, etc.
2. Give a Piece a protected Board field. (e.g. protected: Board* board)
3. In any Piece's constructor, add an argument that allows it to be passed a reference to the Board object (not a new board object, just a reference to the single existing one).
4. Give the Board an isOccupied(int x, int y) method which states whether the space is occupied.
5. Have the piece call this method if it needs to know if a space is empty.

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: universal function for pawns.

Postby Jplus » Tue Oct 12, 2010 11:03 am UTC

This is what I was thinking of:
- Give the Piece base class a pure virtual member function possibleMoves which takes the currentPosition as an argument and returns a std::vector of the possible newPositions.
- Let every derived class, such as Pawn, define the possibleMoves function disregarding whether the new positions and intermediate positions are occupied. For examle, if you give a Pawn position (x, y) as argument, it will usually return {(x-1, y+1), (x, y+1), (x+1, y+1), (x, y+2)}, except when it has reached the other side of the board or when it is on one of the sides.
- Let the board keep a twodimensional array which maps every board position to a piece, as well as a linked list which maps every piece on the board to a position (so that's a two-sided lookup mechanism). This allows it to check whether target positions and intermediate positions are occupied.
- Give the board a member function movePiece that takes a pointer to a piece and a targetPosition. It takes the following steps:
  1. Look up the pointer in the pieces list with a linear search. If the piece is not in the list, do not move.
  2. Ask the piece what are its possibleMoves. If the newPositions do not include the targetPosition, do not move.
  3. Look up the targetPosition and all intermediate positions in the twodimensional array.
    • If the targetPosition is occupied by another piece from the same player, do not move.
    • If an intermediate position is occupied, do not move (horse jumps will not generate any intermediate positions if you restrict the intermediate position detection to straight lines and 45˚ diagonals).
    • If the targetPosition is occupied by a piece from the opponent, perform the move and capture the opponent's piece under supervision of the rules object (some moves are check; rules object may block the move afterall).
    • If none of these positions is occupied, perform the move under supervision of the rules object (Pawns can only go diagonal if it is a capture, sometimes moving to an empty position is an en passent capture, some moves are check).
  4. Return a report on what has been done.

Edit: several additions and some more markup.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

Axidos
Posts: 167
Joined: Tue Jan 20, 2009 12:02 pm UTC
Location: trapped in a profile factory please send help

Re: universal function for pawns.

Postby Axidos » Tue Oct 12, 2010 11:01 pm UTC

That is loads better than what I said. I wasn't happy with my reference pass at all.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 6 guests