diff --git a/exec/ircbots/poker/poker_commands.js b/exec/ircbots/poker/poker_commands.js
new file mode 100644
index 0000000000000000000000000000000000000000..eae7df6a2a1194b6586256cb007ba9ac716db596
--- /dev/null
+++ b/exec/ircbots/poker/poker_commands.js
@@ -0,0 +1,152 @@
+this.Bot_Commands["DEAL"] = new Bot_Command(0,false,false);
+this.Bot_Commands["DEAL"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	cmd.shift();
+	if (!poker_games[target]) {
+		srv.o(target, onick + " just started a new poker hand.  To get "
+			+ "in on the action, type '" + get_cmd_prefix() + "DEAL'");
+		srv.o(target, "Seats will remain open for the next 60 seconds, "
+			+ "or until someone types '" + get_cmd_prefix() + "GO'");
+		poker_games[target] = new Poker_Game();
+		poker_games[target].users[onick.toUpperCase()]=new Poker_Player();
+	} else	if (poker_games[target].users[onick.toUpperCase()]) {
+		srv.o(target, onick + ", you're already in the hand. Relax, don't do it.");
+	} else {
+		poker_games[target].users[onick.toUpperCase()]=new Poker_Player();
+		srv.o(target, onick + " has been dealt in for this hand.");
+	}
+	return;
+}
+
+this.Bot_Commands["GO"] = new Bot_Command(0,false,false);
+this.Bot_Commands["GO"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	cmd.shift();
+	if (!poker_games[target]) {
+		srv.o(target, "No poker game to 'GO' with. Type '" + get_cmd_prefix() + "DEAL' to "
+			+ "start a new one.");
+		return;
+	} else if(poker_games[target].round>0) {
+		srv.o(target, "This hand has already started.");
+		return;
+	}
+	if(true_array_len(poker_games[target].users)==1) {
+		srv.o(target, "At least two players are necessary to start the game.");
+		return;
+	}
+	poker_init_hand(target);
+	poker_deal_hole_cards(target,srv);
+	poker_prompt_player(target,srv);
+	return;
+}
+
+this.Bot_Commands["FOLD"] = new Bot_Command(0,false,false);
+this.Bot_Commands["FOLD"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	if (!poker_games[target]) {
+		srv.o(target, onick + ", there is no game in progress.");
+		return;
+	} else	if (!poker_games[target].users[onick.toUpperCase()]) {
+		srv.o(target, onick + ", you aren't playing this game.");
+		return;
+	} else if(poker_games[target].round<1) {
+		srv.o(target, onick + ", the game hasn't started yet.");
+		return;
+	}
+	
+	delete poker_games[target].users[onick.toUpperCase()];
+	srv.o(target, onick + " folded their hand.");
+	poker_next_turn(target,srv);
+	return;
+}
+
+this.Bot_Commands["CHECK"] = new Bot_Command(0,false,false);
+this.Bot_Commands["CHECK"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	if(!poker_verify_game_status(target,srv,onick)) return;
+	srv.o(target,onick + " checks.");
+	poker_next_turn(target,srv);
+	return;
+}
+
+this.Bot_Commands["BET"] = new Bot_Command(0,false,false);
+this.Bot_Commands["BET"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	if(!poker_verify_game_status(target,srv,onick)) return;
+	if(!cmd[1]) {
+		srv.writeout("NOTICE " + p + " :" + "You must specify an amount to bet!");
+		return;
+	}
+	var poker=poker_games[target];
+	if(cmd[1]>poker.users[onick.toUpperCase()].money) {
+		srv.writeout("NOTICE " + p + " :" + "You don't have that much money!");
+		srv.writeout("NOTICE " + p + " :" + "Balance: $" + poker.users[onick.toUpperCase()].money);
+		return;
+	}
+	if(cmd[1]<poker.current_bet) {
+		srv.writeout("NOTICE " + p + " :" + "You must meet the minimum bet!");
+		srv.writeout("NOTICE " + p + " :" + "Minimum bet: $" + poker.current_bet);
+		return;
+	}
+	srv.o(target,onick + " bets $" + cmd[1]);
+	poker.users[onick.toUpperCase()].money-=Number(cmd[1]);
+	poker.users[onick.toUpperCase()].bet+=Number(cmd[1]);
+	poker.current_bet=Number(cmd[1]);
+	srv.writeout("NOTICE " + onick + " :" + "Balance: $" + poker.users[onick.toUpperCase()].money);
+	poker_next_turn(target,srv);
+	return;
+}
+
+this.Bot_Commands["CALL"] = new Bot_Command(0,false,false);
+this.Bot_Commands["CALL"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	if(!poker_verify_game_status(target,srv,onick)) return;
+	var poker=poker_games[target];
+	if(poker.current_bet>poker.users[onick.toUpperCase()].money) {
+		srv.writeout("NOTICE " + onick + " :" + "You don't have enough to call!");
+		srv.writeout("NOTICE " + onick + " :" + "Balance: $" + poker.users[onick.toUpperCase()].money);
+		return;
+	}
+	srv.o(target,onick + " calls the bet: $" + poker.current_bet);
+	poker.users[onick.toUpperCase()].money-=poker.current_bet;
+	poker.users[onick.toUpperCase()].bet+=poker.current_bet;
+	srv.writeout("NOTICE " + onick + " :" + "Balance: $" + poker.users[onick.toUpperCase()].money);
+	poker_next_turn(target,srv);
+	return;
+}
+
+this.Bot_Commands["RAISE"] = new Bot_Command(0,false,false);
+this.Bot_Commands["RAISE"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	if(!poker_verify_game_status(target,srv,onick)) return;
+	if(!cmd[1]) {
+		srv.writeout("NOTICE " + onick + " :" + "You must specify an amount to raise!");
+		return;
+	}
+	var poker=poker_games[target];
+	var bet=Number(cmd[1]);
+	if(poker.current_bet+bet>poker.users[onick.toUpperCase()].money) {
+		srv.writeout("NOTICE " + onick + " :" + "You don't have that much money!");
+		srv.writeout("NOTICE " + onick + " :" + "Balance: $" + poker.users[onick.toUpperCase()].money);
+		return;
+	}
+	srv.o(target,onick + " raises the bet to $" + poker.current_bet+bet);
+	poker.users[onick.toUpperCase()].money-=bet;
+	poker.users[onick.toUpperCase()].bet+=bet;
+	poker.current_bet+=bet;
+	srv.writeout("NOTICE " + onick + " :" + "Balance: $" + poker.users[onick.toUpperCase()].money);
+	poker_next_turn(target,srv);
+	return;
+}
+
+this.Bot_Commands["STATUS"] = new Bot_Command(0,false,false);
+this.Bot_Commands["STATUS"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	return;
+}
+
+this.Bot_Commands["LIST"] = new Bot_Command(0,false,false);
+this.Bot_Commands["LIST"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	if(!poker_games[target]) {
+		srv.o(target,"There is no active game.");
+		return;
+	}
+	var list="";
+	for(u in poker_games[target].users) {
+		list+=" "+u;
+	}
+	srv.o(target,"Poker players:" + list);
+	return;
+}
\ No newline at end of file
diff --git a/exec/ircbots/poker/poker_functions.js b/exec/ircbots/poker/poker_functions.js
new file mode 100644
index 0000000000000000000000000000000000000000..49a38a41d57f0e380dd50f7e8360e9749486eb9e
--- /dev/null
+++ b/exec/ircbots/poker/poker_functions.js
@@ -0,0 +1,169 @@
+/* 	IRC Bot Module - Server Commands
+	You would place all of your module functions in this file.	*/
+	
+this.Server_command=function(srv,cmdline,onick,ouh) 
+{
+	var cmd=IRC_parsecommand(cmdline);
+	switch (cmd[0]) {
+		case "JOIN":
+			if (onick == srv.curnick) break;
+			
+			// Someone else joining? Let's send them a private welcome message!
+			srv.o(onick,"Welcome to Poker!");
+			srv.o(onick,"This is a module for IRCBot - by Cyan");
+			break;
+		case "PRIVMSG":
+			if ((cmd[1][0] == "#") || (cmd[1][0] == "&")) {
+				var chan = srv.channel[cmd[1].toUpperCase()];
+				if (!chan)
+					break;
+				if (!chan.is_joined)
+					break;
+				if(srv.users[onick.toUpperCase()]) {
+					/* 	You can do special command processing here, if you like.
+						This is currently set up to parse public room messages for
+						things like trivia answers, or other responses that
+						are inconvenient for users to submit with a command prefix */
+				}
+			}
+			break;
+		default:
+			break;
+	}
+}
+
+//////////////////// Non-object Functions ////////////////////
+function poker_deal_hole_cards(target,srv) {
+	var poker_game=poker_games[target];
+	poker_game.round = 1;
+	for (p in poker_game.users) {
+		poker_game.users[p].cards[0] = poker_game.deck.deal();
+		poker_game.users[p].cards[1] = poker_game.deck.deal();
+		srv.writeout("NOTICE " + p + " :" + "Your hole cards: " + 
+		poker_game.users[p].cards[0].color + "[ " + poker_game.users[p].cards[0].char + " ] " +
+		poker_game.users[p].cards[1].color + "[ " + poker_game.users[p].cards[1].char + " ]");
+	}
+}
+
+function poker_next_turn(target,srv) {
+	var poker=poker_games[target];
+	poker.turn++;
+	if(poker.turn==poker.users_map.length) poker.turn=0;
+	
+	if(poker.deal_next) {
+		poker_load_pot(target,srv);
+		switch(++poker.round) {
+			case 1:
+				poker_deal_flop(target,srv);
+				break;
+			case 2:
+				poker_deal_turn(target,srv);
+				break;
+			case 3:
+				poker_deal_river(target,srv);
+				break;
+		}
+		poker.deal_next=false;
+	} else {
+		var turn_user=poker.users[poker.users_map[poker.turn]];
+		if(poker.current_bet==turn_user.bet) poker.deal_next=true;
+	}
+	poker_prompt_player(target,srv);
+}
+
+function poker_deal_flop(target,srv) { 
+	var poker_game=poker_games[target];
+	poker_game.round = 2;
+	poker_game.community_cards[0] = poker_game.deck.deal();
+	poker_game.community_cards[1] = poker_game.deck.deal();
+	poker_game.community_cards[2] = poker_game.deck.deal();
+	srv.writeout("PRIVMSG " + target + " :The Flop: " +
+	poker_show_card(poker_game.community_cards[0]) +
+	poker_show_card(poker_game.community_cards[1]) +
+	poker_show_card(poker_game.community_cards[2]));
+}
+
+function poker_deal_turn(target,srv) {
+	var poker_game=poker_games[target];
+	poker_game.round = 3;
+	poker_game.community_cards[3] = poker_game.deck.deal();
+	srv.writeout("PRIVMSG " + target + " :The Turn: " + 
+	poker_show_card(poker_game.community_cards[0]) +
+	poker_show_card(poker_game.community_cards[1]) +
+	poker_show_card(poker_game.community_cards[2]) +
+	poker_show_card(poker_game.community_cards[3]));
+}
+
+function poker_deal_river(target,srv) {
+	var poker_game=poker_games[target];
+	poker_game.round = 4;
+	poker_game.community_cards[4] = poker_game.deck.deal();
+	srv.writeout("PRIVMSG " + target + " :The River: " + 
+	poker_show_card(poker_game.community_cards[0]) +
+	poker_show_card(poker_game.community_cards[1]) +
+	poker_show_card(poker_game.community_cards[2]) +
+	poker_show_card(poker_game.community_cards[3]) +
+	poker_show_card(poker_game.community_cards[4]));
+}
+
+function poker_show_card(card) {
+	return(card.color + "[ " + card.char + " ]");
+}
+
+function poker_load_pot(target,srv) {
+	var poker=poker_games[target];
+	for(var p in poker.users) {
+		poker.pot+=poker.users[p].bet;
+		poker.users[p].bet=0;
+	}
+	srv.o(target,"Current pot: $" + poker.pot);
+	return;
+}
+
+function poker_prompt_player(target,srv) {
+	var poker=poker_games[target];
+	var turn=poker.users_map[poker.turn];
+	srv.writeout("NOTICE " + turn + " :" + "It is your turn. You may CHECK,  CALL, BET, RAISE or FOLD");
+	srv.writeout("NOTICE " + turn + " :" + "Minimum bet: $" + poker.current_bet);
+}
+
+function poker_verify_game_status(target,srv,onick) {
+	var poker=poker_games[target];
+	if (!poker) {
+		srv.o(target, "No poker game in progress. Type '" + get_cmd_prefix() + "DEAL' to "
+			+ "start a new one.");
+		return false;
+	}
+	if(!poker.users[onick.toUpperCase()]) {
+		srv.o(onick, "You're not even in the hand!");
+		return false;
+	}
+	var turn_player=poker.users_map[poker.turn];
+	if (turn_player != onick.toUpperCase()) {
+		srv.o(target, "Acting out of turn?");
+		return false;
+	}
+	return true;
+}
+
+function poker_init_hand(target) {
+	poker_games[target].deck.shuffle();
+	for(var u in poker_games[target].users) {
+		poker_games[target].users_map.push(u);
+	}
+}
+
+function load_scores()
+{
+	var s_file=new File(poker_dir + "scores.ini");
+	if(s_file.open(file_exists(s_file.name)?"r+":"w+")) {
+		writeln("reading scores from file: " + s_file.name);
+		var players=s_file.iniGetKeys();
+		for(var p in players) {
+			writeln("loading player score: " + players[p]);
+			poker_scores[players[p]]=s_file.iniGetValue(null,players[p]);
+		}
+		s_file.close();
+	}
+}
+
diff --git a/exec/ircbots/poker/pokerbot.js b/exec/ircbots/poker/pokerbot.js
new file mode 100644
index 0000000000000000000000000000000000000000..1a3cb9d2e34d47485bed9f206123ee447444040d
--- /dev/null
+++ b/exec/ircbots/poker/pokerbot.js
@@ -0,0 +1,72 @@
+var poker_dir=this.dir;
+var poker_scores=[];
+var notice_interval=10; //seconds
+var activity_timeout=120;
+var poker_games=[];
+
+this.save=function()
+{
+	var s_file=new File(poker_dir + "scores.ini");
+	if(!s_file.open(file_exists(s_file.name)?"r+":"w+")) return false;
+	writeln("writing scores to file: " + s_file.name);
+	for(s in poker_scores) {
+		s_file.iniSetValue(null,s,poker_scores[s]);
+	}
+	s_file.close();
+}
+this.main=function(srv,target)
+{	
+	var poker=poker_games[target];
+	if(!poker || poker.paused) return;
+	var active_users=false;
+	for(var u in srv.users) {
+		if(poker.users[u]) {
+			if(time()-srv.users[u].last_spoke<activity_timeout){
+				active_users=true;
+				break;
+			} else {
+				delete poker.users[u];
+				srv.o(u,"You have been idle too long. Type 'DEAL' here to resume playing poker.");
+			}
+		}
+	}
+	if(!active_users) return;
+	
+	if(poker.cycle()) {
+	}
+}
+
+function Poker_Game()
+{
+	this.last_update=0;
+	this.turn=0;
+	this.pot=0;
+	this.lg_blind=10;
+	this.sm_blind=5;
+	this.min_bet=this.sm_blind;
+	this.current_bet=this.min_bet;
+	this.round=0;
+	this.deck=new Deck();
+	this.community_cards=new Array();
+	this.paused=false;
+	this.users=[];
+	this.users_map=[];
+
+	this.cycle=function()
+	{
+		if(time()-this.last_update>=notice_interval) {
+			this.last_update=time();
+			return true;
+		}
+		return false
+	}
+	this.deck.shuffle();
+}
+function Poker_Player()
+{
+	this.cards=[];
+	this.money=100;
+	this.bet=0;
+}
+
+load_scores();