1local function onevent(ev, ...)
2	local vv, r
3	if stead.api_atleast(1, 6, 3) then
4		vv, r = stead.call(game, ev, ...);
5		if r == false then
6			return vv, false
7		end
8		if vv == false then
9			return nil, false
10		end
11		return vv
12	end
13end
14
15local go = function (self, where, back, noenter, noexit, nodsc)
16	local was = self.where;
17	local need_scene = false;
18	local ret
19
20	if not stead.in_walk_call then
21		ret = function(rc) stead.in_walk_call = false return nil end
22	else
23		ret = function(rc) return rc end
24	end
25
26	stead.in_walk_call = true
27
28	if where == nil then
29		return nil, ret(false)
30	end
31
32	if not isRoom(stead.ref(where)) then
33		error ("Trying to go nowhere: "..where);
34	end
35
36	if not isRoom(stead.ref(self.where)) then
37		error ("Trying to go from nowhere: "..self.where);
38	end
39
40	if stead.in_entered_call or stead.in_onexit_call then
41		error ("Do not use walk from left/entered action! Use exit/enter action instead:" .. self.where);
42	end
43
44	local v, r, jump;
45
46	if not isVroom(stead.ref(where)) and not stead.in_exit_call and not noexit then
47		stead.in_exit_call = true -- to break recurse
48		v,r = stead.call(stead.ref(self.where), 'exit', stead.ref(where));
49		stead.in_exit_call = nil
50		if r == false or (stead.api_atleast(1, 3, 0) and v == false and r == nil) then
51			return v, ret(r)
52		end
53		if stead.api_atleast(2, 4, 0) then
54			jump = stead.rawget(_G, 'PLAYER_MOVED')
55		else
56			jump = (self.where ~= was)
57		end
58		if jump then
59			where = stead.deref(self.where) -- jump
60		end
61	end
62
63	local res = v;
64	v = nil;
65
66	if not isVroom(stead.ref(where)) then
67		self.where = stead.deref(where);
68	end
69
70	if not jump and not noenter then
71		v, r = stead.call(stead.ref(where), 'enter', stead.ref(was));
72		if r == false or (stead.api_atleast(1, 3, 0) and v == false and r == nil) then
73			self.where = was;
74			return stead.par(stead.scene_delim, res, v), ret(r)
75		end
76	end
77
78	if stead.api_atleast(2, 4, 0) then
79		need_scene = not stead.rawget(_G, 'PLAYER_MOVED');
80	else
81		need_scene = not (stead.ref(where) ~= stead.ref(self.where))
82	end
83
84	res = stead.par(stead.scene_delim, res, v);
85
86	if not back then
87		stead.ref(where).__from__ = stead.deref(was);
88	end
89
90	ret()
91
92	stead.rawset(_G, 'PLAYER_MOVED', true)
93	if need_scene and not nodsc then
94		stead.need_scene()
95	end
96
97	if not stead.in_walk_call  then
98		local to = self.where
99		if not noexit then
100			self.where = was
101			stead.in_onexit_call = true
102			v = stead.call(stead.ref(was), 'left', stead.ref(to));
103			stead.in_onexit_call = false
104			res = stead.par(stead.scene_delim, res, v);
105		end
106
107		self.where = stead.deref(to)
108
109		if not noenter then
110			stead.in_entered_call = true
111			v = stead.call(stead.ref(to), 'entered', stead.ref(was));
112			stead.in_entered_call = false
113			res = stead.par(stead.scene_delim, res, v);
114		end
115
116		if stead.tonum(stead.ref(to).__visited) then
117			stead.ref(to).__visited = stead.ref(to).__visited + 1;
118		elseif stead.here().__visited == nil then
119			stead.ref(to).__visited = 1
120		end
121		if not stead.api_atleast(1, 6, 3) and isDialog(stead.ref(to)) then
122			stead.dialog_rescan(stead.ref(to))
123		end
124	end
125	return res;
126end
127
128stead.player_go = function(self, where) -- cmd iface
129	local w = stead.ref(self.where).way:srch(where);
130	if not w then
131		return nil,false
132	end
133	return self:walk(w);
134end
135
136stead.player_walk = function(self, where, ...) -- real work
137	local v, r, vv;
138	vv, r = onevent('onwalk', stead.ref(where), ...);
139	if vv == false then
140		return
141	end
142	if r == false then
143		return vv
144	end
145	v, r = stead.go(self, where, ...);
146	if stead.type(vv) == 'string' then
147		v = stead.par(stead.space_delim, vv, v);
148	end
149	return v, r;
150end
151
152stead.player_back = function(self) -- deprecated
153	error ("Do not use stead.me():back(). It's deprecated.", 2)
154end
155
156stead.back = function(w)
157	if isDialog(stead.here()) and not isDialog(stead.from()) then
158		return stead.walkout(w);
159	end
160	return stead.walkback(w);
161end
162back = stead.back
163
164stead.walkback = function(w)
165	if isRoom(stead.ref(w)) then
166		return stead.me():walk(w, true);
167	end
168	return stead.me():walk(stead.from(), true);
169end
170walkback = stead.walkback
171
172stead.walk = function(what, back, noenter, noexit, nodsc, ...)
173	return stead.me():walk(what, back, noenter, noexit, nodsc, ...);
174end
175walk = stead.walk
176
177stead.walkin = function(what)
178	return stead.me():walk(what, false, false, true);
179end
180walkin = stead.walkin
181
182stead.walkout = function(what)
183	if isRoom(stead.ref(what)) then
184		return stead.me():walk(what, true, true, false, true);
185	end
186	return stead.me():walk(stead.from(), true, true, false, true);
187end
188walkout = stead.walkout
189
190function visited(w)
191	if not w then w = stead.here() end
192	w = stead.ref(w)
193	if w == nil then
194		return nil;
195	end
196	if not isRoom(w) then
197		error ("Wrong parameter to visited.", 2);
198	end
199	return w.__visited
200end
201stead.visited = visited
202
203function visits(w)
204	local n = stead.visited(w)
205	if not n then n = 0 end
206	return n
207end
208stead.visits = visits
209
210iface.fmt = function(self, cmd, st, moved, r, av, objs, pv) -- st -- changed state (main win), move -- loc changed
211	local l, vv
212	if st then
213		av = txtem(av);
214		pv = txtem(pv);
215--		if not PLAYER_MOVED then
216			r = txtem(r)
217--		end
218		if isForcedsc(stead.here()) or stead.rawget(_G, 'NEED_SCENE') then
219			l = stead.here():scene();
220		end
221	end
222	if moved then
223		vv = stead.fmt(stead.cat(stead.par(stead.scene_delim, r, l, av, objs, pv), '^'));
224	else
225		vv = stead.fmt(stead.cat(stead.par(stead.scene_delim, l, r, av, objs, pv), '^'));
226	end
227	return vv
228end
229
230stead.go = function(...)
231	local r,v = go(...)
232	if stead.type(r) == 'string' and stead.cctx() then
233		stead.pr (r)
234	end
235--	if stead.in_life_call then
236--		ACTION_TEXT = nil
237--	end
238	if r == nil and v == nil then
239		if stead.cctx() then
240			stead.cctx().action = true
241		else
242			r = true
243		end
244	end
245	return r,v
246end
247
248iface.cmd = stead.hook(iface.cmd, function(f, ...)
249	stead.rawset(_G, 'NEED_SCENE', nil)
250	return f(...)
251end)
252
253player  = stead.inherit(player, function(v)
254	v.look = function(s)
255		if not stead.started then
256			game:start()
257		end
258		if game._time == 0 then
259			return stead.walk(stead.here(), false, false, true);
260		end
261		stead.need_scene()
262		if stead.api_atleast(1, 3, 5) then
263			return true -- force action
264		end
265	end
266	return v
267end)
268
269pl = player(pl) -- reinit
270-- vim:ts=4
271