[[php_dhtml:exemple5]]
 
Table of Contents

Exemple 5 - a Marienbad Game

This one is a Marienbad Game1) made with the winApp class.

Result

Code

<?php
/**
 * php_dhtml
 * Copyright (C) 2004  Eric Colinet <e.colinet@laposte.net>
 * http://wildphp.free.fr
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
include_once 'dhtml/winApp.inc';
$GLOBALS['WINAPP_RC_PATH']=  '../rc/winapp_classic/';
 
 
class Marienbad extends winApp {
	var $title= '';
 
	/* Configuration du jeu */
	var $start_game= array( 1, 2, 3, 5, 7 );
	var $game= array( 1, 2, 3, 5, 7 );
	
	/* Parametre de la partie en cours */
	var $current_col= -1;
	var $current_count= 0;
 
	var $current_player= 0;
	var $ia_player= 2;
 
	function Marienbad() {
		$this->title= 'Marienbad Game';
		parent::winApp($this->title, false, true, '450x300');
	}
 
	/**
	 * Global Init
	 */
	function on_init() {
		$this->toolbar->add_button( 'app', 'File', 'buttons/new.png', 
			array(
				'start' => 'Play alone',
				'login' => 'Remotly connect',
				'-',
				'quit' => 'Quit',
				)
			);
		$this->toolbar->add_button( 'undo', 'Game', 'buttons/open.png', 
			array('switch_players' => '<img id="player_starts" src="buttons/checked.jpg">&nbsp;Player starts') ,
			array('undo' => 'Undo')
		);
		$this->toolbar->add_button( 'help', '', 'buttons/help.png',
				array(
					'help_about' => 'About',
					'help_about_php' => 'About Php'
				)
			);
 
		$this->handles_click('allumette', true);
		$this->handles_click('play');
 
		$this->ia_player= 2;
	}	
 
	function on_click( $id ) {
		if( !ereg('^image_([0-9]+)_([0-9]+)$', $id, $matches) ) return;
		if( $this->current_player==$this->ia_player ) { $this->set_status("Your opponent have played - click OK to continue"); return; }
 
		list($foo, $height, $col) = $matches;
 
		/* Row check */
		if( $this->current_col!=-1 && $this->current_col!=$col ) { 
			$this->set_warning("You have already played in ".$this->current_col); 
			return; 
		}
		else $this->current_col= $col;
			
		if( $this->current_count>=$this->game[$col] ) { 
			$this->set_warning("All matches have been removed in ".$this->current_col); 
			return; 
		}
 
		$this->current_count++;
		$this->update_col($this->current_col);
 
		$this->set_status("Played in ".$this->current_col);
	}
 
	/**
	 * Page loading
	 */
	function on_page_load($url) {
		parent::on_page_load($url);
		$this->id_html('window_frame', '<div id="window"></div>');
		$this->start();
	}
 
	function on_command_switch_players() {
		if( $this->ia_player==2 ) $this->ia_player= 1; else  $this->ia_player= 2;
		if( $this->ia_player==2 ) $this->id_img_src('player_starts', 'buttons/checked.jpg');
		else $this->id_img_src('player_starts', 'buttons/unchecked.jpg');
		$this->start();
	}
 
	function on_command_help_about() {
		new MessageBox($this, "Marienbad Game CopyLeft 2004.<br><br><i> The one that remove the last matche loose </i><br>You can remove any number of matches in the same column.<br>Note: The starting player has a <b>BIG</b> advantage.<br>Have Fun !", "About", false, '300x250');
	}
	
	function on_command_help_about_php() {
		about_php($this);
	}
 
	function on_command_start() {
		$this->start();
	}
	
	function on_command_play() {
		$this->play();
	}
	
	function on_command_ia_play() {
		$this->ia_play();
	}
	
	function on_command_quit() {
		$this->close();
	}
	
	function on_command_login() {
		new MessageBox($this, '<h3>Not implemented</h3>');
	}
	
	function start() {
		$this->current_player= 2; // So initial switching set it to 1
		$this->current_col= -1;
		$this->current_count= 0;
		$this->game= $this->start_game;
 
		$this->new_round();
	}
 
	
	function new_round() {
		if( !$this->current_player ) return;
		if( $this->current_player==1 ) $this->current_player= 2; else $this->current_player= 1;
		if( $this->count()==0 ) { // Fin du jeu
			$this->clear();
			if( $this->current_player==$this->ia_player )
				$this->write("<div align='center'><br/><font size='+3'color='red'>You loose ...<br>:-(</font></div>");
			else
				$this->write("<div align='center'><br/><font size='+3' color='green'>Player Win !<br>:-)</font></div>");
			$this->current_player= 0;
			return;
		}
		$this->display_table();
		if( $this->current_player==$this->ia_player ) $this->ia_play();
	}
 
 
	function play() {
		if( $this->current_col==-1 || !$this->current_count ) {
			$this->set_warning('Vous devez choisir une colonne dans laquelle enlever une ou plusieurs allumettes');
			return;
		}
		$this->game[$this->current_col]-= $this->current_count;
		$this->current_col= -1; $this->current_count= 0;
 
		$this->set_status('Ready');
		$this->new_round();
	}
 
	function count() {
		$count= 0;
		foreach( $this->game as $k => $v ) {
			$count+= $v;
		}
		return $count;
	}
 
	function ia_play() {
		$ia= &new Marienbad_IA;
		list($col, $number)= $ia->best($this->game);
		$this->set_status("AI plays in: $col, $number");
		//$this->player_action($col, $number);
		$this->current_col= $col;
		$this->current_count= $number;
		$this->update_cols();
	}
 
	function update_cols() {
		for( $col= 0; $col<count($this->game); $col++ ) {
			$this->update_col($col);
		}
	}
 
	function update_col($col) {
		for( $i= $this->game[$col]-1; $i>=0; $i-- ) {
			if( $this->current_col==$col && $i>=$this->game[$col]-$this->current_count )
				$this->id_img_src('image_'.$i.'_'.$col, realpath('images/allumette_off_h.gif'));
			else
				$this->id_img_src('image_'.$i.'_'.$col, realpath('images/allumette_h.gif'));
		}
	}
 
	function display_table() {
		$max= 7;
		if( $this->current_player==$this->ia_player )
			$game.= "<H3>IA turn <font size=\"-2\">(click ok)</font></H3>";
		else
			$game.= "<H3>Player ".$this->current_player." it's your turn ".($this->current_player==$this->ia_player?"(IA)":'')."</H3>";
		$game.= '<TABLE border="0">';
		for( $i= $max-1; $i>=0; $i-- ) {
			$game.= '<tr height="7">';
			for( $col= 0; $col<count($this->game); $col++ ) {
				if( $this->game[$col]>$i ) {
					$game.= '<TD width="68" style="cursor: pointer" class="rows"><img class="allumette" id="image_'.$i.'_'.$col.'" src="'.realpath('images/allumette_h.gif').'" border="0"></TD>';
				}
				else {
					$game.= '<TD width="68"><img id="image_'.$i.'_'.$col.'" src="'.realpath('images/allumette_black_v.gif').'" border="0"></TD>';
				}
			}
			$game.= '</tr>';
		}
		$game.= '</table>';
 
		if( $this->count() ) {
			$buttons.= ToolBar::build_button(array('play', '', "buttons/button_ok.gif"));
		}
		else {
			$buttons.= '<font size="+2" color="green">Fin !</font>';
		}
 
		$html= <<< EOHTML
<center>
<TABLE border="0" width="100%" height="100%">
<tr>
	<td align="center">$game</td>
</tr>
<tr>
	<td align="right" height="30">$buttons</td>
</tr>
</TABLE>
EOHTML;
		$this->clear();
		$this->write($html);
	}
 
 
	function clear() {
		$this->write_buffer= '';
		$this->id_html('window', $this->write_buffer);
	}
 
	function write( $string ) {
		$this->write_buffer.= $string;
		$this->id_html('window_frame', $this->write_buffer);
	}
	function writeln( $string ) {
		$this->write( $string.'<br/>' );
	}
}
 
 
class Marienbad_IA {
	
	function best($game) {
		$col= $num= 0;
		$count= 0;
		$best_note= -1;
 
		// Get all possible
		$possible= array();
		foreach( $game as $col => $value ) {
			//echo "$col => $value\n";
			for($i= 1; $i<=$value; $i++ ) {
				$possible_game= $game;
				$possible_game[$col]-= $i;
				$note= $this->_eval($possible_game);
				if( $best_note<$note ) $best_note= $note;
				array_push($possible, array($col, $i, $note) );
			}
		}
		if( $best_note==-1 ) // No possible choice
			return -1;
 
		// Get bests
		$bests= array();
		for($i= 0; $i<count($possible); $i++) {
			if( $possible[$i][2]==$best_note ) array_push($bests, array($possible[$i][0], $possible[$i][1]) );
		}
 
		// Randomly choose between bests
		$choose= mt_rand(0,count($bests)-1);
 
		return $bests[$choose];
	}
 
	function _eval($game) {
		$count= 0;
		foreach( $game as $num ) {
			$count+= $num;
		}
		return $count%2*(20-$num); // Plus le nombre est bas plus la note est élevée (mmmh..)
	}
}
 
/* Go */
new Marienbad();
winApp::run();
?>
1) The actual name is: Game of nim
 
  php_dhtml/exemple5.txt · Last modified: 2004/12/03 16:40
 
Recent changes RSS feed Powered by PHP Driven by DokuWiki