CE4  Changes On Branch imbastardizer

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch imbastardizer Excluding Merge-Ins

This is equivalent to a diff from f6133f9d57 to d0869948be

2018-04-05
21:10
Update documentation. check-in: f96fc54fb0 user: programandala.net tags: vimclair_basic
2017-09-12
23:22
Fix/improve some comments. Leaf check-in: d0869948be user: programandala.net tags: imbastardizer
2017-09-11
20:52
Improve README. check-in: 050e6c0946 user: programandala.net tags: imbastardizer
2016-12-14
01:38
Start the conversion from Sinclair BASIC (written with the Vimclair BASIC preprocessor) to GW-BASIC (written with the Imbastardizer preprocessor). check-in: a9bfb9d222 user: programandala.net tags: imbastardizer
2016-07-30
22:52
Convert Markdown docs to Asciidoctor. check-in: f6133f9d57 user: programandala.net tags: vimclair_basic
2016-06-20
12:16
Fix label; update version numbering. check-in: 6da9bc0c7e user: programandala.net tags: vimclair_basic

Deleted COPYING.txt.

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
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted FILES.adoc.

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
= Ficheros de CE4
:author: Marcos Cruz (programandala.net)
:revdate: 2016-07-31

- `src/ce4.vbas`  =  juego.
- `src/ce4.data_maker.vbas` = crea en el disco duro los ficheros con
  las matrices de datos.
- `src/ce4.data_packer.vbas` = empaqueta las matrices grabadas por
  `ce4.data_maker.vbas` en un solo fichero BASIC, que al inicio de
  cada partida será cargado por `ce4.vbas` con el comando `MERGE`.
- `src/ce4.common.vbas` =  contiene todas las directivas `#vim`
  necesarias para transformar las fuentes; es incluido por el resto de
  las fuentes vbas.
- `src/ce4.common.enum.vim` = función `Enum()` creada Vim necesaria
  para `ce4.commo.vbas`.
- `src/cl1st3rd.z80s` = rutina gráfica.
- `src/fn_dpeek.z80s` = función de BASIC.
- `src/fn_dpoke.z80s` =  función de BASIC.
- `src/fn_instr1.z80s` =  función de BASIC.
- `src/fn_termn.z80s` =  función de BASIC.
- `src/fn_term.z80s` =  función de BASIC.
- `src/fn_trunc.z80s` =  función de BASIC.
- `src/udg.z80s` = gráficos de usuario, con los caracteres españoles
- `src/ce4.bin.symbols.vbas` = 
- `src/ce4.bin.symbols.z80s` = 
- `src/ce4.bin.z80s` = 
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































Deleted INSTALL.adoc.

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
= Instalación de CE4
:author: Marcos Cruz (programandala.net)
:revdate: 2016-07-31

Para instalar una nueva versión de CE4 en el disco duro de ZX Spectrum +3
hay que hacer lo siguiente:

Primero, en el directorio del programa hacer:

    make

Eso creará la imagen de disquete `bin/ce4.dsk`.

Segundo, arrancar el programa:

El ejecutable `bin/ce4.sh` arranca el emulador Fuse con la configuración
necesaria para arrancar un ZX Spectrum +3e desde el disquete `bin/ce4.dsk`, y
con el disco duro `bin/ce4.hdf` conectado (el disco duro ya tiene las dos
particiones hechas y, en una de ellas, los gráficos del juego).

Tras arrancar desde disquete (con la opción «Loader» del menú del sistema)
aparecerá el menú propio de CE4. Elige la opción de instalación (con la tecla
«i»). El proceso es automático salvo el último paso, que se explica en
pantalla y es muy sencillo.

Lo único que aún no es automático es el cálculo de la dirección del fichero
`c:ce4.bin` (`bin/ce4.bin.tap`), que aún hay que fijar a mano en
`src/ce4.bin.z80s`, pero esto solo es necesario hacerlo cuando se modifica
algún fichero en ensamblador.


== Instrucciones antiguas, obsoletas

Estas instrucciones explican cómo se compilan los ficheros fuente de CE4
(ficheros VBAS, VIM y Z80S) en ficheros TAP, y cómo con ellos se actualiza el
disco duro (fichero HDF) del juego.

Este procedimiento se usa durante el desarrollo del juego, y 
provisional. Más adelante la instalación será más
automática.

Cómo reinstalar

1. Entra en el directorio del programa (por ejemplo, `cd ce4`)
2. Ejecuta el comando `make` para actualizar los ficheros TAP.
3. Arranca CE4 con `./bin/ce4.sh`. Verás la lista de particiones de
   disco duro asignadas y un menú de arranque.
4. Elige la opción «Cargar manualmente desde cinta».
5. Elige el fichero `bin/ce4.data_packer.tap`en el emulador, cárgalo
   desde BASIC con `LOAD ""`. Cuando termine te pedirá que borres sus
   dos líneas y lo grabes con otro nombre. Ignora estas instrucciones
   porque en esta primera ocasión lo único que queremos es que el
   programa se grabe en el disco duro, cosa que hace nada más arrancar
   (de hecho, puedes cortarlo mientras funciona).
6. Elige el fichero `bin/ce4.data_maker.tap`en el emulador, cárgalo
   desde BASIC con `LOAD ""`. Después de hacer su trabajo (crear las
   matrices de datos en disco) te pedirá continuar para cargar el
   programa empaquetador que has cargado antes.  El empaquetador, al
   terminar su trabajo, te pedirá, como dijimos, que borres sus líneas
   y grabes el programa vacío con `SAVE "C:DATA.BAS"`.
7. Elige el fichero `bin/ce4.tap`en el emulador, cárgalo desde BASIC
   con `LOAD ""`. El juego se grabará a sí mismo en el disco duro y
   después se pondrá en marcha.

Los gráficos están en la partición asignada a la unidad G y de momento no
necesitan ser actualizados.

Cuándo reinstalar:

- El paso 7 debe repetirse cuando se modifique el programa principal.
- El paso 6 debe repetirse cuando se modifiquen los datos del programa
  en `ce4.data_maker.vbas`.
- Los pasos 5 y 6 deben repetirse cuando se modifique la estructura de
  los datos del programa (por ejemplo, el tamaño de las matrices).
- Todo el proceso debe repetirse cuando se modifique o añada alguna
  fuente en Z80, a o se modifique el programa `ce4.common.vbas`.

== Cambios en este documento

2015-02-22:: Primera versión, instalación manual.
2015-02-26:: Segunda versión, instalación casi totalmente automatizada.

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































Added LICENSE.txt.









>
>
>
>
1
2
3
4
You may do whatever you want with this work, so long as you retain
the copyright/authorship/acknowledgment/credit notice(s) and this
license in all redistributed copies and derived works.  There is no
warranty.

Changes to Makefile.

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
# Makefile
#
# This file is part of CE4
# (http://programandala.net/es.programa.ce4.vimclair_basic.html)

################################################################
# History

# 2015-02-22: Start.
#
# 2015-02-24: A DSK file is made with all the TAPs created from Vimclar BASIC
# sources, in order to save time copying the BASIC programs to C:. Now the boot
# disk menu has an option to copy them from B: to C:.
#
# 2015-02-26: Only one DSK file is needed. It is created with make and have all
# the files required to install, update or run the program.
#
# 2015-03-01: Improved conversion of the symbols file from Z80 to Vimclair
# BASIC.
# 
# 2015-03-04: New: <ce4.text_maker.vbas>, <ce4.fn_txtfile.vbas>.
#
# 2016-06-09: Improve comment.

################################################################
# Requirements

# The following programs must be installed in your system:

# bas2tap 2.4 (by Martijn van der Heide of ThunderWare Research Center)
# http://www.worldofspectrum.org/ (in the utilities section)
# ftp://ftp.worldofspectrum.org/pub/sinclair/tools/pc

# Pasmo (by Julián Albo)
# http://pasmo.speccy.org/

# tap2dsk from Taptools (by John Elliott)
# http://www.seasip.info/ZX/unix.html

# Vimclair BASIC (by Marcos Cruz)
# http://programandala.net/en.program.vimclair_basic.html

# zmakebas (by Russell Marks)
# Version 1.2 is a package of Debian, Raspbian, Ubuntu and probably other distros.
# Version 1.1 can be found here:
# http://web.archive.org/web/20080525213938/http://rus.members.beeb.net/zmakebas.html
# ftp://ftp.ibiblio.org/pub/Linux/system/emulators/zx/
#
# Version by Antonio Villena (with fixed DEF FN):
# http://sourceforge.net/p/emuscriptoria/code/HEAD/tree/desprot/ZMakeBas.c

################################################################
# Config

VPATH = ./:src:bin:bin/tmp
MAKEFLAGS = --no-print-directory

.ONESHELL :




.PHONY : all
all : dsk


# XXX TODO check if this was needed:
# .PHONY : clean
clean :
	-rm -f bin/tmp/*




################################################################
# Z80 code

z80_sources=$(wildcard src/*.z80s)

# The Z80 code:
ce4.bin.tap : $(z80_sources)
	cd src ; \
	pasmo -v --tap --name CE4.BIN --public \
		ce4.bin.z80s \
		../bin/tmp/ce4.bin.tap \
		ce4.bin.symbols.z80s

# The Vimclair BASIC substitutions related to the Z80 symbols:
ce4.bin.symbols.vbas : $(z80_sources)
	@make ce4.bin.tap
	cd src ; \
		sed \
		--expression='/^fn_\S\+_size\s\+EQU/s|^.\+||' \
		--expression='/^[fc]\S\+/s/^\(\S\+\)\s\+EQU \([0-9A-F]\+\)H/#vim %substitute@\\<\1\\>@eval[65536-z80_size+str2nr("\2",16)]eval@gi/' \
	  --expression='/^z80.\+/s/\(^\S\+\)\s\+EQU \([0-9A-F]\+\)H/#vim %substitute@\\<\1\\>@\\=str2nr("\2",16)@gi/' \
		ce4.bin.symbols.z80s > ce4.bin.symbols.vbas

#	  --expression='/^zzz.\+/s/\(^\S\+\)\s\+EQU \([0-9A-F]\+\)H/#vim %substitute@\\<\1\\>@\\=str2nr("\2",16)@gi/' \
# XXX TODO -- use relatives addresses for Z80 symbols, calculated with: routine+65536-z80_length

################################################################
# Graphics

# User defined graphics are included in <CE4.BIN>, the file used by the main program,
# but also as a separate file <CE4.UDG>, used by the tool programs.

ce4.udg.tap : udg.z80s
	cd src ; \
	pasmo -v --tap --name CE4.UDG --public \
		udg.z80s \
		../bin/tmp/ce4.udg.tap

# XXX TODO alternative with bin2code

################################################################

# BASIC code

# The common requisite for most other Vimclair BASIC sources:
ce4.common.vbas : \
		ce4.bin.symbols.vbas \
		ce4.common.enum.vim
	@make ce4.bin.symbols.vbas

# The boot program:
ce4.disk.tap : ce4.disk.vbas
	cd src ; \
	vbas2tap ce4.disk.vbas ; \
	mv ce4.disk.tap ../bin/tmp/

# The development boot menu:
ce4.menu.tap : ce4.menu.vbas
	cd src ; \
	vbas2tap ce4.menu.vbas ; \
	mv ce4.menu.tap ../bin/tmp/

# The game:
ce4.tap : \
		ce4.vbas \
		ce4.common.vbas \
		ce4.fn_txtfile.vbas
	cd src ; \
	vbas2tap ce4.vbas ; \
	mv ce4.tap ../bin/tmp/

# The tool that creates the data files in the hard disk:
ce4.data_maker.tap : \
		ce4.data_maker.vbas \
		ce4.common.vbas
	cd src ; \
	vbas2tap ce4.data_maker.vbas ; \
	mv ce4.data_maker.tap ../bin/tmp/

# The tool that packs the data files into one BASIC file:
ce4.data_packer.tap : \
		ce4.data_packer.vbas \
		ce4.common.vbas
	cd src ; \
	vbas2tap ce4.data_packer.vbas ; \
	mv ce4.data_packer.tap ../bin/tmp/

# The tool that creates the texts file in the hard disk:
ce4.text_maker.tap : \
		ce4.text_maker.vbas \
		ce4.common.vbas \
		ce4.fn_txtfile.vbas
	cd src ; \
	vbas2tap ce4.text_maker.vbas ; \
	mv ce4.text_maker.tap ../bin/tmp/

################################################################
# The main DSK

tapes= \
	ce4.disk.tap \
	ce4.menu.tap \
	ce4.tap \
	ce4.bin.tap \
	ce4.udg.tap \
	ce4.data_maker.tap \
	ce4.data_packer.tap \
	ce4.text_maker.tap

.PHONY : dsk
dsk : ce4.dsk


ce4.dsk : $(tapes)
	cd bin/tmp ; \
	cat $(tapes) > ce4.tap_for_dsk.tap ; \
	tap2dsk -180 -cpmonly -label CE4 ce4.tap_for_dsk.tap ../ce4.dsk ; \
	rm ce4.tap_for_dsk.tap



################################################################




# tar.gz and zip archives



# XXX TODO

# PACKED_FILES = \
# 	deffnder/src/*.z80s \
# 	deffnder/bin/*.tap \
# 	deffnder/README.txt

# .PHONY : tar.gz
# tar.gz :
# 	@make deffnder.tar.gz

# deffnder.tar.gz : \
# 	src/*.z80s \
# 	bin/*.tap \
# 	README.txt
# 	tar \
# 	--create \
# 	--gzip \
# 	--file deffnder.tar.gz \
# 	--dereference \
# 	--hard-dereference \
# 	--directory .. \
# 	$(PACKED_FILES)

# .PHONY : zip
# zip :
# 	@make deffnder.zip


# deffnder.zip : deffnder.tar.gz
# 	cd .. && \
# 	zip -9 deffnder/deffnder.zip \
# 	$(PACKED_FILES)







################################################################
# Old code



# XXX OLD
# This works, but it's not used anymore,
# because other TAP file in bin/ has to be build
# with the assemebler:
#bin/%.tap : src/%.vbas
#	vbas2tap $<
#	mv src/$*.tap bin/


# XXX OLD
# cd src ; \
# bas2tap -c -n -a10 -sDISK ce4.disk.bas ; \
# mv ce4.disk.tap ../bin/


# XXX FIXME bas2tap stops with an error because of the 'OUT' here:

#
#   100 MOVE "c:"OUT : MOVE "c:"IN "program"


#
# But the "-n" flag is used, and if fact it ignores a similar use of 'IN' in
# <ce4.disk.bas>.
#
# Happily, zmakebas works



# zmakebas fails with this
#   DEF FN o$(k$)=CHR$ 20+CHR$ 1+k$+CHR$ 20+CHR$ 0+" "
# The string after the equals sign is corrupted

# XXX 2015-07-08: Is it the same bug of zmakebas Antonio Villena fixed right
# after I announced it in the forum of speccy.org? It was a problem with DEF FN
# parameters.


#	zmakebas -a 1 -n MENU.BAS -o ../bin/ce4.menu.tap ce4.menu.bas

#	cd src ; \
#	bas2tap -c -n -a1 -sMENU.BAS ce4.menu.bas ; \
#	mv ce4.menu.tap ../bin/tmp/

#cd src ; \
#	zmakebas -a 1 -n DISK -o ../bin/tmp/ce4.disk.tap ce4.disk.bas



|
|

|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|


|

>
>
>
|
<
>

<
|
|
<
>
>
>

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
>

<
<
<
<
<
>
>

<
>
>
>

<
>
>

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
>

<
<
<
<
>
>

>
>
>

<
<
>
>

<
<
<
<
<
<
<
>
|
<
<
<
<
>
|
<
>

<
>
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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

























# Makefile
#
# This file is part of CE4 in GW-BASIC
# (http://programandala.net/)

# ==============================================================














































# Config

#VPATH = ./:src:bin:bin/tmp
MAKEFLAGS = --no-print-directory

.ONESHELL:

# ==============================================================
# Main

.PHONY: all

all: pcbasic gwbasic


.PHONY: clean
clean:

	rm -f target/*.bas;\
	rm -f target/pc-basic/*.bas;\
	rm -f target/gw-basic/*.bas










































# ==============================================================
# PC-BASIC


































































.PHONY: pcbasic

pcbasic: target/pc-basic/init.bas target/pc-basic/main.bas






target/pc-basic/init.bas: src/init.bas src/common.bas src/version.bas
	imbastardizer $< $@


target/pc-basic/main.bas: src/main.bas src/common.bas src/version.bas src/wt.bas
	ln -f src/target.pc-basic.bas src/target.bas ;\
	imbastardizer $< $@


# ==============================================================
# GW-BASIC

























.PHONY: gwbasic


gwbasic: target/gw-basic/init.bas target/gw-basic/main.bas





target/gw-basic/init.bas: src/init.bas src/common.bas src/version.bas
	imbastardizer $< $@

target/gw-basic/main.bas: src/main.bas src/common.bas src/version.bas src/wt.bas
	ln -f src/target.gw-basic.bas src/target.bas ;\
	imbastardizer $< $@



# ==============================================================
# Change log








# 2016-12-14: Start.
#




# 2016-12-28: Add `wt` target, for testing the text output routine.
#

# 2017-06-05: Update: change IMBAS extensions to BAS.
#

# 2017-06-13: Implement two different targets: GW-BASIC and the PC-BASIC
# emulator.


























Changes to README.adoc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


= CE
:author: Marcos Cruz (programandala.net)
:revdate: 2016-06-20

// This file is written in AsciiDoc/Asciidoctor format
// (http://asciidoctor.org).

(Este documento está disponible también link:README.es.adoc[en español].)

== Description

CE4 is a text adventure, with graphics, in Spanish, written in
http://programandala.net/en.program.vimclair_basic.html[Vimclair BASIC] and
http://programandala.net/en.program.deffnder.html[Z80] for
http://www.worldofspectrum.org/zxplus3e/[ZX Spectrum +3e].

CE4 is under development.

Home page (in Spanish): http://programandala.net/es.programa.ce4.html.


|

|




|
|
|
|
|
|
|
|
|
|
|
|
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
= CE4
:author: Marcos Cruz (programandala.net)
:revdate: 2017-09-11

// This file is written in AsciiDoc/Asciidoctor format
// (http://asciidoctor.org).

== Description

CE4 is a text adventure, in Spanish, written in
https://en.wikipedia.org/wiki/GW-BASIC[GW-BASIC] with the
http://programandala.net/en.program.imbastardizer.html[Imbastardizer]
preprocessor and the http://pc-basic.org[PC-BASIC] emulator.

Home page (in Spanish):
http://programandala.net/es.programa.ce4.html.

== Status

CE4 in GW-BASIC started in 2016-12.
It's under development.

Deleted README.es.adoc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
= CE
:author: Marcos Cruz (programandala.net)
:revdate: 2016-06-20

// Este fichero está escrito en formato AsciiDoc/Asciidoctor
// (http://asciidoctor.org).

(This document is available also link:README.en.adoc[in English].)

== Descripción

CE4 es una aventura de texto, con gráficos, en español, escrita en
http://programandala.net/es.programa.vimclair_basic.html[Vimclair
BASIC] y http://programandala.net/es.programa.deffnder.html[Z80] para
http://www.worldofspectrum.org/zxplus3e/[ZX Spectrum +3e].

CE4 está en desarrollo.

Sede: http://programandala.net/es.programa.ce4.html.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































Changes to TO-DO.adoc.

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

= Tareas pendientes del proyecto CE4
:author: Marcos Cruz (programandala.net)
:revdate: 2016-07-31

== Dónde me quedé la última vez


2015-03-20:


Los últimos cambios en el conversor vbas2tap.vim de Vimclair BASIC (la nueva
forma de interpretar las directivas `#vim` y las nuevas `#previm`) no están
terminados, y hasta que lo estén CE4 no puede ser traducido.

2015-03-04:


creé la función `fn currentLocationTxt()` para apuntar al texto
adecuado (largo o corto) de descripción de escenario, y ya la usan dos
escenarios, para probar.



Fallo: en ce4.data_maker.vbas, el cálculo de maxLen para nombres de escenarios
parece bien, pero da 32 y una de las cadenas mide 33:


    data theCorridorA,"el final del pasillo por el norte",false,true


2015-03-07:


Inicio la adaptación de la rutina de impresión justificada del menú del disco
de Deducir.


== Arreglar (código)


update `multitasking` before `accept`

2014-08-31: finish deffn wholeNoun$()

2015-03-03: El sistema de control de scroll no puede funcionar, porque no se
puede saber la línea actual de la ventana, y tampoco se puede calcular (debido
a la impresión justificada). Consultaré en los foros. Mientras, uso el número
aproximado de caracteres.

2015-03-04: Esta descripción se imprime sin la última letra:

    data theCorridorA,"el final del pasillo por el norte",false,true

== Arreglar (datos)

2015-03-04: la variable `light` debe referirse a la linterna.


== Mejorar (código)

change the method for locked doors: simply unlock and pass if you have the key

2014-10-16: let "entrar" and "salir" be combined with cardinal points?

2014-10-16: use a string instead of the outside() array, in order to
save memory.

2014-10-16: cursor position: below the command output (and same about the prompt).

2015-02-25: use peek and poke instead of the map array, for the sake of memory and speed.

2015-02-25: in `ce4.data_packer.vbas`, order the arrays to put the most used first.

2015-03-01: create `#vim` directives to optimize calculations that resulted
from substitutions? So far there's  only one case: "37-4" -> "33".

2015-03-03: La memoria libre es de 4 KiB al empezar el juego, tras cargar los
datos, y baja a 400 B durante el juego. Hay que empezar a convertir matrices
numéricas en cadenas, y sacar los textos grandes a ficheros.

2015-03-04 use machine code to remove the lines at the end of `ce4.data_packer.vbas`.

== Añadir (código)

2014-08-07: change the noun$() array to a function returning the noun of the
given thing, extracted from nouns$.

2014-08-15: meta commands:

*  castellano
*  americano
*  sesión

2014-10-21: command history (in a ram disk file?)

2014-10-20: fake direction "backwards", to the previous location.

2015-02-26: command to toggle copying the session to printer.

2015-02-26: keyboard buffer.

2015-03-01: rutina para limpiar la pila de retorno de BASIC y poder hacer un GOTO limpio al final.

== Argumento

2014-10-17: the keys have to be found (uniform of the guard?).

2014-10-17: no key. only one entrance (randomly chosen at the start of every
game) is unlocked at the start ?

2014-10-17: only the office is locked.

2015-03-05: buscar nombre original de «Ole ole si me eligen».

== Textos

2015-03-05: consultar «se digna [a] abrir».

== Notas

----
    // XXX zmakebas fails at the following line (the code is corrupted
    // right from the equals sign) but bas2tap works fine:
    def fn o$(k$)=chr$ 20+chr$ 1+k$+chr$ 20+chr$ 0+" "
----

== Ficheros

2016-07-31: Mover src/ugd.bin a bin/udg.bin.

|

|

<
>

<
>

|
<
<

<
>

<
<
<
>
>

<
<
>

<
>

<
>

<
<
>

<
>

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
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
= CE4 to-do list
:author: Marcos Cruz (programandala.net)
:revdate: 2017-07-02


.2016-12-15:


Use `view print` to create the output window.

Fix dimensions of `syntax()`.




.2017-01-07:




Fix name of empty complement in debug message: now it's number 7 but
name "sí".



.2017-06-02:


Fix: `Examine` does not work with the carried key.


.2017-06-07:



Make things known when they are taken, so their article changes.


.2017-07-02:


























































































Remove old code to load graphics.

Deleted bin/ce4.dsk.

cannot compute difference between binary files

Deleted bin/ce4.hdf.

cannot compute difference between binary files

Deleted bin/ce4.sh.

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
#!/bin/sh
# ce4.boot.sh
# Este programa forma parte del proyecto
#   CE4
# escrito en Vimclair BASIC para ZX Spectrum +3e.

# Este programa arranca Fuse con los parámetros
# necesarios para poner en marcha el programa CE4.

# No se puede cambiar con parámetros la geometría de las unidades de disco!

# 2014-08-03: Inicio.  2015-02-22: Cambio de directorio, solución
# temporal.  2015-02-24: Cambio a 'fuse', mi redirección con cambio de
# filtro automático según se ejecute en Kinasus o Raspesis. Cambio los
# nombres de ficheros de la ROM a los originales.
#
# 2015-03-04: ROM españolas como opción; su juego de caracteres trae
# eñes, interrogación y admiración. Esto ahorraría 32 octetos de
# gráficos.

# XXX TMP
cd ~/zx_spectrum/ce4/en_vimclair_basic/bin/

fuse \
	--machine plus3e \
	--rom-plus3e-0 ./dives3e0.rom \
	--rom-plus3e-1 ./dives3e1.rom \
	--rom-plus3e-2 ./dives3e2.rom \
	--rom-plus3e-3 ./dives3e3.rom \
	--plus3disk ./ce4.dsk \
	--divide \
	--divide-masterfile ./ce4.hdf \
	&
#	--rom-plus3e-0 ./diven3e0.rom \
#	--rom-plus3e-1 ./diven3e1.rom \
#	--rom-plus3e-2 ./diven3e2.rom \
#	--rom-plus3e-3 ./diven3e3.rom \
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































Deleted bin/diven3e0.rom.

cannot compute difference between binary files

Deleted bin/diven3e1.rom.

cannot compute difference between binary files

Deleted bin/diven3e2.rom.

cannot compute difference between binary files

Deleted bin/diven3e3.rom.

cannot compute difference between binary files

Deleted bin/dives3e0.rom.

cannot compute difference between binary files

Deleted bin/dives3e1.rom.

cannot compute difference between binary files

Deleted bin/dives3e2.rom.

cannot compute difference between binary files

Deleted bin/dives3e3.rom.

cannot compute difference between binary files

Deleted bin/graphics.dsk.

cannot compute difference between binary files

Deleted src/ce4.bas.

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
    1 rem CE4
    2 rem Version 0.2.0+201606201408
    3 rem Copyright (C) 2014,2015,2016 Marcos Cruz (programandala.net)
    4 rem License: GPL 3
    5 def fn r(m)=int(rnd*m):def fn b(a,b)=int(rnd*(b-a+1))+a:def fn c$(s$)=s$(fn b(1,len(s$))):def fn d(a)=usr 65064:def fn o(a,n)=usr 65078:def fn t()=fn d(23672)+65536*peek 23674:def fn s()=fn t()/50:def fn d$(n)=("0" and (n<10))+str$ n:def fn h$(h,m,s)=fn d$(h)+":"+fn d$(m)+":"+fn d$(s):def fn u$(t$)="" and usr 65487:def fn w(h$,n$)=usr 65302:def fn w$(h$,n)="" and usr 65397:def fn k(t$,k)=usr 65212:def fn l(t$,k)=usr 65251
    6 def fn t$(t,o)=fn u$(e$(a(t))):def fn n$(t)=fn w$(n$,n(t)):def fn p$(t)=fn t$(t,a(t))+" "+fn n$(t):def fn a(t)=l=l(t) and not d(l(t),l):def fn f()=val "65536"-usr val"7962":def fn x()=l+100*(v(l)>1):def fn h(n)=fn d(23631)+fn d(23568+2*(n+3))-1:def fn y(n)=peek (fn h(n)+18)/8:def fn c()=peek (wi+15)-peek (wi+17)
    7 rem This file is part of
    8 rem CE4
    9 rem A text adventure in Spanish
   10 rem for the ZX Spectrum +3e with DivIDE
   11 rem Copyright (C) 2015 Marcos Cruz (programandala.net)
   12 rem Licencia/Permesilo/License:
   13 rem GPL
   14 def fn f$(n)=str$ n+".txt"
   15 go to 581:rem initOnce XXX
   17 go sub 590
   18 go sub 572:rem _credits XXX
   19 go sub 579:rem _intro XXX
   20 go sub 23
   21 go to 17
   23 go sub 547:rem _gameInit XXX
   24 go sub 384:rem _enterLocation XXX
   25 let t$="Libre="+str$ fn f()+" B":go sub 528
   26 go sub 39:rem _accept XXX
   27 if len q$ and not ii then let t$="{10}{06}"+fn u$(q$)+"{10}{07}":go sub 542
   28 go sub 68: rem _parse XXX
   29 if not(a) then go to 32
   30 go sub 175:rem _obey XXX
   31 go to 37
   32 if not(ii) then go to 35
   33 if not fn r(3) then let t$="El tiempo pasa.":go sub 534
   34 go to 36
   35 let t$="{O}"+x$+"?":go sub 531
   37 if not (go) then go to 25
   38 return
   39 let pl=1
   40 if k=13 then go sub 64
   41 let ii=0:let mt=fn t()+1000
   42 print #6;chr$ 4;q$;
   43 poke 23263+cp,134
   44 let k=code inkey$
   45 if fn t()>mt then let ii=1:poke 23263+cp,6:return
   46 let v=fn o(23662,46):poke 23664,code l$(k+1)+3:continue:go to 54:go to 47:go to 55:go to 50:go to 56:go to 57:go to 61:go to 58:go to 60:go to 52:go to 59
   47 if cp>1 then let cp=cp-1:let sp=sp*(q$(cp)<>" ")
   48 let q$(cp)=" ":print #6;chr$ 4;q$;:poke 23263+cp,134
   49 go to 61
   50 if cp>1 then let c$=q$(to cp-1):print #6;chr$ 14:return
   51 go to 61
   52 if cp>1 and not sp and cp<32 then let mt=mt+250:let sp=cp:let q$(cp)=" ":poke 23263+cp,6:print #6;chr$ 4;q$;:let cp=cp+1:poke 23263+cp,134
   53 go to 61
   54 let k=144:go to 60
   55 let k=146:go to 60
   56 let k=148:go to 60
   57 let k=154:go to 60
   58 let k=150:go to 60
   59 let k=152
   60 if cp<32 then let mt=mt+250:let q$(cp)=chr$ k:poke 23263+cp,6:print #6;chr$ 4;q$;:let cp=cp+1:poke 23263+cp,134
   61 if mu*not peek 23672 then go sub 103
   62 go to 44
   63 return
   64 let k=0:let q$="":let c$="":let cp=1:let sp=0
   65 return
   66 let t$="No tengo "+fn p$(c)+".":go sub 534
   67 return
   68 if not(sp) then go to 71
   69 let x$=c$(to sp-1):let y$=c$(sp+1 to)
   70 go to 72
   71 let x$=c$:let y$=""
   72 let t$="Verbo='"+x$+"'":go sub 528
   73 let t$="Nombre='"+y$+"'":go sub 528
   74 let a=fn w(v$,chr$ 0+x$+chr$ 14):let c=fn w(n$,chr$ 0+y$+chr$ 14)
   75 if not(c>=37) then go to 79
   76 let v=fn o(23662,76):poke 23664,c-37+4:continue:go to 95:go to 84:go to 91
   77 let t$="Complemento ambiguo fuera de rango: "+str$ c:go sub 530
   78 go to 81
   79 if c then go to 81
   80 let c=7
   81 let t$="Acci{G}n= "+str$ a:go sub 528
   82 let t$="Compl.= "+str$ c:go sub 528
   83 return
   84 let t$="Complemento ambiguo {R}mesa{S}= "+str$ c:go sub 528
   85 if not(l=13) then go to 88
   86 let c=10
   87 go to 89
   88 let c=13
   89 let t$="Complemento inequ{E}voco= "+str$ c:go sub 528
   90 return
   91 let t$="Complemento ambiguo {R}muro{S}= "+str$ c:go sub 528
   92 if o(l) then let c=15+(l-14)
   93 let t$="Complemento inequ{E}voco= "+str$ c:go sub 528
   94 return
   95 let t$="Complemento ambiguo {R}tiesto{S}= "+str$ c:go sub 528
   96 let t$="Escenario actual= "+str$ l:go sub 528
   97 if not(o(l)) then go to 100
   98 let c=28+(l-14):let t$="Complemento inequ{E}voco seg{I}n escenario= "+str$ c:go sub 528:let lp=c:return
   99 go to 102
  100 let c=lp
  101 let t$="Complemento inequ{E}voco seg{I}n recuerdo= "+str$ c:go sub 528
  102 return
  103 let e=fn b(1,4):if not x(l(23),e) then return
  104 let l(23)=x(l(23),e)-100*(x(l(23),e)>100)
  105 let t$="El guarda se va hacia "+fn n$(e)+" ("+fn u$(s$(l(23)))+").":go sub 528
  106 if not(l=l(23)) then go to 109
  107 go sub 115
  108 go to 114
  109 if not(d(l,l(23))) then go to 112
  110 let t$="Oigo pasos al "+fn n$(d(l,l(23)))+"...":go sub 534
  111 go to 114
  112 if not(c(l(23)) and c(l)) then go to 114
  113 let t$="He o{E}do algo en el pasillo...":go sub 534
  114 return
  115 let mu=0:let b=0
  116 let t$="Me agarra por el cuello y me dice: ":go sub 537
  117 if not(o(l)) then go to 120
  118 let t$="{R}{O}Qu{C} haces rondando por aqu{E}?{S}.":go sub 542
  119 go to 122
  120 let b=1
  121 let t$="{R}{O}C{G}mo has entrado aqu{E}?{S}.":go sub 542
  122 if not(gm and not b) then go to 126
  123 let t$="Se acerca a m{E} y me dice:":go sub 537
  124 if -1=l(26) then go to 130
  125 go to 137
  126 if not(b) then go to 129
  127 let t$="{R}Esta habitaci{G}n estaba cerrada con llave...":go sub 537:if l=l(33) and so then let t$="{P}Y adem{A}s has abierto la caja!":go sub 539
  128 let t$="{P}Maldito hereje!{S}.":go sub 539
  130 if -1=l(26) then let t$="{R}{O}Qu{C} es ese papel que tienes ah{E} escondido? D{C}jame ver...{S}.":go sub 534:pause 100:let t$="{R}Hum...{S}, dice, echando un vistazo.":go sub 534:pause 100:let t$="{R}As{E} que has copiado el examen...{S}, dice por fin.":go sub 534:let b=1
  131 if b then let t$="{R}Esto significa tu inmediata expulsi{G}n de este complejo.":go sub 537:go to 147
  132 let t$="Se vuelve hacia m{E} y me dice:":go sub 537
  133 let t$="{R}{O}Sabes que estar en el complejo a estas horas es una grave falta de disciplina?{S}.":go sub 542
  134 pause 100
  135 let t$="{R}Este comportamiento no es propio de un alumno que se esta formando en el complejo{S}, a{K}ade.":go sub 534
  136 if b then go to 147
  137 go sub 139
  138 return
  140 let l(23)=fn b(1,30)
  141 if not (not fn a(23)) then go to 140
  142 print #win
  143 let t$="Se da media vuelta y se va.":go sub 534
  144 let gm=gm+1
  145 if not b then let t$="{P}Uf!... por poco.":go sub 534
  146 return
  147 let tps=fn s()
  148 let pm=int (tps/60)
  149 let ps=int (tps-pm*60)
  150 let ph=int (pm/60)
  151 let pm=pm-ph*60
  152 if not(b) then go to 156
  153 let t$="Has sido expulsado del Complejo Educativo.":go sub 537
  154 let t$="La pr{G}xima vez ten m{A}s cuidado.":go sub 542
  155 go to 158
  156 let t$="Has logrado tu objetivo.":go sub 537
  157 let t$="{P}Enhorabuena!":go sub 542
  158 go sub 171
  159 if b then go to 168
  160 if not(tps<trs) then go to 164
  161 let trs=tps:let rh=ph:let rm=pm:let rs=ps:let r$=h$
  162 let t$="{P}Has establecido un nuevo r{C}cor!":go sub 534
  163 go to 167
  164 let t$="El r{C}cor sigue en posesi{G}n de":go sub 537
  165 let t$=r$+", con un tiempo de":go sub 539
  166 let t$=fn h$(rh,rm,rs)+".":go sub 542
  168 let t$="Pulsa una tecla para jugar.":go sub 534
  169 pause 0
  170 go to 16
  171 let t$="Tardaste en ":go sub 537
  172 let t$=("ser expulsado" and b)+("lograrlo" and not b)+": ":go sub 539
  173 let t$=fn h$(ph,pm,ps)+".":go sub 542
  174 return
  175 if len y$ and c=7 then let t$="{O}"+y$+"?":go sub 531:return
  176 if s(a,c) then go to 182
  177 if not(c=7) then go to 180
  178 let t$="Falta complemento.":go sub 531
  179 go to 181
  180 let t$="Imposible.":go sub 531
  181 return
  182 go sub 184
  183 return
  185 let v=fn o(23662,185):poke 23664,a+3:continue:go to 258:go to 234:go to 315:go to 206:go to 195:go to 204:go to 191:go to 199:go to 193:go to 197:go to 259:go to 277:go to 248:go to 358:go to 366:go to 226:go to 348:go to 353:go to 187:let t$="Valor incorrecto de la variable 'a' (la acci{G}n): "+str$ a:go sub 530
  186 let t$="Flujo descontrolado en la rutina 'obey'":go sub 530
  187 let t$="El complemento est{A} en el escenario "+str$ l(c)+"("+s$(l(c))+" )":go sub 528
  188 return
  189 let t$="doGoComplement":go sub 528
  190 let d=c:go to 206
  191 let t$="doGoNorth":go sub 528
  192 let d=1:go to 206
  193 let t$="doGoSouth":go sub 528
  194 let d=2:go to 206
  195 let t$="doGoEast":go sub 528
  196 let d=3:go to 206
  197 let t$="doGoWest":go sub 528
  198 let d=4:go to 206
  199 let t$="doGoOut":go sub 528
  200 let d=6
  201 let e=x(l,d)
  202 if not e then let e=pl
  203 go to 208
  204 let t$="doGoIn":go sub 528
  205 let d=5
  206 let t$="doGo":go sub 528
  207 let e=x(l,d)
  208 if e then go to 211
  209 let t$="No puedo ir en esa direcci{G}n.":go sub 534
  210 go to 225
  211 if not(e>100) then go to 222
  212 if not(-1=l(24)) then go to 220
  213 let t$="Abro la puerta con la llave.":go sub 534
  214 let x(l,d)=e-100
  215 let x(e-100,u(d))=l
  216 let pl=l
  217 let l=e-100
  218 go sub 384
  219 go to 221
  220 let t$="No puedo ir en esa direcci{G}n. Hay una puerta cerrada con llave.":go sub 534
  221 go to 225
  222 let pl=l
  223 let l=e
  224 go sub 384
  225 return
  226 let t$="doTake":go sub 528
  227 if -1=l(c) then let t$="Ya tengo "+fn p$(c)+".":go sub 534:return
  228 if not light then let t$="La oscuridad me lo impide.":go sub 534:return
  229 if l<>l(c) then let t$="No veo "+fn p$(c)+" aqu{E}.":go sub 534:return
  230 if c>=28 and c<=32 then let t$="Eso debe de pesar m{A}s que una vaca.":go sub 534:return
  231 let l(c)=-1:let ca=ca+1
  232 let t$="Recojo "+fn p$(c)+".":go sub 534
  233 return
  234 let t$="doDrop":go sub 528
  235 if not(c=8) then go to 241
  236 for n=21 to 36
  237 if -1=l(n) then let l(n)=l
  238 next n
  239 let ca=0
  240 go to 247
  241 if not(-1<>l(c)) then go to 244
  242 go sub 66
  243 go to 246
  244 let l(c)=l:let ca=ca-1
  245 let t$="Dejo "+fn p$(c)+".":go sub 534
  247 return
  248 let t$="doOpen":go sub 528
  249 if c=33 then go to 368
  250 if -1<>l(24) then let t$="No tengo la llave.":go sub 534:return
  251 for n=1 to 4
  252 let e=x(l,n)
  253 if not(e>100) then go to 255
  254 let x(l,n)=e-100:let x(e-100,n-(n=2 or n=4)+(n=1 or n=3))=l:let t$="Abro la puerta que va al "+fn n$(n)+".":go sub 534:return
  255 next n
  256 let t$="No hay ninguna puerta cerrada.":go sub 534
  257 return
  258 let t$="doDo":go sub 528
  259 let t$="doInventory":go sub 528
  260 if not ca then let t$="No tengo nada.":go sub 534:return
  261 let li=0
  262 let t$="Tengo ":go sub 537
  263 for n=21 to 36
  264 if not(-1=l(n)) then go to 275
  265 let li=li+1
  266 if not(li=ca) then go to 270
  267 if ca>1 then let t$=" y ":go sub 539
  268 let t$=fn p$(n)+".":go sub 542
  269 go to 274
  270 if not(li=ca-1) then go to 273
  271 let t$=fn p$(n):go sub 539
  272 go to 274
  273 let t$=fn p$(n)+", ":go sub 539
  275 next n
  276 return
  277 let t$="doLook":go sub 528
  278 if not(c=8 or c=7) then go to 281
  279 go sub 392:go sub 404:go sub 429
  280 go to 314
  281 if light then go to 284
  282 let t$="Me encantar{E}a poder ver en la oscuridad.":go sub 534
  283 go to 314
  284 if not(-1<>l(c) and l<>l(c)) then go to 287
  285 let t$="No veo "+fn p$(c)+" aqu{E}.":go sub 534
  286 go to 314
  287 if not(c=25) then go to 293
  288 if not(-1=l(c)) then go to 291
  289 let t$="Tiene algo escrito.":go sub 534:pause 100:go sub 376
  290 go to 292
  291 let t$="Ah{E} est{A}.":go sub 534
  292 go to 314
  293 if not(c=9) then go to 296
  294 let t$="Los libros est{A}n polvorientos.":go sub 534
  295 go to 314
  296 if not(c=13) then go to 299
  297 let t$="Es una triste mesa de acampada, enclenque y oxidada.":go sub 534
  298 go to 314
  299 if not(c=10) then go to 302
  300 let t$="Son viejas y desgastadas mesas de madera.":go sub 534
  301 go to 314
  302 if not(c>=1 and c<=6) then go to 310
  303 let e=x(l,c)
  304 if not e and c=6 then let t$="Se usa en su lugar el escenario previo: "+str$ pl:go sub 528:let e=pl
  305 if not(e) then go to 308
  306 let t$="Hacia "+("el " and (c<5))+fn p$(c)+" est{A} "+fn u$(s$(e-100*(e>100)))+("." and (e<100))+(", pero la puerta est{A} cerrada." and (e>100)):go sub 534
  307 go to 309
  308 let t$="No hay salida hacia "+("el " and (c<5))+fn p$(c)+".":go sub 534
  309 go to 314
  310 if not(c=12) then go to 313
  311 go to 259
  312 go to 314
  313 let t$="No veo nada especial.":go sub 534
  314 return
  315 let t$="doExamine":go sub 528
  316 if not(c=8 or c=7) then go to 319
  317 go sub 392:go sub 404:go sub 429
  318 go to 347
  319 if light then go to 322
  320 let t$="Con esta oscuridad no es posible examinar nada.":go sub 534
  321 go to 347
  322 if not(-1<>l(c) and l<>l(c)) then go to 325
  323 let t$="No veo "+fn p$(c)+" aqu{E}.":go sub 534
  324 go to 347
  325 if not(c=25) then go to 331
  326 if not(-1=l(c)) then go to 329
  327 let t$="Tiene algo escrito.":go sub 534:pause 100:go sub 376
  328 go to 330
  329 let t$="Ah{E} est{A}.":go sub 534
  330 go to 347
  331 if not(c=9) then go to 334
  332 let t$="Examino los libros polvorientos.":go sub 534
  333 go to 347
  334 if not(c=13) then go to 337
  335 let t$="Es una triste mesa de acampada, enclenque y oxidada.":go sub 534
  336 go to 347
  337 if not(c=10) then go to 340
  338 let t$="Son viejas y desgastadas mesas de madera.":go sub 534
  339 go to 347
  340 if not(c>=28 and c<=32) then go to 343
  341 go sub 378
  342 go to 347
  343 if not(c=12) then go to 346
  344 go to 259
  345 go to 347
  346 let t$="No veo nada especial.":go sub 534
  347 return
  348 let t$="doTurnOff":go sub 528
  349 if -1<>l(c) then go sub 66:return
  350 if not light then let t$="Ya est{A} apagada.":go sub 534
  351 let light=0
  352 return
  353 let t$="doTurnOn":go sub 528
  354 if -1<>l(c) then go sub 66:return
  355 if light then let t$="Ya est{A} encendida.":go sub 534
  356 let light=1
  357 return
  358 let t$="doRead":go sub 528
  359 if -1<>l(c) then go sub 66:return
  360 if not light then let t$="No puedo leer a oscuras.":go sub 534:return
  361 if not(c=26) then go to 364
  362 let t$="Est{A} en blanco.":go sub 534
  363 return
  364 if c=25 then go sub 376:return
  365 return
  366 let i=gr:let gr=(not gr)*(c=7)+(c=20):if gr<>i then cls:go sub 585:if gr then let v=usr 65036:go sub 402
  367 return
  368 if so then let t$="Ya estaba abierta.":go sub 534:return
  369 let t$="{O}Cu{A}l es la combinaci{G}n?":go sub 534:go sub 39
  370 if not(c$=f$) then go to 373
  371 let so=1
  372 go to 375
  373 let t$="La caja no se abre.":go sub 534
  374 let t$="Parece que esa no es la combinaci{G}n.":go sub 534
  375 return
  376 let t$="Pone... "+f$:go sub 534
  377 return
  378 if not(c=kp) then go to 382
  379 let t$="{P}Aqu{E} est{A} la llave!"+(" {P}A la primera!" and not examinedPots)+(" No ha sido tan dif{E}cil." and examinedPots<3)+(" {P}Por fin!" and examinedPots>3)+(" Ten{E}a que estar en el {I}ltimo." and examinedPots=5):go sub 534
  380 let l(24)=-1:let ca=ca+1
  381 go to 383
  382 let t$="En este "+("primero no " and not examinedPots)+("tampoco " and examinedPots)+"est{A} la llave.":go sub 534:let examinedPots=examinedPots+(examinedPots<5)
  383 return
  384 let v(l)=v(l)+1
  385 go sub 389
  386 go sub 395
  387 if not go then go sub 404:go sub 429
  388 return
  389 if gr then go sub 402
  390 let t$=chr$ 14+"Entro en ":go sub 537
  391 go to 393
  392 let t$=chr$ 14+"Estoy en ":go sub 537
  393 let v=fn o(23662,393):poke 23664,l+3:continue:go to 478:go to 509:go to 466:go to 511:go to 521:go to 523:go to 497:go to 499:go to 501:go to 503:go to 505:go to 507:go to 513:go to 451:go to 454:go to 457:go to 460:go to 463:go to 469:go to 490:go to 484:go to 475:go to 472:go to 525:go to 496:go to 492:go to 515:go to 517:go to 519:go to 494:let t$="La variable 'l' (escenario actual) tiene un valor incorrecto: "+str$ l:go sub 530
  394 let t$="Flujo descontrolado en la rutina 'describeLocation'":go sub 530
  395 if not(l=l(23)) then go to 400
  396 let t$="{P}El guarda est{A} aqu{E}!":go sub 534
  397 pause 100
  398 go sub 115
  399 go to 401
  400 if not(o(l)) then go to 401
  401 return
  402 let i$=("0" and l<10)+str$ l+chr$ (48+light):load "g:"+i$+".scr" code 16384
  403 return
  404 let j$=""
  405 for n=21 to 36
  406 if l=l(n) then let j$=j$+chr$ n
  407 next n
  408 let th=len j$
  409 let t$="Cosas: "+str$ th:go sub 528
  410 if not th then return
  411 let li=0
  412 let t$="Veo ":go sub 537
  413 for n=1 to th
  414 let i=code j$(n)
  415 let t$="Cosa n{I}mero "+str$ i+"("+fn p$(i)+")" :go sub 528
  416 if not(l=l(i)) then go to 427
  417 let li=li+1
  418 if not(li=th) then go to 422
  419 if th>1 then let t$=" y ":go sub 539
  420 let t$=fn p$(i)+".":go sub 542
  421 go to 426
  422 if not(li=th-1) then go to 425
  423 let t$=fn p$(i):go sub 539
  424 go to 426
  425 let t$=fn p$(i)+", ":go sub 539
  427 next n
  428 return
  429 let eh=y(l)
  430 let t$="Salidas: "+str$ eh:go sub 528
  431 if not eh then return
  432 let li=0
  433 let t$="Hay salida"+("s" and eh>1)+" hacia ":go sub 537
  434 for n=1 to 4
  435 let t$="Salida "+str$ n+": "+str$ x(l,n):go sub 528
  436 if not(x(l,n)) then go to 447
  437 let li=li+1
  438 if not(li=eh) then go to 442
  439 if eh>1 then let t$=" y ":go sub 539
  440 let t$=fn n$(n)+".":go sub 542
  441 go to 446
  442 if not(li=eh-1) then go to 445
  443 let t$=fn n$(n):go sub 539
  444 go to 446
  445 let t$=fn n$(n)+", ":go sub 539
  447 next n
  448 let t$="Salida "+str$ 5+": "+str$ x(l,5):go sub 528
  449 let t$="Salida "+str$ 6+": "+str$ x(l,6):go sub 528
  450 return
  451 let t$=fn u$(s$(14))+".":go sub 542
  452 go sub 592
  453 return
  454 let t$=fn u$(s$(15))+".":go sub 542
  455 go sub 592
  456 return
  457 let t$=fn u$(s$(16))+".":go sub 542
  458 go sub 592
  459 return
  460 let t$=fn u$(s$(17))+".":go sub 542
  461 go sub 592
  462 return
  463 let t$=fn u$(s$(18))+".":go sub 542
  464 go sub 592
  465 return
  466 let t$=fn u$(s$(3))+". ":go sub 539
  467 let t$="El olor es inaguantable.":go sub 542
  468 return
  469 let t$=fn u$(s$(19))+". ":go sub 539
  470 let t$="El olor a zapato es sobrehumano.":go sub 542
  471 return
  472 let t$=fn u$(s$(23))+". ":go sub 539
  473 let t$="Hay un tufo a carne podrida.":go sub 542
  474 return
  475 let t$=fn u$(s$(22))+". ":go sub 539
  476 let t$="La suciedad cubre los muebles.":go sub 542
  477 return
  478 let t$=fn u$(s$(1))+". ":go sub 542
  479 if light then go to 482
  480 let t$="Todo est{A} a oscuras.":go sub 534
  481 go to 483
  482 let light=0
  483 return
  484 let t$=fn u$(s$(21))+". ":go sub 542
  485 if light then go to 488
  486 let t$="Todo est{A} a oscuras.":go sub 534
  487 go to 489
  488 let light=0
  489 return
  490 let t$=fn u$(s$(20))+", ":go sub 539
  491 let t=fn x():go sub 541:return
  492 let t$=fn u$(s$(26))+".":go sub 542
  493 return
  494 let t$=fn u$(s$(30))+".":go sub 542
  495 return
  496 let t$=fn u$(s$(25))+". ":go sub 539:let t=fn x():go sub 541:return
  497 let t$=fn u$(s$(7))+".":go sub 542
  498 return
  499 let t$=fn u$(s$(8))+".":go sub 542
  500 return
  501 let t$=fn u$(s$(9))+".":go sub 542
  502 return
  503 let t$=fn u$(s$(10))+".":go sub 542
  504 return
  505 let t$=fn u$(s$(11))+".":go sub 542
  506 return
  507 let t$=fn u$(s$(12))+".":go sub 542
  508 return
  509 let t$=fn u$(s$(2))+".":go sub 542
  510 return
  511 let t$=fn u$(s$(4))+".":go sub 542
  512 return
  513 let t$=fn u$(s$(13))+".":go sub 542
  514 return
  515 let t$=fn u$(s$(27))+".":go sub 542
  516 return
  517 let t$=fn u$(s$(28))+".":go sub 542
  518 return
  519 let t$=fn u$(s$(29))+".":go sub 542
  520 return
  521 let t$=fn u$(s$(5))+".":go sub 542
  522 return
  523 let t$=fn u$(s$(6))+".":go sub 542
  524 return
  525 let t$=fn u$(s$(24))+". ":go sub 539
  526 let t$="Una monta{K}a de libros polvorientos oculta la pared.":go sub 542
  527 return
  528 print #7;t$
  529 return
  530 let t$="ERROR FATAL: "+t$
  531 let t$="{10}{02}["+t$+"]{10}{07}"
  532 go to 534
  533 load fn f$(t) data a$():let t$=a$
  534 print #win;"{-8}{-8}";chr$ 1;t$
  535 go to 543
  536 load fn f$(t) data a$():let t$=a$
  537 print #win;"{-8}{-8}";:go to 539
  538 load fn f$(t) data a$():let t$=a$
  539 print #win;chr$ 1;t$;:go to 543
  540 print #win;chr$ 14;chr$ 4:let pc=0:return
  541 load fn f$(t) data a$():let t$=a$
  542 print #win;chr$ 1;t$
  543 return
  544 let t$="@textPAUSE":go sub 528:let t$="PRESS ANY KEY":go sub 528:pause 0
  545 print #6;"{0E}...";:pause val "1e3":print #6;"{0E}":let pl=1
  546 return
  547 randomize
  548 go sub 540
  549 let go=0:let mu=1:let so=0:let gm=0:let light=1
  550 for n=1 to sd
  551 let f$(n)=chr$ fn b(48,57)
  552 next n
  553 dim m(19,39)
  554 load "location.dat" data l():for n=1 to 39
  555 if not(s(16,n)) then go to 559
  556 let i=27
  557 if o(i) then go to 556
  558 let l(n)=i
  559 next n
  560 for n=28 to 32:let l(n)=14+n-28:next n
  561 let l(33)=27:let l(9)=24:let l(36)=code fn c$(chr$ 29+chr$ 30+chr$ 5+chr$ 6+chr$ 21):let l(24)=0
  562 let l=20
  563 let pl=0
  564 let l(23)=fn b(14,18)
  565 if not (not fn a(23)) then go to 564
  566 let kp=fn b(28,31):let examinedPots=0:let lp=0:let ca=0
  567 go sub 588
  568 go sub 540
  569 if gr then let v=usr 65036
  570 poke 23672,not pi:poke 23673,not pi:poke 23674,not pi
  571 return
  572 cls
  573 let t$="CE4":go sub 534
  574 let t$="(C) 2014,2015 Marcos Cruz (programandala.net)":go sub 534
  575 let t$="Licencia/Permesilo/License: GPL 3":go sub 534
  576 let t$="Memoria libre: "+str$ fn f()+" B":go sub 534
  577 pause 200
  578 return
  579 cls:go sub 590:for i=1000 to 1003:let t=i:go sub 533:next i:go sub 544
  580 return
  581 border 0:paper 0:ink 7:bright 0:flash 0:clear 64883:load "c:":load "ce4.bin" code 64884:let v=fn o(23675,64884):let ma=3:let sd=4:let gr=1:let b=0:let rh=0:let rm=16:let rs=0:let trs=rm*60:let r$="Lutero":dim q$(32):let c$="":dim f$(sd):go sub 64:go sub 582:dim a$(1):merge "data.bas":go to 16
  582 let fwt=0:let fww=22:let fwh=23:let fwcs=7:let fwb=fwt+fwh-1:close #4:open #4,"w>"+str$ fwt+",0,"+str$ fwh+","+str$ fww+","+str$ fwcs:print #4;paper 0;ink 7;chr$ 14:let fwc=int(fwh*fww*fwcs/val"8"*val".75"):close #6:open #6,"w>23,0,1,32,8":print #6;paper 0;ink 6;chr$ 14
  583 go sub 585
  584 return
  585 let twt=9*gr:let twh=21-8*gr:let twb=twt+twh-1:close #5:close #7:open #7,"w>"+str$ twt+",22,"+str$ twh+",10,6":print #7;chr$ 24+chr$ 2+chr$ 14:let tww=22:let twcs=7:let twc=int(twh*tww*twcs/val"8"*val".75"):open #5,"w>"+str$ twt+",0,"+str$ twh+","+str$ tww+","+str$ twcs:print #5;paper 0;ink 7;chr$ 30;chr$ 0;chr$ 31;chr$ 1;chr$ 14;
  586 let pl=1
  587 return
  588 let win=5:let wi=fn h(win):let winHeight=fwh:let pl=1
  589 return
  590 let win=4:let wi=fn h(win):let winHeight=twh:let pl=1
  591 return
  592 return
  593 for n=1 to 39
  594 print n,fn p$(n)
  595 next n
  596 save "c:ce4.bas" line 1:run
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted src/ce4.bin.symbols.vbas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#vim %substitute@\<ce4_udg\>@eval[65536-z80_size+str2nr("00000",16)]eval@gi
#vim %substitute@\<cl1st3rd\>@eval[65536-z80_size+str2nr("00098",16)]eval@gi
#vim %substitute@\<fn_dpeek\>@eval[65536-z80_size+str2nr("000B4",16)]eval@gi

#vim %substitute@\<fn_dpoke\>@eval[65536-z80_size+str2nr("000C2",16)]eval@gi

#vim %substitute@\<fn_instr1\>@eval[65536-z80_size+str2nr("000D6",16)]eval@gi

#vim %substitute@\<fn_lookup16\>@eval[65536-z80_size+str2nr("0016F",16)]eval@gi

#vim %substitute@\<fn_lookup8\>@eval[65536-z80_size+str2nr("00148",16)]eval@gi

#vim %substitute@\<fn_term\>@eval[65536-z80_size+str2nr("001A2",16)]eval@gi

#vim %substitute@\<fn_termn\>@eval[65536-z80_size+str2nr("00201",16)]eval@gi

#vim %substitute@\<fn_trunc\>@eval[65536-z80_size+str2nr("0025B",16)]eval@gi

#vim %substitute@\<z80_clear_address\>@\=str2nr("0FD73",16)@gi
#vim %substitute@\<z80_load_address\>@\=str2nr("0FD74",16)@gi
#vim %substitute@\<z80_size\>@\=str2nr("0028C",16)@gi
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































Deleted src/ce4.bin.symbols.z80s.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ce4_udg		EQU 00000H
cl1st3rd	EQU 00098H
fn_dpeek	EQU 000B4H
fn_dpeek_size	EQU 0000EH
fn_dpoke	EQU 000C2H
fn_dpoke_size	EQU 00014H
fn_instr1	EQU 000D6H
fn_instr1_size	EQU 00072H
fn_lookup16	EQU 0016FH
fn_lookup16_size EQU 00033H
fn_lookup8	EQU 00148H
fn_lookup8_size	EQU 00027H
fn_term		EQU 001A2H
fn_term_size	EQU 0005FH
fn_termn	EQU 00201H
fn_termn_size	EQU 0005AH
fn_trunc	EQU 0025BH
fn_trunc_size	EQU 00031H
z80_clear_address EQU 0FD73H
z80_load_address EQU 0FD74H
z80_size	EQU 0028CH
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































Deleted src/ce4.bin.z80s.

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
; ce4.bin.z80s

; This file is part of CE4
; http://programandala.net/es.programa.ce4.vimclair_basic.html

; By Marcos Cruz (programandala.net)

; Change history

; 2014-08-10: Start.
;
; 2015-02-26: Improved. 
;
; 2015-03-01: New: <fn_lookup16.z80s>. Change: the labels are reorganized in
; order to make their conversion into the Vimclair BASIC sources, and the final
; installation, fully automatic.

org 0

include udg.z80s
include cl1st3rd.z80s
include fn_dpeek.z80s
include fn_dpoke.z80s
include fn_instr1.z80s
include fn_lookup8.z80s
include fn_lookup16.z80s
include fn_term.z80s
include fn_termn.z80s
include fn_trunc.z80s

; Note: The symbols that start with "z80" are treated apart by <Makefile>.  The
; lenght of the code must be the last symbol in the symbols file, therefore its
; name ("z80_size") must be the last one in alphabetical order.

public z80_size
z80_size: equ $

public z80_clear_address
z80_clear_address: equ 0xFFFF-z80_size

public z80_load_address
z80_load_address: equ z80_clear_address+1

end

; -- end of file --
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































Deleted src/ce4.common.bas.

1

<


Deleted src/ce4.common.enum.vim.

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
" ce4.common.enum.vim

" This file is part of
" CE4
" A text adventure in Spanish
" for the ZX Spectrum +3e with DivIDE

" This file was last modified: 2014-12-14

" Copyright (C) 2014 Marcos Cruz (programandala.net)

" Licencia/Permesilo/License:
" GPL

" This file provides a Vim function used by some Vim directives of
" <ce4.common.vbas>.

" 2014-12-14: Written.

let b:enum=0
function! Enum(...)
  " Return the current value of 'b:enum' and increase it.
  " If a parameter is given, store it into 'b:enum' first.
  if a:0 " Any parameter?
    let b:enum=a:1 " Use the first parameter
  endif
  let l:output=b:enum
  let b:enum=b:enum+1
  return l:output
endfunction
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































Deleted src/ce4.common.vbas.

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
// ce4.common.vbas

// This file is part of
// CE4
// A text adventure in Spanish
// for the ZX Spectrum +3e with DivIDE

// This file was last modified: 2015-03-20

// Copyright (C) 2014 Marcos Cruz (programandala.net)

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://gnu.org/licenses>.

// }}} ---------------------------------------------------------
// Requirements {{{

// Note: the debug code occupies c. 2 KiB
#define debug

// Add a Vim function required to create identifiers:

// XXX TMP -- absolute path only for debugging
#previm source /home/m/zx_spectrum/ce4/en_vimclair_basic/src/ce4.common.enum.vim

// }}} ---------------------------------------------------------
// Z80 code symbols {{{

// The graphics and the Z80 routines are packed in one single file
// (<src/ce4.bin.z80s). Its symbols are exported to
// <scr/ce4.bin.symbols.z80s> by the assembler. The <Makefile> file
// converts it to <scr/ce4.bin.symbols.vbas>, in order to include it
// here.

// This file contains the '#vim' directives required to convert the
// Z80 code symbols used in the Vimclair BASIC sources (e.g. the entry
// points of the machine code routines) to actual values:

#include ce4.bin.symbols.vbas

// A final step is required:

#vim %substitute@\<eval\[\(.\{-}\)]eval\>@\=eval(submatch(1))@gi

// }}} ---------------------------------------------------------
// System addresses {{{

// Note: case sensitive

#vim %substitute,\<SCRAD\>,16384,gI
#vim %substitute,\<ATTRAD\>,22528,gI
#vim %substitute,\<bottomLineAttrAddress\>,23263,gI

// }}} ---------------------------------------------------------
// System variables {{{

// Note: case sensitive

#vim %substitute,\<STRMS\>,23568,gI
#vim %substitute,\<CHANS\>,23631,gI
#vim %substitute,\<FLAGS2\>,23658,gI
#vim %substitute,\<OLDPPC\>,23662,gI
#vim %substitute,\<OSPPC\>,23664,gI
#vim %substitute,\<SEED\>,23670,gI
#vim %substitute,\<FRAMES\>,23672,gI
#vim %substitute,\<FRAMES1\>,23673,gI
#vim %substitute,\<FRAMES2\>,23674,gI
#vim %substitute,\<UDG\>,23675,gI
#vim %substitute,\<RAMTOP\>,23730,gI

// }}} ---------------------------------------------------------
// Character codes {{{

// Note: case sensitive

#vim %substitute,\<DELETE_CHAR\>,12,gI
#vim %substitute,\<ENTER_CHAR\>,13,gI
#vim %substitute,\<SPACE_CHAR\>,32,gI

// }}} ---------------------------------------------------------
// UDG {{{

// Note: case sensitive

#vim %substitute,\<code\s*\["{A}"],144,gI
#vim %substitute,\<code\s*\["{C}"],146,gI
#vim %substitute,\<code\s*\["{E}"],148,gI
#vim %substitute,\<code\s*\["{G}"],150,gI
#vim %substitute,\<code\s*\["{I}"],152,gI
#vim %substitute,\<code\s*\["{K}"],154,gI

#vim %substitute,á,{A},gI
#vim %substitute,Á,{B},gI
#vim %substitute,é,{C},gI
#vim %substitute,É,{D},gI
#vim %substitute,í,{E},gI
#vim %substitute,Í,{F},gI
#vim %substitute,ó,{G},gI
#vim %substitute,Ó,{H},gI
#vim %substitute,ú,{I},gI
#vim %substitute,Ú,{J},gI
#vim %substitute,ñ,{K},gI
#vim %substitute,Ñ,{L},gI
#vim %substitute,ü,{M},gI
#vim %substitute,Ü,{N},gI
#vim %substitute,¿,{O},gI
#vim %substitute,¡,{P},gI
#vim %substitute,º,{Q},gI
#vim %substitute,«,{R},gI
#vim %substitute,»,{S},gI

// }}} ---------------------------------------------------------
// Colors {{{

// First, the embedded chars, in hex:
#vim %substitute,{black},{00},gi
#vim %substitute,{red},{02},gi
#vim %substitute,{yellow},{06},gi
#vim %substitute,{white},{07},gi

// Then the ordinary ones:
#vim %substitute,\<black\>,0,gi
#vim %substitute,\<blue\>,1,gi
#vim %substitute,\<red\>,2,gi
#vim %substitute,\<green\>,4,gi
#vim %substitute,\<cyan\>,5,gi
#vim %substitute,\<yellow\>,6,gi
#vim %substitute,\<white\>,7,gi
# #vim %substitute,\<contrast\>,8,gi
#vim %substitute,\<transparent\>,9,gi
# #vim %substitute,\<papery\>,8,gi
# #vim %substitute,\<flashy\>,128,gi

// Specific attributes:
#vim %substitute,\<cursorAttr\>,134,gi
#vim %substitute,{inputInk},{06},gi
#vim %substitute,\<inputAttr\>,6,gi
#vim %substitute,\<inputInk\>,6,gi
#vim %substitute,{outputInk},{07},gi
#vim %substitute,\<outputInk\>,7,gi

// }}} ---------------------------------------------------------
// Subroutines with parameters {{{

#vim %substitute,\<_echo_\[\(.\{-}\)],let t$=\1:gosub @_echo_,gi
#vim %substitute,\<_echo\[\(.\{-}\)],let t$=\1:gosub @_echo,gi
#vim %substitute,\<echo_\[\(.\{-}\)],let t$=\1:gosub @echo_,gi
#vim %substitute,\<echo\[\(.\{-}\)],let t$=\1:gosub @echo,gi
#vim %substitute,\<error\[\(.\{-}\)],let t$=\1:gosub @error,gi
#vim %substitute,\<fatal_error\[\(.\{-}\)],let t$=\1:gosub @fatal_error,gi
#vim %substitute,\<debug\[\(.\{-}\)],let t$=\1:gosub @debug,gi

#vim %substitute,\<_echoTxt_\[\(.\{-}\)],let t=\1:gosub @_echoTxt_,gi
#vim %substitute,\<_echoTxt\[\(.\{-}\)],let t=\1:gosub @_echoTxt,gi
#vim %substitute,\<echoTxt_\[\(.\{-}\)],let t=\1:gosub @echoTxt_,gi
#vim %substitute,\<echoTxt\[\(.\{-}\)],let t=\1:gosub @echoTxt,gi


// }}} ---------------------------------------------------------
// Valid function names {{{

// Function names must be substituted before variables, to prevent name
// clashes.

// Fake functions
#vim %substitute,\<\fn isCarried(,theProtagonist=location(,gi
#vim %substitute,\<\fn isNotCarried(,theProtagonist<>location(,gi
#vim %substitute,\<\fn isHere(,currentLocation=location(,gi
#vim %substitute,\<\fn isNotHere(,currentLocation<>location(,gi
# #vim %substitute@\<\fn noun\$(@fn termn$(nouns$,@gi // XXX OLD
# #vim %substitute@\<\fn name\$(@fn termn$(nouns$,@gi // XXX old
# #vim %substitute@\<\fn exitNoun\$(\(\.\{-}\))\$(@fn termn$(nouns$,\1)+fn termn$(nouns$,)@gi // XXX not used
#vim %substitute@\<\fn locationName\$(\(.\{-}\))@fn trunc$(locationName$(\1))@gi
// XXX TMP:
# #vim %substitute@\<\fn wholeNoun\$(@fn termn$(nouns$,@gi

// Actual functions
#vim %substitute,\<\(def\s\?\)\?fn aroundHere(,\1fn a(,gi
#vim %substitute,\<\(def\s\?\)\?fn between(,\1fn b(,gi
#vim %substitute,\<\(def\s\?\)\?fn winFreeCols(,\1fn c(,gi
#vim %substitute,\<\(def\s\?\)\?fn char\$(,\1fn c$(,gi
#vim %substitute,\<\(def\s\?\)\?fn dpeek(,\1fn d(,gi
#vim %substitute,\<\(def\s\?\)\?fn twoDigits\$(,\1fn d$(,gi
# #vim %substitute,\<\(def\s\?\)\?fn nounEnding\$(,\1fn e$(,gi // XXX OLD
#vim %substitute,\<\(def\s\?\)\?fn freeMemory(,\1fn f(,gi
#vim %substitute,\<\(def\s\?\)\?fn txtFile\$(,\1fn f$(,gi
#vim %substitute,\<\(def\s\?\)\?fn hour\$(,\1fn h$(,gi
#vim %substitute,\<\(def\s\?\)\?fn channel(,\1fn h(,gi
#vim %substitute,\<\(def\s\?\)\?fn instr(,\1fn i(,gi
#vim %substitute,\<\(def\s\?\)\?fn lookup8(,\1fn k(,gi
#vim %substitute,\<\(def\s\?\)\?fn lookup16(,\1fn l(,gi
# #vim %substitute,\<\(def\s\?\)\?fn noun\$(,\1fn n$(,gi  // XXX OLD
#vim %substitute,\<\(def\s\?\)\?fn name\$(,\1fn n$(,gi
#vim %substitute,\<\(def\s\?\)\?fn dpoke(,\1fn o(,gi
#vim %substitute,\<\(def\s\?\)\?fn pokeStr(,\1fn p(,gi
#vim %substitute,\<\(def\s\?\)\?fn wholeName\$(,\1fn p$(,gi
#vim %substitute,\<\(def\s\?\)\?fn random(,\1fn r(,gi
#vim %substitute,\<\(def\s\?\)\?fn seconds(,\1fn s(,gi
#vim %substitute,\<\(def\s\?\)\?fn tics(,\1fn t(,gi
# #vim %substitute,\<\(def\s\?\)\?fn thingEnding\$(,\1fn t$(,gi // XXX OLD
#vim %substitute,\<\(def\s\?\)\?fn thingArticle\$(,\1fn t$(,gi
#vim %substitute,\<\(def\s\?\)\?fn trunc\$(,\1fn u$(,gi
#vim %substitute,\<\(def\s\?\)\?fn term(,\1fn w(,gi
#vim %substitute,\<\(def\s\?\)\?fn termn$(,\1fn w$(,gi
#vim %substitute,\<\(def\s\?\)\?fn currentLocationTxt(,\1fn x(,gi
#vim %substitute,\<\(def\s\?\)\?fn winLine(,\1fn y(,gi

// }}} ---------------------------------------------------------
// Valid string variable and string array names {{{

// In Sinclar BASIC, a string variable and a string array can not use the
// same name.

#vim %substitute,\<number\$,a$,gi
// a$ is used to load the text arrays
#vim %substitute,\<command\$,c$,gi
// d$ is free
#vim %substitute,\<article\$,e$,gi
#vim %substitute,\<safecode\$,f$,gi
// g$ is free
#vim %substitute,\<player\$,h$,gi
// i$ is used as a temporary variable, 'as is' or with other names:
#vim %substitute,\<file\$,i$,gi
// #vim %substitute,\<top\$,i$,gi
#vim %substitute,\<thingsHere\$,j$,gi
#vim %substitute,\<key\$,k$,gi
#vim %substitute,\<keyAction\$,l$,gi
// #vim %substitute,\<height\$,m$,gi
#vim %substitute,\<nouns\$,n$,gi
#vim %substitute,\<torchLocations\$,o$,gi
#vim %substitute,\<accept\$,q$,gi
#vim %substitute,\<recordman\$,r$,gi
#vim %substitute,\<locationName\$,s$,gi
// t$ is used as parameter of the echo routines
# #vim %substitute,\<input\$,t$,gi // XXX OLD
# #vim %substitute,\<exam\$,u$,gi // XXX OLD
// u$ is free
#vim %substitute,\<verbs\$,v$,gi
#vim %substitute,\<theVerb\$,x$,gi
#vim %substitute,\<theNoun\$,y$,gi
// z$ is used as a temporary array
#vim %substitute,\<tmp\$,z$,gi


// }}} ---------------------------------------------------------
// Valid numeric array names {{{

# #vim %substitute,\<nounArticle(,a(,gi  // XXX OLD
#vim %substitute,\<thingArticle(,a(,gi
#vim %substitute,\<corridor(,c(,gi
#vim %substitute,\<adjacent(,d(,gi
# #vim %substitute,\<nounGender(,g(,gi  // XXX OLD
#vim %substitute,\<thingGender(,h(,gi
#vim %substitute,\<location(,l(,gi
#vim %substitute,\<done(,m(,gi
#vim %substitute,\<thingNoun(,n(,gi
#vim %substitute,\<outside(,o(,gi
#vim %substitute,\<thingNumber(,p(,gi
# #vim %substitute,\<nounNumber(,q(,gi  // XXX OLD
#vim %substitute,\<syntax(,s(,gi
#vim %substitute,\<nounThing(,t(,gi
#vim %substitute,\<oppositeDirection(,u(,gi
#vim %substitute,\<visits(,v(,gi
#vim %substitute,\<exit(,x(,gi
#vim %substitute,\<exits(,y(,gi
#vim %substitute,\<tmp(,z(,gi

// }}} ---------------------------------------------------------
// Constants {{{

// XXX TMP -- The protagonist could be an ordinary thing other things
// could be located at, but things and locations should be joined into
// one single array. At the moment, it's easier this way:
#vim %substitute,\<theProtagonist\>,-1,gi
// Note: this has to do with the protagonist's 'location' variable.
// Should the protagonist be a thing, the 'location()' array could be
// used instead.

#vim %substitute,\<true\>,1,gi
#vim %substitute,\<false\>,0,gi

#vim %substitute,\<noExit\>,0,gi
#vim %substitute,\<locked\>,100,gi

#vim %substitute,\<neuter\>,0,gi
#vim %substitute,\<masculine\>,1,gi
#vim %substitute,\<femenine\>,2,gi

#vim %substitute,\<singular\>,0,gi
#vim %substitute,\<plural\>,2,gi

// Article offsets
// These are used to point an alternative article set
// in the article$() array.
#vim %substitute,\<known\>,4,gi
#vim %substitute,\<owned\>,8,gi
#vim %substitute,\<noone\>,12,gi
#vim %substitute,\<someone\>,16,gi

// Streams 
#vim %substitute,\<fullWin\>,4,gi
#vim %substitute,\<textWin\>,5,gi
#vim %substitute,\<inputWin\>,6,gi
#vim %substitute,\<debugWin\>,7,gi
#vim %substitute,\<txtFile\>,8,gi

// Key actions
#vim %substitute,\<a_acute_char_action\>,1,gi
#vim %substitute,\<delete_char_action\>,2,gi
#vim %substitute,\<e_acute_char_action\>,3,gi
#vim %substitute,\<enter_char_action\>,4,gi
#vim %substitute,\<i_acute_char_action\>,5,gi
#vim %substitute,\<n_tilde_char_action\>,6,gi
#vim %substitute,\<next_key_action\>,7,gi
#vim %substitute,\<o_acute_char_action\>,8,gi
#vim %substitute,\<printable_char_action\>,9,gi
#vim %substitute,\<space_char_action\>,10,gi
#vim %substitute,\<u_acute_char_action\>,11,gi

// Text windows attributes
#vim %substitute,\<inputWinCPL\>,32,gi

// +3e text windows control chars (first, the embedded versions, in hex):
#vim %substitute,{winAttr},{18},gi
#vim %substitute,{winCentredJustification},{01},gi
#vim %substitute,{winCls},{0E},gi
#vim %substitute,{winFullJustification},{02},gi
#vim %substitute,{winSaveContents},{02},gi
#vim %substitute,{winRestoreContents},{03},gi
#vim %substitute,{winHome},{04},gi
#vim %substitute,{winHomeBottomLeft},{05},gi
#vim %substitute,{winInk},{10},gi
#vim %substitute,{winPaper},{11},gi
#vim %substitute,{winJustificationMode},{1E},gi
#vim %substitute,{winJustificationOff},{00},gi
#vim %substitute,{winJustificationOn},{01},gi
#vim %substitute,{winLeftJustification},{00},gi
#vim %substitute,{winTab},{17},gi
#vim %substitute,{winWash},{0F},gi
// +3e text windows control chars (second, the ordinary versions):
#vim %substitute,\<winAttr\>,24,gi
#vim %substitute,\<winCentredJustification\>,1,gi
#vim %substitute,\<winCls\>,14,gi
#vim %substitute,\<winEmbeddedCodesMode\>,31,gi
#vim %substitute,\<winEmbeddedCodesOn\>,1,gi
#vim %substitute,\<winFullJustification\>,2,gi
#vim %substitute,\<winSaveContents\>,2,gi
#vim %substitute,\<winRestoreContents\>,3,gi
#vim %substitute,\<winHome\>,4,gi
#vim %substitute,\<winHomeBottomLeft\>,5,gi
#vim %substitute,\<winInk\>,16,gi
#vim %substitute,\<winPaper\>,17,gi
#vim %substitute,\<winJustificationMode\>,30,gi
#vim %substitute,\<winJustificationOff\>,0,gi
#vim %substitute,\<winJustificationOn\>,1,gi
#vim %substitute,\<winLeftJustification\>,0,gi
#vim %substitute,\<winTab\>,23,gi
#vim %substitute,\<winWash\>,15,gi

// This value depends on the inputWin definition
// (one less than the chars per line in the window's char size):
#vim %substitute,\<maxAcceptedChars\>,32,gi

// Justified print
// This constant inits the printedLines counter;
// its value is 1 instead of 0 in order to save one
// calculation at run-time:
// XXX OLD
#vim %substitute,\<printedLinesInit\>,1,gi

// XXX OLD
# #vim %substitute,\<prompt\$,"> ",gi
# #vim %substitute,\<cursor\$,"{+8}{08}",gi

// Counts
#vim %substitute,\<totalPots\>,5,gi

// }}} ---------------------------------------------------------
// Thing identifiers and count {{{

// .............................

// This substitution modifies the #vim directives that substitute the
// thing identifiers:
#previm let b:enum=1
#previm /ThingIds\[/,/\]ThingIds/substitute,{enum},\=Enum(),gi

#vim " ThingIds[ "

// .............................
// Directions

// The cardinal points and directions must be the first identifiers,
// and they must be in the given order (north, south, east, west,
// inside and outside):

#vim %substitute,\<theNorth\>,{enum},gi
#vim %substitute,\<theSouth\>,{enum},gi
#vim %substitute,\<theEast\>,{enum},gi
#vim %substitute,\<theWest\>,{enum},gi
#vim %substitute,\<theInside\>,{enum},gi
#vim %substitute,\<theOutside\>,{enum},gi

// The order of the rest is not important:

// .............................
// Non-portable things

#vim %substitute,\<noThing\>,{enum},gI
#vim %substitute,\<theAll\>,{enum},gi
#vim %substitute,\<theBooks\>,{enum},gi
#vim %substitute,\<theDiningTables\>,{enum},gi
#vim %substitute,\<theDoor\>,{enum},gi
#vim %substitute,\<theInventory\>,{enum},gi
#vim %substitute,\<theLivingTable\>,{enum},gi
#vim %substitute,\<theNo\>,{enum},gi
#vim %substitute,\<theWallA\>,{enum},gi
#vim %substitute,\<theWallB\>,{enum},gi
#vim %substitute,\<theWallC\>,{enum},gi
#vim %substitute,\<theWallD\>,{enum},gi
#vim %substitute,\<theWallE\>,{enum},gi
#vim %substitute,\<theYes\>,{enum},gi

// .............................
// Portable things

#vim %substitute,\<firstPortable\>,theBallPen,gi

#vim %substitute,\<theBallpen\>,{enum},gi
#vim %substitute,\<theBrick\>,{enum},gi
#vim %substitute,\<theGuard\>,{enum},gi
#vim %substitute,\<theKey\>,{enum},gi
#vim %substitute,\<thePaperPiece\>,{enum},gi
#vim %substitute,\<thePaperSheet\>,{enum},gi
#vim %substitute,\<thePencil\>,{enum},gi
#vim %substitute,\<thePotA\>,{enum},gi
#vim %substitute,\<thePotB\>,{enum},gi
#vim %substitute,\<thePotC\>,{enum},gi
#vim %substitute,\<thePotD\>,{enum},gi
#vim %substitute,\<thePotE\>,{enum},gi
#vim %substitute,\<theSafe\>,{enum},gi
#vim %substitute,\<theShoe\>,{enum},gi
#vim %substitute,\<theSock\>,{enum},gi

#vim %substitute,\<lastPortable\>,theTorch,gi

#vim %substitute,\<theTorch\>,{enum},gi

// .............................
// Ambiguous things 

// Ambiguous things share a common name, so the actual thing must be
// calculated from their location or other data. E.g. there are
// several tables in different locations.

#vim %substitute,\<firstAmbiguous\>,thePotX,gi

// These substitutions must be in order (the alphabetical order of
// thing ids must match the numerical order of their values):

#vim %substitute,\<thePotX\>,{enum},gi
#vim %substitute,\<theTableX\>,{enum},gi

#vim %substitute,\<things\>,theWallX,gi // 'things' = last thing defined:

#vim %substitute,\<theWallX\>,{enum},gi

// .............................

#vim " ]ThingIds "

// }}} ---------------------------------------------------------
// Action identifiers and count {{{

// The list must be in alphabetical Order of ids, to match the values
// of the correspondent action labels defined in <ce4.vbas>.

// Note: the Vim's 'sort' command doesn't give the same result on both
// lists, because the char after the id is different. This list has to
// be manually adjusted in order to match the list in <ce4.vbas>.

// Note: the 'I' flag (to force case-sensitive substitutions) is used
// only to prevent clashes, e.g. when the identifier matchs a Spanish
// word used in the texts of the program.

// This substitution modifies the #vim directives that substitute the
// action identifiers:
#previm let b:enum=1
#previm /actionIds\[/,/\]actionIds/substitute,{enum},\=Enum(),gi

#vim " actionIds[ "

#vim %substitute,\<toDo\>,{enum},gI
#vim %substitute,\<toDrop\>,{enum},gi
#vim %substitute,\<toExamine\>,{enum},gi
#vim %substitute,\<toGo\>,{enum},gi
#vim %substitute,\<toGoEast\>,{enum},gi
#vim %substitute,\<toGoIn\>,{enum},gi
#vim %substitute,\<toGoNorth\>,{enum},gi
#vim %substitute,\<toGoOut\>,{enum},gi
#vim %substitute,\<toGoSouth\>,{enum},gi
#vim %substitute,\<toGoWest\>,{enum},gi
#vim %substitute,\<toInventory\>,{enum},gi
#vim %substitute,\<toLook\>,{enum},gi
#vim %substitute,\<toOpen\>,{enum},gi
#vim %substitute,\<toRead\>,{enum},gi
#vim %substitute,\<toShowGraphics\>,{enum},gi
#vim %substitute,\<toTake\>,{enum},gi
#vim %substitute,\<toTurnOff\>,{enum},gi
#vim %substitute,\<toTurnOn\>,{enum},gi

#ifdef debug
  #vim %substitute,\<toDebug\>,{enum},gi
#endif

#vim %substitute,\<actions\>,\=b:enum-1,gi

#vim " ]actionIds "

// }}} ---------------------------------------------------------
// Location identifiers and count {{{

// The values should not be changed, because some algorithms depend on
// them:
//
// 1) The correspondent graphic files are named after these values.
// 2) The ids from theEntranceA to theEntranceE must be defined in
// alphabetical order and their values must be consecutive.

#vim %substitute,\<theLimbo\>,0,gi

#vim %substitute,\<theBasement\>,1,gi
#vim %substitute,\<theBathroomA\>,2,gi
#vim %substitute,\<theBathroomB\>,3,gi
#vim %substitute,\<theChapel\>,4,gi
#vim %substitute,\<theClassA\>,5,gi
#vim %substitute,\<theClassB\>,6,gi
#vim %substitute,\<theCorridorA\>,7,gi
#vim %substitute,\<theCorridorB\>,8,gi
#vim %substitute,\<theCorridorC\>,9,gi
#vim %substitute,\<theCorridorD\>,10,gi
#vim %substitute,\<theCorridorE\>,11,gi
#vim %substitute,\<theCorridorF\>,12,gi
#vim %substitute,\<theDining\>,13,gi
#vim %substitute,\<theEntranceA\>,14,gi
#vim %substitute,\<theEntranceB\>,15,gi
#vim %substitute,\<theEntranceC\>,16,gi
#vim %substitute,\<theEntranceD\>,17,gi
#vim %substitute,\<theEntranceE\>,18,gi
#vim %substitute,\<theGym\>,19,gi
#vim %substitute,\<theHall\>,20,gi
#vim %substitute,\<theJunkRoom\>,21,gi
#vim %substitute,\<theKitchen\>,22,gi
#vim %substitute,\<theLarder\>,23,gi
#vim %substitute,\<theLibrary\>,24,gi
#vim %substitute,\<theLiving\>,25,gi
#vim %substitute,\<theLobby\>,26,gi
#vim %substitute,\<theOfficeA\>,27,gi
#vim %substitute,\<theOfficeB\>,28,gi
#vim %substitute,\<theOfficeC\>,29,gi
#vim %substitute,\<theReception\>,30,gi

#vim %substitute,\<locations\>,30,gi

// }}} ---------------------------------------------------------
// Shorter variables {{{

// Valid long names are shortened in order to save memory and gain a
// bit of execution speed.

// Short variables already used:
//  'i' -- a temporary variable
//  'n' -- for-next index
//  't' -- text id of the echoTxt routines

#vim %substitute,\<aKey\>,k,gi
#vim %substitute,\<action\>,a,gi
#vim %substitute,\<anExit\>,e,gi
#vim %substitute,\<banished\>,b,gi
#vim %substitute,\<carried\>,ca,gi
#vim %substitute,\<complement\>,c,gi
#vim %substitute,\<currentLocation\>,l,gi
#vim %substitute,\<cursorPos\>,cp,gi
#vim %substitute,\<direction\>,d,gi
#vim %substitute,\<exitsHere\>,eh,gi
#vim %substitute,\<fullWinBottom\>,fwb,gi
#vim %substitute,\<fullWinChars\>,fwc,gi
#vim %substitute,\<fullWinCharSize\>,fwcs,gi
#vim %substitute,\<fullWinHeight\>,fwh,gi
#vim %substitute,\<fullWinLeft\>,fwb,gi
# #vim %substitute,\<fullWinCharsPerLine\>,fwl,gi
#vim %substitute,\<fullWinTop\>,fwt,gi
#vim %substitute,\<fullWinWidth\>,fww,gi
#vim %substitute,\<gameOver\>,go,gi
#vim %substitute,\<guardMet\>,gm,gi
#vim %substitute,\<hours\>,h,gi
#vim %substitute,\<inactiveInput\>,ii,gi
#vim %substitute,\<keyAction\>,ka,gi
#vim %substitute,\<keyPot\>,kp,gi
#vim %substitute,\<listed\>,li,gi
#vim %substitute,\<lastPot\>,lp,gi
#vim %substitute,\<maxCarried\>,ma,gi
#vim %substitute,\<maxTics\>,mt,gi
#vim %substitute,\<multitasking\>,mu,gi
#vim %substitute,\<nounGender\>,ng,gi
#vim %substitute,\<nounNumber\>,nn,gi
#vim %substitute,\<printedChars\>,pc,gi
#vim %substitute,\<playingHours\>,ph,gi
#vim %substitute,\<printedLines\>,pl,gi
#vim %substitute,\<playingMinutes\>,pm,gi
#vim %substitute,\<playingSeconds\>,ps,gi
#vim %substitute,\<previousLocation\>,pl,gi
#vim %substitute,\<recordHours\>,rh,gi
#vim %substitute,\<recordMinutes\>,rm,gi
#vim %substitute,\<recordSeconds\>,rs,gi
#vim %substitute,\<safeCodeDigits\>,sd,gi
#vim %substitute,\<safeOpened\>,so,gi
#vim %substitute,\<showGraphics\>,gr,gi
#vim %substitute,\<spacePos\>,sp,gi
#vim %substitute,\<textEnd\>,te,gi
#vim %substitute,\<thingGender\>,tg,gi
#vim %substitute,\<thingsHere\>,th,gi
#vim %substitute,\<textLength\>,tl,gi
#vim %substitute,\<torchLocations\>,tlo,gi
#vim %substitute,\<thingNumber\>,tn,gi
#vim %substitute,\<totalPlayingSeconds\>,tps,gi
#vim %substitute,\<totalRecordSeconds\>,trs,gi
#vim %substitute,\<textStart\>,ts,gi
#vim %substitute,\<void\>,v,gi
#vim %substitute,\<textWinBottom\>,twb,gi
#vim %substitute,\<textWinChars\>,twc,gi
#vim %substitute,\<textWinCharSize\>,twcs,gi
#vim %substitute,\<textWinHeight\>,twh,gi
# #vim %substitute,\<textWinCharsPerLine\>,twl,gi
#vim %substitute,\<textWinLeft\>,twl,gi
#vim %substitute,\<textWinTop\>,twt,gi
#vim %substitute,\<textWinWidth\>,tww,gi
# #vim %substitute,\<winChars\>,wc,gi
#vim %substitute,\<winBottom\>,wb,gi
#vim %substitute,\<winInfo\>,wi,gi


// }}} ---------------------------------------------------------
// Memory saving {{{

# XXX TODO

# #vim %substitute,\([<>=+-/(]\)0\>,\1not pi,gi
# #vim %substitute,\([<>=+-/(]\)1\>,\1sgn pi,gi
# #vim %substitute,\([<>=+-/(]\)3\>,\1int pi,gi

# // XXX TODO -- Improve:
# // Use af Vim function to convert bytes to 'CODE "x"':

# #vim %substitute,\([<>=+-\(]\)\(\d\+\)\>,\1val"\1",gi
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted src/ce4.data_maker.bas.

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
    1 rem This file is part of
    2 rem CE4
    3 rem A text adventure in Spanish
    4 rem for the ZX Spectrum +3e with DivIDE
    5 rem Copyright (C) 2014 Marcos Cruz (programandala.net)
    6 rem Licencia/Permesilo/License:
    7 rem GPL
    8 cls
    9 load "c:"
   10 load "ce4.udg" code usr "a"
   11 print "Creando los ficheros de datos de CE4:"''
   12 go sub 14
   13 load "datapk.bas"
   14 print "Art{E}culos..."
   15 dim e$(20,8)
   16 let e$(1+0)="un"
   17 let e$(1+2)="unos"
   18 let e$(2+0)="una"
   19 let e$(2+2)="unas"
   20 let e$(1+0+4)="el"
   21 let e$(1+2+4)="los"
   22 let e$(2+0+4)="la"
   23 let e$(2+2+4)="las"
   24 let e$(1+0+8)="mi"
   25 let e$(1+2+8)="mis"
   26 let e$(2+0+8)="mi"
   27 let e$(2+2+8)="mis"
   28 let e$(1+0+12)="ning{I}n"
   29 let e$(1+2+12)="ningunos"
   30 let e$(2+0+12)="ninguna"
   31 let e$(2+2+12)="ningunas"
   32 let e$(1+0+16)="alguno"
   33 let e$(1+2+16)="algunos"
   34 let e$(2+0+16)="alguna"
   35 let e$(2+2+16)="algunas"
   36 save "c:article.dat" data e$()
   37 print "Mapa..."
   38 dim x(30,6)
   39 dim y(30)
   40 dim v(30)
   41 restore 133
   42 for n=1 to 30
   43 read l,x(l,1),x(l,2),x(l,3),x(l,4),x(l,5),x(l,6)
   44 let y(n)=(x(l,1)<>0)+(x(l,2)<>0)+(x(l,3)<>0)+(x(l,4)<>0)
   45 next n
   46 save "c:exit.dat" data x()
   47 save "c:exits.dat" data y()
   48 save "c:visits.dat" data v()
   49 dim d(30,30)
   50 for n=1 to 30
   51 for i=1 to 4
   52 let destination=x(n,i)-100*(x(n,i)>100)
   53 if destination then let d(n,destination)=i:go sub 765:let d(destination,n)=o
   54 next i
   55 next n
   56 save "c:adjacent.dat" data d()
   57 dim u(6)
   58 let u(1)=2
   59 let u(2)=1
   60 let u(3)=4
   61 let u(4)=3
   62 let u(5)=6
   63 let u(6)=5
   64 save "c:opposdir.dat" data u()
   65 print "Escenarios..."
   66 restore 732
   67 let maxLen=0
   68 read i:if not i then go to 72
   69 read i$,i
   70 if len i$>maxLen then let maxLen=len i$
   71 go to 68
   72 dim s$(30,maxLen)
   73 dim o(30)
   74 dim c(30)
   75 restore 732
   76 read i:if not i then go to 79
   77 read s$(i),o(i),c(i)
   78 go to 76
   79 save "c:locname.dat" data s$()
   80 save "c:outside.dat" data o()
   81 save "c:corridor.dat" data c()
   82 print "Cosas..."
   83 dim l(39):dim n(39):dim h(39):dim p(39):dim a(39)
   84 restore 292
   85 read i:if not i then go to 88
   86 read l(i)
   87 go to 85
   88 save "c:location.dat" data l()
   89 print "Verbos..."
   90 restore 166
   91 let v$=""
   92 read i$
   93 if not len i$ then go to 97
   94 read i
   95 let v$=v$+chr$ 0+i$+chr$ 14+chr$ i
   96 go to 92
   97 dim z$(len v$):let z$=v$
   98 save "c:verbs.dat" data z$()
   99 print "Nombres..."
  100 restore 232
  101 let nouns=0
  102 read i:if not i then go to 105
  103 read i$,i,i:let nouns=nouns+1
  104 go to 102
  105 dim t(nouns)
  106 restore 232
  107 let n$=""
  108 for n=1 to nouns
  109 read i,i$,h(i),p(i):let n$=n$+chr$ 0+i$+chr$ 14+chr$ i:let n(i)=n:let a(i)=h(i)+p(i)
  110 next n
  111 dim z$(len n$):let z$=n$
  112 save "c:nouns.dat" data z$()
  113 save "c:nthing.dat" data t()
  114 save "c:tarticle.dat" data a()
  115 save "c:tnoun.dat" data n()
  116 save "c:tgender.dat" data h()
  117 save "c:tnumber.dat" data p()
  118 print "Sintaxis..."
  119 dim s(19,39)
  120 restore 331
  121 read a,thing
  122 if not a then go to 125
  123 let s(a,thing)=1
  124 go to 121
  125 save "c:syntax.dat" data s()
  126 print "Teclado..."
  127 dim l$(256)
  128 restore 474
  129 for n=1 to 256:read k,ka:let l$(k+1)=chr$ ka:next n
  130 save "c:kaction.dat" data l$()
  131 return
  132 rem Map exits
  133 rem Data: location, north, south, east, west, in, out
  134 rem (Exits through a 100 door are marked with '+100'.)
  135 data 1,0,0,0,7,0,7
  136 data 2,0,0,0,11,0,11
  137 data 3,0,0,0,9,0,9
  138 data 4,0,0,12,0,0,12
  139 data 5,0,0,8,0,0,8
  140 data 6,0,0,9,0,0,9
  141 data 7,30,8,1,0,0,0
  142 data 8,7,9,15+100,5,0,0
  143 data 9,8,10,3,6,0,0
  144 data 10,9,11,16+100,0,0,0
  145 data 11,10,12,2,24,0,0
  146 data 12,11,13,19,4,0,0
  147 data 13,12,22,21,17+100,0,17+100
  148 data 14,15,18,26+100,0,26+100,0
  149 data 15,14,16,0,8+100,8+100,0
  150 data 16,15,17,0,10+100,10+100,0
  151 data 17,16,18,13+100,0,13+100,0
  152 data 18,14,17,0,22+100,22+100,0
  153 data 19,0,0,0,12,0,12
  154 data 20,27+100,30,29,28+100,0,30
  155 data 21,0,0,0,13,0,13
  156 data 22,13,0,18+100,23,0,18+100
  157 data 23,0,0,22,0,0,22
  158 data 24,0,0,11+100,0,0,11
  159 data 25,26,0,0,0,0,26
  160 data 26,0,25,30,14+100,0,14+100
  161 data 27,0,20+100,0,0,0,20+100
  162 data 28,0,0,20+100,0,0,20+100
  163 data 29,0,0,0,20,0,20
  164 data 30,20,7,0,26,0,26
  165 rem Verbs
  166 rem Data: "term",a id
  167 data "abre",13
  168 data "abrir",13
  169 data "apaga",17
  170 data "apagar",17
  171 data "coge",16
  172 data "coger",16
  173 data "conecta",18
  174 data "conectar",18
  175 data "deja",2
  176 data "dejar",2
  177 data "e",5
  178 data "encender",18
  179 data "enciende",18
  180 data "entra",6
  181 data "entrar",6
  182 data "este",5
  183 data "ex",3
  184 data "examina",3
  185 data "examinar",3
  186 data "g",15
  187 data "gr{A}ficos",15
  188 data "hacer",1
  189 data "haz",1
  190 data "i",11
  191 data "inspecciona",3
  192 data "inspeccionar",3
  193 data "inventariar",11
  194 data "inventario",11
  195 data "inventar{E}a",11
  196 data "ir",4
  197 data "irse",4
  198 data "largarse",4
  199 data "lee",14
  200 data "leer",14
  201 data "l{A}rgate",4
  202 data "m",12
  203 data "marchar",4
  204 data "marcharse",4
  205 data "mira",12
  206 data "mirar",12
  207 data "n",7
  208 data "norte",7
  209 data "o",10
  210 data "observa",12
  211 data "observar",12
  212 data "oeste",10
  213 data "recoge",16
  214 data "recoger",16
  215 data "registra",3
  216 data "registrar",3
  217 data "s",9
  218 data "sal",8
  219 data "salir",8
  220 data "soltar",2
  221 data "suelta",2
  222 data "sur",9
  223 data "tira",2
  224 data "tirar",2
  225 data "toma",16
  226 data "tomar",16
  227 data "ve",4
  228 data "vete",4
  229 data "d",19
  230 data ""
  231 rem Nouns
  232 rem Data: "term",thing id,noun gender,noun number
  233 rem Unambiguous nouns
  234 data 8,"todo",1,0
  235 data 21,"boli",1,0
  236 data 21,"bol{E}grafo",1,0
  237 data 9,"monta{K}a",2,0
  238 data 9,"mont{G}n",2,0
  239 data 9,"libros",1,2
  240 data 22,"ladrillo",1,0
  241 data 10,"mesas",2,2
  242 data 11,"puerta",2,0
  243 data 3,"e",1,0
  244 data 3,"este",1,0
  245 data 23,"guarda",1,0
  246 data 23,"guardia",1,0
  247 data 23,"vigilante",1,0
  248 data 5,"adentro",0,0
  249 data 5,"dentro",0,0
  250 data 12,"i",1,0
  251 data 12,"inventario",1,0
  252 data 24,"llave",2,0
  253 data 14,"no",0,0
  254 data 1,"n",1,0
  255 data 1,"norte",1,0
  256 data 6,"afuera",0,0
  257 data 6,"fuera",0,0
  258 data 25,"papelito",1,0
  259 data 26,"folio",1,0
  260 data 26,"papel",1,0
  261 data 27,"lapicero",1,0
  262 data 27,"l{A}piz",1,0
  263 data 33,"caja",2,0
  264 data 34,"zapato",1,0
  265 data 35,"calcet{E}n",1,0
  266 data 2,"s",1,0
  267 data 2,"sur",1,0
  268 data 36,"linterna",2,0
  269 data 4,"o",1,0
  270 data 4,"oeste",1,0
  271 data 20,"s{E}",0,0
  272 rem Ambiguous nouns
  273 data 38,"mesa",2,0
  274 data 13,"mesa",2,0
  275 data 39,"pared",2,0
  276 data 39,"paredes",2,2
  277 data 39,"muro",1,0
  278 data 39,"muros",1,2
  279 data 15,"muro",1,0
  280 data 16,"muro",1,0
  281 data 17,"muro",1,0
  282 data 18,"muro",1,0
  283 data 19,"muro",1,0
  284 data 37,"tiesto",1,0
  285 data 28,"tiesto",1,0
  286 data 29,"tiesto",1,0
  287 data 30,"tiesto",1,0
  288 data 31,"tiesto",1,0
  289 data 32,"tiesto",1,0
  290 data 0
  291 rem 39
  292 rem Data: thing id,location
  293 rem The directions must be the first elements defined, and in the given
  294 rem order (north, south, east, west, inside and outside):
  295 data 1,0
  296 data 2,0
  297 data 3,0
  298 data 4,0
  299 data 5,0
  300 data 6,0
  301 rem The order of the rest is not important:
  302 data 8,0
  303 data 21,0
  304 data 9,0
  305 data 22,0
  306 data 10,13
  307 data 11,0
  308 data 23,0
  309 data 12,0
  310 data 24,0
  311 data 13,25
  312 data 25,0
  313 data 26,0
  314 data 27,0
  315 data 28,14
  316 data 29,15
  317 data 30,16
  318 data 31,17
  319 data 32,18
  320 data 33,0
  321 data 34,0
  322 data 35,0
  323 data 36,-1
  324 data 15,14
  325 data 16,15
  326 data 17,16
  327 data 18,17
  328 data 19,18
  329 data 0
  330 rem Syntax
  331 rem Data: a id,thing id
  332 data 1,12
  333 data 2,8
  334 data 2,21
  335 data 2,22
  336 data 2,24
  337 data 2,25
  338 data 2,26
  339 data 2,27
  340 data 2,34
  341 data 2,35
  342 data 2,36
  343 data 3,21
  344 data 3,9
  345 data 3,22
  346 data 3,10
  347 data 3,11
  348 data 3,23
  349 data 3,5
  350 data 3,12
  351 data 3,24
  352 data 3,13
  353 data 3,1
  354 data 3,25
  355 data 3,26
  356 data 3,27
  357 data 3,28
  358 data 3,29
  359 data 3,30
  360 data 3,31
  361 data 3,32
  362 data 3,33
  363 data 3,34
  364 data 3,35
  365 data 3,36
  366 data 3,15
  367 data 3,16
  368 data 3,17
  369 data 3,18
  370 data 3,19
  371 data 4,3
  372 data 4,5
  373 data 4,1
  374 data 4,6
  375 data 4,2
  376 data 4,4
  377 data 5,7
  378 data 6,7
  379 data 7,7
  380 data 8,7
  381 data 9,7
  382 data 10,7
  383 data 11,7
  384 data 11,8
  385 data 11,12
  386 data 12,7
  387 data 12,8
  388 data 12,21
  389 data 12,9
  390 data 12,22
  391 data 12,10
  392 data 12,11
  393 data 12,3
  394 data 12,23
  395 data 12,5
  396 data 12,12
  397 data 12,24
  398 data 12,13
  399 data 12,1
  400 data 12,6
  401 data 12,25
  402 data 12,26
  403 data 12,27
  404 data 12,28
  405 data 12,29
  406 data 12,30
  407 data 12,31
  408 data 12,32
  409 data 12,33
  410 data 12,34
  411 data 12,35
  412 data 12,2
  413 data 12,36
  414 data 12,15
  415 data 12,16
  416 data 12,17
  417 data 12,18
  418 data 12,19
  419 data 12,4
  420 data 13,11
  421 data 13,33
  422 data 14,9
  423 data 14,25
  424 data 14,26
  425 data 15,7
  426 data 15,14
  427 data 15,20
  428 data 16,21
  429 data 16,22
  430 data 16,24
  431 data 16,25
  432 data 16,26
  433 data 16,27
  434 data 16,28
  435 data 16,29
  436 data 16,30
  437 data 16,31
  438 data 16,32
  439 data 16,34
  440 data 16,35
  441 data 16,36
  442 data 17,36
  443 data 18,36
  444 data 19,7
  445 data 19,8
  446 data 19,21
  447 data 19,9
  448 data 19,22
  449 data 19,10
  450 data 19,11
  451 data 19,3
  452 data 19,23
  453 data 19,5
  454 data 19,24
  455 data 19,13
  456 data 19,1
  457 data 19,6
  458 data 19,25
  459 data 19,26
  460 data 19,27
  461 data 19,28
  462 data 19,29
  463 data 19,30
  464 data 19,31
  465 data 19,32
  466 data 19,33
  467 data 19,34
  468 data 19,35
  469 data 19,2
  470 data 19,36
  471 data 19,4
  472 data 0,0
  473 rem Key 19
  474 rem Data: char code,a
  475 data 0,7
  476 data 1,7
  477 data 2,7
  478 data 3,7
  479 data 4,7
  480 data 5,7
  481 data 6,7
  482 data 7,7
  483 data 8,7
  484 data 9,7
  485 data 10,7
  486 data 11,7
  487 data 12,2
  488 data 13,4
  489 data 14,7
  490 data 15,7
  491 data 16,7
  492 data 17,7
  493 data 18,7
  494 data 19,7
  495 data 20,7
  496 data 21,7
  497 data 22,7
  498 data 23,7
  499 data 24,7
  500 data 25,7
  501 data 26,7
  502 data 27,7
  503 data 28,7
  504 data 29,7
  505 data 30,7
  506 data 31,7
  507 data 32,10
  508 data 33,7
  509 data 34,7
  510 data 35,7
  511 data 36,7
  512 data 37,7
  513 data 38,7
  514 data 39,7
  515 data 40,7
  516 data 41,7
  517 data 42,7
  518 data 43,7
  519 data 44,6
  520 data 45,7
  521 data 46,7
  522 data 47,7
  523 data 48,7
  524 data 49,7
  525 data 50,7
  526 data 51,7
  527 data 52,7
  528 data 53,7
  529 data 54,7
  530 data 55,7
  531 data 56,7
  532 data 57,7
  533 data 58,7
  534 data 59,8
  535 data 60,7
  536 data 61,7
  537 data 62,7
  538 data 63,7
  539 data 64,7
  540 data 65,9
  541 data 66,9
  542 data 67,9
  543 data 68,9
  544 data 69,9
  545 data 70,9
  546 data 71,9
  547 data 72,9
  548 data 73,9
  549 data 74,9
  550 data 75,9
  551 data 76,9
  552 data 77,9
  553 data 78,9
  554 data 79,9
  555 data 80,9
  556 data 81,9
  557 data 82,9
  558 data 83,9
  559 data 84,9
  560 data 85,9
  561 data 86,9
  562 data 87,9
  563 data 88,9
  564 data 89,9
  565 data 90,9
  566 data 91,7
  567 data 92,7
  568 data 93,7
  569 data 94,7
  570 data 95,7
  571 data 96,7
  572 data 97,9
  573 data 98,9
  574 data 99,9
  575 data 100,9
  576 data 101,9
  577 data 102,9
  578 data 103,9
  579 data 104,9
  580 data 105,9
  581 data 106,9
  582 data 107,9
  583 data 108,9
  584 data 109,9
  585 data 110,9
  586 data 111,9
  587 data 112,9
  588 data 113,9
  589 data 114,9
  590 data 115,9
  591 data 116,9
  592 data 117,9
  593 data 118,9
  594 data 119,9
  595 data 120,9
  596 data 121,9
  597 data 122,9
  598 data 123,7
  599 data 124,7
  600 data 125,7
  601 data 126,7
  602 data 127,7
  603 data 128,7
  604 data 129,7
  605 data 130,7
  606 data 131,7
  607 data 132,7
  608 data 133,7
  609 data 134,7
  610 data 135,7
  611 data 136,7
  612 data 137,7
  613 data 138,7
  614 data 139,7
  615 data 140,7
  616 data 141,7
  617 data 142,7
  618 data 143,7
  619 data 144,7
  620 data 145,7
  621 data 146,7
  622 data 147,7
  623 data 148,7
  624 data 149,7
  625 data 150,7
  626 data 151,7
  627 data 152,7
  628 data 153,7
  629 data 154,7
  630 data 155,7
  631 data 156,7
  632 data 157,7
  633 data 158,7
  634 data 159,7
  635 data 160,7
  636 data 161,7
  637 data 162,7
  638 data 163,7
  639 data 164,7
  640 data 165,7
  641 data 166,7
  642 data 167,7
  643 data 168,7
  644 data 169,7
  645 data 170,7
  646 data 171,7
  647 data 172,5
  648 data 173,7
  649 data 174,7
  650 data 175,7
  651 data 176,7
  652 data 177,7
  653 data 178,7
  654 data 179,7
  655 data 180,7
  656 data 181,7
  657 data 182,7
  658 data 183,7
  659 data 184,7
  660 data 185,7
  661 data 186,7
  662 data 187,7
  663 data 188,7
  664 data 189,7
  665 data 190,7
  666 data 191,7
  667 data 192,7
  668 data 193,7
  669 data 194,7
  670 data 195,7
  671 data 196,7
  672 data 197,11
  673 data 198,7
  674 data 199,7
  675 data 200,3
  676 data 201,7
  677 data 202,7
  678 data 203,7
  679 data 204,7
  680 data 205,7
  681 data 206,7
  682 data 207,7
  683 data 208,7
  684 data 209,7
  685 data 210,7
  686 data 211,7
  687 data 212,7
  688 data 213,7
  689 data 214,7
  690 data 215,7
  691 data 216,7
  692 data 217,7
  693 data 218,7
  694 data 219,7
  695 data 220,7
  696 data 221,7
  697 data 222,7
  698 data 223,7
  699 data 224,7
  700 data 225,7
  701 data 226,1
  702 data 227,7
  703 data 228,7
  704 data 229,7
  705 data 230,7
  706 data 231,7
  707 data 232,7
  708 data 233,7
  709 data 234,7
  710 data 235,7
  711 data 236,7
  712 data 237,7
  713 data 238,7
  714 data 239,7
  715 data 240,7
  716 data 241,7
  717 data 242,7
  718 data 243,7
  719 data 244,7
  720 data 245,7
  721 data 246,7
  722 data 247,7
  723 data 248,7
  724 data 249,7
  725 data 250,7
  726 data 251,7
  727 data 252,7
  728 data 253,7
  729 data 254,7
  730 data 255,7
  731 rem 30
  732 rem Data: location id,name,outside?,corridor?
  733 data 14,"la entrada noroeste del edificio",1,0
  734 data 15,"la entrada noreste del edificio",1,0
  735 data 16,"la entrada este del edificio",1,0
  736 data 17,"la entrada sureste del edificio",1,0
  737 data 18,"la entrada suroeste del edificio",1,0
  738 data 3,"el aseo de los profesores",0,0
  739 data 19,"el gimnasio",0,0
  740 data 23,"la despensa",0,0
  741 data 22,"la cocina",0,0
  742 data 1,"el s{G}tano",0,0
  743 data 21,"el trastero",0,0
  744 data 20,"el distribuidor",0,0
  745 data 26,"el recibidor",0,0
  746 data 30,"la recepci{G}n",0,0
  747 data 25,"la sala de visitas",0,0
  748 data 7,"el final del pasillo por el norte",0,1
  749 data 8,"el tramo norte del pasillo",0,1
  750 data 9,"el tramo central del pasillo",0,1
  751 data 10,"el tramo central del pasillo",0,1
  752 data 11,"el tramo sur del pasillo",0,1
  753 data 12,"el final del pasillo por el sur",0,1
  754 data 2,"el aseo del alumnado",0,0
  755 data 4,"la capilla",0,0
  756 data 13,"el comedor",0,0
  757 data 27,"el despacho del director",0,0
  758 data 28,"el despacho del jefe de estudios",0,0
  759 data 29,"la secretar{E}a",0,0
  760 data 5,"el aula de los alfa",0,0
  761 data 6,"el aula de los beta",0,0
  762 data 24,"la biblioteca",0,0
  763 data 0
  764 rem Tools
  765 if not(i=1) then go to 768
  766 let o=2
  767 go to 782
  768 if not(i=2) then go to 771
  769 let o=1
  770 go to 782
  771 if not(i=4) then go to 774
  772 let o=3
  773 go to 782
  774 if not(i=3) then go to 777
  775 let o=4
  776 go to 782
  777 if not(i=6) then go to 780
  778 let o=5
  779 go to 782
  780 if not(i=5) then go to 782
  781 let o=6
  782 return
  783 save "c:datamk.bas" line 1:run
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted src/ce4.data_maker.vbas.

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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
// ce4.data_maker.vbas
// (DATAMK.BAS in the ZX Spectrum +3e)

rem This file is part of
rem CE4
rem A text adventure in Spanish
rem for the ZX Spectrum +3e with DivIDE

// This tool program creates the data arrays, saves them to drive C
// and loads <C:DATAPK.BAS> (whose original source is
// <ce4.data_packer.vbas>) for packing them.

// This file was last modified: 2015-03-15

rem Copyright (C) 2014 Marcos Cruz (programandala.net)

rem Licencia/Permesilo/License:
rem GPL

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://gnu.org/licenses>.

// }}} ---------------------------------------------------------
// Requirements {{{

#include ce4.common.vbas

#filename datamk.bas
#procedureCall
#renumLine 1
#run @firstRun
#tapmaker bas2tap

// Shorter variable:
#vim %substitute,\<aLocation\>,l,gI

// }}} ---------------------------------------------------------
// Main {{{

cls
load "c:"
load "ce4.udg" code usr "a"
print "Creando los ficheros de datos de CE4:"''
makeData
load "datapk.bas"
// -- end ---

// }}} ---------------------------------------------------------
// Make the data arrays

defproc makeData

	// ...........................................

	print "Artículos..."
  dim article$(20,8)
  // This array stores articles and article-like adjectives
  // to be used with nouns depending on its gender, number,
  // and the status of the thing they are associated with.
  let article$(masculine+singular)="un"
  let article$(masculine+plural)="unos"
  let article$(femenine+singular)="una"
  let article$(femenine+plural)="unas"
  let article$(masculine+singular+known)="el"
  let article$(masculine+plural+known)="los"
  let article$(femenine+singular+known)="la"
  let article$(femenine+plural+known)="las"
  let article$(masculine+singular+owned)="mi"
  let article$(masculine+plural+owned)="mis"
  let article$(femenine+singular+owned)="mi"
  let article$(femenine+plural+owned)="mis"
  let article$(masculine+singular+noone)="ningún"
  let article$(masculine+plural+noone)="ningunos"
  let article$(femenine+singular+noone)="ninguna"
  let article$(femenine+plural+noone)="ningunas"
  let article$(masculine+singular+someone)="alguno"
  let article$(masculine+plural+someone)="algunos"
  let article$(femenine+singular+someone)="alguna"
  let article$(femenine+plural+someone)="algunas"

	save "c:article.dat" data article$()

	// ...........................................
	
	print "Mapa..."

  dim exit(locations,6) // exit locations
  dim exits(locations) // counters
  dim visits(locations) // counters
  
  restore @mapData
  for n=1 to locations
    read \
      aLocation,\
      exit(aLocation,theNorth),\
      exit(aLocation,theSouth),\
      exit(aLocation,theEast),\
      exit(aLocation,theWest),\
      exit(aLocation,theInside),\
      exit(aLocation,theOutside)
		// Keeping the count of free exits updated makes 
		// their run-time listing (with proper
		// separators and punctuation) much faster.
		// That's the reason for the exits() array.
		// XXX Note: the parens are required!
		let exits(n)=\
      (exit(aLocation,theNorth)<>0)+\
      (exit(aLocation,theSouth)<>0)+\
      (exit(aLocation,theEast)<>0)+\
      (exit(aLocation,theWest)<>0)
			// XXX TODO inside and outside
 #     (exit(aLocation,theInside)<>0)+\
 #     (exit(aLocation,theOutside)<>0)
  next n

	save "c:exit.dat" data exit()
	save "c:exits.dat" data exits()
	save "c:visits.dat" data visits()

  dim adjacent(locations,locations) // flags
  for n=1 to locations
    for i=theNorth to theWest  // XXX TODO inside and outside
      let destination=exit(n,i)-locked*(exit(n,i)>locked)
      if destination then \
        let adjacent(n,destination)=i:\
        gosub @oppositeDirection:\
        let adjacent(destination,n)=o
    next i
  next n

	save "c:adjacent.dat" data adjacent()

  dim oppositeDirection(6)
  let oppositeDirection(theNorth)=theSouth
  let oppositeDirection(theSouth)=theNorth
  let oppositeDirection(theEast)=theWest
  let oppositeDirection(theWest)=theEast
  let oppositeDirection(theInside)=theOutside
  let oppositeDirection(theOutside)=theInside

	save "c:opposdir.dat" data oppositeDirection()

	// ...........................................
	
  print "Escenarios..."

  restore @locationData
  let maxLen=0 // max length
  do
    read i:if not i then exit do
    read i$,i
    if len i$>maxLen then let maxLen=len i$
  loop
  dim locationName$(locations,maxLen)
  // XXX TODO use strings instead, to save memory:
  dim outside(locations)
  dim corridor(locations)

  restore @locationData
  do
    read i:if not i then exit do
    read \
			locationName$(i),\
      outside(i),\
      corridor(i)
  loop
  save "c:locname.dat" data locationName$()
	save "c:outside.dat" data outside()
	save "c:corridor.dat" data corridor()

	// ...........................................

	print "Cosas..." 

  dim location(things):\
	dim thingNoun(things):\
  dim thingGender(things):\
  dim thingNumber(things):\
  dim thingArticle(things)
  restore @thingData
  do
    read i:if not i then exit do
    read location(i)
  loop
	save "c:location.dat" data location()

	// ...........................................

	print "Verbos..."
  restore @verbData

	// Verbs are joined into a long string.
	// Every verb is followed by the value of its action. 
	// In order to prevent wrong matches:
	// - chr$ 0 is used as prefix for every verb term.
	// - chr$ 14 is used as prefix for the action byte.
	 
	let verbs$=""
  do
    read i$ // verb
		if not len i$ then exit do
    read i // action
		let verbs$=verbs$+chr$ 0+i$+chr$ 14+chr$ i
  loop
	dim tmp$(len verbs$):let tmp$=verbs$
	save "c:verbs.dat" data tmp$()

	// ...........................................

	print "Nombres..."

  restore @nounData
  let nouns=0 // counter
  do
    read i:if not i then exit do
    read i$,i,i:\
    let nouns=nouns+1
  loop
  dim nounThing(nouns)

  restore @nounData

	// Nouns are joined into a long string.
	// Every noun is followed by the value of its thing. 
	// In order to prevent wrong matches:
	// - chr$ 0 is used as prefix for every noun term.
	// - chr$ 14 is used as prefix for the thing byte.

	let nouns$=""
  for n=1 to nouns
    read \
			i,\ // associated thing
			i$,\ // noun
      thingGender(i),thingNumber(i):\
		let nouns$=nouns$+chr$ 0+i$+chr$ 14+chr$ i:\
		let thingNoun(i)=n:\ // associate the thing with its latest noun
		let thingArticle(i)=thingGender(i)+thingNumber(i)
  next n
	dim tmp$(len nouns$):let tmp$=nouns$
	save "c:nouns.dat" data tmp$()
	save "c:nthing.dat" data nounThing()
	save "c:tarticle.dat" data thingArticle()
	save "c:tnoun.dat" data thingNoun()
	save "c:tgender.dat" data thingGender()
	save "c:tnumber.dat" data thingNumber()
	
	// ...........................................

	print "Sintaxis..."

	// XXX TODO simpler method to store and use these data
	// XXX TODO a string array would save a lot of memory
  dim syntax(actions,things)
	restore @syntaxData
	do
		read action,thing
		if not action then exit do
		let syntax(action,thing)=true
  loop
	save "c:syntax.dat" data syntax()

	// ...........................................
	
	print "Teclado..."

  dim keyAction$(256)
  restore @keyActionData
  for n=1 to 256:\
    read aKey,keyAction:let keyAction$(aKey+1)=chr$ keyAction:\
  next n
	save "c:kaction.dat" data keyAction$()

endproc

// }}} ---------------------------------------------------------
// Data {{{

// .............................................................
rem Map exits

@mapData

rem Data: location, north, south, east, west, in, out
rem (Exits through a locked door are marked with '+locked'.)

data theBasement,noExit,noExit,noExit,theCorridorA,noExit,theCorridorA // XXX TODO change the name and description
data theBathroomA,noExit,noExit,noExit,theCorridorE,noExit,theCorridorE
data theBathroomB,noExit,noExit,noExit,theCorridorC,noExit,theCorridorC
data theChapel,noExit,noExit,theCorridorF,noExit,noExit,theCorridorF
data theClassA,noExit,noExit,theCorridorB,noExit,noExit,theCorridorB
data theClassB,noExit,noExit,theCorridorC,noExit,noExit,theCorridorC
data theCorridorA,theReception,theCorridorB,theBasement,noExit,noExit,noExit
data theCorridorB,theCorridorA,theCorridorC,theEntranceB+locked,theClassA,noExit,noExit
data theCorridorC,theCorridorB,theCorridorD,theBathroomB,theClassB,noExit,noExit
data theCorridorD,theCorridorC,theCorridorE,theEntranceC+locked,noExit,noExit,noExit
data theCorridorE,theCorridorD,theCorridorF,theBathroomA,theLibrary,noExit,noExit
data theCorridorF,theCorridorE,theDining,theGym,theChapel,noExit,noExit
data theDining,theCorridorF,theKitchen,theJunkRoom,theEntranceD+locked,noExit,theEntranceD+locked
data theEntranceA,theEntranceB,theEntranceE,theLobby+locked,noExit,theLobby+locked,noExit
data theEntranceB,theEntranceA,theEntranceC,noExit,theCorridorB+locked,theCorridorB+locked,noExit
data theEntranceC,theEntranceB,theEntranceD,noExit,theCorridorD+locked,theCorridorD+locked,noExit
data theEntranceD,theEntranceC,theEntranceE,theDining+locked,noExit,theDining+locked,noExit
data theEntranceE,theEntranceA,theEntranceD,noExit,theKitchen+locked,theKitchen+locked,noExit
data theGym,noExit,noExit,noExit,theCorridorF,noExit,theCorridorF
data theHall,theOfficeA+locked,theReception,theOfficeC,theOfficeB+locked,noExit,theReception
data theJunkRoom,noExit,noExit,noExit,theDining,noExit,theDining // XXX TODO move to a better place in the map
data theKitchen,theDining,noExit,theEntranceE+locked,theLarder,noExit,theEntranceE+locked
data theLarder,noExit,noExit,theKitchen,noExit,noExit,theKitchen
data theLibrary,noExit,noExit,theCorridorE+locked,noExit,noExit,theCorridorE
data theLiving,theLobby,noExit,noExit,noExit,noExit,theLobby
data theLobby,noExit,theLiving,theReception,theEntranceA+locked,noExit,theEntranceA+locked
data theOfficeA,noExit,theHall+locked,noExit,noExit,noExit,theHall+locked
data theOfficeB,noExit,noExit,theHall+locked,noExit,noExit,theHall+locked
data theOfficeC,noExit,noExit,noExit,theHall,noExit,theHall
data theReception,theHall,theCorridorA,noExit,theLobby,noExit,theLobby

// .............................................................
rem Verbs

@verbData

rem Data: "term",action id

data "abre",toOpen
data "abrir",toOpen
data "apaga",toTurnOff
data "apagar",toTurnOff
data "coge",toTake
data "coger",toTake
data "conecta",toTurnOn
data "conectar",toTurnOn
data "deja",toDrop
data "dejar",toDrop
# data "dirigirse",toGo
# data "dirígete",toGo
data "e",toGoEast
# data "encaminarse",toGo
# data "encamínate",toGo
data "encender",toTurnOn
data "enciende",toTurnOn
data "entra",toGoIn
data "entrar",toGoIn
data "este",toGoEast
data "ex",toExamine
data "examina",toExamine
data "examinar",toExamine
data "g",toShowGraphics
data "gráficos",toShowGraphics
data "hacer",toDo
data "haz",toDo
data "i",toInventory
data "inspecciona",toExamine
data "inspeccionar",toExamine
data "inventariar",toInventory
data "inventario",toInventory
data "inventaría",toInventory
data "ir",toGo
data "irse",toGo
data "largarse",toGo
data "lee",toRead
data "leer",toRead
data "lárgate",toGo
data "m",toLook
data "marchar",toGo
data "marcharse",toGo
data "mira",toLook
data "mirar",toLook
data "n",toGoNorth
data "norte",toGoNorth
data "o",toGoWest
data "observa",toLook
data "observar",toLook
data "oeste",toGoWest
data "recoge",toTake
data "recoger",toTake
data "registra",toExamine
data "registrar",toExamine
data "s",toGoSouth
data "sal",toGoOut
data "salir",toGoOut
data "soltar",toDrop
data "suelta",toDrop
data "sur",toGoSouth
data "tira",toDrop
data "tirar",toDrop
data "toma",toTake
data "tomar",toTake
data "ve",toGo
data "vete",toGo

#ifdef debug
  data "d",toDebug
#endif

data "" // end of data

// .............................................................
rem Nouns

// Nouns are associated with things. Several nouns can be associated
// with one thing, and one noun can be associated with several things.
// This is how it works and how the data must be organized:
//
// When several nouns are associated with one thing, the last noun in
// the data list will be the default one for the thing.
//
// Example: See "boli" and and "bolígrafo" below, two words for
// "ballpen" in Spanish.
//
// When one noun is associated with several things, the noun is
// associated with an ambiguous thing, a fake thing id, whose actual
// value will be calculated at runtime, depending on the current
// location and other variables. The id of an ambiguous things use the
// "X" suffix.
//
// In order to set the default noun of every calculated thing, the
// noun data is repeated after the association with the ambiguous
// thing.
//
// Example: First, the term "mesa" (table is Spanish) is associated
// with the ambiguous thing 'theTableX'. This first association will
// be found by the parser and the proper routine will be called in
// order to calculate the actual thing, 'theLivingTable' or
// 'theDiningTable', depending on the current location.  Second,
// "mesa" is associated also with the thing 'theLivingTable', what
// makes "mesa" the default noun of 'theLivingTable' thing.

@nounData

rem Data: "term",thing id,noun gender,noun number

rem Unambiguous nouns

data theAll,"todo",masculine,singular
data theBallpen,"boli",masculine,singular
data theBallpen,"bolígrafo",masculine,singular
data theBooks,"montaña",femenine,singular
data theBooks,"montón",femenine,singular
data theBooks,"libros",masculine,plural
data theBrick,"ladrillo",masculine,singular
data theDiningTables,"mesas",femenine,plural
data theDoor,"puerta",femenine,singular
data theEast,"e",masculine,singular
data theEast,"este",masculine,singular
data theGuard,"guarda",masculine,singular
data theGuard,"guardia",masculine,singular
data theGuard,"vigilante",masculine,singular
data theInside,"adentro",neuter,singular
data theInside,"dentro",neuter,singular
data theInventory,"i",masculine,singular
data theInventory,"inventario",masculine,singular
data theKey,"llave",femenine,singular
data theNo,"no",neuter,singular
data theNorth,"n",masculine,singular
data theNorth,"norte",masculine,singular
data theOutside,"afuera",neuter,singular
data theOutside,"fuera",neuter,singular
data thePaperPiece,"papelito",masculine,singular
data thePaperSheet,"folio",masculine,singular
data thePaperSheet,"papel",masculine,singular
data thePencil,"lapicero",masculine,singular
data thePencil,"lápiz",masculine,singular
data theSafe,"caja",femenine,singular
data theShoe,"zapato",masculine,singular
data theSock,"calcetín",masculine,singular
data theSouth,"s",masculine,singular
data theSouth,"sur",masculine,singular
data theTorch,"linterna",femenine,singular
data theWest,"o",masculine,singular
data theWest,"oeste",masculine,singular
data theYes,"sí",neuter,singular

rem Ambiguous nouns

// Note: the first association in every group must be the ambiguous
// one (the one with the X-suffix identifier). This will be the first
// one found by the parser.

data theTableX,"mesa",femenine,singular
data theLivingTable,"mesa",femenine,singular

data theWallX,"pared",femenine,singular
data theWallX,"paredes",femenine,plural
data theWallX,"muro",masculine,singular
data theWallX,"muros",masculine,plural
data theWallA,"muro",masculine,singular
data theWallB,"muro",masculine,singular
data theWallC,"muro",masculine,singular
data theWallD,"muro",masculine,singular
data theWallE,"muro",masculine,singular

data thePotX,"tiesto",masculine,singular
data thePotA,"tiesto",masculine,singular
data thePotB,"tiesto",masculine,singular
data thePotC,"tiesto",masculine,singular
data thePotD,"tiesto",masculine,singular
data thePotE,"tiesto",masculine,singular

data 0 // end of data

// .............................................................
rem Things 

@thingData

rem Data: thing id,location

rem The directions must be the first elements defined, and in the given
rem order (north, south, east, west, inside and outside):

data theNorth,theLimbo
data theSouth,theLimbo
data theEast,theLimbo
data theWest,theLimbo
data theInside,theLimbo
data theOutside,theLimbo

rem The order of the rest is not important:

data theAll,theLimbo
data theBallpen,theLimbo
data theBooks,theLimbo
data theBrick,theLimbo
data theDiningTables,theDining
data theDoor,theLimbo
data theGuard,theLimbo
data theInventory,theLimbo
data theKey,theLimbo
data theLivingTable,theLiving
data thePaperPiece,theLimbo
data thePaperSheet,theLimbo
data thePencil,theLimbo
data thePotA,theEntranceA
data thePotB,theEntranceB
data thePotC,theEntranceC
data thePotD,theEntranceD
data thePotE,theEntranceE
data theSafe,theLimbo
data theShoe,theLimbo
data theSock,theLimbo
data theTorch,theProtagonist
data theWallA,theEntranceA
data theWallB,theEntranceB
data theWallC,theEntranceC
data theWallD,theEntranceD
data theWallE,theEntranceE

data 0 // end of data

// .............................................................
rem Syntax

// These data define what actions and things (complements) can be
// combined in a user command. Actions that can be used without a
// complement use the special thing id 'noThing'.
//
// These data are used as a first filter, before executing the
// specific code of the action. Depending on the action, it can be
// useful to use this primary filter or to make the checks in the
// action code itself.

@syntaxData

rem Data: action id,thing id

data toDo,theInventory
data toDrop,theAll
data toDrop,theBallpen
data toDrop,theBrick
data toDrop,theKey
data toDrop,thePaperPiece
data toDrop,thePaperSheet
data toDrop,thePencil
data toDrop,theShoe
data toDrop,theSock
data toDrop,theTorch
data toExamine,theBallpen
data toExamine,theBooks
data toExamine,theBrick
data toExamine,theDiningTables
data toExamine,theDoor
data toExamine,theGuard
data toExamine,theInside
data toExamine,theInventory
data toExamine,theKey
data toExamine,theLivingTable
data toExamine,theNorth
data toExamine,thePaperPiece
data toExamine,thePaperSheet
data toExamine,thePencil
data toExamine,thePotA
data toExamine,thePotB
data toExamine,thePotC
data toExamine,thePotD
data toExamine,thePotE
data toExamine,theSafe
data toExamine,theShoe
data toExamine,theSock
data toExamine,theTorch
data toExamine,theWallA
data toExamine,theWallB
data toExamine,theWallC
data toExamine,theWallD
data toExamine,theWallE
data toGo,theEast
data toGo,theInside
data toGo,theNorth
data toGo,theOutside
data toGo,theSouth
data toGo,theWest
data toGoEast,noThing
data toGoIn,noThing
data toGoNorth,noThing
data toGoOut,noThing
data toGoSouth,noThing
data toGoWest,noThing
data toInventory,noThing
data toInventory,theAll
data toInventory,theInventory
data toLook,noThing
data toLook,theAll
data toLook,theBallpen
data toLook,theBooks
data toLook,theBrick
data toLook,theDiningTables
data toLook,theDoor
data toLook,theEast
data toLook,theGuard
data toLook,theInside
data toLook,theInventory
data toLook,theKey
data toLook,theLivingTable
data toLook,theNorth
data toLook,theOutside
data toLook,thePaperPiece
data toLook,thePaperSheet
data toLook,thePencil
data toLook,thePotA
data toLook,thePotB
data toLook,thePotC
data toLook,thePotD
data toLook,thePotE
data toLook,theSafe
data toLook,theShoe
data toLook,theSock
data toLook,theSouth
data toLook,theTorch
data toLook,theWallA
data toLook,theWallB
data toLook,theWallC
data toLook,theWallD
data toLook,theWallE
data toLook,theWest
data toOpen,theDoor
data toOpen,theSafe
data toRead,theBooks
data toRead,thePaperPiece
data toRead,thePaperSheet
data toShowGraphics,noThing
data toShowGraphics,theNo
data toShowGraphics,theYes
data toTake,theBallpen
data toTake,theBrick
data toTake,theKey
data toTake,thePaperPiece
data toTake,thePaperSheet
data toTake,thePencil
data toTake,thePotA
data toTake,thePotB
data toTake,thePotC
data toTake,thePotD
data toTake,thePotE
data toTake,theShoe
data toTake,theSock
data toTake,theTorch
data toTurnOff,theTorch
data toTurnOn,theTorch

#ifdef debug
  data toDebug,noThing
  data toDebug,theAll
  data toDebug,theBallpen
  data toDebug,theBooks
  data toDebug,theBrick
  data toDebug,theDiningTables
  data toDebug,theDoor
  data toDebug,theEast
  data toDebug,theGuard
  data toDebug,theInside
  data toDebug,theKey
  data toDebug,theLivingTable
  data toDebug,theNorth
  data toDebug,theOutside
  data toDebug,thePaperPiece
  data toDebug,thePaperSheet
  data toDebug,thePencil
  data toDebug,thePotA
  data toDebug,thePotB
  data toDebug,thePotC
  data toDebug,thePotD
  data toDebug,thePotE
  data toDebug,theSafe
  data toDebug,theShoe
  data toDebug,theSock
  data toDebug,theSouth
  data toDebug,theTorch
  data toDebug,theWest
#endif

data 0,0 // end of data

// .............................................................
rem Key actions

// These data configure the action of every key pressed by the player
// during the command input. This way control chars and Spanish
// letters are implemented.

@keyActionData

rem Data: char code,action

data 0,next_key_action
data 1,next_key_action
data 2,next_key_action
data 3,next_key_action
data 4,next_key_action
data 5,next_key_action
data 6,next_key_action
data 7,next_key_action
data 8,next_key_action
data 9,next_key_action
data 10,next_key_action
data 11,next_key_action
data 12,delete_char_action
data 13,enter_char_action
data 14,next_key_action
data 15,next_key_action
data 16,next_key_action
data 17,next_key_action
data 18,next_key_action
data 19,next_key_action
data 20,next_key_action
data 21,next_key_action
data 22,next_key_action
data 23,next_key_action
data 24,next_key_action
data 25,next_key_action
data 26,next_key_action
data 27,next_key_action
data 28,next_key_action
data 29,next_key_action
data 30,next_key_action
data 31,next_key_action
data 32,space_char_action
data 33,next_key_action
data 34,next_key_action
data 35,next_key_action
data 36,next_key_action
data 37,next_key_action
data 38,next_key_action
data 39,next_key_action
data 40,next_key_action
data 41,next_key_action
data 42,next_key_action
data 43,next_key_action
data 44,n_tilde_char_action
data 45,next_key_action
data 46,next_key_action
data 47,next_key_action
data 48,next_key_action
data 49,next_key_action
data 50,next_key_action
data 51,next_key_action
data 52,next_key_action
data 53,next_key_action
data 54,next_key_action
data 55,next_key_action
data 56,next_key_action
data 57,next_key_action
data 58,next_key_action
data 59,o_acute_char_action
data 60,next_key_action
data 61,next_key_action
data 62,next_key_action
data 63,next_key_action
data 64,next_key_action
data 65,printable_char_action
data 66,printable_char_action
data 67,printable_char_action
data 68,printable_char_action
data 69,printable_char_action
data 70,printable_char_action
data 71,printable_char_action
data 72,printable_char_action
data 73,printable_char_action
data 74,printable_char_action
data 75,printable_char_action
data 76,printable_char_action
data 77,printable_char_action
data 78,printable_char_action
data 79,printable_char_action
data 80,printable_char_action
data 81,printable_char_action
data 82,printable_char_action
data 83,printable_char_action
data 84,printable_char_action
data 85,printable_char_action
data 86,printable_char_action
data 87,printable_char_action
data 88,printable_char_action
data 89,printable_char_action
data 90,printable_char_action
data 91,next_key_action
data 92,next_key_action
data 93,next_key_action
data 94,next_key_action
data 95,next_key_action
data 96,next_key_action
data 97,printable_char_action
data 98,printable_char_action
data 99,printable_char_action
data 100,printable_char_action
data 101,printable_char_action
data 102,printable_char_action
data 103,printable_char_action
data 104,printable_char_action
data 105,printable_char_action
data 106,printable_char_action
data 107,printable_char_action
data 108,printable_char_action
data 109,printable_char_action
data 110,printable_char_action
data 111,printable_char_action
data 112,printable_char_action
data 113,printable_char_action
data 114,printable_char_action
data 115,printable_char_action
data 116,printable_char_action
data 117,printable_char_action
data 118,printable_char_action
data 119,printable_char_action
data 120,printable_char_action
data 121,printable_char_action
data 122,printable_char_action
data 123,next_key_action
data 124,next_key_action
data 125,next_key_action
data 126,next_key_action
data 127,next_key_action
data 128,next_key_action
data 129,next_key_action
data 130,next_key_action
data 131,next_key_action
data 132,next_key_action
data 133,next_key_action
data 134,next_key_action
data 135,next_key_action
data 136,next_key_action
data 137,next_key_action
data 138,next_key_action
data 139,next_key_action
data 140,next_key_action
data 141,next_key_action
data 142,next_key_action
data 143,next_key_action
data 144,next_key_action
data 145,next_key_action
data 146,next_key_action
data 147,next_key_action
data 148,next_key_action
data 149,next_key_action
data 150,next_key_action
data 151,next_key_action
data 152,next_key_action
data 153,next_key_action
data 154,next_key_action
data 155,next_key_action
data 156,next_key_action
data 157,next_key_action
data 158,next_key_action
data 159,next_key_action
data 160,next_key_action
data 161,next_key_action
data 162,next_key_action
data 163,next_key_action
data 164,next_key_action
data 165,next_key_action
data 166,next_key_action
data 167,next_key_action
data 168,next_key_action
data 169,next_key_action
data 170,next_key_action
data 171,next_key_action
data 172,i_acute_char_action
data 173,next_key_action
data 174,next_key_action
data 175,next_key_action
data 176,next_key_action
data 177,next_key_action
data 178,next_key_action
data 179,next_key_action
data 180,next_key_action
data 181,next_key_action
data 182,next_key_action
data 183,next_key_action
data 184,next_key_action
data 185,next_key_action
data 186,next_key_action
data 187,next_key_action
data 188,next_key_action
data 189,next_key_action
data 190,next_key_action
data 191,next_key_action
data 192,next_key_action
data 193,next_key_action
data 194,next_key_action
data 195,next_key_action
data 196,next_key_action
data 197,u_acute_char_action
data 198,next_key_action
data 199,next_key_action
data 200,e_acute_char_action
data 201,next_key_action
data 202,next_key_action
data 203,next_key_action
data 204,next_key_action
data 205,next_key_action
data 206,next_key_action
data 207,next_key_action
data 208,next_key_action
data 209,next_key_action
data 210,next_key_action
data 211,next_key_action
data 212,next_key_action
data 213,next_key_action
data 214,next_key_action
data 215,next_key_action
data 216,next_key_action
data 217,next_key_action
data 218,next_key_action
data 219,next_key_action
data 220,next_key_action
data 221,next_key_action
data 222,next_key_action
data 223,next_key_action
data 224,next_key_action
data 225,next_key_action
data 226,a_acute_char_action
data 227,next_key_action
data 228,next_key_action
data 229,next_key_action
data 230,next_key_action
data 231,next_key_action
data 232,next_key_action
data 233,next_key_action
data 234,next_key_action
data 235,next_key_action
data 236,next_key_action
data 237,next_key_action
data 238,next_key_action
data 239,next_key_action
data 240,next_key_action
data 241,next_key_action
data 242,next_key_action
data 243,next_key_action
data 244,next_key_action
data 245,next_key_action
data 246,next_key_action
data 247,next_key_action
data 248,next_key_action
data 249,next_key_action
data 250,next_key_action
data 251,next_key_action
data 252,next_key_action
data 253,next_key_action
data 254,next_key_action
data 255,next_key_action

// .............................................................
rem Locations

@locationData

rem Data: location id,name,outside?,corridor?

data theEntranceA,"la entrada noroeste del edificio",true,false
data theEntranceB,"la entrada noreste del edificio",true,false
data theEntranceC,"la entrada este del edificio",true,false
data theEntranceD,"la entrada sureste del edificio",true,false
data theEntranceE,"la entrada suroeste del edificio",true,false
data theBathroomB,"el aseo de los profesores",false,false
data theGym,"el gimnasio",false,false
data theLarder,"la despensa",false,false
data theKitchen,"la cocina",false,false
data theBasement,"el sótano",false,false
data theJunkRoom,"el trastero",false,false
data theHall,"el distribuidor",false,false
data theLobby,"el recibidor",false,false
data theReception,"la recepción",false,false
data theLiving,"la sala de visitas",false,false
data theCorridorA,"el final del pasillo por el norte",false,true
data theCorridorB,"el tramo norte del pasillo",false,true
data theCorridorC,"el tramo central del pasillo",false,true
data theCorridorD,"el tramo central del pasillo",false,true
data theCorridorE,"el tramo sur del pasillo",false,true
data theCorridorF,"el final del pasillo por el sur",false,true
data theBathroomA,"el aseo del alumnado",false,false
data theChapel,"la capilla",false,false
data theDining,"el comedor",false,false
data theOfficeA,"el despacho del director",false,false
data theOfficeB,"el despacho del jefe de estudios",false,false
data theOfficeC,"la secretaría",false,false
data theClassA,"el aula de los alfa",false,false
data theClassB,"el aula de los beta",false,false
data theLibrary,"la biblioteca",false,false

data 0 // end of data

// }}} ---------------------------------------------------------
rem Tools

@oppositeDirection
  // Input:  i
  // Output: o
  if i=theNorth then
    let o=theSouth
  else if i=theSouth then
    let o=theNorth
  else if i=theWest then
    let o=theEast
  else if i=theEast then
    let o=theWest
  else if i=theOutside then
    let o=theInside
  else if i=theInside then
    let o=theOutside
  endif
  return 

// }}} ---------------------------------------------------------
// Meta {{{

@firstRun
save "c:datamk.bas" line 1:run

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted src/ce4.data_packer.bas.

1
2
    1 clear:load "c:":load "ce4.udg" code usr "a":print "Cargando los ficheros de datos";:load "adjacent.dat" data d():print ".";:load "article.dat" data e$():print ".";:load "corridor.dat" data c():print ".";:load "exit.dat" data x():print ".";:load "exits.dat" data y():print ".";:load "kaction.dat" data l$():print ".";:load "location.dat" data l():print ".";:load "locname.dat" data s$():print ".";:load "nouns.dat" data n$():print ".";:load "nthing.dat" data t():print ".";:load "opposdir.dat" data u():print ".";:load "outside.dat" data o():print ".";:load "syntax.dat" data s():print ".";:load "tarticle.dat" data a():print ".";:load "tgender.dat" data h():print ".";:load "tnoun.dat" data n():print ".";:load "tnumber.dat" data p():print ".";:load "verbs.dat" data v$():print ".";:load "visits.dat" data v():print ".";:print ''"Los datos est{A}n cargados."'"Ahora borra las dos l{E}neas"'"del programa y gr{A}balo con:"'"   save ""data.bas"""'"Despu{C}s puedes reiniciar.":stop
    2 save "c:datapk.bas" line 1:run
<
<




Deleted src/ce4.data_packer.vbas.

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
// ce4.data_packer.vbas
// (DATAPK.BAS in the ZX Spectrum +3e)

// This file is part of
// CE4
// A text adventure in Spanish
// for the ZX Spectrum +3e with DivIDE

// This tool program loads the data arrays from disk, as created by
// <ce4.data_maker.vbas> (<C:DATAMAKE.BAS> in the ZX Spectrum's disk),
// and saves them packed in an empty BASIC program. The user must do
// the final step of the proccess: delete the program lines and save
// the program.

// This file was last modified: 2015-03-15

// Copyright (C) 2014 Marcos Cruz (programandala.net)
// Licencia/Permesilo/License: GPL 3

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://gnu.org/licenses>.

#include ce4.common.vbas

#filename datapk.bas
#renumLine 1
#run @firstRun
#tapmaker bas2tap

// XXX TODO use machine code to remove the lines at the end

clear:\
load "c:":\
load "ce4.udg" code usr "a":\
print "Cargando los ficheros de datos";:\
load "adjacent.dat" data adjacent():print ".";:\
load "article.dat" data article$():print ".";:\
load "corridor.dat" data corridor():print ".";:\
load "exit.dat" data exit():print ".";:\
load "exits.dat" data exits():print ".";:\
load "kaction.dat" data keyAction$():print ".";:\
load "location.dat" data location():print ".";:\
load "locname.dat" data locationName$():print ".";:\
# load "narticle.dat" data nounArticle():print ".";:\ // XXX OLD
# load "ngender.dat" data nounGender():print ".";:\ // XXX OLD
# load "nnumber.dat" data nounNumber():print ".";:\ // XXX OLD
load "nouns.dat" data nouns$():print ".";:\
load "nthing.dat" data nounThing():print ".";:\
load "opposdir.dat" data oppositeDirection():print ".";:\
load "outside.dat" data outside():print ".";:\
load "syntax.dat" data syntax():print ".";:\
load "tarticle.dat" data thingArticle():print ".";:\
load "tgender.dat" data thingGender():print ".";:\
load "tnoun.dat" data thingNoun():print ".";:\
load "tnumber.dat" data thingNumber():print ".";:\
load "verbs.dat" data verbs$():print ".";:\
load "visits.dat" data visits():print ".";:\
print ''\
"Los datos están cargados."'\
"Ahora borra las dos líneas"'\
"del programa y grábalo con:"'\
"   save ""data.bas"""'\
"Después puedes reiniciar.":\
stop

// }}} ---------------------------------------------------------
// Meta {{{

@firstRun
save "c:datapk.bas" line 1:run
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































Deleted src/ce4.disk.bas.

1
2
3
4
5
6
7
    1 REM CE4 Loader
    2 REM By Marcos Cruz (programandala.net)
    3 border 0: paper 0: ink 4: spectrum attr 4 asn
    4 move "c:" out : move "c:" in "program"
    5 move "g:" out : move "g:" in "graphics"
    6 load "menu.bas"
    7 save "a:disk" line 1
<
<
<
<
<
<
<














Deleted src/ce4.disk.vbas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
REM CE4 Loader
REM By Marcos Cruz (programandala.net)

#filename DISK
#tapmaker zmakebas
#run 1

border 0: paper 0: ink 4: spectrum attr 4 asn 
move "c:" out : move "c:" in "program"
move "g:" out : move "g:" in "graphics"
load "menu.bas"
save "a:disk" line 1

// Change log
//
// 2014-08: StartLabel
//
// 2015-02-26: New version. Extracted as a text file, to be converted
// with zmakebas (bas2tap fails with the MOVE "c:" OUT).
//
// 2015-03-01: Converted to Vimclair BASIC; the new '#tapmaker'
// directive is used.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































Deleted src/ce4.fn_txtfile.vbas.

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
// ce4.fn_txtfile.vbas

rem This file is part of
rem CE4
rem A text adventure in Spanish
rem for the ZX Spectrum +3e with DivIDE

// This file contains the BASIC function textFile$()

// This file was last modified: 2015-03-04

rem Copyright (C) 2015 Marcos Cruz (programandala.net)

rem Licencia/Permesilo/License:
rem GPL

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://gnu.org/licenses>.

def fn txtFile$(n)=\
  // File name of the given text id
  str$ n+".txt"


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































Deleted src/ce4.menu.bas.

1
2
3
4
5
6
7
8
9
10
11
12
    1 rem CE4 development disk menu
    2 rem This file is part of CE4
    3 rem (http:
    4 rem Copyright (c) 2014,2015 Marcos Cruz (programandala.net)
    6 cls:print "Proyecto CE4"''"  escrito en Vimclair BASIC"'"  para ZX Spectrum +3e"'"  por programandala.net"''"Opciones:"''inverse 1;"A";inverse 0;"rrancar"'"Actualizar ";inverse 1;"p";inverse 0;"rograma y arrancar"'"Actualizar ";inverse 1;"d";inverse 0;"atos"'"Actualizar ";inverse 1;"t";inverse 0;"extos y arrancar"'"Ver las ";inverse 1;"u";inverse 0;"nidades asignadas"
    7 pause 0:let k$=inkey$
    8 if k$="a" then load "c:ce4.bas"
    9 if k$="p" then cls:copy "a:ce4.bas" to "c:":load "c:ce4.bas"
   10 if k$="d" then cls:copy "a:ce4.*" to "c:":copy "a:data*.bas" to "c:":load "c:datamk.bas"
   11 if k$="t" then cls:copy "a:ce4.*" to "c:":copy "a:textmk.bas" to "c:":load "c:textmk.bas"
   12 if k$="u" then cls:print "Unidades asignadas:"'':cat asn:print '"Pulsa una tecla para regresar":pause 0:go sub 6
   13 go to 5
<
<
<
<
<
<
<
<
<
<
<
<
























Deleted src/ce4.menu.vbas.

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
rem CE4 development disk menu
rem This file is part of CE4
// XXX FIXME  bas2tap omits everything after "http:" in the line:
rem (http://programandala.net/es.programa.ce4.html)
rem Copyright (c) 2014,2015 Marcos Cruz (programandala.net)

// Change history: at the end of the file

#filename MENU.BAS
#renumLine 1
#run 1
#tapmaker bas2tap

do

  @menu
    cls:\
    print \
      "Proyecto CE4"''\
      "  escrito en Vimclair BASIC"'\
      "  para ZX Spectrum +3e"'\
      "  por programandala.net"''\
      "Opciones:"''\
      inverse 1;"A";inverse 0;"rrancar"'\
      "Actualizar ";inverse 1;"p";inverse 0;"rograma y arrancar"'\
      "Actualizar ";inverse 1;"d";inverse 0;"atos"'\
      "Actualizar ";inverse 1;"t";inverse 0;"extos y arrancar"'\
      "Ver las ";inverse 1;"u";inverse 0;"nidades asignadas"

    pause 0:\
    let k$=inkey$

    if k$="a" then \
      load "c:ce4.bas"

    if k$="p" then \
      cls:\
      copy "a:ce4.bas" to "c:":\
      load "c:ce4.bas"

    if k$="d" then \
      cls:\
      copy "a:ce4.*" to "c:":\
      copy "a:data*.bas" to "c:":\
      load "c:datamk.bas"
    
    if k$="t" then \
      cls:\
      copy "a:ce4.*" to "c:":\
      copy "a:textmk.bas" to "c:":\
      load "c:textmk.bas"

    if k$="u" then \
      cls:\
      print "Unidades asignadas:"'':\
      cat asn:\
      print '"Pulsa una tecla para regresar":\
      pause 0:\
      gosub @menu

loop

// ***********************
// Change history

// 2014-08-07: First version.
//
// 2014-08-09: Improved.
//
// 2015-02-24: New menu options to copy from drive b: and run the
// installers from c:.  Improved menu, the look and the options.
//
// 2015-02-26: Extracted as a text file, to be converted with bas2tap.
// (zmakebas fails with the parameters of fn o$)a.
//
// 2015-02-27: Converted to Vimclair BASIC.
//
// 2015-03-01: Changes in the menu texts.
//
// 2015-03-04: Rewritten in Spanish. Menu rearranged. New option to
// install the texts and UDG.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































































Deleted src/ce4.text_maker.bas.

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
    1 rem This file is part of
    2 rem CE4
    3 rem A text adventure in Spanish
    4 rem for the ZX Spectrum +3e with DivIDE
    5 rem Copyright (C) 2015 Marcos Cruz (programandala.net)
    6 rem Licencia/Permesilo/License:
    7 rem GPL
    8 cls
    9 print "Actualizando los textos";
   10 go sub 20
   11 load "c:ce4.bas"
   12 rem This file is part of
   13 rem CE4
   14 rem A text adventure in Spanish
   15 rem for the ZX Spectrum +3e with DivIDE
   16 rem Copyright (C) 2015 Marcos Cruz (programandala.net)
   17 rem Licencia/Permesilo/License:
   18 rem GPL
   19 def fn f$(n)=str$ n+".txt"
   20 save "c:":restore 28
   21 let t$="":read fileId:if not fileId then return
   22 read i$:if i$=chr$ 13 then go to 25
   23 let t$=t$+(" " and len t$)+i$
   24 go to 22
   25 dim a$(len t$):let a$=t$:save fn f$(fileId) data a$():print ".";
   26 go to 21
   27 return
   28 data 25
   29 data "La triste mesa y sus tres esquel{C}ticas e inc{G}modas sillas,"
   30 data "le dan a esta salita de visitas el aspecto de la sala de interrogatorios"
   31 data "que realmente es."
   32 data "En una de las desnudas paredes hay un peque{K}o y sucio ventanuco"
   33 data "por el que, cuando es de d{E}a, con gran esfuerzo, logran entrar"
   34 data "uno o dos agotados rayos de luz."
   35 data chr$ 13
   36 data 100+25
   37 data "Llamada {R}sala de interrogatorios{S}."
   38 data chr$ 13
   39 data 20
   40 data "Una diminuta pieza que comunica los despachos entre s{E}."
   41 data "Es tan peque{K}a que la llamamos {R}la cabina{S}, como la peli;"
   42 data "y tambi{C}n porque aqu{E},"
   43 data "cuando el director te llama a su despacho para nada bueno,"
   44 data "te hacen esperar de pie, sin lugar donde sentarte,"
   45 data "unos largos y tensos minutos,"
   46 data "hasta que el Oleolesimeligen se digna a abrir la puerta."
   47 data chr$ 13
   48 data 100+20
   49 data "Alias {R}la cabina{S}."
   50 data chr$ 13
   51 data 1000
   52 data "{04}Ya es medianoche. Menudo fr{E}o que hace."
   53 data chr$ 13
   54 data 1001
   55 data "Y para colmo el Gafopelao me ha dejado solo."
   56 data "{R}Esconder{C} la llave en un tiesto{S}, me dice ayer,"
   57 data "de repente, durante el examen de mates,"
   58 data "as{E} por lo bajito, con su susurro de chicharra moribunda:"
   59 data "{R}Pero ya te dir{C} cu{A}l elijo para que no me vea el guarda."
   60 data "Ll{A}mame a la hora de la merienda y te lo digo{S}."
   61 data chr$ 13
   62 data 1002
   63 data "Pues ni a la hora de la merienda ni a la hora de la cena:"
   64 data "No s{C} cu{A}ntas veces lo he llamado y nadie respond{E}a al tel{C}fono en su casa."
   65 data "Seguro que le ha explotado el cerebro y lo han llevado al ambulatorio."
   66 data "Pero no ser{A} por estudiar mates,"
   67 data "sino por pasarse el d{E}a programando su Spectrum."
   68 data "Se lo he dicho un mont{G}n de veces:"
   69 data "{R}Pon alg{I}n juego de vez en cuando, Gafopelao,"
   70 data "que te va a estallar la cabeza{S}."
   71 data chr$ 13
   72 data 1003
   73 data "Ahora me va a tocar buscar la llave."
   74 data chr$ 13
   75 data 0
   76 save "c:textmk.bas" line 1:run
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































Deleted src/ce4.text_maker.vbas.

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
// ce4.text_maker.vbas
// (TEXTMK.BAS in the ZX Spectrum +3e)

rem This file is part of
rem CE4
rem A text adventure in Spanish
rem for the ZX Spectrum +3e with DivIDE

// This tool program creates the text file in drive C.

// This file was last modified: 2015-03-15

rem Copyright (C) 2015 Marcos Cruz (programandala.net)

rem Licencia/Permesilo/License:
rem GPL

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://gnu.org/licenses>.

// }}} ---------------------------------------------------------
// Requirements {{{

#include ce4.common.vbas

#filename TEXTMK.BAS
#procedureCall
#renumLine 1
#run @firstRun
#tapmaker bas2tap

// }}} ---------------------------------------------------------
// Main {{{

cls
print "Actualizando los textos";
makeTexts
load "c:ce4.bas"

// }}} ---------------------------------------------------------
// Make the texts file

#include ce4.fn_txtfile.vbas

defproc makeTexts

  save "c:":\
  restore @texts
  do
    let t$="":\ // new text
    read fileId:\
    if not fileId then exit proc
    do
      read i$:\
      if i$=chr$ 13 then exit do
      let t$=t$+(" " and len t$)+i$
    loop
    dim a$(len t$):\
    let a$=t$:\
    save fn txtFile$(fileId) data a$():\
    print ".";
  loop

endproc

// }}} ---------------------------------------------------------
// Texts

@texts

// .............................
// Locations

// Note: text id of long location descriptions use the location id.
// Short descriptions, for already visited locations, add 100.

data theLiving // text id
data "La triste mesa y sus tres esqueléticas e incómodas sillas,"
data "le dan a esta salita de visitas el aspecto de la sala de interrogatorios"
data "que realmente es."
data "En una de las desnudas paredes hay un pequeño y sucio ventanuco"
data "por el que, cuando es de día, con gran esfuerzo, logran entrar"
data "uno o dos agotados rayos de luz."
data chr$ 13

data 100+theLiving // text id
data "Llamada «sala de interrogatorios»." // XXX TMP
data chr$ 13

data theHall // text id
data "Una diminuta pieza que comunica los despachos entre sí."
data "Es tan pequeña que la llamamos «la cabina», como la peli;"
data "y también porque aquí,"
data "cuando el director te llama a su despacho para nada bueno,"
data "te hacen esperar de pie, sin lugar donde sentarte,"
data "unos largos y tensos minutos,"
data "hasta que el Oleolesimeligen se digna a abrir la puerta."
data chr$ 13

data 100+theHall // text id
data "Alias «la cabina»."
data chr$ 13

// .............................
// Intro

data 1000 // text id
data "{winHome}Ya es medianoche. Menudo frío que hace."
data chr$ 13

data 1001 // text id
data "Y para colmo el Gafopelao me ha dejado solo."
data "«Esconderé la llave en un tiesto», me dice ayer,"
data "de repente, durante el examen de mates,"
data "así por lo bajito, con su susurro de chicharra moribunda:"
data "«Pero ya te diré cuál elijo para que no me vea el guarda."
data "Llámame a la hora de la merienda y te lo digo»."
data chr$ 13

data 1002 // text id
data "Pues ni a la hora de la merienda ni a la hora de la cena:"
data "No sé cuántas veces lo he llamado y nadie respondía al teléfono en su casa."
data "Seguro que le ha explotado el cerebro y lo han llevado al ambulatorio."
data "Pero no será por estudiar mates,"
data "sino por pasarse el día programando su Spectrum."
data "Se lo he dicho un montón de veces:"
data "«Pon algún juego de vez en cuando, Gafopelao,"
data "que te va a estallar la cabeza»."
data chr$ 13

data 1003 // text id
data "Ahora me va a tocar buscar la llave."
data chr$ 13

data 0 // end of data

// }}} ---------------------------------------------------------
// Meta {{{

@firstRun
save "c:textmk.bas" line 1:run


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















































































































































































































































































































Deleted src/ce4.vbas.

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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
// ce4.vbas
// (CE4.BAS in the ZX Spectrum +3e)

// A text adventure in Spanish for the ZX Spectrum +3e

// UNDER DEVELOPMENT

// Home page:
// http://programandala.net/es.programa.ce4.html

rem CE4
#include ce4.version.vbas

rem Copyright (C) 2014,2015,2016 Marcos Cruz (programandala.net)
rem License: GPL 3

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://gnu.org/licenses>.

// History:
// See: http://programandala.net/es.programa.ce4.html
// To-do:
// See the file TO-DO.md

// }}} ---------------------------------------------------------
// Config {{{

#filename CE4.BAS
#procedureCall
#renumLine 1
#run @firstRun
#tapmaker bas2tap

#include ce4.common.vbas

// }}} ---------------------------------------------------------
// Functions {{{

// Note: All functions are created in one line of code.

// .............................
// Random

deffn random(m)=\
  // Random integer number between 0 and m-1.
  int(rnd*m):\

deffn between(a,b)=\
  // Random integer between a and b.
  int(rnd*(b-a+1))+a:\

deffn char$(s$)=\
  // Random character from a string.
  s$(fn between(1,len(s$))):\

// .............................
// Memory

deffn dpeek(a)=\
  // Peek a 16-bit value from the given address.
  usr fn_dpeek:\

deffn dpoke(a,n)=\
  // Poke a 16-bit value into the given address.
  usr fn_dpoke:\

// .............................
// Time

deffn tics()=\
  // Current system time in 50ths of second
  fn dpeek(FRAMES)+65536*peek FRAMES2:\

deffn seconds()=\
  // Current system time in seconds.
  fn tics()/50:\

deffn twoDigits$(n)=\
  // Convert a number (0-99) to a two-digit string.
  ("0" and (n<10))+str$ n:\

deffn hour$(h,m,s)=\
  // Hour, minute and second as an ISO time string.
  fn twoDigits$(h)+":"+fn twoDigits$(m)+":"+fn twoDigits$(s):\

// .............................
// Strings

deffn trunc$(t$)=\
  // Remove trailing spaces of a string.
  "" and usr fn_trunc:\

deffn term(h$,n$)=\
  // The id of the given term (n$, the needle)
  // in the given list of terms (h$, the haystack).
  // h$ = list of terms;
  //      every term has a byte 0 as prefix and a byte 14 suffix;
  //      the term id is the byte following the byte 14.
  usr fn_term:\

deffn termn$(h$,n)=\
  // The n-th term (1 is first one) 
  // in the given list of terms (h$, the haystack).
  // h$ = list of terms;
  //      every term has a byte 0 as prefix and a byte 14 suffix;
  //      the term id is the byte following the byte 14.
  "" and usr fn_termn:\

deffn lookup8(t$,k)=\
  // The 8-bit value associated to a 8-bit key
  // (or 0 if the key is not found).
  // t$ = lookup table: key-value pairs;
  //      first the key, second the value.
  // k = 8-bit key to search for
  usr fn_lookup8:\

deffn lookup16(t$,k)=\
  // The 16-bit value associated to a 16-bit key
  // (or 0 if the key is not found).
  // t$ = lookup table: 4-byte groups of key-value pairs;
  //      first the key, second the value; key and value are
  //      stored as two bytes in the usual Z80 format (least
  //      significant byte first).
  // k = 16-bit key to search for
  usr fn_lookup16

// .............................
// Data interface

deffn thingArticle$(t,o)=\
  // Proper article for thing t, with offset o.  The offset can be
  // zero for the default undefined article, or one of the article
  // offsets defined in <ce4.common.vbas>: 'known', 'owned', 'noone'
  // and 'someone'.
  // XXX TODO use the offset
  fn trunc$(article$(thingArticle(t))):\

deffn name$(t)=\
  // Name (noun) associated with the thing t.
  fn termn$(nouns$,thingNoun(t)):\

deffn wholeName$(t)=\
  // Whole name of the thing t.
  fn thingArticle$(t,thingArticle(t))+" "+fn name$(t):\

deffn aroundHere(t)=\
  // Is the given thing around here?
  fn isHere(t) and not adjacent(location(t),currentLocation):\

deffn freeMemory()=\
   // Free memory in bytes
   val "65536"-usr val"7962":\

deffn currentLocationTxt()=\
  // Text id of the current location's description
  currentLocation+100*(visits(currentLocation)>1):\

deffn channel(n)=\
  // Address of a channel information area
  fn dpeek(CHANS)+fn dpeek(STRMS+2*(n+3))-1:\

deffn winLine(n)=\
  // Screen current line position of a window (0-23)
  peek (fn channel(n)+18)/8:\

deffn winFreeCols()=\
  // Free cols on the current line of a window (0-32)
  peek (winInfo+15)-peek (winInfo+17)

// .............................
// Files

#include ce4.fn_txtfile.vbas

// }}} ---------------------------------------------------------
// Main {{{

// 'rem' comments with ending 'XXX' are only for debugging with the
// emulator; they will be removed.

goto @initOnce:rem initOnce XXX
@main

do
  setFullWin
  credits:rem _credits XXX
  intro:rem _intro XXX
  game
loop

defproc game

#  border red:_echo_["XXX"]:border blue // XXX INFORMER

  gameInit:rem _gameInit XXX
  enterLocation:rem _enterLocation XXX

  do
    #ifdef debug
      debug["Libre="+str$ fn freeMemory()+" B"] // XXX
    #endif
    accept:rem _accept XXX
    if len accept$ and not inactiveInput then \
      echo_["{winInk}{inputInk}"+fn trunc$(accept$)+"{winInk}{outputInk}"]
    parse: rem _parse XXX
    # _echo_["XXX -- between __parse__ and __obey__"]
    if action then
      gosub @obey:rem _obey XXX
    else
      // XXX TODO check empty commands
      if inactiveInput then
        if not fn random(3) then \
          _echo_["El tiempo pasa."] // XXX TODO random message?
      else
        // XXX TODO move this error to the parse proc?:
        error["¿"+theVerb$+"?"] // XXX TMP
      endif
    endif
  loop until gameOver

endproc

// }}} ---------------------------------------------------------
// Input {{{

defproc accept

  // Accept a line of text from the user.
  //
  // Ouput:
  //  command$ = text
  //  inactiveInput = flag; if set, the proc finished because there
  //     was no time left, not because the user pressed the enter key

  let printedLines=printedLinesInit // XXX OLD
#  let printedChars=0 // XXX OLD

  if aKey=ENTER_CHAR then \
    acceptInit
  let inactiveInput=false:\
  let maxTics=fn tics()+1000 // 50th of second
  print #inputWin;chr$ winHome;accept$;
  poke bottomLineAttrAddress+cursorPos,cursorAttr

  do // endless loop to read the keyboard
  
    let aKey=code inkey$
    if fn tics()>maxTics then \
      let inactiveInput=true:\
      poke bottomLineAttrAddress+cursorPos,inputAttr:\
      exit proc

    // Do a simulated 'ON GOTO' to the corresponding routine:
    @onKeyActionGoto
    let void=fn dpoke(OLDPPC,@onKeyActionGoto):\
    poke OSPPC,code keyAction$(aKey+1)+3:\
    continue:\
      goto @a_acute_char:\
      goto @delete_char:\
      goto @e_acute_char:\
      goto @enter_char:\
      goto @i_acute_char:\
      goto @n_tilde_char:\
      goto @next_key:\
      goto @o_acute_char:\
      goto @printable_char:\
      goto @space_char:\
      goto @u_acute_char

    @delete_char
    if cursorPos>1 then \
      let cursorPos=cursorPos-1:\
      let spacePos=spacePos*(accept$(cursorPos)<>" ")
      let accept$(cursorPos)=" ":\
      print #inputWin;chr$ winHome;accept$;:\
      poke bottomLineAttrAddress+cursorPos,cursorAttr
    goto @next_key

    @enter_char
    if cursorPos>1 then \
      let command$=accept$(to cursorPos-1):\
      print #inputWin;chr$ winCls:\
      exit proc
    goto @next_key

    @space_char
    if \
        cursorPos>1 \
        and not spacePos \
        and cursorPos<maxAcceptedChars then \
          let maxTics=maxTics+250:\
          let spacePos=cursorPos:\
          let accept$(cursorPos)=" ":\
          poke bottomLineAttrAddress+cursorPos,inputAttr:\
          print #inputWin;chr$ winHome;accept$;:\
          let cursorPos=cursorPos+1:\
          poke bottomLineAttrAddress+cursorPos,cursorAttr
    goto @next_key

    @a_acute_char
    let aKey=code["{A}"]:goto @printable_char
    @e_acute_char
    let aKey=code["{C}"]:goto @printable_char
    @i_acute_char
    let aKey=code["{E}"]:goto @printable_char
    @n_tilde_char
    let aKey=code["{K}"]:goto @printable_char
    @o_acute_char
    let aKey=code["{G}"]:goto @printable_char
    @u_acute_char
    let aKey=code["{I}"]

    @printable_char
    if cursorPos<maxAcceptedChars then \
      let maxTics=maxTics+250:\
      let accept$(cursorPos)=chr$ aKey:\
      poke bottomLineAttrAddress+cursorPos,inputAttr:\
      print #inputWin;chr$ winHome;accept$;:\
      let cursorPos=cursorPos+1:\
      poke bottomLineAttrAddress+cursorPos,cursorAttr

    @next_key
    if multitasking*not peek FRAMES then \
      theGuardMoves

  loop

endproc

defproc acceptInit

  // Init the values used by the accept procedure

  let aKey=0:\
  let accept$="":\
  let command$="":\ // XXX necessary?
  let cursorPos=1:\ // position of the cursor in command$
  let spacePos=0 // position of space, and flag

endproc

// }}} ---------------------------------------------------------
// Errors {{{

defproc notCarriedError 

  // Error: the complement is not carried.

  // XXX TODO -- rewrite
#  _echo_["No tengo eso."]  // XXX OLD
  _echo_["No tengo "+fn wholeName$(complement)+"."]

endproc

// }}} ---------------------------------------------------------
// Parser {{{

defproc parse 

  // Parse the command

  // Input:
  //     command$
  //     spacePos

  if spacePos then
    let theVerb$=command$(to spacePos-1):\
    let theNoun$=command$(spacePos+1 to)
  else
    let theVerb$=command$:\
    let theNoun$=""
  endif

  #ifdef debug
    debug["Verbo='"+theVerb$+"'"] // XXX
    debug["Nombre='"+theNoun$+"'"] // XXX
  #endif

  let action=fn term(verbs$,chr$ 0+theVerb$+chr$ 14):\
  let complement=fn term(nouns$,chr$ 0+theNoun$+chr$ 14)
  if complement>=firstAmbiguous then // Is it an ambiguous thing?
    // The ambiguous complement must be converted to the actual one.
    // Do a simulated 'ON GOTO' to the corresponding routine:
    @onAmbiguousGoto
    let void=fn dpoke(OLDPPC,@onAmbiguousGoto):\
    poke OSPPC,complement-firstAmbiguous+4:\
    continue:\
      // The 'goto' list must be in alphabetical order:
      goto @unAmbiguousPotX:\
      goto @unAmbiguousTableX:\
      goto @unAmbiguousWallX
    fatal_error["Complemento ambiguo fuera de rango: "+str$ complement] // XXX TMP
  else if not complement then
    let complement=noThing
  endif
  #ifdef debug
    debug["Acción= "+str$ action] // XXX
    debug["Compl.= "+str$ complement] // XXX
  #endif
  exit proc

  @unAmbiguousTableX
  // Make 'theTableX' unambiguous
  #ifdef debug
    debug["Complemento ambiguo «mesa»= "+str$ complement] // XXX
  #endif
  if currentLocation=theDining then
    let complement=theDiningTables
  else 
    let complement=theLivingTable
  endif
  #ifdef debug
    debug["Complemento inequívoco= "+str$ complement] // XXX
  #endif
  exit proc

  @unAmbiguousWallX
  // Make 'theWallX' unambiguous
  #ifdef debug
    debug["Complemento ambiguo «muro»= "+str$ complement] // XXX
  #endif
  // XXX OLD
#   if currentLocation=theEntranceA then
#     let complement=theWallA
#   else if currentLocation=theEntranceB then
#     let complement=theWallB
#   else if currentLocation=theEntranceC then
#     let complement=theWallC
#   else if currentLocation=theEntranceD then
#     let complement=theWallD
#   else if currentLocation=theEntranceE then
#     let complement=theWallE
#   endif
  // XXX simpler and faster method.
  // XXX FIXME will fail with more outside locations...
  // XXX ...than theEntranceA...theEntranceE.
  if outside(currentLocation) then \
#  if currentLocation<=theEntranceE and currentLocation>=theEntranceA then \  // XXX solution, slower
    let complement=theWallA+(currentLocation-theEntranceA)

  #ifdef debug
    debug["Complemento inequívoco= "+str$ complement] // XXX
  #endif

  exit proc

  @unAmbiguousPotX
  // Make 'thePotX' unambiguous
  #ifdef debug
    debug["Complemento ambiguo «tiesto»= "+str$ complement] // XXX
    debug["Escenario actual= "+str$ currentLocation] // XXX
  #endif
  if outside(currentLocation) then
    let complement=thePotA+(currentLocation-theEntranceA):\
    #ifdef debug
      debug["Complemento inequívoco según escenario= "+str$ complement]:\ // XXX
    #endif
    let lastPot=complement:\
    exit proc
  else
    let complement=lastPot
    #ifdef debug
      debug["Complemento inequívoco según recuerdo= "+str$ complement] // XXX
    #endif
  endif
  
endproc

// }}} ---------------------------------------------------------
// Non-playing character {{{

defproc theGuardMoves

  // The guard moves to a random adjacent location.

  // XXX TODO -- improve 

  let anExit=fn between(theNorth,theWest):\
  if not exit(location(theGuard),anExit) then \
    exit proc

  let location(theGuard)=exit(location(theGuard),anExit)-locked*(exit(location(theGuard),anExit)>locked)
  #ifdef debug
    debug["El guarda se va hacia "+fn name$(anExit)+" ("+fn locationName$(location(theGuard))+")."]
  #endif
  if fn isHere(theGuard) then
    catchedByTheGuard
  else if adjacent(currentLocation,location(theGuard)) then
    _echo_["Oigo pasos al "+fn name$(adjacent(currentLocation,location(theGuard)))+"..."]
  else if corridor(location(theGuard)) and corridor(currentLocation) then
    _echo_["He oído algo en el pasillo..."]
  endif

endproc

defproc catchedByTheGuard

  // XXX TODO -- rewrite everything:

#  _echo_["Viene el guarda de seguridad."]

  let multitasking=false:\
  let banished=false
  // XXX TODO -- flag: catched

  _echo["Me agarra por el cuello y me dice: "]
  if outside(currentLocation) then
    echo_["«¿Qué haces rondando por aquí?»."]
  else
    let banished=true
    echo_["«¿Cómo has entrado aquí?»."]
  endif

  if guardMet and not banished then
    _echo["Se acerca a mí y me dice:"]
    if fn isCarried(thePaperSheet) then \
      goto @l4007
    goto @l4085
  endif

  if banished then
    _echo["«Esta habitación estaba cerrada con llave..."]:\
    if fn isHere(theSafe) and safeOpened then \
      echo["¡Y además has abierto la caja!"]
    echo["¡Maldito hereje!»."]
  endif

  @l4007
  if fn isCarried(thePaperSheet) then \
    _echo_["«¿Qué es ese papel que tienes ahí escondido? Déjame ver...»."]:\
    pause 100:_echo_["«Hum...», dice, echando un vistazo."]:\
    pause 100:_echo_["«Así que has copiado el examen...», dice por fin."]:\
    let banished=true

  if banished then \
    _echo["«Esto significa tu inmediata expulsión de este complejo."]:\
    goto @theEnd
  _echo["Se vuelve hacia mí y me dice:"]
  echo_["«¿Sabes que estar en el complejo a estas horas es una grave falta de disciplina?»."]
  pause 100
  _echo_["«Este comportamiento no es propio de un alumno que se esta formando en el complejo», añade."]

  if banished then \
    goto @theEnd

  @l4085
  theGuardLeaves

endproc

defproc theGuardLeaves

  do
    let location(theGuard)=fn between(1,locations)
  loop until not fn aroundHere(theGuard)
  print #win
  _echo_["Se da media vuelta y se va."]
  let guardMet=guardMet+1
  // XXX FIXME this is nonsense here:
  if not banished then \
    _echo_["¡Uf!... por poco."]

endproc

// }}} ---------------------------------------------------------
// The end {{{

// XXX TODO rewrite

// XXX Note: @theEnd is called with a goto
@theEnd
// XXX TODO 
let totalPlayingSeconds=fn seconds()
let playingMinutes=int (totalPlayingSeconds/60)
let playingSeconds=int (totalPlayingSeconds-playingMinutes*60)
let playingHours=int (playingMinutes/60)
let playingMinutes=playingMinutes-playingHours*60

if banished then 

  _echo["Has sido expulsado del Complejo Educativo."]
  // XXX TODO finish
  echo_["La próxima vez ten más cuidado."]

else

  _echo["Has logrado tu objetivo."]
  echo_["¡Enhorabuena!"]

endif

timeReport

if not banished then 

  if totalPlayingSeconds<totalRecordSeconds then

    let totalRecordSeconds=totalPlayingSeconds:\
    let recordHours=playingHours:\
    let recordMinutes=playingMinutes:\
    let recordSeconds=playingSeconds:\
    let recordMan$=player$ // XXX
    _echo_["¡Has establecido un nuevo récor!"]

  else

    _echo["El récor sigue en posesión de"]
    echo[recordMan$+", con un tiempo de"]
    echo_[fn hour$(recordHours,recordMinutes,recordSeconds)+"."]

  endif

endif

_echo_["Pulsa una tecla para jugar."]
pause 0
goto @main

defproc timeReport
  _echo["Tardaste en "]
  echo[("ser expulsado" and banished)+("lograrlo" and not banished)+": "]
  echo_[fn hour$(playingHours,playingMinutes,playingSeconds)+"."]
endproc

// }}} ---------------------------------------------------------
// Action dispatcher {{{

@obey

  // XXX TODO different values in syntax(), e.g.:
  // 1 = doable, normal
  // 0 = impossible
  // -1 = absurd
  // -2 = contra natura

  // XXX TODO move to the parse proc?
  if len theNoun$ and complement=noThing then \
    error["¿"+theNoun$+"?"]:\
    return

  if not syntax(action,complement) then
    if complement=noThing then
      error["Falta complemento."] // XXX ??
    else
      error["Imposible."]
    endif
    return
  endif

  gosub @doAction

  // XXX TODO update the 'known' flag of the complement,
  // in order to force the definite article.

  return

@doAction

  // NOTE: All actions must end with 'RETURN'.

  // Do a simulated 'ON GOTO' to the action routine:
  @onActionGoto
  let void=fn dpoke(OLDPPC,@onActionGoto):\
  poke OSPPC,action+3:\
  continue:\

    // The following list of labels must be in alphabetical order,
    // to match the values of the correspondent action ids defined in
    // <ce4.common.vbas>.

    goto @doDo:\
    goto @doDrop:\
    goto @doExamine:\
    goto @doGo:\
    goto @doGoEast:\
    goto @doGoIn:\
    goto @doGoNorth:\
    goto @doGoOut:\
    goto @doGoSouth:\
    goto @doGoWest:\
    goto @doInventory:\
    goto @doLook:\
    goto @doOpen:\
    goto @doRead:\
    goto @doShowGraphics:\
    goto @doTake:\
    goto @doTurnOff:\
    goto @doTurnOn:\
    #ifdef debug
      goto @doDebug:\
    #endif
    fatal_error["Valor incorrecto de la variable 'action' (la acción): "+str$ action] // XXX TMP
    
    fatal_error["Flujo descontrolado en la rutina 'obey'"] // XXX TMP

// }}} ---------------------------------------------------------
// Actions {{{

// Every action must end with a 'RETURN'.

#ifdef debug

  @doDebug
    debug["El complemento está en el escenario "+\
      str$ location(complement)+\
      "("+locationName$(location(complement))+" )"]
    return

#endif

@doGoComplement
  // XXX TODO -- not used
  #ifdef debug
    debug["doGoComplement"]
  #endif
  let direction=complement:goto @doGo

@doGoNorth
  #ifdef debug
    debug["doGoNorth"]
  #endif
  let direction=theNorth:goto @doGo

@doGoSouth
  #ifdef debug
    debug["doGoSouth"]
  #endif
  let direction=theSouth:goto @doGo

@doGoEast
  #ifdef debug
    debug["doGoEast"]
  #endif
  let direction=theEast:goto @doGo

@doGoWest
  #ifdef debug
    debug["doGoWest"]
  #endif
  let direction=theWest:goto @doGo

@doGoOut
  #ifdef debug
    debug["doGoOut"]
  #endif
  let direction=theOutside
  let anExit=exit(currentLocation,direction)
  if not anExit then \
    // No explicit way out, so use the previous location instead
    let anExit=previousLocation
  goto @doGoExit

@doGoIn
  #ifdef debug
    debug["doGoIn"]
  #endif
  let direction=theInside

@doGo

  #ifdef debug
    debug["doGo"]
  #endif
  // Input: direction

  let anExit=exit(currentLocation,direction)
  @doGoExit // used by the @doGoOut routine
  if not anExit then
    _echo_["No puedo ir en esa dirección."]
  else if anExit>locked then // locked?

    if fn isCarried(theKey) then

      _echo_["Abro la puerta con la llave."]
      // Unlock the door from this side:
      let exit(currentLocation,direction)=\
        anExit-locked
      // Unlock from the other side
      // XXX FIXME -- it  works only if exits are regular
      // (N<-->S, E<-->W, etc):
      let exit(anExit-locked,oppositeDirection(direction))=\
        currentLocation

      let previousLocation=currentLocation
      let currentLocation=anExit-locked
      enterLocation

    else
      _echo_["No puedo ir en esa dirección. Hay una puerta cerrada con llave."]
    endif

  else
    let previousLocation=currentLocation
    let currentLocation=anExit
    enterLocation
  endif

  return

@doTake

  #ifdef debug
    debug["doTake"]
  #endif
  if fn isCarried(complement) then \
    _echo_["Ya tengo "+fn wholeName$(complement)+"."]:\
    return

  if not light then \
    _echo_["La oscuridad me lo impide."]:\
    return

  if fn isNotHere(complement) then \

     _echo_["No veo "+fn wholeName$(complement)+" aquí."]:\
#    _echo_["No veo eso aquí."]:\ // XXX simpler alternative
    return

  if complement>=thePotA and complement<=thePotE then \
    _echo_["Eso debe de pesar más que una vaca."]:\
    return

// XXX TODO improve or remove this plot condition
#   if carried=maxCarried then \
#     _echo_["No puedo llevar más cosas."]:\
#     return

  // XXX TODO check the pot, and issue proper messages, "it's too heavy"

  let location(complement)=theProtagonist:\
  let carried=carried+1
  // XXX TODO write fn name$()
  _echo_["Recojo "+fn wholeName$(complement)+"."]

  // XXX OLD
  // if complement=thePot then \
  //   if location(theKey)=theLimbo then \
  //     _echo_["Debajo del tiesto estaba la llave."]:\
  //     let location(theKey)=currentLocation

  return

@doDrop

  #ifdef debug
    debug["doDrop"]
  #endif
  if complement=theAll then
    for n=firstPortable to lastPortable
      if fn isCarried(n) then \
        let location(n)=currentLocation
    next n
    let carried=0
  else
    if fn isNotCarried(complement) then
      notCarriedError
    else
      let location(complement)=currentLocation:\
      let carried=carried-1
      _echo_["Dejo "+fn wholeName$(complement)+"."]
    endif
  endif

  return

@doOpen

  #ifdef debug
    debug["doOpen"]
  #endif
  if complement=theSafe then \
    goto @doOpenTheSafe

  if fn isNotCarried(theKey) then \
    _echo_["No tengo la llave."]:\
    return

  // XXX TODO improve
  for n=theNorth to theWest
    let anExit=exit(currentLocation,n)
    if anExit>locked then
      let exit(currentLocation,n)=anExit-locked:\
      let exit(anExit-locked,n-(n=2 or n=4)+(n=1 or n=3))=currentLocation:\
      _echo_["Abro la puerta que va al "+fn name$(n)+"."]:\
      return
    endif
  next n
  _echo_["No hay ninguna puerta cerrada."]

  return

@doDo
  #ifdef debug
    debug["doDo"]
  #endif
  // XXX TODO other possible complements?

@doInventory

  #ifdef debug
    debug["doInventory"]
  #endif
  if not carried then \
    _echo_["No tengo nada."]:\
    return

// XXX OLD
#  let listed=0
#  let t$="Tengo "
#  // XXX TODO in the data, mark also the last portable (and add locations after it)
#  for n=firstPortable to lastPortable
#    if fn isCarried(n) then
#      let listed=listed+1
#      if listed=carried then
#        // The last one
#        if carried>1 then let t$=t$+" y "
#        let t$=t$+fn name$(n)+"."
#      else
#        let t$=t$+fn name$(n)+(", " and listed<(carried-1))
#      endif
#    endif
#  next n
#  gosub @_echo_
  
  // The current version prints every element apart.

  // XXX The text justification routines had to be adjusted in order
  // to make this method work fine.

  let listed=0
  _echo["Tengo "]
  for n=firstPortable to lastPortable
    if fn isCarried(n) then
      let listed=listed+1
      if listed=carried then
        // The last one
        if carried>1 then echo[" y "]
        echo_[fn wholeName$(n)+"."]
      else if listed=carried-1 then
        // The last but one
        echo[fn wholeName$(n)]
      else
        echo[fn wholeName$(n)+", "]
      endif
    endif
  next n

  return

@doLook

  #ifdef debug
    debug["doLook"]
  #endif

  if complement=theAll or complement=noThing then

    gosub @describeCurrentLocation:\
    showThings:\
    showExits

  else if not light then

    _echo_["Me encantaría poder ver en la oscuridad."]

  else if fn isNotCarried(complement) and fn isNotHere(complement) then

    _echo_["No veo "+fn wholeName$(complement)+" aquí."]

  else if complement=thePaperPiece then

    if fn isCarried(complement) then 
      _echo_["Tiene algo escrito."]:\
      pause 100:\
      readThePaperPiece
    else
      _echo_["Ahí está."] // XXX TODO
    endif

  else if complement=theBooks then

    _echo_["Los libros están polvorientos."]

  else if complement=theLivingTable then

    _echo_["Es una triste mesa de acampada, enclenque y oxidada."]
    
  else if complement=theDiningTables then

    _echo_["Son viejas y desgastadas mesas de madera."]

  else if complement>=theNorth and complement<=theOutside then

    let anExit=exit(currentLocation,complement)
    if not anExit and complement=theOutside then \
      // No explicit way out, so use the previous location instead
      #ifdef debug
        debug["Se usa en su lugar el escenario previo: "+str$ previousLocation]:\
      #endif
      let anExit=previousLocation

    if anExit then
      _echo_["Hacia "+("el " and (complement<theInside))+fn wholeName$(complement)+" está "+fn locationName$(anExit-locked*(anExit>locked))+("." and (anExit<locked))+(", pero la puerta está cerrada." and (anExit>locked))]
    else
      _echo_["No hay salida hacia "+("el " and (complement<theInside))+fn wholeName$(complement)+"."]
    endif

  else if complement=theInventory then

    goto @doInventory

  else

    // Default message
    # _echo_["No veo nada especial en "+fn wholeName$(complement)+"."]
    _echo_["No veo nada especial."]

  endif
    
  return

@doExamine

  #ifdef debug
    debug["doExamine"]
  #endif

  if complement=theAll or complement=noThing then

    gosub @describeCurrentLocation:\
    showThings:\
    showExits

  else if not light then

    _echo_["Con esta oscuridad no es posible examinar nada."]

  else if fn isNotCarried(complement) and fn isNotHere(complement) then

    _echo_["No veo "+fn wholeName$(complement)+" aquí."]

  else if complement=thePaperPiece then

    if fn isCarried(complement) then 
      _echo_["Tiene algo escrito."]:\
      pause 100:\
      readThePaperPiece
    else
      _echo_["Ahí está."] // XXX TODO
    endif

  // XXX TODO -- faster, use 'on goto' instead of one 'if' for every
  // possible complement:

  else if complement=theBooks then

    // XXX TODO
    _echo_["Examino los libros polvorientos."]

  else if complement=theLivingTable then

    // XXX TODO
    _echo_["Es una triste mesa de acampada, enclenque y oxidada."]
    
  else if complement=theDiningTables then

    // XXX TODO
    _echo_["Son viejas y desgastadas mesas de madera."]

  else if complement>=thePotA and complement<=thePotE then

    searchPot

  else if complement=theInventory then

    goto @doInventory

  else

    // Default message
    # _echo_["No nada especial en "+fn wholeName$(complement)+"."]
    _echo_["No veo nada especial."]

  endif
    
  return

@doTurnOff

  #ifdef debug
    debug["doTurnOff"]
  #endif
  if fn isNotCarried(complement) then \
    notCarriedError:\
    return

  if not light then \
    _echo_["Ya está apagada."]
  let light=false

  return

@doTurnOn

  #ifdef debug
    debug["doTurnOn"]
  #endif
  if fn isNotCarried(complement) then \
    notCarriedError:\
    return

  if light then \
    _echo_["Ya está encendida."]
  let light=true

  return

@doRead

  #ifdef debug
    debug["doRead"]
  #endif
  if fn isNotCarried(complement) then \
    notCarriedError:\
    return

  if not light then \
    _echo_["No puedo leer a oscuras."]:\
    return
  if complement=thePaperSheet then
    // XXX TODO
    _echo_["Está en blanco."]
    return
  endif
  if complement=thePaperPiece then \
    readThePaperPiece:\
    return

  return

@doShowGraphics

  // Toggle, set, or unset the graphics.

  let i=showGraphics:\ // current mode

  let showGraphics=\
    (not showGraphics)*(complement=noThing)+\
    (complement=theYes):\

  if showGraphics<>i then \
    cls:\
    modeWindows:\
    if showGraphics then \
      let void=usr cl1st3rd:\
      loadImg

  return
    
// }}} ---------------------------------------------------------
// Action tools {{{

@doOpenTheSafe

  if safeOpened then \
    _echo_["Ya estaba abierta."]:\
    return

  _echo_["¿Cuál es la combinación?"]:\
  accept
  if command$=safeCode$ then
// XXX TODO
    let safeOpened=true
  else
    _echo_["La caja no se abre."]
    _echo_["Parece que esa no es la combinación."]
  endif

  return

defproc readThePaperPiece

  _echo_["Pone... "+safeCode$]

endproc

// }}} ---------------------------------------------------------
// Puzzles {{{

defproc searchPot

//  let potsExamined=potsExamined+1  // XXX TODO
  if complement=keyPot then

    // XXX TODO improve the texts
    _echo_["¡Aquí está la llave!"+\
      (" ¡A la primera!" and not examinedPots)+\
      (" No ha sido tan difícil." and examinedPots<3)+\
      (" ¡Por fin!" and examinedPots>3)+\
      (" Tenía que estar en el último." and examinedPots=totalPots)]
    let location(theKey)=theProtagonist:\
    let carried=carried+1

  else

    // XXX TODO improve the texts
    _echo_["En este "+\
      ("primero no " and not examinedPots)+\
      ("tampoco " and examinedPots)+\
      "está la llave."]:\
#    _echo_["Aquí no hay llave. Este Pelao se va a enterar."]
    let examinedPots=examinedPots+(examinedPots<totalPots)

  endif

endproc

// }}} ---------------------------------------------------------
// Locations {{{

defproc enterLocation

  // XXX TODO separate plot and description

  let visits(currentLocation)=visits(currentLocation)+1
  gosub @describeNewLocation
  locationPlot
  if not gameOver then \
    showThings:\
    showExits

endproc

// .............................................................

@describeNewLocation

  // XXX TODO -- "Entro en / Vuelvo a", but problem: "a / al / a la"

  if showGraphics then \
    loadImg 
  _echo[chr$ winCls+"Entro en "] // XXX TODO more options
  goto @onLocationGoto

@describeCurrentLocation

  // Describe the current location
  
  // XXX FIXME -- +3e bug?
  //
  // The first text is shown 3 lines down from the top.

#  // XXX does not work:
#  gosub @clearWin
#  _echo["Estoy en "]i

#  // XXX works
#  _echo["{winCls}Estoy en "]

#  // XXX does not work:
#  print #win;chr$ winCls:\
#  _echo["Estoy en "] // XXX TODO more options
  
#  // XXX does not work (but 1 line less):
#  print #win;chr$ winCls;:\
#  _echo["Estoy en "] // XXX TODO more options
  
  _echo[chr$ winCls+"Estoy en "] // XXX TODO more options

  // Do a simulated 'ON GOTO' to the corresponding routine:
@onLocationGoto
  let void=fn dpoke(OLDPPC,@onLocationGoto):\
  poke OSPPC,currentLocation+3:\
  continue:\

    // The following list of labels must be in alphabetical order, to
    // match the values of the correspondent location ids defined in
    // <ce4.common.vbas>.  These routines must end with 'RETURN'.
  
  goto @atTheBasement:\
  goto @atTheBathroomA:\
  goto @atTheBathroomB:\
  goto @atTheChapel:\
  goto @atTheClassA:\
  goto @atTheClassB:\
  goto @atTheCorridorA:\
  goto @atTheCorridorB:\
  goto @atTheCorridorC:\
  goto @atTheCorridorD:\
  goto @atTheCorridorE:\
  goto @atTheCorridorF:\
  goto @atTheDining:\
  goto @atTheEntranceA:\
  goto @atTheEntranceB:\
  goto @atTheEntranceC:\
  goto @atTheEntranceD:\
  goto @atTheEntranceE:\
  goto @atTheGym:\
  goto @atTheHall:\
  goto @atTheJunkRoom:\
  goto @atTheKitchen:\
  goto @atTheLarder:\
  goto @atTheLibrary:\
  goto @atTheLiving:\
  goto @atTheLobby:\
  goto @atTheOfficeA:\
  goto @atTheOfficeB:\
  goto @atTheOfficeC:\
  goto @atTheReception:\
  fatal_error["La variable 'currentLocation' (escenario actual) tiene un valor incorrecto: "+str$ currentLocation] // XXX TMP

  fatal_error["Flujo descontrolado en la rutina 'describeLocation'"] // XXX TMP

defproc locationPlot

  // XXX TODO remove the gotos

  if fn isHere(theGuard) then
    _echo_["¡El guarda está aquí!"]
    pause 100
    catchedByTheGuard
  else if outside(currentLocation) then
    // XXX TODO -- success?
#     if examCopied and marksModified and fn isCarried(thePaperSheet) then \
#       goto @theEnd
  endif

#   _echo_["XXX -- End of PROC_locationPlot"]

endproc

defproc loadImg 

  let file$=("0" and currentLocation<10)+str$ currentLocation+chr$ (48+light):\
  load "g:"+file$+".scr" code SCRAD
#   print at 0,30;using$("00",currentLocation) // XXX TMP

endproc

defproc showThings

// First version, deprecated, that prints a simple list:

#   let first=true
#   for n=firstPortable to lastPortable
#     if fn isHere(n) then
#       if first then \
#         _echo_["Veo:"]:\
#         let first=false
#       // XXX TODO articles
#       _echo_["- "+fn name$(n)+","]
#     endif
#   next n
 
// The following abandoned alternative would require keeping a count
// of things present in every location:

#   let thingsHere=thingsIn(currentLocation)
#   debug["things: "+str$ thingsHere]
#   if not thingsHere then \
#     exit proc
#   // XXX FIXME the punctuation is not right.
#   let listed=0
#   _echo_["Veo"]
#   for n=firstPortable to lastPortable
#     debug["Thing "+str$ n]
#     if fn isHere(n) then 
#       let listed=listed+1
#       if listed=things then
#         // The last one
#         if things>1 then echo["y"]
#         echo_[fn name$(n)+"."]
#       else if listed=things-1 then
#         // The last but one
#         echo[fn name$(n)]
#       else
#         echo[fn name$(n)+","]
#       endif
#     endif
#   next n

// The following deprecated version first creates the paragraph and
// then prints it:

#   let listed=0
#   let t$="Veo "
#   for n=1 to thingsHere
#     let i=code thingsHere$(n)
#     if fn isHere(i) then 
#       let listed=listed+1
#       if listed=thingsHere then
#         // The last one
#         if thingsHere>1 then let t$=t$+" y "
#         let t$=t$+fn wholeName$(i)+"."
#       else
#         let t$=t$+fn wholeName$(i)+(", " and listed<(thingsHere-1))
#       endif
#     endif
#   next n
#   gosub @_echo_

  // The current version prints every element apart.

  // XXX The text justification routines had to be adjusted in order
  // to make this method work fine.

  let thingsHere$=""
  for n=firstPortable to lastPortable
    if fn isHere(n) then \
      let thingsHere$=thingsHere$+chr$ n
  next n
  let thingsHere=len thingsHere$
  #ifdef debug
    debug["Cosas: "+str$ thingsHere]
  #endif

  if not thingsHere then \
    exit proc

  let listed=0
  _echo["Veo "]
  for n=1 to thingsHere
    let i=code thingsHere$(n)
    #ifdef debug
      debug["Cosa número "+str$ i+"("+fn wholeName$(i)+")" ]
    #endif
    if fn isHere(i) then 
      let listed=listed+1
      if listed=thingsHere then
        // The last one
        if thingsHere>1 then echo[" y "]
        echo_[fn wholeName$(i)+"."]
      else if listed=thingsHere-1 then
        // The last but one
        echo[fn wholeName$(i)]
      else
        echo[fn wholeName$(i)+", "]
      endif
    endif
  next n

endproc

// .............................................................
// Exits

defproc showExits

  let exitsHere=exits(currentLocation)
  #ifdef debug
    debug["Salidas: "+str$ exitsHere]
  #endif
  if not exitsHere then \
    exit proc

  let listed=0
  _echo["Hay salida"+("s" and exitsHere>1)+" hacia "]
  for n=theNorth to theWest
    #ifdef debug
      debug["Salida "+str$ n+": "+str$ exit(currentLocation,n)]
    #endif
    // XXX TODO add short names of destinations?
    if exit(currentLocation,n) then 
      let listed=listed+1
      if listed=exitsHere then
        // The last one
        if exitsHere>1 then echo[" y "]
        echo_[fn name$(n)+"."]
        # echo_[fn exitNoun$(n)+"."] // XXX TODO destination's short name
      else if listed=exitsHere-1 then
        // The last but one
        echo[fn name$(n)]
        # echo[fn exitNoun$(n)] // XXX TODO destination's short name
      else
        echo[fn name$(n)+", "]
        # echo[fn exitNoun$(n)+", "] // XXX TODO destination's short name
      endif
    endif
  next n
  #ifdef debug
    debug["Salida "+str$ theInside+": "+str$ exit(currentLocation,theInside)]
    debug["Salida "+str$ theOutside+": "+str$ exit(currentLocation,theOutside)]
  #endif

endproc

// .............................................................
// Locations' descriptions

// XXX TODO -- simplify: one single routine

@atTheEntranceA
  echo_[fn locationName$(theEntranceA)+"."]
  longPhonyText
  return

@atTheEntranceB
  echo_[fn locationName$(theEntranceB)+"."]
  longPhonyText
  return

@atTheEntranceC
  echo_[fn locationName$(theEntranceC)+"."]
  longPhonyText
  return

@atTheEntranceD
  echo_[fn locationName$(theEntranceD)+"."]
  longPhonyText
  return

@atTheEntranceE
  echo_[fn locationName$(theEntranceE)+"."]
  longPhonyText
  return

@atTheBathroomB
  echo[fn locationName$(theBathroomB)+". "]
  echo_["El olor es inaguantable."]
  return

@atTheGym
  echo[fn locationName$(theGym)+". "]
  echo_["El olor a zapato es sobrehumano."]
  return

@atTheLarder
  echo[fn locationName$(theLarder)+". "]
  echo_["Hay un tufo a carne podrida."]
  return

@atTheKitchen
  echo[fn locationName$(theKitchen)+". "]
  echo_["La suciedad cubre los muebles."]
  return

@atTheBasement
  echo_[fn locationName$(theBasement)+". "]
  if not light then
    _echo_["Todo está a oscuras."]
  else
    // XXX FIXME print something here to finish the paragraph
    let light=false
  endif
  return

@atTheJunkRoom
  echo_[fn locationName$(theJunkRoom)+". "]
  if not light then
    _echo_["Todo está a oscuras."]
  else
    // XXX FIXME print something here to finish the paragraph
    let light=false
  endif
  return

@atTheHall
  echo[fn locationName$(theHall)+", "]
  echoTxt_[fn currentLocationTxt()]:\ // XXX TMP
  return

@atTheLobby
  echo_[fn locationName$(theLobby)+"."]
  return

@atTheReception
  echo_[fn locationName$(theReception)+"."]
  // XXX TODO create the things
  # echo["Varias ventanillas."]
  return

@atTheLiving
  echo[fn locationName$(theLiving)+". "]:\
  // XXX TODO create the mentioned things
  echoTxt_[fn currentLocationTxt()]:\ // XXX TMP
  return

@atTheCorridorA
  echo_[fn locationName$(theCorridorA)+"."]
  return

@atTheCorridorB
  echo_[fn locationName$(theCorridorB)+"."]
  return

@atTheCorridorC
  echo_[fn locationName$(theCorridorC)+"."]
  return

@atTheCorridorD
  echo_[fn locationName$(theCorridorD)+"."]
  return

@atTheCorridorE
  echo_[fn locationName$(theCorridorE)+"."]
  return

@atTheCorridorF
  echo_[fn locationName$(theCorridorF)+"."]
  return

@atTheBathroomA
  echo_[fn locationName$(theBathroomA)+"."]
  return

@atTheChapel
  echo_[fn locationName$(theChapel)+"."]
  return

@atTheDining
  echo_[fn locationName$(theDining)+"."]
  return

@atTheOfficeA
  echo_[fn locationName$(theOfficeA)+"."]
  return

@atTheOfficeB
  echo_[fn locationName$(theOfficeB)+"."]
  return

@atTheOfficeC
  echo_[fn locationName$(theOfficeC)+"."]
  return

@atTheClassA
  echo_[fn locationName$(theClassA)+"."]
  return

@atTheClassB
  echo_[fn locationName$(theClassB)+"."]
  return

@atTheLibrary
  echo[fn locationName$(theLibrary)+". "]
  // XXX TODO create the things
  echo_["Una montaña de libros polvorientos oculta la pared."]
  return

// }}} ---------------------------------------------------------
// Text output {{{

// Note: blank block graphic are used to force the indentation,
// because the +3e text routines remove leading spaces.

@debug
  // Print a debug message in the debug window.
  // input: t$
  #ifdef debug
    print #debugWin;t$
    return
  #endif

@fatal_error
  // Print a fatal meta error as a justified paragraph in the current window.
  // input: t$
  let t$="ERROR FATAL: "+t$

@error
  // Print a meta error as a justified paragraph in the current window.
  // input: t$
  let t$="{winInk}{red}["+t$+"]{winInk}{outputInk}"
  goto @_echo_

@_echoTxt_
  // input: t (text id of a text file)
  load fn txtFile$(t) data a$():let t$=a$
@_echo_
  // Print a whole justified paragraph in the current window.
  // input: t$
  print #win;"{-8}{-8}";chr$ winJustificationOn;t$ // XXX TMP
  goto @possibleScroll
  
@_echoTxt
  // input: t (text id of a text file)
  load fn txtFile$(t) data a$():let t$=a$
@_echo
  // Start a justified paragraph in the current window.
  // input: t$
  print #win;"{-8}{-8}";:\ // XXX TMP
  goto @echo

@echoTxt
  // input: t (text id of a text file)
  load fn txtFile$(t) data a$():let t$=a$
@echo
  // Print justified text at the current position of the current window.
  // input: t$
#   print #win;"{-8}";chr$ winJustificationOn;t$; // XXX TMP
  print #win;chr$ winJustificationOn;t$;:\ // XXX TMP
  goto @possibleScroll

@clearWin
  print #win;chr$ winCls;chr$ winHome:\
  let printedChars=0:\ // XXX OLD
  return

@echoTxt_
  // input: t (text id of a text file)
  load fn txtFile$(t) data a$():let t$=a$
@echo_
  // End a justified text at the current position of the current window.
  // input: t$
  print #win;chr$ winJustificationOn;t$

@possibleScroll

  // XXX OLD
  // Version that uses an aprox calculation of chars that can be
  // printed on one line of the window:

  # let printedLines=printedLines+int(len t$/winCharsPerLine)
  # #ifdef debug
  #   debug["new lines= "+str$ int(len t$/winCharsPerLine)]
  #   debug["updated printedLines= "+str$ printedLines]
  #   debug["winHeight= "+str$ winHeight]
  #   if printedLines < winHeight then pause 0
  # #endif
  # if printedLines >= winHeight then gosub @textPause
  # return

  // XXX TMP
  // Version that uses an average calculation of chars that can be
  // printed on the window:
  
  # let printedChars=printedChars+len t$:\
  # #ifdef debug
  #   debug["new chars= "+str$ len t$]
  #   debug["printedChars= "+str$ printedChars+"/"+str$ winChars]
  #   debug["win line= "+str$ fn winLine(win)]
  #   debug["PRESS ANY KEY"]:\
  #   pause 0
  # #endif
  # if printedChars < winChars then return
  # #ifdef debug
  #   debug["printedChars >= winChars"]:\
  #   debug["PRESS ANY KEY"]:\
  #   pause 0
  # #endif
  # if fn winLine(win) < winBottom then return
  # #ifdef debug
  #   debug["fn winLin(win) >= winBottom"]:\
  #   debug["PRESS ANY KEY"]:\
  #   pause 0
  # #endif

#  if printedLines < winHeight then return // XXX TMP
  return

@textPause
  #ifdef debug
    debug["@textPAUSE"]:\
    debug["PRESS ANY KEY"]:\
    pause 0
  #endif
#  print #inputWin;"{winCls}... [ XXX ";printedLines;"]":\ // XXX TMP
  print #inputWin;"{winCls}...";:\
  pause val "1e3":\
  print #inputWin;"{winCls}":\
  let printedLines=printedLinesInit
#  let printedChars=0 // XXX OLD
#  #ifdef debug
#    debug["printedChars reseted= "+str$ printedChars+"/"+str$ winChars]
#  #endif
  return

// }}} ---------------------------------------------------------
// Init {{{

defproc gameInit

  // Init needed before every game.

  randomize
  gosub @clearWin
  // XXX TODO message or picture

  // Flags
  let gameOver=false:\
  let multitasking=true:\
  let safeOpened=false:\
  let guardMet=false:\ // XXX not used yet
  let light=true // XXX TMP for debugging

  // The safe code

  // XXX TODO -- new method for the code
  for n=1 to safeCodeDigits
    let safeCode$(n)=chr$ fn between(48,57) // digit 0-9
  next n

  // Done actions

  // This array stores how many times an action has been done with
  // every thing:
  // XXX TODO -- not used yet

  dim done(actions,things)

  // Default location of things
 
  load "location.dat" data location():\
  
  // Random location of some things

  // XXX FIXME -- do this only to things marked to do so
  // (they can have a negative constant in the location).
  for n=1 to things
    if syntax(toTake,n) then
      do
        # let i=fn between(1,locations)
        let i=theOfficeA // XXX TMP for debugging
      loop while outside(i)
      let location(n)=i
    endif
  next n

  // Special location of some things

  // Location of the pots
  // XXX FIXME -- this is already done in the data,
  // but still required until the random loop above
  // is fixed.
  for n=thePotA to thePotE:\
    let location(n)=theEntranceA+n-thePotA:\
  next n
  
  let location(theSafe)=theOfficeA:\
  let location(theBooks)=theLibrary:\ // XXX needed? could be set in the original data
  let location(theTorch)=\
    code fn char$(\
      chr$ theOfficeC+\
      chr$ theReception+\
      chr$ theClassA+\
      chr$ theClassB+\
      chr$ theJunkRoom\
    ):\
  let location(theKey)=theLimbo

  // Location of the protagonist
#   let currentLocation=fn between(theEntranceA,theEntranceE):\
  let currentLocation=theHall // XXX TMP
  let previousLocation=0

  // Location of the guard
  do
    let location(theGuard)=fn between(theEntranceA,theEntranceE)
  loop until not fn aroundHere(theGuard)
  
  // Plot
  let keyPot=fn between(thePotA,thePotD):\ // the pot the key is hidden into
  let examinedPots=0:\ // counter
  let lastPot=0:\ // last pot manipulated by the protagonist

  let carried=0 // number of things currently carried

  // XXX OLD
  # // Open the door of a random entrance
  # let i=fn between(theEntranceA,theEntranceD) // random entrance
  # // First, open the door of the chosen entrance
  # // Note: one exit location can be in a cardinal direction and in theInside
  # for n=theEast to theInside // the rest can be ignored in this case
  #   let anExit=exit(i,n):\
  #   if anExit>locked then \
  #     let anExit=anExit-locked:\
  #     let exit(i,n)=anExit
  # next n
  # // Second, open the door of its connected location
  # //  i = entrance location
  # //  anExit = location the entrance leads to
  # for n=theEast to theOutside // the rest can be ignored in this case
  #   if exit(anExit,n)=i+locked then \
  #     let exit(anExit,n)=i
  # next n

  setTextWin // default window
  gosub @clearWin

  // Common attributes for all location pictures:
  // XXX FIXME -- the change is still visible (an emulator issue?)
  if showGraphics then \
    let void=usr cl1st3rd
  
   // Reset the time
  poke FRAMES,not pi:\
  poke FRAMES1,not pi:\
  poke FRAMES2,not pi

endproc

defproc credits

  cls
  _echo_["CE4"]
  _echo_["(C) 2014,2015 Marcos Cruz (programandala.net)"]
  _echo_["Licencia/Permesilo/License: GPL 3"]
  _echo_["Memoria libre: "+str$ fn freeMemory()+" B"]
  
  // XXX TMP
#   print '"Pulsa una tecla para empezar."
  pause 200

endproc

defproc intro

  // Print the intro

  cls:\
  setFullWin:\
  for i=1000 to 1003:\
    _echoTxt_[i]:\
  next i:\
  gosub @textPause

endproc

@initOnce

  // This routine is called only once, before the first game.
  //
  // Given the way Sinclair BASIC manages the jumps, this routine is
  // placed at the end of the code. This way it does not make the rest
  // of the code slower.  
  //
  // This routine can not be called with GOSUB because it contains a
  // CLEAR.

  // Screen

  border black:\
  paper black:\
  ink white:\
  bright false:\
  flash false:\

  clear z80_clear_address:\
  load "c:":\

  // The binary file contains the Z80 routines and the UDGs
  load "ce4.bin" code z80_load_address:\
  let void=fn dpoke(UDG,ce4_udg):\ // point to the UDG

  // Constants

  let maxCarried=3:\ // maximum number of things that can be carried XXX TMP
  let safeCodeDigits=4:\

  // Variables

  let showGraphics=true:\ // mode let multitasking=true:\
  let banished=false:\ 
  let recordHours=0:\
  let recordMinutes=16:\
  let recordSeconds=0:\
  let totalRecordSeconds=recordMinutes*60:\
  let recordMan$="Lutero":\
  dim accept$(32):\ // accept text buffer
  let command$="":\ // XXX necessary?
  dim safeCode$(safeCodeDigits):\
  acceptInit:\

  // Screen

  windows:\
 
  // Files 

  dim a$(1):\ // to load the text arrays
 
  // All arrays have been created by <ce4.data_maker.vbas>
  // (<C:DATAMAKE.BAS> in the ZX Spectrum disk) and then converted
  // into an empty BASIC file by <ce4.data_packer.vbas>
  // (<C:DATAPACK.BAS> in the ZX Spectrum disk).  This is the fastest
  // way to load all the data:

  merge "data.bas":\

goto @main // return

// }}} ---------------------------------------------------------
// Windows {{{

defproc windows

  // Define all windows.

  // The definition string format is:
  // "w>top,left,height,width,csize"

  // The full window does not ocuppy the bottom line,
  // in order to use it for the scrolling prompts.
  let fullWinTop=0:\
  #ifdef debug
    let fullWinWidth=22:\
  #else
    let fullWinWidth=32:\
  #endif
  let fullWinHeight=23:\
  let fullWinCharSize=7:\
  let fullWinBottom=fullWinTop+fullWinHeight-1:\
  close #fullWin:\
  open #fullWin,"w>"+\
    str$ fullWinTop+",0,"+\
    str$ fullWinHeight+","+str$ fullWinWidth+","+\
    str$ fullWinCharSize:\
  print #fullWin;paper black;ink white;chr$ winCls:\ // XXX TMP
#  let fullWinCharsPerLine=int(fullWinWidth*8/fullWinCharSize):\

  // XXX FIXME -- The following calculation is
  // wrong, unless the line is edited in the +3e. That means the bug
  // is in BAS2TAP, that makes a wrong binary format for non-integer
  // numbers.

#  let fullWinChars=int(fullWinHeight*fullWinWidth*fullWinCharSize/ 8 * .75 ):\ // XXX TMP -- average
  // XXX TMP solution:
  let fullWinChars=int(fullWinHeight*fullWinWidth*fullWinCharSize/val"8"*val".75"):\ // XXX TMP -- average

  close #inputWin:\
  open #inputWin,"w>23,0,1,32,8":\
  print #inputWin;paper black;ink inputInk;chr$ winCls // XXX TMP

  modeWindows

endproc

defproc modeWindows

  // Define the windows that depend on the graphics mode.

  // The definition string format is:
  // "w>top,left,height,width,csize"

  // top and height depend on the mode:
  let textWinTop=9*showGraphics:\ // 0 or 9 
  let textWinHeight=21-8*showGraphics:\ // 13 or 21
  let textWinBottom=textWinTop+textWinHeight-1:\
  close #textWin:\
  #ifdef debug
    close #debugWin:\
    open #debugWin,"w>"+str$ textWinTop+",22,"+str$ textWinHeight+",10,6":\
    print #debugWin;chr$ winAttr+chr$ red+chr$ winCls:\
    let textWinWidth=22:\
  #else
    let textWinWidth=32:\
  #endif
  let textWinCharSize=7:\
#  let textWinCharsPerLine=int(textWinWidth*8/textWinCharSize):\

  // XXX FIXME -- The following calculation is
  // wrong, unless the line is edited in the +3e. That means the bug
  // is in BAS2TAP, that makes a wrong binary format for non-integer
  // numbers.

#  let textWinChars=int(textWinHeight*textWinWidth*textWinCharSize/8*.75):\ // XXX TMP -- average
// XXX TODO try with zmakebas

  // XXX TMP solution:
  let textWinChars=int(textWinHeight*textWinWidth*textWinCharSize/val"8"*val".75"):\ // XXX TMP -- average
#  let textWinChars=48 // XXX TMP

  open #textWin,"w>"+\
    str$ textWinTop+",0,"+\
    str$ textWinHeight+","+str$ textWinWidth+","+\
    str$ textWinCharSize:\
  print #textWin;\
    paper black;ink outputInk;\
    chr$ winJustificationMode;chr$ winLeftJustification;\
    chr$ winEmbeddedCodesMode;chr$ winEmbeddedCodesOn;\
    chr$ winCls;
// XXX OLD:
  let printedLines=printedLinesInit // counter used to manage the scroll
#  let printedChars=0 // XXX needed?

endproc

defproc setTextWin

  // Make the text window the current window

  let win=textWin:\
  let winInfo=fn channel(win):\
  let winHeight=fullWinHeight:\
// XXX OLD
#  let winCharsPerLine=textWinCharsPerLine:\
  let printedLines=printedLinesInit
#  let winChars=textWinChars:\
#  let printedChars=0
#  let winBottom=textWinBottom // for the scroll control

endproc

defproc setFullWin

  // Make the full-screen window the current window

  let win=fullWin:\
  let winInfo=fn channel(win):\
  let winHeight=textWinHeight:\
// XXX OLD
#  let winCharsPerLine=fullWinCharsPerLine:\
  let printedLines=printedLinesInit
#  let winChars=fullWinChars:\
#  let printedChars=0
#  let winBottom=fullWinBottom // for the scroll control

endproc

// }}} ---------------------------------------------------------
// Meta {{{

defproc longPhonyText // XXX TMP

  # for i=sgn pi to val "5"
  #   _echo[str$ i+": En un lugar de La Mancha de cuyo nombre no quiero acordarme, "]
  #   echo["no ha mucho que vivía un hildalgo de los de lanza en astillero, "]
  #   echo_["rocín flaco y galgo corredor."]
  # next i

endproc

#ifdef debug

  // XXX TMP

  for n=1 to things
  print n,fn wholeName$(n)
  next n

#endif

@firstRun
save "c:ce4.bas" line 1:run

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted src/ce4.version.vbas.

1
2
3
4
// ce4.version.vbas

rem Version 0.2.0+201606201408
//  (after Semantic Versioning: http://semver.org)
<
<
<
<








Deleted src/cl1st3rd.z80s.

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
; z80/cl1st3rd.z80s
;
; This file is part of the CE4 project,
; a text adventure in Spanish
; written in Vimclair BASIC for the ZX Spectrum +3e

; This Z80 routine fills and wipes the first third of the screen.  It's needed
; only once, before the first location picture is loaded, in order to make the
; transition smooth. The reason is the location pictures are just bitmaps
; without attributes, and they require ink white on paper black, the opposite
; of the rest of the screen.

; 2014-08-08: Written.
; 2014-08-10: New: 'halt'.
; 2014-08-11: New: 'proc', 'endp', 'local', 'public'.

proc

  public cl1st3rd

cl1st3rd

  local SCR_ADDRESS 
  SCR_ADDRESS equ 16384 ; address of the screen bitmap
  local ATT_ADDRESS 
  ATT_ADDRESS equ 22528 ; address of the screen attributes

  halt
  ; Fill the first screen third
  ld hl,SCR_ADDRESS
  ld de,SCR_ADDRESS+1
  ld bc,6144/3-1
  ld (hl),0xff ; all pixels set to ink
  ldir
  ; Wipe its attributes
  ld hl,ATT_ADDRESS
  ld de,ATT_ADDRESS+1
  ld bc,768/3-1
  ld (hl),%00111000 ; flash 0, bright 0, paper 7 (white), ink 0 (black)
  ldir
  ret

endp
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































Added src/common.bas.





























































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// common.bas

// This file is part of

rem CE4

// A text adventure in Spanish
// written in GW-BASIC
// with the Imbastardizer preprocessor
// for the PC-BASIC emulator.

// Last modified 201709130120

// Copyright (C) 2014,2016,2017 Marcos Cruz (programandala.net)

// =============================================================

#include target.bas

screen 0
width 80
key off
color 7,0,0
cls
defint a-z
option base 1

#iftarget gwbasic

  // Target: original GW-BASIC, not the PC-BASIC emulator

  // First, convert the encoding from UTF-8 to DOS codepage 850,
  // in order to use the Spanish characters:
  #vim %!iconv -f utf8 -t 850

  // Then, make sure the encoding is 8-bit, even if it's not latin1:
  #vim set fileencoding=latin1

  // Finally, change the end of line format to DOS:
  #vim set fileformat=dos

#endif

// =============================================================
// Subroutines with parameters {{{1

#vim %substitute,\<echo\[\(.\{-}\)],let text$=\1:gosub @wt,gi
#vim %substitute,\<_echo\[\(.\{-}\)],let text$=\1:gosub @wtNewLine,gi
#vim %substitute,\<__echo\[\(.\{-}\)],let text$=\1:gosub @wtNewPara,gi
#vim %substitute,\<error\[\(.\{-}\)],let text$=\1:gosub @error,gi
#vim %substitute,\<fatal_error\[\(.\{-}\)],let text$=\1:gosub @fatal_error,gi
#vim %substitute,\<debug\[\(.\{-}\)],let text$=\1:gosub @debug,gi

// =============================================================
// Valid function names {{{1

// Function names must be replaced before variables, to prevent name
// clashes.

// Actual functions
#vim %substitute,\<\(def\s\?\)\?fn aroundHere(,\1fn a(,gi
#vim %substitute,\<\(def\s\?\)\?fn between(,\1fn b(,gi
#vim %substitute,\<\(def\s\?\)\?fn winFreeCols(,\1fn c(,gi
#vim %substitute,\<\(def\s\?\)\?fn char\$(,\1fn c$(,gi
#vim %substitute,\<\(def\s\?\)\?fn dpeek(,\1fn d(,gi
#vim %substitute,\<\(def\s\?\)\?fn twoDigits\$(,\1fn d$(,gi
#vim %substitute,\<\(def\s\?\)\?fn freeMemory(,\1fn f(,gi
#vim %substitute,\<\(def\s\?\)\?fn txtFile\$(,\1fn f$(,gi
#vim %substitute,\<\(def\s\?\)\?fn hour\$(,\1fn h$(,gi
#vim %substitute,\<\(def\s\?\)\?fn channel(,\1fn h(,gi
#vim %substitute,\<\(def\s\?\)\?fn instr(,\1fn i(,gi
#vim %substitute,\<\(def\s\?\)\?fn lookup8(,\1fn k(,gi
#vim %substitute,\<\(def\s\?\)\?fn lookup16(,\1fn l(,gi
#vim %substitute,\<\(def\s\?\)\?fn name\$(,\1fn n$(,gi
#vim %substitute,\<\(def\s\?\)\?fn dpoke(,\1fn o(,gi
#vim %substitute,\<\(def\s\?\)\?fn wholeName\$(,\1fn p$(,gi
#vim %substitute,\<\(def\s\?\)\?fn random(,\1fn r(,gi
#vim %substitute,\<\(def\s\?\)\?fn seconds(,\1fn s(,gi
#vim %substitute,\<\(def\s\?\)\?fn tics(,\1fn t(,gi
#vim %substitute,\<\(def\s\?\)\?fn thingArticle\$(,\1fn t$(,gi
#vim %substitute,\<\(def\s\?\)\?fn trunc\$(,\1fn u$(,gi
#vim %substitute,\<\(def\s\?\)\?fn term(,\1fn w(,gi
#vim %substitute,\<\(def\s\?\)\?fn termn$(,\1fn w$(,gi
#vim %substitute,\<\(def\s\?\)\?fn currentLocationTxt(,\1fn x(,gi
#vim %substitute,\<\(def\s\?\)\?fn winLine(,\1fn y(,gi

// =============================================================
// Constants {{{1

// XXX TMP -- The protagonist could be an ordinary thing other things
// could be located at, but things and locations should be joined into
// one single array. At the moment, it's easier this way:
#vim %substitute,\<theProtagonist\>,-1,gi
// Note: this has to do with the protagonist's 'location' variable.
// Should the protagonist be a thing, the 'thingLocation()' array could be
// used instead.

#vim %substitute,\<TRUE\>,-1,gi
#vim %substitute,\<FALSE\>,0,gi

#vim %substitute,\<noExit\>,0,gi

#vim %substitute@\([a-zA-Z]\+\)+locked@-\1@g
# #vim %substitute,\<locked\>,100,gi

// Noun attributes
#vim %substitute,\<neuter\>,1,gi
#vim %substitute,\<masculine\>,2,gi
#vim %substitute,\<femenine\>,3,gi
#vim %substitute,\<singular\>,1,gi
#vim %substitute,\<plural\>,2,gi

// Article types
#vim %substitute,\<indefinite\>,1,gi
#vim %substitute,\<definite\>,2,gi
#vim %substitute,\<possesive\>,3,gi

// XXX OLD
# #vim %substitute,\<noone\>,12,gi
# #vim %substitute,\<someone\>,16,gi

// Counts
#vim %substitute,\<totalPots\>,5,gi

// Chars

#vim %substitute,\<BACKSPACE\>,8,gi
#vim %substitute,\<ENTER\>,13,gI
#vim %substitute,\<SPACE\>,32,gi


// =============================================================
// Thing identifiers and count {{{1

// ---------------------------------------------

// This substitution modifies the #vim directives that substitute the
// thing identifiers:
#previm let b:enum=1
#previm /ThingIds\[/,/\]ThingIds/substitute,{enum},\=Enum(),gi

#vim " ThingIds[ "

// ---------------------------------------------
// Directions

// The cardinal points and directions must be the first identifiers,
// and they must be in the given order (north, south, east, west,
// inside and outside):

#vim %substitute,\<theNorth\>,{enum},gi
#vim %substitute,\<theSouth\>,{enum},gi
#vim %substitute,\<theEast\>,{enum},gi
#vim %substitute,\<theWest\>,{enum},gi
#vim %substitute,\<theInside\>,{enum},gi
#vim %substitute,\<theOutside\>,{enum},gi

// The order of the rest is not important:

// ---------------------------------------------
// Non-portable things

#vim %substitute,\<noThing\>,{enum},gI
#vim %substitute,\<theAll\>,{enum},gi
#vim %substitute,\<theBooks\>,{enum},gi
#vim %substitute,\<theDiningTables\>,{enum},gi
#vim %substitute,\<theDoor\>,{enum},gi
#vim %substitute,\<theInventory\>,{enum},gi
#vim %substitute,\<theLivingTable\>,{enum},gi
#vim %substitute,\<theNo\>,{enum},gi
#vim %substitute,\<theWallA\>,{enum},gi
#vim %substitute,\<theWallB\>,{enum},gi
#vim %substitute,\<theWallC\>,{enum},gi
#vim %substitute,\<theWallD\>,{enum},gi
#vim %substitute,\<theWallE\>,{enum},gi
#vim %substitute,\<theYes\>,{enum},gi

// ---------------------------------------------
// Portable things

#vim %substitute,\<firstPortable\>,theBallPen,gi

#vim %substitute,\<theBallpen\>,{enum},gi
#vim %substitute,\<theBrick\>,{enum},gi
#vim %substitute,\<theGuard\>,{enum},gi
#vim %substitute,\<theKey\>,{enum},gi
#vim %substitute,\<thePaperPiece\>,{enum},gi
#vim %substitute,\<thePaperSheet\>,{enum},gi
#vim %substitute,\<thePencil\>,{enum},gi
#vim %substitute,\<thePotA\>,{enum},gi
#vim %substitute,\<thePotB\>,{enum},gi
#vim %substitute,\<thePotC\>,{enum},gi
#vim %substitute,\<thePotD\>,{enum},gi
#vim %substitute,\<thePotE\>,{enum},gi
#vim %substitute,\<theSafe\>,{enum},gi
#vim %substitute,\<theShoe\>,{enum},gi
#vim %substitute,\<theSock\>,{enum},gi

#vim %substitute,\<lastPortable\>,theTorch,gi

#vim %substitute,\<theTorch\>,{enum},gi

// ---------------------------------------------
// Ambiguous things

// Ambiguous things share a common name, so the actual thing must be
// calculated from their location or other data. E.g. there are
// several tables in different locations.

#vim %substitute,\<firstAmbiguous\>,thePotX,gi

// These substitutions must be in order (the alphabetical order of
// thing ids must match the numerical order of their values):

#vim %substitute,\<thePotX\>,{enum},gi
#vim %substitute,\<theTableX\>,{enum},gi

#vim %substitute,\<things\>,theWallX,gi // 'things' = last thing defined:

#vim %substitute,\<theWallX\>,{enum},gi

// ---------------------------------------------

#vim " ]ThingIds "

// =============================================================
// Action identifiers and count {{{1

// The list must be in alphabetical Order of ids, to match the values
// of the correspondent action labels defined in <main.bas>.

// Note: the Vim's 'sort' command doesn't give the same result on both
// lists, because the char after the id is different. This list has to
// be manually adjusted in order to match the list in <main.bas>.

// Note: the 'I' flag (to force case-sensitive substitutions) is used
// only to prevent clashes, e.g. when the identifier matchs a Spanish
// word used in the texts of the program.

// This substitution modifies the #vim directives that replace the
// action identifiers:
#previm let b:enum=1
#previm /actionIds\[/,/\]actionIds/substitute,{enum},\=Enum(),gi

#vim " actionIds[ "

#vim %substitute,\<toDo\>,{enum},gI
#vim %substitute,\<toDrop\>,{enum},gi
#vim %substitute,\<toExamine\>,{enum},gi
#vim %substitute,\<toGo\>,{enum},gi
#vim %substitute,\<toGoEast\>,{enum},gi
#vim %substitute,\<toGoIn\>,{enum},gi
#vim %substitute,\<toGoNorth\>,{enum},gi
#vim %substitute,\<toGoOut\>,{enum},gi
#vim %substitute,\<toGoSouth\>,{enum},gi
#vim %substitute,\<toGoWest\>,{enum},gi
#vim %substitute,\<toInventory\>,{enum},gi
#vim %substitute,\<toLook\>,{enum},gi
#vim %substitute,\<toOpen\>,{enum},gi
#vim %substitute,\<toRead\>,{enum},gi
#vim %substitute,\<toShowGraphics\>,{enum},gi
#vim %substitute,\<toTake\>,{enum},gi
#vim %substitute,\<toTurnOff\>,{enum},gi
#vim %substitute,\<toTurnOn\>,{enum},gi

#ifdef debug
  #vim %substitute,\<toDebug\>,{enum},gi
#endif

#vim %substitute,\<actions\>,\=b:enum-1,gi

#vim " ]actionIds "

// =============================================================
// Location identifiers and count {{{1

// The values should not be changed, because some algorithms depend on
// them.
//
// The ids from `theEntranceA` to `theEntranceE` must be defined in
// alphabetical order and their values must be consecutive.

#vim %substitute,\<theLimbo\>,0,gi

#vim %substitute,\<theBasement\>,1,gi
#vim %substitute,\<theBathroomA\>,2,gi
#vim %substitute,\<theBathroomB\>,3,gi
#vim %substitute,\<theChapel\>,4,gi
#vim %substitute,\<theClassA\>,5,gi
#vim %substitute,\<theClassB\>,6,gi
#vim %substitute,\<theCorridorA\>,7,gi
#vim %substitute,\<theCorridorB\>,8,gi
#vim %substitute,\<theCorridorC\>,9,gi
#vim %substitute,\<theCorridorD\>,10,gi
#vim %substitute,\<theCorridorE\>,11,gi
#vim %substitute,\<theCorridorF\>,12,gi
#vim %substitute,\<theDining\>,13,gi
#vim %substitute,\<theEntranceA\>,14,gi
#vim %substitute,\<theEntranceB\>,15,gi
#vim %substitute,\<theEntranceC\>,16,gi
#vim %substitute,\<theEntranceD\>,17,gi
#vim %substitute,\<theEntranceE\>,18,gi
#vim %substitute,\<theGym\>,19,gi
#vim %substitute,\<theHall\>,20,gi
#vim %substitute,\<theJunkRoom\>,21,gi
#vim %substitute,\<theKitchen\>,22,gi
#vim %substitute,\<theLarder\>,23,gi
#vim %substitute,\<theLibrary\>,24,gi
#vim %substitute,\<theLiving\>,25,gi
#vim %substitute,\<theLobby\>,26,gi
#vim %substitute,\<theOfficeA\>,27,gi
#vim %substitute,\<theOfficeB\>,28,gi
#vim %substitute,\<theOfficeC\>,29,gi
#vim %substitute,\<theReception\>,30,gi

#vim %substitute,\<locations\>,30,gi

# vim:filetype=imbastardizer

Deleted src/fn_dpeek.z80s.

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
; fn_dpeek.z80s 
;
; DPEEK BASIC function for ZX Spectrum

; Version B-00-20150122

; This file is part of DEFFNder:
; http://programandala.net/en.program.deffnder.html

; --------------------------------------------------------------
; Author and license

; Copyright (C) 2014,2015 Marcos Cruz (programandala.net)

; You may do whatever you want with this work, so long as you
; retain the copyright notice(s) and this license in all
; redistributed copies and derived works. There is no warranty.

; --------------------------------------------------------------
; Description

; This code adds a DPEEK function to Sinclair BASIC, that
; returns the 16-bit value from a memory address.

; --------------------------------------------------------------
; Usage

; The routine is called from BASIC using a function defined this
; way (the actual names are unimportant):
;   10 DEF FN d(a)=USR dpeek
; Where:
;   a     = address to peek
;   dpeek = address of the machine code routine

; Example:
;   PRINT FN d(1887)

; --------------------------------------------------------------
; Internal

; During the execution of a FN, the system variable DEFADD holds
; the address of the first parameter of its DEF FN definition
; (the first address after the opening paren). The structure of
; DEF FN d(a) is the following:

; offset  content
; ------  -------
; -03     DEF FN
; -02     d
; -01     (
; +00     a
; +01     14
; +02     0
; +03     [sign byte: 0=positive; 255=negative]
; +04     [16-bit number, LSB first]
; +06     0
; +07     )
; +08     =

; --------------------------------------------------------------
; History of this file

; 2014-08-07: Written.
;
; 2014-08-10: Removed unnecessary saving and restoring of
; registers.  New: 'proc', 'local' and 'public', in order to
; make it possible to combine several modules into a single
; file.
;
; 2015-01-22: Some changes for publication. Version B-00.
;
; 2015-02-27: Improved comment.
;
; 2015-08-10: Revision. License.

; --------------------------------------------------------------

  proc

  ; The code is relocatable

  public fn_dpeek,fn_dpeek_size
fn_dpeek:

  local DEFADD
  DEFADD equ 23563 ; system variable

  ld ix,(DEFADD)
  ld l,(ix+4)
  ld h,(ix+5)
  ; hl = parameter address
  ld c,(hl)
  inc hl
  ld b,(hl)
  ; bc = value, returned by USR
  ret

fn_dpeek_size equ $-fn_dpeek

  endp

; vim: textwidth=64
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































































































































































































Deleted src/fn_dpoke.z80s.

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
; fn_dpoke.z80s 
;
; DPOKE BASIC function for ZX Spectrum

; Version B-00-20150122

; This file is part of DEFFNder:
; http://programandala.net/en.program.deffnder.html

; --------------------------------------------------------------
; Author and license

; Copyright (C) 2014,2015 Marcos Cruz (programandala.net)

; You may do whatever you want with this work, so long as you
; retain the copyright notice(s) and this license in all
; redistributed copies and derived works. There is no warranty.

; --------------------------------------------------------------
; Description

; This code adds a DPOKE function to Sinclair BASIC, that pokes
; a 16-bit value into a memory address.

; --------------------------------------------------------------
; Usage

; A function must be defined this way.
; (the actual names are unimportant):
;   10 DEF FN p(a,n)=USR dpoke
; Where:
;   a     = address to poke into
;   n     = 16-bit number to poke
;   dpoke = address of the machine code routine

; Example:
;   RANDOMIZE FN p(22528,1024)

; --------------------------------------------------------------
; Internal

; During the execution of a FN, the system variable DEFADD holds
; the address of the first parameter of its DEF FN definition
; (the first address after the opening paren). The structure of
; DEF FN d(a) is the following:

; offset  content
; ------  -------
; -03     DEF FN
; -02     p(
; +00     a
; +01     14
; +02     0
; +03     [sign byte: 0=positive; 255=negative]
; +04     [16-bit number, LSB first]
; +06     0
; +07     ,
; +08     n
; +09     14
; +10     0
; +11     [sign byte: 0=positive; 255=negative]
; +12     [16-bit number, LSB first]
; +14     0
; +15     )=

; --------------------------------------------------------------
; History

; 2014-08-10: Written 
;
; 2015-01-22: Some changes for publication. Version B-00.
;
; 2015-02-25: Typo in "Internal".
;
; 2015-02-27: Improved comment.
;
; 2015-08-10: Revision. License.

; --------------------------------------------------------------

  proc

  ; The code is relocatable

  public fn_dpoke,fn_dpoke_size
fn_dpoke:

  local DEFADD
DEFADD equ 23563 ; system variable

  ld ix,(DEFADD)
  ld l,(ix+4)
  ld h,(ix+5)
  ; hl = address
  ld e,(ix+12)
  ld d,(ix+13)
  ; de = number 
  ld (hl),e
  inc hl
  ld (hl),d
  ret

fn_dpoke_size equ $-fn_dpoke

  endp

; vim: textwidth=64
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































































































































































Deleted src/fn_instr1.z80s.

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
; fn_instr1.z80s
;
; Simplified INSTR BASIC function for ZX Spectrum

; Version B-00-20150122

; This file is part of DEFFNder:
; http://programandala.net/en.program.deffnder.html

; --------------------------------------------------------------
; Authors and license

; Copyright (C) 1986 Ricardo Serrial Wigge
;   1986-05, original version.
;   Published in:
;     Microhobby magazine, issue 77 (1986-05-06), pages 22-24:
;     http://microhobby.org/
;     http://microhobby.speccy.cz/mhf/077/MH077_22.jpg
;     http://microhobby.speccy.cz/mhf/077/MH077_23.jpg
;     http://microhobby.speccy.cz/mhf/077/MH077_24.jpg

; Copyright (C) 2014,2015 Marcos Cruz (programandala.net)
;   2014-08, modified version.

; You may do whatever you want with this work, so long as you
; retain the copyright notice(s) and this license in all
; redistributed copies and derived works. There is no warranty.

; --------------------------------------------------------------
; Usage

; The routine is called from BASIC using a function defined this way
; (the actual names are unimportant):
;   10 DEF FN i(h$,n$)=USR instr1
; Where:
;   h$     = the haystack, the searched string
;   n$     = the needle, the string to be searched for
;   instr1 = address of the machine code routine

; Example:
;   PRINT FN i("En vilagxo de La Mancxo kies nomon mi ne...","Mancxo")

; --------------------------------------------------------------
; Internal

; During the execution of a FN, the system variable DEFADD holds
; the address of the first parameter of its DEF FN definition
; (the first address after the opening paren). The structure of
; DEF FN i(h$,n$) is the following:

; offset  content
; ------  -------
; -03     DEF FN
; -02     i
; -01     (
; +00     h
; +01     $
; +02     14
; +03     [string type]      
; +04     [string address, LSB first]
; +06     [string length, LSB first]
; +08     ,
; +09     n
; +10     $
; +11     14
; +12     [string type]      
; +13     [string address, LSB first]
; +15     [string length, LSB first]
; +17     )
; +18     =

; --------------------------------------------------------------
; History of this file

; 2014-08-06: This modified version doesn't use the position
; parameter. The search is done always from the start of the
; haystack.
;
; 2014-08-10: Removed unnecessary saving and restoring of
; registers.  New: 'proc', 'local' and 'public', in order to
; make it possible to combine several modules into a single
; file.
;
; 2015-01-22: Some typos fixed. Credits improved. Some changes
; for publication. Version B-00.
;
; 2015-02-27: Improved comment.
;
; 2015-08-10: Revision. License.

; --------------------------------------------------------------

  proc

  ; The code is relocatable

  public fn_instr1,fn_instr1_size
fn_instr1:

  local again
  local exit
  local found
  local haystack_exhausted
  local match
  local needle_exhausted
  local not_found

; ..............................
; System variables

  local DEFADD
DEFADD equ 23563

; ..............................
; Parameters

  ld ix,(DEFADD)
  ld a,(ix+6)
  or (ix+7) ; empty string?
  jr z, not_found

  ld e,(ix+4)
  ld d,(ix+5)
  ; de = address of h$
  ld l,(ix+6)
  ld h,(ix+7)
  ; hl = length of h$
  add hl,de
  ; hl = address after the end of h$

  ; Use ix+6 as temporary storage
  ld (ix+6),l
  ld (ix+7),h

  ld l,e
  ld h,d
  ; hl = address of h$

; ..............................
again:

  ; Start searching h$ for n$ from the current position of h$

  ld e,(ix+13)
  ld d,(ix+14)
  dec de
  ; de = address of n$ -1
  ld c,(ix+15)
  ld b,(ix+16)
  ; bc =length of n$

; ..............................
match:
  
  ; Keep on searching h$

  inc de
  ; de = address of current char of n$
  ; hl = address of current char of h$
  ld a,(de)
  cpi ; compare a with (hl) and increment hl
  ex af,af'
  push hl
  push de

  ld e,(ix+6)
  ld d,(ix+7)
  ; de = address after the end of h$
  and a
  sbc hl,de
  ; z = last char of h$?
  pop de
  pop hl
  jr z,haystack_exhausted 

  ld a,b
  or c
  ; z = last char of n$?
  jr z,needle_exhausted

  ex af,af'
  ; z = (hl)=(de)?
  jr z,match
  jr again

; ..............................
needle_exhausted:

  ex af,af'
  ; z = (hl)=(de)?
  jr nz,again
  jr found

; ..............................
haystack_exhausted:

  ld a,b
  or c
  ; z = bc=0?
  jr nz,not_found

  ex af,af'
  ; z = (hl)=(de)?
  jr z,found

; ..............................
not_found:

  ld bc,0
  jr exit

; ..............................
found:

  ; hl = address of current char of h$
  ld e,(ix+4)
  ld d,(ix+5)
  ; de = address of h$
  and a
  sbc hl,de
  ; hl = offset to the current char of h$
  ld e,(ix+15)
  ld d,(ix+16)
  ; de = length of n$
  and a
  sbc hl,de
  inc hl
  ; hl = position of n$ in h$
  ld b,h
  ld c,l
  ; bc = position of n$ in h$

; ..............................
exit:

  ; bc = position of n$ in h$ (or zero)
  ret

fn_instr1_size equ $-fn_instr1

  endp

; vim: textwidth=64
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































































































































































































































































































































































































































Deleted src/fn_lookup16.z80s.

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
; fn_lookup16.z80s
;
; A database BASIC function for ZX Spectrum

; Version B-00-20150813

; This file is part of DEFFNder:
; http://programandala.net/en.program.deffnder.html

; --------------------------------------------------------------
; Author and license

; Copyright (C) 2014,2015 Marcos Cruz (programandala.net)

; You may do whatever you want with this work, so long as you
; retain the copyright notice(s) and this license in all
; redistributed copies and derived works. There is no warranty.

; --------------------------------------------------------------
; Description

; This code adds a function to Sinclair BASIC that searchs a
; lookup table of 16-bit values, stored in a string, for a
; 16-bit key value, and returns its associated value.

; --------------------------------------------------------------
; Usage

; A BASIC function must be defined this way:
; (the actual names are unimportant):
;   10 DEF FN f(h$,k)=USR lookup16
; Where:
;   h$       = the haystack, the searched string,
;              with the following structure:
;              every 16-bit key precedes its associated
;              16-bit value; both are stored in two bytes
;              (chars of the string), in the usual Z80 format
;              (least significant byte first).
;   k        = the key to be searched for
;   lookup16 = address of the machine code routine

; Example for a text adventure, where a$ holds a lookup table of
; actions associated to line numbers:
;   GO TO FN f(a$,action)
  
; WARNING: As explained above, the haystack string must consist
; of groups of exactly 4 bytes: a 16-bit key followed by its
; 16-bit value. When the string is not well formed (for example,
; any single character is missing), the end check will fail and
; strange things will happen.

; --------------------------------------------------------------
; Internal

; During the execution of a FN, the system variable DEFADD holds
; the address of the first parameter of its DEF FN definition
; (the first address after the opening paren). The structure of
; DEF FN i(h$,n) is the following:

; offset  content
; ------  -------
; -04     DEF FN
; -03     f(
; +00     h$
; +02     14
; +03     [string type]      
; +04     [string address, LSB first]
; +06     [string length, LSB first]
; +08     ,
; +09     k
; +10     14
; +11     0
; +12     [sign byte: 0=positive; 255=negative]
; +13     [16-bit number, LSB first]
; +15     0
; +16     )=

; --------------------------------------------------------------
; History of this file

; 2015-02-28: First version (started with the code of
; <fn_termn.z80s>).
;
; 2015-03-01: Fix: Usage.
;
; 2015-08-10: Revision. License.
;
; 2015-08-13: Fixed typo in the usage instructions. Thanks Derek
; (http://www.worldofspectrum.org/forums/discussion/comment/831230/#Comment_831230).

; --------------------------------------------------------------

  proc

  ; The code is relocatable

  public fn_lookup16,fn_lookup16_size
fn_lookup16:

  local check
  local next
  local found

; ..............................
; System variables

  local DEFADD
DEFADD equ 23563

; ..............................
; Parameters

  ld ix,(DEFADD)

  ld c,(ix+6)
  ld b,(ix+7)
  ; bc = len of h$
  ld a,b
  or c ; is h$ empty?
  ret z ; if so, back to BASIC (the function returns 0)
  ld l,(ix+4)
  ld h,(ix+5)
  ; hl = start of h$
  ld e,(ix+13)
  ld d,(ix+14)
  ; de = k

; ..............................
check:

  ; Check the current key

  ; hl = address of the current key
  ; de = key searched for

  ld a,(hl)
  cp e
  inc hl
  jr nz,next
  ld a,(hl)
  cp d
  jr z,found

next:

  ; hl = address of the second byte of the current key
  ; bc = remaining length

  inc hl
  inc hl
  inc hl ; hl = address of the next key
  dec bc
  dec bc
  dec bc
  dec bc ; bc = remaining chars
  ld a,b
  or c ; end of the haystack?
  ret z ; if so, back to BASIC (the function returns 0)
  
  jr check

found:

  ; The key was found

  ; hl = address of the second byte of the current key

  inc hl
  ld c,(hl)
  inc hl
  ld b,(hl)
  ; bc =  value
  ret ; back to BASIC (the function returns the value)


fn_lookup16_size: equ $-fn_lookup16

  endp

; vim: textwidth=64
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































































































































































































































































































Deleted src/fn_lookup8.z80s.

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
; fn_lookup8.z80s
;
; A database BASIC function for ZX Spectrum

; Version B-00-20150813

; This file is part of DEFFNder:
; http://programandala.net/en.program.deffnder.html

; --------------------------------------------------------------
; Author and license

; Copyright (C) 2014,2015 Marcos Cruz (programandala.net)

; You may do whatever you want with this work, so long as you
; retain the copyright notice(s) and this license in all
; redistributed copies and derived works. There is no warranty.

; --------------------------------------------------------------
; Description

; This code adds a function to Sinclair BASIC that searchs a
; lookup table of 8-bit values, stored in a string, for a
; 8-bit key value, and returns its associated value.

; --------------------------------------------------------------
; Usage

; A BASIC function must be defined this way:
; (the actual names are unimportant):
;   10 DEF FN f(h$,k)=USR lookup8
; Where:
;   h$       = the haystack, the searched string,
;              with the following structure:
;              every 8-bit key precedes its associated
;              8-bit value.
;   k        = the key to be searched for
;   lookup8 = address of the machine code routine

; Example of a key translation table:
;   LET t$=CHR$ 200 + CHR$ 160 + CHR$ 203 + CHR$ 162
;   LET key=FN f(t$,key)

; WARNING: As explained above, the haystack string must consist
; of pairs of chars.  When the string is not well formed (for
; example, any single character is missing), the end check will
; fail and strange things will happen.

; --------------------------------------------------------------
; Internal

; During the execution of a FN, the system variable DEFADD holds
; the address of the first parameter of its DEF FN definition
; (the first address after the opening paren). The structure of
; DEF FN i(h$,n) is the following:

; offset  content
; ------  -------
; -04     DEF FN
; -03     f(
; +00     h$
; +02     14
; +03     [string type]      
; +04     [string address, LSB first]
; +06     [string length, LSB first]
; +08     ,
; +09     k
; +10     14
; +11     0
; +12     [sign byte: 0=positive; 255=negative]
; +13     [16-bit number, LSB first]
; +15     0
; +16     )=

; --------------------------------------------------------------
; History of this file

; 2015-03-01: First version (started with the code of
; <fn_lookup16.z80s>).
;
; 2015-08-10: Revision. License.
;
; 2015-08-13: Fixed typo in the usage instructions. Thanks Derek
; (http://www.worldofspectrum.org/forums/discussion/comment/831230/#Comment_831230).

; --------------------------------------------------------------

  proc

  ; The code is relocatable

  public fn_lookup8,fn_lookup8_size
fn_lookup8:

  local check
  local next
  local found

; ..............................
; System variables

  local DEFADD
DEFADD equ 23563

; ..............................
; Parameters

  ld ix,(DEFADD)

  ld c,(ix+6)
  ld b,(ix+7)
  ; bc = len of h$
  ld a,b
  or c ; is h$ empty?
  ret z ; if so, back to BASIC (the function returns 0)
  ld l,(ix+4)
  ld h,(ix+5)
  ; hl = start of h$
  ld e,(ix+13)
  ; e = k

; ..............................
check:

  ; Check the current key

  ; hl = address of the current key
  ; e = key searched for

  ld a,(hl)
  cp e
  inc hl
  jr z,found

next:

  ; hl = address of the current value
  ; bc = remaining length

  inc hl ; hl = address of the next key
  dec bc
  dec bc ; bc = remaining chars
  ld a,b
  or c ; end of the haystack?
  ret z ; if so, back to BASIC (the function returns 0)
  
  jr check

found:

  ; The key was found

  ; hl = address of the current value

  ld c,(hl)
  ld b,0
  ; bc =  value
  ret ; back to BASIC (the function returns the value)


fn_lookup8_size: equ $-fn_lookup8

  endp

; vim: textwidth=64
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































































































































































































































Deleted src/fn_term.z80s.

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
; fn_term.z80s
;
; A database BASIC function for ZX Spectrum

; Version B-00-20150122

; This file is part of DEFFNder:
; http://programandala.net/en.program.deffnder.html

; --------------------------------------------------------------
; Author and license

; Copyright (C) 2014,2015 Marcos Cruz (programandala.net)
;
; Based on code written by Ricardo Serrial Wigge, published in:
;   Microhobby magazine, issue 77 (1986-05-06), pages 22-24:
;   http://microhobby.org/
;   http://microhobby.speccy.cz/mhf/077/MH077_22.jpg
;   http://microhobby.speccy.cz/mhf/077/MH077_23.jpg
;   http://microhobby.speccy.cz/mhf/077/MH077_24.jpg

; You may do whatever you want with this work, so long as you
; retain the copyright notice(s) and this license in all
; redistributed copies and derived works. There is no warranty.

; --------------------------------------------------------------
; Description

; This code adds a function to Sinclair BASIC that
; returns the identifier of a given term in a list of terms.

; --------------------------------------------------------------
; Usage:
;
; A BASIC function must be defined this way
; (the actual names are unimportant):
;   10 DEF FN t(h$,n$)=USR term
; Where:
;   h$    = the haystack, the searched string,
;           with the following structure:
;           every term is prefixed by byte 0, and followed
;           by byte 14 and an id byte.
;           Example of how a single term could be built:
;           let t$=chr$ 0+"term1"+chr$14+chr$ id1
;   n$    = the needle, the string to be searched for
;           (it must include the starting byte 0 and the
;           ending byte 14).
;   term  = address of the machine code routine

; Example for a text adventure, where v$ holds a list of verb terms:
;   PRINT FN t(v$,CHR$ 0+"examine"+CHR$ 14)

; --------------------------------------------------------------
; Internal

; During the execution of a FN, the system variable DEFADD holds
; the address of the first parameter of its DEF FN definition
; (the first address after the opening paren). The structure of
; DEF FN i(h$,n$) is the following:

; offset  content
; ------  -------
; -03     DEF FN
; -02     t(
; +00     h$
; +02     14
; +03     [string type]      
; +04     [string address, LSB first]
; +06     [string length, LSB first]
; +08     ,
; +09     n$
; +11     14
; +12     [string type]      
; +13     [string address, LSB first]
; +15     [string length, LSB first]
; +17     )=

; --------------------------------------------------------------
; History of this file 

; 2014-08-07: Started, with the code of <fn_instr1.z80s>.
;
; 2014-08-10: Removed unnecessary saving and restoring of
; registers.  New: 'proc', 'local' and 'public', in order to
; make it possible to combine several modules into a single
; file.
;
; 2014-08-11: A bug was introduced by trying to reduce the
; number of jumps.
;
; 2014-08-12: The bug was fixed by comparing with the previous
; version A-00-201408071702.
;
; 2014-08-13: Simpler 'not_found' exit point, no jump.
;
; 2015-01-22: Some typos fixed. Improved description and usage.
; Some changes for publication. Version B-00.
;
; 2015-02-27: Improved comment.
;
; 2015-08-10: Revision. License.

; --------------------------------------------------------------

  proc

  ; The code is relocatable

  public fn_term,fn_term_size
fn_term:

  local again
  local found
  local haystack_exhausted
  local match
  local not_found
  local needle_exhausted

; ..............................
; System variables

  local DEFADD
DEFADD equ 23563

; ..............................
; Parameters

  ld ix,(DEFADD)
  ld a,(ix+6)
  or (ix+7) ; empty string?
  jr z, not_found

  ld e,(ix+4)
  ld d,(ix+5)
  ; de = address of h$
  ld l,(ix+6)
  ld h,(ix+7)
  ; hl = length of h$
  add hl,de
  ; hl = address after the end of h$

  ; Use ix+6 as temporary storage
  ld (ix+6),l
  ld (ix+7),h

  ld l,e
  ld h,d
  ; hl = address of h$

; ..............................
again:

  ; Start searching h$ for n$ from the current position of h$

  ld e,(ix+13)
  ld d,(ix+14)
  dec de
  ; de = address of n$ -1
  ld c,(ix+15)
  ld b,(ix+16)
  ; bc =length of n$

; ..............................
match:
  
  ; Keep on searching h$

  inc de
  ; de = address of current char of n$
  ; hl = address of current char of h$
  ld a,(de)
  cpi ; compare a with (hl) and increment hl
  ex af,af'
  push hl
  push de

  ld e,(ix+6)
  ld d,(ix+7)
  ; de = address after the end of h$
  and a
  sbc hl,de
  ; z = last char of h$?
  pop de
  pop hl
  jr z,haystack_exhausted 

  ld a,b
  or c
  ; z = last char of n$?
  jr z,needle_exhausted

  ex af,af'
  ; z = (hl)=(de)?
  jr z,match
  jr again

; ..............................
needle_exhausted:

  ex af,af'
  ; z = (hl)=(de)?
  jr nz,again
  jr found

; ..............................
haystack_exhausted:

  ld a,b
  or c
  ; z = bc=0?
  jr nz,not_found

  ex af,af'
  ; z = (hl)=(de)?
  jr z,found

; ..............................
not_found:

  ld bc,0
  ret

; ..............................
found:

  ; hl = address after the last char of n$ in h$
  ld b,0
  ld c,(hl) ; take the term id
  ret

fn_term_size equ $-fn_term

  endp

; vim: textwidth=64
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































































































































































































































































































































































































































Deleted src/fn_termn.z80s.

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
; fn_termn.z80s
;
; A database BASIC function for ZX Spectrum

; Version B-00-20150122

; This file is part of DEFFNder:
; http://programandala.net/en.program.deffnder.html

; --------------------------------------------------------------
; Author and license

; Copyright (C) 2014,2015 Marcos Cruz (programandala.net)

; You may do whatever you want with this work, so long as you
; retain the copyright notice(s) and this license in all
; redistributed copies and derived works. There is no warranty.

; --------------------------------------------------------------
; Description

; This code adds a function to Sinclair BASIC that returns the
; n-th term (1 is the first one) in a given list of terms.

; --------------------------------------------------------------
; Usage

; A BASIC function must be defined this way:
; (the actual names are unimportant):
;   10 DEF FN t$(h$,n)="" AND USR termn
; Where:
;   h$    = the haystack, the searched string,
;           with the following structure:
;           every term is prefixed by byte 0, and followed
;           by byte 14 and an id byte.
;           Example of how a single term could be built:
;           let t$=chr$ 0+"term1"+chr$14+chr$ id1
;   n     = the ordinal number of the term that will be returned
;   termn = address of the machine code routine

; Example for a text adventure, where n$ holds a list of noun terms:
;   PRINT FN t$(n$,3)

; --------------------------------------------------------------
; Internal

; During the execution of a FN, the system variable DEFADD holds
; the address of the first parameter of its DEF FN definition
; (the first address after the opening paren). The structure of
; DEF FN i(h$,n) is the following:

; offset  content
; ------  -------
; -04     DEF FN
; -03     t$(
; +00     h$
; +02     14
; +03     [string type]      
; +04     [string address, LSB first]
; +06     [string length, LSB first]
; +08     ,
; +09     n
; +10     14
; +11     0
; +12     [sign byte: 0=positive; 255=negative]
; +13     [16-bit number, LSB first]
; +15     0
; +16     )=

; --------------------------------------------------------------
; History of this file

; 2014-08-08: Started, with the code of <fn_term.z80s>.
;
; 2014-08-10: New: 'proc', 'public' and 'local', in order to
; make it possible to combine several modules into a single
; file.
;
; 2015-01-22: Some typos fixed. Improved description and usage.
; Some changes for publication. Version B-00.
;
; 2015-02-27: Improved comment.
;
; 2015-08-10: Revision. License.

; --------------------------------------------------------------

  proc

  ; The code is relocatable

  public fn_termn,fn_termn_size
fn_termn:

  local exit
  local haystack_char
  local needle_char
  local needle_end
  local needle_found
  local next_haystack_char

; ..............................
; System variables

  local DEFADD
DEFADD equ 23563

; ..............................
; ROM routines

  local STK_STO_$
STK_STO_$ equ 0x2ab2
  local STK_STORE
STK_STORE equ 0x2ab6
          ; Input:
          ;   A = flag
          ;   DE = string address
          ;   BC = string length

; ..............................
; Start

  ; hl' must be preserved!
  ; The only mention I've found about this issue is in
  ; Ian Logan's book "Understanding You Spectrum", 1982, page 43.
  exx
  push hl

; ..............................
; Parameters

  ld ix,(DEFADD)

  ld bc,0 ; term counter
  ld l,(ix+13)
  ld h,(ix+14)
  ; hl = n
  ld a,h
  or l
  ; z = is n zero?
  jr z,exit
  exx
  ld c,(ix+6)
  ld b,(ix+7)
  ; bc = len of h$
  ld a,b
  or c
  ; z = is h$ empty?
  jr z,exit
  ld l,(ix+4)
  ld h,(ix+5)
  ; hl = start of h$

; ..............................
haystack_char:

  ; Check the current char of h$.
  ; hl = address of the current char in h$
  ld a,(hl)
  and a
  ; z = zero char found?
  jr z,needle_found

next_haystack_char:

  ; hl = address of the current char in h$
  ; bc = remaining length of h$
  inc hl
  dec bc
  ld a,b
  or c
  ; z = is the haystack exhausted?
  jr z,exit
  jr haystack_char

; ..............................
needle_found:

  ; A zero byte has been found in h$;
  ; it's the marker of a new term.
  ; But is it the term searched for?

  exx
  ; hl = n
  ; bc = term count
  inc bc
  ld d,h
  ld e,l
  ; cy = 0 (because of the 'and a' above)
  sbc hl,bc ; is this term the n term?
  ld h,d
  ld l,e
  exx
  ; z = is this term the n term?
  jr nz,next_haystack_char

; ..............................

  ; The desired n term has been found.
  ; Now its length has to be calculated.

  ld bc,0 ; length of the term
needle_char:
  ; hl = address of the current char in h$
  inc hl
  ld a,(hl)
  cp 14 ; is it the end of the needle string?
  ; z = end of string found?
  jr z,needle_end
  inc bc
  jr needle_char

; ..............................
needle_end:

  ; The end of the n term has been found.  In order to return it
  ; to BASIC, it has to be pushed onto the calculator stack, and
  ; added to the empty string already there.

  ; hl = address after the last char of the needle
  ; bc = length of the n term
  sbc hl,bc
  ld d,h
  ld e,l
  xor a
  ; a = 0 (=new string)
  ; de = address of the first char of the needle
  ; bc = length of the needle
  call STK_STO_$
  rst 0x28 ; calculator
  db 0x17 ; concatenate it to the empty string in the DEF FN expression
  db 0x38 ; end
  ld bc,1 ; to be ANDed with the string

exit:
 
  ; bc = 1 (valid string returned) or 0 (empty string returned)
  ; hl' must be restored
  pop hl
  push bc
  exx 
  pop bc
  ret

fn_termn_size equ $-fn_termn

  endp

; vim: textwidth=64
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















































































































































































































































































































































































































































































































Deleted src/fn_trunc.z80s.

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
; fn_trunc.z80s
;
; TRUNC$ BASIC function for ZX Spectrum

; Version B-00-20150122

; This file is part of DEFFNder:
; http://programandala.net/en.program.deffnder.html

; --------------------------------------------------------------
; Author and license

; Copyright (C) 2014,2015 Marcos Cruz (programandala.net)

; You may do whatever you want with this work, so long as you
; retain the copyright notice(s) and this license in all
; redistributed copies and derived works. There is no warranty.

; --------------------------------------------------------------
; Description

; This code adds a TRUNC$ function to Sinclair BASIC, to strip
; the trailing spaces of a string.

; --------------------------------------------------------------
; Usage

; The routine is called from BASIC using a function defined this way:
; (the actual names are unimportant):
;   10 DEF FN t$(s$)="" AND USR trunc
; Where:
;   s$    = string to trunc
;   trunc = address of the machine code routine

; Example:
;   PRINT FN t$("En vilagxo de La Mancxo         ")

; --------------------------------------------------------------
; Internal

; During the execution of a FN, the system variable DEFADD holds
; the address of the first parameter of its DEF FN definition
; (the first address after the opening paren). The structure of
; DEF FN t$(s$) is the following:

; offset  content
; ------  -------
; -04     DEF FN
; -03     t$(
; +00     s$
; +02     14
; +03     [string type]
; +04     [string address, LSB first]
; +06     [string lenght, LSB first]
; +08     )=

; --------------------------------------------------------------
; History of this file

; 2014-08-06: Start.
;
; 2014-08-07: Finished. 
;
; 2014-08-10: Removed unnecessary saving and restoring of
; registers.  New: 'proc', 'public' and 'local', in order to
; make it possible to combine several modules into a single
; file.
;
; 2015-01-22: Some changes for publication. Version B-00.
;
; 2015-02-27: Improved comment.
;
; 2015-08-10: Revision. License.

; --------------------------------------------------------------

  proc

  ; The code is relocatable

  public fn_trunc,fn_trunc_size
fn_trunc:

  local exit
  local truncate
  local truncated

; ..............................
; System variables

  local DEFADD
DEFADD equ 23563

; ..............................
; ROM routines

  local STK_STORE
STK_STORE   equ 0x2ab6
            ; Input:
            ;   A = flag
            ;   DE = string address
            ;   BC = string lenght

; ..............................
; Parameters

  ld ix,(DEFADD)
  ld c,(ix+6)
  ld b,(ix+7)
  ; bc = string lenght
  ld a,b
  or c
  ; z = empty string?
  jr z, exit

  ld l,(ix+4)
  ld h,(ix+5)
  ; hl = string address
  add hl,bc
  ; hl = address after the last char of the string

; ..............................
truncate:

  ; bc = counter, remaining chars
  dec hl
  ; hl = address of the current char
  ld a,(hl)
  cp " "
  ; z=space?
  jr nz,truncated
  dec bc
  ld a,b
  or c
  ; z=end of the string?
  jr nz,truncate

; ..............................
truncated:

  ; bc = string lenght without the trailing spaces
  ld e,(ix+4)
  ld d,(ix+5)
  ; de = string address
  xor a  ; a = 0 (=new string)
  call STK_STORE
  rst 0x28 ; calculator
  db 0x17 ; concatenate to the empty string in the DEF FN expression
  db 0x38 ; end

; ..............................
exit:

  ld bc,1
  ret

fn_trunc_size equ $-fn_trunc

  endp

; vim: textwidth=64
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































































































































































































































Added src/init.bas.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// init.bas

// This file is part of

rem CE4

// A text adventure in Spanish
// written in GW-BASIC
// with the Imbastardizer preprocessor
// for the PC-BASIC emulator.

// This tool program creates the data arrays

// Last modified 201707020019

rem Copyright (C) 2014,2016,2017 Marcos Cruz (programandala.net)

// =============================================================
// Requirements {{{1

#include common.bas

#include version.bas

// =============================================================
// Development config {{{1

key 2,"run"+chr$(34)+"init.bas"+chr$(34)+chr$(13)

// =============================================================
// Main {{{1

print "CE4"
print "Versión ";version$
print copyright$
print
print "Preparando los datos:"
print

// =============================================================
// Constants {{{1

print "Constantes..."

let Black=0
let Blue=1
let Green=2
let Cyan=3
let Red=4
let Magenta=5
let Brown=6
let White=7
let Gray=8
let LightBlue=9
let LightGreen=10
let LightCyan=11
let LightRed=12
let LightMagenta=13
let Yellow=14
let BrightWhite=15

let maxCarried=3 // maximum number of things that can be carried XXX TMP

let safeCodeDigits=4

let prompt$="> "
let cursor$="_"

let textPausePrompt$="[...]"

let foregroundColor=white
let backgroundColor=black
let borderColor=black
let inputColor=yellow

// =============================================================
// Arrays {{{1

// ---------------------------------------------

print "Artículos..."
dim article$(3,3,2)
  // type: indefinite, definite or possesive
  // gender: neuter (no article), masculine or feminine
  // number: singular or plural

let article$(indefinite,masculine,singular)="un"
let article$(indefinite,masculine,plural)="unos"
let article$(indefinite,femenine,singular)="una"
let article$(indefinite,femenine,plural)="unas"
let article$(definite,masculine,singular)="el"
let article$(definite,masculine,plural)="los"
let article$(definite,femenine,singular)="la"
let article$(definite,femenine,plural)="las"
let article$(possesive,masculine,singular)="mi"
let article$(possesive,masculine,plural)="mis"
let article$(possesive,femenine,singular)="mi"
let article$(possesive,femenine,plural)="mis"

// XXX OLD
# let article$(noone,masculine+singular)="ningún"
# let article$(noone,masculine+plural)="ningunos"
# let article$(noone,femenine+singular)="ninguna"
# let article$(noone,femenine+plural)="ningunas"
# let article$(someone,masculine+singular)="alguno"
# let article$(someone,masculine+plural)="algunos"
# let article$(someone,femenine+singular)="alguna"
# let article$(someone,femenine+plural)="algunas"

// ---------------------------------------------

print "Mapa..."

dim exit(locations,6) // exit locations
dim exits(locations) // counters
dim visits(locations) // counters

restore @mapData
for n=1 to locations
  read aLocation
  read \
    exit(aLocation,theNorth),\
    exit(aLocation,theSouth),\
    exit(aLocation,theEast),\
    exit(aLocation,theWest),\
    exit(aLocation,theInside),\
    exit(aLocation,theOutside)
  // Keeping the count of free exits updated makes
  // their run-time listing (with proper
  // separators and punctuation) much faster.
  // That's the reason for the exits() array.
  let exits(n)=\
    abs((exit(aLocation,theNorth)<>0)+\
        (exit(aLocation,theSouth)<>0)+\
        (exit(aLocation,theEast)<>0)+\
        (exit(aLocation,theWest)<>0))
    // XXX TODO inside and outside
#     (exit(aLocation,theInside)<>0)+\
#     (exit(aLocation,theOutside)<>0)
next n

dim adjacent(locations,locations) // flags
for n=1 to locations
  for i=theNorth to theWest  // XXX TODO inside and outside
    let destination=abs(exit(n,i))
    if destination then \
      let adjacent(n,destination)=i:\
      gosub @oppositeDirection:\
      let adjacent(destination,n)=o
  next i
next n

dim oppositeDirection(6)
let oppositeDirection(theNorth)=theSouth
let oppositeDirection(theSouth)=theNorth
let oppositeDirection(theEast)=theWest
let oppositeDirection(theWest)=theEast
let oppositeDirection(theInside)=theOutside
let oppositeDirection(theOutside)=theInside

// ---------------------------------------------

print "Escenarios..."

restore @locationData
dim locationName$(locations)
// XXX TODO use strings instead, to save memory:
dim outside(locations)
dim corridor(locations)

restore @locationData
do
  read i:if i=0 then exit do
  read \
    locationName$(i),\
    outside(i),\
    corridor(i)
loop

// ---------------------------------------------

print "Cosas..."

dim thingLocation(things):\
dim thingNoun(things):\
dim thingGender(things):\
dim thingNumber(things):\
dim thingArticleType(things)
restore @thingData
do
  read i:if i=0 then exit do
  read thingLocation(i),thingArticleType(i)
  let thingLocation(i)=theHall // XXX TMP --
loop

// ---------------------------------------------

print "Verbos..."

let verbs=0
restore @verbData
do
  read verb$
  if verb$="" then exit do
  read verbAction
  let verbs=verbs+1
loop

dim verb$(verbs),verbAction(verbs)

restore @verbData
for verb=1 to verbs
  read verb$(verb),verbAction(verb)
next verb

// ---------------------------------------------

print "Nombres..."

restore @nounData
let nouns=0 // counter
do
  read i:if i=0 then exit do
  read i$,i,i:\
  let nouns=nouns+1
loop

dim noun$(nouns),nounThing(nouns)

restore @nounData
for noun=1 to nouns
  read associatedThing
  read \
    noun$(noun),\
    thingGender(associatedThing),\
    thingNumber(associatedThing)
  let nounThing(noun)=associatedThing
  let thingNoun(associatedThing)=noun
next noun

// ---------------------------------------------

print "Sintaxis..."

dim syntax(actions,things)
restore @syntaxData
do
  read action,thing
  if action=0 then exit do
  let syntax(action,thing)=TRUE
loop

// ---------------------------------------------

// This array stores how many times an action has been done with
// every thing:
// XXX TODO -- not used yet

dim done(actions,things)

// ---------------------------------------------

chain "main.bas",,all

// =============================================================
// Data {{{1

// ---------------------------------------------
rem Map exits

@mapData

rem Data: location, north, south, east, west, in, out
rem (Exits through a locked door are marked with '+locked'.)

data theBasement,noExit,noExit,noExit,theCorridorA,noExit,theCorridorA // XXX TODO change the name and description
data theBathroomA,noExit,noExit,noExit,theCorridorE,noExit,theCorridorE
data theBathroomB,noExit,noExit,noExit,theCorridorC,noExit,theCorridorC
data theChapel,noExit,noExit,theCorridorF,noExit,noExit,theCorridorF
data theClassA,noExit,noExit,theCorridorB,noExit,noExit,theCorridorB
data theClassB,noExit,noExit,theCorridorC,noExit,noExit,theCorridorC
data theCorridorA,theReception,theCorridorB,theBasement,noExit,noExit,noExit
data theCorridorB,theCorridorA,theCorridorC,theEntranceB+locked,theClassA,noExit,noExit
data theCorridorC,theCorridorB,theCorridorD,theBathroomB,theClassB,noExit,noExit
data theCorridorD,theCorridorC,theCorridorE,theEntranceC+locked,noExit,noExit,noExit
data theCorridorE,theCorridorD,theCorridorF,theBathroomA,theLibrary,noExit,noExit
data theCorridorF,theCorridorE,theDining,theGym,theChapel,noExit,noExit
data theDining,theCorridorF,theKitchen,theJunkRoom,theEntranceD+locked,noExit,theEntranceD+locked
data theEntranceA,theEntranceB,theEntranceE,theLobby+locked,noExit,theLobby+locked,noExit
data theEntranceB,theEntranceA,theEntranceC,noExit,theCorridorB+locked,theCorridorB+locked,noExit
data theEntranceC,theEntranceB,theEntranceD,noExit,theCorridorD+locked,theCorridorD+locked,noExit
data theEntranceD,theEntranceC,theEntranceE,theDining+locked,noExit,theDining+locked,noExit
data theEntranceE,theEntranceA,theEntranceD,noExit,theKitchen+locked,theKitchen+locked,noExit
data theGym,noExit,noExit,noExit,theCorridorF,noExit,theCorridorF
data theHall,theOfficeA+locked,theReception,theOfficeC,theOfficeB+locked,noExit,theReception
data theJunkRoom,noExit,noExit,noExit,theDining,noExit,theDining // XXX TODO move to a better place in the map
data theKitchen,theDining,noExit,theEntranceE+locked,theLarder,noExit,theEntranceE+locked
data theLarder,noExit,noExit,theKitchen,noExit,noExit,theKitchen
data theLibrary,noExit,noExit,theCorridorE+locked,noExit,noExit,theCorridorE
data theLiving,theLobby,noExit,noExit,noExit,noExit,theLobby
data theLobby,noExit,theLiving,theReception,theEntranceA+locked,noExit,theEntranceA+locked
data theOfficeA,noExit,theHall+locked,noExit,noExit,noExit,theHall+locked
data theOfficeB,noExit,noExit,theHall+locked,noExit,noExit,theHall+locked
data theOfficeC,noExit,noExit,noExit,theHall,noExit,theHall
data theReception,theHall,theCorridorA,noExit,theLobby,noExit,theLobby

// ---------------------------------------------
rem Verbs

@verbData

rem Data: "term",action id

data "abre",toOpen
data "abrir",toOpen
data "apaga",toTurnOff
data "apagar",toTurnOff
data "coge",toTake
data "coger",toTake
data "conecta",toTurnOn
data "conectar",toTurnOn
data "deja",toDrop
data "dejar",toDrop
# data "dirigirse",toGo
# data "dirígete",toGo
data "e",toGoEast
# data "encaminarse",toGo
# data "encamínate",toGo
data "encender",toTurnOn
data "enciende",toTurnOn
data "entra",toGoIn
data "entrar",toGoIn
data "este",toGoEast
data "ex",toExamine
data "examina",toExamine
data "examinar",toExamine
data "hacer",toDo
data "haz",toDo
data "i",toInventory
data "inspecciona",toExamine
data "inspeccionar",toExamine
data "inventariar",toInventory
data "inventario",toInventory
data "inventaría",toInventory
data "ir",toGo
data "irse",toGo
data "largarse",toGo
data "lee",toRead
data "leer",toRead
data "lárgate",toGo
data "m",toLook
data "marchar",toGo
data "marcharse",toGo
data "mira",toLook
data "mirar",toLook
data "n",toGoNorth
data "norte",toGoNorth
data "o",toGoWest
data "observa",toLook
data "observar",toLook
data "oeste",toGoWest
data "recoge",toTake
data "recoger",toTake
data "registra",toExamine
data "registrar",toExamine
data "s",toGoSouth
data "sal",toGoOut
data "salir",toGoOut
data "soltar",toDrop
data "suelta",toDrop
data "sur",toGoSouth
data "tira",toDrop
data "tirar",toDrop
data "toma",toTake
data "tomar",toTake
data "ve",toGo
data "vete",toGo

#ifdef debug
  data "d",toDebug
#endif

data "" // end of data

// ---------------------------------------------
rem Nouns

// Nouns are associated with things. Several nouns can be associated
// with one thing, and one noun can be associated with several things.
// This is how it works and how the data must be organized:
//
// When several nouns are associated with one thing, the last noun in
// the data list will be the default one for the thing.
//
// Example: See "boli" and and "bolígrafo" below, two words for
// "ballpen" in Spanish.
//
// When one noun is associated with several things, the noun is
// associated with an ambiguous thing, a fake thing id, whose actual
// value will be calculated at runtime, depending on the current
// location and other variables. The id of an ambiguous things use the
// "X" suffix.
//
// In order to set the default noun of every calculated thing, the
// noun data is repeated after the association with the ambiguous
// thing.
//
// Example: First, the term "mesa" (table is Spanish) is associated
// with the ambiguous thing 'theTableX'. This first association will
// be found by the parser and the proper routine will be called in
// order to calculate the actual thing, 'theLivingTable' or
// 'theDiningTable', depending on the current location.  Second,
// "mesa" is associated also with the thing 'theLivingTable', what
// makes "mesa" the default noun of 'theLivingTable' thing.

@nounData

rem Data: "term",thing id,noun gender,noun number

rem Unambiguous nouns

data theAll,"todo",masculine,singular
data theBallpen,"boli",masculine,singular
data theBallpen,"bolígrafo",masculine,singular
data theBooks,"montaña",femenine,singular
data theBooks,"montón",femenine,singular
data theBooks,"libros",masculine,plural
data theBrick,"ladrillo",masculine,singular
data theDiningTables,"mesas",femenine,plural
data theDoor,"puerta",femenine,singular
data theEast,"e",masculine,singular
data theEast,"este",masculine,singular
data theGuard,"guarda",masculine,singular
data theGuard,"guardia",masculine,singular
data theGuard,"vigilante",masculine,singular
data theInside,"adentro",neuter,singular
data theInside,"dentro",neuter,singular
data theInventory,"i",masculine,singular
data theInventory,"inventario",masculine,singular
data theKey,"llave",femenine,singular
data theNo,"no",neuter,singular
data theNorth,"n",masculine,singular
data theNorth,"norte",masculine,singular
data theOutside,"afuera",neuter,singular
data theOutside,"fuera",neuter,singular
data thePaperPiece,"papelito",masculine,singular
data thePaperSheet,"folio",masculine,singular
data thePaperSheet,"papel",masculine,singular
data thePencil,"lapicero",masculine,singular
data thePencil,"lápiz",masculine,singular
data theSafe,"caja",femenine,singular
data theShoe,"zapato",masculine,singular
data theSock,"calcetín",masculine,singular
data theSouth,"s",masculine,singular
data theSouth,"sur",masculine,singular
data theTorch,"linterna",femenine,singular
data theWest,"o",masculine,singular
data theWest,"oeste",masculine,singular
data theYes,"sí",neuter,singular
data noThing,"",neuter,singular

rem Ambiguous nouns

// Note: the first association in every group must be the ambiguous
// one (the one with the X-suffix identifier). This will be the first
// one found by the parser.

data theTableX,"mesa",femenine,singular
data theLivingTable,"mesa",femenine,singular

data theWallX,"pared",femenine,singular
data theWallX,"paredes",femenine,plural
data theWallX,"muro",masculine,singular
data theWallX,"muros",masculine,plural
data theWallA,"muro",masculine,singular
data theWallB,"muro",masculine,singular
data theWallC,"muro",masculine,singular
data theWallD,"muro",masculine,singular
data theWallE,"muro",masculine,singular

data thePotX,"tiesto",masculine,singular
data thePotA,"tiesto",masculine,singular
data thePotB,"tiesto",masculine,singular
data thePotC,"tiesto",masculine,singular
data thePotD,"tiesto",masculine,singular
data thePotE,"tiesto",masculine,singular

data 0 // end of data

// ---------------------------------------------
rem Things

@thingData

rem Data: thing id,location

rem The directions must be the first elements defined, and in the given
rem order (north, south, east, west, inside and outside):

data theNorth,theLimbo,indefinite
data theSouth,theLimbo,indefinite
data theEast,theLimbo,indefinite
data theWest,theLimbo,indefinite
data theInside,theLimbo,indefinite
data theOutside,theLimbo,indefinite

rem The order of the rest is not important:

data theAll,theLimbo,indefinite
data theBallpen,theLimbo,indefinite
data theBooks,theLimbo,indefinite
data theBrick,theLimbo,indefinite
data theDiningTables,theDining,indefinite
data theDoor,theLimbo,indefinite
data theGuard,theLimbo,indefinite
data theInventory,theLimbo,indefinite
data theKey,theLimbo,definite
data theLivingTable,theLiving,indefinite
data thePaperPiece,theLimbo,indefinite
data thePaperSheet,theLimbo,indefinite
data thePencil,theLimbo,indefinite
data thePotA,theEntranceA,indefinite
data thePotB,theEntranceB,indefinite
data thePotC,theEntranceC,indefinite
data thePotD,theEntranceD,indefinite
data thePotE,theEntranceE,indefinite
data theSafe,theLimbo,indefinite
data theShoe,theLimbo,possesive
data theSock,theLimbo,indefinite
data theTorch,theProtagonist,indefinite
data theWallA,theEntranceA,indefinite
data theWallB,theEntranceB,indefinite
data theWallC,theEntranceC,indefinite
data theWallD,theEntranceD,indefinite
data theWallE,theEntranceE,indefinite

data 0 // end of data

// ---------------------------------------------
rem Syntax

// These data define what actions and things (complements) can be
// combined in a user command. Actions that can be used without a
// complement use the special thing id 'noThing'.
//
// These data are used as a first filter, before executing the
// specific code of the action. Depending on the action, it can be
// useful to use this primary filter or to make the checks in the
// action code itself.

@syntaxData

rem Data: action id,thing id

data toDo,theInventory
data toDrop,theAll
data toDrop,theBallpen
data toDrop,theBrick
data toDrop,theKey
data toDrop,thePaperPiece
data toDrop,thePaperSheet
data toDrop,thePencil
data toDrop,theShoe
data toDrop,theSock
data toDrop,theTorch
data toExamine,theBallpen
data toExamine,theBooks
data toExamine,theBrick
data toExamine,theDiningTables
data toExamine,theDoor
data toExamine,theGuard
data toExamine,theInside
data toExamine,theInventory
data toExamine,theKey
data toExamine,theLivingTable
data toExamine,theNorth
data toExamine,thePaperPiece
data toExamine,thePaperSheet
data toExamine,thePencil
data toExamine,thePotA
data toExamine,thePotB
data toExamine,thePotC
data toExamine,thePotD
data toExamine,thePotE
data toExamine,theSafe
data toExamine,theShoe
data toExamine,theSock
data toExamine,theTorch
data toExamine,theWallA
data toExamine,theWallB
data toExamine,theWallC
data toExamine,theWallD
data toExamine,theWallE
data toGo,theEast
data toGo,theInside
data toGo,theNorth
data toGo,theOutside
data toGo,theSouth
data toGo,theWest
data toGoEast,noThing
data toGoIn,noThing
data toGoNorth,noThing
data toGoOut,noThing
data toGoSouth,noThing
data toGoWest,noThing
data toInventory,noThing
data toInventory,theAll
data toInventory,theInventory
data toLook,noThing
data toLook,theAll
data toLook,theBallpen
data toLook,theBooks
data toLook,theBrick
data toLook,theDiningTables
data toLook,theDoor
data toLook,theEast
data toLook,theGuard
data toLook,theInside
data toLook,theInventory
data toLook,theKey
data toLook,theLivingTable
data toLook,theNorth
data toLook,theOutside
data toLook,thePaperPiece
data toLook,thePaperSheet
data toLook,thePencil
data toLook,thePotA
data toLook,thePotB
data toLook,thePotC
data toLook,thePotD
data toLook,thePotE
data toLook,theSafe
data toLook,theShoe
data toLook,theSock
data toLook,theSouth
data toLook,theTorch
data toLook,theWallA
data toLook,theWallB
data toLook,theWallC
data toLook,theWallD
data toLook,theWallE
data toLook,theWest
data toOpen,theDoor
data toOpen,theSafe
data toRead,theBooks
data toRead,thePaperPiece
data toRead,thePaperSheet
data toTake,theAll
data toTake,theBallpen
data toTake,theBrick
data toTake,theKey
data toTake,thePaperPiece
data toTake,thePaperSheet
data toTake,thePencil
data toTake,thePotA
data toTake,thePotB
data toTake,thePotC
data toTake,thePotD
data toTake,thePotE
data toTake,theShoe
data toTake,theSock
data toTake,theTorch
data toTurnOff,theTorch
data toTurnOn,theTorch

#ifdef debug
  data toDebug,noThing
  data toDebug,theAll
  data toDebug,theBallpen
  data toDebug,theBooks
  data toDebug,theBrick
  data toDebug,theDiningTables
  data toDebug,theDoor
  data toDebug,theEast
  data toDebug,theGuard
  data toDebug,theInside
  data toDebug,theKey
  data toDebug,theLivingTable
  data toDebug,theNorth
  data toDebug,theOutside
  data toDebug,thePaperPiece
  data toDebug,thePaperSheet
  data toDebug,thePencil
  data toDebug,thePotA
  data toDebug,thePotB
  data toDebug,thePotC
  data toDebug,thePotD
  data toDebug,thePotE
  data toDebug,theSafe
  data toDebug,theShoe
  data toDebug,theSock
  data toDebug,theSouth
  data toDebug,theTorch
  data toDebug,theWest
#endif

data 0,0 // end of data

// ---------------------------------------------
rem Locations

@locationData

rem Data: location id,name,outside?,corridor?

data theEntranceA,"la entrada noroeste del edificio",TRUE,FALSE
data theEntranceB,"la entrada noreste del edificio",TRUE,FALSE
data theEntranceC,"la entrada este del edificio",TRUE,FALSE
data theEntranceD,"la entrada sureste del edificio",TRUE,FALSE
data theEntranceE,"la entrada suroeste del edificio",TRUE,FALSE
data theBathroomB,"el aseo de los profesores",FALSE,FALSE
data theGym,"el gimnasio",FALSE,FALSE
data theLarder,"la despensa",FALSE,FALSE
data theKitchen,"la cocina",FALSE,FALSE
data theBasement,"el sótano",FALSE,FALSE
data theJunkRoom,"el trastero",FALSE,FALSE
data theHall,"el distribuidor",FALSE,FALSE
data theLobby,"el recibidor",FALSE,FALSE
data theReception,"la recepción",FALSE,FALSE
data theLiving,"la sala de visitas",FALSE,FALSE
data theCorridorA,"el final del pasillo por el norte",FALSE,TRUE
data theCorridorB,"el tramo norte del pasillo",FALSE,TRUE
data theCorridorC,"el tramo central del pasillo",FALSE,TRUE
data theCorridorD,"el tramo central del pasillo",FALSE,TRUE
data theCorridorE,"el tramo sur del pasillo",FALSE,TRUE
data theCorridorF,"el final del pasillo por el sur",FALSE,TRUE
data theBathroomA,"el aseo del alumnado",FALSE,FALSE
data theChapel,"la capilla",FALSE,FALSE
data theDining,"el comedor",FALSE,FALSE
data theOfficeA,"el despacho del director",FALSE,FALSE
data theOfficeB,"el despacho del jefe de estudios",FALSE,FALSE
data theOfficeC,"la secretaría",FALSE,FALSE
data theClassA,"el aula de los alfa",FALSE,FALSE
data theClassB,"el aula de los beta",FALSE,FALSE
data theLibrary,"la biblioteca",FALSE,FALSE

data 0 // end of data

// ---------------------------------------------
rem Tools

@oppositeDirection
  // Input:  i
  // Output: o
  if i=theNorth then let o=theSouth:return
  if i=theSouth then let o=theNorth:return
  if i=theWest then let o=theEast:return
  if i=theEast then let o=theWest:return
  if i=theOutside then let o=theInside:return
  if i=theInside then let o=theOutside:return
  return

// =============================================================
// Texts {{{1

# XXX TODO --

print "Textos..."

restore @texts
do
  let t$="":\ // new text
  read fileId:\
  if fileId=0 then exit proc
  do
    read i$:\
    if i$=chr$ 13 then exit do
    let t$=t$+(" " and len t$)+i$
  loop
  dim a$(len t$):\
  let a$=t$:\
  save fn txtFile$(fileId) data a$():\
  print ".";
loop

// ---------------------------------------------

@texts

data 0 // end of data

# vim:filetype=imbastardizer

Added src/main.bas.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
// main.bas

// This file is part of

  rem CE4

// A text adventure in Spanish
// written in GW-BASIC
// with the Imbastardizer preprocessor
// for the PC-BASIC emulator.

  rem Copyright (C) 2014,2015,2016,2017 Marcos Cruz (programandala.net)

// XXX UNDER DEVELOPMENT

// Last modified 201707080030

// =============================================================
// Config {{{1

#include common.bas

// =============================================================
// Functions {{{1

// ---------------------------------------------
// Random

  def fnRandom(n)=int(rnd*n)
  // Random integer number between 0 and n-1.

  def fnBetween(n1,n2)=int(rnd*(n2-n1+1))+n1
  // Random integer between n1 and n2.

  def fnChar$(s$)=mid$(s$,fnBetween(1,len(s$)),1)
  // Random character from a string.
  // XXX FIXME -- Out of memory

// ---------------------------------------------
// Strings

  def fnIfs$(flag,s$)=left$(s$,255*abs(flag))
  // If flag is non-zero, return s$; else return an empty string.
  
  def fnIfElses$(flag,s1$,s0$)=left$(s1$,255*abs(flag))+left$(s0$,255*abs(flag=0))
  // If flag is non-zero, return s1$; else return s0$.

// ---------------------------------------------
// Time

  def fnTwoDigits$(n)=right$("00"+str$(n),2)
  // Convert a number n (0-99) to a two-digit string.

  def fnHour$(h,m,s)=\
  fnTwoDigits$(h)+":"+fnTwoDigits$(m)+":"+fnTwoDigits$(s)
  // Hour, minute and second as an ISO time string.

// ---------------------------------------------
// Data interface

  def fnThingArticle$(thing)=\
  article$(thingArticleType(thing),thingGender(thing),thingNumber(thing))
  // Proper article for a thing.

  def fnTheName$(thing)=noun$(thingNoun(thing))
  // Name (noun) associated to a thing.

  def fnWholeName$(thing)=fnThingArticle$(thing)+" "+fnTheName$(thing)
  // Whole name of a thing.

  def fnAroundHere(thing)=\
  fnIsHere(thing) and not(adjacent(thingLocation(thing),currentLocation))
  // Is a thing around here?

  def fnAlreadyVisited(location)=\
  visits(location)>1
  // Is the given location already visited?

  def fnFirstVisit(location)=\
  visits(location)=1
  // Is it the first visit to the given location?

  def fnLongLocationDescription(x)=\
  fnFirstVisit(currentLocation) or action=toLook
  // Show the long location description?

  def fnIsCarried(thing)=theProtagonist=thingLocation(thing)

  def fnIsNotCarried(thing)=theProtagonist<>thingLocation(thing)

  def fnIsHere(thing)=currentLocation=thingLocation(thing)

  def fnIsNotHere(thing)=currentLocation<>thingLocation(thing)

  def fnIsLocked(x)=x<0

  // XXX TODO -- define fnUnlock()

  #include wt.bas

// =============================================================
// Main {{{1

  gosub @initOnce

@main

  do
    gosub @credits
    gosub @intro
    gosub @game
  loop

// =============================================================
// Game loop {{{1

@game

  gosub @initGame
  gosub @enterLocation

  do
    gosub @accept
    if len(command$)>0 and  pausedAccept then \
      echo[prompt$+accept$]
    gosub @parse
    if action then
      gosub @obey
    else
      // XXX TODO check empty commands
      if pausedAccept then
        if fnRandom(64) then \
          __echo["El tiempo pasa."] // XXX TODO random message?
      else
        // XXX TODO move this error to the parse proc?:
        error["¿"+theVerb$+"?"] // XXX TMP
      endif
    endif
  loop until gameOver

  return

// =============================================================
// Input {{{1

@accept

  // Accept a line of text from the user.
  //
  // Ouput:
  //  command$ = text
  //  pausedAccept = flag; if set, the input finished because there
  //     was no time left,  because the user pressed the enter key

  let command$=""

  if aKey=ENTER then \
    gosub @initAccept

  let pausedAccept=FALSE
  let maxSeconds!=timer+5 // XXX TMP -- small value for debugging

  # print "hola"
  # print maxAcceptedChars // XXX INFORMER
  # print len(accept$) // XXX INFORMER
  # do
  # loop until inkey$<>""

  gosub @printAccept

  # print "nada"
  # print maxAcceptedChars // XXX INFORMER
  # print len(accept$) // XXX INFORMER
  # do
  # loop until inkey$<>""

  # poke bottomLineAttrAddress+cursorPos,cursorAttr // XXX TODO --

@nextKey

  // endless loop to read the keyboard

  let aKey$=inkey$+chr$(0):\
  let aKey=asc(aKey$)

  if timer>maxSeconds! then \
    let pausedAccept=TRUE:\
    gosub @printAccept:\
    return

  if aKey=BACKSPACE then

    if cursorPos>1 then
      let cursorPos=cursorPos-1
      if mid$(accept$,cursorPos,1)=" " then \
        let acceptedSpaces=acceptedSpaces-1 \
      else \
        mid$(accept$,cursorPos,1)=" "
      gosub @printAccept
    endif
    goto @nextKey

  endif

  if aKey=ENTER then

    if cursorPos>1 then \
      let command$=left$(accept$,cursorPos-1-(lastAcceptedChar$=" ")):\
      gosub @initAccept:\
      gosub @printAccept:\
      return \
    else goto @nextKey

  endif

  if aKey=SPACE then

    if cursorPos>1 and lastAcceptedChar$<>" " then \
      if acceptedSpaces<maxAcceptedSpaces then \
        let acceptedSpaces=acceptedSpaces+1: \
        goto @accept_new_char \
      else goto @nextKey

  endif

  if aKey>SPACE then

    @accept_new_char

    if cursorPos<maxAcceptedChars then \
      let maxSeconds!=maxSeconds!+2:\
      let lastAcceptedChar$=chr$(aKey):\
      mid$(accept$,cursorPos,1)=lastAcceptedChar$:\
      let cursorPos=cursorPos+1:\
      gosub @printAccept

  endif

  goto @nextKey

// ---------------------------------------------

@initAccept

  // Init the values used by the input routine

  let aKey=0
  let lastAcceptedChar$=""
  let acceptedSpaces=0
  let maxAcceptedSpaces=1
  let maxAcceptedChars=80-len(prompt$)-len(cursor$) // text buffer
  let accept$=string$(maxAcceptedChars,SPACE) // text buffer
  let cursorPos=1 // position of the cursor in accept$

  return

// ---------------------------------------------

@printAccept

  // Print the current input text

  locate 25,1
  color inputColor,backgroundColor
  print prompt$;left$(accept$,cursorPos-1);

  if not(pausedAccept) then \
    color backgroundColor,inputColor
    print " ";:\
    color foregroundColor,backgroundColor

  print mid$(accept$,cursorPos+1);

  return

// =============================================================
// Plot errors {{{1

@notCarriedError

  // Error: the complement is not carried.

  // XXX TODO -- rewrite
  __echo["No tengo "+fnWholeName$(complement)+"."]

  return

// =============================================================
// Parser {{{1

@parse

  // Parse the command

  // Input:
  //     command$ (with no leading or trailing space, and only one or
  //     zero spaces in the text)

  let spacePos=instr(command$," ")

  if spacePos then \
    let theVerb$=left$(command$,spacePos-1):\
    let theNoun$=mid$(command$,spacePos+1) \
  else \
    let theVerb$=command$:\
    let theNoun$=""

#  #ifdef debug
    debug["Verbo='"+theVerb$+"'"] // XXX
    debug["Nombre='"+theNoun$+"'"] // XXX
#  #endif

  let action=0
  for verb=1 to verbs
    if verb$(verb)=theVerb$ then \
      let action=verbAction(verb):\
      exit for
  next verb

  let complement=noThing
  for noun=1 to nouns
#    debug["noun="+str$(noun)+"("+noun$(noun)+")"] // XXX INFORMER
    if noun$(noun)=theNoun$ then \
      let complement=nounThing(noun):\
      exit for
  next noun

#  #ifdef debug
    debug["Acción= "+str$(action)] // XXX
    debug["Compl.= "+str$(complement)+"("+fnTheName$(complement)+")"] // XXX
#  #endif

  if complement>=firstAmbiguous then \

    // The ambiguous complement must be converted to the actual one.

    on complement-firstAmbiguous+1 goto \
      // The 'goto' list must be in alphabetical order:
      @unAmbiguousPotX,\
      @unAmbiguousTableX,\
      @unAmbiguousWallX,\
      0 // XXX TMP -- for debugging

  return

@unAmbiguousTableX

  // Make 'theTableX' unambiguous

  #ifdef debug
    debug["Complemento ambiguo «mesa»= "+str$(complement)] // XXX
  #endif
  if currentLocation=theDining then \
    let complement=theDiningTables
  else \
    let complement=theLivingTable

  #ifdef debug
    debug["Complemento inequívoco= "+str$(complement)] // XXX
  #endif
  return

@unAmbiguousWallX

  // Make 'theWallX' unambiguous

  #ifdef debug
    debug["Complemento ambiguo «muro»= "+str$(complement)] // XXX
  #endif

  // XXX FIXME will fail with more outside locations...
  // XXX ...than theEntranceA...theEntranceE.

  if outside(currentLocation) then \
    #  if currentLocation<=theEntranceE and currentLocation>=theEntranceA then \  // XXX solution, slower
    let complement=theWallA+(currentLocation-theEntranceA)

  #ifdef debug
    debug["Complemento inequívoco= "+str$(complement)] // XXX
  #endif

  return

@unAmbiguousPotX

  // Make 'thePotX' unambiguous

  #ifdef debug
    debug["Complemento ambiguo «tiesto»= "+str$(complement)] // XXX
    debug["Escenario actual= "+str$(currentLocation)] // XXX
  #endif

  if outside(currentLocation) then
    let complement=thePotA+(currentLocation-theEntranceA):\
    #ifdef debug
      debug["Complemento inequívoco según escenario= "+str$(complement)]:\ // XXX
    #endif
    let lastPot=complement:\
    return
  else
    let complement=lastPot
    #ifdef debug
      debug["Complemento inequívoco según recuerdo= "+str$(complement)] // XXX
    #endif
  endif

  return

// =============================================================
// Non-playing character {{{1

@theGuardMoves

  // The guard moves to a random adjacent location.

  // XXX TODO -- improve

  let anExit=fnBetween(theNorth,theWest):\
  if exit(thingLocation(theGuard),anExit)=0 then \
    return

  let thingLocation(theGuard)=abs(exit(thingLocation(theGuard),anExit))
0ifdef debug
  debug["El guarda se va hacia "+fnTheName$(anExit)+" ("+locationName$(thingLocation(theGuard))+")."]

  if fnIsHere(theGuard) then
    gosub @catchedByTheGuard
  else if adjacent(currentLocation,thingLocation(theGuard)) then
    __echo["Oigo pasos al "+fnTheName$(adjacent(currentLocation,thingLocation(theGuard)))+"..."]
  else if corridor(thingLocation(theGuard)) and corridor(currentLocation) then
    __echo["He oído algo en el pasillo..."]
  endif

  return

@catchedByTheGuard

  // XXX TODO -- rewrite everything:

  #  __echo["Viene el guarda de seguridad."]

  gosub @multitasking_off
  let banished=FALSE

  // XXX TODO -- flag: catched

  __echo["Me agarra por el cuello y me dice:"]

  if outside(currentLocation) then \
    echo["«¿Qué haces rondando por aquí?»."]
  else \
    let banished=TRUE:\
    echo["«¿Cómo has entrado aquí?»."]

  if guardMet and banished then
    __echo["Se acerca a mí y me dice:"]
    if fnIsCarried(thePaperSheet) then \
      goto @l4007
    goto @l4085
  endif

  if banished then
    __echo["«Esta habitación estaba cerrada con llave..."]
    if fnIsHere(theSafe) and safeOpened then \
      echo["¡Y además has abierto la caja!"]
    echo["¡Maldito hereje!»."]
  endif

@l4007

  if fnIsCarried(thePaperSheet) then
    __echo["«¿Qué es ese papel que tienes ahí escondido? Déjame ver...»."]
    let pauseSeconds=100
    gosub @pause:__echo["«Hum...», dice, echando un vistazo."]
    let pauseSeconds=100:gosub @pause
  __echo["«Así que has copiado el examen...», dice por fin."]
    let banished=TRUE
  endif

  if banished then :\
    __echo["«Esto significa tu inmediata expulsión de este complejo."]:\
    goto @theEnd

  __echo["Se vuelve hacia mí y me dice:"]
  echo["«¿Sabes que estar en el complejo a estas horas es una grave falta de disciplina?»."]
  let pauseSeconds=100:gosub @pause
  __echo["«Este comportamiento no es propio de un alumno que se esta formando en el complejo», añade."]

  if banished then \
    goto @theEnd

@l4085
  gosub @theGuardLeaves

  return

@theGuardLeaves

  do
    let thingLocation(theGuard)=fnBetween(1,locations)
  loop until  fnAroundHere(theGuard)
  __echo["Se da media vuelta y se va."]
  let guardMet=guardMet+1

  // XXX FIXME this is nonsense here:
  if banished=0 then \
    __echo["¡Uf!... por poco."]

  return

@multitasking_off
  // XXX TODO --
  return

@multitasking_on
  // XXX TODO --
  return

// =============================================================
// The end {{{1

  // XXX TODO rewrite

  // XXX Note: @theEnd is called with a goto

@theEnd

  // XXX TODO
  let totalPlayingSeconds=fnSeconds(x)
  let playingMinutes=int (totalPlayingSeconds/60)
  let playingSeconds=int (totalPlayingSeconds-playingMinutes*60)
  let playingHours=int (playingMinutes/60)
  let playingMinutes=playingMinutes-playingHours*60

  if banished then

    __echo["Has sido expulsado del Complejo Educativo."]
    // XXX TODO finish
    echo["La próxima vez ten más cuidado."]

  else

    __echo["Has logrado tu objetivo."]
    echo["¡Enhorabuena!"]

  endif

  timeReport

  if banished=0 then

    if totalPlayingSeconds<totalRecordSeconds then

    let totalRecordSeconds=totalPlayingSeconds:\
    let recordHours=playingHours:\
    let recordMinutes=playingMinutes:\
    let recordSeconds=playingSeconds:\
    let recordMan$=player$ // XXX
    __echo["¡Has establecido un nuevo récor!"]

  else

    __echo["El récor sigue en posesión de"]
    echo[recordMan$+", con un tiempo de"]
    echo[fnHour$(recordHours,recordMinutes,recordSeconds)+"."]

  endif

  endif

  __echo["Pulsa una tecla para jugar."]
  let pauseSeconds=0:gosub @pause
  goto @main

@timeReport
  __echo["Tardaste en"]
  echo[fnIfElses$(banished,"ser expulsado","lograrlo")+":"]
  echo[fnHour$(playingHours,playingMinutes,playingSeconds)+"."]
  return

// =============================================================
// Action dispatcher {{{1

@obey

  // XXX TODO different values in syntax(), e.g.:
  // 1 = doable, normal
  // 0 = impossible
  // -1 = absurd
  // -2 = contra natura

  if len(theNoun$) and complement=noThing then \
    error["¿"+theNoun$+"?"]:\
    return

  if not(syntax(action,complement)) then \
    error["Eso no tiene sentido."]:\
    return

  gosub @doAction

  // XXX TODO update the 'known' flag of the complement,
  // in order to force the definite article.

  return

@doAction

  on action goto \

  // The following list of labels must be in alphabetical order,
  // to match the values of the correspondent action ids defined in
  // <common.bas>.

    @doDo,\
    @doDrop,\
    @doExamine,\
    @doGo,\
    @doGoEast,\
    @doGoIn,\
    @doGoNorth,\
    @doGoOut,\
    @doGoSouth,\
    @doGoWest,\
    @doInventory,\
    @doLook,\
    @doOpen,\
    @doRead,\
    @doTake,\
    @doTurnOff,\
    @doTurnOn,\
    #ifdef debug
      @doDebug,\
    #endif
    0 // XXX TMP --

  fatal_error["Flujo descontrolado en la rutina 'obey'"] // XXX TMP

// =============================================================
// Actions {{{1

// ---------------------------------------------

  #ifdef debug

@doDebug

    debug["El complemento está en el escenario "+\
      str$(thingLocation(complement))+\
      "("+locationName$(thingLocation(complement))+" )"]
    return

  #endif

// ---------------------------------------------

@doGoComplement

  // XXX TODO --  used

  #ifdef debug
    debug["doGoComplement"]
  #endif

  let direction=complement:\
  goto @doGo

// ---------------------------------------------

@doGoNorth

  #ifdef debug
    debug["doGoNorth"]
  #endif

  let direction=theNorth:goto @doGo

// ---------------------------------------------

@doGoSouth

  #ifdef debug
    debug["doGoSouth"]
  #endif

  let direction=theSouth:goto @doGo

// ---------------------------------------------

@doGoEast

  #ifdef debug
    debug["doGoEast"]
  #endif

  let direction=theEast:goto @doGo

// ---------------------------------------------

@doGoWest

  #ifdef debug
    debug["doGoWest"]
  #endif

  let direction=theWest:goto @doGo

// ---------------------------------------------

@doGoOut

  #ifdef debug
    debug["doGoOut"]
  #endif

  let direction=theOutside
  let anExit=exit(currentLocation,direction)

  if anExit=0 then \
    // No explicit way out, so use the previous location instead
    let anExit=previousLocation

 goto @doGoExit

// ---------------------------------------------

@doGoIn

  #ifdef debug
    debug["doGoIn"]
  #endif

  let direction=theInside

// ---------------------------------------------

@doGo

  // Input: direction

  #ifdef debug
    debug["doGo"]
  #endif

  let anExit=exit(currentLocation,direction)

@doGoExit // used by the @doGoOut routine

  if anExit=0 then
    __echo["No puedo ir en esa dirección."]

  else if fnIsLocked(anExit) then

    if fnIsCarried(theKey) then

      __echo["Abro la puerta con la llave."]
      // Unlock the door from this side:
      let exit(currentLocation,direction)=\
        fnUnlocked(anExit)
      // Unlock from the other side
      // XXX FIXME -- it  works only if exits are regular
      // (N<-->S, E<-->W, etc):
      let exit(fnUnlocked(anExit),oppositeDirection(direction))=\
        currentLocation

      let previousLocation=currentLocation
      let currentLocation=fnUnlocked(anExit)
      gosub @enterLocation

    else
      __echo["No puedo ir en esa dirección. Hay una puerta cerrada con llave."]
    endif

  else

    let previousLocation=currentLocation
    let currentLocation=anExit
    gosub @enterLocation

  endif

  return

// ---------------------------------------------

@doTake

  #ifdef debug
    debug["doTake"]
  #endif

  if fnIsCarried(complement) then \
    __echo["Ya tengo "+fnWholeName$(complement)+"."]:\
    return

  if light=0 then \
    __echo["La oscuridad me lo impide."]:\
    return

  if complement=theAll then

    gosub @calculateThingsHere

    if thingsHere=0 then

      __echo["Aquí no veo nada que pueda recoger."]

    else

# XXX TODO -- Improve the listing, after the method used by the
# inventory.

#      let listed=0
      for complement=firstPortable to lastPortable
        if fnIsHere(complement) then
#          let listed=listed+1
          gosub @doTakePresentComplement
        endif
      next complement

    endif

    return

  endif

@doTakeComplement

  if fnIsNotHere(complement) then \

    __echo["No veo "+fnWholeName$(complement)+" aquí."]:\
    # __echo["No veo eso aquí."]:\ // XXX simpler alternative
    return

@doTakePresentComplement

  if complement>=thePotA and complement<=thePotE then \
    __echo["Eso debe de pesar más que una vaca."]:\
    return

  // XXX TODO improve or remove this plot condition
  #   if carried=maxCarried then \
  #     __echo["No puedo llevar más cosas."]:\
  #     return

  // XXX TODO check the pot, and issue proper messages, "it's too heavy"

  let thingLocation(complement)=theProtagonist:\
  let carried=carried+1
  __echo["Recojo "+fnWholeName$(complement)+"."]

  // XXX OLD
  # if complement=thePot then \
  #   if thingLocation(theKey)=theLimbo then \
  #     __echo["Debajo del tiesto estaba la llave."]:\
  #     let thingLocation(theKey)=currentLocation

  return

// ---------------------------------------------

@doDrop

  #ifdef debug
    debug["doDrop"]
  #endif

  if complement=theAll then

    if carried=0 then

      __echo["No tengo nada."]

    else

      __echo["Dejo"]
      let listed=0
      for n=firstPortable to lastPortable
        if fnIsCarried(n) then
          let listed=listed+1
          if listed=carried then            // the last one
            if carried>1 then echo["y"]
            echo[fnWholeName$(n)+"."]
          else if listed=carried-1 then     // the last but one
            echo[fnWholeName$(n)]
          else
            echo[fnWholeName$(n)+","]
          endif
          let thingLocation(n)=currentLocation
        endif
      next n
      let carried=0

    endif

  else

    if fnIsNotCarried(complement) then
      gosub @notCarriedError
    else
      let thingLocation(complement)=currentLocation:\
      let carried=carried-1
      __echo["Dejo "+fnWholeName$(complement)+"."]
    endif

  endif

  return

// ---------------------------------------------

@doOpen

  #ifdef debug
    debug["doOpen"]
  #endif

  if complement=theSafe then \
  goto @doOpenTheSafe

  if fnIsNotCarried(theKey) then \
    __echo["No tengo la llave."]:\
    return

  // XXX TODO improve
  for n=theNorth to theWest
    let anExit=exit(currentLocation,n)
    if fnIsLocked(anExit) then
      let exit(currentLocation,n)=fnUnlocked(anExit):\
      let exit(fnUnlocked(anExit),n-(n=2 or n=4)+(n=1 or n=3))=currentLocation:\
      __echo["Abro la puerta que va al "+fnTheName$(n)+"."]:\
      return
    endif
  next n
  __echo["No hay ninguna puerta cerrada."]

  return

// ---------------------------------------------

@doDo

  #ifdef debug
    debug["doDo"]
  #endif

  // XXX TODO other possible complements?

// ---------------------------------------------

@doInventory

  if carried=0 then \
    __echo["No tengo nada."]:\
    return

  let listed=0
  __echo["Tengo"]
  for n=firstPortable to lastPortable
    if fnIsCarried(n) then
      let listed=listed+1
      if listed=carried then            // the last one
        if carried>1 then echo["y"]
        echo[fnWholeName$(n)+"."]
      else if listed=carried-1 then     // the last but one
        echo[fnWholeName$(n)]
      else
        echo[fnWholeName$(n)+","]
      endif
    endif
  next n

  return

// ---------------------------------------------

@doLook

  #ifdef debug
    debug["doLook"]
  #endif

  if complement=theAll or complement=noThing then

    gosub @describeCurrentLocation:\
    gosub @showThings:\
    gosub @showExits

  else if light=0 then

    __echo["Me encantaría poder ver en la oscuridad."]

  else if fnIsNotCarried(complement) and fnIsNotHere(complement) then

    __echo["No veo "+fnWholeName$(complement)+" aquí."]


  // XXX TODO -- Use `on goto` for the rest. Problem: the numeric
  // values should be known, because of the order, and all the
  // unimportant things should be included. Alternative solution: Use
  // a double array. New problem: the array should contain the line
  // numbers, so it should be created here, not in <init.bas>.

  else if complement=thePaperPiece then

    if fnIsCarried(complement) then
      __echo["Tiene algo escrito."]:\
      let pauseSeconds=100:gosub @pause:\
      readThePaperPiece
    else
      __echo["Ahí está."] // XXX TODO
    endif

  else if complement=theBooks then

    __echo["Los libros están polvorientos."]

  else if complement=theLivingTable then

    __echo["Es una triste mesa de acampada, enclenque y oxidada."]

  else if complement=theDiningTables then

    __echo["Son viejas y desgastadas mesas de madera."]

  else if complement>=theNorth and complement<=theOutside then

    let anExit=exit(currentLocation,complement)
    if anExit=0 and complement=theOutside then
      // No explicit way out, so use the previous location instead
      #ifdef debug
        debug["Se usa en su lugar el escenario previo: "+str$(previousLocation)]:\
      #endif
      let anExit=previousLocation
    endif

    if anExit then
      __echo["Hacia "+fnIfs$(complement<theInside,"el ")+fnWholeName$(complement)+" está "+locationName$(fnUnlocked(anExit)*(anExit>locked))+fnIfs$(anExit<locked,".")+fnIfs$(anExit>locked,", pero la puerta está cerrada.")]
    else
      __echo["No hay salida hacia "+fnIfs$(complement<theInside,"el ")+fnWholeName$(complement)+"."]
    endif

  else if complement=theInventory then

    goto @doInventory

  else

    // Default message
    # __echo["No veo nada especial en "+fnWholeName$(complement)+"."]
    __echo["No veo nada especial."]

  endif

  return

// ---------------------------------------------

@doExamine

#  #ifdef debug
    debug["doExamine"]
#  #endif

  if complement=theAll or complement=noThing then

    gosub @describeCurrentLocation:\
    gosub @showThings:\
    gosub @showExits

  else if light=0 then

    __echo["Con esta oscuridad no es posible examinar nada."]

  else if fnIsNotCarried(complement) and fnIsNotHere(complement) then

    // XXX FIXME -- This does not work with the carried key.

    __echo["No veo "+fnWholeName$(complement)+" aquí."]

    stop // XXX TMP --

  else if complement=thePaperPiece then

    if fnIsCarried(complement) then
      __echo["Tiene algo escrito."]:\
      let pauseSeconds=100:gosub @pause:\
      readThePaperPiece
    else
      __echo["Ahí está."] // XXX TODO
    endif

  // XXX TODO -- faster, use 'on goto' instead of one 'if' for every
  // possible complement:

  else if complement=theBooks then

    // XXX TODO
    __echo["Examino los libros polvorientos."]

  else if complement=theLivingTable then

    // XXX TODO
    __echo["Es una triste mesa de acampada, enclenque y oxidada."]

  else if complement=theDiningTables then

    // XXX TODO
    __echo["Son viejas y desgastadas mesas de madera."]

  else if complement>=thePotA and complement<=thePotE then

    // XXX TODO -- use `fnIsBetween(x,from,to)`
  
    gosub @searchPot

  else if complement=theInventory then

    goto @doInventory

  else

    // Default message
    # __echo["No nada especial en "+fnWholeName$(complement)+"."]
    __echo["No veo nada especial."]

  endif

  return

// ---------------------------------------------

@doTurnOff

  #ifdef debug
    debug["doTurnOff"]
  #endif

  if fnIsNotCarried(complement) then \
    gosub @notCarriedError:\
    return

  if light=0 then \
    __echo["Ya está apagada."]
    let light=FALSE

  return

// ---------------------------------------------

@doTurnOn

  #ifdef debug
    debug["doTurnOn"]
  #endif

  if fnIsNotCarried(complement) then \
    gosub @notCarriedError:\
    return

  if light then \
    __echo["Ya está encendida."]
    let light=TRUE

  return

// ---------------------------------------------

@doRead

  #ifdef debug
    debug["doRead"]
  #endif

  if fnIsNotCarried(complement) then \
    gosub @notCarriedError:\
    return

  if light=0 then \
    __echo["No puedo leer a oscuras."]:\
    return

  if complement=thePaperSheet then:\
    // XXX TODO
    __echo["Está en blanco."]:\
    return

  if complement=thePaperPiece then \
    gosub @readThePaperPiece

  return

// =============================================================
// Action tools {{{1

// ---------------------------------------------

@knownThing

  // A given thing is known, therefore change its article type
  //
  // Input: thing

  if thingArticleType(thing)<>possesive then \
    let thingArticleType(thing)=definite
  return

@doOpenTheSafe

  if safeOpened then \
    __echo["Ya estaba abierta."]:\
   return

  __echo["¿Cuál es la combinación?"]:\
  gosub @accept

  if command$=safeCode$ then \

    // XXX TODO
    let safeOpened=TRUE:\

  else \

    __echo["La caja no se abre."]:\
    __echo["Parece que esa no es la combinación."]

  return

// ---------------------------------------------

@readThePaperPiece

  __echo["Pone... "+safeCode$]

  return

// =============================================================
// Puzzles {{{1

@searchPot

  if keyPot<0 then

    // The key was already found.

    __echo["No tiene nada de especial."]
    if complement=abs(keyPot) then \
      echo["Buen sitio eligió el Gafopelao para esconder la llave."]

  else

    // The key has not being found yet.

    if complement=keyPot then

      // The key is in the searched pot.

      __echo["¡Aquí está la llave! "+\
        fnIfs$(examinedPots=0,"¡A la primera! ")+\
        fnIfs$(examinedPots<3,"No ha sido tan difícil.")+\
        fnIfs$(examinedPots>2,"¡Por fin!")+\
        fnIfs$(examinedPots=totalPots,"Tenía que estar en el último.")]
      let thingLocation(theKey)=theProtagonist:\
      let carried=carried+1
      let keyPot=-keyPot

    else

      __echo["En este "+\
        fnIfElses$(examinedPots,"tampoco","primero no")+\
        " está la llave."]:\

      #    __echo["Aquí no hay llave. Este Pelao se va a enterar."] //
      #    XXX TODO --

      let examinedPots=examinedPots+abs(examinedPots<totalPots)

    endif

  endif

  return

// =============================================================
// Locations {{{1

// ---------------------------------------------
// Enter location {{{2

@enterLocation

  // XXX TODO separate plot and description

  let visits(currentLocation)=visits(currentLocation)+1
  gosub @describeNewLocation
  gosub @locationPlot
  if gameOver=0 then \
    gosub @showThings:\
    gosub @showExits

  return

// ---------------------------------------------
// Describe new location {{{2

@describeNewLocation

  // XXX FIXME -- "Entro en / Vuelvo a", but problem: "a / al / a la"

  gosub @wtCls
  __echo["Entro en"] // XXX TODO more options
  goto @onLocationGoto

// ---------------------------------------------
// Describe current location {{{2

@describeCurrentLocation

  __echo["Estoy en"] // XXX TODO more options

@onLocationGoto

  on currentLocation goto \

  // The following list of labels must be in alphabetical order, to
  // match the values of the correspondent location ids defined in
  // <common.bas>.  These routines must end with 'return'.

    @atTheBasement,\
    @atTheBathroomA,\
    @atTheBathroomB,\
    @atTheChapel,\
    @atTheClassA,\
    @atTheClassB,\
    @atTheCorridorA,\
    @atTheCorridorB,\
    @atTheCorridorC,\
    @atTheCorridorD,\
    @atTheCorridorE,\
    @atTheCorridorF,\
    @atTheDining,\
    @atTheEntranceA,\
    @atTheEntranceB,\
    @atTheEntranceC,\
    @atTheEntranceD,\
    @atTheEntranceE,\
    @atTheGym,\
    @atTheHall,\
    @atTheJunkRoom,\
    @atTheKitchen,\
    @atTheLarder,\
    @atTheLibrary,\
    @atTheLiving,\
    @atTheLobby,\
    @atTheOfficeA,\
    @atTheOfficeB,\
    @atTheOfficeC,\
    @atTheReception,\
    0: // XXX TMP -- for debugging

  fatal_error["Flujo descontrolado en la rutina 'describeLocation'"] // XXX TMP

// ---------------------------------------------
// Location plot {{{2

@locationPlot

  // XXX TODO remove the gotos

  if fnIsHere(theGuard) then

    __echo["¡El guarda está aquí!"]
    let pauseSeconds=100:gosub @pause
    gosub @catchedByTheGuard

  else if outside(currentLocation) then

    // XXX TODO -- success?
    #     if examCopied and marksModified and fnIsCarried(thePaperSheet) then \
    #       goto @theEnd

  endif

  #   __echo["XXX -- End of PROC_locationPlot"]

  return

// ---------------------------------------------
// List present things {{{2

@showThings

  gosub @calculateThingsHere

  if thingsHere=0 then \
    return

  let listed=0
  __echo["Veo"]
  for n=1 to thingsHere
    let i=asc(mid$(thingsHere$,n,1))
    #ifdef debug
      debug["Cosa número"+str$(i)+": "+fnWholeName$(i)+"." ]
      debug["fnIsHere("+str$(i)+"): "+str$(fnIsHere(i))+"." ]
    #endif
    if fnIsHere(i) then
      let listed=listed+1
      if listed=thingsHere then
        // The last one
        if thingsHere>1 then echo["y"]
        echo[fnWholeName$(i)+"."]
      else if listed=thingsHere-1 then
        // The last but one
        echo[fnWholeName$(i)]
      else
        echo[fnWholeName$(i)+","]
      endif
    endif
  next n

  return

@calculateThingsHere

  let thingsHere$=""
  for n=firstPortable to lastPortable
    if fnIsHere(n) then \
      let thingsHere$=thingsHere$+chr$(n)
  next n
  let thingsHere=len(thingsHere$)

  #ifdef debug
    debug["Cosas: "+str$(thingsHere)]
  #endif

  return

// ---------------------------------------------
// List exits {{{2

@showExits

  let exitsHere=exits(currentLocation)

  #ifdef debug
    debug["Salidas: "+str$(exitsHere)]
  #endif

  if exitsHere=0 then \
    return

  let listed=0
  __echo["Hay salida"+left$("s",abs(exitsHere>1))+" hacia"]

  for n=theNorth to theWest

    #ifdef debug
      debug["Salida "+str$(n)+": "+str$(exit(currentLocation,n))]
    #endif

    // XXX TODO add short names of destinations?
    if exit(currentLocation,n) then
      let listed=listed+1
      if listed=exitsHere then
        // The last one
        if exitsHere>1 then echo["y"]
        echo[fnTheName$(n)+"."]
        # echo[fnExitNoun$(n)+"."] // XXX TODO destination's short name
      else if listed=exitsHere-1 then
        // The last but one
        echo[fnTheName$(n)]
        # echo[fnExitNoun$(n)] // XXX TODO destination's short name
      else
        echo[fnTheName$(n)+","]
        # echo[fnExitNoun$(n)+","] // XXX TODO destination's short name
      endif
    endif

  next n

  #ifdef debug
    debug["Salida "+str$(theInside)+": "+str$(exit(currentLocation,theInside))]
    debug["Salida "+str$(theOutside)+": "+str$(exit(currentLocation,theOutside))]
  #endif

  return

// =============================================================
// Location descriptions {{{1

// ---------------------------------------------

@atTheEntranceA

  echo[locationName$(theEntranceA)+"."]
  return

// ---------------------------------------------

@atTheEntranceB

  echo[locationName$(theEntranceB)+"."]
  return

// ---------------------------------------------

@atTheEntranceC

  echo[locationName$(theEntranceC)+"."]
  return

// ---------------------------------------------

@atTheEntranceD

  echo[locationName$(theEntranceD)+"."]
  return

// ---------------------------------------------

@atTheEntranceE

  echo[locationName$(theEntranceE)+"."]
  return

// ---------------------------------------------

@atTheBathroomB

  echo[locationName$(theBathroomB)+"."]
  echo["El olor es inaguantable."]
  return

// ---------------------------------------------

@atTheGym

  echo[locationName$(theGym)+"."]
  echo["El olor a zapato es sobrehumano."]
  return

// ---------------------------------------------

@atTheLarder

  echo[locationName$(theLarder)+"."]
  echo["Hay un tufo a carne podrida."]
  return

// ---------------------------------------------

@atTheKitchen

  echo[locationName$(theKitchen)+"."]
  echo["La suciedad cubre los muebles."]
  return

// ---------------------------------------------

@atTheBasement

  echo[locationName$(theBasement)+"."]
  if light=0 then \
    __echo["Todo está a oscuras."] \
  else \
    // XXX FIXME print something here to finish the paragraph
    let light=FALSE

  return

// ---------------------------------------------

@atTheJunkRoom

  echo[locationName$(theJunkRoom)+"."]
  if light=0 then \
    __echo["Todo está a oscuras."] \
  else \
    // XXX FIXME print something here to finish the paragraph
    let light=FALSE

  return

// ---------------------------------------------

@atTheHall

  echo[locationName$(theHall)+","]

  if fnLongLocationDescription(0) then

    echo["una diminuta pieza que comunica los despachos entre sí."]
    echo["Es tan pequeña que la llamamos «la cabina», como la peli;"]
    echo["y también porque aquí,"]
    echo["cuando el director te llama a su despacho para nada bueno,"]
    echo["te hacen esperar de pie, sin lugar donde sentarte,"]
    echo["unos largos y tensos minutos,"]
    echo["hasta que el Oleolesimeligen se digna a abrir la puerta."]

  else

    echo["alias «la cabina»."]

  endif

  return

// ---------------------------------------------

@atTheLobby

  echo[locationName$(theLobby)+"."]
  return

// ---------------------------------------------

@atTheReception

  echo[locationName$(theReception)+"."]
  // XXX TODO create the things
  # echo["Varias ventanillas."]
  return

// ---------------------------------------------

@atTheLiving

  if fnLongLocationDescription(0) then

    // XXX TODO create the mentioned things
    echo[locationName$(theLiving)+"."]
    echo["La triste mesa y sus tres esqueléticas e incómodas sillas,"]
    echo["le dan a esta salita de visitas el aspecto"]
    echo["de la sala de interrogatorios que realmente es."]
    echo["En una de las desnudas paredes hay un pequeño y sucio ventanuco"]
    echo["por el que, cuando es de día, con gran esfuerzo, logran entrar"]
    echo["uno o dos agotados rayos de luz."]

  else

    echo[locationName$(theLiving)+","]
    echo["también llamada «sala de interrogatorios»."]

  endif

  return

// ---------------------------------------------

@atTheCorridorA

  echo[locationName$(theCorridorA)+"."]
  return

// ---------------------------------------------

@atTheCorridorB

  echo[locationName$(theCorridorB)+"."]
  return

// ---------------------------------------------

@atTheCorridorC

  echo[locationName$(theCorridorC)+"."]
  return

// ---------------------------------------------

@atTheCorridorD

  echo[locationName$(theCorridorD)+"."]
  return

// ---------------------------------------------

@atTheCorridorE

  echo[locationName$(theCorridorE)+"."]
  return

// ---------------------------------------------

@atTheCorridorF

  echo[locationName$(theCorridorF)+"."]
  return

// ---------------------------------------------

@atTheBathroomA

  echo[locationName$(theBathroomA)+"."]
  return

// ---------------------------------------------

@atTheChapel

  echo[locationName$(theChapel)+"."]
  return

// ---------------------------------------------

@atTheDining

  echo[locationName$(theDining)+"."]
  return

// ---------------------------------------------

@atTheOfficeA

  echo[locationName$(theOfficeA)+"."]
  return

// ---------------------------------------------

@atTheOfficeB

  echo[locationName$(theOfficeB)+"."]
  return

// ---------------------------------------------

@atTheOfficeC

  echo[locationName$(theOfficeC)+"."]
  return

// ---------------------------------------------

@atTheClassA

  echo[locationName$(theClassA)+"."]
  return

// ---------------------------------------------

@atTheClassB

  echo[locationName$(theClassB)+"."]
  return

// ---------------------------------------------

@atTheLibrary

  echo[locationName$(theLibrary)+"."]
  // XXX TODO create the things
  echo["Una montaña de libros polvorientos oculta la pared."]
  return

// =============================================================
// Text output {{{1

// ---------------------------------------------
// Debug message {{{2

@debug

  // Print a debug message.
  //
  // input: text$

  let tex$="INFO:"+text$
  goto @error

// ---------------------------------------------
// Fatal error message {{{2

@fatal_error

  // Print a fatal meta error as a justified paragraph in the current
  // window.
  //
  // input: text$

  let text$="ERROR FATAL: "+text$

// ---------------------------------------------
// Meta error message {{{2

@error

  // Print a meta error as a justified paragraph in the current
  // window.
  //
  // input: text$

  color red
  __echo[text$]
  gosub @defaultColor
  return

// =============================================================
// Time {{{1

// ---------------------------------------------
// Pause {{{2

@pause

  let pauseLimit!=timer+pauseSeconds
  do
    if inkey$<>"" then exit do
  loop until timer>=pauseLimit!

  return

// ---------------------------------------------
// Text pause {{{2

@textPause

  gosub @wtCr
  let tmpCol%=pos(0)
  let tmpRow%=csrlin
  print textPausePrompt$
  let pauseSeconds=60
  gosub @pause
  locate tmpRow%,tmpCol%,0
  print string$(len(textPausePrompt$),32)
  locate tmpRow%,tmpCol%,0
  return

// =============================================================
// Init the game {{{1

@initGame

  // Init needed before every game.

  randomize timer

  // Flags

  let gameOver=FALSE
  let safeOpened=FALSE
  let guardMet=FALSE // XXX  not used yet
  let light=TRUE // XXX TMP for debugging

  // The safe code

  for n=1 to safeCodeDigits
    let safeCode$=safeCode$+chr$(fnBetween(asc("0"),asc("9")))
  next n

  // Done actions

  // XXX TODO -- not used yet

  erase done
  dim done(actions,things)

  # XXX OLD -- this method makes no difference after `run`, same error,
  # because `done()` has been deleted:

  # for m=1 to actions:\
  #   for n=1 to things:\
  #     let done(m,n)=0:\
  #   next n:\
  # next m

  // Default location of things

  // load "location.dat" data thingLocation():\
  // XXX TODO --

  // Random location of some things

  // XXX FIXME -- do this only to things marked to do so (they can
  // have a negative constant in the location).

  for n=1 to things
    if syntax(toTake,n) then
      do
        # let i=fnBetween(1,locations)
        let i=theHall // XXX TMP for debugging
      loop while outside(i)
      let thingLocation(n)=i
    endif
  next n

  // Special location of some things

  // Location of the pots

  // XXX FIXME -- this is already done in the data, but still required
  // until the random loop above is fixed.

  for n=thePotA to thePotE:\
    let thingLocation(n)=theEntranceA+n-thePotA:\
  next n

  let thingLocation(theSafe)=theOfficeA:\
  let thingLocation(theBooks)=theLibrary:\ // XXX needed? could be set in the original data
  let thingLocation(theTorch)=\
  asc(fnChar$(\
    chr$(theOfficeC)+\
    chr$(theReception)+\
    chr$(theClassA)+\
    chr$(theClassB)+\
    chr$(theJunkRoom)\
  )):\
  let thingLocation(theKey)=theLimbo

  // Location of the protagonist

  let currentLocation=fnBetween(theEntranceA,theEntranceE)
  # let currentLocation=theHall // XXX TMP
  let previousLocation=0

  // Location of the guard

  do
    let thingLocation(theGuard)=fnBetween(theEntranceA,theEntranceE)
  loop while fnIsHere(theGuard)

  // Plot

  let keyPot=fnBetween(thePotA,thePotD):\ // the pot the key is hidden into
  let examinedPots=0:\ // counter
  let lastPot=0:\ // last pot manipulated by the protagonist

  let carried=0 // number of things currently carried

  return

// =============================================================
// Credits

@credits

  echo["CE4"]
  _echo["Versión "+version$]
  _echo[copyright$]
  __echo["Memoria libre: "+str$(fre(0))+" B"]  // XXX TMP --
  gosub @wtCr

  gosub @textPause

  return

// =============================================================
// Intro {{{1

@intro

  cls
  restore @introText
  do
    read text$
    if text$="END" then exit do
    if text$="" then gosub @wtCr:gosub @wtCr else gosub @wt
  loop
  gosub @textPause // XXX OLD
  return

@introText

  // XXX TODO -- move to a text file:

  data "Ya es medianoche. Menudo frío que hace."
  data ""
  data "Y para colmo el Gafopelao me ha dejado solo.  «Esconderé la llave en un tiesto»,"
  data "me dice ayer, de repente, durante el examen de mates, así por lo bajito, con su"
  data "susurro de chicharra moribunda: «Pero ya te diré cuál elijo para que no me vea"
  data "el guarda.  Llámame a la hora de la merienda y te lo digo»."
  data ""
  data "Pues ni a la hora de la merienda ni a la hora de la cena: No sé cuántas veces lo"
  data "he llamado y nadie respondía al teléfono en su casa.  Seguro que le ha explotado"
  data "el cerebro y lo han llevado al ambulatorio.  Pero no será por estudiar mates,"
  data "sino por pasarse el día programando su computadora.  Se lo he dicho un montón de"
  data "veces: «Pon algún juego de vez en cuando, Gafopelao, que te va a estallar la"
  data "cabeza»."
  data ""
  data "Ahora me va a tocar buscar la llave."
  data "END"

// =============================================================
// Init once {{{1

@initOnce

  // This routine is called only once, before the first game.

  // Variables

  let banished=FALSE
  let recordHours=0
  let recordMinutes=16
  let recordSeconds=0
  let totalRecordSeconds=recordMinutes*60
  let recordMan$="Lutero"

  // Other

  gosub @initScreen
  gosub @initAccept

  return

// =============================================================

@initScreen

  gosub @defaultColor
  gosub @wtInit
  let wtIndentation%=0      // spaces at the start of a paragraph's first line
  let wtParaSeparation%=1   // blank lines between paragraphs
  gosub @wtCls

  return

// =============================================================
// Default color

@defaultColor

  color foregroundColor,backgroundColor,borderColor:\
  return

// =============================================================
// Meta {{{1

  #ifdef debug

    // XXX TMP

    for n=1 to things
      print n,fnWholeName$(n)
    next n

  #endif

# vim:filetype=imbastardizer

Added src/target.bas.







>
>
>
1
2
3
#target gwbasic

# vim:filetype=imbastardizer

Added src/target.gw-basic.bas.







>
>
>
1
2
3
#target gwbasic

# vim:filetype=imbastardizer

Added src/target.pc-basic.bas.









>
>
>
>
1
2
3
4
#target pcbasic

# vim:filetype=imbastardizer

Deleted src/udg.bin.

cannot compute difference between binary files

Deleted src/udg.z80s.

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
; z80/udg.z80s
;
; This file is part of the CE4 project,
; a text adventure in Spanish
; written in Vimclair BASIC for the ZX Spectrum +3e

; This Z80 code defines the UDG characters, mainly Spanish letters and
; punctuation.

; 2014-08-10: Copied from the Nuevo Mundo project, in ZX BASIC, by the same
; author.

  public ce4_udg
ce4_udg

  ; á
  defb %00001000
  defb %00010000
  defb %00111000
  defb %00000100
  defb %00111100
  defb %01000100
  defb %00111100
  defb %00000000
  ; Á
  defb %00000100
  defb %00001000
  defb %00111100
  defb %01000010
  defb %01111110
  defb %01000010
  defb %01000010
  defb %00000000
  ; é
  defb %00001000
  defb %00010000
  defb %00111000
  defb %01000100
  defb %01111000
  defb %01000000
  defb %00111100
  defb %00000000
  ; É
  defb %00000100
  defb %00001000
  defb %01111110
  defb %01000000
  defb %01111100
  defb %01000000
  defb %01111110
  defb %00000000
  ; í
  defb %00001000
  defb %00010000
  defb %00000000
  defb %00110000
  defb %00010000
  defb %00010000
  defb %00111000
  defb %00000000
  ; Í
  defb %00000100
  defb %00001000
  defb %00111110
  defb %00001000
  defb %00001000
  defb %00001000
  defb %00111110
  defb %00000000
  ; ó
  defb %00001000
  defb %00010000
  defb %00111000
  defb %01000100
  defb %01000100
  defb %01000100
  defb %00111000
  defb %00000000
  ; Ó
  defb %00001000
  defb %00010000
  defb %00111100
  defb %01000010
  defb %01000010
  defb %01000010
  defb %00111100
  defb %00000000
  ; ú
  defb %00001000
  defb %00010000
  defb %01000100
  defb %01000100
  defb %01000100
  defb %01000100
  defb %00111000
  defb %00000000
  ; Ú
  defb %00000100
  defb %01001010
  defb %01000010
  defb %01000010
  defb %01000010
  defb %01000010
  defb %00111100
  defb %00000000
  ; ñ
  defb %00000000
  defb %01111000
  defb %00000000
  defb %01111000
  defb %01000100
  defb %01000100
  defb %01000100
  defb %00000000
  ; Ñ
  defb %00111100
  defb %00000000
  defb %01100010
  defb %01010010
  defb %01001010
  defb %01000110
  defb %01000010
  defb %00000000
  ; ü
  defb %01000100
  defb %00000000
  defb %01000100
  defb %01000100
  defb %01000100
  defb %01000100
  defb %00111000
  defb %00000000
  ; Ü
  defb %01000010
  defb %00000000
  defb %01000010
  defb %01000010
  defb %01000010
  defb %01000010
  defb %00111100
  defb %00000000
  ; ¿
  defb %00000000
  defb %00010000
  defb %00000000
  defb %00010000
  defb %00100000
  defb %01000010
  defb %00111100
  defb %00000000
  ; ¡
  defb %00000000
  defb %00001000
  defb %00000000
  defb %00001000
  defb %00001000
  defb %00001000
  defb %00001000
  defb %00000000
  ; º
  defb %00011000
  defb %00100100
  defb %00011000
  defb %00000000
  defb %00111100
  defb %00000000
  defb %00000000
  defb %00000000
  ; «
  defb %00000000
  defb %00000000
  defb %00010010
  defb %00100100
  defb %01001000
  defb %00100100
  defb %00010010
  defb %00000000
  ; »
  defb %00000000
  defb %00000000
  defb %01001000
  defb %00100100
  defb %00010010
  defb %00100100
  defb %01001000
  defb %00000000
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































































































































































































































































































Added src/version.bas.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// version.bas

// This file is part of

rem CE4

// A text adventure in Spanish
// written in GW-BASIC
// with the Imbastardizer preprocessor
// for the PC-BASIC emulator.

let version$="0.20.1+201709130121"
//  (after Semantic Versioning: http://semver.org)
let copyright$="(C) 2014..2017 Marcos Cruz (programandala.net)"

# vim:filetype=imbastardizer

Added src/wt.bas.











































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// wt.bas

// =============================================================
// Description

' wt ("wrapping text") is a text output module for GW-BASIC,
' written with the Imbastardizer preprocessor.

'  Version 0.3.1+201706132336
// (after Semantic Versioning: http://semver.org)

// =============================================================
// Author and license

' Copyright (C) 2016,2017 Marcos Cruz (programandala.net)

// You may do whatever you want with this work, so long as you retain
// the copyright/authorship/acknowledgment/credit notice(s) and this
// license in all redistributed copies and derived works.  There is no
// warranty.

// =============================================================
// To-do

// scroll, pause

// =============================================================
// History

// See at the end of the file.

// =============================================================
// Usage

// Merge this source at the end of the function definitions of your
// main source.

// =============================================================
// Imbastardizer directives

#vim %substitute,\<TRUE\>,-1,gi
#vim %substitute,\<FALSE\>,0,gi

// =============================================================
// Functions

def fnwtFreeCols%(x)=(wtCols%-pos(0)+1)

goto @skipWT

// =============================================================

@wtInit

  let wtFastMode%=TRUE:\      // TRUE=print by lines; FALSE=print by words
  let wtCols%=80:\
  let wtRows%=25:\
  let wtCol%=1:\              // backup of the last used column
  let wtRow%=1:\              // backup of the last used row
  let wtCursor%=FALSE:\       // show the cursor when restoring its position?
  let wtIndentation%=2:\      // spaces at the start of a paragraph
  let wtParaSeparation%=0:\   // blank lines between paragraphs
  return
  // Init the constants and variables of the module.

// =============================================================

@wtCls

  // Clear the screen and set the cursor at the top left position.

  cls

// =============================================================

@wtHome

  // Set the cursor at the top left position.

  locate 1,1:\
  gosub @wtSavePosition:\
  return

// =============================================================

@wtCr

  // Do a carriage return, if needed.

  gosub @wtRestorePosition
  if pos(0)>1 then gosub @wtDoCr
  return

// =============================================================

@wtDoCr

  // Do a carriage return.

  gosub @wtRestorePosition
  print:\
  gosub @wtSavePosition:\
  return

// =============================================================

@wtIndent

  // Do a carriage return and indent.

  gosub @wtCr:\
  if csrlin>1 then \
    print string$(wtIndentation%,32);:\
    gosub @wtSavePosition
  return

// =============================================================

@wtByWords

  // Print `text$` at the current cursor position, left
  // justified, word after word. This is slower than line by
  // line printing.

  do

    let wtSpacePos%=instr(text$," ")
    if wtSpacePos% then \
      let aWord$=left$(text$,wtSpacePos%-1):\
      let text$=mid$(text$,wtSpacePos%+1) \
    else \
      let aWord$=text$:\
      let text$=""

    if fnwtFreeCols%(0)<len(aWord$) then gosub @wtCr
    print aWord$;
    if pos(0)>1 and pos(0)<wtCols% then print " ";

  loop until len(text$)=0

  gosub @wtSavePosition

  return

// =============================================================

@wt

  // Print `text$` at the current cursor position, left
  // justified, word after word or line after line.

  if not(wtFastMode%) then goto @wtByWords

// =============================================================

@wtByLines

  // Print `text$` at the current cursor position, left
  // justified, line after line. This is faster than word by
  // word printing. This is the default.

  do

    let wtFreeCols%=fnwtFreeCols%(0)

    if len(text$)<=wtFreeCols% then \
      print text$;:\
      let text$="":\
      goto @wtByLines_separate

    let wtSpaceFound%=FALSE

    for wtSpacePos%=wtFreeCols%+1 to 1 step -1

      if mid$(text$,wtSpacePos%,1)=" " then \
        print left$(text$,wtSpacePos%-1);:\
        let text$=mid$(text$,wtSpacePos%+1):\
        let wtSpaceFound%=TRUE:\
        goto @wtByLines_search_done

    next wtSpacePos%

@wtByLines_search_done

    if not(wtSpaceFound%) then \
      gosub @wtCr:\
      let wtFreeCols%=fnwtFreeCols%(0):\
      print left$(text$,wtFreeCols%);:\
      let text$=mid$(text$,wtFreeCols%+1)

@wtByLines_separate

    if pos(0)>1 and pos(0)<wtCols% then print " ";
    if fnwtFreeCols%(0)<2 then print

  loop while len(text$)

// =============================================================

@wtSavePosition

  let wtCol%=pos(0):\
  let wtRow%=csrlin:\
  return

// =============================================================

@wtRestorePosition

  locate wtRow%,wtCol%,wtCursor%:\
  return

// =============================================================

@wtNewLine

  // Print `text$` on a new line, left justified

  gosub @wtCr:\
  gosub @wt:\
  return

// =============================================================

@wtNewPara

  // Print `text$` on a new paragraph, left justified.

  gosub @wtRestorePosition
  if (wtParaSeparation%>0) and (csrlin>1) then \
    for wtI%=1 to wtParaSeparation%:\
      gosub @wtDoCr:\
    next wtI%
  gosub @wtIndent:\
  gosub @wt:\
  return

@skipWT

// =============================================================
// History

// 2016-12-14: Start, from the source of wt v1.0.0+201611042344 for
// X11-Basic.
//
// 2016-12-15: First (partly) working version.
//
// 2016-12-27: Fix the main output routine.
//
// 2016-12-28: Add faster default method to print the texts,
// line by line. Save and restore the last cursor position, in order
// to make the system independent from ordinary printing.
//
// 2017-01-01: Rename `i%` to `wtI%` to fix a name clash with the main
// program.
//
// 2017-06-05: Rename IMBAS filename extension to BAS.
//
// 2017-06-13: Add Vim modeline to set filetype.

# vim: filetype=imbastardizer

Added target/.empty.

Added target/gw-basic/.empty.

Added target/pc-basic/.empty.