Advertisement
Guest User

Untitled

a guest
May 26th, 2019
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 66.63 KB | None | 0 0
  1. #
  2. # Marky's Color Uno v0.98
  3. # Copyright (C) 2004-2011 Mark A. Day (techwhiz@embarqmail.com)
  4. #
  5. # Uno(tm) is Copyright (C) 2001 Mattel, Inc.
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. #
  21.  
  22. # default settings (these are overridden by uno.cfg)
  23. set UnoAds 1
  24. set UnoDebug 0
  25. set UnoChan "#Friends"
  26. set UnoRobot $botnick
  27. set UnoPointsName "Rand"
  28. set UnoStopAfter 3
  29. set UnoJoinAnyTime 0
  30. set UnoUseDCC 0
  31. set UnoBonus 1000
  32. set UnoWildDrawTwos 0
  33. set UnoWDFAnyTime 0
  34. set UnoMaxNickLen 9
  35. set UnoMaxPlayers 10
  36. set UnoOpFlags "o|o"
  37. set UnoNTC "NOTICE"
  38. set UnoCFGFile "scripts/added/uno/uno.cfg"
  39. set UnoScoreFile "UnoScores"
  40. set UnoVersion "0.98.9"
  41.  
  42. # command binds
  43. bind pub - !uno UnoInit
  44. bind pub "o|o" !stop UnoStop
  45. bind pub "o|o" !pause UnoPause
  46. bind pub "o|o" !join UnoJoinBotPlayer
  47. bind pub - !remove UnoRemove
  48. bind pub - !unocmds UnoCmds
  49. bind pub - !unowon UnoWon
  50. bind pub - !unotop10 UnoTopTen
  51. bind pub - !unotop3last UnoTopThreeLast
  52. bind pub - !unostats UnoPlayStats
  53. bind pub - !unorecords UnoRecords
  54. bind pub - !unorow UnoCurrentRow
  55. bind pub - !unoversion UnoVersion
  56.  
  57. # dcc commands
  58. bind dcc - unohands dccunohands
  59. bind dcc - unowritecfg dcc_unowriteconfig
  60. bind dcc - unorehash dcc_unorehash
  61. bind dcc - unopoints dcc_unopoints
  62.  
  63. # monthly score reset
  64. bind time - "00 00 01 * *" UnoNewMonth
  65.  
  66. # rehash
  67. bind evnt - "prerehash" unoevnt:prerehash
  68. proc unoevnt:prerehash {type} {
  69. global UnoRobot UnoChan
  70. UnoStop $UnoRobot "console" $UnoRobot $UnoChan ""
  71. }
  72. # restart
  73. bind evnt - "prerestart" unoevnt:prerestart
  74. proc unoevnt:prerestart {type} {
  75. global UnoRobot UnoChan
  76. UnoStop $UnoRobot "console" $UnoRobot $UnoChan ""
  77. }
  78.  
  79. # global variables
  80. set UnoOn 0
  81. set UnoMode 0
  82. set UnoPaused 0
  83. set UnoPlayers 0
  84. set MasterDeck ""
  85. set UnoDeck ""
  86. set DiscardPile ""
  87. set PlayCard ""
  88. set RoundRobin ""
  89. set ThisPlayer ""
  90. set ThisPlayerIDX 0
  91. set UnoStartTime [unixtime]
  92. set IsColorChange 0
  93. set ColorPicker ""
  94. set IsDraw 0
  95. set UnoIDX ""
  96. set UnPlayedRounds 0
  97. set UnoWinDefault 0
  98. set UnoLastWinner ""
  99. set UnoLastIdler ""
  100. set UnoWinsInARow 0
  101.  
  102. # card types
  103. set unocardtype_invalid 0
  104. set unocardtype_skip 1
  105. set unocardtype_reverse 2
  106. set unocardtype_draw2 3
  107. set unocardtype_draw4 4
  108. set unocardtype_wild 5
  109. set unocardtype_number 6
  110.  
  111. # scores, records and ads
  112. set UnoLastMonthCards(0) "Nobody 0"
  113. set UnoLastMonthCards(1) "Nobody 0"
  114. set UnoLastMonthCards(2) "Nobody 0"
  115. set UnoLastMonthGames(0) "Nobody 0"
  116. set UnoLastMonthGames(1) "Nobody 0"
  117. set UnoLastMonthGames(2) "Nobody 0"
  118. set UnoFast "Nobody 600"
  119. set UnoHigh "Nobody 0"
  120. set UnoPlayed "Nobody 0"
  121. set UnoRow "Nobody 0"
  122. set UnoRecordHigh "Nobody 0"
  123. set UnoRecordFast "Nobody 600"
  124. set UnoRecordCard "Nobody 0"
  125. set UnoRecordWins "Nobody 0"
  126. set UnoRecordPlayed "Nobody 0"
  127. set UnoRecordRow "Nobody 0"
  128. set UnoAdNumber 0
  129.  
  130. # card stats
  131. set CardStats(played) 0
  132.  
  133. # timers
  134. set UnoStartTimer ""
  135. set UnoSkipTimer ""
  136. set UnoCycleTimer ""
  137. set UnoBotTimer ""
  138.  
  139. #
  140. # grace periods and timeouts ( AutoSkipPeriod can be raised but dont go below 2)
  141. #
  142.  
  143. # time to skip an inactive player
  144. set AutoSkipPeriod 2
  145.  
  146. # time to join game
  147. set StartGracePeriod 30
  148.  
  149. # time between games
  150. set UnoCycleTime 30
  151.  
  152. # internal bot player use dont change
  153. set RobotRestartPeriod 1
  154.  
  155. # nick colors
  156. set UnoNickColors "6 13 3 7 12 10 4 11 9 8 5"
  157.  
  158. # cards and logo
  159. set UnoRedCard "\0030,04 Red "
  160. set UnoGreenCard "\0030,03 Green "
  161. set UnoBlueCard "\0030,12 Blue "
  162. set UnoYellowCard "\0031,08 Yellow "
  163. set UnoSkipCard "\002Skip\002 \003 "
  164. set UnoReverseCard "\002Reverse\002 \003 "
  165. set UnoDrawTwoCard "\002Draw Two\002 \003 "
  166. set UnoWildCard "\0031,8 \002W\0030,3I \0030,4L\0030,12D\002 \003 "
  167. 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 "
  168. set UnoLogo "\002\0033U\00312N\00313O\00308!\002\003"
  169.  
  170. #
  171. # bind channel commands
  172. #
  173. proc UnoBindCmds {} {
  174. bind pub - jo UnoJoin
  175. bind pub - od UnoOrder
  176. bind pub - ti UnoTime
  177. bind pub - ca UnoShowCards
  178. bind pub - pl UnoPlayCard
  179. bind pub - cd UnoTopCard
  180. bind pub - tu UnoTurn
  181. bind pub - dr UnoDraw
  182. bind pub - co UnoColorChange
  183. bind pub - pa UnoPass
  184. bind pub - ct UnoCardCount
  185. bind pub - st UnoCardStats
  186.  
  187. bind chon - * unologin:dcc
  188. bind chof - * unologout:dcc
  189. bind filt - .quit* unologout:filt
  190. }
  191.  
  192. #
  193. # unbind channel commands
  194. #
  195. proc UnoUnbindCmds {} {
  196. catch {unbind pub - jo UnoJoin}
  197. catch {unbind pub - od UnoOrder}
  198. catch {unbind pub - ti UnoTime}
  199. catch {unbind pub - ca UnoShowCards}
  200. catch {unbind pub - pl UnoPlayCard}
  201. catch {unbind pub - cd UnoTopCard}
  202. catch {unbind pub - tu UnoTurn}
  203. catch {unbind pub - dr UnoDraw}
  204. catch {unbind pub - co UnoColorChange}
  205. catch {unbind pub - pa UnoPass}
  206. catch {unbind pub - ct UnoCardCount}
  207. catch {unbind pub - st UnoCardStats}
  208.  
  209. catch {unbind chon - * unologin:dcc}
  210. catch {unbind chof - * unologout:dcc}
  211. catch {unbind filt - .quit* unologout:filt}
  212. }
  213.  
  214. #
  215. # reset game variables
  216. #
  217. proc UnoReset {} {
  218. global UnoOn UnoMode UnoPaused UnoPlayers RoundRobin UnoDeck ThisPlayer ThisPlayerIDX PlayCard
  219. global DiscardPile IsColorChange ColorPicker IsDraw UnoIDX MasterDeck CardStats
  220. global UnoStartTimer UnoSkipTimer UnoCycleTimer UnoWinDefault UnoRobot botnick UnoLastIdler
  221.  
  222. set UnoMode 0
  223. set UnoPaused 0
  224. set UnoPlayers 0
  225. set MasterDeck ""
  226. set UnoDeck ""
  227. set DiscardPile ""
  228. set RoundRobin ""
  229. set ThisPlayer ""
  230. set ThisPlayerIDX 0
  231. set PlayCard ""
  232. set IsColorChange 0
  233. set ColorPicker ""
  234. set IsDraw 0
  235. set UnoIDX ""
  236. set UnoAdNumber 0
  237. set UnoWinDefault 0
  238. set UnoLastIdler ""
  239.  
  240. set CardStats(played) 0
  241.  
  242. set UnoStartTimer ""
  243. set UnoSkipTimer ""
  244. set UnoCycleTimer ""
  245.  
  246. set UnoRobot $botnick
  247.  
  248. return
  249. }
  250.  
  251. # return 1 if is this the uno channel, else return 0
  252. proc uno_ischan {chan} {
  253. global UnoChan
  254. if {([string tolower $chan] == [string tolower $UnoChan])} {return 1}
  255. return 0
  256. }
  257. # return 1 if is this the uno channel and uno is running, else return 0
  258. proc uno_isrunning {chan} {
  259. global UnoMode
  260. if {([uno_ischan $chan])&&($UnoMode == 2)} {return 1}
  261. return 0
  262. }
  263.  
  264. # remove player dcc list
  265. proc uno_removedccplayers { } {
  266. global RoundRobin UnoDCCIDX
  267. set pcount 0
  268. while {[lindex $RoundRobin $pcount] != ""} {
  269. set pnick [lindex $RoundRobin $pcount]
  270. if [info exist UnoDCCIDX($pnick)] {unset UnoDCCIDX($pnick)}
  271. incr pcount
  272. }
  273. }
  274.  
  275. #
  276. # stop a game
  277. #
  278. proc UnoStop {nick uhost hand chan txt} {
  279. global UnoOn UnoPaused UnPlayedRounds UnoStartTimer UnoSkipTimer UnoCycleTimer UnoLastWinner UnoWinsInARow
  280.  
  281. if {(![uno_ischan $chan])||($UnoOn == 0)} {return}
  282.  
  283. catch {killutimer $UnoStartTimer}
  284. catch {killtimer $UnoSkipTimer}
  285. catch {killutimer $UnoCycleTimer}
  286.  
  287. # remove player dcc list
  288. uno_removedccplayers
  289.  
  290. set UnoOn 0
  291. set UnoPaused 0
  292. set UnPlayedRounds 0
  293. set UnoLastWinner ""
  294. set UnoWinsInARow 0
  295.  
  296. UnoUnbindCmds
  297.  
  298. UnoReset
  299.  
  300. unochanmsg "stopped by $nick"
  301.  
  302. return
  303. }
  304.  
  305. #
  306. # first entry
  307. #
  308. proc UnoInit {nick uhost hand chan txt} {
  309. global UnoOn
  310. if {(![uno_ischan $chan])||($UnoOn > 0)} {return}
  311. #unochanmsg "$nick\!$uhost"
  312. set UnoOn 1
  313. UnoBindCmds
  314. UnoNext
  315. return
  316. }
  317.  
  318. #
  319. # initialize a new game
  320. #
  321. proc UnoNext {} {
  322. global UnoOn MasterDeck UnoDeck UnoMode StartGracePeriod UnoHand UnoNickColor UnoVersion UnoStartTimer UnoSkipTimer
  323.  
  324. if {!$UnoOn} {return}
  325.  
  326. UnoReset
  327.  
  328. set UnoMode 1
  329.  
  330. 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]
  331.  
  332. unochanmsg "$UnoVersion by #World-Chat Team"
  333.  
  334. set done 0
  335. while {!$done} {
  336. set rseed [rand 65535]
  337. if {$rseed} {set done 1}
  338. }
  339. set newrand [expr srand($rseed)]
  340. set newrand [rand [llength $MasterDeck]]
  341.  
  342. set UnoDeck ""
  343. while {[llength $UnoDeck] != 108} {
  344. set pnum [rand [llength $MasterDeck]]
  345. set pcard [lindex $MasterDeck $pnum]
  346. lappend UnoDeck $pcard
  347. set MasterDeck [lreplace $MasterDeck $pnum $pnum]
  348. }
  349.  
  350. if [info exist UnoHand] {unset UnoHand}
  351. if [info exist UnoNickColor] {unset UnoNickColor}
  352.  
  353. unochanmsg "You have \00314\002[UnoDuration $StartGracePeriod]\002\003 to join uno"
  354.  
  355. set UnoStartTimer [utimer $StartGracePeriod UnoStart]
  356.  
  357. return
  358. }
  359.  
  360. #
  361. # cycle a new game
  362. #
  363. proc UnoCycle {} {
  364. global UnoOn UnoMode UnoCycleTime UnoCycleTimer UnoSkipTimer UnoAds
  365.  
  366. if {!$UnoOn} {return}
  367.  
  368. set UnoMode 4
  369. catch {killtimer $UnoSkipTimer}
  370.  
  371. if {$UnoAds} {
  372. set AdTime [expr $UnoCycleTime /2]
  373. set UnoAdTimer [utimer $AdTime UnoScoreAdvertise]
  374. }
  375.  
  376. set UnoCycleTimer [utimer $UnoCycleTime UnoNext]
  377.  
  378. return
  379. }
  380.  
  381. # force bot player to join
  382. proc UnoJoinBotPlayer {nick uhost hand chan txt} {
  383. global UnoMode UnoOn
  384. if {!$UnoOn || ($UnoMode != 2)} {return}
  385. UnoBotPlayerJoins
  386. return 0
  387. }
  388.  
  389. # bot player joins in if no one else does
  390. proc UnoBotPlayerJoins {} {
  391. global UnoPlayers RoundRobin UnoIDX UnoRobot UnoLogo UnoDebug UnoHand UnoNickColor
  392.  
  393. # prevent bot player from joining multiple times
  394. if [info exist UnoHand($UnoRobot)] { return }
  395.  
  396. incr UnoPlayers
  397.  
  398. lappend RoundRobin $UnoRobot
  399. lappend UnoIDX $UnoRobot
  400.  
  401. set UnoHand($UnoRobot) ""
  402. set UnoNickColor($UnoRobot) [unocolornick $UnoPlayers]
  403.  
  404. unomsg "[unonik $UnoRobot]\003 joins $UnoLogo"
  405.  
  406. # deal hand to bot
  407. uno_newplayerhand $UnoRobot
  408. }
  409.  
  410. #
  411. # start a new game
  412. #
  413. proc UnoStart {} {
  414. global UnoChan UnoOn UnoCycleTime UnoRobot UnoDebug UnoIDX UnoStartTime UnoPlayers RoundRobin ThisPlayer ThisPlayerIDX UnoDeck DiscardPile UnoMode UnoHand AutoSkipPeriod
  415. global UnoSkipTimer UnPlayedRounds UnoStopAfter UnoNickColor UnoLogo
  416.  
  417. if {!$UnoOn} {return}
  418.  
  419. if {![llength $RoundRobin]} {
  420. unochanmsg "no players, next game in \00314[UnoDuration $UnoCycleTime]"
  421. incr UnPlayedRounds
  422. if {($UnoStopAfter > 0)&&($UnPlayedRounds >= $UnoStopAfter)} {
  423. unochanmsg "idle $UnoStopAfter rounds"
  424. utimer 1 "UnoStop $UnoRobot $UnoRobot none $UnoChan none"
  425. return
  426. }
  427.  
  428. UnoCycle
  429.  
  430. return
  431. }
  432.  
  433. # bot joins if one player
  434. if {[llength $RoundRobin] == 1} {
  435. UnoBotPlayerJoins
  436. }
  437.  
  438. unomsg "Welcome to $UnoLogo"
  439. unomsg "\00314$UnoPlayers\003 players this round:\00314 $RoundRobin"
  440.  
  441. set UnoMode 2
  442.  
  443. set ThisPlayer [lindex $RoundRobin 0]
  444.  
  445. # draw first card from deck
  446. set DiscardPile ""
  447. set pcardnum [rand [llength $UnoDeck]]
  448. set pcard [lindex $UnoDeck $pcardnum]
  449.  
  450. # play doesnt start with a wild card
  451. while {[string range $pcard 0 0] == "W"} {
  452. set pcardnum [rand [llength $UnoDeck]]
  453. set pcard [lindex $UnoDeck $pcardnum]
  454. }
  455.  
  456. # put first card on top of discard pile
  457. uno_addtodiscardpile $pcard
  458. set Card [uno_cardcolor $pcard]
  459.  
  460. set UnoDeck [lreplace $UnoDeck $pcardnum $pcardnum]
  461.  
  462. # first player draws two if first card is a draw two, but not skipped
  463. unomsg "[unonik $ThisPlayer]\003 plays first... The top card is $Card"
  464.  
  465. if {([string range $pcard 0 0] != "W")&&([string range $pcard 1 1] == "D")} {
  466. uno_adddrawtohand $ThisPlayer $ThisPlayerIDX 2
  467. unomsg "[unonik $ThisPlayer]\003 \002drew two\002 cards"
  468. }
  469.  
  470. uno_showcards $ThisPlayer $ThisPlayerIDX
  471.  
  472. # start autoskip timer
  473. set UnoSkipTimer [timer $AutoSkipPeriod UnoAutoSkip]
  474.  
  475. set UnPlayedRounds 0
  476.  
  477. # running game time
  478. set UnoStartTime [unixtime]
  479. }
  480.  
  481. #
  482. # deal full hand of 7 cards
  483. #
  484. proc uno_newplayerhand {cplayer} {
  485. global UnoDeck UnoHand
  486. # shuffle deck if needed
  487. UnoShuffle 7
  488. # deal cards to player
  489. set picknum 0
  490. while {[llength $UnoHand($cplayer)] != 7} {
  491. set pick [lindex $UnoDeck $picknum]
  492. lappend UnoHand($cplayer) $pick
  493. set UnoDeck [lreplace $UnoDeck $picknum $picknum]
  494. }
  495. }
  496.  
  497. #
  498. # add a player
  499. #
  500. proc UnoJoin {nick uhost hand chan txt} {
  501. global UnoDebug UnoIDX UnoMode UnoPlayers RoundRobin UnoHand UnoNickColor UnoMaxPlayers UnoDCCIDX UnoLogo UnoJoinAnyTime
  502. global UnoUseDCC
  503.  
  504. if {(![uno_ischan $chan])||($UnoMode < 1)||($UnoMode > 2)} {return}
  505.  
  506. if {!$UnoJoinAnyTime && ($UnoMode == 2)} {return}
  507.  
  508. # player is already joined
  509. set pcount 0
  510. while {[lindex $RoundRobin $pcount] != ""} {
  511. if {[lindex $RoundRobin $pcount] == $nick} {
  512. return
  513. }
  514. incr pcount
  515. }
  516.  
  517. if {[llength $RoundRobin] >= $UnoMaxPlayers} {
  518. unogntc $nick "$UnoLogo maximum of $UnoMaxPlayers players reached... try next round, $nick"
  519. return
  520. }
  521.  
  522. incr UnoPlayers
  523.  
  524. lappend RoundRobin $nick
  525. lappend UnoIDX $nick
  526.  
  527. if [info exist UnoHand($nick)] {unset UnoHand($nick)}
  528. if [info exist UnoNickColor($nick)] {unset UnoNickColor($nick)}
  529. if [info exist UnoDCCIDX($nick)] {unset UnoDCCIDX($nick)}
  530.  
  531. set UnoHand($nick) ""
  532. set UnoNickColor($nick) [unocolornick $UnoPlayers]
  533.  
  534. # if player is in dcc chat, use that socket for card output (fast)
  535. set UnoDCCIDX($nick) -1
  536.  
  537. if {$UnoUseDCC} {
  538. set dhand [nick2hand $nick $chan]
  539. if {($dhand != "")&&($dhand != "*")} {
  540. set idx [hand2idx $dhand]
  541. if {$idx != -1} {
  542. set UnoDCCIDX($nick) $idx
  543. } {
  544. set UnoDCCIDX($nick) -1
  545. }
  546. }
  547. }
  548.  
  549. # deal hand
  550. uno_newplayerhand $nick
  551.  
  552. #if {$UnoDebug > 1} { unolog $nick $UnoHand($nick) }
  553.  
  554. unomsg "[unonik $nick]\003 joins $UnoLogo"
  555.  
  556. unontc $nick "[uno_cardcolorall $nick]"
  557. }
  558.  
  559. #
  560. # card handling
  561. #
  562.  
  563. # remove played card from hand
  564. proc uno_removecardfromhand {cplayer ccard} {
  565. global UnoHand
  566. set UnoHand($cplayer) [lreplace $UnoHand($cplayer) $ccard $ccard]
  567. }
  568.  
  569. # add card to discard pile
  570. proc uno_addtodiscardpile {ccard} {
  571. global DiscardPile PlayCard
  572. set PlayCard $ccard
  573. if {[string range $ccard 0 0] != ""} { lappend DiscardPile $ccard }
  574. }
  575.  
  576. # add num drawn cards to hand
  577. proc uno_adddrawtohand {cplayer idx num} {
  578. global UnoHand UnoDeck RoundRobin
  579.  
  580. # check if deck needs reshuffling
  581. UnoShuffle $num
  582.  
  583. set newhand [expr [llength $UnoHand($cplayer)] + $num]
  584.  
  585. set Drawn ""
  586. set pcardnum 0
  587. while {[llength $UnoHand($cplayer)] != $newhand} {
  588. set pcard [lindex $UnoDeck $pcardnum]
  589. set UnoDeck [lreplace $UnoDeck $pcardnum $pcardnum]
  590. lappend UnoHand($cplayer) $pcard
  591. append Drawn [uno_cardcolor $pcard]
  592. }
  593. uno_showdraw $idx $Drawn
  594. }
  595.  
  596. # reset isdraw flag
  597. proc uno_isdrawreset {} {
  598. global IsDraw
  599. set IsDraw 0
  600. }
  601.  
  602. #
  603. # player with no cards left wins
  604. #
  605.  
  606. proc uno_checkwin {cplayer crd} {
  607. global UnoHand
  608. if {[llength $UnoHand($cplayer)]} {return 0}
  609. uno_showwin $cplayer $crd
  610. UnoWin $cplayer
  611. UnoCycle
  612. return 1
  613. }
  614.  
  615. # win on a draw card
  616. proc uno_checkwindraw {cplayer crd dplayer dplayeridx num} {
  617. global UnoHand
  618. if {[llength $UnoHand($cplayer)]} {return 0}
  619. uno_adddrawtohand $dplayer $dplayeridx $num
  620. uno_showwin $cplayer $crd
  621. UnoWin $cplayer
  622. UnoCycle
  623. return 1
  624. }
  625.  
  626. #
  627. # check for wdf card in hand
  628. #
  629. proc uno_checkhandwdf {cplayer} {
  630. global UnoHand
  631. set ccount 0
  632. while {$ccount < [llength $UnoHand($cplayer)]} {
  633. set pcard [lindex $UnoHand($cplayer) $ccount]
  634. set hc0 [string range $pcard 0 0]
  635. set hc1 [string range $pcard 1 1]
  636. if {($hc0 == "W") && ($hc1 == "D")} { return 1 }
  637. incr ccount
  638. }
  639. return 0
  640. }
  641.  
  642. #
  643. # check if player has same color card in hand for wdf
  644. #
  645. proc uno_checkhandcolor {cplayer} {
  646. global PlayCard UnoHand
  647.  
  648. # color of card in play
  649. set cip0 [string range $PlayCard 0 0]
  650.  
  651. set ccount 0
  652. while {$ccount < [llength $UnoHand($cplayer)]} {
  653. set pcard [lindex $UnoHand($cplayer) $ccount]
  654. set hc0 [string range $pcard 0 0]
  655. if {([uno_iscolorcard $cip0]) && ($cip0 == $hc0)} {return 1}
  656. incr ccount
  657. }
  658. return 0
  659. }
  660.  
  661. #
  662. # draw a card
  663. #
  664. proc UnoDraw {nick uhost hand chan txt} {
  665. global UnoMode IsDraw ThisPlayer ThisPlayerIDX
  666.  
  667. if {(![uno_ischan $chan])||($UnoMode != 2)||($nick != $ThisPlayer)} {return}
  668.  
  669. uno_autoskipreset $nick
  670.  
  671. if {$IsDraw} {
  672. unontc $nick "You've already drawn a card, $nick, play a card or pass"
  673. return
  674. }
  675.  
  676. if {[uno_checkhandwdf $ThisPlayer]} {
  677. unontc $nick "You have a playable card in your hand already, $nick, you must play it"
  678. return
  679. }
  680.  
  681. set IsDraw 1
  682.  
  683. uno_adddrawtohand $ThisPlayer $ThisPlayerIDX 1
  684.  
  685. uno_showwhodrew $nick
  686.  
  687. return
  688. }
  689.  
  690. #
  691. # pass a turn
  692. #
  693. proc UnoPass {nick uhost hand chan txt} {
  694. global UnoMode IsDraw ThisPlayer ThisPlayerIDX IsColorChange
  695.  
  696. if {(![uno_ischan $chan])||($UnoMode != 2)||($nick != $ThisPlayer)||($IsColorChange == 1)} {return}
  697.  
  698. uno_autoskipreset $nick
  699.  
  700. if {$IsDraw} {
  701. uno_isdrawreset
  702.  
  703. uno_nextplayer
  704.  
  705. uno_showplaypass $nick $ThisPlayer
  706.  
  707. uno_showcards $ThisPlayer $ThisPlayerIDX
  708.  
  709. uno_restartbotplayer
  710. } {
  711. unontc $nick "You must draw a card before you can pass, $nick"
  712. }
  713.  
  714. return
  715. }
  716.  
  717. #
  718. # color change
  719. #
  720. proc UnoColorChange {nick uhost hand chan txt} {
  721. global UnoMode PlayCard ColorPicker IsColorChange ThisPlayer ThisPlayerIDX
  722. global UnoRedCard UnoGreenCard UnoBlueCard UnoYellowCard
  723.  
  724. #if {(![uno_ischan $chan])||($UnoMode != 2)||($nick != $ColorPicker)||(!$IsColorChange)} {return}
  725. if {($UnoMode != 2)||($nick != $ColorPicker)||(!$IsColorChange)} {return}
  726.  
  727. uno_autoskipreset $nick
  728.  
  729. regsub -all \[`.,!{}\ ] $txt "" txt
  730.  
  731. set NewColor [string toupper [string range $txt 0 0]]
  732.  
  733. switch $NewColor {
  734. "R" { set PlayCard "R"; set Card "$UnoRedCard\003"}
  735. "G" { set PlayCard "G"; set Card "$UnoGreenCard\003"}
  736. "B" { set PlayCard "B"; set Card "$UnoBlueCard\003"}
  737. "Y" { set PlayCard "Y"; set Card "$UnoYellowCard\003"}
  738. default { unontc $nick "choose a valid color \(r,g,b or y\)"; return }
  739. }
  740.  
  741. uno_nextplayer
  742.  
  743. unomsg "[unonik $ColorPicker]\003 chose $Card, play continues with [unonik $ThisPlayer]"
  744.  
  745. uno_showcards $ThisPlayer $ThisPlayerIDX
  746.  
  747. uno_isdrawreset
  748.  
  749. set IsColorChange 0
  750. set ColorPicker ""
  751.  
  752. uno_restartbotplayer
  753.  
  754. return
  755. }
  756.  
  757. #
  758. # skip card
  759. #
  760. proc uno_playskipcard {nick pickednum crd} {
  761. global ThisPlayer ThisPlayerIDX RoundRobin
  762.  
  763. uno_removecardfromhand $nick $pickednum
  764.  
  765. uno_addtodiscardpile $crd
  766.  
  767. set SkipPlayer $ThisPlayer
  768.  
  769. uno_nextplayer
  770.  
  771. set SkippedPlayer [lindex $RoundRobin $ThisPlayerIDX]
  772.  
  773. uno_nextplayer
  774.  
  775. if {[uno_checkwin $SkipPlayer [uno_cardcolor $crd]]} { return }
  776.  
  777. uno_showplayskip $nick [uno_cardcolor $crd] $SkippedPlayer $ThisPlayer
  778.  
  779. uno_checkuno $SkipPlayer
  780.  
  781. uno_showcards $ThisPlayer $ThisPlayerIDX
  782.  
  783. uno_isdrawreset
  784. }
  785.  
  786. #
  787. # reverse card
  788. #
  789. proc uno_playreversecard {nick pickednum crd} {
  790. global UnoIDX ThisPlayer ThisPlayerIDX RoundRobin
  791.  
  792. uno_removecardfromhand $nick $pickednum
  793.  
  794. uno_addtodiscardpile $crd
  795.  
  796. # reverse roundrobin and move to next player
  797. set NewRoundRobin ""
  798. set OrigOrderLength [llength $RoundRobin]
  799. set IDX $OrigOrderLength
  800.  
  801. while {$OrigOrderLength != [llength $NewRoundRobin]} {
  802. set IDX [expr ($IDX - 1)]
  803. lappend NewRoundRobin [lindex $RoundRobin $IDX]
  804. }
  805.  
  806. set Newindexorder ""
  807. set OrigindexLength [llength $UnoIDX]
  808. set IDX $OrigindexLength
  809.  
  810. while {$OrigindexLength != [llength $Newindexorder]} {
  811. set IDX [expr ($IDX - 1)]
  812. lappend Newindexorder [lindex $UnoIDX $IDX]
  813. }
  814.  
  815. set UnoIDX $Newindexorder
  816. set RoundRobin $NewRoundRobin
  817.  
  818. set ReversePlayer $ThisPlayer
  819.  
  820. # next player after reversing roundrobin
  821. set pcount 0
  822. while {$pcount != [llength $RoundRobin]} {
  823. if {[lindex $RoundRobin $pcount] == $ThisPlayer} {
  824. set ThisPlayerIDX $pcount
  825. break
  826. }
  827. incr pcount
  828. }
  829.  
  830. # less than 3 players acts like a skip card
  831. if {[llength $RoundRobin] > 2} {
  832. incr ThisPlayerIDX
  833. if {$ThisPlayerIDX >= [llength $RoundRobin]} {set ThisPlayerIDX 0}
  834. }
  835.  
  836. set ThisPlayer [lindex $RoundRobin $ThisPlayerIDX]
  837.  
  838. if {[uno_checkwin $ReversePlayer [uno_cardcolor $crd]]} { return }
  839.  
  840. uno_showplaycard $nick [uno_cardcolor $crd] $ThisPlayer
  841.  
  842. uno_checkuno $ReversePlayer
  843.  
  844. uno_showcards $ThisPlayer $ThisPlayerIDX
  845.  
  846. uno_isdrawreset
  847. }
  848.  
  849. #
  850. # draw two card
  851. #
  852. proc uno_playdrawtwocard {nick pickednum crd} {
  853. global ThisPlayer ThisPlayerIDX RoundRobin
  854.  
  855. uno_removecardfromhand $nick $pickednum
  856.  
  857. uno_addtodiscardpile $crd
  858.  
  859. set DrawPlayer $ThisPlayer
  860. set DrawPlayerIDX $ThisPlayerIDX
  861.  
  862. # move to the player that draws
  863. uno_nextplayer
  864.  
  865. set PlayerThatDrew $ThisPlayer
  866. set PlayerThatDrewIDX $ThisPlayerIDX
  867.  
  868. # move to the player skipped to
  869. uno_nextplayer
  870.  
  871. if {[uno_checkwindraw $nick [uno_cardcolor $crd] $PlayerThatDrew $PlayerThatDrewIDX 2]} { return }
  872.  
  873. uno_showplaydraw $nick [uno_cardcolor $crd] $PlayerThatDrew $ThisPlayer
  874.  
  875. uno_adddrawtohand $PlayerThatDrew $PlayerThatDrewIDX 2
  876.  
  877. uno_checkuno $nick
  878.  
  879. uno_showcards $ThisPlayer $ThisPlayerIDX
  880.  
  881. uno_isdrawreset
  882. }
  883.  
  884. #
  885. # wild draw four card
  886. #
  887. proc uno_playwilddrawfourcard {nick pickednum crd isrobot} {
  888. global ThisPlayer ThisPlayerIDX RoundRobin IsColorChange ColorPicker
  889.  
  890. set ColorPicker $ThisPlayer
  891.  
  892. uno_removecardfromhand $nick $pickednum
  893.  
  894. uno_addtodiscardpile $crd
  895.  
  896. # move to the player that draws
  897. uno_nextplayer
  898.  
  899. set PlayerThatDrew $ThisPlayer
  900. set PlayerThatDrewIDX $ThisPlayerIDX
  901.  
  902. # bot chooses a color
  903. if {$isrobot > 0} {
  904. set cip [uno_botpickcolor]
  905. uno_nextplayer
  906. }
  907.  
  908. if {[uno_checkwindraw $nick [uno_cardcolor $crd] $PlayerThatDrew $PlayerThatDrewIDX 4]} { return }
  909.  
  910. if {$isrobot} {
  911. uno_showbotplaywildfour $ColorPicker $PlayerThatDrew $ColorPicker $cip $ThisPlayer
  912. set ColorPicker ""
  913. set IsColorChange 0
  914. uno_showcards $ThisPlayer $ThisPlayerIDX
  915. } {
  916. uno_showplaywildfour $nick $PlayerThatDrew $ColorPicker
  917. set IsColorChange 1
  918. }
  919.  
  920. uno_adddrawtohand $PlayerThatDrew $PlayerThatDrewIDX 4
  921.  
  922. uno_checkuno $nick
  923.  
  924. uno_isdrawreset
  925. }
  926.  
  927. #
  928. # wild card
  929. #
  930. proc uno_playwildcard {nick pickednum crd isrobot} {
  931. global ThisPlayer ThisPlayerIDX RoundRobin IsColorChange ColorPicker
  932.  
  933. set ColorPicker $ThisPlayer
  934.  
  935. uno_removecardfromhand $nick $pickednum
  936.  
  937. uno_addtodiscardpile $crd
  938.  
  939. if {$isrobot} {
  940. # make a color choice
  941. set cip [uno_botpickcolor]
  942. uno_nextplayer
  943. }
  944.  
  945. # no cards remaining = winner
  946. if {[uno_checkwin $nick [uno_cardcolor $crd]]} { return }
  947.  
  948. if {$isrobot} {
  949. uno_showbotplaywild $nick $ColorPicker $cip $ThisPlayer
  950. set ColorPicker ""
  951. uno_showcards $ThisPlayer $ThisPlayerIDX
  952. set IsColorChange 0
  953. } {
  954. uno_showplaywild $nick $ColorPicker
  955. set IsColorChange 1
  956. }
  957.  
  958. uno_checkuno $nick
  959.  
  960. uno_isdrawreset
  961. }
  962.  
  963. #
  964. # number card
  965. #
  966. proc uno_playnumbercard {nick pickednum crd} {
  967. global ThisPlayer ThisPlayerIDX RoundRobin
  968.  
  969. uno_removecardfromhand $nick $pickednum
  970.  
  971. uno_addtodiscardpile $crd
  972.  
  973. set NumberCardPlayer $ThisPlayer
  974.  
  975. uno_nextplayer
  976.  
  977. if {[uno_checkwin $NumberCardPlayer [uno_cardcolor $crd]]} { return }
  978.  
  979. uno_showplaycard $nick [uno_cardcolor $crd] $ThisPlayer
  980.  
  981. uno_checkuno $NumberCardPlayer
  982.  
  983. uno_showcards $ThisPlayer $ThisPlayerIDX
  984.  
  985. uno_isdrawreset
  986. }
  987.  
  988. #
  989. # attempt to find card in hand
  990. #
  991. proc uno_findcard {nick pickednum crd} {
  992. global UnoRobot ThisPlayer ThisPlayerIDX PlayCard UnoWildDrawTwos UnoWDFAnyTime
  993.  
  994. #if {$UnoDebug > 1} {unolog $UnoRobot "uno_findcard: [lindex $UnoHand($ThisPlayer) $pickednum"}
  995.  
  996. # card in hand
  997. set c0 [string range $crd 0 0]
  998. set c1 [string range $crd 1 1]
  999.  
  1000. # card in play
  1001. set cip0 [string range $PlayCard 0 0]
  1002. set cip1 [string range $PlayCard 1 1]
  1003.  
  1004. # skip
  1005. if {$c1 == "S"} {
  1006. if {($c0 == $cip0)||($c1 == $cip1)} { return 1 }
  1007. return 0
  1008. }
  1009.  
  1010. # reverse
  1011. if {$c1 == "R"} {
  1012. if {($c0 == $cip0)||($c1 == $cip1)} { return 2 }
  1013. return 0
  1014. }
  1015.  
  1016. # wild draw four
  1017. if {($c0 == "W")&&($c1 == "D")} {
  1018. if {$UnoWDFAnyTime} { return 4 }
  1019. if {![uno_checkhandcolor $ThisPlayer]} { return 4 }
  1020. return 7
  1021. }
  1022.  
  1023. # wild
  1024. if {$c0 == "W"} { return 5 }
  1025.  
  1026. # draw two
  1027. if {$c1 == "D"} {
  1028. set CardOk 0
  1029. if {$c0 == $cip0} {set CardOk 1}
  1030. if {$UnoWildDrawTwos != 0} {
  1031. if {($cip0 != "W")&&($cip1 == "D")} {set CardOk 1}
  1032. if {$cip1 != ""} {set CardOk 1}
  1033. } {
  1034. if {($cip0 != "W")&&($cip1 == "D")} {set CardOk 1}
  1035. }
  1036. if {$CardOk} {
  1037. return 3
  1038. }
  1039. return 0
  1040. }
  1041.  
  1042. # number card
  1043. if {($c1 == -1)} {return 0}
  1044. if {($c0 == $cip0)||(($cip1 != "")&&($c1 == $cip1))} { return 6 }
  1045.  
  1046. return 0
  1047. }
  1048.  
  1049. #
  1050. # play the picked card
  1051. #
  1052. # cardfound is set by uno_findcard, which returns a card type as follows:
  1053. #
  1054. # 0 invalid card
  1055. # 1 skip card
  1056. # 2 reverse card
  1057. # 3 draw-two card
  1058. # 4 draw-four card
  1059. # 5 wild card
  1060. # 6 number card
  1061. # 7 illegal card
  1062. #
  1063. proc uno_playactualcard {nick cardfound pickednum crd isrobot} {
  1064. global CardStats
  1065. switch $cardfound {
  1066. 0 {
  1067. if {$isrobot} {
  1068. unolog $nick "UnoRobot: oops $crd"
  1069. } {
  1070. unontc $nick "Oops! Not a valid card... draw or play another"
  1071. }
  1072. }
  1073. 1 {
  1074. uno_playskipcard $nick $pickednum $crd
  1075. incr CardStats(played)
  1076. uno_restartbotplayer
  1077. }
  1078. 2 {
  1079. uno_playreversecard $nick $pickednum $crd
  1080. incr CardStats(played)
  1081. uno_restartbotplayer
  1082. }
  1083. 3 {
  1084. uno_playdrawtwocard $nick $pickednum $crd
  1085. incr CardStats(played)
  1086. uno_restartbotplayer
  1087. }
  1088. 4 {
  1089. uno_playwilddrawfourcard $nick $pickednum $crd $isrobot
  1090. incr CardStats(played)
  1091. if {$isrobot} { uno_restartbotplayer }
  1092. }
  1093. 5 {
  1094. uno_playwildcard $nick $pickednum $crd $isrobot
  1095. incr CardStats(played)
  1096. }
  1097. 6 {
  1098. uno_playnumbercard $nick $pickednum $crd
  1099. incr CardStats(played)
  1100. if {!$isrobot} { uno_restartbotplayer }
  1101. }
  1102. 7 {
  1103. if {$isrobot} {
  1104. unolog $nick "UnoRobot: oops valid card in-hand"; return
  1105. uno_restartbotplayer
  1106. } {
  1107. unontc $nick "You have a valid color card in-hand, $nick, you must play it first"; return
  1108. }
  1109. }
  1110. }
  1111. }
  1112.  
  1113. #
  1114. # attempt to play a card
  1115. #
  1116. proc UnoPlayCard {nick uhost hand chan txt} {
  1117. global UnoMode IsColorChange UnoHand ThisPlayer
  1118.  
  1119. if {(![uno_ischan $chan])||($UnoMode != 2)||($nick != $ThisPlayer)||($IsColorChange == 1)} {return}
  1120.  
  1121. uno_autoskipreset $nick
  1122.  
  1123. regsub -all \[`,.!{}\ ] $txt "" txt
  1124.  
  1125. if {$txt == ""} {return}
  1126.  
  1127. set pcard [string toupper [string range $txt 0 1]]
  1128.  
  1129. set CardInHand 0
  1130.  
  1131. set pcount 0
  1132. while {[lindex $UnoHand($nick) $pcount] != ""} {
  1133. if {$pcard == [lindex $UnoHand($nick) $pcount]} {
  1134. set pcardnum $pcount
  1135. uno_playactualcard $nick [uno_findcard $nick $pcardnum $pcard] $pcardnum $pcard 0
  1136. return
  1137. }
  1138. incr pcount
  1139. }
  1140. unontc $nick "You don't have that card $nick, draw or play another"
  1141. return
  1142. }
  1143.  
  1144. #
  1145. # robot player
  1146. #
  1147.  
  1148. # robot tries to find card from hand
  1149. proc uno_botplayertrycard {} {
  1150. global PlayCard UnoHand ThisPlayer
  1151.  
  1152. # card in play
  1153. set cip0 [string range $PlayCard 0 0]
  1154. set cip1 [string range $PlayCard 1 1]
  1155.  
  1156. set colorcardinplay [uno_iscolorcard $cip0]
  1157.  
  1158. set Tier 0
  1159. set TierMax 8
  1160.  
  1161. # Tier is the order in which the bot player chooses cards:
  1162. # 0 draw two
  1163. # 1 skip
  1164. # 2 reverse
  1165. # skip or reverse on same color
  1166. # color or number match
  1167. # draw four
  1168. # wild
  1169.  
  1170. while {$Tier < $TierMax} {
  1171. set CardCount 0
  1172. while {$CardCount < [llength $UnoHand($ThisPlayer)]} {
  1173.  
  1174. set pcard [lindex $UnoHand($ThisPlayer) $CardCount]
  1175.  
  1176. # card in hand
  1177. set hc0 [string range $pcard 0 0]
  1178. set hc1 [string range $pcard 1 1]
  1179.  
  1180. set colorcardinhand [uno_iscolorcard $hc0]
  1181.  
  1182. switch $Tier {
  1183. 0 {if {($colorcardinplay)&&($hc0 == $cip0)&&($hc1 == "D")} {return $CardCount}}
  1184. 1 {if {($colorcardinplay)&&($cip1 == "D")&&($colorcardinhand)&&($hc1 == "D")} {return $CardCount}}
  1185. 2 {if {($cip1 == "S")&&($hc1 == "S")} {return $CardCount}}
  1186. 3 {if {($cip1 == "R")&&($hc1 == "R")} {return $CardCount}}
  1187. 4 {if {($hc0 == $cip0)&&(($hc1 == "S")||($hc1 == "R"))} {return $CardCount}}
  1188. 5 {if {($hc0 == $cip0)||(($hc1 != "D")&&($hc1 == $cip1))} {return $CardCount}}
  1189. 6 {if {($hc0 == "W")&&($hc1 == "D")} {return $CardCount}}
  1190. 7 {if {($hc0 == "W")} {return $CardCount}}
  1191. }
  1192. incr CardCount
  1193. }
  1194. incr Tier
  1195. }
  1196. return -1;
  1197. }
  1198.  
  1199. proc UnoRobotPlayer {} {
  1200. global UnoDeck UnoHand ThisPlayer ThisPlayerIDX UnoRobot
  1201.  
  1202. set CardOk -1
  1203.  
  1204. uno_isdrawreset
  1205.  
  1206. set UnoHand($ThisPlayer) [uno_sorthand $UnoHand($ThisPlayer)]
  1207.  
  1208. # look for card in hand
  1209. set CardOk [uno_botplayertrycard]
  1210.  
  1211. # play card if found
  1212. if {$CardOk > -1} {
  1213. set pcard [lindex $UnoHand($ThisPlayer) $CardOk]
  1214. uno_playactualcard $UnoRobot [uno_findcard $UnoRobot $CardOk $pcard] $CardOk $pcard 1
  1215. return
  1216. }
  1217.  
  1218. # bot draws a card
  1219. UnoShuffle 1
  1220.  
  1221. set dcardnum 0
  1222. set dcard [lindex $UnoDeck $dcardnum]
  1223. lappend UnoHand($ThisPlayer) $dcard
  1224. set UnoDeck [lreplace $UnoDeck $dcardnum $dcardnum]
  1225.  
  1226. uno_showwhodrew $UnoRobot
  1227.  
  1228. set UnoHand($ThisPlayer) [uno_sorthand $UnoHand($ThisPlayer)]
  1229.  
  1230. # look for card in hand
  1231. set CardOk [uno_botplayertrycard]
  1232.  
  1233. # bot plays drawn card or passes turn
  1234. if {$CardOk > -1} {
  1235. set pcard [lindex $UnoHand($ThisPlayer) $CardOk]
  1236. uno_playactualcard $UnoRobot [uno_findcard $UnoRobot $CardOk $pcard] $CardOk $pcard 1
  1237. } {
  1238. uno_isdrawreset
  1239. uno_nextplayer
  1240. uno_showplaypass $UnoRobot $ThisPlayer
  1241. uno_showcards $ThisPlayer $ThisPlayerIDX
  1242. }
  1243. return
  1244. }
  1245.  
  1246. #
  1247. # autoskip inactive players
  1248. #
  1249. proc UnoAutoSkip {} {
  1250. global UnoMode ThisPlayer ThisPlayerIDX RoundRobin AutoSkipPeriod IsColorChange ColorPicker
  1251. global UnoIDX UnoPlayers UnoDeck UnoHand UnoChan UnoSkipTimer UnoDebug UnoNickColor UnoPaused UnoDCCIDX UnoLastIdler
  1252. global botnick
  1253.  
  1254. if {($UnoMode != 2)||($UnoPaused != 0)} {return}
  1255.  
  1256. set Idler $ThisPlayer
  1257. set IdlerIDX $ThisPlayerIDX
  1258.  
  1259. if {[uno_isrobot $ThisPlayerIDX]} {unolog "uno" "oops: Autoskip called while bot players turn"; return}
  1260.  
  1261. if {[uno_timerexists UnoAutoSkip] != ""} {
  1262. unolog "uno" "oops: Autoskip timer called, but already exists"
  1263. return
  1264. }
  1265.  
  1266. set InChannel 0
  1267. set uclist [chanlist $UnoChan]
  1268.  
  1269. set pcount 0
  1270. while {[lindex $uclist $pcount] != ""} {
  1271. if {[lindex $uclist $pcount] == $Idler} {
  1272. set InChannel 1
  1273. break
  1274. }
  1275. incr pcount
  1276. }
  1277.  
  1278. if {!$InChannel || ($Idler == $UnoLastIdler)} {
  1279. if {!$InChannel} {
  1280. unomsg "[unonik $Idler]\003 left the channel and is removed from Uno"
  1281. } {
  1282. unomsg "[unonik $Idler]\003 has been idle twice in a row and is removed from Uno"
  1283. set UnoLastIdler ""
  1284. }
  1285. if {$IsColorChange == 1} {
  1286. if {$Idler == $ColorPicker} {
  1287. # Make A Color Choice
  1288. set cip [uno_pickcolor]
  1289. unomsg "\0030,13 $Idler \003was picking a color : randomly selecting $cip"
  1290. set IsColorChange 0
  1291. } {
  1292. unolog "uno" "oops: UnoAutoRemove color change set but $Idler not color picker"
  1293. }
  1294. }
  1295.  
  1296. uno_nextplayer
  1297.  
  1298. unomsg "[unonik $Idler]\003 was the current player, continuing with [unonik $ThisPlayer]"
  1299.  
  1300. uno_showcards $ThisPlayer $ThisPlayerIDX
  1301.  
  1302. set UnoPlayers [expr ($UnoPlayers -1)]
  1303.  
  1304. # remove player from game and put cards back in deck
  1305. if {$UnoPlayers > 1} {
  1306. set RoundRobin [lreplace $RoundRobin $IdlerIDX $IdlerIDX]
  1307. set UnoIDX [lreplace $UnoIDX $IdlerIDX $IdlerIDX]
  1308. while {[llength $UnoHand($Idler)] > 0} {
  1309. set pcard [lindex $UnoHand($Idler) 0]
  1310. set UnoHand($Idler) [lreplace $UnoHand($Idler) 0 0]
  1311. lappend UnoDeck $pcard
  1312. }
  1313. if [info exist UnoHand($Idler)] {unset UnoHand($Idler)}
  1314. if [info exist UnoNickColor($Idler)] {unset UnoNickColor($Idler)}
  1315. if [info exist UnoDCCIDX($Idler)] {unset UnoDCCIDX($Idler)}
  1316. }
  1317.  
  1318. switch $UnoPlayers {
  1319. 1 {
  1320. uno_showwindefault $ThisPlayer
  1321. UnoWin $ThisPlayer
  1322. UnoCycle
  1323. }
  1324. 0 {
  1325. unochanmsg "\00306no players, no winner... cycling"
  1326. UnoCycle
  1327. }
  1328. default {
  1329. if {![uno_isrobot $ThisPlayerIDX]} {
  1330. uno_autoskipreset $botnick
  1331. uno_restartbotplayer
  1332. }
  1333. }
  1334. }
  1335. return
  1336. }
  1337.  
  1338. if {$UnoDebug > 0} {unolog "uno" "AutoSkip Player: $Idler"}
  1339.  
  1340. unomsg "[unonik $Idler]\003 idle for \00313$AutoSkipPeriod \003minutes and is skipped"
  1341.  
  1342. set UnoLastIdler $Idler
  1343.  
  1344. # player was color picker
  1345. if {$IsColorChange == 1} {
  1346. if {$Idler == $ColorPicker} {
  1347. # Make A Color Choice
  1348. set cip [uno_pickcolor]
  1349. unomsg "[unonik $Idler]\003 was picking a color : randomly selecting $cip"
  1350. set IsColorChange 0
  1351. } {
  1352. unolog "uno" "UnoRemove: IsColorChange set but $Idler not ColorPicker"
  1353. }
  1354. }
  1355.  
  1356. uno_nextplayer
  1357.  
  1358. unomsg "[unonik $Idler]\003 was the current player, continuing with [unonik $ThisPlayer]"
  1359.  
  1360. uno_showcards $ThisPlayer $ThisPlayerIDX
  1361.  
  1362. if {[uno_isrobot $ThisPlayerIDX]} {
  1363. uno_restartbotplayer
  1364. }
  1365.  
  1366. uno_autoskipreset $botnick
  1367. return
  1368. }
  1369.  
  1370. #
  1371. # pause play
  1372. #
  1373. proc UnoPause {nick uhost hand chan txt} {
  1374. global UnoChan UnoOpFlags UnoPaused
  1375.  
  1376. if {![uno_isrunning $chan]} {return}
  1377.  
  1378. if {([validuser $nick])&&([matchattr $nick $UnoOpFlags $UnoChan])} {
  1379. if {!$UnoPaused} {
  1380. set UnoPaused 1
  1381. UnoUnbindCmds
  1382. unochanmsg "\00304 paused \003by $nick"
  1383. } {
  1384. set UnoPaused 0
  1385. UnoBindCmds
  1386. uno_autoskipreset $nick
  1387. unochanmsg "\00303 resumed \003by $nick"
  1388. }
  1389. }
  1390. }
  1391.  
  1392. #
  1393. # remove user from play
  1394. #
  1395. proc UnoRemove {nick uhost hand chan txt} {
  1396. global UnoChan UnoCycleTime UnoIDX UnoPlayers ThisPlayer ThisPlayerIDX RoundRobin UnoDeck DiscardPile UnoHand IsColorChange ColorPicker UnoNickColor UnoOpFlags UnoDCCIDX
  1397.  
  1398. if {![uno_isrunning $chan]} {return}
  1399.  
  1400. regsub -all \[`,.!{}] $txt "" txt
  1401.  
  1402. # allow ops to remove another player
  1403. set UnoOpRemove 0
  1404.  
  1405. if {[string length $txt] > 0} {
  1406. if {([validuser $nick])&&([matchattr $nick $UnoOpFlags $UnoChan])} {
  1407. set UnoOpRemove 1
  1408. set UnoOpNick $nick
  1409. set nick $txt
  1410. } {
  1411. return
  1412. }
  1413. }
  1414.  
  1415. # remove player if found - put cards back to bottom of deck
  1416. set pcount 0
  1417. set PlayerFound 0
  1418. while {[lindex $RoundRobin $pcount] != ""} {
  1419. if {[string tolower [lindex $RoundRobin $pcount]] == [string tolower $nick]} {
  1420. set PlayerFound 1
  1421. set FoundIDX $pcount
  1422. set nick [lindex $RoundRobin $pcount]
  1423. break
  1424. }
  1425. incr pcount
  1426. }
  1427.  
  1428. if {!$PlayerFound} {return}
  1429.  
  1430. if {$UnoOpRemove > 0} {
  1431. unomsg "[unonik $nick]\003 was removed from uno by $UnoOpNick"
  1432. } {
  1433. unontc $nick "You are now removed from the current uno game."
  1434. unomsg "[unonik $nick]\003 left Uno"
  1435. }
  1436.  
  1437. # player was color picker
  1438. if {$IsColorChange == 1} {
  1439. if {$nick == $ColorPicker} {
  1440. # Make A Color Choice
  1441. set cip [uno_pickcolor]
  1442. unomsg "[unonik $nick]\003 was choosing a color... I randomly select $cip"
  1443. set IsColorChange 0
  1444. } {
  1445. unolog "uno" "UnoRemove: IsColorChange set but $nick not ColorPicker"
  1446. }
  1447. }
  1448.  
  1449. if {$nick == $ThisPlayer} {
  1450. uno_nextplayer
  1451. if {$UnoPlayers > 2} {
  1452. unomsg "[unonik $nick]\003 was the current player, continuing with [unonik $ThisPlayer]"
  1453. }
  1454. uno_autoskipreset $nick
  1455. }
  1456.  
  1457. set UnoPlayers [expr ($UnoPlayers -1)]
  1458.  
  1459. # remove player from game and put cards back in deck
  1460.  
  1461. if {$UnoPlayers > 1} {
  1462. set RoundRobin [lreplace $RoundRobin $FoundIDX $FoundIDX]
  1463. set UnoIDX [lreplace $UnoIDX $FoundIDX $FoundIDX]
  1464. while {[llength $UnoHand($nick)] > 0} {
  1465. set pcard [lindex $UnoHand($nick) 0]
  1466. set UnoHand($nick) [lreplace $UnoHand($nick) 0 0]
  1467. lappend DiscardPile $pcard
  1468. }
  1469. if [info exist UnoHand($nick)] {unset UnoHand($nick)}
  1470. if [info exist UnoNickColor($nick)] {unset UnoNickColor($nick)}
  1471. if [info exist UnoDCCIDX($nick)] {unset UnoDCCIDX($nick)}
  1472. }
  1473.  
  1474. set pcount 0
  1475. while {[lindex $RoundRobin $pcount] != ""} {
  1476. if {[lindex $RoundRobin $pcount] == $ThisPlayer} {
  1477. set ThisPlayerIDX $pcount
  1478. break
  1479. }
  1480. incr pcount
  1481. }
  1482.  
  1483. if {$UnoPlayers == 1} {
  1484. uno_showwindefault $ThisPlayer
  1485. UnoWin $ThisPlayer
  1486. UnoCycle
  1487. return
  1488. }
  1489.  
  1490. uno_restartbotplayer
  1491.  
  1492. if {!$UnoPlayers} {
  1493. unochanmsg "no players, no winner... recycling"
  1494. UnoCycle
  1495. }
  1496. return
  1497. }
  1498.  
  1499. #
  1500. # move to next player
  1501. #
  1502. proc uno_nextplayer {} {
  1503. global ThisPlayer ThisPlayerIDX RoundRobin
  1504. incr ThisPlayerIDX
  1505. if {$ThisPlayerIDX >= [llength $RoundRobin]} {set ThisPlayerIDX 0}
  1506. set ThisPlayer [lindex $RoundRobin $ThisPlayerIDX]
  1507. }
  1508.  
  1509. #
  1510. # set global PlayCard to chosen color and return colored card
  1511. #
  1512. proc uno_getcolorcard {crd} {
  1513. global PlayCard UnoRedCard UnoGreenCard UnoBlueCard UnoYellowCard
  1514. set pcol [string range $crd 0 0]
  1515. switch $pcol {
  1516. "R" {set PlayCard "R"; return "$UnoRedCard\003" }
  1517. "G" {set PlayCard "G"; return "$UnoGreenCard\003" }
  1518. "B" {set PlayCard "B"; return "$UnoBlueCard\003" }
  1519. "Y" {set PlayCard "Y"; return "$UnoYellowCard\003" }
  1520. }
  1521. }
  1522.  
  1523. #
  1524. # returns 1 if color card, 0 if not
  1525. #
  1526. proc uno_iscolorcard {c} {
  1527. switch $c {
  1528. "R" {return 1}
  1529. "G" {return 1}
  1530. "B" {return 1}
  1531. "Y" {return 1}
  1532. }
  1533. return 0
  1534. }
  1535.  
  1536. #
  1537. # pick a random color for skipped/removed players
  1538. #
  1539. proc uno_pickcolor {} {
  1540. set ucolors "R G B Y"
  1541. set pcol [lindex $ucolors [rand [llength $ucolors]]]
  1542. return [uno_getcolorcard $pcol]
  1543. }
  1544.  
  1545. #
  1546. # robot player picks a color by checking hand for 1st color card
  1547. # found with matching color, else it picks a color at random
  1548. #
  1549. proc uno_botpickcolor {} {
  1550. global UnoHand ThisPlayer ColorPicker
  1551.  
  1552. set hlen [llength $UnoHand($ColorPicker)]
  1553.  
  1554. # draw two
  1555. set CardCount 0
  1556. while {$CardCount < $hlen} {
  1557. set thiscolor [string range [lindex $UnoHand($ColorPicker) $CardCount] 0 0]
  1558. set thiscard [string range [lindex $UnoHand($ColorPicker) $CardCount] 1 1]
  1559. if {([uno_iscolorcard $thiscolor])&&($thiscard == "D")} { return [uno_getcolorcard $thiscolor] }
  1560. incr CardCount
  1561. }
  1562.  
  1563. # skip/reverse
  1564. set CardCount 0
  1565. while {$CardCount < $hlen} {
  1566. set thiscolor [string range [lindex $UnoHand($ColorPicker) $CardCount] 0 0]
  1567. set thiscard [string range [lindex $UnoHand($ColorPicker) $CardCount] 1 1]
  1568. if {([uno_iscolorcard $thiscolor])&&(($thiscard == "S")||($thiscard == "R"))} { return [uno_getcolorcard $thiscolor] }
  1569. incr CardCount
  1570. }
  1571.  
  1572. # number card
  1573. set CardCount 0
  1574. while {$CardCount < $hlen} {
  1575. set thiscolor [string range [lindex $UnoHand($ColorPicker) $CardCount] 0 0]
  1576. if {[uno_iscolorcard $thiscolor]} { return [uno_getcolorcard $thiscolor] }
  1577. incr CardCount
  1578. }
  1579.  
  1580. # wild or wdf remain, pick color at random
  1581. return [uno_pickcolor]
  1582. }
  1583.  
  1584. #
  1585. # timers
  1586. #
  1587.  
  1588. # set robot for next turn
  1589. proc uno_restartbotplayer {} {
  1590. global UnoMode ThisPlayerIDX RobotRestartPeriod UnoBotTimer
  1591. if {$UnoMode != 2} {return}
  1592. if {![uno_isrobot $ThisPlayerIDX]} {return}
  1593. set UnoBotTimer [utimer $RobotRestartPeriod UnoRobotPlayer]
  1594. }
  1595.  
  1596. # reset autoskip timer
  1597. proc uno_autoskipreset {nick} {
  1598. global AutoSkipPeriod UnoMode UnoSkipTimer UnoLastIdler
  1599. catch {killtimer $UnoSkipTimer}
  1600. if {$nick == $UnoLastIdler} { set UnoLastIdler "" }
  1601. if {$UnoMode == 2} { set UnoSkipTimer [timer $AutoSkipPeriod UnoAutoSkip] }
  1602. }
  1603.  
  1604. #
  1605. # channel triggers
  1606. #
  1607.  
  1608. # game help
  1609. proc UnoCmds {nick uhost hand chan txt} {
  1610. global UnoLogo
  1611. if {![uno_ischan $chan]} {return}
  1612. unogntc $nick "$UnoLogo Commands: !uno !stop !remove \[nick\] !unowon \[nick\] !unocmds"
  1613. unogntc $nick "$UnoLogo Stats: !unotop10 \[games\|wins\|21\] !unotop3last !unostats !unorecords"
  1614. unogntc $nick "$UnoLogo Card Commands: jo=join pl=play dr=draw pa=pass co=color"
  1615. unogntc $nick "$UnoLogo Chan Commands: ca=cards cd=card tu=turn od=order ct=count st=stats ti=time"
  1616. return
  1617. }
  1618.  
  1619. # game version
  1620. proc UnoVersion {nick uhost hand chan txt} {
  1621. global UnoVersion
  1622. unochanmsg "$UnoVersion by #World-Chat Team \003"
  1623. return
  1624. }
  1625.  
  1626. # current player order
  1627. proc UnoOrder {nick uhost hand chan txt} {
  1628. global UnoPlayers RoundRobin
  1629. if {![uno_isrunning $chan]} {return}
  1630. unochanmsg "Player order: \00314$RoundRobin\003"
  1631. return
  1632. }
  1633.  
  1634. # game running time
  1635. proc UnoTime {nick uhost hand chan txt} {
  1636. global UnoLogo
  1637. if {![uno_isrunning $chan]} {return}
  1638. unochanmsg "Game time \00314[UnoDuration [uno_gametime]] \003"
  1639. return
  1640. }
  1641.  
  1642. # show player what cards in hand
  1643. proc UnoShowCards {nick uhost hand chan txt} {
  1644. global UnoHand ThisPlayerIDX
  1645.  
  1646. if {![uno_isrunning $chan]} {return}
  1647.  
  1648. if ![info exist UnoHand($nick)] { return }
  1649.  
  1650. set UnoHand($nick) [uno_sorthand $UnoHand($nick)]
  1651.  
  1652. set Card [uno_cardcolorall $nick]
  1653.  
  1654. if {![uno_isrobot $ThisPlayerIDX]} { unontc $nick "$Card\003" }
  1655.  
  1656. return
  1657. }
  1658.  
  1659. # show current player
  1660. proc UnoTurn {nick uhost hand chan txt} {
  1661. global ThisPlayer RoundRobin UnoMode
  1662. if {![uno_isrunning $chan]} {return}
  1663. if {[llength $RoundRobin] < 1 } {return}
  1664. unochanmsg "Current player: \00314$ThisPlayer\003"
  1665. return
  1666. }
  1667.  
  1668. # show current top card
  1669. proc UnoTopCard {nick uhost hand chan txt} {
  1670. global PlayCard
  1671. if {![uno_isrunning $chan]} {return}
  1672. set Card [uno_cardcolor $PlayCard]
  1673. unochanmsg "Card in play: $Card"
  1674. return
  1675. }
  1676.  
  1677. # card stats
  1678. proc UnoCardStats {nick uhost hand chan txt} {
  1679. global CardStats
  1680. if {![uno_isrunning $chan]} {return}
  1681. unochanmsg "Played:\00314$CardStats(played)\003"
  1682. return
  1683. }
  1684.  
  1685. # card count
  1686. proc UnoCardCount {nick uhost hand chan txt} {
  1687. global RoundRobin UnoHand
  1688. if {![uno_isrunning $chan]} {return}
  1689. set ordcnt 0
  1690. set crdcnt ""
  1691. while {[lindex $RoundRobin $ordcnt] != ""} {
  1692. set cp [lindex $RoundRobin $ordcnt]
  1693. set cc [llength $UnoHand($cp)]
  1694. append crdcnt "\00310 $cp \00306 $cc cards "
  1695. incr ordcnt
  1696. }
  1697. unomsg "$crdcnt\003"
  1698. return
  1699. }
  1700.  
  1701. # player's score
  1702. proc UnoWon {nick uhost hand chan txt} {
  1703. global UnoScoreFile UnoPointsName
  1704.  
  1705. if {![uno_ischan $chan]} {return}
  1706.  
  1707. regsub -all \[`,.!] $txt "" txt
  1708.  
  1709. if {![string length $txt]} {set txt $nick}
  1710.  
  1711. set scorer [string tolower $txt]
  1712.  
  1713. set pflag 0
  1714.  
  1715. set f [open $UnoScoreFile r]
  1716. while {[gets $f sc] != -1} {
  1717. set cnick [string tolower [lindex [split $sc] 0]]
  1718. if {$cnick == $scorer} {
  1719. set winratio [format "%4.1f" [expr [lindex $sc 2] /[lindex $sc 1]]]
  1720. set pmsg "\00306[lindex [split $sc] 0] \003 [lindex $sc 2] $UnoPointsName in [lindex $sc 1] games \($winratio p\/g\)"
  1721. set pflag 1
  1722. }
  1723. }
  1724. close $f
  1725.  
  1726. if {!$pflag} {
  1727. set pmsg "\00306$txt\003 no score"
  1728. }
  1729. unochanmsg "$pmsg"
  1730. return
  1731. }
  1732.  
  1733. # current top10 list
  1734. proc UnoTopTen {nick uhost hand chan txt} {
  1735. if {![uno_ischan $chan]} {return}
  1736. regsub -all \[`,.!{}\ ] $txt "" txt
  1737. set txt [string tolower [string range $txt 0 10]]
  1738. switch $txt {
  1739. "won" {set mode 1}
  1740. "games" {set mode 0}
  1741. "Rand" {set mode 1}
  1742. "21" {set mode 2}
  1743. "blackjack" {set mode 2}
  1744. default {set mode 1}
  1745. }
  1746. UnoTop10 $mode
  1747. return
  1748. }
  1749.  
  1750. # last month's top3
  1751. proc UnoTopThreeLast {nick uhost hand chan txt} {
  1752. if {![uno_ischan $chan]} {return}
  1753. UnoLastMonthTop3 $nick $uhost $hand $chan 0
  1754. UnoLastMonthTop3 $nick $uhost $hand $chan 1
  1755. return
  1756. }
  1757.  
  1758. # month's stats
  1759. proc UnoPlayStats {nick uhost hand chan txt} {
  1760. global UnoFast UnoHigh UnoPlayed UnoPointsName
  1761. if {![uno_ischan $chan]} {return}
  1762. unochanmsg "Current record holders"
  1763. set msg "\00306Fast:\003 [lindex [split $UnoFast] 0] \002[UnoDuration [lindex $UnoFast 1]]\002 "
  1764. append msg "\00306High:\003 [lindex [split $UnoHigh] 0] \002[lindex $UnoHigh 1]\002 $UnoPointsName "
  1765. append msg "\00306Played:\003 [lindex [split $UnoPlayed] 0] \002[lindex $UnoPlayed 1]\002 Cards"
  1766. unochanmsg "$msg"
  1767. return
  1768. }
  1769.  
  1770. # all-time records
  1771. proc UnoRecords {nick uhost hand chan txt} {
  1772. global UnoRecordFast UnoRecordHigh UnoRecordCard UnoRecordWins UnoRecordPlayed
  1773. if {![uno_ischan $chan]} {return}
  1774. unochanmsg "All-Time Records"
  1775. 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"
  1776. return
  1777. }
  1778.  
  1779. # current row (streak)
  1780. proc UnoCurrentRow {nick uhost hand chan txt} {
  1781. global UnoLastWinner UnoWinsInARow
  1782. if {![uno_ischan $chan]} {return}
  1783. if {($UnoLastWinner != "")&&($UnoWinsInARow > 0)} {
  1784. switch ($UnoWinsInARow) {
  1785. 1 { unochanmsg "\0036$UnoLastWinner \003 has won \0030,6 $UnoWinsInARow game \003" }
  1786. default { unochanmsg "\0033$UnoLastWinner \003 is on a \0030,6 $UnoWinsInARow game streak \003" }
  1787. }
  1788. }
  1789. return
  1790. }
  1791.  
  1792. # month top10
  1793. proc UnoTop10 {mode} {
  1794. global UnoScoreFile unsortedscores UnoPointsName UnoRobot
  1795.  
  1796. if {($mode < 0)||($mode > 2)} {set mode 0}
  1797.  
  1798. switch $mode {
  1799. 0 {set winners "Top10 Game Wins "}
  1800. 1 {set winners "Top10 $UnoPointsName "}
  1801. 2 {set winners "Top10 Blackjacks "}
  1802. }
  1803.  
  1804. if ![file exists $UnoScoreFile] {
  1805. set f [open $UnoScoreFile w]
  1806. puts $f "$UnoRobot 0 0 0"
  1807. unochanmsg "\0034Uno scores reset"
  1808. close $f
  1809. return
  1810. } {
  1811. unomsg "$winners"
  1812. set winners ""
  1813. }
  1814.  
  1815. if [info exists unsortedscores] {unset unsortedscores}
  1816. if [info exists top10] {unset top10}
  1817.  
  1818. set f [open $UnoScoreFile r]
  1819. while {[gets $f s] != -1} {
  1820. switch $mode {
  1821. 0 {set unsortedscores([lindex [split $s] 0]) [lindex $s 1]}
  1822. 1 {set unsortedscores([lindex [split $s] 0]) [lindex $s 2]}
  1823. 2 {set unsortedscores([lindex [split $s] 0]) [lindex $s 3]}
  1824. }
  1825. }
  1826. close $f
  1827.  
  1828. for {set s 0} {$s < 10} {incr s} {
  1829. set top10($s) "Nobody 0"
  1830. }
  1831.  
  1832. set s 0
  1833. foreach n [lsort -decreasing -command uno_sortscores [array names unsortedscores]] {
  1834. set top10($s) "$n $unsortedscores($n)"
  1835. incr s
  1836. }
  1837.  
  1838. for {set s 0} {$s < 10} {incr s} {
  1839. if {[llength [lindex $top10($s) 0]] > 0} {
  1840. if {[lindex [split $top10($s)] 0] != "Nobody"} {
  1841. append winners "\0030,6 #[expr $s +1] \0030,10 [lindex [split $top10($s)] 0] [lindex $top10($s) 1] "
  1842. }
  1843. }
  1844. }
  1845.  
  1846. unomsg "$winners \003"
  1847. return
  1848. }
  1849.  
  1850. # last month's top3
  1851. proc UnoLastMonthTop3 {nick uhost hand chan txt} {
  1852. global UnoLastMonthCards UnoLastMonthGames UnoPointsName
  1853. if {![uno_ischan $chan]} {return}
  1854. if {!$txt} {
  1855. if [info exists UnoLastMonthCards] {
  1856. set UnoTop3 ""
  1857. unochanmsg "Last Month's Top 3 $UnoPointsName Winners"
  1858. for { set s 0} { $s < 3 } { incr s} {
  1859. append UnoTop3 "\0030,6 #[expr $s +1] \0030,10 $UnoLastMonthCards($s) "
  1860. }
  1861. unomsg "$UnoTop3"
  1862. }
  1863. } {
  1864. if [info exists UnoLastMonthGames] {
  1865. set UnoTop3 ""
  1866. unochanmsg "Last Month's Top 3 Game Winners"
  1867. for { set s 0} { $s < 3 } { incr s} {
  1868. append UnoTop3 "\0030,6 #[expr $s +1] \0030,10 $UnoLastMonthGames($s) "
  1869. }
  1870. unomsg "$UnoTop3"
  1871. }
  1872. }
  1873. }
  1874.  
  1875. #
  1876. # scores/records
  1877. #
  1878.  
  1879. # read score file
  1880. proc UnoReadScores {} {
  1881. global unogameswon unoptswon unoblackjackswon UnoScoreFile UnoRobot
  1882.  
  1883. if [info exists unogameswon] { unset unogameswon }
  1884. if [info exists unoptswon] { unset unoptswon }
  1885. if [info exists unoblackjackswon] { unset unoblackjackswon }
  1886.  
  1887. if ![file exists $UnoScoreFile] {
  1888. set f [open $UnoScoreFile w]
  1889. puts $f "$UnoRobot 0 0 0"
  1890. close $f
  1891. }
  1892.  
  1893. set f [open $UnoScoreFile r]
  1894. while {[gets $f s] != -1} {
  1895. set unogameswon([lindex [split $s] 0]) [lindex $s 1]
  1896. set unoptswon([lindex [split $s] 0]) [lindex $s 2]
  1897. set unoblackjackswon([lindex [split $s] 0]) [lindex $s 3]
  1898. }
  1899. close $f
  1900.  
  1901. return
  1902. }
  1903.  
  1904. # clear top10 and write monthly scores
  1905. proc UnoNewMonth {min hour day month year} {
  1906. global unsortedscores unogameswon unoptswon unoblackjackswon UnoLastMonthCards UnoLastMonthGames UnoScoreFile UnoRobot
  1907. global UnoFast UnoHigh UnoPlayed UnoRecordFast UnoRecordHigh UnoRecordPlayed UnoRecordCard UnoRecordWins
  1908.  
  1909. set lmonth [UnoLastMonthName $month]
  1910.  
  1911. unochanmsg "\00306Clearing monthly scores"
  1912.  
  1913. set UnoMonthFileName "$UnoScoreFile.$lmonth"
  1914.  
  1915. # read current scores
  1916. UnoReadScores
  1917.  
  1918. # write to old month file
  1919. if ![file exists $UnoMonthFileName] {
  1920. set f [open $UnoMonthFileName w]
  1921. foreach n [array names unogameswon] {
  1922. puts $f "$n $unogameswon($n) $unoptswon($n) $unoblackjackswon($n)"
  1923. }
  1924. close $f
  1925. }
  1926.  
  1927. # find top 3 card holders and game winners
  1928. set mode 0
  1929.  
  1930. while {$mode < 2} {
  1931. if [info exists unsortedscores] {unset unsortedscores}
  1932. if [info exists top10] {unset top10}
  1933.  
  1934. set f [open $UnoScoreFile r]
  1935. while {[gets $f s] != -1} {
  1936. switch $mode {
  1937. 0 {set unsortedscores([lindex [split $s] 0]) [lindex $s 1]}
  1938. 1 {set unsortedscores([lindex [split $s] 0]) [lindex $s 2]}
  1939. }
  1940. }
  1941. close $f
  1942.  
  1943. set s 0
  1944. foreach n [lsort -decreasing -command uno_sortscores [array names unsortedscores]] {
  1945. set top10($s) "$n $unsortedscores($n)"
  1946. incr s
  1947. }
  1948.  
  1949. for {set s 0} {$s < 3} {incr s} {
  1950. if {[lindex $top10($s) 1] > 0} {
  1951. switch $mode {
  1952. 0 {set UnoLastMonthGames($s) "[lindex [split $top10($s)] 0] [lindex $top10($s) 1]"}
  1953. 1 {set UnoLastMonthCards($s) "[lindex [split $top10($s)] 0] [lindex $top10($s) 1]"}
  1954. }
  1955. } {
  1956. switch $mode {
  1957. 0 {set UnoLastMonthGames($s) "Nobody 0"}
  1958. 1 {set UnoLastMonthCards($s) "Nobody 0"}
  1959. }
  1960. }
  1961. }
  1962. incr mode
  1963. }
  1964.  
  1965. # update records
  1966. if {[lindex $UnoFast 1] < [lindex $UnoRecordFast 1]} {set UnoRecordFast $UnoFast}
  1967. if {[lindex $UnoHigh 1] > [lindex $UnoRecordHigh 1]} {set UnoRecordHigh $UnoHigh}
  1968. if {[lindex $UnoPlayed 1] > [lindex $UnoRecordPlayed 1]} {set UnoRecordPlayed $UnoPlayed}
  1969. if {[lindex $UnoLastMonthCards(0) 1] > [lindex $UnoRecordCard 1]} {set UnoRecordCard $UnoLastMonthCards(0)}
  1970. if {[lindex $UnoLastMonthGames(0) 1] > [lindex $UnoRecordWins 1]} {set UnoRecordWins $UnoLastMonthGames(0)}
  1971.  
  1972. # wipe last months records
  1973. set UnoFast "$UnoRobot 60"
  1974. set UnoHigh "$UnoRobot 100"
  1975. set UnoPlayed "$UnoRobot 100"
  1976.  
  1977. # save top3 and records to config file
  1978. UnoWriteCFG
  1979.  
  1980. # wipe this months score file
  1981. set f [open $UnoScoreFile w]
  1982. puts $f "$UnoRobot 0 0 0"
  1983. close $f
  1984.  
  1985. unolog "uno" "cleared monthly scores"
  1986. return
  1987. }
  1988.  
  1989. # update score of winning player
  1990. proc UnoUpdateScore {winner cardtotals blackjack} {
  1991. global unogameswon unoptswon unoblackjackswon UnoScoreFile
  1992.  
  1993. UnoReadScores
  1994.  
  1995. if {[info exists unogameswon($winner)]} {
  1996. incr unogameswon($winner) 1
  1997. } {
  1998. set unogameswon($winner) 1
  1999. }
  2000.  
  2001. if {[info exists unoptswon($winner)]} {
  2002. incr unoptswon($winner) $cardtotals
  2003. } {
  2004. set unoptswon($winner) $cardtotals
  2005. }
  2006.  
  2007. if {$blackjack} {
  2008. if {[info exists unoblackjackswon($winner)]} {
  2009. incr unoblackjackswon($winner) 1
  2010. } {
  2011. set unoblackjackswon($winner) 1
  2012. }
  2013. } {
  2014. if {![info exists unoblackjackswon($winner)]} {
  2015. set unoblackjackswon($winner) 0
  2016. }
  2017. }
  2018.  
  2019. set f [open $UnoScoreFile w]
  2020. foreach n [array names unogameswon] {
  2021. puts $f "$n $unogameswon($n) $unoptswon($n) $unoblackjackswon($n)"
  2022. }
  2023. close $f
  2024.  
  2025. return
  2026. }
  2027.  
  2028. # display winner and game statistics
  2029. proc UnoWin {winner} {
  2030. global UnoHand ThisPlayer RoundRobin UnoPointsName CardStats UnoMode UnoCycleTime
  2031. global UnoFast UnoHigh UnoPlayed UnoBonus UnoWinDefault UnoDCCIDX UnoRobot UnoLastWinner UnoWinsInARow
  2032.  
  2033. # get time game finished
  2034. set UnoTime [uno_gametime]
  2035.  
  2036. set cardtotals 0
  2037. set UnoMode 3
  2038. set ThisPlayerIDX 0
  2039. set needCFGWrite 0
  2040. set isblackjack 0
  2041. set cardtake 0
  2042.  
  2043. # colour winner's nick
  2044. set cnick [unonik $winner]
  2045.  
  2046. #unomsg "\00306Card Totals"
  2047.  
  2048. # total up all player's cards
  2049. while {$ThisPlayerIDX != [llength $RoundRobin]} {
  2050. set Card ""
  2051. set ThisPlayer [lindex $RoundRobin $ThisPlayerIDX]
  2052. if [info exist UnoDCCIDX($ThisPlayer)] {unset UnoDCCIDX($ThisPlayer)}
  2053. if {$ThisPlayer != $winner} {
  2054. set ccount 0
  2055. while {[lindex $UnoHand($ThisPlayer) $ccount] != ""} {
  2056. set cardtotal [lindex $UnoHand($ThisPlayer) $ccount]
  2057. set c1 [string range $cardtotal 0 0]
  2058. set c2 [string range $cardtotal 1 1]
  2059. set cardtotal 0
  2060.  
  2061. if {$c1 == "W"} {
  2062. set cardtotal 50
  2063. } {
  2064. switch $c2 {
  2065. "S" {set cardtotal 20}
  2066. "R" {set cardtotal 20}
  2067. "D" {set cardtotal 20}
  2068. default {set cardtotal $c2}
  2069. }
  2070. }
  2071. set cardtotals [expr $cardtotals + $cardtotal]
  2072. incr ccount
  2073. }
  2074. set Card [uno_cardcolorall $ThisPlayer]
  2075. unochanmsg "[unonik $ThisPlayer] \003 $Card"
  2076. #unochanmsg "[unonik $ThisPlayer] \003\[$ccount\] $Card"
  2077. incr cardtake $ccount
  2078. }
  2079. incr ThisPlayerIDX
  2080. }
  2081.  
  2082. set bonus 0
  2083. set bbonus 0
  2084.  
  2085. # bonuses not given for win by default
  2086. if {$UnoWinDefault != 1} {
  2087. set HighScore [lindex $UnoHigh 1]
  2088. set HighPlayed [lindex $UnoPlayed 1]
  2089. set FastRecord [lindex $UnoFast 1]
  2090.  
  2091. # out with 21 adds blackjack bonus
  2092. if {$cardtotals == 21} {
  2093. set bbonus [expr $UnoBonus /2]
  2094. unochanmsg "$cnick\003 goes out on 21! \0034\002$bbonus\002\003 Blackjack Bonus $UnoPointsName"
  2095. incr bonus $bbonus
  2096. set isblackjack 1
  2097. }
  2098.  
  2099. # high score record
  2100. if {$cardtotals > $HighScore} {
  2101. unochanmsg "$cnick\003 broke the \002High Score Record\002 \00304$UnoBonus\003 bonus $UnoPointsName"
  2102. set UnoHigh "$winner $cardtotals"
  2103. incr bonus $UnoBonus
  2104. }
  2105.  
  2106. # played cards record
  2107. if {$CardStats(played) > $HighPlayed} {
  2108. unochanmsg "$cnick\003 broke the \002Most Cards Played Record\002 \00304$UnoBonus\003 bonus $UnoPointsName"
  2109. set UnoPlayed "$winner $CardStats(played)"
  2110. incr bonus $UnoBonus
  2111. }
  2112.  
  2113. # fast game record
  2114. if {($UnoTime < $FastRecord)&&($winner != $UnoRobot)} {
  2115. unochanmsg "$cnick\003 broke the \002Fast Game Record\002 \00304$UnoBonus\003 bonus $UnoPointsName"
  2116. incr bonus $UnoBonus
  2117. set UnoFast "$winner $UnoTime"
  2118. }
  2119. }
  2120.  
  2121. # win streak bonus
  2122. if {$winner == $UnoLastWinner} {
  2123. incr UnoWinsInARow
  2124. set RowMod [expr {$UnoWinsInARow %3}]
  2125. if {!$RowMod} {
  2126. set RowBonus [expr int((pow(2,($UnoWinsInARow/3)-1)*($UnoBonus/4)))]
  2127. unochanmsg "$cnick\003 has won \00314\002$UnoWinsInARow\002\003 in a row and earns \00304\002$RowBonus\002\003 bonus $UnoPointsName"
  2128. incr bonus $RowBonus
  2129. }
  2130. } {
  2131. if {($UnoLastWinner != "")&&($UnoWinsInARow > 1)} {
  2132. unochanmsg "$cnick\003 has put an end to \002$UnoLastWinner\'\s\002 streak of \002$UnoWinsInARow\002 wins"
  2133. }
  2134. set UnoLastWinner $winner
  2135. set UnoWinsInARow 1
  2136. }
  2137.  
  2138. # show winner
  2139. set msg "$cnick\003 wins \00314\002$cardtotals\002\003 $UnoPointsName by taking \00314\002$cardtake\002\003 cards"
  2140.  
  2141. # add bonus
  2142. if {$bonus} {
  2143. incr cardtotals $bonus
  2144. set needCFGWrite 1
  2145. append msg " total:\00303\002$cardtotals\002\003 $UnoPointsName"
  2146. }
  2147.  
  2148. unochanmsg "$msg"
  2149.  
  2150. # show game stats
  2151. unochanmsg "\00314$CardStats(played)\003 cards played in \00314[UnoDuration $UnoTime]\003"
  2152.  
  2153. # write scores
  2154. UnoUpdateScore $winner $cardtotals $isblackjack
  2155.  
  2156. # write records
  2157. if {$needCFGWrite} {UnoWriteCFG}
  2158.  
  2159. return
  2160. }
  2161.  
  2162. # reshuffle deck
  2163. proc UnoShuffle {cardsneeded} {
  2164. global UnoDeck DiscardPile
  2165.  
  2166. # no need in shuffling if more cards remain than needed
  2167. if {[llength $UnoDeck] >= $cardsneeded} { return }
  2168.  
  2169. unochanmsg "\0034\002Re-shuffling deck\002"
  2170.  
  2171. set DeckLeft 0
  2172. while {$DeckLeft < [llength $UnoDeck]} {
  2173. lappend DiscardPile [lindex $UnoDeck $DeckLeft]
  2174. incr DeckLeft
  2175. }
  2176.  
  2177. set UnoDeck ""
  2178. set NewDeckSize [llength $DiscardPile]
  2179.  
  2180. while {[llength $UnoDeck] != $NewDeckSize} {
  2181. set pcardnum [rand [llength $DiscardPile]]
  2182. set pcard [lindex $DiscardPile $pcardnum]
  2183. lappend UnoDeck $pcard
  2184. set DiscardPile [lreplace $DiscardPile $pcardnum $pcardnum]
  2185. }
  2186.  
  2187. return
  2188. }
  2189.  
  2190. # read config file
  2191. proc UnoReadCFG {} {
  2192. global UnoChan UnoCFGFile UnoLastMonthCards UnoLastMonthGames UnoPointsName UnoScoreFile UnoStopAfter UnoBonus
  2193. global UnoFast UnoHigh UnoPlayed UnoRecordHigh UnoRecordFast UnoRecordCard UnoRecordWins UnoRecordPlayed UnoWildDrawTwos UnoWDFAnyTime UnoAds
  2194.  
  2195. if {[file exist $UnoCFGFile]} {
  2196. set f [open $UnoCFGFile r]
  2197. while {[gets $f s] != -1} {
  2198. set kkey [string tolower [lindex [split $s "="] 0]]
  2199. set kval [lindex [split $s "="] 1]
  2200. switch $kkey {
  2201. channel {set UnoChan $kval}
  2202. points {set UnoPointsName $kval}
  2203. scorefile {set UnoScoreFile $kval}
  2204. stopafter {set UnoStopAfter $kval}
  2205. wilddrawtwos {set UnoWildDrawTwos $kval}
  2206. wdfanytime {set UnoWDFAnyTime $kval}
  2207. lastmonthcard1 {set UnoLastMonthCards(0) $kval}
  2208. lastmonthcard2 {set UnoLastMonthCards(1) $kval}
  2209. lastmonthcard3 {set UnoLastMonthCards(2) $kval}
  2210. lastmonthwins1 {set UnoLastMonthGames(0) $kval}
  2211. lastmonthwins2 {set UnoLastMonthGames(1) $kval}
  2212. lastmonthwins3 {set UnoLastMonthGames(2) $kval}
  2213. ads {set UnoAds $kval}
  2214. fast {set UnoFast $kval}
  2215. high {set UnoHigh $kval}
  2216. played {set UnoPlayed $kval}
  2217. bonus {set UnoBonus $kval}
  2218. recordhigh {set UnoRecordHigh $kval}
  2219. recordfast {set UnoRecordFast $kval}
  2220. recordcard {set UnoRecordCard $kval}
  2221. recordwins {set UnoRecordWins $kval}
  2222. recordplayed {set UnoRecordPlayed $kval}
  2223. }
  2224. }
  2225. close $f
  2226. if {$UnoStopAfter < 0} {set UnoStopAfter 0}
  2227. if {$UnoBonus <= 0} {set UnoBonus 100}
  2228. if {($UnoWildDrawTwos < 0)||($UnoWildDrawTwos > 1)} {set UnoWildDrawTwos 0}
  2229. if {($UnoAds < 0)||($UnoAds > 1)} {set UnoAds 1}
  2230. return
  2231. }
  2232. putcmdlog "\[Uno\] config file $UnoCFGFile not found... saving defaults"
  2233. UnoWriteCFG
  2234. return
  2235. }
  2236.  
  2237. # write config file
  2238. proc UnoWriteCFG {} {
  2239. global UnoChan UnoCFGFile UnoLastMonthCards UnoLastMonthGames UnoPointsName UnoScoreFile UnoStopAfter UnoBonus
  2240. global UnoFast UnoHigh UnoPlayed UnoRecordHigh UnoRecordFast UnoRecordCard UnoRecordWins UnoRecordPlayed UnoWildDrawTwos UnoWDFAnyTime UnoAds
  2241.  
  2242. set f [open $UnoCFGFile w]
  2243.  
  2244. puts $f "# This file is automatically overwritten"
  2245. puts $f "Channel=$UnoChan"
  2246. puts $f "Points=$UnoPointsName"
  2247. puts $f "ScoreFile=$UnoScoreFile"
  2248. puts $f "StopAfter=$UnoStopAfter"
  2249. puts $f "WildDrawTwos=$UnoWildDrawTwos"
  2250. puts $f "WDFAnyTime=$UnoWDFAnyTime"
  2251. puts $f "Ads=$UnoAds"
  2252. puts $f "LastMonthCard1=$UnoLastMonthCards(0)"
  2253. puts $f "LastMonthCard2=$UnoLastMonthCards(1)"
  2254. puts $f "LastMonthCard3=$UnoLastMonthCards(2)"
  2255. puts $f "LastMonthWins1=$UnoLastMonthGames(0)"
  2256. puts $f "LastMonthWins2=$UnoLastMonthGames(1)"
  2257. puts $f "LastMonthWins3=$UnoLastMonthGames(2)"
  2258. puts $f "Fast=$UnoFast"
  2259. puts $f "High=$UnoHigh"
  2260. puts $f "Played=$UnoPlayed"
  2261. puts $f "Bonus=$UnoBonus"
  2262. puts $f "RecordHigh=$UnoRecordHigh"
  2263. puts $f "RecordFast=$UnoRecordFast"
  2264. puts $f "RecordCard=$UnoRecordCard"
  2265. puts $f "RecordWins=$UnoRecordWins"
  2266. puts $f "RecordPlayed=$UnoRecordPlayed"
  2267.  
  2268. close $f
  2269. return
  2270. }
  2271.  
  2272. # score advertiser
  2273. proc UnoScoreAdvertise {} {
  2274. global UnoChan UnoAdNumber UnoRobot
  2275.  
  2276. switch $UnoAdNumber {
  2277. 0 {UnoTop10 1}
  2278. 1 {UnoLastMonthTop3 $UnoRobot none none $UnoChan 0}
  2279. 2 {UnoTop10 0}
  2280. 3 {UnoRecords $UnoRobot none none $UnoChan ""}
  2281. 4 {UnoTop10 2}
  2282. 5 {UnoPlayed $UnoRobot none none $UnoChan ""}
  2283. 6 {UnoHighScore $UnoRobot none none $UnoChan ""}
  2284. 7 {UnoTopFast $UnoRobot none none $UnoChan ""}
  2285. }
  2286.  
  2287. incr UnoAdNumber
  2288.  
  2289. if {$UnoAdNumber > 7} {set UnoAdNumber 0}
  2290.  
  2291. return
  2292. }
  2293.  
  2294. #
  2295. # misc utility functions
  2296. #
  2297.  
  2298. # sort cards in hand
  2299. proc uno_sorthand {playerhand} {
  2300. set uhand [lsort -dictionary $playerhand]
  2301. return $uhand
  2302. }
  2303.  
  2304. # color all cards in hand
  2305. proc uno_cardcolorall {cplayer} {
  2306. global UnoHand
  2307. set ccard ""
  2308. set ccount 0
  2309. set hcount [llength $UnoHand($cplayer)]
  2310. while {$ccount != $hcount} {
  2311. append ccard [uno_cardcolor [lindex $UnoHand($cplayer) $ccount]]
  2312. incr ccount
  2313. }
  2314. return $ccard
  2315. }
  2316.  
  2317. # color a single card
  2318. proc uno_cardcolor {pcard} {
  2319. global UnoRedCard UnoGreenCard UnoBlueCard UnoYellowCard UnoSkipCard UnoReverseCard UnoDrawTwoCard
  2320. global UnoWildCard UnoWildDrawFourCard
  2321. set c1 [string range $pcard 1 1]
  2322. switch [string range $pcard 0 0] {
  2323. "W" {
  2324. if {$c1 == "D"} {
  2325. set cCard $UnoWildDrawFourCard
  2326. } {
  2327. set cCard $UnoWildCard
  2328. }
  2329. return $cCard
  2330. }
  2331. "R" { set cCard $UnoRedCard }
  2332. "G" { set cCard $UnoGreenCard }
  2333. "B" { set cCard $UnoBlueCard }
  2334. "Y" { set cCard $UnoYellowCard }
  2335. default { set cCard "" }
  2336. }
  2337. switch $c1 {
  2338. "S" { append cCard $UnoSkipCard }
  2339. "R" { append cCard $UnoReverseCard }
  2340. "D" { append cCard $UnoDrawTwoCard }
  2341. default { append cCard "$c1 \003 " }
  2342. }
  2343. return $cCard
  2344. }
  2345.  
  2346. # check if player has uno
  2347. proc uno_checkuno {cplayer} {
  2348. global UnoHand
  2349. if {[llength $UnoHand($cplayer)] > 1} {return}
  2350. set has_uno "\002\00309H\00312a\00313s \00309U\00312n\00313o\00308! \002\003"
  2351. unomsg "\001ACTION says [unonik $cplayer] $has_uno\001"
  2352. return
  2353. }
  2354.  
  2355. # show player what cards they have
  2356. proc uno_showcards {cplayer cplayeridx} {
  2357. global UnoIDX
  2358. if {[uno_isrobot $cplayeridx]} {return}
  2359. unontc [lindex $UnoIDX $cplayeridx] "[uno_cardcolorall $cplayer]"
  2360. }
  2361.  
  2362. # check if this is the robot player
  2363. proc uno_isrobot {cplayeridx} {
  2364. global RoundRobin UnoRobot UnoMaxNickLen
  2365. if {[string range [lindex $RoundRobin $cplayeridx] 0 $UnoMaxNickLen] != $UnoRobot} {return 0}
  2366. return 1
  2367. }
  2368.  
  2369. # check if timer exists
  2370. proc uno_timerexists {cmd} {
  2371. foreach i [timers] {
  2372. if {![string compare $cmd [lindex $i 1]]} then {
  2373. return [lindex $i 2]
  2374. }
  2375. }
  2376. return
  2377. }
  2378.  
  2379. # sort scores
  2380. proc uno_sortscores {s1 s2} {
  2381. global unsortedscores
  2382. if {$unsortedscores($s1) < $unsortedscores($s2)} {return -1}
  2383. if {$unsortedscores($s1) == $unsortedscores($s2)} {return 0}
  2384. if {$unsortedscores($s1) > $unsortedscores($s2)} {return 1}
  2385. }
  2386.  
  2387. # calculate game running time
  2388. proc uno_gametime {} {
  2389. global UnoStartTime
  2390. set UnoCurrentTime [unixtime]
  2391. set gt [expr ($UnoCurrentTime - $UnoStartTime)]
  2392. return $gt
  2393. }
  2394.  
  2395. # colorize nickname
  2396. proc unonik {nick} {
  2397. global UnoNickColor
  2398. return "\003$UnoNickColor($nick)$nick"
  2399. }
  2400. proc unocolornick {pnum} {
  2401. global UnoNickColors
  2402. set c [lindex $UnoNickColors [expr $pnum-1]]
  2403. set nik [format "%02d" $c]
  2404. return $nik
  2405. }
  2406.  
  2407. # ratio of two numbers
  2408. proc unoget_ratio {num den} {
  2409. set n 0.0
  2410. set d 0.0
  2411. set n [expr $n +$num]
  2412. set d [expr $d +$den]
  2413. if {!$d} {return 0}
  2414. set ratio [expr (($n /$d) *100.0)]
  2415. return $ratio
  2416. }
  2417.  
  2418. # name of last month
  2419. proc UnoLastMonthName {month} {
  2420. switch $month {
  2421. 00 {return "Dec"}
  2422. 01 {return "Jan"}
  2423. 02 {return "Feb"}
  2424. 03 {return "Mar"}
  2425. 04 {return "Apr"}
  2426. 05 {return "May"}
  2427. 06 {return "Jun"}
  2428. 07 {return "Jul"}
  2429. 08 {return "Aug"}
  2430. 09 {return "Sep"}
  2431. 10 {return "Oct"}
  2432. 11 {return "Nov"}
  2433. default {return "???"}
  2434. }
  2435. }
  2436.  
  2437. # pad a string with spaces
  2438. proc unostrpad {str len} {
  2439. set slen [string length $str]
  2440. if {$slen > $len} {return $str}
  2441. while {$slen < $len} {
  2442. append str " "
  2443. incr slen
  2444. }
  2445. return $str
  2446. }
  2447.  
  2448. # time interval in min and sec
  2449. proc UnoDuration {sec} {
  2450. set s ""
  2451. if {$sec >= 3600} {
  2452. set tmp [expr $sec / 3600]
  2453. set s [format "%s\002%d\002h:" $s $tmp]
  2454. set sec [expr $sec - ($tmp*3600)]
  2455. }
  2456. if {$sec >= 60} {
  2457. set tmp [expr $sec / 60]
  2458. set s [format "%s\002%d\002m:" $s $tmp]
  2459. set sec [expr $sec - ($tmp*60)]
  2460. }
  2461. if {$sec > 0} {
  2462. set tmp $sec
  2463. set s [format "%s\002%d\002s" $s $tmp]
  2464. }
  2465. return $s
  2466. }
  2467.  
  2468. #
  2469. # game messages
  2470. #
  2471.  
  2472. # played card
  2473. proc uno_showplaycard {who crd nplayer} {
  2474. unomsg "[unonik $who]\003 plays $crd \003to [unonik $nplayer]"
  2475. }
  2476.  
  2477. # played draw card
  2478. proc uno_showplaydraw {who crd dplayer nplayer} {
  2479. unomsg "[unonik $who]\003 plays $crd [unonik $dplayer]\003 draws \002two cards\002 and skips to [unonik $nplayer]"
  2480. }
  2481.  
  2482. # played wild card
  2483. proc uno_showplaywild {who chooser} {
  2484. global UnoWildCard
  2485. unomsg "[unonik $who]\003 plays $UnoWildCard choose a color [unonik $chooser]"
  2486. }
  2487.  
  2488. # played wild draw four
  2489. proc uno_showplaywildfour {who skipper chooser} {
  2490. global UnoWildDrawFourCard
  2491. unomsg "[unonik $who]\003 plays $UnoWildDrawFourCard [unonik $skipper]\003 draws \002four cards\002 and is skipped... Choose a color [unonik $chooser]"
  2492. }
  2493.  
  2494. # played skip card
  2495. proc uno_showplayskip {who crd skipper nplayer} {
  2496. unomsg "[unonik $who]\003 plays $crd\003 and skips [unonik $skipper]\003 to [unonik $nplayer]"
  2497. }
  2498.  
  2499. # who drew a card
  2500. proc uno_showwhodrew {who} {
  2501. unomsg "[unonik $who]\003 \002drew\002 a card"
  2502. }
  2503.  
  2504. # player passes a turn
  2505. proc uno_showplaypass {who nplayer} {
  2506. unomsg "[unonik $who]\003 \002passes\002 to [unonik $nplayer]"
  2507. }
  2508.  
  2509. # bot plays wild card
  2510. proc uno_showbotplaywild {who chooser ncolr nplayer} {
  2511. global UnoWildCard
  2512. unomsg "[unonik $who]\003 plays $UnoWildCard and chooses $ncolr \003 Current player [unonik $nplayer]"
  2513. }
  2514.  
  2515. # bot plays wild draw four
  2516. proc uno_showbotplaywildfour {who skipper chooser choice nplayer} {
  2517. global UnoWildDrawFourCard
  2518. unomsg "[unonik $who]\003 plays $UnoWildDrawFourCard [unonik $skipper]\003 draws \002four cards\002 and is skipped. [unonik $chooser]\003 chooses $choice\003 Current player [unonik $nplayer]"
  2519. }
  2520.  
  2521. # show a player what they drew
  2522. proc uno_showdraw {idx crd} {
  2523. global UnoIDX
  2524. if {[uno_isrobot $idx]} {return}
  2525. unontc [lindex $UnoIDX $idx] "Draw $crd"
  2526. }
  2527.  
  2528. # show win
  2529. proc uno_showwin {who crd} {
  2530. global UnoLogo
  2531. unomsg "[unonik $who]\003 plays $crd and \002\00309W\00312i\00313n\00308s\002 $UnoLogo"
  2532. }
  2533.  
  2534. # show win by default
  2535. proc uno_showwindefault {who} {
  2536. global UnoWinDefault UnoLogo
  2537. unomsg "[unonik $who] \002\00309W\00312i\00313n\00308s $UnoLogo \002by default"
  2538. set UnoWinDefault 1
  2539. }
  2540.  
  2541.  
  2542. #
  2543. # channel and dcc output
  2544. #
  2545.  
  2546. proc unomsg {what} {
  2547. global UnoChan
  2548. putquick "PRIVMSG $UnoChan :$what"
  2549. }
  2550.  
  2551. proc unochanmsg {what} {
  2552. global UnoChan UnoLogo
  2553. putquick "PRIVMSG $UnoChan :$UnoLogo $what"
  2554. }
  2555.  
  2556. proc unogntc {who what} {
  2557. global UnoNTC
  2558. putquick "$UnoNTC $who :$what"
  2559. }
  2560.  
  2561. proc unontc {who what} {
  2562. global UnoNTC UnoDCCIDX
  2563. if {$UnoDCCIDX($who) != -1} {
  2564. putdcc $UnoDCCIDX($who) $what
  2565. } {
  2566. putquick "$UnoNTC $who :$what"
  2567. }
  2568. }
  2569.  
  2570. proc unolog {who what} {
  2571. putcmdlog "\[$who\] $what"
  2572. }
  2573.  
  2574. #
  2575. # dcc routines
  2576. #
  2577.  
  2578. proc unologin:dcc {hand idx} {
  2579. global UnoChan UnoOn UnoDCCIDX RoundRobin
  2580.  
  2581. if ![handonchan $hand $UnoChan] {return 0}
  2582.  
  2583. set tnick [hand2nick $hand $UnoChan]
  2584. if {($tnick == "")||($tnick == "*")} {return 0}
  2585. if ![info exist UnoDCCIDX($tnick)] {return 0}
  2586.  
  2587. set pcount 0
  2588. while {[lindex $RoundRobin $pcount] != ""} {
  2589. set pnick [lindex $RoundRobin $pcount]
  2590. if {$pnick == $tnick} {
  2591. if {[info exist UnoDCCIDX($pnick)]} {
  2592. set UnoDCCIDX($pnick) $idx
  2593. unolog "Uno" "$pnick on new dcc socket $idx"
  2594. break
  2595. }
  2596. }
  2597. incr pcount
  2598. }
  2599. return 0
  2600. }
  2601.  
  2602. proc unologout:dcc {hand idx} {
  2603. global UnoChan UnoDCCIDX party-chan party-just-quit
  2604. if {[info exists party-just-quit] && ${party-just-quit} == $hand} {unset party-just-quit ; return 0}
  2605. if ![handonchan $hand $UnoChan] {return 0}
  2606. set tnick [hand2nick $hand $UnoChan]
  2607. if {($tnick == "")||($tnick == "*")} {return 0}
  2608. if {[info exist UnoDCCIDX($tnick)]} {
  2609. unolog "Uno" "$tnick left dcc \(resuming channel message mode\)"
  2610. set UnoDCCIDX($tnick) -1
  2611. }
  2612. }
  2613.  
  2614. proc unologout:filt {idx text} {
  2615. global UnoChan UnoDCCIDX party-chan party-just-quit
  2616. set hand [idx2hand $idx]
  2617. set party-just-quit $hand
  2618. set tnick [hand2nick $hand]
  2619. if {($tnick == "")||($tnick == "*")} {return $text}
  2620. if {[info exist UnoDCCIDX($tnick)]} {
  2621. unolog "Uno" "$tnick left dcc \(resuming channel message mode\)"
  2622. set UnoDCCIDX($tnick) -1
  2623. }
  2624. return $text
  2625. }
  2626.  
  2627. # show all players cards
  2628. proc dccunohands {hand idx txt} {
  2629. global UnoHand RoundRobin
  2630. set n 0
  2631. while {$n != [llength $RoundRobin]} {
  2632. set un [lindex $RoundRobin $n]
  2633. unolog $un [uno_sorthand $UnoHand($un)]
  2634. incr n
  2635. }
  2636. }
  2637.  
  2638. # write configuration
  2639. proc dcc_unowriteconfig {hand idx txt} {
  2640. unolog "$hand" "writing current uno config"
  2641. UnoWriteCFG
  2642. return
  2643. }
  2644.  
  2645. # rehash configuration
  2646. proc dcc_unorehash {hand idx txt} {
  2647. unolog "$hand" "rehashing uno config"
  2648. UnoReadCFG
  2649. return
  2650. }
  2651.  
  2652. # set points name
  2653. proc dcc_unopoints {hand idx txt} {
  2654. global UnoPointsName
  2655. set pn [string trim $txt]
  2656. if {[string length $pn] > 2} {
  2657. set UnoPointsName $pn
  2658. unolog "$hand" "uno points set to: $UnoPointsName"
  2659. }
  2660. return
  2661. }
  2662.  
  2663. UnoReadCFG
  2664.  
  2665. UnoReadScores
  2666.  
  2667. putlog "Loaded Color Uno $UnoVersion Copyright (C) 2004-2011 by #World-Chat Team"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement