; magic.lisp ; 9/3/09 magic.kevinleung.com ;this creates our environment. Our environment is a set of objects in the world. In this case, everything is a creatures, but this might include cards, libraries, players, lands, and more (setq initial* (list '(creature c1 name GrizzlyBears power 2 toughness 2 player 2 status defense) '(creature c2 name HillGiant power 3 toughness 3 player 2 status defense) '(creature c3 name CrawWurm power 6 toughness 4 player 1 status none)) ) ;(push '(creature c4 name KalonianBehemoth power 9 toughness 9 player 2 status defense) initial*) ; junk (defun initialize-world () (setq state* (rcopy initial*)) nil) (defun update-world () nil) (defun preattend () state*) ; a function you don't need to worry about (defun search-state (key value) (dolist (percept state*) (when (equal (second percept) value) ;woo, the hax (return-from search-state percept) ))) ; this is an action that makes the given creature attack (defun *attack (creature) (let* ((object (search-state 'creature creature)) ; searches for the create in the environment that this is referring to (name (member 'name object)) (rest (member 'status object))) (format t "Creature ~a is attacking" (second name)) (setf (cadr rest) 'attacking) ; and sets its state to be attacking ) ) ; another action. Debatable whether a real magic player would make might of oaks an action in itself, but I'm hacking anyways (defun *might-of-oaks (creature) (let* ((object (search-state 'creature creature)) ; finds the creature (name (member 'name object)) (power (member 'power object)) (toughness (member 'toughness object))) (format t "~%before: power ~a toughness ~a~%" power toughness) (setf (cadr power) (+ (cadr power) 7)) ; and changes its power (setf (cadr toughness) (+ (cadr toughness) 7)) ; and toughness. Were this real, again, I would probably need to note this as something that would end at the end of combat (format t "~%Creature ~a is pumped by Might of Oaks~%" (second name)) (format t "~%after : power ~a toughness ~a~%" power toughness) ) ) ; our concepts, being beliefs and percepts (create-concepts ; our first concept ((strongest ?creature1) :percepts ((creature ?creature1)) ;so our belief is based off a percept of a creature. Because ?creature1 is a variable, it is going to test all creatures to see if any of them are the strongest :relations ((not (stronger ?creature2 ?creature1))) ;this is interesting. Strongest is a belief based on another belief. Specifically, stronger. Morever, it's checking against ?creature2, which isn't in our percepts. This is an unbound variable, so ?creature1 must be stronger than all possible values of ?creature2 before it is satisfied ) ; another concept ((stronger ?creature1 ?creature2) :percepts ((creature ?creature1 power ?p1 toughness ?t1) ;here, we can bind additional variables from the state. So it'll pull ?creature1 out of the environment, and assign its corresponding power and toughness at the same time (creature ?creature2 power ?p2 toughness ?t2)) :tests ((>= ?p1 ?t2) ; some simple logic to see if it's satisfied. In this case, these 3 tests combine to check that ?creature1 can kill ?creature2 without dying itself (> ?t1 ?p2) (not (equal ?p1 ?p2))) ;I don't really worry about whether a creature is stronger than another on its own team. This is a hack. ) ; a concept for whether a creature is attacking ((attack ?creature1) :percepts ((creature ?creature1 power ?p1 toughness ?t1 status ?s player 1)) :tests ((equal ?s 'attacking)) ) ; this is a hack as well. All goals must have an associated concept. Optimally, this would check to see if a creature's status is "not attacking" as well since we don't have an infinite supply of might of oaks to ensure that a creature can attack, but that's more work ((attack-set ?creature1) :percepts ((creature ?creature1 power ?p1 toughness ?t1 status ?s player 1)) :tests ((equal ?s 'attacking)) ) ) ; and skills (create-skills ; our goal is to set whether a creature is attacking. This is an example of a hierarchical skills because it must first know that the creature is the strongest before trying to make it attack ((attack-set ?creature) :percepts ((creature ?creature)) :subgoals ((strongest ?creature) (attack ?creature)) ) ; much simpler. It simply has the one action of making a creature attack ((attack ?creature) :percepts ((creature ?creature)) :actions ((*attack ?creature)) ) ; here, the skill of making something the strongest is to pump it, so it makes sense to use the "play might of oaks" action ((strongest ?creature) :percepts ((creature ?creature)) :actions ((*might-of-oaks ?creature)) ) ) ; and we set our goal to be determining whether creature c3, craw wurm, should attack (create-goals (attack-set c3))