+ return OK;
+}
+
+/**
+ * Calculates the intrinsic strategic worth of a point on the board
+ * @param x the x coordinate of the point
+ * @param y the y coordinate of the point
+ * @returns a value between 0 and 1, with 0 indicating worthless and 1 indicating highly desirable
+ * (NOTE: No points will actually be worth 0)
+ */
+double Forfax::IntrinsicWorth(int x, int y) const
+{
+ static double intrinsicWorth[][10][10] =
+ {
+ //Red
+ {
+ {0.1,0.5,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1},
+ {0.5,0.5,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1},
+ {0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2},
+ {0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.3},
+ {0.6,0.6,0.1,0.1,0.65,0.65,0.1,0.1,0.6,0.6},
+ {0.6,0.6,0.1,0.1,0.65,0.65,0.1,0.1,0.6,0.6},
+ {0.6,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.6},
+ {0.6,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.6},
+ {0.6,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.6},
+ {0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7}
+
+
+ },
+ //Blue
+ {
+ {0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7},
+ {0.6,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.6},
+ {0.6,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.6},
+ {0.6,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.6},
+ {0.6,0.6,0.1,0.1,0.65,0.65,0.1,0.1,0.6,0.6},
+ {0.6,0.6,0.1,0.1,0.65,0.65,0.1,0.1,0.6,0.6},
+ {0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.3},
+ {0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2},
+ {0.5,0.5,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1},
+ {0.1,0.5,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1}
+ }
+ };
+
+ return intrinsicWorth[(int)(colour)][x][y];
+}
+
+/**
+ * Calculates a score assuming that attacker will beat defender, indicating how much killing that piece is worth
+ * @param attacker the Attacking piece
+ * @param defender the Defending piece
+ * @returns a value between 0 and 1, with 0 indicating worthless and 1 indicating highly desirable
+ */
+double Forfax::VictoryScore(Piece * attacker, Piece * defender) const
+{
+ if (defender->minRank == defender->maxRank)
+ {
+ if (defender->minRank == Piece::FLAG)
+ return 1;
+ else if (defender->minRank == Piece::BOMB)
+ return 0.9;
+ }
+ return max<double>(((defender->maxRank / Piece::BOMB) + (defender->minRank / Piece::BOMB))/2, 0.6);
+}
+
+/**
+ * Calculates a score assuming that attacker will lose to defender, indicating how much learning the rank of that piece is worth
+ * @param attacker the Attacking piece
+ * @param defender the Defending piece
+ * @returns a value between 0 and 1, with 0 indicating worthless and 1 indicating highly desirable
+ */
+double Forfax::DefeatScore(Piece * attacker, Piece * defender) const
+{
+ if (attacker->minRank == Piece::SPY)
+ return 0.05;
+
+ if (defender->minRank == defender->maxRank)
+ {
+ if (defender->minRank == Piece::BOMB)
+ return 1 - (double)((double)(attacker->minRank) / (double)(Piece::BOMB));
+ else
+ return 0.5;
+ }
+
+ double possibleRanks = 0; double totalRanks = 0;
+ for (Piece::Type rank = Piece::NOTHING; rank <= Piece::BOMB; rank = Piece::Type((int)(rank) + 1))
+ {
+ totalRanks += remainingUnits[(int)(defender->colour)][(int)(rank)];
+ if (rank >= defender->minRank && rank <= defender->maxRank)
+ possibleRanks += remainingUnits[(int)(defender->colour)][(int)(rank)];
+
+ }
+
+ if (totalRanks > 0)
+ return (possibleRanks/totalRanks) - (double)((double)(attacker->minRank) / (double)(Piece::BOMB));
+ return 0;
+}
+
+/**
+ * DEBUG - Print the board seen by Forfax to a stream
+ * @param out The stream to print to
+ */
+void Forfax::PrintBoard(ostream & out)
+{
+ for (int y = 0; y < board->Height(); ++y)
+ {
+ for (int x = 0; x < board->Width(); ++x)
+ {
+ Piece * at = board->Get(x, y);
+ if (at == NULL)
+ out << ".";
+ else
+ {
+ if (at->colour == colour)
+ {
+ out << Piece::tokens[(int)(at->minRank)];
+ }
+ else if (at->colour == Piece::Opposite(colour))
+ {
+ out << "#";
+ }
+ else
+ {
+ out << "+";
+ }
+ }
+ }
+ out << "\n";
+ }