/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.drools.examples.pacman

declare Direction
   @role(event)
end 

/**
 * This controls the flow of time in pacman, currently it's slow 500ms, to make it easy to visualise things as
 * they happen
 */
rule IncreaseTick dialect "mvel" salience -1 duration 300 when
    $t : Tick()
then
    modify( $t ) { tock +=  1 };
    //exitPoints["ConsoleExitPoint" ].insert( "tick " + $t.tock + "\n" );
end

/**
 * Retract old Directions
 */
rule RetractOldDirections dialect "mvel" salience 100 when
    $oldD     : Direction()   
    $newD     : Direction( this != $oldD, character == $oldD.character, this after $oldD )
then
    delete( $oldD );
end

/**
 * The current Direction would move the Location into a WALL, so we can't move and need to retract the Direction,
 * so that no futher movement for is attempted
 */
rule InvalidDirection dialect "mvel" when
    $l : Location( )
    $d : Direction( character == $l.character )
    $target : Cell( row == ($l.row + $d.vertical), col == ($l.col + $d.horizontal) )
    $ct : CellContents( cell == $target, cellType == CellType.WALL )
    Tick()        
then
    exitPoints["ConsoleExitPoint"].insert( "retract " + $d + "\n" );
    delete( $d );
end

/**
 * Checks that the current Direction moves to a valid location, i.e. not a WALL.
 * It does not set the new direction straight away, this is because we need movement to be intime
 * with the Tick increase, so we schedule the new Location instead.
 */
rule ValidDirection dialect "mvel" when
    $l : Location( )
    $d : Direction( character == $l.character )
    $target : Cell( row == ($l.row + $d.vertical), col == ($l.col + $d.horizontal) )
    CellContents( cell == $target, cellType != CellType.WALL )
    not ScheduledLocationUpdate( location == $l )    
     $t : Tick()  
then
    insert( new ScheduledLocationUpdate($l.character, $l, $l.row += $d.vertical, $l.col += $d.horizontal, $t.tock + $l.character.speed ) );
end

/**
 * When the Tick increases, update any Locations from inserted scheduled updates.
 */
rule SetNewDirection dialect "mvel" when
    $s : ScheduledLocationUpdate()
    $l : Location( this == $s.location )
    Tick( tock == $s.tock )
then
   exitPoints["ConsoleExitPoint"].insert( "set new Location " + $l + "\n"  );
   modify( $l ) { row = $s.row, col = $s.col };
   delete( $s );
end

/**
 * When all the cells are empty stock the clock (retract the tick), as the level is now finishedW
 */
rule IsLevelFinished dialect "mvel" when
    not CellContents( cellType == CellType.FOOD )
    not CellContents( cellType == CellType.POWER_PILL ) 
    $t : Tick()
then
    delete( $t );
end

rule FinishedCompleted  dialect "mvel" when
    not CellContents( cellType == CellType.FOOD )
    not CellContents( cellType == CellType.POWER_PILL )
    not Tick() 
    $s : Score()
then
    exitPoints["ConsoleExitPoint"].insert( "LEVEL COMPLETED!!!! score = " + $s.score + " \n" );
    kcontext.knowledgeRuntime.halt();
end

rule FinishedKilled  dialect "mvel" when
    $pac    : Character( name == "Pacman" )
    $pacLoc : Location( character == $pac )
    $mon    : Character( name == "Monster" )
    $monLoc : Location( character == $mon, col == $pacLoc.col, row == $pacLoc.row )
    not Tick()    
    $s : Score()
then
    exitPoints["ConsoleExitPoint"].insert( "Killed!!!! score = " + $s.score + " \n" );
    kcontext.knowledgeRuntime.halt();
end
