Advertisement
wolfsinner

FFXIII-2 Hands of Time Solver

Mar 3rd, 2012
386
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 4.02 KB | None | 0 0
  1. <?php
  2.     /**
  3.      * FFXIII-2 Hands Of Time Solver v0.1b (and probably the only version!)
  4.      * Author: Nuno Melo (c) 2012
  5.      * Final Fantasy and all related stuff is a trademark of Square-Enix and all that stuff.
  6.      *
  7.      * Example usage:
  8.      * try {
  9.      *      //ex: new Puzzle(1,4,2,5,2)
  10.      *      $puzzle = new Puzzle([Pass the clock numbers as arguments from the top-center position, in a clockwise direction]);
  11.      *      $solution = $puzzle->solve();
  12.      *      foreach ($res->getValues() as $node)
  13.      *          echo $node . " ";
  14.      * } catch (Exception $ex){
  15.      *      echo $lang[$ex->getMessage()];
  16.      * }
  17.      *
  18.      * Exceptions:
  19.      * I went with using the top-class Exception, and a string is passed to identify the error. Let's keep it simple.
  20.      * IP -> Too many, or too little nodes.
  21.      * NS -> No solutions were found.
  22.      * IN -> Numbers are out of range.
  23.      * ES -> Empty stack (if you try to pop() in an empty Path object)
  24.      */
  25.     //Constants
  26.     define('MAX_NODES', 13);
  27.     define('MIN_NODES', 5);
  28.    
  29.     //text responses
  30.     $lang = array(
  31.         "IP" => "Nodes out of bounds. 5-13 nodes tops!",
  32.         "ES" => "Stack is empty.",
  33.         "NS" => "No solutions.",
  34.         "IN" => "Invalid numbers. Must be in the [1, 9] E N, range"
  35.     );
  36.    
  37.     /**
  38.      * Represents a full puzzle
  39.      */
  40.     class Puzzle {
  41.        
  42.         private $nodeCount;
  43.         private $move = array();
  44.         private $state = array();
  45.         private $found = FALSE;
  46.        
  47.         function __construct() {
  48.             $this->nodeCount = func_num_args();
  49.             if($this->nodeCount >= MIN_NODES && $this->nodeCount <= MAX_NODES){
  50.                 //initialize state and move
  51.                 for($i = 0, $tmp = func_get_args() ; $i < $this->nodeCount ; $this->state[$i] = TRUE, $this->move[$i] = $tmp[$i],  $i++)
  52.                     if($tmp[$i] < 1 || $tmp[$i] > 9 || !is_int($tmp[$i])) throw new Exception('IN');
  53.             } else throw new Exception('IP');
  54.         }
  55.        
  56.         /**
  57.          * This calls the recursive function.. Starts with the first node, and visits every node until it finds a solution
  58.          */
  59.         public function solve(){
  60.             for($i = 0, $tmp ; !$this->found && $i < $this->nodeCount ; $i++)
  61.                 $tmp = $this->solveRec($this->state, $i, $this->nodeCount, new Path());
  62.             if($tmp != null) return $tmp;
  63.             else throw new Exception('NS');
  64.         }
  65.        
  66.         /**
  67.          * Recursive bruteforce function
  68.          */
  69.         private function solveRec($state, $node, $left, $path){
  70.             //check if a solution has been found or if this node hasn't been visited
  71.             if($this->found == TRUE || $state[$node] == FALSE) return null;
  72.             $left--;
  73.             $path->push($node);
  74.             $state[$node] = FALSE;
  75.             //checks if this is the final node (All other nodes have been visited)
  76.             if($left == 0){
  77.                 $this->found = TRUE;
  78.                 return $path;
  79.             }
  80.             //if not, keep on moving through this node's path if possible
  81.             $links = $this->getNodes($node, $this->move[$node]);
  82.             //is it worth going to the connected nodes?
  83.             if(!$state[$links['left']] && !$state[$links['right']]) return NULL;
  84.             $leftRes = $this->solveRec($state, $links['left'], $left, clone $path);
  85.             $rightRes = $this->solveRec($state, $links['right'], $left, clone $path);
  86.            
  87.             if($leftRes != NULL) return $leftRes;
  88.             else if($rightRes != NULL) return $rightRes;
  89.             else return null;
  90.         }
  91.        
  92.         /**
  93.          * This simply calculates the left and right nodes of a given node using its offset (value).
  94.          */
  95.         private function getNodes($node, $value){
  96.             $left = ($node-$value < 0) ? $this->nodeCount-(abs($node-$value) % $this->nodeCount) : $node-$value;
  97.             return array("left" => $left, "right" => ($node+$value) % $this->nodeCount);
  98.         }
  99.     }
  100.    
  101.     /**
  102.      * Represents a path through the clock, it's similar to a stack (but we're breaking some rules here :) )
  103.      */
  104.     class Path {
  105.        
  106.         private $top = -1;
  107.         private $values = array();
  108.  
  109.         public function push($value){
  110.             $this->top++;
  111.             $this->values[$this->top] = $value;
  112.         }
  113.        
  114.         public function pop(){
  115.             if($this->top < 0) throw new Exception('ES');
  116.             $tmp = $this->values[$this->top];
  117.             $this->top--;
  118.             return $tmp;
  119.         }
  120.        
  121.         public function isEmpty(){ return $this->top < 0; }
  122.        
  123.         public function getValues(){ return $this->values; }
  124.     }
  125.    
  126. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement