/// <summary> /// Attempt an attack. /// </summary> /// <param name="allAttacks">A list of WeaponDetails representing a round of attacks.</param> private bool ProcessAttack(WeaponDetails attack) { // First, check that the target stack we originally identified has not // been destroyed (actually, the stack still exists at this point but // it may have no ship tokens left). In which case, don't bother trying to // fire this weapon system (we'll wait until the next battle clock // "tick" and re-target then). if (attack.TargetStack == null || attack.TargetStack.IsDestroyed) { return(false); } if (attack.SourceStack == null || attack.SourceStack.IsDestroyed) { // Report.Error("attacking stack no longer exists"); return(false); } // If the target stack is not within the range of this weapon system // then there is no point in trying to fire it. if (PointUtilities.Distance(attack.SourceStack.Position, attack.TargetStack.Position) > attack.Weapon.Range) { return(false); } // Target is valid; execute attack. ExecuteAttack(attack); return(true); }
/// <summary> /// Check if the fleet hits the minefiled. /// </summary> /// <remarks> /// The probability of hitting a mine is 0.3% per light year traveled for each /// warp over the safe speed. /// TODO (priority 3) - reference required. /// /// Example: A fleet traveling at Warp 9 has a 1.5% chance per light year /// traveled in a turn. Traveling 10 light years through the Minefield that /// turn, the fleet has a 10.5% chance of triggering a mine. /// </remarks> /// <param name="fleet">The moving fleet.</param> /// <param name="minefield">The minefield being traversed.</param> /// <returns>true if the minefield is hit.</returns> private bool CheckForHit(Fleet fleet, Minefield minefield) { // Calculate how long we are going to be in the Minefield. This is the // lesser of the distance to the next waypoint and the radius of the // field. NovaPoint currentPosition = fleet.Position; Waypoint targetWaypoint = fleet.Waypoints[0]; NovaPoint targetPosition = targetWaypoint.Position; double travelDistance = PointUtilities.Distance(currentPosition, targetPosition); if (minefield.Radius > (int)travelDistance) { travelDistance = minefield.Radius; } double speeding = fleet.Speed - minefield.SafeSpeed; double probability = (0.03 * travelDistance * speeding) * 100; double dice = random.Next(0, 100); if (dice < probability) { return(true); } return(false); }
public void Test5PositionStacks() { battleEngine.PositionStacks(zoneStacks); double distance = 0; Fleet stackA = zoneStacks[0] as Fleet; Fleet stackB = zoneStacks[1] as Fleet; distance = PointUtilities.Distance(stackA.Position, stackB.Position); Assert.Greater((int)distance, 3); // changed from Global.MaxRange -1 to 3 due to reduction in battle board size from Ken's 20x20 to Stars! 10x10 - Dan 07 Jul 11 }
/// <summary> /// Determine if a fleet is within a Minefield. The fleet is inside the /// circle if the distance between the field and the center of the field is /// less than the radius of the field. /// </summary> private bool IsInField(Fleet fleet, Minefield minefield) { // If we are travelling at a "safe" speed we can just pretend we are // not in a Minefield. if (fleet.Speed <= minefield.SafeSpeed) { return(false); } double distance = PointUtilities.Distance(fleet.Position, minefield.Position); if (distance < minefield.Radius) { return(true); } return(false); }
public void Test6DoBattle() { Fleet stackA = zoneStacks[0] as Fleet; Fleet stackB = zoneStacks[1] as Fleet; List <Fleet> battlingFleets = new List <Fleet>(); battlingFleets.Add(stackA); battlingFleets.Add(stackB); double distanceS, distanceE; distanceS = PointUtilities.Distance(stackA.Position, stackB.Position); battleEngine.DoBattle(zoneStacks); distanceE = PointUtilities.Distance(stackA.Position, stackB.Position); // Check that the fleets have moved towards each other. Assert.Greater(distanceS, distanceE); }
/// <Summary> /// If there is another waypoint before the selected one, display the fuel, /// time, etc. required for this leg. /// </Summary> /// <param name="index">Index of the waypoint to display.</param> private void DisplayLegDetails(int index) { Waypoint thisWaypoint = selectedFleet.Waypoints[index]; WaypointTasks.Text = thisWaypoint.Task.Name; if (selectedFleet.Waypoints.Count == 1) { thisWaypoint.WarpFactor = 0; } selectedFleet.Waypoints[index] = thisWaypoint; warpFactor.Value = thisWaypoint.WarpFactor; warpText.Text = "Warp " + thisWaypoint.WarpFactor; if (index > 0 && thisWaypoint.WarpFactor > 0) { Waypoint from = selectedFleet.Waypoints[index - 1]; Waypoint to = selectedFleet.Waypoints[index]; double distance = PointUtilities.Distance(from.Position, to.Position); double time = distance / (to.WarpFactor * to.WarpFactor); double fuelUsed = selectedFleet.FuelConsumption(to.WarpFactor, empireState.Race) * time; legDistance.Text = string.Format("{0}", distance.ToString("f1")); legFuel.Text = string.Format("{0}", fuelUsed.ToString("f1")); legTime.Text = string.Format("{0}", time.ToString("f1")); } else { legDistance.Text = "0"; legFuel.Text = "0"; legTime.Text = "0"; } Waypoint previous = null; double fuelRequired = 0; // Sum up the total fuel required for all waypoints in the current // route (as long as there is more than one waypoint). foreach (Waypoint waypoint in selectedFleet.Waypoints) { if (previous != null && waypoint.WarpFactor > 0) { double distance = PointUtilities.Distance(waypoint.Position, previous.Position); int warp = waypoint.WarpFactor; double speed = warp * warp; double travelTime = distance / speed; fuelRequired += selectedFleet.FuelConsumption(warp, empireState.Race) * travelTime; } previous = waypoint; } System.Drawing.Color color = fuelRequired > selectedFleet.FuelAvailable ? System.Drawing.Color.Red : System.Drawing.Color.Black; routeFuelUse.ForeColor = color; label3.ForeColor = color; label5.ForeColor = color; routeFuelUse.Text = fuelRequired.ToString("f1"); }
/// ---------------------------------------------------------------------------- /// <Summary> /// Populate the display. We use unbound population because some of the fields /// need a little logic to decode (we don't just have a bunch of strings). /// </Summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="EventArgs"/> that contains the event data.</param> /// ---------------------------------------------------------------------------- private void OnLoad(object sender, EventArgs e) { const int NumColumns = 11; this.fleetGridView.Columns[6].Name = "Cargo"; this.fleetGridView.AutoSize = true; foreach (Fleet fleet in empireState.OwnedFleets.Values) { if (fleet.Owner == empireState.Id) { if (fleet.Type == ItemType.Starbase) { continue; } string location; if (fleet.InOrbit != null) { location = fleet.InOrbit.Name; } else { location = "Space at " + fleet.Position.ToString(); } string destination = "-"; string eta = "-"; string task = "-"; if (fleet.Waypoints.Count > 1) { Waypoint waypoint = fleet.Waypoints[1]; destination = waypoint.Destination; if (!(waypoint.Task is NoTask)) { task = waypoint.Task.Name; } double distance = PointUtilities.Distance( waypoint.Position, fleet.Position); double speed = waypoint.WarpFactor * waypoint.WarpFactor; double time = distance / speed; eta = time.ToString("F1"); } Cargo cargo = fleet.Cargo; StringBuilder cargoText = new StringBuilder(); cargoText.AppendFormat( "{0} {1} {2} {3}", cargo.Ironium, cargo.Boranium, cargo.Germanium, cargo.ColonistsInKilotons); int i = 0; string[] row = new string[NumColumns]; row[i++] = fleet.Name; row[i++] = location; row[i++] = destination; row[i++] = eta; row[i++] = task; row[i++] = fleet.FuelAvailable.ToString("f1"); row[i++] = cargoText.ToString(); row[i++] = fleet.Composition.Count.ToString(System.Globalization.CultureInfo.InvariantCulture); row[i++] = "-"; row[i++] = fleet.BattlePlan; row[i++] = fleet.Mass.ToString(System.Globalization.CultureInfo.InvariantCulture); this.fleetGridView.Rows.Add(row); } } this.fleetGridView.AutoResizeColumns(); }
private void Scan(EmpireData empire) { foreach (Mappable scanner in empire.IterateAllMappables()) { int scanRange = 0; int penScanRange = 0; //Do some self scanning (Update reports) and set ranges.. if (scanner is Star) { scanRange = (scanner as Star).ScanRange; penScanRange = (scanner as Star).ScanRange; // TODO:(priority 6) Planetary Pen-Scan not implemented yet. empire.StarReports[scanner.Name].Update(scanner as Star, ScanLevel.Owned, serverState.TurnYear); } else { scanRange = (scanner as Fleet).ScanRange; penScanRange = (scanner as Fleet).PenScanRange; empire.FleetReports[scanner.Key].Update(scanner as Fleet, ScanLevel.Owned, empire.TurnYear); } // Scan everything foreach (Mappable scanned in serverState.IterateAllMappables()) { // ...That isn't ours! if (scanned.Owner == empire.Id) { continue; } ScanLevel scanLevel = ScanLevel.None; double range = 0; range = PointUtilities.Distance(scanner.Position, scanned.Position); if (scanned is Star) { Star star = scanned as Star; // There are two ways to get information from a Star: // 1. In orbit with a fleet, // 2. Not in orbit with a Pen Scan (fleet or star). // Non penetrating distance scans won't tell anything about it. if ((scanner is Fleet) && range == 0) { scanLevel = (scanner as Fleet).CanScan ? ScanLevel.InDeepScan : ScanLevel.InPlace; } else // scanner is Star or non orbiting Fleet { scanLevel = (range <= penScanRange) ? ScanLevel.InDeepScan : ScanLevel.None; } // Dont update if we didn't scan to allow report to age. if (scanLevel == ScanLevel.None) { continue; } if (empire.StarReports.ContainsKey(scanned.Name)) { empire.StarReports[scanned.Name].Update((scanned as Star), scanLevel, serverState.TurnYear); } else { empire.StarReports.Add(scanned.Name, (scanned as Star).GenerateReport(scanLevel, serverState.TurnYear)); } } else // scanned is Fleet { // Fleets are simple as scan levels (PenScan for example) won't affect them. We only // care for non penetrating distance scans. if (range > scanRange) { continue; } // Check if we have a record of this design(s). foreach (ShipToken token in (scanned as Fleet).Composition.Values) { if (empire.EmpireReports[scanned.Owner].Designs.ContainsKey(token.Design.Key)) { continue; } // If not, add just the empty Hull. ShipDesign newDesign = new ShipDesign(token.Design); newDesign.Key = token.Design.Key; newDesign.ClearAllocated(); empire.EmpireReports[scanned.Owner].Designs.Add(newDesign.Key, newDesign); } if (!empire.FleetReports.ContainsKey(scanned.Key)) { empire.FleetReports.Add(scanned.Key, (scanned as Fleet).GenerateReport(ScanLevel.InScan, serverState.TurnYear)); } else { empire.FleetReports[scanned.Key].Update((scanned as Fleet), ScanLevel.InScan, serverState.TurnYear); } } } } }