]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/games/uno.rb
time: support POSIX time
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / games / uno.rb
index 84420631ecb317cb0d155d047c647b440d7c6d2d..870526fc38e8a9636d14252d97dcdca535d06147 100644 (file)
@@ -211,6 +211,13 @@ class UnoGame
     @bot.notice player.user, msg, opts
   end
 
+  def notify_error(player, msg, opts={})
+    announce _("you can't do that, %{p}") % {
+      :p => player.user
+    }
+    notify player, msg, opts
+  end
+
   def make_base_stock
     @base_stock = COLORS.inject([]) do |list, clr|
       VALUES.each do |n|
@@ -237,6 +244,7 @@ class UnoGame
   end
 
   def start_game
+    @join_timer = nil
     debug "Starting game"
     @players.shuffle!
     show_order
@@ -329,7 +337,7 @@ class UnoGame
   def next_turn(opts={})
     @players << @players.shift
     @player_has_picked = false
-    show_turn
+    show_turn unless opts[:silent]
   end
 
   def can_play(card)
@@ -390,14 +398,28 @@ class UnoGame
       toplay = (full == short) ? 1 : 2
     end
     debug [full, short, jolly, jcolor, toplay].inspect
-    # r7r7 -> r7r7, r7, nil, nil
-    # r7 -> r7, r7, nil, nil
-    # w -> w, nil, w, nil
-    # wg -> wg, nil, w, g
+    # r7r7 -> r7r7, r7, nil, nil, 2
+    # r7 -> r7, r7, nil, nil, 1
+    # w -> w, nil, w, nil, 1
+    # wg -> wg, nil, w, g, 1
+
+    # if @color is nil, the player just played a wild without specifying
+    # a color. (s)he should now use "co <colorname>", but we allow him to
+    # replay the wild _and_ specify the color, without actually replaying
+    # the card (which would otherwise happen if the player has another wild)
+    if @color.nil?
+      if jcolor
+        choose_color(p.user, jcolor)
+      else
+        announce _("you already played your card, ") + _("%{p}, choose a color with: co r|b|g|y") % { :p => p }
+      end
+      return
+    end
+
     if cards = p.has_card?(short)
       debug cards
       unless can_play(cards.first)
-        announce _("you can't play that card")
+        notify_error p, _("you can't play that card")
         return
       end
       if cards.length >= toplay
@@ -451,10 +473,10 @@ class UnoGame
           announce _("%{p}, choose a color with: co r|b|g|y") % { :p => p }
         end
       else
-        announce _("you don't have two cards of that kind")
+        notify_error p, _("you don't have two cards of that kind")
       end
     else
-      announce _("you don't have that card")
+      notify_error p, _("you don't have that card")
     end
   end
 
@@ -522,6 +544,10 @@ class UnoGame
       }
       deal(p, @picker)
       @picker = 0
+      # make sure that if this is the "pick and pass" after a W+4,
+      # then the following player cannot do a challenge:
+      @last_discard = nil
+      @last_color = nil
     else
       if @player_has_picked
         announce _("%{p} passes turn") % { :p => p }
@@ -699,11 +725,18 @@ class UnoGame
     }
     case @players.length
     when 2
+      if @join_timer
+        @bot.timer.remove(@join_timer)
+        announce _("game start countdown stopped")
+        @join_timer = nil
+      end
       if p == @players.first
-        next_turn
+        next_turn :silent => @start_time.nil?
+      end
+      if @start_time
+        end_game
+        return
       end
-      end_game
-      return
     when 1
       end_game(true)
       return
@@ -719,11 +752,17 @@ class UnoGame
   def replace_player(old, new)
     # The new user
     user = channel.get_user(new)
+    if not user
+      announce _("there is no '%{nick}' here") % {
+        :nick => new
+      }
+      return false
+    end
     if p = get_player(user)
       announce _("%{p} is already playing %{uno} here") % {
         :p => p, :uno => UNO
       }
-      return
+      return false
     end
     # We scan the player list of the player with the old nick, instead
     # of using get_player, in case of IRC drops etc
@@ -733,16 +772,22 @@ class UnoGame
         announce _("%{p} takes %{b}%{old}%{b}'s place at %{uno}") % {
           :p => p, :b => Bold, :old => old, :uno => UNO
         }
-        return
+        return true
       end
     end
     announce _("%{b}%{old}%{b} isn't playing %{uno} here") % {
       :uno => UNO, :b => Bold, :old => old
     }
+    return false
   end
 
   def end_game(halted = false)
     runtime = @start_time ? Time.now -  @start_time : 0
+    if @join_timer
+      @bot.timer.remove(@join_timer)
+      announce _("game start countdown stopped")
+      @join_timer = nil
+    end
     if halted
       if @start_time
         announce _("%{uno} game halted after %{time}") % {
@@ -880,6 +925,7 @@ class UnoPlugin < Plugin
     return unless @games.key?(m.channel)
     return unless m.plugin # skip messages such as: <someuser> botname,
     g = @games[m.channel]
+    replied = true
     case m.plugin.intern
     when :jo # join game
       return if m.params
@@ -945,7 +991,10 @@ class UnoPlugin < Plugin
       else
         g.show_turn(:cards => false)
       end
+    else
+      replied=false
     end
+    m.replied=true if replied
   end
 
   def create_game(m, p)