isundil 6 vuotta sitten
vanhempi
commit
28d4969a2c
2 muutettua tiedostoa jossa 129 lisäystä ja 27 poistoa
  1. 4 3
      config.js
  2. 125 24
      loupgarou.js

+ 4 - 3
config.js

@@ -55,9 +55,10 @@ module.exports.MODULES["#rapido"].push(new (require('./rapido.js'))({
 module.exports.MODULES["#rapido"].push(new (require('./loupgarou.js'))({
     DISABLED: false,
     registrationDelay: 2*60, // 2 min
-    cupidonDelay: 90, // 1 min 30
-    seerDelay: 90, // 1 min 30
-    reminderInterval: 30, // 30 sec
+    cupidonDelay: 90,        // 1 min 30
+    seerDelay: 90,           // 1 min 30
+    wolfDelay: 180,          // 2 min
+    reminderInterval: 30,    // 30 sec
     privateChannel: "#test-lg"
 }));
 

+ 125 - 24
loupgarou.js

@@ -6,10 +6,10 @@ function LoupGarou(config) {
 const ROLES = {
     WOLF: "WOLF",
     VILLAGER: "VILLAGER",
-    CUPIDON: "CUPIDON",
+    CUPIDON: "CUPIDON",     // OK
     HUNTER: "HUNTER",
     WITCH: "WITCH",
-    SEER: "SEER",
+    SEER: "SEER",           // OK
     GIRL: "GIRL"
 };
 
@@ -61,12 +61,15 @@ const langMng = [
         remainingPseudos: function(nicks) { return "Vous avez le choix entre : " +nicks.join(", "); },
         seerMessage: function(players) { return "Tu vas pouvoir decouvrir le role d'un joueur. Tapes juste le pseudo du joueur qui t'interesse. Tu as le choix entre: " +players.join(", "); },
         seerTimeout: function() { return "Il est tard et tu vas te coucher. Tu pourras reessayer demain."; },
+        wolfTimeout: function() { return "Les Loups-Garous ne se sont pas nourris ce soir et sont tous morts de faim !"; },
         loverWins: function() { return "Les amoureux gagnent la partie !"; },
         wolfWins: function() { return "Les loup-garous gagnent la partie !"; },
         villagerWins: function() { return "Les villageois gagnent la partie !"; },
         congrats: function(nickList) { return nickList.length == 1 ? ("Félicitations au gagnant " +nickList[0]) : ("Félicitations aux gagnants " +nickList.join(", ")); },
         waitingCupidon: function(timeSec) { return `En attente de cupidon (${timeSec} secondes)`; },
         waitingSeer: function(timeSec) { return `En attente de la voyante (${timeSec} secondes)`; },
+        waitingWolf: function(timeSec) { return `En attente des loup-garous (${timeSec} secondes)`; },
+        currentVotes: function() { return "Etat des votes:"; },
         whoiswhat: {
             "WOLF": function(who) { return `${who} est un Loup-Garou.`; },
             "VILLAGER": function(who) { return `${who} est un simple villageois.`; },
@@ -102,7 +105,8 @@ const KILL_REASON = {
     WOLF: 1,
     LEFT: 2,
     LOVE: 3,
-    VILLAGER: 4
+    VILLAGER: 4,
+    HUNGER: 5
 }
 
 function Player(lg, name) {
@@ -122,7 +126,71 @@ Player.prototype.kill = function(reason, msg) {
     this.dead = reason;
     this.killReason = msg;
     this.loupgarou.onKilled(this);
-}
+};
+
+VoteEngine = function() {
+    this.players = null;
+    this.canBeVoted = null;
+};
+
+VoteEngine.prototype.init = function(canVote, canBeVoted) {
+    this.players = {};
+    this.canBeVoted = {};
+    canVote.forEach(i => this.players[i.toLowerCase()] = false);
+    canBeVoted.forEach(i => this.canBeVoted[i.toLowerCase()] = true);
+};
+
+VoteEngine.prototype.vote = function(player, text) {
+    text = text.trim().toLowerCase();
+    if (!player ||
+        this.players[player] === undefined ||
+        this.canBeVoted[text] === undefined)
+        return;
+    this.players[player] = text;
+    if (this.canBeVoted === true)
+        this.canBeVoted = Date.now();
+};
+
+VoteEngine.prototype.hasVotes = function() {
+    for (var i in this.players)
+        if (this.players[i])
+            return true;
+    return false;
+};
+
+VoteEngine.prototype.getVotes = function() {
+    var votedByName = {},
+        voted = [];
+
+    for (var i in this.players) {
+        if (this.players[i] !== false) {
+            var arr = votedByName[this.players[i]];
+            if (!arr)
+                voted.push(arr = votedByName[this.players[i]] = {name: this.players[i], from: []});
+            arr.from.push(i);
+        }
+    }
+    return voted.sort((i, j) => j.from.length -i.from.length);
+};
+
+VoteEngine.prototype.getVote = function() {
+    var voted = {};
+    for (var i in this.players)
+        if (this.players[i] !== undefined)
+            voted[this.players[i]] = (voted[this.players[i]] || 0) +1
+    var result = null,
+        max = 0,
+        time = null;
+
+    for (var i in voted) {
+        if (voted[i] > max || (voted[i] === max && (time === null || time > this.canBeVoted[i]))) {
+            result = i;
+            max = voted[i];
+            time = this.canBeVoted[i];
+        }
+    }
+    return result;
+};
 
 LoupGarou.prototype.init = function(bot, chanName) {
     this.room = chanName;
@@ -135,6 +203,7 @@ LoupGarou.prototype.init = function(bot, chanName) {
     this.currentScenario = langMng[0];
     this.nightChannelPersons = {};
     this.justDead = [];
+    this.voteEngine = new VoteEngine();
 
     for (var i in STEP) this.stepListeners[STEP[i]] = [];
     this.stepListeners[STEP.NOT_STARTED].push(function() { this.bot.setModes(this.room, "-m"); this.bot.endGame(this); });
@@ -150,10 +219,10 @@ LoupGarou.prototype.init = function(bot, chanName) {
     this.stepListeners[STEP.DAY_HUNTER].push(LoupGarou.prototype.onHunter);
     this.stepListeners[STEP.DAY].push(LoupGarou.prototype.onDay);
     this.stepListeners[STEP.DAY].push(LoupGarou.prototype.cleanCorpses);
-    this.stepListeners[STEP.DAY].push(LoupGarou.prototype.checkEndOfGame);
+    this.stepListeners[STEP.DAY].push(LoupGarou.prototype.checkEndOfGameAndContinue);
     this.stepListeners[STEP.DAY_VILLA].push(LoupGarou.prototype.onVillagers);
     this.stepListeners[STEP.DAY_EVENING].push(LoupGarou.prototype.onEvening);
-    this.stepListeners[STEP.DAY_EVENING].push(LoupGarou.prototype.checkEndOfGame);
+    this.stepListeners[STEP.DAY_EVENING].push(LoupGarou.prototype.checkEndOfGameAndContinue);
 
     var self = this;
     this.bot.bot.addListener("pm", (from, text) => {
@@ -211,8 +280,11 @@ LoupGarou.prototype.onSelfJoin = function() {
     var _this = this;
     this.nightChannelPersons = this.nightChannelPersons || {};
     this.bot.bot.addListener("join" +_this.config.privateChannel, nick => {
-        if (this.bot.name.toLowerCase() !== nick.toLowerCase())
+        if (_this.bot.name.toLowerCase() !== nick.toLowerCase()) {
             _this.nightChannelPersons[nick.toLowerCase()] = true;
+            if (_this.currentStep === STEP.NIGHT_LG)
+                _this.bot.voice(_this.config.privateChannel, nick);
+        }
     });
     this.bot.bot.addListener("names" +_this.config.privateChannel, nicks => {
         for (var nick in nicks)
@@ -225,9 +297,12 @@ LoupGarou.prototype.onSelfJoin = function() {
     this.bot.bot.addListener("kick" +_this.config.privateChannel, nick => {
         delete _this.nightChannelPersons[nick.toLowerCase()];
     });
-    this.bot.bot.join(this.config.privateChannel, () => {
-        this.bot.setModes(_this.config.privateChannel, "+iKmnpt");
+    this.bot.bot.addListener("message" +_this.config.privateChannel, (user, text) => {
+        var player = this.players[user];
+        if (this.currentStep === STEP.NIGHT_LG && player && player.dead === null)
+            this.voteEngine.vote(player.name.toLowerCase(), text);
     });
+    this.bot.bot.join(this.config.privateChannel);
     this.bot.setModes(this.room, "-m");
 };
 
@@ -249,7 +324,7 @@ LoupGarou.prototype.setStep = function(newStep) {
     }
     LoupGarou.prototype.nextStep.messageDelayed = [];
     LoupGarou.prototype.setStep.recursive = true;
-    this.timeInStep = Date.now();
+    this.timeInStep = Date.now() / 1000;
     this.clearReminder();
     this.currentStep = newStep;
     this.stepListeners[newStep] && this.stepListeners[newStep].some(i => i.call(this), this);
@@ -472,21 +547,43 @@ LoupGarou.prototype.onGirl = function() {
     }
 };
 
-LoupGarou.prototype.onWolfInternal = function(player) {
-    //FIXME ...
-    this.bot.sendMsg(this.room, "Attente loups"); // FIXME this.currentScenario
-    setTimeout((function() { this.nextStep(); }).bind(this), 15000);
+LoupGarou.prototype.sendCurrentVotes = function(channel) {
+    if (this.voteEngine.hasVotes()) {
+        this.bot.sendMsg(channel, this.currentScenario.currentVotes());
+        this.voteEngine.getVotes().forEach(i => {
+            this.bot.sendMsg(channel, i.name +' : ' +i.from.join(", "));
+        }, this);
+    }
 };
 
 LoupGarou.prototype.onWolf = function() {
-    var notWolf = [];
-    for (var i in this.players) if (this.players[i].role !== ROLES.WOLF) notWolf.push(this.players[i]);
-    notWolf = notWolf.sort(() => Math.random() -.5)[0];
-    notWolf.kill(KILL_REASON.WOLF, this.currentScenario.killedWolf(notWolf.name));
-
     var players = this.withRole(ROLES.WOLF);
     if (players.length) {
-        this.onWolfInternal(players[0]);
+        this.bot.voice(this.config.privateChannel, Object.keys(this.nightChannelPersons));
+        this.voteEngine.init(players.map(i => i.name), this.aliveNicks());
+        this.setReminder(function() {
+            this.bot.sendMsg(this.room, this.currentScenario.waitingWolf(Math.round((this.config.wolfDelay -(Date.now() / 1000) +this.timeInStep))));
+            this.bot.sendMsg(this.config.privateChannel, this.currentScenario.remainingPseudos(this.aliveNicks()));
+            this.sendCurrentVotes(this.config.privateChannel);
+        });
+        setTimeout((function() {
+            this.bot.devoice(this.config.privateChannel, Object.keys(this.nightChannelPersons));
+            if (!this.voteEngine.hasVotes()) {
+                var msg = this.currentScenario.wolfTimeout();
+                this.bot.sendMsg(this.room, msg);
+                players.forEach(i => {
+                    this.bot.sendMsg(this.room, this.currentScenario.whowaswhat[i.role](i.name))
+                    i.kill(KILL_REASON.HUNGER, msg);
+                });
+                this.checkEndOfGameAndContinue(); // Will end game
+                return;
+            } else {
+                var p = this.players[this.voteEngine.getVote()];
+                p.kill(KILL_REASON.WOLF, this.currentScenario.killedWolf(p.name));
+                this.bot.sendMsg(this.room, this.current);
+                this.nextStep();
+            }
+        }).bind(this), this.config.wolfDelay * 1000);
     } else {
         this.nextStep();
     }
@@ -545,6 +642,13 @@ LoupGarou.prototype.cleanCorpses = function() {
     this.justDead = [];
 };
 
+LoupGarou.prototype.checkEndOfGameAndContinue = function() {
+    if (this.checkEndOfGame())
+        this.setStep(STEP.NOT_STARTED);
+    else
+        this.nextStep();
+};
+
 LoupGarou.prototype.checkEndOfGame = function() {
     var alive = [];
     for (var i in this.players) this.players[i].dead === null && alive.push(this.players[i]);
@@ -552,23 +656,20 @@ LoupGarou.prototype.checkEndOfGame = function() {
     if (alive.length === 2 && alive[0].lover === alive[1]) {
         this.bot.sendMsg(this.room, this.currentScenario.loverWins());
         this.bot.sendMsg(this.room, this.currentScenario.congrats(alive.map(i => i.name)));
-        this.setStep(STEP.NOT_STARTED);
         return true;
     }
     var liveWolfCount = alive.filter(i => i.role === ROLES.WOLF).length;
     if (liveWolfCount === alive.length) {
         this.bot.sendMsg(this.room, this.currentScenario.wolfWins());
         this.bot.sendMsg(this.room, this.currentScenario.congrats(alive.map(i => i.name)));
-        this.setStep(STEP.NOT_STARTED);
         return true;
     }
     if(!liveWolfCount) {
         this.bot.sendMsg(this.room, this.currentScenario.villagerWins());
         this.bot.sendMsg(this.room, this.currentScenario.congrats(alive.map(i => i.name)));
-        this.setStep(STEP.NOT_STARTED);
         return true;
     }
-    this.nextStep();
+    return false;
 };
 
 LoupGarou.prototype.advertiseDeath = function(player) {