[Welcome to Sensei's Library!]

StartingPoints
ReferenceSection
About


Referenced by
TheCodeSoFar
TheCodeSoFarASimp...

 

The Code So Far - A Better Life And Death Solver
   

My new solver can deal with n-step problems, and even print out a Sensei's Library compatible solution. Not bad for 650 lines of code! I'll add text/code in a little while: right now I'm off to drink a celebratory beer or six.

 * (printsl (solve (nth 23 *ps1*)))

[Diagram]
Diag.: Black to kill the marked stones.

[Diagram]
Diag.: Solution


The class responsible for look-ahead is the analyzer:

 (defclass Analyzer ()
   ((p :documentation "the problem being solved")
    (g :documentation "the current game state")
    (goal :documentation "the goal of this analyzer")
    (answer :documentation "success or failure")
    (resolved :documentation "t if answer is known")
    (children :documentation "the tree of games after this game state")
    (active-children :documentation "unresolved children")
    (next :documentation "next active child to get a tick"))

The analyzer has a problem and a current game state. It either declares the problem solved, or creates child analyzers that do the min-max search (each child has the inverse goal of its parent: SaveG, save a goup, is the inverse goal of KillG, kill a group, etc.)

"Tick" is the unit of computation: one tick is the time to create a new game state (e.g. playing a stone.) When an Analyzer gets a tick, it can either create a new game state, or pass the tick onto one of its children (round-robin style.) For now, my code doesn't obey the one game-state per tick design goal. Varously crappy short-cuts are also used in deciding life and death (e.g. 3 or more liberties means a group is safe,) but these are probably adequate for GGPFB1.

Observers will have noted that main classes (Position, Game, Analyzer) are all non-destructive (functional) in that they don't alter themselves, they create new versions of themselves that reflect the state change (e.g. a Position plus a Stone creates a new Position without changing the old Position.) This is by design: I get confused when things change underneath me.


The above diagrams were honestly generated by the code!

This method prints the initial problem and the solution:

 (defmethod printsl ((a Analyzer) &optional text)
   (if text
       (print text))
   (printsl (p a))
   (format t *line-break*)
   (if (resolved a)
	 (printsl (main-line a)
                  (if (eq (current-player (game (p a))) *White*)
                      "W Solution"
                     "B Solution"))))

This one does the 1,2,3 thing to explain the play:

 (defmethod printsl ((l Line) &optional text)
   (let* ((as (as l))
	  (pos (copy (pos (g (car as)))))
	  (i 1))
     (dolist (e as)
	     (setf (at pos (last-move (g e)))
                   (make-instance 'Stone 'PChar (character (format nil "~S" i))))
	     (setf i (1+ i)))
     (printsl pos text)))

And this one marks the stones that are the focus of the problem:

 (defmethod printsl ((p Problem) &optional text)
   (if text
       (print text))
   (let ((text (cond
	        ((eq (Action (Goal p)) 'KillG )
                     (format nil " ~A to kill the marked stones."
                             (name (current-player (game p)))))
	        ((eq (Action (Goal p)) 'SaveG )
                     (format nil " ~A to save the marked stones."
                             (name (current-player (game p)))))
	        (t "Unknown goal."))))
     (let ((pos (copy (Pos (Game p)))))
       (cond
        ((or (eq (Action (Goal p)) 'KillG ) (eq (Action (Goal p)) 'SaveG ))
	 (mapcar (lambda (pnt)
                   (setf (at pos pnt)
                         (make-instance 'Stone
                                        'PChar (MChar (at pos pnt)))))
		 (points (at (smap (snake-set (game p))) (Focus (Goal p)))))))
       (printsl pos text))))

Hehe, I love my code:

 * (printsl (solve (nth 24 *ps1*)))

[Diagram]
Diag.: Black to kill the marked stones.


[Diagram]
Diag.: Solution


The new code tears through GradedGoProblemsForBeginners life and death problems until it hits Problem #41.



This is a copy of the living page "The Code So Far - A Better Life And Death Solver" at Sensei's Library.
(C) the Authors, published under the OpenContent License V1.0.