/*
*
* (c) by Robin Johnson - robindouglasjohnson@gmail.com - @rdouglasjohnson
* Copy and distribute freely in unmodified form, preserving this licence.
* No commercial use without permission of the author.
*
*/
Game = {
id: "PIR",
title: "Pirateship",
author: "Robin Johnson",
hero_location: 'cabin',
score: 0,
max_score: 25,
score_percentage: false,
game_over: false,
turn_number: 0,
intro: "Captain Iago \"Sharksclaw\" Montpelier is the most deadly pirate the world has ever known. \
He's stolen millions of doubloons, embarrassed countless governors, and generally hornswoggled \
his way around the tropics leaving a trail of burnt wrecks and dead merchants wherever he \
goes. The mention of his name can terrify the hardiest sailor. Hopefully you won't meet \
him round here.",
inventory: [],
held: "",
rooms: {},
things: {},
vars: {
},
fuses: {
},
options: {},
before: [],
always: [],
initialise: function() {
},
// startingMusic: 'saxloopmusic',
};
On_hold = [];
Rules = [];
Longdesc = {};
// Longroomdesc = {};
// currentMusic = Game.startingMusic;
male_pronouns = ["he", "him", "his", "his", "himself"];
female_pronouns = ["she", "her", "her", "hers", "herself"];
neuter_pronouns = ["it", "it", "its", "its", "itself" ];
plural_pronouns = ["they", "them", "their", "theirs", "themselves"];
nb_pronouns = ["they", "them", "their", "theirs", "themself"];
Game.always.push(
function() {
Game.turn_number++;
// do_room_music();
}
);
/**************** the Poseidon's Hope ***********/
Game.rooms.cabin = {
description: "You're in a cabin on a pirate ship.",
directions: {
starboard: 'midships',
},
is_poseidons_hope: true,
};
Game.things.hammock = {
location: "cabin",
};
Longdesc.hammock = "A length of blue-grey canvas fixed to the bulkheads at either end.";
add_rule('after', 'examine', 'hammock', function() {
if(!location_of('catbeard') && has_status('catbeard', 'in hammock')) {
say("You discover Catbeard, the ship's cat, " +
(has_status('catbeard', 'asleep') ? "asleep ": '') +
"in the hammock.");
bring('catbeard');
get_point_for('found_catbeard');
}
});
Game.things.catbeard = {
description: "Catbeard",
status: ["asleep", "in hammock"],
proper_name: true,
is_alive: true,
pronouns: male_pronouns,
};
CATBEARD_DESC = "Catbeard carries the official rank of First Mate in Charge of Mousing aboard the \
Poseidon's Hope. He is a ginger moggy of about twelve years, with a matted mane and enough teeth left to look menacing and daft at the same time.",
CATBEARD_SLEEPY_DESC = "Catbeard carries the official rank of First Mate in Charge of Mousing aboard the \
Poseidon's Hope. He currently resembles a sleepy ginger puddle."
add_rule('before', 'examine', 'catbeard', function() {
Longdesc.catbeard = has_status('catbeard', 'asleep') ? CATBEARD_SLEEPY_DESC : CATBEARD_DESC;
});
Game.always.push(function() {
do_catbeard();
});
function do_catbeard() {
if(Game.things.catbeard.direct_control) {
return;
}
if(!location_of('catbeard')) {
return;
}
if(has_status('catbeard', 'asleep')) {
if(!pick(8)) {
remove_status('catbeard', 'asleep');
say_where('catbeard', 'Catbeard wakes up' + pickOne(["","",""," with a yawn"," with a stretch"]) + (remove_status('catbeard', 'in hammock') ? " and jumps down out of the hammock.":"") + '.');
return;
}
if(!pick(4) && in_scope('catbeard')) {
say(pickOne([
"Catbeard snores.",
"Catbeard twitches his " + pickOne(["paws", "tail", "whiskers"]) + " in his sleep."
]));
}
return;
}
// Catbeard isn't asleep...
if(!pick(8)) {
add_status('catbeard', 'asleep');
if(location_of('catbeard')==location_of('hammock')) {
add_status('catbeard', 'in hammock');
say_where('catbeard', "Catbeard jumps into the hammock, curls up, and falls asleep.");
} else {
say_where('catbeard', "Catbeard curls up and falls asleep.");
}
return;
}
// ...and hasn't fallen asleep this turn.
if(in_scope('catbeard') && !pick(3)) {
say(pickOne([
"Catbeard chases his tail.",
"Catbeard stares at you.",
"Catbeard blinks at you.",
"Catbeard purrs.",
"Catbeard meows.",
"Catbeard yowls.",
"Catbeard pounces on an imaginary mouse.",
"Catbeard chirrups.",
"Catbeard snuggles against your leg.",
]));
}
if(!pick(4)) {
wander('catbeard', pickOne(['walks', 'trots', 'runs', 'zooms', 'pounces']), pickOne(['walks in', 'trots in', 'runs in', 'zooms in', 'pounces in']) + ' from');
}
};
function wander(npc, verb_goes, verb_arrives, check_location) {
var fromRoom = location_of(npc);
//console.log('wandering ' + npc + ' currently at ' + fromRoom);
var pre_checked_reachables = get_reachable_rooms(fromRoom);
var reachables = [];
//console.log('reachables is: ' + pre_checked_reachables.join(','));
if(check_location) {
for(var i in pre_checked_reachables) {
var room = pre_checked_reachables[i];
if(check_location(room)) {
reachables.push(room);
}
}
} else {
reachables = pre_checked_reachables;
}
if(reachables.length==0) {
return false;
}
if(!verb_goes) {
verb_goes = 'walks';
}
if(!verb_arrives) {
verb_arrives = 'arrives from';
}
var toRoom = pickOne(reachables);
//console.log('wandering to ' + toRoom);
// find how it got there
var dirMoved = '';
var thingEntered = '';
var thingClimbed = '';
var thingCrossed = '';
for(var dir in Game.rooms[fromRoom].directions) {
if(Game.rooms[fromRoom].directions[dir] == toRoom) {
dirMoved = dir;
break;
}
}
if(dirMoved) {
say_where(npc, capitalise(the_thing(npc)) + ' ' + verb_goes + ' ' + dirwards(dirMoved) + '.');
put(npc, toRoom);
say_where(npc, capitalise(the_thing(npc)) + ' ' + verb_arrives + ' ' + the_opposite_dir(dirMoved) + '.');
return true;
}
// no direction found - the movement must have been through climb or enter.
for(var thing in Game.things) {
if(Game.things[thing].location==fromRoom) {
if(has_active_verb(thing, 'enter') && Game.things[thing].enter_to==toRoom) {
thingEntered = thing;
break;
} else if(has_active_verb(thing, 'climb') && Game.things[thing].climb_to==toRoom) {
thingClimbed = thing;
break;
} else if(has_active_verb(thing, 'cross') && Game.things[thing].cross_to==toRoom) {
thingCrossed = thing;
}
}
if(thingEntered || thingClimbed || thingCrossed) {
break;
}
}
if(thingEntered) {
say_where(npc, capitalise(the_thing(npc)) + ' enters ' + the_thing(thingEntered) + '.');
put(npc, toRoom);
say_where(npc, capitalise(the_thing(npc)) + ' arrives.');
// todo: if fromRoom is a direction from toRoom, use the opposite of THAT direction
// (e.g. CLIMB LADDER might move you to the crowsnest, but DOWN takes you back,
// so viewed from the crowsnest, you'd want to see "The captain arrives from below."
return true;
} else if(thingClimbed) {
say_where(npc, capitalise(the_thing(npc)) + ' climbs ' + the_thing(thingClimbed) + '.');
put(npc, toRoom);
say_where(npc, capitalise(the_thing(npc)) + ' arrives.');
} else if(thingCrossed) {
say_where(npc, capitalise(the_thing(npc)) + ' crosses ' + the_thing(thingCrossed) + '.');
put(npc, toRoom);
say_where(npc, capitalise(the_thing(npc)) + ' arrives.');
} else {
console.log('wandering ' + npc + ': - couldn\'t find step from ' + fromRoom + ' to ' + toRoom + '???');
return false;
}
}
Game.rooms.midships = {
description: "You're in a passageway amidships.",
directions: {
fore: 'gun_deck',
aft: 'sick_bay',
port: 'cabin',
},
before: {
depart: function(dir) {
return check_midships(dir);
}
},
is_poseidons_hope: true,
};
function check_midships(dir) {
if(dir!='aft') {
return false;
}
say("To aft is sick bay, and the doctor is busy right now.");
return true;
}
Game.things.midships_ladder = {
name: "ladder",
description: "ladder leading up",
location: "midships",
active_verbs: ["climb"],
climb_to: "mid_deck",
}
Longdesc.midships_ladder = "A sturdy wooden ladder, leading up through a hatchway to the open deck.";
Game.rooms.sick_bay = {
description: "You're in sick bay.",
directions: {
fore: 'midships',
},
is_poseidons_hope: true,
};
Game.things.dr_deadsey = {
name: "Doctor Deadsey",
description: "Doctor Deadsey",
image: 'res/img/dr-deadsey.png',
is_alive: true,
pronouns: male_pronouns,
location: "sick_bay",
active_verbs: ["talk"],
conversifier: function() {
return conv_deadsey();
}
};
add_rule('before', 'talk', 'dr_deadsey', function() {
if(Game.talking_to != 'dr_deadsey') {
say('"I\'m busy," snaps Doctor Deadsey.');
return true;
}
return false;
});
Longdesc.dr_deadsey = "Doctor Deadsey is the Hope's surgeon, a big-bellied man with an unkempt mop of \
black hair and a matching beard.";
function conv_deadsey() {
var conv = {};
conv.start_conversation = '"Now, tell me what hurts," says Doctor Deadsey seriously.';
conv.says = {
head: function() { deadsey_reject('head'); },
eyes: function() {
if(!Game.things.dr_deadsey.given_eyepatch) {
say('"Hmmm. It might be catARRRRRRacts," says the doctor. He rummages in his \
medical drawers, pulls out an eye patch, and hands it to you. "Here. When one of \
\'em falls out, wear this."');
give_hero('eyepatch');
get_point_for('got_eyepatch');
Game.things.dr_deadsey.given_eyepatch = true;
} else {
say('"Well, ain\'t you been wearin\' that eyepatch I gave you? You gotta look \
after yourself, matey, or it\'ll only get worse."');
}
say('Doctor Deadsey shoves you out of sick bay and closes the door.');
hide_conversation();
put_hero('midships');
},
mouth: function() { deadsey_reject('mouth'); },
arms: function() { deadsey_reject('arm', 'arms'); },
chest: function() { deadsey_reject('chest'); },
stomach: function() { deadsey_reject('stomach'); },
hands: function() {
if(!Game.things.dr_deadsey.given_hook) {
say('"Might be a case of deck hands," says Deadsey. He rummages in his medical \
drawers, pulls out an iron hook, and gives it to you. "Here. When one of \'em falls off, \
wear this."');
give_hero('hook');
get_point_for('got_hook');
Game.things.dr_deadsey.given_hook = true;
} else {
say('"Well, ain\'t you been wearin\' that hook I gave you? You gotta look after \
yourself, matey, or it\'ll only get worse."');
}
say('Doctor Deadsey shoves you out of sick bay and closes the door.');
hide_conversation();
put_hero('midships');
},
legs: function() {
if(!Game.things.dr_deadsey.given_pegleg) {
say('"Looks like a mutey knee," says Deadsey. He rummages in his medical \
cabinet, pulls out a peg leg, and gives it to you. "Here. When one of \'em falls off, \
wear this."');
give_hero('pegleg');
get_point_for('got_pegleg');
Game.things.dr_deadsey.given_pegleg = true;
} else {
say('"Well, ain\'t you been wearin\' that pegleg I gave you? You gotta look after \
yourself, matey, or it\'ll only get worse."');
}
say('Doctor Deadsey shoves you out of sick bay and closes the door.');
hide_conversation();
put_hero('midships');
},
feet: function() { deadsey_reject('foot', 'feet') },
nothing: function() {
say('"Well then, we\'re not much use to each other, are we?"');
say('Doctor Deadsey shoves you out of sick bay and closes the door.');
hide_conversation();
put_hero('midships');
}
};
return conv;
};
function deadsey_reject(bodyPart, bodyParts) {
if(!bodyParts) {
bodyParts = bodyPart;
}
say('"Your ' + bodyParts + '?" he says, offended. "Well, that\'s no concern o\' mine! ' +
capitalise(pirate_oath(true)) + '! Whoever heard of a ' + bodyPart + ' patch, or a wooden ' +
bodyPart + '? Stop wastin\' my time."');
say("Deadsey shoves you out of sick bay and slams the door.");
put_hero('midships');
hide_conversation();
}
Game.things.eyepatch = {
name: "eyepatch",
description: "eye patch",
portable: true,
wearable: true,
suppress_wear_message: true,
}
Longdesc.eyepatch = "A patch of black leather, just big enough to cover one eye, attached to \
an elasticated headband.";
Game.always.push(function() {
do_eyepatch();
});
function do_eyepatch() {
if(worn('eyepatch') && !Game.vars.hallucinating && !pick(3)) {
say("It's quite hard to focus on things with this eye patch on.");
}
}
add_rule('before', 'wear', 'eyepatch', function() {
say('You put on the eyepatch. Everything looks a little less three-dimensional without your depth \
perception.');
return false;
});
add_rule('after', 'remove', 'eyepatch', function() {
say('Everything looks a bit more three-dimensional now.');
return true;
});
Game.things.hook = {
description: "hook hand",
portable: true,
wearable: true,
suppress_wear_message: true,
};
Longdesc.hook = "A blunt iron hook attached to a short wooden pot, which can be strapped on over the \
stump of an amputated hand (or over a healthy hand, for that matter.)";
add_rule('before', 'wear', 'hook', function() {
say('You slip the hook on over your right hand, and manage to do up the straps.');
return false;
});
Game.things.pegleg = {
name: "pegleg",
description: "peg leg",
portable: true,
wearable: true,
suppress_wear_message: true,
};
Longdesc.pegleg = "A solid pillar of walnut wood, exactly the length of a human leg from the knee down. \
Its straps allow it to be connected to an amputated leg, or as a stylish accessory to an uninjured leg \
if you bend your knee behind your back.";
add_rule('before', 'wear', 'pegleg', function() {
say('You bend your left leg behind your back and strap the peg leg to your knee.');
return false;
});
add_rule('after', 'wear', 'pegleg', function() {
set_fuse('pegleg', 6);
});
Game.fuses.pegleg = {
burn: function() {
if(worn('pegleg')) {
var t = Game.fuses.pegleg.time;
if(t==4) {
say("Your leg is feeling rather stiff from being bent behind you.");
} else if(t==2) {
say("The peg leg is making your real leg very sore.");
}
}
},
explode: function() {
if(worn('pegleg')) {
say('Your left leg mutinies and straightens itself, and the peg leg falls off.');
bring('pegleg');
}
}
};
Game.rooms.gun_deck = {
description: "You're in the gun deck.",
directions: {
aft: "midships",
},
is_poseidons_hope: true,
};
Game.things.cannon = {
description: "18-pounder cannon",
location: "gun_deck",
active_verbs: ["fire"],
};
add_rule('before','fire','cannon', function() {
say("BANG! A cannonball flies out of the porthole and sploshes into the sea. That was fun!");
get_point_for('fired_cannon');
return true;
});
/*
Game.things.jordan_feet = {
name: "Jordan Feet",
description: "Jordan Feet",
location: "gun_deck",
is_alive: true,
image: 'res/img/jordan-feet.png',
pronouns: male_pronouns,
proper_name: true,
active_verbs: ["talk"],
conversifier: function() {
return conv_jordan();
},
always: function() {
do_jordan();
}
};
Longdesc.jordan_feet = "Jordan Feet is the Hope's quartermaster, in charge of weapons and \
supplies. A large, stubbly man with a cotton headkerchief and a gold earring, he's been a pirate \
since liberating himself from a construction firm in Florida, and he's got the muscles -- and the \
disaffection -- to show for it.";
function conv_jordan() {
var conv = {
start_conversation: 'Jordan looks at you. "Want something?"',
end_conversation: 'Jordan goes back to inspecting the gun-deck.',
};
conv.asks = {
cannon: '"You leave that alone. It\'s dangerous. That\'s the point."'
};
return conv;
}; */
function do_jordan() {
if(!pick(3) && !talking_to('jordan_feet')) {
sayOne([
"Jordan polishes the cannon with a rag.",
"Jordan dusts the portholes.",
"Jordan inspects the cannon's wheels.",
]);
}
}
Game.rooms.mid_deck = {
description: "You're on the deck of the Poseidon's Hope.",
directions: {
fore: 'bow',
aft: 'stern'
},
is_poseidons_hope: true,
};
Game.things.deck_hatch = {
name: "hatchway",
description: "hatchway leading down",
location: "mid_deck",
active_verbs: ["enter"],
enter_to: "midships"
};
Longdesc.deck_hatch = "A square hatchway leading down into the depths of the ship.",
Game.things.capn = {
name: "cap'n",
description: "Cap'n",
proper_name: true,
is_alive: true,
pronouns: female_pronouns,
location: 'mid_deck',
active_verbs: ["talk"],
image: 'res/img/capn.png',
conversifier: function() {
return conv_capn();
}
};
Game.always.push(function() {
do_capn();
});
Longdesc.capn = "The Cap'n of the Poseidon's Hope is a formidable looking seafarer with \ waist-length, greying hair, intense eyes, and a grin that could mean anything. She wears a \
wide-lapelled, dark green greatcoat over a white vest and billowing silk trousers, and the most \
expensive boots on the ship. You can count at least five swords.";
function do_capn() {
if(in_scope('capn') && !talking_to('capn')) {
say('Cap\'n yells, "' + capitalise(pirate_oath()) + '!"');
}
};
function conv_capn() {
var conv = {};
conv.start_conversation = function() {
if(!Game.things.capn.given_mission) {
say('"'+capitalise(arrr())+', you there, ' + pickOne(PIRATE_INSULTS) + '!" says Cap\'n, \
looking you up and down. "I\'m afraid your performance on this voyage has been well \
below tarrrrrget. If you\'re gonna make it past your next evaluation you need to up your \
pirate game. ' + capitalise(pirate_oath()) + '! So, I\'m givin\' you this chance. \
Somewhere on this here island there\'s a treasure, ' + pirate_oath(true) + '. \
Bring it to me an\' your job\'s safe. Jim Lad -- deploy gangplank!"');
Game.things.capn.given_mission = true;
get_point_for('talked_to_capn');
if(in_scope('jim_lad')) {
say('Jim Lad deploys the gangplank.');
} else {
bring('jim_lad');
say('Jim Lad, the cabin boy, arrives and deploys the gangplank.');
}
deploy_gangplank();
} else {
say("Cap'n scowls.");
}
};
conv.asks = {
island: '"It\'s a Class 3 treasure island," says Cap\'n. "Cliffs, swamps, forests, \
secrets. Good for workin\' on your professional skills."',
treasure: '"It\'s out there somewhere. Ye\'ll know it when ye see it. Bring it back an\' \
give it to me when you find it."',
}
conv.tells = {};
if(Game.things.treasure_fleet.seen) {
if(!Game.things.treasure_fleet.miniaturised) {
conv.tells["Spanish treasure fleet"] = '"The Spanish treasure fleet? Ye don\'t say?" \
Cap\'n looks frustrated, then resigned. "There\'s no way we can outgun her. Some days \
piratin\' is about knowing when not to charge in with flintlocks blazin\', \
temptin\' as it is."';
} else {
conv.tells["Spanish treasure fleet"] = function() {
say('Cap\'n listens incredulously. "Oh yeah? Bring me this microscopic Spain fleet \
then, or else quit makin\' up stories."');
};
}
}
conv.end_conversation = 'Cap\'n says, "' + capitalise(pirate_oath(true)) + ', ' +
pickOne(PIRATE_INSULTS) + '."';
return conv;
}
function pirate_oath(dont_repeat) {
var oath = pickOne(['splice', 'furl', 'avast', 'load', 'flog', 'hard', 'shiver', 'ahoy',
'all hands on', 'batten', 'blow', 'horn', 'pieces', 'light', 'tie', 'scuttle', 'abandon',
'walk', 'yo ho', arrr()+',', 'ahoy', 'heave-ho', 'yo ho ho and', 'steady',
'hang', 'blister', 'haul', 'land', 'load', 'fire', 'blast', 'jolly', 'scrub', 'fifteen men on',
'lash', 'whip', 'man', 'board', 'bail', 'sound', 'bottle', 'all', 'row', 'full speed',
'strike'
]);
if(!pick(8)) {
oath += pickOne([' down', ' up', ' out']);
}
if(!pick(3) ) {
oath += pickOne([' the ', ' me ', '-a-', ' \'em ', ' a-', ' to ', ' her ', ' to the ',
' the old ', ' of ', ' o\' ', ' o\' nine ',
]);
} else {
oath += ' ';
}
oath += pickOne(['mainbrace', 'mainsail', 'topsail', 'mizzen', 'sails', 'timbers', 'Roger',
'swoggle', 'ahoy', 'binnacle', 'jack', 'booty', 'pegleg', 'barnacles',
'cutlasses', 'cannon', 'plank', 'jig', 'boots', 'starboard', 'larboard', 'port', 'bowsprit',
'rudder', 'keel', 'halter', 'mast', 'round', 'rum', 'salt', 'rigging', 'sharks', 'quarter',
'eight', 'doubloons', 'grog', 'shanties', 'deck', 'overboard', 'forward', 'cat', 'powder',
'galleon', 'leeward', 'windward', 'scurvy', 'dogs', 'scallywags', 'left', 'right',
'cabins', 'hammocks', 'oars', 'bilge', 'boats', 'bulkheads', 'hatches', 'portholes',
'ahead', 'sloop', 'barque', 'pistols', 'wheel', 'helm', 'crew'
]);
if(!dont_repeat && !pick(8)) {
oath += ' and ' + pirate_oath(true);
}
return oath;
};
PIRATE_INSULTS = ['lubber', 'scunner', 'scalawag', 'bilgerat', 'bucko', 'knave', 'matey',
'scoundrel', 'rapscallion', 'swab', 'salt'];
function deploy_gangplank() {
put('gangplank', 'mid_deck');
put('gangplank_2', 'west_dock');
}
Game.things.gangplank = {
description: "gangplank",
active_verbs: ["cross"],
cross_to: "west_dock",
};
Game.things.gangplank_2 = {
name: "gangplank",
description: "gangplank",
active_verbs: ["cross"],
cross_to: "mid_deck"
};
Longdesc.gangplank = 'A plank about two feet wide, for entering and exiting the ship.'
Longdesc.gangplank_2 = Longdesc.gangplank;
Game.things.main_mast = {
location: "mid_deck",
active_verbs: ["climb"],
indefinite: "the main mast",
climb_to: 'main_mast',
};
Game.rooms.main_mast = {
description: "You're halfway up the main mast.",
directions: {
up: "crows_nest",
down: "mid_deck",
},
is_poseidons_hope: true,
};
Game.things.mainsails = {
plural: true,
indefinite: "the mainsails",
status: ["furled"],
location: "main_mast",
};
MAINSAILS_DESC = "Large squares of black canvas, billowing in the wind to provide the ship's main oomph.",
MAINSAILS_FURLED_DESC = "As the Poseidon's Hope is at anchor, the mainsails are currently furled up into neat rolls.",
add_rule('before', 'examine', 'mainsails', function() {
Longdesc.mainsails = Game.things.mainsails.furled ? MAINSAILS_FURLED_DESC : MAINSAILS_DESC;
});
Longdesc.main_mast = "A great mast made from three white pine trunks on top of each other, holding the ship's mainsails. At the very top is the crow's nest.";
Game.rooms.crows_nest = {
description: "You're in the crow's nest atop the main mast.",
directions: {
down: "main_mast"
},
is_poseidons_hope: true,
};
Game.things.pirate_flag = {
name: "pirate flag",
description: "pirate flag",
// portable: true,
location: 'crows_nest',
};
Longdesc.pirate_flag = "A black flag with a white skull and crossbones on it. Pirates are traditionalists.",
Game.rooms.bow = {
description: "You're on the bow of the Poseidon's Hope.",
directions: {
aft: "mid_deck"
},
is_poseidons_hope: true,
};
Game.things.wheel = {
name: "ship's wheel",
indefinite: "the ship's wheel",
location: "bow",
};
Longdesc.wheel = "A big wooden steering wheel with sticky-out spokes in the classic design.",
Game.things.foremast = {
indefinite: "the foremast",
location: "bow",
active_verbs: ["climb"],
climb_to: "foremast",
};
Longdesc.foremast = "Shorter than the main mast, with smaller sails used for manoeuvring.";
Game.rooms.foremast = {
description: "You're at the top of the foremast.",
directions: {
down: "bow",
},
is_poseidons_hope: true,
};
Game.things.foresails = {
is_plural: true,
indefinite: "the foresails",
location: "foremast",
},
Longdesc.foresails = 'A small set of white sails, used for manoeuvring.'
Game.rooms.stern = {
description: "You're on the stern of the Poseidon's Hope.",
directions: {
fore: 'mid_deck',
},
is_poseidons_hope: true,
};
Game.things.mizzenmast = {
name: "mizzen-mast",
indefinite: "the mizzen-mast",
location: "stern",
active_verbs: ["climb"],
climb_to: "mizzentop",
};
Longdesc.mizzenmast = "The shortest of the ship's three masts, which holds the mizzen-sail.";
Game.rooms.mizzentop = {
description: "You're on the mizzen-top.",
directions: {
down: "stern"
},
is_poseidons_hope: true,
};
Game.things.mizzensail = {
name: "mizzen-sail",
indefinite: "the mizzen sail",
location: "mizzentop"
};
Longdesc.mizzensail = "A triangular sail that helps the ship balance.",
Game.things.jim_lad = {
name: "Jim Lad",
description: "Jim Lad",
proper_name: true,
location: 'cabin',
is_alive: true,
pronouns: male_pronouns,
active_verbs: ["talk"],
always: function() {
do_jimlad();
},
};
Longdesc.jim_lad = "As the ship's cabin boy, Jim Lad's duties include anything that anyone who outranks \
him says they do. And as he\'s the lowest-ranking crew member, and pirates tend to enjoy bossing people \
about, that\'s rather a lot of duties. This probably makes him the only person on board who knows how \
the whole ship works. He's an eager teenager with a neat ponytail and crisp linen clothes, \
and probably not actually called Jim.";
add_rule('before', 'talk', 'jim_lad', function() {
if(!Game.things.capn.given_mission && !Game.vars.jimlad_told_you) {
say('Jim Lad tells you, "Cap\'n wants to talk to you!"');
Game.vars.jimlad_told_you = true;
} else {
say('Jim Lad is too busy to talk.');
}
return true;
});
function do_jimlad() {
if(!Game.things.capn.given_mission && !Game.vars.jimlad_told_you) {
say('Jim Lad tells you, "Cap\'n wants to talk to you!"');
Game.vars.jimlad_told_you = true;
} else {
say_where('jim_lad', pickOne([
'"Make way!" cries Jim Lad.',
'"Can\'t stop!" cries Jim Lad.',
'"Gangway!" cries Jim Lad.',
]));
}
wander('jim_lad', 'runs', 'runs in from', function(room) {
//console.log('checking whether ' + room + ' is Poseidon\'s Hope');
return !!Game.rooms[room].is_poseidons_hope;
});
}
Game.things.pirate_crew = {
name: "pirates",
description: "pirates",
is_alive: true,
pronouns: plural_pronouns,
is_plural: true,
location: "midships",
always: function() {
do_pirates();
}
};
Game.things.pirate_crew2 = {
name: "pirates",
description: "pirates",
is_alive: true,
pronouns: plural_pronouns,
is_plural: true,
location: "gun_deck",
always: function() {
do_pirates();
}
};
Game.things.pirate_crew3 = {
name: "pirates",
description: "pirates",
is_alive: true,
pronouns: plural_pronouns,
is_plural: true,
location: "bow",
always: function() {
do_pirates();
}
};
Game.things.pirate_crew4 = {
name: "pirates",
description: "pirates",
is_alive: true,
pronouns: plural_pronouns,
is_plural: true,
location: "mid_deck",
always: function() {
do_pirates();
}
};
Game.things.pirate_crew5 = {
name: "pirates",
description: "pirates",
is_alive: true,
pronouns: plural_pronouns,
is_plural: true,
location: "stern",
always: function() {
do_pirates();
}
};
add_rule('before', 'examine', 'pirate_crew', function() {
describe_pirates();
});
add_rule('before', 'talk', 'pirate_crew', function() {
say("None of them stop to talk to you.");
return true;
});
add_rule('before', 'examine', 'pirate_crew2', function() {
describe_pirates();
});
add_rule('before', 'talk', 'pirate_crew2', function() {
say("None of them stop to talk to you.");
return true;
});
add_rule('before', 'examine', 'pirate_crew3', function() {
describe_pirates();
});
add_rule('before', 'talk', 'pirate_crew3', function() {
say("None of them stop to talk to you.");
return true;
});
add_rule('before', 'examine', 'pirate_crew4', function() {
describe_pirates();
});
add_rule('before', 'talk', 'pirate_crew4', function() {
say("None of them stop to talk to you.");
return true;
});
add_rule('before', 'examine', 'pirate_crew5', function() {
describe_pirates();
});
add_rule('before', 'talk', 'pirate_crew5', function() {
say("None of them stop to talk to you.");
return true;
});
function describe_pirates() {
if(!Game.vars.done_limbs_gag) {
Longdesc.pirate_crew = 'The ship is crowded with men and women of all sizes, shapes and colours, dressed \
in everything from rags to velvet finery, with \
little in common except ambition, courage and a habit of saying silly nautical oaths. There \
are notably less than four limbs present per person. Pirating is a dangerous \
profession. They swagger around the ship with determination, not stopping to talk.';
Game.vars.done_limbs_gag = true;
} else {
Longdesc.pirate_crew = 'A collection of men and women of all sizes, shapes and colours, dressed \
in everything from rags to velvet finery, with \
little in common except ambition, courage and a habit of saying silly nautical oaths. They \
swagger around the ship with determination, not stopping to talk.';
}
Longdesc.pirate_crew2 = Longdesc.pirate_crew;
Longdesc.pirate_crew3 = Longdesc.pirate_crew;
Longdesc.pirate_crew4 = Longdesc.pirate_crew;
Longdesc.pirate_crew5 = Longdesc.pirate_crew;
}
function do_pirates() {
var valid_entrances = [];
var loc = Game.hero_location;
if(loc=='midships') {
valid_entrances = ['fore', 'up'];
} else if(loc=='gun_deck') {
valid_entrances = ['aft'];
} else if(loc=='mid_deck') {
valid_entrances = ['fore', 'aft', 'down'];
} else if(loc=='bow') {
valid_entrances = ['aft'];
} else if(loc=='stern') {
valid_entrances = ['fore'];
}
//console.log('valid entrances: ' + valid_entrances);
var fromDir = the_dir(pickOne(valid_entrances));
var toDir = dirwards(pickOne(valid_entrances));
say(get_pirate(true) + pickOne([
" takes a swig from a bottle of rum.",
" swigs from a bottle of rum, then passes it to " + get_pirate(false) + ".",
" plays a tune on an accordion.",
' puffs on a pipe.',
" says, \"Yarrrr!\"",
' shouts, "' + capitalise(pirate_oath(true)) + '!"',
' shouts at ' + get_pirate(false) + '.',
' picks a fight with ' + get_pirate(false) + '.',
' has a fist-fight with ' + get_pirate(false) + '.',
' has an argument with ' + get_pirate(false) + '.',
' has a cutlass fight with ' + get_pirate(false) + '.',
' punches ' + get_pirate(false) + '.',
' embraces ' + get_pirate(false) + '.',
' argues loudly with ' + get_pirate(false) + '.',
' sings a sea-shanty.',
' sits down and starts singing about gold.',
' runs past you.',
' walks past you.',
' jostles against you.',
' pushes you out the way.',
' swears at you.',
' hobbles past you.',
' enters from ' + fromDir + '.',
' walks ' + toDir + '.',
' walks in from ' + fromDir + '.',
' runs in from ' + fromDir + '.',
' runs ' + toDir + '.',
' swaggers in from ' + fromDir + '.',
' swaggers ' + toDir + '.',
' limps ' + toDir + '.',
' limps in from ' + fromDir + '.'
]));
}
function get_pirate(capsP) {
var txt = capsP ? "A" : "a";
if(!pick(3)) {
txt += pickOne([
' young',
'n old',
'n ancient',
' burly',
' skinny',
' tall',
' short',
' big',
' muscular'
])
}
txt += pickOne([' pirate', ' crewman', ' crewwoman', ' sailor',
' carpenter', ' buccaneer', ' marauder', ' gunner']);
if(!pick(2)) {
txt += pickOne([
' in a striped jersey',
' with a wooden leg',
' with a hook for a hand',
' with an eye patch',
' in a long coat',
' in a tricorn hat',
' in a torn waistcoat',
' in a hat with a skull-and-crossbones on it'
]);
}
return txt;
}
/*************** the island ***********/
Game.rooms.sandy_beach = {
is_coastal: true,
coast_dir: 'northwest',
description: "You're on a sandy beach.",
directions: {
northeast: 'lagoon',
east: 'dry_grass',
south: 'west_dock',
}
};
Game.rooms.dry_grass = {
description: "You're on an area of dry grass north of a palm forest.",
directions: {
north: 'lagoon',
east: 'outside_barracks',
south: 'forest_north',
west: 'sandy_beach',
}
};
Game.rooms.lagoon = {
is_coastal: true,
coast_dir: 'northwest',
description: "You're by a palm-fringed lagoon.",
directions: {
southeast: 'outside_barracks',
south: 'dry_grass',
southwest: 'sandy_beach'
}
};
Game.things.stockade_from_west = {
name: "stockade",
description: "stockade",
status: ["to east"],
location: "lagoon",
};
STOCKADEDESC = 'A wooden fence, made from stripped tree trunks jammed very close together. It\'s \
too high to climb and too strong to beat down.';
Longdesc.stockade_from_west = STOCKADEDESC;
Game.things.sea_urchin = {
name: "sea urchin",
description: "sea urchin shell",
portable: true,
location: 'lagoon',
};
add_rule('before', 'examine', 'sea_urchin', function() {
Longdesc.sea_urchin = "A stylish and spacious hemispherical shell with elegant curves, \
opalescent rainbow colours and gently textured ridges. " +
(Game.things.sea_urchin.contains_crab ? "Whatever lives in this must be" :
"Whatever used to live in this must have been") +
" the envy of the sea-bed.";
});
Game.rooms.west_dock = {
description: "You're on a ramshackle wooden jetty in a natural harbour, where the \
Poseidon's Hope is moored.",
directions: {
north: "sandy_beach",
east: "forest_north",
south: "rocky_shore",
},
is_coastal: true,
coast_dir: 'west',
};
Game.things.poseidons_hope = {
dont_list_in_scroller: true,
description: "Poseidon's Hope",
indefinite: "the Poseidon's Hope",
pronouns: female_pronouns,
location: "west_dock",
};
add_rule('before', 'examine', 'poseidons_hope', function() {
if(location_of('pirate_flag')=='crows_nest') {
Longdesc.poseidons_hope = "The Poseidon's Hope is a three-mast, 150-foot galleon, in \
decent nick considering she's survived dozens of battles and is barred from most of the service \
shipyards this side of Nassau. She sways slowly on the water, making gentle but powerful \
creaks like the snores of a sleeping wild animal. Her sails are furled, but you can \
make out the pirate flag at the top of her mainmast.";
} else {
Longdesc.poseidons_hope = "The Poseidon's Hope is a three-mast, 150-foot galleon, in \
decent nick considering she's survived dozens of battles and is barred from most of the service \
shipyards this side of Mauritius. She sways slowly on the water, making gentle but powerful \
like the snores of a sleeping wild animal. Her sails are furled.";
}
});
Game.things.sea = {
dont_list_in_scroller: true,
indefinite: "the sea",
always: function() {
activate_dive();
},
list_last: true,
};
function activate_dive() {
set_active('sea', 'enter', worn('diving_helmet'));
};
Game.always.push(function() {
do_sea();
});
function do_sea() {
if(hero_location().is_coastal) {
bring('sea');
Game.things.sea.direction = hero_location().coast_dir;
if(Game.hero_location=='peninsula') {
Longdesc.sea = "A calm, cobalt sea stretches away to the east, south and west.";
}
Longdesc.sea = "A calm, cobalt sea stretches away to " +
the_dir(hero_location().coast_dir) +
', glinting in the sun.';
}
};
add_rule('before', 'enter', 'sea', function() {
if(!worn('diving_helmet')) {
console.log('tried to enter sea without helmet on??');
say("You'd probably drown.");
return true;
}
say('Putting all your faith in the copper helmet, you march into the sea.');
if(Game.things.air_compressor.winds <= 0) {
say('Unfortunately, it immediately fills up with water.');
drown();
return true;
}
if(!hero_location().enter_sea_to) {
drown();
return true;
}
Game.things.sea.enter_to = hero_location().enter_sea_to;
get_point_for('figured_out_helmet');
return false;
});
add_rule('before', 'enter', 'swamp', function() {
if(!worn('diving_helmet')) {
console.log('tried to enter swamp without helmet on??');
say("You'd probably drown.");
return true;
}
say('Putting all your faith in the copper helmet, you march into the swamp.');
if(Game.things.air_compressor.winds <= 0) {
say('Unfortunately, it immediately fills up with swampwater.');
drown();
return true;
}
get_point_for('got_into_swamp');
return false;
});
// rooms where the player's inventory can wash up
WASHUP_ROOMS = ['west_dock', 'rocky_shore', 'mermaid_cove', 'bottom_of_cliff'];
function drown() {
say('Currents pull you down... everything goes black.');
put('diving_helmet', 'bottom_of_cliff');
revive('Ye nearly drowned.', WASHUP_ROOMS);
}
function revive(deadseySays, whereToPutThings) {
put_hero('sick_bay', true);
if(!whereToPutThings) {
whereToPutThings = WASHUP_ROOMS;
}
// scatter the player's belongings around the shore near the ship
for(var thing in Game.things) {
if(carried(thing)) {
if(thing=='diving_helmet') {
put(thing, 'bottom_of_cliff');
} else {
put(thing, pickOne(whereToPutThings));
}
put('rubber_hose', 'bottom_of_cliff');
}
}
say('***\n\
You awake on a table in the sick bay of the Poseidon\'s Hope. Doctor Deadsey stands \
over you.');
say('"' + capitalise(arrr()) + '!" says the doctor. "'+ deadseySays +
' Ye\'re lucky to have survived. I didn\'t even get to amputate anythin\'," he adds sadly.');
say('"Now," the doctor asks, "does anything still hurt?"');
start_conversation('dr_deadsey', true);
};
function arrr() {
var txt = '';
if(!pick(3)) { txt += 'y' }
var n = 1 + pick(4);
for(var i=0; i \"Free your mind and ye may alter your perspective.\"");
get_point_for('read_treasuremap');
} else if(Game.things.paper.ironed) {
Longdesc.paper = "A square of thick white cartographers' paper. Now that the crinkles are \
gone, it does appear that there's a drawing of some kind on it -- but you can't make it out \
against the stark white background.";
} else if(Game.things.paper.stained) {
Longdesc.paper = "A square of thick cartographers' paper, stained light brown. Now that there \
is some colour to it, you can see that there's a drawing of some kind on it -- but you can't \
make out the details as they're lost among the creases of the crinkled paper.";
} else {
Longdesc.paper = "A square of thick cartographers' paper, stark white and a bit crinkly. It appears \
to be blank.";
}
});
/*
function mermaid_demands_conch() {
if(carried('conch') && in_scope('mermaid')) {
say('The mermaid stops you. "Leave the conch," she says firmly.');
return true;
}
return false;
}
*/
Game.rooms.mermaid_cove = {
description: "You're on a shell-covered beach by a tranquil cove.",
directions: {
north: "rocky_shore",
east: "top_of_cliff",
southeast: "bottom_of_cliff",
},
is_coastal: true,
coast_dir: "west",
enter_sea_to: "coral_reef",
helmet_cantgo: ['north', 'east'],
before: {
depart: function(dir) {
return check_helmet(dir);
}
},
};
function check_helmet(dir) {
if(carried('diving_helmet') && hero_location().helmet_cantgo.indexOf(dir)!=-1) {
say("The hose attached to your helmet pulls tight. You can't go any further while " +
(worn('diving_helmet') ? "wearing" : "carrying") + " it.");
return true;
}
return false;
};
Game.things.conch = {
portable: true,
location: "mermaid_cove",
description: "conch shell",
contains_crab: true,
};
Game.things.hermit_crab = {
seen: false
};
add_rule('before', 'take', 'sea_urchin', function() {
if(!worn('hook') && Game.things.sea_urchin.contains_crab) {
say('As you try to pick it up, a hermit crab pokes a claw out of the mouth of the shell \
and nips your fingers. Ouch!');
Game.things.hermit_crab.seen = true;
return true;
}
return false;
});
add_rule('before', 'take', 'conch', function() {
if(!worn('hook') && Game.things.conch.contains_crab) {
say('As you try to pick it up, a hermit crab pokes a claw out of the mouth of the shell \
and nips your fingers. Ouch!');
Game.things.hermit_crab.seen = true;
return true;
}
if(worn('hook') && Game.things.conch.contains_crab) {
if(!Game.things.conch.crab_gone) {
say('As you pick up the conch shell with your hook hand, a hermit crab pokes out a claw and \
tries to nip the metal, to no avail. Confused, it falls to the beach and scuttles away.');
Game.things.conch.contains_crab = false;
get_point_for('got_conch');
}
}
return false;
});
add_rule('before', 'examine', 'conch', function() {
Longdesc.conch = "A long, narrow, trumpet-shaped shell, with a hole at one end. \
It is shabby and grey" + (Game.things.conch.contains_crab ? ' and was probably once home to \
some near-destitute sea snail' : '') + "." +
(carried('conch') ? " It seems to be vibrating slightly." : "" );
});
add_rule('after', 'drop', 'sea_urchin', function() {
if(Game.things.conch.contains_crab && in_scope('conch')) {
say("At the sound of the urchin shell landing on the sand, " + (Game.things.hermit_crab.seen
? "the" : "a") + " hermit crab pokes its head out of the nearby conch and pauses, mentally \
surveying the new property in the neighbourhood. Its antennae wiggle as thoughts \
containing the crustacean equivalents of \"stunning residence\", \"luxurious \
presentation\" and \"close to local amenities\" rush through its little crabby mind. \
Coming to a decision, the crab takes one last look back into the conch, then scuttles out, \
across the beach -- and up the property ladder -- into its new home.");
get_point_for('got_conch');
Game.things.conch.contains_crab = false;
Game.things.sea_urchin.contains_crab = true;
}
});
Game.things.mermaid = {
is_alive: true,
pronouns: female_pronouns,
location: "mermaid_cove",
active_verbs: ["talk"],
conversifier: function() {
return conv_mermaid();
},
image: 'res/img/mermaid.png',
needs_conch: true,
always: function() {
do_mermaid();
}
};
function do_mermaid() {
Game.things.mermaid.seen = true;
if(Game.things.persilla.rescued) {
if(held('conch')) {
say('"Thanks for saving my sister," says ' + the_thing('mermaid') + '. "Here." She slither-walks in your \
direction, and kisses you on the forehead. "You\'re now a friend of the Great Underwater \
Empire."');
} else {
say(the_thing('mermaid', true) + ' faces you and makes grateful noises. She slither-walks \
in your direction, and kisses you on the forehead. You have a strong feeling that the \
two of you are now friends.');
}
say("She jumps into the sea, and is gone.");
hide('mermaid');
}
}
add_rule('before', 'talk', 'mermaid', function() {
if(!held('conch')) {
say('The mermaid speaks in an alien language of high clicks, low wails and \'blup\' noises. \
You can\'t understand each other.');
if(in_scope('conch')) {
say('The mermaid gestures a ' + (pickOne(['hand', 'fin'])) + ' towards the conch shell.');
}
return true;
} else {
get_point_for('talked_to_mermaid');
say('The mermaid speaks in an alien language of high clicks, low wails and \'blup\' noises -- \
but somehow, you can understand the words.');
return false;
}
});
On_hold.push(function() {
check_conch();
});
function check_conch() {
if(!held('conch') && Game.talking_to && Game.things[Game.talking_to].needs_conch) {
if(Game.talking_to=='mermaid' || Game.talking_to=='persilla') {
say("As you let go of the conch, " + the_thing(Game.talking_to) + "'s speech turns back \
into an inscrutable series of clicks and moans. You can't understand a syllable of it.");
} else if(Game.talking_to=='islanders_at_village'||Game.talking_to=='islanders_at_farmland') {
say("As you let go of the conch, you find you are suddenly unable to understand the \
islanders' language.");
} else {
say("As you let go of the conch, you find you are suddenly unable to understand " +
the_thing(Game.talking_to) + "'s language.");
}
hide_conversation();
}
};
Longdesc.mermaid = "Most mermaids that you've seen in paintings have the top half of a woman and the \
bottom half of a fish. This one, however, has the left half of a woman and the right half \
of a fish. Her human half is tan and brown-haired, with a shroud of woven seaweed strands to its \
modesty, and the fish half has scintillating green scales.";
function conv_mermaid() {
var conv = {};
conv.start_conversation = '"How\'s it going, weird-looking creature?" she says.';
conv.asks = {
mermaids: function() {
say("\"Not what you expected? We're not all vertically arranged, you know. Those are just \
the most painting-genic, by human standards. I know someone with the front half of a \
lady and the back half of a fish. One in four of us just looks like an ordinary human -- \
genetics, you see. My mother -- she's the king, you know -- doesn\'t have any fish \
bits at all. And as for my sister...\" she rolls her eyes.");
Game.things.mermaid.mentioned_sister = true;
Game.things.mermaid.mentioned_mother = true;
},
island: function() {
say('"We come here to airbathe sometimes. It used to be more peaceful -- \
the islanders have always left us alone." Her eyes drop. "It\'s more difficult now \
the soldiers are here, though."');
Game.things.mermaid.mentioned_islanders = true;
Game.things.mermaid.mentioned_soldiers = true;
Game.vars.heard_of_islanders = true;
},
};
if(Game.things.mermaid.mentioned_mother) {
conv.asks.king = '"Mum lives in a cave palace just offshore there," she says, pointing a ' +
(pick(2) ? 'hand' : 'fin') + ' westward. "I\'d say \
you could go and look, but you breathe air, don\'t you? I think you might drown."';
}
if(Game.things.mermaid.mentioned_sister) {
conv.asks.sister = function() {
say('"Persilla\'s always been a bit of a romantic. She ran off with one of those \
soldiers a while ago. She\'s read too many scrolls about mermaids falling in love with \
humans. I hope she\'s all right."');
};
Game.things.mermaid.mentioned_soldiers = true;
}
if(Game.things.mermaid.mentioned_islanders) {
conv.asks.islanders = "\"There's a human village on the island,\" she says, pointing eastward \
with her human arm. \"We leave them alone, they don't pollute much and they only fish in the \
river -- there are no freshwater mermaids.\"";
}
if(Game.things.mermaid.mentioned_soldiers) {
conv.asks.soldiers = "\"Horrible men in red coats. They built a fort in the north \
of the island. We stay away from there now -- too many near-misses with fishing lines.\"";
}
conv.end_conversation = "The mermaid gestures politely with her flipper.";
return conv;
}
Game.rooms.top_of_cliff = {
description: "You're on a grassy plateau. Cliffs fall away to the south.",
directions: {
east: "hill",
west: "mermaid_cove",
},
};
Game.rooms.hill = {
description: "You're on a hill in the south of the island.",
directions: {
north: "swamp",
west: "top_of_cliff",
},
};
Game.things.island_view = {
dont_list_in_scroller: true,
location: "hill",
name: "view",
description: "view of the whole island",
};
Longdesc.island_view = "";
add_rule('before', 'examine', 'island_view', function() {
say("The island is roughly oval, and longer on the north-south axis. \
This hill is somewhere near the south end, with cliffs tumbling down to the southern shore. \
To the northwest you can see a strip of palm forest, and slightly east of that, a swamp, from \
which a brown river flows south to the ocean. At the southeast of the island, a long thin \
peninsula protrudes like the tail of a lower-case q.");
say("There are artificial structures too. In the far north is a wooden stockade flying the \
garish, butcher's-shop colours of the British flag. A more permanent-looking village \
lies east, just across the river. You can see your ship from here, anchored by the west coast" + ( Game.things.treasure_fleet.miniaturised ? "." : ", and the " +
(Game.things.treasure_fleet.seen_from_peninsula ? "other ships in the distant south, \
which from here you can identify as the Spanish Treasure Fleet." :
"Spanish treasure fleet in the distant south.")
)
);
Game.vars.seen_fort = true;
Game.vars.village_seen = true;
Game.things.treasure_fleet.name = "treasure fleet";
Game.things.treasure_fleet.description = "Spanish treasure fleet";
Game.things.treasure_fleet.indefinite = "the Spanish treasure fleet";
Game.things.treasure_fleet.portable = true;
if(!Game.vars.seen_treasure_fleet) {
set_fuse('saw_fleet', 5);
Game.vars.seen_treasure_fleet = true;
}
return true;
});
Game.fuses.saw_fleet = {
burn: function() {
if(Game.fuses.saw_fleet.time==2) {
say('Something seems to be nagging at your mind.');
}
},
explode: function() {
var el = $('#scroller span.new_message').last();
var ehtml = el.text(); // clear formatting to avoid cutting in the middle of an or something
if(ehtml.length > 8) {
ehtml = ehtml.substring(0, Math.floor(ehtml.length * 0.66));
ehtml += '—'
el.html(ehtml);
} else {
say("Hang on...");
}
say(" ");
say("HOLY " + pirate_oath(true).toUpperCase() + ", YOU SAW THE SPANISH \
TREASURE FLEET. The Holy Grail of pirating! Except that the Holy Grail is just one golden \
cup, whereas that fleet -- why, there\'s probably at least an entire golden crockery set on \
those ships, \
not to mention barrels and barrels of gold, jewels, gold, diamonds, looted artefacts, \
emeralds, rubies, paella, tapas, gold, spicy meat snacks, and gold! And " +
(Game.hero_location=='hill' ? "they're" : "they were")
+ " just sitting there like ducks, becalmed! \
Of course they have thousands of the best cannon in the world, operated by the most skilled \
warriors on the seven seas. But " + pirate_oath(true) + ", if you could ever take that \
fleet... even the thought feels magical.");
Game.things.treasure_fleet.seen = true;
get_point_for('identified_treasure_fleet');
}
};
Game.rooms.meadow = {
description: "You're in a rolling green meadow.",
directions: {
north: "outside_barracks",
east: "pebbly_shore",
south: "swamp",
west: "forest_north",
},
};
Game.rooms.pebbly_shore = {
description: "You're on a pebbly shore at the northeast of the island.",
is_coastal: true,
coast_dir: 'northeast',
directions: {
south: "farmland",
west: "meadow",
}
};
Game.rooms.farmland = {
description: "You're on some cultivated farmland by the east shore.",
is_coastal: true,
coast_dir: 'east',
directions: {
north: "pebbly_shore",
south: "village",
},
};
Game.things.crops = {
location: "farmland",
};
Longdesc.crops = "Long runs of tilled ground, each growing a different plant that you don't \
recognise, with access spaces between them and some irrigation ditches cut from the river.";
Game.things.river_at_farmland = {
name: "river",
description: "river",
location: "farmland",
status: ["to west"],
};
Longdesc.river_at_farmland = "The river flows out of a nearby swamp, then rushes \
southward. The water is brown and moving too fast to cross.";
Game.rooms.village = {
description: "You're in a village of baked clay houses.",
directions: {
north: "farmland",
south: "crag",
},
is_coastal: true,
coast_dir: "east",
always: function() {
Game.vars.village_seen = true;
}
};
Game.things.houses = {
dont_list_in_scroller: true,
is_plural: true,
location: "village",
};
Longdesc.houses = "Several houses built out of baked clay blocks, with colours varying from dark \
brown to pale pink."
Game.things.river_at_village = {
name: "river",
description: "river",
location: "village",
status: ["to west"]
};
Longdesc.river_at_village = "A wide, fast-flowing river blocks the way west. On the other side is \
a tall hill.";
Game.things.islanders_at_farmland = {
name: "islanders",
description:"islanders",
is_alive: true,
is_plural: true,
pronouns: plural_pronouns,
location: "farmland",
active_verbs: ["talk"],
image: 'res/img/islanders.png',
conversifier: function() {
return conv_islanders();
},
always: function() {
do_islanders_at_farmland();
}
};
Game.things.islanders_at_village = {
name: "islanders",
description:"islanders",
is_alive: true,
is_plural: true,
pronouns: plural_pronouns,
location: "village",
active_verbs: ["talk"],
image: 'res/img/islanders.png',
conversifier: function() {
return conv_islanders();
},
always: function() {
do_islanders_at_village();
}
};
function do_islanders_at_farmland() {
say(get_islander(true) + " " + pickOne([
"plants something.",
"pulls up a plant.",
"arrives from the south.",
"walks south.",
"tills some soil with a wooden tool."
]));
}
function do_islanders_at_village() {
say(get_islander(true) + " " + pickOne([
"emerges from one of the houses.",
"enters one of the houses.",
"stops to talk to " + get_islander(false),
"and " + get_islander(false) + " walk by.",
"walks north.",
"arrives from the north."
]));
}
Longdesc.islanders_at_farmland = "A crowd of brown-skinned people in white clothes mill around, attending to \
various duties. You've been told that islanders tend to be hostile to foreigners, but apart from a few \
distrustful glances, this lot seem more concerned with working their bums off so they don't starve.";
Longdesc.islanders_at_village = "A crowd of brown-skinned people in white clothes mill around, attending to \
various duties. You've been told that islanders tend to be hostile to foreigners, but apart from a few \
distrustful glances, this lot seem more concerned with working their bums off so they don't starve.";
add_rule('before', 'talk', 'islanders_at_farmland', function() {
if(!held('conch')) {
say("You don't speak their language, and they don't speak yours.");
return true;
} else {
say("You don't speak their language, and they don't speak yours... but somehow, you're able \
to understand each other anyway.");
return false;
}
});
add_rule('before', 'talk', 'islanders_at_village', function() {
if(!held('conch')) {
say("You don't speak their language, and they don't speak yours.");
return true;
} else {
say("You don't speak their language, and they don't speak yours... but somehow, you're able \
to understand each other anyway.");
return false;
}
});
function conv_islanders() {
var conv = {};
conv.start_conversation = get_islander(true) + " stops to talk.";
conv.asks = {
island: "\"Well, it's quite small, and it rains for three months a year, and every now and \
then some pirate comes and chucks a treasure chest full of gold in our swamp, but we \
happen to like it.\""
};
if(Game.vars.village_seen) {
conv.asks.village = '"Pretty, isn\'t it? Just don\'t touch anything, please."';
};
if(Game.vars.seen_fort) {
conv.asks.fort = '"Ugh, those redcoats. Coming over here without permission, not bothering to \
learn the language, never doing any hard work. Send them back where they came from if you ask \
me."';
};
if(Game.things.old_bob.seen) {
conv.asks[name('old_bob')] = '"That nutter? We call him \
\'Man That-Day-a-Bunch-of-Idiots-Crashed-Their-Ship-Into-Our-Island\'. There used to be a \
bunch more people from that ship, but I don\'t know what happened to the rest of them. One \
day there was a smell of fava beans and Chianti, and they all disappeared."';
};
if(Game.things.mermaid.seen) {
conv.asks.mermaids = '"The fish ladies? They leave us alone and we leave them alone, really. \
They say they have a palace under the sea somewhere, but I\'ve never been."';
};
conv.end_conversation = "The islander moves off."
return conv;
}
function get_islander(capsP) {
var txt = capsP ? "A" : "a";
if(!pick(3)) {
txt += pickOne([' young', 'n old', ' middle-aged']);
}
txt += pickOne([" man", " woman", " islander"]);
return txt;
}
Game.rooms.crag = {
description: "You're in a craggy area at the southeast of the island.",
is_coastal: true,
coast_dir: "east",
directions: {
north: 'village',
south: 'peninsula',
}
};
Game.things.river_at_crag = {
location: "crag",
name: "river",
description: "river",
status: ["to west"]
}
Longdesc.river_at_crag = "A rushing river blocks your way west.";
Game.rooms.peninsula = {
description: "You're on a long peninsula trailing south from the island.",
is_coastal: true,
coast_dir: 'south',
directions: {
north: 'crag'
},
always: function() {
Game.things.treasure_fleet.seen_from_peninsula = true;
}
};
Game.things.treasure_fleet = {
name: "fleet of ships",
description: "fleet",
status: ["in distant south"],
location: "peninsula",
};
add_rule('before', 'examine', 'treasure_fleet', function() {
if(Game.things.treasure_fleet.miniaturised) {
Longdesc.treasure_fleet = "A collection of twenty miniature ships, each about an inch long. \
The ships seem somehow much heavier than they actually are. The space around them ripples \
strangely.";
} else if(worn('eyepatch')) {
Longdesc.treasure_fleet = "The fleet of twenty huge, heavily armed ships sits just on the \
southern horizon. Without your depth perception, they seem like they could be either \
large ships far away, or tiny ships close up.";
} else {
Longdesc.treasure_fleet = "The fleet of twenty huge, heavily armed ships sits just on the \
southern horizon, so far away that they look tiny at this distance.";
}
});
Game.always.push(function() {
do_magic();
});
function do_magic() {
if(!Game.things.treasure_fleet.miniaturised) {
var magicP = (Game.vars.hallucinating && worn('eyepatch') && Game.hero_location=='peninsula' && Game.things.treasure_fleet.seen);
set_active('treasure_fleet', 'take', magicP);
if(magicP && !Game.vars.done_magic_message) {
say('Something in the air feels magical. Space and distance seem to warp and shift around you.');
Game.vars.done_magic_message = true;
}
}
}
add_rule('before', 'take', 'treasure_fleet', function() {
if(!Game.things.treasure_fleet.miniaturised) {
say('You reach out an arm, which suddenly seems very long, towards the tiny ships. Somehow, \
impossibly, your fingers close around them.');
Game.things.treasure_fleet.miniaturised = true;
}
return false;
});
add_rule('after', 'take', 'treasure_fleet', function() {
clear_status('treasure_fleet');
Game.things.treasure_fleet.description = "miniaturised Spanish treasure fleet";
get_point_for('got_treasure_fleet');
});
Game.rooms.swamp = {
description: "You're in a scrubland area by a fetid swamp.",
directions: {
north: "meadow",
south: "hill",
west: "forest_south",
},
helmet_cantgo: ['north', 'south', 'west'],
before: {
depart: function(dir) {
return check_helmet(dir);
}
},
always: function() {
do_swamp();
},
enter_to: "bottom_of_swamp",
};
function do_swamp() {
set_active('swamp', 'enter', worn('diving_helmet'));
}
Game.rooms.bottom_of_swamp = {
description: "You're at the bottom of a swamp.",
directions: {
up: "swamp",
},
underwater: true,
};
Game.things.treasure_chest = {
name: "treasure chest",
description: "treasure chest",
location: "bottom_of_swamp",
portable: true,
locked: true,
active_verbs: ["open"],
contents: ["gold_bar"],
};
Longdesc.treasure_chest = "This is the classic pirate treasure chest, all right -- weathered oak \
sides, a curved lid, brass binding, ornate carvings of mermaids, the lot. It\'s small enough to be \
easily portable, but could still fit a very respectable amount of loot.";
On_hold.push(function() {
set_active('treasure_chest', 'unlock', held('silver_key') && Game.things.treasure_chest.locked);
});
add_rule('before', 'open', 'treasure_chest', function() {
if(Game.things.treasure_chest.locked) {
say("It's locked.");
if(carried('treasure_chest') && carried('silver_key')) {
say("(You'll need to put it down to unlock it.)");
}
return true;
}
if(hero_location().underwater) {
say('The water pressure stops you from opening it down here.');
return true;
}
return false;
});
Game.things.gold_bar = {
portable: true,
always: function() {
get_point_for('found_gold');
}
};
Longdesc.gold_bar = "A cuboid of entirely useless metal with no practical applications, which is \
probably worth more than food for a family of ten or a month's wage for an entire ship's crew. \
One side is imprinted with the words: \"Certified treasure.\"";
On_hold.push(function() {
set_active('treasure_chest', 'give', in_scope('capn'));
set_active('gold_bar', 'give', in_scope('capn'));
set_active('treasure_fleet', 'give', in_scope('capn'));
});
add_rule('before', 'give', 'treasure_chest', function() {
say("(to cap\'n)");
if(Game.things.treasure_chest.locked) {
say("Cap\'n says, \"Good progress, but it ain\'t much good to me if it\'s locked, is it?\"");
} else if(!Game.things.treasure_chest.contents.length) {
say("Cap\'n says, \"It ain\'t much good to me if it\'s empty, is it?\"");
} else {
say("Cap\'n takes the chest and opens it, revealing a big, valuable gold bar.");
win(false);
}
return true;
});
add_rule('before', 'give', 'gold_bar', function() {
say('(to cap\'n)');
win(false);
});
add_rule('before', 'give', 'treasure_fleet', function() {
say('(to cap\'n)');
win(true);
});
function win(specialSuperSecretEnding) {
if(!specialSuperSecretEnding) {
say('Cap\'n looks pleased.');
die('"That\'ll do nicely enough," she says. "I guess you can stay on board. \
You\'re hereby promoted to Marauder, Second Class. Well done, matey!"', 'Ending 1 of 2');
} else {
say('Cap\'n looks delighted.');
die('"Well," she says. "I ain\'t seen anythin\' like this in all my days at sea. \
You\'re hereby promoted to First Pirate Officer. Brilliantly done, matey!"', 'Ending 2 of 2');
}
}
Game.things.nest = {
name: "nest",
description: "filthy nest",
};
Longdesc.nest = "A large nest made of mud, sticks, and a few white glints that might be bones.";
Game.things.egg = {
name: "egg",
portable: true,
edible: true,
status: ["in nest"],
active_when_carried: ["eat"],
location: "swamp",
};
add_rule('after', 'take', 'egg', function() {
remove_status('egg', 'in nest');
});
add_rule('before', 'eat', 'egg', function() {
say('What, raw? You\'d get salmonella!');
return true;
});
add_rule('before', 'examine', 'egg', function() {
if(!carried('egg')) {
Longdesc.egg = "A biggish, white-shelled egg. Now and then you could swear you saw \
it wobble.";
} else {
Longdesc.egg = "A biggish, white-shelled egg.";
}
});
Game.things.swamp = {
location: "swamp",
dont_list_in_scroller: true,
enter_to: "bottom_of_swamp"
};
Longdesc.swamp = "A wide, dirty pool of gooey mud. Bubbles burst slowly on its surface.";
Game.things.river_at_swamp = {
name: "river",
description: "river",
status: ["to east"],
location: "swamp"
};
add_rule('before', 'examine', 'river_at_swamp', function() {
if(!worn('diving_helmet')) {
Longdesc.river_at_swamp = "The river flows out of the east side of the swamp and then rushes \
southward. The water is brown and moving too fast to cross. On the other side you can see some \
cultivated land.";
} else {
Longdesc.river_at_swamp = "The river flows out of the east side of the swamp and then rushes \
southward. The water is brown and moving too fast to cross, even with special gear. On the \
other side you can see some cultivated land.";
}
return false;
});
Game.things.berry_bush = {
name: "bush",
description: "berry bush",
active_verbs: ["pick_berries"],
enter_to: "bobs_cave",
location: "swamp",
};
add_rule('before', 'examine', 'berry_bush', function() {
if(!Game.things.berry_bush.picked) {
Longdesc.berry_bush = "A thorny, unfriendly looking shrub bearing bright purple berries.";
} else {
Longdesc.berry_bush = "A thorny, unfriendly looking shrub. It has no berries at the moment.";
}
});
add_rule('before', 'enter', 'berry_bush', function() {
say('Shielding yourself against the thorns, you part the leaves of the bush and plunge through...');
get_point_for('got_through_bush');
Game.suppress_ok = true;
return false;
});
Game.things.berries = {
is_plural: true,
portable: true,
edible: true,
active_when_carried: ["eat"],
};
Longdesc.berries = "A handful of bright purple berries. They smell a little bitter a little sweet.";
add_rule('after', 'eat', 'berries', function() {
// put them back on the bush to avoid an unwinnable state
Game.things.berry_bush.picked = false;
var loc = "" + Game.hero_location;
revive('Ye were found passed out with a stomach full of Almost Deadly Nightshade berries.', [loc]);
});
Game.rooms.bottom_of_cliff = {
is_coastal: true,
coast_dir: 'southwest',
enter_sea_to: 'coral_reef',
description: "You're at the bottom of a rugged cliff on the south coast of the island.",
directions: {
east: "bobs_camp",
northwest: "mermaid_cove",
},
always: function() {
Game.things.shipwreck.seen = true;
}
};
Game.things.shipwreck = {
location: "bottom_of_cliff",
};
Longdesc.shipwreck = "\"Wreck\" is an understatement, really -- this is more what might be nautically \
termed \"a pile of mangled firewood\". You couldn\'t be certain it was a ship, except that it's \
scattered in a vaguely hull-shaped pattern. It must have hit the cliffs at extraordinary speed. There are no signs of any crew, surviving or otherwise.";
Game.things.air_compressor = {
name: "machine",
description: "strange machine",
location: "bottom_of_cliff",
working: false,
winds: 0,
max_winds: 25,
winds_per_windlass_turn: 5,
};
add_rule('before', 'examine', 'air_compressor', function() {
return exam_air_compressor();
});
add_rule('after', 'examine', 'air_compressor', function() {
describe_hose_from_machine();
});
Game.always.push(function() {
do_air_compressor();
});
function do_air_compressor() {
if(Game.things.air_compressor.winds > 0) {
Game.things.air_compressor.winds--;
if(Game.things.air_compressor.winds <= 0) {
remove_status('air_compressor', 'working');
}
if(!worn('diving_helmet')) {
return;
}
var w = Game.things.air_compressor.winds;
if(w==10) {
say("The air flow inside the copper helmet gets noticeably weaker.");
} else if(w==5) {
say("The air flow inside the copper helmet is very faint now.");
} else if(w==2) {
say("There's hardly any air flow inside the copper helmet now." +
(hero_location().underwater ? " You gasp for breath." : "")
);
} else if(w==1) {
say("The air inside the copper helmet starts to smell stale." +
(hero_location().underwater ? " Your vision starts to blur." : "")
);
} else if(w==0) {
say("The air flow inside the copper helmet has stopped.");
if(!hero_location().underwater) {
return;
}
say("Quickly, dreadfully, the copper helmet fills up with water.");
drown();
return;
}
}
};
function exam_air_compressor() {
if(Game.things.air_compressor.winds<=0) {
Longdesc.air_compressor = "It's a big cube, about eight feet long on each side, with brass \
edges. Judging by the splinters of broken glass lying around it, you suppose it once had glass \
sides, but they were shattered when the ship crashed. Inside the cube is a wide cylinder with a \
concertina-like section, but nothing\'s moving. In one corner there's a windlass with an ivory \
handle.";
activate_verb('air_compressor', 'turn_windlass');
} else {
Longdesc.air_compressor = "It's a big cube, about eight foot long on each side, with brass \
edges. Judging by the splinters of broken glass lying around it, you suppose it once had glass \
sides, but they were shattered when the ship crashed. Inside the cube is a wide cylinder with a \
concertina-like section, heaving up and down and hissing like an enormous bellows. In one \
corner there's a windlass with an ivory handle, which is turning slowly anti-clockwise.";
}
return false;
};
function describe_hose_from_machine() {
if(in_scope('diving_helmet')) {
say("A length of rubber hose trails from a valve in the mechanism, connecting it to the copper \
helmet.");
} else {
say("A length of rubber hose trails from a valve in the mechanism.");
}
};
Game.things.rubber_hose = {
name: "hose",
description: "rubber hose",
};
Game.always.push(function() {
do_rubber_hose();
});
function do_rubber_hose() {
// TODO: deploy rubber hose depending on location of hero, helmet and machine
var helmetHere = in_scope('diving_helmet');
var machineHere = in_scope('air_compressor');
if(!helmetHere && !machineHere) {
return;
}
bring('rubber_hose'); // should be dealt with already if we're doing mid-sections of the hose
clear_status('rubber_hose');
var helmetDesc = "the copper helmet";
if(worn('diving_helmet')) {
helmetDesc += " that you're wearing";
} else if(held('diving_helmet')) {
helmetDesc += " that you're holding";
} else if(carried('diving_helmet')) {
helmetDesc += " that you're carrying";
}
if(helmetHere && machineHere) {
add_status('rubber_hose', 'connecting machine to copper helmet');
Longdesc.rubber_hose = "A length of coiling yellow tube connected at one end to the strange \
machine and at the other end to " + helmetDesc + ".";
} else if(helmetHere) {
add_status('rubber_hose', 'connected to copper helmet');
Longdesc.rubber_hose = "A length of coiling yellow tube. One end is connected to " +
helmetDesc + ". You can't see the other end.";
} else if(machineHere) {
add_status('rubber_hose', 'connected to strange machine');
Longdesc.rubber_hose = "A length of coiling yellow tube. One end is connected to the \
strange machine. You can't see the other end.";
} else {
Longdesc.rubber_hose = "A length of coiling yellow tube sprawls across the " +
(hero_location().underwater ? "sea-bed" : "ground") + ". You can't see either end.";
}
set_active('rubber_hose', 'pull', !helmetHere);
};
add_rule('before', 'pull', 'rubber_hose', function() {
say("You pull on the rubber hose until the copper helmet at the other end trundles to your feet.");
bring('diving_helmet');
do_rubber_hose();
});
Game.things.diving_helmet = {
name: "helmet",
description: "copper helmet",
wearable: true,
portable: true,
location: "bottom_of_cliff",
done_freshish_gag: false,
};
Longdesc.diving_helmet = "A spherical copper helmet, big enough to cover your whole head, \
with a round glass window in the front and a sort of rubber skirt in the neck area to seal it off.";
add_rule('after', 'wear', 'diving_helmet', function() {
if(Game.things.air_compressor.winds > 0) {
if(!Game.things.air_compressor.done_freshish_gag) {
say("There is a hissing noise as fresh air -- well, freshish air -- flows in and out through the rubber hose.");
Game.things.air_compressor.done_freshish_gag = true;
} else {
say("There is a hissing noise as freshish air flows in and out through the rubber hose.");
}
} else {
say("The air inside the helmet feels stale and muggy.");
}
});
add_rule('after', 'remove', 'diving_helmet', function() {
if(hero_location().underwater) {
say("Well, that was daft.");
drown();
}
});
add_rule('after', 'drop', 'diving_helmet', function() {
if(hero_location != 'bottom_of_cliff') {
say('The rubber hose goes taut and retracts, gently pulling the helmet away over the ground \
and out of sight.');
put('diving_helmet', 'bottom_of_cliff');
put('rubber_hose', 'bottom_of_cliff');
};
});
Game.rooms.undersea_south = {
description: "You're surrounded by murky seawater.",
directions: {
north: 'bottom_of_cliff',
east: 'undersea_south',
south: 'deep_sea',
west: 'coral_reef',
},
underwater: true,
};
Game.rooms.deep_sea = {
description: "You're deep in the ocean.",
directions: {
north: 'coral_reef',
east: 'undersea_south',
south: 'deep_sea',
west: 'deep_sea',
},
underwater: true,
}
Game.rooms.bobs_camp = {
description: "You're on an area of patchy grass by the south coast.",
is_coastal: true,
coast_dir: 'south',
enter_sea_to: "undersea_south",
directions: {
west: 'bottom_of_cliff',
}
};
Game.things.fire = {
name: "fire",
description: "burnt-out fire",
location: "bobs_camp",
};
Longdesc.fire = "The charred remains of a driftwood cooking-fire, contained by a ring of blackened \
pebbles.";
Game.things.river_mouth = {
name: "river",
description: "mouth of river",
location: "bobs_camp",
status: ["to east"],
};
add_rule('before', 'examine', 'river_mouth', function() {
if(!worn('diving_helmet')) {
Longdesc.river_mouth = "The bubbling water churns out into the sea at this point. It's too \
rapid to cross.";
} else {
Longdesc.river_mouth = "The bubbling water churns out into the sea at this point. It's too \
rapid to cross, even with special gear.";
}
});
Game.things.cave_entrance = {
name: "cave",
description: "cave entrance",
status: ["to north"],
active_verbs: ["enter"],
location: "bobs_camp",
enter_to: "bobs_cave",
};
Longdesc.cave_entrance = "A cave entrance leads darkly into the rock face to the north. You can't see many \
details from out here, but it's clearly a permanent residence -- there are some tools and trinkets \
scattered about, and what looks like a Royal Navy greatcoat carpeting the cavern floor.";
add_rule('before', 'enter', 'cave_entrance', function() {
if(in_scope('old_bob')) {
if(Game.things.old_bob.hurt_teeth) {
say(the_thing('old_bob', true) + ' cowers away from you. "Please don\'t hurt my teeth again!" he whimpers.');
}
say(the_thing('old_bob', true) + ' bars your way.');
say('"I found that cave," he insists. "It\'s my home. Stay out."');
return true;
}
return false;
});
Game.things.greatcoat = {
name: "greatcoat",
description: "naval greatcoat",
portable: true,
wearable: true,
location: "bobs_cave",
ironable: true,
};
add_rule('before', 'iron', 'greatcoat', function() {
if(Game.things.greatcoat.ironed) {
Game.things.greatcoat.already_ironed = true;
}
return false;
});
add_rule('after', 'iron', 'greatcoat', function() {
if(Game.things.greatcoat.already_ironed) {
say("It's probably as neat as it's going to get.");
} else {
say('You got a few of the creases out.');
}
});
add_rule('before', 'iron', 'paper', function() {
if(Game.things.paper.ironed) {
Game.things.paper.already_ironed = true;
}
return false;
});
add_rule('after', 'iron', 'paper', function() {
if(Game.things.paper.already_ironed) {
say("It's probably as flat as it's going to get.");
} else {
say('The paper seems flatter now.');
Game.things.paper.ironed = true;
get_point_for('ironed_map');
if(Game.things.paper.stained) {
say('It seems you can now make out a drawing on the paper...')
};
}
});
Longdesc.greatcoat = 'A woollen floor-length coat in the dark blue of the British Royal Navy, with two \
almost-complete columns of brass buttons and the insignia of the engineering corps. It has \
acquired a rather fusty smell from years of being used as a cave carpet, possibly an improvement \
after its years of being used as a coat by naval engineers.';
Game.things.old_bob = {
description: "bearded old man",
name: "old man",
met_description: "Old Bob",
met_name: "Bob",
is_alive: true,
pronouns: male_pronouns,
image: 'res/img/old-bob.png',
location: "bobs_camp",
active_verbs: ["talk"],
conversifier: function() {
return conv_bob();
},
always: function() {
Game.things.old_bob.seen = true;
}
};
Longdesc.old_bob = "A long-bearded, elderly man. He watches you with a slightly aggressive bearing.";
function conv_bob() {
var conv = {};
if(!Game.things.old_bob.met) {
conv.start_conversation = 'The old man looks up and suddenly charges at you, only stopping \
when his face is a few inches from yours. "This here\'s my bit," he says aggressively.';
} else {
conv.start_conversation = 'Old Bob regards you suspiciously. "Whatcha want now?"';
}
conv.asks = {
himself: function() {
say('"Why, I\'m..." the old man seems to struggle to remember the answer. \
"Bob, I reckon. Old Bob. First mate of the HMS -- " he points west -- "that pile of \
matchwood along there." He performs a mock salute.');
meet('old_bob');
}
};
conv.asks.cave = function() {
say("\"Nice, isn't it! And it's all mine. It's even got a little entrance round the \
back, through a berry bush.\"");
activate_verb('berry_bush', 'enter');
get_point_for('learned_about_cave');
}
if(Game.things.shipwreck.seen) {
conv.asks.ship = function() {
say('"Musta been -- well, I\'da counted the summers, but it\'s all summers here. \
Best I can do is tell you I shaved that morning." He holds up a tuft of his four-foot \
beard. "We was on a scientific expedition led by this navy engineer. Only we got into \
a bleeder of a storm, see, an\' it blew away all the maps. Lifted the ship clear out \
the water and smashed straight into them cliffs over there at thirty knots. So much for \
our trip to the south pole." He looks down. "Never worked out \
quite where we ended up, but I\'m pretty sure I ain\'t seen any penguins."');
Game.things.old_bob.mentioned_crash = true;
};
conv.asks.machine = function() {
say("\"Yeah, that was some gizmo the engineer came up with. Said it was for lettin\' \
people go overboard without drownin\'. I says, \'What\'s the point in throwin\' \
someone overboard if they don't even drown?\'\"");
};
}
if(Game.things.old_bob.mentioned_crash) {
if(!Game.things.old_bob.hurt_teeth) {
conv.asks.crew = '"The cap\'n and the rest of the crew, well, they all drowned, or starved, \
or got et by octopussuses, or whatever. I was the only one with the wit to survive, I \
s\'pose. Also, it may have \'elped that I nicked the only lifebelt," he adds \
apologetically.';
} else {
conv.asks.crew = '"Oh all right... I ate \'em"';
}
}
return conv;
}
Game.rooms.bobs_cave = {
description: "You're in a mouldy-smelling cave.",
directions: {
north: 'swamp',
south: 'bobs_camp',
},
always: function() {
if(!Game.things.old_bob.hurt_teeth && location_of('old_bob')=='bobs_camp') {
do_bite();
};
}
};
Game.things.skeletons = {
name: "skeletons",
location: "bobs_cave",
description: "pile of skeletons",
always: function() {
Game.things.skeletons.seen = true;
}
};
Longdesc.skeletons = "A large, gruesome pile of human bones. They're a bit tangled up so it's \
hard to say how many people they might once have been, but at a quick guess, maybe around the crew \
complement of an antarctic science ship. Some of them are visibly notched with the horseshoe marks of \
human teeth.";
function do_bite() {
say(capitalise(a_thing("old_bob")) + " enters from the south.");
say('"What are you doing?" he cries. "This is my cave for murderin\' all me former crewmates \
and eating them -- er, I mean, my place what I just found here with all these skeletons in it."');
if(!worn('pegleg')) {
say('He pauses, then makes a lunge for you, grabs your left leg, and sinks in his surprisingly \
sharp and numerous teeth. You try to run...');
revive('We found you runnin\' through the forest, bleedin\' an\' gently brushed with ' +
pickOne(['garlic', 'lemon', 'horseradish', 'apple', 'mint', 'cheese']) + ' sauce.',
['forest_north', 'forest_south', 'swamp']);
} else {
say('He pauses, then makes a lunge for you, grabs your peg leg, and sinks in his teeth -- \
then cries out in pain. "Owwww! That\'s not fair," he adds broodingly, and runs \
away.');
Game.things.old_bob.hurt_teeth = true;
get_point_for('fixed_bob');
hide('old_bob');
}
}
Game.things.fungus = {
indefinite: "some fungus",
description: "fungus",
status: ["growing on wall"],
location: "bobs_cave",
active_verbs: ["pick"],
edible: true,
active_when_carried: ["eat"],
};
Longdesc.fungus = "A clump of little mushrooms, coloured a faintly luminescent green with black spots.";
add_rule('before', 'eat', 'fungus', function() {
console.log('eating fungus');
if(!Game.vars.hallucinating) {
//console.log('not hallucinating');
say("You eat one of the little mushrooms. There's plenty left over.");
say("Oh my. They're quite... yeah... sort of spirally, sort of wibbly, like... \
yeah, you're totally in touch with the cosmos, you reach me?")
set_fuse('tripping_balls', 5);
//console.log('started fuse');
Game.vars.hallucinating = true;
} else {
say("You would, but like, your hand keeps trying to fly off or whatever");
}
return true;
});
COLOURS = ['pink', 'red', 'yellow', 'turquoise', 'green', 'orange', 'blue', 'purple'];
ANIMALS = ['elephant', 'hippo', 'rhino', 'unicorn', 'creepy-crawly', 'heebie-jeebie'];
Game.vars.num_hallucinations = 0;
function bring_hallucination() {
var desc = pickOne(COLOURS) + ' ' + pickOne(ANIMALS);
Game.things['hallucination_' + Game.vars.num_hallucinations++] = {
name: desc,
description: desc,
location: Game.hero_location,
isHallucination: true,
active_verbs: [], status: []
};
};
function clear_hallucinations() {
for(var i in Game.things) {
if(Game.things[i].isHallucination) {
delete Game.things[i];
}
}
Game.vars.hallucinating = false;
Game.vars.num_hallucinations = 0;
}
Game.fuses.tripping_balls = {
burn: function() {
bring_hallucination();
},
explode: function() {
say('Everything is just a little too gnarly. You pass out.');
clear_hallucinations();
revive('Ye were trippin\' some serious cannonballs, matey. We found ye in the forest \
claimin\' to be a ' + pickOne(['koala', 'squirrel', 'marmoset', 'dodo', 'tree frog',
'sloth', 'rattlesnake']) + ' named ' +
pickOne(['Mozart', 'Beethoven', 'Chopin', 'Bach', 'Vivaldi', 'Pachelbel']) + '.', ['forest_south', 'forest_north']);
},
};
Game.rooms.coral_reef = {
description: "You're on an underwater coral reef.",
underwater: true,
directions: {
north: 'undersea_west',
east: 'mermaid_cove',
south: 'undersea_south',
west: 'underwater_cave',
},
};
Game.rooms.undersea_west = {
description: "You're surrounded by murky seawater.",
directions: {
north: 'undersea_west',
east: 'mermaid_cove',
south: 'coral_reef',
west: 'deep_sea',
}
};
Game.rooms.underwater_cave = {
description: "You're in an undersea cavern lit by eerie luminescent seaweed.",
underwater: true,
directions: {
east: 'coral_reef',
down: 'mer_palace'
},
};
Game.rooms.mer_palace = {
description: "You're in an underwater palace in a deep sea-cave.",
directions: {
up: 'underwater_cave',
},
};
Game.things.mermaid_king = {
description: "Mermaid King",
indefinite: "the Mermaid King",
is_alive: true,
pronouns: female_pronouns,
active_verbs: ["talk"],
location: 'mer_palace',
image: 'res/img/mermaid-king.png',
always: function() {
get_point_for('found_mermaid_king');
}
};
Longdesc.mermaid_king = 'The Mermaid King is humanoid all over, dressed in a sailcloth robe \
and a pearl coronet. Apart from a certain scaly sheen to the skin, the king could pass as \
a full human. Like all mermaids, she\'s female.';
add_rule('before', 'talk', 'mermaid_king', function() {
if(!Game.things.persilla.rescued) {
say((held('conch') ? "Even with special gear, you" : "You" ) + " can\'t talk underwater \
-- but that's ok, because the king's expression tells you very firmly that she wouldn't \
lower herself to speaking to the likes of you anyway.");
} else {
say((held('conch') ? "Even with special gear, you" : "You") + " can\'t talk underwater, \
but the king gives you a nod of approval.");
}
return true;
});
Game.things.silver_key = {
name: "key",
description: "silver key",
portable: true,
location: "mer_palace",
};
Longdesc.silver_key = 'A small silver key carved with an ornate carving of a mermaid on the handle.'
add_rule('before', 'take', 'silver_key', function() {
if(!Game.things.persilla.rescued) {
say('The Mermaid King won\'t let you. What must be a telepathic message arrives in your mind: \
We don\'t know you, human. Perform some duty to the Great Underwater Empire, and we may \
reconsider.');
return true;
} else if(!Game.things.mermaid_king.nodded) {
say('The Mermaid King gives you a nod of approval.');
Game.things.mermaid_king.nodded = true;
return false;
}
return false;
});
function conv_mermaid_king() {
var conv = {};
return conv;
}
Game.rooms.forest_north = {
description: "You're in a dense palm forest.",
directions: {
northwest: "sandy_beach",
northeast: "outside_barracks",
west: "dry_grass",
south: "forest_south",
},
};
Game.rooms.forest_south = {
description: "You're in a dense palm forest.",
directions: {
north: "forest_north",
east: "swamp",
southwest: "mermaid_cove",
},
};
Game.rooms.outside_barracks = {
description: "You're in a clearing by a gate in a wooden stockade.",
directions: {
west: "forest_north",
south: "meadow",
},
always: function() {
Game.vars.seen_fort = true;
}
};
Game.things.stockade_from_south = {
name: "gate",
description: "stockade gate",
status: ["to north"],
location: 'outside_barracks',
dont_list_in_scroller: true,
active_verbs: ["enter"],
enter_to: "fort",
};
Longdesc.stockade_from_south = "A heavy hinged door in the stockade leads into some sort of \
military yard.";
STATE_SECRETS = [
"We hate the French",
"King George is particularly fond of spruces",
"Earl Grey tea is really just ordinary tea with turpentine in",
"Lady Hamilton buys her cakes at Marks and Spencer",
"Scotland isn't real",
"Those curly white hairstyles the lords have are actually wigs",
"We're thinking of starting an imperialist war against another colonial power",
"The Empire exists to plunder resources from the global south",
"Benedict Arnold is a spy",
"We just make up the rules of cricket as we go along",
"Yorkshire pudding is actually from Lancashire"
];
add_rule('before', 'enter', 'stockade_from_south', function() {
if(!in_scope('private_cobb')) {
return false;
} else if(worn('greatcoat')) {
say('Private Cobb gives you a salute as you pass through.');
get_point_for('got_past_cobb');
return false;
} else {
say('Private Cobb blocks your way. "Sorry -- British soldiers only in there. \
Wouldn\'t want you stealin\' state secrets like \'' + pickOne(STATE_SECRETS) + '\'" -- \
he stops and puts a hand over his mouth. "Anyway, can\'t let you in."');
return true;
}
});
On_hold.push(function() {
set_active('egg', 'give', held('egg') && Game.things.private_cobb.mentioned_breakfast &&
in_scope('private_cobb'));
set_active('fungus', 'give', held('fungus') && Game.things.private_cobb.mentioned_breakfast &&
in_scope('private_cobb'));
});
add_rule('before', 'give', 'egg', function() {
say('(to ' + name('private_cobb') + ')');
hide('egg');
Game.things.private_cobb.has_egg = true;
if(!Game.things.private_cobb.has_mushrooms) {
say(the_thing('private_cobb', true) + ' grabs the egg eagerly. "Coo, ta!" he says. \
"Now if only I \'ad some mushrooms, I could get a proper fry-up on."');
say('He puts the egg down next to his cooking-fire.');
bring('egg');
} else {
say(the_thing('private_cobb', true) + ' grabs the egg eagerly. "Coo, ta!" he says. \
"Now for a proper fry-up!"');
do_fryup();
}
return true;
});
add_rule('before', 'give', 'fungus', function() {
say('(to ' + name('private_cobb') + ')');
hide('fungus');
Game.things.private_cobb.has_mushrooms = true;
if(!Game.things.private_cobb.has_egg) {
say(the_thing('private_cobb', true) + ' grabs the fungus eagerly. "Coo, ta, real mushrooms!" \
he says. "Now if only I \'ad an egg, I could get a proper fry-up on."');
say('He puts the fungus down next to the cooking-fire.');
bring('fungus');
} else {
say(the_thing('private_cobb', true) + ' grabs the fungus eagerly. "Coo, ta, real mushrooms!" \
he says. "Now for a proper fry-up!"');
bring('fungus');
do_fryup();
}
return true;
});
function do_fryup() {
say('He tosses the egg and fungus into the frying pan, pokes them \
around with a stick for about twenty seconds, then declares: "Done!"');
say('But something happens. The egg wobbles and cracks. A baby crocodile emerges, leaps at ' +
the_thing('private_cobb') + ' and bites him on the nose.');
say(the_thing('private_cobb', true) + ' runs away crying. The baby crocodile scarfs down the \
bacon, then scurries after him.');
hide('private_cobb');
hide('egg');
hide('bacon');
add_status('fungus', 'in frying pan');
get_point_for('got_past_cobb');
// it does NOT, however, scarf down the mushrooms!
};
Game.things.cooking_fire = {
location: "outside_barracks",
is_fire: true,
};
Longdesc.cooking_fire = "A small fire, just about big enough to cook breakfast on.";
Game.things.frying_pan = {
status: ["over fire"],
portable: true,
location: "outside_barracks",
};
Longdesc.frying_pan = "A cast-iron frying-pan with considerable weight and heft.";
Game.things.bacon = {
indefinite: "some bacon",
status: ["in frying pan"],
portable: true,
edible: true,
location: "outside_barracks",
};
Longdesc.bacon = "A couple of strips of cheap streaky bacon, fried to a golden black.";
Game.things.private_cobb = {
name: "soldier",
description: "British soldier",
met_name: "Private Cobb",
met_description: "Private Cobb",
is_alive: true,
pronouns: male_pronouns,
location: "outside_barracks",
active_verbs: ["talk"],
image: 'res/img/private-cobb.png',
conversifier: function() {
return conv_cobb();
}
};
add_rule('before', 'take', 'bacon', function() {
return cobb_wont_let('bacon');
});
add_rule('before', 'take', 'egg', function() {
return cobb_wont_let('egg');
});
add_rule('before', 'take', 'fungus', function() {
return cobb_wont_let('fungus');
});
add_rule('before', 'take', 'frying_pan', function() {
return cobb_wont_let('frying_pan');
});
function cobb_wont_let(thing) {
if(in_scope('private_cobb')) {
say("Private Cobb won\'t let you.");
return true;
}
remove_status(thing, 'in frying pan');
return false;
}
Longdesc.private_cobb = "A wretched-looking British squaddie clad in a frayed pith helmet, a shabby \
red coat, trousers that may once have been white, and about one and a half boots. He sits over \
his frying-pan, occasionally prodding at some bacon with a dry stick.";
function conv_cobb() {
var conv = {};
conv.asks = {
himself: function() {
say(the_thing('private_cobb', true) + ' raises a hand to his temple. \"Horace \'Corny\' \
Cobb, Private, King\'s Ninth Blunderbusseers. Born in a slum in Bickering, joined up \
\'cause they \'ad nice coats and I\'d run out. Two more years of shootin\' people \
then I can go \'ome an\' maybe write a book or something. \'Course, I\'ll \'ave to \
learn to read first."');
meet('private_cobb');
},
stockade: function() {
say('"We were posted here because it was gonna become strategically important in some \
colonial war with... oh, probably France." ' + the_thing('private_cobb', true) +
' scratches his chin. "But we\'ve had no orders in months. Honestly, I reckon the \
Colonel would\'ve taken us \'ome by now, except he likes the fishing."');
Game.things.private_cobb.mentioned_colonel = true;
},
food: function() {
say(the_thing('private_cobb', true) + '\'s eyes go a bit misty. "These are me last \
rashers o\' real bacon," he says. "Been keepin\' \'em in the soles o\' me boots ever \
since we left Bristol. Cripes, I wish I \'ad the rest o\' the bits to make a proper \
breakfast. Bacon, eggs, mushrooms..." He sighs, wipes his chin, and contemplates the \
blackened strips. "I know they\'re overdone already, but when I eat \'em, they\'ll be \
gone..."');
Game.things.private_cobb.mentioned_breakfast = true;
}
}
return conv;
};
Game.rooms.fort = {
description: "You're in a British fort.",
directions: {
out: "outside_barracks",
}
};
Game.things.soldiers = {
location: "fort",
name: "soldiers",
description: "soldiers",
is_alive: true,
is_plural: true,
pronouns: plural_pronouns,
active_verbs: ["talk"],
always: function() {
do_soldiers();
}
};
Longdesc.soldiers = "Men wearing red coats in various states of disrepair -- that goes for the men \
and the coats -- mill around, walk from one tent to another, polish their rifles, \
practise their marching and so on, all looking somewhat miserable about it.";
add_rule('before', 'talk', 'soldiers', function() {
say("They're too busy.");
return true;
});
add_rule('before', 'talk', 'soldiers_in_tent', function() {
say("They're too busy.");
return true;
});
Game.things.soldiers_in_tent = {
location: "soldiers_tent",
name: "soldiers",
description: "soldiers",
is_alive: true,
is_plural: true,
pronouns: plural_pronouns,
active_verbs: ["talk"],
};
Longdesc.soldiers = "Men wearing red coats in various states of disrepair -- that goes for the men \
and the coats -- mill around, walk from one tent to another, polish their rifles, \
practise their marching and so on, all looking rather glum about it.";
Longdesc.soldiers_in_tent = "Men wearing red coats in various states of disrepair -- that goes for the men \
and the coats -- mill around, walk ina nd out of the tent, polish their rifles, \
practise their marching and so on, all looking rather glum about it.";
add_rule('before', 'talk', 'soldiers', function() {
say("They're too busy.");
});
function do_soldiers() {
var man = pickOne([
"A young man ",
"An old man ",
"A man ",
"A boy ",
"A teenage boy ",
"A sergeant ",
"A private ",
"A squaddie ",
"A redcoat ",
"A soldier ",
"An old soldier ",
"A young soldier ",
"An officer ",
"A junior officer "]);
var desc = "";
if(!pick(2)) {
desc = pickOne([
"with a bandage over one eye ",
"with his arm in a sling ",
"in a pith helmet ",
"with a bad moustache ",
"with side-whiskers "])
}
var doesThing = pickOne(Game.hero_location=='soldiers_tent' ? [
"walks into the tent",
"leaves the tent",
"goes to sleep on one of the bunks",
"gets up from one of the bunks",
"falls onto one of the bunks and starts crying",
"cleans his musket",
"rattles his sabre"
]: [
"emerges from the shabby tent",
"walks into the shabby tent",
"practices a few drill steps",
"polishes his boots",
"cleans his musket",
"rattles his sabre"
]);
say(man + desc + doesThing + ".");
};
Game.always.push(function() { // hotfix
if(!Game.vars.fixed_tower) {
Game.rooms.tower_top.description = "You're at the top of a wooden lookout tower.";
Game.vars.fixed_tower = true;
}
});
Game.things.tower = {
description: "watch tower",
name: "tower",
location: "fort",
active_verbs: ["climb"],
climb_to: "tower_top",
};
Longdesc.tower = "A wooden lookout tower, somewhat rickety. A union jack flies from the top.";
Game.rooms.tower_top = {
description: "You're at the top of a wooden lookout tower.",
directions: {
down: "fort",
},
}
Game.things.british_flag = {
name: "union jack",
description: "union jack",
//portable: true,
location: "tower_top",
};
Longdesc.british_flag = "The British flag -- the red cross of England superimposed over the white \
cross of Scotland, with a bit of space left over for any pieces of other countries that might be \
assimilated in the future. Whether it\'s really a \"jack\" if it\'s not on a ship is one of the \
most heated and tedious debates in vexillology.";
Game.things.fancy_tent = {
location: "fort",
enter_to: "colonels_tent",
active_verbs: ["enter"],
};
Longdesc.fancy_tent = "A nice silk tent, cubical with a slightly pointed roof. Warm lamplight comes from inside.";
Game.things.shabby_tent = {
location: "fort",
active_verbs: ["enter"],
enter_to: "soldiers_tent",
};
Longdesc.shabby_tent = "A long, low, patchy canvas tent. The door-flap waves in the breeze.";
Game.rooms.soldiers_tent = {
description: "You're in a cramped, plain canvas tent.",
directions: {
out: "fort",
}
};
Game.things.bunks = {
location: "soldiers_tent",
};
Longdesc.bunks = "A couple of dozen narrow wooden campbeds are squeezed against the back wall of \
the tent. Some of them have soldiers sleeping in them.";
Game.things.ironing_board = {
name: "ironing board",
description: "ironing board",
location: "soldiers_tent"
};
Longdesc.ironing_board = "A wooden board covered with fabric, on which the soldiers forget to \
press their uniforms. The iron itself lies nearby, and is already hot.";
On_hold.push(function() {
for(var i in Game.things) {
set_active(i, 'iron', Game.things[i].ironable && !worn(i) && in_scope(i) && in_scope('ironing_board'));
}
});
Game.things.tea = {
name: "tea",
description: "cup of tea",
location: "colonels_tent",
status: ["on desk"],
portable: true,
drinkable: true,
active_when_carried: ["drink"],
};
Longdesc.tea = "A bone-china cup containing finest Indian tea, polluted with a dash of milk.";
add_rule('before', 'examine', 'tea', function() {
if(!Game.things.tea.poisoned) {
Longdesc.tea = "A bone-china cup containing finest Indian tea, polluted with a dash of milk.";
} else {
Longdesc.tea = "A bone-china cup containing finest Indian tea, polluted with a dash of milk. \
It smells a little sweet, and a little bitter.";
}
});
add_rule('after', 'drink', 'tea', function() {
var loc = Game.hero_location;
revive('Think ye drank some poison tea.', [loc]);
});
On_hold.push(function() {
set_active('berries', 'put_in_tea', held('berries') && in_scope('tea') && !carried('tea'));
set_active('paper', 'dip_in_tea', held('paper') && !Game.things.paper.stained && in_scope('tea'));
});
add_rule('before', 'dip_in_tea', 'paper', function() {
if(!Game.things.paper.stained) {
say('You dip the paper in the tea. It turns a light brown colour.');
get_point_for('tea_dipped');
Game.things.paper.stained = true;
if(Game.things.paper.ironed) {
say('It seems you can now make out a drawing on the paper...');
}
} else {
say('You dip the paper in the tea. It has no further effect.');
}
return true;
});
add_rule('before', 'take', 'tea', function() {
if(in_scope('colonel')) {
say(the_thing('colonel', true) + " rounds on you, and for one moment looks genuinely \
threatening. \"You may defy us,\" he growls. \"You may mock us. You may spread \
ghastly untruths about our dental hygiene. But you -- will -- not -- take -- our -- \
tea!\"");
say('He snatches the cup back, takes a sip, and calms down.');
return true;
}
remove_status('tea', 'on desk');
return false;
});
add_rule('before', 'put_in_tea', 'berries', function() {
say((in_scope('colonel') ? 'While the colonel looks away briefly, you slip' : 'You put') + ' the berries into the tea. They dissolve \
without trace.');
Game.things.tea.poisoned = true;
get_point_for('poisoned_tea');
hide('berries');
if(carried('tea')) {
hold('tea');
}
return true;
});
Game.rooms.colonels_tent = {
description: "You're in a clean, spacious silk tent",
directions: {
out: "fort",
},
description: "You're in a fancy-looking army tent.",
};
Game.things.fishing_gear = {
location: "colonels_tent"
};
Longdesc.fishing_gear = "An enormous shoulderbag out of which are poking various rods, lines, nets, \
sinkers, hooks, floats... you know what, this is just a list of fishing words. You've no idea \
what any of those things look like. But it's a safe bet that this is a bag of fishing things, \
because the flap is embroidered \"Colonel Crumpington's Fishing Gear\".";
Game.things.persilla = {
name: "fish",
description: "fish",
met_name: "Persilla",
met_desc :"Princess Persilla",
status: ["on wall"],
always: function() {
do_persilla()
},
location: "colonels_tent",
portable: "true",
conversifier: function() {
return conv_persilla()
},
needs_conch: true,
pronouns: neuter_pronouns,
met_pronouns: female_pronouns
};
add_rule('before', 'examine', 'persilla', function() {
if(!Game.things.persilla.met) {
if(has_status('persilla', 'on wall')) {
Longdesc.persilla = "An impressively big fish of uncertain species, with scintillating green scales. \
It is hooked to the wall, and appears to be struggling occasionally.";
} else {
Longdesc.persilla = "An impressively big fish of uncertain species, with scintillating green scales.";
}
} else {
Longdesc.persilla = "Princess Persilla is one of the one-in-four mermaids who appear entirely fishlike. \
She is struggling slightly, and breathing with difficulty.";
}
});
function conv_persilla() {
var conv = {};
conv.start_conversation = function() {
if(has_status('persilla', 'on wall')) {
say('"Get me out of here!" says ' + the_thing('persilla'));
if(in_scope('colonel') && !Game.things.colonel.said_fishnotdead) {
say('"I don\'t think it\'s quite dead yet. Persistent little blighter, what?" \
chuckles ' + the_thing('colonel'));
Game.things.colonel.said_fishnotdead = true;
}
} else {
say(the_thing('persilla', true) + ' looks at you with a piscine stare.');
}
}
conv.asks = {};
if(!Game.things.persilla.met) {
conv.asks.itself = function() {
say('"I am Princess Persilla of the Great Underwater Empire and I demand to be returned to my \
people!" says the fish.');
meet('persilla');
confuse_colonel();
}
} else {
conv.asks.herself = function() {
say('"I am Princess Persilla of the Great Underwater Empire and I demand to be \
returned to my people!" says Persilla.');
confuse_colonel();
}
}
if(Game.things.mermaid.mentioned_sister) {
conv.asks.sister = function() {
say('"Oh, she always worries about me," says ' + the_thing('persilla') + '. "Although on this \
occasion, she may be correct to do so."');
confuse_colonel();
}
}
conv.asks.colonel = function() {
if(in_scope('colonel')) {
say(the_thing('persilla', true) + ' glares at ' + the_thing('colonel') + ' as best ' +
pronoun('persilla', 0) + ' can from her position. "I thought he liked me," ' +
pronoun('persilla', 0) + ' says. "Turns out he just wanted to get me on the wall."');
} else {
say('"I thought he liked me," says ' + the_thing('persilla') + '. \
"Turns out he just wanted to get me on the wall."');
}
}
return conv;
}
function confuse_colonel() {
if(in_scope('colonel')) {
var txt = the_thing('colonel', true);
if(!pick(3)) {
txt += pickOne([
' scratches his head. ',
' looks perplexed. ',
'\'s eyes bulge. ',
' looks confused. '
]);
} else {
txt += ' says, '
}
txt += '"' + pickOne([
"Who are you talking to?",
"Are you attempting to have a conversation with that fish?",
"I'm afraid it can't speak.",
"I say, please do not talk to the fish.",
"Oh, you won\'t get an answer. You see, it\'s quite stand-offish! Little joke, there.",
"Are you all right?",
"It looks like you're trying to talk to a fish. Would you like some help?"
]) + '"';
}
}
add_rule('before', 'take', 'persilla', function() {
if(in_scope('colonel')) {
say('The colonel won\'t let you. "I\'m glad you\'re a fellow fish-appreciator, " \
he says, "but I really can\'t have you stealing my prize catch."');
return true;
}
remove_status('persilla', 'on wall');
return false;
});
add_rule('after', 'take', 'persilla', function() {
remove_status('persilla', 'on wall');
});
On_hold.push(function() {
do_talk_persilla();
});
function do_talk_persilla() {
set_active('persilla', 'talk', held('conch'));
}
function do_persilla() {
if(has_status('persilla', 'on_wall') && !pick(3)) {
if(!held('conch')) {
say(pickOne([
'A sad gasping sound comes from the fish on the wall.',
'A quiet wailing sound comes from the fish on the wall.']));
if(in_scope('colonel') && !Game.things.colonel.said_fishnotdead) {
say('"I don\'t think it\'s quite dead yet. Persistent little blighter, what?" \
chuckles ' + the_thing('colonel'));
Game.things.colonel.said_fishnotdead = true;
}
} else {
say('"Get me out of here!" cries the fish.');
if(in_scope('colonel')) {
say(the_thing('colonel', true) + ' seems not to notice.');
}
}
return;
}
if(!pick(3) && held('conch') && !hero_location().underwater &&
Game.hero_location != 'bottom_of_swamp' && !pick(3)) {
say(the_thing('persilla', true) + ' speaks: "Get me back to the sea at once!"');
}
set_active('persilla', 'put_in_sea', hero_location().is_coastal);
if(in_scope('mermaid')) {
say(the_thing('mermaid', true) + ' sees ' + the_thing('persilla') + ' and gives a screech of \
joy. She limps up, takes her sister in her arms for a hug, then puts her in the sea. ' +
the_thing('persilla', true) + ' swims away happily.');
if(held('conch')) {
say('"Thanks," says ' + the_thing('mermaid') + '. "Here." She slither-walks in your \
direction, and kisses you on the forehead. "You\'re now a friend of the Great Underwater \
Empire."');
} else {
say(the_thing('mermaid', true) + ' faces you and makes grateful noises. She slither-walks \
in your direction, and kisses you on the forehead. You have a strong feeling that the \
two of you are now friends.');
}
say("She jumps into the sea, and is gone.");
hide('mermaid');
hide('persilla');
Game.things.persilla.rescued = true;
get_point_for('rescued_persilla');
}
};
add_rule('before', 'put_in_sea', 'persilla', function() {
say("You toss " + the_thing('persilla') + " into the sea and " +
pronoun('persilla', 0) + " swims away happily.");
hide('persilla');
get_point_for('rescued_persilla');
Game.things.persilla.rescued = true;
return true;
});
Game.things.colonels_desk = {
name: "desk",
description: "mahogany desk",
location: "colonels_tent",
};
Longdesc.colonels_desk = "A large desk in varnished redwood, decorated with ornaments stolen \
from various cultures around the world.";
Game.things.colonel = {
name: "colonel",
description: "colonel",
location: "colonels_tent",
image: 'res/img/colonel.png',
met_name: "colonel",
met_description: "Colonel Crumpington",
active_verbs: ["talk"],
pronouns: male_pronouns,
is_alive: true,
conversifier: function() {
return conv_colonel();
},
always: function() {
return do_colonel();
}
};
Longdesc.colonel = 'A portly British artistocrat in a shining red coat and a ridiculous white wig. \
He stares at you with faint curiosity, as if he\'s waiting for you to do something interesting.';
function do_colonel() {
if(!pick(3) && in_scope('tea')) {
say('The colonel picks up the teacup and takes a sip.');
if(Game.things.tea.poisoned) {
say('He suddenly looks rather unwell.\n\
"Excuse me," he says, and runs out of the tent clutching his belly.');
hide_conversation();
hide('colonel');
}
}
};
function conv_colonel() {
var conv = {};
conv.start_conversation = '"How do you do?" says the colonel.';
conv.asks = {
himself: function() {
say('"Lieutenant-Colonel Sir Roderick Uxorius Wigbert Crumpington," he introduces himself. \
"Governor of this province, or I intend to be, if they ever decide whether they\'re making \
it a province. Meanwhile, well, at least it\'s warm, and there\'s good fishing. \
Not that there\'s anything wrong with Cambridgeshire," he adds sharply. "Nothing \
that a good roof wouldn\'t fix, anyway."');
},
fish: function() {
var txt = '"Fishing\'s always been a passion of mine, ever since I used to sneak out of my \
house at Eton to catch minnows in jam-jars.';
if(!Game.things.colonel.done_trout_gag) {
txt += ' Why, once I went down to the brook and saw this huge common trout -- \
so I told him to bog off because I wanted the space.';
Game.things.colonel.done_trout_gag = true;
}
if(has_status('persilla', 'on wall')) {
txt += '" He nods proudly at the fish on the tent wall. "My best ever catch. \
I caught that one round the southwest of the island. There\'s some fascinating \
sea life down that way."';
}
say(txt);
},
};
conv.tells = {};
if(Game.things.mermaid.mentioned_sister && Game.things.mermaid.mentioned_soldiers) {
conv.tells.mermaid = function() {
say(the_thing('colonel', true) + ' listens incredulously as you tell him about \
the mermaid looking for her sister. Then he bursts out laughing. "Oh yes, I\'ve heard \
plenty of stories from the men about mermaids. Also dragons, manticores, \
platypuses, sasquatches, gorillas, rhinoceroses... I put it down to the gin, you know."');
}
}
return conv;
}
/************************************************ utilities *****************************************/
function qq(str) {
return '"' + str + '"';
}
function Mathsign(n) { // IE doesn't support Math.sign
if(n>0) {
return 1;
} else if (n<0) {
return -1;
} else {
return 0
}
}
function capialise(str) {
if(str.length==0) { return ''; }
return str.charAt(0).toUppercase() + str.substring(1);
};
function get_reachable_rooms(room) {
//console.log('getting reachable rooms from ' + room)
if(!Game.rooms[room]) {
//console.log('there\'s no such room');
return [];
}
var reachable_rooms = [];
//console.log('checking directions from ' + room);
if(Game.rooms[room].directions) {
for(var i in Game.rooms[room].directions) {
reachable_rooms.push(Game.rooms[room].directions[i]);
}
}
for(var i in Game.things) {
if(location_of(i)==room && has_active_verb(i,'enter')) {
reachable_rooms.push(Game.things[i].enter_to);
}
if(location_of(i)==room && has_active_verb(i,'climb')) {
reachable_rooms.push(Game.things[i].climb_to);
}
if(location_of(i)==room && has_active_verb(i,'cross')) {
reachable_rooms.push(Game.things[i].cross_to);
}
}
return reachable_rooms;
}
function path_from(this_room, that_room, max_depth, ignore_rooms, path_so_far) {
if(!ignore_rooms) { ignore_rooms = [] };
if(!path_so_far) { path_so_far = [] };
//console.log('checking: reachable from ' + this_room + ' to ' + that_room + ' in ' + n);
//console.log('ignoring: ' + ignore_rooms.join(','));
if(!Game.rooms[that_room] || !Game.rooms[this_room]) {
return null; // false;
}
if(max_depth == 1) {
if(reachable_from(this_room, that_room)) {
return path_so_far.concat([this_room, that_room]); // yay!
} else {
return null;
}
}
if(ignore_rooms.indexOf(this_room)!=-1) {
return null;
}
var reachable_rooms = get_reachable_rooms(this_room);
//console.log('reachable rooms from ' + this_room + ' are: ' + reachable_rooms.join(', '));
if(reachable_rooms.indexOf(that_room)!=-1) {
console.log('and one of those is ' + that_room);
return path_so_far.concat([this_room, that_room]);
}
for(var i in reachable_rooms) {
if(ignore_rooms.indexOf(i)!=-1) {
continue;
}
ignore_rooms.push(this_room);
var test_path = path_from(reachable_rooms[i], that_room, max_depth - 1, ignore_rooms, [this_room]);
if(test_path) {
return path_so_far.concat(test_path);
}
//if(reachable_within(reachable_rooms[i], that_room, n - 1, ignore_rooms)) {
// return true;
//}
}
return null;
}
function reachable_within(this_room, that_room, n, ignore_rooms) {
if(!ignore_rooms) { ignore_rooms = [] };
//console.log('checking: reachable from ' + this_room + ' to ' + that_room + ' in ' + n);
//console.log('ignoring: ' + ignore_rooms.join(','));
if(!Game.rooms[that_room]) {
return false;
}
if(n == 1) {
return reachable_from(this_room, that_room);
}
if(ignore_rooms.indexOf(this_room)!=-1) {
return false;
}
var reachable_rooms = get_reachable_rooms(this_room);
if(reachable_rooms.indexOf(that_room)!=-1) {
return true;
}
for(var i in reachable_rooms) {
if(ignore_rooms.indexOf(i)!=-1) {
continue;
}
ignore_rooms.push(this_room);
if(reachable_within(reachable_rooms[i], that_room, n - 1, ignore_rooms)) {
return true;
}
}
return false;
}
function reachable_from(this_room, that_room) {
//console.log('reachable_from: checking if route from ' + this_room + ' to ' + that_room);
if(Game.rooms[this_room].directions) {
for(var i in Game.rooms[this_room].directions) {
if(Game.rooms[this_room].directions[i] == that_room) {
return true;
}
}
} //else console.log('this room has no directions');
for(var i in Game.things) {
if(Game.things[i].location==this_room && (
(has_active_verb(i, 'enter') && Game.things[i].enter_to == that_room) ||
(has_active_verb(i, 'climb') && Game.things[i].climb_to == that_room) ||
(has_active_verb(i, 'cross') && Game.things[i].cross_to == that_room)
)) {
return true;
}
}
return false;
}
function opposite_dir(dir) {
return ['north', 'east', 'south', 'west',
'northeast', 'southeast', 'southwest', 'northwest',
'up', 'down', 'in', 'out', 'aft', 'fore', 'starboard', 'port', 'somewhere'][
['south', 'west', 'north', 'east',
'southwest', 'northwest', 'northeast', 'southeast',
'down', 'up', 'out', 'in', 'fore', 'aft', 'port', 'starboard', 'away'].indexOf(dir)]
}
function the_dir(dir) {
return ['the north', 'the east', 'the south', 'the west',
'the northeast', 'the southeast', 'the southwest', 'the northwest',
'above', 'below', 'inside', 'afore', 'abaft', 'port', 'starboard', 'outside', 'somewhere'][
['north', 'east', 'south', 'west',
'northeast', 'southeast', 'southwest', 'northwest',
'up', 'down', 'in', 'fore', 'aft', 'port', 'starboard', 'out', 'away'].indexOf(dir)];
}
function dirwards(dir) {
return ['north', 'east', 'south', 'west',
'northeast', 'southeast', 'southwest', 'northwest',
'upwards', 'downwards', 'inside', 'outside', 'to fore', 'to aft', 'to port', 'to starboard', 'somewhere'][
['north', 'east', 'south', 'west',
'northeast', 'southeast', 'southwest', 'northwest',
'up', 'down', 'in', 'out', 'fore', 'aft', 'port', 'starboard', 'away'].indexOf(dir)];
}
function the_opposite_dir(dir) {
return the_dir(opposite_dir(dir));
}
function meet(npc) {
Game.things[npc].met = true;
Game.things[npc].name = Game.things[npc].met_name;
Game.things[npc].description = (Game.things[npc].met_description ? Game.things[npc].met_description : Game.things[npc].met_name);
Game.things[npc].proper_name = true;
if(Game.things[npc].met_pronouns) {
Game.things[npc].pronouns = Game.things[npc].met_pronouns;
}
}
// move metacommands buttons on resize
$(window).resize(function() {
move_metacommands();
set_heights();
//animate_heights();
});
$(document).ready(function() {
move_metacommands();
});
function move_metacommands() {
if(false && is_landscape()) {
$("#save_load_container").detach().appendTo('#left-column');
$("#save_load_container").css('margin-top', '');
} else {
$("#save_load_container").detach().appendTo('#savefix'); // '#right-column');
$("#save_load_container").css('margin-top', '20px');
}
}
function hide_splash() {
$('#splashscreen').fadeOut();
//do_room_music(true);
}
function list_missing_longdescs() {
var txt = 'No longdesc for:';
for(var thing in Game.things) {
if(!Longdesc[thing]) {
txt += '\n' + thing;
}
}
console.log(txt);
}
function deepCopy(obj) {
return JSONfn.parse(JSONfn.stringify(obj));
}