/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
 * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
 * http://www.gnu.org/software/gnugo/ for more information.          *
 *                                                                   *
 * Copyright 1999, 2000, 2001, 2002, 2003 and 2004                   *
 * by the Free Software Foundation.                                  *
 *                                                                   *
 * 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 - version 2             *
 *                                                                   *
 * 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 in file COPYING 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, USA.                                            *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef _LIBERTY_H_
#define _LIBERTY_H_

#include "board.h"
#include "hash.h"
#include "gnugo.h"

/* ================================================================ */
/*                           public variables                       */
/* ================================================================ */


/* ================================================================ */


#define FALSE_EYE          1
#define HALF_EYE           2


#define REVERSE_RESULT(result)		(WIN - result)


void start_timer(int n);
double time_report(int n, const char *occupation, int move, double mintime);
void showstats(void);
void clearstats(void);

void transformation_init(void);

void report_worm(int m, int n);
void ascii_report_worm(char *string);
void report_dragon(FILE *outfile, int pos);
void ascii_report_dragon(char *string);
struct dragon_data2 *dragon2_func(int pos);

/* prototypes for reorientation functions */

void rotate2(int i, int j, int *ri, int *rj, int rot);
void inv_rotate2(int i, int j, int *ri, int *rj, int rot);
int rotate1(int pos, int rot);
int inv_rotate1(int pos, int rot);

/* Routine names used by persistent and non-persistent caching schemes. */
enum routine_id {
  OWL_ATTACK,
  OWL_DEFEND,
  SEMEAI,
  FIND_DEFENSE,
  ATTACK,
  CONNECT,
  DISCONNECT,
  BREAK_IN,
  BLOCK_OFF,
  OWL_THREATEN_ATTACK,
  OWL_THREATEN_DEFENSE,
  OWL_DOES_DEFEND,
  OWL_DOES_ATTACK,
  OWL_CONNECTION_DEFENDS,
  OWL_SUBSTANTIAL,
  OWL_CONFIRM_SAFETY,
  NUM_CACHE_ROUTINES
};

#define ROUTINE_NAMES \
  "owl_attack", \
  "owl_defend", \
  "semeai", \
  "find_defense", \
  "attack", \
  "connect", \
  "disconnect", \
  "break_in", \
  "block_off", \
  "owl_threaten_attack", \
  "owl_threatend_defense", \
  "owl_does_defend", \
  "owl_does_attack", \
  "owl_connection_defends", \
  "owl_substantial", \
  "owl_confirm_safety"

/* To prioritize between different types of reading, we give a cost
 * ranking to each of the routines above:
 *
 * 4 semeai
 * 3 owl
 * 2 break-in
 * 1 connection
 * 0 tactical reading
 *
 * -1 is left at the end for a consistency check.
 */
#define ROUTINE_COSTS \
  3, 3, 4, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, -1
  

const char *routine_id_to_string(enum routine_id routine);


/* This is used for both the dragon status and safety fields.
 * Also used for unconditional status in struct worm_data and for the
 * final status computed by the aftermath code.
 */
enum dragon_status {
  DEAD,
  ALIVE,
  CRITICAL,
  UNKNOWN,
  UNCHECKED,
  CAN_THREATEN_ATTACK,
  CAN_THREATEN_DEFENSE, 
  INESSENTIAL,
  TACTICALLY_DEAD,
  ALIVE_IN_SEKI,
  STRONGLY_ALIVE,
  INVINCIBLE,
  INSUBSTANTIAL,
  WHITE_TERRITORY,
  BLACK_TERRITORY,
  DAME,
  NUM_DRAGON_STATUS
};

#define DRAGON_STATUS_NAMES \
  "dead", \
  "alive", \
  "critical", \
  "unknown", \
  "unchecked", \
  "can threaten attack", \
  "can threaten defense", \
  "inessential", \
  "tactically dead", \
  "alive in seki", \
  "strongly alive", \
  "invincible", \
  "insubstantial", \
  "white_territory", \
  "black_territory", \
  "dame"

const char *status_to_string(enum dragon_status status);


/* Forward struct declarations. */
struct pattern;
struct pattern_db;
struct fullboard_pattern;
struct corner_pattern;
struct corner_db;
struct half_eye_data;
struct movelist;
struct tree_node_list;
struct match_node;

/*
 * Try to match a pattern in the database to the board. Callbacks for
 * each match.
 */
typedef void (*matchpat_callback_fn_ptr)(int anchor, int color,
                                         struct pattern *, int rotation,
                                         void *data);
typedef void (*fullboard_matchpat_callback_fn_ptr)(int move,
                                                   struct fullboard_pattern *,
                                                   int rotation);
typedef void (*corner_matchpat_callback_fn_ptr)(int move, int color,
						struct corner_pattern *pattern,
						int trans,
						int *stones, int num_stones);
void matchpat(matchpat_callback_fn_ptr callback, int color,
	      struct pattern_db *pdb, void *callback_data,
	      char goal[BOARDMAX]);
void matchpat_goal_anchor(matchpat_callback_fn_ptr callback, int color,
	      struct pattern_db *pdb, void *callback_data,
	      char goal[BOARDMAX], int anchor_in_goal);
void fullboard_matchpat(fullboard_matchpat_callback_fn_ptr callback,
			int color, struct fullboard_pattern *pattern);
void corner_matchpat(corner_matchpat_callback_fn_ptr callback, int color,
		     struct corner_db *database);
void dfa_match_init(void);
void tree_match_init(void);
void tree_initialize_pointers(struct tree_node_list *tnl,
                              struct match_node *matches,
                              int tnl_size,
                              int matches_size);

void reading_cache_init(int bytes);
void reading_cache_clear(void);

/* reading.c */
int attack(int str, int *move);
int find_defense(int str, int *move);
int attack_and_defend(int str,
		      int *attack_code, int *attack_point,
		      int *defend_code, int *defense_point);
int attack_either(int astr, int bstr);
int defend_both(int astr, int bstr);
int break_through(int apos, int bpos, int cpos);
int attack_threats(int pos, int max_points, int moves[], int codes[]);

int restricted_defend1(int str, int *move,
		       int num_forbidden_moves, int *forbidden_moves);
int restricted_attack2(int str, int *move,
		       int num_forbidden_moves, int *forbidden_moves);

int simple_ladder(int str, int *move);
#define MOVE_ORDERING_PARAMETERS 67
void tune_move_ordering(int params[MOVE_ORDERING_PARAMETERS]);
void draw_reading_shadow(void);

/* persistent.c */
void persistent_cache_init(void);
void purge_persistent_caches(void);
void clear_persistent_caches(void);

int search_persistent_reading_cache(enum routine_id routine, int str,
				    int *result, int *move);
void store_persistent_reading_cache(enum routine_id routine, int str,
				    int result, int move, int nodes);
void reading_hotspots(float values[BOARDMAX]);
int search_persistent_connection_cache(enum routine_id routine,
				       int str1, int str2,
				       int *result, int *move);
void store_persistent_connection_cache(enum routine_id routine,
				       int str1, int str2,
				       int result, int move,
				       int tactical_nodes,
				       char connection_shadow[BOARDMAX]);
int search_persistent_breakin_cache(enum routine_id routine,
				    int str, Hash_data *goal_hash,
				    int breakin_node_limit,
				    int *result, int *move);
void store_persistent_breakin_cache(enum routine_id routine,
				    int str, Hash_data *goal_hash,
				    int result, int move,
				    int tactical_nodes,
				    int breakin_node_limit,
				    char breakin_shadow[BOARDMAX]);
int search_persistent_owl_cache(enum routine_id routine,
				int apos, int bpos, int cpos,
				int *result, int *move, int *move2,
				int *certain);
void store_persistent_owl_cache(enum routine_id routine,
				int apos, int bpos, int cpos,
				int result, int move, int move2, int certain,
				int tactical_nodes, char goal[BOARDMAX],
				int goal_color);
void owl_hotspots(float values[BOARDMAX]);

/* readconnect.c */
int string_connect(int str1, int str2, int *move);
int disconnect(int str1, int str2, int *move);
int non_transitivity(int str1, int str2, int str3, int *move);

int break_in(int str, const char goal[BOARDMAX], int *move);
int block_off(int str1, const char goal[BOARDMAX], int *move);

int obvious_false_eye(int pos, int color);
void estimate_lunch_eye_value(int lunch, int *min, int *probable, int *max,
			      int appreciate_one_two_lunches);
int owl_topological_eye(int pos, int color);
int vital_chain(int pos);
int confirm_safety(int move, int color, int *defense_point,
		   char safe_stones[BOARDMAX]);
int dragon_weak(int pos);
int size_of_biggest_critical_dragon(void);
float blunder_size(int move, int color, int *defense_point,
		   char safe_stones[BOARDMAX]);
void set_depth_values(int level, int report_levels);
void modify_depth_values(int n);
void increase_depth_values(void);
void decrease_depth_values(void);
void set_temporary_depth_values(int d, int b, int b2, int bc,
				int ss, int br, int f, int k);
void restore_depth_values(void);

int safe_move(int move, int color);
int does_secure(int color, int move, int pos);

void compute_new_dragons(int dragon_origins[BOARDMAX]);
void join_dragons(int d1, int d2);
int dragon_escape(char goal[BOARDMAX], int color, char escape_value[BOARDMAX]);
void compute_refined_dragon_weaknesses(void);

struct eyevalue;
void compute_dragon_genus(int d, struct eyevalue *genus, int eye_to_exclude);
float crude_dragon_weakness(int safety, struct eyevalue *genus, int has_lunch,
			    float moyo_value, float escape_route);

int is_same_dragon(int d1, int d2);
int are_neighbor_dragons(int d1, int d2);
void mark_dragon(int pos, char mx[BOARDMAX], char mark);
int first_worm_in_dragon(int d);
int next_worm_in_dragon(int w);
int lively_dragon_exists(int color);
void compute_dragon_influence(void);
void set_strength_data(int color, char safe_stones[BOARDMAX],
		       float strength[BOARDMAX]);
void mark_inessential_stones(int color, char safe_stones[BOARDMAX]);

void get_lively_stones(int color, char safe_stones[BOARDMAX]);
int is_same_worm(int w1, int w2);
int is_worm_origin(int w, int pos);
void propagate_worm(int pos);
void transform2(int i, int j, int *ti, int *tj, int trans);
void find_cuts(void);
void find_connections(void);

/* movelist.c */
int movelist_move_known(int move, int max_points, int points[], int codes[]);
void movelist_change_point(int move, int code, int max_points, 
			   int points[], int codes[]);

/* surround.c */
int compute_surroundings(int pos, int apos, int showboard,
			 int *surround_size);
int is_surrounded(int pos);
int does_surround(int move, int dragon);
void reset_surround_data(void);
int surround_map(int dr, int pos);

/* functions to add (or remove) move reasons */
void collect_move_reasons(int color);

void clear_move_reasons(void);
void add_lunch(int eater, int food);
void add_attack_move(int pos, int ww, int code);
void add_defense_move(int pos, int ww, int code);
void add_attack_threat_move(int pos, int ww, int code);
void remove_attack_threat_move(int pos, int ww);
void add_defense_threat_move(int pos, int ww, int code);
void add_connection_move(int pos, int dr1, int dr2);
void add_cut_move(int pos, int dr1, int dr2);
void add_antisuji_move(int pos);
void add_semeai_move(int pos, int dr);
void add_semeai_threat(int pos, int dr);

void add_owl_attack_move(int pos, int dr, int kworm, int code);
void add_owl_defense_move(int pos, int dr, int code);
void add_owl_attack_threat_move(int pos, int dr, int code);
void add_owl_defense_threat_move(int pos, int dr, int code);
void add_owl_prevent_threat_move(int pos, int dr);
void add_owl_uncertain_defense_move(int pos, int dr);
void add_owl_uncertain_attack_move(int pos, int dr);
void add_gain_move(int pos, int target1, int target2);
void add_loss_move(int pos, int target1, int target2);

void add_my_atari_atari_move(int pos, int size);
void add_your_atari_atari_move(int pos, int size);
void add_vital_eye_move(int pos, int eyespace, int color);
void add_invasion_move(int pos);
void add_expand_territory_move(int pos);
void add_expand_moyo_move(int pos);
void add_strategical_attack_move(int pos, int dr);
void add_strategical_defense_move(int pos, int dr);
void add_worthwhile_threat_move(int pos);
void add_replacement_move(int from, int to);

/* Parameters to add_either_move and add_all_move */
#define ATTACK_STRING  1
#define DEFEND_STRING  2
void add_either_move(int pos, int reason1, int target1,
		     int reason2, int target2);
void add_all_move(int pos, int reason1, int target1,
		  int reason2, int target2);

int set_minimum_move_value(int pos, float value);
void set_maximum_move_value(int pos, float value);
void set_minimum_territorial_value(int pos, float value);
void set_maximum_territorial_value(int pos, float value);
void add_shape_value(int pos, float value);
void add_followup_value(int pos, float value);
void add_reverse_followup_value(int pos, float value);
int list_move_reasons(FILE *out, int pos);
void print_all_move_values(void);
void record_top_move(int move, float val);
void remove_top_move(int move);
void scale_randomness(int pos, float scaling);
void compute_move_probabilities(float probabilities[BOARDMAX]);

void register_good_attack_threat(int move, int target);
int is_known_good_attack_threat(int move, int target);

int get_attack_threats(int pos, int max_strings, int strings[]);
int get_defense_threats(int pos, int max_strings, int strings[]);
void get_saved_worms(int pos, char saved[BOARDMAX]);
void get_saved_dragons(int pos, char saved[BOARDMAX]);
void mark_safe_stones(int color, int move_pos,
		      const char saved_dragons[BOARDMAX],
		      const char saved_worms[BOARDMAX],
		      char safe_stones[BOARDMAX]);


int owl_lively(int pos);
int owl_escape_value(int pos);
int owl_goal_dragon(int pos);
int owl_eyespace(int pos);
int owl_big_eyespace(int pos);
int owl_mineye(int pos);
int owl_maxeye(int pos);
int owl_proper_eye(int pos);
int owl_eye_size(int pos);
int owl_lunch(int str);
int owl_strong_dragon(int pos);
void owl_reasons(int color);

void unconditional_life(int unconditional_territory[BOARDMAX], int color);
void find_superstring(int str, int *num_stones, int *stones);
void find_superstring_conservative(int str, int *num_stones, int *stones);
void find_superstring_liberties(int str, int *liberties, int *libs,
                                int liberty_cap);
void find_proper_superstring_liberties(int str, int *liberties, int *libs, 
                                       int liberty_cap);
void find_superstring_stones_and_liberties(int str, int *num_stones,
					   int *stones, int *liberties,
					   int *libs, int liberty_cap);
void superstring_chainlinks(int str, int *num_adj, int adj[MAXCHAIN],
                            int liberty_cap);
void proper_superstring_chainlinks(int str, int *num_adj, 
                                   int adj[MAXCHAIN], int liberty_cap);

int place_fixed_handicap(int handicap); /* place stones on board only */
int place_free_handicap(int handicap); /* place stones on board only */
int free_handicap_remaining_stones(void);
int free_handicap_total_stones(void);


/* Various different strategies for finding a move */
void fuseki(int color);
void semeai(void);
void semeai_move_reasons(int color);
void shapes(int color);
void endgame(int color);
void endgame_shapes(int color);

void combinations(int color);
int atari_atari(int color, int *attack_move, char defense_moves[BOARDMAX],
		int save_verbose);
int atari_atari_confirm_safety(int color, int tpos, int *move, int minsize,
			       const char saved_dragons[BOARDMAX],
			       const char saved_worms[BOARDMAX]);

int atari_atari_blunder_size(int color, int tpos, char defense_moves[BOARDMAX],
			     const char safe_stones[BOARDMAX]);

int review_move_reasons(int *move, float *val, int color,
			float pure_threat_value, float our_score,
			int allowed_moves[BOARDMAX]);
void prepare_move_influence_debugging(int pos, int color);
int fill_liberty(int *move, int color);
int aftermath_genmove(int *aftermath_move, int color,
		      int under_control[BOARDMAX],
		      int do_capture_dead_stones);
enum dragon_status aftermath_final_status(int color, int pos);

int owl_attack(int target, int *attack_point, int *certain, int *kworm);
int owl_defend(int target, int *defense_point, int *certain, int *kworm);
int owl_threaten_attack(int target, int *attack1, int *attack2);
int owl_threaten_defense(int target, int *defend1, int *defend2);
int owl_does_defend(int move, int target, int *kworm);
int owl_confirm_safety(int move, int target, int *defense_point, int *kworm);
int owl_does_attack(int move, int target, int *kworm);
int owl_connection_defends(int move, int target1, int target2);
int owl_substantial(int str);
void owl_analyze_semeai(int apos, int bpos, 
			int *resulta, int *resultb, int *semeai_move,
			int owl, int *semeai_result_certain);
void owl_analyze_semeai_after_move(int move, int color, int apos, int bpos,
				   int *resulta, int *resultb,
				   int *semeai_move, int owl,
				   int *semeai_result_certain,
				   int recompute_dragons);

void set_search_diamond(int pos);
void reset_search_mask(void);
void set_search_limit(int pos, int value);
int oracle_play_move(int pos, int color);
void consult_oracle(int color);
void summon_oracle(void);
void oracle_loadsgf(char *infilename, char *untilstring);
int oracle_threatens(int move, int target);
int within_search_area(int pos);
int metamachine_genmove(int *i, int *j, int color);
void draw_search_area(void);

int genmove_restricted(int *i, int *j, int color, int allowed_moves[BOARDMAX]);

void change_attack(int str, int move, int acode);
void change_defense(int str, int move, int dcode);
void change_attack_threat(int str, int move, int acode);
void change_defense_threat(int str, int move, int dcode);
int attack_move_known(int move, int str);
int defense_move_known(int move, int str);
int attack_threat_move_known(int move, int str);
int defense_threat_move_known(int move, int str);
void worm_reasons(int color);

int semeai_move_reason_known(int move, int dr);

int does_attack(int move, int str);
int does_defend(int move, int str);
int double_atari(int move, int color, float *value,
		 char safe_stones[BOARDMAX]);
int play_attack_defend_n(int color, int do_attack, int num_moves, ...);
int play_attack_defend2_n(int color, int do_attack, int num_moves, ...);
int play_break_through_n(int color, int num_moves, ...);
int play_connect_n(int color, int do_connect, int num_moves, ...);
int cut_possible(int pos, int color);
int defend_against(int move, int color, int apos);
int somewhere(int color, int check_alive, int num_moves, ...);
int visible_along_edge(int color, int apos, int bpos);
int test_symmetry_after_move(int move, int color, int strict);

/* Printmoyo values, specified by -m flag. */
#define PRINTMOYO_TERRITORY         0x01
#define PRINTMOYO_MOYO              0x02
#define PRINTMOYO_AREA              0x04
/* The following have been borrowed by the influence functions below. */
#define PRINTMOYO_INITIAL_INFLUENCE 0x08
#define PRINTMOYO_PRINT_INFLUENCE   0x10
#define PRINTMOYO_NUMERIC_INFLUENCE 0x20
#define PRINTMOYO_PERMEABILITY      0x40
#define PRINTMOYO_STRENGTH          0x80
#define PRINTMOYO_ATTENUATION       0x100
#define PRINTMOYO_VALUE_TERRITORY   0x200

/* These values are used to communicate whether stones are safe or
 * have been saved, when computing influence.
 */
#define INFLUENCE_SAFE_STONE	1
#define INFLUENCE_SAVED_STONE	2

/* These values are used to communicate the status of stones when analyzing
 * a move for potentially being a blunder.
 */
/* 	dead		0 */
#define SAFE_STONE 	1
#define OWL_SAVED_STONE	2

/* This format is used when exporting the moyo segmentation. */
#define MAX_MOYOS MAX_BOARD*MAX_BOARD

struct moyo_data
{
  int number; /* Number of moyos. */
  int segmentation[BOARDMAX]; /* Numbers the moyos. */
  int size[MAX_MOYOS];
  int owner[MAX_MOYOS];
  float territorial_value[MAX_MOYOS];
};

/* We use a forward declaration of influence_data so that the rest
 * of the engine can reference influence data. It can only be accessed
 * in influence.c, however!
 */
struct influence_data;
extern struct influence_data initial_black_influence;
extern struct influence_data initial_white_influence;
extern struct influence_data move_influence;
extern struct influence_data followup_influence;

#define INITIAL_INFLUENCE(color) ((color) == WHITE ? \
				    &initial_white_influence \
				  : &initial_black_influence)
#define OPPOSITE_INFLUENCE(color) (INITIAL_INFLUENCE(OTHER_COLOR(color)))

#define DEFAULT_STRENGTH 100.0

/* Influence functions. */
void compute_influence(int color, const char safe_stones[BOARDMAX],
		       const float strength[BOARDMAX],
		       struct influence_data *q,
		       int move, const char *trace_message);
void compute_followup_influence(const struct influence_data *base,
			        struct influence_data *q, 
		                int move, const char *trace_message);
void compute_escape_influence(int color, const char safe_stones[BOARDMAX],
			      const char goal[BOARDMAX],
			      const float strength[BOARDMAX],
                              char escape_value[BOARDMAX]);

float influence_delta_territory(const struct influence_data *base,
	                        const struct influence_data *q, int color,
				int move);
int retrieve_delta_territory_cache(int pos, int color, float *move_value,
			           float *followup_value,
				   const struct influence_data *base,
				   Hash_data safety_hash);
void store_delta_territory_cache(int pos, int color, float move_value,
				 float followup_value,
				 const struct influence_data *base,
			         Hash_data safety_hash);

int whose_territory(const struct influence_data *q, int pos);
int whose_loose_territory(const struct influence_data *q, int pos);
int whose_moyo(const struct influence_data *q, int pos);
int whose_area(const struct influence_data *q, int pos);
float influence_territory(const struct influence_data *q, int pos, int color);
void influence_get_moyo_segmentation(const struct influence_data *q,
	       			     struct moyo_data *moyo);
void influence_get_territory_segmentation(const struct influence_data *q,
	       			          struct moyo_data *moyo);
void influence_get_moyo_data(const struct influence_data *q,
			     int moyo_color[BOARDMAX],
			     float territory_value[BOARDMAX]);
void get_influence(const struct influence_data *q,
		   float white_influence[BOARDMAX],
		   float black_influence[BOARDMAX],
		   float white_strength[BOARDMAX],
		   float black_strength[BOARDMAX],
		   float white_attenuation[BOARDMAX], 
		   float black_attenuation[BOARDMAX],
		   float white_permeability[BOARDMAX],
		   float black_permeability[BOARDMAX],
		   float territory_value[BOARDMAX],
		   int influence_regions[BOARDMAX],
		   int non_territory[BOARDMAX]);
float influence_score(const struct influence_data *q);
float game_status(int color);
void resegment_initial_influence(void);
void influence_mark_non_territory(int pos, int color);
int influence_considered_lively(const struct influence_data *q, int pos);
void influence_erase_territory(struct influence_data *q, int pos, int color);

void break_territories(int color_to_move, struct influence_data *q,
			 int store);
void clear_break_in_list(void);
void break_in_move_reasons(int color);

float estimate_score(float *upper, float *lower);
void choose_strategy(int color, float our_score, float game_status);

/* Eye space functions. */
int is_eye_space(int pos);
int is_proper_eye_space(int pos);
int is_marginal_eye_space(int pos);
int max_eye_value(int pos);
void test_eyeshape(int eyesize, int *eye_vertices);
int analyze_eyegraph(const char *coded_eyegraph, struct eyevalue *value,
		     char *analyzed_eyegraph);


/* debugging support */
void goaldump(const char goal[BOARDMAX]);
void move_considered(int move, float value);


/* Transformation stuff. */
#define MAX_OFFSET			(2*MAX_BOARD - 1) * (2*MAX_BOARD - 1)
#define OFFSET(dx, dy)\
  ((dy + MAX_BOARD - 1) * (2*MAX_BOARD - 1) + (dx + MAX_BOARD - 1))
#define OFFSET_DELTA(dx, dy)		(OFFSET(dx, dy) - OFFSET(0, 0))
#define CENTER_OFFSET(offset)		(offset - OFFSET(0, 0))
#define TRANSFORM(offset, trans)	(transformation[offset][trans])
#define AFFINE_TRANSFORM(offset, trans, delta)\
  (transformation[offset][trans] + delta)
#define TRANSFORM2(x, y, tx, ty, trans)\
  do {\
    *tx = transformation2[trans][0][0] * (x) + transformation2[trans][0][1] * (y);\
    *ty = transformation2[trans][1][0] * (x) + transformation2[trans][1][1] * (y);\
  } while (0)


/* ================================================================ */
/*                         global variables                         */
/* ================================================================ */

extern int disable_threat_computation;
extern int disable_endgame_patterns;
extern int doing_scoring;

/* Reading parameters */
extern int depth;               /* deep reading cutoff */
extern int backfill_depth;      /* deep reading cutoff */
extern int backfill2_depth;     /* deep reading cutoff */
extern int break_chain_depth;   /* deep reading cutoff */
extern int superstring_depth;   /* deep reading cutoff */
extern int branch_depth;        /* deep reading cutoff */
extern int fourlib_depth;       /* deep reading cutoff */
extern int ko_depth;            /* deep ko reading cutoff */
extern int aa_depth;            /* deep global reading cutoff */
extern int depth_offset;        /* keeps track of temporary depth changes */
extern int owl_distrust_depth;  /* below this owl trusts the optics code */
extern int owl_branch_depth;    /* below this owl tries only one variation */
extern int owl_reading_depth;   /* owl does not read below this depth */
extern int owl_node_limit;      /* maximum number of nodes considered */
extern int semeai_branch_depth;
extern int semeai_branch_depth2;
extern int semeai_node_limit;
extern int connect_depth;
extern int connect_depth2;
extern int connection_node_limit;
extern int breakin_depth;
extern int breakin_node_limit;
extern int level;               /* controls the strength of play */
extern int min_level;           /* minimum level for adjustment schemes */
extern int max_level;           /* minimum level for adjustment schemes */
extern int semeai_variations;   /* max variations considered reading semeai */
extern float best_move_values[10];
extern int best_moves[10];

extern int experimental_owl_ext;     /* use experimental owl (GAIN/LOSS) */
extern int experimental_semeai;      /* use experimental semeai module */
extern int experimental_connections; /* use experimental connection module */
extern int alternate_connections;    /* use alternate connection module */
extern int owl_threats;              /* compute owl threats */
extern int experimental_break_in;    /* use experimental module breakin.c */
extern int cosmic_gnugo;             /* use center oriented influence */
extern int large_scale;              /* seek large scale captures */

extern int thrashing_dragon;        /* Dead opponent's dragon trying to live */
extern char thrashing_stone[BOARDMAX];        /* All thrashing stones. */

/* Experimental reading */
extern char *rgoal;
extern int goallib;

extern int transformation[MAX_OFFSET][8];
extern const int transformation2[8][2][2];


/* Arrays pointing out the closest worms from each vertex.  The first
 * one is the closest worms of either color, the last two ones ignore
 * worms of the other color.  Beyond a certain distance from any worm
 * no close worm is listed at all.  Only the closest worm is listed
 * and if more than one are equally close they are all listed. The
 * number of equally close worms is given in the number_*_worms
 * arrays. If more than MAX_CLOSE_WORMS are equally close, none is
 * listed.
 *
 * See compute_effective_worm_sizes() in worm.c for details.
 */
#define MAX_CLOSE_WORMS 4
extern int close_worms[BOARDMAX][MAX_CLOSE_WORMS];
extern int number_close_worms[BOARDMAX];
extern int close_black_worms[BOARDMAX][MAX_CLOSE_WORMS];
extern int number_close_black_worms[BOARDMAX];
extern int close_white_worms[BOARDMAX][MAX_CLOSE_WORMS];
extern int number_close_white_worms[BOARDMAX];

extern int false_eye_territory[BOARDMAX];
extern int forced_backfilling_moves[BOARDMAX];

extern double slowest_time;      /* Timing statistics */
extern int slowest_move;
extern int slowest_movenum;
extern double total_time;


struct eyevalue {
#if 0
  char maxeye;       /* number of eyes if defender plays first               */
  char mineye;       /* number of eyes if attacker plays first               */
#else
  unsigned char a; /* number of eyes if attacker plays first twice */
  unsigned char b; /* number of eyes if attacker plays first */
  unsigned char c; /* number of eyes if defender plays first */
  unsigned char d; /* number of eyes if defender plays first twice */
#endif
};


struct half_eye_data {
  float value;          /* Topological eye value. */
  char type;            /* HALF_EYE or FALSE_EYE; */
  int num_attacks;      /* number of attacking points */
  int attack_point[4];  /* the moves to attack a topological halfeye */
  int num_defenses;     /* number of defending points */
  int defense_point[4]; /* the moves to defend a topological halfeye */
};

/* array of half-eye data */
extern struct half_eye_data half_eye[BOARDMAX];

/*
 * data concerning a worm. A copy is kept at each vertex of the worm.
 */

#define MAX_TACTICAL_POINTS 10

struct worm_data {
  int color;         /* its color */
  int size;          /* its cardinality */
  float effective_size; /* stones and surrounding spaces */
  int origin;        /* the origin of the string. Two vertices are in */
                     /* the same worm iff they have same origin. */
  int liberties;     /* number of liberties */
  int liberties2;    /* number of second order liberties */
  int liberties3;    /* third order liberties (empty vertices at distance 3) */
  int liberties4;    /* fourth order liberties */
  int lunch;         /* if lunch != 0 then lunch points to a boundary */
                     /* worm which can be captured easily. */
  int cutstone;      /* 1=potential cutting stone; 2=cutting stone */
  int cutstone2;     /* Number of potential cuts involving the worm. */
  int genus;         /* number of connected components of the complement, less one */
  int inessential;   /* 1=inessential worm */
  int invincible;    /* 1=strongly unconditionally non-capturable */
  enum dragon_status unconditional_status; /* ALIVE, DEAD, WHITE_TERRITORY,
					      BLACK_TERRITORY, UNKNOWN */

  /* The following arrays keeps track of up to MAX_TACTICAL_POINTS
   * different attack, defense, attack threat, and defense threat
   * points with corresponding result codes. (0 = loss, 1 = bad ko, 2
   * = good ko, 3 = win). The arrays are guaranteed to be sorted with
   * respect to the codes so that the first element contains the best
   * result.
   */
  int attack_points[MAX_TACTICAL_POINTS];
  int attack_codes[MAX_TACTICAL_POINTS];
  int defense_points[MAX_TACTICAL_POINTS];
  int defense_codes[MAX_TACTICAL_POINTS];
  int attack_threat_points[MAX_TACTICAL_POINTS];
  int attack_threat_codes[MAX_TACTICAL_POINTS]; 
  int defense_threat_points[MAX_TACTICAL_POINTS];
  int defense_threat_codes[MAX_TACTICAL_POINTS];
};

extern struct worm_data worm[BOARDMAX];

/* Surround cache (see surround.c) */

#define MAX_SURROUND 10

struct surround_data {
  int dragon_number;           /* number of the (surrounded) beast */
  char surround_map[BOARDMAX]; /* surround map                     */
};

extern struct surround_data surroundings[MAX_SURROUND];
extern int surround_pointer;

/*
 * data concerning a dragon. A copy is kept at each stone of the string.
 */

struct dragon_data {
  int color;    /* its color                                                 */
  int id;       /* the index into the dragon2 array                          */
  int origin;   /* the origin of the dragon. Two vertices are in the same    */
                /* dragon iff they have same origin.                         */
  int size;     /* size of the dragon                                        */
  float effective_size; /* stones and surrounding spaces                     */
  enum dragon_status crude_status; /* (ALIVE, DEAD, UNKNOWN, CRITICAL)       */
  enum dragon_status status;       /* best trusted status                    */
};

extern struct dragon_data dragon[BOARDMAX];

/* Supplementary data concerning a dragon. Only one copy is stored per
 * dragon in the dragon2 array.
 */

#define MAX_NEIGHBOR_DRAGONS 10

struct dragon_data2 {
  int origin;                         /* the origin of the dragon            */
  int adjacent[MAX_NEIGHBOR_DRAGONS]; /* adjacent dragons                    */
  int neighbors;                      /* number of adjacent dragons          */
  int hostile_neighbors;              /* neighbors of opposite color         */

  int moyo_size;		      /* size of surrounding influence moyo, */
  float moyo_territorial_value;       /* ...and its territorial value        */
  enum dragon_status safety;          /* a more detailed status estimate     */
  float weakness; /* A new (3.4) continuous estimate of the dragon's safety  */
  float weakness_pre_owl;     /* Dragon safety based on pre-owl computations */
  int escape_route; /* a measurement of likelihood of escape                 */
  struct eyevalue genus;    /* the number of eyes (approximately)            */
  int heye;     /* coordinates of a half eye                                 */
  int lunch;    /* if lunch != 0 then lunch points to a boundary worm which  */
                /* can be captured easily.                                   */
  int surround_status;         /* Is it surrounded?                          */
  int surround_size;           /* Size of the surrounding area               */

  int semeais;         /* number of semeais in which the dragon is involved  */
  int semeai_defense_point;/* Move found by semeai code to rescue dragon     */
  int semeai_defense_certain;
  int semeai_defense_target; /* The opponent dragon involved in the semeai   */
  int semeai_attack_point; /* Move found by semeai code to kill dragon       */
  int semeai_attack_certain;
  int semeai_attack_target; /* The opponent dragon involved in the semeai    */
  enum dragon_status owl_threat_status; /* CAN_THREATEN_ATTACK/DEFENSE       */
  enum dragon_status owl_status; /* (ALIVE, DEAD, UNKNOWN, CRITICAL, UNCHECKED)    */
  int owl_attack_point;    /* vital point for attack                         */
  int owl_attack_code;     /* ko result code                                 */
  int owl_attack_certain;  /* 0 if owl reading node limit is reached         */
  int owl_second_attack_point;/* if attacker gets both attack points, wins   */
  int owl_defense_point;   /* vital point for defense                        */
  int owl_defense_code;    /* ko result code                                 */
  int owl_defense_certain; /* 0 if owl reading node limit is reached         */
  int owl_second_defense_point;/* if defender gets both attack points, wins  */
  int owl_attack_kworm;    /* only valid when owl_attack_code is GAIN        */
  int owl_defense_kworm;   /* only valid when owl_defense_code is LOSS       */
};

/* dragon2 is dynamically allocated */
extern int number_of_dragons;
extern struct dragon_data2 *dragon2;

/* Macros for accessing the dragon2 data with board coordinates and
 * the dragon data with a dragon id.
 */
#if 1 /* Trust DRAGON2 accesses */
#define DRAGON2(pos) dragon2[dragon[pos].id]
#else
struct dragon_data2 * dragon2_func(int pos);
#define DRAGON2(pos) (*dragon2_func(pos))
#endif

#define DRAGON(d) dragon[dragon2[d].origin]


/* Global variables to tune strategy. */

extern int use_optimistic_territory;

extern float minimum_value_weight;
extern float maximum_value_weight;
extern float invasion_malus_weight;
extern float strategical_weight;
extern float territorial_weight;
extern float attack_dragon_weight;
extern float followup_weight;

struct aftermath_data {
  int white_captured;
  int black_captured;
  int white_prisoners;
  int black_prisoners;
  int white_territory;
  int black_territory;
  int white_area;
  int black_area;
  int white_control[BOARDMAX];
  int black_control[BOARDMAX];
  enum dragon_status final_status[BOARDMAX];
};

#define MAX_EYE_ATTACKS 3

struct eye_data {
  int color;/* BLACK, WHITE, BLACK_BORDERED, WHITE_BORDERED or GRAY_BORDERED */
  int esize;         /* size of the eyespace                                 */
  int msize;         /* number of marginal vertices                          */
  int origin;        /* The origin                                           */
  struct eyevalue value; /* Number of eyes.                                  */
  int attack_point;  /* vital point for attack */
  int defense_point; /* vital point for defense	*/

  /* The above fields are constant on the whole eyespace. */
  /* ---------------------------------------------------------------- */
  /* The below fields are not. */

  char marginal;             /* This vertex is marginal                    */
  char type;                 /* Various characteristics of the eyespace    */
  char neighbors;            /* number of neighbors in eyespace            */
  char marginal_neighbors;   /* number of marginal neighbors               */
};

struct vital_eye_points {
  int attack_points[MAX_EYE_ATTACKS];
  int defense_points[MAX_EYE_ATTACKS];
};

extern struct vital_eye_points black_vital_points[BOARDMAX];
extern struct vital_eye_points white_vital_points[BOARDMAX];

extern struct eye_data white_eye[BOARDMAX];
extern struct eye_data black_eye[BOARDMAX];

/* Array with the information which was previously stored in the cut
 * field and in the INHIBIT_CONNECTION bit of the type field in struct
 * eye_data.
 */
extern int cutting_points[BOARDMAX];

/* The following declarations have to be postponed until after the
 * definition of struct eye_data or struct half_eye_data.
 */

void compute_eyes(int pos, struct eyevalue *value,
                  int *attack_point, int *defense_point,
                  struct eye_data eye[BOARDMAX],
                  struct half_eye_data heye[BOARDMAX],
		  int add_moves);
void compute_eyes_pessimistic(int pos, struct eyevalue *value,
                              int *pessimistic_min,
                              int *attack_point, int *defense_point,
                              struct eye_data eye[BOARDMAX],
                              struct half_eye_data heye[BOARDMAX]);
void propagate_eye(int pos, struct eye_data eye[BOARDMAX]);
int find_eye_dragons(int origin, struct eye_data eye[BOARDMAX], int eye_color,
		     int dragons[], int max_dragons);
float topological_eye(int pos, int color,
		      struct eye_data my_eye[BOARDMAX],
		      struct half_eye_data heye[BOARDMAX]);
void add_false_eye(int pos, struct eye_data eye[BOARDMAX], 
		   struct half_eye_data heye[BOARDMAX]);
void make_domains(struct eye_data b_eye[BOARDMAX],
                  struct eye_data w_eye[BOARDMAX],
		  int owl_call);
void partition_eyespaces(struct eye_data eye[BOARDMAX], int color);
void find_half_and_false_eyes(int color, struct eye_data eye[BOARDMAX],
			      struct half_eye_data heye[BOARDMAX],
			      int find_mask[BOARDMAX]);

void set_eyevalue(struct eyevalue *e, int a, int b, int c, int d);
int min_eye_threat(struct eyevalue *e);
int min_eyes(struct eyevalue *e);
int max_eyes(struct eyevalue *e);
int max_eye_threat(struct eyevalue *e);
void add_eyevalues(struct eyevalue *e1, struct eyevalue *e2,
		   struct eyevalue *sum);
int eye_move_urgency(struct eyevalue *e);
char *eyevalue_to_string(struct eyevalue *e);

int is_halfeye(struct half_eye_data heye[BOARDMAX], int pos);
int is_false_eye(struct half_eye_data heye[BOARDMAX], int pos);

#endif  /* _LIBERTY_H_ */


/*
 * Local Variables:
 * tab-width: 8
 * c-basic-offset: 2
 * End:
 */
