<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}
.readOnly {background:[[ColorPalette::TertiaryPale]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity=60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser

Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])

<<option txtUserName>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]

----
Also see [[AdvancedOptions]]
<<importTiddlers>>
<<bridgeHand "7,3;t,6,5,2;j,9,7,6,5,3;a" "9,2;8,7,4;t,4;q,9,8,6,5,2" "k,q,t,6;a,j,9;k,q;t,7,4,3" "a,j,8,5,4;k,q,3;a,8,2;k,j">>

West leads a 4th highest !S against 3NT, small, 9, K! This is actually a double falsecard, in that declarer conceals both the T and the Q. Of course, West is not fooled about the Q - if East has &spades;~QT9 they will certainly play the Q, not the 9. But it is inconceivable that South would spurn a free trick with the &spades; T, and East's play is consistent with the &spades T9. Subsequently, when, after setting up @@color:red;&diams;@@ South leads a small &spades; toward the 7 in dummy, West ducks. He ''knows'' that East has the T. It's hard to imagine the feeling in West's stomach when that 7 held the trick.

Now, it's an interesting question as to where Belladonna dredged this idea up from; had he used it before? Or seen the possibility of it previously, perhaps when defending? Read about it? Did he "see" it for the 1st time as he visualised the &spades; pips? I don't know. They all seem possible. There is another possibility also, which I've seen in a Seres hand. Seres, having punted 3NT on a running minor & on the lead into his AQ of opener's suit, had 8 tricks (the minor was only 6 cards long). However, instead of winning with the Q over the (J or T), he won with the Ace. Unlike this hand, there was no potential tactical payoff for this deception, no materialising entry. Nonetheless, there was a payoff, because the contract was made; both East and West, believing partner held the missing Q, made a series of poor decisions both discarding & on regaining the lead.  Perhaps Belladonna also sacrificed a trick for defensive confusion, without seeing specifically how it could come back.

More questions raised: Are both hands equally elegant? I think Seres' play, with no tactical payoff is ingenious, a tool everyone should have in their bag. But I'm not sure it's elegant. However, the nexus between play and payoff in Belladonna's case makes me feel that it might be possible to call the play elegant; but it's problematic if the player's vision or intention enters into the evaluation - I'm not necessarily saying that it shouldn't, but I would prefer to avoid questions of intentionality, here at least. Belladonna's motives might have been the same as Seres': but the relationship of the outcome to the deceptive play renders Belladonna's play elegant. Both plays created new worlds; but Belladonna went one step further and created a specific thing, an entry, in that new world.
One of the great bridge books for intricate positions. Geza Ottlik was, I assume, the main analyst & Hugh Kelsey (no mean analyst either. As a literary exercise - which was clearly part of its ambition - it was a little heavy-handed but it did raise some interesting ideas. The one that stuck for me was the brief meditation on why we name things; naming is actually a twofold act, categorising first and naming second, and we do it to facilitate memory and execution. In theory, every hand could be worked out as if it was new. In practice, named [[strategies|Strategy and Tactics]] make that working out much easier.
Aesthetics, insofar as it's been the province of the philosophy department for a very long time, and the art department for slightly less time, is a mess. Sadly, it seems likely that in all that mess will be the odd pearl of wisdom, so I suspect I will have to jump down and dig through it at some stage. In the meantime I thought I had a brainwave; surely all those characters in the IT department who spent their lives playing computer games, would have some ideas about what makes a good game. This was not my most productive research idea ever, in terms of relevance. Still, I can't say I didn't learn //anything//. [[Computer Game Aesthetics]]

Chess turned out to be a much more directly relevant starting point. [[Chess Aesthetics]]

I haven't spent much time on [[Philosophical aesthetics]] yet.

And this is where I am up to with [[Bridge Aesthetics]]

Probably important to mention that "elegance" is an important idea in [[mathematics|Mathematical Aesthetics]]. I would need to research the details, but I am certain that even when a theorem has been proven, more elegant proofs will continue to be sought, and this seeking after elegance is a legitimate activity within the profession. I've discussed this with a former mathematician (briefly) who agrees that part of the idea of elegance is that one gets a lot from a little; a short proof is //essentially// more elegant than a long one. A big payoff (increasing the "lot") also improves the elegance of a proof; so that if you combine a huge payoff with a simple proof you have something of such blinding elegance that it might almost be invisible. For me, one example of such a proof would be Cantor's (?) proof that the infinity of points on a plane is not of a different order to the infinity of points on a line; not only is that a huge payoff (in terms of being counter intuitive) but the proof is so simple that pretty much anyone with Year 8 maths can understand it. (They may not believe it - in Year 8, for many students, intuition trumps proof - but they will understand it)
<<bridgeHand "2;a,t;k,q,j,7,6,5,4;j,9,3" "k,q,j,5,4,3;5,3;a,8;a,q,t" ";k,j,9,7,6,4,2;t,9;k,7,6,2" "a,t,9,8,7,6;q,8;3,2;8,5,4">>
I used to play bridge; I guess I may play again. In the meantime, I still find myself thinking about it & these are some of my thoughts. I won a couple of national titles; probably my partners would want to take the majority of credit for that. I lost a couple, too, once beaten by a better team, once on countback. If I was ever a good player, or close to a good player, I'd say it was more of a philosophical triumph than one of skill, talent, or discipline.
I used to play bridge; I guess I may play again. In the meantime, I still find myself thinking about it & these are some of my thoughts. I won a couple of national titles; probably my partners would want to take the majority of credit for that. I lost a couple, too, once beaten by a better team, once on countback. If I was ever a good player, or close to a good player, I'd say it was more of a philosophical triumph than one of skill, talent, or discipline.
A very atypical squeeze, in that one of the cards squeezed against is a trump. 
<<bridgeHand "q,7,6,4,2;8,6;k,q;k,q,j,t" "k,j,t,9;k,5,4;9,7,6,5,3;2" "a;a,q,9,2;t,4,2;A,9,8,7,6" "8,5,3;j,t,7,3;a,j,8;5,4,3">>

This is the hand reported as the "Seres Squeeze", although now it is typically reported as a subclass of the Backwash. The key position is as below, with &clubs; as trumps.

||||||&spades;|Q|7|||
||||||@@color:red;&hearts;@@|-||||
||||||@@color:red;&diams;@@|-||||
||||||&clubs;|K|||||
|&spades;|-||||&lceil;|@@font-weight:bold;n@@|&rceil;||&spades;|K|||||||
|@@color:red;&hearts;@@|J||||@@font-weight:bold;w@@||||@@color:red;&hearts;@@|-|||||||
|@@color:red;&diams;@@|J||||||@@font-weight:bold;e@@||@@color:red;&diams;@@|9|7|||||||
|&clubs;|3||||&lfloor;|@@font-weight:bold;s@@|&rfloor;||&clubs;|-||||||
||||||&spades;|-|||||
||||||@@color:red;&hearts;@@|9||||
||||||@@color:red;&diams;@@|T||||
||||||&clubs;|A||||
|borderless|k

South ruffs the &spades;7, establishing the spades;Q, and West is doomed. Pitching either red card allows South to coup East's trump, while an under-ruff would allow South to cash dummy's established &spades;Q. This is a very unusual squeeze position, in that the victim is squeezed in three singletons; also, the fact that one of the singletons is a trump makes the position quite remarkable. Furthermore, in a way, all the threats are in declarer's hand; dummy is already high.
[[The greatest of them all.|http://bridgefiles.net/Person/Belladonna_Giorgio.htm]]
#[[Symmetric Relay]] was, when first published, an astonishing achievement in terms of simplicity, comprehensiveness and memorability. It was light years ahead of other other relay systems extant at the time.
#The [[GF NT]] has the sort of elegance of the hippopotamus; not immediately apparent, but it grows over time.
#Splinter bids, allowing when successful the maximum value of fitting hands to be achieved.
#European Multi - unexpected, angular & strangely effective. And cheap.   
#''NATURAL''
#[[Forcing Pass]]
Aesthetics maps an emotional response from subject back onto object. People prefer not to interrogate themselves and say "Why do I feel this way?"; they prefer to look at something outside themselves and ask, "Why does it make me feel this way?". "Feel" is, of course, a //state// verb in English, which means that [[causation]] is abrogated; still, abrogating responsibility along with causation seems to be going too far. Having inscribed a set of values onto the object, or the class of objects, as the case may (well) be, another debate is initiated, to wit, "What does it mean when someone disputes my inscription?". (I'm often accused of being unclear in my writing - the above paragraph claims that aethetics is a system in the viewer rather than the object viewed, and that arguments about aesthetics are arguments about systems and not arguments about objects. It makes some other claims as well, but that's the core)

In this project, I am going to map my emotional responses to a subset of features of the game of bridge, related to the play of the hand. I might tackle the [[aesthetics of bidding|Bidding Aesthetics]] later. I a/m also going to try an describe the formal elements that evoke that response as accurately and abstractly as possible, //for the sole purposes of predicting my future//. It's been rolling around in my head that I need to think about the [[aesthetics of the partnership aspect of the game|Partnership Aesthetics]], which covers both bidding and play.

I got off to a slow start when I tried to define some abstract ideas first, so I decided to look at some hands. The only book I had handy (see my [[biog|Autobiography]]) was @@color:red;font-weight:bold; Bridge with the Blue Team@@, and if aesthetics meant "worthy of being published" then at least three people (the author, the publisher, and I) would have successfully agreed on an aesthetic system. I love this book. All the hands are worth publishing. But within that broad category I'm sure something more fine-grained can be uncovered.

I love the to-and-fro with generalising and particularising; first [[Forquet]] generalises, a group of hands worth publishing. Then he particularises, hands with different themes - in his introduction he specifically notes this. Then he generalises again, in the interests of, say, narrative structure, so we get little clusters of similar hands; sufficiently similar to be so named (amongst others, Belladonna's Strip Tease, Garrozzo's Strip Tease, My Own Strip Tease - although, interestingly, Belladonna's hand is in a completely different play category from the other two). The I come along and decide to look for my own generalisations; having found those I will doubtless particularise all over again. It's a bit like breathing; I'm not sure that I can not do it.

Anyway, back when I started thinking about this, the question that was uppermost in my mind was to find a definition of [[elegance]]; now, I think that [[elegance]] is just one part of something more complex. Originally I had an idea that [[elegance]] was an [[epitome]]; now, I'm beginning to think that it's a subtype, a particular kind of aesthetic category.

In the [[Squeezes]] entry I've put one marker in the ground by stating that //prima facie// squeezes aren't elegant, although I'm allowing myself some wiggle room to refine that idea later. Here's the marker for the other end of the continuum, a hand type that I feel is //always// - please allow some rhetorical leeway - elegant: [[falsecards|Falsecards]]. I can quickly point to @@color:red;font-weight:bold; Bridge with the Blue Team@@ for support in terms of the //noteworthiness// of these two types of play: of 140 hands discussed, 51 canvass squeeze positions, and 21 include deception as at least part of the narrative.

These are great squeeze hands, but [[Knowing the Theory is Enough]] (a non-simultaneous double) pretty much sums it up. These hands are a great exhibition of documented technique; they show a mastery of some section of the theoretical literature. Having said that, the [[Winnipeg Coup]], which produces 2 tricks from a 2-suit squeeze, and [[Changing Tack]], an entry-shifter, are special hands. I'm not sure that these squeezes were necessarily documented before they were played, which makes them impressive over-the-table discoveries. It's not clear how to distinguish this "newness" from the kind of newness that I claim in [[Falsecards]] is part of the concept of elegance, but I continue to want to make such a distinction.

Two of my favourite falsecard hands are [[A Farsighted Move]] and [[An Almost Unbeatable Contract]]
<<bridgeHand "9,6,4,3;a,8,6;k,5;q,8,7,6" "7,5,2;7,5,3,2;6,4;t,9,3,2" "a,k,q,j,t,8;k,q,4;9,7,3,2;;" ";j,t,9;a,q,j,t,8;a,k,j,5,4">>

This might be the first reported entry-shifting squeeze. I really don't know if Forquet discovered this at the table (he admits that he didn't foresee the end position at trick 1, where he [[heuristically|heuristic]] ruffed high, thus keeping the - later essential - &spades;8 ), but irrespective, it's a very rare hand. (//Confession: I had one once, but miscounted the sides suits and ended in the wrong hand. I'm still cross.//)

If you're not familiar with the critical point of the entry shift, it looks like this:

||||||&spades;|9|6|||
||||||@@color:red;&hearts;@@|-||||
||||||@@color:red;&diams;@@|-||||
||||||&clubs;|Q|4||||
|&spades;|-||||&lceil;|@@font-weight:bold;n@@|&rceil;||&spades;|3|||||||
|@@color:red;&hearts;@@|-||||@@font-weight:bold;w@@||||@@color:red;&hearts;@@|5|||||||
|@@color:red;&diams;@@|Q|9|||||@@font-weight:bold;e@@||@@color:red;&diams;@@|-||||||||
|&clubs;|A|J|||&lfloor;|@@font-weight:bold;s@@|&rfloor;||&clubs;|T|9|||||
||||||&spades;|T|8||||
||||||@@color:red;&hearts;@@|-||||
||||||@@color:red;&diams;@@|8|4|||
||||||&clubs;|-||||
|borderless|k

When South plays the &spades;8, West must unguard a minor and South arranges to win the trick in the appropriate hand to ruff that minor good. What makes these hands interesting - apart from their rarity at the table - is the intense spotlight on the issue of entries. Entries are a theme in card play generally, and a particular focus in squeeze play (//see [[Love]]//), so one is, perhaps, hyper-aware of entry-related matters. Here, you need twice as many entries as a normal squeeze, both to set up ''and'' cash your winners post-squeeze PLUS, unlike other squeezes (except some non-simultaneous doubles), the squeeze card is part of the entry arrangement.  
Inevitably, chess has a significant literature on aesthetics. Wikipedia suggests, as a starting point, the following:
|expediency||
|disguise||
|sacrifice||
|correctness||
|preparation||
|paradox|anti-heuristic|
|unity||
|originality||

Chess also has a well developed sub-field of compositions - bridge, perhaps, does not, although [[par problems]] might roughly parallel compositions - which has its own aesthetics, which overlap and influence ideas of aesthetics in the over-the-board game. Actually, I don't, in general, want to explicitly compare bridge and chess; my feeling is that they are radically different [[games]].
Conway's Life - the only thing I know about cellular automata.
/*
  TiddlyWiki Comments Plugin - Online demo at http://tiddlyguv.org/CommentsPlugin.html

  TODO:
  - Support Cascade comment delete when the top-level tiddler is deleted
  - Support more than one < <comments> > per tiddler. This will probably entail creating an invisible root tiddler to
    hold all the comments for a macro together. The user will need to provide an ID for this tiddler.
  - Don't use global "macro" var (use "macro" param a la jquery)
  - Sort by tiddler title or duration

*/

/***
|Name|CommentsPlugin|
|Description|Macro for nested comments, where each comment is a separate tiddler.|
|Source|http://tiddlyguv.org/CommentsPlugin.html#CommentsPlugin|
|Documentation|http://tiddlyguv.org/CommentsPlugin.html#CommentsPluginInfo|
|Version|0.1|
|Author|Michael Mahemoff, Osmosoft|
|''License:''|[[BSD open source license]]|
|~CoreVersion|2.2|
***/

/*{{{*/
if(!version.extensions.CommentsPlugin) {

  version.extensions.CommentsPlugin = {installed:true};

  (function(plugin) {

  var cmacro = config.macros.comments = {



init: function() {
  var stylesheet = store.getTiddlerText(tiddler.title + "##StyleSheet");
  if (stylesheet) { // check necessary because it happens more than once for some reason
    config.shadowTiddlers["StyleSheetCommentsPlugin"] = stylesheet;
    store.addNotification("StyleSheetCommentsPlugin", refreshStyles);
  }
  if (!version.extensions.CommentsPlugin.retainViewTemplate) cmacro.enhanceViewTemplate();
},

enhanceViewTemplate: function() {
  var template = config.shadowTiddlers.ViewTemplate;
  if ((/commentBreadcrumb/g).test(template)) return; // already enhanced
  var TITLE_DIV = "<div class='title' macro='view title'></div>";
  var commentsDiv = "<div class='commentBreadcrumb' macro='commentBreadcrumb'></div>";
  config.shadowTiddlers.ViewTemplate = template.replace(TITLE_DIV,commentsDiv+"\n"+TITLE_DIV);
},

handler: function(place,macroName,params,wikifier,paramString,tiddler) {
  var macroParams = paramString.parseParams();
  var tiddlerParam = getParam(macroParams, "tiddler");
  tiddler = tiddlerParam ? store.getTiddler(tiddlerParam) : tiddler;
  if (!tiddler || !store.getTiddler(tiddler.title)) return;
  cmacro.buildCommentsArea(tiddler, place, macroParams);
  // cmacro.refreshCommentsFromRoot(story.getTiddler(tiddler.title).commentsEl, tiddler, macroParams);
  cmacro.refreshCommentsFromRoot(place.commentsEl, tiddler, macroParams);
},


buildCommentsArea: function(rootTiddler, place, macroParams) {
  var commentsArea = createTiddlyElement(place, "div", null, "comments");
  var heading = getParam(macroParams, "heading");
  if (heading) createTiddlyElement(commentsArea, "h1", null, null, heading);
  var comments = createTiddlyElement(commentsArea, "div", null, "");
  place.commentsEl = comments;

  if (cmacro.editable(macroParams)) {
    var newCommentArea = createTiddlyElement(commentsArea, "div", null, "newCommentArea", "New comment:");
    cmacro.forceLoginIfRequired(params, newCommentArea, function() {
      var newCommentEl = cmacro.makeTextArea(newCommentArea, macroParams);
      // var addComment = createTiddlyElement(newCommentArea, "button", null, "addComment button", "Add Comment");
      var addComment = createTiddlyButton(newCommentArea, "Add Comment", null, function() {
        var comment = cmacro.createComment(newCommentEl.value, rootTiddler, macroParams); 
        newCommentEl.value = "";
        cmacro.refreshCommentsFromRoot(comments, rootTiddler, macroParams);
      }, "addComment button");
    });
  }

},


makeTextArea: function(container, macroParams) {
  var textArea = createTiddlyElement(container, "textarea");
  textArea.rows = getParam(macroParams, "textRows") || 4;
  textArea.cols = getParam(macroParams, "textCols") || 20;
  textArea.value = getParam(macroParams, "text") || "";
  return textArea;
},

refreshCommentsFromRoot: function(rootCommentsEl, rootTiddler, macroParams) {
  cmacro.treeifyComments(rootTiddler);
  cmacro.refreshComments(rootCommentsEl, rootTiddler, macroParams);
},

refreshComments: function(daddyCommentsEl, tiddler, macroParams) {

  var commentsEl;
  if (tiddler.fields.daddy) {
    var commentEl = cmacro.buildCommentEl(daddyCommentsEl, tiddler, macroParams);
    daddyCommentsEl.appendChild(commentEl);
    commentsEl = commentEl.commentsEl;
  } else { // root element
    removeChildren(daddyCommentsEl);
    // refreshedEl = story.getTiddler(tiddler.title);
    commentsEl = daddyCommentsEl;
  }

  for (var child = tiddler.firstChild; child; child = child.next) {
     cmacro.refreshComments(commentsEl, child, macroParams);
  }

},

// This has become more complex due to "confused comments" - multiple comments
// pointing back to the same daddy (which implies they all think they're the first
// child) or a single "2nd-last" sibling (which implies they all think they're the
// last sibling). This happens in the typical "atomic transaction 101" scenario -
// user A opens wiki, user B opens wiki, one of the users submits a comment, 
// the other user submits a comment.
//
// Normally, each comment says "make my daddy's first child be me", or "make my prev
// sibling's next sibling be me". That's how the tree gets built. But to deal
// with confused comments, we now have to check if daddy/prev is already pointing
// to something. If so, we will have to walk through the list to find the right place
// for the new item.
//
// We begin by sorting by date; if we can assume we are walking through the comments by date, 
// the confused comments will appear in the right order.
treeifyComments: function(rootTiddler) {

  // First, clear the tree data
  // We sort the comments to ensure "confused" comments
  var comments = cmacro.findCommentsFromRoot(rootTiddler).sort(function(a,b) {
    return a.modified > b.modified;
  });
  var nodes=comments.concat(rootTiddler);
  for (var i=0; i<nodes.length; i++) {
    delete nodes[i]["firstChild"];
    delete nodes[i]["next"];
  }

  // Now walk through each comment
  cmacro.forEach(comments, function(comment) {
    var prev = comment.fields.prev;
    var daddy = comment.fields.daddy;
    if (prev) {
      var prevTiddler = store.getTiddler(prev);
      if (prevTiddler.next) {
        for (var lastChild=prevTiddler.next; lastChild.next; lastChild=lastChild.next)
          ;
        lastChild.next = comment;
      // } else {
      } else {
        prevTiddler.next = comment;
      }
    } else {
      var daddyTiddler = store.getTiddler(daddy);
      if (daddyTiddler.firstChild) {
        for (var lastChild=daddyTiddler.firstChild; lastChild.next; lastChild=lastChild.next)
          ;
        lastChild.next = comment;
      } else {
        daddyTiddler.firstChild = comment;
      }
    }
  });
  for (var i=0; i<comments.length; i++) {
    var c=comments.sort()[i];
  }

},

logComments: function(comments) {
  for (var i=0; i<comments.length; i++) {
    var comment = comments[i];
  }
},

findCommentsFromRoot: function(rootTiddler) {
  var comments = [];
  store.forEachTiddler(function(title,tiddler) {
    if (tiddler.fields.root==rootTiddler.title) comments.push(tiddler);
  });
  return comments;
},

findChildren: function(daddyTiddler) {
  var comments = [];
  store.forEachTiddler(function(title,tiddler) {
    if (tiddler.fields.daddy==daddyTiddler.title) comments.push(tiddler);
  });
  return comments;
},

buildCommentEl: function(daddyCommentsEl, comment, macroParams) {

  // COMMENT ELEMENT
  var commentEl = document.createElement("div");
  commentEl.className = "comment";

  // HEADING <- METAINFO AND DELETE
  var headingEl = createTiddlyElement(commentEl, "div", null, "heading");

  var metaInfoEl = createTiddlyElement(headingEl, "div", null, "commentTitle",  comment.modifier + '@' + comment.modified.formatString(getParam(macroParams,"dateFormat") || "DDD, MMM DDth, YYYY hh12:0mm:0ss am"));
  metaInfoEl.onclick = function() { 
    // story.closeAllTiddlers();
    story.displayTiddler("top", comment.title, null, true);
    // document.location.hash = "#" + comment.title;
  };

  var deleteEl = createTiddlyElement(headingEl, "div", null, "deleteComment", "X");
  deleteEl.onclick = function() {
    if (true || confirm("Delete this comment and all of its replies?")) {
      cmacro.deleteTiddlerAndDescendents(comment);
      commentEl.parentNode.removeChild(commentEl);
    }
  };

  // TEXT
  commentEl.text = createTiddlyElement(commentEl, "div", null, "commentText");
  wikify(comment.text, commentEl.text);

  // REPLY LINK
  if (cmacro.editable(macroParams)) {
    var replyLinkZone = createTiddlyElement(commentEl, "div", null, "replyLinkZone");
    var replyLink = createTiddlyElement(replyLinkZone, "span", null, "replyLink", "reply to this comment");
    replyLink.onclick = function() { cmacro.openReplyLink(comment, commentEl, replyLink, macroParams); };
  }

  // var clearance = createTiddlyElement(commentEl, "clearance", null, "clearance");
  // clearance.innerHTML = "&nbsp;";

  // COMMENTS AREA
  commentEl.commentsEl = createTiddlyElement(commentEl, "div", null, "comments");

  // RETURN
  return commentEl;

},

openReplyLink: function(commentTiddler, commentEl, replyLink, macroParams) {
  if (commentEl.replyEl) {
    commentEl.replyEl.style.display = "block";
    return;
  }

  commentEl.replyEl = document.createElement("div");
  commentEl.replyEl.className = "reply";

  replyLink.style.display = "none";
  var newReplyHeading = createTiddlyElement(commentEl.replyEl, "div", null, "newReply");
  createTiddlyElement(newReplyHeading, "div", null, "newReplyLabel", "New Reply:");
  var closeNewReply = createTiddlyElement(newReplyHeading, "div", null, "closeNewReply", "close");
  closeNewReply.onclick = function() {
    commentEl.replyEl.style.display = "none";
    replyLink.style.display = "block";
  };

  cmacro.forceLoginIfRequired(params, commentEl.replyEl, function() {
    var replyText =  cmacro.makeTextArea(commentEl.replyEl, macroParams);
      var submitReply = createTiddlyButton(commentEl.replyEl, "Reply", null, function() {
        var newComment = cmacro.createComment(replyText.value, commentTiddler, macroParams);
        replyText.value = "";
        closeNewReply.onclick();
        cmacro.refreshComments(commentEl.commentsEl, newComment, macroParams);
      });
  });

  commentEl.insertBefore(commentEl.replyEl, commentEl.commentsEl);
},


createComment: function(text, daddy, macroParams) {

  var rootTitle = daddy.fields.root ? daddy.fields.root : daddy.title;
    // second case is the situation where daddy *is* root
  var newComment = cmacro.createCommentTiddler(macroParams, rootTitle);
  var fieldsParam = getParam(macroParams, "fields") || "";
  var fields = fieldsParam.decodeHashMap();
  var inheritedFields = (getParam(macroParams, "inheritedFields") || "").split(",");
  cmacro.forEach(inheritedFields, function(field) {
    if (field!="") fields[field] = daddy.fields[field];
  });
  var tagsParam = getParam(macroParams, "tags") || "comment";
  var now = new Date();
  newComment.set(null, text, config.options.txtUserName, now, tagsParam.split(","), now, fields);

  var youngestSibling = cmacro.findYoungestChild(daddy)
  if (youngestSibling) newComment.fields.prev = youngestSibling.title;
  newComment.fields.daddy = daddy.title;
  newComment.fields.root = rootTitle;

  cmacro.saveTiddler(newComment.title);
  autoSaveChanges(false);
  return newComment;
},

findYoungestChild: function(daddy) {

  var siblingCount = 0;
  var elderSiblings = cmacro.mapize(cmacro.selectTiddlers(function(tiddler) {
    isChild = (tiddler.fields.daddy==daddy.title);
    if (isChild) siblingCount++;
    return isChild;
  }));
  if (!siblingCount) return null;

  // Find the only sibling that doesn't have a prev pointing at it
  var youngestSiblings = cmacro.clone(elderSiblings) // as a starting point
  cmacro.forEachMap(elderSiblings, function(tiddler) {
    delete youngestSiblings[tiddler.fields.prev];
  });

  for (title in youngestSiblings) { return youngestSiblings[title]; }

},

// The recursive delete is run by a separate function (nested inside
// this one, for encapsulation purposes).
deleteTiddlerAndDescendents: function(tiddler) {

  function deleteRecursively(tiddler) {
    for (var child = tiddler.firstChild; child; child = child.next) {
      deleteRecursively(child);
    }
    store.removeTiddler(tiddler.title);
  }

  cmacro.treeifyComments(store.getTiddler(tiddler.fields.root));

  // save some info prior to deleting
  var prev = tiddler.fields.prev;
  var next = tiddler.next;

  deleteRecursively(tiddler);

  // used saved info
  if (next) {
    next.fields.prev = prev;
    cmacro.saveTiddler(next.title);
  }

  autoSaveChanges(false);

},


forEach: function(list, visitor) { for (var i=0; i<list.length; i++) visitor(list[i]); },
forEachMap: function(map, visitor) { for (var key in map) visitor(map[key]); },
select: function(list, selector) { 
  var selection = [];
  cmacro.forEach(list, function(currentItem) {
    if (selector(currentItem)) { selection.push(currentItem); }
  });
  return selection;
},
selectTiddlers: function(selector) { 
  var tiddlers = [];
  store.forEachTiddler(function(title, tiddler) {
    var wanted = selector(tiddler);
    if (wanted) tiddlers.push(tiddler);
  });
  return tiddlers;
},
map: function(list, mapper) { 
  var mapped = [];
  cmacro.forEach(list, function(currentItem) { mapped.push(mapper(currentItem)); });
  return mapped;
},
remove: function(list, unwantedItem) {
  return cmacro.select(list,
        function(currentItem) { return currentItem!=unwantedItem; });
},
mapize: function(tiddlerList) {
  var map = {};
  cmacro.forEach(tiddlerList, function(tiddler) { map[tiddler.title] = tiddler; });
  return map;
},
clone: function(map) { return merge({}, map); },


editable: function(params) {
  var editable = getParam(params, "editable");
  return (!editable || editable!="false");
},

needsLogin: function(params) {
  var loginCheck = getParam(params, "loginCheck");
  return loginCheck && !window[loginCheck]();
},

forceLoginIfRequired: function(params, loginPromptContainer, authenticatedBlock) {
  if (cmacro.needsLogin(params)) wikify("<<"+getParam(macroParams, "loginPrompt")+">>", loginPromptContainer);
  else authenticatedBlock();
},


mergeReadOnly: function(first, second) {
  var merged = {};
  for (var field in first) { merged[field] = first[field]; }
  for (var field in second) { merged[field] = second[field]; }
  return merged;
},

// callers may replace this with their own ID generation algorithm
createCommentTiddler: function(macroParams, rootTitle) {
  // var titleFormat = getParam(macroParams, "titleFormat") || "%root%Comment"; 
  var prefix = rootTitle+"Comment"; // was "_comment"
  if (!store.createGuidTiddler) return store.createTiddler(prefix+((new Date()).getTime()));
  return store.createGuidTiddler(prefix);
},
saveTiddler: function(tiddler) {
  var tiddler = (typeof(tiddler)=="string") ? store.getTiddler(tiddler) : tiddler; 
  store.saveTiddler(tiddler.title, tiddler.title, tiddler.text, tiddler.modifier, tiddler.modified, tiddler.tags, cmacro.mergeReadOnly(config.defaultCustomFields, tiddler.fields), false, tiddler.created)
},
log: function() { if (console && console.firebug) console.log.apply(console, arguments); },
assert: function() { if (console && console.firebug) console.assert.apply(console, arguments); },


copyFields: function(fromTiddler, toTiddler, field1, field2, fieldN) {
  for (var i=2; i<arguments.length; i++) {
    fieldKey = arguments[i];
    if (fromTiddler.fields[fieldKey]) toTiddler.fields[fieldKey] = fromTiddler.fields[fieldKey];
  }
}
}

config.macros.commentsCount = {
  handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    var count = 0;
    if (tiddler && store.getTiddler(tiddler.title)) {
      var rootTiddler = paramString.length ? paramString : tiddler.title;
      count = config.macros.comments.findCommentsFromRoot(store.getTiddler(rootTiddler)).length;
    }
    createTiddlyText(place, count);
  }
},

config.macros.commentBreadcrumb = {
  handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    if (!tiddler.fields.root) return;
    var rootLink = createTiddlyElement(place, "span", null, null);
    createTiddlyLink(rootLink, tiddler.fields.root, true);

    var rootIsParent = tiddler.fields.daddy==tiddler.fields.root;
    var rootIsGrandparent = (store.getTiddler(tiddler.fields.daddy)).fields.daddy==tiddler.fields.root;

    if (!rootIsParent) {
      if (!rootIsGrandparent) createTiddlyElement(place, "span", null, null, " > ... ");
      createTiddlyElement(place, "span", null, null, " > ");
      var daddyLink = createTiddlyElement(place, "span", null, null);
      createTiddlyLink(daddyLink, tiddler.fields.daddy, true);
    }

    createTiddlyElement(place, "span", null, null, " > ");

    // place.appendChild(createTiddlyLink(tiddler.fields.root));
  }
}

config.macros.tiddlyWebComments = {};
config.macros.tiddlyWebComments.handler =
  function(place,macroName,params,wikifier,paramString,tiddler) {
    paramString = "fields:'server.workspace:bags/comments' inheritedFields:'server.host,server.type'";
    config.macros.comments.handler(place,macroName,params,wikifier, paramString,tiddler);
  };

function log() { if (console && console.firebug) console.log.apply(console, arguments); }

})(version.extensions.CommentsPlugin);


/***
!StyleSheet

.comments h1 { margin-bottom: 0; padding-bottom: 0; }
.comments { padding: 0; }
.comment .comments { margin-left: 1em; }

.comment { padding: 0; margin: 1em 0 0; }
.comment .comment { margin 0; }
.comment .toolbar .button { border: 0; color: #9a4; }
.comment .heading { background: [[ColorPalette::PrimaryPale]]; color: [[ColorPalette::PrimaryDark]]; border-bottom: 1px solid [[ColorPalette::PrimaryLight]]; border-right: 1px solid [[ColorPalette::PrimaryLight]]; padding: 0.5em; height: 1.3em; }
.commentTitle { float: left; }
.commentTitle:hover { text-decoration: underline; cursor: pointer; }
.commentText { clear: both; padding: 1em 1em; }
.deleteComment { float: right; cursor: pointer; text-decoration:underline; color:[[ColorPalette::SecondaryDark]]; padding-right: 0.3em; }
.comment .reply { margin-left: 1em; }
.comment .replyLink { color:[[ColorPalette::SecondaryDark]]; font-style: italic; 
                     cursor: pointer; text-decoration: underline; margin: 0 1em; }
.comment .created { }
.comment .newReply { color:[[ColorPalette::SecondaryDark]]; margin-top: 1em; }
.newReplyLabel { float: left; }
.closeNewReply { cursor: pointer; float: right; text-decoration: underline; }
.comments textarea { width: 100%; padding: 0.3em; margin-bottom: 0.6em; }
.newCommentArea { margin-top: 0.5em; }

.clearance { clear: both; }


!(end of StyleSheet)

***/

  config.macros.comments.init();

} // end of 'install only once'
/*}}}*/

// function log() { if (console && console.firebug) console.log.apply(console, arguments); }
On one level, //in this field//, a game is aesthetic if it is playable. (find reference) That's plausible in an environment where hundreds of games are mooted and few make it to the marketplace and even fewer are commercially successful; it's easy to see how "aesthetic" might serve as a shorthand for the largely intuitive balancing of many difficult-to-quantify factors. After all, in its home territory, aesthetics serves a similar purpose of articulating intuition. 

Other meanings have been assigned to it as well. It's not uncommonly used as a rubric for discussing visual and/or sound design; a fairly conservative use, not moving far from the art world. There is also way in which established arguments in aesthetics are pressed into service to explore the question of whether or not computer games might be art; to my mind a trivial question.

One paper I read uses "Aesthetics" as the name for his typology of "fun" elements of gameplay. (Hunicke, 2005 ) 
|!Type|!Game as|
|Sensation|sense-pleasure |
|Fantasy|make-believe|
|Narrative|drama|
|Challenge|obstacle course|
|Fellowship|social framework|
|Discovery|uncharted territory |
|Expression|self-discovery |
|Submission|pastime|

These ideas are probably not going to be relevant to my thinking about the aesthetics of bridge, although as an explanation of why bridge has been such a successful game this framework might have some argumentative value.

/* note to self - perhaps one could evaluate a hand (should I look for a more abstract term to include all play events?) in terms of its contribution to an evaluation on the value matrix above? */
WelcomeToBridge [[Aesthetics]]
There are lots of double squeezes; let's attempt a definition and say that both hands are squeezed in one common suit & one (each) unique suit. Sometimes one begins with two common suits, and the deal reduces to one common suit, which may require card reading. They may be simultaneous - both players are squeezed on the same trick - or [[non-simultaneous|Knowing the Theory is Enough]] - one player is squeezed first and the other on a subsequent trick.

All double squeezes have a [[positional]] element. The double squeeze is the building block for most of the extremely complex squeezes. This however, despite appearances, is not a squeeze wiki. 

A simple double squeeze end position:

||||||&spades;|A|2|||
||||||@@color:red;&hearts;@@|-||||
||||||@@color:red;&diams;@@|-||||
||||||&clubs;|K|||||
|&spades;|Q|J|||&lceil;|@@font-weight:bold;n@@|&rceil;||&spades;|K|5||||||
|@@color:red;&hearts;@@|-||||@@font-weight:bold;w@@||||@@color:red;&hearts;@@|-|||||||
|@@color:red;&diams;@@|-||||||@@font-weight:bold;e@@||@@color:red;&diams;@@|A||||||||
|&clubs;|A||||&lfloor;|@@font-weight:bold;s@@|&rfloor;||&clubs;|-||||||
||||||&spades;|8|||||
||||||@@color:red;&hearts;@@|A||||
||||||@@color:red;&diams;@@|K||||
||||||&clubs;|-||||
|borderless|k

South cashes the @@color:red;&hearts;@@A. West must discard a &spades; to retain the high &clubs;. North can now pitch the useless &clubs;K (this is the [[positional]] aspect of the squeeze) and East is caught in a simple &spades;/@@color:red;&diams;@@ squeeze because West has been compelled to unguard the &spades;. Neat, heh?
To me, a good falsecard is always elegant. This immediately invites accusations of circularity, of course, because what's a "bad" falsecard? The quick answer would be, One that doesn't work, and the literature has plenty of those as cautionary tales. The oldest that springs to my mind is exploited by [[S.J.Simon]]'s "Unlucky Expert" - I forget the name of the perpetrator, some half-smart character "//epithet// Willy" as I recall. This theme, the falsecard exploited by opponents, is probably more accessible in the myriads of "brilliant" falsecards perpetrated by [[Mollo]]'s Papa the Greek which only allow the Hideous Hog a startling path to make an otherwise unmakeable contract. These are transparently not good falsecards.

There is another category of falsecards which I am deeming not "good", without wishing to condemn them as bad, and these are the routine falsecards; T from Tx or T9x, in the first instance to ensure that declarer cannot reliably take the T as a proxy for QT, in the second to maintain a guess for declarer between a (defensive) holding of T9 and T9x; a high pip from declarer to conceal a low pip, and thus the exact meaning of defenders' signals; others may spring to mind. These plays do not achieve //deception//; just //doubt// - insufficient to be labelled elegant. I'm making a distinction here between plays that create a //possibility// of a world while the target of the play remains aware of the multiple possibilities - doubt - and those plays where the //possibility// blots out alternatives from the target's mind. Put that way it becomes clear that repetition of a deceptive theme may shift if from the category of //deception// to that of //doubt//.

||||||&spades;|J|9|4||
||||||@@color:red;&hearts;@@|?||||
||||||@@color:red;&diams;@@|?||||
||||||&clubs;|8|||||
|&spades;|8|7|3||&lceil;|@@font-weight:bold;n@@|&rceil;||&spades;|Q|T||||||
|@@color:red;&hearts;@@|?||||@@font-weight:bold;w@@||||@@color:red;&hearts;@@|?|||||||
|@@color:red;&diams;@@|?||||||@@font-weight:bold;e@@||@@color:red;&diams;@@|?||||||||
|&clubs;|?||||&lfloor;|@@font-weight:bold;s@@|&rfloor;||&clubs;|?||||||
||||||&spades;|A|K|6|5|2|
||||||@@color:red;&hearts;@@|?||||
||||||@@color:red;&diams;@@|?||||
||||||&clubs;|A||||
|borderless|k

This situation is fairly well known; South cashes the &spades;A and East plays the Q; South, believing it to be singleton, hooks the 9 and loses to the T. If East doesn't do this, South has no option but to cash the &spades;K next, inevitably picking up the QT. Perhaps it's so well known as to fall into the category of compulsory falsecards - but note that in the final of a world championship, holding an analogous KT under the AQ, a reasonably famous expert (Kantar) failed to find the "compulsory" play. (Not that it would have succeeded) On the other hand:
<<bridgeHand "A;k,4;a,q,6,5,2;a,q,j,9,4" "k,j,7,6,3,2;7;8,4,3;t,7,5" "Q,9,5,4;Q,8,6,2;j,9,8;K,8" "t,8;a,j,t,9,5,3;k,t;6,3,2">>

In hand with the &clubs;K, South led the @@color:red;&diams;@@8 to the K (!) and A before finessing the 10 unsuccessfully on the next round. ''Now'' West cashed the @@color:red;&hearts;@@A and gave his partner a ruff - if he'd tried that at trick one South could not have gone wrong in trumps. Believe me, declarer was shocked; I never considered the KT option, despite its (retrospectively) obvious analogy with QT. For these reasons then, Kantar's and my own obliviousness (you can believe I wrote this article just to include that conjunction, if you like), I believe the ~K-from-KT falsecard is a candidate for elegance, where the ~Q-from-QT is not. Where the Q, like the rest of the automatic falsecards, merely raises a jaundiced eyebrow from the opponent(s), the K creates a new, albeit fictitious, reality. In that //newness// lies some part of my ideas about the attributes of elegance.
3 things underpin Forcing Pass. First, the incredible additional number of hands you can show by relaying below 3NT (610 vs 377 after a strong &clubs;). Mind you, it turns out not to be much of a practical advantage. Second, at least as far as [[Regres]] went, the recognition that 8-12 was the most common point range for a hand meshes with the idea of using opening bids to describe these common hands. Another theoretical idea that probably didn't stand the "praxis" test, although the atempts to regulate FP out of existence inevitably render that judgement problematic. Third, the desire to entertain/amuse/transgress.
[[see|http://en.wikipedia.org/wiki/Pietro_Forquet]] - sorry, the WBF link was too slow. 
Gallus variety, NOT the Austrian implementation.
You don't meet a lot of guard squeezes. This is a double guard squeeze, just to ram it home.

||||||&spades;|-||||
||||||@@color:red;&hearts;@@|A|J|||
||||||@@color:red;&diams;@@|J||||
||||||&clubs;|9|||||
|&spades;|||||&lceil;|@@font-weight:bold;n@@|&rceil;||&spades;|-|-||||||
|@@color:red;&hearts;@@|K|7|||@@font-weight:bold;w@@||||@@color:red;&hearts;@@|Q|||||||
|@@color:red;&diams;@@|K||||||@@font-weight:bold;e@@||@@color:red;&diams;@@|Q||||||||
|&clubs;|J||||&lfloor;|@@font-weight:bold;s@@|&rfloor;||&clubs;|Q|5|||||
||||||&spades;|A|||||
||||||@@color:red;&hearts;@@|5||||
||||||@@color:red;&diams;@@|-||||
||||||&clubs;|K|T|||
|borderless|k

When South cashes the &spades;A West cannot pitch the &clubs; J, which is //''guarding''// against the &clubs; finesse, or the @@color:red;&hearts;@@, so must release a @@color:red;&diams;@@. North can now let go of the &club; (the &clubs; threat remains - in South - as a ''length'' threat rather than a ''finesse'' threat) and West //''guard''// squeezed in @@color:red;&hearts;@@, rank squeezed in @@color:red;&diams;@@ and length squeezed in &clubs;.
<<bridgeHand "k,q;a,3,2;a,q,j,3,2;8,5,4" "j,9,8,3;k,q,7,6;9,7;q,3,2" "a,t,7,6;j,8,5;k,t,8;a,k,t" "5,4,2;t,9,4;6,5,4;j,9,7,6">>

This is one of many non-simultaneous double squeezes in the book. After five rounds of &diams; East can't hold @@color:red;&hearts;@@ and &spades; on the 2nd round of &clubs;, while West can't hold @@color:red;&hearts;@@ and &clubs; on the third round of &spades;.

I've always had a particularly soft spot for non-simultaneous doubles. I should state my self-interest, the family includes one of my personal memorable hands, of which there are not so many. Viewed quickly (superficially) they seem to violate the "rectification of the count" principle... how can one hand be squeezed before the other without necessarily having an idle card? (The answer lies in closer inspection; the first defender hand is squeezed in four cards, the second in three) Is it this apparent contradiction that makes me prepared to consider them as candidates for elegance, or is it the fact that they stand apart from the remainder of the squeeze family, where simultaneity (or sequentiality in the case of triples & backwashes) rules?

I've simplified the question to an extent by ruling out all squeezes, but the ideas of "(apparent) violation of rules" and "unique subtype of class" are related to the idea of elegance.
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
 major: 1, minor: 1, revision: 0, 
 date: new Date("mar 17, 2007"), 
 source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};

if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};

bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
 if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){ 
 url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
 }
 return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
Clyde Love, author of //Bridge Squeezes Complete// and inventor of the acronym ''BLUE'' - ''B''oth, ''L''eft ''U''nder ''E''ntry
[[WelcomeToBridge]] [[Autobiography]] 
[[Bridge Aesthetics]]
See [[this link|http://en.wikipedia.org/wiki/Mathematical_beauty]]. Lots to be done here; the headings are
#beauty of method
##minimum assumptions
##succinctness
##counter-intuitive
##new and original
##easily generalised
#beauty of result
## cf Hardy ... "inevitability, unexpectedness, economy"
## Rota disagrees on "unexpectedness"
## ''I'' think "inevitability" is a stupid word in this context
#beauty in experience
#beauty & philosophy
#beauty and information theory
#mathematics and art
Victor Mollo, great British rubber player & author of many books, both theoretical and entertaining. Best remembered for his //Menagerie// books, featuring the Hideous Hog, Papa the Greek, the Rueful Rabbit & supporting cast of cheerful (and well wined and dined) losers.
Not that //''imagination''// is a bad thing (see [[Symmetric Relay]])
OK, this is the hand that inspired this wiki: <<bridgeHand  "a,t,8,5,3;a,8;a,6,4;j,8,4" "7,3;q,8,5,3;j,t,6,2;8,4,2" "6,3;j,7,2;k,q,7,4;A,k,t,5" "k,q,j,9;K,7,5,2;5,3;q,9,5">>
The partnership aspect of the games one of the //marked// features of bridge; it seems therefore that as a //classing// quality, it should be eligible to have aesthetics. A well managed auction, where, for example, one player conveys the relevant information and the other player makes the most effective use of it seems to be a candidate. Many users of relay feel that its accuracy & economy are aesthetic - against that it can be argued that relay "eliminates" one partner from the thinking process, which is quintessentially anti-partnership. In tur, against that, it might be argued that the removal of a source of error (partner) from a process at risk of being compromised by error ''is'' a deep response to the partnership aspect of the game. /* For investigation*/ 

As a partnership playing, defence offers potential for collaboration;at some point, say, simultaneous falsecards, that might become aesthetic.
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
	major: 1, minor: 0, revision: 2, 
	date: new Date("Apr 19, 2007"),
	source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
	coreVersion: '2.2.0 (Beta 5)'
};

config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");

merge(config.macros.option.types, {
	'pas': {
		elementType: "input",
		valueField: "value",
		eventName: "onkeyup",
		className: "pasOptionInput",
		typeValue: config.macros.option.passwordInputType,
		create: function(place,type,opt,className,desc) {
			// password field
			config.macros.option.genericCreate(place,'pas',opt,className,desc);
			// checkbox linked with this password "save this password on this computer"
			config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);			
			// text savePasswordCheckboxLabel
			place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
		},
		onChange: config.macros.option.genericOnChange
	}
});

merge(config.optionHandlers['chk'], {
	get: function(name) {
		// is there an option linked with this chk ?
		var opt = name.substr(3);
		if (config.options[opt]) 
			saveOptionCookie(opt);
		return config.options[name] ? "true" : "false";
	}
});

merge(config.optionHandlers, {
	'pas': {
 		get: function(name) {
			if (config.options["chk"+name]) {
				return encodeCookie(config.options[name].toString());
			} else {
				return "";
			}
		},
		set: function(name,value) {config.options[name] = decodeCookie(value);}
	}
});

// need to reload options to load passwordOptions
loadOptionsCookie();

/*
if (!config.options['pasPassword'])
	config.options['pasPassword'] = '';

merge(config.optionsDesc,{
		pasPassword: "Test password"
	});
*/
//}}}
English (Russian) professional bridge player, contemporary of Terence Reese. Author of @@color:red;font-weight:bold; Why You Lose at Bridge@@, one of the great foundational books about bridge. Advocates simplicity and pragmatism.
can be [[positional]] or [[non-positional]]. 

A non-positional simple squeeze looks like this:

||||||&spades;|A|7|||
||||||@@color:red;&hearts;@@|-||||
||||||@@color:red;&diams;@@|-||||
||||||&clubs;|8|||||
|&spades;|-||||&lceil;|@@font-weight:bold;n@@|&rceil;||&spades;|K|Q||||||
|@@color:red;&hearts;@@|J||||@@font-weight:bold;w@@||||@@color:red;&hearts;@@|K|||||||
|@@color:red;&diams;@@|J||||||@@font-weight:bold;e@@||@@color:red;&diams;@@|-||||||||
|&clubs;|3||||&lfloor;|@@font-weight:bold;s@@|&rfloor;||&clubs;|-||||||
||||||&spades;|3|||||
||||||@@color:red;&hearts;@@|Q||||
||||||@@color:red;&diams;@@|-||||
||||||&clubs;|A||||
|borderless|k

When South cashes the &clubs;A, East cannot retain the high @@color:red;&hearts;@@ and the &spades; guard.
//...dark thoughts in a damp month//
Bridge
A family of hand positions where one (or both) partners are unable to maintain their defence to all threats because it would require them to hold more cards than is legal. In my opinion squeezes are ''not'' elegant. They are an extremely interesting topic, and they are certainly ''noteworthy'', but broadly speaking - more argument in the [[main line|Bridge Aesthetics]] - they are not elegant because they are too complicated, or, in the case of the simple squeeze, which, after you get the knack of it, isn't that complicated, too common. "Elegance" encompasses ideas of simplicity and rarity.

Having said that, I might challenge that overview with two subtypes, the "backwash" and the "non-simultaneous double".

Now, it's not easy for me to wipe out squeezes in this cavalier way. I really like them. The first bridge book I read, back when I didn't know that a 2@@color:red;&hearts;@@ response to 1&spades; conventionally showed a 5 card suit to 99.9999% of the bridge playing world, was Clyde [[Love]]'s @@color:red;font-weight:bold;Bridge Squeezes Complete@@ and probably for the first two years that I thought squeezes were the be-all and end-all of card play. It is a great book, but greatness turns out not to correlate with elegance.
 
<<tabs txtCookie [[Simple]] "" [[SimpleText]] [[Double]] "" [[DoubleText]] [[Guard]] "" [[Guardtext]] [[Triple]] "" [[TripleText]] [[Backwash]] "The Seres Squeeze" [[BackwashText]]>>
Strategy; a long term plan. Tactics; a short term plan. In bridge, you could think strategically about a deal, during both the auction and the play, about a match, or about a tournament. Typically, a tactic would be limited to one hand, likewise both in bidding and play. Perhaps throwing a match could be considered a tactic, within some overall strategy of winning the tournament. (As, for instance, //losing the first match in a Swiss// which notionally secures one an easier draw. Although, personally, I always feel this is an alibi, rather than a strategy).

It's interesting to look at [[Winnipeg Coup]]. Did [[Belladonna]] look at his 10 top tricks and think, well, if I run the &diams; given that East has pre-empted in &clubs; West can probably be squeezed in the majors, which would be a strategic approach to the hand, or did he envisage the final four card end position (not actually that hard to do), in which case he played the hand tactically? If the first, at some point in the play, he switched from strategic to tactical.

In his discussion of [[Changing Tack]], Forquet states explicitly that "not yet foreseeing the subsequent developments, but preserving maximum entries on general principles...", acknowledging a strategic (or perhaps, a [[heuristic]] approach).

It's not always clear whether a play is strategic or tactical. A great player is good at both; many weaker players are tactically quite advanced. Good strategic thinking is also part of remaining mentally fresh, requiring less trick-by-trick calculation than a tactical approach.

.borderless, .borderless table, .borderless td, .borderless tr, .borderless th, .borderless tbody { border:0 !important; margin:0 !important; padding:2px !important; td.width:1em !important; td.vertical-align:top !important;margin-left: auto !important; margin-right: auto !important;}

.borderlessL, .borderlessL table, .borderlessL td, .borderlessL tr, .borderlessL th, .borderlessL tbody { border:0 !important; margin:0 !important; padding:2px !important; td.vertical-align:top !important;margin-left: 0 !important; margin-right: auto !important;}
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}
.readOnly {background:[[ColorPalette::TertiaryPale]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity=60)';}
/*}}}*/
Suits/handtype/shortage/shape/controls/placement; one hand shows/one hand asks. A clear and consistent structure with re-use of design themes to assist in learning. (It can be made more efficient, but almost always at the cost of "symmetry").

Because one hand only "asks" (typically by one step relay) it uses only 1/2 the possible auctions, yet is very //efficient//. On the downside, it isn't designed to handle texture & is not good with J's and 10's at a low level.

Assuming that shape showing starts with 1@@color:red;&hearts;@@ (as in most Precision-type strong &clubs; systems) and you can show 377 hands below 4&clubs;. This also (partly) explains the excitement about [[Forcing Pass]] systems: if you start shape-showing at 1@@color:red;&diams;@@ you caqn show 610 hands!!! to the same level.

If, OTOH, you play relay over a strong 2&clubs:, you can only fit in 34 hands (assuming a negative).

There's probably a quantatitive way to measure that efficiency; I haven't worked that out yet, but I can qualitatively describe the notional quantatitive algorithm: the number of pages of system descripton required to describe all GF auctions. In Symmetric, that's ''//really//'' very small. With [[NATURAL]] people just ''//imagine//'' that it's small.




If you had parallel/linked/coupled structure/systems, one for dealing with the world, one for talking about the world, how would you organise that so that the verbal structure alters the operation of the mundial structure? Is that a trivial question or not? Imagine two [[Clife]] boards; perhaps the rules of each are slightly different. The mundial board is primary; the verbal board overlaps in limited ways for input, and in structured ways for output (motor, as a minimum). Then, could the verbal board set goals by loading structure into the mundial board? Is this a useful analogy?
The classic triple squeeze yields 2 tricks; the first trick given up becomes the squeeze card for the second stage; however triple squeezes, in the sense of one player needing to retain cards in three suits - question, could it be cards in two suits, but for three reasons? - are integral to many more complex squeezes, not dealt with here.

A typical triple squeeze end position:

||||||&spades;|A|6|4|3|
||||||@@color:red;&hearts;@@|-||||
||||||@@color:red;&diams;@@|-||||
||||||&clubs;|-|||||
|&spades;|-|-|||&lceil;|@@font-weight:bold;n@@|&rceil;||&spades;|Q|J||||||
|@@color:red;&hearts;@@|-||||@@font-weight:bold;w@@||||@@color:red;&hearts;@@|Q|||||||
|@@color:red;&diams;@@|-||||||@@font-weight:bold;e@@||@@color:red;&diams;@@|K||||||||
|&clubs;|T|9|6|4|&lfloor;|@@font-weight:bold;s@@|&rfloor;||&clubs;|-||||||
||||||&spades;|8|||||
||||||@@color:red;&hearts;@@|J||||
||||||@@color:red;&diams;@@|Q||||
||||||&clubs;|A||||
|borderless|k

When South cashes the &clubs; East is helpless; pitching a red winner allows South to cash in that suit and repeat the squeeze, while an immediate &spades; discard gives up the rest of the tricks. This is a [[non-positional]] squeeze.
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{

// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'bridgethunk';

// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too

// disable autosave in d3
if (window.location.protocol != "file:")
	config.options.chkGTDLazyAutoSave = false;

// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
	SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
	SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
	OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
	DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
	MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}

// create some shadow tiddler content
merge(config.shadowTiddlers,{

'TspotOptions':[
 "tiddlyspot password:",
 "<<option pasUploadPassword>>",
 ""
].join("\n"),

'TspotControls':[
 "| tiddlyspot password:|<<option pasUploadPassword>>|",
 "| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
 "| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),

'WelcomeToTiddlyspot':[
 "This document is a ~TiddlyWiki from tiddlyspot.com.  A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below.  Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
 "<<tiddler TspotControls>>",
 "See also GettingStarted.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick.  You can make changes and save them locally without being connected to the Internet.  When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]].  Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help.  If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site.  Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),

'TspotSidebar':[
 "<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n")

});
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 04/04/2011 11:02:47 | AndrewX | [[/|http://bridgethunk.tiddlyspot.com/]] | [[store.cgi|http://bridgethunk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bridgethunk.tiddlyspot.com/index.html]] | . |
| 04/04/2011 11:03:51 | AndrewX | [[/|http://bridgethunk.tiddlyspot.com/]] | [[store.cgi|http://bridgethunk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bridgethunk.tiddlyspot.com/index.html]] | . |
| 04/04/2011 11:04:50 | AndrewX | [[/|http://bridgethunk.tiddlyspot.com/]] | [[store.cgi|http://bridgethunk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bridgethunk.tiddlyspot.com/index.html]] | . | ok |
| 04/04/2011 11:05:46 | AndrewX | [[/|http://bridgethunk.tiddlyspot.com/]] | [[store.cgi|http://bridgethunk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bridgethunk.tiddlyspot.com/index.html]] | . | ok |
| 04/04/2011 11:06:14 | AndrewX | [[/|http://bridgethunk.tiddlyspot.com/]] | [[store.cgi|http://bridgethunk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bridgethunk.tiddlyspot.com/index.html]] | . |
| 04/04/2011 15:46:29 | AndrewX | [[/|http://bridgethunk.tiddlyspot.com/]] | [[store.cgi|http://bridgethunk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bridgethunk.tiddlyspot.com/index.html]] | . |
| 18/04/2011 11:35:49 | AndrewX | [[/|http://bridgethunk.tiddlyspot.com/]] | [[store.cgi|http://bridgethunk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bridgethunk.tiddlyspot.com/index.html]] | . | ok |
| 18/04/2011 11:44:49 | AndrewX | [[/|http://bridgethunk.tiddlyspot.com/]] | [[store.cgi|http://bridgethunk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bridgethunk.tiddlyspot.com/index.html]] | . |
| 21/04/2011 12:46:16 | AndrewX | [[/|http://bridgethunk.tiddlyspot.com/]] | [[store.cgi|http://bridgethunk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bridgethunk.tiddlyspot.com/index.html]] | . |
| 27/04/2011 08:46:41 | AndrewX | [[/|http://bridgethunk.tiddlyspot.com/]] | [[store.cgi|http://bridgethunk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bridgethunk.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.3|
|''Date:''|Feb 24, 2008|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
	major: 4, minor: 1, revision: 3,
	date: new Date("Feb 24, 2008"),
	source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

//
// Environment
//

if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false;	// true to activate both in Plugin and UploadService
	
//
// Upload Macro
//

config.macros.upload = {
// default values
	defaultBackupDir: '',	//no backup
	defaultStoreScript: "store.php",
	defaultToFilename: "index.html",
	defaultUploadDir: ".",
	authenticateUser: true	// UploadService Authenticate User
};
	
config.macros.upload.label = {
	promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
	promptParamMacro: "Save and Upload this TiddlyWiki in %0",
	saveLabel: "save to web", 
	saveToDisk: "save to disk",
	uploadLabel: "upload"	
};

config.macros.upload.messages = {
	noStoreUrl: "No store URL in parmeters or options",
	usernameOrPasswordMissing: "Username or password missing"
};

config.macros.upload.handler = function(place,macroName,params) {
	if (readOnly)
		return;
	var label;
	if (document.location.toString().substr(0,4) == "http") 
		label = this.label.saveLabel;
	else
		label = this.label.uploadLabel;
	var prompt;
	if (params[0]) {
		prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0], 
			(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
	} else {
		prompt = this.label.promptOption;
	}
	createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};

config.macros.upload.action = function(params)
{
		// for missing macro parameter set value from options
		if (!params) params = {};
		var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
		var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
		var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
		var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
		var username = params[4] ? params[4] : config.options.txtUploadUserName;
		var password = config.options.pasUploadPassword; // for security reason no password as macro parameter	
		// for still missing parameter set default value
		if ((!storeUrl) && (document.location.toString().substr(0,4) == "http")) 
			storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
		if (storeUrl.substr(0,4) != "http")
			storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
		if (!toFilename)
			toFilename = bidix.basename(window.location.toString());
		if (!toFilename)
			toFilename = config.macros.upload.defaultToFilename;
		if (!uploadDir)
			uploadDir = config.macros.upload.defaultUploadDir;
		if (!backupDir)
			backupDir = config.macros.upload.defaultBackupDir;
		// report error if still missing
		if (!storeUrl) {
			alert(config.macros.upload.messages.noStoreUrl);
			clearMessage();
			return false;
		}
		if (config.macros.upload.authenticateUser && (!username || !password)) {
			alert(config.macros.upload.messages.usernameOrPasswordMissing);
			clearMessage();
			return false;
		}
		bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password); 
		return false; 
};

config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir) 
{
	if (!storeUrl)
		return null;
		var dest = bidix.dirname(storeUrl);
		if (uploadDir && uploadDir != '.')
			dest = dest + '/' + uploadDir;
		dest = dest + '/' + toFilename;
	return dest;
};

//
// uploadOptions Macro
//

config.macros.uploadOptions = {
	handler: function(place,macroName,params) {
		var wizard = new Wizard();
		wizard.createWizard(place,this.wizardTitle);
		wizard.addStep(this.step1Title,this.step1Html);
		var markList = wizard.getElement("markList");
		var listWrapper = document.createElement("div");
		markList.parentNode.insertBefore(listWrapper,markList);
		wizard.setValue("listWrapper",listWrapper);
		this.refreshOptions(listWrapper,false);
		var uploadCaption;
		if (document.location.toString().substr(0,4) == "http") 
			uploadCaption = config.macros.upload.label.saveLabel;
		else
			uploadCaption = config.macros.upload.label.uploadLabel;
		
		wizard.setButtons([
				{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption, 
					onClick: config.macros.upload.action},
				{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
				
			]);
	},
	options: [
		"txtUploadUserName",
		"pasUploadPassword",
		"txtUploadStoreUrl",
		"txtUploadDir",
		"txtUploadFilename",
		"txtUploadBackupDir",
		"chkUploadLog",
		"txtUploadLogMaxLine"		
	],
	refreshOptions: function(listWrapper) {
		var opts = [];
		for(i=0; i<this.options.length; i++) {
			var opt = {};
			opts.push();
			opt.option = "";
			n = this.options[i];
			opt.name = n;
			opt.lowlight = !config.optionsDesc[n];
			opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
			opts.push(opt);
		}
		var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
		for(n=0; n<opts.length; n++) {
			var type = opts[n].name.substr(0,3);
			var h = config.macros.option.types[type];
			if (h && h.create) {
				h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
			}
		}
		
	},
	onCancel: function(e)
	{
		backstage.switchTab(null);
		return false;
	},
	
	wizardTitle: "Upload with options",
	step1Title: "These options are saved in cookies in your browser",
	step1Html: "<input type='hidden' name='markList'></input><br>",
	cancelButton: "Cancel",
	cancelButtonPrompt: "Cancel prompt",
	listViewTemplate: {
		columns: [
			{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
			{name: 'Option', field: 'option', title: "Option", type: 'String'},
			{name: 'Name', field: 'name', title: "Name", type: 'String'}
			],
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'} 
			]}
};

//
// upload functions
//

if (!bidix.upload) bidix.upload = {};

if (!bidix.upload.messages) bidix.upload.messages = {
	//from saving
	invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
	backupSaved: "Backup saved",
	backupFailed: "Failed to upload backup file",
	rssSaved: "RSS feed uploaded",
	rssFailed: "Failed to upload RSS feed file",
	emptySaved: "Empty template uploaded",
	emptyFailed: "Failed to upload empty template file",
	mainSaved: "Main TiddlyWiki file uploaded",
	mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
	//specific upload
	loadOriginalHttpPostError: "Can't get original file",
	aboutToSaveOnHttpPost: 'About to upload on %0 ...',
	storePhpNotFound: "The store script '%0' was not found."
};

bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
	var callback = function(status,uploadParams,original,url,xhr) {
		if (!status) {
			displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
			return;
		}
		if (bidix.debugMode) 
			alert(original.substr(0,500)+"\n...");
		// Locate the storeArea div's 
		var posDiv = locateStoreArea(original);
		if((posDiv[0] == -1) || (posDiv[1] == -1)) {
			alert(config.messages.invalidFileError.format([localPath]));
			return;
		}
		bidix.upload.uploadRss(uploadParams,original,posDiv);
	};
	
	if(onlyIfDirty && !store.isDirty())
		return;
	clearMessage();
	// save on localdisk ?
	if (document.location.toString().substr(0,4) == "file") {
		var path = document.location.toString();
		var localPath = getLocalPath(path);
		saveChanges();
	}
	// get original
	var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
	var originalPath = document.location.toString();
	// If url is a directory : add index.html
	if (originalPath.charAt(originalPath.length-1) == "/")
		originalPath = originalPath + "index.html";
	var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
	var log = new bidix.UploadLog();
	log.startUpload(storeUrl, dest, uploadDir,  backupDir);
	displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
	if (bidix.debugMode) 
		alert("about to execute Http - GET on "+originalPath);
	var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
	if (typeof r == "string")
		displayMessage(r);
	return r;
};

bidix.upload.uploadRss = function(uploadParams,original,posDiv) 
{
	var callback = function(status,params,responseText,url,xhr) {
		if(status) {
			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
			displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
			bidix.upload.uploadMain(params[0],params[1],params[2]);
		} else {
			displayMessage(bidix.upload.messages.rssFailed);			
		}
	};
	// do uploadRss
	if(config.options.chkGenerateAnRssFeed) {
		var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
		var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
		var rssString = generateRss();
		// no UnicodeToUTF8 conversion needed when location is "file" !!!
		if (document.location.toString().substr(0,4) != "file")
			rssString = convertUnicodeToUTF8(rssString);	
		bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
	} else {
		bidix.upload.uploadMain(uploadParams,original,posDiv);
	}
};

bidix.upload.uploadMain = function(uploadParams,original,posDiv) 
{
	var callback = function(status,params,responseText,url,xhr) {
		var log = new bidix.UploadLog();
		if(status) {
			// if backupDir specified
			if ((params[3]) && (responseText.indexOf("backupfile:") > -1))  {
				var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
				displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
			}
			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
			displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
			store.setDirty(false);
			log.endUpload("ok");
		} else {
			alert(bidix.upload.messages.mainFailed);
			displayMessage(bidix.upload.messages.mainFailed);
			log.endUpload("failed");			
		}
	};
	// do uploadMain
	var revised = bidix.upload.updateOriginal(original,posDiv);
	bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};

bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
	var localCallback = function(status,params,responseText,url,xhr) {
		url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
		if (xhr.status == 404)
			alert(bidix.upload.messages.storePhpNotFound.format([url]));
		if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
			alert(responseText);
			if (responseText.indexOf("Debug mode") >= 0 )
				responseText = responseText.substring(responseText.indexOf("\n\n")+2);
		} else if (responseText.charAt(0) != '0') 
			alert(responseText);
		if (responseText.charAt(0) != '0')
			status = null;
		callback(status,params,responseText,url,xhr);
	};
	// do httpUpload
	var boundary = "---------------------------"+"AaB03x";	
	var uploadFormName = "UploadPlugin";
	// compose headers data
	var sheader = "";
	sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
	sheader += uploadFormName +"\"\r\n\r\n";
	sheader += "backupDir="+uploadParams[3] +
				";user=" + uploadParams[4] +
				";password=" + uploadParams[5] +
				";uploaddir=" + uploadParams[2];
	if (bidix.debugMode)
		sheader += ";debug=1";
	sheader += ";;\r\n"; 
	sheader += "\r\n" + "--" + boundary + "\r\n";
	sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
	sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
	sheader += "Content-Length: " + data.length + "\r\n\r\n";
	// compose trailer data
	var strailer = new String();
	strailer = "\r\n--" + boundary + "--\r\n";
	data = sheader + data + strailer;
	if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
	var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
	if (typeof r == "string")
		displayMessage(r);
	return r;
};

// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
	if (!posDiv)
		posDiv = locateStoreArea(original);
	if((posDiv[0] == -1) || (posDiv[1] == -1)) {
		alert(config.messages.invalidFileError.format([localPath]));
		return;
	}
	var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
				store.allTiddlersAsHtml() + "\n" +
				original.substr(posDiv[1]);
	var newSiteTitle = getPageTitle().htmlEncode();
	revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
	revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
	revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
	revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
	revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
	return revised;
};

//
// UploadLog
// 
// config.options.chkUploadLog :
//		false : no logging
//		true : logging
// config.options.txtUploadLogMaxLine :
//		-1 : no limit
//      0 :  no Log lines but UploadLog is still in place
//		n :  the last n lines are only kept
//		NaN : no limit (-1)

bidix.UploadLog = function() {
	if (!config.options.chkUploadLog) 
		return; // this.tiddler = null
	this.tiddler = store.getTiddler("UploadLog");
	if (!this.tiddler) {
		this.tiddler = new Tiddler();
		this.tiddler.title = "UploadLog";
		this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
		this.tiddler.created = new Date();
		this.tiddler.modifier = config.options.txtUserName;
		this.tiddler.modified = new Date();
		store.addTiddler(this.tiddler);
	}
	return this;
};

bidix.UploadLog.prototype.addText = function(text) {
	if (!this.tiddler)
		return;
	// retrieve maxLine when we need it
	var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
	if (isNaN(maxLine))
		maxLine = -1;
	// add text
	if (maxLine != 0) 
		this.tiddler.text = this.tiddler.text + text;
	// Trunck to maxLine
	if (maxLine >= 0) {
		var textArray = this.tiddler.text.split('\n');
		if (textArray.length > maxLine + 1)
			textArray.splice(1,textArray.length-1-maxLine);
			this.tiddler.text = textArray.join('\n');		
	}
	// update tiddler fields
	this.tiddler.modifier = config.options.txtUserName;
	this.tiddler.modified = new Date();
	store.addTiddler(this.tiddler);
	// refresh and notifiy for immediate update
	story.refreshTiddler(this.tiddler.title);
	store.notify(this.tiddler.title, true);
};

bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir,  backupDir) {
	if (!this.tiddler)
		return;
	var now = new Date();
	var text = "\n| ";
	var filename = bidix.basename(document.location.toString());
	if (!filename) filename = '/';
	text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
	text += config.options.txtUserName + " | ";
	text += "[["+filename+"|"+location + "]] |";
	text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
	text += uploadDir + " | ";
	text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
	text += backupDir + " |";
	this.addText(text);
};

bidix.UploadLog.prototype.endUpload = function(status) {
	if (!this.tiddler)
		return;
	this.addText(" "+status+" |");
};

//
// Utilities
// 

bidix.checkPlugin = function(plugin, major, minor, revision) {
	var ext = version.extensions[plugin];
	if (!
		(ext  && 
			((ext.major > major) || 
			((ext.major == major) && (ext.minor > minor))  ||
			((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
			// write error in PluginManager
			if (pluginInfo)
				pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
			eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
	}
};

bidix.dirname = function(filePath) {
	if (!filePath) 
		return;
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(0, lastpos);
	} else {
		return filePath.substring(0, filePath.lastIndexOf("\\"));
	}
};

bidix.basename = function(filePath) {
	if (!filePath) 
		return;
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("#")) != -1) 
		filePath = filePath.substring(0, lastpos);
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(lastpos + 1);
	} else
		return filePath.substring(filePath.lastIndexOf("\\")+1);
};

bidix.initOption = function(name,value) {
	if (!config.options[name])
		config.options[name] = value;
};

//
// Initializations
//

// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);

// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");

//optionsDesc
merge(config.optionsDesc,{
	txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
	txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
	txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
	txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
	txtUploadUserName: "Upload Username",
	pasUploadPassword: "Upload Password",
	chkUploadLog: "do Logging in UploadLog (default: true)",
	txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});

// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');


// Backstage
merge(config.tasks,{
	uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");


//}}}

<!--{{{-->
<div style=text-align:right;><div style="font-size:85%"><span macro="wordCount"></span> words</div></div>
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='commentBreadcrumb' macro='commentBreadcrumb'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
The back end of this site is a tool called [[TiddlyWiki|http://www.tiddlywiki.com]], which I quite like; I hope it doesn't antagonise readers, but do feel free to leave a comment either way. I like it for a number of reasons, but the main one is it suits my spasmodic, disordered thought processes. To use it, you can click on the links, which are in dark blue, and/or you can click on tags, which are in the top right of each window. To some extent this forces you to put up with my sense of disorder, but I'm trying to create a "[[main article|Bridge Aesthetics]]" for those who like continuity. There is a search function too; I guess nothing is universally intuitive, but I've found other sites based on this framework to be quite easy to navigate. It's perfectly possible that's because their authors are better designers than me, of course, but I hope that's not the sole reason.

It started because of a discussion about bridge & chess at [[this blog|http://http://swatchless.wordpress.com/]], and the topic of [[aesthetics|Aesthetics]] came up. I think it's probably fair to say that chess, as a community, has a stronger idea of aesthetics than bridge, and I thought I'd like to analyse bridge aesthetics; I don't play any more, but I ''DO'' enjoy watching, which seems like an excellent aesthetic perspective. Well, as always one thing procrastinated to a another and now I have another MA. And, not coincidentally as it happens, I think I have an idea of where to start this exploration.

<<comments>>
<<bridgeHand "7,6,5,4;A,8,3;j,3,2;k,q,5" "8,3;9,2;9;a,j,t,9,7,4,3,2" "a,q,t;k,7,5,4;a,k,q,t,7,6;;" "k,j,9,2;q,j,t,6;8,5,4;8,6">>

A squeeze without the count for 12 tricks (assume a &clubs; lead). One threat __//combines//__ both endplay and suit establishment, while the other threat is suit establishment alone. There are only ten (//n-2//) top tricks - the canonical squeeze has //n-1// tricks. That combined threat, gaining //two tricks// is very unusual, as is the fact that the suit establishment play in the second threat likewise gains //two tricks//. 

If ''rarity'' were a criteria for elegance, this hand would have it.
merge(config.macros,{
	wordCount: {
		handler: function(place,macroName,params,wikifier,paramString,tiddler) {
			createTiddlyText(place,tiddler&&tiddler.text?tiddler.text.match(/\w+/g).length:"0");
		}
	}
});
AndrewX
//{{{
config.macros.bridgeHand = {
  handler: function (place, macroName, params, wikifier, paramString, tiddler)
  {
    var lineBreak = "\n";
    var tabString = "|";
    var suit = new Array();
    var deal = new Array();
    var North = new Array();
    var East = new Array();
    var South = new Array();
    var West = new Array();
    var lineOut = [];
    var westLongSuit = 0;
    for (ix=0;ix<12;ix++)
    {
     lineOut[ix] = tabString;
    }
    suitSymbol = ["&spades;" , "@@color:red;&hearts;@@" , "@@color:red;&diams;@@" , "&clubs;"];

//parse input & check for 4 hands with 4 suits & 13 cards per hand
//there is no checking for duplicate or missing cards
//this looks crude 'cos I had a lot of trouble with arrays
//then
//upcase all cards
//then
//format output starting with West as W's longest suit...
//...determines edge of table
    if (params.length < 4)    {
       alert("Not enough hands");
       }
    else if (params[0].length < 4)    {
        alert("North is short on suits");
        }
    else if (params[1].length < 4)    {
        alert("East is short on suits");
        }
    else if (params[2].length < 4)    {
        alert("South is short on suits");
        }
    else if (params[3].length < 4)    {
        alert("West is short on suits");
        }
    else
    {
// mainline - find way to improve error handling!
// Build North hand
    hand = params[0].split(";");
    var nCardCount = 0;
    for (i=0; i<4; i++)    {
         North[i] = hand[i].split(",");
         if (North[i][0] =="")    {
             nCardCount -= 1;               // handle voids - Don't muck around with the hand array directly
             }                                       //                       cos it affects the output array 
         nCardCount = nCardCount + North[i].length;
         }   
    if (nCardCount != 13)
    {
    alert("North doesn't have 13 cards");
    } 
// Build East hand
    hand = params[1].split(";");
    var eCardCount = 0;
    for (i=0; i<4; i++)    {
         East[i] = hand[i].split(",");
         if (East[i][0] =="")    {
             eCardCount -= 1;               // handle voids - Don't muck around with the hand array directly
             }                                       //                       cos it affects the output array 
         eCardCount = eCardCount + East[i].length;
         }   
    if (eCardCount != 13)
    {
    alert("East doesn't have 13 cards");
    }    
// Build South hand
    hand = params[2].split(";");
    var sCardCount = 0;
    for (i=0; i<4; i++)    {
         South[i] = hand[i].split(",");
         if (South[i][0] =="")    {
             sCardCount -= 1;               // handle voids - Don't muck around with the hand array directly
             }                                       //                       cos it affects the output array 
         sCardCount = sCardCount + South[i].length;
         }   
    if (sCardCount != 13)
    {
    alert("South doesn't have 13 cards");
    } 
// Build West hand  
    hand = params[3].split(";");
    var wCardCount = 0;
    for (i=0; i<4; i++)    {
          West[i] = hand[i].split(",");
          if (West[i][0] =="")    {
             wCardCount -= 1;               // handle voids - Don't muck around with the hand array directly
             }                                       //                       cos it affects the output array   
         wCardCount = wCardCount + West[i].length;
         if (westLongSuit < West[i].length)    {
             westLongSuit = West[i].length;
             }
         }   
    if (wCardCount != 13)    {
        alert("West doesn't have 13 cards");
        }
// -----------------------------------------------------
// build output strings in W,N,S,table,E order
// -----------------------------------------------------
   for (w_ix=0;w_ix<4;w_ix++)    {   // for the 4 suits
        w_out_ix = w_ix + 4;             // output lines are 4-7
        for (suit_ix = 0;suit_ix < West[w_ix].length;suit_ix++)    {     // for each card in the suit
             switch (suit_ix)    {
                 case 0:
                      lineOut[w_out_ix] = lineOut[w_out_ix] + suitSymbol[w_ix] + tabString + West[w_ix][suit_ix].toUpperCase() +tabString;
                 break;
                 default:
                      lineOut[w_out_ix] = lineOut[w_out_ix]  + West[w_ix][suit_ix].toUpperCase() + tabString;
                 } //end-switch
          } //end card-counter
     padLength = westLongSuit - suit_ix; 
     if (padLength != 0)    {
         for (pad_ix = 0; pad_ix < padLength; pad_ix++)    {
               lineOut[w_out_ix] = lineOut[w_out_ix] + tabString;
               }
         }
     }//end West
 //use westLongSuit to align North & South
   for (n_ix=0;n_ix<4;n_ix++)    {
        for (suit_ix = 0;suit_ix < North[n_ix].length;suit_ix++)    {
            switch (suit_ix)    {
                 case 0: 
                 for (index = 0; index < westLongSuit + 1 ; index++)    {
                     lineOut[n_ix] = lineOut[n_ix] + tabString;
                     }   
                 lineOut[n_ix] = lineOut[n_ix] + suitSymbol[n_ix] + tabString + North[n_ix][suit_ix].toUpperCase() + tabString;
                 break;
                 default:
                 lineOut[n_ix] = lineOut[n_ix]  + North[n_ix][suit_ix].toUpperCase() + tabString;
                 } //end-switch
            } //end suit_ix
        }//end North
// South is lines 8-11
    for (s_ix=0;s_ix<4;s_ix++)    {
        var s_out_ix = s_ix + 8; //set output line number
        for (suit_ix = 0;suit_ix < South[s_ix].length;suit_ix++)    {
            switch (suit_ix)     {
                 case 0:
                 for (index = 0; index < westLongSuit + 1 ; index++)    {
                     lineOut[s_out_ix] = lineOut[s_out_ix] + tabString;
                     }   
                 lineOut[s_out_ix] = lineOut[s_out_ix] + suitSymbol[s_ix] + tabString + South[s_ix][suit_ix].toUpperCase() +tabString;
                 break;
                 default:
                 lineOut[s_out_ix] = lineOut[s_out_ix]  + South[s_ix][suit_ix].toUpperCase() + tabString;
                 }
            }    
        }//end South

//draw table (lines 4-7)
    lineOut[4] = lineOut[4] + tabString + "&lceil;" + tabString + "@@font-weight:bold;n@@" + tabString + "&rceil;" + tabString + tabString;
    lineOut[5] = lineOut[5] + tabString + "@@font-weight:bold;w@@" + tabString + tabString + "" + tabString + tabString;;
    lineOut[6] = lineOut[6] + tabString + "" + tabString + tabString + "@@font-weight:bold;e@@" + tabString + tabString;;
    lineOut[7] = lineOut[7] + tabString +  "&lfloor;" + tabString+ "@@font-weight:bold;s@@"+ tabString + "&rfloor;" + tabString + tabString;;

//append East to West (lines 4-7)
    for (e_ix=0;e_ix<4;e_ix++)     {
         var e_out_ix = e_ix + 4; //set output line number
         for (suit_ix = 0;suit_ix < East[e_ix].length;suit_ix++)    {
              switch (suit_ix)    {
                   case 0:
                   lineOut[e_out_ix] = lineOut[e_out_ix] + suitSymbol[e_ix] + tabString + East[e_ix][suit_ix].toUpperCase() +tabString;
                   break;
                   default:
                   lineOut[e_out_ix] = lineOut[e_out_ix]  + East[e_ix][suit_ix].toUpperCase() + tabString;
                   }
             }
        }//end East
//write out hand
    wikify (lineOut.join("\n") + lineBreak + tabString + "borderless|k", place);
// wikify (lineOut.join("\n") , place); //for debug
    } //end-else
} //end handler
} //end macro
//}}} 
Causation is very difficult. ''I'' (not being happy, say) cause ''myself'' to feel happy. Is that unhappy ''I'' still around? What's their (gender-neutral) relationship to the happy ''myself''? Perhaps there's an intermediate stage, or stages, as well? The ''I-becoming-happy'' stage, for example. Maybe it's better to junk causation as "real" and recognise it as a narrative (or linguistic) device.
Elegance is a response to a hand, a mixture of emotion and analysis. 
[[Squeezes]], generally speaking, aren't elegant. They're complex.They require analysis, sometimes quite complex analysis. But they don't evoke the emotion of elegance - most of the time. [[Adventures in Card Play]], whose authors were particular sensitive has perhaps a couple of squeezes that might challenge that idea, one being the once-named [[Seres|Backwash]] squeeze.
epitome: 1. A person or thing that is a perfect example of a particular quality or type: "she is the epitome of elegance and taste"
What abstract description(s) can be given for (a) game(s)? Will they be of use here?
A generalised strategy based on recognition of a standard pattern, e.g. "where possible preserve entries between hands" as in Forquet's [[Changing Tack]].
//{{{
config.macros.htBrdgeHand = {
// html output
  handler: function (place, macroName, params, wikifier, paramString, tiddler)
  {
    var lineBreak = "<br/>";
    var tabString = "|";
    var suit = new Array();
    var deal = new Array();
    var North = new Array();
    var East = new Array();
    var South = new Array();
    var West = new Array();
    var lineOut = [];
    var rowStart = "<tr>";
    var rowEnd = "</tr>";
    var cellStart = "<td>";
    var cellEnd = "</td>";
    var westLongSuit = 0;
    for (ix=0;ix<12;ix++) {
        lineOut[ix] = rowStart;
        }
    suitSymbol = ["&spades;" , "&hearts;" , "&diams;" , "&clubs;"];

//parse input & check for 4 hands with 4 suits & 13 cards per hand
//there is no checking for duplicate or missing cards
//this looks crude 'cos I had a lot of trouble with arrays
//then
//upcase all cards
//then
//format output starting with West as W's longest suit...
//...determines edge of table
    if (params.length < 4)     {
        alert("Not enough hands");
        }
    else if (params[0].length < 4)     {
        alert("North is short on suits")
        }
    else if (params[1].length < 4)     {
         alert("East is short on suits")
         }
    else if (params[2].length < 4)    {
        alert("South is short on suits")
        }
    else if (params[3].length < 4)     {
        alert("West is short on suits")
        }
    else  
   {
    hand = params[0].split(";"); 
    North[0] = hand[0].split(",");
    North[1] = hand[1].split(",");
    North[2] = hand[2].split(",");
    North[3] = hand[3].split(",");
    cardCount= North[0].length +North[1].length +North[2].length +North[3].length;
    if (cardCount != 13)     {
        alert("North doesn't have 13 cards");
        }
    
   hand = params[1].split(";");
   East[0] = hand[0]. split(",");
   East[1] = hand[1].split(",");
   East[2] = hand[2].split(",");
   East[3] = hand[3].split(",");
    cardCount= East[0].length +East[1].length +East[2].length +East[3].length;
    if (cardCount != 13)     {
        alert("East doesn't have 13 cards");
        }
   
   hand = params[2].split(";");
   South[0] = hand[0]. split(",");
   South[1] = hand[1].split(",");
   South[2] = hand[2].split(",");
   South[3]= hand[3].split(",");
    cardCount= South[0].length +South[1].length +South[2].length +South[3].length;
    if (cardCount != 13)     {
        alert("South doesn't have 13 cards");
        }
   
   hand = params[3].split(";");
   West[0] = hand[0]. split(",");
   West[1] = hand[1].split(",");
   West[2] = hand[2].split(",");
   West[3]= hand[3].split(",");
    cardCount= West[0].length +West[1].length +West[2].length +West[3].length;
    if (cardCount != 13)    {
        alert("West doesn't have 13 cards");
        }
   for (w_ix=0;w_ix<4;w_ix++)    { // for the 4 suits
       w_out_ix = w_ix +4;
       for (suit_ix = 0;suit_ix < West[w_ix].length;suit_ix++)    { // for each card in the suit
           switch (suit_ix)     {
                case 0:
                    lineOut[w_out_ix] = lineOut[w_out_ix] + cellStart + suitSymbol[w_ix] + cellEnd + cellStart + West[w_ix][suit_ix].toUpperCase() + cellEnd;
                break;
                default:
                    lineOut[w_out_ix] = lineOut[w_out_ix]  + cellStart +West[w_ix][suit_ix].toUpperCase() + cellEnd;
                 } //end switch
           } 
      if (westLongSuit < suit_ix)    { 
           westLongSuit = suit_ix;
           }
       }//end West
 //use westLongSuit to align North & South
   for (n_ix=0;n_ix<4;n_ix++)    {
        for (suit_ix = 0;suit_ix < North[n_ix].length;suit_ix++)    {
             switch (suit_ix)   {
                  case 0:
                      for (index = 0; index < westLongSuit + 1 ; index++)     {
                           lineOut[n_ix] = lineOut[n_ix] + cellStart + cellEnd;
                           }   
                      lineOut[n_ix] = lineOut[n_ix] + cellStart + suitSymbol[n_ix] + cellEnd + cellStart + North[n_ix][suit_ix].toUpperCase() + cellEnd;
                  break;
                  default:
                      lineOut[n_ix] = lineOut[n_ix]  + cellStart + North[n_ix][suit_ix].toUpperCase() + cellEnd;
                  }  // end-switch
            }
       lineOut[n_ix] = lineOut[n_ix]  + rowEnd;  
       }//end North
// South is lines 8-11
    for (s_ix=0;s_ix<4;s_ix++)   {
        var s_out_ix = s_ix + 8; //set output line number
        for (suit_ix = 0;suit_ix < South[s_ix].length;suit_ix++)    {
            switch (suit_ix)    {
                 case 0:
                     for (index = 0; index < westLongSuit + 1 ; index++)    {
                         lineOut[s_out_ix] = lineOut[s_out_ix] + cellStart + cellEnd;
                         }   
                     lineOut[s_out_ix] = lineOut[s_out_ix] + cellStart + suitSymbol[s_ix] + cellEnd + cellStart + South[s_ix][suit_ix].toUpperCase() + cellEnd;
                     break; 
                 default:
                     lineOut[s_out_ix] = lineOut[s_out_ix]  + cellStart + South[s_ix][suit_ix].toUpperCase() + + cellEnd;
                 }
            }
        lineOut[s_out_ix] = lineOut[s_out_ix]  + rowEnd;
        }  //end South
//draw table (lines 4-7)
    lineOut[4] = lineOut[4] + cellStart + cellEnd + cellStart + "&lceil;" + cellEnd + cellStart + "N" + cellEnd + cellStart + "&rceil;" + cellEnd + cellStart + cellEnd;
    lineOut[5] = lineOut[5] + cellStart + cellEnd + tabString + "W" + tabString + cellStart + cellEnd + cellStart + cellEnd + cellStart + cellEnd;
    lineOut[6] = lineOut[6] + cellStart + cellEnd + cellStart + cellEnd + cellStart + cellEnd + cellStart + "E" + cellEnd + cellStart + cellEnd;
    lineOut[7] = lineOut[7] + cellStart + cellEnd + cellStart + "&lfloor;" + cellEnd + cellStart + "S"+ cellEnd + cellStart + "&rfloor;" + cellEnd +cellStart + cellEnd;
//append East to West (lines 4-7)
     for (e_ix=0;e_ix<4;e_ix++)    {
          var e_out_ix = e_ix + 4; //set output line number
          for (suit_ix = 0;suit_ix < East[e_ix].length;suit_ix++)    {
               switch (suit_ix)    {
                   case 0:
                         lineOut[e_out_ix] = lineOut[e_out_ix] + cellStart + suitSymbol[e_ix] + cellEnd + cellStart + East[e_ix][suit_ix].toUpperCase() + cellEnd;
                  break;
                  default:
                       lineOut[e_out_ix] = lineOut[e_out_ix]  + cellStart + East[e_ix][suit_ix].toUpperCase() + cellEnd;
                 }
            }
        lineOut[e_out_ix] = lineOut[e_out_ix]  + rowEnd;
        }//end East
//write out hand
    place.innherHTML = "<table>" + lineOut.join("") + "</table>";
   } //end-else
} //end handler
} //end macro
//}}} 
//{{{
window.coreWikify = wikify;
window.wikify = function(source,output,highlightRegExp,tiddler) {
	if (source) arguments[0]=source.replace(/\\\\\n/mg,"<br>");
	coreWikify.apply(this,arguments);
}
//}}}
Any [[tactic/strategy|Strategy and Tactics]] that is not [[positional]] - not much of a surprise. My feeling is that there is a an undocumented slur on "positional" plays, as if, somehow, it's not quite //kosher// to exploit the luck of the deal. As it that isn't the essence of the game. At the same time, if there is a choice between a positional and a non-positional play, the non-positional play will work twice as often, so in that sense the positional play is inferior. However, it can happen that a positional play will produce more tricks than a non-positional play, and in matchpoints, the total number of tricks taken is often an issue.
A par problem is a layout which asks for the optimum result given perfect play by all participants. That seems a little too simple; problems in general assume best play or defence. So, is a par problem one which also involves multiple, intermingled decisions by players on both sides? (Need to investigate) 
Many bridge positions exploit the fact that one player is playing after another, and can make radically different choices of which card to play in consequence. Many squeezes exploit it (the majority), but finesses, elopements, trump coups, smother plays - I can't think of any more off hand - all exploit this.

Perhaps [[rank]] starts off as the primary source of trick taking; then position creates extra play options. 
The rank of a card //prima facie// determines its ability to win a trick. The higher (the rank of) the card, the better its trick taking ability. Rank can be altered by context; for example, trumps outrank non-trumps by virtue of suit, rather than rank within a suit. Another common alteration is caused by compression/establishment; a trick may, for example, contain J;Q;K;A; this leaves the T as the highest ranked card in that suit - somewhat before it might have been expected to be. Recognition of this is reflected in terms like "texture", which draw attention to the possession of intermediate cards in a suit which maybe exploited in this way.
wikify
<<bridgeHand "Q;J,T,9;8,7,6;7,6,5,4,3,2" "J,t,9;8,7,6;5,4,3,2;a,k,q" "8,7,6;5,4,3,2;A,k,q;j,t,9" "a,k,5,4,3,2;a,K,Q;j,T,9;8">>

html
<<htBrdgeHand "A,K,Q;J,T,9;8,7,6;5,4,3,2" "J,t,9;8,7,6;5,4,3,2;a,k,q" "8,7,6;5,4,3,2;A,k,q;j,t,9" "5,4,3,2;a,K,Q;j,T,9;8,7,6"]>>

native
||||||&spades;|A|K|Q||
||||||&hearts;|J|T|9||
||||||&diams;|8|7|6||
||||||&clubs;|5|4|3|2||
|&spades;|J|T|9|||&lceil;|N|&rceil;||&spades;|8|7|6|||||
|&hearts;|8|7|6|||W||||&hearts;|5|4|3|2|||||
|&diams;|5|4|3|2||||E||&diams;|A|K|Q||||||
|&clubs;|A|K|Q|||&lfloor;|S|&rfloor;||&clubs;|J|T|9|||||
||||||&spades;|5|4|3|2||
||||||&hearts;|A|K|Q||
||||||&diams;|J|T|9||
||||||&clubs;|8|7|6||
|borderless|k

//{{{
config.macros.tmacro = {
  handler: function (place, macroName, params, wikifier, paramString, tiddler)
  {
    var lineBreak = "<br/>";javascript:;
    var tabString = "|";
    wikify("|" + "hello" + "|" + lineBreak,place);
    for (i=0;i<12;i++) {
       wikify(tabString + "|" + "|goodbye|" + tabString + lineBreak, place);
       }
  } //end handler
} //end macro
//}}}