· 6 years ago · Jul 01, 2019, 06:34 PM
1registerPlugin({
2 name: 'Tic Tac Toe',
3 version: '0.1',
4 description: 'Tic Tac Toe Game',
5 author: 'Filtik <filtik@gmx.net>',
6 vars: [{
7 name: "timeout",
8 indent: 0,
9 title: "Time till the game gets closed when there is no user input (in secounds)",
10 type: "number",
11 placeholder: 300
12 }, {
13 name: 'withPoints',
14 indent: 0,
15 title: 'With points? (MySQL required)',
16 type: 'select',
17 options: [
18 'No',
19 'Yes'
20 ]
21 }, {
22 name: "maxbet",
23 indent: 1,
24 title: "Maxiaml bet points (default: 10, 0 = no max)",
25 type: "number",
26 placeholder: 10,
27 conditions: [
28 { field: 'withPoints', value: 1 }
29 ]
30 }, {
31 name: "dbhost",
32 indent: 1,
33 title: "Host adress:",
34 type: "string",
35 placeholder: 'localhost',
36 conditions: [
37 { field: 'withPoints', value: 1 }
38 ]
39 }, {
40 name: "dbport",
41 indent: 1,
42 title: "Port:",
43 type: "string",
44 placeholder: '3306',
45 conditions: [
46 { field: 'withPoints', value: 1 }
47 ]
48 }, {
49 name: "dbusername",
50 indent: 1,
51 title: "Username",
52 type: "string",
53 placeholder: 'username',
54 conditions: [
55 { field: 'withPoints', value: 1 }
56 ]
57 }, {
58 name: "dbpassword",
59 indent: 1,
60 title: "Password",
61 type: "string",
62 placeholder: 'password',
63 conditions: [
64 { field: 'withPoints', value: 1 }
65 ]
66 }, {
67 name: "dbdatabase",
68 indent: 1,
69 title: "Database",
70 type: "string",
71 placeholder: 'sinusbot',
72 conditions: [
73 { field: 'withPoints', value: 1 }
74 ]
75 }]
76}, function(sinusbot, config){
77 var engine = require('engine');
78 var backend = require('backend');
79 var event = require('event');
80 var db = require('db');
81 var helpers = require('helpers');
82 var thisChannel = backend.getCurrentChannel();
83
84 var spacer = "[COLOR=#0000ff] | [/COLOR]";
85 var playerOneColor = "[COLOR=#ff0000]X[/COLOR]";
86 var playerTwoColor = "[COLOR=#00ff00]O[/COLOR]";
87
88 var withPoints = parseInt(config.withPoints);
89
90 if (withPoints) {
91 if (typeof config.dbhost == 'undefined' || config.dbhost == '') {
92 engine.log("No host adress - stoped");
93 return;
94 }
95 if (typeof config.dbport == 'undefined' || config.dbport == '') {
96 engine.log("No port adress - stoped");
97 return;
98 }
99 if (typeof config.dbusername == 'undefined' || config.dbusername == '') {
100 engine.log("No username - stoped");
101 return;
102 }
103 if (typeof config.dbpassword == 'undefined' || config.dbpassword == '') {
104 engine.log("No password - stoped");
105 return;
106 }
107 if (typeof config.dbdatabase == 'undefined' || config.dbdatabase == '') {
108 engine.log("No database - stoped");
109 return;
110 }
111 if (typeof config.withPoints == 'undefined' || config.withPoints == '') {
112 config.withPoints = 0;
113 }
114 if (typeof config.maxbet == 'undefined' || config.maxbet.length == 0) {
115 config.maxbet = 10;
116 }
117 }
118
119 if (typeof config.timeout == 'undefined' || config.timeout == '' || config.timeout == null) {
120 config.timeout = 300;
121 }
122
123 var dbhost = config.dbhost;
124 var dbport = config.dbport;
125 var dbusername = config.dbusername;
126 var dbpassword = config.dbpassword;
127 var dbdatabase = config.dbdatabase;
128
129 var timeout = parseInt(config.timeout);
130 var maxbet = config.maxbet;
131
132 var board = [[9,9,9], [9,9,9], [9,9,9]];
133 var playing = false;
134 var joinable = false;
135 var inactive = 0;
136 var joined = 0;
137 var num = 0;
138 var turn = "";
139 var symbol = -1;
140 var playerOneId = "";
141 var playerOneNick = "";
142 var playerOneBet = false;
143 var playerTwoId = "";
144 var playerTwoNick = "";
145 var playerTwoBet = false;
146 var dbc;
147
148 if (withPoints) {
149 dbc = db.connect({ driver: "mysql", host: dbhost, port: dbport, username: dbusername, password: dbpassword, database: dbdatabase }, function(err) {
150 if (err) {
151 engine.log(err);
152 }
153 });
154
155 if (dbc) dbc.exec("CREATE TABLE IF NOT EXISTS `points` ( " +
156 "`id` int(11) unsigned NOT NULL auto_increment, " +
157 "`name` varchar(255) NOT NULL, " +
158 "`uid` varchar(255) NOT NULL, " +
159 "`points` varchar(255) NOT NULL default '100', " +
160 "`create_date` DATETIME NOT NULL, " +
161 "`last_played_date` DATETIME NULL, " +
162 "PRIMARY KEY (`id`)) " +
163 "CHARSET=UTF8", function(err, res) {
164 if (err) {
165 engine.log(err);
166 dbc = null;
167 return;
168 }
169 });
170
171 if (dbc) dbc.exec("CREATE TABLE IF NOT EXISTS `tictactoe` ( " +
172 "`id` int(11) unsigned NOT NULL auto_increment, " +
173 "`uid` varchar(255) NOT NULL, " +
174 "`bet` varchar(50) NOT NULL default '0', " +
175 "`played` INT(10) NULL default '0', " +
176 "`wins` INT(10) NULL default '0', " +
177 "`lose` INT(10) NULL default '0', " +
178 "`create_date` DATETIME NOT NULL, " +
179 "`last_played_date` DATETIME NULL, " +
180 "PRIMARY KEY (`id`)) " +
181 "CHARSET=UTF8", function(err, res) {
182 if (err) {
183 engine.log(err);
184 dbc = null;
185 return;
186 }
187 });
188 if (dbc) dbc.exec("UPDATE `tictactoe` SET bet = 0, last_played_date = NOW() WHERE bet != 0 ", function(err, res) {
189 if (err) {
190 engine.log(err);
191 dbc = null;
192 return;
193 }
194 });
195 }
196
197 setInterval(function() {
198 if(playing) {
199 if (dbc) {
200 dbc.query("SELECT * FROM `tictactoe` WHERE bet != 0 ", function(err, res) {
201 if (err) {
202 engine.log(err);
203 dbc = null;
204 return;
205 }
206 else {
207 if (res.length > 0) {
208 res.forEach(function(row) {
209 var lastplayed = helpers.toString(row.last_played_date);
210 if(checkovertime(lastplayed, timeout))
211 {
212 dbc.exec("UPDATE `tictactoe` SET bet = 0, played = played + 1, lose = lose + 1, last_played_date = NOW() WHERE uid = ? OR uid = ? ", playerOneId, playerTwoId, function(err, res) {
213 if (err) {
214 engine.log(err);
215 dbc = null;
216 return;
217 }
218 else {
219 resetGame();
220 dbc.exec("UPDATE `points` SET last_played_date = NOW() WHERE uid = ? OR uid = ? ", playerOneId, playerTwoId);
221 thisChannel.chat('[B][COLOR=#FF0000]\nGame was closed because times up, your bet is lost![/COLOR][/B]');
222 }
223 });
224 }
225 });
226 }
227 else {
228 if(inactive > timeout) {
229 resetGame();
230 thisChannel.chat("[B][COLOR=#FF0000]Game was closed because nobody is playing![/COLOR][/B]");
231 }
232 }
233 }
234 });
235 }
236 else {
237 if(inactive > timeout) {
238 resetGame();
239 thisChannel.chat("[B][COLOR=#FF0000]Game was closed because nobody is playing![/COLOR][/B]");
240 }
241 }
242
243 inactive = inactive + 10;
244 }
245 }, 10000);
246
247 function resetGame() {
248 for (var i=0; i<3; i++)
249 {
250 for (var j=0; j<3; j++)
251 {
252 board[i][j] = 9;
253 }
254 }
255
256 playing = false;
257 joinable = false;
258 inactive = 0;
259 joined = 0;
260 num = 0;
261 turn = "";
262 symbol = -1;
263 playerOneId = "";
264 playerOneNick = "";
265 playerOneBet = false;
266 playerTwoId = "";
267 playerTwoNick = "";
268 playerTwoBet = false;
269 };
270
271 function placeMark(y) {
272 if (y<0 || y>8)
273 {
274 thisChannel.chat("[B][COLOR=#1e7f39]Coordinates are out of bounds![/COLOR][/B]");
275 return -1;
276 }
277
278 var i = Math.floor(y/3);
279 y = y-(i*3);
280
281 if(board[i][y] == 9)
282 {
283 board[i][y] = symbol;
284 printBoard();
285
286 return i;
287 }
288
289 thisChannel.chat("[B][COLOR=#1e7f39]There is no more space![/COLOR][/B]");
290 return -1;
291 };
292
293 function hMatch(x) {
294 var count = 0;
295
296 for(var i=0; i<3; i++)
297 {
298 if(board[x][i] == symbol)
299 count++;
300 else
301 count = 0;
302
303 if(count==3)
304 return true;
305 }
306 return false;
307 };
308
309 function vMatch(y) {
310 var count = 0;
311
312 var x = Math.floor(y/3);
313 y = y-(x*3);
314
315 for(var i=0; i<3; i++)
316 {
317 if(board[i][y] == symbol)
318 count++;
319 else
320 count = 0;
321
322 if(count==3)
323 return true;
324 }
325 return false;
326 };
327
328 function dMatch1(x,y){
329 var count = 0;
330
331 for(var i=0; i<3; i++)
332 {
333 if(board[i][i] == symbol)
334 count++;
335 else
336 count = 0;
337
338 if(count==3)
339 return true;
340 }
341
342 return false;
343 };
344
345 function dMatch2(x,y){
346 var count = 0;
347
348 for(var i=0; i<3; i++)
349 {
350 if(board[i][2-i] == symbol)
351 count++;
352 else
353 count = 0;
354
355 if(count==3)
356 return true;
357 }
358
359 return false;
360 };
361
362 function checkWin(x, y) {
363 if(num >=9)
364 {
365 thisChannel.chat("[B][COLOR=#1e7f39]It's a draw![/COLOR][/B]");
366 if (dbc) {
367 dbc.exec("UPDATE `points` SET last_played_date = NOW() WHERE uid = ? OR uid = ? ", playerOneId, playerTwoId, function(err, res) {
368 if (err) {
369 engine.log(err);
370 dbc = null;
371 return;
372 }
373 else {
374 dbc.exec("UPDATE `tictactoe` SET bet = 0, played = played + 1, last_played_date = NOW() WHERE uid = ? OR uid = ? ", playerOneId, playerTwoId, function(err, res) {
375 if (err) {
376 engine.log(err);
377 dbc = null;
378 return;
379 }
380 else {
381 return true;
382 }
383 });
384 }
385 });
386 }
387 else {
388 return true;
389 }
390 }
391
392 if(!(hMatch(x) || vMatch(y) || dMatch1(x,y) || dMatch2(x,y)))
393 return false;
394
395 var GameBet = 0;
396 var winner, loser, nick;
397
398 if (turn == playerOneId) {
399 winner = playerOneId;
400 loser = playerTwoId;
401 nick = playerOneNick;
402 }
403 else {
404 winner = playerTwoId;
405 loser = playerOneId;
406 nick = playerTwoNick;
407 }
408
409 if (dbc) {
410 dbc.query("SELECT * FROM `tictactoe` WHERE uid = ? OR uid = ? ", winner, loser, function(err, res) {
411 if (err) {
412 engine.log(err);
413 dbc = null;
414 return;
415 }
416 else {
417 res.forEach(function(row) {
418 GameBet = GameBet + parseInt(helpers.toString(row.bet));
419 });
420
421 if (dbc) {
422 dbc.exec("UPDATE `tictactoe` SET bet = 0, played = played + 1, lose = lose + 1, last_played_date = NOW() WHERE uid = ? ", loser, function(err, res) {
423 if (err) {
424 engine.log(err);
425 dbc = null;
426 return;
427 }
428 });
429 }
430
431 dbc.exec("UPDATE `points` SET points = points + ? , last_played_date = NOW() WHERE uid = ? ", GameBet, winner, function(err, res) {
432 if (err) {
433 engine.log(err);
434 dbc = null;
435 return;
436 }
437 else {
438 dbc.exec("UPDATE `tictactoe` SET bet = 0, played = played + 1, wins = wins + 1, last_played_date = NOW() WHERE uid = ? ", winner, function(err, res) {
439 if (err) {
440 engine.log(err);
441 dbc = null;
442 return;
443 }
444 else {
445 thisChannel.chat("[B][COLOR=#1e7f39]" + nick + " wins the Game![/COLOR][/B]");
446 thisChannel.chat("[B][COLOR=#1e7f39]Congratulations you've got "+GameBet+" earns points. These have been credited to you.[/COLOR][/B]");
447 return true;
448 }
449 });
450 }
451 });
452 }
453 });
454 return true;
455 }
456 else {
457 thisChannel.chat("[B][COLOR=#1e7f39]" + nick + " wins the Game![/COLOR][/B]");
458 return true;
459 }
460 };
461
462 function playGame(client, y) {
463 if (playing)
464 {
465 if (turn == client.uid())
466 {
467 var x = placeMark(y-1)
468 if(x == -1)
469 return;
470
471 num++
472 if(checkWin(x, y-1)) {
473 resetGame();
474 }
475 else
476 {
477 if (turn == playerOneId)
478 {
479 turn = playerTwoId;
480 symbol = 1;
481 thisChannel.chat("[B][COLOR=#1e7f39]" + playerTwoNick + " is next![/COLOR][/B]");
482 }
483 else
484 {
485 turn = playerOneId;
486 symbol = 0;
487 thisChannel.chat("[B][COLOR=#1e7f39]" + playerOneNick + " is next![/COLOR][/B]");
488 }
489 }
490 if (dbc) {
491 dbc.exec("UPDATE `points` SET last_played_date = NOW() WHERE uid = ? ", turn, function(err, res) {
492 if (err) {
493 engine.log(err);
494 dbc = null;
495 return;
496 }
497 else {
498 dbc.exec("UPDATE `tictactoe` SET last_played_date = NOW() WHERE uid = ? ", turn, function(err, res) {
499 if (err) {
500 engine.log(err);
501 dbc = null;
502 return;
503 }
504 });
505 }
506 });
507 }
508 }
509 else
510 thisChannel.chat("[B][COLOR=#1e7f39]It's not your turn![/COLOR][/B]");
511 }
512 else
513 thisChannel.chat("[B][COLOR=#1e7f39]There is no game running![/COLOR][/B]");
514 };
515
516 function createGame(client) {
517 if (playing)
518 {
519 thisChannel.chat("[B][COLOR=#1e7f39]Game already running![/COLOR][/B]");
520 return;
521 }
522
523 playing = true;
524 joinable = true;
525 thisChannel.chat('[B][COLOR=#1e7f39]Game created! Use "!ttt join" or "!ttt j" to join![/COLOR][/B]');
526 };
527
528 function joinGame(client) {
529 if (playing)
530 {
531 if (joinable)
532 {
533 var uid = client.uid();
534 var name = client.name();
535
536 if (dbc) dbc.exec("INSERT INTO `tictactoe` (uid, create_date) SELECT * FROM (SELECT ? , NOW() ) AS tmp WHERE NOT EXISTS ( SELECT uid FROM tictactoe WHERE uid = ? ) LIMIT 1", uid, uid, function(err, res) {
537 if (err) {
538 engine.log(err);
539 dbc = null;
540 return;
541 }
542 });
543 if (dbc) dbc.exec("INSERT INTO `points` (uid, points, create_date) SELECT * FROM (SELECT ? , 100, NOW() ) AS tmp WHERE NOT EXISTS ( SELECT uid FROM points WHERE uid = ? ) LIMIT 1", uid, uid, function(err, res) {
544 if (err) {
545 engine.log(err);
546 dbc = null;
547 return;
548 }
549 });
550
551 if(joined==0)
552 {
553 playerOneId = client.uid();
554 playerOneNick = client.nick();
555 thisChannel.chat("[B][COLOR=#1e7f39]" + playerOneNick + " joined the game! One more is needed![/COLOR][/B]");
556 if (dbc) {
557 dbc.exec("UPDATE `tictactoe` SET last_played_date = NOW() WHERE uid = ? ", uid);
558 dbc.exec("UPDATE `points` SET name = ? , last_played_date = NOW() WHERE uid = ? ", name, uid);
559 }
560 }
561 else
562 {
563 if (client.uid() != playerOneId)
564 {
565 joinable = false;
566 playerTwoId = client.uid();
567 playerTwoNick = client.nick();
568 thisChannel.chat("[B][COLOR=#1e7f39]" + playerTwoNick + " joined the game![/COLOR][/B]");
569 if (dbc) {
570 dbc.exec("UPDATE `tictactoe` SET last_played_date = NOW() WHERE uid = ? ", uid);
571 dbc.exec("UPDATE `points` SET name = ? , last_played_date = NOW() WHERE uid = ? ", name, uid);
572 }
573
574 if (dbc) {
575 thisChannel.chat('[B][COLOR=#FF6600]\nGame is in stand by!\nPlease bet your points. Use "!ttt bet x"! x = points[/COLOR][/B]');
576 }
577 else {
578 startGame();
579 }
580 }
581 else
582 thisChannel.chat("[B][COLOR=#FF0000]ERROR: The same person can not play with himself![/COLOR][/B]");
583 }
584 joined++;
585 }
586 else
587 thisChannel.chat("[B][COLOR=#1e7f39]It's not possible to join the game at this time![/COLOR][/B]");
588 }
589 else
590 thisChannel.chat("[B][COLOR=#1e7f39]There is no game running![/COLOR][/B]");
591 };
592
593 function betGame(client, newbet) {
594 var uid = client.uid();
595
596 if (dbc) dbc.query("SELECT * FROM `tictactoe` WHERE uid = ? LIMIT 1", uid, function(err, res) {
597 if (err) {
598 engine.log(err);
599 dbc = null;
600 }
601 else {
602 res.forEach(function(row) {
603 var bet = helpers.toString(row.bet);
604 if (playing) {
605 if ((!isNaN(newbet)) && (newbet > 0)) {
606 if (newbet == 0 || newbet == '' || typeof newbet == 'undefined') {
607 thisChannel.chat('[B][COLOR=#FF0000]\nGame stand by!\nPlease bet points. Use "!ttt bet x"! x = points[/COLOR][/B]');
608 }
609 else if ((newbet <= maxbet && maxbet > 0) || (maxbet == 0)) {
610 if (bet == 0) {
611 if (dbc) dbc.query("SELECT * FROM `points` WHERE uid = ? LIMIT 1", uid, function(err, res2) {
612 if (err) {
613 engine.log(err);
614 dbc = null;
615 return;
616 }
617 else {
618 res2.forEach(function(row2) {
619 var points = helpers.toString(row2.points);
620 if (parseInt(points) >= parseInt(newbet)) {
621 dbc.exec("UPDATE `tictactoe` SET bet = ? , last_played_date = NOW() WHERE uid = ? ", newbet, uid);
622 if (err) {
623 engine.log(err);
624 dbc = null;
625 return;
626 }
627 dbc.exec("UPDATE `points` SET points = points - ? , last_played_date = NOW() WHERE uid = ? ", newbet, uid);
628 if (err) {
629 engine.log(err);
630 dbc = null;
631 return;
632 }
633
634 if (uid == playerOneId) {
635 playerOneBet = true;
636 thisChannel.chat("[B][COLOR=#1e7f39]" + playerOneNick + " beted![/COLOR][/B]");
637 }
638 else if (uid == playerTwoId) {
639 playerTowBet = true;
640 thisChannel.chat("[B][COLOR=#1e7f39]" + playerTwoNick + " beted![/COLOR][/B]");
641 }
642
643 if (playerOneBet && playerTowBet) {
644 startGame();
645 }
646 }
647 else {
648 thisChannel.chat('[B][COLOR=#FF0000]\nUnfortunately, you do not have enough points to start this game.\nYour score is '+points+'![/COLOR][/B]');
649 }
650 });
651 }
652 });
653 }
654 else if (bet > 0) {
655 thisChannel.chat('[B][COLOR=#FF0000]You have already beted![/COLOR][/B]');
656 }
657 else {
658 thisChannel.chat('[B][COLOR=#FF0000]\nGame already running!\nWrite "!ttt place x" or "!ttt p x" to make your turn![/COLOR][/B]');
659 }
660 }
661 else if (newbet > maxbet) {
662 thisChannel.chat('[B][COLOR=#FF0000]\nSry, yout bet is to high, max bet is '+maxbet+'![/COLOR][/B]');
663 }
664 }
665 else {
666 thisChannel.chat('[B][COLOR=#FF0000]\nYour bet is not a number, please bet a number![/COLOR][/B]');
667 }
668 }
669 else {
670 thisChannel.chat('[B][COLOR=#FF0000]\nGame not running!\nPlease use "!ttt create"![/COLOR][/B]');
671 }
672 });
673 }
674 });
675 };
676
677 function startGame() {
678 thisChannel.chat("[B][COLOR=#1e7f39]Game is startig now! Randomly choosing who starts![/COLOR][/B]");
679
680 printBoard();
681
682 if (Math.floor(Math.random()*2) == 0)
683 {
684 turn = playerOneId;
685 symbol = 0;
686 thisChannel.chat("[B][COLOR=#1e7f39]" + playerOneNick + " starts![/COLOR][/B]");
687 }
688 else
689 {
690 turn = playerTwoId;
691 symbol = 1;
692 thisChannel.chat("[B][COLOR=#1e7f39]" + playerTwoNick + " starts![/COLOR][/B]");
693 }
694 thisChannel.chat('[B][COLOR=#1e7f39]Write "!ttt place x" or "!ttt p x" to make your turn![/COLOR][/B]');
695 }
696
697 function printBoard() {
698 var msg = spacer;
699 var numplace = 1;
700
701 inactive = 0;
702
703 for(var i=0; i<3; i++)
704 {
705 for(var j=0; j<3; j++)
706 {
707 switch(board[i][j])
708 {
709 case 9:
710 msg = msg + numplace + spacer;
711 break;
712 case 0:
713 msg = msg + playerOneColor + spacer;
714 break;
715 case 1:
716 msg = msg + playerTwoColor + spacer;
717 break;
718 }
719 numplace++;
720 }
721 engine.log(msg);
722 thisChannel.chat(msg);
723 msg = spacer;
724 }
725 };
726
727 function showPoints(client) {
728 var uid = client.uid();
729
730 if (dbc) dbc.query("SELECT * FROM `points` WHERE uid = ? LIMIT 1", uid, function(err, res) {
731 if (err) {
732 engine.log(err);
733 dbc = null;
734 return;
735 }
736 else {
737 if (res.length > 0) {
738 res.forEach(function(row) {
739 var points = helpers.toString(row.points);
740 thisChannel.chat('[B][COLOR=#1e7f39]\nYour point score is '+points+'![/COLOR][/B]');
741 });
742 }
743 else {
744 thisChannel.chat('[B][COLOR=#FF0000]\nYou have no points because you have never played![/COLOR][/B]');
745 }
746 }
747 });
748 };
749
750 event.on('chat', function(ev) {
751 if (!ev.client.isSelf()) {
752 var client = ev.client;
753 var parts = ev.text.split(" ");
754 if (parts.shift() == "!ttt") {
755 switch (parts.shift())
756 {
757 case "create":
758 case "c":
759 createGame(client);
760 break;
761
762 case "join":
763 case "j":
764 joinGame(client);
765 break;
766
767 case "bet":
768 case "b":
769 betGame(client, parts.shift());
770 break;
771
772 case "place":
773 case "p":
774 if (parts.length < 1)
775 thisChannel.chat('[B][COLOR=#FF0000]You entered something wrong! Usage: "!ttt place y" or "!ttt p y"[/COLOR][/B]');
776 else
777 playGame(client, parts.shift());
778 break;
779
780 case "points":
781 showPoints(client);
782 break;
783 }
784 }
785 }
786 });
787
788 function checkovertime(date, difftime) {
789 var now = new Date();
790 date = date.replace(' ', "T") + "Z";
791 var timediff = new Date(date).getTimezoneOffset() / 60;
792 date = new Date(date).getTime() + (difftime*1000);
793 date = date + (timediff*3600000);
794 date = new Date(date);
795
796 if (date < now) {
797 return true;
798 }
799 return false;
800 }
801});