if (navigator.appName === "DOjS") {
var TEXT_COLOR = "#35FF02";
var COMMAND_SEPARATOR = " - ";
var ACTION_HIGHLIGHT = "#ff3502";
var CMD_CLEAR = "<BACK>";
var CMD_ENTER = "<ENTER>";
var CMD_INVENTORY = "INVENTORY";
var TXT_NOTHING = ["You see nothing special"];
var TXT_CANTGO = ["You can't go there!"];
var TXT_WHAT = ["I don't understand you!"];
var con, actions, cmdline;
var BEDROOM_ALARMCLOCK = "alarmclock";
var BEDROOM_SLIPPERS = "slippers";
var BEDROOM_BATHROBE = "bathrobe";
var BEDROOM_LIGHT_SWITCH = "light switch";
var BEDROOM_WINDOW = "window";
text: function (cmd, room) {
if (room.objects.introduction) {
"Screen reader support: Press SPACE to confirm a selection.",
"Press T for the current rooms text. Press R to toggle reading actions.",
"Two month ago you've started your new job at a space station.",
"The first days were very exciting.",
"Everything was new, everything was different than at your previous jobs.",
"Meanwhile, you already have your routines and a structured day.",
"At some time in the morning your alarm clock will ring, you'll get up",
"and after getting ready you'll start your assigned tasks for the day.",
"But some days will break these routines and so will today...",
room.objects.introduction = false;
txt.push("You are barely awake in your bedroom.");
if (room.objects.alarmclock) {
txt.push("The alarmclock is ringing.");
txt.push("!!! RING !!!");
if (room.objects.light) {
txt.push("The lights are on.");
if (room.objects.alarmclock) {
txt.push("!!! RING !!!");
txt.push("There is a door to the east.");
if (room.objects.alarmclock) {
txt.push("!!! RING !!!");
txt.push("The room is pitch black beside an illuminated light switch.");
if (room.objects.alarmclock) {
txt.push("!!! RING !!!");
look: function (cmd, room) {
if (!room.objects.light) {
return ["It is to dark, you can't see anything new"];
"On one wall is a window to the outside.",
if (room.objects.alarmclock) {
txt.push("The alarmclock on your bedside table is ringing.");
txt.push("!!! RING !!!");
txt.push("There is a roughed up alarmclock on your bedside table.");
if (room.objects.slippers) {
txt.push("Your slippers are on the floor in front of your bed.");
if (room.objects.bathrobe) {
txt.push("Your bathrobe hangs on a hook on the wall.");
use: function (cmd, room) {
if (cmd.length === 2 && cmd[1] === BEDROOM_LIGHT_SWITCH) {
room.objects.light = !room.objects.light;
return ["You toggle the light switch"];
} else if (cmd.length === 2 && cmd[1] === BEDROOM_ALARMCLOCK) {
room.objects.alarmclock = false;
return ["You give your alarm clock a hearty smack on the button..."];
} else if (cmd.length === 2 && cmd[1] === BEDROOM_WINDOW) {
"Even though you are still very sleepy you realize it is",
"a VERY BAD idea to air the room in a space station.",
take: function (cmd, room) {
if (cmd.length === 2 && cmd[1] === BEDROOM_SLIPPERS) {
room.objects.slippers = false;
return ["You put on your slippers"];
} else if (cmd.length === 2 && cmd[1] === BEDROOM_BATHROBE) {
room.objects.bathrobe = false;
return ["You put on the bathrobe"];
walk: function (cmd, room) {
if (!room.objects.light) {
return ["You can't go anywhere, it is to dark!"];
return ["You refuse to run around the space station with bare feet."];
"You can't run around the space station stark naked.",
"What would the neighbours think!?",
if (cmd[0] === CMD_EAST) {
if (room.objects.alarmclock) {
"Do you really want to annoy your neighbors",
"by letting the alarm sound indefinitely?"
setNewRoom(space_hallway);
return ["You walk through the door into the hallway..."];
take_words: function (cmd, room) {
if (room.objects.light) {
if (room.objects.slippers) {
ret.push(BEDROOM_SLIPPERS);
if (room.objects.bathrobe) {
ret.push(BEDROOM_BATHROBE);
use_words: function (cmd, room) {
var ret = [BEDROOM_LIGHT_SWITCH, BEDROOM_ALARMCLOCK];
if (room.objects.light) {
ret.push(BEDROOM_WINDOW);
var HALLWAY_SPACESUIT = "space suit";
var HALLWAY_SPACEHELMET = "space helmet";
var HALLWAY_LOCKER = "locker";
var HALLWAY_TOOLBOX = "toolbox";
var HALLWAY_NEWSPAPER = "newspaper";
text: function (cmd, room) {
person.toilet_used && person.hair_combed && person.teeth_brushed &&
person.drank_coffee && person.eaten_toast && person.eaten_banana;
"There are doors on the north, south, west and on the east.",
look: function (cmd, room) {
var txt = ["There is a locker in one corner of the hallway."];
if (room.objects.locker) {
if (room.objects.toolbox) {
txt.push("You can see a toolbox and lots of junk inside the locker.");
txt.push("You can see a lot of junk inside the locker.");
txt.push("The locker is closed.");
if (room.objects.space_helmet) {
txt.push("There is a space helmet on the wardrobe.");
if (room.objects.space_suit) {
txt.push("There is a space suit on the wardrobe.");
if (room.objects.newspaper) {
"A newspaper is on the floor below the mail slot in the door."
use: function (cmd, room) {
if (cmd.length === 2 && cmd[1] === HALLWAY_LOCKER) {
room.objects.locker = !room.objects.locker;
if (room.objects.locker) {
return ["You open the locker"];
return ["You close the locker"];
} else if (cmd.length === 2 && cmd[1] === HALLWAY_NEWSPAPER) {
return ["You stand in the hallway and flip through the newspaper."];
take: function (cmd, room) {
if (cmd.length === 2 && cmd[1] === HALLWAY_NEWSPAPER) {
putInventory(HALLWAY_NEWSPAPER);
room.objects.newspaper = false;
return ["You take the newspaper."];
} else if (cmd.length === 2 && cmd[1] === HALLWAY_SPACEHELMET) {
person.space_helmet = true;
room.objects.space_helmet = false;
return ["You put on the space helmet"];
"You still need to finish you morning routine before dressing up for work.",
} else if (cmd.length === 2 && cmd[1] === HALLWAY_SPACESUIT) {
person.space_suit = true;
room.objects.space_suit = false;
return ["You put on the space suit"];
"You still need to finish you morning routine before dressing up for work.",
} else if (cmd.length === 2 && cmd[1] === HALLWAY_TOOLBOX) {
if (person.broken_toilet) {
putInventory(HALLWAY_TOOLBOX);
room.objects.toolbox = false;
return ["That toolbox might be handy to fix the broken toilet."];
"Most people don't haul toolboxes around when doing their morning routine.",
walk: function (cmd, room) {
if (cmd[0] === CMD_WEST) {
setNewRoom(space_bedroom);
return ["You walk through the door into the bedroom."];
} else if (cmd[0] === CMD_NORTH) {
setNewRoom(space_bathroom);
return ["You walk through the door into the bathroom."];
} else if (cmd[0] === CMD_SOUTH) {
if (person.toilet_used) {
setNewRoom(space_kitchen);
return ["You walk through the door into the kitchen."];
"You have VERY urgent business on the bathroom ",
"before going into the kitchen."
} else if (cmd[0] === CMD_EAST) {
if (person.space_suit && person.space_helmet) {
setNewRoom(space_finish);
"You close the visor of the helmet and leave your apartment for work."
return ["You need to put on your work clothes before leaving the apartment."];
take_words: function (cmd, room) {
if (room.objects.space_helmet) {
ret.push(HALLWAY_SPACEHELMET);
if (room.objects.space_suit) {
ret.push(HALLWAY_SPACESUIT);
if (room.objects.newspaper) {
ret.push(HALLWAY_NEWSPAPER);
if (room.objects.toolbox && room.objects.locker) {
ret.push(HALLWAY_TOOLBOX);
use_words: function (cmd, room) {
var BATHROOM_TOILET = "toilet";
var BATHROOM_TOOTHBRUSH = "toothbrush";
var BATHROOM_TOOTHPASTE = "toothpaste";
var BATHROOM_COMB = "comb";
var BATHROOM_MIRROR = "mirror";
text: function (cmd, room) {
return ["You are in standard space station bathroom."];
look: function (cmd, room) {
"In the corner is a vacuum toilet for space usage.",
"There is a mirror on the wall.",
if (room.objects.toothpaste) {
ret.push("Below the mirror you see a comb, a toothbrush and some toothpaste.");
ret.push("Below the mirror you see a comb and a toothbrush.");
use: function (cmd, room) {
if (cmd.length === 2 && cmd[0] === CMD_USE && cmd[1] === BATHROOM_MIRROR) {
var ret = ["You see yourself in the mirror"];
if (!person.hair_combed) {
"Your hair looks like you participated in a nuclear explosion."
ret.push("Mmmh, what nice hair!");
if (!person.teeth_brushed) {
"Half of yesterdays dinner is still located in your interdental spaces."
ret.push("You are blinded by the glitter of your teeth.");
} else if (cmd.length === 2 && cmd[1] === HALLWAY_NEWSPAPER) {
return ["You stand in the bathroom and flip through the newspaper."];
} else if (cmd.length === 2 && cmd[1] === BATHROOM_TOOTHBRUSH) {
"Scrubbing away at your teeth with just the brush would not yield",
} else if (cmd.length === 2 && cmd[1] === BATHROOM_COMB) {
if (person.hair_combed) {
return ["Every hair on your head is in the exact location it was meant to be.",];
person.hair_combed = true;
return ["You groom your hair thoroughly like you were Rapunzel."];
} else if (cmd.length === 2 && cmd[1] === BATHROOM_TOILET) {
if (room.objects.toilet_repaired) {
return ["You will need some distraction during your usually long toilet sessions.",];
person.broken_toilet = true;
"You try to turn on the vacuum toilet, but there are weird sounds",
"from the pump. Seems like the toilet is broken!",
} else if (checkCombination(cmd, BATHROOM_MIRROR, BATHROOM_TOOTHPASTE)) {
return ["It would be very childish to smear toothpaste on the mirror, wouldn't it?",];
} else if (checkCombination(cmd, BATHROOM_TOILET, BATHROOM_TOOTHBRUSH)) {
return ["EEEEEeeeeewwwwwwwwww!"];
} else if (checkCombination(cmd, BATHROOM_TOILET, HALLWAY_NEWSPAPER)) {
if (room.objects.ass_cleaned) {
return ["Even space contains more mater than your bovels right now!"];
if (room.objects.toilet_repaired) {
if (!room.objects.bovel_movement) {
room.objects.bovel_movement = true;
room.objects.ass_cleaned = true;
person.toilet_used = true;
delInventory(HALLWAY_NEWSPAPER);
return ["You wipe your ass with the newspaper."];
person.broken_toilet = true;
"You try to turn on the vacuum toilet, but there are weird sounds",
"from the pump. Seems like the toilet is broken!",
} else if (checkCombination(cmd, BATHROOM_TOILET, HALLWAY_TOOLBOX)) {
if (room.objects.toilet_repaired) {
"The toilet is working again.",
"Fiddling with it some more will most probably only break it again.",
room.objects.toilet_repaired = true;
delInventory(HALLWAY_TOOLBOX);
"You hammer away at the pump until it is working flawlessly.",
} else if (checkCombination(cmd, BATHROOM_TOOTHBRUSH, BATHROOM_TOOTHPASTE)) {
if (person.teeth_brushed) {
return ["Your teeth won't get whiter than white."];
person.teeth_brushed = true;
delInventory(BATHROOM_TOOTHPASTE);
"You have a minty explosion in your mouth as you brush your teeth.",
take: function (cmd, room) {
if (cmd.length === 2 && cmd[1] === BATHROOM_TOOTHPASTE) {
putInventory(BATHROOM_TOOTHPASTE);
room.objects.toothpaste = false;
return ["You take the toothpaste."];
walk: function (cmd, room) {
if (cmd[0] === CMD_SOUTH) {
if (room.objects.bovel_movement && !room.objects.ass_cleaned) {
"You should clean your bum first before leaving the bathroom!",
setNewRoom(space_hallway);
return ["You walk through the door into the hallway."];
take_words: function (cmd, room) {
if (room.objects.toothpaste) {
return [BATHROOM_TOOTHPASTE];
use_words: function (cmd, room) {
var KITCHEN_EGGLICATOR = "egglicator";
var KITCHEN_TOASTYNATOR = "toastynator";
var KITCHEN_COFFEEMACHINE = "coffee machine";
var KITCHEN_FRUITCHUTE = "fruitchute";
var KITCHEN_PLATE = "plate";
var KITCHEN_PLATE_WITH_TOAST = "plate with toast";
var KITCHEN_PLATE_WITH_TOAST_EGG = "plate with toast and egg";
var KITCHEN_CUP_OF_COFFEE = "cup of coffee";
var KITCHEN_BANANA = "banana";
text: function (cmd, room) {
return ["This is a fully automated space station kitchen."];
look: function (cmd, room) {
"On the wall there is a nutrition plan for astronauts.",
"It reads: 'BREAKFAST - One toast with fried eggs, a coffe with milk",
"and a banana'. There is a slit on the wall labeled 'toastynator'.",
"There is a recess labled 'egglicator'. You see a coffee machine.",
"A pipe with an opening comes down from the ceiling, labeled 'fruitchute'.",
"A shelf with plates, cups and cutlery is on the wall.",
"In the north there is the door to the hallway."
use: function (cmd, room) {
if (cmd.length === 2 && cmd[1] === KITCHEN_TOASTYNATOR) {
return ["The toastynator makes a buzzing error sound."];
} else if (cmd.length === 2 && cmd[1] === KITCHEN_EGGLICATOR) {
return ["The egglicator makes a cackling error sound."];
} else if (cmd.length === 2 && cmd[1] === KITCHEN_COFFEEMACHINE) {
return ["The coffee machine makes a gurgling error sound."];
} else if (cmd.length === 2 && cmd[1] === KITCHEN_FRUITCHUTE) {
if (room.objects.banana) {
putInventory(KITCHEN_BANANA);
room.objects.banana = false;
return ["The fruitchute procures a nice, yellow banana."];
return ["The fruitchute has a constipation. I asume from to many bananas."];
} else if (cmd.length === 2 && cmd[1] === KITCHEN_PLATE_WITH_TOAST) {
return ["Dry toast without anything would get stuck in your throat."];
} else if (cmd.length === 2 && cmd[1] === KITCHEN_BANANA) {
delInventory(KITCHEN_BANANA);
person.eaten_banana = true;
return ["You skin and eat the banana. You feel banananized now."];
} else if (cmd.length === 2 && cmd[1] === KITCHEN_CUP_OF_COFFEE) {
person.drank_coffee = true;
delInventory(KITCHEN_CUP_OF_COFFEE);
return ["You carefully drink the hot coffee and you are wide awake now."];
} else if (cmd.length === 2 && cmd[1] === KITCHEN_PLATE_WITH_TOAST_EGG) {
person.eaten_toast = true;
delInventory(KITCHEN_PLATE_WITH_TOAST_EGG);
return ["You chew on your tasty toast and egg. Space chickens are the best..."];
} else if (checkCombination(cmd, KITCHEN_PLATE, KITCHEN_TOASTYNATOR)) {
room.objects.toast = false;
delInventory(KITCHEN_PLATE);
putInventory(KITCHEN_PLATE_WITH_TOAST);
return ["The toastynator ejects a warm, brown toast onto the plate."];
} else if (checkCombination(cmd, KITCHEN_TOASTYNATOR, KITCHEN_PLATE_WITH_TOAST)) {
return ["The toastynator refuses to put toast on toast."];
} else if (checkCombination(cmd, KITCHEN_PLATE, KITCHEN_EGGLICATOR)) {
return ["Eggs MUST be placed on toasts, this is required by space law!",];
} else if (checkCombination(cmd, KITCHEN_PLATE_WITH_TOAST, KITCHEN_EGGLICATOR)) {
room.objects.egg = false;
delInventory(KITCHEN_PLATE_WITH_TOAST);
putInventory(KITCHEN_PLATE_WITH_TOAST_EGG);
return ["The egglicator egglicates a fried egg onto your toast."];
} else if (checkCombination(cmd, KITCHEN_PLATE_WITH_TOAST_EGG, KITCHEN_EGGLICATOR)) {
return ["The egglicator can not egglicate eggs on eggs."];
} else if (checkCombination(cmd, KITCHEN_CUP_OF_COFFEE, KITCHEN_COFFEEMACHINE)) {
"The advanced remote fluid level sensor of the coffee machine",
"prevents your cup from overflowing to the floor!"
} else if (checkCombination(cmd, KITCHEN_CUP, KITCHEN_COFFEEMACHINE)) {
delInventory(KITCHEN_CUP);
putInventory(KITCHEN_CUP_OF_COFFEE);
"The coffee machine hisses and steams to produce a steaming coffee",
"with creamy space milk."
take: function (cmd, room) {
if (cmd.length === 2 && cmd[1] === KITCHEN_PLATE) {
putInventory(KITCHEN_PLATE);
room.objects.plate = false;
return ["You take a plate."];
} else if (cmd.length === 2 && cmd[1] === KITCHEN_CUP) {
putInventory(KITCHEN_CUP);
room.objects.cup = false;
return ["You take a cup."];
walk: function (cmd, room) {
if (cmd[0] === CMD_NORTH) {
setNewRoom(space_hallway);
return ["You walk through the door into the hallway."];
take_words: function (cmd, room) {
if (room.objects.plate) {
use_words: function (cmd, room) {
text: function (cmd, room) {
"Thank you for playing SpaceButton.",
"A game (c) 2022 by @melly_maeh and @dec_hl.",
" https://twitter.com/melly_maeh",
" https://twitter.com/dec_hl",
look: function (cmd, room) {
return ["That's all folks, thanks for the fish!"];
use: function (cmd, room) {
return ["Press ESCAPE to exit!"];
take: function (cmd, room) {
return ["Press ESCAPE to exit!"];
walk: function (cmd, room) {
return ["Press ESCAPE to exit!"];
take_words: function (cmd, room) {
use_words: function (cmd, room) {
createCanvas(windowWidth, windowHeight);
actions = new Actions(con);
cmdline = new CommandLine(actions);
setNewRoom(space_bedroom);
function mouseClicked() {
} else if (keyCode === 82) {
readActions = !readActions;
function checkCombination(cmd, it1, it2) {
return (cmd.length === 4 && cmd[1] === it1 && cmd[3] === it2) || (cmd.length === 4 && cmd[1] === it2 && cmd[3] === it1);
function putInventory(item) {
person.__inventory__.push(item);
function hasInventory(item) {
return person.__inventory__.indexOf(item) > -1;
function delInventory(item) {
var index = person.__inventory__.indexOf(item);
person.__inventory__.splice(index, 1);
function setNewRoom(room) {
con.SetText(current.text([], current));
function updateCurrentActions() {
if (current.take_words([], current).length > 0) {
if (current.use_words([], current).length > 0) {
base.push(CMD_INVENTORY);
actions.SetActions(base);
} else if (cmd.length == 1) {
if (cmd[0] === CMD_USE) {
var usable = current.use_words(cmd, current).concat(person.__inventory__);
actions.SetActions(usable);
} else if (cmd[0] === CMD_TAKE) {
actions.SetActions(current.take_words(cmd, current));
} else if (cmd.length == 2 && cmd[0] === CMD_USE) {
actions.SetActions([CMD_WITH]);
} else if (cmd.length == 3 && cmd[0] === CMD_USE) {
var usable = current.use_words(cmd, current).concat(person.__inventory__);
actions.SetActions(usable);
this.y = con.y + con.height + SPACING;
this.width = width - 2 * SPACING;
height - 4 * SPACING - (height / 4) * 3 - (2 * SPACING + TEXT_SIZE);
this.current_time = millis();
Actions.prototype.SetActions = function (act) {
this.current_time = millis();
Actions.prototype.Draw = function () {
strokeWeight(BORDER_SIZE);
rect(this.x, this.y, this.width, this.height);
var xPos = this.x + SPACING;
var yPos = this.y + SPACING;
for (var i = 0; i < this.draw_actions.length; i++) {
text_width = textWidth(COMMAND_SEPARATOR);
if (xPos + SPACING + text_width >= this.x + this.width) {
yPos += TEXT_SIZE + TEXT_SPACING;
text(COMMAND_SEPARATOR, xPos, yPos);
text_width = textWidth(this.draw_actions[i]);
if (xPos + SPACING + text_width >= this.x + this.width) {
yPos += TEXT_SIZE + TEXT_SPACING;
text(this.draw_actions[i], xPos, yPos);
stroke(ACTION_HIGHLIGHT);
strokeWeight(ACTION_BOX_SIZE);
rect(xPos - 1, yPos - 1 - dojsOffset, text_width + 2, TEXT_SIZE + 2);
Actions.prototype.Update = function () {
for (i = 0; i < this.actions.length; i++) {
this.draw_actions.push(this.actions[i]);
if (!cmdline.IsEmpty()) {
this.draw_actions.push(CMD_CLEAR);
this.draw_actions.push(CMD_ENTER);
if (this.current_time + COMMAND_DELAY < millis()) {
this.current = (this.current + 1) % this.draw_actions.length;
this.current_time = millis();
srSpeak(this.draw_actions[this.current]);
Actions.prototype.Clicked = function () {
if (this.draw_actions[this.current] === CMD_CLEAR) {
} else if (this.draw_actions[this.current] === CMD_ENTER) {
cmdline.Add(this.draw_actions[this.current]);
function CommandLine(act) {
this.y = act.y + act.height + SPACING;
this.width = width - 2 * SPACING;
this.height = 2 * SPACING + TEXT_SIZE;
CommandLine.prototype.Draw = function () {
strokeWeight(BORDER_SIZE);
rect(this.x, this.y, this.width, this.height);
for (var i = 0; i < this.cmd.length; i++) {
cmd_txt += this.cmd[i] + " ";
var xPos = this.x + SPACING;
var yPos = this.y + SPACING;
text(cmd_txt, xPos, yPos);
CommandLine.prototype.Add = function (w) {
CommandLine.prototype.Del = function () {
CommandLine.prototype.Clear = function () {
CommandLine.prototype.IsEmpty = function () {
return this.cmd.length == 0;
CommandLine.prototype.Get = function () {
CommandLine.prototype.Run = function () {
if (this.cmd[0] === CMD_LOOK) {
ret = current.commands.look(this.cmd, current);
} else if (this.cmd[0] === CMD_INVENTORY) {
if (person.__inventory__.length > 0) {
ret.push("Your inventory contains:");
ret.push(person.__inventory__.join(", "));
ret.push("Your inventory is empty");
} else if (this.cmd[0] === CMD_USE) {
if (this.cmd.length >= 2) {
ret = current.commands.use(this.cmd, current);
} else if (this.cmd[0] === CMD_TAKE) {
if (this.cmd.length >= 2) {
ret = current.commands.take(this.cmd, current);
ret = current.commands.walk(this.cmd, current);
con.SetText(current.text([], current));
con.AddText("Command: ");
for (var i = 0; i < this.cmd.length; i++) {
cmd_txt += this.cmd[i] + " ";
con.AddText(" " + cmd_txt);
con.AddText("Response: ");
for (var i = 0; i < ret.length; i++) {
con.AddText(" " + ret[i]);
this.width = width - 2 * SPACING;
this.height = (height / 4) * 3;
Console.prototype.Clear = function () {
Console.prototype.SetText = function (txt) {
for (var i = 0; i < txt.length; i++) {
this.line_time = millis();
Console.prototype.AddText = function (txt) {
Console.prototype.Draw = function () {
strokeWeight(BORDER_SIZE);
rect(this.x, this.y, this.width, this.height);
if (this.text.length > 0) {
var yPos = this.x + SPACING;
for (var i = 0; i < this.text.length && i < this.line; i++) {
text(this.text[i], this.xPos, yPos);
yPos += TEXT_SIZE + TEXT_SPACING;
this.line < this.text.length &&
this.line_time + LINE_DELAY < millis()
this.line_time = millis();
for (var i = 0; i < this.text.length; i++) {
txt += this.text[i] + "\n";
window.speechSynthesis.cancel();
var msg = new SpeechSynthesisUtterance();
window.speechSynthesis.speak(msg);