Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

The perfect Kniffel-game (Yahtzee)


  • Please log in to reply
6 replies to this topic
Lequi
  • Members
  • 29 posts
  • Last active: Apr 19 2008 02:02 PM
  • Joined: 31 Aug 2007
Do you always wanted to have a perfekt kniffel game? if yes, get this:
Kniffel

this game is able to give you tips whats best to keep and which result to submit, so the perfekt yahtzee game is nearer then ever before :)
you can play it alone or change the playernumber up to 5.

here the code for those who are interessted in and for me to keep it up to date
edit: forgot sth, get this code after you downloaded and extracted the rar :)
edit: Kniffel is called Yahtzee outside of German-speaking countries
sorry for that ;)
hModule := DllCall("LoadLibrary", "str", "ole32.dll")
DllCall("ole32\CoInitialize", "uint", 0)

;variables

trials = 0
rounds = 0
tips = 0
Player1 = Player1
Player2 = 
Player3 = 
Player4 =
Player5 =
players = 1
currenttab = %Player1%
currentplayer = 1

;
;GUI
;

;creating menubar+gui
Menu, Filemenu, add, New &Game, new_game
Menu, Filemenu, add
Menu, Filemenu, add, E&xit, filemenuexit
Menu, gamemenu, add, Show &tips, tips
Menu, gamemenu, add, &Change Player Number, pl_number
Menu, gamemenu, add, Change Player &Names, pl_names
Menu, Helpmenu, add, &Help, helpmenuhelp
Menu, helpmenu, add
Menu, helpmenu, add, &About, helpmenuabout
Menu, mybar, add, &File, :Filemenu
Menu, mybar, add, &Game, :gamemenu
Menu, mybar, add, &Help, :Helpmenu
Gui, menu, mybar
Gui, color, white

;creating dice + checkbox buttons
loop, 5
{
	xpos:=-40 +50*a_index
	Gui, add, button, x%xpos% y10 w40 h40 vb%a_index% gbutton%a_index%
	xpos:=-30 +50*a_index
	Gui, add, checkbox, x%xpos% y60 vkeep%a_index%
	Guicontrol, disable, keep%a_index%
}

;shuffle button
Gui, add, button,y20 x270 w40 h25 default vRoll, Roll

;tip text
gui, add, text, w100 x20 y80 vvtips, Best:
guicontrol, hide, vtips

;throw-bar
Gui, add, text ,x170 y80, Throws
Gui, Add, Progress, range0-3 xp+40 yp+3 h10 w80 vMyProgress cblue

;tab control
Gui, add, tab, vmytab x0 y100 w400 h400 , %Player1%|


;ListView
bgURL = %a_workingdir%\images\wuerfel.bmp

loop, 5
{
gui, tab, %a_index%
gui, font, s10 bold, verdana
Gui, Add, ListView, +grid vLV%a_index% HwndhMyListView gmylistview NoSortHdr -multi h330 w300 LV0x10000, Throws|Points|
LV_SetBackgroundURL(bgURL, hMyListView)
LV_add( "", "1er")
LV_add( "", "2er")
LV_add( "", "3er")
LV_add( "", "4er")
LV_add( "", "5er")
LV_add( "", "6er")
LV_add( "", "Total")
LV_add( "", "Bonus?")
LV_add( "", "Total up")
LV_add( "", "3 of a kind")
LV_add( "", "4 of a kind")
LV_add( "", "Full House")
LV_add( "", "Lt. Street")
LV_add( "", "Bg. Street")
LV_add( "", "Kniffel")
LV_add( "", "Chance")
LV_add( "", "Total down")
LV_add( "", "Overall")

LV_ModifyCol(1, 150)
LV_ModifyCol(2, 145)
}


Gui, Show, w320 h470, Kniffel - %Player1%
Guicontrol,choose, mytab, 1
Gui, ListView, LV1
return

;
; Submit result
;
MyListView:
if A_GuiEvent = DoubleClick
{
	Guicontrolget, whichtab , ,mytab
	if whichtab = %currenttab%
	{
		if trials>=1
		{
			LV_GetText(RowText, A_EventInfo, 2)
			if a_eventinfo not in 7,8,9,17,18
			{
				if Rowtext =
				{
					LV_modify(a_eventinfo, "Col2", check(a_eventinfo, var) )
					gosub calc_up
					gosub calc_down
					sleep, 1000
					Guicontrol, enable, Roll
					trials = 0
					GuiControl,, MyProgress, 0
					GuiControl,, vtips, Best:
					loop, 5
					{
						Guicontrol,, b%a_index%	
						Guicontrol,, keep%a_index%, 0
					}
					Guicontrolget, currenttab , ,mytab	
	
					loop, %players%
					{
						if currenttab = % Player%a_index%
						{	
							currentplayer = 1
							currentplayer += %a_index%
							if currentplayer <= %Players%
							{
								Guicontrol, choose, mytab, %currentplayer%
								Gui, ListView, LV%currentplayer%
								loop, 5
								{
									Guicontrol, disable, keep%a_index%
								}
								currenttab = % Player%currentplayer%
								Gui,1: show ,, Kniffel - %currenttab%
								Guicontrol, focus, Roll
								return
							}
							else
							{
								Guicontrol, choose, mytab, 1
								Gui, ListView, LV1
								loop, 5
								{
									Guicontrol, disable, keep%a_index%
								}
								currenttab = %Player1%
								currentplayer = 1
								Gui,1: show ,, Kniffel - %Player1%
								Guicontrol, focus, Roll
								rounds++
							}
						}
					}		
	
					if rounds = 13  ; END
					{
						gosub calc_together
						msgbox, 4, , Again?
						ifmsgbox, yes
							goto new_round
						ifmsgbox, no
							return
					}
				}
			}
		}
	}
	else
		msgbox, This is not your tab!
}

return
;
;check result
;
check(x, var)
{
	if x in 1,2,3,4,5,6 ; gather numbers
	{
		temp=0
		loop, 5
		{
			if numbers%a_index% = %x%
			temp +=x
		}
		return %temp%
	}

	if x= 10 ; kind of three
	{
		temp=0
		loop, 6
		{
			xkind=0
			indexa= %a_index%
			if var contains %a_index%
			{
				loop,5
				{	
					if numbers%a_index% = %indexa%
					{
						xkind++
					}
					if xkind = 3
					{
						3kind =% numbers%a_index%
						loop, 5
						{
							temp+= numbers%a_index%
						}
						break
					}
				}
				if 3kind
					break
			}
		}
		return %temp%
	}

	if x= 11 ; kind of 4
	{
		temp=0
		loop, 6
		{
			xkind=0
			indexa= %a_index%
			if var contains %a_index%
			{
				loop,5
				{	
					if numbers%a_index% = %indexa%
					{
						xkind++
					}
					if xkind = 4
					{
						4kind =% numbers%a_index%
						loop, 5
						{
							temp+= numbers%a_index%
						}
						break
					}
				}
				if 4kind
					break
			}
		}
		return %temp%
	}

	if x= 12 ; full house
	{
		temp=0
		loop, 6
		{
			xkind=0
			indexa= %a_index%
			if var contains %a_index%
			{
				loop,5
				{	
					if numbers%a_index% = %indexa%
						{
							xkind++
						}
					if xkind = 3
					{
						3kind =% numbers%a_index%
						break
					}
				}
				if 3kind
					break
			}
		}
		loop, 6
		{
			xkind=0
			indexa= %a_index%
			if var contains %a_index%
			{
				loop,5
				{	
					if numbers%a_index% = %indexa%
						if numbers%a_index% <> %3kind%
							{
								xkind++
							}
					if xkind = 2
					{
						2kind =% numbers%a_index%
						break
					}
				}
				if 2kind
					break
			}
		}
		if 3kind
		{
			if 2kind
			{
				temp =25
			}
		}
		return %temp%
	}

	if x= 13 ; little street
	{
		temp=0
		if var contains 1
			if var contains 2
				if var contains 3
					if var contains 4
					{	
						temp =30
					}	
		if var contains 2	
			if var contains 3
				if var contains 4
					if var contains 5		
					{	
						temp =30
					}
		if var contains 3
			if var contains 4
				if var contains 5
					if var contains 6		
					{	
						temp =30
					}


		return %temp%
	}

	if x= 14 ; Big street
	{
		temp=0
		if var contains 1
			if var contains 2
				if var contains 3
					if var contains 4
						if var contains 5		
							temp=40
		if var contains 2
			if var contains 3
				if var contains 4
					if var contains 5
						if var contains 6		
							temp=40
		return %temp%
	}	

	if x= 15 ; kniffel
	{
		temp=0
		loop, 6
		{
			xkind=0
			indexa= %a_index%
			if var contains %a_index%
			{
				loop,5
				{	
					if numbers%a_index% = %indexa%
						{
							xkind++
						}
					if xkind = 5
					{
						5kind =% numbers%a_index%
						temp=50
						break
					}
				}
				if 5kind
					break
			}
		}
		return %temp%
		
	}

	if x= 16 ; chance
	{
		temp=0
		loop, 5
		{
			temp+= numbers%a_index%
		}
		return %temp%
	}

	

}
return

;calcs

calc_up:
temp=0
loop, 6
{
	LV_GetText(value, a_index, 2)
	temp += value
}
if temp
{
	LV_modify(7, "Col2", temp )
}
if temp >=63
{
	LV_modify(8, "Col2", 35)
}
loop, 6
{
	LV_GetText(value, a_index, 2)
	if value =
		return
	if a_index = 6
	{
		if temp <63
		{
			LV_modify(8, "Col2"," - ")
		}
		temp = 0
		LV_GetText(value, 8, 2)
		temp+=value
		LV_GetText(value, 7, 2)
		temp+=value
		LV_modify(9, "Col2", temp )
	}

}
return

calc_down:
temp=0
loop, 7
{
	LV_GetText(value, a_index+9, 2)
	temp += value
}
if temp
{
	LV_modify(17, "Col2", temp )
}
return

calc_together:
temp=0
LV_GetText(value, 9, 2)
temp+=value
LV_GetText(value, 17, 2)
temp+=value
LV_modify(18, "Col2", temp )
return


;
;misc functions
;
button1:
keep_toggle(1)
return
button2:
if trials >0
keep_toggle(2)
return
button3:
if trials >0
keep_toggle(3)
return
button4:
if trials >0
keep_toggle(4)
return
button5:
if trials >0
keep_toggle(5)
return

keep_toggle(x)
{
	global
	if trials >0
	{
		gui, submit, nohide
		if keep%x%
			Guicontrol, , keep%x%, 0
		else
			Guicontrol, , keep%x%, 1
	}
}
return


LV_SetBackgroundURL(URL, ControlID) 
{ 
    VarSetCapacity(bki, 24, 0) 
    NumPut(0x2|0x10, bki, 0)  ; LVBKIF_SOURCE_URL | LVBKIF_STYLE_TILE 
    NumPut(&URL, bki, 8) 
    SendMessage, 0x1044, 0, &bki,, ahk_id %ControlID%  ; LVM_SETBKIMAGE 
}


new_round:
{
	Gui, 1:default
	rounds = 0
	trials = 0
	loop, 5
	{
		Gui, ListView, LV%a_index%
		LV_deleteCol(2)
		LV_InsertCol(2,"", "Points")
	}
	Guicontrol,1: choose, mytab, 1
	Gui, ListView, LV1
	currenttab = %Player1%
	loop, 5
	{
		Guicontrol,, b%a_index%	
		Guicontrol,, keep%a_index%, 0
		Guicontrol, disable, keep%a_index%
	}
	Gui, show ,, Kniffel - %player1%
	Guicontrol, enable, Roll
	Guicontrol,1: focus, Roll
	GuiControl,, MyProgress, 0
	Guicontrol,, vtips, Best:
}
return


mergeplayer:
{

	loop, 5
	{
		if a_index > %players%		; clear only those which dont play
			player%a_index% = 
	}

	if player1
	{
		if player2
		{
			if player3
			{
				if player4
				{
					if player5
					{
						str= %player1%|%player2%|%player3%|%player4%|%player5%
					}
					else
					{
						str= %player1%|%player2%|%player3%|%player4%
					}
				}
				else
				{
					str= %player1%|%player2%|%player3%
				}
			}
			else
			{
				str= %player1%|%player2%
			}
		}
		else
		{
			str= %player1%
		}
	}
	Guicontrol,1: ,mytab, |%str%
}
return



;
; Menu functions
;
#IfWinActive, ahk_class AutoHotkeyGUI
^g::
new_game:
msgbox, 4, , Sure?
ifmsgbox, yes
	goto new_round
ifmsgbox, no
	return
return

#IfWinActive, ahk_class AutoHotkeyGUI
^x::
filemenuexit:
exitapp
return

#IfWinActive, ahk_class AutoHotkeyGUI
^t::
tips:
menu, gamemenu, ToggleCheck, Show &tips
if tips =0
{
	tips = 1
	guicontrol, show, vtips
	if trials
		gosub showtips
}
else
{
	tips = 0
	guicontrol, hide, vtips
}
return

showtips:
if tips
{
	str = kniffel
	loop, 18
	{
		if a_index not in 7,8,9,17,18
		{
			LV_GetText(value, a_index, 2)
			if value
				str = %str% %value%
			else if value = 0
				str = %str% 0
			else
				str = %str% -
		}
	}
	str = %str% %trials% %var% > history.txt
	runwait, %comspec% /c %str%
	FileReadLine, line, history.txt, 22
	StringSplit, prearray, line , `, 
	StringSplit, endarray, prearray1 , :, %a_space% 
;translation
	best = %endarray4%
	if best = Einser
		best = 1er
	else if best = Zweier
		best = 2er
	else if best = Dreier
		best = 3er
	else if best = Vierer
		best = 4er
	else if best = Fuenfer
		best = 5er
	else if best = Sechser
		best = 6er
	else if best = FullHouse
		best = Full House
	else if best = Kleine Strasse
		best = Lt. Street
	else if best = Grosse Strasse
		best = Bg. Street
	else if best = 0
		best = -

	Guicontrol,, vtips, Best: %best%
}
return




#IfWinActive, ahk_class AutoHotkeyGUI
^c::
pl_number:
Gui, 4:destroy
Gui, 4:font, s12 bold
Gui, 4:add, text, , Choose the number`nof players:
Gui, 4:Add, Edit, x70 w50 vpl_nbr
Gui, 4:font, normal
Gui, 4:Add, UpDown, Range1-5, 2
Gui, 4:add, button, x40 default, Ok
Gui, 4:add, button, x85 yp, Cancel
Gui, 4:show, autosize, Playernumber
return



4Buttonok:
Gui, 4:submit
gui, 4:destroy
if pl_nbr = %players%
	return
else
{
	players = %pl_nbr%

	loop, %players%
	{
		if player%a_index% =
			player%a_index% = Player%a_index%
	}
	gosub mergeplayer
	goto new_round
}
return

4Guiescape:
4Guiclose:
4ButtonCancel:
Gui,4:destroy
Guicontrol,1: focus, Roll
return

#IfWinActive, ahk_class AutoHotkeyGUI
^n::
pl_names:
Gui, 5:destroy
gui, 5:font, s12
loop,5
	if player%a_index%
	{
		ypos := -20 +40*a_index
		gui, 5:add, text,x10 y%ypos%, Player %a_index%:
		gui, 5:add, edit,vpl_name%a_index% x80 y%ypos% w100, % player%a_index%
	}
Gui, 5:add, button, x40 y+15 default, Ok
Gui, 5:add, button, x85 yp, Cancel
Gui, 5:show, autosize, Playernames
return

5ButtonOk:
Gui,5:Submit
loop, 5
	player%a_index% = % pl_name%a_index%
Gui,5:destroy
gosub mergeplayer
currenttab = % player%currentplayer%
Gui,1: show ,, Kniffel - %currenttab%
return

5Guiescape:
5Guiclose:
5ButtonCancel:
gui,5:destroy
Guicontrol,1: focus, Roll
return


#IfWinActive, ahk_class AutoHotkeyGUI
^h::
helpmenuhelp:
Gui, 2:destroy
gui, 2:font, s15 underline bold, Arial
Gui, 2:add, text,, Help
gui, 2:font, normal
gui, 2:font, s10
gui, 2:add, text,,-Click the roll button to get new dice`n-Select either a dice or a checkbox under a it in order to keep 

the dice`n-Double click on an entry to submit your result.`n-The "throw-bar" indicates how many throws you have left`n-The 

menuentries are self-explaining
Gui, 2:add, button, default +center x185 yp+100, Ok
Gui, 2:color, white
Gui, 2:+resize
Gui, 2:show,  autosize
return
2Buttonok:
Gui, 2:destroy
return

#IfWinActive, ahk_class AutoHotkeyGUI
^a::
helpmenuabout:
gui, 3:destroy
gui, 3:font, s15 underline bold, Arial
Gui, 3:add, text,, Kniffel
gui, 3:font, normal
gui, 3:font, s10
gui, 3:add, text,, Version: 1.00`nAuthor: Nils
Gui, 3:add, button, default +center x70 yp+50, Ok
Gui, 3:color, white
Gui, 3:+resize
Gui, 3:show, autosize
return
3Buttonok:
Gui, 3:destroy
return


;
;Roll
;


;shuffle
ButtonRoll:
Gui, submit, nohide
var=0
trials+=1
GuiControl,, MyProgress, +1
if trials =1
{
	loop, 5
	{
		Guicontrol, enable, keep%a_index%
	}
}

if trials = 3
	Guicontrol, disable, Roll
loop, 5
{
	xpos:=-40 +50*a_index
	Random, rnd, 1,6
	if keep%a_index% = 0
	{
		Guicontrol,, b%a_index%, %rnd%
		numbers%a_index% = %rnd%
	}
}
var = %numbers1%%numbers2%%numbers3%%numbers4%%numbers5%
gosub showtips

return


Guiclose:
FileDelete, %a_workingdir%\history.txt
  gui, destroy  ;do this to avoid access violation
  DllCall("ole32\CoUninitialize")		;
  DllCall("FreeLibrary", "UInt", hModule)	;this must be done at the end
exitapp
return


daonlyfreez
  • Members
  • 995 posts
  • Last active: Jan 23 2013 08:16 AM
  • Joined: 16 Mar 2005
Interesting...

FYI: Kniffel is called Yahtzee outside of German-speaking countries :wink:

Remarks:

- I see no pictures on the buttons
- I see no background on the listview (on Win2K)
- Why is a cygwin.dll/restgewinn-file included in the download?
- Why do you include a call to ole32.dll, which is not used in the script as far as I can see?
- Why do you use the kniffel.exe to generate "tooltips", yet it doesn't show anything?


LV_SetBackgroundURL(URL, ControlID) 
{ 
    VarSetCapacity(bki, 24, 0) 
    NumPut(0x2|0x10, bki, 0)  ; LVBKIF_SOURCE_URL | LVBKIF_STYLE_TILE 
    NumPut(&URL, bki, 8) 
    SendMessage, 0x1044, 0, &bki,, ahk_id %ControlID%  ; LVM_SETBKIMAGE
    [color=red]SendMessage, 0x1026, 0, -1,, ahk_id %ControlID%  ; LVM_SETTEXTBKCOLOR,, CLR_NONE[/color] 
}

:wink:
Posted Image mirror 1mirror 2mirror 3ahk4.me • PM or Posted Image

Lequi
  • Members
  • 29 posts
  • Last active: Apr 19 2008 02:02 PM
  • Joined: 31 Aug 2007
there are no pictures on the buttons, looks quite ugly so i decided to simply show the numbers

i started it with win2k compatibility mode and i saw a background (native xpsp2)

the dll and the "restgewinn" file are necessary for the probabiltiy calculating, the calculating is written in c cause its much easier there

the call to the ole32.dll is needed because otherwise the programm would crash after you close the gui, this is because i included a background picture to the listview

Why do you use the kniffel.exe to generate "tooltips", yet it doesn't show anything?

which tooltips you mean?

SendMessage, 0x1026, 0, -1,, ahk_id %ControlID% ; LVM_SETTEXTBKCOLOR,, CLR_NONE

what is that for?

daonlyfreez
  • Members
  • 995 posts
  • Last active: Jan 23 2013 08:16 AM
  • Joined: 16 Mar 2005
Ok, so the cygwin.dll is needed for the kniffel.exe?

The extra line makes the background image in the listview show on Win2K

:)
Posted Image mirror 1mirror 2mirror 3ahk4.me • PM or Posted Image

Lequi
  • Members
  • 29 posts
  • Last active: Apr 19 2008 02:02 PM
  • Joined: 31 Aug 2007
cool, and how? what does 0x1026 mean and what are its parameters?

daonlyfreez
  • Members
  • 995 posts
  • Last active: Jan 23 2013 08:16 AM
  • Joined: 16 Mar 2005
It makes the background of the text transparent, so the background picture shines thru...

LVM_SETTEXTBKCOLOR = set background color of text
CLR_NONE = color is none

:wink:
Posted Image mirror 1mirror 2mirror 3ahk4.me • PM or Posted Image

Lequi
  • Members
  • 29 posts
  • Last active: Apr 19 2008 02:02 PM
  • Joined: 31 Aug 2007
ah, nice; thank you :)