Repository navigation
Expand file tree
/
Copy pathoutfit.py
More file actions
145 lines (132 loc) · 5.5 KB
/
Copy pathoutfit.py
File metadata and controls
145 lines (132 loc) · 5.5 KB
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
137
138
139
140
141
142
143
144
145
"""Buy a new character the essentials it lacks: ;outfit
;outfit INVENTORY's worn list read; each missing essential bought at its shop and worn; then back where you started
;outfit check list what is missing and where it is sold; buy nothing
;outfit stay ... and stay at the last shop instead of walking back
The essentials are client/game/outfit.py's catalog; the first is a
worn skinning knife, so ;hunt skins with the hand the weapon leaves
free (a held knife fills it: "You must have one hand free to skin.").
After dr-scripts' new-character.lic, which buys a new character's
knife at the same shop. Each
missing one is an errand: walk to the shop's map room, count the purse
(WEALTH), and when it is short of the price in the shop's coin WITHDRAW
the difference at the nearest teller (client/game/shop.py's afford) —
the shop's own town, once there — or, when the teller refuses, EXCHANGE
the purse's other coins at the nearest money-changer (client/game/bank.py's
exchange_each, as ;bank does: his minimum kept, his own line said); then
BUY, WEAR ("You attach a small steel skinning knife with a
leather-wrapped hilt to your wrist."). A purchase the shop refuses, or a purse that
stays short, ends the run with the game's line. The knife is Tobb's
at Knife Clan, 500 Kronars (Elanthipedia: Tobb's Smithy, Skinning
knife; captured 2026-09-13), #341. Stops on death.
Stop with: ;stop outfit.
"""
from client.game import bank, money, shop, travel
from client.game.act import ask, said
from client.game.mapdb import MapDB
from client.game.money import CURRENCIES, phrase
from client.game.outfit import (
ESSENTIALS,
bought,
missing,
parse_args,
put_on,
worn_items,
)
from client.game.walker import locate, walk
def exchange_in(s, mapdb, walk_fn, currency):
"""Every other coin in the purse EXCHANGEd into `currency` at the
nearest money-changer (bank.exchange_each: a sum under his minimum
is kept, his own line is the answer, #389); False when there is
none to exchange or no changer to reach."""
purse = money.purse(s, ask)
others = [c for c in CURRENCIES if c != currency and purse.get(c, 0) > 0]
if not others:
return False
changers = set(mapdb.rooms_tagged("exchange"))
if not travel.go(s, changers, "the money-changer", db=mapdb, walk=walk_fn):
s.echo("outfit: could not reach a money-changer")
return False
bank.exchange_each(s, ask, "outfit", [c.lower() for c in others], currency.lower())
return True
def afford(s, mapdb, walk_fn, essential):
"""The price in the purse, in the shop's coin: the shortfall fetched
from the nearest teller (shop.afford), else exchanged from the
purse's other coins. True when the purse covers it after."""
price, currency = essential["price"], essential["currency"]
if shop.afford(
s,
ask,
"outfit",
price,
currency,
db=mapdb,
walk=walk_fn,
retry="start ;outfit again",
):
return True
if exchange_in(s, mapdb, walk_fn, currency) and (
money.carried(s, currency, ask) >= price
):
return True
s.echo(
f"outfit: the purse still lacks {phrase(price, currency)} for the "
f"{essential['name']} — bring the coin and start ;outfit again"
)
return False
def outfit_one(s, mapdb, walk_fn, essential):
"""One essential bought and worn; True when it went on."""
room = essential["shop"]
if not travel.go(s, room, essential["shop_name"], db=mapdb, walk=walk_fn):
s.echo(f"outfit: could not reach {essential['shop_name']} — stopping")
return False
if not afford(s, mapdb, walk_fn, essential):
return False
if locate(mapdb, s.state) != room and not travel.go(
s, room, essential["shop_name"], db=mapdb, walk=walk_fn
):
s.echo(f"outfit: could not walk back to {essential['shop_name']} — stopping")
return False
answer = ask(s, essential["buy"])
if not bought(answer):
s.echo(f"outfit: {essential['buy']} answered {said(answer)!r} — stopping")
return False
answer = ask(s, essential["wear"])
s.waitrt()
if not put_on(answer):
s.echo(
f"outfit: bought the {essential['name']}, but {essential['wear']} "
f"answered {said(answer)!r} — it is in hand"
)
return False
s.echo(f"outfit: {said(answer)}")
return True
def run(s, words, mapdb, walk_fn=walk):
options = parse_args(words)
worn = worn_items(ask(s, "inventory"))
todo = missing(worn, ESSENTIALS)
if not todo:
names = ", ".join(essential["name"] for essential in ESSENTIALS)
s.echo(f"outfit: nothing missing — {names} already worn")
return
for essential in todo:
s.echo(
f"outfit: no {essential['name']} — {essential['shop_name']}, "
f"{phrase(essential['price'], essential['currency'])}"
)
if options["check"]:
return
start = locate(mapdb, s.state)
done = 0
for essential in todo:
if s.dead or not outfit_one(s, mapdb, walk_fn, essential):
break
done += 1
s.echo(f"outfit: {done} of {len(todo)} bought and worn")
if s.dead or not options["back"] or start is None:
return
if locate(mapdb, s.state) != start and not travel.go(
s, start, "where you started", db=mapdb, walk=walk_fn
):
s.echo("outfit: could not walk back — you are where the errand ended")
def main(s):
run(s, list(s.args or []), MapDB.load())