Candy Shop Economics


check it out on github: the candy shop on github
Welcome to the Candy Shop (Yes, Literally)
If you’ve read any of my blog posts, you know I enjoy taking completely ridiculous lyrics or pop culture references, interpreting them as literally as possible, and building software engineering projects around them in an overly serious, data-driven way.
So naturally, when I heard the 2003 hit “Candy Shop” by 50 Cent, I had only one question:
What if this was a real candy shop?
One taste of a free sample — and people are spending all they got? That’s either great marketing… or the start of an economic crisis.
This post explores that question using agent-based modeling (ABM), Python, and the Mesa framework. If 50 Cent opened a real-world candy shop with candy that addictive, what would happen to the local economy? Would people go broke? Would society collapse? Would rent go unpaid while lollipops fly off the shelves?
Here’s how this post is structured, so you can skip to the good parts if you like:
Part 1: The Premise — Taking “Candy Shop” Literally. The absurd scenario behind this project.
We break down the lyrics and imagine a world where 50 Cent runs a real, wildly successful candy business — one so good it causes customers to overspend on sugar.
Part 2: Agent-Based Modeling — Simulating People, Not Just Numbers. What ABM is and why it’s ideal for this scenario.
A crash course in ABM: what it is, how it works, and why it’s perfect for modeling economic ripple effects from an addictive candy economy.
Part 3: Building the Simulation — Python, Mesa, and Candy Logic. Real-world data, agent generation, economic modeling.
How I created realistic (and some not-so-realistic) agents with behaviors like income, stress, addiction, spending habits, and how they interact inside a growing candy crisis.
Part 4: The Results — What Happens When the Candy’s Too Good. Does society collapse from candy addiction?
We run the simulation and find out: does society collapse under the weight of its own sweet tooth?
Part 1: The Premise
Zoom image will be displayed
Image designed by the author using elements generated with AI
If you’ve read some of my previous blog posts, you know I have a bit of a habit: I take utterly absurd lyrics or pop culture references, interpret them as literally as possible, and then build an entirely serious, data-driven software engineering project around that ridiculous premise.
Take, for example:
Jay-Z’s 99 Problems — where I used a neural network to figure out what all 99 problems might actually be:
Jay-Z Has 99 Problems — Here’s What a Neural Network Thinks They Are“Peaches” by The Presidents of the United States of America — where I simulated what would happen if someone hoarded millions of peaches and wrecked a local fruit economy:
Millions of Peaches: An Economic Simulation in Python
So, recently I was listening to another pop classic: “Candy Shop” by 50 Cent — a 2003 hit filled with… let’s call it entrepreneurial ambition. In it, 50 Cent proclaims:
“I’ll take you to the Candy Shop,
I’ll let you lick the lollipop,
Go ‘head, girl, don’t you stop,
Boy, one taste of what I got,
I’ll have you spendin’ all you got.”
Now, yes, I do understand that he isn’t actually talking about a literal candy shop. There’s no need to slide into my DMs with “You know that’s not about candy, right?” I get it.
But let’s suspend disbelief for a moment. Let’s say, hypothetically, 50 Cent did open a real candy shop. Based on these lyrics, the business model appears to go something like this:
Free samples up front (“I’ll let you lick the lollipop” — no mention of a purchase).
After one taste, customers are so hooked that they spend everything they have (“I’ll have you spendin’ all you got”).
Now, I’m no economist, and I don’t run a small business, but… that sounds like some seriously addictive candy. If it only takes one free taste to drain someone’s bank account, this candy practically markets itself. No ad budget needed — word of mouth would spread like wildfire. Honestly, if the music thing hadn’t panned out, 50 Cent may have had a real opportunity in confectionery.
But then I started thinking: what would actually happen if this candy shop existed, and the product really was that irresistible?
Well… chaos. If people start spending all their money on candy, the downstream effects would be wild: missed rent, unpaid utilities, declining productivity, sugar-related health crises, strained families, and — inevitably — economic collapse.
Zoom image will be displayed
Image designed by the author using elements generated with AI
As I got deeper into building the simulation, I realized just how closely this absurd candy scenario mirrored real-world addiction. According to numerous studies and government resources, addiction dramatically impacts spending habits. Individuals struggling with addiction often prioritize purchasing addictive substances above essential needs, allocating significant portions of their income to drugs or alcohol while neglecting crucial expenses like housing, utilities, food, and healthcare.
In other words, you might think of this scenario as a sugary, legal version of the opioid crisis — sweet yet devastating.
Zoom image will be displayed
Image designed by the author using elements generated with AI
So, that’s the premise. In this 4-part post, we’ll build a data-driven simulation to explore:
1. How a single candy shop could destabilize a city.
2. How addiction economics scale in a population.
3. What happens when irresistible desires meet real-world constraints.
Because if 50 Cent really did open a Candy Shop like this… we might all be in trouble.
Part 2: Agent-Based Modeling — Simulating People, Not Just Numbers
I’ve played around with simulations before — using AI tools and Python loops with libraries like pandas. But with each new absurd project I tackle, I try to pick up a new technology I haven’t used before. This one felt like the perfect chance to dive deeper into Agent-Based Modeling, or ABM.
For this project, I used a Python framework called Mesa, which is specifically built for ABM work. It’s flexible, extensible, and a great fit for modeling behavior-driven systems — especially ridiculous ones involving fictional candy shops.
Mesa provided essential tools like built-in scheduling loops (SimultaneousActivation
) and automatic data collection (DataCollector
), drastically simplifying implementation.
What Is Agent-Based Modeling?
At its core, ABM is a bottom-up simulation technique where individual entities (called agents) interact with each other and their environment. Each agent operates independently, based on its own set of rules, attributes, and behaviors. These micro-level interactions combine to produce emergent, system-wide outcomes that often can’t be easily predicted from top-down analysis.
Agents can represent just about anything:
Zoom image will be displayed
Image designed by the author using elements generated with AI
- What makes ABM powerful is that you’re not modeling averages or aggregates. You’re modeling individual behavior and watching what unfolds.
ABM vs. AI/ML: What’s the Difference?
These days, when someone says “simulation” or “prediction,” people tend to think of AI or machine learning. But ABM is a very different beast.
Here’s a breakdown:
Zoom image will be displayed
So, for example, if you had a massive dataset of real-world candy shops and you wanted to predict next month’s revenue, machine learning would be your go-to.
But if you’re trying to model something hypothetical, like the world-shaking candy shop 50 Cent dreams of — one where a single taste ruins people’s financial lives — then ABM is your best friend.
Real-World Example: ABM vs. AI in a Pandemic
Imagine you’re analyzing the spread of a disease like COVID-19.
Zoom image will be displayed
Image designed by the author using elements generated with AI
- With AI, you’d gather data on population density, mobility patterns, and case counts, and then train a model to forecast new infections. You don’t necessarily know why it spreads — just that it tends to under certain patterns.
Zoom image will be displayed
Image designed by the author using elements generated with AI
- With ABM, you’d simulate a virtual town with virtual people who go to work, school, and restaurants. You’d model how the disease spreads based on their behavior and environment. Then you could test interventions like, “What if we closed schools for two weeks?” or “What if 50% of agents wore masks?”
This is where ABM shines: exploring complex cause-and-effect relationships in a system where data is incomplete, sparse, or entirely theoretical.
Who Uses ABM?
Aside from people simulating financial devastation via lollipops, ABM is used in:
Epidemiology (e.g. virus spread, vaccine strategy)
Economics (e.g. consumer behavior, market crashes)
Urban planning (e.g. traffic, zoning, public services)
Ecology (e.g. predator-prey dynamics)
Social science (e.g. crime, segregation, migration)
While it’s powerful, ABM still has a relatively small user base compared to Scikit-Learn, TensorFlow, or PyTorch. That’s mostly because:
1. Many business problems don’t require modeling entire cities.
2. Tuning and validating ABMs can be complex and time-consuming.
3. The industry is largely focused on AI/ML for prediction, not simulation.
Still, when you’re more interested in “what might happen?” than in “what will happen?”, ABM offers a unique and incredibly insightful lens.
Why Use Mesa for ABM?
Could you build an ABM system from scratch in Python? Sure. But Mesa makes it easier — and keeps you from reinventing a very complex wheel.
Mesa provides:
1. A structured framework for agent management and scheduling
2. Built-in tools for visualization and user interaction
3. Easier scaling as your model grows in complexity
Without Mesa, you’d be writing your own update loops, state containers, interaction rules, and possibly custom visualization tools — which would get overwhelming fast if you’re juggling addiction stages, economic ripple effects, and population behavior.
TL;DR
If you want to:
1. Forecast something from lots of data → use AI/ML.
2. Explore what might happen in a hypothetical system with complex behaviors → use ABM.
And if you’re going the ABM route, Mesa can save you a ton of time.
Zoom image will be displayed
Image designed by the author using elements generated with AI
Part 3: Building the Simulation — Python, Mesa, and Candy Logic
So now that all the boring stuff with ABM and Mesa is out of the way, let’s dive into this project. So my initial goal was simply to create a simulation that would eventually crash. At some point, if everyone buys a lot of candy, they will go broke, and the economy will collapse. Simple enough. But once I really dove into the project and the ABM system I was creating, I realized 2 things:
1. Your simulation will only be as good as your starting data.
2. Fine tuning an ABM system from scratch is a lot of work.
Basically I started with a very simple and rudimentary set of data, based loosely on Queens, NY from 2003. Why that oddly specific date and time you might ask? Because 50 Cent, who this entire project was based on, is from Queens, New York. And 2003 was when he released some of his biggest hits and really got on the map. And let’s be honest, if he did have a candy shop, it probably would have been after 2003, once he had enough capital to do so.
To ground the simulation in reality, I sourced detailed demographic and economic statistics from publicly available resources, primarily the U.S. Census Bureau, city-specific data repositories, and historical economic reports. These data points included income brackets, household sizes, average living expenses, typical debt-to-income ratios, and asset distributions. For example, I translated census income brackets into realistic agent incomes using random sampling weighted according to the actual distribution seen in Queens in 2003.
Zoom image will be displayed
Using this and other data, I created a generation system that would build a set of 10,000 agents. The really tricky part with this was that I wanted to keep the data within the average ranges of Queens, NY 2003. But If you simply set a randInt or random.uniform within the average range of all the values you want, you get a perfectly homogenous distribution of values. For example, if you do that with ages, then you end up with the same number of 80 year olds as 20 year olds. Yes, they all fall within the average range of ages for Queens, NY 2003, but the distribution of ages doesn’t match reality. This can be a problem with simulations like this, because specifically with addiction type behaviors, age can be a factor, and if your age distribution is off, it will be hard to see how policy changes in your environment will actually affect the real world.
To fix this, I had to figure out what the distribution was for values I cared about, like age, income, housing, employment…really any value that would affect addiction. Then, I had to adjust my formula for generating the agents, so that they not only stayed within the average ranges I expected, but followed a bell curve or whatever scale they were meant to follow.
Zoom image will be displayed
Image designed by the author using elements generated with AI
As an example of this, I chose income brackets that each agent would fall into, with corresponding weights. What this does is make sure that as agents are generated, more agents will fall into the most probable income brackets, and less will fall into the less probable income brackets. You still end up with an average income of around $42,000 ( based on Queens 2003 ), but the distribution of those incomes follows a realistic curve.
def generate_income():
income_brackets = [(15000, 0.2), (30000, 0.5), (60000, 0.25), (100000, 0.05)]
bracket = random.choices(
[b[0] for b in income_brackets], # Income values
[b[1] for b in income_brackets] # Weights/probabilities
)[0]
return random.randint(bracket - 5000, bracket + 5000) # Random within bracket
Honestly, I did not expect for the fine tuning of the agent generation portion of this project to take so long. I figured, “Ah, I’ll make a short script with ChatGPT, and I’ll be done in an hour.” That was partially true. I was done in an hour, but my data was jacked.
Like I said earlier, your simulation will only be as good as your data.
Once your agent generation seems to be in order, the next challenge is simulating each step. In Mesa, each step can represent any arbitrary length of time. A day, a month, etc. It really just depends on what you want your simulation to measure. Since I was measuring candy purchased over time, I ran the simulation for a month of time, but each step lasted a day. This allowed me to fine tune daily purchases like candy or groceries, and then also figure in monthly expenses like rent, car payments, etc. Mesa’s built in tools for creating this loop of time make it a lot easier than just hardcoding and manually doing it with loops and panda arrays.
However, it’s not all unicorns and rainbows. I can’t tell you how many hours I spent debugging the data to figure out why so many agents were abandoning credit card payments ( Sure, that’s normal with addictive behavior ). But not after having already sold their house. I set up an intricate system to simulate decision making based on the National Institute on Drug Abuse (NIDA), and fine tuned how agents might realistically, slowly over time begin to divert more money from sources to spending on candy. I found part of the problem was my finance system that I had created, which was largely insufficient at first for handling the simulation.
I ended up settling on a system that looks basically like this:
Opportunity > Influence > Actions > Effects
Zoom image will be displayed
Image designed by the author using elements generated with AI
Exposure
Basically, each day, I calculate how much exposure or opportunity an agent has to “candy”. This is in the form of friends, family, acquaintances as well as marketing. Each agent has a group of friends based on income, employment, marital status, hobbies, etc, which are randomly but methodically assigned in the agent generation ( Yes, I said it was a rabbit hole ). Each family member who starts using “candy” gives another agent in that same group a level of exposure. Acquaintances do to, but less of an exposure.
Influence
Then, I calculate how much of that exposure turns into influence by asking questions like, is the agent stressed, has trauma, or is unemployed? I determined how to distribute factors among agents like this based on data from sources including The American Psychological Association (APA), The National Institute for Occupational Safety, Health (NIOSH) and The American Institute of Stress. I know…rabbit hole. In addition to emotional factors, I also included physical factors like whether the agent has a car, or has been divorced ( from sources like The Federal Highway Administration (FHWA) and Census Bureau ). Based on all this, I make a calculation on how much that opportunity will convert into actual influence on an agent.
Image designed by the author using elements generated with AI
I also introduced a funny bug into this project ( don’t judge ). Everything was working swimmingly well, then I made some changes to finances, fixed some other bugs. Then suddenly, every time the simulation ran, like, nobody wanted any candy. It rose a little, but pennies to the dollar of what it was doing before. I couldn’t figure out why influence had dropped so drastically when opportunity and actions had remained relatively constant. I discovered that earlier, I was keeping track of days candy had been consumed with 1’s and 0’s, and storing them as a string. Each day, I would concatenate a 1 or 0 to the string. So if someone had consumed candy the last 4 days, but none the 2 days previous to that, the string would be “001111”. Then, I would interpret this as a habit. Which agents had used the most, the most frequently, and the most consistently. But then, I decided this neglected quantity. An agent who consumes 25 candies a day gets a “1”, and so does an agent who consumes a single candy. So I changed this to keep track of quanity by day, so the string became something like “0–1–1–3–5–5–10”. And so on. Influence was dropping, because I forgot to update the logic to count only ones and zeros. So an agent with a score like “0–1–25–35–45” who is consuming a ton of candy, would get a score of 1. Duh?! Anyway, I came up with a nifty scaler function to weight the score based on quantity and recent use, which gave me some flexibitliy if I decided to use linear or exponential scaling.
def addiction_score(data_string, method="exp", base=1.1):
lollipops = list(map(float, data_string.split('-')))
n = len(lollipops)
if method == "exp":
weights = [base ** i for i in range(n)]
elif method == "linear":
weights = [i + 1 for i in range(n)]
else:
raise ValueError("Unknown weighting method")
score = sum(l * w for l, w in zip(lollipops, weights))
return score
Action
Finally, we move to actions, where I convert that number ( a value from 1 to 10 ) of influence into actions. Based on this agents influence, how much “candy” are they going to want. The original market price for candy in my simulation is based on the average candy price for Queens NY 2003, which oddly enough there wasn’t much data on. But I did find several Facebook posts from around that time where people mentioned things like, “$1.00 doesn’t buy nearly as much candy as it did in 1990”. Based on the average rates of inflation and commodities I could find data for, I came up with a base price for candy when the simulation starts, and then adjusted that value as supply and demand changed through the experiment. In this simulation, I let each agent buy how much ever candy they wanted, as long as there was supply, and they had money. They weren’t usually deterred by price if the price had gone up.
Here, each agent has a desired amount of candy and a budget constraint. The function calculates how much candy the agent can realistically purchase, reflecting tough decisions that lead to possible overspending or reallocating money from essential needs:
def determine_candy_purchase_amount(agent_data, candy_price):
desired_amount = agent_data["desire_for_candy"]
affordable_amount = agent_data["finances"]["available_cash"] // candy_price
purchase_amount = min(desired_amount, affordable_amount)
return purchase_amount
available_cash
is calculated each day by subtracting essential daily expenses like groceries from total liquid assets.
Effects
Then the final step. This is where I created the effects that would stem from actions of buying candy, such as missed rent or unpaid bills. Until this point, most of the financial calculations had been largely ad-hoc. But it was at this point that I redesigned many of the decisions and created a more robust financial system within the project. I realized I needed to track income sources, assets (both physical and liquid assets), as well as planned, monthly expenditures (housing, utilities, payments), but I would also need to keep track of immediate expenditures (candy and groceries). I also needed to keep track of liabilities and each agent’s payment status on those liabilities (credit card debts and credit card limits), as well as Dti (debt to income ratio), spending habits, and most importantly, how any of those funds were being allocated over time to pay for candy.
Zoom image will be displayed
Image designed by the author using elements generated with AI
Anatomy of the Agent
At the core of our simulation is the agent itself, defined in the agent.py
file. This class contains:
Attributes that track the agent’s financial state, addiction level, stress, and personal details.
Methods that dictate how an agent behaves each step of the simulation, from decision-making to interacting with their environment.
class CandyAgent(Agent):
def __init__(self, unique_id, model, agent_data):
super().__init__(unique_id, model)
self.data = agent_data
def step(self):
candy_to_buy = determine_candy_purchase_amount(self.data, self.model.candy_price)
self.data["finances"]["cash"] -= candy_to_buy * self.model.candy_price
update_addiction(self.data, candy_to_buy)
This basic agent step method demonstrates how agents make daily purchasing decisions based on available funds and addiction levels. With each step, an agent’s financial and addiction states update, creating emergent economic behaviors over time.
Modularity
Having modularized, DRY code is just a good coding practice across the board. But I found that with Mesa and ABM projects, having modularized code is not just a good practice, but is essential. It will also keep you from ripping your hair out trying to hunt down a bug later. As you can see from my structure above, I broke the agent logic down into clear sections. And this is reflected in my project structure. With any ABM project, there will be lots of fine-tuned adjustments. And having the code modularized will make those adjustments easier to diagnose and dial in. Here’s a snapshot of part of my file structure so you can see how I structured this part of my file.
With each iteration of this project, the simulations took longer and longer as I added more data, more feedback loops and more calculations. On my standard MacBook Pro (M4 Max, 32GB RAM), each simulation took about 20 minutes to run through 10,000 agents for a month of simulated time. If you check out my GitHub, I’m sure you can find ways I could have parallelized or optimized certain areas. And for sure, I started down that route. But the problem with too much optimization is that, it’s a heck of a lot easier to find a bug when it’s neatly sandwiched in between basic if blocks, rather than in a monstrosity of a nested ternary in a loop. Sure, maybe whatever you wrote is optimized. But can you read it?
Part 4: The Results — What Happens When the Candy’s Too Good.
Thanks for staying with me so far. This last part will be short and sweet. What happens when the candy is too good? Honestly, from my simulations, the candy basically has to be heroin, and the entire society has to be extremely prone to addictive behavior to drive demand enough to cause economic collapse. In short, 50 Cent must have one heck of a candy recipe!
Analysis
This graph illustrates the trajectory of average DTI among agents in the simulation across a 30-day period. Debt-to-Income ratio is a critical financial metric that compares an individual’s monthly debt obligations to their monthly income. In the context of this simulation, a rising DTI suggests that agents are accruing debt at a pace that outstrips income growth — or, more realistically, in a stagnant income environment, that spending is accelerating dangerously.
Zoom image will be displayed
1. Initial Stability (~Days 0–6)
The graph begins with a flat trend in DTI, indicating relative financial stability among agents. At this stage, candy consumption may be minimal, sporadic, or confined to agents with disposable income.
There is likely limited exposure or influence at this point — the social/marketing contagion model of candy addiction hasn’t yet gained traction.
Interpretation: Early on, candy remains a controlled discretionary expense. Agents are not yet influenced by external social or psychological factors to increase spending.
The graph reflects behavioral contagion and economic erosion triggered by a seemingly trivial product. While candy begins as a small vice, it becomes a catalyst for systemic financial instability once agents experience sustained exposure and emotional vulnerability. The rising DTI demonstrates how micro-decisions (individual purchases) compound into macro-level consequences (population-wide economic decline).
Zoom image will be displayed
Behavioral Economic Analysis: Candy Addiction vs. Influence Over Time
This dual-line graph tracks the average levels of influence and candy addiction among agents across a 30-day simulation period. The two variables represent distinct but tightly connected stages in the behavioral contagion model underlying your simulation:
Influence: a composite measure of social exposure, environmental triggers (e.g., marketing), psychological vulnerability (e.g., stress), and opportunity.
Candy Addiction: the resulting behavioral outcome, representing how deeply agents are committing to repeated consumption behavior.
Key Observations
1. Initial Rise and Divergence (Days 1–6)
Both influence and addiction begin at moderate levels and rise together. Influence shows a sharper climb between Day 2 and Day 6, indicating early exposure and susceptibility gains traction quickly.
Addiction tracks slightly behind influence, as expected in a lagging behavioral response model — agents need time to act on exposure.
Inference: This reflects the natural delay between influence and action, consistent with real-world habit formation where peer influence precedes actual consumption.
2. Peak and Response Period (Days 6–11)
Addiction peaks around Day 7–8 while influence begins a decline, suggesting agents begin acting on accumulated influence by initiating candy consumption en masse.
The divergence may indicate saturation effects — once exposed, agents don’t need further influence to sustain addictive behavior.
Inference: Influence loses marginal utility as agents cross a threshold; addiction momentum takes over, driven more by habit and less by continued exposure.
3. Stabilization and Oscillation (Days 12–22)
Both variables show mild oscillations. Influence dips but stabilizes around ~5.0, while addiction remains elevated but fluctuates slightly below its peak.
These fluctuations may correspond to economic constraints (e.g., limited cash/credit) or social backpressure — not all agents can continually escalate consumption indefinitely.
Inference: The system appears to enter a behavioral equilibrium*, where the social contagion model hits structural limitations — possibly due to market saturation or agents self-regulating.*
4. Late Plateau (Days 23–30)
Addiction flattens near 5.3–5.5; influence remains steady but slightly below that.
The consistent gap suggests addiction is now self-sustaining, no longer tightly coupled to new influence. This resembles substance or habit-based consumption patterns where behavioral inertia dominates.
Inference: Agents have entered a chronic phase of behavior — consumption persists even without rising external pressure, possibly because past decisions and sunk costs (debt, stress) reinforce the habit.
Behavioral Analysis Summary
- Initiation — Influence rises sharply; addiction follows with a short lag. Early exposure (marketing, social networks) begins influencing agents, but addiction behavior takes time to manifest.
2. Acceleration — Addiction outpaces influence; addiction peaks while influence flattens. This suggests a tipping point: agents begin consuming candy en masse, influence becomes less necessary once the behavior is adopted.
3. Fluctuation & Saturation — Both metrics fluctuate; addiction stabilizes slightly above influence. This Reflects agents hitting economic or social limits. Some may resist, others relapse or reinforce habits.
4. Behavioral Plateau — Addiction flattens at a high level; influence stays moderate. Long-term behavioral inertia sets in — agents maintain addiction even with stable or reduced influence. Habit is now internalized.
Subscribe to my newsletter
Read articles from Ethan Jarrell directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
