This is StufComp.m in view mode; [Download] [Up]
/*
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
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.