/* This file is part of cardwords
   (c) 1999 Tobias Peters
   see file COPYING for the copyright terms.
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

// cardwords_dicbot_cardtablerequirement.hh

// Please notice the difference between CardWords_DicBot_CardTableRequirement
// and CardWords_DicBot_CardTableRequirements ! (Hint: the latter is plural)

/* This file defines the class CardWords_DicBot_CardTableRequirement. This
   class helps replacing CardWords_DicBot_CellValues and
   CardWords_DicBot_LetterFactors.

   An instance of CardWords_DicBot_CardTableRequirement should collect
   information about a single cell of a part of the card-table that is
   relevant to
   1 - finding words that can be layed in that part
   2 - finding the best arrangement of cards in that part
   .   and provide that information to interested parties in the form of class
   .   CardWords_DicBot_CardTableRequirements.

   The information considered relevant is:
   - the meaning of Cards that are already on the card-table
   - the word factor and letter factor of cells in that part
   - (bool) if there is an adjacent card next to a free cell that would lead
   .   to a side word
   - if the cell is free, a list of characters (meanings/CardWords_Chars) that
   .   are known not to be allowed there because of creating of invalid side
   .   words
*/

#ifndef  CARDWORDS_DICBOT_CARDTABLEREQUIREMENT_HH
#define  CARDWORDS_DICBOT_CARDTABLEREQUIREMENT_HH

#include "cardwords_direction.hh"
#include "cardwords_exceptions.hh"
#include "cardwords_dicbot_cardtable.hh"

class CardWords_DicBot_CardTableRequirement {
public:
  CardWords_DicBot_CardTableRequirement (const
                                         CardWords_DicBot_CardTableCell &,

                                         bool has_sideWord,

                                         CardWords_Direction dir);

  inline bool has_card(void) const;

  inline bool is_must(void) const {return has_card();} // Thats just the same.

  inline bool is_must_not(void) const; // Will only return true if the must
  //                                      not is not empty.
  
  inline CardWords_Char get_meaning(void)const; // Will return the meaning of
  //                       the card in this cell. If there is no card, it
  //                       will return CardWords_Char::blanko as this is an
  //                       invalid value for a card meaning on the card-table.

  inline CardWords_Char get_must (void) const { // Thats just the same.
    return get_meaning();
  }
  
  inline const CardWords_DicBot_CardTableMustNot * get_must_not(void) const;
  //   will return 0 if there is no must not or can return 0 if it is empty.
  
  // Check if the must_not allows char c, or if there is a card in this
  // cell, if that card's meaning is the same as c:
  inline bool test_allowed(CardWords_Char c) const;

  // Return the contained info:
  inline bool has_sideWord(void) const;
  inline int get_letterFactor(void) const;
  inline int get_wordFactor(void) const;

private:
  bool containsCard;
  bool mustNot_Empty;
  bool sideWord;
  int letter_factor;
  int word_factor;
  const CardWords_DicBot_CardTableMustNot *mustNot;
  CardWords_Char must;
public:
};

inline
CardWords_DicBot_CardTableRequirement::
CardWords_DicBot_CardTableRequirement (const
                                       CardWords_DicBot_CardTableCell &
                                       cell,

                                       bool has_sideWord,

                                       CardWords_Direction dir)
  : containsCard(cell.get_containsCard()),
    sideWord    (containsCard ? false : has_sideWord),
    letter_factor(containsCard ? 0 : cell.get_letter_factor()),
    word_factor  (containsCard ? 1 : cell.get_word_factor()),
    mustNot     (cell.get_must_not(dir))
{
  mustNot_Empty = containsCard || mustNot==0 || mustNot->empty();
  must = (containsCard
          ? cell.get_card()->get_meaning()
          : CardWords_Char::blanko
          );
}

inline bool CardWords_DicBot_CardTableRequirement::has_card(void) const
{
  return containsCard;
}

inline bool CardWords_DicBot_CardTableRequirement::is_must_not (void) const
  // Will only return true if the must not is not empty.
{
  return !containsCard && !mustNot_Empty;
}
  
inline CardWords_Char
CardWords_DicBot_CardTableRequirement::get_meaning (void) const
  // Will return the meaning of the card in this cell. If there is no card, it
  // will return CardWords_Char::blanko as this is an invalid value for a card
  // meaning on the card-table.
{
  return must;
}

inline const CardWords_DicBot_CardTableMustNot *
CardWords_DicBot_CardTableRequirement::get_must_not(void) const
{
  return mustNot;
}

// Check if the must_not allows char c, or if there is a card in this
// cell, if that card's meaning is the same as c:
inline bool
CardWords_DicBot_CardTableRequirement::test_allowed(CardWords_Char c) const
{
  if (containsCard == true) {
    return must == c;
  }
  return (mustNot == 0) ? true : mustNot->test_allowed(c);
}

inline bool CardWords_DicBot_CardTableRequirement::has_sideWord(void) const
{
  return sideWord;
}
inline int CardWords_DicBot_CardTableRequirement::get_letterFactor(void) const
{
  return letter_factor;
}
inline int CardWords_DicBot_CardTableRequirement::get_wordFactor(void) const
{
  return word_factor;
}

#endif
