/*
   Stuf: a combination of Greedier and a new method which tries to keep
   the number of empties touched by this_player at a certain percentage of the
   total number of empty squares.

   This Splat (Version 0.91) strategy written by:

     John Garnett (garnett@gestalt.austin.tx.us)
     on March 13, 1993
*/

#import "StufComp.h"

/* PLIER: multiplier used to scale up the raw board score */
#define PLIER 100

/* EMPTY_PCT: percentage of the empty squares that we would like to have
   our pieces adjacent to.
*/
#define EMPTY_PCT 0.10

/* SWITCHOVER: indicate at what point to switch from pure Greedier over to
   Greedier plus the ratio of touched empties to all empties.  A value of
   0.50 means switch over when half of the empties remain.  A value of
   1.00 means switch over immediately (when all empties remain).  A value of
   0.00 means never switch.
*/
#define SWITCHOVER 0.50

@implementation StufComp

+ (const char *)strategyName
{
	return "Stuf";
}

/* surrounds: returns the number of pieces of type 'type' that are within
   'delta' squares of board position (r, c).
*/

inline int
surrounds(Board *b, int r, int c, square_state type, int delta)
{
    int r1, c1, count;
    int outerMax, innerMax;

    count = 0;
	outerMax = MAX(r + delta, b->maxRow - 1);
	innerMax = MAX(c + delta, b->maxCol - 1);
    for (r1 = MAX(r - delta, 0); r1 <= outerMax; r1++) {
        for (c1 = MAX(c - delta, 0); c1 <= innerMax; c1++) {
			if ((r != r1) || (c != c1)) {
				count += (b->board[c1 + r1 * b->maxCol] == type);
			}
        }
    }
    return count;
}

/* scoreBoard: return the evaluation score for the board 'b',
   given that 'us' denotes the code identifying our pieces
*/

-(int)scoreBoard:(Board *)b forPlayer:(square_state)us
{
	int result, s, r1, c1, ourMaterial, empties;
	square_state them;
	double ratio;
	move cm;

	them = OTHER_PLAYER(us);
	cm = b->currentMove;
	/* the difference in material is the main factor.  give more weight to
	   our material than the opponent's.  this weighting should cause
	   us to make more copying moves than jumping moves.
	*/
	ourMaterial = [b numberOfPiece:us];
	result = PLIER * (2 * ourMaterial - [b numberOfPiece:them]);
	s = 0;
	empties = [b numberOfPiece:SQUARE_EMPTY];
	/*
	  Give a bonus for touching a given percentage of the empties.
	  Size of bonus depends on how close we come to touching EMPTY_PCT of
	  empties.  Strategy somewhat expensive so we are pure greedy until
	  number of empties is less than 1/2 the number of squares on the board.
	*/
	if (empties && (empties < (b->maxRow * b->maxCol * SWITCHOVER))) {
		for (r1 = 0; r1 < b->maxRow; r1++) {
			for (c1 = 0; c1 < b->maxCol; c1++) {
				if (b->board[c1 + r1 * b->maxCol] == SQUARE_EMPTY) {
					s += (surrounds(b, r1, c1, us, 1) > 0);
				}
			}
		}
		ratio = s / empties;
		result += PLIER *
			(1.0 - (fabs(ratio - EMPTY_PCT) / MAX(ratio, EMPTY_PCT)));
	}
	return result;
}

@end
