55
Learning Rule Based Programming Using Games

Classic Games Development with Drools

Embed Size (px)

DESCRIPTION

Games Development with Drools. Covers text adventure games, pong, wumpus and invaders. As well as a general rules introduction Those games were also covered separately in other videos Invaders : http://tinyurl.com/jwml42m Wumpus : http://tinyurl.com/na376bu Pong : http://tinyurl.com/pkgub9b Text Adventure : http://tinyurl.com/mfggm8n

Citation preview

Page 1: Classic Games Development with Drools

Learning Rule Based Programming

Using Games

Page 2: Classic Games Development with Drools

1979 Rete Algorithm by Charles Forgy 2

Page 3: Classic Games Development with Drools

Clips and Jess

Clips 1986 !!!!!!!

3

Clips 1995 !!!!!!!

Page 4: Classic Games Development with Drools

Rules and Patterns

Page 5: Classic Games Development with Drools

5

What is a Rule

rule <rule_name> <attribute><value> when <conditions> then <actions>end

Page 6: Classic Games Development with Drools

6

Pattern Matching

Person( age >= 18 ) field name restriction

constraintobject type

pattern

Page 7: Classic Games Development with Drools

CashFlow

Page 8: Classic Games Development with Drools

8

Classes

Account

long accountNo

int balance

CashFlow

Date date

int amount

AccountPeriod

Date start

Date end

CashFlow Example

Page 9: Classic Games Development with Drools

select * from Account acc, Cashflow cf, AccountPeriod apwhere acc.accountNo == cf.accountNo and cf.type == CREDIT cf.date >= ap.start and cf.date <= ap.end

rule “increase balance for AccountPeriod Credits” when ap : AccountPeriod() acc : Account() cf : CashFlow( type == CREDIT, accountNo == acc.accountNo, date >= ap.start && <= ap.end ) then acc.balance += cf.amount; end

9

acc.balance += cf.amount

CashFlow Rule

Page 10: Classic Games Development with Drools

select * from Account acc, Cashflow cf, AccountPeriod apwhere acc.accountNo == cf.accountNo and cf.type == CREDIT cf.date >= ap.start and cf.date <= ap.end

rule “increase balance for AccountPeriod Credits” when ap : AccountPeriod() acc : Account() cf : CashFlow( type == CREDIT, accountNo == acc.accountNo, date >= ap.start && <= ap.end ) then acc.balance += cf.amount; end

10

acc.balance += cf.amount

CashFlow Rule

Page 11: Classic Games Development with Drools

select * from Account acc, Cashflow cf, AccountPeriod apwhere acc.accountNo == cf.accountNo and cf.type == CREDIT cf.date >= ap.start and cf.date <= ap.end

rule “increase balance for AccountPeriod Credits” when ap : AccountPeriod() acc : Account() cf : CashFlow( type == CREDIT, accountNo == acc.accountNo, date >= ap.start && <= ap.end ) then acc.balance += cf.amount; end

11

acc.balance += cf.amount

CashFlow Rule

Page 12: Classic Games Development with Drools

select * from Account acc, Cashflow cf, AccountPeriod apwhere acc.accountNo == cf.accountNo and cf.type == CREDIT cf.date >= ap.start and cf.date <= ap.end

rule “increase balance for AccountPeriod Credits” when ap : AccountPeriod() acc : Account() cf : CashFlow( type == CREDIT, accountNo == acc.accountNo, date >= ap.start && <= ap.end ) then acc.balance += cf.amount; end

12

acc.balance += cf.amount

CashFlow Rule

Page 13: Classic Games Development with Drools

select * from Account acc, Cashflow cf, AccountPeriod apwhere acc.accountNo == cf.accountNo and cf.type == CREDIT cf.date >= ap.start and cf.date <= ap.end

rule “increase balance for AccountPeriod Credits” when ap : AccountPeriod() acc : Account() cf : CashFlow( type == CREDIT, accountNo == acc.accountNo, date >= ap.start && <= ap.end ) then acc.balance += cf.amount; end

13

acc.balance += cf.amount

CashFlow Rule

Page 14: Classic Games Development with Drools

14

rule "Increase balance for AccountPeriod Credits"when ap : AccountPeriod( ) acc : Account( ) cf : CashFlow( type == CashFlowType.CREDIT, accountNo == acc.accountNo, date >= ap.start && <= ap.end ) then acc.balance = acc.balance + cf.amount;end

rule "Decrease balance for AccountPeriod Debits"when ap : AccountPeriod( ) acc : Account( ) cf : CashFlow( type == CashFlowType.DEBIT, accountNo == acc.accountNo, date >= ap.start && <= ap.end ) then acc.balance = acc.balance - cf.amount;end

CashFlow

date amount type accountNo

12-Jan-12 100 CREDIT 1

2-Feb-12 200 DEBIT 1

18-May-12 50 CREDIT 1

9-Mar-12 75 CREDIT 1

AccountingPeriod

start end

01-JAN-2012 31-MAR-2012

Account

accountNo balance

1 0

CashFlow

date amount type accountNo

12-Jan-12 100 CREDIT 1

9-Mar-12 75 CREDIT 1

CashFlow

date amount type accountNo

2-Feb-12 200 DEBIT 1

Account

accountNo balance

1 -25

CashFlow Example

Page 15: Classic Games Development with Drools

15

rule "Print blance for AccountPeriod" salience -50when ap : AccountPeriod() acc : Account( )then System.out.println( "Account Number " + acc.accountNo + " balance " + acc.balance );end

Agenda

1 increase balance

arbitrary2 decrease balance

3 increase balance

4 print balance

CashFlow Example

Page 16: Classic Games Development with Drools

16

Two Phase

Page 17: Classic Games Development with Drools

17

AccountingPeriod

start end

01-Apr-2012 30-JUN-2012

Account

accountNo balance

1 0

AccountingPeriod

start end

01-JAN-2012 31-MAR-2012

Account

accountNo balance

1 0

update AccountPeriod set start=“01-Apr-2012” end = “31-MAR-2012”

Page 18: Classic Games Development with Drools

18

rule "Increase balance for AccountPeriod Credits"when ap : AccountPeriod( ) acc : Account( ) cf : CashFlow( type == CashFlowType.CREDIT, accountNo == acc.accountNo, date >= ap.start && <= ap.end ) then acc.balance = acc.balance + cf.amount;end

rule "Decrease balance for AccountPeriod Debits"when ap : AccountPeriod( ) acc : Account( ) cf : CashFlow( type == CashFlowType.DEBIT, accountNo == acc.accountNo, date >= ap.start && <= ap.end ) then acc.balance = acc.balance - cf.amount;end

CashFlow

date amount type accountNo

12-Jan-12 100 CREDIT 1

2-Feb-12 200 DEBIT 1

18-May-12 50 CREDIT 1

9-Mar-12 75 CREDIT 1

AccountingPeriod

start end

01-Apr-2012 30-JUN-2012

Account

accountNo balance

1 0

CashFlow

date amount type accountNo

18-May-12 75 CREDIT 1

CashFlow

date amount type accountNo

Account

accountNo balance

1 25

CashFlow Example

Page 19: Classic Games Development with Drools

19

not Bus( color = “red” )

Conditional Elements

exists Bus( color = “red” )

forall ( $bus : Bus( floors == 2 ) Bus( this == $bus, color == “red” ) )

forall ( $bus : Bus( color == “red” ) )

Page 20: Classic Games Development with Drools

Fire System

Page 21: Classic Games Development with Drools

Definitionspublic 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 { }

Page 22: Classic Games Development with Drools

Definitionsrule "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

Page 23: Classic Games Development with Drools

Definitionsrule "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

Page 24: Classic Games Development with Drools

Definitions

rule "Status output when things are ok" when not Alarm() not Sprinkler( on == true ) then println( "Everything is ok" ); end

Page 25: Classic Games Development with Drools

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

Page 26: Classic Games Development with Drools

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

Page 27: Classic Games Development with Drools

Executingksession.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

Page 28: Classic Games Development with Drools

Number Guess

Page 29: Classic Games Development with Drools

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;

Page 30: Classic Games Development with Drools

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;

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(); }}

<kbase name="NumberGuessKB" packages="org.drools.games.numberguess"> <ksession name="NumberGuessKS"/></kbase>

Page 31: Classic Games Development with Drools

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

Page 32: Classic Games Development with Drools

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

Page 33: Classic Games Development with Drools

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

Page 34: Classic Games Development with Drools

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

Page 35: Classic Games Development with Drools

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 guesses\nThe correct guess was " + r.value );end

Page 36: Classic Games Development with Drools

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"] ) ];

Page 37: Classic Games Development with Drools

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"] ) ];

Page 38: Classic Games Development with Drools

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

Page 39: Classic Games Development with Drools

query things(Character $char, List $things) $char := Character() Location( $char, $room; ) $things := List() from accumulate( Location($thing, $room; thing != $char), collectList( $thing ) ) end

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"] ) ];

query exits(Character $char, List $exits) $char := Character() Location( $char, $room; ) $exits := List() from accumulate( connect($room, $exit;), collectList( $exit ) ) end

Page 40: Classic Games Development with Drools

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

Page 41: Classic Games Development with Drools

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

Page 42: Classic Games Development with Drools

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

Page 43: Classic Games Development with Drools

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

Page 44: Classic Games Development with Drools

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

Page 45: Classic Games Development with Drools

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

Page 46: Classic Games Development with Drools
Page 47: Classic Games Development with Drools
Page 48: Classic Games Development with Drools
Page 49: Classic Games Development with Drools
Page 50: Classic Games Development with Drools
Page 51: Classic Games Development with Drools
Page 52: Classic Games Development with Drools
Page 53: Classic Games Development with Drools
Page 54: Classic Games Development with Drools
Page 55: Classic Games Development with Drools