-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathch11.html
More file actions
221 lines (185 loc) · 9.34 KB
/
ch11.html
File metadata and controls
221 lines (185 loc) · 9.34 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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<style type="text/css">
td, th { border: 1px solid #c3c3c3; padding: 0 3px 0 3px; }
table { border-collapse: collapse; }
img { max-width: 100%; }
</style>
<meta name="generator" content="ReText 7.2.3">
<title>ch11</title>
<style type="text/css">
</style>
</head>
<body>
<p><a href="ch10.html">Previous</a> <a href="index.html">Index</a> <a href="ch12.html">Next</a></p>
<hr>
<h1>11 - The Script task</h1>
<h4>Table of Contents</h4>
<ul>
<li><a href="#11.1">11.1 Types of Axbasic script</a></li>
<li><a href="#11.2">11.2 Scripts that require a task</a></li>
<li><a href="#11.3">11.3 Using a main loop</a></li>
<li><a href="#11.4">11.4 Main loops without flags</a></li>
<li><a href="#11.5">11.5 Main loop examples</a></li>
</ul>
<hr>
<h2><a name="11.1">11.1 Types of Axbasic script</a></h2>
<p><a href="ch02.html#2.6">Section 2.6</a> describes how to run an Axbasic script using the Script task. In case you've forgotten, to run <em>Hunt the Wumpus!</em> you might type the client command</p>
<pre><code> ;runscript wumpus
</code></pre>
<p>But to run that script as a task, you would type</p>
<pre><code> ;runscripttask wumpus
</code></pre>
<p>As you start writing your own Axbasic scripts, you'll soon discover that there are basically three types of script:</p>
<ol>
<li>A short script designed to be run once, from beginning to end<ul>
<li>This includes most of the scripts we've examined so far</li>
</ul>
</li>
<li>A longer script designed to be one run once, from beginning to end<ul>
<li>We saw a good example in <a href="ch04.html#4.7">Section 4.7</a></li>
<li>Because it was a longer script, it was broken up into stages, with a pause between the stages</li>
<li>You can put the pauses (almost) anywhere you like</li>
</ul>
</li>
<li>A script which is designed to run indefinitely<ul>
<li>We haven't examined a script like this, yet</li>
<li>Because the script runs for a long time, we need <em>a lot</em> of pauses and they need to occur <em>regularly</em></li>
<li>Without pauses, the rest of the Axmud code won't be able to do anything</li>
</ul>
</li>
</ol>
<h2><a name="11.2">11.2 Scripts that require a task</a></h2>
<p>Axbasic provides a number of ways to pause a script. You've already seen PAUSE, of course.</p>
<pre><code> SEND "turn on radio"
PAUSE 30
SEND "turn off radio"
</code></pre>
<p>You've also seen WAITTRIG, which creates a temporary trigger and waits for it to fire, before resuming execution of the script.</p>
<pre><code> ! Wait for the door to open, before moving
SEND "press button"
WAITTRIG "open"
MOVE "east"
</code></pre>
<p>Any Axbasic script that includes any kind of pause <em>must be run as a task</em>.</p>
<p>If you forget, the PAUSE and WAITTRIG statements are ignored. Axmud won't wait 30 seconds until turning off the radio, nor will it create a temporary trigger.</p>
<p>If your script uses any kind of pause, you can avoid nasty surprises by including an OPTION NEEDTASK statement anywhere in the script.</p>
<pre><code> OPTION NEEDTASK
SEND "turn on radio"
PAUSE 30
SEND "turn off radio"
END
</code></pre>
<p>If you try to run that script without a task, you'll see an error message like this:</p>
<pre><code> AXBASIC: ERROR: Script cannot run without parent task, line 1
</code></pre>
<h2><a name="11.3">11.3 Using a main loop</a></h2>
<p>You can create a script that runs indefinitely by using DO...LOOP.</p>
<pre><code> ! This script runs indefinitely
LET exit_flag = 0
DO
PRINT "Hello world!"
UNTIL exit_flag = 1
END
</code></pre>
<p>A <em>flag</em> is a variable that is on or off, true or false, up or down, light or dark. How you implement a flag is, of course, entirely up to you, but a very common practice is to use the number 1 for <em>true</em> or <em>on</em>, and the number 0 for <em>false</em> or <em>off</em>.</p>
<p>In the example above, the script runs indefinitely because <strong>exit_flag</strong> is always set to 0. When we're ready to terminate the script, we can just change the flag's value to 1.</p>
<pre><code> ! This script terminates an hour after the session started
LET exit_flag = 0
DO
PRINT Timestamp ()
IF Timestamp () > 3600 THEN
LET exit_flag = 1
END IF
UNTIL exit_flag = 1
END
</code></pre>
<p>Now, any script that runs indefinitely needs some pauses. The most convenient place to put one is near the end of the loop.</p>
<pre><code> ! This script terminates an hour after the session started
! The time limit is only checked once per second
OPTION NEEDTASK
LET exit_flag = 0
DO
PRINT Timestamp ()
IF Timestamp () > 3600 THEN
LET exit_flag = 1
END IF
PAUSE 1
UNTIL exit_flag = 1
END
</code></pre>
<p>That's convenient in a lot of situations, but in other situations you'll want a shorter pause, perhaps the shortest possible pause. (If your script doesn't include any pauses at all, eventually the Script task will pause anyway. It's better if the script decides for itself when the pause should occur.)</p>
<p>The shortest possible pause is currently 0.1 seconds. Axmud aims to call the Script task ten times a second, but if some serious computation is taking place, the delay might be longer.</p>
<p>If you want your loop to take place as often as possible - up to 10 times a second, in other words - you can use a BREAK statement.</p>
<pre><code> ! This script terminates an hour after the session started
! The time limit is checked after the shortest possible pause
LET exit_flag = 0
DO
PRINT Timestamp ()
IF Timestamp () > 3600 THEN
LET exit_flag = 1
END IF
BREAK
UNTIL exit_flag = 1
END
</code></pre>
<p>What we have now is called a <em>main loop</em>. After setting up variables, the loop runs once, then execution pauses briefly, then the loop runs again, pauses again, and so on and so on.</p>
<p>Sometimes, your main loop will decide that it's necessary to take some kind of action. If so, it will call an Axbasic function or a subroutine. Most of the time, however, no action will be necessary and the main loop won't call anything.</p>
<h2><a name="11.4">11.4 Main loops without flags</a></h2>
<p>An alternative to using <strong>exit_flag</strong> is, of course, to use EXIT DO. You'll remember from <a href="ch07.html">Section 7</a> that a DO...UNTIL 0 loop runs indefinitely.</p>
<pre><code> ! This script terminates an hour after the session started
! The time limit is checked after the shortest possible pause
DO
PRINT Timestamp ()
IF Timestamp () > 3600 THEN
EXIT DO
END IF
BREAK
UNTIL 0
END
</code></pre>
<p>This script terminates <em>in the middle of a loop</em>. If that's not what you want, it would be better to use an <strong>exit_flag</strong> rather than EXIT DO.</p>
<p>In long scripts, a human reader is much more likely to see the first line of a loop than the last one. In most cases, it's better to write a main loop using WHILE 1...LOOP than by using DO...UNTIL 0.</p>
<h2><a name="11.5">11.5 Main loop examples</a></h2>
<p>Here's a practical example of a main loop.</p>
<p>The PEEK statement is used to retrieve some value stored in Axmud's memory. We'll be talking a lot more about PEEK in later Sections, but for now, all you need to know is that the following line retrieves your character's health points and stores them in the variable <strong>hp</strong>.</p>
<p>(This script won't work if there is no current character profile, or if the Status task hasn't able to store your character's health points in that profile. Note, also, that the capital P in Points must not be typed as a lower-case p.)</p>
<pre><code> PEEK hp = char.current.healthPoints
</code></pre>
<p>Now we can write an Axbasic script that keeps an eye on your character's health. If it falls too low, the character is made to go to sleep, and later made to wake up again.</p>
<pre><code> ! Automatic sleep machine
! First set up the variables
LET exit_flag = 0
! Let's assume the character is awake right now
! Use 1 for awake, 0 for asleep
LET awake_flag = 1
! Now start the main loop
DO
! Check current health points
PEEK hp = char.current.healthPoints
! If awake and health points are low, go to sleep
! If asleep and health points are high, wake up
! Otherwise, do nothing until the next main loop
IF hp < 20 AND awake_flag = 1 THEN
SEND "sleep"
LET awake_flag = 0
ELSE IF hp > 80 AND awake_flag = 0 THEN
SEND "wake up"
LET awake_flag = 1
END IF
BREAK
UNTIL exit_flag = 1
END
</code></pre>
<p>This simple script assumes your character's maximum health points are 100. That's not going to work at many MUDs, but happily Axmud is abloe to detect the maximum health points, too.</p>
<pre><code>PEEK maxhp = char.current.maxHealthPoints
</code></pre>
<p>If you know the current and maximum values, then it would be quite simple to convert them into a percentage, with 100 meaning "perfectly healthy" and 0 meaning "dead".</p>
<pre><code>LET percent = Int ( (hp / maxhp) * 100 )
</code></pre>
<hr>
<p><a href="ch10.html">Previous</a> <a href="index.html">Index</a> <a href="ch12.html">Next</a></p>
</body>
</html>