Britbot
Simulator/SimulatedGame.cs
Go to the documentation of this file.
00001 #region #Usings
00002 
00003 using System.Collections.Generic;
00004 using Britbot.PriorityQueue;
00005 using Pirates;
00006 using System;
00007 using System.Threading;
00008 
00009 #endregion
00010 
00011 namespace Britbot.Simulator
00012 {
00016     class SimulatedGame
00017     {
00018         #region Fields & Properies
00019 
00024         private HeapPriorityQueue<SimulatedEvent> CommingEvents;
00025 
00029         public Dictionary<int,SimulatedGroup> EnemyGroups;
00030 
00034         public Dictionary<int,SimulatedIsland> Islands;
00035 
00039         public Dictionary<int, SimulatedGroup> MyGroups;
00040 
00044         public double Score { get; private set; }
00045 
00049         public int CurrentTurn { get; set; }
00050 
00051 
00052         public double MyIslandCount;
00053         public double EnemyIslandCount;
00054         public double MyDeadPirates;
00055         public double EnemyDeadPirates;
00056 
00057         public double OriginalMyIslandCount;
00058         public double OriginalEnemyIslandCount;
00059         public double OriginalMyDeadPirates;
00060         public double OriginalEnemyDeadPirates;
00061 
00066         public List<SimulatedEvent> ConstantEvents;
00067 
00068         #endregion
00069 
00070         #region Constructors & Initializers
00071 
00076         public SimulatedGame()
00077         {
00078             //initialize stuff
00079             this.CommingEvents = new HeapPriorityQueue<SimulatedEvent>((int) (2 * Magic.MaxCalculableDistance));
00080             this.ConstantEvents = new List<SimulatedEvent>();
00081             this.Islands = new Dictionary<int,SimulatedIsland>();
00082             this.MyGroups = new Dictionary<int, SimulatedGroup>();
00083             this.EnemyGroups = new Dictionary<int, SimulatedGroup>();
00084 
00085             //add the ending Event
00086             this.ConstantEvents.Add(new SimulationEndEvent(Magic.SimulationLength));
00087 
00088             this.OriginalEnemyDeadPirates = 0;
00089             this.OriginalMyDeadPirates = 0;
00090             this.OriginalMyIslandCount = 0;
00091             this.OriginalEnemyIslandCount = 0;
00092 
00093             //set my groups
00094             foreach (Group group in Commander.Groups)
00095             {
00096                 //check if capturing
00097                 bool isCapturing = false;
00098                 foreach(SmartIsland sIsland in SmartIsland.IslandList)
00099                 {
00100                     if(group.MinimalETATo(sIsland.Loc) == 0)
00101                     {
00102                         isCapturing = true;
00103                         break;
00104                     }
00105                 }
00106                 this.MyGroups.Add(group.Id, new SimulatedGroup(group.Id, Consts.ME, group.LiveCount(), isCapturing));
00107             }
00108 
00109             //set enemy group
00110             foreach (EnemyGroup eGroup in Enemy.Groups)
00111             {
00112                 //check if capturing
00113                 bool isCapturing = false;
00114                 foreach (SmartIsland sIsland in SmartIsland.IslandList)
00115                 {
00116                     if (eGroup.MinimalETATo(sIsland.Loc) == 0)
00117                     {
00118                         isCapturing = true;
00119                         break;
00120                     }
00121                 }
00122                 this.EnemyGroups.Add(eGroup.Id, new SimulatedGroup(eGroup.Id, Consts.ENEMY, eGroup.GetMaxFightPower(), isCapturing));
00123             }
00124 
00125             //set up islands
00126             foreach (SmartIsland sIsland in SmartIsland.IslandList)
00127             {
00128                 SimulatedIsland newIsland = new SimulatedIsland(id: sIsland.Id,
00129                                                                 owner: sIsland.Owner,
00130                                                                 turnsBeingCaptured: sIsland.TurnsBeingCaptured,
00131                                                                 value: sIsland.Value);
00132 
00133                 //we set capturing teams through events
00134 
00135                 this.Islands.Add(newIsland.Id, newIsland);
00136 
00137                 if (sIsland.Owner == Consts.ME)
00138                     OriginalMyIslandCount+= sIsland.Value;
00139                 if (sIsland.Owner == Consts.ENEMY)
00140                     OriginalEnemyIslandCount += sIsland.Value;
00141             }
00142 
00143             //set constant events
00144             foreach (SmartIsland sIsland in SmartIsland.IslandList)
00145             {
00146                 //go over the enemy list of each island
00147                 foreach (KeyValuePair<EnemyGroup, bool> enemy in sIsland.approachingEnemies)
00148                 {
00149                     SimulatedEvent newEvent;
00150                     //if it is likely that he will come to the island
00151                     if (enemy.Value)
00152                     {
00153                         newEvent = new GroupArrivalEvent((int)enemy.Key.MinimalETATo(sIsland.Loc),
00154                                       this.Islands[sIsland.Id],
00155                                       this.EnemyGroups[enemy.Key.Id]);
00156                         this.ConstantEvents.Add(newEvent);
00157                     }
00158                     else if ((int)enemy.Key.MinimalETATo(sIsland.Loc) < 0 || Commander.IsDefensive() )
00159                     {
00160                         newEvent = new PossibleArrivalEvent((int)enemy.Key.MinimalETATo(sIsland.Loc),
00161                                       this.Islands[sIsland.Id],
00162                                       this.EnemyGroups[enemy.Key.Id]);
00163                         this.ConstantEvents.Add(newEvent);
00164                     }
00165                  }
00166 
00167 
00168                     //add the event
00169                     
00170             
00171 
00172                 //check if there are ships on the islands
00173                 foreach(Group g in Commander.Groups)
00174                 {
00175                     if(g.MinimalETATo(sIsland.Loc) <= 1)
00176                     {
00177                         this.Islands[sIsland.Id].CapturingGroup = this.MyGroups[g.Id];
00178                         break;
00179                     }
00180                 }
00181             }
00182 
00183         }
00184 
00188         public void ResetSimulation()
00189         {
00190             //reset general stuff
00191             this.CurrentTurn = Bot.Game.GetTurn();
00192             this.Score = 0;
00193             this.EnemyDeadPirates = this.OriginalEnemyDeadPirates;
00194             this.MyDeadPirates = this.OriginalMyDeadPirates;
00195             this.EnemyIslandCount = this.OriginalEnemyIslandCount;
00196             this.MyIslandCount = this.OriginalMyIslandCount;
00197 
00198             //reset islands
00199             foreach(KeyValuePair<int, SimulatedIsland> sIsland in this.Islands)
00200             {
00201                 sIsland.Value.Owner = sIsland.Value.OriginalOwner;
00202                 sIsland.Value.TurnsBeingCaptured = sIsland.Value.OriginalTrunsBeingCaptured;
00203                 sIsland.Value.CapturingGroup = sIsland.Value.OriginalCapturingGroup;
00204             }
00205 
00206             //reset my groups
00207             foreach(KeyValuePair<int,SimulatedGroup> sGroup in this.MyGroups)
00208             {
00209                 sGroup.Value.IsBusy = false;
00210                 sGroup.Value.IsAlive = sGroup.Value.OriginalIsAlive;
00211                 sGroup.Value.IsCapturing = sGroup.Value.OriginalIsCapturing;
00212                 sGroup.Value.ReviveTurn = sGroup.Value.OriginalReviveTurn;
00213             }
00214 
00215             //reset enemy groups
00216             foreach (KeyValuePair<int, SimulatedGroup> sGroup in this.EnemyGroups)
00217             {
00218                 sGroup.Value.IsBusy = false;
00219                 sGroup.Value.IsAlive = sGroup.Value.OriginalIsAlive;
00220                 sGroup.Value.IsCapturing = sGroup.Value.OriginalIsCapturing;
00221                 sGroup.Value.ReviveTurn = sGroup.Value.OriginalReviveTurn;
00222             }
00223 
00224             //reset events
00225             this.CommingEvents.Clear();
00226             foreach(SimulatedEvent sEvent in this.ConstantEvents)
00227             {
00228                 this.CommingEvents.Enqueue(sEvent, sEvent.Turn);
00229             }
00230         }
00231         #endregion
00232 
00238         public void AddEvent(SimulatedEvent newEvent)
00239         {
00240             this.CommingEvents.Enqueue(newEvent, newEvent.Turn);
00241         }
00242 
00248         public double RunSimulation(CancellationToken cancellationToken)
00249         {
00250             int nextTurn = 0;
00251 
00252             //variables for PPT
00253             double PPT;
00254 
00255             int count = 0;
00256 
00257             //start going over events
00258             while(this.CommingEvents.Count > 0)
00259             {
00260                 count++;
00261                 //calculate PPT
00262                 PPT = this.CalculatePpt();
00263 
00264                 nextTurn = this.CommingEvents.First.Turn;
00265 
00266                 //update score
00267                 this.Score += (nextTurn - this.CurrentTurn) * PPT;
00268 
00269                 //update iteration      
00270                 this.CurrentTurn = nextTurn;
00271 
00272                 //activate the comming event, if it is the end then break
00273                 if (this.CommingEvents.Dequeue().Activate(this))
00274                     break;
00275             }
00276 
00277             //Logger.Write(this.MyIslandCount.ToString(),true);
00278             //Logger.Write(this.EnemyIslandCount.ToString(),true);
00279 
00280 
00281             Logger.Write("COUNT: " + count);
00282             return Score;
00283         }
00284 
00290         public double CalculatePpt()
00291         {
00292             //calc score
00293             double friendlyPPT = Math.Floor(Math.Pow(2, this.MyIslandCount - 1));
00294             double enemyPPT = Math.Floor(Math.Pow(2, this.EnemyIslandCount - 1));
00295 
00296             //account for dead ships
00297             friendlyPPT -= Math.Pow(Magic.FriendlyBaseFactor, this.MyDeadPirates);
00298 
00299             //account for dead enemy ships
00300             enemyPPT -= Math.Pow(Magic.EnemyBaseFactor, this.EnemyDeadPirates);
00301 
00302             return friendlyPPT - enemyPPT;
00303         }
00304     }
00305 }