app menu - and a demo application 'tictac'
This commit is contained in:
parent
0bf8e418a8
commit
642a71ffde
661
addon/tictac/tictac.php
Normal file
661
addon/tictac/tictac.php
Normal file
|
@ -0,0 +1,661 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
function tictac_install() {
|
||||||
|
register_hook('app_menu', 'addon/tictac/tictac.php', 'tictac_app_menu');
|
||||||
|
}
|
||||||
|
|
||||||
|
function tictac_uninstall() {
|
||||||
|
unregister_hook('app_menu', 'addon/tictac/tictac.php', 'tictac_app_menu');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function tictac_app_menu($a,&$b) {
|
||||||
|
$b['app_menu'] .= '<a href="tictac">Three Dimensional Tic-Tac-Toe</a><br />';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function tictac_module() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function tictac_content(&$a) {
|
||||||
|
|
||||||
|
$o = '';
|
||||||
|
|
||||||
|
if($_POST['move']) {
|
||||||
|
$handicap = $a->argv[1];
|
||||||
|
$mefirst = $a->argv[2];
|
||||||
|
$dimen = $a->argv[3];
|
||||||
|
$yours = $a->argv[4];
|
||||||
|
$mine = $a->argv[5];
|
||||||
|
|
||||||
|
$yours .= $_POST['move'];
|
||||||
|
}
|
||||||
|
elseif($a->argc > 1) {
|
||||||
|
$handicap = $a->argv[1];
|
||||||
|
$dimen = 3;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$dimen = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
$o .= '<h3>3D Tic-Tac-Toe</h3><br />';
|
||||||
|
|
||||||
|
$t = new tictac($dimen,$handicap,$mefirst,$yours,$mine);
|
||||||
|
$o .= $t->play();
|
||||||
|
|
||||||
|
$o .= '<a href="tictac">New game</a><br />';
|
||||||
|
$o .= '<a href="tictac/1">New game with handicap</a><br />';
|
||||||
|
$o .= <<< EOT
|
||||||
|
<p>
|
||||||
|
Three dimensional tic-tac-toe is just like the traditional game except that it is played on multiple levels simultaneously. In this case there are three levels. You win by getting three in a row on any level, as well as up, down, and diagonally across the different levels.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The handicap game disables the center position on the middle level because the player claiming this square often has an unfair advantage.
|
||||||
|
</p>
|
||||||
|
EOT;
|
||||||
|
return $o;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class tictac {
|
||||||
|
private $dimen;
|
||||||
|
private $first_move = true;
|
||||||
|
private $handicap = 0;
|
||||||
|
private $yours;
|
||||||
|
private $mine;
|
||||||
|
private $winning_play;
|
||||||
|
private $you;
|
||||||
|
private $me;
|
||||||
|
private $debug = 1;
|
||||||
|
private $crosses = array('011','101','110','112','121','211');
|
||||||
|
|
||||||
|
/*
|
||||||
|
'001','010','011','012','021',
|
||||||
|
'101','110','111','112','121',
|
||||||
|
'201','210','211','212','221');
|
||||||
|
*/
|
||||||
|
|
||||||
|
private $corners = array(
|
||||||
|
'000','002','020','022',
|
||||||
|
'200','202','220','222');
|
||||||
|
|
||||||
|
private $planes = array(
|
||||||
|
array('000','001','002','010','011','012','020','021','022'), // horiz 1
|
||||||
|
array('100','101','102','110','111','112','120','121','122'), // 2
|
||||||
|
array('200','201','202','210','211','212','220','221','222'), // 3
|
||||||
|
array('000','010','020','100','110','120','200','210','220'), // vert left
|
||||||
|
array('000','001','002','100','101','102','200','201','202'), // vert top
|
||||||
|
array('002','012','022','102','112','122','202','212','222'), // vert right
|
||||||
|
array('020','021','022','120','121','122','220','221','222'), // vert bot
|
||||||
|
array('010','011','012','110','111','112','210','211','212'), // left vertx
|
||||||
|
array('001','011','021','101','111','221','201','211','221'), // top vertx
|
||||||
|
array('000','001','002','110','111','112','220','221','222'), // diag top
|
||||||
|
array('020','021','022','110','111','112','200','201','202'), // diag bot
|
||||||
|
array('000','010','020','101','111','121','202','212','222'), // diag left
|
||||||
|
array('002','012','022','101','111','121','200','210','220'), // diag right
|
||||||
|
array('002','011','020','102','111','120','202','211','220'), // diag x
|
||||||
|
array('000','011','022','100','111','122','200','211','222') // diag x
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
private $winner = array(
|
||||||
|
array('000','001','002'), // board 0 winners - left corner across
|
||||||
|
array('000','010','020'), // down
|
||||||
|
array('000','011','022'), // diag
|
||||||
|
array('001','011','021'), // middle-top down
|
||||||
|
array('010','011','012'), // middle-left across
|
||||||
|
array('002','011','020'), // right-top diag
|
||||||
|
array('002','012','022'), // right-top down
|
||||||
|
array('020','021','022'), // bottom-left across
|
||||||
|
array('100','101','102'), // board 1 winners
|
||||||
|
array('100','110','120'),
|
||||||
|
array('100','111','122'),
|
||||||
|
array('101','111','121'),
|
||||||
|
array('110','111','112'),
|
||||||
|
array('102','111','120'),
|
||||||
|
array('102','112','122'),
|
||||||
|
array('120','121','122'),
|
||||||
|
array('200','201','202'), // board 2 winners
|
||||||
|
array('200','210','220'),
|
||||||
|
array('200','211','222'),
|
||||||
|
array('201','211','221'),
|
||||||
|
array('210','211','212'),
|
||||||
|
array('202','211','220'),
|
||||||
|
array('202','212','222'),
|
||||||
|
array('220','221','222'),
|
||||||
|
array('000','100','200'), // top-left corner 3d
|
||||||
|
array('000','101','202'),
|
||||||
|
array('000','110','220'),
|
||||||
|
array('000','111','222'),
|
||||||
|
array('001','101','201'), // top-middle 3d
|
||||||
|
array('001','111','221'),
|
||||||
|
array('002','102','202'), // top-right corner 3d
|
||||||
|
array('002','101','200'),
|
||||||
|
array('002','112','222'),
|
||||||
|
array('002','111','220'),
|
||||||
|
array('010','110','210'), // left-middle 3d
|
||||||
|
array('010','111','212'),
|
||||||
|
array('011','111','211'), // middle-middle 3d
|
||||||
|
array('012','112','212'), // right-middle 3d
|
||||||
|
array('012','111','210'),
|
||||||
|
array('020','120','220'), // bottom-left corner 3d
|
||||||
|
array('020','110','200'),
|
||||||
|
array('020','121','222'),
|
||||||
|
array('020','111','202'),
|
||||||
|
array('021','121','221'), // bottom-middle 3d
|
||||||
|
array('021','111','201'),
|
||||||
|
array('022','122','222'), // bottom-right corner 3d
|
||||||
|
array('022','121','220'),
|
||||||
|
array('022','112','202'),
|
||||||
|
array('022','111','200')
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
function __construct($dimen,$handicap,$mefirst,$yours,$mine) {
|
||||||
|
$this->dimen = 3;
|
||||||
|
$this->handicap = (($handicap) ? 1 : 0);
|
||||||
|
$this->mefirst = (($mefirst) ? 1 : 0);
|
||||||
|
$this->yours = str_replace('XXX','',$yours);
|
||||||
|
$this->mine = $mine;
|
||||||
|
$this->you = $this->parse_moves('you');
|
||||||
|
$this->me = $this->parse_moves('me');
|
||||||
|
|
||||||
|
if(strlen($yours))
|
||||||
|
$this->first_move = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function play() {
|
||||||
|
|
||||||
|
if($this->first_move) {
|
||||||
|
if(rand(0,1) == 1) {
|
||||||
|
$o .= '<div class="errmsg">You go first...</div><br />';
|
||||||
|
$this->mefirst = 0;
|
||||||
|
$o .= $this->draw_board();
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
$o .= '<div class="errmsg">I\'m going first this time...</div><br />';
|
||||||
|
$this->mefirst = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->check_youwin()) {
|
||||||
|
$o .= '<div class="errmsg">You won!</div><br />';
|
||||||
|
$o .= $this->draw_board();
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->fullboard())
|
||||||
|
$o .= 'Cat game!';
|
||||||
|
|
||||||
|
$move = $this->winning_move();
|
||||||
|
if(strlen($move)) {
|
||||||
|
$this->mine .= $move;
|
||||||
|
$this->me = $this->parse_moves('me');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$move = $this->defensive_move();
|
||||||
|
if(strlen($move)) {
|
||||||
|
$this->mine .= $move;
|
||||||
|
$this->me = $this->parse_moves('me');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$move = $this->offensive_move();
|
||||||
|
if(strlen($move)) {
|
||||||
|
$this->mine .= $move;
|
||||||
|
$this->me = $this->parse_moves('me');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->check_iwon())
|
||||||
|
$o .= '<div class="errmsg">I won!</div><br />';
|
||||||
|
if($this->fullboard())
|
||||||
|
$o .= 'Cat game!';
|
||||||
|
$o .= $this->draw_board();
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_moves($player) {
|
||||||
|
if($player == 'me')
|
||||||
|
$str = $this->mine;
|
||||||
|
if($player == 'you')
|
||||||
|
$str = $this->yours;
|
||||||
|
$ret = array();
|
||||||
|
while(strlen($str)) {
|
||||||
|
$ret[] = substr($str,0,3);
|
||||||
|
$str = substr($str,3);
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function check_youwin() {
|
||||||
|
for($x = 0; $x < count($this->winner); $x ++) {
|
||||||
|
if(in_array($this->winner[$x][0],$this->you) && in_array($this->winner[$x][1],$this->you) && in_array($this->winner[$x][2],$this->you)) {
|
||||||
|
$this->winning_play = $this->winner[$x];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function check_iwon() {
|
||||||
|
for($x = 0; $x < count($this->winner); $x ++) {
|
||||||
|
if(in_array($this->winner[$x][0],$this->me) && in_array($this->winner[$x][1],$this->me) && in_array($this->winner[$x][2],$this->me)) {
|
||||||
|
$this->winning_play = $this->winner[$x];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function defensive_move() {
|
||||||
|
|
||||||
|
for($x = 0; $x < count($this->winner); $x ++) {
|
||||||
|
if(($this->handicap) && in_array('111',$this->winner[$x]))
|
||||||
|
continue;
|
||||||
|
if(in_array($this->winner[$x][0],$this->you) && in_array($this->winner[$x][1],$this->you) && (! in_array($this->winner[$x][2],$this->me)))
|
||||||
|
return($this->winner[$x][2]);
|
||||||
|
if(in_array($this->winner[$x][0],$this->you) && in_array($this->winner[$x][2],$this->you) && (! in_array($this->winner[$x][1],$this->me)))
|
||||||
|
return($this->winner[$x][1]);
|
||||||
|
if(in_array($this->winner[$x][1],$this->you) && in_array($this->winner[$x][2],$this->you) && (! in_array($this->winner[$x][0],$this->me)))
|
||||||
|
return($this->winner[$x][0]);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function winning_move() {
|
||||||
|
|
||||||
|
for($x = 0; $x < count($this->winner); $x ++) {
|
||||||
|
if(($this->handicap) && in_array('111',$this->winner[$x]))
|
||||||
|
continue;
|
||||||
|
if(in_array($this->winner[$x][0],$this->me) && in_array($this->winner[$x][1],$this->me) && (! in_array($this->winner[$x][2],$this->you)))
|
||||||
|
return($this->winner[$x][2]);
|
||||||
|
if(in_array($this->winner[$x][0],$this->me) && in_array($this->winner[$x][2],$this->me) && (! in_array($this->winner[$x][1],$this->you)))
|
||||||
|
return($this->winner[$x][1]);
|
||||||
|
if(in_array($this->winner[$x][1],$this->me) && in_array($this->winner[$x][2],$this->me) && (! in_array($this->winner[$x][0],$this->you)))
|
||||||
|
return($this->winner[$x][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function offensive_move() {
|
||||||
|
|
||||||
|
shuffle($this->planes);
|
||||||
|
shuffle($this->winner);
|
||||||
|
shuffle($this->corners);
|
||||||
|
shuffle($this->crosses);
|
||||||
|
|
||||||
|
if(! count($this->me)) {
|
||||||
|
if($this->handicap) {
|
||||||
|
$p = $this->uncontested_plane();
|
||||||
|
foreach($this->corners as $c)
|
||||||
|
if((in_array($c,$p))
|
||||||
|
&& (! $this->is_yours($c)) && (! $this->is_mine($c)))
|
||||||
|
return($c);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if((! $this->marked_yours(1,1,1)) && (! $this->marked_mine(1,1,1)))
|
||||||
|
return '111';
|
||||||
|
$p = $this->uncontested_plane();
|
||||||
|
foreach($this->crosses as $c)
|
||||||
|
if((in_array($c,$p))
|
||||||
|
&& (! $this->is_yours($c)) && (! $this->is_mine($c)))
|
||||||
|
return($c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->handicap) {
|
||||||
|
if(count($this->me) >= 1) {
|
||||||
|
if(count($this->get_corners($this->me)) == 1) {
|
||||||
|
if(in_array($this->me[0],$this->corners)) {
|
||||||
|
$p = $this->my_best_plane();
|
||||||
|
foreach($this->winner as $w) {
|
||||||
|
if((in_array($w[0],$this->you))
|
||||||
|
|| (in_array($w[1],$this->you))
|
||||||
|
|| (in_array($w[2],$this->you)))
|
||||||
|
continue;
|
||||||
|
if(in_array($w[0],$this->corners)
|
||||||
|
&& in_array($w[2],$this->corners)
|
||||||
|
&& in_array($w[0],$p) && in_array($w[2],$p)) {
|
||||||
|
if($this->me[0] == $w[0])
|
||||||
|
return($w[2]);
|
||||||
|
elseif($this->me[0] == $w[2])
|
||||||
|
return($w[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$r = $this->get_corners($this->me);
|
||||||
|
if(count($r) > 1) {
|
||||||
|
$w1 = array(); $w2 = array();
|
||||||
|
foreach($this->winner as $w) {
|
||||||
|
if(in_array('111',$w))
|
||||||
|
continue;
|
||||||
|
if(($r[0] == $w[0]) || ($r[0] == $w[2]))
|
||||||
|
$w1[] = $w;
|
||||||
|
if(($r[1] == $w[0]) || ($r[1] == $w[2]))
|
||||||
|
$w2[] = $w;
|
||||||
|
}
|
||||||
|
if(count($w1) && count($w2)) {
|
||||||
|
foreach($w1 as $a) {
|
||||||
|
foreach($w2 as $b) {
|
||||||
|
if((in_array($a[0],$this->you))
|
||||||
|
|| (in_array($a[1],$this->you))
|
||||||
|
|| (in_array($a[2],$this->you))
|
||||||
|
|| (in_array($b[0],$this->you))
|
||||||
|
|| (in_array($b[1],$this->you))
|
||||||
|
|| (in_array($b[2],$this->you)))
|
||||||
|
continue;
|
||||||
|
if(($a[0] == $b[0]) && ! $this->is_mine($a[0])) {
|
||||||
|
return $a[0];
|
||||||
|
}
|
||||||
|
elseif(($a[2] == $b[2]) && ! $this->is_mine($a[2])) {
|
||||||
|
return $a[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//&& (count($this->me) == 1) && (count($this->you) == 1)
|
||||||
|
// && in_array($this->you[0],$this->corners)
|
||||||
|
// && $this->is_neighbor($this->me[0],$this->you[0])) {
|
||||||
|
|
||||||
|
// Yuck. You foiled my plan. Since you obviously aren't playing to win,
|
||||||
|
// I'll try again. You may keep me busy for a few rounds, but I'm
|
||||||
|
// gonna' get you eventually.
|
||||||
|
|
||||||
|
// $p = $this->uncontested_plane();
|
||||||
|
// foreach($this->crosses as $c)
|
||||||
|
// if(in_array($c,$p))
|
||||||
|
// return($c);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// find all the winners containing my points.
|
||||||
|
$mywinners = array();
|
||||||
|
foreach($this->winner as $w)
|
||||||
|
foreach($this->me as $m)
|
||||||
|
if((in_array($m,$w)) && (! in_array($w,$mywinners)))
|
||||||
|
$mywinners[] = $w;
|
||||||
|
|
||||||
|
// find all the rules where my points are in the center.
|
||||||
|
$trythese = array();
|
||||||
|
if(count($mywinners)) {
|
||||||
|
foreach($mywinners as $w) {
|
||||||
|
foreach($this->me as $m) {
|
||||||
|
if(($m == $w[1]) && ($this->uncontested_winner($w))
|
||||||
|
&& (! in_array($w,$trythese)))
|
||||||
|
$trythese[] = $w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$myplanes = array();
|
||||||
|
for($p = 0; $p < count($this->planes); $p ++) {
|
||||||
|
if($this->handicap && in_array('111',$this->planes[$p]))
|
||||||
|
continue;
|
||||||
|
foreach($this->me as $m)
|
||||||
|
if((in_array($m,$this->planes[$p]))
|
||||||
|
&& (! in_array($this->planes[$p],$myplanes)))
|
||||||
|
$myplanes[] = $this->planes[$p];
|
||||||
|
}
|
||||||
|
shuffle($myplanes);
|
||||||
|
|
||||||
|
// find all winners which share an endpoint, and which are uncontested
|
||||||
|
$candidates = array();
|
||||||
|
if(count($trythese) && count($myplanes)) {
|
||||||
|
foreach($trythese as $t) {
|
||||||
|
foreach($this->winner as $w) {
|
||||||
|
if(! $this->uncontested_winner($w))
|
||||||
|
continue;
|
||||||
|
if((in_array($t[0],$w)) || (in_array($t[2],$w))) {
|
||||||
|
foreach($myplanes as $p)
|
||||||
|
if(in_array($w[0],$p) && in_array($w[1],$p) && in_array($w[2],$p) && ($w[1] != $this->me[0]))
|
||||||
|
if(! in_array($w,$candidates))
|
||||||
|
$candidates[] = $w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find out if we are about to force a win.
|
||||||
|
// Looking for two winning vectors with a common endpoint
|
||||||
|
// and where we own the middle of both - we are now going to
|
||||||
|
// grab the endpoint. The game isn't yet over but we've already won.
|
||||||
|
|
||||||
|
if(count($candidates)) {
|
||||||
|
foreach($candidates as $c) {
|
||||||
|
if(in_array($c[1],$this->me)) {
|
||||||
|
// return endpoint
|
||||||
|
foreach($trythese as $t)
|
||||||
|
if($t[0] == $c[0])
|
||||||
|
return($t[0]);
|
||||||
|
elseif($t[2] == $c[2])
|
||||||
|
return($t[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find opponents planes
|
||||||
|
$yourplanes = array();
|
||||||
|
for($p = 0; $p < count($this->planes); $p ++) {
|
||||||
|
if($this->handicap && in_array('111',$this->planes[$p]))
|
||||||
|
continue;
|
||||||
|
if(in_array($this->you[0],$this->planes[$p]))
|
||||||
|
$yourplanes[] = $this->planes[$p];
|
||||||
|
}
|
||||||
|
|
||||||
|
shuffle($this->winner);
|
||||||
|
foreach($candidates as $c) {
|
||||||
|
|
||||||
|
// We now have a list of winning strategy vectors for our second point
|
||||||
|
// Pick one that will force you into defensive mode.
|
||||||
|
// Pick a point close to you so we don't risk giving you two
|
||||||
|
// in a row when you block us. That would force *us* into
|
||||||
|
// defensive mode.
|
||||||
|
// We want: or: not:
|
||||||
|
// X|O| X| | X| |
|
||||||
|
// |0| O|O| |O|
|
||||||
|
// | | | | |O|
|
||||||
|
|
||||||
|
if(count($this->you) == 1) {
|
||||||
|
foreach($this->winner as $w) {
|
||||||
|
if(in_array($this->me[0], $w) && in_array($c[1],$w)
|
||||||
|
&& $this->uncontested_winner($w)
|
||||||
|
&& $this->is_neighbor($this->you[0],$c[1])) {
|
||||||
|
return($c[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// You're somewhere else entirely or have made more than one move
|
||||||
|
// - any strategy vector which puts you on the defense will have to do
|
||||||
|
|
||||||
|
foreach($candidates as $c) {
|
||||||
|
foreach($this->winner as $w) {
|
||||||
|
if(in_array($this->me[0], $w) && in_array($c[1],$w)
|
||||||
|
&& $this->uncontested_winner($w)) {
|
||||||
|
return($c[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// worst case scenario, no strategy we can play,
|
||||||
|
// just find an empty space and take it
|
||||||
|
|
||||||
|
for($x = 0; $x < $this->dimen; $x ++)
|
||||||
|
for($y = 0; $y < $this->dimen; $y ++)
|
||||||
|
for($z = 0; $z < $this->dimen; $z ++)
|
||||||
|
if((! $this->marked_yours($x,$y,$z))
|
||||||
|
&& (! $this->marked_mine($x,$y,$z))) {
|
||||||
|
if($this->handicap && $x == 1 && $y == 1 && $z == 1)
|
||||||
|
continue;
|
||||||
|
return(sprintf("%d%d%d",$x,$y,$z));
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function marked_yours($x,$y,$z) {
|
||||||
|
$str = sprintf("%d%d%d",$x,$y,$z);
|
||||||
|
if(in_array($str,$this->you))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function marked_mine($x,$y,$z) {
|
||||||
|
$str = sprintf("%d%d%d",$x,$y,$z);
|
||||||
|
if(in_array($str,$this->me))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_yours($str) {
|
||||||
|
if(in_array($str,$this->you))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_mine($str) {
|
||||||
|
if(in_array($str,$this->me))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_corners($a) {
|
||||||
|
$total = array();
|
||||||
|
if(count($a))
|
||||||
|
foreach($a as $b)
|
||||||
|
if(in_array($b,$this->corners))
|
||||||
|
$total[] = $b;
|
||||||
|
return $total;
|
||||||
|
}
|
||||||
|
|
||||||
|
function uncontested_winner($w) {
|
||||||
|
if($this->handicap && in_array('111',$w))
|
||||||
|
return false;
|
||||||
|
$contested = false;
|
||||||
|
if(count($this->you)) {
|
||||||
|
foreach($this->you as $you)
|
||||||
|
if(in_array($you,$w))
|
||||||
|
$contested = true;
|
||||||
|
}
|
||||||
|
return (($contested) ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function is_neighbor($p1,$p2) {
|
||||||
|
list($x1,$y1,$z1) = sscanf($p1, "%1d%1d%1d");
|
||||||
|
list($x2,$y2,$z2) = sscanf($p2, "%1d%1d%1d");
|
||||||
|
|
||||||
|
if((($x1 == $x2) || ($x1 == $x2+1) || ($x1 == $x2-1)) &&
|
||||||
|
(($y1 == $y2) || ($y1 == $y2+1) || ($y1 == $y2-1)) &&
|
||||||
|
(($z1 == $z2) || ($z1 == $z2+1) || ($z1 == $z2-1)))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function my_best_plane() {
|
||||||
|
|
||||||
|
$second_choice = array();
|
||||||
|
shuffle($this->planes);
|
||||||
|
for($p = 0; $p < count($this->planes); $p ++ ) {
|
||||||
|
$contested = 0;
|
||||||
|
if($this->handicap && in_array('111',$this->planes[$p]))
|
||||||
|
continue;
|
||||||
|
if(! in_array($this->me[0],$this->planes[$p]))
|
||||||
|
continue;
|
||||||
|
foreach($this->you as $m) {
|
||||||
|
if(in_array($m,$this->planes[$p]))
|
||||||
|
$contested ++;
|
||||||
|
}
|
||||||
|
if(! $contested)
|
||||||
|
return($this->planes[$p]);
|
||||||
|
if($contested == 1)
|
||||||
|
$second_choice = $this->planes[$p];
|
||||||
|
}
|
||||||
|
return $second_choice;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function uncontested_plane() {
|
||||||
|
$freeplane = true;
|
||||||
|
shuffle($this->planes);
|
||||||
|
$pl = $this->planes;
|
||||||
|
|
||||||
|
for($p = 0; $p < count($pl); $p ++ ) {
|
||||||
|
if($this->handicap && in_array('111',$pl[$p]))
|
||||||
|
continue;
|
||||||
|
foreach($this->you as $m) {
|
||||||
|
if(in_array($m,$pl[$p]))
|
||||||
|
$freeplane = false;
|
||||||
|
}
|
||||||
|
if(! $freeplane) {
|
||||||
|
$freeplane = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if($freeplane)
|
||||||
|
return($pl[$p]);
|
||||||
|
}
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
function fullboard() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw_board() {
|
||||||
|
if(! strlen($this->yours))
|
||||||
|
$this->yours = 'XXX';
|
||||||
|
$o .= "<form action=\"tictac/{$this->handicap}/{$this->mefirst}/{$this->dimen}/{$this->yours}/{$this->mine}\" method=\"post\" />";
|
||||||
|
for($x = 0; $x < $this->dimen; $x ++) {
|
||||||
|
$o .= '<table>';
|
||||||
|
for($y = 0; $y < $this->dimen; $y ++) {
|
||||||
|
$o .= '<tr>';
|
||||||
|
for($z = 0; $z < $this->dimen; $z ++) {
|
||||||
|
$s = sprintf("%d%d%d",$x,$y,$z);
|
||||||
|
$winner = ((is_array($this->winning_play) && in_array($s,$this->winning_play)) ? " color: #FF0000; " : "");
|
||||||
|
$bordertop = (($y != 0) ? " border-top: 2px solid #000;" : "");
|
||||||
|
$borderleft = (($z != 0) ? " border-left: 2px solid #000;" : "");
|
||||||
|
if($this->handicap && $x == 1 && $y == 1 && $z == 1)
|
||||||
|
$o .= "<td style=\"width: 25px; height: 25px; $bordertop $borderleft\" align=\"center\"> </td>";
|
||||||
|
elseif($this->marked_yours($x,$y,$z))
|
||||||
|
$o .= "<td style=\"width: 25px; height: 25px; $bordertop $borderleft $winner\" align=\"center\">X</td>";
|
||||||
|
elseif($this->marked_mine($x,$y,$z))
|
||||||
|
$o .= "<td style=\"width: 25px; height: 25px; $bordertop $borderleft $winner\" align=\"center\">O</td>";
|
||||||
|
else {
|
||||||
|
$val = sprintf("%d%d%d",$x,$y,$z);
|
||||||
|
$o .= "<td style=\"width: 25px; height: 25px; $bordertop $borderleft\" align=\"center\"><input type=\"checkbox\" name=\"move\" value=\"$val\" onclick=\"this.form.submit();\" /></td>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$o .= '</tr>';
|
||||||
|
}
|
||||||
|
$o .= '</table><br />';
|
||||||
|
}
|
||||||
|
$o .= '</form>';
|
||||||
|
return $o;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
3
boot.php
3
boot.php
|
@ -196,6 +196,7 @@ class App {
|
||||||
public $timezone;
|
public $timezone;
|
||||||
public $interactive = true;
|
public $interactive = true;
|
||||||
public $plugins;
|
public $plugins;
|
||||||
|
public $apps;
|
||||||
|
|
||||||
private $scheme;
|
private $scheme;
|
||||||
private $hostname;
|
private $hostname;
|
||||||
|
@ -2453,7 +2454,7 @@ if(! function_exists('get_plink')) {
|
||||||
function get_plink($item) {
|
function get_plink($item) {
|
||||||
$a = get_app();
|
$a = get_app();
|
||||||
$plink = (((x($item,'plink')) && (! $item['private'])) ? '<div class="wall-item-links-wrapper"><a href="'
|
$plink = (((x($item,'plink')) && (! $item['private'])) ? '<div class="wall-item-links-wrapper"><a href="'
|
||||||
. $item['plink'] . '" title="' . t('link to source') . '"><img src="' . $a->get_baseurl() . '/images/remote-link.gif" alt="' . t('link to source') . '" /></a></div>' : '');
|
. $item['plink'] . '" title="' . t('link to source') . '" target="external-link" ><img src="' . $a->get_baseurl() . '/images/remote-link.gif" alt="' . t('link to source') . '" /></a></div>' : '');
|
||||||
return $plink;
|
return $plink;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,10 @@
|
||||||
$a->page['nav'] .= '<a id="nav-register-link" class="nav-commlink" href="register" >'
|
$a->page['nav'] .= '<a id="nav-register-link" class="nav-commlink" href="register" >'
|
||||||
. t('Register') . "</a>\r\n";
|
. t('Register') . "</a>\r\n";
|
||||||
|
|
||||||
|
if(strlen($a->apps)) {
|
||||||
|
$a->page['nav'] .= '<a id="nav-apps-link" class="nav-link" href="apps">' . t('Apps') . "</a>\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
$a->page['nav'] .= '<a id="nav-search-link" class="nav-link" href="search">' . t('Search') . "</a>\r\n";
|
$a->page['nav'] .= '<a id="nav-search-link" class="nav-link" href="search">' . t('Search') . "</a>\r\n";
|
||||||
$a->page['nav'] .= '<a id="nav-directory-link" class="nav-link" href="directory">' . t('Directory') . "</a>\r\n";
|
$a->page['nav'] .= '<a id="nav-directory-link" class="nav-link" href="directory">' . t('Directory') . "</a>\r\n";
|
||||||
|
|
||||||
|
|
12
index.php
12
index.php
|
@ -113,6 +113,13 @@ else
|
||||||
check_config($a);
|
check_config($a);
|
||||||
|
|
||||||
|
|
||||||
|
$arr = array('app_menu' => $a->apps);
|
||||||
|
|
||||||
|
call_hooks('app_menu', $arr);
|
||||||
|
|
||||||
|
$a->apps = $arr['app_menu'];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* We have already parsed the server path into $->argc and $a->argv
|
* We have already parsed the server path into $->argc and $a->argv
|
||||||
|
@ -132,10 +139,9 @@ else
|
||||||
* further processing.
|
* further processing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
if(strlen($a->module)) {
|
if(strlen($a->module)) {
|
||||||
if(is_array($a->plugins) && in_array($a->module,$a->plugins) && file_exists("addon/{$a->module}/{$a->module}.php")) {
|
if(is_array($a->plugins) && in_array($a->module,$a->plugins) && file_exists("addon/{$a->module}/{$a->module}.php")) {
|
||||||
include("addon/{$a->module}/{$a->module}.php");
|
include_once("addon/{$a->module}/{$a->module}.php");
|
||||||
if(function_exists($a->module . '_module'))
|
if(function_exists($a->module . '_module'))
|
||||||
$a->module_loaded = true;
|
$a->module_loaded = true;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +161,8 @@ if(strlen($a->module)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* initialise content region */
|
/* initialise content region */
|
||||||
|
|
||||||
if(! x($a->page,'content'))
|
if(! x($a->page,'content'))
|
||||||
|
|
Loading…
Reference in a new issue