/**
 * This applet demonstrates a simple game. It isn't designed to be general or reusable.
<p>
 * Copyright (C) 2006  <A HREF="http://www.cs.ubc.ca/spider/poole/">David Poole</A>.
<p>
 * This program gives core of the simulation. The GUI is in <A HREF=SGameGUI.java">SGameGUI.java</A>.  The environemnt code is at <A HREF="SGameEnv.java">SGameEnv.java</A>. The controller is at <A HREF="SGameController.java">SGameController.java</A>.
<p>
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
<p>
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
<p>
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.


 * @author David Poole  poole@cs.ubc.ca
 * @version 0.41 2007-09-09 */

public class TGameController
{
    // Change this if you modify the controller - it is printed by the GUI
	String title = "hand-coded controller";
	public String getTitle() {
		return title;
	}

    TGameEnv environment;
    public TGameEnv getEnvironment() {
    	return environment;
    }
    public boolean tracing=false;

    public boolean sarsa=false;

    // Some parameters the GUI sets (not used, but might be useful)
    double discount = 0.9;
    public double getDiscount() {
    	return discount;
    }
    public void setDiscount(double newDisc) {
    	discount = newDisc;
    }
    
    boolean alphaFixed = false;
    public boolean getAlphaFixed() {
    	return alphaFixed;
    }
    public void setAlphaFixed(boolean newVal) {
    	alphaFixed=newVal;
    }
    
    double alpha = 0.1;
    public double getAlpha() {
    	return alpha;
    }
    public void setAlpha(double newVal) {
    	alpha=newVal;
    }

    /**
       This is not used in this controller, but is overridden by learning controllers.

       It doesn't mean anything. The GUI uses it to display values and for the arrows.  
       It is used if a controller wants to display Q values (or other values)
     */
    public double qvalue(int xval, int yval, int action) 
    {
	return 0.0;
    };

    /**
     * Construct a new controller
    */
    TGameController(TGameEnv environment) {
	this.environment=environment;
    }

    /**
     * resets the Q-values.
     *
     * this is overridden by learning controllers
     * @param initVal   the initial value given by a box in the GUI
     */
    public void doreset(double initVal)
    {     
    }


    /**
     * does one step.
     *
     * carries out the action in the environment. This may be a place
     * to record what the agent has learned from its experience.
     *
     *
     <p>
     The actions are
     <ul>
     <li> 0 is up
     <li> 1 is right
     <li> 2 is careful up
     <li> 3 is left
     </ul>
     * @param action  the action that the agent does
     */
    public void dostep(int action)  { 
    	environment.dostep(action);
    }



    /**
     * does count number of steps
     *
     * This is where you would put your controller
     * @param count  the number of steps to do
     * @param greedyProb  the probability that is step is chosen greedily
     */
    public void doSteps(int count, double greedyProb){
	for(int i=0; i<count; i++)
	    {
 		double rand = Math.random();
		if (rand<greedyProb)
		    {// act greedily 
			int bestDir;
			if (environment.currY>0 ) // agent is not at top
			    bestDir = 2;  // go careful-up
			else 
			    bestDir=3;    //go left
			dostep(bestDir);
		    }
 		else
		    { // act randomly
			dostep((int) (Math.random() * 4));
		    }
	    }
    }

    /** This can optionally return a set of real values to dosplay.
     **/
    public double[] toDisplay()
    {
	return null;
    }
}

