Checkers NPC

Status
Not open for further replies.
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:
  • 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

  • checkers1 - Checkers NPC - RaGEZONE Forums
    checkers1.webp
    8.6 KB · Views: 219
  • checkers2 - Checkers NPC - RaGEZONE Forums
    checkers2.webp
    15.3 KB · Views: 280
  • checkers3 - Checkers NPC - RaGEZONE Forums
    checkers3.webp
    17.3 KB · Views: 221
  • checkers4 - Checkers NPC - RaGEZONE Forums
    checkers4.webp
    15.6 KB · Views: 198
  • checker5 - Checkers NPC - RaGEZONE Forums
    checker5.webp
    15.2 KB · Views: 194
Last edited:
I told you I was trolling. And using someone else's npc as a skeleton is pretty bad.

Sorry, I've been thinking about all possible ways where taking the skeleton of someone else's work is bad, I failed so see any legit reasons though. Besides, I've given proper credits for her work. But w/e, I reached a new goal and that's what I wanted.

Damn, son, you must be really bored...
Good job with this mate! :)

It's all for the sake of advancing in JS lol. Thanks =].
 
I don't like leeching, incomplete/half copied scripts make me "grumpy". Even when credits are given, it just ruins your precious "learning" and the quality of your work. So yes, I have no respect for this release at all, imo there is nothing positive about it.

Note: getting ideas from or adopting others styles is fine sometimes for the sake of learning. But this is a blatantly disgusting copy paste. Emily's algorithms, her style, her method names, even her code in some cases.
 
style? those variable names is a common way of using them in java. there's nothing unique about it.

algorithms? just the one for the grabselection.. is one of her algorithms.

method names? so if I had simply renamed those it'd have been Ok? I left it like that out of respect for using her code, I didn't need to hide that fact.

I told you I had used very small pieces of her code, because there was hardly any other way to do it. if you would just look at it you would see how much I have done myself.

Wikipedia says this about leeching: "In computing and specifically Internet,
a leech or leeching is one who
benefits, usually deliberately, from
others' information or effort but does
not offer anything in return, or makes
only token offerings in an attempt to
avoid being called a leech. "

I don't see how that definition applies to me or my release.
 
The argument is GG cause Osiris joined lol.

Anyways, just to bluntly put it: Even looking at someone's code and following it is not copying and pasting. Studying someone's code then replicating itself is a lesson, even if you didn't create the majority of the code.
 
I don't like leeching, incomplete/half copied scripts make me "grumpy". Even when credits are given, it just ruins your precious "learning" and the quality of your work. So yes, I have no respect for this release at all, imo there is nothing positive about it.

Note: getting ideas from or adopting others styles is fine sometimes for the sake of learning. But this is a blatantly disgusting copy paste. Emily's algorithms, her style, her method names, even her code in some cases.
Shut up fagfist, stop qqing because he can actually do it and you can't.

Gj Lapje, not bad at all. You should make it better looking tho. You definitely could have used items instead of letters, it just takes some tweaking lol. And do the CPU move part. Otherwise, it's just an incomplete script nobody will finish.
 
Thanks everyone for the great comments, really appreciate it =].

@Osiris, I'm sorry. I just hoped anyone could finish it. You may lock it and if I somehow complete it, I will send you a message to re-open the thread? I'll try to finish it myself but I have little confidence in actually succeeding.

I'll try finishing it tomoz, just got home from a crazy night out ><.
 
Status
Not open for further replies.
Back