include "Parser";

constant Story "CASTLE ADVENTURE^";
constant Headline "";
constant NO_SCORE;

replace PushSub;
replace WearSub;
replace DisrobeSub;
replace TakeSub;
replace DropSub;

include "VerbLib";

attribute oiled;
attribute indoors;
attribute seen_player_masked;
attribute seen_player_unmasked;

object AtGate "At Gate" 
  with description
    "You are at the front of the castle. The door to the north is shut. A button is next to the door.",
    e_to AtWindow, w_to Garden,
    n_to "The door is locked from the inside.";
object -> Button "button"
  with name "button",
  has scenery;
object DoorF "door"
  with name "door",
  found_in AtGate Foyer,
  has scenery;

object Garden "Garden"
  with description
    "There is a shed in the garden's west corner.",
  w_to ToolShed, e_to AtGate;

object ToolShed "Tool Shed"
  with description
    "The shed is dark and cramped.",
  e_to Garden;
object -> Oilcan "oilcan"
  with name "oil",
       describe "There is an oilcan here.";

object AtWindow "At Window"
  with description
    "A window in the castle wall. Paths lead north and west.",
    n_to SideDoor, w_to AtGate;
object Window "window"
  with name "window",
       found_in AtWindow Armory,
  has scenery;

object SideDoor "Side Door"
  with description [;
    if (Guard in SideDoor) {
      "You are at the side entrance, a door to the west.^A guard blocks the door.";
    } else {
      "You are at the side entrance, a door to the west.";
    }
  ],
  s_to AtWindow,
  w_to [;
    if (Guard in SideDoor) {
      "He won't let you near the door!";
    } else if (DoorS has oiled) {
      print "You enter the castle.";
      Guard.timer = 1;
      return Corridor;
    } else {
      "The door is rusted shut!";
    }
  ];
object -> Guard "guard"
  with name "guard",
       timer,
  has scenery;
object -> DoorS "door"
  with name "door",
  has scenery;

object Corridor "Corridor"
  with description
    "Halls lead in all directions.",
    e_to [; "The guard is back. You can't exit that way now."; ],
    n_to Treasury, s_to Armory, w_to Foyer,
  has indoors;

object Treasury "Treasury"
  with description
    "The King's treasure -- what a magnificent sight!",
    s_to Corridor,
  has indoors;
object -> TreasureChest "treasure chest"
  with name "chest",
       describe "A heavy treasure chest is here!";

object Armory "Armory"
  with description
    "The door leads north. A window to the south is closed.",
    n_to Corridor, s_to [;
      if (Window hasnt oiled) "The window is rusted shut!";
      if (TreasureChest in player) "The chest won't fit out the window!";
      Guard.timer = 0;  ! You successfully evaded the guards.
      return AtWindow;
    ],
  has indoors;
object -> Gloves "pair of gloves"
  with name "gloves",
       describe "A pair of gloves is here.",
  has clothing;

object Foyer "Foyer"
  with description
    "Festive streamers adorn the front door to the south.",
    s_to [;
      if (TreasureChest notin player) "You forgot the treasure!";
      if (DoorF hasnt oiled) "The door is rusted shut!";
      ! Actually leaving by the front door wins you the game.
      if (Mask has moved) {
        deadflag = 4;
        "Congratulations! You have recovered the treasure!^
          ...But can you win without the mask?^";
      } else {
        deadflag = 5;
        "Congratulations!";
      }
    ], e_to Corridor,
  has indoors;
object -> Mask "mask"
  with name "mask",
       describe "A mask is discarded nearby.",
  has clothing;

[TalkToSub;
  if (noun == Guard) "The guard grumbles.";
  "Don't be silly!";
];

[OilSub;
  if (Oilcan notin player) return L__M(##Miscellany, 38);
  if (noun == Button) "Don't be silly!";
  if (noun == Window && player in AtWindow) "It's too high to reach.";
  if (noun == DoorF && player in AtGate) "It doesn't need oiling. It's locked.";
  if (noun == DoorF && player in Foyer) {
    if (Gloves hasnt worn) {
      move Oilcan to location;
      "The can slips from your oily hands!";
    }
    give DoorF oiled;
    "Done.";
  }
  if (noun == DoorS && player in SideDoor) {
    if (Guard in location) "He won't let you near the door!";
    if (Gloves hasnt worn && DoorS has oiled) {
      move Oilcan to location;
      "The can slips from your oily hands!";
    }
    give DoorS oiled;
    "Done.";
  }
  if (noun == Window && player in Armory) {
    if (Gloves hasnt worn)
      "The can slips from your oily hands!";
    give Window oiled;
    "Done.";
  }
  "Don't be silly!";
];

[PushSub;
  if (noun == Guard) {
    deadflag = 3;  ! You lose.
    "You picked your last fight!";
  } else if (noun == DoorS && Guard in SideDoor) {
    "He won't let you near it!";
  } else if (noun == DoorF) {
    "It doesn't budge.";
  } else if (noun == Button) {
    if (Guard.timer == 0) {
      remove Guard;  ! move Guard to nowhere until timer expires
      Guard.timer = 1;
      "You hear someone approaching.";
    } else {
      "Done.";
    }
  } else {
    "Don't be silly!";
  }
];

[WearSub;
  if (noun ~= Gloves && noun ~= Mask) "Don't be silly!";
  if (noun == Gloves) {
    if (noun has worn) "You're already wearing them.";
    if (noun notin player) "You're not carrying them.";
    give noun worn;
    "You put on the gloves.";
  } else {
    if (noun has worn) "You're already wearing it.";
    if (noun notin player) "You're not carrying it.";
    give noun worn;
    "No one will recognize you.";
  }
];

[DisrobeSub j k;
  if (noun == Gloves && Gloves hasnt worn) "You aren't wearing them.";
  if (noun == Mask && Mask hasnt worn) "You aren't wearing it.";
  if (noun hasnt worn) "Don't be silly!";
  k = 0; objectloop (j in player) if (j hasnt worn) k++;
  give noun ~worn;
  if (k ~= 0) {
    ! The player is already carrying something.
    move noun to location;
    "Dropped.";
  }
  "Okay.";
];

[TakeSub j k;
  if (noun in player) {
    if (noun == Gloves && Gloves has worn) "You're already wearing them.";
    if (noun == Gloves) "You're already carrying them.";
    if (noun has worn) "You're already wearing it.";
    "You're already carrying it.";
  }
  if (noun ~= Oilcan && noun ~= Gloves && noun ~= Mask && noun ~= TreasureChest) {
    "Don't be silly!";
  }
  k = 0; objectloop (j in player) if (j hasnt worn) k++;
  if (k ~= 0) "Drop something first.";
  move noun to player;
  "Taken.";
];

[DropSub;
  if (noun ~= Oilcan && noun ~= Gloves && noun ~= Mask && noun ~= TreasureChest) {
    "Don't be silly!";
  }
  if (noun notin player) {
    if (noun == Gloves) "You aren't carrying them.";
    "You aren't carrying it.";
  }
  give noun ~worn;
  move noun to location;
  "Dropped.";
];

[TimePasses;
  if (Guard.timer ~= 0) {
    ++Guard.timer;
  }
  if (Guard.timer == 5) {
    move Guard to SideDoor;
    if (location has indoors) "Uh-oh! Someone is coming!";
    Guard.timer = 0;
    if (player in AtGate) "The guard tells you to go away.";
    if (player in SideDoor) "The guard returns.";
  } else {
    if (Guard.timer == 6) "You'd better get out of here!";
    if (Guard.timer == 4 && player in AtGate) "You hear grumbling.";
    if (Guard.timer == 7) {
      print "A guard rushes into the room. You have been captured!^";
      if (TreasureChest in player || TreasureChest in location) {
        deadflag = 3;  ! You lose.
        "You thief... I hope you like dungeons!";
      } else if (Mask has worn && Guard has seen_player_masked) {
        deadflag = 3;  ! You lose.
        "You again... I hope you like dungeons!";
      } else if (Mask hasnt worn && Guard has seen_player_unmasked) {
        deadflag = 3;  ! You lose.
        "You again... I hope you like dungeons!";
      } else {
        if (Mask has worn) give Guard seen_player_masked;
        else give Guard seen_player_unmasked;
        Guard.timer = 0;
        print "The guards kick you out.^";
        PlayerTo(AtGate, 2);  ! describe the room upon landing there
        rtrue;
      }
    }
  }
];

[DeathMessage;
  if (deadflag == 3) print "You lose";
  if (deadflag == 4) print "You win";
  if (deadflag == 5) print "You beat the game";
];

[Initialise;
  give player light;  ! so we don't have to give each room light
  lookmode = 2;  ! verbose
  remove nw_obj; remove ne_obj; remove u_obj; ! disable these direction-verbs
  remove sw_obj; remove se_obj; remove d_obj; ! disable these direction-verbs
  location = AtGate;
  "^^^^^Welcome to...^";
];


Verb meta 'quit' 'q//'
    *                                           -> Quit;
Verb meta 'restart'
    *                                           -> Restart;
Verb meta 'restore'
    *                                           -> Restore;
Verb meta 'save'
    *                                           -> Save;

Verb 'drop'
    * noun                                      -> Drop;
Verb 'get'
    * noun                                      -> Take;
Verb 'inventory' 'i//'
    *                                           -> Inv;
Verb 'look' 'l//'
    *                                           -> Look;
Verb 'oil'
    * noun                                      -> Oil;
Verb 'push'
    * noun                                      -> Push;
Verb 'put'
    * 'oil' 'on' noun                           -> Oil
    * 'on' noun                                 -> Wear;
Verb 'take'
    * noun                                      -> Take
    * 'off' noun                                -> Disrobe;
Verb 'talk'
    * 'to' noun                                 -> TalkTo;
Verb 'wear'
    * noun                                      -> Wear;
Verb 'wait' 'z//'
    *                                           -> Wait;

#Stub AfterLife         0;
#Stub AfterPrompt       0;
#Stub Amusing           0;
#Stub BeforeParsing     0;
#Stub ChooseObjects     2;
#Stub DarkToDark        0;
#Stub GamePostRoutine   0;
#Stub GamePreRoutine    0;
#Stub InScope           1;
#Stub LookRoutine       0;
#Stub NewRoom           0;
#Stub ParseNumber       2;
#Stub ParserError       1;
#Stub PrintTaskName     1;
#Stub PrintVerb         1;
#Stub UnknownVerb       1;

[ ParseNoun; return -1; ];