diff --git a/dicebot.rb b/dicebot.rb new file mode 100755 index 0000000..77abcc6 --- /dev/null +++ b/dicebot.rb @@ -0,0 +1,607 @@ +#!/usr/bin/env ruby +# encoding: utf-8 + +require 'rubygems' +require 'xmpp4r' +require 'xmpp4r/muc/helper/simplemucclient' + +# Initialement cree par Philippe Depriester et Clement Gauche + +salut = ["Bonjour","Chalut","Coucou","Salutations"] +join = false +if ARGV.size < 3 + puts "Usage: #{$0} [debug]" +username = "" +password = "" +room_and_nick = "" +mynick = "" +else +username = ARGV[0] +password = ARGV[1] +room_and_nick = ARGV[2] +mynick = room_and_nick.split("/")[1] +debug = ARGV[3] ? ARGV[3] : false +end + +version = '0.9.2' +#Jabber::debug = true +#test = [" :roll env -10D10 x2;on tire 5 carte; :carte x5#e+- 5d6W6 2d 3dw+--+ 2 - 3 + dw - 3d0 + 7d1 -- w8 X2", ":roll nvwg5f2 +10d2w1e +w0 10d2w1 -e#n10d2 +#f10d2w1+#f#n10d2w1#gx2",":alias tot lol",":alias totv 2d6",":alias :tot 1d6",":roll v :totv","roll ven; ; ; ;-#n10d2--#e#v10d2x2; ;:roll; ;1d6;w",":alias ** :roll;",":aliasd furtd ;vne 1d6w+4;","**S'approche furtivement de sa cible;1d6; ;+2**","totv 1d6",":alias tot :roll",":alias totv :roll",":alias tot :roll","totv 1d6",":alias toto",":alias toto francis aime acheter du pain",":alias francis toto aussi",":alias toto",":alias",":alias clear toto",":alias toto",":alias",":alias clear",":alias",":sw -n -10d2 -v-en 10d2",":roll dw",":roll wdw","Salut la compagnie, une petite partie de JdR ça vous tente ? J'ai pris mes dés et mes cartes ",":roll w",":roll w ",":roll v w 2d 3d","toto aime la ^plage",":roll toto",":roll env -10D10 x2;on tire 5 carte; :carte x5;on mélange; :carte m x2 5d6W2 2d 3dw+--+ 2 - 3 + dw - 3d0 + 7d1 -- w8 X2",":roll v 6d6w",":roll v -1",":roll v w8",":roll v -1 + 5d6",":roll env -10D10 +- 5d6W +--+ 2 - 3 + dw - 3d0 + 7d1 -- w8", ":sw d8 8w +8 -1d", ":roll", ":roll -8 lol"] +$alias = {} +$cartes_base = ["As de carreau", "2 de carreau", "3 de carreau", "4 de carreau", "5 de carreau", "6 de carreau", "7 de carreau", "8 de carreau", "9 de carreau", "10 de carreau", "Valet de carreau", "Dame de carreau", "Roi de carreau", "As de coeur", "2 de coeur", "3 de coeur", "4 de coeur", "5 de coeur", "6 de coeur", "7 de coeur", "8 de coeur", "9 de coeur", "10 de coeur", "Valet de coeur", "Dame de coeur", "Roi de coeur", "As de pique", "2 de pique", "3 de pique", "4 de pique", "5 de pique", "6 de pique", "7 de pique", "8 de pique", "9 de pique", "10 de pique", "Valet de pique", "Dame de pique", "Roi de pique", "As de trèfle", "2 de trèfle", "3 de trèfle", "4 de trèfle", "5 de trèfle", "6 de trèfle", "7 de trèfle", "8 de trèfle", "9 de trèfle", "10 de trèfle", "Valet de trèfle", "Dame de trèfle", "Roi de trèfle", "Joker rouge", "Joker noir"] +$cartes = ["0"] +$cartes.replace($cartes_base) +class Parser + attr_accessor :str, :mtch, :arg, :old, :nick, :option + def initialize (str, nick) + @str = str.strip + @nick = nick + @old = "" + @mtch = "" + @arg = {} + @option = [false,false,false,0,0,0,0,0,false,0] + end + def space () + if @str =~ /^\s/ + return true + elsif @str =~ /^$/ + return true + end + end + def restaure () + @str = mtch + str + @old.sub(/\s*(;(.*?);)*\s*#{ mtch }$/,'') + end + def eat (mtch, opt) + if mtch != ".+" and mtch != "\\s" + @str =~ /^(\s*(;(.*?);)*)*(.*)/ + #$bot.say "str = " + @str + #$bot.say "pr-$1 =" + $1 if $1 + #$bot.say "pr-$2 =" + $2 if $2 + #$bot.say "pr-$3 =" + $3 if $3 + #$bot.say "pr-$4 =" + $4 if $4 + @str = $4 + @old += $1 + end + if str =~ /^(#{ mtch })(.*)/ + #$bot.say "str = " + @str + if (opt == 1) + #$bot.say "$1 =" + $1 + #$bot.say "$2 =" + $2 + #$bot.say "$3 =" + $3 + @mtch = $1 + @str = $2 + @old += $1 + end + return true; + end + return false; + end +end +# Print a line formatted depending on time.nil? +def print_line(time, line) + if time.nil? + puts line + else + puts "#{time.strftime('%I:%M')} #{line}" + end +end +def carte(opt) + #if opt =~ /.*m.*/ # Melanger les cartes. + if opt + $cartes.replace($cartes_base) + return "Paquet mélangé" + else + nb = rand($cartes.length).to_i + value = $cartes.at(nb) + $cartes.delete_at(nb) + return value + end + +end + +def card() + return $cartes_base.at(rand($cartes_base.length).to_i) +end + +def roll(result,type,explosif,nb,f,noadd,ars,relance) + roll = 0 + new = 0 + if (ars) + roll = 1 + if (type > 1) + tmp = 1 + begin + roll *= 2 + tmp = rand(type).to_i + 1 + end while ars and tmp == 1 + roll = ((roll/2)*tmp) + end + else + begin + roll += (tmp = rand(type).to_i + 1) + end while explosif and tmp == type + end + + #print_line nil, "relance : " + relance.to_s + #print_line nil, "roll : " + roll.to_s + if (relance != 0 && relance != 1 && relance <= roll) + new = 1 + end + #print_line nil, new + + result += (nb>0 ? ' ' : '') + roll.to_s + if (f!=0 && roll=f && noadd) + tmp = (roll/type).to_i + roll = tmp + ((roll - tmp*type) >=f ? 1 : 0) + end + return [result,roll,new] +end +def rolls(result,jet,type,nb,explosif,noadd,wild,f,g,ars,relance) + total = 0 + allresult = [] + if (tmp=(type && nb)) + jet += nb.to_s+"d"+type.to_s + nb.times do |n| + new = 0 + begin + result, res1, new = roll(result,type,explosif,n,f,noadd,ars,relance) + allresult << res1 + end while new == 1 + end + end + if wild != 0 + jet += "w" + wild.to_s + result, res1, new = roll(result,wild,wild!=1,nb ? nb : 0,f,noadd,ars,relance) + allresult << res1 + result += 'w' + end + allresult = allresult.sort.reverse + (0..((g==0 and ((f!=0 and noadd) or not noadd)) ? (allresult.length() -1): ((noadd and f == 0) ? 0 : g-1))).each do | i | + total += allresult[i] ? allresult[i] : 0 + end + jet += "g" + g.to_s if g != 0 + jet += "f" + f.to_s if f != 0 + jet += "r" + relance.to_s if relance != 0 + if tmp + jet += (explosif != $parser.option[0] ? (explosif == true ? "e" : "#e") : "") + (noadd != $parser.option[1] ? (noadd == true ? "n" : "#n") : "") + (ars != $parser.option[8] ? (ars == true ? "a" : "#a") : "") + end + return [result, total,jet] +end + +def help () + $bot.say("\n==== Commandes du bot ====\nOptions : e (explosif : relance sur un max), n (noadd : pas d'addition entre les dés), v (verbeux : donne le détail), w (wild die : dé additionnel, conserve le meilleur), f (seuil : seuil de difficulté pour chaque dé), g (garde : nombre de dés conservés), s (seuil : avec niveaux de réussite), a (ars magica : dé de tension), r (rejoue : lance un dé supplémentaire si le seuil est atteint), # + lettre : annule une option en cours\nExemples : ':roll d6', ':roll 3d6', ':roll 1d20+1'; Tirer deux fois 10 dés 10 en mode verbeux sans les ajouter et explosifs :roll env 10D10+5 x2; \n\nFonctions et raccourcis :\n':carte' Tire une carte retirée du paquet. ':carte m' Mélange le paquet. :card' Tire une carte sans la retirer du paquet.\n:sw (Savage Wolrds) ':sw d8w' Lance en mode verbose, explosif et no add un d8 accompagné d'un wild die d6, meilleur conservé contre un seuil de 4. - :dom (Dommages) :dom 3d6' lance 3d6 en mode verbose et explosif.\n:ars (Ars Magica) ':ars 1d10' (jette un dé de tension, si le résultat est 1, on relance et on double) - :des (Désastre) ':des 4d10' (jette 4d10 et retourne le nombre de 0 obtenus)\n\n Exemple complexe : ':roll ven s4/2 3d10w8+2 #s#n 4d10g2 - 3 n#e 6D10f8r9 #n 3d8-2d10+2' : \n - Lancer en mode verbeux/explosif/noadd pour un seuil de 4 avec niveau de réussite par tranche de 2 3 dés 10 avec wild die en d8 et ajouter 2 au meilleur en retournant les succès et niveaux de réussite, \n - Pis lancer en désactivant l'option de seuil et de noadd 4d10 et additionner les deux meilleurs en ôtant 3 et retourner le résultat,\n - Puis réactiver l'option noadd en désactivant l'option explosif et lancer 6d10 en comptant les dés atteignant au moins 8 et relancer ceux atteignant au moins 9 et retourner le nombre de succès,\n - Enfin, désactiver l'option noadd pour lancer 3 dés 8 et ôter à la somme 2 dés 10 puis ajouter 2 et retourner le résultat.\n\n- :alias => Liste tous ses alias - :alias cmd effet => enregistre l'alias cmd (ne doit etre composé d'espace) a effet (le reste du message, et composé du reste du message) - :alias clear => Efface toutes ses alias - :alias clear cmd => Efface l'alias ayant pour nom cmd") +end +class MyDebugguer + def initialize() + end + def say (par) + print_line nil, par + end +end +$bot = MyDebugguer.new +def aliasPoint() + lalias = $alias.has_key?($parser.nick) ? $alias[$parser.nick] : ($alias[$parser.nick] = {}) + if $parser.eat(":alias",1) + aliasCommandPoint() + else + lalias.keys.sort_by {|k| -k.length}.each { |key| + $parser.str.gsub!(key, lalias[key]) + } + #$bot.say("Désaliassé = " + $parser.str) + entryPoint() + end +end +def aliasCommandPoint + lalias = $alias[$parser.nick] + if $parser.eat("clear",1) + if $parser.eat("[^\\s]+",1) + if lalias.has_key?($parser.mtch) + lalias.delete $parser.mtch + $bot.say($parser.nick + ": " + $parser.mtch + " deleted") + else + $bot.say($parser.nick + ": " + $parser.mtch + " not be aliased") + end + else + $alias[$parser.nick] = {} + $bot.say($parser.nick + ": alias cleared") + end + elsif $parser.eat("[^\\s]+",1) + par1 = $parser.mtch + $parser.eat("\\s",1) + if $parser.eat(".+",1) + lalias[par1] = $parser.mtch + $bot.say($parser.nick + ": " + par1 + " = " + $parser.mtch) + elsif (lalias.has_key?(par1)) + $bot.say($parser.nick + ": " + par1 + " = " + lalias[par1]) + else + $bot.say($parser.nick + ": " + par1 + " not be aliased") + end + elsif (lalias.length != 0) + lalias.each do | key, value | + $bot.say($parser.nick + ": " + key + " = " + value) + end + else + $bot.say($parser.nick + ": You have no alias recorded") + end +end +def entryPoint () + if $parser.eat(":card",1) + $bot.say(card()) + if ($parser.eat("[xX]",1)) + if ($parser.eat("\\d+",1)) + ($parser.mtch.to_i - 1).times do + $bot.say(card()) + end + else + $parser.arg["error"] = true + end + end + elsif $parser.eat(":carte",1) + m = $parser.eat("[mM]",1) ? true : false + $bot.say(carte(m)) + if ($parser.eat("[xX]",1)) + if ($parser.eat("\\d+",1)) + ($parser.mtch.to_i - 1).times do + $bot.say(carte(m)) + end + else + $parser.arg["error"] = true + end + end + elsif $parser.eat(":roll",1) + $parser.option = [false,false,false,0,0,0,0,0,false,0] + rollXPoint() + elsif $parser.eat(":dom",1) + $parser.option = [true,false,true,0,0,0,4,4,false,0] + rollXPoint() + elsif $parser.eat(":sw",1) + $parser.option = [true,true,true,0,0,0,4,4,false,0] + rollXPoint() + elsif $parser.eat(":ars",1) + $parser.option = [false,true,true,0,0,0,0,0,true,0] + rollXPoint() + elsif $parser.eat(":des",1) + $parser.option = [false,true,true,0,10,0,0,0,false,0] + rollXPoint() + elsif $parser.eat(":wod",1) + $parser.option = [false,true,true,0,8,0,0,0,false,10] + rollXPoint() + elsif $parser.str =~ /^(.*)jdr(.*)$/ + $parser.str="" + jdr($parser.nick) + elsif $parser.str =~ /^(.*)gens(.*)$/ + $parser.str="" + gens($parser.nick) + elsif $parser.str =~ /^(.*)ça va|vas(.*)$/ + $parser.str="" + va($parser.nick) + elsif $parser.str =~ /^(.*)maman|mère(.*)$/ + $parser.str="" + maman($parser.nick) + elsif $parser.arg["noerror"] + rollXPoint() + else + $parser.arg["error"] = true + end + if not $parser.arg["error"] and not $parser.eat("$",0) + $parser.arg["noerror"] = true + entryPoint() + end +end +def rollOptionPoint () + while true + if $parser.eat("[eE]",1) + $parser.option[0] = true + elsif $parser.eat("#[eE]",1) + $parser.option[0] = false + elsif $parser.eat("[nN]",1) + $parser.option[1] = true + elsif $parser.eat("#[nN]",1) + $parser.option[1] = false + elsif $parser.eat("[vV]",1) + $parser.option[2] = true + elsif $parser.eat("#[vV]",1) + $parser.option[2] = false + elsif $parser.eat("[wW]",1) + if $parser.space() + $parser.option[3] = 6 + elsif $parser.eat("\\d+",1) + $parser.option[3] = $parser.mtch.to_i + else + $parser.option[3] = 6 + end + elsif $parser.eat("#[wW]",1) + $parser.option[3] = 0 + elsif $parser.eat("[fF]",1) + if $parser.space() + $parser.option[4] = 6 + elsif $parser.eat("\\d+",1) + $parser.option[4] = $parser.mtch.to_i + else + $parser.option[4] = 6 + end + elsif $parser.eat("#[fF]",1) + $parser.option[4] = 0 + elsif $parser.eat("[gG]",1) + if $parser.space() + $parser.option[5] = 6 + elsif $parser.eat("\\d+",1) + $parser.option[5] = $parser.mtch.to_i + else + $parser.option[5] = 6 + end + elsif $parser.eat("#[gG]",1) + $parser.option[5] = 0 + elsif $parser.eat("[sS]",1) + if $parser.space() + $parser.option[6] = 4 + elsif $parser.eat("\\d+",1) + $parser.option[6] = $parser.mtch.to_i + else + $parser.option[6] = 4 + end + if $parser.eat("[/]",1) + if $parser.space() + $parser.option[7] = 4 + elsif $parser.eat("\\d+",1) + $parser.option[7] = $parser.mtch.to_i + else + $parser.option[7] = 4 + end + else + $parser.option[7] = 4 + end + elsif $parser.eat("#[sS]",1) + $parser.option[6] = 0 + $parser.option[7] = 0 + elsif $parser.eat("[aA]",1) + $parser.option[8] = true + elsif $parser.eat("#[aA]",1) + $parser.option[8] = false + elsif $parser.eat("[rR]",1) + if $parser.space() + $parser.option[9] = 10 + elsif $parser.eat("\\d+",1) + $parser.option[9] = $parser.mtch.to_i + else + $parser.option[9] = 10 + end + elsif $parser.eat("#[rR]",1) + $parser.option[9] = 0 + elsif $parser.eat("[hH]+[eE]+[lL]+[pP]+",1) + help() + $parser.arg["noerror"] = true + else + break; + end + end +end +def rollXPoint() + rollPlusMoinsPoint() + if ($parser.eat("[xX]",1)) + if ($parser.eat("\\d+",1)) + tmp = $parser + str = $parser.arg["jet"] + ($parser.mtch.to_i - 1).times do + $parser = $parser.clone + $parser.str = str + $parser.option = [$parser.option[0],$parser.option[1],$parser.option[2],0,0,0,$parser.option[6],$parser.option[7],$parser.option[8],$parser.option[9]] + rollPlusMoinsPoint() + end + $parser = tmp + else + $parser.arg["error"] = true + end + end +end +def rollPlusMoinsPoint () + $parser.arg["roll_sig"] = true + $parser.arg["error"] = nil + result = "" + jet = "" + rollOptionPoint() + exp,noa,ver,will,f,g,s,d,ars,r = $parser.option + rollEntityPoint() + if not $parser.arg["error"] + if not $parser.arg["roll_sig"] + jet += "-" + result += "-"; + end + if $parser.arg["roll_typ"] or $parser.arg["roll_wil"] + result += "("; + exp2,noa2,ver2,will2,f2,g2,s2,d2,ars2,r2 = $parser.option + $parser.option = [exp,noa,ver,will,f,g,s,d,ars,r] + result, res1, jet = rolls(result,jet,$parser.arg["roll_typ"],$parser.arg["roll_nb"],exp2,noa2,will2,f2,g2,ars2,r2) + result += " = " +res1.to_s+")"; + else + jet += $parser.arg["roll_nb"].to_s + result += $parser.arg["roll_nb"].to_s + res1 = $parser.arg["roll_nb"] + end + if not $parser.arg["roll_sig"] + res1 = -res1; + end + while ($parser.eat("[+-]",1)) + $parser.arg["roll_sig"] = true + if ($parser.mtch == "-") + $parser.arg["roll_sig"] = ! $parser.arg["roll_sig"] + end + rollEntityPoint() + if not $parser.arg["error"] + jet += $parser.arg["roll_sig"] ? " +" : " -" + result += ($parser.arg["roll_sig"] ? " + " : " - ") + if $parser.arg["roll_typ"] or $parser.arg["roll_wil"] + result += "(" + exp2,noa2,ver2,will2,f2,g2,s2,d2,ars2,r2 = $parser.option + $parser.option = [exp,noa,ver,will,f,g,s,d,ars,r] + result, res2, jet = rolls(result,jet,$parser.arg["roll_typ"],$parser.arg["roll_nb"],exp2,noa2,will2,f2,g2,ars2,r2) + result += " = " + res2.to_s+ ")"; + else + jet += $parser.arg["roll_nb"].to_s + result += $parser.arg["roll_nb"].to_s + res2 = $parser.arg["roll_nb"] + end + res1 += $parser.arg["roll_sig"] ? res2 : -res2 + end + end + end + if (res1) + if ver + result = jet + ' = ('+ result +') = ' + res1.to_s + else + result = jet + ' = ' + res1.to_s + end + result += "/"+((tmp=(res1-s)/d +1) < 0 ? "0":tmp.to_s) if s != 0 + $parser.arg["jet"] = jet + $bot.say("#{$parser.nick} rolls "+(exp ? "e":"")+(noa ? "n":"")+(ver ? "v":"")+(ars ? "a":"")+(s!=0 ? "s"+s.to_s+"/"+d.to_s : "")+((exp or noa or ver or s!=0) ? " " : "")+ "#{result}") + elsif not $parser.arg["noerror"] + $bot.say("match = #{$parser.mtch}\nstr = #{$parser.str}") + $bot.say("Rien compris. Essayez ':roll help' pour obtenir de l'aide.") + end +end +def rollEntityPoint () + if ($parser.eat("[-+]", 0)) + while $parser.eat("[-+]", 1) + if $parser.mtch == "-" + $parser.arg["roll_sig"] = ! $parser.arg["roll_sig"] + end + end + end + rollOptionPoint + rollNbPoint +end +def rollNbPoint () + $parser.arg["roll_nb"] = nil + if $parser.eat("\\d+",1) + $parser.arg["roll_nb"] = $parser.mtch.to_i + end + rollDPoint() +end +def rollDPoint() + if !$parser.space() and $parser.eat("[dD]",1) + if not $parser.arg["roll_nb"] + $parser.arg["roll_nb"] = 1 + end + $parser.arg["roll_bon"] = 0 + rollTypePoint() + elsif $parser.arg["roll_nb"] + $parser.arg["roll_typ"] = nil + else + $parser.arg["error"] = true + end +end +def rollTypePoint() + if $parser.space() + $parser.arg["roll_typ"] = 6 + elsif $parser.eat("\\d+",1) + $parser.arg["roll_typ"] = $parser.mtch.to_i + if ($parser.mtch == "1") + $parser.option[0] = false + end + else + $parser.arg["roll_typ"] = 6 + end + rollOptionPoint() + if ! $parser.arg["roll_nb"] + $parser.arg["error"] = true + end +end +def reponses(phrases) + i = rand(phrases.length) + $bot.say(phrases.at(i)) +end +def jdr(nick) + phrases = Array.new + phrases.push("Rock & Rôle baby!") + phrases.push("De toute manière #{nick}, les gens ont perdu la foi dans le rolisme.") + phrases.push("Bon, c'est quand la prochaine partie #{nick}?") + reponses(phrases) +end +def gens(nick) + phrases = Array.new + phrases.push("L'enfer c'est les autres.") + phrases.push("Bah #{nick}, les gens c'est pratique pour jouer aux osselets. Bon faut juste trouver où mettre la chair ensuite.") + phrases.push("Franchement #{nick}, les gens c'est comme les films X. Plus il y'en a, plus ça part en couilles...") + reponses(phrases) +end +def va(nick) + phrases = Array.new + phrases.push("Moi ça va si jamais quelqu'un se pose la question...") + phrases.push("Quand l'appétit va, tout va #{nick}!") + phrases.push("Attention à #{nick}, la suite est 'not safe for depression'") + reponses(phrases) +end +def maman(nick) + phrases = Array.new + phrases.push("On avait dit 'Pas les mamans'!") + phrases.push("Oh, c'est pas la mère à boire #{nick}!") + phrases.push("C'est pas l'homme qui prend la mère, c'est la mère qui prend l'homme... Ouch trompé de salon, désolé #{nick}.") + reponses(phrases) +end +if debug + test.each do |cmd| + $bot.say("==> " + cmd) + $parser = Parser.new cmd,"Jinashi" + aliasPoint(); + end +end + +if (not debug) +xmpp = Jabber::Client.new(Jabber::JID::new(username)) +print_line nil, "#{username}." +xmpp.connect +print_line nil, "Connected." +xmpp.auth(password) +print_line nil, "Authenticated." +xmpp.send(Jabber::Presence::new.set_type(:available)) + +mainthread = Thread.current + +$bot = Jabber::MUC::SimpleMUCClient.new(xmpp) + +$bot.on_join { |time, nick| + if (join && $bot.roster.keys.select{ |i| i[/^#{nick.sub("_","")}_*$/] }.count == 1) + coucou=salut.at(rand(salut.length)) + print_line time, "#{coucou} #{nick} !" + $bot.say("#{coucou} #{nick} !") + end + print_line time, "#{nick} joined the chat." + puts "Users: " +$bot.roster.keys.join(', ') +} + +$bot.on_leave { |time, nick| + print_line time, "#{nick} left the chat." +} +$bot.on_message { |time, nick, text | + + print_line time, "<#{nick}> #{text}" + + unless time + if nick != mynick + $parser = Parser.new text, nick + aliasPoint(); + end + end +} +$bot.on_room_message { |time,text| + print_line time, "- #{text}" +} +$bot.on_subject { |time,nick,subject| + print_line time, "*** (#{nick}) #{subject}" +} + +$bot.join(room_and_nick) +print_line nil, "Room joined." +$bot.say("Salut la compagnie, une petite partie de JdR ça vous tente ? J'ai pris mes dés et mes cartes :)"); +join = true + +#while 1 +# cmd = STDIN.gets.chomp() +# $bot.say(cmd) +#end +Thread.stop + +xmpp.close +end