#!/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