(define state0
    '((object wheel1) (object wheel2) (object nuts) (object hub)
      (object pump) (object jack) (object wrench) (object boot)
      (container boot) (wheel wheel1) (wheel wheel2) (nut nuts) (hub hub)
      (closed boot) (unlocked boot) (in jack boot) (in pump boot)
      (in wheel2 boot) (intact wheel2) (in wrench boot) (flat wheel2)
      (flat wheel1) (on wheel1 hub) (on-ground wheel1)
      (on-ground hub) (tight nuts wheel1)))
(define goal0
  '((closed boot) (in jack boot) (in pump boot) (in wheel1 boot)
    (in wrench boot) (inflated wheel2) (on wheel2 hub) 
    (tight nuts wheel2)))

(define state1
  '((object pump) (object jack) (object wrench) (object boot)
    (object wheel1) (object wheel2) (object nuts) (object hub)
    (container boot) 
    (wheel wheel1) (wheel wheel2) (nut nuts) (hub hub)
    (closed boot) (unlocked boot) (in jack boot) (in pump boot)
    (in wheel2 boot) (intact wheel2) (in wrench boot) (flat wheel2)
    (flat wheel1) (on wheel1 hub) (on-ground wheel1)
    (on-ground hub) (tight nuts wheel1)))
(define goal1
  '((have jack) (have pump) (have wheel2) (have wrench)))

(define state2
  '((object pump) (object jack) (object wrench) (object boot)
    (object wheel1 wheel) (object wheel2 wheel) (object nuts nut)
    (object hub hub) 
    (container boot) 
    (wheel wheel1) (wheel wheel2) (nut nuts) (hub hub)
    (open boot)(intact wheel2)(have jack) (have pump) (have wheel2)
    (have wrench) (flat wheel2) (flat wheel1) (on wheel1 hub)
    (on-ground wheel1) (on-ground hub) (tight nuts wheel1)))
(define goal2
  '((inflated wheel2) (off-ground wheel1) (off-ground hub)
    (loose nuts wheel1)))

(define state3
  '((object pump) (object jack) (object wrench) (object boot)
    (object wheel1) (object wheel2) (object nuts) (object hub)
    (container boot) 
    (wheel wheel1) (wheel wheel2) (nut nuts) (hub hub)
    (open boot)(intact wheel2) (have jack) (have pump) 
    (have wheel2) (have wrench) (flat wheel1) (on wheel1 hub) 
    (inflated wheel2) (off-ground wheel1) (off-ground hub)
    (loose nuts wheel1)))
(define goal3
  '((on wheel2 hub) (tight nuts wheel2) (on-ground wheel2) (on-ground hub)))

(define state4
  '((object pump) (object jack) (object wrench) (object boot)
    (object wheel1) (object wheel2) (object nuts) (object hub)
    (container boot) 
    (wheel wheel1) (wheel wheel2) (nut nuts) (hub hub)
    (intact wheel2) (have jack) (have pump) (have wheel1)
    (have wrench) (open boot) (flat wheel1)  (inflated wheel2) 
    (on wheel2 hub) (tight nuts wheel2) (on-ground wheel2) (on-ground hub)))
(define goal4
  '((in jack boot) (in pump boot) (in wheel1 boot) (in wrench boot) 
    (inflated wheel2) (on wheel2 hub) (tight nuts wheel2)))

(define state5
  '((object pump) (object jack) (object wrench) (object boot)
    (object wheel1) (object wheel2) (object nuts) (object hub)
    (container boot) 
    (wheel wheel1) (wheel wheel2) (nut nuts) (hub hub)
    (open boot) (in jack boot) (in pump boot) (in wheel1 boot)
    (in wrench boot) (inflated wheel2) (on wheel2 hub) (tight nuts wheel2)))
(define goal5
  '((closed boot) (in jack boot) (in pump boot) (in wheel1 boot)
    (in wrench boot) (inflated wheel2) (on wheel2 hub) (tight nuts wheel2)))

(define state6
  '((flat wheel1) (flat wheel2) (flat wheel3) (flat wheel4)
    (flat wheela) (flat wheelb) (flat wheelc) (flat wheeld)
    (on wheel1 hub1) (on wheel2 hub2) (on wheel3 hub3)
    (on wheel4 hub4) (intact wheela) (intact wheelb)
    (intact wheelc) (intact wheeld) (on-ground hub1) (on-ground hub2)
    (on-ground hub3) (on-ground hub4) (on-ground wheel1)
    (on-ground wheel2) (on-ground wheel3) (on-ground wheel4)
    (tight nuts wheel1) (tight nuts wheel2) (tight nuts wheel3)
    (tight nuts wheel4) (in jack boot) (in pump boot) (in wheela boot)
    (in wheelb boot) (in wheelc boot) (in wheeld boot) (in wrench boot)
    (unlocked boot) (closed boot)
    (object pump) (object jack) (object wrench) (object boot)
    (object nuts)
    (object hub1) (object hub2) (object hub3) (object hub4)
    (hub hub1) (hub hub2) (hub hub3) (hub hub4)
    (object wheel1) (object wheel2) (object wheel3) (object wheel4)
    (object wheela) (object wheelb) (object wheelc) (object wheeld)
    (wheel wheel1) (wheel wheel2) (wheel wheel3) (wheel wheel4)
    (wheel wheela) (wheel wheelb) (wheel wheelc) (wheel wheeld) 
    (container boot)
    (nut nuts)))

(define goal6
  '((inflated wheela) (inflated wheelb) (inflated wheelc)
    (inflated wheeld) (on wheela hub1) (on wheelb hub2) (on wheelc hub3)
    (on wheeld hub4) (on-ground hub1) (on-ground hub2) (on-ground hub3)
    (tight nuts wheela) (tight nuts wheelb) (tight nuts wheelc)
    (tight nuts wheeld) (in jack boot) (in pump boot) (in wheel1 boot)
    (in wrench boot) (closed boot)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; random problems involving the canonical tire changing task.
;;; *tool-facts* contains init facts that do not depend on wheels.
;;; *tool-goals* contains goal facts that do not depend on wheels:
;;;  we have 4 of them.
;;; Each wheel generates 6 different possible subgoals.
;;; Hence, for 1 wheel we have up to 9 subgoals
;;;            2 wheels we have up to 14 subgoals
;;;            3                      19
;;;            ...                    ...
;;;            18                     94
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define *tool-facts*
  '((container boot) (object boot) (object jack) (object pump)
    (object wrench) (object nuts) (nut nuts) (closed boot)
    (unlocked boot) (in jack boot) (in pump boot) (in wrench boot)))

(define *tool-goals*
  '((in jack boot) (in pump boot) (in wrench boot) (closed boot)))

(define *hubs* '(hub1 hub2 hub3 hub4 hub5 hub6 hub7 hub8 hub9 hub10
               hub11 hub12 hub13 hub14 hub15 hub16 hub17 hub18))

(define *new-wheels* '(wheela wheelb wheelc wheeld wheele wheelf wheelg
                     wheelh wheeli wheelj wheelk wheell wheelm wheeln
                     wheelo wheelp wheelq wheelr))

(define *used-wheels* '(wheel1 wheel2 wheel3 wheel4 wheel5 wheel6 wheel7
		      wheel8 wheel9 wheel10 wheel11 wheel12 wheel13 wheel14
                      wheel15 wheel16 wheel17 wheel18))

(define (new-wheel-facts wheels)
  (let((facts '()))
    (for-each (lambda(w) 
		(set! facts (append 
			     facts 
			     (list (list 'object w) (list 'wheel w)
				   (list 'in w 'boot) (list 'intact w)
				   (list 'flat w)))))
	      wheels)
    facts))

(define (used-wheel-facts wheels)
  (let((facts '()))
    (for-each 
     (lambda(w) 
       (let ((h (used-hub-wheel w)))
	 (set! facts (append 
		      facts
		      (list (list 'object w) (list 'wheel w)
			    (list 'object h) (list 'hub h)
			    (list 'flat w) (list 'on w h) (list 'on-ground w)
			    (list 'on-ground h) (list 'tight 'nuts w))))))
     wheels)
    facts))

(define (used-hub-wheel w)
  (case w 
    (wheel1 'hub1) (wheel2 'hub2) (wheel3 'hub3) (wheel4 'hub4) 
    (wheel5 'hub5) (wheel6 'hub6) (wheel7 'hub7) (wheel8 'hub8) 
    (wheel9 'hub9) (wheel10 'hub10) (wheel11 'hub11) (wheel12 'hub12) 
    (wheel13 'hub13) (wheel14 'hub14) (wheel15 'hub15) (wheel16 'hub16) 
    (wheel17 'hub17) (wheel18 'hub18)))

(define (new-hub-wheel w)
  (case w (wheela 'hub1) (wheelb 'hub2) (wheelc 'hub3) (wheeld 'hub4) 
	(wheele 'hub5) (wheelf 'hub6) (wheelg 'hub7) (wheelh 'hub8) 
	(wheeli 'hub9) (wheelj 'hub10) (wheelk 'hub11) (wheell 'hub12) 
	(wheelm 'hub13) (wheeln 'hub14) (wheelo 'hub15) (wheelp 'hub16) 
	(wheelq 'hub17) (wheelr 'hub18)))

(define (new-wheel-goals wheels)
  (let ((facts '()))
    (for-each 
     (lambda(w) 
       (let ((h (new-hub-wheel w)))
	 (set! facts (append 
		      facts
		      (list (list 'on w h) (list 'tight 'nuts w) 
			    (list 'inflated w)
			    (list 'on-ground h))))))
     wheels)
    facts))

(define (used-wheel-goals wheels)
  (let ((facts '()))
    (for-each 
     (lambda(w) (set! facts (append facts (list (list 'in w 'boot)))))
     wheels)
    facts))

(define (random-world numgoals)
  "Select an initial world state that allows numgoals different subgoals"
  ;; num-hubs: how many different hubs are necessary to have numgoals
  (let* ((num-hubs (min 18 (max 1 (ceiling (/ (- numgoals 4) 5)))))
         (nwheels (sublist *new-wheels* 0 num-hubs))
         (uwheels (sublist *used-wheels* 0 num-hubs)))
    (append *tool-facts*
	    (new-wheel-facts nwheels)
	    (used-wheel-facts uwheels))))

(define (random-goal numgoals)
  "Select a subgoal list of size numgoals"
  (let* ((num-hubs (min 18 (max 1 (ceiling (/ (- numgoals 4) 5)))))
         (nwheels (sublist *new-wheels* 0 num-hubs))
         (uwheels (sublist *used-wheels* 0 num-hubs))
         (goals (append (new-wheel-goals (list (car nwheels)))
                        (used-wheel-goals (list (car uwheels)))
                        *tool-goals*
                        (new-wheel-goals (cdr nwheels))
                        (used-wheel-goals (cdr uwheels)))))
    (sublist goals 0 (min numgoals (length goals)))))


