-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhugolib.h
4900 lines (4263 loc) · 155 KB
/
hugolib.h
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
!----------------------------------------------------------------------------
!
! Hugo Library v3.1.03.2 by Kent Tessman (c) 1995-2006
! for use with the Hugo Compiler
!
!----------------------------------------------------------------------------
#ifclear _HUGOLIB_H
#set _HUGOLIB_H
constant BANNER "Hugo v3.1 / Library 31032"
constant HUGO_VERSION "v3.1"
!----------------------------------------------------------------------------
! RESERVED PROPERTIES:
!----------------------------------------------------------------------------
!\ The first 6 are pre-defined by the compiler:
property name ! property 0: basic object name
property before $additive $complex ! pre-verb routines
property after $additive $complex ! post-verb routines
property noun ! noun(s) for referring to object
property adjective ! adjective(s) describing object
property article ! "a", "an", "some", etc.
\!
property nouns alias noun !
property adjectives alias adjective !
property preposition ! "in", "inside", "outside of", etc.
property prep alias preposition !
property pronoun "it" ! "he", "him", "his", "himself"
property pronouns alias pronoun ! (or equivalent)
property react_before ! to allow reaction by an object that
property react_after ! is not directly involved
property short_desc ! basic "X is here" description
property initial_desc ! same as above, before obj. is moved
property long_desc ! detailed description
property found_in ! in case of multiple parents
property type ! to identify the type of object
property size 10 ! for holding/inventory purposes
property capacity ! " " "
property holding ! " " "
property reach ! for limiting accessible objects
property list_contents ! to override normal listing routine
property in_scope ! actor(s) which can access an object
property parse_rank ! for matching similarly named objects
property exclude_from_all ! i.e., exclude from multi-obj. verbs
property door_to ! for handling "Enter <object>"
! The following are used only for room objects:
property n_to !
property ne_to !
property e_to !
property se_to !
property s_to ! If the player can move from one
property sw_to ! room to another in direction X,
property w_to ! X_to holds the object number of the
property nw_to ! second room.
property u_to !
property d_to !
property in_to !
property out_to !
property cant_go ! message if a move is invalid
property extra_scenery ! unimportant words/objects in desc.
property each_turn ! a routine called each turn
! The following are used only for non-room objects:
property key_object alias ne_to ! if lockable, what is the key?
property when_open alias e_to ! desc. for openable objects
property when_closed alias se_to ! " " " "
property ignore_response alias s_to ! for unfriendly characters
property order_response alias sw_to ! for giving orders to characters
property contains_desc alias w_to ! instead of "X contains...", etc.
property inv_desc alias nw_to ! for inventory listing only
property desc_detail alias u_to ! parenthetical detail (ObjectIs)
property misc ! miscellaneous use
!----------------------------------------------------------------------------
! RESERVED ATTRIBUTES:
!----------------------------------------------------------------------------
attribute known ! set once an object is known about
attribute moved ! " once an object is moved
attribute visited alias moved ! " once a room is visited
attribute static ! " when object cannot be taken
attribute plural ! " for plural objects
attribute living ! " if object is a character
attribute female ! " if character is female
attribute openable ! " if object can be opened
attribute open ! " if object is open
attribute lockable ! " if object can be locked
attribute locked ! " if object is locked
attribute unfriendly ! for characters
attribute light ! set if an object is/provides light
attribute readable ! " if object can be read
attribute switchable ! " if object can be turned on/off
attribute switchedon ! " if object is on
attribute active alias switchedon ! generally for fuses/daemons
attribute clothing ! set if object can be worn
attribute worn ! " if object is being worn
attribute mobile alias worn ! " if object may be moved around
attribute enterable ! " if object may be entered
attribute container ! " if things can be placed IN obj.
attribute platform ! " if things can be placed ON obj.
! ("container" and "platform" are
! mutually exclusive)
attribute hidden ! " if object isn't listed
attribute quiet ! " if container/platform is quiet
! (contents not initially listed)
attribute transparent ! " if object is not opaque
attribute workflag ! for library use
attribute already_listed alias workflag
attribute special ! for miscellaneous use
!----------------------------------------------------------------------------
! RESERVED GLOBALS:
!----------------------------------------------------------------------------
!\ The first 12 are pre-defined by the compiler:
global object ! direct object of a verb action
global xobject ! indirect object
global self ! self-referential object
global words ! total number of words
global player ! the player object
global actor ! player, or a char. (for scripts)
global location ! location of the player object
global verbroutine ! the verb routine
global endflag ! if non-false, run EndGame
global prompt ! for input line
global objects ! total number of objects
global system_status ! after certain operations
\!
global player_person = 2 ! 1=first, 2=second, 3=third
global MAX_SCORE ! total possible score
global FORMAT ! contains bitmap of format masks
global DEFAULT_FONT ! 0=monospaced normal text
global STATUSTYPE ! 0=none, 1=score/turns, 2=time
global UNDO_OFF ! overrides undo when true
global counter ! elapsed turns (or time, as desired)
global score ! accumulated score
global verbosity ! for room descriptions
global list_nest ! used by ListObjects
global light_source ! in location
global event_flag ! set when something happens
global speaking ! if the player is talking to a char.
global old_location ! whenever location changes
global last_object ! set by Perform to object global
global obstacle ! if something is stopping the player
global list_count ! number of unlisted objects
global need_newline ! true when newline should be printed
global override_indent ! true if no indent should be printed
global customerror_flag ! true after CustomError is called
array parser_data[5]
! parser_data elements:
constant PARSER_STATUS 0 ! PARSER_STATUS mask
constant LAST_PARSER_STATUS 1
constant BEST_PARSE_RANK 2 ! for matching similarly named objects
constant PARSE_RANK_TESTS 3 ! counter
constant LAST_SINGLE_OBJECT 4 ! for next-turn disambiguation
constant VERB_IS_XVERB 5 ! for this call to Perform()
#ifclear NO_SCRIPTS
constant MAX_SCRIPTS 16 !
constant MAX_SCRIPT_STEPS 32 !
global number_scripts ! for object scripts
array scriptdata[48] !
array setscript[1024] !
#endif
global MAX_RANK ! allow for up to 10 levels of
array ranking[10] ! player ranking (as a default)
global it_obj !
global them_obj !
global him_obj ! to reference objects via pronouns
global her_obj !
array replace_pronoun[4] !
constant MAX_WORDS 32 ! in a parsed input line
array oldword[MAX_WORDS] ! for "again" command
global general ! for general use
!----------------------------------------------------------------------------
! COLOR CONSTANTS AND GLOBALS
!----------------------------------------------------------------------------
enumerate ! colors 0 to 17
{
BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, WHITE,
DARK_GRAY, LIGHT_BLUE, LIGHT_GREEN, LIGHT_CYAN,
LIGHT_RED, LIGHT_MAGENTA, YELLOW, BRIGHT_WHITE,
DEF_FOREGROUND, DEF_BACKGROUND,
DEF_SL_FOREGROUND, DEF_SL_BACKGROUND,
MATCH_FOREGROUND
}
global TEXTCOLOR = DEF_FOREGROUND ! normal text color
global BGCOLOR = DEF_BACKGROUND ! normal background color
global SL_TEXTCOLOR = DEF_SL_FOREGROUND ! statusline text color
global SL_BGCOLOR = DEF_SL_BACKGROUND ! statusline background color
global INPUTCOLOR = MATCH_FOREGROUND ! input color
!----------------------------------------------------------------------------
! PARSER STATUS
!
! For parser_data[PARSER_STATUS]. Mask must be reset in Parse, as well as
! after Perform and ParseError.
!----------------------------------------------------------------------------
enumerate step *2
{
PARSER_RESET, ! 0, for reset
PARSER_ACTIVE = 1,
PRONOUNS_SET, ! if "it", etc. are used
FINDOBJECT_KNOWN, ! if FindObject() encounters a 'known' object
FINDOBJECT_NONLIVING, ! if a nonliving object is encountered
PERFORM_QUEUE ! one of multiple calls to Perform()
}
!----------------------------------------------------------------------------
! PRINTING FORMAT MASKS
!
! The following are bitmasks added/subtracted from the FORMAT global
! to affect text/list output. Combine formats using '+' or '|' as in:
!
! FORMAT = LIST_F | GROUPPLURALS_F | ...
!----------------------------------------------------------------------------
enumerate start = 1, step *2
{
LIST_F ! print itemized lists, not sentences
NORECURSE_F ! do not recurse object contents
NOINDENT_F ! do not indent listings
DESCFORM_F ! alternate room desc. formatting
GROUPPLURALS_F ! list plurals together where possible
NOPARENTHESES_F ! ignore printing by ObjectIs
! For internal (library) use:
INVENTORY_F ! list as player inventory
FIRSTCAPITAL_F ! capitalize first article
ISORARE_F ! print "is" or "are" at the start
ISORAREHERE_F ! print "is here" or "are here" last
USECHARNAMES_F ! before listing contents
TEMPLIST_F ! used if LIST_F must be overridden
}
global INVENTORY_MASK = 0 ! may be set by DoInventory
!----------------------------------------------------------------------------
! FONT STYLE BITMASKS
!
! Used with the Font routine to set or change the font style. Combine
! settings using '+' or '|', as in:
!
! Font(BOLD_ON | ITALIC_OFF | ...)
!----------------------------------------------------------------------------
enumerate start = 1, step *2
{
BOLD_ON, BOLD_OFF,
ITALIC_ON, ITALIC_OFF,
UNDERLINE_ON, UNDERLINE_OFF,
PROP_ON, PROP_OFF ! proportional printing
}
!----------------------------------------------------------------------------
! ADDITIONAL CONSTANTS (AND GLOBALS)
!----------------------------------------------------------------------------
constant UP_ARROW 11 ! special keystrokes
constant DOWN_ARROW 10
constant LEFT_ARROW 8
constant RIGHT_ARROW 21
constant ESCAPE_KEY 27
constant ENTER_KEY 13
constant MOUSE_CLICK 1
constant AND_WORD "and" ! for language translation
constant ARE_WORD "are"
constant HERE_WORD "here"
constant IN_WORD "in"
constant IS_WORD "is"
constant ON_WORD "on"
constant FILE_CHECK 4660 ! for readfile/writefile blocks
#if undefined INDENT_SIZE
constant INDENT_SIZE 2 ! for paragraph formatting
#endif
#if undefined AFTER_PERIOD
constant AFTER_PERIOD " " ! double-space after period
#endif
!----------------------------------------------------------------------------
! SYNONYMS, COMPOUNDS, AND REMOVALS
!----------------------------------------------------------------------------
synonym "and" for "~and"
synonym "except" for "~except"
synonym "but" for "~except"
synonym "all" for "~all"
synonym "everything" for "~all"
synonym "any" for "~any"
synonym "either" for "~any"
synonym "oops" for "~oops"
synonym "o" for "~oops"
synonym "mine" for "my"
synonym "myself" for "me"
#ifset NO_OBJLIB
synonym "herself" for "her"
synonym "himself" for "him"
synonym "themselves" for "them"
#endif
compound "mr", "."
compound "mrs", "."
compound "dr", "."
compound "st", "."
compound "off", "of"
compound "out", "of"
compound "on", "to"
compound "in", "to"
removal "a", "an", "the", "some", "of"
!----------------------------------------------------------------------------
object nothing "nothing" ! OBJECT 0: the great granddaddy
{}
enumerate start = 1, step 1
{
screenwidth, screenheight, ! built-in display object read-only
linelength, windowlines, ! properties
cursor_column, cursor_row,
hasgraphics, title_caption,
hasvideo, needs_repaint,
pointer_x, pointer_y
}
property statusline_height alias n_to ! library-specific display object
! properties
object display
{
statusline_height 1
}
!----------------------------------------------------------------------------
! EndGame(end_type)
! called by the engine via EndGame(end_type) when endflag is not false
! (endflag is cleared previous to calling); return false to terminate
!
! Default responses (in PrintEndGame): 1 = win, 2 = die, 0 = no response
routine EndGame(end_type)
{
PrintStatusLine ! update one last time
PrintEndGame(end_type) ! print appropriate ending message
#ifclear NO_VERBS
local r
:AskAgain
Message(&EndGame, 1) ! ask to RESTART, RESTORE, (UNDO), or QUIT
r = -1
while true
{
GetInput
select word[1]
case "restart", "r"
{
if restart
{
r = true
PrintStatusline
}
#ifclear NO_XVERBS
else
Message(&DoRestart, 2) ! failed
#endif
break
}
case "restore", "e"
{
#ifclear NO_XVERBS
r = Perform(&DoRestore)
#else
if restore
{
r = true
PrintStatusline
DescribePlace(location)
}
#endif
break
}
#ifclear NO_UNDO
case "undo", "u"
{
if not UNDO_OFF
{
if undo
{
r = true
PrintStatusLine
DescribePlace(location)
}
#ifclear NO_XVERBS
else
Message(&DoUndo, 1) ! failed
}
else
Message(&DoUndo, 1)
#else
}
#endif
break
}
#endif
case "quit", "q"
{
r = 0
break
}
Message(&EndGame, 2) ! ask again (more succinctly)
}
if r = -1: jump AskAgain
return r
#else ! i.e., #elseif set NO_VERBS
return 0;
#endif
}
routine PrintEndGame(end_type)
{
Font(BOLD_ON)
select end_type
case 1: print "\n*** YOU'VE WON THE GAME! ***"
case 2
{
if player_person = 2
print "\n*** YOU HAVE DIED ***"
else
print "\n*** "; CThe(player); \
MatchPlural(player, "has", "have"); \
" died! ***"
}
Font(BOLD_OFF)
PrintScore(true)
}
!----------------------------------------------------------------------------
routine PrintScore(end_of_game)
{
if STATUSTYPE = 1 and MAX_SCORE
{
if end_of_game: print ""
print "You ";
if not end_of_game
print "have ";
print "scored a total of ";
print number score; " out of "; number MAX_SCORE;
if ranking[0] ~= ""
{
print ", giving you the rank of ";
! A complicated formula, since only
! integer division is allowed:
!
print ranking[(score*100)/MAX_SCORE*MAX_RANK/100]
}
print "."
}
}
!----------------------------------------------------------------------------
! Parse is called by the engine without parameters after input but before
! any grammar matching; returning true signals the engine to reparse the
! existing input (in case it has been changed)
!
! The engine parser is responsible for splitting the input line into the
! word[] array, removing removals, replacing synonyms, and combining
! compounds.
!
! This Parse routine is then called to take care of:
! - picking out extra_scenery words
! - checking for an "again" command
! - rewording imperatives to "<Name>, <command>"
! - renaming pronouns to objects
! - changing "then <do something else>" into a new command
!
! Control then returns to the engine for grammar matching and, if that is
! successful, calling of the matched verb routine.
! NOTE: There are some snags with the object-based pronoun replacement
! system (such as, for example, requiring a specific object in grammar)
! so OLD_STYLE_PRONOUNS are still being used.
#set OLD_STYLE_PRONOUNS
#ifclear OLD_STYLE_PRONOUNS
! If OLD_STYLE_PRONOUNS is set, the Parse routine will actually change
! the input line by inserting the object name. This is a different
! approach using actual stand-in objects.
object it_object "it"
{
is known, hidden
nouns "it"
misc { return it_obj }
parse_rank 1000
found_in
{
local obj
obj = self.misc
if FindObject(obj, location)
return parent(obj)
else
return false
}
}
it_object him_object "him"
{
nouns "him"
misc { return him_obj }
}
it_object her_object "her"
{
nouns "her"
misc { return her_obj }
}
it_object them_object "them"
{
nouns "them"
misc { return them_obj }
}
#endif ! OLD_STYLE_PRONOUNS
routine Parse
{
local a
local reparse
local temp_verb, temp_obj, temp_xobj
ResetParse
list_nest = 0
event_flag = 0
if nothing ~= 0 ! best place to check this
print "[WARNING: Objects/classes defined before library]"
#ifset DEBUG
if debug_flags & D_PARSE_RANK
{
print "[parser_data[BEST_PARSE_RANK] = 0]"
}
#endif
#ifclear OLD_STYLE_PRONOUNS
! Only need to set up all attributes once, so that a given
! pronoun will satisfy any grammatical attribute requirements
if it_object is not 127
{
local i
for (i=0; i<128; i++)
{
it_object is i
him_object is i
her_object is i
them_object is i
}
}
#endif
if word[1] = "~oops"
return
! Allow the player object to override the parsing cycle completely
temp_verb = verbroutine
temp_obj = object
temp_xobj = xobject
verbroutine = &PreParse
object = nothing
xobject = nothing
if player.before
{
verbroutine = temp_verb
object = temp_obj
xobject = temp_xobj
parser_data[PARSER_STATUS] = 0
parser_data[LAST_PARSER_STATUS] = 0
return false
}
verbroutine = temp_verb
object = temp_obj
xobject = temp_xobj
! The following, devised by Jim Newland, checks to see if the player
! input refers to an unnecessary item of scenery (for example) which is
! nonetheless mentioned in the location description.
for (a=2; a<=words and word[a]~="" and word[a]~="then"; a++)
{
if Inlist(location, extra_scenery, word[a])
{
Message(&Parse, 1)
word[1] = "" ! force ParseError(0)
words = 0
customerror_flag = true
return true
}
}
if PreParse: reparse = true ! easily replaceable routine
! Last player-specified object
if object > 0 and object < objects and last_object ~= -1
AssignPronoun(object)
parser_data[LAST_PARSER_STATUS] = 0
! Must do this after AssignPronoun, and reset it to 0
! after both of Perform and ParseError:
parser_data[PARSER_STATUS] = PARSER_ACTIVE
#ifclear OLD_STYLE_PRONOUNS
move it_object to parent(it_obj)
move him_object to parent(him_obj)
move her_object to parent(her_obj)
move them_object to parent(them_obj)
#endif
! To repeat last command
if (word[1] = "again" or word[1] = "g") and word[2] = ""
{
for (a=1; a<=oldword[0]; a++)
word[a] = oldword[a]
words = oldword[0]
reparse = true
jump LeaveParse
}
local count
#ifset OLD_STYLE_PRONOUNS
local n, number_pronouns
#endif
for (count=2; count<=words and word[count]~=""; count++)
{
select word[count]
#ifset OLD_STYLE_PRONOUNS
! Rename pronouns to appropriate objects
case "it", "them", "him", "her"
{
select word[count]
case "it": a = it_obj
case "them": a = them_obj
case "him": a = him_obj
case "her": a = her_obj
if a = nothing
{
! "...be a little more specific"
ParseError(13)
words = 0
customerror_flag = true
return
}
! Avoid, e.g., "put it it something"
elseif word[count] ~= word[count+1]
{
! For her_obj, we can run into trouble, since
! it's both possessive and a pronoun, so only
! replace "her" where it's the last word:
if a ~= her_obj or
(a = her_obj and (count = 2 or count = words))
{
n = SetObjWord(count, a)
replace_pronoun[number_pronouns] = a
number_pronouns++
if n > 1
count = count + (n - 1)
parser_data[PARSER_STATUS] |= PRONOUNS_SET
reparse = true
}
}
}
#endif
! Allow for "then..." and "and then..."
case "then"
{
! end of this command
word[count] = "."
if word[count-1] = "~and"
DeleteWord(count-1)
reparse = true
break
}
}
#ifset OLD_STYLE_PRONOUNS
if number_pronouns = 2 and replace_pronoun[0] = replace_pronoun[1]
number_pronouns--
if number_pronouns > 0
{
PrintReplacedPronouns(number_pronouns)
}
#endif
! Reword imperatives given as "Tell Bob to do something" as "Bob, do
! something" so that the engine automatically reroutes them to SpeakTo
if word[1] = "tell", "order", "instruct", "ask", "command"
{
for (a=1; a<=words and word[a]~=""; a++)
{
if word[a] = "to"
{
!DeleteWord(a) ! "to"
word[a] = "~and"
DeleteWord(1) ! "tell", "order", etc.
reparse = true
break
}
}
}
#ifset USE_PLURAL_OBJECTS
if ParsePluralObjects: reparse = true
#endif
#ifset USE_CHECKHELD
ParseCheckHeld
#endif
! Store current command for future reference
local ow
for (a=1; a<=words and a<MAX_WORDS; a++)
{
if word[a] = "g", "again"
{
if word[a+1] = ""
a++
}
else
oldword[++ow] = word[a]
}
oldword[a] = ""
oldword[0] = ow
:LeaveParse
#ifset DEBUG
if debug_flags & D_PARSE
{
Font(BOLD_ON)
for (a=1; a<=words and word[a]~=""; a++)
print "["; word[a]; "] ";
print newline
if parse$ ~= ""
print "[parse$ = \""; parse$; "\"]"
Font(BOLD_OFF)
}
#endif
return reparse
}
routine ResetParse
{
customerror_flag = false
parser_data[BEST_PARSE_RANK] = 0 ! reset each parser cycle
parser_data[PARSE_RANK_TESTS] = 0
parser_data[VERB_IS_XVERB] = 0
}
routine PreParse ! to be replaced if needed
{}
routine CurrentCommandWords
{
if words = 0
return 0
local i
for (i=1; i<words; i++) ! not <=, because of the i++
{
if word[i] = ""
break
}
return i
}
routine SetObjWord(a, obj) ! inserts unique name of <obj> at word <a>
{
local i, n
if obj.#adjectives ! Allowing multiple adjectives...
{
for (i=1; i<=obj.#adjectives; i++)
{
if obj.adjective #i
{
if ++n > 1: InsertWord(a)
word[a] = obj.adjective #i
a++
}
if i = 15: break ! match MAX_MOBJ in heparse.c
}
}
if obj.#nouns ! ...and 1 noun (obj.noun #1)
{
for (i=1; i<=obj.#nouns; i++)
{
if obj.noun #i
{
if n: InsertWord(a)
word[a] = obj.noun #i
break
! Never executed:
!a++ : n++
}
}
}
return n
}
routine InsertWord(p, n) ! inserts <n> words at position <p>
{
local i
if n = 0: n = 1
if words+n >= MAX_WORDS: return
for (i=words+n; i>p; i--)
word[i] = word[i-n]
words = words + n
return n
}
routine DeleteWord(p, n) ! deletes <n> words at position <p>
{
local i
if n = 0: n = 1
if (words < n) or (p + n >= MAX_WORDS): return
for (i=p; i<=words-n; i++)
word[i] = word[i+n]
word[words] = ""
words = words - n
return n
}
routine VerbWord(which) ! returns word used as verb
{ ! in a typed command
select verbroutine
case &DoLook
{
if word[1] = "x"
return "examine"
}
case else
return word[1]
}
routine ObjWord(wd, obj) ! returns adjective or noun if <wd>
{ ! is either for <obj>
if InList(obj, noun, wd)
return noun
if InList(obj, adjective, wd)
return adjective
return false ! didn't match either
}
routine PrintReplacedPronouns(number_pronouns)
{
local count
Message(&Parse, 2) ! "Assuming you mean..."
for (count = 0; count < number_pronouns; count++)
{
if count > 0
{
if number_pronouns > 2
print ",";
if count = number_pronouns - 1
print " "; AND_WORD;
}
print " ";
if replace_pronoun[count].name = ""
The(nothing)
else
The(replace_pronoun[count])
}
if number_pronouns > 1
Message(&Parse, 3) ! ", respectively"
print ")"
}
!----------------------------------------------------------------------------
! ParseError(errornumber, object)
! prints an appropriate error message; if called by the engine, signals the
! engine to produce the default message by returning false
!
! (Note: If <errornumber> is equal to or greater than 100, CustomError
! is called instead. Replace CustomError for cases where custom error
! messages are desired for user parsing routines. Do not call CustomError
! directly. NewParseError can be replaced to modify only some
! messages.)
routine ParseError(errornumber, obj)
{
local r
r = NewParseError(errornumber, obj)
if r
{
parser_data[PARSER_STATUS] = PARSER_RESET
return r
}
if errornumber >= 100
{
CustomError(errornumber, obj)
word[1] = "" ! force ParseError(0)
words = 0
customerror_flag = true
parser_data[PARSER_STATUS] = PARSER_RESET
return true
}
if customerror_flag
{
customerror_flag = 0 ! CustomError already printed error
parser_data[PARSER_STATUS] = PARSER_RESET
return true
}
#ifset DEBUG
if debug_flags & D_PARSE
{
Font(BOLD_ON)
print "[ParseError("; number errornumber; ", "; obj.name; \
" ("; number obj; ")]"
Font(BOLD_OFF)
}
#endif
select errornumber
case 1
print CThe(player); \
! " can't use the word \""; \
MatchPlural(player, "doesn't", "don't"); \
" need to use the word \""; \
parse$; "\"."
case 3
print CThe(actor); " can't "; parse$; " multiple