#########################   ACROMANIA v1.1.4   ###############################
##
## Here is the latest release of something I was told that if I didn't make,
## the ppl in #bor would annoy me until I did (oweff!! ;P). Plus dh asked me
## to.
## It works for sure with Eggdrop and it works 100% with BitchX+tcl. There is
## also a special version for bX DCC networks, look for "acronet"...
## Please tell me of any bugs or any suggestions u may have.... Read thru 
## the script and make changes as you wish. (Most of the init_acro proc is
## customizable).
##
##  -- |By-Tor|@EFNet
##
##  SPECIAL NOTE!!!! If you want a copy of this, DONT ASK ME just get it from
##  my CDCC/XDCC list.
##
## Greetz to (in NO particular order) dh, hammz, scoop, hammz, oweff, shewp
## Phucilage, ice-man, sideshow, BlackJac, fudd, sX, shade, psykotyk, MHacker,
## macker, |Fingers|, and anyone else I'm forgetting (let me know)
##
## And all you little people (Yah, mr_bill is a `little people').
##
## Oh, and Kaitlin, the most wonderfulest oper of all (aol, bahahaha)
##
## Special (non-sexual) greets to Robey for Eggdrop and the devel-team for
## keeping it going. Also panasync for the (TCL) BitchX...
##
## WEWP, have fun and remember that Microsoft(c) is evil!

set scorefile ".acro.score"
set webscore "/home/staff/rain/public_html/acro.html"
if {![info exists acro(noreset)]} {
	set round 0
}
proc init_acro { } {
	global acro
	if {[info exists acro(force)]} {
		set save $acro(force)
	}

	if [info exists acro] { unset acro }
	if [info exists vote] { unset vote }

	if {[info exists save]} {
		set acro(force) $save
	}

	set acro(progress) 0
	set acro(min) 3;             # Minimum number of letters per acronym
	set acro(max) 6;             # Max number of letters per acronym
	set acro(rounds) 10;         # Number of rounds to play
	set acro(maxlen) 15;         # Max length of each word, to prevent crap like
	                             # YOURMOTHERISAPIECEOFCRAP as a word...

	set acro(nym) ""
	set acro(chan) ""
	set acro(players) 0;
	set acro(maxpl) 10;          # Max number of players per game
	set acro(minpl) 2;           # Minimum number of players per game
	set acro(nicks) "";
	set acro(extend) 3;          # Max number of 30 second extensions
	set acro(extended) 0;
	set acro(top) 10;            # Show the top XX names for the scores

	set acro(noreset) 1
}

proc read_score { } {
	global score scorefile
	if [info exists score] { unset score }
	if {([info exists scorefile]) && ([file exists $scorefile])} {
		set f [open $scorefile r]
		while {![eof $f]} {
			set s [gets $f]
			if {[llength $s] == 2} { set score([lindex $s 0]) [lindex $s 1] }
		}
		close $f
	}
}

proc write_score { } {
	global score scorefile webscore
	set f [open $scorefile w]
	foreach s [lsort -decreasing -command sort_score [array names score]] {
		if {$score($s) != 0} {
			puts $f "$s $score($s)"
		}
	}
	close $f
	if {$webscore != ""} {
		set f [open $webscore w]
		puts $f "<HTML><HEAD><TITLE>Current Acromania standings as of [clock format [clock seconds] -format {%c %Z}]</TITLE>"
		puts $f "<TABLE BORDER=4 WIDTH=80%>"
		puts $f "<TR ALIGN=center><TH ALIGN=center>Nick</TH><TD>Score</TD></TR>"
		foreach s [lsort -decreasing -command sort_score [array names score]] {
			if {$score($s) != 0} {
				puts $f "<TR ALIGN=center><TH ALIGN=center>$s</TH><TD>$score($s)</TD></TR>"
			}
		}
		puts $f "</TABLE></HTML>"
		close $f
	}
}

proc sort_score {s1 s2} {
	global score
	if {$score($s1) > $score($s2)} { return 1 }
	if {$score($s1) < $score($s2)} { return -1 }
	if {$score($s1) == $score($s2)} { return 0 }
}

proc sort_games {s1 s2} {
	global gamescore
	if {$gamescore($s1) > $gamescore($s2)} { return 1 }
	if {$gamescore($s1) < $gamescore($s2)} { return -1 }
	if {$gamescore($s1) == $gamescore($s2)} { return 0 }
}

if {![info exists acro(noreset)]} {
	foreach t [utimers] {	if [string match *acro* [lindex $t 1]] { killutimer [lindex $t end] } }
	 
	init_acro
	if [file exists $scorefile] { read_score }
	set letters "ABCDEFGHIJKLMNOPRSTUVWY"
}

if [string match *BitchX* $version] {
	bind pub -1 start start_acro
	set botnick $nick
} { bind pub - !acro-start start_acro }

proc start_acro { n u h c a } {
	global acro botnick round
	if { $acro(progress) != 0 } { putserv "notice $n :Game already in progress, sorry... Current puzzle is $acro(nym)" ; return 0 }
	if {[llength [chanlist $c]] < $acro(minpl)} { putserv "notice $n :Not enough players present. Minimum players required is $acro(minpl)" ; return 0 }
	init_acro
	set acro(progress) 1
	if {$round >= $acro(rounds)} { set round 0 }
	incr round
	putserv "privmsg $c :Round $round\($acro(rounds)\)"
	putserv "privmsg $c :The acronym for this round is [make_acro]. You have 90 seconds."
	putserv "privmsg $c :/msg $botnick acro <your answer>. Good luck!"
	set acro(chan) $c
	utimer 45 "warn_acro $c"
}

if [string match *BitchX* $version] {
#	bind pub 90 stop stop_acro; REMOVED BECAUSE OF ABUSE (NOVALOGIC YOU SLUT)
} { bind pub m !acro-stop stop_acro }

proc stop_acro { n u h c a } {
	init_acro
	foreach t [utimers] {	if [string match *acro* [lindex $t 1]] { killutimer [lindex $t end] } }	
}

if [string match *BitchX* $version] {
	bind msg -1 acro msg_acro
} { bind msg - acro msg_acro }

proc msg_acro { n u h a } {
	global botnick acro
	set u [string tolower $u]
	regsub -nocase -all \[{}] $a "" a

	if {![onchan $n $acro(chan)]} {
		putserv "notice $n :You are not on the channel where the game is taking place."
		return 0
	}

	if {$acro(progress) == 1} {
		if {([llength $a] != [string length $acro(nym)]) || ([string length [join $a ""]] == [string length $acro(nym)]) } { putserv "notice $n :Invalid Acronym" ; return 0 }
		regsub -nocase -all {[0-9]} $a "" tempa
		foreach el $a {
			if {[string length $el] > $acro(maxlen)} { putserv "notice $n :\"$el\" is too long." ; return 0 }
		}
		if {[info exists acro($u)]} {
			if {$a == [lrange $acro($u) 2 end]} {
				putserv "notice $n :Your answer is already \"$a\""
				return 0
			}
			if {[lindex $acro($u) 1] == 0} {
				putserv "notice $n :You have already submitted an answer. Submit once more to change."
				set acro($u) "$n {$a} [lrange $acro($u) 2 end]"
				return 0
			}
			if {[lindex $acro($u) 1] == $a} {
				putserv "notice $n :Your answer has been changed to \"$a\""
				putlog "!$n! acro \[something\]"
				set acro($u) "$n 0 $a"
				return 0
			}
			putserv "notice $n :You have already submitted an answer. Submit once more to change."
			set acro($u) "$n {$a} [lrange $acro($u) 2 end]"
			return 0
		}
		if {$acro(players) >= $acro(maxpl)} {
			putserv "notice $n :Maximum players reached, please try again later."
			return 0
		}
		for { set r 0 } { $r <= [string length $acro(nym)] } { incr r } {
			if ![string match [string index $acro(nym) $r] [string toupper [string index [lindex $a $r] 0]]] {
				putserv "notice $n :Invalid Acronym"
				return 0
			}
		}
		putserv "notice $n :Answer set to \"$a\""
		putlog "!$n! acro \[something\]"
		set acro($u) "$n 0 $a"
		incr acro(players)
		putserv "notice $n :You are player #$acro(players)"
	}
	if {$acro(progress) == 2} {
		global vote

		if {![onchan $n $acro(chan)]} {
			putserv "notice $n :You are not on the channel where the game is taking place."
			return 0
		}
		if {[lsearch $vote(voters) $u] != -1} {
			putserv "notice $n :You already voted"
			return 0
		}
		set a [lindex $a 0]
		if ![info exists vote($a)] { 
			putserv "notice $n :No such answer."
			return 0
		}
		if {$n == [lindex $vote($a) 0]} {
			putserv "notice $n :You can't vote for yourself, stupid."
			return 0
		}
		set vote($a) "[lindex $vote($a) 0] [expr {[lindex $vote($a) 1] + 1}]"
		putserv "notice $n :Your vote has been recorded..."
		putlog "!$n! acro (vote) \[something\]"
		lappend vote(voters) $u
	}
}
proc force_acro {hand idx arg} {
	global acro
	set acro(force) $arg
}

bind dcc "|n #lb" force-acro force_acro

proc make_acro { } {
	global acro letters

	if {[info exists acro(force)]} {
		set acro(nym) $acro(force)
		unset acro(force)
		return $acro(nym)
	} else {
		set r [expr [rand [expr {$acro(max) - $acro(min) + 1}]] + $acro(min)]
		while { [string length $acro(nym)] < $r } {
			append acro(nym) [string index $letters [rand [string length $letters]]]
		}
		return $acro(nym)
	}
}

proc warn_acro { c } {

	global acro
	utimer 45 "end_acro $c"
	putserv "privmsg $c :(acro) 45 Seconds!"
}

proc end_acro { c } {
	global acro botnick vote
	if {$acro(players) < $acro(minpl)} {
		if {$acro(extended) >= $acro(extend)} {	putserv "privmsg $c :Not enough players and maximum deadline extensions reached. Ending game..." ; init_acro ; set rount 0 ; return }
		putserv "privmsg $c :Not enough players, extending deadline 45 seconds..."
		incr acro(extended)
		utimer 45 "end_acro $c"
		return 0
	}
	set acro(progress) 2
	if [info exists vote] { unset vote }
	set vote(voters) ""
	putserv "privmsg $c :Time expired, lets vote!"
	set n 1
	foreach g [array names acro] {
		if {[llength $acro($g)] > 1} {
			putserv "privmsg $c :$n: [lrange $acro($g) 2 end]"
			set vote($n) "[lindex $acro($g) 0] 0"
			incr n
		}
	}
	putserv "privmsg $c :/msg $botnick \"acro #\" to vote"
	utimer 30 "warn_vote $c"
}

proc warn_vote { c } {
	putserv "privmsg $c :(acro) 30 seconds left to vote..."
	utimer 30 "end_vote $c"
}

proc end_vote { c } {
	global acro score vote gamescore round
	putserv "privmsg $c :Voting complete..."
	set vote(novotes) ""
	foreach e [array names acro] {
		if {[llength $acro($e)] > 1} {
			# gave acro
			if {[lsearch $vote(voters) $e] == -1} {
				lappend vote(novotes) [lindex $acro($e) 0]
			}
		}
	}
	if {$vote(novotes) != ""} {
		putserv "privmsg $c :The following people gave acros but didn't vote: $vote(novotes)"
#testing: non-voters: $vote(novotes)"
	}
	set acro(progress) 0
	foreach e [array names vote] {
		if {$e == "voters" || $e == "novotes"} { continue }
		if {![info exists score([lindex $vote($e) 0])]} {
			set score([lindex $vote($e) 0]) [lindex $vote($e) 1]
		} {
			set score([lindex $vote($e) 0]) [expr {[lindex $vote($e) 1] + $score([lindex $vote($e) 0])}]
		}
		if {![info exists gamescore([lindex $vote($e) 0])]} {
			set oldscore([lindex $vote($e) 0]) 0
			set gamescore([lindex $vote($e) 0]) [lindex $vote($e) 1]
		} {
			set oldscore([lindex $vote($e) 0]) $gamescore([lindex $vote($e) 0])
			set gamescore([lindex $vote($e) 0]) [expr {[lindex $vote($e) 1] + $gamescore([lindex $vote($e) 0])}]
		}
	}
	write_score
	if {$round >= $acro(rounds)} {
		putserv "privmsg $c :Game over, tallying final scores..."
		putserv "privmsg $c :     Game Totals                Grand Totals  "
		putserv "privmsg $c :--= Nick =---= Score =--   --= Nick =---= Score =--"
		set grandlist [lsort -decreasing -command sort_score [array names score]]
		set gamelist [lsort -decreasing -command sort_games [array names gamescore]]
		if {[set top [llength $grandlist]] > [llength $gamelist]} { set top [llength $gamelist] }
		if {$acro(top) < $top} { set top $acro(top) }
		for { set s 0 } { $s < $top } { incr s } {
			if {[info exists line]} { unset line }
			if {$gamescore([lindex $gamelist $s]) != 0} {
				set line "privmsg $c :  [c 9 [lindex $gamelist $s]]   [c 7 $gamescore([lindex $gamelist $s])]"
			}
			if {$score([lindex $gamelist $s]) != 0} {
				if {[info exists line]} {
					append line "        [c 9 [lindex $grandlist $s]]   [c 7 $score([lindex $grandlist $s])]"
				} {
					set line "privmsg $c :                             [c 9 [lindex $grandlist $s]]   [c 7 $score([lindex $grandlist $s])]"
				}
			}
			if {[info exists line]} { putserv $line }
		}
		init_acro
		unset gamescore
		set round 0
	} {
		putserv "privmsg $c :Score totals as of round $round:"
		putserv "privmsg $c :--= Nick =---= Score =---= Inc =--"
		set scorelist [lsort -decreasing -command sort_games [array names gamescore]]
		if {$acro(top) < [llength $scorelist]} { set top $acro(top) } { set top [llength $scorelist] }
		for { set s 0 } { $s < $top } { incr s } {
			if {[lindex $scorelist $s] == ""} {continue}
			if {$gamescore([lindex $scorelist $s]) != 0} {
				if {[info exists oldscore([lindex $scorelist $s])]} {
					set plus [expr {$gamescore([lindex $scorelist $s]) - $oldscore([lindex $scorelist $s])}]
				} {
					set plus 0
				}
				putserv "privmsg $c :  [c 9 [lindex $scorelist $s]]   [c 7 $gamescore([lindex $scorelist $s])]      [c 5 "+$plus"]"
			}
		}
		start_acro blah blah blah $c ""
	}
}

proc c { c t } {
	set h [expr $c/2 - [string length $t]/2]
	for { set r 0 ; set s "" } {$r < $h} { incr r } { append s " " }
	set l [expr $c - [string length $t] - [string length $s]]
	for { set r 0 ; set v "" } {$r < $l} { incr r } { append v " " }
	return [append s $t $v]
}

if [string match *BitchX* $version] {
	bind pub -1 help acro_help
	} { bind pub - !acro-help acro_help }

proc acro_help { n u h c a } {
	putserv "NOTICE $n :Acromania 1.1b for EggDrop and BitchX by |By-Tor|"
  putserv "NOTICE $n :To start a game, or continue a the game in progress, simply type \"start\" in the channel"
  putserv "NOTICE $n :To submit a puzzle, you MUST prefix it with the word \"acro\"."
  putserv "NOTICE $n :Otherwise it could interfere with normal bot operations. The same applies for voting."
	putserv "NOTICE $n :Typing \"scores\" in the channel will retrieve a score list"
	putserv "NOTICE $n :Thank you for playing, and enjoy yourself!"
}

if [string match *BitchX* $version] {
	bind pub -1 scores acro_scores
	} { bind pub - !acro-score acro_scores }

proc acro_scores { n u h c a } {
	global score
	putserv "notice $n :--= Nick =---= Score =--"
	set scorelist [lsort -decreasing -command sort_score [array names score]]
	for { set s 0 } { $s < [llength $scorelist] } { incr s } {
		if {$score([lindex $scorelist $s]) != 0} {
			putserv "notice $n :[c 13 [lindex $scorelist $s]] [c 7 $score([lindex $scorelist $s])]"
		}
	}
}	

# If acro crashes on you, run this and send me the file along with the error
# message...

proc dump_acro {} {
	global score acro gamescore round vote
	set f [open acrodump w+]
	puts $f "round $round"
	if {[info exists score]} {
		puts $f "--- score output ---"
		foreach el [array names score] {
			puts $f "$el $score($el"
		}
	}
	if {[info exists gamescore]} {
		puts $f "--- gamescore output ---"
		foreach el [array names gamescore] {
			puts $f "$el $gamescore($el"
		}
	}
	if {[info exists vote]} {
		puts $f "--- vote output ---"
		foreach el [array names vote] {
			puts $f "$el $vote($el"
		}
	}
	if {[info exists acro]} {
		puts $f "--- acro output ---"
		foreach el [array names acro] {
			puts $f "$el $acro($el"
		}
	}
	close $f
}
#if {[info exists acro(noreset)]} {
#	unset acro(noreset)
#}
# Microsoft is a registered trademark of the Evil Empire, er I mean Microsoft
