MG Feb 18 2005 - After being in need of a quick diversion, I started writing another card game (see Spider Solitaire for my last), this time Hearts, similar to the one shipped with Windows since, IIRC, Windows 3.1.1 for Workgroups.It's not quite finished yet, but I thought I'd post what I've done so far and update it as I go.It uses the same set of card images as Spider Solitaire and Once in a Lifetime, with a few changes; the card back image now has a black border around it (nicer when you have 13 cards overlapping in a line), and I added a few new card back images (one is picked at random), using a few of the 'fill patterns' from Photoshop.Comments welcomed, as always :)Vince says that in the UK the rules are different - normally AKQ of spades are bad, with A=7,K=10,Q=13 points, and the hearts one point each. Normally J-diamonds isn't special, either. Also, the player to left of dealer leads whatever card they want (no forcing of the 2-clubs lead). Finally, you can't lead a heart until one has been discarded, unless all you have are hearts. I've played both versions a lot, in the US and UK, and most people I know find the UK rules lead to a more interesting game.MG is from the UK himself, but hadn't heard of those rules - the only version I've ever played in the one shipped with Windows. Would be interesting to add that ruleset at the end and make it configurable, too, though. Thanks for posting about it :)With your comment about the Jack of Diamonds.. it shouldn't be special in this version, either. Did you find that you got points for it somewhere? If so, it's a bug that I'll take a look for...Vince you're right it's not special in this version at present. The standard US rules give -10 points for it. In the UK it's irrelevant.rdt Well, Vince, I've played (in the US) for decades and never heard of that rule, maybe its not so 'standard' after all.MG Ah, I see. I was going by the scoring in the MS Windows version of Hearts (though who knows where they got the rules from, after what you said). *grins* More options to add.See help-files in the game for changes in different versions
rdt says this is a nice game and its getting to be in "pretty good shape". I have one suggestion about the AI that I've noticed. When a player is about to take a trick, that is, he is playing the fourth card on a trick and he doesn't have a card lower than any of the three already played, why does he play his lowest card of the suit instead of the highest? MG March 12 - this shouldn't happen any more, with the recoded AIsMG Hi rdt, thanks for your comments. I'm planning to do three levels of AI, but all that's there right now is the really stupid one (which I just wrote so that the game would actually be playable). And when I say stupid, I really mean it :) It uses extremely basic routines to pick a card - if there are cards down, and it can match suit, it always does so with the lowest card it has. I'll probably change that as you suggest, though, when I do the other AIs, since otherwise it's going to be a little too basic, even for an 'easy' player. (Right now, though, it has the advantage of making it easy to test things, since it's fairly easy to win or lose any round.) Hopefully I should fix up the other AIs in the next couple of days. At the moment, though, and after reading some of RS's pages like Describing and rendering flags in Tcl in the last few days, I'm thinking of recoding the AI handling slightly, to make it easier to define different difficulties/intelligence levels with shorthand / a little language - as it is, every AI proc has to check for the 2 of clubs (which is something every single one will definitely have to do, so it's kind've pointless repeating it like that...), and things like that. (Wow, that was rambling.)rdt I understand. Its fun as it is, like you say.
rdt Hey, I thought the rule was "you can't drop a heart on the first trick". Top led the 2 clubs & Right dropped the Jack of Hearts. Is that supposed to permitted or is it a bug?MG That is a bug, yes. You can't play a heart on the first round (or any other point card). I haven't looked at the code yet, but I'm pretty sure where it is - I didn't check for it being the first round in the AI code. (It does check that, in the 'player' code, though, so it's not possible for you to do that.) Will fix later tonight. Thanks :)MG Fixed now (v 0.7).rdt Thanks MG, now I'm getting a "can't read $origx while executing if { $origx == $tox && ..." error from the doMoveCard proc for some reason & I can't figure out why. :(MG Ack. I'd gotten that once before, but wasn't sure why, and thought/hoped some small changes I'd made had sorted it. I'll go digging later on and see if I can find what's causing it. Thanks :)MG adds, a few minutes later, that v 0.8 has been released, with an extra call to [puts] in [doMoveCard], which should show what's causing the problem. (Incidently, whenever I saw the error myself, it was on the right-hand player. Did you happen to notice the same thing, if you remember?) Update: *coughs* Removed a stupid bug in the 'puts' check (I had [info exists $origx] not [info exists origx])rdt Ok, the output was 'Error! [doMoveCard .c cardNum 3] /' from Top, I believe. Apparentely the '[$c coords $item]' did not return anything. Further testing reveals that to be correct.MG With the aid of another 25 or so calls to puts, I've tracked it down ;) Hopefully it's fixed now (v 0.9). The problem was that the AI was filtering the cards incorrectly - it was stopping the AI from playing a heart or the queen of spades (ie, point cards) if there were no cards down, rather than if it was the first play of the round (when the 2 of clubs is played, and point cards are banned). That caused an AI whose cards were soley made up of point cards to not be able to start a play (with getBestCard-1 returning an empty string, instead of a card). Should work fine, now (he says, crossing his fingers).rdt Shoot. I broke it for the wiki_reaper so I edited my text above. :)MG v 0.10 now released (early hours of March 12 2005). The AI code is now re-written, which should make defining AIs easier - instead of actual coded procs, it uses two variables per AI, both a Tcl list.MG, several hours later: now at v0.11, with some improvements to the AI code, and a new, more intelligent AI added. Explaination of how they both work removed; I'll re-add it at the end, when it's set. Right now, if you have a suggestion for how an AI should work, the best thing to do is just drop a textual explaination here - the code format may change a little, and it's somewhat confusing, at the moment, I think. Any comments welcomed, though :) The top and right AIs now use a (theoretically) more intelligent AI than the left-hand one, which is also slightly better at the game than it was before. A third level of AI will follow, which will have "memory" (will remember if the queen of spades was played, and play it's cards accordingly, and so on).rdt Well, it certainly is a better AI.MG March 13 2005 - Fixed a really, really stupid bug in the AI - where I had glob patterns for choosing which cards to put up, the * was on the wrong side of the character, so none of them matched. :P Fixed that, now, and a bug in the AIchooseCardsUp proc which let one card match several times (meaning that some AIs only passed 1 or 2 cards over, instead of 3). Also added a third AI, which is better than both the others. It's not as intelligent as it could be yet, I don't think, but it definitely beats the other two. I think the AI code is suitable for more intelligent things, too - if there's something that's not possible, I think it just means more variables need to made available for the expressions - so I'll explain the way the AIs are coded later tonight. At the moment, there's one AI of each difficulty - no "good" way to change it yet, so just edit the code, it's quite near the top (data(diffs,$num), set to 1 for basic, 2 for moderate, 3 for better). Any suggestions for improvements to make the AIs more intelligent would be appreciated, either with code or just an explaination of why they're stupid :)MG Bug in AIchooseCardsUp fixed in v0.13rdt A suggestion, the color of the score for the player that goes over 100, should be red and how about having the score be a "drop-down" white rectangle from the top of the canvas? MG Agreed, on the red, I'll add that in (done in v0.14). I'm not completely sure what you mean for the drop-down part, though?rdt Instead of opening a new toplevel window, a rectangle (in white as if it were a score sheet) drawn directly onto the canvas beginning at its top. Additional lines would extend the rectangle downward. It would come and go just like the current score window does.MG Ah, I see what you mean now. Hrm... not too sure about that one, I'll have to think about it. It would seem to have a few drawbacks to me: it would be harder to align things properly (I'm not too fond of the experience I've had with doing text on the canvas with this, though it could well just be me being stupid), whereas pack takes care of things very simply. It would also be more difficult to arrange the bindings - simple deactivation of the canvas wouldn't be an option, if the score dialog was a part of it. (Just binding to the canvas itself and still deactivating the canvas may sort it, though.) I'm not really sure that I see any benefit of doing it like that, though...rdt Yes, I understand your feeling about text on the canvas. It could be done by label windows (one for each score) placed onto the canvas. The "dismiss" button would just clear the canvas like the end of a game.rdt Whoops. I meant to have just the score over 100 be red. Not the entire column.MG Personally, I think it looks better with all of them in red. But I've made it more easily changable - just find the line 'set allRed 1' in the showScores proc, and change it to 0, and only the last score (the one over 99 - 100 loses the game, too) will be shown in red. The previous scores are also shown with an overstrike, now, similar to the MS version.
MG March 22 2005 - Version 0.18 released (including changes from 0.16 and 0.17, which I never uploaded as they were minor). Now has an Options dialog (not the most attractive, but it works). AI names are only changed when you start a new game, the other options take effect immediately. Also made some small internal changes, and added a button-3 binding to show the whole card by raising it above the others.
[Anon] 22Mar05 - Request - could you add a keyboard interface, so that it could be played entirely without resort to the mouse? MS-Hearts uses <space> to throw in either lowest card in suit or furtherst left if you can't follow suit. But this could be improved by using the arrow keys to pick a card (it could toggle between allowable moves). Cheers!MG That would be good to have, I agree. Maybe 1, 2,.. 9, 0 to play one of the first ten cards, and Shift-[1-3] for one of the others? (That's also much easier to do than using the arrow keys to scroll through, since it basically requires no new code other than the [bind] calls.)
MJL 22Mar05 - Has someone fiddled with doEndRound? The scoring system is completely broken. For example the command incr last $data(points,$x) isn't going to work as data(points,$x) is a list of cards. (Note: updated Anon -> MJL 17May05).MG Woops.. that would be me. I was changing it over to add a new feature, but decided to release all the other changes first, and add that feature later - and completely forgot I'd half-started. I'll fix that ASAP. Thanks for pointing it out...MG Fixed now, hopefully. The incr last $data(points,$x) you mentioned should have been incr last $points, and then there were several stupid other bugs like an lsearch's return value being checked incorrectly (so it was always taken as being true, even if it returned -1, which should've been false here). Anyway... hopefully all sorted, now. Thanks again.
MG March 25th 2005 - Version 0.21 released. Just a couple of minor changes/additions now before I'd consider it "ready" for proper use. Also decided to leave implementing the other scoring methods suggested by Vince until later, since it would require re-writing the AIs for each scoring method, as well as the code that handles player clicks to check what's valid.
MG April 2nd 2005 - Version 0.22 out now, with a bug fix. "Changes" are also moved into the help-file, now. (Appearance - indentation, etc - could be improved some, still.)
20may05 jcw - Moved this 200 Kb script to http://wiki.tcl.tk/_repo/wiki_images/hearts.tcl - please don't store these amounts of text in wiki pages, they become totally unmanageable for people wanting to add comments. Try SourceForge instead ;)MG Sorry :D It was a fair bit smaller than that, when I started it, and grew more than I'd anticipated or realised.MiHa 2015-06-25: When the page is divided into sections that can be edited separately (like '**Comments**'), this should not be an issue.
MG July 28 2005 - Version 0.23 released (see the top of the page for a download link). It now prompts for your name at the start (as per the Win XP version), and starts a game as soon as you give it your name. It also saves some of the options (like the player names and the cardback you're using) to a textfile, in the same directory as the game itself. These changes were all written by Olier Raby [1], with some extremely minor modifications from me.
MG July 29 - Ver 0.24 fixes an error in the help-files regarding scoring (it stated the game ended when someone had more than 100 points, instead of 100 or more). Fixed by Olier Raby.
LV Question about 0.24 - on line 116, the line:
wm geometry $top +$x+$y $dialog(geo,$top)is coded. But wm geometry only takes 2 arguments; a window and a geometry. So what's that 3rd argument for?MG That's part of the code Olier Raby added, so I can't say for sure. However, it looks like the idea is to place the dialog box back where it was previously, when the window is deiconified (and that the +$x+$y argument shouldn't be there). I think most window managers handle returning a window to the right position when it's deiconified automatically, though, so it's probably unnecessary anyway... I'm going to rework the code for those dialogs a little, to make the prompt a transient window, among other things, so I'll fix that at the same time.
uniquename 2013aug02As mentioned above, this code is getting pretty mature. It deserves an image: