function savePromotion() { global $mysql; global $movesArray, $FENarray, $curTurn; $num_moves = count($FENarray) - 1; // subtract one for initpos // when we run the promotion script, the color to be promoted // is the oppposite of the color who's turn it is $piece = $_POST['promotion']; if ('white' == $curTurn) { $piece = strtolower($piece); } // save the promoted piece in the movesArray $movesArray[$num_moves]['promo'] = $piece; // seperate the FEN board from the rest of the FEN $FEN = $FENarray[$num_moves]; $FENbits = trim(substr($FEN, strpos($FEN, ' '))); $xFEN = expandFEN(substr($FEN, 0, strpos($FEN, ' '))); // insert the promoted piece sqr2idx($movesArray[$num_moves]['toSq'], $idx); FENplace($xFEN, $idx, $movesArray[$num_moves]['promo']); // and repack the FEN $FENhead = packFEN($xFEN); $FEN = $FENhead . ' ' . $FENbits; // and save the new and improved FEN to the history $query = "\n\t\tSELECT MAX(h_time)\n\t\tFROM " . T_HISTORY . "\n\t\tWHERE h_game_id = '{$_SESSION['game_id']}'\n\t"; $result = $mysql->fetch_value($query, __LINE__, __FILE__); $query = "\n\t\tUPDATE " . T_HISTORY . "\n\t\tSET h_fen = '{$FEN}'\n\t\tWHERE h_game_id = '{$_SESSION['game_id']}'\n\t\t\tAND h_time = '{$result}'\n\t"; $mysql->query($query, __LINE__, __FILE__); updateTimestamp(); }
/** static public function fire_laser * FIRE ZEE MISSILES !!! * But I am le tired * * Fires the laser of the given color * * @param string color (red or silver) * @param string board (expanded FEN) * @param array [optional] extra info * @return array (laser path array, and squares hit (empty array if none) array) */ public static function fire_laser($color, $board, $extra_info = false) { call(__METHOD__); // search for the sphynx in the board $has_sphynx = Setup::has_sphynx($board); $color = strtolower($color); $board = expandFEN($board); $extra_info = self::extra_info($extra_info); call($color); call($board); call($extra_info); if (!in_array($color, array('silver', 'red'))) { throw new MyException(__METHOD__ . ': Trying to fire laser for unknown color: ' . $color); } $reflections = array('A' => array(I_LEFT => I_UP, I_DOWN => I_RIGHT), 'B' => array(I_LEFT => I_DOWN, I_UP => I_RIGHT), 'C' => array(I_RIGHT => I_DOWN, I_UP => I_LEFT), 'D' => array(I_RIGHT => I_UP, I_DOWN => I_LEFT), 'X' => array(I_RIGHT => I_DOWN, I_LEFT => I_UP, I_DOWN => I_RIGHT, I_UP => I_LEFT), 'Y' => array(I_RIGHT => I_UP, I_LEFT => I_DOWN, I_DOWN => I_LEFT, I_UP => I_RIGHT), 'H' => array(I_RIGHT => array(I_RIGHT, I_DOWN), I_LEFT => array(I_LEFT, I_UP), I_DOWN => array(I_RIGHT, I_DOWN), I_UP => array(I_LEFT, I_UP)), 'I' => array(I_RIGHT => array(I_RIGHT, I_UP), I_LEFT => array(I_LEFT, I_DOWN), I_DOWN => array(I_LEFT, I_DOWN), I_UP => array(I_RIGHT, I_UP))); // fire the laser if (!$has_sphynx) { if ('silver' == $color) { $laser_path = array(array(array(79, I_UP))); } else { // red $laser_path = array(array(array(0, I_DOWN))); } } else { list($shoot_sphynx_idx, $shoot_sphynx_dir) = self::find_sphynx($board, 'silver' === $color); list($hit_sphynx_idx, $hit_sphynx_dir) = self::find_sphynx($board, 'silver' !== $color); $laser_path = array(array(array($shoot_sphynx_idx + $shoot_sphynx_dir, $shoot_sphynx_dir))); } // because we can now possibly move the laser around and rotate it // make sure we don't hit a wall right out of the gate // check if we hit a wall list($current, $dir) = $laser_path[0][0]; $long_wall = 0 > $current || 80 <= $current; $short_wall = 1 == abs($dir) && floor($current / 10) !== floor(($current - $dir) / 10); if ($long_wall || $short_wall) { // we hit the wall... just stop $laser_path[0][0][0] = false; return array('laser_path' => $laser_path, 'hits' => array(), 'laser_hit' => false); } // also check and make sure that the sphynx was not hit right out of the gate $hit_silver = $hit_red = false; $var_name = 'hit_' . ('silver' == $color ? 'silver' : 'red'); if ($has_sphynx && $hit_sphynx_idx == $current) { if (!$extra_info['battle_front_only']) { ${$var_name} = true; } elseif ($hit_sphynx_dir == -$dir) { ${$var_name} = true; } } if ($hit_red || $hit_silver) { // we hit the sphynx... just stop $laser_path[] = array(array(true, $dir)); return array('laser_path' => $laser_path, 'hits' => array(), 'laser_hit' => true); } $i = 0; // infinite loop protection $paths = $laser_path[0]; $used = array(); $next = array(); $hits = array(); $laser_hit = false; while ($i < 999) { // no ad infinitum here $split = 0; $continue = false; foreach ($paths as $key => $node) { if (false === $node[0] || true === $node[0]) { unset($node[2]); $next[$key] = $node; // propagate the individual path indexes continue; } // let the loop know we still have valid nodes $continue = true; // current is the current board index // dir is the direction that the laser was heading // when it entered the current index list($current, $dir) = $node; // check the current location for a piece if ('0' !== ($piece = $board[$current])) { // check for hit or reflection if (!isset($reflections[strtoupper($piece)][$dir])) { // dont track the hit for the following situations: // is an anubis and hit the front $front_anubis = preg_match('/[LMNO]/i', $piece) && $dir == -self::get_anubis_dir($piece); // hit the sphynx (laser hits get tracked elsewhere) $hit_sphynx = $has_sphynx && ($current == $hit_sphynx_idx || $current == $shoot_sphynx_idx); // if any of those hit, don't track the hit if (!($front_anubis || $hit_sphynx)) { $hits[] = $current; } // but still change the path data to recognize the path stopped // we store dir here because it keeps the output format consistent // we don't really care at this point because we just hit a piece // ... the laser isn't going any further $next[$key] = array(true, $dir); // stop this path continue; } $dir = $reflections[strtoupper($piece)][$dir]; } // this is where we split off in two directions through the beam splitter $do_split = false; if (is_array($dir)) { // add a new entry in the paths for the reflection // and change dir to be the pass-through beam // if we've already split a beam once, // we'll need to add a few more to the index // (it is possible to hit a single splitter from two sides, // as well as hit both splitters from two sides, so...) // also note: if there are no beam splitters, there is no way // of doubling back or going over the same path again, ever // before we add to $next, make sure we haven't been here, or hit any walls $do_split = true; $split_dir = $dir[0]; $split_current = $current + $split_dir; // make sure we haven't been here before if (in_array(array($split_current, $split_dir), $used, true)) { // don't even create a new path $do_split = false; } else { // check if we hit the laser $hit_silver = $hit_red = false; if (!$has_sphynx) { $hit_red = -10 == $split_current && 'silver' == $color; $hit_silver = 89 == $split_current && 'red' == $color; } else { // find the laser $var_name = 'hit_' . ('silver' == $color ? 'silver' : 'red'); if ($hit_sphynx_idx == $split_current) { if (!$extra_info['battle_front_only']) { ${$var_name} = true; } elseif ($hit_sphynx_dir == -$split_dir) { ${$var_name} = true; } } } if ($hit_red || $hit_silver) { $laser_hit = true; } // check if we hit a wall $long_wall = 0 > $split_current || 80 <= $split_current; $short_wall = 1 == abs($split_dir) && floor($split_current / 10) !== floor(($split_current - $split_dir) / 10); if ($long_wall || $short_wall) { // set split_current to false, so we know we hit a wall, // but keep going, we need to store the dir so we can show any reflection properly // and we need to add the new path index below // we store dir here because we need to know in which direction the laser left the node // for edge/corner piece hits that send the laser through the wall $split_current = false; } $next[count($paths) + $split] = array($split_current, $split_dir); if (false !== $split_current) { $used[] = array($split_current, $split_dir); } $split += 1; } // now that the split is done, go back and keep processing the new path $dir = $dir[1]; } // increment $current and run a few tests // so we don't shoot through walls // or loop back on ourselves forever $current += $dir; // make sure we haven't been here before if (in_array(array($current, $dir), $used, true)) { // we store dir here because it keeps the output format consistent // we don't really care at this point because we've been here before // and know what's going to happen $next[$key] = array(false, $dir); // stop this path continue; } // check if we hit the laser $hit_silver = $hit_red = false; if (!$has_sphynx) { $hit_red = -10 == $current && 'silver' == $color; $hit_silver = 89 == $current && 'red' == $color; } else { $var_name = 'hit_' . ('silver' == $color ? 'silver' : 'red'); if ($hit_sphynx_idx == $current) { if (!$extra_info['battle_front_only']) { ${$var_name} = true; } elseif ($hit_sphynx_dir == -$dir) { ${$var_name} = true; } } } if ($hit_red || $hit_silver) { $laser_hit = true; } // check if we hit a wall $long_wall = 0 > $current || 80 <= $current; $short_wall = 1 == abs($dir) && floor($current / 10) !== floor(($current - $dir) / 10); if ($long_wall || $short_wall) { // set current to false, so we know we hit a wall, // but keep going, we need to store the dir so we can show any reflection properly // and we need to add the new path index below // we store dir here because we need to know which direction the laser left the node in // for corner piece hits that send the laser through the wall $current = false; } $next[$key] = array($current, $dir); if ($do_split) { // add the new path index here so we know which path was the original path // and where are the splits came from $next[$key][2] = count($paths) + $split - 1; } if (false !== $current) { $used[] = array($current, $dir); } } // end foreach $current // if we have no valid nodes left // break the loop if (!$continue) { break; } // add to our laser path // and pass along to the next round $laser_path[] = $paths = $next; ++$i; // keep those pesky infinite loops at bay } // end while call(self::get_laser_ascii($board, $laser_path)); call($hits); // straighten up the laser path array_walk($laser_path, create_function('& $val', 'ksort($val);')); return compact('laser_path', 'hits', 'laser_hit'); }
<?php require_once 'includes/inc.global.php'; $setups = Game::get_setup_stats_list(); $setup_selection = '<option value="0">Random</option>'; $setup_javascript = ''; foreach ($setups as $setup) { $setup_selection .= ' <option value="' . $setup['setup_id'] . '">' . $setup['name'] . '</option>'; $setup_javascript .= "'" . $setup['setup_id'] . "' : '" . expandFEN($setup['board']) . "',\n"; } $setup_javascript = substr(trim($setup_javascript), 0, -1); // remove trailing comma $meta['title'] = 'Statistics'; $meta['head_data'] = ' <link rel="stylesheet" type="text/css" media="screen" href="css/board.css" /> <script type="text/javascript">//<![CDATA[ var setups = { ' . $setup_javascript . ' }; /*]]>*/</script> <script type="text/javascript" src="scripts/board.js">></script> <script type="text/javascript" src="scripts/stats.js">></script> '; $hints = array('View ' . GAME_NAME . ' Player and Setup statistics.', 'Click on Setup table row to view setup.'); $contents = ''; // grab the wins and losses for the players $list = Game::get_player_stats_list(); $table_meta = array('sortable' => true, 'no_data' => '<p>There are no player stats to show</p>', 'caption' => 'Player Stats', 'init_sort_column' => array(1 => 1));
/** static public function get_invites * Returns a list array of all the invites in the database * for the given player * * @param int player's id * @return 2D array invite list */ public static function get_invites($player_id) { call(__METHOD__); $Mysql = Mysql::get_instance(); $player_id = (int) $player_id; $query = "\n\t\t\tSELECT G.*\n\t\t\t\t, DATE_ADD(NOW( ), INTERVAL -1 DAY) AS resend_limit\n\t\t\t\t, R.username AS invitor\n\t\t\t\t, E.username AS invitee\n\t\t\t\t, S.name AS setup\n\t\t\tFROM " . self::GAME_TABLE . " AS G\n\t\t\t\tLEFT JOIN " . Setup::SETUP_TABLE . " AS S\n\t\t\t\t\tON S.setup_id = G.setup_id\n\t\t\t\tLEFT JOIN " . Player::PLAYER_TABLE . " AS R\n\t\t\t\t\tON R.player_id = G.white_id\n\t\t\t\tLEFT JOIN " . Player::PLAYER_TABLE . " AS E\n\t\t\t\t\tON E.player_id = G.black_id\n\t\t\tWHERE G.state = 'Waiting'\n\t\t\t\tAND (G.white_id = {$player_id}\n\t\t\t\t\tOR G.black_id = {$player_id}\n\t\t\t\t\tOR G.black_id IS NULL\n\t\t\t\t\tOR G.black_id = FALSE\n\t\t\t\t)\n\t\t\tORDER BY G.create_date DESC\n\t\t"; $list = $Mysql->fetch_array($query); call($list); $in_vites = $out_vites = $open_vites = array(); foreach ($list as $item) { $extra_info = array_merge_plus(self::$_EXTRA_INFO_DEFAULTS, unserialize($item['extra_info'])); $white_color = 'random' == $extra_info['white_color'] ? 'Random' : ('white' == $extra_info['white_color'] ? 'Silver' : 'Red'); $black_color = 'random' == $extra_info['white_color'] ? 'Random' : ('white' == $extra_info['white_color'] ? 'Red' : 'Silver'); $hover = array(); if (!empty($item['extra_info'])) { $hover = unserialize($item['extra_info']); unset($hover['invite_setup']); unset($hover['white_color']); } $hover_text = array(); foreach ($hover as $key => $value) { if (is_bool($value)) { $value = $value ? 'Yes' : 'No'; } $hover_text[] = humanize($key) . ': ' . $value; } $item['hover_text'] = implode(' | ', $hover_text); $item['board'] = 'setup_display'; if (!empty($extra_info['invite_setup'])) { $item['board'] = expandFEN($extra_info['invite_setup']); } if ($player_id == $item['white_id']) { $item['color'] = $white_color; $out_vites[] = $item; } elseif ($player_id == $item['black_id']) { $item['color'] = $black_color; $in_vites[] = $item; } else { $item['color'] = $black_color; $open_vites[] = $item; } } return array($in_vites, $out_vites, $open_vites); }
function movetoFEN() { global $FENarray, $movesArray, $board, $COLS, $initpos, $pieceColor; $num_moves = count($FENarray) - 1; // get the post info out foreach ($_POST as $key => $var) { ${$key} = $var; } // reverse row and col so i don't confuse myself $colFrom = $fromCol; $colTo = $toCol; $rowFrom = $fromRow; $rowTo = $toRow; // and convert it to something we can use colrow2idx($colFrom, $rowFrom, $idxFrom); colrow2idx($colTo, $rowTo, $idxTo); // get the current FEN data $FENitems = explode(' ', $FENarray[$num_moves]); $thatFEN = expandFEN($FENitems[0]); $CM = $FENitems[1]; $CI = $FENitems[2]; $EP = $FENitems[3]; $PN = $FENitems[4]; $MN = $FENitems[5]; $newEP = '-'; // get original placement of rooks $origARookPos = strpos($initpos, 'R'); $origHRookPos = strrpos($initpos, 'R'); $origKingPos = strpos($initpos, 'K'); // separate the castle indicator $WK = false !== strpos($CI, 'K') ? 'K' : ''; $WQ = false !== strpos($CI, 'Q') ? 'Q' : ''; $BK = false !== strpos($CI, 'k') ? 'k' : ''; $BQ = false !== strpos($CI, 'q') ? 'q' : ''; // put board into expanded FEN string $xFEN = ""; for ($i = 7; $i >= 0; $i--) { for ($j = 0; $j < 8; $j++) { $xFEN .= $board[$i][$j]; } } // get the piece that is moving $piece = FENplace($xFEN, $idxFrom); // check for castling move if ('false' != $_POST['castleMove']) { if ('white' == $pieceColor[$piece]) { // clear the castle indicators $WK = ''; $WQ = ''; // make the move if ('a' == $_POST['castleMove']) { FENplace($xFEN, $origKingPos + 56, '0'); // delete the king FENplace($xFEN, $origARookPos + 56, '0'); // delete the rook FENplace($xFEN, 2 + 56, 'K'); // place the king FENplace($xFEN, 3 + 56, 'R'); // place the rook } elseif ('h' == $_POST['castleMove']) { FENplace($xFEN, $origKingPos + 56, '0'); // delete the king FENplace($xFEN, $origHRookPos + 56, '0'); // delete the rook FENplace($xFEN, 6 + 56, 'K'); // place the king FENplace($xFEN, 5 + 56, 'R'); // place the rook } else { die("castleMove is incorrect"); } } elseif ('black' == $pieceColor[$piece]) { // clear the castle indicators $BK = ''; $BQ = ''; // make the move if ('a' == $_POST['castleMove']) { FENplace($xFEN, $origKingPos, '0'); // delete the king FENplace($xFEN, $origARookPos, '0'); // delete the rook FENplace($xFEN, 2, 'k'); // place the king FENplace($xFEN, 3, 'r'); // place the rook } elseif ('h' == $_POST['castleMove']) { FENplace($xFEN, $origKingPos, '0'); // delete the king FENplace($xFEN, $origHRookPos, '0'); // delete the rook FENplace($xFEN, 6, 'k'); // place the king FENplace($xFEN, 5, 'r'); // place the rook } else { die("castleMove is incorrect"); } } else { echo "<pre>"; for ($i = 0; $i < $idxFrom; $i++) { echo " "; } echo "|\n"; echo $xFEN . "</pre>"; } } else { // make the move $piece = FENplace($xFEN, $idxFrom, '0'); $capt = FENplace($xFEN, $idxTo, $piece); $PN++; // if we have a pawn advance, or a capture if ('P' == strtoupper($piece) || '0' != $capt) { $PN = 0; } // reset the ply count // if we have a pawn double advance if ('P' == strtoupper($piece) && 2 == abs($rowFrom - $rowTo)) { colrow2til($colTo, ($rowFrom + $rowTo) * 0.5, $newEP); } // set the en passant indicator // if we moved a castling piece if ('K' == $piece) { $WK = ''; $WQ = ''; } elseif ('k' == $piece) { $BK = ''; $BQ = ''; } elseif ('R' == $piece) { if ($colFrom == $origARookPos) { // a-side moved $WQ = ''; } elseif ($colFrom == $origHRookPos) { // h-side moved $WK = ''; } } elseif ('r' == $piece) { if ($colFrom == $origARookPos) { // a-side moved $BQ = ''; } elseif ($colFrom == $origHRookPos) { // h-side moved $BK = ''; } } } // check for en passant capture colrow2til($colTo, $rowTo, $tilTo); if ($tilTo == $EP && 'P' == strtoupper($piece)) { // get the idx of the captured pawn colrow2idx($colTo, $rowFrom, $idxCapt); // and remove the captured pawn FENplace($xFEN, $idxCapt, '0'); } $FENbit = packFEN($xFEN); // search for ambiguous castle notation //-------------------------------------------- // remove any extra information from the current castle notations if ('' != $WK) { $WK = 'K'; } if ('' != $WQ) { $WQ = 'Q'; } if ('' != $BK) { $BK = 'k'; } if ('' != $BQ) { $BQ = 'q'; } // get current position of main pieces $whiteBackRank = substr($xFEN, -8); $blackBackRank = substr($xFEN, 0, 8); // search the ends of the back ranks for rooks // and add unambiguous notation if needed if (strrpos($whiteBackRank, 'R') > $origHRookPos && '' != $WK) { $WK = $WK . substr($COLS, $origHRookPos, 1); } if (strpos($whiteBackRank, 'R') < $origARookPos && '' != $WQ) { $WQ = $WQ . substr($COLS, $origARookPos, 1); } if (strrpos($blackBackRank, 'r') > $origHRookPos && '' != $BK) { $BK = $BK . substr($COLS, $origHRookPos, 1); } if (strpos($blackBackRank, 'r') < $origARookPos && '' != $BQ) { $BQ = $BQ . substr($COLS, $origARookPos, 1); } $castlingAvail = $WK . $WQ . $BK . $BQ; if ('' == $castlingAvail) { $castlingAvail = '-'; } // increase the move number (if needed) $MN = "w" == $CM ? $MN : ++$MN; // make sure to use the pre-increment (++var) here // toggle the current move $CM = "w" == $CM ? "b" : "w"; // put the whole thing together and return return "{$FENbit} {$CM} {$castlingAvail} {$newEP} {$PN} {$MN}"; }
?> <input type="button" name="nudge" id="nudge" value="Nudge" /> <?php } ?> <?php } ?> </div></form> </div> <!-- #board_wrapper --> <?php echo $chat_html; ?> </div> <!-- #contents --> <script type="text/javascript"> document.write('<'+'div id="setup"'+'>'+create_board('<?php echo expandFEN($Game->get_setup()); ?> ', true)+'<'+'/'+'div'+'>'); </script> <?php call($GLOBALS); echo get_footer($meta);
/** static public function _get_reflection * Gets the reflection type for the given setup * * @param string board * @return string reflection type */ public static function _get_reflection($setup) { call(__METHOD__); call($setup); // expand the board FEN $xFEN = expandFEN($setup); foreach (array('Origin', 'Long', 'Short', 'None') as $type) { try { self::is_valid_reflection($xFEN, $type); } catch (MyException $e) { continue; } break; } return $type; }