/*
  crossword -- a crossword game
  Copyright (C) 2000 Falk Hueffner

  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

  $Id: Bot.hh,v 1.10 2000/11/29 01:29:38 falk Exp $
*/

#ifndef BOT_HH
#define BOT_HH

#include <string>
#include <vector>

#include "Board.hh"
#include "Player.hh"
#include "Pos.hh"
#include "Rack.hh"
#include "Trie.hh"
#include "Move.hh"

class Bot : public Player {
public:
    Bot(const string& dictname)
	: dict(dictname), isRotated(false),
	  letterOkNormal(vector<vector<bool> >(Rules::numFields(),
					       vector<bool>(256, true))),
	  letterOkRotated(vector<vector<bool> >(Rules::numFields(),
						vector<bool>(256, true))),
	  letterOk(&letterOkNormal) { }

    string name() const { return "Bot"; }

    void apply(const Move& move);
    Move getMove();

private:
    enum ScanDir { LEFT = -1, RIGHT = 1 };
    static Pos rotatedPos(Pos p);
    void prepareLetterOk();	// set up cache for valid vertical words
    void updateLetterOk(Pos p);	// a tile has been placed on p; update cache
    void rotateBoard();
    void scanBoard();		// find moves
    void placeTile(Pos pos, const TrieNode* node);
    void tryPutting(Pos pos, const TrieNode* node);
    void scoreWord();

    Board board;		// a copy, to allow fiddling with
    Trie dict;			// the dictionary
    Rack rack;			// the rack, including information which tiles
				// are already put
    Move bestMove;
    int bestScore;

    // The following variables are only meaningful when a search is performed
    // via scanBoard(). Instead of passing them around between the functions,
    // they're stored here.
    Move move;			// accumulated puts
    int score;			// accumulated score
    int multiplier;		// accumulated word multiplier
    bool isRotated;		// true if we're actually searching vertically
    Pos rightBorder, leftBorder; // borders of the line we're searching (first
				 // illegal position)
    Pos anchor, lastAnchor;
    bool isContinuation;	// FIMXE ugly... or not? I'll see.
    ScanDir dir;

    // This array caches for each position and letter if putting this letter
    // there would give a valid word *vertically*.
    vector<vector<bool> > letterOkNormal, letterOkRotated;
    vector<vector<bool> >* letterOk;
};

#endif

