mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
925 lines
52 KiB
HTML
925 lines
52 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>S/ot</title>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</head>
|
|
<body>
|
|
|
|
<!--Weave of 'S/at' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">★</a></li><li><a href="index.html">standard_rules Template Library</a></li><li><b>Actions Template</b></li></ul><p class="purpose">To try actions by people in the model world, processing the necessary rulebooks.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Summary</a></li><li><a href="#SP2">§2. Action Data</a></li><li><a href="#SP3">§3. Requirements Bitmap</a></li><li><a href="#SP4">§4. Try Action</a></li><li><a href="#SP5">§5. I6 Angle Brackets</a></li><li><a href="#SP6">§6. Conversion</a></li><li><a href="#SP7">§7. Implicit Take</a></li><li><a href="#SP8">§8. Look After Going</a></li><li><a href="#SP9">§9. Abbreviated Room Description</a></li><li><a href="#SP10">§10. Begin Action</a></li><li><a href="#SP11">§11. Action Primitive</a></li><li><a href="#SP12">§12. Internal Rule</a></li><li><a href="#SP13">§13. Type Safety</a></li><li><a href="#SP14">§14. Basic Visibility Rule</a></li><li><a href="#SP15">§15. Basic Accessibility Rule</a></li><li><a href="#SP16">§16. Carrying Requirements Rule</a></li><li><a href="#SP17">§17. Standard Implicit Taking Rule</a></li><li><a href="#SP18">§18. Requested Actions Require Persuasion Rule</a></li><li><a href="#SP19">§19. Carry Out Requested Actions Rule</a></li><li><a href="#SP20">§20. Generic Verb Subroutine</a></li><li><a href="#SP21">§21. Work Out Details Of Specific Action Rule</a></li><li><a href="#SP22">§22. Actions Bitmap</a></li><li><a href="#SP23">§23. Printing Actions</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Summary. </b>To review: an action is an impulse to do something by a person in the model
|
|
world. Commands such as DROP POTATO are converted into actions ("dropping
|
|
the Idaho potato"); sometimes they succeed, sometimes they fail. While
|
|
they run, the fairly complicated details are stored in a suite of I6
|
|
global variables such as <code class="display"><span class="extract">actor</span></code>, <code class="display"><span class="extract">noun</span></code>, <code class="display"><span class="extract">inp1</span></code>, and so on (see
|
|
"OrderOfPlay.i6t" for details); the running of an action is mainly a
|
|
matter of processing many rulebooks, chief among them they "action processing
|
|
rules".
|
|
</p>
|
|
|
|
<p class="inwebparagraph">In general, actions can come from five different sources:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(i) As a result of parsing the player's command: there are actually two ways
|
|
this can happen, one if the command calls for a single action, and another
|
|
if it calls for a whole run of them (like TAKE ALL). See the rules in
|
|
"OrderOfPlay.i6t".
|
|
</li><li>(ii) From an I7 "try" phrase, in which case <code class="display"><span class="extract">TryAction</span></code> is called.
|
|
</li><li>(iii) From an I6 angle-bracket-notation such as <code class="display"><span class="extract"><Wait></span></code>, though this is a
|
|
syntax which is deprecated now, and is never normally used in I7. The I6
|
|
compiler converts such a syntax into a call to the <code class="display"><span class="extract">R_Process</span></code> below.
|
|
</li><li>(iv) Through conversion of an existing action. For instance, "removing the
|
|
cup from the table" is converted in the Standard Rules to "taking the cup".
|
|
This is done via a routine called <code class="display"><span class="extract">GVS_Convert</span></code>.
|
|
</li><li>(v) When a request is successful, the "carry out requested actions" rule
|
|
turns the original action — a request by the player, such as is produced
|
|
by CHOPIN, PLAY POLONAISE — into an action by the person asked, such as
|
|
"Chopin playing the Polonaise".
|
|
</li></ul>
|
|
<p class="inwebparagraph">Certain exceptional cases can arise for other reasons:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(vi) Implicit taking actions are generated by the "carrying requirements rule"
|
|
when the actor tries something which requires him to be holding an item which
|
|
he can see, but is not currently holding.
|
|
</li><li>(vii) A partial but intentionally incomplete form of the "looking" action is
|
|
generated when describing the new location at the end of a "going" action.
|
|
</li></ul>
|
|
<p class="inwebparagraph">In every case except (vii), the action is carried out by <code class="display"><span class="extract">BeginAction</span></code>, the
|
|
single routine which unifies all of these approaches. Except the last one.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This segment of the template is divided into two: first, the I6 code needed
|
|
for (i) to (vii), the alternative ways for actions to begin; and secondly
|
|
the common machinery into which all actions eventually pass.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. Action Data. </b>This is perhaps a good place to document the <code class="display"><span class="extract">ActionData</span></code> array, a convenient
|
|
table of metadata about the actions. Since this is compiled by NI, the
|
|
following structure can't be modified here without making matching changes
|
|
in NI. <code class="display"><span class="extract">ActionData</span></code> is an I6 <code class="display"><span class="extract">table</span></code> containing a series of fixed-length
|
|
records, one on each action.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The routine <code class="display"><span class="extract">FindAction</span></code> locates the record in this table for a given
|
|
action number, returning its word offset within the table: the argument -1
|
|
means "the current action".
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Constant AD_ACTION = 0; ! The I6 action number (0 to 4095)</span>
|
|
<span class="plain">Constant AD_REQUIREMENTS = 1; ! Such as requiring light; a bitmap, see below</span>
|
|
<span class="plain">Constant AD_NOUN_KOV = 2; ! Kind of value of the first noun</span>
|
|
<span class="plain">Constant AD_SECOND_KOV = 3; ! Kind of value of the second noun</span>
|
|
<span class="plain">Constant AD_VARIABLES_CREATOR = 4; ! Routine to initialise variables owned</span>
|
|
<span class="plain">Constant AD_VARIABLES_ID = 5; ! Frame ID for variables owned by action</span>
|
|
|
|
<span class="plain">Constant AD_RECORD_SIZE = 6;</span>
|
|
|
|
<span class="plain">[ FindAction fa t;</span>
|
|
<span class="plain">if (fa == -1) fa = action;</span>
|
|
<span class="plain">t = 1;</span>
|
|
<span class="plain">while (t <= ActionData-->0) {</span>
|
|
<span class="plain">if (fa == ActionData-->t) return t;</span>
|
|
<span class="plain">t = t + AD_RECORD_SIZE;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ ActionNumberIndexed i;</span>
|
|
<span class="plain">if ((i>=0) && (i < AD_RECORDS)) return ActionData-->(i*AD_RECORD_SIZE + AD_ACTION + 1);</span>
|
|
<span class="plain">return 0;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. Requirements Bitmap. </b>As noted above, the <code class="display"><span class="extract">AD_REQUIREMENTS</span></code> field is a bitmap of flags for
|
|
various possible action requirements:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Constant TOUCH_NOUN_ABIT = $$00000001;</span>
|
|
<span class="plain">Constant TOUCH_SECOND_ABIT = $$00000010;</span>
|
|
<span class="plain">Constant LIGHT_ABIT = $$00000100;</span>
|
|
<span class="plain">Constant NEED_NOUN_ABIT = $$00001000;</span>
|
|
<span class="plain">Constant NEED_SECOND_ABIT = $$00010000;</span>
|
|
<span class="plain">Constant OUT_OF_WORLD_ABIT = $$00100000;</span>
|
|
<span class="plain">Constant CARRY_NOUN_ABIT = $$01000000;</span>
|
|
<span class="plain">Constant CARRY_SECOND_ABIT = $$10000000;</span>
|
|
|
|
<span class="plain">[ NeedToCarryNoun; return TestActionMask(CARRY_NOUN_ABIT); ];</span>
|
|
<span class="plain">[ NeedToCarrySecondNoun; return TestActionMask(CARRY_SECOND_ABIT); ];</span>
|
|
<span class="plain">[ NeedToTouchNoun; return TestActionMask(TOUCH_NOUN_ABIT); ];</span>
|
|
<span class="plain">[ NeedToTouchSecondNoun; return TestActionMask(TOUCH_SECOND_ABIT); ];</span>
|
|
<span class="plain">[ NeedLightForAction; return TestActionMask(LIGHT_ABIT); ];</span>
|
|
|
|
<span class="plain">[ TestActionMask match mask at;</span>
|
|
<span class="plain">at = FindAction(-1);</span>
|
|
<span class="plain">if (at == 0) rfalse;</span>
|
|
<span class="plain">mask = ActionData-->(at+AD_REQUIREMENTS);</span>
|
|
<span class="plain">if (mask & match) rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. Try Action. </b>This is method (ii) in the summary above.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ TryAction req by ac n s stora smeta tbits saved_command text_of_command;</span>
|
|
<span class="plain">if (stora) return STORED_ACTION_TY_New(ac, n, s, by, req, stora);</span>
|
|
<span class="plain">tbits = req & (16+32);</span>
|
|
<span class="plain">req = req & 1;</span>
|
|
<span class="plain">@push actor; @push act_requester; @push inp1; @push inp2;</span>
|
|
<span class="plain">@push parsed_number; smeta = meta;</span>
|
|
<span class="plain">actor = by; if (req) act_requester = player; else act_requester = 0;</span>
|
|
|
|
<span class="plain">by = FindAction(ac);</span>
|
|
<span class="plain">if (by) {</span>
|
|
<span class="plain">if (ActionData-->(by+AD_NOUN_KOV) == OBJECT_TY) inp1 = n;</span>
|
|
<span class="plain">else { inp1 = 1; parsed_number = n; }</span>
|
|
<span class="plain">if (ActionData-->(by+AD_SECOND_KOV) == OBJECT_TY) inp2 = s;</span>
|
|
<span class="plain">else { inp2 = 1; parsed_number = s; }</span>
|
|
<span class="plain">if (((ActionData-->(by+AD_NOUN_KOV) == UNDERSTANDING_TY) ||</span>
|
|
<span class="plain">(ActionData-->(by+AD_SECOND_KOV) == UNDERSTANDING_TY)) && (tbits)) {</span>
|
|
<span class="plain">saved_command = BlkValueCreate(TEXT_TY);</span>
|
|
<span class="plain">BlkValueCast(saved_command, SNIPPET_TY, players_command);</span>
|
|
<span class="plain">text_of_command = BlkValueCreate(TEXT_TY);</span>
|
|
<span class="plain">BlkValueCopy(text_of_command, parsed_number);</span>
|
|
<span class="plain">SetPlayersCommand(text_of_command);</span>
|
|
<span class="plain">if (tbits == 16) {</span>
|
|
<span class="plain">n = players_command; inp1 = 1; parsed_number = players_command;</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">s = players_command; inp2 = 1; parsed_number = players_command;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">BlkValueFree(text_of_command);</span>
|
|
<span class="plain">@push consult_from; @push consult_words;</span>
|
|
<span class="plain">consult_from = 1; consult_words = parsed_number - 100;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">BeginAction(ac, n, s, 0, true);</span>
|
|
|
|
<span class="plain">if (saved_command) {</span>
|
|
<span class="plain">@pull consult_words; @pull consult_from;</span>
|
|
<span class="plain">SetPlayersCommand(saved_command);</span>
|
|
<span class="plain">BlkValueFree(saved_command);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">meta = smeta; @pull parsed_number;</span>
|
|
<span class="plain">@pull inp2; @pull inp1; @pull act_requester; @pull actor;</span>
|
|
<span class="plain">TrackActions(true, smeta);</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. I6 Angle Brackets. </b>This is method (iii) in the summary above. The routine here has slightly
|
|
odd conventions and a curious name which would take too long to explain:
|
|
neither can be changed without amending the veneer code within the I6
|
|
compiler.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ R_Process a i j;</span>
|
|
<span class="plain">@push inp1; @push inp2;</span>
|
|
<span class="plain">inp1 = i; inp2 = j; BeginAction(a, i, j);</span>
|
|
<span class="plain">@pull inp2; @pull inp1;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. Conversion. </b>This is method (iv) in the summary above.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Global converted_action_outcome = -1;</span>
|
|
<span class="plain">[ GVS_Convert ac n s;</span>
|
|
<span class="plain">converted_action_outcome = BeginAction(ac, n, s);</span>
|
|
<span class="plain">if (converted_action_outcome == true) FollowRulebook(AFTER_RB, nothing, true );</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ ConvertToRequest X AN Y Z;</span>
|
|
<span class="plain">WORK_OUT_DETAILS_OF_SPECIFIC_R();</span>
|
|
<span class="plain">if (X == player) TryAction(false, X, AN, Y, Z);</span>
|
|
<span class="plain">else TryAction(true, X, AN, Y, Z);</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ ConvertToGoingWithPush i oldrm newrm infl;</span>
|
|
<span class="plain">i=noun;</span>
|
|
<span class="plain">if (IndirectlyContains(noun, actor) == false) { move i to actor; infl = true; }</span>
|
|
<span class="plain">move_pushing = i;</span>
|
|
<span class="plain">oldrm = LocationOf(noun);</span>
|
|
<span class="plain">BeginAction(##Go, second);</span>
|
|
<span class="plain">newrm = LocationOf(actor);</span>
|
|
<span class="plain">move_pushing = nothing; move i to newrm;</span>
|
|
<span class="plain">if (newrm ~= oldrm) {</span>
|
|
<span class="plain">if (IndirectlyContains(i, player)) TryAction(0, player, ##Look, 0, 0);</span>
|
|
<span class="plain">RulebookSucceeds();</span>
|
|
<span class="plain">} else RulebookFails();</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. Implicit Take. </b>This is method (vi) in the summary above.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ ImplicitTake obj ks;</span>
|
|
<span class="plain">if (actor == player) { STANDARD_IMPLICIT_TAKING_RM('A', obj); }</span>
|
|
<span class="plain">else {</span>
|
|
<span class="plain">if (TestVisibility(player, actor))</span>
|
|
<span class="plain">STANDARD_IMPLICIT_TAKING_RM('B', obj, actor);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">ClearParagraphing(3);</span>
|
|
<span class="plain">@push keep_silent; keep_silent = true;</span>
|
|
<span class="plain">@push say__p; @push say__pc; ClearParagraphing(4);</span>
|
|
<span class="plain">if (act_requester) TryAction(true, actor, ##Take, obj, nothing);</span>
|
|
<span class="plain">else TryAction(false, actor, ##Take, obj, nothing);</span>
|
|
<span class="plain">DivideParagraphPoint(); @pull say__pc; @pull say__p; AdjustParagraphPoint(); @pull keep_silent;</span>
|
|
<span class="plain">if (obj in actor) rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. Look After Going. </b>This is method (vii) in the summary above.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Fundamentally, room descriptions arise through looking actions, but they
|
|
are also printed after successful going actions, with a special form of
|
|
paragraph break (see "Printing.i6t" for an explanation of this). Room
|
|
descriptions through looking are always given in full, unless we have
|
|
SUPERBRIEF mode set.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ LookAfterGoing;</span>
|
|
<span class="plain">GoingLookBreak();</span>
|
|
<span class="plain">AbbreviatedRoomDescription();</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. Abbreviated Room Description. </b>This is used when we want a room description with the same abbreviation
|
|
conventions as after a going action, and we don't quite want a looking
|
|
action fully to take place. We nevertheless want to be sure that the
|
|
action variables for looking exist, and in particular, we want to set the
|
|
"room-describing action" variable to the action which was prevailing
|
|
when the room description was called for. We also set "abbreviated form
|
|
allowed" to "true": when the ordinary looking action is running, this
|
|
is "false".
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The actual description occurs during <code class="display"><span class="extract">LookSub</span></code>, which is the specific
|
|
action processing stage for the "looking" action: thus, we use the
|
|
check, carry out, after and report rules as if we were "looking", but
|
|
are unaffected by before or instead rules.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Uniquely, this pseudo-action does not use <code class="display"><span class="extract">BeginAction</span></code>: it works only
|
|
through the specific action processing rules, not the main action-processing
|
|
ones, though that is not easy to see from the code below because it is
|
|
hidden in the call to <code class="display"><span class="extract">LookSub</span></code>. The <code class="display"><span class="extract">-Sub</span></code> suffix is an I6 usage identifying
|
|
this as the routine to go along with the action <code class="display"><span class="extract">##Look</span></code>, and so it is,
|
|
but it looks nothing like the <code class="display"><span class="extract">LookSub</span></code> of the old I6 library. NI compiles
|
|
<code class="display"><span class="extract">-Sub</span></code> routines like so:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ LookSub; return GenericVerbSub(153,154,155); ];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">(with whatever rulebook numbers are appropriate). <code class="display"><span class="extract">GenericVerbSub</span></code> then
|
|
runs through the specific action processing stage.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ AbbreviatedRoomDescription prior_action pos frame_id;</span>
|
|
<span class="plain">prior_action = action;</span>
|
|
|
|
<span class="plain">action = ##Look;</span>
|
|
<span class="plain">pos = FindAction(##Look);</span>
|
|
<span class="plain">if ((pos) && (ActionData-->(pos+AD_VARIABLES_CREATOR))) {</span>
|
|
<span class="plain">frame_id = ActionData-->(pos+AD_VARIABLES_ID);</span>
|
|
<span class="plain">Mstack_Create_Frame(ActionData-->(pos+AD_VARIABLES_CREATOR), frame_id);</span>
|
|
<span class="plain">FollowRulebook(SETTING_ACTION_VARIABLES_RB);</span>
|
|
<span class="plain">(MStack-->MstVO(frame_id, 0)) = prior_action; ! "room-describing action"</span>
|
|
<span class="plain">(MStack-->MstVO(frame_id, 1)) = true; ! "abbreviated form allowed"</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">LookSub(); ! The I6 verb routine for "looking"</span>
|
|
<span class="plain">if (frame_id) Mstack_Destroy_Frame(ActionData-->(pos+AD_VARIABLES_CREATOR), frame_id);</span>
|
|
|
|
<span class="plain">action = prior_action;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. Begin Action. </b>We now begin the second half of the segment: the machinery which handles
|
|
all actions.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The significance of 4096 here is that this is how I6 distinguishes genuine
|
|
actions — numbered upwards in order of creation — from what I6 calls
|
|
"fake actions" — numbered upwards from 4096. Fake actions are hardly
|
|
used at all in I7, and certainly shouldn't get here, but it's possible
|
|
nonetheless using I6 angled-brackets, so... In other respects all we do
|
|
is to save details of whatever current action is happening onto the stack,
|
|
and then call <code class="display"><span class="extract">ActionPrimitive</span></code>.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ BeginAction a n s moi notrack rv;</span>
|
|
<span class="plain">ChronologyPoint();</span>
|
|
|
|
<span class="plain">@push action; @push noun; @push second; @push self; @push multiple_object_item;</span>
|
|
|
|
<span class="plain">action = a; noun = n; second = s; self = noun; multiple_object_item = moi;</span>
|
|
<span class="plain">if (action < 4096) rv = ActionPrimitive();</span>
|
|
|
|
<span class="plain">@pull multiple_object_item; @pull self; @pull second; @pull noun; @pull action;</span>
|
|
|
|
<span class="plain">if (notrack == false) TrackActions(true, meta);</span>
|
|
<span class="plain">return rv;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. Action Primitive. </b>This is somewhat different from the I6 library counterpart which gives it
|
|
its name, but the idea is the same. It has no arguments at all: everything
|
|
it needs to know is now stored in global variables. The routine looks long,
|
|
but really contains little: it's all just book-keeping, printing debugging
|
|
information if ACTIONS is in force, etc., with all of the actual work
|
|
delegated to the action processing rulebook.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We use a rather sneaky device to handle out-of-world actions, those for
|
|
which the <code class="display"><span class="extract">meta</span></code> flag is set: we make it look to the system as if the
|
|
"action processing rulebook" is being followed, so that all its variables
|
|
are created and placed in scope, but at the crucial moment we descend to
|
|
the specific action processing rules directly instead of processing the
|
|
main rulebook. This is what short-circuits out of world actions and
|
|
protects them from before and instead rules: see the Standard Rules for
|
|
more discussion of this.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ ActionPrimitive rv p1 p2 p3 p4 p5 frame_id;</span>
|
|
<span class="plain">MStack_CreateRBVars(ACTION_PROCESSING_RB);</span>
|
|
|
|
<span class="plain">if ((keep_silent == false) && (multiflag == false)) DivideParagraphPoint();</span>
|
|
<span class="plain">reason_the_action_failed = 0;</span>
|
|
|
|
<span class="plain">frame_id = -1;</span>
|
|
<span class="plain">p1 = FindAction(action);</span>
|
|
<span class="plain">if ((p1) && (ActionData-->(p1+AD_VARIABLES_CREATOR))) {</span>
|
|
<span class="plain">frame_id = ActionData-->(p1+AD_VARIABLES_ID);</span>
|
|
<span class="plain">Mstack_Create_Frame(ActionData-->(p1+AD_VARIABLES_CREATOR), frame_id);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (ActionVariablesNotTypeSafe()) {</span>
|
|
<span class="plain">if (actor ~= player) { ACTION_PROCESSING_INTERNAL_RM('K'); new_line; }</span>
|
|
<span class="plain">if (frame_id ~= -1)</span>
|
|
<span class="plain">Mstack_Destroy_Frame(ActionData-->(p1+AD_VARIABLES_CREATOR), frame_id);</span>
|
|
<span class="plain">MStack_DestroyRBVars(ACTION_PROCESSING_RB);</span>
|
|
<span class="plain">return;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">FollowRulebook(SETTING_ACTION_VARIABLES_RB);</span>
|
|
|
|
<span class="plain">#IFDEF DEBUG;</span>
|
|
<span class="plain">if ((trace_actions) && (FindAction(-1))) {</span>
|
|
<span class="plain">print "["; p1=actor; p2=act_requester; p3=action; p4=noun; p5=second;</span>
|
|
<span class="plain">DB_Action(p1,p2,p3,p4,p5);</span>
|
|
<span class="plain">print "]^"; ClearParagraphing(5);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">++debug_rule_nesting;</span>
|
|
<span class="plain">#ENDIF;</span>
|
|
<span class="plain">TrackActions(false, meta);</span>
|
|
<span class="plain">if ((meta) && (actor ~= player)) {</span>
|
|
<span class="plain">ACTION_PROCESSING_INTERNAL_RM('A', actor); new_line; rv = RS_FAILS; }</span>
|
|
<span class="plain">else if (meta) { DESCEND_TO_SPECIFIC_ACTION_R(); rv = RulebookOutcome(); }</span>
|
|
<span class="plain">else { FollowRulebook(ACTION_PROCESSING_RB); rv = RulebookOutcome(); }</span>
|
|
<span class="plain">#IFDEF DEBUG;</span>
|
|
<span class="plain">--debug_rule_nesting;</span>
|
|
<span class="plain">if ((trace_actions) && (FindAction(-1))) {</span>
|
|
<span class="plain">print "["; DB_Action(p1,p2,p3,p4,p5); print " - ";</span>
|
|
<span class="plain">switch (rv) {</span>
|
|
<span class="plain">RS_SUCCEEDS: print "succeeded";</span>
|
|
<span class="plain">RS_FAILS: print "failed";</span>
|
|
<span class="plain">#IFNDEF MEMORY_ECONOMY;</span>
|
|
<span class="plain">if (reason_the_action_failed)</span>
|
|
<span class="plain">print " the ",</span>
|
|
<span class="plain">(RulePrintingRule) reason_the_action_failed;</span>
|
|
<span class="plain">#ENDIF;</span>
|
|
<span class="plain">default: print "ended without result";</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">print "]^"; say__p = 1;</span>
|
|
<span class="plain">SetRulebookOutcome(rv); ! In case disturbed by printing activities</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">#ENDIF;</span>
|
|
<span class="plain">if (rv == RS_SUCCEEDS) UpdateActionBitmap();</span>
|
|
<span class="plain">if (frame_id ~= -1) {</span>
|
|
<span class="plain">p1 = FindAction(action);</span>
|
|
<span class="plain">Mstack_Destroy_Frame(ActionData-->(p1+AD_VARIABLES_CREATOR), frame_id);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">MStack_DestroyRBVars(ACTION_PROCESSING_RB);</span>
|
|
<span class="plain">if ((keep_silent == false) && (multiflag == false)) DivideParagraphPoint();</span>
|
|
<span class="plain">if (rv == RS_SUCCEEDS) rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. Internal Rule. </b>Provided only as a hook on which to hang responses.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ ACTION_PROCESSING_INTERNAL_R; ];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. Type Safety. </b>Some basic action requirements have to be met before we can go any further:
|
|
if they aren't, then it isn't type-safe even to run the action processing
|
|
rulebook.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(i) For an out of world action, we set the <code class="display"><span class="extract">meta</span></code> flag. Otherwise:
|
|
</li><li>(ii) If either the noun or second noun is a topic, then this is an action
|
|
arising from parsing (such actions do not arise through the "try" phrase,
|
|
unless by stored actions in which case this has all happened before and
|
|
doesn't need to be done again) — the parser places details of which words
|
|
make up the topic in the I6 global variables <code class="display"><span class="extract">consult_words</span></code> and <code class="display"><span class="extract">consult_from</span></code>.
|
|
We convert them to a valid I7 snippet value.
|
|
</li><li>(iii) If either the first or second noun is supposed to be an object but
|
|
seems here to be a value, or vice versa, we stop with a parser error. (This
|
|
should be fairly difficult to provoke: NI's type-checking will make it
|
|
difficult to arrange without I6 subterfuges.)
|
|
</li><li>(iv) If either the first or second noun is supposed to be an object and
|
|
required to exist, yet is missing, we use the "supplying a missing noun"
|
|
or "supplying a missing second noun" activities to fill the void.
|
|
</li></ul>
|
|
<p class="inwebparagraph">We return <code class="display"><span class="extract">true</span></code> if type safety is violated, <code class="display"><span class="extract">false</span></code> if all is well.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ ActionVariablesNotTypeSafe mask noun_kova second_kova at;</span>
|
|
<span class="plain">at = FindAction(-1); if (at == 0) rfalse; ! For any I6-defined actions</span>
|
|
|
|
<span class="plain">noun_kova = ActionData-->(at+AD_NOUN_KOV);</span>
|
|
<span class="plain">second_kova = ActionData-->(at+AD_SECOND_KOV);</span>
|
|
|
|
<span class="plain">!print "at = ", at, " nst = ", noun_kova, "^";</span>
|
|
<span class="plain">!print "consult_from = ", consult_from, " consult_words = ", consult_from, "^";</span>
|
|
<span class="plain">!print "inp1 = ", inp1, " noun = ", noun, "^";</span>
|
|
<span class="plain">!print "inp2 = ", inp2, " second = ", second, "^";</span>
|
|
<span class="plain">!print "sst = ", second_kova, "^";</span>
|
|
|
|
<span class="plain">if (noun_kova == SNIPPET_TY or UNDERSTANDING_TY) {</span>
|
|
<span class="plain">if (inp1 ~= 1) { inp2 = inp1; second = noun; }</span>
|
|
<span class="plain">parsed_number = 100*consult_from + consult_words;</span>
|
|
<span class="plain">inp1 = 1; noun = nothing; ! noun = parsed_number;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (second_kova == SNIPPET_TY or UNDERSTANDING_TY) {</span>
|
|
<span class="plain">parsed_number = 100*consult_from + consult_words;</span>
|
|
<span class="plain">inp2 = 1; second = nothing; ! second = parsed_number;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">mask = ActionData-->(at+AD_REQUIREMENTS);</span>
|
|
<span class="plain">if (mask & OUT_OF_WORLD_ABIT) { meta = 1; rfalse; }</span>
|
|
<span class="plain">meta = 0;</span>
|
|
|
|
<span class="plain">if (inp1 == 1) {</span>
|
|
<span class="plain">if (noun_kova == OBJECT_TY) {</span>
|
|
<span class="plain">if (actor == player) { ACTION_PROCESSING_INTERNAL_RM('B'); new_line; }</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">if (noun_kova ~= OBJECT_TY) {</span>
|
|
<span class="plain">if (actor == player) { ACTION_PROCESSING_INTERNAL_RM('C'); new_line; }</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if ((mask & NEED_NOUN_ABIT) && (noun == nothing)) {</span>
|
|
<span class="plain">@push act_requester; act_requester = nothing;</span>
|
|
<span class="plain">CarryOutActivity(SUPPLYING_A_MISSING_NOUN_ACT);</span>
|
|
<span class="plain">@pull act_requester;</span>
|
|
<span class="plain">if (noun == nothing) {</span>
|
|
<span class="plain">if (say__p) rtrue;</span>
|
|
<span class="plain">if (actor == player) { ACTION_PROCESSING_INTERNAL_RM('D'); new_line; }</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (((mask & NEED_NOUN_ABIT) == 0) && (noun ~= nothing)) {</span>
|
|
<span class="plain">if (actor == player) { ACTION_PROCESSING_INTERNAL_RM('E'); new_line; }</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">if (inp2 == 1) {</span>
|
|
<span class="plain">if (second_kova == OBJECT_TY) {</span>
|
|
<span class="plain">if (actor == player) { ACTION_PROCESSING_INTERNAL_RM('F'); new_line; }</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">if (second_kova ~= OBJECT_TY) {</span>
|
|
<span class="plain">if (actor == player) { ACTION_PROCESSING_INTERNAL_RM('G'); new_line; }</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if ((mask & NEED_SECOND_ABIT) && (second == nothing)) {</span>
|
|
<span class="plain">@push act_requester; act_requester = nothing;</span>
|
|
<span class="plain">CarryOutActivity(SUPPLYING_A_MISSING_SECOND_ACT);</span>
|
|
<span class="plain">@pull act_requester;</span>
|
|
<span class="plain">if (second == nothing) {</span>
|
|
<span class="plain">if (say__p) rtrue;</span>
|
|
<span class="plain">if (actor == player) { ACTION_PROCESSING_INTERNAL_RM('H'); new_line; }</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (((mask & NEED_SECOND_ABIT) == 0) && (second ~= nothing)) {</span>
|
|
<span class="plain">if (actor == player) { ACTION_PROCESSING_INTERNAL_RM('I'); new_line; }</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. Basic Visibility Rule. </b>This is one of the I6 primitive rules in the action processing rulebook:
|
|
see the account in the Standard Rules for details.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Note that this rule only blocks the player from acting in darkness: this is
|
|
because light is only reckoned from the player's perspective in any case,
|
|
so that it would be unfair to apply the rule to any other person.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ BASIC_VISIBILITY_R;</span>
|
|
<span class="plain">if (act_requester) rfalse;</span>
|
|
<span class="plain">if ((NeedLightForAction()) &&</span>
|
|
<span class="plain">(actor == player) &&</span>
|
|
<span class="plain">(FollowRulebook(VISIBLE_RB)) &&</span>
|
|
<span class="plain">(RulebookSucceeded())) {</span>
|
|
<span class="plain">BeginActivity(REFUSAL_TO_ACT_IN_DARK_ACT);</span>
|
|
<span class="plain">if (ForActivity(REFUSAL_TO_ACT_IN_DARK_ACT)==false) {</span>
|
|
<span class="plain">BASIC_VISIBILITY_RM('A'); new_line;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">EndActivity(REFUSAL_TO_ACT_IN_DARK_ACT);</span>
|
|
<span class="plain">reason_the_action_failed = BASIC_VISIBILITY_R;</span>
|
|
<span class="plain">RulebookFails();</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. Basic Accessibility Rule. </b>This is one of the I6 primitive rules in the action processing rulebook:
|
|
see the account in the Standard Rules for details.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ BASIC_ACCESSIBILITY_R mask at;</span>
|
|
<span class="plain">if (act_requester) rfalse;</span>
|
|
<span class="plain">at = FindAction(-1);</span>
|
|
<span class="plain">if (at == 0) rfalse;</span>
|
|
<span class="plain">mask = ActionData-->(at+AD_REQUIREMENTS);</span>
|
|
|
|
<span class="plain">if ((mask & TOUCH_NOUN_ABIT) && noun && (inp1 ~= 1)) {</span>
|
|
<span class="plain">if (noun ofclass K3_direction) {</span>
|
|
<span class="plain">RulebookFails();</span>
|
|
<span class="plain">reason_the_action_failed = BASIC_ACCESSIBILITY_R;</span>
|
|
<span class="plain">if (actor~=player) rtrue;</span>
|
|
<span class="plain">BASIC_ACCESSIBILITY_RM('A'); new_line;</span>
|
|
<span class="plain">RulebookFails();</span>
|
|
<span class="plain">reason_the_action_failed = BASIC_ACCESSIBILITY_R;</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (ObjectIsUntouchable(noun, (actor~=player), actor)) {</span>
|
|
<span class="plain">RulebookFails();</span>
|
|
<span class="plain">reason_the_action_failed = BASIC_ACCESSIBILITY_R;</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">if ((mask & TOUCH_SECOND_ABIT) && second && (inp2 ~= 1)) {</span>
|
|
<span class="plain">if (second ofclass K3_direction) {</span>
|
|
<span class="plain">RulebookFails();</span>
|
|
<span class="plain">reason_the_action_failed = BASIC_ACCESSIBILITY_R;</span>
|
|
<span class="plain">if (actor~=player) rtrue;</span>
|
|
<span class="plain">BASIC_ACCESSIBILITY_RM('A'); new_line;</span>
|
|
<span class="plain">RulebookFails();</span>
|
|
<span class="plain">reason_the_action_failed = BASIC_ACCESSIBILITY_R;</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (ObjectIsUntouchable(second, (actor~=player), actor)) {</span>
|
|
<span class="plain">RulebookFails();</span>
|
|
<span class="plain">reason_the_action_failed = BASIC_ACCESSIBILITY_R;</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. Carrying Requirements Rule. </b>This is one of the I6 primitive rules in the action processing rulebook:
|
|
see the account in the Standard Rules for details.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ CARRYING_REQUIREMENTS_R mask at;</span>
|
|
|
|
<span class="plain">at = FindAction(-1);</span>
|
|
<span class="plain">if (at == 0) rfalse;</span>
|
|
<span class="plain">mask = ActionData-->(at+AD_REQUIREMENTS);</span>
|
|
|
|
<span class="plain">if ((mask & TOUCH_NOUN_ABIT) && noun && (inp1 ~= 1)) {</span>
|
|
<span class="plain">if ((mask & CARRY_NOUN_ABIT) && (noun notin actor)) {</span>
|
|
<span class="plain">CarryOutActivity(IMPLICITLY_TAKING_ACT, noun);</span>
|
|
<span class="plain">if (noun notin actor) {</span>
|
|
<span class="plain">RulebookFails();</span>
|
|
<span class="plain">reason_the_action_failed = CARRYING_REQUIREMENTS_R;</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">if ((mask & TOUCH_SECOND_ABIT) && second && (inp2 ~= 1)) {</span>
|
|
<span class="plain">if ((mask & CARRY_SECOND_ABIT) && (second notin actor)) {</span>
|
|
<span class="plain">CarryOutActivity(IMPLICITLY_TAKING_ACT, second);</span>
|
|
<span class="plain">if (second notin actor) {</span>
|
|
<span class="plain">RulebookFails();</span>
|
|
<span class="plain">reason_the_action_failed = CARRYING_REQUIREMENTS_R;</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. Standard Implicit Taking Rule. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ STANDARD_IMPLICIT_TAKING_R;</span>
|
|
<span class="plain">ImplicitTake(parameter_value);</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. Requested Actions Require Persuasion Rule. </b>This is one of the I6 primitive rules in the action processing rulebook:
|
|
see the account in the Standard Rules for details.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ REQUESTED_ACTIONS_REQUIRE_R rv;</span>
|
|
<span class="plain">if ((actor ~= player) && (act_requester)) {</span>
|
|
<span class="plain">@push say__p;</span>
|
|
<span class="plain">say__p = 0;</span>
|
|
<span class="plain">rv = FollowRulebook(PERSUADE_RB);</span>
|
|
<span class="plain">if (RulebookSucceeded() == false) {</span>
|
|
<span class="plain">if ((deadflag == false) && (say__p == false)) {</span>
|
|
<span class="plain">REQUESTED_ACTIONS_REQUIRE_RM('A', actor);</span>
|
|
<span class="plain">new_line;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">ActRulebookFails(rv); rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">@pull say__p;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§19. Carry Out Requested Actions Rule. </b>This is one of the I6 primitive rules in the action processing rulebook:
|
|
see the account in the Standard Rules for details.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ CARRY_OUT_REQUESTED_ACTIONS_R rv;</span>
|
|
<span class="plain">if ((actor ~= player) && (act_requester)) {</span>
|
|
<span class="plain">@push act_requester; act_requester = nothing;</span>
|
|
<span class="plain">rv = BeginAction(action, noun, second);</span>
|
|
<span class="plain">if (((meta) || (rv == false)) && (deadflag == false)) {</span>
|
|
<span class="plain">if (FollowRulebook(UNSUCCESSFUL_ATTEMPT_RB) == false) {</span>
|
|
<span class="plain">CARRY_OUT_REQUESTED_ACTIONS_RM('A', actor); new_line;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">@pull act_requester;</span>
|
|
<span class="plain">FollowRulebook(AFTER_RB);</span>
|
|
<span class="plain">ActRulebookSucceeds();</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§20. Generic Verb Subroutine. </b>In I6, actions are carried out by routines with names like <code class="display"><span class="extract">TakeSub</span></code>,
|
|
consisting of <code class="display"><span class="extract">-Sub</span></code> tacked on to the action name <code class="display"><span class="extract">Take</span></code>. <code class="display"><span class="extract">Sub</span></code> stands for
|
|
"subroutine": this is all a convention going back to Inform 1, which was
|
|
in 1993 practically an assembler. In the I6 code generated by I7, every
|
|
<code class="display"><span class="extract">-Sub</span></code> routine corresponding to an I7 action consists only of a call to
|
|
<code class="display"><span class="extract">GenericVerbSub</span></code> which specifies the three rulebooks it owns: its check,
|
|
carry out and report rulebooks.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Array Details_of_Specific_Action-->5;</span>
|
|
|
|
<span class="plain">[ GenericVerbSub ch co re vis rv;</span>
|
|
<span class="plain">@push converted_action_outcome;</span>
|
|
<span class="plain">converted_action_outcome = -1;</span>
|
|
|
|
<span class="plain">Details_of_Specific_Action-->0 = true;</span>
|
|
<span class="plain">if (meta) Details_of_Specific_Action-->0 = false;</span>
|
|
<span class="plain">Details_of_Specific_Action-->1 = keep_silent;</span>
|
|
<span class="plain">Details_of_Specific_Action-->2 = ch; ! Check rules for the action</span>
|
|
<span class="plain">Details_of_Specific_Action-->3 = co; ! Carry out rules for the action</span>
|
|
<span class="plain">Details_of_Specific_Action-->4 = re; ! Report rules for the action</span>
|
|
|
|
<span class="plain">FollowRulebook(SPECIFIC_ACTION_PROCESSING_RB, 0, true);</span>
|
|
<span class="plain">if ((RulebookFailed()) && (converted_action_outcome == 1)) ActRulebookSucceeds();</span>
|
|
|
|
<span class="plain">@pull converted_action_outcome;</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21"></a><b>§21. Work Out Details Of Specific Action Rule. </b>This is one of the I6 primitive rules in the specific action processing
|
|
rulebook, and it's basically a trick to allow information known to the
|
|
<code class="display"><span class="extract">GenericVerbSub</span></code> routine to be passed down as rulebook variables for the
|
|
specific action-processing rules — in effect allowing us to pass not
|
|
one but five parameters to the rulebook: the out-of-world and silence
|
|
flags, plus the three specific rulebooks needed to process the action.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ WORK_OUT_DETAILS_OF_SPECIFIC_R;</span>
|
|
<span class="plain">MStack-->MstVO(SPECIFIC_ACTION_PROCESSING_RB, 0) = Details_of_Specific_Action-->0;</span>
|
|
<span class="plain">MStack-->MstVO(SPECIFIC_ACTION_PROCESSING_RB, 1) = Details_of_Specific_Action-->1;</span>
|
|
<span class="plain">MStack-->MstVO(SPECIFIC_ACTION_PROCESSING_RB, 2) = Details_of_Specific_Action-->2;</span>
|
|
<span class="plain">MStack-->MstVO(SPECIFIC_ACTION_PROCESSING_RB, 3) = Details_of_Specific_Action-->3;</span>
|
|
<span class="plain">MStack-->MstVO(SPECIFIC_ACTION_PROCESSING_RB, 4) = Details_of_Specific_Action-->4;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22"></a><b>§22. Actions Bitmap. </b>This is a fairly large bitmap recording which actions have succeeded thus
|
|
far on which nouns. It was to some extent an early attempt at implementing
|
|
a past-tense system; I'm not at all sure it was successful, since it is
|
|
hindered by certain restrictions — it only records action/noun combinations,
|
|
for instance, and the notion of "success" is a vexed one for actions
|
|
anyway. There is a clearly defined meaning, but it doesn't always correspond
|
|
to what the user might expect, which is unfortunate.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ TestActionBitmap obj act i j k bitmap;</span>
|
|
<span class="plain">if (obj == nothing) bitmap = ActionHappened;</span>
|
|
<span class="plain">else {</span>
|
|
<span class="plain">if (~~(obj provides action_bitmap)) rfalse;</span>
|
|
<span class="plain">bitmap = obj.&action_bitmap;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (act == -1) return (((bitmap->0) & 1) ~= 0);</span>
|
|
<span class="plain">for (i=0, k=2: i<ActionCount: i++) {</span>
|
|
<span class="plain">if (act == ActionCoding-->i) {</span>
|
|
<span class="plain">return (((bitmap->j) & k) ~= 0);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">k = k*2; if (k == 256) { k = 1; j++; }</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ UpdateActionBitmap;</span>
|
|
<span class="plain">SetActionBitmap(noun, action);</span>
|
|
<span class="plain">if (action == ##Go) SetActionBitmap(location, ##Enter);</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ SetActionBitmap obj act i j k bitmap;</span>
|
|
<span class="plain">for (i=0, k=2: i<ActionCount: i++) {</span>
|
|
<span class="plain">if (act == ActionCoding-->i) {</span>
|
|
<span class="plain">if (obj provides action_bitmap) {</span>
|
|
<span class="plain">bitmap = obj.&action_bitmap;</span>
|
|
<span class="plain">bitmap->0 = (bitmap->0) | 1;</span>
|
|
<span class="plain">bitmap->j = (bitmap->j) | k;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">ActionHappened->0 = (ActionHappened->0) | 1;</span>
|
|
<span class="plain">ActionHappened->j = (ActionHappened->j) | k;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">k = k*2; if (k == 256) { k = 1; j++; }</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23"></a><b>§23. Printing Actions. </b>This is really for debugging purposes, but also provides us with a way to
|
|
print a stored action, for instance, or to print an action name value.
|
|
(For instance, printing an action name might result in "taking"; printing
|
|
a whole action might produce "Henry taking the grapefruit".)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ SayActionName act; DB_Action(0, 0, act, 0, 0, 2); ];</span>
|
|
|
|
<span class="plain">[ DA_Name n; if (n ofclass K3_direction) print (name) n; else print (the) n; ];</span>
|
|
<span class="plain">[ DA_Topic x a b c d i cf cw;</span>
|
|
<span class="plain">cw = x%100; cf = x/100;</span>
|
|
<span class="plain">print "~";</span>
|
|
<span class="plain">for (a=cf:d<cw:d++,a++) {</span>
|
|
<span class="plain">wn = a; b = WordAddress(a); c = WordLength(a);</span>
|
|
<span class="plain">for (i=b:i<b+c:i++) {</span>
|
|
<span class="plain">print (char) 0->i;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (d<cw-1) print " ";</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">print "~";</span>
|
|
<span class="plain">];</span>
|
|
<span class="plain">[ DB_Action ac acr act n s for_say t at l j v c clc;</span>
|
|
<span class="plain">if ((for_say == 0) && (debug_rule_nesting > 0))</span>
|
|
<span class="plain">print "(", debug_rule_nesting, ") ";</span>
|
|
<span class="plain">if ((ac ~= player) && (for_say ~= 2)) {</span>
|
|
<span class="plain">if (acr) print "asking ", (the) ac, " to try ";</span>
|
|
<span class="plain">else print (the) ac, " ";</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">DB_Action_Details(act, n, s, for_say);</span>
|
|
<span class="plain">if ((keep_silent) && (for_say == 0)) print " - silently";</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="S-ot.html">Back to 'Output Template'</a></li><li><a href="S-at2.html">Continue with 'Activities Template'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</body>
|
|
</html>
|
|
|