Lemonade Stand: browser recreation of the Atari 8-bit BASIC game
Faithful day loop - weather report, cost of lemonade rising over the summer, glasses/signs/price decisions, thunderstorms, heat waves and street crews - with the $$ LEMONSVILLE DAILY FINANCIAL REPORT $$ laid out the way it printed. The simulation is kept out of React so a season can be run headlessly: a careful player compounds $2.00 into roughly $22 over twelve days, while an all-in player goes broke about seven times in ten. Weather scenes are pixel rectangles in SVG and the music is a small chiptune engine on the Web Audio API, so there are no binary assets. The screen is locked to a 4:3 tube and never scrolls.
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
# Lemonade Stand
|
||||
|
||||
A browser recreation of the Atari 8-bit BASIC classic — the one you typed in,
|
||||
ran on a TV, and lost two dollars to on a cloudy day.
|
||||
|
||||
React + TypeScript + Vite. No art assets and no audio files: the weather is
|
||||
drawn as pixel rectangles in SVG, and the music is generated by a small
|
||||
chiptune engine built on the Web Audio API.
|
||||
|
||||
## Playing
|
||||
|
||||
```
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
One to four players share the keyboard, hot-seat style. Each morning you see
|
||||
the weather, then decide three things: how many glasses to make, how many
|
||||
15-cent signs to put up, and what to charge. Then the town votes with its
|
||||
pocket money.
|
||||
|
||||
- Lemonade costs 2 cents a glass on days 1–2, 4 cents through day 7, and
|
||||
5 cents after that.
|
||||
- Everything you make is made *today*. Unsold glasses are poured away.
|
||||
- A hot, dry day brings a bigger crowd that will pay more. A heat wave is
|
||||
better still.
|
||||
- A cloudy day can turn into a thunderstorm, and a thunderstorm ruins every
|
||||
glass you made.
|
||||
- Street crews close the road now and then, and they tend to stay for a
|
||||
second day.
|
||||
- Signs work, but with sharp diminishing returns — the fourth one barely
|
||||
earns its 15 cents.
|
||||
|
||||
You are broke when you cannot afford a single glass. Otherwise the summer runs
|
||||
as long as you like; **RETIRE** closes the books and shows the standings.
|
||||
|
||||
## How it is put together
|
||||
|
||||
```
|
||||
src/
|
||||
game/ pure simulation - no React, no DOM
|
||||
constants.ts costs, weather profiles, the demand curve
|
||||
engine.ts rolls each day and settles the takings
|
||||
reducer.ts the day/turn state machine
|
||||
rng.ts seeded mulberry32, so a run can be replayed
|
||||
audio/
|
||||
synth.ts pulse-wave voices, noise percussion, look-ahead sequencer
|
||||
tunes.ts the title, trading and closing themes
|
||||
components/ the screens, and the CRT they are drawn on
|
||||
```
|
||||
|
||||
The simulation is deliberately kept out of React: `engine.ts` takes a player, a
|
||||
decision and a day and hands back a `DayResult`. That is what makes it possible
|
||||
to run a few hundred seasons in a script and check that a careful player grows
|
||||
their two dollars while a reckless one goes broke about seven times in ten.
|
||||
|
||||
### The demand curve
|
||||
|
||||
The original BASIC listing is not reproduced line for line. `constants.ts`
|
||||
holds a reconstruction tuned to behave the way the game plays: cheap lemonade
|
||||
sells out, sales fall to nothing once the price stops being a bargain, heat
|
||||
lifts both the crowd and the price people will tolerate, and signs help a lot
|
||||
at first and hardly at all later.
|
||||
|
||||
### The television
|
||||
|
||||
An Atari 800 fed a 4:3 television, and a television has no scrollbar. The tube
|
||||
is locked to 4:3 and everything inside it is sized in container units, so the
|
||||
picture stays in proportion at any size. If a page ever did come out taller
|
||||
than the tube, `Fit` scales it down rather than clipping or scrolling it.
|
||||
|
||||
## Sound
|
||||
|
||||
Audio starts on the first click or key press, as browsers require. Two pulse
|
||||
voices, a triangle bass and filtered white noise for percussion, driven by a
|
||||
scheduler that queues notes 200 ms ahead so the music does not stutter when
|
||||
React re-renders. `MUSIC` and `SOUND` toggle independently.
|
||||
Reference in New Issue
Block a user