Example #1
0
        /// <summary>
        ///  Constructs a new game engine.
        /// </summary>
        /// <param name="dataPath">The path to save game directory.</param>
        /// <param name="useNetwork">Controls the usage of the network engine.</param>
        /// <param name="deserializeState">Controls if the state is deserialized or not.</param>
        /// <param name="fileName">The path to the state file.</param>
        /// <param name="reportData">Determines if data should be reported.</param>
        /// <param name="leds">Provides a listing of game leds that can be used.</param>
        /// <param name="trackLastRun">Controls whether the PAC keeps track of the last run creature for blacklisting.</param>
        private GameEngine(string dataPath, bool useNetwork, bool deserializeState, string fileName, bool reportData,
            TerrariumLed[] leds, bool trackLastRun)
        {
            _ledIndicators = leds;
            _currentStateFileName = fileName;

            // test to make sure we're not violating any constraints by current
            // physics settings in the engine.
            EngineSettings.EngineSettingsAsserts();

            // Calculate quanta and worldsize if we haven't done so yet
            if (_reloadSettings)
                CalculateWorldSize();

            _pac = new PrivateAssemblyCache(dataPath, fileName, true, trackLastRun);

            // Reset the appdomain policy since we changed the location of the organism dlls
            // This must be done before any animals are loaded in any way.  Make sure this call stays
            // as soon as possible
            AppDomain.CurrentDomain.SetAppDomainPolicy(SecurityUtils.MakePolicyLevel(_pac.AssemblyDirectory));

            _usingNetwork = useNetwork;
            _populationData = new PopulationData(reportData, leds[(int) LedIndicators.ReportWebService]);

            // Should only happen if an exception prevented a previous attempt to start a game
            if (AppMgr.CurrentScheduler != null)
            {
                AppMgr.DestroyScheduler();
            }

            // Create a scheduler that manages giving the creatures timeslices
            _scheduler = AppMgr.CreateSameDomainScheduler(this);
            _scheduler.Quantum = _organismQuanta;

            if (useNetwork)
            {
                // Required to start up the network listeners
                _networkEngine = new NetworkEngine();
            }

            WorldState currentState;
            Boolean successfulDeserialization = false;
            if (deserializeState && File.Exists(fileName))
            {
                try
                {
                    if (_pac.LastRun.Length != 0)
                    {
                        // The process was killed while an organism was being run, blacklist it
                        // Since this potentially means the animal hung the game.
                        _pac.BlacklistAssemblies(new string[] {_pac.LastRun});
                    }
                    this.deserializeState(fileName);
                    currentState = CurrentVector.State;
                    _scheduler.CurrentState = currentState;
                    _scheduler.CompleteOrganismDeserialization();
                    successfulDeserialization = true;
                }
                catch (Exception e)
                {
                    ErrorLog.LogHandledException(e);
                }
            }

            if (successfulDeserialization) return;

            // Set up initial world state
            currentState = new WorldState(GridWidth, GridHeight);
            currentState.TickNumber = 0;
            currentState.StateGuid = Guid.NewGuid();
            currentState.Teleporter = new Teleporter(AnimalCount/EngineSettings.NumberOfAnimalsPerTeleporter);
            currentState.MakeImmutable();

            WorldVector vector = new WorldVector(currentState);
            CurrentVector = vector;
            _scheduler.CurrentState = currentState;
        }
Example #2
0
        /// <summary>
        /// Processes turns in a phase manner.  After 10 calls to ProcessTurn
        /// all 10 phases will be complete and the method will have completed
        /// one game tick.
        /// </summary>
        /// <returns>True if a tick has been processed, false otherwise.</returns>
        public Boolean ProcessTurn()
        {
            // shutdownError and invalidPeerError are two errors that get set from
            // deep in the system.  We process them here because it is a clean place
            // to restart the game since we aren't in the middle of any phases.
            // This is just a mechanism for cleanly throwing an error from a known good
            // location.
            if (_shutdownError)
            {
                _shutdownError = false;
                throw new ShutdownFailureException();
            }

            if (_invalidPeerError)
            {
                _invalidPeerError = false;
                throw new InvalidPeerException();
            }

            // We break the main processing of the game into 10 phases that have been tuned to each
            // take roughly the same amount of time.  We paint the screen in between each one.  This way
            // We can have a constant frame rate and incrementally do the engine processing we need to
            // do.
            // After we do all 10 phases we've done one game "tick".  We can do two ticks a second which means
            // we have a frame rate of 20.
            switch (_turnPhase)
            {
                case 0:
                    // If we are in ecosystem mode, we want to save the game state periodically in case the user
                    // shuts down the screensaver by pressing ctl-alt-del which just kills the process.  This way
                    // we won't have lost too much processing time.
                    // We always want to save on the tick after we've reported so we don't get our state messed up
                    // on the server.  For example: never start the game in a state that was before the information
                    // was sent to the server because the server will think we're corrupted.
                    if (_logState ||
                        (_ecosystemMode && _populationData.IsReportingTick(CurrentVector.State.TickNumber - 1)))
                    {
                        Debug.WriteLine("Saving state.");
                        serializeState(_currentStateFileName);
                    }

                    // Give 1/5 of the animals a chance to do their processing
                    Scheduler.Tick();
                    break;

                case 1:
                    // Give 1/5 of the animals a chance to do their processing
                    Scheduler.Tick();
                    break;

                case 2:
                    // Give 1/5 of the animals a chance to do their processing
                    Scheduler.Tick();
                    break;

                case 3:
                    // Give 1/5 of the animals a chance to do their processing
                    Scheduler.Tick();
                    break;

                case 4:
                    // Give 1/5 of the animals a chance to do their processing
                    Scheduler.Tick();
                    break;

                case 5:
                    // Get all the actions that the animals want to perform in this tick.
                    TickActions act = _scheduler.GatherTickActions();

                    CurrentVector.Actions = act;

                    // Create a mutable version of the world state that we'll change to create the next
                    // world state.
                    _newWorldState = (WorldState) CurrentVector.State.DuplicateMutable();
                    _newWorldState.TickNumber = _newWorldState.TickNumber + 1;
                    _populationData.BeginTick(_newWorldState.TickNumber, CurrentVector.State.StateGuid);

                    // Remove any organisms queued to be removed
                    removeOrganismsFromQueue();

                    // We take a snapshot of the organism IDs since we do several foreach loops
                    // and change the state, which causes exceptions to occur
                    _organismIDList = new string[_newWorldState.OrganismIDs.Count];
                    _newWorldState.OrganismIDs.CopyTo(_organismIDList, 0);
                    killDiseasedOrganisms2();
                    break;

                case 6:
                    Debug.Assert(_newWorldState != null, "Worldstate did not get created for this tick");

                    // Do this first, since it always must happen so that things (like growing)
                    // won't happen if there isn't enough energy
                    burnBaseEnergy();

                    // Do attacks before movement so that when a carnivore asks if it can attack
                    // they actually get to hit the target before it moves
                    doAttacks();
                    doDefends();
                    changeMovementVectors();
                    break;

                case 7:
                    moveAnimals();
                    break;

                case 8:
                    doBites();
                    growAllOrganisms();
                    incubate();
                    startReproduction();
                    heal();
                    break;

                case 9:
                    // Do this last so that the plant always starts charged up,
                    // and has to operate with what it has for the next turn
                    giveEnergyToPlants();

                    // Teleport after all actions have been processed so that there are
                    // no single turn pending actions left for the organism.
                    teleportOrganisms();

                    // Insert any new organisms
                    insertOrganismsFromQueue();

                    // Set Antenna States
                    doAntennas();

                    // We're done changing the state, now make it immutable
                    _newWorldState.MakeImmutable();
                    Debug.Assert(_newWorldState.Organisms.Count == Scheduler.Organisms.Count);

                    WorldVector vector = new WorldVector(_newWorldState);
                    CurrentVector = vector;

                    _scheduler.CurrentState = _newWorldState;
                    _populationData.EndTick(_newWorldState.TickNumber);

                    _newWorldState = null;
                    break;
            }

            _turnPhase++;
            if (_turnPhase == 10)
            {
                _turnPhase = 0;
                return true;
            }
            return false;
        }
Example #3
0
 // In 10 frames we animate the world from oldState to newState
 // Frame 0 paints the world exactly as it is in oldState
 internal void PaintFrame(WorldVector oldVector, WorldVector newVector, int frameNumber, Boolean erase)
 {
     if (frameNumber == 0)
     {
         if (newVector == null)
         {
             tddGameView.UpdateWorld(oldVector);
         }
         else
         {
             tddGameView.UpdateWorld(newVector);
         }
     }
 }
        /// <summary>
        ///  Updates the sprites controlled by the game view by providing a new
        ///  world vector from the game engine.
        /// </summary>
        /// <param name="worldVector">The new world vector of organisms.</param>
        public void UpdateWorld(WorldVector worldVector)
        {
#if TRACE
            Profiler.Start("TerrariumDirectDrawGameView.UpdateWorld()");
#endif
            wv = worldVector;
            paintPlants = true;

            updateTicker++;
            updateTickerChanged = true;

            var zones = wv.State.Teleporter.GetTeleportZones();
            foreach (var zone in zones)
            {
                if (hackTable.ContainsKey(zone.ID))
                {
                    var tsZone = (TerrariumSprite) hackTable[zone.ID];
                    tsZone.XDelta = (zone.Rectangle.X - tsZone.XPosition)/10;
                    tsZone.YDelta = (zone.Rectangle.Y - tsZone.YPosition)/10;
                    hackTable[zone.ID] = tsZone;
                }
                else
                {
                    InitTeleporter(zone);
                }
            }

            foreach (OrganismState orgState in wv.State.Organisms)
            {
                if (orgState.RenderInfo != null)
                {
                    var tsSprite = (TerrariumSprite) orgState.RenderInfo;

                    if (orgState is AnimalState)
                    {
                        if (tsSprite.PreviousAction != orgState.PreviousDisplayAction)
                        {
                            tsSprite.CurFrame = 0;
                            tsSprite.PreviousAction = orgState.PreviousDisplayAction;
                        }
                        tsSprite.XDelta = (orgState.Position.X - tsSprite.XPosition)/10;
                        tsSprite.YDelta = (orgState.Position.Y - tsSprite.YPosition)/10;
                    }
                    else
                    {
                        tsSprite.CurFrame = 0;
                        tsSprite.PreviousAction = orgState.PreviousDisplayAction;
                        tsSprite.XPosition = orgState.Position.X;
                        tsSprite.YPosition = orgState.Position.Y;
                    }
                    orgState.RenderInfo = tsSprite;
                }
                else
                {
                    InitOrganism(orgState);
                }
            }
#if TRACE
            Profiler.End("TerrariumDirectDrawGameView.UpdateWorld()");
#endif
        }
Example #5
0
        // Called by the game engine every time a tick creates a new state for the world
        private void WorldVectorChanged(object sender, WorldVectorChangedEventArgs e)
        {
            oldVector = newVector;
            newVector = e.NewVector;

            if (tddGameView != null)
            {
                if (e.NewVector.State.Organisms.Count < 1)
                {
                    if (GameEngine.Current != null && GameEngine.Current.EcosystemMode)
                    {
                        if (developerPanel.Leds[(int)LedIndicators.DiscoveryWebService].LedState == LedStates.Failed ||
                            developerPanel.Leds[(int)LedIndicators.ReportWebService].LedState == LedStates.Failed)
                        {
                            tddGameView.TerrariumMessage = emptyEcosystemServerDownMessage;
                        }
                        else
                        {
                            tddGameView.TerrariumMessage = emptyEcosystemMessage;
                        }
                    }
                    else
                    {
                        tddGameView.TerrariumMessage = emptyTerrariumMessage;
                    }
                }
                else
                {
                    // Only clear our messages, not those set by someone else
                    if (tddGameView.TerrariumMessage == emptyEcosystemMessage || tddGameView.TerrariumMessage == emptyTerrariumMessage)
                    {
                        tddGameView.TerrariumMessage = null;
                    }
                }

                // If the network has a problem, always override the message with this
                if (GameEngine.Current != null && GameEngine.Current.NetworkEngine != null)
                {
                    if (GameEngine.Current.NetworkEngine.NetworkStatusMessage.Length != 0)
                    {
                        tddGameView.TerrariumMessage = GameEngine.Current.NetworkEngine.NetworkStatusMessage;
                    }
                    else
                    {
                        if (tddGameView.TerrariumMessage == NetworkEngine.NetworkBehindNatMessage)
                        {
                            tddGameView.TerrariumMessage = null;
                        }
                    }
                }
            }

            // Tell the tracewindow that we've got a new tick
            if (traceWindow != null)
            {
                traceWindow.TickEnded();
            }

            this.developerPanel.AnimalCount = GameEngine.Current.AnimalCount;
            this.developerPanel.MaximumAnimalCount = GameEngine.Current.MaxAnimals;
            this.developerPanel.PeerCount = GameEngine.Current.PeerCount;

            if (GameEngine.Current.EcosystemMode == true)
            {
                //this.taskBar.Text = GameConfig.WebRoot;
            }
            else
            {
                //this.taskBar.Text = GameEngine.Current.FileName;
            }

            this.taskBar.Text = "Terrarium";

            this.taskBar.Text += "\r\nPopulation: " + GameEngine.Current.AnimalCount + "/" + GameEngine.Current.MaxAnimals + "\r\nPeers: " + GameEngine.Current.PeerCount;

            try
            {
                if (GameEngine.Current.IsNetworkEnabled == true)
                {
                    developerPanel.Teleportations = GameEngine.Current.NetworkEngine.Teleportations;
                    developerPanel.FailedSends = GameEngine.Current.NetworkEngine.FailedTeleportationSends;
                    developerPanel.FailedReceives = GameEngine.Current.NetworkEngine.FailedTeleportationReceives;
                }
            }
            catch { }

            if (engineStateText != null && engineStateText.Length != 0)
            {
                this.bottomPanel.Ticker.Messages.Enqueue(engineStateText);
                engineStateText = "";
            }
        }
Example #6
0
        // Sets up the form after a new game has been loaded
        private void NewGameLoaded()
        {
            if (GameEngine.Current.Pac.LastRun.Length != 0)
            {
                engineStateText += "Terrarium automatically shutdown and restarted (without saving)because the creature '" + PrivateAssemblyCache.GetAssemblyShortName(GameEngine.Current.Pac.LastRun) + "' hung your machine and Terrarium needed to remove this offensive animal.";
                GameEngine.Current.Pac.LastRun = "";
            }

            if (GameEngine.Current.EcosystemMode == true)
            {
                this.developerPanel.GameModeText = "Ecosystem";
                developerPanel.WebRoot = GameConfig.WebRoot;
                bottomPanel.GameMode = GameModes.Ecosystem;
                bottomPanel.Mode = screenSaverMode;
            }
            else
            {
                this.developerPanel.GameModeText = "Terrarium";
                this.bottomPanel.GameMode = GameModes.Terrarium;

                if (GameEngine.Current.FileName.Length == 0)
                {
                    developerPanel.WebRoot = "[New Terrarium]";
                }
                else
                {
                    developerPanel.WebRoot = GameEngine.Current.FileName;
                }
            }

            GameEngine.Current.WorldVectorChanged += new WorldVectorChangedEventHandler(WorldVectorChanged);
            GameEngine.Current.EngineStateChanged += new EngineStateChangedEventHandler(EngineStateChanged);

            oldVector = null;
            newVector = null;
            frameNumber = 0;

            InitializeGraphics(GameEngine.Current.WorldWidth, GameEngine.Current.WorldHeight);

            timer1.Enabled = true;

            if (screenSaverMode == ScreenSaverMode.Run)
            {
                Block.BlockScreens(Screen.FromControl(this));

                this.ShowUI = false;
                this.Fullscreen = true;
                this.ContextMenu = null;
                this.tddGameView.DrawText = true;
                Cursor.Hide();
                Cursor.Position = new Point(this.Width / 2, this.Height / 2);
                this.tddGameView.DrawCursor = false;
            }
            else
            {
                this.Cursor = Cursors.Default;

                if (wasRelaunched)
                {
                    this.SuspendLayout();

                    if (windowState == FormWindowState.Maximized)
                    {
                        this.WindowState = FormWindowState.Maximized;
                    }
                    else if (windowState == FormWindowState.Minimized)
                    {
                        this.Hide();
                        this.taskBar.Visible = true;
                    }
                    else
                    {
                        this.WindowState = FormWindowState.Normal;
                    }

                    this.Location = new Point(windowRectangle.Left, windowRectangle.Top);
                    this.Size = new Size(windowRectangle.Width, windowRectangle.Height);

                    this.ResumeLayout();
                }
                else
                {
                    if (GameConfig.StartFullscreen == true)
                        this.Fullscreen = true;
                }
            }

            this.ConfigureTickerBar();
        }
 /// <summary>
 ///  Creates a new set of event arguments for when the world vector changes.
 /// </summary>
 /// <param name="oldVector">The previous world vector object.</param>
 /// <param name="newVector">The new world vector object.</param>
 public WorldVectorChangedEventArgs(WorldVector oldVector, WorldVector newVector)
 {
     this.oldVector = oldVector;
     this.newVector = newVector;
 }
 /// <summary>
 ///  Creates a new set of event arguments for when the world vector changes.
 /// </summary>
 /// <param name="oldVector">The previous world vector object.</param>
 /// <param name="newVector">The new world vector object.</param>
 public WorldVectorChangedEventArgs(WorldVector oldVector, WorldVector newVector)
 {
     OldVector = oldVector;
     NewVector = newVector;
 }
Example #9
0
 /// <summary>
 ///  Creates a new set of event arguments for when the world vector changes.
 /// </summary>
 /// <param name="oldVector">The previous world vector object.</param>
 /// <param name="newVector">The new world vector object.</param>
 public WorldVectorChangedEventArgs(WorldVector oldVector, WorldVector newVector)
 {
     OldVector = oldVector;
     NewVector = newVector;
 }