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.