1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137namespace Duets.Cli.Text.Prompts
open Duets.Cli.Text
open Duets.Common
open Duets.Entities
open Duets.Simulation
[<RequireQualifiedAccess>]
module CarDealer =
let createGreetingPrompt
state
(carDealer: CarDealer)
(availableCars: PurchasableItem list)
=
let currentCity = state |> Queries.World.currentCity
let currentPlace = state |> Queries.World.currentPlace
let currentDate = state |> Queries.Calendar.today
let priceRangeDescription =
match carDealer.PriceRange with
| CarPriceRange.Budget -> "budget-friendly, practical vehicles"
| CarPriceRange.MidRange ->
"quality mid-range vehicles with premium features"
| CarPriceRange.Premium ->
"luxury, high-performance premium vehicles"
let formattedItems =
availableCars
|> List.map (fun (item, _) -> $"{item.Brand} {item.Name}")
|> String.join ","
Common.createPrompt
$"""
You are {carDealer.Dealer.Name}, an enthusiastic car salesperson at a dealership called {currentPlace.Name} in {currentCity.Id |> Generic.cityName}
that specializes in {priceRangeDescription}. A customer has just walked into the showroom.
Rules:
- Generate a single, natural greeting and opening line (2-3 sentences max).
- Be professional but friendly - you're trying to make a sale.
- You might comment on the vehicles, ask about their needs, or make them feel welcome.
- Keep it conversational and realistic for a car salesperson.
- **Do not** use quotation marks, asterisks, or any formatting.
- **Do not** include the salesperson's name or any labels like "Salesperson:" - just the dialogue itself.
- Match the tone to selling {priceRangeDescription}.
Context:
- Time: {currentDate.DayMoment} in {currentDate.Season}
- Dealership type: {priceRangeDescription}
- City: {currentCity.Id |> Generic.cityName}
- Available models: {formattedItems}
Generate the salesperson's greeting:
"""
let createPitchPrompt
state
(carDealer: CarDealer)
(car: Item)
(price: Amount)
=
let character = state |> Queries.Characters.playableCharacter
let currentCity = state |> Queries.World.currentCity
Common.createPrompt
$"""
You are {carDealer.Dealer.Name}, a car salesperson in {currentCity.Id |> Generic.cityName}. The customer ({character.Name}) is interested in a {car.Brand} {car.Name} priced at {price}.
Rules:
- Generate a brief sales pitch (2-3 sentences) highlighting the car's appeal.
- Be persuasive but not pushy - focus on features, style, performance, or lifestyle fit.
- Keep it natural and conversational.
- **Do not** use quotation marks, asterisks, or any formatting.
- **Do not** include the salesperson's name or labels - just the dialogue itself.
Generate the sales pitch for this specific car:
"""
let createClosingPrompt
(carDealer: CarDealer)
(car: Item)
(accepted: bool)
=
let context =
if accepted then
"The customer has decided to purchase the vehicle"
else
"The customer has decided not to purchase the vehicle today"
Common.createPrompt
$"""
You are {carDealer.Dealer.Name}, a car salesperson. {context} - the {car.Brand} {car.Name}.
Rules:
- Generate a brief, natural closing line (1-2 sentences).
- If they bought: be congratulatory and professional, mention they'll find the car outside.
- If they didn't buy: be understanding and leave the door open for future business.
- Keep it short and realistic.
- **Do not** use quotation marks, asterisks, or any formatting.
- **Do not** include the salesperson's name or labels - just the dialogue itself.
Generate the closing line:
"""
let createInsufficientFundsPrompt
state
(carDealer: CarDealer)
(car: Item)
(price: Amount)
=
let character = state |> Queries.Characters.playableCharacter
let currentCity = state |> Queries.World.currentCity
let dealershipTone =
match carDealer.PriceRange with
| CarPriceRange.Budget -> "understanding but slightly disappointed"
| CarPriceRange.MidRange ->
"professional but noticeably condescending"
| CarPriceRange.Premium ->
"highly condescending and subtly shaming, making it clear this customer doesn't belong here"
Common.createPrompt
$"""
You are {carDealer.Dealer.Name}, a car salesperson in {currentCity.Id |> Generic.cityName}. The customer ({character.Name}) wanted to purchase a {car.Brand} {car.Name} priced at {price}, but their payment was declined - they don't have enough money.
Rules:
- Generate a brief response (2-3 sentences) to this awkward situation.
- Tone should be {dealershipTone}.
- For budget dealerships: be sympathetic, suggest saving up or looking at financing options.
- For mid-range dealerships: be politely condescending, perhaps suggest they look at "more suitable options" or come back when they're "ready."
- For premium dealerships: be cutting and subtly cruel - imply they're wasting your time, question why they're even here, make them feel out of place. Use phrases like "perhaps this isn't the right establishment for you" or "we cater to a certain clientele."
- Keep it realistic for a salesperson (they won't be overtly rude, but the disdain should be clear in premium stores).
- **Do not** use quotation marks, asterisks, or any formatting.
- **Do not** include the salesperson's name or labels - just the dialogue itself.
Generate the salesperson's response to the declined payment:
"""