I would like the bot points to be hidden from the Top10 or if there's a way to prevent them altogether in Marky's Color UNO.
Thank you!
**The entire script is too large to fit in one post. The rest of the script is in the next post.**
Code: Select all
# Marky's Color Uno v0.98
# Copyright (C) 2004-2011 Mark A. Day (techwhiz@embarqmail.com)
#
# Uno(tm) is Copyright (C) 2001 Mattel, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# default settings (these are overridden by uno.cfg)
set UnoAds 1
set UnoDebug 0
set UnoChan "#World-UNO"
set UnoRobot $botnick
set UnoPointsName "Points"
set UnoStopAfter 3
set UnoJoinAnyTime 0
set UnoUseDCC 0
set UnoBonus 1000
set UnoWildDrawTwos 0
set UnoWDFAnyTime 0
set UnoMaxNickLen 9
set UnoMaxPlayers 10
set UnoOpFlags "o|o"
set UnoNTC "NOTICE"
set UnoCFGFile "scripts/added/uno/uno.cfg"
set UnoScoreFile "UnoScores"
set UnoVersion "1.00.0"
# command binds
bind pub - !uno UnoInit
bind pub "o|o" !stop UnoStop
bind pub "o|o" !pause UnoPause
bind pub "o|o" !join UnoJoinBotPlayer
bind pub - !remove UnoRemove
bind pub - !unocmds UnoCmds
bind pub - !unowon UnoWon
bind pub - !unotop10 UnoTopTen
bind pub - !unotop3last UnoTopThreeLast
bind pub - !unostats UnoPlayStats
bind pub - !unorecords UnoRecords
bind pub - !unorow UnoCurrentRow
bind pub - !unoversion UnoVersion
# dcc commands
bind dcc - unohands dccunohands
bind dcc - unowritecfg dcc_unowriteconfig
bind dcc - unorehash dcc_unorehash
bind dcc - unopoints dcc_unopoints
# monthly score reset
bind time - "00 00 01 * *" UnoNewMonth
# rehash
bind evnt - "prerehash" unoevnt:prerehash
proc unoevnt:prerehash {type} {
global UnoRobot UnoChan
UnoStop $UnoRobot "console" $UnoRobot $UnoChan ""
}
# restart
bind evnt - "prerestart" unoevnt:prerestart
proc unoevnt:prerestart {type} {
global UnoRobot UnoChan
UnoStop $UnoRobot "console" $UnoRobot $UnoChan ""
}
# global variables
set UnoOn 0
set UnoMode 0
set UnoPaused 0
set UnoPlayers 0
set MasterDeck ""
set UnoDeck ""
set DiscardPile ""
set PlayCard ""
set RoundRobin ""
set ThisPlayer ""
set ThisPlayerIDX 0
set UnoStartTime [unixtime]
set IsColorChange 0
set ColorPicker ""
set IsDraw 0
set UnoIDX ""
set UnPlayedRounds 0
set UnoWinDefault 0
set UnoLastWinner ""
set UnoLastIdler ""
set UnoWinsInARow 0
# card types
set unocardtype_invalid 0
set unocardtype_skip 1
set unocardtype_reverse 2
set unocardtype_draw2 3
set unocardtype_draw4 4
set unocardtype_wild 5
set unocardtype_number 6
# scores, records and ads
set UnoLastMonthCards(0) "Nobody 0"
set UnoLastMonthCards(1) "Nobody 0"
set UnoLastMonthCards(2) "Nobody 0"
set UnoLastMonthGames(0) "Nobody 0"
set UnoLastMonthGames(1) "Nobody 0"
set UnoLastMonthGames(2) "Nobody 0"
set UnoFast "Nobody 600"
set UnoHigh "Nobody 0"
set UnoPlayed "Nobody 0"
set UnoRow "Nobody 0"
set UnoRecordHigh "Nobody 0"
set UnoRecordFast "Nobody 600"
set UnoRecordCard "Nobody 0"
set UnoRecordWins "Nobody 0"
set UnoRecordPlayed "Nobody 0"
set UnoRecordRow "Nobody 0"
set UnoAdNumber 0
# card stats
set CardStats(played) 0
# timers
set UnoStartTimer ""
set UnoSkipTimer ""
set UnoCycleTimer ""
set UnoBotTimer ""
#
# grace periods and timeouts ( AutoSkipPeriod can be raised but dont go below 2)
#
# time to skip an inactive player
set AutoSkipPeriod 2
# time to join game
set StartGracePeriod 30
# time between games
set UnoCycleTime 30
# internal bot player use dont change
set RobotRestartPeriod 1
# nick colors
set UnoNickColors "6 13 3 7 12 10 4 11 9 8 5"
# cards and logo
set UnoRedCard "\0030,04 Red "
set UnoGreenCard "\0030,03 Green "
set UnoBlueCard "\0030,12 Blue "
set UnoYellowCard "\0031,08 Yellow "
set UnoSkipCard "\002Skip\002 \003 "
set UnoReverseCard "\002Reverse\002 \003 "
set UnoDrawTwoCard "\002Draw Two\002 \003 "
set UnoWildCard "\0031,8 \002W\0030,3I \0030,4L\0030,12D\002 \003 "
set UnoWildDrawFourCard "\0031,8 \002W\0030,3I \0030,4L\0030,12D \0031,8D\0030,3r\0030,4a\0030,12w \0031,8F\0030,3o\0030,4u\0030,12r\002 \003 "
set UnoLogo "\002\0033U\00312N\00313O\00308!\002\003"
#
# bind channel commands
#
proc UnoBindCmds {} {
bind pub - jo UnoJoin
bind pub - od UnoOrder
bind pub - ti UnoTime
bind pub - ca UnoShowCards
bind pub - pl UnoPlayCard
bind pub - cd UnoTopCard
bind pub - tu UnoTurn
bind pub - dr UnoDraw
bind pub - co UnoColorChange
bind pub - pa UnoPass
bind pub - ct UnoCardCount
bind pub - st UnoCardStats
bind chon - * unologin:dcc
bind chof - * unologout:dcc
bind filt - .quit* unologout:filt
}
#
# unbind channel commands
#
proc UnoUnbindCmds {} {
catch {unbind pub - jo UnoJoin}
catch {unbind pub - od UnoOrder}
catch {unbind pub - ti UnoTime}
catch {unbind pub - ca UnoShowCards}
catch {unbind pub - pl UnoPlayCard}
catch {unbind pub - cd UnoTopCard}
catch {unbind pub - tu UnoTurn}
catch {unbind pub - dr UnoDraw}
catch {unbind pub - co UnoColorChange}
catch {unbind pub - pa UnoPass}
catch {unbind pub - ct UnoCardCount}
catch {unbind pub - st UnoCardStats}
catch {unbind chon - * unologin:dcc}
catch {unbind chof - * unologout:dcc}
catch {unbind filt - .quit* unologout:filt}
}
#
# reset game variables
#
proc UnoReset {} {
global UnoOn UnoMode UnoPaused UnoPlayers RoundRobin UnoDeck ThisPlayer ThisPlayerIDX PlayCard
global DiscardPile IsColorChange ColorPicker IsDraw UnoIDX MasterDeck CardStats
global UnoStartTimer UnoSkipTimer UnoCycleTimer UnoWinDefault UnoRobot botnick UnoLastIdler
set UnoMode 0
set UnoPaused 0
set UnoPlayers 0
set MasterDeck ""
set UnoDeck ""
set DiscardPile ""
set RoundRobin ""
set ThisPlayer ""
set ThisPlayerIDX 0
set PlayCard ""
set IsColorChange 0
set ColorPicker ""
set IsDraw 0
set UnoIDX ""
set UnoAdNumber 0
set UnoWinDefault 0
set UnoLastIdler ""
set CardStats(played) 0
set UnoStartTimer ""
set UnoSkipTimer ""
set UnoCycleTimer ""
set UnoRobot $botnick
return
}
# return 1 if is this the uno channel, else return 0
proc uno_ischan {chan} {
global UnoChan
if {([string tolower $chan] == [string tolower $UnoChan])} {return 1}
return 0
}
# return 1 if is this the uno channel and uno is running, else return 0
proc uno_isrunning {chan} {
global UnoMode
if {([uno_ischan $chan])&&($UnoMode == 2)} {return 1}
return 0
}
# remove player dcc list
proc uno_removedccplayers { } {
global RoundRobin UnoDCCIDX
set pcount 0
while {[lindex $RoundRobin $pcount] != ""} {
set pnick [lindex $RoundRobin $pcount]
if [info exist UnoDCCIDX($pnick)] {unset UnoDCCIDX($pnick)}
incr pcount
}
}
#
# stop a game
#
proc UnoStop {nick uhost hand chan txt} {
global UnoOn UnoPaused UnPlayedRounds UnoStartTimer UnoSkipTimer UnoCycleTimer UnoLastWinner UnoWinsInARow
if {(![uno_ischan $chan])||($UnoOn == 0)} {return}
catch {killutimer $UnoStartTimer}
catch {killtimer $UnoSkipTimer}
catch {killutimer $UnoCycleTimer}
# remove player dcc list
uno_removedccplayers
set UnoOn 0
set UnoPaused 0
set UnPlayedRounds 0
set UnoLastWinner ""
set UnoWinsInARow 0
UnoUnbindCmds
UnoReset
unochanmsg "stopped by $nick"
unoupdatetopic $chan
return
}
proc unoupdatetopic { chan } {
set mode 1
set topic [UnoTop10 $mode 1]
puthelp "TOPIC $chan :$topic"
}
#
# first entry
#
proc UnoInit {nick uhost hand chan txt} {
global UnoOn
if {(![uno_ischan $chan])||($UnoOn > 0)} {return}
#unochanmsg "$nick\!$uhost"
set UnoOn 1
UnoBindCmds
UnoNext
return
}
#
# initialize a new game
#
proc UnoNext {} {
global UnoOn MasterDeck UnoDeck UnoMode StartGracePeriod UnoHand UnoNickColor UnoVersion UnoStartTimer UnoSkipTimer
if {!$UnoOn} {return}
UnoReset
set UnoMode 1
set MasterDeck [list B0 B1 B1 B2 B2 B3 B3 B4 B4 B5 B5 B6 B6 B7 B7 B8 B8 B9 B9 BR BR BS BS BD BD R0 R1 R1 R2 R2 R3 R3 R4 R4 R5 R5 R6 R6 R7 R7 R8 R8 R9 R9 RR RR RS RS RD RD Y0 Y1 Y1 Y2 Y2 Y3 Y3 Y4 Y4 Y5 Y5 Y6 Y6 Y7 Y7 Y8 Y8 Y9 Y9 YR YR YS YS YD YD G0 G1 G1 G2 G2 G3 G3 G4 G4 G5 G5 G6 G6 G7 G7 G8 G8 G9 G9 GR GR GS GS GD GD W W W W WD WD WD WD]
unochanmsg "$UnoVersion by #World-Chat Team"
set done 0
while {!$done} {
set rseed [rand 65535]
if {$rseed} {set done 1}
}
set newrand [expr srand($rseed)]
set newrand [rand [llength $MasterDeck]]
set UnoDeck ""
while {[llength $UnoDeck] != 108} {
set pnum [rand [llength $MasterDeck]]
set pcard [lindex $MasterDeck $pnum]
lappend UnoDeck $pcard
set MasterDeck [lreplace $MasterDeck $pnum $pnum]
}
if [info exist UnoHand] {unset UnoHand}
if [info exist UnoNickColor] {unset UnoNickColor}
unochanmsg "You have \00314\002[UnoDuration $StartGracePeriod]\002\003 to join uno"
set UnoStartTimer [utimer $StartGracePeriod UnoStart]
return
}
#
# cycle a new game
#
proc UnoCycle {} {
global UnoOn UnoMode UnoCycleTime UnoCycleTimer UnoSkipTimer UnoAds
if {!$UnoOn} {return}
set UnoMode 4
catch {killtimer $UnoSkipTimer}
if {$UnoAds} {
set AdTime [expr $UnoCycleTime /2]
set UnoAdTimer [utimer $AdTime UnoScoreAdvertise]
}
set UnoCycleTimer [utimer $UnoCycleTime UnoNext]
return
}
# force bot player to join
proc UnoJoinBotPlayer {nick uhost hand chan txt} {
global UnoMode UnoOn
if {!$UnoOn || ($UnoMode != 2)} {return}
UnoBotPlayerJoins
return 0
}
# bot player joins in if no one else does
proc UnoBotPlayerJoins {} {
global UnoPlayers RoundRobin UnoIDX UnoRobot UnoLogo UnoDebug UnoHand UnoNickColor
# prevent bot player from joining multiple times
if [info exist UnoHand($UnoRobot)] { return }
incr UnoPlayers
lappend RoundRobin $UnoRobot
lappend UnoIDX $UnoRobot
set UnoHand($UnoRobot) ""
set UnoNickColor($UnoRobot) [unocolornick $UnoPlayers]
unomsg "[unonik $UnoRobot]\003 joins $UnoLogo"
# deal hand to bot
uno_newplayerhand $UnoRobot
}
#
# start a new game
#
proc UnoStart {} {
global UnoChan UnoOn UnoCycleTime UnoRobot UnoDebug UnoIDX UnoStartTime UnoPlayers RoundRobin ThisPlayer ThisPlayerIDX UnoDeck DiscardPile UnoMode UnoHand AutoSkipPeriod
global UnoSkipTimer UnPlayedRounds UnoStopAfter UnoNickColor UnoLogo
if {!$UnoOn} {return}
if {![llength $RoundRobin]} {
unochanmsg "no players, next game in \00314[UnoDuration $UnoCycleTime]"
incr UnPlayedRounds
if {($UnoStopAfter > 0)&&($UnPlayedRounds >= $UnoStopAfter)} {
unochanmsg "idle $UnoStopAfter rounds"
utimer 1 "UnoStop $UnoRobot $UnoRobot none $UnoChan none"
return
}
UnoCycle
return
}
# bot joins if one player
if {[llength $RoundRobin] == 1} {
UnoBotPlayerJoins
}
unomsg "Welcome to $UnoLogo"
unomsg "\00314$UnoPlayers\003 players this round:\00314 $RoundRobin"
set UnoMode 2
set ThisPlayer [lindex $RoundRobin 0]
# draw first card from deck
set DiscardPile ""
set pcardnum [rand [llength $UnoDeck]]
set pcard [lindex $UnoDeck $pcardnum]
# play doesnt start with a wild card
while {[string range $pcard 0 0] == "W"} {
set pcardnum [rand [llength $UnoDeck]]
set pcard [lindex $UnoDeck $pcardnum]
}
# put first card on top of discard pile
uno_addtodiscardpile $pcard
set Card [uno_cardcolor $pcard]
set UnoDeck [lreplace $UnoDeck $pcardnum $pcardnum]
# first player draws two if first card is a draw two, but not skipped
unomsg "[unonik $ThisPlayer]\003 plays first... The top card is $Card"
if {([string range $pcard 0 0] != "W")&&([string range $pcard 1 1] == "D")} {
uno_adddrawtohand $ThisPlayer $ThisPlayerIDX 2
unomsg "[unonik $ThisPlayer]\003 \002drew two\002 cards"
}
uno_showcards $ThisPlayer $ThisPlayerIDX
# start autoskip timer
set UnoSkipTimer [timer $AutoSkipPeriod UnoAutoSkip]
set UnPlayedRounds 0
# running game time
set UnoStartTime [unixtime]
}
#
# deal full hand of 7 cards
#
proc uno_newplayerhand {cplayer} {
global UnoDeck UnoHand
# shuffle deck if needed
UnoShuffle 7
# deal cards to player
set picknum 0
while {[llength $UnoHand($cplayer)] != 7} {
set pick [lindex $UnoDeck $picknum]
lappend UnoHand($cplayer) $pick
set UnoDeck [lreplace $UnoDeck $picknum $picknum]
}
}
#
# add a player
#
proc UnoJoin {nick uhost hand chan txt} {
global UnoDebug UnoIDX UnoMode UnoPlayers RoundRobin UnoHand UnoNickColor UnoMaxPlayers UnoDCCIDX UnoLogo UnoJoinAnyTime
global UnoUseDCC
if {(![uno_ischan $chan])||($UnoMode < 1)||($UnoMode > 2)} {return}
if {!$UnoJoinAnyTime && ($UnoMode == 2)} {return}
# player is already joined
set pcount 0
while {[lindex $RoundRobin $pcount] != ""} {
if {[lindex $RoundRobin $pcount] == $nick} {
return
}
incr pcount
}
if {[llength $RoundRobin] >= $UnoMaxPlayers} {
unogntc $nick "$UnoLogo maximum of $UnoMaxPlayers players reached... try next round, $nick"
return
}
incr UnoPlayers
lappend RoundRobin $nick
lappend UnoIDX $nick
if [info exist UnoHand($nick)] {unset UnoHand($nick)}
if [info exist UnoNickColor($nick)] {unset UnoNickColor($nick)}
if [info exist UnoDCCIDX($nick)] {unset UnoDCCIDX($nick)}
set UnoHand($nick) ""
set UnoNickColor($nick) [unocolornick $UnoPlayers]
# if player is in dcc chat, use that socket for card output (fast)
set UnoDCCIDX($nick) -1
if {$UnoUseDCC} {
set dhand [nick2hand $nick $chan]
if {($dhand != "")&&($dhand != "*")} {
set idx [hand2idx $dhand]
if {$idx != -1} {
set UnoDCCIDX($nick) $idx
} {
set UnoDCCIDX($nick) -1
}
}
}
# deal hand
uno_newplayerhand $nick
#if {$UnoDebug > 1} { unolog $nick $UnoHand($nick) }
unomsg "[unonik $nick]\003 joins $UnoLogo"
unontc $nick "[uno_cardcolorall $nick]"
}
#
# card handling
#
# remove played card from hand
proc uno_removecardfromhand {cplayer ccard} {
global UnoHand
set UnoHand($cplayer) [lreplace $UnoHand($cplayer) $ccard $ccard]
}
# add card to discard pile
proc uno_addtodiscardpile {ccard} {
global DiscardPile PlayCard
set PlayCard $ccard
if {[string range $ccard 0 0] != ""} { lappend DiscardPile $ccard }
}
# add num drawn cards to hand
proc uno_adddrawtohand {cplayer idx num} {
global UnoHand UnoDeck RoundRobin
# check if deck needs reshuffling
UnoShuffle $num
set newhand [expr [llength $UnoHand($cplayer)] + $num]
set Drawn ""
set pcardnum 0
while {[llength $UnoHand($cplayer)] != $newhand} {
set pcard [lindex $UnoDeck $pcardnum]
set UnoDeck [lreplace $UnoDeck $pcardnum $pcardnum]
lappend UnoHand($cplayer) $pcard
append Drawn [uno_cardcolor $pcard]
}
uno_showdraw $idx $Drawn
}
# reset isdraw flag
proc uno_isdrawreset {} {
global IsDraw
set IsDraw 0
}
#
# player with no cards left wins
#
proc uno_checkwin {cplayer crd} {
global UnoHand
if {[llength $UnoHand($cplayer)]} {return 0}
uno_showwin $cplayer $crd
UnoWin $cplayer
UnoCycle
return 1
}
# win on a draw card
proc uno_checkwindraw {cplayer crd dplayer dplayeridx num} {
global UnoHand
if {[llength $UnoHand($cplayer)]} {return 0}
uno_adddrawtohand $dplayer $dplayeridx $num
uno_showwin $cplayer $crd
UnoWin $cplayer
UnoCycle
return 1
}
#
# check for wdf card in hand
#
proc uno_checkhandwdf {cplayer} {
global UnoHand
set ccount 0
while {$ccount < [llength $UnoHand($cplayer)]} {
set pcard [lindex $UnoHand($cplayer) $ccount]
set hc0 [string range $pcard 0 0]
set hc1 [string range $pcard 1 1]
if {($hc0 == "W") && ($hc1 == "D")} { return 1 }
incr ccount
}
return 0
}
#
# check if player has same color card in hand for wdf
#
proc uno_checkhandcolor {cplayer} {
global PlayCard UnoHand
# color of card in play
set cip0 [string range $PlayCard 0 0]
set ccount 0
while {$ccount < [llength $UnoHand($cplayer)]} {
set pcard [lindex $UnoHand($cplayer) $ccount]
set hc0 [string range $pcard 0 0]
if {([uno_iscolorcard $cip0]) && ($cip0 == $hc0)} {return 1}
incr ccount
}
return 0
}
#
# draw a card
#
proc UnoDraw {nick uhost hand chan txt} {
global UnoMode IsDraw ThisPlayer ThisPlayerIDX
if {(![uno_ischan $chan])||($UnoMode != 2)||($nick != $ThisPlayer)} {return}
uno_autoskipreset $nick
if {$IsDraw} {
unontc $nick "You've already drawn a card, $nick, play a card or pass"
return
}
if {[uno_checkhandwdf $ThisPlayer]} {
unontc $nick "You have a playable card in your hand already, $nick, you must play it"
return
}
set IsDraw 1
uno_adddrawtohand $ThisPlayer $ThisPlayerIDX 1
uno_showwhodrew $nick
return
}
#
# pass a turn
#
proc UnoPass {nick uhost hand chan txt} {
global UnoMode IsDraw ThisPlayer ThisPlayerIDX IsColorChange
if {(![uno_ischan $chan])||($UnoMode != 2)||($nick != $ThisPlayer)||($IsColorChange == 1)} {return}
uno_autoskipreset $nick
if {$IsDraw} {
uno_isdrawreset
uno_nextplayer
uno_showplaypass $nick $ThisPlayer
uno_showcards $ThisPlayer $ThisPlayerIDX
uno_restartbotplayer
} {
unontc $nick "You must draw a card before you can pass, $nick"
}
return
}
#
# color change
#
proc UnoColorChange {nick uhost hand chan txt} {
global UnoMode PlayCard ColorPicker IsColorChange ThisPlayer ThisPlayerIDX
global UnoRedCard UnoGreenCard UnoBlueCard UnoYellowCard
#if {(![uno_ischan $chan])||($UnoMode != 2)||($nick != $ColorPicker)||(!$IsColorChange)} {return}
if {($UnoMode != 2)||($nick != $ColorPicker)||(!$IsColorChange)} {return}
uno_autoskipreset $nick
regsub -all \[`.,!{}\ ] $txt "" txt
set NewColor [string toupper [string range $txt 0 0]]
switch $NewColor {
"R" { set PlayCard "R"; set Card "$UnoRedCard\003"}
"G" { set PlayCard "G"; set Card "$UnoGreenCard\003"}
"B" { set PlayCard "B"; set Card "$UnoBlueCard\003"}
"Y" { set PlayCard "Y"; set Card "$UnoYellowCard\003"}
default { unontc $nick "choose a valid color \(r,g,b or y\)"; return }
}
uno_nextplayer
unomsg "[unonik $ColorPicker]\003 chose $Card, play continues with [unonik $ThisPlayer]"
uno_showcards $ThisPlayer $ThisPlayerIDX
uno_isdrawreset
set IsColorChange 0
set ColorPicker ""
uno_restartbotplayer
return
}
#
# skip card
#
proc uno_playskipcard {nick pickednum crd} {
global ThisPlayer ThisPlayerIDX RoundRobin
uno_removecardfromhand $nick $pickednum
uno_addtodiscardpile $crd
set SkipPlayer $ThisPlayer
uno_nextplayer
set SkippedPlayer [lindex $RoundRobin $ThisPlayerIDX]
uno_nextplayer
if {[uno_checkwin $SkipPlayer [uno_cardcolor $crd]]} { return }
uno_showplayskip $nick [uno_cardcolor $crd] $SkippedPlayer $ThisPlayer
uno_checkuno $SkipPlayer
uno_showcards $ThisPlayer $ThisPlayerIDX
uno_isdrawreset
}
#
# reverse card
#
proc uno_playreversecard {nick pickednum crd} {
global UnoIDX ThisPlayer ThisPlayerIDX RoundRobin
uno_removecardfromhand $nick $pickednum
uno_addtodiscardpile $crd
# reverse roundrobin and move to next player
set NewRoundRobin ""
set OrigOrderLength [llength $RoundRobin]
set IDX $OrigOrderLength
while {$OrigOrderLength != [llength $NewRoundRobin]} {
set IDX [expr ($IDX - 1)]
lappend NewRoundRobin [lindex $RoundRobin $IDX]
}
set Newindexorder ""
set OrigindexLength [llength $UnoIDX]
set IDX $OrigindexLength
while {$OrigindexLength != [llength $Newindexorder]} {
set IDX [expr ($IDX - 1)]
lappend Newindexorder [lindex $UnoIDX $IDX]
}
set UnoIDX $Newindexorder
set RoundRobin $NewRoundRobin
set ReversePlayer $ThisPlayer
# next player after reversing roundrobin
set pcount 0
while {$pcount != [llength $RoundRobin]} {
if {[lindex $RoundRobin $pcount] == $ThisPlayer} {
set ThisPlayerIDX $pcount
break
}
incr pcount
}
# less than 3 players acts like a skip card
if {[llength $RoundRobin] > 2} {
incr ThisPlayerIDX
if {$ThisPlayerIDX >= [llength $RoundRobin]} {set ThisPlayerIDX 0}
}
set ThisPlayer [lindex $RoundRobin $ThisPlayerIDX]
if {[uno_checkwin $ReversePlayer [uno_cardcolor $crd]]} { return }
uno_showplaycard $nick [uno_cardcolor $crd] $ThisPlayer
uno_checkuno $ReversePlayer
uno_showcards $ThisPlayer $ThisPlayerIDX
uno_isdrawreset
}
#
# draw two card
#
proc uno_playdrawtwocard {nick pickednum crd} {
global ThisPlayer ThisPlayerIDX RoundRobin
uno_removecardfromhand $nick $pickednum
uno_addtodiscardpile $crd
set DrawPlayer $ThisPlayer
set DrawPlayerIDX $ThisPlayerIDX
# move to the player that draws
uno_nextplayer
set PlayerThatDrew $ThisPlayer
set PlayerThatDrewIDX $ThisPlayerIDX
# move to the player skipped to
uno_nextplayer
if {[uno_checkwindraw $nick [uno_cardcolor $crd] $PlayerThatDrew $PlayerThatDrewIDX 2]} { return }
uno_showplaydraw $nick [uno_cardcolor $crd] $PlayerThatDrew $ThisPlayer
uno_adddrawtohand $PlayerThatDrew $PlayerThatDrewIDX 2
uno_checkuno $nick
uno_showcards $ThisPlayer $ThisPlayerIDX
uno_isdrawreset
}
#
# wild draw four card
#
proc uno_playwilddrawfourcard {nick pickednum crd isrobot} {
global ThisPlayer ThisPlayerIDX RoundRobin IsColorChange ColorPicker
set ColorPicker $ThisPlayer
uno_removecardfromhand $nick $pickednum
uno_addtodiscardpile $crd
# move to the player that draws
uno_nextplayer
set PlayerThatDrew $ThisPlayer
set PlayerThatDrewIDX $ThisPlayerIDX
# bot chooses a color
if {$isrobot > 0} {
set cip [uno_botpickcolor]
uno_nextplayer
}
if {[uno_checkwindraw $nick [uno_cardcolor $crd] $PlayerThatDrew $PlayerThatDrewIDX 4]} { return }
if {$isrobot} {
uno_showbotplaywildfour $ColorPicker $PlayerThatDrew $ColorPicker $cip $ThisPlayer
set ColorPicker ""
set IsColorChange 0
uno_showcards $ThisPlayer $ThisPlayerIDX
} {
uno_showplaywildfour $nick $PlayerThatDrew $ColorPicker
set IsColorChange 1
}
uno_adddrawtohand $PlayerThatDrew $PlayerThatDrewIDX 4
uno_checkuno $nick
uno_isdrawreset
}
#
# wild card
#
proc uno_playwildcard {nick pickednum crd isrobot} {
global ThisPlayer ThisPlayerIDX RoundRobin IsColorChange ColorPicker
set ColorPicker $ThisPlayer
uno_removecardfromhand $nick $pickednum
uno_addtodiscardpile $crd
if {$isrobot} {
# make a color choice
set cip [uno_botpickcolor]
uno_nextplayer
}
# no cards remaining = winner
if {[uno_checkwin $nick [uno_cardcolor $crd]]} { return }
if {$isrobot} {
uno_showbotplaywild $nick $ColorPicker $cip $ThisPlayer
set ColorPicker ""
uno_showcards $ThisPlayer $ThisPlayerIDX
set IsColorChange 0
} {
uno_showplaywild $nick $ColorPicker
set IsColorChange 1
}
uno_checkuno $nick
uno_isdrawreset
}
#
# number card
#
proc uno_playnumbercard {nick pickednum crd} {
global ThisPlayer ThisPlayerIDX RoundRobin
uno_removecardfromhand $nick $pickednum
uno_addtodiscardpile $crd
set NumberCardPlayer $ThisPlayer
uno_nextplayer
if {[uno_checkwin $NumberCardPlayer [uno_cardcolor $crd]]} { return }
uno_showplaycard $nick [uno_cardcolor $crd] $ThisPlayer
uno_checkuno $NumberCardPlayer
uno_showcards $ThisPlayer $ThisPlayerIDX
uno_isdrawreset
}
#
# attempt to find card in hand
#
proc uno_findcard {nick pickednum crd} {
global UnoRobot ThisPlayer ThisPlayerIDX PlayCard UnoWildDrawTwos UnoWDFAnyTime
#if {$UnoDebug > 1} {unolog $UnoRobot "uno_findcard: [lindex $UnoHand($ThisPlayer) $pickednum"}
# card in hand
set c0 [string range $crd 0 0]
set c1 [string range $crd 1 1]
# card in play
set cip0 [string range $PlayCard 0 0]
set cip1 [string range $PlayCard 1 1]
# skip
if {$c1 == "S"} {
if {($c0 == $cip0)||($c1 == $cip1)} { return 1 }
return 0
}
# reverse
if {$c1 == "R"} {
if {($c0 == $cip0)||($c1 == $cip1)} { return 2 }
return 0
}
# wild draw four
if {($c0 == "W")&&($c1 == "D")} {
if {$UnoWDFAnyTime} { return 4 }
if {![uno_checkhandcolor $ThisPlayer]} { return 4 }
return 7
}
# wild
if {$c0 == "W"} { return 5 }
# draw two
if {$c1 == "D"} {
set CardOk 0
if {$c0 == $cip0} {set CardOk 1}
if {$UnoWildDrawTwos != 0} {
if {($cip0 != "W")&&($cip1 == "D")} {set CardOk 1}
if {$cip1 != ""} {set CardOk 1}
} {
if {($cip0 != "W")&&($cip1 == "D")} {set CardOk 1}
}
if {$CardOk} {
return 3
}
return 0
}
# number card
if {($c1 == -1)} {return 0}
if {($c0 == $cip0)||(($cip1 != "")&&($c1 == $cip1))} { return 6 }
return 0
}
#
# play the picked card
#
# cardfound is set by uno_findcard, which returns a card type as follows:
#
# 0 invalid card
# 1 skip card
# 2 reverse card
# 3 draw-two card
# 4 draw-four card
# 5 wild card
# 6 number card
# 7 illegal card
#
proc uno_playactualcard {nick cardfound pickednum crd isrobot} {
global CardStats
switch $cardfound {
0 {
if {$isrobot} {
unolog $nick "UnoRobot: oops $crd"
} {
unontc $nick "Oops! Not a valid card... draw or play another"
}
}
1 {
uno_playskipcard $nick $pickednum $crd
incr CardStats(played)
uno_restartbotplayer
}
2 {
uno_playreversecard $nick $pickednum $crd
incr CardStats(played)
uno_restartbotplayer
}
3 {
uno_playdrawtwocard $nick $pickednum $crd
incr CardStats(played)
uno_restartbotplayer
}
4 {
uno_playwilddrawfourcard $nick $pickednum $crd $isrobot
incr CardStats(played)
if {$isrobot} { uno_restartbotplayer }
}
5 {
uno_playwildcard $nick $pickednum $crd $isrobot
incr CardStats(played)
}
6 {
uno_playnumbercard $nick $pickednum $crd
incr CardStats(played)
if {!$isrobot} { uno_restartbotplayer }
}
7 {
if {$isrobot} {
unolog $nick "UnoRobot: oops valid card in-hand"; return
uno_restartbotplayer
} {
unontc $nick "You have a valid color card in-hand, $nick, you must play it first"; return
}
}
}
}
#
# attempt to play a card
#
proc UnoPlayCard {nick uhost hand chan txt} {
global UnoMode IsColorChange UnoHand ThisPlayer
if {(![uno_ischan $chan])||($UnoMode != 2)||($nick != $ThisPlayer)||($IsColorChange == 1)} {return}
uno_autoskipreset $nick
regsub -all \[`,.!{}\ ] $txt "" txt
if {$txt == ""} {return}
set pcard [string toupper [string range $txt 0 1]]
set CardInHand 0
set pcount 0
while {[lindex $UnoHand($nick) $pcount] != ""} {
if {$pcard == [lindex $UnoHand($nick) $pcount]} {
set pcardnum $pcount
uno_playactualcard $nick [uno_findcard $nick $pcardnum $pcard] $pcardnum $pcard 0
return
}
incr pcount
}
unontc $nick "You don't have that card $nick, draw or play another"
return
}
#
# robot player
#
# robot tries to find card from hand
proc uno_botplayertrycard {} {
global PlayCard UnoHand ThisPlayer
# card in play
set cip0 [string range $PlayCard 0 0]
set cip1 [string range $PlayCard 1 1]
set colorcardinplay [uno_iscolorcard $cip0]
set Tier 0
set TierMax 8
# Tier is the order in which the bot player chooses cards:
# 0 draw two
# 1 skip
# 2 reverse
# skip or reverse on same color
# color or number match
# draw four
# wild
while {$Tier < $TierMax} {
set CardCount 0
while {$CardCount < [llength $UnoHand($ThisPlayer)]} {
set pcard [lindex $UnoHand($ThisPlayer) $CardCount]
# card in hand
set hc0 [string range $pcard 0 0]
set hc1 [string range $pcard 1 1]
set colorcardinhand [uno_iscolorcard $hc0]
switch $Tier {
0 {if {($colorcardinplay)&&($hc0 == $cip0)&&($hc1 == "D")} {return $CardCount}}
1 {if {($colorcardinplay)&&($cip1 == "D")&&($colorcardinhand)&&($hc1 == "D")} {return $CardCount}}
2 {if {($cip1 == "S")&&($hc1 == "S")} {return $CardCount}}
3 {if {($cip1 == "R")&&($hc1 == "R")} {return $CardCount}}
4 {if {($hc0 == $cip0)&&(($hc1 == "S")||($hc1 == "R"))} {return $CardCount}}
5 {if {($hc0 == $cip0)||(($hc1 != "D")&&($hc1 == $cip1))} {return $CardCount}}
6 {if {($hc0 == "W")&&($hc1 == "D")} {return $CardCount}}
7 {if {($hc0 == "W")} {return $CardCount}}
}
incr CardCount
}
incr Tier
}
return -1;
}
proc UnoRobotPlayer {} {
global UnoDeck UnoHand ThisPlayer ThisPlayerIDX UnoRobot
set CardOk -1
uno_isdrawreset
set UnoHand($ThisPlayer) [uno_sorthand $UnoHand($ThisPlayer)]
# look for card in hand
set CardOk [uno_botplayertrycard]
# play card if found
if {$CardOk > -1} {
set pcard [lindex $UnoHand($ThisPlayer) $CardOk]
uno_playactualcard $UnoRobot [uno_findcard $UnoRobot $CardOk $pcard] $CardOk $pcard 1
return
}
# bot draws a card
UnoShuffle 1
set dcardnum 0
set dcard [lindex $UnoDeck $dcardnum]
lappend UnoHand($ThisPlayer) $dcard
set UnoDeck [lreplace $UnoDeck $dcardnum $dcardnum]
uno_showwhodrew $UnoRobot
set UnoHand($ThisPlayer) [uno_sorthand $UnoHand($ThisPlayer)]
# look for card in hand
set CardOk [uno_botplayertrycard]
# bot plays drawn card or passes turn
if {$CardOk > -1} {
set pcard [lindex $UnoHand($ThisPlayer) $CardOk]
uno_playactualcard $UnoRobot [uno_findcard $UnoRobot $CardOk $pcard] $CardOk $pcard 1
} {
uno_isdrawreset
uno_nextplayer
uno_showplaypass $UnoRobot $ThisPlayer
uno_showcards $ThisPlayer $ThisPlayerIDX
}
return
}
#
# autoskip inactive players
#
proc UnoAutoSkip {} {
global UnoMode ThisPlayer ThisPlayerIDX RoundRobin AutoSkipPeriod IsColorChange ColorPicker
global UnoIDX UnoPlayers UnoDeck UnoHand UnoChan UnoSkipTimer UnoDebug UnoNickColor UnoPaused UnoDCCIDX UnoLastIdler
global botnick
if {($UnoMode != 2)||($UnoPaused != 0)} {return}
set Idler $ThisPlayer
set IdlerIDX $ThisPlayerIDX
if {[uno_isrobot $ThisPlayerIDX]} {unolog "uno" "oops: Autoskip called while bot players turn"; return}
if {[uno_timerexists UnoAutoSkip] != ""} {
unolog "uno" "oops: Autoskip timer called, but already exists"
return
}
set InChannel 0
set uclist [chanlist $UnoChan]
set pcount 0
while {[lindex $uclist $pcount] != ""} {
if {[lindex $uclist $pcount] == $Idler} {
set InChannel 1
break
}
incr pcount
}
if {!$InChannel || ($Idler == $UnoLastIdler)} {
if {!$InChannel} {
unomsg "[unonik $Idler]\003 left the channel and is removed from Uno"
} {
unomsg "[unonik $Idler]\003 has been idle twice in a row and is removed from Uno"
set UnoLastIdler ""
}
if {$IsColorChange == 1} {
if {$Idler == $ColorPicker} {
# Make A Color Choice
set cip [uno_pickcolor]
unomsg "\0030,13 $Idler \003was picking a color : randomly selecting $cip"
set IsColorChange 0
} {
unolog "uno" "oops: UnoAutoRemove color change set but $Idler not color picker"
}
}
uno_nextplayer
unomsg "[unonik $Idler]\003 was the current player, continuing with [unonik $ThisPlayer]"
uno_showcards $ThisPlayer $ThisPlayerIDX
set UnoPlayers [expr ($UnoPlayers -1)]
# remove player from game and put cards back in deck
if {$UnoPlayers > 1} {
set RoundRobin [lreplace $RoundRobin $IdlerIDX $IdlerIDX]
set UnoIDX [lreplace $UnoIDX $IdlerIDX $IdlerIDX]
while {[llength $UnoHand($Idler)] > 0} {
set pcard [lindex $UnoHand($Idler) 0]
set UnoHand($Idler) [lreplace $UnoHand($Idler) 0 0]
lappend UnoDeck $pcard
}
if [info exist UnoHand($Idler)] {unset UnoHand($Idler)}
if [info exist UnoNickColor($Idler)] {unset UnoNickColor($Idler)}
if [info exist UnoDCCIDX($Idler)] {unset UnoDCCIDX($Idler)}
}
switch $UnoPlayers {
1 {
uno_showwindefault $ThisPlayer
UnoWin $ThisPlayer
UnoCycle
}
0 {
unochanmsg "\00306no players, no winner... cycling"
UnoCycle
}
default {
if {![uno_isrobot $ThisPlayerIDX]} {
uno_autoskipreset $botnick
uno_restartbotplayer
}
}
}
return
}
if {$UnoDebug > 0} {unolog "uno" "AutoSkip Player: $Idler"}
unomsg "[unonik $Idler]\003 idle for \00313$AutoSkipPeriod \003minutes and is skipped"
set UnoLastIdler $Idler
# player was color picker
if {$IsColorChange == 1} {
if {$Idler == $ColorPicker} {
# Make A Color Choice
set cip [uno_pickcolor]
unomsg "[unonik $Idler]\003 was picking a color : randomly selecting $cip"
set IsColorChange 0
} {
unolog "uno" "UnoRemove: IsColorChange set but $Idler not ColorPicker"
}
}
uno_nextplayer
unomsg "[unonik $Idler]\003 was the current player, continuing with [unonik $ThisPlayer]"
uno_showcards $ThisPlayer $ThisPlayerIDX
if {[uno_isrobot $ThisPlayerIDX]} {
uno_restartbotplayer
}
uno_autoskipreset $botnick
return
}
#
# pause play
#
proc UnoPause {nick uhost hand chan txt} {
global UnoChan UnoOpFlags UnoPaused
if {![uno_isrunning $chan]} {return}
if {([validuser $nick])&&([matchattr $nick $UnoOpFlags $UnoChan])} {
if {!$UnoPaused} {
set UnoPaused 1
UnoUnbindCmds
unochanmsg "\00304 paused \003by $nick"
} {
set UnoPaused 0
UnoBindCmds
uno_autoskipreset $nick
unochanmsg "\00303 resumed \003by $nick"
}
}
}
#
# remove user from play
#
proc UnoRemove {nick uhost hand chan txt} {
global UnoChan UnoCycleTime UnoIDX UnoPlayers ThisPlayer ThisPlayerIDX RoundRobin UnoDeck DiscardPile UnoHand IsColorChange ColorPicker UnoNickColor UnoOpFlags UnoDCCIDX
if {![uno_isrunning $chan]} {return}
regsub -all \[`,.!{}] $txt "" txt
# allow ops to remove another player
set UnoOpRemove 0
if {[string length $txt] > 0} {
if {([validuser $nick])&&([matchattr $nick $UnoOpFlags $UnoChan])} {
set UnoOpRemove 1
set UnoOpNick $nick
set nick $txt
} {
return
}
}
# remove player if found - put cards back to bottom of deck
set pcount 0
set PlayerFound 0
while {[lindex $RoundRobin $pcount] != ""} {
if {[string tolower [lindex $RoundRobin $pcount]] == [string tolower $nick]} {
set PlayerFound 1
set FoundIDX $pcount
set nick [lindex $RoundRobin $pcount]
break
}
incr pcount
}
if {!$PlayerFound} {return}
if {$UnoOpRemove > 0} {
unomsg "[unonik $nick]\003 was removed from uno by $UnoOpNick"
} {
unontc $nick "You are now removed from the current uno game."
unomsg "[unonik $nick]\003 left Uno"
}
# player was color picker
if {$IsColorChange == 1} {
if {$nick == $ColorPicker} {
# Make A Color Choice
set cip [uno_pickcolor]
unomsg "[unonik $nick]\003 was choosing a color... I randomly select $cip"
set IsColorChange 0
} {
unolog "uno" "UnoRemove: IsColorChange set but $nick not ColorPicker"
}
}
if {$nick == $ThisPlayer} {
uno_nextplayer
if {$UnoPlayers > 2} {
unomsg "[unonik $nick]\003 was the current player, continuing with [unonik $ThisPlayer]"
}
uno_autoskipreset $nick
}
set UnoPlayers [expr ($UnoPlayers -1)]
# remove player from game and put cards back in deck
if {$UnoPlayers > 1} {
set RoundRobin [lreplace $RoundRobin $FoundIDX $FoundIDX]
set UnoIDX [lreplace $UnoIDX $FoundIDX $FoundIDX]
while {[llength $UnoHand($nick)] > 0} {
set pcard [lindex $UnoHand($nick) 0]
set UnoHand($nick) [lreplace $UnoHand($nick) 0 0]
lappend DiscardPile $pcard
}
if [info exist UnoHand($nick)] {unset UnoHand($nick)}
if [info exist UnoNickColor($nick)] {unset UnoNickColor($nick)}
if [info exist UnoDCCIDX($nick)] {unset UnoDCCIDX($nick)}
}
set pcount 0
while {[lindex $RoundRobin $pcount] != ""} {
if {[lindex $RoundRobin $pcount] == $ThisPlayer} {
set ThisPlayerIDX $pcount
break
}
incr pcount
}
if {$UnoPlayers == 1} {
uno_showwindefault $ThisPlayer
UnoWin $ThisPlayer
UnoCycle
return
}
uno_restartbotplayer
if {!$UnoPlayers} {
unochanmsg "no players, no winner... recycling"
UnoCycle
}
return
}
#
# move to next player
#
proc uno_nextplayer {} {
global ThisPlayer ThisPlayerIDX RoundRobin
incr ThisPlayerIDX
if {$ThisPlayerIDX >= [llength $RoundRobin]} {set ThisPlayerIDX 0}
set ThisPlayer [lindex $RoundRobin $ThisPlayerIDX]
}
#
# set global PlayCard to chosen color and return colored card
#
proc uno_getcolorcard {crd} {
global PlayCard UnoRedCard UnoGreenCard UnoBlueCard UnoYellowCard
set pcol [string range $crd 0 0]
switch $pcol {
"R" {set PlayCard "R"; return "$UnoRedCard\003" }
"G" {set PlayCard "G"; return "$UnoGreenCard\003" }
"B" {set PlayCard "B"; return "$UnoBlueCard\003" }
"Y" {set PlayCard "Y"; return "$UnoYellowCard\003" }
}
}
#
# returns 1 if color card, 0 if not
#
proc uno_iscolorcard {c} {
switch $c {
"R" {return 1}
"G" {return 1}
"B" {return 1}
"Y" {return 1}
}
return 0
}
#
# pick a random color for skipped/removed players
#
proc uno_pickcolor {} {
set ucolors "R G B Y"
set pcol [lindex $ucolors [rand [llength $ucolors]]]
return [uno_getcolorcard $pcol]
}
#
# robot player picks a color by checking hand for 1st color card
# found with matching color, else it picks a color at random
#
proc uno_botpickcolor {} {
global UnoHand ThisPlayer ColorPicker
set hlen [llength $UnoHand($ColorPicker)]
# draw two
set CardCount 0
while {$CardCount < $hlen} {
set thiscolor [string range [lindex $UnoHand($ColorPicker) $CardCount] 0 0]
set thiscard [string range [lindex $UnoHand($ColorPicker) $CardCount] 1 1]
if {([uno_iscolorcard $thiscolor])&&($thiscard == "D")} { return [uno_getcolorcard $thiscolor] }
incr CardCount
}
# skip/reverse
set CardCount 0
while {$CardCount < $hlen} {
set thiscolor [string range [lindex $UnoHand($ColorPicker) $CardCount] 0 0]
set thiscard [string range [lindex $UnoHand($ColorPicker) $CardCount] 1 1]
if {([uno_iscolorcard $thiscolor])&&(($thiscard == "S")||($thiscard == "R"))} { return [uno_getcolorcard $thiscolor] }
incr CardCount
}
# number card
set CardCount 0
while {$CardCount < $hlen} {
set thiscolor [string range [lindex $UnoHand($ColorPicker) $CardCount] 0 0]
if {[uno_iscolorcard $thiscolor]} { return [uno_getcolorcard $thiscolor] }
incr CardCount
}
# wild or wdf remain, pick color at random
return [uno_pickcolor]
}
#
# timers
#
# set robot for next turn
proc uno_restartbotplayer {} {
global UnoMode ThisPlayerIDX RobotRestartPeriod UnoBotTimer
if {$UnoMode != 2} {return}
if {![uno_isrobot $ThisPlayerIDX]} {return}
set UnoBotTimer [utimer $RobotRestartPeriod UnoRobotPlayer]
}
# reset autoskip timer
proc uno_autoskipreset {nick} {
global AutoSkipPeriod UnoMode UnoSkipTimer UnoLastIdler
catch {killtimer $UnoSkipTimer}
if {$nick == $UnoLastIdler} { set UnoLastIdler "" }
if {$UnoMode == 2} { set UnoSkipTimer [timer $AutoSkipPeriod UnoAutoSkip] }
}
#
# channel triggers
#
# game help
proc UnoCmds {nick uhost hand chan txt} {
global UnoLogo
if {![uno_ischan $chan]} {return}
unogntc $nick "$UnoLogo Commands: !uno !stop !remove \[nick\] !unowon \[nick\] !unocmds"
unogntc $nick "$UnoLogo Stats: !unotop10 \[games\|wins\|21\] !unotop3last !unostats !unorecords"
unogntc $nick "$UnoLogo Card Commands: jo=join pl=play dr=draw pa=pass co=color"
unogntc $nick "$UnoLogo Chan Commands: ca=cards cd=card tu=turn od=order ct=count st=stats ti=time"
return
}
# game version
proc UnoVersion {nick uhost hand chan txt} {
global UnoVersion
unochanmsg "$UnoVersion by #World-Chat Team \003"
return
}
# current player order
proc UnoOrder {nick uhost hand chan txt} {
global UnoPlayers RoundRobin
if {![uno_isrunning $chan]} {return}
unochanmsg "Player order: \00314$RoundRobin\003"
return
}
# game running time
proc UnoTime {nick uhost hand chan txt} {
global UnoLogo
if {![uno_isrunning $chan]} {return}
unochanmsg "Game time \00314[UnoDuration [uno_gametime]] \003"
return
}
# show player what cards in hand
proc UnoShowCards {nick uhost hand chan txt} {
global UnoHand ThisPlayerIDX
if {![uno_isrunning $chan]} {return}
if ![info exist UnoHand($nick)] { return }
set UnoHand($nick) [uno_sorthand $UnoHand($nick)]
set Card [uno_cardcolorall $nick]
if {![uno_isrobot $ThisPlayerIDX]} { unontc $nick "$Card\003" }
return
}
# show current player
proc UnoTurn {nick uhost hand chan txt} {
global ThisPlayer RoundRobin UnoMode
if {![uno_isrunning $chan]} {return}
if {[llength $RoundRobin] < 1 } {return}
unochanmsg "Current player: \00314$ThisPlayer\003"
return
}
# show current top card
proc UnoTopCard {nick uhost hand chan txt} {
global PlayCard
if {![uno_isrunning $chan]} {return}
set Card [uno_cardcolor $PlayCard]
unochanmsg "Card in play: $Card"
return
}
# card stats
proc UnoCardStats {nick uhost hand chan txt} {
global CardStats
if {![uno_isrunning $chan]} {return}
unochanmsg "Played:\00314$CardStats(played)\003"
return
}
# card count
proc UnoCardCount {nick uhost hand chan txt} {
global RoundRobin UnoHand
if {![uno_isrunning $chan]} {return}
set ordcnt 0
set crdcnt ""
while {[lindex $RoundRobin $ordcnt] != ""} {
set cp [lindex $RoundRobin $ordcnt]
set cc [llength $UnoHand($cp)]
append crdcnt "\00310 $cp \00306 $cc cards "
incr ordcnt
}
unomsg "$crdcnt\003"
return
}
# player's score
proc UnoWon {nick uhost hand chan txt} {
global UnoScoreFile UnoPointsName
if {![uno_ischan $chan]} {return}
regsub -all \[`,.!] $txt "" txt
if {![string length $txt]} {set txt $nick}
set scorer [string tolower $txt]
set pflag 0
set f [open $UnoScoreFile r]
while {[gets $f sc] != -1} {
set cnick [string tolower [lindex [split $sc] 0]]
if {$cnick == $scorer} {
set winratio [format "%4.1f" [expr [lindex $sc 2] /[lindex $sc 1]]]
set pmsg "\00306[lindex [split $sc] 0] \003 [lindex $sc 2] $UnoPointsName in [lindex $sc 1] games \($winratio p\/g\)"
set pflag 1
}
}
close $f
if {!$pflag} {
set pmsg "\00306$txt\003 no score"
}
unochanmsg "$pmsg"
return
}
# current top10 list
proc UnoTopTen {nick uhost hand chan txt} {
if {![uno_ischan $chan]} {return}
regsub -all \[`,.!{}\ ] $txt "" txt
set txt [string tolower [string range $txt 0 10]]
switch $txt {
"won" {set mode 1}
"games" {set mode 0}
"Rand" {set mode 1}
"21" {set mode 2}
"blackjack" {set mode 2}
default {set mode 1}
}
UnoTop10 $mode
return
}
# last month's top3
proc UnoTopThreeLast {nick uhost hand chan txt} {
if {![uno_ischan $chan]} {return}
UnoLastMonthTop3 $nick $uhost $hand $chan 0
UnoLastMonthTop3 $nick $uhost $hand $chan 1
return
}
# month's stats
proc UnoPlayStats {nick uhost hand chan txt} {
global UnoFast UnoHigh UnoPlayed UnoPointsName
if {![uno_ischan $chan]} {return}
unochanmsg "Current record holders"
set msg "\00306Fast:\003 [lindex [split $UnoFast] 0] \002[UnoDuration [lindex $UnoFast 1]]\002 "
append msg "\00306High:\003 [lindex [split $UnoHigh] 0] \002[lindex $UnoHigh 1]\002 $UnoPointsName "
append msg "\00306Played:\003 [lindex [split $UnoPlayed] 0] \002[lindex $UnoPlayed 1]\002 Cards"
unochanmsg "$msg"
return
}
# all-time records
proc UnoRecords {nick uhost hand chan txt} {
global UnoRecordFast UnoRecordHigh UnoRecordCard UnoRecordWins UnoRecordPlayed
if {![uno_ischan $chan]} {return}
unochanmsg "All-Time Records"
unochanmsg "\00306Points:\003 $UnoRecordCard \00306 Games:\003 $UnoRecordWins \00306 Fast:\003 [lindex $UnoRecordFast 0] [UnoDuration [lindex $UnoRecordFast 1]] \00306 High Score:\003 $UnoRecordHigh \00306 Cards Played:\003 $UnoRecordPlayed \003"
return
}
# current row (streak)
proc UnoCurrentRow {nick uhost hand chan txt} {
global UnoLastWinner UnoWinsInARow
if {![uno_ischan $chan]} {return}
if {($UnoLastWinner != "")&&($UnoWinsInARow > 0)} {
switch ($UnoWinsInARow) {
1 { unochanmsg "\0036$UnoLastWinner \003 has won \0030,6 $UnoWinsInARow game \003" }
default { unochanmsg "\0033$UnoLastWinner \003 is on a \0030,6 $UnoWinsInARow game streak \003" }
}
}
return
}
# month top10
proc UnoTop10 {mode {disp 1}} {
global UnoScoreFile unsortedscores UnoPointsName UnoRobot
if {($mode < 0)||($mode > 2)} {set mode 0}
switch $mode {
0 {set winners "Top10 Game Wins "}
1 {set winners "Top10 $UnoPointsName "}
2 {set winners "Top10 Blackjacks "}
}
if ![file exists $UnoScoreFile] {
set f [open $UnoScoreFile w]
puts $f "$UnoRobot 0 0 0"
unochanmsg "\0034Uno scores reset"
close $f
return
} {
unomsg "$winners"
set winners ""
}
if [info exists unsortedscores] {unset unsortedscores}
if [info exists top10] {unset top10}
set f [open $UnoScoreFile r]
while {[gets $f s] != -1} {
switch $mode {
0 {set unsortedscores([lindex [split $s] 0]) [lindex $s 1]}
1 {set unsortedscores([lindex [split $s] 0]) [lindex $s 2]}
2 {set unsortedscores([lindex [split $s] 0]) [lindex $s 3]}
}
}
close $f
for {set s 0} {$s < 10} {incr s} {
set top10($s) "Nobody 0"
}
set s 0
foreach n [lsort -decreasing -command uno_sortscores [array names unsortedscores]] {
set top10($s) "$n $unsortedscores($n)"
incr s
}
for {set s 0} {$s < 10} {incr s} {
if {[llength [lindex $top10($s) 0]] > 0} {
if {[lindex [split $top10($s)] 0] != "Nobody"} {
append winners "\0030,6 #[expr $s +1] \0030,10 [lindex [split $top10($s)] 0] [lindex $top10($s) 1] "
}
}
}
append winners " \003"
if {[string is true $disp]} {
unomsg $winners
}
return $winners
}
# last month's top3
proc UnoLastMonthTop3 {nick uhost hand chan txt} {
global UnoLastMonthCards UnoLastMonthGames UnoPointsName
if {![uno_ischan $chan]} {return}
if {!$txt} {
if [info exists UnoLastMonthCards] {
set UnoTop3 ""
unochanmsg "Last Month's Top 3 $UnoPointsName Winners"
for { set s 0} { $s < 3 } { incr s} {
append UnoTop3 "\0030,6 #[expr $s +1] \0030,10 $UnoLastMonthCards($s) "
}
unomsg "$UnoTop3"
}
} {
if [info exists UnoLastMonthGames] {
set UnoTop3 ""
unochanmsg "Last Month's Top 3 Game Winners"
for { set s 0} { $s < 3 } { incr s} {
append UnoTop3 "\0030,6 #[expr $s +1] \0030,10 $UnoLastMonthGames($s) "
}
unomsg "$UnoTop3"
}
}
}
#
# scores/records
#
# read score file
proc UnoReadScores {} {
global unogameswon unoptswon unoblackjackswon UnoScoreFile UnoRobot
if [info exists unogameswon] { unset unogameswon }
if [info exists unoptswon] { unset unoptswon }
if [info exists unoblackjackswon] { unset unoblackjackswon }
if ![file exists $UnoScoreFile] {
set f [open $UnoScoreFile w]
puts $f "$UnoRobot 0 0 0"
close $f
}
set f [open $UnoScoreFile r]
while {[gets $f s] != -1} {
set unogameswon([lindex [split $s] 0]) [lindex $s 1]
set unoptswon([lindex [split $s] 0]) [lindex $s 2]
set unoblackjackswon([lindex [split $s] 0]) [lindex $s 3]
}
close $f
return
}