This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

Array producing crazy indexes

Help for those learning Tcl or writing their own scripts.
Post Reply
L
Landslyde
Halfop
Posts: 46
Joined: Thu May 01, 2014 6:01 pm

Array producing crazy indexes

Post by Landslyde »

So this is my first-ever script. It's a dice game I use to play growing up way back in the stone age. The dice array is acting weird though. The array information I'm using is from http://www.tcl.tk/man/tcl8.5/tutorial/Tcl22.html.

Code: Select all

set dice	{ 
		"1"	
		"2" 
		"3" 
		"4"	
		"5" 
		"6"
}

proc roll:dice {nick host handle chan arg} { 
	global dice fPRVMSG fChan numbers
	set die1 [lindex $dice [rand [llength $dice]]]
	set die2 [lindex $dice [rand [llength $dice]]]
	set die3 [lindex $dice [rand [llength $dice]]]
	set die4 [lindex $dice [rand [llength $dice]]]
	set die5 [lindex $dice [rand [llength $dice]]]
	set die6 [lindex $dice [rand [llength $dice]]]	
	set rolled [list $die1 $die2 $die3 $die4 $die5 $die6]

	array set arolled [list $die1 $die2 $die3 $die4 $die5 $die6]

	putquick "$fPRVMSG $chan :$nick rolls  \002\0030,4  $die1  \003 \002\0030,4  $die2  \003  \002\0030,4  $die3  \003  \002\0030,4  $die4  \003  \002\0030,4  $die5  \003  \002\0030,4  $die6  \003"
	putquick "$fPRVMSG $fChan :The rolled numbers are: [array get arolled]"
	putquick "$fPRVMSG $fChan :Dice 3 and 5 were: $arolled(2) and $arolled(4)"
}
Following the three outputs, this is what I get from my bot:

Code: Select all

[19:54:30] <@Slyde> .roll
[19:54:31] <Shianne> Slyde rolls    4     2      6      5      2      3  
[19:54:32] <Shianne> The rolled numbers are: 4 2 2 3 6 5
[19:54:32] <Shianne> Dice 3 and 5 were: 3 and 2
The indexes are off from the way I stored them in the last two outputs. But, like I said, this is my first tcl script. So maybe I'm not using the arrays the right way. Will someone please tell me what I'm doing wrong? Thanks.
w
willyw
Revered One
Posts: 1197
Joined: Thu Jan 15, 2009 12:55 am

Re: Array producing crazy indexes

Post by willyw »

Landslyde wrote: ...
putquick "$fPRVMSG $fChan :The rolled numbers are: [array get arolled]"
....
See:
http://www.tcl.tk/man/tcl8.5/TclCmd/array.htm#M8

"... The order of the pairs is undefined...."

Is that it?

I hope this helps.
For a fun (and popular) Trivia game, visit us at: irc.librairc.net #science-fiction . Over 300K Q & A to play in BogusTrivia !
L
Landslyde
Halfop
Posts: 46
Joined: Thu May 01, 2014 6:01 pm

Post by Landslyde »

Thank you for the link. It has a lot more info on arrays. I think I'll be able to sort out what I need, which is allowing the user to select the dice they want to re-roll. That's why having the indexes be static as set in the array is important.

Say the roll is: 2 5 4 6 5 5

They wld want to keep the three 5s and re-roll the 2 4 6. Set in the array, those wld be indexes 0, 2, and 3. Then I'd unset those in the array and append the re-roll to the three 5s. That's why having the indexes static and not rearranging themselves is necessary.

But thank you for the link, willyw. I'll study what they have there and see what I can come up with.
User avatar
caesar
Mint Rubber
Posts: 3776
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Instead of all this:

Code: Select all

set die1 [lindex $dice [rand [llength $dice]]]
set die2 [lindex $dice [rand [llength $dice]]]
set die3 [lindex $dice [rand [llength $dice]]]
set die4 [lindex $dice [rand [llength $dice]]]
set die5 [lindex $dice [rand [llength $dice]]]
set die6 [lindex $dice [rand [llength $dice]]]
I would use this code:

Code: Select all

proc dice:roll {count} {
	for {set x 0} {$x<$count} {incr x} {
		lappend roll [expr [rand 6] + 1]
	}
	return $roll
}
to get a roll of 6 dices then:

Code: Select all

set roll [dice:roll 6]
Now, if taking your example where you got a list of 3 positions to swap and want to generate 3 new rolls, we have the positions stored in a variable, for example:

Code: Select all

set pos [list 0 2 3]
and to generate 3 or an unknown number of rolls:

Code: Select all

set swap [dice:roll [llength $pos]]
and then to do the actual swap use this code:

Code: Select all

proc dice:swap {pos roll swap} {
	set count [llength $pos]
	for {set x 0} {$x<$count} {incr x} {
		set ele [lindex $pos $x]
		set roll [lreplace $roll $ele $ele [lindex $swap $x]]
	}
	return $roll
}
and call it:

Code: Select all

set newRoll [dice:swap $pos $roll $swap]
From here do whatever you want with $newRoll as is a list with 6 rolls that have been changed in the positions you asked for.

And here's the result:

Code: Select all

% set roll [list 2 5 4 6 5 5]
2 5 4 6 5 5
% set pos [list 0 2 3]
0 2 3
% set swap [list 4 6 2]
4 6 2
% dice:swap $pos $roll $swap
4 5 6 2 5 5
Hope this helps. :)
Last edited by caesar on Thu Apr 28, 2016 10:19 am, edited 1 time in total.
Once the game is over, the king and the pawn go back in the same box.
w
willyw
Revered One
Posts: 1197
Joined: Thu Jan 15, 2009 12:55 am

Post by willyw »

Landslyde wrote: ...
That's why having the indexes be static as set in the array is important.

...
That's why having the indexes static and not rearranging themselves is necessary.

...
Or, is it just necessary to be able to find them somehow? Maybe it would be better to ask that.
This is assuming you are really wanting to work with arrays and learn what they can do. This is not to say that an array is the best tool for your present job.

I don't think that an array works that way - held in position. (Perhaps caesar and nml375 will comment)
When this happens, it can be time to find another way with TCL, to do what you are envisioning. See caesar's code.

If mastering arrays right now is not the main focus, but finding a way to roll your dice is, then spend some time experimenting with his code, piece by piece. Figure out how he is doing it. It is interesting.
I was thinking of lists, but had not gone further.

caesar:
set swap [split $swap]
Just curious - why split? Isn't $swap already a list?
For a fun (and popular) Trivia game, visit us at: irc.librairc.net #science-fiction . Over 300K Q & A to play in BogusTrivia !
User avatar
caesar
Mint Rubber
Posts: 3776
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Ah! Right. Power of habit. :roll:
Once the game is over, the king and the pawn go back in the same box.
w
willyw
Revered One
Posts: 1197
Joined: Thu Jan 15, 2009 12:55 am

Post by willyw »

caesar wrote:Ah! Right. Power of habit. :roll:
ahh..
I was doubting myself. I looked it, and again, and again...

Finally, I just had to ask. :)


By the way:
I forget about for loops. I'm glad you posted that.

Sometimes - not often - I will use a while loop.
With just a quick overview of both, it seems like in many cases, either could be used.
For a fun (and popular) Trivia game, visit us at: irc.librairc.net #science-fiction . Over 300K Q & A to play in BogusTrivia !
User avatar
caesar
Mint Rubber
Posts: 3776
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Since the $swap was already a list the split wasn't needed. Thanks for pointing that out. Fixed the above code. :)

The only notable difference between the for loop and while loop lays in the number of lines you use, else you will get the same results. For example with a while loop the dice:roll function would be:

Code: Select all

proc dice:roll {count} { 
	set x 0
	while {$x<$count} {
		lappend roll [expr [rand 6] + 1] 
		incr x
	}
	return $roll
}
As a rule of thumb I tend to stay away from while loops cos if you screw up something, like let's say you forget that increment of the x variable, it has the potential to loop indefinitely and don't want that. :)

The for loop has all the stuff defined right away in the same line and it's next to impossible to screw up something to make it run indefinitely. :P
Once the game is over, the king and the pawn go back in the same box.
w
willyw
Revered One
Posts: 1197
Joined: Thu Jan 15, 2009 12:55 am

Post by willyw »

caesar wrote:Since the $swap was already a list...
It sure looked like it to me. :)
The only notable difference between the for loop and while loop lays in the number of lines you use, else you will get the same results. ...
Good.
As a rule of thumb I tend to stay away from while loops cos if you screw up something, like let's say you forget that increment of the x variable, it has the potential to loop indefinitely and don't want that. :)
I don't forget it, but I still manage to screw it up somehow on the first draft. :D
The for loop has all the stuff defined right away in the same line and it's next to impossible to screw up something to make it run indefinitely. :P
Next time I need something like this, and after these few posts here now, maybe I'll remember to utilize the for loop.

Thanks.
For a fun (and popular) Trivia game, visit us at: irc.librairc.net #science-fiction . Over 300K Q & A to play in BogusTrivia !
L
Landslyde
Halfop
Posts: 46
Joined: Thu May 01, 2014 6:01 pm

Post by Landslyde »

willyw and caesar:

Thank you both for your input. I get what you said, all but the $swap / split stuff. I'll work with this and see what I can do. Really appreciated.

And sorry for the pate response. I just set my IRC network back up and have been going hard at it there.

Thanks again :D
Post Reply