/*
 * Atom-4 AI player
 * Header file
 *
 * $Id: ai.h,v 1.18 2003/04/11 04:37:47 hsteoh Exp hsteoh $
 */

#ifndef AI_H
#define AI_H

//#define DEBUG_AI

#ifdef PROFILE
#define PROFILE_AI
#endif

#ifdef DEBUG_AI
#include <stdio.h>
#endif //DEBUG_AI

// TESTING ONLY!
#include <sys/types.h>
#include <unistd.h>

#include "board4.h"
#include "event.h"
#include "game.h"


class atom4ai : public atom4local {
  int playernum;
  int search_depth;			// game tree search depth

#ifdef DEBUG_AI
  FILE *logfile;
  void reopen_log();
#endif //DEBUG_AI

  struct move_t { int x, y; };
  struct hdelta {			// heuristic function accumulator
    int changes, pcreated, pdestroyed;
    inline hdelta operator-() {
      hdelta neg = { -changes, -pdestroyed, -pcreated };
      return neg;
    }
  };

//TESTING ONLY!!!!!!!!
  eventloop *loop;
  pid_t child;
  int childpipe;			// pipe to child process
  class childmon : public eventhandler {
    atom4ai *ai;
  public:
    childmon(atom4ai *context) : ai(context) {}
    void read_ready(eventloop *src, int fd);
    void write_ready(eventloop *src, int fd);
  } babysitter;

  // FIXME: THIS SHOULD BE MOVED TO PARENT CLASS
  static color4 nextcolor(color4 c) { return c.rotr().complement(); }

  void find_legal_moves(board4 &board, elist<move_t> &moves);
  float score_opponent_turn(board4 &board, color4 nexttile, float min,
                            float max, hdelta h, int maxdepth);
  void update_heuristic(board4 &board, color4 propagator,
                        elist<boardchange> &undolist, hdelta &h);
  float calc_heuristic(hdelta h);
  float score_move(board4 &board, color4 tile, move_t m, float min, float max,
                   hdelta h, int maxdepth);
  move_t pick_random(elist<move_t> &list);
  void pick_best_move(int parentfd);
  void make_move();
protected:
  void notify_move(int player, elist<boardchange> &chg);
  void notify_clear();
public:
  atom4ai(eventloop *loop, unsigned int width, unsigned int height,
          int which_player);
  ~atom4ai();

  // AI configuration
  void set_search_depth(int depth) { search_depth=depth; }

  // Base class overrides
  void reset();				// restart game
  mode_t game_mode();
  int local_playernum();
  int is_local_turn();

  int newround();
};

#endif // AI_H
