Home
Fractals
Tutorials
Books
Archive
My blog
My LinkedIn Profile

BOOKS i'm reading

Napoleon Hill Keys to Success: The 17 Principles of Personal Achievement, Napoleon Hill, ISBN: 978-0452272811
The 4-Hour Workweek: Escape 9-5, Live Anywhere, and Join the New Rich (Expanded and Updated), Timothy Ferriss, ISBN: 978-0307465351
The Fountainhead, Ayn Rand, ISBN: 0452273331

/*
 * Module ID: chess.h
 * Titre    : Declaration de classes pour le jeu d'echec
 *
 * Auteur   : Olivier Langlois <olivier@olivierlanglois.net>
 * Date     : 4 Fevrier 1998
 *
 */

#ifndef _CHESS_H_
#define _CHESS_H_

#include "collect/idlist.h"
#include <iostream>


/*
 * Definitions
 */
#define NUMROW 8
#define NUMCOL 8

/*
 * Declarations partielles
 */
class ChessBoard;
class Column;
class ChessCase;

class GamePiece
{
  private:
  // Position de la piece.
  ChessCase *position;

  public:
  GamePiece() : dx(NULL), dy(NULL), position(NULL) {}
  GamePiece( ChessCase *Case ) : dx(NULL), dy(NULL), position(Case) {}
  virtual ~GamePiece() = 0;

  /*
   * Fonctions Setters
   */
  void setPos( ChessCase *pos ) { position = pos; }

  /*
   * A l'origine, les fonctions visit*() avaient tous le nom visit.
   * Tant qu'il n'existe pas de classe derivee qui override aucune de ces
   * fonctions cela ne cause aucun probleme puisque le compilateur performe un
   * 'name mangling' a partir du nom ET des parametres.
   * Cependant, des qu'une classe possede une fonction qui override une des
   * fonctions visit*, elle cache les autres.
   */
  virtual void visitCase( ChessCase &Case );
  virtual void visitCol( Column &col );
  virtual void visitBoard( ChessBoard &board );

  protected:
     /*
      * Variables qui definit les deplacements possibles de la piece.
      */
     int numMove;
     int *dx, *dy;
};

class Knight : public GamePiece
{
  public:
     Knight() {init();}
     Knight( ChessCase *initialPos ) { init(); setPos(initialPos); }
     ~Knight();

  private:
     void init(void);
};

class ChessCase : public IsvDlink
{
  private:
     // Piece presente sur la case.
     GamePiece  *presentPiece;

  protected:
     ChessBoard *Board;

     /*
      * La presence de la position dans cette classe peut sembler redondante
      * puisqu'elle doit etre connue pour atteindre la case. Cependant, lorsque
      * l'on desire faire interagir la case avec une piece, les objets doivent
      * avoir un moyen d'acceder a cette information. Cela aurrait pu etre
      * accompli de d'autres facons:
      *
      * 1 - Passer la position aux fonctions necessitant cette information
      *
      * 2 - La position aurrait pu etre contenue dans les objets de pieces
      *     (Mauvaise idee car elle aurrait du etre ajustee a chaque
      *      deplacement)
      *
      * En conclusion, la presence de la position dans la classe ChessCase
      * semble etre la meilleure solution car elle necessite qu'une seule
      * initialisation puisqu'il est tres peu probable que les cases ait a se
      * deplacer.
      */
     int x, y;

  public:
  /*
   * Les valeurs par defaut de x & y sont choisies loin des coordonnees du
   * jeu de sorte que si jamais par erreur une Piece tentait de se deplacer a
   * partir d'une case non-initialisee qu'il soit impossible pour n'importe
   * quel (dx,dy) que la piece se retrouve sur le Chessboard.
   */
  ChessCase() : presentPiece(NULL), x(-256), y(-256) {}

  /*
   * Ce constructeur a peu de chance d'etre utilise frequemment car il est
   * anticipe que les objets seront construit en array la majorite du temps,
   * situation ou le constructeur par defaut est appelle.
   */
  ChessCase( int new_x, int new_y, GamePiece *piece = NULL )
  : x(new_x), y(new_y), presentPiece(piece) {}
  virtual ~ChessCase() {}

  virtual void init( void ) {}
  virtual void print( ostream &os ) {}

  // Fonctions Setters
  void setBoard( ChessBoard *cb )   { Board = cb; }
  void setPiece( GamePiece *piece ) { presentPiece = piece; }
  void setPosition( int new_x, int new_y ) { x = new_x; y = new_y; }

  // Fonctions Getters
  void getPosition( int &xRef, int &yRef ) { xRef = x; yRef = y; }

  virtual void accept( GamePiece &piece )
  { piece.visitCase(*this); }
};


/*
 * La classe Column permet de creer l'operateur [Column][Row] pour la classe
 * ChessBoard.
 */
class Column : public IsvDlink
{
  public:
     Column();
     virtual ~Column()   {}
     ChessCase &operator[](int i)
     { return *dynamic_cast<ChessCase *>(ChessCases[i]); }

    virtual void print( ostream &os, int y = -1 );

     virtual void accept( GamePiece &piece )
     { piece.visitCol(*this); }

  protected:
     friend class ChessBoard;
     /*
      * ChessCases est alloue dynamiquement, ce qui permet eventuellement de
      * remplacer ChessCases par des objets d'une classe derivee de ChessCase.
      */
//   ChessCase *ChessCases;
     /*
      * Une liste a du etre utilisee pour contenir les cases car un pointeur
      * de classe ne peut avoir une reference correcte sur une chaine d'objets
      * d'une classe derivee.
      */
      IDList ChessCases;

     /*
      * Ce constructeur doit etre utilise par les classes derivee de Column
      * qui doivent assigner une des objets d'un classe derivee de ChessCase
      * a ChessCases.
      */
     Column(int) {}
     virtual void initCases( int x, ChessBoard *cb );
};

class ChessBoard
{
  public:
     /*
      * Il est important d'appeler initColumns() apres l'appel du constructeur
      * Cela ne peut pas etre fait a l'interieur du constructeur car l'appel
      * de fonctions virtuelles a l'interieur de constructeur est deconseille.
      */
     ChessBoard();
     virtual ~ChessBoard() {}
     Column &operator[](int i)
     { return *dynamic_cast<Column *>(columns[i]); }

     virtual void initColumns( void );
     virtual void print( ostream &os );

/******************************************************************************
 *
 * Nom       : accept
 *
 * Utilite   : Recoit une piece.
 *
 * Parametres:
 *     piece   (GamePiece &) Piece a deplacer.
 *
 * Valeur de retour: Aucune.
 *
 ****************************************************************************/
     virtual void accept( GamePiece &piece )
     { piece.visitBoard(*this); }

  protected:
     /*
      * columns est alloue dynamiquement, ce qui permet eventuellement de
      * remplacer columns par des objets d'une classe derivee de Column.
      */
//   Column *columns;
     /*
      * Une liste a du etre utilisee pour contenir les cases car un pointeur
      * de classe ne peut avoir une reference correcte sur une chaine d'objets
      * d'une classe derivee.
      */
      IDList columns;

     /*
      * Ce constructeur doit etre utilise par les classes derivee de ChessBoard
      * qui doivent assigner des objets d'un classe derivee de Column
      * a columns.
      */
     ChessBoard(int) {}
};

ostream &operator <<(
            ostream &os,
            ChessBoard &s
            );

ostream &operator <<(
            ostream &os,
            ChessCase &s
            );

#endif /* _CHESS_H_ */

Home :: Fractals :: Tutorials :: Books :: Archive :: My blog :: My LinkedIn Profile :: Contact