Ejemplo n.º 1
0
function main_control()
{
    // These globals are used in the HTML template
    global $current_player, $history;
    global $heading, $name_white, $name_black;
    global $show_command_form, $flip_board;
    global $preset_from_value, $preset_to_value, $id_focus;
    global $chess_board_markup, $history_markup, $promotion_dialog_markup;
    global $board_encoded, $game_title, $turn_nr;
    global $history_next, $history_prev;
    global $href_this, $href_player, $href_flip;
    global $game_state_link, $hmw_home_link;
    // Initialize a bit
    $promotion_popup = false;
    //...NYI Show pawn promotion dialog
    $show_command_form = true;
    // Show the move input dialog
    $game_status = IN_PROGRESS;
    // The game has not ended yet
    $heading = '';
    // "White's move" caption
    $game_title = '';
    // Current game info for page title
    $game_state_link = '';
    // "Send this link"-link ..
    $hmw_home_link = '';
    // .. corrected for my stupid router
    //... Remember an initial double move of a pawn
    $get_en_passant = get_parameter(GET_EN_PASSANT);
    $new_en_passant = '';
    // Retreive GET data
    $flip_board = isset($_GET[GET_FLIP_BOARD]);
    $history = get_parameter(GET_HISTORY);
    $goto = get_parameter(GET_GOTO);
    $name_white = get_parameter(GET_WHITE, DEFAULT_NAME_WHITE);
    $name_black = get_parameter(GET_BLACK, DEFAULT_NAME_BLACK);
    if (get_parameter(GET_PLAYER, GET_WHITE) != GET_WHITE) {
        //  &player  set, but not to "white", is taken as "black"
        $current_player = BLACKS_MOVE;
    } else {
        $current_player = WHITES_MOVE;
    }
    // Load base positions of pieces
    $base_array = decode_board(get_parameter(GET_BASE_BOARD, INITIAL_BOARD_CODED));
    // Trace history (Reconstruct the current board from initial positions)
    //...list( $board_array, $tie_info ) = decode_history(
    $board_array = decode_history($base_array, $history, $goto);
    // Execute given command
    // Retreive FORM input
    // Move: "from" and "to" must be field names
    // Edit: "from" must be the code character for a piece and "to" a field
    $clickable = $selected = array();
    $redirect_after_move = false;
    $cmd_piece = get_parameter(GET_FROM);
    $cmd_from = strtoupper(get_parameter(GET_FROM));
    // Retreive commands
    $cmd_to = strtoupper(get_parameter(GET_TO));
    if ($cmd_from == $cmd_to) {
        // Deselect a piece
        $cmd_from = $cmd_to = '';
    }
    if ($cmd_from == '') {
        $cmd_to = '';
    }
    // Never allow only TO command
    // Exec: Editor
    if (strlen($cmd_from) == 1 && valid_field_name($cmd_to)) {
        if (strpos(WHITE_PIECES . BLACK_PIECES, $cmd_from) !== false) {
            list($row, $col) = field_to_rowcol($cmd_to);
            if ($base_array[$row][$col] == $cmd_piece) {
                // Delete existing piece
                $base_array[$row][$col] = '';
            } else {
                if ($base_array[$row][$col] == '') {
                    // Add new piece
                    $base_array[$row][$col] = $cmd_piece;
                }
            }
            #$base_array = $board_array;
            $redirect_after_move = true;
        }
        // No other commands with FROM being only one char.
        $cmd_from = $cmd_to = '';
    }
    // Make sure, no invalid data is being processed as a move
    if (!valid_field_name($cmd_from)) {
        $cmd_from = '';
    }
    if (!valid_field_name($cmd_to)) {
        $cmd_to = '';
    }
    // Exec: Move
    if ($cmd_from != '' && $cmd_to != '') {
        $turn_nr = i_to_round($history);
        if ($turn_nr - floor($turn_nr) == 0.5) {
            $turn_nr = floor($turn_nr);
            $color = 'Black';
        } else {
            $color = 'White';
        }
        debug_out($_SERVER['REMOTE_ADDR'] . " - {$name_white} vs. {$name_black}, {$turn_nr}, {$color}: {$cmd_from} - {$cmd_to}\n");
        list($f_row, $f_col) = field_to_rowcol($cmd_from);
        list($t_row, $t_col) = field_to_rowcol($cmd_to);
        list($clickable, $selected) = select_piece($board_array, $current_player, $cmd_from, $get_en_passant);
        // Check if it is our//... piece (or a piece at all)
        if (!in_array($cmd_from, $clickable)) {
            die("Error: clickable[{$f_row}][{$f_col}] empty.");
        }
        if (!in_array($cmd_to, $clickable)) {
            // Capturing a piece!
            echo "Capture! clickable = ";
            print_r($clickable);
            die;
        }
        // En passant
        $piece = $board_array[$f_row][$f_col];
        if ($piece == 'P' && $f_row == 1 || $piece == 'p' && $f_row == 6) {
            if ($t_row == 3 || $t_row == 4) {
                $get_en_passant = chr(ord('A') + $f_col);
            }
        }
        if ($piece == 'P' && $t_row - $f_row == +1 || $piece == 'p' && $t_row - $f_row == -1 || $piece != 'P' && $piece != 'p') {
            $get_en_passant = '';
        }
        // Promotion
        if ($piece == 'P' && $t_row == 7 || $piece == 'p' && $t_row == 0) {
            $href_this = update_href($href_this, GET_PROMOTE, chr(ord('A') + $t_col));
            $promotion_popup = true;
            $heading = 'Promote your pawn to:';
            $board_array = apply_move($board_array, $f_row, $f_col, $t_row, $t_col);
        }
        // New move applied, prepare for fresh move
        $clickable = $selected = array();
        $cmd_from = $cmd_to = '';
        // Fall through to NO COMMAND mode
        $current_player = !$current_player;
        $history .= encode_move($f_row, $f_col, $t_row, $t_col);
        // We changed the board, but the user's browser still shows the
        // move command in its address bar. An HTTP redirect is used to
        // update that address, but the URL is not determined yet
        if (!$promotion_popup) {
            $redirect_after_move = true;
        }
    }
    // Exec: Deselect, continuation of fall throughs above
    if ($cmd_from == '' && $cmd_to == '') {
        $clickable = find_movable_pieces($board_array, $current_player);
        // Get rid of moves with king in check afterwards
        $new = array();
        foreach ($clickable as $from_field) {
            // Get two arrays (clickable, selected)
            $temp = select_piece($board_array, $current_player, $from_field);
            // Ignore moves with only one "deselection entry"
            if (count($temp[0]) > 1) {
                $new[] = $from_field;
            }
        }
        $clickable = $new;
        if (count($clickable) == 0) {
            if (king_in_check($board_array, $current_player)) {
                $heading = HEADING_CHECK_MATE;
                $game_status = $current_player != WHITES_MOVE ? WHITE_WINS : BLACK_WINS;
            } else {
                $heading = HEADING_STALE_MATE;
                $game_status = NOONE_WINS;
            }
        }
    }
    // Exec: Select piece
    if ($cmd_from != '' && $cmd_to == '' && $goto == '') {
        list($clickable, $selected) = select_piece($board_array, $current_player, $cmd_from);
        $heading = 'Select target';
    }
    // Prepare move command form
    $preset_from_value = $cmd_from;
    $preset_to_value = $cmd_to;
    $id_focus = $preset_from_value == '' ? 'idFrom' : 'idTo';
    // Generate links for main menu and board markup (pieces)
    $board_encoded = encode_board($base_array);
    // Name parameter as code for who's player's term this is
    $p = $current_player == WHITES_MOVE ? GET_WHITE : GET_BLACK;
    $href_this = update_href();
    // get base link
    $href_this = update_href($href_this, GET_FROM, $preset_from_value);
    $href_this = update_href($href_this, GET_TO, $preset_to_value);
    $href_this = update_href($href_this, GET_PLAYER, $p);
    $href_this = update_href($href_this, GET_HISTORY, $history);
    $href_this = update_href($href_this, GET_WHITE, $name_white);
    $href_this = update_href($href_this, GET_BLACK, $name_black);
    $href_this = update_href($href_this, GET_EN_PASSANT, $get_en_passant);
    $href_this = update_href($href_this, GET_BASE_BOARD, $board_encoded);
    if ($flip_board) {
        $href_this = update_href($href_this, GET_FLIP_BOARD, '');
        $href_flip = update_href($href_this, GET_FLIP_BOARD, REMOVE_FROM_LINK);
    } else {
        $href_flip = update_href($href_this, GET_FLIP_BOARD, '');
    }
    if ($current_player == BLACKS_MOVE) {
        $href_player = update_href($href_this, GET_PLAYER, GET_WHITE);
    } else {
        $href_player = update_href($href_this, GET_PLAYER, GET_BLACK);
    }
    // HTTP redirect?
    if (!false && $redirect_after_move) {
        if (DEBUG) {
            #die( "Continue: <a href='$href_this'>$href_this</a>" );
        }
        // Game state has been updated. In case of an executed move,
        // the browser needs to reload the page with the updated URL:
        header('HTTP/1.0 303 Found');
        header('Location: ' . htmlspecialchars_decode($href_this));
        die;
    }
    // Create HTML markup
    // History
    $history_markup = history_markup($base_array, $history, $href_this, $name_white, $name_black, $game_status);
    // Promotion
    if ($promotion_popup) {
        $promotion_dialog_markup = promotion_dialog_markup($href_this, $current_player, $t_row, $t_col, $history);
        $clickable = $selected = array();
    } else {
        $promotion_dialog_markup = '';
    }
    // Board
    if (STEADY_BOARD && $current_player == BLACKS_MOVE) {
        //... GET switch
        $flip_board = !$flip_board;
    }
    if (isset($_GET[GET_GOTO])) {
        $clickable = $selected = array();
    } else {
        if ($history > '' && $cmd_from == $cmd_to) {
            if (substr($history, -4, 1) == '(') {
                // Skip promotion
                $selected[] = decode_field(substr($history, -3, 1));
                $selected[] = decode_field(substr($history, -6, 1));
            } else {
                // Normal move
                $selected[] = decode_field(substr($history, -2, 1));
                $selected[] = decode_field(substr($history, -1, 1));
            }
        }
    }
    $chess_board_markup = chess_board_markup($href_this, $board_array, $clickable, $selected, $current_player, $flip_board);
    // If no heading was set above, say who's next
    if ($goto != '') {
        $current_player = $goto % 2 != 0;
    }
    if ($heading == '') {
        $heading = $current_player ? $name_white : $name_black;
        $heading = ucfirst($heading) . "'";
        if (substr($heading, -2, 1) != 's') {
            $heading .= 's';
        }
        $heading .= ' move';
    }
    if (king_in_check($board_array, $current_player) && strpos($heading, 'mate') === false) {
        $heading .= ' - <strong>Check!</strong>';
    }
    if ($goto != '') {
        $turn_nr = goto_to_round($history, $goto);
        $heading = "Round {$turn_nr}, {$heading}";
    }
    $heading = get_parameter(GET_COMMENT, $heading);
    // Game title
    if (isset($_GET[GET_WHITE])) {
        $turn_nr = i_to_round($history);
        $game_title = "{$name_white} vs. {$name_black} - Turn #{$turn_nr} - ";
    }
    $turn_nr = floor($turn_nr);
    // History links
    $next_goto = ($goto + 1) % (count_moves($history) + 1);
    $history_next = update_href($href_this, GET_GOTO, $next_goto);
    $next_goto = ($goto + count_moves($history)) % (count_moves($history) + 1);
    $history_prev = update_href($href_this, GET_GOTO, $next_goto);
    // Links for copy and paste
    if (!isset($_GET[GET_NEW_GAME]) && !isset($_GET[GET_BASE_BOARD]) && isset($_SERVER['HTTP_REFERER']) && $_SERVER['QUERY_STRING'] != '' && $cmd_from == '' && $cmd_to == '') {
        // Empty referer: Not reached by clicking a link in the browser
        $t = str_replace('&amp;', '&', $href_this);
        $game_state_link = str_replace(' ', '+', $t);
        $home_IPs = array('192.168.14.1', '213.47.94.176', 'local.at');
        foreach ($home_IPs as $ip_address) {
            if (strpos($game_state_link, $ip_address) !== false) {
                $hmw_home_link = str_replace($ip_address, 'harald.ist.org/home', $game_state_link);
            }
        }
        if ($hmw_home_link != '') {
            $game_state_link = $hmw_home_link;
        }
        $game_state_link = str_replace('flip&', '', $game_state_link);
        $game_state_link = str_replace('&', '&amp;', $game_state_link);
    }
    debug_out("board_encoded = {$board_encoded}\n");
}
Ejemplo n.º 2
0
/**
 * possible_move_list() - returns fields a piece can move to
 */
function possible_move_list($board_array, $current_player, $from_field)
{
    $ret = array();
    list($row, $col) = field_to_rowcol($from_field);
    $piece_codes = get_player_pieces($current_player);
    $piece = $board_array[$row][$col];
    if ($piece == '') {
        die("Error: possible_move_list(): board_array[{$row}][{$col}] Empty field selected?");
    }
    $b = $board_array;
    $c = $current_player;
    $f = $from_field;
    if (strpos($piece_codes, $piece) !== false) {
        switch (strtolower($piece)) {
            case 'p':
                $ret = pawn_move_list($b, $c, $f);
                break;
            case 's':
                // Fall through: Not yet mode rook
            // Fall through: Not yet mode rook
            case 'r':
                $ret = rook_move_list($b, $c, $f);
                break;
            case 'n':
                $ret = knight_move_list($b, $c, $f);
                break;
            case 'b':
                $ret = bishop_move_list($b, $c, $f);
                break;
            case 'q':
                $ret = queen_move_list($b, $c, $f);
                break;
            case 'l':
                // Fall through: Not yet moved king
            // Fall through: Not yet moved king
            case 'k':
                $ret = king_move_list($b, $c, $f, $piece);
                break;
            default:
                die('Error: possible_move_list(): unknown piece.');
        }
    }
    return $ret;
}
Ejemplo n.º 3
0
/**
 * history_markup()
 * See  decode_history  in  game_logic.php , it was the template for this
 * function. The coded history string is analyzed 2 chars at a time, because
 * the main portion of content will be from-to codes for moves on the board.
 * If a from-code is a round left paranthesis, these 2 bytes and the following
 * 2 contain information of a promotion. Those 4 bytes are considered an "empty"
 * or not counted round, regarding the output move list. 
 */
function history_markup($board, $history, $href_this, $name_white, $name_black, $prompt)
{
    $history .= '__';
    // Add code representing the "?" prompt
    $goto = get_parameter(GET_GOTO);
    $link = '';
    $class = HISTORY_BREAK_UL ? '' : ' class="scrolling"';
    $ret = "<h2><strong>{$name_white}</strong>" . " vs. <strong>{$name_black}</strong></h2>\n" . "<ul{$class}>\n";
    $current_move = 0;
    //... Newly introduced. Routine might need cleanup.
    $promotions = 0;
    // Nr. of promotions, each leading to 4 chars of
    //  $history  being skipped
    $length = strlen($history);
    for ($i = 0; $i < $length; $i += 2) {
        // Extract 2 char instruction from history
        // (Usually from-field and to-field codes or possibly
        // promotion of a pawn into another piece)
        $from_code = substr($history, $i, 1);
        $to_code = substr($history, $i + 1, 1);
        if (HISTORY_BREAK_UL && $i > 0 && ($i - 4 * $promotions) % 80 == 0) {
            $ret .= "</ul><ul>\n";
        }
        switch ($from_code) {
            case '_':
                // Last item, show prompt /////////////////////////
                if ($i % 4 == 0) {
                    if (HISTORY_LINK_BACK) {
                        $link = $href_this;
                    }
                    $ret .= "\t<li>";
                    $nr = i_to_round($history, $i);
                    $ret .= $nr . ': ';
                    if (HISTORY_LINK_BACK) {
                        $ret .= "<a href=\"{$link}\">";
                    } else {
                        $ret .= '<span>';
                    }
                }
                $ret .= $prompt;
                break;
            case '(':
                // Pawn Promotion /////////////////////////////////
                //... This section used to be larger and is now almost
                //... obsolete, integrate into "Move" section!
                $i += 2;
                $promotions++;
                break;
            default:
                // Move ////////////////////////////////////////////
                $new_move = '';
                $current_move++;
                $current_color = $current_move % 2 == WHITES_MOVE;
                $opponent_color = !$current_color;
                $from_field = decode_field($from_code);
                $to_field = decode_field($to_code);
                list($f_row, $f_col) = field_to_rowcol($from_field);
                list($t_row, $t_col) = field_to_rowcol($to_field);
                if ($i % 4 == 0) {
                    if (HISTORY_LINK_BACK) {
                        if ($i < $length) {
                            $link = history_link($href_this, $current_move, WHITES_MOVE);
                        } else {
                            $link = $href_this;
                        }
                    }
                    // Highlight history entry
                    $class = $current_move == $goto ? ' class="selected"' : '';
                    $nr = i_to_round($history, $i);
                    $new_move .= "\t<li>{$nr}: ";
                    if (HISTORY_LINK_BACK) {
                        $new_move .= "<a href=\"{$link}\"{$class}>";
                    } else {
                        $new_move .= '<span>';
                    }
                }
                $piece = $board[$f_row][$f_col];
                $new_move .= piece_glyph($piece);
                $new_move .= strtolower($from_field);
                if ($board[$t_row][$t_col] != '') {
                    $new_move .= ' &#215; ' . piece_glyph($board[$t_row][$t_col]);
                } else {
                    $new_move .= ' &ndash; ';
                }
                $new_move .= strtolower($to_field);
                // Update the board
                $board = apply_move($board, $f_row, $f_col, $t_row, $t_col);
                // Promotion
                if (substr($history, $i + 2, 1) == '(') {
                    $piece = substr($history, $i + 4, 1);
                    $new_move .= piece_glyph($piece);
                    $board[$t_row][$t_col] = substr($history, $i + 4, 1);
                }
                // Do we threaten the other king?
                if (king_in_check($board, !$current_color)) {
                    $new_move .= '+';
                }
                if ($i % 4 == 0) {
                    if (HISTORY_LINK_BACK) {
                        if ($i + 4 < $length) {
                            $link = history_link($href_this, $current_move, BLACKS_MOVE);
                        } else {
                            $link = $href_this;
                        }
                    }
                    $class = $current_move + 1 == $goto ? ' class="selected"' : '';
                    $new_move .= ',';
                    if (HISTORY_LINK_BACK) {
                        $new_move .= "</a> <a href=\"{$link}\"{$class}>";
                    } else {
                        $new_move .= '</span> <span>';
                    }
                } else {
                    if (HISTORY_LINK_BACK) {
                        $new_move .= '</a>';
                    } else {
                        $new_move .= '</span>';
                    }
                    $new_move .= "\n";
                }
                // Reduce opening pawn moves
                $new_move = simplify_history($new_move);
                $ret .= $new_move;
        }
        // switch $from_code
    }
    // for $i
    if (HISTORY_LINK_BACK) {
        $ret .= '</a>';
    } else {
        $ret .= '</span>';
    }
    if (substr($ret, -1, 1) != "\n") {
        $ret .= "\n";
    }
    return $ret . "</ul>\n";
}
Ejemplo n.º 4
0
/**
 * history_markup()
 * See  decode_history  in  game_logic.php , it was the template for this
 * function.
 */
function history_markup($board, $history, $href_this, $name_white, $name_black, $prompt)
{
    $history .= '__';
    $goto = get_parameter(GET_GOTO);
    $class = HISTORY_BREAK_UL ? '' : ' class="scrolling"';
    $ret = "<h2><strong>{$name_white}</strong>" . " vs. <strong>{$name_black}</strong></h2>\n" . "<ul{$class}>\n";
    $current_move = 0;
    //... Newly introduced. Routine might need cleanup.
    $skipped_turns = 0;
    $length = strlen($history);
    for ($i = 0; $i < $length; $i += 2) {
        $from_code = substr($history, $i, 1);
        $to_code = substr($history, $i + 1, 1);
        $from_field = decode_field($from_code);
        $to_field = decode_field($to_code);
        list($f_row, $f_col) = field_to_rowcol($from_field);
        list($t_row, $t_col) = field_to_rowcol($to_field);
        if (HISTORY_BREAK_UL && $i > 0 && ($i - 4 * $skipped_turns) % 80 == 0) {
            $ret .= "</ul><ul>\n";
        }
        switch ($from_code) {
            case '_':
                // Last item, show prompt /////////////////////////
                if ($i % 4 == 0) {
                    $link = $href_this;
                    $ret .= "\t<li>";
                    $nr = i_to_round($history, $i);
                    $ret .= $nr . ': ';
                    $ret .= "<a href=\"{$link}\">";
                }
                $ret .= $prompt;
                break;
            case '(':
                // Pawn Promotion /////////////////////////////////
                $i += 2;
                $skipped_turns++;
                break;
            default:
                // Move ////////////////////////////////////////////
                $new_move = '';
                $current_move++;
                $current_color = $current_move % 2 == WHITES_MOVE;
                $opponent_color = !$current_color;
                if ($i % 4 == 0) {
                    if ($i < $length) {
                        $link = history_link($href_this, $current_move, WHITES_MOVE);
                    } else {
                        $link = $href_this;
                    }
                    // Highlight history entry
                    $class = $current_move == $goto ? ' class="selected"' : '';
                    $nr = i_to_round($history, $i);
                    $new_move .= "\t<li>{$nr}: <a href=\"{$link}\"{$class}>";
                }
                $piece = $board[$f_row][$f_col];
                $new_move .= piece_glyph($piece);
                $new_move .= strtolower($from_field);
                if ($board[$t_row][$t_col] != '') {
                    $new_move .= ' &#215; ' . piece_glyph($board[$t_row][$t_col]);
                } else {
                    $new_move .= ' &ndash; ';
                }
                $new_move .= strtolower($to_field);
                // Update the board
                $board = apply_move($board, $f_row, $f_col, $t_row, $t_col);
                // Promotion
                if (substr($history, $i + 2, 1) == '(') {
                    $piece = substr($history, $i + 4, 1);
                    $new_move .= piece_glyph($piece);
                    $board[$t_row][$t_col] = substr($history, $i + 4, 1);
                }
                // Do we threaten the other king?
                if (king_in_check($board, !$current_color)) {
                    $new_move .= '+';
                }
                if ($i % 4 == 0) {
                    if ($i + 4 < $length) {
                        $link = history_link($href_this, $current_move, BLACKS_MOVE);
                    } else {
                        $link = $href_this;
                    }
                    $class = $current_move + 1 == $goto ? ' class="selected"' : '';
                    $new_move .= ",</a> <a href=\"{$link}\"{$class}>";
                } else {
                    $new_move .= "</a>\n";
                }
                // Reduce opening pawn moves
                $new_move = simplify_history($new_move);
                $ret .= $new_move;
        }
        // switch $from_code
    }
    // for $i
    $ret .= '</a>';
    if (substr($ret, -1, 1) != "\n") {
        $ret .= "\n";
    }
    return $ret . "</ul>\n";
}