.. bdeal documentation master file, created by sphinx-quickstart on Wed Oct 2 17:17:22 2013. You can adapt this file completely to your liking, but it should at least contain the root ``toctree`` directive. .. include:: About bdeal =========== The :program:`bdeal` is a program that generates (randomly) card distributions that meets given requirements. :program:`bdeal` is developed by Piotr Beling and it is a part of the `Bridge Calculator `_. .. toctree:: :maxdepth: 2 .. role:: lua(code) :language: lua .. highlight:: lua .. _Lua: http://www.lua.org/ The main futures of the program are: * it is scriptable in the `Lua`_, * it uses multiple threads to generates and filters distributions of cards, * it has built-in, fast double-dummy solver, * it has console-based, shell-script-friendly user interface. .. _examples: Quick start examples ==================== Print 20 random hands distributions ----------------------------------- To print 20 random hands distributions just run: .. code-block:: bash $ bdeal -n 20 See :ref:`bcalc-invocation` for details. The chance to win 3NT --------------------- Suppose that your partner (S) opened 1NT (classical, 16-18 hcp) and you (N) have |spades|\ K42 |hearts|\ QT2 |diams|\ K98 |clubs|\ J653. To check how many trick, in average, S can take in NT and what is a chance to win 3NT, call: .. code-block:: bash $ bdeal nt_script.lua Where :file:`nt_script.lua` is a name of file with `Lua`_ script from which :program:`bdeal` will read all details. It may have the following content:: conf = { N="K42.QT2.K98.J653", -- fix N hand num=100 -- finish after accepting 100 deals } -- accept only the deals in which S has 1NT opening: function filter() return S:nt(16, 18) end -- for each accepted deal, calculate number of tricks in NT by S: function stats() local t = tricks(S, "NT") count("NT by S, number of tricks", t) count("chance to win 3NT by S", t >= 9) end See :ref:`scripts` for details about writing scripts. No one can make 7 tricks ------------------------ This script accept only deals in which it is impossible to win any contract (after optimal defence):: conf = { num = 1 } -- we want to find only one distribution function filter() for i1, s in pairs({ 'c', 'd', 'h', 's', 'nt' }) do for i2, p in pairs({ 'n', 'e', 'w', 's' }) do if cantake(7, p, s) then return false end end end return true end .. warning:: It may take a long time (even few hours) before it accepts any distribution. The best lead against 3NT ------------------------- Supposed that N opened 1NT (15-18 hcp) and S bid 3NT (10-12 hcp, without major 4). E is on lead and has |spades|\ K873 |hearts|\ J1076 |diams|\ A87 |clubs|\ Q7. This script measures the average numbers of tricks E-W can take and the chances to defeat the contract (3NT), after each lead:: conf = { num=2000, E="K873.J1076.A87.Q7" } function filter() return N:nt(15, 18) and S:nt(10, 12) and S:spades() < 4 and S:hearts() < 4 end function stats() for c in E:cards() do -- for each card c in the hand E: local t = tricks(N, "NT", c) -- tricks to take by N-S count("E-W tricks after " .. tostring(c), 13 - t) count("chance to defeat after " .. tostring(c), t < 9) end end .. _bcalc-invocation: Invocation ========== :program:`bdeal` is called like this: .. code-block:: bash $ bdeal [options] where ** are the (zero or more) names of files with :ref:`Lua scripts `. The :program:`bdeal` has several options: .. option:: -r, --noremarks Don't print remarks provided by calls of remark function. .. option:: -s, --nostats Don't print statistics for individual deals. .. option:: -f , --format Output format, one of: none (do not print), NESW, short (used by default), full, PBN, PBNf (PBN file/full). .. option:: -W , --west Fixed cards in WEST hand. should has a format like in examples: *"AKQJ.AK65.642.94"* (AKQJ of spades, AK65 of hearts, 642 of diamonds, 94 of clubs) *"63.6.9.AQ"* (only 6 cards are fixed, rest will be chosen randomly) *"Q7.8543..94"* (8 cards are fixed, 0 in diamonds) *"..K."* (the king of diamonds + 12 random cards) .. option:: -S , --south Fixed cards in SOUTH hand. .. option:: -E , --east Fixed cards in EAST hand. .. option:: -N , --north Fixed cards in NORTH hand. .. option:: -n , --num Number of hands to deal (10 by default). .. option:: -j , --jobs Number of threads to use (by default equals to number of available CPU cores). If argument is non-positive, it will be increased by number of available CPU cores (0 to use all cores, -1 to use all cores except one). .. option:: -h, --help Displays usage information and exits. .. option:: --, --ignore_rest Ignores the rest of the labeled arguments following this flag. .. option:: --version Displays version information and exits. .. _scripts: .. _lua-scripts: Lua scripts =========== About ----- Bdeal accepts scripts in `Lua`_ language. The scripts can include (each element is optional): - :ref:`conf table or function `, - :ref:`filter() function `, - :ref:`stat() function `. If more than one script are given, they are read sequentially (from left to right), and each can overwrite abovementioned elements (i.e. if two scripts provide ``filter()`` function, the one from script given later will be used). .. _lua-conf: Configuration ------------- Some configuration options can be put in `Lua`_ script file, in ``conf`` table or in ``conf`` function that returns a table, for instance:: -- N has king of diamond, W has AQ of spades and 9 of clubs, use 2 threads: conf = { N="..K.", W="AQ...9", jobs=2 } The following options (keys in the ``conf`` table) are allowed: ``N``, ``E``, ``S``, ``W``, ``format``, ``num``, ``jobs``. See :ref:`bcalc-invocation` for description of the options. .. _lua-filter: Filtering --------- Script can contain ``filter`` function which describes deal constraints. The function can **accept** or **refuse** deal described by the variables ``N``, ``E``, ``S``, ``W`` and should **return**: * ``true`` to **accept** the deal, * ``false`` to **refuse** it, * a number in range [0, 1], which will be interpreted as probability of accepting the deal. Each of the ``N``, ``E``, ``S``, ``W`` represents the sets of cards held by the respective hands. Functions and operators described in next sections can be used to examine the properties of the hands. If all given scripts do not include ``filter()`` function, all distributions are accepted. Examples: * accept deals in which E has 12 or more honour points, and more than 2 points in diamonds:: function filter() return E:hcp() >= 12 and E:D():hcp() > 2 end * accept deals in which W opens 1 spade and should have 5 or more spades, and 11 or more honour points (but we know that W sometimes, with 10% probability, opens with 4 strong spades -- but only if he has less than 5 hearts):: function filter() if W:hcp() < 11 then -- W does not have 11 points? return false -- refuse end -- here, W has 11 or more points local s = W:spades() -- number of spades if s >= 5 then -- has 5 spades? return true -- accept end if s == 4 and W:S():hcp() >= 6 and W:hearts() < 5 then -- 4 strong spades without 5 hearts? return 0.10 -- accept with 10% probability end return false -- everything else is refused, this line can be omitted (if filter returns no value, the deal will be refused) end * see also :ref:`examples` .. _lua-stat: Statistics ---------- Script can contain ``stats`` function which is called for each deal accepted by ``filter`` function. The ``stats`` function also has access to ``N``, ``E``, ``S`` and ``W`` variables. Typically, this function calls one or more time ``count`` function, which can collect series of numbers and calculates some statistics (average and others). Examples: * checking how many spades and honour points does W have in average:: function stats() count("spades in W's hand", W:spades()) count("honour points in W's hand", W:hcp()) end * see also :ref:`examples` Cards set operations (operators) -------------------------------- Let ``s1`` and ``s2`` be sets of cards. The following operators are available: ``s1 + s2`` Sum of the sets, for example: ``E:S() + E:H()`` represents E majors. ``s1 * s2`` Product of the sets, for example: ``W * C.new("AS AH")`` represents W major aces. ``s1 - s2`` Difference of the sets, for example: ``N - N:S()`` represents N cards without spades. ``-s1`` Complement of the set, for example: ``-S`` represents all 52-13 cards not included in S's hand. ``#s1`` Number of cards in ``s1``, same as ``count(s1)`` or ``s1:count()``. For example: ``#N:S()`` -- a number of spades cards in N's hand. ``s1 ^ s2`` xor, the set of cards which are in exactly one set ``s1`` or ``s2``. ``s1 == s2`` ``true`` only if sets ``s1`` and ``s2`` are equals. ``s1 ~= s2`` ``true`` only if sets ``s1`` and ``s2`` are not equals. ``s1 <= s2`` ``true`` only if set ``s1`` is included in ``s2``. ``s1 < s2`` ``true`` only if set ``s1`` is included in but not equal to ``s2``. Functions which operates on sets of cards ----------------------------------------- .. note:: Each function, excluding ``new``, can be called as ``C.function_name(arg1, arg2, ..., argN)`` or ``arg1:function_name(arg2, ..., argN)``. For example ``C.hcp(N)`` is equal to ``N:hcp()``. For sets of cards ``c``, ``c1``, ``c2``, ..., a function ``f``, and a string ``str``: .. lua:function:: C.new(str) Construct a set of cards described by the string ``str`` (note that there is upper-case ``C`` here). Accepts many formats. Example usage (all represent the same set of 10 cards): ``C.new("AK87.975..QT9")``, ``C.new("AK87 975 - QT9")``, ``C.new("SAK87 H975 CQT9")``, ``C.new("AK87s 975h QT9c")`` .. lua:function:: count(c) A number of cards in the given cards set ``c``, same as ``#c``. .. lua:function:: spades(c) .. lua:function:: Scount(c) A number of spades cards in set of cards ``c``. .. lua:function:: hearts(c) .. lua:function:: Hcount(c) A number of hearts cards in set of cards ``c``. .. lua:function:: diamonds(c) .. lua:function:: Dcount(c) A number of diamonds cards in set of cards ``c``. .. lua:function:: clubs(c) .. lua:function:: Ccount(c) A number of clubs cards in set of cards ``c``. .. lua:function:: S(c) Subset of ``c`` which includes only spades. .. lua:function:: H(c) Subset of ``c`` which includes only hearts. .. lua:function:: D(c) Subset of ``c`` which includes only diamonds. .. lua:function:: C(c) Subset of ``c`` which includes only clubs. .. lua:function:: get(c, arg) If ``arg`` is a string, return the subset of ``c`` which includes only cards of suit pointed by ``arg`` (which can equal to "S", "H", "D" or "C"). If ``arg`` is a positive integer, return ``arg``-th lowest card from ``c``. Cards are numbered from ``0`` to ``#c-1``, clubs have number from ``0`` to ``#c:C()-1``, diamonds from ``#c:C()`` to ``#c:C()+#c:D()-1``, and so on. If ``arg`` is out of range, an empty set is returned. If ``arg`` is a negative integer, return ``#c+arg`` lowest (``-arg`` highest) card from ``c``. .. lua:function:: cards(c) Iterator over cards included in ``c``. Each card is represented as a one-element set of cards. Example:: for x in N:cards() do -- for each card x handled by N: -- do something with card x end .. lua:function:: hcp(c) .. lua:function:: miltons(c) Honour points (4 for Ace, 3 for King, 2 for Queen, 1 for Jack) in the given cards set ``c``. .. lua:function:: controls(c) Controls (2 for Ace, 1 for King) in the given cards set ``c``. .. lua:function:: points(c, wAce, wKing, ...) Calculate ``wAce`` * Aces + ``wKing`` * Kings + ..., where Aces, Kings, ... are the numbers of aces, kings, ... in ``c``. Examples: * ``points(N, 4, 3, 2, 1)`` equals to ``hcp(N)``, * ``points(E, 1, 1, 1, 1)`` equals to the number of figures owned by E. .. lua:function:: balanced(c) Logic value which is ``true`` only if ``c`` is balanced. .. lua:function:: semiBalanced(c) Logic value which is ``true`` only if ``c`` includes minimum 2 cards in all suits, maximum 5 cards in each major and maximum 6 cards in each minor. .. lua:function:: union(c1, c2, ...) Union of the sets, same as ``c1 + c2 + ...`` .. lua:function:: product(c1, c2, ...) Product of the sets, same as ``c1 * c2 * ...`` .. lua:function:: complement(c) Complement of the set ``c``, same as ``-c``. .. lua:function:: xor(c1, c2, ...) Same as ``c1 ^ c2 ^ ...`` .. lua:function:: shape(c) Return 4 numbers: ``spades(c), hearts(c), diamonds(c), clubs(c)`` (in the given order). .. lua:function:: shape(c, f) Calculate and return ``f(spades(c), hearts(c), diamonds(c), clubs(c))``. For example ``shape(S, function(s, h, d, c) return s == 5 and h == 5; end)`` gives ``true`` only if ``S`` has 5-5 in majors. .. lua:function:: pattern(c) Return 4 numbers: ``spades(c), hearts(c), diamonds(c), clubs(c)`` (in non-increasing order, from highest to lowest). .. lua:function:: pattern(c, f) Return ``f(c1, c2, c3, c4)``, where ``c1, c2, c3, c4 = pattern(c)``. For example ``pattern(S, function(a, b, c, d) return a == 5 and b == 5; end)`` gives ``true`` only if ``S`` has any 5-5. .. lua:function:: hcp_in_range(c, from, to) Return ``true`` if ``hcp(c)`` is in the range [``from``, ``to``], and ``false`` if it is not. .. lua:function:: nt(c, from, to) Calculate logic value which is ``true`` only if ``c`` is balanced and ``hcp(c)`` is in the range [``from``, ``to``]. .. tip:: Most of the commands can be called with more than one argument and than they return more than one result (one per argument). In such case ``command(a, b, ...)`` is equal to ``command(a), command(b), ...``. For example you can write:``EpS, EpH = C.hcp(E:S(), E:H())`` to obtain number of E honour points in spades and hearts. Functions useful for doing statistical research ----------------------------------------------- .. lua:function:: count(str, n1, n2, ...) Add to the counter named ``str`` values ``n1``, ``n2``, ... Each value (``n1``, ``n2``, ...) can be a **number**, a **boolean** (**1** is added if the value is ``true`` and **0** when it is ``false``) or ``nil`` (then value is ignored). Example:: count("number of spades in E's hand", E:spades()) .. lua:function:: remark(arg1, arg2, ...) Attach a remark to the deal considered. The remark consists with concatenation of arguments, which are converted to strings. Remarks are printed next to each deal. Example:: remark("E can take ", tricks(E, "NT"), " tricks in NT.") .. lua:function:: note(arg1, arg2, ...) Similar to ``remark(arg1, arg2, ...)`` but puts spaces between each pair of arguments. Example:: note("E can take", tricks(E, "NT"), "tricks in NT.") Functions that use double dummy solver -------------------------------------- .. lua:function:: tricks(declarer, game[, cmds]) Return the number of tricks that ``declarer`` can take when a trump suit is given by ``game``, and a beginning of play is described by ``cmds``. If game cannot begin from ``cmds``, return ``nil``. :param declarer: one of ``N`` (or ``'N'``), ``E`` (or ``'E'``), ``S`` (or ``'S'``), ``W`` (or ``'W'``), lower cases are also allowed :param game: shows type of the game, is one of: ``'NT'`` (no trump), ``'S'`` (spades), ``'H'`` (hearts), ``'D'`` (diamonds), ``'C'`` (clubs), lower cases are also allowed. :param cmds: (optional) fixes beginning of the play; if it is not possible, ``tricks`` returns ``nil`` :rtype: **number** or ``nil`` (if the game cannot begin from ``cmds``) Example:: tricks(N, "NT", "AD x QD") It returns number of tricks that can be taken by N in no-trump game, after ace of diamond lead, discarding the smallest diamond by the dummy and queen of diamond by the right hand opponent. ``nil`` will be returned if: N has no ace of diamond, the dummy has no diamonds at all, or RHO has no queen of diamond. Since ``count`` ignores ``nil``, it is save to write:: count("NT by N after AD x QD", tricks(N, "NT", "AD x QD")) .. lua:function:: cantake(target, declarer, game[, cmds]) Check if ``declarer`` can take ``target`` tricks when a trump suit is given by ``game``, and a beginning of play is described by ``cmds``. :param target: number of tricks to take :param declarer: one of ``N`` (or ``'N'``), ``E`` (or ``'E'``), ``S`` (or ``'S'``), ``W`` (or ``'W'``), lower cases are also allowed :param game: shows type of the game, is one of: ``'NT'`` (no trump), ``'S'`` (spades), ``'H'`` (hearts), ``'D'`` (diamonds), ``'C'`` (clubs), lower cases are also allowed. :param cmds: (optional) fixes beginning of the play, if it is not possible, ``cantake`` returns ``nil`` :rtype: **boolean** or ``nil`` (if the game cannot begin from ``cmds``) Example:: count("chance to win 3NT by N", cantake(9, N, "NT")) Indices and tables ================== * :ref:`genindex` * :ref:`search`