function play(scope = globalScope, resetNodes = false) {
    if (errorDetected) return; // Don't simulate until error is fixed
    if (loading === true) return; // Don't simulate until loaded

    simulationArea.simulationQueue.reset();
    plotArea.setExecutionTime(); // Waveform thing
    resetNodeHighlights(scope);
    // Reset Nodes if required
    if (resetNodes || forceResetNodes) {
        scope.reset();
        simulationArea.simulationQueue.reset();
        forceResetNodesSet(false);
    }

    // To store set of Nodes that have shown contention but kept temporarily
    simulationArea.contentionPending = new ContentionPendingData();
    // add inputs to the simulation queue
    scope.addInputs();
    // to check if we have infinite loop in circuit
    let stepCount = 0;
    let elem;
    while (!simulationArea.simulationQueue.isEmpty()) {
        if (errorDetected) {
            simulationArea.simulationQueue.reset();
            return;
        }
        elem = simulationArea.simulationQueue.pop();

        elem.resolve();

        stepCount++;
        if (stepCount > 1000000) { // Cyclic or infinite Circuit Detection
            showError('Simulation Stack limit exceeded: maybe due to cyclic paths or contention');
            forceResetNodesSet(true);
        }
    }
    // Check for Contentions
    if (simulationArea.contentionPending.size() > 0) {
        for (const [ourNode, theirNode] of simulationArea.contentionPending.nodes()) {
            ourNode.highlighted = true;
            theirNode.highlighted = true;
        }

        forceResetNodesSet(true);
        showError('Contention Error: One or more bus contentions in the circuit (check highlighted nodes)');
    }
}
Main fn that resolves circuit using event driven simulation
All inputs are added to a scope using scope.addinput() and
the simulation starts to play.
@param {Scope=} scope - the circuit we want to simulate
@param {boolean} resetNodes - boolean to reset all nodes
@category engine