2-Player Pokémon Chess [Work in progress]
Because it's more fun this way. Coming up some day: AI, isometric grid, and shadows!
http://minite.ch/chess/?i=1http://minite.ch/chess/?i=2http://minite.ch/chess/?i=3http://minite.ch/chess/?i=4http://minite.ch/chess/?i=5http://minite.ch/chess/?i=6http://minite.ch/chess/?i=7http://minite.ch/chess/?i=8
http://minite.ch/chess/?i=9http://minite.ch/chess/?i=10http://minite.ch/chess/?i=11http://minite.ch/chess/?i=12http://minite.ch/chess/?i=13http://minite.ch/chess/?i=14http://minite.ch/chess/?i=15http://minite.ch/chess/?i=16
http://minite.ch/chess/?i=17http://minite.ch/chess/?i=18http://minite.ch/chess/?i=19http://minite.ch/chess/?i=20http://minite.ch/chess/?i=21http://minite.ch/chess/?i=22http://minite.ch/chess/?i=23http://minite.ch/chess/?i=24
http://minite.ch/chess/?i=25http://minite.ch/chess/?i=26http://minite.ch/chess/?i=27http://minite.ch/chess/?i=28http://minite.ch/chess/?i=29http://minite.ch/chess/?i=30http://minite.ch/chess/?i=31http://minite.ch/chess/?i=32
http://minite.ch/chess/?i=33http://minite.ch/chess/?i=34http://minite.ch/chess/?i=35http://minite.ch/chess/?i=36http://minite.ch/chess/?i=37http://minite.ch/chess/?i=38http://minite.ch/chess/?i=39http://minite.ch/chess/?i=40
http://minite.ch/chess/?i=41http://minite.ch/chess/?i=42http://minite.ch/chess/?i=43http://minite.ch/chess/?i=44http://minite.ch/chess/?i=45http://minite.ch/chess/?i=46http://minite.ch/chess/?i=47http://minite.ch/chess/?i=48
http://minite.ch/chess/?i=49http://minite.ch/chess/?i=50http://minite.ch/chess/?i=51http://minite.ch/chess/?i=52http://minite.ch/chess/?i=53http://minite.ch/chess/?i=54http://minite.ch/chess/?i=55http://minite.ch/chess/?i=56
http://minite.ch/chess/?i=57http://minite.ch/chess/?i=58http://minite.ch/chess/?i=59http://minite.ch/chess/?i=60http://minite.ch/chess/?i=61http://minite.ch/chess/?i=62http://minite.ch/chess/?i=63http://minite.ch/chess/?i=64
No en passant or castling, sorry. Checkmate/check/stalemate detection to be implemented. Sprites from here: http://floatzel.net/pokemon/black-white/sprites/
Here's the source:
<?php
session_start();
function kick() {
header("Status: Forbidden\r\n", true, 403);
header("Content-Type: text/plain\r\n");
die('Go away.');
}
function isEnemy($item) {
return $item !== -1 && $item & 8;
}
function iValidMoves($board, $type, $x, $y) {
$results = array();
switch($type) {
case 0:
# Pawn
if($board[$y - 1][$x] === -1) {
$results[] = array($x, $y - 1);
if($y == 6 && $board[$y - 2][$x] === -1) $results[] = array($x, $y - 2);
}
if($x > 0 && isEnemy($board[$y - 1][$x - 1])) $results[] = array($x - 1, $y - 1);
if($x < 7 && isEnemy($board[$y - 1][$x + 1])) $results[] = array($x + 1, $y - 1);
break;
case 1:
# King
if($x > 0 && $board[$y][$x - 1] & 8) $results[] = array($x - 1, $y);
if($x > 0 && $y > 0 && $board[$y - 1][$x - 1] & 8) $results[] = array($x - 1, $y - 1);
if($x > 0 && $y < 7 && $board[$y + 1][$x - 1] & 8) $results[] = array($x - 1, $y + 1);
if($x < 7 && $board[$y][$x + 1] & 8) $results[] = array($x + 1, $y);
if($x < 7 && $y > 0 && $board[$y - 1][$x + 1] & 8) $results[] = array($x + 1, $y - 1);
if($x < 7 && $y < 7 && $board[$y + 1][$x + 1] & 8) $results[] = array($x + 1, $y + 1);
if($y > 0 && $board[$y - 1][$x] & 8) $results[] = array($x, $y - 1);
if($y < 7 && $board[$y + 1][$x] & 8) $results[] = array($x, $y + 1);
break;
case 2:
# Queen
# Downwards diagonal
for($d = 1; $x + $d < 8 && $y + $d < 8; $d++) {
if($board[$y + $d][$x + $d] & 8) {
$results[] = array($x + $d, $y + $d);
if($board[$y + $d][$x + $d] !== -1) break;
} else {
break;
}
}
for($d = -1; $x + $d >= 0 && $y + $d >= 0; $d--) {
if($board[$y + $d][$x + $d] & 8) {
$results[] = array($x + $d, $y + $d);
if($board[$y + $d][$x + $d] !== -1) break;
} else {
break;
}
}
# Upwards diagonal
for($d = 1; $x + $d < 8 && $y - $d >= 0; $d++) {
if($board[$y - $d][$x + $d] & 8) {
$results[] = array($x + $d, $y - $d);
if($board[$y - $d][$x + $d] !== -1) break;
} else {
break;
}
}
for($d = -1; $x + $d >= 0 && $y - $d < 8; $d--) {
if($board[$y - $d][$x + $d] & 8) {
$results[] = array($x + $d, $y - $d);
if($board[$y - $d][$x + $d] !== -1) break;
} else {
break;
}
}
# Horizontal
for($d = 1; $x + $d < 8; $d++) {
if($board[$y][$x + $d] & 8) {
$results[] = array($x + $d, $y);
if($board[$y][$x + $d] !== -1) break;
} else {
break;
}
}
for($d = -1; $x + $d >= 0; $d--) {
if($board[$y][$x + $d] & 8) {
$results[] = array($x + $d, $y);
if($board[$y][$x + $d] !== -1) break;
} else {
break;
}
}
# Vertical
for($d = 1; $y + $d < 8; $d++) {
if($board[$y + $d][$x] & 8) {
$results[] = array($x, $y + $d);
if($board[$y + $d][$x] !== -1) break;
} else {
break;
}
}
for($d = -1; $y + $d >= 0; $d--) {
if($board[$y + $d][$x] & 8) {
$results[] = array($x, $y + $d);
if($board[$y + $d][$x] !== -1) break;
} else {
break;
}
}
break;
case 3:
# Bishop
# Downwards diagonal
for($d = 1; $x + $d < 8 && $y + $d < 8; $d++) {
if($board[$y + $d][$x + $d] & 8) {
$results[] = array($x + $d, $y + $d);
if($board[$y + $d][$x + $d] !== -1) break;
} else {
break;
}
}
for($d = -1; $x + $d >= 0 && $y + $d >= 0; $d--) {
if($board[$y + $d][$x + $d] & 8) {
$results[] = array($x + $d, $y + $d);
if($board[$y + $d][$x + $d] !== -1) break;
} else {
break;
}
}
# Upwards diagonal
for($d = 1; $x + $d < 8 && $y - $d >= 0; $d++) {
if($board[$y - $d][$x + $d] & 8) {
$results[] = array($x + $d, $y - $d);
if($board[$y - $d][$x + $d] !== -1) break;
} else {
break;
}
}
for($d = -1; $x + $d >= 0 && $y - $d < 8; $d--) {
if($board[$y - $d][$x + $d] & 8) {
$results[] = array($x + $d, $y - $d);
if($board[$y - $d][$x + $d] !== -1) break;
} else {
break;
}
}
break;
case 4:
# Knight
if($x > 1 && $y > 0 && $board[$y - 1][$x - 2] & 8) $results[] = array($x - 2, $y - 1);
if($x > 0 && $y > 1 && $board[$y - 2][$x - 1] & 8) $results[] = array($x - 1, $y - 2);
if($x < 7 && $y > 1 && $board[$y - 2][$x + 1] & 8) $results[] = array($x + 1, $y - 2);
if($x < 6 && $y > 0 && $board[$y - 1][$x + 2] & 8) $results[] = array($x + 2, $y - 1);
if($x < 6 && $y < 7 && $board[$y + 1][$x + 2] & 8) $results[] = array($x + 2, $y + 1);
if($x < 7 && $y < 6 && $board[$y + 2][$x + 1] & 8) $results[] = array($x + 1, $y + 2);
if($x > 0 && $y < 6 && $board[$y + 2][$x - 1] & 8) $results[] = array($x - 1, $y + 2);
if($x > 1 && $y < 7 && $board[$y + 1][$x - 2] & 8) $results[] = array($x - 2, $y + 1);
break;
case 5:
# Rook
# Horizontal
for($d = 1; $x + $d < 8; $d++) {
if($board[$y][$x + $d] & 8) {
$results[] = array($x + $d, $y);
if($board[$y][$x + $d] !== -1) break;
} else {
break;
}
}
for($d = -1; $x + $d >= 0; $d--) {
if($board[$y][$x + $d] & 8) {
$results[] = array($x + $d, $y);
if($board[$y][$x + $d] !== -1) break;
} else {
break;
}
}
# Vertical
for($d = 1; $y + $d < 8; $d++) {
if($board[$y + $d][$x] & 8) {
$results[] = array($x, $y + $d);
if($board[$y + $d][$x] !== -1) break;
} else {
break;
}
}
for($d = -1; $y + $d >= 0; $d--) {
if($board[$y + $d][$x] & 8) {
$results[] = array($x, $y + $d);
if($board[$y + $d][$x] !== -1) break;
} else {
break;
}
}
break;
}
return $results;
}
function invertRelationship($piece) {
return $piece === -1 ? -1 : $piece ^ 8;
}
function invertPosition($position) {
return array($position[0], 7 - $position[1]);
}
function invertBoard($board) {
$invertedBoard = array();
for($i = 7; $i > -1; $i--) {
$invertedBoard[] = array_map('invertRelationship', $board[$i]);
}
return $invertedBoard;
}
function validMoves($x, $y) {
global $board;
$type = $board[$y][$x];
if($type & 8) {
return array_map('invertPosition', iValidMoves(invertBoard($board), $type & ~8, $x, 7 - $y));
} else {
return iValidMoves($board, $type, $x, $y);
}
}
function shouldHighlight($x, $y) {
global $highlight;
foreach($highlight as $position) {
if($position[0] == $x && $position[1] == $y) {
return true;
}
}
return false;
}
if(isset($_SESSION['board'])) {
$board = $_SESSION['board'];
} else {
$board = array(
array(5 | 8, 4 | 8, 3 | 8, 1 | 8, 2 | 8, 3 | 8, 4 | 8, 5 | 8),
array(0 | 8, 0 | 8, 0 | 8, 0 | 8, 0 | 8, 0 | 8, 0 | 8, 0 | 8),
array(-1, -1, -1, -1, -1, -1, -1, -1),
array(-1, -1, -1, -1, -1, -1, -1, -1),
array(-1, -1, -1, -1, -1, -1, -1, -1),
array(-1, -1, -1, -1, -1, -1, -1, -1),
array(0, 0, 0, 0, 0, 0, 0, 0),
array(5, 4, 3, 1, 2, 3, 4, 5)
);
}
$back = array(
imagecreatefrompng('back/16.png'), # pawn
imagecreatefrompng('back/6.png'), # king
imagecreatefrompng('back/149.png'), # queen
imagecreatefrompng('back/37.png'), # bishop
imagecreatefrompng('back/25.png'), # knight
imagecreatefrompng('back/75.png') # rook
);
$front = array(
imagecreatefrompng('front/16.png'), # pawn
imagecreatefrompng('front/6.png'), # king
imagecreatefrompng('front/149.png'), # queen
imagecreatefrompng('front/37.png'), # bishop
imagecreatefrompng('front/25.png'), # knight
imagecreatefrompng('front/75.png') # rook
);
$image = $_GET['i'];
if(ctype_digit($image)) {
$image = (int)$image;
} else {
kick();
}
if($image < 1 || $image > 64) {
kick();
}
$highlight = array();
$referrer = $_SERVER['HTTP_REFERER'];
$action = null;
if(strpos($referrer, '?a=') > -1) {
$action = substr($referrer, strpos($referrer, '?a=') + 3);
}
if($action !== null && $image === 1) { # Only do this once!
if(!ctype_digit($action)) kick();
$action = (int)$action;
if($action < 1 || $action > 64) kick();
$aX = ($action - 1) % 8;
$aY = floor(($action - 1) / 8);
if(isset($_SESSION['selected'])) {
if($_SESSION['selected'] !== $action) {
# Make sure the piece can actually move there.
# If it can, move.
# "Highlight" the places that the piece can move:
$highlight = validMoves(($_SESSION['selected'] - 1) % 8, floor(($_SESSION['selected'] - 1) / 8));
if(shouldHighlight($aX, $aY)) {
# The move is good!
$sX = ($_SESSION['selected'] - 1) % 8;
$sY = floor(($_SESSION['selected'] - 1) / 8);
$board[$aY][$aX] = $board[$sY][$sX];
$board[$sY][$sX] = -1;
# Now, rotate the board for the next person to play:
$invertedBoard = invertBoard($board);
$rotatedBoard = array();
foreach($invertedBoard as $row) {
for($i = 0; $i < 4; $i++) {
$row[$i] ^= $row[7 - $i];
$row[7 - $i] ^= $row[$i];
$row[$i] ^= $row[7 - $i];
}
$rotatedBoard[] = $row;
}
$board = $rotatedBoard;
}
}
unset($_SESSION['selected']);
} elseif(($board[$aY][$aX] & 8) === 0) {
# Select a piece:
$_SESSION['selected'] = $action;
}
}
if(isset($_SESSION['selected'])) {
# Highlight the places that the piece can move:
$highlight = validMoves(($_SESSION['selected'] - 1) % 8, floor(($_SESSION['selected'] - 1) / 8));
}
# Draw the background:
$background = imagecreatetruecolor(96, 96);
$black = imagecolorallocate($background, 0, 0, 0);
$white = imagecolorallocate($background, 255, 255, 255);
$red = imagecolorallocatealpha($background, 255, 0, 0, 100);
if(($image + floor(($image - 1) / 8)) % 2) {
imagefilledrectangle($background, 0, 0, 96, 96, $black);
} else {
imagefilledrectangle($background, 0, 0, 96, 96, $white);
}
# Draw a piece, if there is one:
$piece = $board[floor(($image - 1) / 8)][($image - 1) % 8];
if($piece > -1) {
if($piece & 8) {
$piece &= ~8;
$draw = $front[$piece];
} else {
$draw = $back[$piece];
}
imagecopy($background, $draw, 0, 0, 0, 0, 96, 96);
}
# Should we highlight this place?
if(shouldHighlight(($image - 1) % 8, floor(($image - 1) / 8))) {
imagefilledrectangle($background, 0, 0, 96, 96, $red);
}
header("Content-Type: image/png\r\n");
imagepng($background);
$_SESSION['board'] = $board;
?>
1+1 Simple, but brilliant idea! BTW - for the deadline I think you mean June 2, 2012. – Cristian Lupascu – 2012-05-23T15:22:09.163
Derp, yes I did, thanks :) – mellamokb – 2012-05-23T15:23:09.710
Short deadline + already answered your own question = downvote. – boothby – 2012-05-23T18:50:07.717
1@boothby: I was actually thinking about deleting my answer. The intention was to provide a concrete example, not to win the contest (or votes, I don't greatly care about rep). Can you provide some constructive suggestions to the competition? What would you like the deadline to be? How should the spec be changed to motivate you to participate? – mellamokb – 2012-05-23T19:02:46.480
4I just noticed that minitech's AI can't play a perfect game of tic-tac-toe. Play center, bottom-left, top-center, center-right, center-left. – PhiNotPi – 2012-05-23T23:04:25.810
@mellamokb, the later you make the deadline (within reason), the more answers and more variety you'll get. I'd say set it for Canada Day. – boothby – 2012-05-24T01:35:08.837
@boothby, There was just a recent SE blogpost reminding people that they are encouraged to answer their own questions. – breadbox – 2012-05-24T06:57:56.880
@breadbox: That was probably more relevant for SO than here. I agree with
boothby
that my posting an answer could be seen as an unfair way to win/get votes, so I removed it and placed my example inside the question instead. – mellamokb – 2012-05-24T13:23:50.507@boothby: No I agree, I'll extend it out some more. I didn't want to make the contest too long, but I think end of June is fine. I'll update. – mellamokb – 2012-05-24T13:25:35.743
Maybe I'm being stupid, but none of these work for me (Chrome 19.0.1084.46 beta-m) – Griffin – 2012-06-02T22:09:14.813
I'm on Chrome 19.0.1084.52 and have no issue. What are you seeing? – mellamokb – 2012-06-03T01:47:39.327
Neither example works in Firefox 12 on Windows 7. What are the browser requirements? – Mr.Wizard – 2012-06-04T08:54:54.413
1@Mr.Wizard: working fine on FF 12.0 & Windows 7 here, could you post more details about what's not working? – ChristopheD – 2012-06-04T13:36:03.303
@Mr.Wizard: If you look at some of the examples below, they should all work because they have a single image. As I mention in my post, since I have 4 images, there are flukey things that happen, where it doesn't appear to work but it actually has. My updates are applied specifically when the image with text (first image) is loaded. If that image is loaded last due to how the browser loads the images, it will appear that nothing has happened, but the state of the game actually has changed if you reload the page (i.e., click the question title to reload) or click another peg. – mellamokb – 2012-06-04T13:40:07.983
You might have to allow 3rd party cookies to get Hangman and Maze working (my game should work fine without it; I recommend blocking them again afterwards for privacy reasons). ChristopheD's and my game also need a browser that allows svg in img tags
– copy – 2012-06-04T16:16:07.897@copy: I switched to PNG output for compatibility purposes, and the 3rd party cookie (which was really only a problem with IE with most browser's default settings) should be solved now as well afaik. – ChristopheD – 2012-06-04T17:34:13.097
@ChristopheD I think P3P policies only work for IE and Safari. I can't play Maze or Hangman without changing my settings at least (Chromium 17) – copy – 2012-06-04T19:42:45.153
Yeah, this was randomly thrown together. Chess coming up next, guys! Also, nice job on the towers of Hanoi. It looks better. – Ry- – 2012-06-10T14:15:22.457
@minitech: I especially liked your secret message in TTT if you try to hack :P – mellamokb – 2012-06-11T13:57:05.863