public float Score(CachedMultiMetricState state, int index) { var me = state.World.Snakes[index]; float score = 0.0f; if (!state.World.Snakes[BountySnake].Alive && index != BountySnake) { // Be really pessimistic everybody hates us score += 2000.0f; } // 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) { return(score - 1000.0f + state.World.Turn / 100.0f - BaseDuellingHeuristic.ScoreKillReason(me.Status)); } else if (IsTerminal(state)) { // High score if we are the sole survivor, try to win earlier return(score + 1000.0f - state.World.Turn / 100.0f); } // Else evaluate detailed heuristic if no terminal return(ScoreDetail(state, index)); }
public float ScoreCached(CachedMultiMetricState state, int ownIndex) { var self = state.World.Snakes[ownIndex]; bool ownTailReachable = state.AdversarialFill.Tiles[self.Tail.Y, self.Tail.X].Snake == ownIndex; if (!ownTailReachable) { bool sufficientSpace = state.AdversarialFill.EmptyCounts[ownIndex] > self.MaxLength; return(sufficientSpace ? 1.0f : -1.0f); } else { return(1.0f); } }
public float Score(CachedMultiMetricState s, int index) { if (s.World.Snakes[index].Health > SatisfactionThreshold) { return(1.0f); } int bestOwnDistance = int.MaxValue; foreach (var fruit in s.World.Fruits) { ref var tile = ref s.AdversarialFill.Tiles[fruit.Y, fruit.X]; if (tile.Snake == index) { bestOwnDistance = Math.Min(bestOwnDistance, tile.Distance); } }
protected override float ScoreDetail(CachedMultiMetricState state, int index) { var me = state.World.Snakes[index]; float score = 0.0f; var fill = Util.CountBasicFloodFill(state.World, me.Head); var deltaLengthScore = 12.0f * deltaLengthFoodMetric.Score(state.World, index, fill); var controlScore = 1.0f * controlMetric.Score(state, index); var hungerScore = 10.0f * hungerPressureMetric.Score(state, index); var distanceTailScore = TailScoreMultiplier * distanceToOwnTailMetric.ScoreCached(state, index); score += deltaLengthScore + controlScore + hungerScore + (me.MaxLength > 6 ? distanceTailScore : 0.0f); return(score); }
public float Score(CachedMultiMetricState s, int index) { var adversarialFill = s.AdversarialFill.EmptyCounts; int friendlyCounter = adversarialFill[index]; int sum = 0; for (int i = 0; i < adversarialFill.Count; ++i) { sum += adversarialFill[i]; } if (sum == 0) { return(0.0f); } float score = ((friendlyCounter / (float)sum) - 0.5f) * 2.0f; Debug.Assert(!float.IsNaN(score)); return(score); }
protected abstract float ScoreDetail(CachedMultiMetricState state, int index);
public bool IsTerminal(CachedMultiMetricState state) { return(state.World.IsDecided || !state.World.Snakes[BountySnake].Alive); }