! QPrint
! Mid-string rule printing system.
! Dave Robinson
! khelwood at hotmail dot com
! version 1: 17-03-2005
! Rules are inserted into strings using % as an escape character.
! For instance,
! QPrint("You take %the 1% and put %it 1% into %the 2%.",obj1,obj2);
! is equivalent to
! print "You take ",(the) obj1," and put ", (itorthem) obj1,
! " into ",(the) obj2,".";
! The number 1 to 6 indicated which argument to use.
! For instance,
! QPrint("%The 1%,x,y,z);
! translates to print (The) x;
! whereas
! QPrint("%The 3%",x,y,z);
! translates to print (The) z;
! You can also use "noun" and "second" as argument indicators.
! For instance
! QPrint("You cannot take %the noun%.");
! or
! QPrint("You put %the n% into %the s%.");
! n is short for "noun"
! s is short for "second"
! a is short for "actor"
! Use examples:
! QPrint("You take %t n% and put %it n% in your pocket.");
! QPrint("%T n% %is n% too large to carry.");
! QPrint("You put %t 1% into %t 2%.", obj1, obj2);
! QPrint("There %is 1% %a 1% here.", x);
! Command list:
! ROUTINE:
! QPrint(" ... %f 1 2% ... ", rout, arg);
! This command calls function rout with argument arg.
! ADDRESS: goes like print (address) ...
! QPrint("The verb_word is '%addr 1%'.", verb_word);
! The figure 1 in the command means "first argument",
! in this case, verb_word.
! STRING: goes like print (string) ...
! QPrint("The string says ~%str 1%~.", "Hello there");
! CHAR: goes like print (char) ...
! QPrint("The character is %ch 1%.", 'X');
! NUMBER: goes like print n;
! QPrint("The number is %num 1%.", n);
! OBJECT: goes like print (object) ...
! QPrint("The object's object-name is %obj 1%.", obj);
! NAME: goes like print (name) ...
! QPrint("The object's short name is %name 1%.", obj);
! THE: goes like print (the) ... or print (The) ...
! QPrint("You open %the 1%.", noun);
! or equivalently
! QPrint("You open %the noun%.");
! or
! QPrint("You open %t n%.");
! t is short for "the" and n is short for "noun".
! If the t is capitalised, then the printing rule (The) is used.
! e.g. QPrint("%The 1% is open.",noun);
! or QPrint("%T n% is open.");
! A: goes like print (a) noun
! QPrint("You can see %a 1% here.", obj);
! GEN: goes like print (the) x, "'s";
! QPrint("%Gen 1% eyes are open.", person);
! Basically, this prints
! "Your" (or "your") if person==player
! (The) person,"'s" otherwise
! HE: Nominative pronoun
! QPrint("%He 1% explodes.", obj);
! prints "You" or "He" or "They" &c.
! If the h in %he is lower case, then
! prints "you" or "he" or "they" &c.
! HIM: Accusative pronoun
! QPrint("You hug %him 1%.", obj);
! prints "you" or "her" or "them" &c.
! HIS: Genitive pronoun
! QPrint("You take %his 1% pulse.", obj);
! prints "your" or "his" or "their" &c.
! if the h in %his is upper case then
! prints "Your" or "His" or "Their" &c.
! HERS:
! QPrint("That isn't %hers 1%.", obj);
! prints "yours" or "hers" or "theirs" &c.
! SELF:
! %self 1%
! prints "yourself" or "herself" or "themselves" &c.
! THAT:
! %That 1%
! prints "You" or "He" or "That" or "Those" &c.
! %that 1%
! prints "you" or "he" or "that" or "those" &c.
! THATS:
! %Thats 1%
! prints "You're" or "She's" or "That's" or "Those are"
! also works with lower case
! THATSNOT:
! %Thatsnot 1%
! prints "You're not" or "Those aren't" &c.
! also works with lower case
! HES:
! %Hes 1%
! prints "You're" or "He's" or "They're" &c.
! also works with lower case
! IS:
! QPrint("%The 1% %is 1% here.", obj);
! prints "are" if obj is player or plural
! prints "is" otherwise
! HAS:
! QPrint("The 1% %has 1% no windows.", obj);
! prints "have" if obj is player or plural
! prints "has" otherwise
! DOES:
! QPrint("%The 1% %do 1%n't reply.", obj);
! prints "does" or "do"
! S:
! QPrint("%The 1% look%s 1% around.", obj);
! prints "s" or nothing.
! The command above may print
! "You look around" or "Bob looks around" &c.
! ES:
! QPrint("The 1% focus%es 1% the telescope.", obj);
! prints "es" or nothing.
! The command above may print
! "You focus the telescope" or "Bob focuses the telescope" &c.
! INORON:
! %in 1% or %on 1% or %In 1% or %On 1%
! if the argument is a supporter, prints "on" or "On"
! otherwise prints "in" or "In"
! INORONTHE:
! Equivalent to %in followed by %the.
! OFFOROUTOF:
! %off 1%
! if the argument is a supporter prints "off"
! otherwise prints "out of"
! IF:
! %if X rule Y%
! where X indicates an argument that is considered as
! a boolean,
! rule indicates any rule listed here,
! Y indicates the arguments for the rule.
! So, for instance,
! QPrint("%if 1 the 2%", fl, obj);
! is equivalent to
! if (fl) print (the) obj;
! IFNOT:
! %if~ X rule Y%
! this works as above but "not"s the boolean argument.
! QUESTION:
! %? 1 txt1#txt2%
! If the boolean is true, prints txt1, otherwise
! prints txt2.
! For instance
! QPrint("The apple is %? 1 rotten#ripe%.", fl);
! will print "The apple is rotten."
! or "The apple is ripe."
! depending on fl.
! EMPH:
! %emph%, e.g. QPrint("%emph%This sentence in italics.%roman%.");
! or
! %emph txt%, e.g. QPrint("One word is in %emph italics%.");
! BOLD:
! As emph but with bold instead of italics.
! ROMAN:
! Switches style to roman.
! THEIS:
! Equivalent to %the followed by %is.
! e.g.
! QPrint("%Theis 1% open.", obj);
! or
! QPrint("%Tis 1% open.", obj);
! (where T is short for The).
! This also works with lower case.
! HEIS:
! %Heis 1%
! Equivalent to %He followed by %is.
! Also works with lower case.
! WAS:
! %was 1%
! prints "was" or "were"
! THEWAS:
! %Twas 1%
! equivalent to %The followed by %was
! Also works with lower case.
! THATWAS
! %Thatwas 1%
! equivalent to %That followed by %was
! Also works with lower case.
! OFFTHE:
! %offthe 1%
! equivalent to %off followed by %the
! HEWAS:
! %hewas 1%
! equivalent to %he followed by %was
! IFSPACE:
! %if_ 1 rule 2%
! if followed by a space if argument 1 is true.
! SPACEIF:
! %_if 1 rule 2%
! if preceded by a space if argument 1 is true.
! The routine QPR works the same as QPrint but prints
! a new-line at the end.
[ QPrint txt p1 p2 p3 f l i t m bfl;
QPArg-->0 = p1;
QPArg-->1 = p2;
QPArg-->2 = p3;
QPArg-->3 = f;
QPArg-->4 = l;
QPArg-->5 = i;
t = MAX_QPRINT_LENGTH;
#ifdef TARGET_GLULX;
l = PrintAnyToArray(QPchar,MAX_QPRINT_LENGTH,txt);
#ifnot; ! TARGET_ZCODE
@storew QPchar 0 t;
@output_stream 3 QPchar;
if (txt ofclass String)
print (string) txt;
else if (txt ofclass Routine)
txt.call();
else txt();
@output_stream -3;
l = QPchar-->0; ! l == length of txt
#endif; ! TARGET_
if (l>MAX_QPRINT_LENGTH)
{
print "^[Exceeded size for QPrint text on^ ~";
switch (metaclass(txt))
{
String: print (string) txt;
Routine: txt();
}
"~^ which is ",l," characters long.]^";
}
#IfDef TARGET_GLULX;
i = 0;
#IfNot; ! TARGET_ZCODE
i = 2; l = l + 2;
#EndIf; ! TARGET_
! print "[qprinting ~",(string)txt,"~^~";
! for (: i<l: i++)
! {
! print (char) (QPchar->i);
! }
! if (WORDSIZE==2) i = 2; else i = 0;
! print "~^]";
for (: i < l: i++) if (QPchar->i==QP_esc_ch)
{
i++;
if (QPchar->i==QP_esc_ch) { print (char) QP_esc_ch; continue; }
! print (char)'<';
QPchar->QP_POS_INDEX = i; ! store pos at end of array
bfl = 0;
t = QPType();
!print "[pos is ",QPchar->MAX_QPRINT_LENGTH," ('",
! (char) (QPchar->(QPchar->MAX_QPRINT_LENGTH)),"')]";
f = (t&QP_CAPS);
t = (t &~QP_CAPS);
if (t==QP_IF) bfl = 1;
if (t==QP_IFNOT) bfl = 2;
if (t==QP_IFSPACE) bfl = 3;
if (t==QP_SPACEIF) bfl = 4;
if (bfl)
{
i = QPParam();
(QPchar->QP_POS_INDEX)++;
t = QPType();
f = (t&QP_CAPS);
t = (t&~QP_CAPS);
switch (bfl)
{
1: if (i==0) bfl = 1; else bfl = 0;
2: if (i) bfl = 1; else bfl = 0;
3: if (i==0) bfl = 1; else bfl = 2; !print with space
4: if (i==0) bfl = 1;
else { print (char)' '; bfl = 0; }
}
!bfl==1 means "do not print"
}
if (t==0)
{
i = QPchar->QP_POS_INDEX;
print "[ QPrint failed at index ",i,": '",
(char) (QPchar->i),"']^";
while (i<l && QPchar->i~=QP_esc_ch) i++;
continue;
}
p1 = 0; p2 = 0; p3 = 0; i = 0;
! Set m to number of args required
m = 1;
if (t==QP_ROUTINE) m = 4;
if (t==QP_EMPH or QP_BOLD or QP_ROMAN) m = 0;
if (t==QP_NAME or QP_THE or QP_THEACC or QP_A or QP_GEN
or QP_THEIS or QP_THATACC or QP_THEWAS) m = 2;
if (t==QP_IFSTRING) m = 3;
if (m>0) p1 = QPParam(); !(1+QPchar->MAX_QPRINT_LENGTH);
! print "[pos is ",QPchar->MAX_QPRINT_LENGTH," ('",
! (char) (QPchar->(QPchar->MAX_QPRINT_LENGTH)),"')]";
if (m>1) p2 = QPParam(); !(1+QPchar->MAX_QPRINT_LENGTH);
if (m>2) p3 = QPParam(); !(1+QPchar->MAX_QPRINT_LENGTH);
if (m>3) i = QPParam(); !(1+QPchar->MAX_QPRINT_LENGTH);
if (p1==p2) switch (t)
{
QP_NAME, QP_THE: t = QP_HE;
QP_THEACC, QP_A, QP_THATACC: t = QP_SELF;
QP_GEN: t = QP_HIS;
QP_THEIS: t = QP_HEIS;
QP_THEWAS: t = QP_HEWAS;
}
if (bfl~=1) QPrintType(t,p1,p2,p3,i,f);
if (bfl==2) print (char)' ';
QP_NAME: print (name) p1;
QP_THE, QP_THEACC: if (f) print (The) p1; else print (the) p1;
QP_A: if (f) print (A) p1; else print (a) p1;
QP_GEN:
if (f) print (The) p1;
else print (the) p1;
! slightly dodgy, this
print (char)''';
if (p1 hasnt pluralname) print (char)'s';
QP_HE:
if (f)
{ if (p1 has pluralname) print "They";
else if (p1 has female) print "She";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "He";
else print "It";
} else {
if (p1 has pluralname) print "they";
else if (p1 has female) print "she";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "he";
else print "it";
}
QP_HIM: if (p1 has pluralname) print "them";
else if (p1 has female) print "her";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "him";
else print "it";
QP_HIS: if (f)
{ if (p1 has pluralname) print "Their";
else if (p1 has female) print "Her";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "His";
else print "Its";
} else {
if (p1 has pluralname) print "their";
else if (p1 has female) print "her";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "his";
else print "its";
}
QP_HERS: if (p1 has pluralname) print "theirs";
else if (p1 has female) print "hers";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "his";
else print "its";
QP_SELF: if (p1 has pluralname) print "themselves";
else if (p1 has female) print "herself";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "himself";
else print "itself";
QP_THAT: if (f)
{ if (p1 has pluralname) print "Those";
else if (p1 has female) print "She";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "He";
else print "That";
} else {
if (p1 has pluralname) print "those";
else if (p1 has female) print "she";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "he";
else print "that";
}
QP_THATACC:
if (p1 has pluralname) print "those";
else if (p1 has female) print "her";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "him";
else print "that";
QP_THATS: if (f)
{ if (p1 has pluralname) print "Those are";
else if (p1 has female) print "She's";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "He's";
else print "That's";
} else {
if (p1 has pluralname) print "those are";
else if (p1 has female) print "she's";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "he's";
else print "that's";
}
QP_THATSNOT: if (f)
{ if (p1 has pluralname) print "Those aren't";
else if (p1 has female) print "She's not";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "He's not";
else print "That's not";
} else {
if (p1 has pluralname) print "those aren't";
else if (p1 has female) print "she's not";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "he's not";
else print "that's not";
}
QP_HES: if (f)
{ if (p1 has pluralname) print "They're";
else if (p1 has female) print "She's";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "He's";
else print "It's";
} else {
if (p1 has pluralname) print "they're";
else if (p1 has female) print "she's";
else if (p1 has male || p1 has animate && p1 hasnt neuter)
print "he's";
else print "it's";
}
QP_IS: if (p1 has pluralname) print "are";
else print "is";
QP_HAS: if (p1 has pluralname) print "have";
else print "has";
QP_DOES: if (p1 has pluralname) print "do";
else print "does";
QP_S: if (p1 hasnt pluralname) print (char)'s';
QP_ES: if (p1 hasnt pluralname) print "es";
QP_INORON: if (p1 has supporter)
{ if (f) print "On"; else print "on"; }
else if (f) print "In"; else print "in";
QP_OFFOROUTOF: if (p1 has supporter) print "off";
else print "out of";
QP_INORONTHE: if (p1 has supporter)
{ if (f) print "On "; else print "on "; }
else if (f) print "In "; else print "in ";
print (the) p1;
QP_IFSTRING: if (p1) { if (p2) print (string) p2; }
else if (p3) print (string) p3;
QP_QUESTION:
QPoutnext1(p1);
QPoutnext(p1);
QP_EMPH: style underline;
if (QPoutnext()) style roman;
QP_BOLD: style bold;
if (QPoutnext()) style roman;
QP_ROMAN: style roman;
QPoutnext();
QP_THEIS:
if (f) print (The) p1; else print (the) p1;
if (p1 has pluralname) print (string) ARE__TX;
else print (string) IS__TX;
QP_HEIS:
if (p1 has pluralname)
{ if (f) print "They"; else print "they"; }
else if (p1 has female)
{ if (f) print "She"; else print "she"; }
else if (p1 has male || p1 has animate && p1 hasnt neuter)
{ if (f) print "He"; else print "he"; }
else if (f) print "It"; else print "it";
if (p1 has pluralname) print (string) ARE__TX;
else print (string) IS__TX;
QP_WAS:
if (p1 has pluralname) print "were";
else print "was";
QP_THEWAS:
if (f) print (The) p1; else print (the) p1;
if (p1 has pluralname) print " were";
else print " was";
QP_THATWAS:
if (p1 has pluralname)
{ if (f) print "Those were"; else print "those were"; }
else
{ if (p1 has female)
{ if (f) print "She"; else print "she"; }
else if (p1 has male || p1 has animate && p1 hasnt neuter)
{ if (f) print "He"; else print "he"; }
else if (f) print "That"; else print "that";
print " was";
}
QP_OFFTHE:
if (p1 has supporter)
{ if (f) print "Off "; else print "off "; }
else if (f) print "Out of "; else print "out of ";
print (the) p1;
QP_HEWAS:
if (p1 has pluralname)
{ if (f) print "They were"; else print "they were"; }
else
{ if (p1 has female)
{ if (f) print "She"; else print "she"; }
else if (p1 has male || p1 has animate && p1 hasnt neuter)
{ if (f) print "He"; else print "he"; }
else if (f) print "It"; else print "it";
print " was";
}
}
];
[ QPType pos tl l c fl;
pos = QPchar->QP_POS_INDEX; ! pos = cur position
if (QPchar->pos==QP_esc_ch) rfalse;
tl = 2 + QPchar-->0; ! tl = total length
l = pos; ! l starts at cur position
while (l<tl && QPchar->l~=' ' or QP_esc_ch) l++;
QPchar->QP_POS_INDEX = l;
l = l - pos; ! l == length of tag to read
if (l<1) rfalse;
pos = pos + QPchar; ! pos == array starting at position
c = pos->0;
if (c>='A' && c<='Z')
{
fl = QP_CAPS;
c = c+'a'-'A';
}
else fl = 0;
if (l==1) ! t (the), s (-s), f (function), a (indef art),
! ? (quick if construct)
{
switch (c)
{
'a': return fl|QP_A;
's': return fl|QP_S;
'f': return fl|QP_ROUTINE;
't': return fl|QP_THE;
'?': return QP_QUESTION;
}
rfalse;
}
if (l==2) ! an (indef art), ch(ar), do, es (-es),
! he (nominative pronoun), is, in / on, It (nom pronoun),
! it (acc pronoun), if (if construct)
{
switch (c)
{
'a': if (pos->1=='n') return fl|QP_A;
'c': if (pos->1=='h') return fl|QP_CHAR;
'd': if (pos->1=='o') return fl|QP_DOES;
'e': if (pos->1=='s') return fl|QP_ES;
'h': if (pos->1=='e') return fl|QP_HE;
'i': if (pos->1=='s') return fl|QP_IS;
if (pos->1=='n') return fl|QP_INORON;
if (pos->1=='t')
{
if (fl) return QP_CAPS|QP_HE;
return QP_HIM; ! note this
}
if (pos->1=='f') return fl|QP_IF;
'o': if (pos->1=='n') return fl|QP_INORON;
}
rfalse;
}
if (l==3)
! are, gen(itive), has, him/her (acc pronoun),
! his (gen pronoun), hes (he's, she's, it's, they're),
! if~ (ifnot), ifs (ifstring), off, obj, num(ber), str(ing),
! she, the, was, tis (the is), if_ (if,space)
{
switch (c)
{
'a': if (pos->1=='r' && pos->2=='e') return fl|QP_IS;
'g': if (pos->1=='e' && pos->2=='n') return fl|QP_GEN;
'h': if (pos->1=='a' && pos->2=='s') return fl|QP_HAS;
if (pos->1=='i')
{
if (pos->2=='m') return fl|QP_HIM;
if (pos->2=='s') return fl|QP_HIS;
}
if (pos->1=='e')
{
if (pos->2=='r') return fl|QP_HIM;
if (pos->2=='s') return fl|QP_HES;
}
'i': if (pos->1=='f')
{
if (pos->2==126 or 33) ! tilde or exclamation
return fl|QP_IFNOT;
if (pos->2=='s') return fl|QP_IFSTRING;
if (pos->2=='_') return fl|QP_IFSPACE;
}
'_': if (pos->1=='i' && pos->2=='f') return QP_SPACEIF;