! RAPDEMO - a simple testbed for the RAP 1.1 Reactive Agent Planner engine ! ! It's not very exciting, but it proves that RAP works in a trivial case. ! The next demo world will be more interesting, I promise. ! ! Note: You will most likely get a bunch of 'local variable declared ! but not used' warnings when you compile this. That's Inform's ! fault, not mine. It can't get its head around the concept of a ! parameter that isn't used in every routine. Either turn warnings ! off or ignore them, or help Graham Nelson fix the compiler. Constant DEBUG; Constant Story "RAPDEMO"; Constant Headline "^An Interactive Testbed^ written 2000 by Nate Cull.^"; Include "Parser"; Include "VerbLib"; Include "./rapcore.h"; Include "./rapplans.h"; ! Place is my personal 'room' class, which I define in my ! game files rather than using 'object' for all rooms. ! Among other things it gives light to all rooms. ! Here I'm simply modifying it to inherit from RapRoom, ! so I can use RAP movement hints Class Place class RapRoom, has light ; Place kitchen "Kitchen" with description "This is a comfortable kitchen. A door leads west to the lounge, and north to the laundry.", w_to lounge, n_to laundry, ! These are RAP movement hints. ! They simply specify all the NPC-accessible *entrances to*, ! rather than exits from, this room. rap_from_num is the number ! of possible entrances. ! ! These hints currently (in v1.1 of the planbase) don't deal with ! interesting obstacles like lockable doorways. In a later versin ! I'll probably add these to the standard movement handling. ! To implement NPC-traversable obstacles at the moment, you'll ! need to override rap_get_move_to() in each RapRoom that has an ! obstacle as an entrance, and write the code yourself. rap_from_num 2, rap_from_1 lounge, rap_from_2 laundry ; Place laundry "Laundry" with description "This is the laundry. A door leads south to the kitchen, and west to the hall.", s_to kitchen, w_to hall, rap_from_num 2, rap_from_1 kitchen, rap_from_2 hall ; Place lounge "Lounge" with description "This is a warmly furnished lounge. A door leads east to the kitchen, and north to the hall.", e_to kitchen, n_to hall, rap_from_num 2, rap_from_1 kitchen, rap_from_2 hall ; Place hall "Hall" with description "This is a hallway. A door leads south to the lounge, and east to the laundry.", s_to lounge, e_to laundry, rap_from_num 2, rap_from_1 lounge, rap_from_2 laundry ; ! Yes, it's a boring map. But it does test RAP's ability to avoid ! circular references. This whole map is one circular reference. Object ball "red ball" with name "red" "plastic" "ball", description "It's a shiny red plastic ball, Widget's favourite toy.", ; Object widget "Widget" with name "widget" "animatronic" "puppy" "dog" "robot", initial "Widget the animatronic puppy is here.", description "Widget is a robot puppy who seems to have a mind of his own.", daemon [; if (rap_trace_level > 1) print "^rapdemo: starting rap_goalseek^"; ! And this one line is what generates all of Widget's behaviour. ! It specifies the top-level goal which RAP will attempt to achieve ! each move. The rest is all produced by the planbase. rap_goalseek( self, rapDoggyFun, false, false); if (rap_trace_level > 1) print "^rapdemo: rap_goalseek completed^"; if (rap_trace_level > 1) print "^rapdemo: rap_answer_action=", (name) rap_answer_action, ", rap_answer_param1=", (name) rap_answer_param1, ", rap_answer_param2=", (name) rap_answer_param2, "^"; ! Okay, two lines. The rap_goalseek() line just calculates the suggested ! best action. This line is what actually runs the action. They're ! separated so you can couple RAP loosely to your NPC - use it where ! appropriate, and ignore it at other times. It's a library, not a ! straightjacket. rap_answer_action.execute( self, rap_answer_param1, rap_answer_param2); ], has proper male ; Object my_player ; [ Initialise; lookmode = 2; ! Start in Verbose mode ChangePlayer(my_player); move ball to player; location = kitchen; move widget to kitchen; StartDaemon(widget); ! trace_level specifies what level of verbosity you want from ! RAP debug messages. 0 is silent, 1 traces each goal for catching ! planbase bugs, 2 gives internal debugging messages for catching engine bugs. ! Trust me - you don't want to set it to 2. rap_trace_level = 0; "^Reactive Agent Planner 1.1 testbed now active. ^Use RAPTRACE [ON|OFF|DEBUG] to toggle tracing. ^^The object of this game is simply to demonstrate RAP's use for automatic path-finding and simple actions and check that it works correctly. There is one RAP-enabled actor in this story, Widget the Puppy. Widget has only one goal, and that is to find and play with the red ball. At all times, he knows exactly where the ball is, which makes him pretty simpleminded. However, you can try picking up and dropping him and the ball, to see how he reacts automatically to changes in his environment. Also, try RAPTRACE ON to watch the RAP engine running through its plan queue, for insight into how the engine works.^"; ]; Include "Grammar"; Verb 'raptrace' * -> RapTrace * 'on' -> RapTraceOn * 'off' -> RapTraceOff * 'debug' -> RapTraceDebug; [ RapTraceSub; print "RAP tracing is currently "; if (rap_trace_level > 1) "DEBUG"; if (rap_trace_level > 0) "ON."; "OFF."; ]; [ RapTraceOnSub; rap_trace_level = 1; "RAP tracing is now ON."; ]; [ RapTraceOffSub; rap_trace_level = 0; "RAP tracing is now OFF."; ]; [ RapTraceDebugSub; rap_trace_level = 2; "RAP tracing is now DEBUG."; ];