Sorry for the delay in responding to this, but I have now gathered all the special code I wrote for gun handling into one spot. I hope it turns out to be useful. The goal is to handle the difficulties that English presents in understanding the different syntaxes used for shooting something. (e.g., >Shoot gun and >Shoot target). I believe this code deals successfully with inputs like:
shoot gun
Shoot gun at target
Shoot target with gun
Shoot at target with gun
Shoot at target
Shoot bullet at target (etc)
Fire gun (etc)
Load gun
For this scenario I have created a blowpipe, with this the equivalent of a gun, and a pellet, with is the equivalent of a bullet.
A few caveats: I am still quite a novice at TADS (which you can see from my inelegant coding style) so there are probably more efficient ways to do these things. Also, my game hasn’t been tested yet, so although this code seems to work for me, it hasn’t been given a good working-over, so proceed with caution!
Best of luck,
–Bob
/***********************
OBJECT HANDLING
***********************/
th_blowpipe: Container
{
name = 'blowpipe'
vocabWords = 'bamboo blow blowpipe blowpipe gun/pipe/tube'
location = rm_target
isListedInContents = (moved) //So that it won't be listed in the contents of the room until after you have moved it.
dobjFor(Examine) {
action() {
"It's a bamboo tube that is at least 8 feet long. ";
}
}
dobjFor(Shoot) { //The Player's input is >Shoot gun (Not >shoot foo, or >shoot gun at foo)
action () { //In other words the player has typed shoot gun, but not specified what he wants to shoot it at. Ask him.
askForIobj(ShootWeaponAt); //This sends us over to ShootWeaponAt from here on.
}
}
dobjFor(ShootWeaponAt) { //The Player's input is >Shoot gun at foo, or is piped here from >Shoot gun
action () {
if (!th_blowpipe.isIn(me)) {
"You'd have to be holding the blowpipe to fire it. ";
}
else if (!th_pellet.isIn(th_blowpipe)) {
"The blowpipe isn't loaded. ";
}
else if (gIobj == th_target) {
"You fire the pellet at the target and hit it. The pellet falls to the ground and disintegrates. ";
th_pellet.moveInto(nil);
}
else {
say ('The pellet strikes {the iobj/him} then falls to the ground and disintegrates. ');
th_pellet.moveInto(nil);
}
}
}
dobjFor(Blow) { //The Player's input is >Blow gun
action () { //In other words the player has typed >shoot gun, but not specified what he wants to shoot it at. Ask him.
askForIobj(ShootWeaponAt); //This sends us over to ShootWeaponAt from here on.
}
}
dobjFor(BlowAt) {
action () {
replaceAction (ShootWeaponAt, th_blowpipe, gIobj);
}
}
dobjFor(Load) {
action () {
if (th_pellet.isIn(getOutermostRoom)) {
replaceAction (PutIn, th_pellet, th_blowpipe);
}
else {
"You don't have anything to put in the blowpipe. ";
}
}
}
dobjFor(LoadWith) {
action() {
if (gIobj == th_pellet) {
replaceAction (Load, th_blowpipe);
}
else {
say ('{The iobj/him} {does}n\'t fit inside the blowpipe. ');
}
}
}
dobjFor (Break) {
verify () {}
action () {
"The blowpipe is made of stout bamboo. You can't break it. ";
}
}
iobjFor(ShootWith) {
action () {
replaceAction (ShootWeaponAt, th_blowpipe, gDobj);
}
}
iobjFor(PutIn) {
action {
if (gDobj == th_pellet) {
"You put the pellet into the blowpipe. ";
inherited;
}
else {
"That won't fit inside the blowpipe. ";
}
}
}
}
th_pellet: Thing
{
name = 'pellet'
vocabWords = 'small round clay pellet'
location = nil
dobjFor(Examine) {
action() {
"It's a small round pellet made of clay. ";
}
}
dobjFor(ShootWeaponAt) { //The Player's input is >Shoot pellet at foo
action () {
replaceAction (ShootWeaponAt, th_blowpipe, gIobj);
}
}
dobjFor(Blow) { //The Player's input is >Blow pellet
action () { //In other words the player has typed blow pellet, but not specified what he wants to shoot it at. Ask him.
askForIobj(ShootWeaponAt); //This sends us over to ShootWeaponAt from here on.
}
}
dobjFor(BlowAt) {
action () {
replaceAction (ShootWeaponAt, th_blowpipe, gIobj);
}
}
}
th_target: Fixture
{
name = 'target'
vocabWords = 'target'
location = rm_target
dobjFor(Examine) {
action() {
"It's like an archery target, with concentric rings and a bull's eye. ";
}
}
}
/***********************
VERB HANDLING
***********************/
/***********************
BLOW
***********************/
DefineTAction(Blow);
VerbRule(Blow)
('blow' | 'blow' 'in' | 'blow' 'into' | 'blow' 'at' ) singleDobj
: BlowAction
verbPhrase = 'blow/blowing (what)'
;
modify Thing
dobjFor(Blow) {
action () { //Note that blowing into the blowpipe is handled in the blowpipe itself
if (gDobj.ofKind(Person)) {
"Hey! Let's keep things civil. ";
}
else {
"That would be a waste of breath. ";
}
}
}
;
/***********************
BLOW-AT
***********************/
DefineTIAction(BlowAt);
VerbRule(BlowAt)
('blow') singleDobj ('at') singleIobj
: BlowAtAction
verbPhrase = 'blow/blowing (what) (at what)'
askIobjResponseProd = onSingleNoun
askDobjResponseProd = onSingleNoun
;
modify Thing
dobjFor(BlowAt) {
action () { //Note that blowing into the blowpipe is handled in the blowpipe itself
"Save your breath. You'll need it for the spectacular finale. ";
}
}
;
/***********************
LOAD
***********************/
DefineTAction(Load);
VerbRule(Load)
('load') singleDobj
: LoadAction
verbPhrase = 'load/loading (what)'
;
modify Thing
dobjFor(Load) {
action () {
replaceAction (Take, gDobj);
}
}
;
/***********************
LOADWITH (LOAD GUN WITH PELLET)
***********************/
DefineTIAction(LoadWith)
/* resolve the direct object first */
resolveFirst = DirectObject
/* limit 'all' for the indirect object to items in inventory */
getAllIobj(actor, scopeList)
{
return scopeList.subset({x: x.isIn(actor)});
}
;
VerbRule(LoadWith)
'load' singleDobj 'with' singleIobj
: LoadWithAction
verbPhrase = 'load/loading (what) (with what)'
omitIobjInDobjQuery = true //TODO: RAB, This and next two lines are stolen from "UnlockWith" and I don't know what they do
askDobjResponseProd = singleNoun
askIobjResponseProd = withSingleNoun
;
modify Thing
dobjFor(LoadWith)
{
preCond = [touchObj]
}
iobjFor(LoadWith)
{
preCond = [objHeld]
}
;
/***********************
SHOOT, SHOOT-WEAPON-AT, SHOOT-WITH
***********************/
DefineTAction(Shoot);
DefineTIAction(ShootWeaponAt);
DefineTIAction(ShootWith);
VerbRule(Shoot)
('shoot' | 'fire' | 'shoot' 'at' | 'fire' 'at' ) singleDobj
: ShootAction
verbPhrase = 'shoot/shooting (what)'
;
VerbRule(ShootWeaponAt)
('shoot' | 'fire') singleDobj ('at') singleIobj
: ShootWeaponAtAction
verbPhrase = 'shoot/shooting (what) (at what)'
askIobjResponseProd = onSingleNoun
askDobjResponseProd = onSingleNoun
;
VerbRule(ShootWith)
('shoot' | 'fire' |'shoot' 'at' | 'fire' 'at') singleDobj 'with' singleIobj
: ShootWithAction
verbPhrase = 'shoot/shooting (at what) (with what)'
omitIobjInDobjQuery = true
askDobjResponseProd = atSingleNoun
askIobjResponseProd = withSingleNoun
;
modify Thing
dobjFor(Shoot)
{
action() { //The player has typed >Shoot or >Shoot foo, where foo is something he wants to shoot at.
// If he had typed >Shoot gun, it would have been caught before this by the blowpipe handling.
if (th_pellet.isIn(th_blowpipe)) {
replaceAction (ShootWeaponAt, th_blowpipe, gDobj); // If the player is has loaded the blowpipe, >Shoot foo should fire at the foo
// This avoids the game asking him "What do you want to shoot the foo with, when
// it is obvious that he is holding a loaded weapon.
}
else {
askForIobj(ShootWith);
}
}
}
;
modify Thing
dobjFor(ShootWeaponAt)
{
action () {
if (gDobj == th_pellet) {
replaceAction (ShootWeaponAt, th_blowpipe, gIobj); // In case this gets here as the result of an orphan from "What do you want
// to shoot at foo with, and the player types "pellet."
}
else {
say ('You can\'t shoot anything with {a dobj/him}. ');
}
}
}
;
modify Thing
iobjFor(ShootWith)
{
action () {
if (gIobj == th_pellet) {
replaceAction (ShootWeaponAt, th_blowpipe, gDobj); // In case this gets here as the result of an orphan from "What do you want
// to shoot at foo with, and the player types "pellet."
}
else {
say ('You can\'t shoot anything with {a iobj/him}. ');
}
}
}
;