TADS Programming (3) - Daemons Sent in by The Grue This little bit on TADS will hopefully help explain how to set up a Daemon and to show just how flexible they can be. Firstly a Daemon is really nothing more than a counter that increases by a set amount (normally 1) each time the player takes a move. Now supposing you had in your game a pedestal and on the pedestal there is a red rod. If you take the red rod an alarm goes off and after 6 moves a guard comes in and shoots you. (Isn't life a bitch). You can call the Daemon anything you like so for this puzzle we'll call it guardDaemon. (Obvious really). The first thing you need to do is amend the doTake for the red rod so when the player takes it, they hear the alarm sound and the guardDaemon is started. redrod : item sdesc = "red rod" ldesc = "The rod is red" noun = 'rod' location = pedestal doTake (Me) = { if (redrod.location=pedestal) {"As you lift the rod from the pedestal, a loud siren begins to wail."; redrod.moveInto(Me); setDaemon(guardDaemon,true);} else { pass doTake; } } Now before we define the complete workings of our Daemon we will have to add a little bit in the std.t file, under the global object. We need to add this: siren = 0 guard = 6 The reason for this is because each Daemon you define has two local conditions, one of which will be incremented by one each time the player makes a move. In our guardDaemon the two local conditions will be s and g, s for siren and g for guard. The s or siren is the one that will be incremented and when it equals g or guard (6 moves) the guard will appear and shoot the player. Now we can write the routine for our guardDaemon. guardDaemon :function { local s,g; global.siren:=global.siren +1; s := global.siren; g := global. guard; if (s=g) {"\bA guard rushes through the doorway, lifts a huge magnum and blows you away";die();} } ; That seems ok but what if the player replaces the red rod within the six moves. We alter the Daemon so it reads... if (s=g and redrod.location<>pedestal) {"\bA guard rushes through the doorway, lifts a huge magnum and blows you away;die();} else if (s=g and redrod.location=pedestal) {"\bA guard rushes through the doorway, he notices the red rod is still on the pedestal and quietly saunters back to the guard room.";} } ; Now if the red rod is not on the pedestal after six moves the player gets shot but if it is on the pedestal the guard will return to the guard room. This is still not perfect, because Daemons keep increasing by one all the time, if the player replaces the red rod and the guard returns to the guard room the siren condition will be more than 6. The player could then take the red rod without being shot. To stop this we will reset the Daemon, so if the siren condition is greater than 6 and the red rod's location doesn't equal the pedestal, we will make the s or siren condition = 1, and it will continue to increase. Once again when it reaches 6 the player will either be shot or if he has replaced the rod, the guard will return to the guard room. This is how to alter your guardDaemon to give the desired effect. if (s=g and redrod.location<>pedestal) {"\bA guard rushes through the doorway, lifts a huge magnum and blows you away;die();} else if (s=g and redrod.location=pedestal) {"\bA guard rushes through the doorway, he notices the red rod is still on the pedestal and quietly saunters back to the guard room.";} else if (s>g and redrod.location<>pedestal) {global.siren:=1;} } ; At the moment this Daemon does not really do much towards the gameplay, as the player can never take the red rod. What you could do is invent another item in the game, perhaps a red stick and if the player was to take the red rod and replace it with the red stick the guard would be fooled and return to the guard room. But really the thing with Daemons is that you can make them do virtually anything you want and can also incorporate other routines within them if you needed to. This last example will show you how to incorporate a query function into the guardDaemon. guardDaemon :function { local s,g; global.siren:=global.siren +1; s := global.siren; g := global.guard; if (s=g and redrod.location<>pedestal) {"A guard rushes through the doorway, lifts a huge magnum and blows you away";die();} else if (s=g and redrod.location=pedestal) {local yesno; while (true) {"A guard rushes through the doorway, he glances over at the pedestal. Although the red rod is now back on the pedestal he still seems a little bit suspicious, he turns to you and says \"Have you been messing around with that red rod?\"(YES or NO) >"; yesno :=yorn(); if (yesno = 1) {"The guard can hardly believe your stupidity in owning up, he quickly slaps a pair of handcuffs upon you and marches you off to the local jail"; Me.moveInto(jail);incscore(10);exit;} else if (yesno = 0) {"\"Oh! my mistake, for a minute I thought someone had been messing around with the red rod.\" The guard grabs you firmly by the arm and proceeds to escort you back into the lobby.";Me.moveInto(lobby);exit;} } } } ; Now if the siren condition equals the guard condition (6 moves) and the red red is not on the pedestal the player is shot. If the Daemon has been started but the player has replaced the red rod within the 6 moves then the guard will appear and ask the player a simple question. The local conditions of s and g have now been made redundant and the game is now functioning under the local conditions of yesno. The while true is used so if the player types something other than a yes or no to answer the guard's question, the question will be repeated. If the player responds with a yes, he will be move into the jail and his score will be increased by 10 pts. If the player responds no, he will be escorted to the lobby and his score will not increase. The correct response should be a yes as there is a prisoner in the jail he needs to talk to. I have found that with a yesno condition, if you wish the player to be moved to another location so that they can continue with the game, you will need to have an 'exit' after the moveInto(room) command. If you do not put one in you will find the player is moved to the correct location but the question will still be repeated. Only if you intend to kill the player off for a certain response can you leave it out, as all processing of the player's input will have finished anyway. Till next time IN FROBS WE TRUST!