| View previous topic :: View next topic |
| Author |
Message |
Ian-Highlander Op
Joined: 24 Sep 2001 Posts: 165 Location: Ely, Cambridgeshire
|
Posted: Mon Aug 08, 2005 8:42 am Post subject: |
|
|
Ok, I'm having another problem that no doubt is something really simple again. Whilst TCL is coming back to me bit by bit there are large gaps still in my basic knowledge which are causing me issues.
I'm working on the new major rebuild of this script and one of the functions (which I've got working perfectly apart from this exception) is that instead of having to issue the command !start for each question you can now issue !start ** (where ** represents the number of questions you want in the round) up to a max number of questions preconfigured in the script and also configurable with a public command. Its one of the most commonly requested updates people email me about constantly. Anyway I've got it working for the most part, there is now a public command that picks up the number of questions requested, checks it against the maximum number configured and then starts a counter, the questions then start and off it goes. I've got it working for two out of three scenarios so far, if you get the answer right and its your first ever win and if you get it right and you've won before (different parts of a proc for each so the code to return to the counter proc was required in both places).
The issue I'm having is that when no one gets the answer right there is a utimer that kicks in and sends it to another proc which basically was designed to tell them they didnt get it right and reset all functions, stopping the game. As nobody got it right, it didnt need to know any of the normal variables (nick uhost hand chan) so they quite rightly aren't declared at the beginning of the proc. Here's the issue, because the other procs (the counter and the main game start code require those variables, the no_answer proc isnt passing all the information back to them and the script errors out. If I add the variables to the code it simply gives the usual, null value for x error and errors out again. I cant for the life of me (and no doubt its simple) get it to return to the counter proc with the right information for the counter to carry on the round and start asking questions again.
Here's the relevant pieces of code, can someone show this silly old fool what he's doing wrong please.
This is part of the new code that checks if this is a multiple question round or not and plays the game accordingly by running "start_game".
| Code: | #Are we playing more than one question at a time and is it within the maximum set in the config at the top?
proc start_game_check {nick uhost handle channel args} {
global questtoask maxquesttoask
set questtoask [lindex $args 0]
if {$questtoask == ""} {
start_game $nick $uhost $handle $channel
} else {
if {$questtoask > $maxquesttoask} {
putserv "PRIVMSG $channel :Sorry\002\ $nick\002 the maximum number of questions per round is set to\002\ $maxquesttoask\002, please retry."
return 0
}
count_questions $nick $uhost $handle $channel
}
}
#Procedure to keep count of and track the number of questions asked in a round.
proc count_questions {nick uhost handle channel args} {
global questtoask questannounce
if {$questtoask == ""} {
return 0
} else {
if {$questtoask == "0"} {
putserv "PRIVMSG $channel :That is the end of the current round."
set questtoask ""
return 0
} else {
if {($questannounce == "1") && ($questtoask == "1")} {
putserv "PRIVMSG $channel :This is the last question in this round"
set questtoask [expr $questtoask-1]
} elseif {($questannounce == "1") && ($questtoask > "1")} {
putserv "PRIVMSG $channel :There are $questtoask questions left in this round"
set questtoask [expr $questtoask-1]
} else {
set questtoask ""
set gameplaying "0"
return 0
}
start_game $nick $uhost $handle $channel
}
}
} |
This is the part of the code that generates the question, waits for the answer and has the timer in it for the "no_answer" proc.
| Code: | set ques_pair [lindex $quest $questionno]
set puzzle [lindex [split $ques_pair :] 1]
set answer [lindex [split $::ques_pair :] 0]
#DEBUG LINE - SHOWS ANSWER BEFORE QUESTION FOR TESTING PURPOSES ONLY
putserv "PRIVMSG $chan :DEBUG - $answer"
bind pubm -|- * answercheck
putserv "PRIVMSG $chan :Question.......\00304$puzzle"
incr questionno
utimer 25 no_answer
setuser $player XTRA wcount.$chan $questionno |
The code that checks the answer and passes it to the "winner" proc if its right.
| Code: | proc answercheck {nick uhost handle channel arg} {
global answer
if {[string equal -nocase $answer $arg]} {
winner $nick $uhost $handle $channel
}
return
} |
The code that reacts if its the users first ever win (the user adding code has already run at this point) The important new line is the last one which sends it back to the counter and keeps the game playing. There is a similar addition to the code for if you have won before.
| Code: | set chan $gamechan
putserv "PRIVMSG $chan :$nick this is your first ever win!!!...\00304Now try and win again!"
set score [lappend score $handle]
set score [lappend score 1]
set score [lappend score 1]
set fd [open $scores w]
foreach line $score {
puts $fd $line
}
close $fd
set gameplaying 0
set chan ""
count_questions $nick $uhost $handle $channel |
The proc that is invoked if the right answer isnt given in the time specified in the utimer above. Checks if it's supposed to tell the channel the answer or not (another new function in the new version of the script) and stops the game. As shown at the bottom I tried just sending it back to count_questions using the same line of code, however it fails because the variables arent declared in the proc. If I declare them it fails because they are null. There has to be another way of doing it but I cant for the life of me see what or where and have been staring at it solidly for three days now.
| Code: | #If no one gets it right within the alloted time, stop game and reset.
proc no_answer {} {
global gameplaying answer chan gamechan questtoask giveanswer
set chan $gamechan
if {$giveanswer == "0"} {
putserv "PRIVMSG $chan :No body got it right!!.....\00304Try Again!!"
}
if {$giveanswer == "1"} {
putserv "PRIVMSG $chan :No body got it right!!.....The answer was \00304$answer"
}
kill_timers
unbind pubm -|- * answercheck
set gameplaying 0
set chan ""
count_questions $nick $uhost $handle $channel
return 0
} |
Once again guys, any help is hugely appreciated, this is another niggly little thing that is driving me insane again. I'm having nightmares about this code now  _________________ "Insanity Takes Its Toll, Please Have Exact Change" |
|
| Back to top |
|
 |
demond Revered One

Joined: 12 Jun 2004 Posts: 3073 Location: San Francisco, CA
|
Posted: Mon Aug 08, 2005 12:01 pm Post subject: |
|
|
generally, you have 2 options: either use global variables to save what you will need in other procs (for example, the channel), or pass the necessary info as parameters, in which case for [utimer] you need to use:
| Code: |
utimer 25 [list no_answer $nick $uhost $handle $channel]
|
|
|
| Back to top |
|
 |
Ian-Highlander Op
Joined: 24 Sep 2001 Posts: 165 Location: Ely, Cambridgeshire
|
Posted: Mon Aug 08, 2005 12:14 pm Post subject: |
|
|
| demond wrote: | generally, you have 2 options: either use global variables to save what you will need in other procs (for example, the channel), or pass the necessary info as parameters, in which case for [utimer] you need to use:
| Code: |
utimer 25 [list no_answer $nick $uhost $handle $channel]
|
|
Ahhhhhhhhhhhhhhhhhhhhhhh, that could be exactly what I was looking for, I'd tried
| Code: | | utimer 25 no_answer $nick $uhost $handle $channel |
as a last ditch effort without the braces which quite rightly failed but if enclosing them in braces as a list works, that should hopefully solve my problem. I'll be back later  _________________ "Insanity Takes Its Toll, Please Have Exact Change" |
|
| Back to top |
|
 |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
Posted: Mon Aug 08, 2005 12:51 pm Post subject: |
|
|
Using braces instead of [list] will not return the values of the variables inside the braces, so use what demond suggested:
| Code: | | utimer 25 [list no_answer $nick $uhost $handle $channel] |
_________________ Follow me on GitHub
- Opposing
Public Tcl scripts |
|
| Back to top |
|
 |
Ian-Highlander Op
Joined: 24 Sep 2001 Posts: 165 Location: Ely, Cambridgeshire
|
Posted: Mon Aug 08, 2005 5:07 pm Post subject: |
|
|
Ok, that's worked apart from one silly thing that for some reason I cant find. The kill_timers proc no longer works and as a result the game isnt being stopped correctly and causing all sorts of weird things to happen.
I've proved this after a lot of chasing my own tail round and round by a few additional debugs to list the timers that are running before and after and they're the same.
The code above solved my last problem but has caused this one an example of what the utimer is now listed as when the game is running is:
My normal code to kill "all" timers (there is only ever one) is:
| Code: | # Kill all timers.
proc kill_timers {} {
global chan
foreach j [utimers] {
if {[lindex $j 1] == "no_answer"} {
killutimer [lindex $j 2]
}
}
return 0
} |
But because of the above, this no longer catches the timer. I've proved this by using:
| Code: | # Kill all timers.
proc kill_timers {} {
global chan
foreach j [utimers] {
if {[lindex $j 1] != ""} {
killutimer [lindex $j 2]
}
}
return 0
} |
Which obviously catches every possible utimer and that works perfectly the script behaves exactly as it's supposed to, but of course I cant have my script killing every single utimer on someone's bot every time they run it, fun as that might be lol
I'm fairly sure it's back to my old favourites of splitting lists and indexes but I cant see where. God I'm rusty at this
Any help again? Sorry I hope this will be the last time (although not guaranteeing it), dunno where I'd be without this forum here  _________________ "Insanity Takes Its Toll, Please Have Exact Change" |
|
| Back to top |
|
 |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
|
| Back to top |
|
 |
Ian-Highlander Op
Joined: 24 Sep 2001 Posts: 165 Location: Ely, Cambridgeshire
|
Posted: Mon Aug 08, 2005 6:22 pm Post subject: |
|
|
Yup, already read through that many times and tried some of it to catch the timer but like I say, its silly things like this that I'm really really rusty on as evidenced by the silly requests I've made so far for help whilst being able to code some otherwise fairly complex stuff without issues.
I guess if thats your answer then once again I'll thankyou for your help it is appreciated (and I really really mean that) and continue to bang my head against my desk for a few more hours trying to work it the hell out (or you could be really really kind again and put me out of my misery ) _________________ "Insanity Takes Its Toll, Please Have Exact Change" |
|
| Back to top |
|
 |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
Posted: Mon Aug 08, 2005 6:28 pm Post subject: |
|
|
String match should do the job
| Code: | # Kill all timers.
proc kill_timers {} {
global chan
foreach j [utimers] {
if {[string match -nocase "no_answer *" [lindex $j 1]]} {
killutimer [lindex $j 2]
}
}
} |
_________________ Follow me on GitHub
- Opposing
Public Tcl scripts |
|
| Back to top |
|
 |
Ian-Highlander Op
Joined: 24 Sep 2001 Posts: 165 Location: Ely, Cambridgeshire
|
Posted: Mon Aug 08, 2005 6:35 pm Post subject: |
|
|
See?? Thats exactly why I come here for help
You just fixed in two seconds flat what I've been working on for four hours trying to get working.
Thankyou once again, I definitely owe you a drink finally it all works as it should (so far). _________________ "Insanity Takes Its Toll, Please Have Exact Change" |
|
| Back to top |
|
 |
Ian-Highlander Op
Joined: 24 Sep 2001 Posts: 165 Location: Ely, Cambridgeshire
|
Posted: Thu Mar 23, 2006 7:38 am Post subject: |
|
|
The old rust is cracking off slowly and various bits and bobs are coming back to me or I'm working them out the hard way.
BUT.... it's always the relatively simple things that keep foxing me and I need some help with one of the other small things on my current "bugfix" list for Trivia 2000.
I have Trivia 2000 (and a couple of my other scripts) running on some bots in a chat room where a lot of users use coloured text. The bots dont respond to the binds from users using colour, the second they switch to black text it works fine. I dont want to wildcard the binds, that could have other adverse effects.
How can I get the bot to strip off the colour codes from what is typed in and react to the correct commands or answers regardless of the colour they where typed in without wild carding the whole bind?
Can anyone help? _________________ "Insanity Takes Its Toll, Please Have Exact Change" |
|
| Back to top |
|
 |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
Posted: Thu Mar 23, 2006 1:35 pm Post subject: |
|
|
You can't do that, you'll have to edit the eggdrop source in order to do that. What you can do is bind to * and call the other procs from there if the stripped-text matches. Example:
| Code: | bind pubm - * call:others
proc call:others {nick uhost hand chan arg} {
set arg [stripcodes <switches> $arg]
switch [string tolower [lindex [split $arg] 0]] {
"!trivia" {
trivia:proc $nick $uhost $hand $chan $arg
}
default {
return 0
}
}
} |
_________________ Follow me on GitHub
- Opposing
Public Tcl scripts |
|
| Back to top |
|
 |
Ian-Highlander Op
Joined: 24 Sep 2001 Posts: 165 Location: Ely, Cambridgeshire
|
Posted: Thu Mar 23, 2006 1:53 pm Post subject: |
|
|
Thanks Sir_Fz, hopefully that will point me in the right direction.
 _________________ "Insanity Takes Its Toll, Please Have Exact Change" |
|
| Back to top |
|
 |
Ian-Highlander Op
Joined: 24 Sep 2001 Posts: 165 Location: Ely, Cambridgeshire
|
Posted: Fri Mar 31, 2006 9:40 am Post subject: |
|
|
Right, finally had enough time to do some work on this and with a great deal of swearing eventually got all the main commands to work using this code based on what Sir_Fz gave me above.
| Code: | bind pubm -|- * strip_colour_codes
proc strip_colour_codes {nick uhost handle channel args} {
set args [string tolower [string trim [stripcodes c $args] "{}" ]]
switch [string tolower [lindex [split $args] 0]] {
"!help" {give_help $nick $uhost $handle $channel $args}
"!trivia" {give_help $nick $uhost $handle $channel $args}
"!score" {give_score $nick $uhost $handle $channel $args}
"!choose" {give_choice $nick $uhost $handle $channel $args}
"!start" {start_game_check $nick $uhost $handle $channel $args}
"!hints" {hints_onoff $nick $uhost $handle $channel $args}
"!answers" {give_answers $nick $uhost $handle $channel $args}
"!announce" {quest_announce $nick $uhost $handle $channel $args}
"!game" {game_onoff $nick $uhost $handle $channel $args}
"!stop" {stop_game $nick $uhost $handle $channel $args}
}
return 0
} |
The stumbling block that took me a while to get working was the second part of some commands and passing that correctly to the relevant procs that needed it (i.e. the command "!game on") but resolved that using the code above and a few minor edits to the relevant procs and all appears to be working great.
However I now find myself stuck again with the same problem but for some of the other binds in the script. I'll try to explain and hopefully someone can help with this because I'm going round in circles here.
The above commands are the games main control commands but there are several other places in the script where the bot has to "listen" for specific words in almost all of these situations the bot has to stop listening for those words the second someone has said it. For example when offering a choice of category, it has six binds listening, one for each category. The moment someone enters one of these words, the category is set and all six words are then unbound immediately. The code below is a snippet of the proc that creates the binds.
| Code: | putserv "PRIVMSG $chan :\002\003$copycol1\'Trivia 2000'\002 \003$copycol2\Version $triviaversion ŠIan-Highlander 2000-2006 started, please wait for a moment."
putserv "PRIVMSG $chan :\002\003$copycol1\'Trivia 2000'\002 \003$copycol2\Inspired by ^norma ------------------- ('I can't play word games')"
putserv "PRIVMSG $chan :\003$categcol1\Please select a category of questions to be answered"
putserv "PRIVMSG $chan :Current categories available are: \003$categcol2\Geography, Entertainment, History, Art & Literature, Science & Nature, Sport & Leisure, Queen"
putserv "PRIVMSG $chan :\003$choosecol\To choose a category simply type in the first word of that category."
bind pub -|- geography set_geog
bind pub -|- entertainment set_ent
bind pub -|- history set_his
bind pub -|- art set_art
bind pub -|- science set_sci
bind pub -|- sport set_sport
bind pub -|- queen set_queen
} |
There are then six seperate procs each of which are almost identical that look like this.
| Code: | #Geography's been set
proc set_geog {nick uhost handle channel args} {
global questfile geography gamechan quessetcol1 quessetcol2 quessetcol3
set chan $gamechan
set questfile $geography
putserv "PRIVMSG $chan :\003$quessetcol1\Questions set to \002\003$quessetcol2\ Geography\002 \003$quessetcol1\ by $nick enter\002\003$quessetcol3\ !start\002 \003$quessetcol1\ to play!"
unbind pub -|- geography set_geog
unbind pub -|- entertainment set_ent
unbind pub -|- history set_his
unbind pub -|- art set_art
unbind pub -|- science set_sci
unbind pub -|- sport set_sport
unbind pub -|- queen set_queen
} |
As you can see the minute the category is set, the bot sets the variable $questfile to $geography (specified in the user config at the top of the script) so that it knows which questions database to use, it then immediately unbinds all the words it was listening for to stop anyone else being able to choose too and stop any confusion.
My problem is this, if as Sir_Fz says, I cant strip the colour codes from the binds and the only way round it is to wildcard the binds then how can I achieve this? I tried re-writing the entire section with a wildcarded bind "switching" the correct trigger words to the right procs and I can get it working but as I did a wildcard bind, there is no way of unbinding the words. The same problem occurs when answers are given, as soon as a correct answer is given the bot reacts to it and unbinds it so that it wont react to anyone else giving that answer.
I'm tearing my hair out here guys, any help would be massively appreciated.
Ian _________________ "Insanity Takes Its Toll, Please Have Exact Change" |
|
| Back to top |
|
 |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
Posted: Fri Mar 31, 2006 9:25 pm Post subject: |
|
|
I'm not sure if I understood you very well; but if you mean you don't want to unbind the '*' pubm bind since it will stop listening to any command, what you can do is create a variable which is set to 1 when the commands are bound and 0 when unbound (you figure the whole logic of this). _________________ Follow me on GitHub
- Opposing
Public Tcl scripts |
|
| Back to top |
|
 |
Ian-Highlander Op
Joined: 24 Sep 2001 Posts: 165 Location: Ely, Cambridgeshire
|
Posted: Sat Apr 01, 2006 7:45 am Post subject: |
|
|
Yeah I cant unbind the pubm * because it would then stop every other command working. I just need to be able to unbind the category selections or answers after they have been given so that no repeats or user clashes happen.
I had an idea kind of on the lines of what you where suggesting so am hoping to get some time to work on that. If I get stuck I'll be back.
Thanks  _________________ "Insanity Takes Its Toll, Please Have Exact Change" |
|
| Back to top |
|
 |
|