Scenario Creation Basics
To create a new scenario, click the "Create New Scenario" on the main menu. This will bring you to the Scenario Creator.
To run the scenario, click the "Start!" button.
If you have a scenario opened, you may return to the Scenario Creator by clicking the Menu button (the gear) and then clicking Edit Scenario.
You may download the scenario to your computer at any time, and reload it by clicking "Upload". There is no server-side storage currently, you must store all scenarios on your computer.
Creating a Site
A Site is a regional location in the PathoGenic engine (a country, a city, etc.). Currently a scenario should have exactly one site. (There may be multi-site support later).
To create a new Site, click on the Sites button and then click New. This is how you will always create objects in the PathoGenic Scenario Creator. You may edit, copy, and delete objects from any object list.
Let's create a large city of one million people. Set Population to 1000000. Ignore the other options for now.
Creating a virus
Let us create a simulation of a virus that spreads through the population.
To start, open the Traits menu and create a new Trait. Set its id as "infected" and its color to red. You may also give it a title; the difference between an ID and Title is that the id will be used internally and should not be changed. You may change the Title to make it appear with a different name in menus.
Now, return to your Site and double-click (or click the "E" button) to open it. Open the Initial Local Traits menu.
There are two menus here: Initial Populations and Additional Vectors. Initial populations are for demographic info, which we are not using yet. Additional Vectors lets you infect a specific number of people in the population using vectors.
Click Additional Vectors to create a new vector.
This vector should add the infected trait to whoever it touches, so click on the Apply button and select "infected" from the drop-down menu. Let us start by infecting 10 people; set Amount to 10.
You may now run the scenario. When you click the Play button, you should see that 10 people are infected.
Since the graph displays the entire population, this will appear as a red line at the very bottom of the graph, slide the slider on the right all the way to the bottom to see smaller numbers properly.
Making the virus spread
Return to the editor and go back to the Infected trait. Let us make infected people infect others.
Click on the Transmit submenu. This will allow people with the Infected trait to create new vectors. Create a new Transmit object and, as before, make it apply the Infected trait.
The Amount will determine the number of vectors each infected person produces per day. Each vector represents the ability to infect one person. So, if you set the Amount to 1, each infected person will try and infect one more person per day, and the number of infected will double every day.
Try it out and run the scenario. You should see that on the first day you have 10 infected, on the second you have 20, on the third you have 40, and so on.
After a little while though, you will see the total infected not quite doubling every day. This is because, in PathoGenic, each trait is either active or inactive, so people who are already infected will be touched by the virus, but their status will not change.
Eventually, the entire population will be infected.
Making the virus heal
Currently, everyone infected stays infected, which is unrealistic for most diseases. Let us give infected people the ability to recover.
Open the Infected trait again in the editor and open the Progress submenu. This allows the trait to add new traits to people who have that trait, or remove existing traits. To make an infection that heals, we will give it a chance of healing itself.
Add a Progress object, but this time, instead of Applying a trait, make it Remove the Infected trait. Give it a Probability of 0.5 - this will give each infected person a 50% chance of recovering every day.
Now run the scenario.
You should see that the number of infected increases more slowly, but something is off - instead of the number of infected peaking and then dropping off like with real epidemics, it climbs to infect about 50% of the population and just stays there. What happened?
There is an oversight in our simulation - an epidemic "peaks" because people who recover generally have immunity to being re-infected. In this model, people who recover immediately become susceptible again. So the disease never peaks.
Let's fix that.
Vector Types
In order to properly make immunity work, we will need to add an Immunity trait. However, to make the immunity trait work properly, we need to give the simulator a way to identify the vectors it is supposed to block against.
Open up the Vector Types menu and add a new object. Give it an ID of "virus".
Create another Vector Type and give it an ID of "recovery".
Now, go back to the Infected Trait, open the Transmissions sub-menu, and open the +infected transmission you added before. Click the Vector Types button and add "virus". This will identify this particular vector as a virus.
Do the same with the -infected under the Progress sub-menu, but give it the vector type of "recovery".
It is generally a good idea to give all Transmissions and Progress vectors at least one vector type. Only vectors with vector types can be affected by other traits.
Adding Immunity
Add a new trait, and give it an ID of "immune". Color it blue.
We want the immunity trait to modify the chance of re-infection, so open up the Infected Mod sub-menu and add a new object.
Select "virus" from the Modify Vector Type Effectiveness and set the multiplier to 0. This means that when a virus attempts to infect a person with the Immune trait, its chance of infecting will be multiplied by 0 - meaning it will never infect a person who is immune.
Now, we want to make sure that whenever a person recovers from the virus, they become immune. Go back to the Infected trait and open up the recovery progress event. Make this same event that removes the Infected trait also add the Immune trait.
Go and run the scenario. You should see the number of people immune rise as they recover, and as the number of susceptible people in the population decreases, the number of newly infected will decrease until eventually the virus goes extinct. The disease will hit a peak and then drop off, like in a real epidemic.
Adding Mortality
Adding mortality to the simulation is fairly simple. As far as the simulation is concerned, death is just another trait that a person may possess, and may be added in the same way as any other trait.
Add a new trait with the ID of "dead", and color it dark red.
Add a new vector type with the id of "death".
Now, add a new Progress event to the Infected trait. This event should apply the Dead trait, remove the Infected and Immune traits, have a Vector Type of death, and have a probability of 0.1 - meaning that a person has a 10% chance of dying every day they are infected (a fairly deadly disease).
You can now run the scenario and see how the disease spreads through a population and kills around 150,000 people before it disappears.
Adding Doctors
Let's simulate some doctors to try and keep people from dying.
Add another trait, and call it "doctor".
Now, how to simulate doctors under the rules of the PathoGenic engine? Remember, a trait can be anything, and a vector is nothing but the ability to transmit that trait.
The premise here is, we will make a "treated" trait that reduces the probability of infection progressing to death. Then, we can create a vector allowing doctors to transmit that trait to the infected.
First, let's create the "treated" trait and color it green. To simplify and test this model, we will make the doctors perfectly effective: people will not die on the same day they are being attended to by a doctor. Give the Treated trait a Progress Mod that multiplies death-type vectors by 0.
Treatment should only make an impact for one day. To make the Treated trait go away, give it a Progress event that removes the trait Treated with a probability of 1. This means it will have a 100% chance of destroying itself each day.
Now, create a new vector type, and call it "treatment".
Then, add a Transmit event to the doctors. Make it add the Treated trait using the "treatment" vector. Let us assume that a doctor can treat 50 patients per day; give it an Amount of 50.
Finally, we must add the doctors to the city. Go to Sites and add 1000 doctors. You may do this through Additional Vectors.
Now, try running the scenario.
Well, that didn't work at all. The number of people dying barely decreased. Not only that, but on the graph, it looks like the number of people being treated was higher than the number who were sick, at least at first. What happened?
Debugging with Omniscient Mode
This is where things will get more complicated, so it's important to learn about the debugging tool. To start, click on the All-Seeing-Eye icon (that's the one in the triangle) while running the scenario to activate Omniscient Mode.
This will show you all of the sub-populations active in your scenario. After running it for a bit, you may notice that the number of people with the "treated" trait greatly outnumbers people with the infected.treated trait.
Well, of course - we didn't tell the doctors that they are only supposed to be treating infected people. They are trying to treat everyone equally, meaning that the majority of sick people weren't getting any treatment.
To fix this, we need to use Seek behavior.
Making treatment focus on the sick
Seek behavior lets vectors prioritize people with certain traits over others. Often, you will want to make vectors ignore people who have (or lack) particular traits.
Go to the "treatment" vector type and open the Seek sub-menu. Add a Seek behavior, set it to "Lacks Traits: infected" and set the multiplier to 0. This will make treatment vectors ignore anyone who is not infected.
Now run the scenario again. You should see doctors acting more logically, but they don't seem to be saving quite as many people as they should. You may notice that only a certain percentage of the infected people are being treated - usually only about half - even when there should be enough doctors.
What is the issue here?
How Order of Events works
You may have noticed that we haven't really given any rules for what order events happen in. Every day, the infection spreads, some of the infected die, some recover, and the doctors try and treat some - but what order are these effects applied?
The PathoGenic simulation has 3 stages each phase (which, up until now, is each day).
- All people create their vectors based on the traits they have. This includes both Transmit and Progress vectors.
- All vectors find their targets and infect them at the same time. Progress vectors always try and infect the person who created them. The vectors do not interact with each other at this time.
- All changes from the infections are applied. If the same person is infected by a vector that adds a trait and another that removes the trait, removal wins.
Until the doctors got involved, this worked out well enough - infected people released their viruses, then either died, recovered, or neither. If someone tried to die and recover on the same day, they would die, because the "recovery" vector would remove the Infected trait and add the Immune trait, and the "death" vector would add the Dead trait and remove the Immune trait - so they would wind up dead. If they were infected and recovered or died on the same day, the Infected trait would be removed. A bit messy, but functional.
But the "treatment" vectors don't know to seek out a person who was infected on the same day they were created, because they do not yet have the Infected trait during the seeking step. So people are only treated the day after they are infected, at the earliest.
More importantly, if a treatment vector attaches to an infected person on the same day that person triggered a progress vector for death, they are not protected from death until after the death vector has already affected them. So they get the Dead and Treated traits at the same time - meaning they are dead (and also being treated, but that doesn't help much).
We need to fix this.
Adding Phases
To ensure that doctors always provide treatment to infected patients before they die, we will want the order of events to happen as follows:
- The infection spreads
- Doctors give treatment to whoever is infected
- Untreated patients have a chance to die
- Surviving patients have a chance to recover
To do this, open up the Phases menu and create four Phases: "infection", "treatment", "death", and "recovery".
Now, go to the Infected trait and apply the correct phase to each of its Transmit and Progress events.
So, the transmit event that adds Infected should be in the "infection" phase, the progress event that removes infection and adds immunity should be in the "recovery" phase, and the one that applies Dead should be in the "death" phase.
You will also need to move the treatment Transmit event in the Doctor trait to the "treatment" phase.
All events not assigned a phase (like the removal of treatment) will happen at the beginning of a day, before the other phases.
Now try and run it again.
The disease doesn't seem to be spreading anymore.
By splitting up the phases, we have created an unintended consequence - since infection doubles the number of infected, and the recovery phase causes half of the infected to recover, and now recovery happens after infection now, it balances it out and the disease never spreads.
This kind of thing tends to happen when splitting events into phases. You may need to adjust your scenarios to make things work as intended.
Let's re-adjust by setting the recovery probability to 0.25 and the death probability to 0.05.
Now things work as intended - all infected people are given treatment, and none of them die until the doctors can no longer handle them.
You may also want to remove the Doctor trait during the death event, to prevent dead doctors from treating people.
Adding Government Restrictions
Government Actions allows the user to control the scenario. Let us create an action that adds restrictions to the population in order to slow down the transmission of the virus.
Open the Government Actions menu and add a new action. Call it "restrictions". Let us make it a sliding scale that goes from 0 to 100. Set the Max to 100 and the Control Type to Slider.
All Government Actions work by producing vectors - for this one, we will apply a "restricted" trait that reduces the chances of either spreading or being infected by the virus. Let us create a new Trait called "restricted".
To start, create a new Trait, called "restricted", and give it a Transmit Mod that multiplies Transmission events of the vector type "virus" by 0, and an Infect Mod that multiplies infection by transmitted viruses by 0. Since we want the Trait to disappear at the beginning of each day, give it a Progress event that removes itself with a probability of 1 as well.
Then, add a new Vector Type, called "restrictions".
We will also need to create a new phase, which occurs before the "infect" phase. If restrictions are added at the same phase they are removed, people who were restricted on the previous day will be unaffected by the restrictions applied on the current day - but they will still have the Progress event that remove the restrictions from them. This will prevent the same person from being restricted two days in a row, which is not what we want.
So, create a "restrictions" phase and put it before the "infect" phase.
Finally, go back to the restriction Government Action, and make it transmit a vector of type "restrictions" that applies the Restricted trait, in the "restrictions" phase.
Determining the Amount can be a bit tricky. The actual amount of vectors produced each day will be the player-selected value (a number from 0 to 100), multiplied by the Amount selected. If the "Broadcast" checkbox is clicked, the vectors will be multiplied by the total population - meaning that, if the current value multiplied by the Amount is 1, all people in the site will be infected. If it is 0.5, half of the people will be.
Let us make it so that the amount selected will affect that particular percentage of the population. Set Amount to 0.01 (since 0.01 * 100 is 1) and select the Broadcast option. When the value is 100, all people in the city should be affected.
Now run the scenario.
By moving the Restrictions slider back and forth, you can adjust the effective infection rate of the virus and try to keep it low enough to avoid overwhelming the doctors, preventing deaths.
Adding a Cost
To prevent the player from simply using whatever government actions they want, you may create a resource that the action consumes.
Open the Government Resources menu, then create a resource. Call it "economic health".
There are many different display options available for government resources. You can display it as a simple number, or as a percentage (with 1 as 100% by default). You may also show it as a fraction, using another resource as the denominator. It can be displayed as a value on the graph, or as a percentage, which will make it a dotted line that always occupies a certain height on the graph and does not change when you move the graph height slider.
Let's use it as a percentage. Set the initial value to 1 and both the display type and the graph type to Percentage.
Next, go to the Restrictions panel, and add a Cost. Set the resource to economic health. The cost will be multiplied by the current value of the action, and each percentage point is 0.01, so to make it drop by 1% each day when at full restrictions, set the cost to -0.0001.
But what about...
This is by no means a true-to-life scenario. Few diseases spread this quickly, few are this deadly, most do not convey 100% immunity, and treatment is rarely 100% effective. However, by modifying these variables, it is possible to model many existing diseases.
You can also use this tutorial as a springboard for adding more systems, as we have demonstrated most of the principles involved in creating a scenario using the PathoGenic engine.
What happens if we add a multi-stage illness, for example - if an infected person can progress to a more severe stage of the illness, but can infect others even at earlier stages? What if certain demographics are more vulnerable to the effects of the disease, or more prone to spreading it? What if we add vaccination into the mix, conveying immunity without the disease - and what if it comes with side effects? What if there are people spreading ideas that impact the way others interact with the virus?
By this point, you should understand the system well enough to construct your own scenarios and model all kinds of epidemics on a basic level.
But if you want to do more, read on.
Working with Events
PathoGenic includes an in-depth event-based system which allows you to incorporate custom behaviors into a scenario. Custom events have numerous possible effects and will trigger whenever their specified conditions are met.
Events may trigger a specific number of times, or you may let them try and trigger every day by setting their "Times event can fire" value to -1.
Each event has a set of conditions, and will fire when one of those conditions (or several, if they include the "required" option) is met. A condition compares two values and checks if one is greater than, less than, or equal to the other.
If an event's condition is true, it will run a number of results. These results may display news items for flavor, transmit vectors, set the value of a government resource, show and hide parts of the user interface, and trigger the scenario's victory or failure conditions.
Government resources are particularly useful for custom events. A government resource doubles up as a simple numeric variable, which means that events can use them to store data. You may hide them from the UI by clicking the "hidden" checkbox.
I strongly suggest using events and resources to handle values whenever possible, rather than traits. Adding traits significantly increases the complexity of a scenario and produces lag if you are using too many of them, while events and resources are handled much faster.
For example, in most of my scenarios, I will use events to handle hospitalization, storing hospital capacity as a resource and producing treatment vectors based on the amount of hospital beds, rather than using doctors-as-traits, as in the tutorial. Although this means that doctors will not get sick and die since they are abstracted, it frees up an extra trait to add more complexity elsewhere.
Note that, when determining a value in an event, order-of-operations is not respected. Instead, each value starts at 0 and each step has a value added, subtracted, multiplied or divided on top of the current value. So if, for example, you want to add 1 to economic health, you will need to set the resource "economic health" to {economic health + 1}.
You may print any government resource's value in a news event by surrounding the variable id in {curly brackets}.