2

I am trying to solve a Pacman problem using PDDL. The main thing I need to do is soft code the power duration without using functions or fluents. It returns no error but somehow I feel like it inits Powerlose(n2, n0). I never init Powerlose(n2, n0) or change Powerlose in the effect. But the initial value it gives to c is n2. So what's wrong? Thanks in advance.

You can check the problem and domain through this link: http://editor.planning.domains/#edit_session=bD5G0tIIl1vyWDf

I tried to use exists statement instead of Powerlose(cPlus1, c) on line 34 of the domain file, it does not work. It still init c with n2. I am so confused. Here is my domain file:

(define
    (domain pacman_hard)
    (:requirements :strips :typing :equality :adl)

    (:types
       pos int
    )

    (:predicates
        (PacmanAt ?p - pos)
        (GhostAt ?p - pos)
        (FoodAt ?p - pos)
        (CapsuleAt ?p - pos)
        (PowerCurr ?n - int)
        (PowerLose ?n1 ?n2 - int)
        (PowerGain ?n1 ?n2 - int)
        (Adjacent ?p1 ?p2 - pos)
    )


    (:action move
        :parameters (?posCurr ?posNext - pos ?cPlus1 ?c ?MaxPower - int)
        :precondition (and
                        (and
                        ; check if there is any food left,
                        ; which guarantees all ghosts are eaten before last food
                        (exists (?p - pos) (FoodAt ?p)) 
                        (PacmanAt ?posCurr)
                        (Adjacent ?posCurr ?posNext)
                        (PowerCurr ?cPlus1)
                        (PowerGain ?cPlus1 ?MaxPower)
                        )
                        (or
                        (PowerLose ?cPlus1 ?c) ;powered
                        (not (GhostAt ?posNext))
                        )
                      )
        :effect (and 
                    (PacmanAt ?posNext)
                    (not (PacmanAt ?posCurr))
                    ; update power status accordingly/with priority
                    ; first reduce the time of power
                    (when (PowerLose ?cPlus1 ?c); could minus 1  
                        (and
                        (not (PowerCurr ?cPlus1))
                        (PowerCurr ?c)
                        (not (GhostAt ?posNext))
                        )
                    )

                    ; refresh the power time if in next pos its a capsule
                    (when (CapsuleAt ?posNext)
                        (and
                        (not (PowerCurr ?cPlus1))
                        (not (PowerCurr ?c))
                        (PowerCurr ?MaxPower)
                        )
                    )
                    (not (FoodAt ?posNext))
                    (not (CapsuleAt ?posNext))
                )
    )
)

The problem file:

  problem map
 | 1 | 2 | 3 | 4 | 5 |
-|---|--- ---|---|---|
a| P | _ | _ | G | F |
b| _ | C | _ | G | C |
 |---|---|---|---|---|





(define
    (problem pacman-level-1)
    (:domain pacman_hard)
    (:objects
        a1 a2 a3 a4 a5 b1 b2 b3 b4 b5 - pos
        n0 n1 n2 - int
    )

    (:init
        (PacmanAt a1)
        (GhostAt a4)
        (GhostAt b4)
        (CapsuleAt b2)
        (CapsuleAt b5)
        (FoodAt a5)

        (PowerCurr n0)
        (PowerLose n1 n0)
        (PowerLose n2 n1)

        (PowerGain n0 n2)
        (PowerGain n1 n2)
        (PowerGain n2 n2)


        (Adjacent a1 a2)
        (Adjacent a1 b1)
        (Adjacent b1 a1)
        (Adjacent b1 b2)
        (Adjacent a2 a1)
        (Adjacent a2 b2)
        (Adjacent a2 a3)
        (Adjacent b2 a2)
        (Adjacent b2 b1)
        (Adjacent b2 b3)
        (Adjacent a3 a2)
        (Adjacent a3 b3)
        (Adjacent a3 a4)
        (Adjacent b3 b2)
        (Adjacent b3 a3)
        (Adjacent b3 b4)
        (Adjacent a4 a3)
        (Adjacent a4 b4)
        (Adjacent a4 a5)
        (Adjacent b4 b3)
        (Adjacent b4 a4)
        (Adjacent b4 b5)
        (Adjacent a5 a4)
        (Adjacent a5 b5)
        (Adjacent b5 b4)
        (Adjacent b5 a5)
    )

    (:goal
        ; this would guarantee the pacman has eaten all food and ghosts.
        (forall (?p - pos) 
            (and (not (FoodAt ?p)) (not (GhostAt ?p))) 
        )
    )
)

The plan it returns: (move a1 b1 n0 n2 n2) (move b1 b2 n0 n2 n2) (move b2 b3 n2 n2 n2) (move b3 b4 n2 n1 n2) (move b4 a4 n1 n0 n2) (move a4 a5 n0 n2 n2)

The correct plan: (move a1 b1) (move b1 b2) (move b2 b3) (move b3 b4) (move b4 b5) (move b5 b4) (move b4 a4) (move a4 a5)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Dan
  • 103
  • 7

1 Answers1

2

As an aside, it's always useful to specify what planner (and it's configuration) that you're using.

I loaded your problem into the online editor:

It gave a similar plan (at least start of plan) when I tried solving. I'd suggest doing the same (Solve button is at the top), and looking at the plan. The right side shows the grounded action. First thing to notice is that your Powerlose precondition is part of an or clause, and the other part is certainly satisfied (i.e., (ghostat b1) is false). So that aspect of the precondition is satisfied.

Hopefully, this clears up what might be going on!

haz
  • 625
  • 4
  • 12
  • I used the same planner. I am really confused why the value of c in the first action is n2. I only init Powerlose(n2,n1), Powerlose(n1,n0), and I don't change Powerlose in the effect, then I don't know why c starts with n2. I am really new to this. – Dan May 02 '20 at 00:19
  • Do you think is the problem of `Or`? Like the planner firstly give `c` a value of `n2`, and because `(not (ghostat b1))` is met so the `powerlose(n0, n2)' is added to the add list? – Dan May 02 '20 at 00:22
  • @Dan, can you post the resulting domain to a session and share? It is a very interesting model. – Jan Dolejsi May 03 '20 at 07:36
  • @Jan You can reach out to Nir Lipovetzky -- he runs this Pac-Man assignment as part of his AI course. – haz May 04 '20 at 11:40