internal static Bundle GetBestUtilityBundle(BlueprintUtilityBuilding building, GameLayer layer) { switch (building.BuildingName) { case "WindTurbine": return(GetBestWindTurbineBundle(building, layer)); case "Mall": return(GetBestMallBundle(building, layer)); case "Park": return(GetBestParkBundle(building, layer)); default: return(null); } }
private static Bundle GetBestWindTurbineBundle(BlueprintUtilityBuilding building, GameLayer layer) { var state = layer.GetState(); Position pos = GetBestUtilityPosition(layer, building); if (pos == null) { return(null); } int turnsLeft = state.MaxTurns - state.Turn - 5; double energySaved = 0; int avalibleSpace = 0; for (int k = -2; k < 3; k++) { for (int c = -2; c < 3; c++) { int i = pos.x; int j = pos.y; if (Math.Abs(k) + Math.Abs(c) > 2 || !Helper.InGrid(i + k, j + c, state) || state.Map[i + k][j + c] == 1 || (k == 0 && c == 0)) { continue; } if (state.ResidenceBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c && !x.Effects.Contains(building.BuildingName))) { BuiltBuilding b = state.ResidenceBuildings.First(x => x.Position.x == i + k && x.Position.y == j + c); energySaved += Math.Min(3.4, Math.Max(b.EffectiveEnergyIn - (b.Effects.Contains("SolarPanel") ? 3.4 : 0), 0)); } if (state.UtilityBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c && x.BuildingName != "WindTurbine" && !x.Effects.Contains(building.BuildingName))) { BuiltBuilding b = state.UtilityBuildings.First(x => x.Position.x == i + k && x.Position.y == j + c); energySaved += Math.Min(3.4, Math.Max(b.EffectiveEnergyIn - (b.Effects.Contains("SolarPanel") ? 3.4 : 0), 0)); } else if (!state.ResidenceBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c) && !state.UtilityBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c)) { avalibleSpace++; } else if (state.UtilityBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c)) { avalibleSpace--; } } } EnergyLevel el = Helper.GetEnergyLevel(layer, Helper.GetEnergyConsumation(layer)); EnergyLevel elAfter = Helper.GetEnergyLevel(layer, Helper.GetEnergyConsumation(layer) - energySaved); double potentialScore = -25; potentialScore -= 25 * Constants.AVG_POP_HAPPINESS * turnsLeft / 20.0; if (!state.UtilityBuildings.Any(t => t.BuildingName == building.BuildingName)) { potentialScore += 15 * 0.15 * turnsLeft / 2; } potentialScore += el.TonCo2PerMwh * Helper.GetEnergyConsumation(layer) * turnsLeft - (elAfter.TonCo2PerMwh * (Helper.GetEnergyConsumation(layer) - energySaved)) * turnsLeft; if (Helper.GetPossibleMorePop(layer, 1) + Helper.GetCurrentMaxPop(layer) < Constants.TARGET_END_POP_COUNT) { return(null); } Bundle bundle = new Bundle { UpfrontCost = building.Cost, TotalIncome = turnsLeft * elAfter.CostPerMwh * energySaved,//saved on electicity ExtraCost = 0, Turn = new PlaceUtilityTurn(pos.x, pos.y, building, layer.GetState().GameId), PotentialScore = potentialScore, EnergyNeed = -energySaved }; return(bundle); }
private static Bundle GetBestMallBundle(BlueprintUtilityBuilding building, GameLayer layer) { var state = layer.GetState(); Position pos = GetBestUtilityPosition(layer, building); if (pos == null) { return(null); } int turnsLeft = state.MaxTurns - state.Turn - 8; if (state.UtilityBuildings.Any(t => t.BuildingName == "Mall")) { return(null); } var arr = Helper.GetUtilitiyGrid(state); int popAffected = 0; int popOne = 0; int avalibleSpace = 0; int avSpaceOne = 0; for (int k = -3; k < 4; k++) { for (int c = -3; c < 4; c++) { int i = pos.x; int j = pos.y; if (Math.Abs(k) + Math.Abs(c) > 3 || !Helper.InGrid(i + k, j + c, state) || state.Map[i + k][j + c] == 1 || (k == 0 && c == 0)) { continue; } if (state.ResidenceBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c && !x.Effects.Any(t => t.StartsWith(building.BuildingName)))) { popAffected += layer.GetResidenceBlueprint(state.ResidenceBuildings.Find(x => x.Position.x == i + k && x.Position.y == j + c).BuildingName).MaxPop; if ((Math.Abs(k) + Math.Abs(c) == 1)) { popOne += layer.GetResidenceBlueprint(state.ResidenceBuildings.Find(x => x.Position.x == i + k && x.Position.y == j + c).BuildingName).MaxPop; } } else if (!state.ResidenceBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c) && !state.UtilityBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c) && (arr[i + k, j + c] & Helper.UtilityToInt[building.BuildingName]) != Helper.UtilityToInt[building.BuildingName]) { avalibleSpace++; if ((Math.Abs(k) + Math.Abs(c) == 1)) { avSpaceOne++; } } else if (state.UtilityBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c)) { avalibleSpace--; } } } EnergyLevel el = Helper.GetEnergyLevel(layer, Helper.GetEnergyConsumation(layer)); EnergyLevel elAfter = Helper.GetEnergyLevel(layer, Helper.GetEnergyConsumation(layer) + 8 - (state.UtilityBuildings.Any(t => t.BuildingName == "WindTurbine" && Math.Abs(pos.x - t.Position.x) + Math.Abs(pos.y - t.Position.y) <= 2) ? 3.4 : 0)); double potentialScore = -200 - (popAffected - popOne) * 0.009 / 2 * turnsLeft - (Math.Max(0, (avalibleSpace - avSpaceOne)) * 15.0 / 10.0) * 0.009 / 2 * turnsLeft + 0.12 * (popAffected + avalibleSpace * 25.0 / 3.0) * turnsLeft / 10; //potentialScore -= 25 * Constants.AVG_POP_HAPPINESS * turnsLeft / 20.0; if (!state.UtilityBuildings.Any(t => t.BuildingName == building.BuildingName)) { potentialScore += 15 * 0.15 * turnsLeft / 2; } if (el.CostPerMwh != elAfter.CostPerMwh) { potentialScore -= (elAfter.TonCo2PerMwh - el.TonCo2PerMwh) * Helper.GetEnergyConsumation(layer) * turnsLeft; } potentialScore -= turnsLeft * elAfter.TonCo2PerMwh * (8 - (state.UtilityBuildings.Any(t => t.BuildingName == "WindTurbine" && Math.Abs(pos.x - t.Position.x) + Math.Abs(pos.y - t.Position.y) <= 2) ? 3.4 : 0)); if (Helper.GetPossibleMorePop(layer, 1) + Helper.GetCurrentMaxPop(layer) < Constants.TARGET_END_POP_COUNT) { return(null); } Bundle bundle = new Bundle { UpfrontCost = building.Cost, TotalIncome = Math.Pow(0.5, state.UtilityBuildings.Where(t => t.BuildingName == building.BuildingName).Count()) * 240 * turnsLeft, ExtraCost = elAfter.CostPerMwh * (8 - (state.UtilityBuildings.Any(t => t.BuildingName == "WindTurbine" && Math.Abs(pos.x - t.Position.x) + Math.Abs(pos.y - t.Position.y) <= 2) ? 3.4 : 0)) * turnsLeft, Turn = new PlaceUtilityTurn(pos.x, pos.y, building, layer.GetState().GameId), PotentialScore = potentialScore, EnergyNeed = 8 - (state.UtilityBuildings.Any(t => t.BuildingName == "WindTurbine" && Math.Abs(pos.x - t.Position.x) + Math.Abs(pos.y - t.Position.y) <= 2) ? 3.4 : 0) }; return(bundle); }
private static Bundle GetBestParkBundle(BlueprintUtilityBuilding building, GameLayer layer) { var state = layer.GetState(); Position pos = GetBestUtilityPosition(layer, building); if (pos == null) { return(null); } int turnsLeft = state.MaxTurns - state.Turn - 5; var arr = Helper.GetUtilitiyGrid(layer.GetState()); int popAffected = 0; int avalibleSpace = 0; for (int k = -3; k < 4; k++) { for (int c = -3; c < 4; c++) { int i = pos.x; int j = pos.y; if (Math.Abs(k) + Math.Abs(c) > 2 || !Helper.InGrid(i + k, j + c, state) || state.Map[i + k][j + c] == 1 || (k == 0 && j == 0)) { continue; } if (state.ResidenceBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c && !x.Effects.Contains(building.BuildingName))) { popAffected += layer.GetResidenceBlueprint(state.ResidenceBuildings.First(x => x.Position.x == i + k && x.Position.y == j + c).BuildingName).MaxPop; } else if (!state.ResidenceBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c) && !state.UtilityBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c) && (arr[i + k, j + c] & Helper.UtilityToInt[building.BuildingName]) != Helper.UtilityToInt[building.BuildingName]) { avalibleSpace++; } else if (state.UtilityBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c)) { avalibleSpace--; } } } EnergyLevel el = Helper.GetEnergyLevel(layer); EnergyLevel elAfter = Helper.GetEnergyLevel(layer, Helper.GetEnergyConsumation(layer) + Math.Max(0, 2.4 - (state.UtilityBuildings.Any(t => t.BuildingName == "WindTurbine" && Math.Abs(pos.x - t.Position.x) + Math.Abs(pos.y - t.Position.y) <= 2) ? 2.4 : 0))); double potentialScore = -10 + (popAffected + avalibleSpace * 30.0 / 6.0) * 0.007 * turnsLeft + 0.11 * (popAffected + avalibleSpace * 30.0 / 6.0) * turnsLeft / 10; if (!state.UtilityBuildings.Any(t => t.BuildingName == building.BuildingName)) { potentialScore += 15 * 0.15 * turnsLeft / 2; } else { potentialScore -= 20 * Constants.AVG_POP_HAPPINESS * turnsLeft / 20.0; } if (el.CostPerMwh != elAfter.CostPerMwh) { potentialScore -= (elAfter.TonCo2PerMwh - el.TonCo2PerMwh) * Helper.GetEnergyConsumation(layer); } potentialScore -= turnsLeft * elAfter.TonCo2PerMwh * Math.Max(0, 2.4 - (state.UtilityBuildings.Any(t => t.BuildingName == "WindTurbine" && Math.Abs(pos.x - t.Position.x) + Math.Abs(pos.y - t.Position.y) <= 2) ? 2.4 : 0)); if (Helper.GetPossibleMorePop(layer, 1) + Helper.GetCurrentMaxPop(layer) < Constants.TARGET_END_POP_COUNT) { return(null); } Bundle bundle = new Bundle { UpfrontCost = building.Cost, TotalIncome = 0, ExtraCost = el.CostPerMwh * (2.4 - (state.UtilityBuildings.Any(t => t.BuildingName == "WindTurbine" && Math.Abs(pos.x - t.Position.x) + Math.Abs(pos.y - t.Position.y) <= 2) ? 2.4 : 0)) * turnsLeft, Turn = new PlaceUtilityTurn(pos.x, pos.y, building, layer.GetState().GameId), PotentialScore = potentialScore, EnergyNeed = Math.Max(0, 2.4 - (state.UtilityBuildings.Any(t => t.BuildingName == "WindTurbine" && Math.Abs(pos.x - t.Position.x) + Math.Abs(pos.y - t.Position.y) <= 2) ? 2.4 : 0)) }; return(bundle); }
private static Position GetBestUtilityPosition(GameLayer layer, BlueprintUtilityBuilding building) { int radius = 2; if (building.BuildingName == "Mall") { radius = 3; } var state = layer.GetState(); var arr = Helper.GetUtilitiyGrid(state); Position ret = new Position(-1, -1); int fd = 0; int sd = 0; for (int i = 0; i < arr.GetLength(0); i++) { for (int j = 0; j < arr.GetLength(1); j++) { if (state.Map[i][j] != 0 || state.ResidenceBuildings.Any(x => x.Position.x == i && x.Position.y == j) || state.UtilityBuildings.Any(x => x.Position.x == i && x.Position.y == j)) { continue; } int cnt = 0; int avSpace = 0; for (int k = -3; k < 4; k++) { for (int c = -3; c < 4; c++) { if (Math.Abs(k) + Math.Abs(c) > radius || !Helper.InGrid(i + k, j + c, state) || state.Map[i + k][j + c] != 0 || (k == 0 && c == 0)) { continue; } if (state.ResidenceBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c && !x.Effects.Any(t => t.StartsWith(building.BuildingName))) || (building.BuildingName == "WindTurbine" && state.UtilityBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c && x.BuildingName != "WindTurbine" && !x.Effects.Contains(building.BuildingName)))) { cnt++; } else if (!state.ResidenceBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c) && !state.UtilityBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c) && (arr[i + k, j + c] & Helper.UtilityToInt[building.BuildingName]) != Helper.UtilityToInt[building.BuildingName]) { avSpace++; } else if (state.UtilityBuildings.Any(x => x.Position.x == i + k && x.Position.y == j + c && building.BuildingName != "WindTurbine")) { avSpace--; } } } if (cnt > fd) { fd = cnt; sd = avSpace; ret.x = i; ret.y = j; } else if (cnt == fd && avSpace > sd) { fd = cnt; sd = avSpace; ret.x = i; ret.y = j; } } } if (ret.x == -1) { return(null); // NO POSSIBLE POSITION } return(ret); }
public PlaceUtilityTurn(int x, int y, BlueprintUtilityBuilding bp, string gameId) : base(gameId) { bluePrint = bp; this.x = x; this.y = y; }