protected override float ScoreDetail(CachedMetricState state) { return(0.7f * totalFillAdvantage.ScoreCached(state) + 10.0f * hungerPressureAdvantage.ScoreCached(state) + 4.0f * adversarialFillAdvantage.ScoreCached(state) + 4.0f * combinedLengthAdvantage.ScoreCached(state)); }
private float FoodDistanceMetric(CachedMetricState state) { var floodBoard = state.OwnFill; int bestOwnDistance = int.MaxValue; foreach (var fruit in state.World.Fruits) { var dist = floodBoard.Distances[fruit.Y, fruit.X]; if (dist <= 0) { continue; } bestOwnDistance = Math.Min(bestOwnDistance, dist); } if (bestOwnDistance == int.MaxValue) { return(0); } return((float)Math.Exp(-FoodDistanceDecay * bestOwnDistance)); }
public float ScoreCached(CachedMetricState state) { float deltaAdvantage = state.OwnSnake.Length - state.EnemySnake.Length; float deltaMetric = ScoreDeltaAdvantage(deltaAdvantage); float deltaOnEatMetric = ScoreDeltaAdvantage(deltaAdvantage + 1); // If food distance metric is 1, want to be exactly as good as eating one // fruit. Since food distance is always less than 1, ensures that eating // is always better than guarding with proximity of 1. float foodMetricMultiplier = deltaOnEatMetric - deltaMetric; return(deltaMetric + FoodDistanceMetric(state) * foodMetricMultiplier); }
public float ScoreCached(CachedMetricState state) { var floodBoard = state.AdversarialFill.Tiles; int bestOwnDistance = int.MaxValue; int bestEnemyDistance = int.MaxValue; foreach (var fruit in state.World.Fruits) { ref var tile = ref floodBoard[fruit.Y, fruit.X]; if (tile.Snake == state.OwnIndex) { bestOwnDistance = Math.Min(bestOwnDistance, tile.Distance); } else if (tile.Snake == state.EnemyIndex) { bestEnemyDistance = Math.Min(bestEnemyDistance, tile.Distance); } }
public float ScoreCached(CachedMetricState state) { var floodBoard = state.AdversarialFill.Tiles; int friendlyCounter = 0; int enemyCounter = 0; for (int i = 0; i < floodBoard.GetLength(0); ++i) { for (int j = 0; j < floodBoard.GetLength(1); ++j) { if (floodBoard[i, j].Snake == state.OwnIndex) { friendlyCounter++; } else if (floodBoard[i, j].Snake == state.EnemyIndex) { enemyCounter++; } } } return((((float)friendlyCounter / (enemyCounter + friendlyCounter)) - 0.5f) * 2.0f); }
public float Score(FastWorld state) { var me = state.Snakes[snakeIndex]; var enemy = state.Snakes[enemyIndex]; // Try to win as early as possible and lose or draw as late as possible // Also try to prefer death reasons which are not completely deterministic if (!me.Alive && !enemy.Alive) { return(-900.0f + state.Turn / 100.0f); } if (!me.Alive) { return(-1000.0f + state.Turn / 100.0f - ScoreKillReason(me.Status)); } if (!enemy.Alive) { return(1000.0f - state.Turn / 100.0f); } var cache = new CachedMetricState(state, snakeIndex, enemyIndex); return(ScoreDetail(cache)); }
public float ScoreCached(CachedMetricState state) { return((state.OwnFill.Count / ((float)state.OwnFill.Count + state.EnemyFill.Count) - 0.5f) * 2.0f); }
protected abstract float ScoreDetail(CachedMetricState state);