Package org.gojul.fourinaline.model

Source Code of org.gojul.fourinaline.model.HumanGameClient$SimpleObserver

/*
* HumanGameClient.java
*
* Created: 2008/02/23
*
* Copyright (C) 2008 Julien Aubin
*
* 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.
*
* 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.
*
* 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.
*/
package org.gojul.fourinaline.model;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Observable;
import java.util.Observer;

import org.gojul.fourinaline.model.GameModel.GameModelException;
import org.gojul.fourinaline.model.GameModel.GameStatus;
import org.gojul.fourinaline.model.GameServer.PlayerRegisterException;
import org.gojul.fourinaline.model.GameServer.ServerTicket;
import org.gojul.fourinaline.model.GameServer.ServerTicketException;

/**
* The <code>HumanGameClient</code> class represents a human player
* game client.<br/>
* This game client may be shipped with a GUI or a simple user interface,
* depending on the needs.
*
* @author Julien Aubin
*/
public final class HumanGameClient extends GameClient
  /**
   * The game model.
   */
  private GameModel currentGameModel;
 
  /**
   * Constructor.
   * @param gameServer the game server.
   * @param ticket the server ticket.
   * @param playerName the player name.
   * @throws NullPointerException if any method parameter is null.
   * @throws PlayerRegisterException if there's an error while registering
   * the player which has for name <code>playerName</code>.
   * @throws RemoteException if a remote error occurs while registering the game.
   * @throws ServerTicketException if no more server ticket is available.
   */ 
  public HumanGameClient(final GameServer gameServer, final ServerTicket ticket, final String playerName)
    throws NullPointerException, PlayerRegisterException, RemoteException, ServerTicketException
  {
    super(gameServer, ticket, playerName);
    currentGameModel = null;
  }
 
  /**
   * Returns the game model used.
   * @return the game model used.
   */
  public synchronized GameModel getGameModel()
  {
    return currentGameModel;
  }

  /**
   * @see java.lang.Runnable#run()
   */
  public void run()
  {
    // The thread stops if the server is no longer running,
    // or at the first exception encountered.
    while (isConnectedToServer())
    {
     
      try
      {         
        GameModel gameModel = getServer().getGame(getPlayer().getPlayerMark(), getTicket());
       
        boolean isGameRunning = true;
       
        synchronized(this)
        {         
          // We only notify the observers in case of an update of the game model
          if ((gameModel != null && !gameModel.equals(currentGameModel))
              || (currentGameModel != null && gameModel == null))
          {
            setChanged();
          }
         
          currentGameModel = gameModel;
         
          // We evaluate the if() condition in a thread safe environment
          // in order to avoid bad stuff with multithread.
          isGameRunning = getServer().isGameRunning() && currentGameModel != null;
        }
       
        notifyObservers();
       
        // In case the game is running, the process self-blocks until the next turn
        // at line getServer().getGame()
        // Otherwise we need to sleep a bit in order to avoid a high CPU consumption
        if (!isGameRunning)
        {
          // The sleep process is here to avoid the use of an infinite
          // loop which would consume a lot of CPU.
          try
          {
            Thread.sleep(SERVER_STATUS_UPDATE_PERIOD);
          }
          catch (InterruptedException e)
          {
            throw new RuntimeException(e.getMessage());
          }
        }
      }
      catch (RemoteException e)
      {
        // Avoids blocking the server by having too many dead client.
        disconnect();
        throw new RuntimeException(e.getMessage());
      }
    }

    setChanged();   
    notifyObservers();
  }
 
  /**
   * Plays at column <code>columnIndex</code>.
   * @param columnIndex the column index where we want to play.
   * @throws GameModelException if the play is not valid.
   * @throws RemoteException if an external error occurs.
   */
  public synchronized void play(final int columnIndex) throws GameModelException, RemoteException
  {   
    if (currentGameModel != null
      && currentGameModel.getGameStatus().equals(GameStatus.CONTINUE_STATUS)
      && currentGameModel.getCurrentPlayer().equals(getPlayer().getPlayerMark()))
    {
      getServer().play(columnIndex, getPlayer().getPlayerMark(), currentGameModel, getTicket());
     
      // We play locally AFTER having notified the server because we must be
      // sync to the server when notifying it !!!
      currentGameModel.play(columnIndex, getPlayer().getPlayerMark());
     
      setChanged();
      notifyObservers();
    }
  }
 
  /**
   * The <code>SimpleObserver</code> class is a simple command-line
   * game observer for debug purposes.
   *
   * @author Julien Aubin
   */
  private final static class SimpleObserver implements Observer
  {
   
    /**
     * The input reader.
     */
    private BufferedReader inputReader;
   
    /**
     * Constructor.
     * @throws IOException if an I/O error occurs while initializing
     * the observer.
     */
    public SimpleObserver() throws IOException
    {
      inputReader = new BufferedReader(new InputStreamReader(System.in));
    }

    /**
     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    public void update(final Observable o, final Object arg)
    {
      if (inputReader == null) {
        throw new RuntimeException("FATAL : input reader not initialized. Aborting...");
      }
     
      if (o != null && o instanceof HumanGameClient)
      {       
        HumanGameClient client = (HumanGameClient) o;
       
        System.out.println("Current status : ");
                       
        System.out.println(client.getGameModel());
       
        try
        {
          if (client.getServer().isGameRunning() && client.getGameModel() != null)
          {
            System.out.println("?");
       
            boolean isPlaySuccessful = false;
       
            while (!isPlaySuccessful)
            {
              try
              {
                String line = inputReader.readLine();
               
                if (line != null) {
                  int colIndex = Integer.parseInt(line);         
                  client.play(colIndex);               
                  isPlaySuccessful = true;
                }
              }
              catch (Throwable t)
              {
                System.err.println(t.getMessage());
              }
            }
          }
          else
            System.out.println("Game halted.");
        }
        catch (Throwable t)
        {
          t.printStackTrace();
        }
      }
    }
   
  }

  public static void main(String[] args) throws Throwable
  {
    if (GameServerImpl.startDaemon(false))
    {
      Registry registry = LocateRegistry.getRegistry("127.0.0.1");
     
      GameServer gameServer = (GameServer) registry.lookup(GameServer.STUB_NAME);
     
      HumanGameClient playerClient = new HumanGameClient(gameServer, gameServer.getTicket(), "Julek");
      playerClient.addObserver(new SimpleObserver());
      new Thread(playerClient).start();
      new Thread(new AIGameClient(gameServer, gameServer.getTicket(), "bougo", new DefaultEvalScore(), 4)).start();
     
      gameServer.newGame(playerClient.getTicket());
    }
  }
}
TOP

Related Classes of org.gojul.fourinaline.model.HumanGameClient$SimpleObserver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.