1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4: */
3// +----------------------------------------------------------------------+
4// | PHP version 4                                                        |
5// +----------------------------------------------------------------------+
6// | Copyright (c) 2003 The PHP Group                                     |
7// +----------------------------------------------------------------------+
8// | This source file is subject to version 3.0 of the PHP license,       |
9// | that is bundled with this package in the file LICENSE, and is        |
10// | available through the world-wide-web at                              |
11// | http://www.php.net/license/3_0.txt.                                  |
12// | If you did not receive a copy of the PHP license and are unable to   |
13// | obtain it through the world-wide-web, please send a note to          |
14// | license@php.net so we can mail you a copy immediately.               |
15// +----------------------------------------------------------------------+
16// | Authors: Gregory Beaver <cellog@php.net>                             |
17// +----------------------------------------------------------------------+
18//
19// $Id: Losers.php,v 1.3 2004/04/09 06:22:30 cellog Exp $
20/**
21 * A Losers chess game representation (wild 16 on ICC)
22 * @package Games_Chess
23 * @author Gregory Beaver <cellog@php.net>
24 */
25/**
26 * The parent class
27 */
28require_once 'Games/Chess/Standard.php';
29
30/**
31 * Losers chess game
32 *
33 * The goal of the game is to lose all of your pieces or force your opponent
34 * to checkmate you.  The only differences from standard chess are that if
35 * a capture is possible it must be executed, similar to checkers, and
36 * checkmate actually loses the game!
37 * @package Games_Chess
38 * @author Gregory Beaver <cellog@php.net>
39 */
40class Games_Chess_Losers extends Games_Chess_Standard {
41    /**
42     * Determine whether it is possible to capture an opponent's piece
43     * @access protected
44     */
45    function _capturePossible()
46    {
47        $allmoves = array();
48        $color = $this->_move == 'W' ? 'B' : 'W';
49        foreach ($this->_pieces as $name => $loc) {
50            if (!$loc) {
51                continue;
52            }
53            if ($name{0} == $this->_move) {
54                // don't return castle move shortcuts
55                if ($name{1} == 'P') {
56                    $allmoves = array_merge($allmoves,
57                        $this->getPossibleMoves($loc[1], $loc[0], $this->_move, false));
58                } else {
59                    $allmoves = array_merge($allmoves,
60                        $this->getPossibleMoves($name{1}, $loc, $this->_move, false));
61                }
62            }
63        }
64        foreach ($this->_pieces as $name => $loc) {
65            if ($name{0} == $this->_move || !$loc) {
66                continue;
67            }
68            if (is_array($loc)) {
69                if (in_array($loc[0], $allmoves)) {
70                    return true;
71                }
72            } else {
73                if (in_array($loc, $allmoves)) {
74                    return true;
75                }
76            }
77        }
78        return false;
79    }
80
81    /**
82     * Validate a move
83     * @param array parsed move array from {@link _parseMove()}
84     * @return true|PEAR_Error
85     * @throws GAMES_CHESS_ERROR_MOVE_MUST_CAPTURE
86     * @access protected
87     */
88    function _validMove($move)
89    {
90        list($type, $info) = each($move);
91        if ($this->_capturePossible() &&
92              ($type == GAMES_CHESS_CASTLE ||
93              $this->_board[$info['square']] == $info['square'])) {
94            if ($type == GAMES_CHESS_CASTLE) {
95                $san = $info == 'K' ? 'O-O' : 'O-O-O';
96            } else {
97                $san = $info['piece'] . $info['disambiguate'] . $info['takes'] . $info['square'];
98            }
99            return $this->raiseError(GAMES_CHESS_ERROR_MOVE_MUST_CAPTURE,
100                      array('san' => $san));
101        }
102        return parent::_validMove($move);
103    }
104
105    /**
106     * @return W|B|D winner of game, or draw
107     */
108    function gameOver()
109    {
110        $opposite = $this->_move == 'W' ? 'B' : 'W';
111        if ($this->inCheckmate()) {
112            return $this->_move;
113        }
114        if ($this->inDraw()) {
115            return 'D';
116        }
117        $W = array();
118        $B = array();
119        foreach ($this->_pieces as $name => $loc) {
120            if (!$loc || $name{1} == 'K') {
121                continue;
122            }
123            if ($name{0} == 'W') {
124                $W[] = 1;
125            } else {
126                $B[] = 1;
127            }
128        }
129        if (!count($W)) {
130            return 'W';
131        }
132        if (!count($B)) {
133            return 'B';
134        }
135        return false;
136    }
137}
138?>