Posted on ::

Introduction

Schedule 1 Mix Calculator

I have made a website programmed in Rust, compiled to Web Assembly using the Yew framework, that can perform calculations related to the mixing mechanic in the Schedule 1 video game.

Schedule 1 is a business simulator video game which allows you to combine various ingredients to create products that have various effects on the user of the product. (Apologies for the circumlocutory language...)

This tool is available here: Schedule 1 Mix Calculator and can help you to:

  • Find the effects a product will have given a list of ingredients
  • Find a recipe that produces a product with the desired effects
  • Find a recipe with maximum revenue

The mixing logic in the project is based on Schedule1-Tools/mixer, which is a mixing calculator for Schedule 1 implemented in TypeScript.

Notice

This is a fan‑made project and is not affiliated with, authorized, maintained, sponsored, or endorsed by the developers of Schedule I the game. All game‑related content (names, trademarks, etc.) belongs to its respective owners.

Mixing Overview

Each ingredient in Schedule 1 has its own intrinsic effect, which will add to the product, when mixed in. For example, Cuke has the effect "Energizing".

However, if the product being mixed already has some effects, the ingredient may interact with the pre-existing effects and transform them into new effects. For example, if a product has the effect "Anti-Gravity", and Cuke is added, then the "Anti-Gravity" effect will be transformed into "Tropic Thunder". We call these ingredient interactions transformation rules.

In general, in order to determine the resulting effects from adding an ingredient to a recipe, we need a three-phase calculation.

  1. Apply any transformation rules of the ingredient to the existing effects
  2. Reapply unused transformation rules, to untransformed effects.
  3. If there are fewer than 8 effects at this point, add the ingredient's intrinsic effect.

Each of the transformation rules associated with an ingredient has a source effect and a target effect. In the first phase, if the source effect is present and the target effect is not present, then the source effect will be transformed into the target effect.

In the second phase, we reapply any unused transformation rules to any untransformed effects.

For example, suppose we have a mix with the effects Slippery and Munchies. Cuke has transformation rules that transform Slippery into Munchies and Munchies into Athletic. So in the first phase, Munchies will be transformed to Athletic, but Slippery will not go to Munchies because Munchies is already present. So at the start of the second phase, Slippery is untransformed and the Slippery → Munchies transformation is unused. The result is that Slippery+Munchies transforms to Munchies+Athletic.

In the third phase, the intrinsic effect of the ingrdient will be added, only if the product had less than 8 effects. If the product has 8 effects, adding another ingredient can swap effects in and out, but it will not add another effect, because 8 is the maximum.

Revenue and Cost

Each ingredient has an associated unit cost and each effect has a price multiplier. The formula for the price of a product is $\operatorname{round}(\text{Product Base Price} \times ( 1 + \text{Sum of Multipliers}))$.

Given a set of desired effects, we would like to find a recipe that produces those effects. If there are multiple ways to get the desired effects, we want the recipe with the lowest cost. This can be done with a Breadth-First Sort (BFS), which is a graph algorithm. In our case, the nodes are recipes (a base product plus a list of ingredients) and we place an edge from one node to another by adding an ingredient. There is only one way to reach each node, so our graph is, in fact a tree.

In the BFS algorithm, we start with a queue for nodes. When we visit each node, we add all the child nodes to the queue unless they have already been visited. However in our case there is only one path to each node, so we would always add every child node.

There are a few ways to "prune" our search tree, based on the fact we want to minimise cost. This means we can do some tests to avoid adding a node to the queue for further exploration. To do so, we keep a mapping from effect sets to the cheapest cost that achieves that combination. We also keep track of the cheapest recipe that has the desired effects.

  1. If the recipe has all the desired effects we do not need to add it to the queue as any child recipes will cost more
  2. If the recipe costs more than another recipe with the same effects, then do not add to the queue.
  3. If adding the cheapest ingredient to the recipe would make it more expensive than the cheapest known recipe that has the desired effects, then do not add it to the queue.
  4. If the recipe already has the maximum number of ingredients (which is a parameter you can set) do not add it to the queue.

A remark on "cost": even if the dollar cost of a recipe is lower, you may prefer another recipe that has fewer ingredients, as manufacturing times are quicker and staff requirements are lower in a production line. Therefore by default, we sort costs by number of ingredients first, followed by dollar cost. Using this cost metric makes the search faster, as it makes pruning more aggressive.