public double GetResourceScoreSlice( Galaxy galaxy, List <int> players, Dictionary <int, List <SystemTile> > sliceClaim, Dictionary <int, List <SystemTile> > sliceContest, ResourceScoreMethod resMethod = ResourceScoreMethod.MaxVal, double ResInfRatio = 1.0, double ResScaling = 2.0) { double resourceScore = 0; switch (resMethod) { case ResourceScoreMethod.Separate: double bestRes = double.MinValue; double worstRes = double.MaxValue; double bestInf = double.MinValue; double worstInf = double.MaxValue; foreach (int player in players) { double res = sliceVal(sliceClaim[player], sliceContest[player], res: true); bestRes = res > bestRes ? res : bestRes; worstRes = res < worstRes ? res : worstRes; double inf = sliceVal(sliceClaim[player], sliceContest[player], res: false); bestInf = inf > bestInf ? inf : bestInf; worstInf = inf < worstInf ? inf : worstInf; } resourceScore = (Math.Pow(worstRes / bestRes, ResScaling) + ResInfRatio * Math.Pow(worstInf / bestInf, ResScaling)); resourceScore /= (1 + ResInfRatio); break; case ResourceScoreMethod.DirectSum: double best = double.MinValue; double worst = double.MaxValue; foreach (int player in players) { double resValue = sliceVal(sliceClaim[player], sliceContest[player], res: true); double infValue = sliceVal(sliceClaim[player], sliceContest[player], res: true); double value = resValue + ResInfRatio * infValue; best = value > best ? value : best; worst = value < worst ? value : worst; } resourceScore = Math.Pow(worst / best, ResScaling); break; case ResourceScoreMethod.MaxVal: default: double bestVal = double.MinValue; double worstVal = double.MaxValue; foreach (int player in players) { double maxVal = 0; if (sliceClaim[player].Where(tile => tile.planets.Count > 0).Count() > 0) { maxVal += sliceClaim[player].Where(tile => tile.planets.Count > 0).Select(tile => tile.planets.Select(planet => Math.Max(planet.resources, ResInfRatio * planet.influence) ).Aggregate((i, j) => i + j) ).Aggregate((i, j) => i + j); } if (sliceContest[player].Where(tile => tile.planets.Count > 0).Count() > 0) { maxVal += sliceContest[player].Where(tile => tile.planets.Count > 0).Select(tile => (double)(tile.planets.Select(planet => Math.Max(planet.resources, ResInfRatio * planet.influence) ).Aggregate((i, j) => i + j)) / tile.contestedBy.Count() ).Aggregate((i, j) => i + j); } bestVal = maxVal > bestVal ? maxVal : bestVal; worstVal = maxVal < worstVal ? maxVal : worstVal; } resourceScore = Math.Pow(worstVal / bestVal, ResScaling); break; } return(resourceScore); }
public double scoreGalaxy( Galaxy galaxy, bool bothHoles = true, bool hardHoleLimit = true, int HoleCount = 2, bool allowAdjacentHoles = false, bool allowAdjacentAnomalies = false, ContestValue contestMethod = ContestValue.ClaimSize, ResourceScoreMethod resMethod = ResourceScoreMethod.MaxVal, double ResInfRatio = 1.0, double ResScaling = 2.0, double claimExponent = -3.0) { double score = 0.0; double resourceScore = 0.0; int MaxRadius = galaxy.MaxRadius; SystemTile[][] tiles = galaxy.tiles; List <Tuple <int, int> > HSLocations = galaxy.HSLocations; if (!wormholesOK( galaxy, bothHoles, hardHoleLimit, HoleCount, allowAdjacentHoles)) { return(0.0); } if (!AnomaliesOK(galaxy, allowAdjacentAnomalies)) { return(0.0); } List <int> players; Dictionary <int, List <SystemTile> > sliceClaim; Dictionary <int, List <SystemTile> > sliceContest; (players, sliceClaim, sliceContest) = StakeClaims(galaxy); if (contestMethod == ContestValue.Slices) { resourceScore = GetResourceScoreSlice( galaxy, players, sliceClaim, sliceContest, resMethod, ResInfRatio, ResScaling); } else { resourceScore = GetResourceScoreClaims( galaxy, players, resMethod, contestMethod, ResInfRatio, ResScaling, claimExponent); } score = resourceScore; return(score); }
public double GetResourceScoreClaims( Galaxy galaxy, List <int> players, ResourceScoreMethod resMethod = ResourceScoreMethod.MaxVal, ContestValue contestMethod = ContestValue.TopAndRunnerUp, double ResInfRatio = 1.0, double ResScaling = 2.0, double claimExponent = -2.0) { Dictionary <int, double> resourceClaims = new Dictionary <int, double>(); foreach (int pnum in players) { resourceClaims.Add(pnum, 0); } int MaxRadius = galaxy.MaxRadius; for (int x = 0; x <= 2 * MaxRadius; x++) { for (int y = 0; y <= 2 * MaxRadius; y++) { SystemTile tile = galaxy.tiles[x][y]; if (tile.sysNum > 0 && tile.planets.Count() > 0) { Dictionary <int, double> claims = new Dictionary <int, double>(); foreach (int pnum in tile.claims.Keys) { switch (contestMethod) { case ContestValue.Slices: if (claims[pnum] == tile.bestClaim) { claims.Add(pnum, 1.0); } break; case ContestValue.ClaimSize: if (tile.bestClaim > 0) { claims.Add(pnum, Math.Pow(tile.claims[pnum], claimExponent)); } else if (claims[pnum] == tile.bestClaim) { claims.Add(pnum, 1.0); } break; case ContestValue.TopAndRunnerUp: if (tile.bestClaim == 0 && claims[pnum] == tile.bestClaim) { claims.Add(pnum, 1.0); } else if (claims[pnum] == tile.bestClaim || claims[pnum] == tile.secondBestClaim) { claims.Add(pnum, Math.Pow(tile.claims[pnum], claimExponent)); } break; } } if (claims.Count() == 0) { throw new Exception("Every system should have at least one claim, right?"); } double claimScale = claims.Sum(claim => claim.Value); foreach (KeyValuePair <int, double> claim in claims) { double val = 0.0; switch (resMethod) { case ResourceScoreMethod.DirectSum: val = tile.GetResources() + ResInfRatio * tile.GetInfluence(); break; case ResourceScoreMethod.Separate: throw new Exception("Not supporting \"separate\" for claim method"); case ResourceScoreMethod.MaxVal: val = tile.planets.Sum(planet => Math.Max(planet.resources, ResInfRatio * planet.influence)); break; } tile.adjClaims.Add(claim.Key, claim.Value / claimScale); resourceClaims[claim.Key] += val * claim.Value / claimScale; } } } } double minSlice = resourceClaims.Min(claim => claim.Value); double maxSlice = resourceClaims.Max(claim => claim.Value); return(Math.Pow(minSlice / maxSlice, ResScaling)); }