- Joined
- Feb 16, 2009
- Messages
- 658
- Reaction score
- 96
Hi Guys,
I made a Checkers NPC cause Soulfist asked someone to do it in the help section and I wanted to see if I could pull it off.
I should first tell you it's not completely finished, it misses CPU Checker movement, which I failed to add in. But I think it's a waste to not release it and so here it is.
By releasing this I hope somebody could finish it sometime lol.
What is already has:
I might have forgotten to name some stuff but w/e.
It might not be coded in the best possible way but I did it all by myself without any help from anyone.
That having said, I should tell you I did take Emilyx3's Minesweeper NPC as an example (you might notice function names are the same and the top part of the action function, as well as a few very small functions). The rest is done 100% by me (No Soulfist, this is not leeching).
So yeh, only cpu movement for the checkers is left. I really do hope anyone could add that in.
One more thing: Using Items in stead of characters for checkers and field types is not possible. It makes the board too wide causing the 8th option to appear on a new line.
Yap, enjoy. I've commented away the turn checks for player <-> cpu so you'll be able to move anything you'd like.
One last thing (so many things to say @_@), don't ask for my help on this, I cannot finish it myself either.
I made a Checkers NPC cause Soulfist asked someone to do it in the help section and I wanted to see if I could pull it off.
I should first tell you it's not completely finished, it misses CPU Checker movement, which I failed to add in. But I think it's a waste to not release it and so here it is.
By releasing this I hope somebody could finish it sometime lol.
What is already has:
- Draw Board
- Draw Checkers
- Move Counters
- Redrawing of fields after movements
- Time Counter, showed after the game is over
- Very fancy colors for the checkers and board pieces ^^,
- Game Over en Game Win.
I might have forgotten to name some stuff but w/e.
It might not be coded in the best possible way but I did it all by myself without any help from anyone.
That having said, I should tell you I did take Emilyx3's Minesweeper NPC as an example (you might notice function names are the same and the top part of the action function, as well as a few very small functions). The rest is done 100% by me (No Soulfist, this is not leeching).
So yeh, only cpu movement for the checkers is left. I really do hope anyone could add that in.
One more thing: Using Items in stead of characters for checkers and field types is not possible. It makes the board too wide causing the 8th option to appear on a new line.
PHP:
/* Checkers NPC
* Credits:
* Emilyx3, for the general layout
* Lapje, for doig pretty much everything else
* http://forum.ragezone.com/
*/
/***********************************************************************/
/* Don't touch the below variables unless you know what you're doing */
/***********************************************************************/
var status;
var Checker, beatenChecker, movingChecker; // Board has board values checker or board. Checker has checker values black or white. Beatenchecker records the position of the beaten checker, so it can be removed.
var ownCheckerSelected; // selection
var killingMove = false, playerMove = true;
var WHITE_SPACES, BLACK_SPACES; // field types
var VALUE_BOARD = 1, VALUE_CHECKER = 0; // values
var BLACK_FIELD = "#gX#k", WHITE_FIELD = "#dO#k"; // field type pieces
var BLACK_CHECKER = "#bB#k", WHITE_CHECKER = "#rW#k"; // checker pieces
var StartTime = -1, NumCols = -1,
NumRows = -1, NumCheckersWhite = -1, NumCheckersBlack = -1, Moves = 0;
/***********************************************************************/
/* Don't touch the above variables unless you know what you're doing */
/***********************************************************************/
function start(){
status = -1;
action(1,0,0);
}
function Header() {
return "#d============ Checkers ============#k\r\n\r\n";
}
function InitializeBoard() { //done
NumCols = 8;
NumRows = 8;
InitializeCheckers();
}
function InitializeCheckers() { // DONE! [+]
Checker = new Array(NumCols);
for (var i = 0;i < NumCols;i++) {
Checker[i] = new Array(NumRows);
for (var j = 0;j < NumRows;j++) {
if (j % 2 == 0) { // even number
if (i < 4) { // Adding White Checkers
if (i % 2 != 0) { // uneven row
Checker[i][j] = BLACK_FIELD;
continue;
}
Checker[i][j] = WHITE_CHECKER; // add White Checker
continue;
} else if (i > 5) { // Adding Black Checkers
if (i % 2 != 0) { // uneven row
Checker[i][j] = BLACK_FIELD;
continue;
}
Checker[i][j] = BLACK_CHECKER; // add White Checker
continue;
}
if (i % 2 != 0) { // uneven row
Checker[i][j] = BLACK_FIELD;
continue;
}
Checker[i][j] = WHITE_FIELD;
} else {
if (i % 2 != 0) { // uneven row
if (i == 1) { // row 2
Checker[i][j] = WHITE_CHECKER;
continue;
} else if (i == 5 || i == 7) { // row 6 and 8
Checker[i][j] = BLACK_CHECKER;
continue;
} else { // everything else in an uneven row
Checker[i][j] = WHITE_FIELD;
continue;
}
}
Checker[i][j] = BLACK_FIELD; //everything else
}
}
}
numCheckersWhite = 12;
numCheckersBlack = 12;
}
function restoreFieldType(i, j) { // DONE! [+]
if (j % 2 == 0) { // even number
if (i < 4) { // Adding White Checkers
if (i % 2 != 0) // uneven row
return Checker[i][j] = BLACK_FIELD;
} else if (i > 5) { // Adding Black Checkers
if (i % 2 != 0) // uneven row
return Checker[i][j] = BLACK_FIELD;
}
if (i % 2 != 0) // uneven row
return Checker[i][j] = BLACK_FIELD;
return Checker[i][j] = WHITE_FIELD;
} else {
if (i % 2 != 0) { // uneven row
return Checker[i][j] = WHITE_FIELD;
}
return Checker[i][j] = BLACK_FIELD; //everything else
}
}
function InitializeFieldTypes() { // DONE! [+]
var offspring = 0;
for (var i = 0; i < NumRows; i++) {
for (var j = 1; j < NumCols; j += 2) {
if ( i % 2 == j % 2 ) {
if (i % 2 == 0 && offspring % 2 == 0)
Checkers[i][j] = WHITE_FIELD;
else
Checkers[i][j] = BLACK_FIELD;
offspring++;
}
}
}
}
function ConstructBoardString() { // DONE! [+]
var ret = "Moves: " + Moves + ", White Checkers Left: " + numCheckersWhite + "\r\n";
var num = 0;
for (var i = 0;i < NumCols;i++) {
for (var j = 0;j < NumRows;j++) {
ret += "#L"+num+"#"+Checker[i][j]+"#l";
num++;
}
ret += "\r\n";
}
return ret;
}
function ValidPosition(r, c) { // DONE! [+]
return r >= 0 && r < NumRows && c >= 0 && c < NumCols;
}
function GetPositionFromSelection(s) { // DONE! [+]
return [(s / NumCols) | 0, (s % NumCols) | 0];
}
function IsGameOver() { // DONE! [+]
return numCheckersWhite == 0 || numCheckersBlack == 0;
}
function GetGameTime(End) { // DONE! [+]
var Diff = End - StartTime;
var MilliSec = (Diff % 1000) | 0;
Diff /= 1000;
var Min = (Diff / 60) | 0;
var Sec = (Diff % 60) | 0;
return ((Min < 10) ? "0" + Min : Min) + ":" + ((Sec < 10) ? "0" + Sec : Sec)
+ "." + ((MilliSec < 100) ? "0" + ((MilliSec < 10) ? "0" + MilliSec : MilliSec) : MilliSec);
}
function isValidMove(dY, dX) { // DONE! [+]
var y = ownCheckerSelected[0];
var x = ownCheckerSelected[1];
var validMovement = [y -= 1, x -= 1, x += 2];
if (!isKillingMove(dY, dX)) { // not a killing move
if (dY == validMovement[0] && (dX == validMovement[1] || dX == validMovement[2])) { // correct movement
return true;
}
return false;
} else
KillingMove = true;
}
function isKillingMove(dY, dX) { // DONE! [+], not yet tested tho! x3
var y = ownCheckerSelected[0];
var x = ownCheckerSelected[1];
var checker = [y -= 1, x -= 1, x += 2];
var validMovement = [y -= 2, x -= 2, x += 3];
if (y != 1) { // almost at the end, no landing space
if (dY == validMovement[0] && (dX == validMovement[1] || dX == validMovement[2])) {
if (Checker[checker[0]][checker[1]] == WHITE_CHECKER) {
beatenChecker = [checker[0],checker[1]];
return true;
} else if (Checker[checker[0]][checker[2]] == WHITE_CHECKER) {
beatenChecker = [checker[0],checker[2]];
return true;
}
}
}
return false;
}
function makeMove(dY, dX) {
var ret = "";
if (isValidMove(dY, dX)) {
if (killingMove) {
Checker[dY][dX] = BLACK_CHECKER;
restoreFieldType(ownCheckerSelected[0], ownCheckerSelected[1]);
ret += "You have beaten a white piece!" + ConstructBoardString();
restoreFieldType(beatenChecker[0], beatenChecker[1]); // supposed to delete beaten white checker
numCheckersWhite--;
Moves++;
return ret;
} else if (Checker[dY][dX] == BLACK_FIELD || Checker[dY][dX] == WHITE_FIELD) { // empty board type
Checker[dY][dX] = BLACK_CHECKER; // Correct!
restoreFieldType(ownCheckerSelected[0], ownCheckerSelected[1]);
Moves++;
ret += "You have made a move.\r\n" + ConstructBoardString();
return ret;
} else {
ret += "You cannot select your opponents pieces. \r\n" + ConstructBoardString();
return ret;
}
} else {
ret += "You cannot make this move.\r\n" + ConstructBoardString();
return ret;
}
Moves++;
return ret;
}
function action(mode, type, selection) {
if (mode < 1) // exit convo
cm.dispose();
else {
if (status != 2) // checkers game
status++;
}
if (status == 0) {
cm.sendYesNo(Header()+"Are you ready to play some checkers?\r\n");
} else if (status == 1) {
InitializeBoard(); // start the checkers game
cm.sendSimple(Header() + ConstructBoardString()); // display checkers game
} else if (status == 2) { // Checkers game Status
if (StartTime == -1) { // Game time
StartTime = (new Date()).getTime();
}
var SendStr = Header();
var Move = GetPositionFromSelection(selection); // get selection from the player
if (!ValidPosition(Move[0], Move[1])) { // Blabla
cm.sendOk("PE Detected ...");
return;
}
//if (playerMove) { // player move
if (Checker[Move[0]][Move[1]] == BLACK_CHECKER) { //Selecting a checker to move it
SendStr += "Checker Selected ...\r\n\r\n" + ConstructBoardString();
ownCheckerSelected = GetPositionFromSelection(selection); // this selection. Correct.
cm.sendSimple(SendStr);
return;
} else if (ownCheckerSelected !== undefined) {// has selected a piece to move
makeMove(Move[0], Move[1]);
} else {
SendStr += "You have to select a checker first in order to move one ...\r\n\r\n" + ConstructBoardString();
cm.sendSimple(SendStr);
return;
}
playerMove = false;
//} else {
// insert cpu checker movement here and remove the //
//}
SendStr += ConstructBoardString();
if (IsGameOver()) {
if (numCheckersWhite == 0)
cm.sendOk(Header() + "\r\nYou won! Game Time: " + GetGameTime((new Date()).getTime()));
else
cm.sendOk(Header() + "\r\nYou lost! Game Time: " + GetGameTime((new Date()).getTime()));
cm.dispose();
} else {
cm.sendSimple(SendStr);
}
}
}
Yap, enjoy. I've commented away the turn checks for player <-> cpu so you'll be able to move anything you'd like.
One last thing (so many things to say @_@), don't ask for my help on this, I cannot finish it myself either.
Attachments
Last edited:

