package org.drools.games.wumpus

dialect "mvel"

rule "Create Sensor Array" salience 100 when
    Command() 
then
    insert( new SensorArray() );
end

rule "Clear FeelBump" salience 100 when
    Command() 
    $s : FeelBump()
then
    retract( $s );
end

rule "Clear HearScream" salience 100 when
    Command() 
    $s : HearScream()
then
    retract( $s );
end

rule "Direction.UP, Move.TURN_LEFT"  when
    $h  : Hero( direction == Direction.UP)
    $mc : MoveCommand( move == Move.TURN_LEFT )   
then
	retract ( $mc ); 
    modify( $h ) { direction = Direction.LEFT };  
end

rule "Direction.LEFT, MOVE.TURN_LEFT"  when
    $h  : Hero( direction == Direction.LEFT)
    $mc : MoveCommand( move == Move.TURN_LEFT )   
then
	retract ( $mc );
    modify( $h ) { direction = Direction.DOWN };   
end

rule "Direction DOWN,  MOVE.TURN_LEFT" when
    $h  : Hero( direction == Direction.DOWN)
    $mc : MoveCommand( move == Move.TURN_LEFT )   
then
	retract ( $mc );
    modify( $h ) { direction = Direction.RIGHT };   
end

rule "Direction.RIGHT, MOVE.TURN_LEFT" when
    $h  : Hero( direction == Direction.RIGHT )
    $mc : MoveCommand( move == Move.TURN_LEFT )   
then
	retract ( $mc );  
    modify( $h ) { direction = Direction.UP }; 
end

rule "Direction.UP, Move.TURN_RIGHT" when
    $h  : Hero( direction == Direction.UP)
    $mc : MoveCommand( move == Move.TURN_RIGHT )   
then
	retract ( $mc );  
    modify( $h ) { direction = Direction.RIGHT }; 
end

rule "Direction.RIGHT, MOVE.TURN_RIGHT"  when
    $h  : Hero( direction == Direction.RIGHT)
    $mc : MoveCommand( move == Move.TURN_RIGHT )   
then
	retract ( $mc );  
    modify( $h ) { direction = Direction.DOWN }; 
end

rule "Direction DOWN,  MOVE.TURN_RIGHT"  when
    $h  : Hero( direction == Direction.DOWN)
    $mc : MoveCommand( move == Move.TURN_RIGHT )   
then
	retract ( $mc );
    modify( $h ) { direction = Direction.LEFT };   
end

rule "Direction.LEFT, MOVE.TURN_RIGHT"  when
    $h  : Hero( direction == Direction.LEFT )
    $mc : MoveCommand( move == Move.TURN_RIGHT )   
then
	retract ( $mc );
    modify( $h ) { direction = Direction.UP };   
end


rule "Move Up" when
    (($mc : MoveCommand( move == Move.MOVE_FORWARD ) and   
     $h  : Hero(direction == Direction.UP)) or
    ($mc : MoveCommand( move == Move.MOVE_BACKWARD ) and  
     $h  : Hero(direction == Direction.DOWN)))
     $c  : Cell(row == $h.row + 1, col == $h.col )
then
	retract ( $mc );  
    modify( $h ) { row = $h.row + 1 };
    modify( $c ) { hidden = false }; 
end

rule "Move Down" when
    (($mc : MoveCommand( move == Move.MOVE_FORWARD ) and   
     $h  : Hero(direction == Direction.DOWN)) or
    ($mc : MoveCommand( move == Move.MOVE_BACKWARD ) and  
     $h  : Hero(direction == Direction.UP)))
     $c  : Cell(row == $h.row - 1, col == $h.col )
then
	retract ( $mc );  
    modify( $h ) { row = $h.row - 1 };
    modify( $c ) { hidden = false };
end

rule "Move Left" when
    (($mc : MoveCommand( move == Move.MOVE_FORWARD ) and   
     $h  : Hero(direction == Direction.LEFT)) or
    ($mc : MoveCommand( move == Move.MOVE_BACKWARD ) and  
     $h  : Hero(direction == Direction.RIGHT)))
     $c  : Cell(row == $h.row, col == $h.col - 1 )
then
	retract ( $mc );  
    modify( $h ) { col = $h.col - 1 };
    modify( $c ) { hidden = false };
end

rule "Move Right" when
    (($mc : MoveCommand( move == Move.MOVE_FORWARD ) and   
     $h  : Hero(direction == Direction.RIGHT)) or
    ($mc : MoveCommand( move == Move.MOVE_BACKWARD ) and  
     $h  : Hero(direction == Direction.LEFT))) 
     $c  : Cell(row == $h.row, col == $h.col + 1 )
then
	retract ( $mc );  
    modify( $h ) { col = $h.col + 1 };
    modify( $c ) { hidden = false };
end

rule "Invalid Move"   when
     // Invalid Up
     ((($mc : MoveCommand( move == Move.MOVE_FORWARD ) and   
     $h  : Hero(direction == Direction.UP)) or
     ($mc : MoveCommand( move == Move.MOVE_BACKWARD ) and  
     $h  : Hero(direction == Direction.DOWN))) and 
     not Cell(row == $h.row + 1, col == $h.col )) or
    
    // Invalid Down 
     ((($mc : MoveCommand( move == Move.MOVE_FORWARD ) and   
     $h  : Hero(direction == Direction.DOWN)) or
     ($mc : MoveCommand( move == Move.MOVE_BACKWARD ) and  
     $h  : Hero(direction == Direction.UP))) and
     not Cell(row == $h.row - 1, col == $h.col )) or

     // Invalid LEFT
     ((($mc : MoveCommand( move == Move.MOVE_FORWARD ) and   
     $h  : Hero(direction == Direction.LEFT)) or
     ($mc : MoveCommand( move == Move.MOVE_BACKWARD ) and  
     $h  : Hero(direction == Direction.RIGHT))) and
     not Cell(row == $h.row, col == $h.col - 1 )) or
          
     // Invalid RIGHT     
     ((($mc : MoveCommand( move == Move.MOVE_FORWARD ) and   
     $h  : Hero(direction == Direction.RIGHT)) or
     ($mc : MoveCommand( move == Move.MOVE_BACKWARD ) and  
     $h  : Hero(direction == Direction.LEFT))) and
     not Cell(row == $h.row, col == $h.col + 1 ) )        
then
    retract( $mc );
    insert( new FeelBump() );
end

rule "Move Gold" when
    $h : Hero( gold == true ) @watch( col, row )
    $g : Gold()
then
   modify( $g ) { col = $h.col, row = $h.row };
end    

rule "Climb With Gold" when
    $cc : ClimbCommand()
    Hero( gold == true, row == 0, col == 0 )
then
    retract( $cc );
    insert( new GoldWin() );
end

rule "Climb without Gold" when
    $cc : ClimbCommand()
    Hero( gold == false,  row == 0, col == 0 )
then
    retract( $cc );
    insert( new Reset() );
end

rule "Climb retraction"   when
    $cc : ClimbCommand()
    Hero( row != 0 || col != 0 )    
then
    retract( $cc );
end

rule "Grab Gold" when
    $gc : GrabCommand()
    $h  : Hero()
    $g  : Gold(row == $h.row, col == $h.col )
then
    retract ( $gc );   
    modify ( $h ) { gold = true };
end

rule "Smell Stench"  when 
    $h  : Hero() @watch( col, row )
          Wumpus(row == $h.row, col == $h.col ) or    
          Wumpus(row == $h.row + 1, col == $h.col ) or
          Wumpus(row == $h.row - 1, col == $h.col ) or          
          Wumpus(row == $h.row, col == $h.col + 1 ) or
          Wumpus(row == $h.row, col == $h.col - 1 )
then
    insertLogical( new SmellStench() );
end 

rule "Feel Breeze"  when 
    $h  : Hero() @watch( col, row )
          Pit(row == $h.row + 1, col == $h.col ) or
          Pit(row == $h.row - 1, col == $h.col ) or          
          Pit(row == $h.row, col == $h.col + 1 ) or
          Pit(row == $h.row, col == $h.col - 1 )
then
    insertLogical( new FeelBreeze() );
end

rule "See Glitter"  when 
    $h  : Hero( ) @watch( col, row )
          Gold(row == $h.row, col == $h.col )
then
    insertLogical( new SeeGlitter() );
end

rule "Wumpus Death" when
    $h  : Hero() @watch( col, row )
          Wumpus(row == $h.row, col == $h.col, alive == true )
then
    insert( new WumpusDeath() );
end

rule "Pit Death" when
    $h  : Hero() @watch( col, row )
          Pit(row == $h.row, col == $h.col )
then
    insert( new PitDeath() ); 
end

