private Game(Game _g) { Planets = new List<Planet>(); foreach (Planet p in _g.Planets) { Planets.Add((Planet)(p.clone())); } Fleets = new List<Fleet>(); foreach (Fleet f in _g.Fleets) { Fleets.Add((Fleet)(f.clone())); } //PORT: Strings are immutable if (_g.mapFilename != null) mapFilename = _g.mapFilename; if (_g.mapData != null) mapData = _g.mapData; initMode = _g.initMode; if (_g.gamePlayback != null) gamePlayback = new StringBuilder(_g.gamePlayback.ToString()); maxGameLength = _g.maxGameLength; numTurns = _g.numTurns; // Dont need to init the drawing stuff (it does it itself) }
public static bool CheckForAlliveOrDropPlayer(Game engine, botDebugBase player) { if (engine.IsAlive(player.Id)) return true; else { engine.DropPlayer(player.Id); return false; } }
public bool Start() { if (IsRunning) { return false; } else { System.Diagnostics.Debug.Assert(Player1 != null, "Player 1 should be assigned"); System.Diagnostics.Debug.Assert(Player2 != null, "Player 2 should be assigned"); System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(MapName), "MapName should be assigned"); if (MaxTurns <= 0) { MaxTurns = 200; } Aborted = false; IsRunning = true; TurnsPlayed = 0; PlayerWinnerId = 0; try { engine = new Game(MapName, MaxTurns, 0, null); engine.Init(); List<botDebugBase> players = new List<botDebugBase>(); players.Add(Player1); players.Add(Player2); IQueryable<botDebugBase> parallel = players.AsQueryable<botDebugBase>(); int turnsLeft = MaxTurns; // I looked at the original engine, which had a lot of overhead because it was working with application instances // and was capturing the output. Since I have a direct instance to the bot (wall, the debug wrapper) I can skip a lot of that // and just use the bare essentials. while (turnsLeft > 0 && (engine.Winner()) < 0) { if (!SilentGameEngine.CheckForAlliveOrDropPlayer(engine, players[0])) PlayerWinnerId = 1; if (!SilentGameEngine.CheckForAlliveOrDropPlayer(engine, players[1])) PlayerWinnerId = 2; if (PlayerWinnerId > 0) break; players.ForEach(player => player.GameBoardData = engine.PovRepresentation(player.Id)); foreach (botDebugBase player in parallel) { PushGameDataToPlayer(player); } turnsLeft--; if (Aborted) { return false; } else { TurnsPlayed++; engine.FlushGamePlaybackString(); engine.DoTimeStep(); if (!SilentGameEngine.CheckForAlliveOrDropPlayer(engine, players[0])) PlayerWinnerId = 1; if (!SilentGameEngine.CheckForAlliveOrDropPlayer(engine, players[1])) PlayerWinnerId = 2; if (PlayerWinnerId > 0) break; } } } finally { IsRunning = false; } return true; } }
// Renders the current state of the game to a graphics object // // The offset is a number between 0 and 1 that specifies how far we are // past this game state, in units of time. As this parameter varies from // 0 to 1, the fleets all move in the forward direction. This is used to // fake smooth animation. // // On success, return an image. If something goes wrong, returns null. public void Render(Game gameData, Image bgImage, // Background image ColorDictionary colors, Graphics canvas, botDebugBase getPlayerStats) { _Canvas = canvas; MyColors = colors; try { int width = (int)(Width * 0.9); int height = (int)(Height * 0.9); PointF offset = new PointF(Width - width - 30, Height - height - 15); List<Planet> planets = gameData.Planets; List<Fleet> fleets = gameData.Fleets; if (bgImage != null) { _Canvas.DrawImage(bgImage, 0, 0); } else { _Canvas.FillRectangle(Brushes.LightGray, _Canvas.ClipBounds); } // Determine the dimensions of the viewport in game coordinates. double _top = Double.MAX_VALUE; double _left = Double.MAX_VALUE; double _right = Double.MIN_VALUE; double _bottom = Double.MIN_VALUE; int maxGrowthRate = 0; foreach (Planet p in planets) { if (p.X < _left) _left = p.X; if (p.X > _right) _right = p.X; if (p.Y > _bottom) _bottom = p.Y; if (p.Y < _top) _top = p.Y; if (p.GrowthRate > maxGrowthRate) maxGrowthRate = p.GrowthRate; } _left--; _right++; _top--; _bottom++; int _xRange = (int)_right - (int)_left; int _yRange = (int)_bottom - (int)_top; PointF sizePerUnit = new PointF((float)width / (_xRange), (float)height / (_yRange)); double minSizeFactor = 5.0 + (sizePerUnit.X / maxGrowthRate); Point[] planetPos = new Point[planets.Count]; RectangleF bounds = new RectangleF((float)(offset.X), (float)(offset.Y), (float)width, (float)height); PointF origin = new PointF((float)(bounds.Left - (_left * sizePerUnit.X)), (float)(bounds.Top - (_top * sizePerUnit.Y))); if (DrawGrid) { for (float iGridX = (int)_left; iGridX <= _xRange; iGridX++) { float newX = origin.X + (iGridX * sizePerUnit.X); PointF gridTop = new PointF(newX, bounds.Top); PointF gridBottom = new PointF(newX, bounds.Bottom); _Canvas.DrawLine(MyColors.GetPen(RenderColor.GridLine), gridTop, gridBottom); string linesString = iGridX.ToString(); WriteTextInElLipseWithBorder(RenderColor.GridDark, RenderColor.GridLight, linesString, font50, gridTop, true, false); WriteTextInElLipseWithBorder(RenderColor.GridDark, RenderColor.GridLight, linesString, font50, gridBottom, false, false); } for (float iGridY = (int)_top; iGridY <= _yRange; iGridY++) { float newY = origin.Y + ((float)_bottom - iGridY) * sizePerUnit.Y; PointF gridLeft = new PointF(offset.X, newY); PointF gridRight = new PointF(bounds.Right, newY); _Canvas.DrawLine(MyColors.GetPen(RenderColor.GridLine), gridLeft, gridRight); string linesString = iGridY.ToString(); WriteTextInElLipseWithBorder(RenderColor.GridDark, RenderColor.GridLight, linesString, font50, gridLeft, true, true); WriteTextInElLipseWithBorder(RenderColor.GridDark, RenderColor.GridLight, linesString, font50, gridRight, false, false); } } // Draw the planets. int idx = 0; int[] growthRatesCounter = new int[4]; int[] inbaseCounter = new int[4]; int[] planetCounter = new int[4]; int[] planetOwnerIds = new int[planets.Count]; foreach (Planet planet in planets) { growthRatesCounter[planet.Owner] += planet.GrowthRate; growthRatesCounter[3] += planet.GrowthRate; inbaseCounter[planet.Owner] += planet.NumShips; inbaseCounter[3] += planet.NumShips; planetCounter[planet.Owner] += 1; planetCounter[3] += 1; int newX = (int)(origin.X + (planet.X * sizePerUnit.X)); int newY = (int)(bounds.Bottom - (planet.Y * sizePerUnit.Y)); Point pos = new Point(newX, newY); planetPos[idx] = pos; planetOwnerIds[idx++] = planet.Owner; int x = pos.X; int y = pos.Y; double size = minSizeFactor * (planet.GrowthRate + 0.5); double r = size; double cx = x - r / 2; double cy = y - r / 2; Brush fillColor = MyColors.GetDarkBrush(planet.Owner); Pen textColor = MyColors.GetLightPen(planet.Owner); if (planet.GrowthRate == 0) { fillColor = Brushes.Black; } else { bool canSurvive = true; if (getPlayerStats != null) { canSurvive = getPlayerStats.QueryPlanetCanSurviveAttack(planet.PlanetID); } if (!canSurvive) { textColor = MyColors.GetDarkPen(planet.Owner); fillColor = MyColors.GetLightBrush(planet.Owner); } } _Canvas.FillEllipse(fillColor, (int)cx, (int)cy, (int)r, (int)r); _Canvas.DrawEllipse(textColor, (int)cx, (int)cy, (int)r, (int)r); } if (ShortestRoute != null) { Planet current = null; foreach (Planet next in ShortestRoute) { if (current != null) { Point from = planetPos[current.PlanetID]; Point to = planetPos[next.PlanetID]; _Canvas.DrawLine(Pens.Black, from, to); } current = next; } } int[] inTransitCounter = new int[4]; int[] approachingFleetTotalCount = new int[planets.Count]; int[] approachingFleetAttackCount = new int[planets.Count]; int[] approachingFleetDefenceCount = new int[planets.Count]; //Draw in two passes, first the lines, then the labels. for (int passCount = 1; passCount < 3; passCount++) { foreach (Fleet fleet in fleets) { if (DetermineShouldDrawPlayer(fleet.Owner)) { if (passCount == 1) { inTransitCounter[fleet.Owner] += fleet.NumShips; inTransitCounter[3] += fleet.NumShips; if (fleet.Owner == planets[fleet.DestinationPlanet].Owner) { approachingFleetTotalCount[fleet.DestinationPlanet] += fleet.NumShips; approachingFleetDefenceCount[fleet.DestinationPlanet] += fleet.NumShips; } else { approachingFleetTotalCount[fleet.DestinationPlanet] -= fleet.NumShips; approachingFleetAttackCount[fleet.DestinationPlanet] -= fleet.NumShips; } } Point sPos = planetPos[fleet.SourcePlanet]; Point dPos = planetPos[fleet.DestinationPlanet]; float tripProgress = 1.0f - (float)fleet.TurnsRemaining / (float)fleet.TotalTripLength; if (tripProgress > 0.99 || tripProgress < 0.01) { continue; } int fleetOwnerOffset = (fleet.Owner - 1) * 2; float dx = dPos.X - sPos.X + fleetOwnerOffset; float dy = dPos.Y - sPos.Y + fleetOwnerOffset; PointF fleetCenter = new PointF( sPos.X + dx * tripProgress + fleetOwnerOffset, sPos.Y + dy * tripProgress + fleetOwnerOffset); if (passCount == 1 && DrawAttacklines) { Pen myPen = MyColors.GetPen(RenderColor.FleetOutgoingAttackLine); if (fleet.Owner == 1) { if (planetOwnerIds[fleet.DestinationPlanet] == fleet.Owner) { myPen = MyColors.GetPen(RenderColor.FleetDefensiveLine); } } else { myPen = MyColors.GetPen(RenderColor.FleetIncomingAttackLine); _Canvas.DrawLine(myPen, dPos.X + 1, dPos.Y, fleetCenter.X + 1, fleetCenter.Y); _Canvas.DrawLine(myPen, dPos.X, dPos.Y + 1, fleetCenter.X, fleetCenter.Y + 1); } _Canvas.DrawLine(myPen, dPos, fleetCenter); } if (passCount == 2 || (passCount == 1 && !DrawAttacklines)) { SizeF tSize = _Canvas.MeasureString(fleet.NumShips.ToString(), font100); fleetCenter = new PointF((fleetCenter.X - tSize.Width / 2), (fleetCenter.Y - tSize.Height / 2)); RenderColor background = MyColors.GetDarkColor(fleet.Owner); RenderColor foreground = MyColors.GetLightColor(fleet.Owner); RectangleF fleetrect = WriteTextInElLipseWithBorder(background, foreground, fleet.NumShips, font100b, fleetCenter, false, false); if (DrawFleetArrival) { fleetCenter = new PointF(fleetrect.Right + 5, fleetrect.Bottom + 5); WriteTextInElLipseWithBorder(RenderColor.FleetDistanceDark, RenderColor.FleetDistanceLight, fleet.TurnsRemaining, font25, fleetCenter, true, true); } } } } if (!DrawAttacklines) { break; } } foreach (Planet planet in planets) { Point sPos = planetPos[planet.PlanetID]; WriteTextInElLipseWithBorder(RenderColor.PlanetIdDark, RenderColor.PlanetIdLight, planet.PlanetID, font75b, sPos, true, true); RectangleF goRight = WriteTextInElLipseWithBorder(RenderColor.PlanetGrowthDark, RenderColor.PlanetGrowthLight, planet.GrowthRate, font75, sPos, false, true); sPos = new Point((int)goRight.Right, (int)goRight.Bottom); RectangleF goUp = WriteTextInElLipseWithBorder(RenderColor.PlanetNumShipsDark, RenderColor.PlanetNumShipsLight, planet.NumShips, font50b, sPos, true, false); if (DrawPlanetStatistics) { sPos = new Point((int)goUp.Left + 2, (int)goUp.Top); goRight = WriteTextInElLipseWithBorder(RenderColor.PlanetAttackDark, RenderColor.PlanetAttackLight, approachingFleetAttackCount[planet.PlanetID], font25, sPos, true, false); sPos = new Point((int)goRight.Right, (int)goUp.Top); WriteTextInElLipseWithBorder(RenderColor.PlanetDefenceDark, RenderColor.PlanetDefenceLight, approachingFleetDefenceCount[planet.PlanetID], font25, sPos, true, false); sPos = new Point((int)goRight.Left, (int)goRight.Top); int nettEffect = approachingFleetTotalCount[planet.PlanetID]; if (nettEffect < 0) { WriteTextInElLipseWithBorder(RenderColor.PlanetAttackNettoNegativeDark, RenderColor.PlanetAttackNettoNegativeLight, nettEffect, font25b, sPos, true, false); } else { WriteTextInElLipseWithBorder(RenderColor.PlanetAttackNettoPositiveDark, RenderColor.PlanetAttackNettoPositiveLight, nettEffect, font25b, sPos, true, false); } } } SizeF textSize = _Canvas.MeasureString("In base : 1234", font50); int lineCounter = 0; double avg = (double)growthRatesCounter[3] / (double)planets.Count; #region Draw neutral player stats (UpperLeft) Brush color = MyColors.GetLightBrush(0); _Canvas.FillRectangle(Brushes.Black, 0, 0, textSize.Width, textSize.Height * 6); _Canvas.DrawString("In base : " + inbaseCounter[0], font50, color, 0, textSize.Height * lineCounter++); _Canvas.DrawString("Growth : " + growthRatesCounter[0], font50, color, 0, textSize.Height * lineCounter++); _Canvas.DrawString(string.Format("Gr.Avg. : {0:G}", avg), font50, color, 0, textSize.Height * lineCounter++); #endregion #region Draw Player1 stats (Below neurtral) color = MyColors.GetLightBrush(1); _Canvas.DrawString("In base : " + inbaseCounter[1], font50, color, 0, textSize.Height * lineCounter++); _Canvas.DrawString("Transit : " + inTransitCounter[1], font50, color, 0, textSize.Height * lineCounter++); _Canvas.DrawString("Growth : " + growthRatesCounter[1], font50, color, 0, textSize.Height * lineCounter++); #endregion int topLeftCornerHeight = (int)(textSize.Height * lineCounter) + 1; lineCounter = 0; color = MyColors.GetLightBrush(2); #region Draw Player2 stats (Right next to neurtral) _Canvas.FillRectangle(Brushes.Black, textSize.Width, 0, textSize.Width, textSize.Height * 3); _Canvas.DrawString("In base : " + inbaseCounter[2], font50, color, textSize.Width, textSize.Height * lineCounter++); int centralLine = (int)(textSize.Height * lineCounter++); _Canvas.DrawString("Transit : " + inTransitCounter[2], font50, color, textSize.Width, centralLine); _Canvas.DrawString("Growth : " + growthRatesCounter[2], font50, color, textSize.Width, textSize.Height * lineCounter++); if (getPlayerStats != null) { if (getPlayerStats.QueryIsDominating()) { _Canvas.DrawString("Dominating", font100b, MyColors.GetDarkBrush(1), Width / 2 - textSize.Width, centralLine); } } #endregion if (DrawUniverseStatistics) { PaintVerticalStatisticBars(growthRatesCounter, inbaseCounter, planetCounter, inTransitCounter, color, topLeftCornerHeight); } } finally { _Canvas = null; MyColors = null; } }