This document describes using rule-based programming and games to teach rule-based programming concepts. It provides examples of rule-based systems for modeling cash flow accounting, a fire suppression system, and a number guessing game. It also includes code snippets defining classes and rules for a text-based adventure game.
21. Definitions
public class Room {
private String name
// getter and setter methods here
}
public class Sprinkler {
private Room room;
private boolean on;
// getter and setter methods here
}
public class Fire {
private Room room;
// getter and setter methods here
}
public class Alarm {
}
22. Definitions
rule "When there is a fire turn on the sprinkler" when
f : Fire()
s : Sprinkler( room == f.room, on == false )
then
modify( s ) { on = true };
println( "Turn on the sprinkler for room " + r.name );
end
rule "When the fire is gone turn off the sprinkler" when
r : Room( )
s : Sprinkler( room == r, on == true )
not Fire( room == r )
then
modify( s) { on = false };
println( "Turn off the sprinkler for room " + r.name);
end
23. Definitions
rule "Raise the alarm when we have one or more fires" when
exists Fire()
then
insert( new Alarm() );
println( "Raise the alarm" );
end
rule "Cancel the alarm when all the fires have gone" when
not Fire()
a: Alarm()
then
retract( a );
println( "Cancel the alarm" );
end
24. Definitions
rule "Status output when things are ok" when
not Alarm()
not Sprinkler( on == true )
then
println( "Everything is ok" );
end
25. Executing
String[] names = new String[]{"kitchen", "bedroom", "office", "livingroom"};
Map<String,Room> name2room = new HashMap<String,Room>();
!
for( String name: names ){
Room room = new Room( name );
name2room.put( name, room );
ksession.insert( room );
Sprinkler sprinkler = new Sprinkler( room );
ksession.insert( sprinkler );
}
!
ksession.fireAllRules()
> Everything is ok
26. Executing
Fire kitchenFire = new Fire( name2room.get( "kitchen" ) );
Fire officeFire = new Fire( name2room.get( "office" ) );
!
FactHandle kitchenFireHandle = ksession.insert( kitchenFire );
FactHandle officeFireHandle = ksession.insert( officeFire );
!
ksession.fireAllRules();
> Raise the alarm
> Turn on the sprinkler for room kitchen
> Turn on the sprinkler for room office
27. Executing
ksession.retract( kitchenFireHandle );
ksession.retract( officeFireHandle );
!
ksession.fireAllRules()
> Turn off the sprinkler for room office
> Turn off the sprinkler for room kitchen
> Cancel the alarm
> Everything is ok
rule "Status output when things are ok" when
not Alarm()
not Sprinkler( on == true )
then
println( "Everything is ok" );
end
29. public class Game {
private int biggest;
private int smallest;
private int guessCount;
public class Guess {
private int value;
public class GameRules {
private int maxRange;
private int allowedGuesses;
public class RandomNumber {
private int randomNumber;
30. public class Game {
private int biggest;
private int smallest;
private int guessCount;
public class Guess {
private int value;
public class GameRules {
private int maxRange;
private int allowedGuesses;
public class RandomNumber {
private int randomNumber;
<kbase name="NumberGuessKB" packages="org.drools.games.numberguess">
public class NumberGuessMain {
public static void main(String[] args) {
KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
final KieSession ksession = kc.newKieSession( "NumberGuessKS");
ksession.insert( new GameRules( 100, 5 ) );
ksession.insert( new RandomNumber() );
ksession.insert( new Game() );
ksession.fireAllRules();
}
}
<ksession name="NumberGuessKS"/>
</kbase>
31. rule Main when
rules : GameRules( )
game : Game( guessCount < rules.allowedGuesses )
not Guess()
then
setFocus("Guess");
end
rule "Get user Guess" agenda-group "Guess" when
$r : RandomNumber()
rules : GameRules( )
game : Game( )
not Guess()
then
System.out.println( "You have " + ( rules.allowedGuesses - game.guessCount ) +
" out of " + rules.allowedGuesses +
" guesses left.nPlease enter your guess from 0 to " +
rules.maxRange );
br = new BufferedReader( new InputStreamReader( System.in ) );
modify (game) { guessCount = game.guessCount + 1 }
int i = Integer.parseInt( br.readLine() );
insert( new Guess( i ) );
end
32. rule "Record the highest Guess" agenda-group "Guess" no-loop when
game : Game( )
r : RandomNumber()
guess : Guess( value > r.value)
then
modify ( game ) { biggest = guess.value };
retract( guess );
System.out.println( "Your guess was too high" );
end
33. rule "Record the highest Guess" agenda-group "Guess" no-loop when
game : Game( )
r : RandomNumber()
guess : Guess( value > r.value)
then
modify ( game ) { biggest = guess.value };
retract( guess );
System.out.println( "Your guess was too high" );
end
rule "Record the lowest Guess" agenda-group "Guess" when
game : Game( )
r : RandomNumber()
guess : Guess(value < r.value )
then
modify ( game ) { smallest = guess.value };
retract( guess );
System.out.println( "Your guess was too low" );
end
34. rule "Record the highest Guess" agenda-group "Guess" no-loop when
game : Game( )
r : RandomNumber()
guess : Guess( value > r.value)
then
modify ( game ) { biggest = guess.value };
retract( guess );
System.out.println( "Your guess was too high" );
end
rule "Record the lowest Guess" agenda-group "Guess" when
game : Game( )
r : RandomNumber()
guess : Guess(value < r.value )
then
modify ( game ) { smallest = guess.value };
retract( guess );
System.out.println( "Your guess was too low" );
end
rule "Guess correct" agenda-group "Guess" when
game : Game( )
r : RandomNumber()
guess : Guess( value == r.value)
then
System.out.println( "You guessed correctly" );
end
35. rule Main when
rules : GameRules( )
game : Game( guessCount < rules.allowedGuesses )
not Guess()
then
setFocus("Guess");
end
rule "No more Guesses" when
rules : GameRules( )
game : Game( guessCount == rules.allowedGuesses )
not Guess()
r : RandomNumber()
then
System.out.println( "You have no more guessesnThe correct guess was " + r.value );
end
36. rooms = [
"basement" : new Room("basement"),
"lounge" : new Room("lounge"),
"dining room” : new Room("dining room"),
“kitchen" : new Room("kitchen"),
"ground floor hallway" : new Room("ground floor hallway"),
"bedroom1" : new Room("bedroom1"),
"bedroom2" : new Room("bedroom2"),
“bathroom" : new Room("bathroom"),
"office" : new Room("office"),
"first floor hallway" : new Room("first floor hallway")
];
doors = [
"d1" : new Door( rooms[“kitchen", rooms["basement"] ),
"d2" : new Door( rooms["ground floor hallway"], rooms["lounge"]),
"d3" : new Door( rooms["ground floor hallway"], rooms["dining room"] ),
"d4" : new Door( rooms["ground floor hallway"], rooms["kitchen"]),
"d5" : new Door( rooms["ground floor hallway"], rooms[ "first floor hallway"] ),
"d6" : new Door( rooms["first floor hallway"], rooms[ "bedroom1"] ),
"d7" : new Door( rooms["first floor hallway”], rooms[ "bedroom2"] ),
"d8" : new Door( rooms["first floor hallway"], rooms[ "bathroom"] ),
"d9" : new Door( rooms["first floor hallway”], rooms[ "office"] )
];
37. characters = [ "hero" : new Character( "hero" ),
"monster" : new Character( "monster" ) ];
items = [
"mace" : new Item( "mace" ),
"cucumber" : new Item( "cucumber" ),
"torch" : new Item( "torch" ),
"umbrella" : new Item( "umbrella" )
];
locations = [
"mace" : new Location( items["mace"], rooms["basement"] ),
"monster" : new Location( characters["monster"], rooms["basement"] ),
"cucumber" : new Location( items["cucumber"], rooms["kitchen"] ),
"torch" : new Location( items["torch"], rooms["office"] ),
"hero" : new Location( characters["hero"], rooms["ground floor hallway"] ),
"umbrella" : new Location( items["umbrella"], rooms["ground floor hallway"] )
];
38. doors = [
"d1" : new Door( rooms[“kitchen", rooms["basement"] ),
"d2" : new Door( rooms["ground floor hallway"], rooms["lounge"]),
"d3" : new Door( rooms["ground floor hallway"], rooms["dining room"] ),
"d4" : new Door( rooms["ground floor hallway"], rooms["kitchen"]),
"d5" : new Door( rooms["ground floor hallway"], rooms[ "first floor hallway"] ),
"d6" : new Door( rooms["first floor hallway"], rooms[ "bedroom1"] ),
"d7" : new Door( rooms["first floor hallway”], rooms[ "bedroom2"] ),
"d8" : new Door( rooms["first floor hallway"], rooms[ "bathroom"] ),
"d9" : new Door( rooms["first floor hallway”], rooms[ "office"] )
];
query connect( Room $x, Room $y )
Door($id, $x, $y;)
or
Door($id, $y, $x;)
end
39. locations = [
query things(Character $char, List $things)
$char := Character()
Location( $char, $room; )
$things := List() from accumulate( Location($thing, $room; thing != $char),
collectList( $thing ) )
end
"mace" : new Location( items["mace"], rooms["basement"] ),
"monster" : new Location( characters["monster"], rooms["basement"] ),
"cucumber" : new Location( items["cucumber"], rooms["kitchen"] ),
"torch" : new Location( items["torch"], rooms["office"] ),
"hero" : new Location( characters["hero"], rooms["ground floor hallway"] ),
"umbrella" : new Location( items["umbrella"], rooms["ground floor hallway"] )
];
query exits(Character $char, List $exits)
$char := Character()
Location( $char, $room; )
$exits := List() from accumulate( connect($room, $exit;),
collectList( $exit ) )
end
40. query look(Character $char, List $things, List $exits)
$char := Character()
things( $char, $things; )
exits( $char, $exits; )
end
rule lookCmd agenda-group "commands" lock-on-active auto-focus when
lc : LookCommand( c : character )
Location( thing == c, $room : target )
?look( c, things, exits; )
then
str = "You are in the " + $room + "n";
str +="You can see " + things + "n";
str +="Available exits are " + exits + "n";
str +="n";
res = new Response( str );
res.localId = lc.requestId;
insert( res );
end
41. rule lookCmd agenda-group "commands" lock-on-active auto-focus when
lc : LookCommand( c : character )
Location( thing == c, $room : target )
?look( c, things, exits; )
then
str = "You are in the " + $room + "n";
str +="You can see " + things + "n";
str +="Available exits are " + exits + "n";
str +="n";
res = new Response( str );
res.localId = lc.requestId;
insert( res );
end
42. rule validMove agenda-group "commands" lock-on-active auto-focus when
mc : MoveCommand( c : character, r : room )
l : Location( thing == c, ltarget : target )
exists ?connect( r, ltarget; )
then
modify( l ) { target = r };
res = new Response( "You have entered the " + l.target + "n" );
res.localId = mc.requestId;
insert( res );
end
rule lookCmd agenda-group "commands" lock-on-active auto-focus when
lc : LookCommand( c : character )
Location( thing == c, $room : target )
?look( c, things, exits; )
then
str = "You are in the " + $room + "n";
str +="You can see " + things + "n";
str +="Available exits are " + exits + "n";
str +="n";
res = new Response( str );
res.localId = lc.requestId;
insert( res );
end
43. rule validPickup agenda-group "commands" lock-on-active auto-focus when
pc : PickupCommand( c : character, t : thing)
cl : Location( thing == c )
tl : Location( thing == t, target == cl.target )
then
insert( new Holding( c, t ) );
modify( tl ) { target = c };
res = new Response( "You have picked up the " + t + "n" );
res.localId = pc.requestId;
insert( res );
end
44. rule validPickup agenda-group "commands" lock-on-active auto-focus when
pc : PickupCommand( c : character, t : thing)
cl : Location( thing == c )
tl : Location( thing == t, target == cl.target )
then
insert( new Holding( c, t ) );
modify( tl ) { target = c };
res = new Response( "You have picked up the " + t + "n" );
res.localId = pc.requestId;
insert( res );
end
rule validDrop agenda-group "commands" lock-on-active auto-focus when
dc : DropCommand( c : character, t : thing)
cl : Location( thing == c )
tl : Location( thing == t )
h : Holding( c, t;)
then
modify( tl ) { target = cl.target };
retract ( h );
insert( new DropEvent( c, t ) );
res = new Response( "You have droped the " + t + "n" );
res.localId = dc.requestId;
insert( res );
end
45. rule validGive agenda-group "commands" lock-on-active auto-focus when
gc : GiveCommand( $giver : giver, $thing : thing )
// They are in the same room
giverl : Location( thing == gc.giver )
Location( thing == gc.receiver, target == giverl.target )
// The giver must be holding the thing
h : Holding( $giver, $thing;)
then
modify( h ) { character = gc.receiver };
insert( new GiveEvent( gc.giver, gc.thing, gc.receiver ) );
res = new Response( "You have given the " + gc.thing + " to " + gc.receiver + "n" );
res.localId = gc.requestId;
insert( res );
end