Complexity Theory and Worldbuilding History

Background

Process

'Peace', 'Tax Dispute', 'Peace', 'Long Winter', 'Border Skirmishes', 'Earthquake', 'Major Recession', 'Valuable Resource Discovered', 'Taxes Raised', 'Bumper Crop', 'Peace', 'Long Winter', 'Peace', 'Trade Dispute', 'Border Skirmishes', 'Great Work of Art', 'Peace', 'Tax Dispute', 'Peace', 'Long Winter', 'Failed Harvest', 'Earthquake', 'Great Building Project', 'Peasant Uprising', 'Great Building Project', 'Bumper Crop', 'Peace', 'Long Winter', 'Blockade', 'Bumper Crop', 'Failed Harvest', 'Shortages', 'Great Building Project', 'Peasant Uprising', 'Taxes Raised', 'Bumper Crop', 'Blockade', 'Great Work of Art', 'Peace', 'Tax Dispute', 'Peace', 'Tax Dispute', 'Peace', 'Long Winter', 'Blockade', 'Great Work of Art', 'Blockade', 'Bumper Crop', 'Peace', 'Long Winter'

Building a Network

Possible Extensions

Appendix B: Event Dictionary

{
    0: ['Peace'],
    1: { 
        1 : ['Bumper Crop', 'Great Work of Art'],
        -1 : ['Tax Dispute', 'Trade Dispute', 'Long Winter']
    },
    2: {
        1: ['Taxes Raised', 'Great Building Project'],
        -1: ['Failed Harvest','Blockade', 'Border Skirmishes']
    },
    3: {
        1: ['Draft Enacted', 'Valuable Resource Discovered'],
        -1: ['Peasant Uprising', 'Earthquake', 'Shortages']
    },
    4: {
        1: ['Government Reformation', 'New Religious Movement'],
        -1: ['Famine', 'Major Recession', 'War', 'Inquisition']
    },
    5: {
        1: ['Great Battle', 'Martial Law Declared'],
        -1: ['Attempted Coup', 'Plague']
    },
    6: {
        1: ['Warlords Rise to Power','City States Rise in Power'],
        -1: ['Civil War', 'Invasion']
    },
    7: ['Collapse', 'Meteor Strike', 'Volcanic Eruption']
}

Appendix C: Code

import random
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import time
import copy

class History():

    def __init__(self):
        self.stability = 0
        self.base = .5
        self.thresh = .5
        self.step = 1
        self.multiplier = 2.
        self.eps = .5/7
        self.history = []

    def destabilize(self):
        # This makes it more likely for a history to become more unstable
        if self.thresh == 1. or self.thresh == 0.:
            pass
        elif self.thresh < .5:
            self.thresh -= self.eps * self.multiplier
        elif self.thresh > .5:
            self.thresh += self.eps * self.multiplier
        else:
            if random.random() < .5:
                self.thresh -= self.eps * self.multiplier
            else:
                self.thresh += self.eps * self.multiplier

    def refresh(self):
        # This sets the base probability of a step
        self.thresh = self.base - self.eps * self.stability
                
    def complex_step(self):
        # This takes a complex step
        r = random.random()
        if r < self.thresh:
            self.stability += self.step
        else:
            self.stability -= self.step
        self.history.append(self.stability)

class Network():

    def __init__(self, map=dict()):
        self.map = map

    def eval(self, events):
        # this method evaluates the histories
        for e in range(events):
            self.eval_step()

    def eval_step(self):
        self.refresh()
        self.update()
        for k in self.map.keys():
            k.complex_step()

    def update(self):
        # this method updates the thresh value for each key in map
        for k in self.map.keys():
            neighbors = self.map[k]
            for n in neighbors:
                # if a neighbor is less stable than a history, it is destabilized
                if abs(k.stability) < abs(n.stability):
                    k.destabilize()

    def refresh(self):
        # this method refreshes each key in map
        for k in self.map.keys():
            k.refresh()

And here are some analysis functions if you want to make some plots

def unpack(network, t):
    for i,k in enumerate(network.map.keys()):
        plt.scatter(t, k.history, label=f'history{i}',alpha=.5)
    plt.legend()
    plt.show()

def trend_analysis(network, t):
    for i, k in enumerate(network.map.keys()):
        lol = []
        for n in network.map[k]:
            lol.append(n.history)
        arr = np.array(lol)
        avg = np.average(abs(arr))
        h = copy.deepcopy(k.history)
        for j, el in enumerate(h):
            h[j] = abs(el)
        diff = abs(avg) - h
        plt.scatter(t, diff, label = f'hist{i}', alpha=.5)
    plt.legend()
    plt.ylabel('Average Distance to Neighbors')
    plt.show()

def stability_analysis(network):
    lol = []
    for k in network.map.keys():
        lol.append(k.history)
    arr = np.array(lol)
    print(arr)
    plt.hist(arr.flatten(),bins=[i for i in range(-7,8)], density=True)
    plt.show()